xref: /illumos-gate/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gc_via_tkt.c (revision 55fea89dcaa64928bed4327112404dcb3e07b79f)
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