diff mbox

[04/11] fedfsc: Convert fedfs-delete-junction to use new libadmin API

Message ID 20131202203240.12541.63866.stgit@seurat.1015granger.net
State Accepted
Headers show

Commit Message

Chuck Lever Dec. 2, 2013, 8:32 p.m. UTC
Add support for AUTH_UNIX and RPCSEC_GSS security.  The tool now
exits with a typical Unix exit status code.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 doc/man/fedfs-delete-junction.8    |  105 ++++++++-------------
 src/fedfsc/fedfs-delete-junction.c |  180 +++++++++++++++++++++---------------
 2 files changed, 144 insertions(+), 141 deletions(-)
diff mbox

Patch

diff --git a/doc/man/fedfs-delete-junction.8 b/doc/man/fedfs-delete-junction.8
index 33a051e..e7b4e7b 100644
--- a/doc/man/fedfs-delete-junction.8
+++ b/doc/man/fedfs-delete-junction.8
@@ -5,7 +5,7 @@ 
 .\"
 
 .\"
-.\" Copyright 2011 Oracle.  All rights reserved.
+.\" Copyright 2011, 2013 Oracle.  All rights reserved.
 .\"
 .\" This file is part of fedfs-utils.
 .\"
@@ -33,6 +33,8 @@  fedfs-delete-junction \- send a FEDFS_DELETE_JUNCTION ADMIN protocol request
 .IR nettype ]
 .RB [ \-h
 .IR hostname ]
+.RB [ \-s
+.IR security ]
 .I path
 .SH INTRODUCTION
 RFC 5716 introduces the Federated File System (FedFS, for short).
@@ -102,70 +104,21 @@  If this option is not specified, the default value is
 See
 .BR rpc (3t)
 for details.
-.SH EXIT CODES
-The remote administration service returns a value that reflects the
-success of the requested operation.
-.TP
-.B FEDFS_OK
-The operation succeeded.
-.TP
-.B FEDFS_ERR_ACCESS
-The caller does not have permission to perform the requested operation
-on the remote server.
-.TP
-.B FEDFS_ERR_BADCHAR
-The pathname contains a character which is not
-supported by the remote server.
-.TP
-.B FEDFS_ERR_BADNAME
-A component of the pathname consisted of valid UTF-8 characters
-supported by the remote server,
-but the name is not supported by the remote server
-as a valid name for the current operation.
-.TP
-.B FEDFS_ERR_NAMETOOLONG
-The length of the pathname exceeds the remote server’s implementation limit.
-.TP
-.B FEDFS_ERR_LOOP
-Too many symbolic links were encountered in resolving the pathname.
-.TP
-.B FEDFS_ERR_BADXDR
-The remote server encountered an XDR decoding error while
-processing the request.
-.TP
-.B FEDFS_ERR_INVAL
-One of the arguments was not valid.
-.TP
-.B FEDFS_ERR_IO
-A hard error occurred on the remote server.
-.TP
-.B FEDFS_ERR_NOSPC
-The requested operation would have caused the remote
-server’s filesystem to exceed some limit (for example, if there is
-a fixed number of junctions per fileset or per server).
-.TP
-.B FEDFS_ERR_NOTJUNCT
-The pathname does not end in a junction.
-.TP
-.B FEDFS_ERR_NOTLOCAL
-The pathname contains a junction in any position other than the last component.
-.TP
-.B FEDFS_ERR_PERM
-The operation was not allowed because the caller is
-either not a privileged user or not the owner of an object that
-would be modified by the operation.
-.TP
-.B FEDFS_ERR_ROFS
-A modifying operation was attempted on a read-only filesystem.
-.TP
-.B FEDFS_ERR_SVRFAULT
-An unanticipated non-protocol error occurred on the remote server.
-.TP
-.B FEDFS_ERR_PATH_TYPE_UNSUPP
-The remote server does not support the specified FedFsPathType value.
-.TP
-.B FEDFS_ERR_NOTSUPP
-The remote server does not support the specified procedure.
+.IP "\fB\-s, \-\-security=\fIflavor\fP"
+Specifies the security flavor to use
+when contacting the remote FedFS ADMIN service.
+Valid flavors are
+.BR sys ,
+.BR unix ,
+.BR krb5 ,
+.BR krb5i ", and"
+.BR krb5p .
+If this option is not specified, the
+.B unix
+flavor is used.
+See the
+.B SECURITY
+section of this man page for details.
 .SH EXAMPLES
 Suppose you are the FedFS administrator of the
 .I example.net
@@ -179,10 +132,30 @@  use:
 .sp
 $ fedfs-delete-junction -h fs.example.net /export/junction1
 .SH SECURITY
-RPCSEC GSSAPI authentication has not yet been implemented for this command.
+By default, or if the
+.B sys
+and
+.B unix
+flavors are specified with the
+.BI \-\-security= flavor
+option, the
+.BR fedfs-create-junction (8)
+command uses AUTH_SYS security for the Remote Procedure Call.
+AUTH_SYS has known weaknesses and should be avoided on untrusted networks.
+.P
+The RPC client uses the Kerberos v5 GSS mechanism
+if a Kerberos security flavor is specified.
+When specifying a Kerberos security flavor,
+the user must first obtain a valid Kerberos ticket using
+.BR kinit (1)
+before running
+.BR fedfs-create-junction (8).
+.P
+The AUTH_NONE security flavor is no longer supported by this implementation.
 .SH "SEE ALSO"
 .BR fedfs (7),
 .BR rpc.fedfsd (8),
+.BR kinit (1),
 .BR rpc (3t)
 .sp
 RFC 5716 for FedFS requirements and overview
diff --git a/src/fedfsc/fedfs-delete-junction.c b/src/fedfsc/fedfs-delete-junction.c
index f2085c5..97bd072 100644
--- a/src/fedfsc/fedfs-delete-junction.c
+++ b/src/fedfsc/fedfs-delete-junction.c
@@ -4,7 +4,7 @@ 
  */
 
 /*
- * Copyright 2010 Oracle.  All rights reserved.
+ * Copyright 2010, 2013 Oracle.  All rights reserved.
  *
  * This file is part of fedfs-utils.
  *
@@ -27,30 +27,25 @@ 
 #include <sys/stat.h>
 
 #include <stdbool.h>
+#include <stdlib.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <errno.h>
 #include <getopt.h>
 #include <locale.h>
 
-#include <rpc/clnt.h>
-
 #include "fedfs.h"
 #include "fedfs_admin.h"
+#include "admin.h"
 #include "nsdb.h"
 #include "junction.h"
 #include "xlog.h"
 #include "gpl-boiler.h"
 
 /**
- * Default RPC request timeout
- */
-static struct timeval fedfs_delete_junction_timeout = { 25, 0 };
-
-/**
  * Short form command line options
  */
-static const char fedfs_delete_junction_opts[] = "?dh:n:";
+static const char fedfs_delete_junction_opts[] = "?dh:n:s:";
 
 /**
  * Long form command line options
@@ -60,6 +55,7 @@  static const struct option fedfs_delete_junction_longopts[] = {
 	{ "help", 0, NULL, '?', },
 	{ "hostname", 1, NULL, 'h', },
 	{ "nettype", 1, NULL, 'n', },
+	{ "security", 1, NULL, 's', },
 	{ NULL, 0, NULL, 0, },
 };
 
@@ -67,8 +63,9 @@  static const struct option fedfs_delete_junction_longopts[] = {
  * Display program synopsis
  *
  * @param progname NUL-terminated C string containing name of program
+ * @return program exit status
  */
-static void
+static int
 fedfs_delete_junction_usage(const char *progname)
 {
 	fprintf(stderr, "\n%s version " VERSION "\n", progname);
@@ -79,70 +76,97 @@  fedfs_delete_junction_usage(const char *progname)
 	fprintf(stderr, "\t-d, --debug          Enable debug messages\n");
 	fprintf(stderr, "\t-n, --nettype        RPC transport (default: 'netpath')\n");
 	fprintf(stderr, "\t-h, --hostname       ADMIN server hostname (default: 'localhost')\n");
+	fprintf(stderr, "\t-s, --security       RPC security level\n");
 
 	fprintf(stderr, "%s", fedfs_gpl_boilerplate);
 
-	exit((int)FEDFS_ERR_INVAL);
+	return EXIT_FAILURE;
 }
 
 /**
  * Delete a junction on a remote fileserver
  *
- * @param hostname NUL-terminated UTF-8 string containing ADMIN server's hostname
- * @param nettype NUL-terminated C string containing nettype to use for connection
- * @param path NUL-terminated C string containing remote pathname of junction to delete
- * @return a FedFsStatus code
+ * @param host an initialized and opened admin_t
+ * @param path_array an array of NUL-terminated C strings containing pathname components
+ * @return program exit status
  */
-static FedFsStatus
-fedfs_delete_junction_call(const char *hostname, const char *nettype,
-		const char *path)
+static int
+fedfs_delete_junction_try(admin_t host, char * const *path_array)
 {
-	enum clnt_stat status;
-	FedFsStatus result;
-	char **path_array;
-	CLIENT *client;
-	FedFsPath arg;
-
-	memset(&arg, 0, sizeof(arg));
-
-	result = nsdb_posix_to_path_array(path, &path_array);
-	if (result != FEDFS_OK) {
-		fprintf(stderr, "Failed to encode pathname: %s",
-			nsdb_display_fedfsstatus(result));
-		return result;
-	}
-	result = nsdb_path_array_to_fedfspathname(path_array,
-					&arg.FedFsPath_u.adminPath);
-	if (result != FEDFS_OK) {
-		fprintf(stderr, "Failed to encode pathname: %s",
-			nsdb_display_fedfsstatus(result));
-		nsdb_free_string_array(path_array);
-		return result;
-	}
-
-	client = clnt_create(hostname, FEDFS_PROG, FEDFS_V1, nettype);
-	if (client == NULL) {
-		clnt_pcreateerror("Failed to create FEDFS client");
-		result = FEDFS_ERR_SVRFAULT;
+	int status, err;
+
+	status = EXIT_FAILURE;
+	err = admin_delete_junction(host, path_array);
+	switch (err) {
+	case 0:
+		break;
+	case EACCES:
+		xlog(L_ERROR, "%s: access denied", admin_hostname(host));
+		xlog(D_GENERAL, "%s",
+			admin_perror(host, admin_hostname(host)));
+		goto out;
+	case EIO:
+		xlog(L_ERROR, "%s",
+			admin_perror(host, admin_hostname(host)));
+		goto out;
+	default:
+		xlog(L_ERROR, "ADMIN client: %s", strerror(err));
 		goto out;
 	}
 
-	memset((char *)&result, 0, sizeof(result));
-	status = clnt_call(client, FEDFS_DELETE_JUNCTION,
-				(xdrproc_t)xdr_FedFsPath, (caddr_t)&arg,
-				(xdrproc_t)xdr_FedFsStatus, (caddr_t)&result,
-				fedfs_delete_junction_timeout);
-	if (status != RPC_SUCCESS) {
-		clnt_perror(client, "FEDFS_DELETE_JUNCTION call failed");
-		result = FEDFS_ERR_SVRFAULT;
-	} else
-		nsdb_print_fedfsstatus(result);
-	(void)clnt_destroy(client);
+	switch (admin_status(host)) {
+	case FEDFS_OK:
+		printf("Junction deleted successfully\n");
+		status = EXIT_SUCCESS;
+		break;
+	case FEDFS_ERR_NSDB_PARAMS:
+		printf("No connection parameters found\n");
+		break;
+	default:
+		nsdb_print_fedfsstatus(admin_status(host));
+	}
 
 out:
-	nsdb_free_fedfspathname(&arg.FedFsPath_u.adminPath);
-	nsdb_free_string_array(path_array);
-	return result;
+	return status;
+}
+
+/**
+ * Delete a junction on a remote fileserver
+ *
+ * @param hostname NUL-terminated UTF-8 string containing ADMIN server's hostname
+ * @param nettype NUL-terminated C string containing nettype to use for connection
+ * @param security NUL-terminated C string containing RPC security mode
+ * @param path_array an array of NUL-terminated C strings containing pathname components
+ * @return program exit status
+ */
+static int
+fedfs_delete_junction_host(const char *hostname, const char *nettype,
+		const char *security, char * const *path_array)
+{
+	admin_t host;
+	int status;
+
+	status = EXIT_FAILURE;
+	switch (admin_create(hostname, nettype, security, &host)) {
+	case 0:
+		status = fedfs_delete_junction_try(host, path_array);
+		admin_release(host);
+		break;
+	case EINVAL:
+		xlog(L_ERROR, "Invalid command line parameter");
+		break;
+	case EACCES:
+		xlog(L_ERROR, "Failed to authenticate server");
+		break;
+	case EKEYEXPIRED:
+		xlog(L_ERROR, "User credentials not found");
+		break;
+	default:
+		xlog(L_ERROR, "%s",
+			admin_open_perror(admin_hostname(host)));
+	}
+
+	return status;
 }
 
 /**
@@ -155,10 +179,10 @@  out:
 int
 main(int argc, char **argv)
 {
-	char *progname, *hostname, *nettype, *path;
-	unsigned int seconds;
-	FedFsStatus status;
-	int arg;
+	char *progname, *hostname, *nettype, *security, *path;
+	FedFsStatus retval;
+	char **path_array;
+	int arg, status;
 
 	(void)setlocale(LC_ALL, "");
 	(void)umask(S_IRWXO);
@@ -176,6 +200,7 @@  main(int argc, char **argv)
 
 	hostname = "localhost";
 	nettype = "netpath";
+	security = "unix";
 	while ((arg = getopt_long(argc, argv, fedfs_delete_junction_opts, fedfs_delete_junction_longopts, NULL)) != -1) {
 		switch (arg) {
 		case 'd':
@@ -184,30 +209,35 @@  main(int argc, char **argv)
 		case 'h':
 			hostname = optarg;
 			break;
+		case 's':
+			security = optarg;
+			break;
 		default:
 			fprintf(stderr, "Invalid command line argument: %c\n", (char)arg);
 		case '?':
-			fedfs_delete_junction_usage(progname);
+			return fedfs_delete_junction_usage(progname);
 		}
 	}
 	if (argc == optind + 1)
 		path = argv[optind];
 	else if (argc > optind + 1) {
 		fprintf(stderr, "Unrecognized positional parameters\n");
-		fedfs_delete_junction_usage(progname);
+		return fedfs_delete_junction_usage(progname);
 	} else {
 		fprintf(stderr, "No junction pathname was specified\n");
-		fedfs_delete_junction_usage(progname);
+		return fedfs_delete_junction_usage(progname);
 	}
 
-	for (seconds = FEDFS_DELAY_MIN_SECS;; seconds = fedfs_delay(seconds)) {
-		status = fedfs_delete_junction_call(hostname, nettype, path);
-		if (status != FEDFS_ERR_DELAY)
-			break;
-
-		xlog(D_GENERAL, "Delaying %u seconds...", seconds);
-		if (sleep(seconds) != 0)
-			break;
+	retval = nsdb_posix_to_path_array(path, &path_array);
+	if (retval != FEDFS_OK) {
+		fprintf(stderr, "Failed to encode pathname: %s",
+			nsdb_display_fedfsstatus(retval));
+		return EXIT_FAILURE;
 	}
-	return (int)status;
+
+	status = fedfs_delete_junction_host(hostname, nettype,
+						security, path_array);
+
+	nsdb_free_string_array(path_array);
+	return status;
 }