1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* lib/gssapi/mechglue/g_imp_cred.c - gss_import_cred definition */ 3 /* 4 * Copyright (C) 2012 by the Massachusetts Institute of Technology. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 30 * OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include "mglueP.h" 34 35 static OM_uint32 36 val_imp_cred_args(OM_uint32 *minor_status, gss_buffer_t token, 37 gss_cred_id_t *cred_handle) 38 { 39 /* Initialize outputs. */ 40 if (minor_status != NULL) 41 *minor_status = 0; 42 if (cred_handle != NULL) 43 *cred_handle = GSS_C_NO_CREDENTIAL; 44 45 /* Validate arguments. */ 46 if (minor_status == NULL) 47 return GSS_S_CALL_INACCESSIBLE_WRITE; 48 if (cred_handle == NULL) 49 return GSS_S_CALL_INACCESSIBLE_WRITE; 50 if (token == GSS_C_NO_BUFFER) 51 return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_DEFECTIVE_TOKEN; 52 if (GSS_EMPTY_BUFFER(token)) 53 return GSS_S_DEFECTIVE_TOKEN; 54 return GSS_S_COMPLETE; 55 } 56 57 /* Populate mech_oid and mech_token with the next entry in token, using aliased 58 * memory from token. Advance token by the amount consumed. */ 59 static OM_uint32 60 get_entry(OM_uint32 *minor_status, gss_buffer_t token, gss_OID mech_oid, 61 gss_buffer_t mech_token) 62 { 63 OM_uint32 len; 64 65 /* Get the mechanism OID. */ 66 if (token->length < 4) 67 return GSS_S_DEFECTIVE_TOKEN; 68 len = load_32_be(token->value); 69 if (token->length - 4 < len) 70 return GSS_S_DEFECTIVE_TOKEN; 71 mech_oid->length = len; 72 mech_oid->elements = (char *)token->value + 4; 73 token->value = (char *)token->value + 4 + len; 74 token->length -= 4 + len; 75 76 /* Get the mechanism token. */ 77 if (token->length < 4) 78 return GSS_S_DEFECTIVE_TOKEN; 79 len = load_32_be(token->value); 80 if (token->length - 4 < len) 81 return GSS_S_DEFECTIVE_TOKEN; 82 mech_token->length = len; 83 mech_token->value = (char *)token->value + 4; 84 token->value = (char *)token->value + 4 + len; 85 token->length -= 4 + len; 86 87 return GSS_S_COMPLETE; 88 } 89 90 OM_uint32 KRB5_CALLCONV 91 gss_import_cred(OM_uint32 *minor_status, gss_buffer_t token, 92 gss_cred_id_t *cred_handle) 93 { 94 OM_uint32 status, tmpmin, count; 95 gss_union_cred_t cred = NULL; 96 gss_mechanism mech; 97 gss_buffer_desc tok, mech_token; 98 gss_OID_desc mech_oid; 99 gss_OID selected_mech; 100 gss_cred_id_t mech_cred; 101 void *elemcopy; 102 103 status = val_imp_cred_args(minor_status, token, cred_handle); 104 if (status != GSS_S_COMPLETE) 105 return status; 106 107 /* Count the entries in token. */ 108 for (tok = *token, count = 0; tok.length > 0; count++) { 109 status = get_entry(minor_status, &tok, &mech_oid, &mech_token); 110 if (status != GSS_S_COMPLETE) 111 return status; 112 } 113 114 /* Allocate a union credential. */ 115 cred = calloc(1, sizeof(*cred)); 116 if (cred == NULL) 117 goto oom; 118 cred->loopback = cred; 119 cred->count = 0; 120 cred->mechs_array = calloc(count, sizeof(*cred->mechs_array)); 121 if (cred->mechs_array == NULL) 122 goto oom; 123 cred->cred_array = calloc(count, sizeof(*cred->cred_array)); 124 if (cred->cred_array == NULL) 125 goto oom; 126 127 tok = *token; 128 while (tok.length > 0) { 129 (void)get_entry(minor_status, &tok, &mech_oid, &mech_token); 130 131 /* Import this entry's mechanism token. */ 132 status = gssint_select_mech_type(minor_status, &mech_oid, 133 &selected_mech); 134 if (status != GSS_S_COMPLETE) 135 goto error; 136 mech = gssint_get_mechanism(selected_mech); 137 if (mech == NULL || (mech->gss_import_cred == NULL && 138 mech->gssspi_import_cred_by_mech == NULL)) { 139 status = GSS_S_DEFECTIVE_TOKEN; 140 goto error; 141 } 142 if (mech->gssspi_import_cred_by_mech) { 143 status = mech->gssspi_import_cred_by_mech(minor_status, 144 gssint_get_public_oid(selected_mech), 145 &mech_token, &mech_cred); 146 } else { 147 status = mech->gss_import_cred(minor_status, &mech_token, 148 &mech_cred); 149 } 150 if (status != GSS_S_COMPLETE) { 151 map_error(minor_status, mech); 152 goto error; 153 } 154 155 /* Add the resulting mechanism cred to the union cred. */ 156 elemcopy = malloc(selected_mech->length); 157 if (elemcopy == NULL) { 158 if (mech->gss_release_cred != NULL) 159 mech->gss_release_cred(&tmpmin, &mech_cred); 160 goto oom; 161 } 162 memcpy(elemcopy, selected_mech->elements, selected_mech->length); 163 cred->mechs_array[cred->count].length = selected_mech->length; 164 cred->mechs_array[cred->count].elements = elemcopy; 165 cred->cred_array[cred->count++] = mech_cred; 166 } 167 168 *cred_handle = cred; 169 return GSS_S_COMPLETE; 170 171 oom: 172 status = GSS_S_FAILURE; 173 *minor_status = ENOMEM; 174 error: 175 (void)gss_release_cred(&tmpmin, &cred); 176 return status; 177 } 178