85 |
char **pp = env_cur = &env_var[0]; |
char **pp = env_cur = &env_var[0]; |
86 |
while (*pp) { |
while (*pp) { |
87 |
char *var = *pp; |
char *var = *pp; |
88 |
*strchrnul(var, '=') = '\0'; |
bb_unsetenv(var); |
|
unsetenv(var); |
|
89 |
free(var); |
free(var); |
90 |
*pp++ = NULL; |
*pp++ = NULL; |
91 |
} |
} |
184 |
int sock; |
int sock; |
185 |
int conn; |
int conn; |
186 |
unsigned backlog = 20; |
unsigned backlog = 20; |
187 |
|
unsigned opts; |
188 |
|
|
189 |
INIT_G(); |
INIT_G(); |
190 |
|
|
193 |
/* 3+ args, -i at most once, -p implies -h, -v is counter, -b N, -c N */ |
/* 3+ args, -i at most once, -p implies -h, -v is counter, -b N, -c N */ |
194 |
opt_complementary = "-3:i--i:ph:vv:b+:c+"; |
opt_complementary = "-3:i--i:ph:vv:b+:c+"; |
195 |
#ifdef SSLSVD |
#ifdef SSLSVD |
196 |
getopt32(argv, "+c:C:i:x:u:l:Eb:hpt:vU:/:Z:K:", |
opts = getopt32(argv, "+c:C:i:x:u:l:Eb:hpt:vU:/:Z:K:", |
197 |
&cmax, &str_C, &instructs, &instructs, &user, &preset_local_hostname, |
&cmax, &str_C, &instructs, &instructs, &user, &preset_local_hostname, |
198 |
&backlog, &str_t, &ssluser, &root, &cert, &key, &verbose |
&backlog, &str_t, &ssluser, &root, &cert, &key, &verbose |
199 |
); |
); |
200 |
#else |
#else |
201 |
/* "+": stop on first non-option */ |
/* "+": stop on first non-option */ |
202 |
getopt32(argv, "+c:C:i:x:u:l:Eb:hpt:v", |
opts = getopt32(argv, "+c:C:i:x:u:l:Eb:hpt:v", |
203 |
&cmax, &str_C, &instructs, &instructs, &user, &preset_local_hostname, |
&cmax, &str_C, &instructs, &instructs, &user, &preset_local_hostname, |
204 |
&backlog, &str_t, &verbose |
&backlog, &str_t, &verbose |
205 |
); |
); |
206 |
#endif |
#endif |
207 |
if (option_mask32 & OPT_C) { /* -C n[:message] */ |
if (opts & OPT_C) { /* -C n[:message] */ |
208 |
max_per_host = bb_strtou(str_C, &str_C, 10); |
max_per_host = bb_strtou(str_C, &str_C, 10); |
209 |
if (str_C[0]) { |
if (str_C[0]) { |
210 |
if (str_C[0] != ':') |
if (str_C[0] != ':') |
215 |
} |
} |
216 |
if (max_per_host > cmax) |
if (max_per_host > cmax) |
217 |
max_per_host = cmax; |
max_per_host = cmax; |
218 |
if (option_mask32 & OPT_u) { |
if (opts & OPT_u) { |
219 |
xget_uidgid(&ugid, user); |
xget_uidgid(&ugid, user); |
220 |
} |
} |
221 |
#ifdef SSLSVD |
#ifdef SSLSVD |
222 |
if (option_mask32 & OPT_U) ssluser = optarg; |
if (opts & OPT_U) ssluser = optarg; |
223 |
if (option_mask32 & OPT_slash) root = optarg; |
if (opts & OPT_slash) root = optarg; |
224 |
if (option_mask32 & OPT_Z) cert = optarg; |
if (opts & OPT_Z) cert = optarg; |
225 |
if (option_mask32 & OPT_K) key = optarg; |
if (opts & OPT_K) key = optarg; |
226 |
#endif |
#endif |
227 |
argv += optind; |
argv += optind; |
228 |
if (!argv[0][0] || LONE_CHAR(argv[0], '0')) |
if (!argv[0][0] || LONE_CHAR(argv[0], '0')) |
237 |
#ifdef SSLSVD |
#ifdef SSLSVD |
238 |
sslser = user; |
sslser = user; |
239 |
client = 0; |
client = 0; |
240 |
if ((getuid() == 0) && !(option_mask32 & OPT_u)) { |
if ((getuid() == 0) && !(opts & OPT_u)) { |
241 |
xfunc_exitcode = 100; |
xfunc_exitcode = 100; |
242 |
bb_error_msg_and_die("-U ssluser must be set when running as root"); |
bb_error_msg_and_die(bb_msg_you_must_be_root); |
243 |
} |
} |
244 |
if (option_mask32 & OPT_u) |
if (opts & OPT_u) |
245 |
if (!uidgid_get(&sslugid, ssluser, 1)) { |
if (!uidgid_get(&sslugid, ssluser, 1)) { |
246 |
if (errno) { |
if (errno) { |
247 |
bb_perror_msg_and_die("can't get user/group: %s", ssluser); |
bb_perror_msg_and_die("can't get user/group: %s", ssluser); |
251 |
if (!cert) cert = "./cert.pem"; |
if (!cert) cert = "./cert.pem"; |
252 |
if (!key) key = cert; |
if (!key) key = cert; |
253 |
if (matrixSslOpen() < 0) |
if (matrixSslOpen() < 0) |
254 |
fatal("cannot initialize ssl"); |
fatal("can't initialize ssl"); |
255 |
if (matrixSslReadKeys(&keys, cert, key, 0, ca) < 0) { |
if (matrixSslReadKeys(&keys, cert, key, 0, ca) < 0) { |
256 |
if (client) |
if (client) |
257 |
fatal("cannot read cert, key, or ca file"); |
fatal("can't read cert, key, or ca file"); |
258 |
fatal("cannot read cert or key file"); |
fatal("can't read cert or key file"); |
259 |
} |
} |
260 |
if (matrixSslNewSession(&ssl, keys, 0, SSL_FLAGS_SERVER) < 0) |
if (matrixSslNewSession(&ssl, keys, 0, SSL_FLAGS_SERVER) < 0) |
261 |
fatal("cannot create ssl session"); |
fatal("can't create ssl session"); |
262 |
#endif |
#endif |
263 |
|
|
264 |
sig_block(SIGCHLD); |
sig_block(SIGCHLD); |
277 |
setsockopt_reuseaddr(sock); |
setsockopt_reuseaddr(sock); |
278 |
sa_len = lsa->len; /* I presume sockaddr len stays the same */ |
sa_len = lsa->len; /* I presume sockaddr len stays the same */ |
279 |
xbind(sock, &lsa->u.sa, sa_len); |
xbind(sock, &lsa->u.sa, sa_len); |
280 |
if (tcp) |
if (tcp) { |
281 |
xlisten(sock, backlog); |
xlisten(sock, backlog); |
282 |
else /* udp: needed for recv_from_to to work: */ |
close_on_exec_on(sock); |
283 |
|
} else { /* udp: needed for recv_from_to to work: */ |
284 |
socket_want_pktinfo(sock); |
socket_want_pktinfo(sock); |
285 |
|
} |
286 |
/* ndelay_off(sock); - it is the default I think? */ |
/* ndelay_off(sock); - it is the default I think? */ |
287 |
|
|
288 |
#ifndef SSLSVD |
#ifndef SSLSVD |
289 |
if (option_mask32 & OPT_u) { |
if (opts & OPT_u) { |
290 |
/* drop permissions */ |
/* drop permissions */ |
291 |
xsetgid(ugid.gid); |
xsetgid(ugid.gid); |
292 |
xsetuid(ugid.uid); |
xsetuid(ugid.uid); |
295 |
|
|
296 |
if (verbose) { |
if (verbose) { |
297 |
char *addr = xmalloc_sockaddr2dotted(&lsa->u.sa); |
char *addr = xmalloc_sockaddr2dotted(&lsa->u.sa); |
298 |
bb_error_msg("listening on %s, starting", addr); |
if (opts & OPT_u) |
299 |
free(addr); |
bb_error_msg("listening on %s, starting, uid %u, gid %u", addr, |
|
#ifndef SSLSVD |
|
|
if (option_mask32 & OPT_u) |
|
|
printf(", uid %u, gid %u", |
|
300 |
(unsigned)ugid.uid, (unsigned)ugid.gid); |
(unsigned)ugid.uid, (unsigned)ugid.gid); |
301 |
#endif |
else |
302 |
|
bb_error_msg("listening on %s, starting", addr); |
303 |
|
free(addr); |
304 |
} |
} |
305 |
|
|
306 |
/* Main accept() loop */ |
/* Main accept() loop */ |
412 |
|
|
413 |
/* Child: prepare env, log, and exec prog */ |
/* Child: prepare env, log, and exec prog */ |
414 |
|
|
|
/* Closing tcp listening socket */ |
|
|
if (tcp) |
|
|
close(sock); |
|
|
|
|
415 |
{ /* vfork alert! every xmalloc in this block should be freed! */ |
{ /* vfork alert! every xmalloc in this block should be freed! */ |
416 |
char *local_hostname = local_hostname; /* for compiler */ |
char *local_hostname = local_hostname; /* for compiler */ |
417 |
char *local_addr = NULL; |
char *local_addr = NULL; |
419 |
char *free_me1 = NULL; |
char *free_me1 = NULL; |
420 |
char *free_me2 = NULL; |
char *free_me2 = NULL; |
421 |
|
|
422 |
if (verbose || !(option_mask32 & OPT_E)) { |
if (verbose || !(opts & OPT_E)) { |
423 |
if (!max_per_host) /* remote_addr is not yet known */ |
if (!max_per_host) /* remote_addr is not yet known */ |
424 |
free_me0 = remote_addr = xmalloc_sockaddr2dotted(&remote.u.sa); |
free_me0 = remote_addr = xmalloc_sockaddr2dotted(&remote.u.sa); |
425 |
if (option_mask32 & OPT_h) { |
if (opts & OPT_h) { |
426 |
free_me1 = remote_hostname = xmalloc_sockaddr2host_noport(&remote.u.sa); |
free_me1 = remote_hostname = xmalloc_sockaddr2host_noport(&remote.u.sa); |
427 |
if (!remote_hostname) { |
if (!remote_hostname) { |
428 |
bb_error_msg("cannot look up hostname for %s", remote_addr); |
bb_error_msg("can't look up hostname for %s", remote_addr); |
429 |
remote_hostname = remote_addr; |
remote_hostname = remote_addr; |
430 |
} |
} |
431 |
} |
} |
436 |
getsockname(0, &local.u.sa, &local.len); |
getsockname(0, &local.u.sa, &local.len); |
437 |
/* else: for UDP it is done earlier by parent */ |
/* else: for UDP it is done earlier by parent */ |
438 |
local_addr = xmalloc_sockaddr2dotted(&local.u.sa); |
local_addr = xmalloc_sockaddr2dotted(&local.u.sa); |
439 |
if (option_mask32 & OPT_h) { |
if (opts & OPT_h) { |
440 |
local_hostname = preset_local_hostname; |
local_hostname = preset_local_hostname; |
441 |
if (!local_hostname) { |
if (!local_hostname) { |
442 |
free_me2 = local_hostname = xmalloc_sockaddr2host_noport(&local.u.sa); |
free_me2 = local_hostname = xmalloc_sockaddr2host_noport(&local.u.sa); |
443 |
if (!local_hostname) |
if (!local_hostname) |
444 |
bb_error_msg_and_die("cannot look up hostname for %s", local_addr); |
bb_error_msg_and_die("can't look up hostname for %s", local_addr); |
445 |
} |
} |
446 |
/* else: local_hostname is not NULL, but is NOT malloced! */ |
/* else: local_hostname is not NULL, but is NOT malloced! */ |
447 |
} |
} |
453 |
remote_addr, |
remote_addr, |
454 |
cur_per_host, max_per_host); |
cur_per_host, max_per_host); |
455 |
} |
} |
456 |
bb_error_msg((option_mask32 & OPT_h) |
bb_error_msg((opts & OPT_h) |
457 |
? "start %u %s-%s (%s-%s)" |
? "start %u %s-%s (%s-%s)" |
458 |
: "start %u %s-%s", |
: "start %u %s-%s", |
459 |
pid, |
pid, |
461 |
local_hostname, remote_hostname); |
local_hostname, remote_hostname); |
462 |
} |
} |
463 |
|
|
464 |
if (!(option_mask32 & OPT_E)) { |
if (!(opts & OPT_E)) { |
465 |
/* setup ucspi env */ |
/* setup ucspi env */ |
466 |
const char *proto = tcp ? "TCP" : "UDP"; |
const char *proto = tcp ? "TCP" : "UDP"; |
467 |
|
|
477 |
xsetenv_plain("PROTO", proto); |
xsetenv_plain("PROTO", proto); |
478 |
xsetenv_proto(proto, "LOCALADDR", local_addr); |
xsetenv_proto(proto, "LOCALADDR", local_addr); |
479 |
xsetenv_proto(proto, "REMOTEADDR", remote_addr); |
xsetenv_proto(proto, "REMOTEADDR", remote_addr); |
480 |
if (option_mask32 & OPT_h) { |
if (opts & OPT_h) { |
481 |
xsetenv_proto(proto, "LOCALHOST", local_hostname); |
xsetenv_proto(proto, "LOCALHOST", local_hostname); |
482 |
xsetenv_proto(proto, "REMOTEHOST", remote_hostname); |
xsetenv_proto(proto, "REMOTEHOST", remote_hostname); |
483 |
} |
} |