6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2013 DEY Storage Systems, Inc.
  24  * Copyright (c) 2014 Gary Mills
  25  * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
  26  */
  27 
  28 /*
  29  * zlogin provides three types of login which allow users in the global
  30  * zone to access non-global zones.
  31  *
  32  * - "interactive login" is similar to rlogin(1); for example, the user could
  33  *   issue 'zlogin my-zone' or 'zlogin -e ^ -l me my-zone'.   The user is
  34  *   granted a new pty (which is then shoved into the zone), and an I/O
  35  *   loop between parent and child processes takes care of the interactive
  36  *   session.  In this mode, login(1) (and its -c option, which means
  37  *   "already authenticated") is employed to take care of the initialization
  38  *   of the user's session.
  39  *
  40  * - "non-interactive login" is similar to su(1M); the user could issue
  41  *   'zlogin my-zone ls -l' and the command would be run as specified.
  42  *   In this mode, zlogin sets up pipes as the communication channel, and
  43  *   'su' is used to do the login setup work.
  44  *
  45  * - "console login" is the equivalent to accessing the tip line for a
  46  *   zone.  For example, the user can issue 'zlogin -C my-zone'.
  47  *   In this mode, zlogin contacts the zoneadmd process via unix domain
  48  *   socket.  If zoneadmd is not running, it starts it.  This allows the
  49  *   console to be available anytime the zone is installed, regardless of
  50  *   whether it is running.
  51  */
  52 
  53 #include <sys/socket.h>
  54 #include <sys/termios.h>
  55 #include <sys/utsname.h>
  56 #include <sys/stat.h>
  57 #include <sys/types.h>
  58 #include <sys/contract/process.h>
  59 #include <sys/ctfs.h>
  60 #include <sys/brand.h>
  61 #include <sys/wait.h>
  62 #include <alloca.h>
  63 #include <assert.h>
  64 #include <ctype.h>
  65 #include <paths.h>
  66 #include <door.h>
  67 #include <errno.h>
  68 #include <nss_dbdefs.h>
  69 #include <poll.h>
  70 #include <priv.h>
 
 
  75 #include <signal.h>
  76 #include <stdarg.h>
  77 #include <stdio.h>
  78 #include <stdlib.h>
  79 #include <string.h>
  80 #include <strings.h>
  81 #include <stropts.h>
  82 #include <wait.h>
  83 #include <zone.h>
  84 #include <fcntl.h>
  85 #include <libdevinfo.h>
  86 #include <libintl.h>
  87 #include <locale.h>
  88 #include <libzonecfg.h>
  89 #include <libcontract.h>
  90 #include <libbrand.h>
  91 #include <auth_list.h>
  92 #include <auth_attr.h>
  93 #include <secdb.h>
  94 
  95 static int masterfd;
  96 static struct termios save_termios;
  97 static struct termios effective_termios;
  98 static int save_fd;
  99 static struct winsize winsize;
 100 static volatile int dead;
 101 static volatile pid_t child_pid = -1;
 102 static int interactive = 0;
 103 static priv_set_t *dropprivs;
 104 
 105 static int nocmdchar = 0;
 106 static int failsafe = 0;
 107 static int disconnect = 0;
 108 static char cmdchar = '~';
 109 static int quiet = 0;
 110 
 111 static int pollerr = 0;
 112 
 113 static const char *pname;
 114 static char *username;
 115 
 116 /*
 117  * When forced_login is true, the user is not prompted
 118  * for an authentication password in the target zone.
 119  */
 120 static boolean_t forced_login = B_FALSE;
 121 
 122 #if !defined(TEXT_DOMAIN)               /* should be defined by cc -D */
 123 #define TEXT_DOMAIN     "SYS_TEST"      /* Use this only if it wasn't */
 124 #endif
 125 
 126 #define SUPATH  "/usr/bin/su"
 127 #define FAILSAFESHELL   "/sbin/sh"
 128 #define DEFAULTSHELL    "/sbin/sh"
 129 #define DEF_PATH        "/usr/sbin:/usr/bin"
 130 
 131 #define CLUSTER_BRAND_NAME      "cluster"
 132 
 133 /*
 134  * The ZLOGIN_BUFSIZ is larger than PIPE_BUF so we can be sure we're clearing
 135  * out the pipe when the child is exiting.  The ZLOGIN_RDBUFSIZ must be less
 136  * than ZLOGIN_BUFSIZ (because we share the buffer in doio).  This value is
 137  * also chosen in conjunction with the HI_WATER setting to make sure we
 138  * don't fill up the pipe.  We can write FIFOHIWAT (16k) into the pipe before
 139  * blocking.  By having ZLOGIN_RDBUFSIZ set to 1k and HI_WATER set to 8k, we
 140  * know we can always write a ZLOGIN_RDBUFSIZ chunk into the pipe when there
 141  * is less than HI_WATER data already in the pipe.
 142  */
 143 #define ZLOGIN_BUFSIZ   8192
 144 #define ZLOGIN_RDBUFSIZ 1024
 145 #define HI_WATER        8192
 146 
 147 /*
 148  * See canonify() below.  CANONIFY_LEN is the maximum length that a
 149  * "canonical" sequence will expand to (backslash, three octal digits, NUL).
 150  */
 151 #define CANONIFY_LEN 5
 152 
 153 static void
 154 usage(void)
 155 {
 156         (void) fprintf(stderr, gettext("usage: %s [ -dnQCES ] [ -e cmdchar ] "
 157             "[-l user] zonename [command [args ...] ]\n"), pname);
 158         exit(2);
 159 }
 160 
 161 static const char *
 162 getpname(const char *arg0)
 163 {
 164         const char *p = strrchr(arg0, '/');
 165 
 166         if (p == NULL)
 167                 p = arg0;
 168         else
 169                 p++;
 170 
 171         pname = p;
 172         return (p);
 173 }
 174 
 175 static void
 176 zerror(const char *fmt, ...)
 
 231 /*
 232  * The second part of the privilege drop.  We are paranoid about being attacked
 233  * by the zone, so we drop all privileges.  This should prevent a compromise
 234  * which gets us to fork(), exec(), symlink(), etc.
 235  */
 236 static void
 237 postfork_dropprivs()
 238 {
 239         if ((setppriv(PRIV_SET, PRIV_PERMITTED, dropprivs)) == -1) {
 240                 zperror(gettext("Warning: could not set permitted privileges"));
 241         }
 242         if ((setppriv(PRIV_SET, PRIV_LIMIT, dropprivs)) == -1) {
 243                 zperror(gettext("Warning: could not set limit privileges"));
 244         }
 245         if ((setppriv(PRIV_SET, PRIV_INHERITABLE, dropprivs)) == -1) {
 246                 zperror(gettext("Warning: could not set inheritable "
 247                     "privileges"));
 248         }
 249 }
 250 
 251 /*
 252  * Create the unix domain socket and call the zoneadmd server; handshake
 253  * with it to determine whether it will allow us to connect.
 254  */
 255 static int
 256 get_console_master(const char *zname)
 257 {
 258         int sockfd = -1;
 259         struct sockaddr_un servaddr;
 260         char clientid[MAXPATHLEN];
 261         char handshake[MAXPATHLEN], c;
 262         int msglen;
 263         int i = 0, err = 0;
 264 
 265         if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
 266                 zperror(gettext("could not create socket"));
 267                 return (-1);
 268         }
 269 
 270         bzero(&servaddr, sizeof (servaddr));
 271         servaddr.sun_family = AF_UNIX;
 272         (void) snprintf(servaddr.sun_path, sizeof (servaddr.sun_path),
 273             "%s/%s.console_sock", ZONES_TMPDIR, zname);
 274 
 275         if (connect(sockfd, (struct sockaddr *)&servaddr,
 276             sizeof (servaddr)) == -1) {
 277                 zperror(gettext("Could not connect to zone console"));
 278                 goto bad;
 279         }
 280         masterfd = sockfd;
 281 
 282         msglen = snprintf(clientid, sizeof (clientid), "IDENT %lu %s %d\n",
 283             getpid(), setlocale(LC_MESSAGES, NULL), disconnect);
 284 
 285         if (msglen >= sizeof (clientid) || msglen < 0) {
 286                 zerror("protocol error");
 287                 goto bad;
 288         }
 289 
 290         if (write(masterfd, clientid, msglen) != msglen) {
 291                 zerror("protocol error");
 292                 goto bad;
 293         }
 294 
 295         bzero(handshake, sizeof (handshake));
 296 
 297         /*
 298          * Take care not to accumulate more than our fill, and leave room for
 299          * the NUL at the end.
 300          */
 301         while ((err = read(masterfd, &c, 1)) == 1) {
 302                 if (i >= (sizeof (handshake) - 1))
 303                         break;
 304                 if (c == '\n')
 305                         break;
 306                 handshake[i] = c;
 307                 i++;
 308         }
 309 
 310         /*
 311          * If something went wrong during the handshake we bail; perhaps
 312          * the server died off.
 313          */
 314         if (err == -1) {
 315                 zperror(gettext("Could not connect to zone console"));
 316                 goto bad;
 317         }
 318 
 319         if (strncmp(handshake, "OK", sizeof (handshake)) == 0)
 320                 return (0);
 321 
 322         zerror(gettext("Console is already in use by process ID %s."),
 323             handshake);
 324 bad:
 325         (void) close(sockfd);
 326         masterfd = -1;
 327         return (-1);
 328 }
 329 
 330 
 331 /*
 332  * Routines to handle pty creation upon zone entry and to shuttle I/O back
 333  * and forth between the two terminals.  We also compute and store the
 334  * name of the slave terminal associated with the master side.
 335  */
 336 static int
 337 get_master_pty()
 338 {
 339         if ((masterfd = open("/dev/ptmx", O_RDWR|O_NONBLOCK)) < 0) {
 340                 zperror(gettext("failed to obtain a pseudo-tty"));
 341                 return (-1);
 342         }
 343         if (tcgetattr(STDIN_FILENO, &save_termios) == -1) {
 344                 zperror(gettext("failed to get terminal settings from stdin"));
 345                 return (-1);
 346         }
 347         (void) ioctl(STDIN_FILENO, TIOCGWINSZ, (char *)&winsize);
 348 
 349         return (0);
 350 }
 
 499          */
 500         if (tcgetattr(STDIN_FILENO, &effective_termios) < 0) {
 501                 zperror(gettext("failed to get user terminal settings"));
 502                 return (-1);
 503         }
 504         effective_termios.c_cc[VEOF] = save_termios.c_cc[VEOF];
 505         effective_termios.c_cc[VEOL] = save_termios.c_cc[VEOL];
 506 
 507         return (0);
 508 }
 509 
 510 /*
 511  * Copy terminal window size from our terminal to the pts.
 512  */
 513 /*ARGSUSED*/
 514 static void
 515 sigwinch(int s)
 516 {
 517         struct winsize ws;
 518 
 519         if (ioctl(0, TIOCGWINSZ, &ws) == 0)
 520                 (void) ioctl(masterfd, TIOCSWINSZ, &ws);
 521 }
 522 
 523 static volatile int close_on_sig = -1;
 524 
 525 static void
 526 /*ARGSUSED*/
 527 sigcld(int s)
 528 {
 529         int status;
 530         pid_t pid;
 531 
 532         /*
 533          * Peek at the exit status.  If this isn't the process we cared
 534          * about, then just reap it.
 535          */
 536         if ((pid = waitpid(child_pid, &status, WNOHANG|WNOWAIT)) != -1) {
 537                 if (pid == child_pid &&
 538                     (WIFEXITED(status) || WIFSIGNALED(status))) {
 539                         dead = 1;
 540                         if (close_on_sig != -1) {
 541                                 (void) write(close_on_sig, "a", 1);
 542                                 (void) close(close_on_sig);
 
 845                  * passed the test above, we would go into poll and hang.
 846                  * To avoid this we use the sig_fd as an additional poll fd.
 847                  * The signal handler writes into the other end of this pipe
 848                  * when the child dies so that the poll will always see that
 849                  * input and proceed.  We just loop around at that point and
 850                  * then notice the dead flag.
 851                  */
 852 
 853                 ret = poll(pollfds,
 854                     sizeof (pollfds) / sizeof (struct pollfd), -1);
 855 
 856                 if (ret == -1 && errno != EINTR) {
 857                         perror("poll failed");
 858                         break;
 859                 }
 860 
 861                 if (errno == EINTR && dead) {
 862                         break;
 863                 }
 864 
 865                 /* event from master side stdout */
 866                 if (pollfds[0].revents) {
 867                         if (pollfds[0].revents &
 868                             (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) {
 869                                 if (process_output(stdout_fd, STDOUT_FILENO)
 870                                     != 0)
 871                                         break;
 872                         } else {
 873                                 pollerr = pollfds[0].revents;
 874                                 break;
 875                         }
 876                 }
 877 
 878                 /* event from master side stderr */
 879                 if (pollfds[1].revents) {
 880                         if (pollfds[1].revents &
 881                             (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) {
 882                                 if (process_output(stderr_fd, STDERR_FILENO)
 883                                     != 0)
 884                                         break;
 885                         } else {
 886                                 pollerr = pollfds[1].revents;
 887                                 break;
 888                         }
 889                 }
 890 
 891                 /* event from user STDIN side */
 892                 if (pollfds[2].revents) {
 893                         if (pollfds[2].revents &
 894                             (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) {
 895                                 /*
 896                                  * stdin fd is stdin of the target; so,
 897                                  * the thing we'll write the user data *to*.
 898                                  *
 899                                  * Also, unlike on the output side, we
 900                                  * close the pipe on a zero-length message.
 901                                  */
 902                                 int res;
 903 
 904                                 if (raw_mode)
 905                                         res = process_raw_input(stdin_fd,
 906                                             appin_fd);
 
1036         /* Get the login command for the target zone. */
1037         bzero(result_buf, sizeof (result_buf));
1038 
1039         if (forced_login) {
1040                 if (brand_get_forcedlogin_cmd(bh, login,
1041                     result_buf, sizeof (result_buf)) != 0)
1042                         return (NULL);
1043         } else {
1044                 if (brand_get_login_cmd(bh, login,
1045                     result_buf, sizeof (result_buf)) != 0)
1046                         return (NULL);
1047         }
1048 
1049         /*
1050          * We got back a string that we'd like to execute.  But since
1051          * we're not doing the execution via a shell we'll need to convert
1052          * the exec string to an array of strings.  We'll do that here
1053          * but we're going to be very simplistic about it and break stuff
1054          * up based on spaces.  We're not even going to support any kind
1055          * of quoting or escape characters.  It's truly amazing that
1056          * there is no library function in OpenSolaris to do this for us.
1057          */
1058 
1059         /*
1060          * Be paranoid.  Since we're deliniating based on spaces make
1061          * sure there are no adjacent spaces.
1062          */
1063         if (strstr(result_buf, "  ") != NULL)
1064                 return (NULL);
1065 
1066         /* Remove any trailing whitespace.  */
1067         n = strlen(result_buf);
1068         if (result_buf[n - 1] == ' ')
1069                 result_buf[n - 1] = '\0';
1070 
1071         /* Count how many elements there are in the exec string. */
1072         ptr = result_buf;
1073         for (n = 2; ((ptr = strchr(ptr + 1, (int)' ')) != NULL); n++)
1074                 ;
1075 
1076         /* Allocate the argv array that we're going to return. */
1077         if ((new_argv = malloc(sizeof (char *) * n)) == NULL)
1078                 return (NULL);
1079 
1080         /* Tokenize the exec string and return. */
1081         a = 0;
1082         new_argv[a++] = result_buf;
1083         if (n > 2) {
1084                 (void) strtok_r(result_buf, " ", &lasts);
1085                 while ((new_argv[a++] = strtok_r(NULL, " ", &lasts)) != NULL)
1086                         ;
1087         } else {
1088                 new_argv[a++] = NULL;
1089         }
1090         assert(n == a);
1091         return (new_argv);
1092 }
1093 
1094 /*
1095  * Prepare argv array for exec'd process; if we're passing commands to the
1096  * new process, then use su(1M) to do the invocation.  Otherwise, use
1097  * 'login -z <from_zonename> -f' (-z is an undocumented option which tells
1098  * login that we're coming from another zone, and to disregard its CONSOLE
1099  * checks).
1100  */
1101 static char **
1102 prep_args(brand_handle_t bh, const char *login, char **argv)
1103 {
1104         int argc = 0, a = 0, i, n = -1;
1105         char **new_argv;
1106 
1107         if (argv != NULL) {
1108                 size_t subshell_len = 1;
1109                 char *subshell;
1110 
1111                 while (argv[argc] != NULL)
1112                         argc++;
1113 
1114                 for (i = 0; i < argc; i++) {
1115                         subshell_len += strlen(argv[i]) + 1;
1116                 }
1117                 if ((subshell = calloc(1, subshell_len)) == NULL)
1118                         return (NULL);
1119 
1120                 for (i = 0; i < argc; i++) {
1121                         (void) strcat(subshell, argv[i]);
1122                         (void) strcat(subshell, " ");
1123                 }
1124 
1125                 if (failsafe) {
1126                         n = 4;
1127                         if ((new_argv = malloc(sizeof (char *) * n)) == NULL)
1128                                 return (NULL);
1129 
1130                         new_argv[a++] = FAILSAFESHELL;
1131                 } else {
1132                         n = 5;
1133                         if ((new_argv = malloc(sizeof (char *) * n)) == NULL)
1134                                 return (NULL);
1135 
1136                         new_argv[a++] = SUPATH;
1137                         if (strcmp(login, "root") != 0) {
1138                                 new_argv[a++] = "-";
1139                                 n++;
1140                         }
1141                         new_argv[a++] = (char *)login;
1142                 }
1143                 new_argv[a++] = "-c";
1144                 new_argv[a++] = subshell;
1145                 new_argv[a++] = NULL;
1146                 assert(a == n);
1147         } else {
1148                 if (failsafe) {
1149                         n = 2;
1150                         if ((new_argv = malloc(sizeof (char *) * n)) == NULL)
1151                                 return (NULL);
1152                         new_argv[a++] = FAILSAFESHELL;
1153                         new_argv[a++] = NULL;
1154                         assert(n == a);
1155                 } else {
1156                         new_argv = zone_login_cmd(bh, login);
1157                 }
1158         }
1159 
1160         return (new_argv);
1161 }
1162 
1163 /*
1164  * Helper routine for prep_env below.
1165  */
1166 static char *
1167 add_env(char *name, char *value)
1168 {
1169         size_t sz = strlen(name) + strlen(value) + 2; /* name, =, value, NUL */
1170         char *str;
1171 
1172         if ((str = malloc(sz)) == NULL)
1173                 return (NULL);
1174 
1175         (void) snprintf(str, sz, "%s=%s", name, value);
1176         return (str);
1177 }
1178 
1179 /*
1180  * Prepare envp array for exec'd process.
1181  */
1182 static char **
1183 prep_env()
1184 {
1185         int e = 0, size = 1;
1186         char **new_env, *estr;
1187         char *term = getenv("TERM");
1188 
1189         size++; /* for $PATH */
1190         if (term != NULL)
1191                 size++;
1192 
1193         /*
1194          * In failsafe mode we set $HOME, since '-l' isn't valid in this mode.
1195          * We also set $SHELL, since neither login nor su will be around to do
1196          * it.
1197          */
1198         if (failsafe)
1199                 size += 2;
1200 
1201         if ((new_env = malloc(sizeof (char *) * size)) == NULL)
1202                 return (NULL);
1203 
1204         if ((estr = add_env("PATH", DEF_PATH)) == NULL)
1205                 return (NULL);
1206         new_env[e++] = estr;
1207 
1208         if (term != NULL) {
1209                 if ((estr = add_env("TERM", term)) == NULL)
1210                         return (NULL);
1211                 new_env[e++] = estr;
1212         }
1213 
1214         if (failsafe) {
1215                 if ((estr = add_env("HOME", "/")) == NULL)
1216                         return (NULL);
1217                 new_env[e++] = estr;
1218 
1219                 if ((estr = add_env("SHELL", FAILSAFESHELL)) == NULL)
1220                         return (NULL);
1221                 new_env[e++] = estr;
1222         }
1223 
1224         new_env[e++] = NULL;
 
1706         uid_t   uid;
1707         struct passwd *nptr;
1708 
1709         /*
1710          * Authorizations are checked to restrict access based on the
1711          * requested operation and zone name, It is assumed that the
1712          * program is running with all privileges, but that the real
1713          * user ID is that of the user or role on whose behalf we are
1714          * operating. So we start by getting the username that will be
1715          * used for subsequent authorization checks.
1716          */
1717 
1718         uid = getuid();
1719         if ((nptr = getpwuid(uid)) == NULL) {
1720                 zerror(gettext("could not get user name."));
1721                 _exit(1);
1722         }
1723         return (nptr->pw_name);
1724 }
1725 
1726 int
1727 main(int argc, char **argv)
1728 {
1729         int arg, console = 0;
1730         zoneid_t zoneid;
1731         zone_state_t st;
1732         char *login = "root";
1733         int lflag = 0;
1734         int nflag = 0;
1735         char *zonename = NULL;
1736         char **proc_args = NULL;
1737         char **new_args, **new_env;
1738         sigset_t block_cld;
1739         char devroot[MAXPATHLEN];
1740         char *slavename, slaveshortname[MAXPATHLEN];
1741         priv_set_t *privset;
1742         int tmpl_fd;
1743         char zonebrand[MAXNAMELEN];
1744         char default_brand[MAXNAMELEN];
1745         struct stat sb;
1746         char kernzone[ZONENAME_MAX];
1747         brand_handle_t bh;
1748         char user_cmd[MAXPATHLEN];
1749         char authname[MAXAUTHS];
1750 
1751         (void) setlocale(LC_ALL, "");
1752         (void) textdomain(TEXT_DOMAIN);
1753 
1754         (void) getpname(argv[0]);
1755         username = get_username();
1756 
1757         while ((arg = getopt(argc, argv, "dnECR:Se:l:Q")) != EOF) {
1758                 switch (arg) {
1759                 case 'C':
1760                         console = 1;
1761                         break;
1762                 case 'E':
1763                         nocmdchar = 1;
1764                         break;
1765                 case 'R':       /* undocumented */
1766                         if (*optarg != '/') {
1767                                 zerror(gettext("root path must be absolute."));
1768                                 exit(2);
1769                         }
1770                         if (stat(optarg, &sb) == -1 || !S_ISDIR(sb.st_mode)) {
1771                                 zerror(
1772                                     gettext("root path must be a directory."));
1773                                 exit(2);
1774                         }
1775                         zonecfg_set_root(optarg);
1776                         break;
1777                 case 'Q':
1778                         quiet = 1;
1779                         break;
1780                 case 'S':
1781                         failsafe = 1;
1782                         break;
1783                 case 'd':
1784                         disconnect = 1;
1785                         break;
1786                 case 'e':
1787                         set_cmdchar(optarg);
1788                         break;
1789                 case 'l':
1790                         login = optarg;
1791                         lflag = 1;
1792                         break;
1793                 case 'n':
1794                         nflag = 1;
1795                         break;
1796                 default:
1797                         usage();
1798                 }
1799         }
1800 
1801         if (console != 0) {
1802 
1803                 if (lflag != 0) {
1804                         zerror(gettext(
1805                             "-l may not be specified for console login"));
1806                         usage();
1807                 }
1808 
1809                 if (nflag != 0) {
1810                         zerror(gettext(
1811                             "-n may not be specified for console login"));
1812                         usage();
1813                 }
1814 
1815                 if (failsafe != 0) {
1816                         zerror(gettext(
1817                             "-S may not be specified for console login"));
1818                         usage();
1819                 }
1820 
1821                 if (zonecfg_in_alt_root()) {
1822                         zerror(gettext(
1823                             "-R may not be specified for console login"));
1824                         exit(2);
1825                 }
1826 
1827         }
1828 
1829         if (failsafe != 0 && lflag != 0) {
1830                 zerror(gettext("-l may not be specified for failsafe login"));
1831                 usage();
1832         }
1833 
1834         if (!console && disconnect != 0) {
1835                 zerror(gettext(
1836                     "-d may only be specified with console login"));
1837                 usage();
1838         }
1839 
1840         if (optind == (argc - 1)) {
1841                 /*
1842                  * zone name, no process name; this should be an interactive
1843                  * as long as STDIN is really a tty.
1844                  */
1845                 if (nflag != 0) {
1846                         zerror(gettext(
1847                             "-n may not be specified for interactive login"));
1848                         usage();
1849                 }
1850                 if (isatty(STDIN_FILENO))
1851                         interactive = 1;
1852                 zonename = argv[optind];
1853         } else if (optind < (argc - 1)) {
1854                 if (console) {
1855                         zerror(gettext("Commands may not be specified for "
1856                             "console login."));
1857                         usage();
1858                 }
1859                 /* zone name and process name, and possibly some args */
1860                 zonename = argv[optind];
1861                 proc_args = &argv[optind + 1];
1862                 interactive = 0;
1863         } else {
1864                 usage();
1865         }
1866 
1867         if (getzoneid() != GLOBAL_ZONEID) {
1868                 zerror(gettext("'%s' may only be used from the global zone"),
1869                     pname);
1870                 return (1);
1871         }
1872 
1873         if (strcmp(zonename, GLOBAL_ZONENAME) == 0) {
1874                 zerror(gettext("'%s' not applicable to the global zone"),
1875                     pname);
1876                 return (1);
1877         }
1878 
1879         if (zone_get_state(zonename, &st) != Z_OK) {
1880                 zerror(gettext("zone '%s' unknown"), zonename);
1881                 return (1);
1882         }
 
1928                 } else {
1929                         (void) snprintf(authname, MAXAUTHS, "%s%s%s",
1930                             ZONE_LOGIN_AUTH, KV_OBJECT, zonename);
1931                         if (failsafe || !interactive) {
1932                                 zerror(gettext("%s is not authorized for  "
1933                                     "failsafe or non-interactive login "
1934                                     "to  %s zone."), username, zonename);
1935                                 return (1);
1936                         } else if (chkauthattr(authname, username) == 0) {
1937                                 zerror(gettext("%s is not authorized "
1938                                     " to login to %s zone."),
1939                                     username, zonename);
1940                                 return (1);
1941                         }
1942                 }
1943         } else {
1944                 forced_login = B_TRUE;
1945         }
1946 
1947         /*
1948          * The console is a separate case from the rest of the code; handle
1949          * it first.
1950          */
1951         if (console) {
1952                 /*
1953                  * Ensure that zoneadmd for this zone is running.
1954                  */
1955                 if (start_zoneadmd(zonename) == -1)
1956                         return (1);
1957 
1958                 /*
1959                  * Make contact with zoneadmd.
1960                  */
1961                 if (get_console_master(zonename) == -1)
1962                         return (1);
1963 
1964                 if (!quiet)
1965                         (void) printf(
1966                             gettext("[Connected to zone '%s' console]\n"),
1967                             zonename);
1968 
1969                 if (set_tty_rawmode(STDIN_FILENO) == -1) {
1970                         reset_tty();
1971                         zperror(gettext("failed to set stdin pty to raw mode"));
1972                         return (1);
1973                 }
1974 
1975                 (void) sigset(SIGWINCH, sigwinch);
1976                 (void) sigwinch(0);
1977 
1978                 /*
1979                  * Run the I/O loop until we get disconnected.
1980                  */
1981                 doio(masterfd, -1, masterfd, -1, -1, B_FALSE);
1982                 reset_tty();
1983                 if (!quiet)
1984                         (void) printf(
1985                             gettext("\n[Connection to zone '%s' console "
1986                             "closed]\n"), zonename);
1987 
1988                 return (0);
1989         }
1990 
1991         if (st != ZONE_STATE_RUNNING && st != ZONE_STATE_MOUNTED) {
1992                 zerror(gettext("login allowed only to running zones "
1993                     "(%s is '%s')."), zonename, zone_state_str(st));
1994                 return (1);
1995         }
1996 
1997         (void) strlcpy(kernzone, zonename, sizeof (kernzone));
1998         if (zonecfg_in_alt_root()) {
1999                 FILE *fp = zonecfg_open_scratch("", B_FALSE);
2000 
2001                 if (fp == NULL || zonecfg_find_scratch(fp, zonename,
2002                     zonecfg_get_root(), kernzone, sizeof (kernzone)) == -1) {
2003                         zerror(gettext("cannot find scratch zone %s"),
2004                             zonename);
2005                         if (fp != NULL)
2006                                 zonecfg_close_scratch(fp);
 
2034          * the zone as native if it is cluster.  Cluster zones can be
2035          * native for the purpose of LU or upgrade, and the cluster
2036          * brand may not exist in the miniroot (such as in net install
2037          * upgrade).
2038          */
2039         if (zonecfg_default_brand(default_brand,
2040             sizeof (default_brand)) != Z_OK) {
2041                 zerror(gettext("unable to determine default brand"));
2042                 return (1);
2043         }
2044         if (zonecfg_in_alt_root() &&
2045             strcmp(zonebrand, CLUSTER_BRAND_NAME) == 0) {
2046                 (void) strlcpy(zonebrand, default_brand, sizeof (zonebrand));
2047         }
2048 
2049         if ((bh = brand_open(zonebrand)) == NULL) {
2050                 zerror(gettext("could not open brand for zone %s"), zonename);
2051                 return (1);
2052         }
2053 
2054         if ((new_args = prep_args(bh, login, proc_args)) == NULL) {
2055                 zperror(gettext("could not assemble new arguments"));
2056                 brand_close(bh);
2057                 return (1);
2058         }
2059         /*
2060          * Get the brand specific user_cmd.  This command is used to get
2061          * a passwd(4) entry for login.
2062          */
2063         if (!interactive && !failsafe) {
2064                 if (zone_get_user_cmd(bh, login, user_cmd,
2065                     sizeof (user_cmd)) == NULL) {
2066                         zerror(gettext("could not get user_cmd for zone %s"),
2067                             zonename);
2068                         brand_close(bh);
2069                         return (1);
2070                 }
2071         }
2072         brand_close(bh);
2073 
2074         if ((new_env = prep_env()) == NULL) {
2075                 zperror(gettext("could not assemble new environment"));
2076                 return (1);
2077         }
2078 
 
2184 
2185                 /*
2186                  * Close all fds except for the slave pty.
2187                  */
2188                 (void) fdwalk(close_func, &slavefd);
2189 
2190                 /*
2191                  * Temporarily dup slavefd to stderr; that way if we have
2192                  * to print out that zone_enter failed, the output will
2193                  * have somewhere to go.
2194                  */
2195                 if (slavefd != STDERR_FILENO)
2196                         (void) dup2(slavefd, STDERR_FILENO);
2197 
2198                 if (zone_enter(zoneid) == -1) {
2199                         zerror(gettext("could not enter zone %s: %s"),
2200                             zonename, strerror(errno));
2201                         return (1);
2202                 }
2203 
2204                 if (slavefd != STDERR_FILENO)
2205                         (void) close(STDERR_FILENO);
2206 
2207                 /*
2208                  * We take pains to get this process into a new process
2209                  * group, and subsequently a new session.  In this way,
2210                  * we'll have a session which doesn't yet have a controlling
2211                  * terminal.  When we open the slave, it will become the
2212                  * controlling terminal; no PIDs concerning pgrps or sids
2213                  * will leak inappropriately into the zone.
2214                  */
2215                 (void) setpgrp();
2216 
2217                 /*
2218                  * We need the slave pty to be referenced from the zone's
2219                  * /dev in order to ensure that the devt's, etc are all
2220                  * correct.  Otherwise we break ttyname and the like.
2221                  */
2222                 if ((newslave = open(slavename, O_RDWR)) == -1) {
2223                         (void) close(slavefd);
 
2225                 }
2226                 (void) close(slavefd);
2227                 slavefd = newslave;
2228 
2229                 /*
2230                  * dup the slave to the various FDs, so that when the
2231                  * spawned process does a write/read it maps to the slave
2232                  * pty.
2233                  */
2234                 (void) dup2(slavefd, STDIN_FILENO);
2235                 (void) dup2(slavefd, STDOUT_FILENO);
2236                 (void) dup2(slavefd, STDERR_FILENO);
2237                 if (slavefd != STDIN_FILENO && slavefd != STDOUT_FILENO &&
2238                     slavefd != STDERR_FILENO) {
2239                         (void) close(slavefd);
2240                 }
2241 
2242                 /*
2243                  * In failsafe mode, we don't use login(1), so don't try
2244                  * setting up a utmpx entry.
2245                  */
2246                 if (!failsafe)
2247                         if (setup_utmpx(slaveshortname) == -1)
2248                                 return (1);
2249 
2250                 /*
2251                  * The child needs to run as root to
2252                  * execute the brand's login program.
2253                  */
2254                 if (setuid(0) == -1) {
2255                         zperror(gettext("insufficient privilege"));
2256                         return (1);
2257                 }
2258 
2259                 (void) execve(new_args[0], new_args, new_env);
2260                 zperror(gettext("exec failure"));
2261                 return (1);
2262         }
2263 
2264         (void) ct_tmpl_clear(tmpl_fd);
2265         (void) close(tmpl_fd);
2266 
2267         /*
2268          * The rest is only for the parent process.
2269          */
2270         (void) sigset(SIGWINCH, sigwinch);
2271 
2272         postfork_dropprivs();
2273 
2274         (void) sigprocmask(SIG_UNBLOCK, &block_cld, NULL);
2275         doio(masterfd, -1, masterfd, -1, -1, B_FALSE);
2276 
2277         reset_tty();
2278         if (!quiet)
2279                 (void) fprintf(stderr,
2280                     gettext("\n[Connection to zone '%s' %s closed]\n"),
2281                     zonename, slaveshortname);
2282 
2283         if (pollerr != 0) {
2284                 (void) fprintf(stderr, gettext("Error: connection closed due "
2285                     "to unexpected pollevents=0x%x.\n"), pollerr);
2286                 return (1);
2287         }
2288 
2289         return (0);
2290 }
 | 
 
 
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2013 DEY Storage Systems, Inc.
  24  * Copyright (c) 2014 Gary Mills
  25  * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
  26  * Copyright 2016 Joyent, Inc.
  27  */
  28 
  29 /*
  30  * zlogin provides five types of login which allow users in the global
  31  * zone to access non-global zones.
  32  *
  33  * - "interactive login" is similar to rlogin(1); for example, the user could
  34  *   issue 'zlogin my-zone' or 'zlogin -e ^ -l me my-zone'.   The user is
  35  *   granted a new pty (which is then shoved into the zone), and an I/O
  36  *   loop between parent and child processes takes care of the interactive
  37  *   session.  In this mode, login(1) (and its -c option, which means
  38  *   "already authenticated") is employed to take care of the initialization
  39  *   of the user's session.
  40  *
  41  * - "non-interactive login" is similar to su(1M); the user could issue
  42  *   'zlogin my-zone ls -l' and the command would be run as specified.
  43  *   In this mode, zlogin sets up pipes as the communication channel, and
  44  *   'su' is used to do the login setup work.
  45  *
  46  * - "interactive command" is a combination of the above two modes where
  47  *   a command is provide like the non-interactive case, but the -i option is
  48  *   also provided to make things interactive. For example, the user could
  49  *   issue 'zlogin -i my-zone /bin/sh'. In this mode neither 'login -c' nor
  50  *   'su root -c' is prepended to the command invocation. Because of this
  51  *   there will be no wtmpx login record within the zone.
  52  *
  53  * - "console login" is the equivalent to accessing the tip line for a
  54  *   zone.  For example, the user can issue 'zlogin -C my-zone'.
  55  *   In this mode, zlogin contacts the zoneadmd process via unix domain
  56  *   socket.  If zoneadmd is not running, it starts it.  This allows the
  57  *   console to be available anytime the zone is installed, regardless of
  58  *   whether it is running.
  59  *
  60  * - "standalone-processs interactive" is specified with -I and connects to
  61  *   the zone's stdin, stdout and stderr zfd(7D) devices.
  62  */
  63 
  64 #include <sys/socket.h>
  65 #include <sys/termios.h>
  66 #include <sys/utsname.h>
  67 #include <sys/stat.h>
  68 #include <sys/types.h>
  69 #include <sys/contract/process.h>
  70 #include <sys/ctfs.h>
  71 #include <sys/brand.h>
  72 #include <sys/wait.h>
  73 #include <alloca.h>
  74 #include <assert.h>
  75 #include <ctype.h>
  76 #include <paths.h>
  77 #include <door.h>
  78 #include <errno.h>
  79 #include <nss_dbdefs.h>
  80 #include <poll.h>
  81 #include <priv.h>
 
 
  86 #include <signal.h>
  87 #include <stdarg.h>
  88 #include <stdio.h>
  89 #include <stdlib.h>
  90 #include <string.h>
  91 #include <strings.h>
  92 #include <stropts.h>
  93 #include <wait.h>
  94 #include <zone.h>
  95 #include <fcntl.h>
  96 #include <libdevinfo.h>
  97 #include <libintl.h>
  98 #include <locale.h>
  99 #include <libzonecfg.h>
 100 #include <libcontract.h>
 101 #include <libbrand.h>
 102 #include <auth_list.h>
 103 #include <auth_attr.h>
 104 #include <secdb.h>
 105 
 106 static int masterfd = -1;
 107 static int ctlfd = -1;
 108 static struct termios save_termios;
 109 static struct termios effective_termios;
 110 static int save_fd;
 111 static struct winsize winsize;
 112 static volatile int dead;
 113 static volatile pid_t child_pid = -1;
 114 static int interactive = 0;
 115 static priv_set_t *dropprivs;
 116 static unsigned int connect_flags = 0;
 117 
 118 static int nocmdchar = 0;
 119 static int failsafe = 0;
 120 static char cmdchar = '~';
 121 static int quiet = 0;
 122 static char zonebrand[MAXNAMELEN];
 123 
 124 static int pollerr = 0;
 125 
 126 static const char *pname;
 127 static char *username;
 128 
 129 /*
 130  * When forced_login is true, the user is not prompted
 131  * for an authentication password in the target zone.
 132  */
 133 static boolean_t forced_login = B_FALSE;
 134 
 135 #if !defined(TEXT_DOMAIN)               /* should be defined by cc -D */
 136 #define TEXT_DOMAIN     "SYS_TEST"      /* Use this only if it wasn't */
 137 #endif
 138 
 139 #define SUPATH1 "/usr/bin/su"
 140 #define SUPATH2 "/bin/su"
 141 #define FAILSAFESHELL   "/sbin/sh"
 142 #define DEFAULTSHELL    "/sbin/sh"
 143 #define DEF_PATH        "/usr/sbin:/usr/bin"
 144 #define LX_DEF_PATH     "/bin:/usr/sbin:/usr/bin"
 145 
 146 #define MAX_RETRY       30
 147 
 148 #define CLUSTER_BRAND_NAME      "cluster"
 149 
 150 /*
 151  * The ZLOGIN_BUFSIZ is larger than PIPE_BUF so we can be sure we're clearing
 152  * out the pipe when the child is exiting.  The ZLOGIN_RDBUFSIZ must be less
 153  * than ZLOGIN_BUFSIZ (because we share the buffer in doio).  This value is
 154  * also chosen in conjunction with the HI_WATER setting to make sure we
 155  * don't fill up the pipe.  We can write FIFOHIWAT (16k) into the pipe before
 156  * blocking.  By having ZLOGIN_RDBUFSIZ set to 1k and HI_WATER set to 8k, we
 157  * know we can always write a ZLOGIN_RDBUFSIZ chunk into the pipe when there
 158  * is less than HI_WATER data already in the pipe.
 159  */
 160 #define ZLOGIN_BUFSIZ   8192
 161 #define ZLOGIN_RDBUFSIZ 1024
 162 #define HI_WATER        8192
 163 
 164 /*
 165  * See canonify() below.  CANONIFY_LEN is the maximum length that a
 166  * "canonical" sequence will expand to (backslash, three octal digits, NUL).
 167  */
 168 #define CANONIFY_LEN 5
 169 
 170 static void
 171 usage(void)
 172 {
 173         (void) fprintf(stderr, gettext("usage: %s [-dinCEINQS] [-e cmdchar] "
 174             "[-l user] zonename [command [args ...] ]\n"), pname);
 175         exit(2);
 176 }
 177 
 178 static const char *
 179 getpname(const char *arg0)
 180 {
 181         const char *p = strrchr(arg0, '/');
 182 
 183         if (p == NULL)
 184                 p = arg0;
 185         else
 186                 p++;
 187 
 188         pname = p;
 189         return (p);
 190 }
 191 
 192 static void
 193 zerror(const char *fmt, ...)
 
 248 /*
 249  * The second part of the privilege drop.  We are paranoid about being attacked
 250  * by the zone, so we drop all privileges.  This should prevent a compromise
 251  * which gets us to fork(), exec(), symlink(), etc.
 252  */
 253 static void
 254 postfork_dropprivs()
 255 {
 256         if ((setppriv(PRIV_SET, PRIV_PERMITTED, dropprivs)) == -1) {
 257                 zperror(gettext("Warning: could not set permitted privileges"));
 258         }
 259         if ((setppriv(PRIV_SET, PRIV_LIMIT, dropprivs)) == -1) {
 260                 zperror(gettext("Warning: could not set limit privileges"));
 261         }
 262         if ((setppriv(PRIV_SET, PRIV_INHERITABLE, dropprivs)) == -1) {
 263                 zperror(gettext("Warning: could not set inheritable "
 264                     "privileges"));
 265         }
 266 }
 267 
 268 static int
 269 connect_zone_sock(const char *zname, const char *suffix, boolean_t verbose)
 270 {
 271         int sockfd = -1;
 272         struct sockaddr_un servaddr;
 273 
 274         if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
 275                 if (verbose)
 276                         zperror(gettext("could not create socket"));
 277                 return (-1);
 278         }
 279 
 280         bzero(&servaddr, sizeof (servaddr));
 281         servaddr.sun_family = AF_UNIX;
 282         (void) snprintf(servaddr.sun_path, sizeof (servaddr.sun_path),
 283             "%s/%s.%s", ZONES_TMPDIR, zname, suffix);
 284         if (connect(sockfd, (struct sockaddr *)&servaddr,
 285             sizeof (servaddr)) == -1) {
 286                 if (verbose)
 287                         zperror(gettext("Could not connect to zone"));
 288                 (void) close(sockfd);
 289                 return (-1);
 290         }
 291         return (sockfd);
 292 }
 293 
 294 
 295 static int
 296 handshake_zone_sock(int sockfd, unsigned int flags)
 297 {
 298         char clientid[MAXPATHLEN];
 299         char handshake[MAXPATHLEN], c;
 300         int msglen;
 301         int i = 0, err = 0;
 302 
 303         msglen = snprintf(clientid, sizeof (clientid), "IDENT %s %u\n",
 304             setlocale(LC_MESSAGES, NULL), flags);
 305 
 306         if (msglen >= sizeof (clientid) || msglen < 0) {
 307                 zerror("protocol error");
 308                 return (-1);
 309         }
 310 
 311         if (write(sockfd, clientid, msglen) != msglen) {
 312                 zerror("protocol error");
 313                 return (-1);
 314         }
 315 
 316         /*
 317          * Take care not to accumulate more than our fill, and leave room for
 318          * the NUL at the end.
 319          */
 320         bzero(handshake, sizeof (handshake));
 321         while ((err = read(sockfd, &c, 1)) == 1) {
 322                 if (i >= (sizeof (handshake) - 1))
 323                         break;
 324                 if (c == '\n')
 325                         break;
 326                 handshake[i] = c;
 327                 i++;
 328         }
 329 
 330         /*
 331          * If something went wrong during the handshake we bail.
 332          * Perhaps the server died off.
 333          */
 334         if (err == -1) {
 335                 zperror(gettext("Could not connect to zone"));
 336                 return (-1);
 337         }
 338 
 339         if (strncmp(handshake, "OK", sizeof (handshake)) != 0) {
 340                 zerror(gettext("Zone is already in use by process ID %s."),
 341                     handshake);
 342                 return (-1);
 343         }
 344 
 345         return (0);
 346 }
 347 
 348 static int
 349 send_ctl_sock(const char *buf, size_t len)
 350 {
 351         char rbuf[BUFSIZ];
 352         int i;
 353         if (ctlfd == -1) {
 354                 return (-1);
 355         }
 356         if (write(ctlfd, buf, len) != len) {
 357                 return (-1);
 358         }
 359         /* read the response */
 360         for (i = 0; i < (BUFSIZ - 1); i++) {
 361                 char c;
 362                 if (read(ctlfd, &c, 1) != 1 || c == '\n' || c == '\0') {
 363                         break;
 364                 }
 365                 rbuf[i] = c;
 366         }
 367         rbuf[i+1] = '\0';
 368         if (strncmp("OK", rbuf, BUFSIZ) != 0) {
 369                 return (-1);
 370         }
 371         return (0);
 372 }
 373 /*
 374  * Routines to handle pty creation upon zone entry and to shuttle I/O back
 375  * and forth between the two terminals.  We also compute and store the
 376  * name of the slave terminal associated with the master side.
 377  */
 378 static int
 379 get_master_pty()
 380 {
 381         if ((masterfd = open("/dev/ptmx", O_RDWR|O_NONBLOCK)) < 0) {
 382                 zperror(gettext("failed to obtain a pseudo-tty"));
 383                 return (-1);
 384         }
 385         if (tcgetattr(STDIN_FILENO, &save_termios) == -1) {
 386                 zperror(gettext("failed to get terminal settings from stdin"));
 387                 return (-1);
 388         }
 389         (void) ioctl(STDIN_FILENO, TIOCGWINSZ, (char *)&winsize);
 390 
 391         return (0);
 392 }
 
 541          */
 542         if (tcgetattr(STDIN_FILENO, &effective_termios) < 0) {
 543                 zperror(gettext("failed to get user terminal settings"));
 544                 return (-1);
 545         }
 546         effective_termios.c_cc[VEOF] = save_termios.c_cc[VEOF];
 547         effective_termios.c_cc[VEOL] = save_termios.c_cc[VEOL];
 548 
 549         return (0);
 550 }
 551 
 552 /*
 553  * Copy terminal window size from our terminal to the pts.
 554  */
 555 /*ARGSUSED*/
 556 static void
 557 sigwinch(int s)
 558 {
 559         struct winsize ws;
 560 
 561         if (ioctl(0, TIOCGWINSZ, &ws) == 0) {
 562                 if (ctlfd != -1) {
 563                         char buf[BUFSIZ];
 564                         (void) snprintf(buf, sizeof (buf),
 565                             "TIOCSWINSZ %hu %hu\n", ws.ws_row, ws.ws_col);
 566                         (void) send_ctl_sock(buf, strlen(buf));
 567                 } else {
 568                         (void) ioctl(masterfd, TIOCSWINSZ, &ws);
 569                 }
 570         }
 571 }
 572 
 573 /*
 574  * Toggle zfd EOF mode and notify zoneadmd
 575  */
 576 /*ARGSUSED*/
 577 static void
 578 sigusr1(int s)
 579 {
 580         connect_flags ^= ZLOGIN_ZFD_EOF;
 581         if (ctlfd != -1) {
 582                 char buf[BUFSIZ];
 583                 (void) snprintf(buf, sizeof (buf), "SETFLAGS %u\n",
 584                     connect_flags);
 585                 (void) send_ctl_sock(buf, strlen(buf));
 586         }
 587 }
 588 
 589 static volatile int close_on_sig = -1;
 590 
 591 static void
 592 /*ARGSUSED*/
 593 sigcld(int s)
 594 {
 595         int status;
 596         pid_t pid;
 597 
 598         /*
 599          * Peek at the exit status.  If this isn't the process we cared
 600          * about, then just reap it.
 601          */
 602         if ((pid = waitpid(child_pid, &status, WNOHANG|WNOWAIT)) != -1) {
 603                 if (pid == child_pid &&
 604                     (WIFEXITED(status) || WIFSIGNALED(status))) {
 605                         dead = 1;
 606                         if (close_on_sig != -1) {
 607                                 (void) write(close_on_sig, "a", 1);
 608                                 (void) close(close_on_sig);
 
 911                  * passed the test above, we would go into poll and hang.
 912                  * To avoid this we use the sig_fd as an additional poll fd.
 913                  * The signal handler writes into the other end of this pipe
 914                  * when the child dies so that the poll will always see that
 915                  * input and proceed.  We just loop around at that point and
 916                  * then notice the dead flag.
 917                  */
 918 
 919                 ret = poll(pollfds,
 920                     sizeof (pollfds) / sizeof (struct pollfd), -1);
 921 
 922                 if (ret == -1 && errno != EINTR) {
 923                         perror("poll failed");
 924                         break;
 925                 }
 926 
 927                 if (errno == EINTR && dead) {
 928                         break;
 929                 }
 930 
 931                 /* event from master side stderr */
 932                 if (pollfds[1].revents) {
 933                         if (pollfds[1].revents &
 934                             (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) {
 935                                 if (process_output(stderr_fd, STDERR_FILENO)
 936                                     != 0)
 937                                         break;
 938                         } else {
 939                                 pollerr = pollfds[1].revents;
 940                                 break;
 941                         }
 942                 }
 943 
 944                 /* event from master side stdout */
 945                 if (pollfds[0].revents) {
 946                         if (pollfds[0].revents &
 947                             (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) {
 948                                 if (process_output(stdout_fd, STDOUT_FILENO)
 949                                     != 0)
 950                                         break;
 951                         } else {
 952                                 pollerr = pollfds[0].revents;
 953                                 break;
 954                         }
 955                 }
 956 
 957                 /* event from user STDIN side */
 958                 if (pollfds[2].revents) {
 959                         if (pollfds[2].revents &
 960                             (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) {
 961                                 /*
 962                                  * stdin fd is stdin of the target; so,
 963                                  * the thing we'll write the user data *to*.
 964                                  *
 965                                  * Also, unlike on the output side, we
 966                                  * close the pipe on a zero-length message.
 967                                  */
 968                                 int res;
 969 
 970                                 if (raw_mode)
 971                                         res = process_raw_input(stdin_fd,
 972                                             appin_fd);
 
1102         /* Get the login command for the target zone. */
1103         bzero(result_buf, sizeof (result_buf));
1104 
1105         if (forced_login) {
1106                 if (brand_get_forcedlogin_cmd(bh, login,
1107                     result_buf, sizeof (result_buf)) != 0)
1108                         return (NULL);
1109         } else {
1110                 if (brand_get_login_cmd(bh, login,
1111                     result_buf, sizeof (result_buf)) != 0)
1112                         return (NULL);
1113         }
1114 
1115         /*
1116          * We got back a string that we'd like to execute.  But since
1117          * we're not doing the execution via a shell we'll need to convert
1118          * the exec string to an array of strings.  We'll do that here
1119          * but we're going to be very simplistic about it and break stuff
1120          * up based on spaces.  We're not even going to support any kind
1121          * of quoting or escape characters.  It's truly amazing that
1122          * there is no library function in Illumos to do this for us.
1123          */
1124 
1125         /*
1126          * Be paranoid.  Since we're deliniating based on spaces make
1127          * sure there are no adjacent spaces.
1128          */
1129         if (strstr(result_buf, "  ") != NULL)
1130                 return (NULL);
1131 
1132         /* Remove any trailing whitespace.  */
1133         n = strlen(result_buf);
1134         if (result_buf[n - 1] == ' ')
1135                 result_buf[n - 1] = '\0';
1136 
1137         /* Count how many elements there are in the exec string. */
1138         ptr = result_buf;
1139         for (n = 2; ((ptr = strchr(ptr + 1, (int)' ')) != NULL); n++)
1140                 ;
1141 
1142         /* Allocate the argv array that we're going to return. */
1143         if ((new_argv = malloc(sizeof (char *) * n)) == NULL)
1144                 return (NULL);
1145 
1146         /* Tokenize the exec string and return. */
1147         a = 0;
1148         new_argv[a++] = result_buf;
1149         if (n > 2) {
1150                 (void) strtok_r(result_buf, " ", &lasts);
1151                 while ((new_argv[a++] = strtok_r(NULL, " ", &lasts)) != NULL)
1152                         ;
1153         } else {
1154                 new_argv[a++] = NULL;
1155         }
1156         assert(n == a);
1157         return (new_argv);
1158 }
1159 
1160 /*
1161  * Prepare argv array for exec'd process.  If commands are passed to the new
1162  * process and su(1M) is avalable, use it for the invocation.  Otherwise, use
1163  * 'login -z <from_zonename> -f' (-z is an undocumented option which tells
1164  * login that we're coming from another zone, and to disregard its CONSOLE
1165  * checks).
1166  */
1167 static char **
1168 prep_args(brand_handle_t bh, char *zonename, const char *login, char **argv)
1169 {
1170         int argc = 0, i;
1171         size_t subshell_len = 1;
1172         char *subshell = NULL, *supath = NULL;
1173         char **new_argv = NULL;
1174 
1175         if (argv == NULL) {
1176                 if (failsafe) {
1177                         if ((new_argv = malloc(sizeof (char *) * 2)) == NULL)
1178                                 return (NULL);
1179                         new_argv[0] = FAILSAFESHELL;
1180                         new_argv[1] = NULL;
1181                 } else {
1182                         new_argv = zone_login_cmd(bh, login);
1183                 }
1184                 return (new_argv);
1185         }
1186 
1187         /*
1188          * Attempt to locate a 'su' binary if not using the failsafe shell.
1189          */
1190         if (!failsafe) {
1191                 struct stat sb;
1192                 char zonepath[MAXPATHLEN];
1193                 char supath_check[MAXPATHLEN];
1194 
1195                 if (zone_get_zonepath(zonename, zonepath,
1196                     sizeof (zonepath)) != Z_OK) {
1197                         zerror(gettext("unable to determine zone "
1198                             "path"));
1199                         return (NULL);
1200                 }
1201 
1202                 (void) snprintf(supath_check, sizeof (supath), "%s/root/%s",
1203                     zonepath, SUPATH1);
1204                 if (stat(supath_check, &sb) == 0) {
1205                         supath = SUPATH1;
1206                 } else {
1207                         (void) snprintf(supath_check, sizeof (supath_check),
1208                             "%s/root/%s", zonepath, SUPATH2);
1209                         if (stat(supath_check, &sb) == 0) {
1210                                 supath = SUPATH2;
1211                         }
1212                 }
1213         }
1214 
1215         /*
1216          * With no failsafe shell or supath to wrap the incoming command, the
1217          * arguments are passed straight through.
1218          */
1219         if (!failsafe && supath == NULL) {
1220                 /*
1221                  * Such an outcome is not acceptable, however, if the caller
1222                  * expressed a desire to switch users.
1223                  */
1224                 if (strcmp(login, "root") != 0) {
1225                         zerror(gettext("unable to find 'su' command"));
1226                         return (NULL);
1227                 }
1228                 return (argv);
1229         }
1230 
1231         /*
1232          * Inventory arguments and allocate a buffer to escape them for the
1233          * subshell.
1234          */
1235         while (argv[argc] != NULL) {
1236                 /*
1237                  * Allocate enough space for the delimiter and 2
1238                  * quotes which might be needed.
1239                  */
1240                 subshell_len += strlen(argv[argc]) + 3;
1241                 argc++;
1242         }
1243         if ((subshell = calloc(1, subshell_len)) == NULL) {
1244                 return (NULL);
1245         }
1246 
1247         /*
1248          * The handling of quotes in the following block may seem unusual, but
1249          * it is done this way for backward compatibility.
1250          * When running a command, zlogin is documented as:
1251          *    zlogin zonename command args
1252          * However, some code has come to depend on the following usage:
1253          *    zlogin zonename 'command args'
1254          * This relied on the fact that the single argument would be re-parsed
1255          * within the zone and excuted as a command with an argument. To remain
1256          * compatible with this (incorrect) usage, if there is only a single
1257          * argument, it is not quoted, even if it has embedded spaces.
1258          *
1259          * Here are two examples which both need to work:
1260          * 1) zlogin foo 'echo hello'
1261          *    This has a single argv member with a space in it but will not be
1262          *    quoted on the command passed into the zone.
1263          * 2) zlogin foo bash -c 'echo hello'
1264          *    This has 3 argv members. The 3rd arg has a space and must be
1265          *    quoted on the command passed into the zone.
1266          */
1267         for (i = 0; i < argc; i++) {
1268                 if (i > 0)
1269                         (void) strcat(subshell, " ");
1270 
1271                 if (argc > 1 && (strchr(argv[i], ' ') != NULL ||
1272                     strchr(argv[i], '\t') != NULL)) {
1273                         (void) strcat(subshell, "'");
1274                         (void) strcat(subshell, argv[i]);
1275                         (void) strcat(subshell, "'");
1276                 } else {
1277                         (void) strcat(subshell, argv[i]);
1278                 }
1279         }
1280 
1281         if (failsafe) {
1282                 int a = 0, n = 4;
1283 
1284                 if ((new_argv = malloc(sizeof (char *) * n)) == NULL)
1285                         return (NULL);
1286 
1287                 new_argv[a++] = FAILSAFESHELL;
1288                 new_argv[a++] = "-c";
1289                 new_argv[a++] = subshell;
1290                 new_argv[a++] = NULL;
1291                 assert(a == n);
1292         } else {
1293                 int a = 0, n = 6;
1294 
1295                 assert(supath != NULL);
1296                 if ((new_argv = malloc(sizeof (char *) * n)) == NULL)
1297                         return (NULL);
1298 
1299                 new_argv[a++] = supath;
1300                 if (strcmp(login, "root") != 0) {
1301                         new_argv[a++] = "-";
1302                 } else {
1303                         n--;
1304                 }
1305                 new_argv[a++] = (char *)login;
1306                 new_argv[a++] = "-c";
1307                 new_argv[a++] = subshell;
1308                 new_argv[a++] = NULL;
1309                 assert(a == n);
1310         }
1311 
1312         return (new_argv);
1313 }
1314 
1315 /*
1316  * Helper routine for prep_env below.
1317  */
1318 static char *
1319 add_env(char *name, char *value)
1320 {
1321         size_t sz = strlen(name) + strlen(value) + 2; /* name, =, value, NUL */
1322         char *str;
1323 
1324         if ((str = malloc(sz)) == NULL)
1325                 return (NULL);
1326 
1327         (void) snprintf(str, sz, "%s=%s", name, value);
1328         return (str);
1329 }
1330 
1331 /*
1332  * Prepare envp array for exec'd process.
1333  */
1334 static char **
1335 prep_env()
1336 {
1337         int e = 0, size = 1;
1338         char **new_env, *estr;
1339         char *term = getenv("TERM");
1340         char *path;
1341 
1342         size++; /* for $PATH */
1343         if (term != NULL)
1344                 size++;
1345 
1346         /*
1347          * In failsafe mode we set $HOME, since '-l' isn't valid in this mode.
1348          * We also set $SHELL, since neither login nor su will be around to do
1349          * it.
1350          */
1351         if (failsafe)
1352                 size += 2;
1353 
1354         if ((new_env = malloc(sizeof (char *) * size)) == NULL)
1355                 return (NULL);
1356 
1357         if (strcmp(zonebrand, "lx") == 0)
1358                 path = LX_DEF_PATH;
1359         else
1360                 path = DEF_PATH;
1361 
1362         if ((estr = add_env("PATH", path)) == NULL)
1363                 return (NULL);
1364         new_env[e++] = estr;
1365 
1366         if (term != NULL) {
1367                 if ((estr = add_env("TERM", term)) == NULL)
1368                         return (NULL);
1369                 new_env[e++] = estr;
1370         }
1371 
1372         if (failsafe) {
1373                 if ((estr = add_env("HOME", "/")) == NULL)
1374                         return (NULL);
1375                 new_env[e++] = estr;
1376 
1377                 if ((estr = add_env("SHELL", FAILSAFESHELL)) == NULL)
1378                         return (NULL);
1379                 new_env[e++] = estr;
1380         }
1381 
1382         new_env[e++] = NULL;
 
1864         uid_t   uid;
1865         struct passwd *nptr;
1866 
1867         /*
1868          * Authorizations are checked to restrict access based on the
1869          * requested operation and zone name, It is assumed that the
1870          * program is running with all privileges, but that the real
1871          * user ID is that of the user or role on whose behalf we are
1872          * operating. So we start by getting the username that will be
1873          * used for subsequent authorization checks.
1874          */
1875 
1876         uid = getuid();
1877         if ((nptr = getpwuid(uid)) == NULL) {
1878                 zerror(gettext("could not get user name."));
1879                 _exit(1);
1880         }
1881         return (nptr->pw_name);
1882 }
1883 
1884 static boolean_t
1885 zlog_mode_logging(char *zonename, boolean_t *found)
1886 {
1887         boolean_t lm = B_FALSE;
1888         zone_dochandle_t handle;
1889         struct zone_attrtab attr;
1890 
1891         *found = B_FALSE;
1892         if ((handle = zonecfg_init_handle()) == NULL)
1893                 return (lm);
1894 
1895         if (zonecfg_get_handle(zonename, handle) != Z_OK)
1896                 goto done;
1897 
1898         if (zonecfg_setattrent(handle) != Z_OK)
1899                 goto done;
1900         while (zonecfg_getattrent(handle, &attr) == Z_OK) {
1901                 if (strcmp("zlog-mode", attr.zone_attr_name) == 0) {
1902                         int len = strlen(attr.zone_attr_value);
1903 
1904                         *found = B_TRUE;
1905                         if (strncmp("log", attr.zone_attr_value, 3) == 0 ||
1906                             strncmp("nolog", attr.zone_attr_value, 5) == 0 ||
1907                             (len >= 3 && attr.zone_attr_value[len - 2] == '-'))
1908                                 lm = B_TRUE;
1909                         break;
1910                 }
1911         }
1912         (void) zonecfg_endattrent(handle);
1913 
1914 done:
1915         zonecfg_fini_handle(handle);
1916         return (lm);
1917 }
1918 
1919 int
1920 main(int argc, char **argv)
1921 {
1922         int arg, console = 0, imode = 0;
1923         int estatus = 0;
1924         zoneid_t zoneid;
1925         zone_state_t st;
1926         char *login = "root";
1927         int iflag = 0;
1928         int lflag = 0;
1929         int nflag = 0;
1930         char *zonename = NULL;
1931         char **proc_args = NULL;
1932         char **new_args, **new_env;
1933         sigset_t block_cld;
1934         siginfo_t si;
1935         char devroot[MAXPATHLEN];
1936         char *slavename, slaveshortname[MAXPATHLEN];
1937         priv_set_t *privset;
1938         int tmpl_fd;
1939         char default_brand[MAXNAMELEN];
1940         struct stat sb;
1941         char kernzone[ZONENAME_MAX];
1942         brand_handle_t bh;
1943         char user_cmd[MAXPATHLEN];
1944         char authname[MAXAUTHS];
1945 
1946         (void) setlocale(LC_ALL, "");
1947         (void) textdomain(TEXT_DOMAIN);
1948 
1949         (void) getpname(argv[0]);
1950         username = get_username();
1951 
1952         while ((arg = getopt(argc, argv, "diNnECIR:Se:l:Q")) != EOF) {
1953                 switch (arg) {
1954                 case 'C':
1955                         console = 1;
1956                         break;
1957                 case 'E':
1958                         nocmdchar = 1;
1959                         break;
1960                 case 'I':
1961                         /*
1962                          * interactive mode is just a slight variation on the
1963                          * console mode.
1964                          */
1965                         console = 1;
1966                         imode = 1;
1967                         /* The default is HUP, disconnect on EOF */
1968                         connect_flags ^= ZLOGIN_ZFD_EOF;
1969                         break;
1970                 case 'R':       /* undocumented */
1971                         if (*optarg != '/') {
1972                                 zerror(gettext("root path must be absolute."));
1973                                 exit(2);
1974                         }
1975                         if (stat(optarg, &sb) == -1 || !S_ISDIR(sb.st_mode)) {
1976                                 zerror(
1977                                     gettext("root path must be a directory."));
1978                                 exit(2);
1979                         }
1980                         zonecfg_set_root(optarg);
1981                         break;
1982                 case 'Q':
1983                         quiet = 1;
1984                         break;
1985                 case 'S':
1986                         failsafe = 1;
1987                         break;
1988                 case 'd':
1989                         connect_flags |= ZLOGIN_DISCONNECT;
1990                         break;
1991                 case 'e':
1992                         set_cmdchar(optarg);
1993                         break;
1994                 case 'i':
1995                         iflag = 1;
1996                         break;
1997                 case 'l':
1998                         login = optarg;
1999                         lflag = 1;
2000                         break;
2001                 case 'N':
2002                         /* NOHUP - do not send EOF */
2003                         connect_flags ^= ZLOGIN_ZFD_EOF;
2004                         break;
2005                 case 'n':
2006                         nflag = 1;
2007                         break;
2008                 default:
2009                         usage();
2010                 }
2011         }
2012 
2013         if (console != 0) {
2014 
2015                 /*
2016                  * The only connect option in console mode is ZLOGIN_DISCONNECT
2017                  */
2018                 if (imode == 0)
2019                         connect_flags &= ZLOGIN_DISCONNECT;
2020 
2021                 if (lflag != 0) {
2022                         zerror(gettext(
2023                             "-l may not be specified for console login"));
2024                         usage();
2025                 }
2026 
2027                 if (nflag != 0) {
2028                         zerror(gettext(
2029                             "-n may not be specified for console login"));
2030                         usage();
2031                 }
2032 
2033                 if (failsafe != 0) {
2034                         zerror(gettext(
2035                             "-S may not be specified for console login"));
2036                         usage();
2037                 }
2038 
2039                 if (zonecfg_in_alt_root()) {
2040                         zerror(gettext(
2041                             "-R may not be specified for console login"));
2042                         exit(2);
2043                 }
2044 
2045         }
2046 
2047         if (iflag != 0 && nflag != 0) {
2048                 zerror(gettext("-i and -n flags are incompatible"));
2049                 usage();
2050         }
2051 
2052         if (failsafe != 0 && lflag != 0) {
2053                 zerror(gettext("-l may not be specified for failsafe login"));
2054                 usage();
2055         }
2056 
2057         if (!console && (connect_flags & ZLOGIN_DISCONNECT) != 0) {
2058                 zerror(gettext(
2059                     "-d may only be specified with console login"));
2060                 usage();
2061         }
2062 
2063         if (imode == 0 && (connect_flags & ZLOGIN_ZFD_EOF) != 0) {
2064                 zerror(gettext("-N may only be specified with -I"));
2065                 usage();
2066         }
2067 
2068         if (optind == (argc - 1)) {
2069                 /*
2070                  * zone name, no process name; this should be an interactive
2071                  * as long as STDIN is really a tty.
2072                  */
2073                 if (nflag != 0) {
2074                         zerror(gettext(
2075                             "-n may not be specified for interactive login"));
2076                         usage();
2077                 }
2078                 if (isatty(STDIN_FILENO))
2079                         interactive = 1;
2080                 zonename = argv[optind];
2081         } else if (optind < (argc - 1)) {
2082                 if (console) {
2083                         zerror(gettext("Commands may not be specified for "
2084                             "console login."));
2085                         usage();
2086                 }
2087                 /* zone name and process name, and possibly some args */
2088                 zonename = argv[optind];
2089                 proc_args = &argv[optind + 1];
2090                 if (iflag && isatty(STDIN_FILENO))
2091                         interactive = 1;
2092         } else {
2093                 usage();
2094         }
2095 
2096         if (getzoneid() != GLOBAL_ZONEID) {
2097                 zerror(gettext("'%s' may only be used from the global zone"),
2098                     pname);
2099                 return (1);
2100         }
2101 
2102         if (strcmp(zonename, GLOBAL_ZONENAME) == 0) {
2103                 zerror(gettext("'%s' not applicable to the global zone"),
2104                     pname);
2105                 return (1);
2106         }
2107 
2108         if (zone_get_state(zonename, &st) != Z_OK) {
2109                 zerror(gettext("zone '%s' unknown"), zonename);
2110                 return (1);
2111         }
 
2157                 } else {
2158                         (void) snprintf(authname, MAXAUTHS, "%s%s%s",
2159                             ZONE_LOGIN_AUTH, KV_OBJECT, zonename);
2160                         if (failsafe || !interactive) {
2161                                 zerror(gettext("%s is not authorized for  "
2162                                     "failsafe or non-interactive login "
2163                                     "to  %s zone."), username, zonename);
2164                                 return (1);
2165                         } else if (chkauthattr(authname, username) == 0) {
2166                                 zerror(gettext("%s is not authorized "
2167                                     " to login to %s zone."),
2168                                     username, zonename);
2169                                 return (1);
2170                         }
2171                 }
2172         } else {
2173                 forced_login = B_TRUE;
2174         }
2175 
2176         /*
2177          * The console (or standalong interactive mode) is a separate case from
2178          * the rest of the code; handle it first.
2179          */
2180         if (console) {
2181                 int gz_stderr_fd = -1;
2182                 int retry;
2183                 boolean_t set_raw = B_TRUE;
2184 
2185                 if (imode) {
2186                         boolean_t has_zfd_config;
2187 
2188                         if (zlog_mode_logging(zonename, &has_zfd_config))
2189                                 set_raw = B_FALSE;
2190 
2191                         /*
2192                          * Asked for standalone interactive mode but the
2193                          * zlog-mode attribute is not configured on the zone.
2194                          */
2195                         if (!has_zfd_config) {
2196                                 zerror(gettext("'%s' is not configured on "
2197                                     "the zone"), "zlog-mode");
2198                                 return (1);
2199                         }
2200                 }
2201 
2202                 /*
2203                  * Ensure that zoneadmd for this zone is running.
2204                  */
2205                 if (start_zoneadmd(zonename) == -1)
2206                         return (1);
2207 
2208                 /*
2209                  * Make contact with zoneadmd.
2210                  *
2211                  * Handshake with the control socket first. We handle retries
2212                  * here since the relevant thread in zoneadmd might not have
2213                  * finished setting up yet.
2214                  */
2215                 for (retry = 0; retry < MAX_RETRY; retry++) {
2216                         masterfd = connect_zone_sock(zonename,
2217                             (imode ? "server_ctl" : "console_sock"), B_FALSE);
2218                         if (masterfd != -1)
2219                                 break;
2220                         (void) sleep(1);
2221                 }
2222 
2223                 if (retry == MAX_RETRY) {
2224                         zerror(gettext("unable to connect for %d seconds"),
2225                             MAX_RETRY);
2226                         return (1);
2227                 }
2228 
2229                 if (handshake_zone_sock(masterfd, connect_flags) != 0) {
2230                         (void) close(masterfd);
2231                         return (1);
2232                 }
2233 
2234                 if (imode) {
2235                         ctlfd = masterfd;
2236 
2237                         /* Now open the io-related sockets */
2238                         masterfd = connect_zone_sock(zonename, "server_out",
2239                             B_TRUE);
2240                         gz_stderr_fd = connect_zone_sock(zonename,
2241                             "server_err", B_TRUE);
2242                         if (masterfd == -1 || gz_stderr_fd == -1) {
2243                                 (void) close(ctlfd);
2244                                 (void) close(masterfd);
2245                                 (void) close(gz_stderr_fd);
2246                                 return (1);
2247                         }
2248                 }
2249 
2250                 if (!quiet) {
2251                         if (imode)
2252                                 (void) printf(gettext("[Connected to zone '%s' "
2253                                     "interactively]\n"), zonename);
2254                         else
2255                                 (void) printf(gettext("[Connected to zone '%s' "
2256                                     "console]\n"), zonename);
2257                 }
2258 
2259                 if (set_raw && set_tty_rawmode(STDIN_FILENO) == -1) {
2260                         reset_tty();
2261                         zperror(gettext("failed to set stdin pty to raw mode"));
2262                         return (1);
2263                 }
2264 
2265                 (void) sigset(SIGWINCH, sigwinch);
2266                 (void) sigwinch(0);
2267 
2268                 if (imode) {
2269                         /* Allow EOF mode toggling via SIGUSR1 */
2270                         (void) sigset(SIGUSR1, sigusr1);
2271                 }
2272 
2273                 /*
2274                  * Run the I/O loop until we get disconnected.
2275                  */
2276                 doio(masterfd, -1, masterfd, gz_stderr_fd, -1, B_FALSE);
2277                 reset_tty();
2278                 if (!quiet) {
2279                         if (imode)
2280                                 (void) printf(gettext("\n[Interactive "
2281                                     "connection to zone '%s' closed]\n"),
2282                                     zonename);
2283                         else
2284                                 (void) printf(gettext("\n[Connection to zone "
2285                                     "'%s' console closed]\n"), zonename);
2286                 }
2287 
2288                 return (0);
2289         }
2290 
2291         if (st != ZONE_STATE_RUNNING && st != ZONE_STATE_MOUNTED) {
2292                 zerror(gettext("login allowed only to running zones "
2293                     "(%s is '%s')."), zonename, zone_state_str(st));
2294                 return (1);
2295         }
2296 
2297         (void) strlcpy(kernzone, zonename, sizeof (kernzone));
2298         if (zonecfg_in_alt_root()) {
2299                 FILE *fp = zonecfg_open_scratch("", B_FALSE);
2300 
2301                 if (fp == NULL || zonecfg_find_scratch(fp, zonename,
2302                     zonecfg_get_root(), kernzone, sizeof (kernzone)) == -1) {
2303                         zerror(gettext("cannot find scratch zone %s"),
2304                             zonename);
2305                         if (fp != NULL)
2306                                 zonecfg_close_scratch(fp);
 
2334          * the zone as native if it is cluster.  Cluster zones can be
2335          * native for the purpose of LU or upgrade, and the cluster
2336          * brand may not exist in the miniroot (such as in net install
2337          * upgrade).
2338          */
2339         if (zonecfg_default_brand(default_brand,
2340             sizeof (default_brand)) != Z_OK) {
2341                 zerror(gettext("unable to determine default brand"));
2342                 return (1);
2343         }
2344         if (zonecfg_in_alt_root() &&
2345             strcmp(zonebrand, CLUSTER_BRAND_NAME) == 0) {
2346                 (void) strlcpy(zonebrand, default_brand, sizeof (zonebrand));
2347         }
2348 
2349         if ((bh = brand_open(zonebrand)) == NULL) {
2350                 zerror(gettext("could not open brand for zone %s"), zonename);
2351                 return (1);
2352         }
2353 
2354         /*
2355          * The 'interactive' parameter (-i option) indicates that we're running
2356          * a command interactively. In this case we skip prep_args so that we
2357          * don't prepend the 'su root -c' preamble to the command invocation
2358          * since the 'su' command typically will execute a setpgrp which will
2359          * disassociate the actual command from the controlling terminal that
2360          * we (zlogin) setup.
2361          */
2362         if (!iflag) {
2363                 if ((new_args = prep_args(bh, zonename, login, proc_args))
2364                     == NULL) {
2365                         zperror(gettext("could not assemble new arguments"));
2366                         brand_close(bh);
2367                         return (1);
2368                 }
2369         }
2370 
2371         /*
2372          * Get the brand specific user_cmd.  This command is used to get
2373          * a passwd(4) entry for login.
2374          */
2375         if (!interactive && !failsafe) {
2376                 if (zone_get_user_cmd(bh, login, user_cmd,
2377                     sizeof (user_cmd)) == NULL) {
2378                         zerror(gettext("could not get user_cmd for zone %s"),
2379                             zonename);
2380                         brand_close(bh);
2381                         return (1);
2382                 }
2383         }
2384         brand_close(bh);
2385 
2386         if ((new_env = prep_env()) == NULL) {
2387                 zperror(gettext("could not assemble new environment"));
2388                 return (1);
2389         }
2390 
 
2496 
2497                 /*
2498                  * Close all fds except for the slave pty.
2499                  */
2500                 (void) fdwalk(close_func, &slavefd);
2501 
2502                 /*
2503                  * Temporarily dup slavefd to stderr; that way if we have
2504                  * to print out that zone_enter failed, the output will
2505                  * have somewhere to go.
2506                  */
2507                 if (slavefd != STDERR_FILENO)
2508                         (void) dup2(slavefd, STDERR_FILENO);
2509 
2510                 if (zone_enter(zoneid) == -1) {
2511                         zerror(gettext("could not enter zone %s: %s"),
2512                             zonename, strerror(errno));
2513                         return (1);
2514                 }
2515 
2516                 /* Note: we're now inside the zone, can't use gettext anymore */
2517 
2518                 if (slavefd != STDERR_FILENO)
2519                         (void) close(STDERR_FILENO);
2520 
2521                 /*
2522                  * We take pains to get this process into a new process
2523                  * group, and subsequently a new session.  In this way,
2524                  * we'll have a session which doesn't yet have a controlling
2525                  * terminal.  When we open the slave, it will become the
2526                  * controlling terminal; no PIDs concerning pgrps or sids
2527                  * will leak inappropriately into the zone.
2528                  */
2529                 (void) setpgrp();
2530 
2531                 /*
2532                  * We need the slave pty to be referenced from the zone's
2533                  * /dev in order to ensure that the devt's, etc are all
2534                  * correct.  Otherwise we break ttyname and the like.
2535                  */
2536                 if ((newslave = open(slavename, O_RDWR)) == -1) {
2537                         (void) close(slavefd);
 
2539                 }
2540                 (void) close(slavefd);
2541                 slavefd = newslave;
2542 
2543                 /*
2544                  * dup the slave to the various FDs, so that when the
2545                  * spawned process does a write/read it maps to the slave
2546                  * pty.
2547                  */
2548                 (void) dup2(slavefd, STDIN_FILENO);
2549                 (void) dup2(slavefd, STDOUT_FILENO);
2550                 (void) dup2(slavefd, STDERR_FILENO);
2551                 if (slavefd != STDIN_FILENO && slavefd != STDOUT_FILENO &&
2552                     slavefd != STDERR_FILENO) {
2553                         (void) close(slavefd);
2554                 }
2555 
2556                 /*
2557                  * In failsafe mode, we don't use login(1), so don't try
2558                  * setting up a utmpx entry.
2559                  *
2560                  * A branded zone may have very different utmpx semantics.
2561                  * At the moment, we only have two brand types:
2562                  * Illumos-like (native, sn1) and Linux.  In the Illumos
2563                  * case, we know exactly how to do the necessary utmpx
2564                  * setup.  Fortunately for us, the Linux /bin/login is
2565                  * prepared to deal with a non-initialized utmpx entry, so
2566                  * we can simply skip it.  If future brands don't fall into
2567                  * either category, we'll have to add a per-brand utmpx
2568                  * setup hook.
2569                  */
2570                 if (!failsafe && (strcmp(zonebrand, "lx") != 0))
2571                         if (setup_utmpx(slaveshortname) == -1)
2572                                 return (1);
2573 
2574                 /*
2575                  * The child needs to run as root to
2576                  * execute the brand's login program.
2577                  */
2578                 if (setuid(0) == -1) {
2579                         zperror("insufficient privilege");
2580                         return (1);
2581                 }
2582 
2583                 if (iflag) {
2584                         (void) execve(proc_args[0], proc_args, new_env);
2585                 } else {
2586                         (void) execve(new_args[0], new_args, new_env);
2587                 }
2588                 zperror("exec failure");
2589                 return (ENOEXEC);
2590         }
2591 
2592         (void) ct_tmpl_clear(tmpl_fd);
2593         (void) close(tmpl_fd);
2594 
2595         /*
2596          * The rest is only for the parent process.
2597          */
2598         (void) sigset(SIGWINCH, sigwinch);
2599 
2600         postfork_dropprivs();
2601 
2602         (void) sigprocmask(SIG_UNBLOCK, &block_cld, NULL);
2603         doio(masterfd, -1, masterfd, -1, -1, B_FALSE);
2604 
2605         reset_tty();
2606         if (!quiet)
2607                 (void) fprintf(stderr,
2608                     gettext("\n[Connection to zone '%s' %s closed]\n"),
2609                     zonename, slaveshortname);
2610 
2611         if (pollerr != 0) {
2612                 (void) fprintf(stderr, gettext("Error: connection closed due "
2613                     "to unexpected pollevents=0x%x.\n"), pollerr);
2614                 return (EPIPE);
2615         }
2616 
2617         /* reap child and get its status */
2618         if (waitid(P_PID, child_pid, &si, WEXITED | WNOHANG) == -1) {
2619                 estatus = errno;
2620         } else if (si.si_pid == 0) {
2621                 estatus = ECHILD;
2622         } else if (si.si_code == CLD_EXITED) {
2623                 estatus = si.si_status;
2624         } else {
2625                 estatus = ECONNABORTED;
2626         }
2627 
2628         return (estatus);
2629 }
 |