Blob Blame History Raw
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);