Project

General

Profile

Feature #688 » 0003-pam-auth.patch

akschu1, 2018-09-17 19:47

View differences:

lighttpd-1.4.50/configure.ac 2018-09-17 10:50:50.339749492 -0800
fi
AM_CONDITIONAL([BUILD_WITH_LDAP], [test "$WITH_LDAP" != no])
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
AM_CONDITIONAL(BUILD_WITH_PAM, test ! $WITH_PAM = no)
dnl Check for xattr
AC_MSG_NOTICE([----------------------------------------])
AC_MSG_CHECKING([for extended attributes support])
......
mod_wstunnel \
"
plugins="mod_authn_pam"
if test ! "x$PAM_LIB" = x; then
do_build="$do_build $plugins"
else
no_build="$no_build $plugins"
fi
lighty_track_feature() {
if eval "$3"; then
enable_feature="$enable_feature $1"
lighttpd-1.4.50/src/Makefile.am 2018-09-17 10:50:50.346749589 -0800
mod_authn_ldap_la_LIBADD = $(LDAP_LIB) $(LBER_LIB) $(common_libadd)
endif
if BUILD_WITH_PAM
lib_LTLIBRARIES += mod_authn_pam.la
mod_authn_pam_la_SOURCES = mod_authn_pam.c
mod_authn_pam_la_LDFLAGS = $(common_module_ldflags)
mod_authn_pam_la_LIBADD = $(PAM_LIB) $(common_libadd)
endif
if BUILD_WITH_MYSQL
lib_LTLIBRARIES += mod_authn_mysql.la
mod_authn_mysql_la_SOURCES = mod_authn_mysql.c
lighttpd-1.4.50/src/configfile.c 2018-09-17 10:50:50.351749629 -0800
#include <glob.h>
#if defined(HAVE_MYSQL) || (defined(HAVE_LDAP_H) && defined(HAVE_LBER_H) && defined(HAVE_LIBLDAP) && defined(HAVE_LIBLBER))
#if defined(HAVE_LIBPAM) || defined(HAVE_MYSQL) || (defined(HAVE_LDAP_H) && defined(HAVE_LBER_H) && defined(HAVE_LIBLDAP) && defined(HAVE_LIBLBER))
static void config_warn_authn_module (server *srv, const char *module) {
size_t len = strlen(module);
for (size_t i = 0; i < srv->config_context->used; ++i) {
......
int append_mod_authn_file = 1;
int append_mod_authn_ldap = 1;
int append_mod_authn_mysql = 1;
int append_mod_authn_pam = 1;
int append_mod_openssl = 1;
int contains_mod_auth = 0;
......
append_mod_authn_mysql = 0;
}
if (buffer_is_equal_string(ds->value, CONST_STR_LEN("mod_authn_pam"))) {
append_mod_authn_pam = 0;
}
if (buffer_is_equal_string(ds->value, CONST_STR_LEN("mod_auth"))) {
contains_mod_auth = 1;
}
......
0 == append_mod_authn_file &&
0 == append_mod_authn_ldap &&
0 == append_mod_authn_mysql &&
0 == append_mod_authn_pam &&
1 == contains_mod_auth) {
break;
}
lighttpd-1.4.50/src/mod_authn_pam.c 2018-09-17 10:51:47.680591497 -0800
#include "first.h"
#define USE_PAM
#include <security/pam_appl.h>
#include "base.h"
#include "http_auth.h"
#include "log.h"
#include "plugin.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
buffer *auth_pam_servicename;
} plugin_config;
typedef struct {
PLUGIN_DATA;
plugin_config **config_storage;
plugin_config conf, *anon_conf; /* this is only used as long as no handler_ctx is setup */
} plugin_data;
static handler_t mod_authn_pam_basic(server *srv, connection *con, void *p_d, const http_auth_require_t *require, const buffer *username, const char *pw);
INIT_FUNC(mod_authn_pam_init) {
static http_auth_backend_t http_auth_backend_pam =
{ "pam", mod_authn_pam_basic, NULL, NULL };
plugin_data *p = calloc(1, sizeof(*p));
/* register http_auth_backend_pam */
http_auth_backend_pam.p_d = p;
http_auth_backend_set(&http_auth_backend_pam);
return p;
}
FREE_FUNC(mod_authn_pam_free) {
plugin_data *p = p_d;
UNUSED(srv);
if (!p) return HANDLER_GO_ON;
if (p->config_storage) {
size_t i;
for (i = 0; i < srv->config_context->used; i++) {
plugin_config *s = p->config_storage[i];
if (NULL == s) continue;
buffer_free(s->auth_pam_servicename);
free(s);
}
free(p->config_storage);
}
free(p);
return HANDLER_GO_ON;
}
SETDEFAULTS_FUNC(mod_authn_pam_set_defaults) {
plugin_data *p = p_d;
size_t i;
config_values_t cv[] = {
{ "auth.backend.pam.service-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
{ NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
};
p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *));
for (i = 0; i < srv->config_context->used; i++) {
data_config const* config = (data_config const*)srv->config_context->data[i];
plugin_config *s;
s = calloc(1, sizeof(plugin_config));
s->auth_pam_servicename = buffer_init();
cv[0].destination = s->auth_pam_servicename;
p->config_storage[i] = s;
if (0 != config_insert_values_global(srv, config->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION)) {
return HANDLER_ERROR;
}
}
return HANDLER_GO_ON;
}
#define PATCH(x) \
p->conf.x = s->x;
static int mod_authn_pam_patch_connection(server *srv, connection *con, plugin_data *p) {
size_t i, j;
plugin_config *s = p->config_storage[0];
PATCH(auth_pam_servicename);
/* skip the first, the global context */
for (i = 1; i < srv->config_context->used; i++) {
data_config *dc = (data_config *)srv->config_context->data[i];
s = p->config_storage[i];
/* condition didn't match */
if (!config_check_cond(srv, con, dc)) continue;
/* merge config */
for (j = 0; j < dc->value->used; j++) {
data_unset *du = dc->value->data[j];
if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.pam.service-name"))) {
PATCH(auth_pam_servicename);
}
}
}
return 0;
}
#undef PATCH
typedef struct {
plugin_config *conf;
const char *username;
const char *realm;
const char *password;
} mod_auth_pam_data;
static int mod_authn_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;
}
static handler_t mod_authn_pam_basic(server *srv, connection *con, void *p_d, const http_auth_require_t *require, const buffer *username, const char *pw) {
plugin_data *p = (plugin_data *)p_d;
pam_handle_t *pamh = NULL;
mod_auth_pam_data pam_data = {
&p->conf,
username->ptr,
require->realm->ptr,
pw
};
struct pam_conv conv = { mod_authn_pam_fn_conv, &pam_data };
mod_authn_pam_patch_connection(srv, con, p);
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;
pam_end(pamh, retval);
return HANDLER_GO_ON;
auth_pam_fail:
log_error_write(srv, __FILE__, __LINE__, "ss", "pam:", pam_strerror(pamh, retval));
pam_end(pamh, retval);
return HANDLER_ERROR;
}
int mod_authn_pam_plugin_init(plugin *p);
int mod_authn_pam_plugin_init(plugin *p) {
p->version = LIGHTTPD_VERSION_ID;
p->name = buffer_init_string("authn_pam");
p->init = mod_authn_pam_init;
p->set_defaults = mod_authn_pam_set_defaults;
p->cleanup = mod_authn_pam_free;
p->data = NULL;
return 0;
}
lighttpd-1.4.50/src/server.c 2018-09-17 10:50:50.358749597 -0800
#else
"\t- DBI support\n"
#endif
#ifdef HAVE_LIBPAM
"\t+ PAM support\n"
#else
"\t- PAM support\n"
#endif
#ifdef HAVE_KRB5
"\t+ Kerberos support\n"
#else
(3-3/3)