gss_accept_sec_context.c revision 168340
1276479Sdim/*- 2249259Sdim * Copyright (c) 2005 Doug Rabson 3353358Sdim * All rights reserved. 4353358Sdim * 5353358Sdim * Redistribution and use in source and binary forms, with or without 6249259Sdim * modification, are permitted provided that the following conditions 7249259Sdim * are met: 8249259Sdim * 1. Redistributions of source code must retain the above copyright 9276479Sdim * notice, this list of conditions and the following disclaimer. 10249259Sdim * 2. Redistributions in binary form must reproduce the above copyright 11249259Sdim * notice, this list of conditions and the following disclaimer in the 12249259Sdim * documentation and/or other materials provided with the distribution. 13280031Sdim * 14280031Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15249259Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16276479Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17276479Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18280031Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19276479Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20276479Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21327952Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22327952Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23327952Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24327952Sdim * SUCH DAMAGE. 25327952Sdim * 26276479Sdim * $FreeBSD: head/lib/libgssapi/gss_accept_sec_context.c 168340 2007-04-04 02:40:59Z kan $ 27276479Sdim */ 28249259Sdim 29249259Sdim#include <gssapi/gssapi.h> 30249259Sdim#include <stdlib.h> 31249259Sdim#include <string.h> 32249259Sdim#include <errno.h> 33276479Sdim 34249259Sdim#include "mech_switch.h" 35288943Sdim#include "context.h" 36249259Sdim#include "cred.h" 37314564Sdim#include "name.h" 38309124Sdim 39309124SdimOM_uint32 gss_accept_sec_context(OM_uint32 *minor_status, 40296417Sdim gss_ctx_id_t *context_handle, 41360784Sdim const gss_cred_id_t acceptor_cred_handle, 42360784Sdim const gss_buffer_t input_token, 43360784Sdim const gss_channel_bindings_t input_chan_bindings, 44360784Sdim gss_name_t *src_name, 45360784Sdim gss_OID *mech_type, 46296417Sdim gss_buffer_t output_token, 47296417Sdim OM_uint32 *ret_flags, 48327952Sdim OM_uint32 *time_rec, 49296417Sdim gss_cred_id_t *delegated_cred_handle) 50360784Sdim{ 51309124Sdim OM_uint32 major_status; 52309124Sdim struct _gss_mech_switch *m; 53327952Sdim struct _gss_context *ctx = (struct _gss_context *) *context_handle; 54353358Sdim struct _gss_cred *cred = (struct _gss_cred *) acceptor_cred_handle; 55341825Sdim struct _gss_mechanism_cred *mc; 56314564Sdim gss_cred_id_t acceptor_mc, delegated_mc; 57309124Sdim gss_name_t src_mn; 58360784Sdim int allocated_ctx; 59360784Sdim 60327952Sdim *minor_status = 0; 61321369Sdim if (src_name) *src_name = 0; 62321369Sdim if (mech_type) *mech_type = 0; 63321369Sdim if (ret_flags) *ret_flags = 0; 64321369Sdim if (time_rec) *time_rec = 0; 65344779Sdim if (delegated_cred_handle) *delegated_cred_handle = 0; 66363496Sdim output_token->length = 0; 67363496Sdim output_token->value = 0; 68296417Sdim 69276479Sdim /* 70309124Sdim * If this is the first call (*context_handle is NULL), we must 71276479Sdim * parse the input token to figure out the mechanism to use. 72309124Sdim */ 73276479Sdim if (*context_handle == GSS_C_NO_CONTEXT) { 74309124Sdim unsigned char *p = input_token->value; 75309124Sdim size_t len = input_token->length; 76327952Sdim size_t a, b; 77341825Sdim gss_OID_desc mech_oid; 78344779Sdim 79288943Sdim /* 80309124Sdim * Token must start with [APPLICATION 0] SEQUENCE. 81309124Sdim */ 82309124Sdim if (len == 0 || *p != 0x60) 83327952Sdim return (GSS_S_DEFECTIVE_TOKEN); 84309124Sdim p++; 85314564Sdim len--; 86309124Sdim 87321369Sdim /* 88309124Sdim * Decode the length and make sure it agrees with the 89309124Sdim * token length. 90344779Sdim */ 91309124Sdim if (len == 0) 92341825Sdim return (GSS_S_DEFECTIVE_TOKEN); 93344779Sdim if ((*p & 0x80) == 0) { 94344779Sdim a = *p; 95344779Sdim p++; 96344779Sdim len--; 97344779Sdim } else { 98344779Sdim b = *p & 0x7f; 99344779Sdim p++; 100344779Sdim len--; 101344779Sdim if (len < b) 102344779Sdim return (GSS_S_DEFECTIVE_TOKEN); 103353358Sdim a = 0; 104353358Sdim while (b) { 105353358Sdim a = (a << 8) | *p; 106353358Sdim p++; 107353358Sdim len--; 108353358Sdim b--; 109344779Sdim } 110344779Sdim } 111344779Sdim if (a != len) 112344779Sdim return (GSS_S_DEFECTIVE_TOKEN); 113344779Sdim 114344779Sdim /* 115344779Sdim * Decode the OID for the mechanism. Simplify life by 116344779Sdim * assuming that the OID length is less than 128 bytes. 117344779Sdim */ 118344779Sdim if (len < 2 || *p != 0x06) 119344779Sdim return (GSS_S_DEFECTIVE_TOKEN); 120344779Sdim if ((p[1] & 0x80) || p[1] > (len - 2)) 121344779Sdim return (GSS_S_DEFECTIVE_TOKEN); 122344779Sdim mech_oid.length = p[1]; 123360784Sdim p += 2; 124344779Sdim len -= 2; 125344779Sdim mech_oid.elements = p; 126344779Sdim 127341825Sdim /* 128321369Sdim * Now that we have a mechanism, we can find the 129321369Sdim * implementation. 130353358Sdim */ 131327952Sdim ctx = malloc(sizeof(struct _gss_context)); 132341825Sdim if (!ctx) { 133249259Sdim *minor_status = ENOMEM; 134344779Sdim return (GSS_S_DEFECTIVE_TOKEN); 135344779Sdim } 136344779Sdim memset(ctx, 0, sizeof(struct _gss_context)); 137344779Sdim m = ctx->gc_mech = _gss_find_mech_switch(&mech_oid); 138344779Sdim if (!m) { 139344779Sdim free(ctx); 140344779Sdim return (GSS_S_BAD_MECH); 141344779Sdim } 142344779Sdim allocated_ctx = 1; 143344779Sdim } else { 144344779Sdim m = ctx->gc_mech; 145360784Sdim allocated_ctx = 0; 146344779Sdim } 147353358Sdim 148353358Sdim if (cred) { 149353358Sdim SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) 150353358Sdim if (mc->gmc_mech == m) 151353358Sdim break; 152353358Sdim if (!mc) 153360784Sdim return (GSS_S_BAD_MECH); 154360784Sdim acceptor_mc = mc->gmc_cred; 155360784Sdim } else { 156360784Sdim acceptor_mc = GSS_C_NO_CREDENTIAL; 157276479Sdim } 158309124Sdim delegated_mc = GSS_C_NO_CREDENTIAL; 159261991Sdim 160276479Sdim major_status = m->gm_accept_sec_context(minor_status, 161309124Sdim &ctx->gc_ctx, 162344779Sdim acceptor_mc, 163344779Sdim input_token, 164327952Sdim input_chan_bindings, 165276479Sdim &src_mn, 166296417Sdim mech_type, 167309124Sdim output_token, 168321369Sdim ret_flags, 169321369Sdim time_rec, 170321369Sdim &delegated_mc); 171321369Sdim if (major_status != GSS_S_COMPLETE && 172321369Sdim major_status != GSS_S_CONTINUE_NEEDED) 173321369Sdim return (major_status); 174321369Sdim 175309124Sdim if (!src_name) { 176309124Sdim m->gm_release_name(minor_status, &src_mn); 177309124Sdim } else { 178309124Sdim /* 179341825Sdim * Make a new name and mark it as an MN. 180309124Sdim */ 181309124Sdim struct _gss_name *name = _gss_make_name(m, src_mn); 182314564Sdim 183327952Sdim if (!name) { 184309124Sdim m->gm_release_name(minor_status, &src_mn); 185314564Sdim return (GSS_S_FAILURE); 186314564Sdim } 187341825Sdim *src_name = (gss_name_t) name; 188321369Sdim } 189344779Sdim 190341825Sdim if (*ret_flags & GSS_C_DELEG_FLAG) { 191344779Sdim if (!delegated_cred_handle) { 192321369Sdim m->gm_release_cred(minor_status, &delegated_mc); 193309124Sdim *ret_flags &= ~GSS_C_DELEG_FLAG; 194309124Sdim } else { 195344779Sdim struct _gss_cred *cred; 196353358Sdim struct _gss_mechanism_cred *mc; 197353358Sdim 198353358Sdim cred = malloc(sizeof(struct _gss_cred)); 199360784Sdim if (!cred) { 200309124Sdim *minor_status = ENOMEM; 201309124Sdim return (GSS_S_FAILURE); 202309124Sdim } 203309124Sdim mc = malloc(sizeof(struct _gss_mechanism_cred)); 204309124Sdim if (!mc) { 205309124Sdim free(cred); 206360784Sdim *minor_status = ENOMEM; 207360784Sdim return (GSS_S_FAILURE); 208314564Sdim } 209321369Sdim m->gm_inquire_cred(minor_status, delegated_mc, 210296417Sdim 0, 0, &cred->gc_usage, 0); 211344779Sdim mc->gmc_mech = m; 212344779Sdim mc->gmc_mech_oid = &m->gm_mech_oid; 213296417Sdim mc->gmc_cred = delegated_mc; 214344779Sdim SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link); 215344779Sdim 216341825Sdim *delegated_cred_handle = (gss_cred_id_t) cred; 217288943Sdim } 218288943Sdim } 219276479Sdim 220276479Sdim *context_handle = (gss_ctx_id_t) ctx; 221276479Sdim return (major_status); 222276479Sdim} 223276479Sdim