5 * Common Development and Distribution License (the "License").
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 2016 Joyent, Inc.
26 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
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
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 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);
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 snprintf(buf, sizeof (buf), "TIOCSWINSZ %hu %hu\n",
565 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 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 &&
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 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,
|
5 * Common Development and Distribution License (the "License").
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
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);
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 &&
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,
|