1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2005 Doug Rabson 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 #include <gssapi/gssapi.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include <errno.h> 35 36 #include "mech_switch.h" 37 #include "name.h" 38 #include "cred.h" 39 #include "context.h" 40 #include "utils.h" 41 42 static gss_cred_id_t 43 _gss_mech_cred_find(gss_cred_id_t cred_handle, gss_OID mech_type) 44 { 45 struct _gss_cred *cred = (struct _gss_cred *)cred_handle; 46 struct _gss_mechanism_cred *mc; 47 48 if (cred == NULL) 49 return GSS_C_NO_CREDENTIAL; 50 51 SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { 52 if (gss_oid_equal(mech_type, mc->gmc_mech_oid)) 53 return mc->gmc_cred; 54 } 55 return GSS_C_NO_CREDENTIAL; 56 } 57 58 OM_uint32 59 gss_init_sec_context(OM_uint32 * minor_status, 60 const gss_cred_id_t initiator_cred_handle, 61 gss_ctx_id_t * context_handle, 62 const gss_name_t target_name, 63 const gss_OID input_mech_type, 64 OM_uint32 req_flags, 65 OM_uint32 time_req, 66 const gss_channel_bindings_t input_chan_bindings, 67 const gss_buffer_t input_token, 68 gss_OID * actual_mech_type, 69 gss_buffer_t output_token, 70 OM_uint32 * ret_flags, 71 OM_uint32 * time_rec) 72 { 73 OM_uint32 major_status; 74 struct _gss_mech_switch *m; 75 struct _gss_name *name = (struct _gss_name *) target_name; 76 struct _gss_mechanism_name *mn; 77 struct _gss_context *ctx = (struct _gss_context *) *context_handle; 78 gss_cred_id_t cred_handle; 79 int allocated_ctx; 80 gss_OID mech_type = input_mech_type; 81 82 *minor_status = 0; 83 84 _gss_buffer_zero(output_token); 85 if (actual_mech_type) 86 *actual_mech_type = GSS_C_NO_OID; 87 if (ret_flags) 88 *ret_flags = 0; 89 if (time_rec) 90 *time_rec = 0; 91 92 /* 93 * If we haven't allocated a context yet, do so now and lookup 94 * the mechanism switch table. If we have one already, make 95 * sure we use the same mechanism switch as before. 96 */ 97 if (!ctx) { 98 if (mech_type == GSS_C_NO_OID) { 99 _gss_load_mech(); 100 if (_gss_mech_oids == GSS_C_NO_OID_SET 101 || _gss_mech_oids->count == 0) 102 return (GSS_S_BAD_MECH); 103 mech_type = &_gss_mech_oids->elements[0]; 104 } 105 106 ctx = malloc(sizeof(struct _gss_context)); 107 if (!ctx) { 108 *minor_status = ENOMEM; 109 return (GSS_S_FAILURE); 110 } 111 memset(ctx, 0, sizeof(struct _gss_context)); 112 m = ctx->gc_mech = _gss_find_mech_switch(mech_type); 113 if (!m) { 114 free(ctx); 115 return (GSS_S_BAD_MECH); 116 } 117 allocated_ctx = 1; 118 } else { 119 m = ctx->gc_mech; 120 mech_type = &ctx->gc_mech->gm_mech_oid; 121 allocated_ctx = 0; 122 } 123 124 /* 125 * Find the MN for this mechanism. 126 */ 127 major_status = _gss_find_mn(minor_status, name, mech_type, &mn); 128 if (major_status != GSS_S_COMPLETE) { 129 if (allocated_ctx) 130 free(ctx); 131 return (major_status); 132 } 133 134 /* 135 * If we have a cred, find the cred for this mechanism. 136 */ 137 cred_handle = _gss_mech_cred_find(initiator_cred_handle, mech_type); 138 139 major_status = m->gm_init_sec_context(minor_status, 140 cred_handle, 141 &ctx->gc_ctx, 142 mn->gmn_name, 143 mech_type, 144 req_flags, 145 time_req, 146 input_chan_bindings, 147 input_token, 148 actual_mech_type, 149 output_token, 150 ret_flags, 151 time_rec); 152 153 if (major_status != GSS_S_COMPLETE 154 && major_status != GSS_S_CONTINUE_NEEDED) { 155 if (allocated_ctx) 156 free(ctx); 157 _gss_buffer_zero(output_token); 158 _gss_mg_error(m, major_status, *minor_status); 159 } else { 160 *context_handle = (gss_ctx_id_t) ctx; 161 } 162 163 return (major_status); 164 } 165