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----