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 37static OM_uint32 38import_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); 112out: 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 128static OM_uint32 129allowed_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 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 220 221OM_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