diff options
Diffstat (limited to 'sshconnect2.c')
-rw-r--r-- | sshconnect2.c | 111 |
1 files changed, 63 insertions, 48 deletions
diff --git a/sshconnect2.c b/sshconnect2.c index 1a69c6b2b..5190b07e5 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,30 +99,30 @@ 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; | 102 | char *orig = NULL, *gss = NULL; |
89 | int len; | 103 | char *gss_host = NULL; |
90 | char *gss_host; | ||
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 | /* Add the GSSAPI mechanisms currently supported on this client to | 110 | if (options.gss_keyex) { |
98 | * the key exchange algorithm proposal */ | 111 | /* Add the GSSAPI mechanisms currently supported on this |
99 | orig = myproposal[PROPOSAL_KEX_ALGS]; | 112 | * client to the key exchange algorithm proposal */ |
100 | if (options.gss_trust_dns) | 113 | orig = myproposal[PROPOSAL_KEX_ALGS]; |
101 | gss_host = (char *)get_canonical_hostname(1); | 114 | |
102 | else | 115 | if (options.gss_trust_dns) |
103 | gss_host = host; | 116 | gss_host = (char *)get_canonical_hostname(1); |
104 | 117 | else | |
105 | gss = ssh_gssapi_client_mechanisms(gss_host); | 118 | gss_host = host; |
106 | if (gss) { | 119 | |
107 | debug("Offering GSSAPI proposal: %s", gss); | 120 | gss = ssh_gssapi_client_mechanisms(gss_host); |
108 | len = strlen(orig) + strlen(gss) + 2; | 121 | if (gss) { |
109 | myproposal[PROPOSAL_KEX_ALGS] = xmalloc(len); | 122 | debug("Offering GSSAPI proposal: %s", gss); |
110 | snprintf(myproposal[PROPOSAL_KEX_ALGS], len, "%s,%s", gss, | 123 | xasprintf(&myproposal[PROPOSAL_KEX_ALGS], |
111 | orig); | 124 | "%s,%s", gss, orig); |
125 | } | ||
112 | } | 126 | } |
113 | #endif | 127 | #endif |
114 | 128 | ||
@@ -142,11 +156,9 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) | |||
142 | #ifdef GSSAPI | 156 | #ifdef GSSAPI |
143 | /* If we've got GSSAPI algorithms, then we also support the | 157 | /* If we've got GSSAPI algorithms, then we also support the |
144 | * 'null' hostkey, as a last resort */ | 158 | * 'null' hostkey, as a last resort */ |
145 | if (gss) { | 159 | if (options.gss_keyex && gss) { |
146 | orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; | 160 | orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; |
147 | len = strlen(orig) + sizeof(",null"); | 161 | xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], |
148 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = xmalloc(len); | ||
149 | snprintf(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], len, | ||
150 | "%s,null", orig); | 162 | "%s,null", orig); |
151 | } | 163 | } |
152 | #endif | 164 | #endif |
@@ -159,8 +171,10 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) | |||
159 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; | 171 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; |
160 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; | 172 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; |
161 | 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; | ||
162 | #ifdef GSSAPI | 175 | #ifdef GSSAPI |
163 | kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; | 176 | kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; |
177 | kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client; | ||
164 | kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client; | 178 | kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client; |
165 | #endif | 179 | #endif |
166 | kex->client_version_string=client_version_string; | 180 | kex->client_version_string=client_version_string; |
@@ -415,7 +429,7 @@ input_userauth_banner(int type, u_int32_t seq, void *ctxt) | |||
415 | debug3("input_userauth_banner"); | 429 | debug3("input_userauth_banner"); |
416 | msg = packet_get_string(NULL); | 430 | msg = packet_get_string(NULL); |
417 | lang = packet_get_string(NULL); | 431 | lang = packet_get_string(NULL); |
418 | if (options.log_level > SYSLOG_LEVEL_QUIET) | 432 | if (options.log_level >= SYSLOG_LEVEL_INFO) |
419 | fprintf(stderr, "%s", msg); | 433 | fprintf(stderr, "%s", msg); |
420 | xfree(msg); | 434 | xfree(msg); |
421 | xfree(lang); | 435 | xfree(lang); |
@@ -537,6 +551,12 @@ userauth_gssapi(Authctxt *authctxt) | |||
537 | static u_int mech = 0; | 551 | static u_int mech = 0; |
538 | OM_uint32 min; | 552 | OM_uint32 min; |
539 | int ok = 0; | 553 | int ok = 0; |
554 | char *gss_host = NULL; | ||
555 | |||
556 | if (options.gss_trust_dns) | ||
557 | gss_host = (char *)get_canonical_hostname(1); | ||
558 | else | ||
559 | gss_host = (char *)authctxt->host; | ||
540 | 560 | ||
541 | /* Try one GSSAPI method at a time, rather than sending them all at | 561 | /* Try one GSSAPI method at a time, rather than sending them all at |
542 | * once. */ | 562 | * once. */ |
@@ -546,15 +566,10 @@ userauth_gssapi(Authctxt *authctxt) | |||
546 | 566 | ||
547 | /* Check to see if the mechanism is usable before we offer it */ | 567 | /* Check to see if the mechanism is usable before we offer it */ |
548 | while (mech < gss_supported->count && !ok) { | 568 | while (mech < gss_supported->count && !ok) { |
549 | if (gssctxt) | ||
550 | ssh_gssapi_delete_ctx(&gssctxt); | ||
551 | ssh_gssapi_build_ctx(&gssctxt); | ||
552 | ssh_gssapi_set_oid(gssctxt, &gss_supported->elements[mech]); | ||
553 | |||
554 | /* My DER encoding requires length<128 */ | 569 | /* My DER encoding requires length<128 */ |
555 | if (gss_supported->elements[mech].length < 128 && | 570 | if (gss_supported->elements[mech].length < 128 && |
556 | !GSS_ERROR(ssh_gssapi_import_name(gssctxt, | 571 | ssh_gssapi_check_mechanism(&gssctxt, |
557 | authctxt->host))) { | 572 | &gss_supported->elements[mech], gss_host)) { |
558 | ok = 1; /* Mechanism works */ | 573 | ok = 1; /* Mechanism works */ |
559 | } else { | 574 | } else { |
560 | mech++; | 575 | mech++; |
@@ -650,8 +665,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt) | |||
650 | { | 665 | { |
651 | Authctxt *authctxt = ctxt; | 666 | Authctxt *authctxt = ctxt; |
652 | Gssctxt *gssctxt; | 667 | Gssctxt *gssctxt; |
653 | int oidlen; | 668 | u_int oidlen; |
654 | char *oidv; | 669 | u_char *oidv; |
655 | 670 | ||
656 | if (authctxt == NULL) | 671 | if (authctxt == NULL) |
657 | fatal("input_gssapi_response: no authentication context"); | 672 | fatal("input_gssapi_response: no authentication context"); |
@@ -1057,14 +1072,16 @@ load_identity_file(char *filename) | |||
1057 | { | 1072 | { |
1058 | Key *private; | 1073 | Key *private; |
1059 | char prompt[300], *passphrase; | 1074 | char prompt[300], *passphrase; |
1060 | int quit, i; | 1075 | int perm_ok, quit, i; |
1061 | struct stat st; | 1076 | struct stat st; |
1062 | 1077 | ||
1063 | if (stat(filename, &st) < 0) { | 1078 | if (stat(filename, &st) < 0) { |
1064 | debug3("no such identity: %s", filename); | 1079 | debug3("no such identity: %s", filename); |
1065 | return NULL; | 1080 | return NULL; |
1066 | } | 1081 | } |
1067 | private = key_load_private_type(KEY_UNSPEC, filename, "", NULL); | 1082 | private = key_load_private_type(KEY_UNSPEC, filename, "", NULL, &perm_ok); |
1083 | if (!perm_ok) | ||
1084 | return NULL; | ||
1068 | if (private == NULL) { | 1085 | if (private == NULL) { |
1069 | if (options.batch_mode) | 1086 | if (options.batch_mode) |
1070 | return NULL; | 1087 | return NULL; |
@@ -1073,8 +1090,8 @@ load_identity_file(char *filename) | |||
1073 | for (i = 0; i < options.number_of_password_prompts; i++) { | 1090 | for (i = 0; i < options.number_of_password_prompts; i++) { |
1074 | passphrase = read_passphrase(prompt, 0); | 1091 | passphrase = read_passphrase(prompt, 0); |
1075 | if (strcmp(passphrase, "") != 0) { | 1092 | if (strcmp(passphrase, "") != 0) { |
1076 | private = key_load_private_type(KEY_UNSPEC, filename, | 1093 | private = key_load_private_type(KEY_UNSPEC, |
1077 | passphrase, NULL); | 1094 | filename, passphrase, NULL, NULL); |
1078 | quit = 0; | 1095 | quit = 0; |
1079 | } else { | 1096 | } else { |
1080 | debug2("no passphrase given, try next key"); | 1097 | debug2("no passphrase given, try next key"); |
@@ -1117,8 +1134,7 @@ pubkey_prepare(Authctxt *authctxt) | |||
1117 | if (key && key->type == KEY_RSA1) | 1134 | if (key && key->type == KEY_RSA1) |
1118 | continue; | 1135 | continue; |
1119 | options.identity_keys[i] = NULL; | 1136 | options.identity_keys[i] = NULL; |
1120 | id = xmalloc(sizeof(*id)); | 1137 | id = xcalloc(1, sizeof(*id)); |
1121 | memset(id, 0, sizeof(*id)); | ||
1122 | id->key = key; | 1138 | id->key = key; |
1123 | id->filename = xstrdup(options.identity_files[i]); | 1139 | id->filename = xstrdup(options.identity_files[i]); |
1124 | TAILQ_INSERT_TAIL(&files, id, next); | 1140 | TAILQ_INSERT_TAIL(&files, id, next); |
@@ -1142,8 +1158,7 @@ pubkey_prepare(Authctxt *authctxt) | |||
1142 | } | 1158 | } |
1143 | } | 1159 | } |
1144 | if (!found && !options.identities_only) { | 1160 | if (!found && !options.identities_only) { |
1145 | id = xmalloc(sizeof(*id)); | 1161 | id = xcalloc(1, sizeof(*id)); |
1146 | memset(id, 0, sizeof(*id)); | ||
1147 | id->key = key; | 1162 | id->key = key; |
1148 | id->filename = comment; | 1163 | id->filename = comment; |
1149 | id->ac = ac; | 1164 | id->ac = ac; |
@@ -1339,8 +1354,7 @@ ssh_keysign(Key *key, u_char **sigp, u_int *lenp, | |||
1339 | return -1; | 1354 | return -1; |
1340 | } | 1355 | } |
1341 | if (pid == 0) { | 1356 | if (pid == 0) { |
1342 | seteuid(getuid()); | 1357 | permanently_drop_suid(getuid()); |
1343 | setuid(getuid()); | ||
1344 | close(from[0]); | 1358 | close(from[0]); |
1345 | if (dup2(from[1], STDOUT_FILENO) < 0) | 1359 | if (dup2(from[1], STDOUT_FILENO) < 0) |
1346 | fatal("ssh_keysign: dup2: %s", strerror(errno)); | 1360 | fatal("ssh_keysign: dup2: %s", strerror(errno)); |
@@ -1420,12 +1434,11 @@ userauth_hostbased(Authctxt *authctxt) | |||
1420 | if (p == NULL) { | 1434 | if (p == NULL) { |
1421 | error("userauth_hostbased: cannot get local ipaddr/name"); | 1435 | error("userauth_hostbased: cannot get local ipaddr/name"); |
1422 | key_free(private); | 1436 | key_free(private); |
1437 | xfree(blob); | ||
1423 | return 0; | 1438 | return 0; |
1424 | } | 1439 | } |
1425 | len = strlen(p) + 2; | 1440 | len = strlen(p) + 2; |
1426 | chost = xmalloc(len); | 1441 | xasprintf(&chost, "%s.", p); |
1427 | strlcpy(chost, p, len); | ||
1428 | strlcat(chost, ".", len); | ||
1429 | debug2("userauth_hostbased: chost %s", chost); | 1442 | debug2("userauth_hostbased: chost %s", chost); |
1430 | xfree(p); | 1443 | xfree(p); |
1431 | 1444 | ||
@@ -1458,6 +1471,7 @@ userauth_hostbased(Authctxt *authctxt) | |||
1458 | error("key_sign failed"); | 1471 | error("key_sign failed"); |
1459 | xfree(chost); | 1472 | xfree(chost); |
1460 | xfree(pkalg); | 1473 | xfree(pkalg); |
1474 | xfree(blob); | ||
1461 | return 0; | 1475 | return 0; |
1462 | } | 1476 | } |
1463 | packet_start(SSH2_MSG_USERAUTH_REQUEST); | 1477 | packet_start(SSH2_MSG_USERAUTH_REQUEST); |
@@ -1473,6 +1487,7 @@ userauth_hostbased(Authctxt *authctxt) | |||
1473 | xfree(signature); | 1487 | xfree(signature); |
1474 | xfree(chost); | 1488 | xfree(chost); |
1475 | xfree(pkalg); | 1489 | xfree(pkalg); |
1490 | xfree(blob); | ||
1476 | 1491 | ||
1477 | packet_send(); | 1492 | packet_send(); |
1478 | return 1; | 1493 | return 1; |