xref: /illumos-gate/usr/src/cmd/fs.d/nfs/tests/rpcsec_gss_conn/rpcsec_gss_conn.c (revision 851677fbe21ab9cad62cea9e299167ea661fd1c8)
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
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