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