xref: /illumos-gate/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gc_via_tkt.c (revision 505d05c73a6e56769f263d4803b22eddd168ee24)
17c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
27c478bd9Sstevel@tonic-gate /*
37c478bd9Sstevel@tonic-gate  * lib/krb5/krb/gc_via_tgt.c
47c478bd9Sstevel@tonic-gate  *
57c478bd9Sstevel@tonic-gate  * Copyright 1990,1991 by the Massachusetts Institute of Technology.
67c478bd9Sstevel@tonic-gate  * All Rights Reserved.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
97c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
107c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
117c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
147c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
157c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
167c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
177c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
187c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
197c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
207c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
217c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
227c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
237c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
247c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
257c478bd9Sstevel@tonic-gate  * or implied warranty.
267c478bd9Sstevel@tonic-gate  *
277c478bd9Sstevel@tonic-gate  *
287c478bd9Sstevel@tonic-gate  * Given a tkt, and a target cred, get it.
297c478bd9Sstevel@tonic-gate  * Assumes that the kdc_rep has been decrypted.
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include "k5-int.h"
337c478bd9Sstevel@tonic-gate #include "int-proto.h"
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #define in_clock_skew(date, now) (labs((date)-(now)) < context->clockskew)
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate static krb5_error_code
38*505d05c7Sgtb krb5_kdcrep2creds(krb5_context context, krb5_kdc_rep *pkdcrep, krb5_address *const *address, krb5_data *psectkt, krb5_creds **ppcreds)
397c478bd9Sstevel@tonic-gate {
407c478bd9Sstevel@tonic-gate     krb5_error_code retval;
417c478bd9Sstevel@tonic-gate     krb5_data *pdata;
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate     if ((*ppcreds = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL) {
447c478bd9Sstevel@tonic-gate         return ENOMEM;
457c478bd9Sstevel@tonic-gate     }
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate     memset(*ppcreds, 0, sizeof(krb5_creds));
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate     if ((retval = krb5_copy_principal(context, pkdcrep->client,
507c478bd9Sstevel@tonic-gate                                      &(*ppcreds)->client)))
517c478bd9Sstevel@tonic-gate         goto cleanup;
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate     if ((retval = krb5_copy_principal(context, pkdcrep->enc_part2->server,
547c478bd9Sstevel@tonic-gate                                      &(*ppcreds)->server)))
557c478bd9Sstevel@tonic-gate         goto cleanup;
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate     if ((retval = krb5_copy_keyblock_contents(context,
587c478bd9Sstevel@tonic-gate 					      pkdcrep->enc_part2->session,
597c478bd9Sstevel@tonic-gate 					      &(*ppcreds)->keyblock)))
607c478bd9Sstevel@tonic-gate         goto cleanup;
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate     if ((retval = krb5_copy_data(context, psectkt, &pdata)))
637c478bd9Sstevel@tonic-gate 	goto cleanup;
647c478bd9Sstevel@tonic-gate     (*ppcreds)->second_ticket = *pdata;
657c478bd9Sstevel@tonic-gate     krb5_xfree(pdata);
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate     (*ppcreds)->ticket_flags = pkdcrep->enc_part2->flags;
687c478bd9Sstevel@tonic-gate     (*ppcreds)->times = pkdcrep->enc_part2->times;
697c478bd9Sstevel@tonic-gate     (*ppcreds)->magic = KV5M_CREDS;
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate     (*ppcreds)->authdata = NULL;   			/* not used */
727c478bd9Sstevel@tonic-gate     (*ppcreds)->is_skey = psectkt->length != 0;
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate     if (pkdcrep->enc_part2->caddrs) {
757c478bd9Sstevel@tonic-gate 	if ((retval = krb5_copy_addresses(context, pkdcrep->enc_part2->caddrs,
767c478bd9Sstevel@tonic-gate 					  &(*ppcreds)->addresses)))
777c478bd9Sstevel@tonic-gate 	    goto cleanup_keyblock;
787c478bd9Sstevel@tonic-gate     } else {
797c478bd9Sstevel@tonic-gate 	/* no addresses in the list means we got what we had */
807c478bd9Sstevel@tonic-gate 	if ((retval = krb5_copy_addresses(context, address,
817c478bd9Sstevel@tonic-gate 					  &(*ppcreds)->addresses)))
827c478bd9Sstevel@tonic-gate 	    goto cleanup_keyblock;
837c478bd9Sstevel@tonic-gate     }
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate     if ((retval = encode_krb5_ticket(pkdcrep->ticket, &pdata)))
867c478bd9Sstevel@tonic-gate 	goto cleanup_keyblock;
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate     (*ppcreds)->ticket = *pdata;
897c478bd9Sstevel@tonic-gate     free(pdata);
907c478bd9Sstevel@tonic-gate     return 0;
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate cleanup_keyblock:
937c478bd9Sstevel@tonic-gate     krb5_free_keyblock(context, &(*ppcreds)->keyblock);
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate cleanup:
967c478bd9Sstevel@tonic-gate     free (*ppcreds);
977c478bd9Sstevel@tonic-gate     return retval;
987c478bd9Sstevel@tonic-gate }
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate krb5_error_code
101*505d05c7Sgtb krb5_get_cred_via_tkt (krb5_context context, krb5_creds *tkt,
102*505d05c7Sgtb 		       krb5_flags kdcoptions, krb5_address *const *address,
103*505d05c7Sgtb 		       krb5_creds *in_cred, krb5_creds **out_cred)
1047c478bd9Sstevel@tonic-gate {
1057c478bd9Sstevel@tonic-gate     krb5_error_code retval;
1067c478bd9Sstevel@tonic-gate     krb5_kdc_rep *dec_rep;
1077c478bd9Sstevel@tonic-gate     krb5_error *err_reply;
1087c478bd9Sstevel@tonic-gate     krb5_response tgsrep;
1097c478bd9Sstevel@tonic-gate     krb5_enctype *enctypes = 0;
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate     /* tkt->client must be equal to in_cred->client */
1127c478bd9Sstevel@tonic-gate     if (!krb5_principal_compare(context, tkt->client, in_cred->client))
1137c478bd9Sstevel@tonic-gate 	return KRB5_PRINC_NOMATCH;
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate     if (!tkt->ticket.length)
1167c478bd9Sstevel@tonic-gate 	return KRB5_NO_TKT_SUPPLIED;
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate     if ((kdcoptions & KDC_OPT_ENC_TKT_IN_SKEY) &&
1197c478bd9Sstevel@tonic-gate 	(!in_cred->second_ticket.length))
1207c478bd9Sstevel@tonic-gate         return(KRB5_NO_2ND_TKT);
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate     /* check if we have the right TGT                    */
1247c478bd9Sstevel@tonic-gate     /* tkt->server must be equal to                      */
1257c478bd9Sstevel@tonic-gate     /* krbtgt/realmof(cred->server)@realmof(tgt->server) */
1267c478bd9Sstevel@tonic-gate /*
1277c478bd9Sstevel@tonic-gate     {
1287c478bd9Sstevel@tonic-gate     krb5_principal tempprinc;
1297c478bd9Sstevel@tonic-gate         if (retval = krb5_tgtname(context,
1307c478bd9Sstevel@tonic-gate 		     krb5_princ_realm(context, in_cred->server),
1317c478bd9Sstevel@tonic-gate 		     krb5_princ_realm(context, tkt->server), &tempprinc))
1327c478bd9Sstevel@tonic-gate     	    return(retval);
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate         if (!krb5_principal_compare(context, tempprinc, tkt->server)) {
1357c478bd9Sstevel@tonic-gate             krb5_free_principal(context, tempprinc);
1367c478bd9Sstevel@tonic-gate 	    return (KRB5_PRINC_NOMATCH);
1377c478bd9Sstevel@tonic-gate         }
1387c478bd9Sstevel@tonic-gate     krb5_free_principal(context, tempprinc);
1397c478bd9Sstevel@tonic-gate     }
1407c478bd9Sstevel@tonic-gate */
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate     if (in_cred->keyblock.enctype) {
1437c478bd9Sstevel@tonic-gate 	enctypes = (krb5_enctype *) malloc(sizeof(krb5_enctype)*2);
1447c478bd9Sstevel@tonic-gate 	if (!enctypes)
1457c478bd9Sstevel@tonic-gate 	    return ENOMEM;
1467c478bd9Sstevel@tonic-gate 	enctypes[0] = in_cred->keyblock.enctype;
1477c478bd9Sstevel@tonic-gate 	enctypes[1] = 0;
1487c478bd9Sstevel@tonic-gate     }
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate     retval = krb5_send_tgs(context, kdcoptions, &in_cred->times, enctypes,
1517c478bd9Sstevel@tonic-gate 			   in_cred->server, address, in_cred->authdata,
1527c478bd9Sstevel@tonic-gate 			   0,		/* no padata */
1537c478bd9Sstevel@tonic-gate 			   (kdcoptions & KDC_OPT_ENC_TKT_IN_SKEY) ?
1547c478bd9Sstevel@tonic-gate 			   &in_cred->second_ticket : NULL,
1557c478bd9Sstevel@tonic-gate 			   tkt, &tgsrep);
1567c478bd9Sstevel@tonic-gate     if (enctypes)
1577c478bd9Sstevel@tonic-gate 	free(enctypes);
1587c478bd9Sstevel@tonic-gate     if (retval)
1597c478bd9Sstevel@tonic-gate 	return retval;
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate     switch (tgsrep.message_type) {
1627c478bd9Sstevel@tonic-gate     case KRB5_TGS_REP:
1637c478bd9Sstevel@tonic-gate 	break;
1647c478bd9Sstevel@tonic-gate     case KRB5_ERROR:
1657c478bd9Sstevel@tonic-gate     default:
1667c478bd9Sstevel@tonic-gate 	if (krb5_is_krb_error(&tgsrep.response))
1677c478bd9Sstevel@tonic-gate 	    retval = decode_krb5_error(&tgsrep.response, &err_reply);
1687c478bd9Sstevel@tonic-gate 	else
1697c478bd9Sstevel@tonic-gate 	    retval = KRB5KRB_AP_ERR_MSG_TYPE;
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate 	if (retval) 			/* neither proper reply nor error! */
1727c478bd9Sstevel@tonic-gate 	    goto error_4;
1737c478bd9Sstevel@tonic-gate 
174*505d05c7Sgtb 	retval = (krb5_error_code) err_reply->error + ERROR_TABLE_BASE_krb5;
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	krb5_free_error(context, err_reply);
1777c478bd9Sstevel@tonic-gate 	goto error_4;
1787c478bd9Sstevel@tonic-gate     }
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate     if ((retval = krb5_decode_kdc_rep(context, &tgsrep.response,
1817c478bd9Sstevel@tonic-gate 				      &tkt->keyblock, &dec_rep)))
1827c478bd9Sstevel@tonic-gate 	goto error_4;
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate     if (dec_rep->msg_type != KRB5_TGS_REP) {
1857c478bd9Sstevel@tonic-gate 	retval = KRB5KRB_AP_ERR_MSG_TYPE;
1867c478bd9Sstevel@tonic-gate 	goto error_3;
1877c478bd9Sstevel@tonic-gate     }
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate     /* make sure the response hasn't been tampered with..... */
1907c478bd9Sstevel@tonic-gate     retval = 0;
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate     if (!krb5_principal_compare(context, dec_rep->client, tkt->client))
1937c478bd9Sstevel@tonic-gate 	retval = KRB5_KDCREP_MODIFIED;
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate     if (!krb5_principal_compare(context, dec_rep->enc_part2->server, in_cred->server))
1967c478bd9Sstevel@tonic-gate 	retval = KRB5_KDCREP_MODIFIED;
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate     if (!krb5_principal_compare(context, dec_rep->ticket->server, in_cred->server))
1997c478bd9Sstevel@tonic-gate 	retval = KRB5_KDCREP_MODIFIED;
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate     if (dec_rep->enc_part2->nonce != tgsrep.expected_nonce)
2027c478bd9Sstevel@tonic-gate 	retval = KRB5_KDCREP_MODIFIED;
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate     if ((kdcoptions & KDC_OPT_POSTDATED) &&
2057c478bd9Sstevel@tonic-gate 	(in_cred->times.starttime != 0) &&
2067c478bd9Sstevel@tonic-gate     	(in_cred->times.starttime != dec_rep->enc_part2->times.starttime))
2077c478bd9Sstevel@tonic-gate 	retval = KRB5_KDCREP_MODIFIED;
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate     if ((in_cred->times.endtime != 0) &&
2107c478bd9Sstevel@tonic-gate 	(dec_rep->enc_part2->times.endtime > in_cred->times.endtime))
2117c478bd9Sstevel@tonic-gate 	retval = KRB5_KDCREP_MODIFIED;
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate     if ((kdcoptions & KDC_OPT_RENEWABLE) &&
2147c478bd9Sstevel@tonic-gate 	(in_cred->times.renew_till != 0) &&
2157c478bd9Sstevel@tonic-gate 	(dec_rep->enc_part2->times.renew_till > in_cred->times.renew_till))
2167c478bd9Sstevel@tonic-gate 	retval = KRB5_KDCREP_MODIFIED;
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate     if ((kdcoptions & KDC_OPT_RENEWABLE_OK) &&
2197c478bd9Sstevel@tonic-gate 	(dec_rep->enc_part2->flags & KDC_OPT_RENEWABLE) &&
2207c478bd9Sstevel@tonic-gate 	(in_cred->times.endtime != 0) &&
2217c478bd9Sstevel@tonic-gate 	(dec_rep->enc_part2->times.renew_till > in_cred->times.endtime))
2227c478bd9Sstevel@tonic-gate  	retval = KRB5_KDCREP_MODIFIED;
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate     if (retval != 0)
2257c478bd9Sstevel@tonic-gate     	goto error_3;
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate     if (!in_cred->times.starttime &&
2287c478bd9Sstevel@tonic-gate 	!in_clock_skew(dec_rep->enc_part2->times.starttime,
2297c478bd9Sstevel@tonic-gate 		       tgsrep.request_time)) {
2307c478bd9Sstevel@tonic-gate 	retval = KRB5_KDCREP_SKEW;
2317c478bd9Sstevel@tonic-gate 	goto error_3;
2327c478bd9Sstevel@tonic-gate     }
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate     retval = krb5_kdcrep2creds(context, dec_rep, address,
2357c478bd9Sstevel@tonic-gate 			       &in_cred->second_ticket,  out_cred);
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate error_3:;
2387c478bd9Sstevel@tonic-gate     memset(dec_rep->enc_part2->session->contents, 0,
2397c478bd9Sstevel@tonic-gate 	   dec_rep->enc_part2->session->length);
2407c478bd9Sstevel@tonic-gate     krb5_free_kdc_rep(context, dec_rep);
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate error_4:;
2437c478bd9Sstevel@tonic-gate     free(tgsrep.response.data);
2447c478bd9Sstevel@tonic-gate     return retval;
2457c478bd9Sstevel@tonic-gate }
246