=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/ssh-agent.c,v retrieving revision 1.37.2.6 retrieving revision 1.38 diff -u -r1.37.2.6 -r1.38 --- src/usr.bin/ssh/ssh-agent.c 2002/03/08 17:04:43 1.37.2.6 +++ src/usr.bin/ssh/ssh-agent.c 2000/11/12 19:03:28 1.38 @@ -1,3 +1,5 @@ +/* $OpenBSD: ssh-agent.c,v 1.38 2000/11/12 19:03:28 markus Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -10,7 +12,8 @@ * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * - * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * SSH2 implementation, + * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,53 +37,47 @@ */ #include "includes.h" -#include -RCSID("$OpenBSD: ssh-agent.c,v 1.37.2.6 2002/03/08 17:04:43 brad Exp $"); +RCSID("$OpenBSD: ssh-agent.c,v 1.38 2000/11/12 19:03:28 markus Exp $"); -#include -#include - #include "ssh.h" #include "rsa.h" #include "buffer.h" #include "bufaux.h" #include "xmalloc.h" +#include "packet.h" #include "getput.h" +#include "mpaux.h" + +#include +#include +#include +#include #include "key.h" #include "authfd.h" +#include "dsa.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; - sock_type type; + enum { + AUTH_UNUSED, AUTH_SOCKET, AUTH_CONNECTION + } type; Buffer input; Buffer output; } SocketEntry; -u_int sockets_alloc = 0; +unsigned int sockets_alloc = 0; SocketEntry *sockets = NULL; -typedef struct identity { - TAILQ_ENTRY(identity) next; +typedef struct { Key *key; char *comment; } Identity; typedef struct { int nentries; - TAILQ_HEAD(idqueue, identity) idlist; + Identity *identities; } Idtab; /* private key table, one per protocol version */ @@ -97,18 +94,18 @@ extern char *__progname; -static void +void idtab_init(void) { int i; - for (i = 0; i <=2; i++) { - TAILQ_INIT(&idtable[i].idlist); + for (i = 0; i <=2; i++){ + idtable[i].identities = NULL; idtable[i].nentries = 0; } } /* return private key table for requested protocol version */ -static Idtab * +Idtab * idtab_lookup(int version) { if (version < 1 || version > 2) @@ -117,48 +114,43 @@ } /* return matching private key for given public key */ -static Identity * -lookup_identity(Key *key, int version) +Key * +lookup_private_key(Key *key, int *idx, int version) { - Identity *id; - + int i; Idtab *tab = idtab_lookup(version); - TAILQ_FOREACH(id, &tab->idlist, next) { - if (key_equal(key, id->key)) - return (id); + for (i = 0; i < tab->nentries; i++) { + if (key_equal(key, tab->identities[i].key)) { + if (idx != NULL) + *idx = i; + return tab->identities[i].key; + } } - return (NULL); + return NULL; } -static void -free_identity(Identity *id) -{ - key_free(id->key); - xfree(id->comment); - xfree(id); -} - /* send list of supported public keys to 'client' */ -static void +void process_request_identities(SocketEntry *e, int version) { Idtab *tab = idtab_lookup(version); Buffer msg; - Identity *id; + int i; buffer_init(&msg); buffer_put_char(&msg, (version == 1) ? SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER); buffer_put_int(&msg, tab->nentries); - TAILQ_FOREACH(id, &tab->idlist, next) { - if (id->key->type == KEY_RSA1) { + for (i = 0; i < tab->nentries; i++) { + Identity *id = &tab->identities[i]; + if (id->key->type == KEY_RSA) { buffer_put_int(&msg, BN_num_bits(id->key->rsa->n)); buffer_put_bignum(&msg, id->key->rsa->e); buffer_put_bignum(&msg, id->key->rsa->n); } else { - u_char *blob; - u_int blen; - key_to_blob(id->key, &blob, &blen); + unsigned char *blob; + unsigned int blen; + dsa_make_key_blob(id->key, &blob, &blen); buffer_put_string(&msg, blob, blen); xfree(blob); } @@ -170,22 +162,20 @@ } /* ssh1 only */ -static void +void process_authentication_challenge1(SocketEntry *e) { - Identity *id; - Key *key; + Key *key, *private; BIGNUM *challenge; int i, len; Buffer msg; MD5_CTX md; - u_char buf[32], mdbuf[16], session_id[16]; - u_int response_type; + unsigned char buf[32], mdbuf[16], session_id[16]; + unsigned int response_type; buffer_init(&msg); - key = key_new(KEY_RSA1); - if ((challenge = BN_new()) == NULL) - fatal("process_authentication_challenge1: BN_new failed"); + key = key_new(KEY_RSA); + challenge = BN_new(); buffer_get_int(&e->input); /* ignored */ buffer_get_bignum(&e->input, key->rsa->e); @@ -195,17 +185,15 @@ /* Only protocol 1.1 is supported */ if (buffer_len(&e->input) == 0) goto failure; - buffer_get(&e->input, session_id, 16); + buffer_get(&e->input, (char *) session_id, 16); response_type = buffer_get_int(&e->input); if (response_type != 1) goto failure; - id = lookup_identity(key, 1); - if (id != NULL) { - Key *private = id->key; + private = lookup_private_key(key, NULL, 1); + if (private != NULL) { /* Decrypt the challenge using the private key. */ - if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0) - goto failure; + rsa_private_decrypt(challenge, challenge, private->rsa); /* The response is MD5 of decrypted challenge plus session id. */ len = BN_num_bytes(challenge); @@ -239,19 +227,19 @@ } /* ssh2 only */ -static void +void process_sign_request2(SocketEntry *e) { extern int datafellows; - Key *key; - u_char *blob, *data, *signature = NULL; - u_int blen, dlen, slen = 0; + Key *key, *private; + unsigned char *blob, *data, *signature = NULL; + unsigned 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); @@ -259,11 +247,11 @@ if (flags & SSH_AGENT_OLD_SIGNATURE) datafellows = SSH_BUG_SIGBLOB; - key = key_from_blob(blob, blen); + key = dsa_key_from_blob(blob, blen); if (key != NULL) { - Identity *id = lookup_identity(key, 2); - if (id != NULL) - ok = key_sign(id->key, &signature, &slen, data, dlen); + private = lookup_private_key(key, NULL, 2); + if (private != NULL) + ok = dsa_sign(private, &signature, &slen, data, dlen); } key_free(key); buffer_init(&msg); @@ -284,49 +272,51 @@ } /* shared */ -static void +void process_remove_identity(SocketEntry *e, int version) { - Key *key = NULL; - u_char *blob; - u_int blen; - u_int bits; + Key *key = NULL, *private; + unsigned char *blob; + unsigned int blen; + unsigned int bits; int success = 0; - switch (version) { + switch(version){ case 1: - key = key_new(KEY_RSA1); + key = key_new(KEY_RSA); bits = buffer_get_int(&e->input); buffer_get_bignum(&e->input, key->rsa->e); buffer_get_bignum(&e->input, key->rsa->n); 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); - key = key_from_blob(blob, blen); + key = dsa_key_from_blob(blob, blen); xfree(blob); break; } if (key != NULL) { - Identity *id = lookup_identity(key, version); - if (id != NULL) { + int idx; + private = lookup_private_key(key, &idx, version); + if (private != NULL) { /* * 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 move - * all the entries between the empty slot and the end - * of the array. + * the array, we actually free the key there and copy + * data from the last entry. */ Idtab *tab = idtab_lookup(version); + key_free(tab->identities[idx].key); + xfree(tab->identities[idx].comment); if (tab->nentries < 1) fatal("process_remove_identity: " "internal error: tab->nentries %d", tab->nentries); - TAILQ_REMOVE(&tab->idlist, id, next); - free_identity(id); + if (idx != tab->nentries - 1) + tab->identities[idx] = tab->identities[tab->nentries - 1]; tab->nentries--; success = 1; } @@ -337,17 +327,16 @@ success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); } -static void +void process_remove_all_identities(SocketEntry *e, int version) { + unsigned int i; Idtab *tab = idtab_lookup(version); - Identity *id; /* Loop over all identities and clear the keys. */ - for (id = TAILQ_FIRST(&tab->idlist); id; - id = TAILQ_FIRST(&tab->idlist)) { - TAILQ_REMOVE(&tab->idlist, id, next); - free_identity(id); + for (i = 0; i < tab->nentries; i++) { + key_free(tab->identities[i].key); + xfree(tab->identities[i].comment); } /* Mark that there are no identities. */ @@ -359,73 +348,94 @@ return; } -static void +void process_add_identity(SocketEntry *e, int version) { Key *k = NULL; - char *type_name; + RSA *rsa; + BIGNUM *aux; + BN_CTX *ctx; + char *type; char *comment; - int type, success = 0; + int success = 0; Idtab *tab = idtab_lookup(version); switch (version) { case 1: - k = key_new_private(KEY_RSA1); - 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); - buffer_get_bignum(&e->input, k->rsa->iqmp); + k = key_new(KEY_RSA); + rsa = k->rsa; + /* allocate mem for private key */ + /* XXX rsa->n and rsa->e are already allocated */ + rsa->d = BN_new(); + rsa->iqmp = BN_new(); + rsa->q = BN_new(); + rsa->p = BN_new(); + rsa->dmq1 = BN_new(); + rsa->dmp1 = BN_new(); + + buffer_get_int(&e->input); /* ignored */ + + buffer_get_bignum(&e->input, rsa->n); + buffer_get_bignum(&e->input, rsa->e); + buffer_get_bignum(&e->input, rsa->d); + buffer_get_bignum(&e->input, rsa->iqmp); + /* SSH and SSL have p and q swapped */ - buffer_get_bignum(&e->input, k->rsa->q); /* p */ - buffer_get_bignum(&e->input, k->rsa->p); /* q */ + buffer_get_bignum(&e->input, rsa->q); /* p */ + buffer_get_bignum(&e->input, rsa->p); /* q */ /* Generate additional parameters */ - rsa_generate_additional_parameters(k->rsa); + 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); + break; case 2: - type_name = buffer_get_string(&e->input, NULL); - type = key_type_from_name(type_name); - xfree(type_name); - switch (type) { - case KEY_DSA: - k = key_new_private(type); - buffer_get_bignum2(&e->input, k->dsa->p); - buffer_get_bignum2(&e->input, k->dsa->q); - buffer_get_bignum2(&e->input, k->dsa->g); - buffer_get_bignum2(&e->input, k->dsa->pub_key); - buffer_get_bignum2(&e->input, k->dsa->priv_key); - break; - case KEY_RSA: - k = key_new_private(type); - buffer_get_bignum2(&e->input, k->rsa->n); - buffer_get_bignum2(&e->input, k->rsa->e); - buffer_get_bignum2(&e->input, k->rsa->d); - buffer_get_bignum2(&e->input, k->rsa->iqmp); - buffer_get_bignum2(&e->input, k->rsa->p); - buffer_get_bignum2(&e->input, k->rsa->q); - - /* Generate additional parameters */ - rsa_generate_additional_parameters(k->rsa); - break; - default: + type = buffer_get_string(&e->input, NULL); + if (strcmp(type, KEX_DSS)) { buffer_clear(&e->input); + xfree(type); goto send; } + xfree(type); + + k = key_new(KEY_DSA); + + /* allocate mem for private key */ + k->dsa->priv_key = BN_new(); + + buffer_get_bignum2(&e->input, k->dsa->p); + buffer_get_bignum2(&e->input, k->dsa->q); + buffer_get_bignum2(&e->input, k->dsa->g); + buffer_get_bignum2(&e->input, k->dsa->pub_key); + buffer_get_bignum2(&e->input, k->dsa->priv_key); + break; } + comment = buffer_get_string(&e->input, NULL); if (k == NULL) { xfree(comment); goto send; } success = 1; - if (lookup_identity(k, version) == NULL) { - Identity *id = xmalloc(sizeof(Identity)); - id->key = k; - id->comment = comment; - TAILQ_INSERT_TAIL(&tab->idlist, id, next); + if (lookup_private_key(k, NULL, version) == NULL) { + if (tab->nentries == 0) + tab->identities = xmalloc(sizeof(Identity)); + else + tab->identities = xrealloc(tab->identities, + (tab->nentries + 1) * sizeof(Identity)); + tab->identities[tab->nentries].key = k; + tab->identities[tab->nentries].comment = comment; /* Increment the number of identities. */ tab->nentries++; } else { @@ -438,112 +448,17 @@ 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_identity(k, 1) == NULL) { - Identity *id = xmalloc(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()); - id->key = n; - id->comment = xstrdup("rsa1 smartcard"); - TAILQ_INSERT_TAIL(&tab->idlist, id, next); - tab->nentries++; - } - k->type = KEY_RSA; - tab = idtab_lookup(2); - if (lookup_identity(k, 2) == NULL) { - Identity *id = xmalloc(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()); - id->key = n; - id->comment = xstrdup("rsa smartcard"); - TAILQ_INSERT_TAIL(&tab->idlist, id, next); - 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; - 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 { - Identity *id; - k->type = KEY_RSA1; - id = lookup_identity(k, 1); - if (id != NULL) { - Idtab *tab = idtab_lookup(1); - TAILQ_REMOVE(&tab->idlist, id, next); - free_identity(id); - tab->nentries--; - success = 1; - } - k->type = KEY_RSA; - id = lookup_identity(k, 2); - if (id != NULL) { - Idtab *tab = idtab_lookup(2); - TAILQ_REMOVE(&tab->idlist, id, next); - free_identity(id); - 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 */ -static void +void process_message(SocketEntry *e) { - u_int msg_len; - u_int type; - u_char *cp; + unsigned int msg_len; + unsigned int type; + unsigned char *cp; if (buffer_len(&e->input) < 5) return; /* Incomplete message. */ - cp = buffer_ptr(&e->input); + cp = (unsigned char *) buffer_ptr(&e->input); msg_len = GET_32BIT(cp); if (msg_len > 256 * 1024) { shutdown(e->fd, SHUT_RDWR); @@ -556,7 +471,6 @@ buffer_consume(&e->input, 4); type = buffer_get_char(&e->input); - debug("type %d", type); switch (type) { /* ssh1 */ case SSH_AGENTC_RSA_CHALLENGE: @@ -590,14 +504,6 @@ 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); @@ -608,10 +514,10 @@ } } -static void -new_socket(sock_type type, int fd) +void +new_socket(int type, int fd) { - u_int i, old_alloc; + unsigned int i, old_alloc; if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) error("fcntl O_NONBLOCK: %s", strerror(errno)); @@ -640,17 +546,17 @@ buffer_init(&sockets[old_alloc].output); } -static int -prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, int *nallocp) +void +prepare_select(fd_set *readset, fd_set *writeset) { - u_int i, sz; - int n = 0; - - for (i = 0; i < sockets_alloc; i++) { + unsigned int i; + for (i = 0; i < sockets_alloc; i++) switch (sockets[i].type) { case AUTH_SOCKET: case AUTH_CONNECTION: - n = MAX(n, sockets[i].fd); + FD_SET(sockets[i].fd, readset); + if (buffer_len(&sockets[i].output) > 0) + FD_SET(sockets[i].fd, writeset); break; case AUTH_UNUSED: break; @@ -658,43 +564,12 @@ 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); } -static void +void after_select(fd_set *readset, fd_set *writeset) { - u_int i; + unsigned int i; int len, sock; socklen_t slen; char buf[1024]; @@ -707,11 +582,9 @@ 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) { - error("accept from AUTH_SOCKET: %s", - strerror(errno)); + perror("accept from AUTH_SOCKET"); break; } new_socket(AUTH_CONNECTION, sock); @@ -720,15 +593,8 @@ case AUTH_CONNECTION: if (buffer_len(&sockets[i].output) > 0 && FD_ISSET(sockets[i].fd, writeset)) { - 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); + len = write(sockets[i].fd, buffer_ptr(&sockets[i].output), + buffer_len(&sockets[i].output)); if (len <= 0) { shutdown(sockets[i].fd, SHUT_RDWR); close(sockets[i].fd); @@ -740,13 +606,7 @@ buffer_consume(&sockets[i].output, len); } if (FD_ISSET(sockets[i].fd, readset)) { - do { - len = read(sockets[i].fd, buf, sizeof(buf)); - if (len == -1 && (errno == EAGAIN || - errno == EINTR)) - continue; - break; - } while (1); + len = read(sockets[i].fd, buf, sizeof(buf)); if (len <= 0) { shutdown(sockets[i].fd, SHUT_RDWR); close(sockets[i].fd); @@ -764,70 +624,57 @@ } } -static void -cleanup_socket(void *p) -{ - if (socket_name[0]) - unlink(socket_name); - if (socket_dir[0]) - rmdir(socket_dir); -} - -static void -cleanup_exit(int i) -{ - cleanup_socket(NULL); - exit(i); -} - -static void -cleanup_handler(int sig) -{ - cleanup_socket(NULL); - _exit(2); -} - -static void +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 */ + exit(1); } signal(SIGALRM, check_parent_exists); alarm(10); - errno = save_errno; } -static void -usage(void) +void +cleanup_socket(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"); + remove(socket_name); + rmdir(socket_dir); +} + +void +cleanup_exit(int i) +{ + cleanup_socket(); + exit(i); +} + +void +usage() +{ + fprintf(stderr, "ssh-agent version %s\n", SSH_VERSION); + fprintf(stderr, "Usage: %s [-c | -s] [-k] [command {args...]]\n", + __progname); exit(1); } int main(int ac, char **av) { - int sock, c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0, ch, nalloc; + fd_set readset, writeset; + int sock, c_flag = 0, k_flag = 0, s_flag = 0, ch; struct sockaddr_un sunaddr; - struct rlimit rlim; 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(); - - while ((ch = getopt(ac, av, "cdks")) != -1) { + /* check if RSA support exists */ + if (rsa_alive() == 0) { + fprintf(stderr, + "%s: no RSA support in libssl and libcrypto. See ssl(8).\n", + __progname); + exit(1); + } + while ((ch = getopt(ac, av, "cks")) != -1) { switch (ch) { case 'c': if (s_flag) @@ -842,11 +689,6 @@ usage(); s_flag++; break; - case 'd': - if (d_flag) - usage(); - d_flag++; - break; default: usage(); } @@ -854,10 +696,10 @@ ac -= optind; av += optind; - if (ac > 0 && (c_flag || k_flag || s_flag || d_flag)) + if (ac > 0 && (c_flag || k_flag || s_flag)) usage(); - if (ac == 0 && !c_flag && !k_flag && !s_flag && !d_flag) { + if (ac == 0 && !c_flag && !k_flag && !s_flag) { shell = getenv("SHELL"); if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0) c_flag = 1; @@ -866,13 +708,14 @@ 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) { + if (pid < 1) { /* XXX PID_MAX check too */ + /* Yes, PID_MAX check please */ 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) { @@ -894,7 +737,7 @@ 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 @@ -916,23 +759,14 @@ 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"); - cleanup_exit(1); + exit(1); } if (pid != 0) { /* Parent - execute the given command. */ close(sock); @@ -940,9 +774,9 @@ 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); } @@ -955,49 +789,38 @@ perror(av[0]); exit(1); } - /* child */ - log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0); - - if (setsid() == -1) { - error("setsid: %s", strerror(errno)); - cleanup_exit(1); - } - - (void)chdir("/"); close(0); close(1); close(2); - /* deny core dumps, since memory contains unencrypted private keys */ - rlim.rlim_cur = rlim.rlim_max = 0; - if (setrlimit(RLIMIT_CORE, &rlim) < 0) { - error("setrlimit RLIMIT_CORE: %s", strerror(errno)); + if (setsid() == -1) { + perror("setsid"); cleanup_exit(1); } - -skip: - fatal_add_cleanup(cleanup_socket, NULL); + if (atexit(cleanup_socket) < 0) { + perror("atexit"); + cleanup_exit(1); + } new_socket(AUTH_SOCKET, sock); if (ac > 0) { signal(SIGALRM, check_parent_exists); alarm(10); } idtab_init(); - if (!d_flag) - signal(SIGINT, SIG_IGN); + signal(SIGINT, SIG_IGN); signal(SIGPIPE, SIG_IGN); - signal(SIGHUP, cleanup_handler); - signal(SIGTERM, cleanup_handler); - nalloc = 0; - + signal(SIGHUP, cleanup_exit); + signal(SIGTERM, cleanup_exit); while (1) { - prepare_select(&readsetp, &writesetp, &max_fd, &nalloc); - if (select(max_fd + 1, readsetp, writesetp, NULL, NULL) < 0) { + FD_ZERO(&readset); + FD_ZERO(&writeset); + prepare_select(&readset, &writeset); + if (select(max_fd + 1, &readset, &writeset, NULL, NULL) < 0) { if (errno == EINTR) continue; - fatal("select: %s", strerror(errno)); + exit(1); } - after_select(readsetp, writesetp); + after_select(&readset, &writeset); } /* NOTREACHED */ }