From patchwork Fri Aug 8 11:14:06 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stanislav Ravas X-Patchwork-Id: 378189 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from hemlock.osuosl.org (hemlock.osuosl.org [140.211.166.133]) by ozlabs.org (Postfix) with ESMTP id 78E40140120 for ; Fri, 8 Aug 2014 21:19:49 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id 539CF931CF; Fri, 8 Aug 2014 11:19:48 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from hemlock.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id MkkChemWk6N0; Fri, 8 Aug 2014 11:19:46 +0000 (UTC) Received: from ash.osuosl.org (ash.osuosl.org [140.211.166.34]) by hemlock.osuosl.org (Postfix) with ESMTP id A1222931B6; Fri, 8 Aug 2014 11:19:46 +0000 (UTC) X-Original-To: buildroot@lists.busybox.net Delivered-To: buildroot@osuosl.org Received: from whitealder.osuosl.org (whitealder.osuosl.org [140.211.166.138]) by ash.osuosl.org (Postfix) with ESMTP id 922451BFA51 for ; Fri, 8 Aug 2014 11:19:45 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 8D3C18CDF9 for ; Fri, 8 Aug 2014 11:19:45 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id HnNtGCJOP0DJ for ; Fri, 8 Aug 2014 11:19:44 +0000 (UTC) X-Greylist: delayed 00:05:25 by SQLgrey-1.7.6 Received: from mxload.webglobe.sk (mxload.webglobe.sk [212.57.32.39]) by whitealder.osuosl.org (Postfix) with ESMTP id 9D63F8CEAA for ; Fri, 8 Aug 2014 11:19:43 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by mxload.webglobe.sk (Postfix) with ESMTP id DF08D303A8A30 for ; Fri, 8 Aug 2014 13:14:15 +0200 (CEST) X-Virus-Scanned: AVscan on mxload.webglobe.sk Received: from mxload.webglobe.sk ([127.0.0.1]) by localhost (inmail-08.webglobe.sk [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 3ue-Gww4myoM for ; Fri, 8 Aug 2014 13:14:06 +0200 (CEST) Received: from [192.168.0.56] (unknown [193.87.79.243]) (Authenticated sender: ravas@tind.sk) by mxload.webglobe.sk (Postfix) with ESMTPSA id EF06E30340C2B for ; Fri, 8 Aug 2014 13:14:06 +0200 (CEST) Message-ID: <53E4B0FE.3020703@tind.sk> Date: Fri, 08 Aug 2014 13:14:06 +0200 From: Stanislav Ravas User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Icedove/24.5.0 MIME-Version: 1.0 To: buildroot@busybox.net Subject: [Buildroot] [PATCH] lighttpd PAM auth X-BeenThere: buildroot@busybox.net X-Mailman-Version: 2.1.14 Precedence: list List-Id: Discussion and development of buildroot List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: buildroot-bounces@busybox.net Sender: buildroot-bounces@busybox.net Hello, this patch adds basic support for PAM authentification to lighttpd. It applies to version 1.4.35. I have submitted this patch to lighttpd upstream too, but I doubt they will accept. Stano From 1f93264972a7cb3070e86de5a476de1dec8b1456 Mon Sep 17 00:00:00 2001 From: Stanislav Ravas Date: Thu, 7 Aug 2014 14:08:26 +0200 Subject: [PATCH] pam_auth: PAM authentification support --- configure.ac | 23 ++++++++++++++++++ src/Makefile.am | 2 +- src/http_auth.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/http_auth.h | 17 +++++++++++++- src/mod_auth.c | 12 +++++++++- 5 files changed, 120 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 48e6b52..75062e8 100644 --- a/configure.ac +++ b/configure.ac @@ -212,6 +212,22 @@ if test "$WITH_LDAP" != "no"; then AC_SUBST(LBER_LIB) fi +dnl Check for PAM +AC_MSG_CHECKING(for PAM support) +AC_ARG_WITH(pam, AC_HELP_STRING([--with-pam],[enable PAM support]), +[WITH_PAM=$withval], [WITH_PAM=no]) +AC_MSG_RESULT([$withval]) +if test "$WITH_PAM" != "no"; then + AC_CHECK_LIB(pam, pam_start, [ + AC_CHECK_HEADERS([security/pam_appl.h],[ + PAM_LIB=-lpam + AC_DEFINE([HAVE_LIBPAM], [1], [libpam]) + AC_DEFINE([HAVE_SECURITY_PAM_APPL_H], [1]) + ]) + ]) + AC_SUBST(PAM_LIB) +fi + dnl Check for xattr AC_MSG_CHECKING(for extended attributes support) AC_ARG_WITH(attr, AC_HELP_STRING([--with-attr],[enable extended attribute support]), @@ -723,6 +739,13 @@ else disable_feature="$disable_feature $features" fi +features="auth-pam" +if test ! "x$PAM_LIB" = x; then + enable_feature="$enable_feature $features" +else + disable_feature="$disable_feature $features" +fi + features="network-openssl" if test ! "x$SSL_LIB" = x; then enable_feature="$enable_feature $features" diff --git a/src/Makefile.am b/src/Makefile.am index 4afdcc6..b40c5ce 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -243,7 +243,7 @@ mod_compress_la_LIBADD = $(Z_LIB) $(BZ_LIB) $(common_libadd) lib_LTLIBRARIES += mod_auth.la mod_auth_la_SOURCES = mod_auth.c http_auth.c mod_auth_la_LDFLAGS = -module -export-dynamic -avoid-version -mod_auth_la_LIBADD = $(CRYPT_LIB) $(SSL_LIB) $(LDAP_LIB) $(LBER_LIB) $(common_libadd) +mod_auth_la_LIBADD = $(CRYPT_LIB) $(SSL_LIB) $(LDAP_LIB) $(LBER_LIB) $(PAM_LIB) $(common_libadd) lib_LTLIBRARIES += mod_rewrite.la mod_rewrite_la_SOURCES = mod_rewrite.c diff --git a/src/http_auth.c b/src/http_auth.c index e1d15e0..3b169fc 100644 --- a/src/http_auth.c +++ b/src/http_auth.c @@ -315,6 +315,8 @@ static int http_auth_get_password(server *srv, mod_auth_plugin_data *p, buffer * stream_close(&f); } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) { ret = 0; + } else if (p->conf.auth_backend == AUTH_BACKEND_PAM) { + ret = 0; } else { return -1; } @@ -629,6 +631,35 @@ static void apr_sha_encode(const char *pw, char *result, size_t nbytes) { } #endif +#ifdef USE_PAM +// appdata_ptr shall point to mod_auth_pam_data structure +static int pam_fn_conv(int num_msg, const struct pam_message **msg, struct pam_response **p_resp, void *appdata_ptr) { + mod_auth_pam_data *p_pam = (mod_auth_pam_data *)appdata_ptr; + struct pam_response *resp = (struct pam_response *)malloc(num_msg * sizeof(struct pam_response)); + + for(int i = 0; i < num_msg; ++i) { + switch(msg[i]->msg_style) { + case PAM_PROMPT_ECHO_OFF: + case PAM_PROMPT_ECHO_ON: + resp[i].resp = strdup(p_pam->password); + resp[i].resp_retcode = 0; + break; + case PAM_ERROR_MSG: + case PAM_TEXT_INFO: + default: + // ignore + resp[i].resp_retcode = 0; + resp[i].resp = NULL; + continue; + } + } + + *p_resp = resp; + + return PAM_SUCCESS; +} +#endif + /** * * @@ -834,7 +865,44 @@ static int http_auth_basic_password_compare(server *srv, mod_auth_plugin_data *p return 0; #endif - } + } else if (p->conf.auth_backend == AUTH_BACKEND_PAM) { +#ifdef USE_PAM + pam_handle_t *pamh = NULL; + mod_auth_pam_data pam_data = { + &p->conf, + username->ptr, + realm->ptr, + pw + }; + struct pam_conv conv = { pam_fn_conv, &pam_data }; + + int retval = pam_start( + !buffer_is_empty(p->conf.auth_pam_servicename) ? p->conf.auth_pam_servicename->ptr : "lighttpd", + username->ptr, + &conv, + &pamh); + + if(retval != PAM_SUCCESS) + goto auth_pam_fail; + + if((retval = pam_authenticate(pamh, PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK)) != PAM_SUCCESS) + goto auth_pam_fail; + + if((retval = pam_acct_mgmt(pamh, PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK)) != PAM_SUCCESS) + goto auth_pam_fail; + + if (p->conf.auth_debug > 1) + log_error_write(srv, __FILE__, __LINE__, "ss", "pam: authenticated as", username->ptr); + + pam_end(pamh, retval); + return 0; + +auth_pam_fail: + log_error_write(srv, __FILE__, __LINE__, "ss", "pam:", pam_strerror(pamh, retval)); + pam_end(pamh, retval); + return -1; +#endif + } return -1; } diff --git a/src/http_auth.h b/src/http_auth.h index 081cef3..ad3143f 100644 --- a/src/http_auth.h +++ b/src/http_auth.h @@ -9,12 +9,18 @@ # include #endif +#if defined(HAVE_SECURITY_PAM_APPL_H) && defined(HAVE_LIBPAM) +# define USE_PAM +# include +#endif + typedef enum { AUTH_BACKEND_UNSET, AUTH_BACKEND_PLAIN, AUTH_BACKEND_LDAP, AUTH_BACKEND_HTPASSWD, - AUTH_BACKEND_HTDIGEST + AUTH_BACKEND_HTDIGEST, + AUTH_BACKEND_PAM } auth_backend_t; typedef struct { @@ -38,6 +44,8 @@ typedef struct { unsigned short auth_ldap_starttls; unsigned short auth_ldap_allow_empty_pw; + buffer *auth_pam_servicename; + unsigned short auth_debug; /* generated */ @@ -66,6 +74,13 @@ typedef struct { mod_auth_plugin_config conf, *anon_conf; /* this is only used as long as no handler_ctx is setup */ } mod_auth_plugin_data; +typedef struct { + mod_auth_plugin_config *conf; + const char *username; + const char *realm; + const char *password; +} mod_auth_pam_data; + int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, const char *realm_str); int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, const char *realm_str); int http_auth_digest_generate_nonce(server *srv, mod_auth_plugin_data *p, buffer *fn, char hh[33]); diff --git a/src/mod_auth.c b/src/mod_auth.c index 31e1140..163fd95 100644 --- a/src/mod_auth.c +++ b/src/mod_auth.c @@ -76,6 +76,8 @@ FREE_FUNC(mod_auth_free) { buffer_free(s->auth_ldap_filter); buffer_free(s->auth_ldap_cafile); + buffer_free(s->auth_pam_servicename); + #ifdef USE_LDAP buffer_free(s->ldap_filter_pre); buffer_free(s->ldap_filter_post); @@ -114,6 +116,7 @@ static int mod_auth_patch_connection(server *srv, connection *con, mod_auth_plug PATCH(auth_ldap_cafile); PATCH(auth_ldap_starttls); PATCH(auth_ldap_allow_empty_pw); + PATCH(auth_pam_servicename); #ifdef USE_LDAP p->anon_conf = s; PATCH(ldap_filter_pre); @@ -169,7 +172,9 @@ static int mod_auth_patch_connection(server *srv, connection *con, mod_auth_plug PATCH(auth_ldap_bindpw); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.allow-empty-pw"))) { PATCH(auth_ldap_allow_empty_pw); - } + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.pam.service-name"))) { + PATCH(auth_pam_servicename); + } } } @@ -361,6 +366,7 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { { "auth.backend.htdigest.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 12 */ { "auth.backend.htpasswd.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 13 */ { "auth.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 14 */ + { "auth.backend.pam.service-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 15 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; @@ -386,6 +392,7 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { s->auth_ldap_filter = buffer_init(); s->auth_ldap_cafile = buffer_init(); s->auth_ldap_starttls = 0; + s->auth_pam_servicename = buffer_init(); s->auth_debug = 0; s->auth_require = array_init(); @@ -411,6 +418,7 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { cv[12].destination = s->auth_htdigest_userfile; cv[13].destination = s->auth_htpasswd_userfile; cv[14].destination = &(s->auth_debug); + cv[15].destination = s->auth_pam_servicename; p->config_storage[i] = s; ca = ((data_config *)srv->config_context->data[i])->value; @@ -428,6 +436,8 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { s->auth_backend = AUTH_BACKEND_PLAIN; } else if (0 == strcmp(s->auth_backend_conf->ptr, "ldap")) { s->auth_backend = AUTH_BACKEND_LDAP; + } else if (0 == strcmp(s->auth_backend_conf->ptr, "pam")) { + s->auth_backend = AUTH_BACKEND_PAM; } else { log_error_write(srv, __FILE__, __LINE__, "sb", "auth.backend not supported:", s->auth_backend_conf); -- 1.7.10.4