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);