commit - 2030e314860f1ba4a1b0294b741164dca2391466
commit + ae08ec7da5bf349bea4621219df41f297b3116e9
blob - ad0aeba97f7232a1d19b9386ae486e802cb90884
blob + 4382cd017e3394902cda8acc1039180613f0b74f
--- gmid.1
+++ gmid.1
to the given
.Ar mime-type .
Both argument are strings.
+.It Ic chroot Pa path
+.Xr chroot 2
+the process to the given
+.Pa path .
+The daemon has to be run with root privileges and thus the option
+.Ic user
+needs to be provided, so
+.Nm
+can drop the privileges.
+Note that they are dropped after loading the TLS keys, so it's
+recommended to put those outside the chroot.
+Future version of
+.Nm
+may require this.
+.It Ic user Ar string
+Run the daemon as the given user.
.El
.Ss Servers
Every virtual host is defined by a
blob - f2db8c66f860bc88d146e1aa0dd60cada498403c
blob + 7b1238e37afbcfbfe0d8ed4fd64d3f936768f082
--- gmid.c
+++ gmid.c
#include <fcntl.h>
#include <limits.h>
#include <netdb.h>
+#include <pwd.h>
#include <signal.h>
#include <stdarg.h>
#include <string.h>
struct conf conf;
+struct tls *ctx;
+
void
fatal(const char *fmt, ...)
{
}
void
-load_vhosts(struct tls_config *tlsconf)
+load_vhosts(void)
{
struct vhost *h;
- /* we need to set something, then we can add how many key we want */
- if (tls_config_set_keypair_file(tlsconf, hosts->cert, hosts->key))
- fatal("tls_config_set_keypair_file failed");
-
for (h = hosts; h->domain != NULL; ++h) {
- if (tls_config_add_keypair_file(tlsconf, h->cert, h->key) == -1)
- fatal("failed to load the keypair (%s, %s)",
- h->cert, h->key);
-
if ((h->dirfd = open(h->dir, O_RDONLY | O_DIRECTORY)) == -1)
fatal("open %s for domain %s", h->dir, h->domain);
}
return sock;
}
-int
-listener_main()
+void
+setup_tls(void)
{
- int sock4, sock6;
- struct tls *ctx = NULL;
struct tls_config *tlsconf;
-
- load_default_mime(&conf.mime);
+ struct vhost *h;
if ((tlsconf = tls_config_new()) == NULL)
fatal("tls_config_new");
if ((ctx = tls_server()) == NULL)
fatal("tls_server failure");
- load_vhosts(tlsconf);
+ /* we need to set something, then we can add how many key we want */
+ if (tls_config_set_keypair_file(tlsconf, hosts->cert, hosts->key))
+ fatal("tls_config_set_keypair_file failed");
+ for (h = hosts; h->domain != NULL; ++h) {
+ if (tls_config_add_keypair_file(tlsconf, h->cert, h->key) == -1)
+ fatal("failed to load the keypair (%s, %s)",
+ h->cert, h->key);
+ }
+
if (tls_configure(ctx, tlsconf) == -1)
fatal("tls_configure: %s", tls_error(ctx));
+}
+int
+listener_main(void)
+{
+ int sock4, sock6;
+
+ load_default_mime(&conf.mime);
+
if (!conf.foreground && daemon(0, 1) == -1)
exit(1);
if (conf.ipv6)
sock6 = make_socket(conf.port, AF_INET6);
+ load_vhosts();
+
sandbox();
loop(ctx, sock4, sock6);
conf.protos = TLS_PROTOCOL_TLSv1_2 | TLS_PROTOCOL_TLSv1_3;
init_mime(&conf.mime);
+
+ conf.chroot = NULL;
+ conf.user = NULL;
}
void
+drop_priv(void)
+{
+ struct passwd *pw = NULL;
+
+ if (conf.chroot != NULL && conf.user == NULL)
+ fatal("can't chroot without an user to switch to after.");
+
+ if (conf.user != NULL) {
+ if ((pw = getpwnam(conf.user)) == NULL)
+ fatal("can't find user %s", conf.user);
+ }
+
+ if (conf.chroot != NULL) {
+ if (chroot(conf.chroot) != 0 || chdir("/") != 0)
+ fatal("%s: %s", conf.chroot, strerror(errno));
+ }
+
+ if (pw != NULL) {
+ if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
+ fatal("setresuid(%d): %s", pw->pw_uid,
+ strerror(errno));
+ }
+
+ if (getuid() == 0)
+ LOGW(NULL, "%s",
+ "not a good idea to run a network daemon as root");
+}
+
+void
usage(const char *me)
{
fprintf(stderr,
return 0;
}
+ /* setup tls before dropping privileges: we don't want user
+ * to put private certs inside the chroot. */
+ setup_tls();
+ drop_priv();
+
signal(SIGPIPE, SIG_IGN);
signal(SIGCHLD, SIG_IGN);
blob - 2364e7c7bc0cbda5e0eeb965b11ca858c6c21db1
blob + 968559bddf67af3f24a4879b61fd3bf1783d0594
--- gmid.h
+++ gmid.h
};
struct conf {
- int foreground;
- int port;
- int ipv6;
- uint32_t protos;
- struct mime mime;
+ int foreground;
+ int port;
+ int ipv6;
+ uint32_t protos;
+ struct mime mime;
+ char *chroot;
+ char *user;
};
extern struct conf conf;
void yyerror(const char*);
int parse_portno(const char*);
void parse_conf(const char*);
-void load_vhosts(struct tls_config*);
+void load_vhosts(void);
int make_socket(int, int);
+void setup_tls(void);
int listener_main(void);
void init_config(void);
+void drop_priv(void);
void usage(const char*);
/* provided by lex/yacc */
blob - 240f7c466e7c1551d21d5664d4aaab6974aba9d3
blob + 099b3c4b19d822ba495bb7d4980f114d99cbd54f
--- lex.l
+++ lex.l
mime return TMIME;
default return TDEFAULT;
type return TTYPE;
+chroot return TCHROOT;
+user return TUSER;
server return TSERVER;
location return TLOCATION;
blob - 5e7cb216241e588d84ac594ed7b7a2ef4a4671cc
blob + 97934599fd9039217e0a83785418fb3fb5a25d6f
--- parse.y
+++ parse.y
int num;
}
-%token TDAEMON TIPV6 TPORT TPROTOCOLS TMIME TDEFAULT TTYPE TSERVER
+%token TDAEMON TIPV6 TPORT TPROTOCOLS TMIME TDEFAULT TTYPE
+%token TCHROOT TUSER TSERVER
%token TLOCATION TCERT TKEY TROOT TCGI TLANG TINDEX TAUTO
%token TERR
errx(1, "invalid protocols string \"%s\"", $2);
}
| TMIME TSTRING TSTRING { add_mime(&conf.mime, $2, $3); }
+ | TCHROOT TSTRING { conf.chroot = $2; }
+ | TUSER TSTRING { conf.user = $2; }
;
vhosts : /* empty */