1 /* 2 * Copyright (c) 2009 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 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 KTH nor the names of its contributors may be 18 * used to endorse or promote products derived from this software without 19 * specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY 22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE 25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "mech_locl.h" 35 #include <krb5.h> 36 37 /* 38 * format: any number of: 39 * mech-len: int32 40 * mech-data: char * (not alligned) 41 * cred-len: int32 42 * cred-data char * (not alligned) 43 */ 44 45 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL 46 gss_export_cred(OM_uint32 * minor_status, 47 gss_cred_id_t cred_handle, 48 gss_buffer_t token) 49 { 50 struct _gss_cred *cred = (struct _gss_cred *)cred_handle; 51 struct _gss_mechanism_cred *mc; 52 gss_buffer_desc buffer; 53 krb5_error_code ret; 54 krb5_storage *sp; 55 OM_uint32 major; 56 krb5_data data; 57 58 _mg_buffer_zero(token); 59 60 if (cred == NULL) { 61 *minor_status = 0; 62 return GSS_S_NO_CRED; 63 } 64 65 HEIM_SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { 66 if (mc->gmc_mech->gm_export_cred == NULL) { 67 *minor_status = 0; 68 return GSS_S_NO_CRED; 69 } 70 } 71 72 sp = krb5_storage_emem(); 73 if (sp == NULL) { 74 *minor_status = ENOMEM; 75 return GSS_S_FAILURE; 76 } 77 78 HEIM_SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { 79 80 major = mc->gmc_mech->gm_export_cred(minor_status, 81 mc->gmc_cred, &buffer); 82 if (major) { 83 krb5_storage_free(sp); 84 return major; 85 } 86 87 ret = krb5_storage_write(sp, buffer.value, buffer.length); 88 if (ret < 0 || (size_t)ret != buffer.length) { 89 gss_release_buffer(minor_status, &buffer); 90 krb5_storage_free(sp); 91 *minor_status = EINVAL; 92 return GSS_S_FAILURE; 93 } 94 gss_release_buffer(minor_status, &buffer); 95 } 96 97 ret = krb5_storage_to_data(sp, &data); 98 krb5_storage_free(sp); 99 if (ret) { 100 *minor_status = ret; 101 return GSS_S_FAILURE; 102 } 103 104 token->value = data.data; 105 token->length = data.length; 106 107 return GSS_S_COMPLETE; 108 } 109 110 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL 111 gss_import_cred(OM_uint32 * minor_status, 112 gss_buffer_t token, 113 gss_cred_id_t * cred_handle) 114 { 115 gssapi_mech_interface m; 116 krb5_error_code ret; 117 struct _gss_cred *cred; 118 krb5_storage *sp = NULL; 119 OM_uint32 major, junk; 120 krb5_data data; 121 122 *cred_handle = GSS_C_NO_CREDENTIAL; 123 124 if (token->length == 0) { 125 *minor_status = ENOMEM; 126 return GSS_S_FAILURE; 127 } 128 129 sp = krb5_storage_from_readonly_mem(token->value, token->length); 130 if (sp == NULL) { 131 *minor_status = ENOMEM; 132 return GSS_S_FAILURE; 133 } 134 135 cred = calloc(1, sizeof(struct _gss_cred)); 136 if (cred == NULL) { 137 krb5_storage_free(sp); 138 *minor_status = ENOMEM; 139 return GSS_S_FAILURE; 140 } 141 HEIM_SLIST_INIT(&cred->gc_mc); 142 143 *cred_handle = (gss_cred_id_t)cred; 144 145 while(1) { 146 struct _gss_mechanism_cred *mc; 147 gss_buffer_desc buffer; 148 gss_cred_id_t mcred; 149 gss_OID_desc oid; 150 151 ret = krb5_ret_data(sp, &data); 152 if (ret == HEIM_ERR_EOF) { 153 break; 154 } else if (ret) { 155 *minor_status = ret; 156 major = GSS_S_FAILURE; 157 goto out; 158 } 159 oid.elements = data.data; 160 oid.length = data.length; 161 162 m = __gss_get_mechanism(&oid); 163 krb5_data_free(&data); 164 if (!m) { 165 *minor_status = 0; 166 major = GSS_S_BAD_MECH; 167 goto out; 168 } 169 170 if (m->gm_import_cred == NULL) { 171 *minor_status = 0; 172 major = GSS_S_BAD_MECH; 173 goto out; 174 } 175 176 ret = krb5_ret_data(sp, &data); 177 if (ret) { 178 *minor_status = ret; 179 major = GSS_S_FAILURE; 180 goto out; 181 } 182 183 buffer.value = data.data; 184 buffer.length = data.length; 185 186 major = m->gm_import_cred(minor_status, 187 &buffer, &mcred); 188 krb5_data_free(&data); 189 if (major) { 190 goto out; 191 } 192 193 mc = malloc(sizeof(struct _gss_mechanism_cred)); 194 if (mc == NULL) { 195 *minor_status = EINVAL; 196 major = GSS_S_FAILURE; 197 goto out; 198 } 199 200 mc->gmc_mech = m; 201 mc->gmc_mech_oid = &m->gm_mech_oid; 202 mc->gmc_cred = mcred; 203 204 HEIM_SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link); 205 } 206 krb5_storage_free(sp); 207 sp = NULL; 208 209 if (HEIM_SLIST_EMPTY(&cred->gc_mc)) { 210 major = GSS_S_NO_CRED; 211 goto out; 212 } 213 214 return GSS_S_COMPLETE; 215 216 out: 217 if (sp) 218 krb5_storage_free(sp); 219 220 gss_release_cred(&junk, cred_handle); 221 222 return major; 223 224 } 225