- Support for multiple IdP
- IdP discovery service - add a dimple built-in IdP discovery mechanism: send HTTP GET on ProviderID URL. If we get HTTP 200, the IdP is selected git-svn-id: https://modmellon.googlecode.com/svn/trunk@44 a716ebb1-153a-0410-b759-cfb97c6a1b53
This commit is contained in:
parent
6b2fb648ff
commit
4c740a21c1
|
@ -49,6 +49,7 @@
|
|||
#include "apr_md5.h"
|
||||
#include "apr_file_info.h"
|
||||
#include "apr_file_io.h"
|
||||
#include "apr_xml.h"
|
||||
|
||||
#include "ap_config.h"
|
||||
#include "httpd.h"
|
||||
|
@ -116,7 +117,6 @@ typedef enum {
|
|||
am_decoder_feide,
|
||||
} am_decoder_t;
|
||||
|
||||
|
||||
typedef struct am_dir_cfg_rec {
|
||||
/* enable_mellon is used to enable auth_mellon for a location.
|
||||
*/
|
||||
|
@ -144,7 +144,7 @@ typedef struct am_dir_cfg_rec {
|
|||
const char *sp_metadata_file;
|
||||
const char *sp_private_key_file;
|
||||
const char *sp_cert_file;
|
||||
const char *idp_metadata_file;
|
||||
apr_hash_t *idp_metadata_files;
|
||||
const char *idp_public_key_file;
|
||||
const char *idp_ca_file;
|
||||
|
||||
|
@ -157,6 +157,9 @@ typedef struct am_dir_cfg_rec {
|
|||
/* Login path for IdP initiated logins */
|
||||
const char *login_path;
|
||||
|
||||
/* IdP discovery service */
|
||||
const char *discovery_url;
|
||||
|
||||
/* Mutex to prevent us from creating several lasso server objects. */
|
||||
apr_thread_mutex_t *server_mutex;
|
||||
/* Cached lasso server object. */
|
||||
|
@ -242,8 +245,9 @@ int am_check_uid(request_rec *r);
|
|||
int am_handle_metadata(request_rec *r);
|
||||
|
||||
|
||||
int am_httpclient_get(request_rec *r, const char *uri,
|
||||
void **buffer, apr_size_t *size);
|
||||
int am_httpclient_get(request_rec *r, const char *uri,
|
||||
void **buffer, apr_size_t *size,
|
||||
apr_time_t timeout, long *status);
|
||||
int am_httpclient_post(request_rec *r, const char *uri,
|
||||
const void *post_data, apr_size_t post_length,
|
||||
const char *content_type,
|
||||
|
|
|
@ -83,6 +83,103 @@ static const char *am_set_filestring_slot(cmd_parms *cmd,
|
|||
}
|
||||
|
||||
|
||||
/* This function extracts an IdP ProviderID from metadata
|
||||
*
|
||||
* Parameters:
|
||||
* apr_pool_t *p Pool to allocate temporary items from.
|
||||
* server_rec *s The server.
|
||||
* const char *file File containing metadata.
|
||||
* const char **provider The providerID
|
||||
*
|
||||
* Returns:
|
||||
* NULL on success or an error string on failure.
|
||||
*
|
||||
*/
|
||||
static const char *am_get_proovider_id(apr_pool_t *p,
|
||||
server_rec *s,
|
||||
const char *file,
|
||||
const char **provider)
|
||||
{
|
||||
char *data;
|
||||
apr_xml_parser *xp;
|
||||
apr_xml_doc *xd;
|
||||
apr_xml_attr *xa;
|
||||
char error[1024];
|
||||
|
||||
*provider = NULL;
|
||||
|
||||
/*
|
||||
* Get the data
|
||||
*/
|
||||
if ((data = am_getfile(p, s, file)) == NULL)
|
||||
return apr_psprintf(p, "Cannot read file %s", file);
|
||||
|
||||
/*
|
||||
* Parse
|
||||
*/
|
||||
xp = apr_xml_parser_create(p);
|
||||
if (apr_xml_parser_feed(xp, data, strlen(data)) != 0)
|
||||
return apr_psprintf(p, "Cannot parse %s: %s", file,
|
||||
apr_xml_parser_geterror(xp, error, sizeof(error)));
|
||||
|
||||
if (apr_xml_parser_done(xp, &xd) != 0)
|
||||
return apr_psprintf(p, "Parse error %s: %s", file,
|
||||
apr_xml_parser_geterror(xp, error, sizeof(error)));
|
||||
|
||||
/*
|
||||
* Extract /EntityDescriptor@EntityID
|
||||
*/
|
||||
if (strcasecmp(xd->root->name, "EntityDescriptor") != 0)
|
||||
return apr_psprintf(p, "<EntityDescriptor> is not root in %s", file);
|
||||
|
||||
for (xa = xd->root->attr; xa; xa = xa->next)
|
||||
if (strcasecmp(xa->name, "entityID") == 0)
|
||||
break;
|
||||
|
||||
if (xa == NULL)
|
||||
return apr_psprintf(p, "entityID not found in %s", file);
|
||||
|
||||
*provider = xa->value;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This function handles configuration directives which set an
|
||||
* idp related 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.
|
||||
* const char *arg The string argument following this configuration
|
||||
* directive in the configuraion file.
|
||||
*
|
||||
* Returns:
|
||||
* NULL on success or an error string on failure.
|
||||
*/
|
||||
static const char *ap_set_idp_string_slot(cmd_parms *cmd,
|
||||
void *struct_ptr,
|
||||
const char *arg)
|
||||
{
|
||||
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 *error;
|
||||
const char *provider_id;
|
||||
|
||||
if ((error = am_get_proovider_id(cmd->pool, s,
|
||||
arg, &provider_id)) != NULL)
|
||||
return apr_psprintf(cmd->pool, "%s - %s", cmd->cmd->name, error);
|
||||
|
||||
apr_hash_set(cfg->idp_metadata_files,
|
||||
apr_pstrdup(pconf, provider_id),
|
||||
APR_HASH_KEY_STRING,
|
||||
apr_pstrdup(pconf, arg));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* This function handles configuration directives which set a string
|
||||
* slot in the module configuration.
|
||||
*
|
||||
|
@ -431,8 +528,8 @@ const command_rec auth_mellon_commands[] = {
|
|||
),
|
||||
AP_INIT_TAKE1(
|
||||
"MellonIdPMetadataFile",
|
||||
ap_set_string_slot,
|
||||
(void *)APR_OFFSETOF(am_dir_cfg_rec, idp_metadata_file),
|
||||
ap_set_idp_string_slot,
|
||||
NULL,
|
||||
OR_AUTHCFG,
|
||||
"Full path to xml metadata file for the IdP."
|
||||
),
|
||||
|
@ -458,6 +555,13 @@ const command_rec auth_mellon_commands[] = {
|
|||
"The location where to redirect after IdP initiated login."
|
||||
" Default value is \"/\"."
|
||||
),
|
||||
AP_INIT_TAKE1(
|
||||
"MellonDiscoveryURL",
|
||||
ap_set_string_slot,
|
||||
(void *)APR_OFFSETOF(am_dir_cfg_rec, discovery_url),
|
||||
OR_AUTHCFG,
|
||||
"The URL of IdP discovery service. Default is unset."
|
||||
),
|
||||
AP_INIT_TAKE1(
|
||||
"MellonEndpointPath",
|
||||
am_set_endpoint_path,
|
||||
|
@ -506,11 +610,11 @@ 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_file = NULL;
|
||||
dir->idp_metadata_files = apr_hash_make(p);
|
||||
dir->idp_public_key_file = NULL;
|
||||
dir->idp_ca_file = NULL;
|
||||
dir->login_path = default_login_path;
|
||||
|
||||
dir->discovery_url = NULL;
|
||||
|
||||
apr_thread_mutex_create(&dir->server_mutex, APR_THREAD_MUTEX_DEFAULT, p);
|
||||
|
||||
|
@ -602,9 +706,10 @@ 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_file = (add_cfg->idp_metadata_file ?
|
||||
add_cfg->idp_metadata_file :
|
||||
base_cfg->idp_metadata_file);
|
||||
new_cfg->idp_metadata_files = apr_hash_copy(p,
|
||||
(apr_hash_count(add_cfg->idp_metadata_files) > 0) ?
|
||||
add_cfg->idp_metadata_files :
|
||||
base_cfg->idp_metadata_files);
|
||||
|
||||
new_cfg->idp_public_key_file = (add_cfg->idp_public_key_file ?
|
||||
add_cfg->idp_public_key_file :
|
||||
|
@ -618,6 +723,10 @@ void *auth_mellon_dir_merge(apr_pool_t *p, void *base, void *add)
|
|||
add_cfg->login_path :
|
||||
base_cfg->login_path);
|
||||
|
||||
new_cfg->discovery_url = (add_cfg->discovery_url ?
|
||||
add_cfg->discovery_url :
|
||||
base_cfg->discovery_url);
|
||||
|
||||
apr_thread_mutex_create(&new_cfg->server_mutex,
|
||||
APR_THREAD_MUTEX_DEFAULT, p);
|
||||
new_cfg->server = NULL;
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#endif /* HAVE_lasso_server_new_from_buffers */
|
||||
|
||||
|
||||
#ifdef HAVE_lasso_server_new_from_buffers
|
||||
/* This function produces the endpoint URL
|
||||
*
|
||||
* Parameters:
|
||||
|
@ -69,6 +68,7 @@ static char *am_get_endpoint_url(request_rec *r)
|
|||
port, cfg->endpoint_path);
|
||||
}
|
||||
|
||||
#ifdef HAVE_lasso_server_new_from_buffers
|
||||
/* This function generates metadata
|
||||
*
|
||||
* Parameters:
|
||||
|
@ -132,12 +132,213 @@ static char *am_generate_metadata(apr_pool_t *p, request_rec *r)
|
|||
}
|
||||
#endif /* HAVE_lasso_server_new_from_buffers */
|
||||
|
||||
/* This function returns the first configured IdP
|
||||
*
|
||||
* Parameters:
|
||||
* request_rec *r The request we received.
|
||||
*
|
||||
* Returns:
|
||||
* the providerID, or NULL if an error occured
|
||||
*/
|
||||
static const char *am_first_idp(request_rec *r)
|
||||
{
|
||||
am_dir_cfg_rec *cfg = am_get_dir_cfg(r);
|
||||
apr_hash_index_t *index;
|
||||
const char *provider_id;
|
||||
apr_ssize_t len;
|
||||
void *idp_metadata_file;
|
||||
|
||||
index = apr_hash_first(r->pool, cfg->idp_metadata_files);
|
||||
if (index == NULL)
|
||||
return NULL;
|
||||
|
||||
apr_hash_this(index, (const void **)&provider_id,
|
||||
&len, &idp_metadata_file);
|
||||
return provider_id;
|
||||
}
|
||||
|
||||
/* This returns built-in IdP discovery timeout
|
||||
*
|
||||
* Parameters:
|
||||
* request_rec *r The request we received.
|
||||
*
|
||||
* Returns:
|
||||
* the timeout, -1 if not enabled.
|
||||
*/
|
||||
static long am_builtin_discovery_timeout(request_rec *r)
|
||||
{
|
||||
am_dir_cfg_rec *cfg = am_get_dir_cfg(r);
|
||||
const char *builtin = "builtin:get-metadata";
|
||||
const char *timeout = "?timeout=";
|
||||
const char *cp;
|
||||
const long default_timeout = 1L;
|
||||
|
||||
if ((cfg->discovery_url == NULL) ||
|
||||
(strncmp(cfg->discovery_url, builtin, strlen(builtin)) != 0))
|
||||
return -1;
|
||||
|
||||
cp = cfg->discovery_url + strlen(builtin);
|
||||
if (strncmp(cp, timeout, strlen(timeout)) != 0)
|
||||
return default_timeout;
|
||||
|
||||
cp += strlen(timeout);
|
||||
return atoi(cp);
|
||||
}
|
||||
|
||||
/* This function selects an IdP and returns its provider_id
|
||||
*
|
||||
* Parameters:
|
||||
* request_rec *r The request we received.
|
||||
*
|
||||
* Returns:
|
||||
* the provider_id, or NULL if an error occured
|
||||
*/
|
||||
static const char *am_get_idp(request_rec *r)
|
||||
{
|
||||
am_dir_cfg_rec *cfg = am_get_dir_cfg(r);
|
||||
const char *idp_provider_id;
|
||||
const char *idp_metadata_file;
|
||||
apr_hash_index_t *index;
|
||||
long timeout;
|
||||
|
||||
/*
|
||||
* If we have a single IdP, return that one.
|
||||
*/
|
||||
if (apr_hash_count(cfg->idp_metadata_files) == 1)
|
||||
return am_first_idp(r);
|
||||
|
||||
/*
|
||||
* If IdP discovery handed us an IdP, try to use it.
|
||||
*/
|
||||
idp_provider_id = am_extract_query_parameter(r->pool, r->args, "IdP");
|
||||
if (idp_provider_id != NULL) {
|
||||
int rc;
|
||||
|
||||
rc = am_urldecode((char *)idp_provider_id);
|
||||
if (rc != OK) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
|
||||
"Could not urldecode IdP discovery value.");
|
||||
idp_provider_id = NULL;
|
||||
} else {
|
||||
idp_metadata_file = apr_hash_get(cfg->idp_metadata_files,
|
||||
idp_provider_id,
|
||||
APR_HASH_KEY_STRING);
|
||||
if (idp_metadata_file == NULL)
|
||||
idp_provider_id = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we do not know about it, fall back to default.
|
||||
*/
|
||||
if (idp_provider_id == NULL) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
|
||||
"IdP discovery returned unknown or inexistant IdP");
|
||||
idp_provider_id = am_first_idp(r);
|
||||
}
|
||||
|
||||
return idp_provider_id;
|
||||
}
|
||||
|
||||
/*
|
||||
* If built-in IdP discovery is not configured, return default.
|
||||
*/
|
||||
timeout = am_builtin_discovery_timeout(r);
|
||||
if (timeout == -1)
|
||||
return am_first_idp(r);
|
||||
|
||||
/*
|
||||
* Otherwise, proceed with built-in IdP discovery:
|
||||
* send probes for all configures IdP to check availability.
|
||||
* The first to answer is chosen. On error, use default.
|
||||
*/
|
||||
for (index = apr_hash_first(r->pool, cfg->idp_metadata_files);
|
||||
index;
|
||||
index = apr_hash_next(index)) {
|
||||
void *buffer;
|
||||
apr_size_t len;
|
||||
apr_ssize_t slen;
|
||||
long status;
|
||||
|
||||
apr_hash_this(index,
|
||||
(const void **)&idp_provider_id,
|
||||
&slen,
|
||||
(void *)&idp_metadata_file);
|
||||
|
||||
status = 0;
|
||||
if (am_httpclient_get(r, idp_provider_id, &buffer, &len,
|
||||
timeout, &status) != OK)
|
||||
continue;
|
||||
|
||||
if (status != HTTP_OK) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||
"Cannot probe %s: IdP returned HTTP %ld",
|
||||
idp_provider_id, status);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We got some succes */
|
||||
return idp_provider_id;
|
||||
}
|
||||
|
||||
/*
|
||||
* No IdP answered, use default
|
||||
* Perhaps we should redirect to an error page instead.
|
||||
*/
|
||||
return am_first_idp(r);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function loads all IdP metadata in a lasso server
|
||||
*
|
||||
* Parameters:
|
||||
* request_rec *r The request we received.
|
||||
*
|
||||
* Returns:
|
||||
* number of loaded providers
|
||||
*/
|
||||
static int 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_hash_index_t *index;
|
||||
int count = 0;
|
||||
|
||||
if (apr_hash_count(cfg->idp_metadata_files) == 1)
|
||||
idp_public_key_file = cfg->idp_public_key_file;
|
||||
else
|
||||
idp_public_key_file = NULL;
|
||||
|
||||
for (index = apr_hash_first(r->pool, cfg->idp_metadata_files);
|
||||
index;
|
||||
index = apr_hash_next(index)) {
|
||||
const char *idp_provider_id;
|
||||
apr_ssize_t len;
|
||||
int ret;
|
||||
|
||||
apr_hash_this(index, (const void **)&idp_provider_id,
|
||||
&len, (void *)&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 \"%s\" to lasso server object.",
|
||||
idp_provider_id);
|
||||
} else {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static LassoServer *am_get_lasso_server(request_rec *r)
|
||||
{
|
||||
am_dir_cfg_rec *cfg;
|
||||
gint ret;
|
||||
|
||||
cfg = am_get_dir_cfg(r);
|
||||
am_dir_cfg_rec *cfg = am_get_dir_cfg(r);
|
||||
|
||||
apr_thread_mutex_lock(cfg->server_mutex);
|
||||
if(cfg->server == NULL) {
|
||||
|
@ -166,12 +367,7 @@ static LassoServer *am_get_lasso_server(request_rec *r)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
ret = lasso_server_add_provider(cfg->server, LASSO_PROVIDER_ROLE_IDP,
|
||||
cfg->idp_metadata_file,
|
||||
cfg->idp_public_key_file,
|
||||
cfg->idp_ca_file);
|
||||
if(ret != 0) {
|
||||
if (am_server_add_providers(r) == 0) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||
"Error adding IdP to lasso server object. Please"
|
||||
" verify the following configuration directives:"
|
||||
|
@ -1452,59 +1648,58 @@ int am_handle_metadata(request_rec *r)
|
|||
}
|
||||
|
||||
|
||||
/* This function takes a request for an endpoint and passes it on to the
|
||||
* correct handler function.
|
||||
*
|
||||
* Parameters:
|
||||
* request_rec *r The request we are currently handling.
|
||||
*
|
||||
* Returns:
|
||||
* The return value of the endpoint handler function,
|
||||
* or HTTP_NOT_FOUND if we don't have a handler for the requested
|
||||
* endpoint.
|
||||
*/
|
||||
static int am_endpoint_handler(request_rec *r)
|
||||
{
|
||||
const char *endpoint;
|
||||
am_dir_cfg_rec *dir = am_get_dir_cfg(r);
|
||||
|
||||
/* r->uri starts with cfg->endpoint_path, so we can find the endpoint
|
||||
* by extracting the string following chf->endpoint_path.
|
||||
*/
|
||||
endpoint = &r->uri[strlen(dir->endpoint_path)];
|
||||
|
||||
|
||||
if(!strcmp(endpoint, "postResponse")) {
|
||||
return am_handle_post_reply(r);
|
||||
} else if(!strcmp(endpoint, "artifactResponse")) {
|
||||
return am_handle_artifact_reply(r);
|
||||
} else if(!strcmp(endpoint, "metadata")) {
|
||||
return OK;
|
||||
} else if(!strcmp(endpoint, "logout")
|
||||
|| !strcmp(endpoint, "logoutRequest")) {
|
||||
/* logoutRequest is included for backwards-compatibility
|
||||
* with version 0.0.6 and older.
|
||||
*/
|
||||
return am_handle_logout(r);
|
||||
} else {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||
"Endpoint \"%s\" not handled by mod_auth_mellon.",
|
||||
endpoint);
|
||||
|
||||
return HTTP_NOT_FOUND;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int am_auth_new_ticket(request_rec *r)
|
||||
{
|
||||
am_dir_cfg_rec *cfg = am_get_dir_cfg(r);
|
||||
LassoServer *server;
|
||||
LassoLogin *login;
|
||||
LassoSamlp2AuthnRequest *request;
|
||||
gint ret;
|
||||
char *redirect_to;
|
||||
const char *relay_state;
|
||||
|
||||
relay_state = am_reconstruct_url(r);
|
||||
|
||||
/* Check if IdP discovery is in use and no IdP was selected yet */
|
||||
if ((cfg->discovery_url != NULL) &&
|
||||
(am_builtin_discovery_timeout(r) == -1) && /* no built-in discovery */
|
||||
(am_extract_query_parameter(r->pool, r->args, "IdP") == NULL)) {
|
||||
char *discovery_url;
|
||||
char *return_url;
|
||||
char *endpoint = am_get_endpoint_url(r);
|
||||
char *sep;
|
||||
|
||||
/* If discovery URL already has a ? we append a & */
|
||||
sep = (strchr(cfg->discovery_url, '?')) ? "&" : "?";
|
||||
|
||||
return_url = apr_psprintf(r->pool, "%sauth?ReturnTo=%s",
|
||||
endpoint,
|
||||
am_urlencode(r->pool, relay_state));
|
||||
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
|
||||
"return_url = %s", return_url);
|
||||
discovery_url = apr_psprintf(r->pool, "%s%sentityID=%smetadata&"
|
||||
"return=%s&returnIDParam=IdP",
|
||||
cfg->discovery_url, sep,
|
||||
am_urlencode(r->pool, endpoint),
|
||||
am_urlencode(r->pool, return_url));
|
||||
|
||||
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
|
||||
"discovery_url = %s", discovery_url);
|
||||
apr_table_setn(r->headers_out, "Location", discovery_url);
|
||||
return HTTP_SEE_OTHER;
|
||||
}
|
||||
|
||||
/* If IdP discovery is in use and we have an IdP selected,
|
||||
* set the relay_state
|
||||
*/
|
||||
if ((cfg->discovery_url != NULL) &&
|
||||
(am_builtin_discovery_timeout(r) == -1)) { /* no built-in discovery */
|
||||
char *return_url;
|
||||
|
||||
return_url = am_extract_query_parameter(r->pool, r->args, "ReturnTo");
|
||||
if ((return_url != NULL) && am_urldecode((char *)return_url) == 0)
|
||||
relay_state = return_url;
|
||||
}
|
||||
|
||||
/* Add cookie for cookie test. We know that we should have
|
||||
* a valid cookie when we return from the IdP after SP-initiated
|
||||
|
@ -1525,7 +1720,7 @@ static int am_auth_new_ticket(request_rec *r)
|
|||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
ret = lasso_login_init_authn_request(login, NULL,
|
||||
ret = lasso_login_init_authn_request(login, am_get_idp(r),
|
||||
LASSO_HTTP_METHOD_REDIRECT);
|
||||
if(ret != 0) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||
|
@ -1552,7 +1747,7 @@ static int am_auth_new_ticket(request_rec *r)
|
|||
LASSO_SAMLP2_REQUEST_ABSTRACT(request)->Consent
|
||||
= g_strdup(LASSO_SAML2_CONSENT_IMPLICIT);
|
||||
|
||||
LASSO_PROFILE(login)->msg_relayState = g_strdup(am_reconstruct_url(r));
|
||||
LASSO_PROFILE(login)->msg_relayState = g_strdup(relay_state);
|
||||
|
||||
ret = lasso_login_build_authn_request_msg(login);
|
||||
if(ret != 0) {
|
||||
|
@ -1588,6 +1783,53 @@ static int am_auth_new_ticket(request_rec *r)
|
|||
return HTTP_SEE_OTHER;
|
||||
}
|
||||
|
||||
/* This function takes a request for an endpoint and passes it on to the
|
||||
* correct handler function.
|
||||
*
|
||||
* Parameters:
|
||||
* request_rec *r The request we are currently handling.
|
||||
*
|
||||
* Returns:
|
||||
* The return value of the endpoint handler function,
|
||||
* or HTTP_NOT_FOUND if we don't have a handler for the requested
|
||||
* endpoint.
|
||||
*/
|
||||
static int am_endpoint_handler(request_rec *r)
|
||||
{
|
||||
const char *endpoint;
|
||||
am_dir_cfg_rec *dir = am_get_dir_cfg(r);
|
||||
|
||||
/* r->uri starts with cfg->endpoint_path, so we can find the endpoint
|
||||
* by extracting the string following chf->endpoint_path.
|
||||
*/
|
||||
endpoint = &r->uri[strlen(dir->endpoint_path)];
|
||||
|
||||
|
||||
if(!strcmp(endpoint, "postResponse")) {
|
||||
return am_handle_post_reply(r);
|
||||
} else if(!strcmp(endpoint, "artifactResponse")) {
|
||||
return am_handle_artifact_reply(r);
|
||||
} else if(!strcmp(endpoint, "auth")) {
|
||||
return am_auth_new_ticket(r);
|
||||
} else if(!strcmp(endpoint, "metadata")) {
|
||||
return OK;
|
||||
} else if(!strcmp(endpoint, "logout")
|
||||
|| !strcmp(endpoint, "logoutRequest")) {
|
||||
/* logoutRequest is included for backwards-compatibility
|
||||
* with version 0.0.6 and older.
|
||||
*/
|
||||
return am_handle_logout(r);
|
||||
} else {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||
"Endpoint \"%s\" not handled by mod_auth_mellon.",
|
||||
endpoint);
|
||||
|
||||
return HTTP_NOT_FOUND;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int am_auth_mellon_user(request_rec *r)
|
||||
{
|
||||
|
@ -1606,7 +1848,6 @@ int am_auth_mellon_user(request_rec *r)
|
|||
return DECLINED;
|
||||
}
|
||||
|
||||
|
||||
/* Disable all caching within this location. */
|
||||
am_set_nocache(r);
|
||||
|
||||
|
|
|
@ -246,6 +246,7 @@ static CURL *am_httpclient_init_curl(request_rec *r, const char *uri,
|
|||
am_hc_block_header_t *bh,
|
||||
char *curl_error)
|
||||
{
|
||||
am_dir_cfg_rec *cfg = am_get_dir_cfg(r);
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
|
||||
|
@ -311,6 +312,17 @@ static CURL *am_httpclient_init_curl(request_rec *r, const char *uri,
|
|||
goto cleanup_fail;
|
||||
}
|
||||
|
||||
/* If we have a CA configured, try to use it */
|
||||
if (cfg->idp_ca_file != NULL) {
|
||||
res = curl_easy_setopt(curl, CURLOPT_CAINFO, cfg->idp_ca_file);
|
||||
if(res != CURLE_OK) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||
"Failed to set SSL CA info %s:"
|
||||
" [%u] %s", cfg->idp_ca_file, res, curl_error);
|
||||
goto cleanup_fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable fail on http error. */
|
||||
res = curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
|
||||
if(res != CURLE_OK) {
|
||||
|
@ -359,7 +371,7 @@ static CURL *am_httpclient_init_curl(request_rec *r, const char *uri,
|
|||
}
|
||||
|
||||
|
||||
/* This function downloads data from a specified URI.
|
||||
/* This function downloads data from a specified URI, with specified timeout
|
||||
*
|
||||
* Parameters:
|
||||
* request_rec *r The apache request this download is associated
|
||||
|
@ -371,13 +383,16 @@ static CURL *am_httpclient_init_curl(request_rec *r, const char *uri,
|
|||
* apr_size_t *size This is a pointer to where we will store the length
|
||||
* of the downloaded data, not including the
|
||||
* null-terminator we add. This parameter can be NULL.
|
||||
* apr_time_t timeout Timeout in seconds, 0 for no timeout.
|
||||
* long *status Pointer to HTTP status code.
|
||||
*
|
||||
* Returns:
|
||||
* OK on success, or HTTP_INTERNAL_SERVER_ERROR on failure. On failure we
|
||||
* will write a log message describing the error.
|
||||
*/
|
||||
int am_httpclient_get(request_rec *r, const char *uri,
|
||||
void **buffer, apr_size_t *size)
|
||||
void **buffer, apr_size_t *size,
|
||||
apr_time_t timeout, long *status)
|
||||
{
|
||||
am_hc_block_header_t bh;
|
||||
CURL *curl;
|
||||
|
@ -393,15 +408,45 @@ int am_httpclient_get(request_rec *r, const char *uri,
|
|||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
res = curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout);
|
||||
if(res != CURLE_OK) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||
"Failed to download data from the uri \"%s\", "
|
||||
"cannot set timeout to %ld: [%u] %s",
|
||||
uri, (long)timeout, res, curl_error);
|
||||
goto cleanup_fail;
|
||||
}
|
||||
|
||||
res = curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout);
|
||||
if(res != CURLE_OK) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||
"Failed to download data from the uri \"%s\", "
|
||||
"cannot set connect timeout to %ld: [%u] %s",
|
||||
uri, (long)timeout, res, curl_error);
|
||||
goto cleanup_fail;
|
||||
}
|
||||
|
||||
/* Do the download. */
|
||||
res = curl_easy_perform(curl);
|
||||
if(res != CURLE_OK) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||
"Failed to download data from the uri \"%s\": [%u] %s",
|
||||
"Failed to download data from the uri \"%s\", "
|
||||
"transaction aborted: [%u] %s",
|
||||
uri, res, curl_error);
|
||||
goto cleanup_fail;
|
||||
}
|
||||
|
||||
if (status != NULL) {
|
||||
res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, status);
|
||||
if(res != CURLE_OK) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||
"Failed to download data from the uri \"%s\", "
|
||||
"no status report: [%u] %s",
|
||||
uri, res, curl_error);
|
||||
goto cleanup_fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the curl object. */
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ static apr_status_t am_global_kill(void *p)
|
|||
server_rec *s = (server_rec *) p;
|
||||
am_mod_cfg_rec *m = am_get_mod_cfg(s);
|
||||
|
||||
|
||||
if (m->cache) {
|
||||
/* Destroy the shared memory for session data. */
|
||||
apr_shm_destroy(m->cache);
|
||||
|
|
Loading…
Reference in New Issue