summaryrefslogtreecommitdiff
path: root/gss-genr.c
diff options
context:
space:
mode:
Diffstat (limited to 'gss-genr.c')
-rw-r--r--gss-genr.c156
1 files changed, 156 insertions, 0 deletions
diff --git a/gss-genr.c b/gss-genr.c
index 3f5727b3e..36925df4e 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
40extern u_char *session_id2; 41extern u_char *session_id2;
41extern u_int session_id2_len; 42extern u_int session_id2_len;
42 43
44typedef 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
54Gssctxt *gss_kex_context = NULL;
55
56static 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
66char *
67ssh_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
77char *
78ssh_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
148gss_OID
149ssh_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 */
44int 169int
45ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len) 170ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len)
@@ -250,6 +375,9 @@ ssh_gssapi_acquire_cred(Gssctxt *ctx)
250OM_uint32 375OM_uint32
251ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) 376ssh_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 */
389OM_uint32
390ssh_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
260void 401void
261ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service, 402ssh_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
422int
423ssh_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 */