On Wed, Apr 28, 2021 at 08:18:47AM -0400, Dave Voutila wrote:
> 
> Claudio Jeker writes:
> 
> > Another thing to consider is that X-Forwarded headers should only be
> > accepted from trusted sources. I don't think this particular usage of
> > X-Forwarded-Proto is probelmatic. In the end for this particular case of
> > redirect using a relative URL seems to be a better choice since it will
> > preserve the host, port and proto from the original requests without any
> > configuration magic.
> 
> Here's a quick effort to test out the idea. Not sure I like it yet...but
> figured this could help move discussion forward. (Not looking for an OK
> yet as I doubt this config style is good yet.)
> 
> Couple points:
>   * the srvflag bitmap is sort of at the semantic breaking point as a
>     uint32_t...hesitant to bump it to uint64_t just to allow better flag
>     groupings but that's a thought
> 
>   * not sure i like my config style...maybe (yet another) optional token
>     or two in the "auto index" pattern instead?
> 
> Quick example config folks can test with. First `# cp -R /var/www /tmp`
> and then stage some files there for your enjoyment.
> 
> chroot "/tmp/www"
> server "default" {
>       listen on * port 80
>       directory {
>               auto index
>               relative redirects
>       }
> }
> 
> Example without "relative redirects":
> 
> ~ $ curl -i localhost/bgplg
> HTTP/1.0 301 Moved Permanently
> Server: OpenBSD httpd
> Connection: close
> Content-Type: text/html
> Content-Length: 510
> Location: http://localhost/bgplg/
> 
> With "relative redirects":
> 
> ~ $ curl -i localhost/bgplg
> HTTP/1.0 301 Moved Permanently
> Server: OpenBSD httpd
> Connection: close
> Content-Type: text/html
> Content-Length: 510
> Location: /bgplg/
> 

To be honest I feel this is total overkill. This is an automatic redirect
from /foo/bar to /foo/bar/ when accessing directories that have an index
file or have auto index on. It is one very specific case of redirect that
never changes the host, port or protocol. I see no reason why this can't
default to a relative redirect (but using an absolute path).

Are there clients in the wild that fail to handle such a redirect?


> Index: usr.sbin/httpd/httpd.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/httpd/httpd.h,v
> retrieving revision 1.156
> diff -u -p -r1.156 httpd.h
> --- usr.sbin/httpd/httpd.h    20 Apr 2021 21:11:56 -0000      1.156
> +++ usr.sbin/httpd/httpd.h    28 Apr 2021 12:10:18 -0000
> @@ -392,6 +392,7 @@ SPLAY_HEAD(client_tree, client);
>  #define SRVFLAG_DEFAULT_TYPE 0x00800000
>  #define SRVFLAG_PATH_REWRITE 0x01000000
>  #define SRVFLAG_NO_PATH_REWRITE      0x02000000
> +#define SRVFLAG_RELATIVE_REDIR       0x04000000
>  #define SRVFLAG_LOCATION_FOUND       0x40000000
>  #define SRVFLAG_LOCATION_NOT_FOUND 0x80000000
> 
> @@ -401,7 +402,7 @@ SPLAY_HEAD(client_tree, client);
>       "\14SYSLOG\15NO_SYSLOG\16TLS\17ACCESS_LOG\20ERROR_LOG"          \
>       "\21AUTH\22NO_AUTH\23BLOCK\24NO_BLOCK\25LOCATION_MATCH"         \
>       "\26SERVER_MATCH\27SERVER_HSTS\30DEFAULT_TYPE\31PATH\32NO_PATH" \
> -     "\37LOCATION_FOUND\40LOCATION_NOT_FOUND"
> +     "\33RELATIVE_REDIR\37LOCATION_FOUND\40LOCATION_NOT_FOUND"
> 
>  #define TCPFLAG_NODELAY              0x01
>  #define TCPFLAG_NNODELAY     0x02
> Index: usr.sbin/httpd/parse.y
> ===================================================================
> RCS file: /cvs/src/usr.sbin/httpd/parse.y,v
> retrieving revision 1.125
> diff -u -p -r1.125 parse.y
> --- usr.sbin/httpd/parse.y    10 Apr 2021 10:10:07 -0000      1.125
> +++ usr.sbin/httpd/parse.y    28 Apr 2021 12:10:18 -0000
> @@ -137,9 +137,10 @@ typedef struct {
>  %token       ACCESS ALIAS AUTO BACKLOG BODY BUFFER CERTIFICATE CHROOT 
> CIPHERS COMMON
>  %token       COMBINED CONNECTION DHE DIRECTORY ECDHE ERR FCGI INDEX IP KEY 
> LIFETIME
>  %token       LISTEN LOCATION LOG LOGDIR MATCH MAXIMUM NO NODELAY OCSP ON 
> PORT PREFORK
> -%token       PROTOCOLS REQUESTS ROOT SACK SERVER SOCKET STRIP STYLE SYSLOG 
> TCP TICKET
> -%token       TIMEOUT TLS TYPE TYPES HSTS MAXAGE SUBDOMAINS DEFAULT PRELOAD 
> REQUEST
> -%token       ERROR INCLUDE AUTHENTICATE WITH BLOCK DROP RETURN PASS REWRITE
> +%token       PROTOCOLS REDIRECTS RELATIVE REQUESTS ROOT SACK SERVER SOCKET 
> STRIP
> +%token       STYLE SYSLOG TCP TICKET TIMEOUT TLS TYPE TYPES HSTS MAXAGE 
> SUBDOMAINS
> +%token       DEFAULT PRELOAD REQUEST ERROR INCLUDE AUTHENTICATE WITH BLOCK 
> DROP
> +%token       RETURN PASS REWRITE
>  %token       CA CLIENT CRL OPTIONAL PARAM FORWARDED FOUND NOT
>  %token       <v.string>      STRING
>  %token  <v.number>   NUMBER
> @@ -1038,7 +1039,11 @@ dirflags       : INDEX STRING          {
>                       srv_conf->flags &= ~SRVFLAG_AUTO_INDEX;
>                       srv_conf->flags |= SRVFLAG_NO_AUTO_INDEX;
>               }
> -             ;
> +             | RELATIVE REDIRECTS    {
> +                     srv_conf->flags &= ~SRVFLAG_RELATIVE_REDIR;
> +                     srv_conf->flags |= SRVFLAG_RELATIVE_REDIR;
> +             }
> +     ;
> 
> 
>  logformat    : LOG logflags
> @@ -1425,6 +1430,8 @@ lookup(char *s)
>               { "prefork",            PREFORK },
>               { "preload",            PRELOAD },
>               { "protocols",          PROTOCOLS },
> +             { "redirects",          REDIRECTS },
> +             { "relative",           RELATIVE },
>               { "request",            REQUEST },
>               { "requests",           REQUESTS },
>               { "return",             RETURN },
> Index: usr.sbin/httpd/server_file.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/httpd/server_file.c,v
> retrieving revision 1.69
> diff -u -p -r1.69 server_file.c
> --- usr.sbin/httpd/server_file.c      16 Mar 2021 06:44:14 -0000      1.69
> +++ usr.sbin/httpd/server_file.c      28 Apr 2021 12:10:18 -0000
> @@ -85,13 +85,17 @@ server_file_access(struct httpd *env, st
>               if (path[strlen(path) - 1] != '/') {
>                       if ((encodedpath = url_encode(desc->http_path)) == NULL)
>                               return (500);
> -                     if (asprintf(&newpath, "http%s://%s%s/",
> -                         srv_conf->flags & SRVFLAG_TLS ? "s" : "",
> -                         desc->http_host, encodedpath) == -1) {
> -                             free(encodedpath);
> -                             return (500);
> -                     }
> +
> +                     if (srv_conf->flags & SRVFLAG_RELATIVE_REDIR)
> +                             ret = asprintf(&newpath, "%s/", encodedpath);
> +                     else
> +                             ret = asprintf(&newpath, "http%s://%s%s/",
> +                                 srv_conf->flags & SRVFLAG_TLS ? "s" : "",
> +                                 desc->http_host, encodedpath);
> +
>                       free(encodedpath);
> +                     if (ret < 0)
> +                             return (500);
> 
>                       /* Path alias will be used for the redirection */
>                       desc->http_path_alias = newpath;
> 

-- 
:wq Claudio

Reply via email to