1 /* 2 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 | #pragma ident "@(#)g_accept_sec_context.c 1.20 04/09/08 SMI" 6 | #pragma ident "@(#)g_accept_sec_context.c 1.19 04/02/23 SMI" 7 8 /* 9 * glue routine for gss_accept_sec_context 10 */ 11 12 #include <mechglueP.h> 13 #ifdef HAVE_STDLIB_H 14 #include <stdlib.h> 15 #endif 16 #include <string.h> 17 #include <errno.h> 18 19 OM_uint32 20 gss_accept_sec_context(minor_status, 21 context_handle, 22 verifier_cred_handle, 23 input_token_buffer, 24 input_chan_bindings, 25 src_name, 26 mech_type, 27 output_token, 28 ret_flags, 29 time_rec, 30 d_cred) 31 32 OM_uint32 *minor_status; 33 gss_ctx_id_t *context_handle; 34 const gss_cred_id_t verifier_cred_handle; 35 const gss_buffer_t input_token_buffer; 36 const gss_channel_bindings_t input_chan_bindings; 37 gss_name_t *src_name; 38 gss_OID *mech_type; 39 gss_buffer_t output_token; 40 OM_uint32 *ret_flags; 41 OM_uint32 *time_rec; 42 gss_cred_id_t *d_cred; /* delegated cred handle */ 43 44 { 45 OM_uint32 status, temp_status, temp_minor_status; 46 gss_union_ctx_id_t union_ctx_id; 47 gss_union_cred_t union_cred; 48 gss_cred_id_t input_cred_handle = GSS_C_NO_CREDENTIAL; 49 | gss_name_t internal_name; 50 | gss_name_t tmp_src_name; 49 | gss_cred_id_t tmp_d_cred = GSS_C_NO_CREDENTIAL; 50 | gss_name_t internal_name = GSS_C_NO_NAME; 51 + gss_name_t tmp_src_name = GSS_C_NO_NAME; 52 gss_OID_desc token_mech_type_desc; 53 gss_OID token_mech_type = &token_mech_type_desc; 54 gss_mechanism mech; 55 55 | gss_initialize(); 56 | /* check parameters first */ 57 + if (minor_status == NULL) 58 + return (GSS_S_CALL_INACCESSIBLE_WRITE); 59 + *minor_status = 0; 60 57 | if (context_handle == NULL) 58 | return (GSS_S_NO_CONTEXT); 61 | if (context_handle == NULL || output_token == NULL) 62 | return (GSS_S_CALL_INACCESSIBLE_WRITE); 63 64 + /* clear optional fields */ 65 + output_token->value = NULL; 66 + output_token->length = 0; 67 + if (src_name) 68 + *src_name = NULL; 69 + 70 + if (mech_type) 71 + *mech_type = NULL; 72 + 73 + if (d_cred) 74 + *d_cred = NULL; 75 /* 76 * if context_handle is GSS_C_NO_CONTEXT, allocate a union context 77 * descriptor to hold the mech type information as well as the 78 * underlying mechanism context handle. Otherwise, cast the 79 * value of *context_handle to the union context variable. 80 */ 81 82 if (*context_handle == GSS_C_NO_CONTEXT) { 83 84 + if (GSS_EMPTY_BUFFER(input_token_buffer)) 85 + return (GSS_S_CALL_INACCESSIBLE_READ); 86 + 87 /* Get the token mech type */ 88 status = __gss_get_mech_type(token_mech_type, 89 input_token_buffer); 90 91 if (status) 92 return (status); 93 94 status = GSS_S_FAILURE; 95 union_ctx_id = (gss_union_ctx_id_t) 96 malloc(sizeof (gss_union_ctx_id_desc)); 79 | if (!union_ctx_id) { 80 | *minor_status = ENOMEM; 97 | if (!union_ctx_id) 98 | return (GSS_S_FAILURE); 81 - goto error_out; 82 - } 83 - union_ctx_id->mech_type = (gss_OID) malloc(sizeof(gss_OID_desc)); 84 - if (!union_ctx_id->mech_type) { 85 - *minor_status = ENOMEM; 86 - goto error_out; 87 - } 99 89 | union_ctx_id->mech_type->elements = (void *) 90 | malloc(token_mech_type->length); 91 | if (!union_ctx_id->mech_type->elements) { 92 | *minor_status = ENOMEM; 93 | goto error_out; 100 | union_ctx_id->internal_ctx_id = GSS_C_NO_CONTEXT; 101 | status = generic_gss_copy_oid(&temp_minor_status, 102 | token_mech_type, 103 | &union_ctx_id->mech_type); 104 | if (status != GSS_S_COMPLETE) { 105 + free(union_ctx_id); 106 + return (status); 107 } 108 96 | union_ctx_id->mech_type->length = token_mech_type->length; 97 | memcpy(union_ctx_id->mech_type->elements, 109 | /* set the new context handle to caller's data */ 110 | *context_handle = (gss_ctx_id_t)union_ctx_id; 98 - token_mech_type->elements, 99 - token_mech_type->length); 100 - 101 - /* copy the supplied context handle */ 102 - 103 - union_ctx_id->internal_ctx_id = *context_handle; 111 } else { 105 | union_ctx_id = *context_handle; 112 | union_ctx_id = (gss_union_ctx_id_t)*context_handle; 113 token_mech_type = union_ctx_id->mech_type; 114 } 115 116 /* 117 * get the appropriate cred handle from the union cred struct. 118 * defaults to GSS_C_NO_CREDENTIAL if there is no cred, which will 119 * use the default credential. 120 */ 121 union_cred = (gss_union_cred_t)verifier_cred_handle; 122 input_cred_handle = __gss_get_mechanism_cred(union_cred, 123 token_mech_type); 124 125 /* 126 * now select the approprate underlying mechanism routine and 127 * call it. 128 */ 129 130 mech = __gss_get_mechanism(token_mech_type); 131 if (mech && mech->gss_accept_sec_context) { 132 status = mech->gss_accept_sec_context( 133 mech->context, 134 minor_status, 135 &union_ctx_id->internal_ctx_id, 136 input_cred_handle, 137 input_token_buffer, 138 input_chan_bindings, 139 &internal_name, 140 mech_type, 141 output_token, 142 ret_flags, 143 time_rec, 137 | delegated_cred_handle); 144 | d_cred ? &tmp_d_cred : NULL); 145 146 /* If there's more work to do, keep going... */ 147 if (status == GSS_S_CONTINUE_NEEDED) 148 return (GSS_S_CONTINUE_NEEDED); 149 150 /* if the call failed, return with failure */ 151 if (status != GSS_S_COMPLETE) 152 goto error_out; 153 154 /* 155 * if src_name is non-NULL, 156 * convert internal_name into a union name equivalent 157 * First call the mechanism specific display_name() 158 * then call gss_import_name() to create 159 * the union name struct cast to src_name 160 */ 154 | if (src_name != NULL && status == GSS_S_COMPLETE) { 161 | if (internal_name != NULL) { 162 temp_status = __gss_convert_name_to_union_name( 163 &temp_minor_status, mech, 157 | internal_name, src_name); 164 | internal_name, &tmp_src_name); 159 - if (minor_status) 165 if (temp_status != GSS_S_COMPLETE) { 166 *minor_status = temp_minor_status; 167 + if (output_token->length) 168 (void) gss_release_buffer( 169 &temp_minor_status, 170 output_token); 164 | __gss_release_internal_name(&temp_minor_status, 165 | &mech->mech_type, &internal_name); 171 | if (internal_name != GSS_C_NO_NAME) 172 | mech->gss_release_name( 173 + mech->context, 174 + &temp_minor_status, 175 + &internal_name); 176 return (temp_status); 177 } 178 + if (src_name != NULL) { 179 + *src_name = tmp_src_name; 180 } 181 + } else if (src_name != NULL) { 182 + *src_name = GSS_C_NO_NAME; 183 + } 184 170 | if(*context_handle == GSS_C_NO_CONTEXT) 171 | *context_handle = (gss_ctx_id_t *) union_ctx_id; 185 | /* Ensure we're returning correct creds format */ 186 | if ((ret_flags && GSS_C_DELEG_FLAG) && 187 + tmp_d_cred != GSS_C_NO_CREDENTIAL) { 188 + gss_union_cred_t d_u_cred = NULL; 189 173 | return(status); 190 | d_u_cred = malloc(sizeof (gss_union_cred_desc)); 191 + if (d_u_cred == NULL) { 192 + status = GSS_S_FAILURE; 193 + goto error_out; 194 } 195 + (void) memset(d_u_cred, 0, 196 + sizeof (gss_union_cred_desc)); 197 176 | return(GSS_S_BAD_MECH); 198 | d_u_cred->count = 1; 199 200 + status = generic_gss_copy_oid(&temp_minor_status, 201 + token_mech_type, 202 + &d_u_cred->mechs_array); 203 + 204 + if (status != GSS_S_COMPLETE) { 205 + free(d_u_cred); 206 + goto error_out; 207 + } 208 + 209 + d_u_cred->cred_array = malloc(sizeof (gss_cred_id_t)); 210 + if (d_u_cred->cred_array != NULL) { 211 + d_u_cred->cred_array[0] = tmp_d_cred; 212 + } else { 213 + free(d_u_cred); 214 + status = GSS_S_FAILURE; 215 + goto error_out; 216 + } 217 + 218 + if (status != GSS_S_COMPLETE) { 219 + free(d_u_cred->cred_array); 220 + free(d_u_cred); 221 + goto error_out; 222 + } 223 + 224 + internal_name = GSS_C_NO_NAME; 225 + 226 + d_u_cred->auxinfo.creation_time = time(0); 227 + d_u_cred->auxinfo.time_rec = 0; 228 + 229 + if (mech->gss_inquire_cred) { 230 + status = mech->gss_inquire_cred(mech->context, 231 + minor_status, 232 + tmp_d_cred, 233 + &internal_name, 234 + &d_u_cred->auxinfo.time_rec, 235 + &d_u_cred->auxinfo.cred_usage, 236 + NULL); 237 + } 238 + 239 + if (internal_name != NULL) { 240 + temp_status = __gss_convert_name_to_union_name( 241 + &temp_minor_status, mech, 242 + internal_name, &tmp_src_name); 243 + if (temp_status != GSS_S_COMPLETE) { 244 + *minor_status = temp_minor_status; 245 + if (output_token->length) 246 + (void) gss_release_buffer( 247 + &temp_minor_status, 248 + output_token); 249 + free(d_u_cred->cred_array); 250 + free(d_u_cred); 251 + return (temp_status); 252 + } 253 + } 254 + 255 + if (tmp_src_name != NULL) { 256 + status = gss_display_name( 257 + &temp_minor_status, 258 + tmp_src_name, 259 + &d_u_cred->auxinfo.name, 260 + &d_u_cred->auxinfo.name_type); 261 + } 262 + 263 + *d_cred = (gss_cred_id_t)d_u_cred; 264 + } 265 + 266 + if (src_name == NULL && tmp_src_name != NULL) 267 + (void) gss_release_name(&temp_minor_status, 268 + &tmp_src_name); 269 + return (status); 270 + } else { 271 + 272 + status = GSS_S_BAD_MECH; 273 + } 274 + 275 error_out: 276 if (union_ctx_id) { 277 if (union_ctx_id->mech_type) { 278 if (union_ctx_id->mech_type->elements) 279 free(union_ctx_id->mech_type->elements); 280 free(union_ctx_id->mech_type); 281 } 282 free(union_ctx_id); 283 + *context_handle = GSS_C_NO_CONTEXT; 284 } 285 + 286 + if (output_token->length) 287 + (void) gss_release_buffer(&temp_minor_status, output_token); 288 + 289 + if (src_name) 290 + *src_name = GSS_C_NO_NAME; 291 + 292 + if (tmp_src_name != GSS_C_NO_NAME) 293 + (void) gss_release_buffer(&temp_minor_status, 294 + (gss_buffer_t)tmp_src_name); 295 + 296 return (status); 297 } ----Unchanged portion omitted----