aboutsummaryrefslogtreecommitdiffstats
path: root/auth_pam.c
diff options
context:
space:
mode:
authorDennis Kaarsemaker <dennis@kaarsemaker.net>2016-02-23 19:52:32 +0100
committerDennis Kaarsemaker <dennis@kaarsemaker.net>2016-03-25 19:07:53 +0100
commita6005da78ae1563ae4577179d1e54fff74cfe21a (patch)
tree5429777b8c47b3a33f0213952c8b6de932974e89 /auth_pam.c
parent8e6ecfe23ff985e57675bd00b94860edb62de9ad (diff)
Linux pam authentication backend
This backend authenticates users against pam.
Diffstat (limited to 'auth_pam.c')
-rw-r--r--auth_pam.c62
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,
+};