On Mon, Dec 05, 2016 at 04:20:02PM +0200, Gregory Edigarov wrote:
> Hello,
> 
> I know, it considered featuritis, but still, hey, it should go somewhere.
> This diff is based on the diff sent here by Stanislav Adaszewski
> (s.adaszev...@gmail.com),
> some time ago.
> I've added one option 'test', i.e.: pass rewrite [test] index.php?q=%1, so
> it will not rewrite
> if file or directory present, and a manual page section, describing the
> rule.
> For those like me, trying to stick with base as much as possible.
> 
> suggestions?
> 

Hello,

The diff is malformed and cannot be applied.
The patch below is re-based against -current.
I exclude the httpd.conf example bits.
They can be added later as separate patch.

Index: httpd.conf.5
===================================================================
RCS file: /home/vlado/cvsync/cvsroot/src/usr.sbin/httpd/httpd.conf.5,v
retrieving revision 1.76
diff -u -p -r1.76 httpd.conf.5
--- httpd.conf.5        14 Nov 2016 10:28:31 -0000      1.76
+++ httpd.conf.5        6 Jan 2017 09:47:53 -0000
@@ -388,6 +388,8 @@ The pattern may contain captures that ca
 .Ar uri
 of an enclosed
 .Ic block return
+or
+.Ic pass rewrite
 option.
 .It Oo Ic no Oc Ic log Op Ar option
 Set the specified logging options.
@@ -446,6 +448,17 @@ instead of the log files.
 Disable any previous
 .Ic block
 in a location.
+.It Ic pass rewrite Oo Ic test Oc Ic Ar uri
+Disable any previous block in location, the path gets rewritten as 
+specified in
+.Ic block return
+statement. If
+.Ic test
+option is present, the rewrite will
+.Em not
+happen if file or directory referenced by the
+.Ar uri
+present.
 .It Ic root Ar option
 Configure the document root and options for the request path.
 Valid options are:
Index: httpd.h
===================================================================
RCS file: /home/vlado/cvsync/cvsroot/src/usr.sbin/httpd/httpd.h,v
retrieving revision 1.124
diff -u -p -r1.124 httpd.h
--- httpd.h     17 Nov 2016 14:52:48 -0000      1.124
+++ httpd.h     6 Jan 2017 09:47:53 -0000
@@ -73,6 +73,7 @@
 #define SERVER_MAX_PREFETCH    256
 #define SERVER_MIN_PREFETCHED  32
 #define SERVER_HSTS_DEFAULT_AGE        31536000
+#define SERVER_MAX_RECUR_REWR  0
 
 #define MEDIATYPE_NAMEMAX      128     /* file name extension */
 #define MEDIATYPE_TYPEMAX      64      /* length of type/subtype */
@@ -364,13 +365,15 @@ SPLAY_HEAD(client_tree, client);
 #define SRVFLAG_SERVER_MATCH   0x00200000
 #define SRVFLAG_SERVER_HSTS    0x00400000
 #define SRVFLAG_DEFAULT_TYPE   0x00800000
+#define SRVFLAG_REWRITE                0x01000000
+#define SRVFLAG_TEST           0x02000000
 
 #define SRVFLAG_BITS                                                   \
        "\10\01INDEX\02NO_INDEX\03AUTO_INDEX\04NO_AUTO_INDEX"           \
        "\05ROOT\06LOCATION\07FCGI\10NO_FCGI\11LOG\12NO_LOG\13SOCKET"   \
        "\14SYSLOG\15NO_SYSLOG\16TLS\17ACCESS_LOG\20ERROR_LOG"          \
        "\21AUTH\22NO_AUTH\23BLOCK\24NO_BLOCK\25LOCATION_MATCH"         \
-       "\26SERVER_MATCH\27SERVER_HSTS\30DEFAULT_TYPE"
+       "\26SERVER_MATCH\27SERVER_HSTS\30DEFAULT_TYPE\31REWRITE\32TEST"
 
 #define TCPFLAG_NODELAY                0x01
 #define TCPFLAG_NNODELAY       0x02
@@ -472,6 +475,7 @@ struct server_config {
        int                      return_code;
        char                    *return_uri;
        off_t                    return_uri_len;
+       char                     rewrite_uri[PATH_MAX];
 
        int                      hsts_max_age;
        uint8_t                  hsts_flags;
Index: parse.y
===================================================================
RCS file: /home/vlado/cvsync/cvsroot/src/usr.sbin/httpd/parse.y,v
retrieving revision 1.87
diff -u -p -r1.87 parse.y
--- parse.y     5 Jan 2017 13:53:09 -0000       1.87
+++ parse.y     6 Jan 2017 09:47:53 -0000
@@ -134,7 +134,7 @@ typedef struct {
 %token LOCATION LOG LOGDIR MATCH MAXIMUM NO NODELAY OCSP ON PORT PREFORK
 %token PROTOCOLS REQUESTS ROOT SACK SERVER SOCKET STRIP STYLE SYSLOG TCP 
TIMEOUT
 %token TLS TYPE TYPES HSTS MAXAGE SUBDOMAINS DEFAULT PRELOAD REQUEST
-%token ERROR INCLUDE AUTHENTICATE WITH BLOCK DROP RETURN PASS
+%token ERROR INCLUDE AUTHENTICATE WITH BLOCK DROP RETURN PASS REWRITE TEST
 %token <v.string>      STRING
 %token  <v.number>     NUMBER
 %type  <v.port>        port
@@ -971,6 +971,29 @@ filter             : block RETURN NUMBER optstring 
                        /* Forbidden */
                        srv_conf->return_code = 403;
                }
+               | PASS REWRITE STRING           {
+                       srv_conf->flags |= SRVFLAG_REWRITE;
+                       if (strlcpy(srv_conf->rewrite_uri, $3,
+                               sizeof(srv_conf->rewrite_uri)) >=
+                               sizeof(srv_conf->rewrite_uri)) {
+                               yyerror("url rewrite string too long");
+                               free($3);
+                               YYERROR;
+                       }
+                       free($3);
+               }
+               | PASS REWRITE TEST STRING    {
+                       srv_conf->flags |= SRVFLAG_REWRITE;
+                       srv_conf->flags |= SRVFLAG_TEST;
+                       if (strlcpy(srv_conf->rewrite_uri, $4,
+                               sizeof(srv_conf->rewrite_uri)) >=
+                               sizeof(srv_conf->rewrite_uri)) {
+                               yyerror("url rewrite string too long");
+                               free($4);
+                               YYERROR;
+                       }
+                       free($4);
+               }
                | PASS                          {
                        srv_conf->flags &= ~SRVFLAG_BLOCK;
                        srv_conf->flags |= SRVFLAG_NO_BLOCK;
@@ -1231,6 +1254,7 @@ lookup(char *s)
                { "request",            REQUEST },
                { "requests",           REQUESTS },
                { "return",             RETURN },
+               { "rewrite",            REWRITE },
                { "root",               ROOT },
                { "sack",               SACK },
                { "server",             SERVER },
@@ -1240,6 +1264,7 @@ lookup(char *s)
                { "subdomains",         SUBDOMAINS },
                { "syslog",             SYSLOG },
                { "tcp",                TCP },
+               { "test",               TEST },
                { "timeout",            TIMEOUT },
                { "tls",                TLS },
                { "type",               TYPE },
Index: server_http.c
===================================================================
RCS file: /home/vlado/cvsync/cvsroot/src/usr.sbin/httpd/server_http.c,v
retrieving revision 1.110
diff -u -p -r1.110 server_http.c
--- server_http.c       26 Aug 2016 10:46:39 -0000      1.110
+++ server_http.c       6 Jan 2017 09:47:53 -0000
@@ -20,6 +20,7 @@
 #include <sys/queue.h>
 #include <sys/socket.h>
 #include <sys/tree.h>
+#include <sys/stat.h>
 
 #include <netinet/in.h>
 #include <arpa/inet.h>
@@ -1039,7 +1040,7 @@ server_expand_http(struct client *clt, c
 int
 server_response(struct httpd *httpd, struct client *clt)
 {
-       char                     path[PATH_MAX];
+       char                     path[PATH_MAX],d_path[PATH_MAX];
        char                     hostname[HOST_NAME_MAX+1];
        struct http_descriptor  *desc = clt->clt_descreq;
        struct http_descriptor  *resp = clt->clt_descresp;
@@ -1047,9 +1048,12 @@ server_response(struct httpd *httpd, str
        struct server_config    *srv_conf = &srv->srv_conf;
        struct kv               *kv, key, *host;
        struct str_find          sm;
+       struct stat              st;
        int                      portval = -1, ret;
        char                    *hostval;
        const char              *errstr = NULL;
+       char                     buf[IBUF_READ_SIZE];
+       int                      n;
 
        /* Canonicalize the request path */
        if (desc->http_path == NULL ||
@@ -1154,6 +1158,75 @@ server_response(struct httpd *httpd, str
        /* Now search for the location */
        srv_conf = server_getlocation(clt, desc->http_path);
 
+       /* URL Rewriting logic */
+       DPRINTF("%s: URL Rewriting logic, flags: %08X, rewrite_uri: %s, "
+               "http_path: %s\n", __func__, srv_conf->flags,
+               srv_conf->rewrite_uri, desc->http_path);
+       for (n = 0; srv_conf->flags & SRVFLAG_REWRITE; n++) {
+               if (n > SERVER_MAX_RECUR_REWR) {
+                       server_abort_http(clt, 500, "recursive "
+                       "rewrite limit exceeded");
+                       return (-1);
+               }
+               if (srv_conf->flags & SRVFLAG_TEST) {
+                       snprintf(d_path,PATH_MAX,"%s%s",srv_conf->root,path);
+                       if (stat(d_path,&st)) {
+                               DPRINTF("%s: Rewrite test from: %s to %s, n: 
%d\n", 
+                                  __func__, desc->http_path, 
srv_conf->rewrite_uri, n);
+                               if (server_expand_http(clt, 
srv_conf->rewrite_uri, buf,
+                                  sizeof(buf)) == NULL) {
+                                       server_abort_http(clt, 500, 
strerror(errno));
+                                       return (-1);
+                               }
+                               if (desc->http_path != NULL) {
+                                       free(desc->http_path);
+                                       desc->http_path = NULL;
+                               }
+                               desc->http_path = strdup(buf);
+                               if (desc->http_path == NULL) {
+                                       server_abort_http(clt, 500, 
strerror(errno));
+                                       return (-1);
+                               }
+                               desc->http_query = strchr(desc->http_path, '?');
+                               if (desc->http_query != NULL) {
+                                       *desc->http_query++ = '\0';
+                                       desc->http_query = 
strdup(desc->http_query);
+                                       if (desc->http_query == NULL) {
+                                               server_abort_http(clt, 500, 
strerror(errno));
+                                       }
+                               }
+                       srv_conf = server_getlocation(clt, desc->http_path);
+                       }
+                       else break;
+               } else {
+                       DPRINTF("%s: Rewrite from: %s to %s, n: %d\n", __func__,
+                          desc->http_path, srv_conf->rewrite_uri, n);
+                       if (server_expand_http(clt, srv_conf->rewrite_uri, buf,
+                          sizeof(buf)) == NULL) {
+                               server_abort_http(clt, 500, strerror(errno));
+                               return (-1);
+                       }
+                       if (desc->http_path != NULL) {
+                               free(desc->http_path);
+                               desc->http_path = NULL;
+                       }
+                       desc->http_path = strdup(buf);
+                       if (desc->http_path == NULL) {
+                               server_abort_http(clt, 500, strerror(errno));
+                               return (-1);
+                       }
+                       desc->http_query = strchr(desc->http_path, '?');
+                       if (desc->http_query != NULL) {
+                               *desc->http_query++ = '\0';
+                               desc->http_query = strdup(desc->http_query);
+                               if (desc->http_query == NULL) {
+                                       server_abort_http(clt, 500, 
strerror(errno));
+                               }
+                       }
+                       srv_conf = server_getlocation(clt, desc->http_path);
+               }
+       }
+
        if (srv_conf->flags & SRVFLAG_BLOCK) {
                server_abort_http(clt, srv_conf->return_code,
                    srv_conf->return_uri);
@@ -1196,8 +1269,10 @@ server_getlocation(struct client *clt, c
        TAILQ_FOREACH(location, &srv->srv_hosts, entry) {
 #ifdef DEBUG
                if (location->flags & SRVFLAG_LOCATION) {
-                       DPRINTF("%s: location \"%s\" path \"%s\"",
-                           __func__, location->location, path);
+                       DPRINTF("%s: location \"%s\" path \"%s\" flags: %08X "
+                          "rewrite_uri: %s",
+                          __func__, location->location, path, location->flags,
+                          location->rewrite_uri);
                }
 #endif
                if ((location->flags & SRVFLAG_LOCATION) &&


Attachment: signature.asc
Description: PGP signature

Reply via email to