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