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 <[email protected]> --- doc/man/fedfs-create-junction.8 | 112 ++++++------------ src/fedfsc/fedfs-create-junction.c | 223 +++++++++++++++++++----------------- 2 files changed, 156 insertions(+), 179 deletions(-) diff --git a/doc/man/fedfs-create-junction.8 b/doc/man/fedfs-create-junction.8 index 743d3bd..c7360a9 100644 --- a/doc/man/fedfs-create-junction.8 +++ b/doc/man/fedfs-create-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. .\" @@ -37,6 +37,8 @@ fedfs-create-junction \- send a FEDFS_CREATE_JUNCTION ADMIN protocol request .IR nsdbname ] .RB [ \-r .IR nsdbport ] +.RB [ \-s +.IR security ] .I path .I fsn-uuid .SH INTRODUCTION @@ -122,77 +124,21 @@ Specifies the IP port of the NSDB to insert into the new FedFS junction. If this option is not specified, the value of the FEDFS_NSDB_PORT environment variable is consulted. The default value if the variable is not set is 389. -.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_EXIST -The specified junction already exists. -.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_NSDB_PARAMS -The remote server does not have any connection -parameters on record for the specified NSDB. -.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 @@ -214,12 +160,32 @@ command, and added to the NSDB using the .BR nsdb-create-fsn (8) command. .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 fedfs-lookup-junction (8), .BR nsdb-create-fsn (8), +.BR kinit (1), .BR rpc (3t) .sp RFC 5716 for FedFS requirements and overview diff --git a/src/fedfsc/fedfs-create-junction.c b/src/fedfsc/fedfs-create-junction.c index 0d6ce2d..987c02a 100644 --- a/src/fedfsc/fedfs-create-junction.c +++ b/src/fedfsc/fedfs-create-junction.c @@ -1,13 +1,10 @@ /** * @file src/fedfsc/fedfs-create-junction.c * @brief Send a FEDFS_CREATE_JUNCTION RPC to a FedFS ADMIN server - * - * @todo - * Implement RPCGSS authentication */ /* - * Copyright 2010 Oracle. All rights reserved. + * Copyright 2010, 2013 Oracle. All rights reserved. * * This file is part of fedfs-utils. * @@ -30,31 +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 <uuid/uuid.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_create_junction_timeout = { 25, 0 }; - -/** * Short form command line options */ -static const char fedfs_create_junction_opts[] = "?dh:l:n:r:"; +static const char fedfs_create_junction_opts[] = "?dh:l:n:r:s:"; /** * Long form command line options @@ -63,9 +54,10 @@ static const struct option fedfs_create_junction_longopts[] = { { "debug", 0, NULL, 'd', }, { "help", 0, NULL, '?', }, { "hostname", 1, NULL, 'h', }, - { "nettype", 1, NULL, 'n', }, { "nsdbname", 1, NULL, 'l', }, + { "nettype", 1, NULL, 'n', }, { "nsdbport", 1, NULL, 'r', }, + { "security", 1, NULL, 's', }, { NULL, 0, NULL, 0, }, }; @@ -73,8 +65,9 @@ static const struct option fedfs_create_junction_longopts[] = { * Display program synopsis * * @param progname NUL-terminated C string containing name of program + * @return program exit status */ -static void +static int fedfs_create_junction_usage(const char *progname) { fprintf(stderr, "\n%s version " VERSION "\n", progname); @@ -89,89 +82,101 @@ fedfs_create_junction_usage(const char *progname) fprintf(stderr, "\t-h, --hostname ADMIN server hostname (default: 'localhost')\n"); fprintf(stderr, "\t-l, --nsdbname NSDB hostname to set\n"); fprintf(stderr, "\t-r, --nsdbport NSDB port to set\n"); + fprintf(stderr, "\t-s, --security RPC security level\n"); fprintf(stderr, "%s", fedfs_gpl_boilerplate); - exit((int)FEDFS_ERR_INVAL); + return EXIT_FAILURE; } /** * Create 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 new junction - * @param uuid NUL-terminated C string containing FSN UUID for new junction - * @param nsdbname NUL-terminated UTF-8 string containing name of NSDB node for this junction - * @param nsdbport port number of NSDB node for this junction - * @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 + * @param fsn FileSet Name to plant in new junction + * @return program exit status */ -static FedFsStatus -fedfs_create_junction_call(const char *hostname, const char *nettype, - const char *path, const char *uuid, char *nsdbname, - const uint16_t nsdbport) +static int +fedfs_create_junction_try(admin_t host, char * const *path_array, + struct admin_fsn *fsn) { - enum clnt_stat status; - FedFsCreateArgs arg; - FedFsStatus result; - char **path_array; - CLIENT *client; - uuid_t uu; - int res; + int status, err; - memset(&arg, 0, sizeof(arg)); + status = EXIT_FAILURE; + err = admin_create_junction(host, path_array, fsn); + 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; + } - res = uuid_parse(uuid, uu); - if (res != 0) { - fprintf(stderr, "Failed to parse UUID %s\n", uuid); - return FEDFS_ERR_INVAL; + switch (admin_status(host)) { + case FEDFS_OK: + printf("Junction created 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)); } - memcpy(arg.fsn.fsnUuid, uu, sizeof(FedFsUuid)); - arg.fsn.nsdbName.hostname.utf8string_val = nsdbname; - arg.fsn.nsdbName.hostname.utf8string_len = strlen(nsdbname); - arg.fsn.nsdbName.port = nsdbport; +out: + return status; +} - arg.path.type = FEDFS_PATH_SYS; - 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.path.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; - } +/** + * Create 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 + * @param fsn FileSet Name to plant in new junction + * @return program exit status + */ +static int +fedfs_create_junction_host(const char *hostname, const char *nettype, + const char *security, char * const *path_array, + struct admin_fsn *fsn) +{ + admin_t host; + int status; - client = clnt_create(hostname, FEDFS_PROG, FEDFS_V1, nettype); - if (client == NULL) { - clnt_pcreateerror("Failed to create FEDFS client"); - result = FEDFS_ERR_SVRFAULT; - goto out; + status = EXIT_FAILURE; + switch (admin_create(hostname, nettype, security, &host)) { + case 0: + status = fedfs_create_junction_try(host, path_array, fsn); + 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))); } - memset((char *)&result, 0, sizeof(result)); - status = clnt_call(client, FEDFS_CREATE_JUNCTION, - (xdrproc_t)xdr_FedFsCreateArgs, - (caddr_t)&arg, - (xdrproc_t)xdr_FedFsStatus, (caddr_t)&result, - fedfs_create_junction_timeout); - if (status != RPC_SUCCESS) { - clnt_perror(client, "FEDFS_CREATE_JUNCTION call failed"); - result = FEDFS_ERR_SVRFAULT; - } else - nsdb_print_fedfsstatus(result); - (void)clnt_destroy(client); - -out: - nsdb_free_fedfspathname(&arg.path.FedFsPath_u.adminPath); - nsdb_free_string_array(path_array); - return result; + return status; } /** @@ -184,12 +189,12 @@ out: int main(int argc, char **argv) { - char *progname, *hostname, *nettype; - char *fsn_uuid, *path, *nsdbname; - unsigned short nsdbport; - unsigned int seconds; - FedFsStatus status; - int arg; + char *progname, *hostname, *nettype, *security, *path; + struct admin_nsdb *nsdb; + struct admin_fsn fsn; + FedFsStatus retval; + char **path_array; + int arg, status; (void)setlocale(LC_ALL, ""); (void)umask(S_IRWXO); @@ -205,10 +210,12 @@ main(int argc, char **argv) xlog_syslog(0); xlog_open(progname); - nsdb_env(&nsdbname, &nsdbport, NULL, NULL); + nsdb = &fsn.af_nsdb; + nsdb_env((char **)&nsdb->an_hostname, &nsdb->an_port, NULL, NULL); hostname = "localhost"; nettype = "netpath"; + security = "unix"; while ((arg = getopt_long(argc, argv, fedfs_create_junction_opts, fedfs_create_junction_longopts, NULL)) != -1) { switch (arg) { @@ -222,48 +229,52 @@ main(int argc, char **argv) if (!nsdb_is_hostname_utf8(optarg)) { fprintf(stderr, "NSDB name %s is " "not a UTF-8 hostname\n", optarg); - fedfs_create_junction_usage(progname); + return fedfs_create_junction_usage(progname); } - nsdbname = optarg; + nsdb->an_hostname = optarg; break; case 'n': nettype = optarg; break; case 'r': - if (!nsdb_parse_port_string(optarg, &nsdbport)) { + if (!nsdb_parse_port_string(optarg, &nsdb->an_port)) { fprintf(stderr, "Bad port number: '%s'\n", optarg); - fedfs_create_junction_usage(progname); + return fedfs_create_junction_usage(progname); } break; + case 's': + security = optarg; + break; default: fprintf(stderr, "Invalid command line " "argument: %c\n", (char)arg); case '?': - fedfs_create_junction_usage(progname); + return fedfs_create_junction_usage(progname); } } if (argc == optind + 2) { path = argv[optind]; - fsn_uuid = argv[optind + 1]; + fsn.af_uuid = argv[optind + 1]; } else { fprintf(stderr, "Ambiguous positional parameters\n"); - fedfs_create_junction_usage(progname); + return fedfs_create_junction_usage(progname); } - if (nsdbname == NULL) { + if (nsdb->an_hostname == NULL) { fprintf(stderr, "No NSDB hostname was specified\n"); - fedfs_create_junction_usage(progname); + return fedfs_create_junction_usage(progname); } - for (seconds = FEDFS_DELAY_MIN_SECS;; seconds = fedfs_delay(seconds)) { - status = fedfs_create_junction_call(hostname, nettype, path, - fsn_uuid, nsdbname, nsdbport); - 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_create_junction_host(hostname, nettype, security, + path_array, &fsn); + + nsdb_free_string_array(path_array); + return status; } _______________________________________________ fedfs-utils-devel mailing list [email protected] https://oss.oracle.com/mailman/listinfo/fedfs-utils-devel
