1 /*
2  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  *
5  * A module for Kerberos V5  security mechanism.
6  *
7  */
8 
9 #pragma ident	"%Z%%M%	%I%	%E% SMI"
10 
11 char _depends_on[] = "misc/kgssapi crypto/md5";
12 
13 #include <sys/types.h>
14 #include <sys/modctl.h>
15 #include <sys/errno.h>
16 #include <mechglueP.h>
17 #include <gssapiP_krb5.h>
18 #include <gssapi_err_generic.h>
19 #include <gssapi/kgssapi_defs.h>
20 #include <sys/debug.h>
21 #include <k5-int.h>
22 
23 OM_uint32 krb5_gss_get_context(void ** context);
24 
25 extern krb5_error_code krb5_ser_context_init
26 	(krb5_context);
27 
28 extern	krb5_error_code	krb5_ser_auth_context_init
29 	(krb5_context);
30 
31 static	struct	gss_config krb5_mechanism =
32 	{{9, "\052\206\110\206\367\022\001\002\002"},
33 	NULL,	/* context */
34 	NULL,	/* next */
35 	TRUE,	/* uses_kmod */
36 /* EXPORT DELETE START */ /* CRYPT DELETE START */
37 	krb5_gss_unseal,
38 /* EXPORT DELETE END */ /* CRYPT DELETE END */
39 	krb5_gss_delete_sec_context,
40 /* EXPORT DELETE START */ /* CRYPT DELETE START */
41 	krb5_gss_seal,
42 /* EXPORT DELETE END */ /* CRYPT DELETE END */
43 	krb5_gss_import_sec_context,
44 /* EXPORT DELETE START */
45 /* CRYPT DELETE START */
46 #if 0
47 /* CRYPT DELETE END */
48 	krb5_gss_seal,
49 	krb5_gss_unseal,
50 /* CRYPT DELETE START */
51 #endif
52 /* CRYPT DELETE END */
53 /* EXPORT DELETE END */
54 	krb5_gss_sign,
55 	krb5_gss_verify,
56 };
57 
58 static gss_mechanism
59 	gss_mech_initialize()
60 {
61 	(void) krb5_gss_get_context(&(krb5_mechanism.context));
62 	return (&krb5_mechanism);
63 }
64 
65 
66 /*
67  * Module linkage information for the kernel.
68  */
69 extern struct mod_ops mod_miscops;
70 
71 static struct modlmisc modlmisc = {
72 	&mod_miscops, "Krb5 GSS mechanism"
73 };
74 
75 static struct modlinkage modlinkage = {
76 	MODREV_1,
77 	(void *)&modlmisc,
78 	NULL
79 };
80 
81 
82 static int krb5_fini_code = EBUSY;
83 
84 int
85 _init()
86 {
87 	int retval;
88 	gss_mechanism mech, tmp;
89 
90 	if ((retval = mod_install(&modlinkage)) != 0)
91 		return (retval);
92 
93 	mech = gss_mech_initialize();
94 
95 	mutex_enter(&__kgss_mech_lock);
96 	tmp = __kgss_get_mechanism(&mech->mech_type);
97 	if (tmp != NULL) {
98 
99 		KRB5_LOG0(KRB5_INFO,
100 			"KRB5 GSS mechanism: mechanism already in table.\n");
101 
102 		if (tmp->uses_kmod == TRUE) {
103 			KRB5_LOG0(KRB5_INFO, "KRB5 GSS mechanism: mechanism "
104 				"table supports kernel operations!\n");
105 		}
106 		/*
107 		 * keep us loaded, but let us be unloadable. This
108 		 * will give the developer time to trouble shoot
109 		 */
110 		krb5_fini_code = 0;
111 	} else {
112 		__kgss_add_mechanism(mech);
113 		ASSERT(__kgss_get_mechanism(&mech->mech_type) == mech);
114 	}
115 	mutex_exit(&__kgss_mech_lock);
116 
117 	return (0);
118 }
119 
120 int
121 _fini()
122 {
123 	int ret = krb5_fini_code;
124 
125 	if (ret == 0) {
126 		ret = (mod_remove(&modlinkage));
127 	}
128 	return (ret);
129 }
130 
131 int
132 _info(struct modinfo *modinfop)
133 {
134 	return (mod_info(&modlinkage, modinfop));
135 }
136 
137 OM_uint32
138 krb5_gss_get_context(context)
139 void **	context;
140 {
141 	OM_uint32 major_status = 0;
142 
143 	mutex_lock(&krb5_mutex);
144 	if (context == NULL)
145 	{
146 		major_status = GSS_S_FAILURE;
147 		goto unlock;
148 	}
149 	if (kg_context) {
150 		*context = kg_context;
151 		major_status = GSS_S_COMPLETE;
152 		goto unlock;
153 	}
154 
155 	if (krb5_init_context(&kg_context))
156 	{
157 		major_status = GSS_S_FAILURE;
158 		goto unlock;
159 	}
160 	if (krb5_ser_auth_context_init(kg_context))
161 	{
162 		kg_context = 0;
163 		major_status = GSS_S_FAILURE;
164 		goto unlock;
165 	}
166 
167 	*context = kg_context;
168 unlock:
169 	mutex_unlock(&krb5_mutex);
170 	return (major_status);
171 }
172