diff options
author | Dennis Kaarsemaker <dennis@kaarsemaker.net> | 2016-02-23 19:52:32 +0100 |
---|---|---|
committer | Dennis Kaarsemaker <dennis@kaarsemaker.net> | 2016-03-25 19:07:53 +0100 |
commit | a6005da78ae1563ae4577179d1e54fff74cfe21a (patch) | |
tree | 5429777b8c47b3a33f0213952c8b6de932974e89 /auth_pam.c | |
parent | 8e6ecfe23ff985e57675bd00b94860edb62de9ad (diff) |
Linux pam authentication backend
This backend authenticates users against pam.
Diffstat (limited to 'auth_pam.c')
-rw-r--r-- | auth_pam.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/auth_pam.c b/auth_pam.c new file mode 100644 index 00000000..1a8f4344 --- /dev/null +++ b/auth_pam.c @@ -0,0 +1,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, +}; |