1/* 2 * Copyright (c) 2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 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 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Portions of this software have been released under the following terms: 31 * 32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC. 33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY 34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION 35 * 36 * To anyone who acknowledges that this file is provided "AS IS" 37 * without any express or implied warranty: 38 * permission to use, copy, modify, and distribute this file for any 39 * purpose is hereby granted without fee, provided that the above 40 * copyright notices and this notice appears in all source code copies, 41 * and that none of the names of Open Software Foundation, Inc., Hewlett- 42 * Packard Company or Digital Equipment Corporation be used 43 * in advertising or publicity pertaining to distribution of the software 44 * without specific, written prior permission. Neither Open Software 45 * Foundation, Inc., Hewlett-Packard Company nor Digital 46 * Equipment Corporation makes any representations about the suitability 47 * of this software for any purpose. 48 * 49 * Copyright (c) 2007, Novell, Inc. All rights reserved. 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 54 * 1. Redistributions of source code must retain the above copyright 55 * notice, this list of conditions and the following disclaimer. 56 * 2. Redistributions in binary form must reproduce the above copyright 57 * notice, this list of conditions and the following disclaimer in the 58 * documentation and/or other materials provided with the distribution. 59 * 3. Neither the name of Novell Inc. nor the names of its contributors 60 * may be used to endorse or promote products derived from this 61 * this software without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY 67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 73 * 74 * @APPLE_LICENSE_HEADER_END@ 75 */ 76 77/* 78** NAME 79** 80** schnauthcn.c 81** 82** FACILITY: 83** 84** Remote Procedure Call (RPC) 85** 86** ABSTRACT: 87** 88** The netlogon/schannel CN authentication module. 89** 90** 91*/ 92 93#include <dce/schannel.h> 94#include <schnauth.h> 95 96#include <pwd.h> /* for getpwuid, etc, for "level_none" */ 97 98#include <schnauthcn.h> 99 100INTERNAL boolean32 rpc__schnauth_cn_three_way (void); 101 102INTERNAL boolean32 rpc__schnauth_cn_context_valid ( 103 rpc_cn_sec_context_p_t /*sec*/, 104 unsigned32 * /*st*/ 105 ); 106 107INTERNAL void rpc__schnauth_cn_create_info ( 108 rpc_authn_level_t /*authn_level*/, 109 rpc_auth_info_p_t * /*auth_info*/, 110 unsigned32 * /*st*/ 111 ); 112 113INTERNAL boolean32 rpc__schnauth_cn_cred_changed ( 114 rpc_cn_sec_context_p_t /*sec*/, 115 unsigned32 * /*st*/ 116 ); 117 118INTERNAL void rpc__schnauth_cn_cred_refresh ( 119 rpc_auth_info_p_t /*auth_info*/, 120 unsigned32 * /*st*/ 121 ); 122 123INTERNAL void rpc__schnauth_cn_fmt_client_req ( 124 rpc_cn_assoc_sec_context_p_t /* assoc_sec */, 125 rpc_cn_sec_context_p_t /* sec */, 126 dce_pointer_t /* auth_value */, 127 unsigned32 * /* auth_value_len */, 128 dce_pointer_t * /* last_auth_pos */, 129 unsigned32 * /* auth_len_remain */, 130 unsigned32 /* old_server */, 131 unsigned32 * /* st */ 132 ); 133 134INTERNAL void rpc__schnauth_cn_fmt_srvr_resp ( 135 unsigned32 /*verify_st*/, 136 rpc_cn_assoc_sec_context_p_t /*assoc_sec*/, 137 rpc_cn_sec_context_p_t /*sec*/, 138 dce_pointer_t /*req_auth_value*/, 139 unsigned32 /*req_auth_value_len*/, 140 dce_pointer_t /*auth_value*/, 141 unsigned32 * /*auth_value_len*/ 142 ); 143 144INTERNAL void rpc__schnauth_cn_free_prot_info ( 145 rpc_auth_info_p_t /*info*/, 146 rpc_cn_auth_info_p_t * /*cn_info*/ 147 ); 148 149INTERNAL void rpc__schnauth_cn_get_prot_info ( 150 rpc_auth_info_p_t /*info*/, 151 rpc_cn_auth_info_p_t * /*cn_info*/, 152 unsigned32 * /*st*/ 153 ); 154 155INTERNAL void rpc__schnauth_cn_pre_call ( 156 rpc_cn_assoc_sec_context_p_t /*assoc_sec*/, 157 rpc_cn_sec_context_p_t /*sec*/, 158 dce_pointer_t /*auth_value*/, 159 unsigned32 * /*auth_value_len*/, 160 unsigned32 * /*st*/ 161 ); 162 163INTERNAL void rpc__schnauth_cn_pre_send ( 164 rpc_cn_assoc_sec_context_p_t /*assoc_sec*/, 165 rpc_cn_sec_context_p_t /*sec*/, 166 rpc_socket_iovec_p_t /*iov*/, 167 unsigned32 /*iovlen*/, 168 rpc_socket_iovec_p_t /*out_iov*/, 169 unsigned32 * /*st*/ 170 ); 171 172INTERNAL void rpc__schnauth_cn_recv_check ( 173 rpc_cn_assoc_sec_context_p_t /*assoc_sec*/, 174 rpc_cn_sec_context_p_t /*sec*/, 175 rpc_cn_common_hdr_p_t /*pdu*/, 176 unsigned32 /*pdu_len*/, 177 unsigned32 /*cred_len*/, 178 rpc_cn_auth_tlr_p_t /*auth_tlr*/, 179 boolean32 /*unpack_ints*/, 180 unsigned32 * /*st*/ 181 ); 182 183INTERNAL void rpc__schnauth_cn_tlr_uuid_crc ( 184 dce_pointer_t /*auth_value*/, 185 unsigned32 /*auth_value_len*/, 186 unsigned32 * /*uuid_crc*/ 187 ); 188 189INTERNAL void rpc__schnauth_cn_tlr_unpack ( 190 rpc_cn_packet_p_t /*pkt_p*/, 191 unsigned32 /*auth_value_len*/, 192 unsigned8 * /*packed_drep*/ 193 ); 194 195INTERNAL void rpc__schnauth_cn_vfy_client_req ( 196 rpc_cn_assoc_sec_context_p_t /* assoc_sec */, 197 rpc_cn_sec_context_p_t /* sec */, 198 dce_pointer_t /* auth_value */, 199 unsigned32 /* auth_value_len */, 200 unsigned32 /* old_client */, 201 unsigned32 * /* st */ 202 ); 203 204INTERNAL void rpc__schnauth_cn_vfy_srvr_resp ( 205 rpc_cn_assoc_sec_context_p_t /*assoc_sec*/, 206 rpc_cn_sec_context_p_t /*sec*/, 207 dce_pointer_t /*auth_value*/, 208 unsigned32 /*auth_value_len*/, 209 unsigned32 * /*st*/ 210 ); 211 212INTERNAL const rpc_cn_auth_epv_t rpc_g_schnauth_cn_epv = 213{ 214 .three_way = rpc__schnauth_cn_three_way, 215 .context_valid = rpc__schnauth_cn_context_valid, 216 .create_info = rpc__schnauth_cn_create_info, 217 .cred_changed = rpc__schnauth_cn_cred_changed, 218 .cred_refresh = rpc__schnauth_cn_cred_refresh, 219 .fmt_client_req = rpc__schnauth_cn_fmt_client_req, 220 .fmt_srvr_resp = rpc__schnauth_cn_fmt_srvr_resp, 221 .free_prot_info = rpc__schnauth_cn_free_prot_info, 222 .get_prot_info = rpc__schnauth_cn_get_prot_info, 223 .pre_call = rpc__schnauth_cn_pre_call, 224 .pre_send = rpc__schnauth_cn_pre_send, 225 .recv_check = rpc__schnauth_cn_recv_check, 226 .tlr_uuid_crc = rpc__schnauth_cn_tlr_uuid_crc, 227 .tlr_unpack = rpc__schnauth_cn_tlr_unpack, 228 .vfy_client_req = rpc__schnauth_cn_vfy_client_req, 229 .vfy_srvr_resp = rpc__schnauth_cn_vfy_srvr_resp 230}; 231 232/*****************************************************************************/ 233/* 234**++ 235** 236** ROUTINE NAME: rpc__schnauth_cn_three_way 237** 238** SCOPE: INTERNAL - declared locally 239** 240** DESCRIPTION: 241** 242** Determine whether the authentication protocol requires a 243** 3-way authentication handshake. If true the client is expected to 244** provide an rpc_auth3 PDU before the security context is fully 245** established and a call can be made. 246** 247** INPUTS: none 248** 249** INPUTS/OUTPUTS: none 250** 251** OUTPUTS: none 252** 253** IMPLICIT INPUTS: none 254** 255** IMPLICIT OUTPUTS: none 256** 257** FUNCTION VALUE: boolean32 258** 259** True if the authentication protocol requires a 3-way 260** authentication handshake. 261** 262** SIDE EFFECTS: none 263** 264**-- 265**/ 266 267INTERNAL boolean32 rpc__schnauth_cn_three_way (void) 268{ 269 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 270 ("(rpc__schnauth_cn_three_way)\n")); 271 272 return (false); 273} 274 275/*****************************************************************************/ 276/* 277**++ 278** 279** ROUTINE NAME: rpc__schnauth_cn_context_valid 280** 281** SCOPE: INTERNAL - declared locally 282** 283** DESCRIPTION: 284** 285** Determine whether the established security context will be 286** valid (i. e. timely) for the next 300 seconds. If 287** not this routine will try to renew the context. 288** If it cannot be renewed false is returned. This is 289** called from the client side. 290** 291** INPUTS: 292** 293** sec A pointer to security context element which includes 294** the key ID, auth information rep and RPC auth 295** information rep. 296** 297** INPUTS/OUTPUTS: none 298** 299** OUTPUTS: 300** 301** st The return status of this routine. 302** 303** IMPLICIT INPUTS: none 304** 305** IMPLICIT OUTPUTS: none 306** 307** FUNCTION VALUE: boolean32 308** 309** True if security context identified by the auth 310** information rep and RPC auth information rep will 311** still be valid in 300 seconds, false if not. 312** 313** SIDE EFFECTS: 314** 315** The context may be renewed. 316** 317**-- 318**/ 319 320INTERNAL boolean32 rpc__schnauth_cn_context_valid 321( 322 rpc_cn_sec_context_p_t sec, 323 unsigned32 *st 324) 325{ 326 CODING_ERROR (st); 327 328 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 329 ("(rpc__schnauth_cn_context_valid)\n")); 330 331 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 332 ("(rpc__schnauth_cn_context_valid) prot->%x level->%x key_id->%x\n", 333 rpc_c_authn_dce_dummy, 334 sec->sec_info->authn_level, 335 sec->sec_key_id)); 336 337#ifdef DEBUG 338 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, 339 RPC_C_CN_DBG_AUTH_CONTEXT_VALID)) 340 { 341 *st = RPC_S_CN_DBG_AUTH_FAILURE; 342 return (false); 343 } 344#endif 345 346 *st = rpc_s_ok; 347 return (true); 348} 349 350 351/*****************************************************************************/ 352/* 353**++ 354** 355** ROUTINE NAME: rpc__schnauth_cn_create_info 356** 357** SCOPE: INTERNAL - declared locally 358** 359** DESCRIPTION: 360** 361** Create an auth information rep data structure with and 362** add a reference to it. This is called on the server 363** side. The fields will be initialized to NULL values. 364** The caller should fill them in based on information 365** decrypted from the authenticator passed in the bind 366** request. 367** 368** INPUTS: 369** 370** authn_level The authentication level to be applied over this 371** security context. 372** 373** INPUTS/OUTPUTS: none 374** 375** OUTPUTS: 376** 377** info A pointer to the auth information rep structure 378** containing RPC protocol indenpendent information. 379** st The return status of this routine. 380** 381** IMPLICIT INPUTS: none 382** 383** IMPLICIT OUTPUTS: none 384** 385** FUNCTION VALUE: none 386** 387** SIDE EFFECTS: 388** 389** The newly create auth info will have a reference count of 1. 390** 391**-- 392**/ 393 394INTERNAL void rpc__schnauth_cn_create_info 395( 396 rpc_authn_level_t authn_level, 397 rpc_auth_info_p_t *auth_info, 398 unsigned32 *st 399) 400{ 401 rpc_schnauth_info_p_t schnauth_info; 402 403 CODING_ERROR (st); 404 405 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 406 ("(rpc__schnauth_cn_create_info)\n")); 407 408 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 409 ("(rpc__schnauth_cn_create_info) prot->%x level->%x\n", 410 rpc_c_authn_dce_dummy, 411 authn_level)); 412 413#ifdef DEBUG 414 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, 415 RPC_C_CN_DBG_AUTH_CREATE_INFO)) 416 { 417 *st = RPC_S_CN_DBG_AUTH_FAILURE; 418 return; 419 } 420#endif 421 422 /* 423 * Allocate storage for a noauth info structure from heap. 424 */ 425 RPC_MEM_ALLOC(schnauth_info, 426 rpc_schnauth_info_p_t, 427 sizeof (rpc_schnauth_info_t), 428 RPC_C_MEM_SCHNAUTH_INFO, 429 RPC_C_MEM_WAITOK); 430 431 /* 432 * Initialize it. 433 */ 434 memset(schnauth_info, 0, sizeof(rpc_schnauth_info_t)); 435 RPC_MUTEX_INIT (schnauth_info->lock); 436 437 /* 438 * Initialize the common auth_info stuff. 439 */ 440 schnauth_info->auth_info.refcount = 1; 441 schnauth_info->auth_info.server_princ_name = '\0'; 442 schnauth_info->auth_info.authn_level = authn_level; 443 schnauth_info->auth_info.authn_protocol = rpc_c_authn_dce_dummy; 444 schnauth_info->auth_info.authz_protocol = rpc_c_authz_name; 445 schnauth_info->auth_info.is_server = true; 446 447 *auth_info = (rpc_auth_info_t *) schnauth_info; 448 *st = rpc_s_ok; 449} 450 451 452/*****************************************************************************/ 453/* 454**++ 455** 456** ROUTINE NAME: rpc__schnauth_cn_cred_changed 457** 458** SCOPE: INTERNAL - declared locally 459** 460** DESCRIPTION: 461** 462** Determine whether the client's credentials stored in the 463** security context are different from those in the auth info. 464** If they are not the same return true, else false. 465** 466** INPUTS: 467** 468** sec A pointer to security context element which includes 469** the key ID, auth information rep and RPC auth 470** information rep. 471** 472** INPUTS/OUTPUTS: none 473** 474** OUTPUTS: 475** 476** st The return status of this routine. 477** 478** IMPLICIT INPUTS: none 479** 480** IMPLICIT OUTPUTS: none 481** 482** FUNCTION VALUE: boolean32 483** 484** True if the credentials identified by the auth 485** information rep and RPC auth information rep are different, 486** false if not. 487** 488** The md5 checksum algorithm requires the use of the session key 489** to encrypt the CRC(assoc_uuid). Since the session key will 490** change when the credential changes, this routine sets the flag 491** indicating that a (potentially) valid encrypted crc is now 492** invalid, forcing a recomputation. 493** 494** SIDE EFFECTS: none 495** 496**-- 497**/ 498 499INTERNAL boolean32 rpc__schnauth_cn_cred_changed 500( 501 rpc_cn_sec_context_p_t sec, 502 unsigned32 *st 503) 504{ 505 rpc_schnauth_cn_info_t *schnauth_cn_info ATTRIBUTE_UNUSED; 506 rpc_schnauth_info_p_t schnuth_info ATTRIBUTE_UNUSED; 507 boolean32 different_creds; 508 509 CODING_ERROR (st); 510 511 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 512 ("(rpc__schnauth_cn_cred_changed)\n")); 513 514 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 515 ("(rpc__schnauth_cn_cred_changed) prot->%x level->%x key_id->%x\n", 516 rpc_c_authn_dce_private, 517 sec->sec_info->authn_level, 518 sec->sec_key_id)); 519 520#ifdef DEBUG 521 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, 522 RPC_C_CN_DBG_AUTH_CRED_CHANGED)) 523 { 524 *st = RPC_S_CN_DBG_AUTH_FAILURE; 525 return (false); 526 } 527#endif 528 529 /* 530 * Assume that cred is already valid. 531 */ 532 different_creds = false; 533 *st = rpc_s_ok; 534 return (different_creds); 535} 536 537 538/*****************************************************************************/ 539/* 540**++ 541** 542** ROUTINE NAME: rpc__schnauth_cn_cred_refresh 543** 544** SCOPE: INTERNAL - declared locally 545** 546** DESCRIPTION: 547** 548** Determine whether the client's credentials are still 549** valid. If not this routine will try to renew the credentials. 550** If they cannot be renewed an error is returned. This routine 551** is called from the client side. 552** 553** INPUTS: 554** 555** auth_info A pointer to the auth information rep 556** 557** INPUTS/OUTPUTS: none 558** 559** OUTPUTS: 560** 561** st The return status of this routine. 562** 563** IMPLICIT INPUTS: none 564** 565** IMPLICIT OUTPUTS: none 566** 567** FUNCTION VALUE: none 568** 569** SIDE EFFECTS: none 570** 571**-- 572**/ 573 574INTERNAL void rpc__schnauth_cn_cred_refresh 575( 576 rpc_auth_info_p_t auth_info, 577 unsigned32 *st 578) 579{ 580 rpc_schnauth_info_p_t schnauth_info; 581 582 schnauth_info = (rpc_schnauth_info_p_t)auth_info; 583 584 CODING_ERROR (st); 585 586 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 587 ("(rpc__schnauth_cn_cred_refresh)\n")); 588 589 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 590 ("(rpc__schnauth_cn_cred_refresh) prot->%x level->%x\n", 591 rpc_c_authn_dce_private, 592 auth_info->authn_level)); 593 594#ifdef DEBUG 595 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, 596 RPC_C_CN_DBG_AUTH_CRED_REFRESH)) 597 { 598 *st = RPC_S_CN_DBG_AUTH_FAILURE; 599 return; 600 } 601#endif 602 603 /* 604 * Assume that cred is already valid. 605 */ 606 *st = rpc_s_ok; 607} 608 609/*****************************************************************************/ 610/* 611**++ 612** 613** ROUTINE NAME: rpc__schnauth_cn_fmt_client_req 614** 615** SCOPE: INTERNAL - declared locally 616** 617** DESCRIPTION: 618** 619** This routine will format the auth_value field of 620** either an rpc_bind or rpc_alter_context PDU. This is 621** called from the client side association state machine. 622** 623** INPUTS: 624** 625** assoc_sec A pointer to per-association security context 626** including association UUID CRC and sequence numbers. 627** sec A pointer to security context element which includes 628** the key ID, auth information rep and RPC auth 629** information rep. 630** auth_value A pointer to the auth_value field in the rpc_bind or 631** rpc_alter_context PDU authentication trailer. 632** 633** INPUTS/OUTPUTS: 634** 635** auth_value_len On input, the lenght, in bytes of the available space 636** for the auth_value field. On output, the lenght in 637** bytes used in encoding the auth_value field. Zero if 638** an error status is returned. 639** 640** OUTPUTS: 641** 642** st The return status of this routine. 643** 644** IMPLICIT INPUTS: none 645** 646** IMPLICIT OUTPUTS: none 647** 648** FUNCTION VALUE: none 649** 650** SIDE EFFECTS: none 651** 652**-- 653**/ 654 655INTERNAL void rpc__schnauth_cn_fmt_client_req 656( 657 rpc_cn_assoc_sec_context_p_t assoc_sec, 658 rpc_cn_sec_context_p_t sec, 659 dce_pointer_t auth_value, 660 unsigned32 * auth_value_len, 661 dce_pointer_t * last_auth_pos ATTRIBUTE_UNUSED, 662 unsigned32 * auth_len_remain ATTRIBUTE_UNUSED, 663 unsigned32 old_server ATTRIBUTE_UNUSED, 664 unsigned32 * st 665) 666{ 667 rpc_cn_bind_auth_value_priv_t *priv_auth_value ATTRIBUTE_UNUSED; 668 rpc_cn_auth_info_t *auth_info; 669 rpc_schnauth_cn_info_t *schnauth_info; 670 struct schn_blob schn_creds; 671 672 CODING_ERROR (st); 673 674 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 675 ("(rpc__schnauth_cn_fmt_client_req)\n")); 676 677 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 678 ("(rpc__schnauth_cn_fmt_client_req) prot->%x level->%x key_id->%x assoc_uuid_crc->%x xmit_seq->%x recv_seq->%x\n", 679 rpc_c_authn_dce_dummy, 680 sec->sec_info->authn_level, 681 sec->sec_key_id, 682 assoc_sec->assoc_uuid_crc, 683 assoc_sec->assoc_next_snd_seq, 684 assoc_sec->assoc_next_rcv_seq)); 685 686#ifdef DEBUG 687 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, 688 RPC_C_CN_DBG_AUTH_FMT_CLIENT_REQ)) 689 { 690 *st = RPC_S_CN_DBG_AUTH_FAILURE; 691 return; 692 } 693#endif 694 695 auth_info = sec->sec_cn_info; 696 schnauth_info = (rpc_schnauth_cn_info_t*)auth_info; 697 698 schn_creds.base = (uint8*)auth_value; 699 schn_creds.len = 0; 700 701 schn_init_creds(&schnauth_info->sec_ctx, &schn_creds); 702 703 *auth_value_len = (unsigned32) schn_creds.len; 704 705 *st = rpc_s_ok; 706} 707 708/*****************************************************************************/ 709/* 710**++ 711** 712** ROUTINE NAME: rpc__schnauth_cn_fmt_srvr_resp 713** 714** SCOPE: INTERNAL - declared locally 715** 716** DESCRIPTION: 717** 718** This routine will format the auth_value field of 719** either an rpc_bind_ack or rpc_alter_context_response 720** PDU. The authentication protocol encoding in the 721** credentials field of auth_value should correspond 722** to the status returned from rpc__auth_cn_vfy_ 723** client_req() routine. This credentials field, when 724** decoded by rpc__auth_cn_vfy_srvr_resp(), should 725** result in the same error code being returned. If the 726** memory provided is not large enough an authentication 727** protocol specific error message will be encoded in 728** the credentials field indicating this error. This is 729** called from the server side association state machine. 730** 731** INPUTS: 732** 733** verify_st The status code returned by rpc__auth_cn_verify_ 734** client_req(). 735** assoc_sec A pointer to per-association security context 736** including association UUID CRC and sequence numbers. 737** sec A pointer to security context element which includes 738** the key ID, auth information rep and RPC auth 739** information rep. 740** req_auth_value A pointer to the auth_value field in the 741** rpc_bind or rpc_alter_context PDU authentication trailer. 742** req_auth_value_len The length, in bytes, of the 743** req_auth_value field. 744** auth_value A pointer to the auth_value field in the rpc_bind or 745** rpc_alter_context PDU authentication trailer. 746** 747** INPUTS/OUTPUTS: 748** 749** auth_value_len On input, the length, in bytes of the available space 750** for the auth_value field. On output, the length in 751** bytes used in encoding the auth_value field. Zero if 752** an error status is returned. 753** 754** OUTPUTS: none 755** 756** IMPLICIT INPUTS: none 757** 758** IMPLICIT OUTPUTS: none 759** 760** FUNCTION VALUE: none 761** 762** SIDE EFFECTS: none 763** 764**-- 765**/ 766 767INTERNAL void rpc__schnauth_cn_fmt_srvr_resp 768( 769 unsigned32 verify_st, 770 rpc_cn_assoc_sec_context_p_t assoc_sec, 771 rpc_cn_sec_context_p_t sec, 772 dce_pointer_t req_auth_value ATTRIBUTE_UNUSED, 773 unsigned32 req_auth_value_len ATTRIBUTE_UNUSED, 774 dce_pointer_t auth_value, 775 unsigned32 *auth_value_len 776) 777{ 778 rpc_cn_bind_auth_value_priv_t *priv_auth_value; 779 780 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 781 ("(rpc__schnauth_cn_fmt_srvr_resp)\n")); 782 783 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 784 ("(rpc__schnauth_cn_fmt_srvr_resp) prot->%x level->%x key_id->%x assoc_uuid_crc->%x xmit_seq->%x recv_seq->%x, vfy_client_st->%x\n", 785 rpc_c_authn_dce_dummy, 786 sec->sec_info->authn_level, 787 sec->sec_key_id, 788 assoc_sec->assoc_uuid_crc, 789 assoc_sec->assoc_next_snd_seq, 790 assoc_sec->assoc_next_rcv_seq, 791 verify_st)); 792 793#ifdef DEBUG 794 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, 795 RPC_C_CN_DBG_AUTH_FMT_SERVER_RESP)) 796 { 797 verify_st = RPC_S_CN_DBG_AUTH_FAILURE; 798 } 799#endif 800 801 assert (verify_st == rpc_s_ok); 802 assert (*auth_value_len >= RPC_CN_PKT_SIZEOF_BIND_AUTH_VAL); 803 *auth_value_len = RPC_CN_PKT_SIZEOF_BIND_AUTH_VAL; 804 805 priv_auth_value = (rpc_cn_bind_auth_value_priv_t *)auth_value; 806 priv_auth_value->assoc_uuid_crc = assoc_sec->assoc_uuid_crc; 807 priv_auth_value->sub_type = RPC_C_CN_DCE_SUB_TYPE; 808 priv_auth_value->checksum_length = 0; 809 priv_auth_value->cred_length = 0; 810} 811 812/*****************************************************************************/ 813/* 814**++ 815** 816** ROUTINE NAME: rpc__schnauth_cn_free_prot_info 817** 818** SCOPE: INTERNAL - declared locally 819** 820** DESCRIPTION: 821** 822** This routine will free an NCA Connection RPC auth 823** information rep. 824** 825** INPUTS: 826** 827** info A pointer to the auth information rep structure 828** containing RPC protocol indenpendent information. 829** 830** INPUTS/OUTPUTS: 831** 832** cn_info A pointer to the RPC auth information rep structure 833** containing NCA Connection specific 834** information. NULL on output. 835** 836** OUTPUTS: none 837** 838** IMPLICIT INPUTS: none 839** 840** IMPLICIT OUTPUTS: none 841** 842** FUNCTION VALUE: none 843** 844** SIDE EFFECTS: none 845** 846**-- 847**/ 848 849INTERNAL void rpc__schnauth_cn_free_prot_info 850( 851 rpc_auth_info_p_t info, 852 rpc_cn_auth_info_p_t *cn_info 853) 854{ 855 856 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 857 ("(rpc__schnauth_cn_free_prot_info)\n")); 858 859 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 860 ("(rpc__schnauth_cn_free_prot_info) prot->%x level->%x \n", 861 rpc_c_authn_dce_dummy, 862 info->authn_level)); 863 864#ifdef DEBUG 865 memset (*cn_info, 0, sizeof (rpc_cn_auth_info_t)); 866#endif 867 868 RPC_MEM_FREE (*cn_info, RPC_C_MEM_SCHNAUTH_CN_INFO); 869 *cn_info = NULL; 870} 871 872/*****************************************************************************/ 873/* 874**++ 875** 876** ROUTINE NAME: rpc__schnauth_cn_get_prot_info 877** 878** SCOPE: INTERNAL - declared locally 879** 880** DESCRIPTION: 881** 882** This routine will create and return an NCA Connection 883** RPC auth information rep. 884** 885** INPUTS: 886** 887** info A pointer to the auth information rep structure 888** containing RPC protocol indenpendent information. 889** 890** INPUTS/OUTPUTS: none 891** 892** OUTPUTS: 893** 894** cn_info A pointer to the RPC auth information rep structure 895** containing NCA Connection specific information. 896** st The return status of this routine. 897** 898** IMPLICIT INPUTS: none 899** 900** IMPLICIT OUTPUTS: none 901** 902** FUNCTION VALUE: none 903** 904** SIDE EFFECTS: none 905** 906**-- 907**/ 908 909INTERNAL void rpc__schnauth_cn_get_prot_info 910( 911 rpc_auth_info_p_t info, 912 rpc_cn_auth_info_p_t *cn_info, 913 unsigned32 *st 914) 915{ 916 rpc_schnauth_info_t *schnauth_info; 917 rpc_schnauth_cn_info_t *schnauth_cn_info; 918 919 CODING_ERROR (st); 920 921 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 922 ("(rpc__schnauth_cn_get_prot_info)\n")); 923 924 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 925 ("(rpc__schnauth_cn_get_prot_info) prot->%x level->%x \n", 926 rpc_c_authn_dce_dummy, 927 info->authn_level)); 928 929 schnauth_info = (rpc_schnauth_info_t*)info; 930 931#ifdef DEBUG 932 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, 933 RPC_C_CN_DBG_AUTH_GET_PROT_INFO)) 934 { 935 *st = RPC_S_CN_DBG_AUTH_FAILURE; 936 return; 937 } 938#endif 939 940 /* 941 * Allocate storage for a schnauth cn info structure from heap. 942 */ 943 RPC_MEM_ALLOC (schnauth_cn_info, 944 rpc_schnauth_cn_info_p_t, 945 sizeof (rpc_schnauth_cn_info_t), 946 RPC_C_MEM_SCHNAUTH_CN_INFO, 947 RPC_C_MEM_WAITOK); 948 949 /* 950 * Initialize it. 951 */ 952 memset (schnauth_cn_info, 0, sizeof(rpc_schnauth_cn_info_t)); 953 954 /* Set entry points to schannel functions */ 955 schnauth_cn_info->cn_info.cn_epv = &rpc_g_schnauth_cn_epv; 956 957 /* Copy available schannel init credentials - temporary hack */ 958 memcpy(&schnauth_cn_info->sec_ctx, 959 &schnauth_info->sec_ctx, 960 sizeof(struct schn_auth_ctx)); 961 962 *cn_info = (rpc_cn_auth_info_t *)schnauth_cn_info; 963 *st = rpc_s_ok; 964} 965 966/*****************************************************************************/ 967/* 968**++ 969** 970** ROUTINE NAME: rpc__schnauth_cn_pre_call 971** 972** SCOPE: INTERNAL - declared locally 973** 974** DESCRIPTION: 975** 976** This routine will format the auth_value field of 977** a call level PDU, namely an rpc_request, rpc_response 978** rpc_fault, rpc_remote_alert or rpc_orphaned PDU. It will 979** also format the auth_value field of the association level 980** rpc_shutdown PDU. This does 981** not include generating any checksums in the auth_value_field 982** or encrypting of data corresponding to the authentication 983** level. That will be done in the rpc__cn_auth_pre_send 984** routine. This is called on both client and server when a the 985** data structures and header template for a call is being set up. 986** 987** INPUTS: 988** 989** assoc_sec A pointer to per-association security context 990** including association UUID CRC and sequence numbers. 991** sec A pointer to security context element which includes 992** the key ID, auth information rep and RPC auth 993** information rep. 994** auth_value A pointer to the auth_value field in the rpc_bind or 995** rpc_alter_context PDU authentication trailer. 996** 997** INPUTS/OUTPUTS: 998** 999** auth_value_len On input, the lenght, in bytes of the available space 1000** for the auth_value field. On output, the lenght in 1001** bytes used in encoding the auth_value field. Zero if 1002** an error status is returned. 1003** 1004** OUTPUTS: 1005** 1006** st The return status of this routine. 1007** 1008** IMPLICIT INPUTS: none 1009** 1010** IMPLICIT OUTPUTS: none 1011** 1012** FUNCTION VALUE: none 1013** 1014** SIDE EFFECTS: none 1015** 1016**-- 1017**/ 1018 1019INTERNAL void rpc__schnauth_cn_pre_call 1020( 1021 rpc_cn_assoc_sec_context_p_t assoc_sec, 1022 rpc_cn_sec_context_p_t sec, 1023 dce_pointer_t auth_value ATTRIBUTE_UNUSED, 1024 unsigned32 *auth_value_len, 1025 unsigned32 *st 1026) 1027{ 1028 rpc_cn_auth_value_priv_t *priv_auth_value ATTRIBUTE_UNUSED; 1029 unsigned32 ptype; 1030 1031 CODING_ERROR(st); 1032 1033 ptype = sec->sec_info->authn_protocol; 1034 1035 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 1036 ("(rpc__schnauth_cn_pre_call)\n")); 1037 1038 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 1039 ("(rpc__schnauth_cn_pre_call) prot->%x level->%x key_id->%x assoc_uuid_crc->%x xmit_seq->%x recv_seq->%x\n", 1040 rpc_c_authn_dce_dummy, 1041 sec->sec_info->authn_level, 1042 sec->sec_key_id, 1043 assoc_sec->assoc_uuid_crc, 1044 assoc_sec->assoc_next_snd_seq, 1045 assoc_sec->assoc_next_rcv_seq)); 1046 1047#ifdef DEBUG 1048 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, 1049 RPC_C_CN_DBG_AUTH_PRE_CALL)) 1050 { 1051 *st = RPC_S_CN_DBG_AUTH_FAILURE; 1052 return; 1053 } 1054#endif 1055 1056 *auth_value_len = sizeof(rpc_cn_schnauth_tlr_t); 1057 1058 *st = rpc_s_ok; 1059} 1060 1061/* 1062 * Sign the packet prior to sending 1063 */ 1064 1065INTERNAL void rpc__schnauth_cn_wrap_pdu 1066( 1067 rpc_cn_assoc_sec_context_p_t assoc_sec ATTRIBUTE_UNUSED, 1068 rpc_cn_sec_context_p_t sec, 1069 rpc_socket_iovec_p_t iov, 1070 unsigned32 iovlen, 1071 rpc_socket_iovec_p_t out_iov, 1072 unsigned32 *st 1073) 1074{ 1075 const unsigned32 hdr_idx = 0; 1076 unsigned32 status = rpc_s_ok; 1077 rpc_schnauth_cn_info_p_t schn_auth; 1078 rpc_cn_common_hdr_p_t com_hdr; 1079 rpc_cn_auth_tlr_p_t com_tlr; 1080 rpc_cn_schnauth_tlr_p_t schn_tlr; 1081 unsigned32 tlr_idx; 1082 unsigned32 part_idx; 1083 unsigned_char_p_t pdu_blob; 1084 unsigned32 pdu_blob_len; 1085 unsigned16 packet_len, stub_len, auth_pad_len; 1086 dce_pointer_t base; 1087 uint32 sec_level; 1088 struct schn_auth_ctx *schn_ctx = NULL; 1089 struct schn_blob input_token, output_token; 1090 struct schn_tail tail; 1091 1092 schn_auth = (rpc_schnauth_cn_info_p_t)sec->sec_cn_info; 1093 schn_ctx = &schn_auth->sec_ctx; 1094 1095 tlr_idx = iovlen - 1; 1096 com_tlr = (rpc_cn_auth_tlr_p_t)(iov[tlr_idx].iov_base); 1097 schn_tlr = (rpc_cn_schnauth_tlr_p_t)(com_tlr->auth_value); 1098 com_hdr = (rpc_cn_common_hdr_p_t)(iov[hdr_idx].iov_base); 1099 1100 /* 1101 * Calculate header + stub length (including initial padding) 1102 */ 1103 1104 part_idx = hdr_idx; 1105 stub_len = 0; 1106 while (part_idx < tlr_idx) { 1107 stub_len += iov[part_idx++].iov_len; 1108 } 1109 1110 stub_len -= RPC_CN_PKT_SIZEOF_RQST_HDR; 1111 1112 /* ensure auth trailer padding */ 1113 auth_pad_len = stub_len % 0x0008; 1114 1115 /* 1116 * Allocate the entire packet in one piece 1117 */ 1118 packet_len = stub_len + (RPC_CN_PKT_SIZEOF_RQST_HDR + 1119 RPC_CN_PKT_SIZEOF_COM_AUTH_TLR + 1120 RPC_CN_PKT_SIZEOF_SCHNAUTH_TLR + 1121 auth_pad_len); 1122 1123 out_iov->iov_len = packet_len; 1124 RPC_MEM_ALLOC(out_iov->iov_base, 1125 dce_pointer_t, 1126 out_iov->iov_len, 1127 RPC_C_MEM_SCHNAUTH_INFO, 1128 RPC_C_MEM_WAITOK); 1129 if (out_iov->iov_base == NULL) { 1130 *st = rpc_s_no_memory; 1131 return; 1132 } 1133 1134 memset(out_iov->iov_base, 0, out_iov->iov_len); 1135 1136 /* Update packet and padding length after adding auth padding bytes */ 1137 com_hdr->frag_len += auth_pad_len; 1138 com_tlr->stub_pad_length += auth_pad_len; 1139 1140 /* 1141 * Create the packet blob including auth trailer padding 1142 */ 1143 1144 base = out_iov->iov_base; 1145 1146 /* header [idx = 0] */ 1147 memcpy(base, (void*)com_hdr, RPC_CN_PKT_SIZEOF_COMMON_HDR); 1148 base += RPC_CN_PKT_SIZEOF_COMMON_HDR; 1149 1150 /* stub [idx = 0] (the rest of it following header) */ 1151 memcpy(base, iov[hdr_idx].iov_base + RPC_CN_PKT_SIZEOF_COMMON_HDR, 1152 iov[hdr_idx].iov_len - RPC_CN_PKT_SIZEOF_COMMON_HDR); 1153 base += iov[hdr_idx].iov_len - RPC_CN_PKT_SIZEOF_COMMON_HDR; 1154 1155 /* stub [idx = 1 .. (tlr_idx - 1)] (if there is any remaining part) */ 1156 part_idx = 1; 1157 while (part_idx < tlr_idx) { 1158 /* This packet is longer than 2 parts (header+stub and trailer) 1159 so make sure we copy all of them */ 1160 memcpy(base, iov[part_idx].iov_base, iov[part_idx].iov_len); 1161 base += iov[part_idx].iov_len; 1162 part_idx++; 1163 } 1164 1165 /* auth padding */ 1166 base += auth_pad_len; 1167 1168 /* common trailer [idx = tlr_idx] */ 1169 memcpy(base, (void*)com_tlr, RPC_CN_PKT_SIZEOF_COM_AUTH_TLR); 1170 base += RPC_CN_PKT_SIZEOF_COM_AUTH_TLR; 1171 1172 /* schannel trailer */ 1173 memcpy(base, (void*)schn_tlr, RPC_CN_PKT_SIZEOF_SCHNAUTH_TLR); 1174 base += RPC_CN_PKT_SIZEOF_SCHNAUTH_TLR; 1175 1176 /* set PDU blob pointer and length */ 1177 pdu_blob = out_iov->iov_base + RPC_CN_PKT_SIZEOF_RQST_HDR; 1178 pdu_blob_len = stub_len + auth_pad_len; 1179 1180 /* set new location of common and schannel trailer */ 1181 com_tlr = (rpc_cn_auth_tlr_p_t)(pdu_blob + pdu_blob_len); 1182 schn_tlr = (rpc_cn_schnauth_tlr_p_t)(com_tlr->auth_value); 1183 1184 switch (com_tlr->auth_level) { 1185 case rpc_c_protect_level_pkt_integ: 1186 sec_level = SCHANNEL_SEC_LEVEL_INTEGRITY; 1187 break; 1188 1189 case rpc_c_protect_level_pkt_privacy: 1190 sec_level = SCHANNEL_SEC_LEVEL_PRIVACY; 1191 break; 1192 1193 default: 1194 *st = rpc_s_unsupported_protect_level; 1195 return; 1196 } 1197 1198 input_token.base = (uint8*)pdu_blob; 1199 input_token.len = pdu_blob_len; 1200 1201 status = schn_wrap(schn_ctx, sec_level, &input_token, &output_token, &tail); 1202 1203 memcpy(pdu_blob, output_token.base, output_token.len); 1204 1205 memcpy(schn_tlr->signature, tail.signature, 8); 1206 memcpy(schn_tlr->digest, tail.digest, 8); 1207 memcpy(schn_tlr->seq_number, tail.seq_number, 8); 1208 memcpy(schn_tlr->nonce, tail.nonce, 8); 1209 1210 schn_free_blob(&output_token); 1211 1212 *st = status; 1213} 1214 1215/*****************************************************************************/ 1216/* 1217**++ 1218** 1219** ROUTINE NAME: rpc__schnauth_cn_pre_send 1220** 1221** SCOPE: INTERNAL - declared locally 1222** 1223** DESCRIPTION: 1224** 1225** This routine will perform per-packet security 1226** processing on a packet before it is sent. This 1227** includes checksumming and encryption. 1228** 1229** Note that in some cases, the data is copied to 1230** a contiguous buffer for checksumming and 1231** encryption. In these cases, the contiguous 1232** iov element should be used instead of the original 1233** iovector. 1234** 1235** INPUTS: 1236** 1237** assoc_sec A pointer to per-association security context 1238** including association UUID CRC and sequence numbers. 1239** sec A pointer to security context element which includes 1240** the key ID, auth information rep and RPC auth 1241** information rep. 1242** iov A pointer to the iovector containing the PDU 1243** about to be sent. The appropriate per-packet security 1244** services will be applied to it. 1245** iovlen The length, in bytes, of the PDU. 1246** out_iov An iovector element. This iovector element 1247** will describe packet if the original iov 1248** had to be copied. If the original iov was 1249** copied, out_iov->base will be non-NULL. 1250** 1251** INPUTS/OUTPUTS: none 1252** 1253** OUTPUTS: 1254** 1255** st The return status of this routine. 1256** 1257** IMPLICIT INPUTS: none 1258** 1259** IMPLICIT OUTPUTS: none 1260** 1261** FUNCTION VALUE: none 1262** 1263** SIDE EFFECTS: none 1264** 1265**-- 1266**/ 1267 1268INTERNAL void rpc__schnauth_cn_pre_send 1269( 1270 rpc_cn_assoc_sec_context_p_t assoc_sec, 1271 rpc_cn_sec_context_p_t sec, 1272 rpc_socket_iovec_p_t iov, 1273 unsigned32 iovlen, 1274 rpc_socket_iovec_p_t out_iov, 1275 unsigned32 *st 1276) 1277{ 1278 unsigned32 ptype; 1279 1280 CODING_ERROR (st); 1281 1282 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 1283 ("(rpc__schnauth_cn_pre_send)\n")); 1284 1285 ptype = ((rpc_cn_common_hdr_t *)(iov[0].iov_base))->ptype; 1286 1287 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL, 1288 ("(rpc__schnauth_cn_pre_send) authn level->%x packet type->%x\n", sec->sec_info->authn_level, ptype)); 1289 1290 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 1291 ("(rpc__schnauth_cn_pre_send) prot->%x level->%x key_id->%x assoc_uuid_crc->%x xmit_seq->%x recv_seq->%x ptype->%x\n", 1292 rpc_c_authn_dce_dummy, 1293 sec->sec_info->authn_level, 1294 sec->sec_key_id, 1295 assoc_sec->assoc_uuid_crc, 1296 assoc_sec->assoc_next_snd_seq, 1297 assoc_sec->assoc_next_rcv_seq, 1298 ptype)); 1299#ifdef DEBUG 1300 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, 1301 RPC_C_CN_DBG_AUTH_PRE_SEND)) 1302 { 1303 *st = RPC_S_CN_DBG_AUTH_FAILURE; 1304 return; 1305 } 1306#endif 1307 1308 out_iov->iov_base = NULL; 1309 switch (ptype) 1310 { 1311 case RPC_C_CN_PKT_REQUEST: 1312 case RPC_C_CN_PKT_RESPONSE: 1313 { 1314 rpc__schnauth_cn_wrap_pdu(assoc_sec, sec, iov, iovlen, out_iov, st); 1315 return; 1316 } 1317 1318 case RPC_C_CN_PKT_FAULT: 1319 case RPC_C_CN_PKT_BIND: 1320 case RPC_C_CN_PKT_BIND_ACK: 1321 case RPC_C_CN_PKT_BIND_NAK: 1322 case RPC_C_CN_PKT_ALTER_CONTEXT: 1323 case RPC_C_CN_PKT_ALTER_CONTEXT_RESP: 1324 case RPC_C_CN_PKT_AUTH3: 1325 case RPC_C_CN_PKT_SHUTDOWN: 1326 case RPC_C_CN_PKT_REMOTE_ALERT: 1327 case RPC_C_CN_PKT_ORPHANED: 1328 default: 1329 { 1330 break; 1331 } 1332 } 1333 1334 *st = rpc_s_ok; 1335} 1336 1337INTERNAL void rpc__schnauth_cn_unwrap_pdu 1338( 1339 rpc_cn_assoc_sec_context_p_t assoc_sec ATTRIBUTE_UNUSED, 1340 rpc_cn_sec_context_p_t sec, 1341 rpc_cn_common_hdr_p_t pdu, 1342 unsigned32 pdu_len, 1343 unsigned32 cred_len, 1344 rpc_cn_auth_tlr_p_t auth_tlr, 1345 boolean32 unpack_ints, 1346 unsigned32 *st 1347) 1348{ 1349 unsigned32 status = rpc_s_ok; 1350 rpc_schnauth_cn_info_p_t schn_auth; 1351 rpc_cn_schnauth_tlr_p_t schn_tlr; 1352 unsigned32 sec_level; 1353 struct schn_auth_ctx *sec_ctx; 1354 struct schn_blob input_token, output_token; 1355 struct schn_tail tail; 1356 unsigned16 auth_len = 0; 1357 1358 schn_auth = (rpc_schnauth_cn_info_p_t)sec->sec_cn_info; 1359 schn_tlr = (rpc_cn_schnauth_tlr_p_t)auth_tlr->auth_value; 1360 1361 switch (auth_tlr->auth_level) { 1362 case rpc_c_protect_level_pkt_integ: 1363 sec_level = SCHANNEL_SEC_LEVEL_INTEGRITY; 1364 break; 1365 1366 case rpc_c_protect_level_pkt_privacy: 1367 sec_level = SCHANNEL_SEC_LEVEL_PRIVACY; 1368 break; 1369 1370 default: 1371 *st = rpc_s_unsupported_protect_level; 1372 return; 1373 } 1374 1375 sec_ctx = &schn_auth->sec_ctx; 1376 1377 auth_len = RPC_CN_PKT_AUTH_LEN((rpc_cn_packet_p_t)pdu); 1378 if (unpack_ints) { 1379 SWAB_INPLACE_16(auth_len); 1380 } 1381 1382 input_token.base = (uint8*)(pdu) + RPC_CN_PKT_SIZEOF_RESP_HDR; 1383 input_token.len = pdu_len - (RPC_CN_PKT_SIZEOF_RESP_HDR + 1384 RPC_CN_PKT_SIZEOF_COM_AUTH_TLR + 1385 auth_len); 1386 1387 output_token.base = NULL; 1388 output_token.len = 0; 1389 1390 memcpy(tail.signature, schn_tlr->signature, 8); 1391 memcpy(tail.seq_number, schn_tlr->seq_number, 8); 1392 memcpy(tail.digest, schn_tlr->digest, 8); 1393 memcpy(tail.nonce, schn_tlr->nonce, 8); 1394 1395 status = schn_unwrap(sec_ctx, sec_level, &input_token, &output_token, 1396 &tail); 1397 1398 memcpy(input_token.base, output_token.base, output_token.len); 1399 schn_free_blob(&output_token); 1400 1401 *st = status; 1402} 1403 1404/*****************************************************************************/ 1405/* 1406**++ 1407** 1408** ROUTINE NAME: rpc__schnauth_cn_recv_check 1409** 1410** SCOPE: INTERNAL - declared locally 1411** 1412** DESCRIPTION: 1413** 1414** This routine will perform per-packet security 1415** processing on a packet after it is received. This 1416** includes decryption and verification of checksums. 1417** 1418** INPUTS: 1419** 1420** assoc_sec A pointer to per-association security context 1421** including association UUID CRC and sequence numbers. 1422** sec A pointer to security context element which includes 1423** the key ID, auth information rep and RPC auth 1424** information rep. 1425** pdu A pointer to the PDU about to be sent. The appropriate 1426** per-packet security services will be applied to it. 1427** pdu_len The length, in bytes, of the PDU. 1428** cred_len The length, in bytes, of the credentials. 1429** auth_tlr A pointer to the auth trailer. 1430** unpack_ints A boolean indicating whether the integer rep 1431** of fields in the pdu need to be adjusted for 1432** endian differences. 1433** 1434** INPUTS/OUTPUTS: none 1435** 1436** OUTPUTS: 1437** 1438** st The return status of this routine. 1439** 1440** IMPLICIT INPUTS: none 1441** 1442** IMPLICIT OUTPUTS: none 1443** 1444** FUNCTION VALUE: none 1445** 1446** SIDE EFFECTS: none 1447** 1448**-- 1449**/ 1450 1451INTERNAL void rpc__schnauth_cn_recv_check 1452( 1453 rpc_cn_assoc_sec_context_p_t assoc_sec, 1454 rpc_cn_sec_context_p_t sec, 1455 rpc_cn_common_hdr_p_t pdu, 1456 unsigned32 pdu_len ATTRIBUTE_UNUSED, 1457 unsigned32 cred_len ATTRIBUTE_UNUSED, 1458 rpc_cn_auth_tlr_p_t auth_tlr, 1459 boolean32 unpack_ints ATTRIBUTE_UNUSED, 1460 unsigned32 *st 1461) 1462{ 1463 rpc_cn_auth_value_priv_t *priv_auth_value; 1464 unsigned32 ptype; 1465 unsigned32 authn_level; 1466 unsigned32 assoc_uuid_crc; 1467 1468 CODING_ERROR (st); 1469 1470 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 1471 ("(rpc__schnauth_cn_recv_check)\n")); 1472 1473 ptype = pdu->ptype; 1474 priv_auth_value = (rpc_cn_auth_value_priv_t *)(auth_tlr->auth_value); 1475 authn_level = auth_tlr->auth_level; 1476 if (ptype == RPC_C_CN_PKT_BIND) 1477 { 1478 assoc_uuid_crc = ((rpc_cn_bind_auth_value_priv_t *)priv_auth_value)->assoc_uuid_crc; 1479 } 1480 else 1481 { 1482 assoc_uuid_crc = assoc_sec->assoc_uuid_crc; 1483 } 1484 1485 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL, 1486 ("(rpc__schnauth_cn_recv_check) authn level->%x packet type->%x\n", authn_level, ptype)); 1487 1488 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 1489 ("(rpc__schnauth_cn_recv_check) prot->%x level->%x key_id->%x assoc_uuid_crc->%x xmit_seq->%x recv_seq->%x ptype->%x\n", 1490 rpc_c_authn_dce_dummy, 1491 authn_level, 1492 sec->sec_key_id, 1493 assoc_uuid_crc, 1494 assoc_sec->assoc_next_snd_seq, 1495 assoc_sec->assoc_next_rcv_seq, 1496 ptype)); 1497 1498#ifdef DEBUG 1499 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, 1500 RPC_C_CN_DBG_AUTH_RECV_CHECK)) 1501 { 1502 *st = RPC_S_CN_DBG_AUTH_FAILURE; 1503 return; 1504 } 1505#endif 1506 1507 switch (ptype) 1508 { 1509 case RPC_C_CN_PKT_REQUEST: 1510 case RPC_C_CN_PKT_RESPONSE: 1511 { 1512 rpc__schnauth_cn_unwrap_pdu(assoc_sec, sec, pdu, pdu_len, cred_len, 1513 auth_tlr, unpack_ints, st); 1514 return; 1515 } 1516 case RPC_C_CN_PKT_FAULT: 1517 case RPC_C_CN_PKT_BIND: 1518 case RPC_C_CN_PKT_BIND_ACK: 1519 case RPC_C_CN_PKT_BIND_NAK: 1520 case RPC_C_CN_PKT_ALTER_CONTEXT: 1521 case RPC_C_CN_PKT_ALTER_CONTEXT_RESP: 1522 case RPC_C_CN_PKT_AUTH3: 1523 case RPC_C_CN_PKT_SHUTDOWN: 1524 case RPC_C_CN_PKT_REMOTE_ALERT: 1525 case RPC_C_CN_PKT_ORPHANED: 1526 default: 1527 { 1528 break; 1529 } 1530 } 1531 1532 *st = rpc_s_ok; 1533} 1534 1535/*****************************************************************************/ 1536/* 1537**++ 1538** 1539** ROUTINE NAME: rpc__schnauth_cn_tlr_uuid_crc 1540** 1541** SCOPE: INTERNAL - declared locally 1542** 1543** DESCRIPTION: 1544** 1545** This routine will locate and return the association 1546** UUID CRC contained in the auth_value field of an 1547** authentication trailer of an rpc_bind, rpc_bind_ack, 1548** rpc_alter_context or rpc_alter_context_response PDU. 1549** 1550** INPUTS: 1551** 1552** auth_value A pointer to the auth_value field in an authentication 1553** trailer. 1554** auth_value_len The length, in bytes, of the auth_value field. 1555** 1556** INPUTS/OUTPUTS: none 1557** 1558** OUTPUTS: 1559** 1560** assoc_uuid_crc The association UUID CRC contained in the auth_value 1561** field. 1562** 1563** IMPLICIT INPUTS: none 1564** 1565** IMPLICIT OUTPUTS: none 1566** 1567** FUNCTION VALUE: none 1568** 1569** SIDE EFFECTS: none 1570** 1571**-- 1572**/ 1573 1574INTERNAL void rpc__schnauth_cn_tlr_uuid_crc 1575( 1576 dce_pointer_t auth_value, 1577 unsigned32 auth_value_len, 1578 unsigned32 *uuid_crc 1579) 1580{ 1581 rpc_cn_bind_auth_value_priv_t *priv_auth_value; 1582 1583 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 1584 ("(rpc__schnauth_cn_tlr_uuid_crc)\n")); 1585 1586 assert (auth_value_len >= RPC_CN_PKT_SIZEOF_BIND_AUTH_VAL); 1587 priv_auth_value = (rpc_cn_bind_auth_value_priv_t *)auth_value; 1588 *uuid_crc = priv_auth_value->assoc_uuid_crc; 1589 1590 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL, 1591 ("(rpc__schnauth_cn_tlr_uuid_crc) assoc_uuid_crc->%x\n", *uuid_crc)); 1592} 1593 1594/*****************************************************************************/ 1595/* 1596**++ 1597** 1598** ROUTINE NAME: rpc__schnauth_cn_tlr_unpack 1599** 1600** SCOPE: INTERNAL - declared locally 1601** 1602** DESCRIPTION: 1603** 1604** This routine will byte swap all the appropriate fields 1605** of the the auth_value field of an authentication 1606** trailer. It will also convert any characters from 1607** the remote representation into the local, for example, 1608** ASCII to EBCDIC. 1609** 1610** INPUTS: 1611** 1612** auth_value_len The length, in bytes, of the auth_value field. 1613** packed_drep The packed Networ Data Representation, (see NCA RPC 1614** RunTime Extensions Specification Version OSF TX1.0.9 1615** pre 1003 for details), of the remote machine. 1616** 1617** INPUTS/OUTPUTS: 1618** 1619** pkt_p A pointer to the entire packet. 1620** 1621** OUTPUTS: none 1622** 1623** IMPLICIT INPUTS: none 1624** 1625** IMPLICIT OUTPUTS: none 1626** 1627** FUNCTION VALUE: none 1628** 1629** SIDE EFFECTS: none 1630** 1631**-- 1632**/ 1633 1634INTERNAL void rpc__schnauth_cn_tlr_unpack 1635( 1636 rpc_cn_packet_p_t pkt_p ATTRIBUTE_UNUSED, 1637 unsigned32 auth_value_len ATTRIBUTE_UNUSED, 1638 unsigned8 *packed_drep ATTRIBUTE_UNUSED 1639) 1640{ 1641 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 1642 ("(rpc__schnauth_cn_tlr_unpack)\n")); 1643} 1644 1645/*****************************************************************************/ 1646/* 1647**++ 1648** 1649** ROUTINE NAME: rpc__schnauth_cn_vfy_client_req 1650** 1651** SCOPE: INTERNAL - declared locally 1652** 1653** DESCRIPTION: 1654** 1655** This routine will decode the auth_value field of 1656** either an rpc_bind or rpc_alter_context PDU. Any 1657** error encountered while authenticating the client 1658** will result in an error status return. The contents 1659** of the credentials field includes the authorization 1660** data. This is called from the server side association 1661** state machine. Note that upon successful return 1662** the auth information rep will contain the client's 1663** authorization protocol and data. 1664** 1665** INPUTS: 1666** 1667** assoc_sec A pointer to per-association security context 1668** including association UUID CRC and sequence numbers. 1669** sec A pointer to security context element which includes 1670** the key ID, auth information rep and RPC auth 1671** information rep. 1672** auth_value A pointer to the auth_value field in the rpc_bind or 1673** rpc_alter_context PDU authentication trailer. 1674** auth_value_len The length, in bytes, of auth_value. 1675** 1676** INPUTS/OUTPUTS: none 1677** 1678** OUTPUTS: 1679** 1680** st The return status of this routine. 1681** 1682** IMPLICIT INPUTS: none 1683** 1684** IMPLICIT OUTPUTS: none 1685** 1686** FUNCTION VALUE: none 1687** 1688** SIDE EFFECTS: none 1689** 1690**-- 1691**/ 1692 1693INTERNAL void rpc__schnauth_cn_vfy_client_req 1694( 1695 rpc_cn_assoc_sec_context_p_t assoc_sec, 1696 rpc_cn_sec_context_p_t sec, 1697 dce_pointer_t auth_value, 1698 unsigned32 auth_value_len ATTRIBUTE_UNUSED, 1699 unsigned32 old_client ATTRIBUTE_UNUSED, 1700 unsigned32 *st 1701) 1702{ 1703 rpc_cn_bind_auth_value_priv_t *priv_auth_value; 1704 1705 CODING_ERROR (st); 1706 1707 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 1708 ("(rpc__schnauth_cn_vfy_client_req)\n")); 1709 1710 priv_auth_value = (rpc_cn_bind_auth_value_priv_t *)auth_value; 1711 1712 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 1713 ("(rpc__schnauth_cn_vfy_client_req) prot->%x level->%x key_id->%x assoc_uuid_crc->%x xmit_seq->%x recv_seq->%x\n", 1714 rpc_c_authn_dce_dummy, 1715 sec->sec_info->authn_level, 1716 sec->sec_key_id, 1717 assoc_sec->assoc_uuid_crc, 1718 assoc_sec->assoc_next_snd_seq, 1719 assoc_sec->assoc_next_rcv_seq)); 1720 1721#ifdef DEBUG 1722 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, 1723 RPC_C_CN_DBG_AUTH_VFY_CLIENT_REQ)) 1724 { 1725 *st = RPC_S_CN_DBG_AUTH_FAILURE; 1726 return; 1727 } 1728#endif 1729 1730 *st = rpc_s_ok; 1731} 1732 1733/*****************************************************************************/ 1734/* 1735**++ 1736** 1737** ROUTINE NAME: rpc__schnauth_cn_vfy_srvr_resp 1738** 1739** SCOPE: INTERNAL - declared locally 1740** 1741** DESCRIPTION: 1742** 1743** This routine will decode auth_value field either an 1744** rpc_bind_ack or rpc_alter_context_response PDU. If the 1745** credentials field of the auth_value field contains an 1746** authentication protocol specific encoding of an error 1747** this will be returned as an error status code. This is 1748** called from the client side association state machine. 1749** Note that upon successful return the auth information 1750** rep will contain the client's authorization protocol 1751** and data. 1752** 1753** INPUTS: 1754** 1755** assoc_sec A pointer to per-association security context 1756** including association UUID CRC and sequence numbers. 1757** sec A pointer to security context element which includes 1758** the key ID, auth information rep and RPC auth 1759** information rep. 1760** auth_value A pointer to the auth_value field in the rpc_bind or 1761** rpc_alter_context PDU authentication trailer. 1762** auth_value_len The length, in bytes, of auth_value. 1763** 1764** INPUTS/OUTPUTS: none 1765** 1766** OUTPUTS: 1767** 1768** st The return status of this routine. 1769** 1770** IMPLICIT INPUTS: none 1771** 1772** IMPLICIT OUTPUTS: none 1773** 1774** FUNCTION VALUE: none 1775** 1776** SIDE EFFECTS: none 1777** 1778**-- 1779**/ 1780 1781INTERNAL void rpc__schnauth_cn_vfy_srvr_resp 1782( 1783 rpc_cn_assoc_sec_context_p_t assoc_sec, 1784 rpc_cn_sec_context_p_t sec, 1785 dce_pointer_t auth_value ATTRIBUTE_UNUSED, 1786 unsigned32 auth_value_len ATTRIBUTE_UNUSED, 1787 unsigned32 *st 1788) 1789{ 1790 CODING_ERROR (st); 1791 1792 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 1793 ("(rpc__schnauth_cn_vfy_srvr_resp)\n")); 1794 1795 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 1796 ("(rpc__schnauth_cn_vfy_server_resp) prot->%x level->%x key_id->%x assoc_uuid_crc->%x xmit_seq->%x recv_seq->%x\n", 1797 rpc_c_authn_dce_dummy, 1798 sec->sec_info->authn_level, 1799 sec->sec_key_id, 1800 assoc_sec->assoc_uuid_crc, 1801 assoc_sec->assoc_next_snd_seq, 1802 assoc_sec->assoc_next_rcv_seq)); 1803 1804#ifdef DEBUG 1805 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, 1806 RPC_C_CN_DBG_AUTH_VFY_SERVER_RESP)) 1807 { 1808 *st = RPC_S_CN_DBG_AUTH_FAILURE; 1809 return; 1810 } 1811#endif 1812 1813 *st = rpc_s_ok; 1814} 1815 1816PRIVATE rpc_protocol_id_t rpc__schnauth_cn_init 1817( 1818 rpc_auth_rpc_prot_epv_p_t *epv, 1819 unsigned32 *st 1820) 1821{ 1822 CODING_ERROR (st); 1823 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 1824 ("(rpc__schnauth_cn_init)\n")); 1825 1826 *epv = (rpc_auth_rpc_prot_epv_p_t) (&rpc_g_schnauth_cn_epv); 1827 *st = rpc_s_ok; 1828 return (RPC_C_PROTOCOL_ID_NCACN); 1829} 1830