xref: /freebsd/crypto/heimdal/lib/krb5/ticket.c (revision 531c2d7af3cd2e64eec94aa1b19c4b2f16fce515)
1b528cefcSMark Murray /*
2ae771770SStanislav Sedov  * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
3b528cefcSMark Murray  * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray  * All rights reserved.
5b528cefcSMark Murray  *
6ae771770SStanislav Sedov  * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
7ae771770SStanislav Sedov  *
8b528cefcSMark Murray  * Redistribution and use in source and binary forms, with or without
9b528cefcSMark Murray  * modification, are permitted provided that the following conditions
10b528cefcSMark Murray  * are met:
11b528cefcSMark Murray  *
12b528cefcSMark Murray  * 1. Redistributions of source code must retain the above copyright
13b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer.
14b528cefcSMark Murray  *
15b528cefcSMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
16b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer in the
17b528cefcSMark Murray  *    documentation and/or other materials provided with the distribution.
18b528cefcSMark Murray  *
19b528cefcSMark Murray  * 3. Neither the name of the Institute nor the names of its contributors
20b528cefcSMark Murray  *    may be used to endorse or promote products derived from this software
21b528cefcSMark Murray  *    without specific prior written permission.
22b528cefcSMark Murray  *
23b528cefcSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24b528cefcSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25b528cefcSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26b528cefcSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27b528cefcSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28b528cefcSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29b528cefcSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30b528cefcSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31b528cefcSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32b528cefcSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33b528cefcSMark Murray  * SUCH DAMAGE.
34b528cefcSMark Murray  */
35b528cefcSMark Murray 
36b528cefcSMark Murray #include "krb5_locl.h"
37b528cefcSMark Murray 
38ae771770SStanislav Sedov /**
39ae771770SStanislav Sedov  * Free ticket and content
40ae771770SStanislav Sedov  *
41ae771770SStanislav Sedov  * @param context a Kerberos 5 context
42ae771770SStanislav Sedov  * @param ticket ticket to free
43ae771770SStanislav Sedov  *
44ae771770SStanislav Sedov  * @return Returns 0 to indicate success.  Otherwise an kerberos et
45ae771770SStanislav Sedov  * error code is returned, see krb5_get_error_message().
46ae771770SStanislav Sedov  *
47ae771770SStanislav Sedov  * @ingroup krb5
48ae771770SStanislav Sedov  */
49b528cefcSMark Murray 
50ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_free_ticket(krb5_context context,krb5_ticket * ticket)51b528cefcSMark Murray krb5_free_ticket(krb5_context context,
52b528cefcSMark Murray 		 krb5_ticket *ticket)
53b528cefcSMark Murray {
54b528cefcSMark Murray     free_EncTicketPart(&ticket->ticket);
55b528cefcSMark Murray     krb5_free_principal(context, ticket->client);
56b528cefcSMark Murray     krb5_free_principal(context, ticket->server);
57c19800e8SDoug Rabson     free(ticket);
58b528cefcSMark Murray     return 0;
59b528cefcSMark Murray }
60b528cefcSMark Murray 
61ae771770SStanislav Sedov /**
62ae771770SStanislav Sedov  * Copy ticket and content
63ae771770SStanislav Sedov  *
64ae771770SStanislav Sedov  * @param context a Kerberos 5 context
65ae771770SStanislav Sedov  * @param from ticket to copy
66ae771770SStanislav Sedov  * @param to new copy of ticket, free with krb5_free_ticket()
67ae771770SStanislav Sedov  *
68ae771770SStanislav Sedov  * @return Returns 0 to indicate success.  Otherwise an kerberos et
69ae771770SStanislav Sedov  * error code is returned, see krb5_get_error_message().
70ae771770SStanislav Sedov  *
71ae771770SStanislav Sedov  * @ingroup krb5
72ae771770SStanislav Sedov  */
73ae771770SStanislav Sedov 
74ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_copy_ticket(krb5_context context,const krb5_ticket * from,krb5_ticket ** to)75b528cefcSMark Murray krb5_copy_ticket(krb5_context context,
76b528cefcSMark Murray 		 const krb5_ticket *from,
77b528cefcSMark Murray 		 krb5_ticket **to)
78b528cefcSMark Murray {
79b528cefcSMark Murray     krb5_error_code ret;
801c43270aSJacques Vidrine     krb5_ticket *tmp;
811c43270aSJacques Vidrine 
821c43270aSJacques Vidrine     *to = NULL;
831c43270aSJacques Vidrine     tmp = malloc(sizeof(*tmp));
84adb0ddaeSAssar Westerlund     if(tmp == NULL) {
85ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM,
86ae771770SStanislav Sedov 			       N_("malloc: out of memory", ""));
87b528cefcSMark Murray 	return ENOMEM;
88adb0ddaeSAssar Westerlund     }
89b528cefcSMark Murray     if((ret = copy_EncTicketPart(&from->ticket, &tmp->ticket))){
90b528cefcSMark Murray 	free(tmp);
91b528cefcSMark Murray 	return ret;
92b528cefcSMark Murray     }
93b528cefcSMark Murray     ret = krb5_copy_principal(context, from->client, &tmp->client);
94b528cefcSMark Murray     if(ret){
95b528cefcSMark Murray 	free_EncTicketPart(&tmp->ticket);
961c43270aSJacques Vidrine 	free(tmp);
97b528cefcSMark Murray 	return ret;
98b528cefcSMark Murray     }
991c43270aSJacques Vidrine     ret = krb5_copy_principal(context, from->server, &tmp->server);
100b528cefcSMark Murray     if(ret){
101b528cefcSMark Murray 	krb5_free_principal(context, tmp->client);
102b528cefcSMark Murray 	free_EncTicketPart(&tmp->ticket);
1031c43270aSJacques Vidrine 	free(tmp);
104b528cefcSMark Murray 	return ret;
105b528cefcSMark Murray     }
106b528cefcSMark Murray     *to = tmp;
107b528cefcSMark Murray     return 0;
108b528cefcSMark Murray }
109c19800e8SDoug Rabson 
110ae771770SStanislav Sedov /**
111ae771770SStanislav Sedov  * Return client principal in ticket
112ae771770SStanislav Sedov  *
113ae771770SStanislav Sedov  * @param context a Kerberos 5 context
114ae771770SStanislav Sedov  * @param ticket ticket to copy
115ae771770SStanislav Sedov  * @param client client principal, free with krb5_free_principal()
116ae771770SStanislav Sedov  *
117ae771770SStanislav Sedov  * @return Returns 0 to indicate success.  Otherwise an kerberos et
118ae771770SStanislav Sedov  * error code is returned, see krb5_get_error_message().
119ae771770SStanislav Sedov  *
120ae771770SStanislav Sedov  * @ingroup krb5
121ae771770SStanislav Sedov  */
122ae771770SStanislav Sedov 
123ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ticket_get_client(krb5_context context,const krb5_ticket * ticket,krb5_principal * client)124c19800e8SDoug Rabson krb5_ticket_get_client(krb5_context context,
125c19800e8SDoug Rabson 		       const krb5_ticket *ticket,
126c19800e8SDoug Rabson 		       krb5_principal *client)
127c19800e8SDoug Rabson {
128c19800e8SDoug Rabson     return krb5_copy_principal(context, ticket->client, client);
129c19800e8SDoug Rabson }
130c19800e8SDoug Rabson 
131ae771770SStanislav Sedov /**
132ae771770SStanislav Sedov  * Return server principal in ticket
133ae771770SStanislav Sedov  *
134ae771770SStanislav Sedov  * @param context a Kerberos 5 context
135ae771770SStanislav Sedov  * @param ticket ticket to copy
136ae771770SStanislav Sedov  * @param server server principal, free with krb5_free_principal()
137ae771770SStanislav Sedov  *
138ae771770SStanislav Sedov  * @return Returns 0 to indicate success.  Otherwise an kerberos et
139ae771770SStanislav Sedov  * error code is returned, see krb5_get_error_message().
140ae771770SStanislav Sedov  *
141ae771770SStanislav Sedov  * @ingroup krb5
142ae771770SStanislav Sedov  */
143ae771770SStanislav Sedov 
144ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ticket_get_server(krb5_context context,const krb5_ticket * ticket,krb5_principal * server)145c19800e8SDoug Rabson krb5_ticket_get_server(krb5_context context,
146c19800e8SDoug Rabson 		       const krb5_ticket *ticket,
147c19800e8SDoug Rabson 		       krb5_principal *server)
148c19800e8SDoug Rabson {
149c19800e8SDoug Rabson     return krb5_copy_principal(context, ticket->server, server);
150c19800e8SDoug Rabson }
151c19800e8SDoug Rabson 
152ae771770SStanislav Sedov /**
153ae771770SStanislav Sedov  * Return end time of ticket
154ae771770SStanislav Sedov  *
155ae771770SStanislav Sedov  * @param context a Kerberos 5 context
156ae771770SStanislav Sedov  * @param ticket ticket to copy
157ae771770SStanislav Sedov  *
158ae771770SStanislav Sedov  * @return end time of ticket
159ae771770SStanislav Sedov  *
160ae771770SStanislav Sedov  * @ingroup krb5
161ae771770SStanislav Sedov  */
162ae771770SStanislav Sedov 
163ae771770SStanislav Sedov KRB5_LIB_FUNCTION time_t KRB5_LIB_CALL
krb5_ticket_get_endtime(krb5_context context,const krb5_ticket * ticket)164c19800e8SDoug Rabson krb5_ticket_get_endtime(krb5_context context,
165c19800e8SDoug Rabson 			const krb5_ticket *ticket)
166c19800e8SDoug Rabson {
167c19800e8SDoug Rabson     return ticket->ticket.endtime;
168c19800e8SDoug Rabson }
169c19800e8SDoug Rabson 
170ae771770SStanislav Sedov /**
171ae771770SStanislav Sedov  * Get the flags from the Kerberos ticket
172ae771770SStanislav Sedov  *
173ae771770SStanislav Sedov  * @param context Kerberos context
174ae771770SStanislav Sedov  * @param ticket Kerberos ticket
175ae771770SStanislav Sedov  *
176ae771770SStanislav Sedov  * @return ticket flags
177ae771770SStanislav Sedov  *
178ae771770SStanislav Sedov  * @ingroup krb5_ticket
179ae771770SStanislav Sedov  */
180ae771770SStanislav Sedov KRB5_LIB_FUNCTION unsigned long KRB5_LIB_CALL
krb5_ticket_get_flags(krb5_context context,const krb5_ticket * ticket)181ae771770SStanislav Sedov krb5_ticket_get_flags(krb5_context context,
182ae771770SStanislav Sedov 		      const krb5_ticket *ticket)
183ae771770SStanislav Sedov {
184ae771770SStanislav Sedov     return TicketFlags2int(ticket->ticket.flags);
185ae771770SStanislav Sedov }
186ae771770SStanislav Sedov 
187c19800e8SDoug Rabson static int
find_type_in_ad(krb5_context context,int type,krb5_data * data,krb5_boolean * found,krb5_boolean failp,krb5_keyblock * sessionkey,const AuthorizationData * ad,int level)188c19800e8SDoug Rabson find_type_in_ad(krb5_context context,
189c19800e8SDoug Rabson 		int type,
190c19800e8SDoug Rabson 		krb5_data *data,
191c19800e8SDoug Rabson 		krb5_boolean *found,
192c19800e8SDoug Rabson 		krb5_boolean failp,
193c19800e8SDoug Rabson 		krb5_keyblock *sessionkey,
194c19800e8SDoug Rabson 		const AuthorizationData *ad,
195c19800e8SDoug Rabson 		int level)
196c19800e8SDoug Rabson {
197c19800e8SDoug Rabson     krb5_error_code ret = 0;
198ae771770SStanislav Sedov     size_t i;
199c19800e8SDoug Rabson 
200c19800e8SDoug Rabson     if (level > 9) {
201c19800e8SDoug Rabson 	ret = ENOENT; /* XXX */
202ae771770SStanislav Sedov 	krb5_set_error_message(context, ret,
203ae771770SStanislav Sedov 			       N_("Authorization data nested deeper "
204ae771770SStanislav Sedov 				  "then %d levels, stop searching", ""),
205ae771770SStanislav Sedov 			       level);
206c19800e8SDoug Rabson 	goto out;
207c19800e8SDoug Rabson     }
208c19800e8SDoug Rabson 
209c19800e8SDoug Rabson     /*
210c19800e8SDoug Rabson      * Only copy out the element the first time we get to it, we need
211c19800e8SDoug Rabson      * to run over the whole authorization data fields to check if
212c19800e8SDoug Rabson      * there are any container clases we need to care about.
213c19800e8SDoug Rabson      */
214c19800e8SDoug Rabson     for (i = 0; i < ad->len; i++) {
215c19800e8SDoug Rabson 	if (!*found && ad->val[i].ad_type == type) {
216c19800e8SDoug Rabson 	    ret = der_copy_octet_string(&ad->val[i].ad_data, data);
217c19800e8SDoug Rabson 	    if (ret) {
218ae771770SStanislav Sedov 		krb5_set_error_message(context, ret,
219ae771770SStanislav Sedov 				       N_("malloc: out of memory", ""));
220c19800e8SDoug Rabson 		goto out;
221c19800e8SDoug Rabson 	    }
222c19800e8SDoug Rabson 	    *found = TRUE;
223c19800e8SDoug Rabson 	    continue;
224c19800e8SDoug Rabson 	}
225c19800e8SDoug Rabson 	switch (ad->val[i].ad_type) {
226c19800e8SDoug Rabson 	case KRB5_AUTHDATA_IF_RELEVANT: {
227c19800e8SDoug Rabson 	    AuthorizationData child;
228c19800e8SDoug Rabson 	    ret = decode_AuthorizationData(ad->val[i].ad_data.data,
229c19800e8SDoug Rabson 					   ad->val[i].ad_data.length,
230c19800e8SDoug Rabson 					   &child,
231c19800e8SDoug Rabson 					   NULL);
232c19800e8SDoug Rabson 	    if (ret) {
233ae771770SStanislav Sedov 		krb5_set_error_message(context, ret,
234ae771770SStanislav Sedov 				       N_("Failed to decode "
235ae771770SStanislav Sedov 					  "IF_RELEVANT with %d", ""),
236ae771770SStanislav Sedov 				       (int)ret);
237c19800e8SDoug Rabson 		goto out;
238c19800e8SDoug Rabson 	    }
239c19800e8SDoug Rabson 	    ret = find_type_in_ad(context, type, data, found, FALSE,
240c19800e8SDoug Rabson 				  sessionkey, &child, level + 1);
241c19800e8SDoug Rabson 	    free_AuthorizationData(&child);
242c19800e8SDoug Rabson 	    if (ret)
243c19800e8SDoug Rabson 		goto out;
244c19800e8SDoug Rabson 	    break;
245c19800e8SDoug Rabson 	}
246c19800e8SDoug Rabson #if 0 /* XXX test */
247c19800e8SDoug Rabson 	case KRB5_AUTHDATA_KDC_ISSUED: {
248c19800e8SDoug Rabson 	    AD_KDCIssued child;
249c19800e8SDoug Rabson 
250c19800e8SDoug Rabson 	    ret = decode_AD_KDCIssued(ad->val[i].ad_data.data,
251c19800e8SDoug Rabson 				      ad->val[i].ad_data.length,
252c19800e8SDoug Rabson 				      &child,
253c19800e8SDoug Rabson 				      NULL);
254c19800e8SDoug Rabson 	    if (ret) {
255ae771770SStanislav Sedov 		krb5_set_error_message(context, ret,
256ae771770SStanislav Sedov 				       N_("Failed to decode "
257ae771770SStanislav Sedov 					  "AD_KDCIssued with %d", ""),
258ae771770SStanislav Sedov 				       ret);
259c19800e8SDoug Rabson 		goto out;
260c19800e8SDoug Rabson 	    }
261c19800e8SDoug Rabson 	    if (failp) {
262c19800e8SDoug Rabson 		krb5_boolean valid;
263c19800e8SDoug Rabson 		krb5_data buf;
264c19800e8SDoug Rabson 		size_t len;
265c19800e8SDoug Rabson 
266c19800e8SDoug Rabson 		ASN1_MALLOC_ENCODE(AuthorizationData, buf.data, buf.length,
267c19800e8SDoug Rabson 				   &child.elements, &len, ret);
268c19800e8SDoug Rabson 		if (ret) {
269c19800e8SDoug Rabson 		    free_AD_KDCIssued(&child);
270ae771770SStanislav Sedov 		    krb5_clear_error_message(context);
271c19800e8SDoug Rabson 		    goto out;
272c19800e8SDoug Rabson 		}
273c19800e8SDoug Rabson 		if(buf.length != len)
274c19800e8SDoug Rabson 		    krb5_abortx(context, "internal error in ASN.1 encoder");
275c19800e8SDoug Rabson 
276c19800e8SDoug Rabson 		ret = krb5_c_verify_checksum(context, sessionkey, 19, &buf,
277c19800e8SDoug Rabson 					     &child.ad_checksum, &valid);
278c19800e8SDoug Rabson 		krb5_data_free(&buf);
279c19800e8SDoug Rabson 		if (ret) {
280c19800e8SDoug Rabson 		    free_AD_KDCIssued(&child);
281c19800e8SDoug Rabson 		    goto out;
282c19800e8SDoug Rabson 		}
283c19800e8SDoug Rabson 		if (!valid) {
284ae771770SStanislav Sedov 		    krb5_clear_error_message(context);
285c19800e8SDoug Rabson 		    ret = ENOENT;
286c19800e8SDoug Rabson 		    free_AD_KDCIssued(&child);
287c19800e8SDoug Rabson 		    goto out;
288c19800e8SDoug Rabson 		}
289c19800e8SDoug Rabson 	    }
290c19800e8SDoug Rabson 	    ret = find_type_in_ad(context, type, data, found, failp, sessionkey,
291c19800e8SDoug Rabson 				  &child.elements, level + 1);
292c19800e8SDoug Rabson 	    free_AD_KDCIssued(&child);
293c19800e8SDoug Rabson 	    if (ret)
294c19800e8SDoug Rabson 		goto out;
295c19800e8SDoug Rabson 	    break;
296c19800e8SDoug Rabson 	}
297c19800e8SDoug Rabson #endif
298c19800e8SDoug Rabson 	case KRB5_AUTHDATA_AND_OR:
299c19800e8SDoug Rabson 	    if (!failp)
300c19800e8SDoug Rabson 		break;
301c19800e8SDoug Rabson 	    ret = ENOENT; /* XXX */
302ae771770SStanislav Sedov 	    krb5_set_error_message(context, ret,
303ae771770SStanislav Sedov 				   N_("Authorization data contains "
304ae771770SStanislav Sedov 				      "AND-OR element that is unknown to the "
305ae771770SStanislav Sedov 				      "application", ""));
306c19800e8SDoug Rabson 	    goto out;
307c19800e8SDoug Rabson 	default:
308c19800e8SDoug Rabson 	    if (!failp)
309c19800e8SDoug Rabson 		break;
310c19800e8SDoug Rabson 	    ret = ENOENT; /* XXX */
311ae771770SStanislav Sedov 	    krb5_set_error_message(context, ret,
312ae771770SStanislav Sedov 				   N_("Authorization data contains "
313ae771770SStanislav Sedov 				      "unknown type (%d) ", ""),
314ae771770SStanislav Sedov 				   ad->val[i].ad_type);
315c19800e8SDoug Rabson 	    goto out;
316c19800e8SDoug Rabson 	}
317c19800e8SDoug Rabson     }
318c19800e8SDoug Rabson out:
319c19800e8SDoug Rabson     if (ret) {
320c19800e8SDoug Rabson 	if (*found) {
321c19800e8SDoug Rabson 	    krb5_data_free(data);
322c19800e8SDoug Rabson 	    *found = 0;
323c19800e8SDoug Rabson 	}
324c19800e8SDoug Rabson     }
325c19800e8SDoug Rabson     return ret;
326c19800e8SDoug Rabson }
327c19800e8SDoug Rabson 
328ae771770SStanislav Sedov /**
329ae771770SStanislav Sedov  * Extract the authorization data type of type from the ticket. Store
330ae771770SStanislav Sedov  * the field in data. This function is to use for kerberos
331ae771770SStanislav Sedov  * applications.
332ae771770SStanislav Sedov  *
333ae771770SStanislav Sedov  * @param context a Kerberos 5 context
334ae771770SStanislav Sedov  * @param ticket Kerberos ticket
335ae771770SStanislav Sedov  * @param type type to fetch
336ae771770SStanislav Sedov  * @param data returned data, free with krb5_data_free()
337ae771770SStanislav Sedov  *
338ae771770SStanislav Sedov  * @ingroup krb5
339c19800e8SDoug Rabson  */
340c19800e8SDoug Rabson 
341ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ticket_get_authorization_data_type(krb5_context context,krb5_ticket * ticket,int type,krb5_data * data)342c19800e8SDoug Rabson krb5_ticket_get_authorization_data_type(krb5_context context,
343c19800e8SDoug Rabson 					krb5_ticket *ticket,
344c19800e8SDoug Rabson 					int type,
345c19800e8SDoug Rabson 					krb5_data *data)
346c19800e8SDoug Rabson {
347c19800e8SDoug Rabson     AuthorizationData *ad;
348c19800e8SDoug Rabson     krb5_error_code ret;
349c19800e8SDoug Rabson     krb5_boolean found = FALSE;
350c19800e8SDoug Rabson 
351c19800e8SDoug Rabson     krb5_data_zero(data);
352c19800e8SDoug Rabson 
353c19800e8SDoug Rabson     ad = ticket->ticket.authorization_data;
354c19800e8SDoug Rabson     if (ticket->ticket.authorization_data == NULL) {
355ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOENT,
356ae771770SStanislav Sedov 			       N_("Ticket have not authorization data", ""));
357c19800e8SDoug Rabson 	return ENOENT; /* XXX */
358c19800e8SDoug Rabson     }
359c19800e8SDoug Rabson 
360c19800e8SDoug Rabson     ret = find_type_in_ad(context, type, data, &found, TRUE,
361c19800e8SDoug Rabson 			  &ticket->ticket.key, ad, 0);
362c19800e8SDoug Rabson     if (ret)
363c19800e8SDoug Rabson 	return ret;
364c19800e8SDoug Rabson     if (!found) {
365ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOENT,
366ae771770SStanislav Sedov 			       N_("Ticket have not "
367ae771770SStanislav Sedov 				  "authorization data of type %d", ""),
368ae771770SStanislav Sedov 			       type);
369c19800e8SDoug Rabson 	return ENOENT; /* XXX */
370c19800e8SDoug Rabson     }
371c19800e8SDoug Rabson     return 0;
372c19800e8SDoug Rabson }
373ae771770SStanislav Sedov 
374ae771770SStanislav Sedov static krb5_error_code
check_server_referral(krb5_context context,krb5_kdc_rep * rep,unsigned flags,krb5_const_principal requested,krb5_const_principal returned,krb5_keyblock * key)375ae771770SStanislav Sedov check_server_referral(krb5_context context,
376ae771770SStanislav Sedov 		      krb5_kdc_rep *rep,
377ae771770SStanislav Sedov 		      unsigned flags,
378ae771770SStanislav Sedov 		      krb5_const_principal requested,
379ae771770SStanislav Sedov 		      krb5_const_principal returned,
380ae771770SStanislav Sedov 		      krb5_keyblock * key)
381ae771770SStanislav Sedov {
382ae771770SStanislav Sedov     krb5_error_code ret;
383ae771770SStanislav Sedov     PA_ServerReferralData ref;
384ae771770SStanislav Sedov     krb5_crypto session;
385ae771770SStanislav Sedov     EncryptedData ed;
386ae771770SStanislav Sedov     size_t len;
387ae771770SStanislav Sedov     krb5_data data;
388ae771770SStanislav Sedov     PA_DATA *pa;
389ae771770SStanislav Sedov     int i = 0, cmp;
390ae771770SStanislav Sedov 
391ae771770SStanislav Sedov     if (rep->kdc_rep.padata == NULL)
392ae771770SStanislav Sedov 	goto noreferral;
393ae771770SStanislav Sedov 
394ae771770SStanislav Sedov     pa = krb5_find_padata(rep->kdc_rep.padata->val,
395ae771770SStanislav Sedov 			  rep->kdc_rep.padata->len,
396ae771770SStanislav Sedov 			  KRB5_PADATA_SERVER_REFERRAL, &i);
397ae771770SStanislav Sedov     if (pa == NULL)
398ae771770SStanislav Sedov 	goto noreferral;
399ae771770SStanislav Sedov 
400ae771770SStanislav Sedov     memset(&ed, 0, sizeof(ed));
401ae771770SStanislav Sedov     memset(&ref, 0, sizeof(ref));
402ae771770SStanislav Sedov 
403ae771770SStanislav Sedov     ret = decode_EncryptedData(pa->padata_value.data,
404ae771770SStanislav Sedov 			       pa->padata_value.length,
405ae771770SStanislav Sedov 			       &ed, &len);
406ae771770SStanislav Sedov     if (ret)
407ae771770SStanislav Sedov 	return ret;
408ae771770SStanislav Sedov     if (len != pa->padata_value.length) {
409ae771770SStanislav Sedov 	free_EncryptedData(&ed);
410ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
411ae771770SStanislav Sedov 			       N_("Referral EncryptedData wrong for realm %s",
412ae771770SStanislav Sedov 				  "realm"), requested->realm);
413ae771770SStanislav Sedov 	return KRB5KRB_AP_ERR_MODIFIED;
414ae771770SStanislav Sedov     }
415ae771770SStanislav Sedov 
416ae771770SStanislav Sedov     ret = krb5_crypto_init(context, key, 0, &session);
417ae771770SStanislav Sedov     if (ret) {
418ae771770SStanislav Sedov 	free_EncryptedData(&ed);
419ae771770SStanislav Sedov 	return ret;
420ae771770SStanislav Sedov     }
421ae771770SStanislav Sedov 
422ae771770SStanislav Sedov     ret = krb5_decrypt_EncryptedData(context, session,
423ae771770SStanislav Sedov 				     KRB5_KU_PA_SERVER_REFERRAL,
424ae771770SStanislav Sedov 				     &ed, &data);
425ae771770SStanislav Sedov     free_EncryptedData(&ed);
426ae771770SStanislav Sedov     krb5_crypto_destroy(context, session);
427ae771770SStanislav Sedov     if (ret)
428ae771770SStanislav Sedov 	return ret;
429ae771770SStanislav Sedov 
430ae771770SStanislav Sedov     ret = decode_PA_ServerReferralData(data.data, data.length, &ref, &len);
431ae771770SStanislav Sedov     if (ret) {
432ae771770SStanislav Sedov 	krb5_data_free(&data);
433ae771770SStanislav Sedov 	return ret;
434ae771770SStanislav Sedov     }
435ae771770SStanislav Sedov     krb5_data_free(&data);
436ae771770SStanislav Sedov 
437ae771770SStanislav Sedov     if (strcmp(requested->realm, returned->realm) != 0) {
438ae771770SStanislav Sedov 	free_PA_ServerReferralData(&ref);
439ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
440ae771770SStanislav Sedov 			       N_("server ref realm mismatch, "
441ae771770SStanislav Sedov 				  "requested realm %s got back %s", ""),
442ae771770SStanislav Sedov 			       requested->realm, returned->realm);
443ae771770SStanislav Sedov 	return KRB5KRB_AP_ERR_MODIFIED;
444ae771770SStanislav Sedov     }
445ae771770SStanislav Sedov 
446ae771770SStanislav Sedov     if (krb5_principal_is_krbtgt(context, returned)) {
447ae771770SStanislav Sedov 	const char *realm = returned->name.name_string.val[1];
448ae771770SStanislav Sedov 
449ae771770SStanislav Sedov 	if (ref.referred_realm == NULL
450ae771770SStanislav Sedov 	    || strcmp(*ref.referred_realm, realm) != 0)
451ae771770SStanislav Sedov 	{
452ae771770SStanislav Sedov 	    free_PA_ServerReferralData(&ref);
453ae771770SStanislav Sedov 	    krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
454ae771770SStanislav Sedov 				   N_("tgt returned with wrong ref", ""));
455ae771770SStanislav Sedov 	    return KRB5KRB_AP_ERR_MODIFIED;
456ae771770SStanislav Sedov 	}
457ae771770SStanislav Sedov     } else if (krb5_principal_compare(context, returned, requested) == 0) {
458ae771770SStanislav Sedov 	free_PA_ServerReferralData(&ref);
459ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
460ae771770SStanislav Sedov 			       N_("req princ no same as returned", ""));
461ae771770SStanislav Sedov 	return KRB5KRB_AP_ERR_MODIFIED;
462ae771770SStanislav Sedov     }
463ae771770SStanislav Sedov 
464ae771770SStanislav Sedov     if (ref.requested_principal_name) {
465ae771770SStanislav Sedov 	cmp = _krb5_principal_compare_PrincipalName(context,
466ae771770SStanislav Sedov 						    requested,
467ae771770SStanislav Sedov 						    ref.requested_principal_name);
468ae771770SStanislav Sedov 	if (!cmp) {
469ae771770SStanislav Sedov 	    free_PA_ServerReferralData(&ref);
470ae771770SStanislav Sedov 	    krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
471ae771770SStanislav Sedov 				   N_("referred principal not same "
472ae771770SStanislav Sedov 				      "as requested", ""));
473ae771770SStanislav Sedov 	    return KRB5KRB_AP_ERR_MODIFIED;
474ae771770SStanislav Sedov 	}
475ae771770SStanislav Sedov     } else if (flags & EXTRACT_TICKET_AS_REQ) {
476ae771770SStanislav Sedov 	free_PA_ServerReferralData(&ref);
477ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
478ae771770SStanislav Sedov 			       N_("Requested principal missing on AS-REQ", ""));
479ae771770SStanislav Sedov 	return KRB5KRB_AP_ERR_MODIFIED;
480ae771770SStanislav Sedov     }
481ae771770SStanislav Sedov 
482ae771770SStanislav Sedov     free_PA_ServerReferralData(&ref);
483ae771770SStanislav Sedov 
484ae771770SStanislav Sedov     return ret;
485ae771770SStanislav Sedov noreferral:
486ae771770SStanislav Sedov     /*
487ae771770SStanislav Sedov      * Expect excact match or that we got a krbtgt
488ae771770SStanislav Sedov      */
489ae771770SStanislav Sedov     if (krb5_principal_compare(context, requested, returned) != TRUE &&
490ae771770SStanislav Sedov 	(krb5_realm_compare(context, requested, returned) != TRUE &&
491ae771770SStanislav Sedov 	 krb5_principal_is_krbtgt(context, returned) != TRUE))
492ae771770SStanislav Sedov     {
493ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
494ae771770SStanislav Sedov 			       N_("Not same server principal returned "
495ae771770SStanislav Sedov 				  "as requested", ""));
496ae771770SStanislav Sedov 	return KRB5KRB_AP_ERR_MODIFIED;
497ae771770SStanislav Sedov     }
498ae771770SStanislav Sedov     return 0;
499ae771770SStanislav Sedov }
500ae771770SStanislav Sedov 
501ae771770SStanislav Sedov 
502ae771770SStanislav Sedov /*
503ae771770SStanislav Sedov  * Verify referral data
504ae771770SStanislav Sedov  */
505ae771770SStanislav Sedov 
506ae771770SStanislav Sedov 
507ae771770SStanislav Sedov static krb5_error_code
check_client_referral(krb5_context context,krb5_kdc_rep * rep,krb5_const_principal requested,krb5_const_principal mapped,krb5_keyblock const * key)508ae771770SStanislav Sedov check_client_referral(krb5_context context,
509ae771770SStanislav Sedov 		      krb5_kdc_rep *rep,
510ae771770SStanislav Sedov 		      krb5_const_principal requested,
511ae771770SStanislav Sedov 		      krb5_const_principal mapped,
512ae771770SStanislav Sedov 		      krb5_keyblock const * key)
513ae771770SStanislav Sedov {
514ae771770SStanislav Sedov     krb5_error_code ret;
515ae771770SStanislav Sedov     PA_ClientCanonicalized canon;
516ae771770SStanislav Sedov     krb5_crypto crypto;
517ae771770SStanislav Sedov     krb5_data data;
518ae771770SStanislav Sedov     PA_DATA *pa;
519ae771770SStanislav Sedov     size_t len;
520ae771770SStanislav Sedov     int i = 0;
521ae771770SStanislav Sedov 
522ae771770SStanislav Sedov     if (rep->kdc_rep.padata == NULL)
523ae771770SStanislav Sedov 	goto noreferral;
524ae771770SStanislav Sedov 
525ae771770SStanislav Sedov     pa = krb5_find_padata(rep->kdc_rep.padata->val,
526ae771770SStanislav Sedov 			  rep->kdc_rep.padata->len,
527ae771770SStanislav Sedov 			  KRB5_PADATA_CLIENT_CANONICALIZED, &i);
528ae771770SStanislav Sedov     if (pa == NULL)
529ae771770SStanislav Sedov 	goto noreferral;
530ae771770SStanislav Sedov 
531ae771770SStanislav Sedov     ret = decode_PA_ClientCanonicalized(pa->padata_value.data,
532ae771770SStanislav Sedov 					pa->padata_value.length,
533ae771770SStanislav Sedov 					&canon, &len);
534ae771770SStanislav Sedov     if (ret) {
535ae771770SStanislav Sedov 	krb5_set_error_message(context, ret,
536ae771770SStanislav Sedov 			       N_("Failed to decode ClientCanonicalized "
537ae771770SStanislav Sedov 				  "from realm %s", ""), requested->realm);
538ae771770SStanislav Sedov 	return ret;
539ae771770SStanislav Sedov     }
540ae771770SStanislav Sedov 
541ae771770SStanislav Sedov     ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length,
542ae771770SStanislav Sedov 		       &canon.names, &len, ret);
543ae771770SStanislav Sedov     if (ret) {
544ae771770SStanislav Sedov 	free_PA_ClientCanonicalized(&canon);
545ae771770SStanislav Sedov 	return ret;
546ae771770SStanislav Sedov     }
547ae771770SStanislav Sedov     if (data.length != len)
548ae771770SStanislav Sedov 	krb5_abortx(context, "internal asn.1 error");
549ae771770SStanislav Sedov 
550ae771770SStanislav Sedov     ret = krb5_crypto_init(context, key, 0, &crypto);
551ae771770SStanislav Sedov     if (ret) {
552ae771770SStanislav Sedov 	free(data.data);
553ae771770SStanislav Sedov 	free_PA_ClientCanonicalized(&canon);
554ae771770SStanislav Sedov 	return ret;
555ae771770SStanislav Sedov     }
556ae771770SStanislav Sedov 
557ae771770SStanislav Sedov     ret = krb5_verify_checksum(context, crypto, KRB5_KU_CANONICALIZED_NAMES,
558ae771770SStanislav Sedov 			       data.data, data.length,
559ae771770SStanislav Sedov 			       &canon.canon_checksum);
560ae771770SStanislav Sedov     krb5_crypto_destroy(context, crypto);
561ae771770SStanislav Sedov     free(data.data);
562ae771770SStanislav Sedov     if (ret) {
563ae771770SStanislav Sedov 	krb5_set_error_message(context, ret,
564ae771770SStanislav Sedov 			       N_("Failed to verify client canonicalized "
565ae771770SStanislav Sedov 				  "data from realm %s", ""),
566ae771770SStanislav Sedov 			       requested->realm);
567ae771770SStanislav Sedov 	free_PA_ClientCanonicalized(&canon);
568ae771770SStanislav Sedov 	return ret;
569ae771770SStanislav Sedov     }
570ae771770SStanislav Sedov 
571ae771770SStanislav Sedov     if (!_krb5_principal_compare_PrincipalName(context,
572ae771770SStanislav Sedov 					       requested,
573ae771770SStanislav Sedov 					       &canon.names.requested_name))
574ae771770SStanislav Sedov     {
575ae771770SStanislav Sedov 	free_PA_ClientCanonicalized(&canon);
576ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_PRINC_NOMATCH,
577ae771770SStanislav Sedov 			       N_("Requested name doesn't match"
578ae771770SStanislav Sedov 				  " in client referral", ""));
579ae771770SStanislav Sedov 	return KRB5_PRINC_NOMATCH;
580ae771770SStanislav Sedov     }
581ae771770SStanislav Sedov     if (!_krb5_principal_compare_PrincipalName(context,
582ae771770SStanislav Sedov 					       mapped,
583ae771770SStanislav Sedov 					       &canon.names.mapped_name))
584ae771770SStanislav Sedov     {
585ae771770SStanislav Sedov 	free_PA_ClientCanonicalized(&canon);
586ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_PRINC_NOMATCH,
587ae771770SStanislav Sedov 			       N_("Mapped name doesn't match"
588ae771770SStanislav Sedov 				  " in client referral", ""));
589ae771770SStanislav Sedov 	return KRB5_PRINC_NOMATCH;
590ae771770SStanislav Sedov     }
591ae771770SStanislav Sedov 
592ae771770SStanislav Sedov     return 0;
593ae771770SStanislav Sedov 
594ae771770SStanislav Sedov noreferral:
595ae771770SStanislav Sedov     if (krb5_principal_compare(context, requested, mapped) == FALSE) {
596ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
597ae771770SStanislav Sedov 			       N_("Not same client principal returned "
598ae771770SStanislav Sedov 				  "as requested", ""));
599ae771770SStanislav Sedov 	return KRB5KRB_AP_ERR_MODIFIED;
600ae771770SStanislav Sedov     }
601ae771770SStanislav Sedov     return 0;
602ae771770SStanislav Sedov }
603ae771770SStanislav Sedov 
604ae771770SStanislav Sedov 
605ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
decrypt_tkt(krb5_context context,krb5_keyblock * key,krb5_key_usage usage,krb5_const_pointer decrypt_arg,krb5_kdc_rep * dec_rep)606ae771770SStanislav Sedov decrypt_tkt (krb5_context context,
607ae771770SStanislav Sedov 	     krb5_keyblock *key,
608ae771770SStanislav Sedov 	     krb5_key_usage usage,
609ae771770SStanislav Sedov 	     krb5_const_pointer decrypt_arg,
610ae771770SStanislav Sedov 	     krb5_kdc_rep *dec_rep)
611ae771770SStanislav Sedov {
612ae771770SStanislav Sedov     krb5_error_code ret;
613ae771770SStanislav Sedov     krb5_data data;
614ae771770SStanislav Sedov     size_t size;
615ae771770SStanislav Sedov     krb5_crypto crypto;
616ae771770SStanislav Sedov 
617ae771770SStanislav Sedov     ret = krb5_crypto_init(context, key, 0, &crypto);
618ae771770SStanislav Sedov     if (ret)
619ae771770SStanislav Sedov 	return ret;
620ae771770SStanislav Sedov 
621ae771770SStanislav Sedov     ret = krb5_decrypt_EncryptedData (context,
622ae771770SStanislav Sedov 				      crypto,
623ae771770SStanislav Sedov 				      usage,
624ae771770SStanislav Sedov 				      &dec_rep->kdc_rep.enc_part,
625ae771770SStanislav Sedov 				      &data);
626ae771770SStanislav Sedov     krb5_crypto_destroy(context, crypto);
627ae771770SStanislav Sedov 
628ae771770SStanislav Sedov     if (ret)
629ae771770SStanislav Sedov 	return ret;
630ae771770SStanislav Sedov 
631ae771770SStanislav Sedov     ret = decode_EncASRepPart(data.data,
632ae771770SStanislav Sedov 			      data.length,
633ae771770SStanislav Sedov 			      &dec_rep->enc_part,
634ae771770SStanislav Sedov 			      &size);
635ae771770SStanislav Sedov     if (ret)
636ae771770SStanislav Sedov 	ret = decode_EncTGSRepPart(data.data,
637ae771770SStanislav Sedov 				   data.length,
638ae771770SStanislav Sedov 				   &dec_rep->enc_part,
639ae771770SStanislav Sedov 				   &size);
640ae771770SStanislav Sedov     krb5_data_free (&data);
641ae771770SStanislav Sedov     if (ret) {
642ae771770SStanislav Sedov         krb5_set_error_message(context, ret,
643ae771770SStanislav Sedov 			       N_("Failed to decode encpart in ticket", ""));
644ae771770SStanislav Sedov 	return ret;
645ae771770SStanislav Sedov     }
646ae771770SStanislav Sedov     return 0;
647ae771770SStanislav Sedov }
648ae771770SStanislav Sedov 
649ae771770SStanislav Sedov int
_krb5_extract_ticket(krb5_context context,krb5_kdc_rep * rep,krb5_creds * creds,krb5_keyblock * key,krb5_const_pointer keyseed,krb5_key_usage key_usage,krb5_addresses * addrs,unsigned nonce,unsigned flags,krb5_decrypt_proc decrypt_proc,krb5_const_pointer decryptarg)650ae771770SStanislav Sedov _krb5_extract_ticket(krb5_context context,
651ae771770SStanislav Sedov 		     krb5_kdc_rep *rep,
652ae771770SStanislav Sedov 		     krb5_creds *creds,
653ae771770SStanislav Sedov 		     krb5_keyblock *key,
654ae771770SStanislav Sedov 		     krb5_const_pointer keyseed,
655ae771770SStanislav Sedov 		     krb5_key_usage key_usage,
656ae771770SStanislav Sedov 		     krb5_addresses *addrs,
657ae771770SStanislav Sedov 		     unsigned nonce,
658ae771770SStanislav Sedov 		     unsigned flags,
659ae771770SStanislav Sedov 		     krb5_decrypt_proc decrypt_proc,
660ae771770SStanislav Sedov 		     krb5_const_pointer decryptarg)
661ae771770SStanislav Sedov {
662ae771770SStanislav Sedov     krb5_error_code ret;
663ae771770SStanislav Sedov     krb5_principal tmp_principal;
664ae771770SStanislav Sedov     size_t len = 0;
665ae771770SStanislav Sedov     time_t tmp_time;
666ae771770SStanislav Sedov     krb5_timestamp sec_now;
667ae771770SStanislav Sedov 
668ae771770SStanislav Sedov     /* decrypt */
669ae771770SStanislav Sedov 
670ae771770SStanislav Sedov     if (decrypt_proc == NULL)
671ae771770SStanislav Sedov 	decrypt_proc = decrypt_tkt;
672ae771770SStanislav Sedov 
673ae771770SStanislav Sedov     ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep);
674ae771770SStanislav Sedov     if (ret)
675ae771770SStanislav Sedov 	goto out;
676ae771770SStanislav Sedov 
677ae771770SStanislav Sedov     /* save session key */
678ae771770SStanislav Sedov 
679ae771770SStanislav Sedov     creds->session.keyvalue.length = 0;
680ae771770SStanislav Sedov     creds->session.keyvalue.data   = NULL;
681ae771770SStanislav Sedov     creds->session.keytype = rep->enc_part.key.keytype;
682ae771770SStanislav Sedov     ret = krb5_data_copy (&creds->session.keyvalue,
683ae771770SStanislav Sedov 			  rep->enc_part.key.keyvalue.data,
684ae771770SStanislav Sedov 			  rep->enc_part.key.keyvalue.length);
685ae771770SStanislav Sedov     if (ret) {
686ae771770SStanislav Sedov 	krb5_clear_error_message(context);
687ae771770SStanislav Sedov 	goto out;
688ae771770SStanislav Sedov     }
689ae771770SStanislav Sedov 
690ae771770SStanislav Sedov     /* compare client and save */
691ae771770SStanislav Sedov     ret = _krb5_principalname2krb5_principal (context,
692ae771770SStanislav Sedov 					      &tmp_principal,
693ae771770SStanislav Sedov 					      rep->kdc_rep.cname,
694ae771770SStanislav Sedov 					      rep->kdc_rep.crealm);
695ae771770SStanislav Sedov     if (ret)
696ae771770SStanislav Sedov 	goto out;
697ae771770SStanislav Sedov 
698ae771770SStanislav Sedov     /* check client referral and save principal */
699ae771770SStanislav Sedov     /* anonymous here ? */
700ae771770SStanislav Sedov     if((flags & EXTRACT_TICKET_ALLOW_CNAME_MISMATCH) == 0) {
701ae771770SStanislav Sedov 	ret = check_client_referral(context, rep,
702ae771770SStanislav Sedov 				    creds->client,
703ae771770SStanislav Sedov 				    tmp_principal,
704ae771770SStanislav Sedov 				    &creds->session);
705ae771770SStanislav Sedov 	if (ret) {
706ae771770SStanislav Sedov 	    krb5_free_principal (context, tmp_principal);
707ae771770SStanislav Sedov 	    goto out;
708ae771770SStanislav Sedov 	}
709ae771770SStanislav Sedov     }
710ae771770SStanislav Sedov     krb5_free_principal (context, creds->client);
711ae771770SStanislav Sedov     creds->client = tmp_principal;
712ae771770SStanislav Sedov 
713ae771770SStanislav Sedov     /* check server referral and save principal */
714ae771770SStanislav Sedov     ret = _krb5_principalname2krb5_principal (context,
715ae771770SStanislav Sedov 					      &tmp_principal,
716*49426905SXin LI 					      rep->enc_part.sname,
717*49426905SXin LI 					      rep->enc_part.srealm);
718ae771770SStanislav Sedov     if (ret)
719ae771770SStanislav Sedov 	goto out;
720ae771770SStanislav Sedov     if((flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH) == 0){
721ae771770SStanislav Sedov 	ret = check_server_referral(context,
722ae771770SStanislav Sedov 				    rep,
723ae771770SStanislav Sedov 				    flags,
724ae771770SStanislav Sedov 				    creds->server,
725ae771770SStanislav Sedov 				    tmp_principal,
726ae771770SStanislav Sedov 				    &creds->session);
727ae771770SStanislav Sedov 	if (ret) {
728ae771770SStanislav Sedov 	    krb5_free_principal (context, tmp_principal);
729ae771770SStanislav Sedov 	    goto out;
730ae771770SStanislav Sedov 	}
731ae771770SStanislav Sedov     }
732ae771770SStanislav Sedov     krb5_free_principal(context, creds->server);
733ae771770SStanislav Sedov     creds->server = tmp_principal;
734ae771770SStanislav Sedov 
735ae771770SStanislav Sedov     /* verify names */
736ae771770SStanislav Sedov     if(flags & EXTRACT_TICKET_MATCH_REALM){
737ae771770SStanislav Sedov 	const char *srealm = krb5_principal_get_realm(context, creds->server);
738ae771770SStanislav Sedov 	const char *crealm = krb5_principal_get_realm(context, creds->client);
739ae771770SStanislav Sedov 
740ae771770SStanislav Sedov 	if (strcmp(rep->enc_part.srealm, srealm) != 0 ||
741ae771770SStanislav Sedov 	    strcmp(rep->enc_part.srealm, crealm) != 0)
742ae771770SStanislav Sedov 	{
743ae771770SStanislav Sedov 	    ret = KRB5KRB_AP_ERR_MODIFIED;
744ae771770SStanislav Sedov 	    krb5_clear_error_message(context);
745ae771770SStanislav Sedov 	    goto out;
746ae771770SStanislav Sedov 	}
747ae771770SStanislav Sedov     }
748ae771770SStanislav Sedov 
749ae771770SStanislav Sedov     /* compare nonces */
750ae771770SStanislav Sedov 
751ae771770SStanislav Sedov     if (nonce != (unsigned)rep->enc_part.nonce) {
752ae771770SStanislav Sedov 	ret = KRB5KRB_AP_ERR_MODIFIED;
753ae771770SStanislav Sedov 	krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
754ae771770SStanislav Sedov 	goto out;
755ae771770SStanislav Sedov     }
756ae771770SStanislav Sedov 
757ae771770SStanislav Sedov     /* set kdc-offset */
758ae771770SStanislav Sedov 
759ae771770SStanislav Sedov     krb5_timeofday (context, &sec_now);
760ae771770SStanislav Sedov     if (rep->enc_part.flags.initial
761ae771770SStanislav Sedov 	&& (flags & EXTRACT_TICKET_TIMESYNC)
762ae771770SStanislav Sedov 	&& context->kdc_sec_offset == 0
763ae771770SStanislav Sedov 	&& krb5_config_get_bool (context, NULL,
764ae771770SStanislav Sedov 				 "libdefaults",
765ae771770SStanislav Sedov 				 "kdc_timesync",
766ae771770SStanislav Sedov 				 NULL)) {
767ae771770SStanislav Sedov 	context->kdc_sec_offset = rep->enc_part.authtime - sec_now;
768ae771770SStanislav Sedov 	krb5_timeofday (context, &sec_now);
769ae771770SStanislav Sedov     }
770ae771770SStanislav Sedov 
771ae771770SStanislav Sedov     /* check all times */
772ae771770SStanislav Sedov 
773ae771770SStanislav Sedov     if (rep->enc_part.starttime) {
774ae771770SStanislav Sedov 	tmp_time = *rep->enc_part.starttime;
775ae771770SStanislav Sedov     } else
776ae771770SStanislav Sedov 	tmp_time = rep->enc_part.authtime;
777ae771770SStanislav Sedov 
778ae771770SStanislav Sedov     if (creds->times.starttime == 0
779ae771770SStanislav Sedov 	&& abs(tmp_time - sec_now) > context->max_skew) {
780ae771770SStanislav Sedov 	ret = KRB5KRB_AP_ERR_SKEW;
781ae771770SStanislav Sedov 	krb5_set_error_message (context, ret,
782ae771770SStanislav Sedov 				N_("time skew (%d) larger than max (%d)", ""),
783ae771770SStanislav Sedov 			       abs(tmp_time - sec_now),
784ae771770SStanislav Sedov 			       (int)context->max_skew);
785ae771770SStanislav Sedov 	goto out;
786ae771770SStanislav Sedov     }
787ae771770SStanislav Sedov 
788ae771770SStanislav Sedov     if (creds->times.starttime != 0
789ae771770SStanislav Sedov 	&& tmp_time != creds->times.starttime) {
790ae771770SStanislav Sedov 	krb5_clear_error_message (context);
791ae771770SStanislav Sedov 	ret = KRB5KRB_AP_ERR_MODIFIED;
792ae771770SStanislav Sedov 	goto out;
793ae771770SStanislav Sedov     }
794ae771770SStanislav Sedov 
795ae771770SStanislav Sedov     creds->times.starttime = tmp_time;
796ae771770SStanislav Sedov 
797ae771770SStanislav Sedov     if (rep->enc_part.renew_till) {
798ae771770SStanislav Sedov 	tmp_time = *rep->enc_part.renew_till;
799ae771770SStanislav Sedov     } else
800ae771770SStanislav Sedov 	tmp_time = 0;
801ae771770SStanislav Sedov 
802ae771770SStanislav Sedov     if (creds->times.renew_till != 0
803ae771770SStanislav Sedov 	&& tmp_time > creds->times.renew_till) {
804ae771770SStanislav Sedov 	krb5_clear_error_message (context);
805ae771770SStanislav Sedov 	ret = KRB5KRB_AP_ERR_MODIFIED;
806ae771770SStanislav Sedov 	goto out;
807ae771770SStanislav Sedov     }
808ae771770SStanislav Sedov 
809ae771770SStanislav Sedov     creds->times.renew_till = tmp_time;
810ae771770SStanislav Sedov 
811ae771770SStanislav Sedov     creds->times.authtime = rep->enc_part.authtime;
812ae771770SStanislav Sedov 
813ae771770SStanislav Sedov     if (creds->times.endtime != 0
814ae771770SStanislav Sedov 	&& rep->enc_part.endtime > creds->times.endtime) {
815ae771770SStanislav Sedov 	krb5_clear_error_message (context);
816ae771770SStanislav Sedov 	ret = KRB5KRB_AP_ERR_MODIFIED;
817ae771770SStanislav Sedov 	goto out;
818ae771770SStanislav Sedov     }
819ae771770SStanislav Sedov 
820ae771770SStanislav Sedov     creds->times.endtime  = rep->enc_part.endtime;
821ae771770SStanislav Sedov 
822ae771770SStanislav Sedov     if(rep->enc_part.caddr)
823ae771770SStanislav Sedov 	krb5_copy_addresses (context, rep->enc_part.caddr, &creds->addresses);
824ae771770SStanislav Sedov     else if(addrs)
825ae771770SStanislav Sedov 	krb5_copy_addresses (context, addrs, &creds->addresses);
826ae771770SStanislav Sedov     else {
827ae771770SStanislav Sedov 	creds->addresses.len = 0;
828ae771770SStanislav Sedov 	creds->addresses.val = NULL;
829ae771770SStanislav Sedov     }
830ae771770SStanislav Sedov     creds->flags.b = rep->enc_part.flags;
831ae771770SStanislav Sedov 
832ae771770SStanislav Sedov     creds->authdata.len = 0;
833ae771770SStanislav Sedov     creds->authdata.val = NULL;
834ae771770SStanislav Sedov 
835ae771770SStanislav Sedov     /* extract ticket */
836ae771770SStanislav Sedov     ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length,
837ae771770SStanislav Sedov 		       &rep->kdc_rep.ticket, &len, ret);
838ae771770SStanislav Sedov     if(ret)
839ae771770SStanislav Sedov 	goto out;
840ae771770SStanislav Sedov     if (creds->ticket.length != len)
841ae771770SStanislav Sedov 	krb5_abortx(context, "internal error in ASN.1 encoder");
842ae771770SStanislav Sedov     creds->second_ticket.length = 0;
843ae771770SStanislav Sedov     creds->second_ticket.data   = NULL;
844ae771770SStanislav Sedov 
845ae771770SStanislav Sedov 
846ae771770SStanislav Sedov out:
847ae771770SStanislav Sedov     memset (rep->enc_part.key.keyvalue.data, 0,
848ae771770SStanislav Sedov 	    rep->enc_part.key.keyvalue.length);
849ae771770SStanislav Sedov     return ret;
850ae771770SStanislav Sedov }
851