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