Home | History | Annotate | Line # | Download | only in krb5
      1 /*	$NetBSD: set_cred_option.c,v 1.2 2017/01/28 21:31:46 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2004, PADL Software Pty Ltd.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  *
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  *
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  *
     18  * 3. Neither the name of PADL Software nor the names of its contributors
     19  *    may be used to endorse or promote products derived from this software
     20  *    without specific prior written permission.
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
     23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25  * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
     26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32  * SUCH DAMAGE.
     33  */
     34 
     35 #include "gsskrb5_locl.h"
     36 
     37 static OM_uint32
     38 import_cred(OM_uint32 *minor_status,
     39 	    krb5_context context,
     40             gss_cred_id_t *cred_handle,
     41             const gss_buffer_t value)
     42 {
     43     OM_uint32 major_stat;
     44     krb5_error_code ret;
     45     krb5_principal keytab_principal = NULL;
     46     krb5_keytab keytab = NULL;
     47     krb5_storage *sp = NULL;
     48     krb5_ccache id = NULL;
     49     char *str;
     50 
     51     if (cred_handle == NULL || *cred_handle != GSS_C_NO_CREDENTIAL) {
     52 	*minor_status = 0;
     53 	return GSS_S_FAILURE;
     54     }
     55 
     56     sp = krb5_storage_from_mem(value->value, value->length);
     57     if (sp == NULL) {
     58 	*minor_status = 0;
     59 	return GSS_S_FAILURE;
     60     }
     61 
     62     /* credential cache name */
     63     ret = krb5_ret_string(sp, &str);
     64     if (ret) {
     65 	*minor_status = ret;
     66 	major_stat =  GSS_S_FAILURE;
     67 	goto out;
     68     }
     69     if (str[0]) {
     70 	ret = krb5_cc_resolve(context, str, &id);
     71 	if (ret) {
     72 	    *minor_status = ret;
     73 	    major_stat =  GSS_S_FAILURE;
     74 	    goto out;
     75 	}
     76     }
     77     free(str);
     78     str = NULL;
     79 
     80     /* keytab principal name */
     81     ret = krb5_ret_string(sp, &str);
     82     if (ret == 0 && str[0])
     83 	ret = krb5_parse_name(context, str, &keytab_principal);
     84     if (ret) {
     85 	*minor_status = ret;
     86 	major_stat = GSS_S_FAILURE;
     87 	goto out;
     88     }
     89     free(str);
     90     str = NULL;
     91 
     92     /* keytab principal */
     93     ret = krb5_ret_string(sp, &str);
     94     if (ret) {
     95 	*minor_status = ret;
     96 	major_stat =  GSS_S_FAILURE;
     97 	goto out;
     98     }
     99     if (str[0]) {
    100 	ret = krb5_kt_resolve(context, str, &keytab);
    101 	if (ret) {
    102 	    *minor_status = ret;
    103 	    major_stat =  GSS_S_FAILURE;
    104 	    goto out;
    105 	}
    106     }
    107     free(str);
    108     str = NULL;
    109 
    110     major_stat = _gsskrb5_krb5_import_cred(minor_status, id, keytab_principal,
    111 					   keytab, cred_handle);
    112 out:
    113     if (id)
    114 	krb5_cc_close(context, id);
    115     if (keytab_principal)
    116 	krb5_free_principal(context, keytab_principal);
    117     if (keytab)
    118 	krb5_kt_close(context, keytab);
    119     if (str)
    120 	free(str);
    121     if (sp)
    122 	krb5_storage_free(sp);
    123 
    124     return major_stat;
    125 }
    126 
    127 
    128 static OM_uint32
    129 allowed_enctypes(OM_uint32 *minor_status,
    130 		 krb5_context context,
    131 		 gss_cred_id_t *cred_handle,
    132 		 const gss_buffer_t value)
    133 {
    134     OM_uint32 major_stat;
    135     krb5_error_code ret;
    136     size_t len, i;
    137     krb5_enctype *enctypes = NULL;
    138     krb5_storage *sp = NULL;
    139     gsskrb5_cred cred;
    140 
    141     if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) {
    142 	*minor_status = 0;
    143 	return GSS_S_FAILURE;
    144     }
    145 
    146     cred = (gsskrb5_cred)*cred_handle;
    147 
    148     if ((value->length % 4) != 0) {
    149 	*minor_status = 0;
    150 	major_stat = GSS_S_FAILURE;
    151 	goto out;
    152     }
    153 
    154     len = value->length / 4;
    155     enctypes = malloc((len + 1) * 4);
    156     if (enctypes == NULL) {
    157 	*minor_status = ENOMEM;
    158 	major_stat = GSS_S_FAILURE;
    159 	goto out;
    160     }
    161 
    162     sp = krb5_storage_from_mem(value->value, value->length);
    163     if (sp == NULL) {
    164 	*minor_status = ENOMEM;
    165 	major_stat = GSS_S_FAILURE;
    166 	goto out;
    167     }
    168 
    169     for (i = 0; i < len; i++) {
    170 	uint32_t e;
    171 
    172 	ret = krb5_ret_uint32(sp, &e);
    173 	if (ret) {
    174 	    *minor_status = ret;
    175 	    major_stat =  GSS_S_FAILURE;
    176 	    goto out;
    177 	}
    178 	enctypes[i] = e;
    179     }
    180     enctypes[i] = 0;
    181 
    182     if (cred->enctypes)
    183 	free(cred->enctypes);
    184     cred->enctypes = enctypes;
    185 
    186     krb5_storage_free(sp);
    187 
    188     return GSS_S_COMPLETE;
    189 
    190 out:
    191     if (sp)
    192 	krb5_storage_free(sp);
    193     if (enctypes)
    194 	free(enctypes);
    195 
    196     return major_stat;
    197 }
    198 
    199 static OM_uint32
    200 no_ci_flags(OM_uint32 *minor_status,
    201 	    krb5_context context,
    202 	    gss_cred_id_t *cred_handle,
    203 	    const gss_buffer_t value)
    204 {
    205     gsskrb5_cred cred;
    206 
    207     if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) {
    208 	*minor_status = 0;
    209 	return GSS_S_FAILURE;
    210     }
    211 
    212     cred = (gsskrb5_cred)*cred_handle;
    213     cred->cred_flags |= GSS_CF_NO_CI_FLAGS;
    214 
    215     *minor_status = 0;
    216     return GSS_S_COMPLETE;
    217 
    218 }
    219 
    220 
    221 OM_uint32 GSSAPI_CALLCONV
    222 _gsskrb5_set_cred_option
    223            (OM_uint32 *minor_status,
    224             gss_cred_id_t *cred_handle,
    225             const gss_OID desired_object,
    226             const gss_buffer_t value)
    227 {
    228     krb5_context context;
    229 
    230     GSSAPI_KRB5_INIT (&context);
    231 
    232     if (value == GSS_C_NO_BUFFER) {
    233 	*minor_status = EINVAL;
    234 	return GSS_S_FAILURE;
    235     }
    236 
    237     if (gss_oid_equal(desired_object, GSS_KRB5_IMPORT_CRED_X))
    238 	return import_cred(minor_status, context, cred_handle, value);
    239 
    240     if (gss_oid_equal(desired_object, GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X))
    241 	return allowed_enctypes(minor_status, context, cred_handle, value);
    242 
    243     if (gss_oid_equal(desired_object, GSS_KRB5_CRED_NO_CI_FLAGS_X)) {
    244 	return no_ci_flags(minor_status, context, cred_handle, value);
    245     }
    246 
    247 
    248     *minor_status = EINVAL;
    249     return GSS_S_FAILURE;
    250 }
    251