[an error occurred while processing the directive]
![]() |
cosign-discuss at umich.edu |
general discussion of cosign development and deployment | |
Has anyone implemented a cosign-protected squid proxy?
From: Josh Partlow <jpartlow@xxxxxxxxxxxxxxxx> Date: 18 July 2005 21:08:00 GMT-04:00 To: wes@xxxxxxxxx Cc: Kirsten Comandich <kirsten@xxxxxxxxxxxxxxxx> Subject: Re: [Fwd: [Fwd: Re: patch to mod_cosign.c]]
Hi Wes,
Kirsten forwarded this to me, since I wrote the original patch. Sorry for the delay, I've been very busy with other projects.
So here's the background:
Reed College has a proxy server that allows users logged onto to its
internal network to access an array of periodical and research services
which Reed pays for. Reed also has a Cosign system set up to handle
authentication of users using web services on their network. Reed
wanted legitimate users of their network to be able to login outside of
Reed's internal network (from the Internet, at large) and still get
access to these various proxied services, and they wanted to be able to
use their same cosignd server for authentication.
The purpose of this patch is to allow Cosign to authenticate requests
made to a proxy server. By default, the Apache2 mod_cosign filter (the
only one we worked with), doesn't handle HTTP proxy requests. (Here's a
snippet of a text doc I wrote up for Reed describing the issue.)
The Problem:
The mod_cosign filter assumes that it is dealing with a normal, non-proxied request of the form:
GET /foo HTTP/1.1 Host www.example.com
In order to get confirmation of this request, cosign redirects the user
to the cosign server, via HTTPS, creates a service cookie and appends a
full URI that the cosign login server can redirect to once the user is
authenticated. To create this URI it appends
scheme://resource-host/path, so for our example above, assuming that
resource /foo is hosted on www.example.com it creates:
https://www.example.com/foo
However if a proxied request of the form:
GET http://www.proxied.com/bar HTTP/1.1 Host www.proxied.com
is requested, this causes problems, because when cosign attempts to 'recreate' a proper return URI to add to the querystring, it comes up with:
https://www.proxied.comhttp//www.proxied.com/bar
The non-parsed uri (http//www.proxied.com/bar - the colon removed) is appended (as if it were just the path info) to a newly constructed scheme and server.
Once cosign validates the user, this mangled url is returned to the proxy server, which, of course, fails to retrieve anything for it.
------
The Patch:
The two changes made are in the attached context diff, and are in the set_cookie_and_redirect() method of the filters/apache2/mod_cosign.c source file.
The first change ensures that cookies associated with an http proxy
request are not secured; otherwise the cookies don't get associated with
the original request and the service never gets athorized, even though
the user authenticates.
Of course, this allows the authenticating cookie for a particular
proxied service to be hijacked by a man-in-the-middle attack. This was
deemed an acceptable risk, since it would only affect a particular
proxied service, and would be subject to timeouts. The actual login
authentication is still over HTTPS since we didn't fiddle with cosignd.
The second change just checks to see if the request object matches a proxy-request, and if so, sets the reference to the original request object's unparsed uri (the original proxy request address).
They're very small changes. It takes longer to explain the reasons than
to apply the work-around :). I don't know if the changes would have a
security impact on an unproxied server or not. And we only tested
against Apache2.
Please let me know if you have any questions. Thank you for the Cosign
work!
Josh
-- Josh Partlow OpenSourcery, LLC jpartlow@xxxxxxxxxxxxxxxx www.osourcery.com
--- ../../cosign-1.8.5/filters/apache2/mod_cosign.c 2005-04-06 13:36:28.000000000 -0700 +++ filters/apache2/mod_cosign.c 2005-06-09 22:35:04.000000000 -0700 @@ -158,6 +158,16 @@ /* returned upon revisit. */ gettimeofday( &now, NULL ); + /* proxy request service cookies should only be secure if the scheme is https */ + if ( r->proxyreq == PROXYREQ_PROXY ) { + if ( r->parsed_uri.scheme && strcmp( r->parsed_uri.scheme, "https") == 0 ) { + full_cookie = apr_psprintf( r->pool, "%s/%lu;;path=/;secure", + my_cookie, now.tv_sec ); + } else { + full_cookie = apr_psprintf( r->pool, "%s/%lu;;path=/", + my_cookie, now.tv_sec ); + } + } else { if ( cfg->http ) { /* living dangerously */ full_cookie = apr_psprintf( r->pool, "%s/%lu;;path=/", my_cookie, now.tv_sec ); @@ -165,6 +175,7 @@ full_cookie = apr_psprintf( r->pool, "%s/%lu;;path=/;secure", my_cookie, now.tv_sec ); } + } /* cookie needs to be set and sent in error headers as * standard headers don't get returned when we redirect, @@ -176,6 +187,10 @@ if ( cfg->siteentry != NULL ) { ref = cfg->siteentry; } else { + /* proxy requests should be redirected exactly as requested */ + if ( r->proxyreq == PROXYREQ_PROXY) { + ref = r->unparsed_uri; + } else { /* live dangerously, we're redirecting to http */ if ( cfg->http ) { if (( port = ap_get_server_port( r )) == 80 ) { @@ -196,6 +211,7 @@ } } } + } dest = apr_psprintf( r->pool, "%s?%s;&%s", cfg->redirect, my_cookie, ref ); apr_table_set( r->headers_out, "Location", dest );