summaryrefslogtreecommitdiffstats
path: root/auth_mellon_handler.c
diff options
context:
space:
mode:
authorolavmrk <olavmrk@a716ebb1-153a-0410-b759-cfb97c6a1b53>2010-06-30 14:02:33 +0000
committerolavmrk <olavmrk@a716ebb1-153a-0410-b759-cfb97c6a1b53>2010-06-30 14:02:33 +0000
commit88baa3dee8d9d64d5d166e72997183968f120737 (patch)
tree1c04f6b6ac7d92c5e4940f2441b63a991c403c1a /auth_mellon_handler.c
parent6706ab2946b3712a9b3a259bb6f1d6c356fd4555 (diff)
downloadmod_auth_mellon-88baa3dee8d9d64d5d166e72997183968f120737.tar.gz
mod_auth_mellon-88baa3dee8d9d64d5d166e72997183968f120737.tar.xz
mod_auth_mellon-88baa3dee8d9d64d5d166e72997183968f120737.zip
Validate received response.
git-svn-id: https://modmellon.googlecode.com/svn/trunk@99 a716ebb1-153a-0410-b759-cfb97c6a1b53
Diffstat (limited to 'auth_mellon_handler.c')
-rw-r--r--auth_mellon_handler.c196
1 files changed, 196 insertions, 0 deletions
diff --git a/auth_mellon_handler.c b/auth_mellon_handler.c
index 7acf103..6b0ec72 100644
--- a/auth_mellon_handler.c
+++ b/auth_mellon_handler.c
@@ -1094,6 +1094,170 @@ static apr_time_t am_parse_timestamp(request_rec *r, const char *timestamp)
}
+/* Validate the subject on an Assertion.
+ *
+ * request_rec *r The current request. Used to log
+ * errors.
+ * LassoSaml2Assertion *assertion The assertion we will validate.
+ * const char *url The current URL.
+ *
+ * Returns:
+ * OK on success, HTTP_BAD_REQUEST on failure.
+ */
+static int am_validate_subject(request_rec *r, LassoSaml2Assertion *assertion,
+ const char *url)
+{
+ apr_time_t now;
+ apr_time_t t;
+ LassoSaml2SubjectConfirmation *sc;
+ LassoSaml2SubjectConfirmationData *scd;
+
+ if (assertion->Subject == NULL) {
+ /* No Subject to validate. */
+ return OK;
+ }
+
+ if (assertion->Subject->SubjectConfirmation == NULL) {
+ /* No SubjectConfirmation. */
+ return OK;
+ }
+
+ sc = assertion->Subject->SubjectConfirmation;
+ if (sc->Method == NULL ||
+ strcmp(sc->Method, "urn:oasis:names:tc:SAML:2.0:cm:bearer")) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Invalid Method in SubjectConfirmation.");
+ return HTTP_BAD_REQUEST;
+ }
+
+ scd = sc->SubjectConfirmationData;
+ if (scd == NULL) {
+ /* Nothing to verify. */
+ return OK;
+ }
+
+ now = apr_time_now();
+
+ if (scd->NotBefore) {
+ t = am_parse_timestamp(r, scd->NotBefore);
+ if (t == 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Invalid timestamp in NotBefore in SubjectConfirmationData.");
+ return HTTP_BAD_REQUEST;
+ }
+ if (t - 60000000 > now) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "NotBefore in SubjectConfirmationData was in the future.");
+ return HTTP_BAD_REQUEST;
+ }
+ }
+
+ if (scd->NotOnOrAfter) {
+ t = am_parse_timestamp(r, scd->NotOnOrAfter);
+ if (t == 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Invalid timestamp in NotOnOrAfter in SubjectConfirmationData.");
+ return HTTP_BAD_REQUEST;
+ }
+ if (now >= t + 60000000) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "NotOnOrAfter in SubjectConfirmationData was in the past.");
+ return HTTP_BAD_REQUEST;
+ }
+ }
+
+ if (scd->Recipient) {
+ if (strcmp(scd->Recipient, url)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Wrong Recipient in SubjectConfirmationData. Current URL is: %s",
+ url);
+ return HTTP_BAD_REQUEST;
+ }
+ }
+
+ return OK;
+}
+
+
+/* Validate the conditions on an Assertion.
+ *
+ * Parameters:
+ * request_rec *r The current request. Used to log
+ * errors.
+ * LassoSaml2Assertion *assertion The assertion we will validate.
+ * const char *providerID The providerID of the SP.
+ *
+ * Returns:
+ * OK on success, HTTP_BAD_REQUEST on failure.
+ */
+static int am_validate_conditions(request_rec *r,
+ LassoSaml2Assertion *assertion,
+ const char *providerID)
+{
+ LassoSaml2Conditions *conditions;
+ apr_time_t now;
+ apr_time_t t;
+ GList *i;
+ LassoSaml2AudienceRestriction *ar;
+
+ conditions = assertion->Conditions;
+
+ if (conditions->Condition != NULL) {
+ /* This is a list of LassoSaml2ConditionAbstract - if it
+ * isn't empty, we have an unsupported condition.
+ */
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Unsupported condition in Assertion.");
+ return HTTP_BAD_REQUEST;
+ }
+
+
+ now = apr_time_now();
+
+ if (conditions->NotBefore) {
+ t = am_parse_timestamp(r, conditions->NotBefore);
+ if (t == 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Invalid timestamp in NotBefore in Condition.");
+ return HTTP_BAD_REQUEST;
+ }
+ if (t - 60000000 > now) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "NotBefore in Condition was in the future.");
+ return HTTP_BAD_REQUEST;
+ }
+ }
+
+ if (conditions->NotOnOrAfter) {
+ t = am_parse_timestamp(r, conditions->NotOnOrAfter);
+ if (t == 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Invalid timestamp in NotOnOrAfter in Condition.");
+ return HTTP_BAD_REQUEST;
+ }
+ if (now >= t + 60000000) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "NotOnOrAfter in Condition was in the past.");
+ return HTTP_BAD_REQUEST;
+ }
+ }
+
+ for (i = g_list_first(conditions->AudienceRestriction); i != NULL;
+ i = g_list_next(i)) {
+ ar = i->data;
+ if (ar->Audience == NULL || strcmp(ar->Audience, providerID)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Invalid Audience in Conditions. Should be: %s",
+ providerID);
+ return HTTP_BAD_REQUEST;
+ }
+ }
+
+ return OK;
+}
+
+
+
/* This function sets the session expire timestamp based on NotOnOrAfter
* attribute of a condition element.
*
@@ -1392,6 +1556,8 @@ static int add_attributes(am_cache_entry_t *session, request_rec *r,
static int am_handle_reply_common(request_rec *r, LassoLogin *login,
char *relay_state, char *saml_response)
{
+ char *url;
+ char *chr;
const char *name_id;
LassoSamlp2Response *response;
LassoSaml2Assertion *assertion;
@@ -1401,6 +1567,12 @@ static int am_handle_reply_common(request_rec *r, LassoLogin *login,
int rc;
const char *idp;
+ url = am_reconstruct_url(r);
+ chr = strchr(url, '&');
+ if (chr) {
+ *chr = '\0';
+ }
+
dir_cfg = am_get_dir_cfg(r);
if(LASSO_PROFILE(login)->nameIdentifier == NULL) {
@@ -1416,6 +1588,16 @@ static int am_handle_reply_common(request_rec *r, LassoLogin *login,
response = LASSO_SAMLP2_RESPONSE(LASSO_PROFILE(login)->response);
+ if (response->parent.Destination) {
+ if (strcmp(response->parent.Destination, url)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Invalid Destination on Response. Should be: %s",
+ url);
+ lasso_login_destroy(login);
+ return HTTP_BAD_REQUEST;
+ }
+ }
+
if (g_list_length(response->Assertion) == 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"No Assertion in response.");
@@ -1430,6 +1612,20 @@ static int am_handle_reply_common(request_rec *r, LassoLogin *login,
}
assertion = g_list_first(response->Assertion)->data;
+ rc = am_validate_subject(r, assertion, url);
+ if (rc != OK) {
+ lasso_login_destroy(login);
+ return rc;
+ }
+
+ rc = am_validate_conditions(r, assertion,
+ LASSO_PROVIDER(LASSO_PROFILE(login)->server)->ProviderID);
+
+ if (rc != OK) {
+ lasso_login_destroy(login);
+ return rc;
+ }
+
in_response_to = response->parent.InResponseTo;