Please whitelist cPanel in your adblocker so that you’re able to see our version release promotions, thanks!

The Community Forums

Interact with an entire community of cPanel & WHM users!
  1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Automating cPanel from a Desktop Program

Discussion in 'cPanel Developers' started by Indinfer, Mar 25, 2018.

  1. Indinfer

    Indinfer Member

    Joined:
    Mar 25, 2018
    Messages:
    7
    Likes Received:
    0
    Trophy Points:
    1
    Location:
    Baltimore, Maryland
    cPanel Access Level:
    Website Owner
    By "Automating cPanel from a Desktop Program" I mean that I run the desktop program, and then the desktop program logs into cPanel and (for example) creates a thousand or so email addresses and sets up global filters for the new email addresses.

    I am a Website Owner. I subscribe to GoDaddy website hosting.

    I am writing the program in Common Lisp and using Drakma library. I am okay with using a different library or even no library (since the particular Common Lisp I am using can do sockets). From Lisp I can do "Foreign Language Interface" (FLI) which means I can call a C language function in a DLL file.

    I don't think you need to know anything about Lisp to help--and I do need help because my stuff is not working. I think I need to understand what to send through the socket and what to do with what I get back. That would be language independent, but would be critical to getting this to work.


    QUESTION 1: To which forum should I post to get help getting my program to work? This one? or some other forum?


    The specific things I want to do through the desktop program are:
    1. Create and delete email boxes (addresses)
    2. Create and delete global filters

    After reading cPanel documentation, I think what I need to do is get a cPanel "Security Token". I get a Security Token by logging into cPanel. When I log into cPanel from a web browser, I see a security token in the URL line. From there, I can construct Session URL Calls that include the security token. The desktop program can then send the the session calls to invoke UAPI calls.


    QUESTION 2: Would having a desktop program log in as if it were a browser be a recommended way to get a security token?


    QUESTION 3: Would issuing Session URL commands be a recommended way to invoke UAPI calls? or is this method only for debugging?


    My logging in as if my desktop program is a browser is not working. My call to login looks like:
    Code:
    (drakma:http-request url-cpanel
                           :method :post
                           :parameters (list (cons "user" username)
                                             (cons "pass" password))
                           :cookie-jar *cookie-jar*))
    What this Lisp code says is that I am sending to the website (variable "url-cpanel"). The contents of url-cpanel (Lisp variables can have '-' as part of variable names) includes "https://" , the website URL, and ":2083".

    Because I have "https" instead of "http", Drakma library will do the secure socket. I think the ":2083" is a cPanel requirement for a secure connection for a specific cPanel website.

    Then you see in the Lisp code that I am using the POST method, not the GET method to send login data.

    You see I am sending parameters for user and pass.

    Then you see that I have ":cookie-jar *cookie-jar*". This is supposed to be the same as a browser enabling cookies. If I would not have cookie-jar, then that should be the same as a browser disabling cookies.

    So far, I think this Lisp code does not work. I don't think I'm getting logged in.

    What I get back varies. Almost always, I cannot write out what I get to a disk file so that I can analyze.

    The error I get is "Unexpected value #xFC at start of UTF-8 sequence."
    The hex-value (in C Language) 0xFC is different values. Sometimes it is 0x80. And sometimes I get the response written to a file. But I am not getting a token back.

    I am trying to write the response as UTF-8 form to a file.



    QUESTION 4: Any ideas what I might be missing or doing wrong?


    The later questions depend on the answers to earlier questions. So, I have made assumptions in order to include more questions. Therefore, you might help by answering only one question, or (having figured what I need) a response that does not directly answer any question I posed.

    Directing me to a forum better suited for what I seem to need is helpful. And directing me to what I might have missed or misunderstood in the cPanel documentation is helpful.


    Thank you for seeing this. I hope someone can get me unstuck on this login problem.
     
  2. cPanelMichael

    cPanelMichael Forums Analyst
    Staff Member

    Joined:
    Apr 11, 2011
    Messages:
    42,734
    Likes Received:
    1,706
    Trophy Points:
    363
    cPanel Access Level:
    Root Administrator
    Hello,

    The following document is a good place to start:

    Guide to API Authentication - Developer Documentation - cPanel Documentation

    Since you are connecting from a remote location (your desktop in this case), and you only have cPanel access, the following method is likely a good choice:

    Guide to API Authentication - Secure Remote Logins - Developer Documentation - cPanel Documentation

    There's also a thread here with some links to other posts that you may find helpful as proof-of-concept examples:

    working with whm api using c#.net

    Thank you.
     
  3. Indinfer

    Indinfer Member

    Joined:
    Mar 25, 2018
    Messages:
    7
    Likes Received:
    0
    Trophy Points:
    1
    Location:
    Baltimore, Maryland
    cPanel Access Level:
    Website Owner
    Thank you very much. This is the kind of information I am seeking. I am studying the leads. Thank you.
     
  4. Indinfer

    Indinfer Member

    Joined:
    Mar 25, 2018
    Messages:
    7
    Likes Received:
    0
    Trophy Points:
    1
    Location:
    Baltimore, Maryland
    cPanel Access Level:
    Website Owner
    I construct my code based on the Secure Remote Logins documentation. Maybe I am further along, but still not there yet. Meaning: I think I should be getting a CP session token and am not, should get an "OK" but am getting "Access Denied", etc.

    I think I'm capturing the headers maybe both ways. To make this post okay to post publicly, I am substituting "my-website.com" "my-password", etc. for the real website domain, password, and so forth.

    I present my Lisp code (with a walkthrough explanation), then the headers both ways, and then all the results returned by my lisp function "login". I suspect the headers will be the most useful in your being able to tell me what I am doing wrong and am missing.

    The results are labeled =========== Result n ==========
    where n is the result number.

    I am abbreviating the HTML returned as the Result 1 by using <... html for cPanel logging webpage ...> instead of all the HTML code.

    Here it is:

    My Lisp Code and Walkthrough

    Code:
    (defun login ()
      (drakma:http-request
       "https://my-website.com:2083/cpanel"
       :parameters (list (cons "user" "my-user")
                         (cons "pass" "my-password")
                         (cons "hostname" "my-website.com")
                         (cons "service" "cpanel")
                         (cons "goto_uri" "/"))))
    
    
    "defun" says we are defining a function
    "login" is the name of the function
    "drakma" is the name of the Lisp library to compose, send, and receive HTTPS.
    "http-request" is the drakma function. It is doing SSL secure connection because the URL starts HTTPS instead of HTTP.
    Probably you can see what happens with the parameters by comparing with the headers.
    Because I do not specify POST, I am sending using GET method.

    I understand that you might not need to look at this Lisp code part.


    Headers Both Ways
    Code:
    GET /cpanel?user=my-user&pass=q8C%250g!4tX&hostname=my-website.com&service=cpanel&goto_uri=%2F HTTP/1.1
    Host: my-website.com:2083
    User-Agent: Drakma/2.0.4 (LispWorks 7.1.0; Windows NT; Windows 10: 10.0 (build 16299) ; Drakma - A Common Lisp HTTP client)
    Accept: */*
    Connection: close
    HTTP/1.1 401 Access Denied
    Connection: close
    Content-Type: text/html; charset="utf-8"
    Date: Tue, 27 Mar 2018 20:20:38 GMT
    Cache-Control: no-cache, no-store, must-revalidate, private
    Pragma: no-cache
    Set-Cookie: cprelogin=no; HttpOnly; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; port=2083; secure
    Set-Cookie: cpsession=%3aRjubuDXY5TQz7OkZ%2ce0ca8fee57083b7592ea352dc6300996; HttpOnly; path=/; port=2083; secure
    Set-Cookie: roundcube_sessid=expired; HttpOnly; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; port=2083; secure
    Set-Cookie: roundcube_sessauth=expired; HttpOnly; domain=my-website.com; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; port=2083; secure
    Set-Cookie: Horde=expired; HttpOnly; domain=.my-website.com; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; port=2083; secure
    Set-Cookie: horde_secret_key=expired; HttpOnly; domain=.my-website.com; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; port=2083; secure
    Set-Cookie: Horde=expired; HttpOnly; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; port=2083; secure
    Set-Cookie: Horde=expired; HttpOnly; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/horde; port=2083; secure
    Set-Cookie: PPA_ID=expired; HttpOnly; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; port=2083; secure
    Set-Cookie: imp_key=expired; HttpOnly; domain=my-website.com; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; port=2083; secure
    Set-Cookie: key=expired; HttpOnly; domain=my-website.com; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/3rdparty/squirrelmail/; port=2083; secure
    Set-Cookie: SQMSESSID=expired; HttpOnly; domain=my-website.com; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; port=2083; secure
    Set-Cookie: Horde=expired; HttpOnly; domain=.my-website.com; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; port=2083
    Set-Cookie: horde_secret_key=expired; HttpOnly; domain=.my-website.com; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; port=2083
    Cache-Control: no-cache, no-store, must-revalidate, private
    Content-Length: 28012
    
    
    Results Returned from drakma:http-request
    Code:
    ============= Result 1 HTML of Webpage Returned =================
    "
    <!DOCTYPE html>
    <html dir=\"ltr\">
    <... html for cPanel loggin webpage ...>
    </html>
    "
    ============= Result 2 Status Code =================
    401
    ============= Result 3 Headers =================
    (:)CONNECTION . "close") :)CONTENT-TYPE . "text/html; charset=\"utf-8\"") :)DATE . "Tue, 27 Mar 2018 20:20:38 GMT") :)CACHE-CONTROL . "no-cache, no-store, must-revalidate, private,no-cache, no-store, must-revalidate, private") :)PRAGMA . "no-cache") :)SET-COOKIE . "cprelogin=no; HttpOnly; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; port=2083; secure,cpsession=%3aRjubuDXY5TQz7OkZ%2ce0ca8fee57083b7592ea352dc6300996; HttpOnly; path=/; port=2083; secure,roundcube_sessid=expired; HttpOnly; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; port=2083; secure,roundcube_sessauth=expired; HttpOnly; domain=my-website.com; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; port=2083; secure,Horde=expired; HttpOnly; domain=.my-website.com; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; port=2083; secure,horde_secret_key=expired; HttpOnly; domain=.my-website.com; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; port=2083; secure,Horde=expired; HttpOnly; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; port=2083; secure,Horde=expired; HttpOnly; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/horde; port=2083; secure,PPA_ID=expired; HttpOnly; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; port=2083; secure,imp_key=expired; HttpOnly; domain=my-website.com; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; port=2083; secure,key=expired; HttpOnly; domain=my-website.com; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/3rdparty/squirrelmail/; port=2083; secure,SQMSESSID=expired; HttpOnly; domain=my-website.com; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; port=2083; secure,Horde=expired; HttpOnly; domain=.my-website.com; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; port=2083,horde_secret_key=expired; HttpOnly; domain=.my-website.com; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; port=2083") :)CONTENT-LENGTH . "28012"))
    ============= Result 4 URL =================
    #<PURI:URI https://my-website.com:2083/cpanel?user=my-user&pass=q8C%0g!4tX&hostname=my-website.com&service=cpanel&goto_uri=/>
    ============= Result 5  Stream =================
    #<FLEXI-STREAMS:FLEXI-IO-STREAM 20081083>
    ============= Result 6 Must Close (T=true, nil=false) =================
    T
    ============= Result 7 Reason Phrase =================
    "Access Denied"
    ============= No more results ==========
    
    In Result 3, you see how Lisp likes to wrap everything in parenthesis.

    I hope you can help me understand (probably from Headers Both Ways) what cPanel's response means and what I might need to do to do the Secure Remote Login.
     
    #4 Indinfer, Mar 27, 2018
    Last edited by a moderator: Mar 27, 2018
  5. Indinfer

    Indinfer Member

    Joined:
    Mar 25, 2018
    Messages:
    7
    Likes Received:
    0
    Trophy Points:
    1
    Location:
    Baltimore, Maryland
    cPanel Access Level:
    Website Owner
    The forum editor gave me some unexpected bolding and converted some parentheis+characters to emoji. It's fine. Just that you should know some of my post above is not as I typed it.
     
  6. cPanelMichael

    cPanelMichael Forums Analyst
    Staff Member

    Joined:
    Apr 11, 2011
    Messages:
    42,734
    Likes Received:
    1,706
    Trophy Points:
    363
    cPanel Access Level:
    Root Administrator
    Do you notice any specific output in /usr/local/cpanel/logs/login_log when authentication fails?

    Thank you.
     
  7. Indinfer

    Indinfer Member

    Joined:
    Mar 25, 2018
    Messages:
    7
    Likes Received:
    0
    Trophy Points:
    1
    Location:
    Baltimore, Maryland
    cPanel Access Level:
    Website Owner
    I opened File Manager. I could not follow the path you gave me exactly, maybe because I am at "Website Owner" level with just cPanel access. Or, maybe I simply did not understand.

    I found "logs" directory. Path is /home/my-user-name/logs/

    I have these GZ compressed files:
    my-website.com-Mar-2018.gz
    my-website.com-ssl_log-Mar-2018.gz

    I don't see anything with "login" such as "login_log".
    I did download "my-website.com-ssl_log-Mar-2018.gz" and extracted the file.

    Just before I downloaded, I ran my program at somewhere around 8:30 PM my time. The date on the GZ compressed files is "Today 8:26 AM" about 12 hours before. Maybe the servers are in India or Singapore?

    Anyway, I opened the file.

    Here are the last few lines:
    Code:
    69.140.87.176 - - [27/Mar/2018:10:50:27 -0700] "GET /cpanel HTTP/1.1" 200 12517 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
    
    69.140.87.176 - - [27/Mar/2018:12:36:11 -0700] "GET /cpanel HTTP/1.1" 200 12516 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
    
    69.140.87.176 - - [27/Mar/2018:13:07:36 -0700] "GET /?user=someusr&pass=xxxxxxxxxxxxx&hostname=assigned-email-example.com&service=cpanel&goto_uri=%2F HTTP/1.1" 200 6860 "-" "Drakma/2.0.4 (LispWorks 7.1.0; Windows NT; Windows 10: 10.0 (build 16299) ; http://weitz.de/drakma/)"
    
    35.162.70.167 - - [28/Mar/2018:02:19:22 -0700] "GET / HTTP/1.1" 200 2746 "-" "Magic Browser"
    
    35.162.70.167 - - [28/Mar/2018:02:19:23 -0700] "GET / HTTP/1.1" 200 2746 "-" "Magic Browser"
    
    173.244.48.51 - - [28/Mar/2018:02:22:48 -0700] "GET / HTTP/1.0" 200 2746 "-" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/537.36"

    So, I don't know. I see "Drakma" in one line in the whole file. Maybe I succeeded once yesterday with a GET request? But I don't see an entry for what I just did, like a login success or fail.

    Am I looking in the place you intended?

    Seems like I should have a log to inspect that shows what I just did. But I don't know where to look.
     
    #7 Indinfer, Mar 28, 2018
    Last edited by a moderator: Mar 28, 2018
  8. cPanelMichael

    cPanelMichael Forums Analyst
    Staff Member

    Joined:
    Apr 11, 2011
    Messages:
    42,734
    Likes Received:
    1,706
    Trophy Points:
    363
    cPanel Access Level:
    Root Administrator
    Hello,

    Actually, /usr/local/cpanel/logs/login_log isn't a log file you have access to as a cPanel user. You can check with your web hosting provider to see if they can provide you with the specific output that appears in that log file when authentication from your application fails.

    Thank you.
     
  9. Indinfer

    Indinfer Member

    Joined:
    Mar 25, 2018
    Messages:
    7
    Likes Received:
    0
    Trophy Points:
    1
    Location:
    Baltimore, Maryland
    cPanel Access Level:
    Website Owner
    Probably be sometime next week that I am able to check with my website hosting service, GoDaddy. I hope to post the results.
     
  10. Indinfer

    Indinfer Member

    Joined:
    Mar 25, 2018
    Messages:
    7
    Likes Received:
    0
    Trophy Points:
    1
    Location:
    Baltimore, Maryland
    cPanel Access Level:
    Website Owner
    GoDaddy did not seem to be able to help me. However, I believe I got a successful login. I will share my Common Lisp answer as code with a walkthrough which I hope is suitable for those unfamiliar with Common Lisp. Then I will state what I learned. Maybe this will help others, or maybe myself if I forget how I did it.

    Code:

    Code:
    (defun login-to-cpanel ()
      (setf *login-result*
            (multiple-value-list
             (drakma:http-request "https://my-website.com:2083/login/"
                                  :method :post
                                  :cookie-jar *cookies*
                                  :parameters (list (cons "user" username)
                                                    (cons "pass" password))))))
    Walkthrough:

    defun login-to-cpanel (): defines a function called "login-to-cpanel" that takes no parameters

    setf *login-result* : sets the variable *login-result* (the asterisks are part of the variable name) to the result. The result is that which is returned on the next line.

    multiple-value-list : a lisp function that collects the multiple values returned from the following function (drakma:http-request ...) and formats the "multiple values" into a "list of values". Lisp functions can return multiple values. But for this sample, don't need to get stuck trying to understand it.

    drakma:http-request : this is the Drakma-Lisp-Library function through which I am making my login-call.

    "https://my-website.com:2083/login/" : substitute the actual domain for "my-website.com".

    :method :post : use POST HTTP method instead of GET HTTP method.

    :cookie-jar *cookies* : enable cookies, such as in a browser.

    :parameters (etc.) : This is where I specify my username and password.

    Comment:

    This is a browser-style login. I did not figure out how to do the remote login.

    What I Learned:

    The URL was the thing that was preventing me from logging in. I needed to have "/login/" appended to the domain ("my-website.com") with port :2083 .

    I don't know whether this kind of URL will work for all web hosting services providing cPanel. I would appreciate a comment whether the required URL could be different for different web hosting services.

    ---

    I know I need to learn a lot more. Maybe I am doing things in a way that is contra-recommended, or maybe this kind of program login is okay. Therefore, I will appreciate comments and suggestions.
     
  11. cPanelMichael

    cPanelMichael Forums Analyst
    Staff Member

    Joined:
    Apr 11, 2011
    Messages:
    42,734
    Likes Received:
    1,706
    Trophy Points:
    363
    cPanel Access Level:
    Root Administrator
    Hi @Indinfer,

    Thank you for taking the time to share the solution. I do see other examples where appending /login/ to the URL allows the post method to work:

    Send cPanel Login Credentials via POST instead of GET
    Security Token Integration for downloading API generated Backup Files

    The method you used should also work for WHM and Webmail, but let us know if you notice any further issues.

    Thank you.
     
Loading...

Share This Page