Detect FPU by checking CPUID features.
[dragonfly.git] / contrib / bind-9.5.2 / lib / dns / gssapi_link.c
blob6b4a90ab711ebd466ea8a5ee193a23b34bc96eb2
1 /*
2 * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-2002 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or 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.
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.
19 * $Id: gssapi_link.c,v 1.7.128.5 2008/07/23 10:33:26 marka Exp $
22 #include <config.h>
24 #ifdef GSSAPI
26 #include <isc/buffer.h>
27 #include <isc/mem.h>
28 #include <isc/string.h>
29 #include <isc/util.h>
31 #include <dst/result.h>
33 #include "dst_internal.h"
34 #include "dst_parse.h"
36 #include <dst/gssapi.h>
38 #define INITIAL_BUFFER_SIZE 1024
39 #define BUFFER_EXTRA 1024
41 #define REGION_TO_GBUFFER(r, gb) \
42 do { \
43 (gb).length = (r).length; \
44 (gb).value = (r).base; \
45 } while (0)
48 struct dst_gssapi_signverifyctx {
49 isc_buffer_t *buffer;
52 /*%
53 * Allocate a temporary "context" for use in gathering data for signing
54 * or verifying.
56 static isc_result_t
57 gssapi_create_signverify_ctx(dst_key_t *key, dst_context_t *dctx) {
58 dst_gssapi_signverifyctx_t *ctx;
59 isc_result_t result;
61 UNUSED(key);
63 ctx = isc_mem_get(dctx->mctx, sizeof(dst_gssapi_signverifyctx_t));
64 if (ctx == NULL)
65 return (ISC_R_NOMEMORY);
66 ctx->buffer = NULL;
67 result = isc_buffer_allocate(dctx->mctx, &ctx->buffer,
68 INITIAL_BUFFER_SIZE);
69 if (result != ISC_R_SUCCESS) {
70 isc_mem_put(dctx->mctx, ctx, sizeof(dst_gssapi_signverifyctx_t));
71 return (result);
74 dctx->ctxdata.gssctx = ctx;
76 return (ISC_R_SUCCESS);
79 /*%
80 * Destroy the temporary sign/verify context.
82 static void
83 gssapi_destroy_signverify_ctx(dst_context_t *dctx) {
84 dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
86 if (ctx != NULL) {
87 if (ctx->buffer != NULL)
88 isc_buffer_free(&ctx->buffer);
89 isc_mem_put(dctx->mctx, ctx, sizeof(dst_gssapi_signverifyctx_t));
90 dctx->ctxdata.gssctx = NULL;
94 /*%
95 * Add data to our running buffer of data we will be signing or verifying.
96 * This code will see if the new data will fit in our existing buffer, and
97 * copy it in if it will. If not, it will attempt to allocate a larger
98 * buffer and copy old+new into it, and free the old buffer.
100 static isc_result_t
101 gssapi_adddata(dst_context_t *dctx, const isc_region_t *data) {
102 dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
103 isc_buffer_t *newbuffer = NULL;
104 isc_region_t r;
105 unsigned int length;
106 isc_result_t result;
108 result = isc_buffer_copyregion(ctx->buffer, data);
109 if (result == ISC_R_SUCCESS)
110 return (ISC_R_SUCCESS);
112 length = isc_buffer_length(ctx->buffer) + data->length + BUFFER_EXTRA;
114 result = isc_buffer_allocate(dctx->mctx, &newbuffer, length);
115 if (result != ISC_R_SUCCESS)
116 return (result);
118 isc_buffer_usedregion(ctx->buffer, &r);
119 (void)isc_buffer_copyregion(newbuffer, &r);
120 (void)isc_buffer_copyregion(newbuffer, data);
122 isc_buffer_free(&ctx->buffer);
123 ctx->buffer = newbuffer;
125 return (ISC_R_SUCCESS);
129 * Sign.
131 static isc_result_t
132 gssapi_sign(dst_context_t *dctx, isc_buffer_t *sig) {
133 dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
134 isc_region_t message;
135 gss_buffer_desc gmessage, gsig;
136 OM_uint32 minor, gret;
137 gss_ctx_id_t gssctx = dctx->key->keydata.gssctx;
138 char buf[1024];
141 * Convert the data we wish to sign into a structure gssapi can
142 * understand.
144 isc_buffer_usedregion(ctx->buffer, &message);
145 REGION_TO_GBUFFER(message, gmessage);
148 * Generate the signature.
150 gret = gss_get_mic(&minor, gssctx, GSS_C_QOP_DEFAULT, &gmessage,
151 &gsig);
154 * If it did not complete, we log the result and return a generic
155 * failure code.
157 if (gret != GSS_S_COMPLETE) {
158 gss_log(3, "GSS sign error: %s",
159 gss_error_tostring(gret, minor, buf, sizeof(buf)));
160 return (ISC_R_FAILURE);
164 * If it will not fit in our allocated buffer, return that we need
165 * more space.
167 if (gsig.length > isc_buffer_availablelength(sig)) {
168 gss_release_buffer(&minor, &gsig);
169 return (ISC_R_NOSPACE);
173 * Copy the output into our buffer space, and release the gssapi
174 * allocated space.
176 isc_buffer_putmem(sig, gsig.value, gsig.length);
177 if (gsig.length != 0)
178 gss_release_buffer(&minor, &gsig);
180 return (ISC_R_SUCCESS);
184 * Verify.
186 static isc_result_t
187 gssapi_verify(dst_context_t *dctx, const isc_region_t *sig) {
188 dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
189 isc_region_t message, r;
190 gss_buffer_desc gmessage, gsig;
191 OM_uint32 minor, gret;
192 gss_ctx_id_t gssctx = dctx->key->keydata.gssctx;
193 unsigned char *buf;
194 char err[1024];
197 * Convert the data we wish to sign into a structure gssapi can
198 * understand.
200 isc_buffer_usedregion(ctx->buffer, &message);
201 REGION_TO_GBUFFER(message, gmessage);
204 * XXXMLG
205 * It seem that gss_verify_mic() modifies the signature buffer,
206 * at least on Heimdal's implementation. Copy it here to an allocated
207 * buffer.
209 buf = isc_mem_allocate(dst__memory_pool, sig->length);
210 if (buf == NULL)
211 return (ISC_R_FAILURE);
212 memcpy(buf, sig->base, sig->length);
213 r.base = buf;
214 r.length = sig->length;
215 REGION_TO_GBUFFER(r, gsig);
218 * Verify the data.
220 gret = gss_verify_mic(&minor, gssctx, &gmessage, &gsig, NULL);
222 isc_mem_free(dst__memory_pool, buf);
225 * Convert return codes into something useful to us.
227 if (gret != GSS_S_COMPLETE) {
228 gss_log(3, "GSS verify error: %s",
229 gss_error_tostring(gret, minor, err, sizeof(err)));
230 if (gret == GSS_S_DEFECTIVE_TOKEN ||
231 gret == GSS_S_BAD_SIG ||
232 gret == GSS_S_DUPLICATE_TOKEN ||
233 gret == GSS_S_OLD_TOKEN ||
234 gret == GSS_S_UNSEQ_TOKEN ||
235 gret == GSS_S_GAP_TOKEN ||
236 gret == GSS_S_CONTEXT_EXPIRED ||
237 gret == GSS_S_NO_CONTEXT ||
238 gret == GSS_S_FAILURE)
239 return(DST_R_VERIFYFAILURE);
240 else
241 return (ISC_R_FAILURE);
244 return (ISC_R_SUCCESS);
247 static isc_boolean_t
248 gssapi_compare(const dst_key_t *key1, const dst_key_t *key2) {
249 gss_ctx_id_t gsskey1 = key1->keydata.gssctx;
250 gss_ctx_id_t gsskey2 = key2->keydata.gssctx;
252 /* No idea */
253 return (ISC_TF(gsskey1 == gsskey2));
256 static isc_result_t
257 gssapi_generate(dst_key_t *key, int unused) {
258 UNUSED(key);
259 UNUSED(unused);
261 /* No idea */
262 return (ISC_R_FAILURE);
265 static isc_boolean_t
266 gssapi_isprivate(const dst_key_t *key) {
267 UNUSED(key);
268 return (ISC_TRUE);
271 static void
272 gssapi_destroy(dst_key_t *key) {
273 REQUIRE(key != NULL);
274 dst_gssapi_deletectx(key->mctx, &key->keydata.gssctx);
275 key->keydata.gssctx = NULL;
278 static dst_func_t gssapi_functions = {
279 gssapi_create_signverify_ctx,
280 gssapi_destroy_signverify_ctx,
281 gssapi_adddata,
282 gssapi_sign,
283 gssapi_verify,
284 NULL, /*%< computesecret */
285 gssapi_compare,
286 NULL, /*%< paramcompare */
287 gssapi_generate,
288 gssapi_isprivate,
289 gssapi_destroy,
290 NULL, /*%< todns */
291 NULL, /*%< fromdns */
292 NULL, /*%< tofile */
293 NULL, /*%< parse */
294 NULL /*%< cleanup */
297 isc_result_t
298 dst__gssapi_init(dst_func_t **funcp) {
299 REQUIRE(funcp != NULL);
300 if (*funcp == NULL)
301 *funcp = &gssapi_functions;
302 return (ISC_R_SUCCESS);
305 #else
306 int gssapi_link_unneeded = 1;
307 #endif
309 /*! \file */