Merge from vendor branch NTPD:
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / dns / sec / dst / gssapictx.c
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.3.2.2 2004/03/09 06:11:41 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
70 static inline void
71 name_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
94 isc_result_t
95 dst_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
130 isc_result_t
131 dst_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
183 isc_result_t
184 dst_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
228 isc_result_t
229 dst_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
236 isc_result_t
237 dst_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
249 isc_result_t
250 dst_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