Wrapper for PAM

Salih Dincer salihdb at hotmail.com
Thu Oct 3 23:56:37 UTC 2024


On Thursday, 3 October 2024 at 22:54:53 UTC, Alexander Zhirov 
wrote:
> I want to try to make access via D to PAM.
>
> ```d
> /// I added it here:
> import pam_wrapper;
> int main(string[] args)
> {
>    if (args.length < 3)
>     {
>         writeln("Usage: ", args[0], "<username> <password>");
>         return 1;
>     }
> /// I added it here.
>     string username = args[1];
>     string password = args[2];
>
>     int result = authenticate_user(username, password);
>     if (result == 0) {
>         writeln("Authentication succeeded!");
>     } else {
>         writefln("Authentication failed with code: %d", result);
>     }
>
>     return EXIT_SUCCESS;
> }
> ```

It is possible to implement PAM (Pluggable Authentication 
Modules) support in the D programming language using the standard 
library. The D standard library provides extern(C) support to 
access C language APIs and a strong FFI (Foreign Function 
Interface) support to adapt to C data structures. However, D 
itself does not include a special module for PAM, so it is 
necessary to work with C-based PAM libraries in the D language.


I think you should use 2 separate modules! This can make type 
conversions and memory management safer. Here is the 
pam_wrapper.d file:

```d
module pam_wrapper;

import pam; // You have this module.
import std.string, std.conv : to;
import core.stdc.string : strdup;
import core.stdc.stdlib : malloc, free;
public import std.stdio;

struct pam_data { string password; }

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

         *resp = cast(pam_response *)malloc(num_msg * 
pam_response.sizeof);
         if (resp == null) return PAM_BUF_ERR;

         for (int i = 0; i < num_msg; i++)
         {
             switch (msg[i].msg_style)
             {
                 case PAM_PROMPT_ECHO_ON:
                     goto case;
                 case PAM_PROMPT_ECHO_OFF:
                     resp[i].resp = 
strdup(data.password.toStringz);
                     resp[i].resp_retcode = 0;
                     break;
                 default:
                     resp[i].resp = null;
                     resp[i].resp_retcode = 0;
                     break;
             }
         }

         return PAM_SUCCESS;
     }
}

int authenticate_user(string username, string password)
{
     pam_handle_t *pamh = null;
     int retval = 0;

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

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

     retval = pam_start("login", username.toStringz, &conv, &pamh);
     if (retval != PAM_SUCCESS)
     {
         pam_strerror(pamh, retval).to!string.writefln!"pam_start: 
%s";
         return 1;
     }

     retval = pam_authenticate(pamh, 0);
     if (retval != PAM_SUCCESS)
     {
         pam_strerror(pamh, 
retval).to!string.writefln!"Authentication failure: %s";
         pam_end(pamh, retval);
         return 2;
     }

     retval = pam_end(pamh, PAM_SUCCESS);
     if (retval != PAM_SUCCESS)
     {
         pam_strerror(pamh, retval).to!string.writefln!"pam_end: 
%s";
         return 3;
     }

     return 0;
}
```

SDB at 79


More information about the Digitalmars-d-learn mailing list