diff options
author | Omar Polo <op@omarpolo.com> | 2023-07-23 18:45:05 +0000 |
---|---|---|
committer | Omar Polo <op@omarpolo.com> | 2023-07-23 18:45:05 +0000 |
commit | a1ba9650a9f0cc0d9e70800d71769d32f927b939 (patch) | |
tree | 4ce8a9b5e4cd3aff8a41d4cd67c15f7c07774b17 | |
parent | f36ba9be59c1b60aff4b9663f49d8656800afa00 (diff) |
revamp fastcgi configuration: make it per-location
this revamps the syntax in the configuration to better match httpd(8)
(and in general be less weird) and to allow per-location fastcgi
configurations.
the bare `param' is now deprecated, but for compatibility it acts
like `fastcgi param' would do now. Same story for `fastcgi <pathÂ>'.
-rw-r--r-- | config.c | 30 | ||||
-rw-r--r-- | fcgi.c | 4 | ||||
-rw-r--r-- | gmid.conf.5 | 127 | ||||
-rw-r--r-- | gmid.h | 6 | ||||
-rw-r--r-- | parse.y | 55 | ||||
-rw-r--r-- | server.c | 19 | ||||
-rw-r--r-- | utils.c | 2 |
7 files changed, 136 insertions, 107 deletions
@@ -97,11 +97,11 @@ config_purge(struct conf *conf) free(l->reqca_path); X509_STORE_free(l->reqca); free(l); - } - TAILQ_FOREACH_SAFE(e, &h->params, envs, te) { - TAILQ_REMOVE(&h->params, e, envs); - free(e); + TAILQ_FOREACH_SAFE(e, &l->params, envs, te) { + TAILQ_REMOVE(&l->params, e, envs); + free(e); + } } TAILQ_FOREACH_SAFE(a, &h->aliases, aliases, ta) { @@ -363,12 +363,12 @@ config_send(struct conf *conf) if (config_send_file(ps, PROC_SERVER, IMSG_RECONF_LOC, fd, &lcopy, sizeof(lcopy)) == -1) return -1; - } - TAILQ_FOREACH(e, &h->params, envs) { - if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_ENV, - e, sizeof(*e)) == -1) - return -1; + TAILQ_FOREACH(e, &l->params, envs) { + if (proc_compose(ps, PROC_SERVER, + IMSG_RECONF_ENV, e, sizeof(*e)) == -1) + return -1; + } } if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1) @@ -501,6 +501,7 @@ int config_recv(struct conf *conf, struct imsg *imsg) { static struct vhost *h; + static struct location *l; static struct proxy *p; struct privsep *ps = conf->ps; struct etm m; @@ -570,7 +571,8 @@ config_recv(struct conf *conf, struct imsg *imsg) h = vh; TAILQ_INSERT_TAIL(&conf->hosts, h, vhosts); - /* reset proxy */ + /* reset location and proxy */ + l = NULL; p = NULL; break; @@ -633,6 +635,7 @@ config_recv(struct conf *conf, struct imsg *imsg) IMSG_SIZE_CHECK(imsg, loc); loc = xcalloc(1, sizeof(*loc)); memcpy(loc, imsg->data, datalen); + TAILQ_INIT(&loc->params); if (imsg->fd != -1) { if (load_file(imsg->fd, &d, &len) == -1) @@ -643,16 +646,17 @@ config_recv(struct conf *conf, struct imsg *imsg) free(d); } + l = loc; TAILQ_INSERT_TAIL(&h->locations, loc, locations); break; case IMSG_RECONF_ENV: - if (h == NULL) - fatalx("recv'd env without host"); + if (l == NULL) + fatalx("recv'd env without location"); IMSG_SIZE_CHECK(imsg, env); env = xcalloc(1, sizeof(*env)); memcpy(env, imsg->data, datalen); - TAILQ_INSERT_TAIL(&h->params, env, envs); + TAILQ_INSERT_TAIL(&l->params, env, envs); break; case IMSG_RECONF_ALIAS: @@ -371,7 +371,7 @@ fcgi_error(struct bufferevent *bev, short err, void *d) } void -fcgi_req(struct client *c) +fcgi_req(struct client *c, struct location *loc) { char buf[22]; char *qs; @@ -398,7 +398,7 @@ fcgi_req(struct client *c) free(qs); } - TAILQ_FOREACH(p, &c->host->params, envs) { + TAILQ_FOREACH(p, &loc->params, envs) { fcgi_send_param(c->cgibev, p->name, p->value); } diff --git a/gmid.conf.5 b/gmid.conf.5 index 07e58e0..8e81498 100644 --- a/gmid.conf.5 +++ b/gmid.conf.5 @@ -212,10 +212,17 @@ If not specified, the .Ic default type is set to .Dq application/octet-stream . -.It Ic fastcgi Oo Ic tcp Oc Ar socket Oo Cm port Ar port Oc -Enable -.Sx FastCGI -instead of serving files. +.It Ic fastcgi Ar option +Enable FastCGI instead of serving files. +Multiple options may be specified within curly braces. +Valid options are: +.Bl -tag -width Ds +.It Ic param Ar name Cm = Ar value +Set the param +.Ar name +to +.Ar value . +.It Ic socket Oo Ic tcp Oc Ar socket Oo Cm port Ar port Oc The .Ar socket can either be a UNIX-domain socket or a TCP socket. @@ -234,64 +241,9 @@ is interpreted as a hostname or an IP address. can be either a port number or the name of a service enclosed in double quotes. If not specified defaults to 9000. -.It Ic index Ar string -Set the directory index file. -If not specified, it defaults to -.Pa index.gmi . -.It Ic key Ar file -Specify the private key to use for this server. -.Ar file -should contain a PEM encoded private key. -This option is mandatory. -.It Ic lang Ar string -Specify the language tag for the text/gemini content served. -If not specified, no -.Dq lang -parameter will be added in the response. -.It Ic listen on Ar address Op Ic port Ar number -Set the listen -.Ar address -and -.Ar port -which defaults to -.Sq 1965 . -This statement can be specified multiple times. -If -.Ar address -is -.Sq * -then -.Xr gmid 8 -will listen on all IPv4 and IPv6 addresses. -.Ar 0.0.0.0 -can be used to listen on all IPv4 addresses and -.Ar :: -on all IPv6 addresses. -.It Ic location Ar path Brq ... -Specify server configuration rules for a specific location. -.Ar path -argument will be matched against the request path with shell globbing -rules. -In case of multiple location statements in the same context, the first -matching location will be put into effect and the later ones ignored. -Therefore is advisable to match for more specific paths first and for -generic ones later on. -A -.Ic location -section may include most of the server configuration rules -except -.Ic alias , Ic cert , Ic key , Ic listen , Ic location , Ic param -and -.Ic proxy . -.It Ic log Ar bool -Enable or disable the logging for the current server or location block. -.It Ic param Ar name Cm = Ar value -Set the param -.Ar name -to -.Ar value -for FastCGI. -By default the following parameters are defined: +.El +.Pp +The FastCGI handler will be given the following variables by default: .Bl -tag -width 24m .It Ev GATEWAY_INTERFACE .Dq CGI/1.1 @@ -368,6 +320,57 @@ certificate in the ISO 8601 format The time corresponding to the start of the validity period of the peer certificate in the ISO 8601 format. .El +.It Ic index Ar string +Set the directory index file. +If not specified, it defaults to +.Pa index.gmi . +.It Ic key Ar file +Specify the private key to use for this server. +.Ar file +should contain a PEM encoded private key. +This option is mandatory. +.It Ic lang Ar string +Specify the language tag for the text/gemini content served. +If not specified, no +.Dq lang +parameter will be added in the response. +.It Ic listen on Ar address Op Ic port Ar number +Set the listen +.Ar address +and +.Ar port +which defaults to +.Sq 1965 . +This statement can be specified multiple times. +If +.Ar address +is +.Sq * +then +.Xr gmid 8 +will listen on all IPv4 and IPv6 addresses. +.Ar 0.0.0.0 +can be used to listen on all IPv4 addresses and +.Ar :: +on all IPv6 addresses. +.It Ic location Ar path Brq ... +Specify server configuration rules for a specific location. +.Ar path +argument will be matched against the request path with shell globbing +rules. +In case of multiple location statements in the same context, the first +matching location will be put into effect and the later ones ignored. +Therefore is advisable to match for more specific paths first and for +generic ones later on. +A +.Ic location +section may include most of the server configuration rules +except +.Ic alias , Ic cert , Ic key , Ic listen , Ic location +and +.Ic proxy . +.It Ic log Ar bool +Enable or disable the logging for the current server or location block. .It Ic ocsp Ar file Specify an OCSP response to be stapled during TLS handshakes with this server. @@ -175,6 +175,7 @@ struct location { X509_STORE *reqca; int disable_log; int fcgi; + struct envhead params; char dir[PATH_MAX]; int dirfd; @@ -209,7 +210,6 @@ struct vhost { */ struct lochead locations; - struct envhead params; struct aliashead aliases; struct proxyhead proxies; }; @@ -389,7 +389,7 @@ const char *vhost_default_mime(struct vhost*, const char*); const char *vhost_index(struct vhost*, const char*); int vhost_auto_index(struct vhost*, const char*); int vhost_block_return(struct vhost*, const char*, int*, const char**); -int vhost_fastcgi(struct vhost*, const char*); +struct location *vhost_fastcgi(struct vhost*, const char*); int vhost_dirfd(struct vhost*, const char*, size_t*); int vhost_strip(struct vhost*, const char*); X509_STORE *vhost_require_ca(struct vhost*, const char*); @@ -418,7 +418,7 @@ int select_non_dotdot(const struct dirent*); void fcgi_read(struct bufferevent *, void *); void fcgi_write(struct bufferevent *, void *); void fcgi_error(struct bufferevent *, short, void *); -void fcgi_req(struct client *); +void fcgi_req(struct client *, struct location *); /* sandbox.c */ void sandbox_main_process(void); @@ -133,7 +133,7 @@ typedef struct { %token OCSP OFF ON %token PARAM PORT PREFORK PROTO PROTOCOLS PROXY %token RELAY_TO REQUIRE RETURN ROOT -%token SERVER SNI STRIP +%token SERVER SNI SOCKET STRIP %token TCP TOEXT TYPE TYPES %token USE_TLS USER %token VERIFYNAME @@ -326,6 +326,8 @@ servopt : ALIAS string { host->ocsp_path = $2; } | PARAM string '=' string { + yywarn("the top-level `param' directive is deprecated." + " Please use `fastcgi { param ... }`"); add_param($2, $4); } | LISTEN ON listen_addr { @@ -465,7 +467,7 @@ locopt : AUTO INDEX bool { loc->auto_index = $3 ? 1 : -1; } sizeof(loc->default_mime)); free($3); } - | FASTCGI fastcgi + | fastcgi | INDEX string { (void) strlcpy(loc->index, $2, sizeof(loc->index)); free($2); @@ -487,26 +489,44 @@ locopt : AUTO INDEX bool { loc->auto_index = $3 ? 1 : -1; } | STRIP NUM { loc->strip = check_strip_no($2); } ; -fastcgi : string { - loc->fcgi = fastcgi_conf($1, NULL); - free($1); +fastcgi : FASTCGI '{' optnl fastcgiopts '}' + | FASTCGI fastcgiopt + | FASTCGI string { + yywarn("`fastcgi path' is deprecated. " + "Please use `fastcgi socket path' instead."); + loc->fcgi = fastcgi_conf($2, NULL); + free($2); + } + | error '}' + ; + +fastcgiopts : /* empty */ + | fastcgiopts fastcgiopt optnl + ; + +fastcgiopt : PARAM string '=' string { + add_param($2, $4); } - | TCP string PORT NUM { + | SOCKET string { + loc->fcgi = fastcgi_conf($2, NULL); + free($2); + } + | SOCKET TCP string PORT NUM { char *c; - if (asprintf(&c, "%d", $4) == -1) + + if (asprintf(&c, "%d", $5) == -1) fatal("asprintf"); - loc->fcgi = fastcgi_conf($2, c); - free($2); + loc->fcgi = fastcgi_conf($3, c); + free($3); free(c); } - | TCP string { - loc->fcgi = fastcgi_conf($2, "9000"); - free($2); + | SOCKET TCP string { + loc->fcgi = fastcgi_conf($3, "9000"); } - | TCP string PORT string { - loc->fcgi = fastcgi_conf($2, $4); - free($2); - free($4); + | SOCKET TCP string PORT string { + loc->fcgi = fastcgi_conf($3, $5); + free($3); + free($5); } ; @@ -586,6 +606,7 @@ static const struct keyword { {"root", ROOT}, {"server", SERVER}, {"sni", SNI}, + {"socket", SOCKET}, {"strip", STRIP}, {"tcp", TCP}, {"to-ext", TOEXT}, @@ -1183,7 +1204,7 @@ void add_param(char *name, char *val) { struct envlist *e; - struct envhead *h = &host->params; + struct envhead *h = &loc->params; e = xcalloc(1, sizeof(*e)); (void) strlcpy(e->name, name, sizeof(e->name)); @@ -243,23 +243,23 @@ vhost_block_return(struct vhost *v, const char *path, int *code, const char **fm return loc->block_code != 0; } -int +struct location * vhost_fastcgi(struct vhost *v, const char *path) { struct location *loc; if (v == NULL || path == NULL) - return -1; + return NULL; loc = TAILQ_FIRST(&v->locations); while ((loc = TAILQ_NEXT(loc, locations)) != NULL) { if (loc->fcgi != -1) if (matches(loc->match, path)) - return loc->fcgi; + return loc; } loc = TAILQ_FIRST(&v->locations); - return loc->fcgi; + return loc->fcgi == -1 ? NULL : loc; } int @@ -705,20 +705,21 @@ fcgi_open_conn(struct fcgi *f) static int apply_fastcgi(struct client *c) { - int id, i = 0; + int i = 0; struct fcgi *f; + struct location *loc; - if ((id = vhost_fastcgi(c->host, c->iri.path)) == -1) + if ((loc = vhost_fastcgi(c->host, c->iri.path)) == NULL) return 0; TAILQ_FOREACH(f, &c->conf->fcgi, fcgi) { - if (i == id) + if (i == loc->fcgi) break; ++i; } if (f == NULL) { - log_warnx("can't find fcgi #%d", id); + log_warnx("can't find fcgi #%d", loc->fcgi); return 0; } @@ -745,7 +746,7 @@ apply_fastcgi(struct client *c) } bufferevent_enable(c->cgibev, EV_READ|EV_WRITE); - fcgi_req(c); + fcgi_req(c, loc); return 1; } @@ -348,7 +348,6 @@ new_vhost(void) h = xcalloc(1, sizeof(*h)); TAILQ_INIT(&h->addrs); TAILQ_INIT(&h->locations); - TAILQ_INIT(&h->params); TAILQ_INIT(&h->aliases); TAILQ_INIT(&h->proxies); return h; @@ -362,6 +361,7 @@ new_location(void) l = xcalloc(1, sizeof(*l)); l->dirfd = -1; l->fcgi = -1; + TAILQ_INIT(&l->params); return l; } |