1 /* _ _
2 ** _ __ ___ ___ __| | ___ ___| | mod_ssl
3 ** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
4 ** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
5 ** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
6 ** |_____|
7 ** ssl_engine_mutex.c
8 ** Semaphore for Mutual Exclusion
9 */
10
11 /* ====================================================================
12 * Copyright (c) 1998-2003 Ralf S. Engelschall. All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 *
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following
23 * disclaimer in the documentation and/or other materials
24 * provided with the distribution.
25 *
26 * 3. All advertising materials mentioning features or use of this
27 * software must display the following acknowledgment:
28 * "This product includes software developed by
29 * Ralf S. Engelschall <rse@engelschall.com> for use in the
30 * mod_ssl project (http://www.modssl.org/)."
31 *
32 * 4. The names "mod_ssl" must not be used to endorse or promote
33 * products derived from this software without prior written
34 * permission. For written permission, please contact
35 * rse@engelschall.com.
36 *
37 * 5. Products derived from this software may not be called "mod_ssl"
38 * nor may "mod_ssl" appear in their names without prior
39 * written permission of Ralf S. Engelschall.
40 *
41 * 6. Redistributions of any form whatsoever must retain the following
42 * acknowledgment:
43 * "This product includes software developed by
44 * Ralf S. Engelschall <rse@engelschall.com> for use in the
45 * mod_ssl project (http://www.modssl.org/)."
46 *
47 * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
48 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
50 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
51 * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
52 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
53 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
54 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
56 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
57 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
58 * OF THE POSSIBILITY OF SUCH DAMAGE.
59 * ====================================================================
60 */
61 /* ``Real programmers confuse
62 Christmas and Halloween
63 because DEC 25 = OCT 31.''
64 -- Unknown */
65 #include "mod_ssl.h"
66
67
68 /* _________________________________________________________________
69 **
70 ** Mutex Support (Common)
71 ** _________________________________________________________________
72 */
73
ssl_mutex_init(server_rec * s,pool * p)74 void ssl_mutex_init(server_rec *s, pool *p)
75 {
76 SSLModConfigRec *mc = myModConfig();
77
78 if (mc->nMutexMode == SSL_MUTEXMODE_FILE)
79 ssl_mutex_file_create(s, p);
80 else if (mc->nMutexMode == SSL_MUTEXMODE_SEM)
81 ssl_mutex_sem_create(s, p);
82 return;
83 }
84
ssl_mutex_reinit(server_rec * s,pool * p)85 void ssl_mutex_reinit(server_rec *s, pool *p)
86 {
87 SSLModConfigRec *mc = myModConfig();
88
89 if (mc->nMutexMode == SSL_MUTEXMODE_FILE)
90 ssl_mutex_file_open(s, p);
91 else if (mc->nMutexMode == SSL_MUTEXMODE_SEM)
92 ssl_mutex_sem_open(s, p);
93 return;
94 }
95
ssl_mutex_on(server_rec * s)96 void ssl_mutex_on(server_rec *s)
97 {
98 SSLModConfigRec *mc = myModConfig();
99 BOOL ok = TRUE;
100
101 if (mc->nMutexMode == SSL_MUTEXMODE_FILE)
102 ok = ssl_mutex_file_acquire();
103 else if (mc->nMutexMode == SSL_MUTEXMODE_SEM)
104 ok = ssl_mutex_sem_acquire();
105 if (!ok)
106 ssl_log(s, SSL_LOG_WARN, "Failed to acquire global mutex lock");
107 return;
108 }
109
ssl_mutex_off(server_rec * s)110 void ssl_mutex_off(server_rec *s)
111 {
112 SSLModConfigRec *mc = myModConfig();
113 BOOL ok = TRUE;
114
115 if (mc->nMutexMode == SSL_MUTEXMODE_FILE)
116 ok = ssl_mutex_file_release();
117 else if (mc->nMutexMode == SSL_MUTEXMODE_SEM)
118 ok = ssl_mutex_sem_release();
119 if (!ok)
120 ssl_log(s, SSL_LOG_WARN, "Failed to release global mutex lock");
121 return;
122 }
123
ssl_mutex_kill(server_rec * s)124 void ssl_mutex_kill(server_rec *s)
125 {
126 SSLModConfigRec *mc = myModConfig();
127
128 if (mc->nMutexMode == SSL_MUTEXMODE_FILE)
129 ssl_mutex_file_remove(s);
130 else if (mc->nMutexMode == SSL_MUTEXMODE_SEM)
131 ssl_mutex_sem_remove(s);
132 return;
133 }
134
135
136 /* _________________________________________________________________
137 **
138 ** Mutex Support (Lockfile)
139 ** _________________________________________________________________
140 */
141
ssl_mutex_file_create(server_rec * s,pool * p)142 void ssl_mutex_file_create(server_rec *s, pool *p)
143 {
144 SSLModConfigRec *mc = myModConfig();
145 char mutexfile[MAXPATHLEN];
146
147 /* create the lockfile */
148 strlcpy(mutexfile, mc->szMutexFile, sizeof(mutexfile));
149 ap_server_strip_chroot(mutexfile, 0);
150 unlink(mutexfile);
151 if ((mc->nMutexFD = ap_popenf(p, mutexfile,
152 O_WRONLY|O_CREAT, SSL_MUTEX_LOCK_MODE)) < 0) {
153 ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
154 "Parent process could not create SSLMutex lockfile %s",
155 mutexfile);
156 ssl_die();
157 }
158 ap_pclosef(p, mc->nMutexFD);
159
160 /* make sure the childs have access to this file */
161 if (geteuid() == 0 /* is superuser */)
162 chown(mutexfile, ap_user_id, -1 /* no gid change */);
163
164 /* open the lockfile for real */
165 if ((mc->nMutexFD = ap_popenf(p, mutexfile,
166 O_WRONLY, SSL_MUTEX_LOCK_MODE)) < 0) {
167 ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
168 "Parent could not open SSLMutex lockfile %s",
169 mutexfile);
170 ssl_die();
171 }
172 return;
173 }
174
ssl_mutex_file_open(server_rec * s,pool * p)175 void ssl_mutex_file_open(server_rec *s, pool *p)
176 {
177 SSLModConfigRec *mc = myModConfig();
178 char mutexfile[MAXPATHLEN];
179
180 strlcpy(mutexfile, mc->szMutexFile, sizeof(mutexfile));
181 ap_server_strip_chroot(mutexfile, 0);
182
183 /* open the lockfile (once per child) to get a unique fd */
184 if ((mc->nMutexFD = ap_popenf(p, mutexfile,
185 O_WRONLY, SSL_MUTEX_LOCK_MODE)) < 0) {
186 ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
187 "Child could not open SSLMutex lockfile %s",
188 mutexfile);
189 ssl_die();
190 }
191 return;
192 }
193
ssl_mutex_file_remove(void * data)194 void ssl_mutex_file_remove(void *data)
195 {
196 SSLModConfigRec *mc = myModConfig();
197 char mutexfile[MAXPATHLEN];
198 strlcpy(mutexfile, mc->szMutexFile, sizeof(mutexfile));
199 ap_server_strip_chroot(mutexfile, 0);
200
201 /* remove the mutex lockfile */
202 unlink(mutexfile);
203 return;
204 }
205
206 #ifdef SSL_USE_FCNTL
207 static struct flock lock_it;
208 static struct flock unlock_it;
209 #endif
210
ssl_mutex_file_acquire(void)211 BOOL ssl_mutex_file_acquire(void)
212 {
213 int rc = -1;
214 SSLModConfigRec *mc = myModConfig();
215
216 #ifdef SSL_USE_FCNTL
217 lock_it.l_whence = SEEK_SET; /* from current point */
218 lock_it.l_start = 0; /* -"- */
219 lock_it.l_len = 0; /* until end of file */
220 lock_it.l_type = F_WRLCK; /* set exclusive/write lock */
221 lock_it.l_pid = 0; /* pid not actually interesting */
222
223 while ( ((rc = fcntl(mc->nMutexFD, F_SETLKW, &lock_it)) < 0)
224 && (errno == EINTR) )
225 ;
226 #endif
227 #ifdef SSL_USE_FLOCK
228 while ( ((rc = flock(mc->nMutexFD, LOCK_EX)) < 0)
229 && (errno == EINTR) )
230 ;
231 #endif
232
233 if (rc < 0)
234 return FALSE;
235 else
236 return TRUE;
237 }
238
ssl_mutex_file_release(void)239 BOOL ssl_mutex_file_release(void)
240 {
241 int rc = -1;
242 SSLModConfigRec *mc = myModConfig();
243
244 #ifdef SSL_USE_FCNTL
245 unlock_it.l_whence = SEEK_SET; /* from current point */
246 unlock_it.l_start = 0; /* -"- */
247 unlock_it.l_len = 0; /* until end of file */
248 unlock_it.l_type = F_UNLCK; /* unlock */
249 unlock_it.l_pid = 0; /* pid not actually interesting */
250
251 while ( (rc = fcntl(mc->nMutexFD, F_SETLKW, &unlock_it)) < 0
252 && (errno == EINTR) )
253 ;
254 #endif
255 #ifdef SSL_USE_FLOCK
256 while ( (rc = flock(mc->nMutexFD, LOCK_UN)) < 0
257 && (errno == EINTR) )
258 ;
259 #endif
260
261 if (rc < 0)
262 return FALSE;
263 else
264 return TRUE;
265 }
266
267 /* _________________________________________________________________
268 **
269 ** Mutex Support (Process Semaphore)
270 ** _________________________________________________________________
271 */
272
ssl_mutex_sem_create(server_rec * s,pool * p)273 void ssl_mutex_sem_create(server_rec *s, pool *p)
274 {
275 int semid;
276 SSLModConfigRec *mc = myModConfig();
277 union ssl_ipc_semun semctlarg;
278 struct semid_ds semctlbuf;
279
280 semid = semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR);
281 if (semid == -1 && errno == EEXIST)
282 semid = semget(IPC_PRIVATE, 1, IPC_EXCL|S_IRUSR|S_IWUSR);
283 if (semid == -1) {
284 ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
285 "Parent process could not create private SSLMutex semaphore");
286 ssl_die();
287 }
288 semctlarg.val = 0;
289 if (semctl(semid, 0, SETVAL, semctlarg) < 0) {
290 ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
291 "Parent process could not initialize SSLMutex semaphore value");
292 ssl_die();
293 }
294 semctlbuf.sem_perm.uid = ap_user_id;
295 semctlbuf.sem_perm.gid = ap_group_id;
296 semctlbuf.sem_perm.mode = 0600;
297 semctlarg.buf = &semctlbuf;
298 if (semctl(semid, 0, IPC_SET, semctlarg) < 0) {
299 ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
300 "Parent process could not set permissions for SSLMutex semaphore");
301 ssl_die();
302 }
303 mc->nMutexSEMID = semid;
304 return;
305 }
306
ssl_mutex_sem_open(server_rec * s,pool * p)307 void ssl_mutex_sem_open(server_rec *s, pool *p)
308 {
309 return;
310 }
311
ssl_mutex_sem_remove(void * data)312 void ssl_mutex_sem_remove(void *data)
313 {
314 SSLModConfigRec *mc = myModConfig();
315
316 semctl(mc->nMutexSEMID, 0, IPC_RMID, 0);
317 return;
318 }
319
ssl_mutex_sem_acquire(void)320 BOOL ssl_mutex_sem_acquire(void)
321 {
322 int rc = 0;
323 SSLModConfigRec *mc = myModConfig();
324
325 struct sembuf sb[] = {
326 { 0, 0, 0 }, /* wait for semaphore */
327 { 0, 1, SEM_UNDO } /* increment semaphore */
328 };
329
330 while ( (rc = semop(mc->nMutexSEMID, sb, 2)) < 0
331 && (errno == EINTR) )
332 ;
333 if (rc != 0)
334 return FALSE;
335 else
336 return TRUE;
337 }
338
ssl_mutex_sem_release(void)339 BOOL ssl_mutex_sem_release(void)
340 {
341 int rc = 0;
342 SSLModConfigRec *mc = myModConfig();
343
344 struct sembuf sb[] = {
345 { 0, -1, SEM_UNDO } /* decrements semaphore */
346 };
347
348 while ( (rc = semop(mc->nMutexSEMID, sb, 1)) < 0
349 && (errno == EINTR) )
350 ;
351 if (rc != 0)
352 return FALSE;
353 else
354 return TRUE;
355 }
356
357