mirror of https://github.com/omar-polo/gmid.git
chroot & drop privileges
This commit is contained in:
parent
2030e31486
commit
ae08ec7da5
16
gmid.1
16
gmid.1
|
@ -129,6 +129,22 @@ Add a mapping for the given
|
||||||
to the given
|
to the given
|
||||||
.Ar mime-type .
|
.Ar mime-type .
|
||||||
Both argument are strings.
|
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
|
.El
|
||||||
.Ss Servers
|
.Ss Servers
|
||||||
Every virtual host is defined by a
|
Every virtual host is defined by a
|
||||||
|
|
79
gmid.c
79
gmid.c
|
@ -18,6 +18,7 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#include <pwd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -32,6 +33,8 @@ int exfd;
|
||||||
|
|
||||||
struct conf conf;
|
struct conf conf;
|
||||||
|
|
||||||
|
struct tls *ctx;
|
||||||
|
|
||||||
void
|
void
|
||||||
fatal(const char *fmt, ...)
|
fatal(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
@ -242,19 +245,11 @@ parse_conf(const char *path)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
load_vhosts(struct tls_config *tlsconf)
|
load_vhosts(void)
|
||||||
{
|
{
|
||||||
struct vhost *h;
|
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) {
|
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)
|
if ((h->dirfd = open(h->dir, O_RDONLY | O_DIRECTORY)) == -1)
|
||||||
fatal("open %s for domain %s", h->dir, h->domain);
|
fatal("open %s for domain %s", h->dir, h->domain);
|
||||||
}
|
}
|
||||||
|
@ -315,14 +310,11 @@ make_socket(int port, int family)
|
||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
listener_main()
|
setup_tls(void)
|
||||||
{
|
{
|
||||||
int sock4, sock6;
|
|
||||||
struct tls *ctx = NULL;
|
|
||||||
struct tls_config *tlsconf;
|
struct tls_config *tlsconf;
|
||||||
|
struct vhost *h;
|
||||||
load_default_mime(&conf.mime);
|
|
||||||
|
|
||||||
if ((tlsconf = tls_config_new()) == NULL)
|
if ((tlsconf = tls_config_new()) == NULL)
|
||||||
fatal("tls_config_new");
|
fatal("tls_config_new");
|
||||||
|
@ -337,10 +329,26 @@ listener_main()
|
||||||
if ((ctx = tls_server()) == NULL)
|
if ((ctx = tls_server()) == NULL)
|
||||||
fatal("tls_server failure");
|
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)
|
if (tls_configure(ctx, tlsconf) == -1)
|
||||||
fatal("tls_configure: %s", tls_error(ctx));
|
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)
|
if (!conf.foreground && daemon(0, 1) == -1)
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -350,6 +358,8 @@ listener_main()
|
||||||
if (conf.ipv6)
|
if (conf.ipv6)
|
||||||
sock6 = make_socket(conf.port, AF_INET6);
|
sock6 = make_socket(conf.port, AF_INET6);
|
||||||
|
|
||||||
|
load_vhosts();
|
||||||
|
|
||||||
sandbox();
|
sandbox();
|
||||||
loop(ctx, sock4, sock6);
|
loop(ctx, sock4, sock6);
|
||||||
|
|
||||||
|
@ -371,6 +381,38 @@ init_config(void)
|
||||||
conf.protos = TLS_PROTOCOL_TLSv1_2 | TLS_PROTOCOL_TLSv1_3;
|
conf.protos = TLS_PROTOCOL_TLSv1_2 | TLS_PROTOCOL_TLSv1_3;
|
||||||
|
|
||||||
init_mime(&conf.mime);
|
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
|
void
|
||||||
|
@ -461,6 +503,11 @@ main(int argc, char **argv)
|
||||||
return 0;
|
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(SIGPIPE, SIG_IGN);
|
||||||
signal(SIGCHLD, SIG_IGN);
|
signal(SIGCHLD, SIG_IGN);
|
||||||
|
|
||||||
|
|
16
gmid.h
16
gmid.h
|
@ -92,11 +92,13 @@ struct mime {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct conf {
|
struct conf {
|
||||||
int foreground;
|
int foreground;
|
||||||
int port;
|
int port;
|
||||||
int ipv6;
|
int ipv6;
|
||||||
uint32_t protos;
|
uint32_t protos;
|
||||||
struct mime mime;
|
struct mime mime;
|
||||||
|
char *chroot;
|
||||||
|
char *user;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct conf conf;
|
extern struct conf conf;
|
||||||
|
@ -169,10 +171,12 @@ char *absolutify_path(const char*);
|
||||||
void yyerror(const char*);
|
void yyerror(const char*);
|
||||||
int parse_portno(const char*);
|
int parse_portno(const char*);
|
||||||
void parse_conf(const char*);
|
void parse_conf(const char*);
|
||||||
void load_vhosts(struct tls_config*);
|
void load_vhosts(void);
|
||||||
int make_socket(int, int);
|
int make_socket(int, int);
|
||||||
|
void setup_tls(void);
|
||||||
int listener_main(void);
|
int listener_main(void);
|
||||||
void init_config(void);
|
void init_config(void);
|
||||||
|
void drop_priv(void);
|
||||||
void usage(const char*);
|
void usage(const char*);
|
||||||
|
|
||||||
/* provided by lex/yacc */
|
/* provided by lex/yacc */
|
||||||
|
|
2
lex.l
2
lex.l
|
@ -58,6 +58,8 @@ protocols return TPROTOCOLS;
|
||||||
mime return TMIME;
|
mime return TMIME;
|
||||||
default return TDEFAULT;
|
default return TDEFAULT;
|
||||||
type return TTYPE;
|
type return TTYPE;
|
||||||
|
chroot return TCHROOT;
|
||||||
|
user return TUSER;
|
||||||
server return TSERVER;
|
server return TSERVER;
|
||||||
|
|
||||||
location return TLOCATION;
|
location return TLOCATION;
|
||||||
|
|
5
parse.y
5
parse.y
|
@ -45,7 +45,8 @@ extern void yyerror(const char*);
|
||||||
int num;
|
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 TLOCATION TCERT TKEY TROOT TCGI TLANG TINDEX TAUTO
|
||||||
%token TERR
|
%token TERR
|
||||||
|
|
||||||
|
@ -69,6 +70,8 @@ option : TDAEMON TBOOL { conf.foreground = !$2; }
|
||||||
errx(1, "invalid protocols string \"%s\"", $2);
|
errx(1, "invalid protocols string \"%s\"", $2);
|
||||||
}
|
}
|
||||||
| TMIME TSTRING TSTRING { add_mime(&conf.mime, $2, $3); }
|
| TMIME TSTRING TSTRING { add_mime(&conf.mime, $2, $3); }
|
||||||
|
| TCHROOT TSTRING { conf.chroot = $2; }
|
||||||
|
| TUSER TSTRING { conf.user = $2; }
|
||||||
;
|
;
|
||||||
|
|
||||||
vhosts : /* empty */
|
vhosts : /* empty */
|
||||||
|
|
Loading…
Reference in New Issue