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