root/source4/heimdal/lib/gssapi/krb5/add_cred.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _gsskrb5_add_cred

   1 /*
   2  * Copyright (c) 2003 Kungliga Tekniska Högskolan
   3  * (Royal Institute of Technology, Stockholm, Sweden).
   4  * All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  *
  10  * 1. Redistributions of source code must retain the above copyright
  11  *    notice, this list of conditions and the following disclaimer.
  12  *
  13  * 2. Redistributions in binary form must reproduce the above copyright
  14  *    notice, this list of conditions and the following disclaimer in the
  15  *    documentation and/or other materials provided with the distribution.
  16  *
  17  * 3. Neither the name of the Institute nor the names of its contributors
  18  *    may be used to endorse or promote products derived from this software
  19  *    without specific prior written permission.
  20  *
  21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
  22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
  25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31  * SUCH DAMAGE.
  32  */
  33 
  34 #include "krb5/gsskrb5_locl.h"
  35 
  36 RCSID("$Id$");
  37 
  38 OM_uint32 _gsskrb5_add_cred (
     /* [<][>][^][v][top][bottom][index][help] */
  39      OM_uint32           *minor_status,
  40      const gss_cred_id_t input_cred_handle,
  41      const gss_name_t    desired_name,
  42      const gss_OID       desired_mech,
  43      gss_cred_usage_t    cred_usage,
  44      OM_uint32           initiator_time_req,
  45      OM_uint32           acceptor_time_req,
  46      gss_cred_id_t       *output_cred_handle,
  47      gss_OID_set         *actual_mechs,
  48      OM_uint32           *initiator_time_rec,
  49      OM_uint32           *acceptor_time_rec)
  50 {
  51     krb5_context context;
  52     OM_uint32 ret, lifetime;
  53     gsskrb5_cred cred, handle;
  54     krb5_const_principal dname;
  55 
  56     handle = NULL;
  57     cred = (gsskrb5_cred)input_cred_handle;
  58     dname = (krb5_const_principal)desired_name;
  59 
  60     GSSAPI_KRB5_INIT (&context);
  61 
  62     if (gss_oid_equal(desired_mech, GSS_KRB5_MECHANISM) == 0) {
  63         *minor_status = 0;
  64         return GSS_S_BAD_MECH;
  65     }
  66 
  67     if (cred == NULL && output_cred_handle == NULL) {
  68         *minor_status = 0;
  69         return GSS_S_NO_CRED;
  70     }
  71 
  72     if (cred == NULL) { /* XXX standard conformance failure */
  73         *minor_status = 0;
  74         return GSS_S_NO_CRED;
  75     }
  76 
  77     /* check if requested output usage is compatible with output usage */
  78     if (output_cred_handle != NULL) {
  79         HEIMDAL_MUTEX_lock(&cred->cred_id_mutex);
  80         if (cred->usage != cred_usage && cred->usage != GSS_C_BOTH) {
  81             HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
  82             *minor_status = GSS_KRB5_S_G_BAD_USAGE;
  83             return(GSS_S_FAILURE);
  84         }
  85     }
  86         
  87     /* check that we have the same name */
  88     if (dname != NULL &&
  89         krb5_principal_compare(context, dname,
  90                                cred->principal) != FALSE) {
  91         if (output_cred_handle)
  92             HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
  93         *minor_status = 0;
  94         return GSS_S_BAD_NAME;
  95     }
  96 
  97     /* make a copy */
  98     if (output_cred_handle) {
  99         krb5_error_code kret;
 100 
 101         handle = calloc(1, sizeof(*handle));
 102         if (handle == NULL) {
 103             HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
 104             *minor_status = ENOMEM;
 105             return (GSS_S_FAILURE);
 106         }
 107 
 108         handle->usage = cred_usage;
 109         handle->lifetime = cred->lifetime;
 110         handle->principal = NULL;
 111         handle->keytab = NULL;
 112         handle->ccache = NULL;
 113         handle->mechanisms = NULL;
 114         HEIMDAL_MUTEX_init(&handle->cred_id_mutex);
 115         
 116         ret = GSS_S_FAILURE;
 117 
 118         kret = krb5_copy_principal(context, cred->principal,
 119                                   &handle->principal);
 120         if (kret) {
 121             HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
 122             free(handle);
 123             *minor_status = kret;
 124             return GSS_S_FAILURE;
 125         }
 126 
 127         if (cred->keytab) {
 128             char name[KRB5_KT_PREFIX_MAX_LEN + MAXPATHLEN];
 129             int len;
 130         
 131             ret = GSS_S_FAILURE;
 132 
 133             kret = krb5_kt_get_type(context, cred->keytab,
 134                                     name, KRB5_KT_PREFIX_MAX_LEN);
 135             if (kret) {
 136                 *minor_status = kret;
 137                 goto failure;
 138             }
 139             len = strlen(name);
 140             name[len++] = ':';
 141 
 142             kret = krb5_kt_get_name(context, cred->keytab,
 143                                     name + len,
 144                                     sizeof(name) - len);
 145             if (kret) {
 146                 *minor_status = kret;
 147                 goto failure;
 148             }
 149 
 150             kret = krb5_kt_resolve(context, name,
 151                                    &handle->keytab);
 152             if (kret){
 153                 *minor_status = kret;
 154                 goto failure;
 155             }
 156         }
 157 
 158         if (cred->ccache) {
 159             const char *type, *name;
 160             char *type_name;
 161 
 162             ret = GSS_S_FAILURE;
 163 
 164             type = krb5_cc_get_type(context, cred->ccache);
 165             if (type == NULL){
 166                 *minor_status = ENOMEM;
 167                 goto failure;
 168             }
 169 
 170             if (strcmp(type, "MEMORY") == 0) {
 171                 ret = krb5_cc_gen_new(context, &krb5_mcc_ops,
 172                                       &handle->ccache);
 173                 if (ret) {
 174                     *minor_status = ret;
 175                     goto failure;
 176                 }
 177 
 178                 ret = krb5_cc_copy_cache(context, cred->ccache,
 179                                          handle->ccache);
 180                 if (ret) {
 181                     *minor_status = ret;
 182                     goto failure;
 183                 }
 184 
 185             } else {
 186                 name = krb5_cc_get_name(context, cred->ccache);
 187                 if (name == NULL) {
 188                     *minor_status = ENOMEM;
 189                     goto failure;
 190                 }
 191                 
 192                 asprintf(&type_name, "%s:%s", type, name);
 193                 if (type_name == NULL) {
 194                     *minor_status = ENOMEM;
 195                     goto failure;
 196                 }
 197                 
 198                 kret = krb5_cc_resolve(context, type_name,
 199                                        &handle->ccache);
 200                 free(type_name);
 201                 if (kret) {
 202                     *minor_status = kret;
 203                     goto failure;
 204                 }       
 205             }
 206         }
 207         ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms);
 208         if (ret)
 209             goto failure;
 210 
 211         ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM,
 212                                      &handle->mechanisms);
 213         if (ret)
 214             goto failure;
 215     }
 216 
 217     HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
 218 
 219     ret = _gsskrb5_inquire_cred(minor_status, (gss_cred_id_t)cred,
 220                                 NULL, &lifetime, NULL, actual_mechs);
 221     if (ret)
 222         goto failure;
 223 
 224     if (initiator_time_rec)
 225         *initiator_time_rec = lifetime;
 226     if (acceptor_time_rec)
 227         *acceptor_time_rec = lifetime;
 228 
 229     if (output_cred_handle) {
 230         *output_cred_handle = (gss_cred_id_t)handle;
 231     }
 232 
 233     *minor_status = 0;
 234     return ret;
 235 
 236  failure:
 237 
 238     if (handle) {
 239         if (handle->principal)
 240             krb5_free_principal(context, handle->principal);
 241         if (handle->keytab)
 242             krb5_kt_close(context, handle->keytab);
 243         if (handle->ccache)
 244             krb5_cc_destroy(context, handle->ccache);
 245         if (handle->mechanisms)
 246             gss_release_oid_set(NULL, &handle->mechanisms);
 247         free(handle);
 248     }
 249     if (output_cred_handle)
 250         HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
 251     return ret;
 252 }

/* [<][>][^][v][top][bottom][index][help] */