diff options
Diffstat (limited to 'ssh-agent.c')
-rw-r--r-- | ssh-agent.c | 78 |
1 files changed, 43 insertions, 35 deletions
diff --git a/ssh-agent.c b/ssh-agent.c index ba2461211..25f10c549 100644 --- a/ssh-agent.c +++ b/ssh-agent.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-agent.c,v 1.183 2014/02/02 03:44:31 djm Exp $ */ | 1 | /* $OpenBSD: ssh-agent.c,v 1.190 2014/07/25 21:22:03 dtucker Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -49,8 +49,10 @@ | |||
49 | #endif | 49 | #endif |
50 | #include "openbsd-compat/sys-queue.h" | 50 | #include "openbsd-compat/sys-queue.h" |
51 | 51 | ||
52 | #ifdef WITH_OPENSSL | ||
52 | #include <openssl/evp.h> | 53 | #include <openssl/evp.h> |
53 | #include "openbsd-compat/openssl-compat.h" | 54 | #include "openbsd-compat/openssl-compat.h" |
55 | #endif | ||
54 | 56 | ||
55 | #include <errno.h> | 57 | #include <errno.h> |
56 | #include <fcntl.h> | 58 | #include <fcntl.h> |
@@ -124,6 +126,9 @@ int max_fd = 0; | |||
124 | pid_t parent_pid = -1; | 126 | pid_t parent_pid = -1; |
125 | time_t parent_alive_interval = 0; | 127 | time_t parent_alive_interval = 0; |
126 | 128 | ||
129 | /* pid of process for which cleanup_socket is applicable */ | ||
130 | pid_t cleanup_pid = 0; | ||
131 | |||
127 | /* pathname and directory for AUTH_SOCKET */ | 132 | /* pathname and directory for AUTH_SOCKET */ |
128 | char socket_name[MAXPATHLEN]; | 133 | char socket_name[MAXPATHLEN]; |
129 | char socket_dir[MAXPATHLEN]; | 134 | char socket_dir[MAXPATHLEN]; |
@@ -221,9 +226,11 @@ process_request_identities(SocketEntry *e, int version) | |||
221 | buffer_put_int(&msg, tab->nentries); | 226 | buffer_put_int(&msg, tab->nentries); |
222 | TAILQ_FOREACH(id, &tab->idlist, next) { | 227 | TAILQ_FOREACH(id, &tab->idlist, next) { |
223 | if (id->key->type == KEY_RSA1) { | 228 | if (id->key->type == KEY_RSA1) { |
229 | #ifdef WITH_SSH1 | ||
224 | buffer_put_int(&msg, BN_num_bits(id->key->rsa->n)); | 230 | buffer_put_int(&msg, BN_num_bits(id->key->rsa->n)); |
225 | buffer_put_bignum(&msg, id->key->rsa->e); | 231 | buffer_put_bignum(&msg, id->key->rsa->e); |
226 | buffer_put_bignum(&msg, id->key->rsa->n); | 232 | buffer_put_bignum(&msg, id->key->rsa->n); |
233 | #endif | ||
227 | } else { | 234 | } else { |
228 | u_char *blob; | 235 | u_char *blob; |
229 | u_int blen; | 236 | u_int blen; |
@@ -238,6 +245,7 @@ process_request_identities(SocketEntry *e, int version) | |||
238 | buffer_free(&msg); | 245 | buffer_free(&msg); |
239 | } | 246 | } |
240 | 247 | ||
248 | #ifdef WITH_SSH1 | ||
241 | /* ssh1 only */ | 249 | /* ssh1 only */ |
242 | static void | 250 | static void |
243 | process_authentication_challenge1(SocketEntry *e) | 251 | process_authentication_challenge1(SocketEntry *e) |
@@ -273,7 +281,7 @@ process_authentication_challenge1(SocketEntry *e) | |||
273 | if (id != NULL && (!id->confirm || confirm_key(id) == 0)) { | 281 | if (id != NULL && (!id->confirm || confirm_key(id) == 0)) { |
274 | Key *private = id->key; | 282 | Key *private = id->key; |
275 | /* Decrypt the challenge using the private key. */ | 283 | /* Decrypt the challenge using the private key. */ |
276 | if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0) | 284 | if (rsa_private_decrypt(challenge, challenge, private->rsa) != 0) |
277 | goto failure; | 285 | goto failure; |
278 | 286 | ||
279 | /* The response is MD5 of decrypted challenge plus session id. */ | 287 | /* The response is MD5 of decrypted challenge plus session id. */ |
@@ -308,6 +316,7 @@ send: | |||
308 | BN_clear_free(challenge); | 316 | BN_clear_free(challenge); |
309 | buffer_free(&msg); | 317 | buffer_free(&msg); |
310 | } | 318 | } |
319 | #endif | ||
311 | 320 | ||
312 | /* ssh2 only */ | 321 | /* ssh2 only */ |
313 | static void | 322 | static void |
@@ -359,12 +368,16 @@ process_sign_request2(SocketEntry *e) | |||
359 | static void | 368 | static void |
360 | process_remove_identity(SocketEntry *e, int version) | 369 | process_remove_identity(SocketEntry *e, int version) |
361 | { | 370 | { |
362 | u_int blen, bits; | 371 | u_int blen; |
363 | int success = 0; | 372 | int success = 0; |
364 | Key *key = NULL; | 373 | Key *key = NULL; |
365 | u_char *blob; | 374 | u_char *blob; |
375 | #ifdef WITH_SSH1 | ||
376 | u_int bits; | ||
377 | #endif /* WITH_SSH1 */ | ||
366 | 378 | ||
367 | switch (version) { | 379 | switch (version) { |
380 | #ifdef WITH_SSH1 | ||
368 | case 1: | 381 | case 1: |
369 | key = key_new(KEY_RSA1); | 382 | key = key_new(KEY_RSA1); |
370 | bits = buffer_get_int(&e->request); | 383 | bits = buffer_get_int(&e->request); |
@@ -375,6 +388,7 @@ process_remove_identity(SocketEntry *e, int version) | |||
375 | logit("Warning: identity keysize mismatch: actual %u, announced %u", | 388 | logit("Warning: identity keysize mismatch: actual %u, announced %u", |
376 | key_size(key), bits); | 389 | key_size(key), bits); |
377 | break; | 390 | break; |
391 | #endif /* WITH_SSH1 */ | ||
378 | case 2: | 392 | case 2: |
379 | blob = buffer_get_string(&e->request, &blen); | 393 | blob = buffer_get_string(&e->request, &blen); |
380 | key = key_from_blob(blob, blen); | 394 | key = key_from_blob(blob, blen); |
@@ -471,6 +485,7 @@ process_add_identity(SocketEntry *e, int version) | |||
471 | Key *k = NULL; | 485 | Key *k = NULL; |
472 | 486 | ||
473 | switch (version) { | 487 | switch (version) { |
488 | #ifdef WITH_SSH1 | ||
474 | case 1: | 489 | case 1: |
475 | k = key_new_private(KEY_RSA1); | 490 | k = key_new_private(KEY_RSA1); |
476 | (void) buffer_get_int(&e->request); /* ignored */ | 491 | (void) buffer_get_int(&e->request); /* ignored */ |
@@ -484,7 +499,9 @@ process_add_identity(SocketEntry *e, int version) | |||
484 | buffer_get_bignum(&e->request, k->rsa->p); /* q */ | 499 | buffer_get_bignum(&e->request, k->rsa->p); /* q */ |
485 | 500 | ||
486 | /* Generate additional parameters */ | 501 | /* Generate additional parameters */ |
487 | rsa_generate_additional_parameters(k->rsa); | 502 | if (rsa_generate_additional_parameters(k->rsa) != 0) |
503 | fatal("%s: rsa_generate_additional_parameters " | ||
504 | "error", __func__); | ||
488 | 505 | ||
489 | /* enable blinding */ | 506 | /* enable blinding */ |
490 | if (RSA_blinding_on(k->rsa, NULL) != 1) { | 507 | if (RSA_blinding_on(k->rsa, NULL) != 1) { |
@@ -493,6 +510,7 @@ process_add_identity(SocketEntry *e, int version) | |||
493 | goto send; | 510 | goto send; |
494 | } | 511 | } |
495 | break; | 512 | break; |
513 | #endif /* WITH_SSH1 */ | ||
496 | case 2: | 514 | case 2: |
497 | k = key_private_deserialize(&e->request); | 515 | k = key_private_deserialize(&e->request); |
498 | if (k == NULL) { | 516 | if (k == NULL) { |
@@ -501,11 +519,10 @@ process_add_identity(SocketEntry *e, int version) | |||
501 | } | 519 | } |
502 | break; | 520 | break; |
503 | } | 521 | } |
504 | comment = buffer_get_string(&e->request, NULL); | 522 | if (k == NULL) |
505 | if (k == NULL) { | ||
506 | free(comment); | ||
507 | goto send; | 523 | goto send; |
508 | } | 524 | comment = buffer_get_string(&e->request, NULL); |
525 | |||
509 | while (buffer_len(&e->request)) { | 526 | while (buffer_len(&e->request)) { |
510 | switch ((type = buffer_get_char(&e->request))) { | 527 | switch ((type = buffer_get_char(&e->request))) { |
511 | case SSH_AGENT_CONSTRAIN_LIFETIME: | 528 | case SSH_AGENT_CONSTRAIN_LIFETIME: |
@@ -733,6 +750,7 @@ process_message(SocketEntry *e) | |||
733 | case SSH_AGENTC_UNLOCK: | 750 | case SSH_AGENTC_UNLOCK: |
734 | process_lock_agent(e, type == SSH_AGENTC_LOCK); | 751 | process_lock_agent(e, type == SSH_AGENTC_LOCK); |
735 | break; | 752 | break; |
753 | #ifdef WITH_SSH1 | ||
736 | /* ssh1 */ | 754 | /* ssh1 */ |
737 | case SSH_AGENTC_RSA_CHALLENGE: | 755 | case SSH_AGENTC_RSA_CHALLENGE: |
738 | process_authentication_challenge1(e); | 756 | process_authentication_challenge1(e); |
@@ -750,6 +768,7 @@ process_message(SocketEntry *e) | |||
750 | case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: | 768 | case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: |
751 | process_remove_all_identities(e, 1); | 769 | process_remove_all_identities(e, 1); |
752 | break; | 770 | break; |
771 | #endif | ||
753 | /* ssh2 */ | 772 | /* ssh2 */ |
754 | case SSH2_AGENTC_SIGN_REQUEST: | 773 | case SSH2_AGENTC_SIGN_REQUEST: |
755 | process_sign_request2(e); | 774 | process_sign_request2(e); |
@@ -949,6 +968,7 @@ after_select(fd_set *readset, fd_set *writeset) | |||
949 | break; | 968 | break; |
950 | } | 969 | } |
951 | buffer_append(&sockets[i].input, buf, len); | 970 | buffer_append(&sockets[i].input, buf, len); |
971 | explicit_bzero(buf, sizeof(buf)); | ||
952 | process_message(&sockets[i]); | 972 | process_message(&sockets[i]); |
953 | } | 973 | } |
954 | break; | 974 | break; |
@@ -960,6 +980,9 @@ after_select(fd_set *readset, fd_set *writeset) | |||
960 | static void | 980 | static void |
961 | cleanup_socket(void) | 981 | cleanup_socket(void) |
962 | { | 982 | { |
983 | if (cleanup_pid != 0 && getpid() != cleanup_pid) | ||
984 | return; | ||
985 | debug("%s: cleanup", __func__); | ||
963 | if (socket_name[0]) | 986 | if (socket_name[0]) |
964 | unlink(socket_name); | 987 | unlink(socket_name); |
965 | if (socket_dir[0]) | 988 | if (socket_dir[0]) |
@@ -1001,15 +1024,10 @@ check_parent_exists(void) | |||
1001 | static void | 1024 | static void |
1002 | usage(void) | 1025 | usage(void) |
1003 | { | 1026 | { |
1004 | fprintf(stderr, "usage: %s [options] [command [arg ...]]\n", | 1027 | fprintf(stderr, |
1005 | __progname); | 1028 | "usage: ssh-agent [-c | -s] [-d] [-a bind_address] [-t life]\n" |
1006 | fprintf(stderr, "Options:\n"); | 1029 | " [command [arg ...]]\n" |
1007 | fprintf(stderr, " -c Generate C-shell commands on stdout.\n"); | 1030 | " ssh-agent [-c | -s] -k\n"); |
1008 | fprintf(stderr, " -s Generate Bourne shell commands on stdout.\n"); | ||
1009 | fprintf(stderr, " -k Kill the current agent.\n"); | ||
1010 | fprintf(stderr, " -d Debug mode.\n"); | ||
1011 | fprintf(stderr, " -a socket Bind agent socket to given name.\n"); | ||
1012 | fprintf(stderr, " -t life Default identity lifetime (seconds).\n"); | ||
1013 | exit(1); | 1031 | exit(1); |
1014 | } | 1032 | } |
1015 | 1033 | ||
@@ -1021,17 +1039,16 @@ main(int ac, char **av) | |||
1021 | u_int nalloc; | 1039 | u_int nalloc; |
1022 | char *shell, *format, *pidstr, *agentsocket = NULL; | 1040 | char *shell, *format, *pidstr, *agentsocket = NULL; |
1023 | fd_set *readsetp = NULL, *writesetp = NULL; | 1041 | fd_set *readsetp = NULL, *writesetp = NULL; |
1024 | struct sockaddr_un sunaddr; | ||
1025 | #ifdef HAVE_SETRLIMIT | 1042 | #ifdef HAVE_SETRLIMIT |
1026 | struct rlimit rlim; | 1043 | struct rlimit rlim; |
1027 | #endif | 1044 | #endif |
1028 | int prev_mask; | ||
1029 | extern int optind; | 1045 | extern int optind; |
1030 | extern char *optarg; | 1046 | extern char *optarg; |
1031 | pid_t pid; | 1047 | pid_t pid; |
1032 | char pidstrbuf[1 + 3 * sizeof pid]; | 1048 | char pidstrbuf[1 + 3 * sizeof pid]; |
1033 | struct timeval *tvp = NULL; | 1049 | struct timeval *tvp = NULL; |
1034 | size_t len; | 1050 | size_t len; |
1051 | mode_t prev_mask; | ||
1035 | 1052 | ||
1036 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ | 1053 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ |
1037 | sanitise_stdfd(); | 1054 | sanitise_stdfd(); |
@@ -1045,7 +1062,9 @@ main(int ac, char **av) | |||
1045 | prctl(PR_SET_DUMPABLE, 0); | 1062 | prctl(PR_SET_DUMPABLE, 0); |
1046 | #endif | 1063 | #endif |
1047 | 1064 | ||
1065 | #ifdef WITH_OPENSSL | ||
1048 | OpenSSL_add_all_algorithms(); | 1066 | OpenSSL_add_all_algorithms(); |
1067 | #endif | ||
1049 | 1068 | ||
1050 | __progname = ssh_get_progname(av[0]); | 1069 | __progname = ssh_get_progname(av[0]); |
1051 | seed_rng(); | 1070 | seed_rng(); |
@@ -1142,27 +1161,14 @@ main(int ac, char **av) | |||
1142 | * Create socket early so it will exist before command gets run from | 1161 | * Create socket early so it will exist before command gets run from |
1143 | * the parent. | 1162 | * the parent. |
1144 | */ | 1163 | */ |
1145 | sock = socket(AF_UNIX, SOCK_STREAM, 0); | ||
1146 | if (sock < 0) { | ||
1147 | perror("socket"); | ||
1148 | *socket_name = '\0'; /* Don't unlink any existing file */ | ||
1149 | cleanup_exit(1); | ||
1150 | } | ||
1151 | memset(&sunaddr, 0, sizeof(sunaddr)); | ||
1152 | sunaddr.sun_family = AF_UNIX; | ||
1153 | strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path)); | ||
1154 | prev_mask = umask(0177); | 1164 | prev_mask = umask(0177); |
1155 | if (bind(sock, (struct sockaddr *) &sunaddr, sizeof(sunaddr)) < 0) { | 1165 | sock = unix_listener(socket_name, SSH_LISTEN_BACKLOG, 0); |
1156 | perror("bind"); | 1166 | if (sock < 0) { |
1167 | /* XXX - unix_listener() calls error() not perror() */ | ||
1157 | *socket_name = '\0'; /* Don't unlink any existing file */ | 1168 | *socket_name = '\0'; /* Don't unlink any existing file */ |
1158 | umask(prev_mask); | ||
1159 | cleanup_exit(1); | 1169 | cleanup_exit(1); |
1160 | } | 1170 | } |
1161 | umask(prev_mask); | 1171 | umask(prev_mask); |
1162 | if (listen(sock, SSH_LISTEN_BACKLOG) < 0) { | ||
1163 | perror("listen"); | ||
1164 | cleanup_exit(1); | ||
1165 | } | ||
1166 | 1172 | ||
1167 | /* | 1173 | /* |
1168 | * Fork, and have the parent execute the command, if any, or present | 1174 | * Fork, and have the parent execute the command, if any, or present |
@@ -1231,6 +1237,8 @@ main(int ac, char **av) | |||
1231 | 1237 | ||
1232 | skip: | 1238 | skip: |
1233 | 1239 | ||
1240 | cleanup_pid = getpid(); | ||
1241 | |||
1234 | #ifdef ENABLE_PKCS11 | 1242 | #ifdef ENABLE_PKCS11 |
1235 | pkcs11_init(0); | 1243 | pkcs11_init(0); |
1236 | #endif | 1244 | #endif |