diff options
Diffstat (limited to 'gss-genr.c')
-rw-r--r-- | gss-genr.c | 136 |
1 files changed, 78 insertions, 58 deletions
diff --git a/gss-genr.c b/gss-genr.c index 491e62cee..763a63ffa 100644 --- a/gss-genr.c +++ b/gss-genr.c | |||
@@ -39,12 +39,13 @@ | |||
39 | #include "xmalloc.h" | 39 | #include "xmalloc.h" |
40 | #include "ssherr.h" | 40 | #include "ssherr.h" |
41 | #include "sshbuf.h" | 41 | #include "sshbuf.h" |
42 | #include "sshkey.h" | ||
43 | #include "log.h" | 42 | #include "log.h" |
44 | #include "ssh2.h" | 43 | #include "ssh2.h" |
45 | #include "cipher.h" | 44 | #include "cipher.h" |
45 | #include "sshkey.h" | ||
46 | #include "kex.h" | 46 | #include "kex.h" |
47 | #include "digest.h" | 47 | #include "digest.h" |
48 | #include "packet.h" | ||
48 | 49 | ||
49 | #include "ssh-gss.h" | 50 | #include "ssh-gss.h" |
50 | 51 | ||
@@ -65,7 +66,7 @@ Gssctxt *gss_kex_context = NULL; | |||
65 | 66 | ||
66 | static ssh_gss_kex_mapping *gss_enc2oid = NULL; | 67 | static ssh_gss_kex_mapping *gss_enc2oid = NULL; |
67 | 68 | ||
68 | int | 69 | int |
69 | ssh_gssapi_oid_table_ok(void) { | 70 | ssh_gssapi_oid_table_ok(void) { |
70 | return (gss_enc2oid != NULL); | 71 | return (gss_enc2oid != NULL); |
71 | } | 72 | } |
@@ -85,6 +86,21 @@ ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g) | |||
85 | return 0; | 86 | return 0; |
86 | } | 87 | } |
87 | 88 | ||
89 | /* sshpkt_get of gss_buffer_desc */ | ||
90 | int | ||
91 | ssh_gssapi_sshpkt_get_buffer_desc(struct ssh *ssh, gss_buffer_desc *g) | ||
92 | { | ||
93 | int r; | ||
94 | u_char *p; | ||
95 | size_t len; | ||
96 | |||
97 | if ((r = sshpkt_get_string(ssh, &p, &len)) != 0) | ||
98 | return r; | ||
99 | g->value = p; | ||
100 | g->length = len; | ||
101 | return 0; | ||
102 | } | ||
103 | |||
88 | /* | 104 | /* |
89 | * Return a list of the gss-group1-sha1 mechanisms supported by this program | 105 | * Return a list of the gss-group1-sha1 mechanisms supported by this program |
90 | * | 106 | * |
@@ -93,27 +109,30 @@ ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g) | |||
93 | */ | 109 | */ |
94 | 110 | ||
95 | char * | 111 | char * |
96 | ssh_gssapi_client_mechanisms(const char *host, const char *client) { | 112 | ssh_gssapi_client_mechanisms(const char *host, const char *client, |
97 | gss_OID_set gss_supported; | 113 | const char *kex) { |
114 | gss_OID_set gss_supported = NULL; | ||
98 | OM_uint32 min_status; | 115 | OM_uint32 min_status; |
99 | 116 | ||
100 | if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported))) | 117 | if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported))) |
101 | return NULL; | 118 | return NULL; |
102 | 119 | ||
103 | return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism, | 120 | return ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism, |
104 | host, client)); | 121 | host, client, kex); |
105 | } | 122 | } |
106 | 123 | ||
107 | char * | 124 | char * |
108 | ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, | 125 | ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, |
109 | const char *host, const char *client) { | 126 | const char *host, const char *client, const char *kex) { |
110 | struct sshbuf *buf; | 127 | struct sshbuf *buf = NULL; |
111 | size_t i; | 128 | size_t i; |
112 | int r, oidpos, enclen; | 129 | int r = SSH_ERR_ALLOC_FAIL; |
130 | int oidpos, enclen; | ||
113 | char *mechs, *encoded; | 131 | char *mechs, *encoded; |
114 | u_char digest[SSH_DIGEST_MAX_LENGTH]; | 132 | u_char digest[SSH_DIGEST_MAX_LENGTH]; |
115 | char deroid[2]; | 133 | char deroid[2]; |
116 | struct ssh_digest_ctx *md; | 134 | struct ssh_digest_ctx *md = NULL; |
135 | char *s, *cp, *p; | ||
117 | 136 | ||
118 | if (gss_enc2oid != NULL) { | 137 | if (gss_enc2oid != NULL) { |
119 | for (i = 0; gss_enc2oid[i].encoded != NULL; i++) | 138 | for (i = 0; gss_enc2oid[i].encoded != NULL; i++) |
@@ -128,6 +147,7 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, | |||
128 | fatal("%s: sshbuf_new failed", __func__); | 147 | fatal("%s: sshbuf_new failed", __func__); |
129 | 148 | ||
130 | oidpos = 0; | 149 | oidpos = 0; |
150 | s = cp = xstrdup(kex); | ||
131 | for (i = 0; i < gss_supported->count; i++) { | 151 | for (i = 0; i < gss_supported->count; i++) { |
132 | if (gss_supported->elements[i].length < 128 && | 152 | if (gss_supported->elements[i].length < 128 && |
133 | (*check)(NULL, &(gss_supported->elements[i]), host, client)) { | 153 | (*check)(NULL, &(gss_supported->elements[i]), host, client)) { |
@@ -136,12 +156,15 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, | |||
136 | deroid[1] = gss_supported->elements[i].length; | 156 | deroid[1] = gss_supported->elements[i].length; |
137 | 157 | ||
138 | if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL || | 158 | if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL || |
139 | ssh_digest_update(md, deroid, 2) != 0 || | 159 | (r = ssh_digest_update(md, deroid, 2)) != 0 || |
140 | ssh_digest_update(md, | 160 | (r = ssh_digest_update(md, |
141 | gss_supported->elements[i].elements, | 161 | gss_supported->elements[i].elements, |
142 | gss_supported->elements[i].length) != 0 || | 162 | gss_supported->elements[i].length)) != 0 || |
143 | ssh_digest_final(md, digest, sizeof(digest)) != 0) | 163 | (r = ssh_digest_final(md, digest, sizeof(digest))) != 0) |
144 | fatal("%s: digest failed", __func__); | 164 | fatal("%s: digest failed: %s", __func__, |
165 | ssh_err(r)); | ||
166 | ssh_digest_free(md); | ||
167 | md = NULL; | ||
145 | 168 | ||
146 | encoded = xmalloc(ssh_digest_bytes(SSH_DIGEST_MD5) | 169 | encoded = xmalloc(ssh_digest_bytes(SSH_DIGEST_MD5) |
147 | * 2); | 170 | * 2); |
@@ -149,69 +172,66 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, | |||
149 | ssh_digest_bytes(SSH_DIGEST_MD5), encoded, | 172 | ssh_digest_bytes(SSH_DIGEST_MD5), encoded, |
150 | ssh_digest_bytes(SSH_DIGEST_MD5) * 2); | 173 | ssh_digest_bytes(SSH_DIGEST_MD5) * 2); |
151 | 174 | ||
152 | if (oidpos != 0) { | 175 | cp = strncpy(s, kex, strlen(kex)); |
153 | if ((r = sshbuf_put_u8(buf, ',')) != 0) | 176 | for ((p = strsep(&cp, ",")); p && *p != '\0'; |
154 | fatal("%s: buffer error: %s", | 177 | (p = strsep(&cp, ","))) { |
178 | if (sshbuf_len(buf) != 0 && | ||
179 | (r = sshbuf_put_u8(buf, ',')) != 0) | ||
180 | fatal("%s: sshbuf_put_u8 error: %s", | ||
181 | __func__, ssh_err(r)); | ||
182 | if ((r = sshbuf_put(buf, p, strlen(p))) != 0 || | ||
183 | (r = sshbuf_put(buf, encoded, enclen)) != 0) | ||
184 | fatal("%s: sshbuf_put error: %s", | ||
155 | __func__, ssh_err(r)); | 185 | __func__, ssh_err(r)); |
156 | } | 186 | } |
157 | 187 | ||
158 | if ((r = sshbuf_put(buf, KEX_GSS_GEX_SHA1_ID, | ||
159 | sizeof(KEX_GSS_GEX_SHA1_ID) - 1)) != 0 || | ||
160 | (r = sshbuf_put(buf, encoded, enclen)) != 0 || | ||
161 | (r = sshbuf_put_u8(buf, ',')) != 0 || | ||
162 | (r = sshbuf_put(buf, KEX_GSS_GRP1_SHA1_ID, | ||
163 | sizeof(KEX_GSS_GRP1_SHA1_ID) - 1)) != 0 || | ||
164 | (r = sshbuf_put(buf, encoded, enclen)) != 0 || | ||
165 | (r = sshbuf_put_u8(buf, ',')) != 0 || | ||
166 | (r = sshbuf_put(buf, KEX_GSS_GRP14_SHA1_ID, | ||
167 | sizeof(KEX_GSS_GRP14_SHA1_ID) - 1)) != 0 || | ||
168 | (r = sshbuf_put(buf, encoded, enclen)) != 0) | ||
169 | fatal("%s: buffer error: %s", | ||
170 | __func__, ssh_err(r)); | ||
171 | |||
172 | gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]); | 188 | gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]); |
173 | gss_enc2oid[oidpos].encoded = encoded; | 189 | gss_enc2oid[oidpos].encoded = encoded; |
174 | oidpos++; | 190 | oidpos++; |
175 | } | 191 | } |
176 | } | 192 | } |
193 | free(s); | ||
177 | gss_enc2oid[oidpos].oid = NULL; | 194 | gss_enc2oid[oidpos].oid = NULL; |
178 | gss_enc2oid[oidpos].encoded = NULL; | 195 | gss_enc2oid[oidpos].encoded = NULL; |
179 | 196 | ||
180 | if ((mechs = sshbuf_dup_string(buf)) == NULL) | 197 | if ((mechs = sshbuf_dup_string(buf)) == NULL) |
181 | fatal("%s: sshbuf_dup_string failed", __func__); | 198 | fatal("%s: sshbuf_dup_string failed", __func__); |
182 | 199 | ||
200 | sshbuf_free(buf); | ||
201 | |||
183 | if (strlen(mechs) == 0) { | 202 | if (strlen(mechs) == 0) { |
184 | free(mechs); | 203 | free(mechs); |
185 | mechs = NULL; | 204 | mechs = NULL; |
186 | } | 205 | } |
187 | 206 | ||
188 | return (mechs); | 207 | return (mechs); |
189 | } | 208 | } |
190 | 209 | ||
191 | gss_OID | 210 | gss_OID |
192 | ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) { | 211 | ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) { |
193 | int i = 0; | 212 | int i = 0; |
194 | 213 | ||
195 | switch (kex_type) { | 214 | #define SKIP_KEX_NAME(type) \ |
196 | case KEX_GSS_GRP1_SHA1: | 215 | case type: \ |
197 | if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID)) | 216 | if (strlen(name) < sizeof(type##_ID)) \ |
198 | return GSS_C_NO_OID; | 217 | return GSS_C_NO_OID; \ |
199 | name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1; | 218 | name += sizeof(type##_ID) - 1; \ |
200 | break; | ||
201 | case KEX_GSS_GRP14_SHA1: | ||
202 | if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID)) | ||
203 | return GSS_C_NO_OID; | ||
204 | name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1; | ||
205 | break; | ||
206 | case KEX_GSS_GEX_SHA1: | ||
207 | if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID)) | ||
208 | return GSS_C_NO_OID; | ||
209 | name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1; | ||
210 | break; | 219 | break; |
220 | |||
221 | switch (kex_type) { | ||
222 | SKIP_KEX_NAME(KEX_GSS_GRP1_SHA1) | ||
223 | SKIP_KEX_NAME(KEX_GSS_GRP14_SHA1) | ||
224 | SKIP_KEX_NAME(KEX_GSS_GRP14_SHA256) | ||
225 | SKIP_KEX_NAME(KEX_GSS_GRP16_SHA512) | ||
226 | SKIP_KEX_NAME(KEX_GSS_GEX_SHA1) | ||
227 | SKIP_KEX_NAME(KEX_GSS_NISTP256_SHA256) | ||
228 | SKIP_KEX_NAME(KEX_GSS_C25519_SHA256) | ||
211 | default: | 229 | default: |
212 | return GSS_C_NO_OID; | 230 | return GSS_C_NO_OID; |
213 | } | 231 | } |
214 | 232 | ||
233 | #undef SKIP_KEX_NAME | ||
234 | |||
215 | while (gss_enc2oid[i].encoded != NULL && | 235 | while (gss_enc2oid[i].encoded != NULL && |
216 | strcmp(name, gss_enc2oid[i].encoded) != 0) | 236 | strcmp(name, gss_enc2oid[i].encoded) != 0) |
217 | i++; | 237 | i++; |
@@ -425,8 +445,8 @@ ssh_gssapi_client_identity(Gssctxt *ctx, const char *name) | |||
425 | GSS_C_NT_USER_NAME, &gssname); | 445 | GSS_C_NT_USER_NAME, &gssname); |
426 | 446 | ||
427 | if (!ctx->major) | 447 | if (!ctx->major) |
428 | ctx->major = gss_acquire_cred(&ctx->minor, | 448 | ctx->major = gss_acquire_cred(&ctx->minor, |
429 | gssname, 0, oidset, GSS_C_INITIATE, | 449 | gssname, 0, oidset, GSS_C_INITIATE, |
430 | &ctx->client_creds, NULL, NULL); | 450 | &ctx->client_creds, NULL, NULL); |
431 | 451 | ||
432 | gss_release_name(&status, &gssname); | 452 | gss_release_name(&status, &gssname); |
@@ -441,7 +461,7 @@ ssh_gssapi_client_identity(Gssctxt *ctx, const char *name) | |||
441 | OM_uint32 | 461 | OM_uint32 |
442 | ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) | 462 | ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) |
443 | { | 463 | { |
444 | if (ctx == NULL) | 464 | if (ctx == NULL) |
445 | return -1; | 465 | return -1; |
446 | 466 | ||
447 | if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, | 467 | if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, |
@@ -480,7 +500,7 @@ ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, | |||
480 | } | 500 | } |
481 | 501 | ||
482 | int | 502 | int |
483 | ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host, | 503 | ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host, |
484 | const char *client) | 504 | const char *client) |
485 | { | 505 | { |
486 | gss_buffer_desc token = GSS_C_EMPTY_BUFFER; | 506 | gss_buffer_desc token = GSS_C_EMPTY_BUFFER; |
@@ -512,7 +532,7 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host, | |||
512 | GSS_C_NO_BUFFER); | 532 | GSS_C_NO_BUFFER); |
513 | } | 533 | } |
514 | 534 | ||
515 | if (GSS_ERROR(major) || intctx != NULL) | 535 | if (GSS_ERROR(major) || intctx != NULL) |
516 | ssh_gssapi_delete_ctx(ctx); | 536 | ssh_gssapi_delete_ctx(ctx); |
517 | 537 | ||
518 | return (!GSS_ERROR(major)); | 538 | return (!GSS_ERROR(major)); |
@@ -527,7 +547,7 @@ ssh_gssapi_credentials_updated(Gssctxt *ctxt) { | |||
527 | static OM_uint32 last_call = 0; | 547 | static OM_uint32 last_call = 0; |
528 | OM_uint32 lifetime, now, major, minor; | 548 | OM_uint32 lifetime, now, major, minor; |
529 | int equal; | 549 | int equal; |
530 | 550 | ||
531 | now = time(NULL); | 551 | now = time(NULL); |
532 | 552 | ||
533 | if (ctxt) { | 553 | if (ctxt) { |
@@ -555,8 +575,8 @@ ssh_gssapi_credentials_updated(Gssctxt *ctxt) { | |||
555 | 575 | ||
556 | if (saved_mech == GSS_C_NO_OID) | 576 | if (saved_mech == GSS_C_NO_OID) |
557 | return 0; | 577 | return 0; |
558 | 578 | ||
559 | major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, | 579 | major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, |
560 | &name, &lifetime, NULL, NULL); | 580 | &name, &lifetime, NULL, NULL); |
561 | if (major == GSS_S_CREDENTIALS_EXPIRED) | 581 | if (major == GSS_S_CREDENTIALS_EXPIRED) |
562 | return 0; | 582 | return 0; |