commit a1ba9650a9f0cc0d9e70800d71769d32f927b939 from: Omar Polo date: Sun Jul 23 18:45:05 2023 UTC 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 '. commit - f36ba9be59c1b60aff4b9663f49d8656800afa00 commit + a1ba9650a9f0cc0d9e70800d71769d32f927b939 blob - 0eac060cab77e8d58cf641739431835a8beab823 blob + 3b84aa40f0805acd04d2af75d2f68d218db79a57 --- config.c +++ config.c @@ -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: blob - 7a141a58fe7808af08033bb33aa9643e5e19b143 blob + 281dfaa37bc6bbc0c3481155016e4d7e19493925 --- fcgi.c +++ fcgi.c @@ -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); } blob - 07e58e099c17b03f7fbada0f29b418c6a007a9b1 blob + 8e81498bc910d365ee024df56062c609efcbe103 --- gmid.conf.5 +++ 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. blob - c1fd62c38256e0a3ec065c10c7a501326ce6bb70 blob + 337fb0cd3c19959e03906c2b31d8925b032114f7 --- gmid.h +++ gmid.h @@ -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 ch 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); blob - 5a72bf41391cc76033b7e78a4b74989d3213a575 blob + 2dcb4bc5a1edbb6cb2bd722b275f7529256791f0 --- parse.y +++ parse.y @@ -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 : sizeof(loc->default_mime)); free($3); } - | FASTCGI fastcgi + | fastcgi | INDEX string { (void) strlcpy(loc->index, $2, sizeof(loc->index)); free($2); @@ -487,27 +489,45 @@ locopt : AUTO INDEX bool { loc->auto_index = $3 ? 1 : | STRIP NUM { loc->strip = check_strip_no($2); } ; -fastcgi : string { - loc->fcgi = fastcgi_conf($1, NULL); - free($1); - } - | TCP string PORT NUM { - char *c; - if (asprintf(&c, "%d", $4) == -1) - fatal("asprintf"); - loc->fcgi = fastcgi_conf($2, c); +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); - free(c); } - | TCP string { - loc->fcgi = fastcgi_conf($2, "9000"); - free($2); + | error '}' + ; + +fastcgiopts : /* empty */ + | fastcgiopts fastcgiopt optnl + ; + +fastcgiopt : PARAM string '=' string { + add_param($2, $4); } - | TCP string PORT string { - loc->fcgi = fastcgi_conf($2, $4); + | SOCKET string { + loc->fcgi = fastcgi_conf($2, NULL); free($2); - free($4); } + | SOCKET TCP string PORT NUM { + char *c; + + if (asprintf(&c, "%d", $5) == -1) + fatal("asprintf"); + loc->fcgi = fastcgi_conf($3, c); + free($3); + free(c); + } + | SOCKET TCP string { + loc->fcgi = fastcgi_conf($3, "9000"); + } + | SOCKET TCP string PORT string { + loc->fcgi = fastcgi_conf($3, $5); + free($3); + free($5); + } ; types : TYPES '{' optnl mediaopts_l '}' ; @@ -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)); blob - 8559b99344adc7478d8e745af031c24b490e6d5e blob + 88479f1e797759712b76b50494e83a023e2760d7 --- server.c +++ server.c @@ -243,23 +243,23 @@ vhost_block_return(struct vhost *v, const char *path, 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; } blob - a020b9f5324af7e99561557ca739df446276dca4 blob + 2a9d4a4cfc0e314f6aa3c51ce2ac5a02e706bab8 --- utils.c +++ utils.c @@ -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; }