diff options
author | rica <none@none> | 2007-07-27 16:45:56 -0700 |
---|---|---|
committer | rica <none@none> | 2007-07-27 16:45:56 -0700 |
commit | f875b4ebb1dd9fdbeb043557cab38ab3bf7f6e01 (patch) | |
tree | a89bd9be4c155028f554c0df7142f5c3365fb6d0 /usr/src/cmd/allocate/add_allocatable.c | |
parent | 836fa82ea903ec0a04de2b008034c3816b75a739 (diff) | |
download | illumos-gate-f875b4ebb1dd9fdbeb043557cab38ab3bf7f6e01.tar.gz |
PSARC 2007/254 - Enabling method for Trusted Extensions
6432114 [tjds] cannot login via gdm unless clearance is set to admin_high
6533113 split install and enabling of Trusted Extensions
6533118 move TX source from TLC to ON gate
6542578 TLC putback requires i.pamconf change similar to the kerberos solution.
6552207 txzonemgr does not configure loopback mounts for /etc/passwd and /etc/shadow when creating zones
6552253 solaris.smf.manage.labels should allow for permanent as well as temporary enable/disable of labeld
6555057 txzonemgr assumes LANG is valid
6557684 pam_tsol_account could use a thorough house cleaning
6561392 txzonemgr should work from Zone Management profile
6565347 txzonemgr failed to add an interface to a zone
Diffstat (limited to 'usr/src/cmd/allocate/add_allocatable.c')
-rw-r--r-- | usr/src/cmd/allocate/add_allocatable.c | 505 |
1 files changed, 505 insertions, 0 deletions
diff --git a/usr/src/cmd/allocate/add_allocatable.c b/usr/src/cmd/allocate/add_allocatable.c new file mode 100644 index 0000000000..759d1ed1e9 --- /dev/null +++ b/usr/src/cmd/allocate/add_allocatable.c @@ -0,0 +1,505 @@ +/* + * 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 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * add_allocatable - + * a command-line interface to add device to device_allocate and + * device_maps. + */ + +#ifndef __EXTENSIONS__ +#define __EXTENSIONS__ /* needed for _strtok_r */ +#endif + +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <strings.h> +#include <string.h> +#include <locale.h> +#include <libintl.h> +#include <pwd.h> +#include <nss_dbdefs.h> +#include <auth_attr.h> +#include <auth_list.h> +#include <zone.h> +#include <tsol/label.h> +#include <bsm/devices.h> +#include <bsm/devalloc.h> + +#define NO_OVERRIDE -1 + +int check_args(da_args *); +int process_args(int, char **, da_args *, char *); +int scan_label(char *, char *); +void usage(da_args *, char *); + +int system_labeled = 0; + +int +main(int argc, char *argv[]) +{ + int rc; + uid_t uid; + char *progname; + char pwbuf[NSS_LINELEN_PASSWD]; + struct passwd pwd; + da_args dargs; + devinfo_t devinfo; + + (void) setlocale(LC_ALL, ""); +#if !defined(TEXT_DOMAIN) +#define TEXT_DOMAIN "SYS_TEST" +#endif + (void) textdomain(TEXT_DOMAIN); + if ((progname = strrchr(argv[0], '/')) == NULL) + progname = argv[0]; + else + progname++; + + system_labeled = is_system_labeled(); + if (system_labeled) { + /* + * this command can be run only in the global zone. + */ + if (getzoneid() != GLOBAL_ZONEID) { + (void) fprintf(stderr, "%s%s", progname, + gettext(" : must be run in global zone\n")); + exit(1); + } + } else { + /* + * this command works in Trusted Extensions only. + */ + (void) fprintf(stderr, "%s%s", progname, + gettext(" : need to install Trusted Extensions\n")); + exit(1); + } + + dargs.optflag = 0; + dargs.rootdir = NULL; + dargs.devnames = NULL; + dargs.devinfo = &devinfo; + + if (strcmp(progname, "add_allocatable") == 0) { + dargs.optflag |= DA_ADD; + } else if (strcmp(progname, "remove_allocatable") == 0) { + dargs.optflag |= DA_REMOVE; + } else { + usage(&dargs, progname); + exit(1); + } + + uid = getuid(); + if ((getpwuid_r(uid, &pwd, pwbuf, sizeof (pwbuf))) == NULL) { + (void) fprintf(stderr, "%s%s", progname, + gettext(" : getpwuid_r failed: ")); + (void) fprintf(stderr, "%s\n", strerror(errno)); + exit(2); + } + + if (chkauthattr(DEVICE_CONFIG_AUTH, pwd.pw_name) != 1) { + (void) fprintf(stderr, "%s%s%s", progname, + gettext(" : user lacks authorization: \n"), + DEVICE_CONFIG_AUTH); + exit(4); + } + + if (process_args(argc, argv, &dargs, progname) != 0) { + usage(&dargs, progname); + exit(1); + } + + if (dargs.optflag & DA_ADD) { + if (check_args(&dargs) == NO_OVERRIDE) { + (void) fprintf(stderr, "%s%s%s%s", progname, + gettext(" : entry exists for "), + dargs.devinfo->devname, gettext("\n")); + usage(&dargs, progname); + exit(3); + } + } + + if (dargs.optflag & DA_DEFATTRS) + rc = da_update_defattrs(&dargs); + else + rc = da_update_device(&dargs); + + if ((rc != 0) && (!(dargs.optflag & DA_SILENT))) { + if (rc == -2) + (void) fprintf(stderr, "%s%s", progname, + gettext(" : device name/type/list missing\n")); + else if (dargs.optflag & DA_ADD) + (void) fprintf(stderr, "%s%s", progname, + gettext(" : error adding/updating device\n")); + else if (dargs.optflag & DA_REMOVE) + (void) fprintf(stderr, "%s%s", progname, + gettext(" : error removing device\n")); + rc = 2; /* exit code for 'Unknown system error' in man page */ + } + + return (rc); +} + +int +process_args(int argc, char **argv, da_args *dargs, char *progname) +{ + int c; + int aflag, cflag, dflag, fflag, lflag, nflag, oflag, tflag; + extern char *optarg; + devinfo_t *devinfo; + + devinfo = dargs->devinfo; + aflag = cflag = dflag = fflag = lflag = nflag = oflag = tflag = 0; + devinfo->devname = devinfo->devtype = devinfo->devauths = + devinfo->devexec = devinfo->devopts = devinfo->devlist = NULL; + devinfo->instance = 0; + + while ((c = getopt(argc, argv, "a:c:dfl:n:o:st:")) != EOF) { + switch (c) { + case 'a': + devinfo->devauths = optarg; + aflag++; + break; + case 'c': + devinfo->devexec = optarg; + if (strlen(devinfo->devexec) == 0) { + if (!(dargs->optflag & DA_SILENT)) + (void) fprintf(stderr, "%s%s", progname, + gettext(" : device clean program" + " name not found\n")); + return (1); + } + cflag++; + break; + case 'd': + dargs->optflag |= DA_DEFATTRS; + dflag++; + break; + case 'l': + devinfo->devlist = optarg; + if (strlen(devinfo->devlist) == 0) { + if (!(dargs->optflag & DA_SILENT)) + (void) fprintf(stderr, "%s%s", progname, + gettext(" : device file list" + " not found\n")); + return (1); + } + lflag++; + break; + case 'f': + dargs->optflag |= DA_FORCE; + fflag++; + break; + case 'n': + devinfo->devname = optarg; + if (strlen(devinfo->devname) == 0) { + if (!(dargs->optflag & DA_SILENT)) + (void) fprintf(stderr, "%s%s", progname, + gettext(" : device name " + "not found\n")); + return (1); + } + nflag++; + break; + case 'o': + /* check for field delimiters in the option */ + if (strpbrk(optarg, ":;=") == NULL) { + if (!(dargs->optflag & DA_SILENT)) { + (void) fprintf(stderr, "%s%s%s", + progname, + gettext(" : invalid " + "key=val string: "), + optarg); + (void) fprintf(stderr, "%s", + gettext("\n")); + } + return (1); + } + devinfo->devopts = optarg; + if (dargs->optflag & DA_ADD) { + if (scan_label(devinfo->devopts, progname) != 0) + return (1); + } + oflag++; + break; + case 's': + dargs->optflag |= DA_SILENT; + break; + case 't': + devinfo->devtype = optarg; + if (strlen(devinfo->devtype) == 0) { + if (!(dargs->optflag & DA_SILENT)) + (void) fprintf(stderr, "%s%s", progname, + gettext(" : device type " + "not found\n")); + return (1); + } + tflag++; + break; + default : + return (1); + } + } + + + if (dargs->optflag & DA_ADD) { + if (dflag) { + /* -d requires -t, but does not like -n */ + if (nflag || tflag == 0) + return (1); + } else if (nflag == 0 && tflag == 0 && lflag == 0) { + /* require at least -n or -t or -l to be specified */ + if (!(dargs->optflag & DA_SILENT)) + (void) fprintf(stderr, "%s%s", progname, + gettext(" : required options missing\n")); + return (1); + } + } else if (dargs->optflag & DA_REMOVE) { + if (dflag) { + /* -d requires -t, but does not like -n */ + if (nflag || tflag == 0) + return (1); + } else if (nflag == 0 && tflag == 0) { + /* require at least -n or -t to be specified */ + if (!(dargs->optflag & DA_SILENT)) + (void) fprintf(stderr, "%s%s", progname, + gettext(" : required options missing\n")); + return (1); + } + /* there's a bunch not accepted by remove_allocatable */ + if (aflag || cflag || lflag || oflag) + return (1); + } else { + return (1); + } + + /* check for option specified more than once */ + if (aflag > 1 || cflag > 1 || lflag > 1 || fflag > 1 || + nflag > 1 || tflag > 1) { + if (!(dargs->optflag & DA_SILENT)) + (void) fprintf(stderr, "%s%s", progname, + gettext(" : multiple-defined options\n")); + return (1); + } + + return (0); +} + +int +verify_label(char *token, char *progname) +{ + int error = 0; + char *p, *val, *str; + + if ((strstr(token, DAOPT_MINLABEL) == NULL) && + (strstr(token, DAOPT_MAXLABEL) == NULL)) { + /* no label specified */ + return (0); + } + if ((val = strchr(token, '=')) == NULL) + return (1); + val++; + /* + * if non-default labels are specified, check if they are correct + */ + if ((strcmp(val, DA_DEFAULT_MIN) != 0) && + (strcmp(val, DA_DEFAULT_MAX) != 0)) { + m_label_t *slabel = NULL; + + str = strdup(val); + /* get rid of double quotes if they exist */ + while (*str == '"') + str++; + if ((p = strchr(str, '"')) != NULL) + *p = '\0'; + if (str_to_label(str, &slabel, MAC_LABEL, L_NO_CORRECTION, + &error) == -1) { + (void) fprintf(stderr, "%s%s%s", progname, + gettext(" : bad label input: "), + val); + (void) fprintf(stderr, "%s", gettext("\n")); + free(str); + m_label_free(slabel); + return (1); + } + free(str); + m_label_free(slabel); + } + + return (0); +} + +int +scan_label(char *devopts, char *progname) +{ + char *tok = NULL; + char *lasts, *optsarg; + + if (devopts == NULL) + return (0); + + if ((optsarg = strdup(devopts)) == NULL) + return (1); + + if ((tok = strtok_r(optsarg, KV_TOKEN_DELIMIT, &lasts)) == NULL) + return (1); + + if (verify_label(tok, progname) != 0) { + free(optsarg); + return (1); + } + + while ((tok = strtok_r(NULL, KV_TOKEN_DELIMIT, &lasts)) != NULL) { + if (verify_label(tok, progname) != 0) { + free(optsarg); + return (1); + } + } + + return (0); +} + +int +check_args(da_args *dargs) +{ + int nlen; + char *kval, *nopts, *ntok, *nstr, + *defmin, *defmax, *defauths, *defexec; + kva_t *kva; + devinfo_t *devinfo; + devalloc_t *da = NULL; + da_defs_t *da_defs = NULL; + + devinfo = dargs->devinfo; + /* + * check if we're updating an existing entry without -f + */ + setdaent(); + da = getdanam(devinfo->devname); + enddaent(); + if (da && !(dargs->optflag & DA_FORCE)) { + freedaent(da); + return (NO_OVERRIDE); + } + if ((devinfo->devopts == NULL) || + (strstr(devinfo->devopts, DAOPT_MINLABEL) == NULL) || + (strstr(devinfo->devopts, DAOPT_MAXLABEL) == NULL) || + (devinfo->devauths == NULL) || + (devinfo->devexec == NULL)) { + /* fill in defaults as required */ + defmin = DA_DEFAULT_MIN; + defmax = DA_DEFAULT_MAX; + defauths = DEFAULT_DEV_ALLOC_AUTH; + defexec = DA_DEFAULT_CLEAN; + setdadefent(); + if (da_defs = getdadeftype(devinfo->devtype)) { + kva = da_defs->devopts; + if ((kval = kva_match(kva, DAOPT_MINLABEL)) != NULL) + defmin = strdup(kval); + if ((kval = kva_match(kva, DAOPT_MAXLABEL)) != NULL) + defmax = strdup(kval); + if ((kval = kva_match(kva, DAOPT_AUTHS)) != NULL) + defauths = strdup(kval); + if ((kval = kva_match(kva, DAOPT_CSCRIPT)) != NULL) + defexec = strdup(kval); + freedadefent(da_defs); + } + enddadefent(); + if (devinfo->devauths == NULL) + devinfo->devauths = defauths; + if (devinfo->devexec == NULL) + devinfo->devexec = defexec; + if (devinfo->devopts == NULL) { + /* add default minlabel and maxlabel */ + nlen = strlen(DAOPT_MINLABEL) + strlen(KV_ASSIGN) + + strlen(defmin) + strlen(KV_TOKEN_DELIMIT) + + strlen(DAOPT_MAXLABEL) + strlen(KV_ASSIGN) + + strlen(defmax) + 1; /* +1 for terminator */ + if (nopts = (char *)malloc(nlen)) { + (void) snprintf(nopts, nlen, "%s%s%s%s%s%s%s", + DAOPT_MINLABEL, KV_ASSIGN, defmin, + KV_TOKEN_DELIMIT, + DAOPT_MAXLABEL, KV_ASSIGN, defmax); + devinfo->devopts = nopts; + } + } else { + if (strstr(devinfo->devopts, DAOPT_MINLABEL) == NULL) { + /* add default minlabel */ + ntok = DAOPT_MINLABEL; + nstr = defmin; + nlen = strlen(devinfo->devopts) + + strlen(KV_TOKEN_DELIMIT) + + strlen(ntok) + strlen(KV_ASSIGN) + + strlen(nstr) + 1; + if (nopts = (char *)malloc(nlen)) { + (void) snprintf(nopts, nlen, + "%s%s%s%s%s", + devinfo->devopts, KV_TOKEN_DELIMIT, + ntok, KV_ASSIGN, nstr); + devinfo->devopts = nopts; + } + } + if (strstr(devinfo->devopts, DAOPT_MAXLABEL) == NULL) { + /* add default maxlabel */ + ntok = DAOPT_MAXLABEL; + nstr = defmax; + nlen = strlen(devinfo->devopts) + + strlen(KV_TOKEN_DELIMIT) + + strlen(ntok) + strlen(KV_ASSIGN) + + strlen(nstr) + 1; + if (nopts = (char *)malloc(nlen)) { + (void) snprintf(nopts, nlen, + "%s%s%s%s%s", + devinfo->devopts, KV_TOKEN_DELIMIT, + ntok, KV_ASSIGN, nstr); + devinfo->devopts = nopts; + } + } + } + } + + return (0); +} + +void +usage(da_args *dargs, char *progname) +{ + if (dargs->optflag & DA_SILENT) + return; + if (dargs->optflag & DA_ADD) + (void) fprintf(stderr, "%s%s%s", gettext("Usage: "), progname, + gettext(" [-f][-s][-d] -n name -t type -l device-list" + "\n\t[-a authorization] [-c cleaning program] " + "[-o key=value]\n")); + else if (dargs->optflag & DA_REMOVE) + (void) fprintf(stderr, "%s%s%s", gettext("Usage: "), progname, + gettext(" [-f][-s][-d] [-n name|-t type]\n")); + else + (void) fprintf(stderr, gettext("Invalid usage\n"), progname); +} |