odyssey/sources/pam.c

160 lines
3.1 KiB
C
Raw Normal View History

2019-09-27 13:47:45 +00:00
2019-09-09 09:17:41 +00:00
/*
* Odyssey.
*
* Scalable PostgreSQL connection pooler.
*/
2019-09-09 09:17:41 +00:00
#include <machinarium.h>
#include <odyssey.h>
2019-09-27 13:47:45 +00:00
2019-09-09 09:17:41 +00:00
#include <security/pam_appl.h>
2019-09-27 13:47:45 +00:00
struct sss
{
char *psswd;
char *res;
};
2019-09-09 09:17:41 +00:00
static int
2019-09-27 13:47:45 +00:00
od_pam_conversation(int msgc,
const struct pam_message **msgv,
struct pam_response **rspv,
void *authdata)
{
od_pam_auth_data_t *auth_data = authdata;
if (msgc < 1 || msgv == NULL)
2019-09-09 09:17:41 +00:00
return PAM_CONV_ERR;
2019-09-27 13:47:45 +00:00
2019-09-09 09:17:41 +00:00
*rspv = malloc(msgc * sizeof(struct pam_response));
2019-09-27 13:47:45 +00:00
if (*rspv == NULL)
2019-09-09 09:17:41 +00:00
return PAM_CONV_ERR;
memset(*rspv, 0, msgc * sizeof(struct pam_response));
2019-09-27 13:47:45 +00:00
int rc = PAM_SUCCESS;
2019-09-27 13:47:45 +00:00
int counter = 0;
for (; counter < msgc; counter++) {
od_list_t *i;
od_list_foreach(&auth_data->link, i)
{
od_pam_auth_data_t *param;
param = od_container_of(i, od_pam_auth_data_t, link);
if (param->msg_style == msgv[counter]->msg_style) {
(*rspv)[counter].resp = strdup(param->value);
2019-09-27 13:47:45 +00:00
break;
2019-09-09 09:17:41 +00:00
}
}
if ((*rspv)[counter].resp == NULL) {
rc = PAM_CONV_ERR;
break;
}
2019-09-09 09:17:41 +00:00
}
2019-09-27 13:47:45 +00:00
if (rc != PAM_SUCCESS) {
for (; counter >= 0; counter--) {
od_list_t *i;
od_list_foreach(&auth_data->link, i)
{
od_pam_auth_data_t *param;
param = od_container_of(i, od_pam_auth_data_t, link);
if (param->msg_style == msgv[counter]->msg_style) {
free((*rspv)[counter].resp);
break;
}
}
2019-09-27 13:47:45 +00:00
}
2019-09-09 09:17:41 +00:00
free(*rspv);
*rspv = NULL;
2019-09-09 09:17:41 +00:00
}
2019-09-27 13:47:45 +00:00
return rc;
2019-09-09 09:17:41 +00:00
}
int
od_pam_auth(char *od_pam_service,
char *usrname,
2020-06-09 09:19:11 +00:00
od_pam_auth_data_t *auth_data,
machine_io_t *io)
2019-09-27 13:47:45 +00:00
{
struct pam_conv conv = {
2019-09-27 13:47:45 +00:00
od_pam_conversation,
.appdata_ptr = auth_data,
2019-09-09 09:17:41 +00:00
};
pam_handle_t *pamh = NULL;
2019-09-27 13:47:45 +00:00
int rc;
2020-06-09 09:19:11 +00:00
rc = pam_start(od_pam_service, usrname, &conv, &pamh);
2019-09-27 13:47:45 +00:00
if (rc != PAM_SUCCESS)
goto error;
char peer[128];
od_getpeername(io, peer, sizeof(peer), 1, 0);
rc = pam_set_item(pamh, PAM_RHOST, peer);
if (rc != PAM_SUCCESS) {
goto error;
}
rc = pam_authenticate(pamh, PAM_SILENT);
2019-09-27 13:47:45 +00:00
if (rc != PAM_SUCCESS)
goto error;
2019-09-27 13:47:45 +00:00
rc = pam_acct_mgmt(pamh, PAM_SILENT);
if (rc != PAM_SUCCESS)
goto error;
rc = pam_end(pamh, rc);
if (rc != PAM_SUCCESS)
2019-09-09 09:17:41 +00:00
return -1;
2019-09-27 13:47:45 +00:00
return 0;
error:
pam_end(pamh, rc);
return -1;
2019-09-09 09:17:41 +00:00
}
2020-06-09 09:19:11 +00:00
void
od_pam_convert_passwd(od_pam_auth_data_t *d, char *passwd)
2020-06-09 09:19:11 +00:00
{
od_list_t *i;
od_list_foreach(&d->link, i)
{
od_pam_auth_data_t *param =
od_container_of(i, od_pam_auth_data_t, link);
if (param->msg_style == PAM_PROMPT_ECHO_OFF) {
param->value = strdup(passwd);
}
return;
}
od_pam_auth_data_t *passwd_data = malloc(sizeof(od_pam_auth_data_t));
passwd_data->msg_style = PAM_PROMPT_ECHO_OFF;
passwd_data->value = strdup(passwd);
2020-06-09 09:19:11 +00:00
od_list_append(&d->link, &passwd_data->link);
2020-06-09 09:19:11 +00:00
}
od_pam_auth_data_t *
od_pam_auth_data_create(void)
2020-06-09 09:19:11 +00:00
{
od_pam_auth_data_t *d;
d = (od_pam_auth_data_t *)malloc(sizeof(*d));
if (d == NULL)
return NULL;
od_list_init(&d->link);
return d;
}
void
od_pam_auth_data_free(od_pam_auth_data_t *d)
{
od_list_t *i;
od_list_foreach(&d->link, i)
{
od_pam_auth_data_t *current =
od_container_of(i, od_pam_auth_data_t, link);
free(current->value);
}
2020-06-09 09:19:11 +00:00
od_list_unlink(&d->link);
free(d);
}