17c478bd9Sstevel@tonic-gate /*
2*5e01956fSGlenn Barry * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
3*5e01956fSGlenn Barry */
4*5e01956fSGlenn Barry /*
57c478bd9Sstevel@tonic-gate * lib/krb5/krb/gc_via_tgt.c
67c478bd9Sstevel@tonic-gate *
77c478bd9Sstevel@tonic-gate * Copyright 1990,1991 by the Massachusetts Institute of Technology.
87c478bd9Sstevel@tonic-gate * All Rights Reserved.
97c478bd9Sstevel@tonic-gate *
107c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may
117c478bd9Sstevel@tonic-gate * require a specific license from the United States Government.
127c478bd9Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating
137c478bd9Sstevel@tonic-gate * export to obtain such a license before exporting.
147c478bd9Sstevel@tonic-gate *
157c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
167c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and
177c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright
187c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and
197c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that
207c478bd9Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining
217c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior
227c478bd9Sstevel@tonic-gate * permission. Furthermore if you modify this software you must label
237c478bd9Sstevel@tonic-gate * your software as modified software and not distribute it in such a
247c478bd9Sstevel@tonic-gate * fashion that it might be confused with the original M.I.T. software.
257c478bd9Sstevel@tonic-gate * M.I.T. makes no representations about the suitability of
267c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express
277c478bd9Sstevel@tonic-gate * or implied warranty.
287c478bd9Sstevel@tonic-gate *
297c478bd9Sstevel@tonic-gate *
307c478bd9Sstevel@tonic-gate * Given a tkt, and a target cred, get it.
317c478bd9Sstevel@tonic-gate * Assumes that the kdc_rep has been decrypted.
327c478bd9Sstevel@tonic-gate */
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate #include "k5-int.h"
357c478bd9Sstevel@tonic-gate #include "int-proto.h"
36*5e01956fSGlenn Barry #include <locale.h>
37*5e01956fSGlenn Barry #include <ctype.h>
38fe598cdcSmp153739
397c478bd9Sstevel@tonic-gate static krb5_error_code
krb5_kdcrep2creds(krb5_context context,krb5_kdc_rep * pkdcrep,krb5_address * const * address,krb5_data * psectkt,krb5_creds ** ppcreds)40505d05c7Sgtb krb5_kdcrep2creds(krb5_context context, krb5_kdc_rep *pkdcrep, krb5_address *const *address, krb5_data *psectkt, krb5_creds **ppcreds)
417c478bd9Sstevel@tonic-gate {
427c478bd9Sstevel@tonic-gate krb5_error_code retval;
437c478bd9Sstevel@tonic-gate krb5_data *pdata;
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate if ((*ppcreds = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL) {
467c478bd9Sstevel@tonic-gate return ENOMEM;
477c478bd9Sstevel@tonic-gate }
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate memset(*ppcreds, 0, sizeof(krb5_creds));
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gate if ((retval = krb5_copy_principal(context, pkdcrep->client,
527c478bd9Sstevel@tonic-gate &(*ppcreds)->client)))
537c478bd9Sstevel@tonic-gate goto cleanup;
547c478bd9Sstevel@tonic-gate
557c478bd9Sstevel@tonic-gate if ((retval = krb5_copy_principal(context, pkdcrep->enc_part2->server,
567c478bd9Sstevel@tonic-gate &(*ppcreds)->server)))
577c478bd9Sstevel@tonic-gate goto cleanup;
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate if ((retval = krb5_copy_keyblock_contents(context,
607c478bd9Sstevel@tonic-gate pkdcrep->enc_part2->session,
617c478bd9Sstevel@tonic-gate &(*ppcreds)->keyblock)))
627c478bd9Sstevel@tonic-gate goto cleanup;
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate if ((retval = krb5_copy_data(context, psectkt, &pdata)))
657c478bd9Sstevel@tonic-gate goto cleanup;
667c478bd9Sstevel@tonic-gate (*ppcreds)->second_ticket = *pdata;
677c478bd9Sstevel@tonic-gate krb5_xfree(pdata);
687c478bd9Sstevel@tonic-gate
697c478bd9Sstevel@tonic-gate (*ppcreds)->ticket_flags = pkdcrep->enc_part2->flags;
707c478bd9Sstevel@tonic-gate (*ppcreds)->times = pkdcrep->enc_part2->times;
717c478bd9Sstevel@tonic-gate (*ppcreds)->magic = KV5M_CREDS;
727c478bd9Sstevel@tonic-gate
737c478bd9Sstevel@tonic-gate (*ppcreds)->authdata = NULL; /* not used */
747c478bd9Sstevel@tonic-gate (*ppcreds)->is_skey = psectkt->length != 0;
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate if (pkdcrep->enc_part2->caddrs) {
777c478bd9Sstevel@tonic-gate if ((retval = krb5_copy_addresses(context, pkdcrep->enc_part2->caddrs,
787c478bd9Sstevel@tonic-gate &(*ppcreds)->addresses)))
797c478bd9Sstevel@tonic-gate goto cleanup_keyblock;
807c478bd9Sstevel@tonic-gate } else {
817c478bd9Sstevel@tonic-gate /* no addresses in the list means we got what we had */
827c478bd9Sstevel@tonic-gate if ((retval = krb5_copy_addresses(context, address,
837c478bd9Sstevel@tonic-gate &(*ppcreds)->addresses)))
847c478bd9Sstevel@tonic-gate goto cleanup_keyblock;
857c478bd9Sstevel@tonic-gate }
867c478bd9Sstevel@tonic-gate
877c478bd9Sstevel@tonic-gate if ((retval = encode_krb5_ticket(pkdcrep->ticket, &pdata)))
887c478bd9Sstevel@tonic-gate goto cleanup_keyblock;
897c478bd9Sstevel@tonic-gate
907c478bd9Sstevel@tonic-gate (*ppcreds)->ticket = *pdata;
917c478bd9Sstevel@tonic-gate free(pdata);
927c478bd9Sstevel@tonic-gate return 0;
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate cleanup_keyblock:
957c478bd9Sstevel@tonic-gate krb5_free_keyblock(context, &(*ppcreds)->keyblock);
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate cleanup:
987c478bd9Sstevel@tonic-gate free (*ppcreds);
997c478bd9Sstevel@tonic-gate return retval;
1007c478bd9Sstevel@tonic-gate }
1017c478bd9Sstevel@tonic-gate
102fe598cdcSmp153739 static krb5_error_code
check_reply_server(krb5_context context,krb5_flags kdcoptions,krb5_creds * in_cred,krb5_kdc_rep * dec_rep)103fe598cdcSmp153739 check_reply_server(krb5_context context, krb5_flags kdcoptions,
104fe598cdcSmp153739 krb5_creds *in_cred, krb5_kdc_rep *dec_rep)
105fe598cdcSmp153739 {
106fe598cdcSmp153739
107fe598cdcSmp153739 if (!krb5_principal_compare(context, dec_rep->ticket->server,
108fe598cdcSmp153739 dec_rep->enc_part2->server))
109fe598cdcSmp153739 return KRB5_KDCREP_MODIFIED;
110fe598cdcSmp153739
111fe598cdcSmp153739 /* Reply is self-consistent. */
112fe598cdcSmp153739
113fe598cdcSmp153739 if (krb5_principal_compare(context, dec_rep->ticket->server,
114fe598cdcSmp153739 in_cred->server))
115fe598cdcSmp153739 return 0;
116fe598cdcSmp153739
117fe598cdcSmp153739 /* Server in reply differs from what we requested. */
118fe598cdcSmp153739
119fe598cdcSmp153739 if (kdcoptions & KDC_OPT_CANONICALIZE) {
120fe598cdcSmp153739 /* in_cred server differs from ticket returned, but ticket
121fe598cdcSmp153739 returned is consistent and we requested canonicalization. */
122fe598cdcSmp153739 #if 0
123fe598cdcSmp153739 #ifdef DEBUG_REFERRALS
124fe598cdcSmp153739 printf("gc_via_tkt: in_cred and encoding don't match but referrals requested\n");
125fe598cdcSmp153739 krb5int_dbgref_dump_principal("gc_via_tkt: in_cred",in_cred->server);
126fe598cdcSmp153739 krb5int_dbgref_dump_principal("gc_via_tkt: encoded server",dec_rep->enc_part2->server);
127fe598cdcSmp153739 #endif
128fe598cdcSmp153739 #endif
129fe598cdcSmp153739 return 0;
130fe598cdcSmp153739 }
131fe598cdcSmp153739
132fe598cdcSmp153739 /* We didn't request canonicalization. */
133fe598cdcSmp153739
134fe598cdcSmp153739 if (!IS_TGS_PRINC(context, in_cred->server) ||
135fe598cdcSmp153739 !IS_TGS_PRINC(context, dec_rep->ticket->server)) {
136fe598cdcSmp153739 /* Canonicalization not requested, and not a TGS referral. */
137fe598cdcSmp153739 return KRB5_KDCREP_MODIFIED;
138fe598cdcSmp153739 }
139fe598cdcSmp153739 #if 0
140fe598cdcSmp153739 /*
141fe598cdcSmp153739 * Is this check needed? find_nxt_kdc() in gc_frm_kdc.c already
142fe598cdcSmp153739 * effectively checks this.
143fe598cdcSmp153739 */
144fe598cdcSmp153739 if (krb5_realm_compare(context, in_cred->client, in_cred->server) &&
145fe598cdcSmp153739 in_cred->server->data[1].length == in_cred->client->realm.length &&
146fe598cdcSmp153739 !memcmp(in_cred->client->realm.data, in_cred->server->data[1].data,
147fe598cdcSmp153739 in_cred->client->realm.length)) {
148fe598cdcSmp153739 /* Attempted to rewrite local TGS. */
149fe598cdcSmp153739 return KRB5_KDCREP_MODIFIED;
150fe598cdcSmp153739 }
151fe598cdcSmp153739 #endif
152fe598cdcSmp153739 return 0;
153fe598cdcSmp153739 }
154fe598cdcSmp153739
1557c478bd9Sstevel@tonic-gate krb5_error_code
krb5_get_cred_via_tkt(krb5_context context,krb5_creds * tkt,krb5_flags kdcoptions,krb5_address * const * address,krb5_creds * in_cred,krb5_creds ** out_cred)156505d05c7Sgtb krb5_get_cred_via_tkt (krb5_context context, krb5_creds *tkt,
157505d05c7Sgtb krb5_flags kdcoptions, krb5_address *const *address,
158505d05c7Sgtb krb5_creds *in_cred, krb5_creds **out_cred)
1597c478bd9Sstevel@tonic-gate {
1607c478bd9Sstevel@tonic-gate krb5_error_code retval;
1617c478bd9Sstevel@tonic-gate krb5_kdc_rep *dec_rep;
1627c478bd9Sstevel@tonic-gate krb5_error *err_reply;
1637c478bd9Sstevel@tonic-gate krb5_response tgsrep;
1647c478bd9Sstevel@tonic-gate krb5_enctype *enctypes = 0;
165*5e01956fSGlenn Barry char *hostname_used = NULL;
1667c478bd9Sstevel@tonic-gate
167fe598cdcSmp153739 #ifdef DEBUG_REFERRALS
168fe598cdcSmp153739 printf("krb5_get_cred_via_tkt starting; referral flag is %s\n", kdcoptions&KDC_OPT_CANONICALIZE?"on":"off");
169fe598cdcSmp153739 krb5int_dbgref_dump_principal("krb5_get_cred_via_tkt requested ticket", in_cred->server);
170fe598cdcSmp153739 krb5int_dbgref_dump_principal("krb5_get_cred_via_tkt TGT in use", tkt->server);
171fe598cdcSmp153739 #endif
172fe598cdcSmp153739
1737c478bd9Sstevel@tonic-gate /* tkt->client must be equal to in_cred->client */
174*5e01956fSGlenn Barry if (!krb5_principal_compare(context, tkt->client, in_cred->client)) {
175*5e01956fSGlenn Barry /* Solaris Kerberos */
176*5e01956fSGlenn Barry char *r_name = NULL;
177*5e01956fSGlenn Barry char *t_name = NULL;
178*5e01956fSGlenn Barry krb5_error_code r_err, t_err;
179*5e01956fSGlenn Barry t_err = krb5_unparse_name(context, tkt->client, &t_name);
180*5e01956fSGlenn Barry r_err = krb5_unparse_name(context, in_cred->client, &r_name);
181*5e01956fSGlenn Barry krb5_set_error_message(context, KRB5_PRINC_NOMATCH,
182*5e01956fSGlenn Barry dgettext(TEXT_DOMAIN,
183*5e01956fSGlenn Barry "Requested principal and ticket don't match: Requested principal is '%s' and ticket is '%s'"),
184*5e01956fSGlenn Barry r_err ? "unknown" : r_name,
185*5e01956fSGlenn Barry t_err ? "unknown" : t_name);
186*5e01956fSGlenn Barry if (r_name)
187*5e01956fSGlenn Barry krb5_free_unparsed_name(context, r_name);
188*5e01956fSGlenn Barry if (t_name)
189*5e01956fSGlenn Barry krb5_free_unparsed_name(context, t_name);
1907c478bd9Sstevel@tonic-gate return KRB5_PRINC_NOMATCH;
191*5e01956fSGlenn Barry }
1927c478bd9Sstevel@tonic-gate
1937c478bd9Sstevel@tonic-gate if (!tkt->ticket.length)
1947c478bd9Sstevel@tonic-gate return KRB5_NO_TKT_SUPPLIED;
1957c478bd9Sstevel@tonic-gate
1967c478bd9Sstevel@tonic-gate if ((kdcoptions & KDC_OPT_ENC_TKT_IN_SKEY) &&
1977c478bd9Sstevel@tonic-gate (!in_cred->second_ticket.length))
1987c478bd9Sstevel@tonic-gate return(KRB5_NO_2ND_TKT);
1997c478bd9Sstevel@tonic-gate
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate /* check if we have the right TGT */
2027c478bd9Sstevel@tonic-gate /* tkt->server must be equal to */
2037c478bd9Sstevel@tonic-gate /* krbtgt/realmof(cred->server)@realmof(tgt->server) */
2047c478bd9Sstevel@tonic-gate /*
2057c478bd9Sstevel@tonic-gate {
2067c478bd9Sstevel@tonic-gate krb5_principal tempprinc;
2077c478bd9Sstevel@tonic-gate if (retval = krb5_tgtname(context,
2087c478bd9Sstevel@tonic-gate krb5_princ_realm(context, in_cred->server),
2097c478bd9Sstevel@tonic-gate krb5_princ_realm(context, tkt->server), &tempprinc))
2107c478bd9Sstevel@tonic-gate return(retval);
2117c478bd9Sstevel@tonic-gate
2127c478bd9Sstevel@tonic-gate if (!krb5_principal_compare(context, tempprinc, tkt->server)) {
2137c478bd9Sstevel@tonic-gate krb5_free_principal(context, tempprinc);
2147c478bd9Sstevel@tonic-gate return (KRB5_PRINC_NOMATCH);
2157c478bd9Sstevel@tonic-gate }
2167c478bd9Sstevel@tonic-gate krb5_free_principal(context, tempprinc);
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate */
2197c478bd9Sstevel@tonic-gate
2207c478bd9Sstevel@tonic-gate if (in_cred->keyblock.enctype) {
2217c478bd9Sstevel@tonic-gate enctypes = (krb5_enctype *) malloc(sizeof(krb5_enctype)*2);
2227c478bd9Sstevel@tonic-gate if (!enctypes)
2237c478bd9Sstevel@tonic-gate return ENOMEM;
2247c478bd9Sstevel@tonic-gate enctypes[0] = in_cred->keyblock.enctype;
2257c478bd9Sstevel@tonic-gate enctypes[1] = 0;
2267c478bd9Sstevel@tonic-gate }
2277c478bd9Sstevel@tonic-gate
228*5e01956fSGlenn Barry retval = krb5_send_tgs2(context, kdcoptions, &in_cred->times, enctypes,
2297c478bd9Sstevel@tonic-gate in_cred->server, address, in_cred->authdata,
2307c478bd9Sstevel@tonic-gate 0, /* no padata */
2317c478bd9Sstevel@tonic-gate (kdcoptions & KDC_OPT_ENC_TKT_IN_SKEY) ?
2327c478bd9Sstevel@tonic-gate &in_cred->second_ticket : NULL,
233*5e01956fSGlenn Barry tkt, &tgsrep, &hostname_used);
2347c478bd9Sstevel@tonic-gate if (enctypes)
2357c478bd9Sstevel@tonic-gate free(enctypes);
236fe598cdcSmp153739 if (retval) {
237fe598cdcSmp153739 #ifdef DEBUG_REFERRALS
238fe598cdcSmp153739 printf("krb5_get_cred_via_tkt ending early after send_tgs with: %s\n",
239fe598cdcSmp153739 error_message(retval));
240fe598cdcSmp153739 #endif
2417c478bd9Sstevel@tonic-gate return retval;
242fe598cdcSmp153739 }
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate switch (tgsrep.message_type) {
2457c478bd9Sstevel@tonic-gate case KRB5_TGS_REP:
2467c478bd9Sstevel@tonic-gate break;
2477c478bd9Sstevel@tonic-gate case KRB5_ERROR:
2487c478bd9Sstevel@tonic-gate default:
2497c478bd9Sstevel@tonic-gate if (krb5_is_krb_error(&tgsrep.response))
2507c478bd9Sstevel@tonic-gate retval = decode_krb5_error(&tgsrep.response, &err_reply);
2517c478bd9Sstevel@tonic-gate else
2527c478bd9Sstevel@tonic-gate retval = KRB5KRB_AP_ERR_MSG_TYPE;
2537c478bd9Sstevel@tonic-gate
2547c478bd9Sstevel@tonic-gate if (retval) /* neither proper reply nor error! */
2557c478bd9Sstevel@tonic-gate goto error_4;
2567c478bd9Sstevel@tonic-gate
257505d05c7Sgtb retval = (krb5_error_code) err_reply->error + ERROR_TABLE_BASE_krb5;
258159d09a2SMark Phalan if (err_reply->text.length > 0) {
259159d09a2SMark Phalan #if 0
260159d09a2SMark Phalan const char *m;
261159d09a2SMark Phalan #endif
262159d09a2SMark Phalan switch (err_reply->error) {
263159d09a2SMark Phalan case KRB_ERR_GENERIC:
264159d09a2SMark Phalan krb5_set_error_message(context, retval,
265*5e01956fSGlenn Barry /* Solaris Kerberos - added dgettext */
266*5e01956fSGlenn Barry dgettext(TEXT_DOMAIN,
267*5e01956fSGlenn Barry "KDC returned error string: %s"),
268159d09a2SMark Phalan err_reply->text.data);
269159d09a2SMark Phalan break;
270*5e01956fSGlenn Barry case KDC_ERR_S_PRINCIPAL_UNKNOWN:
271*5e01956fSGlenn Barry {
272*5e01956fSGlenn Barry char *s_name;
273*5e01956fSGlenn Barry if (krb5_unparse_name(context, in_cred->server, &s_name) ==
274*5e01956fSGlenn Barry 0) {
275*5e01956fSGlenn Barry /* Solaris Kerberos - added dgettext */
276*5e01956fSGlenn Barry krb5_set_error_message(context, retval,
277*5e01956fSGlenn Barry dgettext(TEXT_DOMAIN,
278*5e01956fSGlenn Barry "Server %s not found in Kerberos database"),
279*5e01956fSGlenn Barry s_name);
280*5e01956fSGlenn Barry krb5_free_unparsed_name(context, s_name);
281*5e01956fSGlenn Barry } else
282*5e01956fSGlenn Barry /* In case there's a stale S_PRINCIPAL_UNKNOWN
283*5e01956fSGlenn Barry report already noted. */
284*5e01956fSGlenn Barry krb5_clear_error_message(context);
285*5e01956fSGlenn Barry }
286*5e01956fSGlenn Barry break;
287*5e01956fSGlenn Barry
288*5e01956fSGlenn Barry case KRB_AP_ERR_SKEW:
289*5e01956fSGlenn Barry /* Solaris Kerberos */
290*5e01956fSGlenn Barry {
291*5e01956fSGlenn Barry char *s_name = NULL;
292*5e01956fSGlenn Barry char *c_name = NULL;
293*5e01956fSGlenn Barry char stimestring[17];
294*5e01956fSGlenn Barry char ctimestring[17];
295*5e01956fSGlenn Barry char fill = ' ';
296*5e01956fSGlenn Barry int st_err, ct_err, serr, cerr;
297*5e01956fSGlenn Barry
298*5e01956fSGlenn Barry st_err = krb5_timestamp_to_sfstring(err_reply->stime,
299*5e01956fSGlenn Barry stimestring,
300*5e01956fSGlenn Barry sizeof (stimestring),
301*5e01956fSGlenn Barry &fill);
302*5e01956fSGlenn Barry ct_err = krb5_timestamp_to_sfstring(err_reply->ctime,
303*5e01956fSGlenn Barry ctimestring,
304*5e01956fSGlenn Barry sizeof (ctimestring),
305*5e01956fSGlenn Barry &fill);
306*5e01956fSGlenn Barry serr = krb5_unparse_name(context, in_cred->server, &s_name);
307*5e01956fSGlenn Barry cerr = krb5_unparse_name(context, in_cred->client, &c_name);
308*5e01956fSGlenn Barry krb5_set_error_message(context, retval,
309*5e01956fSGlenn Barry dgettext(TEXT_DOMAIN,
310*5e01956fSGlenn Barry "Clock skew too great: '%s' requesting ticket '%s' from KDC '%s' (%s). Skew is %dm."),
311*5e01956fSGlenn Barry cerr == 0 ? c_name : "unknown",
312*5e01956fSGlenn Barry serr == 0 ? s_name : "unknown",
313*5e01956fSGlenn Barry hostname_used ?
314*5e01956fSGlenn Barry hostname_used : "host unknown",
315*5e01956fSGlenn Barry st_err == 0 ? stimestring : "unknown",
316*5e01956fSGlenn Barry (ct_err||st_err) ? 0 :
317*5e01956fSGlenn Barry abs(err_reply->stime -
318*5e01956fSGlenn Barry err_reply->ctime) / 60);
319*5e01956fSGlenn Barry
320*5e01956fSGlenn Barry if (s_name)
321*5e01956fSGlenn Barry krb5_free_unparsed_name(context, s_name);
322*5e01956fSGlenn Barry if (c_name)
323*5e01956fSGlenn Barry krb5_free_unparsed_name(context, c_name);
324*5e01956fSGlenn Barry }
325*5e01956fSGlenn Barry break;
326*5e01956fSGlenn Barry case KRB_AP_ERR_TKT_NYV:
327*5e01956fSGlenn Barry /* Solaris Kerberos */
328*5e01956fSGlenn Barry {
329*5e01956fSGlenn Barry char *s_name = NULL;
330*5e01956fSGlenn Barry char *c_name = NULL;
331*5e01956fSGlenn Barry char timestring[17];
332*5e01956fSGlenn Barry char stimestring[17];
333*5e01956fSGlenn Barry char fill = ' ';
334*5e01956fSGlenn Barry krb5_error_code t_err, st_err, cerr, serr;
335*5e01956fSGlenn Barry
336*5e01956fSGlenn Barry t_err = krb5_timestamp_to_sfstring(tkt->times.starttime,
337*5e01956fSGlenn Barry timestring,
338*5e01956fSGlenn Barry sizeof (timestring),
339*5e01956fSGlenn Barry &fill);
340*5e01956fSGlenn Barry st_err = krb5_timestamp_to_sfstring(err_reply->stime,
341*5e01956fSGlenn Barry stimestring,
342*5e01956fSGlenn Barry sizeof (stimestring),
343*5e01956fSGlenn Barry &fill);
344*5e01956fSGlenn Barry serr = krb5_unparse_name(context, in_cred->server, &s_name);
345*5e01956fSGlenn Barry cerr = krb5_unparse_name(context, in_cred->client, &c_name);
346*5e01956fSGlenn Barry krb5_set_error_message(context, retval,
347*5e01956fSGlenn Barry dgettext(TEXT_DOMAIN,
348*5e01956fSGlenn Barry "Ticket not yet valid: '%s' requesting ticket '%s' from '%s' (%s). TGT start time is %s"),
349*5e01956fSGlenn Barry cerr ? "unknown" : c_name,
350*5e01956fSGlenn Barry serr ? "unknown" : s_name,
351*5e01956fSGlenn Barry hostname_used ? hostname_used : "host unknown",
352*5e01956fSGlenn Barry st_err ? "unknown" : stimestring,
353*5e01956fSGlenn Barry t_err ? "unknown" : timestring);
354*5e01956fSGlenn Barry if (s_name)
355*5e01956fSGlenn Barry krb5_free_unparsed_name(context, s_name);
356*5e01956fSGlenn Barry if (c_name)
357*5e01956fSGlenn Barry krb5_free_unparsed_name(context, c_name);
358*5e01956fSGlenn Barry }
359*5e01956fSGlenn Barry break;
360159d09a2SMark Phalan default:
361159d09a2SMark Phalan #if 0 /* We should stop the KDC from sending back this text, because
362159d09a2SMark Phalan if the local language doesn't match the KDC's language, we'd
363159d09a2SMark Phalan just wind up printing out the error message in two languages.
364159d09a2SMark Phalan Well, when we get some localization. Which is already
365159d09a2SMark Phalan happening in KfM. */
366159d09a2SMark Phalan m = error_message(retval);
367159d09a2SMark Phalan /* Special case: MIT KDC may return this same string
368159d09a2SMark Phalan in the e-text field. */
369159d09a2SMark Phalan if (strlen (m) == err_reply->text.length-1
370159d09a2SMark Phalan && !strcmp(m, err_reply->text.data))
371159d09a2SMark Phalan break;
372*5e01956fSGlenn Barry /* Solaris Kerberos - added dgettext */
373159d09a2SMark Phalan krb5_set_error_message(context, retval,
374*5e01956fSGlenn Barry dgettext(TEXT_DOMAIN,
375*5e01956fSGlenn Barry "%s (KDC supplied additional data: %s)"),
376159d09a2SMark Phalan m, err_reply->text.data);
377159d09a2SMark Phalan #endif
378159d09a2SMark Phalan break;
379159d09a2SMark Phalan }
380159d09a2SMark Phalan }
3817c478bd9Sstevel@tonic-gate
3827c478bd9Sstevel@tonic-gate krb5_free_error(context, err_reply);
3837c478bd9Sstevel@tonic-gate goto error_4;
3847c478bd9Sstevel@tonic-gate }
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate if ((retval = krb5_decode_kdc_rep(context, &tgsrep.response,
3877c478bd9Sstevel@tonic-gate &tkt->keyblock, &dec_rep)))
3887c478bd9Sstevel@tonic-gate goto error_4;
3897c478bd9Sstevel@tonic-gate
3907c478bd9Sstevel@tonic-gate if (dec_rep->msg_type != KRB5_TGS_REP) {
3917c478bd9Sstevel@tonic-gate retval = KRB5KRB_AP_ERR_MSG_TYPE;
3927c478bd9Sstevel@tonic-gate goto error_3;
3937c478bd9Sstevel@tonic-gate }
3947c478bd9Sstevel@tonic-gate
3957c478bd9Sstevel@tonic-gate /* make sure the response hasn't been tampered with..... */
3967c478bd9Sstevel@tonic-gate retval = 0;
3977c478bd9Sstevel@tonic-gate
3987c478bd9Sstevel@tonic-gate if (!krb5_principal_compare(context, dec_rep->client, tkt->client))
3997c478bd9Sstevel@tonic-gate retval = KRB5_KDCREP_MODIFIED;
4007c478bd9Sstevel@tonic-gate
401fe598cdcSmp153739 if (retval == 0)
402fe598cdcSmp153739 retval = check_reply_server(context, kdcoptions, in_cred, dec_rep);
4037c478bd9Sstevel@tonic-gate
4047c478bd9Sstevel@tonic-gate if (dec_rep->enc_part2->nonce != tgsrep.expected_nonce)
4057c478bd9Sstevel@tonic-gate retval = KRB5_KDCREP_MODIFIED;
4067c478bd9Sstevel@tonic-gate
4077c478bd9Sstevel@tonic-gate if ((kdcoptions & KDC_OPT_POSTDATED) &&
4087c478bd9Sstevel@tonic-gate (in_cred->times.starttime != 0) &&
4097c478bd9Sstevel@tonic-gate (in_cred->times.starttime != dec_rep->enc_part2->times.starttime))
4107c478bd9Sstevel@tonic-gate retval = KRB5_KDCREP_MODIFIED;
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate if ((in_cred->times.endtime != 0) &&
4137c478bd9Sstevel@tonic-gate (dec_rep->enc_part2->times.endtime > in_cred->times.endtime))
4147c478bd9Sstevel@tonic-gate retval = KRB5_KDCREP_MODIFIED;
4157c478bd9Sstevel@tonic-gate
4167c478bd9Sstevel@tonic-gate if ((kdcoptions & KDC_OPT_RENEWABLE) &&
4177c478bd9Sstevel@tonic-gate (in_cred->times.renew_till != 0) &&
4187c478bd9Sstevel@tonic-gate (dec_rep->enc_part2->times.renew_till > in_cred->times.renew_till))
4197c478bd9Sstevel@tonic-gate retval = KRB5_KDCREP_MODIFIED;
4207c478bd9Sstevel@tonic-gate
4217c478bd9Sstevel@tonic-gate if ((kdcoptions & KDC_OPT_RENEWABLE_OK) &&
4227c478bd9Sstevel@tonic-gate (dec_rep->enc_part2->flags & KDC_OPT_RENEWABLE) &&
4237c478bd9Sstevel@tonic-gate (in_cred->times.endtime != 0) &&
4247c478bd9Sstevel@tonic-gate (dec_rep->enc_part2->times.renew_till > in_cred->times.endtime))
4257c478bd9Sstevel@tonic-gate retval = KRB5_KDCREP_MODIFIED;
4267c478bd9Sstevel@tonic-gate
4277c478bd9Sstevel@tonic-gate if (retval != 0)
4287c478bd9Sstevel@tonic-gate goto error_3;
4297c478bd9Sstevel@tonic-gate
4307c478bd9Sstevel@tonic-gate if (!in_cred->times.starttime &&
4317c478bd9Sstevel@tonic-gate !in_clock_skew(dec_rep->enc_part2->times.starttime,
4327c478bd9Sstevel@tonic-gate tgsrep.request_time)) {
4337c478bd9Sstevel@tonic-gate retval = KRB5_KDCREP_SKEW;
4347c478bd9Sstevel@tonic-gate goto error_3;
4357c478bd9Sstevel@tonic-gate }
4367c478bd9Sstevel@tonic-gate
4377c478bd9Sstevel@tonic-gate retval = krb5_kdcrep2creds(context, dec_rep, address,
4387c478bd9Sstevel@tonic-gate &in_cred->second_ticket, out_cred);
4397c478bd9Sstevel@tonic-gate
4407c478bd9Sstevel@tonic-gate error_3:;
4417c478bd9Sstevel@tonic-gate memset(dec_rep->enc_part2->session->contents, 0,
4427c478bd9Sstevel@tonic-gate dec_rep->enc_part2->session->length);
4437c478bd9Sstevel@tonic-gate krb5_free_kdc_rep(context, dec_rep);
4447c478bd9Sstevel@tonic-gate
4457c478bd9Sstevel@tonic-gate error_4:;
446*5e01956fSGlenn Barry if (hostname_used)
447*5e01956fSGlenn Barry free(hostname_used);
4487c478bd9Sstevel@tonic-gate free(tgsrep.response.data);
449fe598cdcSmp153739 #ifdef DEBUG_REFERRALS
450fe598cdcSmp153739 printf("krb5_get_cred_via_tkt ending; %s\n", retval?error_message(retval):"no error");
451fe598cdcSmp153739 #endif
4527c478bd9Sstevel@tonic-gate return retval;
4537c478bd9Sstevel@tonic-gate }
454