5689f1eaf2e1c7b4efb3255cd7b3209037a8334a
[krb5.git] / src / lib / krb5 / krb / gc_2tgt.c
1 /*
2  * lib/krb5/krb/gc_2tgt.c
3  *
4  * Copyright 1991 by the Massachusetts Institute of Technology.
5  * All Rights Reserved.
6  *
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.
11  * 
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.
22  * 
23  *
24  * Given two tgts, get a ticket.
25  */
26
27 #include "k5-int.h"
28 #include "int-proto.h"
29
30 krb5_error_code INTERFACE
31 krb5_get_cred_via_2tgt (context, tgt, kdcoptions, sumtype, in_cred, out_cred)
32     krb5_context context;
33     krb5_creds *tgt;
34     const krb5_flags kdcoptions;
35     const krb5_cksumtype sumtype;
36     krb5_creds * in_cred;
37     krb5_creds ** out_cred;
38 {
39     krb5_error_code retval;
40 #if 0
41     krb5_principal tempprinc;
42 #endif
43     krb5_data *scratch;
44     krb5_kdc_rep *dec_rep;
45     krb5_error *err_reply;
46     krb5_response tgsrep;
47     krb5_enctype etype;
48
49     /* tgt->client must be equal to in_cred->client */
50     /* tgt->server must be equal to krbtgt/realmof(cred->client) */
51     if (!krb5_principal_compare(context, tgt->client, in_cred->client))
52         return KRB5_PRINC_NOMATCH;
53
54     if (!tgt->ticket.length)
55         return(KRB5_NO_TKT_SUPPLIED);
56
57     if (!in_cred->second_ticket.length)
58         return(KRB5_NO_2ND_TKT);
59
60 #if 0   /* What does this do? */
61     if (retval = krb5_tgtname(context, krb5_princ_realm(in_cred->server),
62                               krb5_princ_realm(context, in_cred->client), &tempprinc))
63         return(retval);
64
65     if (!krb5_principal_compare(context, tempprinc, tgt->server)) {
66         krb5_free_principal(context, tempprinc);
67         return KRB5_PRINC_NOMATCH;
68     }
69     krb5_free_principal(context, tempprinc);
70 #endif
71
72     if (!(kdcoptions & KDC_OPT_ENC_TKT_IN_SKEY))
73         return KRB5_INVALID_FLAGS;
74
75     if (retval = krb5_send_tgs(context, kdcoptions, &in_cred->times, NULL, 
76                                sumtype, in_cred->server, tgt->addresses,
77                                in_cred->authdata,
78                                0,               /* no padata */
79                                &in_cred->second_ticket, tgt, &tgsrep))
80         return retval;
81
82     if (tgsrep.message_type != KRB5_TGS_REP)
83       {
84         if (!krb5_is_krb_error(&tgsrep.response)) {
85             free(tgsrep.response.data);
86             return KRB5KRB_AP_ERR_MSG_TYPE;
87         }
88         retval = decode_krb5_error(&tgsrep.response, &err_reply);
89         if (retval) {
90             free(tgsrep.response.data);
91             return retval;
92         }
93         retval = err_reply->error + ERROR_TABLE_BASE_krb5;
94
95         krb5_free_error(context, err_reply);
96         free(tgsrep.response.data);
97         return retval;
98       }
99     etype = tgt->keyblock.etype;
100     retval = krb5_decode_kdc_rep(context, &tgsrep.response, &tgt->keyblock,
101                                  etype, &dec_rep);
102     free(tgsrep.response.data);
103     if (retval)
104         return retval;
105
106     if (dec_rep->msg_type != KRB5_TGS_REP) {
107         retval = KRB5KRB_AP_ERR_MSG_TYPE;
108         goto errout;
109     }
110     
111     /* now it's decrypted and ready for prime time */
112
113     if (!krb5_principal_compare(context, dec_rep->client, tgt->client)) {
114         retval = KRB5_KDCREP_MODIFIED;
115         goto errout;
116     }
117
118     /*
119      * get a cred structure 
120      * The caller is responsible for cleaning up 
121      */
122     if (((*out_cred) = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL) {
123         retval = ENOMEM;
124         goto errout;
125     }
126
127     /* Copy the client straig from in_cred */
128     if (retval = krb5_copy_principal(context, in_cred->client, 
129                                      &(*out_cred)->client)) {
130         goto errout;
131     }
132
133     /* put pieces into out_cred-> */
134     (*out_cred)->keyblock.magic = KV5M_KEYBLOCK;
135     (*out_cred)->keyblock.etype = dec_rep->ticket->enc_part.etype;
136     if (retval = krb5_copy_keyblock_contents(context, 
137                                              dec_rep->enc_part2->session,
138                                              &(*out_cred)->keyblock))
139         goto errout;
140
141     /* Should verify that the ticket is what we asked for. */
142     (*out_cred)->times = dec_rep->enc_part2->times;
143     (*out_cred)->ticket_flags = dec_rep->enc_part2->flags;
144     (*out_cred)->is_skey = TRUE;
145     if (dec_rep->enc_part2->caddrs)
146         retval = krb5_copy_addresses(context, dec_rep->enc_part2->caddrs,
147                                      &(*out_cred)->addresses);
148     else
149         /* no addresses in the list means we got what we had */
150         retval = krb5_copy_addresses(context, tgt->addresses, &(*out_cred)->addresses);
151     if (retval)
152             goto errout;
153     
154     if (retval = krb5_copy_principal(context, dec_rep->enc_part2->server,
155                                      &(*out_cred)->server))
156         goto errout;
157
158     if (retval = encode_krb5_ticket(dec_rep->ticket, &scratch))
159         goto errout;
160
161     (*out_cred)->ticket = *scratch;
162     krb5_xfree(scratch);
163
164 errout:
165     if (retval) {
166         if (*out_cred) {
167             if ((*out_cred)->keyblock.contents) {
168                 memset((*out_cred)->keyblock.contents, 0, 
169                    (*out_cred)->keyblock.length);
170                 krb5_xfree((*out_cred)->keyblock.contents);
171                 (*out_cred)->keyblock.contents = 0;
172             }
173             if ((*out_cred)->addresses) {
174                 krb5_free_addresses(context, (*out_cred)->addresses);
175                 (*out_cred)->addresses = 0;
176             }
177             if ((*out_cred)->server) {
178                 krb5_free_principal(context, (*out_cred)->server);
179                 (*out_cred)->server = 0;
180             }
181             krb5_free_creds(context, *out_cred);
182         }
183     }
184     memset((char *)dec_rep->enc_part2->session->contents, 0,
185            dec_rep->enc_part2->session->length);
186     krb5_free_kdc_rep(context, dec_rep);
187     return retval;
188 }
189
190 /*
191  * Local variables:
192  * mode:c
193  * eval: (make-local-variable (quote c-indent-level))
194  * eval: (make-local-variable (quote c-continued-statement-offset))
195  * eval: (setq c-indent-level 4 c-continued-statement-offset 4)
196  * End:
197  */
198