summaryrefslogtreecommitdiff
path: root/usr/src/cmd/zonecfg/zonecfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/zonecfg/zonecfg.c')
-rw-r--r--usr/src/cmd/zonecfg/zonecfg.c338
1 files changed, 334 insertions, 4 deletions
diff --git a/usr/src/cmd/zonecfg/zonecfg.c b/usr/src/cmd/zonecfg/zonecfg.c
index c18c572df7..3827d53026 100644
--- a/usr/src/cmd/zonecfg/zonecfg.c
+++ b/usr/src/cmd/zonecfg/zonecfg.c
@@ -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 @@ char *res_types[] = {
"ip-type",
"capped-cpu",
"hostid",
+ "admin",
NULL
};
@@ -223,6 +225,8 @@ char *prop_types[] = {
"ip-type",
"defrouter",
"hostid",
+ "user",
+ "auths",
NULL
};
@@ -271,6 +275,7 @@ static const char *add_cmds[] = {
"add dedicated-cpu",
"add capped-cpu",
"add capped-memory",
+ "add admin",
NULL
};
@@ -301,6 +306,7 @@ static const char *remove_cmds[] = {
"remove dedicated-cpu ",
"remove capped-cpu ",
"remove capped-memory ",
+ "remove admin ",
NULL
};
@@ -315,6 +321,7 @@ static const char *select_cmds[] = {
"select dedicated-cpu",
"select capped-cpu",
"select capped-memory",
+ "select admin",
NULL
};
@@ -365,6 +372,7 @@ static const char *info_cmds[] = {
"info max-sem-ids",
"info cpu-shares",
"info hostid",
+ "info admin",
NULL
};
@@ -486,6 +494,17 @@ static const char *mcap_res_scope_cmds[] = {
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_attrtab old_attrtab, in_progress_attrtab;
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 @@ CPL_MATCH_FN(cmd_cpl_fn)
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 @@ usage(boolean_t verbose, uint_t flags)
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 @@ usage(boolean_t verbose, uint_t flags)
}
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 @@ usage(boolean_t verbose, uint_t flags)
(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 @@ initialize(boolean_t handle_expected)
" 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 @@ export_func(cmd_t *cmd)
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 @@ export_func(cmd_t *cmd)
(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 @@ add_resource(cmd_t *cmd)
"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 @@ delete_func(cmd_t *cmd)
* 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 @@ delete_func(cmd_t *cmd)
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 @@ fill_in_dstab(cmd_t *cmd, struct zone_dstab *dstab, boolean_t fill_in_only)
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 @@ remove_mcap()
}
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 @@ remove_resource(cmd_t *cmd)
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 @@ select_func(cmd_t *cmd)
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 @@ set_func(cmd_t *cmd)
usage(B_FALSE, HELP_PROPS);
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 @@ info_mcap(zone_dochandle_t handle, FILE *fp)
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 @@ info_func(cmd_t *cmd)
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 @@ info_func(cmd_t *cmd)
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 @@ info_func(cmd_t *cmd)
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 @@ verify_func(cmd_t *cmd)
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 @@ verify_func(cmd_t *cmd)
}
(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 @@ end_func(cmd_t *cmd)
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 @@ end_func(cmd_t *cmd)
(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 @@ revert_func(cmd_t *cmd)
}
/*
+ * 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 @@ revert_func(cmd_t *cmd)
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;