1 /* 2 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 | #pragma ident "@(#)g_init_sec_context.c 1.21 04/09/08 SMI" 6 | #pragma ident "@(#)g_init_sec_context.c 1.20 03/10/24 SMI" 7 8 /* 9 * glue routine for gss_init_sec_context 10 */ 11 #include <mechglueP.h> 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 16 OM_uint32 17 gss_init_sec_context(minor_status, 18 claimant_cred_handle, 19 context_handle, 20 target_name, 21 req_mech_type, 22 req_flags, 23 time_req, 24 input_chan_bindings, 25 input_token, 26 actual_mech_type, 27 output_token, 28 ret_flags, 29 time_rec) 30 31 OM_uint32 * minor_status; 32 const gss_cred_id_t claimant_cred_handle; 33 gss_ctx_id_t *context_handle; 34 const gss_name_t target_name; 35 const gss_OID req_mech_type; 36 OM_uint32 req_flags; 37 OM_uint32 time_req; 38 const gss_channel_bindings_t input_chan_bindings; 39 const gss_buffer_t input_token; 40 gss_OID * actual_mech_type; 41 gss_buffer_t output_token; 42 OM_uint32 * ret_flags; 43 OM_uint32 * time_rec; 44 45 { 46 | OM_uint32 status, temp_status, temp_minor_status; 46 | OM_uint32 status, temp_minor_status; 47 gss_union_name_t union_name; 48 gss_union_cred_t union_cred; 49 gss_name_t internal_name; 50 gss_union_ctx_id_t union_ctx_id; 51 gss_OID mech_type = GSS_C_NULL_OID; 52 gss_mechanism mech; 53 gss_cred_id_t input_cred_handle; 54 55 | gss_initialize(); 55 | if (minor_status == NULL) 56 + return (GSS_S_CALL_INACCESSIBLE_WRITE); 57 + *minor_status = 0; 58 59 + /* clear output values */ 60 + if (actual_mech_type) 61 + *actual_mech_type = NULL; 62 + 63 if (context_handle == NULL) 58 | return (GSS_S_NO_CONTEXT); 64 | return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CONTEXT); 65 60 | /* 61 | * If mech_type is NULL, and the target_name is 66 | if (target_name == NULL) 67 | return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME); 62 - * mechanism-specific, then set it to the mech_type of 63 - * target_name. 64 - */ 65 - if ((mech_type == GSS_C_NULL_OID) && union_name->mech_type) 66 - mech_type = union_name->mech_type; 68 69 + if (output_token == NULL) 70 + return (GSS_S_CALL_INACCESSIBLE_WRITE); 71 + 72 + output_token->value = NULL; 73 + output_token->length = 0; 74 + 75 + 76 + if (req_mech_type) 77 + mech_type = (gss_OID)req_mech_type; 78 + 79 + union_name = (gss_union_name_t)target_name; 80 + 81 /* 82 * obtain the gss mechanism information for the requested 83 * mechanism. If mech_type is NULL, set it to the resultant 84 * mechanism 85 */ 86 mech = __gss_get_mechanism(mech_type); 87 if (mech == NULL) 88 return (GSS_S_BAD_MECH); 89 90 + if (mech->gss_init_sec_context == NULL) 91 + return (GSS_S_UNAVAILABLE); 92 + 93 if (mech_type == GSS_C_NULL_OID) 94 mech_type = &mech->mech_type; 95 96 /* 97 * If target_name is mechanism_specific, then it must match the 98 * mech_type that we're about to use. Otherwise, do an import on 99 * the external_name form of the target name. 100 */ 85 | if (union_name->mech_type) { 86 | if (!g_OID_equal(union_name->mech_type, mech_type)) 101 | if (union_name->mech_type && 102 | g_OID_equal(union_name->mech_type, mech_type)) { 87 - return (GSS_S_BAD_MECH); 103 internal_name = union_name->mech_name; 104 } else { 90 | if ((temp_status = __gss_import_internal_name(minor_status, 105 | if ((status = __gss_import_internal_name(minor_status, 106 mech_type, union_name, 92 | &internal_name))) 93 | return (GSS_S_BAD_NAME); 107 | &internal_name)) != GSS_S_COMPLETE) 108 | return (status); 109 } 110 111 /* 112 * if context_handle is GSS_C_NO_CONTEXT, allocate a union context 113 * descriptor to hold the mech type information as well as the 114 * underlying mechanism context handle. Otherwise, cast the 115 * value of *context_handle to the union context variable. 116 */ 117 if (*context_handle == GSS_C_NO_CONTEXT) { 118 + status = GSS_S_FAILURE; 119 union_ctx_id = (gss_union_ctx_id_t) 120 malloc(sizeof (gss_union_ctx_id_desc)); 121 + if (union_ctx_id == NULL) 122 + goto end; 123 106 | /* copy the mech type information */ 124 | if (generic_gss_copy_oid(&temp_minor_status, mech_type, 125 + &union_ctx_id->mech_type) != GSS_S_COMPLETE) { 126 + free(union_ctx_id); 127 + goto end; 128 + } 108 - union_ctx_id->mech_type->elements = (void *) 109 - malloc(mech_type->length); 110 - 111 - union_ctx_id->mech_type->length = mech_type->length; 112 - memcpy(union_ctx_id->mech_type->elements, mech_type->elements, 113 - mech_type->length); 114 - 129 116 - 130 /* copy the supplied context handle */ 131 union_ctx_id->internal_ctx_id = *context_handle; 132 } else 133 union_ctx_id = (gss_union_ctx_id_t)*context_handle; 134 135 /* 136 * get the appropriate cred handle from the union cred struct. 137 * defaults to GSS_C_NO_CREDENTIAL if there is no cred, which will 138 * use the default credential. 139 */ 140 union_cred = (gss_union_cred_t)claimant_cred_handle; 141 input_cred_handle = __gss_get_mechanism_cred(union_cred, mech_type); 142 143 /* 144 * now call the approprate underlying mechanism routine 145 */ 133 - if (mech->gss_init_sec_context) { 146 147 status = mech->gss_init_sec_context( 148 mech->context, 149 minor_status, 150 input_cred_handle, 151 &union_ctx_id->internal_ctx_id, 152 internal_name, 153 mech_type, 154 req_flags, 155 time_req, 156 input_chan_bindings, 157 input_token, 158 actual_mech_type, 159 output_token, 160 ret_flags, 161 time_rec); 162 150 | if (*context_handle == GSS_C_NO_CONTEXT) 163 | if (status != GSS_S_COMPLETE && status != GSS_S_CONTINUE_NEEDED) { 164 + /* 165 + * the spec says (the preferred) method is to delete all 166 + * context info on the first call to init, and on all 167 + * subsequent calls make the caller responsible for 168 + * calling gss_delete_sec_context 169 + */ 170 + if (*context_handle == GSS_C_NO_CONTEXT) { 171 + free(union_ctx_id->mech_type->elements); 172 + free(union_ctx_id->mech_type); 173 + free(union_ctx_id); 174 + } 175 + } else if (*context_handle == GSS_C_NO_CONTEXT) 152 - } else 153 - status = GSS_S_BAD_BINDINGS; 176 *context_handle = (gss_ctx_id_t)union_ctx_id; 177 155 | if (!union_name->mech_type) { 178 | end: 179 + if (union_name->mech_name == NULL || 180 + union_name->mech_name != internal_name) { 181 (void) __gss_release_internal_name(&temp_minor_status, 182 mech_type, &internal_name); 183 } 184 185 return (status); 186 } ----Unchanged portion omitted----