summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stef@memberwebs.com>2004-09-16 18:53:20 +0000
committerStef Walter <stef@memberwebs.com>2004-09-16 18:53:20 +0000
commit6147270ba7e07face960fde5653489e920cd2707 (patch)
treeacfd4c2102683de0d1739b7b5c8359984baf2da0
parent216e32d823baa33dd3e302201197860db52ce7a4 (diff)
- Ability to switch users
- Fix for config files not ending in a line break
-rw-r--r--common/smtppass.c62
-rw-r--r--common/sppriv.h1
-rw-r--r--doc/clamsmtpd.conf5
-rw-r--r--doc/clamsmtpd.conf.55
4 files changed, 68 insertions, 5 deletions
diff --git a/common/smtppass.c b/common/smtppass.c
index 0038d9e..c2d2136 100644
--- a/common/smtppass.c
+++ b/common/smtppass.c
@@ -52,6 +52,7 @@
#include <err.h>
#include <paths.h>
#include <stdarg.h>
+#include <pwd.h>
#include "usuals.h"
@@ -129,7 +130,7 @@ spthread_t;
* - Be sure that your configuration option needs to go into this
* file. More likely it'll go into clamsmtpd.c
* - When adding configuration options follow the instructions in
- * clamsmtpd.c, except add option to spstate_t (above) and parse in
+ * clamsmtpd.c, except add option to spstate_t (sppriv.h) and parse in
* sp_parse_option (below)
*/
@@ -139,7 +140,7 @@ spthread_t;
#define CFG_LISTENADDR "Listen"
#define CFG_TRANSPARENT "TransparentProxy"
#define CFG_DIRECTORY "TempDirectory"
-
+#define CFG_USER "User"
/* -----------------------------------------------------------------------
* DEFAULT SETTINGS
@@ -156,7 +157,7 @@ spthread_t;
spstate_t g_state; /* The state and configuration of the daemon */
unsigned int g_unique_id = 0x00100000; /* For connection ids */
-pthread_mutex_t g_mutex; /* The main mutex */
+pthread_mutex_t g_mutex; /* The main mutex */
pthread_mutexattr_t g_mtxattr;
@@ -165,6 +166,7 @@ pthread_mutexattr_t g_mtxattr;
*/
static void on_quit(int signal);
+static void drop_privileges();
static void pid_file(const char* pidfile, int write);
static void connection_loop(int sock);
static void* thread_main(void* arg);
@@ -242,6 +244,9 @@ int sp_run(const char* configfile, const char* pidfile, int dbg_level)
sp_messagex(NULL, LOG_DEBUG, "starting up...");
+ /* Drop privileges before daemonizing */
+ drop_privileges();
+
/* When set to this we daemonize */
if(g_state.debug_level == -1)
{
@@ -342,6 +347,47 @@ static void on_quit(int signal)
g_state.quit = 1;
}
+static void drop_privileges()
+{
+ char* t;
+ struct passwd* pw;
+ uid_t uid;
+
+ if(g_state.user)
+ {
+ if(geteuid() != 0)
+ {
+ sp_messagex(NULL, LOG_WARNING, "must be started as root to switch to user: %s", g_state.user);
+ return;
+ }
+
+ uid = strtol(g_state.user, &t, 10);
+ if(!t[0]) /* successful parse */
+ pw = getpwuid(uid);
+ else /* must be a name */
+ pw = getpwnam(g_state.user);
+
+ if(pw == NULL)
+ errx(1, "couldn't look up user: %s", g_state.user);
+
+ if(setgid(pw->pw_gid) == -1)
+ err(1, "unable to switch group: %d", pw->pw_gid);
+
+ if(setuid(pw->pw_uid) == -1)
+ err(1, "unable to switch user: %d", pw->pw_uid);
+
+ /* A paranoia check */
+ if(setreuid(-1, 0) == 0)
+ err(1, "unable to completely drop privileges");
+
+ sp_messagex(NULL, LOG_DEBUG, "switched to user %s (uid %d, gid %d)", g_state.user, pw->pw_uid, pw->pw_gid);
+ }
+
+ if(geteuid() == 0)
+ sp_messagex(NULL, LOG_WARNING, "running as root is NOT recommended");
+}
+
+
static void pid_file(const char* pidfile, int write)
{
if(write)
@@ -1413,6 +1459,14 @@ int sp_parse_option(const char* name, const char* value)
ret = 1;
}
+ else if(strcasecmp(CFG_USER, name) == 0)
+ {
+ if(strlen(value) == 0)
+ errx(2, "invalid setting: " CFG_USER);
+ g_state.user = value;
+ ret = 1;
+ }
+
/* Always pass through to program */
if(cb_parse_option(name, value) == 1)
ret = 1;
@@ -1457,7 +1511,7 @@ static int parse_config_file(const char* configfile)
/* Double null terminate the data */
p = g_state._p;
- p[len] = 0;
+ p[len] = '\n';
p[len + 1] = 0;
n = g_state._p;
diff --git a/common/sppriv.h b/common/sppriv.h
index 89a89f9..30686f9 100644
--- a/common/sppriv.h
+++ b/common/sppriv.h
@@ -49,6 +49,7 @@ typedef struct spstate
struct timeval timeout; /* Timeout for communication */
int transparent; /* Transparent proxying */
const char* directory; /* The temp directory */
+ const char* user; /* User to run as */
struct sockaddr_any outaddr; /* The outgoing address */
const char* outname;
diff --git a/doc/clamsmtpd.conf b/doc/clamsmtpd.conf
index b450091..44fd01e 100644
--- a/doc/clamsmtpd.conf
+++ b/doc/clamsmtpd.conf
@@ -3,7 +3,7 @@
# ------------------------------------------------------------------------------
#
# - Comments are a line that starts with a #
-# - All the options are found below with their defaults commented out
+# - All the options are found below with sample settings
# The address to send scanned mail to.
@@ -39,3 +39,6 @@ OutAddress: 10026
# Enable transparent proxy support
#TransparentProxy: off
+
+# User to switch to
+#User: clamav
diff --git a/doc/clamsmtpd.conf.5 b/doc/clamsmtpd.conf.5
index c61a0fc..9505629 100644
--- a/doc/clamsmtpd.conf.5
+++ b/doc/clamsmtpd.conf.5
@@ -123,6 +123,11 @@ This option enables transparent proxy support, which allows you to route all
SMTP traffic that's going through a gateway through clamsmtp which will then
send it on to its final destination. This setup usually involves firewall
rules which redirect traffic to clamsmtp, and the setup varies from OS to OS.
+.It Ar User
+The user to run as. If this option is specified then
+.Xr clamsmtpd 8
+must be started as root. It will then drop root privileges and run as the
+specified user. The user can either be a name or a numerical user id.
.El
.Sh ADDRESSES
Addresses can be specified in multiple formats: