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) &&