Sorry let me clarify.   I'm looking at doing external policy evaluation of the 
URI like is done is most SSO products.   I have to create a policy for every 
URL the user may hit (with support for wildcards).  I would like to minimize 
the number of policies created.  So while there may be 5 different ways a user 
may type the hostname and port portions of the URI for the same content, I 
would want it to evaluate to just 1 definitive answer that I can create policy 
for (or at least as few as possible).   Plus I need to beware of malicious 
users.  If they set an invalid host header, I don't want a case where apache 
ignores the host header and host header port because it doesn't know about the 
server mentioned in the host header, but the policy code still uses it to do 
policy evaluation. That creates a case where the code would be granting or 
denying access based on the wrong policy.

Example

ServerName foo.com
ServerAlias bob.smith.bar.com *.jones.com

Assume these requests:

GET http://bob.smith.bar.com/cgi-bin/printenv
GET http://mark.jones.com/cgi-bin/printenv

I want all of these evaluated to only http://foo.com/cgi-bin/printenv

Which API's would do this for the server name and host portions?

-Christopher
-----Original Message-----
From: Ray Morris [mailto:[EMAIL PROTECTED]
Sent: Thursday, March 06, 2008 3:32 PM
To: [email protected]
Subject: Re: secure use of ap_get_server_name/port

On 03/06/2008 01:09:37 PM, Nebergall, Christopher wrote:
> I'm looking for secure versions of ap_get_server_name and
> ap_get_server_port which can be trusted to always evaluate to the
> correct host and port for re-constructing the original URL the user
> requested.

  The text part of your question seems to contradict itself regarding what 
you're actually wanting, then the code gives a third result.  Let's be sure 
exactly what you want.  If you really do want to reconstruct the orginal URL 
requested, the hostname will be found in headers_in:


host = apr_pstrdup( r->pool, apr_table_get(r->main->headers_in, "Host") ); if 
(host == NULL) {
    # The client didn't specify a hostname, so punt:
    host = apr_pstrdup( r->pool, ap_get_server_name(r) );
    if (host == NULL) return 0;
}


> I've removed all of the code below which seemed to rely on DNS, or
> info sent from the client.

  I thought you wanted to reconstruct what the client sent, but now you say you 
want to remove any reference to what the client sent?  You're asking for two 
opposite things.



> It seems that if the ServerName directive is there it should return a
> value and that would be it.

   The ServerName may have no relationship at all to the original URL requested 
by the client, which is what you said you wanted.

ServerName foo.com
ServerAlias bob.smith.bar.com

GET http://bob.smith.bar.com/


> I'm confused why there are so many different ways to get the hostname
> or port.

  Assume this configuration and no other hosts on the server for the four 
following requests:

ServerName foo.com
ServerAlias bob.smith.bar.com *.jones.com

CASE 1
Assume this request:
GET http://bob.smith.bar.com/

  There are at least two "correct" answers for the hostname - one can get the 
value of ServerName, as you mentioned, or one cause use the ServerAlias which 
matched the request.
So we need to functions to do the two different things.
Given the possibility of UseCanonicalName, we may want three functions - one 
for the first answer, one for the second answer, and one that respects that 
silly UseCanonicalName directive.

CASE 2
Assume this request:
GET http://joe.jones.com/

  Now we have three hostnames you be interested in - the specified ServerName, 
foo.com, the alias that matched, *.jones.com, and the actual hostname 
requested, joe.jones.com.  Throw in the fact that UseCanonicalName may be on or 
off and you need four functions in order to be able to get whichever answer you 
seek.

CASE 3
Assume noname.com resolves to 123.123.123.123, an IP on this server.

Assume this request:
GET http://noname.com/

  Now we have four possible answers - the value of ServerName, the the 
requested host name, or the match, which is just the IP - or is it an empty 
name?

  I could go on and on, but I think the point is clear - there are a lot of 
ways to get different hostnames, depending on what you're looking for.  You say 
you are confused about why there are so many ways to get the host name, but 
then again you're also confused about which hostname you want - the one from 
the original request or the one from the ServerName directive.
One could also throw in the possibility that this request isn't the orginal 
request, but is a sub-request.
In that case there could up to twelve different answers you may be interested 
in - the four answers from case 4, each regarding THIS request, it's parent, or 
the main original request.

   In most cases, the best one to use is probably the hostname that was 
actually requested for this request:
apr_table_get(r->headers_in, "Host")
There may be a better way to get that information. I'm somewhat new to Apache 
module programming.
--
Ray B. Morris
[EMAIL PROTECTED]

Strongbox - The next generation in site security:
http://www.bettercgi.com/strongbox/




On 03/06/2008 01:09:37 PM, Nebergall, Christopher wrote:
> I'm looking for secure versions of ap_get_server_name and
> ap_get_server_port which can be trusted to always evaluate to the
> correct host and port for re-constructing the original URL the user
> requested.   I've removed all of the code below which seemed to rely
> on DNS, or info sent from the client.  Is the code below a sufficient
> minimal set to get working secure versions of those functions?  I'm
> confused why there are so many different ways to get the hostname or
> port.  It seems that if the ServerName directive is there it should
> return a value and that would be it.   Also why would code like cport
> below ever be zero?
>
> API_EXPORT(const char *) ap_get_server_name2(request_rec *r) {
>         return r->hostname?r->hostname:r->server->server_hostname;
> }
>
> API_EXPORT(unsigned) ap_get_server_port2(const request_rec *r) {
>     unsigned port;
>     unsigned cport = ntohs(r->connection->local_addr.sin_port);
>     port = cport ? cport : r->server->port ? r->server->port :
> ap_default_port(r);
>     return port;
> }
>
> -Christopher
>
> Original apache 1.3 code
>
> ----------------------------------------------------------------------
> -------------------------------------------
> API_EXPORT(const char *) ap_get_server_name(request_rec *r) {
>     conn_rec *conn = r->connection;
>     core_dir_config *d;
>
>     d = (core_dir_config *)ap_get_module_config(r->per_dir_config,
>                                                 &core_module);
>
>     if (d->use_canonical_name == USE_CANONICAL_NAME_OFF) {
>         return r->hostname ? r->hostname :
> r->server->server_hostname;
>     }
>     if (d->use_canonical_name == USE_CANONICAL_NAME_DNS) {
>         if (conn->local_host == NULL) {
>             struct in_addr *iaddr;
>             struct hostent *hptr;
>             int old_stat;
>             old_stat = ap_update_child_status(conn->child_num,
>                                               SERVER_BUSY_DNS, r);
>             iaddr = &(conn->local_addr.sin_addr);
>             hptr = gethostbyaddr((char *)iaddr, sizeof(struct
> in_addr),
>                                  AF_INET);
>             if (hptr != NULL) {
>                 conn->local_host = ap_pstrdup(conn->pool,
>                                               (void *)hptr->h_name);
>                 ap_str_tolower(conn->local_host);
>             }
>             else {
>                 conn->local_host = ap_pstrdup(conn->pool,
>
> r->server->server_hostname);
>             }
>             (void) ap_update_child_status(conn->child_num, old_stat,
> r);
>         }
>         return conn->local_host;
>     }
>     /* default */
>     return r->server->server_hostname; }
>
> API_EXPORT(unsigned) ap_get_server_port(const request_rec *r) {
>     unsigned port;
>     unsigned cport = ntohs(r->connection->local_addr.sin_port);
>     core_dir_config *d =
>       (core_dir_config *)ap_get_module_config(r->per_dir_config,
> &core_module);
>
>     if (d->use_canonical_name == USE_CANONICAL_NAME_OFF
>         || d->use_canonical_name == USE_CANONICAL_NAME_DNS) {
>
>         /* With UseCanonicalName Off Apache will form self-referential
>          * URLs using the hostname and port supplied by the client if
>          * any are supplied (otherwise it will use the canonical
> name).
>          */
>         port = r->parsed_uri.port_str ? r->parsed_uri.port :
>           cport ? cport :
>             r->server->port ? r->server->port :
>               ap_default_port(r);
>     } else { /* d->use_canonical_name == USE_CANONICAL_NAME_ON */
>         port = r->server->port ? r->server->port :
>           cport ? cport :
>             ap_default_port(r);
>     }
>
>     /* default */
>     return port;
> }
>
>



Reply via email to