Reputation:
I'm planning a REST service for my own shutter control solution in a new house. The service should run on a linux server, and as this is something that really should be available, I want to do it without any runtime dependencies except the OS itself and very few standard libraries. So I'd prefer to do it in c.
So far, I found libasyncd which should give me a nice HTTPS host to work with. My concern now is how to handle authentication. For simplicity, HTTP basic auth should do, but I'd like to authenticate against my system user store (which is an OpenLDAP directory at the moment). Ideally, I'd like to have a solution that abstracts from this store.
I first thought pam might be the way to go, but all examples I could find so far let pam do the password prompt and what I need instead is a function that takes username and password and tells me authenticated or not. Is this even possible with pam? If so, where should I look for documentation? If not, could you suggest any alternatives?
Upvotes: 2
Views: 1229
Reputation:
After continuing my research, I finally have some working example code giving me just the user/password checking using pam I was looking for. I post it here as an answer for reference.
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <security/pam_appl.h>
static int pamconv(int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr)
{
char *pass = malloc(strlen(appdata_ptr)+1);
strcpy(pass, appdata_ptr);
int i;
*resp = calloc(num_msg, sizeof(struct pam_response));
for (i = 0; i < num_msg; ++i)
{
/* Ignore all PAM messages except prompting for hidden input */
if (msg[i]->msg_style != PAM_PROMPT_ECHO_OFF)
continue;
/* Assume PAM is only prompting for the password as hidden input */
resp[i]->resp = pass;
}
return PAM_SUCCESS;
}
bool checkAuthentication(const char *user, const char *pass)
{
/* use own PAM conversation function just responding with the
password passed here */
struct pam_conv conv = { &pamconv, (void *)pass };
pam_handle_t *handle;
int authResult;
pam_start("shutterd", user, &conv, &handle);
authResult = pam_authenticate(handle,
PAM_SILENT|PAM_DISALLOW_NULL_AUTHTOK);
pam_end(handle, authResult);
return (authResult == PAM_SUCCESS);
}
Of course, error checking has to be added everywhere for production quality.
Upvotes: 4