1*a9148abdSDoug Rabson /*-
2*a9148abdSDoug Rabson * Copyright (c) 2008 Isilon Inc http://www.isilon.com/
3*a9148abdSDoug Rabson * Authors: Doug Rabson <dfr@rabson.org>
4*a9148abdSDoug Rabson * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org>
5*a9148abdSDoug Rabson *
6*a9148abdSDoug Rabson * Redistribution and use in source and binary forms, with or without
7*a9148abdSDoug Rabson * modification, are permitted provided that the following conditions
8*a9148abdSDoug Rabson * are met:
9*a9148abdSDoug Rabson * 1. Redistributions of source code must retain the above copyright
10*a9148abdSDoug Rabson * notice, this list of conditions and the following disclaimer.
11*a9148abdSDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright
12*a9148abdSDoug Rabson * notice, this list of conditions and the following disclaimer in the
13*a9148abdSDoug Rabson * documentation and/or other materials provided with the distribution.
14*a9148abdSDoug Rabson *
15*a9148abdSDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*a9148abdSDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*a9148abdSDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*a9148abdSDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*a9148abdSDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*a9148abdSDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*a9148abdSDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*a9148abdSDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*a9148abdSDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*a9148abdSDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*a9148abdSDoug Rabson * SUCH DAMAGE.
26*a9148abdSDoug Rabson */
27*a9148abdSDoug Rabson
28*a9148abdSDoug Rabson #include <sys/types.h>
29*a9148abdSDoug Rabson #include <sys/syscall.h>
30*a9148abdSDoug Rabson #include <sys/module.h>
31*a9148abdSDoug Rabson
32*a9148abdSDoug Rabson #include <stdio.h>
33*a9148abdSDoug Rabson #include <string.h>
34*a9148abdSDoug Rabson #include <err.h>
35*a9148abdSDoug Rabson #include <unistd.h>
36*a9148abdSDoug Rabson #include <stdlib.h>
37*a9148abdSDoug Rabson
38*a9148abdSDoug Rabson #include <krb5.h>
39*a9148abdSDoug Rabson #include <gssapi/gssapi.h>
40*a9148abdSDoug Rabson #include <gssapi/gssapi_krb5.h>
41*a9148abdSDoug Rabson
42*a9148abdSDoug Rabson struct gsstest_2_args {
43*a9148abdSDoug Rabson int step; /* test step number */
44*a9148abdSDoug Rabson gss_buffer_desc input_token; /* token from userland */
45*a9148abdSDoug Rabson gss_buffer_desc output_token; /* buffer to receive reply token */
46*a9148abdSDoug Rabson };
47*a9148abdSDoug Rabson struct gsstest_2_res {
48*a9148abdSDoug Rabson OM_uint32 maj_stat; /* maj_stat from kernel */
49*a9148abdSDoug Rabson OM_uint32 min_stat; /* min_stat from kernel */
50*a9148abdSDoug Rabson gss_buffer_desc output_token; /* reply token (using space from gsstest_2_args.output) */
51*a9148abdSDoug Rabson };
52*a9148abdSDoug Rabson
53*a9148abdSDoug Rabson static void
report_error(gss_OID mech,OM_uint32 maj,OM_uint32 min)54*a9148abdSDoug Rabson report_error(gss_OID mech, OM_uint32 maj, OM_uint32 min)
55*a9148abdSDoug Rabson {
56*a9148abdSDoug Rabson OM_uint32 maj_stat, min_stat;
57*a9148abdSDoug Rabson OM_uint32 message_context;
58*a9148abdSDoug Rabson gss_buffer_desc buf;
59*a9148abdSDoug Rabson
60*a9148abdSDoug Rabson printf("major_stat=%d, minor_stat=%d\n", maj, min);
61*a9148abdSDoug Rabson message_context = 0;
62*a9148abdSDoug Rabson do {
63*a9148abdSDoug Rabson maj_stat = gss_display_status(&min_stat, maj,
64*a9148abdSDoug Rabson GSS_C_GSS_CODE, GSS_C_NO_OID, &message_context, &buf);
65*a9148abdSDoug Rabson printf("%.*s\n", (int)buf.length, (char *) buf.value);
66*a9148abdSDoug Rabson gss_release_buffer(&min_stat, &buf);
67*a9148abdSDoug Rabson } while (message_context);
68*a9148abdSDoug Rabson if (mech) {
69*a9148abdSDoug Rabson message_context = 0;
70*a9148abdSDoug Rabson do {
71*a9148abdSDoug Rabson maj_stat = gss_display_status(&min_stat, min,
72*a9148abdSDoug Rabson GSS_C_MECH_CODE, mech, &message_context, &buf);
73*a9148abdSDoug Rabson printf("%.*s\n", (int)buf.length, (char *) buf.value);
74*a9148abdSDoug Rabson gss_release_buffer(&min_stat, &buf);
75*a9148abdSDoug Rabson } while (message_context);
76*a9148abdSDoug Rabson }
77*a9148abdSDoug Rabson }
78*a9148abdSDoug Rabson
79*a9148abdSDoug Rabson int
main(int argc,char ** argv)80*a9148abdSDoug Rabson main(int argc, char **argv)
81*a9148abdSDoug Rabson {
82*a9148abdSDoug Rabson struct module_stat stat;
83*a9148abdSDoug Rabson int mod;
84*a9148abdSDoug Rabson int syscall_num;
85*a9148abdSDoug Rabson
86*a9148abdSDoug Rabson stat.version = sizeof(stat);
87*a9148abdSDoug Rabson mod = modfind("gsstest_syscall");
88*a9148abdSDoug Rabson if (mod < 0) {
89*a9148abdSDoug Rabson fprintf(stderr, "%s: kernel support not present\n", argv[0]);
90*a9148abdSDoug Rabson exit(1);
91*a9148abdSDoug Rabson }
92*a9148abdSDoug Rabson modstat(mod, &stat);
93*a9148abdSDoug Rabson syscall_num = stat.data.intval;
94*a9148abdSDoug Rabson
95*a9148abdSDoug Rabson switch (atoi(argv[1])) {
96*a9148abdSDoug Rabson case 1:
97*a9148abdSDoug Rabson syscall(syscall_num, 1, NULL, NULL);
98*a9148abdSDoug Rabson break;
99*a9148abdSDoug Rabson
100*a9148abdSDoug Rabson case 2: {
101*a9148abdSDoug Rabson struct gsstest_2_args args;
102*a9148abdSDoug Rabson struct gsstest_2_res res;
103*a9148abdSDoug Rabson char hostname[512];
104*a9148abdSDoug Rabson char token_buffer[8192];
105*a9148abdSDoug Rabson OM_uint32 maj_stat, min_stat;
106*a9148abdSDoug Rabson gss_ctx_id_t client_context = GSS_C_NO_CONTEXT;
107*a9148abdSDoug Rabson gss_cred_id_t client_cred;
108*a9148abdSDoug Rabson gss_OID mech_type = GSS_C_NO_OID;
109*a9148abdSDoug Rabson gss_buffer_desc name_buf, message_buf;
110*a9148abdSDoug Rabson gss_name_t name;
111*a9148abdSDoug Rabson int32_t enctypes[] = {
112*a9148abdSDoug Rabson ETYPE_DES_CBC_CRC,
113*a9148abdSDoug Rabson ETYPE_ARCFOUR_HMAC_MD5,
114*a9148abdSDoug Rabson ETYPE_ARCFOUR_HMAC_MD5_56,
115*a9148abdSDoug Rabson ETYPE_AES256_CTS_HMAC_SHA1_96,
116*a9148abdSDoug Rabson ETYPE_AES128_CTS_HMAC_SHA1_96,
117*a9148abdSDoug Rabson ETYPE_DES3_CBC_SHA1,
118*a9148abdSDoug Rabson };
119*a9148abdSDoug Rabson int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
120*a9148abdSDoug Rabson int established;
121*a9148abdSDoug Rabson int i;
122*a9148abdSDoug Rabson
123*a9148abdSDoug Rabson for (i = 0; i < num_enctypes; i++) {
124*a9148abdSDoug Rabson printf("testing etype %d\n", enctypes[i]);
125*a9148abdSDoug Rabson args.output_token.length = sizeof(token_buffer);
126*a9148abdSDoug Rabson args.output_token.value = token_buffer;
127*a9148abdSDoug Rabson
128*a9148abdSDoug Rabson gethostname(hostname, sizeof(hostname));
129*a9148abdSDoug Rabson snprintf(token_buffer, sizeof(token_buffer),
130*a9148abdSDoug Rabson "nfs@%s", hostname);
131*a9148abdSDoug Rabson name_buf.length = strlen(token_buffer);
132*a9148abdSDoug Rabson name_buf.value = token_buffer;
133*a9148abdSDoug Rabson maj_stat = gss_import_name(&min_stat, &name_buf,
134*a9148abdSDoug Rabson GSS_C_NT_HOSTBASED_SERVICE, &name);
135*a9148abdSDoug Rabson if (GSS_ERROR(maj_stat)) {
136*a9148abdSDoug Rabson printf("gss_import_name failed\n");
137*a9148abdSDoug Rabson report_error(mech_type, maj_stat, min_stat);
138*a9148abdSDoug Rabson goto out;
139*a9148abdSDoug Rabson }
140*a9148abdSDoug Rabson
141*a9148abdSDoug Rabson maj_stat = gss_acquire_cred(&min_stat, GSS_C_NO_NAME,
142*a9148abdSDoug Rabson 0, GSS_C_NO_OID_SET, GSS_C_INITIATE, &client_cred,
143*a9148abdSDoug Rabson NULL, NULL);
144*a9148abdSDoug Rabson if (GSS_ERROR(maj_stat)) {
145*a9148abdSDoug Rabson printf("gss_acquire_cred (client) failed\n");
146*a9148abdSDoug Rabson report_error(mech_type, maj_stat, min_stat);
147*a9148abdSDoug Rabson goto out;
148*a9148abdSDoug Rabson }
149*a9148abdSDoug Rabson
150*a9148abdSDoug Rabson maj_stat = gss_krb5_set_allowable_enctypes(&min_stat,
151*a9148abdSDoug Rabson client_cred, 1, &enctypes[i]);
152*a9148abdSDoug Rabson if (GSS_ERROR(maj_stat)) {
153*a9148abdSDoug Rabson printf("gss_krb5_set_allowable_enctypes failed\n");
154*a9148abdSDoug Rabson report_error(mech_type, maj_stat, min_stat);
155*a9148abdSDoug Rabson goto out;
156*a9148abdSDoug Rabson }
157*a9148abdSDoug Rabson
158*a9148abdSDoug Rabson res.output_token.length = 0;
159*a9148abdSDoug Rabson res.output_token.value = 0;
160*a9148abdSDoug Rabson established = 0;
161*a9148abdSDoug Rabson while (!established) {
162*a9148abdSDoug Rabson maj_stat = gss_init_sec_context(&min_stat,
163*a9148abdSDoug Rabson client_cred,
164*a9148abdSDoug Rabson &client_context,
165*a9148abdSDoug Rabson name,
166*a9148abdSDoug Rabson GSS_C_NO_OID,
167*a9148abdSDoug Rabson (GSS_C_MUTUAL_FLAG
168*a9148abdSDoug Rabson |GSS_C_CONF_FLAG
169*a9148abdSDoug Rabson |GSS_C_INTEG_FLAG
170*a9148abdSDoug Rabson |GSS_C_SEQUENCE_FLAG
171*a9148abdSDoug Rabson |GSS_C_REPLAY_FLAG),
172*a9148abdSDoug Rabson 0,
173*a9148abdSDoug Rabson GSS_C_NO_CHANNEL_BINDINGS,
174*a9148abdSDoug Rabson &res.output_token,
175*a9148abdSDoug Rabson &mech_type,
176*a9148abdSDoug Rabson &args.input_token,
177*a9148abdSDoug Rabson NULL,
178*a9148abdSDoug Rabson NULL);
179*a9148abdSDoug Rabson if (GSS_ERROR(maj_stat)) {
180*a9148abdSDoug Rabson printf("gss_init_sec_context failed\n");
181*a9148abdSDoug Rabson report_error(mech_type, maj_stat, min_stat);
182*a9148abdSDoug Rabson goto out;
183*a9148abdSDoug Rabson }
184*a9148abdSDoug Rabson if (args.input_token.length) {
185*a9148abdSDoug Rabson args.step = 1;
186*a9148abdSDoug Rabson syscall(syscall_num, 2, &args, &res);
187*a9148abdSDoug Rabson gss_release_buffer(&min_stat,
188*a9148abdSDoug Rabson &args.input_token);
189*a9148abdSDoug Rabson if (res.maj_stat != GSS_S_COMPLETE
190*a9148abdSDoug Rabson && res.maj_stat != GSS_S_CONTINUE_NEEDED) {
191*a9148abdSDoug Rabson printf("gss_accept_sec_context (kernel) failed\n");
192*a9148abdSDoug Rabson report_error(mech_type, res.maj_stat,
193*a9148abdSDoug Rabson res.min_stat);
194*a9148abdSDoug Rabson goto out;
195*a9148abdSDoug Rabson }
196*a9148abdSDoug Rabson }
197*a9148abdSDoug Rabson if (maj_stat == GSS_S_COMPLETE)
198*a9148abdSDoug Rabson established = 1;
199*a9148abdSDoug Rabson }
200*a9148abdSDoug Rabson
201*a9148abdSDoug Rabson message_buf.value = "Hello world";
202*a9148abdSDoug Rabson message_buf.length = strlen((char *) message_buf.value);
203*a9148abdSDoug Rabson
204*a9148abdSDoug Rabson maj_stat = gss_get_mic(&min_stat, client_context,
205*a9148abdSDoug Rabson GSS_C_QOP_DEFAULT, &message_buf, &args.input_token);
206*a9148abdSDoug Rabson if (GSS_ERROR(maj_stat)) {
207*a9148abdSDoug Rabson printf("gss_get_mic failed\n");
208*a9148abdSDoug Rabson report_error(mech_type, maj_stat, min_stat);
209*a9148abdSDoug Rabson goto out;
210*a9148abdSDoug Rabson }
211*a9148abdSDoug Rabson
212*a9148abdSDoug Rabson args.step = 2;
213*a9148abdSDoug Rabson syscall(syscall_num, 2, &args, &res);
214*a9148abdSDoug Rabson gss_release_buffer(&min_stat, &args.input_token);
215*a9148abdSDoug Rabson if (GSS_ERROR(res.maj_stat)) {
216*a9148abdSDoug Rabson printf("kernel gss_verify_mic failed\n");
217*a9148abdSDoug Rabson report_error(mech_type, res.maj_stat, res.min_stat);
218*a9148abdSDoug Rabson goto out;
219*a9148abdSDoug Rabson }
220*a9148abdSDoug Rabson
221*a9148abdSDoug Rabson maj_stat = gss_verify_mic(&min_stat, client_context,
222*a9148abdSDoug Rabson &message_buf, &res.output_token, NULL);
223*a9148abdSDoug Rabson if (GSS_ERROR(maj_stat)) {
224*a9148abdSDoug Rabson printf("gss_verify_mic failed\n");
225*a9148abdSDoug Rabson report_error(mech_type, maj_stat, min_stat);
226*a9148abdSDoug Rabson goto out;
227*a9148abdSDoug Rabson }
228*a9148abdSDoug Rabson
229*a9148abdSDoug Rabson maj_stat = gss_wrap(&min_stat, client_context,
230*a9148abdSDoug Rabson TRUE, GSS_C_QOP_DEFAULT, &message_buf, NULL,
231*a9148abdSDoug Rabson &args.input_token);
232*a9148abdSDoug Rabson if (GSS_ERROR(maj_stat)) {
233*a9148abdSDoug Rabson printf("gss_wrap failed\n");
234*a9148abdSDoug Rabson report_error(mech_type, maj_stat, min_stat);
235*a9148abdSDoug Rabson goto out;
236*a9148abdSDoug Rabson }
237*a9148abdSDoug Rabson
238*a9148abdSDoug Rabson args.step = 3;
239*a9148abdSDoug Rabson syscall(syscall_num, 2, &args, &res);
240*a9148abdSDoug Rabson gss_release_buffer(&min_stat, &args.input_token);
241*a9148abdSDoug Rabson if (GSS_ERROR(res.maj_stat)) {
242*a9148abdSDoug Rabson printf("kernel gss_unwrap failed\n");
243*a9148abdSDoug Rabson report_error(mech_type, res.maj_stat, res.min_stat);
244*a9148abdSDoug Rabson goto out;
245*a9148abdSDoug Rabson }
246*a9148abdSDoug Rabson
247*a9148abdSDoug Rabson maj_stat = gss_unwrap(&min_stat, client_context,
248*a9148abdSDoug Rabson &res.output_token, &message_buf, NULL, NULL);
249*a9148abdSDoug Rabson if (GSS_ERROR(maj_stat)) {
250*a9148abdSDoug Rabson printf("gss_unwrap failed\n");
251*a9148abdSDoug Rabson report_error(mech_type, maj_stat, min_stat);
252*a9148abdSDoug Rabson goto out;
253*a9148abdSDoug Rabson }
254*a9148abdSDoug Rabson gss_release_buffer(&min_stat, &message_buf);
255*a9148abdSDoug Rabson
256*a9148abdSDoug Rabson maj_stat = gss_wrap(&min_stat, client_context,
257*a9148abdSDoug Rabson FALSE, GSS_C_QOP_DEFAULT, &message_buf, NULL,
258*a9148abdSDoug Rabson &args.input_token);
259*a9148abdSDoug Rabson if (GSS_ERROR(maj_stat)) {
260*a9148abdSDoug Rabson printf("gss_wrap failed\n");
261*a9148abdSDoug Rabson report_error(mech_type, maj_stat, min_stat);
262*a9148abdSDoug Rabson goto out;
263*a9148abdSDoug Rabson }
264*a9148abdSDoug Rabson
265*a9148abdSDoug Rabson args.step = 4;
266*a9148abdSDoug Rabson syscall(syscall_num, 2, &args, &res);
267*a9148abdSDoug Rabson gss_release_buffer(&min_stat, &args.input_token);
268*a9148abdSDoug Rabson if (GSS_ERROR(res.maj_stat)) {
269*a9148abdSDoug Rabson printf("kernel gss_unwrap failed\n");
270*a9148abdSDoug Rabson report_error(mech_type, res.maj_stat, res.min_stat);
271*a9148abdSDoug Rabson goto out;
272*a9148abdSDoug Rabson }
273*a9148abdSDoug Rabson
274*a9148abdSDoug Rabson maj_stat = gss_unwrap(&min_stat, client_context,
275*a9148abdSDoug Rabson &res.output_token, &message_buf, NULL, NULL);
276*a9148abdSDoug Rabson if (GSS_ERROR(maj_stat)) {
277*a9148abdSDoug Rabson printf("gss_unwrap failed\n");
278*a9148abdSDoug Rabson report_error(mech_type, maj_stat, min_stat);
279*a9148abdSDoug Rabson goto out;
280*a9148abdSDoug Rabson }
281*a9148abdSDoug Rabson gss_release_buffer(&min_stat, &message_buf);
282*a9148abdSDoug Rabson
283*a9148abdSDoug Rabson args.step = 5;
284*a9148abdSDoug Rabson syscall(syscall_num, 2, &args, &res);
285*a9148abdSDoug Rabson
286*a9148abdSDoug Rabson gss_release_name(&min_stat, &name);
287*a9148abdSDoug Rabson gss_release_cred(&min_stat, &client_cred);
288*a9148abdSDoug Rabson gss_delete_sec_context(&min_stat, &client_context,
289*a9148abdSDoug Rabson GSS_C_NO_BUFFER);
290*a9148abdSDoug Rabson }
291*a9148abdSDoug Rabson
292*a9148abdSDoug Rabson break;
293*a9148abdSDoug Rabson }
294*a9148abdSDoug Rabson case 3:
295*a9148abdSDoug Rabson syscall(syscall_num, 3, NULL, NULL);
296*a9148abdSDoug Rabson break;
297*a9148abdSDoug Rabson case 4:
298*a9148abdSDoug Rabson syscall(syscall_num, 4, NULL, NULL);
299*a9148abdSDoug Rabson break;
300*a9148abdSDoug Rabson }
301*a9148abdSDoug Rabson return (0);
302*a9148abdSDoug Rabson
303*a9148abdSDoug Rabson out:
304*a9148abdSDoug Rabson return (1);
305*a9148abdSDoug Rabson }
306