blob: 71a0176b15f81e8cffcbdd3e1e9b371b2a23892e [file] [log] [blame]
From f8304189ad6536fcd7e4c058289aa30f4140cbf1 Mon Sep 17 00:00:00 2001
From: Avery Pennarun <apenwarr@gmail.com>
Date: Thu, 27 Sep 2012 07:59:18 -0400
Subject: [PATCH] Security: drop privileges permanently at connect time.
This changes smbd to setgroups(null), setuid(200), setgid(200) right away
upon receiving a connection. I would rather do it at startup time, but
unfortunately it's designed to do its chroot() after the connection is
established instead of before, and chroot() can't run unless you keep root
privileges. We could probably fix that someday.
Anyway, this security model is much simpler than the normal smbd one where
it keeps the root privileges available to drop back into later using
setreuid(), and thus should have far fewer ways to have a security hole.
---
source3/lib/util_sec.c | 8 ++++++++
source3/printing/pcap.c | 2 ++
source3/smbd/process.c | 7 +++++++
source3/smbd/sec_ctx.c | 5 ++++-
source3/smbd/service.c | 2 ++
5 files changed, 23 insertions(+), 1 deletions(-)
diff --git a/source3/lib/util_sec.c b/source3/lib/util_sec.c
index d7984ac..65f7d0e 100644
--- a/source3/lib/util_sec.c
+++ b/source3/lib/util_sec.c
@@ -128,6 +128,7 @@ static void assert_gid(gid_t rgid, gid_t egid)
****************************************************************************/
void gain_root_privilege(void)
{
+#if USE_ROOT_PRIVILEGES
#if USE_SETRESUID
setresuid(0,0,0);
#endif
@@ -149,6 +150,7 @@ void gain_root_privilege(void)
setuid(0);
assert_uid(0, 0);
+#endif
}
@@ -158,6 +160,7 @@ void gain_root_privilege(void)
****************************************************************************/
void gain_root_group_privilege(void)
{
+#if USE_ROOT_PRIVILEGES
#if USE_SETRESUID
setresgid(0,0,0);
#endif
@@ -178,6 +181,7 @@ void gain_root_group_privilege(void)
setgid(0);
assert_gid(0, 0);
+#endif
}
@@ -195,6 +199,7 @@ void gain_root_group_privilege(void)
****************************************************************************/
void set_effective_uid(uid_t uid)
{
+#if USE_ROOT_PRIVILEGES
#if USE_SETRESUID
/* Set the effective as well as the real uid. */
if (setresuid(uid,uid,-1) == -1) {
@@ -219,6 +224,7 @@ void set_effective_uid(uid_t uid)
#endif
assert_uid(-1, uid);
+#endif
}
/****************************************************************************
@@ -227,6 +233,7 @@ void set_effective_uid(uid_t uid)
****************************************************************************/
void set_effective_gid(gid_t gid)
{
+#if USE_ROOT_PRIVILEGES
#if USE_SETRESUID
setresgid(-1,gid,-1);
#endif
@@ -244,6 +251,7 @@ void set_effective_gid(gid_t gid)
#endif
assert_gid(-1, gid);
+#endif
}
static uid_t saved_euid, saved_ruid;
diff --git a/source3/printing/pcap.c b/source3/printing/pcap.c
index 62db4f5..37d5e0d 100644
--- a/source3/printing/pcap.c
+++ b/source3/printing/pcap.c
@@ -130,6 +130,7 @@ void pcap_cache_reload(struct tevent_context *ev,
void (*post_cache_fill_fn)(struct tevent_context *,
struct messaging_context *))
{
+#if WE_ACTUALLY_WANT_PRINTING_SUPPORT
const char *pcap_name = lp_printcapname();
bool pcap_reloaded = False;
NTSTATUS status;
@@ -202,6 +203,7 @@ done:
}
return;
+#endif
}
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 5aa19cb..0b1dee5 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -3038,6 +3038,13 @@ void smbd_process(struct smbd_server_connection *sconn)
DEBUG(0,("Changed root to %s\n", lp_rootdir()));
}
+ if (setgroups(0, NULL) < 0) {
+ exit_server("failed to setgroups");
+ }
+ if (setgid(200) < 0 || setuid(200) < 0) {
+ exit_server("failed to setuid/setgid");
+ }
+
if (!srv_init_signing(sconn)) {
exit_server("Failed to init smb_signing");
}
diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c
index f8c8847..c2e7e1b 100644
--- a/source3/smbd/sec_ctx.c
+++ b/source3/smbd/sec_ctx.c
@@ -109,7 +109,7 @@ static void gain_root(void)
if (non_root_mode()) {
return;
}
-
+#if USE_ROOT_PRIVILEGES
if (geteuid() != 0) {
set_effective_uid(0);
@@ -129,6 +129,7 @@ static void gain_root(void)
"gid system\n"));
}
}
+#endif
}
/****************************************************************************
@@ -245,11 +246,13 @@ static void set_unix_security_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *grou
{
/* Start context switch */
gain_root();
+#if USE_ROOT_PRIVILEGES
#ifdef HAVE_SETGROUPS
if (sys_setgroups(gid, ngroups, groups) != 0 && !non_root_mode()) {
smb_panic("sys_setgroups failed");
}
#endif
+#endif
become_id(uid, gid);
/* end context switch */
}
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index 34b24f3..e32cb2a 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -1191,6 +1191,7 @@ connection_struct *make_connection(struct smbd_server_connection *sconn,
fstrcpy(dev, pdev);
+#if USE_ROOT_PRIVILEGES
/* This must ONLY BE CALLED AS ROOT. As it exits this function as
* root. */
if (!non_root_mode() && (euid = geteuid()) != 0) {
@@ -1198,6 +1199,7 @@ connection_struct *make_connection(struct smbd_server_connection *sconn,
"(%u)\n", (unsigned int)euid ));
smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
}
+#endif
if (conn_num_open(sconn) > 2047) {
*status = NT_STATUS_INSUFF_SERVER_RESOURCES;
--
1.7.9.dirty