aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOmar Polo <op@omarpolo.com>2023-07-23 18:45:05 +0000
committerOmar Polo <op@omarpolo.com>2023-07-23 18:45:05 +0000
commita1ba9650a9f0cc0d9e70800d71769d32f927b939 (patch)
tree4ce8a9b5e4cd3aff8a41d4cd67c15f7c07774b17
parentf36ba9be59c1b60aff4b9663f49d8656800afa00 (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.c30
-rw-r--r--fcgi.c4
-rw-r--r--gmid.conf.5127
-rw-r--r--gmid.h6
-rw-r--r--parse.y55
-rw-r--r--server.c19
-rw-r--r--utils.c2
7 files changed, 136 insertions, 107 deletions
diff --git a/config.c b/config.c
index 0eac060..3b84aa4 100644
--- a/config.c
+++ b/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:
diff --git a/fcgi.c b/fcgi.c
index 7a141a5..281dfaa 100644
--- a/fcgi.c
+++ b/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);
}
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.
diff --git a/gmid.h b/gmid.h
index c1fd62c..337fb0c 100644
--- a/gmid.h
+++ b/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 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);
diff --git a/parse.y b/parse.y
index 5a72bf4..2dcb4bc 100644
--- a/parse.y
+++ b/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 : -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));
diff --git a/server.c b/server.c
index 8559b99..88479f1 100644
--- a/server.c
+++ b/server.c
@@ -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;
}
diff --git a/utils.c b/utils.c
index a020b9f..2a9d4a4 100644
--- a/utils.c
+++ b/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;
}