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