Annotation of src/usr.bin/ssh/gss-genr.c, Revision 1.1.4.1
1.1.4.1 ! brad 1: /* $OpenBSD: gss-genr.c,v 1.1 2003/08/22 10:56:09 markus Exp $ */
1.1 markus 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 */