#include "c2s.h"
#ifdef STORAGE_PAM
#include <security/pam_appl.h>
static int _ar_pam_user_exists(authreg_t ar, char *username, char *realm) {
return 1;
}
static int _ar_pam_conversation(int nmsg, const struct pam_message **msg, struct pam_response **res, void *arg) {
int i;
struct pam_response *reply;
if(nmsg <= 0)
return PAM_CONV_ERR;
reply = (struct pam_response *) malloc(sizeof(struct pam_response) * nmsg);
memset(reply, 0, sizeof(struct pam_response) * nmsg);
for(i = 0; i < nmsg; i++) {
if(msg[i]->msg_style == PAM_PROMPT_ECHO_OFF || msg[i]->msg_style == PAM_PROMPT_ECHO_ON) {
reply[i].resp = strdup((char *) arg);
reply[i].resp_retcode = 0;
}
}
*res = reply;
return PAM_SUCCESS;
}
#ifdef PAM_FAIL_DELAY
static int _ar_pam_delay(int ret, unsigned int usec, void *arg) {
return PAM_SUCCESS;
}
#endif
static int _ar_pam_check_password(authreg_t ar, char *username, char *realm, char password[257]) {
struct pam_conv conv;
pam_handle_t *pam;
int ret;
conv.conv = _ar_pam_conversation;
conv.appdata_ptr = password;
ret = pam_start("jabberd", username, &conv, &pam);
if(ret != PAM_SUCCESS) {
log_write(ar->c2s->log, LOG_ERR, "pam: couldn't initialise PAM: %s", pam_strerror(NULL, ret));
return 1;
}
#ifdef PAM_FAIL_DELAY
ret = pam_set_item(pam, PAM_FAIL_DELAY, _ar_pam_delay);
if(ret != PAM_SUCCESS) {
log_write(ar->c2s->log, LOG_ERR, "pam: couldn't disable fail delay: %s", pam_strerror(NULL, ret));
return 1;
}
#endif
ret = pam_authenticate(pam, 0);
if(ret == PAM_AUTHINFO_UNAVAIL || ret == PAM_USER_UNKNOWN) {
pam_end(pam, ret);
return 1;
}
if(ret != PAM_SUCCESS) {
log_write(ar->c2s->log, LOG_ERR, "pam: couldn't authenticate: %s", pam_strerror(NULL, ret));
pam_end(pam, ret);
return 1;
}
ret = pam_acct_mgmt(pam, 0);
if(ret != PAM_SUCCESS) {
log_write(ar->c2s->log, LOG_ERR, "pam: auth succeeded, but can't use account: %s", pam_strerror(NULL, ret));
pam_end(pam, ret);
return 1;
}
pam_end(pam, ret);
return 0;
}
int ar_pam_init(authreg_t ar) {
ar->user_exists = _ar_pam_user_exists;
ar->check_password = _ar_pam_check_password;
return 0;
}
#endif