static char *auth_pg_base64(char *pw) { if (auth_pgsql_pool_base64 == NULL) apr_pool_create_ex(&auth_pgsql_pool_base64, NULL, NULL, NULL); if (auth_pgsql_pool == NULL) return NULL; return ap_pbase64encode(auth_pgsql_pool, pw); }
static int check_auth_cookie(request_rec *r) { const char *cookies = NULL, *auth_line = NULL; char *cookie = NULL; /* Debug. */ /*ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "check_auth_cookie called");*/ /* Get config for this directory. */ cookie_auth_config_rec *conf = ap_get_module_config(r->per_dir_config, &auth_cookie_module); /* Check we have been configured. */ if (!conf->cookie_auth_cookie) { return DECLINED; } /* Do not override real auth header, unless config instructs us to. */ if (!conf->cookie_auth_override && apr_table_get(r->headers_in, "Authorization")) { if (conf->cookie_auth_env) { unsetenv(conf->cookie_auth_env); } return DECLINED; } /* todo: protect against xxxCookieNamexxx, regex? */ /* todo: make case insensitive? */ /* Get the cookie (code from mod_log_config). */ if ((cookies = apr_table_get(r->headers_in, "Cookie"))) { char *start_cookie, *end_cookie; if ((start_cookie = ap_strstr_c(cookies, conf->cookie_auth_cookie))) { start_cookie += strlen(conf->cookie_auth_cookie) + 1; cookie = apr_pstrdup(r->pool, start_cookie); /* kill everything in cookie after ';' */ end_cookie = strchr(cookie, ';'); if (end_cookie) { *end_cookie = '\0'; } ap_unescape_url(cookie); } } /* No cookie? Nothing for us to do. */ if (!cookie) { if (conf->cookie_auth_unauth_redirect) { const char* redirect = conf->cookie_auth_unauth_redirect; compose_and_set_redirect(r, redirect); return HTTP_MOVED_TEMPORARILY; } else { return DECLINED; } } /* Debug. */ /*ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "%s=%s", conf->cookie_auth_cookie, cookie);*/ char* aux_auth_info = ""; /* Construct the fake auth_line. */ if (conf->cookie_auth_base64) { char* decoded_cookie = apr_palloc(r->pool, apr_base64_decode_len(cookie)); int decoded_cookie_length = apr_base64_decode(decoded_cookie, cookie); int valid = 1; /* if the cookie is encrypted, decrypt it in place */ if (conf->cookie_auth_encrypt) { MCRYPT td = mcrypt_module_open("rijndael-128", NULL, "cbc", NULL); int keysize = strlen(conf->cookie_auth_encrypt); int blocksize = mcrypt_enc_get_block_size(td); // We will copy the iv from the beginning of the cookie. // The iv does not need to be null-terminated, but we will // null-terminate it for convenience. int iv_length = mcrypt_enc_get_iv_size(td); char* iv = (char*) apr_palloc(r->pool, iv_length + 1); memcpy(iv, decoded_cookie, iv_length); iv[iv_length] = '\0'; // Take the iv off the beginning of the cookie decoded_cookie += iv_length; decoded_cookie_length -= iv_length; mcrypt_generic_init( td, conf->cookie_auth_encrypt, keysize, iv); // Encryption in CBC is performed in blocks, so our // decryption string will always be an integral number // of full blocks. char* decrypt_ptr = decoded_cookie; while (decoded_cookie_length >= blocksize) { mdecrypt_generic(td, decrypt_ptr, blocksize); decrypt_ptr += blocksize; decoded_cookie_length -= blocksize; } if (decoded_cookie_length != 0) { valid = 0; } mcrypt_generic_deinit (td); mcrypt_module_close(td); /*ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "mdecrypt(%s)=%s", conf->cookie_auth_cookie, decoded_cookie);*/ } /* if the cookie did not decrypt, then do nothing */ if (valid) { char* end_auth_info = strchr(decoded_cookie, '\t'); if (end_auth_info) { aux_auth_info = decoded_cookie; char* unencoded_cookie = end_auth_info + 1; *end_auth_info = 0; auth_line = apr_pstrcat(r->pool, "Basic ", ap_pbase64encode(r->pool, unencoded_cookie), NULL); } else { auth_line = apr_pstrcat(r->pool, "Basic ", ap_pbase64encode(r->pool, decoded_cookie), NULL); } } } else { // Aux auth info and cookie encrypt features only available in base64 mode ap_unescape_url(cookie); auth_line = apr_pstrcat(r->pool, "Basic ", ap_pbase64encode(r->pool, cookie), NULL); } /* If there is aux auth info, then set the env variable */ if (conf->cookie_auth_env) { apr_table_set(r->subprocess_env, conf->cookie_auth_env, aux_auth_info); } /* Debug. */ /*ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Authorization: %s", auth_line);*/ /* If there is no aux auth info, then force a redirect if our conf directives say that we should */ if (conf->cookie_auth_env_redirect && !strlen(aux_auth_info)) { const char* redirect = conf->cookie_auth_env_redirect; compose_and_set_redirect(r, redirect); return HTTP_MOVED_TEMPORARILY; } else { /* Set fake auth_line. */ if (auth_line) { apr_table_set(r->headers_in, "Authorization", auth_line); } } /* Always return DECLINED because we don't authorize, */ /* we just set things up for the next auth module to. */ return DECLINED; }
int spep::apache::RequestHandler::handleRequestInner( request_rec *req ) { if( !this->_spep->isStarted() ) { return HTTP_SERVICE_UNAVAILABLE; } spep::SPEPConfigData *spepConfigData = this->_spep->getSPEPConfigData(); char *properURI = apr_pstrdup( req->pool, req->parsed_uri.path ); if( req->parsed_uri.query != NULL ) { properURI = apr_psprintf( req->pool, "%s?%s", properURI, req->parsed_uri.query ); } ap_unescape_url( properURI ); Cookies cookies( req ); std::vector<std::string> cookieValues; cookies.getCookieValuesByName( cookieValues, spepConfigData->getTokenName() ); if( !cookieValues.empty() ) { std::string sessionID; spep::PrincipalSession principalSession; bool validSession = false; // SPEP cookie was found, validate using one of the values and use that to proceed. for (std::vector<std::string>::iterator cookieValueIterator = cookieValues.begin(); cookieValueIterator != cookieValues.end(); ++cookieValueIterator) { sessionID = *cookieValueIterator; try { principalSession = this->_spep->getAuthnProcessor()->verifySession( sessionID ); validSession = true; break; } catch( std::exception& e ) { } } if( validSession ) { // If attribute querying is not disabled... if( !this->_spep->getSPEPConfigData()->disableAttributeQuery() ) { // Put attributes into the environment. std::string usernameAttribute = spepConfigData->getUsernameAttribute(); std::string attributeValueSeparator = spepConfigData->getAttributeValueSeparator(); std::string attributeNamePrefix = spepConfigData->getAttributeNamePrefix(); for( spep::PrincipalSession::AttributeMapType::iterator attributeIterator = principalSession.getAttributeMap().begin(); attributeIterator != principalSession.getAttributeMap().end(); ++attributeIterator ) { std::string name = spep::UnicodeStringConversion::toString( attributeIterator->first ); std::string envName = attributeNamePrefix + name; std::stringstream valueStream; bool first = true; for( std::vector<UnicodeString>::iterator attributeValueIterator = attributeIterator->second.begin(); attributeValueIterator != attributeIterator->second.end(); ++attributeValueIterator ) { std::string value = spep::UnicodeStringConversion::toString( *attributeValueIterator ); if( first ) { valueStream << value; first = false; } else { valueStream << attributeValueSeparator << value; } } std::string envValue = valueStream.str(); // Insert the attribute name/value pair into the subprocess environment. apr_table_set( req->subprocess_env, envName.c_str(), envValue.c_str() ); if( name.compare( usernameAttribute ) == 0 ) { #ifndef APACHE1 req->user = apr_pstrdup( req->pool, envValue.c_str() ); #else req->connection->user = apr_pstrdup( req->pool, envValue.c_str() ); #endif } } } if( this->_spep->getSPEPConfigData()->disablePolicyEnforcement() ) { // No need to perform authorization, just let them in. return DECLINED; } // Perform authorization on the URI requested. spep::PolicyEnforcementProcessorData pepData; pepData.setESOESessionID( principalSession.getESOESessionID() ); pepData.setResource( properURI ); this->_spep->getPolicyEnforcementProcessor()->makeAuthzDecision( pepData ); spep::Decision authzDecision( pepData.getDecision() ); validSession = false; try { principalSession = this->_spep->getAuthnProcessor()->verifySession( sessionID ); validSession = true; } catch( std::exception& e ) { } if( validSession ) { if( authzDecision == spep::Decision::PERMIT ) { return DECLINED; } else if( authzDecision == spep::Decision::DENY ) { return HTTP_FORBIDDEN; } else if( authzDecision == spep::Decision::ERROR ) { return HTTP_INTERNAL_SERVER_ERROR; } else { return HTTP_INTERNAL_SERVER_ERROR; } } } } // If we get to this stage, the session has not been authenticated. We proceed to clear the // cookies configured by the SPEP to be cleared upon logout, since this is potentially the // first time they have come back to the SPEP since logging out. bool requireSend = false; const std::vector<std::string>& logoutClearCookies = this->_spep->getSPEPConfigData()->getLogoutClearCookies(); for( std::vector<std::string>::const_iterator logoutClearCookieIterator = logoutClearCookies.begin(); logoutClearCookieIterator != logoutClearCookies.end(); ++logoutClearCookieIterator ) { // Throw the configured string into a stringstream std::stringstream ss( *logoutClearCookieIterator ); // Split into name, domain, path. Doc says that stringstream operator>> won't throw std::string cookieNameString, cookieDomainString, cookiePathString; ss >> cookieNameString >> cookieDomainString >> cookiePathString; // Default to NULL, and then check if they were specified const char *cookieName = NULL, *cookieDomain = NULL, *cookiePath = NULL; // No cookie name, no clear. if( cookieNameString.length() == 0 ) { continue; } // If the user sent this cookie. Cookies cookies( req ); std::vector<std::string> cookieValues; cookies.getCookieValuesByName( cookieValues, spepConfigData->getTokenName() ); if( !cookieValues.empty() ) { cookieName = cookieNameString.c_str(); if( cookieDomainString.length() > 0 ) { cookieDomain = cookieDomainString.c_str(); } if( cookiePathString.length() > 0 ) { cookiePath = cookiePathString.c_str(); } // Set the cookie to an empty value. cookies.addCookie( req, cookieName, "", cookiePath, cookieDomain, false ); // Flag that we need to send the cookies, because we have set at least one. requireSend = true; } } if( requireSend ) { cookies.sendCookies( req ); } // Lazy init code. if( spepConfigData->isLazyInit() ) { std::string globalESOECookieName( spepConfigData->getGlobalESOECookieName() ); Cookies cookies( req ); std::vector<std::string> cookieValues; cookies.getCookieValuesByName( cookieValues, globalESOECookieName ); if( cookieValues.empty() ) { bool matchedLazyInitResource = false; UnicodeString properURIUnicode( spep::UnicodeStringConversion::toUnicodeString( properURI ) ); std::vector<UnicodeString>::const_iterator lazyInitResourceIterator; for( lazyInitResourceIterator = spepConfigData->getLazyInitResources().begin(); lazyInitResourceIterator != spepConfigData->getLazyInitResources().end(); ++lazyInitResourceIterator ) { // TODO Opportunity for caching of compiled regex patterns is here. UParseError parseError; UErrorCode errorCode = U_ZERO_ERROR; // Perform the regular expression matching here. UBool result = RegexPattern::matches( *lazyInitResourceIterator, properURIUnicode, parseError, errorCode ); if ( U_FAILURE( errorCode ) ) { // TODO throw u_errorName( errorCode ) return HTTP_INTERNAL_SERVER_ERROR; } // FALSE is defined by ICU. This line for portability. if (result != FALSE) { matchedLazyInitResource = true; break; } } if( matchedLazyInitResource ) { if( !spepConfigData->isLazyInitDefaultPermit() ) { return DECLINED; } } else { if( spepConfigData->isLazyInitDefaultPermit() ) { return DECLINED; } } } } boost::posix_time::ptime epoch( boost::gregorian::date( 1970, 1, 1 ) ); boost::posix_time::time_duration timestamp = boost::posix_time::microsec_clock::local_time() - epoch; boost::posix_time::time_duration::tick_type currentTimeMillis = timestamp.total_milliseconds(); apr_uri_t *uri = static_cast<apr_uri_t*>( apr_pcalloc( req->pool, sizeof(apr_uri_t) ) ); apr_uri_parse( req->pool, this->_spep->getSPEPConfigData()->getServiceHost().c_str(), uri ); const char *hostname = apr_table_get( req->headers_in, "Host" ); if( hostname == NULL ) { hostname = req->server->server_hostname; } const char *format = NULL; const char *base64RequestURI = NULL; // If we can't determine our own hostname, just fall through to the service host. // If the service host was requested obviously we want that. if( hostname == NULL || std::strcmp( uri->hostinfo, hostname ) == 0 ) { // Join the service hostname and requested URI to form the return URL char *returnURL = apr_psprintf( req->pool, "%s%s", this->_spep->getSPEPConfigData()->getServiceHost().c_str(), req->unparsed_uri ); // Base64 encode this so that the HTTP redirect doesn't corrupt it. base64RequestURI = ap_pbase64encode( req->pool, returnURL ); // Create the format string for building the redirect URL. format = apr_psprintf( req->pool, "%s%s", this->_spep->getSPEPConfigData()->getServiceHost().c_str(), this->_spep->getSPEPConfigData()->getSSORedirect().c_str() ); } else { base64RequestURI = ap_pbase64encode( req->pool, req->unparsed_uri ); // getSSORedirect() will only give us a temporary.. dup it into the pool so we don't lose it when we leave this scope. format = apr_pstrdup( req->pool, this->_spep->getSPEPConfigData()->getSSORedirect().c_str() ); } char *redirectURL = apr_psprintf( req->pool, format, base64RequestURI ); std::stringstream timestampParameter; if( strchr( redirectURL, '?' ) != NULL ) { // Query string already exists.. append the timestamp as another parameter timestampParameter << "&ts=" << currentTimeMillis; redirectURL = apr_psprintf( req->pool, "%s%s", redirectURL, timestampParameter.str().c_str() ); } else { // No query string. Add one with the timestamp as a parameter. timestampParameter << "?ts=" << currentTimeMillis; redirectURL = apr_psprintf( req->pool, "%s%s", redirectURL, timestampParameter.str().c_str() ); } apr_table_setn( req->headers_out, "Location", redirectURL ); return HTTP_MOVED_TEMPORARILY; }