Ejemplo n.º 1
0
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;
}
Ejemplo n.º 3
0
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;
	
}