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 tgt, and a target cred, get it.
28 #include "int-proto.h"
31 krb5_get_cred_via_tgt (context, tgt, kdcoptions, sumtype, in_cred, out_cred)
34 const krb5_flags kdcoptions;
35 const krb5_cksumtype sumtype;
37 krb5_creds ** out_cred;
39 krb5_error_code retval;
40 krb5_principal tempprinc;
42 krb5_kdc_rep *dec_rep;
43 krb5_error *err_reply;
46 /* tgt->client must be equal to in_cred->client */
47 if (!krb5_principal_compare(context, tgt->client, in_cred->client))
48 return KRB5_PRINC_NOMATCH;
50 if (!tgt->ticket.length)
51 return(KRB5_NO_TKT_SUPPLIED);
53 /* check if we have the right TGT */
54 /* tgt->server must be equal to */
55 /* krbtgt/realmof(cred->server)@realmof(tgt->server) */
57 if (retval = krb5_tgtname(context,
58 krb5_princ_realm(context, in_cred->server),
59 krb5_princ_realm(context, tgt->server), &tempprinc))
62 if (!krb5_principal_compare(context, tempprinc, tgt->server)) {
63 retval = KRB5_PRINC_NOMATCH;
67 if (retval = krb5_send_tgs(context, kdcoptions, &in_cred->times, NULL,
68 sumtype, in_cred->server, tgt->addresses,
71 0, /* no second ticket */
75 switch (tgsrep.message_type) {
80 if (krb5_is_krb_error(&tgsrep.response))
81 retval = decode_krb5_error(&tgsrep.response, &err_reply);
83 retval = KRB5KRB_AP_ERR_MSG_TYPE;
85 if (retval) /* neither proper reply nor error! */
89 /* XXX need access to the actual assembled request...
90 need a change to send_tgs */
91 if ((err_reply->ctime != request.ctime) ||
92 !krb5_principal_compare(context, err_reply->server, request.server) ||
93 !krb5_principal_compare(context, err_reply->client, request.client))
94 retval = KRB5_KDCREP_MODIFIED;
97 retval = err_reply->error + ERROR_TABLE_BASE_krb5;
99 krb5_free_error(context, err_reply);
103 if (retval = krb5_decode_kdc_rep(context, &tgsrep.response, &tgt->keyblock,
104 tgt->keyblock.etype, &dec_rep))
107 if (dec_rep->msg_type != KRB5_TGS_REP) {
108 retval = KRB5KRB_AP_ERR_MSG_TYPE;
112 /* now it's decrypted and ready for prime time */
113 if (!krb5_principal_compare(context, dec_rep->client, tgt->client)) {
114 retval = KRB5_KDCREP_MODIFIED;
118 /* get a cred structure */
119 /* The caller is responsible for cleaning up */
120 if (((*out_cred) = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL) {
124 memset((*out_cred), 0, sizeof(krb5_creds));
126 /* Copy the client straigt from in_cred */
127 if (retval = krb5_copy_principal(context, in_cred->client,
128 &(*out_cred)->client)) {
132 /* put pieces into out_cred-> */
133 if (retval = krb5_copy_keyblock_contents(context,
134 dec_rep->enc_part2->session,
135 &(*out_cred)->keyblock)) {
139 (*out_cred)->keyblock.etype = dec_rep->ticket->enc_part.etype;
140 (*out_cred)->times = dec_rep->enc_part2->times;
143 /* XXX probably need access to the request */
144 /* check the contents for sanity: */
145 if (!krb5_principal_compare(context, dec_rep->client, request.client)
146 || !krb5_principal_compare(context, dec_rep->enc_part2->server, request.server)
147 || !krb5_principal_compare(context, dec_rep->ticket->server, request.server)
148 || (request.nonce != dec_rep->enc_part2->nonce)
149 /* XXX check for extraneous flags */
150 /* XXX || (!krb5_addresses_compare(context, addrs, dec_rep->enc_part2->caddrs)) */
151 || ((request.from != 0) &&
152 (request.from != dec_rep->enc_part2->times.starttime))
153 || ((request.till != 0) &&
154 (dec_rep->enc_part2->times.endtime > request.till))
155 || ((request.kdc_options & KDC_OPT_RENEWABLE) &&
156 (request.rtime != 0) &&
157 (dec_rep->enc_part2->times.renew_till > request.rtime))
158 || ((request.kdc_options & KDC_OPT_RENEWABLE_OK) &&
159 (dec_rep->enc_part2->flags & KDC_OPT_RENEWABLE) &&
160 (request.till != 0) &&
161 (dec_rep->enc_part2->times.renew_till > request.till))
163 retval = KRB5_KDCREP_MODIFIED;
165 if (!request.from && !in_clock_skew(dec_rep->enc_part2->times.starttime)) {
166 retval = KRB5_KDCREP_SKEW;
172 (*out_cred)->ticket_flags = dec_rep->enc_part2->flags;
173 (*out_cred)->is_skey = FALSE;
174 if (dec_rep->enc_part2->caddrs) {
175 if (retval = krb5_copy_addresses(context, dec_rep->enc_part2->caddrs,
176 &(*out_cred)->addresses)) {
180 /* no addresses in the list means we got what we had */
181 if (retval = krb5_copy_addresses(context, tgt->addresses,
182 &(*out_cred)->addresses)) {
186 if (retval = krb5_copy_principal(context, dec_rep->enc_part2->server,
187 &(*out_cred)->server)) {
191 if (retval = encode_krb5_ticket(dec_rep->ticket, &scratch)) {
192 krb5_free_addresses(context, (*out_cred)->addresses);
196 (*out_cred)->ticket = *scratch;
201 memset((*out_cred)->keyblock.contents, 0, (*out_cred)->keyblock.length);
205 krb5_free_creds(context, *out_cred);
208 memset(dec_rep->enc_part2->session->contents, 0,
209 dec_rep->enc_part2->session->length);
210 krb5_free_kdc_rep(context, dec_rep);
213 free(tgsrep.response.data);
216 krb5_free_principal(context, tempprinc);