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** 79** NAME 80** 81** cnsassm.c 82** 83** FACILITY: 84** 85** Remote Procedure Call (RPC) 86** 87** ABSTRACT: 88** 89** NCA Connection (cn) Server (s) Association (as) State Machine (sm). 90** 91** 92*/ 93 94 95#include <commonp.h> /* Common declarations for all RPC runtime */ 96#include <com.h> /* Common communications services */ 97#include <comprot.h> /* Common protocol services */ 98#include <ndrglob.h> /* Network Data Representation syntax global defs */ 99#include <ndrp.h> /* Network Data Representation syntax defs */ 100#include <cnp.h> /* NCA Connection private declarations */ 101#include <cnid.h> /* NCA Connection local ID service */ 102#include <cnnet.h> /* NCA Connection network service */ 103#include <cnpkt.h> /* NCA Connection protocol header */ 104#include <cnassoc.h> /* NCA Connection association services */ 105#include <comcthd.h> /* Externals for Call Thread sub-component */ 106#include <cncall.h> /* NCA connection call service */ 107#include <cnsm.h> /* NCA Connection state machine declarations */ 108#include <cnfbuf.h> /* NCA Connection fragment buffer service */ 109#include <cnassm.h> /* NCA Connection association state machine */ 110 111/******************************************************************************/ 112/* 113 * Global Definitions 114 */ 115GLOBAL const char *rpc_g_cn_assoc_server_events [] = 116{ 117 "INDICATION", 118 "ABORT_REQ", 119 "REJ_RESP", 120 "ALT_CONT_IND", 121 "NO_CONN_IND", 122 "ALT_CONT_RESP", 123 "AUTH3_IND", 124 "AUTH3_ACK", 125 "AUTH3_NACK", 126 "ALLOC_REQ", 127 "DEALLOC_REQ", 128 "SHUTDOWN_REQ", 129 "LOCAL_ERROR", 130 "ACC_RESP", 131 "ASSOC_COMPLETE" 132}; 133 134GLOBAL const char *rpc_g_cn_assoc_server_states [] = 135{ 136 "CLOSED", 137 "REQUESTED", 138 "AUTH3_WAIT", 139 "AUTH3", 140 "OPEN", 141 "ASSOC_WAIT" 142}; 143 144 145/******************************************************************************/ 146/* 147 * Local defines 148 */ 149/******************************************************************************/ 150 151 152/******************************************************************************/ 153/* 154 * Internal function prototyes 155 */ 156/******************************************************************************/ 157 158INTERNAL void rpc__cn_assoc_process_auth_tlr ( 159 rpc_cn_assoc_p_t /*assoc*/, 160 rpc_cn_packet_p_t /*req_header*/, 161 unsigned32 /*req_header_size*/, 162 rpc_cn_packet_p_t /*resp_header*/, 163 unsigned32 * /*header_size*/, 164 unsigned32 * /*auth_len*/, 165 rpc_cn_sec_context_p_t * /*sec_context*/, 166 boolean old_client, 167 unsigned32 * /*st*/); 168 169INTERNAL void send_frag_resp_pdu ( 170 rpc_cn_assoc_p_t /*assoc*/, 171 rpc_cn_fragbuf_p_t /*fragbuf*/, 172 rpc_cn_packet_p_t /*req_header*/); 173 174INTERNAL unsigned32 save_sec_fragment ( 175 rpc_cn_assoc_p_t /*assoc*/, 176 rpc_cn_packet_p_t /*header*/); 177 178 179/***********************************************************************/ 180/* 181 * S E R V E R A S S O C P R E D I C A T E T A B L E 182 * 183 * 184 * The predicates. All predicates except those noted below are described 185 * in the NCA Connection architecture spec. 186 * As a performance enhancement, 187 * we have revamped many predicate routines as macros and have absorbed 188 * the predicates into the actions. Thus, there is no longer a need 189 * for the predicate table; the predicate declarations too, are 190 * modified. 191 */ 192/* #define AUTHENT3_PRED 0 193 * #define ACTIVE_PRED 1 194 * #define LASTBIND_PRED 2 195 */ 196/* 197 * The predicate routine prototypes. 198 */ 199INTERNAL unsigned8 authent3_pred_rtn ( 200 dce_pointer_t /*spc_struct*/, 201 dce_pointer_t /*event_param*/) ATTRIBUTE_UNUSED; 202 203INTERNAL unsigned8 active_pred_rtn ( 204 dce_pointer_t /*spc_struct*/, 205 dce_pointer_t /*event_param*/) ATTRIBUTE_UNUSED; 206 207INTERNAL unsigned8 lastbindfrag_pred_rtn ( 208 dce_pointer_t /*spc_struct*/, 209 dce_pointer_t /*event_param*/); 210 211 212/***********************************************************************/ 213/* 214 * S E R V E R A S S O C A C T I O N T A B L E 215 * 216 * 217 * The actions. All actions except those noted below are described 218 * in the NCA Connection architecture spec. 219 */ 220#define ACCEPT_ASSOC 0 221#define REJECT_ASSOC 1 222#define ADD_ASSOC_TO_GRP 2 223#define REM_ASSOC_FROM_GRP 3 224#define DO_ALTER_CONT_REQ 4 225#define SEND_ALTER_CONT_RESP 5 226#define DO_AUTHENT3 6 227#define DO_ASSOC_REQ 7 228#define SEND_SHUTDOWN_REQ 8 229#define INCR_ACTIVE 9 230#define DECR_ACTIVE 10 231#define ABORT_ASSOC 11 232#define MARK_ASSOC 12 233#define CANCEL_CALLS 13 234#define ACCEPT_ADD 14 235#define REM_MARK_ABORT 15 236#define REM_MARK_CANCEL 16 237#define INCR_DO_ALTER 17 238#define SEND_DECR 18 239#define MARK_ABORT 19 240#define REM_MARK_ABORT_CAN 20 241#define PROTOCOL_ERROR 21 242#define DO_ASSOC_WAIT 22 243#define DO_ASSOC 23 244 245/* 246 * The action routine prototypes. 247 */ 248INTERNAL unsigned32 accept_assoc_action_rtn ( 249 dce_pointer_t /*spc_struct*/, 250 dce_pointer_t /*event_param*/, 251 dce_pointer_t /*sm*/); 252 253INTERNAL unsigned32 reject_assoc_action_rtn ( 254 dce_pointer_t /*spc_struct*/, 255 dce_pointer_t /*event_param*/, 256 dce_pointer_t /*sm*/); 257 258INTERNAL unsigned32 add_assoc_to_grp_action_rtn ( 259 dce_pointer_t /*spc_struct*/, 260 dce_pointer_t /*event_param*/, 261 dce_pointer_t /*sm*/); 262 263INTERNAL unsigned32 rem_assoc_from_grp_action_rtn ( 264 dce_pointer_t /*spc_struct*/, 265 dce_pointer_t /*event_param*/, 266 dce_pointer_t /*sm*/); 267 268INTERNAL unsigned32 do_alter_cont_req_action_rtn ( 269 dce_pointer_t /*spc_struct*/, 270 dce_pointer_t /*event_param*/, 271 dce_pointer_t /*sm*/); 272 273INTERNAL unsigned32 send_alter_cont_resp_action_rtn ( 274 dce_pointer_t /*spc_struct*/, 275 dce_pointer_t /*event_param*/, 276 dce_pointer_t /*sm*/); 277 278INTERNAL unsigned32 do_authent3_action_rtn ( 279 dce_pointer_t /*spc_struct*/, 280 dce_pointer_t /*event_param*/, 281 dce_pointer_t /*sm*/); 282 283INTERNAL unsigned32 do_assoc_req_action_rtn ( 284 dce_pointer_t /*spc_struct*/, 285 dce_pointer_t /*event_param*/, 286 dce_pointer_t /*sm*/); 287 288INTERNAL unsigned32 send_shutdown_req_action_rtn ( 289 dce_pointer_t /*spc_struct*/, 290 dce_pointer_t /*event_param*/, 291 dce_pointer_t /*sm*/); 292 293INTERNAL unsigned32 incr_active_action_rtn ( 294 dce_pointer_t /*spc_struct*/, 295 dce_pointer_t /*event_param*/, 296 dce_pointer_t /*sm*/); 297 298INTERNAL unsigned32 decr_active_action_rtn ( 299 dce_pointer_t /*spc_struct*/, 300 dce_pointer_t /*event_param*/, 301 dce_pointer_t /*sm*/); 302 303INTERNAL unsigned32 abort_assoc_action_rtn ( 304 dce_pointer_t /*spc_struct*/, 305 dce_pointer_t /*event_param*/, 306 dce_pointer_t /*sm*/); 307 308INTERNAL unsigned32 mark_assoc_action_rtn ( 309 dce_pointer_t /*spc_struct*/, 310 dce_pointer_t /*event_param*/, 311 dce_pointer_t /*sm*/); 312 313INTERNAL unsigned32 cancel_calls_action_rtn ( 314 dce_pointer_t /*spc_struct*/, 315 dce_pointer_t /*event_param*/, 316 dce_pointer_t /*sm*/); 317 318INTERNAL unsigned32 accept_add_action_rtn ( 319 dce_pointer_t /*spc_struct*/, 320 dce_pointer_t /*event_param*/, 321 dce_pointer_t /*sm*/); 322 323INTERNAL unsigned32 rem_mark_abort_action_rtn ( 324 dce_pointer_t /*spc_struct*/, 325 dce_pointer_t /*event_param*/, 326 dce_pointer_t /*sm*/); 327 328INTERNAL unsigned32 rem_mark_cancel_action_rtn ( 329 dce_pointer_t /*spc_struct*/, 330 dce_pointer_t /*event_param*/, 331 dce_pointer_t /*sm*/); 332 333INTERNAL unsigned32 incr_do_alter_action_rtn ( 334 dce_pointer_t /*spc_struct*/, 335 dce_pointer_t /*event_param*/, 336 dce_pointer_t /*sm*/); 337 338INTERNAL unsigned32 send_decr_action_rtn ( 339 dce_pointer_t /*spc_struct*/, 340 dce_pointer_t /*event_param*/, 341 dce_pointer_t /*sm*/); 342 343INTERNAL unsigned32 mark_abort_action_rtn ( 344 dce_pointer_t /*spc_struct*/, 345 dce_pointer_t /*event_param*/, 346 dce_pointer_t /*sm*/); 347 348INTERNAL unsigned32 rem_mark_abort_can_action_rtn ( 349 dce_pointer_t /*spc_struct*/, 350 dce_pointer_t /*event_param*/, 351 dce_pointer_t /*sm*/); 352 353INTERNAL unsigned32 do_assoc_wait_action_rtn ( 354 dce_pointer_t /*spc_struct*/, 355 dce_pointer_t /*event_param*/, 356 dce_pointer_t /*sm*/); 357 358INTERNAL unsigned32 do_assoc_action_rtn ( 359 dce_pointer_t /*spc_struct*/, 360 dce_pointer_t /*event_param*/, 361 dce_pointer_t /*sm*/); 362 363/* 364 * The action table itself. 365 */ 366GLOBAL rpc_cn_sm_action_fn_t rpc_g_cn_server_assoc_act_tbl [] = 367{ 368 accept_assoc_action_rtn, 369 reject_assoc_action_rtn, 370 add_assoc_to_grp_action_rtn, 371 rem_assoc_from_grp_action_rtn, 372 do_alter_cont_req_action_rtn, 373 send_alter_cont_resp_action_rtn, 374 do_authent3_action_rtn, 375 do_assoc_req_action_rtn, 376 send_shutdown_req_action_rtn, 377 incr_active_action_rtn, 378 decr_active_action_rtn, 379 abort_assoc_action_rtn, 380 mark_assoc_action_rtn, 381 cancel_calls_action_rtn, 382 accept_add_action_rtn, 383 rem_mark_abort_action_rtn, 384 rem_mark_cancel_action_rtn, 385 incr_do_alter_action_rtn, 386 send_decr_action_rtn, 387 mark_abort_action_rtn, 388 rem_mark_abort_can_action_rtn, 389 rpc__cn_assoc_sm_protocol_error, 390 do_assoc_wait_action_rtn, 391 do_assoc_action_rtn 392}; 393 394 395/***********************************************************************/ 396/* 397 * S E R V E R A S S O C S T A T E T A B L E 398 * 399 * 400 * C L O S E D _ S T A T E 401 * 402 * state 0 - closed. The association is unknown to the server. 403 */ 404INTERNAL rpc_cn_sm_state_tbl_entry_t closed_state = 405{ 406 /* event 0 - ind */ 407 {DO_ASSOC}, 408 409 /* event 1 - abort_req */ 410 {RPC_C_CLIENT_ASSOC_CLOSED}, 411 412 /* event 2 - reject_resp */ 413 {RPC_C_CLIENT_ASSOC_CLOSED}, 414 415 /* event 3 - alter_context_ind */ 416 {RPC_C_CLIENT_ASSOC_CLOSED}, 417 418 /* event 4 - no_conn_ind */ 419 {RPC_C_CLIENT_ASSOC_CLOSED}, 420 421 /* event 5 - alter_context_resp */ 422 {RPC_C_CLIENT_ASSOC_CLOSED}, 423 424 /* event 6 - auth3_ind */ 425 {RPC_C_CLIENT_ASSOC_CLOSED}, 426 427 /* event 7 - auth3_ack */ 428 {RPC_C_CLIENT_ASSOC_CLOSED}, 429 430 /* event 8 - auth3_nack */ 431 {RPC_C_CLIENT_ASSOC_CLOSED}, 432 433 /* event 9 - allocate_req */ 434 {RPC_C_CLIENT_ASSOC_CLOSED}, 435 436 /* event 10 - deallocate_req */ 437 {RPC_C_CLIENT_ASSOC_CLOSED}, 438 439 /* event 11 - shutdown_req */ 440 {RPC_C_CLIENT_ASSOC_CLOSED}, 441 442 /* event 12 - local_error */ 443 {RPC_C_CLIENT_ASSOC_CLOSED}, 444 445 /* event 13 - accept_resp */ 446 {RPC_C_CLIENT_ASSOC_CLOSED}, 447 448 /* event 14 - assoc_complete_resp */ 449 ILLEGAL_TRANSITION 450}; 451 452 453/* 454 * R E Q U E S T E D _ S T A T E 455 * 456 * state 1 - requested_wait. The server has received a complete rpc_bind PDU 457 * and is processing it. 458 */ 459INTERNAL rpc_cn_sm_state_tbl_entry_t requested_state = 460{ 461 /* event 0 - ind */ 462 ILLEGAL_TRANSITION, 463 464 /* event 1 - abort_req */ 465 {ABORT_ASSOC}, 466 467 /* event 2 - reject_resp */ 468 {REJECT_ASSOC}, 469 470 /* event 3 - alter_context_ind */ 471 ILLEGAL_TRANSITION, 472 473 /* event 4 - no_conn_ind */ 474 {MARK_ASSOC}, 475 476 /* event 5 - alter_context_resp */ 477 ILLEGAL_TRANSITION, 478 479 /* event 6 - auth3_ind */ 480 ILLEGAL_TRANSITION, 481 482 /* event 7 - auth3_ack */ 483 ILLEGAL_TRANSITION, 484 485 /* event 8 - auth3_nack */ 486 ILLEGAL_TRANSITION, 487 488 /* event 9 - allocate_req */ 489 ILLEGAL_TRANSITION, 490 491 /* event 10 - deallocate_req */ 492 ILLEGAL_TRANSITION, 493 494 /* event 11 - shutdown_req */ 495 {RPC_C_SERVER_ASSOC_REQUESTED}, 496 497 /* event 12 - local_error */ 498 {MARK_ABORT}, 499 500 /* event 13 - accept_resp */ 501 {ACCEPT_ADD}, 502 503 /* event 14 - assoc_complete_resp */ 504 ILLEGAL_TRANSITION 505}; 506 507 508/* 509 * A U T H 3 _ W A I T _ S T A T E 510 * 511 * state 2 - auth3_wait. Wait for the 3rd leg of the optional 3-way 512 * authentication handshake. 513 */ 514INTERNAL rpc_cn_sm_state_tbl_entry_t auth3_wait_state = 515{ 516 /* event 0 - ind */ 517 ILLEGAL_TRANSITION, 518 519 /* event 1 - abort_req */ 520 {ABORT_ASSOC}, 521 522 /* event 2 - reject_resp */ 523 ILLEGAL_TRANSITION, 524 525 /* event 3 - alter_context_ind */ 526 {DO_ALTER_CONT_REQ}, 527 528 /* event 4 - no_conn_ind */ 529 {MARK_ASSOC}, 530// {REM_MARK_CANCEL}, 531 532 /* event 5 - alter_context_resp */ 533 ILLEGAL_TRANSITION, 534 535 /* event 6 - auth3_ind */ 536 {DO_AUTHENT3}, 537 538 /* event 7 - auth3_ack */ 539 ILLEGAL_TRANSITION, 540 541 /* event 8 - auth3_nack */ 542 ILLEGAL_TRANSITION, 543 544 /* event 9 - allocate_req */ 545 ILLEGAL_TRANSITION, 546 547 /* event 10 - deallocate_req */ 548 ILLEGAL_TRANSITION, 549 550 /* event 11 - shutdown_req */ 551 {SEND_SHUTDOWN_REQ}, 552 553 /* event 12 - local_error */ 554 {MARK_ABORT}, 555 556 /* event 13 - accept_resp */ 557 ILLEGAL_TRANSITION, 558 559 /* event 14 - assoc_complete_resp */ 560 ILLEGAL_TRANSITION 561}; 562 563 564/* 565 * A U T H 3 _ S T A T E 566 * 567 * state 3 - auth3_wait. Process the 3rd leg of the optional 3-way 568 * authentication handshake. 569 */ 570INTERNAL rpc_cn_sm_state_tbl_entry_t auth3_state = 571{ 572 /* event 0 - ind */ 573 ILLEGAL_TRANSITION, 574 575 /* event 1 - abort_req */ 576 {ABORT_ASSOC}, 577 578 /* event 2 - reject_resp */ 579 ILLEGAL_TRANSITION, 580 581 /* event 3 - alter_context_ind */ 582 ILLEGAL_TRANSITION, 583 584 /* event 4 - no_conn_ind */ 585 {MARK_ASSOC}, 586// {REM_MARK_CANCEL}, 587 588 /* event 5 - alter_context_resp */ 589 {SEND_ALTER_CONT_RESP}, 590 591 /* event 6 - auth3_ind */ 592 ILLEGAL_TRANSITION, 593 594 /* event 7 - auth3_ack */ 595 {ADD_ASSOC_TO_GRP}, 596 597 /* event 8 - auth3_nack */ 598 {ABORT_ASSOC}, 599 600 /* event 9 - allocate_req */ 601 ILLEGAL_TRANSITION, 602 603 /* event 10 - deallocate_req */ 604 ILLEGAL_TRANSITION, 605 606 /* event 11 - shutdown_req */ 607 {SEND_SHUTDOWN_REQ}, 608 609 /* event 12 - local_error */ 610 {MARK_ABORT}, 611 612 /* event 13 - accept_resp */ 613 ILLEGAL_TRANSITION, 614 615 /* event 14 - assoc_complete_resp */ 616 ILLEGAL_TRANSITION 617}; 618 619 620/* 621 * O P E N _ S T A T E 622 * 623 * state 4 - open. A successul association has been established. One 624 * or more presentation syntaxes have successfully been negotiated. 625 */ 626INTERNAL rpc_cn_sm_state_tbl_entry_t open_state = 627{ 628 /* event 0 - ind */ 629 /* call DO_ASSOC so we can send a bind_nack */ 630 {DO_ASSOC}, 631 632 /* event 1 - abort_req */ 633 {REM_MARK_ABORT}, 634 635 /* event 2 - reject_resp */ 636 ILLEGAL_TRANSITION, 637 638 /* event 3 - alter_context_ind */ 639 {INCR_DO_ALTER}, 640 641 /* event 4 - no_conn_ind */ 642 {REM_MARK_CANCEL}, 643 644 /* event 5 - alter_context_resp */ 645 {SEND_DECR}, 646 647 /* event 6 - auth3_ind */ 648 ILLEGAL_TRANSITION, 649 650 /* event 7 - auth3_ack */ 651 ILLEGAL_TRANSITION, 652 653 /* event 8 - auth3_nack */ 654 ILLEGAL_TRANSITION, 655 656 /* event 9 - allocate_req */ 657 {INCR_ACTIVE}, 658 659 /* event 10 - deallocate_req */ 660 {DECR_ACTIVE}, 661 662 /* event 11 - shutdown_req */ 663 {SEND_SHUTDOWN_REQ}, 664 665 /* event 12 - local_error */ 666 {REM_MARK_ABORT_CAN}, 667 668 /* event 13 - accept_resp */ 669 ILLEGAL_TRANSITION, 670 671 /* event 14 - assoc_complete_resp */ 672 ILLEGAL_TRANSITION 673}; 674 675 676/* 677 * A S S O C _ W A I T 678 * 679 * state 5 - assoc_wait. The server has received at least one rpc_bind PDU 680 * packet already and is processing another. 681 */ 682INTERNAL rpc_cn_sm_state_tbl_entry_t assoc_wait_state = 683{ 684 /* event 0 - ind */ 685 {DO_ASSOC_WAIT}, 686 687 /* event 1 - abort_req */ 688 {ABORT_ASSOC}, 689 690 /* event 2 - reject_resp */ 691 {REJECT_ASSOC}, 692 693 /* event 3 - alter_context_ind */ 694 ILLEGAL_TRANSITION, 695 696 /* event 4 - no_conn_ind */ 697 {MARK_ASSOC}, 698 699 /* event 5 - alter_context_resp */ 700 ILLEGAL_TRANSITION, 701 702 /* event 6 - auth3_ind */ 703 ILLEGAL_TRANSITION, 704 705 /* event 7 - auth3_ack */ 706 ILLEGAL_TRANSITION, 707 708 /* event 8 - auth3_nack */ 709 ILLEGAL_TRANSITION, 710 711 /* event 9 - allocate_req */ 712 ILLEGAL_TRANSITION, 713 714 /* event 10 - deallocate_req */ 715 ILLEGAL_TRANSITION, 716 717 /* event 11 - shutdown_req */ 718 {RPC_C_SERVER_ASSOC_REQUESTED}, 719 720 /* event 12 - local_error */ 721 {MARK_ABORT}, 722 723 /* event 13 - accept_resp */ 724 {ACCEPT_ADD}, 725 726 /* event 14 - assoc_complete_resp */ 727 {DO_ASSOC_REQ} 728}; 729 730 731/* 732 * The state table containing the action routines. 733 */ 734GLOBAL rpc_cn_sm_state_entry_p_t rpc_g_cn_server_assoc_sm [] = 735{ 736 closed_state, /* state 0 - closed */ 737 requested_state, /* state 1 - requested */ 738 auth3_wait_state, /* state 2 - auth3_wait */ 739 auth3_state, /* state 3 - auth3 */ 740 open_state, /* state 4 - open */ 741 assoc_wait_state /* state 5 - assoc_wait */ 742}; 743 744 745/***********************************************************************/ 746/* 747 * 748 * S E R V E R A S S O C P R E D I C A T E R O U T I N E S 749 * 750 */ 751/* 752**++ 753** 754** ROUTINE NAME: authent3_pred_rtn 755** 756** SCOPE: INTERNAL - declared locally 757** 758** DESCRIPTION: 759** 760** Returns 1 if the association request requires an optional 3-leg 761** authentication handshake. Returns 0 if if didn't. 762** 763** INPUTS: 764** 765** spc_struct The association. Note that this is passed in as 766** the special structure which is passed to the 767** state machine event evaluation routine. 768** 769** event_param The fragment buffer containing the rpc_bind 770** PDU. The special event related 771** parameter which is passed to the state 772** machine event evaluation routine. 773** 774** INPUTS/OUTPUTS: none 775** 776** OUTPUTS: none 777** 778** IMPLICIT INPUTS: none 779** 780** IMPLICIT OUTPUTS: none 781** 782** FUNCTION VALUE: 0 if no 3-leg authentication handshake is 783** being done. 784** 1 if a 3-leg authentication handshake is 785** being done. 786** 787** SIDE EFFECTS: none 788** 789**-- 790**/ 791 792INTERNAL unsigned8 authent3_pred_rtn 793( 794 dce_pointer_t spc_struct ATTRIBUTE_UNUSED, 795 dce_pointer_t event_param 796) 797{ 798 rpc_cn_packet_t *header; 799 rpc_cn_auth_tlr_t *tlr; 800 boolean32 three_way; 801 unsigned32 st; 802 unsigned32 authn_protocol; 803 804 RPC_CN_DBG_RTN_PRINTF(SERVER authent3_pred_rtn); 805 806 /* 807 * The event parameter is a pointer to the fragbuf containing 808 * the rpc_bind PDU. 809 */ 810 header = (rpc_cn_packet_t *) ((rpc_cn_fragbuf_t *)event_param)->data_p; 811 812 /* 813 * The authentication length in the header indicates whether the 814 * PDU contains an authentication trailer. 815 */ 816 if (RPC_CN_PKT_AUTH_LEN (header) == 0) 817 { 818 return (0); 819 } 820 else 821 { 822 tlr = RPC_CN_PKT_AUTH_TLR (header, RPC_CN_PKT_FRAG_LEN (header)); 823 authn_protocol = RPC_CN_AUTH_CVT_ID_WIRE_TO_API (tlr->auth_type, &st); 824 if (st == rpc_s_ok) 825 { 826 RPC_CN_AUTH_THREE_WAY (authn_protocol, three_way); 827 if (three_way) 828 { 829 return (1); 830 } 831 else 832 { 833 return (0); 834 } 835 } 836 else 837 { 838 return (0); 839 } 840 } 841} 842 843 844/* 845**++ 846** 847** MACRO NAME: AUTHENT3_PRED 848** 849** SCOPE: INTERNAL 850** 851** DESCRIPTION: 852** This a macro version of the authent3_pred_rtn predicate routine. 853** We added the macro version to avoid overhead associated with calling 854** the predicate function from within the action routines. 855** Macro set status to 1 if the association request requires an optional 3-leg 856** authentication handshake, otherwise, sets status to 0. 857** 858** 859** INPUTS: 860** 861** spc_struct The association group. Note that this is passed in as 862** the special structure which is passed to the 863** state machine event evaluation routine. 864** 865** event_param The fragment buffer containing the rpc_bind 866** PDU. The special event related 867** parameter which is passed to the state 868** machine event evaluation routine. 869** 870** status Instead of returning a value from the macro, 871** write the value calculated in the macro to 872** status. Status' scope includes the routine 873** calling the macro. Check status in the calling 874** routine to determine next state and in cases, 875** flow through the action routine. 876** 877** tlr Struct rpc_cn_auth_tlr_t. Declared in the 878** calling routine. Used in RPC_CN_AUTH_THREE_WAY. 879** 880** st Unsigned32. Used internally to RPC_CN_AUTH_ 881** THREE_WAY. 882** 883** three_way Boolean32. Used internally to RPC_CN_AUTH_ 884** THREE_WAY. 885** 886** INPUTS/OUTPUTS: none 887** 888** OUTPUTS: 889** 890** status See explanation above. 891** 892** IMPLICIT INPUTS: none 893** 894** IMPLICIT OUTPUTS: none 895** 896** FUNCTION VALUE: 0 if no 3-leg authentication handshake is 897** being done. 898** 1 if a 3-leg authentication handshake is 899** being done. 900** 901** SIDE EFFECTS: none 902** 903**-- 904**/ 905#define AUTHENT3_PRED(spc_struct, event_param, status, tlr, st, three_way)\ 906{\ 907 RPC_CN_DBG_RTN_PRINTF(SERVER authent3_pred_macro);\ 908 header = (rpc_cn_packet_t *) ((rpc_cn_fragbuf_t *)event_param)->data_p;\ 909 if (RPC_CN_PKT_AUTH_LEN (header) == 0)\ 910 {\ 911 status = 0;\ 912 }\ 913 else\ 914 {\ 915 rpc_authn_protocol_id_t authn_protocol; \ 916 tlr = RPC_CN_PKT_AUTH_TLR (header, RPC_CN_PKT_FRAG_LEN (header));\ 917 authn_protocol = RPC_CN_AUTH_CVT_ID_WIRE_TO_API (tlr->auth_type, &st); \ 918 if (st == rpc_s_ok) \ 919 {\ 920 RPC_CN_AUTH_THREE_WAY (authn_protocol, three_way);\ 921 if (three_way)\ 922 {\ 923 status = 1;\ 924 }\ 925 else\ 926 {\ 927 status = 0;\ 928 }\ 929 }\ 930 else\ 931 {\ 932 status = 0;\ 933 }\ 934 }\ 935} 936 937 938/* 939**++ 940** 941** ROUTINE NAME: active_pred_rtn 942** 943** SCOPE: INTERNAL - declared locally 944** 945** DESCRIPTION: 946** 947** Determines whether the association is currently in use. Unless 948** the concurrent multiplexing option has been mutually selected, only one 949** call and its related callbacks, or an alter-context request, may use 950** an association at one time. This predicate is manupulated via the 951** incr_active and decr_active action routines which manipulate a 952** reference counter, and is ready by the association group policy 953** mechanisms. A zero reference count implies the predicate value is 954** false, otherwise it is true. 955** 956** INPUTS: 957** 958** spc_struct The association. Note that this is passed in as 959** the special structure which is passed to the 960** state machine event evaluation routine. 961** 962** event_param The special event related parameter which is 963** passed to the state machine event evaluation 964** routine. 965** This input argument is ignored. 966** 967** INPUTS/OUTPUTS: none 968** 969** OUTPUTS: none 970** 971** IMPLICIT INPUTS: none 972** 973** IMPLICIT OUTPUTS: none 974** 975** FUNCTION VALUE: 0 if association reference counter is 0 976** 1 if association reference counter is non-zero 977** 978** SIDE EFFECTS: none 979** 980**-- 981**/ 982 983INTERNAL unsigned8 active_pred_rtn 984( 985 dce_pointer_t spc_struct, 986 dce_pointer_t event_param ATTRIBUTE_UNUSED 987) 988{ 989 rpc_cn_assoc_t *assoc; 990 991 RPC_CN_DBG_RTN_PRINTF(SERVER active_pred_rtn); 992 993 /* 994 * The special structure is a pointer to the association. 995 */ 996 assoc = (rpc_cn_assoc_t *) spc_struct; 997 998 /* 999 * A reference counter in the association indicates whether the 1000 * association is currently active. 1001 */ 1002 if (assoc->assoc_ref_count == 0) 1003 { 1004 return (0); 1005 } 1006 else 1007 { 1008 return (1); 1009 } 1010} 1011 1012 1013/* 1014**++ 1015** 1016** ROUTINE NAME: lastbindfrag_pred_rtn 1017** 1018** SCOPE: INTERNAL - declared locally 1019** 1020** DESCRIPTION: 1021** 1022** Returns 1 if the association request has is last_frag flag bit set 1023** Returns 0 if if doesn't. 1024** 1025** INPUTS: 1026** 1027** spc_struct The association. Note that this is passed in as 1028** the special structure which is passed to the 1029** state machine event evaluation routine. 1030** 1031** event_param The fragment buffer containing the rpc_bind 1032** PDU. The special event related 1033** parameter which is passed to the state 1034** machine event evaluation routine. 1035** 1036** INPUTS/OUTPUTS: none 1037** 1038** OUTPUTS: none 1039** 1040** IMPLICIT INPUTS: none 1041** 1042** IMPLICIT OUTPUTS: none 1043** 1044** FUNCTION VALUE: 0 If the rpc_bind PDU last_frag flag it is NOT set 1045** 1 If the rpc_bind PDU last_frag flag bit is set 1046** 1047** SIDE EFFECTS: none 1048** 1049**-- 1050**/ 1051 1052INTERNAL unsigned8 lastbindfrag_pred_rtn (spc_struct, event_param) 1053 1054dce_pointer_t spc_struct ATTRIBUTE_UNUSED; 1055dce_pointer_t event_param; 1056 1057{ 1058 rpc_cn_packet_t *header; 1059 1060 RPC_CN_DBG_RTN_PRINTF(SERVER lastbindfrag_pred_rtn); 1061 1062 /* 1063 * The event parameter is a pointer to the fragbuf containing 1064 * the rpc_bind PDU. 1065 */ 1066 header = (rpc_cn_packet_t *) ((rpc_cn_fragbuf_t *)event_param)->data_p; 1067 1068 /* 1069 * This is the last packet we are going to get if last_frag flag is set 1070 * or we are talking to an old client. 1071 */ 1072 if ((RPC_CN_PKT_FLAGS (header) & RPC_C_CN_FLAGS_LAST_FRAG) || 1073 (RPC_CN_PKT_VERS_MINOR (header) < RPC_C_CN_PROTO_VERS_MINOR)) 1074 { 1075 return (1); 1076 } 1077 else 1078 { 1079 return(0); 1080 } 1081} 1082 1083 1084/***********************************************************************/ 1085/* 1086 * S E R V E R A S S O C A C T I O N R O U T I N E S 1087 */ 1088/* 1089**++ 1090** 1091** ROUTINE NAME: accept_assoc_action_rtn 1092** 1093** SCOPE: INTERNAL - declared locally 1094** 1095** DESCRIPTION: 1096** 1097** Action routine to send an rpc_bind_ack association accept PDU 1098** to the client, including the secondary address, association 1099** group id and, optionally, authentication information. 1100** 1101** If we have authentication information, we may send more than one 1102** PDU to the client containing the pieces of the auth info. 1103** 1104** INPUTS: 1105** 1106** spc_struct The association. Note that this is passed in as 1107** the special structure which is passed to the 1108** state machine event evaluation routine. 1109** 1110** event_param The fragment buffer containing the rpc_bind_ack PDU. 1111** This is passed in as the 1112** special event related parameter which was 1113** passed to the state machine evaluation routine. 1114** 1115** INPUTS/OUTPUTS: 1116** 1117** sm The control block from the event evaluation 1118** routine. Input is the current state and 1119** event for the control block. SM is not changed 1120** here but is passed in to avoid compile warnings 1121** from rpc__cn_sm_eval_event(). 1122** 1123** OUTPUTS: none 1124** 1125** IMPLICIT INPUTS: none 1126** 1127** IMPLICIT OUTPUTS: none 1128** 1129** FUNCTION VALUE: completion status returned in 1130** assoc->assoc_status. 1131** 1132** SIDE EFFECTS: none 1133** 1134**-- 1135**/ 1136 1137INTERNAL unsigned32 accept_assoc_action_rtn 1138( 1139 dce_pointer_t spc_struct, 1140 dce_pointer_t event_param, 1141 dce_pointer_t sm ATTRIBUTE_UNUSED 1142) 1143{ 1144 rpc_cn_assoc_t *assoc; 1145 rpc_cn_packet_t *req_header; 1146 rpc_cn_fragbuf_t *fragbuf; 1147 1148 RPC_CN_DBG_RTN_PRINTF(SERVER accept_assoc_action_rtn); 1149 1150 /* 1151 * The special structure is a pointer to the association. 1152 */ 1153 assoc = (rpc_cn_assoc_t *) spc_struct; 1154 1155 /* 1156 * The event parameter is the fragbuf containing 1157 * the rpc_bind_ack PDU and the security context element. 1158 */ 1159 fragbuf = (rpc_cn_fragbuf_t *) event_param; 1160 req_header = (rpc_cn_packet_t *) fragbuf->data_p; 1161 1162 /* 1163 * If we have security, we may have to break it apart. 1164 */ 1165 if (RPC_CN_PKT_AUTH_TLR_PRESENT (req_header)) 1166 { 1167 send_frag_resp_pdu(assoc, fragbuf, req_header); 1168 } 1169 else 1170 { 1171 /* 1172 * Just send the PDU and free the fragbuf. 1173 */ 1174 rpc__cn_assoc_send_fragbuf (assoc, 1175 fragbuf, 1176 assoc->security.assoc_current_sec_context, 1177 true, 1178 &(assoc->assoc_status)); 1179 } 1180 RPC_CN_ASSOC_CHECK_ST (assoc, &(assoc->assoc_status)); 1181 return (assoc->assoc_status); 1182} 1183 1184 1185/* 1186**++ 1187** 1188** ROUTINE NAME: reject_assoc_action_rtn 1189** 1190** SCOPE: INTERNAL - declared locally 1191** 1192** DESCRIPTION: 1193** 1194** Action routine to send an rpc_bind_nack association reject PDU 1195** to the client. The client will abort the connection after 1196** receiving the association reject. 1197** 1198** INPUTS: 1199** 1200** spc_struct The association. Note that this is passed in as 1201** the special structure which is passed to the 1202** state machine event evaluation routine. 1203** 1204** event_param The fragment buffer containing the rpc_bind_nack PDU. 1205** This is passed in as the 1206** special event related parameter which was 1207** passed to the state machine evaluation routine. 1208** 1209** INPUTS/OUTPUTS: 1210** 1211** sm The control block from the event evaluation 1212** routine. Input is the current state and 1213** event for the control block. Output is the 1214** next state or updated current state, for the 1215** control block. 1216** 1217** OUTPUTS: none 1218** 1219** IMPLICIT INPUTS: none 1220** 1221** IMPLICIT OUTPUTS: none 1222** 1223** FUNCTION VALUE: completion status, one of: 1224** rpc_s_ok 1225** 1226** SIDE EFFECTS: none 1227** 1228**-- 1229**/ 1230 1231INTERNAL unsigned32 reject_assoc_action_rtn 1232( 1233 dce_pointer_t spc_struct, 1234 dce_pointer_t event_param, 1235 dce_pointer_t sm 1236) 1237{ 1238 rpc_cn_assoc_t *assoc; 1239 rpc_cn_fragbuf_t *fragbuf; 1240 rpc_cn_sm_ctlblk_t *sm_p; 1241 1242 RPC_CN_DBG_RTN_PRINTF(SERVER reject_assoc_action_rtn); 1243 1244 /* 1245 * The special structure is a pointer to the association. 1246 */ 1247 assoc = (rpc_cn_assoc_t *) spc_struct; 1248 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 1249 1250 /* 1251 * The event parameter is a pointer to the fragbuf containing 1252 * the rpc_bind_nack PDU. 1253 */ 1254 fragbuf = (rpc_cn_fragbuf_t *) event_param; 1255 1256 /* 1257 * Now actually send the PDU and free the fragbuf. 1258 */ 1259 rpc__cn_assoc_send_fragbuf (assoc, 1260 fragbuf, 1261 NULL, 1262 true, 1263 &(assoc->assoc_status)); 1264 RPC_CN_ASSOC_CHECK_ST (assoc, &(assoc->assoc_status)); 1265 1266 sm_p->cur_state = RPC_C_SERVER_ASSOC_CLOSED; 1267 return (assoc->assoc_status); 1268} 1269 1270 1271/* 1272**++ 1273** 1274** ROUTINE NAME: add_assoc_to_grp_action_rtn 1275** 1276** SCOPE: INTERNAL - declared locally 1277** 1278** DESCRIPTION: 1279** 1280** Action routine add the current association to the association 1281** group. 1282** 1283** INPUTS: 1284** 1285** spc_struct The association. Note that this is passed in as 1286** the special structure which is passed to the 1287** state machine event evaluation routine. 1288** 1289** event_param This is passed in as the 1290** special event related parameter which was 1291** passed to the state machine evaluation routine. 1292** This argument is ignored. 1293** 1294** INPUTS/OUTPUTS: 1295** 1296** sm The control block from the event evaluation 1297** routine. Input is the current state and 1298** event for the control block. Output is the 1299** next state or updated current state, for the 1300** control block. 1301** 1302** OUTPUTS: none 1303** 1304** IMPLICIT INPUTS: none 1305** 1306** IMPLICIT OUTPUTS: none 1307** 1308** FUNCTION VALUE: completion status, one of: 1309** rpc_s_ok 1310** 1311** SIDE EFFECTS: none 1312** 1313**-- 1314**/ 1315 1316INTERNAL unsigned32 add_assoc_to_grp_action_rtn 1317( 1318 dce_pointer_t spc_struct, 1319 dce_pointer_t event_param ATTRIBUTE_UNUSED, 1320 dce_pointer_t sm 1321) 1322{ 1323 rpc_cn_assoc_t *assoc; 1324 rpc_cn_sm_ctlblk_t *sm_p; 1325 1326 RPC_CN_DBG_RTN_PRINTF(SERVER add_assoc_to_grp_action_rtn); 1327 1328 /* 1329 * The special structure is a pointer to the association. 1330 */ 1331 assoc = (rpc_cn_assoc_t *) spc_struct; 1332 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 1333 1334 /* 1335 * Add the association to the group. 1336 */ 1337 rpc__cn_assoc_grp_add_assoc (assoc->assoc_grp_id, 1338 assoc); 1339 1340 sm_p->cur_state = RPC_C_SERVER_ASSOC_OPEN; 1341 return (assoc->assoc_status); 1342} 1343 1344 1345/* 1346**++ 1347** 1348** ROUTINE NAME: rem_assoc_from_grp_action_rtn 1349** 1350** SCOPE: INTERNAL - declared locally 1351** 1352** DESCRIPTION: 1353** 1354** Action routine to remove the current association from the 1355** association group. 1356** 1357** INPUTS: 1358** 1359** spc_struct The association. Note that this is passed in as 1360** the special structure which is passed to the 1361** state machine event evaluation routine. 1362** 1363** event_param This is passed in as the 1364** special event related parameter which was 1365** passed to the state machine evaluation routine. 1366** This input argument is ignored. 1367** 1368** INPUTS/OUTPUTS: 1369** 1370** sm The control block from the event evaluation 1371** routine. Input is the current state and 1372** event for the control block. SM is not changed 1373** here but is passed in to avoid compile warnings 1374** from rpc__cn_sm_eval_event(). 1375** 1376** OUTPUTS: none 1377** 1378** IMPLICIT INPUTS: none 1379** 1380** IMPLICIT OUTPUTS: none 1381** 1382** FUNCTION VALUE: completion status, one of: 1383** rpc_s_ok 1384** 1385** SIDE EFFECTS: none 1386** 1387**-- 1388**/ 1389 1390INTERNAL unsigned32 rem_assoc_from_grp_action_rtn 1391( 1392 dce_pointer_t spc_struct, 1393 dce_pointer_t event_param ATTRIBUTE_UNUSED, 1394 dce_pointer_t sm ATTRIBUTE_UNUSED 1395) 1396{ 1397 rpc_cn_assoc_t *assoc; 1398 1399 RPC_CN_DBG_RTN_PRINTF(SERVER rem_assoc_from_grp_action_rtn); 1400 1401 /* 1402 * The special structure is a pointer to the association. 1403 */ 1404 assoc = (rpc_cn_assoc_t *) spc_struct; 1405 1406 /* 1407 * Remove the association from the group. 1408 */ 1409 rpc__cn_assoc_grp_rem_assoc (assoc->assoc_grp_id, 1410 assoc); 1411 1412 return (assoc->assoc_status); 1413} 1414 1415 1416/* 1417**++ 1418** 1419** ROUTINE NAME: do_alter_cont_req_action_rtn 1420** 1421** SCOPE: INTERNAL - declared locally 1422** 1423** DESCRIPTION: 1424** 1425** Action routine to process the alter context negotiation request. 1426** 1427** INPUTS: 1428** 1429** spc_struct The association. Note that this is passed in as 1430** the special structure which is passed to the 1431** state machine event evaluation routine. 1432** 1433** event_param The fragbuf containing the alter_context PDU. 1434** This is passed in as the 1435** special event related parameter which was 1436** passed to the state machine evaluation routine. 1437** 1438** INPUTS/OUTPUTS: 1439** 1440** sm The control block from the event evaluation 1441** routine. Input is the current state and 1442** event for the control block. SM is not changed 1443** here but is passed in to avoid compile warnings 1444** from rpc__cn_sm_eval_event(). 1445** 1446** OUTPUTS: none 1447** 1448** IMPLICIT INPUTS: none 1449** 1450** IMPLICIT OUTPUTS: none 1451** 1452** FUNCTION VALUE: completion status, one of: 1453** rpc_s_ok 1454** 1455** SIDE EFFECTS: none 1456** 1457**-- 1458**/ 1459 1460INTERNAL unsigned32 do_alter_cont_req_action_rtn 1461( 1462 dce_pointer_t spc_struct, 1463 dce_pointer_t event_param, 1464 dce_pointer_t sm ATTRIBUTE_UNUSED 1465) 1466{ 1467 rpc_cn_assoc_t *assoc; 1468 rpc_cn_sm_ctlblk_t *sm_p; 1469 rpc_cn_packet_t *req_header; 1470 rpc_cn_packet_t *resp_header; 1471 rpc_cn_pres_cont_list_t *pres_cont_list; 1472 rpc_cn_pres_result_list_t *pres_result_list; 1473 unsigned32 result_list_len; 1474 unsigned32 header_size; 1475 unsigned32 auth_len; 1476 rpc_cn_fragbuf_t *fragbuf; 1477 rpc_cn_sm_event_entry_t event; 1478 rpc_cn_port_any_t *sec_addr; 1479 boolean old_client; 1480 unsigned32 status; 1481 unsigned8 *end_of_pkt; /* ptr to 1 byte past end of packet */ 1482 unsigned8 *end_ptr; 1483 1484 RPC_CN_DBG_RTN_PRINTF(SERVER do_alter_cont_req_action_rtn); 1485 1486 /* 1487 * The special structure is a pointer to the association. 1488 */ 1489 assoc = (rpc_cn_assoc_t *) spc_struct; 1490 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 1491 old_client = (assoc->assoc_vers_minor <= RPC_C_CN_PROTO_VERS_COMPAT); 1492 1493 /* 1494 * The event parameter is a pointer to the fragbuf containing 1495 * the rpc_alter_context PDU. 1496 */ 1497 req_header = (rpc_cn_packet_t *) ((rpc_cn_fragbuf_t *)event_param)->data_p; 1498 end_of_pkt = (unsigned8 *) req_header; 1499 end_of_pkt += ((rpc_cn_fragbuf_t *)event_param)->data_size; 1500 1501 if (!(RPC_CN_PKT_FLAGS(req_header) & RPC_C_CN_FLAGS_LAST_FRAG) && 1502 !(RPC_CN_PKT_VERS_MINOR (req_header) < RPC_C_CN_PROTO_VERS_MINOR)) 1503 { 1504 /* 1505 * Alter context is not complete (and we are not talking to 1506 * an old client who doesn't set the last_frag flag). 1507 * Save the security fragment, and wait for the next one. 1508 */ 1509 return (save_sec_fragment(assoc, req_header)); 1510 } 1511 /* 1512 * Make sure if we have processed previous alter_context PDU's 1513 * that we append the piece from the last packet in the sequence. 1514 */ 1515 if (assoc->security.auth_buffer_info.auth_buffer != NULL) 1516 { 1517 status = save_sec_fragment(assoc, req_header); 1518 if (status != rpc_s_ok) 1519 return (status); 1520 } 1521 1522 /* 1523 * Mark the current security context as NULL. This will be 1524 * filled in when we have successfully established a security 1525 * context. It will be used by the action routine which actually 1526 * sends the rpc_bind_ack PDU. 1527 */ 1528 assoc->security.assoc_current_sec_context = NULL; 1529 1530 /* 1531 * Allocate a large fragbuf for the response PDU. We won't expend any 1532 * more time here trying to optimize to allocate a small fragbuf. 1533 */ 1534 RPC_CN_FRAGBUF_ALLOC (fragbuf, rpc_g_cn_large_frag_size, &(assoc->assoc_status)); 1535 resp_header = (rpc_cn_packet_t *) (fragbuf->data_p); 1536 header_size = RPC_CN_PKT_SIZEOF_ALT_CTX_R_HDR; 1537 1538 sec_addr = (rpc_cn_port_any_t *) 1539 ((unsigned8 *)(resp_header) + header_size); 1540 1541 /* changed from 1 to 0 - lukeh May 2003 */ 1542 sec_addr->length = 0; 1543 sec_addr->s[0] = '\0'; 1544 1545 header_size = (2 + header_size + 3) & ~0x03; 1546 1547 pres_cont_list = (rpc_cn_pres_cont_list_t *) 1548 ((unsigned8 *) req_header + RPC_CN_PKT_SIZEOF_ALT_CTX_HDR); 1549 1550 /* points to end of pkt whether n_context_elem is 0 or not */ 1551 end_ptr = (unsigned8 *) &pres_cont_list->pres_cont_elem[pres_cont_list->n_context_elem]; 1552 1553 if ( ((unsigned8 *) pres_cont_list < (unsigned8 *) req_header) || 1554 ((unsigned8 *) pres_cont_list > (unsigned8 *) end_of_pkt) || 1555 ((unsigned8 *) end_ptr < (unsigned8 *) req_header) || 1556 ((unsigned8 *) end_ptr > (unsigned8 *) end_of_pkt) ) 1557 { 1558 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 1559 ("invalid pres_cont_list in alter context\n")); 1560 assoc->assoc_status = rpc_s_bad_pkt; 1561 } 1562 else 1563 { 1564 pres_result_list = (rpc_cn_pres_result_list_t *) 1565 ((unsigned8 *)(resp_header) + header_size); 1566 1567 result_list_len = rpc_g_cn_large_frag_size - header_size; 1568 1569 rpc__cn_assoc_syntax_negotiate (assoc, 1570 pres_cont_list, 1571 &result_list_len, 1572 pres_result_list, 1573 &assoc->assoc_status); 1574 1575 header_size += result_list_len; 1576 } 1577 1578 if (assoc->assoc_status == rpc_s_ok) 1579 { 1580 auth_len = rpc_g_cn_large_frag_size - header_size; 1581 rpc__cn_assoc_process_auth_tlr (assoc, 1582 req_header, 1583 ((rpc_cn_fragbuf_t *)event_param)->data_size, 1584 resp_header, 1585 &header_size, 1586 &auth_len, 1587 &assoc->security.assoc_current_sec_context, 1588 old_client, 1589 &assoc->assoc_status); 1590 1591 } 1592 1593 /* 1594 * An rpc_alter_context_response PDU will be sent if the association status is 1595 * OK. 1596 */ 1597 if (assoc->assoc_status == rpc_s_ok) 1598 { 1599 fragbuf->data_size = header_size; 1600 rpc__cn_pkt_format_common (resp_header, 1601 RPC_C_CN_PKT_ALTER_CONTEXT_RESP, 1602 (RPC_C_CN_FLAGS_FIRST_FRAG | RPC_C_CN_FLAGS_LAST_FRAG), 1603 fragbuf->data_size, 1604 auth_len, 1605 RPC_CN_PKT_CALL_ID (req_header), 1606 assoc->assoc_vers_minor); 1607 1608 /* 1609 * Send an alter context response event through the association state 1610 * machine. Note the event parameter is the fragment buffer 1611 * containing the response PDU. 1612 */ 1613 sm_p->cur_state = RPC_C_SERVER_ASSOC_AUTH3; 1614 event.event_id = RPC_C_ASSOC_ALTER_CONTEXT_RESP; 1615 event.event_param = (dce_pointer_t) fragbuf; 1616 RPC_CN_ASSOC_INSERT_EVENT (assoc, &event); 1617 } 1618 else 1619 { 1620 /* 1621 * The architecture doesn't specify what to do here. We'll 1622 * at least spit out what happened. 1623 */ 1624 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_ERRORS, 1625 ("CN: call_rep->%p assoc->%p desc->%p error %x while processing alter context PDU \n", 1626 assoc->call_rep, 1627 assoc, 1628 assoc->cn_ctlblk.cn_sock, 1629 assoc->assoc_status)); 1630 } 1631 1632 return (assoc->assoc_status); 1633} 1634 1635/* 1636**++ 1637** 1638** ROUTINE NAME: send_alter_cont_resp_action_rtn 1639** 1640** SCOPE: INTERNAL - declared locally 1641** 1642** DESCRIPTION: 1643** 1644** Action routine to send an alter_context_resp PDU 1645** to the client. 1646** 1647** INPUTS: 1648** 1649** spc_struct The association. Note that this is passed in as 1650** the special structure which is passed to the 1651** state machine event evaluation routine. 1652** 1653** event_param The fragbuf containing the alter_context_resp PDU. 1654** This is passed in as the 1655** special event related parameter which was 1656** passed to the state machine evaluation routine. 1657** 1658** INPUTS/OUTPUTS: 1659** 1660** sm The control block from the event evaluation 1661** routine. Input is the current state and 1662** event for the control block. SM is not changed 1663** here but is passed in to avoid compile warnings 1664** from rpc__cn_sm_eval_event(). 1665** 1666** OUTPUTS: none 1667** 1668** IMPLICIT INPUTS: none 1669** 1670** IMPLICIT OUTPUTS: none 1671** 1672** FUNCTION VALUE: completion status, one of: 1673** rpc_s_ok 1674** 1675** SIDE EFFECTS: none 1676** 1677**-- 1678**/ 1679 1680INTERNAL unsigned32 send_alter_cont_resp_action_rtn 1681( 1682 dce_pointer_t spc_struct, 1683 dce_pointer_t event_param, 1684 dce_pointer_t sm 1685) 1686{ 1687 rpc_cn_assoc_t *assoc; 1688 rpc_cn_fragbuf_t *fragbuf; 1689 rpc_cn_packet_t *req_header; 1690 rpc_cn_sm_ctlblk_t *sm_p; 1691 unsigned8 n_state, o_state; 1692 rpc_cn_sec_context_p_t sec; 1693 1694 RPC_CN_DBG_RTN_PRINTF(SERVER send_alter_cont_resp_action_rtn); 1695 1696 /* 1697 * The special structure is a pointer to the association. 1698 */ 1699 assoc = (rpc_cn_assoc_t *) spc_struct; 1700 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 1701 1702 o_state = sm_p->cur_state; 1703 1704 sec = assoc->security.assoc_current_sec_context; 1705 if (sec == NULL || sec->sec_state == RPC_C_SEC_STATE_COMPLETE) 1706 { 1707 n_state = RPC_C_SERVER_ASSOC_OPEN; 1708 } 1709 else 1710 { 1711 n_state = RPC_C_SERVER_ASSOC_AUTH3_WAIT; 1712 } 1713 1714 if (o_state != RPC_C_SERVER_ASSOC_OPEN && 1715 n_state == RPC_C_SERVER_ASSOC_OPEN) 1716 { 1717 add_assoc_to_grp_action_rtn (spc_struct, (dce_pointer_t) assoc, sm); 1718 } 1719 1720 /* 1721 * The event parameter is a pointer to the fragbuf containing 1722 * the alter_context_resp PDU. 1723 */ 1724 fragbuf = (rpc_cn_fragbuf_t *) event_param; 1725 req_header = (rpc_cn_packet_t *) fragbuf->data_p; 1726 1727 /* 1728 * If we have security, we may have to break it apart. 1729 */ 1730 if (RPC_CN_PKT_AUTH_TLR_PRESENT (req_header)) 1731 { 1732 send_frag_resp_pdu(assoc, fragbuf, req_header); 1733 } 1734 else 1735 { 1736 /* 1737 * Just send the PDU and free the fragbuf. 1738 */ 1739 rpc__cn_assoc_send_fragbuf (assoc, 1740 fragbuf, 1741 assoc->security.assoc_current_sec_context, 1742 true, 1743 &(assoc->assoc_status)); 1744 } 1745 RPC_CN_ASSOC_CHECK_ST (assoc, &(assoc->assoc_status)); 1746 1747 sm_p->cur_state = n_state; 1748 return (assoc->assoc_status); 1749} 1750 1751 1752/* 1753**++ 1754** 1755** ROUTINE NAME: do_authent3_action_rtn 1756** 1757** SCOPE: INTERNAL - declared locally 1758** 1759** DESCRIPTION: 1760** 1761** Action routine to process the 3rd leg of an optional 3-way 1762** authentication handshake. 1763** 1764** INPUTS: 1765** 1766** spc_struct The association. Note that this is passed in as 1767** the special structure which is passed to the 1768** state machine event evaluation routine. 1769** 1770** event_param This is passed in as the 1771** special event related parameter which was 1772** passed to the state machine evaluation routine. 1773** 1774** INPUTS/OUTPUTS: 1775** 1776** sm The control block from the event evaluation 1777** routine. Input is the current state and 1778** event for the control block. Output is the 1779** next state or updated current state, for the 1780** control block. 1781** 1782** OUTPUTS: none 1783** 1784** IMPLICIT INPUTS: none 1785** 1786** IMPLICIT OUTPUTS: none 1787** 1788** FUNCTION VALUE: completion status, one of: 1789** rpc_s_ok 1790** 1791** SIDE EFFECTS: none 1792** 1793**-- 1794**/ 1795 1796INTERNAL unsigned32 do_authent3_action_rtn 1797( 1798 dce_pointer_t spc_struct, 1799 dce_pointer_t event_param, 1800 dce_pointer_t sm 1801) 1802{ 1803 rpc_cn_assoc_t *assoc; 1804 rpc_cn_sm_ctlblk_t *sm_p; 1805 rpc_cn_packet_t *req_header; 1806 rpc_cn_packet_t *tmp_resp_header; 1807 unsigned32 auth_len; 1808 rpc_cn_fragbuf_t *fragbuf; 1809 unsigned32 header_size; 1810 rpc_cn_port_any_t *sec_addr; 1811 boolean old_client; 1812 unsigned8 tmp[rpc_g_cn_large_frag_size]; 1813 unsigned8 new_state; 1814 rpc_cn_sec_context_p_t sec; 1815 unsigned32 status; 1816 1817 RPC_CN_DBG_RTN_PRINTF(SERVER do_authent3_action_rtn); 1818 1819 /* 1820 * The special structure is a pointer to the association. 1821 */ 1822 assoc = (rpc_cn_assoc_t *) spc_struct; 1823 old_client = (assoc->assoc_vers_minor <= RPC_C_CN_PROTO_VERS_COMPAT); 1824 1825 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 1826 1827 sm_p->cur_state = RPC_C_SERVER_ASSOC_AUTH3; 1828 1829 fragbuf = (rpc_cn_fragbuf_t *)event_param; 1830 req_header = (rpc_cn_packet_t *)fragbuf->data_p; 1831 1832 if (!(RPC_CN_PKT_FLAGS (req_header)) && 1833 !(RPC_CN_PKT_VERS_MINOR (req_header) < RPC_C_CN_PROTO_VERS_MINOR)) 1834 { 1835 return (save_sec_fragment (assoc, req_header)); 1836 } 1837 if (assoc->security.auth_buffer_info.auth_buffer != NULL) 1838 { 1839 status = save_sec_fragment (assoc, req_header); 1840 if (status != rpc_s_ok) 1841 return (status); 1842 } 1843 assoc->security.assoc_current_sec_context = NULL; 1844 1845 /* 1846 * Allocate a temporary "response" buffer so we can 1847 * call rpc__cn_assoc_process_auth_tlr() 1848 */ 1849 tmp_resp_header = (rpc_cn_packet_t *) (tmp); 1850 header_size = RPC_CN_PKT_SIZEOF_BIND_ACK_HDR; /* not really, but. */ 1851 1852 sec_addr = (rpc_cn_port_any_t *)((unsigned8 *)(tmp_resp_header) + header_size); 1853 /* changed from 1 to 0 - lukeh May 2003 */ 1854 sec_addr->length = 0; 1855 sec_addr->s[0] = '\0'; 1856 1857 header_size = (2 + header_size + 3) & ~0x03; 1858 1859 /* Process the trailer */ 1860 1861 rpc__cn_assoc_process_auth_tlr (assoc, 1862 req_header, 1863 fragbuf->data_size, 1864 tmp_resp_header, 1865 &header_size, 1866 &auth_len, 1867 &assoc->security.assoc_current_sec_context, 1868 old_client, 1869 &assoc->assoc_status); 1870 if (assoc->assoc_status == rpc_s_ok && auth_len != 0) 1871 { 1872 /* Make sure the authentication subsystem didn't return a response */ 1873 assoc->assoc_status = rpc_s_proto_unsupp_by_auth; 1874 } 1875 1876 sec = assoc->security.assoc_current_sec_context; 1877 if (sec == NULL || sec->sec_state == RPC_C_SEC_STATE_COMPLETE) 1878 { 1879 new_state = (assoc->assoc_status == rpc_s_ok) ? RPC_C_ASSOC_AUTH3_ACK : RPC_C_ASSOC_AUTH3_NACK; 1880 1881 assoc->assoc_status = rpc__cn_sm_eval_event (new_state, event_param, assoc, &assoc->assoc_state); 1882 assoc->assoc_flags &= ~RPC_C_CN_ASSOC_SCANNED; 1883 } 1884 else 1885 { 1886 sm_p->cur_state = RPC_C_SERVER_ASSOC_AUTH3_WAIT; 1887 } 1888 1889 return (assoc->assoc_status); 1890} 1891 1892 1893/* 1894**++ 1895** 1896** ROUTINE NAME: do_assoc_req_action_rtn 1897** 1898** SCOPE: INTERNAL - declared locally 1899** 1900** DESCRIPTION: 1901** 1902** Action routine to process the association request and 1903** presentation and security negotiations. 1904** 1905** INPUTS: 1906** 1907** spc_struct The association. Note that this is passed in as 1908** the special structure which is passed to the 1909** state machine event evaluation routine. 1910** 1911** event_param The fragbuf containing the rpc_bind PDU. 1912** This is passed in as the 1913** special event related parameter which was 1914** passed to the state machine evaluation routine. 1915** 1916** INPUTS/OUTPUTS: 1917** 1918** sm The control block from the event evaluation 1919** routine. Input is the current state and 1920** event for the control block. Output is the 1921** next state or updated current state, for the 1922** control block. 1923** 1924** OUTPUTS: none 1925** 1926** IMPLICIT INPUTS: none 1927** 1928** IMPLICIT OUTPUTS: none 1929** 1930** FUNCTION VALUE: completion status, one of: 1931** rpc_s_ok 1932** rpc_s_assoc_grp_max_exceeded 1933** 1934** SIDE EFFECTS: none 1935** 1936**-- 1937**/ 1938 1939INTERNAL unsigned32 do_assoc_req_action_rtn 1940( 1941 dce_pointer_t spc_struct, 1942 dce_pointer_t event_param, 1943 dce_pointer_t sm 1944) 1945{ 1946 rpc_cn_assoc_t *assoc; 1947 rpc_cn_assoc_grp_t *assoc_grp; 1948 rpc_cn_packet_t *req_header; 1949 rpc_cn_packet_t *resp_header; 1950 rpc_cn_pres_cont_list_t *pres_cont_list; 1951 rpc_cn_pres_result_list_t *pres_result_list; 1952 unsigned32 header_size; 1953 unsigned32 result_list_len; 1954 unsigned32 auth_len; 1955 rpc_cn_local_id_t grp_id; 1956 rpc_cn_fragbuf_t *fragbuf; 1957 rpc_cn_sm_event_entry_t event; 1958 rpc_cn_port_any_t *sec_addr; 1959 boolean old_client; 1960 rpc_cn_sm_ctlblk_t *sm_p; 1961 unsigned8 *end_of_pkt; /* ptr to 1 byte past end of packet */ 1962 unsigned8 *end_ptr; 1963 rpc_socket_error_t serr; 1964 unsigned32 ssize = 0; 1965 unsigned32 rsize = 0; 1966 unsigned32 status; 1967 1968 RPC_CN_DBG_RTN_PRINTF (SERVER do_assoc_req_action_rtn); 1969 1970 /* 1971 * The special structure is a pointer to the association. 1972 */ 1973 assoc = (rpc_cn_assoc_t *) spc_struct; 1974 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 1975 1976 /* 1977 * The event parameter is a pointer to the fragbuf containing 1978 * the rpc_bind PDU. 1979 */ 1980 req_header = (rpc_cn_packet_t *) ((rpc_cn_fragbuf_t *)event_param)->data_p; 1981 end_of_pkt = (unsigned8 *) req_header; 1982 end_of_pkt += ((rpc_cn_fragbuf_t *)event_param)->data_size; 1983 1984 /* 1985 * Allocate a large fragbuf for the response PDU. It will either 1986 * be an rpc_bind_ack or rpc_bind_nack. We won't expend any 1987 * more time here trying to optimize to allocate a small fragbuf. 1988 */ 1989 RPC_CN_FRAGBUF_ALLOC (fragbuf, rpc_g_cn_large_frag_size, &(assoc->assoc_status)); 1990 resp_header = (rpc_cn_packet_t *) (fragbuf->data_p); 1991 1992 /* 1993 * Assume that everything is going to go OK and begin formatting 1994 * an rpc_bind_ack PDU. If something bad happens we'll format an 1995 * rpc_bind_nack PDU below. 1996 */ 1997 header_size = RPC_CN_PKT_SIZEOF_BIND_ACK_HDR; 1998 1999#ifdef DEBUG 2000 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, 2001 RPC_C_CN_DBG_PROT_VERS_MISMATCH)) 2002 { 2003 RPC_CN_PKT_VERS_MINOR (req_header) = 2004 RPC_C_CN_PROTO_VERS_MINOR + 1; 2005 } 2006#endif 2007 2008 if (sm_p->cur_state == RPC_C_SERVER_ASSOC_OPEN) 2009 { 2010 /* Server connection is already bound so reject another Bind request */ 2011 assoc->assoc_status = rpc_s_protocol_error; 2012 goto done; 2013 } 2014 2015 /* 2016 * Since this is a new association we don't yet have an 2017 * association UUID CRC (and will not unless a client on this 2018 * association uses security). 2019 */ 2020 assoc->security.assoc_have_uuid_crc = false; 2021 2022 /* 2023 * Mark the current security context as NULL. This will be 2024 * filled in when we have successfully established a security 2025 * context. It will be used by the action routine which actually 2026 * sends the rpc_bind_ack PDU. 2027 */ 2028 assoc->security.assoc_current_sec_context = NULL; 2029 2030 if ((RPC_CN_PKT_VERS (req_header) != RPC_C_CN_PROTO_VERS) || 2031 (RPC_CN_PKT_VERS_MINOR (req_header) > RPC_C_CN_PROTO_VERS_MINOR)) 2032 { 2033 assoc->assoc_status = rpc_s_rpc_prot_version_mismatch; 2034 } 2035 else 2036 { 2037 /* 2038 * As per the NCA Connection Architecture return the 2039 * client's minor protocol version number and restrict the use 2040 * of the protocol to the client's minor version. 2041 */ 2042 assoc->assoc_vers_minor = RPC_CN_PKT_VERS_MINOR (req_header); 2043 old_client = (assoc->assoc_vers_minor <= RPC_C_CN_PROTO_VERS_COMPAT); 2044 RPC_CN_PKT_VERS_MINOR (resp_header) = RPC_CN_PKT_VERS_MINOR(req_header); 2045 2046 /* 2047 * Return the server's operational max size fragment it will 2048 * send and max size fragment it is capable of receiving. Make 2049 * sure these values are not greater than what the client gave. 2050 */ 2051 if (RPC_CN_PKT_MAX_RECV_FRAG (req_header) == 0) 2052 { 2053 /* 2054 * This is a reserved value as specified in the NCA 2055 * Connection Architecture spec. It implies the default 2056 * rpc_c_assoc_must_recv_frag_size. 2057 */ 2058 RPC_CN_PKT_MAX_RECV_FRAG (req_header) = RPC_C_ASSOC_MUST_RECV_FRAG_SIZE; 2059 } 2060 if (RPC_CN_PKT_MAX_XMIT_FRAG (req_header) == 0) 2061 { 2062 /* 2063 * This is a reserved value as specified in the NCA 2064 * Connection Architecture spec. It implies the default 2065 * rpc_c_assoc_must_recv_frag_size. 2066 */ 2067 RPC_CN_PKT_MAX_XMIT_FRAG (req_header) = RPC_C_ASSOC_MUST_RECV_FRAG_SIZE; 2068 } 2069 2070 /* Set socket's max send/receive sizes to same as max fragment size. */ 2071 serr = rpc__socket_set_bufs (assoc->cn_ctlblk.cn_sock, 2072 rpc_g_cn_large_frag_size, 2073 rpc_g_cn_large_frag_size, 2074 &ssize, 2075 &rsize); 2076 if (!RPC_SOCKET_IS_ERR (serr)) 2077 { 2078 /* update socket buffer sizes with their actual values */ 2079 rpc__cn_set_sock_buffsize(rsize, ssize, &status); 2080 } 2081 else 2082 { 2083 /* 0 means we could not get any of the max sizes */ 2084 ssize = 0; 2085 rsize = 0; 2086 } 2087 2088 if ( (ssize != 0) && (ssize < rpc_g_cn_large_frag_size) ) 2089 { 2090 RPC_CN_PKT_MAX_XMIT_FRAG (resp_header) = 2091 MIN (ssize, RPC_CN_PKT_MAX_RECV_FRAG (req_header)); 2092 } 2093 else 2094 { 2095 RPC_CN_PKT_MAX_XMIT_FRAG (resp_header) = 2096 MIN (rpc_g_cn_large_frag_size, RPC_CN_PKT_MAX_RECV_FRAG (req_header)); 2097 } 2098 2099 if ( (rsize != 0) && (rsize < rpc_g_cn_large_frag_size) ) 2100 { 2101 RPC_CN_PKT_MAX_RECV_FRAG (resp_header) = 2102 MIN (rsize, RPC_CN_PKT_MAX_XMIT_FRAG (req_header)); 2103 } 2104 else 2105 { 2106 RPC_CN_PKT_MAX_RECV_FRAG (resp_header) = 2107 MIN (rpc_g_cn_large_frag_size, RPC_CN_PKT_MAX_XMIT_FRAG (req_header)); 2108 } 2109 2110 assoc->assoc_max_xmit_frag = RPC_CN_PKT_MAX_XMIT_FRAG (resp_header); 2111 assoc->assoc_max_recv_frag = RPC_CN_PKT_MAX_RECV_FRAG (resp_header); 2112 2113 /* 2114 * Determine whether the rpc_bind PDU contains an association 2115 * group id. 2116 */ 2117 if (RPC_CN_PKT_ASSOC_GROUP_ID (req_header) != 0) 2118 { 2119 /* 2120 * The rpc_bind PDU does contain a group id. Use it to look 2121 * up an association group. 2122 */ 2123 grp_id.all = RPC_CN_PKT_ASSOC_GROUP_ID (req_header); 2124 assoc->assoc_grp_id = 2125 rpc__cn_assoc_grp_lkup_by_id (grp_id, 2126 RPC_C_CN_ASSOC_GRP_SERVER, 2127 assoc->transport_info, 2128 &(assoc->assoc_status)); 2129 assoc_grp = RPC_CN_ASSOC_GRP (assoc->assoc_grp_id); 2130 if (assoc->assoc_status == rpc_s_ok) 2131 { 2132#ifdef DEBUG 2133 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, 2134 RPC_C_CN_DBG_GRP_MAX_EXCEEDED)) 2135 { 2136 assert(assoc_grp != NULL); 2137 assoc_grp->grp_cur_assoc = assoc_grp->grp_max_assoc; 2138 } 2139#endif 2140 /* 2141 * The association group was found. Determine whether it can 2142 * support another association. 2143 */ 2144 assert(assoc_grp != NULL); 2145 if (assoc_grp->grp_cur_assoc == assoc_grp->grp_max_assoc) 2146 { 2147 /* 2148 * The group can't support another association. Reject this 2149 * association request by sending an rpc_bind_nack PDU. 2150 */ 2151 assoc->assoc_status = rpc_s_assoc_grp_max_exceeded; 2152 } 2153 } 2154 } /* end if (RPC_CN_PKT_ASSOC_GROUP_ID (req_header) != 0) */ 2155 else /* (RPC_CN_PKT_ASSOC_GROUP_ID (req_header) == 0) */ 2156 { 2157 /* 2158 * A new association group needs to be created. 2159 */ 2160 assoc->assoc_grp_id = rpc__cn_assoc_grp_alloc (assoc->cn_ctlblk.rpc_addr, 2161 assoc->transport_info, 2162 RPC_C_CN_ASSOC_GRP_SERVER, 2163 0, 2164 &(assoc->assoc_status)); 2165 assoc_grp = RPC_CN_ASSOC_GRP (assoc->assoc_grp_id); 2166 } /* end else (RPC_CN_PKT_ASSOC_GROUP_ID (req_header) == 0) */ 2167 2168 if (assoc->assoc_status == rpc_s_ok) 2169 { 2170 /* 2171 * Return the appropriate group ID for the client to use on 2172 * the next association request. 2173 */ 2174 assert(assoc_grp != NULL); 2175 RPC_CN_PKT_ASSOC_GROUP_ID (resp_header) = assoc_grp->grp_id.all; 2176 2177 /* 2178 * Determine the length of the secondary address endpoint including the '\0' 2179 * termination and store this in the PDU. Also string copy the 2180 * actual endpoint into the PDU. If the endpoint won't fit fall 2181 * through and send an rpc_bind_nak. 2182 */ 2183 sec_addr = (rpc_cn_port_any_t *) 2184 ((unsigned8 *) (resp_header) + header_size); 2185 sec_addr->length = 2186 strlen ((char *)assoc->cn_ctlblk.cn_listening_endpoint) + 1; 2187 if (sec_addr->length < 2188 (rpc_g_cn_large_frag_size - header_size + 2)) 2189 { 2190 strlcpy ((char *)(sec_addr->s), 2191 (char *)assoc->cn_ctlblk.cn_listening_endpoint, sec_addr->length); 2192 2193 /* 2194 * To format the balance of the rpc_bind_ack PDU fields we're 2195 * going to have to do some pointer arithmetic because the 2196 * secondary address endpoint is variable length. Also note 2197 * that the because the presentation result list must start 2198 * on a 4-byte boundary rounding up will be necessary. 2199 */ 2200 2201 header_size = (header_size + 2 + sec_addr->length + 3) & ~0x3; 2202 2203 pres_result_list = (rpc_cn_pres_result_list_t *) 2204 ((unsigned8 *) resp_header + header_size); 2205 2206 /* 2207 * Get a local pointer to the presentation context list in the 2208 * PDU header. Use this along with the location of the 2209 * presentation result list in the response hdr to pass to the 2210 * syntax negotiation routine. Upon successful return from this 2211 * routine the presentation result list will be formatted. 2212 * If unsuccessful the presentation context result list would 2213 * not fit in the balance of the fragbuf. Fall through and 2214 * send an rpc_bind_nak. 2215 */ 2216 pres_cont_list = (rpc_cn_pres_cont_list_t *) 2217 ((unsigned8 *) req_header + RPC_CN_PKT_SIZEOF_BIND_HDR); 2218 2219 /* points to end of pkt whether n_context_elem is 0 or not */ 2220 end_ptr = (unsigned8 *) &pres_cont_list->pres_cont_elem[pres_cont_list->n_context_elem]; 2221 2222 if ( ((unsigned8 *) pres_cont_list < (unsigned8 *) req_header) || 2223 ((unsigned8 *) pres_cont_list > (unsigned8 *) end_of_pkt) || 2224 ((unsigned8 *) end_ptr < (unsigned8 *) req_header) || 2225 ((unsigned8 *) end_ptr > (unsigned8 *) end_of_pkt) ) 2226 { 2227 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, 2228 ("invalid pres_cont_list\n")); 2229 assoc->assoc_status = rpc_s_bad_pkt; 2230 } 2231 else 2232 { 2233 result_list_len = rpc_g_cn_large_frag_size - header_size; 2234 2235 rpc__cn_assoc_syntax_negotiate (assoc, 2236 pres_cont_list, 2237 &result_list_len, 2238 pres_result_list, 2239 &assoc->assoc_status); 2240 2241 header_size += result_list_len; 2242 if (assoc->assoc_status == rpc_s_ok) 2243 { 2244 auth_len = rpc_g_cn_large_frag_size - header_size; 2245 rpc__cn_assoc_process_auth_tlr (assoc, 2246 req_header, 2247 ((rpc_cn_fragbuf_t *)event_param)->data_size, 2248 resp_header, 2249 &header_size, 2250 &auth_len, 2251 &assoc->security.assoc_current_sec_context, 2252 old_client, 2253 &assoc->assoc_status); 2254 } 2255 } 2256 } 2257 else 2258 { 2259 assoc->assoc_status = RPC_S_HEADER_FULL; 2260 } 2261 } 2262 } 2263 2264#ifdef DEBUG 2265 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_HEADER_FULL)) 2266 { 2267 assoc->assoc_status = RPC_S_HEADER_FULL; 2268 } 2269#endif 2270 2271done: 2272 /* 2273 * An rpc_bind_nak PDU will be sent if the association status is 2274 * not OK. Assume it will be the only fragment sent. 2275 */ 2276 if (assoc->assoc_status == rpc_s_ok) 2277 { 2278 fragbuf->data_size = header_size; 2279 rpc__cn_pkt_format_common (resp_header, 2280 RPC_C_CN_PKT_BIND_ACK, 2281 (RPC_C_CN_FLAGS_FIRST_FRAG | RPC_C_CN_FLAGS_LAST_FRAG), 2282 fragbuf->data_size, 2283 auth_len, 2284 RPC_CN_PKT_CALL_ID (req_header), 2285 assoc->assoc_vers_minor); 2286 2287 /* 2288 * Send an accept response event through the association state 2289 * machine. 2290 */ 2291 event.event_id = RPC_C_ASSOC_ACCEPT_RESP; 2292 } 2293 else 2294 { 2295 int i; 2296 2297 /* 2298 * Some failure happened. Reject this 2299 * association request by sending an rpc_bind_nak PDU 2300 * with the list of supported protocol versions. 2301 */ 2302 fragbuf->data_size = RPC_CN_PKT_SIZEOF_BIND_NACK_HDR + 2303 (RPC_C_CN_PROTO_VERS_MINOR * sizeof(rpc_cn_version_t)); 2304 rpc__cn_pkt_format_common (resp_header, 2305 RPC_C_CN_PKT_BIND_NAK, 2306 (RPC_C_CN_FLAGS_FIRST_FRAG | RPC_C_CN_FLAGS_LAST_FRAG), 2307 fragbuf->data_size, 2308 0, 2309 RPC_CN_PKT_CALL_ID (req_header), 2310 assoc->assoc_vers_minor); 2311 (RPC_CN_PKT_VERSIONS (resp_header)).n_protocols 2312 = RPC_C_CN_PROTO_VERS_MINOR + 1; 2313 for (i = 0;i <= RPC_C_CN_PROTO_VERS_MINOR; i++) 2314 { 2315 (RPC_CN_PKT_VERSIONS (resp_header)).protocols[i].vers_major 2316 = RPC_C_CN_PROTO_VERS; 2317 (RPC_CN_PKT_VERSIONS (resp_header)).protocols[i].vers_minor = i; 2318 } 2319 RPC_CN_PKT_PROV_REJ_REASON(resp_header) = 2320 rpc__cn_assoc_status_to_prej (assoc->assoc_status); 2321 2322 /* 2323 * Set up the event parameter as the fragment buffer containg 2324 * the PDU and send the event through the association state 2325 * machine. 2326 */ 2327 event.event_id = RPC_C_ASSOC_REJECT_RESP; 2328 } 2329 2330 event.event_param = (dce_pointer_t) fragbuf; 2331 RPC_CN_ASSOC_INSERT_EVENT (assoc, &event); 2332 sm_p->cur_state = RPC_C_SERVER_ASSOC_REQUESTED; 2333 return (assoc->assoc_status); 2334} 2335 2336 2337/* 2338**++ 2339** 2340** ROUTINE NAME: send_shutdown_req_action_rtn 2341** 2342** SCOPE: INTERNAL - declared locally 2343** 2344** DESCRIPTION: 2345** 2346** Action routine to send an rpc_shutdown orderly shutdown PDU 2347** to the client. 2348** 2349** INPUTS: 2350** 2351** spc_struct The association. Note that this is passed in as 2352** the special structure which is passed to the 2353** state machine event evaluation routine. 2354** 2355** event_param This is passed in as the 2356** special event related parameter which was 2357** passed to the state machine evaluation routine. 2358** This input argument is ignored. 2359** 2360** INPUTS/OUTPUTS: 2361** 2362** sm The control block from the event evaluation 2363** routine. Input is the current state and 2364** event for the control block. Output is the 2365** next state or updated current state, for the 2366** control block. 2367** 2368** OUTPUTS: none 2369** 2370** IMPLICIT INPUTS: none 2371** 2372** IMPLICIT OUTPUTS: none 2373** 2374** FUNCTION VALUE: completion status, one of: 2375** rpc_s_ok 2376** 2377** SIDE EFFECTS: none 2378** 2379**-- 2380**/ 2381 2382INTERNAL unsigned32 send_shutdown_req_action_rtn 2383( 2384 dce_pointer_t spc_struct, 2385 dce_pointer_t event_param ATTRIBUTE_UNUSED, 2386 dce_pointer_t sm 2387) 2388{ 2389 rpc_cn_assoc_t *assoc; 2390 unsigned32 pdu_size; 2391 rpc_cn_fragbuf_t *fragbuf; 2392 rpc_cn_packet_t *header; 2393 rpc_cn_sm_ctlblk_t *sm_p; 2394 unsigned8 n_state; 2395 2396 RPC_CN_DBG_RTN_PRINTF(SERVER send_shutdown_req_action_rtn); 2397 2398 /* 2399 * The special structure is a pointer to the association. 2400 */ 2401 assoc = (rpc_cn_assoc_t *) spc_struct; 2402 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 2403 2404 /* 2405 * There is no predicate associated with this routine but the 2406 * new value of sm->cur_state is determined by the value of 2407 * sm->cur_state coming into the routine. Note that 2408 * 2+rpc_c_cn_statebase is auth3_wait_state; 3+rpc_c_cn_statebase is 2409 * auth3_wait; 4+rpc_c_cn_statebase is open_state. These values 2410 * are static and rpc_c_cn_statebase is the value added to 2411 * the states in order to distinguish them from the action 2412 * routine indexes. 2413 */ 2414 switch (sm_p->cur_state) { 2415 case (2 + RPC_C_CN_STATEBASE): 2416 n_state = RPC_C_SERVER_ASSOC_AUTH3_WAIT; 2417 break; 2418 case (3 + RPC_C_CN_STATEBASE): 2419 n_state = RPC_C_SERVER_ASSOC_AUTH3; 2420 break; 2421 case (4 + RPC_C_CN_STATEBASE): 2422 n_state = RPC_C_SERVER_ASSOC_OPEN; 2423 break; 2424 default: 2425 fprintf(stderr, "%s no value for n_state\n", __PRETTY_FUNCTION__); 2426 abort(); 2427 break; 2428 } 2429 2430 /* 2431 * Allocate a fragbuf capable of holding a shutdown PDU. 2432 */ 2433 pdu_size = RPC_CN_PKT_SIZEOF_SHUTDOWN_HDR; 2434 2435 /* 2436 * Allocate a fragbuf of the appropriate size. 2437 */ 2438 RPC_CN_FRAGBUF_ALLOC (fragbuf, pdu_size, &(assoc->assoc_status)); 2439 RPC_CN_ASSOC_CHECK_ST (assoc, &(assoc->assoc_status)); 2440 2441 /* 2442 * Now begin construction of the PDU. 2443 */ 2444 header = (rpc_cn_packet_t *) fragbuf->data_p; 2445 rpc__cn_pkt_format_common (header, 2446 RPC_C_CN_PKT_SHUTDOWN, 2447 0, 2448 pdu_size, 2449 0, 2450 0, 2451 assoc->assoc_vers_minor); 2452 2453 /* 2454 * Now actually send the PDU and free the fragbuf. 2455 */ 2456 rpc__cn_assoc_send_fragbuf (assoc, 2457 fragbuf, 2458 NULL, 2459 true, 2460 &(assoc->assoc_status)); 2461 RPC_CN_ASSOC_CHECK_ST (assoc, &(assoc->assoc_status)); 2462 sm_p->cur_state = n_state; 2463 return (assoc->assoc_status); 2464} 2465 2466 2467/* 2468**++ 2469** 2470** ROUTINE NAME: incr_active_action_rtn 2471** 2472** SCOPE: INTERNAL - declared locally 2473** 2474** DESCRIPTION: 2475** 2476** Action routine to set the active predicate to true. The server 2477** runtime allocated the association for the new call and its 2478** callbacks. Only one call and its related callbacks may allocate an 2479** association at a time. 2480** 2481** INPUTS: 2482** 2483** spc_struct The association. Note that this is passed in as 2484** the special structure which is passed to the 2485** state machine event evaluation routine. 2486** 2487** event_param This is passed in as the 2488** special event related parameter which was 2489** passed to the state machine evaluation routine. 2490** This input argument is ignored. 2491** 2492** INPUTS/OUTPUTS: 2493** 2494** sm The control block from the event evaluation 2495** routine. Input is the current state and 2496** event for the control block. Output is the 2497** next state or updated current state, for the 2498** control block. 2499** 2500** OUTPUTS: none 2501** 2502** IMPLICIT INPUTS: none 2503** 2504** IMPLICIT OUTPUTS: none 2505** 2506** FUNCTION VALUE: completion status, one of: 2507** rpc_s_ok 2508** 2509** SIDE EFFECTS: none 2510** 2511**-- 2512**/ 2513 2514INTERNAL unsigned32 incr_active_action_rtn 2515( 2516 dce_pointer_t spc_struct, 2517 dce_pointer_t event_param ATTRIBUTE_UNUSED, 2518 dce_pointer_t sm 2519) 2520{ 2521 rpc_cn_assoc_t *assoc; 2522 rpc_cn_sm_ctlblk_t *sm_p; 2523 2524 RPC_CN_DBG_RTN_PRINTF(SERVER incr_active_action_rtn); 2525 2526 /* 2527 * The special structure is a pointer to the association. 2528 */ 2529 assoc = (rpc_cn_assoc_t *) spc_struct; 2530 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 2531 2532 /* 2533 * Inccrement the association active reference counter. 2534 */ 2535 RPC_CN_INCR_ACTIVE_SVR_ACTION(assoc, sm_p); 2536 return (assoc->assoc_status); 2537} 2538 2539 2540/* 2541**++ 2542** 2543** ROUTINE NAME: decr_active_action_rtn 2544** 2545** SCOPE: INTERNAL - declared locally 2546** 2547** DESCRIPTION: 2548** 2549** Action routine to set the active predicate to false. The server 2550** runtime deallocated the association when done with an alter context 2551** request, a call, its callbacks, etc. 2552** 2553** INPUTS: 2554** 2555** spc_struct The association. Note that this is passed in as 2556** the special structure which is passed to the 2557** state machine event evaluation routine. 2558** 2559** event_param This is passed in as the 2560** special event related parameter which was 2561** passed to the state machine evaluation routine. 2562** This input argument is ignored. 2563** 2564** INPUTS/OUTPUTS: none 2565** 2566** OUTPUTS: none 2567** 2568** IMPLICIT INPUTS: 2569** 2570** sm The control block from the event evaluation 2571** routine. Input is the current state and 2572** event for the control block. Output is the 2573** next state or updated current state, for the 2574** control block. 2575** 2576** IMPLICIT OUTPUTS: none 2577** 2578** FUNCTION VALUE: completion status, one of: 2579** rpc_s_ok 2580** 2581** SIDE EFFECTS: none 2582** 2583**-- 2584**/ 2585 2586INTERNAL unsigned32 decr_active_action_rtn 2587( 2588 dce_pointer_t spc_struct, 2589 dce_pointer_t event_param ATTRIBUTE_UNUSED, 2590 dce_pointer_t sm 2591) 2592{ 2593 rpc_cn_assoc_t *assoc; 2594 rpc_cn_sm_ctlblk_t *sm_p; 2595 2596 RPC_CN_DBG_RTN_PRINTF(SERVER decr_active_action_rtn); 2597 2598 /* 2599 * The special structure is a pointer to the association. 2600 */ 2601 assoc = (rpc_cn_assoc_t *) spc_struct; 2602 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 2603 2604 /* 2605 * Decrement the association active reference counter. 2606 */ 2607 RPC_CN_DECR_ACTIVE_SVR_ACTION(assoc, sm_p); 2608 return (assoc->assoc_status); 2609} 2610 2611 2612/* 2613**++ 2614** 2615** ROUTINE NAME: abort_assoc_action_rtn 2616** 2617** SCOPE: INTERNAL - declared locally 2618** 2619** DESCRIPTION: 2620** 2621** Action routine to abort the current association. 2622** 2623** INPUTS: 2624** 2625** spc_struct The association. Note that this is passed in as 2626** the special structure which is passed to the 2627** state machine event evaluation routine. 2628** 2629** event_param This is passed in as the 2630** special event related parameter which was 2631** passed to the state machine evaluation routine. 2632** This input argument is ignored. 2633** 2634** INPUTS/OUTPUTS: 2635** 2636** sm The control block from the event evaluation 2637** routine. Input is the current state and 2638** event for the control block. Output is the 2639** next state or updated current state, for the 2640** control block. 2641** 2642** OUTPUTS: none 2643** 2644** IMPLICIT INPUTS: none 2645** 2646** IMPLICIT OUTPUTS: none 2647** 2648** FUNCTION VALUE: completion status, one of: 2649** rpc_s_ok 2650** 2651** SIDE EFFECTS: none 2652** 2653**-- 2654**/ 2655 2656INTERNAL unsigned32 abort_assoc_action_rtn 2657( 2658 dce_pointer_t spc_struct, 2659 dce_pointer_t event_param ATTRIBUTE_UNUSED, 2660 dce_pointer_t sm 2661) 2662{ 2663 rpc_cn_assoc_t *assoc; 2664 rpc_cn_sm_ctlblk_t *sm_p; 2665 2666 RPC_CN_DBG_RTN_PRINTF(SERVER abort_assoc_action_rtn); 2667 2668 /* 2669 * The special structure is a pointer to the association. 2670 */ 2671 assoc = (rpc_cn_assoc_t *) spc_struct; 2672 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 2673 2674 /* 2675 * Close the connection on the association. 2676 */ 2677 if (assoc->cn_ctlblk.cn_state == RPC_C_CN_OPEN) 2678 { 2679 rpc__cn_network_close_connect (assoc, 2680 &(assoc->assoc_status)); 2681 RPC_CN_ASSOC_CHECK_ST (assoc, &(assoc->assoc_status)); 2682 } 2683 sm_p->cur_state = RPC_C_SERVER_ASSOC_CLOSED; 2684 return (assoc->assoc_status); 2685} 2686 2687 2688/* 2689**++ 2690** 2691** ROUTINE NAME: mark_assoc_action_rtn 2692** 2693** SCOPE: INTERNAL - declared locally 2694** 2695** DESCRIPTION: 2696** 2697** Action routine to mark the current association with a status code. 2698** 2699** INPUTS: 2700** 2701** spc_struct The association. Note that this is passed in as 2702** the special structure which is passed to the 2703** state machine event evaluation routine. 2704** 2705** event_param This is passed in as the 2706** special event related parameter which was 2707** passed to the state machine evaluation routine. 2708** This input argument is ignored. 2709** 2710** INPUTS/OUTPUTS: 2711** 2712** sm The control block from the event evaluation 2713** routine. Input is the current state and 2714** event for the control block. Output is the 2715** next state or updated current state, for the 2716** control block. 2717** 2718** OUTPUTS: none 2719** 2720** IMPLICIT INPUTS: none 2721** 2722** IMPLICIT OUTPUTS: none 2723** 2724** FUNCTION VALUE: completion status, one of: 2725** rpc_s_ok 2726** rpc_s_connection_closed 2727** rpc_s_connection_aborted 2728** 2729** SIDE EFFECTS: none 2730** 2731**-- 2732**/ 2733 2734INTERNAL unsigned32 mark_assoc_action_rtn 2735( 2736 dce_pointer_t spc_struct, 2737 dce_pointer_t event_param ATTRIBUTE_UNUSED, 2738 dce_pointer_t sm 2739) 2740{ 2741 rpc_cn_assoc_t *assoc; 2742 dcethread* current_thread_id; 2743 rpc_cn_sm_ctlblk_t *sm_p; 2744 2745 RPC_CN_DBG_RTN_PRINTF(SERVER mark_assoc_action_rtn); 2746 2747 /* 2748 * The special structure is a pointer to the association. 2749 */ 2750 assoc = (rpc_cn_assoc_t *) spc_struct; 2751 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 2752 /* 2753 * Mark the association based on the event currently being 2754 * processed. 2755 */ 2756 switch (assoc->assoc_state.cur_event) 2757 { 2758 case RPC_C_ASSOC_NO_CONN_IND: 2759 { 2760 /* 2761 * The underlying session/transport connection has failed. 2762 */ 2763 assoc->assoc_status = rpc_s_connection_closed; 2764 break; 2765 } 2766 2767 case RPC_C_ASSOC_ABORT_REQ: 2768 { 2769 /* 2770 * The user has aborted the association. 2771 */ 2772 assoc->assoc_status = rpc_s_connection_aborted; 2773 break; 2774 } 2775 2776 case RPC_C_ASSOC_LOCAL_ERROR: 2777 { 2778 /* 2779 * The error status is contained in the association local 2780 * error status for this event. 2781 */ 2782 assoc->assoc_status = assoc->assoc_local_status; 2783 break; 2784 } 2785 2786 default: 2787 { 2788 if (assoc->assoc_status == rpc_s_ok) 2789 assoc->assoc_status = rpc_s_connection_aborted; 2790 break; 2791 } 2792 } 2793 2794 /* 2795 * Queue a dummy fragbuf on the association receive queue. This 2796 * will wake up any threads blocked waiting for receive data. 2797 */ 2798 current_thread_id = dcethread_self(); 2799 if (dcethread_equal (current_thread_id, 2800 assoc->cn_ctlblk.cn_rcvr_thread_id)) 2801 { 2802 RPC_CN_ASSOC_WAKEUP (assoc); 2803 } 2804 2805 sm_p->cur_state = RPC_C_SERVER_ASSOC_CLOSED; 2806 return (assoc->assoc_status); 2807} 2808 2809 2810/* 2811**++ 2812** 2813** ROUTINE NAME: cancel_calls_action_rtn 2814** 2815** SCOPE: INTERNAL - declared locally 2816** 2817** DESCRIPTION: 2818** 2819** Action routine to cancel all the calls currently using the 2820** association. This allows the call state machinery to properly try to 2821** terminate calls when the connection has terminated. 2822** 2823** INPUTS: 2824** 2825** spc_struct The association. Note that this is passed in as 2826** the special structure which is passed to the 2827** state machine event evaluation routine. 2828** 2829** event_param This is passed in as the 2830** special event related parameter which was 2831** passed to the state machine evaluation routine. 2832** This input argument is ignored. 2833** 2834** INPUTS/OUTPUTS: 2835** 2836** sm The control block from the event evaluation 2837** routine. Input is the current state and 2838** event for the control block. SM is not changed 2839** here but is passed in to avoid compile warnings 2840** from rpc__cn_sm_eval_event(). 2841** 2842** OUTPUTS: none 2843** 2844** IMPLICIT INPUTS: none 2845** 2846** IMPLICIT OUTPUTS: none 2847** 2848** FUNCTION VALUE: completion status, one of: 2849** rpc_s_ok 2850** 2851** SIDE EFFECTS: none 2852** 2853**-- 2854**/ 2855 2856INTERNAL unsigned32 cancel_calls_action_rtn 2857( 2858 dce_pointer_t spc_struct, 2859 dce_pointer_t event_param ATTRIBUTE_UNUSED, 2860 dce_pointer_t sm ATTRIBUTE_UNUSED 2861) 2862{ 2863 rpc_cn_assoc_t *assoc; 2864 error_status_t st; 2865 rpc_binding_rep_t *binding_r; 2866 2867 RPC_CN_DBG_RTN_PRINTF(SERVER cancel_calls_action_rtn); 2868 2869 /* 2870 * The special structure is a pointer to the association. 2871 */ 2872 assoc = (rpc_cn_assoc_t *) spc_struct; 2873 2874 /* 2875 * The connection is gone. 2876 */ 2877 if (assoc->call_rep != NULL) 2878 { 2879 /* 2880 * If the call is queued dequeue it otherwise cancel the 2881 * thread it is executing in and signal the association message 2882 * queue condition variable if a thread is waiting on it. 2883 */ 2884 if (rpc__cthread_dequeue((rpc_call_rep_t *) assoc->call_rep)) 2885 { 2886 RPC_DBG_PRINTF(rpc_e_dbg_orphan, RPC_C_CN_DBG_ORPHAN, 2887 ("(cancel_calls_action_rtn) call_rep->%p queued call ... dequeued call id = %x\n", 2888 assoc->call_rep, 2889 RPC_CN_PKT_CALL_ID ((rpc_cn_packet_p_t) RPC_CN_CREP_SEND_HDR(assoc->call_rep)))); 2890 binding_r = (rpc_binding_rep_t *) assoc->call_rep->binding_rep; 2891 RPC_CN_UNLOCK (); 2892 rpc__cn_call_end ((rpc_call_rep_p_t *) &assoc->call_rep, &st); 2893 RPC_CN_LOCK (); 2894 RPC_BINDING_RELEASE (&binding_r, &st); 2895 } 2896 else 2897 { 2898 /* 2899 * We need to cancel and wake up the call executor 2900 * thread. If the call executor thread is in the manager 2901 * routine the cancel may get through. If it is in the 2902 * runtime blocked on a call_receive cancels are disabled 2903 * and needs to be woken up. 2904 */ 2905 RPC_DBG_PRINTF(rpc_e_dbg_orphan, RPC_C_CN_DBG_ORPHAN, 2906 ("(cancel_calls_action_rtn) call_rep->%p running call ... cancelling\n", 2907 assoc->call_rep)); 2908 RPC_CN_ASSOC_CANCEL_AND_WAKEUP (assoc); 2909 } 2910 } 2911 else 2912 { 2913 RPC_DBG_PRINTF(rpc_e_dbg_orphan, RPC_C_CN_DBG_ORPHAN, 2914 ("(cancel_calls_action_rtn) call_rep->%p assoc->%p no call ... do nothing\n", 2915 assoc->call_rep, 2916 assoc)); 2917 } 2918 2919 return (assoc->assoc_status); 2920} 2921 2922 2923/* 2924**++ 2925** 2926** ROUTINE NAME: accept_add_action_rtn 2927** 2928** SCOPE: INTERNAL - declared locally 2929** 2930** DESCRIPTION: 2931** 2932** Action routine to accept the current association and add it to 2933** an association group. 2934** 2935** INPUTS: 2936** 2937** spc_struct The association. Note that this is passed in as 2938** the special structure which is passed to the 2939** state machine event evaluation routine. 2940** 2941** event_param The fragbuf containing the rpc_bind_ack PDU. 2942** This is passed in as the 2943** special event related parameter which was 2944** passed to the state machine evaluation routine. 2945** 2946** INPUTS/OUTPUTS: 2947** 2948** sm The control block from the event evaluation 2949** routine. Input is the current state and 2950** event for the control block. Output is the 2951** next state or updated current state, for the 2952** control block. 2953** 2954** OUTPUTS: none 2955** 2956** IMPLICIT INPUTS: none 2957** 2958** IMPLICIT OUTPUTS: none 2959** 2960** FUNCTION VALUE: completion status, one of: 2961** rpc_s_ok 2962** 2963** SIDE EFFECTS: none 2964** 2965**-- 2966**/ 2967 2968INTERNAL unsigned32 accept_add_action_rtn 2969( 2970 dce_pointer_t spc_struct, 2971 dce_pointer_t event_param, 2972 dce_pointer_t sm 2973) 2974{ 2975 rpc_cn_assoc_t *assoc; 2976 rpc_cn_sm_ctlblk_t *sm_p; 2977 unsigned8 n_state; 2978 rpc_cn_sec_context_p_t sec; 2979 2980 RPC_CN_DBG_RTN_PRINTF(SERVER accept_add_action_rtn); 2981 2982 /* 2983 * The special structure is a pointer to the association. 2984 */ 2985 assoc = (rpc_cn_assoc_t *) spc_struct; 2986 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 2987 2988 sec = assoc->security.assoc_current_sec_context; 2989 if (sec == NULL || sec->sec_state == RPC_C_SEC_STATE_COMPLETE) 2990 { 2991 n_state = RPC_C_SERVER_ASSOC_OPEN; 2992 } 2993 else 2994 { 2995 n_state = RPC_C_SERVER_ASSOC_AUTH3_WAIT; 2996 } 2997 2998 /* 2999 * Add the association to the group and send the rpc_bind_ack PDU 3000 * to the client. 3001 * 3002 * Note: the order in which this is done is important. The assoc 3003 * must be added to the group before sending back the rpc_bind_ack PDU. 3004 * The process of sending a PDU results in the CN mutex being released. 3005 * This opens a window where its possible the association group to which 3006 * we're going to add the assoc could get deallocated which would result 3007 * in a state transition error when we tried to add to it. 3008 * 3009 * Note that since we are calling action routines from 3010 * within action routines, we need to update state as 3011 * a final step here. Otherwise, the action routines 3012 * we call now, would update sm_p->cur_state inappropriately 3013 * for accept_add_action_rtn(). 3014 */ 3015 if (n_state != RPC_C_SERVER_ASSOC_AUTH3_WAIT) 3016 { 3017 add_assoc_to_grp_action_rtn (spc_struct, (dce_pointer_t) assoc, sm); 3018 } 3019 accept_assoc_action_rtn (spc_struct, event_param, sm); 3020 3021 sm_p->cur_state = n_state; 3022 return (assoc->assoc_status); 3023} 3024 3025 3026/* 3027**++ 3028** 3029** ROUTINE NAME: rem_mark_abort_action_rtn 3030** 3031** SCOPE: INTERNAL - declared locally 3032** 3033** DESCRIPTION: 3034** 3035** Action routine to remove the current association from an 3036** association group, mark the association appropriately and abort 3037** the association. 3038** 3039** INPUTS: 3040** 3041** spc_struct The association. Note that this is passed in as 3042** the special structure which is passed to the 3043** state machine event evaluation routine. 3044** 3045** event_param This is passed in as the 3046** special event related parameter which was 3047** passed to the state machine evaluation routine. 3048** This input argument is ignored. 3049** 3050** INPUTS/OUTPUTS: 3051** 3052** sm The control block from the event evaluation 3053** routine. Input is the current state and 3054** event for the control block. Output is the 3055** next state or updated current state, for the 3056** control block. 3057** 3058** OUTPUTS: none 3059** 3060** IMPLICIT INPUTS: none 3061** 3062** IMPLICIT OUTPUTS: none 3063** 3064** FUNCTION VALUE: completion status, one of: 3065** rpc_s_ok 3066** 3067** SIDE EFFECTS: none 3068** 3069**-- 3070**/ 3071 3072INTERNAL unsigned32 rem_mark_abort_action_rtn 3073( 3074 dce_pointer_t spc_struct, 3075 dce_pointer_t event_param, 3076 dce_pointer_t sm 3077) 3078{ 3079 rpc_cn_assoc_t *assoc; 3080 rpc_cn_sm_ctlblk_t *sm_p; 3081 3082 RPC_CN_DBG_RTN_PRINTF(SERVER rem_mark_abort_action_rtn); 3083 3084 /* 3085 * The special structure is a pointer to the association. 3086 */ 3087 assoc = (rpc_cn_assoc_t *) spc_struct; 3088 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 3089 3090 /* 3091 * Remove the association from the group, mark it with the 3092 * appropriate status and abort the underlying session/transport 3093 * connection. 3094 * 3095 * Note that since we are calling action routines from 3096 * within action routines, we need to update state as 3097 * a final step here. Otherwise, the action routines 3098 * we call now, would update sm_p->cur_state inappropriately 3099 * for rem_mark_abort_action_rtn(). 3100 */ 3101 rem_assoc_from_grp_action_rtn (spc_struct, event_param, sm); 3102 abort_assoc_action_rtn (spc_struct, event_param, sm); 3103 mark_assoc_action_rtn (spc_struct, event_param, sm); 3104 3105 sm_p->cur_state = RPC_C_SERVER_ASSOC_CLOSED; 3106 return (assoc->assoc_status); 3107} 3108 3109 3110/* 3111**++ 3112** 3113** ROUTINE NAME: rem_mark_cancel_action_rtn 3114** 3115** SCOPE: INTERNAL - declared locally 3116** 3117** DESCRIPTION: 3118** 3119** Action routine to remove the current association from an 3120** association group, mark the association appropriately and 3121** cancel all calls currently using the association. 3122** 3123** INPUTS: 3124** 3125** spc_struct The association. Note that this is passed in as 3126** the special structure which is passed to the 3127** state machine event evaluation routine. 3128** 3129** event_param This is passed in as the 3130** special event related parameter which was 3131** passed to the state machine evaluation routine. 3132** This input argument is ignored. 3133** 3134** INPUTS/OUTPUTS: 3135** 3136** sm The control block from the event evaluation 3137** routine. Input is the current state and 3138** event for the control block. Output is the 3139** next state or updated current state, for the 3140** control block. 3141** 3142** OUTPUTS: none 3143** 3144** IMPLICIT INPUTS: none 3145** 3146** IMPLICIT OUTPUTS: none 3147** 3148** FUNCTION VALUE: completion status, one of: 3149** rpc_s_ok 3150** 3151** SIDE EFFECTS: none 3152** 3153**-- 3154**/ 3155 3156INTERNAL unsigned32 rem_mark_cancel_action_rtn 3157( 3158 dce_pointer_t spc_struct, 3159 dce_pointer_t event_param, 3160 dce_pointer_t sm 3161) 3162{ 3163 rpc_cn_assoc_t *assoc; 3164 rpc_cn_sm_ctlblk_t *sm_p; 3165 3166 RPC_CN_DBG_RTN_PRINTF(SERVER rem_mark_cancel_action_rtn); 3167 3168 /* 3169 * The special structure is a pointer to the association. 3170 */ 3171 assoc = (rpc_cn_assoc_t *) spc_struct; 3172 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 3173 3174 /* 3175 * Remove the association from the group and mark it with the 3176 * appropriate status and cancels all calls currently using it. 3177 * 3178 * Note that since we are calling action routines from 3179 * within action routines, we need to update state as 3180 * a final step here. Otherwise, the action routines 3181 * we call now, would update sm_p->cur_state inappropriately 3182 * for rem_mark_cancel_action_rtn(). 3183 */ 3184 rem_assoc_from_grp_action_rtn (spc_struct, event_param, sm); 3185 mark_assoc_action_rtn (spc_struct, event_param, sm); 3186 cancel_calls_action_rtn (spc_struct, event_param, sm); 3187 3188 sm_p->cur_state = RPC_C_SERVER_ASSOC_CLOSED; 3189 return (assoc->assoc_status); 3190} 3191 3192 3193/* 3194**++ 3195** 3196** ROUTINE NAME: incr_do_alter_action_rtn 3197** 3198** SCOPE: INTERNAL - declared locally 3199** 3200** DESCRIPTION: 3201** 3202** Action routine to increment the association reference count and process 3203** an rpc_alter_context_req PDU 3204** 3205** INPUTS: 3206** 3207** spc_struct The association. Note that this is passed in as 3208** the special structure which is passed to the 3209** state machine event evaluation routine. 3210** 3211** event_param The fragbuf containing the alter_context_req PDU. 3212** This is passed in as the 3213** special event related parameter which was 3214** passed to the state machine evaluation routine. 3215** 3216** INPUTS/OUTPUTS: 3217** 3218** sm The control block from the event evaluation 3219** routine. Input is the current state and 3220** event for the control block. Output is the 3221** next state or updated current state, for the 3222** control block. 3223** 3224** OUTPUTS: none 3225** 3226** IMPLICIT INPUTS: none 3227** 3228** IMPLICIT OUTPUTS: none 3229** 3230** FUNCTION VALUE: completion status, one of: 3231** rpc_s_ok 3232** 3233** SIDE EFFECTS: none 3234** 3235**-- 3236**/ 3237 3238INTERNAL unsigned32 incr_do_alter_action_rtn 3239( 3240 dce_pointer_t spc_struct, 3241 dce_pointer_t event_param, 3242 dce_pointer_t sm 3243) 3244{ 3245 rpc_cn_assoc_t *assoc; 3246 rpc_cn_sm_ctlblk_t *sm_p; 3247 3248 RPC_CN_DBG_RTN_PRINTF(SERVER incr_do_alter_action_rtn); 3249 3250 /* 3251 * The special structure is a pointer to the association. 3252 */ 3253 assoc = (rpc_cn_assoc_t *) spc_struct; 3254 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 3255 3256 /* 3257 * Increment the active reference counter in the association and 3258 * process the alter context request. 3259 * 3260 * Note that since we are calling action routines from 3261 * within action routines, we need to update state as 3262 * a final step here. Otherwise, the action routines 3263 * we call now, would update sm_p->cur_state inappropriately 3264 * for incr_do_alter_action_rtn(). 3265 */ 3266 incr_active_action_rtn (spc_struct, event_param, sm); 3267 do_alter_cont_req_action_rtn (spc_struct, event_param, sm); 3268 3269 sm_p->cur_state = RPC_C_SERVER_ASSOC_OPEN; 3270 return (assoc->assoc_status); 3271} 3272 3273 3274/* 3275**++ 3276** 3277** ROUTINE NAME: send_decr_action_rtn 3278** 3279** SCOPE: INTERNAL - declared locally 3280** 3281** DESCRIPTION: 3282** 3283** Action routine to send and an rpc_alter_context_response PDU and 3284** decrement the association reference count. 3285** 3286** INPUTS: 3287** 3288** spc_struct The association. Note that this is passed in as 3289** the special structure which is passed to the 3290** state machine event evaluation routine. 3291** 3292** event_param The fragbuf containing the 3293** alter_context_resp PDU. 3294** This is passed in as the 3295** special event related parameter which was 3296** passed to the state machine evaluation routine. 3297** 3298** INPUTS/OUTPUTS: 3299** 3300** sm The control block from the event evaluation 3301** routine. Input is the current state and 3302** event for the control block. Output is the 3303** next state or updated current state, for the 3304** control block. 3305** 3306** OUTPUTS: none 3307** 3308** IMPLICIT INPUTS: none 3309** 3310** IMPLICIT OUTPUTS: none 3311** 3312** FUNCTION VALUE: completion status, one of: 3313** rpc_s_ok 3314** 3315** SIDE EFFECTS: none 3316** 3317**-- 3318**/ 3319 3320INTERNAL unsigned32 send_decr_action_rtn 3321( 3322 dce_pointer_t spc_struct, 3323 dce_pointer_t event_param, 3324 dce_pointer_t sm 3325) 3326{ 3327 rpc_cn_assoc_t *assoc; 3328 rpc_cn_sm_ctlblk_t *sm_p; 3329 3330 RPC_CN_DBG_RTN_PRINTF(SERVER send_decr_action_rtn); 3331 3332 /* 3333 * The special structure is a pointer to the association. 3334 */ 3335 assoc = (rpc_cn_assoc_t *) spc_struct; 3336 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 3337 3338 /* 3339 * Send the alter_context_resp PDU to the client and decrement the 3340 * active reference counter in the association. 3341 * 3342 * Note that since we are calling action routines from 3343 * within action routines, we need to update state as 3344 * a final step here. Otherwise, the action routines 3345 * we call now would update sm_p->cur_state inappropriately 3346 * for send_decr_action_rtn(). 3347 */ 3348 send_alter_cont_resp_action_rtn (spc_struct, event_param, sm); 3349 decr_active_action_rtn (spc_struct, event_param, sm); 3350 3351 sm_p->cur_state = RPC_C_SERVER_ASSOC_OPEN; 3352 return (assoc->assoc_status); 3353} 3354 3355 3356/* 3357**++ 3358** 3359** ROUTINE NAME: mark_abort_action_rtn 3360** 3361** SCOPE: INTERNAL - declared locally 3362** 3363** DESCRIPTION: 3364** 3365** Action routine to mark the association with an error and abort 3366** the session/transport connection. 3367** 3368** INPUTS: 3369** 3370** spc_struct The association. Note that this is passed in as 3371** the special structure which is passed to the 3372** state machine event evaluation routine. 3373** 3374** event_param This is passed in as the 3375** special event related parameter which was 3376** passed to the state machine evaluation routine. 3377** This input argument is ignored. 3378** 3379** INPUTS/OUTPUTS: 3380** 3381** sm The control block from the event evaluation 3382** routine. Input is the current state and 3383** event for the control block. Output is the 3384** next state or updated current state, for the 3385** control block. 3386** 3387** OUTPUTS: none 3388** 3389** IMPLICIT INPUTS: none 3390** 3391** IMPLICIT OUTPUTS: none 3392** 3393** FUNCTION VALUE: completion status, one of: 3394** rpc_s_ok 3395** 3396** SIDE EFFECTS: none 3397** 3398**-- 3399**/ 3400 3401INTERNAL unsigned32 mark_abort_action_rtn 3402( 3403 dce_pointer_t spc_struct, 3404 dce_pointer_t event_param, 3405 dce_pointer_t sm 3406) 3407{ 3408 rpc_cn_assoc_t *assoc; 3409 rpc_cn_sm_ctlblk_t *sm_p; 3410 3411 RPC_CN_DBG_RTN_PRINTF(SERVER mark_abort_action_rtn); 3412 3413 /* 3414 * The special structure is a pointer to the association. 3415 */ 3416 assoc = (rpc_cn_assoc_t *) spc_struct; 3417 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 3418 3419 /* 3420 * Mark the association with the appropriate status and abort 3421 * the underlying session/transport connection. 3422 * 3423 * Note that since we are calling action routines from 3424 * within action routines, we need to update state as 3425 * a final step here. Otherwise, the action routines 3426 * we call now, would update sm_p->cur_state inappropriately 3427 * for mark_abort_action_rtn(). 3428 */ 3429 abort_assoc_action_rtn (spc_struct, event_param, sm); 3430 mark_assoc_action_rtn (spc_struct, event_param, sm); 3431 3432 sm_p->cur_state = RPC_C_SERVER_ASSOC_CLOSED; 3433 return (assoc->assoc_status); 3434} 3435 3436 3437/* 3438**++ 3439** 3440** ROUTINE NAME: rem_mark_abort_can_action_rtn 3441** 3442** SCOPE: INTERNAL - declared locally 3443** 3444** DESCRIPTION: 3445** 3446** Action routine to remove the current association from an 3447** association group, mark the association appropriately, abort 3448** the underlying session/transport connection and cancels all calls 3449** currently using the association. 3450** 3451** INPUTS: 3452** 3453** spc_struct The association. Note that this is passed in as 3454** the special structure which is passed to the 3455** state machine event evaluation routine. 3456** 3457** event_param This is passed in as the 3458** special event related parameter which was 3459** passed to the state machine evaluation routine. 3460** This input argument is ignored. 3461** 3462** INPUTS/OUTPUTS: 3463** 3464** sm The control block from the event evaluation 3465** routine. Input is the current state and 3466** event for the control block. Output is the 3467** next state or updated current state, for the 3468** control block. 3469** 3470** OUTPUTS: none 3471** 3472** IMPLICIT INPUTS: none 3473** 3474** IMPLICIT OUTPUTS: none 3475** 3476** FUNCTION VALUE: completion status, one of: 3477** rpc_s_ok 3478** 3479** SIDE EFFECTS: none 3480** 3481**-- 3482**/ 3483 3484INTERNAL unsigned32 rem_mark_abort_can_action_rtn 3485( 3486 dce_pointer_t spc_struct, 3487 dce_pointer_t event_param, 3488 dce_pointer_t sm 3489) 3490{ 3491 rpc_cn_assoc_t *assoc; 3492 rpc_cn_sm_ctlblk_t *sm_p; 3493 3494 RPC_CN_DBG_RTN_PRINTF(SERVER rem_mark_abort_can_action_rtn); 3495 3496 /* 3497 * The special structure is a pointer to the association. 3498 */ 3499 assoc = (rpc_cn_assoc_t *) spc_struct; 3500 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 3501 3502 /* 3503 * Remove the association from the group, mark it with the 3504 * appropriate status, abort the underlying session/transport 3505 * connection and cancel the call executor thread. 3506 * 3507 * Note that since we are calling action routines from 3508 * within action routines, we need to update state as 3509 * a final step here. Otherwise, the action routines 3510 * we call now, would update sm_p->cur_state inappropriately 3511 * for rem_mark_abort_action_rtn(). 3512 */ 3513 rem_assoc_from_grp_action_rtn (spc_struct, event_param, sm); 3514 abort_assoc_action_rtn (spc_struct, event_param, sm); 3515 mark_assoc_action_rtn (spc_struct, event_param, sm); 3516 cancel_calls_action_rtn (spc_struct, event_param, sm); 3517 3518 sm_p->cur_state = RPC_C_SERVER_ASSOC_CLOSED; 3519 return (assoc->assoc_status); 3520} 3521 3522 3523/* 3524**++ 3525** 3526** ROUTINE NAME: do_assoc_wait_action_rtn 3527** 3528** SCOPE: INTERNAL - declared locally 3529** 3530** DESCRIPTION: 3531** 3532** Action routine to process multiple rpc_bind PDU packets 3533** and reconstruct the security information. 3534** 3535** If we call this routine, this packet is expected to be one of 3536** a series of rpc_bind packets contaiining security information. 3537** 3538** INPUTS: 3539** 3540** spc_struct The association. Note that this is passed in as 3541** the special structure which is passed to the 3542** state machine event evaluation routine. 3543** 3544** event_param The fragbuf containing the rpc_bind PDU. 3545** This is passed in as the special event related 3546** parameter which was passed to the state machine 3547** evaluation routine. 3548** 3549** INPUTS/OUTPUTS: 3550** 3551** sm The control block from the event evaluation 3552** routine. Input is the current state and 3553** event for the control block. Output is the 3554** next state or updated current state, for the 3555** control block. 3556** 3557** OUTPUTS: none 3558** 3559** IMPLICIT INPUTS: none 3560** 3561** IMPLICIT OUTPUTS: none 3562** 3563** FUNCTION VALUE: completion status, one of: 3564** rpc_s_ok 3565** 3566** SIDE EFFECTS: none 3567** 3568**-- 3569**/ 3570 3571INTERNAL unsigned32 do_assoc_wait_action_rtn 3572( 3573 dce_pointer_t spc_struct, 3574 dce_pointer_t event_param, 3575 dce_pointer_t sm 3576) 3577{ 3578 rpc_cn_assoc_t *assoc; 3579 rpc_cn_packet_t *req_header; 3580 rpc_cn_sm_event_entry_t event; 3581 rpc_cn_sm_ctlblk_t *sm_p; 3582 unsigned32 status; 3583 3584 RPC_CN_DBG_RTN_PRINTF(SERVER do_assoc_wait_action_rtn); 3585 3586 /* 3587 * The special structure is a pointer to the association. 3588 */ 3589 assoc = (rpc_cn_assoc_t *) spc_struct; 3590 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 3591 3592 /* 3593 * The event parameter is a pointer to the fragbuf containing 3594 * the rpc_bind PDU. 3595 */ 3596 req_header = (rpc_cn_packet_t *) ((rpc_cn_fragbuf_t *)event_param)->data_p; 3597 3598 /* 3599 * Save the security frament in the association reconstruction buffer 3600 */ 3601 status = save_sec_fragment(assoc, req_header); 3602 if (status != rpc_s_ok) 3603 return (status); 3604 3605 /* 3606 * Now we check to see if this is the last packet for this rpc_bind PDU 3607 * If it is, we send a assoc_complete event through the state 3608 * machine, and run this PDU through the 'old' association request code. 3609 */ 3610 if (RPC_CN_PKT_FLAGS (req_header) & RPC_C_CN_FLAGS_LAST_FRAG) 3611 { 3612 event.event_id = RPC_C_ASSOC_ASSOC_COMPLETE_RESP; 3613 event.event_param = event_param; 3614 RPC_CN_ASSOC_INSERT_EVENT (assoc, &event); 3615 } 3616 3617 sm_p->cur_state = RPC_C_SERVER_ASSOC_WAIT; 3618 return (rpc_s_ok); 3619} 3620 3621 3622/* 3623**++ 3624** 3625** ROUTINE NAME: do_assoc_action_rtn 3626** 3627** SCOPE: INTERNAL - declared locally 3628** 3629** DESCRIPTION: 3630** 3631** Action routine vectors to either do_assoc_wait_action_rtn 3632** or to do_assoc_req_action_rtn, depending on predicate value. 3633** 3634** INPUTS: 3635** 3636** spc_struct The association. Note that this is passed in as 3637** the special structure which is passed to the 3638** state machine event evaluation routine. 3639** 3640** event_param The fragbuf containing the rpc_bind PDU. 3641** This is passed in as the special event related 3642** parameter which was passed to the state machine 3643** evaluation routine. 3644** 3645** INPUTS/OUTPUTS: 3646** 3647** sm The control block from the event evaluation 3648** routine. Input is the current state and 3649** event for the control block. Output is the 3650** next state or updated current state, for the 3651** control block. 3652** 3653** OUTPUTS: none 3654** 3655** IMPLICIT INPUTS: none 3656** 3657** IMPLICIT OUTPUTS: none 3658** 3659** FUNCTION VALUE: completion status, one of: 3660** rpc_s_ok 3661** 3662** SIDE EFFECTS: none 3663** 3664**-- 3665**/ 3666 3667INTERNAL unsigned32 do_assoc_action_rtn 3668( 3669 dce_pointer_t spc_struct, 3670 dce_pointer_t event_param, 3671 dce_pointer_t sm 3672) 3673{ 3674 rpc_cn_assoc_t *assoc; 3675 rpc_cn_packet_t *req_header ATTRIBUTE_UNUSED; 3676 rpc_cn_sm_event_entry_t event ATTRIBUTE_UNUSED; 3677 rpc_cn_sm_ctlblk_t *sm_p ATTRIBUTE_UNUSED; 3678 unsigned32 status; 3679 3680 RPC_CN_DBG_RTN_PRINTF(SERVER do_assoc_action_rtn); 3681 assoc = (rpc_cn_assoc_t *) spc_struct; 3682 3683 status = lastbindfrag_pred_rtn (spc_struct, event_param); 3684 if (status == 0) 3685 { 3686 do_assoc_wait_action_rtn (spc_struct, event_param, sm); 3687 return (rpc_s_ok); 3688 } 3689 3690 do_assoc_req_action_rtn (spc_struct, event_param, sm); 3691 return (assoc->assoc_status); 3692} 3693 3694 3695/* 3696**++ 3697** 3698** ROUTINE NAME: rpc__cn_assoc_process_auth_tlr 3699** 3700** SCOPE: INTERNAL - declared locally 3701** 3702** DESCRIPTION: 3703** 3704** Support routine to decode an auth trailer on an bind or alter 3705** context PDU and format the auth trailer on a bind_ack or 3706** alter_context_response PDU 3707** 3708** If the client had to break part the security information 3709** we have passed through the assoc_wait state and we must 3710** use the re-constuction buffer, not the info in the PDU. 3711** 3712** In addition, since we delayed checksumming the packets 3713** which contained the pieces of the sec info, we have to 3714** do this too. 3715** 3716** INPUTS: 3717** 3718** assoc The association. 3719** req_header bind or alter_context PDU. 3720** req_header_size The size of the bind or alter_context PDU. 3721** resp_header partially formatted bind_ack or alter_context_response 3722** PDU. 3723** 3724** INPUTS/OUTPUTS: 3725** 3726** header_size On input, the size used in the 3727** resp_header already. On output, 3728** the size of the resp_header including the 3729** trailer. 3730** 3731** OUTPUTS: none 3732** 3733** auth_len The size of the auth_value field in the auth trailer. 3734** sec_context The security context element used. 3735** st The return status of this routine. 3736** rpc_s_ok 3737** 3738** IMPLICIT INPUTS: none 3739** 3740** IMPLICIT OUTPUTS: none 3741** 3742** FUNCTION VALUE: none 3743** 3744** SIDE EFFECTS: none 3745** 3746**-- 3747**/ 3748 3749INTERNAL void rpc__cn_assoc_process_auth_tlr 3750( 3751 rpc_cn_assoc_p_t assoc, 3752 rpc_cn_packet_p_t req_header, 3753 unsigned32 req_header_size, 3754 rpc_cn_packet_p_t resp_header, 3755 unsigned32 *header_size, 3756 unsigned32 *auth_len, 3757 rpc_cn_sec_context_p_t *sec_context, 3758 boolean old_client, 3759 unsigned32 *st 3760) 3761{ 3762 rpc_cn_auth_tlr_t *req_auth_tlr; 3763 rpc_cn_auth_tlr_t *resp_auth_tlr; 3764 rpc_auth_info_t *info; 3765 rpc_cn_sec_context_t *sec; 3766 rpc_cn_bind_auth_value_priv_p_t local_auth_value, priv_auth_value; 3767 unsigned32 local_auth_value_len; 3768 rpc_authn_protocol_id_t authn_protocol; 3769 3770 RPC_CN_DBG_RTN_PRINTF(SERVER rpc__cn_assoc_process_auth_tlr); 3771 CODING_ERROR (st); 3772 3773 /* 3774 * If security was requested in the request PDU a 3775 * security response is required in the response PDU. 3776 * All security related errors will be reported within the 3777 * auth_value field of the auth trailer of the 3778 * response PDU. 3779 */ 3780 if (!RPC_CN_PKT_AUTH_TLR_PRESENT (req_header)) 3781 { 3782 *auth_len = 0; 3783 *st = rpc_s_ok; 3784 goto DONE; 3785 } 3786 RPC_DBG_PRINTF (rpc_e_dbg_auth, 20, 3787 ("(rpc__cn_assoc_process_auth_tlr) auth trailer present\n")); 3788 3789 /* 3790 * First make sure the authentication protocol requested is 3791 * supported here. If not, send a bind_nak PDU back to the 3792 * client. 3793 */ 3794 req_auth_tlr = RPC_CN_PKT_AUTH_TLR (req_header, 3795 req_header_size); 3796 authn_protocol = RPC_CN_AUTH_CVT_ID_WIRE_TO_API ( req_auth_tlr->auth_type, st); 3797 if (*st != rpc_s_ok) 3798 { 3799 goto DONE; 3800 } 3801 if ( ! RPC_CN_AUTH_INQ_SUPPORTED ( authn_protocol)) 3802 { 3803 *st = rpc_s_unknown_auth_protocol; 3804 goto DONE; 3805 } 3806 /* 3807 * Determine whether a security context with the given 3808 * key ID already exists. If it does this is an attempt at 3809 * renewing said context. 3810 */ 3811 sec = *sec_context = NULL; 3812 rpc__cn_assoc_sec_lkup_by_id (assoc, 3813 req_auth_tlr->key_id, 3814 &sec, 3815 st); 3816 *st = rpc_s_ok; 3817 if (sec == NULL) 3818 { 3819 RPC_CN_AUTH_CREATE_INFO ( 3820 authn_protocol, 3821 req_auth_tlr->auth_level, 3822 &info, 3823 st); 3824 } 3825 if (*st != rpc_s_ok) 3826 { 3827 dce_error_string_t error_text; 3828 int temp_status; 3829 3830 dce_error_inq_text(*st, error_text, &temp_status); 3831 3832 /* 3833 * "%s failed: %s" 3834 */ 3835 rpc_dce_svc_printf ( 3836 __FILE__, __LINE__, 3837 "%s %x", 3838 rpc_svc_auth, 3839 svc_c_sev_error, 3840 rpc_m_call_failed, 3841 "RPC_CN_AUTH_CREATE_INFO", 3842 error_text ); 3843 goto DONE; 3844 } 3845 if (sec == NULL) 3846 { 3847 sec = rpc__cn_assoc_sec_alloc (info, 3848 st); 3849 } 3850 else 3851 { 3852 info = NULL; 3853 } 3854 if (*st != rpc_s_ok) 3855 { 3856 goto DONE; 3857 } 3858 3859 sec->sec_key_id = req_auth_tlr->key_id; 3860 /* 3861 * Get the assoc_uuid_crc and put it in the association. 3862 * Get it from the last packet recieved. 3863 */ 3864 RPC_CN_AUTH_TLR_UUID_CRC ( 3865 authn_protocol, 3866 (dce_pointer_t)req_auth_tlr->auth_value, 3867 RPC_CN_PKT_AUTH_LEN (req_header), 3868 &assoc->security.assoc_uuid_crc); 3869 3870 /* 3871 * Check to see if we have pieced together the 3872 * auth_value and should use that buffer 3873 */ 3874 if (assoc->security.auth_buffer_info.auth_buffer != NULL) 3875 { 3876 local_auth_value = (rpc_cn_bind_auth_value_priv_t *) 3877 assoc->security.auth_buffer_info.auth_buffer; 3878 local_auth_value_len = assoc->security.auth_buffer_info.auth_buffer_len; 3879 /* 3880 * Better safe than sorry: make sure we get sub_type from the 3881 * packet we are going to checksum. 3882 */ 3883 local_auth_value->sub_type = ((rpc_cn_bind_auth_value_priv_t *) 3884 req_auth_tlr->auth_value)->sub_type; 3885 } 3886 else 3887 { 3888 local_auth_value = (rpc_cn_bind_auth_value_priv_t *) 3889 req_auth_tlr->auth_value; 3890 local_auth_value_len = RPC_CN_PKT_AUTH_LEN(req_header); 3891 } 3892 3893 /* 3894 * Verifing the auth tlr may involve making rpc requests which could end up 3895 * calling rpc__cn_binding_alloc(). Drop the global lock so we do not 3896 * deadlock. 3897 */ 3898 RPC_CN_UNLOCK (); 3899 3900 RPC_CN_AUTH_VFY_CLIENT_REQ (&assoc->security, 3901 sec, 3902 (dce_pointer_t)local_auth_value, 3903 local_auth_value_len, 3904 old_client, 3905 &sec->sec_status); 3906 RPC_CN_LOCK (); 3907 3908 if (sec->sec_status == rpc_s_ok) 3909 { 3910 /* 3911 * We only checksum one packet, since we ignored everything 3912 * in the others. We want to pass the cred_length of the packet 3913 * we are doing the checksum on. 3914 */ 3915 priv_auth_value = (rpc_cn_bind_auth_value_priv_t *) 3916 req_auth_tlr->auth_value; 3917 if (assoc->raw_packet_p != NULL) 3918 { 3919 /* 3920 * Use the raw packet if it exists. 3921 */ 3922 RPC_CN_AUTH_RECV_CHECK (authn_protocol, 3923 &assoc->security, 3924 sec, 3925 (rpc_cn_common_hdr_t *)assoc->raw_packet_p->data_p, 3926 assoc->raw_packet_p->data_size, 3927 priv_auth_value->cred_length, 3928 req_auth_tlr, 3929 0, /* dummy unpack_ints */ 3930 &sec->sec_status); 3931 } 3932 else 3933 { 3934 /* 3935 * Raw packet doesn't exist; use unpacked one. 3936 */ 3937 RPC_CN_AUTH_RECV_CHECK (authn_protocol, 3938 &assoc->security, 3939 sec, 3940 (rpc_cn_common_hdr_t *)req_header, 3941 req_header_size, 3942 priv_auth_value->cred_length, 3943 req_auth_tlr, 3944 0, /* dummy unpack_ints */ 3945 &sec->sec_status); 3946 } 3947 } /* sec->sec_status == rpc_s_ok */ 3948 3949 /* 3950 * Free assembly buffer 3951 */ 3952 if (assoc->security.auth_buffer_info.auth_buffer) 3953 { 3954 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_BIG_PAC, 3955 ("(rpc__cn_assoc_process_auth_tlr) Free'd auth_buffer: %p\n", 3956 assoc->security.auth_buffer_info.auth_buffer)); 3957 3958 RPC_MEM_FREE(assoc->security.auth_buffer_info.auth_buffer, 3959 RPC_C_MEM_CN_PAC_BUF); 3960 assoc->security.auth_buffer_info.auth_buffer = NULL; 3961 assoc->security.auth_buffer_info.auth_buffer_len = 0; 3962 assoc->security.auth_buffer_info.auth_buffer_max = 0; 3963 } 3964 3965 /* 3966 * Start filling in the response packet 3967 */ 3968 *header_size = ((*header_size + 3) & ~0x3); 3969 resp_auth_tlr = (rpc_cn_auth_tlr_t *) 3970 ((unsigned8 *)(resp_header) + *header_size); 3971 (void) memset(resp_auth_tlr, 0, (rpc_g_cn_large_frag_size - *header_size)); 3972 resp_auth_tlr->auth_type = req_auth_tlr->auth_type; 3973 resp_auth_tlr->auth_level = req_auth_tlr->auth_level; 3974 resp_auth_tlr->stub_pad_length = 0; 3975 resp_auth_tlr->reserved = 0; 3976 resp_auth_tlr->key_id = req_auth_tlr->key_id; 3977 *header_size += RPC_CN_PKT_SIZEOF_COM_AUTH_TLR; 3978 *auth_len = rpc_g_cn_large_frag_size - *header_size; 3979 3980#ifdef DEBUG 3981 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_FRAG_BIND_ACK)) 3982 { 3983 char *x; 3984 *auth_len = atoi(((x = getenv("BIND_ACK_FRAG")) == NULL ? "50" : x)); 3985 } 3986#endif 3987 3988 /* 3989 * We need to handle large security info if its not going to 3990 * fit inside one fragbuf. So this routine will store a 3991 * long KRB message in assoc->security->krb_message. 3992 * When the PDU is sent, the rest of the security will be sent. 3993 */ 3994 RPC_CN_AUTH_FMT_SRVR_RESP (sec->sec_status, 3995 &assoc->security, 3996 sec, 3997 (dce_pointer_t)req_auth_tlr->auth_value, 3998 RPC_CN_PKT_AUTH_LEN (req_header), 3999 (dce_pointer_t)resp_auth_tlr->auth_value, 4000 auth_len); 4001 4002 /* auth_len now has length of auth_value */ 4003 *header_size += *auth_len; 4004 4005 if (sec->sec_status != rpc_s_ok) 4006 { 4007 dce_error_string_t error_text; 4008 int temp_status; 4009 4010 dce_error_inq_text(sec->sec_status, error_text, &temp_status); 4011 4012 /* 4013 * "%s on server failed: %s" 4014 */ 4015 rpc_dce_svc_printf ( 4016 __FILE__, __LINE__, 4017 "%s %x", 4018 rpc_svc_auth, 4019 svc_c_sev_error, 4020 rpc_m_call_failed_s, 4021 "RPC_CN_AUTH_VFY_CLIENT_REQ", 4022 error_text ); 4023 4024 RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_SECURITY_ERRORS, 4025 ("CN: call_rep->%p assoc->%p desc->%p client verification failed security_context->%p auth_type->%x auth_level->%x auth_len->%x stub_pad_length->%x st->%x\n", 4026 assoc->call_rep, 4027 assoc, 4028 assoc->cn_ctlblk.cn_sock, 4029 sec, 4030 req_auth_tlr->auth_type, 4031 req_auth_tlr->auth_level, 4032 RPC_CN_PKT_AUTH_LEN (req_header), 4033 req_auth_tlr->stub_pad_length, 4034 sec->sec_status)); 4035 sec->sec_state = RPC_C_SEC_STATE_INCOMPLETE; 4036 } else { 4037 sec->sec_state = RPC_C_SEC_STATE_COMPLETE; 4038 } 4039 RPC_LIST_ADD_TAIL (assoc->security.context_list, 4040 sec, 4041 rpc_cn_sec_context_p_t); 4042 assoc->security.assoc_have_uuid_crc = true; 4043 *sec_context = sec; 4044 4045 if (info != NULL) 4046 { 4047 RPC_CN_AUTH_RELEASE_REFERENCE(&info); 4048 } 4049 4050DONE: 4051 /* 4052 * Deallocate the raw packet if it exists. 4053 */ 4054 if (assoc->raw_packet_p != NULL) 4055 { 4056 rpc__cn_fragbuf_free (assoc->raw_packet_p); 4057 assoc->raw_packet_p = NULL; 4058 } 4059} 4060 4061 4062/* 4063**++ 4064** 4065** ROUTINE NAME: send_frag_resp_pdu 4066** 4067** SCOPE: INTERNAL - declared locally 4068** 4069** DESCRIPTION: 4070** 4071** Support routine to send a bind_ack or alter_context_response PDU 4072** with fragmented security. 4073** 4074** If the security information did not all fit in to the first 4075** response fragbuf, we will send it and as many more as it 4076** takes to completely send the credential information. 4077** 4078** INPUTS: 4079** 4080** assoc The association. 4081** fragbuf The response fragbuf. 4082** header The header of the rpc_bind_ack or alter_context_resp 4083** 4084** INPUTS/OUTPUTS: none 4085** 4086** OUTPUTS: none 4087** 4088** IMPLICIT INPUTS: 4089** 4090** assoc->security.krb_message Contains the credentials 4091** we might have to send in pieces. 4092** 4093** IMPLICIT OUTPUTS: none 4094** 4095** FUNCTION VALUE: none 4096** 4097** SIDE EFFECTS: none 4098** 4099**-- 4100**/ 4101 4102INTERNAL void send_frag_resp_pdu(assoc, 4103 fragbuf, 4104 header) 4105 4106rpc_cn_assoc_p_t assoc; 4107rpc_cn_fragbuf_p_t fragbuf; 4108rpc_cn_packet_p_t header; 4109 4110{ 4111 sec_krb_message *krb_message_ptr; 4112 rpc_cn_auth_tlr_t *auth_tlr; 4113 rpc_cn_bind_auth_value_priv_t *auth_value; 4114 unsigned32 cred_remain; 4115 unsigned32 flags; 4116 unsigned32 cred_len; 4117 unsigned32 msg_length; 4118 unsigned32 offset = 0; 4119 boolean first_frag = true; 4120 boolean free_buf = false; 4121 boolean free_message=false; 4122 4123 /* 4124 * We stashed the KRB_AP_REP message here when we built it. 4125 */ 4126 krb_message_ptr = &(assoc->security.krb_message); 4127 cred_remain = krb_message_ptr->length; 4128 4129 auth_tlr = RPC_CN_PKT_AUTH_TLR (header, RPC_CN_PKT_FRAG_LEN (header)); 4130 auth_value = (rpc_cn_bind_auth_value_priv_t *)auth_tlr->auth_value; 4131 4132 /* 4133 * We want to send the first PDU as is, since its all set 4134 * to go, but we may need to send the same fragbuf several 4135 * times to get all the security info across. 4136 * 4137 * Slightly different than the client side as we are filling 4138 * in only the credentials field, not the whole auth_value_t. 4139 */ 4140 do 4141 { 4142 flags = 0; 4143 4144 if (first_frag) 4145 { 4146 flags = RPC_C_CN_FLAGS_FIRST_FRAG; 4147 first_frag = false; 4148 } 4149 4150 cred_len = auth_value->cred_length; 4151 if (cred_remain > 0) 4152 { 4153 cred_remain -= cred_len; 4154 } 4155 4156 if (cred_remain == 0) 4157 { 4158 flags |= RPC_C_CN_FLAGS_LAST_FRAG; 4159 free_buf = true; 4160 } 4161 4162 RPC_CN_PKT_FLAGS (header) = flags; 4163 4164 /* 4165 * Now actually send the PDU. Free it if free_buf set. 4166 */ 4167 rpc__cn_assoc_send_fragbuf (assoc, 4168 fragbuf, 4169 assoc->security.assoc_current_sec_context, 4170 free_buf, 4171 &(assoc->assoc_status)); 4172 4173 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_BIG_PAC, 4174("(send_frag_resp_pdu) SENT %s PDU: data_size=%u, first_frag=%s, last_frag=%s, cred_len=%u, cred_remain=%u\n", 4175 ((RPC_CN_PKT_PTYPE(header) == RPC_C_CN_PKT_BIND_ACK) ? 4176 "rpc_bind_ack" : "alter_context_resp"), 4177 fragbuf->data_size, 4178 (flags & RPC_C_CN_FLAGS_FIRST_FRAG) ? "true": "false", 4179 (flags & RPC_C_CN_FLAGS_LAST_FRAG) ? "true": "false", 4180 cred_len, 4181 cred_remain)); 4182 4183 if (cred_remain > 0) 4184 { 4185 /* We didn't free the krb_message in fmt_srvr_resp */ 4186 free_message = true; 4187 4188 /* 4189 * Zero out old cred info and put in next segment 4190 */ 4191 (void) memset(auth_value->credentials, 0, cred_len); 4192 4193 /* 4194 * If the rest of the creditials will all fit, put it in, 4195 * otherwise use the same number of bytes as before. 4196 */ 4197 if (cred_len > cred_remain) 4198 { 4199 unsigned32 shorten = (cred_len - cred_remain); 4200 4201 msg_length = cred_remain; 4202 auth_value->cred_length = cred_remain; 4203 fragbuf->data_size -= shorten; 4204 RPC_CN_PKT_AUTH_LEN (header) -= shorten; 4205 RPC_CN_PKT_FRAG_LEN (header) = fragbuf->data_size; 4206 } 4207 else 4208 { 4209 msg_length = cred_len; 4210 } 4211 4212 offset += cred_len; 4213 assert((offset + msg_length) <= (unsigned32)krb_message_ptr->length); 4214 memcpy(auth_value->credentials, 4215 krb_message_ptr->data + offset, 4216 msg_length); 4217 } 4218 } while (cred_remain > 0); 4219 4220 /* 4221 * Free the krb_message if we need to. 4222 */ 4223 if (free_message) 4224 { 4225#ifdef AUTH_KRB 4226 sec_krb_message_free (krb_message_ptr); 4227#endif 4228 4229 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_BIG_PAC, 4230 ("(send_frag_resp_pdu) Freeing KRB message: 0x%p\n", 4231 krb_message_ptr)); 4232 } 4233} 4234 4235 4236/* 4237**++ 4238** 4239** ROUTINE NAME: save_sec_fragment 4240** 4241** SCOPE: INTERNAL - declared locally 4242** 4243** DESCRIPTION: 4244** 4245** Support routine which copies the bytes in the credential 4246** field of an auth_tlr into a reconstruction buffer. 4247** 4248** Used to process rpc_bind and alter_context PDU's which 4249** have fragmented credentials 4250** 4251** INPUTS: 4252** 4253** assoc The association. 4254** header The header of the rpc_bind or alter_context PDU. 4255** 4256** INPUTS/OUTPUTS: none 4257** 4258** OUTPUTS: rpc_s_ok on success, rpc_s_bad_pkt on failure 4259** 4260** IMPLICIT INPUTS: 4261** 4262** assoc->security.auth_buffer_info Contains the pieces of credentials 4263** we have previously saved. 4264** 4265** IMPLICIT OUTPUTS: none 4266** 4267** FUNCTION VALUE: none 4268** 4269** SIDE EFFECTS: none 4270** 4271**-- 4272**/ 4273 4274INTERNAL unsigned32 save_sec_fragment(rpc_cn_assoc_p_t assoc, 4275 rpc_cn_packet_p_t header) 4276 4277{ 4278 rpc_cn_bind_auth_value_priv_t *auth_value; 4279 unsigned32 auth_value_len; 4280 rpc_cn_auth_tlr_t *auth_tlr; 4281 unsigned8 *auth_buffer; 4282 unsigned32 auth_buffer_max; 4283 unsigned32 auth_buffer_len; 4284 4285 /* 4286 * This is a place where we stash the auth information while we 4287 * reconstruct it. 4288 */ 4289 auth_buffer = assoc->security.auth_buffer_info.auth_buffer; 4290 auth_buffer_len = assoc->security.auth_buffer_info.auth_buffer_len; 4291 auth_buffer_max = assoc->security.auth_buffer_info.auth_buffer_max; 4292 4293 if (RPC_CN_PKT_AUTH_LEN (header) > UINT32_MAX - auth_buffer_len) { 4294 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_BIG_PAC, 4295 ("(save_sec_fragment) Error - RPC_CN_PKT_AUTH_LEN %d + auth_buffer_len %d too large\n", 4296 RPC_CN_PKT_AUTH_LEN (header), auth_buffer_len)); 4297 return (rpc_s_bad_pkt); 4298 } 4299 4300 if (auth_buffer == NULL) 4301 { 4302 /* 4303 * If we get here, odds are we are going to get maybe 1 or 2 more 4304 * packets, so get some space to save time later. 4305 */ 4306 auth_buffer_max = RPC_C_CN_LARGE_FRAG_SIZE * 3; 4307 4308 RPC_MEM_ALLOC(auth_buffer, unsigned8 *, 4309 auth_buffer_max, 4310 RPC_C_MEM_CN_PAC_BUF, 4311 RPC_C_MEM_WAITOK); 4312 4313 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_BIG_PAC, 4314 ("(save_sec_fragment) Alloc'd auth_buffer: %p, auth_buffer_max = %d\n", 4315 auth_buffer, 4316 auth_buffer_max)); 4317 4318 assoc->security.auth_buffer_info.auth_buffer = auth_buffer; 4319 assoc->security.auth_buffer_info.auth_buffer_max = auth_buffer_max; 4320 } 4321 4322 if ((RPC_CN_PKT_AUTH_LEN (header) + auth_buffer_len) > auth_buffer_max) 4323 { 4324 auth_buffer_max += RPC_C_CN_LARGE_FRAG_SIZE; 4325 4326 RPC_MEM_REALLOC(auth_buffer, unsigned8 *, 4327 auth_buffer_max, 4328 RPC_C_MEM_CN_PAC_BUF, 4329 RPC_C_MEM_WAITOK); 4330 4331 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_BIG_PAC, 4332("(save_sec_fragment) Realloc'd auth_buffer: %p, auth_buffer_max = %d\n", 4333 auth_buffer, 4334 auth_buffer_max)); 4335 4336 assoc->security.auth_buffer_info.auth_buffer = auth_buffer; 4337 assoc->security.auth_buffer_info.auth_buffer_max = auth_buffer_max; 4338 } 4339 4340 /* 4341 * Concatenate this security info on to the buffer. 4342 * 4343 * We have to watch out for the checksum at the end of the 4344 * auth trailer, we only want to recover the KRB_AP_{REQ|REP} message. 4345 */ 4346 auth_tlr = RPC_CN_PKT_AUTH_TLR(header, RPC_CN_PKT_FRAG_LEN (header)); 4347 auth_value = (rpc_cn_bind_auth_value_priv_t *)auth_tlr->auth_value; 4348 4349 if (RPC_CN_PKT_AUTH_LEN (header) < auth_value->checksum_length) 4350 { 4351 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_BIG_PAC, 4352 ("(save_sec_fragment) Error - header auth len %d < checksum len %d \n", 4353 RPC_CN_PKT_AUTH_LEN (header), auth_value->checksum_length)); 4354 return (rpc_s_bad_pkt); 4355 } 4356 auth_value_len = RPC_CN_PKT_AUTH_LEN (header) - auth_value->checksum_length; 4357 4358 /* 4359 * For the first packet, copy the header info, for the rest 4360 * we just need the credential fragment. We also update 4361 * the cred_length field in the assembly buffer. 4362 */ 4363 4364 if (auth_buffer_len == 0) 4365 { 4366 if (auth_value_len > auth_buffer_max) 4367 { 4368 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_BIG_PAC, 4369 ("(save_sec_fragment) Error - auth_value_len %d > auth_buffer_max %d \n", 4370 auth_value_len, auth_buffer_max)); 4371 return (rpc_s_bad_pkt); 4372 } 4373 memcpy(auth_buffer, auth_value, auth_value_len); 4374 } 4375 else 4376 { 4377 if (auth_value_len < RPC_CN_PKT_SIZEOF_BIND_AUTH_VAL) 4378 { 4379 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_BIG_PAC, 4380 ("(save_sec_fragment) Error - auth_value_len too small %d < RPC_CN_PKT_SIZEOF_BIND_AUTH_VAL %d \n", 4381 auth_value_len, RPC_CN_PKT_SIZEOF_BIND_AUTH_VAL)); 4382 return (rpc_s_bad_pkt); 4383 } 4384 auth_value_len -= RPC_CN_PKT_SIZEOF_BIND_AUTH_VAL; 4385 4386 if (auth_value->cred_length > RPC_CN_PKT_AUTH_LEN (header)) 4387 { 4388 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_BIG_PAC, 4389 ("(save_sec_fragment) Error - cred_length too large (%d) > RPC_CN_PKT_AUTH_LEN %d \n", 4390 auth_value->cred_length, RPC_CN_PKT_AUTH_LEN (header))); 4391 return (rpc_s_bad_pkt); 4392 } 4393 4394 if ((auth_buffer_len + auth_value->cred_length) > auth_buffer_max) 4395 { 4396 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_BIG_PAC, 4397 ("(save_sec_fragment) Error - auth buffer too small (%d + %d) > auth_buffer_max %d \n", 4398 auth_buffer_len, auth_value->cred_length, auth_buffer_max)); 4399 return (rpc_s_bad_pkt); 4400 } 4401 memcpy(auth_buffer + auth_buffer_len, 4402 auth_value->credentials, 4403 auth_value->cred_length); 4404 ((rpc_cn_bind_auth_value_priv_t *)auth_buffer)->cred_length += auth_value->cred_length; 4405 } 4406 4407 RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_BIG_PAC, 4408 ("(save_sec_fragment) Copied to auth_buffer: %p, auth_buffer_len=%d, auth_value_len=%d, auth_buffer_max=%d\n", 4409 auth_buffer, auth_buffer_len, auth_value_len, auth_buffer_max)); 4410 4411 auth_buffer_len += auth_value_len; 4412 4413 /* 4414 * Update our per-association data 4415 */ 4416 assoc->security.auth_buffer_info.auth_buffer = auth_buffer; 4417 assoc->security.auth_buffer_info.auth_buffer_len = auth_buffer_len; 4418 assoc->security.auth_buffer_info.auth_buffer_max = auth_buffer_max; 4419 4420 return (rpc_s_ok); 4421} 4422/* vim:sw=4 ts=4 4423 * */ 4424