1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
|
#define BITLBEE_CORE
#include "bitlbee.h"
#include <security/pam_appl.h>
#define PAM_CHECK(x) do { \
ret = (x); \
if(ret != PAM_SUCCESS) { \
pam_func = #x; \
goto pam_error; \
} \
} while(0)
/* This function fills in the password when PAM asks for it */
int pamconv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) {
int i;
struct pam_response *rsp = g_new0(struct pam_response, num_msg);
for (i = 0; i < num_msg; i++) {
rsp[i].resp = NULL;
rsp[i].resp_retcode = 0;
if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF) {
rsp[i].resp = g_strdup((char *)appdata_ptr);
}
}
*resp = rsp;
return PAM_SUCCESS;
}
static storage_status_t pam_check_pass(const char *nick, const char *password)
{
int ret;
const struct pam_conv pamc = { pamconv, (void*) password };
pam_handle_t *pamh = NULL;
char *pam_func;
PAM_CHECK(pam_start("bitlbee", nick, &pamc, &pamh));
PAM_CHECK(pam_authenticate(pamh, PAM_DISALLOW_NULL_AUTHTOK));
PAM_CHECK(pam_acct_mgmt(pamh, 0));
pam_end(pamh, ret);
return STORAGE_OK;
pam_error:
switch (ret) {
case PAM_AUTH_ERR:
pam_end(pamh, ret);
return STORAGE_INVALID_PASSWORD;
case PAM_USER_UNKNOWN:
case PAM_PERM_DENIED:
pam_end(pamh, ret);
return STORAGE_NO_SUCH_USER;
default:
log_message(LOGLVL_WARNING, "%s failed: %s", pam_func, pam_strerror(pamh, ret));
pam_end(pamh, ret);
return STORAGE_OTHER_ERROR;
}
}
auth_backend_t auth_pam = {
.name = "pam",
.check_pass = pam_check_pass,
};
|