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**      gssauthcn.c
81**
82**  FACILITY:
83**
84**      Remote Procedure Call (RPC)
85**
86**  ABSTRACT:
87**
88**  The gssauth CN authentication module.
89**
90**
91*/
92
93#include <config.h>
94
95#if defined(AUTH_GSS_NEGOTIATE) && AUTH_GSS_NEGOTIATE
96
97#include <gssauth.h>
98#include <gssauthcn.h>
99
100#define RPC__GSSAUTH_CN_AUTH_PADDING		16
101
102INTERNAL boolean32 rpc__gssauth_cn_three_way_winnt (void);	/* NTLM only */
103INTERNAL boolean32 rpc__gssauth_cn_three_way_gss (void);
104
105INTERNAL boolean32 rpc__gssauth_cn_context_valid (
106	rpc_cn_sec_context_p_t		/* in */     /*sec*/,
107	unsigned32			/* out */    * /*st*/
108    );
109
110INTERNAL void rpc__gssauth_negotiate_cn_create_info (
111       rpc_authn_level_t		/* in */     /*authn_level*/,
112       rpc_auth_info_p_t		/* out */    * /*auth_info*/,
113       unsigned32			/* out */    * /*st*/
114    );
115
116INTERNAL void rpc__gssauth_mskrb_cn_create_info (
117       rpc_authn_level_t		/* in */     /*authn_level*/,
118       rpc_auth_info_p_t		/* out */    * /*auth_info*/,
119       unsigned32			/* out */    * /*st*/
120    );
121
122INTERNAL void rpc__gssauth_winnt_cn_create_info (
123       rpc_authn_level_t		/* in */     /*authn_level*/,
124       rpc_auth_info_p_t		/* out */    * /*auth_info*/,
125       unsigned32			/* out */    * /*st*/
126    );
127
128INTERNAL void rpc__gssauth_netlogon_cn_create_info (
129       rpc_authn_level_t		/* in */     /*authn_level*/,
130       rpc_auth_info_p_t		/* out */    * /*auth_info*/,
131       unsigned32			/* out */    * /*st*/
132    );
133INTERNAL boolean32 rpc__gssauth_cn_cred_changed (
134	rpc_cn_sec_context_p_t		/* in */     /*sec*/,
135	unsigned32			/* out */    * /*st*/
136    );
137
138INTERNAL void rpc__gssauth_cn_cred_refresh (
139	rpc_auth_info_p_t		/* in */     /*auth_info*/,
140	unsigned32			/* out */    * /*st*/
141    );
142
143INTERNAL void rpc__gssauth_cn_fmt_client_req (
144	rpc_cn_assoc_sec_context_p_t	/* in */     /*assoc_sec*/,
145	rpc_cn_sec_context_p_t		/* in */     /*sec*/,
146	dce_pointer_t			/* in/out */ /*auth_value*/,
147	unsigned32			/* in/out */ * /*auth_value_len*/,
148	dce_pointer_t			/* in/out */ * /*last_auth_pos*/,
149	unsigned32			/* out */    * /*auth_len_remain*/,
150	unsigned32			/* in */     /*old_server*/,
151	unsigned32			/* out */    * /*st*/
152    );
153
154INTERNAL void rpc__gssauth_cn_fmt_srvr_resp (
155	unsigned32			/* in */     /*verify_st*/,
156	rpc_cn_assoc_sec_context_p_t	/* in */     /*assoc_sec*/,
157	rpc_cn_sec_context_p_t		/* in */     /*sec*/,
158	dce_pointer_t			/* in */     /*req_auth_value*/,
159	unsigned32			/* in */     /*req_auth_value_len*/,
160	dce_pointer_t			/* in/out */ /*auth_value*/,
161	unsigned32			/* in/out */ * /*auth_value_len*/
162    );
163
164INTERNAL void rpc__gssauth_cn_free_prot_info (
165	rpc_auth_info_p_t		/* in */     /*info*/,
166	rpc_cn_auth_info_p_t		/* in/out */ * /*cn_info*/
167    );
168
169INTERNAL void rpc__gssauth_cn_get_prot_info (
170	rpc_auth_info_p_t		/* in */     /*info*/,
171	rpc_cn_auth_info_p_t		/* out */    * /*cn_info*/,
172	unsigned32			/* out */    * /*st*/
173    );
174
175INTERNAL void rpc__gssauth_cn_pre_call (
176	rpc_cn_assoc_sec_context_p_t	/* in */     /*assoc_sec*/,
177	rpc_cn_sec_context_p_t		/* in */     /*sec*/,
178	dce_pointer_t			/* in/out */ /*auth_value*/,
179	unsigned32			/* in/out */ * /*auth_value_len*/,
180	unsigned32			/* in/out */ * /*st*/
181    );
182
183INTERNAL void rpc__gssauth_cn_pre_send (
184	rpc_cn_assoc_sec_context_p_t	/* in */     /*assoc_sec*/,
185	rpc_cn_sec_context_p_t		/* in */     /*sec*/,
186	rpc_socket_iovec_p_t		/* in/out */ /*iov*/,
187	unsigned32			/* in */     /*iovlen*/,
188	rpc_socket_iovec_p_t		/* out */    /*out_iov*/,
189	unsigned32			/* out */    * /*st*/
190    );
191
192INTERNAL void rpc__gssauth_cn_recv_check (
193	rpc_cn_assoc_sec_context_p_t	/* in */     /*assoc_sec*/,
194	rpc_cn_sec_context_p_t		/* in */     /*sec*/,
195	rpc_cn_common_hdr_p_t		/* in */     /*pdu*/,
196	unsigned32			/* in */     /*pdu_len*/,
197	unsigned32			/* in */     /*cred_len*/,
198	rpc_cn_auth_tlr_p_t		/* in */     /*auth_tlr*/,
199	boolean32			/* in */     /*unpack_ints*/,
200	unsigned32			/* out */    * /*st*/
201    );
202
203INTERNAL void rpc__gssauth_cn_tlr_uuid_crc (
204	dce_pointer_t			/* in */     /*auth_value*/,
205	unsigned32			/* in */     /*auth_value_len*/,
206	unsigned32			/* out */    * /*uuid_crc*/
207    );
208
209INTERNAL void rpc__gssauth_cn_tlr_unpack (
210	rpc_cn_packet_p_t		/* in */     /*pkt_p*/,
211	unsigned32			/* in */     /*auth_value_len*/,
212	unsigned8			/* out */    * /*packed_drep*/
213    );
214
215INTERNAL void rpc__gssauth_cn_vfy_client_req (
216	rpc_cn_assoc_sec_context_p_t	/* in */     /*assoc_sec*/,
217	rpc_cn_sec_context_p_t		/* in */     /*sec*/,
218	dce_pointer_t			/* in */     /*auth_value*/,
219	unsigned32			/* in */     /*auth_value_len*/,
220	unsigned32			/* in */     /*old_client*/,
221	unsigned32			/* out */    * /*st*/
222    );
223
224INTERNAL void rpc__gssauth_cn_vfy_srvr_resp (
225	rpc_cn_assoc_sec_context_p_t	/* in */     /*assoc_sec*/,
226	rpc_cn_sec_context_p_t		/* in */     /*sec*/,
227	dce_pointer_t			/* in/out */ /*auth_value*/,
228	unsigned32			/* in */     /*auth_value_len*/,
229	unsigned32			/* out */    * /*st*/
230    );
231
232INTERNAL const rpc_cn_auth_epv_t rpc_g_gssauth_negotiate_cn_epv =
233{
234    .three_way      = rpc__gssauth_cn_three_way_gss,
235    .context_valid  = rpc__gssauth_cn_context_valid,
236    .create_info    = rpc__gssauth_negotiate_cn_create_info,
237    .cred_changed   = rpc__gssauth_cn_cred_changed,
238    .cred_refresh   = rpc__gssauth_cn_cred_refresh,
239    .fmt_client_req = rpc__gssauth_cn_fmt_client_req,
240    .fmt_srvr_resp  = rpc__gssauth_cn_fmt_srvr_resp,
241    .free_prot_info = rpc__gssauth_cn_free_prot_info,
242    .get_prot_info  = rpc__gssauth_cn_get_prot_info,
243    .pre_call       = rpc__gssauth_cn_pre_call,
244    .pre_send       = rpc__gssauth_cn_pre_send,
245    .recv_check     = rpc__gssauth_cn_recv_check,
246    .tlr_uuid_crc   = rpc__gssauth_cn_tlr_uuid_crc,
247    .tlr_unpack     = rpc__gssauth_cn_tlr_unpack,
248    .vfy_client_req = rpc__gssauth_cn_vfy_client_req,
249    .vfy_srvr_resp  = rpc__gssauth_cn_vfy_srvr_resp
250};
251
252INTERNAL const rpc_cn_auth_epv_t rpc_g_gssauth_mskrb_cn_epv =
253{
254    .three_way      =   rpc__gssauth_cn_three_way_gss,
255    .context_valid  =   rpc__gssauth_cn_context_valid,
256    .create_info    =   rpc__gssauth_mskrb_cn_create_info,
257    .cred_changed   =   rpc__gssauth_cn_cred_changed,
258    .cred_refresh   =   rpc__gssauth_cn_cred_refresh,
259    .fmt_client_req =   rpc__gssauth_cn_fmt_client_req,
260    .fmt_srvr_resp  =   rpc__gssauth_cn_fmt_srvr_resp,
261    .free_prot_info =   rpc__gssauth_cn_free_prot_info,
262    .get_prot_info  =   rpc__gssauth_cn_get_prot_info,
263    .pre_call       =   rpc__gssauth_cn_pre_call,
264    .pre_send       =   rpc__gssauth_cn_pre_send,
265    .recv_check     =   rpc__gssauth_cn_recv_check,
266    .tlr_uuid_crc   =   rpc__gssauth_cn_tlr_uuid_crc,
267    .tlr_unpack     =   rpc__gssauth_cn_tlr_unpack,
268    .vfy_client_req =   rpc__gssauth_cn_vfy_client_req,
269    .vfy_srvr_resp  =   rpc__gssauth_cn_vfy_srvr_resp
270};
271
272INTERNAL const rpc_cn_auth_epv_t rpc_g_gssauth_winnt_cn_epv =
273{
274    .three_way      =   rpc__gssauth_cn_three_way_winnt,
275    .context_valid  =   rpc__gssauth_cn_context_valid,
276    .create_info    =   rpc__gssauth_winnt_cn_create_info,
277    .cred_changed   =   rpc__gssauth_cn_cred_changed,
278    .cred_refresh   =   rpc__gssauth_cn_cred_refresh,
279    .fmt_client_req =   rpc__gssauth_cn_fmt_client_req,
280    .fmt_srvr_resp  =   rpc__gssauth_cn_fmt_srvr_resp,
281    .free_prot_info =   rpc__gssauth_cn_free_prot_info,
282    .get_prot_info  =   rpc__gssauth_cn_get_prot_info,
283    .pre_call       =   rpc__gssauth_cn_pre_call,
284    .pre_send       =   rpc__gssauth_cn_pre_send,
285    .recv_check     =   rpc__gssauth_cn_recv_check,
286    .tlr_uuid_crc   =   rpc__gssauth_cn_tlr_uuid_crc,
287    .tlr_unpack     =   rpc__gssauth_cn_tlr_unpack,
288    .vfy_client_req =   rpc__gssauth_cn_vfy_client_req,
289    .vfy_srvr_resp  =   rpc__gssauth_cn_vfy_srvr_resp
290};
291
292INTERNAL const rpc_cn_auth_epv_t rpc_g_gssauth_netlogon_cn_epv =
293{
294    .three_way      =   rpc__gssauth_cn_three_way_gss,
295    .context_valid  =   rpc__gssauth_cn_context_valid,
296    .create_info    =   rpc__gssauth_netlogon_cn_create_info,
297    .cred_changed   =   rpc__gssauth_cn_cred_changed,
298    .cred_refresh   =   rpc__gssauth_cn_cred_refresh,
299    .fmt_client_req =   rpc__gssauth_cn_fmt_client_req,
300    .fmt_srvr_resp  =   rpc__gssauth_cn_fmt_srvr_resp,
301    .free_prot_info =   rpc__gssauth_cn_free_prot_info,
302    .get_prot_info  =   rpc__gssauth_cn_get_prot_info,
303    .pre_call       =   rpc__gssauth_cn_pre_call,
304    .pre_send       =   rpc__gssauth_cn_pre_send,
305    .recv_check     =   rpc__gssauth_cn_recv_check,
306    .tlr_uuid_crc   =   rpc__gssauth_cn_tlr_uuid_crc,
307    .tlr_unpack     =   rpc__gssauth_cn_tlr_unpack,
308    .vfy_client_req =   rpc__gssauth_cn_vfy_client_req,
309    .vfy_srvr_resp  =   rpc__gssauth_cn_vfy_srvr_resp
310};
311
312/*****************************************************************************/
313/*
314**++
315**
316**  ROUTINE NAME:       rpc__gssauth_cn_three_way
317**
318**  SCOPE:              INTERNAL - declared locally
319**
320**  DESCRIPTION:
321**
322**      Determine whether the authentication protocol requires a
323**      3-way authentication handshake. If true the client is expected to
324**      provide an rpc_auth3 PDU before the security context is fully
325**      established and a call can be made.
326**
327**  INPUTS:             none
328**
329**  INPUTS/OUTPUTS:     none
330**
331**  OUTPUTS:            none
332**
333**  IMPLICIT INPUTS:    none
334**
335**  IMPLICIT OUTPUTS:   none
336**
337**  FUNCTION VALUE:     boolean32
338**
339**      True if the authentication protocol requires a 3-way
340**      authentication handshake.
341**
342**  SIDE EFFECTS:       none
343**
344**--
345**/
346
347INTERNAL boolean32 rpc__gssauth_cn_three_way_winnt (void)
348{
349	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
350		("(rpc__gssauth_cn_three_way)\n"));
351
352	return true;
353}
354
355INTERNAL boolean32 rpc__gssauth_cn_three_way_gss (void)
356{
357	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
358		("(rpc__gssauth_cn_three_way)\n"));
359
360	return false;
361}
362
363/*****************************************************************************/
364/*
365**++
366**
367**  ROUTINE NAME:       rpc__gssauth_cn_context_valid
368**
369**  SCOPE:              INTERNAL - declared locally
370**
371**  DESCRIPTION:
372**
373**      Determine whether the established security context will be
374**      valid (i. e. timely) for the next 300 seconds. If
375**      not this routine will try to renew the context.
376**      If it cannot be renewed false is returned. This is
377**      called from the client side.
378**
379**  INPUTS:
380**
381**      sec             A pointer to security context element which includes
382**                      the key ID, auth information rep and RPC auth
383**                      information rep.
384**
385**  INPUTS/OUTPUTS:     none
386**
387**  OUTPUTS:
388**
389**      st              The return status of this routine.
390**
391**  IMPLICIT INPUTS:    none
392**
393**  IMPLICIT OUTPUTS:   none
394**
395**  FUNCTION VALUE:     boolean32
396**
397**      True if security context identified by the auth
398**      information rep and RPC auth information rep will
399**      still be valid in 300 seconds, false if not.
400**
401**  SIDE EFFECTS:
402**
403**      The context may be renewed.
404**
405**--
406**/
407
408INTERNAL boolean32 rpc__gssauth_cn_context_valid
409(
410	rpc_cn_sec_context_p_t	sec,
411	unsigned32		*st
412)
413{
414	CODING_ERROR (st);
415	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
416		("(rpc__gssauth_cn_context_valid)\n"));
417
418	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT,
419		("(rpc__gssauth_cn_context_valid) prot->%x level->%x key_id->%x\n",
420		sec->sec_info->authn_protocol,
421		sec->sec_info->authn_level,
422		sec->sec_key_id));
423
424#ifdef DEBUG
425	if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_CONTEXT_VALID)) {
426		*st = RPC_S_CN_DBG_AUTH_FAILURE;
427		return false;
428	}
429#endif
430
431	*st = rpc_s_ok;
432	return true;
433}
434
435/*****************************************************************************/
436/*
437**++
438**
439**  ROUTINE NAME:       rpc__gssauth_cn_create_info
440**
441**  SCOPE:              INTERNAL - declared locally
442**
443**  DESCRIPTION:
444**
445**      Create an auth information rep data structure with and
446**      add a reference to it. This is called on the server
447**      side. The fields will be initialized to NULL values.
448**      The caller should fill them in based on information
449**      decrypted from the authenticator passed in the bind
450**      request.
451**
452**  INPUTS:
453**
454**      authn_level     The authentication level to be applied over this
455**                      security context.
456**
457**  INPUTS/OUTPUTS:     none
458**
459**  OUTPUTS:
460**
461**      info            A pointer to the auth information rep structure
462**                      containing RPC protocol indenpendent information.
463**      st              The return status of this routine.
464**
465**  IMPLICIT INPUTS:    none
466**
467**  IMPLICIT OUTPUTS:   none
468**
469**  FUNCTION VALUE:     none
470**
471**  SIDE EFFECTS:
472**
473**      The newly create auth info will have a reference count of 1.
474**
475**--
476**/
477
478INTERNAL void rpc__gssauth_cn_create_info
479(
480	rpc_authn_protocol_id_t authn_protocol,
481	rpc_authn_level_t	authn_level,
482	rpc_auth_info_p_t	*auth_info,
483	unsigned32		*st
484)
485{
486	rpc_gssauth_info_p_t gssauth_info;
487
488	CODING_ERROR(st);
489	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
490		("(rpc__gssauth_cn_create_info)\n"));
491
492	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT,
493		("(rpc__gssauth_cn_create_info) prot->%x level->%x\n",
494		authn_protocol,
495		authn_level));
496
497#ifdef DEBUG
498	if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_CREATE_INFO)) {
499		*st = RPC_S_CN_DBG_AUTH_FAILURE;
500		return;
501	}
502#endif
503
504	switch (authn_level) {
505	case rpc_c_authn_level_connect:
506	case rpc_c_authn_level_pkt_integrity:
507	case rpc_c_authn_level_pkt_privacy:
508		break;
509	default:
510		*st = rpc_s_unsupported_authn_level;
511		return;
512	}
513
514	/*
515	 * Allocate storage for a gssauth info structure from heap.
516	 */
517	RPC_MEM_ALLOC(gssauth_info,
518		      rpc_gssauth_info_p_t,
519		      sizeof (rpc_gssauth_info_t),
520		      RPC_C_MEM_GSSAUTH_INFO,
521		      RPC_C_MEM_WAITOK);
522	memset (gssauth_info, 0, sizeof(rpc_gssauth_info_t));
523
524	/*
525	 * Initialize the common auth_info stuff.
526	 */
527	gssauth_info->auth_info.refcount = 1;
528	gssauth_info->auth_info.server_princ_name = '\0';
529	gssauth_info->auth_info.authn_level = authn_level;
530	gssauth_info->auth_info.authn_protocol = authn_protocol;
531	gssauth_info->auth_info.authz_protocol = rpc_c_authz_name;
532	gssauth_info->auth_info.is_server = true;
533
534	*auth_info = &gssauth_info->auth_info;
535	*st = rpc_s_ok;
536}
537
538INTERNAL void rpc__gssauth_negotiate_cn_create_info
539(
540	rpc_authn_level_t	authn_level,
541	rpc_auth_info_p_t	*auth_info,
542	unsigned32		*st
543)
544{
545	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
546		("(rpc__gssauth_negotiate_cn_create_info)\n"));
547
548	rpc__gssauth_cn_create_info(rpc_c_authn_gss_negotiate,
549				    authn_level,
550				    auth_info,
551				    st);
552}
553
554INTERNAL void rpc__gssauth_mskrb_cn_create_info
555(
556	rpc_authn_level_t	authn_level,
557	rpc_auth_info_p_t	*auth_info,
558	unsigned32		*st
559)
560{
561	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
562		("(rpc__gssauth_mskrb_cn_create_info)\n"));
563
564	rpc__gssauth_cn_create_info(rpc_c_authn_gss_mskrb,
565				    authn_level,
566				    auth_info,
567				    st);
568}
569
570INTERNAL void rpc__gssauth_winnt_cn_create_info
571(
572	rpc_authn_level_t	authn_level,
573	rpc_auth_info_p_t	*auth_info,
574	unsigned32		*st
575)
576{
577	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
578		("(rpc__gssauth_winnt_cn_create_info)\n"));
579
580	rpc__gssauth_cn_create_info(rpc_c_authn_winnt,
581				    authn_level,
582				    auth_info,
583				    st);
584}
585
586INTERNAL void rpc__gssauth_netlogon_cn_create_info
587(
588	rpc_authn_level_t	authn_level,
589	rpc_auth_info_p_t	*auth_info,
590	unsigned32		*st
591)
592{
593	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
594		("(rpc__gssauth_netlogon_cn_create_info)\n"));
595
596	rpc__gssauth_cn_create_info(rpc_c_authn_netlogon,
597				    authn_level,
598				    auth_info,
599				    st);
600}
601
602/*****************************************************************************/
603/*
604**++
605**
606**  ROUTINE NAME:       rpc__gssauth_cn_cred_changed
607**
608**  SCOPE:              INTERNAL - declared locally
609**
610**  DESCRIPTION:
611**
612**      Determine whether the client's credentials stored in the
613**      security context are different from those in the auth info.
614**      If they are not the same return true, else false.
615**
616**  INPUTS:
617**
618**      sec             A pointer to security context element which includes
619**                      the key ID, auth information rep and RPC auth
620**                      information rep.
621**
622**  INPUTS/OUTPUTS:     none
623**
624**  OUTPUTS:
625**
626**      st              The return status of this routine.
627**
628**  IMPLICIT INPUTS:    none
629**
630**  IMPLICIT OUTPUTS:   none
631**
632**  FUNCTION VALUE:     boolean32
633**
634**      True if the credentials identified by the auth
635**      information rep and RPC auth information rep are different,
636**      false if not.
637**
638**      The md5 checksum algorithm requires the use of the session key
639**      to encrypt the CRC(assoc_uuid).  Since the session key will
640**      change when the credential changes, this routine sets the flag
641**      indicating that a (potentially) valid encrypted crc is now
642**      invalid, forcing a recomputation.
643**
644**  SIDE EFFECTS:       none
645**
646**--
647**/
648
649INTERNAL boolean32 rpc__gssauth_cn_cred_changed
650(
651	rpc_cn_sec_context_p_t	sec,
652	unsigned32		*st
653)
654{
655	CODING_ERROR(st);
656	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
657		("(rpc__gssauth_cn_cred_changed)\n"));
658
659	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT,
660		("(rpc__gssauth_cn_cred_changed) prot->%x level->%x key_id->%x\n",
661		sec->sec_info->authn_protocol,
662		sec->sec_info->authn_level,
663		sec->sec_key_id));
664
665#ifdef DEBUG
666	if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_CRED_CHANGED)) {
667		*st = RPC_S_CN_DBG_AUTH_FAILURE;
668		return false;
669	}
670#endif
671
672	/*
673	 * Assume that cred is already valid.
674	 */
675	*st = rpc_s_ok;
676	return false;
677}
678
679/*****************************************************************************/
680/*
681**++
682**
683**  ROUTINE NAME:       rpc__gssauth_cn_cred_refresh
684**
685**  SCOPE:              INTERNAL - declared locally
686**
687**  DESCRIPTION:
688**
689**      Determine whether the client's credentials are still
690**      valid. If not this routine will try to renew the credentials.
691**      If they cannot be renewed an error is returned. This routine
692**      is called from the client side.
693**
694**  INPUTS:
695**
696**      auth_info       A pointer to the auth information rep
697**
698**  INPUTS/OUTPUTS:     none
699**
700**  OUTPUTS:
701**
702**      st              The return status of this routine.
703**
704**  IMPLICIT INPUTS:    none
705**
706**  IMPLICIT OUTPUTS:   none
707**
708**  FUNCTION VALUE:     none
709**
710**  SIDE EFFECTS:       none
711**
712**--
713**/
714
715INTERNAL void rpc__gssauth_cn_cred_refresh
716(
717	rpc_auth_info_p_t	auth_info,
718	unsigned32		*st
719)
720{
721	CODING_ERROR(st);
722	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
723		("(rpc__gssauth_cn_cred_refresh)\n"));
724
725	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT,
726		("(rpc__gssauth_cn_cred_refresh) prot->%x level->%x\n",
727		auth_info->authn_protocol,
728		auth_info->authn_level));
729
730#ifdef DEBUG
731	if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_CRED_REFRESH)) {
732		*st = RPC_S_CN_DBG_AUTH_FAILURE;
733		return;
734	}
735#endif
736
737	/*
738	 * Assume that cred is already valid.
739	 */
740	*st = rpc_s_ok;
741}
742
743PRIVATE const char *rpc__gssauth_error_map
744(
745	OM_uint32		maj_stat,
746	OM_uint32		min_stat,
747	const gss_OID		mech,
748	char			*message_buffer,
749	unsigned32		message_length,
750	unsigned32		*st
751)
752{
753	switch (maj_stat) {
754	case GSS_S_BAD_MECH:
755		*st = rpc_s_unknown_authn_service;
756		break;
757	case GSS_S_BAD_NAME:
758		*st = rpc_s_unsupported_name_syntax;
759		break;
760	case GSS_S_BAD_BINDINGS:
761		*st = rpc_s_auth_badaddr;
762		break;
763	case GSS_S_BAD_STATUS:
764		*st = rpc_s_unknown_status_code;
765		break;
766	case GSS_S_BAD_SIG:
767		*st = rpc_s_auth_bad_integrity;
768		break;
769	case GSS_S_NO_CRED:
770	case GSS_S_NO_CONTEXT:
771		*st = rpc_s_auth_nokey;
772		break;
773	case GSS_S_DEFECTIVE_TOKEN:
774		*st = rpc_s_auth_field_toolong;
775		break;
776	case GSS_S_DEFECTIVE_CREDENTIAL:
777		*st = rpc_s_invalid_credentials;
778		break;
779	case GSS_S_CONTEXT_EXPIRED:
780		*st = rpc_s_auth_tkt_expired;
781		break;
782	case GSS_S_BAD_QOP:
783		*st = rpc_s_protect_level_mismatch;
784		break;
785	case GSS_S_UNAUTHORIZED:
786		*st = rpc_s_authn_authz_mismatch;
787		break;
788	case GSS_S_NAME_NOT_MN:
789		*st = rpc_s_auth_not_us;
790		break;
791	case GSS_S_OLD_TOKEN:
792	case GSS_S_DUPLICATE_TOKEN:
793		*st = rpc_s_auth_repeat;
794		break;
795	case GSS_S_GAP_TOKEN:
796		*st = rpc_s_auth_badorder;
797		break;
798	case GSS_S_UNSEQ_TOKEN:
799		*st = rpc_s_auth_badseq;
800		break;
801	case GSS_S_CONTINUE_NEEDED:
802		*st = rpc_s_partial_credentials;
803		break;
804	case GSS_S_COMPLETE:
805		*st = rpc_s_ok;
806		break;
807	case GSS_S_DUPLICATE_ELEMENT:
808	case GSS_S_UNAVAILABLE:
809	case GSS_S_FAILURE:
810	default:
811		*st = rpc_s_auth_method;
812		break;
813	}
814
815	/*
816	 * Possibly this should check that mech is GSS_KRB5_MECHANISM first.
817	 * But, it's likely that other mechanisms use the krb5 minor status
818	 * namespace too, and/or that the Kerberos mechanism uses a different
819	 * OID. So safest to leave it as is for now.
820	 */
821	switch ((signed32) min_stat) {
822	case KRB5KRB_AP_ERR_BAD_INTEGRITY:
823		*st = rpc_s_auth_bad_integrity;
824		break;
825	case KRB5KRB_AP_ERR_TKT_EXPIRED:
826		*st = rpc_s_auth_tkt_expired;
827		break;
828	case KRB5KRB_AP_ERR_TKT_NYV:
829		*st = rpc_s_auth_tkt_nyv;
830		break;
831	case KRB5KRB_AP_ERR_REPEAT:
832		*st = rpc_s_auth_repeat;
833		break;
834	case KRB5KRB_AP_ERR_NOT_US:
835		*st = rpc_s_auth_not_us;
836		break;
837	case KRB5KRB_AP_ERR_BADMATCH:
838		*st = rpc_s_auth_badmatch;
839		break;
840	case KRB5KRB_AP_ERR_SKEW:
841		*st = rpc_s_auth_skew;
842		break;
843	case KRB5KRB_AP_ERR_BADADDR:
844		*st = rpc_s_auth_badaddr;
845		break;
846	case KRB5KRB_AP_ERR_BADVERSION:
847		*st = rpc_s_auth_badversion;
848		break;
849	case KRB5KRB_AP_ERR_MSG_TYPE:
850		*st = rpc_s_auth_msg_type;
851		break;
852	case KRB5KRB_AP_ERR_MODIFIED:
853		*st = rpc_s_auth_modified;
854		break;
855	case KRB5KRB_AP_ERR_BADORDER:
856		*st = rpc_s_auth_badorder;
857		break;
858	case KRB5KRB_AP_ERR_BADKEYVER:
859		*st = rpc_s_auth_badkeyver;
860		break;
861	case KRB5KRB_AP_ERR_NOKEY:
862		*st = rpc_s_auth_nokey;
863		break;
864	case KRB5KRB_AP_ERR_MUT_FAIL:
865		*st = rpc_s_auth_mut_fail;
866		break;
867	case KRB5KRB_AP_ERR_BADDIRECTION:
868		*st = rpc_s_auth_baddirection;
869		break;
870	case KRB5KRB_AP_ERR_METHOD:
871		*st = rpc_s_auth_method;
872		break;
873	case KRB5KRB_AP_ERR_BADSEQ:
874		*st = rpc_s_auth_badseq;
875		break;
876	case KRB5KRB_AP_ERR_INAPP_CKSUM:
877		*st = rpc_s_auth_inapp_cksum;
878		break;
879	default:
880		break;
881	}
882
883	if (message_buffer != NULL && message_length != 0) {
884		OM_uint32 min2;
885		gss_buffer_desc major_msg;
886		gss_buffer_desc minor_msg;
887		OM_uint32 msg_ctx = 0;
888
889		major_msg.value = NULL;
890		major_msg.length = 0;
891		minor_msg.value = NULL;
892		minor_msg.length = 0;
893
894		gss_display_status(&min2, maj_stat, GSS_C_GSS_CODE,
895				   NULL, &msg_ctx, &major_msg);
896		gss_display_status(&min2, min_stat, GSS_C_MECH_CODE,
897				   mech, &msg_ctx, &minor_msg);
898
899		snprintf((char *)message_buffer, message_length - 1,
900			 "major: %*s (%u) minor: %*s (%u) => dcerpc: (0x%08x)\n",
901			 (int)major_msg.length, (char *)major_msg.value,
902			 maj_stat, (int)minor_msg.length,
903			 (char *)minor_msg.value, min_stat,
904			 (unsigned int)*st);
905		message_buffer[message_length - 1] = '\0';
906
907		gss_release_buffer(&min2, &major_msg);
908		gss_release_buffer(&min2, &minor_msg);
909
910		return (const char *)message_buffer;
911	}
912
913	return NULL;
914}
915
916INTERNAL OM_uint32 rpc__gssauth_select_flags
917(
918	OM_uint32		*min_stat,
919	rpc_authn_level_t	authn_level,
920	OM_uint32		*req_flags
921)
922{
923	OM_uint32 flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG |
924                          GSS_C_SEQUENCE_FLAG | GSS_C_DCE_STYLE;
925	*min_stat = 0;
926
927	switch (authn_level) {
928	case rpc_c_authn_level_connect:
929		break;
930	case rpc_c_protect_level_pkt_integ:
931		flags |= GSS_C_INTEG_FLAG;
932		break;
933	case rpc_c_protect_level_pkt_privacy:
934		flags |= GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG;
935		break;
936	}
937
938	*req_flags = flags;
939	return GSS_S_COMPLETE;
940}
941
942INTERNAL OM_uint32 rpc__gssauth_create_client_token
943(
944	OM_uint32			*min_stat,
945	const rpc_cn_sec_context_p_t	sec,
946	const gss_cred_id_t		gss_creds,
947	const gss_name_t		gss_server_name,
948	gss_ctx_id_t			*gss_ctx,
949	gss_OID 			*actual_mech,
950	gss_buffer_desc			*output_token
951)
952{
953	OM_uint32 maj_stat;
954	gss_OID req_mech = GSS_C_NO_OID;
955	OM_uint32 req_flags;
956	gss_buffer_desc input_token;
957
958	maj_stat = rpc__gssauth_select_mech(min_stat,
959					    sec->sec_info->authn_protocol,
960					    &req_mech);
961	if (maj_stat != GSS_S_COMPLETE) {
962		return maj_stat;
963	}
964
965	maj_stat = rpc__gssauth_select_flags(min_stat,
966					     sec->sec_info->authn_level,
967					     &req_flags);
968	if (maj_stat != GSS_S_COMPLETE) {
969		return maj_stat;
970	}
971
972	input_token.value = NULL;
973	input_token.length = 0;
974
975	maj_stat = gss_init_sec_context(min_stat,
976				        gss_creds,
977				        gss_ctx,
978				        gss_server_name,
979				        req_mech,
980				        req_flags,
981				        GSS_C_INDEFINITE,
982				        NULL,
983				        &input_token,
984				        actual_mech,
985				        output_token,
986				        NULL,
987				        NULL);
988	return maj_stat;
989}
990
991INTERNAL OM_uint32 rpc__gssauth_verify_server_token
992(
993	OM_uint32			*min_stat,
994	const rpc_cn_sec_context_p_t	sec,
995	const gss_cred_id_t		gss_creds,
996	const gss_name_t		gss_server_name,
997	gss_ctx_id_t			gss_ctx,
998	gss_buffer_desc			input_token,
999	gss_OID				*actual_mech,
1000	gss_buffer_desc			*output_token
1001)
1002{
1003	OM_uint32 maj_stat;
1004	gss_OID req_mech = GSS_C_NO_OID;
1005	OM_uint32 req_flags;
1006
1007	assert(gss_ctx != GSS_C_NO_CONTEXT);
1008
1009	maj_stat = rpc__gssauth_select_mech(min_stat,
1010					    sec->sec_info->authn_protocol,
1011					    &req_mech);
1012	if (maj_stat != GSS_S_COMPLETE) {
1013		return maj_stat;
1014	}
1015
1016	maj_stat = rpc__gssauth_select_flags(min_stat,
1017					     sec->sec_info->authn_protocol,
1018					     &req_flags);
1019	if (maj_stat != GSS_S_COMPLETE) {
1020		return maj_stat;
1021	}
1022
1023	maj_stat = gss_init_sec_context(min_stat,
1024				        gss_creds,
1025				        &gss_ctx,
1026				        gss_server_name,
1027				        req_mech,
1028				        req_flags,
1029				        GSS_C_INDEFINITE,
1030				        NULL,
1031				        &input_token,
1032				        actual_mech,
1033				        output_token,
1034				        NULL,
1035				        NULL);
1036
1037	return maj_stat;
1038}
1039
1040/*****************************************************************************/
1041/*
1042**++
1043**
1044**  ROUTINE NAME:       rpc__gssauth_cn_fmt_client_req
1045**
1046**  SCOPE:              INTERNAL - declared locally
1047**
1048**  DESCRIPTION:
1049**
1050**      This routine will format the auth_value field of
1051**      either an rpc_bind or rpc_alter_context PDU. This is
1052**      called from the client side association state machine.
1053**
1054**  INPUTS:
1055**
1056**      assoc_sec       A pointer to per-association security context
1057**                      including association UUID CRC and sequence numbers.
1058**      sec             A pointer to security context element which includes
1059**                      the key ID, auth information rep and RPC auth
1060**                      information rep.
1061**      auth_value      A pointer to the auth_value field in the rpc_bind or
1062**                      rpc_alter_context PDU authentication trailer.
1063**
1064**  INPUTS/OUTPUTS:
1065**
1066**      auth_value_len  On input, the lenght, in bytes of the available space
1067**                      for the auth_value field. On output, the lenght in
1068**                      bytes used in encoding the auth_value field. Zero if
1069**                      an error status is returned.
1070**
1071**  OUTPUTS:
1072**
1073**      st              The return status of this routine.
1074**
1075**  IMPLICIT INPUTS:    none
1076**
1077**  IMPLICIT OUTPUTS:   none
1078**
1079**  FUNCTION VALUE:     none
1080**
1081**  SIDE EFFECTS:       none
1082**
1083**--
1084**/
1085
1086INTERNAL void rpc__gssauth_cn_fmt_client_req
1087(
1088	rpc_cn_assoc_sec_context_p_t	assoc_sec ATTRIBUTE_UNUSED,
1089	rpc_cn_sec_context_p_t		sec,
1090	dce_pointer_t			auth_value,
1091	unsigned32			*auth_value_len,
1092	dce_pointer_t			*last_auth_pos ATTRIBUTE_UNUSED,
1093	unsigned32			*auth_len_remain,
1094	unsigned32			old_server ATTRIBUTE_UNUSED,
1095	unsigned32			*st
1096)
1097{
1098	rpc_gssauth_info_p_t gssauth_info = (rpc_gssauth_info_p_t)sec->sec_info;
1099	rpc_gssauth_cn_info_p_t gssauth_cn_info = (rpc_gssauth_cn_info_p_t)sec->sec_cn_info;
1100	int maj_stat;
1101	OM_uint32 min_stat;
1102	gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
1103
1104	CODING_ERROR(st);
1105	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
1106		("(rpc__gssauth_cn_fmt_client_req)\n"));
1107
1108	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT,
1109		("(rpc__gssauth_cn_fmt_client_req) prot->%x level->%x key_id->%x assoc_uuid_crc->%x xmit_seq->%x recv_seq->%x\n",
1110		sec->sec_info->authn_protocol,
1111		sec->sec_info->authn_level,
1112		sec->sec_key_id,
1113		assoc_sec->assoc_uuid_crc,
1114		assoc_sec->assoc_next_snd_seq,
1115		assoc_sec->assoc_next_rcv_seq));
1116
1117#ifdef DEBUG
1118	if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_FMT_CLIENT_REQ)) {
1119		*st = RPC_S_CN_DBG_AUTH_FAILURE;
1120		return;
1121	}
1122#endif
1123
1124	if (gssauth_cn_info->gss_ctx != GSS_C_NO_CONTEXT) {
1125		/*
1126		 * transfer the output of rpc__gssauth_verify_server_token()
1127		 */
1128		output_token.length = assoc_sec->krb_message.length;
1129		output_token.value = assoc_sec->krb_message.data;
1130		assoc_sec->krb_message.length = 0;
1131		assoc_sec->krb_message.data = NULL;
1132	} else {
1133		maj_stat = rpc__gssauth_create_client_token(&min_stat,
1134							    sec,
1135							    gssauth_info->gss_creds,
1136							    gssauth_info->gss_server_name,
1137							    &gssauth_cn_info->gss_ctx,
1138							    &gssauth_cn_info->gss_mech,
1139							    &output_token);
1140		if (GSS_ERROR(maj_stat)) {
1141			char msg[BUFSIZ];
1142			rpc__gssauth_error_map(maj_stat, min_stat,
1143					       gssauth_cn_info->gss_mech,
1144					       msg, sizeof(msg), st);
1145			RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
1146				("(rpc__gssauth_cn_fmt_client_req): %s\n", msg));
1147			return;
1148		}
1149		gssauth_cn_info->gss_stat = maj_stat;
1150	}
1151
1152	if (*auth_value_len < output_token.length) {
1153		assoc_sec->krb_message.length = (int) output_token.length;
1154		assoc_sec->krb_message.data = output_token.value;
1155
1156		*auth_value_len = (unsigned32) output_token.length;
1157		memset((unsigned_char_p_t)auth_value, 0xAF, *auth_value_len);
1158	} else {
1159		*auth_value_len = (unsigned32) output_token.length;
1160		*auth_len_remain = 0;
1161
1162		memcpy((unsigned_char_p_t)auth_value,
1163		       output_token.value,
1164		       output_token.length);
1165
1166		gss_release_buffer(&min_stat, &output_token);
1167	}
1168
1169	*st = rpc_s_ok;
1170}
1171
1172/*****************************************************************************/
1173/*
1174**++
1175**
1176**  ROUTINE NAME:       rpc__gssauth_cn_fmt_srvr_resp
1177**
1178**  SCOPE:              INTERNAL - declared locally
1179**
1180**  DESCRIPTION:
1181**
1182**      This routine will format the auth_value field of
1183**      either an rpc_bind_ack or rpc_alter_context_response
1184**      PDU. The authentication protocol encoding in the
1185**      credentials field of auth_value should correspond
1186**      to the status returned from rpc__auth_cn_vfy_
1187**      client_req()  routine. This credentials field, when
1188**      decoded by rpc__auth_cn_vfy_srvr_resp(),  should
1189**      result in the same error code being returned. If the
1190**      memory provided is not large enough an authentication
1191**      protocol specific error message will be encoded in
1192**      the credentials field indicating this error. This is
1193**      called from the server side association state machine.
1194**
1195**  INPUTS:
1196**
1197**      verify_st       The status code returned by rpc__auth_cn_verify_
1198**                      client_req().
1199**      assoc_sec       A pointer to per-association security context
1200**                      including association UUID CRC and sequence numbers.
1201**      sec             A pointer to security context element which includes
1202**                      the key ID, auth information rep and RPC auth
1203**                      information rep.
1204**      req_auth_value  A pointer to the auth_value field in the
1205**                      rpc_bind or rpc_alter_context PDU authentication trailer.
1206**      req_auth_value_len The length, in bytes, of the
1207**                      req_auth_value field.
1208**      auth_value      A pointer to the auth_value field in the rpc_bind or
1209**                      rpc_alter_context PDU authentication trailer.
1210**
1211**  INPUTS/OUTPUTS:
1212**
1213**      auth_value_len  On input, the length, in bytes of the available space
1214**                      for the auth_value field. On output, the length in
1215**                      bytes used in encoding the auth_value field. Zero if
1216**                      an error status is returned.
1217**
1218**  OUTPUTS:            none
1219**
1220**  IMPLICIT INPUTS:    none
1221**
1222**  IMPLICIT OUTPUTS:   none
1223**
1224**  FUNCTION VALUE:     none
1225**
1226**  SIDE EFFECTS:       none
1227**
1228**--
1229**/
1230
1231INTERNAL void rpc__gssauth_cn_fmt_srvr_resp
1232(
1233	unsigned32			verify_st,
1234	rpc_cn_assoc_sec_context_p_t    assoc_sec,
1235	rpc_cn_sec_context_p_t		sec,
1236	dce_pointer_t			req_auth_value ATTRIBUTE_UNUSED /*TODO*/,
1237	unsigned32			req_auth_value_len ATTRIBUTE_UNUSED /*TODO*/,
1238	dce_pointer_t			auth_value,
1239	unsigned32			*auth_value_len
1240)
1241{
1242	OM_uint32 min_stat;
1243	gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
1244
1245	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
1246		("(rpc__gssauth_cn_fmt_srvr_resp)\n"));
1247
1248	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT,
1249		("(rpc__gssauth_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",
1250		sec->sec_info->authn_protocol,
1251		sec->sec_info->authn_level,
1252		sec->sec_key_id,
1253		assoc_sec->assoc_uuid_crc,
1254		assoc_sec->assoc_next_snd_seq,
1255		assoc_sec->assoc_next_rcv_seq,
1256		verify_st));
1257
1258#if 0
1259	if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_FMT_SERVER_RESP)) {
1260		verify_st = RPC_S_CN_DBG_AUTH_FAILURE;
1261	}
1262#endif
1263
1264	/*
1265	 * transfer the output of rpc__gssauth_cn_vfy_client_req()
1266	 */
1267	output_token.length = assoc_sec->krb_message.length;
1268	output_token.value = assoc_sec->krb_message.data;
1269	assoc_sec->krb_message.length = 0;
1270	assoc_sec->krb_message.data = NULL;
1271
1272	if (*auth_value_len < output_token.length) {
1273		gss_release_buffer(&min_stat, &output_token);
1274		*auth_value_len = 0;
1275		return;
1276	}
1277
1278	*auth_value_len = (unsigned32) output_token.length;
1279
1280	memcpy((unsigned_char_p_t)auth_value,
1281	       output_token.value,
1282	       output_token.length);
1283
1284	gss_release_buffer(&min_stat, &output_token);
1285}
1286
1287/*****************************************************************************/
1288/*
1289**++
1290**
1291**  ROUTINE NAME:       rpc__gssauth_cn_free_prot_info
1292**
1293**  SCOPE:              INTERNAL - declared locally
1294**
1295**  DESCRIPTION:
1296**
1297**      This routine will free an NCA Connection RPC auth
1298**      information rep.
1299**
1300**  INPUTS:
1301**
1302**      info            A pointer to the auth information rep structure
1303**                      containing RPC protocol indenpendent information.
1304**
1305**  INPUTS/OUTPUTS:
1306**
1307**      cn_info         A pointer to the RPC auth information rep structure
1308**                      containing NCA Connection specific
1309**                      information. NULL on output.
1310**
1311**  OUTPUTS:            none
1312**
1313**  IMPLICIT INPUTS:    none
1314**
1315**  IMPLICIT OUTPUTS:   none
1316**
1317**  FUNCTION VALUE:     none
1318**
1319**  SIDE EFFECTS:       none
1320**
1321**--
1322**/
1323
1324INTERNAL void rpc__gssauth_cn_free_prot_info
1325(
1326	rpc_auth_info_p_t	info,
1327	rpc_cn_auth_info_p_t	*cn_info
1328)
1329{
1330	rpc_gssauth_cn_info_p_t gssauth_cn_info = (rpc_gssauth_cn_info_p_t)*cn_info;
1331	OM_uint32 min_stat;
1332
1333	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
1334		("(rpc__gssauth_cn_free_prot_info)\n"));
1335
1336	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT,
1337		("(rpc__gssauth_cn_free_prot_info) prot->%x level->%x \n",
1338		info->authn_protocol,
1339		info->authn_level));
1340
1341	if (gssauth_cn_info->gss_ctx != GSS_C_NO_CONTEXT) {
1342		gss_delete_sec_context(&min_stat,
1343				       &gssauth_cn_info->gss_ctx,
1344				       GSS_C_NO_BUFFER);
1345		gssauth_cn_info->gss_ctx = GSS_C_NO_CONTEXT;
1346	}
1347
1348#ifdef DEBUG
1349	memset (gssauth_cn_info, 0, sizeof (rpc_gssauth_cn_info_p_t));
1350#endif
1351
1352	RPC_MEM_FREE (gssauth_cn_info, RPC_C_MEM_GSSAUTH_CN_INFO);
1353	*cn_info = NULL;
1354}
1355
1356/*****************************************************************************/
1357/*
1358**++
1359**
1360**  ROUTINE NAME:       rpc__gssauth_cn_get_prot_info
1361**
1362**  SCOPE:              INTERNAL - declared locally
1363**
1364**  DESCRIPTION:
1365**
1366**      This routine will create and return an NCA Connection
1367**      RPC auth information rep.
1368**
1369**  INPUTS:
1370**
1371**      info            A pointer to the auth information rep structure
1372**                      containing RPC protocol indenpendent information.
1373**
1374**  INPUTS/OUTPUTS:     none
1375**
1376**  OUTPUTS:
1377**
1378**      cn_info         A pointer to the RPC auth information rep structure
1379**                      containing NCA Connection specific information.
1380**      st              The return status of this routine.
1381**
1382**  IMPLICIT INPUTS:    none
1383**
1384**  IMPLICIT OUTPUTS:   none
1385**
1386**  FUNCTION VALUE:     none
1387**
1388**  SIDE EFFECTS:       none
1389**
1390**--
1391**/
1392
1393INTERNAL void rpc__gssauth_cn_get_prot_info
1394(
1395	rpc_auth_info_p_t		info,
1396	rpc_cn_auth_info_p_t		*cn_info,
1397	unsigned32			*st
1398)
1399{
1400        rpc_gssauth_cn_info_t   *gssauth_cn_info = NULL;
1401	rpc_gssauth_info_t      *gssauth_info = (rpc_gssauth_info_p_t)info;
1402
1403	CODING_ERROR(st);
1404	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
1405		("(rpc__gssauth_cn_get_prot_info)\n"));
1406
1407	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT,
1408		("(rpc__gssauth_cn_get_prot_info) prot->%x level->%x \n",
1409		info->authn_protocol,
1410		info->authn_level));
1411
1412#ifdef DEBUG
1413	if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_GET_PROT_INFO)) {
1414		*st = RPC_S_CN_DBG_AUTH_FAILURE;
1415		return;
1416	}
1417#endif
1418
1419	/*
1420	 * Allocate storage for a gssauth cn info structure from heap.
1421	 */
1422	RPC_MEM_ALLOC(gssauth_cn_info,
1423		      rpc_gssauth_cn_info_p_t,
1424		      sizeof (rpc_gssauth_cn_info_t),
1425		      RPC_C_MEM_GSSAUTH_CN_INFO,
1426		      RPC_C_MEM_WAITOK);
1427
1428	/*
1429	 * Initialize it.
1430	 */
1431	memset (gssauth_cn_info, 0, sizeof(rpc_gssauth_cn_info_t));
1432
1433	/*
1434	 * Set pointer to connection specific auth info if we're
1435	 * on the server side.
1436	 */
1437	if (info->is_server) {
1438		gssauth_info->cn_info = gssauth_cn_info;
1439	}
1440
1441	*cn_info = &gssauth_cn_info->cn_info;
1442	*st = rpc_s_ok;
1443}
1444
1445/*****************************************************************************/
1446/*
1447**++
1448**
1449**  ROUTINE NAME:       rpc__gssauth_cn_pre_call
1450**
1451**  SCOPE:              INTERNAL - declared locally
1452**
1453**  DESCRIPTION:
1454**
1455**      This routine will format the auth_value field of
1456**      a call level PDU, namely an rpc_request, rpc_response
1457**      rpc_fault, rpc_remote_alert or rpc_orphaned PDU. It will
1458**      also format the auth_value field of the association level
1459**      rpc_shutdown PDU. This does
1460**      not include generating any checksums in the auth_value_field
1461**      or encrypting of data corresponding to the authentication
1462**      level. That will be done in the rpc__cn_auth_pre_send
1463**      routine. This is called on both client and server when a the
1464**      data structures and header template for a call is being set up.
1465**
1466**  INPUTS:
1467**
1468**      assoc_sec       A pointer to per-association security context
1469**                      including association UUID CRC and sequence numbers.
1470**      sec             A pointer to security context element which includes
1471**                      the key ID, auth information rep and RPC auth
1472**                      information rep.
1473**      auth_value      A pointer to the auth_value field in the rpc_bind or
1474**                      rpc_alter_context PDU authentication trailer.
1475**
1476**  INPUTS/OUTPUTS:
1477**
1478**      auth_value_len  On input, the lenght, in bytes of the available space
1479**                      for the auth_value field. On output, the lenght in
1480**                      bytes used in encoding the auth_value field. Zero if
1481**                      an error status is returned.
1482**
1483**  OUTPUTS:
1484**
1485**      st              The return status of this routine.
1486**
1487**  IMPLICIT INPUTS:    none
1488**
1489**  IMPLICIT OUTPUTS:   none
1490**
1491**  FUNCTION VALUE:     none
1492**
1493**  SIDE EFFECTS:       none
1494**
1495**--
1496**/
1497
1498INTERNAL void rpc__gssauth_cn_pre_call
1499(
1500	rpc_cn_assoc_sec_context_p_t	assoc_sec,
1501	rpc_cn_sec_context_p_t		sec,
1502	dce_pointer_t			auth_value,
1503	unsigned32			*auth_value_len,
1504	unsigned32			*st
1505)
1506{
1507	rpc_gssauth_cn_info_p_t gssauth_cn_info = (rpc_gssauth_cn_info_p_t)sec->sec_cn_info;
1508	OM_uint32 maj_stat;
1509	OM_uint32 min_stat;
1510	gss_iov_buffer_desc iov[2];
1511	int conf_req_flag = 0;
1512
1513	CODING_ERROR(st);
1514
1515	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
1516		("(rpc__gssauth_cn_pre_call)\n"));
1517
1518	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT,
1519		("(rpc__gssauth_cn_pre_call) prot->%x level->%x key_id->%x assoc_uuid_crc->%x xmit_seq->%x recv_seq->%x\n",
1520		sec->sec_info->authn_protocol,
1521		sec->sec_info->authn_level,
1522		sec->sec_key_id,
1523		assoc_sec->assoc_uuid_crc,
1524		assoc_sec->assoc_next_snd_seq,
1525		assoc_sec->assoc_next_rcv_seq));
1526
1527#ifdef DEBUG
1528	if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_PRE_CALL)) {
1529		*st = RPC_S_CN_DBG_AUTH_FAILURE;
1530		return;
1531	}
1532#endif
1533
1534	if (gssauth_cn_info->gss_stat != GSS_S_COMPLETE) {
1535		/* Can only do this on a completed context */
1536		*st = rpc_s_ok;
1537		return;
1538	}
1539
1540	switch (sec->sec_info->authn_level) {
1541	case rpc_c_protect_level_pkt_privacy:
1542		conf_req_flag = 1;
1543		/* fallthrough */
1544	case rpc_c_protect_level_pkt_integ:
1545		iov[0].type = GSS_IOV_BUFFER_TYPE_DATA;
1546		iov[0].buffer.length = RPC__GSSAUTH_CN_AUTH_PADDING;
1547
1548		iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER;
1549		iov[1].buffer.length = 0;
1550
1551		/*
1552		 * XXX needs to report correct Get_MIC token size too
1553		 * Correctness of this relies on MIC tokens always being
1554		 * equal to or smaller than wrap tokens.
1555		 */
1556		maj_stat = gss_wrap_iov_length(&min_stat,
1557					       gssauth_cn_info->gss_ctx,
1558					       conf_req_flag,
1559					       GSS_C_QOP_DEFAULT,
1560					       NULL, /* conf_state */
1561					       iov,
1562					       sizeof(iov)/sizeof(iov[0]));
1563		if (maj_stat != GSS_S_COMPLETE) {
1564			*st = rpc_s_auth_method;
1565			return;
1566		}
1567		*auth_value_len = (unsigned32) iov[1].buffer.length;
1568		memset((unsigned_char_p_t)auth_value, 0xAF, *auth_value_len);
1569		break;
1570	case rpc_c_authn_level_connect:
1571	default:
1572		*auth_value_len = 0;
1573		break;
1574	}
1575
1576	*st = rpc_s_ok;
1577}
1578
1579INTERNAL void rpc__gssauth_cn_wrap_packet
1580(
1581	rpc_cn_sec_context_p_t		sec,
1582	const char			*comment,
1583	unsigned8			header_size,
1584	rpc_socket_iovec_p_t		iov,
1585	unsigned32			iovlen,
1586	boolean                         conf_req_flag,
1587	rpc_socket_iovec_p_t		out_iov,
1588	unsigned32			*st
1589)
1590{
1591	rpc_gssauth_cn_info_p_t gssauth_cn_info = (rpc_gssauth_cn_info_p_t)sec->sec_cn_info;
1592	rpc_cn_common_hdr_p_t pdu;
1593	rpc_cn_auth_tlr_p_t auth_tlr;
1594	unsigned32 i;
1595	unsigned8 pad_len;
1596	OM_uint32 maj_stat;
1597	OM_uint32 min_stat;
1598	int conf_state;
1599	gss_iov_buffer_desc gss_iov[4];
1600	unsigned_char_p_t pdu_buf;
1601	size_t pdu_buflen, payload_len;
1602	boolean header_sign = gssauth_cn_info->header_sign;
1603
1604	CODING_ERROR(st);
1605	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
1606		("(rpc__gssauth_cn_wrap_packet)\n"));
1607
1608	if (iovlen < 2) {
1609		RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
1610			("(rpc__gssauth_cn_wrap_packet): %s: iovlen[%u]\n",
1611			comment, (unsigned int)iovlen));
1612		*st = rpc_m_no_stub_data;
1613		return;
1614	}
1615	if (iov[0].iov_len < header_size) {
1616		RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
1617			("(rpc__gssauth_cn_wrap_packet): %s: iov[0].iov_len[%u] < header_size[%u]\n",
1618			comment, (unsigned int)iov[0].iov_len,(unsigned int)header_size));
1619		*st = rpc_m_no_stub_data;
1620		return;
1621	}
1622	if (iov[iovlen - 1].iov_len < RPC_CN_PKT_SIZEOF_COM_AUTH_TLR) {
1623		RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
1624			("(rpc__gssauth_cn_wrap_packet): %s: iov[%u].iov_len[%u] != %u\n",
1625			comment,(unsigned int)iovlen - 1,
1626			(unsigned int)iov[iovlen - 1].iov_len,
1627			RPC_CN_PKT_SIZEOF_COM_AUTH_TLR));
1628		*st = rpc_s_auth_field_toolong;
1629		return;
1630	}
1631
1632	for (i = 0, payload_len = 0; i < iovlen - 1; i++) {
1633		payload_len += iov[i].iov_len;
1634	}
1635
1636	/*
1637	 * [MS-RPCE] states that the stub data is padded to the underlying
1638	 * blocksize (or four bytes, if that is greater). In practice they
1639	 * use the underlying keysize when the blocksize is one. For now,
1640	 * a constant 16 bytes works for all known ciphers and mechanisms
1641	 * (at the expense of 8 bytes extra padding for DES), but we should
1642	 * eventually fix it to use gss_context_query_attributes().
1643	 */
1644	payload_len -= header_size;
1645	pad_len = RPC__GSSAUTH_CN_AUTH_PADDING -
1646		  (payload_len % RPC__GSSAUTH_CN_AUTH_PADDING);
1647	if (pad_len == RPC__GSSAUTH_CN_AUTH_PADDING)
1648		pad_len = 0;
1649
1650	pdu_buflen = header_size + payload_len + pad_len + iov[iovlen - 1].iov_len;
1651
1652	RPC_MEM_ALLOC(pdu_buf,
1653		      unsigned_char_p_t,
1654		      pdu_buflen,
1655		      RPC_C_MEM_CN_ENCRYPT_BUF,
1656		      RPC_C_MEM_WAITOK);
1657	memset(pdu_buf, 0xAF, pdu_buflen);
1658
1659	pdu = (rpc_cn_common_hdr_p_t)pdu_buf;
1660
1661	for (i = 0, pdu_buflen = 0; i < iovlen - 1; i++) {
1662		memcpy(&pdu_buf[pdu_buflen],
1663		       iov[i].iov_base,
1664		       iov[i].iov_len);
1665		pdu_buflen += iov[i].iov_len;
1666	}
1667
1668	memset(&pdu_buf[pdu_buflen], 0, pad_len);
1669
1670	gss_iov[0].type = header_sign ? GSS_IOV_BUFFER_TYPE_SIGN_ONLY :
1671					GSS_IOV_BUFFER_TYPE_EMPTY;
1672	gss_iov[0].buffer.value = pdu_buf;
1673	gss_iov[0].buffer.length = header_size;
1674
1675	gss_iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
1676	gss_iov[1].buffer.value = (unsigned_char_p_t)gss_iov[0].buffer.value +
1677				  gss_iov[0].buffer.length;
1678	gss_iov[1].buffer.length = payload_len + pad_len;
1679
1680	gss_iov[2].type = header_sign ? GSS_IOV_BUFFER_TYPE_SIGN_ONLY :
1681					GSS_IOV_BUFFER_TYPE_EMPTY;
1682	gss_iov[2].buffer.value = (unsigned_char_p_t)gss_iov[1].buffer.value +
1683				  gss_iov[1].buffer.length;
1684	gss_iov[2].buffer.length = RPC_CN_PKT_SIZEOF_COM_AUTH_TLR;
1685
1686	/*
1687	 * The auth trailer may have moved relative to the start of the PDU
1688	 * owing to any additional padding. Really, we should be able to allocate
1689	 * just a padding [out] IOV and do the rest in place. This would require
1690	 * some rejigging of the auth provider interface.
1691	 */
1692	memcpy(gss_iov[2].buffer.value, iov[iovlen - 1].iov_base, gss_iov[2].buffer.length);
1693
1694	auth_tlr = (rpc_cn_auth_tlr_p_t)gss_iov[2].buffer.value;
1695	auth_tlr->stub_pad_length = pad_len;
1696
1697	gss_iov[3].type = GSS_IOV_BUFFER_TYPE_HEADER;
1698	gss_iov[3].buffer.value = (unsigned_char_p_t)gss_iov[2].buffer.value +
1699				  gss_iov[2].buffer.length;
1700	gss_iov[3].buffer.length = iov[iovlen - 1].iov_len - RPC_CN_PKT_SIZEOF_COM_AUTH_TLR;
1701
1702	pdu->frag_len        = gss_iov[0].buffer.length +
1703			       gss_iov[1].buffer.length +
1704			       gss_iov[2].buffer.length +
1705			       gss_iov[3].buffer.length;
1706
1707	pdu->auth_len        = gss_iov[3].buffer.length;
1708
1709	if (conf_req_flag) {
1710		maj_stat = gss_wrap_iov(&min_stat,
1711					gssauth_cn_info->gss_ctx,
1712					conf_req_flag,
1713					GSS_C_QOP_DEFAULT,
1714					&conf_state,
1715					gss_iov,
1716					sizeof(gss_iov)/sizeof(gss_iov[0]));
1717		if (maj_stat != GSS_S_COMPLETE)
1718			goto cleanup;
1719	} else {
1720		gss_buffer_desc input_token;
1721		gss_buffer_desc mic_token;
1722
1723		conf_state = 0;
1724
1725		if (header_sign) {
1726			input_token = gss_iov[0].buffer;
1727			input_token.length += gss_iov[1].buffer.length + gss_iov[2].buffer.length;
1728		} else {
1729			input_token = gss_iov[1].buffer;
1730		}
1731
1732		maj_stat = gss_get_mic(&min_stat,
1733				       gssauth_cn_info->gss_ctx,
1734				       GSS_C_QOP_DEFAULT,
1735				       &input_token,
1736				       &mic_token);
1737		if (maj_stat != GSS_S_COMPLETE)
1738			goto cleanup;
1739
1740		assert(mic_token.length <= gss_iov[3].buffer.length);
1741		memcpy(gss_iov[3].buffer.value, mic_token.value, mic_token.length);
1742		gss_iov[3].buffer.length = mic_token.length;
1743		gss_release_buffer(&min_stat, &mic_token);
1744	}
1745
1746	if (conf_req_flag != conf_state) {
1747		RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
1748			("(rpc__gssauth_cn_wrap_packet): %s: conf_req[%u] != conf_state[%u]\n",
1749			comment, (unsigned int)conf_req_flag, (unsigned int)conf_state));
1750		*st = rpc_s_auth_method;
1751		goto cleanup;
1752	}
1753
1754	out_iov->iov_base = pdu_buf;
1755	out_iov->iov_len  = pdu->frag_len;
1756
1757	*st = rpc_s_ok;
1758
1759cleanup:
1760	if (maj_stat != GSS_S_COMPLETE) {
1761		char msg[BUFSIZ];
1762		rpc__gssauth_error_map(maj_stat, min_stat,
1763				       gssauth_cn_info->gss_mech,
1764				       msg, sizeof(msg), st);
1765		RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
1766			("(rpc__gssauth_cn_wrap_packet): %s: %s\n", comment, msg));
1767	}
1768
1769	return;
1770}
1771
1772INTERNAL void rpc__gssauth_cn_create_large_frag
1773(
1774	rpc_cn_assoc_sec_context_p_t	assoc_sec,
1775	const char			*comment,
1776	unsigned8			header_size,
1777	rpc_socket_iovec_p_t		iov,
1778	unsigned32			iovlen,
1779	rpc_socket_iovec_p_t		out_iov,
1780	unsigned32			*st
1781)
1782{
1783	rpc_cn_common_hdr_p_t pdu;
1784	unsigned32 i;
1785	unsigned32 pdu_buflen;
1786	unsigned_char_p_t pdu_buf, pdu_bufp;
1787	OM_uint32 min_stat;
1788	gss_buffer_desc output_token;
1789
1790	CODING_ERROR(st);
1791	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
1792		("(rpc__gssauth_cn_create_large_frag)\n"));
1793
1794	output_token.length = assoc_sec->krb_message.length;
1795	output_token.value = assoc_sec->krb_message.data;
1796	assoc_sec->krb_message.length = 0;
1797	assoc_sec->krb_message.data = NULL;
1798
1799	if (iovlen < 1) {
1800		RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
1801			("(rpc__gssauth_cn_create_large_frag): %s: iovlen[%u]\n",
1802			comment, (unsigned int)iovlen));
1803		gss_release_buffer(&min_stat, &output_token);
1804		*st = rpc_m_no_stub_data;
1805		return;
1806	}
1807	if (iov[0].iov_len < header_size) {
1808		RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
1809			("(rpc__gssauth_cn_create_large_frag): %s: iov[0].iov_len[%u] < header_size[%u]\n",
1810			comment, (unsigned int)iov[0].iov_len,(unsigned int)header_size));
1811		gss_release_buffer(&min_stat, &output_token);
1812		*st = rpc_m_no_stub_data;
1813		return;
1814	}
1815
1816	for (i = 0, pdu_buflen = 0; i < iovlen; i++) {
1817		pdu_buflen += iov[i].iov_len;
1818	}
1819
1820	if (pdu_buflen < header_size + RPC_CN_PKT_SIZEOF_COM_AUTH_TLR + output_token.length) {
1821		RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
1822			("(rpc__gssauth_cn_create_large_frag): %s: pdu_buflen[%u] < min_len[%u]\n",
1823			comment, (unsigned int)pdu_buflen,
1824			(unsigned int)header_size +
1825			RPC_CN_PKT_SIZEOF_COM_AUTH_TLR + (unsigned int)output_token.length));
1826		gss_release_buffer(&min_stat, &output_token);
1827		*st = rpc_m_no_stub_data;
1828		return;
1829	}
1830
1831	pdu_buflen += output_token.length;
1832
1833	RPC_MEM_ALLOC(pdu_buf,
1834		      unsigned_char_p_t,
1835		      pdu_buflen,
1836		      RPC_C_MEM_CN_ENCRYPT_BUF,
1837		      RPC_C_MEM_WAITOK);
1838
1839	pdu_bufp = pdu_buf;
1840	pdu = (rpc_cn_common_hdr_p_t)pdu_bufp;
1841	for (i = 0; i < iovlen; i++) {
1842		memcpy(pdu_bufp, iov[i].iov_base, iov[i].iov_len);
1843		pdu_bufp += iov[i].iov_len;
1844	}
1845
1846	memcpy(pdu_bufp, output_token.value, output_token.length);
1847	pdu_bufp += output_token.length;
1848
1849	pdu->frag_len = (pdu_bufp - pdu_buf);
1850	pdu->auth_len = output_token.length;
1851
1852	out_iov->iov_base = pdu_buf;
1853	out_iov->iov_len = pdu_buflen;
1854
1855	assert(out_iov->iov_len == pdu->frag_len);
1856
1857	gss_release_buffer(&min_stat, &output_token);
1858
1859	*st = rpc_s_ok;
1860}
1861
1862/*****************************************************************************/
1863/*
1864**++
1865**
1866**  ROUTINE NAME:       rpc__gssauth_cn_pre_send
1867**
1868**  SCOPE:              INTERNAL - declared locally
1869**
1870**  DESCRIPTION:
1871**
1872**      This routine will perform per-packet security
1873**      processing on a packet before it is sent. This
1874**      includes checksumming and encryption.
1875**
1876**      Note that in some cases, the data is copied to
1877**      a contiguous buffer for checksumming and
1878**      encryption.  In these cases, the contiguous
1879**      iov element should be used instead of the original
1880**      iovector.
1881**
1882**  INPUTS:
1883**
1884**      assoc_sec       A pointer to per-association security context
1885**                      including association UUID CRC and sequence numbers.
1886**      sec             A pointer to security context element which includes
1887**                      the key ID, auth information rep and RPC auth
1888**                      information rep.
1889**      iov             A pointer to the iovector containing the PDU
1890**                      about to be sent. The appropriate per-packet security
1891**                      services will be applied to it.
1892**      iovlen          The length, in bytes, of the PDU.
1893**      out_iov         An iovector element.  This iovector element
1894**                      will describe packet if the original iov
1895**                      had to be copied.  If the original iov was
1896**                      copied, out_iov->iov_base will be non-NULL.
1897**
1898**  INPUTS/OUTPUTS:     none
1899**
1900**  OUTPUTS:
1901**
1902**      st              The return status of this routine.
1903**
1904**  IMPLICIT INPUTS:    none
1905**
1906**  IMPLICIT OUTPUTS:   none
1907**
1908**  FUNCTION VALUE:     none
1909**
1910**  SIDE EFFECTS:       none
1911**
1912**--
1913**/
1914
1915INTERNAL void rpc__gssauth_cn_pre_send
1916(
1917	rpc_cn_assoc_sec_context_p_t	assoc_sec,
1918	rpc_cn_sec_context_p_t		sec,
1919	rpc_socket_iovec_p_t		iov,
1920	unsigned32			iovlen,
1921	rpc_socket_iovec_p_t		out_iov,
1922	unsigned32			*st
1923)
1924{
1925	rpc_gssauth_cn_info_p_t gssauth_cn_info = (rpc_gssauth_cn_info_p_t)sec->sec_cn_info;
1926	rpc_cn_common_hdr_p_t pdu;
1927	rpc_cn_packet_p_t pkt;
1928	unsigned32 ptype;
1929	boolean conf_req_flag = false;
1930	OM_uint32 min_stat;
1931
1932	CODING_ERROR(st);
1933	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
1934		("(rpc__gssauth_cn_pre_send)\n"));
1935
1936	pdu = (rpc_cn_common_hdr_p_t)iov[0].iov_base;
1937	pkt = (rpc_cn_packet_p_t)pdu;
1938	ptype = pdu->ptype;
1939	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
1940		("(rpc__gssauth_cn_pre_send) authn level->%x packet type->%x\n",
1941		sec->sec_info->authn_level, ptype));
1942
1943	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT,
1944		("(rpc__gssauth_cn_pre_send) prot->%x level->%x key_id->%x assoc_uuid_crc->%x xmit_seq->%x recv_seq->%x ptype->%x\n",
1945		sec->sec_info->authn_protocol,
1946		sec->sec_info->authn_level,
1947		sec->sec_key_id,
1948		assoc_sec->assoc_uuid_crc,
1949		assoc_sec->assoc_next_snd_seq,
1950		assoc_sec->assoc_next_rcv_seq,
1951		ptype));
1952
1953#ifdef DEBUG
1954	if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_PRE_SEND)) {
1955		*st = RPC_S_CN_DBG_AUTH_FAILURE;
1956		return;
1957	}
1958#endif
1959
1960	out_iov->iov_base = NULL;
1961
1962	switch (ptype) {
1963	case RPC_C_CN_PKT_REQUEST:
1964	case RPC_C_CN_PKT_RESPONSE:
1965		switch (sec->sec_info->authn_level) {
1966		case rpc_c_authn_level_connect:
1967			*st = rpc_s_ok;
1968			break;
1969		case rpc_c_authn_level_pkt_privacy:
1970			conf_req_flag = true;
1971			/* fallthrough */
1972		case rpc_c_authn_level_pkt_integrity:
1973			rpc__gssauth_cn_wrap_packet(sec,
1974				ptype == RPC_C_CN_PKT_REQUEST ? "request" : "response",
1975				ptype == RPC_C_CN_PKT_REQUEST ? RPC_CN_PKT_SIZEOF_RQST_HDR :
1976								RPC_CN_PKT_SIZEOF_RESP_HDR,
1977				iov, iovlen, conf_req_flag, out_iov, st);
1978			break;
1979		default:
1980			break;
1981		}
1982		break;
1983	case RPC_C_CN_PKT_BIND:
1984	case RPC_C_CN_PKT_ALTER_CONTEXT:
1985		if (!getenv("DCE_DISABLE_HEADER_SIGN")) {
1986			RPC_CN_PKT_FLAGS(pkt) |= RPC_C_CN_FLAGS_SUPPORT_HEADER_SIGN;
1987		}
1988		if (assoc_sec->krb_message.length == 0) {
1989			*st = rpc_s_ok;
1990		} else {
1991			rpc__gssauth_cn_create_large_frag(assoc_sec,
1992				(ptype == RPC_C_CN_PKT_BIND) ? "bind" : "alter_context",
1993				RPC_CN_PKT_SIZEOF_BIND_HDR,
1994				iov, iovlen, out_iov, st);
1995		}
1996		break;
1997	case RPC_C_CN_PKT_BIND_ACK:
1998	case RPC_C_CN_PKT_BIND_NAK:
1999	case RPC_C_CN_PKT_ALTER_CONTEXT_RESP:
2000		if (gssauth_cn_info->header_sign)
2001			RPC_CN_PKT_FLAGS(pkt) |= RPC_C_CN_FLAGS_SUPPORT_HEADER_SIGN;
2002		break;
2003	case RPC_C_CN_PKT_AUTH3: {
2004		gss_buffer_desc input_token, output_token;
2005		rpc_cn_auth_tlr_p_t auth_tlr;
2006
2007		if (sec->sec_info->is_server)
2008			break;
2009
2010		assert(iovlen == 1);
2011
2012		auth_tlr = RPC_CN_PKT_AUTH_TLR(pkt, iov[0].iov_len);
2013		input_token.value = auth_tlr->auth_value;
2014		input_token.length = RPC_CN_PKT_AUTH_LEN(pkt);
2015
2016		(void) rpc__gssauth_verify_server_token(&min_stat,
2017							    sec,
2018							    GSS_C_NO_CREDENTIAL,
2019							    GSS_C_NO_NAME,
2020							    gssauth_cn_info->gss_ctx,
2021							    input_token,
2022							    &gssauth_cn_info->gss_mech,
2023							    &output_token);
2024		if (output_token.length) {
2025			*st = rpc_s_credentials_too_large;
2026			gss_release_buffer(&min_stat, &output_token);
2027			return;
2028		}
2029		break;
2030	}
2031	case RPC_C_CN_PKT_FAULT:
2032	case RPC_C_CN_PKT_SHUTDOWN:
2033	case RPC_C_CN_PKT_REMOTE_ALERT:
2034	case RPC_C_CN_PKT_ORPHANED:
2035	default:
2036		break;
2037	}
2038}
2039
2040INTERNAL void rpc__gssauth_cn_unwrap_packet
2041(
2042	rpc_cn_sec_context_p_t		sec,
2043	const char			*comment,
2044	unsigned8			header_size,
2045	rpc_cn_common_hdr_p_t		pdu,
2046	unsigned32			pdu_len,
2047	unsigned32			cred_len ATTRIBUTE_UNUSED,
2048	rpc_cn_auth_tlr_p_t		auth_tlr,
2049	boolean                         conf_req_flag,
2050	boolean32			unpack_ints,
2051	unsigned32			*st
2052)
2053{
2054	rpc_gssauth_cn_info_p_t gssauth_cn_info = (rpc_gssauth_cn_info_p_t)sec->sec_cn_info;
2055	OM_uint32 maj_stat;
2056	OM_uint32 min_stat;
2057	int conf_state;
2058	gss_qop_t qop_state;
2059	unsigned16 auth_len;
2060	gss_iov_buffer_desc gss_iov[4];
2061	boolean header_sign = gssauth_cn_info->header_sign;
2062
2063	CODING_ERROR(st);
2064	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
2065		("(rpc__gssauth_cn_unwrap_packet)\n"));
2066
2067	auth_len = pdu->auth_len;
2068	if (unpack_ints) {
2069		SWAB_INPLACE_16(auth_len);
2070	}
2071
2072	gss_iov[0].type = header_sign ? GSS_IOV_BUFFER_TYPE_SIGN_ONLY :
2073					GSS_IOV_BUFFER_TYPE_EMPTY;
2074	gss_iov[0].buffer.value = (unsigned_char_p_t)pdu;
2075	gss_iov[0].buffer.length = header_size;
2076
2077	gss_iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
2078	gss_iov[1].buffer.value = (unsigned_char_p_t)pdu + header_size;
2079	gss_iov[1].buffer.length = pdu_len -
2080		(header_size + RPC_CN_PKT_SIZEOF_COM_AUTH_TLR + auth_len);
2081
2082	gss_iov[2].type = header_sign ? GSS_IOV_BUFFER_TYPE_SIGN_ONLY :
2083					GSS_IOV_BUFFER_TYPE_EMPTY;
2084	gss_iov[2].buffer.value = auth_tlr;
2085	gss_iov[2].buffer.length = RPC_CN_PKT_SIZEOF_COM_AUTH_TLR;
2086
2087	gss_iov[3].type = GSS_IOV_BUFFER_TYPE_HEADER;
2088	gss_iov[3].buffer.value = (unsigned_char_p_t)auth_tlr +
2089		RPC_CN_PKT_SIZEOF_COM_AUTH_TLR;
2090	gss_iov[3].buffer.length = auth_len;
2091
2092	if (conf_req_flag) {
2093		maj_stat = gss_unwrap_iov(&min_stat,
2094					  gssauth_cn_info->gss_ctx,
2095					  &conf_state,
2096					  &qop_state,
2097					  gss_iov,
2098					  sizeof(gss_iov)/sizeof(gss_iov[0]));
2099	} else {
2100		gss_buffer_desc input_token;
2101
2102		conf_state = 0;
2103
2104		if (header_sign) {
2105			input_token = gss_iov[0].buffer;
2106			input_token.length += gss_iov[1].buffer.length + gss_iov[2].buffer.length;
2107		} else {
2108			input_token = gss_iov[1].buffer;
2109		}
2110
2111		maj_stat = gss_verify_mic(&min_stat,
2112					  gssauth_cn_info->gss_ctx,
2113					  &input_token,
2114					  &gss_iov[3].buffer,
2115					  &qop_state);
2116	}
2117
2118	if (maj_stat != GSS_S_COMPLETE) {
2119		char msg[BUFSIZ];
2120		rpc__gssauth_error_map(maj_stat, min_stat,
2121				       gssauth_cn_info->gss_mech,
2122				       msg, sizeof(msg), st);
2123		RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
2124			("(rpc__gssauth_cn_unwrap_packet): %s: %s\n",
2125			comment, msg));
2126		/* *st is already filled */
2127	} else if (conf_state != conf_req_flag) {
2128		RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
2129			("(rpc__gssauth_cn_unwrap_packet): %s: packet privacy mismatch\n",
2130			comment));
2131		*st = rpc_s_auth_bad_integrity;
2132	} else {
2133		*st = rpc_s_ok;
2134	}
2135
2136	return;
2137}
2138
2139/*****************************************************************************/
2140/*
2141**++
2142**
2143**  ROUTINE NAME:       rpc__gssauth_cn_recv_check
2144**
2145**  SCOPE:              INTERNAL - declared locally
2146**
2147**  DESCRIPTION:
2148**
2149**      This routine will perform per-packet security
2150**      processing on a packet after it is received. This
2151**      includes decryption and verification of checksums.
2152**
2153**  INPUTS:
2154**
2155**      assoc_sec       A pointer to per-association security context
2156**                      including association UUID CRC and sequence numbers.
2157**      sec             A pointer to security context element which includes
2158**                      the key ID, auth information rep and RPC auth
2159**                      information rep.
2160**      pdu             A pointer to the PDU about to be sent. The appropriate
2161**                      per-packet security services will be applied to it.
2162**      pdu_len         The length, in bytes, of the PDU.
2163**      cred_len        The length, in bytes, of the credentials.
2164**      auth_tlr        A pointer to the auth trailer.
2165**      unpack_ints     A boolean indicating whether the integer rep
2166**                      of fields in the pdu need to be adjusted for
2167**                      endian differences.
2168**
2169**  INPUTS/OUTPUTS:     none
2170**
2171**  OUTPUTS:
2172**
2173**      st              The return status of this routine.
2174**
2175**  IMPLICIT INPUTS:    none
2176**
2177**  IMPLICIT OUTPUTS:   none
2178**
2179**  FUNCTION VALUE:     none
2180**
2181**  SIDE EFFECTS:       none
2182**
2183**--
2184**/
2185
2186INTERNAL void rpc__gssauth_cn_recv_check
2187(
2188	rpc_cn_assoc_sec_context_p_t    assoc_sec,
2189	rpc_cn_sec_context_p_t		sec,
2190	rpc_cn_common_hdr_p_t		pdu,
2191	unsigned32			pdu_len,
2192	unsigned32			cred_len,
2193	rpc_cn_auth_tlr_p_t		auth_tlr,
2194	boolean32			unpack_ints,
2195	unsigned32			*st
2196)
2197{
2198	rpc_gssauth_cn_info_p_t gssauth_cn_info = (rpc_gssauth_cn_info_p_t)sec->sec_cn_info;
2199	boolean conf_req_flag = false;
2200	rpc_cn_packet_p_t pkt = (rpc_cn_packet_p_t)pdu;
2201
2202	CODING_ERROR(st);
2203	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
2204		("(rpc__gssauth_cn_recv_check)\n"));
2205
2206	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
2207		("(rpc__gssauth_cn_recv_check) authn level->%x packet type->%x\n",
2208		sec->sec_info->authn_level,
2209		pdu->ptype));
2210
2211	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT,
2212		("(rpc__gssauth_cn_recv_check) prot->%x level->%x key_id->%x assoc_uuid_crc->%x xmit_seq->%x recv_seq->%x ptype->%x\n",
2213		sec->sec_info->authn_protocol,
2214		sec->sec_info->authn_level,
2215		sec->sec_key_id,
2216		assoc_sec->assoc_uuid_crc,
2217		assoc_sec->assoc_next_snd_seq,
2218		assoc_sec->assoc_next_rcv_seq,
2219		pdu->ptype));
2220
2221#ifdef DEBUG
2222	if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_RECV_CHECK)) {
2223		*st = RPC_S_CN_DBG_AUTH_FAILURE;
2224		return;
2225	}
2226#endif
2227
2228	switch (pdu->ptype) {
2229	case RPC_C_CN_PKT_REQUEST:
2230	case RPC_C_CN_PKT_RESPONSE:
2231		switch (sec->sec_info->authn_level) {
2232		case rpc_c_authn_level_connect:
2233			*st = rpc_s_ok;
2234			break;
2235		case rpc_c_authn_level_pkt_privacy:
2236			conf_req_flag = true;
2237			/* fallthrough */
2238		case rpc_c_authn_level_pkt_integrity:
2239			rpc__gssauth_cn_unwrap_packet(sec,
2240				(pdu->ptype == RPC_C_CN_PKT_REQUEST) ?  "request" : "response",
2241				(pdu->ptype == RPC_C_CN_PKT_REQUEST) ?  RPC_CN_PKT_SIZEOF_RQST_HDR : RPC_CN_PKT_SIZEOF_RESP_HDR,
2242				pdu, pdu_len, cred_len, auth_tlr, conf_req_flag,
2243				unpack_ints, st);
2244			break;
2245		}
2246		break;
2247	case RPC_C_CN_PKT_AUTH3:
2248	case RPC_C_CN_PKT_BIND:
2249	case RPC_C_CN_PKT_BIND_ACK:
2250	case RPC_C_CN_PKT_BIND_NAK:
2251	case RPC_C_CN_PKT_ALTER_CONTEXT:
2252	case RPC_C_CN_PKT_ALTER_CONTEXT_RESP:
2253		if (RPC_CN_PKT_FLAGS(pkt) & RPC_C_CN_FLAGS_SUPPORT_HEADER_SIGN)
2254			gssauth_cn_info->header_sign = true;
2255		/* fallthrough */
2256	case RPC_C_CN_PKT_SHUTDOWN:
2257	case RPC_C_CN_PKT_REMOTE_ALERT:
2258	case RPC_C_CN_PKT_ORPHANED:
2259	case RPC_C_CN_PKT_FAULT:
2260	default:
2261		*st = rpc_s_ok;
2262		break;
2263	}
2264}
2265
2266/*****************************************************************************/
2267/*
2268**++
2269**
2270**  ROUTINE NAME:       rpc__gssauth_cn_tlr_uuid_crc
2271**
2272**  SCOPE:              INTERNAL - declared locally
2273**
2274**  DESCRIPTION:
2275**
2276**      This routine will locate and return the association
2277**      UUID CRC contained in the auth_value field of an
2278**      authentication trailer of an rpc_bind, rpc_bind_ack,
2279**      rpc_alter_context or rpc_alter_context_response PDU.
2280**
2281**  INPUTS:
2282**
2283**      auth_value      A pointer to the auth_value field in an authentication
2284**                      trailer.
2285**      auth_value_len  The length, in bytes, of the auth_value field.
2286**
2287**  INPUTS/OUTPUTS:     none
2288**
2289**  OUTPUTS:
2290**
2291**      assoc_uuid_crc  The association UUID CRC contained in the auth_value
2292**                      field.
2293**
2294**  IMPLICIT INPUTS:    none
2295**
2296**  IMPLICIT OUTPUTS:   none
2297**
2298**  FUNCTION VALUE:     none
2299**
2300**  SIDE EFFECTS:       none
2301**
2302**--
2303**/
2304
2305INTERNAL void rpc__gssauth_cn_tlr_uuid_crc
2306(
2307	dce_pointer_t		auth_value ATTRIBUTE_UNUSED /*TODO*/,
2308	unsigned32		auth_value_len ATTRIBUTE_UNUSED /*TODO*/,
2309	unsigned32		*uuid_crc
2310)
2311{
2312	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
2313		("(rpc__gssauth_cn_tlr_uuid_crc)\n"));
2314
2315	*uuid_crc = 0;
2316
2317	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
2318		("(rpc__gssauth_cn_tlr_uuid_crc) assoc_uuid_crc->%x\n", *uuid_crc));
2319}
2320
2321/*****************************************************************************/
2322/*
2323**++
2324**
2325**  ROUTINE NAME:       rpc__gssauth_cn_tlr_unpack
2326**
2327**  SCOPE:              INTERNAL - declared locally
2328**
2329**  DESCRIPTION:
2330**
2331**      This routine will byte swap all the appropriate fields
2332**      of the the auth_value field of an authentication
2333**      trailer. It will also convert any characters from
2334**      the remote representation into the local, for example,
2335**      ASCII to EBCDIC.
2336**
2337**  INPUTS:
2338**
2339**      auth_value_len  The length, in bytes, of the auth_value field.
2340**      packed_drep     The packed Networ Data Representation, (see NCA RPC
2341**                      RunTime Extensions Specification Version OSF TX1.0.9
2342**                      pre 1003 for details), of the remote machine.
2343**
2344**  INPUTS/OUTPUTS:
2345**
2346**      pkt_p           A pointer to the entire packet.
2347**
2348**  OUTPUTS:            none
2349**
2350**  IMPLICIT INPUTS:    none
2351**
2352**  IMPLICIT OUTPUTS:   none
2353**
2354**  FUNCTION VALUE:     none
2355**
2356**  SIDE EFFECTS:       none
2357**
2358**--
2359**/
2360
2361INTERNAL void rpc__gssauth_cn_tlr_unpack
2362(
2363	rpc_cn_packet_p_t	pkt_p ATTRIBUTE_UNUSED /*TODO*/,
2364	unsigned32		auth_value_len ATTRIBUTE_UNUSED /*TODO*/,
2365	unsigned8		*packed_drep ATTRIBUTE_UNUSED /*TODO*/
2366)
2367{
2368	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
2369		("(rpc__gssauth_cn_tlr_unpack)\n"));
2370}
2371
2372/*****************************************************************************/
2373/*
2374**++
2375**
2376**  ROUTINE NAME:       rpc__gssauth_cn_vfy_client_req
2377**
2378**  SCOPE:              INTERNAL - declared locally
2379**
2380**  DESCRIPTION:
2381**
2382**      This routine will decode the auth_value field of
2383**      either an rpc_bind or rpc_alter_context PDU. Any
2384**      error encountered while authenticating the client
2385**      will result in an error status return. The contents
2386**      of the credentials field includes the authorization
2387**      data. This is called from the server side association
2388**      state machine. Note that upon successful return
2389**      the auth information rep will contain the client's
2390**      authorization protocol and data.
2391**
2392**  INPUTS:
2393**
2394**      assoc_sec       A pointer to per-association security context
2395**                      including association UUID CRC and sequence numbers.
2396**      sec             A pointer to security context element which includes
2397**                      the key ID, auth information rep and RPC auth
2398**                      information rep.
2399**      auth_value      A pointer to the auth_value field in the rpc_bind or
2400**                      rpc_alter_context PDU authentication trailer.
2401**      auth_value_len  The length, in bytes, of auth_value.
2402**
2403**  INPUTS/OUTPUTS:     none
2404**
2405**  OUTPUTS:
2406**
2407**      st              The return status of this routine.
2408**
2409**  IMPLICIT INPUTS:    none
2410**
2411**  IMPLICIT OUTPUTS:   none
2412**
2413**  FUNCTION VALUE:     none
2414**
2415**  SIDE EFFECTS:       none
2416**
2417**--
2418**/
2419
2420INTERNAL void rpc__gssauth_cn_vfy_client_req
2421(
2422	rpc_cn_assoc_sec_context_p_t	assoc_sec,
2423	rpc_cn_sec_context_p_t		sec,
2424	dce_pointer_t			auth_value,
2425	unsigned32			auth_value_len,
2426	unsigned32			old_client ATTRIBUTE_UNUSED /*TODO*/,
2427	unsigned32			*st
2428)
2429{
2430	rpc_gssauth_cn_info_p_t gssauth_cn_info = (rpc_gssauth_cn_info_p_t)sec->sec_cn_info;
2431	int maj_stat;
2432	OM_uint32 min_stat = 0;
2433	gss_buffer_desc input_token, output_token = GSS_C_EMPTY_BUFFER;
2434
2435	CODING_ERROR(st);
2436	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
2437		("(rpc__gssauth_cn_vfy_client_req)\n"));
2438
2439	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT,
2440		("(rpc__gssauth_cn_vfy_client_req) prot->%x level->%x key_id->%x assoc_uuid_crc->%x xmit_seq->%x recv_seq->%x\n",
2441		sec->sec_info->authn_protocol,
2442		sec->sec_info->authn_level,
2443		sec->sec_key_id,
2444		assoc_sec->assoc_uuid_crc,
2445		assoc_sec->assoc_next_snd_seq,
2446		assoc_sec->assoc_next_rcv_seq));
2447
2448#ifdef DEBUG
2449	if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_VFY_CLIENT_REQ)) {
2450		*st = RPC_S_CN_DBG_AUTH_FAILURE;
2451		return;
2452	}
2453#endif
2454
2455	input_token.value = auth_value;
2456	input_token.length = auth_value_len;
2457
2458	maj_stat = gss_accept_sec_context(&min_stat,
2459					  &gssauth_cn_info->gss_ctx,
2460					  NULL,
2461					  &input_token,
2462					  NULL,
2463					  NULL,
2464					  &gssauth_cn_info->gss_mech,
2465					  &output_token,
2466					  NULL,
2467					  NULL,
2468					  NULL);
2469        gssauth_cn_info->gss_stat = maj_stat;
2470        if (maj_stat == GSS_S_CONTINUE_NEEDED) {
2471                char msg[BUFSIZ];
2472                rpc__gssauth_error_map(maj_stat, min_stat,
2473                                       gssauth_cn_info->gss_mech,
2474                                       msg, sizeof(msg), st);
2475                RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
2476                        ("(rpc__gssauth_cn_vfy_client_req): %s: output_token.length[%u]\n",
2477                        msg, (unsigned int)output_token.length));
2478                /*
2479                 * we still transfer the buffer to the client
2480                 * but fail the auth in rpc__gssauth_cn_fmt_srvr_resp()
2481                 */
2482        } else if (maj_stat != GSS_S_COMPLETE) {
2483                char msg[BUFSIZ];
2484                rpc__gssauth_error_map(maj_stat, min_stat,
2485                                       gssauth_cn_info->gss_mech,
2486                                       msg, sizeof(msg), st);
2487                RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
2488                        ("(rpc__gssauth_cn_vfy_client_req): %s\n", msg));
2489		return;
2490        } else {
2491                *st = rpc_s_ok;
2492        }
2493
2494	assoc_sec->krb_message.length = (unsigned32) output_token.length;
2495	assoc_sec->krb_message.data = output_token.value;
2496}
2497
2498/*****************************************************************************/
2499/*
2500**++
2501**
2502**  ROUTINE NAME:       rpc__gssauth_cn_vfy_srvr_resp
2503**
2504**  SCOPE:              INTERNAL - declared locally
2505**
2506**  DESCRIPTION:
2507**
2508**      This routine will decode auth_value field either an
2509**      rpc_bind_ack or rpc_alter_context_response PDU. If the
2510**      credentials field of the auth_value field contains an
2511**      authentication protocol specific encoding of an error
2512**      this will be returned as an error status code. This is
2513**      called from the client side association state machine.
2514**      Note that upon successful return the auth information
2515**      rep will contain the client's authorization protocol
2516**      and data.
2517**
2518**  INPUTS:
2519**
2520**      assoc_sec       A pointer to per-association security context
2521**                      including association UUID CRC and sequence numbers.
2522**      sec             A pointer to security context element which includes
2523**                      the key ID, auth information rep and RPC auth
2524**                      information rep.
2525**      auth_value      A pointer to the auth_value field in the rpc_bind or
2526**                      rpc_alter_context PDU authentication trailer.
2527**      auth_value_len  The length, in bytes, of auth_value.
2528**
2529**  INPUTS/OUTPUTS:     none
2530**
2531**  OUTPUTS:
2532**
2533**      st              The return status of this routine.
2534**
2535**  IMPLICIT INPUTS:    none
2536**
2537**  IMPLICIT OUTPUTS:   none
2538**
2539**  FUNCTION VALUE:     none
2540**
2541**  SIDE EFFECTS:       none
2542**
2543**--
2544**/
2545
2546INTERNAL void rpc__gssauth_cn_vfy_srvr_resp
2547(
2548	rpc_cn_assoc_sec_context_p_t	assoc_sec,
2549	rpc_cn_sec_context_p_t		sec,
2550	dce_pointer_t			auth_value,
2551	unsigned32			auth_value_len,
2552	unsigned32			*st
2553)
2554{
2555	rpc_gssauth_info_p_t gssauth_info = (rpc_gssauth_info_p_t)sec->sec_info;
2556	rpc_gssauth_cn_info_p_t gssauth_cn_info = (rpc_gssauth_cn_info_p_t)sec->sec_cn_info;
2557	OM_uint32 maj_stat;
2558	OM_uint32 min_stat;
2559	gss_buffer_desc input_token, output_token = GSS_C_EMPTY_BUFFER;
2560
2561	CODING_ERROR(st);
2562	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
2563		("(rpc__gssauth_cn_vfy_srvr_resp)\n"));
2564
2565	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT,
2566		("(rpc__gssauth_cn_vfy_server_resp) prot->%x level->%x key_id->%x assoc_uuid_crc->%x xmit_seq->%x recv_seq->%x\n",
2567		sec->sec_info->authn_protocol,
2568		sec->sec_info->authn_level,
2569		sec->sec_key_id,
2570		assoc_sec->assoc_uuid_crc,
2571		assoc_sec->assoc_next_snd_seq,
2572		assoc_sec->assoc_next_rcv_seq));
2573
2574#ifdef DEBUG
2575	if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_VFY_SERVER_RESP)) {
2576		*st = RPC_S_CN_DBG_AUTH_FAILURE;
2577		return;
2578	}
2579#endif
2580
2581	if (gssauth_cn_info->gss_ctx != GSS_C_NO_CONTEXT &&
2582	    gssauth_cn_info->gss_stat == GSS_S_COMPLETE) {
2583		/* todo only when ready */
2584		goto done;
2585	}
2586
2587	input_token.value = auth_value;
2588	input_token.length = auth_value_len;
2589	maj_stat = rpc__gssauth_verify_server_token(&min_stat,
2590						    sec,
2591						    gssauth_info->gss_creds,
2592						    gssauth_info->gss_server_name,
2593						    gssauth_cn_info->gss_ctx,
2594						    input_token,
2595						    &gssauth_cn_info->gss_mech,
2596						    &output_token);
2597	gssauth_cn_info->gss_stat = maj_stat;
2598	if (maj_stat == GSS_S_CONTINUE_NEEDED) {
2599		char msg[BUFSIZ];
2600		rpc__gssauth_error_map(maj_stat, min_stat,
2601                                       gssauth_cn_info->gss_mech,
2602				       msg, sizeof(msg), st);
2603		RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
2604			("(rpc__gssauth_cn_vfy_srvr_resp): %s: output_token.length[%u]\n",
2605			msg, (unsigned int)output_token.length));
2606		/*
2607		 * we still transfer the buffer to the client
2608		 * but fail the auth in rpc__gssauth_cn_fmt_srvr_resp()
2609		 */
2610	} else if (maj_stat != GSS_S_COMPLETE) {
2611		char msg[BUFSIZ];
2612		rpc__gssauth_error_map(maj_stat, min_stat,
2613                                       gssauth_cn_info->gss_mech,
2614				       msg, sizeof(msg), st);
2615		RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
2616			("(rpc__gssauth_cn_vfy_srvr_resp): %s\n", msg));
2617		return;
2618	}
2619
2620done:
2621	assoc_sec->krb_message.length = (unsigned32) output_token.length;
2622	assoc_sec->krb_message.data = output_token.value;
2623
2624	*st = rpc_s_ok;
2625}
2626
2627PRIVATE rpc_protocol_id_t rpc__gssauth_negotiate_cn_init
2628(
2629	rpc_auth_rpc_prot_epv_p_t	*epv,
2630	unsigned32			*st
2631)
2632{
2633	CODING_ERROR(st);
2634	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
2635		("(rpc__gssauth_negotiate_cn_init)\n"));
2636
2637	*epv = (rpc_auth_rpc_prot_epv_p_t)&rpc_g_gssauth_negotiate_cn_epv;
2638	*st = rpc_s_ok;
2639	return RPC_C_PROTOCOL_ID_NCACN;
2640}
2641
2642PRIVATE rpc_protocol_id_t rpc__gssauth_mskrb_cn_init
2643(
2644	rpc_auth_rpc_prot_epv_p_t	*epv,
2645	unsigned32			*st
2646)
2647{
2648	CODING_ERROR(st);
2649	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
2650		("(rpc__gssauth_mskrb_cn_init)\n"));
2651
2652	*epv = (rpc_auth_rpc_prot_epv_p_t)&rpc_g_gssauth_mskrb_cn_epv;
2653	*st = rpc_s_ok;
2654	return RPC_C_PROTOCOL_ID_NCACN;
2655}
2656
2657PRIVATE rpc_protocol_id_t rpc__gssauth_winnt_cn_init
2658(
2659	rpc_auth_rpc_prot_epv_p_t	*epv,
2660	unsigned32			*st
2661)
2662{
2663	CODING_ERROR(st);
2664	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
2665		("(rpc__gssauth_winnt_cn_init)\n"));
2666
2667	*epv = (rpc_auth_rpc_prot_epv_p_t)&rpc_g_gssauth_winnt_cn_epv;
2668	*st = rpc_s_ok;
2669	return RPC_C_PROTOCOL_ID_NCACN;
2670}
2671
2672PRIVATE rpc_protocol_id_t rpc__gssauth_netlogon_cn_init
2673(
2674	rpc_auth_rpc_prot_epv_p_t	*epv,
2675	unsigned32			*st
2676)
2677{
2678	CODING_ERROR(st);
2679	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
2680		("(rpc__gssauth_netlogon_cn_init)\n"));
2681
2682	*epv = (rpc_auth_rpc_prot_epv_p_t)&rpc_g_gssauth_netlogon_cn_epv;
2683	*st = rpc_s_ok;
2684	return RPC_C_PROTOCOL_ID_NCACN;
2685}
2686
2687#endif /* defined(AUTH_GSS_NEGOTIATE) && AUTH_GSS_NEGOTIATE */
2688