/* * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /* $Id: gssapictx.c,v 1.1.4.1 2004/12/09 04:07:17 marka Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dst_internal.h" #ifdef GSSAPI #include #define RETERR(x) do { \ result = (x); \ if (result != ISC_R_SUCCESS) \ goto out; \ } while (0) #define REGION_TO_GBUFFER(r, gb) \ do { \ (gb).length = (r).length; \ (gb).value = (r).base; \ } while (0) #define GBUFFER_TO_REGION(gb, r) \ do { \ (r).length = (gb).length; \ (r).base = (gb).value; \ } while (0) static inline void name_to_gbuffer(dns_name_t *name, isc_buffer_t *buffer, gss_buffer_desc *gbuffer) { dns_name_t tname, *namep; isc_region_t r; isc_result_t result; if (!dns_name_isabsolute(name)) namep = name; else { unsigned int labels; dns_name_init(&tname, NULL); labels = dns_name_countlabels(name); dns_name_getlabelsequence(name, 0, labels - 1, &tname); namep = &tname; } result = dns_name_totext(namep, ISC_FALSE, buffer); isc_buffer_putuint8(buffer, 0); isc_buffer_usedregion(buffer, &r); REGION_TO_GBUFFER(r, *gbuffer); } isc_result_t dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate, void **cred) { isc_buffer_t namebuf; gss_name_t gname; gss_buffer_desc gnamebuf; unsigned char array[DNS_NAME_MAXTEXT + 1]; OM_uint32 gret, minor; gss_OID_set mechs; OM_uint32 lifetime; gss_cred_usage_t usage; REQUIRE(cred != NULL && *cred == NULL); if (name != NULL) { isc_buffer_init(&namebuf, array, sizeof(array)); name_to_gbuffer(name, &namebuf, &gnamebuf); gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID, &gname); if (gret != GSS_S_COMPLETE) return (ISC_R_FAILURE); } else gname = NULL; if (initiate) usage = GSS_C_INITIATE; else usage = GSS_C_ACCEPT; gret = gss_acquire_cred(&minor, gname, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, usage, cred, &mechs, &lifetime); if (gret != GSS_S_COMPLETE) return (ISC_R_FAILURE); return (ISC_R_SUCCESS); } isc_result_t dst_gssapi_initctx(dns_name_t *name, void *cred, isc_region_t *intoken, isc_buffer_t *outtoken, void **context) { isc_region_t r; isc_buffer_t namebuf; gss_buffer_desc gnamebuf, gintoken, *gintokenp, gouttoken; OM_uint32 gret, minor, flags, ret_flags; gss_OID mech_type, ret_mech_type; OM_uint32 lifetime; gss_name_t gname; isc_result_t result; unsigned char array[DNS_NAME_MAXTEXT + 1]; isc_buffer_init(&namebuf, array, sizeof(array)); name_to_gbuffer(name, &namebuf, &gnamebuf); gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID, &gname); if (gret != GSS_S_COMPLETE) return (ISC_R_FAILURE); if (intoken != NULL) { REGION_TO_GBUFFER(*intoken, gintoken); gintokenp = &gintoken; } else gintokenp = NULL; if (*context == NULL) *context = GSS_C_NO_CONTEXT; flags = GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_DELEG_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG; mech_type = GSS_C_NO_OID; gret = gss_init_sec_context(&minor, cred, context, gname, mech_type, flags, 0, GSS_C_NO_CHANNEL_BINDINGS, gintokenp, &ret_mech_type, &gouttoken, &ret_flags, &lifetime); if (gret != GSS_S_COMPLETE && gret != GSS_S_CONTINUE_NEEDED) return (ISC_R_FAILURE); GBUFFER_TO_REGION(gouttoken, r); RETERR(isc_buffer_copyregion(outtoken, &r)); if (gret == GSS_S_COMPLETE) return (ISC_R_SUCCESS); else return (DNS_R_CONTINUE); out: return (result); } isc_result_t dst_gssapi_acceptctx(dns_name_t *name, void *cred, isc_region_t *intoken, isc_buffer_t *outtoken, void **context) { isc_region_t r; isc_buffer_t namebuf; gss_buffer_desc gnamebuf, gintoken, gouttoken; OM_uint32 gret, minor, flags; gss_OID mech_type; OM_uint32 lifetime; gss_cred_id_t delegated_cred; gss_name_t gname; isc_result_t result; unsigned char array[DNS_NAME_MAXTEXT + 1]; isc_buffer_init(&namebuf, array, sizeof(array)); name_to_gbuffer(name, &namebuf, &gnamebuf); gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID, &gname); if (gret != GSS_S_COMPLETE) return (ISC_R_FAILURE); REGION_TO_GBUFFER(*intoken, gintoken); if (*context == NULL) *context = GSS_C_NO_CONTEXT; gret = gss_accept_sec_context(&minor, context, cred, &gintoken, GSS_C_NO_CHANNEL_BINDINGS, gname, &mech_type, &gouttoken, &flags, &lifetime, &delegated_cred); if (gret != GSS_S_COMPLETE) return (ISC_R_FAILURE); GBUFFER_TO_REGION(gouttoken, r); RETERR(isc_buffer_copyregion(outtoken, &r)); return (ISC_R_SUCCESS); out: return (result); } #else isc_result_t dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate, void **cred) { UNUSED(name); UNUSED(initiate); UNUSED(cred); return (ISC_R_NOTIMPLEMENTED); } isc_result_t dst_gssapi_initctx(dns_name_t *name, void *cred, isc_region_t *intoken, isc_buffer_t *outtoken, void **context) { UNUSED(name); UNUSED(cred); UNUSED(intoken); UNUSED(outtoken); UNUSED(context); return (ISC_R_NOTIMPLEMENTED); } isc_result_t dst_gssapi_acceptctx(dns_name_t *name, void *cred, isc_region_t *intoken, isc_buffer_t *outtoken, void **context) { UNUSED(name); UNUSED(cred); UNUSED(intoken); UNUSED(outtoken); UNUSED(context); return (ISC_R_NOTIMPLEMENTED); } #endif