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 "gsskrb5_locl.h" 34 35 static OM_uint32 36 import_cred(OM_uint32 *minor_status, 37 krb5_context context, 38 gss_cred_id_t *cred_handle, 39 const gss_buffer_t value) 40 { 41 OM_uint32 major_stat; 42 krb5_error_code ret; 43 krb5_principal keytab_principal = NULL; 44 krb5_keytab keytab = NULL; 45 krb5_storage *sp = NULL; 46 krb5_ccache id = NULL; 47 char *str; 48 49 if (cred_handle == NULL || *cred_handle != GSS_C_NO_CREDENTIAL) { 50 *minor_status = 0; 51 return GSS_S_FAILURE; 52 } 53 54 sp = krb5_storage_from_mem(value->value, value->length); 55 if (sp == NULL) { 56 *minor_status = 0; 57 return GSS_S_FAILURE; 58 } 59 60 /* credential cache name */ 61 ret = krb5_ret_string(sp, &str); 62 if (ret) { 63 *minor_status = ret; 64 major_stat = GSS_S_FAILURE; 65 goto out; 66 } 67 if (str[0]) { 68 ret = krb5_cc_resolve(context, str, &id); 69 if (ret) { 70 *minor_status = ret; 71 major_stat = GSS_S_FAILURE; 72 goto out; 73 } 74 } 75 free(str); 76 str = NULL; 77 78 /* keytab principal name */ 79 ret = krb5_ret_string(sp, &str); 80 if (ret == 0 && str[0]) 81 ret = krb5_parse_name(context, str, &keytab_principal); 82 if (ret) { 83 *minor_status = ret; 84 major_stat = GSS_S_FAILURE; 85 goto out; 86 } 87 free(str); 88 str = NULL; 89 90 /* keytab principal */ 91 ret = krb5_ret_string(sp, &str); 92 if (ret) { 93 *minor_status = ret; 94 major_stat = GSS_S_FAILURE; 95 goto out; 96 } 97 if (str[0]) { 98 ret = krb5_kt_resolve(context, str, &keytab); 99 if (ret) { 100 *minor_status = ret; 101 major_stat = GSS_S_FAILURE; 102 goto out; 103 } 104 } 105 free(str); 106 str = NULL; 107 108 major_stat = _gsskrb5_krb5_import_cred(minor_status, id, keytab_principal, 109 keytab, cred_handle); 110 out: 111 if (id) 112 krb5_cc_close(context, id); 113 if (keytab_principal) 114 krb5_free_principal(context, keytab_principal); 115 if (keytab) 116 krb5_kt_close(context, keytab); 117 if (str) 118 free(str); 119 if (sp) 120 krb5_storage_free(sp); 121 122 return major_stat; 123 } 124 125 126 static OM_uint32 127 allowed_enctypes(OM_uint32 *minor_status, 128 krb5_context context, 129 gss_cred_id_t *cred_handle, 130 const gss_buffer_t value) 131 { 132 OM_uint32 major_stat; 133 krb5_error_code ret; 134 size_t len, i; 135 krb5_enctype *enctypes = NULL; 136 krb5_storage *sp = NULL; 137 gsskrb5_cred cred; 138 139 if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) { 140 *minor_status = 0; 141 return GSS_S_FAILURE; 142 } 143 144 cred = (gsskrb5_cred)*cred_handle; 145 146 if ((value->length % 4) != 0) { 147 *minor_status = 0; 148 major_stat = GSS_S_FAILURE; 149 goto out; 150 } 151 152 len = value->length / 4; 153 enctypes = malloc((len + 1) * 4); 154 if (enctypes == NULL) { 155 *minor_status = ENOMEM; 156 major_stat = GSS_S_FAILURE; 157 goto out; 158 } 159 160 sp = krb5_storage_from_mem(value->value, value->length); 161 if (sp == NULL) { 162 *minor_status = ENOMEM; 163 major_stat = GSS_S_FAILURE; 164 goto out; 165 } 166 167 for (i = 0; i < len; i++) { 168 uint32_t e; 169 170 ret = krb5_ret_uint32(sp, &e); 171 if (ret) { 172 *minor_status = ret; 173 major_stat = GSS_S_FAILURE; 174 goto out; 175 } 176 enctypes[i] = e; 177 } 178 enctypes[i] = 0; 179 180 if (cred->enctypes) 181 free(cred->enctypes); 182 cred->enctypes = enctypes; 183 184 krb5_storage_free(sp); 185 186 return GSS_S_COMPLETE; 187 188 out: 189 if (sp) 190 krb5_storage_free(sp); 191 if (enctypes) 192 free(enctypes); 193 194 return major_stat; 195 } 196 197 static OM_uint32 198 no_ci_flags(OM_uint32 *minor_status, 199 krb5_context context, 200 gss_cred_id_t *cred_handle, 201 const gss_buffer_t value) 202 { 203 gsskrb5_cred cred; 204 205 if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) { 206 *minor_status = 0; 207 return GSS_S_FAILURE; 208 } 209 210 cred = (gsskrb5_cred)*cred_handle; 211 cred->cred_flags |= GSS_CF_NO_CI_FLAGS; 212 213 *minor_status = 0; 214 return GSS_S_COMPLETE; 215 216 } 217 218 219 OM_uint32 GSSAPI_CALLCONV 220 _gsskrb5_set_cred_option 221 (OM_uint32 *minor_status, 222 gss_cred_id_t *cred_handle, 223 const gss_OID desired_object, 224 const gss_buffer_t value) 225 { 226 krb5_context context; 227 228 GSSAPI_KRB5_INIT (&context); 229 230 if (value == GSS_C_NO_BUFFER) { 231 *minor_status = EINVAL; 232 return GSS_S_FAILURE; 233 } 234 235 if (gss_oid_equal(desired_object, GSS_KRB5_IMPORT_CRED_X)) 236 return import_cred(minor_status, context, cred_handle, value); 237 238 if (gss_oid_equal(desired_object, GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X)) 239 return allowed_enctypes(minor_status, context, cred_handle, value); 240 241 if (gss_oid_equal(desired_object, GSS_KRB5_CRED_NO_CI_FLAGS_X)) { 242 return no_ci_flags(minor_status, context, cred_handle, value); 243 } 244 245 246 *minor_status = EINVAL; 247 return GSS_S_FAILURE; 248 } 249