4963290 RFE: implement flexible zone administration that doesn't require uid=0
PSARC/2010/132 Delegated Administration for Zones
--- a/usr/src/cmd/oamuser/user/funcs.c Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/cmd/oamuser/user/funcs.c Mon Jun 07 14:07:27 2010 -0700
@@ -19,12 +19,9 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
@@ -231,6 +228,10 @@
int have_grant = 0;
tmp = strdup(auths);
+ if (tmp == NULL) {
+ errmsg(M_NOSPACE);
+ exit(EX_FAILURE);
+ }
authname = strtok(tmp, AUTH_SEP);
pw = getpwuid(getuid());
@@ -242,6 +243,14 @@
char *suffix;
char *authtoks;
+ /* Check if user has been granted this authorization */
+ if (!chkauthattr(authname, pw->pw_name))
+ return (authname);
+
+ /* Remove named object after slash */
+ if ((suffix = index(authname, KV_OBJECTCHAR)) != NULL)
+ *suffix = '\0';
+
/* Find the suffix */
if ((suffix = rindex(authname, '.')) == NULL)
return (authname);
@@ -258,11 +267,6 @@
free_authattr(result);
}
- /* Check if user has been granted this authorization */
- if (!chkauthattr(authname, pw->pw_name)) {
- return (authname);
- }
-
/* Check if user can delegate this authorization */
if (strcmp(suffix, "grant")) { /* Not a grant option */
authtoks = malloc(strlen(authname) + sizeof ("grant"));
@@ -281,6 +285,7 @@
}
authname = strtok(NULL, AUTH_SEP);
}
+ free(tmp);
return (NULL);
}
@@ -299,6 +304,10 @@
char *tmp;
tmp = strdup(profs);
+ if (tmp == NULL) {
+ errmsg(M_NOSPACE);
+ exit(EX_FAILURE);
+ }
profname = strtok(tmp, PROF_SEP);
while (profname != NULL) {
@@ -310,6 +319,7 @@
free_profattr(result);
profname = strtok(NULL, PROF_SEP);
}
+ free(tmp);
return (NULL);
}
@@ -330,6 +340,10 @@
char *tmp;
tmp = strdup(roles);
+ if (tmp == NULL) {
+ errmsg(M_NOSPACE);
+ exit(EX_FAILURE);
+ }
rolename = strtok(tmp, ROLE_SEP);
while (rolename != NULL) {
@@ -352,6 +366,7 @@
free_userattr(result);
rolename = strtok(NULL, ROLE_SEP);
}
+ free(tmp);
return (NULL);
}
--- a/usr/src/cmd/zlogin/Makefile Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/cmd/zlogin/Makefile Mon Jun 07 14:07:27 2010 -0700
@@ -19,8 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
#
PROG = zlogin
@@ -28,7 +27,7 @@
include ../Makefile.cmd
LINTFLAGS += -u
-LDLIBS += -lsocket -lzonecfg -lcontract -lbrand
+LDLIBS += -lsocket -lzonecfg -lcontract -lbrand -lsecdb
CFLAGS += $(CCVERBOSE)
FILEMODE = 0555
--- a/usr/src/cmd/zlogin/zlogin.c Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/cmd/zlogin/zlogin.c Mon Jun 07 14:07:27 2010 -0700
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -85,6 +84,9 @@
#include <libzonecfg.h>
#include <libcontract.h>
#include <libbrand.h>
+#include <auth_list.h>
+#include <auth_attr.h>
+#include <secdb.h>
static int masterfd;
static struct termios save_termios;
@@ -103,6 +105,13 @@
static int pollerr = 0;
static const char *pname;
+static char *username;
+
+/*
+ * When forced_login is true, the user is not prompted
+ * for an authentication password in the target zone.
+ */
+static boolean_t forced_login = B_FALSE;
#if !defined(TEXT_DOMAIN) /* should be defined by cc -D */
#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
@@ -1022,9 +1031,16 @@
/* Get the login command for the target zone. */
bzero(result_buf, sizeof (result_buf));
- if (brand_get_login_cmd(bh, login,
- result_buf, sizeof (result_buf)) != 0)
- return (NULL);
+
+ if (forced_login) {
+ if (brand_get_forcedlogin_cmd(bh, login,
+ result_buf, sizeof (result_buf)) != 0)
+ return (NULL);
+ } else {
+ if (brand_get_login_cmd(bh, login,
+ result_buf, sizeof (result_buf)) != 0)
+ return (NULL);
+ }
/*
* We got back a string that we'd like to execute. But since
@@ -1114,6 +1130,10 @@
return (NULL);
new_argv[a++] = SUPATH;
+ if (strcmp(login, "root") != 0) {
+ new_argv[a++] = "-";
+ n++;
+ }
new_argv[a++] = (char *)login;
}
new_argv[a++] = "-c";
@@ -1637,6 +1657,15 @@
*/
(void) setpgid(getpid(), getpid());
+ /*
+ * The child needs to run as root to
+ * execute the su program.
+ */
+ if (setuid(0) == -1) {
+ zperror(gettext("insufficient privilege"));
+ return (1);
+ }
+
(void) execve(new_args[0], new_args, new_env);
zperror(gettext("exec failure"));
_exit(1);
@@ -1667,6 +1696,29 @@
return (WEXITSTATUS(child_status));
}
+static char *
+get_username()
+{
+ uid_t uid;
+ struct passwd *nptr;
+
+ /*
+ * Authorizations are checked to restrict access based on the
+ * requested operation and zone name, It is assumed that the
+ * program is running with all privileges, but that the real
+ * user ID is that of the user or role on whose behalf we are
+ * operating. So we start by getting the username that will be
+ * used for subsequent authorization checks.
+ */
+
+ uid = getuid();
+ if ((nptr = getpwuid(uid)) == NULL) {
+ zerror(gettext("could not get user name."));
+ _exit(1);
+ }
+ return (nptr->pw_name);
+}
+
int
main(int argc, char **argv)
{
@@ -1689,11 +1741,13 @@
char kernzone[ZONENAME_MAX];
brand_handle_t bh;
char user_cmd[MAXPATHLEN];
+ char authname[MAXAUTHS];
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
(void) getpname(argv[0]);
+ username = get_username();
while ((arg = getopt(argc, argv, "ECR:Se:l:")) != EOF) {
switch (arg) {
@@ -1800,13 +1854,8 @@
* In the console case, because we may need to startup zoneadmd.
* In the non-console case in order to do zone_enter(2), zonept()
* and other tasks.
- *
- * Future work: this solution is temporary. Ultimately, we need to
- * move to a flexible system which allows the global admin to
- * designate that a particular user can zlogin (and probably zlogin
- * -C) to a particular zone. This all-root business we have now is
- * quite sketchy.
*/
+
if ((privset = priv_allocset()) == NULL) {
zperror(gettext("priv_allocset failed"));
return (1);
@@ -1827,6 +1876,37 @@
priv_freeset(privset);
/*
+ * Check if user is authorized for requested usage of the zone
+ */
+
+ (void) snprintf(authname, MAXAUTHS, "%s%s%s",
+ ZONE_MANAGE_AUTH, KV_OBJECT, zonename);
+ if (chkauthattr(authname, username) == 0) {
+ if (console) {
+ zerror(gettext("%s is not authorized for console "
+ "access to %s zone."),
+ username, zonename);
+ return (1);
+ } else {
+ (void) snprintf(authname, MAXAUTHS, "%s%s%s",
+ ZONE_LOGIN_AUTH, KV_OBJECT, zonename);
+ if (failsafe || !interactive) {
+ zerror(gettext("%s is not authorized for "
+ "failsafe or non-interactive login "
+ "to %s zone."), username, zonename);
+ return (1);
+ } else if (chkauthattr(authname, username) == 0) {
+ zerror(gettext("%s is not authorized "
+ " to login to %s zone."),
+ username, zonename);
+ return (1);
+ }
+ }
+ } else {
+ forced_login = B_TRUE;
+ }
+
+ /*
* The console is a separate case from the rest of the code; handle
* it first.
*/
@@ -2116,10 +2196,20 @@
if (setup_utmpx(slaveshortname) == -1)
return (1);
+ /*
+ * The child needs to run as root to
+ * execute the brand's login program.
+ */
+ if (setuid(0) == -1) {
+ zperror(gettext("insufficient privilege"));
+ return (1);
+ }
+
(void) execve(new_args[0], new_args, new_env);
zperror(gettext("exec failure"));
return (1);
}
+
(void) ct_tmpl_clear(tmpl_fd);
(void) close(tmpl_fd);
--- a/usr/src/cmd/zoneadm/Makefile Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/cmd/zoneadm/Makefile Mon Jun 07 14:07:27 2010 -0700
@@ -20,8 +20,7 @@
#
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
#
PROG= zoneadm
@@ -37,7 +36,7 @@
POFILE=zoneadm_all.po
POFILES= $(OBJS:%.o=%.po)
-LDLIBS += -lzonecfg -lsocket -lgen -lpool -lzfs -luuid -lnvpair -lbrand -ldladm
+LDLIBS += -lzonecfg -lsocket -lgen -lpool -lzfs -luuid -lnvpair -lbrand -ldladm -lsecdb
.KEEP_STATE:
--- a/usr/src/cmd/zoneadm/zoneadm.c Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/cmd/zoneadm/zoneadm.c Mon Jun 07 14:07:27 2010 -0700
@@ -79,10 +79,15 @@
#include <sys/fsspriocntl.h>
#include <libdladm.h>
#include <libdllink.h>
+#include <pwd.h>
+#include <auth_list.h>
+#include <auth_attr.h>
+#include <secdb.h>
#include "zoneadm.h"
#define MAXARGS 8
+#define SOURCE_ZONE (CMD_MAX + 1)
/* Reflects kernel zone entries */
typedef struct zone_entry {
@@ -201,6 +206,7 @@
static char *locale;
char *target_zone;
static char *target_uuid;
+char *username;
char *
cmd_to_str(int cmd_num)
@@ -1505,6 +1511,56 @@
return (ZONE_SUBPROC_FATAL);
}
+static int
+auth_check(char *user, char *zone, int cmd_num)
+{
+ char authname[MAXAUTHS];
+
+ switch (cmd_num) {
+ case CMD_LIST:
+ case CMD_HELP:
+ return (Z_OK);
+ case SOURCE_ZONE:
+ (void) strlcpy(authname, ZONE_CLONEFROM_AUTH, MAXAUTHS);
+ break;
+ case CMD_BOOT:
+ case CMD_HALT:
+ case CMD_READY:
+ case CMD_REBOOT:
+ case CMD_SYSBOOT:
+ case CMD_VERIFY:
+ case CMD_INSTALL:
+ case CMD_UNINSTALL:
+ case CMD_MOUNT:
+ case CMD_UNMOUNT:
+ case CMD_CLONE:
+ case CMD_MOVE:
+ case CMD_DETACH:
+ case CMD_ATTACH:
+ case CMD_MARK:
+ case CMD_APPLY:
+ default:
+ (void) strlcpy(authname, ZONE_MANAGE_AUTH, MAXAUTHS);
+ break;
+ }
+ (void) strlcat(authname, KV_OBJECT, MAXAUTHS);
+ (void) strlcat(authname, zone, MAXAUTHS);
+ if (chkauthattr(authname, user) == 0) {
+ return (Z_ERR);
+ } else {
+ /*
+ * Some subcommands, e.g. install, run subcommands,
+ * e.g. sysidcfg, that require a real uid of root,
+ * so switch to root, here.
+ */
+ if (setuid(0) == -1) {
+ zperror(gettext("insufficient privilege"), B_TRUE);
+ return (Z_ERR);
+ }
+ return (Z_OK);
+ }
+}
+
/*
* Various sanity checks; make sure:
* 1. We're in the global zone.
@@ -1568,6 +1624,12 @@
return (Z_ERR);
}
+ if (auth_check(username, zone, cmd_num) == Z_ERR) {
+ zerror(gettext("User %s is not authorized to %s this zone."),
+ username, cmd_to_str(cmd_num));
+ return (Z_ERR);
+ }
+
if (strcmp(zone, GLOBAL_ZONENAME) == 0) {
zerror(gettext("%s operation is invalid for the global zone."),
cmd_to_str(cmd_num));
@@ -3594,6 +3656,13 @@
return (Z_ERR);
}
+ if (auth_check(username, source_zone, SOURCE_ZONE) == Z_ERR) {
+ zerror(gettext("%s operation is invalid because "
+ "user is not authorized to read source zone."),
+ cmd_to_str(CMD_CLONE));
+ return (Z_ERR);
+ }
+
zent = lookup_running_zone(source_zone);
if (zent != NULL) {
/* check whether the zone is ready or running */
@@ -5611,6 +5680,30 @@
return (execbasename);
}
+static char *
+get_username()
+{
+ uid_t uid;
+ struct passwd *nptr;
+
+
+ /*
+ * Authorizations are checked to restrict access based on the
+ * requested operation and zone name, It is assumed that the
+ * program is running with all privileges, but that the real
+ * user ID is that of the user or role on whose behalf we are
+ * operating. So we start by getting the username that will be
+ * used for subsequent authorization checks.
+ */
+
+ uid = getuid();
+ if ((nptr = getpwuid(uid)) == NULL) {
+ zerror(gettext("could not get user name."));
+ exit(Z_ERR);
+ }
+ return (nptr->pw_name);
+}
+
int
main(int argc, char **argv)
{
@@ -5626,11 +5719,13 @@
setbuf(stdout, NULL);
(void) sigset(SIGHUP, SIG_IGN);
execname = get_execbasename(argv[0]);
+ username = get_username();
target_zone = NULL;
if (chdir("/") != 0) {
zerror(gettext("could not change directory to /."));
exit(Z_ERR);
}
+
/*
* Use the default system mask rather than anything that may have been
* set by the caller.
--- a/usr/src/cmd/zonecfg/zonecfg.c Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/cmd/zonecfg/zonecfg.c Mon Jun 07 14:07:27 2010 -0700
@@ -75,6 +75,7 @@
#include <sys/systeminfo.h>
#include <libdladm.h>
#include <libinetutil.h>
+#include <pwd.h>
#include <libzonecfg.h>
#include "zonecfg.h"
@@ -181,6 +182,7 @@
"ip-type",
"capped-cpu",
"hostid",
+ "admin",
NULL
};
@@ -223,6 +225,8 @@
"ip-type",
"defrouter",
"hostid",
+ "user",
+ "auths",
NULL
};
@@ -271,6 +275,7 @@
"add dedicated-cpu",
"add capped-cpu",
"add capped-memory",
+ "add admin",
NULL
};
@@ -301,6 +306,7 @@
"remove dedicated-cpu ",
"remove capped-cpu ",
"remove capped-memory ",
+ "remove admin ",
NULL
};
@@ -315,6 +321,7 @@
"select dedicated-cpu",
"select capped-cpu",
"select capped-memory",
+ "select admin",
NULL
};
@@ -365,6 +372,7 @@
"info max-sem-ids",
"info cpu-shares",
"info hostid",
+ "info admin",
NULL
};
@@ -486,6 +494,17 @@
NULL
};
+static const char *admin_res_scope_cmds[] = {
+ "cancel",
+ "end",
+ "exit",
+ "help",
+ "info",
+ "set user=",
+ "set auths=",
+ NULL
+};
+
/* Global variables */
/* set early in main(), never modified thereafter, used all over the place */
@@ -553,6 +572,7 @@
static struct zone_dstab old_dstab, in_progress_dstab;
static struct zone_psettab old_psettab, in_progress_psettab;
static struct zone_mcaptab old_mcaptab, in_progress_mcaptab;
+static struct zone_admintab old_admintab, in_progress_admintab;
static GetLine *gl; /* The gl_get_line() resource object */
@@ -630,6 +650,8 @@
return (add_stuff(cpl, line, pcap_res_scope_cmds, word_end));
case RT_MCAP:
return (add_stuff(cpl, line, mcap_res_scope_cmds, word_end));
+ case RT_ADMIN:
+ return (add_stuff(cpl, line, admin_res_scope_cmds, word_end));
}
return (0);
}
@@ -1092,6 +1114,20 @@
pt_to_str(PT_LOCKED),
gettext("<qualified unsigned decimal>"));
break;
+ case RT_ADMIN:
+ (void) fprintf(fp, gettext("The '%s' resource scope is "
+ "used to delegate specific zone management\n"
+ "rights to users and roles. These rights are "
+ "only applicable to this zone.\n"),
+ rt_to_str(resource_scope));
+ (void) fprintf(fp, gettext("Valid commands:\n"));
+ (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
+ pt_to_str(PT_USER),
+ gettext("<single user or role name>"));
+ (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
+ pt_to_str(PT_AUTHS),
+ gettext("<comma separated list>"));
+ break;
}
(void) fprintf(fp, gettext("And from any resource scope, you "
"can:\n"));
@@ -1150,12 +1186,13 @@
}
if (flags & HELP_RESOURCES) {
(void) fprintf(fp, "<%s> := %s | %s | %s | %s | %s | %s |\n\t"
- "%s | %s | %s | %s\n\n",
+ "%s | %s | %s | %s | %s\n\n",
gettext("resource type"), rt_to_str(RT_FS),
rt_to_str(RT_IPD), rt_to_str(RT_NET), rt_to_str(RT_DEVICE),
rt_to_str(RT_RCTL), rt_to_str(RT_ATTR),
rt_to_str(RT_DATASET), rt_to_str(RT_DCPU),
- rt_to_str(RT_PCAP), rt_to_str(RT_MCAP));
+ rt_to_str(RT_PCAP), rt_to_str(RT_MCAP),
+ rt_to_str(RT_ADMIN));
}
if (flags & HELP_PROPS) {
(void) fprintf(fp, gettext("For resource type ... there are "
@@ -1217,6 +1254,8 @@
(void) fprintf(fp, "\t%s\t%s, %s, %s\n", rt_to_str(RT_MCAP),
pt_to_str(PT_PHYSICAL), pt_to_str(PT_SWAP),
pt_to_str(PT_LOCKED));
+ (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_ADMIN),
+ pt_to_str(PT_USER), pt_to_str(PT_AUTHS));
}
if (need_to_close)
(void) pclose(fp);
@@ -1266,6 +1305,30 @@
" Unable to continue", zone, brandname);
exit(Z_ERR);
}
+ /*
+ * If the user_attr file is newer than
+ * the zone config file, the admins
+ * may need to be updated since the
+ * RBAC files are authoritative for
+ * authorization checks.
+ */
+ err = zonecfg_update_userauths(handle, zone);
+ if (err == Z_OK) {
+ zerr(gettext("The administrative rights "
+ "were updated to match "
+ "the current RBAC configuration.\n"
+ "Use \"info admin\" and \"revert\" to "
+ "compare with the previous settings."));
+ need_to_commit = B_TRUE;
+ } else if (err != Z_NO_ENTRY) {
+ zerr(gettext("failed to update "
+ "admin rights."));
+ exit(Z_ERR);
+ } else if (need_to_commit) {
+ zerr(gettext("admin rights were updated "
+ "to match RBAC configuration."));
+ }
+
} else if (global_zone && err == Z_NO_ZONE && !got_handle &&
!read_only_mode) {
/*
@@ -1635,6 +1698,7 @@
struct zone_psettab psettab;
struct zone_mcaptab mcaptab;
struct zone_rctlvaltab *valptr;
+ struct zone_admintab admintab;
int err, arg;
char zonepath[MAXPATHLEN], outfile[MAXPATHLEN], pool[MAXNAMELEN];
char bootargs[BOOTARGS_MAX];
@@ -1896,6 +1960,19 @@
(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
}
+ if ((err = zonecfg_setadminent(handle)) != Z_OK) {
+ zone_perror(zone, err, B_FALSE);
+ goto done;
+ }
+ while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
+ (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
+ rt_to_str(RT_ADMIN));
+ export_prop(of, PT_USER, admintab.zone_admin_user);
+ export_prop(of, PT_AUTHS, admintab.zone_admin_auths);
+ (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
+ }
+ (void) zonecfg_endadminent(handle);
+
/*
* There is nothing to export for pcap since this resource is just
* a container for an rctl alias.
@@ -2091,6 +2168,9 @@
"to administer. Please use caution."));
bzero(&in_progress_mcaptab, sizeof (in_progress_mcaptab));
return;
+ case RT_ADMIN:
+ bzero(&in_progress_admintab, sizeof (in_progress_admintab));
+ return;
default:
zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
long_usage(CMD_ADD, B_TRUE);
@@ -2413,7 +2493,7 @@
* user if the zone is not configured. In force mode, we don't
* trust that evaluation, and hence skip it. (We don't need the
* handle to be loaded anyway, since zonecfg_destroy is done by
- * zonename). However, we also have to take care to emulate the
+ * zonename). However, we also have to take care to emulate the
* messages spit out by initialize; see below.
*/
if (initialize(B_TRUE) != Z_OK)
@@ -2431,6 +2511,13 @@
return;
}
+ /*
+ * This function removes the authorizations from user_attr
+ * that correspond to those specified in the configuration
+ */
+ if (initialize(B_TRUE) == Z_OK) {
+ (void) zonecfg_deauthorize_users(handle, zone);
+ }
if ((err = zonecfg_destroy(zone, force)) != Z_OK) {
if ((err == Z_BAD_ZONE_STATE) && !force) {
zerr(gettext("Zone %s not in %s state; %s not "
@@ -2742,6 +2829,45 @@
return (zonecfg_lookup_ds(handle, dstab));
}
+static int
+fill_in_admintab(cmd_t *cmd, struct zone_admintab *admintab,
+ boolean_t fill_in_only)
+{
+ int err, i;
+ property_value_ptr_t pp;
+
+ if ((err = initialize(B_TRUE)) != Z_OK)
+ return (err);
+
+ bzero(admintab, sizeof (*admintab));
+ for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
+ pp = cmd->cmd_property_ptr[i];
+ if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
+ zerr(gettext("A simple value was expected here."));
+ saw_error = B_TRUE;
+ return (Z_INSUFFICIENT_SPEC);
+ }
+ switch (cmd->cmd_prop_name[i]) {
+ case PT_USER:
+ (void) strlcpy(admintab->zone_admin_user, pp->pv_simple,
+ sizeof (admintab->zone_admin_user));
+ break;
+ case PT_AUTHS:
+ (void) strlcpy(admintab->zone_admin_auths,
+ pp->pv_simple, sizeof (admintab->zone_admin_auths));
+ break;
+ default:
+ zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
+ Z_NO_PROPERTY_TYPE, B_TRUE);
+ return (Z_INSUFFICIENT_SPEC);
+ }
+ }
+ if (fill_in_only)
+ return (Z_OK);
+ err = zonecfg_lookup_admin(handle, admintab);
+ return (err);
+}
+
static void
remove_aliased_rctl(int type, char *name)
{
@@ -3144,6 +3270,46 @@
}
static void
+remove_admin(cmd_t *cmd)
+{
+ int err;
+
+ /* traditional, qualified attr removal */
+ if (cmd->cmd_prop_nv_pairs > 0) {
+ struct zone_admintab admintab;
+
+ if ((err = fill_in_admintab(cmd, &admintab, B_FALSE)) != Z_OK) {
+ z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
+ err, B_TRUE);
+ return;
+ }
+ if ((err = zonecfg_delete_admin(handle, &admintab,
+ zone))
+ != Z_OK)
+ z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
+ err, B_TRUE);
+ else
+ need_to_commit = B_TRUE;
+ return;
+ } else {
+ /*
+ * unqualified admin removal.
+ * remove all admins but prompt if more
+ * than one.
+ */
+ if (!prompt_remove_resource(cmd, "admin"))
+ return;
+
+ if ((err = zonecfg_delete_admins(handle, zone))
+ != Z_OK)
+ z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
+ err, B_TRUE);
+ else
+ need_to_commit = B_TRUE;
+ }
+}
+
+static void
remove_resource(cmd_t *cmd)
{
int type;
@@ -3207,6 +3373,9 @@
case RT_MCAP:
remove_mcap();
return;
+ case RT_ADMIN:
+ remove_admin(cmd);
+ return;
default:
zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
long_usage(CMD_REMOVE, B_TRUE);
@@ -3670,6 +3839,16 @@
bzero(&in_progress_mcaptab,
sizeof (in_progress_mcaptab));
return;
+ case RT_ADMIN:
+ if ((err = fill_in_admintab(cmd, &old_admintab, B_FALSE))
+ != Z_OK) {
+ z_cmd_rt_perror(CMD_SELECT, RT_ADMIN, err,
+ B_TRUE);
+ global_scope = B_TRUE;
+ }
+ bcopy(&old_admintab, &in_progress_admintab,
+ sizeof (struct zone_admintab));
+ return;
default:
zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
long_usage(CMD_SELECT, B_TRUE);
@@ -4535,8 +4714,26 @@
usage(B_FALSE, HELP_PROPS);
return;
}
-
- return;
+ return;
+ case RT_ADMIN:
+ switch (prop_type) {
+ case PT_USER:
+ (void) strlcpy(in_progress_admintab.zone_admin_user,
+ prop_id,
+ sizeof (in_progress_admintab.zone_admin_user));
+ return;
+ case PT_AUTHS:
+ (void) strlcpy(in_progress_admintab.zone_admin_auths,
+ prop_id,
+ sizeof (in_progress_admintab.zone_admin_auths));
+ return;
+ default:
+ zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
+ B_TRUE);
+ long_usage(CMD_SET, B_TRUE);
+ usage(B_FALSE, HELP_PROPS);
+ return;
+ }
default:
zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
long_usage(CMD_SET, B_TRUE);
@@ -5160,6 +5357,48 @@
output_mcap(fp, &lookup, res2, swap_limit, res3, locked_limit);
}
+static void
+output_auth(FILE *fp, struct zone_admintab *admintab)
+{
+ (void) fprintf(fp, "%s:\n", rt_to_str(RT_ADMIN));
+ output_prop(fp, PT_USER, admintab->zone_admin_user, B_TRUE);
+ output_prop(fp, PT_AUTHS, admintab->zone_admin_auths, B_TRUE);
+}
+
+static void
+info_auth(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
+{
+ struct zone_admintab lookup, user;
+ boolean_t output = B_FALSE;
+ int err;
+
+ if ((err = zonecfg_setadminent(handle)) != Z_OK) {
+ zone_perror(zone, err, B_TRUE);
+ return;
+ }
+ while (zonecfg_getadminent(handle, &lookup) == Z_OK) {
+ if (cmd->cmd_prop_nv_pairs == 0) {
+ output_auth(fp, &lookup);
+ continue;
+ }
+ if (fill_in_admintab(cmd, &user, B_TRUE) != Z_OK)
+ continue;
+ if (strlen(user.zone_admin_user) > 0 &&
+ strcmp(user.zone_admin_user, lookup.zone_admin_user) != 0)
+ continue; /* no match */
+ output_auth(fp, &lookup);
+ output = B_TRUE;
+ }
+ (void) zonecfg_endadminent(handle);
+ /*
+ * If a property n/v pair was specified, warn the user if there was
+ * nothing to output.
+ */
+ if (!output && cmd->cmd_prop_nv_pairs > 0)
+ (void) printf(gettext("No such %s resource.\n"),
+ rt_to_str(RT_ADMIN));
+}
+
void
info_func(cmd_t *cmd)
{
@@ -5232,6 +5471,9 @@
output_mcap(fp, &in_progress_mcaptab, res1, swap_limit,
res2, locked_limit);
break;
+ case RT_ADMIN:
+ output_auth(fp, &in_progress_admintab);
+ break;
}
goto cleanup;
}
@@ -5284,6 +5526,7 @@
if (!global_zone) {
info_attr(handle, fp, cmd);
info_ds(handle, fp, cmd);
+ info_auth(handle, fp, cmd);
}
info_rctl(handle, fp, cmd);
break;
@@ -5365,6 +5608,9 @@
case RT_HOSTID:
info_hostid(handle, fp);
break;
+ case RT_ADMIN:
+ info_auth(handle, fp, cmd);
+ break;
default:
zone_perror(rt_to_str(cmd->cmd_res_type), Z_NO_RESOURCE_TYPE,
B_TRUE);
@@ -5499,6 +5745,7 @@
struct zone_rctltab rctltab;
struct zone_dstab dstab;
struct zone_psettab psettab;
+ struct zone_admintab admintab;
char zonepath[MAXPATHLEN];
char sched[MAXNAMELEN];
char brand[MAXNAMELEN];
@@ -5737,6 +5984,29 @@
}
(void) zonecfg_enddsent(handle);
+ if ((err = zonecfg_setadminent(handle)) != Z_OK) {
+ zone_perror(zone, err, B_TRUE);
+ return;
+ }
+ while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
+ check_reqd_prop(admintab.zone_admin_user, RT_ADMIN,
+ PT_USER, &ret_val);
+ check_reqd_prop(admintab.zone_admin_auths, RT_ADMIN,
+ PT_AUTHS, &ret_val);
+ if ((ret_val == Z_OK) && (getpwnam(admintab.zone_admin_user)
+ == NULL)) {
+ zerr(gettext("%s %s is not a valid username"),
+ pt_to_str(PT_USER),
+ admintab.zone_admin_user);
+ ret_val = Z_BAD_PROPERTY;
+ }
+ if ((ret_val == Z_OK) && (!zonecfg_valid_auths(
+ admintab.zone_admin_auths, zone))) {
+ ret_val = Z_BAD_PROPERTY;
+ }
+ }
+ (void) zonecfg_endadminent(handle);
+
if (!global_scope) {
zerr(gettext("resource specification incomplete"));
saw_error = B_TRUE;
@@ -5895,6 +6165,7 @@
struct zone_rctltab tmp_rctltab;
struct zone_attrtab tmp_attrtab;
struct zone_dstab tmp_dstab;
+ struct zone_admintab tmp_admintab;
int err, arg, res1, res2, res3;
uint64_t swap_limit;
uint64_t locked_limit;
@@ -6289,6 +6560,58 @@
(void) zonecfg_delete_mcap(handle);
}
break;
+ case RT_ADMIN:
+ /* First make sure everything was filled in. */
+ if (end_check_reqd(in_progress_admintab.zone_admin_user,
+ PT_USER, &validation_failed) == Z_OK) {
+ if (getpwnam(in_progress_admintab.zone_admin_user)
+ == NULL) {
+ zerr(gettext("%s %s is not a valid username"),
+ pt_to_str(PT_USER),
+ in_progress_admintab.zone_admin_user);
+ validation_failed = B_TRUE;
+ }
+ }
+
+ if (end_check_reqd(in_progress_admintab.zone_admin_auths,
+ PT_AUTHS, &validation_failed) == Z_OK) {
+ if (!zonecfg_valid_auths(
+ in_progress_admintab.zone_admin_auths,
+ zone)) {
+ validation_failed = B_TRUE;
+ }
+ }
+
+ if (validation_failed) {
+ saw_error = B_TRUE;
+ return;
+ }
+
+ if (end_op == CMD_ADD) {
+ /* Make sure there isn't already one like this. */
+ bzero(&tmp_admintab, sizeof (tmp_admintab));
+ (void) strlcpy(tmp_admintab.zone_admin_user,
+ in_progress_admintab.zone_admin_user,
+ sizeof (tmp_admintab.zone_admin_user));
+ err = zonecfg_lookup_admin(
+ handle, &tmp_admintab);
+ if (err == Z_OK) {
+ zerr(gettext("A %s resource "
+ "with the %s '%s' already exists."),
+ rt_to_str(RT_ADMIN),
+ pt_to_str(PT_USER),
+ in_progress_admintab.zone_admin_user);
+ saw_error = B_TRUE;
+ return;
+ }
+ err = zonecfg_add_admin(handle,
+ &in_progress_admintab, zone);
+ } else {
+ err = zonecfg_modify_admin(handle,
+ &old_admintab, &in_progress_admintab,
+ zone);
+ }
+ break;
default:
zone_perror(rt_to_str(resource_scope), Z_NO_RESOURCE_TYPE,
B_TRUE);
@@ -6416,6 +6739,12 @@
}
/*
+ * Reset any pending admins that were
+ * removed from the previous zone
+ */
+ zonecfg_remove_userauths(handle, "", zone, B_FALSE);
+
+ /*
* Time for a new handle: finish the old one off first
* then get a new one properly to avoid leaks.
*/
@@ -6424,6 +6753,7 @@
zone_perror(execname, Z_NOMEM, B_TRUE);
exit(Z_ERR);
}
+
if ((err = zonecfg_get_handle(revert_zone, handle)) != Z_OK) {
saw_error = B_TRUE;
got_handle = B_FALSE;
--- a/usr/src/cmd/zonecfg/zonecfg.h Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/cmd/zonecfg/zonecfg.h Mon Jun 07 14:07:27 2010 -0700
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _ZONECFG_H
@@ -89,9 +88,10 @@
#define RT_IPTYPE 24 /* really a property, but for info ... */
#define RT_PCAP 25
#define RT_HOSTID 26 /* really a property, but for info ... */
+#define RT_ADMIN 27
#define RT_MIN RT_UNKNOWN
-#define RT_MAX RT_HOSTID
+#define RT_MAX RT_ADMIN
/* property types: increment PT_MAX when expanding this list */
#define PT_UNKNOWN 0
@@ -131,9 +131,11 @@
#define PT_IPTYPE 34
#define PT_DEFROUTER 35
#define PT_HOSTID 36
+#define PT_USER 37
+#define PT_AUTHS 38
#define PT_MIN PT_UNKNOWN
-#define PT_MAX PT_HOSTID
+#define PT_MAX PT_AUTHS
#define MAX_EQ_PROP_PAIRS 3
--- a/usr/src/cmd/zonecfg/zonecfg_grammar.y Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/cmd/zonecfg/zonecfg_grammar.y Mon Jun 07 14:07:27 2010 -0700
@@ -21,8 +21,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <stdio.h>
@@ -128,15 +127,16 @@
%token NAME MATCH PRIV LIMIT ACTION VALUE EQUAL OPEN_SQ_BRACKET CLOSE_SQ_BRACKET
%token OPEN_PAREN CLOSE_PAREN COMMA DATASET LIMITPRIV BOOTARGS BRAND PSET PCAP
%token MCAP NCPUS IMPORTANCE SHARES MAXLWPS MAXSHMMEM MAXSHMIDS MAXMSGIDS
-%token MAXSEMIDS LOCKED SWAP SCHED CLEAR DEFROUTER
+%token MAXSEMIDS LOCKED SWAP SCHED CLEAR DEFROUTER ADMIN USER AUTHS
%type <strval> TOKEN EQUAL OPEN_SQ_BRACKET CLOSE_SQ_BRACKET
property_value OPEN_PAREN CLOSE_PAREN COMMA simple_prop_val
%type <complex> complex_piece complex_prop_val
%type <ival> resource_type NET FS IPD DEVICE RCTL ATTR DATASET PSET PCAP MCAP
+ ADMIN
%type <ival> property_name SPECIAL RAW DIR OPTIONS TYPE ADDRESS PHYSICAL NAME
MATCH ZONENAME ZONEPATH AUTOBOOT POOL LIMITPRIV BOOTARGS VALUE PRIV LIMIT
- ACTION BRAND SCHED IPTYPE DEFROUTER HOSTID
+ ACTION BRAND SCHED IPTYPE DEFROUTER HOSTID USER AUTHS
%type <cmd> command
%type <cmd> add_command ADD
%type <cmd> cancel_command CANCEL
@@ -924,6 +924,7 @@
| PSET { $$ = RT_DCPU; }
| PCAP { $$ = RT_PCAP; }
| MCAP { $$ = RT_MCAP; }
+ | ADMIN { $$ = RT_ADMIN; }
property_name: SPECIAL { $$ = PT_SPECIAL; }
| RAW { $$ = PT_RAW; }
@@ -959,6 +960,8 @@
| MAXSEMIDS { $$ = PT_MAXSEMIDS; }
| SCHED { $$ = PT_SCHED; }
| HOSTID { $$ = PT_HOSTID; }
+ | USER { $$ = PT_USER; }
+ | AUTHS { $$ = PT_AUTHS; }
/*
* The grammar builds data structures from the bottom up. Thus various
--- a/usr/src/cmd/zonecfg/zonecfg_lex.l Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/cmd/zonecfg/zonecfg_lex.l Mon Jun 07 14:07:27 2010 -0700
@@ -21,8 +21,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <string.h>
@@ -38,8 +37,8 @@
char *safe_strdup(char *s);
%}
-%a 6000
-%p 4000
+%a 7000
+%p 5000
%e 2000
%n 1000
@@ -164,6 +163,8 @@
<TSTATE>attr { return ATTR; }
+<TSTATE>admin { return ADMIN; }
+
<TSTATE>zonename { return ZONENAME; }
<CSTATE>zonename { return ZONENAME; }
@@ -274,6 +275,12 @@
<TSTATE>hostid { return HOSTID; }
<CSTATE>hostid { return HOSTID; }
+<TSTATE>user { return USER; }
+<CSTATE>user { return USER; }
+
+<TSTATE>auths { return AUTHS; }
+<CSTATE>auths { return AUTHS; }
+
<TSTATE>= { return EQUAL; }
<LSTATE>= { return EQUAL; }
<CSTATE>= { return EQUAL; }
--- a/usr/src/head/auth_list.h Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/head/auth_list.h Mon Jun 07 14:07:27 2010 -0700
@@ -18,9 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
*
* This is an internal header file. Not to be shipped.
*/
@@ -56,7 +56,16 @@
#define HP_MODIFY_AUTH "solaris.hotplug.modify"
/*
- * Authorizations used by Trusted Solaris.
+ * The following authorizations can be qualified by appending <zonename>
+ */
+#define ZONE_CLONEFROM_AUTH "solaris.zone.clonefrom"
+#define ZONE_LOGIN_AUTH "solaris.zone.login"
+#define ZONE_MANAGE_AUTH "solaris.zone.manage"
+
+#define ZONE_AUTH_PREFIX "solaris.zone."
+
+/*
+ * Authorizations used by Trusted Extensions.
*/
#define BYPASS_FILE_VIEW_AUTH "solaris.label.win.noview"
#define DEVICE_CONFIG_AUTH "solaris.device.config"
--- a/usr/src/head/libzonecfg.h Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/head/libzonecfg.h Mon Jun 07 14:07:27 2010 -0700
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _LIBZONECFG_H
@@ -50,6 +49,8 @@
#include <sys/uuid.h>
#include <libuutil.h>
#include <sys/mnttab.h>
+#include <limits.h>
+#include <utmpx.h>
#define ZONE_ID_UNDEFINED -1
@@ -122,6 +123,10 @@
#define ZONE_CONFIG_ROOT "/etc/zones"
#define ZONE_INDEX_FILE ZONE_CONFIG_ROOT "/index"
+#define MAXUSERNAME (sizeof (((struct utmpx *)0)->ut_name))
+#define MAXAUTHS 4096
+#define ZONE_MGMT_PROF "Zone Management"
+
/* Owner, group, and mode (defined by packaging) for the config directory */
#define ZONE_CONFIG_UID 0 /* root */
#define ZONE_CONFIG_GID 3 /* sys */
@@ -244,6 +249,17 @@
char *zone_devperm_acl;
};
+struct zone_admintab {
+ char zone_admin_user[MAXUSERNAME];
+ char zone_admin_auths[MAXAUTHS];
+};
+
+typedef struct zone_userauths {
+ char user[MAXUSERNAME];
+ char zonename[ZONENAME_MAX];
+ struct zone_userauths *next;
+} zone_userauths_t;
+
typedef struct {
uu_avl_node_t zpe_entry;
char *zpe_name;
@@ -484,6 +500,9 @@
extern int zonecfg_getdevperment(zone_dochandle_t,
struct zone_devpermtab *);
extern int zonecfg_enddevperment(zone_dochandle_t);
+extern int zonecfg_setadminent(zone_dochandle_t);
+extern int zonecfg_getadminent(zone_dochandle_t, struct zone_admintab *);
+extern int zonecfg_endadminent(zone_dochandle_t);
/*
* Privilege-related functions.
@@ -565,6 +584,22 @@
extern int zonecfg_ping_zoneadmd(const char *);
extern int zonecfg_call_zoneadmd(const char *, zone_cmd_arg_t *, char *,
boolean_t);
+extern int zonecfg_insert_userauths(zone_dochandle_t, char *, char *);
+extern int zonecfg_remove_userauths(zone_dochandle_t, char *, char *,
+ boolean_t);
+extern int zonecfg_add_admin(zone_dochandle_t, struct zone_admintab *,
+ char *);
+extern int zonecfg_delete_admin(zone_dochandle_t,
+ struct zone_admintab *, char *);
+extern int zonecfg_modify_admin(zone_dochandle_t, struct zone_admintab *,
+ struct zone_admintab *, char *);
+extern int zonecfg_delete_admins(zone_dochandle_t, char *);
+extern int zonecfg_lookup_admin(zone_dochandle_t, struct zone_admintab *);
+extern int zonecfg_authorize_users(zone_dochandle_t, char *);
+extern int zonecfg_update_userauths(zone_dochandle_t, char *);
+extern int zonecfg_deauthorize_user(zone_dochandle_t, char *, char *);
+extern int zonecfg_deauthorize_users(zone_dochandle_t, char *);
+extern boolean_t zonecfg_valid_auths(const char *, const char *);
#ifdef __cplusplus
}
--- a/usr/src/head/secdb.h Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/head/secdb.h Mon Jun 07 14:07:27 2010 -0700
@@ -50,6 +50,8 @@
#define KV_ACTION_WILDCARD "*;*;*;*;*"
#define KV_SEPCHAR ','
#define KV_SEPSTR ","
+#define KV_OBJECTCHAR '/'
+#define KV_OBJECT "/"
#define KV_FLAG_NONE 0x0000
#define KV_FLAG_REQUIRED 0x0001
--- a/usr/src/lib/brand/ipkg/zone/config.xml Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/lib/brand/ipkg/zone/config.xml Mon Jun 07 14:07:27 2010 -0700
@@ -20,8 +20,7 @@
CDDL HEADER END
- Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- Use is subject to license terms.
+ Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
DO NOT EDIT THIS FILE.
-->
@@ -33,7 +32,8 @@
<modname></modname>
<initname>/sbin/init</initname>
- <login_cmd>/usr/bin/login -z %Z -f %u</login_cmd>
+ <login_cmd>/usr/bin/login -z %Z %u</login_cmd>
+ <forcedlogin_cmd>/usr/bin/login -z %Z -f %u</forcedlogin_cmd>
<user_cmd>/usr/bin/getent passwd %u</user_cmd>
<!-- We may not be able to do the create in pkg(1) proper. -->
--- a/usr/src/lib/brand/labeled/zone/config.xml Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/lib/brand/labeled/zone/config.xml Mon Jun 07 14:07:27 2010 -0700
@@ -20,8 +20,7 @@
CDDL HEADER END
- Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- Use is subject to license terms.
+ Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
DO NOT EDIT THIS FILE.
-->
@@ -33,7 +32,9 @@
<modname></modname>
<initname>/sbin/init</initname>
- <login_cmd>/usr/bin/login -z %Z -f %u</login_cmd>
+ <login_cmd>/usr/bin/login -z %Z %u</login_cmd>
+ <forcedlogin_cmd>/usr/bin/login -z %Z -f %u</forcedlogin_cmd>
+
<user_cmd>/usr/bin/getent passwd %u</user_cmd>
<!-- We may not be able to do the create in pkg(1) proper. -->
--- a/usr/src/lib/brand/lx/zone/config.xml Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/lib/brand/lx/zone/config.xml Mon Jun 07 14:07:27 2010 -0700
@@ -20,10 +20,7 @@
CDDL HEADER END
- Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- Use is subject to license terms.
-
- ident "%Z%%M% %I% %E% SMI"
+ Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
DO NOT EDIT THIS FILE.
-->
@@ -35,7 +32,8 @@
<modname>lx_brand</modname>
<initname>/sbin/init</initname>
- <login_cmd>/bin/login -h zone:%Z -f %u</login_cmd>
+ <login_cmd>/bin/login -h zone:%Z %u</login_cmd>
+ <forcedlogin_cmd>/bin/login -h zone:%Z -f %u</forcedlogin_cmd>
<user_cmd>/usr/bin/getent passwd %u</user_cmd>
<install>/usr/lib/brand/lx/lx_install %z %R</install>
--- a/usr/src/lib/brand/sn1/zone/config.xml Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/lib/brand/sn1/zone/config.xml Mon Jun 07 14:07:27 2010 -0700
@@ -20,8 +20,7 @@
CDDL HEADER END
- Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- Use is subject to license terms.
+ Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
DO NOT EDIT THIS FILE.
-->
@@ -33,7 +32,9 @@
<modname>sn1_brand</modname>
<initname>/sbin/init</initname>
- <login_cmd>/usr/bin/login -z %Z -f %u</login_cmd>
+ <login_cmd>/usr/bin/login -z %Z %u</login_cmd>
+ <forcedlogin_cmd>/usr/bin/login -z %Z -f %u</forcedlogin_cmd>
+
<user_cmd>/usr/bin/getent passwd %u</user_cmd>
<install>/usr/lib/brand/ipkg/pkgcreatezone -z %z -R %R</install>
--- a/usr/src/lib/brand/solaris10/zone/config.xml Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/lib/brand/solaris10/zone/config.xml Mon Jun 07 14:07:27 2010 -0700
@@ -20,8 +20,7 @@
CDDL HEADER END
- Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- Use is subject to license terms.
+ Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
DO NOT EDIT THIS FILE.
-->
@@ -32,7 +31,8 @@
<brand name="solaris10">
<modname>s10_brand</modname>
<initname>/sbin/init</initname>
- <login_cmd>/usr/bin/login -z %Z -f %u</login_cmd>
+ <login_cmd>/usr/bin/login -z %Z %u</login_cmd>
+ <forcedlogin_cmd>/usr/bin/login -z %Z -f %u</forcedlogin_cmd>
<user_cmd>/usr/bin/getent passwd %u</user_cmd>
<install>/usr/lib/brand/solaris10/image_install %z %R</install>
--- a/usr/src/lib/libbrand/common/libbrand.c Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/lib/libbrand/common/libbrand.c Mon Jun 07 14:07:27 2010 -0700
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <assert.h>
@@ -58,6 +57,7 @@
#define DTD_ELEM_INSTALL ((const xmlChar *) "install")
#define DTD_ELEM_INSTALLOPTS ((const xmlChar *) "installopts")
#define DTD_ELEM_LOGIN_CMD ((const xmlChar *) "login_cmd")
+#define DTD_ELEM_FORCELOGIN_CMD ((const xmlChar *) "forcedlogin_cmd")
#define DTD_ELEM_MODNAME ((const xmlChar *) "modname")
#define DTD_ELEM_MOUNT ((const xmlChar *) "mount")
#define DTD_ELEM_POSTATTACH ((const xmlChar *) "postattach")
@@ -520,6 +520,16 @@
}
int
+brand_get_forcedlogin_cmd(brand_handle_t bh, const char *username,
+ char *buf, size_t len)
+{
+ struct brand_handle *bhp = (struct brand_handle *)bh;
+ const char *curr_zone = get_curr_zone();
+ return (brand_get_value(bhp, NULL, NULL, username, curr_zone,
+ buf, len, DTD_ELEM_FORCELOGIN_CMD, B_TRUE, B_FALSE));
+}
+
+int
brand_get_user_cmd(brand_handle_t bh, const char *username,
char *buf, size_t len)
{
--- a/usr/src/lib/libbrand/common/libbrand.h Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/lib/libbrand/common/libbrand.h Mon Jun 07 14:07:27 2010 -0700
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _LIBBRAND_H
@@ -62,6 +61,8 @@
char *, size_t);
extern int brand_get_installopts(brand_handle_t, char *, size_t);
extern int brand_get_login_cmd(brand_handle_t, const char *, char *, size_t);
+extern int brand_get_forcedlogin_cmd(brand_handle_t, const char *,
+ char *, size_t);
extern int brand_get_modname(brand_handle_t, char *, size_t);
extern int brand_get_postattach(brand_handle_t, const char *, const char *,
char *, size_t);
--- a/usr/src/lib/libbrand/common/mapfile-vers Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/lib/libbrand/common/mapfile-vers Mon Jun 07 14:07:27 2010 -0700
@@ -19,8 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
#
#
@@ -47,6 +46,7 @@
brand_get_brandname;
brand_get_clone;
brand_get_detach;
+ brand_get_forcedlogin_cmd;
brand_get_halt;
brand_get_initname;
brand_get_install;
--- a/usr/src/lib/libbrand/dtd/brand.dtd.1 Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/lib/libbrand/dtd/brand.dtd.1 Mon Jun 07 14:07:27 2010 -0700
@@ -20,8 +20,7 @@
CDDL HEADER END
- Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- Use is subject to license terms.
+ Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
DO NOT EDIT THIS FILE.
-->
@@ -205,6 +204,22 @@
<!ATTLIST login_cmd>
<!--
+ forcedlogin_cmd
+
+ Path to the initial login binary that should be executed when
+ attempting to zlogin into a branded zone without authentication.
+
+ The following replacements are performed:
+
+ %Z Name of the current zone
+ %u User login name
+
+ It has no attributes.
+-->
+<!ELEMENT forcedlogin_cmd (#PCDATA) >
+<!ATTLIST forcedlogin_cmd>
+
+<!--
user_cmd
Path to the binary that will translate a user name to a passwd(4) entry.
@@ -588,7 +603,8 @@
directory in which the configuration file is stored.
-->
-<!ELEMENT brand (modname?, initname, login_cmd, user_cmd, install,
+<!ELEMENT brand (modname?, initname, login_cmd, forcedlogin_cmd,
+ user_cmd, install,
installopts?, boot?, sysboot?, halt?, verify_cfg?,
verify_adm?, postattach?, postclone?, postinstall?,
predetach?, attach?, detach?, clone?,
--- a/usr/src/lib/libsecdb/auth_attr.txt Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/lib/libsecdb/auth_attr.txt Mon Jun 07 14:07:27 2010 -0700
@@ -202,3 +202,7 @@
solaris.smf.value.isns:::Modify iSNS Service Property Values::help=isnsValue.html
solaris.isnsmgr.write:::Modify iSNS configuration::help=AuthISNSmgrWrite.html
solaris.smf.manage.wusb:::Manage Wireless USB Service::help=SmfWusbStates.html
+solaris.zone.:::Zone Management::help=ZoneHeader.html
+solaris.zone.clonefrom:::Clone another Zone::help=ZoneCloneFrom.html
+solaris.zone.login:::Zone Login::help=ZoneLogin.html
+solaris.zone.manage:::Zone Deployment::help=ZoneManage.html
--- a/usr/src/lib/libsecdb/common/chkauthattr.c Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/lib/libsecdb/common/chkauthattr.c Mon Jun 07 14:07:27 2010 -0700
@@ -82,6 +82,8 @@
/*
* Enumerate profiles from listed profiles.
*/
+static int _auth_match_noun(const char *, const char *, size_t, const char *);
+
int
_enum_common_p(const char *cprofiles,
int (*cb)(const char *, kva_t *, void *, void *),
@@ -288,45 +290,90 @@
}
int
-_auth_match(const char *pattern, const char *auth)
+_auth_match_noun(const char *pattern, const char *auth,
+ size_t auth_len, const char *auth_noun)
{
- size_t len;
+ size_t pattern_len;
char *grant;
+ char *pattern_noun;
+ char *slash;
- len = strlen(pattern);
+ pattern_len = strlen(pattern);
+ /*
+ * If the specified authorization has a trailing object
+ * and the current authorization we're checking also has
+ * a trailing object, the object names must match.
+ *
+ * If there is no object name failure, then we must
+ * check for an exact match of the two authorizations
+ */
+ if (auth_noun != NULL) {
+ if ((slash = strchr(pattern, KV_OBJECTCHAR)) != NULL) {
+ pattern_noun = slash + 1;
+ pattern_len -= strlen(slash);
+ if (strcmp(pattern_noun, auth_noun) != 0)
+ return (0);
+ } else if ((auth_len == pattern_len) &&
+ (strncmp(pattern, auth, pattern_len) == 0)) {
+ return (1);
+ }
+ }
/*
* If the wildcard is not in the last position in the string, don't
* match against it.
*/
- if (pattern[len-1] != KV_WILDCHAR)
+ if (pattern[pattern_len-1] != KV_WILDCHAR)
return (0);
/*
* If the strings are identical up to the wildcard and auth does not
* end in "grant", then we have a match.
*/
- if (strncmp(pattern, auth, len-1) == 0) {
+ if (strncmp(pattern, auth, pattern_len - 1) == 0) {
grant = strrchr(auth, '.');
if (grant != NULL) {
if (strncmp(grant + 1, "grant", 5) != NULL)
return (1);
}
}
+ return (0);
+}
- return (0);
+int
+_auth_match(const char *pattern, const char *auth)
+{
+ return (_auth_match_noun(pattern, auth, strlen(auth), NULL));
}
static int
_is_authorized(const char *auth, void *authname, void *res)
{
int *resp = res;
+ char *authname_noun;
+ char *slash;
+ size_t auth_len;
+ size_t noun_len;
- if (strcmp(authname, auth) == 0 ||
- (strchr(auth, KV_WILDCHAR) != NULL &&
- _auth_match(auth, authname))) {
+ auth_len = strlen(authname);
+ if ((slash = strchr(authname, KV_OBJECTCHAR)) != NULL) {
+ authname_noun = slash + 1;
+ noun_len = strlen(slash);
+ auth_len -= noun_len;
+ } else {
+ authname_noun = NULL;
+ }
+
+ if (strcmp(authname, auth) == 0) {
+ /* exact match, we're done */
*resp = 1;
return (1);
+ } else if (noun_len || strchr(auth, KV_WILDCHAR) != NULL) {
+ if (_auth_match_noun(auth, authname,
+ auth_len, authname_noun)) {
+ *resp = 1;
+ return (1);
+ }
}
return (0);
--- a/usr/src/lib/libsecdb/exec_attr.txt Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/lib/libsecdb/exec_attr.txt Mon Jun 07 14:07:27 2010 -0700
@@ -305,8 +305,8 @@
ZFS File System Management:solaris:cmd:::/sbin/zfs:euid=0
ZFS Storage Management:solaris:cmd:::/sbin/zpool:uid=0
ZFS Storage Management:solaris:cmd:::/usr/lib/zfs/availdevs:uid=0
-Zone Management:solaris:cmd:::/usr/sbin/txzonemgr:uid=0
-Zone Management:solaris:cmd:::/usr/sbin/zonecfg:uid=0
-Zone Management:solaris:cmd:::/usr/sbin/zoneadm:uid=0
-Zone Management:solaris:cmd:::/usr/sbin/zlogin:uid=0
+Zone Security:solaris:cmd:::/usr/sbin/txzonemgr:uid=0
+Zone Security:solaris:cmd:::/usr/sbin/zonecfg:uid=0
+Zone Management:solaris:cmd:::/usr/sbin/zoneadm:euid=0
+Zone Management:solaris:cmd:::/usr/sbin/zlogin:euid=0
acctadm:solaris:cmd:::/usr/sbin/acctadm:euid=0;egid=0;privs=sys_acct,file_dac_write
--- a/usr/src/lib/libsecdb/help/auths/Makefile Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/lib/libsecdb/help/auths/Makefile Mon Jun 07 14:07:27 2010 -0700
@@ -167,7 +167,11 @@
SysCpuPowerMgmt.html \
SysSyseventRead.html \
SysSyseventWrite.html \
- SmfManageZFSSnap.html
+ SmfManageZFSSnap.html \
+ ZoneCloneFrom.html \
+ ZoneHeader.html \
+ ZoneLogin.html \
+ ZoneManage.html
HELPDIR=$(ROOT)/usr/lib/help
AUTHDIR=$(HELPDIR)/auths
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsecdb/help/auths/ZoneCloneFrom.html Mon Jun 07 14:07:27 2010 -0700
@@ -0,0 +1,33 @@
+<HTML>
+<!--
+ Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+ 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
+
+-->
+<!--
+ <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+ <META NAME="GENERATOR" CONTENT="Mozilla/4.02 [en] (X11; U; SunOS 5.6 sun4u) [Netscape]">
+-->
+<BODY>
+This authorization allows a user to make a clone from an existing zone. The name of a specific zone may optionally be appended to the authorization, preceded by a slash.
+<BR>
+</BODY>
+</HTML>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsecdb/help/auths/ZoneHeader.html Mon Jun 07 14:07:27 2010 -0700
@@ -0,0 +1,32 @@
+<HTML>
+<!--
+ Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+ 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
+-->
+<!--
+ <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+ <META NAME="GENERATOR" CONTENT="Mozilla/4.02 [en] (X11; U; SunOS 5.6 sun4u) [Netscape]">
+-->
+<BODY>
+These authorizations specify the zones management operations for the user. The name of a specific zone may optionally be appended to the authorization, preceded by a slash.
+<BR>
+</BODY>
+</HTML>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsecdb/help/auths/ZoneLogin.html Mon Jun 07 14:07:27 2010 -0700
@@ -0,0 +1,32 @@
+<HTML>
+<!--
+ Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+ 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
+-->
+<!--
+ <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+ <META NAME="GENERATOR" CONTENT="Mozilla/4.02 [en] (X11; U; SunOS 5.6 sun4u) [Netscape]">
+-->
+<BODY>
+This authorization allows a user to login to a zone if authentication is successful. The name of a specific zone may optionally be appended to the authorization, preceded by a slash.
+<BR>
+</BODY>
+</HTML>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsecdb/help/auths/ZoneManage.html Mon Jun 07 14:07:27 2010 -0700
@@ -0,0 +1,32 @@
+<HTML>
+<!--
+ Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+ 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
+-->
+<!--
+ <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+ <META NAME="GENERATOR" CONTENT="Mozilla/4.02 [en] (X11; U; SunOS 5.6 sun4u) [Netscape]">
+-->
+<BODY>
+This authorization allows a user to install, update, boot or halt a zone. It also allows unauthenticated access to a running zone and its console. The name of a specific zone may optionally be appended to the authorization, preceded by a slash.
+<BR>
+</BODY>
+</HTML>
--- a/usr/src/lib/libsecdb/help/profiles/Makefile Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/lib/libsecdb/help/profiles/Makefile Mon Jun 07 14:07:27 2010 -0700
@@ -86,6 +86,7 @@
RtZFSFileSysMngmnt.html \
RtZFSStorageMngmnt.html \
RtZoneMngmnt.html \
+ RtZoneSecurity.html \
RtInfoSec.html \
RtObjectLabelMngmnt.html \
RtOutsideAccred.html \
--- a/usr/src/lib/libsecdb/help/profiles/RtZoneMngmnt.html Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/lib/libsecdb/help/profiles/RtZoneMngmnt.html Mon Jun 07 14:07:27 2010 -0700
@@ -3,9 +3,8 @@
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.
+ 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.
@@ -20,8 +19,7 @@
CDDL HEADER END
--- Copyright 2003 Sun Microsystems, Inc. All rights reserved.
--- Use is subject to license terms.
+ Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
-->
<HEAD>
<TITLE> </TITLE>
@@ -29,7 +27,6 @@
</HEAD>
<BODY>
-<!-- ident "%Z%%M% %I% %E% SMI" -->
When Zones Management is in the Rights Included column, it grants the right to
use commands needed to administer Solaris Zones.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsecdb/help/profiles/RtZoneSecurity.html Mon Jun 07 14:07:27 2010 -0700
@@ -0,0 +1,37 @@
+<HTML>
+<!--
+ 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) 2010, Oracle and/or its affiliates. All rights reserved.
+-->
+<HEAD>
+ <TITLE> </TITLE>
+
+
+</HEAD>
+<BODY>
+
+When Zones Security is in the Rights Included column, it grants the right to
+use commands needed to configure Solaris Zones and delegate authorizations.
+<p>
+If Zones Security is grayed, then you are not entitled to Add or Remove this right.
+<p>
+</BODY>
+</HTML>
--- a/usr/src/lib/libsecdb/prof_attr.txt Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/lib/libsecdb/prof_attr.txt Mon Jun 07 14:07:27 2010 -0700
@@ -95,6 +95,7 @@
STMF Management:::Start/Stop STMF service:auths=solaris.smf.manage.stmf
ZFS File System Management:::Create and Manage ZFS File Systems:help=RtZFSFileSysMngmnt.html
ZFS Storage Management:::Create and Manage ZFS Storage Pools:help=RtZFSStorageMngmnt.html
+Zone Security:::Zones Virtual Application Environment Security:auths=solaris.zone.*,solaris.zone.grant;help=RtZoneSecurity.html
Zone Management:::Zones Virtual Application Environment Administration:help=RtZoneMngmnt.html
IP Filter Management:::IP Filter Administration:help=RtIPFilterMngmnt.html
Project Management:::Add/Modify/Remove projects:help=RtProjManagement.html
--- a/usr/src/lib/libzonecfg/Makefile.com Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/lib/libzonecfg/Makefile.com Mon Jun 07 14:07:27 2010 -0700
@@ -19,8 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
#
LIBRARY= libzonecfg.a
@@ -31,7 +30,7 @@
LIBS = $(DYNLIB) $(LINTLIB)
LDLIBS += -lc -lsocket -lnsl -luuid -lnvpair -lsysevent -lsec -lbrand \
- -lpool -lscf -lproc -luutil -lbsm
+ -lpool -lscf -lproc -luutil -lbsm -lsecdb
# DYNLIB libraries do not have lint libs and are not linted
$(DYNLIB) := LDLIBS += -lxml2
--- a/usr/src/lib/libzonecfg/common/libzonecfg.c Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/lib/libzonecfg/common/libzonecfg.c Mon Jun 07 14:07:27 2010 -0700
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <libsysevent.h>
@@ -53,6 +52,11 @@
#include <libuutil.h>
#include <wait.h>
#include <bsm/adt.h>
+#include <auth_attr.h>
+#include <auth_list.h>
+#include <secdb.h>
+#include <user_attr.h>
+#include <prof_attr.h>
#include <arpa/inet.h>
#include <netdb.h>
@@ -92,6 +96,7 @@
#define DTD_ELEM_PATCH (const xmlChar *) "patch"
#define DTD_ELEM_OBSOLETES (const xmlChar *) "obsoletes"
#define DTD_ELEM_DEV_PERM (const xmlChar *) "dev-perm"
+#define DTD_ELEM_ADMIN (const xmlChar *) "admin"
#define DTD_ATTR_ACTION (const xmlChar *) "action"
#define DTD_ATTR_ADDRESS (const xmlChar *) "address"
@@ -125,6 +130,8 @@
#define DTD_ATTR_ACL (const xmlChar *) "acl"
#define DTD_ATTR_BRAND (const xmlChar *) "brand"
#define DTD_ATTR_HOSTID (const xmlChar *) "hostid"
+#define DTD_ATTR_USER (const xmlChar *) "user"
+#define DTD_ATTR_AUTHS (const xmlChar *) "auths"
#define DTD_ENTITY_BOOLEAN "boolean"
#define DTD_ENTITY_DEVPATH "devpath"
@@ -189,6 +196,7 @@
boolean_t zone_dh_newzone;
boolean_t zone_dh_snapshot;
boolean_t zone_dh_sw_inv;
+ zone_userauths_t *zone_dh_userauths;
char zone_dh_delete_name[ZONENAME_MAX];
};
@@ -802,6 +810,27 @@
return (getrootattr(handle, DTD_ATTR_NAME, name, namesize));
}
+static int
+insert_admins(zone_dochandle_t handle, char *zonename)
+{
+ int err;
+ struct zone_admintab admintab;
+
+ if ((err = zonecfg_setadminent(handle)) != Z_OK) {
+ return (err);
+ }
+ while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
+ err = zonecfg_insert_userauths(handle,
+ admintab.zone_admin_user, zonename);
+ if (err != Z_OK) {
+ (void) zonecfg_endadminent(handle);
+ return (err);
+ }
+ }
+ (void) zonecfg_endadminent(handle);
+ return (Z_OK);
+}
+
int
zonecfg_set_name(zone_dochandle_t handle, char *name)
{
@@ -883,7 +912,14 @@
return (err);
}
- return (Z_OK);
+ /*
+ * Record the old admins from the old zonename
+ * so that they can be deleted when the operation is committed.
+ */
+ if ((err = insert_admins(handle, curname)) != Z_OK)
+ return (err);
+ else
+ return (Z_OK);
}
int
@@ -1258,6 +1294,11 @@
addcomment(handle, "\n DO NOT EDIT THIS "
"FILE. Use zonecfg(1M) instead.\n");
+ /*
+ * Update user_attr first so that it will be older
+ * than the config file.
+ */
+ (void) zonecfg_authorize_users(handle, zname);
err = zonecfg_save_impl(handle, path);
stripcomments(handle);
@@ -2571,6 +2612,157 @@
return (Z_OK);
}
+static int
+zonecfg_add_auth_core(zone_dochandle_t handle, struct zone_admintab *tabptr,
+ char *zonename)
+{
+ xmlNodePtr newnode, cur = handle->zone_dh_cur;
+ int err;
+
+ newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_ADMIN, NULL);
+ err = newprop(newnode, DTD_ATTR_USER, tabptr->zone_admin_user);
+ if (err != Z_OK)
+ return (err);
+ err = newprop(newnode, DTD_ATTR_AUTHS, tabptr->zone_admin_auths);
+ if (err != Z_OK)
+ return (err);
+ if ((err = zonecfg_remove_userauths(
+ handle, tabptr->zone_admin_user, zonename, B_FALSE)) != Z_OK)
+ return (err);
+ return (Z_OK);
+}
+
+int
+zonecfg_add_admin(zone_dochandle_t handle, struct zone_admintab *tabptr,
+ char *zonename)
+{
+ int err;
+
+ if (tabptr == NULL)
+ return (Z_INVAL);
+
+ if ((err = operation_prep(handle)) != Z_OK)
+ return (err);
+
+ if ((err = zonecfg_add_auth_core(handle, tabptr,
+ zonename)) != Z_OK)
+ return (err);
+
+ return (Z_OK);
+}
+static int
+zonecfg_delete_auth_core(zone_dochandle_t handle, struct zone_admintab *tabptr,
+ char *zonename)
+{
+ xmlNodePtr cur = handle->zone_dh_cur;
+ boolean_t auth_match;
+ int err;
+
+ for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
+ if (xmlStrcmp(cur->name, DTD_ELEM_ADMIN))
+ continue;
+ auth_match = match_prop(cur, DTD_ATTR_USER,
+ tabptr->zone_admin_user);
+ if (auth_match) {
+ if ((err = zonecfg_insert_userauths(
+ handle, tabptr->zone_admin_user,
+ zonename)) != Z_OK)
+ return (err);
+ xmlUnlinkNode(cur);
+ xmlFreeNode(cur);
+ return (Z_OK);
+ }
+ }
+ return (Z_NO_RESOURCE_ID);
+}
+
+int
+zonecfg_delete_admin(zone_dochandle_t handle, struct zone_admintab *tabptr,
+ char *zonename)
+{
+ int err;
+
+ if (tabptr == NULL)
+ return (Z_INVAL);
+
+ if ((err = operation_prep(handle)) != Z_OK)
+ return (err);
+
+ if ((err = zonecfg_delete_auth_core(handle, tabptr, zonename)) != Z_OK)
+ return (err);
+
+ return (Z_OK);
+}
+
+int
+zonecfg_modify_admin(zone_dochandle_t handle, struct zone_admintab *oldtabptr,
+ struct zone_admintab *newtabptr, char *zonename)
+{
+ int err;
+
+ if (oldtabptr == NULL || newtabptr == NULL)
+ return (Z_INVAL);
+
+ if ((err = operation_prep(handle)) != Z_OK)
+ return (err);
+
+ if ((err = zonecfg_delete_auth_core(handle, oldtabptr, zonename))
+ != Z_OK)
+ return (err);
+
+ if ((err = zonecfg_add_auth_core(handle, newtabptr,
+ zonename)) != Z_OK)
+ return (err);
+
+ return (Z_OK);
+}
+
+int
+zonecfg_lookup_admin(zone_dochandle_t handle, struct zone_admintab *tabptr)
+{
+ xmlNodePtr cur, firstmatch;
+ int err;
+ char user[MAXUSERNAME];
+
+ if (tabptr == NULL)
+ return (Z_INVAL);
+
+ if ((err = operation_prep(handle)) != Z_OK)
+ return (err);
+
+ cur = handle->zone_dh_cur;
+ firstmatch = NULL;
+ for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
+ if (xmlStrcmp(cur->name, DTD_ELEM_ADMIN))
+ continue;
+ if (strlen(tabptr->zone_admin_user) > 0) {
+ if ((fetchprop(cur, DTD_ATTR_USER, user,
+ sizeof (user)) == Z_OK) &&
+ (strcmp(tabptr->zone_admin_user, user) == 0)) {
+ if (firstmatch == NULL)
+ firstmatch = cur;
+ else
+ return (Z_INSUFFICIENT_SPEC);
+ }
+ }
+ }
+ if (firstmatch == NULL)
+ return (Z_NO_RESOURCE_ID);
+
+ cur = firstmatch;
+
+ if ((err = fetchprop(cur, DTD_ATTR_USER, tabptr->zone_admin_user,
+ sizeof (tabptr->zone_admin_user))) != Z_OK)
+ return (err);
+
+ if ((err = fetchprop(cur, DTD_ATTR_AUTHS, tabptr->zone_admin_auths,
+ sizeof (tabptr->zone_admin_auths))) != Z_OK)
+ return (err);
+
+ return (Z_OK);
+}
+
+
/* Lock to serialize all devwalks */
static pthread_mutex_t zonecfg_devwalk_lock = PTHREAD_MUTEX_INITIALIZER;
/*
@@ -3699,6 +3891,8 @@
return (DTD_ELEM_RCTL);
if (strcmp(nm, "dataset") == 0)
return (DTD_ELEM_DATASET);
+ if (strcmp(nm, "admin") == 0)
+ return (DTD_ELEM_ADMIN);
return (NULL);
}
@@ -4811,6 +5005,55 @@
return (zonecfg_endent(handle));
}
+int
+zonecfg_setadminent(zone_dochandle_t handle)
+{
+ return (zonecfg_setent(handle));
+}
+
+int
+zonecfg_getadminent(zone_dochandle_t handle, struct zone_admintab *tabptr)
+{
+ xmlNodePtr cur;
+ int err;
+
+ if (handle == NULL)
+ return (Z_INVAL);
+
+ if ((cur = handle->zone_dh_cur) == NULL)
+ return (Z_NO_ENTRY);
+
+ for (; cur != NULL; cur = cur->next)
+ if (!xmlStrcmp(cur->name, DTD_ELEM_ADMIN))
+ break;
+ if (cur == NULL) {
+ handle->zone_dh_cur = handle->zone_dh_top;
+ return (Z_NO_ENTRY);
+ }
+
+ if ((err = fetchprop(cur, DTD_ATTR_USER, tabptr->zone_admin_user,
+ sizeof (tabptr->zone_admin_user))) != Z_OK) {
+ handle->zone_dh_cur = handle->zone_dh_top;
+ return (err);
+ }
+
+
+ if ((err = fetchprop(cur, DTD_ATTR_AUTHS, tabptr->zone_admin_auths,
+ sizeof (tabptr->zone_admin_auths))) != Z_OK) {
+ handle->zone_dh_cur = handle->zone_dh_top;
+ return (err);
+ }
+
+ handle->zone_dh_cur = cur->next;
+ return (Z_OK);
+}
+
+int
+zonecfg_endadminent(zone_dochandle_t handle)
+{
+ return (zonecfg_endent(handle));
+}
+
/*
* The privileges available on the system and described in privileges(5)
* fall into four categories with respect to non-global zones:
@@ -7482,3 +7725,547 @@
free(rvalp);
return (-1);
}
+
+boolean_t
+zonecfg_valid_auths(const char *auths, const char *zonename)
+{
+ char *right;
+ char *tmpauths;
+ char *lasts;
+ char authname[MAXAUTHS];
+ boolean_t status = B_TRUE;
+
+ tmpauths = strdup(auths);
+ if (tmpauths == NULL) {
+ zerror(zonename, gettext("Out of memory"));
+ return (B_FALSE);
+ }
+ right = strtok_r(tmpauths, ",", &lasts);
+ while (right != NULL) {
+ (void) snprintf(authname, MAXAUTHS, "%s%s",
+ ZONE_AUTH_PREFIX, right);
+ if (getauthnam(authname) == NULL) {
+ status = B_FALSE;
+ zerror(zonename, gettext("%s is not a valid right"),
+ right);
+ }
+ right = strtok_r(NULL, ",", &lasts);
+ }
+ free(tmpauths);
+ return (status);
+}
+
+int
+zonecfg_delete_admins(zone_dochandle_t handle, char *zonename)
+{
+ int err;
+ struct zone_admintab admintab;
+ boolean_t changed = B_FALSE;
+
+ if ((err = zonecfg_setadminent(handle)) != Z_OK) {
+ return (err);
+ }
+ while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
+ err = zonecfg_delete_admin(handle, &admintab,
+ zonename);
+ if (err != Z_OK) {
+ (void) zonecfg_endadminent(handle);
+ return (err);
+ } else {
+ changed = B_TRUE;
+ }
+ if ((err = zonecfg_setadminent(handle)) != Z_OK) {
+ return (err);
+ }
+ }
+ (void) zonecfg_endadminent(handle);
+ return (changed? Z_OK:Z_NO_ENTRY);
+}
+
+/*
+ * Checks if a long authorization applies to this zone.
+ * If so, it returns true, after destructively stripping
+ * the authorization of its prefix and zone suffix.
+ */
+static boolean_t
+is_zone_auth(char **auth, char *zonename, char *oldzonename)
+{
+ char *suffix;
+ size_t offset;
+
+ offset = strlen(ZONE_AUTH_PREFIX);
+ if ((strncmp(*auth, ZONE_AUTH_PREFIX, offset) == 0) &&
+ ((suffix = strchr(*auth, '/')) != NULL)) {
+ if (strncmp(suffix + 1, zonename, strlen(zonename)) == 0) {
+ *auth += offset;
+ suffix[0] = '\0';
+ return (B_TRUE);
+ } else if ((oldzonename != NULL) &&
+ (strncmp(suffix + 1, oldzonename,
+ strlen(oldzonename)) == 0)) {
+ *auth += offset;
+ suffix[0] = '\0';
+ return (B_TRUE);
+ }
+ }
+ return (B_FALSE);
+}
+
+/*
+ * This function determines whether the zone-specific authorization
+ * assignments in /etc/user_attr have been changed more recently
+ * than the equivalent data stored in the zone's configuration file.
+ * This should only happen if the zone-specific authorizations in
+ * the user_attr file were modified using a tool other than zonecfg.
+ * If the configuration file is out-of-date with respect to these
+ * authorization assignments, it is updated to match those specified
+ * in /etc/user_attr.
+ */
+
+int
+zonecfg_update_userauths(zone_dochandle_t handle, char *zonename)
+{
+ userattr_t *ua_ptr;
+ char *authlist;
+ char *lasts;
+ FILE *uaf;
+ struct zone_admintab admintab;
+ struct stat config_st, ua_st;
+ char config_file[MAXPATHLEN];
+ boolean_t changed = B_FALSE;
+ int err;
+
+ if ((uaf = fopen(USERATTR_FILENAME, "r")) == NULL) {
+ zerror(zonename, gettext("could not open file %s: %s"),
+ USERATTR_FILENAME, strerror(errno));
+ if (errno == EACCES)
+ return (Z_ACCES);
+ if (errno == ENOENT)
+ return (Z_NO_ZONE);
+ return (Z_MISC_FS);
+ }
+ if ((err = fstat(fileno(uaf), &ua_st)) != 0) {
+ zerror(zonename, gettext("could not stat file %s: %s"),
+ USERATTR_FILENAME, strerror(errno));
+ (void) fclose(uaf);
+ return (Z_MISC_FS);
+ }
+ if (!config_file_path(zonename, config_file)) {
+ (void) fclose(uaf);
+ return (Z_MISC_FS);
+ }
+
+ if ((err = stat(config_file, &config_st)) != 0) {
+ zerror(zonename, gettext("could not stat file %s: %s"),
+ config_file, strerror(errno));
+ (void) fclose(uaf);
+ return (Z_MISC_FS);
+ }
+ if (config_st.st_mtime >= ua_st.st_mtime) {
+ (void) fclose(uaf);
+ return (Z_NO_ENTRY);
+ }
+ if ((err = zonecfg_delete_admins(handle, zonename)) == Z_OK) {
+ changed = B_TRUE;
+ } else if (err != Z_NO_ENTRY) {
+ (void) fclose(uaf);
+ return (err);
+ }
+ while ((ua_ptr = fgetuserattr(uaf)) != NULL) {
+ if (ua_ptr->name[0] == '#') {
+ continue;
+ }
+ authlist = kva_match(ua_ptr->attr, USERATTR_AUTHS_KW);
+ if (authlist != NULL) {
+ char *cur_auth;
+ boolean_t first;
+
+ first = B_TRUE;
+ bzero(&admintab.zone_admin_auths, MAXAUTHS);
+ cur_auth = strtok_r(authlist, ",", &lasts);
+ while (cur_auth != NULL) {
+ if (is_zone_auth(&cur_auth, zonename,
+ NULL)) {
+ /*
+ * Add auths for this zone
+ */
+ if (first) {
+ first = B_FALSE;
+ } else {
+ (void) strlcat(
+ admintab.zone_admin_auths,
+ ",", MAXAUTHS);
+ }
+ (void) strlcat(
+ admintab.zone_admin_auths,
+ cur_auth, MAXAUTHS);
+ }
+ cur_auth = strtok_r(NULL, ",", &lasts);
+ }
+ if (!first) {
+ /*
+ * Add this right to config file
+ */
+ (void) strlcpy(admintab.zone_admin_user,
+ ua_ptr->name,
+ sizeof (admintab.zone_admin_user));
+ err = zonecfg_add_admin(handle,
+ &admintab, zonename);
+ if (err != Z_OK) {
+ (void) fclose(uaf);
+ return (err);
+ } else {
+ changed = B_TRUE;
+ }
+ }
+ }
+ } /* end-of-while-loop */
+ (void) fclose(uaf);
+ return (changed? Z_OK: Z_NO_ENTRY);
+}
+
+static void
+update_profiles(char *rbac_profs, boolean_t add)
+{
+ char new_profs[MAXPROFS];
+ char *cur_prof;
+ boolean_t first = B_TRUE;
+ boolean_t found = B_FALSE;
+ char *lasts;
+
+ cur_prof = strtok_r(rbac_profs, ",", &lasts);
+ while (cur_prof != NULL) {
+ if (strcmp(cur_prof, ZONE_MGMT_PROF) == 0) {
+ found = B_TRUE;
+ if (!add) {
+ cur_prof = strtok_r(NULL, ",", &lasts);
+ continue;
+ }
+ }
+ if (first) {
+ first = B_FALSE;
+ } else {
+ (void) strlcat(new_profs, ",",
+ MAXPROFS);
+ }
+ (void) strlcat(new_profs, cur_prof,
+ MAXPROFS);
+ cur_prof = strtok_r(NULL, ",", &lasts);
+ }
+ /*
+ * Now prepend the Zone Management profile at the beginning
+ * of the list if it is needed, and append the rest.
+ * Return the updated list in the original buffer.
+ */
+ if (add && !found) {
+ first = B_FALSE;
+ (void) strlcpy(rbac_profs, ZONE_MGMT_PROF, MAXPROFS);
+ } else {
+ first = B_TRUE;
+ rbac_profs[0] = '\0';
+ }
+ if (strlen(new_profs) > 0) {
+ if (!first)
+ (void) strlcat(rbac_profs, ",", MAXPROFS);
+ (void) strlcat(rbac_profs, new_profs, MAXPROFS);
+ }
+}
+
+#define MAX_CMD_LEN 1024
+
+static int
+do_subproc(char *zonename, char *cmdbuf)
+{
+ char inbuf[MAX_CMD_LEN];
+ FILE *file;
+ int status;
+
+ file = popen(cmdbuf, "r");
+ if (file == NULL) {
+ zerror(zonename, gettext("Could not launch: %s"), cmdbuf);
+ return (-1);
+ }
+
+ while (fgets(inbuf, sizeof (inbuf), file) != NULL)
+ (void) fprintf(stderr, "%s", inbuf);
+ status = pclose(file);
+
+ if (WIFSIGNALED(status)) {
+ zerror(zonename, gettext("%s unexpectedly terminated "
+ "due to signal %d"),
+ cmdbuf, WTERMSIG(status));
+ return (-1);
+ }
+ assert(WIFEXITED(status));
+ return (WEXITSTATUS(status));
+}
+
+/*
+ * This function updates the local /etc/user_attr file to
+ * correspond to the admin settings that are currently being
+ * committed. The updates are done via usermod and/or rolemod
+ * depending on the type of the specified user. It is also
+ * invoked to remove entries from user_attr corresponding to
+ * removed admin assignments, using an empty auths string.
+ *
+ * Because the removed entries are no longer included in the
+ * cofiguration that is being committed, a linked list of
+ * removed admin entries is maintained to keep track of such
+ * transactions. The head of the list is stored in the zone_dh_userauths
+ * element of the handle strcture.
+ */
+static int
+zonecfg_authorize_user_impl(zone_dochandle_t handle, char *user,
+ char *auths, char *zonename)
+{
+ char *right;
+ char old_auths[MAXAUTHS];
+ char new_auths[MAXAUTHS];
+ char rbac_profs[MAXPROFS];
+ char *lasts;
+ userattr_t *u;
+ boolean_t first = B_TRUE;
+ boolean_t is_zone_admin = B_FALSE;
+ char user_cmd[] = "/usr/sbin/usermod";
+ char role_cmd[] = "/usr/sbin/rolemod";
+ char *auths_cmd = user_cmd;
+
+ /*
+ * First get the existing authorizations for this user
+ */
+
+ bzero(&old_auths, sizeof (old_auths));
+ bzero(&new_auths, sizeof (new_auths));
+ bzero(&rbac_profs, sizeof (rbac_profs));
+ if ((u = getusernam(user)) != NULL) {
+ char *current_auths;
+ char *current_profs;
+ char *type;
+
+ type = kva_match(u->attr, USERATTR_TYPE_KW);
+ if (type != NULL) {
+ if (strcmp(type, USERATTR_TYPE_NONADMIN_KW) == 0)
+ auths_cmd = role_cmd;
+ }
+
+ current_auths = kva_match(u->attr, USERATTR_AUTHS_KW);
+ if (current_auths != NULL) {
+ char *cur_auth;
+ char *delete_name;
+ size_t offset;
+
+ offset = strlen(ZONE_AUTH_PREFIX);
+
+ (void) strlcpy(old_auths, current_auths, MAXAUTHS);
+ cur_auth = strtok_r(current_auths, ",", &lasts);
+
+ /*
+ * Next, remove any existing authorizations
+ * for this zone, and determine if the
+ * user still needs the Zone Management Profile.
+ */
+ if (is_renaming(handle))
+ delete_name = handle->zone_dh_delete_name;
+ else
+ delete_name = NULL;
+ while (cur_auth != NULL) {
+ if (!is_zone_auth(&cur_auth, zonename,
+ delete_name)) {
+ if (first) {
+ first = B_FALSE;
+ } else {
+ (void) strlcat(new_auths, ",",
+ MAXAUTHS);
+ }
+ (void) strlcat(new_auths, cur_auth,
+ MAXAUTHS);
+ /*
+ * If the user has authorizations
+ * for other zones, then set a
+ * flag indicate that the Zone
+ * Management profile should be
+ * preserved in user_attr.
+ */
+ if (strncmp(cur_auth,
+ ZONE_AUTH_PREFIX, offset) == 0)
+ is_zone_admin = B_TRUE;
+ }
+ cur_auth = strtok_r(NULL, ",", &lasts);
+ }
+ }
+ current_profs = kva_match(u->attr, USERATTR_PROFILES_KW);
+ if (current_profs != NULL) {
+ (void) strlcpy(rbac_profs, current_profs, MAXPROFS);
+ }
+ free_userattr(u);
+ }
+ /*
+ * The following is done to avoid revisiting the
+ * user_attr entry for this user
+ */
+ (void) zonecfg_remove_userauths(handle, user, "", B_FALSE);
+
+ /*
+ * Convert each right into a properly formatted authorization
+ */
+ right = strtok_r(auths, ",", &lasts);
+ while (right != NULL) {
+ char auth[MAXAUTHS];
+
+ (void) snprintf(auth, MAXAUTHS, "%s%s/%s",
+ ZONE_AUTH_PREFIX, right, zonename);
+ if (first) {
+ first = B_FALSE;
+ } else {
+ (void) strlcat(new_auths, ",", MAXAUTHS);
+ }
+ (void) strlcat(new_auths, auth, MAXAUTHS);
+ is_zone_admin = B_TRUE;
+ right = strtok_r(NULL, ",", &lasts);
+ }
+
+ /*
+ * If the user's previous authorizations have changed
+ * execute the usermod progam to update them in user_attr
+ */
+ if (strcmp(old_auths, new_auths) != 0) {
+ char *cmdbuf;
+ size_t cmd_len;
+
+ update_profiles(rbac_profs, is_zone_admin);
+ cmd_len = snprintf(NULL, 0, "%s -A \"%s\" -P \"%s\" %s",
+ auths_cmd, new_auths, rbac_profs, user) + 1;
+ if ((cmdbuf = malloc(cmd_len)) == NULL) {
+ return (Z_NOMEM);
+ }
+ (void) snprintf(cmdbuf, cmd_len, "%s -A \"%s\" -P \"%s\" %s",
+ auths_cmd, new_auths, rbac_profs, user);
+ if (do_subproc(zonename, cmdbuf) != 0) {
+ free(cmdbuf);
+ return (Z_SYSTEM);
+ }
+ free(cmdbuf);
+ }
+
+ return (Z_OK);
+}
+
+int
+zonecfg_authorize_users(zone_dochandle_t handle, char *zonename)
+{
+ xmlNodePtr cur;
+ int err;
+ char user[MAXUSERNAME];
+ char auths[MAXAUTHS];
+
+ if ((err = operation_prep(handle)) != Z_OK)
+ return (err);
+
+ cur = handle->zone_dh_cur;
+ for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
+ if (xmlStrcmp(cur->name, DTD_ELEM_ADMIN))
+ continue;
+ if (fetchprop(cur, DTD_ATTR_USER, user,
+ sizeof (user)) != Z_OK)
+ continue;
+ if (fetchprop(cur, DTD_ATTR_AUTHS, auths,
+ sizeof (auths)) != Z_OK)
+ continue;
+ if (zonecfg_authorize_user_impl(handle, user, auths, zonename)
+ != Z_OK)
+ return (Z_SYSTEM);
+ }
+ (void) zonecfg_remove_userauths(handle, "", "", B_TRUE);
+
+ return (Z_OK);
+}
+
+int
+zonecfg_deauthorize_user(zone_dochandle_t handle, char *user, char *zonename)
+{
+ return (zonecfg_authorize_user_impl(handle, user, "", zonename));
+}
+
+int
+zonecfg_deauthorize_users(zone_dochandle_t handle, char *zonename)
+{
+ xmlNodePtr cur;
+ int err;
+ char user[MAXUSERNAME];
+
+ if ((err = operation_prep(handle)) != Z_OK)
+ return (err);
+
+ cur = handle->zone_dh_cur;
+ for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
+ if (xmlStrcmp(cur->name, DTD_ELEM_ADMIN))
+ continue;
+ if (fetchprop(cur, DTD_ATTR_USER, user,
+ sizeof (user)) != Z_OK)
+ continue;
+ if ((err = zonecfg_deauthorize_user(handle, user,
+ zonename)) != Z_OK)
+ return (err);
+ }
+ return (Z_OK);
+}
+
+int
+zonecfg_insert_userauths(zone_dochandle_t handle, char *user, char *zonename)
+{
+ zone_userauths_t *new, **prev, *next;
+
+ prev = &handle->zone_dh_userauths;
+ next = *prev;
+ while (next) {
+ if ((strncmp(next->user, user, MAXUSERNAME) == 0) &&
+ (strncmp(next->zonename, zonename,
+ ZONENAME_MAX) == 0)) {
+ /*
+ * user is already in list
+ * which isn't supposed to happen!
+ */
+ return (Z_OK);
+ }
+ prev = &next->next;
+ next = *prev;
+ }
+ new = (zone_userauths_t *)malloc(sizeof (zone_userauths_t));
+ if (new == NULL)
+ return (Z_NOMEM);
+
+ (void) strlcpy(new->user, user, sizeof (new->user));
+ (void) strlcpy(new->zonename, zonename, sizeof (new->zonename));
+ new->next = NULL;
+ *prev = new;
+ return (Z_OK);
+}
+
+int
+zonecfg_remove_userauths(zone_dochandle_t handle, char *user, char *zonename,
+ boolean_t deauthorize)
+{
+ zone_userauths_t *new, **prev, *next;
+
+ prev = &handle->zone_dh_userauths;
+ next = *prev;
+
+ while (next) {
+ if ((strlen(user) == 0 ||
+ strncmp(next->user, user, MAXUSERNAME) == 0) &&
+ (strlen(zonename) == 0 ||
+ (strncmp(next->zonename, zonename, ZONENAME_MAX) == 0))) {
+ new = next;
+ *prev = next->next;
+ next = *prev;
+ if (deauthorize)
+ (void) zonecfg_deauthorize_user(handle,
+ new->user, new->zonename);
+ free(new);
+ continue;
+ }
+ prev = &next->next;
+ next = *prev;
+ }
+ return (Z_OK);
+}
--- a/usr/src/lib/libzonecfg/common/mapfile-vers Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/lib/libzonecfg/common/mapfile-vers Mon Jun 07 14:07:27 2010 -0700
@@ -19,8 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
#
#
@@ -50,6 +49,7 @@
zonecfg_add_ds;
zonecfg_add_filesystem;
zonecfg_add_fs_option;
+ zonecfg_add_admin;
zonecfg_add_ipd;
zonecfg_add_nwif;
zonecfg_add_patch;
@@ -62,6 +62,7 @@
zonecfg_aliased_rctl_ok;
zonecfg_apply_rctls;
zonecfg_attach_manifest;
+ zonecfg_authorize_users;
zonecfg_bind_pool;
zonecfg_bind_tmp_pool;
zonecfg_call_zoneadmd;
@@ -69,8 +70,12 @@
zonecfg_close_scratch;
zonecfg_construct_rctlblk;
zonecfg_create_snapshot;
+ zonecfg_deauthorize_user;
+ zonecfg_deauthorize_users;
zonecfg_default_brand;
zonecfg_default_privset;
+ zonecfg_delete_admin;
+ zonecfg_delete_admins;
zonecfg_delete_attr;
zonecfg_delete_dev;
zonecfg_delete_ds;
@@ -90,6 +95,7 @@
zonecfg_devperms_apply;
zonecfg_dev_manifest;
zonecfg_enable_rcapd;
+ zonecfg_endadminent;
zonecfg_endattrent;
zonecfg_enddevent;
zonecfg_enddevperment;
@@ -106,6 +112,7 @@
zonecfg_get_aliased_rctl;
zonecfg_get_attach_handle;
zonecfg_get_attr_boolean;
+ zonecfg_getadminent;
zonecfg_getattrent;
zonecfg_get_attr_int;
zonecfg_get_attr_string;
@@ -144,12 +151,14 @@
zonecfg_grab_lock_file;
zonecfg_ifname_exists;
zonecfg_in_alt_root;
+ zonecfg_insert_userauths;
zonecfg_init_handle;
zonecfg_init_lock_file;
zonecfg_is_rctl;
zonecfg_is_scratch;
zonecfg_lock_file_held;
zonecfg_lock_scratch;
+ zonecfg_lookup_admin;
zonecfg_lookup_attr;
zonecfg_lookup_dev;
zonecfg_lookup_ds;
@@ -159,6 +168,7 @@
zonecfg_lookup_nwif;
zonecfg_lookup_pset;
zonecfg_lookup_rctl;
+ zonecfg_modify_admin;
zonecfg_modify_attr;
zonecfg_modify_dev;
zonecfg_modify_ds;
@@ -179,11 +189,13 @@
zonecfg_release_lock_file;
zonecfg_remove_fs_option;
zonecfg_remove_rctl_value;
+ zonecfg_remove_userauths;
zonecfg_reverse_scratch;
zonecfg_rm_aliased_rctl;
zonecfg_rm_detached;
zonecfg_same_net_address;
zonecfg_save;
+ zonecfg_setadminent;
zonecfg_setattrent;
zonecfg_set_aliased_rctl;
zonecfg_set_autoboot;
@@ -207,7 +219,9 @@
zonecfg_set_zonepath;
zonecfg_strerror;
zonecfg_str_to_bytes;
+ zonecfg_update_userauths;
zonecfg_validate_zonename;
+ zonecfg_valid_auths;
zonecfg_valid_alias_limit;
zonecfg_valid_fs_type;
zonecfg_valid_hostid;
--- a/usr/src/lib/libzonecfg/dtd/zonecfg.dtd.1 Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/lib/libzonecfg/dtd/zonecfg.dtd.1 Mon Jun 07 14:07:27 2010 -0700
@@ -20,8 +20,7 @@
CDDL HEADER END
- Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- Use is subject to license terms.
+ Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
-->
@@ -131,9 +130,15 @@
<!ATTLIST mcap physcap CDATA #REQUIRED>
+<!ELEMENT admin EMPTY>
+
+<!ATTLIST admin user CDATA #REQUIRED
+ auths CDATA #REQUIRED>
+
<!ELEMENT zone (filesystem | inherited-pkg-dir | network | device |
deleted-device | rctl | attr | dataset | package |
- patch | dev-perm | tmp_pool | pset | mcap)*>
+ patch | dev-perm | tmp_pool | pset |
+ mcap | admin)*>
<!ATTLIST zone name CDATA #REQUIRED
zonepath CDATA #REQUIRED
--- a/usr/src/pkg/manifests/SUNWcs.mf Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/pkg/manifests/SUNWcs.mf Mon Jun 07 14:07:27 2010 -0700
@@ -1037,6 +1037,10 @@
file path=usr/lib/help/auths/locale/C/SysSyseventWrite.html
file path=usr/lib/help/auths/locale/C/WifiConfig.html
file path=usr/lib/help/auths/locale/C/WifiWep.html
+file path=usr/lib/help/auths/locale/C/ZoneCloneFrom.html
+file path=usr/lib/help/auths/locale/C/ZoneHeader.html
+file path=usr/lib/help/auths/locale/C/ZoneLogin.html
+file path=usr/lib/help/auths/locale/C/ZoneManage.html
file path=usr/lib/help/profiles/locale/C/RtAcctadm.html
file path=usr/lib/help/profiles/locale/C/RtAll.html
file path=usr/lib/help/profiles/locale/C/RtAuditCtrl.html
@@ -1109,6 +1113,7 @@
file path=usr/lib/help/profiles/locale/C/RtZFSFileSysMngmnt.html
file path=usr/lib/help/profiles/locale/C/RtZFSStorageMngmnt.html
file path=usr/lib/help/profiles/locale/C/RtZoneMngmnt.html
+file path=usr/lib/help/profiles/locale/C/RtZoneSecurity.html
file path=usr/lib/hotplugd mode=0555
file path=usr/lib/iconv/646da.8859.t mode=0444
file path=usr/lib/iconv/646de.8859.t mode=0444
--- a/usr/src/pkg/manifests/consolidation-osnet-osnet-message-files.mf Mon Jun 07 13:43:38 2010 -0700
+++ b/usr/src/pkg/manifests/consolidation-osnet-osnet-message-files.mf Mon Jun 07 14:07:27 2010 -0700
@@ -212,6 +212,10 @@
file path=usr/lib/help/auths/locale/ValueTND.html
file path=usr/lib/help/auths/locale/WifiConfig.html
file path=usr/lib/help/auths/locale/WifiWep.html
+file path=usr/lib/help/auths/locale/ZoneCloneFrom.html
+file path=usr/lib/help/auths/locale/ZoneHeader.html
+file path=usr/lib/help/auths/locale/ZoneLogin.html
+file path=usr/lib/help/auths/locale/ZoneManage.html
file path=usr/lib/help/profiles/locale/RtAcctadm.html
file path=usr/lib/help/profiles/locale/RtAll.html
file path=usr/lib/help/profiles/locale/RtAuditCtrl.html
@@ -287,6 +291,7 @@
file path=usr/lib/help/profiles/locale/RtZFSFileSysMngmnt.html
file path=usr/lib/help/profiles/locale/RtZFSStorageMngmnt.html
file path=usr/lib/help/profiles/locale/RtZoneMngmnt.html
+file path=usr/lib/help/profiles/locale/RtZoneSecurity.html
file path=usr/lib/locale/C/LC_MESSAGES/AMD.po
file path=usr/lib/locale/C/LC_MESSAGES/DISK.po
file path=usr/lib/locale/C/LC_MESSAGES/FMD.po