1 /* 2 * lib/krb5/krb/copy_auth.c 3 * 4 * Copyright 1990 by the Massachusetts Institute of Technology. 5 * All Rights Reserved. 6 * 7 * Export of this software from the United States of America may 8 * require a specific license from the United States Government. 9 * It is the responsibility of any person or organization contemplating 10 * export to obtain such a license before exporting. 11 * 12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 13 * distribute this software and its documentation for any purpose and 14 * without fee is hereby granted, provided that the above copyright 15 * notice appear in all copies and that both that copyright notice and 16 * this permission notice appear in supporting documentation, and that 17 * the name of M.I.T. not be used in advertising or publicity pertaining 18 * to distribution of the software without specific, written prior 19 * permission. Furthermore if you modify this software you must label 20 * your software as modified software and not distribute it in such a 21 * fashion that it might be confused with the original M.I.T. software. 22 * M.I.T. makes no representations about the suitability of 23 * this software for any purpose. It is provided "as is" without express 24 * or implied warranty. 25 * 26 * 27 * krb5_copy_authdata() 28 */ 29 /* 30 * Copyright (c) 2006-2008, Novell, Inc. 31 * All rights reserved. 32 * 33 * Redistribution and use in source and binary forms, with or without 34 * modification, are permitted provided that the following conditions are met: 35 * 36 * * Redistributions of source code must retain the above copyright notice, 37 * this list of conditions and the following disclaimer. 38 * * Redistributions in binary form must reproduce the above copyright 39 * notice, this list of conditions and the following disclaimer in the 40 * documentation and/or other materials provided with the distribution. 41 * * The copyright holder's name is not used to endorse or promote products 42 * derived from this software without specific prior written permission. 43 * 44 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 45 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 47 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 48 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 49 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 50 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 51 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 52 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 53 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 54 * POSSIBILITY OF SUCH DAMAGE. 55 */ 56 57 #include "k5-int.h" 58 59 static krb5_error_code 60 krb5_copy_authdatum(krb5_context context, const krb5_authdata *inad, krb5_authdata **outad) 61 { 62 krb5_authdata *tmpad; 63 64 if (!(tmpad = (krb5_authdata *)malloc(sizeof(*tmpad)))) 65 return ENOMEM; 66 *tmpad = *inad; 67 if (!(tmpad->contents = (krb5_octet *)malloc(inad->length))) { 68 free(tmpad); 69 return ENOMEM; 70 } 71 (void) memcpy((char *)tmpad->contents, (char *)inad->contents, inad->length); 72 *outad = tmpad; 73 return 0; 74 } 75 76 /* 77 * Copy an authdata array, with fresh allocation. 78 */ 79 krb5_error_code KRB5_CALLCONV 80 krb5_merge_authdata(krb5_context context, krb5_authdata *const *inauthdat1, krb5_authdata * const *inauthdat2, 81 krb5_authdata ***outauthdat) 82 { 83 krb5_error_code retval; 84 krb5_authdata ** tempauthdat; 85 register unsigned int nelems = 0, nelems2 = 0; 86 87 *outauthdat = NULL; 88 if (!inauthdat1 && !inauthdat2) { 89 *outauthdat = 0; 90 return 0; 91 } 92 93 if (inauthdat1) 94 while (inauthdat1[nelems]) nelems++; 95 if (inauthdat2) 96 while (inauthdat2[nelems2]) nelems2++; 97 98 /* one more for a null terminated list */ 99 if (!(tempauthdat = (krb5_authdata **) calloc(nelems+nelems2+1, 100 sizeof(*tempauthdat)))) 101 return ENOMEM; 102 103 if (inauthdat1) { 104 for (nelems = 0; inauthdat1[nelems]; nelems++) { 105 retval = krb5_copy_authdatum(context, inauthdat1[nelems], 106 &tempauthdat[nelems]); 107 if (retval) { 108 krb5_free_authdata(context, tempauthdat); 109 return retval; 110 } 111 } 112 } 113 114 if (inauthdat2) { 115 for (nelems2 = 0; inauthdat2[nelems2]; nelems2++) { 116 retval = krb5_copy_authdatum(context, inauthdat2[nelems2], 117 &tempauthdat[nelems++]); 118 if (retval) { 119 krb5_free_authdata(context, tempauthdat); 120 return retval; 121 } 122 } 123 } 124 125 *outauthdat = tempauthdat; 126 return 0; 127 } 128 129 krb5_error_code KRB5_CALLCONV 130 krb5_copy_authdata(krb5_context context, 131 krb5_authdata *const *in_authdat, krb5_authdata ***out) 132 { 133 return krb5_merge_authdata(context, in_authdat, NULL, out); 134 } 135 136 krb5_error_code KRB5_CALLCONV 137 krb5_decode_authdata_container(krb5_context context, 138 krb5_authdatatype type, 139 const krb5_authdata *container, 140 krb5_authdata ***authdata) 141 { 142 krb5_error_code code; 143 krb5_data data; 144 145 *authdata = NULL; 146 147 if ((container->ad_type & AD_TYPE_FIELD_TYPE_MASK) != type) 148 return EINVAL; 149 150 data.length = container->length; 151 data.data = (char *)container->contents; 152 153 code = decode_krb5_authdata(&data, authdata); 154 if (code) 155 return code; 156 157 return 0; 158 } 159 160 krb5_error_code KRB5_CALLCONV 161 krb5_encode_authdata_container(krb5_context context, 162 krb5_authdatatype type, 163 krb5_authdata *const*authdata, 164 krb5_authdata ***container) 165 { 166 krb5_error_code code; 167 krb5_data *data; 168 krb5_authdata ad_datum; 169 krb5_authdata *ad_data[2]; 170 171 *container = NULL; 172 173 code = encode_krb5_authdata((krb5_authdata * const *)authdata, &data); 174 if (code) 175 return code; 176 177 ad_datum.ad_type = type & AD_TYPE_FIELD_TYPE_MASK; 178 ad_datum.length = data->length; 179 ad_datum.contents = (unsigned char *)data->data; 180 181 ad_data[0] = &ad_datum; 182 ad_data[1] = NULL; 183 184 code = krb5_copy_authdata(context, ad_data, container); 185 186 krb5_free_data(context, data); 187 188 return code; 189 } 190 191 struct find_authdata_context { 192 krb5_authdata **out; 193 size_t space; 194 size_t length; 195 }; 196 197 static krb5_error_code grow_find_authdata 198 (krb5_context context, struct find_authdata_context *fctx, 199 krb5_authdata *elem) 200 { 201 krb5_error_code retval = 0; 202 if (fctx->length == fctx->space) { 203 krb5_authdata **new; 204 if (fctx->space >= 256) { 205 krb5_set_error_message(context, ERANGE, "More than 256 authdata matched a query"); 206 return ERANGE; 207 } 208 new = realloc(fctx->out, 209 sizeof (krb5_authdata *)*(2*fctx->space+1)); 210 if (new == NULL) 211 return ENOMEM; 212 fctx->out = new; 213 fctx->space *=2; 214 } 215 fctx->out[fctx->length+1] = NULL; 216 retval = krb5_copy_authdatum(context, elem, 217 &fctx->out[fctx->length]); 218 if (retval == 0) 219 fctx->length++; 220 return retval; 221 } 222 223 224 225 226 static krb5_error_code find_authdata_1 227 (krb5_context context, krb5_authdata *const *in_authdat, krb5_authdatatype ad_type, 228 struct find_authdata_context *fctx) 229 { 230 int i = 0; 231 krb5_error_code retval=0; 232 233 for (i = 0; in_authdat[i]; i++) { 234 krb5_authdata *ad = in_authdat[i]; 235 if (ad->ad_type == ad_type && retval ==0) 236 retval = grow_find_authdata(context, fctx, ad); 237 else switch (ad->ad_type) { 238 krb5_authdata **decoded_container; 239 case KRB5_AUTHDATA_IF_RELEVANT: 240 if (retval == 0) 241 retval = krb5_decode_authdata_container( context, ad->ad_type, ad, &decoded_container); 242 if (retval == 0) { 243 retval = find_authdata_1(context, 244 decoded_container, ad_type, fctx); 245 krb5_free_authdata(context, decoded_container); 246 } 247 break; 248 default: 249 break; 250 } 251 } 252 return retval; 253 } 254 255 256 krb5_error_code krb5int_find_authdata 257 (krb5_context context, krb5_authdata *const * ticket_authdata, 258 krb5_authdata * const *ap_req_authdata, 259 krb5_authdatatype ad_type, 260 krb5_authdata ***results) 261 { 262 krb5_error_code retval = 0; 263 struct find_authdata_context fctx; 264 fctx.length = 0; 265 fctx.space = 2; 266 fctx.out = calloc(fctx.space+1, sizeof (krb5_authdata *)); 267 *results = NULL; 268 if (fctx.out == NULL) 269 return ENOMEM; 270 if (ticket_authdata) 271 retval = find_authdata_1( context, ticket_authdata, ad_type, &fctx); 272 if ((retval==0) && ap_req_authdata) 273 retval = find_authdata_1( context, ap_req_authdata, ad_type, &fctx); 274 if ((retval== 0) && fctx.length) 275 *results = fctx.out; 276 else krb5_free_authdata(context, fctx.out); 277 return retval; 278 } 279