/* * process an assertion using the hosted verifier. * * TODO: local verification */ VerifyResult processAssertion(request_rec *r, const char *assertion) { VerifyResult res = apr_pcalloc(r->pool, sizeof(struct _VerifyResult)); yajl_val parsed_result = NULL; char *assertionResult = verifyAssertionRemote(r, (char*) assertion); if (assertionResult) { char errorBuffer[256]; parsed_result = yajl_tree_parse(assertionResult, errorBuffer, 255); if (!parsed_result) { res->errorResponse = apr_psprintf(r->pool, jsonErrorResponse, "malformed payload", errorBuffer); return res; } } else { // XXX: verifyAssertionRemote should return specific error message. res->errorResponse = apr_psprintf(r->pool, jsonErrorResponse, "communication error", "can't contact verification server"); return res; } char *parsePath[2]; parsePath[0] = "email"; parsePath[1] = NULL; yajl_val foundEmail = yajl_tree_get(parsed_result, (const char**)parsePath, yajl_t_string); if (!foundEmail) { res->errorResponse = apr_pstrdup(r->pool, assertionResult); return res; } parsePath[0] = "issuer"; parsePath[1] = NULL; yajl_val identityIssuer = yajl_tree_get(parsed_result, (const char**)parsePath, yajl_t_string); if (!identityIssuer) { res->errorResponse = apr_pstrdup(r->pool, assertionResult); return res; } res->verifiedEmail = apr_pstrdup(r->pool, foundEmail->u.string); res->identityIssuer = apr_pstrdup(r->pool, identityIssuer->u.string); return res; }
/* * process an assertion using the hosted verifier. * * TODO: local verification */ VerifyResult processAssertion(request_rec *r, const char *verifier_url, const char *assertion) { VerifyResult res = apr_pcalloc(r->pool, sizeof(struct _VerifyResult)); json_tokener *tok = json_tokener_new(); json_object *jobj = NULL; enum json_tokener_error jerr; char *assertionResult = verifyAssertionRemote(r, verifier_url, (char *) assertion); if (assertionResult) { jobj = json_tokener_parse_ex(tok, assertionResult, strlen(assertionResult)); jerr = json_tokener_get_error(tok); if (json_tokener_success != jerr) { res->errorResponse = apr_psprintf(r->pool, jsonErrorResponse, "malformed payload", json_tokener_error_desc(jerr)); json_tokener_free(tok); return res; } ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, ERRTAG "Assertion (parsed) recieved is : %s", json_object_to_json_string(jobj)); } else { // XXX: verifyAssertionRemote should return specific error message. res->errorResponse = apr_psprintf(r->pool, jsonErrorResponse, "communication error", "can't contact verification server"); return res; } struct json_object_iterator it = json_object_iter_begin(jobj); struct json_object_iterator itEnd = json_object_iter_end(jobj); const char *reason = NULL; const char *status = "unknown"; int success = 0; while (!json_object_iter_equal(&it, &itEnd)) { const char *key = json_object_iter_peek_name(&it); json_object *val = json_object_iter_peek_value(&it); if (strncmp("email", key, 6) == 0) { res->verifiedEmail = apr_pstrdup(r->pool, json_object_get_string(val)); } else if (strncmp("issuer", key, 7) == 0) { res->identityIssuer = apr_pstrdup(r->pool, json_object_get_string(val)); } else if (strncmp("audience", key, 9) == 0) { res->audience = apr_pstrdup(r->pool, json_object_get_string(val)); } else if (strncmp("expires", key, 8) == 0) { apr_time_ansi_put(&res->expires, json_object_get_int64(val) / 1000); } else if (strncmp("reason", key, 7) == 0) { reason = json_object_get_string(val); } else if (strncmp("status", key, 7) == 0) { status = json_object_get_string(val); if (strncmp("okay", status, 5) == 0) { success = 1; } } json_object_iter_next(&it); } json_tokener_free(tok); // XXX: This is bad, doesn't catch multiple missing bits if (!res->verifiedEmail) { res->errorResponse = apr_pstrdup(r->pool, "Missing e-mail in assertion"); } if (!res->identityIssuer) { res->errorResponse = apr_pstrdup(r->pool, "Missing issuer in assertion"); } if (res->audience && strncmp(res->audience, r->server->server_hostname, strlen(r->server->server_hostname)) != 0) { res->errorResponse = apr_psprintf(r->pool, "Audience %s doesn't match %s", res->audience, r->server->server_hostname); } apr_time_t now = apr_time_now(); if (res->expires && res->expires <= now) { char exp_time[APR_RFC822_DATE_LEN]; apr_rfc822_date(exp_time, res->expires); res->errorResponse = apr_psprintf(r->pool, "Assertion expired on %s", exp_time); } if (!success) { if (reason) { res->errorResponse = apr_pstrdup(r->pool, reason); } else { res->errorResponse = apr_psprintf(r->pool, "Assertion failed with status '%s'", status); } } return res; }