Feature #688 » lighttpd-02-pam_auth.patch
configure.ac | ||
---|---|---|
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]),
|
||
... | ... | |
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"
|
src/Makefile.am | ||
---|---|---|
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
|
src/http_auth.c | ||
---|---|---|
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;
|
||
}
|
||
... | ... | |
}
|
||
#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
|
||
/**
|
||
*
|
||
*
|
||
... | ... | |
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;
|
||
}
|
||
src/http_auth.h | ||
---|---|---|
# include <ldap.h>
|
||
#endif
|
||
#if defined(HAVE_SECURITY_PAM_APPL_H) && defined(HAVE_LIBPAM)
|
||
# define USE_PAM
|
||
# include <security/pam_appl.h>
|
||
#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 {
|
||
... | ... | |
unsigned short auth_ldap_starttls;
|
||
unsigned short auth_ldap_allow_empty_pw;
|
||
buffer *auth_pam_servicename;
|
||
unsigned short auth_debug;
|
||
/* generated */
|
||
... | ... | |
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]);
|
src/mod_auth.c | ||
---|---|---|
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);
|
||
... | ... | |
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);
|
||
... | ... | |
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);
|
||
}
|
||
}
|
||
}
|
||
... | ... | |
{ "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 }
|
||
};
|
||
... | ... | |
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();
|
||
... | ... | |
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;
|
||
... | ... | |
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);
|
||