1/* 2 * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Portions Copyright (c) 2009 Apple Inc. 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 the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include "gssdigest.h" 37#include <gssapi_spi.h> 38 39OM_uint32 40_gss_scram_have_cred(OM_uint32 *minor, 41 const char *name, 42 gss_cred_id_t *rcred) 43{ 44 krb5_context context; 45 krb5_error_code ret; 46 krb5_storage *request = NULL, *response; 47 krb5_data response_data; 48 OM_uint32 major; 49 50 ret = krb5_init_context(&context); 51 if (ret) { 52 *minor = ret; 53 return GSS_S_FAILURE; 54 } 55 56 ret = krb5_kcm_storage_request(context, KCM_OP_HAVE_SCRAM_CRED, &request); 57 if (ret) 58 goto out; 59 60 ret = krb5_store_stringz(request, name); 61 if (ret) 62 goto out; 63 64 ret = krb5_kcm_call(context, request, &response, &response_data); 65 if (ret) 66 goto out; 67 68 request = NULL; 69 70 if (rcred) { 71 *rcred = (gss_cred_id_t)strdup(name); 72 if (*rcred == NULL) 73 ret = ENOMEM; 74 } 75 out: 76 if (request) 77 krb5_storage_free(request); 78 krb5_free_context(context); 79 if (ret) { 80 *minor = ret; 81 major = GSS_S_FAILURE; 82 } else 83 major = GSS_S_COMPLETE; 84 85 return major; 86} 87 88OM_uint32 89_gss_scram_acquire_cred(OM_uint32 * min_stat, 90 const gss_name_t desired_name, 91 OM_uint32 time_req, 92 const gss_OID_set desired_mechs, 93 gss_cred_usage_t cred_usage, 94 gss_cred_id_t * output_cred_handle, 95 gss_OID_set * actual_mechs, 96 OM_uint32 * time_rec) 97{ 98 char *name = (char *) desired_name; 99 OM_uint32 maj_stat; 100 101 *min_stat = 0; 102 *output_cred_handle = GSS_C_NO_CREDENTIAL; 103 if (actual_mechs) 104 *actual_mechs = GSS_C_NO_OID_SET; 105 if (time_rec) 106 *time_rec = GSS_C_INDEFINITE; 107 108 if (desired_name == NULL) 109 return GSS_S_NO_CRED; 110 111 if (cred_usage == GSS_C_BOTH || cred_usage == GSS_C_ACCEPT) { 112 /* we have all server names */ 113 } 114 if (cred_usage == GSS_C_BOTH || cred_usage == GSS_C_INITIATE) { 115 maj_stat = _gss_scram_have_cred(min_stat, name, output_cred_handle); 116 if (maj_stat) 117 return maj_stat; 118 } 119 120 return (GSS_S_COMPLETE); 121} 122 123OM_uint32 124_gss_scram_acquire_cred_ext(OM_uint32 * minor_status, 125 const gss_name_t desired_name, 126 gss_const_OID credential_type, 127 const void *credential_data, 128 OM_uint32 time_req, 129 gss_const_OID desired_mech, 130 gss_cred_usage_t cred_usage, 131 gss_cred_id_t * output_cred_handle) 132{ 133 char *name = (char *) desired_name; 134 krb5_storage *request, *response; 135 gss_buffer_t credential_buffer; 136 krb5_data response_data; 137 krb5_context context; 138 krb5_error_code ret; 139 char *password; 140 char *cred; 141 142 *output_cred_handle = GSS_C_NO_CREDENTIAL; 143 144 krb5_data_zero(&response_data); 145 146 if (!gss_oid_equal(credential_type, GSS_C_CRED_PASSWORD)) 147 return GSS_S_FAILURE; 148 149 if (name == NULL) 150 return GSS_S_FAILURE; 151 152 if (credential_data == NULL) 153 return GSS_S_FAILURE; 154 155 ret = krb5_init_context(&context); 156 if (ret) 157 return GSS_S_FAILURE; 158 159 ret = krb5_kcm_storage_request(context, KCM_OP_ADD_SCRAM_CRED, &request); 160 if (ret) 161 goto fail; 162 163 ret = krb5_store_stringz(request, name); 164 if (ret) 165 goto fail; 166 167 credential_buffer = (gss_buffer_t)credential_data; 168 password = malloc(credential_buffer->length + 1); 169 if (password == NULL) { 170 ret = ENOMEM; 171 goto fail; 172 } 173 memcpy(password, credential_buffer->value, credential_buffer->length); 174 password[credential_buffer->length] = '\0'; 175 176 ret = krb5_store_stringz(request, password); 177 memset(password, 0, strlen(password)); 178 free(password); 179 if (ret) 180 goto fail; 181 182 ret = krb5_kcm_call(context, request, &response, &response_data); 183 if (ret) 184 goto fail; 185 186 request = NULL; 187 188 cred = strdup(name); 189 190 *output_cred_handle = (gss_cred_id_t)cred; 191 192 if (response) 193 krb5_storage_free(response); 194 krb5_data_free(&response_data); 195 krb5_free_context(context); 196 197 return GSS_S_COMPLETE; 198 199 fail: 200 if (request) 201 krb5_storage_free(request); 202 if (minor_status) 203 *minor_status = ret; 204 return GSS_S_FAILURE; 205} 206