diff --git a/basic.cfg b/basic.cfg index 54a799c..f9e8176 100644 --- a/basic.cfg +++ b/basic.cfg @@ -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. diff --git a/common.c b/common.c index 0bd4ce2..12c668e 100644 --- a/common.c +++ b/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 */ diff --git a/common.h b/common.h index de96633..9f4665c 100644 --- a/common.h +++ b/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 */ diff --git a/example.cfg b/example.cfg index 5ea4899..aad3402 100644 --- a/example.cfg +++ b/example.cfg @@ -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 diff --git a/sslh-main.c b/sslh-main.c index 0920d2f..b2cabed 100644 --- a/sslh-main.c +++ b/sslh-main.c @@ -40,7 +40,7 @@ const char* USAGE_STRING = "sslh " VERSION "\n" \ "usage:\n" \ "\tsslh [-v] [-i] [-V] [-f] [-n] [--transparent] [-F]\n" -"\t[-t ] [-P ] -u -p [-p ...] \n" \ +"\t[-t ] [-P ] [-u ] [-C ] -p [-p ...] \n" \ "%s\n\n" /* Dynamically built list of builtin protocols */ \ "\t[--on-timeout ]\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(); diff --git a/sslh.pod b/sslh.pod index 8b08d88..2e73234 100644 --- a/sslh.pod +++ b/sslh.pod @@ -6,7 +6,7 @@ =head1 SYNOPSIS -sslh [B<-F>I] [ B<-t> I ] [B<--transparent>] [B<-p> I [B<-p> I ...] [B<--ssl> I] [B<--tls> I] [B<--ssh> I] [B<--openvpn> I] [B<--http> I] [B<--xmpp> I] [B<--tinc> I] [B<--anyprot> I] [B<--on-timeout> I] [B<-u> I] [B<-P> I] [-v] [-i] [-V] [-f] [-n] +sslh [B<-F>I] [B<-t> I] [B<--transparent>] [B<-p> I [B<-p> I ...] [B<--ssl> I] [B<--tls> I] [B<--ssh> I] [B<--openvpn> I] [B<--http> I] [B<--xmpp> I] [B<--tinc> I] [B<--anyprot> I] [B<--on-timeout> I] [B<-u> I] [B<-C> I] [B<-P> I] [-v] [-i] [-V] [-f] [-n] =head1 DESCRIPTION @@ -184,6 +184,10 @@ Prints B version. Requires to run under the specified username. +=item B<-C> I, B<--chroot> I + +Requires to run under the specified chroot. + =item B<-P> I, B<--pidfile> I Specifies a file in which to write the PID of the main