#! /bin/sh /usr/share/dpatch/dpatch-run ## allow-alternate-config.dpatch by Daniel Kahn Gillmor ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: Allow alternate configuration file from DSPAM_CONF environment ## DP: variable. drop setuid/setgid privs when alt config file is ## DP: used. @DPATCH@ diff -urNad dspam-3.6.6~/man/dspam.1 dspam-3.6.6/man/dspam.1 --- dspam-3.6.6~/man/dspam.1 2006-06-01 17:31:29.000000000 -0400 +++ dspam-3.6.6/man/dspam.1 2006-06-01 17:31:49.523796976 -0400 @@ -279,6 +279,17 @@ .B DSPAM will be cofigured to deliver via LMTP or SMTP, this flag will set the MAIL FROM sent on delivery of the message. The default MAIL FROM depends on how the message was originally relayed to DSPAM. If it was relayed via the commandline, an empty MAIL FROM will be used. If it was relayed via LMTP, the original MAIL FROM will be used. +.SH ENVIRONMENT VARIABLES +.LP +.n3 3 +.TP +.BI DSPAM_CONF\c +When non-empty, the DSPAM_CONF environment variable specifies an +alternate configuration file to use instead of the default (on debian, +the default is /etc/dspam/dspam.conf). Since the dspam configuration +file gives shell-equivalent access, dspam will drop any setuid/setgid +privileges when an alternate config file is specified. + .SH EXIT VALUE .LP .ne 3 diff -urNad dspam-3.6.6~/man/dspam_clean.1 dspam-3.6.6/man/dspam_clean.1 --- dspam-3.6.6~/man/dspam_clean.1 2006-06-01 17:31:29.000000000 -0400 +++ dspam-3.6.6/man/dspam_clean.1 2006-06-01 17:31:49.523796976 -0400 @@ -83,6 +83,17 @@ Specify the username(s) to perform the selected maintenance operations on. If no username is specified, all users are processed. +.SH ENVIRONMENT VARIABLES +.LP +.n3 3 +.TP +.BI DSPAM_CONF\c +When non-empty, the DSPAM_CONF environment variable specifies an +alternate configuration file to use instead of the default (on debian, +the default is /etc/dspam/dspam.conf). Since the dspam configuration +file gives shell-equivalent access, dspam_clean will drop any +setuid/setgid privileges when an alternate config file is specified. + .SH EXIT VALUE .LP .ne 3 diff -urNad dspam-3.6.6~/man/dspam_dump.1 dspam-3.6.6/man/dspam_dump.1 --- dspam-3.6.6~/man/dspam_dump.1 2006-06-01 17:31:29.000000000 -0400 +++ dspam-3.6.6/man/dspam_dump.1 2006-06-01 17:31:49.523796976 -0400 @@ -53,6 +53,17 @@ Dumps the token Subject*Viagra, which represents the word Viagra in the Subject header, for the user specified. +.SH ENVIRONMENT VARIABLES +.LP +.n3 3 +.TP +.BI DSPAM_CONF\c +When non-empty, the DSPAM_CONF environment variable specifies an +alternate configuration file to use instead of the default (on debian, +the default is /etc/dspam/dspam.conf). Since the dspam configuration +file gives shell-equivalent access, dspam_dump will drop any +setuid/setgid privileges when an alternate config file is specified. + .SH EXIT VALUE .LP .ne 3 diff -urNad dspam-3.6.6~/man/dspam_merge.1 dspam-3.6.6/man/dspam_merge.1 --- dspam-3.6.6~/man/dspam_merge.1 2006-06-01 17:31:29.000000000 -0400 +++ dspam-3.6.6/man/dspam_merge.1 2006-06-01 17:31:49.523796976 -0400 @@ -60,6 +60,17 @@ .B ralph . +.SH ENVIRONMENT VARIABLES +.LP +.n3 3 +.TP +.BI DSPAM_CONF\c +When non-empty, the DSPAM_CONF environment variable specifies an +alternate configuration file to use instead of the default (on debian, +the default is /etc/dspam/dspam.conf). Since the dspam configuration +file gives shell-equivalent access, dspam_merge will drop any +setuid/setgid privileges when an alternate config file is specified. + .SH EXIT VALUE .LP .ne 3 diff -urNad dspam-3.6.6~/man/dspam_stats.1 dspam-3.6.6/man/dspam_stats.1 --- dspam-3.6.6~/man/dspam_stats.1 2006-06-01 17:31:48.712920248 -0400 +++ dspam-3.6.6/man/dspam_stats.1 2006-06-01 17:31:49.524796824 -0400 @@ -68,6 +68,17 @@ Specifies the username to query. If no username is provided, all users will be queried. +.SH ENVIRONMENT VARIABLES +.LP +.n3 3 +.TP +.BI DSPAM_CONF\c +When non-empty, the DSPAM_CONF environment variable specifies an +alternate configuration file to use instead of the default (on debian, +the default is /etc/dspam/dspam.conf). Since the dspam configuration +file gives shell-equivalent access, dspam_stats will drop any +setuid/setgid privileges when an alternate config file is specified. + .SH EXIT VALUE .LP .ne 3 diff -urNad dspam-3.6.6~/man/dspam_train.1 dspam-3.6.6/man/dspam_train.1 --- dspam-3.6.6~/man/dspam_train.1 2006-06-01 17:31:29.000000000 -0400 +++ dspam-3.6.6/man/dspam_train.1 2006-06-01 17:31:49.524796824 -0400 @@ -41,9 +41,6 @@ .SH OPTIONS .LP -.ne 3 -.TP - .n3 3 .TP .BI [username]\c @@ -61,6 +58,17 @@ Specifies the pathname to the directory containing the corpus of nonspam. Each message should be separate in its own file. +.SH ENVIRONMENT VARIABLES +.LP +.n3 3 +.TP +.BI DSPAM_CONF\c +When non-empty, the DSPAM_CONF environment variable specifies an +alternate configuration file to use instead of the default (on debian, +the default is /etc/dspam/dspam.conf). Since the dspam configuration +file gives shell-equivalent access, dspam_train will drop any +setuid/setgid privileges when an alternate config file is specified. + .SH EXIT VALUE .LP .ne 3 diff -urNad dspam-3.6.6~/src/agent_shared.c dspam-3.6.6/src/agent_shared.c --- dspam-3.6.6~/src/agent_shared.c 2006-06-01 17:31:29.000000000 -0400 +++ dspam-3.6.6/src/agent_shared.c 2006-06-01 17:31:49.524796824 -0400 @@ -111,6 +111,8 @@ return EUNKNOWN; } + ATX->config_file = NULL; + #ifdef TRUSTED_USER_SECURITY /* Cache the current user's passwd entry and establish trust */ diff -urNad dspam-3.6.6~/src/agent_shared.h dspam-3.6.6/src/agent_shared.h --- dspam-3.6.6~/src/agent_shared.h 2006-06-01 17:31:30.000000000 -0400 +++ dspam-3.6.6/src/agent_shared.h 2006-06-01 17:31:49.525796672 -0400 @@ -79,6 +79,7 @@ char client_args[1024]; /* Args for client connection */ double timestart; agent_pref_t PTX; + const char *config_file; /* can be NULL; it is not the responsibility of AGENT_CTX to de-allocate this */ char status[256]; #ifdef DEBUG diff -urNad dspam-3.6.6~/src/dspam.c dspam-3.6.6/src/dspam.c --- dspam-3.6.6~/src/dspam.c 2006-06-01 17:31:49.322827528 -0400 +++ dspam-3.6.6/src/dspam.c 2006-06-01 17:31:49.527796368 -0400 @@ -108,6 +108,7 @@ int exitcode = EXIT_SUCCESS; struct nt_node *node_nt; struct nt_c c_nt; + const char *config_file; srand ((long) time << (long) getpid ()); umask (006); /* rw-rw---- */ @@ -120,9 +121,11 @@ pthread_mutex_init(&__syslog_lock, NULL); #endif + + config_file = get_config_path(); /* Read dspam.conf into global config structure (ds_config_t) */ - agent_config = read_config(NULL); + agent_config = read_config(config_file); if (!agent_config) { LOG(LOG_ERR, ERR_AGENT_READ_CONFIG); exitcode = EXIT_FAILURE; @@ -142,6 +145,7 @@ exitcode = EXIT_FAILURE; goto BAIL; } else { + ATX.config_file = config_file; agent_init = 1; } @@ -3761,7 +3765,7 @@ if (agent_config) _ds_destroy_config(agent_config); - agent_config = read_config(NULL); + agent_config = read_config(ATX->config_file); if (!agent_config) { LOG(LOG_ERR, ERR_AGENT_READ_CONFIG); exit(EXIT_FAILURE); diff -urNad dspam-3.6.6~/src/dspamc.c dspam-3.6.6/src/dspamc.c --- dspam-3.6.6~/src/dspamc.c 2006-06-01 17:31:30.000000000 -0400 +++ dspam-3.6.6/src/dspamc.c 2006-06-01 17:31:49.528796216 -0400 @@ -115,7 +115,7 @@ /* Read dspam.conf into global config structure (ds_config_t) */ - agent_config = read_config(NULL); + agent_config = read_config(get_config_path()); if (!agent_config) { LOG(LOG_ERR, ERR_AGENT_READ_CONFIG); exitcode = EXIT_FAILURE; diff -urNad dspam-3.6.6~/src/read_config.c dspam-3.6.6/src/read_config.c --- dspam-3.6.6~/src/read_config.c 2006-06-01 17:31:48.963882096 -0400 +++ dspam-3.6.6/src/read_config.c 2006-06-01 17:31:49.528796216 -0400 @@ -45,6 +45,59 @@ long dirread(const char *path, config_t *attrib, long num_root); long fileread(const char *path, config_t *attrib, long num_root); + +/* + Here we check for an alternate configuration file from the + environment variable DSPAM_CONF. If this variable is set and + non-empty, dspam (and any other dspam executable will try to use the + alternate config file instead of the built-in one. + + dspam's configuration file gives you shell-equivalent powers, + however. + + Therefore, executables with special privileges (i.e. setuid or + setgid binaries) will drop those privileges in the presence of an + alternate configuration file. + + Since this privilege drop needs to happen as soon as possible, this + function should be called very early in any executable that + plans to use it. +*/ +const char* +get_config_path(void) { + const char* ret; + + ret = getenv("DSPAM_CONF"); + if (ret) { + if (ret[0] == 0) { /* this was just the empty string so we'll ignore it */ + return NULL; + } + LOG(LOG_INFO, "Using alternate config file '%s'", ret); + if (getgid() != getegid()) { + /* drop special gid privs, because an alternate config file + would allow shell access to that group */ + LOG(LOG_INFO, "Dropping effective group id %d to %d due to alternate config file from DSPAM_CONF", getegid(), getgid()); + if (0 != setegid(getgid())) { + LOG(LOG_ERR, "Failed to drop privileged effective group id (Error: %d). Falling back to default config file (" CONFIG_DEFAULT ")", errno); + return NULL; + } + } + if (getuid() != geteuid()) { + /* drop special uid privs, because an alternate config file + would allow shell access to that account */ + LOG(LOG_INFO, "Dropping effective user id %d to %d due to alternate config file from DSPAM_CONF", geteuid(), getuid()); + if (0 != seteuid(getuid())) { + LOG(LOG_ERR, "Failed to drop privileged effective user id (Error: %d). Falling back to default config file (" CONFIG_DEFAULT ")", errno); + return NULL; + } + } + } + return ret; +} + + + + static char *next_normal_token(char **p) { char *start = *p; diff -urNad dspam-3.6.6~/src/read_config.h dspam-3.6.6/src/read_config.h --- dspam-3.6.6~/src/read_config.h 2006-06-01 17:31:30.000000000 -0400 +++ dspam-3.6.6/src/read_config.h 2006-06-01 17:31:49.529796064 -0400 @@ -33,6 +33,7 @@ config_t read_config (const char *path); int configure_algorithms (DSPAM_CTX * CTX); +const char *get_config_path(void); agent_pref_t pref_config(void); config_t agent_config; diff -urNad dspam-3.6.6~/src/tools/dspam_2sql.c dspam-3.6.6/src/tools/dspam_2sql.c --- dspam-3.6.6~/src/tools/dspam_2sql.c 2006-06-01 17:31:30.000000000 -0400 +++ dspam-3.6.6/src/tools/dspam_2sql.c 2006-06-01 17:31:49.529796064 -0400 @@ -60,7 +60,7 @@ /* Read dspam.conf */ - agent_config = read_config(NULL); + agent_config = read_config(get_config_path()); if (!agent_config) { LOG(LOG_ERR, ERR_AGENT_READ_CONFIG); exit(EXIT_FAILURE); diff -urNad dspam-3.6.6~/src/tools/dspam_admin.c dspam-3.6.6/src/tools/dspam_admin.c --- dspam-3.6.6~/src/tools/dspam_admin.c 2006-06-01 17:31:30.000000000 -0400 +++ dspam-3.6.6/src/tools/dspam_admin.c 2006-06-01 17:31:49.529796064 -0400 @@ -73,7 +73,7 @@ /* Read dspam.conf */ - agent_config = read_config(NULL); + agent_config = read_config(get_config_path()); if (!agent_config) { LOG(LOG_ERR, ERR_AGENT_READ_CONFIG); exit(EXIT_FAILURE); diff -urNad dspam-3.6.6~/src/tools/dspam_clean.c dspam-3.6.6/src/tools/dspam_clean.c --- dspam-3.6.6~/src/tools/dspam_clean.c 2006-06-01 17:31:30.000000000 -0400 +++ dspam-3.6.6/src/tools/dspam_clean.c 2006-06-01 17:31:49.530795912 -0400 @@ -85,7 +85,7 @@ /* Read dspam.conf */ - agent_config = read_config(NULL); + agent_config = read_config(get_config_path()); if (!agent_config) { LOG(LOG_ERR, ERR_AGENT_READ_CONFIG); exit(EXIT_FAILURE); diff -urNad dspam-3.6.6~/src/tools/dspam_dump.c dspam-3.6.6/src/tools/dspam_dump.c --- dspam-3.6.6~/src/tools/dspam_dump.c 2006-06-01 17:31:30.000000000 -0400 +++ dspam-3.6.6/src/tools/dspam_dump.c 2006-06-01 17:31:49.530795912 -0400 @@ -76,7 +76,7 @@ /* Read dspam.conf */ - agent_config = read_config(NULL); + agent_config = read_config(get_config_path()); if (!agent_config) { LOG(LOG_ERR, ERR_AGENT_READ_CONFIG); exit(EXIT_FAILURE); diff -urNad dspam-3.6.6~/src/tools/dspam_merge.c dspam-3.6.6/src/tools/dspam_merge.c --- dspam-3.6.6~/src/tools/dspam_merge.c 2006-06-01 17:31:30.000000000 -0400 +++ dspam-3.6.6/src/tools/dspam_merge.c 2006-06-01 17:31:49.530795912 -0400 @@ -73,7 +73,7 @@ /* Read dspam.conf */ - agent_config = read_config(NULL); + agent_config = read_config(get_config_path()); if (!agent_config) { LOG(LOG_ERR, ERR_AGENT_READ_CONFIG); exit(EXIT_FAILURE); diff -urNad dspam-3.6.6~/src/tools/dspam_stats.c dspam-3.6.6/src/tools/dspam_stats.c --- dspam-3.6.6~/src/tools/dspam_stats.c 2006-06-01 17:31:30.000000000 -0400 +++ dspam-3.6.6/src/tools/dspam_stats.c 2006-06-01 17:31:49.531795760 -0400 @@ -80,7 +80,7 @@ /* Read dspam.conf */ - agent_config = read_config(NULL); + agent_config = read_config(get_config_path()); if (!agent_config) { LOG(LOG_ERR, ERR_AGENT_READ_CONFIG); exit(EXIT_FAILURE); diff -urNad dspam-3.6.6~/src/tools.hash_drv/cssclean.c dspam-3.6.6/src/tools.hash_drv/cssclean.c --- dspam-3.6.6~/src/tools.hash_drv/cssclean.c 2006-06-01 17:31:30.000000000 -0400 +++ dspam-3.6.6/src/tools.hash_drv/cssclean.c 2006-06-01 17:31:49.531795760 -0400 @@ -78,7 +78,7 @@ exit(EXIT_FAILURE); } - agent_config = read_config(NULL); + agent_config = read_config(get_config_path()); if (!agent_config) { LOG(LOG_ERR, ERR_AGENT_READ_CONFIG); exit(EXIT_FAILURE); diff -urNad dspam-3.6.6~/src/tools.hash_drv/csscompress.c dspam-3.6.6/src/tools.hash_drv/csscompress.c --- dspam-3.6.6~/src/tools.hash_drv/csscompress.c 2006-06-01 17:31:30.000000000 -0400 +++ dspam-3.6.6/src/tools.hash_drv/csscompress.c 2006-06-01 17:31:49.531795760 -0400 @@ -79,7 +79,7 @@ exit(EXIT_FAILURE); } - agent_config = read_config(NULL); + agent_config = read_config(get_config_path()); if (!agent_config) { LOG(LOG_ERR, ERR_AGENT_READ_CONFIG); exit(EXIT_FAILURE); diff -urNad dspam-3.6.6~/src/tools.hash_drv/cssconvert.c dspam-3.6.6/src/tools.hash_drv/cssconvert.c --- dspam-3.6.6~/src/tools.hash_drv/cssconvert.c 2006-06-01 17:31:30.000000000 -0400 +++ dspam-3.6.6/src/tools.hash_drv/cssconvert.c 2006-06-01 17:31:49.531795760 -0400 @@ -85,7 +85,7 @@ exit(EXIT_FAILURE); } - agent_config = read_config(NULL); + agent_config = read_config(get_config_path()); if (!agent_config) { LOG(LOG_ERR, ERR_AGENT_READ_CONFIG); exit(EXIT_FAILURE); diff -urNad dspam-3.6.6~/src/tools.hash_drv/cssstat.c dspam-3.6.6/src/tools.hash_drv/cssstat.c --- dspam-3.6.6~/src/tools.hash_drv/cssstat.c 2006-06-01 17:31:30.000000000 -0400 +++ dspam-3.6.6/src/tools.hash_drv/cssstat.c 2006-06-01 17:31:49.532795608 -0400 @@ -79,7 +79,7 @@ exit(EXIT_FAILURE); } - agent_config = read_config(NULL); + agent_config = read_config(get_config_path()); if (!agent_config) { LOG(LOG_ERR, ERR_AGENT_READ_CONFIG); exit(EXIT_FAILURE); diff -urNad dspam-3.6.6~/src/tools.pgsql_drv/dspam_pg2int8.c dspam-3.6.6/src/tools.pgsql_drv/dspam_pg2int8.c --- dspam-3.6.6~/src/tools.pgsql_drv/dspam_pg2int8.c 2006-06-01 17:31:30.000000000 -0400 +++ dspam-3.6.6/src/tools.pgsql_drv/dspam_pg2int8.c 2006-06-01 17:31:49.532795608 -0400 @@ -86,7 +86,7 @@ /* Read dspam.conf */ - agent_config = read_config(NULL); + agent_config = read_config(get_config_path()); if (!agent_config) { LOG(LOG_ERR, ERR_AGENT_READ_CONFIG); exit(EXIT_FAILURE);