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>'.
This commit is contained in:
Omar Polo 2023-07-23 18:45:05 +00:00
parent f36ba9be59
commit a1ba9650a9
7 changed files with 138 additions and 109 deletions

View File

@ -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:

4
fcgi.c
View File

@ -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);
}

View File

@ -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.

6
gmid.h
View File

@ -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);

59
parse.y
View File

@ -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);
}
| 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);
}
| error '}'
;
fastcgiopts : /* empty */
| fastcgiopts fastcgiopt optnl
;
fastcgiopt : PARAM string '=' string {
add_param($2, $4);
}
| SOCKET string {
loc->fcgi = fastcgi_conf($2, NULL);
free($2);
}
| 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);
}
| 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));

View File

@ -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;
}

View File

@ -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;
}