static int do_redirect(request_rec *request, am_status_t status, const am_map_t advice_map, const char *original_url) { boolean_t allocated; char *redirect_url; int apache_status; redirect_url = am_web_get_redirect_url(status, advice_map, original_url, &allocated); if (redirect_url != NULL) { apache_status = HTTP_MOVED_TEMPORARILY; am_web_log_debug("do_redirect() policy status = %s, redirection URL " "is %s", am_status_to_string(status), redirect_url); ap_custom_response(request, apache_status, redirect_url); if (B_TRUE==allocated) { am_web_free_memory(redirect_url); } } else { apache_status = HTTP_FORBIDDEN; am_web_log_debug("do_redirect() policy status = %s, returning %d", am_status_to_string(status), apache_status); } return apache_status; }
void Log::shutdown() throw() { am_status_t status = AM_SUCCESS; if (initialized) { log(Log::ALL_MODULES, Log::LOG_MAX_DEBUG, "Log::shutdown(): Log service being terminated."); // flush any outstanding remote log buffers. status = Log::rmtflush(); if (status != AM_SUCCESS) { log(Log::ALL_MODULES, Log::LOG_ERROR, "Log::shutdown(): Error flushing remote log: %s.", am_status_to_string(status)); } { ScopeLock mylock(*lockPtr); pSetLogFile(""); if (moduleList) { initialized = false; delete moduleList; moduleList = NULL; } } ScopeLock rmtLock(*rmtLockPtr); if (rmtLogSvc) { remoteInitialized = false; delete rmtLogSvc; rmtLogSvc = NULL; } } }
/* * Method to check if notification is enabled in the SDK. * * Returns: * If notification is enabled returns non-zero, otherwise zero. */ extern "C" boolean_t am_policy_is_notification_enabled(am_policy_t policy_handle) { try { return (enginePtr->isNotificationEnabled(policy_handle)==true)?B_TRUE:B_FALSE; } catch(InternalException &ie) { Log::log(enginePtr->getModuleID(), Log::LOG_ERROR, "am_policy_is_notification_enabled: InternalException in %s " "with error message:%s and code:%s", ie.getThrowingMethod(), ie.getMessage(), am_status_to_string(ie.getStatusCode())); } catch(NSPRException &ne) { Log::log(enginePtr->getModuleID(), Log::LOG_ERROR, "am_policy_is_notification_enabled: NSPRException inside %s " "when calling NSPR method %s. Error code:%s", ne.getThrowingMethod(), ne.getNsprMethod(), PR_ErrorToString(ne.getErrorCode(), PR_LANGUAGE_I_DEFAULT)); } catch(std::bad_alloc &ex) { Log::log(enginePtr->getModuleID(), Log::LOG_ERROR, "am_policy_is_notification_enabled: Memory allocation problem."); } catch(std::exception &ex) { // Log:ERROR Log::log(enginePtr->getModuleID(), Log::LOG_ERROR, ex); } catch(...) { // Mother of all catches. Log::log(enginePtr->getModuleID(), Log::LOG_ERROR, "am_policy_is_notification_enabled: Unknown exception occured."); return B_FALSE; } return B_FALSE; }
static int do_deny(Session *sn, Request *rq, am_status_t status) { int retVal = REQ_ABORTED; /* Set the return code 403 Forbidden */ protocol_status(sn, rq, PROTOCOL_FORBIDDEN, NULL); am_web_log_info("do_redirect() Status code= %s.", am_status_to_string(status)); return retVal; }
/** * This fnunction checks whether the incoming naming response has the * REST service url in it. If it has then the agent determines that it is * interacting with the OpenSSO server. If not present then the agent is interacting * with the old AM server */ am_status_t AgentProfileService::isRESTServiceAvailable() { am_status_t status = AM_SUCCESS; Http::CookieList cookieList; NamingInfo namingInfo; const char *thisFunc = "isRESTServiceAvailable()"; try { status = mNamingService.doNamingRequest(mNamingServiceInfo, cookieList, namingInfo); if (status == AM_SUCCESS) { std::string authURL = namingInfo.extraProperties.get(authURLAttribute, "", true); parseURL(authURL, false, mAuthURL); std::string restURL = namingInfo.extraProperties.get(restURLAttribute, "", true); if(!restURL.empty()) { Log::log(logModule, Log::LOG_DEBUG, ": Using rest service info from naming response %s:", restURL.c_str()); parseURL(restURL, true, mRestURL); } else { status = AM_REST_SERVICE_NOT_AVAILABLE; Log::log(logModule, Log::LOG_DEBUG, "%s: No REST service available. " "So local agent configuration file gets used.", thisFunc); } } else { Log::log(logModule, Log::LOG_ERROR, "%s: An error occured while doing naming request. %s", thisFunc, am_status_to_string(status)); } } catch(...) { Log::log(logModule, Log::LOG_ERROR, "%s: An error occured while doing naming request. %s", thisFunc, am_status_to_string(status)); } return status; }
/** * This function is invoked to initialize the agent * during the first request. */ void init_at_request() { am_status_t status; status = am_agent_init(&agentInitialized); if (status != AM_SUCCESS) { log_error(LOG_FAILURE, "URL Access Agent: ", NULL, NULL, "Initialization of the agent failed: " "status = %s (%d)", am_status_to_string(status), status); } }
// this should not throw exception since it is called often in a // catch block to log an error resulting from an exception. void Log::log(ModuleId module, Level level, const InternalException &ex) throw() { if(!isLevelEnabled(module, level)) return; am_status_t statusCode = ex.getStatusCode(); const char *status_desc = am_status_to_string(statusCode); // Print the exception information log(module, level, "Exception InternalException thrown " "with message: \"%s\" and status message: %s", ex.getMessage(), status_desc); return; }
Log::Level Log::setModuleLevel(ModuleId module, Level level) throw() { Log::Level oldLevel = Log::LOG_NONE; am_status_t status = AM_SUCCESS; if (!initialized && (status = initialize()) != AM_SUCCESS) { Log::log(Log::ALL_MODULES, Log::LOG_ERROR, "Log::setModuleLevel(): Cannot set module level. " "Log initialization failed with %s", am_status_to_string(status)); oldLevel= Log::LOG_NONE; } else { ScopeLock myLock(*lockPtr); oldLevel = pSetModuleLevel(module, level); } return oldLevel; }
am_status_t Log::rmtflush() throw() { am_status_t status = AM_FAILURE; if (rmtLogSvc != NULL && remoteInitialized ) { status = rmtLogSvc->flushBuffer(); if(status != AM_SUCCESS) { log(ALL_MODULES, LOG_ERROR, "Log::rmtflush(): Error flushing buffer to remote server: %s", am_status_to_string(status)); } } else { log(ALL_MODULES, LOG_ERROR, "Log::rmtflush(): Error flushing buffer to remote server: " "remote log service not initialized."); } return status; }
/* * This function does the actual job of retrieving the agent configuration data * if the repository type is local or issuing the REST call to Opensso server * to get the latest agent configuration data if the repository type is * centralized */ am_status_t AgentProfileService::fetchAndUpdateAgentConfigCacheInternal (AgentConfigurationRefCntPtr& agentConfig) { //check for REMOTE/LOCAL, then fetch attributes //set latestConfigkey to the current time and then update AgentConfigCache //with a new entry that has the latestConfigKey as the key and agentConfig //as the value. const char *thisfunc = "fetchAndUpdateAgentConfigCache()"; am_properties_t properties; am_status_t status; // am_status_t authStatus = AM_FAILURE; std::string userName(boot_info.agent_name); std::string passwd(boot_info.agent_passwd); std::string sharedAgentProfileName(boot_info.shared_agent_profile_name); std::string realmName(boot_info.realm_name); const char* agentConfigFile = boot_info.agent_config_file; // const Properties& propPtr = // *reinterpret_cast<Properties *>(boot_info.properties); if (getRepoType() == LOCAL_CONFIG) { am_properties_create(&properties); status = am_properties_load(properties,agentConfigFile); if (status != AM_SUCCESS ) { am_web_log_error("%s: Identity REST Services Endpoint URL not" " available. Also failed to load local agent configuration file" ", %s. Please check for any configuration errors during " "installation.", thisfunc, agentConfigFile); } } else { am_properties_t tmpPropPtr; status = am_properties_create(&tmpPropPtr); if (status == AM_SUCCESS) { status = getAgentAttributes(agentSSOToken, sharedAgentProfileName, realmName, tmpPropPtr); if (status == AM_SUCCESS) { const char* repoType = NULL; boolean_t repoKeyPresent; repoKeyPresent = am_properties_is_set(tmpPropPtr, AM_WEB_AGENT_REPOSITORY_LOCATION_PROPERTY); if( repoKeyPresent == B_TRUE) { status = am_properties_get(tmpPropPtr, AM_WEB_AGENT_REPOSITORY_LOCATION_PROPERTY, &repoType ); if (status == AM_SUCCESS) { if (strcasecmp(repoType, AGENT_PROPERTIES_LOCAL) == 0) { //LOCAL repo type am_web_log_info("%s:Repository type property is " "set to %s in agent profile, " "%s. ", thisfunc, repoType, userName.c_str()); am_properties_create(&properties); status = am_properties_load(properties, agentConfigFile); if (status != AM_SUCCESS) { am_web_log_error("%s: Repository type property " "is set to %s in agent " "profile, %s. But Agent " "failed to load local %s " "file", thisfunc, repoType, userName.c_str(), agentConfigFile); } } else if (strcasecmp(repoType, AGENT_PROPERTIES_CENTRALIZED) == 0) { // REMOTE repo type am_properties_create(&properties); am_properties_copy(tmpPropPtr, &properties); } else { //treat as misconfiguration am_web_log_error("%s: Repository type property is " "present in agent profile, %s, " "but invalid value is present, %s." "Sepcify valid value (local|centralized) " "to make agent function properly.", thisfunc, userName.c_str(), repoType); status = AM_REPOSITORY_TYPE_INVALID; } } else { //treat as misconfiguration am_web_log_error("%s:Repository type property is " "present in agent profile, %s, " "but invalid value is present, %s." "Sepcify valid value (local|centralized) " "to make agent function properly.", thisfunc, userName.c_str(), repoType); status = AM_REPOSITORY_TYPE_INVALID; } } else { // repository property doesn't exist am_web_log_warning("%s:Repository type property is not " "present in agent profile, %s. " "So Agent tries to load " "from local %s file", thisfunc, userName.c_str(), agentConfigFile); am_properties_create(&properties); status = am_properties_load(properties,agentConfigFile); if (status != AM_SUCCESS) { am_web_log_error("%s: Agent failed to load local" "file, %s", thisfunc, agentConfigFile); } } } else { am_web_log_error("%s:There is an error while fetching" " attributes by user %s, using REST service. " "Status: %s ", thisfunc, userName.c_str(), am_status_to_string(status)); status = AM_REST_ATTRS_SERVICE_FAILURE; } } am_properties_destroy(tmpPropPtr); } //Insert the AMAgentConfiguration object in the hast table with the current //time stamp as its key. if (status == AM_SUCCESS ) { // AgentConfigurationRefCntPtr agentConfig; agentConfig = new AgentConfiguration(properties); status = load_bootinfo_to_properties(&boot_info, agentConfig->getProperties()); agentConfigCache.populateAgentConfigCacheTable(agentConfig); } return status; }
am_status_t BaseService::sendRequest(Connection& conn, const BodyChunk& headerPrefix, const std::string& uri, const std::string& uriParameters, const Http::HeaderList& headerList, const Http::CookieList& cookieList, const BodyChunk& contentLine, const BodyChunk& headerSuffix, const BodyChunkList& bodyChunkList) const { am_status_t status; std::string requestLine(headerPrefix.data); requestLine.append(uri); requestLine.append(uriParameters); requestLine.append(HTTP_VERSION_SUFFIX); Log::log(logModule, Log::LOG_MAX_DEBUG, "BaseService::sendRequest " "Request line: %s", requestLine.c_str()); status = sendChunk(conn, BodyChunk(requestLine)); if (AM_SUCCESS == status) { std::string cookieLine; // XXX - Need to send cookies here. size_t hListSize = headerList.size(); Http::Cookie theCookie; for(size_t idx = 0; idx < hListSize; idx++) { theCookie = headerList[idx]; cookieLine.append(theCookie.name); cookieLine.append(": "); cookieLine.append(theCookie.value); cookieLine.append("\r\n"); } size_t listSize = cookieList.size(); if(listSize > 0) { cookieLine.append("Cookie: "); for (size_t iii=0; iii < listSize; iii++) { theCookie = cookieList[iii]; cookieLine.append(theCookie.name); cookieLine.append("="); cookieLine.append(theCookie.value); if (iii == listSize-1) { cookieLine.append("\r\n"); } else { cookieLine.append(";"); } } } Log::log(logModule, Log::LOG_DEBUG, "BaseService::sendRequest " "Cookie and Headers =%s ", cookieLine.c_str()); if (cookieLine.size() > 0) { status = sendChunk(conn, BodyChunk(cookieLine)); } Log::log(logModule, Log::LOG_DEBUG, "BaseService::sendRequest " "Content-Length =%s.", contentLine.data.c_str()); if (AM_SUCCESS == status) { status = sendChunk(conn, contentLine); } Log::log(logModule, Log::LOG_DEBUG, "BaseService::sendRequest " "Header Suffix =%s ", headerSuffix.data.c_str()); if (AM_SUCCESS == status) { status = sendChunk(conn, headerSuffix); if (AM_SUCCESS == status) { Log::log(logModule, Log::LOG_MAX_DEBUG, "BaseService::sendRequest(): " "Total chunks: %ld.", bodyChunkList.size()); std::size_t i = 0; for (i = 0; i < bodyChunkList.size(); ++i) { status = sendChunk(conn, bodyChunkList[i]); if (AM_SUCCESS != status) { Log::log(logModule, Log::LOG_ERROR, "BaseService::sendRequest " "Sending chunk %ld failed with error: %s", i, am_status_to_string(status)); break; } } Log::log(logModule, Log::LOG_MAX_DEBUG, "BaseService::sendRequest(): " "Sent %ld chunks.", i); } } } return status; }
am_status_t Http::Response::readAndParse(Log::ModuleId logModule, Connection& conn) { am_status_t status = AM_FAILURE; bool contentLengthHdrSeen = false; int htsts = conn.httpStatusCode(); Log::log(logModule, Log::LOG_DEBUG, "HTTP Status = %d", htsts); if (htsts != -1) { status = AM_SUCCESS; httpStatus = static_cast<Status> (htsts); } if (htsts != 200) { status = AM_HTTP_ERROR; } if (status == AM_SUCCESS) { int contentLength = conn.httpContentLength(); if (contentLength != -1) { contentLengthHdrSeen = true; } std::string search("set-cookie"); Connection::ConnHeaderMap::iterator it = conn.begin(); Connection::ConnHeaderMap::iterator itEnd = conn.end(); for (; it != itEnd; ++it) { std::string k = (*it).first; std::string v = (*it).second; std::string::iterator fpos = std::search(k.begin(), k.end(), search.begin(), search.end(), http_to_lower); if (fpos != k.end()) { cookieList.push_back(Cookie(v.c_str())); //Log::log(logModule, Log::LOG_MAX_DEBUG, "Set-Cookie: %s", v.c_str()); } else { extraHdrs.set(k, v); //Log::log(logModule, Log::LOG_MAX_DEBUG, "Header: %s: %s", k.c_str(), v.c_str()); } } if (contentLengthHdrSeen == true) { Log::log(logModule, Log::LOG_DEBUG, "Http::Response::readAndParse(): " "Reading body content of length: %d", contentLength); const char *body = conn.getBody(); int body_len = conn.httpContentLength(); if (!body || body_len <= 0) { status = AM_END_OF_FILE; bodyPtr = NULL; bodyLen = 0; } else { bodyPtr = new (std::nothrow) char[body_len + 1]; if (bodyPtr) { bodyLen = body_len; memcpy(bodyPtr, body, body_len); bodyPtr[bodyLen] = 0; } else { bodyPtr = NULL; bodyLen = 0; status = AM_NO_MEMORY; } } } else { Log::log(logModule, Log::LOG_DEBUG, "Http::Response::readAndParse(): " "No content length in response."); } } Log::log(logModule, Log::LOG_MAX_DEBUG, "Http::Response::readAndParse(): " "Completed processing the response with status: %s", am_status_to_string(status)); return status; }
/* * Function Name: validate_session_policy * This is the NSAPI directive funtion which gets called for each request * It does session validation and policy check for each request. * Input: As defined by a SAF * Output: As defined by a SAF */ NSAPI_PUBLIC int validate_session_policy(pblock *param, Session *sn, Request *rq) { const char *thisfunc = "validate_session_policy()"; char *dpro_cookie = NULL; am_status_t status = AM_SUCCESS; int requestResult = REQ_ABORTED; int notifResult = REQ_ABORTED; const char *ruser = NULL; am_map_t env_parameter_map = NULL; am_policy_result_t result = AM_POLICY_RESULT_INITIALIZER; void *args[] = { (void *)rq }; char *request_url = NULL; char *orig_req = NULL ; char *response = NULL; char *clf_req = NULL; char *server_protocol = NULL; void *agent_config = NULL; char *logout_url = NULL; char *uri_hdr = NULL; char *pathInfo_hdr = NULL; char *method_hdr = NULL; char *method = NULL; char *virtHost_hdr = NULL; char *query_hdr = NULL; char *query = NULL; char *protocol = "HTTP"; const char *clientIP_hdr_name = NULL; char *clientIP_hdr = NULL; char *clientIP = NULL; const char *clientHostname_hdr_name = NULL; char *clientHostname_hdr = NULL; char *clientHostname = NULL; am_status_t cdStatus = AM_FAILURE; // check if agent is initialized. // if not initialized, then call agent init function // This needs to be synchronized as only one time agent // initialization needs to be done. if(agentInitialized != B_TRUE){ //Start critical section crit_enter(initLock); if(agentInitialized != B_TRUE){ am_web_log_debug("%s: Will call init.", thisfunc); init_at_request(); if(agentInitialized != B_TRUE){ am_web_log_error("%s: Agent is still not intialized", thisfunc); //deny the access requestResult = do_deny(sn, rq, status); status = AM_FAILURE; } else { am_web_log_debug("%s: Agent intialized"); } } //end critical section crit_exit(initLock); } if (status == AM_SUCCESS) { // Get the agent configuration agent_config = am_web_get_agent_configuration(); // Dump the entire set of request headers if (am_web_is_max_debug_on()) { char *header_str = pblock_pblock2str(rq->reqpb, NULL); am_web_log_max_debug("%s: Headers: %s", thisfunc, header_str); system_free(header_str); } } // Get header values if (status == AM_SUCCESS) { status = get_header_value(rq->reqpb, REQUEST_URI, B_TRUE, &uri_hdr, B_FALSE, NULL); } if (status == AM_SUCCESS) { status = get_header_value(rq->vars, PATH_INFO, B_FALSE, &pathInfo_hdr, B_FALSE, NULL); } if (status == AM_SUCCESS) { status = get_header_value(rq->reqpb, REQUEST_METHOD, B_TRUE, &method_hdr, B_TRUE, &method); } if (status == AM_SUCCESS) { status = get_header_value(rq->headers, "ampxy_host", B_TRUE, &virtHost_hdr, B_FALSE, NULL); } if (status == AM_SUCCESS) { status = get_header_value(rq->reqpb, REQUEST_QUERY, B_FALSE, &query_hdr, B_TRUE, &query); } if (security_active) { protocol = "HTTPS"; } // Get the request URL if (status == AM_SUCCESS) { if (am_web_is_proxy_override_host_port_set(agent_config) == AM_FALSE) { status = am_web_get_request_url(virtHost_hdr, protocol, NULL, 0, uri_hdr, query, &request_url, agent_config); if(status == AM_SUCCESS) { am_web_log_debug("%s: Request_url: %s", thisfunc, request_url); } else { am_web_log_error("%s: Could not get the request URL. " "Failed with error: %s.", thisfunc, am_status_to_string(status)); } } } if (status == AM_SUCCESS) { if (am_web_is_proxy_override_host_port_set(agent_config) == AM_TRUE) { const char *agent_host = am_web_get_agent_server_host(agent_config); int agent_port = am_web_get_agent_server_port(agent_config); if (agent_host != NULL) { char *temp = NULL; temp = replace_host_port(request_url, agent_host, agent_port, agent_config); if (temp != NULL) { free(request_url); request_url = temp; } } am_web_log_debug("%s: Request_url after overriding " "host and port: %s", thisfunc, request_url); } } if (status == AM_SUCCESS) { // Check for magic notification URL if (B_TRUE == am_web_is_notification(request_url, agent_config)) { am_web_free_memory(request_url); am_web_delete_agent_configuration(agent_config); if(query != NULL) { free(query); query = NULL; } if(method != NULL) { free(method); method = NULL; } return REQ_PROCEED; } } // Check if the SSO token is in the cookie header if (status == AM_SUCCESS) { requestResult = getISCookie(pblock_findval(COOKIE_HDR, rq->headers), &dpro_cookie, agent_config); if (requestResult == REQ_ABORTED) { status = AM_FAILURE; } else if (dpro_cookie != NULL) { am_web_log_debug("%s: SSO token found in cookie header.", thisfunc); } } // Create the environment map if( status == AM_SUCCESS) { status = am_map_create(&env_parameter_map); if( status != AM_SUCCESS) { am_web_log_error("%s: Unable to create map, status = %s (%d)", thisfunc, am_status_to_string(status), status); } } // If there is a proxy in front of the agent, the user can set in the // properties file the name of the headers that the proxy uses to set // the real client IP and host name. In that case the agent needs // to use the value of these headers to process the request // // Get the client IP address header set by the proxy, if there is one if (status == AM_SUCCESS) { clientIP_hdr_name = am_web_get_client_ip_header_name(agent_config); if (clientIP_hdr_name != NULL) { status = get_header_value(rq->headers, clientIP_hdr_name, B_FALSE, &clientIP_hdr, B_FALSE, NULL); } } // Get the client host name header set by the proxy, if there is one if (status == AM_SUCCESS) { clientHostname_hdr_name = am_web_get_client_hostname_header_name(agent_config); if (clientHostname_hdr_name != NULL) { status = get_header_value(rq->headers, clientHostname_hdr_name, B_FALSE, &clientHostname_hdr, B_FALSE, NULL); } } // If the client IP and host name headers contain more than one // value, take the first value. if (status == AM_SUCCESS) { if ((clientIP_hdr != NULL) || (clientHostname_hdr != NULL)) { status = am_web_get_client_ip_host(clientIP_hdr, clientHostname_hdr, &clientIP, &clientHostname); } } // Set the IP address and host name in the environment map if ((status == AM_SUCCESS) && (clientIP != NULL)) { status = am_web_set_host_ip_in_env_map(clientIP, clientHostname, env_parameter_map, agent_config); } // If the client IP was not obtained previously, // get it from the REMOTE_ADDR header. if ((status == AM_SUCCESS) && (clientIP == NULL)) { status = get_header_value(sn->client, REQUEST_IP_ADDR, B_FALSE, &clientIP_hdr, B_TRUE, &clientIP); } // In CDSSO mode, check if the sso token is in the post data if( status == AM_SUCCESS) { if((am_web_is_cdsso_enabled(agent_config) == B_TRUE) && (strcmp(method, REQUEST_METHOD_POST) == 0)) { if((dpro_cookie == NULL) && (am_web_is_url_enforced(request_url, pathInfo_hdr, clientIP, agent_config) == B_TRUE)) { // Set original method to GET orig_req = strdup(REQUEST_METHOD_GET); if (orig_req != NULL) { am_web_log_debug("%s: Request method set to GET.", thisfunc); } else { am_web_log_error("%s: Not enough memory to ", "allocate orig_req.", thisfunc); status = AM_NO_MEMORY; } // Check if dpro_cookie is in post data if( status == AM_SUCCESS) { response = get_post_assertion_data(sn, rq, request_url); status = am_web_check_cookie_in_post(args, &dpro_cookie, &request_url, &orig_req, method, response, B_FALSE, set_cookie, set_method, agent_config); if( status == AM_SUCCESS) { am_web_log_debug("%s: SSO token found in " "assertion.",thisfunc); } else { am_web_log_debug("%s: SSO token not found in " "assertion. Redirecting to login page.", thisfunc); status = AM_INVALID_SESSION; } } // Set back the original clf-request attribute if (status == AM_SUCCESS) { int clf_reqSize = 0; if ((query != NULL) && (strlen(query) > 0)) { clf_reqSize = strlen(orig_req) + strlen(uri_hdr) + strlen (query) + strlen(protocol) + 4; } else { clf_reqSize = strlen(orig_req) + strlen(uri_hdr) + strlen(protocol) + 3; } clf_req = malloc(clf_reqSize); if (clf_req == NULL) { am_web_log_error("%s: Unable to allocate %i " "bytes for clf_req", thisfunc, clf_reqSize); status = AM_NO_MEMORY; } else { memset (clf_req,'\0',clf_reqSize); strcpy(clf_req, orig_req); strcat(clf_req, " "); strcat(clf_req, uri_hdr); if ((query != NULL) && (strlen(query) > 0)) { strcat(clf_req, "?"); strcat(clf_req, query); } strcat(clf_req, " "); strcat(clf_req, protocol); am_web_log_debug("%s: clf-request set to %s", thisfunc, clf_req); } pblock_nvinsert(REQUEST_CLF, clf_req, rq->reqpb); } } } } // Check if access is allowed. if( status == AM_SUCCESS) { if (dpro_cookie != NULL) { am_web_log_debug("%s: SSO token = %s", thisfunc, dpro_cookie); } else { am_web_log_debug("%s: SSO token not found.", thisfunc); } status = am_web_is_access_allowed(dpro_cookie, request_url, pathInfo_hdr, method, clientIP, env_parameter_map, &result, agent_config); am_map_destroy(env_parameter_map); } switch(status) { case AM_SUCCESS: // Set remote user and authentication type ruser = result.remote_user; if (ruser != NULL) { pb_param *pbuser = pblock_remove(AUTH_USER_VAR, rq->vars); pb_param *pbauth = pblock_remove(AUTH_TYPE_VAR, rq->vars); if (pbuser != NULL) { param_free(pbuser); } pblock_nvinsert(AUTH_USER_VAR, ruser, rq->vars); if (pbauth != NULL) { param_free(pbauth); } pblock_nvinsert(AUTH_TYPE_VAR, AM_WEB_AUTH_TYPE_VALUE, rq->vars); am_web_log_debug("%s: access allowed to %s", thisfunc, ruser); } else { am_web_log_debug("%s: Remote user not set, " "allowing access to the url as it is in not " "enforced list", thisfunc); } if (am_web_is_logout_url(request_url, agent_config) == B_TRUE) { (void)am_web_logout_cookies_reset(reset_cookie, args, agent_config); } // set LDAP user attributes to http header status = am_web_result_attr_map_set(&result, set_header, set_cookie_in_response, set_header_attr_as_cookie, get_cookie_sync, args, agent_config); if (status != AM_SUCCESS) { am_web_log_error("%s: am_web_result_attr_map_set failed, " "status = %s (%d)", thisfunc, am_status_to_string(status), status); requestResult = REQ_ABORTED; } else { requestResult = REQ_PROCEED; } break; case AM_ACCESS_DENIED: am_web_log_debug("%s: Access denied to %s", thisfunc, result.remote_user ? result.remote_user : "******"); requestResult = do_redirect(sn, rq, status, &result, request_url, method, agent_config); break; case AM_INVALID_SESSION: if (am_web_is_cdsso_enabled(agent_config) == B_TRUE) { cdStatus = am_web_do_cookie_domain_set(set_cookie, args, EMPTY_STRING, agent_config); if(cdStatus != AM_SUCCESS) { am_web_log_error("%s: CDSSO reset cookie failed", thisfunc); } } am_web_do_cookies_reset(reset_cookie, args, agent_config); requestResult = do_redirect(sn, rq, status, &result, request_url, method, agent_config); break; case AM_INVALID_FQDN_ACCESS: // Redirect to self with correct FQDN - no post preservation requestResult = do_redirect(sn, rq, status, &result, request_url, method, agent_config); break; case AM_REDIRECT_LOGOUT: status = am_web_get_logout_url(&logout_url, agent_config); if(status == AM_SUCCESS) { do_url_redirect(sn,rq,logout_url); } else { requestResult = REQ_ABORTED; am_web_log_debug("validate_session_policy(): " "am_web_get_logout_url failed. "); } break; case AM_INVALID_ARGUMENT: case AM_NO_MEMORY: default: am_web_log_error("validate_session_policy() Status: %s (%d)", am_status_to_string(status), status); requestResult = REQ_ABORTED; break; } // Cleaning am_web_clear_attributes_map(&result); am_policy_result_destroy(&result); am_web_free_memory(dpro_cookie); am_web_free_memory(request_url); am_web_free_memory(logout_url); am_web_delete_agent_configuration(agent_config); if (orig_req != NULL) { free(orig_req); orig_req = NULL; } if (response != NULL) { free(response); response = NULL; } if (clf_req != NULL) { free(clf_req); clf_req = NULL; } if(query != NULL) { free(query); query = NULL; } if(method != NULL) { free(method); method = NULL; } if(clientIP != NULL) { am_web_free_memory(clientIP); } if(clientHostname != NULL) { am_web_free_memory(clientHostname); } am_web_log_max_debug("%s: Completed handling request with status: %s.", thisfunc, am_status_to_string(status)); return requestResult; }
NSAPI_PUBLIC int web_agent_init(pblock *param, Session *sn, Request *rq) { am_status_t status; int nsapi_status = REQ_PROCEED; char *temp_buf = NULL; char *agent_bootstrap_file = NULL; char *agent_config_file = NULL; initLock = crit_init(); temp_buf = pblock_findval(DSAME_CONF_DIR, param); if (temp_buf != NULL) { agent_bootstrap_file = system_malloc(strlen(temp_buf) + sizeof(AGENT_BOOTSTRAP_FILE)); agent_config_file = system_malloc(strlen(temp_buf) + sizeof(AGENT_CONFIG_FILE)); if (agent_bootstrap_file != NULL) { strcpy(agent_bootstrap_file, temp_buf); strcat(agent_bootstrap_file, AGENT_BOOTSTRAP_FILE); } else { log_error(LOG_FAILURE, "URL Access Agent: ", sn, rq, "web_agent_init() unable to allocate memory for bootstrap " "file name", DSAME_CONF_DIR); nsapi_status = REQ_ABORTED; } if (agent_config_file != NULL) { strcpy(agent_config_file, temp_buf); strcat(agent_config_file, AGENT_CONFIG_FILE); } else { log_error(LOG_FAILURE, "URL Access Agent: ", sn, rq, "web_agent_init() unable to allocate memory for local config " "file name", DSAME_CONF_DIR); nsapi_status = REQ_ABORTED; } status = am_properties_create(&agent_props.agent_bootstrap_props); if(status == AM_SUCCESS) { status = am_properties_load(agent_props.agent_bootstrap_props, agent_bootstrap_file); if(status == AM_SUCCESS) { //this is where the agent config info is passed from filter code //to amsdk. Not sure why agent_props is required. status = am_web_init(agent_bootstrap_file, agent_config_file); system_free(agent_bootstrap_file); system_free(agent_config_file); if (AM_SUCCESS != status) { log_error(LOG_FAILURE, "URL Access Agent: ", sn, rq, "Initialization of the agent failed: " "status = %s (%d)", am_status_to_string(status), status); nsapi_status = REQ_ABORTED; } } else { log_error(LOG_FAILURE, "web_agent_init():", sn, rq, "Error while creating properties object= %s", am_status_to_string(status)); nsapi_status = REQ_ABORTED; } } else { log_error(LOG_FAILURE, "web_agent_init():", sn, rq, "Error while creating properties object= %s", am_status_to_string(status)); nsapi_status = REQ_ABORTED; } } else { log_error(LOG_FAILURE, "URL Access Agent: ", sn, rq, "web_agent_init() %s variable not defined in magnus.conf", DSAME_CONF_DIR); nsapi_status = REQ_ABORTED; } if(nsapi_status == REQ_PROCEED) { daemon_atrestart(&agent_cleanup, NULL); } return nsapi_status; }
/** * determines to grant access */ int dsame_check_access(request_rec *r) { char *dpro_cookie = get_cookie(r, am_web_get_cookie_name()); char *url = get_request_url(r); char *content; am_status_t status = AM_FAILURE; int ret = OK; const char *ruser = NULL; int bytesRead; am_map_t env_parameter_map = NULL; am_policy_result_t result = AM_POLICY_RESULT_INITIALIZER; void *args[1] = { (void *)r }; am_web_log_debug("Apache Agent: %s request for URL %s", r->method, url); if (B_TRUE==am_web_is_notification(url)) { bytesRead = content_read(r, &content); am_web_log_max_debug("Apache Agent: Content is %s", content); am_web_handle_notification(content, bytesRead); ap_rputs("OK",r); return OK; } if (dpro_cookie != NULL){ am_web_log_debug("Apache Agent: cookie value is: %s", dpro_cookie); } else { am_web_log_debug("Apache Agent: cookie is null"); } status = am_map_create(&env_parameter_map); if( status != AM_SUCCESS) { am_web_log_error("Apache Agent: unable to create map, " "status = %s (%d)", am_status_to_string(status), status); } else { am_web_log_debug("Apache Agent: am_map_create returned status=%s", am_status_to_string(status)); } if(status == AM_SUCCESS) { status = am_web_is_access_allowed(dpro_cookie, url, r->method, (char *)r->connection->remote_ip, env_parameter_map, &result); am_map_destroy(env_parameter_map); } am_web_log_debug("Apache Agent: am_web_is_access_allowed returned status=%s", am_status_to_string(status)); switch (status) { case AM_SUCCESS: ruser = result.remote_user; if (ruser != NULL) { r->connection->user = ap_pstrdup(r->pool, ruser); r->connection->ap_auth_type = ap_pstrdup(r->pool, DSAME); am_web_log_debug("URL Access Agent: access allowed to %s", ruser); } else { am_web_log_error("URL Access Agent: access allowed to unknown " "user"); } /* set LDAP user attributes to http header */ status = am_web_do_result_attr_map_set(&result, set_header, args); if (status != AM_SUCCESS) { am_web_log_error("URL Access Agent: am_web_do_result_attr_map_set " "failed, status = %s (%d)", am_status_to_string(status), status); } ret = OK; break; case AM_ACCESS_DENIED: am_web_log_always("URL Access Agent: access denied to %s", result.remote_user ? result.remote_user : "******"); ret = do_redirect(r, status, result.advice_map, url); break; case AM_INVALID_SESSION: /* XXX - Add POST Cache code here. */ ret = do_redirect(r, status, result.advice_map, url); break; case AM_INVALID_FQDN_ACCESS: // Redirect to self with correct FQDN - no post preservation ret = do_redirect(r, status, result.advice_map, url); break; case AM_INVALID_ARGUMENT: case AM_NO_MEMORY: default: am_web_log_error("URL Access Agent: status: %s (%d)", am_status_to_string(status), status); ret = SERVER_ERROR; break; } am_policy_result_destroy(&result); return ret; }
static int do_redirect(Session *sn, Request *rq, am_status_t status, am_policy_result_t *policy_result, const char *original_url, const char* method, void* agent_config) { int retVal = REQ_ABORTED; char *redirect_url = NULL; const am_map_t advice_map = policy_result->advice_map; am_status_t ret = AM_SUCCESS; ret = am_web_get_url_to_redirect(status, advice_map, original_url, method, AM_RESERVED, &redirect_url, agent_config); if (ret == AM_SUCCESS && redirect_url != NULL) { char *advice_txt = NULL; if (B_FALSE == am_web_use_redirect_for_advice(agent_config) && policy_result->advice_string != NULL) { // Composite advice is sent as a POST ret = am_web_build_advice_response(policy_result, redirect_url, &advice_txt); am_web_log_debug("do_redirect(): policy status=%s,", "response[%s]", am_status_to_string(status), advice_txt); if (ret == AM_SUCCESS) { retVal = send_data(advice_txt, sn, rq); } else { am_web_log_error("do_redirect(): Error while building " "advice response body:%s", am_status_to_string(ret)); retVal = REQ_EXIT; } } else { // No composite advice or composite advice is redirected am_web_log_debug("do_redirect() policy status = %s, ", "redirection URL is %s", am_status_to_string(status), redirect_url); // we need to modify the redirect_url with the policy advice if (B_TRUE == am_web_use_redirect_for_advice(agent_config) && policy_result->advice_string != NULL) { char *redirect_url_with_advice = NULL; ret = am_web_build_advice_redirect_url(policy_result, redirect_url, &redirect_url_with_advice); if (ret == AM_SUCCESS) { redirect_url = redirect_url_with_advice; am_web_log_debug("do_redirect(): policy status=%s, " "redirect url with advice [%s]", am_status_to_string(status), redirect_url); } else { am_web_log_error("do_redirect(): Error while building " "the redirect url with advice:%s", am_status_to_string(ret)); } } /* redirection is enabled by the PathCheck directive */ /* Set the return code to 302 Redirect */ protocol_status(sn, rq, PROTOCOL_REDIRECT, NULL); /* set the new URL to redirect */ //pblock_nvinsert("url", redirect_url, rq->vars); pblock_nvinsert("escape", "no", rq->vars); param_free(pblock_remove("Location", rq->srvhdrs)); pblock_nvinsert("Location", redirect_url, rq->srvhdrs); protocol_start_response(sn, rq); am_web_free_memory(redirect_url); } } else if (ret == AM_NO_MEMORY) { /* Set the return code 500 Internal Server Error. */ protocol_status(sn, rq, PROTOCOL_SERVER_ERROR, NULL); am_web_log_error("do_redirect() Status code= %s.", am_status_to_string(status)); } else { /* Set the return code 403 Forbidden */ protocol_status(sn, rq, PROTOCOL_FORBIDDEN, NULL); am_web_log_info("do_redirect() Status code= %s.", am_status_to_string(status)); } return retVal; }
am_status_t Connection::waitForReply(char *&buffer, std::size_t bufferLen, std::size_t totalBytesRead, std::size_t& receivedLen) { am_status_t status = AM_SUCCESS; if (static_cast<char *>(NULL) == buffer || 0 == bufferLen) { if (0 == bufferLen) { bufferLen = DEFAULT_BUFFER_LEN; } totalBytesRead = 0; // Ignore any value that was passed in. buffer = new (std::nothrow) char[bufferLen]; } if (static_cast<char *>(NULL) != buffer) { std::size_t bytesToRead = bufferLen - totalBytesRead; status = read(&buffer[totalBytesRead], bytesToRead); while (status == AM_SUCCESS && bytesToRead > 0) { totalBytesRead += bytesToRead; bytesToRead = bufferLen - totalBytesRead; if (bytesToRead <= MIN_BYTES_TO_READ) { // If the new buffer size is smaller than the INCREMENT_LEN // we grow the buffer by doubling the size. If the current // size is less than the INCREMENT_LEN, but the new size is // greater than we use INCREMENT_LEN as the new buffer size, // otherwise add INCREMENT_LEN. The order of the tests is // rearranged from the prose to reflect the expected // probability of each situation occurring. if ((2 * bufferLen) <= INCREMENT_LEN) { bufferLen *= 2; } else if (bufferLen >= INCREMENT_LEN) { bufferLen += INCREMENT_LEN; } else { bufferLen = INCREMENT_LEN; } buffer = growBuffer(buffer, totalBytesRead, bufferLen); if (static_cast<char *>(NULL) == buffer) { status = AM_NO_MEMORY; break; } bytesToRead = bufferLen - totalBytesRead; } status = read(&buffer[totalBytesRead], bytesToRead); } if (AM_SUCCESS == status) { if (totalBytesRead == bufferLen) { buffer = growBuffer(buffer, totalBytesRead, totalBytesRead + 1); if (static_cast<char *>(NULL) == buffer) { status = AM_NO_MEMORY; } } if (AM_SUCCESS == status) { buffer[totalBytesRead] = '\0'; receivedLen = totalBytesRead; } } } else { status = AM_NO_MEMORY; } Log::log(Log::ALL_MODULES, Log::LOG_MAX_DEBUG, "Connection::waitForReply(): returns with status %s.", am_status_to_string(status)); return status; }
// this should not throw exception since it is called often in a // catch block to log an error resulting from an exception. void Log::vlog(ModuleId module, Level level, const char *format, std::va_list args) throw() { if (initialized) { if (module >= moduleList->size()) { module = ALL_MODULES; } char *logMsg = PR_vsmprintf(format, args); // call user defined logger if any. if (loggerFunc != NULL) { loggerFunc((*moduleList)[module].name.c_str(), static_cast<am_log_level_t>(static_cast<int>(level)), logMsg); } // do default log. if ((*moduleList)[module].level >= level) { // format: // year-month-day hour:min:sec.usec level pid:thread module: msg // get level string std::size_t levelLabelIndex = getLevelString(level); char levelStr[50]; PRUint32 llen; if (levelLabelIndex < numLabels) { llen = PR_snprintf(levelStr, sizeof(levelStr), "%s", levelLabels[levelLabelIndex]); } else { llen = PR_snprintf(levelStr, sizeof(levelStr), "%d", level); } if (llen > 0) { // get time. PRExplodedTime now; PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &now); // format header and msg. PRUint32 len; char hdr[100]; len = PR_snprintf(hdr, sizeof(hdr), "%d-%02d-%02d %02d:%02d:%02d.%03d" "%8s %u:%p %s: %%s\n", now.tm_year, now.tm_month+1, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec, now.tm_usec / 1000, levelStr, getpid(), PR_GetCurrentThread(), (*moduleList)[module].name.c_str()); if (len > 0) { if (logRotation) { if ((currentLogFileSize + 1000) < maxLogFileSize) { std::fprintf(logFile, hdr, logMsg); std::fflush(logFile); } else { ScopeLock scopeLock(*lockPtr); currentLogFileSize = ftell(logFile); if ((currentLogFileSize + 1000) > maxLogFileSize) { // Open a new log file if (!pSetLogFile(logFileName)) { log(ALL_MODULES, LOG_ERROR, "Unable to open log file: '%s', errno = %d", logFileName.c_str(), errno); } } std::fprintf(logFile, hdr, logMsg); std::fflush(logFile); } currentLogFileSize = ftell(logFile); } else { std::fprintf(logFile, hdr, logMsg); std::fflush(logFile); } } } } // Remote Logging starts here. if (module == remoteModule) { if (remoteInitialized) { bool doLogRemotely = ((*moduleList)[module].level >= Log::LOG_AUTH_REMOTE) && ((*moduleList)[module].level & level); if (doLogRemotely) { am_status_t status; status = rmtLogSvc->logMessage(logMsg); if(status != AM_SUCCESS) { Log::log(Log::ALL_MODULES, Log::LOG_ERROR, "Log::vlog(): Error logging message [%s] " "to remote server. Error: %s.", logMsg, am_status_to_string(status)); } } } else { Log::log(Log::ALL_MODULES, Log::LOG_ERROR, "Log::vlog(): Remote logging service not initialized. " "Cannot log message to remote server."); } } PR_smprintf_free(logMsg); } return; }
/** * Parses agent profile REST attributes service response and sets the * properties in properties object. * * Throws XMLTree::ParseException */ am_status_t AgentProfileService::parseAgentResponse(const std::string xmlResponse, am_properties_t properties ) { am_status_t status = AM_SUCCESS; XMLTree namingTree(false, xmlResponse.c_str(), xmlResponse.size()); XMLElement element = namingTree.getRootElement(); XMLElement element1; // get the root element userdetails if (element.isNamed("identitydetails")) { // get the first attribute element element.getSubElement("attribute", element); if (element.isNamed("attribute")) { // iterate through all the attribute elements while (element.isValid()) { if(element.isNamed("attribute")) { std::string propName; std::string propValue; bool propSet = false; // get property name and assign it to propName if (element.getAttributeValue("name", propName)) { // get property's value(s) and assign it to propValue element1 = element.getFirstSubElement(); if (element1.isNamed("value")) { int i = 0; // if multiple values exist, //append them with a separator ' ' while (element1.isValid()) { if(element1.isNamed("value")) { std::string tmpValue; if (element1.getValue(tmpValue)) { // Process freeform properties if(strcasecmp(propName.c_str(), AM_WEB_AGENT_FREEFORM_PROPERTY) == 0) { size_t equals = tmpValue.find("="); std::string ffPropName = tmpValue.substr(0, equals); std::string ffPropValue = tmpValue.substr(equals + 1); am_properties_set(properties, ffPropName.c_str(), ffPropValue.c_str()); Log::log(logModule, Log::LOG_DEBUG, "agentAttributes() %s : %s ", ffPropName.c_str(), ffPropValue.c_str()); } // Process list/map properties if(isListMapProperty(propName.c_str())) { size_t equals = tmpValue.find("="); //the following returns [] portion before = std::string lmPropNameSuffix = tmpValue.substr(0, equals); //the following returns value portion after = std::string lmPropValue = tmpValue.substr(equals + 1); std::string tmpPropName = propName; am_properties_set(properties, (tmpPropName.append(lmPropNameSuffix)).c_str(), lmPropValue.c_str()); propSet = true; Log::log(logModule, Log::LOG_DEBUG, "agentAttributes() %s : %s ", propName.c_str(), lmPropValue.c_str()); } // Process debug.level property if(strcasecmp(propName.c_str(), AM_AGENT_DEBUG_LEVEL_PROPERTY) == 0) { std::string tmpDebugLevel; if(strcasecmp(tmpValue.c_str(),"Error") == 0) tmpDebugLevel = "all:1"; if(strcasecmp(tmpValue.c_str(),"Warning") == 0) tmpDebugLevel = "all:2"; if(strcasecmp(tmpValue.c_str(),"Info") == 0) tmpDebugLevel = "all:3"; if(strcasecmp(tmpValue.c_str(),"Message") == 0) tmpDebugLevel = "all:4"; if(strcasecmp(tmpValue.c_str(),"All") == 0) tmpDebugLevel = "all:5"; if(!tmpDebugLevel.empty()) { am_properties_set(properties, propName.c_str(), tmpDebugLevel.c_str()); propSet = true; Log::log(logModule, Log::LOG_DEBUG, "agentAttributes() %s : %s ", propName.c_str(), tmpDebugLevel.c_str()); } } if(i > 0) propValue.append(" "); propValue.append(tmpValue); } else { throw XMLTree::ParseException( "Attribute value missing "); } } element1.nextSibling(); i++; } // end of value element while loop } // end of if value check if(!propSet) { // assign property name and value in properties object. if(!propValue.empty()) { am_properties_set(properties, propName.c_str(), propValue.c_str()); } else { // The following is required for validation of // agent repository location value. if(strcasecmp(propName.c_str(), AM_WEB_AGENT_REPOSITORY_LOCATION_PROPERTY) == 0) { am_properties_set_null(properties, propName.c_str(), "\0"); } } Log::log(logModule, Log::LOG_DEBUG, "agentAttributes() %s : %s", propName.c_str(), propValue.c_str()); } } else { throw XMLTree::ParseException("Attribute name missing "); } } element.nextSibling(); } status = AM_SUCCESS; } else { throw XMLTree::ParseException("attribute element not present in " "Attributes Response xml"); } } else { throw XMLTree::ParseException("userdetails root element not present in " "Attributes Response xml"); } Log::log(logModule, Log::LOG_DEBUG, "parseAgentResponse() " "returning with status %s.", am_status_to_string(status)); return status; }