03398acd587147404f8a91f1043220364e34fed7
[krb5.git] / src / lib / krb4 / decomp_tkt.c
1 /*
2  * decomp_tkt.c
3  * 
4  * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
5  * of Technology.
6  *
7  * For copying and distribution information, please see the file
8  * <mit-copyright.h>.
9  */
10
11 #include "mit-copyright.h"
12 #include "des.h"
13 #include "krb.h"
14 #include "prot.h"
15 #include <string.h>
16 #include <krb5.h>
17
18 #ifdef KRB_CRYPT_DEBUG
19 extern int krb_debug;
20 #endif
21
22 /*
23  * This routine takes a ticket and pointers to the variables that
24  * should be filled in based on the information in the ticket.  It
25 #ifndef NOENCRYPTION
26  * decrypts the ticket using the given key, and 
27 #endif
28  * fills in values for its arguments.
29  *
30  * Note: if the client realm field in the ticket is the null string,
31  * then the "prealm" variable is filled in with the local realm (as
32  * defined by KRB_REALM).
33  *
34  * If the ticket byte order is different than the host's byte order
35  * (as indicated by the byte order bit of the "flags" field), then
36  * the KDC timestamp "time_sec" is byte-swapped.  The other fields
37  * potentially affected by byte order, "paddress" and "session" are
38  * not byte-swapped.
39  *
40  * The routine returns KFAILURE if any of the "pname", "pinstance",
41  * or "prealm" fields is too big, otherwise it returns KSUCCESS.
42  *
43  * The corresponding routine to generate tickets is create_ticket.
44  * When changes are made to this routine, the corresponding changes
45  * should also be made to that file.
46  *
47  * See create_ticket.c for the format of the ticket packet.
48  */
49
50 int
51 decomp_ticket(tkt, flags, pname, pinstance, prealm, paddress, session,
52               life, time_sec, sname, sinstance, key, key_s)
53     KTEXT tkt;                  /* The ticket to be decoded */
54     unsigned char *flags;       /* Kerberos ticket flags */
55     char *pname;                /* Authentication name */
56     char *pinstance;            /* Principal's instance */
57     char *prealm;               /* Principal's authentication domain */
58     unsigned KRB4_32 *paddress; /* Net address of entity
59                                  * requesting ticket */
60     C_Block session;            /* Session key inserted in ticket */
61     int *life;                  /* Lifetime of the ticket */
62     unsigned KRB4_32 *time_sec; /* Issue time and date */
63     char *sname;                /* Service name */
64     char *sinstance;            /* Service instance */
65     C_Block key;                /* Service's secret key
66                                  * (to decrypt the ticket) */
67     Key_schedule key_s;         /* The precomputed key schedule */
68 {
69     return
70         dcmp_tkt_int(tkt, flags, pname, pinstance, prealm,
71                      paddress, session, life, time_sec, sname, sinstance,
72                      key, key_s, NULL);
73 }
74
75 int
76 decomp_tkt_krb5(tkt, flags, pname, pinstance, prealm, paddress, session,
77               life, time_sec, sname, sinstance, k5key)
78     KTEXT tkt;                  /* The ticket to be decoded */
79     unsigned char *flags;       /* Kerberos ticket flags */
80     char *pname;                /* Authentication name */
81     char *pinstance;            /* Principal's instance */
82     char *prealm;               /* Principal's authentication domain */
83     unsigned KRB4_32 *paddress; /* Net address of entity
84                                  * requesting ticket */
85     C_Block session;            /* Session key inserted in ticket */
86     int *life;                  /* Lifetime of the ticket */
87     unsigned KRB4_32 *time_sec; /* Issue time and date */
88     char *sname;                /* Service name */
89     char *sinstance;            /* Service instance */
90     krb5_keyblock *k5key;       /* krb5 keyblock of service */
91 {
92     C_Block key;                /* placeholder; doesn't get used */
93     Key_schedule key_s;         /* placeholder; doesn't get used */
94
95     return
96         dcmp_tkt_int(tkt, flags, pname, pinstance, prealm, paddress, session,
97                      life, time_sec, sname, sinstance, key, key_s, k5key);
98 }
99
100 static int
101 dcmp_tkt_int(tkt, flags, pname, pinstance, prealm, paddress, session,
102               life, time_sec, sname, sinstance, key, key_s, k5key)
103     KTEXT tkt;                  /* The ticket to be decoded */
104     unsigned char *flags;       /* Kerberos ticket flags */
105     char *pname;                /* Authentication name */
106     char *pinstance;            /* Principal's instance */
107     char *prealm;               /* Principal's authentication domain */
108     unsigned KRB4_32 *paddress; /* Net address of entity
109                                  * requesting ticket */
110     C_Block session;            /* Session key inserted in ticket */
111     int *life;                  /* Lifetime of the ticket */
112     unsigned KRB4_32 *time_sec; /* Issue time and date */
113     char *sname;                /* Service name */
114     char *sinstance;            /* Service instance */
115     C_Block key;                /* Service's secret key
116                                  * (to decrypt the ticket) */
117     Key_schedule key_s;         /* The precomputed key schedule */
118     krb5_keyblock *k5key;       /* krb5 keyblock of service */
119 {
120     static int tkt_swap_bytes;
121     unsigned char *uptr;
122     char *ptr = (char *)tkt->dat;
123
124 #ifndef NOENCRYPTION
125     /* Do the decryption */
126 #ifdef KRB_CRYPT_DEBUG
127     if (krb_debug) {
128         FILE *fp;
129         char *keybuf[BUFSIZ];   /* Avoid secret stuff in stdio buffers */
130
131         fp = fopen("/kerberos/tkt.des", "wb");
132         setbuf(fp, keybuf);
133         fwrite(tkt->dat, 1, tkt->length, fp);
134         fclose(fp);
135         memset(keybuf, 0, sizeof(keybuf));      /* Clear the buffer */
136     }
137 #endif
138     if (k5key != NULL) {
139         /* block locals */
140         krb5_enc_data in;
141         krb5_data out;
142         krb5_error_code ret;
143
144         in.enctype = k5key->enctype;
145         in.kvno = 0;
146         in.ciphertext.length = tkt->length;
147         in.ciphertext.data = tkt->dat;
148         out.length = tkt->length;
149         out.data = malloc(tkt->length);
150         if (out.data == NULL)
151             return KFAILURE;    /* XXX maybe ENOMEM? */
152
153         /* XXX note the following assumes that context arg isn't used  */
154         ret =
155             krb5_c_decrypt(NULL, k5key,
156                            KRB5_KEYUSAGE_KDC_REP_TICKET, NULL, &in, &out);
157         if (ret) {
158             free(out.data);
159             return KFAILURE;
160         } else {
161             memcpy(tkt->dat, out.data, out.length);
162             memset(out.data, 0, out.length);
163             free(out.data);
164         }
165     } else {
166         pcbc_encrypt((C_Block *)tkt->dat,(C_Block *)tkt->dat,
167                      (long) tkt->length,key_s,(C_Block *) key,0);
168     }
169 #endif /* ! NOENCRYPTION */
170 #ifdef KRB_CRYPT_DEBUG
171     if (krb_debug) {
172         FILE *fp;
173         char *keybuf[BUFSIZ];   /* Avoid secret stuff in stdio buffers */
174
175         fp = fopen("/kerberos/tkt.clear", "wb");
176         setbuf(fp, keybuf);
177         fwrite(tkt->dat, 1, tkt->length, fp);
178         fclose(fp);
179         memset(keybuf, 0, sizeof(keybuf));      /* Clear the buffer */
180     }
181 #endif
182
183     *flags = *ptr;              /* get flags byte */
184     ptr += sizeof(*flags);
185     tkt_swap_bytes = 0;
186     if (HOST_BYTE_ORDER != ((*flags >> K_FLAG_ORDER)& 1))
187         tkt_swap_bytes++;
188
189     if (strlen(ptr) > ANAME_SZ)
190         return(KFAILURE);
191     (void) strcpy(pname,ptr);   /* pname */
192     ptr += strlen(pname) + 1;
193
194     if (strlen(ptr) > INST_SZ)
195         return(KFAILURE);
196     (void) strcpy(pinstance,ptr); /* instance */
197     ptr += strlen(pinstance) + 1;
198
199     if (strlen(ptr) > REALM_SZ)
200         return(KFAILURE);
201     (void) strcpy(prealm,ptr);  /* realm */
202     ptr += strlen(prealm) + 1;
203     /* temporary hack until realms are dealt with properly */
204     if (*prealm == 0)
205         (void) strcpy(prealm,KRB_REALM);
206
207     memcpy((char *)paddress, ptr, 4); /* net address */
208     ptr += 4;
209
210     memcpy((char *)session, ptr, 8); /* session key */
211     ptr+= 8;
212 #ifdef notdef /* DONT SWAP SESSION KEY spm 10/22/86 */
213     if (tkt_swap_bytes)
214         swap_C_Block(session);
215 #endif
216
217     /* get lifetime, being certain we don't get negative lifetimes */
218     uptr = (unsigned char *) ptr++;
219     *life = (int) *uptr;
220
221     memcpy((char *) time_sec, ptr, 4); /* issue time */
222     ptr += 4;
223     if (tkt_swap_bytes)
224         *time_sec = krb4_swab32(*time_sec);
225
226     (void) strcpy(sname,ptr);   /* service name */
227     ptr += 1 + strlen(sname);
228
229     (void) strcpy(sinstance,ptr); /* instance */
230     ptr += 1 + strlen(sinstance);
231
232 #ifdef KRB_CRYPT_DEBUG
233     if (krb_debug) {
234         krb_log("service=%s.%s len(sname)=%d, len(sinstance)=%d",
235                 sname, sinstance, strlen(sname), strlen(sinstance));
236         krb_log("ptr - tkt->dat=%d",(char *)ptr - (char *)tkt->dat);
237     }
238 #endif
239
240     return(KSUCCESS);
241 }