Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/kgssapi/krb5/krb5_mech.c
39507 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2008 Isilon Inc http://www.isilon.com/
5
* Authors: Doug Rabson <[email protected]>
6
* Developed with Red Inc: Alfred Perlstein <[email protected]>
7
*
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
10
* are met:
11
* 1. Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
* SUCH DAMAGE.
28
*/
29
30
#include <sys/cdefs.h>
31
#include "opt_inet6.h"
32
33
#include <sys/param.h>
34
#include <sys/kernel.h>
35
#include <sys/kobj.h>
36
#include <sys/lock.h>
37
#include <sys/malloc.h>
38
#include <sys/mbuf.h>
39
#include <sys/module.h>
40
#include <sys/mutex.h>
41
#include <kgssapi/gssapi.h>
42
#include <kgssapi/gssapi_impl.h>
43
44
#include "kgss_if.h"
45
#include "kcrypto.h"
46
47
#define GSS_TOKEN_SENT_BY_ACCEPTOR 1
48
#define GSS_TOKEN_SEALED 2
49
#define GSS_TOKEN_ACCEPTOR_SUBKEY 4
50
51
static gss_OID_desc krb5_mech_oid =
52
{9, (void *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" };
53
54
struct krb5_data {
55
size_t kd_length;
56
void *kd_data;
57
};
58
59
struct krb5_keyblock {
60
uint16_t kk_type; /* encryption type */
61
struct krb5_data kk_key; /* key data */
62
};
63
64
struct krb5_address {
65
uint16_t ka_type;
66
struct krb5_data ka_addr;
67
};
68
69
/*
70
* The km_elem array is ordered so that the highest received sequence
71
* number is listed first.
72
*/
73
struct krb5_msg_order {
74
uint32_t km_flags;
75
uint32_t km_start;
76
uint32_t km_length;
77
uint32_t km_jitter_window;
78
uint32_t km_first_seq;
79
uint32_t *km_elem;
80
};
81
82
struct krb5_context {
83
struct _gss_ctx_id_t kc_common;
84
struct mtx kc_lock;
85
uint32_t kc_ac_flags;
86
uint32_t kc_ctx_flags;
87
uint32_t kc_more_flags;
88
#define LOCAL 1
89
#define OPEN 2
90
#define COMPAT_OLD_DES3 4
91
#define COMPAT_OLD_DES3_SELECTED 8
92
#define ACCEPTOR_SUBKEY 16
93
struct krb5_address kc_local_address;
94
struct krb5_address kc_remote_address;
95
uint16_t kc_local_port;
96
uint16_t kc_remote_port;
97
struct krb5_keyblock kc_keyblock;
98
struct krb5_keyblock kc_local_subkey;
99
struct krb5_keyblock kc_remote_subkey;
100
volatile uint32_t kc_local_seqnumber;
101
uint32_t kc_remote_seqnumber;
102
uint32_t kc_keytype;
103
uint32_t kc_cksumtype;
104
struct krb5_data kc_source_name;
105
struct krb5_data kc_target_name;
106
uint32_t kc_lifetime;
107
struct krb5_msg_order kc_msg_order;
108
struct krb5_key_state *kc_tokenkey;
109
struct krb5_key_state *kc_encryptkey;
110
struct krb5_key_state *kc_checksumkey;
111
112
struct krb5_key_state *kc_send_seal_Ke;
113
struct krb5_key_state *kc_send_seal_Ki;
114
struct krb5_key_state *kc_send_seal_Kc;
115
struct krb5_key_state *kc_send_sign_Kc;
116
117
struct krb5_key_state *kc_recv_seal_Ke;
118
struct krb5_key_state *kc_recv_seal_Ki;
119
struct krb5_key_state *kc_recv_seal_Kc;
120
struct krb5_key_state *kc_recv_sign_Kc;
121
};
122
123
static uint16_t
124
get_uint16(const uint8_t **pp, size_t *lenp)
125
{
126
const uint8_t *p = *pp;
127
uint16_t v;
128
129
if (*lenp < 2)
130
return (0);
131
132
v = (p[0] << 8) | p[1];
133
*pp = p + 2;
134
*lenp = *lenp - 2;
135
136
return (v);
137
}
138
139
static uint32_t
140
get_uint32(const uint8_t **pp, size_t *lenp)
141
{
142
const uint8_t *p = *pp;
143
uint32_t v;
144
145
if (*lenp < 4)
146
return (0);
147
148
v = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
149
*pp = p + 4;
150
*lenp = *lenp - 4;
151
152
return (v);
153
}
154
155
static void
156
get_data(const uint8_t **pp, size_t *lenp, struct krb5_data *dp)
157
{
158
size_t sz = get_uint32(pp, lenp);
159
160
dp->kd_length = sz;
161
dp->kd_data = malloc(sz, M_GSSAPI, M_WAITOK);
162
163
if (*lenp < sz)
164
sz = *lenp;
165
bcopy(*pp, dp->kd_data, sz);
166
(*pp) += sz;
167
(*lenp) -= sz;
168
}
169
170
static void
171
delete_data(struct krb5_data *dp)
172
{
173
if (dp->kd_data) {
174
free(dp->kd_data, M_GSSAPI);
175
dp->kd_length = 0;
176
dp->kd_data = NULL;
177
}
178
}
179
180
static void
181
get_address(const uint8_t **pp, size_t *lenp, struct krb5_address *ka)
182
{
183
184
ka->ka_type = get_uint16(pp, lenp);
185
get_data(pp, lenp, &ka->ka_addr);
186
}
187
188
static void
189
delete_address(struct krb5_address *ka)
190
{
191
delete_data(&ka->ka_addr);
192
}
193
194
static void
195
get_keyblock(const uint8_t **pp, size_t *lenp, struct krb5_keyblock *kk)
196
{
197
198
kk->kk_type = get_uint16(pp, lenp);
199
get_data(pp, lenp, &kk->kk_key);
200
}
201
202
static void
203
delete_keyblock(struct krb5_keyblock *kk)
204
{
205
if (kk->kk_key.kd_data)
206
bzero(kk->kk_key.kd_data, kk->kk_key.kd_length);
207
delete_data(&kk->kk_key);
208
}
209
210
static void
211
copy_key(struct krb5_keyblock *from, struct krb5_keyblock **to)
212
{
213
214
if (from->kk_key.kd_length)
215
*to = from;
216
else
217
*to = NULL;
218
}
219
220
static void
221
copy_lucid_key(gss_buffer_desc *from, uint32_t type, struct krb5_keyblock *to)
222
{
223
224
to->kk_type = type;
225
to->kk_key.kd_length = from->length;
226
if (from->length > 0) {
227
to->kk_key.kd_data = malloc(from->length, M_GSSAPI, M_WAITOK);
228
memcpy(to->kk_key.kd_data, from->value, from->length);
229
}
230
}
231
232
/*
233
* Return non-zero if we are initiator.
234
*/
235
static __inline int
236
is_initiator(struct krb5_context *kc)
237
{
238
return (kc->kc_more_flags & LOCAL);
239
}
240
241
/*
242
* Return non-zero if we are acceptor.
243
*/
244
static __inline int
245
is_acceptor(struct krb5_context *kc)
246
{
247
return !(kc->kc_more_flags & LOCAL);
248
}
249
250
static void
251
get_initiator_subkey(struct krb5_context *kc, struct krb5_keyblock **kdp)
252
{
253
254
if (is_initiator(kc))
255
copy_key(&kc->kc_local_subkey, kdp);
256
else
257
copy_key(&kc->kc_remote_subkey, kdp);
258
if (!*kdp)
259
copy_key(&kc->kc_keyblock, kdp);
260
}
261
262
static void
263
get_acceptor_subkey(struct krb5_context *kc, struct krb5_keyblock **kdp)
264
{
265
266
if (is_initiator(kc))
267
copy_key(&kc->kc_remote_subkey, kdp);
268
else
269
copy_key(&kc->kc_local_subkey, kdp);
270
}
271
272
static OM_uint32
273
get_keys(struct krb5_context *kc)
274
{
275
struct krb5_keyblock *keydata;
276
struct krb5_encryption_class *ec;
277
struct krb5_key_state *key;
278
int etype;
279
280
keydata = NULL;
281
get_acceptor_subkey(kc, &keydata);
282
if (!keydata)
283
if ((kc->kc_more_flags & ACCEPTOR_SUBKEY) == 0)
284
get_initiator_subkey(kc, &keydata);
285
if (!keydata)
286
return (GSS_S_FAILURE);
287
288
/*
289
* GSS-API treats all DES etypes the same and all DES3 etypes
290
* the same.
291
*/
292
switch (keydata->kk_type) {
293
case ETYPE_DES_CBC_CRC:
294
case ETYPE_DES_CBC_MD4:
295
case ETYPE_DES_CBC_MD5:
296
etype = ETYPE_DES_CBC_CRC;
297
break;
298
299
case ETYPE_DES3_CBC_MD5:
300
case ETYPE_DES3_CBC_SHA1:
301
case ETYPE_OLD_DES3_CBC_SHA1:
302
etype = ETYPE_DES3_CBC_SHA1;
303
break;
304
305
default:
306
etype = keydata->kk_type;
307
}
308
309
ec = krb5_find_encryption_class(etype);
310
if (!ec)
311
return (GSS_S_FAILURE);
312
313
key = krb5_create_key(ec);
314
krb5_set_key(key, keydata->kk_key.kd_data);
315
kc->kc_tokenkey = key;
316
317
switch (etype) {
318
case ETYPE_DES_CBC_CRC:
319
case ETYPE_ARCFOUR_HMAC_MD5:
320
case ETYPE_ARCFOUR_HMAC_MD5_56: {
321
/*
322
* Single DES and ARCFOUR uses a 'derived' key (XOR
323
* with 0xf0) for encrypting wrap tokens. The original
324
* key is used for checksums and sequence numbers.
325
*/
326
struct krb5_key_state *ekey;
327
uint8_t *ekp, *kp;
328
int i;
329
330
ekey = krb5_create_key(ec);
331
ekp = ekey->ks_key;
332
kp = key->ks_key;
333
for (i = 0; i < ec->ec_keylen; i++)
334
ekp[i] = kp[i] ^ 0xf0;
335
krb5_set_key(ekey, ekp);
336
kc->kc_encryptkey = ekey;
337
refcount_acquire(&key->ks_refs);
338
kc->kc_checksumkey = key;
339
break;
340
}
341
342
case ETYPE_DES3_CBC_SHA1:
343
/*
344
* Triple DES uses a RFC 3961 style derived key with
345
* usage number KG_USAGE_SIGN for checksums. The
346
* original key is used for encryption and sequence
347
* numbers.
348
*/
349
kc->kc_checksumkey = krb5_get_checksum_key(key, KG_USAGE_SIGN);
350
refcount_acquire(&key->ks_refs);
351
kc->kc_encryptkey = key;
352
break;
353
354
default:
355
/*
356
* We need eight derived keys four for sending and
357
* four for receiving.
358
*/
359
if (is_initiator(kc)) {
360
/*
361
* We are initiator.
362
*/
363
kc->kc_send_seal_Ke = krb5_get_encryption_key(key,
364
KG_USAGE_INITIATOR_SEAL);
365
kc->kc_send_seal_Ki = krb5_get_integrity_key(key,
366
KG_USAGE_INITIATOR_SEAL);
367
kc->kc_send_seal_Kc = krb5_get_checksum_key(key,
368
KG_USAGE_INITIATOR_SEAL);
369
kc->kc_send_sign_Kc = krb5_get_checksum_key(key,
370
KG_USAGE_INITIATOR_SIGN);
371
372
kc->kc_recv_seal_Ke = krb5_get_encryption_key(key,
373
KG_USAGE_ACCEPTOR_SEAL);
374
kc->kc_recv_seal_Ki = krb5_get_integrity_key(key,
375
KG_USAGE_ACCEPTOR_SEAL);
376
kc->kc_recv_seal_Kc = krb5_get_checksum_key(key,
377
KG_USAGE_ACCEPTOR_SEAL);
378
kc->kc_recv_sign_Kc = krb5_get_checksum_key(key,
379
KG_USAGE_ACCEPTOR_SIGN);
380
} else {
381
/*
382
* We are acceptor.
383
*/
384
kc->kc_send_seal_Ke = krb5_get_encryption_key(key,
385
KG_USAGE_ACCEPTOR_SEAL);
386
kc->kc_send_seal_Ki = krb5_get_integrity_key(key,
387
KG_USAGE_ACCEPTOR_SEAL);
388
kc->kc_send_seal_Kc = krb5_get_checksum_key(key,
389
KG_USAGE_ACCEPTOR_SEAL);
390
kc->kc_send_sign_Kc = krb5_get_checksum_key(key,
391
KG_USAGE_ACCEPTOR_SIGN);
392
393
kc->kc_recv_seal_Ke = krb5_get_encryption_key(key,
394
KG_USAGE_INITIATOR_SEAL);
395
kc->kc_recv_seal_Ki = krb5_get_integrity_key(key,
396
KG_USAGE_INITIATOR_SEAL);
397
kc->kc_recv_seal_Kc = krb5_get_checksum_key(key,
398
KG_USAGE_INITIATOR_SEAL);
399
kc->kc_recv_sign_Kc = krb5_get_checksum_key(key,
400
KG_USAGE_INITIATOR_SIGN);
401
}
402
break;
403
}
404
405
return (GSS_S_COMPLETE);
406
}
407
408
static void
409
krb5_init(gss_ctx_id_t ctx)
410
{
411
struct krb5_context *kc = (struct krb5_context *)ctx;
412
413
mtx_init(&kc->kc_lock, "krb5 gss lock", NULL, MTX_DEF);
414
}
415
416
static OM_uint32
417
krb5_lucid_import(gss_ctx_id_t ctx,
418
enum sec_context_format format,
419
const gss_buffer_t context_token)
420
{
421
struct krb5_context *kc = (struct krb5_context *)ctx;
422
kgss_lucid_desc *lctx = (kgss_lucid_desc *)context_token;
423
OM_uint32 res;
424
425
kc->kc_more_flags = 0;
426
if (lctx->protocol == 0) {
427
kc->kc_cksumtype = lctx->rfc_sign;
428
kc->kc_keytype = lctx->rfc_seal;
429
copy_lucid_key(&lctx->ctx_key, lctx->ctx_type,
430
&kc->kc_keyblock);
431
} else if (lctx->protocol == 1) {
432
if (lctx->have_subkey != 0) {
433
if (lctx->initiate != 0)
434
copy_lucid_key(&lctx->subkey_key,
435
lctx->subkey_type,
436
&kc->kc_remote_subkey);
437
else
438
copy_lucid_key(&lctx->subkey_key,
439
lctx->subkey_type,
440
&kc->kc_local_subkey);
441
kc->kc_cksumtype = lctx->subkey_type;
442
kc->kc_keytype = lctx->subkey_type;
443
kc->kc_more_flags |= ACCEPTOR_SUBKEY;
444
} else {
445
if (lctx->initiate != 0)
446
copy_lucid_key(&lctx->ctx_key,
447
lctx->ctx_type,
448
&kc->kc_remote_subkey);
449
else
450
copy_lucid_key(&lctx->ctx_key,
451
lctx->ctx_type,
452
&kc->kc_local_subkey);
453
kc->kc_cksumtype = lctx->ctx_type;
454
kc->kc_keytype = lctx->ctx_type;
455
}
456
} else {
457
return (GSS_S_DEFECTIVE_TOKEN);
458
}
459
kc->kc_local_seqnumber = lctx->send_seq;
460
kc->kc_remote_seqnumber = lctx->recv_seq;
461
if (lctx->initiate != 0)
462
kc->kc_more_flags |= LOCAL;
463
kc->kc_lifetime = lctx->endtime;
464
kc->kc_msg_order.km_flags = 0;
465
466
res = get_keys(kc);
467
if (GSS_ERROR(res))
468
return (res);
469
470
/*
471
* We don't need these anymore.
472
*/
473
delete_keyblock(&kc->kc_keyblock);
474
delete_keyblock(&kc->kc_local_subkey);
475
delete_keyblock(&kc->kc_remote_subkey);
476
477
return (GSS_S_COMPLETE);
478
}
479
480
static OM_uint32
481
krb5_import(gss_ctx_id_t ctx,
482
enum sec_context_format format,
483
const gss_buffer_t context_token)
484
{
485
struct krb5_context *kc = (struct krb5_context *)ctx;
486
OM_uint32 res;
487
const uint8_t *p = (const uint8_t *) context_token->value;
488
size_t len = context_token->length;
489
uint32_t flags;
490
int i;
491
492
/* For MIT, just call krb5_lucid_import(). */
493
if (format == MIT_V1)
494
return (krb5_lucid_import(ctx, format, context_token));
495
496
/*
497
* We support heimdal 0.6 and heimdal 1.1
498
*/
499
if (format != KGSS_HEIMDAL_0_6 && format != KGSS_HEIMDAL_1_1)
500
return (GSS_S_DEFECTIVE_TOKEN);
501
502
#define SC_LOCAL_ADDRESS 1
503
#define SC_REMOTE_ADDRESS 2
504
#define SC_KEYBLOCK 4
505
#define SC_LOCAL_SUBKEY 8
506
#define SC_REMOTE_SUBKEY 16
507
508
/*
509
* Ensure that the token starts with krb5 oid.
510
*/
511
if (p[0] != 0x00 || p[1] != krb5_mech_oid.length
512
|| len < krb5_mech_oid.length + 2
513
|| bcmp(krb5_mech_oid.elements, p + 2,
514
krb5_mech_oid.length))
515
return (GSS_S_DEFECTIVE_TOKEN);
516
p += krb5_mech_oid.length + 2;
517
len -= krb5_mech_oid.length + 2;
518
519
flags = get_uint32(&p, &len);
520
kc->kc_ac_flags = get_uint32(&p, &len);
521
if (flags & SC_LOCAL_ADDRESS)
522
get_address(&p, &len, &kc->kc_local_address);
523
if (flags & SC_REMOTE_ADDRESS)
524
get_address(&p, &len, &kc->kc_remote_address);
525
kc->kc_local_port = get_uint16(&p, &len);
526
kc->kc_remote_port = get_uint16(&p, &len);
527
if (flags & SC_KEYBLOCK)
528
get_keyblock(&p, &len, &kc->kc_keyblock);
529
if (flags & SC_LOCAL_SUBKEY)
530
get_keyblock(&p, &len, &kc->kc_local_subkey);
531
if (flags & SC_REMOTE_SUBKEY)
532
get_keyblock(&p, &len, &kc->kc_remote_subkey);
533
kc->kc_local_seqnumber = get_uint32(&p, &len);
534
kc->kc_remote_seqnumber = get_uint32(&p, &len);
535
kc->kc_keytype = get_uint32(&p, &len);
536
kc->kc_cksumtype = get_uint32(&p, &len);
537
get_data(&p, &len, &kc->kc_source_name);
538
get_data(&p, &len, &kc->kc_target_name);
539
kc->kc_ctx_flags = get_uint32(&p, &len);
540
kc->kc_more_flags = get_uint32(&p, &len);
541
kc->kc_lifetime = get_uint32(&p, &len);
542
/*
543
* Heimdal 1.1 adds the message order stuff.
544
*/
545
if (format == KGSS_HEIMDAL_1_1) {
546
kc->kc_msg_order.km_flags = get_uint32(&p, &len);
547
kc->kc_msg_order.km_start = get_uint32(&p, &len);
548
kc->kc_msg_order.km_length = get_uint32(&p, &len);
549
kc->kc_msg_order.km_jitter_window = get_uint32(&p, &len);
550
kc->kc_msg_order.km_first_seq = get_uint32(&p, &len);
551
kc->kc_msg_order.km_elem =
552
malloc(kc->kc_msg_order.km_jitter_window * sizeof(uint32_t),
553
M_GSSAPI, M_WAITOK);
554
for (i = 0; i < kc->kc_msg_order.km_jitter_window; i++)
555
kc->kc_msg_order.km_elem[i] = get_uint32(&p, &len);
556
} else {
557
kc->kc_msg_order.km_flags = 0;
558
}
559
560
res = get_keys(kc);
561
if (GSS_ERROR(res))
562
return (res);
563
564
/*
565
* We don't need these anymore.
566
*/
567
delete_keyblock(&kc->kc_keyblock);
568
delete_keyblock(&kc->kc_local_subkey);
569
delete_keyblock(&kc->kc_remote_subkey);
570
571
return (GSS_S_COMPLETE);
572
}
573
574
static void
575
krb5_delete(gss_ctx_id_t ctx, gss_buffer_t output_token)
576
{
577
struct krb5_context *kc = (struct krb5_context *)ctx;
578
579
delete_address(&kc->kc_local_address);
580
delete_address(&kc->kc_remote_address);
581
delete_keyblock(&kc->kc_keyblock);
582
delete_keyblock(&kc->kc_local_subkey);
583
delete_keyblock(&kc->kc_remote_subkey);
584
delete_data(&kc->kc_source_name);
585
delete_data(&kc->kc_target_name);
586
if (kc->kc_msg_order.km_elem)
587
free(kc->kc_msg_order.km_elem, M_GSSAPI);
588
if (output_token) {
589
output_token->length = 0;
590
output_token->value = NULL;
591
}
592
if (kc->kc_tokenkey) {
593
krb5_free_key(kc->kc_tokenkey);
594
if (kc->kc_encryptkey) {
595
krb5_free_key(kc->kc_encryptkey);
596
krb5_free_key(kc->kc_checksumkey);
597
} else {
598
krb5_free_key(kc->kc_send_seal_Ke);
599
krb5_free_key(kc->kc_send_seal_Ki);
600
krb5_free_key(kc->kc_send_seal_Kc);
601
krb5_free_key(kc->kc_send_sign_Kc);
602
krb5_free_key(kc->kc_recv_seal_Ke);
603
krb5_free_key(kc->kc_recv_seal_Ki);
604
krb5_free_key(kc->kc_recv_seal_Kc);
605
krb5_free_key(kc->kc_recv_sign_Kc);
606
}
607
}
608
mtx_destroy(&kc->kc_lock);
609
}
610
611
static gss_OID
612
krb5_mech_type(gss_ctx_id_t ctx)
613
{
614
615
return (&krb5_mech_oid);
616
}
617
618
/*
619
* Make a token with the given type and length (the length includes
620
* the TOK_ID), initialising the token header appropriately. Return a
621
* pointer to the TOK_ID of the token. A new mbuf is allocated with
622
* the framing header plus hlen bytes of space.
623
*
624
* Format is as follows:
625
*
626
* 0x60 [APPLICATION 0] SEQUENCE
627
* DER encoded length length of oid + type + inner token length
628
* 0x06 NN <oid data> OID of mechanism type
629
* TT TT TOK_ID
630
* <inner token> data for inner token
631
*
632
* 1: der encoded length
633
*/
634
static void *
635
krb5_make_token(char tok_id[2], size_t hlen, size_t len, struct mbuf **mp)
636
{
637
size_t inside_len, len_len, tlen;
638
gss_OID oid = &krb5_mech_oid;
639
struct mbuf *m;
640
uint8_t *p;
641
642
inside_len = 2 + oid->length + len;
643
if (inside_len < 128)
644
len_len = 1;
645
else if (inside_len < 0x100)
646
len_len = 2;
647
else if (inside_len < 0x10000)
648
len_len = 3;
649
else if (inside_len < 0x1000000)
650
len_len = 4;
651
else
652
len_len = 5;
653
654
tlen = 1 + len_len + 2 + oid->length + hlen;
655
KASSERT(tlen <= MLEN, ("token head too large"));
656
MGET(m, M_WAITOK, MT_DATA);
657
M_ALIGN(m, tlen);
658
m->m_len = tlen;
659
660
p = (uint8_t *) m->m_data;
661
*p++ = 0x60;
662
switch (len_len) {
663
case 1:
664
*p++ = inside_len;
665
break;
666
case 2:
667
*p++ = 0x81;
668
*p++ = inside_len;
669
break;
670
case 3:
671
*p++ = 0x82;
672
*p++ = inside_len >> 8;
673
*p++ = inside_len;
674
break;
675
case 4:
676
*p++ = 0x83;
677
*p++ = inside_len >> 16;
678
*p++ = inside_len >> 8;
679
*p++ = inside_len;
680
break;
681
case 5:
682
*p++ = 0x84;
683
*p++ = inside_len >> 24;
684
*p++ = inside_len >> 16;
685
*p++ = inside_len >> 8;
686
*p++ = inside_len;
687
break;
688
}
689
690
*p++ = 0x06;
691
*p++ = oid->length;
692
bcopy(oid->elements, p, oid->length);
693
p += oid->length;
694
695
p[0] = tok_id[0];
696
p[1] = tok_id[1];
697
698
*mp = m;
699
700
return (p);
701
}
702
703
/*
704
* Verify a token, checking the inner token length and mechanism oid.
705
* pointer to the first byte of the TOK_ID. The length of the
706
* encapsulated data is checked to be at least len bytes; the actual
707
* length of the encapsulated data (including TOK_ID) is returned in
708
* *encap_len.
709
*
710
* If can_pullup is TRUE and the token header is fragmented, we will
711
* rearrange it.
712
*
713
* Format is as follows:
714
*
715
* 0x60 [APPLICATION 0] SEQUENCE
716
* DER encoded length length of oid + type + inner token length
717
* 0x06 NN <oid data> OID of mechanism type
718
* TT TT TOK_ID
719
* <inner token> data for inner token
720
*
721
* 1: der encoded length
722
*/
723
static void *
724
krb5_verify_token(char tok_id[2], size_t len, struct mbuf **mp,
725
size_t *encap_len, bool_t can_pullup)
726
{
727
struct mbuf *m;
728
size_t tlen, hlen, len_len, inside_len;
729
gss_OID oid = &krb5_mech_oid;
730
uint8_t *p;
731
732
m = *mp;
733
tlen = m_length(m, NULL);
734
if (tlen < 2)
735
return (NULL);
736
737
/*
738
* Ensure that at least the framing part of the token is
739
* contigous.
740
*/
741
if (m->m_len < 2) {
742
if (can_pullup)
743
*mp = m = m_pullup(m, 2);
744
else
745
return (NULL);
746
}
747
748
p = m->m_data;
749
750
if (*p++ != 0x60)
751
return (NULL);
752
753
if (*p < 0x80) {
754
inside_len = *p++;
755
len_len = 1;
756
} else {
757
/*
758
* Ensure there is enough space for the DER encoded length.
759
*/
760
len_len = (*p & 0x7f) + 1;
761
if (tlen < len_len + 1)
762
return (NULL);
763
if (m->m_len < len_len + 1) {
764
if (can_pullup)
765
*mp = m = m_pullup(m, len_len + 1);
766
else
767
return (NULL);
768
p = m->m_data + 1;
769
}
770
771
switch (*p++) {
772
case 0x81:
773
inside_len = *p++;
774
break;
775
776
case 0x82:
777
inside_len = (p[0] << 8) | p[1];
778
p += 2;
779
break;
780
781
case 0x83:
782
inside_len = (p[0] << 16) | (p[1] << 8) | p[2];
783
p += 3;
784
break;
785
786
case 0x84:
787
inside_len = (p[0] << 24) | (p[1] << 16)
788
| (p[2] << 8) | p[3];
789
p += 4;
790
break;
791
792
default:
793
return (NULL);
794
}
795
}
796
797
if (tlen != inside_len + len_len + 1)
798
return (NULL);
799
if (inside_len < 2 + oid->length + len)
800
return (NULL);
801
802
/*
803
* Now that we know the value of len_len, we can pullup the
804
* whole header. The header is 1 + len_len + 2 + oid->length +
805
* len bytes.
806
*/
807
hlen = 1 + len_len + 2 + oid->length + len;
808
if (m->m_len < hlen) {
809
if (can_pullup)
810
*mp = m = m_pullup(m, hlen);
811
else
812
return (NULL);
813
p = m->m_data + 1 + len_len;
814
}
815
816
if (*p++ != 0x06)
817
return (NULL);
818
if (*p++ != oid->length)
819
return (NULL);
820
if (bcmp(oid->elements, p, oid->length))
821
return (NULL);
822
p += oid->length;
823
824
if (p[0] != tok_id[0])
825
return (NULL);
826
827
if (p[1] != tok_id[1])
828
return (NULL);
829
830
*encap_len = inside_len - 2 - oid->length;
831
832
return (p);
833
}
834
835
static void
836
krb5_insert_seq(struct krb5_msg_order *mo, uint32_t seq, int index)
837
{
838
int i;
839
840
if (mo->km_length < mo->km_jitter_window)
841
mo->km_length++;
842
843
for (i = mo->km_length - 1; i > index; i--)
844
mo->km_elem[i] = mo->km_elem[i - 1];
845
mo->km_elem[index] = seq;
846
}
847
848
/*
849
* Check sequence numbers according to RFC 2743 section 1.2.3.
850
*/
851
static OM_uint32
852
krb5_sequence_check(struct krb5_context *kc, uint32_t seq)
853
{
854
OM_uint32 res = GSS_S_FAILURE;
855
struct krb5_msg_order *mo = &kc->kc_msg_order;
856
int check_sequence = mo->km_flags & GSS_C_SEQUENCE_FLAG;
857
int check_replay = mo->km_flags & GSS_C_REPLAY_FLAG;
858
int i;
859
860
mtx_lock(&kc->kc_lock);
861
862
/*
863
* Message is in-sequence with no gap.
864
*/
865
if (mo->km_length == 0 || seq == mo->km_elem[0] + 1) {
866
/*
867
* This message is received in-sequence with no gaps.
868
*/
869
krb5_insert_seq(mo, seq, 0);
870
res = GSS_S_COMPLETE;
871
goto out;
872
}
873
874
if (seq > mo->km_elem[0]) {
875
/*
876
* This message is received in-sequence with a gap.
877
*/
878
krb5_insert_seq(mo, seq, 0);
879
if (check_sequence)
880
res = GSS_S_GAP_TOKEN;
881
else
882
res = GSS_S_COMPLETE;
883
goto out;
884
}
885
886
if (seq < mo->km_elem[mo->km_length - 1]) {
887
if (check_replay && !check_sequence)
888
res = GSS_S_OLD_TOKEN;
889
else
890
res = GSS_S_UNSEQ_TOKEN;
891
goto out;
892
}
893
894
for (i = 0; i < mo->km_length; i++) {
895
if (mo->km_elem[i] == seq) {
896
res = GSS_S_DUPLICATE_TOKEN;
897
goto out;
898
}
899
if (mo->km_elem[i] < seq) {
900
/*
901
* We need to insert this seq here,
902
*/
903
krb5_insert_seq(mo, seq, i);
904
if (check_replay && !check_sequence)
905
res = GSS_S_COMPLETE;
906
else
907
res = GSS_S_UNSEQ_TOKEN;
908
goto out;
909
}
910
}
911
912
out:
913
mtx_unlock(&kc->kc_lock);
914
915
return (res);
916
}
917
918
static uint8_t sgn_alg_des_md5[] = { 0x00, 0x00 };
919
static uint8_t seal_alg_des[] = { 0x00, 0x00 };
920
static uint8_t sgn_alg_des3_sha1[] = { 0x04, 0x00 };
921
static uint8_t seal_alg_des3[] = { 0x02, 0x00 };
922
static uint8_t seal_alg_rc4[] = { 0x10, 0x00 };
923
static uint8_t sgn_alg_hmac_md5[] = { 0x11, 0x00 };
924
925
/*
926
* Return the size of the inner token given the use of the key's
927
* encryption class. For wrap tokens, the length of the padded
928
* plaintext will be added to this.
929
*/
930
static size_t
931
token_length(struct krb5_key_state *key)
932
{
933
934
return (16 + key->ks_class->ec_checksumlen);
935
}
936
937
static OM_uint32
938
krb5_get_mic_old(struct krb5_context *kc, struct mbuf *m,
939
struct mbuf **micp, uint8_t sgn_alg[2])
940
{
941
struct mbuf *mlast, *mic, *tm;
942
uint8_t *p, dir;
943
size_t tlen, mlen, cklen;
944
uint32_t seq;
945
char buf[8];
946
947
mlen = m_length(m, &mlast);
948
949
tlen = token_length(kc->kc_tokenkey);
950
p = krb5_make_token("\x01\x01", tlen, tlen, &mic);
951
p += 2; /* TOK_ID */
952
*p++ = sgn_alg[0]; /* SGN_ALG */
953
*p++ = sgn_alg[1];
954
955
*p++ = 0xff; /* filler */
956
*p++ = 0xff;
957
*p++ = 0xff;
958
*p++ = 0xff;
959
960
/*
961
* SGN_CKSUM:
962
*
963
* Calculate the keyed checksum of the token header plus the
964
* message.
965
*/
966
cklen = kc->kc_checksumkey->ks_class->ec_checksumlen;
967
968
mic->m_len = p - (uint8_t *) mic->m_data;
969
mic->m_next = m;
970
MGET(tm, M_WAITOK, MT_DATA);
971
tm->m_len = cklen;
972
mlast->m_next = tm;
973
974
krb5_checksum(kc->kc_checksumkey, 15, mic, mic->m_len - 8,
975
8 + mlen, cklen);
976
bcopy(tm->m_data, p + 8, cklen);
977
mic->m_next = NULL;
978
mlast->m_next = NULL;
979
m_free(tm);
980
981
/*
982
* SND_SEQ:
983
*
984
* Take the four bytes of the sequence number least
985
* significant first followed by four bytes of direction
986
* marker (zero for initiator and 0xff for acceptor). Encrypt
987
* that data using the SGN_CKSUM as IV. Note: ARC4 wants the
988
* sequence number big-endian.
989
*/
990
seq = atomic_fetchadd_32(&kc->kc_local_seqnumber, 1);
991
if (sgn_alg[0] == 0x11) {
992
p[0] = (seq >> 24);
993
p[1] = (seq >> 16);
994
p[2] = (seq >> 8);
995
p[3] = (seq >> 0);
996
} else {
997
p[0] = (seq >> 0);
998
p[1] = (seq >> 8);
999
p[2] = (seq >> 16);
1000
p[3] = (seq >> 24);
1001
}
1002
if (is_initiator(kc)) {
1003
dir = 0;
1004
} else {
1005
dir = 0xff;
1006
}
1007
p[4] = dir;
1008
p[5] = dir;
1009
p[6] = dir;
1010
p[7] = dir;
1011
bcopy(p + 8, buf, 8);
1012
1013
/*
1014
* Set the mic buffer to its final size so that the encrypt
1015
* can see the SND_SEQ part.
1016
*/
1017
mic->m_len += 8 + cklen;
1018
krb5_encrypt(kc->kc_tokenkey, mic, mic->m_len - cklen - 8, 8, buf, 8);
1019
1020
*micp = mic;
1021
return (GSS_S_COMPLETE);
1022
}
1023
1024
static OM_uint32
1025
krb5_get_mic_new(struct krb5_context *kc, struct mbuf *m,
1026
struct mbuf **micp)
1027
{
1028
struct krb5_key_state *key = kc->kc_send_sign_Kc;
1029
struct mbuf *mlast, *mic;
1030
uint8_t *p;
1031
int flags;
1032
size_t mlen, cklen;
1033
uint32_t seq;
1034
1035
mlen = m_length(m, &mlast);
1036
cklen = key->ks_class->ec_checksumlen;
1037
1038
KASSERT(16 + cklen <= MLEN, ("checksum too large for an mbuf"));
1039
MGET(mic, M_WAITOK, MT_DATA);
1040
M_ALIGN(mic, 16 + cklen);
1041
mic->m_len = 16 + cklen;
1042
p = mic->m_data;
1043
1044
/* TOK_ID */
1045
p[0] = 0x04;
1046
p[1] = 0x04;
1047
1048
/* Flags */
1049
flags = 0;
1050
if (is_acceptor(kc))
1051
flags |= GSS_TOKEN_SENT_BY_ACCEPTOR;
1052
if (kc->kc_more_flags & ACCEPTOR_SUBKEY)
1053
flags |= GSS_TOKEN_ACCEPTOR_SUBKEY;
1054
p[2] = flags;
1055
1056
/* Filler */
1057
p[3] = 0xff;
1058
p[4] = 0xff;
1059
p[5] = 0xff;
1060
p[6] = 0xff;
1061
p[7] = 0xff;
1062
1063
/* SND_SEQ */
1064
p[8] = 0;
1065
p[9] = 0;
1066
p[10] = 0;
1067
p[11] = 0;
1068
seq = atomic_fetchadd_32(&kc->kc_local_seqnumber, 1);
1069
p[12] = (seq >> 24);
1070
p[13] = (seq >> 16);
1071
p[14] = (seq >> 8);
1072
p[15] = (seq >> 0);
1073
1074
/*
1075
* SGN_CKSUM:
1076
*
1077
* Calculate the keyed checksum of the message plus the first
1078
* 16 bytes of the token header.
1079
*/
1080
mlast->m_next = mic;
1081
krb5_checksum(key, 0, m, 0, mlen + 16, cklen);
1082
mlast->m_next = NULL;
1083
1084
*micp = mic;
1085
return (GSS_S_COMPLETE);
1086
}
1087
1088
static OM_uint32
1089
krb5_get_mic(gss_ctx_id_t ctx, OM_uint32 *minor_status,
1090
gss_qop_t qop_req, struct mbuf *m, struct mbuf **micp)
1091
{
1092
struct krb5_context *kc = (struct krb5_context *)ctx;
1093
1094
*minor_status = 0;
1095
1096
if (qop_req != GSS_C_QOP_DEFAULT)
1097
return (GSS_S_BAD_QOP);
1098
1099
if (time_uptime > kc->kc_lifetime)
1100
return (GSS_S_CONTEXT_EXPIRED);
1101
1102
switch (kc->kc_tokenkey->ks_class->ec_type) {
1103
case ETYPE_DES_CBC_CRC:
1104
return (krb5_get_mic_old(kc, m, micp, sgn_alg_des_md5));
1105
1106
case ETYPE_DES3_CBC_SHA1:
1107
return (krb5_get_mic_old(kc, m, micp, sgn_alg_des3_sha1));
1108
1109
case ETYPE_ARCFOUR_HMAC_MD5:
1110
case ETYPE_ARCFOUR_HMAC_MD5_56:
1111
return (krb5_get_mic_old(kc, m, micp, sgn_alg_hmac_md5));
1112
1113
default:
1114
return (krb5_get_mic_new(kc, m, micp));
1115
}
1116
1117
return (GSS_S_FAILURE);
1118
}
1119
1120
static OM_uint32
1121
krb5_verify_mic_old(struct krb5_context *kc, struct mbuf *m, struct mbuf *mic,
1122
uint8_t sgn_alg[2])
1123
{
1124
struct mbuf *mlast, *tm;
1125
uint8_t *p, *tp, dir;
1126
size_t mlen, tlen, elen;
1127
size_t cklen;
1128
uint32_t seq;
1129
1130
mlen = m_length(m, &mlast);
1131
1132
tlen = token_length(kc->kc_tokenkey);
1133
p = krb5_verify_token("\x01\x01", tlen, &mic, &elen, FALSE);
1134
if (!p)
1135
return (GSS_S_DEFECTIVE_TOKEN);
1136
#if 0
1137
/*
1138
* Disable this check - heimdal-1.1 generates DES3 MIC tokens
1139
* that are 2 bytes too big.
1140
*/
1141
if (elen != tlen)
1142
return (GSS_S_DEFECTIVE_TOKEN);
1143
#endif
1144
/* TOK_ID */
1145
p += 2;
1146
1147
/* SGN_ALG */
1148
if (p[0] != sgn_alg[0] || p[1] != sgn_alg[1])
1149
return (GSS_S_DEFECTIVE_TOKEN);
1150
p += 2;
1151
1152
if (p[0] != 0xff || p[1] != 0xff || p[2] != 0xff || p[3] != 0xff)
1153
return (GSS_S_DEFECTIVE_TOKEN);
1154
p += 4;
1155
1156
/*
1157
* SGN_CKSUM:
1158
*
1159
* Calculate the keyed checksum of the token header plus the
1160
* message.
1161
*/
1162
cklen = kc->kc_checksumkey->ks_class->ec_checksumlen;
1163
mic->m_len = p - (uint8_t *) mic->m_data;
1164
mic->m_next = m;
1165
MGET(tm, M_WAITOK, MT_DATA);
1166
tm->m_len = cklen;
1167
mlast->m_next = tm;
1168
1169
krb5_checksum(kc->kc_checksumkey, 15, mic, mic->m_len - 8,
1170
8 + mlen, cklen);
1171
mic->m_next = NULL;
1172
mlast->m_next = NULL;
1173
if (bcmp(tm->m_data, p + 8, cklen)) {
1174
m_free(tm);
1175
return (GSS_S_BAD_SIG);
1176
}
1177
1178
/*
1179
* SND_SEQ:
1180
*
1181
* Take the four bytes of the sequence number least
1182
* significant first followed by four bytes of direction
1183
* marker (zero for initiator and 0xff for acceptor). Encrypt
1184
* that data using the SGN_CKSUM as IV. Note: ARC4 wants the
1185
* sequence number big-endian.
1186
*/
1187
bcopy(p, tm->m_data, 8);
1188
tm->m_len = 8;
1189
krb5_decrypt(kc->kc_tokenkey, tm, 0, 8, p + 8, 8);
1190
1191
tp = tm->m_data;
1192
if (sgn_alg[0] == 0x11) {
1193
seq = tp[3] | (tp[2] << 8) | (tp[1] << 16) | (tp[0] << 24);
1194
} else {
1195
seq = tp[0] | (tp[1] << 8) | (tp[2] << 16) | (tp[3] << 24);
1196
}
1197
1198
if (is_initiator(kc)) {
1199
dir = 0xff;
1200
} else {
1201
dir = 0;
1202
}
1203
if (tp[4] != dir || tp[5] != dir || tp[6] != dir || tp[7] != dir) {
1204
m_free(tm);
1205
return (GSS_S_DEFECTIVE_TOKEN);
1206
}
1207
m_free(tm);
1208
1209
if (kc->kc_msg_order.km_flags &
1210
(GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG)) {
1211
return (krb5_sequence_check(kc, seq));
1212
}
1213
1214
return (GSS_S_COMPLETE);
1215
}
1216
1217
static OM_uint32
1218
krb5_verify_mic_new(struct krb5_context *kc, struct mbuf *m, struct mbuf *mic)
1219
{
1220
OM_uint32 res;
1221
struct krb5_key_state *key = kc->kc_recv_sign_Kc;
1222
struct mbuf *mlast;
1223
uint8_t *p;
1224
int flags;
1225
size_t mlen, cklen;
1226
char buf[32];
1227
1228
mlen = m_length(m, &mlast);
1229
cklen = key->ks_class->ec_checksumlen;
1230
1231
KASSERT(mic->m_next == NULL, ("MIC should be contiguous"));
1232
if (mic->m_len != 16 + cklen)
1233
return (GSS_S_DEFECTIVE_TOKEN);
1234
p = mic->m_data;
1235
1236
/* TOK_ID */
1237
if (p[0] != 0x04)
1238
return (GSS_S_DEFECTIVE_TOKEN);
1239
if (p[1] != 0x04)
1240
return (GSS_S_DEFECTIVE_TOKEN);
1241
1242
/* Flags */
1243
flags = 0;
1244
if (is_initiator(kc))
1245
flags |= GSS_TOKEN_SENT_BY_ACCEPTOR;
1246
if (kc->kc_more_flags & ACCEPTOR_SUBKEY)
1247
flags |= GSS_TOKEN_ACCEPTOR_SUBKEY;
1248
if (p[2] != flags)
1249
return (GSS_S_DEFECTIVE_TOKEN);
1250
1251
/* Filler */
1252
if (p[3] != 0xff)
1253
return (GSS_S_DEFECTIVE_TOKEN);
1254
if (p[4] != 0xff)
1255
return (GSS_S_DEFECTIVE_TOKEN);
1256
if (p[5] != 0xff)
1257
return (GSS_S_DEFECTIVE_TOKEN);
1258
if (p[6] != 0xff)
1259
return (GSS_S_DEFECTIVE_TOKEN);
1260
if (p[7] != 0xff)
1261
return (GSS_S_DEFECTIVE_TOKEN);
1262
1263
/* SND_SEQ */
1264
if (kc->kc_msg_order.km_flags &
1265
(GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG)) {
1266
uint32_t seq;
1267
if (p[8] || p[9] || p[10] || p[11]) {
1268
res = GSS_S_UNSEQ_TOKEN;
1269
} else {
1270
seq = (p[12] << 24) | (p[13] << 16)
1271
| (p[14] << 8) | p[15];
1272
res = krb5_sequence_check(kc, seq);
1273
}
1274
if (GSS_ERROR(res))
1275
return (res);
1276
} else {
1277
res = GSS_S_COMPLETE;
1278
}
1279
1280
/*
1281
* SGN_CKSUM:
1282
*
1283
* Calculate the keyed checksum of the message plus the first
1284
* 16 bytes of the token header.
1285
*/
1286
m_copydata(mic, 16, cklen, buf);
1287
mlast->m_next = mic;
1288
krb5_checksum(key, 0, m, 0, mlen + 16, cklen);
1289
mlast->m_next = NULL;
1290
if (bcmp(buf, p + 16, cklen)) {
1291
return (GSS_S_BAD_SIG);
1292
}
1293
1294
return (GSS_S_COMPLETE);
1295
}
1296
1297
static OM_uint32
1298
krb5_verify_mic(gss_ctx_id_t ctx, OM_uint32 *minor_status,
1299
struct mbuf *m, struct mbuf *mic, gss_qop_t *qop_state)
1300
{
1301
struct krb5_context *kc = (struct krb5_context *)ctx;
1302
1303
*minor_status = 0;
1304
if (qop_state)
1305
*qop_state = GSS_C_QOP_DEFAULT;
1306
1307
if (time_uptime > kc->kc_lifetime)
1308
return (GSS_S_CONTEXT_EXPIRED);
1309
1310
switch (kc->kc_tokenkey->ks_class->ec_type) {
1311
case ETYPE_DES_CBC_CRC:
1312
return (krb5_verify_mic_old(kc, m, mic, sgn_alg_des_md5));
1313
1314
case ETYPE_ARCFOUR_HMAC_MD5:
1315
case ETYPE_ARCFOUR_HMAC_MD5_56:
1316
return (krb5_verify_mic_old(kc, m, mic, sgn_alg_hmac_md5));
1317
1318
case ETYPE_DES3_CBC_SHA1:
1319
return (krb5_verify_mic_old(kc, m, mic, sgn_alg_des3_sha1));
1320
1321
default:
1322
return (krb5_verify_mic_new(kc, m, mic));
1323
}
1324
1325
return (GSS_S_FAILURE);
1326
}
1327
1328
static OM_uint32
1329
krb5_wrap_old(struct krb5_context *kc, int conf_req_flag,
1330
struct mbuf **mp, int *conf_state,
1331
uint8_t sgn_alg[2], uint8_t seal_alg[2])
1332
{
1333
struct mbuf *m, *mlast, *tm, *cm, *pm;
1334
size_t mlen, tlen, padlen, datalen;
1335
uint8_t *p, dir;
1336
size_t cklen;
1337
uint8_t buf[8];
1338
uint32_t seq;
1339
1340
/*
1341
* How many trailing pad bytes do we need?
1342
*/
1343
m = *mp;
1344
mlen = m_length(m, &mlast);
1345
tlen = kc->kc_tokenkey->ks_class->ec_msgblocklen;
1346
padlen = tlen - (mlen % tlen);
1347
1348
/*
1349
* The data part of the token has eight bytes of random
1350
* confounder prepended and followed by up to eight bytes of
1351
* padding bytes each of which is set to the number of padding
1352
* bytes.
1353
*/
1354
datalen = mlen + 8 + padlen;
1355
tlen = token_length(kc->kc_tokenkey);
1356
1357
p = krb5_make_token("\x02\x01", tlen, datalen + tlen, &tm);
1358
p += 2; /* TOK_ID */
1359
*p++ = sgn_alg[0]; /* SGN_ALG */
1360
*p++ = sgn_alg[1];
1361
if (conf_req_flag) {
1362
*p++ = seal_alg[0]; /* SEAL_ALG */
1363
*p++ = seal_alg[1];
1364
} else {
1365
*p++ = 0xff; /* SEAL_ALG = none */
1366
*p++ = 0xff;
1367
}
1368
1369
*p++ = 0xff; /* filler */
1370
*p++ = 0xff;
1371
1372
/*
1373
* Copy the padded message data.
1374
*/
1375
if (M_LEADINGSPACE(m) >= 8) {
1376
m->m_data -= 8;
1377
m->m_len += 8;
1378
} else {
1379
MGET(cm, M_WAITOK, MT_DATA);
1380
cm->m_len = 8;
1381
cm->m_next = m;
1382
m = cm;
1383
}
1384
arc4rand(m->m_data, 8, 0);
1385
if (M_TRAILINGSPACE(mlast) >= padlen) {
1386
memset(mlast->m_data + mlast->m_len, padlen, padlen);
1387
mlast->m_len += padlen;
1388
} else {
1389
MGET(pm, M_WAITOK, MT_DATA);
1390
memset(pm->m_data, padlen, padlen);
1391
pm->m_len = padlen;
1392
mlast->m_next = pm;
1393
mlast = pm;
1394
}
1395
tm->m_next = m;
1396
1397
/*
1398
* SGN_CKSUM:
1399
*
1400
* Calculate the keyed checksum of the token header plus the
1401
* padded message. Fiddle with tm->m_len so that we only
1402
* checksum the 8 bytes of head that we care about.
1403
*/
1404
cklen = kc->kc_checksumkey->ks_class->ec_checksumlen;
1405
tlen = tm->m_len;
1406
tm->m_len = p - (uint8_t *) tm->m_data;
1407
MGET(cm, M_WAITOK, MT_DATA);
1408
cm->m_len = cklen;
1409
mlast->m_next = cm;
1410
krb5_checksum(kc->kc_checksumkey, 13, tm, tm->m_len - 8,
1411
datalen + 8, cklen);
1412
tm->m_len = tlen;
1413
mlast->m_next = NULL;
1414
bcopy(cm->m_data, p + 8, cklen);
1415
m_free(cm);
1416
1417
/*
1418
* SND_SEQ:
1419
*
1420
* Take the four bytes of the sequence number least
1421
* significant first (most significant first for ARCFOUR)
1422
* followed by four bytes of direction marker (zero for
1423
* initiator and 0xff for acceptor). Encrypt that data using
1424
* the SGN_CKSUM as IV.
1425
*/
1426
seq = atomic_fetchadd_32(&kc->kc_local_seqnumber, 1);
1427
if (sgn_alg[0] == 0x11) {
1428
p[0] = (seq >> 24);
1429
p[1] = (seq >> 16);
1430
p[2] = (seq >> 8);
1431
p[3] = (seq >> 0);
1432
} else {
1433
p[0] = (seq >> 0);
1434
p[1] = (seq >> 8);
1435
p[2] = (seq >> 16);
1436
p[3] = (seq >> 24);
1437
}
1438
if (is_initiator(kc)) {
1439
dir = 0;
1440
} else {
1441
dir = 0xff;
1442
}
1443
p[4] = dir;
1444
p[5] = dir;
1445
p[6] = dir;
1446
p[7] = dir;
1447
krb5_encrypt(kc->kc_tokenkey, tm, p - (uint8_t *) tm->m_data,
1448
8, p + 8, 8);
1449
1450
if (conf_req_flag) {
1451
/*
1452
* Encrypt the padded message with an IV of zero for
1453
* DES and DES3, or an IV of the sequence number in
1454
* big-endian format for ARCFOUR.
1455
*/
1456
if (seal_alg[0] == 0x10) {
1457
buf[0] = (seq >> 24);
1458
buf[1] = (seq >> 16);
1459
buf[2] = (seq >> 8);
1460
buf[3] = (seq >> 0);
1461
krb5_encrypt(kc->kc_encryptkey, m, 0, datalen,
1462
buf, 4);
1463
} else {
1464
krb5_encrypt(kc->kc_encryptkey, m, 0, datalen,
1465
NULL, 0);
1466
}
1467
}
1468
1469
if (conf_state)
1470
*conf_state = conf_req_flag;
1471
1472
*mp = tm;
1473
return (GSS_S_COMPLETE);
1474
}
1475
1476
static OM_uint32
1477
krb5_wrap_new(struct krb5_context *kc, int conf_req_flag,
1478
struct mbuf **mp, int *conf_state)
1479
{
1480
struct krb5_key_state *Ke = kc->kc_send_seal_Ke;
1481
struct krb5_key_state *Ki = kc->kc_send_seal_Ki;
1482
struct krb5_key_state *Kc = kc->kc_send_seal_Kc;
1483
const struct krb5_encryption_class *ec = Ke->ks_class;
1484
struct mbuf *m, *mlast, *tm;
1485
uint8_t *p;
1486
int flags, EC;
1487
size_t mlen, blen, mblen, cklen, ctlen;
1488
uint32_t seq;
1489
static char zpad[32];
1490
1491
m = *mp;
1492
mlen = m_length(m, &mlast);
1493
1494
blen = ec->ec_blocklen;
1495
mblen = ec->ec_msgblocklen;
1496
cklen = ec->ec_checksumlen;
1497
1498
if (conf_req_flag) {
1499
/*
1500
* For sealed messages, we need space for 16 bytes of
1501
* header, blen confounder, plaintext, padding, copy
1502
* of header and checksum.
1503
*
1504
* We pad to mblen (which may be different from
1505
* blen). If the encryption class is using CTS, mblen
1506
* will be one (i.e. no padding required).
1507
*/
1508
if (mblen > 1)
1509
EC = mlen % mblen;
1510
else
1511
EC = 0;
1512
ctlen = blen + mlen + EC + 16;
1513
1514
/*
1515
* Put initial header and confounder before the
1516
* message.
1517
*/
1518
M_PREPEND(m, 16 + blen, M_WAITOK);
1519
1520
/*
1521
* Append padding + copy of header and checksum. Try
1522
* to fit this into the end of the original message,
1523
* otherwise allocate a trailer.
1524
*/
1525
if (M_TRAILINGSPACE(mlast) >= EC + 16 + cklen) {
1526
tm = NULL;
1527
mlast->m_len += EC + 16 + cklen;
1528
} else {
1529
MGET(tm, M_WAITOK, MT_DATA);
1530
tm->m_len = EC + 16 + cklen;
1531
mlast->m_next = tm;
1532
}
1533
} else {
1534
/*
1535
* For unsealed messages, we need 16 bytes of header
1536
* plus space for the plaintext and a checksum. EC is
1537
* set to the checksum size. We leave space in tm for
1538
* a copy of the header - this will be trimmed later.
1539
*/
1540
M_PREPEND(m, 16, M_WAITOK);
1541
1542
MGET(tm, M_WAITOK, MT_DATA);
1543
tm->m_len = cklen + 16;
1544
mlast->m_next = tm;
1545
ctlen = 0;
1546
EC = cklen;
1547
}
1548
1549
p = m->m_data;
1550
1551
/* TOK_ID */
1552
p[0] = 0x05;
1553
p[1] = 0x04;
1554
1555
/* Flags */
1556
flags = 0;
1557
if (conf_req_flag)
1558
flags = GSS_TOKEN_SEALED;
1559
if (is_acceptor(kc))
1560
flags |= GSS_TOKEN_SENT_BY_ACCEPTOR;
1561
if (kc->kc_more_flags & ACCEPTOR_SUBKEY)
1562
flags |= GSS_TOKEN_ACCEPTOR_SUBKEY;
1563
p[2] = flags;
1564
1565
/* Filler */
1566
p[3] = 0xff;
1567
1568
/* EC + RRC - set to zero initially */
1569
p[4] = 0;
1570
p[5] = 0;
1571
p[6] = 0;
1572
p[7] = 0;
1573
1574
/* SND_SEQ */
1575
p[8] = 0;
1576
p[9] = 0;
1577
p[10] = 0;
1578
p[11] = 0;
1579
seq = atomic_fetchadd_32(&kc->kc_local_seqnumber, 1);
1580
p[12] = (seq >> 24);
1581
p[13] = (seq >> 16);
1582
p[14] = (seq >> 8);
1583
p[15] = (seq >> 0);
1584
1585
if (conf_req_flag) {
1586
/*
1587
* Encrypt according to RFC 4121 section 4.2 and RFC
1588
* 3961 section 5.3. Note: we don't generate tokens
1589
* with RRC values other than zero. If we did, we
1590
* should zero RRC in the copied header.
1591
*/
1592
arc4rand(p + 16, blen, 0);
1593
if (EC) {
1594
m_copyback(m, 16 + blen + mlen, EC, zpad);
1595
}
1596
m_copyback(m, 16 + blen + mlen + EC, 16, p);
1597
1598
krb5_checksum(Ki, 0, m, 16, ctlen, cklen);
1599
krb5_encrypt(Ke, m, 16, ctlen, NULL, 0);
1600
} else {
1601
/*
1602
* The plaintext message is followed by a checksum of
1603
* the plaintext plus a version of the header where EC
1604
* and RRC are set to zero. Also, the original EC must
1605
* be our checksum size.
1606
*/
1607
bcopy(p, tm->m_data, 16);
1608
krb5_checksum(Kc, 0, m, 16, mlen + 16, cklen);
1609
tm->m_data += 16;
1610
tm->m_len -= 16;
1611
}
1612
1613
/*
1614
* Finally set EC to its actual value
1615
*/
1616
p[4] = EC >> 8;
1617
p[5] = EC;
1618
1619
*mp = m;
1620
return (GSS_S_COMPLETE);
1621
}
1622
1623
static OM_uint32
1624
krb5_wrap(gss_ctx_id_t ctx, OM_uint32 *minor_status,
1625
int conf_req_flag, gss_qop_t qop_req,
1626
struct mbuf **mp, int *conf_state)
1627
{
1628
struct krb5_context *kc = (struct krb5_context *)ctx;
1629
1630
*minor_status = 0;
1631
if (conf_state)
1632
*conf_state = 0;
1633
1634
if (qop_req != GSS_C_QOP_DEFAULT)
1635
return (GSS_S_BAD_QOP);
1636
1637
if (time_uptime > kc->kc_lifetime)
1638
return (GSS_S_CONTEXT_EXPIRED);
1639
1640
switch (kc->kc_tokenkey->ks_class->ec_type) {
1641
case ETYPE_DES_CBC_CRC:
1642
return (krb5_wrap_old(kc, conf_req_flag,
1643
mp, conf_state, sgn_alg_des_md5, seal_alg_des));
1644
1645
case ETYPE_ARCFOUR_HMAC_MD5:
1646
case ETYPE_ARCFOUR_HMAC_MD5_56:
1647
return (krb5_wrap_old(kc, conf_req_flag,
1648
mp, conf_state, sgn_alg_hmac_md5, seal_alg_rc4));
1649
1650
case ETYPE_DES3_CBC_SHA1:
1651
return (krb5_wrap_old(kc, conf_req_flag,
1652
mp, conf_state, sgn_alg_des3_sha1, seal_alg_des3));
1653
1654
default:
1655
return (krb5_wrap_new(kc, conf_req_flag, mp, conf_state));
1656
}
1657
1658
return (GSS_S_FAILURE);
1659
}
1660
1661
static void
1662
m_trim(struct mbuf *m, int len)
1663
{
1664
struct mbuf *n;
1665
int off;
1666
1667
if (m == NULL)
1668
return;
1669
n = m_getptr(m, len, &off);
1670
if (n) {
1671
n->m_len = off;
1672
if (n->m_next) {
1673
m_freem(n->m_next);
1674
n->m_next = NULL;
1675
}
1676
}
1677
}
1678
1679
static OM_uint32
1680
krb5_unwrap_old(struct krb5_context *kc, struct mbuf **mp, int *conf_state,
1681
uint8_t sgn_alg[2], uint8_t seal_alg[2])
1682
{
1683
OM_uint32 res;
1684
struct mbuf *m, *mlast, *hm, *cm, *n;
1685
uint8_t *p, dir;
1686
size_t tlen, elen, datalen, padlen;
1687
size_t cklen;
1688
uint8_t buf[32];
1689
uint32_t seq;
1690
int i, conf;
1691
1692
m = *mp;
1693
m_length(m, &mlast);
1694
1695
tlen = token_length(kc->kc_tokenkey);
1696
cklen = kc->kc_tokenkey->ks_class->ec_checksumlen;
1697
1698
p = krb5_verify_token("\x02\x01", tlen, &m, &elen, TRUE);
1699
*mp = m;
1700
if (!p)
1701
return (GSS_S_DEFECTIVE_TOKEN);
1702
datalen = elen - tlen;
1703
1704
/*
1705
* Trim the framing header first to make life a little easier
1706
* later.
1707
*/
1708
m_adj(m, p - (uint8_t *) m->m_data);
1709
1710
/* TOK_ID */
1711
p += 2;
1712
1713
/* SGN_ALG */
1714
if (p[0] != sgn_alg[0] || p[1] != sgn_alg[1])
1715
return (GSS_S_DEFECTIVE_TOKEN);
1716
p += 2;
1717
1718
/* SEAL_ALG */
1719
if (p[0] == seal_alg[0] && p[1] == seal_alg[1])
1720
conf = 1;
1721
else if (p[0] == 0xff && p[1] == 0xff)
1722
conf = 0;
1723
else
1724
return (GSS_S_DEFECTIVE_TOKEN);
1725
p += 2;
1726
1727
if (p[0] != 0xff || p[1] != 0xff)
1728
return (GSS_S_DEFECTIVE_TOKEN);
1729
p += 2;
1730
1731
/*
1732
* SND_SEQ:
1733
*
1734
* Take the four bytes of the sequence number least
1735
* significant first (most significant for ARCFOUR) followed
1736
* by four bytes of direction marker (zero for initiator and
1737
* 0xff for acceptor). Encrypt that data using the SGN_CKSUM
1738
* as IV.
1739
*/
1740
krb5_decrypt(kc->kc_tokenkey, m, 8, 8, p + 8, 8);
1741
if (sgn_alg[0] == 0x11) {
1742
seq = p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24);
1743
} else {
1744
seq = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
1745
}
1746
1747
if (is_initiator(kc)) {
1748
dir = 0xff;
1749
} else {
1750
dir = 0;
1751
}
1752
if (p[4] != dir || p[5] != dir || p[6] != dir || p[7] != dir)
1753
return (GSS_S_DEFECTIVE_TOKEN);
1754
1755
if (kc->kc_msg_order.km_flags &
1756
(GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG)) {
1757
res = krb5_sequence_check(kc, seq);
1758
if (GSS_ERROR(res))
1759
return (res);
1760
} else {
1761
res = GSS_S_COMPLETE;
1762
}
1763
1764
/*
1765
* If the token was encrypted, decode it in-place.
1766
*/
1767
if (conf) {
1768
/*
1769
* Decrypt the padded message with an IV of zero for
1770
* DES and DES3 or an IV of the big-endian encoded
1771
* sequence number for ARCFOUR.
1772
*/
1773
if (seal_alg[0] == 0x10) {
1774
krb5_decrypt(kc->kc_encryptkey, m, 16 + cklen,
1775
datalen, p, 4);
1776
} else {
1777
krb5_decrypt(kc->kc_encryptkey, m, 16 + cklen,
1778
datalen, NULL, 0);
1779
}
1780
}
1781
if (conf_state)
1782
*conf_state = conf;
1783
1784
/*
1785
* Check the trailing pad bytes.
1786
* RFC1964 specifies between 1<->8 bytes, each with a binary value
1787
* equal to the number of bytes.
1788
*/
1789
if (mlast->m_len > 0)
1790
padlen = mlast->m_data[mlast->m_len - 1];
1791
else {
1792
n = m_getptr(m, tlen + datalen - 1, &i);
1793
/*
1794
* When the position is exactly equal to the # of data bytes
1795
* in the mbuf list, m_getptr() will return the last mbuf in
1796
* the list and an off == m_len for that mbuf, so that case
1797
* needs to be checked as well as a NULL return.
1798
*/
1799
if (n == NULL || n->m_len == i)
1800
return (GSS_S_DEFECTIVE_TOKEN);
1801
padlen = n->m_data[i];
1802
}
1803
if (padlen < 1 || padlen > 8 || padlen > tlen + datalen)
1804
return (GSS_S_DEFECTIVE_TOKEN);
1805
m_copydata(m, tlen + datalen - padlen, padlen, buf);
1806
for (i = 0; i < padlen; i++) {
1807
if (buf[i] != padlen) {
1808
return (GSS_S_DEFECTIVE_TOKEN);
1809
}
1810
}
1811
1812
/*
1813
* SGN_CKSUM:
1814
*
1815
* Calculate the keyed checksum of the token header plus the
1816
* padded message. We do a little mbuf surgery to trim out the
1817
* parts we don't want to checksum.
1818
*/
1819
hm = m;
1820
*mp = m = m_split(m, 16 + cklen, M_WAITOK);
1821
mlast = m_last(m);
1822
hm->m_len = 8;
1823
hm->m_next = m;
1824
MGET(cm, M_WAITOK, MT_DATA);
1825
cm->m_len = cklen;
1826
mlast->m_next = cm;
1827
1828
krb5_checksum(kc->kc_checksumkey, 13, hm, 0, datalen + 8, cklen);
1829
hm->m_next = NULL;
1830
mlast->m_next = NULL;
1831
1832
if (bcmp(cm->m_data, hm->m_data + 16, cklen)) {
1833
m_freem(hm);
1834
m_free(cm);
1835
return (GSS_S_BAD_SIG);
1836
}
1837
m_freem(hm);
1838
m_free(cm);
1839
1840
/*
1841
* Trim off the confounder and padding.
1842
*/
1843
m_adj(m, 8);
1844
if (mlast->m_len >= padlen) {
1845
mlast->m_len -= padlen;
1846
} else {
1847
m_trim(m, datalen - 8 - padlen);
1848
}
1849
1850
*mp = m;
1851
return (res);
1852
}
1853
1854
static OM_uint32
1855
krb5_unwrap_new(struct krb5_context *kc, struct mbuf **mp, int *conf_state)
1856
{
1857
OM_uint32 res;
1858
struct krb5_key_state *Ke = kc->kc_recv_seal_Ke;
1859
struct krb5_key_state *Ki = kc->kc_recv_seal_Ki;
1860
struct krb5_key_state *Kc = kc->kc_recv_seal_Kc;
1861
const struct krb5_encryption_class *ec = Ke->ks_class;
1862
struct mbuf *m, *mlast, *hm, *cm;
1863
uint8_t *p;
1864
int sealed, flags, EC, RRC;
1865
size_t blen, cklen, ctlen, mlen, plen, tlen;
1866
char buf[32], buf2[32];
1867
1868
m = *mp;
1869
mlen = m_length(m, &mlast);
1870
1871
if (mlen <= 16)
1872
return (GSS_S_DEFECTIVE_TOKEN);
1873
if (m->m_len < 16) {
1874
m = m_pullup(m, 16);
1875
*mp = m;
1876
}
1877
p = m->m_data;
1878
1879
/* TOK_ID */
1880
if (p[0] != 0x05)
1881
return (GSS_S_DEFECTIVE_TOKEN);
1882
if (p[1] != 0x04)
1883
return (GSS_S_DEFECTIVE_TOKEN);
1884
1885
/* Flags */
1886
sealed = p[2] & GSS_TOKEN_SEALED;
1887
flags = sealed;
1888
if (is_initiator(kc))
1889
flags |= GSS_TOKEN_SENT_BY_ACCEPTOR;
1890
if (kc->kc_more_flags & ACCEPTOR_SUBKEY)
1891
flags |= GSS_TOKEN_ACCEPTOR_SUBKEY;
1892
if (p[2] != flags)
1893
return (GSS_S_DEFECTIVE_TOKEN);
1894
1895
/* Filler */
1896
if (p[3] != 0xff)
1897
return (GSS_S_DEFECTIVE_TOKEN);
1898
1899
/* EC + RRC */
1900
EC = (p[4] << 8) + p[5];
1901
RRC = (p[6] << 8) + p[7];
1902
1903
/* SND_SEQ */
1904
if (kc->kc_msg_order.km_flags &
1905
(GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG)) {
1906
uint32_t seq;
1907
if (p[8] || p[9] || p[10] || p[11]) {
1908
res = GSS_S_UNSEQ_TOKEN;
1909
} else {
1910
seq = (p[12] << 24) | (p[13] << 16)
1911
| (p[14] << 8) | p[15];
1912
res = krb5_sequence_check(kc, seq);
1913
}
1914
if (GSS_ERROR(res))
1915
return (res);
1916
} else {
1917
res = GSS_S_COMPLETE;
1918
}
1919
1920
/*
1921
* Separate the header before dealing with RRC. We only need
1922
* to keep the header if the message isn't encrypted.
1923
*/
1924
if (sealed) {
1925
hm = NULL;
1926
m_adj(m, 16);
1927
} else {
1928
hm = m;
1929
*mp = m = m_split(m, 16, M_WAITOK);
1930
mlast = m_last(m);
1931
}
1932
1933
/*
1934
* Undo the effects of RRC by rotating left.
1935
*/
1936
if (RRC > 0) {
1937
struct mbuf *rm;
1938
size_t rlen;
1939
1940
rlen = mlen - 16;
1941
if (RRC <= sizeof(buf) && m->m_len >= rlen) {
1942
/*
1943
* Simple case, just rearrange the bytes in m.
1944
*/
1945
bcopy(m->m_data, buf, RRC);
1946
bcopy(m->m_data + RRC, m->m_data, rlen - RRC);
1947
bcopy(buf, m->m_data + rlen - RRC, RRC);
1948
} else {
1949
/*
1950
* More complicated - rearrange the mbuf
1951
* chain.
1952
*/
1953
rm = m;
1954
*mp = m = m_split(m, RRC, M_WAITOK);
1955
m_cat(m, rm);
1956
mlast = rm;
1957
}
1958
}
1959
1960
blen = ec->ec_blocklen;
1961
cklen = ec->ec_checksumlen;
1962
if (sealed) {
1963
/*
1964
* Decrypt according to RFC 4121 section 4.2 and RFC
1965
* 3961 section 5.3. The message must be large enough
1966
* for a blocksize confounder, at least one block of
1967
* cyphertext and a checksum.
1968
*/
1969
if (mlen < 16 + 2*blen + cklen)
1970
return (GSS_S_DEFECTIVE_TOKEN);
1971
1972
ctlen = mlen - 16 - cklen;
1973
krb5_decrypt(Ke, m, 0, ctlen, NULL, 0);
1974
1975
/*
1976
* The size of the plaintext is ctlen minus blocklen
1977
* (for the confounder), 16 (for the copy of the token
1978
* header) and EC (for the filler). The actual
1979
* plaintext starts after the confounder.
1980
*/
1981
plen = ctlen - blen - 16 - EC;
1982
1983
/*
1984
* Checksum the padded plaintext.
1985
*/
1986
m_copydata(m, ctlen, cklen, buf);
1987
krb5_checksum(Ki, 0, m, 0, ctlen, cklen);
1988
m_copydata(m, ctlen, cklen, buf2);
1989
1990
if (bcmp(buf, buf2, cklen))
1991
return (GSS_S_BAD_SIG);
1992
1993
/*
1994
* Trim the message back to just plaintext.
1995
*/
1996
m_adj(m, blen);
1997
tlen = 16 + EC + cklen;
1998
if (mlast->m_len >= tlen) {
1999
mlast->m_len -= tlen;
2000
} else {
2001
m_trim(m, plen);
2002
}
2003
} else {
2004
/*
2005
* The plaintext message is followed by a checksum of
2006
* the plaintext plus a version of the header where EC
2007
* and RRC are set to zero. Also, the original EC must
2008
* be our checksum size.
2009
*/
2010
if (mlen < 16 + cklen || EC != cklen)
2011
return (GSS_S_DEFECTIVE_TOKEN);
2012
2013
/*
2014
* The size of the plaintext is simply the message
2015
* size less header and checksum. The plaintext starts
2016
* right after the header (which we have saved in hm).
2017
*/
2018
plen = mlen - 16 - cklen;
2019
2020
/*
2021
* Insert a copy of the header (with EC and RRC set to
2022
* zero) between the plaintext message and the
2023
* checksum.
2024
*/
2025
p = hm->m_data;
2026
p[4] = p[5] = p[6] = p[7] = 0;
2027
2028
cm = m_split(m, plen, M_WAITOK);
2029
mlast = m_last(m);
2030
m->m_next = hm;
2031
hm->m_next = cm;
2032
2033
bcopy(cm->m_data, buf, cklen);
2034
krb5_checksum(Kc, 0, m, 0, plen + 16, cklen);
2035
if (bcmp(cm->m_data, buf, cklen))
2036
return (GSS_S_BAD_SIG);
2037
2038
/*
2039
* The checksum matches, discard all buf the plaintext.
2040
*/
2041
mlast->m_next = NULL;
2042
m_freem(hm);
2043
}
2044
2045
if (conf_state)
2046
*conf_state = (sealed != 0);
2047
2048
return (res);
2049
}
2050
2051
static OM_uint32
2052
krb5_unwrap(gss_ctx_id_t ctx, OM_uint32 *minor_status,
2053
struct mbuf **mp, int *conf_state, gss_qop_t *qop_state)
2054
{
2055
struct krb5_context *kc = (struct krb5_context *)ctx;
2056
OM_uint32 maj_stat;
2057
2058
*minor_status = 0;
2059
if (qop_state)
2060
*qop_state = GSS_C_QOP_DEFAULT;
2061
if (conf_state)
2062
*conf_state = 0;
2063
2064
if (time_uptime > kc->kc_lifetime)
2065
return (GSS_S_CONTEXT_EXPIRED);
2066
2067
switch (kc->kc_tokenkey->ks_class->ec_type) {
2068
case ETYPE_DES_CBC_CRC:
2069
maj_stat = krb5_unwrap_old(kc, mp, conf_state,
2070
sgn_alg_des_md5, seal_alg_des);
2071
break;
2072
2073
case ETYPE_ARCFOUR_HMAC_MD5:
2074
case ETYPE_ARCFOUR_HMAC_MD5_56:
2075
maj_stat = krb5_unwrap_old(kc, mp, conf_state,
2076
sgn_alg_hmac_md5, seal_alg_rc4);
2077
break;
2078
2079
case ETYPE_DES3_CBC_SHA1:
2080
maj_stat = krb5_unwrap_old(kc, mp, conf_state,
2081
sgn_alg_des3_sha1, seal_alg_des3);
2082
break;
2083
2084
default:
2085
maj_stat = krb5_unwrap_new(kc, mp, conf_state);
2086
break;
2087
}
2088
2089
if (GSS_ERROR(maj_stat)) {
2090
m_freem(*mp);
2091
*mp = NULL;
2092
}
2093
2094
return (maj_stat);
2095
}
2096
2097
static OM_uint32
2098
krb5_wrap_size_limit(gss_ctx_id_t ctx, OM_uint32 *minor_status,
2099
int conf_req_flag, gss_qop_t qop_req, OM_uint32 req_output_size,
2100
OM_uint32 *max_input_size)
2101
{
2102
struct krb5_context *kc = (struct krb5_context *)ctx;
2103
const struct krb5_encryption_class *ec;
2104
OM_uint32 overhead;
2105
2106
*minor_status = 0;
2107
*max_input_size = 0;
2108
2109
if (qop_req != GSS_C_QOP_DEFAULT)
2110
return (GSS_S_BAD_QOP);
2111
2112
ec = kc->kc_tokenkey->ks_class;
2113
switch (ec->ec_type) {
2114
case ETYPE_DES_CBC_CRC:
2115
case ETYPE_DES3_CBC_SHA1:
2116
case ETYPE_ARCFOUR_HMAC_MD5:
2117
case ETYPE_ARCFOUR_HMAC_MD5_56:
2118
/*
2119
* up to 5 bytes for [APPLICATION 0] SEQUENCE
2120
* 2 + krb5 oid length
2121
* 8 bytes of header
2122
* 8 bytes of confounder
2123
* maximum of 8 bytes of padding
2124
* checksum
2125
*/
2126
overhead = 5 + 2 + krb5_mech_oid.length;
2127
overhead += 8 + 8 + ec->ec_msgblocklen;
2128
overhead += ec->ec_checksumlen;
2129
break;
2130
2131
default:
2132
if (conf_req_flag) {
2133
/*
2134
* 16 byts of header
2135
* blocklen bytes of confounder
2136
* up to msgblocklen - 1 bytes of padding
2137
* 16 bytes for copy of header
2138
* checksum
2139
*/
2140
overhead = 16 + ec->ec_blocklen;
2141
overhead += ec->ec_msgblocklen - 1;
2142
overhead += 16;
2143
overhead += ec->ec_checksumlen;
2144
} else {
2145
/*
2146
* 16 bytes of header plus checksum.
2147
*/
2148
overhead = 16 + ec->ec_checksumlen;
2149
}
2150
}
2151
2152
*max_input_size = req_output_size - overhead;
2153
2154
return (GSS_S_COMPLETE);
2155
}
2156
2157
static kobj_method_t krb5_methods[] = {
2158
KOBJMETHOD(kgss_init, krb5_init),
2159
KOBJMETHOD(kgss_import, krb5_import),
2160
KOBJMETHOD(kgss_delete, krb5_delete),
2161
KOBJMETHOD(kgss_mech_type, krb5_mech_type),
2162
KOBJMETHOD(kgss_get_mic, krb5_get_mic),
2163
KOBJMETHOD(kgss_verify_mic, krb5_verify_mic),
2164
KOBJMETHOD(kgss_wrap, krb5_wrap),
2165
KOBJMETHOD(kgss_unwrap, krb5_unwrap),
2166
KOBJMETHOD(kgss_wrap_size_limit, krb5_wrap_size_limit),
2167
{ 0, 0 }
2168
};
2169
2170
static struct kobj_class krb5_class = {
2171
"kerberosv5",
2172
krb5_methods,
2173
sizeof(struct krb5_context)
2174
};
2175
2176
/*
2177
* Kernel module glue
2178
*/
2179
static int
2180
kgssapi_krb5_modevent(module_t mod, int type, void *data)
2181
{
2182
2183
switch (type) {
2184
case MOD_LOAD:
2185
kgss_install_mech(&krb5_mech_oid, "kerberosv5", &krb5_class);
2186
break;
2187
2188
case MOD_UNLOAD:
2189
kgss_uninstall_mech(&krb5_mech_oid);
2190
break;
2191
}
2192
2193
return (0);
2194
}
2195
static moduledata_t kgssapi_krb5_mod = {
2196
"kgssapi_krb5",
2197
kgssapi_krb5_modevent,
2198
NULL,
2199
};
2200
DECLARE_MODULE(kgssapi_krb5, kgssapi_krb5_mod, SI_SUB_VFS, SI_ORDER_ANY);
2201
MODULE_DEPEND(kgssapi_krb5, kgssapi, 1, 1, 1);
2202
MODULE_DEPEND(kgssapi_krb5, crypto, 1, 1, 1);
2203
MODULE_DEPEND(kgssapi_krb5, rc4, 1, 1, 1);
2204
MODULE_VERSION(kgssapi_krb5, 1);
2205
2206