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