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

Contents of /hydra/src/boa.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (show annotations)
Mon Sep 23 17:56:41 2002 UTC (21 years, 7 months ago) by nmav
Branch: MAIN
Changes since 1.1: +12 -13 lines
File MIME type: text/plain
Fixes in configure script. Added support for the TCP_CORK tcp option in linux systems.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26