diff options
author | sl108498 <none@none> | 2007-05-29 15:28:30 -0700 |
---|---|---|
committer | sl108498 <none@none> | 2007-05-29 15:28:30 -0700 |
commit | 858a4b9997a29c40b725e606eb9bc3ac0a8c765b (patch) | |
tree | 11bd2c97f0bd4f724719d0084377f420b3829d1a /usr/src | |
parent | 0539614d940e5eb6b299959c16501a5ba81057cb (diff) | |
download | illumos-joyent-858a4b9997a29c40b725e606eb9bc3ac0a8c765b.tar.gz |
6558487 zlogin should not call getpwnam() after zone_enter() during non-interactive zlogin -l
6561300 zlogin error messages are not locale specific for non-native zones
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/zlogin/Makefile | 3 | ||||
-rw-r--r-- | usr/src/cmd/zlogin/zlogin.c | 122 | ||||
-rw-r--r-- | usr/src/lib/brand/lx/zone/config.xml | 1 | ||||
-rw-r--r-- | usr/src/lib/brand/native/zone/config.xml | 1 | ||||
-rw-r--r-- | usr/src/lib/brand/sn1/zone/config.xml | 1 | ||||
-rw-r--r-- | usr/src/lib/libbrand/common/libbrand.c | 11 | ||||
-rw-r--r-- | usr/src/lib/libbrand/common/libbrand.h | 1 | ||||
-rw-r--r-- | usr/src/lib/libbrand/common/mapfile-vers | 1 | ||||
-rw-r--r-- | usr/src/lib/libbrand/dtd/brand.dtd.1 | 21 |
9 files changed, 145 insertions, 17 deletions
diff --git a/usr/src/cmd/zlogin/Makefile b/usr/src/cmd/zlogin/Makefile index 90d1b15a34..2a9d85d543 100644 --- a/usr/src/cmd/zlogin/Makefile +++ b/usr/src/cmd/zlogin/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -28,6 +28,7 @@ PROG = zlogin include ../Makefile.cmd +LINTFLAGS += -u LDLIBS += -lsocket -lzonecfg -lcontract -lbrand CFLAGS += $(CCVERBOSE) FILEMODE = 0555 diff --git a/usr/src/cmd/zlogin/zlogin.c b/usr/src/cmd/zlogin/zlogin.c index e1d2f99b21..c0886a3b0f 100644 --- a/usr/src/cmd/zlogin/zlogin.c +++ b/usr/src/cmd/zlogin/zlogin.c @@ -58,12 +58,13 @@ #include <sys/contract/process.h> #include <sys/ctfs.h> #include <sys/brand.h> - +#include <sys/wait.h> #include <alloca.h> #include <assert.h> #include <ctype.h> #include <door.h> #include <errno.h> +#include <nss_dbdefs.h> #include <poll.h> #include <priv.h> #include <pwd.h> @@ -745,20 +746,20 @@ process_output(int in_fd, int out_fd) * This is the main I/O loop, and is shared across all zlogin modes. * Parameters: * stdin_fd: The fd representing 'stdin' for the slave side; input to - * the zone will be written here. + * the zone will be written here. * * appin_fd: The fd representing the other end of the 'stdin' pipe (when * we're running non-interactive); used in process_raw_input * to ensure we don't fill up the application's stdin pipe. * * stdout_fd: The fd representing 'stdout' for the slave side; output - * from the zone will arrive here. + * from the zone will arrive here. * * stderr_fd: The fd representing 'stderr' for the slave side; output - * from the zone will arrive here. + * from the zone will arrive here. * * raw_mode: If TRUE, then no processing (for example, for '~.') will - * be performed on the input coming from STDIN. + * be performed on the input coming from STDIN. * * stderr_fd may be specified as -1 if there is no stderr (only non-interactive * mode supplies a stderr). @@ -901,6 +902,62 @@ retry: } } +/* + * Fetch the user_cmd brand hook for getting a user's passwd(4) entry. + */ +static const char * +zone_get_user_cmd(brand_handle_t bh, const char *login, char *user_cmd, + size_t len) +{ + bzero(user_cmd, sizeof (user_cmd)); + if (brand_get_user_cmd(bh, login, user_cmd, len) != 0) + return (NULL); + + return (user_cmd); +} + +/* From libc */ +extern int str2passwd(const char *, int, void *, char *, int); + +/* + * exec() the user_cmd brand hook, and convert the output string to a + * struct passwd. This is to be called after zone_enter(). + * + */ +static struct passwd * +zone_get_user_pw(const char *user_cmd, struct passwd *pwent, char *pwbuf, + int pwbuflen) +{ + char pwline[NSS_BUFLEN_PASSWD]; + char *cin = NULL; + FILE *fin; + int status; + + assert(getzoneid() != GLOBAL_ZONEID); + + if ((fin = popen(user_cmd, "r")) == NULL) + return (NULL); + + while (cin == NULL && !feof(fin)) + cin = fgets(pwline, sizeof (pwline), fin); + + if (cin == NULL) { + (void) pclose(fin); + return (NULL); + } + + status = pclose(fin); + if (!WIFEXITED(status)) + return (NULL); + if (WEXITSTATUS(status) != 0) + return (NULL); + + if (str2passwd(pwline, sizeof (pwline), pwent, pwbuf, pwbuflen) == 0) + return (pwent); + else + return (NULL); +} + static char ** zone_login_cmd(brand_handle_t bh, const char *login) { @@ -1102,32 +1159,45 @@ prep_env() * that. */ static char ** -prep_env_noninteractive(char *login, char **env) +prep_env_noninteractive(const char *user_cmd, char **env) { size_t size; - struct passwd *pw; char **new_env; int e, i; char *estr; char varmail[LOGNAME_MAX + 11]; /* strlen(/var/mail/) = 10, NUL */ + char pwbuf[NSS_BUFLEN_PASSWD + 1]; + struct passwd pwent; + struct passwd *pw = NULL; assert(env != NULL); assert(failsafe == 0); /* + * Exec the "user_cmd" brand hook to get a pwent for the + * login user. If this fails, HOME will be set to "/", SHELL + * will be set to $DEFAULTSHELL, and we will continue to exec + * SUPATH <login> -c <cmd>. + */ + pw = zone_get_user_pw(user_cmd, &pwent, pwbuf, sizeof (pwbuf)); + + /* * Get existing envp size. */ for (size = 0; env[size] != NULL; size++) ; + e = size; /* * Finish filling out the environment; we duplicate the environment * setup described in login(1), for lack of a better precedent. */ - if ((pw = getpwnam(login)) != NULL) { + if (pw != NULL) size += 3; /* LOGNAME, HOME, MAIL */ - } + else + size += 1; /* HOME */ + size++; /* always fill in SHELL */ size++; /* terminating NULL */ @@ -1161,6 +1231,10 @@ prep_env_noninteractive(char *login, char **env) if ((estr = add_env("MAIL", varmail)) == NULL) goto malloc_fail; new_env[e++] = estr; + } else { + if ((estr = add_env("HOME", "/")) == NULL) + goto malloc_fail; + new_env[e++] = estr; } if (pw != NULL && strlen(pw->pw_shell) > 0) { @@ -1376,7 +1450,7 @@ init_template(void) } static int -noninteractive_login(char *zonename, zoneid_t zoneid, char *login, +noninteractive_login(char *zonename, const char *user_cmd, zoneid_t zoneid, char **new_args, char **new_env) { pid_t retval; @@ -1475,8 +1549,16 @@ noninteractive_login(char *zonename, zoneid_t zoneid, char *login, _exit(1); } + /* + * For non-native zones, tell libc where it can find locale + * specific getttext() messages. + */ + if (access("/native/usr/lib/locale", R_OK) == 0) + (void) bindtextdomain(TEXT_DOMAIN, + "/native/usr/lib/locale"); + if (!failsafe) - new_env = prep_env_noninteractive(login, new_env); + new_env = prep_env_noninteractive(user_cmd, new_env); if (new_env == NULL) { _exit(1); @@ -1534,6 +1616,7 @@ main(int argc, char **argv) struct stat sb; char kernzone[ZONENAME_MAX]; brand_handle_t bh; + char user_cmd[MAXPATHLEN]; (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); @@ -1759,6 +1842,19 @@ main(int argc, char **argv) brand_close(bh); return (1); } + /* + * Get the brand specific user_cmd. This command is used to get + * a passwd(4) entry for login. + */ + if (!interactive && !failsafe) { + if (zone_get_user_cmd(bh, login, user_cmd, + sizeof (user_cmd)) == NULL) { + zerror(gettext("could not get user_cmd for zone %s"), + zonename); + brand_close(bh); + return (1); + } + } brand_close(bh); if ((new_env = prep_env()) == NULL) { @@ -1767,8 +1863,8 @@ main(int argc, char **argv) } if (!interactive) - return (noninteractive_login(zonename, zoneid, login, new_args, - new_env)); + return (noninteractive_login(zonename, user_cmd, zoneid, + new_args, new_env)); if (zonecfg_in_alt_root()) { zerror(gettext("cannot use interactive login with scratch " diff --git a/usr/src/lib/brand/lx/zone/config.xml b/usr/src/lib/brand/lx/zone/config.xml index 0cdb522457..5829cd153a 100644 --- a/usr/src/lib/brand/lx/zone/config.xml +++ b/usr/src/lib/brand/lx/zone/config.xml @@ -36,6 +36,7 @@ <initname>/sbin/init</initname> <login_cmd>/bin/login -h zone:%Z -f %u</login_cmd> + <user_cmd>/usr/bin/getent passwd %u</user_cmd> <install>/usr/lib/brand/lx/lx_install %z %R %*</install> <installopts>d:hsvX</installopts> diff --git a/usr/src/lib/brand/native/zone/config.xml b/usr/src/lib/brand/native/zone/config.xml index ba8fa8c091..9e0b6244a0 100644 --- a/usr/src/lib/brand/native/zone/config.xml +++ b/usr/src/lib/brand/native/zone/config.xml @@ -36,6 +36,7 @@ <initname>/sbin/init</initname> <login_cmd>/usr/bin/login -z %Z -f %u</login_cmd> + <user_cmd>/usr/bin/getent passwd %u</user_cmd> <install>/usr/lib/lu/lucreatezone -z %z</install> <installopts></installopts> diff --git a/usr/src/lib/brand/sn1/zone/config.xml b/usr/src/lib/brand/sn1/zone/config.xml index 344cecbfbc..56488744d7 100644 --- a/usr/src/lib/brand/sn1/zone/config.xml +++ b/usr/src/lib/brand/sn1/zone/config.xml @@ -36,6 +36,7 @@ <initname>/sbin/init</initname> <login_cmd>/usr/bin/login -z %Z -f %u</login_cmd> + <user_cmd>/usr/bin/getent passwd %u</user_cmd> <install>/usr/lib/lu/lucreatezone -z %z</install> <installopts></installopts> diff --git a/usr/src/lib/libbrand/common/libbrand.c b/usr/src/lib/libbrand/common/libbrand.c index ad17b6709a..696f956915 100644 --- a/usr/src/lib/libbrand/common/libbrand.c +++ b/usr/src/lib/libbrand/common/libbrand.c @@ -62,6 +62,7 @@ #define DTD_ELEM_POSTCLONE ((const xmlChar *) "postclone") #define DTD_ELEM_PRIVILEGE ((const xmlChar *) "privilege") #define DTD_ELEM_SYMLINK ((const xmlChar *) "symlink") +#define DTD_ELEM_USER_CMD ((const xmlChar *) "user_cmd") #define DTD_ELEM_VERIFY_CFG ((const xmlChar *) "verify_cfg") #define DTD_ELEM_VERIFY_ADM ((const xmlChar *) "verify_adm") @@ -485,6 +486,16 @@ brand_get_login_cmd(brand_handle_t bh, const char *username, } int +brand_get_user_cmd(brand_handle_t bh, const char *username, + char *buf, size_t len) +{ + struct brand_handle *bhp = (struct brand_handle *)bh; + + return (brand_get_value(bhp, NULL, NULL, username, NULL, + buf, len, 0, NULL, DTD_ELEM_USER_CMD, B_TRUE, B_FALSE)); +} + +int brand_get_install(brand_handle_t bh, const char *zonename, const char *zoneroot, char *buf, size_t len, int argc, char **argv) { diff --git a/usr/src/lib/libbrand/common/libbrand.h b/usr/src/lib/libbrand/common/libbrand.h index cdb097edf1..5a4620fff5 100644 --- a/usr/src/lib/libbrand/common/libbrand.h +++ b/usr/src/lib/libbrand/common/libbrand.h @@ -63,6 +63,7 @@ extern int brand_get_login_cmd(brand_handle_t, const char *, char *, size_t); extern int brand_get_modname(brand_handle_t, char *, size_t); extern int brand_get_postclone(brand_handle_t, const char *, const char *, char *, size_t, int, char **); +extern int brand_get_user_cmd(brand_handle_t, const char *, char *, size_t); extern int brand_get_verify_cfg(brand_handle_t, char *, size_t); extern int brand_get_verify_adm(brand_handle_t, const char *, const char *, char *, size_t, int, char **); diff --git a/usr/src/lib/libbrand/common/mapfile-vers b/usr/src/lib/libbrand/common/mapfile-vers index f42011400e..15d4fa1c62 100644 --- a/usr/src/lib/libbrand/common/mapfile-vers +++ b/usr/src/lib/libbrand/common/mapfile-vers @@ -39,6 +39,7 @@ SUNWprivate { brand_get_login_cmd; brand_get_modname; brand_get_postclone; + brand_get_user_cmd; brand_get_verify_adm; brand_get_verify_cfg; brand_is_native; diff --git a/usr/src/lib/libbrand/dtd/brand.dtd.1 b/usr/src/lib/libbrand/dtd/brand.dtd.1 index efcb308651..8120b7ba5c 100644 --- a/usr/src/lib/libbrand/dtd/brand.dtd.1 +++ b/usr/src/lib/libbrand/dtd/brand.dtd.1 @@ -186,6 +186,21 @@ <!ATTLIST login_cmd> <!-- + user_cmd + + Path to the binary that will translate a user name to a passwd(4) entry. + + The following replacements are performed: + + %u User login name + + It has no attributes. The passwd(4) entry is used to determine $LOGNAME, + $HOME, and $SHELL for non-interactive "zlogin -l <user> <cmd>". +--> +<!ELEMENT user_cmd (#PCDATA) > +<!ATTLIST user_cmd> + +<!-- postclone Path to a script that will perform any necessary post-processing on @@ -242,8 +257,8 @@ directory in which the configuration file is stored. --> -<!ELEMENT brand (modname, initname, login_cmd, install, installopts, - boot, halt, verify_cfg, verify_adm, postclone, - privilege+)> +<!ELEMENT brand (modname, initname, login_cmd, user_cmd, install, + installopts, boot, halt, verify_cfg, verify_adm, + postclone, privilege+)> <!ATTLIST brand name CDATA #REQUIRED> |