summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorsl108498 <none@none>2007-05-29 15:28:30 -0700
committersl108498 <none@none>2007-05-29 15:28:30 -0700
commit858a4b9997a29c40b725e606eb9bc3ac0a8c765b (patch)
tree11bd2c97f0bd4f724719d0084377f420b3829d1a /usr/src
parent0539614d940e5eb6b299959c16501a5ba81057cb (diff)
downloadillumos-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/Makefile3
-rw-r--r--usr/src/cmd/zlogin/zlogin.c122
-rw-r--r--usr/src/lib/brand/lx/zone/config.xml1
-rw-r--r--usr/src/lib/brand/native/zone/config.xml1
-rw-r--r--usr/src/lib/brand/sn1/zone/config.xml1
-rw-r--r--usr/src/lib/libbrand/common/libbrand.c11
-rw-r--r--usr/src/lib/libbrand/common/libbrand.h1
-rw-r--r--usr/src/lib/libbrand/common/mapfile-vers1
-rw-r--r--usr/src/lib/libbrand/dtd/brand.dtd.121
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>