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