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

« back to all changes in this revision

Viewing changes to src/lib/gssapi/krb5/k5sealv3.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
/* -*- mode: c; indent-tabs-mode: nil -*- */
1
2
/*
2
3
 * lib/gssapi/krb5/k5sealv3.c
3
4
 *
4
 
 * Copyright 2003,2004 by the Massachusetts Institute of Technology.
 
5
 * Copyright 2003,2004,2007 by the Massachusetts Institute of Technology.
5
6
 * All Rights Reserved.
6
7
 *
7
8
 * Export of this software from the United States of America may
8
9
 *   require a specific license from the United States Government.
9
10
 *   It is the responsibility of any person or organization contemplating
10
11
 *   export to obtain such a license before exporting.
11
 
 * 
 
12
 *
12
13
 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13
14
 * distribute this software and its documentation for any purpose and
14
15
 * without fee is hereby granted, provided that the above copyright
22
23
 * M.I.T. makes no representations about the suitability of
23
24
 * this software for any purpose.  It is provided "as is" without express
24
25
 * or implied warranty.
25
 
 * 
 
26
 *
26
27
 *
27
28
 */
28
29
/* draft-ietf-krb-wg-gssapi-cfx-05 */
29
30
 
30
31
#include <assert.h>
31
 
#include "k5-platform.h"        /* for 64-bit support */
32
 
#include "k5-int.h"             /* for zap() */
 
32
#include "k5-platform.h"        /* for 64-bit support */
 
33
#include "k5-int.h"             /* for zap() */
33
34
#include "gssapiP_krb5.h"
34
35
#include <stdarg.h>
35
36
 
36
 
static int
37
 
rotate_left (void *ptr, size_t bufsiz, size_t rc)
 
37
int
 
38
gss_krb5int_rotate_left (void *ptr, size_t bufsiz, size_t rc)
38
39
{
39
40
    /* Optimize for receiving.  After some debugging is done, the MIT
40
41
       implementation won't do any rotates on sending, and while
44
45
    void *tbuf;
45
46
 
46
47
    if (bufsiz == 0)
47
 
        return 1;
 
48
        return 1;
48
49
    rc = rc % bufsiz;
49
50
    if (rc == 0)
50
 
        return 1;
 
51
        return 1;
51
52
 
52
53
    tbuf = malloc(rc);
53
54
    if (tbuf == 0)
54
 
        return 0;
 
55
        return 0;
55
56
    memcpy(tbuf, ptr, rc);
56
57
    memmove(ptr, (char *)ptr + rc, bufsiz - rc);
57
58
    memcpy((char *)ptr + bufsiz - rc, tbuf, rc);
61
62
 
62
63
static const gss_buffer_desc empty_message = { 0, 0 };
63
64
 
64
 
#define FLAG_SENDER_IS_ACCEPTOR 0x01
65
 
#define FLAG_WRAP_CONFIDENTIAL  0x02
66
 
#define FLAG_ACCEPTOR_SUBKEY    0x04
67
 
 
68
65
krb5_error_code
69
66
gss_krb5int_make_seal_token_v3 (krb5_context context,
70
 
                                krb5_gss_ctx_id_rec *ctx,
71
 
                                const gss_buffer_desc * message,
72
 
                                gss_buffer_t token,
73
 
                                int conf_req_flag, int toktype)
 
67
                                krb5_gss_ctx_id_rec *ctx,
 
68
                                const gss_buffer_desc * message,
 
69
                                gss_buffer_t token,
 
70
                                int conf_req_flag, int toktype)
74
71
{
75
72
    size_t bufsize = 16;
76
73
    unsigned char *outbuf = 0;
85
82
    unsigned short tok_id;
86
83
    krb5_checksum sum;
87
84
    krb5_keyblock *key;
 
85
    krb5_cksumtype cksumtype;
88
86
 
89
 
    assert(toktype != KG_TOK_SEAL_MSG || ctx->enc != 0);
90
87
    assert(ctx->big_endian == 0);
91
88
 
92
89
    acceptor_flag = ctx->initiate ? 0 : FLAG_SENDER_IS_ACCEPTOR;
93
90
    key_usage = (toktype == KG_TOK_WRAP_MSG
94
 
                 ? (ctx->initiate
95
 
                    ? KG_USAGE_INITIATOR_SEAL
96
 
                    : KG_USAGE_ACCEPTOR_SEAL)
97
 
                 : (ctx->initiate
98
 
                    ? KG_USAGE_INITIATOR_SIGN
99
 
                    : KG_USAGE_ACCEPTOR_SIGN));
 
91
                 ? (ctx->initiate
 
92
                    ? KG_USAGE_INITIATOR_SEAL
 
93
                    : KG_USAGE_ACCEPTOR_SEAL)
 
94
                 : (ctx->initiate
 
95
                    ? KG_USAGE_INITIATOR_SIGN
 
96
                    : KG_USAGE_ACCEPTOR_SIGN));
100
97
    if (ctx->have_acceptor_subkey) {
101
 
        key = ctx->acceptor_subkey;
 
98
        key = ctx->acceptor_subkey;
 
99
        cksumtype = ctx->acceptor_subkey_cksumtype;
102
100
    } else {
103
 
        key = ctx->enc;
 
101
        key = ctx->subkey;
 
102
        cksumtype = ctx->cksumtype;
104
103
    }
 
104
    assert(key != NULL);
105
105
 
106
106
#ifdef CFX_EXERCISE
107
107
    {
108
 
        static int initialized = 0;
109
 
        if (!initialized) {
110
 
            srand(time(0));
111
 
            initialized = 1;
112
 
        }
 
108
        static int initialized = 0;
 
109
        if (!initialized) {
 
110
            srand(time(0));
 
111
            initialized = 1;
 
112
        }
113
113
    }
114
114
#endif
115
115
 
116
116
    if (toktype == KG_TOK_WRAP_MSG && conf_req_flag) {
117
 
        krb5_data plain;
118
 
        krb5_enc_data cipher;
119
 
        size_t ec_max;
 
117
        krb5_data plain;
 
118
        krb5_enc_data cipher;
 
119
        size_t ec_max;
120
120
 
121
 
        /* 300: Adds some slop.  */
122
 
        if (SIZE_MAX - 300 < message->length)
123
 
            return ENOMEM;
124
 
        ec_max = SIZE_MAX - message->length - 300;
125
 
        if (ec_max > 0xffff)
126
 
            ec_max = 0xffff;
 
121
        /* 300: Adds some slop.  */
 
122
        if (SIZE_MAX - 300 < message->length)
 
123
            return ENOMEM;
 
124
        ec_max = SIZE_MAX - message->length - 300;
 
125
        if (ec_max > 0xffff)
 
126
            ec_max = 0xffff;
127
127
#ifdef CFX_EXERCISE
128
 
        /* For testing only.  For performance, always set ec = 0.  */
129
 
        ec = ec_max & rand();
 
128
        /* For testing only.  For performance, always set ec = 0.  */
 
129
        ec = ec_max & rand();
130
130
#else
131
 
        ec = 0;
 
131
        ec = 0;
132
132
#endif
133
 
        plain.length = message->length + 16 + ec;
134
 
        plain.data = malloc(message->length + 16 + ec);
135
 
        if (plain.data == NULL)
136
 
            return ENOMEM;
137
 
 
138
 
        /* Get size of ciphertext.  */
139
 
        bufsize = 16 + krb5_encrypt_size (plain.length, ctx->enc->enctype);
140
 
        /* Allocate space for header plus encrypted data.  */
141
 
        outbuf = malloc(bufsize);
142
 
        if (outbuf == NULL) {
143
 
            free(plain.data);
144
 
            return ENOMEM;
145
 
        }
146
 
 
147
 
        /* TOK_ID */
148
 
        store_16_be(0x0504, outbuf);
149
 
        /* flags */
150
 
        outbuf[2] = (acceptor_flag
151
 
                     | (conf_req_flag ? FLAG_WRAP_CONFIDENTIAL : 0)
152
 
                     | (ctx->have_acceptor_subkey ? FLAG_ACCEPTOR_SUBKEY : 0));
153
 
        /* filler */
154
 
        outbuf[3] = 0xff;
155
 
        /* EC */
156
 
        store_16_be(ec, outbuf+4);
157
 
        /* RRC */
158
 
        store_16_be(0, outbuf+6);
159
 
        store_64_be(ctx->seq_send, outbuf+8);
160
 
 
161
 
        memcpy(plain.data, message->value, message->length);
162
 
        memset(plain.data + message->length, 'x', ec);
163
 
        memcpy(plain.data + message->length + ec, outbuf, 16);
164
 
 
165
 
        cipher.ciphertext.data = outbuf + 16;
166
 
        cipher.ciphertext.length = bufsize - 16;
167
 
        cipher.enctype = key->enctype;
168
 
        err = krb5_c_encrypt(context, key, key_usage, 0, &plain, &cipher);
169
 
        zap(plain.data, plain.length);
170
 
        free(plain.data);
171
 
        plain.data = 0;
172
 
        if (err)
173
 
            goto error;
174
 
 
175
 
        /* Now that we know we're returning a valid token....  */
176
 
        ctx->seq_send++;
 
133
        plain.length = message->length + 16 + ec;
 
134
        plain.data = malloc(message->length + 16 + ec);
 
135
        if (plain.data == NULL)
 
136
            return ENOMEM;
 
137
 
 
138
        /* Get size of ciphertext.  */
 
139
        bufsize = 16 + krb5_encrypt_size (plain.length, key->enctype);
 
140
        /* Allocate space for header plus encrypted data.  */
 
141
        outbuf = malloc(bufsize);
 
142
        if (outbuf == NULL) {
 
143
            free(plain.data);
 
144
            return ENOMEM;
 
145
        }
 
146
 
 
147
        /* TOK_ID */
 
148
        store_16_be(KG2_TOK_WRAP_MSG, outbuf);
 
149
        /* flags */
 
150
        outbuf[2] = (acceptor_flag
 
151
                     | (conf_req_flag ? FLAG_WRAP_CONFIDENTIAL : 0)
 
152
                     | (ctx->have_acceptor_subkey ? FLAG_ACCEPTOR_SUBKEY : 0));
 
153
        /* filler */
 
154
        outbuf[3] = 0xff;
 
155
        /* EC */
 
156
        store_16_be(ec, outbuf+4);
 
157
        /* RRC */
 
158
        store_16_be(0, outbuf+6);
 
159
        store_64_be(ctx->seq_send, outbuf+8);
 
160
 
 
161
        memcpy(plain.data, message->value, message->length);
 
162
        memset(plain.data + message->length, 'x', ec);
 
163
        memcpy(plain.data + message->length + ec, outbuf, 16);
 
164
 
 
165
        cipher.ciphertext.data = (char *)outbuf + 16;
 
166
        cipher.ciphertext.length = bufsize - 16;
 
167
        cipher.enctype = key->enctype;
 
168
        err = krb5_c_encrypt(context, key, key_usage, 0, &plain, &cipher);
 
169
        zap(plain.data, plain.length);
 
170
        free(plain.data);
 
171
        plain.data = 0;
 
172
        if (err)
 
173
            goto error;
 
174
 
 
175
        /* Now that we know we're returning a valid token....  */
 
176
        ctx->seq_send++;
177
177
 
178
178
#ifdef CFX_EXERCISE
179
 
        rrc = rand() & 0xffff;
180
 
        if (rotate_left(outbuf+16, bufsize-16,
181
 
                        (bufsize-16) - (rrc % (bufsize - 16))))
182
 
            store_16_be(rrc, outbuf+6);
183
 
        /* If the rotate fails, don't worry about it.  */
 
179
        rrc = rand() & 0xffff;
 
180
        if (gss_krb5int_rotate_left(outbuf+16, bufsize-16,
 
181
                        (bufsize-16) - (rrc % (bufsize - 16))))
 
182
            store_16_be(rrc, outbuf+6);
 
183
        /* If the rotate fails, don't worry about it.  */
184
184
#endif
185
185
    } else if (toktype == KG_TOK_WRAP_MSG && !conf_req_flag) {
186
 
        krb5_data plain;
187
 
 
188
 
        /* Here, message is the application-supplied data; message2 is
189
 
           what goes into the output token.  They may be the same, or
190
 
           message2 may be empty (for MIC).  */
191
 
 
192
 
        tok_id = 0x0504;
 
186
        krb5_data plain;
 
187
        size_t cksumsize;
 
188
 
 
189
        /* Here, message is the application-supplied data; message2 is
 
190
           what goes into the output token.  They may be the same, or
 
191
           message2 may be empty (for MIC).  */
 
192
 
 
193
        tok_id = KG2_TOK_WRAP_MSG;
193
194
 
194
195
    wrap_with_checksum:
195
 
        plain.length = message->length + 16;
196
 
        plain.data = malloc(message->length + 16);
197
 
        if (plain.data == NULL)
198
 
            return ENOMEM;
199
 
 
200
 
        if (ctx->cksum_size > 0xffff)
201
 
            abort();
202
 
 
203
 
        bufsize = 16 + message2->length + ctx->cksum_size;
204
 
        outbuf = malloc(bufsize);
205
 
        if (outbuf == NULL) {
206
 
            free(plain.data);
207
 
            plain.data = 0;
208
 
            err = ENOMEM;
209
 
            goto error;
210
 
        }
211
 
 
212
 
        /* TOK_ID */
213
 
        store_16_be(tok_id, outbuf);
214
 
        /* flags */
215
 
        outbuf[2] = (acceptor_flag
216
 
                     | (ctx->have_acceptor_subkey ? FLAG_ACCEPTOR_SUBKEY : 0));
217
 
        /* filler */
218
 
        outbuf[3] = 0xff;
219
 
        if (toktype == KG_TOK_WRAP_MSG) {
220
 
            /* Use 0 for checksum calculation, substitute
221
 
               checksum length later.  */
222
 
            /* EC */
223
 
            store_16_be(0, outbuf+4);
224
 
            /* RRC */
225
 
            store_16_be(0, outbuf+6);
226
 
        } else {
227
 
            /* MIC and DEL store 0xFF in EC and RRC.  */
228
 
            store_16_be(0xffff, outbuf+4);
229
 
            store_16_be(0xffff, outbuf+6);
230
 
        }
231
 
        store_64_be(ctx->seq_send, outbuf+8);
232
 
 
233
 
        memcpy(plain.data, message->value, message->length);
234
 
        memcpy(plain.data + message->length, outbuf, 16);
235
 
 
236
 
        /* Fill in the output token -- data contents, if any, and
237
 
           space for the checksum.  */
238
 
        if (message2->length)
239
 
            memcpy(outbuf + 16, message2->value, message2->length);
240
 
 
241
 
        sum.contents = outbuf + 16 + message2->length;
242
 
        sum.length = ctx->cksum_size;
243
 
 
244
 
        err = krb5_c_make_checksum(context, ctx->cksumtype, key,
245
 
                                   key_usage, &plain, &sum);
246
 
        zap(plain.data, plain.length);
247
 
        free(plain.data);
248
 
        plain.data = 0;
249
 
        if (err) {
250
 
            zap(outbuf,bufsize);
251
 
            free(outbuf);
252
 
            goto error;
253
 
        }
254
 
        if (sum.length != ctx->cksum_size)
255
 
            abort();
256
 
        memcpy(outbuf + 16 + message2->length, sum.contents, ctx->cksum_size);
257
 
        krb5_free_checksum_contents(context, &sum);
258
 
        sum.contents = 0;
259
 
        /* Now that we know we're actually generating the token...  */
260
 
        ctx->seq_send++;
261
 
 
262
 
        if (toktype == KG_TOK_WRAP_MSG) {
 
196
        plain.length = message->length + 16;
 
197
        plain.data = malloc(message->length + 16);
 
198
        if (plain.data == NULL)
 
199
            return ENOMEM;
 
200
 
 
201
        err = krb5_c_checksum_length(context, cksumtype, &cksumsize);
 
202
        if (err)
 
203
            goto error;
 
204
 
 
205
        assert(cksumsize <= 0xffff);
 
206
 
 
207
        bufsize = 16 + message2->length + cksumsize;
 
208
        outbuf = malloc(bufsize);
 
209
        if (outbuf == NULL) {
 
210
            free(plain.data);
 
211
            plain.data = 0;
 
212
            err = ENOMEM;
 
213
            goto error;
 
214
        }
 
215
 
 
216
        /* TOK_ID */
 
217
        store_16_be(tok_id, outbuf);
 
218
        /* flags */
 
219
        outbuf[2] = (acceptor_flag
 
220
                     | (ctx->have_acceptor_subkey ? FLAG_ACCEPTOR_SUBKEY : 0));
 
221
        /* filler */
 
222
        outbuf[3] = 0xff;
 
223
        if (toktype == KG_TOK_WRAP_MSG) {
 
224
            /* Use 0 for checksum calculation, substitute
 
225
               checksum length later.  */
 
226
            /* EC */
 
227
            store_16_be(0, outbuf+4);
 
228
            /* RRC */
 
229
            store_16_be(0, outbuf+6);
 
230
        } else {
 
231
            /* MIC and DEL store 0xFF in EC and RRC.  */
 
232
            store_16_be(0xffff, outbuf+4);
 
233
            store_16_be(0xffff, outbuf+6);
 
234
        }
 
235
        store_64_be(ctx->seq_send, outbuf+8);
 
236
 
 
237
        memcpy(plain.data, message->value, message->length);
 
238
        memcpy(plain.data + message->length, outbuf, 16);
 
239
 
 
240
        /* Fill in the output token -- data contents, if any, and
 
241
           space for the checksum.  */
 
242
        if (message2->length)
 
243
            memcpy(outbuf + 16, message2->value, message2->length);
 
244
 
 
245
        sum.contents = outbuf + 16 + message2->length;
 
246
        sum.length = cksumsize;
 
247
 
 
248
        err = krb5_c_make_checksum(context, cksumtype, key,
 
249
                                   key_usage, &plain, &sum);
 
250
        zap(plain.data, plain.length);
 
251
        free(plain.data);
 
252
        plain.data = 0;
 
253
        if (err) {
 
254
            zap(outbuf,bufsize);
 
255
            goto error;
 
256
        }
 
257
        if (sum.length != cksumsize)
 
258
            abort();
 
259
        memcpy(outbuf + 16 + message2->length, sum.contents, cksumsize);
 
260
        krb5_free_checksum_contents(context, &sum);
 
261
        sum.contents = 0;
 
262
        /* Now that we know we're actually generating the token...  */
 
263
        ctx->seq_send++;
 
264
 
 
265
        if (toktype == KG_TOK_WRAP_MSG) {
263
266
#ifdef CFX_EXERCISE
264
 
            rrc = rand() & 0xffff;
265
 
            /* If the rotate fails, don't worry about it.  */
266
 
            if (rotate_left(outbuf+16, bufsize-16,
267
 
                            (bufsize-16) - (rrc % (bufsize - 16))))
268
 
                store_16_be(rrc, outbuf+6);
 
267
            rrc = rand() & 0xffff;
 
268
            /* If the rotate fails, don't worry about it.  */
 
269
            if (gss_krb5int_rotate_left(outbuf+16, bufsize-16,
 
270
                            (bufsize-16) - (rrc % (bufsize - 16))))
 
271
                store_16_be(rrc, outbuf+6);
269
272
#endif
270
 
            /* Fix up EC field.  */
271
 
            store_16_be(ctx->cksum_size, outbuf+4);
272
 
        } else {
273
 
            store_16_be(0xffff, outbuf+6);
274
 
        }
 
273
            /* Fix up EC field.  */
 
274
            store_16_be(cksumsize, outbuf+4);
 
275
        } else {
 
276
            store_16_be(0xffff, outbuf+6);
 
277
        }
275
278
    } else if (toktype == KG_TOK_MIC_MSG) {
276
 
        tok_id = 0x0404;
277
 
        message2 = &empty_message;
278
 
        goto wrap_with_checksum;
 
279
        tok_id = KG2_TOK_MIC_MSG;
 
280
        message2 = &empty_message;
 
281
        goto wrap_with_checksum;
279
282
    } else if (toktype == KG_TOK_DEL_CTX) {
280
 
        tok_id = 0x0405;
281
 
        message = message2 = &empty_message;
282
 
        goto wrap_with_checksum;
 
283
        tok_id = KG2_TOK_DEL_CTX;
 
284
        message = message2 = &empty_message;
 
285
        goto wrap_with_checksum;
283
286
    } else
284
 
        abort();
 
287
        abort();
285
288
 
286
289
    token->value = outbuf;
287
290
    token->length = bufsize;
299
302
 
300
303
OM_uint32
301
304
gss_krb5int_unseal_token_v3(krb5_context *contextptr,
302
 
                            OM_uint32 *minor_status,
303
 
                            krb5_gss_ctx_id_rec *ctx,
304
 
                            unsigned char *ptr, int bodysize,
305
 
                            gss_buffer_t message_buffer,
306
 
                            int *conf_state, int *qop_state, int toktype)
 
305
                            OM_uint32 *minor_status,
 
306
                            krb5_gss_ctx_id_rec *ctx,
 
307
                            unsigned char *ptr, unsigned int bodysize,
 
308
                            gss_buffer_t message_buffer,
 
309
                            int *conf_state, gss_qop_t *qop_state, int toktype)
307
310
{
308
311
    krb5_context context = *contextptr;
309
312
    krb5_data plain;
315
318
    krb5_error_code err;
316
319
    krb5_boolean valid;
317
320
    krb5_keyblock *key;
 
321
    krb5_cksumtype cksumtype;
318
322
 
319
 
    assert(toktype != KG_TOK_SEAL_MSG || ctx->enc != 0);
320
 
    assert(ctx->big_endian == 0);
321
 
    assert(ctx->proto == 1);
 
323
    if (ctx->big_endian != 0)
 
324
        goto defective;
322
325
 
323
326
    if (qop_state)
324
 
        *qop_state = GSS_C_QOP_DEFAULT;
 
327
        *qop_state = GSS_C_QOP_DEFAULT;
325
328
 
326
329
    acceptor_flag = ctx->initiate ? FLAG_SENDER_IS_ACCEPTOR : 0;
327
330
    key_usage = (toktype == KG_TOK_WRAP_MSG
328
 
                 ? (!ctx->initiate
329
 
                    ? KG_USAGE_INITIATOR_SEAL
330
 
                    : KG_USAGE_ACCEPTOR_SEAL)
331
 
                 : (!ctx->initiate
332
 
                    ? KG_USAGE_INITIATOR_SIGN
333
 
                    : KG_USAGE_ACCEPTOR_SIGN));
 
331
                 ? (!ctx->initiate
 
332
                    ? KG_USAGE_INITIATOR_SEAL
 
333
                    : KG_USAGE_ACCEPTOR_SEAL)
 
334
                 : (!ctx->initiate
 
335
                    ? KG_USAGE_INITIATOR_SIGN
 
336
                    : KG_USAGE_ACCEPTOR_SIGN));
334
337
 
335
338
    /* Oops.  I wrote this code assuming ptr would be at the start of
336
339
       the token header.  */
339
342
 
340
343
    if (bodysize < 16) {
341
344
    defective:
342
 
        *minor_status = 0;
343
 
        return GSS_S_DEFECTIVE_TOKEN;
 
345
        *minor_status = 0;
 
346
        return GSS_S_DEFECTIVE_TOKEN;
344
347
    }
345
348
    if ((ptr[2] & FLAG_SENDER_IS_ACCEPTOR) != acceptor_flag) {
346
 
        *minor_status = G_BAD_DIRECTION;
347
 
        return GSS_S_BAD_SIG;
 
349
        *minor_status = (OM_uint32)G_BAD_DIRECTION;
 
350
        return GSS_S_BAD_SIG;
348
351
    }
349
352
 
350
353
    /* Two things to note here.
351
354
 
352
 
       First, we can't really enforce the use of the acceptor's subkey,
353
 
       if we're the acceptor; the initiator may have sent messages
354
 
       before getting the subkey.  We could probably enforce it if
355
 
       we're the initiator.
 
355
    First, we can't really enforce the use of the acceptor's subkey,
 
356
    if we're the acceptor; the initiator may have sent messages
 
357
    before getting the subkey.  We could probably enforce it if
 
358
    we're the initiator.
356
359
 
357
 
       Second, if someone tweaks the code to not set the flag telling
358
 
       the krb5 library to generate a new subkey in the AP-REP
359
 
       message, the MIT library may include a subkey anyways --
360
 
       namely, a copy of the AP-REQ subkey, if it was provided.  So
361
 
       the initiator may think we wanted a subkey, and set the flag,
362
 
       even though we weren't trying to set the subkey.  The "other"
363
 
       key, the one not asserted by the acceptor, will have the same
364
 
       value in that case, though, so we can just ignore the flag.  */
 
360
    Second, if someone tweaks the code to not set the flag telling
 
361
    the krb5 library to generate a new subkey in the AP-REP
 
362
    message, the MIT library may include a subkey anyways --
 
363
    namely, a copy of the AP-REQ subkey, if it was provided.  So
 
364
    the initiator may think we wanted a subkey, and set the flag,
 
365
    even though we weren't trying to set the subkey.  The "other"
 
366
    key, the one not asserted by the acceptor, will have the same
 
367
    value in that case, though, so we can just ignore the flag.  */
365
368
    if (ctx->have_acceptor_subkey && (ptr[2] & FLAG_ACCEPTOR_SUBKEY)) {
366
 
        key = ctx->acceptor_subkey;
 
369
        key = ctx->acceptor_subkey;
 
370
        cksumtype = ctx->acceptor_subkey_cksumtype;
367
371
    } else {
368
 
        key = ctx->enc;
 
372
        key = ctx->subkey;
 
373
        cksumtype = ctx->cksumtype;
369
374
    }
 
375
    assert(key != NULL);
370
376
 
371
377
    if (toktype == KG_TOK_WRAP_MSG) {
372
 
        if (load_16_be(ptr) != 0x0504)
373
 
            goto defective;
374
 
        if (ptr[3] != 0xff)
375
 
            goto defective;
376
 
        ec = load_16_be(ptr+4);
377
 
        rrc = load_16_be(ptr+6);
378
 
        seqnum = load_64_be(ptr+8);
379
 
        if (!rotate_left(ptr+16, bodysize-16, rrc)) {
380
 
        no_mem:
381
 
            *minor_status = ENOMEM;
382
 
            return GSS_S_FAILURE;
383
 
        }
384
 
        if (ptr[2] & FLAG_WRAP_CONFIDENTIAL) {
385
 
            /* confidentiality */
386
 
            krb5_enc_data cipher;
387
 
            unsigned char *althdr;
388
 
 
389
 
            if (conf_state)
390
 
                *conf_state = 1;
391
 
            /* Do we have no decrypt_size function?
392
 
 
393
 
               For all current cryptosystems, the ciphertext size will
394
 
               be larger than the plaintext size.  */
395
 
            cipher.enctype = key->enctype;
396
 
            cipher.ciphertext.length = bodysize - 16;
397
 
            cipher.ciphertext.data = ptr + 16;
398
 
            plain.length = bodysize - 16;
399
 
            plain.data = malloc(plain.length);
400
 
            if (plain.data == NULL)
401
 
                goto no_mem;
402
 
            err = krb5_c_decrypt(context, key, key_usage, 0,
403
 
                                 &cipher, &plain);
404
 
            if (err) {
405
 
                free(plain.data);
406
 
                goto error;
407
 
            }
408
 
            /* Don't use bodysize here!  Use the fact that
409
 
               cipher.ciphertext.length has been adjusted to the
410
 
               correct length.  */
411
 
            althdr = plain.data + plain.length - 16;
412
 
            if (load_16_be(althdr) != 0x0504
413
 
                || althdr[2] != ptr[2]
414
 
                || althdr[3] != ptr[3]
415
 
                || memcmp(althdr+8, ptr+8, 8)) {
416
 
                free(plain.data);
417
 
                goto defective;
418
 
            }
419
 
            message_buffer->value = plain.data;
420
 
            message_buffer->length = plain.length - ec - 16;
421
 
            if(message_buffer->length == 0) {
422
 
              free(message_buffer->value);
423
 
              message_buffer->value = NULL;
424
 
            }
425
 
        } else {
426
 
            /* no confidentiality */
427
 
            if (conf_state)
428
 
                *conf_state = 0;
429
 
            if (ec + 16 < ec)
430
 
                /* overflow check */
431
 
                goto defective;
432
 
            if (ec + 16 > bodysize)
433
 
                goto defective;
434
 
            /* We have: header | msg | cksum.
435
 
               We need cksum(msg | header).
436
 
               Rotate the first two.  */
437
 
            store_16_be(0, ptr+4);
438
 
            store_16_be(0, ptr+6);
439
 
            plain.length = bodysize-ec;
440
 
            plain.data = ptr;
441
 
            if (!rotate_left(ptr, bodysize-ec, 16))
442
 
                goto no_mem;
443
 
            sum.length = ec;
444
 
            if (sum.length != ctx->cksum_size) {
445
 
                *minor_status = 0;
446
 
                return GSS_S_BAD_SIG;
447
 
            }
448
 
            sum.contents = ptr+bodysize-ec;
449
 
            sum.checksum_type = ctx->cksumtype;
450
 
            err = krb5_c_verify_checksum(context, key, key_usage,
451
 
                                         &plain, &sum, &valid);
452
 
            if (err)
453
 
                goto error;
454
 
            if (!valid) {
455
 
                *minor_status = 0;
456
 
                return GSS_S_BAD_SIG;
457
 
            }
458
 
            message_buffer->length = plain.length - 16;
459
 
            message_buffer->value = malloc(message_buffer->length);
460
 
            if (message_buffer->value == NULL)
461
 
                goto no_mem;
462
 
            memcpy(message_buffer->value, plain.data, message_buffer->length);
463
 
        }
464
 
        err = g_order_check(&ctx->seqstate, seqnum);
465
 
        *minor_status = 0;
466
 
        return err;
 
378
        if (load_16_be(ptr) != KG2_TOK_WRAP_MSG)
 
379
            goto defective;
 
380
        if (ptr[3] != 0xff)
 
381
            goto defective;
 
382
        ec = load_16_be(ptr+4);
 
383
        rrc = load_16_be(ptr+6);
 
384
        seqnum = load_64_be(ptr+8);
 
385
        if (!gss_krb5int_rotate_left(ptr+16, bodysize-16, rrc)) {
 
386
        no_mem:
 
387
            *minor_status = ENOMEM;
 
388
            return GSS_S_FAILURE;
 
389
        }
 
390
        if (ptr[2] & FLAG_WRAP_CONFIDENTIAL) {
 
391
            /* confidentiality */
 
392
            krb5_enc_data cipher;
 
393
            unsigned char *althdr;
 
394
 
 
395
            if (conf_state)
 
396
                *conf_state = 1;
 
397
            /* Do we have no decrypt_size function?
 
398
 
 
399
            For all current cryptosystems, the ciphertext size will
 
400
            be larger than the plaintext size.  */
 
401
            cipher.enctype = key->enctype;
 
402
            cipher.ciphertext.length = bodysize - 16;
 
403
            cipher.ciphertext.data = (char *)ptr + 16;
 
404
            plain.length = bodysize - 16;
 
405
            plain.data = malloc(plain.length);
 
406
            if (plain.data == NULL)
 
407
                goto no_mem;
 
408
            err = krb5_c_decrypt(context, key, key_usage, 0,
 
409
                                 &cipher, &plain);
 
410
            if (err) {
 
411
                free(plain.data);
 
412
                goto error;
 
413
            }
 
414
            /* Don't use bodysize here!  Use the fact that
 
415
               cipher.ciphertext.length has been adjusted to the
 
416
               correct length.  */
 
417
            althdr = (unsigned char *)plain.data + plain.length - 16;
 
418
            if (load_16_be(althdr) != KG2_TOK_WRAP_MSG
 
419
                || althdr[2] != ptr[2]
 
420
                || althdr[3] != ptr[3]
 
421
                || memcmp(althdr+8, ptr+8, 8)) {
 
422
                free(plain.data);
 
423
                goto defective;
 
424
            }
 
425
            message_buffer->value = plain.data;
 
426
            message_buffer->length = plain.length - ec - 16;
 
427
            if(message_buffer->length == 0) {
 
428
                free(message_buffer->value);
 
429
                message_buffer->value = NULL;
 
430
            }
 
431
        } else {
 
432
            size_t cksumsize;
 
433
 
 
434
            err = krb5_c_checksum_length(context, cksumtype, &cksumsize);
 
435
            if (err)
 
436
                goto error;
 
437
 
 
438
            /* no confidentiality */
 
439
            if (conf_state)
 
440
                *conf_state = 0;
 
441
            if (ec + 16 < ec)
 
442
                /* overflow check */
 
443
                goto defective;
 
444
            if (ec + 16 > bodysize)
 
445
                goto defective;
 
446
            /* We have: header | msg | cksum.
 
447
               We need cksum(msg | header).
 
448
               Rotate the first two.  */
 
449
            store_16_be(0, ptr+4);
 
450
            store_16_be(0, ptr+6);
 
451
            plain.length = bodysize-ec;
 
452
            plain.data = (char *)ptr;
 
453
            if (!gss_krb5int_rotate_left(ptr, bodysize-ec, 16))
 
454
                goto no_mem;
 
455
            sum.length = ec;
 
456
            if (sum.length != cksumsize) {
 
457
                *minor_status = 0;
 
458
                return GSS_S_BAD_SIG;
 
459
            }
 
460
            sum.contents = ptr+bodysize-ec;
 
461
            sum.checksum_type = cksumtype;
 
462
            err = krb5_c_verify_checksum(context, key, key_usage,
 
463
                                         &plain, &sum, &valid);
 
464
            if (err)
 
465
                goto error;
 
466
            if (!valid) {
 
467
                *minor_status = 0;
 
468
                return GSS_S_BAD_SIG;
 
469
            }
 
470
            message_buffer->length = plain.length - 16;
 
471
            message_buffer->value = malloc(message_buffer->length);
 
472
            if (message_buffer->value == NULL)
 
473
                goto no_mem;
 
474
            memcpy(message_buffer->value, plain.data, message_buffer->length);
 
475
        }
 
476
        err = g_order_check(&ctx->seqstate, seqnum);
 
477
        *minor_status = 0;
 
478
        return err;
467
479
    } else if (toktype == KG_TOK_MIC_MSG) {
468
 
        /* wrap token, no confidentiality */
469
 
        if (load_16_be(ptr) != 0x0404)
470
 
            goto defective;
 
480
        /* wrap token, no confidentiality */
 
481
        if (load_16_be(ptr) != KG2_TOK_MIC_MSG)
 
482
            goto defective;
471
483
    verify_mic_1:
472
 
        if (ptr[3] != 0xff)
473
 
            goto defective;
474
 
        if (load_32_be(ptr+4) != 0xffffffffL)
475
 
            goto defective;
476
 
        seqnum = load_64_be(ptr+8);
477
 
        plain.length = message_buffer->length + 16;
478
 
        plain.data = malloc(plain.length);
479
 
        if (plain.data == NULL)
480
 
            goto no_mem;
481
 
        if (message_buffer->length)
482
 
            memcpy(plain.data, message_buffer->value, message_buffer->length);
483
 
        memcpy(plain.data + message_buffer->length, ptr, 16);
484
 
        sum.length = bodysize - 16;
485
 
        sum.contents = ptr + 16;
486
 
        sum.checksum_type = ctx->cksumtype;
487
 
        err = krb5_c_verify_checksum(context, key, key_usage,
488
 
                                     &plain, &sum, &valid);
489
 
        free(plain.data);
490
 
        plain.data = NULL;
491
 
        if (err) {
492
 
        error:
493
 
            *minor_status = err;
494
 
            return GSS_S_BAD_SIG; /* XXX */
495
 
        }
496
 
        if (!valid) {
497
 
            *minor_status = 0;
498
 
            return GSS_S_BAD_SIG;
499
 
        }
500
 
        err = g_order_check(&ctx->seqstate, seqnum);
501
 
        *minor_status = 0;
502
 
        return err;
 
484
        if (ptr[3] != 0xff)
 
485
            goto defective;
 
486
        if (load_32_be(ptr+4) != 0xffffffffL)
 
487
            goto defective;
 
488
        seqnum = load_64_be(ptr+8);
 
489
        plain.length = message_buffer->length + 16;
 
490
        plain.data = malloc(plain.length);
 
491
        if (plain.data == NULL)
 
492
            goto no_mem;
 
493
        if (message_buffer->length)
 
494
            memcpy(plain.data, message_buffer->value, message_buffer->length);
 
495
        memcpy(plain.data + message_buffer->length, ptr, 16);
 
496
        sum.length = bodysize - 16;
 
497
        sum.contents = ptr + 16;
 
498
        sum.checksum_type = cksumtype;
 
499
        err = krb5_c_verify_checksum(context, key, key_usage,
 
500
                                     &plain, &sum, &valid);
 
501
        free(plain.data);
 
502
        plain.data = NULL;
 
503
        if (err) {
 
504
        error:
 
505
            *minor_status = err;
 
506
            save_error_info(*minor_status, context);
 
507
            return GSS_S_BAD_SIG; /* XXX */
 
508
        }
 
509
        if (!valid) {
 
510
            *minor_status = 0;
 
511
            return GSS_S_BAD_SIG;
 
512
        }
 
513
        err = g_order_check(&ctx->seqstate, seqnum);
 
514
        *minor_status = 0;
 
515
        return err;
503
516
    } else if (toktype == KG_TOK_DEL_CTX) {
504
 
        if (load_16_be(ptr) != 0x0405)
505
 
            goto defective;
506
 
        message_buffer = &empty_message;
507
 
        goto verify_mic_1;
 
517
        if (load_16_be(ptr) != KG2_TOK_DEL_CTX)
 
518
            goto defective;
 
519
        message_buffer = (gss_buffer_t)&empty_message;
 
520
        goto verify_mic_1;
508
521
    } else {
509
 
        goto defective;
 
522
        goto defective;
510
523
    }
511
524
}