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@79

Reply via email to