xref: /illumos-gate/usr/src/uts/common/gssapi/mechs/krb5/krb5/krb/copy_auth.c (revision ba7b222e36bac28710a7f43739283302b617e7f5)
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