commit 534afd0ddcba7c3d2f8478e89db026010c6190c5 from: Omar Polo date: Wed Oct 05 15:10:44 2022 UTC make the various strings in the config fixed-length will help in future restructuring to have fixed-size objects. commit - 4ceb570910de41133b2771cff29cbb78f37fea30 commit + 534afd0ddcba7c3d2f8478e89db026010c6190c5 blob - 91b6646cccf967ea82f0fd9f573e8b73c9bf9f7c blob + 1ed3f58637bba9b00a42e5a77c1eb39db2eca8e5 --- ge.c +++ ge.c @@ -53,9 +53,9 @@ load_local_cert(struct vhost *h, const char *hostname, if (access(cert, R_OK) == -1 || access(key, R_OK) == -1) gen_certificate(hostname, cert, key); - h->cert = cert; - h->key = key; - h->domain = hostname; + strlcpy(h->cert, cert, sizeof(h->cert)); + strlcpy(h->key, key, sizeof(h->key)); + strlcpy(h->domain, hostname, sizeof(h->domain)); } /* wrapper around dirname(3). dn must be PATH_MAX+1 at least. */ @@ -256,17 +256,22 @@ main(int argc, char **argv) load_local_cert(host, hostname, certs_dir); - host->domain = "*"; + strlcpy(host->domain, "*", sizeof(host->domain)); loc->auto_index = 1; - loc->match = "*"; + strlcpy(loc->match, "*", sizeof(loc->match)); if (*argv == NULL) { if (getcwd(path, sizeof(path)) == NULL) fatal("getcwd"); - loc->dir = path; - } else - loc->dir = absolutify_path(*argv); + strlcpy(loc->dir, path, sizeof(loc->dir)); + } else { + char *tmp; + tmp = absolutify_path(*argv); + strlcpy(loc->dir, tmp, sizeof(loc->dir)); + free(tmp); + } + if ((loc->dirfd = open(loc->dir, O_RDONLY|O_DIRECTORY)) == -1) fatal("can't open %s", loc->dir); blob - f6d5da65ae49b3adbd17e44da637ca0094c08cf0 blob + 0e7918b31992ce016980ae8d45d477a32e0a9ca8 --- gmid.c +++ gmid.c @@ -65,7 +65,7 @@ load_vhosts(void) TAILQ_FOREACH(h, &hosts, vhosts) { TAILQ_FOREACH(l, &h->locations, locations) { - if (l->dir == NULL) + if (*l->dir == '\0') continue; if ((l->dirfd = open(l->dir, O_RDONLY | O_DIRECTORY)) == -1) fatal("open %s for domain %s: %s", l->dir, h->domain, @@ -132,7 +132,7 @@ make_socket(int port, int family) static void add_keypair(struct vhost *h) { - if (h->ocsp == NULL) { + if (*h->ocsp == '\0') { if (tls_config_add_keypair_file(tlsconf, h->cert, h->key) == -1) fatal("failed to load the keypair (%s, %s)", h->cert, h->key); @@ -170,7 +170,7 @@ setup_tls(void) h->cert, h->key); /* same for OCSP */ - if (h->ocsp != NULL && + if (*h->ocsp != '\0' && tls_config_set_ocsp_staple_file(tlsconf, h->ocsp) == -1) fatal("tls_config_set_ocsp_staple_file failed for (%s)", h->ocsp); @@ -216,7 +216,7 @@ free_config(void) struct proxy *p, *tp; struct envlist *e, *te; struct alist *a, *ta; - int v, i; + int v; v = conf.verbose; @@ -229,13 +229,6 @@ free_config(void) TAILQ_FOREACH_SAFE(l, &h->locations, locations, tl) { TAILQ_REMOVE(&h->locations, l, locations); - free((char*)l->match); - free((char*)l->lang); - free((char*)l->default_mime); - free((char*)l->index); - free((char*)l->block_fmt); - free((char*)l->dir); - if (l->dirfd != -1) close(l->dirfd); @@ -244,49 +237,26 @@ free_config(void) TAILQ_FOREACH_SAFE(e, &h->params, envs, te) { TAILQ_REMOVE(&h->params, e, envs); - - free(e->name); - free(e->value); free(e); } TAILQ_FOREACH_SAFE(a, &h->aliases, aliases, ta) { TAILQ_REMOVE(&h->aliases, a, aliases); - - free(a->alias); free(a); } TAILQ_FOREACH_SAFE(p, &h->proxies, proxies, tp) { TAILQ_REMOVE(&h->proxies, p, proxies); - - free(p->match_proto); - free(p->match_host); - free(p->host); - free(p->sni); tls_unload_file(p->cert, p->certlen); tls_unload_file(p->key, p->keylen); free(p); } - - free((char*)h->domain); - free((char*)h->cert); - free((char*)h->key); - free((char*)h->ocsp); TAILQ_REMOVE(&hosts, h, vhosts); free(h); } - for (i = 0; i < FCGI_MAX; ++i) { - if (fcgi[i].path == NULL) - break; - free(fcgi[i].path); - free(fcgi[i].port); - - fcgi[i].path = NULL; - fcgi[i].port = NULL; - } + memset(fcgi, 0, sizeof(fcgi)); tls_free(ctx); tls_config_free(tlsconf); blob - 7be90515e98bc0f9d9eb25cf3b1fe61cc529a5c8 blob + 82d472ac0e0f2abc72a3b1487566e36fb4543993 --- gmid.h +++ gmid.h @@ -77,6 +77,9 @@ #define MEDIATYPE_NAMEMAX 128 /* file name extension */ #define MEDIATYPE_TYPEMAX 128 /* length of type/subtype */ +#define FCGI_NAME_MAX 511 +#define FCGI_VAL_MAX 511 + #define FCGI_MAX 32 #define PROC_MAX 16 @@ -98,20 +101,20 @@ struct parser { struct fcgi { int id; - char *path; - char *port; + char path[PATH_MAX]; + char port[32]; }; extern struct fcgi fcgi[FCGI_MAX]; TAILQ_HEAD(proxyhead, proxy); struct proxy { - char *match_proto; - char *match_host; - const char *match_port; + char match_proto[32]; + char match_host[HOST_NAME_MAX + 1]; + char match_port[32]; - char *host; - const char *port; - char *sni; + char host[HOST_NAME_MAX + 1]; + char port[32]; + char sni[HOST_NAME_MAX]; int notls; uint32_t protocols; int noverifyname; @@ -126,19 +129,19 @@ struct proxy { TAILQ_HEAD(lochead, location); struct location { - const char *match; - const char *lang; - const char *default_mime; - const char *index; + char match[128]; + char lang[32]; + char default_mime[MEDIATYPE_TYPEMAX]; + char index[PATH_MAX]; int auto_index; /* 0 auto, -1 off, 1 on */ int block_code; - const char *block_fmt; + char block_fmt[GEMINI_URL_LEN]; int strip; X509_STORE *reqca; int disable_log; int fcgi; - const char *dir; + char dir[PATH_MAX]; int dirfd; TAILQ_ENTRY(location) locations; @@ -146,23 +149,23 @@ struct location { TAILQ_HEAD(envhead, envlist); struct envlist { - char *name; - char *value; + char name[FCGI_NAME_MAX]; + char value[FCGI_VAL_MAX]; TAILQ_ENTRY(envlist) envs; }; TAILQ_HEAD(aliashead, alist); struct alist { - char *alias; + char alias[HOST_NAME_MAX + 1]; TAILQ_ENTRY(alist) aliases; }; extern TAILQ_HEAD(vhosthead, vhost) hosts; struct vhost { - const char *domain; - const char *cert; - const char *key; - const char *ocsp; + char domain[HOST_NAME_MAX + 1]; + char cert[PATH_MAX]; + char key[PATH_MAX]; + char ocsp[PATH_MAX]; TAILQ_ENTRY(vhost) vhosts; blob - 56f01081f621f518b7300df82677446b08c99a70 blob + c49b5819ea0d7c82674f3dde8a61e30ad3bf17a6 --- parse.y +++ parse.y @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -91,10 +92,9 @@ int check_prefork_num(int); void advance_loc(void); void advance_proxy(void); void parsehp(char *, char **, const char **, const char *); -void only_once(const void*, const char*); -void only_oncei(int, const char*); -int fastcgi_conf(char *, char *, char *); +int fastcgi_conf(const char *, const char *, char *); void add_param(char *, char *); +int getservice(const char *); static struct vhost *host; static struct location *loc; @@ -136,7 +136,7 @@ typedef struct { %token STRING %token NUM -%type bool +%type bool proxy_port %type string numberstring %% @@ -242,15 +242,17 @@ vhost : SERVER string { TAILQ_INIT(&host->proxies); - loc->match = xstrdup("*"); - host->domain = $2; + (void) strlcpy(loc->match, "*", sizeof(loc->match)); + (void) strlcpy(host->domain, $2, sizeof(host->domain)); if (strstr($2, "xn--") != NULL) { yywarn("\"%s\" looks like punycode: you " "should use the decoded hostname", $2); } + + free($2); } '{' optnl servbody '}' { - if (host->cert == NULL || host->key == NULL) + if (*host->cert == '\0' || *host->key == '\0') yyerror("invalid vhost definition: %s", $2); } | error '}' { yyerror("bad server directive"); } @@ -266,20 +268,24 @@ servopt : ALIAS string { struct alist *a; a = xcalloc(1, sizeof(*a)); - a->alias = $2; + (void) strlcpy(a->alias, $2, sizeof(a->alias)); + free($2); TAILQ_INSERT_TAIL(&host->aliases, a, aliases); } | CERT string { - only_once(host->cert, "cert"); - host->cert = ensure_absolute_path($2); + ensure_absolute_path($2); + (void) strlcpy(host->cert, $2, sizeof(host->cert)); + free($2); } | KEY string { - only_once(host->key, "key"); - host->key = ensure_absolute_path($2); + ensure_absolute_path($2); + (void) strlcpy(host->key, $2, sizeof(host->key)); + free($2); } | OCSP string { - only_once(host->ocsp, "ocsp"); - host->ocsp = ensure_absolute_path($2); + ensure_absolute_path($2); + (void) strlcpy(host->ocsp, $2, sizeof(host->ocsp)); + free($2); } | PARAM string '=' string { add_param($2, $4); @@ -289,7 +295,7 @@ servopt : ALIAS string { proxy : PROXY { advance_proxy(); } proxy_matches '{' optnl proxy_opts '}' { - if (proxy->host == NULL) + if (*proxy->host == '\0') yyerror("invalid proxy block: missing `relay-to' option"); if ((proxy->cert == NULL && proxy->key != NULL) || @@ -302,15 +308,24 @@ proxy_matches : /* empty */ | proxy_matches proxy_match ; +proxy_port : /* empty */ { $$ = 1965; } + | PORT STRING { + if (($$ = getservice($2)) == -1) + yyerror("invalid port number %s", $2); + free($2); + } + | PORT NUM { $$ = $2; } + ; + proxy_match : PROTO string { - only_once(proxy->match_proto, "proxy proto"); - free(proxy->match_proto); - proxy->match_proto = $2; + (void) strlcpy(proxy->match_proto, $2, sizeof(proxy->match_proto)); + free($2); } - | FOR_HOST string { - only_once(proxy->match_host, "proxy for-host"); - free(proxy->match_host); - parsehp($2, &proxy->match_host, &proxy->match_port, "10965"); + | FOR_HOST string proxy_port { + (void) strlcpy(proxy->match_host, $2, sizeof(proxy->match_host)); + (void) snprintf(proxy->match_port, sizeof(proxy->match_port), + "%d", $3); + free($2); } ; @@ -319,7 +334,6 @@ proxy_opts : /* empty */ ; proxy_opt : CERT string { - only_once(proxy->cert, "proxy cert"); tls_unload_file(proxy->cert, proxy->certlen); ensure_absolute_path($2); proxy->cert = tls_load_file($2, &proxy->certlen, NULL); @@ -328,7 +342,6 @@ proxy_opt : CERT string { free($2); } | KEY string { - only_once(proxy->key, "proxy key"); tls_unload_file(proxy->key, proxy->keylen); ensure_absolute_path($2); proxy->key = tls_load_file($2, &proxy->keylen, NULL); @@ -341,22 +354,21 @@ proxy_opt : CERT string { yyerror("invalid protocols string \"%s\"", $2); free($2); } - | RELAY_TO string { - only_once(proxy->host, "proxy relay-to"); - free(proxy->host); - parsehp($2, &proxy->host, &proxy->port, "1965"); + | RELAY_TO string proxy_port { + (void) strlcpy(proxy->host, $2, sizeof(proxy->host)); + (void) snprintf(proxy->port, sizeof(proxy->port), + "%d", $3); + free($2); } | REQUIRE CLIENT CA string { - only_once(proxy->reqca, "require client ca"); ensure_absolute_path($4); if ((proxy->reqca = load_ca($4)) == NULL) yyerror("couldn't load ca cert: %s", $4); free($4); } | SNI string { - only_once(proxy->sni, "proxy sni"); - free(proxy->sni); - proxy->sni = $2; + (void) strlcpy(proxy->sni, $2, sizeof(proxy->sni)); + free($2); } | USE_TLS bool { proxy->notls = !$2; @@ -370,7 +382,8 @@ location : LOCATION { advance_loc(); } string '{' optn /* drop the starting '/' if any */ if (*$3 == '/') memmove($3, $3+1, strlen($3)); - loc->match = $3; + (void) strlcpy(loc->match, $3, sizeof(loc->match)); + free($3); } | error '}' ; @@ -381,72 +394,75 @@ locopts : /* empty */ locopt : AUTO INDEX bool { loc->auto_index = $3 ? 1 : -1; } | BLOCK RETURN NUM string { - only_once(loc->block_fmt, "block"); - loc->block_fmt = check_block_fmt($4); + check_block_fmt($4); + (void) strlcpy(loc->block_fmt, $4, sizeof(loc->block_fmt)); loc->block_code = check_block_code($3); + free($4); } | BLOCK RETURN NUM { - only_once(loc->block_fmt, "block"); - loc->block_fmt = xstrdup("temporary failure"); + (void) strlcpy(loc->block_fmt, "temporary failure", + sizeof(loc->block_fmt)); loc->block_code = check_block_code($3); if ($3 >= 30 && $3 < 40) yyerror("missing `meta' for block return %d", $3); } | BLOCK { - only_once(loc->block_fmt, "block"); - loc->block_fmt = xstrdup("temporary failure"); + (void) strlcpy(loc->block_fmt, "temporary failure", + sizeof(loc->block_fmt)); loc->block_code = 40; } | DEFAULT TYPE string { - only_once(loc->default_mime, "default type"); - loc->default_mime = $3; + (void) strlcpy(loc->default_mime, $3, + sizeof(loc->default_mime)); + free($3); } | FASTCGI fastcgi | INDEX string { - only_once(loc->index, "index"); - loc->index = $2; + (void) strlcpy(loc->index, $2, sizeof(loc->index)); + free($2); } | LANG string { - only_once(loc->lang, "lang"); - loc->lang = $2; + (void) strlcpy(loc->lang, $2, + sizeof(loc->lang)); + free($2); } | LOG bool { loc->disable_log = !$2; } | REQUIRE CLIENT CA string { - only_once(loc->reqca, "require client ca"); ensure_absolute_path($4); if ((loc->reqca = load_ca($4)) == NULL) yyerror("couldn't load ca cert: %s", $4); free($4); } | ROOT string { - only_once(loc->dir, "root"); - loc->dir = ensure_absolute_path($2); + (void) strlcpy(loc->dir, $2, sizeof(loc->dir)); + free($2); } | STRIP NUM { loc->strip = check_strip_no($2); } ; fastcgi : SPAWN string { - only_oncei(loc->fcgi, "fastcgi"); loc->fcgi = fastcgi_conf(NULL, NULL, $2); + free($2); } | string { - only_oncei(loc->fcgi, "fastcgi"); loc->fcgi = fastcgi_conf($1, NULL, NULL); + free($1); } | TCP string PORT NUM { char *c; if (asprintf(&c, "%d", $4) == -1) err(1, "asprintf"); - only_oncei(loc->fcgi, "fastcgi"); loc->fcgi = fastcgi_conf($2, c, NULL); + free($2); } | TCP string { - only_oncei(loc->fcgi, "fastcgi"); - loc->fcgi = fastcgi_conf($2, xstrdup("9000"), NULL); + loc->fcgi = fastcgi_conf($2, "9000", NULL); + free($2); } | TCP string PORT string { - only_oncei(loc->fcgi, "fastcgi"); loc->fcgi = fastcgi_conf($2, $4, NULL); + free($2); + free($4); } ; @@ -1151,24 +1167,10 @@ parsehp(char *str, char **host, const char **port, con strtonum(*port, 1, UINT16_MAX, &errstr); if (errstr != NULL) yyerror("port is %s: %s", errstr, *port); -} - -void -only_once(const void *ptr, const char *name) -{ - if (ptr != NULL) - yyerror("`%s' specified more than once", name); -} - -void -only_oncei(int i, const char *name) -{ - if (i != -1) - yyerror("`%s' specified more than once", name); } int -fastcgi_conf(char *path, char *port, char *prog) +fastcgi_conf(const char *path, const char *port, char *prog) { struct fcgi *f; int i; @@ -1178,20 +1180,17 @@ fastcgi_conf(char *path, char *port, char *prog) for (i = 0; i < FCGI_MAX; ++i) { f = &fcgi[i]; - if (f->path == NULL) { + if (*f->path == '\0') { f->id = i; - f->path = path; - f->port = port; + (void) strlcpy(f->path, path, sizeof(f->path)); + (void) strlcpy(f->port, port, sizeof(f->port)); return i; } if (!strcmp(f->path, path) && - ((port == NULL && f->port == NULL) || - !strcmp(f->port, port))) { - free(path); - free(port); + ((port == NULL && *f->port == '\0') || + !strcmp(f->port, port))) return i; - } } yyerror("too much `fastcgi' rules defined."); @@ -1205,7 +1204,27 @@ add_param(char *name, char *val) struct envhead *h = &host->params; e = xcalloc(1, sizeof(*e)); - e->name = name; - e->value = val; + (void) strlcpy(e->name, name, sizeof(e->name)); + (void) strlcpy(e->value, val, sizeof(e->value)); TAILQ_INSERT_TAIL(h, e, envs); } + +int +getservice(const char *n) +{ + struct servent *s; + const char *errstr; + long long llval; + + llval = strtonum(n, 0, UINT16_MAX, &errstr); + if (errstr) { + s = getservbyname(n, "tcp"); + if (s == NULL) + s = getservbyname(n, "udp"); + if (s == NULL) + return (-1); + return (ntohs(s->s_port)); + } + + return ((unsigned short)llval); +} blob - 532517baddf989a7767481f967c199079d78d406 blob + 3c83a325ba92f2549125a474933bb47cfa353419 --- proxy.c +++ proxy.c @@ -326,7 +326,7 @@ proxy_setup_tls(struct client *c) if (tls_configure(c->proxyctx, conf) == -1) goto err; - if ((hn = p->sni) == NULL) + if (*(hn = p->sni) == '\0') hn = p->host; if (tls_connect_socket(c->proxyctx, c->pfd, hn) == -1) goto err; blob - afde8b76618a87bc6807893a54f0c4240e2de0af blob + 668ef2816d519b2cd8b16e088ec74f9ea853401d --- regress/lib.sh +++ regress/lib.sh @@ -80,7 +80,7 @@ server "localhost.local" { cert "$PWD/cert.pem" key "$PWD/key.pem" proxy { - relay-to "localhost:$port" + relay-to localhost port $port $1 } } blob - 52a161ddc90a8a4446fda741dca4c8fbc1729d7f blob + f1ca7cba7bea4b3ed467a5dc0caa805e49552584 --- sandbox.c +++ sandbox.c @@ -514,7 +514,7 @@ server_landlock(void) TAILQ_FOREACH(h, &hosts, vhosts) { TAILQ_FOREACH(l, &h->locations, locations) { - if (l->dir == NULL) + if (*l->dir == '\0') continue; if (landlock_unveil_path(fd, l->dir, perms) == -1) @@ -608,7 +608,7 @@ sandbox_server_process(int can_open_sockets) TAILQ_FOREACH(h, &hosts, vhosts) { TAILQ_FOREACH(l, &h->locations, locations) { - if (l->dir == NULL) + if (*l->dir == '\0') continue; if (unveil(l->dir, "r") == -1) blob - ebac30e06a4b9df017c6d9c1e2e7d6dc47cae63c blob + 50b443fc44835c904057f0166f9930cb390c52b0 --- server.c +++ server.c @@ -90,13 +90,16 @@ vhost_lang(struct vhost *v, const char *path) loc = TAILQ_FIRST(&v->locations); while ((loc = TAILQ_NEXT(loc, locations)) != NULL) { - if (loc->lang != NULL) { + if (*loc->lang != '\0') { if (matches(loc->match, path)) return loc->lang; } } - return TAILQ_FIRST(&v->locations)->lang; + loc = TAILQ_FIRST(&v->locations); + if (*loc->lang == '\0') + return NULL; + return loc->lang; } const char * @@ -110,14 +113,14 @@ vhost_default_mime(struct vhost *v, const char *path) loc = TAILQ_FIRST(&v->locations); while ((loc = TAILQ_NEXT(loc, locations)) != NULL) { - if (loc->default_mime != NULL) { + if (*loc->default_mime != '\0') { if (matches(loc->match, path)) return loc->default_mime; } } loc = TAILQ_FIRST(&v->locations); - if (loc->default_mime != NULL) + if (*loc->default_mime != '\0') return loc->default_mime; return default_mime; } @@ -133,14 +136,14 @@ vhost_index(struct vhost *v, const char *path) loc = TAILQ_FIRST(&v->locations); while ((loc = TAILQ_NEXT(loc, locations)) != NULL) { - if (loc->index != NULL) { + if (*loc->index != '\0') { if (matches(loc->match, path)) return loc->index; } } loc = TAILQ_FIRST(&v->locations); - if (loc->index != NULL) + if (*loc->index != '\0') return loc->index; return index; } @@ -536,11 +539,11 @@ matched_proxy(struct client *c) const char *port; TAILQ_FOREACH(p, &c->host->proxies, proxies) { - if ((proto = p->match_proto) == NULL) + if (*(proto = p->match_proto) == '\0') proto = "gemini"; - if ((host = p->match_host) == NULL) + if (*(host = p->match_host) == '\0') host = "*"; - if ((port = p->match_port) == NULL) + if (*(port = p->match_port) == '\0') port = "*"; if (matches(proto, c->iri.schema) && @@ -719,7 +722,7 @@ apply_fastcgi(struct client *c) log_debug(c, "opening fastcgi connection for (%s,%s)", f->path, f->port); - if (f->port != NULL) + if (*f->port != '\0') c->pfd = fcgi_open_sock(f); else c->pfd = fcgi_open_conn(f);