mirror of
https://github.com/yrutschle/sslh.git
synced 2025-05-28 22:29:34 +03:00
add chroot support
This allows people to chroot sslh into a path to further harden it. We have to rework the user logic a bit because we need to look up the user details *before* we chroot (as we need to read /etc/passwd files), but do the actual priv dropping *after* we chroot (so we have permission to make the actual chroot call). Similarly, we need to open the syslog before we drop privs because /dev/log won't be available inside the chroot.
This commit is contained in:
parent
d9541392f8
commit
0fb4c6b2ad
@ -9,6 +9,7 @@ transparent: false;
|
||||
timeout: 2;
|
||||
user: "nobody";
|
||||
pidfile: "/var/run/sslh.pid";
|
||||
chroot: "/var/empty";
|
||||
|
||||
|
||||
# Change hostname with your external address name.
|
||||
|
56
common.c
56
common.c
@ -41,7 +41,7 @@ int foreground = 0;
|
||||
int background = 0;
|
||||
int transparent = 0;
|
||||
int numeric = 0;
|
||||
const char *user_name, *pid_file, *facility = "auth";
|
||||
const char *user_name, *pid_file, *chroot_path, *facility = "auth";
|
||||
|
||||
struct addrinfo *addr_listen = NULL; /* what addresses do we listen to? */
|
||||
|
||||
@ -719,33 +719,47 @@ void set_capabilities(void) {
|
||||
}
|
||||
|
||||
/* We don't want to run as root -- drop privileges if required */
|
||||
void drop_privileges(const char* user_name)
|
||||
void drop_privileges(const char* user_name, const char* chroot_path)
|
||||
{
|
||||
int res;
|
||||
struct passwd *pw = getpwnam(user_name);
|
||||
if (!pw) {
|
||||
fprintf(stderr, "%s: not found\n", user_name);
|
||||
exit(2);
|
||||
struct passwd *pw = NULL;
|
||||
|
||||
if (user_name) {
|
||||
pw = getpwnam(user_name);
|
||||
if (!pw) {
|
||||
fprintf(stderr, "%s: not found\n", user_name);
|
||||
exit(2);
|
||||
}
|
||||
if (verbose)
|
||||
fprintf(stderr, "turning into %s\n", user_name);
|
||||
}
|
||||
if (verbose)
|
||||
fprintf(stderr, "turning into %s\n", user_name);
|
||||
|
||||
set_keepcaps(1);
|
||||
if (chroot_path) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "chrooting into %s\n", chroot_path);
|
||||
|
||||
/* remove extraneous groups in case we belong to several extra groups that
|
||||
* may have unwanted rights. If non-root when calling setgroups(), it
|
||||
* fails, which is fine because... we have no unwanted rights
|
||||
* (see POS36-C for security context)
|
||||
* */
|
||||
setgroups(0, NULL);
|
||||
res = chroot(chroot_path);
|
||||
CHECK_RES_DIE(res, "chroot");
|
||||
}
|
||||
|
||||
res = setgid(pw->pw_gid);
|
||||
CHECK_RES_DIE(res, "setgid");
|
||||
res = setuid(pw->pw_uid);
|
||||
CHECK_RES_DIE(res, "setuid");
|
||||
if (user_name) {
|
||||
set_keepcaps(1);
|
||||
|
||||
set_capabilities();
|
||||
set_keepcaps(0);
|
||||
/* remove extraneous groups in case we belong to several extra groups
|
||||
* that may have unwanted rights. If non-root when calling setgroups(),
|
||||
* it fails, which is fine because... we have no unwanted rights
|
||||
* (see POS36-C for security context)
|
||||
* */
|
||||
setgroups(0, NULL);
|
||||
|
||||
res = setgid(pw->pw_gid);
|
||||
CHECK_RES_DIE(res, "setgid");
|
||||
res = setuid(pw->pw_uid);
|
||||
CHECK_RES_DIE(res, "setuid");
|
||||
|
||||
set_capabilities();
|
||||
set_keepcaps(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Writes my PID */
|
||||
|
4
common.h
4
common.h
@ -102,7 +102,7 @@ void log_connection(struct connection *cnx);
|
||||
int check_access_rights(int in_socket, const char* service);
|
||||
void setup_signals(void);
|
||||
void setup_syslog(const char* bin_name);
|
||||
void drop_privileges(const char* user_name);
|
||||
void drop_privileges(const char* user_name, const char* chroot_path);
|
||||
void write_pid_file(const char* pidfile);
|
||||
void log_message(int type, char* msg, ...);
|
||||
void dump_connection(struct connection *cnx);
|
||||
@ -118,7 +118,7 @@ extern int probing_timeout, verbose, inetd, foreground,
|
||||
extern struct sockaddr_storage addr_ssl, addr_ssh, addr_openvpn;
|
||||
extern struct addrinfo *addr_listen;
|
||||
extern const char* USAGE_STRING;
|
||||
extern const char* user_name, *pid_file, *facility;
|
||||
extern const char* user_name, *pid_file, *chroot_path, *facility;
|
||||
extern const char* server_type;
|
||||
|
||||
/* sslh-fork.c */
|
||||
|
@ -11,6 +11,7 @@ transparent: false;
|
||||
timeout: 2;
|
||||
user: "nobody";
|
||||
pidfile: "/var/run/sslh.pid";
|
||||
chroot: "/var/empty";
|
||||
|
||||
# Specify which syslog facility to use (names for your
|
||||
# system are usually defined in /usr/include/*/sys/syslog.h
|
||||
|
21
sslh-main.c
21
sslh-main.c
@ -40,7 +40,7 @@ const char* USAGE_STRING =
|
||||
"sslh " VERSION "\n" \
|
||||
"usage:\n" \
|
||||
"\tsslh [-v] [-i] [-V] [-f] [-n] [--transparent] [-F<file>]\n"
|
||||
"\t[-t <timeout>] [-P <pidfile>] -u <username> -p <add> [-p <addr> ...] \n" \
|
||||
"\t[-t <timeout>] [-P <pidfile>] [-u <username>] [-C <chroot>] -p <add> [-p <addr> ...] \n" \
|
||||
"%s\n\n" /* Dynamically built list of builtin protocols */ \
|
||||
"\t[--on-timeout <addr>]\n" \
|
||||
"-v: verbose\n" \
|
||||
@ -48,6 +48,7 @@ const char* USAGE_STRING =
|
||||
"-f: foreground\n" \
|
||||
"-n: numeric output\n" \
|
||||
"-u: specify under which user to run\n" \
|
||||
"-C: specify under which chroot path to run\n" \
|
||||
"--transparent: behave as a transparent proxy\n" \
|
||||
"-F: use configuration file (warning: no space between -F and file name!)\n" \
|
||||
"--on-timeout: connect to specified address upon timeout (default: ssh address)\n" \
|
||||
@ -71,6 +72,7 @@ static struct option const_options[] = {
|
||||
{ "user", required_argument, 0, 'u' },
|
||||
{ "config", optional_argument, 0, 'F' },
|
||||
{ "pidfile", required_argument, 0, 'P' },
|
||||
{ "chroot", required_argument, 0, 'C' },
|
||||
{ "timeout", required_argument, 0, 't' },
|
||||
{ "on-timeout", required_argument, 0, OPT_ONTIMEOUT },
|
||||
{ "listen", required_argument, 0, 'p' },
|
||||
@ -78,7 +80,7 @@ static struct option const_options[] = {
|
||||
};
|
||||
static struct option* all_options;
|
||||
static struct proto* builtins;
|
||||
static const char *optstr = "vt:T:p:VP:F::";
|
||||
static const char *optstr = "vt:T:p:VP:C:F::";
|
||||
|
||||
|
||||
|
||||
@ -399,6 +401,7 @@ static int config_parse(char *filename, struct addrinfo **listen, struct proto *
|
||||
|
||||
config_lookup_string(&config, "user", &user_name);
|
||||
config_lookup_string(&config, "pidfile", &pid_file);
|
||||
config_lookup_string(&config, "chroot", &chroot_path);
|
||||
|
||||
config_lookup_string(&config, "syslog_facility", &facility);
|
||||
|
||||
@ -561,6 +564,10 @@ next_arg:
|
||||
pid_file = optarg;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
chroot_path = optarg;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
@ -605,6 +612,7 @@ int main(int argc, char *argv[])
|
||||
/* Init defaults */
|
||||
pid_file = NULL;
|
||||
user_name = NULL;
|
||||
chroot_path = NULL;
|
||||
|
||||
cmdline_config(argc, argv, &protocols);
|
||||
parse_cmdline(argc, argv, protocols);
|
||||
@ -643,13 +651,12 @@ int main(int argc, char *argv[])
|
||||
if (pid_file)
|
||||
write_pid_file(pid_file);
|
||||
|
||||
if (user_name)
|
||||
drop_privileges(user_name);
|
||||
|
||||
|
||||
/* Open syslog connection */
|
||||
/* Open syslog connection before we drop privs/chroot */
|
||||
setup_syslog(argv[0]);
|
||||
|
||||
if (user_name || chroot_path)
|
||||
drop_privileges(user_name, chroot_path);
|
||||
|
||||
if (verbose)
|
||||
printcaps();
|
||||
|
||||
|
6
sslh.pod
6
sslh.pod
@ -6,7 +6,7 @@
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
sslh [B<-F>I<config file>] [ B<-t> I<num> ] [B<--transparent>] [B<-p> I<listening address> [B<-p> I<listening address> ...] [B<--ssl> I<target address for SSL>] [B<--tls> I<target address for TLS>] [B<--ssh> I<target address for SSH>] [B<--openvpn> I<target address for OpenVPN>] [B<--http> I<target address for HTTP>] [B<--xmpp> I<target address for XMPP>] [B<--tinc> I<target address for TINC>] [B<--anyprot> I<default target address>] [B<--on-timeout> I<protocol name>] [B<-u> I<username>] [B<-P> I<pidfile>] [-v] [-i] [-V] [-f] [-n]
|
||||
sslh [B<-F>I<config file>] [B<-t> I<num>] [B<--transparent>] [B<-p> I<listening address> [B<-p> I<listening address> ...] [B<--ssl> I<target address for SSL>] [B<--tls> I<target address for TLS>] [B<--ssh> I<target address for SSH>] [B<--openvpn> I<target address for OpenVPN>] [B<--http> I<target address for HTTP>] [B<--xmpp> I<target address for XMPP>] [B<--tinc> I<target address for TINC>] [B<--anyprot> I<default target address>] [B<--on-timeout> I<protocol name>] [B<-u> I<username>] [B<-C> I<chroot>] [B<-P> I<pidfile>] [-v] [-i] [-V] [-f] [-n]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
@ -184,6 +184,10 @@ Prints B<sslh> version.
|
||||
|
||||
Requires to run under the specified username.
|
||||
|
||||
=item B<-C> I<chroot>, B<--chroot> I<chroot>
|
||||
|
||||
Requires to run under the specified chroot.
|
||||
|
||||
=item B<-P> I<pidfile>, B<--pidfile> I<pidfile>
|
||||
|
||||
Specifies a file in which to write the PID of the main
|
||||
|
Loading…
x
Reference in New Issue
Block a user