/* * * (c) Copyright 1990 OPEN SOFTWARE FOUNDATION, INC. * (c) Copyright 1990 HEWLETT-PACKARD COMPANY * (c) Copyright 1990 DIGITAL EQUIPMENT CORPORATION * To anyone who acknowledges that this file is provided "AS IS" * without any express or implied warranty: * permission to use, copy, modify, and distribute this * file for any purpose is hereby granted without fee, provided that * the above copyright notices and this notice appears in all source * code copies, and that none of the names of Open Software * Foundation, Inc., Hewlett-Packard Company, or Digital Equipment * Corporation be used in advertising or publicity pertaining to * distribution of the software without specific, written prior * permission. Neither Open Software Foundation, Inc., Hewlett- * Packard Company, nor Digital Equipment Corporation makes any * representations about the suitability of this software for any * purpose. * */ /* */ /* ** ** NAME ** ** cnsassm.c ** ** FACILITY: ** ** Remote Procedure Call (RPC) ** ** ABSTRACT: ** ** NCA Connection (cn) Server (s) Association (as) State Machine (sm). ** ** */ #include /* Common declarations for all RPC runtime */ #include /* Common communications services */ #include /* Common protocol services */ #include /* Network Data Representation syntax global defs */ #include /* Network Data Representation syntax defs */ #include /* NCA Connection private declarations */ #include /* NCA Connection local ID service */ #include /* NCA Connection network service */ #include /* NCA Connection protocol header */ #include /* NCA Connection association services */ #include /* Externals for Call Thread sub-component */ #include /* NCA connection call service */ #include /* NCA Connection state machine declarations */ #include /* NCA Connection fragment buffer service */ #include /* NCA Connection association state machine */ /******************************************************************************/ /* * Global Definitions */ GLOBAL char *rpc_g_cn_assoc_server_events [] = { "INDICATION", "ABORT_REQ", "REJ_RESP", "ALT_CONT_IND", "NO_CONN_IND", "ALT_CONT_RESP", "AUTH3_IND", "AUTH3_ACK", "AUTH3_NACK", "ALLOC_REQ", "DEALLOC_REQ", "SHUTDOWN_REQ", "LOCAL_ERROR", "ACC_RESP", "ASSOC_COMPLETE" }; GLOBAL char *rpc_g_cn_assoc_server_states [] = { "CLOSED", "REQUESTED", "AUTH3_WAIT", "AUTH3", "OPEN", "ASSOC_WAIT" }; /******************************************************************************/ /* * Local defines */ /******************************************************************************/ /******************************************************************************/ /* * Internal function prototyes */ /******************************************************************************/ INTERNAL void rpc__cn_assoc_process_auth_tlr _DCE_PROTOTYPE_ (( rpc_cn_assoc_p_t /*assoc*/, rpc_cn_packet_p_t /*req_header*/, unsigned32 /*req_header_size*/, rpc_cn_packet_p_t /*resp_header*/, unsigned32 * /*header_size*/, unsigned32 * /*auth_len*/, rpc_cn_sec_context_p_t * /*sec_context*/, boolean old_client, unsigned32 * /*st*/)); INTERNAL void send_frag_resp_pdu _DCE_PROTOTYPE_ (( rpc_cn_assoc_p_t /*assoc*/, rpc_cn_fragbuf_p_t /*fragbuf*/, rpc_cn_packet_p_t /*req_header*/)); INTERNAL void save_sec_fragment _DCE_PROTOTYPE_ (( rpc_cn_assoc_p_t /*assoc*/, rpc_cn_packet_p_t /*header*/)); /***********************************************************************/ /* * 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 * * * The predicates. All predicates except those noted below are described * in the NCA Connection architecture spec. * As a performance enhancement, * we have revamped many predicate routines as macros and have absorbed * the predicates into the actions. Thus, there is no longer a need * for the predicate table; the predicate declarations too, are * modified. */ /* #define AUTHENT3_PRED 0 * #define ACTIVE_PRED 1 * #define LASTBIND_PRED 2 */ /* * The predicate routine prototypes. */ INTERNAL unsigned8 authent3_pred_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/)) ATTRIBUTE_UNUSED; INTERNAL unsigned8 active_pred_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/)) ATTRIBUTE_UNUSED; INTERNAL unsigned8 lastbindfrag_pred_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/)); /***********************************************************************/ /* * S E R V E R A S S O C A C T I O N T A B L E * * * The actions. All actions except those noted below are described * in the NCA Connection architecture spec. */ #define ACCEPT_ASSOC 0 #define REJECT_ASSOC 1 #define ADD_ASSOC_TO_GRP 2 #define REM_ASSOC_FROM_GRP 3 #define DO_ALTER_CONT_REQ 4 #define SEND_ALTER_CONT_RESP 5 #define DO_AUTHENT3 6 #define DO_ASSOC_REQ 7 #define SEND_SHUTDOWN_REQ 8 #define INCR_ACTIVE 9 #define DECR_ACTIVE 10 #define ABORT_ASSOC 11 #define MARK_ASSOC 12 #define CANCEL_CALLS 13 #define ACCEPT_ADD 14 #define REM_MARK_ABORT 15 #define REM_MARK_CANCEL 16 #define INCR_DO_ALTER 17 #define SEND_DECR 18 #define MARK_ABORT 19 #define REM_MARK_ABORT_CAN 20 #define PROTOCOL_ERROR 21 #define DO_ASSOC_WAIT 22 #define DO_ASSOC 23 /* * The action routine prototypes. */ INTERNAL unsigned32 accept_assoc_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); INTERNAL unsigned32 reject_assoc_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); INTERNAL unsigned32 add_assoc_to_grp_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); INTERNAL unsigned32 rem_assoc_from_grp_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); INTERNAL unsigned32 do_alter_cont_req_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); INTERNAL unsigned32 send_alter_cont_resp_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); INTERNAL unsigned32 do_authent3_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); INTERNAL unsigned32 do_assoc_req_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); INTERNAL unsigned32 send_shutdown_req_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); INTERNAL unsigned32 incr_active_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); INTERNAL unsigned32 decr_active_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); INTERNAL unsigned32 abort_assoc_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); INTERNAL unsigned32 mark_assoc_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); INTERNAL unsigned32 cancel_calls_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); INTERNAL unsigned32 accept_add_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); INTERNAL unsigned32 rem_mark_abort_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); INTERNAL unsigned32 rem_mark_cancel_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); INTERNAL unsigned32 incr_do_alter_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); INTERNAL unsigned32 send_decr_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); INTERNAL unsigned32 mark_abort_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); INTERNAL unsigned32 rem_mark_abort_can_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); INTERNAL unsigned32 do_assoc_wait_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); INTERNAL unsigned32 do_assoc_action_rtn _DCE_PROTOTYPE_ (( pointer_t /*spc_struct*/, pointer_t /*event_param*/, pointer_t /*sm*/)); /* * The action table itself. */ GLOBAL rpc_cn_sm_action_fn_t rpc_g_cn_server_assoc_act_tbl [] = { accept_assoc_action_rtn, reject_assoc_action_rtn, add_assoc_to_grp_action_rtn, rem_assoc_from_grp_action_rtn, do_alter_cont_req_action_rtn, send_alter_cont_resp_action_rtn, do_authent3_action_rtn, do_assoc_req_action_rtn, send_shutdown_req_action_rtn, incr_active_action_rtn, decr_active_action_rtn, abort_assoc_action_rtn, mark_assoc_action_rtn, cancel_calls_action_rtn, accept_add_action_rtn, rem_mark_abort_action_rtn, rem_mark_cancel_action_rtn, incr_do_alter_action_rtn, send_decr_action_rtn, mark_abort_action_rtn, rem_mark_abort_can_action_rtn, rpc__cn_assoc_sm_protocol_error, do_assoc_wait_action_rtn, do_assoc_action_rtn }; /***********************************************************************/ /* * S E R V E R A S S O C S T A T E T A B L E * * * C L O S E D _ S T A T E * * state 0 - closed. The association is unknown to the server. */ INTERNAL rpc_cn_sm_state_tbl_entry_t closed_state = { /* event 0 - ind */ {DO_ASSOC}, /* event 1 - abort_req */ {RPC_C_CLIENT_ASSOC_CLOSED}, /* event 2 - reject_resp */ {RPC_C_CLIENT_ASSOC_CLOSED}, /* event 3 - alter_context_ind */ {RPC_C_CLIENT_ASSOC_CLOSED}, /* event 4 - no_conn_ind */ {RPC_C_CLIENT_ASSOC_CLOSED}, /* event 5 - alter_context_resp */ {RPC_C_CLIENT_ASSOC_CLOSED}, /* event 6 - auth3_ind */ {RPC_C_CLIENT_ASSOC_CLOSED}, /* event 7 - auth3_ack */ {RPC_C_CLIENT_ASSOC_CLOSED}, /* event 8 - auth3_nack */ {RPC_C_CLIENT_ASSOC_CLOSED}, /* event 9 - allocate_req */ {RPC_C_CLIENT_ASSOC_CLOSED}, /* event 10 - deallocate_req */ {RPC_C_CLIENT_ASSOC_CLOSED}, /* event 11 - shutdown_req */ {RPC_C_CLIENT_ASSOC_CLOSED}, /* event 12 - local_error */ {RPC_C_CLIENT_ASSOC_CLOSED}, /* event 13 - accept_resp */ {RPC_C_CLIENT_ASSOC_CLOSED}, /* event 14 - assoc_complete_resp */ ILLEGAL_TRANSITION }; /* * R E Q U E S T E D _ S T A T E * * state 1 - requested_wait. The server has received a complete rpc_bind PDU * and is processing it. */ INTERNAL rpc_cn_sm_state_tbl_entry_t requested_state = { /* event 0 - ind */ ILLEGAL_TRANSITION, /* event 1 - abort_req */ {ABORT_ASSOC}, /* event 2 - reject_resp */ {REJECT_ASSOC}, /* event 3 - alter_context_ind */ ILLEGAL_TRANSITION, /* event 4 - no_conn_ind */ {MARK_ASSOC}, /* event 5 - alter_context_resp */ ILLEGAL_TRANSITION, /* event 6 - auth3_ind */ ILLEGAL_TRANSITION, /* event 7 - auth3_ack */ ILLEGAL_TRANSITION, /* event 8 - auth3_nack */ ILLEGAL_TRANSITION, /* event 9 - allocate_req */ ILLEGAL_TRANSITION, /* event 10 - deallocate_req */ ILLEGAL_TRANSITION, /* event 11 - shutdown_req */ {RPC_C_SERVER_ASSOC_REQUESTED}, /* event 12 - local_error */ {MARK_ABORT}, /* event 13 - accept_resp */ {ACCEPT_ADD}, /* event 14 - assoc_complete_resp */ ILLEGAL_TRANSITION }; /* * A U T H 3 _ W A I T _ S T A T E * * state 2 - auth3_wait. Wait for the 3rd leg of the optional 3-way * authentication handshake. */ INTERNAL rpc_cn_sm_state_tbl_entry_t auth3_wait_state = { /* event 0 - ind */ ILLEGAL_TRANSITION, /* event 1 - abort_req */ {ABORT_ASSOC}, /* event 2 - reject_resp */ ILLEGAL_TRANSITION, /* event 3 - alter_context_ind */ {DO_ALTER_CONT_REQ}, /* event 4 - no_conn_ind */ {MARK_ASSOC}, // {REM_MARK_CANCEL}, /* event 5 - alter_context_resp */ ILLEGAL_TRANSITION, /* event 6 - auth3_ind */ {DO_AUTHENT3}, /* event 7 - auth3_ack */ ILLEGAL_TRANSITION, /* event 8 - auth3_nack */ ILLEGAL_TRANSITION, /* event 9 - allocate_req */ ILLEGAL_TRANSITION, /* event 10 - deallocate_req */ ILLEGAL_TRANSITION, /* event 11 - shutdown_req */ {SEND_SHUTDOWN_REQ}, /* event 12 - local_error */ {MARK_ABORT}, /* event 13 - accept_resp */ ILLEGAL_TRANSITION, /* event 14 - assoc_complete_resp */ ILLEGAL_TRANSITION }; /* * A U T H 3 _ S T A T E * * state 3 - auth3_wait. Process the 3rd leg of the optional 3-way * authentication handshake. */ INTERNAL rpc_cn_sm_state_tbl_entry_t auth3_state = { /* event 0 - ind */ ILLEGAL_TRANSITION, /* event 1 - abort_req */ {ABORT_ASSOC}, /* event 2 - reject_resp */ ILLEGAL_TRANSITION, /* event 3 - alter_context_ind */ ILLEGAL_TRANSITION, /* event 4 - no_conn_ind */ {MARK_ASSOC}, // {REM_MARK_CANCEL}, /* event 5 - alter_context_resp */ {SEND_ALTER_CONT_RESP}, /* event 6 - auth3_ind */ ILLEGAL_TRANSITION, /* event 7 - auth3_ack */ {ADD_ASSOC_TO_GRP}, /* event 8 - auth3_nack */ {ABORT_ASSOC}, /* event 9 - allocate_req */ ILLEGAL_TRANSITION, /* event 10 - deallocate_req */ ILLEGAL_TRANSITION, /* event 11 - shutdown_req */ {SEND_SHUTDOWN_REQ}, /* event 12 - local_error */ {MARK_ABORT}, /* event 13 - accept_resp */ ILLEGAL_TRANSITION, /* event 14 - assoc_complete_resp */ ILLEGAL_TRANSITION }; /* * O P E N _ S T A T E * * state 4 - open. A successul association has been established. One * or more presentation syntaxes have successfully been negotiated. */ INTERNAL rpc_cn_sm_state_tbl_entry_t open_state = { /* event 0 - ind */ ILLEGAL_TRANSITION, /* event 1 - abort_req */ {REM_MARK_ABORT}, /* event 2 - reject_resp */ ILLEGAL_TRANSITION, /* event 3 - alter_context_ind */ {INCR_DO_ALTER}, /* event 4 - no_conn_ind */ {REM_MARK_CANCEL}, /* event 5 - alter_context_resp */ {SEND_DECR}, /* event 6 - auth3_ind */ ILLEGAL_TRANSITION, /* event 7 - auth3_ack */ ILLEGAL_TRANSITION, /* event 8 - auth3_nack */ ILLEGAL_TRANSITION, /* event 9 - allocate_req */ {INCR_ACTIVE}, /* event 10 - deallocate_req */ {DECR_ACTIVE}, /* event 11 - shutdown_req */ {SEND_SHUTDOWN_REQ}, /* event 12 - local_error */ {REM_MARK_ABORT_CAN}, /* event 13 - accept_resp */ ILLEGAL_TRANSITION, /* event 14 - assoc_complete_resp */ ILLEGAL_TRANSITION }; /* * A S S O C _ W A I T * * state 5 - assoc_wait. The server has received at least one rpc_bind PDU * packet already and is processing another. */ INTERNAL rpc_cn_sm_state_tbl_entry_t assoc_wait_state = { /* event 0 - ind */ {DO_ASSOC_WAIT}, /* event 1 - abort_req */ {ABORT_ASSOC}, /* event 2 - reject_resp */ {REJECT_ASSOC}, /* event 3 - alter_context_ind */ ILLEGAL_TRANSITION, /* event 4 - no_conn_ind */ {MARK_ASSOC}, /* event 5 - alter_context_resp */ ILLEGAL_TRANSITION, /* event 6 - auth3_ind */ ILLEGAL_TRANSITION, /* event 7 - auth3_ack */ ILLEGAL_TRANSITION, /* event 8 - auth3_nack */ ILLEGAL_TRANSITION, /* event 9 - allocate_req */ ILLEGAL_TRANSITION, /* event 10 - deallocate_req */ ILLEGAL_TRANSITION, /* event 11 - shutdown_req */ {RPC_C_SERVER_ASSOC_REQUESTED}, /* event 12 - local_error */ {MARK_ABORT}, /* event 13 - accept_resp */ {ACCEPT_ADD}, /* event 14 - assoc_complete_resp */ {DO_ASSOC_REQ} }; /* * The state table containing the action routines. */ GLOBAL rpc_cn_sm_state_entry_p_t rpc_g_cn_server_assoc_sm [] = { closed_state, /* state 0 - closed */ requested_state, /* state 1 - requested */ auth3_wait_state, /* state 2 - auth3_wait */ auth3_state, /* state 3 - auth3 */ open_state, /* state 4 - open */ assoc_wait_state /* state 5 - assoc_wait */ }; /***********************************************************************/ /* * * 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 * */ /* **++ ** ** ROUTINE NAME: authent3_pred_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Returns 1 if the association request requires an optional 3-leg ** authentication handshake. Returns 0 if if didn't. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param The fragment buffer containing the rpc_bind ** PDU. The special event related ** parameter which is passed to the state ** machine event evaluation routine. ** ** INPUTS/OUTPUTS: none ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: 0 if no 3-leg authentication handshake is ** being done. ** 1 if a 3-leg authentication handshake is ** being done. ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned8 authent3_pred_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct ATTRIBUTE_UNUSED, pointer_t event_param ) #else (spc_struct, event_param) pointer_t spc_struct; pointer_t event_param; #endif { rpc_cn_packet_t *header; rpc_cn_auth_tlr_t *tlr; boolean32 three_way; unsigned32 st; unsigned32 authn_protocol; RPC_CN_DBG_RTN_PRINTF(SERVER authent3_pred_rtn); /* * The event parameter is a pointer to the fragbuf containing * the rpc_bind PDU. */ header = (rpc_cn_packet_t *) ((rpc_cn_fragbuf_t *)event_param)->data_p; /* * The authentication length in the header indicates whether the * PDU contains an authentication trailer. */ if (RPC_CN_PKT_AUTH_LEN (header) == 0) { return (0); } else { tlr = RPC_CN_PKT_AUTH_TLR (header, RPC_CN_PKT_FRAG_LEN (header)); authn_protocol = RPC_CN_AUTH_CVT_ID_WIRE_TO_API (tlr->auth_type, &st); if (st == rpc_s_ok) { RPC_CN_AUTH_THREE_WAY (authn_protocol, three_way); if (three_way) { return (1); } else { return (0); } } else { return (0); } } } /* **++ ** ** MACRO NAME: AUTHENT3_PRED ** ** SCOPE: INTERNAL ** ** DESCRIPTION: ** This a macro version of the authent3_pred_rtn predicate routine. ** We added the macro version to avoid overhead associated with calling ** the predicate function from within the action routines. ** Macro set status to 1 if the association request requires an optional 3-leg ** authentication handshake, otherwise, sets status to 0. ** ** ** INPUTS: ** ** spc_struct The association group. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param The fragment buffer containing the rpc_bind ** PDU. The special event related ** parameter which is passed to the state ** machine event evaluation routine. ** ** status Instead of returning a value from the macro, ** write the value calculated in the macro to ** status. Status' scope includes the routine ** calling the macro. Check status in the calling ** routine to determine next state and in cases, ** flow through the action routine. ** ** tlr Struct rpc_cn_auth_tlr_t. Declared in the ** calling routine. Used in RPC_CN_AUTH_THREE_WAY. ** ** st Unsigned32. Used internally to RPC_CN_AUTH_ ** THREE_WAY. ** ** three_way Boolean32. Used internally to RPC_CN_AUTH_ ** THREE_WAY. ** ** INPUTS/OUTPUTS: none ** ** OUTPUTS: ** ** status See explanation above. ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: 0 if no 3-leg authentication handshake is ** being done. ** 1 if a 3-leg authentication handshake is ** being done. ** ** SIDE EFFECTS: none ** **-- **/ #define AUTHENT3_PRED(spc_struct, event_param, status, tlr, st, three_way)\ {\ RPC_CN_DBG_RTN_PRINTF(SERVER authent3_pred_macro);\ header = (rpc_cn_packet_t *) ((rpc_cn_fragbuf_t *)event_param)->data_p;\ if (RPC_CN_PKT_AUTH_LEN (header) == 0)\ {\ status = 0;\ }\ else\ {\ rpc_authn_protocol_id_t authn_protocol; \ tlr = RPC_CN_PKT_AUTH_TLR (header, RPC_CN_PKT_FRAG_LEN (header));\ authn_protocol = RPC_CN_AUTH_CVT_ID_WIRE_TO_API (tlr->auth_type, &st); \ if (st == rpc_s_ok) \ {\ RPC_CN_AUTH_THREE_WAY (authn_protocol, three_way);\ if (three_way)\ {\ status = 1;\ }\ else\ {\ status = 0;\ }\ }\ else\ {\ status = 0;\ }\ }\ } /* **++ ** ** ROUTINE NAME: active_pred_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Determines whether the association is currently in use. Unless ** the concurrent multiplexing option has been mutually selected, only one ** call and its related callbacks, or an alter-context request, may use ** an association at one time. This predicate is manupulated via the ** incr_active and decr_active action routines which manipulate a ** reference counter, and is ready by the association group policy ** mechanisms. A zero reference count implies the predicate value is ** false, otherwise it is true. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param The special event related parameter which is ** passed to the state machine event evaluation ** routine. ** This input argument is ignored. ** ** INPUTS/OUTPUTS: none ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: 0 if association reference counter is 0 ** 1 if association reference counter is non-zero ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned8 active_pred_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param ATTRIBUTE_UNUSED ) #else (spc_struct, event_param) pointer_t spc_struct; pointer_t event_param; #endif { rpc_cn_assoc_t *assoc; RPC_CN_DBG_RTN_PRINTF(SERVER active_pred_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; /* * A reference counter in the association indicates whether the * association is currently active. */ if (assoc->assoc_ref_count == 0) { return (0); } else { return (1); } } /* **++ ** ** ROUTINE NAME: lastbindfrag_pred_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Returns 1 if the association request has is last_frag flag bit set ** Returns 0 if if doesn't. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param The fragment buffer containing the rpc_bind ** PDU. The special event related ** parameter which is passed to the state ** machine event evaluation routine. ** ** INPUTS/OUTPUTS: none ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: 0 If the rpc_bind PDU last_frag flag it is NOT set ** 1 If the rpc_bind PDU last_frag flag bit is set ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned8 lastbindfrag_pred_rtn (spc_struct, event_param) pointer_t spc_struct ATTRIBUTE_UNUSED; pointer_t event_param; { rpc_cn_packet_t *header; RPC_CN_DBG_RTN_PRINTF(SERVER lastbindfrag_pred_rtn); /* * The event parameter is a pointer to the fragbuf containing * the rpc_bind PDU. */ header = (rpc_cn_packet_t *) ((rpc_cn_fragbuf_t *)event_param)->data_p; /* * This is the last packet we are going to get if last_frag flag is set * or we are talking to an old client. */ if ((RPC_CN_PKT_FLAGS (header) & RPC_C_CN_FLAGS_LAST_FRAG) || (RPC_CN_PKT_VERS_MINOR (header) < RPC_C_CN_PROTO_VERS_MINOR)) { return (1); } else { return(0); } } /***********************************************************************/ /* * 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 */ /* **++ ** ** ROUTINE NAME: accept_assoc_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine to send an rpc_bind_ack association accept PDU ** to the client, including the secondary address, association ** group id and, optionally, authentication information. ** ** If we have authentication information, we may send more than one ** PDU to the client containing the pieces of the auth info. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param The fragment buffer containing the rpc_bind_ack PDU. ** This is passed in as the ** special event related parameter which was ** passed to the state machine evaluation routine. ** ** INPUTS/OUTPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. SM is not changed ** here but is passed in to avoid compile warnings ** from rpc__cn_sm_eval_event(). ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status returned in ** assoc->assoc_status. ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 accept_assoc_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param, pointer_t sm ATTRIBUTE_UNUSED ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; rpc_cn_packet_t *req_header; rpc_cn_fragbuf_t *fragbuf; RPC_CN_DBG_RTN_PRINTF(SERVER accept_assoc_action_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; /* * The event parameter is the fragbuf containing * the rpc_bind_ack PDU and the security context element. */ fragbuf = (rpc_cn_fragbuf_t *) event_param; req_header = (rpc_cn_packet_t *) fragbuf->data_p; /* * If we have security, we may have to break it apart. */ if (RPC_CN_PKT_AUTH_TLR_PRESENT (req_header)) { send_frag_resp_pdu(assoc, fragbuf, req_header); } else { /* * Just send the PDU and free the fragbuf. */ rpc__cn_assoc_send_fragbuf (assoc, fragbuf, assoc->security.assoc_current_sec_context, true, &(assoc->assoc_status)); } RPC_CN_ASSOC_CHECK_ST (assoc, &(assoc->assoc_status)); return (assoc->assoc_status); } /* **++ ** ** ROUTINE NAME: reject_assoc_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine to send an rpc_bind_nack association reject PDU ** to the client. The client will abort the connection after ** receiving the association reject. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param The fragment buffer containing the rpc_bind_nack PDU. ** This is passed in as the ** special event related parameter which was ** passed to the state machine evaluation routine. ** ** INPUTS/OUTPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. Output is the ** next state or updated current state, for the ** control block. ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status, one of: ** rpc_s_ok ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 reject_assoc_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param, pointer_t sm ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; rpc_cn_fragbuf_t *fragbuf; rpc_cn_sm_ctlblk_t *sm_p; RPC_CN_DBG_RTN_PRINTF(SERVER reject_assoc_action_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; sm_p = (rpc_cn_sm_ctlblk_t *)sm; /* * The event parameter is a pointer to the fragbuf containing * the rpc_bind_nack PDU. */ fragbuf = (rpc_cn_fragbuf_t *) event_param; /* * Now actually send the PDU and free the fragbuf. */ rpc__cn_assoc_send_fragbuf (assoc, fragbuf, NULL, true, &(assoc->assoc_status)); RPC_CN_ASSOC_CHECK_ST (assoc, &(assoc->assoc_status)); sm_p->cur_state = RPC_C_SERVER_ASSOC_CLOSED; return (assoc->assoc_status); } /* **++ ** ** ROUTINE NAME: add_assoc_to_grp_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine add the current association to the association ** group. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param This is passed in as the ** special event related parameter which was ** passed to the state machine evaluation routine. ** This argument is ignored. ** ** INPUTS/OUTPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. Output is the ** next state or updated current state, for the ** control block. ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status, one of: ** rpc_s_ok ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 add_assoc_to_grp_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param ATTRIBUTE_UNUSED, pointer_t sm ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; rpc_cn_sm_ctlblk_t *sm_p; RPC_CN_DBG_RTN_PRINTF(SERVER add_assoc_to_grp_action_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; sm_p = (rpc_cn_sm_ctlblk_t *)sm; /* * Add the association to the group. */ rpc__cn_assoc_grp_add_assoc (assoc->assoc_grp_id, assoc); sm_p->cur_state = RPC_C_SERVER_ASSOC_OPEN; return (assoc->assoc_status); } /* **++ ** ** ROUTINE NAME: rem_assoc_from_grp_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine to remove the current association from the ** association group. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param This is passed in as the ** special event related parameter which was ** passed to the state machine evaluation routine. ** This input argument is ignored. ** ** INPUTS/OUTPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. SM is not changed ** here but is passed in to avoid compile warnings ** from rpc__cn_sm_eval_event(). ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status, one of: ** rpc_s_ok ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 rem_assoc_from_grp_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param ATTRIBUTE_UNUSED, pointer_t sm ATTRIBUTE_UNUSED ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; RPC_CN_DBG_RTN_PRINTF(SERVER rem_assoc_from_grp_action_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; /* * Remove the association from the group. */ rpc__cn_assoc_grp_rem_assoc (assoc->assoc_grp_id, assoc); return (assoc->assoc_status); } /* **++ ** ** ROUTINE NAME: do_alter_cont_req_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine to process the alter context negotiation request. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param The fragbuf containing the alter_context PDU. ** This is passed in as the ** special event related parameter which was ** passed to the state machine evaluation routine. ** ** INPUTS/OUTPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. SM is not changed ** here but is passed in to avoid compile warnings ** from rpc__cn_sm_eval_event(). ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status, one of: ** rpc_s_ok ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 do_alter_cont_req_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param, pointer_t sm ATTRIBUTE_UNUSED ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; rpc_cn_sm_ctlblk_t *sm_p; rpc_cn_packet_t *req_header; rpc_cn_packet_t *resp_header; rpc_cn_pres_cont_list_t *pres_cont_list; rpc_cn_pres_result_list_t *pres_result_list; unsigned32 result_list_len; unsigned32 header_size; unsigned32 auth_len; rpc_cn_fragbuf_t *fragbuf; rpc_cn_sm_event_entry_t event; rpc_cn_port_any_t *sec_addr; boolean old_client; RPC_CN_DBG_RTN_PRINTF(SERVER do_alter_cont_req_action_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; sm_p = (rpc_cn_sm_ctlblk_t *)sm; old_client = (assoc->assoc_vers_minor <= RPC_C_CN_PROTO_VERS_COMPAT); /* * The event parameter is a pointer to the fragbuf containing * the rpc_alter_context PDU. */ req_header = (rpc_cn_packet_t *) ((rpc_cn_fragbuf_t *)event_param)->data_p; if (!(RPC_CN_PKT_FLAGS(req_header) & RPC_C_CN_FLAGS_LAST_FRAG) && !(RPC_CN_PKT_VERS_MINOR (req_header) < RPC_C_CN_PROTO_VERS_MINOR)) { /* * Alter context is not complete (and we are not talking to * an old client who doesn't set the last_frag flag). * Save the security fragment, and wait for the next one. */ save_sec_fragment(assoc, req_header); /* FIXME: is this value correct ? */ return rpc_s_ok; } /* * Make sure if we have processed previous alter_context PDU's * that we append the piece from the last packet in the sequence. */ if (assoc->security.auth_buffer_info.auth_buffer != NULL) { save_sec_fragment(assoc, req_header); } /* * Mark the current security context as NULL. This will be * filled in when we have successfully established a security * context. It will be used by the action routine which actually * sends the rpc_bind_ack PDU. */ assoc->security.assoc_current_sec_context = NULL; /* * Allocate a large fragbuf for the response PDU. We won't expend any * more time here trying to optimize to allocate a small fragbuf. */ RPC_CN_FRAGBUF_ALLOC (fragbuf, rpc_g_cn_large_frag_size, &(assoc->assoc_status)); resp_header = (rpc_cn_packet_t *) (fragbuf->data_p); header_size = RPC_CN_PKT_SIZEOF_ALT_CTX_R_HDR; sec_addr = (rpc_cn_port_any_t *) ((unsigned8 *)(resp_header) + header_size); /* changed from 1 to 0 - lukeh May 2003 */ sec_addr->length = 0; sec_addr->s[0] = '\0'; header_size = (2 + header_size + 3) & ~0x03; pres_cont_list = (rpc_cn_pres_cont_list_t *) ((unsigned8 *) req_header + RPC_CN_PKT_SIZEOF_ALT_CTX_HDR); pres_result_list = (rpc_cn_pres_result_list_t *) ((unsigned8 *)(resp_header) + header_size); result_list_len = rpc_g_cn_large_frag_size - header_size; rpc__cn_assoc_syntax_negotiate (assoc, pres_cont_list, &result_list_len, pres_result_list, &assoc->assoc_status); header_size += result_list_len; if (assoc->assoc_status == rpc_s_ok) { auth_len = rpc_g_cn_large_frag_size - header_size; rpc__cn_assoc_process_auth_tlr (assoc, req_header, ((rpc_cn_fragbuf_t *)event_param)->data_size, resp_header, &header_size, &auth_len, &assoc->security.assoc_current_sec_context, old_client, &assoc->assoc_status); } /* * An rpc_alter_context_response PDU will be sent if the association status is * OK. */ if (assoc->assoc_status == rpc_s_ok) { fragbuf->data_size = header_size; rpc__cn_pkt_format_common (resp_header, RPC_C_CN_PKT_ALTER_CONTEXT_RESP, (RPC_C_CN_FLAGS_FIRST_FRAG | RPC_C_CN_FLAGS_LAST_FRAG), fragbuf->data_size, auth_len, RPC_CN_PKT_CALL_ID (req_header), assoc->assoc_vers_minor); /* * Send an alter context response event through the association state * machine. Note the event parameter is the fragment buffer * containing the response PDU. */ sm_p->cur_state = RPC_C_SERVER_ASSOC_AUTH3; event.event_id = RPC_C_ASSOC_ALTER_CONTEXT_RESP; event.event_param = (pointer_t) fragbuf; RPC_CN_ASSOC_INSERT_EVENT (assoc, &event); } else { /* * The architecture doesn't specify what to do here. We'll * at least spit out what happened. */ RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_ERRORS, ("CN: call_rep->%x assoc->%x desc->%x error %x while processing alter context PDU \n", assoc->call_rep, assoc, assoc->cn_ctlblk.cn_sock, assoc->assoc_status)); } return (assoc->assoc_status); } /* **++ ** ** ROUTINE NAME: send_alter_cont_resp_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine to send an alter_context_resp PDU ** to the client. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param The fragbuf containing the alter_context_resp PDU. ** This is passed in as the ** special event related parameter which was ** passed to the state machine evaluation routine. ** ** INPUTS/OUTPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. SM is not changed ** here but is passed in to avoid compile warnings ** from rpc__cn_sm_eval_event(). ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status, one of: ** rpc_s_ok ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 send_alter_cont_resp_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param, pointer_t sm ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; rpc_cn_fragbuf_t *fragbuf; rpc_cn_packet_t *req_header; rpc_cn_sm_ctlblk_t *sm_p; unsigned8 n_state, o_state; rpc_cn_sec_context_p_t sec; RPC_CN_DBG_RTN_PRINTF(SERVER send_alter_cont_resp_action_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; sm_p = (rpc_cn_sm_ctlblk_t *)sm; o_state = sm_p->cur_state; sec = assoc->security.assoc_current_sec_context; if (sec == NULL || sec->sec_state == RPC_C_SEC_STATE_COMPLETE) { n_state = RPC_C_SERVER_ASSOC_OPEN; } else { n_state = RPC_C_SERVER_ASSOC_AUTH3_WAIT; } if (o_state != RPC_C_SERVER_ASSOC_OPEN && n_state == RPC_C_SERVER_ASSOC_OPEN) { add_assoc_to_grp_action_rtn (spc_struct, (pointer_t) assoc, sm); } /* * The event parameter is a pointer to the fragbuf containing * the alter_context_resp PDU. */ fragbuf = (rpc_cn_fragbuf_t *) event_param; req_header = (rpc_cn_packet_t *) fragbuf->data_p; /* * If we have security, we may have to break it apart. */ if (RPC_CN_PKT_AUTH_TLR_PRESENT (req_header)) { send_frag_resp_pdu(assoc, fragbuf, req_header); } else { /* * Just send the PDU and free the fragbuf. */ rpc__cn_assoc_send_fragbuf (assoc, fragbuf, assoc->security.assoc_current_sec_context, true, &(assoc->assoc_status)); } RPC_CN_ASSOC_CHECK_ST (assoc, &(assoc->assoc_status)); sm_p->cur_state = n_state; return (assoc->assoc_status); } /* **++ ** ** ROUTINE NAME: do_authent3_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine to process the 3rd leg of an optional 3-way ** authentication handshake. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param This is passed in as the ** special event related parameter which was ** passed to the state machine evaluation routine. ** ** INPUTS/OUTPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. Output is the ** next state or updated current state, for the ** control block. ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status, one of: ** rpc_s_ok ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 do_authent3_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param, pointer_t sm ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; rpc_cn_sm_ctlblk_t *sm_p; rpc_cn_packet_t *req_header; rpc_cn_packet_t *tmp_resp_header; unsigned32 auth_len; rpc_cn_fragbuf_t *fragbuf; unsigned32 header_size; rpc_cn_port_any_t *sec_addr; boolean old_client; unsigned8 tmp[rpc_g_cn_large_frag_size]; unsigned8 new_state; rpc_cn_sec_context_p_t sec; RPC_CN_DBG_RTN_PRINTF(SERVER do_authent3_action_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; old_client = (assoc->assoc_vers_minor <= RPC_C_CN_PROTO_VERS_COMPAT); sm_p = (rpc_cn_sm_ctlblk_t *)sm; sm_p->cur_state = RPC_C_SERVER_ASSOC_AUTH3; fragbuf = (rpc_cn_fragbuf_t *)event_param; req_header = (rpc_cn_packet_t *)fragbuf->data_p; if (!(RPC_CN_PKT_FLAGS (req_header)) && !(RPC_CN_PKT_VERS_MINOR (req_header) < RPC_C_CN_PROTO_VERS_MINOR)) { save_sec_fragment (assoc, req_header); /* FIXME: is this value correct? */ return rpc_s_ok; } if (assoc->security.auth_buffer_info.auth_buffer != NULL) { save_sec_fragment (assoc, req_header); } assoc->security.assoc_current_sec_context = NULL; /* * Allocate a temporary "response" buffer so we can * call rpc__cn_assoc_process_auth_tlr() */ tmp_resp_header = (rpc_cn_packet_t *) (tmp); header_size = RPC_CN_PKT_SIZEOF_BIND_ACK_HDR; /* not really, but. */ sec_addr = (rpc_cn_port_any_t *)((unsigned8 *)(tmp_resp_header) + header_size); /* changed from 1 to 0 - lukeh May 2003 */ sec_addr->length = 0; sec_addr->s[0] = '\0'; header_size = (2 + header_size + 3) & ~0x03; /* Process the trailer */ rpc__cn_assoc_process_auth_tlr (assoc, req_header, fragbuf->data_size, tmp_resp_header, &header_size, &auth_len, &assoc->security.assoc_current_sec_context, old_client, &assoc->assoc_status); if (assoc->assoc_status == rpc_s_ok && auth_len != 0) { /* Make sure the authentication subsystem didn't return a response */ assoc->assoc_status = rpc_s_proto_unsupp_by_auth; } sec = assoc->security.assoc_current_sec_context; if (sec == NULL || sec->sec_state == RPC_C_SEC_STATE_COMPLETE) { new_state = (assoc->assoc_status == rpc_s_ok) ? RPC_C_ASSOC_AUTH3_ACK : RPC_C_ASSOC_AUTH3_NACK; assoc->assoc_status = rpc__cn_sm_eval_event (new_state, event_param, assoc, &assoc->assoc_state); assoc->assoc_flags &= ~RPC_C_CN_ASSOC_SCANNED; } else { sm_p->cur_state = RPC_C_SERVER_ASSOC_AUTH3_WAIT; } return (assoc->assoc_status); } /* **++ ** ** ROUTINE NAME: do_assoc_req_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine to process the association request and ** presentation and security negotiations. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param The fragbuf containing the rpc_bind PDU. ** This is passed in as the ** special event related parameter which was ** passed to the state machine evaluation routine. ** ** INPUTS/OUTPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. Output is the ** next state or updated current state, for the ** control block. ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status, one of: ** rpc_s_ok ** rpc_s_assoc_grp_max_exceeded ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 do_assoc_req_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param, pointer_t sm ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; rpc_cn_assoc_grp_t *assoc_grp; rpc_cn_packet_t *req_header; rpc_cn_packet_t *resp_header; rpc_cn_pres_cont_list_t *pres_cont_list; rpc_cn_pres_result_list_t *pres_result_list; unsigned32 header_size; unsigned32 result_list_len; unsigned32 auth_len; rpc_cn_local_id_t grp_id; rpc_cn_fragbuf_t *fragbuf; rpc_cn_sm_event_entry_t event; rpc_cn_port_any_t *sec_addr; boolean old_client; rpc_cn_sm_ctlblk_t *sm_p; RPC_CN_DBG_RTN_PRINTF (SERVER do_assoc_req_action_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; sm_p = (rpc_cn_sm_ctlblk_t *)sm; /* * Since this is a new association we don't yet have an * association UUID CRC (and will not unless a client on this * association uses security). */ assoc->security.assoc_have_uuid_crc = false; /* * Mark the current security context as NULL. This will be * filled in when we have successfully established a security * context. It will be used by the action routine which actually * sends the rpc_bind_ack PDU. */ assoc->security.assoc_current_sec_context = NULL; /* * The event parameter is a pointer to the fragbuf containing * the rpc_bind PDU. */ req_header = (rpc_cn_packet_t *) ((rpc_cn_fragbuf_t *)event_param)->data_p; /* * Allocate a large fragbuf for the response PDU. It will either * be an rpc_bind_ack or rpc_bind_nack. We won't expend any * more time here trying to optimize to allocate a small fragbuf. */ RPC_CN_FRAGBUF_ALLOC (fragbuf, rpc_g_cn_large_frag_size, &(assoc->assoc_status)); resp_header = (rpc_cn_packet_t *) (fragbuf->data_p); /* * Assume that everything is going to go OK and begin formatting * an rpc_bind_ack PDU. If something bad happens we'll format an * rpc_bind_nack PDU below. */ header_size = RPC_CN_PKT_SIZEOF_BIND_ACK_HDR; #ifdef DEBUG if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_PROT_VERS_MISMATCH)) { RPC_CN_PKT_VERS_MINOR (req_header) = RPC_C_CN_PROTO_VERS_MINOR + 1; } #endif if ((RPC_CN_PKT_VERS (req_header) != RPC_C_CN_PROTO_VERS) || (RPC_CN_PKT_VERS_MINOR (req_header) > RPC_C_CN_PROTO_VERS_MINOR)) { assoc->assoc_status = rpc_s_rpc_prot_version_mismatch; } else { /* * As per the NCA Connection Architecture return the * client's minor protocol version number and restrict the use * of the protocol to the client's minor version. */ assoc->assoc_vers_minor = RPC_CN_PKT_VERS_MINOR (req_header); old_client = (assoc->assoc_vers_minor <= RPC_C_CN_PROTO_VERS_COMPAT); RPC_CN_PKT_VERS_MINOR (resp_header) = RPC_CN_PKT_VERS_MINOR(req_header); /* * Return the server's operational max size fragment it will * send and max size fragment it is capable of receiving. Make * sure these values are not greater than what the client gave. */ if (RPC_CN_PKT_MAX_RECV_FRAG (req_header) == 0) { /* * This is a reserved value as specified in the NCA * Connection Architecture spec. It implies the default * rpc_c_assoc_must_recv_frag_size. */ RPC_CN_PKT_MAX_RECV_FRAG (req_header) = RPC_C_ASSOC_MUST_RECV_FRAG_SIZE; } if (RPC_CN_PKT_MAX_XMIT_FRAG (req_header) == 0) { /* * This is a reserved value as specified in the NCA * Connection Architecture spec. It implies the default * rpc_c_assoc_must_recv_frag_size. */ RPC_CN_PKT_MAX_XMIT_FRAG (req_header) = RPC_C_ASSOC_MUST_RECV_FRAG_SIZE; } RPC_CN_PKT_MAX_XMIT_FRAG (resp_header) = MIN (rpc_g_cn_large_frag_size, RPC_CN_PKT_MAX_RECV_FRAG (req_header)); RPC_CN_PKT_MAX_RECV_FRAG (resp_header) = MIN (rpc_g_cn_large_frag_size, RPC_CN_PKT_MAX_XMIT_FRAG (req_header)); assoc->assoc_max_xmit_frag = RPC_CN_PKT_MAX_XMIT_FRAG (resp_header); assoc->assoc_max_recv_frag = RPC_CN_PKT_MAX_RECV_FRAG (resp_header); /* * Determine whether the rpc_bind PDU contains an association * group id. */ if (RPC_CN_PKT_ASSOC_GROUP_ID (req_header) != 0) { /* * The rpc_bind PDU does contain a group id. Use it to look * up an association group. */ grp_id.all = RPC_CN_PKT_ASSOC_GROUP_ID (req_header); assoc->assoc_grp_id = rpc__cn_assoc_grp_lkup_by_id (grp_id, RPC_C_CN_ASSOC_GRP_SERVER, assoc->transport_info, &(assoc->assoc_status)); assoc_grp = RPC_CN_ASSOC_GRP (assoc->assoc_grp_id); if (assoc->assoc_status == rpc_s_ok) { #ifdef DEBUG if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_GRP_MAX_EXCEEDED)) { assoc_grp->grp_cur_assoc = assoc_grp->grp_max_assoc; } #endif /* * The association group was found. Determine whether it can * support another association. */ if (assoc_grp->grp_cur_assoc == assoc_grp->grp_max_assoc) { /* * The group can't support another association. Reject this * association request by sending an rpc_bind_nack PDU. */ assoc->assoc_status = rpc_s_assoc_grp_max_exceeded; } } } /* end if (RPC_CN_PKT_ASSOC_GROUP_ID (req_header) != 0) */ else /* (RPC_CN_PKT_ASSOC_GROUP_ID (req_header) == 0) */ { /* * A new association group needs to be created. */ assoc->assoc_grp_id = rpc__cn_assoc_grp_alloc (assoc->cn_ctlblk.rpc_addr, assoc->transport_info, RPC_C_CN_ASSOC_GRP_SERVER, 0, &(assoc->assoc_status)); assoc_grp = RPC_CN_ASSOC_GRP (assoc->assoc_grp_id); } /* end else (RPC_CN_PKT_ASSOC_GROUP_ID (req_header) == 0) */ if (assoc->assoc_status == rpc_s_ok) { /* * Return the appropriate group ID for the client to use on * the next association request. */ RPC_CN_PKT_ASSOC_GROUP_ID (resp_header) = assoc_grp->grp_id.all; /* * Determine the length of the secondary address endpoint including the '\0' * termination and store this in the PDU. Also string copy the * actual endpoint into the PDU. If the endpoint won't fit fall * through and send an rpc_bind_nak. */ sec_addr = (rpc_cn_port_any_t *) ((unsigned8 *) (resp_header) + header_size); sec_addr->length = strlen ((char *)assoc->cn_ctlblk.cn_listening_endpoint) + 1; if (sec_addr->length < (rpc_g_cn_large_frag_size - header_size + 2)) { strcpy ((char *)(sec_addr->s), (char *)assoc->cn_ctlblk.cn_listening_endpoint); /* * To format the balance of the rpc_bind_ack PDU fields we're * going to have to do some pointer arithmetic because the * secondary address endpoint is variable length. Also note * that the because the presentation result list must start * on a 4-byte boundary rounding up will be necessary. */ header_size = (header_size + 2 + sec_addr->length + 3) & ~0x3; pres_result_list = (rpc_cn_pres_result_list_t *) ((unsigned8 *) resp_header + header_size); /* * Get a local pointer to the presentation context list in the * PDU header. Use this along with the location of the * presentation result list in the response hdr to pass to the * syntax negotiation routine. Upon successful return from this * routine the presentation result list will be formatted. * If unsuccessful the presentation context result list would * not fit in the balance of the fragbuf. Fall through and * send an rpc_bind_nak. */ pres_cont_list = (rpc_cn_pres_cont_list_t *) ((unsigned8 *) req_header + RPC_CN_PKT_SIZEOF_BIND_HDR); result_list_len = rpc_g_cn_large_frag_size - header_size; rpc__cn_assoc_syntax_negotiate (assoc, pres_cont_list, &result_list_len, pres_result_list, &assoc->assoc_status); header_size += result_list_len; if (assoc->assoc_status == rpc_s_ok) { auth_len = rpc_g_cn_large_frag_size - header_size; rpc__cn_assoc_process_auth_tlr (assoc, req_header, ((rpc_cn_fragbuf_t *)event_param)->data_size, resp_header, &header_size, &auth_len, &assoc->security.assoc_current_sec_context, old_client, &assoc->assoc_status); } } else { assoc->assoc_status = RPC_S_HEADER_FULL; } } } #ifdef DEBUG if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_HEADER_FULL)) { assoc->assoc_status = RPC_S_HEADER_FULL; } #endif /* * An rpc_bind_nak PDU will be sent if the association status is * not OK. Assume it will be the only fragment sent. */ if (assoc->assoc_status == rpc_s_ok) { fragbuf->data_size = header_size; rpc__cn_pkt_format_common (resp_header, RPC_C_CN_PKT_BIND_ACK, (RPC_C_CN_FLAGS_FIRST_FRAG | RPC_C_CN_FLAGS_LAST_FRAG), fragbuf->data_size, auth_len, RPC_CN_PKT_CALL_ID (req_header), assoc->assoc_vers_minor); /* * Send an accept response event through the association state * machine. */ event.event_id = RPC_C_ASSOC_ACCEPT_RESP; } else { int i; /* * Some failure happened. Reject this * association request by sending an rpc_bind_nak PDU * with the list of supported protocol versions. */ fragbuf->data_size = RPC_CN_PKT_SIZEOF_BIND_NACK_HDR + (RPC_C_CN_PROTO_VERS_MINOR * sizeof(rpc_cn_version_t)); rpc__cn_pkt_format_common (resp_header, RPC_C_CN_PKT_BIND_NAK, (RPC_C_CN_FLAGS_FIRST_FRAG | RPC_C_CN_FLAGS_LAST_FRAG), fragbuf->data_size, 0, RPC_CN_PKT_CALL_ID (req_header), assoc->assoc_vers_minor); (RPC_CN_PKT_VERSIONS (resp_header)).n_protocols = RPC_C_CN_PROTO_VERS_MINOR + 1; for (i=0;i <= RPC_C_CN_PROTO_VERS_MINOR; i++) { (RPC_CN_PKT_VERSIONS (resp_header)).protocols[i].vers_major = RPC_C_CN_PROTO_VERS; (RPC_CN_PKT_VERSIONS (resp_header)).protocols[i].vers_minor = i; } RPC_CN_PKT_PROV_REJ_REASON(resp_header) = rpc__cn_assoc_status_to_prej (assoc->assoc_status); /* * Set up the event parameter as the fragment buffer containg * the PDU and send the event through the association state * machine. */ event.event_id = RPC_C_ASSOC_REJECT_RESP; } event.event_param = (pointer_t) fragbuf; RPC_CN_ASSOC_INSERT_EVENT (assoc, &event); sm_p->cur_state = RPC_C_SERVER_ASSOC_REQUESTED; return (assoc->assoc_status); } /* **++ ** ** ROUTINE NAME: send_shutdown_req_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine to send an rpc_shutdown orderly shutdown PDU ** to the client. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param This is passed in as the ** special event related parameter which was ** passed to the state machine evaluation routine. ** This input argument is ignored. ** ** INPUTS/OUTPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. Output is the ** next state or updated current state, for the ** control block. ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status, one of: ** rpc_s_ok ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 send_shutdown_req_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param ATTRIBUTE_UNUSED, pointer_t sm ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; unsigned32 pdu_size; rpc_cn_fragbuf_t *fragbuf; rpc_cn_packet_t *header; rpc_cn_sm_ctlblk_t *sm_p; unsigned8 n_state; RPC_CN_DBG_RTN_PRINTF(SERVER send_shutdown_req_action_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; sm_p = (rpc_cn_sm_ctlblk_t *)sm; /* * There is no predicate associated with this routine but the * new value of sm->cur_state is determined by the value of * sm->cur_state coming into the routine. Note that * 2+rpc_c_cn_statebase is auth3_wait_state; 3+rpc_c_cn_statebase is * auth3_wait; 4+rpc_c_cn_statebase is open_state. These values * are static and rpc_c_cn_statebase is the value added to * the states in order to distinguish them from the action * routine indexes. */ switch (sm_p->cur_state) { case (2 + RPC_C_CN_STATEBASE): n_state = RPC_C_SERVER_ASSOC_AUTH3_WAIT; break; case (3 + RPC_C_CN_STATEBASE): n_state = RPC_C_SERVER_ASSOC_AUTH3; break; case (4 + RPC_C_CN_STATEBASE): n_state = RPC_C_SERVER_ASSOC_OPEN; break; default: fprintf(stderr, "%s no value for n_state\n", __PRETTY_FUNCTION__); abort(); break; } /* * Allocate a fragbuf capable of holding a shutdown PDU. */ pdu_size = RPC_CN_PKT_SIZEOF_SHUTDOWN_HDR; /* * Allocate a fragbuf of the appropriate size. */ RPC_CN_FRAGBUF_ALLOC (fragbuf, pdu_size, &(assoc->assoc_status)); RPC_CN_ASSOC_CHECK_ST (assoc, &(assoc->assoc_status)); /* * Now begin construction of the PDU. */ header = (rpc_cn_packet_t *) fragbuf->data_p; rpc__cn_pkt_format_common (header, RPC_C_CN_PKT_SHUTDOWN, 0, pdu_size, 0, 0, assoc->assoc_vers_minor); /* * Now actually send the PDU and free the fragbuf. */ rpc__cn_assoc_send_fragbuf (assoc, fragbuf, NULL, true, &(assoc->assoc_status)); RPC_CN_ASSOC_CHECK_ST (assoc, &(assoc->assoc_status)); sm_p->cur_state = n_state; return (assoc->assoc_status); } /* **++ ** ** ROUTINE NAME: incr_active_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine to set the active predicate to true. The server ** runtime allocated the association for the new call and its ** callbacks. Only one call and its related callbacks may allocate an ** association at a time. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param This is passed in as the ** special event related parameter which was ** passed to the state machine evaluation routine. ** This input argument is ignored. ** ** INPUTS/OUTPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. Output is the ** next state or updated current state, for the ** control block. ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status, one of: ** rpc_s_ok ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 incr_active_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param ATTRIBUTE_UNUSED, pointer_t sm ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; rpc_cn_sm_ctlblk_t *sm_p; RPC_CN_DBG_RTN_PRINTF(SERVER incr_active_action_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; sm_p = (rpc_cn_sm_ctlblk_t *)sm; /* * Inccrement the association active reference counter. */ RPC_CN_INCR_ACTIVE_SVR_ACTION(assoc, sm_p); return (assoc->assoc_status); } /* **++ ** ** ROUTINE NAME: decr_active_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine to set the active predicate to false. The server ** runtime deallocated the association when done with an alter context ** request, a call, its callbacks, etc. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param This is passed in as the ** special event related parameter which was ** passed to the state machine evaluation routine. ** This input argument is ignored. ** ** INPUTS/OUTPUTS: none ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. Output is the ** next state or updated current state, for the ** control block. ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status, one of: ** rpc_s_ok ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 decr_active_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param ATTRIBUTE_UNUSED, pointer_t sm ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; rpc_cn_sm_ctlblk_t *sm_p; RPC_CN_DBG_RTN_PRINTF(SERVER decr_active_action_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; sm_p = (rpc_cn_sm_ctlblk_t *)sm; /* * Decrement the association active reference counter. */ RPC_CN_DECR_ACTIVE_SVR_ACTION(assoc, sm_p); return (assoc->assoc_status); } /* **++ ** ** ROUTINE NAME: abort_assoc_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine to abort the current association. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param This is passed in as the ** special event related parameter which was ** passed to the state machine evaluation routine. ** This input argument is ignored. ** ** INPUTS/OUTPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. Output is the ** next state or updated current state, for the ** control block. ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status, one of: ** rpc_s_ok ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 abort_assoc_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param ATTRIBUTE_UNUSED, pointer_t sm ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; rpc_cn_sm_ctlblk_t *sm_p; RPC_CN_DBG_RTN_PRINTF(SERVER abort_assoc_action_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; sm_p = (rpc_cn_sm_ctlblk_t *)sm; /* * Close the connection on the association. */ if (assoc->cn_ctlblk.cn_state == RPC_C_CN_OPEN) { rpc__cn_network_close_connect (assoc, &(assoc->assoc_status)); RPC_CN_ASSOC_CHECK_ST (assoc, &(assoc->assoc_status)); } sm_p->cur_state = RPC_C_SERVER_ASSOC_CLOSED; return (assoc->assoc_status); } /* **++ ** ** ROUTINE NAME: mark_assoc_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine to mark the current association with a status code. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param This is passed in as the ** special event related parameter which was ** passed to the state machine evaluation routine. ** This input argument is ignored. ** ** INPUTS/OUTPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. Output is the ** next state or updated current state, for the ** control block. ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status, one of: ** rpc_s_ok ** rpc_s_connection_closed ** rpc_s_connection_aborted ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 mark_assoc_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param ATTRIBUTE_UNUSED, pointer_t sm ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; dcethread* current_thread_id; rpc_cn_sm_ctlblk_t *sm_p; RPC_CN_DBG_RTN_PRINTF(SERVER mark_assoc_action_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; sm_p = (rpc_cn_sm_ctlblk_t *)sm; /* * Mark the association based on the event currently being * processed. */ switch (assoc->assoc_state.cur_event) { case RPC_C_ASSOC_NO_CONN_IND: { /* * The underlying session/transport connection has failed. */ assoc->assoc_status = rpc_s_connection_closed; break; } case RPC_C_ASSOC_ABORT_REQ: { /* * The user has aborted the association. */ assoc->assoc_status = rpc_s_connection_aborted; break; } case RPC_C_ASSOC_LOCAL_ERROR: { /* * The error status is contained in the association local * error status for this event. */ assoc->assoc_status = assoc->assoc_local_status; break; } default: { if (assoc->assoc_status == rpc_s_ok) assoc->assoc_status = rpc_s_connection_aborted; break; } } /* * Queue a dummy fragbuf on the association receive queue. This * will wake up any threads blocked waiting for receive data. */ current_thread_id = dcethread_self(); if (dcethread_equal (current_thread_id, assoc->cn_ctlblk.cn_rcvr_thread_id)) { RPC_CN_ASSOC_WAKEUP (assoc); } sm_p->cur_state = RPC_C_SERVER_ASSOC_CLOSED; return (assoc->assoc_status); } /* **++ ** ** ROUTINE NAME: cancel_calls_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine to cancel all the calls currently using the ** association. This allows the call state machinery to properly try to ** terminate calls when the connection has terminated. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param This is passed in as the ** special event related parameter which was ** passed to the state machine evaluation routine. ** This input argument is ignored. ** ** INPUTS/OUTPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. SM is not changed ** here but is passed in to avoid compile warnings ** from rpc__cn_sm_eval_event(). ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status, one of: ** rpc_s_ok ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 cancel_calls_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param ATTRIBUTE_UNUSED, pointer_t sm ATTRIBUTE_UNUSED ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; error_status_t st; rpc_binding_rep_t *binding_r; RPC_CN_DBG_RTN_PRINTF(SERVER cancel_calls_action_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; /* * The connection is gone. */ if (assoc->call_rep != NULL) { /* * If the call is queued dequeue it otherwise cancel the * thread it is executing in and signal the association message * queue condition variable if a thread is waiting on it. */ if (rpc__cthread_dequeue((rpc_call_rep_t *) assoc->call_rep)) { RPC_DBG_PRINTF(rpc_e_dbg_orphan, RPC_C_CN_DBG_ORPHAN, ("(cancel_calls_action_rtn) call_rep->%x queued call ... dequeued call id = %x\n", assoc->call_rep, RPC_CN_PKT_CALL_ID ((rpc_cn_packet_p_t) RPC_CN_CREP_SEND_HDR(assoc->call_rep)))); binding_r = (rpc_binding_rep_t *) assoc->call_rep->binding_rep; RPC_CN_UNLOCK (); rpc__cn_call_end ((rpc_call_rep_p_t *) &assoc->call_rep, &st); RPC_CN_LOCK (); RPC_BINDING_RELEASE (&binding_r, &st); } else { /* * We need to cancel and wake up the call executor * thread. If the call executor thread is in the manager * routine the cancel may get through. If it is in the * runtime blocked on a call_receive cancels are disabled * and needs to be woken up. */ RPC_DBG_PRINTF(rpc_e_dbg_orphan, RPC_C_CN_DBG_ORPHAN, ("(cancel_calls_action_rtn) call_rep->%x running call ... cancelling\n", assoc->call_rep)); RPC_CN_ASSOC_CANCEL_AND_WAKEUP (assoc); } } else { RPC_DBG_PRINTF(rpc_e_dbg_orphan, RPC_C_CN_DBG_ORPHAN, ("(cancel_calls_action_rtn) call_rep->%x assoc->%x no call ... do nothing\n", assoc->call_rep, assoc)); } return (assoc->assoc_status); } /* **++ ** ** ROUTINE NAME: accept_add_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine to accept the current association and add it to ** an association group. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param The fragbuf containing the rpc_bind_ack PDU. ** This is passed in as the ** special event related parameter which was ** passed to the state machine evaluation routine. ** ** INPUTS/OUTPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. Output is the ** next state or updated current state, for the ** control block. ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status, one of: ** rpc_s_ok ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 accept_add_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param, pointer_t sm ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; rpc_cn_sm_ctlblk_t *sm_p; unsigned8 n_state; rpc_cn_sec_context_p_t sec; RPC_CN_DBG_RTN_PRINTF(SERVER accept_add_action_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; sm_p = (rpc_cn_sm_ctlblk_t *)sm; sec = assoc->security.assoc_current_sec_context; if (sec == NULL || sec->sec_state == RPC_C_SEC_STATE_COMPLETE) { n_state = RPC_C_SERVER_ASSOC_OPEN; } else { n_state = RPC_C_SERVER_ASSOC_AUTH3_WAIT; } /* * Add the association to the group and send the rpc_bind_ack PDU * to the client. * * Note: the order in which this is done is important. The assoc * must be added to the group before sending back the rpc_bind_ack PDU. * The process of sending a PDU results in the CN mutex being released. * This opens a window where its possible the association group to which * we're going to add the assoc could get deallocated which would result * in a state transition error when we tried to add to it. * * Note that since we are calling action routines from * within action routines, we need to update state as * a final step here. Otherwise, the action routines * we call now, would update sm_p->cur_state inappropriately * for accept_add_action_rtn(). */ if (n_state != RPC_C_SERVER_ASSOC_AUTH3_WAIT) { add_assoc_to_grp_action_rtn (spc_struct, (pointer_t) assoc, sm); } accept_assoc_action_rtn (spc_struct, event_param, sm); sm_p->cur_state = n_state; return (assoc->assoc_status); } /* **++ ** ** ROUTINE NAME: rem_mark_abort_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine to remove the current association from an ** association group, mark the association appropriately and abort ** the association. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param This is passed in as the ** special event related parameter which was ** passed to the state machine evaluation routine. ** This input argument is ignored. ** ** INPUTS/OUTPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. Output is the ** next state or updated current state, for the ** control block. ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status, one of: ** rpc_s_ok ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 rem_mark_abort_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param, pointer_t sm ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; rpc_cn_sm_ctlblk_t *sm_p; RPC_CN_DBG_RTN_PRINTF(SERVER rem_mark_abort_action_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; sm_p = (rpc_cn_sm_ctlblk_t *)sm; /* * Remove the association from the group, mark it with the * appropriate status and abort the underlying session/transport * connection. * * Note that since we are calling action routines from * within action routines, we need to update state as * a final step here. Otherwise, the action routines * we call now, would update sm_p->cur_state inappropriately * for rem_mark_abort_action_rtn(). */ rem_assoc_from_grp_action_rtn (spc_struct, event_param, sm); abort_assoc_action_rtn (spc_struct, event_param, sm); mark_assoc_action_rtn (spc_struct, event_param, sm); sm_p->cur_state = RPC_C_SERVER_ASSOC_CLOSED; return (assoc->assoc_status); } /* **++ ** ** ROUTINE NAME: rem_mark_cancel_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine to remove the current association from an ** association group, mark the association appropriately and ** cancel all calls currently using the association. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param This is passed in as the ** special event related parameter which was ** passed to the state machine evaluation routine. ** This input argument is ignored. ** ** INPUTS/OUTPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. Output is the ** next state or updated current state, for the ** control block. ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status, one of: ** rpc_s_ok ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 rem_mark_cancel_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param, pointer_t sm ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; rpc_cn_sm_ctlblk_t *sm_p; RPC_CN_DBG_RTN_PRINTF(SERVER rem_mark_cancel_action_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; sm_p = (rpc_cn_sm_ctlblk_t *)sm; /* * Remove the association from the group and mark it with the * appropriate status and cancels all calls currently using it. * * Note that since we are calling action routines from * within action routines, we need to update state as * a final step here. Otherwise, the action routines * we call now, would update sm_p->cur_state inappropriately * for rem_mark_cancel_action_rtn(). */ rem_assoc_from_grp_action_rtn (spc_struct, event_param, sm); mark_assoc_action_rtn (spc_struct, event_param, sm); cancel_calls_action_rtn (spc_struct, event_param, sm); sm_p->cur_state = RPC_C_SERVER_ASSOC_CLOSED; return (assoc->assoc_status); } /* **++ ** ** ROUTINE NAME: incr_do_alter_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine to increment the association reference count and process ** an rpc_alter_context_req PDU ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param The fragbuf containing the alter_context_req PDU. ** This is passed in as the ** special event related parameter which was ** passed to the state machine evaluation routine. ** ** INPUTS/OUTPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. Output is the ** next state or updated current state, for the ** control block. ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status, one of: ** rpc_s_ok ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 incr_do_alter_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param, pointer_t sm ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; rpc_cn_sm_ctlblk_t *sm_p; RPC_CN_DBG_RTN_PRINTF(SERVER incr_do_alter_action_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; sm_p = (rpc_cn_sm_ctlblk_t *)sm; /* * Increment the active reference counter in the association and * process the alter context request. * * Note that since we are calling action routines from * within action routines, we need to update state as * a final step here. Otherwise, the action routines * we call now, would update sm_p->cur_state inappropriately * for incr_do_alter_action_rtn(). */ incr_active_action_rtn (spc_struct, event_param, sm); do_alter_cont_req_action_rtn (spc_struct, event_param, sm); sm_p->cur_state = RPC_C_SERVER_ASSOC_OPEN; return (assoc->assoc_status); } /* **++ ** ** ROUTINE NAME: send_decr_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine to send and an rpc_alter_context_response PDU and ** decrement the association reference count. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param The fragbuf containing the ** alter_context_resp PDU. ** This is passed in as the ** special event related parameter which was ** passed to the state machine evaluation routine. ** ** INPUTS/OUTPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. Output is the ** next state or updated current state, for the ** control block. ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status, one of: ** rpc_s_ok ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 send_decr_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param, pointer_t sm ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; rpc_cn_sm_ctlblk_t *sm_p; RPC_CN_DBG_RTN_PRINTF(SERVER send_decr_action_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; sm_p = (rpc_cn_sm_ctlblk_t *)sm; /* * Send the alter_context_resp PDU to the client and decrement the * active reference counter in the association. * * Note that since we are calling action routines from * within action routines, we need to update state as * a final step here. Otherwise, the action routines * we call now would update sm_p->cur_state inappropriately * for send_decr_action_rtn(). */ send_alter_cont_resp_action_rtn (spc_struct, event_param, sm); decr_active_action_rtn (spc_struct, event_param, sm); sm_p->cur_state = RPC_C_SERVER_ASSOC_OPEN; return (assoc->assoc_status); } /* **++ ** ** ROUTINE NAME: mark_abort_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine to mark the association with an error and abort ** the session/transport connection. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param This is passed in as the ** special event related parameter which was ** passed to the state machine evaluation routine. ** This input argument is ignored. ** ** INPUTS/OUTPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. Output is the ** next state or updated current state, for the ** control block. ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status, one of: ** rpc_s_ok ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 mark_abort_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param, pointer_t sm ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; rpc_cn_sm_ctlblk_t *sm_p; RPC_CN_DBG_RTN_PRINTF(SERVER mark_abort_action_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; sm_p = (rpc_cn_sm_ctlblk_t *)sm; /* * Mark the association with the appropriate status and abort * the underlying session/transport connection. * * Note that since we are calling action routines from * within action routines, we need to update state as * a final step here. Otherwise, the action routines * we call now, would update sm_p->cur_state inappropriately * for mark_abort_action_rtn(). */ abort_assoc_action_rtn (spc_struct, event_param, sm); mark_assoc_action_rtn (spc_struct, event_param, sm); sm_p->cur_state = RPC_C_SERVER_ASSOC_CLOSED; return (assoc->assoc_status); } /* **++ ** ** ROUTINE NAME: rem_mark_abort_can_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine to remove the current association from an ** association group, mark the association appropriately, abort ** the underlying session/transport connection and cancels all calls ** currently using the association. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param This is passed in as the ** special event related parameter which was ** passed to the state machine evaluation routine. ** This input argument is ignored. ** ** INPUTS/OUTPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. Output is the ** next state or updated current state, for the ** control block. ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status, one of: ** rpc_s_ok ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 rem_mark_abort_can_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param, pointer_t sm ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; rpc_cn_sm_ctlblk_t *sm_p; RPC_CN_DBG_RTN_PRINTF(SERVER rem_mark_abort_can_action_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; sm_p = (rpc_cn_sm_ctlblk_t *)sm; /* * Remove the association from the group, mark it with the * appropriate status, abort the underlying session/transport * connection and cancel the call executor thread. * * Note that since we are calling action routines from * within action routines, we need to update state as * a final step here. Otherwise, the action routines * we call now, would update sm_p->cur_state inappropriately * for rem_mark_abort_action_rtn(). */ rem_assoc_from_grp_action_rtn (spc_struct, event_param, sm); abort_assoc_action_rtn (spc_struct, event_param, sm); mark_assoc_action_rtn (spc_struct, event_param, sm); cancel_calls_action_rtn (spc_struct, event_param, sm); sm_p->cur_state = RPC_C_SERVER_ASSOC_CLOSED; return (assoc->assoc_status); } /* **++ ** ** ROUTINE NAME: do_assoc_wait_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine to process multiple rpc_bind PDU packets ** and reconstruct the security information. ** ** If we call this routine, this packet is expected to be one of ** a series of rpc_bind packets contaiining security information. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param The fragbuf containing the rpc_bind PDU. ** This is passed in as the special event related ** parameter which was passed to the state machine ** evaluation routine. ** ** INPUTS/OUTPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. Output is the ** next state or updated current state, for the ** control block. ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status, one of: ** rpc_s_ok ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 do_assoc_wait_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param, pointer_t sm ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; rpc_cn_packet_t *req_header; rpc_cn_sm_event_entry_t event; rpc_cn_sm_ctlblk_t *sm_p; RPC_CN_DBG_RTN_PRINTF(SERVER do_assoc_wait_action_rtn); /* * The special structure is a pointer to the association. */ assoc = (rpc_cn_assoc_t *) spc_struct; sm_p = (rpc_cn_sm_ctlblk_t *)sm; /* * The event parameter is a pointer to the fragbuf containing * the rpc_bind PDU. */ req_header = (rpc_cn_packet_t *) ((rpc_cn_fragbuf_t *)event_param)->data_p; /* * Save the security frament in the association reconstruction buffer */ save_sec_fragment(assoc, req_header); /* * Now we check to see if this is the last packet for this rpc_bind PDU * If it is, we send a assoc_complete event through the state * machine, and run this PDU through the 'old' association request code. */ if (RPC_CN_PKT_FLAGS (req_header) & RPC_C_CN_FLAGS_LAST_FRAG) { event.event_id = RPC_C_ASSOC_ASSOC_COMPLETE_RESP; event.event_param = event_param; RPC_CN_ASSOC_INSERT_EVENT (assoc, &event); } sm_p->cur_state = RPC_C_SERVER_ASSOC_WAIT; return (rpc_s_ok); } /* **++ ** ** ROUTINE NAME: do_assoc_action_rtn ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Action routine vectors to either do_assoc_wait_action_rtn ** or to do_assoc_req_action_rtn, depending on predicate value. ** ** INPUTS: ** ** spc_struct The association. Note that this is passed in as ** the special structure which is passed to the ** state machine event evaluation routine. ** ** event_param The fragbuf containing the rpc_bind PDU. ** This is passed in as the special event related ** parameter which was passed to the state machine ** evaluation routine. ** ** INPUTS/OUTPUTS: ** ** sm The control block from the event evaluation ** routine. Input is the current state and ** event for the control block. Output is the ** next state or updated current state, for the ** control block. ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: completion status, one of: ** rpc_s_ok ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL unsigned32 do_assoc_action_rtn #ifdef _DCE_PROTO_ ( pointer_t spc_struct, pointer_t event_param, pointer_t sm ) #else (spc_struct, event_param, sm) pointer_t spc_struct; pointer_t event_param; pointer_t sm; #endif { rpc_cn_assoc_t *assoc; rpc_cn_packet_t *req_header ATTRIBUTE_UNUSED; rpc_cn_sm_event_entry_t event ATTRIBUTE_UNUSED; rpc_cn_sm_ctlblk_t *sm_p ATTRIBUTE_UNUSED; unsigned32 status; RPC_CN_DBG_RTN_PRINTF(SERVER do_assoc_action_rtn); assoc = (rpc_cn_assoc_t *) spc_struct; status = lastbindfrag_pred_rtn (spc_struct, event_param); if (status == 0) { do_assoc_wait_action_rtn (spc_struct, event_param, sm); return (rpc_s_ok); } do_assoc_req_action_rtn (spc_struct, event_param, sm); return (assoc->assoc_status); } /* **++ ** ** ROUTINE NAME: rpc__cn_assoc_process_auth_tlr ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Support routine to decode an auth trailer on an bind or alter ** context PDU and format the auth trailer on a bind_ack or ** alter_context_response PDU ** ** If the client had to break part the security information ** we have passed through the assoc_wait state and we must ** use the re-constuction buffer, not the info in the PDU. ** ** In addition, since we delayed checksumming the packets ** which contained the pieces of the sec info, we have to ** do this too. ** ** INPUTS: ** ** assoc The association. ** req_header bind or alter_context PDU. ** req_header_size The size of the bind or alter_context PDU. ** resp_header partially formatted bind_ack or alter_context_response ** PDU. ** ** INPUTS/OUTPUTS: ** ** header_size On input, the size used in the ** resp_header already. On output, ** the size of the resp_header including the ** trailer. ** ** OUTPUTS: none ** ** auth_len The size of the auth_value field in the auth trailer. ** sec_context The security context element used. ** st The return status of this routine. ** rpc_s_ok ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: none ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL void rpc__cn_assoc_process_auth_tlr #ifdef _DCE_PROTO_ ( rpc_cn_assoc_p_t assoc, rpc_cn_packet_p_t req_header, unsigned32 req_header_size, rpc_cn_packet_p_t resp_header, unsigned32 *header_size, unsigned32 *auth_len, rpc_cn_sec_context_p_t *sec_context, boolean old_client, unsigned32 *st ) #else (assoc, req_header, req_header_size, resp_header, header_size, auth_len, sec_context, old_client, st) rpc_cn_assoc_p_t assoc; rpc_cn_packet_p_t req_header; unsigned32 req_header_size; rpc_cn_packet_p_t resp_header; unsigned32 *header_size; unsigned32 *auth_len; rpc_cn_sec_context_p_t *sec_context; boolean old_client, unsigned32 *st; #endif { rpc_cn_auth_tlr_t *req_auth_tlr; rpc_cn_auth_tlr_t *resp_auth_tlr; rpc_auth_info_t *info; rpc_cn_sec_context_t *sec; rpc_cn_bind_auth_value_priv_p_t local_auth_value, priv_auth_value; unsigned32 local_auth_value_len; rpc_authn_protocol_id_t authn_protocol; RPC_CN_DBG_RTN_PRINTF(SERVER rpc__cn_assoc_process_auth_tlr); CODING_ERROR (st); /* * If security was requested in the request PDU a * security response is required in the response PDU. * All security related errors will be reported within the * auth_value field of the auth trailer of the * response PDU. */ if (!RPC_CN_PKT_AUTH_TLR_PRESENT (req_header)) { *auth_len = 0; *st = rpc_s_ok; goto DONE; } RPC_DBG_PRINTF (rpc_e_dbg_auth, 20, ("(rpc__cn_assoc_process_auth_tlr) auth trailer present\n")); /* * First make sure the authentication protocol requested is * supported here. If not, send a bind_nak PDU back to the * client. */ req_auth_tlr = RPC_CN_PKT_AUTH_TLR (req_header, req_header_size); authn_protocol = RPC_CN_AUTH_CVT_ID_WIRE_TO_API ( req_auth_tlr->auth_type, st); if (*st != rpc_s_ok) { goto DONE; } if ( ! RPC_CN_AUTH_INQ_SUPPORTED ( authn_protocol)) { *st = rpc_s_unknown_auth_protocol; goto DONE; } /* * Determine whether a security context with the given * key ID already exists. If it does this is an attempt at * renewing said context. */ sec = *sec_context = NULL; rpc__cn_assoc_sec_lkup_by_id (assoc, req_auth_tlr->key_id, &sec, st); *st = rpc_s_ok; if (sec == NULL) { RPC_CN_AUTH_CREATE_INFO ( authn_protocol, req_auth_tlr->auth_level, &info, st); } if (*st != rpc_s_ok) { dce_error_string_t error_text; int temp_status; dce_error_inq_text(*st, (unsigned char*) error_text, &temp_status); /* * "%s failed: %s" */ RPC_DCE_SVC_PRINTF (( DCE_SVC(RPC__SVC_HANDLE, "%s%x"), rpc_svc_auth, svc_c_sev_error, rpc_m_call_failed, "RPC_CN_AUTH_CREATE_INFO", error_text )); goto DONE; } if (sec == NULL) { sec = rpc__cn_assoc_sec_alloc (info, st); } else { info = NULL; } if (*st != rpc_s_ok) { goto DONE; } sec->sec_key_id = req_auth_tlr->key_id; /* * Get the assoc_uuid_crc and put it in the association. * Get it from the last packet recieved. */ RPC_CN_AUTH_TLR_UUID_CRC ( authn_protocol, (pointer_t)req_auth_tlr->auth_value, RPC_CN_PKT_AUTH_LEN (req_header), &assoc->security.assoc_uuid_crc); /* * Check to see if we have pieced together the * auth_value and should use that buffer */ if (assoc->security.auth_buffer_info.auth_buffer != NULL) { local_auth_value = (rpc_cn_bind_auth_value_priv_t *) assoc->security.auth_buffer_info.auth_buffer; local_auth_value_len = assoc->security.auth_buffer_info.auth_buffer_len; /* * Better safe than sorry: make sure we get sub_type from the * packet we are going to checksum. */ local_auth_value->sub_type = ((rpc_cn_bind_auth_value_priv_t *) req_auth_tlr->auth_value)->sub_type; } else { local_auth_value = (rpc_cn_bind_auth_value_priv_t *) req_auth_tlr->auth_value; local_auth_value_len = RPC_CN_PKT_AUTH_LEN(req_header); } RPC_CN_AUTH_VFY_CLIENT_REQ (&assoc->security, sec, (pointer_t)local_auth_value, local_auth_value_len, old_client, &sec->sec_status); if (sec->sec_status == rpc_s_ok) { /* * We only checksum one packet, since we ignored everything * in the others. We want to pass the cred_length of the packet * we are doing the checksum on. */ priv_auth_value = (rpc_cn_bind_auth_value_priv_t *) req_auth_tlr->auth_value; if (assoc->raw_packet_p != NULL) { /* * Use the raw packet if it exists. */ RPC_CN_AUTH_RECV_CHECK (authn_protocol, &assoc->security, sec, (rpc_cn_common_hdr_t *)assoc->raw_packet_p->data_p, assoc->raw_packet_p->data_size, priv_auth_value->cred_length, req_auth_tlr, 0, /* dummy unpack_ints */ &sec->sec_status); } else { /* * Raw packet doesn't exist; use unpacked one. */ RPC_CN_AUTH_RECV_CHECK (authn_protocol, &assoc->security, sec, (rpc_cn_common_hdr_t *)req_header, req_header_size, priv_auth_value->cred_length, req_auth_tlr, 0, /* dummy unpack_ints */ &sec->sec_status); } } /* sec->sec_status == rpc_s_ok */ /* * Free assembly buffer */ if (assoc->security.auth_buffer_info.auth_buffer) { RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_BIG_PAC, ("(rpc__cn_assoc_process_auth_tlr) Free'd auth_buffer: %x\n", assoc->security.auth_buffer_info.auth_buffer)); RPC_MEM_FREE(assoc->security.auth_buffer_info.auth_buffer, RPC_C_MEM_CN_PAC_BUF); assoc->security.auth_buffer_info.auth_buffer = NULL; assoc->security.auth_buffer_info.auth_buffer_len = 0; assoc->security.auth_buffer_info.auth_buffer_max = 0; } /* * Start filling in the response packet */ *header_size = ((*header_size + 3) & ~0x3); resp_auth_tlr = (rpc_cn_auth_tlr_t *) ((unsigned8 *)(resp_header) + *header_size); (void) memset(resp_auth_tlr, 0, (rpc_g_cn_large_frag_size - *header_size)); resp_auth_tlr->auth_type = req_auth_tlr->auth_type; resp_auth_tlr->auth_level = req_auth_tlr->auth_level; resp_auth_tlr->stub_pad_length = 0; resp_auth_tlr->reserved = 0; resp_auth_tlr->key_id = req_auth_tlr->key_id; *header_size += RPC_CN_PKT_SIZEOF_COM_AUTH_TLR; *auth_len = rpc_g_cn_large_frag_size - *header_size; #ifdef DEBUG if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_FRAG_BIND_ACK)) { char *x; *auth_len = atoi(((x = getenv("BIND_ACK_FRAG")) == NULL ? "50" : x)); } #endif /* * We need to handle large security info if its not going to * fit inside one fragbuf. So this routine will store a * long KRB message in assoc->security->krb_message. * When the PDU is sent, the rest of the security will be sent. */ RPC_CN_AUTH_FMT_SRVR_RESP (sec->sec_status, &assoc->security, sec, (pointer_t)req_auth_tlr->auth_value, RPC_CN_PKT_AUTH_LEN (req_header), (pointer_t)resp_auth_tlr->auth_value, auth_len); /* auth_len now has length of auth_value */ *header_size += *auth_len; if (sec->sec_status != rpc_s_ok) { dce_error_string_t error_text; int temp_status; dce_error_inq_text(sec->sec_status, (unsigned char*) error_text, &temp_status); /* * "%s on server failed: %s" */ RPC_DCE_SVC_PRINTF (( DCE_SVC(RPC__SVC_HANDLE, "%s%x"), rpc_svc_auth, svc_c_sev_error, rpc_m_call_failed_s, "RPC_CN_AUTH_VFY_CLIENT_REQ", error_text )); RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_SECURITY_ERRORS, ("CN: call_rep->%x assoc->%x desc->%x client verification failed security_context->%x auth_type->%x auth_level->%x auth_len->%x stub_pad_length->%x st->%x\n", assoc->call_rep, assoc, assoc->cn_ctlblk.cn_sock, sec, req_auth_tlr->auth_type, req_auth_tlr->auth_level, RPC_CN_PKT_AUTH_LEN (req_header), req_auth_tlr->stub_pad_length, sec->sec_status)); sec->sec_state = RPC_C_SEC_STATE_INCOMPLETE; } else { sec->sec_state = RPC_C_SEC_STATE_COMPLETE; } RPC_LIST_ADD_TAIL (assoc->security.context_list, sec, rpc_cn_sec_context_p_t); assoc->security.assoc_have_uuid_crc = true; *sec_context = sec; if (info != NULL) { RPC_CN_AUTH_RELEASE_REFERENCE(&info); } DONE: /* * Deallocate the raw packet if it exists. */ if (assoc->raw_packet_p != NULL) { rpc__cn_fragbuf_free (assoc->raw_packet_p); assoc->raw_packet_p = NULL; } } /* **++ ** ** ROUTINE NAME: send_frag_resp_pdu ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Support routine to send a bind_ack or alter_context_response PDU ** with fragmented security. ** ** If the security information did not all fit in to the first ** response fragbuf, we will send it and as many more as it ** takes to completely send the credential information. ** ** INPUTS: ** ** assoc The association. ** fragbuf The response fragbuf. ** header The header of the rpc_bind_ack or alter_context_resp ** ** INPUTS/OUTPUTS: none ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: ** ** assoc->security.krb_message Contains the credentials ** we might have to send in pieces. ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: none ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL void send_frag_resp_pdu(assoc, fragbuf, header) rpc_cn_assoc_p_t assoc; rpc_cn_fragbuf_p_t fragbuf; rpc_cn_packet_p_t header; { sec_krb_message *krb_message_ptr; rpc_cn_auth_tlr_t *auth_tlr; rpc_cn_bind_auth_value_priv_t *auth_value; unsigned32 cred_remain; unsigned32 flags; unsigned32 cred_len; unsigned32 msg_length; unsigned32 offset = 0; boolean first_frag = true; boolean free_buf = false; boolean free_message=false; /* * We stashed the KRB_AP_REP message here when we built it. */ krb_message_ptr = &(assoc->security.krb_message); cred_remain = krb_message_ptr->length; auth_tlr = RPC_CN_PKT_AUTH_TLR (header, RPC_CN_PKT_FRAG_LEN (header)); auth_value = (rpc_cn_bind_auth_value_priv_t *)auth_tlr->auth_value; /* * We want to send the first PDU as is, since its all set * to go, but we may need to send the same fragbuf several * times to get all the security info across. * * Slightly different than the client side as we are filling * in only the credentials field, not the whole auth_value_t. */ do { flags = 0; if (first_frag) { flags = RPC_C_CN_FLAGS_FIRST_FRAG; first_frag = false; } cred_len = auth_value->cred_length; if (cred_remain > 0) { cred_remain -= cred_len; } if (cred_remain == 0) { flags |= RPC_C_CN_FLAGS_LAST_FRAG; free_buf = true; } RPC_CN_PKT_FLAGS (header) = flags; /* * Now actually send the PDU. Free it if free_buf set. */ rpc__cn_assoc_send_fragbuf (assoc, fragbuf, assoc->security.assoc_current_sec_context, free_buf, &(assoc->assoc_status)); RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_BIG_PAC, ("(send_frag_resp_pdu) SENT %s PDU: data_size=%u, first_frag=%s, last_frag=%s, cred_len=%u, cred_remain=%u\n", ((RPC_CN_PKT_PTYPE(header) == RPC_C_CN_PKT_BIND_ACK) ? "rpc_bind_ack" : "alter_context_resp"), fragbuf->data_size, (flags & RPC_C_CN_FLAGS_FIRST_FRAG) ? "true": "false", (flags & RPC_C_CN_FLAGS_LAST_FRAG) ? "true": "false", cred_len, cred_remain)); if (cred_remain > 0) { /* We didn't free the krb_message in fmt_srvr_resp */ free_message = true; /* * Zero out old cred info and put in next segment */ (void) memset(auth_value->credentials, 0, cred_len); /* * If the rest of the creditials will all fit, put it in, * otherwise use the same number of bytes as before. */ if (cred_len > cred_remain) { unsigned32 shorten = (cred_len - cred_remain); msg_length = cred_remain; auth_value->cred_length = cred_remain; fragbuf->data_size -= shorten; RPC_CN_PKT_AUTH_LEN (header) -= shorten; RPC_CN_PKT_FRAG_LEN (header) = fragbuf->data_size; } else { msg_length = cred_len; } offset += cred_len; assert((offset + msg_length) <= (unsigned32)krb_message_ptr->length); memcpy(auth_value->credentials, krb_message_ptr->data + offset, msg_length); } } while (cred_remain > 0); /* * Free the krb_message if we need to. */ if (free_message) { #ifdef AUTH_KRB sec_krb_message_free (krb_message_ptr); #endif RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_BIG_PAC, ("(send_frag_resp_pdu) Freeing KRB message: 0x%x\n", krb_message_ptr)); } } /* **++ ** ** ROUTINE NAME: save_sec_fragment ** ** SCOPE: INTERNAL - declared locally ** ** DESCRIPTION: ** ** Support routine which copies the bytes in the credential ** field of an auth_tlr into a reconstruction buffer. ** ** Used to process rpc_bind and alter_context PDU's which ** have fragmented credentials ** ** INPUTS: ** ** assoc The association. ** header The header of the rpc_bind or alter_context PDU. ** ** INPUTS/OUTPUTS: none ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: ** ** assoc->security.auth_buffer_info Contains the pieces of credentials ** we have previously saved. ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: none ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL void save_sec_fragment(assoc, header) rpc_cn_assoc_p_t assoc; rpc_cn_packet_p_t header; { rpc_cn_bind_auth_value_priv_t *auth_value; unsigned32 auth_value_len; rpc_cn_auth_tlr_t *auth_tlr; unsigned8 *auth_buffer; unsigned32 auth_buffer_max; unsigned32 auth_buffer_len; /* * This is a place where we stash the auth information while we * reconstruct it. */ auth_buffer = assoc->security.auth_buffer_info.auth_buffer; auth_buffer_len = assoc->security.auth_buffer_info.auth_buffer_len; auth_buffer_max = assoc->security.auth_buffer_info.auth_buffer_max; if (auth_buffer == NULL) { /* * If we get here, odds are we are going to get maybe 1 or 2 more * packets, so get some space to save time later. */ auth_buffer_max = RPC_C_CN_LARGE_FRAG_SIZE * 3; RPC_MEM_ALLOC(auth_buffer, unsigned8 *, auth_buffer_max, RPC_C_MEM_CN_PAC_BUF, RPC_C_MEM_WAITOK); RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_BIG_PAC, ("(save_sec_fragment) Alloc'd auth_buffer: %x, auth_buffer_max = %d\n", auth_buffer, auth_buffer_max)); } if ((RPC_CN_PKT_AUTH_LEN (header) + auth_buffer_len) > auth_buffer_max) { auth_buffer_max += RPC_C_CN_LARGE_FRAG_SIZE; RPC_MEM_REALLOC(auth_buffer, unsigned8 *, auth_buffer_max, RPC_C_MEM_CN_PAC_BUF, RPC_C_MEM_WAITOK); RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_BIG_PAC, ("(save_sec_fragment) Realloc'd auth_buffer: %x, auth_buffer_max = %d\n", auth_buffer, auth_buffer_max)); } /* * Concatenate this security info on to the buffer. * * We have to watch out for the checksum at the end of the * auth trailer, we only want to recover the KRB_AP_{REQ|REP} message. */ auth_tlr = RPC_CN_PKT_AUTH_TLR(header,RPC_CN_PKT_FRAG_LEN (header)); auth_value = (rpc_cn_bind_auth_value_priv_t *)auth_tlr->auth_value; auth_value_len = RPC_CN_PKT_AUTH_LEN (header) - auth_value->checksum_length; /* * For the first packet, copy the header info, for the rest * we just need the credential fragment. We also update * the cred_length field in the assembly buffer. */ if (auth_buffer_len == 0) { memcpy(auth_buffer, auth_value, auth_value_len); } else { auth_value_len -= RPC_CN_PKT_SIZEOF_BIND_AUTH_VAL; assert(auth_value_len == auth_value->cred_length); memcpy(auth_buffer+auth_buffer_len, auth_value->credentials, auth_value->cred_length); ((rpc_cn_bind_auth_value_priv_t *)auth_buffer)->cred_length += auth_value->cred_length; } RPC_DBG_PRINTF (rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_BIG_PAC, ("(save_sec_fragment) Copied to auth_buffer: %x, auth_buffer_len=%d, auth_value_len=%d, auth_buffer_max=%d\n", auth_buffer, auth_buffer_len, auth_value_len, auth_buffer_max)); auth_buffer_len += auth_value_len; /* * Update our per-association data */ assoc->security.auth_buffer_info.auth_buffer = auth_buffer; assoc->security.auth_buffer_info.auth_buffer_len = auth_buffer_len; assoc->security.auth_buffer_info.auth_buffer_max = auth_buffer_max; return; } /* vim:sw=4 ts=4 * */