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