2 * lib/krb5/krb/gc_via_tgt.c
4 * Copyright 1990,1991 by the Massachusetts Institute of Technology.
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. M.I.T. makes no representations about the suitability of
20 * this software for any purpose. It is provided "as is" without express
21 * or implied warranty.
24 * Given a tkt, and a target cred, get it.
25 * Assumes that the kdc_rep has been decrypted.
29 #include "int-proto.h"
31 extern krb5_deltat krb5_clockskew;
32 #define in_clock_skew(date, now) (labs((date)-(now)) < krb5_clockskew)
34 static krb5_error_code
35 krb5_kdcrep2creds(context, pkdcrep, address, psectkt, ppcreds)
37 krb5_kdc_rep * pkdcrep;
38 krb5_address *const * address;
40 krb5_creds ** ppcreds;
42 krb5_error_code retval;
45 if ((*ppcreds = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL) {
49 memset(*ppcreds, 0, sizeof(krb5_creds));
51 if ((retval = krb5_copy_principal(context, pkdcrep->client,
52 &(*ppcreds)->client)))
55 if ((retval = krb5_copy_principal(context, pkdcrep->enc_part2->server,
56 &(*ppcreds)->server)))
59 if ((retval = krb5_copy_keyblock_contents(context,
60 pkdcrep->enc_part2->session,
61 &(*ppcreds)->keyblock)))
64 if ((retval = krb5_copy_data(context, psectkt, &pdata)))
66 (*ppcreds)->second_ticket = *pdata;
69 (*ppcreds)->keyblock.etype = pkdcrep->ticket->enc_part.etype;
70 (*ppcreds)->ticket_flags = pkdcrep->enc_part2->flags;
71 (*ppcreds)->times = pkdcrep->enc_part2->times;
72 (*ppcreds)->magic = KV5M_CREDS;
74 (*ppcreds)->authdata = NULL; /* not used */
75 (*ppcreds)->is_skey = 0; /* not used */
77 if (pkdcrep->enc_part2->caddrs) {
78 if ((retval = krb5_copy_addresses(context, pkdcrep->enc_part2->caddrs,
79 &(*ppcreds)->addresses)))
80 goto cleanup_keyblock;
82 /* no addresses in the list means we got what we had */
83 if ((retval = krb5_copy_addresses(context, address,
84 &(*ppcreds)->addresses)))
85 goto cleanup_keyblock;
88 if ((retval = encode_krb5_ticket(pkdcrep->ticket, &pdata)))
89 goto cleanup_keyblock;
91 (*ppcreds)->ticket = *pdata;
95 krb5_free_keyblock(context, &(*ppcreds)->keyblock);
102 krb5_error_code INTERFACE
103 krb5_get_cred_via_tkt (context, tkt, kdcoptions, address, in_cred, out_cred)
104 krb5_context context;
106 const krb5_flags kdcoptions;
107 krb5_address *const * address;
108 krb5_creds * in_cred;
109 krb5_creds ** out_cred;
111 krb5_error_code retval;
112 krb5_kdc_rep *dec_rep;
113 krb5_error *err_reply;
114 krb5_response tgsrep;
116 /* tkt->client must be equal to in_cred->client */
117 if (!krb5_principal_compare(context, tkt->client, in_cred->client))
118 return KRB5_PRINC_NOMATCH;
120 if (!tkt->ticket.length)
121 return KRB5_NO_TKT_SUPPLIED;
123 if ((kdcoptions & KDC_OPT_ENC_TKT_IN_SKEY) &&
124 (!in_cred->second_ticket.length))
125 return(KRB5_NO_2ND_TKT);
128 /* check if we have the right TGT */
129 /* tkt->server must be equal to */
130 /* krbtgt/realmof(cred->server)@realmof(tgt->server) */
133 krb5_principal tempprinc;
134 if (retval = krb5_tgtname(context,
135 krb5_princ_realm(context, in_cred->server),
136 krb5_princ_realm(context, tkt->server), &tempprinc))
139 if (!krb5_principal_compare(context, tempprinc, tkt->server)) {
140 krb5_free_principal(context, tempprinc);
141 return (KRB5_PRINC_NOMATCH);
143 krb5_free_principal(context, tempprinc);
147 if ((retval = krb5_send_tgs(context, kdcoptions, &in_cred->times, NULL,
148 in_cred->server, address, in_cred->authdata,
150 (kdcoptions & KDC_OPT_ENC_TKT_IN_SKEY) ?
151 &in_cred->second_ticket : NULL,
155 switch (tgsrep.message_type) {
160 if (krb5_is_krb_error(&tgsrep.response))
161 retval = decode_krb5_error(&tgsrep.response, &err_reply);
163 retval = KRB5KRB_AP_ERR_MSG_TYPE;
165 if (retval) /* neither proper reply nor error! */
168 retval = err_reply->error + ERROR_TABLE_BASE_krb5;
170 krb5_free_error(context, err_reply);
174 if ((retval = krb5_decode_kdc_rep(context, &tgsrep.response,
176 tkt->keyblock.etype, &dec_rep)))
179 if (dec_rep->msg_type != KRB5_TGS_REP) {
180 retval = KRB5KRB_AP_ERR_MSG_TYPE;
184 /* make sure the response hasn't been tampered with..... */
185 if (!krb5_principal_compare(context, dec_rep->client, tkt->client) ||
186 !krb5_principal_compare(context, dec_rep->enc_part2->server,
188 !krb5_principal_compare(context, dec_rep->ticket->server,
190 (dec_rep->enc_part2->nonce != tgsrep.expected_nonce) ||
191 ((in_cred->times.starttime != 0) &&
192 (in_cred->times.starttime != dec_rep->enc_part2->times.starttime)) ||
193 ((in_cred->times.endtime != 0) &&
194 (dec_rep->enc_part2->times.endtime > in_cred->times.endtime)) ||
195 ((kdcoptions & KDC_OPT_RENEWABLE) &&
196 (in_cred->times.renew_till != 0) &&
197 (dec_rep->enc_part2->times.renew_till > in_cred->times.renew_till)) ||
198 ((kdcoptions & KDC_OPT_RENEWABLE_OK) &&
199 (dec_rep->enc_part2->flags & KDC_OPT_RENEWABLE) &&
200 (in_cred->times.endtime != 0) &&
201 (dec_rep->enc_part2->times.renew_till > in_cred->times.endtime))
203 retval = KRB5_KDCREP_MODIFIED;
207 if (!in_cred->times.starttime &&
208 !in_clock_skew(dec_rep->enc_part2->times.starttime,
209 tgsrep.request_time)) {
210 retval = KRB5_KDCREP_SKEW;
214 retval = krb5_kdcrep2creds(context, dec_rep, address,
215 &in_cred->second_ticket, out_cred);
218 memset(dec_rep->enc_part2->session->contents, 0,
219 dec_rep->enc_part2->session->length);
220 krb5_free_kdc_rep(context, dec_rep);
223 free(tgsrep.response.data);