X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/260d427bf66bcad3160bc19ff308a35c90c947db..67656ffcb8e1bdacdf86ef1f4b2df44fd4ce238e:/ssh-agent.c diff --git a/ssh-agent.c b/ssh-agent.c index f5f87cca..e8018bf3 100644 --- a/ssh-agent.c +++ b/ssh-agent.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-agent.c,v 1.39 2000/11/12 19:50:38 markus Exp $ */ +/* $OpenBSD: ssh-agent.c,v 1.75 2001/12/19 07:18:56 deraadt Exp $ */ /* * Author: Tatu Ylonen @@ -12,8 +12,7 @@ * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * - * SSH2 implementation, - * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,7 +36,10 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh-agent.c,v 1.39 2000/11/12 19:50:38 markus Exp $"); +RCSID("$OpenBSD: ssh-agent.c,v 1.75 2001/12/19 07:18:56 deraadt Exp $"); + +#include +#include #include "ssh.h" #include "rsa.h" @@ -47,26 +49,32 @@ RCSID("$OpenBSD: ssh-agent.c,v 1.39 2000/11/12 19:50:38 markus Exp $"); #include "packet.h" #include "getput.h" #include "mpaux.h" - -#include -#include -#include -#include #include "key.h" #include "authfd.h" +#include "cipher.h" #include "kex.h" #include "compat.h" +#include "log.h" + +#ifdef SMARTCARD +#include +#include "scard.h" +#endif + +typedef enum { + AUTH_UNUSED, + AUTH_SOCKET, + AUTH_CONNECTION +} sock_type; typedef struct { int fd; - enum { - AUTH_UNUSED, AUTH_SOCKET, AUTH_CONNECTION - } type; + sock_type type; Buffer input; Buffer output; } SocketEntry; -unsigned int sockets_alloc = 0; +u_int sockets_alloc = 0; SocketEntry *sockets = NULL; typedef struct { @@ -97,18 +105,18 @@ extern char *__progname; char *__progname; #endif -void +static void idtab_init(void) { int i; - for (i = 0; i <=2; i++){ + for (i = 0; i <=2; i++) { idtable[i].identities = NULL; idtable[i].nentries = 0; } } /* return private key table for requested protocol version */ -Idtab * +static Idtab * idtab_lookup(int version) { if (version < 1 || version > 2) @@ -117,7 +125,7 @@ idtab_lookup(int version) } /* return matching private key for given public key */ -Key * +static Key * lookup_private_key(Key *key, int *idx, int version) { int i; @@ -133,7 +141,7 @@ lookup_private_key(Key *key, int *idx, int version) } /* send list of supported public keys to 'client' */ -void +static void process_request_identities(SocketEntry *e, int version) { Idtab *tab = idtab_lookup(version); @@ -151,8 +159,8 @@ process_request_identities(SocketEntry *e, int version) buffer_put_bignum(&msg, id->key->rsa->e); buffer_put_bignum(&msg, id->key->rsa->n); } else { - unsigned char *blob; - unsigned int blen; + u_char *blob; + u_int blen; key_to_blob(id->key, &blob, &blen); buffer_put_string(&msg, blob, blen); xfree(blob); @@ -165,7 +173,7 @@ process_request_identities(SocketEntry *e, int version) } /* ssh1 only */ -void +static void process_authentication_challenge1(SocketEntry *e) { Key *key, *private; @@ -173,8 +181,8 @@ process_authentication_challenge1(SocketEntry *e) int i, len; Buffer msg; MD5_CTX md; - unsigned char buf[32], mdbuf[16], session_id[16]; - unsigned int response_type; + u_char buf[32], mdbuf[16], session_id[16]; + u_int response_type; buffer_init(&msg); key = key_new(KEY_RSA1); @@ -196,7 +204,8 @@ process_authentication_challenge1(SocketEntry *e) private = lookup_private_key(key, NULL, 1); if (private != NULL) { /* Decrypt the challenge using the private key. */ - rsa_private_decrypt(challenge, challenge, private->rsa); + if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0) + goto failure; /* The response is MD5 of decrypted challenge plus session id. */ len = BN_num_bytes(challenge); @@ -230,19 +239,19 @@ send: } /* ssh2 only */ -void +static void process_sign_request2(SocketEntry *e) { extern int datafellows; Key *key, *private; - unsigned char *blob, *data, *signature = NULL; - unsigned int blen, dlen, slen = 0; + u_char *blob, *data, *signature = NULL; + u_int blen, dlen, slen = 0; int flags; Buffer msg; int ok = -1; datafellows = 0; - + blob = buffer_get_string(&e->input, &blen); data = buffer_get_string(&e->input, &dlen); @@ -275,16 +284,16 @@ process_sign_request2(SocketEntry *e) } /* shared */ -void +static void process_remove_identity(SocketEntry *e, int version) { Key *key = NULL, *private; - unsigned char *blob; - unsigned int blen; - unsigned int bits; + u_char *blob; + u_int blen; + u_int bits; int success = 0; - switch(version){ + switch (version) { case 1: key = key_new(KEY_RSA1); bits = buffer_get_int(&e->input); @@ -293,7 +302,7 @@ process_remove_identity(SocketEntry *e, int version) if (bits != key_size(key)) log("Warning: identity keysize mismatch: actual %d, announced %d", - key_size(key), bits); + key_size(key), bits); break; case 2: blob = buffer_get_string(&e->input, &blen); @@ -308,8 +317,9 @@ process_remove_identity(SocketEntry *e, int version) /* * We have this key. Free the old key. Since we * don\'t want to leave empty slots in the middle of - * the array, we actually free the key there and copy - * data from the last entry. + * the array, we actually free the key there and move + * all the entries between the empty slot and the end + * of the array. */ Idtab *tab = idtab_lookup(version); key_free(tab->identities[idx].key); @@ -318,8 +328,13 @@ process_remove_identity(SocketEntry *e, int version) fatal("process_remove_identity: " "internal error: tab->nentries %d", tab->nentries); - if (idx != tab->nentries - 1) - tab->identities[idx] = tab->identities[tab->nentries - 1]; + if (idx != tab->nentries - 1) { + int i; + for (i = idx; i < tab->nentries - 1; i++) + tab->identities[i] = tab->identities[i+1]; + } + tab->identities[tab->nentries - 1].key = NULL; + tab->identities[tab->nentries - 1].comment = NULL; tab->nentries--; success = 1; } @@ -330,10 +345,10 @@ process_remove_identity(SocketEntry *e, int version) success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); } -void +static void process_remove_all_identities(SocketEntry *e, int version) { - unsigned int i; + u_int i; Idtab *tab = idtab_lookup(version); /* Loop over all identities and clear the keys. */ @@ -351,26 +366,7 @@ process_remove_all_identities(SocketEntry *e, int version) return; } -void -generate_additional_parameters(RSA *rsa) -{ - BIGNUM *aux; - BN_CTX *ctx; - /* Generate additional parameters */ - aux = BN_new(); - ctx = BN_CTX_new(); - - BN_sub(aux, rsa->q, BN_value_one()); - BN_mod(rsa->dmq1, rsa->d, aux, ctx); - - BN_sub(aux, rsa->p, BN_value_one()); - BN_mod(rsa->dmp1, rsa->d, aux, ctx); - - BN_clear_free(aux); - BN_CTX_free(ctx); -} - -void +static void process_add_identity(SocketEntry *e, int version) { Key *k = NULL; @@ -382,7 +378,7 @@ process_add_identity(SocketEntry *e, int version) switch (version) { case 1: k = key_new_private(KEY_RSA1); - buffer_get_int(&e->input); /* ignored */ + buffer_get_int(&e->input); /* ignored */ buffer_get_bignum(&e->input, k->rsa->n); buffer_get_bignum(&e->input, k->rsa->e); buffer_get_bignum(&e->input, k->rsa->d); @@ -393,13 +389,13 @@ process_add_identity(SocketEntry *e, int version) buffer_get_bignum(&e->input, k->rsa->p); /* q */ /* Generate additional parameters */ - generate_additional_parameters(k->rsa); + rsa_generate_additional_parameters(k->rsa); break; case 2: type_name = buffer_get_string(&e->input, NULL); - type = key_type_from_name(type_name); + type = key_type_from_name(type_name); xfree(type_name); - switch(type) { + switch (type) { case KEY_DSA: k = key_new_private(type); buffer_get_bignum2(&e->input, k->dsa->p); @@ -418,7 +414,7 @@ process_add_identity(SocketEntry *e, int version) buffer_get_bignum2(&e->input, k->rsa->q); /* Generate additional parameters */ - generate_additional_parameters(k->rsa); + rsa_generate_additional_parameters(k->rsa); break; default: buffer_clear(&e->input); @@ -452,17 +448,124 @@ send: success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); } + +#ifdef SMARTCARD +static void +process_add_smartcard_key (SocketEntry *e) +{ + Idtab *tab; + Key *n = NULL, *k = NULL; + char *sc_reader_id = NULL; + int success = 0; + + sc_reader_id = buffer_get_string(&e->input, NULL); + k = sc_get_key(sc_reader_id); + xfree(sc_reader_id); + + if (k == NULL) { + error("sc_get_pubkey failed"); + goto send; + } + success = 1; + + tab = idtab_lookup(1); + k->type = KEY_RSA1; + if (lookup_private_key(k, NULL, 1) == NULL) { + if (tab->nentries == 0) + tab->identities = xmalloc(sizeof(Identity)); + else + tab->identities = xrealloc(tab->identities, + (tab->nentries + 1) * sizeof(Identity)); + n = key_new(KEY_RSA1); + BN_copy(n->rsa->n, k->rsa->n); + BN_copy(n->rsa->e, k->rsa->e); + RSA_set_method(n->rsa, sc_get_engine()); + tab->identities[tab->nentries].key = n; + tab->identities[tab->nentries].comment = + xstrdup("rsa1 smartcard"); + tab->nentries++; + } + k->type = KEY_RSA; + tab = idtab_lookup(2); + if (lookup_private_key(k, NULL, 2) == NULL) { + if (tab->nentries == 0) + tab->identities = xmalloc(sizeof(Identity)); + else + tab->identities = xrealloc(tab->identities, + (tab->nentries + 1) * sizeof(Identity)); + n = key_new(KEY_RSA); + BN_copy(n->rsa->n, k->rsa->n); + BN_copy(n->rsa->e, k->rsa->e); + RSA_set_method(n->rsa, sc_get_engine()); + tab->identities[tab->nentries].key = n; + tab->identities[tab->nentries].comment = + xstrdup("rsa smartcard"); + tab->nentries++; + } + key_free(k); +send: + buffer_put_int(&e->output, 1); + buffer_put_char(&e->output, + success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); +} + +static void +process_remove_smartcard_key(SocketEntry *e) +{ + Key *k = NULL, *private; + int idx; + int success = 0; + char *sc_reader_id = NULL; + + sc_reader_id = buffer_get_string(&e->input, NULL); + k = sc_get_key(sc_reader_id); + xfree(sc_reader_id); + + if (k == NULL) { + error("sc_get_pubkey failed"); + } else { + k->type = KEY_RSA1; + private = lookup_private_key(k, &idx, 1); + if (private != NULL) { + Idtab *tab = idtab_lookup(1); + key_free(tab->identities[idx].key); + xfree(tab->identities[idx].comment); + if (idx != tab->nentries) + tab->identities[idx] = tab->identities[tab->nentries]; + tab->nentries--; + success = 1; + } + k->type = KEY_RSA; + private = lookup_private_key(k, &idx, 2); + if (private != NULL) { + Idtab *tab = idtab_lookup(2); + key_free(tab->identities[idx].key); + xfree(tab->identities[idx].comment); + if (idx != tab->nentries) + tab->identities[idx] = tab->identities[tab->nentries]; + tab->nentries--; + success = 1; + } + key_free(k); + } + + buffer_put_int(&e->output, 1); + buffer_put_char(&e->output, + success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); +} +#endif /* SMARTCARD */ + /* dispatch incoming messages */ -void +static void process_message(SocketEntry *e) { - unsigned int msg_len; - unsigned int type; - unsigned char *cp; + u_int msg_len; + u_int type; + u_char *cp; if (buffer_len(&e->input) < 5) return; /* Incomplete message. */ - cp = (unsigned char *) buffer_ptr(&e->input); + cp = (u_char *) buffer_ptr(&e->input); msg_len = GET_32BIT(cp); if (msg_len > 256 * 1024) { shutdown(e->fd, SHUT_RDWR); @@ -475,6 +578,7 @@ process_message(SocketEntry *e) buffer_consume(&e->input, 4); type = buffer_get_char(&e->input); + debug("type %d", type); switch (type) { /* ssh1 */ case SSH_AGENTC_RSA_CHALLENGE: @@ -508,6 +612,14 @@ process_message(SocketEntry *e) case SSH2_AGENTC_REMOVE_ALL_IDENTITIES: process_remove_all_identities(e, 2); break; +#ifdef SMARTCARD + case SSH_AGENTC_ADD_SMARTCARD_KEY: + process_add_smartcard_key(e); + break; + case SSH_AGENTC_REMOVE_SMARTCARD_KEY: + process_remove_smartcard_key(e); + break; +#endif /* SMARTCARD */ default: /* Unknown message. Respond with failure. */ error("Unknown message %d", type); @@ -518,10 +630,10 @@ process_message(SocketEntry *e) } } -void -new_socket(int type, int fd) +static void +new_socket(sock_type type, int fd) { - unsigned int i, old_alloc; + u_int i, old_alloc; if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) error("fcntl O_NONBLOCK: %s", strerror(errno)); @@ -550,17 +662,17 @@ new_socket(int type, int fd) buffer_init(&sockets[old_alloc].output); } -void -prepare_select(fd_set *readset, fd_set *writeset) +static int +prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, int *nallocp) { - unsigned int i; - for (i = 0; i < sockets_alloc; i++) + u_int i, sz; + int n = 0; + + for (i = 0; i < sockets_alloc; i++) { switch (sockets[i].type) { case AUTH_SOCKET: case AUTH_CONNECTION: - FD_SET(sockets[i].fd, readset); - if (buffer_len(&sockets[i].output) > 0) - FD_SET(sockets[i].fd, writeset); + n = MAX(n, sockets[i].fd); break; case AUTH_UNUSED: break; @@ -568,12 +680,43 @@ prepare_select(fd_set *readset, fd_set *writeset) fatal("Unknown socket type %d", sockets[i].type); break; } + } + + sz = howmany(n+1, NFDBITS) * sizeof(fd_mask); + if (*fdrp == NULL || sz > *nallocp) { + if (*fdrp) + xfree(*fdrp); + if (*fdwp) + xfree(*fdwp); + *fdrp = xmalloc(sz); + *fdwp = xmalloc(sz); + *nallocp = sz; + } + if (n < *fdl) + debug("XXX shrink: %d < %d", n, *fdl); + *fdl = n; + memset(*fdrp, 0, sz); + memset(*fdwp, 0, sz); + + for (i = 0; i < sockets_alloc; i++) { + switch (sockets[i].type) { + case AUTH_SOCKET: + case AUTH_CONNECTION: + FD_SET(sockets[i].fd, *fdrp); + if (buffer_len(&sockets[i].output) > 0) + FD_SET(sockets[i].fd, *fdwp); + break; + default: + break; + } + } + return (1); } -void +static void after_select(fd_set *readset, fd_set *writeset) { - unsigned int i; + u_int i; int len, sock; socklen_t slen; char buf[1024]; @@ -586,7 +729,8 @@ after_select(fd_set *readset, fd_set *writeset) case AUTH_SOCKET: if (FD_ISSET(sockets[i].fd, readset)) { slen = sizeof(sunaddr); - sock = accept(sockets[i].fd, (struct sockaddr *) & sunaddr, &slen); + sock = accept(sockets[i].fd, + (struct sockaddr *) &sunaddr, &slen); if (sock < 0) { perror("accept from AUTH_SOCKET"); break; @@ -597,8 +741,15 @@ after_select(fd_set *readset, fd_set *writeset) case AUTH_CONNECTION: if (buffer_len(&sockets[i].output) > 0 && FD_ISSET(sockets[i].fd, writeset)) { - len = write(sockets[i].fd, buffer_ptr(&sockets[i].output), - buffer_len(&sockets[i].output)); + do { + len = write(sockets[i].fd, + buffer_ptr(&sockets[i].output), + buffer_len(&sockets[i].output)); + if (len == -1 && (errno == EAGAIN || + errno == EINTR)) + continue; + break; + } while (1); if (len <= 0) { shutdown(sockets[i].fd, SHUT_RDWR); close(sockets[i].fd); @@ -610,7 +761,13 @@ after_select(fd_set *readset, fd_set *writeset) buffer_consume(&sockets[i].output, len); } if (FD_ISSET(sockets[i].fd, readset)) { - len = read(sockets[i].fd, buf, sizeof(buf)); + do { + len = read(sockets[i].fd, buf, sizeof(buf)); + if (len == -1 && (errno == EAGAIN || + errno == EINTR)) + continue; + break; + } while (1); if (len <= 0) { shutdown(sockets[i].fd, SHUT_RDWR); close(sockets[i].fd); @@ -628,57 +785,82 @@ after_select(fd_set *readset, fd_set *writeset) } } -void -check_parent_exists(int sig) -{ - if (parent_pid != -1 && kill(parent_pid, 0) < 0) { - /* printf("Parent has died - Authentication agent exiting.\n"); */ - exit(1); - } - signal(SIGALRM, check_parent_exists); - alarm(10); -} - -void +static void cleanup_socket(void) { - unlink(socket_name); - rmdir(socket_dir); + if (socket_name[0]) + unlink(socket_name); + if (socket_dir[0]) + rmdir(socket_dir); } -void +static void cleanup_exit(int i) { cleanup_socket(); exit(i); } -void -usage() +static void +cleanup_handler(int sig) { - fprintf(stderr, "ssh-agent version %s\n", SSH_VERSION); - fprintf(stderr, "Usage: %s [-c | -s] [-k] [command {args...]]\n", - __progname); + cleanup_socket(); + _exit(2); +} + +static void +check_parent_exists(int sig) +{ + int save_errno = errno; + + if (parent_pid != -1 && kill(parent_pid, 0) < 0) { + /* printf("Parent has died - Authentication agent exiting.\n"); */ + cleanup_handler(sig); /* safe */ + } + signal(SIGALRM, check_parent_exists); + alarm(10); + errno = save_errno; +} + +static void +usage(void) +{ + fprintf(stderr, "Usage: %s [options] [command [args ...]]\n", + __progname); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -c Generate C-shell commands on stdout.\n"); + fprintf(stderr, " -s Generate Bourne shell commands on stdout.\n"); + fprintf(stderr, " -k Kill the current agent.\n"); + fprintf(stderr, " -d Debug mode.\n"); exit(1); } int main(int ac, char **av) { - fd_set readset, writeset; - int sock, c_flag = 0, k_flag = 0, s_flag = 0, ch; + int sock, c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0, ch, nalloc; struct sockaddr_un sunaddr; +#ifdef HAVE_SETRLIMIT + struct rlimit rlim; +#endif +#ifdef HAVE_CYGWIN + int prev_mask; +#endif pid_t pid; char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid]; extern int optind; - + fd_set *readsetp = NULL, *writesetp = NULL; + + SSLeay_add_all_algorithms(); + __progname = get_progname(av[0]); init_rng(); - + seed_rng(); + #ifdef __GNU_LIBRARY__ - while ((ch = getopt(ac, av, "+cks")) != -1) { + while ((ch = getopt(ac, av, "+cdks")) != -1) { #else /* __GNU_LIBRARY__ */ - while ((ch = getopt(ac, av, "cks")) != -1) { + while ((ch = getopt(ac, av, "cdks")) != -1) { #endif /* __GNU_LIBRARY__ */ switch (ch) { case 'c': @@ -694,6 +876,11 @@ main(int ac, char **av) usage(); s_flag++; break; + case 'd': + if (d_flag) + usage(); + d_flag++; + break; default: usage(); } @@ -701,10 +888,10 @@ main(int ac, char **av) ac -= optind; av += optind; - if (ac > 0 && (c_flag || k_flag || s_flag)) + if (ac > 0 && (c_flag || k_flag || s_flag || d_flag)) usage(); - if (ac == 0 && !c_flag && !k_flag && !s_flag) { + if (ac == 0 && !c_flag && !k_flag && !s_flag && !d_flag) { shell = getenv("SHELL"); if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0) c_flag = 1; @@ -713,14 +900,13 @@ main(int ac, char **av) pidstr = getenv(SSH_AGENTPID_ENV_NAME); if (pidstr == NULL) { fprintf(stderr, "%s not set, cannot kill agent\n", - SSH_AGENTPID_ENV_NAME); + SSH_AGENTPID_ENV_NAME); exit(1); } pid = atoi(pidstr); - if (pid < 1) { /* XXX PID_MAX check too */ - /* Yes, PID_MAX check please */ + if (pid < 1) { fprintf(stderr, "%s=\"%s\", which is not a good PID\n", - SSH_AGENTPID_ENV_NAME, pidstr); + SSH_AGENTPID_ENV_NAME, pidstr); exit(1); } if (kill(pid, SIGTERM) == -1) { @@ -742,7 +928,7 @@ main(int ac, char **av) exit(1); } snprintf(socket_name, sizeof socket_name, "%s/agent.%d", socket_dir, - parent_pid); + parent_pid); /* * Create socket early so it will exist before command gets run from @@ -756,18 +942,36 @@ main(int ac, char **av) memset(&sunaddr, 0, sizeof(sunaddr)); sunaddr.sun_family = AF_UNIX; strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path)); +#ifdef HAVE_CYGWIN + prev_mask = umask(0177); +#endif if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) { perror("bind"); +#ifdef HAVE_CYGWIN + umask(prev_mask); +#endif cleanup_exit(1); } +#ifdef HAVE_CYGWIN + umask(prev_mask); +#endif if (listen(sock, 5) < 0) { perror("listen"); cleanup_exit(1); } + /* * Fork, and have the parent execute the command, if any, or present * the socket data. The child continues as the authentication agent. */ + if (d_flag) { + log_init(__progname, SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 1); + format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n"; + printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name, + SSH_AUTHSOCKET_ENV_NAME); + printf("echo Agent pid %d;\n", parent_pid); + goto skip; + } pid = fork(); if (pid == -1) { perror("fork"); @@ -779,9 +983,9 @@ main(int ac, char **av) if (ac == 0) { format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n"; printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name, - SSH_AUTHSOCKET_ENV_NAME); + SSH_AUTHSOCKET_ENV_NAME); printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf, - SSH_AGENTPID_ENV_NAME); + SSH_AGENTPID_ENV_NAME); printf("echo Agent pid %d;\n", pid); exit(0); } @@ -794,14 +998,27 @@ main(int ac, char **av) perror(av[0]); exit(1); } + + if (setsid() == -1) { + perror("setsid"); + cleanup_exit(1); + } + + (void)chdir("/"); close(0); close(1); close(2); - if (setsid() == -1) { - perror("setsid"); +#ifdef HAVE_SETRLIMIT + /* deny core dumps, since memory contains unencrypted private keys */ + rlim.rlim_cur = rlim.rlim_max = 0; + if (setrlimit(RLIMIT_CORE, &rlim) < 0) { + perror("setrlimit rlimit_core failed"); cleanup_exit(1); } +#endif + +skip: if (atexit(cleanup_socket) < 0) { perror("atexit"); cleanup_exit(1); @@ -812,20 +1029,21 @@ main(int ac, char **av) alarm(10); } idtab_init(); - signal(SIGINT, SIG_IGN); + if (!d_flag) + signal(SIGINT, SIG_IGN); signal(SIGPIPE, SIG_IGN); - signal(SIGHUP, cleanup_exit); - signal(SIGTERM, cleanup_exit); + signal(SIGHUP, cleanup_handler); + signal(SIGTERM, cleanup_handler); + nalloc = 0; + while (1) { - FD_ZERO(&readset); - FD_ZERO(&writeset); - prepare_select(&readset, &writeset); - if (select(max_fd + 1, &readset, &writeset, NULL, NULL) < 0) { + prepare_select(&readsetp, &writesetp, &max_fd, &nalloc); + if (select(max_fd + 1, readsetp, writesetp, NULL, NULL) < 0) { if (errno == EINTR) continue; exit(1); } - after_select(&readset, &writeset); + after_select(readsetp, writesetp); } /* NOTREACHED */ }