1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
14 * Copyright 2021 Tintri by DDN, Inc. All rights reserved.
15 */
16
17 /*
18 * Test connecting to an NFSv4 server with Kerberos auth.
19 */
20
21 #include <stdlib.h>
22 #include <strings.h>
23 #include <rpc/rpc.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <gssapi/gssapi_ext.h>
27
28 #include "rpcsvc/nfs4_prot.h"
29
30 int nfs4_skip_bytes;
31
32 int
main(int argc,char * argv[])33 main(int argc, char *argv[])
34 {
35 CLIENT *client;
36 AUTH *auth;
37 COMPOUND4args args;
38 COMPOUND4res res;
39 enum clnt_stat status;
40 struct timeval timeout;
41 nfs_argop4 arg[1] = {0};
42 char *tag = "RPCSEC_GSS test";
43 char *host;
44 char *ip = NULL;
45 char *slp = NULL;
46 char svc_name[256];
47 ulong_t sleep_time = 0;
48 rpc_gss_options_ret_t opt_ret = {0};
49
50 if (argc < 2) {
51 fprintf(stderr,
52 "usage: %s [-I IP] hostname <seconds to sleep>\n", argv[0]);
53 return (-1);
54 }
55
56 if (strcmp(argv[1], "-I") == 0) {
57 if (argc < 4) {
58 fprintf(stderr, "-I needs an arg\n");
59 return (-3);
60 }
61 ip = argv[2];
62 host = argv[3];
63 if (argc > 4)
64 slp = argv[4];
65 } else {
66 host = ip = argv[1];
67 if (argc > 2)
68 slp = argv[2];
69 }
70
71 if (slp != NULL) {
72 errno = 0;
73 sleep_time = strtoul(argv[2], NULL, 0);
74 if (errno != 0) {
75 perror("failed to convert seconds string");
76 return (-2);
77 }
78 }
79
80 timeout.tv_sec = 30;
81 timeout.tv_usec = 0;
82
83 client = clnt_create(ip, NFS4_PROGRAM, NFS_V4, "tcp");
84 if (client == NULL) {
85 clnt_pcreateerror("test");
86 fprintf(stderr, "clnt_create failed\n");
87 return (1);
88 }
89
90 (void) snprintf(svc_name, sizeof (svc_name), "nfs@%s", host);
91 if ((auth = rpc_gss_seccreate(client, svc_name, "kerberos_v5",
92 rpc_gss_svc_none, "default", NULL, &opt_ret)) == NULL) {
93 uint32_t disp_major, disp_minor, msg_ctx = 0;
94 gss_buffer_desc errstr = {0};
95 rpc_gss_error_t rpcerr = {0};
96
97 fprintf(stderr, "creating GSS ctx failed\n");
98
99 rpc_gss_get_error(&rpcerr);
100 if (rpcerr.rpc_gss_error != 0) {
101 fprintf(stderr, "failed with errno %d\n",
102 rpcerr.system_error);
103 }
104
105 if (!GSS_ERROR(opt_ret.major_status)) {
106 fprintf(stderr, "no GSS error info\n");
107 return (2);
108 }
109
110 do {
111 disp_major = gss_display_status(&disp_minor,
112 opt_ret.major_status, GSS_C_GSS_CODE,
113 GSS_C_NULL_OID, &msg_ctx, &errstr);
114 if (!GSS_ERROR(disp_major) && errstr.length != 0) {
115 fprintf(stderr, "major: %s\n", errstr.value);
116 (void) gss_release_buffer(&disp_minor, &errstr);
117 } else {
118 fprintf(stderr,
119 "gss_display_status() failed with "
120 "0x%x:0x%x", disp_major, disp_minor);
121 }
122 } while (!GSS_ERROR(disp_major) && msg_ctx != 0);
123
124 if (opt_ret.minor_status == 0)
125 return (2);
126
127 do {
128 disp_major = gss_display_status(&disp_minor,
129 opt_ret.minor_status, GSS_C_MECH_CODE,
130 GSS_C_NULL_OID, &msg_ctx, &errstr);
131 if (!GSS_ERROR(disp_major) && errstr.length != 0) {
132 fprintf(stderr, "minor: %s\n", errstr.value);
133 (void) gss_release_buffer(&disp_minor, &errstr);
134 } else {
135 fprintf(stderr,
136 "gss_display_status() failed with "
137 "0x%x:0x%x", disp_major, disp_minor);
138 }
139 } while (!GSS_ERROR(disp_major) && msg_ctx != 0);
140
141 return (2);
142 }
143
144 client->cl_auth = auth;
145
146 args.minorversion = 0;
147 args.tag.utf8string_len = strlen(tag);
148 args.tag.utf8string_val = tag;
149 args.argarray.argarray_len = sizeof (arg) / sizeof (nfs_argop4);
150 args.argarray.argarray_val = arg;
151
152 arg[0].argop = OP_SETCLIENTID;
153 /* leaving arg[0].nfs_argop4_u.opsetclientid as-is */
154
155 bzero(&res, sizeof (res));
156
157 status = clnt_call(client, NFSPROC4_COMPOUND,
158 xdr_COMPOUND4args, (caddr_t)&args,
159 xdr_COMPOUND4res, (caddr_t)&res,
160 timeout);
161 if (status != RPC_SUCCESS) {
162 clnt_perror(client, "test");
163 fprintf(stderr, "clnt_call failed\n");
164 return (2);
165 }
166
167 if (sleep_time != 0)
168 (void) sleep(sleep_time);
169
170 fprintf(stderr, "success!\n");
171 return (0);
172 }
173