API Access Denied for cPanel Account

Nate_GC

Registered
Mar 18, 2010
3
0
51
I am using cPanel and WHM 11.25.0-C43193 and 11.25.0 respectively.

Code:
$ip = "127.0.0.1";
$root_pass = CPANEL_ROOT_PASSWORD;		
$account = CPANEL_USER;
$root = CPANEL_ROOT;
$xmlapi = new xmlapi($ip);
//$xmlapi->password_auth(CPANEL_USER, CPANEL_PASSWORD);
$xmlapi->password_auth($root, $root_pass);
$xmlapi->set_output('xml');
As you can see I am having to use the cPanel Root Account details as the xmlapi login details. Is there any reason why i wouldn't be able to use the cPanel Account itself to use the API?

Really don't want to go spreading the Root account details out everywhere.

If i try the cPanel Account details it returns "Access Denied" for any API Calls. The ones that I have tried this on are addpop, addforward, passwdpop, listpopswithdisk, listforwards. This is the case for both API1 and API2 call.

The account is on a dedicated IP.

Thank for the help in advance.
 

cPanelDavidN

Well-Known Member
Staff member
Dec 17, 2009
571
3
68
Houston, TX
cPanel Access Level
Root Administrator
xml-api access with cPanel credentials

Hi Nate_GC,

You should be able to make API1 and API2 queries with cPanel credentials. I would think that the XML-API calls are only valid with a reseller or root user.

Code:
$ip = '192.168.1.1';
$account = 'dave';
$domain = 'mysite.net'
$passwd = 'some_secret_123';

$xmlapi = new xmlapi($ip);
$xmlapi->password_auth($account, $passwd);

$addpop_args = array(
  'domain'=>$domain,
  'email'=>'bob',
  'password'=>'bobspop_secret',
  'quota'=> 0);

print $xmlapi->api2_query($account, "Email", "addpop", $addpop_args);
print $xmlapi->api2_query($account, "Email", "listpopswithdisk", array('domain'=>$domain) );
Will add [email protected], then list all pop email addresses for mysite.net.

The key is to make sure you specify the user, ie. the person you authenticated as (in my case $account). For completeness, you should be able to specify any user that is owned by the authenticated person (hence, root always works as it always has dominion over any user);

In the client class there are several functions that are wrappers for API1 and API2 calls. I usually prefer calling them directly with api2_query or api1_query because it reminds me that I need ordered arguments or if literal string keys is what the call wants.

Regards,
-Dave
 

Nate_GC

Registered
Mar 18, 2010
3
0
51
Thanks for the info.

I have tried using what you said the semi complete code is:

Code:
<?php
$ip = "127.0.0.1";
$root_pass = CPANEL_ROOT_PASSWORD;		
$account = CPANEL_USER;
$root = CPANEL_ROOT;
$xmlapi = new xmlapi($ip);
$xmlapi->password_auth(CPANEL_USER, CPANEL_PASSWORD);
//$xmlapi->password_auth($root, $root_pass);
$xmlapi->set_output('xml');

//$xmlapi->set_debug(1);
$quota = 10;
if($_GET['action'] == "submit") {
	$error = false;
	$add_email_password1 = $_POST['add_email_password1'];
	$add_email_password2 = $_POST['add_email_password2'];
	$email_address = $_POST['email_address'];
	$quota = $_POST['quota'];
	if($add_email_password1 != $add_email_password2 || strlen($add_email_password1) <= 0) {
		$error = true;
		$error_message[] = "Please submit valid identical email password.";
	} else if(strlen($email_address) <= 0) {
		$error = true;
		$error_message[] = "Please provide a email account name";
	} else if($quota > 50 || $quota <= 0) {
		$error = true;
		$error_message[] = "Please enter a valid Quota";
	}
	if(!$error) {
		
		$response =  $xmlapi->api2_query($account, "Email", "addpop", array("domain" => CPANEL_DOMAIN, "email" => $email_address, "password" => $add_email_password1, "quota" => $quota) );
		$XML = new XmlToArray($response);
		$information = $XML->createArray();
		//displayArray($information);
		if(!isset($information['cpanelresult']['error'])) {
			redirect("cpanel_email.php?message=success_pop");
		}
		else  {
			$error = true;
			$error_message[] = "API Error: " . $information['cpanelresult']['error'] . " (If this message continues submit a support ticket)";
		}
	}
}
?>
//THEN THE FORM
<?php 
                            $response =  $xmlapi->api2_query($account, "Email", "listpopswithdisk", array(CPANEL_DOMAIN) );
                            $XML = new XmlToArray($response);
                            $information = $XML->createArray();
							//displayArray($information);
							if($information['cpanelresult']['data'][0]['reason'] == "Access Denied") {
								displayArray($information['cpanelresult'],false);
							}
                            if(isset($information['cpanelresult']['data'][0])) {
                                print "<div id='task-table'>";
                                print '<table cellpadding="5" cellspacing="0">';
                                print '<tr>
                                        <th>Email Address</th>
                                        <th>Disk Quota</th>
                                        <th>Quota Used</th>
										<th>&nbsp;</th>
                                       </tr>';
                                $rv = "row2";
                                foreach($information['cpanelresult']['data'] as $email_info) {
									$user = $email_info['user'];
                                    print "<tr class='".$rv."'>";
                                    print "<td>".$email_info['email']."</td>";
                                    print "<td align='right'>".$email_info['humandiskquota']."</td>";
                                    print "<td align='right'>".$email_info['humandiskused']."</td>";
									print "<td align='right'>".displayButton("Change Password", "document.getElementById('email_pass".$user."').style.display = 'block';", true)."</td>";
                                    print "</tr>";
									print "<tr class='".$rv."'><td colspan='4'><div id='email_pass".$user."' style='display:none;'><form action='?action=submit_changepwd' method='post'><input type='hidden' name='email' value='".$user."'/><input type='text' name='new_password'/><input type='submit' name='submit' value='Change Password'/></form></td></tr>";
                                    $rv = changeRv($rv);
                                }
                                print "<tr class='".$rv."'>";
                                print "<td style='border-top:1px solid #444' colspan='4'>Using <strong>".count($information['cpanelresult']['data'])." out of ".CPANEL_POP_ACCOUNTS."</strong> available email acccounts</td></tr>";
                                print "</table>";	
                                print "</div>";						
                            }
                            //displayArray($information);
<hr/>
                        <h1>Add New Email Account</h1>
                        <?=$process_message;?>
                        <form action="?action=submit" method="post">
                            <div id='task-table'>
                                <table class="email_add_table" border="0" cellpadding="5" cellspacing="0">
                                <th colspan='4'>&nbsp;</th>
                                <tr class='row2'>
                                    <td align="right">Email:</td>
                                    <td><input id="add_email_account" name='email_address' type="text" style="width: 150px" value="<?=$email_address;?>" /></td>
                                    <td colspan="2">@ 
                            
                            <!--  -->
                            
                             <?php print CPANEL_DOMAIN; ?> <input type="hidden" id="add_email_domain" value="<?php print CPANEL_DOMAIN; ?>" />
                            
                            
                            
                            
                                        &nbsp;
                                    </td>
                                </tr>
                                <tr class='row3'>
                                    <td align="right">Password:</td>
                                    <td><input type="password" name="add_email_password1" id="add_email_password1" style="width: 150px" /></td>
                                    <td><div id="add_email_password1_error"></div></td>
                                    <td></td>
                                </tr>
                                <tr class='row3'>
                                    <td align="right">Password (again):</td>
                                    <td><input type="password" name="add_email_password2" id="add_email_password2" style="width: 150px" /></td>
                                    <td><div id="add_email_password2_error"></div></td>
                                    <td></td>
                                </tr>
                                <tr class='row2'>
                                    <td align="right">Mailbox Quota:</td>
                                    <td colspan="3">
                                        <input name='quota' id='quota' value="<?=$quota;?>"/> <span class="megabyte_font">MB [Max 50]</span>
                                    </td>
                                </tr>
                                <tr>
                                    <td></td>
                                    <td colspan="3"><input id="add_email_create" class="input-button" type="submit" value="Create Account" /><div id="add_email_create_status"></div></td>
                                </tr>
                            </table>
                            </div>    
                        </form>
                   </div>
Unfortunately the result is still always "Access Denied" - I am going to try to change the Account to reseller and see if that helps.
 
Last edited:

Nate_GC

Registered
Mar 18, 2010
3
0
51
Code:
$xmlapi->set_port(2082);
I solved this problem with the code above. Needs to be over port 2082, not the xmlapi default of 2087 (WHM over SSL).

Hope this helps anyone else who comes across the same problem. Just to add no code samples that i have seen so far mentioned that the port should be specified, however i am recollecting that it was mentioned in the orignal documentation the differences in the ports from 2082 to 2087.
 

cPanelDavidN

Well-Known Member
Staff member
Dec 17, 2009
571
3
68
Houston, TX
cPanel Access Level
Root Administrator
if you're on the same box, you don't have to send HTTP

Not to open a can of worms, but I noticed in both your examples you are placing your request to the loopback/localhost. I don't know if that is for example purposes or if you're truly executing the request on the same server.

If you are executing from the same server that you what to query, you might consider:
1)cPanel PHP
2)Live PHP
depending on what you're doing...

both allow you to write PHP code that interfaces with the localhost via APIs without making the HTTP request.

1)cPanel PHP: add <cpanel > or <?cp > api tags in your files. if you file has an extension .php or .cpphp then the api tag will get parsed before the php code. This code must live (or be symlinked ) in /usr/local/cpanel/base/frontend/$theme. Where $theme is 'x3' or what your theme is.
CpanelPhp < AllDocumentation/AutomationIntegration < TWiki

2)Live PHP: a PHP class that is works as an OO interface to a listen socket where the cpanel binary listens. check out:
/usr/local/cpanel/php/
in there you'll find the Cpanel class, is only include file, and a README.txt that has examples. Same caveat applies as with the cPanel PHP, must live or have a pointer within a theme. Must have .live.php as the file extension

Also, I think the x3 theme ships with examples of both.

Regards,
-Dave
 
Last edited by a moderator: