Wrapper for PAM

Alexander Zhirov azhirov1991 at gmail.com
Mon Oct 7 08:24:42 UTC 2024


On Monday, 7 October 2024 at 08:23:08 UTC, Alexander Zhirov wrote:

```
module login.auth;

import libpam;

enum {
     AUTH_SUCCESS = 0,
     AUTH_ERR_USER = 1,
     AUTH_ERR_PASS = 2,
     AUTH_ERR_NPASS = 3,
     AUTH_ERR_START = 4,
     AUTH_ERR_AUTH = 5,
     AUTH_ERR_ACCT = 6,
     AUTH_ERR_CHTOK = 7,
     AUTH_ERR_END = 8
}

class Auth {
private:
     struct PAMdata {
         string password;
         string newPassword;
     }

     extern(C) {
         int conversation_func(int num_msg, const pam_message 
**msg, pam_response **resp, void *appdata_ptr) {
             PAMdata *data = cast(PAMdata*)appdata_ptr;

             pam_response *responses = cast(pam_response 
*)calloc(num_msg, pam_response.sizeof);

             if (responses == null) {
                 return PAM_BUF_ERR;
             }

             for (int count = 0; count < num_msg; ++count) {
                 responses[count].resp_retcode = 0;
                 switch (msg[count].msg_style) {
                     case PAM_PROMPT_ECHO_ON:
                     case PAM_PROMPT_ECHO_OFF:
                         switch (msg[count].msg.to!string) {
                             case "New password: ":
                             case "Retype new password: ":
                                 responses[count].resp = 
strdup(data.newPassword.toStringz);
                                 break;
                             case "Password: ":
                             case "Current password: ":
                                 responses[count].resp = 
strdup(data.password.toStringz);
                                 break;
                             default:
                                 responses[count].resp = null;
                                 break;
                         }
                         break;
                     default:
                         responses[count].resp = null;
                         break;
                 }
             }

             *resp = responses;

             return PAM_SUCCESS;
         }
     }
public:
     int authenticate(string username, string password) {
         if (!username.length) {
             return AUTH_ERR_USER;
         }

         if (!password.length) {
             return AUTH_ERR_PASS;
         }

         pam_handle_t *pamh = null;
         int retval = 0;

         PAMdata data = { password };
         void *appdata_ptr = &data;

         pam_conv conv = { 
cast(conversation*)&this.conversation_func, appdata_ptr };

         retval = pam_start("login", username.toStringz, &conv, 
&pamh);
         if (retval != PAM_SUCCESS) {
             return AUTH_ERR_START;
         }

         retval = pam_authenticate(pamh, 0);
         if (retval != PAM_SUCCESS) {
             pam_end(pamh, retval);
             return AUTH_ERR_AUTH;
         }

         retval = pam_end(pamh, PAM_SUCCESS);
         if (retval != PAM_SUCCESS) {
             return AUTH_ERR_END;
         }

         return AUTH_SUCCESS;
     }
}

```


More information about the Digitalmars-d-learn mailing list