summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Pazdziora <jpazdziora@redhat.com>2015-07-08 09:48:11 +0200
committerJan Pazdziora <jpazdziora@redhat.com>2015-08-03 10:23:21 +0200
commit91c82a1bfbc0d34c5de3426e6a3f5c3e48d287b8 (patch)
tree0486e93fc9ffbc40a9e4a4f7919d93319c4e87bf
parenta43853ab8129e5c327d7a868848e11ecf1d99e3c (diff)
downloadmod_lookup_identity-91c82a1bfbc0d34c5de3426e6a3f5c3e48d287b8.tar.gz
mod_lookup_identity-91c82a1bfbc0d34c5de3426e6a3f5c3e48d287b8.tar.xz
mod_lookup_identity-91c82a1bfbc0d34c5de3426e6a3f5c3e48d287b8.zip
Add support for LookupUserByCertificate.mod_lookup_identity-0.9.3
-rw-r--r--README69
-rw-r--r--mod_lookup_identity.c171
-rw-r--r--mod_lookup_identity.spec5
3 files changed, 223 insertions, 22 deletions
diff --git a/README b/README
index 7a66cd6..cf2c53c 100644
--- a/README
+++ b/README
@@ -2,21 +2,59 @@
Apache module mod_lookup_identity
=================================
-Apache module to retrieve additional information about the
-authenticated user.
+Apache module to lookup user identifier and retrieve additional
+information about the authenticated user.
-It retrieves the GECOS information using the getpwnam call and stores
-it in a note/environment variable (by default REMOTE_USER_GECOS).
-It allows to get list of group names the user belongs using sssd dbus
-org.freedesktop.sssd.infopipe.GetUserGroups call and any custom
-attribute configured in /etc/sssd/sssd.conf using sssd dbus
-org.freedesktop.sssd.infopipe.GetUserAttr call.
+The module supports lookup of the user identifier based on certificate
+via SSSD D-Bus call org.freedesktop.sssd.infopipe.Users.FindByCertificate,
+setting up the r->user request structure.
+
+It also allows retrieval of list of group names the user belongs to
+using org.freedesktop.sssd.infopipe.GetUserGroups call and any
+custom attributes configured in /etc/sssd/sssd.conf using with
+org.freedesktop.sssd.infopipe.GetUserAttr call. It also retrieves
+the GECOS information using the getpwnam call. The retrieved values
+get stored in notes/environment variables.
The sssd-dbus package needs to be installed and the ifp service
-enabled in the [sssd] section of /etc/sssd/sssd.conf. Caching of
-non-POSIX attributes need to be enabled in the [domain/*] section of
-/etc/sssd/sssd.conf, configuration ldap_user_extra_attrs, and they
-also need to be enabled in the [ifp] section using the user_attributes
+enabled in the [sssd] section of /etc/sssd/sssd.conf.
+
+The module itself needs to be loaded into Apache's configuration file
+like /etc/httpd/conf/httpd.conf with directive like
+
+ LoadModule lookup_identity_module modules/mod_lookup_identity.so
+
+User Lookup
+-----------
+
+By default, no user identifier lookup is enabled. Directive
+
+ LookupUserByCertificate On
+
+enables the lookup. It uses the original internal r->user value
+as input, so the typical setup for example with mod_ssl will be
+
+ SSLVerifyClient require
+ SSLUserName SSL_CLIENT_CERT
+ LookupUserByCertificate On
+
+when mod_ssl puts the certificate to the username field and then
+mod_lookup_identity replaces it with user identifier found with
+org.freedesktop.sssd.infopipe.Users.FindByCertificate. If no user
+is found based on the certificate, the r->user value is cleared.
+Make sure the FakeBasicAuth is not enable in SSLOptions or the
+r->user will not be set.
+
+SSSD version 1.13 or higher is needed for LookupUserByCertificate
+functionality.
+
+Retrieving Group Membership and Attributes
+------------------------------------------
+
+For the custom attributes fetching, caching of non-POSIX attributes
+needs to be enabled in the [domain/*] section of /etc/sssd/sssd.conf,
+configuration ldap_user_extra_attrs, and the attributes also need to
+be enabled in the [ifp] section using the user_attributes
configuration option.
Example of sssd.conf:
@@ -32,11 +70,6 @@ Example of sssd.conf:
allowed_uids = apache, root
user_attributes = +mail, +telephoneNumber, +givenname, +sn
-The module itself needs to be loaded into Apache's configuration file
-like /etc/httpd/conf/httpd.conf with directive like
-
- LoadModule lookup_identity_module modules/mod_lookup_identity.so
-
The default behaviour can be changed with the following directives:
LookupOutput where_to_store_results
@@ -266,7 +299,7 @@ in and will not be available.
License
-------
-Copyright 2013--2014 Jan Pazdziora
+Copyright 2013--2015 Jan Pazdziora
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/mod_lookup_identity.c b/mod_lookup_identity.c
index cc65a90..123c223 100644
--- a/mod_lookup_identity.c
+++ b/mod_lookup_identity.c
@@ -1,6 +1,6 @@
/*
- * Copyright 2013--2014 Jan Pazdziora
+ * Copyright 2013--2015 Jan Pazdziora
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,11 +33,18 @@
#ifndef NO_USER_ATTR
#include <dbus/dbus.h>
#define DBUS_SSSD_PATH "/org/freedesktop/sssd/infopipe"
+#define DBUS_SSSD_PATH_USERS "/org/freedesktop/sssd/infopipe/Users"
#define DBUS_SSSD_IFACE "org.freedesktop.sssd.infopipe"
+#define DBUS_SSSD_IFACE_USERS "org.freedesktop.sssd.infopipe.Users"
#define DBUS_SSSD_GET_USER_GROUPS_METHOD "GetUserGroups"
#define DBUS_SSSD_GET_USER_ATTR_METHOD "GetUserAttr"
+#define DBUS_SSSD_FIND_BY_CERTIFICATE "FindByCertificate"
#define DBUS_SSSD_DEST "org.freedesktop.sssd.infopipe"
#define DBUS_SSSD_TIMEOUT 5000
+#define DBUS_PROPERTIES "org.freedesktop.DBus.Properties"
+#define DBUS_PROPERTIES_GET "Get"
+#define DBUS_SSSD_USERS_USER "org.freedesktop.sssd.infopipe.Users.User"
+#define DBUS_SSSD_USERS_ID "name";
#endif
static const int LOOKUP_IDENTITY_OUTPUT_NONE = 0;
@@ -60,12 +67,158 @@ typedef struct lookup_identity_config {
apr_hash_t * output_user_attr_sep;
apr_hash_t * output_user_attr_iter;
int dbus_timeout;
+ signed char lookup_by_certificate;
#endif
} lookup_identity_config;
module AP_MODULE_DECLARE_DATA lookup_identity_module;
#ifndef NO_USER_ATTR
+static int lookup_user_by_certificate(request_rec * r) {
+ const lookup_identity_config * cfg = (lookup_identity_config *) ap_get_module_config(r->per_dir_config, &lookup_identity_module);
+ if (cfg->lookup_by_certificate < 1 || ! r->user) {
+ return DECLINED;
+ }
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server, "lookup_user_by_certificate invoked [%s]", r->user);
+
+ static char * stage = NULL;
+ DBusError error;
+ dbus_error_init(&error);
+ DBusMessage * message = NULL;
+ DBusMessage * reply = NULL;
+
+ DBusConnection * connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ if (! connection) {
+ stage = "dbus_bus_get(DBUS_BUS_SYSTEM)";
+ goto fail;
+ }
+ dbus_connection_set_exit_on_disconnect(connection, FALSE);
+
+ message = dbus_message_new_method_call(DBUS_SSSD_DEST,
+ DBUS_SSSD_PATH_USERS,
+ DBUS_SSSD_IFACE_USERS,
+ DBUS_SSSD_FIND_BY_CERTIFICATE);
+ if (! message) {
+ stage = "dbus_message_new_method_call(" DBUS_SSSD_IFACE_USERS "." DBUS_SSSD_FIND_BY_CERTIFICATE ")";
+ goto fail;
+ }
+ dbus_message_set_auto_start(message, TRUE);
+ if (! dbus_message_append_args(message,
+ DBUS_TYPE_STRING, &(r->user),
+ DBUS_TYPE_INVALID)) {
+ stage = apr_psprintf(r->pool, "dbus_message_append_args(%s)", r->user);
+ goto fail;
+ }
+
+ int timeout = DBUS_SSSD_TIMEOUT;
+ if (cfg->dbus_timeout > 0) {
+ timeout = cfg->dbus_timeout;
+ }
+
+ reply = dbus_connection_send_with_reply_and_block(connection,
+ message, timeout, &error);
+ if (! reply || dbus_error_is_set(&error)) {
+ stage = "dbus_connection_send_with_reply_and_block(" DBUS_SSSD_IFACE_USERS "." DBUS_SSSD_FIND_BY_CERTIFICATE ")";
+ goto fail;
+ }
+ int reply_type = dbus_message_get_type(reply);
+ if (reply_type != DBUS_MESSAGE_TYPE_METHOD_RETURN) {
+ stage = apr_psprintf(r->pool, DBUS_SSSD_IFACE_USERS "." DBUS_SSSD_FIND_BY_CERTIFICATE " returned [%d], not DBUS_MESSAGE_TYPE_METHOD_RETURN", reply_type);
+ goto fail;
+ }
+
+ const char *path;
+ if (! dbus_message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) {
+ stage = DBUS_SSSD_IFACE_USERS "." DBUS_SSSD_FIND_BY_CERTIFICATE ": return arg not DBUS_TYPE_OBJECT_PATH";
+ goto fail;
+ }
+
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server, "lookup_user_by_certificate got object [%s]", path);
+
+ dbus_message_unref(message);
+ message = dbus_message_new_method_call(DBUS_SSSD_DEST,
+ path,
+ DBUS_PROPERTIES,
+ DBUS_PROPERTIES_GET);
+ if (! message) {
+ stage = "dbus_message_new_method_call(" DBUS_PROPERTIES "." DBUS_PROPERTIES_GET ")";
+ goto fail;
+ }
+ dbus_message_set_auto_start(message, TRUE);
+ const char * users_user = DBUS_SSSD_USERS_USER;
+ const char * attrib_name = DBUS_SSSD_USERS_ID;
+ if (! dbus_message_append_args(message,
+ DBUS_TYPE_STRING, &users_user,
+ DBUS_TYPE_STRING, &attrib_name,
+ DBUS_TYPE_INVALID)) {
+ stage = apr_psprintf(r->pool, "dbus_message_append_args(%s, %s)", users_user, attrib_name);
+ goto fail;
+ }
+
+ dbus_message_unref(reply);
+ reply = dbus_connection_send_with_reply_and_block(connection,
+ message, timeout, &error);
+ dbus_message_unref(message);
+ if (!reply || dbus_error_is_set(&error)) {
+ stage = "dbus_connection_send_with_reply_and_block(" DBUS_PROPERTIES "." DBUS_PROPERTIES_GET ")";
+ goto fail;
+ }
+ reply_type = dbus_message_get_type(reply);
+ if (reply_type != DBUS_MESSAGE_TYPE_METHOD_RETURN) {
+ stage = apr_psprintf(r->pool, DBUS_SSSD_IFACE_USERS "." DBUS_SSSD_FIND_BY_CERTIFICATE " returned [%d], not DBUS_MESSAGE_TYPE_METHOD_RETURN", reply_type);
+ goto fail;
+ }
+
+ DBusMessageIter iter, variter;
+ if (! dbus_message_iter_init(reply, &iter)) {
+ stage = DBUS_PROPERTIES "." DBUS_PROPERTIES_GET ": did not return any arguments";
+ goto fail;
+ }
+
+ int type = dbus_message_iter_get_arg_type(&iter);
+ if (type != DBUS_TYPE_VARIANT) {
+ stage = DBUS_PROPERTIES "." DBUS_PROPERTIES_GET ": result is not DBUS_TYPE_VARIANT";
+ goto fail;
+ }
+
+ dbus_message_iter_recurse(&iter, &variter);
+ type = dbus_message_iter_get_arg_type(&variter);
+ if (type == DBUS_TYPE_STRING) {
+ char * r_data;
+ dbus_message_iter_get_basic(&variter, &r_data);
+ r->user = apr_pstrdup(r->pool, r_data);
+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, r->server, "lookup_user_by_certificate found [%s]", r->user);
+ }
+ if (dbus_message_iter_next(&variter) || dbus_message_iter_next(&iter)) {
+ stage = DBUS_PROPERTIES "." DBUS_PROPERTIES_GET ": result is not unique";
+ goto fail;
+ }
+
+ goto pass;
+
+fail:
+ if (dbus_error_is_set(&error)) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "lookup_user_by_certificate failed [%s]: [%s]", stage, error.message);
+ } else if (stage) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "lookup_user_by_certificate failed [%s]", stage);
+ }
+ r->user = NULL;
+
+pass:
+ if (! r->user) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "lookup_user_by_certificate cleared r->user");
+ }
+ if (reply) {
+ dbus_message_unref(reply);
+ }
+ if (connection) {
+ dbus_connection_unref(connection);
+ }
+ dbus_error_free(&error);
+
+ return DECLINED;
+}
+
static DBusMessage * lookup_identity_dbus_message(request_rec * r, DBusConnection * connection, DBusError * error, int timeout, const char * method, apr_hash_t * hash) {
DBusMessage * message = dbus_message_new_method_call(DBUS_SSSD_DEST,
DBUS_SSSD_PATH,
@@ -481,6 +634,9 @@ static lookup_identity_config * create_common_conf(apr_pool_t * pool) {
if (cfg) {
cfg->output = LOOKUP_IDENTITY_OUTPUT_DEFAULT;
cfg->output_gecos = LOOKUP_IDENTITY_OUTPUT_GECOS;
+#ifndef NO_USER_ATTR
+ cfg->lookup_by_certificate = -1;
+#endif
}
return cfg;
}
@@ -539,6 +695,7 @@ static void * merge_dir_conf(apr_pool_t * pool, void * base_void, void * add_voi
cfg->output_user_attr_iter = add->output_user_attr_iter;
}
cfg->dbus_timeout = add->dbus_timeout ? add->dbus_timeout : base->dbus_timeout;
+ cfg->lookup_by_certificate = (add->lookup_by_certificate == -1) ? base->lookup_by_certificate : add->lookup_by_certificate;
#endif
return cfg;
}
@@ -552,13 +709,21 @@ static const command_rec directives[] = {
AP_INIT_TAKE23("LookupUserAttr", set_user_attr, NULL, RSRC_CONF | ACCESS_CONF, "Additional user attribute (attr, note/variable name, separator)"),
AP_INIT_TAKE2("LookupUserAttrIter", set_user_attr_iter, NULL, RSRC_CONF | ACCESS_CONF, "Additional user attributes (attr, note/variable name)"),
AP_INIT_TAKE1("LookupDbusTimeout", ap_set_int_slot, (void*)APR_OFFSETOF(lookup_identity_config, dbus_timeout), RSRC_CONF | ACCESS_CONF, "Timeout for sssd dbus calls (in ms)"),
+ AP_INIT_FLAG("LookupUserByCertificate", ap_set_flag_slot_char, (void*)APR_OFFSETOF(lookup_identity_config, lookup_by_certificate), RSRC_CONF | ACCESS_CONF, "Use org.freedesktop.sssd.infopipe.Users.FindByCertificate to lookup user identity"),
#endif
{ NULL }
};
static void register_hooks(apr_pool_t * pool) {
- static const char * const aszSucc[] = {"mod_headers.c", NULL};
- ap_hook_fixups(lookup_identity_hook, NULL, aszSucc, APR_HOOK_LAST);
+#ifndef NO_USER_ATTR
+ static const char * const access_succ[] = {"mod_authz_core.c", NULL};
+ static const char * const access_pred[] = {"mod_ssl.c", NULL};
+ ap_hook_check_access(lookup_user_by_certificate, access_pred, access_succ, APR_HOOK_MIDDLE,
+ AP_AUTH_INTERNAL_PER_CONF);
+#endif
+
+ static const char * const fixup_succ[] = {"mod_headers.c", NULL};
+ ap_hook_fixups(lookup_identity_hook, NULL, fixup_succ, APR_HOOK_LAST);
APR_REGISTER_OPTIONAL_FN(lookup_identity_hook);
}
diff --git a/mod_lookup_identity.spec b/mod_lookup_identity.spec
index 3681ed7..2862acb 100644
--- a/mod_lookup_identity.spec
+++ b/mod_lookup_identity.spec
@@ -7,7 +7,7 @@
Summary: Apache module to retrieve additional information about the authenticated user
Name: mod_lookup_identity
-Version: 0.9.2
+Version: 0.9.3
Release: 1%{?dist}
License: ASL 2.0
Group: System Environment/Daemons
@@ -63,6 +63,9 @@ install -Dp -m 0644 lookup_identity.confx $RPM_BUILD_ROOT%{_httpd_confdir}/looku
%{_httpd_moddir}/*.so
%changelog
+* Mon Aug 03 2015 Jan Pazdziora <jpazdziora@redhat.com> - 0.9.3-1
+- Added LookupUserByCertificate.
+
* Fri Jun 27 2014 Jan Pazdziora <jpazdziora@redhat.com> - 0.9.2-1
- Fix error handling and reporting.
- Fix module loading/configuration for Apache 2.4.