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