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

Annotation of /hydra/src/boa.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.14 - (hide 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 nmav 1.1 /*
2 nmav 1.12 * Hydra, an http server (based on Boa 0.94.13)
3 nmav 1.1 * 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 nmav 1.14 /* $Id: boa.c,v 1.13 2002/09/28 17:49:13 nmav Exp $*/
26 nmav 1.1
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 nmav 1.13 void hic_init(void);
47 nmav 1.1 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 nmav 1.3 socket_type server_s[2] = {{ -1, 0, 0, 0}, { -1, -1, 0, 0 }}; /* boa socket */
57 nmav 1.1 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 nmav 1.11 #ifdef ENABLE_SSL
145 nmav 1.1 if (boa_ssl) {
146     initialize_ssl();
147     }
148 nmav 1.11 #endif
149 nmav 1.5
150     initialize_mmap();
151 nmav 1.1
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 nmav 1.8
192 nmav 1.14 #ifdef ENABLE_HIC
193 nmav 1.10 hic_init();
194 nmav 1.14 #endif
195 nmav 1.1
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 nmav 1.11 #ifdef ENABLE_SSL
207 nmav 1.1 if (boa_ssl) {
208 nmav 1.4 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 nmav 1.1 alarm( ssl_params_refresh);
215     }
216 nmav 1.11 #endif
217 nmav 1.1
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 nmav 1.9 "%s: Generated pool of %d threads.\n", SERVER_NAME, max_threads);
297 nmav 1.1 }
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 nmav 1.2 int i;
309     server_params *params = global_server_params;
310     int max_threads = server_max_threads;
311 nmav 1.1 #else
312 nmav 1.2 int max_threads = 1;
313 nmav 1.1 #endif
314    
315 nmav 1.2 if (global_server_params_size < max_threads) {
316 nmav 1.1 log_error_time();
317     fprintf(stderr,
318     "Cannot increase threads on runtime.\n");
319     max_threads = global_server_params_size;
320 nmav 1.2 }
321 nmav 1.1
322     #ifdef ENABLE_SMP
323 nmav 1.2 for( i=1;i<max_threads;i++) {
324 nmav 1.1 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 nmav 1.2 }
334 nmav 1.1 #endif
335    
336 nmav 1.2 if (max_threads > 0) {
337 nmav 1.1 log_error_time();
338     fprintf(stderr,
339     "Regenerated a pool of %d threads.\n", max_threads);
340 nmav 1.2 }
341 nmav 1.1
342 nmav 1.2 return;
343 nmav 1.1 }
344    
345 nmav 1.8 #ifdef ENABLE_HIC
346 nmav 1.10
347     pthread_t hic_tid;
348 nmav 1.8
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 nmav 1.13 void hic_init()
353 nmav 1.8 {
354    
355     #ifdef ENABLE_SMP
356    
357 nmav 1.10 if (pthread_create( &hic_tid, NULL, &hic_main_loop, NULL) != 0)
358 nmav 1.8 {
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 nmav 1.9 "%s: Dispatched HIC main thread.\n", SERVER_NAME);
368 nmav 1.8
369     #endif
370    
371 nmav 1.10 return;
372 nmav 1.8 }
373    
374     #endif /* ENABLE_HIC */
375 nmav 1.1
376     static socket_type create_server_socket( int port, int secure)
377     {
378     socket_type server_s;
379    
380     server_s.secure = secure;
381 nmav 1.3 server_s.port = port;
382 nmav 1.1
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 nmav 1.6 fputs(SERVER_NAME": don't know where server root is. Please #define "
472 nmav 1.5 "SERVER_ROOT in defines.h\n"
473 nmav 1.1 "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