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