# # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Copyright 2022 Tintri by DDN, Inc. All rights reserved. # include $(SRC)/Makefile.master SUBDIRS = rpcsec_gss_conn test_svc_tp_create all: TARGET= all install: TARGET= install clean: TARGET= clean clobber: TARGET= clobber catalog: TARGET= catalog .KEEP_STATE: .PARALLEL: $(SUBDIRS) all install clean clobber: $(SUBDIRS) catalog: $(SUBDIRS) $(RM) $(POFILE) cat $(POFILES) > $(POFILE) $(SUBDIRS): FRC @cd $@; pwd; $(MAKE) $(TARGET) FRC: # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License, Version 1.0 only # (the "License"). You may not use this file except in compliance # with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2004 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Copyright (c) 2018, Joyent, Inc. # Copyright 2022 Tintri by DDN, Inc. All rights reserved. # FSTYPE= nfs include $(SRC)/cmd/fs.d/Makefile.fstype CFLAGS += $(CCVERBOSE) SRCS= $(LIBPROG:%=%.c) # message catalog catalog: $(LIBPROG): $(OBJS) $(LINK.c) -o $@ $(OBJS) $(LDLIBS) $(POST_PROCESS) clean: $(RM) $(OBJS) # # This file and its contents are supplied under the terms of the # Common Development and Distribution License ("CDDL"), version 1.0. # You may only use this file in accordance with the terms of version # 1.0 of the CDDL. # # A full copy of the text of the CDDL should have accompanied this # source. A copy of the CDDL is also available via the Internet at # http://www.illumos.org/license/CDDL. # # # Copyright 2022 Tintri by DDN, Inc. All rights reserved. # LIBPROG = rpcsec_gss_conn SNOOPDIR = $(SRC)/cmd/cmd-inet/usr.sbin/snoop SNOOPOBJS = nfs4_xdr.o OBJS = $(LIBPROG:%=%.o) $(SNOOPOBJS) %.o: $(SNOOPDIR)/%.c $(COMPILE.c) -o $@ $< -I$(SNOOPDIR) $(POST_PROCESS_O) include ../Makefile.com CERRWARN += -Wno-switch LDLIBS += -lnsl -lgss /* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Copyright 2021 Tintri by DDN, Inc. All rights reserved. */ /* * Test connecting to an NFSv4 server with Kerberos auth. */ #include #include #include #include #include #include #include "rpcsvc/nfs4_prot.h" int nfs4_skip_bytes; int main(int argc, char *argv[]) { CLIENT *client; AUTH *auth; COMPOUND4args args; COMPOUND4res res; enum clnt_stat status; struct timeval timeout; nfs_argop4 arg[1] = {0}; char *tag = "RPCSEC_GSS test"; char *host; char *ip = NULL; char *slp = NULL; char svc_name[256]; ulong_t sleep_time = 0; rpc_gss_options_ret_t opt_ret = {0}; if (argc < 2) { fprintf(stderr, "usage: %s [-I IP] hostname \n", argv[0]); return (-1); } if (strcmp(argv[1], "-I") == 0) { if (argc < 4) { fprintf(stderr, "-I needs an arg\n"); return (-3); } ip = argv[2]; host = argv[3]; if (argc > 4) slp = argv[4]; } else { host = ip = argv[1]; if (argc > 2) slp = argv[2]; } if (slp != NULL) { errno = 0; sleep_time = strtoul(argv[2], NULL, 0); if (errno != 0) { perror("failed to convert seconds string"); return (-2); } } timeout.tv_sec = 30; timeout.tv_usec = 0; client = clnt_create(ip, NFS4_PROGRAM, NFS_V4, "tcp"); if (client == NULL) { clnt_pcreateerror("test"); fprintf(stderr, "clnt_create failed\n"); return (1); } (void) snprintf(svc_name, sizeof (svc_name), "nfs@%s", host); if ((auth = rpc_gss_seccreate(client, svc_name, "kerberos_v5", rpc_gss_svc_none, "default", NULL, &opt_ret)) == NULL) { uint32_t disp_major, disp_minor, msg_ctx = 0; gss_buffer_desc errstr = {0}; rpc_gss_error_t rpcerr = {0}; fprintf(stderr, "creating GSS ctx failed\n"); rpc_gss_get_error(&rpcerr); if (rpcerr.rpc_gss_error != 0) { fprintf(stderr, "failed with errno %d\n", rpcerr.system_error); } if (!GSS_ERROR(opt_ret.major_status)) { fprintf(stderr, "no GSS error info\n"); return (2); } do { disp_major = gss_display_status(&disp_minor, opt_ret.major_status, GSS_C_GSS_CODE, GSS_C_NULL_OID, &msg_ctx, &errstr); if (!GSS_ERROR(disp_major) && errstr.length != 0) { fprintf(stderr, "major: %s\n", errstr.value); (void) gss_release_buffer(&disp_minor, &errstr); } else { fprintf(stderr, "gss_display_status() failed with " "0x%x:0x%x", disp_major, disp_minor); } } while (!GSS_ERROR(disp_major) && msg_ctx != 0); if (opt_ret.minor_status == 0) return (2); do { disp_major = gss_display_status(&disp_minor, opt_ret.minor_status, GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &errstr); if (!GSS_ERROR(disp_major) && errstr.length != 0) { fprintf(stderr, "minor: %s\n", errstr.value); (void) gss_release_buffer(&disp_minor, &errstr); } else { fprintf(stderr, "gss_display_status() failed with " "0x%x:0x%x", disp_major, disp_minor); } } while (!GSS_ERROR(disp_major) && msg_ctx != 0); return (2); } client->cl_auth = auth; args.minorversion = 0; args.tag.utf8string_len = strlen(tag); args.tag.utf8string_val = tag; args.argarray.argarray_len = sizeof (arg) / sizeof (nfs_argop4); args.argarray.argarray_val = arg; arg[0].argop = OP_SETCLIENTID; /* leaving arg[0].nfs_argop4_u.opsetclientid as-is */ bzero(&res, sizeof (res)); status = clnt_call(client, NFSPROC4_COMPOUND, xdr_COMPOUND4args, (caddr_t)&args, xdr_COMPOUND4res, (caddr_t)&res, timeout); if (status != RPC_SUCCESS) { clnt_perror(client, "test"); fprintf(stderr, "clnt_call failed\n"); return (2); } if (sleep_time != 0) (void) sleep(sleep_time); fprintf(stderr, "success!\n"); return (0); } # # This file and its contents are supplied under the terms of the # Common Development and Distribution License ("CDDL"), version 1.0. # You may only use this file in accordance with the terms of version # 1.0 of the CDDL. # # A full copy of the text of the CDDL should have accompanied this # source. A copy of the CDDL is also available via the Internet at # http://www.illumos.org/license/CDDL. # # # Copyright 2022 Tintri by DDN, Inc. All rights reserved. # LIBPROG= test_svc_tp_create OBJS= $(LIBPROG).o include ../Makefile.com # not linted SMATCH=off LDLIBS += -lnsl -lsocket /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2016 by Delphix. All rights reserved. * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * Portions of this source code were derived from Berkeley 4.3 BSD * under license from the Regents of the University of California. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define TESTPROG 987654 uint32_t test_vers_max = 2; uint32_t test_vers_min = 1; int debug; int verbose; int testd_port; static void mysvc(struct svc_req *, SVCXPRT *); static void bind2(void); /* * This function is called for each configured network type to * bind and register our RPC service programs. * * On TCP or UDP, we want to bind TESTPROG on a specific port * (when testd_port is specified) in which case we'll use the * variant of svc_tp_create() that lets us pass a bind address. */ static void test_svc_tp_create(struct netconfig *nconf) { char port_str[8]; struct nd_hostserv hs; struct nd_addrlist *al = NULL; SVCXPRT *xprt = NULL; rpcvers_t vers; vers = test_vers_max; /* * If testd_port is set and this is an inet transport, * bind this service on the specified port. */ if (testd_port != 0 && (strcmp(nconf->nc_protofmly, NC_INET) == 0 || strcmp(nconf->nc_protofmly, NC_INET6) == 0)) { int err; snprintf(port_str, sizeof (port_str), "%u", (unsigned short)testd_port); hs.h_host = HOST_SELF_BIND; hs.h_serv = port_str; err = netdir_getbyname((struct netconfig *)nconf, &hs, &al); if (err == 0 && al != NULL) { xprt = svc_tp_create_addr(mysvc, TESTPROG, vers, nconf, al->n_addrs); netdir_free(al, ND_ADDRLIST); } if (xprt == NULL) { printf("testd: unable to create " "(TESTD,%d) on transport %s (port %d)\n", (int)vers, nconf->nc_netid, testd_port); } /* fall-back to default bind */ } if (xprt == NULL) { /* * Had testd_port=0, or non-inet transport, * or the bind to a specific port failed. * Do a default bind. */ xprt = svc_tp_create(mysvc, TESTPROG, vers, nconf); } if (xprt == NULL) { printf("testd: unable to create " "(TESTD,%d) on transport %s\n", (int)vers, nconf->nc_netid); return; } /* * Register additional versions on this transport. */ while (--vers >= test_vers_min) { if (!svc_reg(xprt, TESTPROG, vers, mysvc, nconf)) { printf("testd: " "failed to register vers %d on %s\n", (int)vers, nconf->nc_netid); } } } static void test_svc_unreg(void) { rpcvers_t vers; for (vers = test_vers_min; vers <= test_vers_max; vers++) svc_unreg(TESTPROG, vers); } int main(int argc, char *argv[]) { int c; bool_t exclbind = TRUE; int tmp; struct netconfig *nconf; NCONF_HANDLE *nc; while ((c = getopt(argc, argv, "dvp:")) != EOF) { switch (c) { case 'd': debug++; break; case 'v': verbose++; break; case 'p': (void) sscanf(optarg, "%d", &tmp); if (tmp < 1 || tmp > UINT16_MAX) { (void) fprintf(stderr, "testd: -P port invalid.\n"); return (1); } testd_port = tmp; break; default: fprintf(stderr, "usage: testd [-v] [-r]\n"); exit(1); } } (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) #define TEXT_DOMAIN "SYS_TEST" #endif (void) textdomain(TEXT_DOMAIN); /* * Prevent our non-priv udp and tcp ports bound w/wildcard addr * from being hijacked by a bind to a more specific addr. */ if (!rpc_control(__RPC_SVC_EXCLBIND_SET, &exclbind)) { fprintf(stderr, "warning: unable to set udp/tcp EXCLBIND\n"); } if (testd_port < 0 || testd_port > UINT16_MAX) { fprintf(stderr, "unable to use specified port\n"); exit(1); } /* * Make sure to unregister any previous versions in case the * user is reconfiguring the server in interesting ways. */ test_svc_unreg(); /* * Enumerate network transports and create service listeners * as appropriate for each. */ if ((nc = setnetconfig()) == NULL) { perror("setnetconfig failed"); return (-1); } while ((nconf = getnetconfig(nc)) != NULL) { /* * Skip things like tpi_raw, invisible... */ if ((nconf->nc_flag & NC_VISIBLE) == 0) continue; if (nconf->nc_semantics != NC_TPI_CLTS && nconf->nc_semantics != NC_TPI_COTS && nconf->nc_semantics != NC_TPI_COTS_ORD) continue; test_svc_tp_create(nconf); } (void) endnetconfig(nc); /* * XXX: Normally would call svc_run() here, but * we just want to check our IP bindings. */ if (testd_port != 0) bind2(); if (debug) { char sysbuf[100]; snprintf(sysbuf, sizeof (sysbuf), "rpcinfo -p |grep %u", TESTPROG); printf("x %s\n", sysbuf); fflush(stdout); system(sysbuf); if (testd_port) { snprintf(sysbuf, sizeof (sysbuf), "netstat -a -f inet -P udp |grep %u", testd_port); printf("x %s\n", sysbuf); fflush(stdout); system(sysbuf); snprintf(sysbuf, sizeof (sysbuf), "netstat -a -f inet -P tcp |grep %u", testd_port); printf("x %s\n", sysbuf); fflush(stdout); system(sysbuf); } } /* cleanup */ test_svc_unreg(); printf("%s complete\n", argv[0]); return (0); } /* * Server procedure switch routine */ static void mysvc(struct svc_req *rq, SVCXPRT *xprt) { switch (rq->rq_proc) { case NULLPROC: errno = 0; (void) svc_sendreply(xprt, xdr_void, (char *)0); return; default: svcerr_noproc(xprt); return; } } struct sockaddr_in addr; /* * The actual test: Try doing a 2nd bind with a specific IP. * The exclusive wildcard bind should prvent this. */ static void bind2(void) { int ret; int sock; addr.sin_family = AF_INET; addr.sin_port = htons(testd_port); addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) { fprintf(stderr, "bind2 socket fail %s\n", strerror(errno)); exit(1); } ret = bind(sock, (struct sockaddr *)&addr, sizeof (addr)); if (ret == -1) { fprintf(stderr, "bind2 bind fail %s (expected) PASS\n", strerror(errno)); close(sock); return; } printf("Oh no, bind2 worked! test FAILED\n"); close(sock); }