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