xref: /freebsd/crypto/heimdal/lib/krb5/get_for_creds.c (revision 6a068746777241722b2b32c5d0bc443a2a64d80b)
1b528cefcSMark Murray /*
2*ae771770SStanislav Sedov  * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
3b528cefcSMark Murray  * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray  * All rights reserved.
5b528cefcSMark Murray  *
6b528cefcSMark Murray  * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray  * modification, are permitted provided that the following conditions
8b528cefcSMark Murray  * are met:
9b528cefcSMark Murray  *
10b528cefcSMark Murray  * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray  *
13b528cefcSMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray  *    documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray  *
17b528cefcSMark Murray  * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray  *    may be used to endorse or promote products derived from this software
19b528cefcSMark Murray  *    without specific prior written permission.
20b528cefcSMark Murray  *
21b528cefcSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray  * SUCH DAMAGE.
32b528cefcSMark Murray  */
33b528cefcSMark Murray 
34*ae771770SStanislav Sedov #include "krb5_locl.h"
35b528cefcSMark Murray 
36b528cefcSMark Murray static krb5_error_code
add_addrs(krb5_context context,krb5_addresses * addr,struct addrinfo * ai)37b528cefcSMark Murray add_addrs(krb5_context context,
38b528cefcSMark Murray 	  krb5_addresses *addr,
39b528cefcSMark Murray 	  struct addrinfo *ai)
40b528cefcSMark Murray {
41b528cefcSMark Murray     krb5_error_code ret;
421c43270aSJacques Vidrine     unsigned n, i;
43b528cefcSMark Murray     void *tmp;
44b528cefcSMark Murray     struct addrinfo *a;
45b528cefcSMark Murray 
46b528cefcSMark Murray     n = 0;
47b528cefcSMark Murray     for (a = ai; a != NULL; a = a->ai_next)
48b528cefcSMark Murray 	++n;
49b528cefcSMark Murray 
501c43270aSJacques Vidrine     tmp = realloc(addr->val, (addr->len + n) * sizeof(*addr->val));
51c19800e8SDoug Rabson     if (tmp == NULL && (addr->len + n) != 0) {
52b528cefcSMark Murray 	ret = ENOMEM;
53*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
54b528cefcSMark Murray 	goto fail;
55b528cefcSMark Murray     }
56b528cefcSMark Murray     addr->val = tmp;
571c43270aSJacques Vidrine     for (i = addr->len; i < (addr->len + n); ++i) {
585e9cd1aeSAssar Westerlund 	addr->val[i].addr_type = 0;
595e9cd1aeSAssar Westerlund 	krb5_data_zero(&addr->val[i].address);
605e9cd1aeSAssar Westerlund     }
611c43270aSJacques Vidrine     i = addr->len;
62b528cefcSMark Murray     for (a = ai; a != NULL; a = a->ai_next) {
631c43270aSJacques Vidrine 	krb5_address ad;
641c43270aSJacques Vidrine 
651c43270aSJacques Vidrine 	ret = krb5_sockaddr2address (context, a->ai_addr, &ad);
661c43270aSJacques Vidrine 	if (ret == 0) {
671c43270aSJacques Vidrine 	    if (krb5_address_search(context, &ad, addr))
681c43270aSJacques Vidrine 		krb5_free_address(context, &ad);
691c43270aSJacques Vidrine 	    else
701c43270aSJacques Vidrine 		addr->val[i++] = ad;
711c43270aSJacques Vidrine 	}
72adb0ddaeSAssar Westerlund 	else if (ret == KRB5_PROG_ATYPE_NOSUPP)
73*ae771770SStanislav Sedov 	    krb5_clear_error_message (context);
74adb0ddaeSAssar Westerlund 	else
75b528cefcSMark Murray 	    goto fail;
765e9cd1aeSAssar Westerlund 	addr->len = i;
771c43270aSJacques Vidrine     }
78b528cefcSMark Murray     return 0;
79b528cefcSMark Murray fail:
80b528cefcSMark Murray     krb5_free_addresses (context, addr);
81b528cefcSMark Murray     return ret;
82b528cefcSMark Murray }
83b528cefcSMark Murray 
84c19800e8SDoug Rabson /**
85c19800e8SDoug Rabson  * Forward credentials for client to host hostname , making them
86c19800e8SDoug Rabson  * forwardable if forwardable, and returning the blob of data to sent
87c19800e8SDoug Rabson  * in out_data.  If hostname == NULL, pick it from server.
88c19800e8SDoug Rabson  *
89c19800e8SDoug Rabson  * @param context A kerberos 5 context.
90c19800e8SDoug Rabson  * @param auth_context the auth context with the key to encrypt the out_data.
91c19800e8SDoug Rabson  * @param hostname the host to forward the tickets too.
92c19800e8SDoug Rabson  * @param client the client to delegate from.
93c19800e8SDoug Rabson  * @param server the server to delegate the credential too.
94c19800e8SDoug Rabson  * @param ccache credential cache to use.
95c19800e8SDoug Rabson  * @param forwardable make the forwarded ticket forwabledable.
96c19800e8SDoug Rabson  * @param out_data the resulting credential.
97c19800e8SDoug Rabson  *
98c19800e8SDoug Rabson  * @return Return an error code or 0.
99c19800e8SDoug Rabson  *
100c19800e8SDoug Rabson  * @ingroup krb5_credential
101b528cefcSMark Murray  */
102b528cefcSMark Murray 
103*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_fwd_tgt_creds(krb5_context context,krb5_auth_context auth_context,const char * hostname,krb5_principal client,krb5_principal server,krb5_ccache ccache,int forwardable,krb5_data * out_data)104b528cefcSMark Murray krb5_fwd_tgt_creds (krb5_context	context,
105b528cefcSMark Murray 		    krb5_auth_context	auth_context,
106b528cefcSMark Murray 		    const char		*hostname,
107b528cefcSMark Murray 		    krb5_principal	client,
108b528cefcSMark Murray 		    krb5_principal	server,
109b528cefcSMark Murray 		    krb5_ccache		ccache,
110b528cefcSMark Murray 		    int			forwardable,
111b528cefcSMark Murray 		    krb5_data		*out_data)
112b528cefcSMark Murray {
113b528cefcSMark Murray     krb5_flags flags = 0;
114b528cefcSMark Murray     krb5_creds creds;
115b528cefcSMark Murray     krb5_error_code ret;
1164137ff4cSJacques Vidrine     krb5_const_realm client_realm;
117b528cefcSMark Murray 
118b528cefcSMark Murray     flags |= KDC_OPT_FORWARDED;
119b528cefcSMark Murray 
120b528cefcSMark Murray     if (forwardable)
121b528cefcSMark Murray 	flags |= KDC_OPT_FORWARDABLE;
122b528cefcSMark Murray 
1234137ff4cSJacques Vidrine     if (hostname == NULL &&
1244137ff4cSJacques Vidrine 	krb5_principal_get_type(context, server) == KRB5_NT_SRV_HST) {
1254137ff4cSJacques Vidrine 	const char *inst = krb5_principal_get_comp_string(context, server, 0);
1264137ff4cSJacques Vidrine 	const char *host = krb5_principal_get_comp_string(context, server, 1);
1274137ff4cSJacques Vidrine 
1284137ff4cSJacques Vidrine 	if (inst != NULL &&
1294137ff4cSJacques Vidrine 	    strcmp(inst, "host") == 0 &&
1304137ff4cSJacques Vidrine 	    host != NULL &&
1314137ff4cSJacques Vidrine 	    krb5_principal_get_comp_string(context, server, 2) == NULL)
1324137ff4cSJacques Vidrine 	    hostname = host;
1334137ff4cSJacques Vidrine     }
1344137ff4cSJacques Vidrine 
1354137ff4cSJacques Vidrine     client_realm = krb5_principal_get_realm(context, client);
136b528cefcSMark Murray 
137b528cefcSMark Murray     memset (&creds, 0, sizeof(creds));
138b528cefcSMark Murray     creds.client = client;
1394137ff4cSJacques Vidrine 
140*ae771770SStanislav Sedov     ret = krb5_make_principal(context,
1414137ff4cSJacques Vidrine 			      &creds.server,
1424137ff4cSJacques Vidrine 			      client_realm,
1434137ff4cSJacques Vidrine 			      KRB5_TGS_NAME,
1444137ff4cSJacques Vidrine 			      client_realm,
1454137ff4cSJacques Vidrine 			      NULL);
1464137ff4cSJacques Vidrine     if (ret)
1474137ff4cSJacques Vidrine 	return ret;
148b528cefcSMark Murray 
149b528cefcSMark Murray     ret = krb5_get_forwarded_creds (context,
150b528cefcSMark Murray 				    auth_context,
151b528cefcSMark Murray 				    ccache,
152b528cefcSMark Murray 				    flags,
153b528cefcSMark Murray 				    hostname,
154b528cefcSMark Murray 				    &creds,
155b528cefcSMark Murray 				    out_data);
156b528cefcSMark Murray     return ret;
157b528cefcSMark Murray }
158b528cefcSMark Murray 
159c19800e8SDoug Rabson /**
160c19800e8SDoug Rabson  * Gets tickets forwarded to hostname. If the tickets that are
161c19800e8SDoug Rabson  * forwarded are address-less, the forwarded tickets will also be
162c19800e8SDoug Rabson  * address-less.
163b528cefcSMark Murray  *
164c19800e8SDoug Rabson  * If the ticket have any address, hostname will be used for figure
165c19800e8SDoug Rabson  * out the address to forward the ticket too. This since this might
166c19800e8SDoug Rabson  * use DNS, its insecure and also doesn't represent configured all
167c19800e8SDoug Rabson  * addresses of the host. For example, the host might have two
168c19800e8SDoug Rabson  * adresses, one IPv4 and one IPv6 address where the later is not
169c19800e8SDoug Rabson  * published in DNS. This IPv6 address might be used communications
170c19800e8SDoug Rabson  * and thus the resulting ticket useless.
171c19800e8SDoug Rabson  *
172c19800e8SDoug Rabson  * @param context A kerberos 5 context.
173c19800e8SDoug Rabson  * @param auth_context the auth context with the key to encrypt the out_data.
174c19800e8SDoug Rabson  * @param ccache credential cache to use
175c19800e8SDoug Rabson  * @param flags the flags to control the resulting ticket flags
176c19800e8SDoug Rabson  * @param hostname the host to forward the tickets too.
177c19800e8SDoug Rabson  * @param in_creds the in client and server ticket names.  The client
178c19800e8SDoug Rabson  * and server components forwarded to the remote host.
179c19800e8SDoug Rabson  * @param out_data the resulting credential.
180c19800e8SDoug Rabson  *
181c19800e8SDoug Rabson  * @return Return an error code or 0.
182c19800e8SDoug Rabson  *
183c19800e8SDoug Rabson  * @ingroup krb5_credential
184b528cefcSMark Murray  */
185b528cefcSMark Murray 
186*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_get_forwarded_creds(krb5_context context,krb5_auth_context auth_context,krb5_ccache ccache,krb5_flags flags,const char * hostname,krb5_creds * in_creds,krb5_data * out_data)187b528cefcSMark Murray krb5_get_forwarded_creds (krb5_context	    context,
188b528cefcSMark Murray 			  krb5_auth_context auth_context,
189b528cefcSMark Murray 			  krb5_ccache       ccache,
190b528cefcSMark Murray 			  krb5_flags        flags,
191b528cefcSMark Murray 			  const char        *hostname,
192b528cefcSMark Murray 			  krb5_creds        *in_creds,
193b528cefcSMark Murray 			  krb5_data         *out_data)
194b528cefcSMark Murray {
195b528cefcSMark Murray     krb5_error_code ret;
196b528cefcSMark Murray     krb5_creds *out_creds;
1971c43270aSJacques Vidrine     krb5_addresses addrs, *paddrs;
198b528cefcSMark Murray     KRB_CRED cred;
199b528cefcSMark Murray     KrbCredInfo *krb_cred_info;
200b528cefcSMark Murray     EncKrbCredPart enc_krb_cred_part;
201b528cefcSMark Murray     size_t len;
2020cadf2f4SJacques Vidrine     unsigned char *buf;
2030cadf2f4SJacques Vidrine     size_t buf_size;
204b528cefcSMark Murray     krb5_kdc_flags kdc_flags;
205b528cefcSMark Murray     krb5_crypto crypto;
206b528cefcSMark Murray     struct addrinfo *ai;
2071c43270aSJacques Vidrine     krb5_creds *ticket;
2081c43270aSJacques Vidrine 
209c19800e8SDoug Rabson     paddrs = NULL;
210b528cefcSMark Murray     addrs.len = 0;
211b528cefcSMark Murray     addrs.val = NULL;
212c19800e8SDoug Rabson 
213c19800e8SDoug Rabson     ret = krb5_get_credentials(context, 0, ccache, in_creds, &ticket);
214c19800e8SDoug Rabson     if(ret == 0) {
215c19800e8SDoug Rabson 	if (ticket->addresses.len)
2161c43270aSJacques Vidrine 	    paddrs = &addrs;
217c19800e8SDoug Rabson 	krb5_free_creds (context, ticket);
218c19800e8SDoug Rabson     } else {
219c19800e8SDoug Rabson 	krb5_boolean noaddr;
220c19800e8SDoug Rabson 	krb5_appdefault_boolean(context, NULL,
221c19800e8SDoug Rabson 				krb5_principal_get_realm(context,
222c19800e8SDoug Rabson 							 in_creds->client),
223c19800e8SDoug Rabson 				"no-addresses", KRB5_ADDRESSLESS_DEFAULT,
224c19800e8SDoug Rabson 				&noaddr);
225c19800e8SDoug Rabson 	if (!noaddr)
226c19800e8SDoug Rabson 	    paddrs = &addrs;
227c19800e8SDoug Rabson     }
2281c43270aSJacques Vidrine 
2291c43270aSJacques Vidrine     /*
230c19800e8SDoug Rabson      * If tickets have addresses, get the address of the remote host.
2311c43270aSJacques Vidrine      */
2321c43270aSJacques Vidrine 
2331c43270aSJacques Vidrine     if (paddrs != NULL) {
234b528cefcSMark Murray 
235b528cefcSMark Murray 	ret = getaddrinfo (hostname, NULL, NULL, &ai);
236adb0ddaeSAssar Westerlund 	if (ret) {
237*ae771770SStanislav Sedov 	    krb5_error_code ret2 = krb5_eai_to_heim_errno(ret, errno);
238*ae771770SStanislav Sedov 	    krb5_set_error_message(context, ret2,
239*ae771770SStanislav Sedov 				   N_("resolving host %s failed: %s",
240*ae771770SStanislav Sedov 				      "hostname, error"),
241adb0ddaeSAssar Westerlund 				  hostname, gai_strerror(ret));
242*ae771770SStanislav Sedov 	    return ret2;
243adb0ddaeSAssar Westerlund 	}
244b528cefcSMark Murray 
245b528cefcSMark Murray 	ret = add_addrs (context, &addrs, ai);
246b528cefcSMark Murray 	freeaddrinfo (ai);
247b528cefcSMark Murray 	if (ret)
248b528cefcSMark Murray 	    return ret;
2491c43270aSJacques Vidrine     }
250b528cefcSMark Murray 
251c19800e8SDoug Rabson     kdc_flags.b = int2KDCOptions(flags);
252b528cefcSMark Murray 
253b528cefcSMark Murray     ret = krb5_get_kdc_cred (context,
254b528cefcSMark Murray 			     ccache,
255b528cefcSMark Murray 			     kdc_flags,
2561c43270aSJacques Vidrine 			     paddrs,
257b528cefcSMark Murray 			     NULL,
258b528cefcSMark Murray 			     in_creds,
259b528cefcSMark Murray 			     &out_creds);
260b528cefcSMark Murray     krb5_free_addresses (context, &addrs);
261c19800e8SDoug Rabson     if (ret)
262b528cefcSMark Murray 	return ret;
263b528cefcSMark Murray 
264b528cefcSMark Murray     memset (&cred, 0, sizeof(cred));
265b528cefcSMark Murray     cred.pvno = 5;
266b528cefcSMark Murray     cred.msg_type = krb_cred;
267b528cefcSMark Murray     ALLOC_SEQ(&cred.tickets, 1);
268b528cefcSMark Murray     if (cred.tickets.val == NULL) {
269b528cefcSMark Murray 	ret = ENOMEM;
270*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
271b528cefcSMark Murray 	goto out2;
272b528cefcSMark Murray     }
273b528cefcSMark Murray     ret = decode_Ticket(out_creds->ticket.data,
274b528cefcSMark Murray 			out_creds->ticket.length,
275b528cefcSMark Murray 			cred.tickets.val, &len);
276b528cefcSMark Murray     if (ret)
277b528cefcSMark Murray 	goto out3;
278b528cefcSMark Murray 
279b528cefcSMark Murray     memset (&enc_krb_cred_part, 0, sizeof(enc_krb_cred_part));
280b528cefcSMark Murray     ALLOC_SEQ(&enc_krb_cred_part.ticket_info, 1);
281b528cefcSMark Murray     if (enc_krb_cred_part.ticket_info.val == NULL) {
282b528cefcSMark Murray 	ret = ENOMEM;
283*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
284b528cefcSMark Murray 	goto out4;
285b528cefcSMark Murray     }
286b528cefcSMark Murray 
2871c43270aSJacques Vidrine     if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
288c19800e8SDoug Rabson 	krb5_timestamp sec;
289c19800e8SDoug Rabson 	int32_t usec;
2901c43270aSJacques Vidrine 
291b528cefcSMark Murray 	krb5_us_timeofday (context, &sec, &usec);
292b528cefcSMark Murray 
293b528cefcSMark Murray 	ALLOC(enc_krb_cred_part.timestamp, 1);
294b528cefcSMark Murray 	if (enc_krb_cred_part.timestamp == NULL) {
295b528cefcSMark Murray 	    ret = ENOMEM;
296*ae771770SStanislav Sedov 	    krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
297b528cefcSMark Murray 	    goto out4;
298b528cefcSMark Murray 	}
299b528cefcSMark Murray 	*enc_krb_cred_part.timestamp = sec;
300b528cefcSMark Murray 	ALLOC(enc_krb_cred_part.usec, 1);
301b528cefcSMark Murray 	if (enc_krb_cred_part.usec == NULL) {
302b528cefcSMark Murray 	    ret = ENOMEM;
303*ae771770SStanislav Sedov 	    krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
304b528cefcSMark Murray 	    goto out4;
305b528cefcSMark Murray 	}
306b528cefcSMark Murray 	*enc_krb_cred_part.usec      = usec;
3071c43270aSJacques Vidrine     } else {
3081c43270aSJacques Vidrine 	enc_krb_cred_part.timestamp = NULL;
3091c43270aSJacques Vidrine 	enc_krb_cred_part.usec = NULL;
3101c43270aSJacques Vidrine     }
311b528cefcSMark Murray 
312c19800e8SDoug Rabson     if (auth_context->local_address && auth_context->local_port && paddrs) {
3134137ff4cSJacques Vidrine 
314adb0ddaeSAssar Westerlund 	ret = krb5_make_addrport (context,
315adb0ddaeSAssar Westerlund 				  &enc_krb_cred_part.s_address,
316b528cefcSMark Murray 				  auth_context->local_address,
317b528cefcSMark Murray 				  auth_context->local_port);
318b528cefcSMark Murray 	if (ret)
319b528cefcSMark Murray 	    goto out4;
3205e9cd1aeSAssar Westerlund     }
321b528cefcSMark Murray 
3225e9cd1aeSAssar Westerlund     if (auth_context->remote_address) {
3238373020dSJacques Vidrine 	if (auth_context->remote_port) {
3248373020dSJacques Vidrine 	    krb5_boolean noaddr;
325c19800e8SDoug Rabson 	    krb5_const_realm srealm;
3268373020dSJacques Vidrine 
327c19800e8SDoug Rabson 	    srealm = krb5_principal_get_realm(context, out_creds->server);
328c19800e8SDoug Rabson 	    /* Is this correct, and should we use the paddrs == NULL
329c19800e8SDoug Rabson                trick here as well? Having an address-less ticket may
330c19800e8SDoug Rabson                indicate that we don't know our own global address, but
331c19800e8SDoug Rabson                it does not necessary mean that we don't know the
332c19800e8SDoug Rabson                server's. */
333c19800e8SDoug Rabson 	    krb5_appdefault_boolean(context, NULL, srealm, "no-addresses",
3348373020dSJacques Vidrine 				    FALSE, &noaddr);
3358373020dSJacques Vidrine 	    if (!noaddr) {
3368373020dSJacques Vidrine 		ret = krb5_make_addrport (context,
3378373020dSJacques Vidrine 					  &enc_krb_cred_part.r_address,
3388373020dSJacques Vidrine 					  auth_context->remote_address,
3398373020dSJacques Vidrine 					  auth_context->remote_port);
3408373020dSJacques Vidrine 		if (ret)
3418373020dSJacques Vidrine 		    goto out4;
3428373020dSJacques Vidrine 	    }
3438373020dSJacques Vidrine 	} else {
344b528cefcSMark Murray 	    ALLOC(enc_krb_cred_part.r_address, 1);
345b528cefcSMark Murray 	    if (enc_krb_cred_part.r_address == NULL) {
346b528cefcSMark Murray 		ret = ENOMEM;
347*ae771770SStanislav Sedov 		krb5_set_error_message(context, ret,
348*ae771770SStanislav Sedov 				       N_("malloc: out of memory", ""));
349b528cefcSMark Murray 		goto out4;
350b528cefcSMark Murray 	    }
351b528cefcSMark Murray 
352b528cefcSMark Murray 	    ret = krb5_copy_address (context, auth_context->remote_address,
353b528cefcSMark Murray 				     enc_krb_cred_part.r_address);
354b528cefcSMark Murray 	    if (ret)
355b528cefcSMark Murray 		goto out4;
3565e9cd1aeSAssar Westerlund 	}
3578373020dSJacques Vidrine     }
358b528cefcSMark Murray 
359b528cefcSMark Murray     /* fill ticket_info.val[0] */
360b528cefcSMark Murray 
361b528cefcSMark Murray     enc_krb_cred_part.ticket_info.len = 1;
362b528cefcSMark Murray 
363b528cefcSMark Murray     krb_cred_info = enc_krb_cred_part.ticket_info.val;
364b528cefcSMark Murray 
365b528cefcSMark Murray     copy_EncryptionKey (&out_creds->session, &krb_cred_info->key);
366b528cefcSMark Murray     ALLOC(krb_cred_info->prealm, 1);
367b528cefcSMark Murray     copy_Realm (&out_creds->client->realm, krb_cred_info->prealm);
368b528cefcSMark Murray     ALLOC(krb_cred_info->pname, 1);
369b528cefcSMark Murray     copy_PrincipalName(&out_creds->client->name, krb_cred_info->pname);
370b528cefcSMark Murray     ALLOC(krb_cred_info->flags, 1);
371b528cefcSMark Murray     *krb_cred_info->flags          = out_creds->flags.b;
372b528cefcSMark Murray     ALLOC(krb_cred_info->authtime, 1);
373b528cefcSMark Murray     *krb_cred_info->authtime       = out_creds->times.authtime;
374b528cefcSMark Murray     ALLOC(krb_cred_info->starttime, 1);
375b528cefcSMark Murray     *krb_cred_info->starttime      = out_creds->times.starttime;
376b528cefcSMark Murray     ALLOC(krb_cred_info->endtime, 1);
377b528cefcSMark Murray     *krb_cred_info->endtime        = out_creds->times.endtime;
378b528cefcSMark Murray     ALLOC(krb_cred_info->renew_till, 1);
379b528cefcSMark Murray     *krb_cred_info->renew_till = out_creds->times.renew_till;
380b528cefcSMark Murray     ALLOC(krb_cred_info->srealm, 1);
381b528cefcSMark Murray     copy_Realm (&out_creds->server->realm, krb_cred_info->srealm);
382b528cefcSMark Murray     ALLOC(krb_cred_info->sname, 1);
383b528cefcSMark Murray     copy_PrincipalName (&out_creds->server->name, krb_cred_info->sname);
384b528cefcSMark Murray     ALLOC(krb_cred_info->caddr, 1);
385b528cefcSMark Murray     copy_HostAddresses (&out_creds->addresses, krb_cred_info->caddr);
386b528cefcSMark Murray 
387b528cefcSMark Murray     krb5_free_creds (context, out_creds);
388b528cefcSMark Murray 
389b528cefcSMark Murray     /* encode EncKrbCredPart */
390b528cefcSMark Murray 
3910cadf2f4SJacques Vidrine     ASN1_MALLOC_ENCODE(EncKrbCredPart, buf, buf_size,
3920cadf2f4SJacques Vidrine 		       &enc_krb_cred_part, &len, ret);
393b528cefcSMark Murray     free_EncKrbCredPart (&enc_krb_cred_part);
394b528cefcSMark Murray     if (ret) {
395b528cefcSMark Murray 	free_KRB_CRED(&cred);
396b528cefcSMark Murray 	return ret;
397b528cefcSMark Murray     }
3980cadf2f4SJacques Vidrine     if(buf_size != len)
3990cadf2f4SJacques Vidrine 	krb5_abortx(context, "internal error in ASN.1 encoder");
400b528cefcSMark Murray 
401c19800e8SDoug Rabson     /**
402c19800e8SDoug Rabson      * Some older of the MIT gssapi library used clear-text tickets
403c19800e8SDoug Rabson      * (warped inside AP-REQ encryption), use the krb5_auth_context
404c19800e8SDoug Rabson      * flag KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED to support those
405c19800e8SDoug Rabson      * tickets. The session key is used otherwise to encrypt the
406c19800e8SDoug Rabson      * forwarded ticket.
407c19800e8SDoug Rabson      */
4080cadf2f4SJacques Vidrine 
409c19800e8SDoug Rabson     if (auth_context->flags & KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED) {
410c19800e8SDoug Rabson 	cred.enc_part.etype = ENCTYPE_NULL;
411c19800e8SDoug Rabson 	cred.enc_part.kvno = NULL;
412c19800e8SDoug Rabson 	cred.enc_part.cipher.data = buf;
413c19800e8SDoug Rabson 	cred.enc_part.cipher.length = buf_size;
414c19800e8SDoug Rabson     } else {
415c19800e8SDoug Rabson 	/*
416c19800e8SDoug Rabson 	 * Here older versions then 0.7.2 of Heimdal used the local or
417c19800e8SDoug Rabson 	 * remote subkey. That is wrong, the session key should be
418c19800e8SDoug Rabson 	 * used. Heimdal 0.7.2 and newer have code to try both in the
419c19800e8SDoug Rabson 	 * receiving end.
420c19800e8SDoug Rabson 	 */
421c19800e8SDoug Rabson 
422c19800e8SDoug Rabson 	ret = krb5_crypto_init(context, auth_context->keyblock, 0, &crypto);
4235e9cd1aeSAssar Westerlund 	if (ret) {
4240cadf2f4SJacques Vidrine 	    free(buf);
4255e9cd1aeSAssar Westerlund 	    free_KRB_CRED(&cred);
4265e9cd1aeSAssar Westerlund 	    return ret;
4275e9cd1aeSAssar Westerlund 	}
428b528cefcSMark Murray 	ret = krb5_encrypt_EncryptedData (context,
429b528cefcSMark Murray 					  crypto,
430b528cefcSMark Murray 					  KRB5_KU_KRB_CRED,
4310cadf2f4SJacques Vidrine 					  buf,
432b528cefcSMark Murray 					  len,
433b528cefcSMark Murray 					  0,
434b528cefcSMark Murray 					  &cred.enc_part);
4350cadf2f4SJacques Vidrine 	free(buf);
436b528cefcSMark Murray 	krb5_crypto_destroy(context, crypto);
437b528cefcSMark Murray 	if (ret) {
438b528cefcSMark Murray 	    free_KRB_CRED(&cred);
439b528cefcSMark Murray 	    return ret;
440b528cefcSMark Murray 	}
441c19800e8SDoug Rabson     }
442b528cefcSMark Murray 
4430cadf2f4SJacques Vidrine     ASN1_MALLOC_ENCODE(KRB_CRED, buf, buf_size, &cred, &len, ret);
444b528cefcSMark Murray     free_KRB_CRED (&cred);
445b528cefcSMark Murray     if (ret)
446b528cefcSMark Murray 	return ret;
4470cadf2f4SJacques Vidrine     if(buf_size != len)
4480cadf2f4SJacques Vidrine 	krb5_abortx(context, "internal error in ASN.1 encoder");
449b528cefcSMark Murray     out_data->length = len;
4500cadf2f4SJacques Vidrine     out_data->data   = buf;
451b528cefcSMark Murray     return 0;
452b528cefcSMark Murray  out4:
453b528cefcSMark Murray     free_EncKrbCredPart(&enc_krb_cred_part);
454b528cefcSMark Murray  out3:
455b528cefcSMark Murray     free_KRB_CRED(&cred);
456b528cefcSMark Murray  out2:
457b528cefcSMark Murray     krb5_free_creds (context, out_creds);
458b528cefcSMark Murray     return ret;
459b528cefcSMark Murray }
460