Index: modules/mod_cap.c
===================================================================
RCS file: /cvsroot/proftp/proftpd/modules/mod_cap.c,v
retrieving revision 1.27
diff -u -r1.27 mod_cap.c
--- modules/mod_cap.c 23 May 2011 21:11:56 -0000 1.27
+++ modules/mod_cap.c 17 Jun 2013 17:58:05 -0000
@@ -60,7 +60,6 @@
static cap_t capabilities = 0;
static unsigned char have_capabilities = FALSE;
static unsigned char use_capabilities = TRUE;
-static unsigned int cap_flags = 0;
#define CAP_USE_CHOWN 0x0001
#define CAP_USE_DAC_OVERRIDE 0x0002
@@ -69,6 +68,9 @@
#define CAP_USE_AUDIT_WRITE 0x0010
#define CAP_USE_FOWNER 0x0020
+/* CAP_CHOWN and CAP_SETUID are enabled by default. */
+static unsigned int cap_flags = (CAP_USE_CHOWN|CAP_USE_SETUID);
+
module cap_module;
/* log current capabilities */
@@ -165,8 +167,8 @@
CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
- /* CAP_CHOWN is enabled by default. */
- flags |= CAP_USE_CHOWN;
+ /* CAP_CHOWN and CAP_SETUID are enabled by default. */
+ flags |= (CAP_USE_CHOWN|CAP_USE_SETUID);
for (i = 1; i < cmd->argc; i++) {
char *cp = cmd->argv[i];
@@ -192,6 +194,10 @@
if (*cmd->argv[i] == '+')
flags |= CAP_USE_FOWNER;
+ } else if (strcasecmp(cp, "CAP_SETUID") == 0) {
+ if (*cmd->argv[i] == '-')
+ flags &= ~CAP_USE_SETUID;
+
} else {
CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "unknown capability: '",
cp, "'", NULL));
@@ -245,7 +251,7 @@
/* Check for which specific capabilities to include/exclude. */
c = find_config(main_server->conf, CONF_PARAM, "CapabilitiesSet", FALSE);
if (c != NULL) {
- cap_flags |= *((unsigned int *) c->argv[0]);
+ cap_flags = *((unsigned int *) c->argv[0]);
if (!(cap_flags & CAP_USE_CHOWN)) {
pr_log_debug(DEBUG3, MOD_CAP_VERSION
@@ -266,6 +272,11 @@
pr_log_debug(DEBUG3, MOD_CAP_VERSION
": adding CAP_FOWNER capability");
}
+
+ if (!(cap_flags & CAP_USE_SETUID)) {
+ pr_log_debug(DEBUG3, MOD_CAP_VERSION
+ ": removing CAP_SETUID capability");
+ }
}
pr_signals_block();
@@ -275,7 +286,7 @@
* so we can't use PRIVS_ROOT/PRIVS_RELINQUISH. setreuid() is the
* workaround.
*/
- if (setreuid(session.uid, 0) < 0) {
+ if (setreuid(session.uid, PR_ROOT_UID) < 0) {
int xerrno = errno;
const char *proto;
@@ -286,7 +297,7 @@
/* If this is for an SSH2 connection, don't log the error if it is
* an EPERM.
*/
- if (strcmp(proto, "ssh2") != 0 ||
+ if (strncmp(proto, "ssh2", 5) != 0 ||
xerrno != EPERM) {
pr_log_pri(PR_LOG_ERR, MOD_CAP_VERSION ": setreuid: %s",
strerror(xerrno));
@@ -322,7 +333,8 @@
res = lp_add_cap(CAP_DAC_READ_SEARCH, CAP_PERMITTED);
}
- if (res != -1 && (cap_flags & CAP_USE_SETUID)) {
+ if (res != -1 &&
+ (cap_flags & CAP_USE_SETUID)) {
res = lp_add_cap(CAP_SETUID, CAP_PERMITTED);
if (res != -1) {
res = lp_add_cap(CAP_SETGID, CAP_PERMITTED);