process.c revision 155e0b8610c0becd28e9b212e2f1fca182743080
/**
* The contents of this file are subject to the terms of the Common Development and
* Distribution License (the License). You may not use this file except in compliance with the
* License.
*
* You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
* specific language governing permission and limitations under the License.
*
* When distributing Covered Software, include this CDDL Header Notice in each file and include
* the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
* Header, with the fields enclosed by brackets [] replaced by your own identifying
* information: "Portions copyright [year] [name of copyright owner]".
*
* Copyright 2014 - 2015 ForgeRock AS.
*/
#include "platform.h"
#include "am.h"
#include "utility.h"
#include "list.h"
#include "net_client.h"
#define POST_PRESERVE_URI "/dummypost/ampostpreserve"
#define COMPOSITE_ADVICE_KEY "sunamcompositeadvice"
#define AUDIT_ALLOW_USER_MESSAGE "user %s (%s) was allowed access to %s"
#define AUDIT_DENY_USER_MESSAGE "user %s (%s) was denied access to %s"
enum {
AM_SESSION_ATTRIBUTE = 0,
};
enum {
AM_SCOPE_SELF = 0,
};
typedef enum {
} am_state_t;
struct transition {
};
static struct transition state_transitions[] = {
};
#define EXIT_STATE handle_exit_c
#define ENTRY_STATE setup_request_data_c
int i, s = sizeof (state_transitions) / sizeof (state_transitions[0]);
for (i = 0; i < s; i++) {
if (state_transitions[i].src_state == c
&& state_transitions[i].ret_code == r) {
return state_transitions[i].dst_state;
}
}
return EXIT_STATE;
}
int i, compare_status;
return AM_FALSE;
}
return AM_TRUE;
}
/* compare_status = match(request->instance_id, request->overridden_url, m->value);
if (compare_status == AM_SUCCESS) {
return AM_TRUE;
} */
}
return AM_FALSE;
}
static const char *thisfunc = "setup_request_data():";
char *s, *v;
return AM_FAIL;
}
if (r->am_get_request_url_f == NULL) {
return AM_FAIL;
}
return AM_FAIL;
}
/* if the client ip header contains more than one value, use only the first one */
if (v == NULL) {
return AM_FAIL;
}
r->client_ip = v;
//TODO: client_host is not used in a policy call?
if (ISVALID(r->client_host)) {
/* if the client host header contains more than one value, use only the first one */
if (v != NULL) {
s = strstr(v, ":");
/* if client_host contains the port number, remove it */
if (s != NULL) *s = 0;
}
r->client_host = v;
}
int errcode;
if (errcode == 0) {
while (res) {
if (errcode == 0) {
am_free(r->client_host);
break;
}
}
}
}
status = r->am_get_request_url_f(r);
if (status != AM_SUCCESS) {
return AM_FAIL;
}
return AM_FAIL;
}
if (r->normalized_url == NULL) {
return AM_FAIL;
}
/* re-format normalized request url depending on override parameter values */
if (r->conf->override_protocol) {
}
if (r->conf->override_host) {
}
if (r->conf->override_port) {
}
} else {
}
if (r->overridden_url == NULL) {
return AM_FAIL;
}
/* check if this request url (normalized) matches any of
* org.forgerock.agents.config.json.url[] configuration parameter values
*/
r->is_json_url = is_json_request(r);
/* do an early check for a session token in query parameters,
* remove if found (url evaluation later on
* should not contain session token value; aka cookie-less mode,
* applies also to LARES sent as GET parameter)
*/
if (status_token_query == AM_SUCCESS) {
AM_LOG_DEBUG(r->instance_id, "%s found session token '%s' in query parameters", thisfunc, r->token);
} else {
}
"proto: %s\nhost: %s\nport: %d\npath: %s\nquery: %s\ncomplete: %s\noverridden: %s", thisfunc,
r->overridden_url);
return AM_FAIL;
}
return AM_OK;
}
static const char *thisfunc = "validate_url():";
if (s != 0) {
r->status = AM_FORBIDDEN;
return AM_FAIL;
}
return AM_OK;
}
return AM_OK;
}
static const char *thisfunc = "handle_notification():";
/* check if notifications are enabled */
struct notification_worker_data *wd;
/* is override.notification.url set? */
/* int compare_status = r->conf->url_eval_case_ignore == AM_TRUE ?
(stristr((char *) url, r->conf->notif_url) != NULL ? 0 : 1) :
(strstr(url, r->conf->notif_url) != NULL ? 0 : 1); */
if (compare_status != 0) {
AM_LOG_DEBUG(r->instance_id, "%s %s is not an agent notification url %s", thisfunc, url, r->conf->notif_url);
return status;
}
/* read post data (blocking) */
if (r->am_get_post_data_f != NULL) {
r->am_get_post_data_f(r);
}
/* set up notification_worker argument list */
/* original r->post_data inside a worker might not be available already */
}
/* process notification message */
return status;
}
if (r->am_set_custom_response_f != NULL) {
/* OpenAM needs 'OK' message in the body with a successful notification */
}
r->status = AM_NOTIFICATION_DONE;
}
return status;
}
static const char *thisfunc = "validate_fqdn_access():";
int i;
int (*compare)(const char *, const char*);
if (!r->conf->fqdn_check_enable) {
return AM_OK;
}
"%s failed - default fqdn value is not set", thisfunc);
r->status = AM_ACCESS_DENIED;
return AM_FAIL;
}
/* check if its the default fqdn */
return AM_OK;
}
/* if not, look into map values first */
for (i = 0; i < r->conf->fqdn_map_sz; i++) {
r->client_fqdn = m->value;
return AM_OK;
}
}
}
/* still no match? look into map keys now to get the value to redirect to */
for (i = 0; i < r->conf->fqdn_map_sz; i++) {
r->client_fqdn = m->value;
r->status = AM_INVALID_FQDN_ACCESS;
return AM_FAIL;
}
}
}
/* since the client_fqdn is not set, this will redirect to the default fqdn */
r->status = AM_INVALID_FQDN_ACCESS;
return AM_FAIL;
}
if (regex_enable) {
} else {
}
}
static const char *thisfunc = "handle_not_enforced():";
int i;
const char *url = r->normalized_url;
/* post preservation url is not enforced
* (will use com.forgerock.agents.config.pdpuri.prefix value if set)
*/
int erroroffset;
/* all other query parameters, apart from the pdp key, are removed.
* pdp key format: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x
* generated by uuid() utility method
*/
if (x != NULL) {
}
pcre_free(x);
}
r->status = AM_SUCCESS;
return AM_OK;
}
/* check if the request url (normalized) is an application logout url */
if (ISVALID(r->conf->logout_url_regex) && /* check legacy com.forgerock.agents.agent.logout.url.regex option first */
if (!r->conf->not_enforced_fetch_attr) {
r->status = AM_SUCCESS;
return AM_QUIT;
}
return AM_OK;
}
if (r->conf->logout_map_sz > 0) {
for (i = 0; i < r->conf->logout_map_sz; i++) {
if (!r->conf->not_enforced_fetch_attr) {
r->status = AM_SUCCESS;
return AM_QUIT;
}
return AM_OK;
}
}
} else {
}
/* access denied url is not enforced */
if (compare_status == 0) {
r->not_enforced = AM_TRUE;
if (!r->conf->not_enforced_fetch_attr) {
r->status = AM_SUCCESS;
return AM_QUIT;
}
return AM_OK;
}
}
r->not_enforced = AM_FALSE;
/* see if the client ip is in the not enforced client ip list */
if (r->conf->not_enforced_ip_map_sz > 0) {
for (i = 0; i < r->conf->not_enforced_ip_map_sz; i++) {
if (p == NULL) {
const char *l[1] = {m->value};
r->not_enforced = AM_TRUE;
if (!r->conf->not_enforced_fetch_attr) {
r->status = AM_SUCCESS;
return AM_QUIT;
}
return AM_OK;
}
} else {
const char *l[1] = {m->value};
r->not_enforced = AM_TRUE;
if (!r->conf->not_enforced_fetch_attr) {
r->status = AM_SUCCESS;
return AM_QUIT;
}
return AM_OK;
}
}
}
}
}
} else {
AM_LOG_DEBUG(r->instance_id, "%s not enforced client ip validation feature is not enabled", thisfunc);
}
/* check the request url (normalized) is in not enforced url list */
if (r->conf->not_enforced_map_sz > 0) {
int compare_status = 0;
for (i = 0; i < r->conf->not_enforced_map_sz; i++) {
if (p == NULL) {
/* regular [0]=not-enforced-url option */
} else {
/* method-extended [GET,0]=not-enforced-url option */
}
}
}
}
compare_status = compare_status > 0;
if (r->conf->not_enforced_invert) {
"only not enforced list of urls will be enforced", thisfunc);
}
if (compare_status) {
r->not_enforced = AM_TRUE;
if (!r->conf->not_enforced_fetch_attr) {
r->status = AM_SUCCESS;
return AM_QUIT;
}
return AM_OK;
}
} else {
}
/* check the request url (normalized) is in not enforced url list (extended version) */
for (i = 0; i < r->conf->not_enforced_ext_map_sz; i++) {
if (p == NULL) continue;
continue;
}
const char *vlist[1] = {v};
break;
}
}
if (found) {
break;
}
}
}
if (found) {
r->not_enforced = AM_TRUE;
if (!r->conf->not_enforced_fetch_attr) {
r->status = AM_SUCCESS;
return AM_QUIT;
}
return AM_OK;
}
}
} else {
AM_LOG_DEBUG(r->instance_id, "%s extended not enforced url validation feature is not enabled", thisfunc);
}
return AM_OK;
}
static const char *thisfunc = "validate_token():";
char *token_in_post = NULL;
/* read post data (blocking) */
if (r->am_get_post_data_f != NULL) {
r->am_get_post_data_f(r);
status = AM_SUCCESS;
}
struct am_namevalue *e, *t, *session_list;
AM_LIST_FOR_EACH(session_list, e, t) {
token_in_post = strdup(e->v);
r->token_in_post = AM_TRUE;
/* in case its just a LARES post and post was not to dummypost-url,
* change request method to GET
*/
r->method = AM_REQUEST_GET;
r->am_set_method_f(r);
}
status = AM_SUCCESS;
break;
}
}
}
} else if (r->post_data_sz > 0) {
if (r->am_set_post_data_f != NULL) {
r->am_set_post_data_f(r);
}
}
}
if (ISVALID(token_in_post)) {
r->token = token_in_post;
}
}
status = AM_SUCCESS;
}
if (status != AM_SUCCESS) {
/* finally, see if a token is in Cookie-s */
}
}
int decode_status = am_session_decode(r);
}
}
return return_status;
}
static char *create_profile_attribute_request(am_request_t *r) {
int i;
for (i = 0; i < r->conf->profile_attr_map_sz; i++) {
}
return val;
}
/**
* Fetch an attribute value from a cached attribute list (read either from a shared cache
* or directly from a server
*/
static const char *thisfunc = "get_attr_value():";
struct am_namevalue *e, *t;
switch (mask) {
case AM_SESSION_ATTRIBUTE:
{
/* session attribute search */
AM_LIST_FOR_EACH(r->sattr, e, t) {
return e->v;
}
}
}
break;
case AM_RESPONSE_ATTRIBUTE:
{
/* policy response attribute search */
AM_LIST_FOR_EACH(r->response_attributes, e, t) {
return e->v;
}
}
}
break;
case AM_POLICY_ATTRIBUTE:
{
/* policy response decision-attribute search (profile attribute)*/
AM_LIST_FOR_EACH(r->response_decisions, e, t) {
return e->v;
}
}
}
break;
default:
break;
}
return NULL;
}
#define MAX_VALIDATE_POLICY_RETRY 3
static const char *thisfunc = "validate_policy():";
const char *url = r->overridden_url;
/* in case request url is not enforced and attribute fetch is enabled
* but there is no session token - quit processing w/o policy evaluation.
*
*/
r->status = AM_SUCCESS;
return AM_OK;
}
}
/* sso_only mode is interested only in user attributes (ignoring policy result) */
}
if (r->status == AM_NOT_FOUND) {
r->status = AM_INVALID_SESSION;
return AM_OK;
}
if (r->retry >= MAX_VALIDATE_POLICY_RETRY) {
"%s validate policy for '%s' failed (max %d retries exhausted)",
/* status = AM_RETRY_ERROR; */
r->response_attributes = NULL;
r->response_decisions = NULL;
r->policy_advice = NULL;
r->status = AM_ACCESS_DENIED;
return AM_OK;
}
/*
* Look for an entry in a session cache, but only when we are not here because
* of a retry call of a failed cache lookup
**/
struct am_ssl_options info;
const char *service_url = get_valid_openam_url(r);
int max_retry = 3;
/* entry is found, but was not valid, or nothing was found,
* do a policy+session call in either way
**/
max_retry++;
do {
url,
break;
}
if (status == AM_INVALID_SESSION) {
break;
}
if (status == AM_INVALID_AGENT_SESSION) {
break;
}
} while (--max_retry > 0);
if (max_retry == 0) {
}
if (status == AM_SUCCESS) {
/* discard old entries */
}
//TODO: skew? max?
// thisfunc, (retry - max_retry) + 1);
}
} else {
}
if (status == AM_INVALID_AGENT_SESSION) {
"%s agent session is invalid, trying to fetch new configuration/session",
thisfunc);
/* delete all cached data for this agent instance */
/* fetch and update with the new configuration */
am_config_free(&r->conf);
thisfunc);
r->response_attributes = NULL;
r->response_decisions = NULL;
r->policy_advice = NULL;
r->status = entry_status;
r->retry++;
return AM_RETRY;
}
thisfunc);
}
if (status == AM_INVALID_SESSION) {
r->response_attributes = NULL;
r->response_decisions = NULL;
r->policy_advice = NULL;
r->status = AM_INVALID_SESSION;
return AM_OK;
}
r->sattr = session_cache;
}
r->pattr = policy_cache;
}
if (r->conf->client_ip_validate) {
/* check if client ip read from the environment matches token ip found in the session */
r->status = AM_ACCESS_DENIED;
"%s decision: deny, reason: client ip %s does not match sso token ip %s",
return AM_OK;
}
}
AM_LIST_FOR_EACH(r->pattr, e, t) {//TODO: work on loop in 2 threads (split loop in 2; search&match in each thread)
}
do {
int rv;
if (r->conf->policy_cache_valid <= 0) {
/* do not add entries to a global policy-resource cache if policy_cache_valid is set to zero.
* note: this disables policy notifications
*/
break;
}
if (remote) {
/* in case its a fresh policy response, do not do policy-change cache entry validation */
break;
}
am_strerror(rv));
if (rv == AM_SUCCESS) {
break;
}
/* policy change cache entry might be removed or updated by a notification,
*/
r->response_attributes = NULL;
r->response_decisions = NULL;
r->policy_advice = NULL;
r->status = entry_status;
r->retry++;
return AM_RETRY;
} while (0);
/* allow, in case this is a) not-enforced url and attribute fetch is enabled or this is a dummypost_url
* or b) agent is running in sso-only mode (ignoring policy result) */
"%s method: %s, decision: allow, %s",
r->response_attributes = e->response_attributes;
r->response_decisions = e->response_decisions;
r->status = AM_SUCCESS;
/* fetch user parameter value */
} else {
}
}
return AM_OK;
}
if (e->action_decisions == NULL) {
"%s decision: deny, reason: no action decisions found",
thisfunc);
}
/* time_t ts = ae->ttl;
if (difftime(time(NULL), ts) >= 0) {
char tsu[32];
struct tm until;
localtime_r(&ts, &until);
strftime(tsu, sizeof (tsu), AM_CACHE_TIMEFORMAT, &until);
AM_LOG_WARNING(r->instance_id, "%s cache data is obsolete (valid until: %s)",
thisfunc, tsu);
continue;
} */
r->response_decisions = e->response_decisions;
r->status = AM_SUCCESS;
/* fetch user parameter value */
} else {
}
}
return AM_OK;
}
/* deny */
/* set the pointer to the policy advice(s) if any */
r->status = AM_ACCESS_DENIED;
return AM_OK;
}
}
}
}
}
/* in case we haven't found anything in a policy (cached) response - redo validate_policy */
AM_LOG_WARNING(r->instance_id, "%s validate policy did not find a match for '%s' in the cached entries, "
r->response_attributes = NULL;
r->response_decisions = NULL;
r->policy_advice = NULL;
/* technically, this is still a retry */
r->retry++;
return AM_RETRY;
}
}
r->response_attributes = NULL;
r->response_decisions = NULL;
r->policy_advice = NULL;
/* nothing is found in a policy response - respond with a default access denied */
r->status = AM_ACCESS_DENIED;
return AM_OK;
}
/**
* Build and set "Set-Cookie" HTTP header value
*
* @param req pointer to am_request_t
* @param prefix, cookie name prefix, can be NULL
* @param name, cookie name, must not be NULL or empty
* @param value, cookie value, can be NULL
* @param domain, cookie domain value, can be NULL
* @param path, cookie path value, can be NULL
* @param maxage, cookie max-age value in seconds, can be NULL
*/
static const char *thisfunc = "do_cookie_set_generic():";
char time_string[32];
long sec;
int sep_count = 0;
if (r == NULL || r->conf == NULL || r->am_add_header_in_response_f == NULL || !ISVALID(name)) return;
/* cookie-reset list can contain the following values:
* cookiename
* cookiename[=value][;Domain=value]
*
* sep_count with a value of:
* 0 ==> just a cookie name
* 1 ==> name and value
* 2 ==> name, value and domain
* 3 ==> name and domain
*/
sep_count = 3;
}
/* set cookie prefix */
/* set cookie name */
if (sep_count == 3) {
/* cookie-reset with "name and domain" is supplied without '=' after the name - add it here
* as otherwise cookie might not get reset in a browser
*/
*name_sep++ = '\0';
}
} else {
return;
}
} else {
}
}
/* set cookie value */
if (r->conf->cookie_encode_chars) {
}
}
/* no value is provided - we are resetting a cookie */
} else {
/* check if maxage option is provided, if so - use it;
     * if not - try cookie_maxage parameter;
     */
errno = 0;
} else {
#ifdef _WIN32
#endif
"%a, %d-%b-%Y %H:%M:%S GMT",
#ifdef _WIN32
&now
#else
#endif
);
}
}
}
/* set cookie domain value */
}
/* set cookie path value */
}
/* set cookie Secure attribute */
}
/* set cookie HttpOnly attribute */
}
return;
}
}
int type, char cookie_reset_enable) {
int i;
for (i = 0; i < sz; i++) {
am_config_map_t *v = &map[i];
if (cookie_reset_enable) {
} else {
}
}
}
}
static void do_cookie_set(am_request_t *r, char cookie_reset_list_enable, char cookie_reset_enable) {
int i;
if (r->am_add_header_in_response_f == NULL) return;
&& r->conf->cookie_reset_map_sz > 0) {
/* process cookie reset list (agents.config.cookie.reset[0]) */
if (default_domain != NULL) {
/* move past the dot */
}
for (i = 0; i < r->conf->cookie_reset_map_sz; i++) {
}
}
}
}
int i;
for (i = 0; i < sz; i++) {
am_config_map_t *v = &map[i];
if (set_value) {
}
} else {
}
}
}
if (r->am_set_header_in_request_f == NULL) return;
}
}
static void set_user_attributes(am_request_t *r) {
static const char *thisfunc = "set_user_attributes():";
int i;
do {
break;
}
/* CDSSO: update request Cookie header (session token) */
if (r->conf->cdsso_enable) {
char *new_cookie_hdr = NULL;
} else {
r->conf->cookie_name,
r->token);
if (new_cookie_hdr != NULL) {
}
/* if no domain is configured, don't set it,
* browser will default domain to the host value
*/
if (r->conf->cdsso_cookie_domain_map_sz > 0) {
for (i = 0; i < r->conf->cdsso_cookie_domain_map_sz; i++) {
}
} else {
}
}
}
/* if attributes mode is none, we're done */
thisfunc);
break;
}
/* if no attributes in result, we're done */
if (r->conf->profile_attr_map_sz == 0 &&
r->conf->session_attr_map_sz == 0 &&
r->conf->response_attr_map_sz == 0) {
thisfunc);
do_header_set(r, AM_FALSE);
}
break;
}
/* now go do it */
do_header_set(r, AM_FALSE);
}
/* iterate - set attributes */
do_header_set(r, AM_TRUE);
} while (0);
}
static const char *thisfunc = "find_active_login_server():";
int i, j, map_sz = 0;
char local_alloc = AM_FALSE;
char *cdsso_elements = NULL;
const char *url = r->normalized_url;
if (r->conf->cdsso_enable) {
long msec = 0;
char tsc[32];
#ifdef _WIN32
#else
#endif
}
ISVALID(realm) ? "Realm=%s&RequestID=%ld&MajorVersion=1&MinorVersion=0&ProviderID=%s&IssueInstant=%s" :
"%sRequestID=%ld&MajorVersion=1&MinorVersion=0&ProviderID=%s&IssueInstant=%s",
msec,
} else {
}
for (i = 0; i < r->conf->cond_login_url_sz; i++) {
*sep = 0;
} else {
continue;
}
/* try to locate given pattern in a request url */
if (compare_status) {
/* found a match */
/* set up url list */
j = 0;
trim(v, ' ');
j++;
}
}
free(o);
break;
}
}
}
}
/* use url-validator confirmed (index) value */
if (add_goto_value) {
m->value,
if (ISVALID(cdsso_elements)) {
}
} else {
if (ISVALID(cdsso_elements)) {
m->value,
} else {
}
}
}
if (local_alloc) {
}
return login_url;
}
static const char *thisfunc = "handle_exit():";
int valid_idx, i;
return AM_FAIL;
}
if (status == AM_NOTIFICATION_DONE) {
/* fast exit for notification events */
return AM_OK;
}
r->am_add_header_in_response_f != NULL) {
/* do not cache any unauthenticated response */
}
switch (status) {
case AM_SUCCESS:
{
if (r->is_logout_url) {
if (r->am_add_header_in_response_f != NULL &&
r->conf->logout_cookie_reset_map_sz > 0) {
/* process logout cookie reset list (logout.cookie.reset) */
if (default_domain != NULL) {
/* move past the dot */
}
for (i = 0; i < r->conf->logout_cookie_reset_map_sz; i++) {
}
}
do_header_set(r, AM_FALSE);
/* logout.redirect.disable is set - do a background logout and cache cleanup */
const char *oam = get_valid_openam_url(r);
/* find an active OpenAM service URL */
wd->server_id = r->conf->lb_enable && ISVALID(r->session_info.si) ? strdup(r->session_info.si) : NULL;
break;
}
} else {
}
} else {
break;
}
r->status = AM_SUCCESS;
break; /* early exit - we're done with this resource */
}
/* do OpenAM logout redirect with a goto value of logout_redirect_url;
* will land here if no session token is available too.
*/
if (r->conf->openam_logout_map_sz > 0) {
m->value,
} else {
break;
}
break;
}
r->status = AM_REDIRECT;
break;
}
}
/* set user */
r->am_set_user_f(r, r->user);
}
/* set user attributes */
if (audit_status != AM_SUCCESS) {
}
}
}
/* special GET handling after LARES re-post (do redirect only on memory failure) */
am_asprintf(&url, "<html><head><script type=\"text/javascript\">function submitform(sform) {window.location.href = sform.action;}</script></head>"
"<body onload=\"return submitform(document.getform);\">"
"<form name=\"getform\" method=\"GET\" action=\"%s\">"
"</form></body></html>",
r->normalized_url);
thisfunc, r->normalized_url);
} else {
/* r->status = AM_INTERNAL_REDIRECT; */
r->status = AM_REDIRECT;
}
break;
}
if (r->is_dummypost_url) {
if (pdp_status == AM_SUCCESS) {
"entry: %s, url: %s, file: %s, content type: %s",
/* reset pdp sticky-session load-balancer cookie */
if (sess_cookie != NULL) {
*eq++ = 0;
}
} else {
}
}
/* empty post */
r->method = AM_REQUEST_POST;
r->status = AM_PDP_DONE;
r->post_data_url = data;
r->post_data_sz = 0;
/* empty pdp does not need post data set */
} else {
if (r->conf->pdp_js_repost) {
/* IE10+ only */
"function base64toBlob(b64Data, contentType, sliceSize) {contentType = contentType || '';"
"sliceSize = sliceSize || 512;var byteCharacters = atob(b64Data);var byteArrays = [];"
"for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {"
"var slice = byteCharacters.slice(offset, offset + sliceSize);"
"var byteNumbers = new Array(slice.length);"
"for (var i = 0; i < slice.length; i++) {byteNumbers[i] = slice.charCodeAt(i);}"
"var byteArray = new Uint8Array(byteNumbers);byteArrays.push(byteArray);}"
"var blob = new Blob(byteArrays, {type: contentType});"
"return blob;}"
"function sendpost() {var r = new XMLHttpRequest();r.open(\"POST\", \"%s\", true);"
"r.onreadystatechange=function(e) {var x = e.target; "
"if (x.readyState==4 && x.status === 200) {"
"document.body.innerHTML = x.responseText;"
"document.title = !x.response.pageTitle ? x.responseURL : x.response.pageTitle;"
"window.history.pushState({\"html\":x.response,\"pageTitle\":x.response.pageTitle},\"\",\"%s\");}};"
"var b = base64toBlob(\"%s\", \"%s\");r.send(b);"
"}</script></head><body onload=\"sendpost();\">"
"</body><p></p></html>",
post,
r->status = AM_SUCCESS;
} else {
r->method = AM_REQUEST_POST;
r->status = AM_PDP_DONE;
r->post_data_url = data;
r->post_data_sz = post_sz;
if (r->am_set_post_data_f != NULL) {
r->am_set_post_data_f(r);
} else {
thisfunc);
}
}
} else {
}
}
/* delete cache file */
}
/* delete cache entry */
} else {
"%s post data preservation cache entry %s is not available (%s)",
}
} else {
"%s invalid post data preservation key value", thisfunc);
}
if (pdp_status != AM_SUCCESS) {
r->status = AM_NOT_FOUND;
}
break;
}
/* allow access to the resource */
r->status = AM_SUCCESS;
}
break;
case AM_INVALID_SESSION:
case AM_ACCESS_DENIED:
case AM_INVALID_FQDN_ACCESS:
if (status == AM_ACCESS_DENIED &&
if (audit_status != AM_SUCCESS) {
}
}
}
if (r->am_set_custom_response_f != NULL) {
if (status == AM_INVALID_SESSION) {
/* reset LDAP cookies on invalid session */
if (r->conf->cdsso_enable) {
/* reset CDSSO cookie */
}
}
/* reset CDSSO and LDAP cookies on access denied */
}
status != AM_INVALID_FQDN_ACCESS) {
/* post data should already be read in validate_token (with cdsso)
* if not - read it here */
/* read post data (blocking) */
if (!r->conf->cdsso_enable) {
if (r->am_get_post_data_f != NULL) {
r->am_get_post_data_f(r);
} else {
}
}
/* check if we have an access to the post data file directory */
"%s post data preservation module has no access to %s directory",
}
if (pdp_status == AM_SUCCESS) {
/* generate unique post data identifier */
/* create a file name to store post data */
if (r->post_data_sz > 0) {
"%s could not write %d bytes to %s",
}
} else {
}
/* pdp sticky session value, if set, has to be in a correct format: param=value */
/* create a goto value */
key,
);
/* create a redirect url value */
url,
if (pdp_sess_mode_cookie) {
/* create pdp sticky-session load-balancer cookie */
if (sess_cookie != NULL) {
*eq++ = 0;
}
} else {
}
}
}
} else if (status == AM_INVALID_FQDN_ACCESS) {
/* if previous status was invalid fqdn access,
* redirect to a valid fqdn url
*/
/* still nothing - return http403 error
* TODO: redirect to access denied page?
*/
r->status = AM_FORBIDDEN;
break;
}
url,
} else {
/* if previous status was invalid session or if there was a policy
* advice, redirect to the OpenAM login page. If not, redirect to the
* configured access denied url if any
*/
if (r->policy_advice != NULL) {
//TODO: session advice ?
struct am_namevalue *e, *t;
AM_LIST_FOR_EACH(r->policy_advice, e, t) {
"%s<AttributeValuePair><Attribute name=\"%s\"/><Value>%s</Value></AttributeValuePair>",
e->n, e->v);
}
if (composite_advice != NULL) {
}
if (!r->conf->use_redirect_for_advice) {
"<form name=\"postform\" method=\"POST\" action=\"%s\">"
"</form></body></html>",
url,
break;
} else {
url,
}
}
} else {
r->status = AM_FORBIDDEN;
break;
}
}
break;
}
/* set Location header and instruct the container to do a redirect */
r->status = AM_REDIRECT;
}
break;
default:
am_strerror(r->status));
break;
}
return AM_OK;
}
static am_state_func_t const am_request_state[] = {
};
void am_process_request(am_request_t *r) {
for (;;) {
if (EXIT_STATE == cur_state) break;
}
}
/**
* Returns a pointer to the "process state" functions into the callers space and sets the number of pointers.
* This is used to provide access to the process state functions for testing.
*
* @param func_array_ptr address of pointer to be set
* @param array_len_ptr the number of functions returned
*/
}