1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
25 *
26 * A module for Kerberos V5  security mechanism.
27 *
28 */
29
30#include <sys/types.h>
31#include <sys/modctl.h>
32#include <sys/errno.h>
33#include <mechglueP.h>
34#include <gssapiP_krb5.h>
35#include <gssapi_err_generic.h>
36#include <gssapi/kgssapi_defs.h>
37#include <sys/debug.h>
38#include <k5-int.h>
39
40/* mechglue wrappers */
41
42static OM_uint32 k5glue_delete_sec_context
43	(void *, OM_uint32 *,	/* minor_status */
44	gss_ctx_id_t *,	/* context_handle */
45	gss_buffer_t,	/* output_token */
46	OM_uint32);
47
48static OM_uint32 k5glue_sign
49	(void *, OM_uint32 *,	/* minor_status */
50	gss_ctx_id_t,	/* context_handle */
51	int,		/* qop_req */
52	gss_buffer_t,	/* message_buffer */
53	gss_buffer_t,	/* message_token */
54	OM_uint32);
55
56static OM_uint32 k5glue_verify
57	(void *, OM_uint32 *,	/* minor_status */
58	gss_ctx_id_t,	/* context_handle */
59	gss_buffer_t,	/* message_buffer */
60	gss_buffer_t,	/* token_buffer */
61	int *,	/* qop_state */
62	OM_uint32);
63
64static OM_uint32 k5glue_seal
65	(void *, OM_uint32 *,	/* minor_status */
66	gss_ctx_id_t,		/* context_handle */
67	int,			/* conf_req_flag */
68	int,			/* qop_req */
69	gss_buffer_t,		/* input_message_buffer */
70	int *,			/* conf_state */
71	gss_buffer_t,		/* output_message_buffer */
72	OM_uint32);
73
74static OM_uint32 k5glue_unseal
75	(void *, OM_uint32 *,	/* minor_status */
76	gss_ctx_id_t,		/* context_handle */
77	gss_buffer_t,		/* input_message_buffer */
78	gss_buffer_t,		/* output_message_buffer */
79	int *,			/* conf_state */
80	int *,			/* qop_state */
81	OM_uint32);
82
83static OM_uint32 k5glue_import_sec_context
84	(void *, OM_uint32 *,		/* minor_status */
85	gss_buffer_t,			/* interprocess_token */
86	gss_ctx_id_t *);		/* context_handle */
87
88
89
90static	struct	gss_config krb5_mechanism =
91	{{9, "\052\206\110\206\367\022\001\002\002"},
92	NULL,	/* context */
93	NULL,	/* next */
94	TRUE,	/* uses_kmod */
95	k5glue_unseal,
96	k5glue_delete_sec_context,
97	k5glue_seal,
98	k5glue_import_sec_context,
99	k5glue_sign,
100	k5glue_verify,
101	};
102
103static gss_mechanism
104	gss_mech_initialize()
105{
106	return (&krb5_mechanism);
107}
108
109
110/*
111 * Module linkage information for the kernel.
112 */
113extern struct mod_ops mod_miscops;
114
115static struct modlmisc modlmisc = {
116	&mod_miscops, "Krb5 GSS mechanism"
117};
118
119static struct modlinkage modlinkage = {
120	MODREV_1,
121	(void *)&modlmisc,
122	NULL
123};
124
125
126static int krb5_fini_code = EBUSY;
127
128int
129_init()
130{
131	int retval;
132	gss_mechanism mech, tmp;
133
134	if ((retval = mod_install(&modlinkage)) != 0)
135		return (retval);
136
137	mech = gss_mech_initialize();
138
139	mutex_enter(&__kgss_mech_lock);
140	tmp = __kgss_get_mechanism(&mech->mech_type);
141	if (tmp != NULL) {
142
143		KRB5_LOG0(KRB5_INFO,
144		    "KRB5 GSS mechanism: mechanism already in table.\n");
145
146		if (tmp->uses_kmod == TRUE) {
147			KRB5_LOG0(KRB5_INFO, "KRB5 GSS mechanism: mechanism "
148			    "table supports kernel operations!\n");
149		}
150		/*
151		 * keep us loaded, but let us be unloadable. This
152		 * will give the developer time to trouble shoot
153		 */
154		krb5_fini_code = 0;
155	} else {
156		__kgss_add_mechanism(mech);
157		ASSERT(__kgss_get_mechanism(&mech->mech_type) == mech);
158	}
159	mutex_exit(&__kgss_mech_lock);
160
161	return (0);
162}
163
164int
165_fini()
166{
167	int ret = krb5_fini_code;
168
169	if (ret == 0) {
170		ret = (mod_remove(&modlinkage));
171	}
172	return (ret);
173}
174
175int
176_info(struct modinfo *modinfop)
177{
178	return (mod_info(&modlinkage, modinfop));
179}
180
181/* ARGSUSED */
182static OM_uint32
183k5glue_delete_sec_context(ctx, minor_status, context_handle, output_token,
184	gssd_ctx_verifier)
185	void *ctx;
186	OM_uint32 *minor_status;
187	gss_ctx_id_t *context_handle;
188	gss_buffer_t output_token;
189	OM_uint32 gssd_ctx_verifier;
190{
191	return (krb5_gss_delete_sec_context(minor_status,
192				    context_handle, output_token,
193				    gssd_ctx_verifier));
194}
195
196/* V2 */
197/* ARGSUSED */
198static OM_uint32
199k5glue_import_sec_context(ctx, minor_status, interprocess_token, context_handle)
200	void *ctx;
201	OM_uint32 *minor_status;
202	gss_buffer_t	interprocess_token;
203	gss_ctx_id_t	 *context_handle;
204{
205	return (krb5_gss_import_sec_context(minor_status,
206			interprocess_token,
207			context_handle));
208}
209
210/* V1 only */
211/* ARGSUSED */
212static OM_uint32
213k5glue_seal(ctx, minor_status, context_handle, conf_req_flag, qop_req,
214	    input_message_buffer, conf_state, output_message_buffer,
215	    gssd_ctx_verifier)
216	void *ctx;
217	OM_uint32 *minor_status;
218	gss_ctx_id_t context_handle;
219	int conf_req_flag;
220	int qop_req;
221	gss_buffer_t input_message_buffer;
222	int *conf_state;
223	gss_buffer_t output_message_buffer;
224	OM_uint32 gssd_ctx_verifier;
225{
226	return (krb5_gss_seal(minor_status, context_handle,
227			conf_req_flag, qop_req, input_message_buffer,
228			conf_state, output_message_buffer, gssd_ctx_verifier));
229}
230
231/* ARGSUSED */
232static OM_uint32
233k5glue_sign(ctx, minor_status, context_handle,
234		qop_req, message_buffer,
235		message_token, gssd_ctx_verifier)
236	void *ctx;
237	OM_uint32 *minor_status;
238	gss_ctx_id_t context_handle;
239	int qop_req;
240	gss_buffer_t message_buffer;
241	gss_buffer_t message_token;
242	OM_uint32 gssd_ctx_verifier;
243{
244	return (krb5_gss_sign(minor_status, context_handle,
245		qop_req, message_buffer, message_token, gssd_ctx_verifier));
246}
247
248/* ARGSUSED */
249static OM_uint32
250k5glue_unseal(ctx, minor_status, context_handle, input_message_buffer,
251	    output_message_buffer, conf_state, qop_state, gssd_ctx_verifier)
252	void *ctx;
253	OM_uint32 *minor_status;
254	gss_ctx_id_t context_handle;
255	gss_buffer_t input_message_buffer;
256	gss_buffer_t output_message_buffer;
257	int *conf_state;
258	int *qop_state;
259	OM_uint32 gssd_ctx_verifier;
260{
261	return (krb5_gss_unseal(minor_status, context_handle,
262				input_message_buffer, output_message_buffer,
263				conf_state, qop_state, gssd_ctx_verifier));
264}
265
266/* V1 only */
267/* ARGSUSED */
268static OM_uint32
269k5glue_verify(ctx, minor_status, context_handle, message_buffer,
270	    token_buffer, qop_state, gssd_ctx_verifier)
271	void *ctx;
272	OM_uint32 *minor_status;
273	gss_ctx_id_t context_handle;
274	gss_buffer_t message_buffer;
275	gss_buffer_t token_buffer;
276	int *qop_state;
277	OM_uint32 gssd_ctx_verifier;
278{
279	return (krb5_gss_verify(minor_status,
280				context_handle,
281				message_buffer,
282				token_buffer,
283				qop_state, gssd_ctx_verifier));
284}
285