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