1/*
2 * Copyright (c) 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1.  Redistributions of source code must retain the above copyright
11 *     notice, this list of conditions and the following disclaimer.
12 * 2.  Redistributions in binary form must reproduce the above copyright
13 *     notice, this list of conditions and the following disclaimer in the
14 *     documentation and/or other materials provided with the distribution.
15 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
16 *     contributors may be used to endorse or promote products derived from
17 *     this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Portions of this software have been released under the following terms:
31 *
32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC.
33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY
34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION
35 *
36 * To anyone who acknowledges that this file is provided "AS IS"
37 * without any express or implied warranty:
38 * permission to use, copy, modify, and distribute this file for any
39 * purpose is hereby granted without fee, provided that the above
40 * copyright notices and this notice appears in all source code copies,
41 * and that none of the names of Open Software Foundation, Inc., Hewlett-
42 * Packard Company or Digital Equipment Corporation be used
43 * in advertising or publicity pertaining to distribution of the software
44 * without specific, written prior permission.  Neither Open Software
45 * Foundation, Inc., Hewlett-Packard Company nor Digital
46 * Equipment Corporation makes any representations about the suitability
47 * of this software for any purpose.
48 *
49 * Copyright (c) 2007, Novell, Inc. All rights reserved.
50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions
52 * are met:
53 *
54 * 1.  Redistributions of source code must retain the above copyright
55 *     notice, this list of conditions and the following disclaimer.
56 * 2.  Redistributions in binary form must reproduce the above copyright
57 *     notice, this list of conditions and the following disclaimer in the
58 *     documentation and/or other materials provided with the distribution.
59 * 3.  Neither the name of Novell Inc. nor the names of its contributors
60 *     may be used to endorse or promote products derived from this
61 *     this software without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY
67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 *
74 * @APPLE_LICENSE_HEADER_END@
75 */
76
77/*
78**
79**  NAME
80**
81**      gssauth.c
82**
83**  FACILITY:
84**
85**      Remote Procedure Call (RPC)
86**
87**  ABSTRACT:
88**
89**      Client-side support of kerberos module.
90**
91**
92*/
93
94#include <config.h>
95
96#if defined(AUTH_GSS_NEGOTIATE) && AUTH_GSS_NEGOTIATE
97
98#include <gssauth.h>
99
100INTERNAL unsigned32 rpc_g_gssauth_alloc_count = 0;
101INTERNAL unsigned32 rpc_g_gssauth_free_count = 0;
102
103INTERNAL rpc_auth_rpc_prot_epv_p_t rpc_g_gssauth_negotiate_rpc_prot_epv[RPC_C_PROTOCOL_ID_MAX];
104INTERNAL rpc_auth_rpc_prot_epv_p_t rpc_g_gssauth_mskrb_rpc_prot_epv[RPC_C_PROTOCOL_ID_MAX];
105INTERNAL rpc_auth_rpc_prot_epv_p_t rpc_g_gssauth_winnt_rpc_prot_epv[RPC_C_PROTOCOL_ID_MAX];
106INTERNAL rpc_auth_rpc_prot_epv_p_t rpc_g_gssauth_netlogon_rpc_prot_epv[RPC_C_PROTOCOL_ID_MAX];
107
108INTERNAL void rpc__gssauth_negotiate_bnd_set_auth (
109	unsigned_char_p_t		/* in  */    /*server_princ_name*/,
110	rpc_authn_level_t		/* in  */    /*authn_level*/,
111	rpc_auth_identity_handle_t	/* in  */    /*auth_identity*/,
112	rpc_authz_protocol_id_t		/* in  */    /*authz_protocol*/,
113	rpc_binding_handle_t		/* in  */    /*binding_h*/,
114	rpc_auth_info_p_t		/* out */    * /*auth_info*/,
115	unsigned32			/* out */    * /*st*/
116    );
117
118INTERNAL void rpc__gssauth_mskrb_bnd_set_auth (
119	unsigned_char_p_t		/* in  */    /*server_princ_name*/,
120	rpc_authn_level_t		/* in  */    /*authn_level*/,
121	rpc_auth_identity_handle_t	/* in  */    /*auth_identity*/,
122	rpc_authz_protocol_id_t		/* in  */    /*authz_protocol*/,
123	rpc_binding_handle_t		/* in  */    /*binding_h*/,
124	rpc_auth_info_p_t		/* out */    * /*auth_info*/,
125	unsigned32			/* out */    * /*st*/
126    );
127
128INTERNAL void rpc__gssauth_winnt_bnd_set_auth (
129	unsigned_char_p_t		/* in  */    /*server_princ_name*/,
130	rpc_authn_level_t		/* in  */    /*authn_level*/,
131	rpc_auth_identity_handle_t	/* in  */    /*auth_identity*/,
132	rpc_authz_protocol_id_t		/* in  */    /*authz_protocol*/,
133	rpc_binding_handle_t		/* in  */    /*binding_h*/,
134	rpc_auth_info_p_t		/* out */    * /*auth_info*/,
135	unsigned32			/* out */    * /*st*/
136    );
137
138INTERNAL void rpc__gssauth_netlogon_bnd_set_auth (
139	unsigned_char_p_t		/* in  */    /*server_princ_name*/,
140	rpc_authn_level_t		/* in  */    /*authn_level*/,
141	rpc_auth_identity_handle_t	/* in  */    /*auth_identity*/,
142	rpc_authz_protocol_id_t		/* in  */    /*authz_protocol*/,
143	rpc_binding_handle_t		/* in  */    /*binding_h*/,
144	rpc_auth_info_p_t		/* out */    * /*auth_info*/,
145	unsigned32			/* out */    * /*st*/
146    );
147
148INTERNAL void rpc__gssauth_srv_reg_auth (
149	unsigned_char_p_t		/* in  */    /*server_princ_name*/,
150	rpc_auth_key_retrieval_fn_t	/* in  */    /*get_key_func*/,
151	dce_pointer_t			/* in  */    /*arg*/,
152	unsigned32			/* out */    * /*st*/
153    );
154
155INTERNAL void rpc__gssauth_mgt_inq_def (
156	unsigned32			/* out */    * /*authn_level*/,
157	unsigned32			/* out */    * /*st*/
158    );
159
160INTERNAL void rpc__gssauth_inq_my_princ_name (
161	unsigned32			/* in */     /*princ_name_size*/,
162	unsigned_char_p_t		/* out */    /*princ_name*/,
163	unsigned32			/* out */    * /*st*/
164    );
165
166INTERNAL void rpc__gssauth_free_info (
167	rpc_auth_info_p_t		/* in/out */ * /*info*/
168    );
169
170INTERNAL void rpc__gssauth_free_key (
171	rpc_key_info_p_t		/* in/out */ * /*info*/
172    );
173
174INTERNAL error_status_t rpc__gssauth_resolve_identity (
175	rpc_auth_identity_handle_t	/* in */     /* in_identity*/,
176	rpc_auth_identity_handle_t	/* out */    * /*out_identity*/
177    );
178
179INTERNAL void rpc__gssauth_release_identity (
180	rpc_auth_identity_handle_t	/* in/out */ * /*identity*/
181    );
182
183INTERNAL void rpc__gssauth_inq_sec_context (
184	rpc_auth_info_p_t		/* in */     /*auth_info*/,
185	void				/* out */    ** /*mech_context*/,
186	unsigned32			/* out */    * /*stp*/
187    );
188
189INTERNAL void rpc__gssauth_inq_access_token(
190    rpc_auth_info_p_t auth_info,
191    rpc_access_token_p_t* token,
192    unsigned32 *stp
193    );
194
195INTERNAL rpc_auth_epv_t rpc_g_gssauth_negotiate_epv =
196{
197	rpc__gssauth_negotiate_bnd_set_auth,
198	rpc__gssauth_srv_reg_auth,
199	rpc__gssauth_mgt_inq_def,
200	rpc__gssauth_inq_my_princ_name,
201	rpc__gssauth_free_info,
202	rpc__gssauth_free_key,
203	rpc__gssauth_resolve_identity,
204	rpc__gssauth_release_identity,
205	rpc__gssauth_inq_sec_context,
206        rpc__gssauth_inq_access_token
207};
208
209INTERNAL rpc_auth_epv_t rpc_g_gssauth_mskrb_epv =
210{
211	rpc__gssauth_mskrb_bnd_set_auth,
212	rpc__gssauth_srv_reg_auth,
213	rpc__gssauth_mgt_inq_def,
214	rpc__gssauth_inq_my_princ_name,
215	rpc__gssauth_free_info,
216	rpc__gssauth_free_key,
217	rpc__gssauth_resolve_identity,
218	rpc__gssauth_release_identity,
219	rpc__gssauth_inq_sec_context,
220        rpc__gssauth_inq_access_token
221};
222
223INTERNAL rpc_auth_epv_t rpc_g_gssauth_winnt_epv =
224{
225	rpc__gssauth_winnt_bnd_set_auth,
226	rpc__gssauth_srv_reg_auth,
227	rpc__gssauth_mgt_inq_def,
228	rpc__gssauth_inq_my_princ_name,
229	rpc__gssauth_free_info,
230	rpc__gssauth_free_key,
231	rpc__gssauth_resolve_identity,
232	rpc__gssauth_release_identity,
233	rpc__gssauth_inq_sec_context,
234        rpc__gssauth_inq_access_token
235};
236
237INTERNAL rpc_auth_epv_t rpc_g_gssauth_netlogon_epv =
238{
239	rpc__gssauth_netlogon_bnd_set_auth,
240	rpc__gssauth_srv_reg_auth,
241	rpc__gssauth_mgt_inq_def,
242	rpc__gssauth_inq_my_princ_name,
243	rpc__gssauth_free_info,
244	rpc__gssauth_free_key,
245	rpc__gssauth_resolve_identity,
246	rpc__gssauth_release_identity,
247	rpc__gssauth_inq_sec_context,
248        rpc__gssauth_inq_access_token
249};
250
251/*
252 * R P C _ _ G S S A U T H _ B N D _ S E T _ A U T H
253 *
254 */
255
256INTERNAL void rpc__gssauth_bnd_set_auth
257(
258	unsigned_char_p_t server_name,
259	rpc_authn_level_t level,
260	rpc_authn_protocol_id_t authn_protocol,
261	rpc_auth_identity_handle_t auth_ident,
262	rpc_authz_protocol_id_t authz_prot,
263	rpc_binding_handle_t binding_h,
264	rpc_auth_info_p_t *infop,
265	unsigned32 *stp
266)
267{
268	unsigned32 st;
269	rpc_gssauth_info_p_t gssauth_info;
270	unsigned_char_p_t str_server_name;
271	gss_name_t gss_server_name;
272	OM_uint32 maj_stat;
273	OM_uint32 min_stat;
274
275	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
276		("(rpc__gssauth_bnd_set_auth)\n"));
277
278	rpc_g_gssauth_alloc_count++;
279	RPC_MEM_ALLOC(gssauth_info,
280		      rpc_gssauth_info_p_t,
281		      sizeof (*gssauth_info),
282		      RPC_C_MEM_GSSAUTH_INFO,
283		      RPC_C_MEM_WAITOK);
284	memset (gssauth_info, 0, sizeof(*gssauth_info));
285
286	if ((authz_prot != rpc_c_authz_name) &&
287	    (authz_prot != rpc_c_authz_gss_name)) {
288		st = rpc_s_authn_authz_mismatch;
289		goto poison;
290	}
291
292	if ((level != rpc_c_authn_level_connect) &&
293	    (level != rpc_c_authn_level_pkt_integrity) &&
294	    (level != rpc_c_authn_level_pkt_privacy)) {
295		st = rpc_s_unsupported_authn_level;
296		goto poison;
297	}
298
299	/*
300	 * If no server principal name was specified, go ask for it.
301	 */
302	if (authz_prot == rpc_c_authz_name) {
303		gss_buffer_desc input_name;
304
305		if (server_name == NULL) {
306			rpc_mgmt_inq_server_princ_name(binding_h,
307						       authn_protocol,
308						       &str_server_name,
309						       &st);
310			if (st != rpc_s_ok) {
311				goto poison;
312			}
313		} else {
314			str_server_name = rpc_stralloc(server_name);
315		}
316
317		input_name.value = (void *)str_server_name;
318		input_name.length = strlen((char *)str_server_name);
319
320		maj_stat = gss_import_name(&min_stat,
321					   &input_name,
322					   GSS_KRB5_NT_PRINCIPAL_NAME,
323					   &gss_server_name);
324		if (GSS_ERROR(maj_stat)) {
325			char msg[256];
326			rpc__gssauth_error_map(maj_stat, min_stat, GSS_C_NO_OID,
327					       msg, sizeof(msg), &st);
328			RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
329				("(rpc__gssauth_bnd_set_auth): import: %s\n", msg));
330			goto poison;
331		}
332	} else if (authz_prot == rpc_c_authz_gss_name) {
333		gss_buffer_desc output_name;
334
335		gss_server_name = (gss_name_t)server_name;
336		server_name = NULL;
337
338		if (gss_server_name == GSS_C_NO_NAME) {
339			/*
340			 * the caller passes GSS_C_NO_NAME, we'll pass it down
341			 * later, if the caller wants an autolookup
342			 * rpc_c_authz_name should be used
343			 */
344			gss_server_name = GSS_C_NO_NAME;
345			str_server_name = NULL;
346		} else {
347			maj_stat = gss_duplicate_name(&min_stat,
348						      gss_server_name,
349						      &gss_server_name);
350			if (maj_stat != GSS_S_COMPLETE) {
351				char msg[256];
352				rpc__gssauth_error_map(maj_stat, min_stat, GSS_C_NO_OID,
353						       msg, sizeof(msg), &st);
354				RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
355					("(rpc__gssauth_bnd_set_auth): duplicate: %s\n", msg));
356				goto poison;
357			}
358
359			maj_stat = gss_display_name(&min_stat,
360						    gss_server_name,
361						    &output_name,
362						    NULL);
363			if (maj_stat != GSS_S_COMPLETE) {
364				char msg[256];
365				rpc__gssauth_error_map(maj_stat, min_stat, GSS_C_NO_OID,
366						       msg, sizeof(msg), &st);
367				RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
368					("(rpc__gssauth_bnd_set_auth): display: %s\n", msg));
369				goto poison;
370			}
371
372			RPC_MEM_ALLOC(str_server_name,
373				      unsigned_char_p_t,
374				      output_name.length + 1,
375				      RPC_C_MEM_STRING,
376				      RPC_C_MEM_WAITOK);
377			rpc__strncpy(str_server_name,
378				     output_name.value,
379				     output_name.length);
380
381			gss_release_buffer(&min_stat, &output_name);
382		}
383	}
384
385	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
386		("(rpc__gssauth_bnd_set_auth) %p created (now %d active)\n",
387		gssauth_info, rpc_g_gssauth_alloc_count - rpc_g_gssauth_free_count));
388
389	if (auth_ident != NULL) {
390		gss_OID desired_mech = GSS_C_NO_OID;
391
392		rpc__gssauth_select_mech(&min_stat, authn_protocol, &desired_mech);
393
394		assert(gssauth_info->gss_creds == GSS_C_NO_CREDENTIAL);
395
396		maj_stat = gss_add_cred(&min_stat,
397					(const gss_cred_id_t)auth_ident,
398					GSS_C_NO_NAME,
399					desired_mech,
400					GSS_C_INITIATE,
401					GSS_C_INDEFINITE,
402					GSS_C_INDEFINITE,
403					&gssauth_info->gss_creds,
404					NULL,
405					NULL,
406					NULL);
407		if (GSS_ERROR(maj_stat)) {
408			char msg[256];
409			rpc__gssauth_error_map(maj_stat, min_stat, GSS_C_NO_OID,
410					       msg, sizeof(msg), &st);
411			RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
412				("(rpc__gssauth_bnd_set_auth): add_cred: %s\n", msg));
413			goto poison;
414		}
415	}
416
417	gssauth_info->gss_server_name = gss_server_name;
418	gssauth_info->auth_info.server_princ_name = str_server_name;
419	gssauth_info->auth_info.authn_level = level;
420	gssauth_info->auth_info.authn_protocol = authn_protocol;
421	gssauth_info->auth_info.authz_protocol = authz_prot;
422	gssauth_info->auth_info.is_server = false;
423	gssauth_info->auth_info.u.auth_identity = (rpc_auth_identity_handle_t)gssauth_info->gss_creds;
424
425	gssauth_info->auth_info.refcount = 1;
426
427	*infop = &gssauth_info->auth_info;
428	*stp = rpc_s_ok;
429	return;
430
431poison:
432	*infop = &gssauth_info->auth_info;
433	*stp = st;
434	return;
435}
436
437INTERNAL void rpc__gssauth_negotiate_bnd_set_auth
438(
439	unsigned_char_p_t server_name,
440	rpc_authn_level_t level,
441	rpc_auth_identity_handle_t auth_ident,
442	rpc_authz_protocol_id_t authz_prot,
443	rpc_binding_handle_t binding_h,
444	rpc_auth_info_p_t *infop,
445	unsigned32 *stp
446)
447{
448	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
449		("(rpc__gssauth_negotiate_bnd_set_auth)\n"));
450
451	rpc__gssauth_bnd_set_auth(server_name,
452				  level,
453				  rpc_c_authn_gss_negotiate,
454				  auth_ident,
455				  authz_prot,
456				  binding_h,
457				  infop,
458				  stp);
459}
460
461INTERNAL void rpc__gssauth_mskrb_bnd_set_auth
462(
463	unsigned_char_p_t server_name,
464	rpc_authn_level_t level,
465	rpc_auth_identity_handle_t auth_ident,
466	rpc_authz_protocol_id_t authz_prot,
467	rpc_binding_handle_t binding_h,
468	rpc_auth_info_p_t *infop,
469	unsigned32 *stp
470)
471{
472	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
473		("(rpc__gssauth_mskrb_bnd_set_auth)\n"));
474
475	rpc__gssauth_bnd_set_auth(server_name,
476				  level,
477				  rpc_c_authn_gss_mskrb,
478				  auth_ident,
479				  authz_prot,
480				  binding_h,
481				  infop,
482				  stp);
483}
484
485INTERNAL void rpc__gssauth_winnt_bnd_set_auth
486(
487	unsigned_char_p_t server_name,
488	rpc_authn_level_t level,
489	rpc_auth_identity_handle_t auth_ident,
490	rpc_authz_protocol_id_t authz_prot,
491	rpc_binding_handle_t binding_h,
492	rpc_auth_info_p_t *infop,
493	unsigned32 *stp
494)
495{
496	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
497		("(rpc__gssauth_winntmskrb_bnd_set_auth)\n"));
498
499	rpc__gssauth_bnd_set_auth(server_name,
500				  level,
501				  rpc_c_authn_winnt,
502				  auth_ident,
503				  authz_prot,
504				  binding_h,
505				  infop,
506				  stp);
507}
508
509INTERNAL void rpc__gssauth_netlogon_bnd_set_auth
510(
511	unsigned_char_p_t server_name,
512	rpc_authn_level_t level,
513	rpc_auth_identity_handle_t auth_ident,
514	rpc_authz_protocol_id_t authz_prot,
515	rpc_binding_handle_t binding_h,
516	rpc_auth_info_p_t *infop,
517	unsigned32 *stp
518)
519{
520	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
521		("(rpc__gssauth_netlogon_bnd_set_auth)\n"));
522
523	rpc__gssauth_bnd_set_auth(server_name,
524				  level,
525				  rpc_c_authn_netlogon,
526				  auth_ident,
527				  authz_prot,
528				  binding_h,
529				  infop,
530				  stp);
531}
532
533INTERNAL void rpc__gssauth_negotiate_init
534(
535	rpc_auth_epv_p_t *epv,
536	rpc_auth_rpc_prot_epv_tbl_t *rpc_prot_epv,
537	unsigned32 *st
538)
539{
540	unsigned32		prot_id;
541	rpc_auth_rpc_prot_epv_t *prot_epv;
542
543	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
544		("(rpc__gssauth_negotiate_init)\n"));
545
546	/*
547	 * Initialize the RPC-protocol-specific EPVs for the RPC protocols
548	 * we work with (ncacn).
549	 */
550	/* for now only ncacn, that's what windows uses */
551	prot_id = rpc__gssauth_negotiate_cn_init (&prot_epv, st);
552	if (*st == rpc_s_ok) {
553		rpc_g_gssauth_negotiate_rpc_prot_epv[prot_id] = prot_epv;
554	}
555
556	/*
557	 * Return information for this gss_negotiate (SPNEGO) authentication service.
558	 */
559	*epv = &rpc_g_gssauth_negotiate_epv;
560	*rpc_prot_epv = rpc_g_gssauth_negotiate_rpc_prot_epv;
561
562	*st = 0;
563}
564
565INTERNAL void rpc__gssauth_mskrb_init
566(
567	rpc_auth_epv_p_t *epv,
568	rpc_auth_rpc_prot_epv_tbl_t *rpc_prot_epv,
569	unsigned32 *st
570)
571{
572	unsigned32		prot_id;
573	rpc_auth_rpc_prot_epv_t *prot_epv;
574
575	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
576		("(rpc__gssauth_mskrb_init)\n"));
577
578	/*
579	 * Initialize the RPC-protocol-specific EPVs for the RPC protocols
580	 * we work with (ncacn).
581	 */
582	/* for now only ncacn, that's what windows uses */
583	prot_id = rpc__gssauth_mskrb_cn_init (&prot_epv, st);
584	if (*st == rpc_s_ok) {
585		rpc_g_gssauth_mskrb_rpc_prot_epv[prot_id] = prot_epv;
586	}
587
588	/*
589	 * Return information for this (KRB5) authentication service.
590	 */
591	*epv = &rpc_g_gssauth_mskrb_epv;
592	*rpc_prot_epv = rpc_g_gssauth_mskrb_rpc_prot_epv;
593
594	*st = 0;
595}
596
597INTERNAL void rpc__gssauth_winnt_init
598(
599	rpc_auth_epv_p_t *epv,
600	rpc_auth_rpc_prot_epv_tbl_t *rpc_prot_epv,
601	unsigned32 *st
602)
603{
604	unsigned32		prot_id;
605	rpc_auth_rpc_prot_epv_t *prot_epv;
606
607	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
608		("(rpc__gssauth_winnt_init)\n"));
609
610	/*
611	 * Initialize the RPC-protocol-specific EPVs for the RPC protocols
612	 * we work with (ncacn).
613	 */
614	/* for now only ncacn, that's what windows uses */
615	prot_id = rpc__gssauth_winnt_cn_init (&prot_epv, st);
616	if (*st == rpc_s_ok) {
617		rpc_g_gssauth_winnt_rpc_prot_epv[prot_id] = prot_epv;
618	}
619
620	/*
621	 * Return information for this (KRB5) authentication service.
622	 */
623	*epv = &rpc_g_gssauth_winnt_epv;
624	*rpc_prot_epv = rpc_g_gssauth_winnt_rpc_prot_epv;
625
626	*st = 0;
627}
628
629INTERNAL void rpc__gssauth_netlogon_init
630(
631	rpc_auth_epv_p_t *epv,
632	rpc_auth_rpc_prot_epv_tbl_t *rpc_prot_epv,
633	unsigned32 *st
634)
635{
636	unsigned32		prot_id;
637	rpc_auth_rpc_prot_epv_t *prot_epv;
638
639	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
640		("(rpc__gssauth_netlogon_init)\n"));
641
642	/*
643	 * Initialize the RPC-protocol-specific EPVs for the RPC protocols
644	 * we work with (ncacn).
645	 */
646	/* for now only ncacn, that's what windows uses */
647	prot_id = rpc__gssauth_netlogon_cn_init (&prot_epv, st);
648	if (*st == rpc_s_ok) {
649		rpc_g_gssauth_netlogon_rpc_prot_epv[prot_id] = prot_epv;
650	}
651
652	/*
653	 * Return information for this (KRB5) authentication service.
654	 */
655	*epv = &rpc_g_gssauth_netlogon_epv;
656	*rpc_prot_epv = rpc_g_gssauth_netlogon_rpc_prot_epv;
657
658	*st = 0;
659}
660/*
661 * R P C _ _ G S S A U T H _ F R E E _ I N F O
662 *
663 * Free info.
664 */
665
666INTERNAL void rpc__gssauth_free_info
667(
668	rpc_auth_info_p_t *info
669)
670{
671	rpc_gssauth_info_p_t gssauth_info = (rpc_gssauth_info_p_t)*info ;
672	const char *info_type;
673
674	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
675		("(rpc__gssauth_free_info)\n"));
676
677	info_type = (*info)->is_server?"server":"client";
678
679	if (gssauth_info->auth_info.server_princ_name != NULL) {
680		unsigned32 st;
681		rpc_string_free(&gssauth_info->auth_info.server_princ_name, &st);
682	}
683
684	if (gssauth_info->gss_server_name != GSS_C_NO_NAME) {
685		OM_uint32 min_stat;
686		gss_release_name(&min_stat, &gssauth_info->gss_server_name);
687		gssauth_info->gss_server_name = GSS_C_NO_NAME;
688	}
689
690	if (gssauth_info->gss_creds != GSS_C_NO_CREDENTIAL) {
691		OM_uint32 min_stat;
692		gss_release_cred(&min_stat, &gssauth_info->gss_creds);
693		gssauth_info->gss_creds = GSS_C_NO_CREDENTIAL;
694	}
695
696	memset(gssauth_info, 0x69, sizeof(*gssauth_info));
697	RPC_MEM_FREE(gssauth_info, RPC_C_MEM_GSSAUTH_INFO);
698
699	rpc_g_gssauth_free_count++;
700
701	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL,
702		("(rpc__gssauth_free_info) freeing %s auth_info (now %d active).\n",
703		info_type, rpc_g_gssauth_alloc_count - rpc_g_gssauth_free_count));
704
705	*info = NULL;
706}
707
708/*
709 * R P C _ _ G S S A U T H _ M G T _ I N Q _ D E F
710 *
711 * Return default authentication level
712 *
713 * !!! should read this from a config file.
714 */
715
716INTERNAL void rpc__gssauth_mgt_inq_def
717(
718	unsigned32 *authn_level,
719	unsigned32 *stp
720)
721{
722	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
723		("(rpc__gssauth_mgt_inq_def)\n"));
724
725	*authn_level = rpc_c_authn_level_pkt_privacy;
726	*stp = rpc_s_ok;
727}
728
729/*
730 * R P C _ _ G S S A U T H _ S R V _ R E G _ A U T H
731 *
732 */
733
734INTERNAL void rpc__gssauth_srv_reg_auth
735(
736	unsigned_char_p_t server_name ATTRIBUTE_UNUSED,
737	rpc_auth_key_retrieval_fn_t get_key_func ATTRIBUTE_UNUSED,
738	dce_pointer_t arg ATTRIBUTE_UNUSED,
739	unsigned32 *stp
740)
741{
742	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
743		("(rpc__gssauth_srv_reg_auth)\n"));
744
745	*stp = rpc_s_ok;
746}
747
748/*
749 * R P C _ _ G S S A U T H _ I N Q _ M Y _ P R I N C _ N A M E
750 *
751 * All this doesn't matter for this module, but we need the placebo.
752 */
753
754INTERNAL void rpc__gssauth_inq_my_princ_name
755(
756	unsigned32 name_size,
757	unsigned_char_p_t name,
758	unsigned32 *stp
759)
760{
761	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
762		("(rpc__gssauth_inq_my_princ_name)\n"));
763
764	if (name_size > 0) {
765		rpc__strncpy(name, (unsigned char *)"", name_size - 1);
766	}
767	*stp = rpc_s_ok;
768}
769
770/*
771 * R P C _ _ G S S A U T H _ F R E E _ KEY
772 *
773 * Free key.
774 */
775
776INTERNAL void rpc__gssauth_free_key
777(
778	rpc_key_info_p_t *info ATTRIBUTE_UNUSED
779)
780{
781	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
782		("(rpc__gssauth_free_key)\n"));
783}
784
785/*
786 * R P C _ _ G S S A U T H _ R E S O L V E _ I D E N T I T Y
787 *
788 * Resolve identity.
789 */
790
791INTERNAL error_status_t rpc__gssauth_resolve_identity
792(
793	rpc_auth_identity_handle_t in_identity,
794	rpc_auth_identity_handle_t *out_identity
795)
796{
797	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
798		("(rpc__gssauth_resolve_identity)\n"));
799
800	*out_identity = in_identity;
801	return 0;
802}
803
804/*
805 * R P C _ _ G S S A U T H _ R E L E A S E _ I D E N T I T Y
806 *
807 * Release identity.
808 */
809
810INTERNAL void rpc__gssauth_release_identity
811(
812	rpc_auth_identity_handle_t *identity ATTRIBUTE_UNUSED
813)
814{
815	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
816		("(rpc__gssauth_release_identity)\n"));
817}
818
819void rpc__gssauth_init_func(void)
820{
821	static rpc_authn_protocol_id_elt_t auth[4] = {
822	{ /* 0 */
823		rpc__gssauth_negotiate_init,
824		rpc_c_authn_gss_negotiate,
825		dce_c_rpc_authn_protocol_gss_negotiate,
826		NULL,
827		rpc_g_gssauth_negotiate_rpc_prot_epv
828	},
829	{ /* 1 */
830		rpc__gssauth_mskrb_init,
831		rpc_c_authn_gss_mskrb,
832		dce_c_rpc_authn_protocol_gss_mskrb,
833		NULL,
834		rpc_g_gssauth_mskrb_rpc_prot_epv
835	},
836	{ /* 2 */
837		rpc__gssauth_winnt_init,
838		rpc_c_authn_winnt,
839		dce_c_rpc_authn_protocol_winnt,
840		NULL,
841		rpc_g_gssauth_winnt_rpc_prot_epv
842	},
843	{ /* 3 */
844		rpc__gssauth_netlogon_init,
845		rpc_c_authn_netlogon,
846		dce_c_rpc_authn_protocol_netlogon,
847		NULL,
848		rpc_g_gssauth_netlogon_rpc_prot_epv
849	}
850	};
851
852	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
853		("(rpc__module_init_func)\n"));
854
855	rpc__register_authn_protocol(auth, sizeof(auth)/sizeof(auth[0]));
856}
857
858/*
859 * R P C _ _ G S S A U T H _ I N Q _ S E C _ C O N T E X T
860 *
861 * Inq sec context.
862 */
863
864INTERNAL void rpc__gssauth_inq_sec_context
865(
866	rpc_auth_info_p_t auth_info,
867	void **mech_context,
868	unsigned32 *stp
869)
870{
871	rpc_gssauth_info_p_t gssauth_info = NULL;
872	rpc_gssauth_cn_info_p_t gssauth_cn_info = NULL;
873
874	RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE,
875		("(rpc__gssauth_inq_sec_context)\n"));
876
877	gssauth_info = (rpc_gssauth_info_p_t)auth_info;
878	gssauth_cn_info = gssauth_info->cn_info;
879
880	*mech_context = (void*)gssauth_cn_info->gss_ctx;
881	*stp = rpc_s_ok;
882}
883
884INTERNAL void rpc__gssauth_inq_access_token(
885    rpc_auth_info_p_t auth_info ATTRIBUTE_UNUSED,
886    rpc_access_token_p_t* token,
887    unsigned32 *stp
888    )
889{
890	*token = NULL;
891	*stp = rpc_s_not_supported;
892}
893
894static struct {
895	rpc_authn_protocol_id_t authn_protocol;
896	gss_OID_desc gss_oid;
897} rpc__gssauth_mechanisms[] = {
898	{	/* SPNEGO mechanism */
899		rpc_c_authn_gss_negotiate,
900		{ 6, (void *)"\053\006\001\005\005\002" },
901	},
902	{	/* Kerberos mechanism */
903		rpc_c_authn_gss_mskrb,
904		{ 9, (void *)"\052\206\110\206\367\022\001\002\002" },
905	},
906	{	/* NTLM mechanism */
907		rpc_c_authn_winnt,
908		{ 10, (void *)"\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a" },
909	},
910	{	/* NetLogon secure channel mechanism (private) */
911		rpc_c_authn_netlogon,
912		{ 6, (void *)"\x2a\x85\x70\x2b\x0e\x02" },
913	},
914};
915
916PRIVATE OM_uint32 rpc__gssauth_select_mech
917(
918	OM_uint32		*min_stat,
919	rpc_authn_protocol_id_t	authn_protocol,
920	gss_OID			*req_mech
921)
922{
923	gss_OID selected_mech = GSS_C_NO_OID;
924	size_t i;
925
926	*min_stat = 0;
927
928	for (i = 0;
929	     i < sizeof(rpc__gssauth_mechanisms)/sizeof(rpc__gssauth_mechanisms[0]);
930	     i++)
931	{
932		if (rpc__gssauth_mechanisms[i].authn_protocol == authn_protocol) {
933			selected_mech = &rpc__gssauth_mechanisms[i].gss_oid;
934			break;
935		}
936	}
937
938	if (selected_mech == GSS_C_NO_OID)
939		return GSS_S_UNAVAILABLE;
940
941	*req_mech = selected_mech;
942	return GSS_S_COMPLETE;
943}
944
945#endif /* defined(AUTH_GSS_NEGOTIATE) && AUTH_GSS_NEGOTIATE */
946