summaryrefslogtreecommitdiff
path: root/gss-genr.c
diff options
context:
space:
mode:
Diffstat (limited to 'gss-genr.c')
-rw-r--r--gss-genr.c136
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
66static ssh_gss_kex_mapping *gss_enc2oid = NULL; 67static ssh_gss_kex_mapping *gss_enc2oid = NULL;
67 68
68int 69int
69ssh_gssapi_oid_table_ok(void) { 70ssh_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 */
90int
91ssh_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
95char * 111char *
96ssh_gssapi_client_mechanisms(const char *host, const char *client) { 112ssh_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
107char * 124char *
108ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, 125ssh_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
191gss_OID 210gss_OID
192ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) { 211ssh_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)
441OM_uint32 461OM_uint32
442ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) 462ssh_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
482int 502int
483ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host, 503ssh_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;