/[hydra]/hydra/src/boa.c
ViewVC logotype

Contents of /hydra/src/boa.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.14 - (show annotations)
Sat Sep 28 18:32:05 2002 UTC (21 years, 6 months ago) by nmav
Branch: MAIN
CVS Tags: hydra_0_0_3
Changes since 1.13: +3 -1 lines
File MIME type: text/plain
corrected stuff which made compiling fail, if HIC was disabled.

1 /*
2 * Hydra, an http server (based on Boa 0.94.13)
3 * Copyright (C) 1995 Paul Phillips <paulp@go2net.com>
4 * Some changes Copyright (C) 1996 Charles F. Randall <crandall@goldsys.com>
5 * Some changes Copyright (C) 1996 Larry Doolittle <ldoolitt@boa.org>
6 * Some changes Copyright (C) 1996-2002 Jon Nelson <jnelson@boa.org>
7 * Portions Copyright (C) 2002 Nikos Mavroyanopoulos <nmav@gnutls.org>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 1, or (at your option)
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25 /* $Id: boa.c,v 1.13 2002/09/28 17:49:13 nmav Exp $*/
26
27 #include "boa.h"
28 #include "ssl.h"
29 #include <sys/resource.h>
30 #ifdef ENABLE_SMP
31 pthread_t father_id;
32 #endif
33
34 extern int ssl_params_refresh;
35
36 /* globals */
37 int backlog = SO_MAXCONN;
38 time_t start_time;
39
40 time_t current_time;
41
42
43 /* static to boa.c */
44 static void fixup_server_root(void);
45 static socket_type create_server_socket( int port, int);
46 void hic_init(void);
47 static void drop_privs(void);
48 static server_params *smp_init(socket_type server_s[2]);
49 static int sock_opt = 1;
50 static int do_fork = 1;
51 int devnullfd = -1;
52
53 int main(int argc, char **argv)
54 {
55 int c; /* command line arg */
56 socket_type server_s[2] = {{ -1, 0, 0, 0}, { -1, -1, 0, 0 }}; /* boa socket */
57 server_params *params;
58
59 /* set umask to u+rw, u-x, go-rwx */
60 c = umask(~0600);
61 if (c == -1) {
62 perror("umask");
63 exit(1);
64 }
65
66 devnullfd = open("/dev/null", 0);
67
68 /* make STDIN and STDOUT point to /dev/null */
69 if (devnullfd == -1) {
70 DIE("can't open /dev/null");
71 }
72
73 if (dup2(devnullfd, STDIN_FILENO) == -1) {
74 DIE("can't dup2 /dev/null to STDIN_FILENO");
75 }
76
77 if (dup2(devnullfd, STDOUT_FILENO) == -1) {
78 DIE("can't dup2 /dev/null to STDOUT_FILENO");
79 }
80
81 /* but first, update timestamp, because log_error_time uses it */
82 (void) time(&current_time);
83
84 while ((c = getopt(argc, argv, "c:r:d")) != -1) {
85 switch (c) {
86 case 'c':
87 if (server_root)
88 free(server_root);
89 server_root = strdup(optarg);
90 if (!server_root) {
91 perror("strdup (for server_root)");
92 exit(1);
93 }
94 break;
95 case 'r':
96 if (chdir(optarg) == -1) {
97 log_error_time();
98 perror("chdir (to chroot)");
99 exit(1);
100 }
101 if (chroot(optarg) == -1) {
102 log_error_time();
103 perror("chroot");
104 exit(1);
105 }
106 if (chdir("/") == -1) {
107 log_error_time();
108 perror("chdir (after chroot)");
109 exit(1);
110 }
111 break;
112 case 'd':
113 do_fork = 0;
114 break;
115 default:
116 fprintf(stderr, "Usage: %s [-c serverroot] [-r chroot] [-d]\n", argv[0]);
117 exit(1);
118 }
119 }
120
121 fixup_server_root();
122 read_config_files();
123 open_logs();
124
125 if ((boa_ssl >= 2 || boa_ssl == 0) && server_port > 0) {
126 server_s[0] = create_server_socket( server_port, 0);
127 }
128
129 if (boa_ssl != 0 && ssl_port > 0) {
130 server_s[1] = create_server_socket( ssl_port, 1);
131 }
132
133 if (server_s[1].socket == -1 && server_s[0].socket == -1) {
134 log_error_time();
135 fprintf(stderr, "Could not initialize sockets\n");
136 exit(1);
137 }
138
139 init_signals();
140 drop_privs();
141 create_common_env();
142 build_needs_escape();
143
144 #ifdef ENABLE_SSL
145 if (boa_ssl) {
146 initialize_ssl();
147 }
148 #endif
149
150 initialize_mmap();
151
152 if (max_connections < 1) {
153 struct rlimit rl;
154
155 /* has not been set explicitly */
156 c = getrlimit(RLIMIT_NOFILE, &rl);
157 if (c < 0) {
158 perror("getrlimit");
159 exit(1);
160 }
161 max_connections = rl.rlim_cur;
162 }
163
164 /* background ourself */
165 if (do_fork) {
166 switch(fork()) {
167 case -1:
168 /* error */
169 perror("fork");
170 exit(1);
171 break;
172 case 0:
173 /* child, success */
174 break;
175 default:
176 /* parent, success */
177 exit(0);
178 break;
179 }
180 }
181
182 /* main loop */
183 timestamp();
184
185 start_time = current_time;
186
187 /* Blocks signals that are not supposed to be catched
188 * by the children.
189 */
190 block_main_signals();
191
192 #ifdef ENABLE_HIC
193 hic_init();
194 #endif
195
196 /* spawn the children pool
197 */
198 params = smp_init( server_s);
199
200 /* unblock signals for daddy
201 */
202 unblock_main_signals();
203
204 /* regenerate parameters in that time interval
205 */
206 #ifdef ENABLE_SSL
207 if (boa_ssl) {
208 if (ssl_params_refresh < DEFAULT_SSL_PARAMS_REFRESH) {
209 log_error_time();
210 fprintf(stderr, "SSL parameters will be refreshed every %d minutes\n",
211 DEFAULT_SSL_PARAMS_REFRESH/60);
212 ssl_params_refresh = DEFAULT_SSL_PARAMS_REFRESH;
213 }
214 alarm( ssl_params_refresh);
215 }
216 #endif
217
218 select_loop( params);
219
220 return 0;
221 }
222
223 server_params *global_server_params;
224 int global_server_params_size;
225
226 extern int server_max_threads;
227
228 /* This function will return a server_params pointer. This
229 * pointer is to be used as a pointer to the select loop.
230 */
231 static server_params* smp_init( socket_type server_s[2])
232 {
233 int i;
234 server_params *params;
235
236 #ifdef ENABLE_SMP
237 pthread_t tid;
238 int max_threads = server_max_threads;
239
240 father_id = pthread_self();
241 #else
242 const int max_threads = 1;
243 #endif
244
245 params = malloc( sizeof(server_params) * max_threads);
246 if (params == NULL) {
247 log_error_time();
248 fprintf(stderr,
249 "Could not allocate memory.\n");
250 exit(1);
251 }
252
253 for (i=0;i<max_threads;i++) {
254 params[i].server_s[0] = server_s[0];
255 params[i].server_s[1] = server_s[1];
256 params[i].request_ready = NULL;
257 params[i].request_block = NULL;
258 params[i].request_free = NULL;
259
260 /* for signal handling */
261 params[i].sighup_flag = 0;
262 params[i].sigchld_flag = 0;
263 params[i].sigalrm_flag = 0;
264 params[i].sigusr1_flag = 0;
265 params[i].sigterm_flag = 0;
266
267 params[i].sockbufsize = SOCKETBUF_SIZE;
268
269 params[i].status.requests = 0;
270 params[i].status.errors = 0;
271
272 params[i].total_connections = 0;
273 params[i].max_fd = 0;
274
275 params[i].handle_sigbus = 0;
276 }
277
278 #ifdef ENABLE_SMP
279 params[0].tid = father_id;
280
281 for( i=1;i<max_threads;i++) {
282 if (pthread_create( &tid, NULL, &select_loop, &params[i]) != 0)
283 {
284 log_error_time();
285 fprintf(stderr,
286 "Could not dispatch threads.\n");
287 exit(1);
288 }
289 params[i].tid = tid;
290 }
291 #endif
292
293 if (max_threads > 1) {
294 log_error_time();
295 fprintf(stderr,
296 "%s: Generated pool of %d threads.\n", SERVER_NAME, max_threads);
297 }
298
299 global_server_params_size = max_threads;
300 global_server_params = params;
301
302 return &params[0];
303 }
304
305 void smp_reinit()
306 {
307 #ifdef ENABLE_SMP
308 int i;
309 server_params *params = global_server_params;
310 int max_threads = server_max_threads;
311 #else
312 int max_threads = 1;
313 #endif
314
315 if (global_server_params_size < max_threads) {
316 log_error_time();
317 fprintf(stderr,
318 "Cannot increase threads on runtime.\n");
319 max_threads = global_server_params_size;
320 }
321
322 #ifdef ENABLE_SMP
323 for( i=1;i<max_threads;i++) {
324 pthread_t tid;
325 if (pthread_create( &tid, NULL, &select_loop, &params[i]) != 0)
326 {
327 log_error_time();
328 fprintf(stderr,
329 "Could not dispatch threads.\n");
330 exit(1);
331 }
332 params[i].tid = tid;
333 }
334 #endif
335
336 if (max_threads > 0) {
337 log_error_time();
338 fprintf(stderr,
339 "Regenerated a pool of %d threads.\n", max_threads);
340 }
341
342 return;
343 }
344
345 #ifdef ENABLE_HIC
346
347 pthread_t hic_tid;
348
349 /* This function will return a server_params pointer. This
350 * pointer is to be used as a pointer to the select loop.
351 */
352 void hic_init()
353 {
354
355 #ifdef ENABLE_SMP
356
357 if (pthread_create( &hic_tid, NULL, &hic_main_loop, NULL) != 0)
358 {
359 log_error_time();
360 fprintf(stderr,
361 "Could not dispatch hic thread.\n");
362 exit(1);
363 }
364
365 log_error_time();
366 fprintf(stderr,
367 "%s: Dispatched HIC main thread.\n", SERVER_NAME);
368
369 #endif
370
371 return;
372 }
373
374 #endif /* ENABLE_HIC */
375
376 static socket_type create_server_socket( int port, int secure)
377 {
378 socket_type server_s;
379
380 server_s.secure = secure;
381 server_s.port = port;
382
383 server_s.socket = socket(SERVER_AF, SOCK_STREAM, IPPROTO_TCP);
384 if (server_s.socket == -1) {
385 DIE("unable to create socket");
386 }
387
388 /* server socket is nonblocking */
389 if (set_nonblock_fd(server_s.socket) == -1) {
390 DIE("fcntl: unable to set server socket to nonblocking");
391 }
392
393 /* close server socket on exec so cgi's can't write to it */
394 if (fcntl(server_s.socket, F_SETFD, 1) == -1) {
395 DIE("can't set close-on-exec on server socket!");
396 }
397
398 /* reuse socket addr */
399 if ((setsockopt(server_s.socket, SOL_SOCKET, SO_REUSEADDR, (void *) &sock_opt,
400 sizeof (sock_opt))) == -1) {
401 DIE("setsockopt");
402 }
403
404 /* internet family-specific code encapsulated in bind_server() */
405 if (bind_server(server_s.socket, server_ip, port) == -1) {
406 DIE("unable to bind");
407 }
408
409 /* listen: large number just in case your kernel is nicely tweaked */
410 if (listen(server_s.socket, backlog) == -1) {
411 DIE("unable to listen");
412 }
413 return server_s;
414 }
415
416 static void drop_privs(void)
417 {
418 /* give away our privs if we can */
419 if (getuid() == 0) {
420 struct passwd *passwdbuf;
421 passwdbuf = getpwuid(server_uid);
422 if (passwdbuf == NULL) {
423 DIE("getpwuid");
424 }
425 if (initgroups(passwdbuf->pw_name, passwdbuf->pw_gid) == -1) {
426 DIE("initgroups");
427 }
428 if (setgid(server_gid) == -1) {
429 DIE("setgid");
430 }
431 if (setuid(server_uid) == -1) {
432 DIE("setuid");
433 }
434 /* test for failed-but-return-was-successful setuid
435 * http://www.securityportal.com/list-archive/bugtraq/2000/Jun/0101.html
436 */
437 if (setuid(0) != -1) {
438 DIE("icky Linux kernel bug!");
439 }
440 } else {
441 if (server_gid || server_uid) {
442 log_error_time();
443 fprintf(stderr, "Warning: "
444 "Not running as root: no attempt to change"
445 " to uid %d gid %d\n", server_uid, server_gid);
446 }
447 server_gid = getgid();
448 server_uid = getuid();
449 }
450 }
451
452 /*
453 * Name: fixup_server_root
454 *
455 * Description: Makes sure the server root is valid.
456 *
457 */
458
459 static void fixup_server_root()
460 {
461 char *dirbuf;
462
463 if (!server_root) {
464 #ifdef SERVER_ROOT
465 server_root = strdup(SERVER_ROOT);
466 if (!server_root) {
467 perror("strdup (SERVER_ROOT)");
468 exit(1);
469 }
470 #else
471 fputs(SERVER_NAME": don't know where server root is. Please #define "
472 "SERVER_ROOT in defines.h\n"
473 "and recompile, or use the -c command line option to "
474 "specify it.\n", stderr);
475 exit(1);
476 #endif
477 }
478
479 if (chdir(server_root) == -1) {
480 fprintf(stderr, "Could not chdir to \"%s\": aborting\n",
481 server_root);
482 exit(1);
483 }
484
485 dirbuf = normalize_path(server_root);
486 free(server_root);
487 server_root = dirbuf;
488 }
489

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26