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