Mercurial > illumos > illumos-gate
changeset 12578:f9062c43c8bc
4963290 RFE: implement flexible zone administration that doesn't require uid=0
PSARC/2010/132 Delegated Administration for Zones
line wrap: on
line diff
--- 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