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

Annotation of /hydra/src/boa.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4 - (hide annotations)
Tue Sep 24 18:07:58 2002 UTC (21 years, 7 months ago) by nmav
Branch: MAIN
Changes since 1.3: +7 -1 lines
File MIME type: text/plain
*** empty log message ***

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26