1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * glue routine for gss_init_sec_context 31 */ 32 #include <mechglueP.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 37 OM_uint32 38 gss_init_sec_context(minor_status, 39 claimant_cred_handle, 40 context_handle, 41 target_name, 42 req_mech_type, 43 req_flags, 44 time_req, 45 input_chan_bindings, 46 input_token, 47 actual_mech_type, 48 output_token, 49 ret_flags, 50 time_rec) 51 52 OM_uint32 * minor_status; 53 const gss_cred_id_t claimant_cred_handle; 54 gss_ctx_id_t *context_handle; 55 const gss_name_t target_name; 56 const gss_OID req_mech_type; 57 OM_uint32 req_flags; 58 OM_uint32 time_req; 59 const gss_channel_bindings_t input_chan_bindings; 60 const gss_buffer_t input_token; 61 gss_OID * actual_mech_type; 62 gss_buffer_t output_token; 63 OM_uint32 * ret_flags; 64 OM_uint32 * time_rec; 65 66 { 67 OM_uint32 status, temp_minor_status; 68 gss_union_name_t union_name; 69 gss_union_cred_t union_cred; 70 gss_name_t internal_name; 71 gss_union_ctx_id_t union_ctx_id; 72 gss_OID mech_type = GSS_C_NULL_OID; 73 gss_mechanism mech; 74 gss_cred_id_t input_cred_handle; 75 76 if (minor_status == NULL) 77 return (GSS_S_CALL_INACCESSIBLE_WRITE); 78 *minor_status = 0; 79 80 /* clear output values */ 81 if (actual_mech_type) 82 *actual_mech_type = NULL; 83 84 if (context_handle == NULL) 85 return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CONTEXT); 86 87 if (target_name == NULL) 88 return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME); 89 90 if (output_token == NULL) 91 return (GSS_S_CALL_INACCESSIBLE_WRITE); 92 93 output_token->value = NULL; 94 output_token->length = 0; 95 96 97 if (req_mech_type) 98 mech_type = (gss_OID)req_mech_type; 99 100 union_name = (gss_union_name_t)target_name; 101 102 /* 103 * obtain the gss mechanism information for the requested 104 * mechanism. If mech_type is NULL, set it to the resultant 105 * mechanism 106 */ 107 mech = __gss_get_mechanism(mech_type); 108 if (mech == NULL) 109 return (GSS_S_BAD_MECH); 110 111 if (mech->gss_init_sec_context == NULL) 112 return (GSS_S_UNAVAILABLE); 113 114 if (mech_type == GSS_C_NULL_OID) 115 mech_type = &mech->mech_type; 116 117 /* 118 * If target_name is mechanism_specific, then it must match the 119 * mech_type that we're about to use. Otherwise, do an import on 120 * the external_name form of the target name. 121 */ 122 if (union_name->mech_type && 123 g_OID_equal(union_name->mech_type, mech_type)) { 124 internal_name = union_name->mech_name; 125 } else { 126 if ((status = __gss_import_internal_name(minor_status, 127 mech_type, union_name, 128 &internal_name)) != GSS_S_COMPLETE) 129 return (status); 130 } 131 132 /* 133 * if context_handle is GSS_C_NO_CONTEXT, allocate a union context 134 * descriptor to hold the mech type information as well as the 135 * underlying mechanism context handle. Otherwise, cast the 136 * value of *context_handle to the union context variable. 137 */ 138 if (*context_handle == GSS_C_NO_CONTEXT) { 139 status = GSS_S_FAILURE; 140 union_ctx_id = (gss_union_ctx_id_t) 141 malloc(sizeof (gss_union_ctx_id_desc)); 142 if (union_ctx_id == NULL) 143 goto end; 144 145 if (generic_gss_copy_oid(&temp_minor_status, mech_type, 146 &union_ctx_id->mech_type) != GSS_S_COMPLETE) { 147 free(union_ctx_id); 148 goto end; 149 } 150 151 /* copy the supplied context handle */ 152 union_ctx_id->internal_ctx_id = *context_handle; 153 } else 154 union_ctx_id = (gss_union_ctx_id_t)*context_handle; 155 156 /* 157 * get the appropriate cred handle from the union cred struct. 158 * defaults to GSS_C_NO_CREDENTIAL if there is no cred, which will 159 * use the default credential. 160 */ 161 union_cred = (gss_union_cred_t)claimant_cred_handle; 162 input_cred_handle = __gss_get_mechanism_cred(union_cred, mech_type); 163 164 /* 165 * now call the approprate underlying mechanism routine 166 */ 167 168 status = mech->gss_init_sec_context( 169 mech->context, 170 minor_status, 171 input_cred_handle, 172 &union_ctx_id->internal_ctx_id, 173 internal_name, 174 mech_type, 175 req_flags, 176 time_req, 177 input_chan_bindings, 178 input_token, 179 actual_mech_type, 180 output_token, 181 ret_flags, 182 time_rec); 183 184 if (status != GSS_S_COMPLETE && status != GSS_S_CONTINUE_NEEDED) { 185 /* 186 * the spec says (the preferred) method is to delete all 187 * context info on the first call to init, and on all 188 * subsequent calls make the caller responsible for 189 * calling gss_delete_sec_context 190 */ 191 if (*context_handle == GSS_C_NO_CONTEXT) { 192 free(union_ctx_id->mech_type->elements); 193 free(union_ctx_id->mech_type); 194 free(union_ctx_id); 195 } 196 } else if (*context_handle == GSS_C_NO_CONTEXT) 197 *context_handle = (gss_ctx_id_t)union_ctx_id; 198 199 end: 200 if (union_name->mech_name == NULL || 201 union_name->mech_name != internal_name) { 202 (void) __gss_release_internal_name(&temp_minor_status, 203 mech_type, &internal_name); 204 } 205 206 return (status); 207 } 208