bind - Upgraded vendor branch to 9.5.2-P1
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / dns / sec / dst / gssapi_link.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 /*
19  * $Id: gssapi_link.c,v 1.7.2.1 2004/03/09 06:11:41 marka Exp $
20  */
21
22 #ifdef GSSAPI
23
24 #include <config.h>
25
26 #include <isc/buffer.h>
27 #include <isc/mem.h>
28 #include <isc/string.h>
29 #include <isc/util.h>
30
31 #include <dst/result.h>
32
33 #include "dst_internal.h"
34 #include "dst_parse.h"
35
36 #include <gssapi/gssapi.h>
37
38 #define INITIAL_BUFFER_SIZE 1024
39 #define BUFFER_EXTRA 1024
40
41 #define REGION_TO_GBUFFER(r, gb) \
42         do { \
43                 (gb).length = (r).length;       \
44                 (gb).value = (r).base;  \
45         } while (0)
46
47 typedef struct gssapi_ctx {
48         isc_buffer_t *buffer;
49         gss_ctx_id_t *context_id;
50 } gssapi_ctx_t;
51
52
53 static isc_result_t
54 gssapi_createctx(dst_key_t *key, dst_context_t *dctx) {
55         gssapi_ctx_t *ctx;
56         isc_result_t result;
57
58         UNUSED(key);
59
60         ctx = isc_mem_get(dctx->mctx, sizeof(gssapi_ctx_t));
61         if (ctx == NULL)
62                 return (ISC_R_NOMEMORY);
63         ctx->buffer = NULL;
64         result = isc_buffer_allocate(dctx->mctx, &ctx->buffer,
65                                      INITIAL_BUFFER_SIZE);
66         if (result != ISC_R_SUCCESS) {
67                 isc_mem_put(dctx->mctx, ctx, sizeof(gssapi_ctx_t));
68                 return (result);
69         }
70         ctx->context_id = key->opaque;
71         dctx->opaque = ctx;
72         return (ISC_R_SUCCESS);
73 }
74
75 static void
76 gssapi_destroyctx(dst_context_t *dctx) {
77         gssapi_ctx_t *ctx = dctx->opaque;
78
79         if (ctx != NULL) {
80                 if (ctx->buffer != NULL)
81                         isc_buffer_free(&ctx->buffer);
82                 isc_mem_put(dctx->mctx, ctx, sizeof(gssapi_ctx_t));
83                 dctx->opaque = NULL;
84         }
85 }
86
87 static isc_result_t
88 gssapi_adddata(dst_context_t *dctx, const isc_region_t *data) {
89         gssapi_ctx_t *ctx = dctx->opaque;
90         isc_buffer_t *newbuffer = NULL;
91         isc_region_t r;
92         unsigned int length;
93         isc_result_t result;
94
95         result = isc_buffer_copyregion(ctx->buffer, data);
96         if (result == ISC_R_SUCCESS)
97                 return (ISC_R_SUCCESS);
98
99         length = isc_buffer_length(ctx->buffer) + data->length + BUFFER_EXTRA;
100
101         result = isc_buffer_allocate(dctx->mctx, &newbuffer, length);
102         if (result != ISC_R_SUCCESS)
103                 return (result);
104
105         isc_buffer_usedregion(ctx->buffer, &r);
106         (void) isc_buffer_copyregion(newbuffer, &r);
107         (void) isc_buffer_copyregion(newbuffer, data);
108
109         isc_buffer_free(&ctx->buffer);
110         ctx->buffer = newbuffer;
111
112         return (ISC_R_SUCCESS);
113 }
114
115 static isc_result_t
116 gssapi_sign(dst_context_t *dctx, isc_buffer_t *sig) {
117         gssapi_ctx_t *ctx = dctx->opaque;
118         isc_region_t message;
119         gss_buffer_desc gmessage, gsig;
120         OM_uint32 minor, gret;
121
122         isc_buffer_usedregion(ctx->buffer, &message);
123         REGION_TO_GBUFFER(message, gmessage);
124
125         gret = gss_get_mic(&minor, ctx->context_id,
126                            GSS_C_QOP_DEFAULT, &gmessage, &gsig);
127         if (gret != 0)
128                 return (ISC_R_FAILURE);
129
130         if (gsig.length > isc_buffer_availablelength(sig)) {
131                 gss_release_buffer(&minor, &gsig);
132                 return (ISC_R_NOSPACE);
133         }
134
135         isc_buffer_putmem(sig, gsig.value, gsig.length);
136
137         gss_release_buffer(&minor, &gsig);
138
139         return (ISC_R_SUCCESS);
140 }
141
142 static isc_result_t
143 gssapi_verify(dst_context_t *dctx, const isc_region_t *sig) {
144         gssapi_ctx_t *ctx = dctx->opaque;
145         isc_region_t message;
146         gss_buffer_desc gmessage, gsig;
147         OM_uint32 minor, gret;
148
149         isc_buffer_usedregion(ctx->buffer, &message);
150         REGION_TO_GBUFFER(message, gmessage);
151
152         REGION_TO_GBUFFER(*sig, gsig);
153
154         gret = gss_verify_mic(&minor, ctx->context_id, &gmessage, &gsig, NULL);
155         if (gret != 0)
156                 return (ISC_R_FAILURE);
157
158         return (ISC_R_SUCCESS);
159 }
160
161 static isc_boolean_t
162 gssapi_compare(const dst_key_t *key1, const dst_key_t *key2) {
163         gss_ctx_id_t gsskey1 = key1->opaque;
164         gss_ctx_id_t gsskey2 = key2->opaque;
165
166         /* No idea */
167         return (ISC_TF(gsskey1 == gsskey2));
168 }
169
170 static isc_result_t
171 gssapi_generate(dst_key_t *key, int unused) {
172         UNUSED(key);
173         UNUSED(unused);
174
175         /* No idea */
176         return (ISC_R_FAILURE);
177 }
178
179 static isc_boolean_t
180 gssapi_isprivate(const dst_key_t *key) {
181         UNUSED(key);
182         return (ISC_TRUE);
183 }
184
185 static isc_boolean_t
186 gssapi_issymmetric(const dst_key_t *key) {
187         UNUSED(key);
188         return (ISC_TRUE);
189 }
190
191 static void
192 gssapi_destroy(dst_key_t *key) {
193         UNUSED(key);
194         /* No idea */
195 }
196
197 static dst_func_t gssapi_functions = {
198         gssapi_createctx,
199         gssapi_destroyctx,
200         gssapi_adddata,
201         gssapi_sign,
202         gssapi_verify,
203         NULL, /* computesecret */
204         gssapi_compare,
205         NULL, /* paramcompare */
206         gssapi_generate,
207         gssapi_isprivate,
208         gssapi_issymmetric,
209         gssapi_destroy,
210         NULL, /* todns */
211         NULL, /* fromdns */
212         NULL, /* tofile */
213         NULL, /* fromfile */
214 };
215
216 isc_result_t
217 dst__gssapi_init(dst_func_t **funcp) {
218         REQUIRE(funcp != NULL && *funcp == NULL);
219         *funcp = &gssapi_functions;
220         return (ISC_R_SUCCESS);
221 }
222
223 void
224 dst__gssapi_destroy(void) {
225 }
226
227 #else
228 int  gssapi_link_unneeded = 1;
229 #endif