Annotation of src/usr.bin/ssh/sshpty.c, Revision 1.12.6.1
1.12.6.1! brad 1: /* $OpenBSD: sshpty.c,v 1.26 2006/08/03 03:34:42 deraadt Exp $ */
1.1 djm 2: /*
3: * Author: Tatu Ylonen <ylo@cs.hut.fi>
4: * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5: * All rights reserved
6: * Allocating a pseudo-terminal, and making it the controlling tty.
7: *
8: * As far as I am concerned, the code I have written for this software
9: * can be used freely for any purpose. Any derived versions of this
10: * software must be clearly marked as such, and if the derived work is
11: * incompatible with the protocol description in the RFC file, it must be
12: * called by a name other than "ssh" or "Secure Shell".
13: */
14:
1.12.6.1! brad 15: #include <sys/types.h>
! 16: #include <sys/ioctl.h>
! 17: #include <sys/stat.h>
! 18: #include <errno.h>
! 19: #include <fcntl.h>
! 20: #include <grp.h>
! 21: #include <paths.h>
! 22: #include <pwd.h>
! 23: #include <string.h>
! 24: #include <termios.h>
! 25: #include <unistd.h>
1.1 djm 26: #include <util.h>
1.12.6.1! brad 27: #include <stdarg.h>
! 28:
1.1 djm 29: #include "sshpty.h"
30: #include "log.h"
31:
32: /* Pty allocated with _getpty gets broken if we do I_PUSH:es to it. */
33: #if defined(HAVE__GETPTY) || defined(HAVE_OPENPTY)
34: #undef HAVE_DEV_PTMX
35: #endif
36:
37: #ifndef O_NOCTTY
38: #define O_NOCTTY 0
39: #endif
40:
41: /*
42: * Allocates and opens a pty. Returns 0 if no pty could be allocated, or
43: * nonzero if a pty was successfully allocated. On success, open file
44: * descriptors for the pty and tty sides and the name of the tty side are
45: * returned (the buffer must be able to hold at least 64 characters).
46: */
47:
48: int
1.12.6.1! brad 49: pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
1.1 djm 50: {
51: char buf[64];
52: int i;
53:
54: i = openpty(ptyfd, ttyfd, buf, NULL, NULL);
55: if (i < 0) {
56: error("openpty: %.100s", strerror(errno));
57: return 0;
58: }
59: strlcpy(namebuf, buf, namebuflen); /* possible truncation */
60: return 1;
61: }
62:
63: /* Releases the tty. Its ownership is returned to root, and permissions to 0666. */
64:
65: void
1.12 avsm 66: pty_release(const char *tty)
1.1 djm 67: {
1.12 avsm 68: if (chown(tty, (uid_t) 0, (gid_t) 0) < 0)
69: error("chown %.100s 0 0 failed: %.100s", tty, strerror(errno));
70: if (chmod(tty, (mode_t) 0666) < 0)
71: error("chmod %.100s 0666 failed: %.100s", tty, strerror(errno));
1.1 djm 72: }
73:
1.10 markus 74: /* Makes the tty the process's controlling tty and sets it to sane modes. */
1.1 djm 75:
76: void
1.12 avsm 77: pty_make_controlling_tty(int *ttyfd, const char *tty)
1.1 djm 78: {
79: int fd;
80:
81: /* First disconnect from the old controlling tty. */
82: #ifdef TIOCNOTTY
83: fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
84: if (fd >= 0) {
85: (void) ioctl(fd, TIOCNOTTY, NULL);
86: close(fd);
87: }
88: #endif /* TIOCNOTTY */
89: if (setsid() < 0)
90: error("setsid: %.100s", strerror(errno));
91:
92: /*
93: * Verify that we are successfully disconnected from the controlling
94: * tty.
95: */
96: fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
97: if (fd >= 0) {
98: error("Failed to disconnect from controlling tty.");
99: close(fd);
100: }
101: /* Make it our controlling tty. */
102: #ifdef TIOCSCTTY
103: debug("Setting controlling tty using TIOCSCTTY.");
104: if (ioctl(*ttyfd, TIOCSCTTY, NULL) < 0)
105: error("ioctl(TIOCSCTTY): %.100s", strerror(errno));
106: #endif /* TIOCSCTTY */
1.12 avsm 107: fd = open(tty, O_RDWR);
1.1 djm 108: if (fd < 0)
1.12 avsm 109: error("%.100s: %.100s", tty, strerror(errno));
1.1 djm 110: else
111: close(fd);
112:
113: /* Verify that we now have a controlling tty. */
114: fd = open(_PATH_TTY, O_WRONLY);
115: if (fd < 0)
116: error("open /dev/tty failed - could not set controlling tty: %.100s",
1.4 deraadt 117: strerror(errno));
1.6 deraadt 118: else
1.1 djm 119: close(fd);
120: }
121:
122: /* Changes the window size associated with the pty. */
123:
124: void
1.12.6.1! brad 125: pty_change_window_size(int ptyfd, u_int row, u_int col,
! 126: u_int xpixel, u_int ypixel)
1.1 djm 127: {
128: struct winsize w;
1.6 deraadt 129:
1.12.6.1! brad 130: /* may truncate u_int -> u_short */
1.1 djm 131: w.ws_row = row;
132: w.ws_col = col;
133: w.ws_xpixel = xpixel;
134: w.ws_ypixel = ypixel;
135: (void) ioctl(ptyfd, TIOCSWINSZ, &w);
136: }
137:
138: void
1.12 avsm 139: pty_setowner(struct passwd *pw, const char *tty)
1.1 djm 140: {
141: struct group *grp;
142: gid_t gid;
143: mode_t mode;
144: struct stat st;
145:
146: /* Determine the group to make the owner of the tty. */
147: grp = getgrnam("tty");
148: if (grp) {
149: gid = grp->gr_gid;
150: mode = S_IRUSR | S_IWUSR | S_IWGRP;
151: } else {
152: gid = pw->pw_gid;
153: mode = S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH;
154: }
155:
156: /*
157: * Change owner and mode of the tty as required.
1.3 markus 158: * Warn but continue if filesystem is read-only and the uids match/
159: * tty is owned by root.
1.1 djm 160: */
1.12 avsm 161: if (stat(tty, &st))
162: fatal("stat(%.100s) failed: %.100s", tty,
1.1 djm 163: strerror(errno));
164:
165: if (st.st_uid != pw->pw_uid || st.st_gid != gid) {
1.12 avsm 166: if (chown(tty, pw->pw_uid, gid) < 0) {
1.4 deraadt 167: if (errno == EROFS &&
1.6 deraadt 168: (st.st_uid == pw->pw_uid || st.st_uid == 0))
1.8 markus 169: debug("chown(%.100s, %u, %u) failed: %.100s",
1.12 avsm 170: tty, (u_int)pw->pw_uid, (u_int)gid,
1.4 deraadt 171: strerror(errno));
1.1 djm 172: else
1.5 deraadt 173: fatal("chown(%.100s, %u, %u) failed: %.100s",
1.12 avsm 174: tty, (u_int)pw->pw_uid, (u_int)gid,
1.4 deraadt 175: strerror(errno));
1.1 djm 176: }
177: }
178:
179: if ((st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != mode) {
1.12 avsm 180: if (chmod(tty, mode) < 0) {
1.1 djm 181: if (errno == EROFS &&
182: (st.st_mode & (S_IRGRP | S_IROTH)) == 0)
1.8 markus 183: debug("chmod(%.100s, 0%o) failed: %.100s",
1.12 avsm 184: tty, (u_int)mode, strerror(errno));
1.1 djm 185: else
186: fatal("chmod(%.100s, 0%o) failed: %.100s",
1.12 avsm 187: tty, (u_int)mode, strerror(errno));
1.1 djm 188: }
189: }
190: }