From a6005da78ae1563ae4577179d1e54fff74cfe21a Mon Sep 17 00:00:00 2001 From: Dennis Kaarsemaker Date: Tue, 23 Feb 2016 19:52:32 +0100 Subject: Linux pam authentication backend This backend authenticates users against pam. --- .travis.yml | 5 +++-- auth.c | 10 ++++++++++ auth_pam.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bitlbee.conf | 5 +++++ conf.c | 3 +++ configure | 15 ++++++++++++++ tests/Makefile | 2 +- 7 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 auth_pam.c diff --git a/.travis.yml b/.travis.yml index 6a0da07f..992ede90 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ sudo: false language: c script: - - ./configure + - ./configure --pam=1 - make check - BITLBEE_SKYPE=plugin dpkg-buildpackage -uc -us -d @@ -28,12 +28,13 @@ addons: - libevent-dev - libpurple-dev - check + - libpam0g-dev coverity_scan: project: name: "bitlbee/bitlbee" description: "An IRC to other chat networks gateway" notification_email: dx@dxzone.com.ar - build_command_prepend: ./configure --otr=1 --debug=1 + build_command_prepend: ./configure --otr=1 --debug=1 --pam=1 build_command: make branch_pattern: coverity_scan diff --git a/auth.c b/auth.c index e83a683f..9717acc1 100644 --- a/auth.c +++ b/auth.c @@ -1,10 +1,20 @@ #define BITLBEE_CORE #include "bitlbee.h" +#ifdef WITH_PAM +extern auth_backend_t auth_pam; +#endif + GList *auth_init(const char *backend) { GList *gl = NULL; int ok = backend ? 0 : 1; +#ifdef WITH_PAM + gl = g_list_append(gl, &auth_pam); + if (backend && !strcmp(backend, "pam")) { + ok = 1; + } +#endif return ok ? gl : NULL; } 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 + +#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, +}; diff --git a/bitlbee.conf b/bitlbee.conf index 60c5bdf7..d781a7b1 100644 --- a/bitlbee.conf +++ b/bitlbee.conf @@ -60,6 +60,11 @@ ## Beware that this disables password changes and causes passwords for the ## accounts people create to be stored in plain text instead of encrypted with ## their bitlbee password. +## +## Currently available backends: +## +## - storage (internal storage) +## - pam (Linux PAM authentication) # # AuthBackend = storage # diff --git a/conf.c b/conf.c index 24e71b91..403f417a 100644 --- a/conf.c +++ b/conf.c @@ -244,6 +244,9 @@ static int conf_loadini(conf_t *conf, char *file) } else if (g_strcasecmp(ini->key, "authbackend") == 0) { if (g_strcasecmp(ini->value, "storage") == 0) { conf->auth_backend = NULL; + } else if (g_strcasecmp(ini->value, "pam") == 0) { + g_free(conf->auth_backend); + conf->auth_backend = g_strdup(ini->value); } else { fprintf(stderr, "Invalid %s value: %s\n", ini->key, ini->value); return 0; diff --git a/configure b/configure index 8089d1a2..4c08b034 100755 --- a/configure +++ b/configure @@ -51,6 +51,8 @@ skype=0 events=glib ssl=auto +pam=0 + pie=1 arch=$(uname -s) @@ -133,6 +135,8 @@ Option Description Default --purple=0/1 Disable/enable libpurple support $purple (automatically disables other protocol modules) +--pam=0/1 Disable/enable PAM authentication $pam + --doc=0/1 Disable/enable help.txt generation $doc --debug=0/1 Disable/enable debugging $debug --strip=0/1 Disable/enable binary stripping $strip @@ -630,6 +634,17 @@ echo "STORAGE_OBJS="$STORAGE_OBJS >> Makefile.settings authobjs= authlibs= +if [ "$pam" = 0 ]; then + echo '#undef WITH_PAM' >> config.h +else + if ! echo '#include ' | $CC -E - >/dev/null 2>/dev/null; then + echo 'Cannot find libpam development libraries, aborting. (Install libpam0g-dev?)' + exit 1 + fi + echo '#define WITH_PAM' >> config.h + authobjs=$authobjs'auth_pam.o ' + authlibs=$authlibs'-lpam ' +fi echo AUTH_OBJS=$authobjs >> Makefile.settings echo EFLAGS+=$authlibs >> Makefile.settings diff --git a/tests/Makefile b/tests/Makefile index 02cac9eb..77ed2273 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -14,7 +14,7 @@ clean: distclean: clean -main_objs = bitlbee.o conf.o dcc.o help.o ipc.o irc.o irc_cap.o irc_channel.o irc_commands.o irc_im.o irc_send.o irc_user.o irc_util.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o auth.o +main_objs = bitlbee.o conf.o dcc.o help.o ipc.o irc.o irc_cap.o irc_channel.o irc_commands.o irc_im.o irc_send.o irc_user.o irc_util.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o auth.o auth_pam.o test_objs = check.o check_util.o check_nick.o check_md5.o check_arc.o check_irc.o check_help.o check_user.o check_set.o check_jabber_sasl.o check_jabber_util.o -- cgit v1.2.3