]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - tools/regression/rpcsec_gss/rpctest.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / tools / regression / rpcsec_gss / rpctest.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  * $FreeBSD$
28  */
29
30 #ifdef __FreeBSD__
31 #include <sys/cdefs.h>
32 #else
33 #define __unused
34 #endif
35
36 #include <ctype.h>
37 #include <err.h>
38 #include <netdb.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43
44 #include <rpc/rpc.h>
45 #include <rpc/rpcsec_gss.h>
46
47 static rpc_gss_principal_t server_acl = NULL;
48
49 static void
50 usage(void)
51 {
52         printf("rpctest client | server\n");
53         exit(1);
54 }
55
56 static void
57 print_principal(rpc_gss_principal_t principal)
58 {
59         int i, len, n;
60         uint8_t *p;
61
62         len = principal->len;
63         p = (uint8_t *) principal->name;
64         while (len > 0) {
65                 n = len;
66                 if (n > 16)
67                         n = 16;
68                 for (i = 0; i < n; i++)
69                         printf("%02x ", p[i]);
70                 for (; i < 16; i++)
71                         printf("   ");
72                 printf("|");
73                 for (i = 0; i < n; i++)
74                         printf("%c", isprint(p[i]) ? p[i] : '.');
75                 printf("|\n");
76                 len -= n;
77                 p += n;
78         }
79 }
80
81 static void
82 test_client(int argc, const char **argv)
83 {
84         rpcproc_t prog = 123456;
85         rpcvers_t vers = 1;
86         const char *netid = "tcp";
87         char hostname[128], service[128+5];
88         CLIENT *client;
89         AUTH *auth;
90         const char **mechs;
91         rpc_gss_options_req_t options_req;
92         rpc_gss_options_ret_t options_ret;
93         rpc_gss_service_t svc;
94         struct timeval tv;
95         enum clnt_stat stat;
96
97         if (argc == 2)
98                 strlcpy(hostname, argv[1], sizeof(hostname));
99         else
100                 gethostname(hostname, sizeof(hostname));
101
102         client = clnt_create(hostname, prog, vers, netid);
103         if (!client) {
104                 printf("rpc_createerr.cf_stat = %d\n",
105                     rpc_createerr.cf_stat);
106                 printf("rpc_createerr.cf_error.re_errno = %d\n",
107                     rpc_createerr.cf_error.re_errno);
108                 return;
109         }
110         
111         strcpy(service, "host");
112         strcat(service, "@");
113         strcat(service, hostname);
114
115         mechs = rpc_gss_get_mechanisms();
116         auth = NULL;
117         while (*mechs) {
118                 options_req.req_flags = GSS_C_MUTUAL_FLAG;
119                 options_req.time_req = 600;
120                 options_req.my_cred = GSS_C_NO_CREDENTIAL;
121                 options_req.input_channel_bindings = NULL;
122                 auth = rpc_gss_seccreate(client, service,
123                     *mechs,
124                     rpc_gss_svc_none,
125                     NULL,
126                     &options_req,
127                     &options_ret);
128                 if (auth)
129                         break;
130                 mechs++;
131         }
132         if (!auth) {
133                 clnt_pcreateerror("rpc_gss_seccreate");
134                 printf("Can't authenticate with server %s.\n",
135                     hostname);
136                 exit(1);
137         }
138         client->cl_auth = auth;
139
140         for (svc = rpc_gss_svc_none; svc <= rpc_gss_svc_privacy; svc++) {
141                 const char *svc_names[] = {
142                         "rpc_gss_svc_default",
143                         "rpc_gss_svc_none",
144                         "rpc_gss_svc_integrity",
145                         "rpc_gss_svc_privacy"
146                 };
147                 int num;
148
149                 rpc_gss_set_defaults(auth, svc, NULL);
150                 tv.tv_sec = 5;
151                 tv.tv_usec = 0;
152                 num = 42;
153                 stat = CLNT_CALL(client, 1,
154                     (xdrproc_t) xdr_int, (char *) &num,
155                     (xdrproc_t) xdr_int, (char *) &num, tv);
156                 if (stat == RPC_SUCCESS) {
157                         printf("succeeded with %s\n", svc_names[svc]);
158                         if (num != 142)
159                                 printf("unexpected reply %d\n", num);
160                 } else {
161                         clnt_perror(client, "call failed");
162                 }
163         }
164         AUTH_DESTROY(auth);
165         CLNT_DESTROY(client);
166 }
167
168 static void
169 server_program_1(struct svc_req *rqstp, register SVCXPRT *transp)
170 {
171         rpc_gss_rawcred_t *rcred;
172         rpc_gss_ucred_t *ucred;
173         int             i, num;
174
175         if (rqstp->rq_cred.oa_flavor != RPCSEC_GSS) {
176                 svcerr_weakauth(transp);
177                 return;
178         }               
179                 
180         if (!rpc_gss_getcred(rqstp, &rcred, &ucred, NULL)) {
181                 svcerr_systemerr(transp);
182                 return;
183         }
184
185         printf("svc=%d, mech=%s, uid=%d, gid=%d, gids={",
186             rcred->service, rcred->mechanism, ucred->uid, ucred->gid);
187         for (i = 0; i < ucred->gidlen; i++) {
188                 if (i > 0) printf(",");
189                 printf("%d", ucred->gidlist[i]);
190         }
191         printf("}\n");
192
193         switch (rqstp->rq_proc) {
194         case 0:
195                 if (!svc_getargs(transp, (xdrproc_t) xdr_void, 0)) {
196                         svcerr_decode(transp);
197                         goto out;
198                 }
199                 if (!svc_sendreply(transp, (xdrproc_t) xdr_void, 0)) {
200                         svcerr_systemerr(transp);
201                 }
202                 goto out;
203
204         case 1:
205                 if (!svc_getargs(transp, (xdrproc_t) xdr_int,
206                         (char *) &num)) {
207                         svcerr_decode(transp);
208                         goto out;
209                 }
210                 num += 100;
211                 if (!svc_sendreply(transp, (xdrproc_t) xdr_int,
212                         (char *) &num)) {
213                         svcerr_systemerr(transp);
214                 }
215                 goto out;
216
217         default:
218                 svcerr_noproc(transp);
219                 goto out;
220         }
221
222 out:
223         return;
224 }
225
226 #if 0
227 static void
228 report_error(gss_OID mech, OM_uint32 maj, OM_uint32 min)
229 {
230         OM_uint32 maj_stat, min_stat;
231         OM_uint32 message_context;
232         gss_buffer_desc buf;
233
234         printf("major_stat=%d, minor_stat=%d\n", maj, min);
235
236         message_context = 0;
237         do {
238                 maj_stat = gss_display_status(&min_stat, maj,
239                     GSS_C_GSS_CODE, GSS_C_NO_OID, &message_context, &buf);
240                 printf("%.*s\n", (int)buf.length, (char *) buf.value);
241                 gss_release_buffer(&min_stat, &buf);
242         } while (message_context);
243         if (mech) {
244                 message_context = 0;
245                 do {
246                         maj_stat = gss_display_status(&min_stat, min,
247                             GSS_C_MECH_CODE, mech, &message_context, &buf);
248                         printf("%.*s\n", (int)buf.length, (char *) buf.value);
249                         gss_release_buffer(&min_stat, &buf);
250                 } while (message_context);
251         }
252         exit(1);
253 }
254 #endif
255
256 static bool_t
257 server_new_context(__unused struct svc_req *req,
258     __unused gss_cred_id_t deleg,
259     __unused gss_ctx_id_t gss_context,
260     rpc_gss_lock_t *lock,
261     __unused void **cookie)
262 {
263         rpc_gss_rawcred_t *rcred = lock->raw_cred;
264
265         printf("new security context version=%d, mech=%s, qop=%s:\n",
266             rcred->version, rcred->mechanism, rcred->qop);
267         print_principal(rcred->client_principal);
268
269         if (!server_acl)
270                 return (TRUE);
271
272         if (rcred->client_principal->len != server_acl->len
273             || memcmp(rcred->client_principal->name, server_acl->name,
274                 server_acl->len)) {
275                 return (FALSE);
276         }
277
278         return (TRUE);
279 }
280
281 static void
282 test_server(__unused int argc, __unused const char **argv)
283 {
284         char hostname[128];
285         char principal[128 + 5];
286         const char **mechs;
287         static rpc_gss_callback_t cb;
288
289         if (argc == 3) {
290                 if (!rpc_gss_get_principal_name(&server_acl, argv[1],
291                         argv[2], NULL, NULL)) {
292                         printf("Can't create %s ACL entry for %s\n",
293                             argv[1], argv[2]);
294                         return;
295                 }
296         }
297
298         gethostname(hostname, sizeof(hostname));;
299         snprintf(principal, sizeof(principal), "host@%s", hostname);
300
301         mechs = rpc_gss_get_mechanisms();
302         while (*mechs) {
303                 if (!rpc_gss_set_svc_name(principal, *mechs, GSS_C_INDEFINITE,
304                         123456, 1)) {
305                         rpc_gss_error_t e;
306
307                         rpc_gss_get_error(&e);
308                         printf("setting name for %s for %s failed: %d, %d\n",
309                             principal, *mechs,
310                              e.rpc_gss_error, e.system_error);
311
312 #if 0
313                         gss_OID mech_oid;
314                         gss_OID_set_desc oid_set;
315                         gss_name_t name;
316                         OM_uint32 maj_stat, min_stat;
317                         gss_buffer_desc namebuf;
318                         gss_cred_id_t cred;
319
320                         rpc_gss_mech_to_oid(*mechs, &mech_oid);
321                         oid_set.count = 1;
322                         oid_set.elements = mech_oid;
323
324                         namebuf.value = principal;
325                         namebuf.length = strlen(principal);
326                         maj_stat = gss_import_name(&min_stat, &namebuf,
327                             GSS_C_NT_HOSTBASED_SERVICE, &name);
328                         if (maj_stat) {
329                                 printf("gss_import_name failed\n");
330                                 report_error(mech_oid, maj_stat, min_stat);
331                         }
332                         maj_stat = gss_acquire_cred(&min_stat, name,
333                             0, &oid_set, GSS_C_ACCEPT, &cred, NULL, NULL);
334                         if (maj_stat) {
335                                 printf("gss_acquire_cred failed\n");
336                                 report_error(mech_oid, maj_stat, min_stat);
337                         }
338 #endif
339                 }
340                 mechs++;
341         }
342
343         cb.program = 123456;
344         cb.version = 1;
345         cb.callback = server_new_context;
346         rpc_gss_set_callback(&cb);
347
348         svc_create(server_program_1, 123456, 1, 0);
349         svc_run();
350 }
351
352 static void
353 test_get_principal_name(int argc, const char **argv)
354 {
355         const char *mechname, *name, *node, *domain;
356         rpc_gss_principal_t principal;
357
358         if (argc < 3 || argc > 5) {
359                 printf("usage: rpctest principal <mechname> <name> "
360                     "[<node> [<domain>] ]\n");
361                 exit(1);
362         }
363
364         mechname = argv[1];
365         name = argv[2];
366         node = NULL;
367         domain = NULL;
368         if (argc > 3) {
369                 node = argv[3];
370                 if (argc > 4)
371                         domain = argv[4];
372         }
373
374         if (rpc_gss_get_principal_name(&principal, mechname, name,
375                 node, domain)) {
376                 printf("succeeded:\n");
377                 print_principal(principal);
378                 free(principal);
379         } else {
380                 printf("failed\n");
381         }
382 }
383
384 int
385 main(int argc, const char **argv)
386 {
387
388         if (argc < 2)
389                 usage();
390         if (!strcmp(argv[1], "client"))
391                 test_client(argc - 1, argv + 1);
392         else if (!strcmp(argv[1], "server"))
393                 test_server(argc - 1, argv + 1);
394         else if (!strcmp(argv[1], "principal"))
395                 test_get_principal_name(argc - 1, argv + 1);
396         else
397                 usage();
398
399         return (0);
400 }