168591Sdab /*
268591Sdab * $Source: /mit/krb5/.cvsroot/src/appl/bsd/forward.c,v $
368591Sdab * $Id: forward.c,v 1.4 1993/10/15 16:41:29 tytso Exp $
468591Sdab */
568591Sdab
668591Sdab #ifndef lint
768591Sdab static char *rcsid_forward_c =
868591Sdab "$Id: forward.c,v 1.4 1993/10/15 16:41:29 tytso Exp $";
968591Sdab #endif /* lint */
1068591Sdab #define LIBC_SCCS
1168591Sdab
1268591Sdab /*-
1368591Sdab * Copyright (c) 1993
1468591Sdab * The Regents of the University of California. All rights reserved.
1568591Sdab *
1668591Sdab * %sccs.include.redist.c%
1768591Sdab */
1868591Sdab
1968591Sdab #ifndef lint
20*69784Sdab static char sccsid[] = "@(#)forward.c 8.2 (Berkeley) 05/30/95";
2168591Sdab #endif /* not lint */
2268591Sdab
2368591Sdab
2468591Sdab /* General-purpose forwarding routines. These routines may be put into */
25*69784Sdab /* libkrb5.a to allow widespread use */
2668591Sdab
2768591Sdab #if defined(KRB5) && defined(FORWARD)
2868591Sdab #include <stdio.h>
2968591Sdab #include <pwd.h>
3068591Sdab #include <netdb.h>
3168591Sdab
3268591Sdab #include <krb5/krb5.h>
3368591Sdab #include <krb5/asn1.h>
3468591Sdab #include <krb5/crc-32.h>
3568591Sdab #include <krb5/los-proto.h>
3668591Sdab #include <krb5/ext-proto.h>
3768591Sdab
3868591Sdab #define KRB5_DEFAULT_LIFE 60*60*8 /* 8 hours */
3968591Sdab /* helper function: convert flags to necessary KDC options */
4068591Sdab #define flags2options(flags) (flags & KDC_TKT_COMMON_MASK)
4168591Sdab
4268591Sdab
4368591Sdab
4468591Sdab /* Get a TGT for use at the remote host */
4568591Sdab krb5_error_code
get_for_creds(etype,sumtype,rhost,client,enc_key,forwardable,outbuf)4668591Sdab get_for_creds(etype, sumtype, rhost, client, enc_key, forwardable, outbuf)
4768591Sdab const krb5_enctype etype;
4868591Sdab const krb5_cksumtype sumtype;
4968591Sdab char *rhost;
5068591Sdab krb5_principal client;
5168591Sdab krb5_keyblock *enc_key;
5268591Sdab int forwardable; /* Should forwarded TGT also be forwardable? */
5368591Sdab krb5_data *outbuf;
5468591Sdab {
5568591Sdab struct hostent *hp;
5668591Sdab krb5_address **addrs;
5768591Sdab krb5_error_code retval;
5868591Sdab krb5_data *scratch;
5968591Sdab krb5_kdc_rep *dec_rep;
6068591Sdab krb5_error *err_reply;
6168591Sdab krb5_response tgsrep;
6268591Sdab krb5_creds creds, tgt;
6368591Sdab krb5_ccache cc;
6468591Sdab krb5_flags kdcoptions;
6568591Sdab krb5_timestamp now;
6668591Sdab char *remote_host;
6768591Sdab char **hrealms;
6868591Sdab int i;
6968591Sdab
7068591Sdab if (!rhost || !(hp = gethostbyname(rhost)))
7168591Sdab return KRB5_ERR_BAD_HOSTNAME;
7268591Sdab
7368591Sdab remote_host = (char *) malloc(strlen(hp->h_name)+1);
7468591Sdab if (!remote_host)
7568591Sdab return ENOMEM;
7668591Sdab strcpy(remote_host, hp->h_name);
7768591Sdab
7868591Sdab if (retval = krb5_get_host_realm(remote_host, &hrealms)) {
7968591Sdab free(remote_host);
8068591Sdab return retval;
8168591Sdab }
8268591Sdab if (!hrealms[0]) {
8368591Sdab free(remote_host);
8468591Sdab krb5_xfree(hrealms);
8568591Sdab return KRB5_ERR_HOST_REALM_UNKNOWN;
8668591Sdab }
8768591Sdab
8868591Sdab /* Count elements */
8968591Sdab for(i=0; hp->h_addr_list[i]; i++);
9068591Sdab
9168591Sdab addrs = (krb5_address **) malloc ((i+1)*sizeof(*addrs));
9268591Sdab if (!addrs)
9368591Sdab return ENOMEM;
94*69784Sdab
9568591Sdab for(i=0; hp->h_addr_list[i]; i++) {
9668591Sdab addrs[i] = (krb5_address *) malloc(sizeof(krb5_address));
9768591Sdab if (addrs[i]) {
9868591Sdab addrs[i]->addrtype = hp->h_addrtype;
9968591Sdab addrs[i]->length = hp->h_length;
10068591Sdab addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
10168591Sdab if (!addrs[i]->contents) {
10268591Sdab krb5_free_addresses(addrs);
10368591Sdab return ENOMEM;
10468591Sdab }
10568591Sdab else
106*69784Sdab memmove ((char *)addrs[i]->contents, hp->h_addr_list[i],
10768591Sdab addrs[i]->length);
10868591Sdab }
10968591Sdab else {
11068591Sdab return ENOMEM;
11168591Sdab }
11268591Sdab }
11368591Sdab addrs[i] = 0;
11468591Sdab
11568591Sdab memset((char *)&creds, 0, sizeof(creds));
11668591Sdab if (retval = krb5_copy_principal(client, &creds.client))
11768591Sdab return retval;
118*69784Sdab
11968591Sdab if (retval = krb5_build_principal_ext(&creds.server,
12068591Sdab strlen(hrealms[0]),
12168591Sdab hrealms[0],
12268591Sdab KRB5_TGS_NAME_SIZE,
12368591Sdab KRB5_TGS_NAME,
12468591Sdab client->realm.length,
12568591Sdab client->realm.data,
12668591Sdab 0))
12768591Sdab return retval;
128*69784Sdab
12968591Sdab creds.times.starttime = 0;
13068591Sdab if (retval = krb5_timeofday(&now)) {
13168591Sdab return retval;
13268591Sdab }
13368591Sdab creds.times.endtime = now + KRB5_DEFAULT_LIFE;
13468591Sdab creds.times.renew_till = 0;
135*69784Sdab
13668591Sdab if (retval = krb5_cc_default(&cc)) {
13768591Sdab return retval;
13868591Sdab }
13968591Sdab
14068591Sdab /* fetch tgt directly from cache */
14168591Sdab if (retval = krb5_cc_retrieve_cred (cc,
14268591Sdab KRB5_TC_MATCH_SRV_NAMEONLY,
14368591Sdab &creds,
14468591Sdab &tgt)) {
14568591Sdab return retval;
14668591Sdab }
14768591Sdab
14868591Sdab /* tgt->client must be equal to creds.client */
14968591Sdab if (!krb5_principal_compare(tgt.client, creds.client))
15068591Sdab return KRB5_PRINC_NOMATCH;
15168591Sdab
15268591Sdab if (!tgt.ticket.length)
15368591Sdab return(KRB5_NO_TKT_SUPPLIED);
15468591Sdab
15568591Sdab kdcoptions = flags2options(tgt.ticket_flags)|KDC_OPT_FORWARDED;
15668591Sdab
15768591Sdab if (!forwardable) /* Reset KDC_OPT_FORWARDABLE */
15868591Sdab kdcoptions &= ~(KDC_OPT_FORWARDABLE);
15968591Sdab
16068591Sdab if (retval = krb5_send_tgs(kdcoptions, &creds.times, etype, sumtype,
16168591Sdab creds.server,
16268591Sdab addrs,
16368591Sdab creds.authdata,
16468591Sdab 0, /* no padata */
16568591Sdab 0, /* no second ticket */
16668591Sdab &tgt, &tgsrep))
16768591Sdab return retval;
16868591Sdab
16968591Sdab #undef cleanup
17068591Sdab #define cleanup() free(tgsrep.response.data)
17168591Sdab
17268591Sdab switch (tgsrep.message_type) {
17368591Sdab case KRB5_TGS_REP:
17468591Sdab break;
17568591Sdab case KRB5_ERROR:
17668591Sdab default:
17768591Sdab if (!krb5_is_krb_error(&tgsrep.response)) {
17868591Sdab retval = KRB5KRB_AP_ERR_MSG_TYPE;
17968591Sdab } else
18068591Sdab retval = decode_krb5_error(&tgsrep.response, &err_reply);
18168591Sdab if (retval) {
18268591Sdab cleanup();
18368591Sdab return retval; /* neither proper reply nor error! */
18468591Sdab }
18568591Sdab
18668591Sdab retval = err_reply->error + ERROR_TABLE_BASE_krb5;
18768591Sdab
18868591Sdab krb5_free_error(err_reply);
18968591Sdab cleanup();
19068591Sdab return retval;
19168591Sdab }
19268591Sdab retval = krb5_decode_kdc_rep(&tgsrep.response,
19368591Sdab &tgt.keyblock,
19468591Sdab etype, /* enctype */
19568591Sdab &dec_rep);
196*69784Sdab
19768591Sdab cleanup();
19868591Sdab if (retval)
19968591Sdab return retval;
20068591Sdab #undef cleanup
20168591Sdab #define cleanup() {\
20268591Sdab memset((char *)dec_rep->enc_part2->session->contents, 0,\
20368591Sdab dec_rep->enc_part2->session->length);\
20468591Sdab krb5_free_kdc_rep(dec_rep); }
20568591Sdab
20668591Sdab if (dec_rep->msg_type != KRB5_TGS_REP) {
20768591Sdab retval = KRB5KRB_AP_ERR_MSG_TYPE;
20868591Sdab cleanup();
20968591Sdab return retval;
21068591Sdab }
211*69784Sdab
21268591Sdab /* now it's decrypted and ready for prime time */
21368591Sdab
21468591Sdab if (!krb5_principal_compare(dec_rep->client, tgt.client)) {
21568591Sdab cleanup();
21668591Sdab return KRB5_KDCREP_MODIFIED;
21768591Sdab }
21868591Sdab
219*69784Sdab if (retval = mk_cred(dec_rep,
220*69784Sdab etype,
22168591Sdab enc_key,
22268591Sdab 0,
223*69784Sdab 0,
22468591Sdab outbuf))
22568591Sdab return retval;
22668591Sdab
22768591Sdab krb5_free_kdc_rep(dec_rep);
22868591Sdab
22968591Sdab return retval;
23068591Sdab #undef cleanup
23168591Sdab }
23268591Sdab
23368591Sdab
23468591Sdab
23568591Sdab /* Create asn.1 encoded KRB-CRED message from the kdc reply. */
23668591Sdab krb5_error_code
mk_cred(dec_rep,etype,key,sender_addr,recv_addr,outbuf)23768591Sdab mk_cred(dec_rep, etype, key, sender_addr, recv_addr, outbuf)
23868591Sdab krb5_kdc_rep *dec_rep;
23968591Sdab krb5_enctype etype;
24068591Sdab krb5_keyblock *key;
24168591Sdab krb5_address *sender_addr;
24268591Sdab krb5_address *recv_addr;
24368591Sdab krb5_data *outbuf;
24468591Sdab {
24568591Sdab krb5_error_code retval;
24668591Sdab krb5_encrypt_block eblock;
24768591Sdab krb5_cred ret_cred;
24868591Sdab krb5_cred_enc_part cred_enc_part;
24968591Sdab krb5_data *scratch;
25068591Sdab
25168591Sdab if (!valid_etype(etype))
25268591Sdab return KRB5_PROG_ETYPE_NOSUPP;
25368591Sdab
25468591Sdab ret_cred.tickets = (krb5_ticket **) calloc(2, sizeof(*ret_cred.tickets));
25568591Sdab if (!ret_cred.tickets)
25668591Sdab return ENOMEM;
25768591Sdab ret_cred.tickets[0] = dec_rep->ticket;
25868591Sdab ret_cred.tickets[1] = 0;
25968591Sdab
260*69784Sdab ret_cred.enc_part.etype = etype;
26168591Sdab ret_cred.enc_part.kvno = 0;
26268591Sdab
263*69784Sdab cred_enc_part.ticket_info = (krb5_cred_info **)
26468591Sdab calloc(2, sizeof(*cred_enc_part.ticket_info));
26568591Sdab if (!cred_enc_part.ticket_info) {
26668591Sdab krb5_free_tickets(ret_cred.tickets);
26768591Sdab return ENOMEM;
26868591Sdab }
269*69784Sdab cred_enc_part.ticket_info[0] = (krb5_cred_info *)
27068591Sdab malloc(sizeof(*cred_enc_part.ticket_info[0]));
27168591Sdab if (!cred_enc_part.ticket_info[0]) {
27268591Sdab krb5_free_tickets(ret_cred.tickets);
27368591Sdab krb5_free_cred_enc_part(cred_enc_part);
27468591Sdab return ENOMEM;
27568591Sdab }
27668591Sdab cred_enc_part.nonce = 0;
27768591Sdab
27868591Sdab if (retval = krb5_us_timeofday(&cred_enc_part.timestamp,
27968591Sdab &cred_enc_part.usec))
28068591Sdab return retval;
28168591Sdab
28268591Sdab cred_enc_part.s_address = (krb5_address *)sender_addr;
28368591Sdab cred_enc_part.r_address = (krb5_address *)recv_addr;
28468591Sdab
28568591Sdab cred_enc_part.ticket_info[0]->session = dec_rep->enc_part2->session;
28668591Sdab cred_enc_part.ticket_info[0]->client = dec_rep->client;
28768591Sdab cred_enc_part.ticket_info[0]->server = dec_rep->enc_part2->server;
28868591Sdab cred_enc_part.ticket_info[0]->flags = dec_rep->enc_part2->flags;
28968591Sdab cred_enc_part.ticket_info[0]->times = dec_rep->enc_part2->times;
29068591Sdab cred_enc_part.ticket_info[0]->caddrs = dec_rep->enc_part2->caddrs;
29168591Sdab
29268591Sdab cred_enc_part.ticket_info[1] = 0;
29368591Sdab
29468591Sdab /* start by encoding to-be-encrypted part of the message */
29568591Sdab
29668591Sdab if (retval = encode_krb5_enc_cred_part(&cred_enc_part, &scratch))
29768591Sdab return retval;
29868591Sdab
29968591Sdab #define cleanup_scratch() { (void) memset(scratch->data, 0, scratch->length); krb5_free_data(scratch); }
30068591Sdab
30168591Sdab /* put together an eblock for this encryption */
30268591Sdab
30368591Sdab krb5_use_cstype(&eblock, etype);
30468591Sdab ret_cred.enc_part.ciphertext.length = krb5_encrypt_size(scratch->length,
30568591Sdab eblock.crypto_entry);
30668591Sdab /* add padding area, and zero it */
30768591Sdab if (!(scratch->data = realloc(scratch->data,
30868591Sdab ret_cred.enc_part.ciphertext.length))) {
30968591Sdab /* may destroy scratch->data */
31068591Sdab krb5_xfree(scratch);
31168591Sdab return ENOMEM;
31268591Sdab }
31368591Sdab memset(scratch->data + scratch->length, 0,
31468591Sdab ret_cred.enc_part.ciphertext.length - scratch->length);
31568591Sdab if (!(ret_cred.enc_part.ciphertext.data =
31668591Sdab malloc(ret_cred.enc_part.ciphertext.length))) {
317*69784Sdab retval = ENOMEM;
318*69784Sdab goto clean_scratch;
31968591Sdab }
32068591Sdab
32168591Sdab #define cleanup_encpart() {\
32268591Sdab (void) memset(ret_cred.enc_part.ciphertext.data, 0, \
32368591Sdab ret_cred.enc_part.ciphertext.length); \
32468591Sdab free(ret_cred.enc_part.ciphertext.data); \
32568591Sdab ret_cred.enc_part.ciphertext.length = 0; \
32668591Sdab ret_cred.enc_part.ciphertext.data = 0;}
32768591Sdab
32868591Sdab /* do any necessary key pre-processing */
32968591Sdab if (retval = krb5_process_key(&eblock, key)) {
330*69784Sdab goto clean_encpart;
33168591Sdab }
33268591Sdab
33368591Sdab #define cleanup_prockey() {(void) krb5_finish_key(&eblock);}
33468591Sdab
33568591Sdab /* call the encryption routine */
33668591Sdab if (retval = krb5_encrypt((krb5_pointer) scratch->data,
33768591Sdab (krb5_pointer)
338*69784Sdab ret_cred.enc_part.ciphertext.data,
33968591Sdab scratch->length, &eblock,
34068591Sdab 0)) {
341*69784Sdab goto clean_prockey;
34268591Sdab }
343*69784Sdab
34468591Sdab /* private message is now assembled-- do some cleanup */
34568591Sdab cleanup_scratch();
34668591Sdab
34768591Sdab if (retval = krb5_finish_key(&eblock)) {
348*69784Sdab cleanup_encpart();
349*69784Sdab return retval;
35068591Sdab }
35168591Sdab /* encode private message */
35268591Sdab if (retval = encode_krb5_cred(&ret_cred, &scratch)) {
353*69784Sdab cleanup_encpart();
35468591Sdab return retval;
35568591Sdab }
35668591Sdab
35768591Sdab cleanup_encpart();
35868591Sdab
35968591Sdab *outbuf = *scratch;
36068591Sdab krb5_xfree(scratch);
36168591Sdab return 0;
36268591Sdab
36368591Sdab clean_prockey:
36468591Sdab cleanup_prockey();
36568591Sdab clean_encpart:
36668591Sdab cleanup_encpart();
36768591Sdab clean_scratch:
36868591Sdab cleanup_scratch();
36968591Sdab
37068591Sdab return retval;
37168591Sdab #undef cleanup_prockey
37268591Sdab #undef cleanup_encpart
37368591Sdab #undef cleanup_scratch
37468591Sdab }
37568591Sdab
37668591Sdab
37768591Sdab
37868591Sdab /* Decode, decrypt and store the forwarded creds in the local ccache. */
37968591Sdab krb5_error_code
rd_and_store_for_creds(inbuf,ticket,lusername)38068591Sdab rd_and_store_for_creds(inbuf, ticket, lusername)
38168591Sdab krb5_data *inbuf;
38268591Sdab krb5_ticket *ticket;
38368591Sdab char *lusername;
38468591Sdab {
38568591Sdab krb5_encrypt_block eblock;
38668591Sdab krb5_creds creds;
38768591Sdab krb5_error_code retval;
38868591Sdab char ccname[35];
38968591Sdab krb5_ccache ccache = NULL;
39068591Sdab struct passwd *pwd;
39168591Sdab
392*69784Sdab if (retval = rd_cred(inbuf, ticket->enc_part2->session,
39368591Sdab &creds, 0, 0)) {
39468591Sdab return(retval);
39568591Sdab }
396*69784Sdab
39768591Sdab if (!(pwd = (struct passwd *) getpwnam(lusername))) {
39868591Sdab return -1;
39968591Sdab }
40068591Sdab
40168591Sdab sprintf(ccname, "FILE:/tmp/krb5cc_%d", pwd->pw_uid);
40268591Sdab
40368591Sdab if (retval = krb5_cc_resolve(ccname, &ccache)) {
40468591Sdab return(retval);
40568591Sdab }
40668591Sdab
40768591Sdab if (retval = krb5_cc_initialize(ccache,
40868591Sdab ticket->enc_part2->client)) {
40968591Sdab return(retval);
41068591Sdab }
41168591Sdab
41268591Sdab if (retval = krb5_cc_store_cred(ccache, &creds)) {
41368591Sdab return(retval);
41468591Sdab }
41568591Sdab
41668591Sdab if (retval = chown(ccname+5, pwd->pw_uid, -1)) {
41768591Sdab return(retval);
41868591Sdab }
41968591Sdab
42068591Sdab return retval;
42168591Sdab }
42268591Sdab
42368591Sdab
42468591Sdab
425*69784Sdab extern krb5_deltat krb5_clockskew;
42668591Sdab #define in_clock_skew(date) (abs((date)-currenttime) < krb5_clockskew)
42768591Sdab
42868591Sdab /* Decode the KRB-CRED message, and return creds */
42968591Sdab krb5_error_code
rd_cred(inbuf,key,creds,sender_addr,recv_addr)43068591Sdab rd_cred(inbuf, key, creds, sender_addr, recv_addr)
43168591Sdab const krb5_data *inbuf;
43268591Sdab const krb5_keyblock *key;
433*69784Sdab krb5_creds *creds; /* Filled in */
43468591Sdab const krb5_address *sender_addr; /* optional */
435*69784Sdab const krb5_address *recv_addr; /* optional */
43668591Sdab {
43768591Sdab krb5_error_code retval;
43868591Sdab krb5_encrypt_block eblock;
43968591Sdab krb5_cred *credmsg;
44068591Sdab krb5_cred_enc_part *credmsg_enc_part;
44168591Sdab krb5_data *scratch;
44268591Sdab krb5_timestamp currenttime;
44368591Sdab
44468591Sdab if (!krb5_is_krb_cred(inbuf))
44568591Sdab return KRB5KRB_AP_ERR_MSG_TYPE;
446*69784Sdab
44768591Sdab /* decode private message */
44868591Sdab if (retval = decode_krb5_cred(inbuf, &credmsg)) {
44968591Sdab return retval;
45068591Sdab }
451*69784Sdab
45268591Sdab #define cleanup_credmsg() {(void)krb5_xfree(credmsg->enc_part.ciphertext.data); (void)krb5_xfree(credmsg);}
45368591Sdab
45468591Sdab if (!(scratch = (krb5_data *) malloc(sizeof(*scratch)))) {
45568591Sdab cleanup_credmsg();
45668591Sdab return ENOMEM;
45768591Sdab }
45868591Sdab
45968591Sdab #define cleanup_scratch() {(void)memset(scratch->data, 0, scratch->length); (void)krb5_xfree(scratch->data);}
46068591Sdab
46168591Sdab if (retval = encode_krb5_ticket(credmsg->tickets[0], &scratch)) {
46268591Sdab cleanup_credmsg();
46368591Sdab cleanup_scratch();
46468591Sdab return(retval);
46568591Sdab }
46668591Sdab
46768591Sdab creds->ticket = *scratch;
46868591Sdab if (!(creds->ticket.data = malloc(scratch->length))) {
46968591Sdab krb5_xfree(creds->ticket.data);
47068591Sdab return ENOMEM;
47168591Sdab }
472*69784Sdab memmove((char *)creds->ticket.data, (char *) scratch->data, scratch->length);
47368591Sdab
47468591Sdab cleanup_scratch();
47568591Sdab
47668591Sdab if (!valid_etype(credmsg->enc_part.etype)) {
47768591Sdab cleanup_credmsg();
47868591Sdab return KRB5_PROG_ETYPE_NOSUPP;
47968591Sdab }
48068591Sdab
48168591Sdab /* put together an eblock for this decryption */
48268591Sdab
48368591Sdab krb5_use_cstype(&eblock, credmsg->enc_part.etype);
48468591Sdab scratch->length = credmsg->enc_part.ciphertext.length;
485*69784Sdab
48668591Sdab if (!(scratch->data = malloc(scratch->length))) {
48768591Sdab cleanup_credmsg();
488*69784Sdab return ENOMEM;
48968591Sdab }
49068591Sdab
49168591Sdab /* do any necessary key pre-processing */
49268591Sdab if (retval = krb5_process_key(&eblock, key)) {
493*69784Sdab cleanup_credmsg();
49468591Sdab cleanup_scratch();
49568591Sdab return retval;
49668591Sdab }
497*69784Sdab
49868591Sdab #define cleanup_prockey() {(void) krb5_finish_key(&eblock);}
499*69784Sdab
50068591Sdab /* call the decryption routine */
50168591Sdab if (retval = krb5_decrypt((krb5_pointer) credmsg->enc_part.ciphertext.data,
50268591Sdab (krb5_pointer) scratch->data,
50368591Sdab scratch->length, &eblock,
50468591Sdab 0)) {
50568591Sdab cleanup_credmsg();
50668591Sdab cleanup_scratch();
507*69784Sdab cleanup_prockey();
50868591Sdab return retval;
50968591Sdab }
51068591Sdab
51168591Sdab /* cred message is now decrypted -- do some cleanup */
51268591Sdab
51368591Sdab cleanup_credmsg();
51468591Sdab
51568591Sdab if (retval = krb5_finish_key(&eblock)) {
516*69784Sdab cleanup_scratch();
517*69784Sdab return retval;
51868591Sdab }
51968591Sdab
52068591Sdab /* now decode the decrypted stuff */
52168591Sdab if (retval = decode_krb5_enc_cred_part(scratch, &credmsg_enc_part)) {
52268591Sdab cleanup_scratch();
52368591Sdab return retval;
52468591Sdab }
52568591Sdab cleanup_scratch();
52668591Sdab
52768591Sdab #define cleanup_mesg() {(void)krb5_xfree(credmsg_enc_part);}
52868591Sdab
52968591Sdab if (retval = krb5_timeofday(¤ttime)) {
53068591Sdab cleanup_mesg();
53168591Sdab return retval;
53268591Sdab }
53368591Sdab if (!in_clock_skew(credmsg_enc_part->timestamp)) {
534*69784Sdab cleanup_mesg();
53568591Sdab return KRB5KRB_AP_ERR_SKEW;
53668591Sdab }
53768591Sdab
53868591Sdab if (sender_addr && credmsg_enc_part->s_address &&
539*69784Sdab !krb5_address_compare(sender_addr,
54068591Sdab credmsg_enc_part->s_address)) {
54168591Sdab cleanup_mesg();
54268591Sdab return KRB5KRB_AP_ERR_BADADDR;
54368591Sdab }
54468591Sdab if (recv_addr && credmsg_enc_part->r_address &&
545*69784Sdab !krb5_address_compare(recv_addr,
54668591Sdab credmsg_enc_part->r_address)) {
54768591Sdab cleanup_mesg();
54868591Sdab return KRB5KRB_AP_ERR_BADADDR;
549*69784Sdab }
55068591Sdab
55168591Sdab if (credmsg_enc_part->r_address) {
55268591Sdab krb5_address **our_addrs;
553*69784Sdab
55468591Sdab if (retval = krb5_os_localaddr(&our_addrs)) {
55568591Sdab cleanup_mesg();
55668591Sdab return retval;
55768591Sdab }
558*69784Sdab if (!krb5_address_search(credmsg_enc_part->r_address,
55968591Sdab our_addrs)) {
56068591Sdab krb5_free_addresses(our_addrs);
56168591Sdab cleanup_mesg();
56268591Sdab return KRB5KRB_AP_ERR_BADADDR;
56368591Sdab }
56468591Sdab krb5_free_addresses(our_addrs);
56568591Sdab }
56668591Sdab
56768591Sdab if (retval = krb5_copy_principal(credmsg_enc_part->ticket_info[0]->client,
56868591Sdab &creds->client)) {
56968591Sdab return(retval);
57068591Sdab }
57168591Sdab
57268591Sdab if (retval = krb5_copy_principal(credmsg_enc_part->ticket_info[0]->server,
57368591Sdab &creds->server)) {
57468591Sdab return(retval);
575*69784Sdab }
57668591Sdab
57768591Sdab if (retval =
578*69784Sdab krb5_copy_keyblock_contents(credmsg_enc_part->ticket_info[0]->session,
57968591Sdab &creds->keyblock)) {
58068591Sdab return(retval);
58168591Sdab }
58268591Sdab
58368591Sdab #undef clean
58468591Sdab #define clean() {\
58568591Sdab memset((char *)creds->keyblock.contents, 0, creds->keyblock.length);}
58668591Sdab
58768591Sdab creds->times = credmsg_enc_part->ticket_info[0]->times;
58868591Sdab creds->is_skey = FALSE;
58968591Sdab creds->ticket_flags = credmsg_enc_part->ticket_info[0]->flags;
59068591Sdab
59168591Sdab if (retval = krb5_copy_addresses(credmsg_enc_part->ticket_info[0]->caddrs,
59268591Sdab &creds->addresses)) {
59368591Sdab clean();
59468591Sdab return(retval);
59568591Sdab }
59668591Sdab
59768591Sdab creds->second_ticket.length = 0;
59868591Sdab
59968591Sdab creds->authdata = 0;
60068591Sdab
60168591Sdab cleanup_mesg();
60268591Sdab return 0;
60368591Sdab #undef clean
60468591Sdab #undef cleanup_credmsg
60568591Sdab #undef cleanup_scratch
60668591Sdab #undef cleanup_prockey
60768591Sdab #undef cleanup_mesg
60868591Sdab }
60968591Sdab
61068591Sdab #endif /* defined(KRB5) && defined(FORWARD) */
611