1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/krb5/krb/authdata_dec.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 * Copyright (c) 2006-2008, Novell, Inc.
28 * All rights reserved.
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions are met:
32 *
33 * * Redistributions of source code must retain the above copyright notice,
34 * this list of conditions and the following disclaimer.
35 * * Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * * The copyright holder's name is not used to endorse or promote products
39 * derived from this software without specific prior written permission.
40 *
41 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
42 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
45 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
46 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
47 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
48 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
49 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
51 * POSSIBILITY OF SUCH DAMAGE.
52 */
53
54 #include "k5-int.h"
55 #include "int-proto.h"
56
57 krb5_error_code KRB5_CALLCONV
krb5_decode_authdata_container(krb5_context context,krb5_authdatatype type,const krb5_authdata * container,krb5_authdata *** authdata)58 krb5_decode_authdata_container(krb5_context context,
59 krb5_authdatatype type,
60 const krb5_authdata *container,
61 krb5_authdata ***authdata)
62 {
63 krb5_error_code code;
64 krb5_data data;
65
66 *authdata = NULL;
67
68 if ((container->ad_type & AD_TYPE_FIELD_TYPE_MASK) != type)
69 return EINVAL;
70
71 data.length = container->length;
72 data.data = (char *)container->contents;
73
74 code = decode_krb5_authdata(&data, authdata);
75 if (code)
76 return code;
77
78 return 0;
79 }
80
81 struct find_authdata_context {
82 krb5_authdata **out;
83 size_t space;
84 size_t length;
85 };
86
87 static krb5_error_code
grow_find_authdata(krb5_context context,struct find_authdata_context * fctx,krb5_authdata * elem)88 grow_find_authdata(krb5_context context, struct find_authdata_context *fctx,
89 krb5_authdata *elem)
90 {
91 krb5_error_code retval = 0;
92 if (fctx->length == fctx->space) {
93 krb5_authdata **new;
94 if (fctx->space >= 256) {
95 k5_setmsg(context, ERANGE,
96 "More than 256 authdata matched a query");
97 return ERANGE;
98 }
99 new = realloc(fctx->out,
100 sizeof (krb5_authdata *)*(2*fctx->space+1));
101 if (new == NULL)
102 return ENOMEM;
103 fctx->out = new;
104 fctx->space *=2;
105 }
106 fctx->out[fctx->length+1] = NULL;
107 retval = krb5int_copy_authdatum(context, elem,
108 &fctx->out[fctx->length]);
109 if (retval == 0)
110 fctx->length++;
111 return retval;
112 }
113
114 static krb5_error_code
find_authdata_1(krb5_context context,krb5_authdata * const * in_authdat,krb5_authdatatype ad_type,struct find_authdata_context * fctx,int from_ap_req)115 find_authdata_1(krb5_context context, krb5_authdata *const *in_authdat,
116 krb5_authdatatype ad_type, struct find_authdata_context *fctx,
117 int from_ap_req)
118 {
119 size_t i = 0;
120 krb5_error_code retval = 0;
121
122 for (i = 0; in_authdat[i] && retval == 0; i++) {
123 krb5_authdata *ad = in_authdat[i];
124 krb5_authdata **decoded_container;
125
126 switch (ad->ad_type) {
127 case KRB5_AUTHDATA_IF_RELEVANT:
128 if (retval == 0)
129 retval = krb5_decode_authdata_container(context,
130 ad->ad_type,
131 ad,
132 &decoded_container);
133 if (retval == 0) {
134 retval = find_authdata_1(context,
135 decoded_container,
136 ad_type,
137 fctx,
138 from_ap_req);
139 krb5_free_authdata(context, decoded_container);
140 }
141 break;
142 case KRB5_AUTHDATA_SIGNTICKET:
143 case KRB5_AUTHDATA_KDC_ISSUED:
144 case KRB5_AUTHDATA_WIN2K_PAC:
145 case KRB5_AUTHDATA_CAMMAC:
146 case KRB5_AUTHDATA_AUTH_INDICATOR:
147 if (from_ap_req)
148 continue;
149 default:
150 if (ad->ad_type == ad_type && retval == 0)
151 retval = grow_find_authdata(context, fctx, ad);
152 break;
153 }
154 }
155
156 return retval;
157 }
158
159 krb5_error_code KRB5_CALLCONV
krb5_find_authdata(krb5_context context,krb5_authdata * const * ticket_authdata,krb5_authdata * const * ap_req_authdata,krb5_authdatatype ad_type,krb5_authdata *** results)160 krb5_find_authdata(krb5_context context,
161 krb5_authdata *const *ticket_authdata,
162 krb5_authdata *const *ap_req_authdata,
163 krb5_authdatatype ad_type, krb5_authdata ***results)
164 {
165 krb5_error_code retval = 0;
166 struct find_authdata_context fctx;
167 fctx.length = 0;
168 fctx.space = 2;
169 fctx.out = calloc(fctx.space+1, sizeof (krb5_authdata *));
170 *results = NULL;
171 if (fctx.out == NULL)
172 return ENOMEM;
173 if (ticket_authdata)
174 retval = find_authdata_1( context, ticket_authdata, ad_type, &fctx, 0);
175 if ((retval==0) && ap_req_authdata)
176 retval = find_authdata_1( context, ap_req_authdata, ad_type, &fctx, 1);
177 if ((retval== 0) && fctx.length)
178 *results = fctx.out;
179 else krb5_free_authdata(context, fctx.out);
180 return retval;
181 }
182
183 krb5_error_code KRB5_CALLCONV
krb5_verify_authdata_kdc_issued(krb5_context context,const krb5_keyblock * key,const krb5_authdata * ad_kdcissued,krb5_principal * issuer,krb5_authdata *** authdata)184 krb5_verify_authdata_kdc_issued(krb5_context context,
185 const krb5_keyblock *key,
186 const krb5_authdata *ad_kdcissued,
187 krb5_principal *issuer,
188 krb5_authdata ***authdata)
189 {
190 krb5_error_code code;
191 krb5_ad_kdcissued *ad_kdci;
192 krb5_data data, *data2;
193 krb5_boolean valid = FALSE;
194
195 if ((ad_kdcissued->ad_type & AD_TYPE_FIELD_TYPE_MASK) !=
196 KRB5_AUTHDATA_KDC_ISSUED)
197 return EINVAL;
198
199 if (issuer != NULL)
200 *issuer = NULL;
201 if (authdata != NULL)
202 *authdata = NULL;
203
204 data.length = ad_kdcissued->length;
205 data.data = (char *)ad_kdcissued->contents;
206
207 code = decode_krb5_ad_kdcissued(&data, &ad_kdci);
208 if (code != 0)
209 return code;
210
211 if (!krb5_c_is_keyed_cksum(ad_kdci->ad_checksum.checksum_type)) {
212 krb5_free_ad_kdcissued(context, ad_kdci);
213 return KRB5KRB_AP_ERR_INAPP_CKSUM;
214 }
215
216 code = encode_krb5_authdata(ad_kdci->elements, &data2);
217 if (code != 0) {
218 krb5_free_ad_kdcissued(context, ad_kdci);
219 return code;
220 }
221
222 code = krb5_c_verify_checksum(context, key,
223 KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM,
224 data2, &ad_kdci->ad_checksum, &valid);
225 if (code != 0) {
226 krb5_free_ad_kdcissued(context, ad_kdci);
227 krb5_free_data(context, data2);
228 return code;
229 }
230
231 krb5_free_data(context, data2);
232
233 if (valid == FALSE) {
234 krb5_free_ad_kdcissued(context, ad_kdci);
235 return KRB5KRB_AP_ERR_BAD_INTEGRITY;
236 }
237
238 if (issuer != NULL) {
239 *issuer = ad_kdci->i_principal;
240 ad_kdci->i_principal = NULL;
241 }
242
243 if (authdata != NULL) {
244 *authdata = ad_kdci->elements;
245 ad_kdci->elements = NULL;
246 }
247
248 krb5_free_ad_kdcissued(context, ad_kdci);
249
250 return 0;
251 }
252
253 /*
254 * Decode authentication indicator strings from authdata and return as an
255 * allocated array of krb5_data pointers. The caller must initialize
256 * *indicators to NULL for the first call, and successive calls will reallocate
257 * and append to the indicators array.
258 */
259 krb5_error_code
k5_authind_decode(const krb5_authdata * ad,krb5_data *** indicators)260 k5_authind_decode(const krb5_authdata *ad, krb5_data ***indicators)
261 {
262 krb5_error_code ret = 0;
263 krb5_data der_ad, **strdata = NULL, **ai_list = *indicators;
264 size_t count, scount;
265
266 if (ad == NULL || ad->ad_type != KRB5_AUTHDATA_AUTH_INDICATOR)
267 goto cleanup;
268
269 /* Count existing auth indicators. */
270 for (count = 0; ai_list != NULL && ai_list[count] != NULL; count++);
271
272 der_ad = make_data(ad->contents, ad->length);
273 ret = decode_utf8_strings(&der_ad, &strdata);
274 if (ret)
275 return ret;
276
277 /* Count new auth indicators. */
278 for (scount = 0; strdata[scount] != NULL; scount++);
279
280 ai_list = realloc(ai_list, (count + scount + 1) * sizeof(*ai_list));
281 if (ai_list == NULL) {
282 ret = ENOMEM;
283 goto cleanup;
284 }
285 *indicators = ai_list;
286
287 /* Steal decoder-allocated pointers and free the container array. */
288 memcpy(ai_list + count, strdata, scount * sizeof(*strdata));
289 ai_list[count + scount] = NULL;
290 free(strdata);
291 strdata = NULL;
292
293 cleanup:
294 k5_free_data_ptr_list(strdata);
295 return ret;
296 }
297