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 the Institute nor the names of its contributors 18*ae771770SStanislav Sedov * may be used to endorse or promote products derived from this software 19*ae771770SStanislav Sedov * without specific prior written permission. 20*ae771770SStanislav Sedov * 21*ae771770SStanislav Sedov * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22*ae771770SStanislav Sedov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23*ae771770SStanislav Sedov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24*ae771770SStanislav Sedov * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25*ae771770SStanislav Sedov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26*ae771770SStanislav Sedov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27*ae771770SStanislav Sedov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28*ae771770SStanislav Sedov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29*ae771770SStanislav Sedov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30*ae771770SStanislav Sedov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31*ae771770SStanislav Sedov * SUCH DAMAGE. 32*ae771770SStanislav Sedov */ 33*ae771770SStanislav Sedov 34*ae771770SStanislav Sedov #include "gsskrb5_locl.h" 35*ae771770SStanislav Sedov 36*ae771770SStanislav Sedov OM_uint32 GSSAPI_CALLCONV 37*ae771770SStanislav Sedov _gsskrb5_export_cred(OM_uint32 *minor_status, 38*ae771770SStanislav Sedov gss_cred_id_t cred_handle, 39*ae771770SStanislav Sedov gss_buffer_t cred_token) 40*ae771770SStanislav Sedov { 41*ae771770SStanislav Sedov gsskrb5_cred handle = (gsskrb5_cred)cred_handle; 42*ae771770SStanislav Sedov krb5_context context; 43*ae771770SStanislav Sedov krb5_error_code ret; 44*ae771770SStanislav Sedov krb5_storage *sp; 45*ae771770SStanislav Sedov krb5_data data, mech; 46*ae771770SStanislav Sedov const char *type; 47*ae771770SStanislav Sedov char *str; 48*ae771770SStanislav Sedov 49*ae771770SStanislav Sedov GSSAPI_KRB5_INIT (&context); 50*ae771770SStanislav Sedov 51*ae771770SStanislav Sedov if (handle->usage != GSS_C_INITIATE && handle->usage != GSS_C_BOTH) { 52*ae771770SStanislav Sedov *minor_status = GSS_KRB5_S_G_BAD_USAGE; 53*ae771770SStanislav Sedov return GSS_S_FAILURE; 54*ae771770SStanislav Sedov } 55*ae771770SStanislav Sedov 56*ae771770SStanislav Sedov sp = krb5_storage_emem(); 57*ae771770SStanislav Sedov if (sp == NULL) { 58*ae771770SStanislav Sedov *minor_status = ENOMEM; 59*ae771770SStanislav Sedov return GSS_S_FAILURE; 60*ae771770SStanislav Sedov } 61*ae771770SStanislav Sedov 62*ae771770SStanislav Sedov type = krb5_cc_get_type(context, handle->ccache); 63*ae771770SStanislav Sedov if (strcmp(type, "MEMORY") == 0) { 64*ae771770SStanislav Sedov krb5_creds *creds; 65*ae771770SStanislav Sedov ret = krb5_store_uint32(sp, 0); 66*ae771770SStanislav Sedov if (ret) { 67*ae771770SStanislav Sedov krb5_storage_free(sp); 68*ae771770SStanislav Sedov *minor_status = ret; 69*ae771770SStanislav Sedov return GSS_S_FAILURE; 70*ae771770SStanislav Sedov } 71*ae771770SStanislav Sedov 72*ae771770SStanislav Sedov ret = _krb5_get_krbtgt(context, handle->ccache, 73*ae771770SStanislav Sedov handle->principal->realm, 74*ae771770SStanislav Sedov &creds); 75*ae771770SStanislav Sedov if (ret) { 76*ae771770SStanislav Sedov krb5_storage_free(sp); 77*ae771770SStanislav Sedov *minor_status = ret; 78*ae771770SStanislav Sedov return GSS_S_FAILURE; 79*ae771770SStanislav Sedov } 80*ae771770SStanislav Sedov 81*ae771770SStanislav Sedov ret = krb5_store_creds(sp, creds); 82*ae771770SStanislav Sedov krb5_free_creds(context, creds); 83*ae771770SStanislav Sedov if (ret) { 84*ae771770SStanislav Sedov krb5_storage_free(sp); 85*ae771770SStanislav Sedov *minor_status = ret; 86*ae771770SStanislav Sedov return GSS_S_FAILURE; 87*ae771770SStanislav Sedov } 88*ae771770SStanislav Sedov 89*ae771770SStanislav Sedov } else { 90*ae771770SStanislav Sedov ret = krb5_store_uint32(sp, 1); 91*ae771770SStanislav Sedov if (ret) { 92*ae771770SStanislav Sedov krb5_storage_free(sp); 93*ae771770SStanislav Sedov *minor_status = ret; 94*ae771770SStanislav Sedov return GSS_S_FAILURE; 95*ae771770SStanislav Sedov } 96*ae771770SStanislav Sedov 97*ae771770SStanislav Sedov ret = krb5_cc_get_full_name(context, handle->ccache, &str); 98*ae771770SStanislav Sedov if (ret) { 99*ae771770SStanislav Sedov krb5_storage_free(sp); 100*ae771770SStanislav Sedov *minor_status = ret; 101*ae771770SStanislav Sedov return GSS_S_FAILURE; 102*ae771770SStanislav Sedov } 103*ae771770SStanislav Sedov 104*ae771770SStanislav Sedov ret = krb5_store_string(sp, str); 105*ae771770SStanislav Sedov free(str); 106*ae771770SStanislav Sedov if (ret) { 107*ae771770SStanislav Sedov krb5_storage_free(sp); 108*ae771770SStanislav Sedov *minor_status = ret; 109*ae771770SStanislav Sedov return GSS_S_FAILURE; 110*ae771770SStanislav Sedov } 111*ae771770SStanislav Sedov } 112*ae771770SStanislav Sedov ret = krb5_storage_to_data(sp, &data); 113*ae771770SStanislav Sedov krb5_storage_free(sp); 114*ae771770SStanislav Sedov if (ret) { 115*ae771770SStanislav Sedov *minor_status = ret; 116*ae771770SStanislav Sedov return GSS_S_FAILURE; 117*ae771770SStanislav Sedov } 118*ae771770SStanislav Sedov sp = krb5_storage_emem(); 119*ae771770SStanislav Sedov if (sp == NULL) { 120*ae771770SStanislav Sedov krb5_data_free(&data); 121*ae771770SStanislav Sedov *minor_status = ENOMEM; 122*ae771770SStanislav Sedov return GSS_S_FAILURE; 123*ae771770SStanislav Sedov } 124*ae771770SStanislav Sedov 125*ae771770SStanislav Sedov mech.data = GSS_KRB5_MECHANISM->elements; 126*ae771770SStanislav Sedov mech.length = GSS_KRB5_MECHANISM->length; 127*ae771770SStanislav Sedov 128*ae771770SStanislav Sedov ret = krb5_store_data(sp, mech); 129*ae771770SStanislav Sedov if (ret) { 130*ae771770SStanislav Sedov krb5_data_free(&data); 131*ae771770SStanislav Sedov krb5_storage_free(sp); 132*ae771770SStanislav Sedov *minor_status = ret; 133*ae771770SStanislav Sedov return GSS_S_FAILURE; 134*ae771770SStanislav Sedov } 135*ae771770SStanislav Sedov 136*ae771770SStanislav Sedov ret = krb5_store_data(sp, data); 137*ae771770SStanislav Sedov krb5_data_free(&data); 138*ae771770SStanislav Sedov if (ret) { 139*ae771770SStanislav Sedov krb5_storage_free(sp); 140*ae771770SStanislav Sedov *minor_status = ret; 141*ae771770SStanislav Sedov return GSS_S_FAILURE; 142*ae771770SStanislav Sedov } 143*ae771770SStanislav Sedov 144*ae771770SStanislav Sedov ret = krb5_storage_to_data(sp, &data); 145*ae771770SStanislav Sedov krb5_storage_free(sp); 146*ae771770SStanislav Sedov if (ret) { 147*ae771770SStanislav Sedov *minor_status = ret; 148*ae771770SStanislav Sedov return GSS_S_FAILURE; 149*ae771770SStanislav Sedov } 150*ae771770SStanislav Sedov 151*ae771770SStanislav Sedov cred_token->value = data.data; 152*ae771770SStanislav Sedov cred_token->length = data.length; 153*ae771770SStanislav Sedov 154*ae771770SStanislav Sedov return GSS_S_COMPLETE; 155*ae771770SStanislav Sedov } 156*ae771770SStanislav Sedov 157*ae771770SStanislav Sedov OM_uint32 GSSAPI_CALLCONV 158*ae771770SStanislav Sedov _gsskrb5_import_cred(OM_uint32 * minor_status, 159*ae771770SStanislav Sedov gss_buffer_t cred_token, 160*ae771770SStanislav Sedov gss_cred_id_t * cred_handle) 161*ae771770SStanislav Sedov { 162*ae771770SStanislav Sedov krb5_context context; 163*ae771770SStanislav Sedov krb5_error_code ret; 164*ae771770SStanislav Sedov gsskrb5_cred handle; 165*ae771770SStanislav Sedov krb5_ccache id; 166*ae771770SStanislav Sedov krb5_storage *sp; 167*ae771770SStanislav Sedov char *str; 168*ae771770SStanislav Sedov uint32_t type; 169*ae771770SStanislav Sedov int flags = 0; 170*ae771770SStanislav Sedov 171*ae771770SStanislav Sedov *cred_handle = GSS_C_NO_CREDENTIAL; 172*ae771770SStanislav Sedov 173*ae771770SStanislav Sedov GSSAPI_KRB5_INIT (&context); 174*ae771770SStanislav Sedov 175*ae771770SStanislav Sedov sp = krb5_storage_from_mem(cred_token->value, cred_token->length); 176*ae771770SStanislav Sedov if (sp == NULL) { 177*ae771770SStanislav Sedov *minor_status = ENOMEM; 178*ae771770SStanislav Sedov return GSS_S_FAILURE; 179*ae771770SStanislav Sedov } 180*ae771770SStanislav Sedov 181*ae771770SStanislav Sedov ret = krb5_ret_uint32(sp, &type); 182*ae771770SStanislav Sedov if (ret) { 183*ae771770SStanislav Sedov krb5_storage_free(sp); 184*ae771770SStanislav Sedov *minor_status = ret; 185*ae771770SStanislav Sedov return GSS_S_FAILURE; 186*ae771770SStanislav Sedov } 187*ae771770SStanislav Sedov switch (type) { 188*ae771770SStanislav Sedov case 0: { 189*ae771770SStanislav Sedov krb5_creds creds; 190*ae771770SStanislav Sedov 191*ae771770SStanislav Sedov ret = krb5_ret_creds(sp, &creds); 192*ae771770SStanislav Sedov krb5_storage_free(sp); 193*ae771770SStanislav Sedov if (ret) { 194*ae771770SStanislav Sedov *minor_status = ret; 195*ae771770SStanislav Sedov return GSS_S_FAILURE; 196*ae771770SStanislav Sedov } 197*ae771770SStanislav Sedov 198*ae771770SStanislav Sedov ret = krb5_cc_new_unique(context, "MEMORY", NULL, &id); 199*ae771770SStanislav Sedov if (ret) { 200*ae771770SStanislav Sedov *minor_status = ret; 201*ae771770SStanislav Sedov return GSS_S_FAILURE; 202*ae771770SStanislav Sedov } 203*ae771770SStanislav Sedov 204*ae771770SStanislav Sedov ret = krb5_cc_initialize(context, id, creds.client); 205*ae771770SStanislav Sedov if (ret) { 206*ae771770SStanislav Sedov krb5_cc_destroy(context, id); 207*ae771770SStanislav Sedov *minor_status = ret; 208*ae771770SStanislav Sedov return GSS_S_FAILURE; 209*ae771770SStanislav Sedov } 210*ae771770SStanislav Sedov 211*ae771770SStanislav Sedov ret = krb5_cc_store_cred(context, id, &creds); 212*ae771770SStanislav Sedov krb5_free_cred_contents(context, &creds); 213*ae771770SStanislav Sedov 214*ae771770SStanislav Sedov flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; 215*ae771770SStanislav Sedov 216*ae771770SStanislav Sedov break; 217*ae771770SStanislav Sedov } 218*ae771770SStanislav Sedov case 1: 219*ae771770SStanislav Sedov ret = krb5_ret_string(sp, &str); 220*ae771770SStanislav Sedov krb5_storage_free(sp); 221*ae771770SStanislav Sedov if (ret) { 222*ae771770SStanislav Sedov *minor_status = ret; 223*ae771770SStanislav Sedov return GSS_S_FAILURE; 224*ae771770SStanislav Sedov } 225*ae771770SStanislav Sedov 226*ae771770SStanislav Sedov ret = krb5_cc_resolve(context, str, &id); 227*ae771770SStanislav Sedov krb5_xfree(str); 228*ae771770SStanislav Sedov if (ret) { 229*ae771770SStanislav Sedov *minor_status = ret; 230*ae771770SStanislav Sedov return GSS_S_FAILURE; 231*ae771770SStanislav Sedov } 232*ae771770SStanislav Sedov break; 233*ae771770SStanislav Sedov 234*ae771770SStanislav Sedov default: 235*ae771770SStanislav Sedov krb5_storage_free(sp); 236*ae771770SStanislav Sedov *minor_status = 0; 237*ae771770SStanislav Sedov return GSS_S_NO_CRED; 238*ae771770SStanislav Sedov } 239*ae771770SStanislav Sedov 240*ae771770SStanislav Sedov handle = calloc(1, sizeof(*handle)); 241*ae771770SStanislav Sedov if (handle == NULL) { 242*ae771770SStanislav Sedov krb5_cc_close(context, id); 243*ae771770SStanislav Sedov *minor_status = ENOMEM; 244*ae771770SStanislav Sedov return GSS_S_FAILURE; 245*ae771770SStanislav Sedov } 246*ae771770SStanislav Sedov 247*ae771770SStanislav Sedov handle->usage = GSS_C_INITIATE; 248*ae771770SStanislav Sedov krb5_cc_get_principal(context, id, &handle->principal); 249*ae771770SStanislav Sedov handle->ccache = id; 250*ae771770SStanislav Sedov handle->cred_flags = flags; 251*ae771770SStanislav Sedov 252*ae771770SStanislav Sedov *cred_handle = (gss_cred_id_t)handle; 253*ae771770SStanislav Sedov 254*ae771770SStanislav Sedov return GSS_S_COMPLETE; 255*ae771770SStanislav Sedov } 256