1   /*
   2    * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
   3    * Use is subject to license terms.
   4    */
   5   
   6 | #pragma ident        "@(#)g_inquire_cred.c        1.17        04/09/08 SMI"
   6 | #pragma ident        "@(#)g_inquire_cred.c        1.16        04/02/23 SMI"
   7   
   8   /*
   9    *  glue routine for gss_inquire_cred
  10    */
  11   
  12   #include <mechglueP.h>
  13   #include <stdio.h>
  14   #include <stdlib.h>
  15   #include <string.h>
  16   #include <time.h>
  17   
  18   OM_uint32
  19   gss_inquire_cred(minor_status,
  20                           cred_handle,
  21                           name,
  22                           lifetime,
  23                           cred_usage,
  24                           mechanisms)
  25   
  26   OM_uint32 *minor_status;
  27   const gss_cred_id_t                cred_handle;
  28   gss_name_t *name;
  29   OM_uint32 *lifetime;
  30   int *cred_usage;
  31   gss_OID_set *mechanisms;
  32   
  33   {
  34           OM_uint32                status, elapsed_time, temp_minor_status;
  35           gss_union_cred_t        union_cred;
  36           gss_mechanism                mech;
  37           gss_name_t                internal_name;
  38           int                        i;
  39   
  40 |         gss_initialize();
  40 |         /* check parms and set to defaults */
  41 +         if (minor_status == NULL)
  42 +                 return (GSS_S_CALL_INACCESSIBLE_WRITE);
  43 +         *minor_status = 0;
  44   
  45 +         if (name)
  46 +                 *name = NULL;
  47 + 
  48 +         if (mechanisms)
  49 +                 *mechanisms = NULL;
  50 + 
  51           if (cred_handle == GSS_C_NO_CREDENTIAL) {
  52           /*
  53            * No credential was supplied. This means we can't get a mechanism
  54            * pointer to call the mechanism specific gss_inquire_cred.
  55            * So, call get_mechanism with an arguement of GSS_C_NULL_OID.
  56            * get_mechanism will return the first mechanism in the mech
  57            * array, which becomes the default mechanism.
  58            */
  59   
  60                   if ((mech = __gss_get_mechanism(GSS_C_NULL_OID)) == NULL)
  52 |                         return (GSS_S_NO_CRED);
  61 |                         return (GSS_S_DEFECTIVE_CREDENTIAL);
  62   
  63                   if (!mech->gss_inquire_cred)
  55 |                         return (GSS_S_FAILURE);
  64 |                         return (GSS_S_UNAVAILABLE);
  65   
  66                   status = mech->gss_inquire_cred(mech->context, minor_status,
  67                                                   GSS_C_NO_CREDENTIAL,
  68                                                   name ? &internal_name : NULL,
  69                                                   lifetime, cred_usage,
  70                                                   mechanisms);
  71   
  72                   if (status != GSS_S_COMPLETE)
  73                           return (status);
  74   
  75                   if (name) {
  76                   /*
  77                    * Convert internal_name into a union_name equivalent.
  78                    */
  79                           status = __gss_convert_name_to_union_name(
  80                                                   &temp_minor_status, mech,
  81                                                   internal_name, name);
  74 -                                 if (minor_status) {
  82                           if (status != GSS_S_COMPLETE) {
  83                                   *minor_status = temp_minor_status;
  76 |                                         __gss_release_internal_name(
  84 |                                 if (mechanisms && *mechanisms) {
  85 +                                         (void) gss_release_oid_set(
  86                                                   &temp_minor_status,
  78 |                                                         &mech->mech_type,
  87 |                                                         mechanisms);
  79 -                                                         &internal_name);
  88                                   }
  89                                   return (status);
  90                           }
  91                   }
  92                   return (GSS_S_COMPLETE);
  93           }
  94   
  95           /* get the cred_handle cast as a union_credentials structure */
  96   
  97           union_cred = (gss_union_cred_t)cred_handle;
  98   
  99           /*
 100            * get the information out of the union_cred structure that was
 101            * placed there during gss_acquire_cred.
 102            */
 103   
 104           if (cred_usage != NULL)
 105                   *cred_usage = union_cred->auxinfo.cred_usage;
 106   
 107           if (lifetime != NULL) {
 108                   elapsed_time = time(0) - union_cred->auxinfo.creation_time;
 109                   *lifetime = union_cred->auxinfo.time_rec < elapsed_time ? 0 :
 110                   union_cred->auxinfo.time_rec - elapsed_time;
 111           }
 112   
 113           /*
 114            * if name is non_null,
 115            * call gss_import_name() followed by gss_canonicalize_name()
 116            * to get a mechanism specific name passed back to the caller.
 117            * If this call fails, return failure to our caller.
 118            * XXX The cred_handle may contain an array of mechanism OID's
 119            * but we only return the MN for the first mechanism to the caller.
 120            * In theory, we should modify this to provide an array of MN's
 121            * one per mechanism back to the caller.
 122            */
 123   
 124           if (name != NULL) {
 125                   if ((gss_import_name(minor_status,
 126                                           &union_cred->auxinfo.name,
 127                                           union_cred->auxinfo.name_type,
 120 |                                         name) != GSS_S_COMPLETE)
 121 |                         return (GSS_S_DEFECTIVE_CREDENTIAL);
 128 |                                         name) != GSS_S_COMPLETE) ||
 129 |                         (gss_canonicalize_name(minor_status, *name,
 130 +                                         &union_cred->mechs_array[0],
 131 +                                         NULL) != GSS_S_COMPLETE)) {
 132 +                         status = GSS_S_DEFECTIVE_CREDENTIAL;
 133 +                         goto error;
 134                   }
 135 +         }
 136   
 137           /*
 138            * copy the mechanism set in union_cred into an OID set and return in
 139            * the mechanisms parameter.
 140            */
 141           if (mechanisms != NULL) {
 129 | 
 142 |                 status = GSS_S_FAILURE;
 143                   *mechanisms = (gss_OID_set) malloc(sizeof (gss_OID_set_desc));
 144 +                 if (*mechanisms == NULL)
 145 +                         goto error;
 146   
 132 |                 (*mechanisms)->count = union_cred->count;
 147 |                 (*mechanisms)->count = 0;
 148                   (*mechanisms)->elements =
 149                           (gss_OID) malloc(sizeof (gss_OID_desc) *
 150                                                   union_cred->count);
 151   
 152 +                 if ((*mechanisms)->elements == NULL) {
 153 +                         free(*mechanisms);
 154 +                         *mechanisms = NULL;
 155 +                         goto error;
 156 +                 }
 157 + 
 138 -                         (*mechanisms)->elements[i].length =
 139 -                             union_cred->mechs_array[i].length;
 158                   for (i = 0; i < union_cred->count; i++) {
 159                           (*mechanisms)->elements[i].elements = (void *)
 160                                   malloc(union_cred->mechs_array[i].length);
 142 |                         memcpy((*mechanisms)->elements[i].elements,
 143 |                                 union_cred->mechs_array[i].elements,
 144 |                                 union_cred->mechs_array[i].length);        
 161 |                         if ((*mechanisms)->elements[i].elements == NULL)
 162 |                                 goto error;
 163 |                         g_OID_copy(&(*mechanisms)->elements[i],
 164 +                                         &union_cred->mechs_array[i]);
 165 +                         (*mechanisms)->count++;
 166                   }
 167           }
 168   
 169           return (GSS_S_COMPLETE);
 170 + 
 171 + error:
 172 +         /*
 173 +          * cleanup any allocated memory - we can just call
 174 +          * gss_release_oid_set, because the set is constructed so that
 175 +          * count always references the currently copied number of
 176 +          * elements.
 177 +          */
 178 +         if (mechanisms && *mechanisms != NULL)
 179 +                 (void) gss_release_oid_set(&temp_minor_status, mechanisms);
 180 + 
 181 +         if (name && *name != NULL)
 182 +                 (void) gss_release_name(&temp_minor_status, name);
 183 + 
 184 +         return (status);
 185   }
 186   
 187   OM_uint32
 188   gss_inquire_cred_by_mech(minor_status, cred_handle, mech_type, name,
 189                           initiator_lifetime, acceptor_lifetime, cred_usage)
 190           OM_uint32                *minor_status;
 191           const gss_cred_id_t        cred_handle;
 192           const gss_OID                mech_type;
 193           gss_name_t                *name;
 194           OM_uint32                *initiator_lifetime;
 195           OM_uint32                *acceptor_lifetime;
 196           gss_cred_usage_t        *cred_usage;
 197   {
 198           gss_union_cred_t        union_cred;
 199           gss_cred_id_t                mech_cred;
 200           gss_mechanism                mech;
 201 +         OM_uint32                status, temp_minor_status;
 202 +         gss_name_t                internal_name;
 203   
 204 + 
 205           mech = __gss_get_mechanism(mech_type);
 206           if (!mech)
 207                   return (GSS_S_BAD_MECH);
 208           if (!mech->gss_inquire_cred_by_mech)
 209                   return (GSS_S_UNAVAILABLE);
 210   
 211           union_cred = (gss_union_cred_t)cred_handle;
 212           mech_cred = __gss_get_mechanism_cred(union_cred, mech_type);
 213 +         if (mech_cred == NULL)
 214 +                 return (GSS_S_DEFECTIVE_CREDENTIAL);
 215   
 175 |         return (mech->gss_inquire_cred_by_mech(mech->context, minor_status,
 216 |         status = mech->gss_inquire_cred_by_mech(mech->context, minor_status,
 217                                                   mech_cred, mech_type,
 177 |                                                 name, initiator_lifetime,
 218 |                                                 name ? &internal_name : NULL,
 219 +                                                 initiator_lifetime,
 220                                                   acceptor_lifetime, cred_usage);
 221 + 
 222 +         if (status != GSS_S_COMPLETE)
 223 +                 return (status);
 224 + 
 225 +         if (name) {
 226 +                 /*
 227 +                  * Convert internal_name into a union_name equivalent.
 228 +                  */
 229 +                 status = __gss_convert_name_to_union_name(
 230 +                                                 &temp_minor_status, mech,
 231 +                                                 internal_name, name);
 232 +                 if (status != GSS_S_COMPLETE) {
 233 +                         *minor_status = temp_minor_status;
 234 +                         return (status);
 235 +                 }
 236 +         }
 237 + 
 238 +         return (GSS_S_COMPLETE);
 239   }

 ----Unchanged portion omitted----