summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README18
-rw-r--r--auth_mellon.h8
-rw-r--r--auth_mellon_config.c134
-rw-r--r--auth_mellon_handler.c58
-rw-r--r--configure.ac2
5 files changed, 176 insertions, 44 deletions
diff --git a/README b/README
index 359e73e..5e87e07 100644
--- a/README
+++ b/README
@@ -357,11 +357,20 @@ MellonPostCount 100
# metadata for the IdP you are authenticating against. This
# directive is required. Mutliple IdP metadata can be configured
# by using multiple MellonIdPMetadataFile directives.
+ #
+ # If your lasso library is recent enough (higher than 2.3.5),
+ # then MellonIdPMetadataFile will accept an XML file containing
+ # descriptors for multiple IdP. An optional validating chain can
+ # be supplied as a second argument to MellonIdPMetadataFile. If
+ # ommitted, no metadata validation will take place.
+ #
# Default: None set.
MellonIdPMetadataFile /etc/apache2/mellon/idp-metadata.xml
# MellonIdPMetadataGlob is a glob(3) pattern enabled alternative
- # to MellonIdPMetadataFile.
+ # to MellonIdPMetadataFile. Like MellonIdPMetadataFile it will
+ # accept an optional validating chain if lasso is recent enough.
+ #
# Default: None set.
#MellonIdPMetadataGlob /etc/apache2/mellon/*-metadata.xml
@@ -378,6 +387,13 @@ MellonPostCount 100
# Default: None set.
MellonIdPCAFile /etc/apache2/mellon/ca.pem
+ # MellonIdPIgnore lists IdP entityId that should not loaded
+ # from XML federation metadata files. This is usefull if an
+ # IdP cause bugs. Multiple entityId may be specified through
+ # single MellonIdPIgnore, and multiple MellonIdPIgnore are allowed.
+ # Default: None set.
+ #MellonIdPIgnore "https://bug.example.net/saml/idp"
+
# MellonDiscoveryURL is the URL for IdP discovery service.
# This is used for selecting among multiple configured IdP.
# On initiali user authentication, it is redirected to the
diff --git a/auth_mellon.h b/auth_mellon.h
index f6bdede..69c19f1 100644
--- a/auth_mellon.h
+++ b/auth_mellon.h
@@ -151,6 +151,11 @@ typedef struct {
const char *directive;
} am_cond_t;
+typedef struct am_metadata {
+ const char *file; /* Metadata file with one or many IdP */
+ const char *chain; /* Validating chain */
+} am_metadata_t;
+
typedef struct am_dir_cfg_rec {
/* enable_mellon is used to enable auth_mellon for a location.
*/
@@ -183,9 +188,10 @@ typedef struct am_dir_cfg_rec {
const char *sp_metadata_file;
const char *sp_private_key_file;
const char *sp_cert_file;
- apr_array_header_t *idp_metadata_files;
+ apr_array_header_t *idp_metadata;
const char *idp_public_key_file;
const char *idp_ca_file;
+ GList *idp_ignore;
/* metadata autogeneration helper */
apr_hash_t *sp_org_name;
diff --git a/auth_mellon_config.c b/auth_mellon_config.c
index aff13f6..23db996 100644
--- a/auth_mellon_config.c
+++ b/auth_mellon_config.c
@@ -163,37 +163,41 @@ static const char *am_set_filestring_slot(cmd_parms *cmd,
/* This function handles configuration directives which use
- * a glob pattern
+ * a glob pattern, with a second optional argument
*
* Parameters:
* cmd_parms *cmd The command structure for this configuration
* directive.
* void *struct_ptr Pointer to the current directory configuration.
* NULL if we are not in a directory configuration.
- * const char *arg The string argument following this configuration
- * directive in the configuraion file.
+ * const char *glob_pat glob(3) pattern
+ * const char *option Optional argument
*
* Returns:
* NULL on success or an error string on failure.
*/
-static const char *am_set_glob_fn(cmd_parms *cmd,
- void *struct_ptr,
- const char *arg)
+static const char *am_set_glob_fn12(cmd_parms *cmd,
+ void *struct_ptr,
+ const char *glob_pat,
+ const char *option)
{
- const char *(*take_argv)(cmd_parms *, void *, const char *);
+ const char *(*take_argv)(cmd_parms *, void *, const char *, const char *);
apr_array_header_t *files;
const char *error;
const char *directory;
int i;
take_argv = cmd->info;
- directory = am_filepath_dirname(cmd->pool, arg);
- if (arg == NULL || *arg == '\0')
- return apr_psprintf(cmd->pool, "%s takes one argument", cmd->cmd->name);
+ directory = am_filepath_dirname(cmd->pool, glob_pat);
- if (apr_match_glob(arg, &files, cmd->pool) != 0)
- return take_argv(cmd, struct_ptr, arg);
+ if (glob_pat == NULL || *glob_pat == '\0')
+ return apr_psprintf(cmd->pool,
+ "%s takes one or two arguments",
+ cmd->cmd->name);
+
+ if (apr_match_glob(glob_pat, &files, cmd->pool) != 0)
+ return take_argv(cmd, struct_ptr, glob_pat, option);
for (i = 0; i < files->nelts; i++) {
const char *path;
@@ -201,7 +205,7 @@ static const char *am_set_glob_fn(cmd_parms *cmd,
path = apr_pstrcat(cmd->pool, directory, "/",
((const char **)(files->elts))[i], NULL);
- error = take_argv(cmd, struct_ptr, path);
+ error = take_argv(cmd, struct_ptr, path, option);
if (error != NULL)
return error;
@@ -218,25 +222,85 @@ static const char *am_set_glob_fn(cmd_parms *cmd,
* directive.
* void *struct_ptr Pointer to the current directory configuration.
* NULL if we are not in a directory configuration.
- * const char *arg The string argument following this configuration
- * directive in the configuraion file.
+ * const char *metadata Path to metadata file for one or multiple IdP
+ * const char *chain Optional path to validating chain
*
* Returns:
* NULL on success or an error string on failure.
*/
static const char *am_set_idp_string_slot(cmd_parms *cmd,
void *struct_ptr,
- const char *arg)
+ const char *metadata,
+ const char *chain)
+{
+ server_rec *s = cmd->server;
+ apr_pool_t *pconf = s->process->pconf;
+ am_dir_cfg_rec *cfg = (am_dir_cfg_rec *)struct_ptr;
+
+#ifndef HAVE_lasso_server_load_metadata
+ if (chain != NULL)
+ return apr_psprintf(cmd->pool, "Cannot specify validating chain "
+ "for %s since lasso library lacks "
+ "lasso_server_load_metadata()", cmd->cmd->name);
+#endif /* HAVE_lasso_server_load_metadata */
+
+ am_metadata_t *idp_metadata = apr_array_push(cfg->idp_metadata);
+ idp_metadata->file = apr_pstrdup(pconf, metadata);
+ idp_metadata->chain = apr_pstrdup(pconf, chain);
+
+ return NULL;
+}
+
+
+/* This function handles configuration directives which set an
+ * idp federation blacklist slot in the module configuration.
+ *
+ * Parameters:
+ * cmd_parms *cmd The command structure for this configuration
+ * directive.
+ * void *struct_ptr Pointer to the current directory configuration.
+ * NULL if we are not in a directory configuration.
+ * int argc Number of blacklisted providerId.
+ * char *const argv[] List of blacklisted providerId.
+ *
+ * Returns:
+ * NULL on success, or errror string
+ */
+static const char *am_set_idp_ignore_slot(cmd_parms *cmd,
+ void *struct_ptr,
+ int argc,
+ char *const argv[])
{
+#ifdef HAVE_lasso_server_load_metadata
server_rec *s = cmd->server;
apr_pool_t *pconf = s->process->pconf;
am_dir_cfg_rec *cfg = (am_dir_cfg_rec *)struct_ptr;
- const char **filename_slot;
+ GList *new_idp_ignore;
+ int i;
+
+ if (argc < 1)
+ return apr_psprintf(cmd->pool, "%s takes at least one arguments",
+ cmd->cmd->name);
- filename_slot = apr_array_push(cfg->idp_metadata_files);
- *filename_slot = apr_pstrdup(pconf, arg);
+ for (i = 0; i < argc; i++) {
+ new_idp_ignore = apr_palloc(pconf, sizeof(GList));
+ new_idp_ignore->data = apr_pstrdup(pconf, argv[i]);
+
+ /* Prepend it to the list. */
+ new_idp_ignore->next = cfg->idp_ignore;
+ if (cfg->idp_ignore != NULL)
+ cfg->idp_ignore->prev = new_idp_ignore;
+ cfg->idp_ignore = new_idp_ignore;
+ }
return NULL;
+
+#else /* HAVE_lasso_server_load_metadata */
+
+ return apr_psprintf(cmd->pool, "Cannot use %s since lasso library lacks "
+ "lasso_server_load_metadata()", cmd->cmd->name);
+
+#endif /* HAVE_lasso_server_load_metadata */
}
@@ -861,19 +925,21 @@ const command_rec auth_mellon_commands[] = {
OR_AUTHCFG,
"Full path to pem file with certificate for the SP."
),
- AP_INIT_TAKE1(
+ AP_INIT_TAKE12(
"MellonIdPMetadataFile",
am_set_idp_string_slot,
NULL,
OR_AUTHCFG,
- "Full path to xml metadata file for the IdP."
+ "Full path to xml metadata file for IdP, "
+ "with optional validating chain."
),
- AP_INIT_TAKE1(
+ AP_INIT_TAKE12(
"MellonIdPMetadataGlob",
- am_set_glob_fn,
+ am_set_glob_fn12,
am_set_idp_string_slot,
OR_AUTHCFG,
- "Full path to xml metadata files for the IdP, with glob(3) patterns."
+ "Full path to xml metadata files for IdP, with glob(3) patterns. "
+ "An optional validating chain can be supplied."
),
AP_INIT_TAKE1(
"MellonIdPPublicKeyFile",
@@ -889,6 +955,13 @@ const command_rec auth_mellon_commands[] = {
OR_AUTHCFG,
"Full path to pem file with CA chain for the IdP."
),
+ AP_INIT_TAKE_ARGV(
+ "MellonIdPIgnore",
+ am_set_idp_ignore_slot,
+ NULL,
+ OR_AUTHCFG,
+ "List of IdP entityId to ignore."
+ ),
AP_INIT_TAKE12(
"MellonOrganizationName",
am_set_langstring_slot,
@@ -1017,9 +1090,10 @@ void *auth_mellon_dir_config(apr_pool_t *p, char *d)
dir->sp_metadata_file = NULL;
dir->sp_private_key_file = NULL;
dir->sp_cert_file = NULL;
- dir->idp_metadata_files = apr_array_make(p, 0, sizeof(const char *));
+ dir->idp_metadata = apr_array_make(p, 0, sizeof(am_metadata_t));
dir->idp_public_key_file = NULL;
dir->idp_ca_file = NULL;
+ dir->idp_ignore = NULL;
dir->login_path = default_login_path;
dir->discovery_url = NULL;
dir->probe_discovery_timeout = -1; /* -1 means no probe discovery */
@@ -1141,9 +1215,9 @@ void *auth_mellon_dir_merge(apr_pool_t *p, void *base, void *add)
add_cfg->sp_cert_file :
base_cfg->sp_cert_file);
- new_cfg->idp_metadata_files = (add_cfg->idp_metadata_files->nelts > 0 ?
- add_cfg->idp_metadata_files :
- base_cfg->idp_metadata_files);
+ new_cfg->idp_metadata = (add_cfg->idp_metadata->nelts ?
+ add_cfg->idp_metadata :
+ base_cfg->idp_metadata);
new_cfg->idp_public_key_file = (add_cfg->idp_public_key_file ?
add_cfg->idp_public_key_file :
@@ -1153,6 +1227,10 @@ void *auth_mellon_dir_merge(apr_pool_t *p, void *base, void *add)
add_cfg->idp_ca_file :
base_cfg->idp_ca_file);
+ new_cfg->idp_ignore = add_cfg->idp_ignore != NULL ?
+ add_cfg->idp_ignore :
+ base_cfg->idp_ignore;
+
new_cfg->sp_org_name = apr_hash_copy(p,
(apr_hash_count(add_cfg->sp_org_name) > 0) ?
add_cfg->sp_org_name :
diff --git a/auth_mellon_handler.c b/auth_mellon_handler.c
index b4401cf..5694f88 100644
--- a/auth_mellon_handler.c
+++ b/auth_mellon_handler.c
@@ -214,34 +214,64 @@ static char *am_generate_metadata(apr_pool_t *p, request_rec *r)
static guint am_server_add_providers(request_rec *r)
{
am_dir_cfg_rec *cfg = am_get_dir_cfg(r);
- const char *idp_metadata_file;
const char *idp_public_key_file;
apr_size_t index;
- if (cfg->idp_metadata_files->nelts == 1)
+ if (cfg->idp_metadata->nelts == 1)
idp_public_key_file = cfg->idp_public_key_file;
else
idp_public_key_file = NULL;
- for (index = 0; index < cfg->idp_metadata_files->nelts; index++) {
- int ret;
- idp_metadata_file = APR_ARRAY_IDX(cfg->idp_metadata_files, index,
- const char *);
+ for (index = 0; index < cfg->idp_metadata->nelts; index++) {
+ const am_metadata_t *idp_metadata;
+ int error;
+#ifdef HAVE_lasso_server_load_metadata
+ GList *loaded_idp = NULL;
+#endif /* HAVE_lasso_server_load_metadata */
+
+ idp_metadata = &APR_ARRAY_IDX(cfg->idp_metadata, index, const am_metadata_t);
+
+#ifdef HAVE_lasso_server_load_metadata
+ error = lasso_server_load_metadata(cfg->server,
+ LASSO_PROVIDER_ROLE_IDP,
+ idp_metadata->file,
+ idp_metadata->chain,
+ cfg->idp_ignore,
+ &loaded_idp,
+ LASSO_SERVER_LOAD_METADATA_FLAG_DEFAULT);
+ if (error == 0) {
+ GList *idx;
+
+ for (idx = loaded_idp; idx != NULL; idx = idx->next) {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ "loaded IdP \"%s\" from \"%s\".",
+ (char *)idx->data, idp_metadata->file);
+ }
+ }
- ret = lasso_server_add_provider(cfg->server, LASSO_PROVIDER_ROLE_IDP,
- idp_metadata_file,
- idp_public_key_file,
- cfg->idp_ca_file);
- if (ret != 0) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "Error adding IdP from \"%s\" to lasso server object.",
- idp_metadata_file);
+ if (loaded_idp != NULL)
+ g_free(loaded_idp);
+
+#else /* HAVE_lasso_server_load_metadata */
+ error = lasso_server_add_provider(cfg->server,
+ LASSO_PROVIDER_ROLE_IDP,
+ idp_metadata->file,
+ idp_public_key_file,
+ cfg->idp_ca_file);
+#endif /* HAVE_lasso_server_load_metadata */
+
+ if (error != 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Error adding metadata \"%s\" to "
+ "lasso server objects: %s.",
+ idp_metadata->file, lasso_strerror(error));
}
}
return g_hash_table_size(cfg->server->providers);
}
+
static LassoServer *am_get_lasso_server(request_rec *r)
{
am_dir_cfg_rec *cfg = am_get_dir_cfg(r);
diff --git a/configure.ac b/configure.ac
index d37b811..394688d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -46,6 +46,8 @@ PKG_CHECK_MODULES(LASSO, lasso)
saved_LIBS=$LIBS; LIBS="$LIBS $LASSO_LIBS";
AC_CHECK_LIB(lasso, lasso_server_new_from_buffers,
LASSO_CFLAGS="$LASSO_CFLAGS -DHAVE_lasso_server_new_from_buffers")
+AC_CHECK_LIB(lasso, lasso_server_load_metadata,
+ LASSO_CFLAGS="$LASSO_CFLAGS -DHAVE_lasso_server_load_metadata")
LIBS=$saved_LIBS;
AC_SUBST(LASSO_CFLAGS)
AC_SUBST(LASSO_LIBS)