* port our setuid function from citserver to webcit; -u can now specify the UID...
[citadel.git] / webcit / sysdep.c
1 /*
2  * $Id: sysdep.c 5691 2007-11-04 23:19:17Z dothebart $
3  *
4  * Citadel "system dependent" stuff.
5  * See copyright.txt for copyright information.
6  *
7  * Here's where we (hopefully) have most parts of the Citadel server that
8  * would need to be altered to run the server in a non-POSIX environment.
9  * 
10  * If we ever port to a different platform and either have multiple
11  * variants of this file or simply load it up with #ifdefs.
12  *
13  */
14
15 #include "sysdep.h"
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <stdio.h>
19 #include <fcntl.h>
20 #include <ctype.h>
21 #include <signal.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <sys/wait.h>
25 #include <sys/socket.h>
26 #include <syslog.h>
27 #include <sys/syslog.h>
28
29 #if TIME_WITH_SYS_TIME
30 # include <sys/time.h>
31 # include <time.h>
32 #else
33 # if HAVE_SYS_TIME_H
34 #  include <sys/time.h>
35 # else
36 #  include <time.h>
37 # endif
38 #endif
39
40 #include <limits.h>
41 #include <sys/resource.h>
42 #include <netinet/in.h>
43 #include <netinet/tcp.h>
44 #include <arpa/inet.h>
45 #include <netdb.h>
46 #include <sys/un.h>
47 #include <string.h>
48 #include <pwd.h>
49 #include <errno.h>
50 #include <stdarg.h>
51 #include <grp.h>
52 #ifdef HAVE_PTHREAD_H
53 #include <pthread.h>
54 #endif
55 #include "webcit.h"
56 #include "sysdep.h"
57
58 #ifdef HAVE_SYS_SELECT_H
59 #include <sys/select.h>
60 #endif
61
62 #ifndef HAVE_SNPRINTF
63 #include "snprintf.h"
64 #endif
65
66 #include "webserver.h"
67
68 pthread_mutex_t Critters[MAX_SEMAPHORES];       /* Things needing locking */
69 pthread_key_t MyConKey;                         /* TSD key for MyContext() */
70 pthread_key_t MyReq;                            /* TSD key for MyReq() */
71
72 void InitialiseSemaphores(void)
73 {
74         int i;
75
76         /* Set up a bunch of semaphores to be used for critical sections */
77         for (i=0; i<MAX_SEMAPHORES; ++i) {
78                 pthread_mutex_init(&Critters[i], NULL);
79         }
80 }
81
82 /*
83  * Obtain a semaphore lock to begin a critical section.
84  */
85 void begin_critical_section(int which_one)
86 {
87         /* lprintf(CTDL_DEBUG, "begin_critical_section(%d)\n", which_one); */
88         pthread_mutex_lock(&Critters[which_one]);
89 }
90
91 /*
92  * Release a semaphore lock to end a critical section.
93  */
94 void end_critical_section(int which_one)
95 {
96         pthread_mutex_unlock(&Critters[which_one]);
97 }
98
99 void drop_root(uid_t UID)
100 {
101         struct passwd pw, *pwp = NULL;
102
103         /*
104          * Now that we've bound the sockets, change to the Citadel user id and its
105          * corresponding group ids
106          */
107         if (UID != -1) {
108                 
109 #ifdef HAVE_GETPWUID_R
110 #ifdef SOLARIS_GETPWUID
111                 pwp = getpwuid_r(UID, &pw, pwbuf, sizeof(pwbuf));
112 #else // SOLARIS_GETPWUID
113                 getpwuid_r(UID, &pw, pwbuf, sizeof(pwbuf), &pwp);
114 #endif // SOLARIS_GETPWUID
115 #else // HAVE_GETPWUID_R
116                 pwp = NULL;
117 #endif // HAVE_GETPWUID_R
118
119                 if (pwp == NULL)
120                         lprintf(CTDL_CRIT, "WARNING: getpwuid(%ld): %s\n"
121                                 "Group IDs will be incorrect.\n", UID,
122                                 strerror(errno));
123                 else {
124                         initgroups(pw.pw_name, pw.pw_gid);
125                         if (setgid(pw.pw_gid))
126                                 lprintf(CTDL_CRIT, "setgid(%ld): %s\n", (long)pw.pw_gid,
127                                         strerror(errno));
128                 }
129                 lprintf(CTDL_INFO, "Changing uid to %ld\n", (long)UID);
130                 if (setuid(UID) != 0) {
131                         lprintf(CTDL_CRIT, "setuid() failed: %s\n", strerror(errno));
132                 }
133 #if defined (HAVE_SYS_PRCTL_H) && defined (PR_SET_DUMPABLE)
134                 prctl(PR_SET_DUMPABLE, 1);
135 #endif
136         }
137 }