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