~ubuntu-branches/ubuntu/maverick/krb5/maverick

« back to all changes in this revision

Viewing changes to src/lib/krb4/decomp_tkt.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Hartman
  • Date: 2009-05-07 16:16:34 UTC
  • mfrom: (13.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20090507161634-xqyk0s9na0le4flj
Tags: 1.7dfsg~beta1-4
When  decrypting the TGS response fails with the subkey, try with the
session key to work around Heimdal bug, Closes: #527353 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * lib/krb4/decomp_tkt.c
3
 
 *
4
 
 * Copyright 1985, 1986, 1987, 1988, 2000, 2001 by the Massachusetts
5
 
 * Institute of Technology.  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.  Furthermore if you modify this software you must label
20
 
 * your software as modified software and not distribute it in such a
21
 
 * fashion that it might be confused with the original M.I.T. software.
22
 
 * M.I.T. makes no representations about the suitability of
23
 
 * this software for any purpose.  It is provided "as is" without express
24
 
 * or implied warranty.
25
 
 */
26
 
 
27
 
#include "des.h"
28
 
#include "krb.h"
29
 
#include "prot.h"
30
 
#include <string.h>
31
 
#include <krb5.h>
32
 
#include "krb54proto.h"
33
 
#include "port-sockets.h"
34
 
 
35
 
#ifdef KRB_CRYPT_DEBUG
36
 
extern int krb_debug;
37
 
#endif
38
 
 
39
 
static int dcmp_tkt_int (KTEXT tkt, unsigned char *flags, 
40
 
                                   char *pname, char *pinstance, char *prealm,
41
 
                                   unsigned KRB4_32 *paddress, C_Block session,
42
 
                                   int *life, unsigned KRB4_32 *time_sec, 
43
 
                                   char *sname, char *sinstance, C_Block key, 
44
 
                                   Key_schedule key_s, krb5_keyblock *k5key);
45
 
/*
46
 
 * This routine takes a ticket and pointers to the variables that
47
 
 * should be filled in based on the information in the ticket.  It
48
 
#ifndef NOENCRYPTION
49
 
 * decrypts the ticket using the given key, and 
50
 
#endif
51
 
 * fills in values for its arguments.
52
 
 *
53
 
 * Note: if the client realm field in the ticket is the null string,
54
 
 * then the "prealm" variable is filled in with the local realm (as
55
 
 * defined by KRB_REALM).
56
 
 *
57
 
 * If the ticket byte order is different than the host's byte order
58
 
 * (as indicated by the byte order bit of the "flags" field), then
59
 
 * the KDC timestamp "time_sec" is byte-swapped.  The other fields
60
 
 * potentially affected by byte order, "paddress" and "session" are
61
 
 * not byte-swapped.
62
 
 *
63
 
 * The routine returns KFAILURE if any of the "pname", "pinstance",
64
 
 * or "prealm" fields is too big, otherwise it returns KSUCCESS.
65
 
 *
66
 
 * The corresponding routine to generate tickets is create_ticket.
67
 
 * When changes are made to this routine, the corresponding changes
68
 
 * should also be made to that file.
69
 
 *
70
 
 * See create_ticket.c for the format of the ticket packet.
71
 
 */
72
 
 
73
 
int KRB5_CALLCONV               /* XXX should this be exported on win32? */
74
 
decomp_ticket(tkt, flags, pname, pinstance, prealm, paddress, session,
75
 
              life, time_sec, sname, sinstance, key, key_s)
76
 
    KTEXT tkt;                  /* The ticket to be decoded */
77
 
    unsigned char *flags;       /* Kerberos ticket flags */
78
 
    char *pname;                /* Authentication name */
79
 
    char *pinstance;            /* Principal's instance */
80
 
    char *prealm;               /* Principal's authentication domain */
81
 
    unsigned KRB4_32 *paddress; /* Net address of entity
82
 
                                 * requesting ticket */
83
 
    C_Block session;            /* Session key inserted in ticket */
84
 
    int *life;                  /* Lifetime of the ticket */
85
 
    unsigned KRB4_32 *time_sec; /* Issue time and date */
86
 
    char *sname;                /* Service name */
87
 
    char *sinstance;            /* Service instance */
88
 
    C_Block key;                /* Service's secret key
89
 
                                 * (to decrypt the ticket) */
90
 
    Key_schedule key_s;         /* The precomputed key schedule */
91
 
{
92
 
    return
93
 
        dcmp_tkt_int(tkt, flags, pname, pinstance, prealm,
94
 
                     paddress, session, life, time_sec, sname, sinstance,
95
 
                     key, key_s, NULL);
96
 
}
97
 
 
98
 
int
99
 
decomp_tkt_krb5(tkt, flags, pname, pinstance, prealm, paddress, session,
100
 
              life, time_sec, sname, sinstance, k5key)
101
 
    KTEXT tkt;                  /* The ticket to be decoded */
102
 
    unsigned char *flags;       /* Kerberos ticket flags */
103
 
    char *pname;                /* Authentication name */
104
 
    char *pinstance;            /* Principal's instance */
105
 
    char *prealm;               /* Principal's authentication domain */
106
 
    unsigned KRB4_32 *paddress; /* Net address of entity
107
 
                                 * requesting ticket */
108
 
    C_Block session;            /* Session key inserted in ticket */
109
 
    int *life;                  /* Lifetime of the ticket */
110
 
    unsigned KRB4_32 *time_sec; /* Issue time and date */
111
 
    char *sname;                /* Service name */
112
 
    char *sinstance;            /* Service instance */
113
 
    krb5_keyblock *k5key;       /* krb5 keyblock of service */
114
 
{
115
 
    C_Block key;                /* placeholder; doesn't get used */
116
 
    Key_schedule key_s;         /* placeholder; doesn't get used */
117
 
 
118
 
    return
119
 
        dcmp_tkt_int(tkt, flags, pname, pinstance, prealm, paddress, session,
120
 
                     life, time_sec, sname, sinstance, key, key_s, k5key);
121
 
}
122
 
 
123
 
static int
124
 
dcmp_tkt_int(tkt, flags, pname, pinstance, prealm, paddress, session,
125
 
              life, time_sec, sname, sinstance, key, key_s, k5key)
126
 
    KTEXT tkt;                  /* The ticket to be decoded */
127
 
    unsigned char *flags;       /* Kerberos ticket flags */
128
 
    char *pname;                /* Authentication name */
129
 
    char *pinstance;            /* Principal's instance */
130
 
    char *prealm;               /* Principal's authentication domain */
131
 
    unsigned KRB4_32 *paddress; /* Net address of entity
132
 
                                 * requesting ticket */
133
 
    C_Block session;            /* Session key inserted in ticket */
134
 
    int *life;                  /* Lifetime of the ticket */
135
 
    unsigned KRB4_32 *time_sec; /* Issue time and date */
136
 
    char *sname;                /* Service name */
137
 
    char *sinstance;            /* Service instance */
138
 
    C_Block key;                /* Service's secret key
139
 
                                 * (to decrypt the ticket) */
140
 
    Key_schedule key_s;         /* The precomputed key schedule */
141
 
    krb5_keyblock *k5key;       /* krb5 keyblock of service */
142
 
{
143
 
    int tkt_le;                 /* little-endian ticket? */
144
 
    unsigned char *ptr = tkt->dat;
145
 
    int kret, len;
146
 
    struct in_addr paddr;
147
 
 
148
 
    /* Be really paranoid. */
149
 
    if (sizeof(paddr.s_addr) != 4)
150
 
        return KFAILURE;
151
 
 
152
 
#ifndef NOENCRYPTION
153
 
    /* Do the decryption */
154
 
#ifdef KRB_CRYPT_DEBUG
155
 
    if (krb_debug) {
156
 
        FILE *fp;
157
 
        char *keybuf[BUFSIZ];   /* Avoid secret stuff in stdio buffers */
158
 
 
159
 
        fp = fopen("/kerberos/tkt.des", "wb");
160
 
        setbuf(fp, keybuf);
161
 
        fwrite(tkt->dat, 1, tkt->length, fp);
162
 
        fclose(fp);
163
 
        memset(keybuf, 0, sizeof(keybuf));      /* Clear the buffer */
164
 
    }
165
 
#endif
166
 
    if (k5key != NULL) {
167
 
        /* block locals */
168
 
        krb5_enc_data in;
169
 
        krb5_data out;
170
 
        krb5_error_code ret;
171
 
 
172
 
        in.enctype = k5key->enctype;
173
 
        in.kvno = 0;
174
 
        in.ciphertext.length = tkt->length;
175
 
        in.ciphertext.data = (char *)tkt->dat;
176
 
        out.length = tkt->length;
177
 
        out.data = malloc((size_t)tkt->length);
178
 
        if (out.data == NULL)
179
 
            return KFAILURE;    /* XXX maybe ENOMEM? */
180
 
 
181
 
        /* XXX note the following assumes that context arg isn't used  */
182
 
        ret =
183
 
            krb5_c_decrypt(NULL, k5key,
184
 
                           KRB5_KEYUSAGE_KDC_REP_TICKET, NULL, &in, &out);
185
 
        if (ret) {
186
 
            free(out.data);
187
 
            return KFAILURE;
188
 
        } else {
189
 
            memcpy(tkt->dat, out.data, out.length);
190
 
            memset(out.data, 0, out.length);
191
 
            free(out.data);
192
 
        }
193
 
    } else {
194
 
        pcbc_encrypt((C_Block *)tkt->dat, (C_Block *)tkt->dat,
195
 
                     (long)tkt->length, key_s, (C_Block *)key, 0);
196
 
    }
197
 
#endif /* ! NOENCRYPTION */
198
 
#ifdef KRB_CRYPT_DEBUG
199
 
    if (krb_debug) {
200
 
        FILE *fp;
201
 
        char *keybuf[BUFSIZ];   /* Avoid secret stuff in stdio buffers */
202
 
 
203
 
        fp = fopen("/kerberos/tkt.clear", "wb");
204
 
        setbuf(fp, keybuf);
205
 
        fwrite(tkt->dat, 1, tkt->length, fp);
206
 
        fclose(fp);
207
 
        memset(keybuf, 0, sizeof(keybuf));      /* Clear the buffer */
208
 
    }
209
 
#endif
210
 
 
211
 
#define TKT_REMAIN (tkt->length - (ptr - tkt->dat))
212
 
    kret = KFAILURE;
213
 
    if (TKT_REMAIN < 1)
214
 
        goto cleanup;
215
 
    *flags = *ptr++;
216
 
    tkt_le = (*flags >> K_FLAG_ORDER) & 1;
217
 
 
218
 
    len = krb4int_strnlen((char *)ptr, TKT_REMAIN) + 1;
219
 
    if (len <= 0 || len > ANAME_SZ)
220
 
        goto cleanup;
221
 
    memcpy(pname, ptr, (size_t)len);
222
 
    ptr += len;
223
 
 
224
 
    len = krb4int_strnlen((char *)ptr, TKT_REMAIN) + 1;
225
 
    if (len <= 0 || len > INST_SZ)
226
 
        goto cleanup;
227
 
    memcpy(pinstance, ptr, (size_t)len);
228
 
    ptr += len;
229
 
 
230
 
    len = krb4int_strnlen((char *)ptr, TKT_REMAIN) + 1;
231
 
    if (len <= 0 || len > REALM_SZ)
232
 
        goto cleanup;
233
 
    memcpy(prealm, ptr, (size_t)len);
234
 
    ptr += len;
235
 
 
236
 
    /*
237
 
     * This hack may be needed for some really krb4 servers, such as
238
 
     * AFS kaserver (?), that fail to fill in the realm of a ticket
239
 
     * under some circumstances.
240
 
     */
241
 
    if (*prealm == '\0')
242
 
        krb_get_lrealm(prealm, 1);
243
 
 
244
 
    /*
245
 
     * Ensure there's enough remaining in the ticket to get the
246
 
     * fixed-size stuff.
247
 
     */
248
 
    if (TKT_REMAIN < 4 + 8 + 1 + 4)
249
 
        goto cleanup;
250
 
 
251
 
    memcpy(&paddr.s_addr, ptr, sizeof(paddr.s_addr));
252
 
    ptr += sizeof(paddr.s_addr);
253
 
    *paddress = paddr.s_addr;
254
 
 
255
 
    memcpy(session, ptr, 8); /* session key */
256
 
    memset(ptr, 0, 8);
257
 
    ptr += 8;
258
 
#ifdef notdef /* DONT SWAP SESSION KEY spm 10/22/86 */
259
 
    if (tkt_swap_bytes)
260
 
        swap_C_Block(session);
261
 
#endif
262
 
 
263
 
    *life = *ptr++;
264
 
 
265
 
    KRB4_GET32(*time_sec, ptr, tkt_le);
266
 
 
267
 
    len = krb4int_strnlen((char *)ptr, TKT_REMAIN) + 1;
268
 
    if (len <= 0 || len > SNAME_SZ)
269
 
        goto cleanup;
270
 
    memcpy(sname, ptr, (size_t)len);
271
 
    ptr += len;
272
 
 
273
 
    len = krb4int_strnlen((char *)ptr, TKT_REMAIN) + 1;
274
 
    if (len <= 0 || len > INST_SZ)
275
 
        goto cleanup;
276
 
    memcpy(sinstance, ptr, (size_t)len);
277
 
    ptr += len;
278
 
    kret = KSUCCESS;
279
 
 
280
 
#ifdef KRB_CRYPT_DEBUG
281
 
    if (krb_debug) {
282
 
        krb_log("service=%s.%s len(sname)=%d, len(sinstance)=%d",
283
 
                sname, sinstance, strlen(sname), strlen(sinstance));
284
 
        krb_log("ptr - tkt->dat=%d",(char *)ptr - (char *)tkt->dat);
285
 
    }
286
 
#endif
287
 
 
288
 
cleanup:
289
 
    if (kret != KSUCCESS) {
290
 
        memset(session, 0, sizeof(session));
291
 
        memset(tkt->dat, 0, (size_t)tkt->length);
292
 
        return kret;
293
 
    }
294
 
    return KSUCCESS;
295
 
}