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