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