diff options
Diffstat (limited to 'gss-genr.c')
-rw-r--r-- | gss-genr.c | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/gss-genr.c b/gss-genr.c index c2b4f2dd8..2a905f5e9 100644 --- a/gss-genr.c +++ b/gss-genr.c | |||
@@ -32,12 +32,137 @@ | |||
32 | #include "bufaux.h" | 32 | #include "bufaux.h" |
33 | #include "log.h" | 33 | #include "log.h" |
34 | #include "ssh2.h" | 34 | #include "ssh2.h" |
35 | #include <openssl/evp.h> | ||
35 | 36 | ||
36 | #include "ssh-gss.h" | 37 | #include "ssh-gss.h" |
37 | 38 | ||
38 | extern u_char *session_id2; | 39 | extern u_char *session_id2; |
39 | extern u_int session_id2_len; | 40 | extern u_int session_id2_len; |
40 | 41 | ||
42 | typedef struct { | ||
43 | char *encoded; | ||
44 | gss_OID oid; | ||
45 | } ssh_gss_kex_mapping; | ||
46 | |||
47 | /* | ||
48 | * XXX - It would be nice to find a more elegant way of handling the | ||
49 | * XXX passing of the key exchange context to the userauth routines | ||
50 | */ | ||
51 | |||
52 | Gssctxt *gss_kex_context = NULL; | ||
53 | |||
54 | static ssh_gss_kex_mapping *gss_enc2oid = NULL; | ||
55 | |||
56 | /* | ||
57 | * Return a list of the gss-group1-sha1 mechanisms supported by this program | ||
58 | * | ||
59 | * We test mechanisms to ensure that we can use them, to avoid starting | ||
60 | * a key exchange with a bad mechanism | ||
61 | */ | ||
62 | |||
63 | |||
64 | char * | ||
65 | ssh_gssapi_client_mechanisms(char *host) { | ||
66 | gss_OID_set gss_supported; | ||
67 | OM_uint32 min_status; | ||
68 | |||
69 | gss_indicate_mechs(&min_status, &gss_supported); | ||
70 | |||
71 | return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism, | ||
72 | (void *)host)); | ||
73 | } | ||
74 | |||
75 | char * | ||
76 | ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, | ||
77 | void *data) { | ||
78 | Buffer buf; | ||
79 | int i, oidpos, enclen; | ||
80 | char *mechs, *encoded; | ||
81 | char digest[EVP_MAX_MD_SIZE]; | ||
82 | char deroid[2]; | ||
83 | const EVP_MD *evp_md = EVP_md5(); | ||
84 | EVP_MD_CTX md; | ||
85 | |||
86 | evp_md = EVP_md5(); | ||
87 | |||
88 | if (gss_enc2oid != NULL) { | ||
89 | for (i=0;gss_enc2oid[i].encoded!=NULL;i++) | ||
90 | xfree(gss_enc2oid[i].encoded); | ||
91 | xfree(gss_enc2oid); | ||
92 | } | ||
93 | |||
94 | gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping)* | ||
95 | (gss_supported->count+1)); | ||
96 | |||
97 | buffer_init(&buf); | ||
98 | |||
99 | oidpos = 0; | ||
100 | for (i=0;i<gss_supported->count;i++) { | ||
101 | if (gss_supported->elements[i].length<128 && | ||
102 | (*check)(&(gss_supported->elements[i]), data)) { | ||
103 | |||
104 | deroid[0] = SSH_GSS_OIDTYPE; | ||
105 | deroid[1] = gss_supported->elements[i].length; | ||
106 | EVP_DigestInit(&md, evp_md); | ||
107 | EVP_DigestUpdate(&md, deroid, 2); | ||
108 | EVP_DigestUpdate(&md, | ||
109 | gss_supported->elements[i].elements, | ||
110 | gss_supported->elements[i].length); | ||
111 | EVP_DigestFinal(&md, digest, NULL); | ||
112 | |||
113 | encoded = xmalloc(EVP_MD_size(evp_md)*2); | ||
114 | enclen = __b64_ntop(digest, EVP_MD_size(evp_md), | ||
115 | encoded, EVP_MD_size(evp_md)*2); | ||
116 | |||
117 | if (oidpos != 0) | ||
118 | buffer_put_char(&buf,','); | ||
119 | |||
120 | buffer_append(&buf, KEX_GSS_SHA1, | ||
121 | sizeof(KEX_GSS_SHA1)-1); | ||
122 | buffer_append(&buf, encoded, enclen); | ||
123 | |||
124 | gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]); | ||
125 | gss_enc2oid[oidpos].encoded = encoded; | ||
126 | oidpos++; | ||
127 | } | ||
128 | } | ||
129 | gss_enc2oid[oidpos].oid = NULL; | ||
130 | gss_enc2oid[oidpos].encoded = NULL; | ||
131 | |||
132 | buffer_put_char(&buf,'\0'); | ||
133 | |||
134 | mechs = xmalloc(buffer_len(&buf)); | ||
135 | buffer_get(&buf, mechs, buffer_len(&buf)); | ||
136 | buffer_free(&buf); | ||
137 | |||
138 | if (strlen(mechs) == 0) { | ||
139 | xfree(mechs); | ||
140 | mechs = NULL; | ||
141 | } | ||
142 | |||
143 | return (mechs); | ||
144 | } | ||
145 | |||
146 | gss_OID | ||
147 | ssh_gssapi_id_kex(Gssctxt *ctx, char *name) { | ||
148 | int i = 0; | ||
149 | |||
150 | if (strncmp(name, KEX_GSS_SHA1, sizeof(KEX_GSS_SHA1)-1) != 0) | ||
151 | return NULL; | ||
152 | |||
153 | name+=sizeof(KEX_GSS_SHA1)-1; /* Skip ID string */ | ||
154 | |||
155 | while (gss_enc2oid[i].encoded != NULL && | ||
156 | strcmp(name,gss_enc2oid[i].encoded)!=0) { | ||
157 | i++; | ||
158 | } | ||
159 | |||
160 | if (gss_enc2oid[i].oid != NULL && ctx != NULL) | ||
161 | ssh_gssapi_set_oid(ctx,gss_enc2oid[i].oid); | ||
162 | |||
163 | return gss_enc2oid[i].oid; | ||
164 | } | ||
165 | |||
41 | /* Check that the OID in a data stream matches that in the context */ | 166 | /* Check that the OID in a data stream matches that in the context */ |
42 | int | 167 | int |
43 | ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len) | 168 | ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len) |
@@ -248,6 +373,9 @@ ssh_gssapi_acquire_cred(Gssctxt *ctx) | |||
248 | OM_uint32 | 373 | OM_uint32 |
249 | ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) | 374 | ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) |
250 | { | 375 | { |
376 | if (ctx == NULL) | ||
377 | return -1; | ||
378 | |||
251 | if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, | 379 | if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, |
252 | GSS_C_QOP_DEFAULT, buffer, hash))) | 380 | GSS_C_QOP_DEFAULT, buffer, hash))) |
253 | ssh_gssapi_error(ctx); | 381 | ssh_gssapi_error(ctx); |
@@ -255,6 +383,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) | |||
255 | return (ctx->major); | 383 | return (ctx->major); |
256 | } | 384 | } |
257 | 385 | ||
386 | /* Priviledged when used by server */ | ||
387 | OM_uint32 | ||
388 | ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) | ||
389 | { | ||
390 | if (ctx == NULL) | ||
391 | return -1; | ||
392 | |||
393 | ctx->major = gss_verify_mic(&ctx->minor, ctx->context, | ||
394 | gssbuf, gssmic, NULL); | ||
395 | |||
396 | return (ctx->major); | ||
397 | } | ||
398 | |||
258 | void | 399 | void |
259 | ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service, | 400 | ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service, |
260 | const char *context) | 401 | const char *context) |
@@ -277,4 +418,19 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) | |||
277 | return (ssh_gssapi_acquire_cred(*ctx)); | 418 | return (ssh_gssapi_acquire_cred(*ctx)); |
278 | } | 419 | } |
279 | 420 | ||
421 | int | ||
422 | ssh_gssapi_check_mechanism(gss_OID oid, void *host) { | ||
423 | Gssctxt * ctx = NULL; | ||
424 | gss_buffer_desc token = GSS_C_EMPTY_BUFFER; | ||
425 | OM_uint32 major, minor; | ||
426 | |||
427 | ssh_gssapi_build_ctx(&ctx); | ||
428 | ssh_gssapi_set_oid(ctx, oid); | ||
429 | ssh_gssapi_import_name(ctx, host); | ||
430 | major = ssh_gssapi_init_ctx(ctx, 0, GSS_C_NO_BUFFER, &token, NULL); | ||
431 | gss_release_buffer(&minor, &token); | ||
432 | ssh_gssapi_delete_ctx(&ctx); | ||
433 | return (!GSS_ERROR(major)); | ||
434 | } | ||
435 | |||
280 | #endif /* GSSAPI */ | 436 | #endif /* GSSAPI */ |