diff options
author | Darren Tucker <dtucker@zip.com.au> | 2003-08-26 11:49:55 +1000 |
---|---|---|
committer | Darren Tucker <dtucker@zip.com.au> | 2003-08-26 11:49:55 +1000 |
commit | 0efd155c3c184f0eaa2e1eb244eaaf066e6906e0 (patch) | |
tree | 10f24586373d825d68cefd4a3746fe738cf0614a /gss-genr.c | |
parent | 30912f7259b771a1cf705c0bc47a6c3f3edffb43 (diff) |
- markus@cvs.openbsd.org 2003/08/22 10:56:09
[auth2.c auth2-gss.c auth.h compat.c compat.h gss-genr.c gss-serv-krb5.c
gss-serv.c monitor.c monitor.h monitor_wrap.c monitor_wrap.h readconf.c
readconf.h servconf.c servconf.h session.c session.h ssh-gss.h
ssh_config.5 sshconnect2.c sshd_config sshd_config.5]
support GSS API user authentication; patches from Simon Wilkinson,
stripped down and tested by Jakob and myself.
Diffstat (limited to 'gss-genr.c')
-rw-r--r-- | gss-genr.c | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/gss-genr.c b/gss-genr.c new file mode 100644 index 000000000..bda12d6f1 --- /dev/null +++ b/gss-genr.c | |||
@@ -0,0 +1,256 @@ | |||
1 | /* $OpenBSD: gss-genr.c,v 1.1 2003/08/22 10:56:09 markus Exp $ */ | ||
2 | |||
3 | /* | ||
4 | * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions | ||
8 | * are met: | ||
9 | * 1. Redistributions of source code must retain the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer. | ||
11 | * 2. Redistributions in binary form must reproduce the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer in the | ||
13 | * documentation and/or other materials provided with the distribution. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR | ||
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
25 | */ | ||
26 | |||
27 | #include "includes.h" | ||
28 | |||
29 | #ifdef GSSAPI | ||
30 | |||
31 | #include "xmalloc.h" | ||
32 | #include "bufaux.h" | ||
33 | #include "compat.h" | ||
34 | #include "log.h" | ||
35 | #include "monitor_wrap.h" | ||
36 | |||
37 | #include "ssh-gss.h" | ||
38 | |||
39 | |||
40 | /* Check that the OID in a data stream matches that in the context */ | ||
41 | int | ||
42 | ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len) | ||
43 | { | ||
44 | return (ctx != NULL && ctx->oid != GSS_C_NO_OID && | ||
45 | ctx->oid->length == len && | ||
46 | memcmp(ctx->oid->elements, data, len) == 0); | ||
47 | } | ||
48 | |||
49 | /* Set the contexts OID from a data stream */ | ||
50 | void | ||
51 | ssh_gssapi_set_oid_data(Gssctxt *ctx, void *data, size_t len) | ||
52 | { | ||
53 | if (ctx->oid != GSS_C_NO_OID) { | ||
54 | xfree(ctx->oid->elements); | ||
55 | xfree(ctx->oid); | ||
56 | } | ||
57 | ctx->oid = xmalloc(sizeof(gss_OID_desc)); | ||
58 | ctx->oid->length = len; | ||
59 | ctx->oid->elements = xmalloc(len); | ||
60 | memcpy(ctx->oid->elements, data, len); | ||
61 | } | ||
62 | |||
63 | /* Set the contexts OID */ | ||
64 | void | ||
65 | ssh_gssapi_set_oid(Gssctxt *ctx, gss_OID oid) | ||
66 | { | ||
67 | ssh_gssapi_set_oid_data(ctx, oid->elements, oid->length); | ||
68 | } | ||
69 | |||
70 | /* All this effort to report an error ... */ | ||
71 | void | ||
72 | ssh_gssapi_error(Gssctxt *ctxt) | ||
73 | { | ||
74 | debug("%s", ssh_gssapi_last_error(ctxt, NULL, NULL)); | ||
75 | } | ||
76 | |||
77 | char * | ||
78 | ssh_gssapi_last_error(Gssctxt *ctxt, | ||
79 | OM_uint32 *major_status, OM_uint32 *minor_status) | ||
80 | { | ||
81 | OM_uint32 lmin; | ||
82 | gss_buffer_desc msg = GSS_C_EMPTY_BUFFER; | ||
83 | OM_uint32 ctx; | ||
84 | Buffer b; | ||
85 | char *ret; | ||
86 | |||
87 | buffer_init(&b); | ||
88 | |||
89 | if (major_status != NULL) | ||
90 | *major_status = ctxt->major; | ||
91 | if (minor_status != NULL) | ||
92 | *minor_status = ctxt->minor; | ||
93 | |||
94 | ctx = 0; | ||
95 | /* The GSSAPI error */ | ||
96 | do { | ||
97 | gss_display_status(&lmin, ctxt->major, | ||
98 | GSS_C_GSS_CODE, GSS_C_NULL_OID, &ctx, &msg); | ||
99 | |||
100 | buffer_append(&b, msg.value, msg.length); | ||
101 | buffer_put_char(&b, '\n'); | ||
102 | |||
103 | gss_release_buffer(&lmin, &msg); | ||
104 | } while (ctx != 0); | ||
105 | |||
106 | /* The mechanism specific error */ | ||
107 | do { | ||
108 | gss_display_status(&lmin, ctxt->minor, | ||
109 | GSS_C_MECH_CODE, GSS_C_NULL_OID, &ctx, &msg); | ||
110 | |||
111 | buffer_append(&b, msg.value, msg.length); | ||
112 | buffer_put_char(&b, '\n'); | ||
113 | |||
114 | gss_release_buffer(&lmin, &msg); | ||
115 | } while (ctx != 0); | ||
116 | |||
117 | buffer_put_char(&b, '\0'); | ||
118 | ret = xmalloc(buffer_len(&b)); | ||
119 | buffer_get(&b, ret, buffer_len(&b)); | ||
120 | buffer_free(&b); | ||
121 | return (ret); | ||
122 | } | ||
123 | |||
124 | /* | ||
125 | * Initialise our GSSAPI context. We use this opaque structure to contain all | ||
126 | * of the data which both the client and server need to persist across | ||
127 | * {accept,init}_sec_context calls, so that when we do it from the userauth | ||
128 | * stuff life is a little easier | ||
129 | */ | ||
130 | void | ||
131 | ssh_gssapi_build_ctx(Gssctxt **ctx) | ||
132 | { | ||
133 | *ctx = xmalloc(sizeof (Gssctxt)); | ||
134 | (*ctx)->major = 0; | ||
135 | (*ctx)->minor = 0; | ||
136 | (*ctx)->context = GSS_C_NO_CONTEXT; | ||
137 | (*ctx)->name = GSS_C_NO_NAME; | ||
138 | (*ctx)->oid = GSS_C_NO_OID; | ||
139 | (*ctx)->creds = GSS_C_NO_CREDENTIAL; | ||
140 | (*ctx)->client = GSS_C_NO_NAME; | ||
141 | (*ctx)->client_creds = GSS_C_NO_CREDENTIAL; | ||
142 | } | ||
143 | |||
144 | /* Delete our context, providing it has been built correctly */ | ||
145 | void | ||
146 | ssh_gssapi_delete_ctx(Gssctxt **ctx) | ||
147 | { | ||
148 | OM_uint32 ms; | ||
149 | |||
150 | if ((*ctx) == NULL) | ||
151 | return; | ||
152 | if ((*ctx)->context != GSS_C_NO_CONTEXT) | ||
153 | gss_delete_sec_context(&ms, &(*ctx)->context, GSS_C_NO_BUFFER); | ||
154 | if ((*ctx)->name != GSS_C_NO_NAME) | ||
155 | gss_release_name(&ms, &(*ctx)->name); | ||
156 | if ((*ctx)->oid != GSS_C_NO_OID) { | ||
157 | xfree((*ctx)->oid->elements); | ||
158 | xfree((*ctx)->oid); | ||
159 | (*ctx)->oid = GSS_C_NO_OID; | ||
160 | } | ||
161 | if ((*ctx)->creds != GSS_C_NO_CREDENTIAL) | ||
162 | gss_release_cred(&ms, &(*ctx)->creds); | ||
163 | if ((*ctx)->client != GSS_C_NO_NAME) | ||
164 | gss_release_name(&ms, &(*ctx)->client); | ||
165 | if ((*ctx)->client_creds != GSS_C_NO_CREDENTIAL) | ||
166 | gss_release_cred(&ms, &(*ctx)->client_creds); | ||
167 | |||
168 | xfree(*ctx); | ||
169 | *ctx = NULL; | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * Wrapper to init_sec_context | ||
174 | * Requires that the context contains: | ||
175 | * oid | ||
176 | * server name (from ssh_gssapi_import_name) | ||
177 | */ | ||
178 | OM_uint32 | ||
179 | ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok, | ||
180 | gss_buffer_desc* send_tok, OM_uint32 *flags) | ||
181 | { | ||
182 | int deleg_flag = 0; | ||
183 | |||
184 | if (deleg_creds) { | ||
185 | deleg_flag = GSS_C_DELEG_FLAG; | ||
186 | debug("Delegating credentials"); | ||
187 | } | ||
188 | |||
189 | ctx->major = gss_init_sec_context(&ctx->minor, | ||
190 | GSS_C_NO_CREDENTIAL, &ctx->context, ctx->name, ctx->oid, | ||
191 | GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag, | ||
192 | 0, NULL, recv_tok, NULL, send_tok, flags, NULL); | ||
193 | |||
194 | if (GSS_ERROR(ctx->major)) | ||
195 | ssh_gssapi_error(ctx); | ||
196 | |||
197 | return (ctx->major); | ||
198 | } | ||
199 | |||
200 | /* Create a service name for the given host */ | ||
201 | OM_uint32 | ||
202 | ssh_gssapi_import_name(Gssctxt *ctx, const char *host) | ||
203 | { | ||
204 | gss_buffer_desc gssbuf; | ||
205 | |||
206 | gssbuf.length = sizeof("host@") + strlen(host); | ||
207 | gssbuf.value = xmalloc(gssbuf.length); | ||
208 | snprintf(gssbuf.value, gssbuf.length, "host@%s", host); | ||
209 | |||
210 | if ((ctx->major = gss_import_name(&ctx->minor, | ||
211 | &gssbuf, GSS_C_NT_HOSTBASED_SERVICE, &ctx->name))) | ||
212 | ssh_gssapi_error(ctx); | ||
213 | |||
214 | xfree(gssbuf.value); | ||
215 | return (ctx->major); | ||
216 | } | ||
217 | |||
218 | /* Acquire credentials for a server running on the current host. | ||
219 | * Requires that the context structure contains a valid OID | ||
220 | */ | ||
221 | |||
222 | /* Returns a GSSAPI error code */ | ||
223 | OM_uint32 | ||
224 | ssh_gssapi_acquire_cred(Gssctxt *ctx) | ||
225 | { | ||
226 | OM_uint32 status; | ||
227 | char lname[MAXHOSTNAMELEN]; | ||
228 | gss_OID_set oidset; | ||
229 | |||
230 | gss_create_empty_oid_set(&status, &oidset); | ||
231 | gss_add_oid_set_member(&status, ctx->oid, &oidset); | ||
232 | |||
233 | if (gethostname(lname, MAXHOSTNAMELEN)) | ||
234 | return (-1); | ||
235 | |||
236 | if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) | ||
237 | return (ctx->major); | ||
238 | |||
239 | if ((ctx->major = gss_acquire_cred(&ctx->minor, | ||
240 | ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, NULL, NULL))) | ||
241 | ssh_gssapi_error(ctx); | ||
242 | |||
243 | gss_release_oid_set(&status, &oidset); | ||
244 | return (ctx->major); | ||
245 | } | ||
246 | |||
247 | OM_uint32 | ||
248 | ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) { | ||
249 | if (*ctx) | ||
250 | ssh_gssapi_delete_ctx(ctx); | ||
251 | ssh_gssapi_build_ctx(ctx); | ||
252 | ssh_gssapi_set_oid(*ctx, oid); | ||
253 | return (ssh_gssapi_acquire_cred(*ctx)); | ||
254 | } | ||
255 | |||
256 | #endif /* GSSAPI */ | ||