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