* port our setuid function from citserver to webcit; -u can now specify the UID...
authorWilfried Göesgens <willi@citadel.org>
Fri, 22 Jan 2010 19:21:15 +0000 (19:21 +0000)
committerWilfried Göesgens <willi@citadel.org>
Fri, 22 Jan 2010 19:21:15 +0000 (19:21 +0000)
webcit/sysdep.c
webcit/webserver.c

index 84ea33d06eb17ce1d68b3b746272af9113e691da..36155ed8494fb1de541b5167ac2457950cf44b2e 100644 (file)
@@ -63,6 +63,8 @@
 #include "snprintf.h"
 #endif
 
+#include "webserver.h"
+
 pthread_mutex_t Critters[MAX_SEMAPHORES];      /* Things needing locking */
 pthread_key_t MyConKey;                                /* TSD key for MyContext() */
 pthread_key_t MyReq;                           /* TSD key for MyReq() */
@@ -94,3 +96,42 @@ void end_critical_section(int which_one)
        pthread_mutex_unlock(&Critters[which_one]);
 }
 
+void drop_root(uid_t UID)
+{
+       struct passwd pw, *pwp = NULL;
+
+       /*
+        * Now that we've bound the sockets, change to the Citadel user id and its
+        * corresponding group ids
+        */
+       if (UID != -1) {
+               
+#ifdef HAVE_GETPWUID_R
+#ifdef SOLARIS_GETPWUID
+               pwp = getpwuid_r(UID, &pw, pwbuf, sizeof(pwbuf));
+#else // SOLARIS_GETPWUID
+               getpwuid_r(UID, &pw, pwbuf, sizeof(pwbuf), &pwp);
+#endif // SOLARIS_GETPWUID
+#else // HAVE_GETPWUID_R
+               pwp = NULL;
+#endif // HAVE_GETPWUID_R
+
+               if (pwp == NULL)
+                       lprintf(CTDL_CRIT, "WARNING: getpwuid(%ld): %s\n"
+                               "Group IDs will be incorrect.\n", UID,
+                               strerror(errno));
+               else {
+                       initgroups(pw.pw_name, pw.pw_gid);
+                       if (setgid(pw.pw_gid))
+                               lprintf(CTDL_CRIT, "setgid(%ld): %s\n", (long)pw.pw_gid,
+                                       strerror(errno));
+               }
+               lprintf(CTDL_INFO, "Changing uid to %ld\n", (long)UID);
+               if (setuid(UID) != 0) {
+                       lprintf(CTDL_CRIT, "setuid() failed: %s\n", strerror(errno));
+               }
+#if defined (HAVE_SYS_PRCTL_H) && defined (PR_SET_DUMPABLE)
+               prctl(PR_SET_DUMPABLE, 1);
+#endif
+       }
+}
index 03b6c42b77dd61e30d4346b599e3def6b3574a36..c70419b3be0d405c982abfbf537168a50109ca49 100644 (file)
@@ -36,6 +36,7 @@ extern pthread_key_t MyConKey;
 extern int ig_tcp_server(char *ip_addr, int port_number, int queue_len);
 extern int ig_uds_server(char *sockpath, int queue_len);
 
+extern void drop_root(uid_t UID);
 
 char ctdl_key_dir[PATH_MAX]=SSL_DIR;
 char file_crpt_file_key[PATH_MAX]="";
@@ -315,6 +316,7 @@ webcit_calc_dirs_n_files(int relh, const char *basedir, int home, char *webcitdi
  */
 int main(int argc, char **argv)
 {
+       uid_t UID = -1;
        size_t basesize = 2;            /* how big should strbufs be on creation? */
        pthread_t SessThread;           /* Thread descriptor */
        pthread_attr_t attr;            /* Thread attributes */
@@ -355,11 +357,14 @@ int main(int argc, char **argv)
 
        /* Parse command line */
 #ifdef HAVE_OPENSSL
-       while ((a = getopt(argc, argv, "h:i:p:t:T:B:x:dD:G:cfsS:Z")) != EOF)
+       while ((a = getopt(argc, argv, "u:h:i:p:t:T:B:x:dD:G:cfsS:Z")) != EOF)
 #else
-       while ((a = getopt(argc, argv, "h:i:p:t:T:B:x:dD:G:cfZ")) != EOF)
+       while ((a = getopt(argc, argv, "u:h:i:p:t:T:B:x:dD:G:cfZ")) != EOF)
 #endif
                switch (a) {
+               case 'u':
+                       UID = atol(optarg);
+                       break;
                case 'h':
                        hdir = strdup(optarg);
                        relh=hdir[0]!='/';
@@ -580,6 +585,7 @@ int main(int argc, char **argv)
                init_ssl();
        }
 #endif
+       drop_root(UID);
 
        /* Start a few initial worker threads */
        for (i = 0; i < (MIN_WORKER_THREADS); ++i) {