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