gssapictx.c revision 143731
1/*
2 * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000, 2001  Internet Software Consortium.
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/* $Id: gssapictx.c,v 1.1.4.1 2004/12/09 04:07:17 marka Exp $ */
19
20#include <config.h>
21
22#include <stdlib.h>
23
24#include <isc/buffer.h>
25#include <isc/dir.h>
26#include <isc/entropy.h>
27#include <isc/lex.h>
28#include <isc/mem.h>
29#include <isc/once.h>
30#include <isc/random.h>
31#include <isc/string.h>
32#include <isc/time.h>
33#include <isc/util.h>
34
35#include <dns/fixedname.h>
36#include <dns/name.h>
37#include <dns/rdata.h>
38#include <dns/rdataclass.h>
39#include <dns/result.h>
40#include <dns/types.h>
41#include <dns/keyvalues.h>
42
43#include <dst/gssapi.h>
44#include <dst/result.h>
45
46#include "dst_internal.h"
47
48#ifdef GSSAPI
49
50#include <gssapi/gssapi.h>
51
52#define RETERR(x) do { \
53	result = (x); \
54	if (result != ISC_R_SUCCESS) \
55		goto out; \
56	} while (0)
57
58#define REGION_TO_GBUFFER(r, gb)		\
59	do {					\
60		(gb).length = (r).length;	\
61		(gb).value = (r).base;		\
62	} while (0)
63
64#define GBUFFER_TO_REGION(gb, r)		\
65	do {					\
66		(r).length = (gb).length;	\
67		(r).base = (gb).value;		\
68	} while (0)
69
70static inline void
71name_to_gbuffer(dns_name_t *name, isc_buffer_t *buffer,
72		gss_buffer_desc *gbuffer)
73{
74	dns_name_t tname, *namep;
75	isc_region_t r;
76	isc_result_t result;
77
78	if (!dns_name_isabsolute(name))
79		namep = name;
80	else {
81		unsigned int labels;
82		dns_name_init(&tname, NULL);
83		labels = dns_name_countlabels(name);
84		dns_name_getlabelsequence(name, 0, labels - 1, &tname);
85		namep = &tname;
86	}
87
88	result = dns_name_totext(namep, ISC_FALSE, buffer);
89	isc_buffer_putuint8(buffer, 0);
90	isc_buffer_usedregion(buffer, &r);
91	REGION_TO_GBUFFER(r, *gbuffer);
92}
93
94isc_result_t
95dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate, void **cred) {
96	isc_buffer_t namebuf;
97	gss_name_t gname;
98	gss_buffer_desc gnamebuf;
99	unsigned char array[DNS_NAME_MAXTEXT + 1];
100	OM_uint32 gret, minor;
101	gss_OID_set mechs;
102	OM_uint32 lifetime;
103	gss_cred_usage_t usage;
104
105	REQUIRE(cred != NULL && *cred == NULL);
106
107	if (name != NULL) {
108		isc_buffer_init(&namebuf, array, sizeof(array));
109		name_to_gbuffer(name, &namebuf, &gnamebuf);
110		gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID,
111				       &gname);
112		if (gret != GSS_S_COMPLETE)
113			return (ISC_R_FAILURE);
114	} else
115		gname = NULL;
116
117	if (initiate)
118		usage = GSS_C_INITIATE;
119	else
120		usage = GSS_C_ACCEPT;
121
122	gret = gss_acquire_cred(&minor, gname, GSS_C_INDEFINITE,
123				GSS_C_NO_OID_SET, usage,
124				cred, &mechs, &lifetime);
125	if (gret != GSS_S_COMPLETE)
126		return (ISC_R_FAILURE);
127	return (ISC_R_SUCCESS);
128}
129
130isc_result_t
131dst_gssapi_initctx(dns_name_t *name, void *cred,
132		   isc_region_t *intoken, isc_buffer_t *outtoken,
133		   void **context)
134{
135	isc_region_t r;
136	isc_buffer_t namebuf;
137	gss_buffer_desc gnamebuf, gintoken, *gintokenp, gouttoken;
138	OM_uint32 gret, minor, flags, ret_flags;
139	gss_OID mech_type, ret_mech_type;
140	OM_uint32 lifetime;
141	gss_name_t gname;
142	isc_result_t result;
143	unsigned char array[DNS_NAME_MAXTEXT + 1];
144
145	isc_buffer_init(&namebuf, array, sizeof(array));
146	name_to_gbuffer(name, &namebuf, &gnamebuf);
147	gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID, &gname);
148	if (gret != GSS_S_COMPLETE)
149		return (ISC_R_FAILURE);
150
151	if (intoken != NULL) {
152		REGION_TO_GBUFFER(*intoken, gintoken);
153		gintokenp = &gintoken;
154	} else
155		gintokenp = NULL;
156
157	if (*context == NULL)
158		*context = GSS_C_NO_CONTEXT;
159	flags = GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_DELEG_FLAG |
160		GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG;
161	mech_type = GSS_C_NO_OID;
162
163	gret = gss_init_sec_context(&minor, cred, context, gname,
164				    mech_type, flags, 0,
165				    GSS_C_NO_CHANNEL_BINDINGS, gintokenp,
166				    &ret_mech_type, &gouttoken, &ret_flags,
167				    &lifetime);
168	if (gret != GSS_S_COMPLETE && gret != GSS_S_CONTINUE_NEEDED)
169		return (ISC_R_FAILURE);
170
171	GBUFFER_TO_REGION(gouttoken, r);
172	RETERR(isc_buffer_copyregion(outtoken, &r));
173
174	if (gret == GSS_S_COMPLETE)
175		return (ISC_R_SUCCESS);
176	else
177		return (DNS_R_CONTINUE);
178
179 out:
180 	return (result);
181}
182
183isc_result_t
184dst_gssapi_acceptctx(dns_name_t *name, void *cred,
185		     isc_region_t *intoken, isc_buffer_t *outtoken,
186		     void **context)
187{
188	isc_region_t r;
189	isc_buffer_t namebuf;
190	gss_buffer_desc gnamebuf, gintoken, gouttoken;
191	OM_uint32 gret, minor, flags;
192	gss_OID mech_type;
193	OM_uint32 lifetime;
194	gss_cred_id_t delegated_cred;
195	gss_name_t gname;
196	isc_result_t result;
197	unsigned char array[DNS_NAME_MAXTEXT + 1];
198
199	isc_buffer_init(&namebuf, array, sizeof(array));
200	name_to_gbuffer(name, &namebuf, &gnamebuf);
201	gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID, &gname);
202	if (gret != GSS_S_COMPLETE)
203		return (ISC_R_FAILURE);
204
205	REGION_TO_GBUFFER(*intoken, gintoken);
206
207	if (*context == NULL)
208		*context = GSS_C_NO_CONTEXT;
209
210	gret = gss_accept_sec_context(&minor, context, cred, &gintoken,
211				      GSS_C_NO_CHANNEL_BINDINGS, gname,
212				      &mech_type, &gouttoken, &flags,
213				      &lifetime, &delegated_cred);
214	if (gret != GSS_S_COMPLETE)
215		return (ISC_R_FAILURE);
216
217	GBUFFER_TO_REGION(gouttoken, r);
218	RETERR(isc_buffer_copyregion(outtoken, &r));
219
220	return (ISC_R_SUCCESS);
221
222 out:
223	return (result);
224}
225
226#else
227
228isc_result_t
229dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate, void **cred) {
230	UNUSED(name);
231	UNUSED(initiate);
232	UNUSED(cred);
233	return (ISC_R_NOTIMPLEMENTED);
234}
235
236isc_result_t
237dst_gssapi_initctx(dns_name_t *name, void *cred,
238		   isc_region_t *intoken, isc_buffer_t *outtoken,
239		   void **context)
240{
241	UNUSED(name);
242	UNUSED(cred);
243	UNUSED(intoken);
244	UNUSED(outtoken);
245	UNUSED(context);
246	return (ISC_R_NOTIMPLEMENTED);
247}
248
249isc_result_t
250dst_gssapi_acceptctx(dns_name_t *name, void *cred,
251		     isc_region_t *intoken, isc_buffer_t *outtoken,
252		     void **context)
253{
254	UNUSED(name);
255	UNUSED(cred);
256	UNUSED(intoken);
257	UNUSED(outtoken);
258	UNUSED(context);
259	return (ISC_R_NOTIMPLEMENTED);
260}
261
262#endif
263