diff options
Diffstat (limited to 'sshconnect2.c')
-rw-r--r-- | sshconnect2.c | 97 |
1 files changed, 55 insertions, 42 deletions
diff --git a/sshconnect2.c b/sshconnect2.c index 566571ae9..63e9369b1 100644 --- a/sshconnect2.c +++ b/sshconnect2.c | |||
@@ -1,3 +1,4 @@ | |||
1 | /* $OpenBSD: sshconnect2.c,v 1.162 2006/08/30 00:06:51 dtucker Exp $ */ | ||
1 | /* | 2 | /* |
2 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
3 | * | 4 | * |
@@ -23,18 +24,30 @@ | |||
23 | */ | 24 | */ |
24 | 25 | ||
25 | #include "includes.h" | 26 | #include "includes.h" |
26 | RCSID("$OpenBSD: sshconnect2.c,v 1.143 2005/10/14 02:17:59 stevesk Exp $"); | 27 | |
28 | #include <sys/types.h> | ||
29 | #include <sys/socket.h> | ||
30 | #include <sys/wait.h> | ||
31 | #include <sys/stat.h> | ||
32 | |||
33 | #include <errno.h> | ||
34 | #include <pwd.h> | ||
35 | #include <signal.h> | ||
36 | #include <stdarg.h> | ||
37 | #include <stdio.h> | ||
38 | #include <string.h> | ||
39 | #include <unistd.h> | ||
27 | 40 | ||
28 | #include "openbsd-compat/sys-queue.h" | 41 | #include "openbsd-compat/sys-queue.h" |
29 | 42 | ||
43 | #include "xmalloc.h" | ||
30 | #include "ssh.h" | 44 | #include "ssh.h" |
31 | #include "ssh2.h" | 45 | #include "ssh2.h" |
32 | #include "xmalloc.h" | ||
33 | #include "buffer.h" | 46 | #include "buffer.h" |
34 | #include "packet.h" | 47 | #include "packet.h" |
35 | #include "compat.h" | 48 | #include "compat.h" |
36 | #include "bufaux.h" | ||
37 | #include "cipher.h" | 49 | #include "cipher.h" |
50 | #include "key.h" | ||
38 | #include "kex.h" | 51 | #include "kex.h" |
39 | #include "myproposal.h" | 52 | #include "myproposal.h" |
40 | #include "sshconnect.h" | 53 | #include "sshconnect.h" |
@@ -49,6 +62,7 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.143 2005/10/14 02:17:59 stevesk Exp $"); | |||
49 | #include "canohost.h" | 62 | #include "canohost.h" |
50 | #include "msg.h" | 63 | #include "msg.h" |
51 | #include "pathnames.h" | 64 | #include "pathnames.h" |
65 | #include "uidswap.h" | ||
52 | 66 | ||
53 | #ifdef GSSAPI | 67 | #ifdef GSSAPI |
54 | #include "ssh-gss.h" | 68 | #include "ssh-gss.h" |
@@ -85,19 +99,19 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) | |||
85 | Kex *kex; | 99 | Kex *kex; |
86 | 100 | ||
87 | #ifdef GSSAPI | 101 | #ifdef GSSAPI |
88 | char *orig, *gss = NULL; | 102 | char *orig = NULL, *gss = NULL; |
89 | int len; | 103 | char *gss_host = NULL; |
90 | char *gss_host = NULL; | ||
91 | #endif | 104 | #endif |
92 | 105 | ||
93 | xxx_host = host; | 106 | xxx_host = host; |
94 | xxx_hostaddr = hostaddr; | 107 | xxx_hostaddr = hostaddr; |
95 | 108 | ||
96 | #ifdef GSSAPI | 109 | #ifdef GSSAPI |
97 | if (options.gss_authentication) { | 110 | if (options.gss_keyex) { |
98 | /* Add the GSSAPI mechanisms currently supported on this | 111 | /* Add the GSSAPI mechanisms currently supported on this |
99 | * client to the key exchange algorithm proposal */ | 112 | * client to the key exchange algorithm proposal */ |
100 | orig = myproposal[PROPOSAL_KEX_ALGS]; | 113 | orig = myproposal[PROPOSAL_KEX_ALGS]; |
114 | |||
101 | if (options.gss_trust_dns) | 115 | if (options.gss_trust_dns) |
102 | gss_host = (char *)get_canonical_hostname(1); | 116 | gss_host = (char *)get_canonical_hostname(1); |
103 | else | 117 | else |
@@ -106,10 +120,8 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) | |||
106 | gss = ssh_gssapi_client_mechanisms(gss_host); | 120 | gss = ssh_gssapi_client_mechanisms(gss_host); |
107 | if (gss) { | 121 | if (gss) { |
108 | debug("Offering GSSAPI proposal: %s", gss); | 122 | debug("Offering GSSAPI proposal: %s", gss); |
109 | len = strlen(orig) + strlen(gss) + 2; | 123 | xasprintf(&myproposal[PROPOSAL_KEX_ALGS], |
110 | myproposal[PROPOSAL_KEX_ALGS] = xmalloc(len); | 124 | "%s,%s", gss, orig); |
111 | snprintf(myproposal[PROPOSAL_KEX_ALGS], len, "%s,%s", | ||
112 | gss, orig); | ||
113 | } | 125 | } |
114 | } | 126 | } |
115 | #endif | 127 | #endif |
@@ -144,11 +156,9 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) | |||
144 | #ifdef GSSAPI | 156 | #ifdef GSSAPI |
145 | /* If we've got GSSAPI algorithms, then we also support the | 157 | /* If we've got GSSAPI algorithms, then we also support the |
146 | * 'null' hostkey, as a last resort */ | 158 | * 'null' hostkey, as a last resort */ |
147 | if (gss) { | 159 | if (options.gss_keyex && gss) { |
148 | orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; | 160 | orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; |
149 | len = strlen(orig) + sizeof(",null"); | 161 | xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], |
150 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = xmalloc(len); | ||
151 | snprintf(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], len, | ||
152 | "%s,null", orig); | 162 | "%s,null", orig); |
153 | } | 163 | } |
154 | #endif | 164 | #endif |
@@ -161,9 +171,11 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) | |||
161 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; | 171 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; |
162 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; | 172 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; |
163 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; | 173 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; |
174 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; | ||
164 | #ifdef GSSAPI | 175 | #ifdef GSSAPI |
165 | if (options.gss_authentication) { | 176 | if (options.gss_keyex) { |
166 | kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; | 177 | kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; |
178 | kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client; | ||
167 | kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client; | 179 | kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client; |
168 | } | 180 | } |
169 | #endif | 181 | #endif |
@@ -423,7 +435,7 @@ input_userauth_banner(int type, u_int32_t seq, void *ctxt) | |||
423 | debug3("input_userauth_banner"); | 435 | debug3("input_userauth_banner"); |
424 | msg = packet_get_string(NULL); | 436 | msg = packet_get_string(NULL); |
425 | lang = packet_get_string(NULL); | 437 | lang = packet_get_string(NULL); |
426 | if (options.log_level > SYSLOG_LEVEL_QUIET) | 438 | if (options.log_level >= SYSLOG_LEVEL_INFO) |
427 | fprintf(stderr, "%s", msg); | 439 | fprintf(stderr, "%s", msg); |
428 | xfree(msg); | 440 | xfree(msg); |
429 | xfree(lang); | 441 | xfree(lang); |
@@ -545,8 +557,14 @@ userauth_gssapi(Authctxt *authctxt) | |||
545 | static u_int mech = 0; | 557 | static u_int mech = 0; |
546 | OM_uint32 min; | 558 | OM_uint32 min; |
547 | int ok = 0; | 559 | int ok = 0; |
560 | char *gss_host = NULL; | ||
548 | int old_gssapi_method; | 561 | int old_gssapi_method; |
549 | 562 | ||
563 | if (options.gss_trust_dns) | ||
564 | gss_host = (char *)get_canonical_hostname(1); | ||
565 | else | ||
566 | gss_host = (char *)authctxt->host; | ||
567 | |||
550 | /* Try one GSSAPI method at a time, rather than sending them all at | 568 | /* Try one GSSAPI method at a time, rather than sending them all at |
551 | * once. */ | 569 | * once. */ |
552 | 570 | ||
@@ -555,15 +573,10 @@ userauth_gssapi(Authctxt *authctxt) | |||
555 | 573 | ||
556 | /* Check to see if the mechanism is usable before we offer it */ | 574 | /* Check to see if the mechanism is usable before we offer it */ |
557 | while (mech < gss_supported->count && !ok) { | 575 | while (mech < gss_supported->count && !ok) { |
558 | if (gssctxt) | ||
559 | ssh_gssapi_delete_ctx(&gssctxt); | ||
560 | ssh_gssapi_build_ctx(&gssctxt); | ||
561 | ssh_gssapi_set_oid(gssctxt, &gss_supported->elements[mech]); | ||
562 | |||
563 | /* My DER encoding requires length<128 */ | 576 | /* My DER encoding requires length<128 */ |
564 | if (gss_supported->elements[mech].length < 128 && | 577 | if (gss_supported->elements[mech].length < 128 && |
565 | !GSS_ERROR(ssh_gssapi_import_name(gssctxt, | 578 | ssh_gssapi_check_mechanism(&gssctxt, |
566 | authctxt->host))) { | 579 | &gss_supported->elements[mech], gss_host)) { |
567 | ok = 1; /* Mechanism works */ | 580 | ok = 1; /* Mechanism works */ |
568 | } else { | 581 | } else { |
569 | mech++; | 582 | mech++; |
@@ -587,7 +600,7 @@ userauth_gssapi(Authctxt *authctxt) | |||
587 | * for the old gssapi method. | 600 | * for the old gssapi method. |
588 | * We only include tagged oids for the new gssapi-with-mic method. | 601 | * We only include tagged oids for the new gssapi-with-mic method. |
589 | */ | 602 | */ |
590 | packet_put_int(old_gssapi_method?2:1); | 603 | packet_put_int(old_gssapi_method ? 2 : 1); |
591 | 604 | ||
592 | packet_put_int((gss_supported->elements[mech].length) + 2); | 605 | packet_put_int((gss_supported->elements[mech].length) + 2); |
593 | packet_put_char(SSH_GSS_OIDTYPE); | 606 | packet_put_char(SSH_GSS_OIDTYPE); |
@@ -595,7 +608,7 @@ userauth_gssapi(Authctxt *authctxt) | |||
595 | packet_put_raw(gss_supported->elements[mech].elements, | 608 | packet_put_raw(gss_supported->elements[mech].elements, |
596 | gss_supported->elements[mech].length); | 609 | gss_supported->elements[mech].length); |
597 | if (old_gssapi_method) { | 610 | if (old_gssapi_method) { |
598 | packet_put_int((gss_supported->elements[mech].length)); | 611 | packet_put_int(gss_supported->elements[mech].length); |
599 | packet_put_raw(gss_supported->elements[mech].elements, | 612 | packet_put_raw(gss_supported->elements[mech].elements, |
600 | gss_supported->elements[mech].length); | 613 | gss_supported->elements[mech].length); |
601 | } | 614 | } |
@@ -673,8 +686,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt) | |||
673 | { | 686 | { |
674 | Authctxt *authctxt = ctxt; | 687 | Authctxt *authctxt = ctxt; |
675 | Gssctxt *gssctxt; | 688 | Gssctxt *gssctxt; |
676 | int oidlen; | 689 | u_int oidlen; |
677 | char *oidv, *oidv_free; | 690 | u_char *oidv, *oidv_free; |
678 | 691 | ||
679 | if (authctxt == NULL) | 692 | if (authctxt == NULL) |
680 | fatal("input_gssapi_response: no authentication context"); | 693 | fatal("input_gssapi_response: no authentication context"); |
@@ -1086,14 +1099,16 @@ load_identity_file(char *filename) | |||
1086 | { | 1099 | { |
1087 | Key *private; | 1100 | Key *private; |
1088 | char prompt[300], *passphrase; | 1101 | char prompt[300], *passphrase; |
1089 | int quit, i; | 1102 | int perm_ok, quit, i; |
1090 | struct stat st; | 1103 | struct stat st; |
1091 | 1104 | ||
1092 | if (stat(filename, &st) < 0) { | 1105 | if (stat(filename, &st) < 0) { |
1093 | debug3("no such identity: %s", filename); | 1106 | debug3("no such identity: %s", filename); |
1094 | return NULL; | 1107 | return NULL; |
1095 | } | 1108 | } |
1096 | private = key_load_private_type(KEY_UNSPEC, filename, "", NULL); | 1109 | private = key_load_private_type(KEY_UNSPEC, filename, "", NULL, &perm_ok); |
1110 | if (!perm_ok) | ||
1111 | return NULL; | ||
1097 | if (private == NULL) { | 1112 | if (private == NULL) { |
1098 | if (options.batch_mode) | 1113 | if (options.batch_mode) |
1099 | return NULL; | 1114 | return NULL; |
@@ -1102,8 +1117,8 @@ load_identity_file(char *filename) | |||
1102 | for (i = 0; i < options.number_of_password_prompts; i++) { | 1117 | for (i = 0; i < options.number_of_password_prompts; i++) { |
1103 | passphrase = read_passphrase(prompt, 0); | 1118 | passphrase = read_passphrase(prompt, 0); |
1104 | if (strcmp(passphrase, "") != 0) { | 1119 | if (strcmp(passphrase, "") != 0) { |
1105 | private = key_load_private_type(KEY_UNSPEC, filename, | 1120 | private = key_load_private_type(KEY_UNSPEC, |
1106 | passphrase, NULL); | 1121 | filename, passphrase, NULL, NULL); |
1107 | quit = 0; | 1122 | quit = 0; |
1108 | } else { | 1123 | } else { |
1109 | debug2("no passphrase given, try next key"); | 1124 | debug2("no passphrase given, try next key"); |
@@ -1146,8 +1161,7 @@ pubkey_prepare(Authctxt *authctxt) | |||
1146 | if (key && key->type == KEY_RSA1) | 1161 | if (key && key->type == KEY_RSA1) |
1147 | continue; | 1162 | continue; |
1148 | options.identity_keys[i] = NULL; | 1163 | options.identity_keys[i] = NULL; |
1149 | id = xmalloc(sizeof(*id)); | 1164 | id = xcalloc(1, sizeof(*id)); |
1150 | memset(id, 0, sizeof(*id)); | ||
1151 | id->key = key; | 1165 | id->key = key; |
1152 | id->filename = xstrdup(options.identity_files[i]); | 1166 | id->filename = xstrdup(options.identity_files[i]); |
1153 | TAILQ_INSERT_TAIL(&files, id, next); | 1167 | TAILQ_INSERT_TAIL(&files, id, next); |
@@ -1171,8 +1185,7 @@ pubkey_prepare(Authctxt *authctxt) | |||
1171 | } | 1185 | } |
1172 | } | 1186 | } |
1173 | if (!found && !options.identities_only) { | 1187 | if (!found && !options.identities_only) { |
1174 | id = xmalloc(sizeof(*id)); | 1188 | id = xcalloc(1, sizeof(*id)); |
1175 | memset(id, 0, sizeof(*id)); | ||
1176 | id->key = key; | 1189 | id->key = key; |
1177 | id->filename = comment; | 1190 | id->filename = comment; |
1178 | id->ac = ac; | 1191 | id->ac = ac; |
@@ -1368,8 +1381,7 @@ ssh_keysign(Key *key, u_char **sigp, u_int *lenp, | |||
1368 | return -1; | 1381 | return -1; |
1369 | } | 1382 | } |
1370 | if (pid == 0) { | 1383 | if (pid == 0) { |
1371 | seteuid(getuid()); | 1384 | permanently_drop_suid(getuid()); |
1372 | setuid(getuid()); | ||
1373 | close(from[0]); | 1385 | close(from[0]); |
1374 | if (dup2(from[1], STDOUT_FILENO) < 0) | 1386 | if (dup2(from[1], STDOUT_FILENO) < 0) |
1375 | fatal("ssh_keysign: dup2: %s", strerror(errno)); | 1387 | fatal("ssh_keysign: dup2: %s", strerror(errno)); |
@@ -1449,12 +1461,11 @@ userauth_hostbased(Authctxt *authctxt) | |||
1449 | if (p == NULL) { | 1461 | if (p == NULL) { |
1450 | error("userauth_hostbased: cannot get local ipaddr/name"); | 1462 | error("userauth_hostbased: cannot get local ipaddr/name"); |
1451 | key_free(private); | 1463 | key_free(private); |
1464 | xfree(blob); | ||
1452 | return 0; | 1465 | return 0; |
1453 | } | 1466 | } |
1454 | len = strlen(p) + 2; | 1467 | len = strlen(p) + 2; |
1455 | chost = xmalloc(len); | 1468 | xasprintf(&chost, "%s.", p); |
1456 | strlcpy(chost, p, len); | ||
1457 | strlcat(chost, ".", len); | ||
1458 | debug2("userauth_hostbased: chost %s", chost); | 1469 | debug2("userauth_hostbased: chost %s", chost); |
1459 | xfree(p); | 1470 | xfree(p); |
1460 | 1471 | ||
@@ -1487,6 +1498,7 @@ userauth_hostbased(Authctxt *authctxt) | |||
1487 | error("key_sign failed"); | 1498 | error("key_sign failed"); |
1488 | xfree(chost); | 1499 | xfree(chost); |
1489 | xfree(pkalg); | 1500 | xfree(pkalg); |
1501 | xfree(blob); | ||
1490 | return 0; | 1502 | return 0; |
1491 | } | 1503 | } |
1492 | packet_start(SSH2_MSG_USERAUTH_REQUEST); | 1504 | packet_start(SSH2_MSG_USERAUTH_REQUEST); |
@@ -1502,6 +1514,7 @@ userauth_hostbased(Authctxt *authctxt) | |||
1502 | xfree(signature); | 1514 | xfree(signature); |
1503 | xfree(chost); | 1515 | xfree(chost); |
1504 | xfree(pkalg); | 1516 | xfree(pkalg); |
1517 | xfree(blob); | ||
1505 | 1518 | ||
1506 | packet_send(); | 1519 | packet_send(); |
1507 | return 1; | 1520 | return 1; |