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>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
31 #include <sys/cdefs.h>
45 #include <rpc/rpcsec_gss.h>
47 static rpc_gss_principal_t server_acl = NULL;
52 printf("rpctest client | server\n");
57 print_principal(rpc_gss_principal_t principal)
63 p = (uint8_t *) principal->name;
68 for (i = 0; i < n; i++)
69 printf("%02x ", p[i]);
73 for (i = 0; i < n; i++)
74 printf("%c", isprint(p[i]) ? p[i] : '.');
82 test_client(int argc, const char **argv)
84 rpcproc_t prog = 123456;
86 const char *netid = "tcp";
87 char hostname[128], service[128+5];
91 rpc_gss_options_req_t options_req;
92 rpc_gss_options_ret_t options_ret;
93 rpc_gss_service_t svc;
98 strlcpy(hostname, argv[1], sizeof(hostname));
100 gethostname(hostname, sizeof(hostname));
102 client = clnt_create(hostname, prog, vers, netid);
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);
111 strcpy(service, "host");
112 strcat(service, "@");
113 strcat(service, hostname);
115 mechs = rpc_gss_get_mechanisms();
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,
133 clnt_pcreateerror("rpc_gss_seccreate");
134 printf("Can't authenticate with server %s.\n",
138 client->cl_auth = auth;
140 for (svc = rpc_gss_svc_none; svc <= rpc_gss_svc_privacy; svc++) {
141 const char *svc_names[] = {
142 "rpc_gss_svc_default",
144 "rpc_gss_svc_integrity",
145 "rpc_gss_svc_privacy"
149 rpc_gss_set_defaults(auth, svc, NULL);
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]);
159 printf("unexpected reply %d\n", num);
161 clnt_perror(client, "call failed");
165 CLNT_DESTROY(client);
169 server_program_1(struct svc_req *rqstp, register SVCXPRT *transp)
171 rpc_gss_rawcred_t *rcred;
172 rpc_gss_ucred_t *ucred;
175 if (rqstp->rq_cred.oa_flavor != RPCSEC_GSS) {
176 svcerr_weakauth(transp);
180 if (!rpc_gss_getcred(rqstp, &rcred, &ucred, NULL)) {
181 svcerr_systemerr(transp);
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]);
193 switch (rqstp->rq_proc) {
195 if (!svc_getargs(transp, (xdrproc_t) xdr_void, 0)) {
196 svcerr_decode(transp);
199 if (!svc_sendreply(transp, (xdrproc_t) xdr_void, 0)) {
200 svcerr_systemerr(transp);
205 if (!svc_getargs(transp, (xdrproc_t) xdr_int,
207 svcerr_decode(transp);
211 if (!svc_sendreply(transp, (xdrproc_t) xdr_int,
213 svcerr_systemerr(transp);
218 svcerr_noproc(transp);
228 report_error(gss_OID mech, OM_uint32 maj, OM_uint32 min)
230 OM_uint32 maj_stat, min_stat;
231 OM_uint32 message_context;
234 printf("major_stat=%d, minor_stat=%d\n", maj, min);
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);
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);
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)
263 rpc_gss_rawcred_t *rcred = lock->raw_cred;
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);
272 if (rcred->client_principal->len != server_acl->len
273 || memcmp(rcred->client_principal->name, server_acl->name,
282 test_server(__unused int argc, __unused const char **argv)
285 char principal[128 + 5];
287 static rpc_gss_callback_t cb;
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",
298 gethostname(hostname, sizeof(hostname));;
299 snprintf(principal, sizeof(principal), "host@%s", hostname);
301 mechs = rpc_gss_get_mechanisms();
303 if (!rpc_gss_set_svc_name(principal, *mechs, GSS_C_INDEFINITE,
307 rpc_gss_get_error(&e);
308 printf("setting name for %s for %s failed: %d, %d\n",
310 e.rpc_gss_error, e.system_error);
314 gss_OID_set_desc oid_set;
316 OM_uint32 maj_stat, min_stat;
317 gss_buffer_desc namebuf;
320 rpc_gss_mech_to_oid(*mechs, &mech_oid);
322 oid_set.elements = mech_oid;
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);
329 printf("gss_import_name failed\n");
330 report_error(mech_oid, maj_stat, min_stat);
332 maj_stat = gss_acquire_cred(&min_stat, name,
333 0, &oid_set, GSS_C_ACCEPT, &cred, NULL, NULL);
335 printf("gss_acquire_cred failed\n");
336 report_error(mech_oid, maj_stat, min_stat);
345 cb.callback = server_new_context;
346 rpc_gss_set_callback(&cb);
348 svc_create(server_program_1, 123456, 1, 0);
353 test_get_principal_name(int argc, const char **argv)
355 const char *mechname, *name, *node, *domain;
356 rpc_gss_principal_t principal;
358 if (argc < 3 || argc > 5) {
359 printf("usage: rpctest principal <mechname> <name> "
360 "[<node> [<domain>] ]\n");
374 if (rpc_gss_get_principal_name(&principal, mechname, name,
376 printf("succeeded:\n");
377 print_principal(principal);
385 main(int argc, const char **argv)
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);