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