]> andersk Git - openssh.git/blobdiff - ssh-agent.c
- djm@cvs.openbsd.org 2003/06/11 11:18:38
[openssh.git] / ssh-agent.c
index d4c008bbf6200cc90b6753795510fbeca0c8e3be..61ea3458007aadb897f14689f5b671443cebd0ee 100644 (file)
@@ -35,7 +35,7 @@
 
 #include "includes.h"
 #include "openbsd-compat/sys-queue.h"
-RCSID("$OpenBSD: ssh-agent.c,v 1.103 2002/09/10 20:24:47 markus Exp $");
+RCSID("$OpenBSD: ssh-agent.c,v 1.110 2003/06/11 11:18:38 djm Exp $");
 
 #include <openssl/evp.h>
 #include <openssl/md5.h>
@@ -50,6 +50,8 @@ RCSID("$OpenBSD: ssh-agent.c,v 1.103 2002/09/10 20:24:47 markus Exp $");
 #include "authfd.h"
 #include "compat.h"
 #include "log.h"
+#include "readpass.h"
+#include "misc.h"
 
 #ifdef SMARTCARD
 #include "scard.h"
@@ -77,6 +79,7 @@ typedef struct identity {
        Key *key;
        char *comment;
        u_int death;
+       u_int confirm;
 } Identity;
 
 typedef struct {
@@ -106,6 +109,9 @@ extern char *__progname;
 char *__progname;
 #endif
 
+/* Default lifetime (0 == forever) */
+static int lifetime = 0;
+
 static void
 close_socket(SocketEntry *e)
 {
@@ -159,6 +165,30 @@ lookup_identity(Key *key, int version)
        return (NULL);
 }
 
+/* Check confirmation of keysign request */
+static int
+confirm_key(Identity *id)
+{
+       char *p, prompt[1024];
+       int ret = -1;
+
+       p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
+       snprintf(prompt, sizeof(prompt), "Allow use of key %s?\n"
+           "Key fingerprint %s.", id->comment, p);
+       xfree(p);
+       p = read_passphrase(prompt, RP_ALLOW_EOF);
+       if (p != NULL) {
+               /*
+                * Accept empty responses and responses consisting 
+                * of the word "yes" as affirmative.
+                */
+               if (*p == '\0' || *p == '\n' || strcasecmp(p, "yes") == 0)
+                       ret = 0;
+               xfree(p);
+       }
+       return (ret);
+}
+
 /* send list of supported public keys to 'client' */
 static void
 process_request_identities(SocketEntry *e, int version)
@@ -222,7 +252,7 @@ process_authentication_challenge1(SocketEntry *e)
                goto failure;
 
        id = lookup_identity(key, 1);
-       if (id != NULL) {
+       if (id != NULL && (!id->confirm || confirm_key(id) == 0)) {
                Key *private = id->key;
                /* Decrypt the challenge using the private key. */
                if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0)
@@ -231,7 +261,7 @@ process_authentication_challenge1(SocketEntry *e)
                /* The response is MD5 of decrypted challenge plus session id. */
                len = BN_num_bytes(challenge);
                if (len <= 0 || len > 32) {
-                       log("process_authentication_challenge: bad challenge length %d", len);
+                       logit("process_authentication_challenge: bad challenge length %d", len);
                        goto failure;
                }
                memset(buf, 0, 32);
@@ -282,7 +312,7 @@ process_sign_request2(SocketEntry *e)
        key = key_from_blob(blob, blen);
        if (key != NULL) {
                Identity *id = lookup_identity(key, 2);
-               if (id != NULL)
+               if (id != NULL && (!id->confirm || confirm_key(id) == 0))
                        ok = key_sign(id->key, &signature, &slen, data, dlen);
        }
        key_free(key);
@@ -320,7 +350,7 @@ process_remove_identity(SocketEntry *e, int version)
                buffer_get_bignum(&e->request, key->rsa->n);
 
                if (bits != key_size(key))
-                       log("Warning: identity keysize mismatch: actual %u, announced %u",
+                       logit("Warning: identity keysize mismatch: actual %u, announced %u",
                            key_size(key), bits);
                break;
        case 2:
@@ -402,7 +432,7 @@ static void
 process_add_identity(SocketEntry *e, int version)
 {
        Idtab *tab = idtab_lookup(version);
-       int type, success = 0, death = 0;
+       int type, success = 0, death = 0, confirm = 0;
        char *type_name, *comment;
        Key *k = NULL;
 
@@ -453,6 +483,17 @@ process_add_identity(SocketEntry *e, int version)
                }
                break;
        }
+       /* enable blinding */
+       switch (k->type) {
+       case KEY_RSA:
+       case KEY_RSA1:
+               if (RSA_blinding_on(k->rsa, NULL) != 1) {
+                       error("process_add_identity: RSA_blinding_on failed");
+                       key_free(k);
+                       goto send;
+               }
+               break;
+       }
        comment = buffer_get_string(&e->request, NULL);
        if (k == NULL) {
                xfree(comment);
@@ -464,15 +505,21 @@ process_add_identity(SocketEntry *e, int version)
                case SSH_AGENT_CONSTRAIN_LIFETIME:
                        death = time(NULL) + buffer_get_int(&e->request);
                        break;
+               case SSH_AGENT_CONSTRAIN_CONFIRM:
+                       confirm = 1;
+                       break;
                default:
                        break;
                }
        }
+       if (lifetime && !death)
+               death = time(NULL) + lifetime;
        if (lookup_identity(k, version) == NULL) {
                Identity *id = xmalloc(sizeof(Identity));
                id->key = k;
                id->comment = comment;
                id->death = death;
+               id->confirm = confirm;
                TAILQ_INSERT_TAIL(&tab->idlist, id, next);
                /* Increment the number of identities. */
                tab->nentries++;
@@ -533,13 +580,29 @@ static void
 process_add_smartcard_key (SocketEntry *e)
 {
        char *sc_reader_id = NULL, *pin;
-       int i, version, success = 0;
+       int i, version, success = 0, death = 0, confirm = 0;
        Key **keys, *k;
        Identity *id;
        Idtab *tab;
 
        sc_reader_id = buffer_get_string(&e->request, NULL);
        pin = buffer_get_string(&e->request, NULL);
+
+       while (buffer_len(&e->request)) {
+               switch (buffer_get_char(&e->request)) {
+               case SSH_AGENT_CONSTRAIN_LIFETIME:
+                       death = time(NULL) + buffer_get_int(&e->request);
+                       break;
+               case SSH_AGENT_CONSTRAIN_CONFIRM:
+                       confirm = 1;
+                       break;
+               default:
+                       break;
+               }
+       }
+       if (lifetime && !death)
+               death = time(NULL) + lifetime;
+
        keys = sc_get_keys(sc_reader_id, pin);
        xfree(sc_reader_id);
        xfree(pin);
@@ -556,7 +619,8 @@ process_add_smartcard_key (SocketEntry *e)
                        id = xmalloc(sizeof(Identity));
                        id->key = k;
                        id->comment = xstrdup("smartcard key");
-                       id->death = 0;
+                       id->death = death;
+                       id->confirm = confirm;
                        TAILQ_INSERT_TAIL(&tab->idlist, id, next);
                        tab->nentries++;
                        success = 1;
@@ -700,6 +764,7 @@ process_message(SocketEntry *e)
                break;
 #ifdef SMARTCARD
        case SSH_AGENTC_ADD_SMARTCARD_KEY:
+       case SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED:
                process_add_smartcard_key(e);
                break;
        case SSH_AGENTC_REMOVE_SMARTCARD_KEY:
@@ -833,10 +898,10 @@ after_select(fd_set *readset, fd_set *writeset)
                                        close(sock);
                                        break;
                                }
-                               if (getuid() != euid) {
+                               if ((euid != 0) && (getuid() != euid)) {
                                        error("uid mismatch: "
-                                           "peer euid %d != uid %d",
-                                           (int) euid, (int) getuid());
+                                           "peer euid %u != uid %u",
+                                           (u_int) euid, (u_int) getuid());
                                        close(sock);
                                        break;
                                }
@@ -914,7 +979,7 @@ check_parent_exists(int sig)
                /* printf("Parent has died - Authentication agent exiting.\n"); */
                cleanup_handler(sig); /* safe */
        }
-       signal(SIGALRM, check_parent_exists);
+       mysignal(SIGALRM, check_parent_exists);
        alarm(10);
        errno = save_errno;
 }
@@ -930,13 +995,15 @@ usage(void)
        fprintf(stderr, "  -k          Kill the current agent.\n");
        fprintf(stderr, "  -d          Debug mode.\n");
        fprintf(stderr, "  -a socket   Bind agent socket to given name.\n");
+       fprintf(stderr, "  -t life     Default identity lifetime (seconds).\n");
        exit(1);
 }
 
 int
 main(int ac, char **av)
 {
-       int sock, c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0, ch, nalloc;
+       int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0;
+       int sock, fd,  ch, nalloc;
        char *shell, *format, *pidstr, *agentsocket = NULL;
        fd_set *readsetp = NULL, *writesetp = NULL;
        struct sockaddr_un sunaddr;
@@ -961,7 +1028,7 @@ main(int ac, char **av)
        init_rng();
        seed_rng();
 
-       while ((ch = getopt(ac, av, "cdksa:")) != -1) {
+       while ((ch = getopt(ac, av, "cdksa:t:")) != -1) {
                switch (ch) {
                case 'c':
                        if (s_flag)
@@ -984,6 +1051,12 @@ main(int ac, char **av)
                case 'a':
                        agentsocket = optarg;
                        break;
+               case 't':
+                       if ((lifetime = convtime(optarg)) == -1) {
+                               fprintf(stderr, "Invalid lifetime\n");
+                               usage();
+                       }
+                       break;
                default:
                        usage();
                }
@@ -1116,9 +1189,14 @@ main(int ac, char **av)
        }
 
        (void)chdir("/");
-       close(0);
-       close(1);
-       close(2);
+       if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+               /* XXX might close listen socket */
+               (void)dup2(fd, STDIN_FILENO);
+               (void)dup2(fd, STDOUT_FILENO);
+               (void)dup2(fd, STDERR_FILENO);
+               if (fd > 2)
+                       close(fd);
+       }
 
 #ifdef HAVE_SETRLIMIT
        /* deny core dumps, since memory contains unencrypted private keys */
@@ -1133,7 +1211,7 @@ skip:
        fatal_add_cleanup(cleanup_socket, NULL);
        new_socket(AUTH_SOCKET, sock);
        if (ac > 0) {
-               signal(SIGALRM, check_parent_exists);
+               mysignal(SIGALRM, check_parent_exists);
                alarm(10);
        }
        idtab_init();
This page took 0.238348 seconds and 4 git commands to generate.