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