Convert to keyserv, telnetd and telnet to libcrypto's BIGNUM
[dragonfly.git] / crypto / openssh-3.9p1 / sshpty.c
1 /*
2  * Author: Tatu Ylonen <ylo@cs.hut.fi>
3  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4  *                    All rights reserved
5  * Allocating a pseudo-terminal, and making it the controlling tty.
6  *
7  * As far as I am concerned, the code I have written for this software
8  * can be used freely for any purpose.  Any derived versions of this
9  * software must be clearly marked as such, and if the derived work is
10  * incompatible with the protocol description in the RFC file, it must be
11  * called by a name other than "ssh" or "Secure Shell".
12  */
13
14 #include "includes.h"
15 RCSID("$OpenBSD: sshpty.c,v 1.12 2004/06/21 17:36:31 avsm Exp $");
16
17 #ifdef HAVE_UTIL_H
18 # include <util.h>
19 #endif /* HAVE_UTIL_H */
20
21 #include "sshpty.h"
22 #include "log.h"
23 #include "misc.h"
24
25 #ifdef HAVE_PTY_H
26 # include <pty.h>
27 #endif
28
29 #ifndef O_NOCTTY
30 #define O_NOCTTY 0
31 #endif
32
33 /*
34  * Allocates and opens a pty.  Returns 0 if no pty could be allocated, or
35  * nonzero if a pty was successfully allocated.  On success, open file
36  * descriptors for the pty and tty sides and the name of the tty side are
37  * returned (the buffer must be able to hold at least 64 characters).
38  */
39
40 int
41 pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
42 {
43         /* openpty(3) exists in OSF/1 and some other os'es */
44         char *name;
45         int i;
46
47         i = openpty(ptyfd, ttyfd, NULL, NULL, NULL);
48         if (i < 0) {
49                 error("openpty: %.100s", strerror(errno));
50                 return 0;
51         }
52         name = ttyname(*ttyfd);
53         if (!name)
54                 fatal("openpty returns device for which ttyname fails.");
55
56         strlcpy(namebuf, name, namebuflen);     /* possible truncation */
57         return 1;
58 }
59
60 /* Releases the tty.  Its ownership is returned to root, and permissions to 0666. */
61
62 void
63 pty_release(const char *tty)
64 {
65         if (chown(tty, (uid_t) 0, (gid_t) 0) < 0)
66                 error("chown %.100s 0 0 failed: %.100s", tty, strerror(errno));
67         if (chmod(tty, (mode_t) 0666) < 0)
68                 error("chmod %.100s 0666 failed: %.100s", tty, strerror(errno));
69 }
70
71 /* Makes the tty the process's controlling tty and sets it to sane modes. */
72
73 void
74 pty_make_controlling_tty(int *ttyfd, const char *tty)
75 {
76         int fd;
77 #ifdef USE_VHANGUP
78         void *old;
79 #endif /* USE_VHANGUP */
80
81 #ifdef _UNICOS
82         if (setsid() < 0)
83                 error("setsid: %.100s", strerror(errno));
84
85         fd = open(tty, O_RDWR|O_NOCTTY);
86         if (fd != -1) {
87                 signal(SIGHUP, SIG_IGN);
88                 ioctl(fd, TCVHUP, (char *)NULL);
89                 signal(SIGHUP, SIG_DFL);
90                 setpgid(0, 0);
91                 close(fd);
92         } else {
93                 error("Failed to disconnect from controlling tty.");
94         }
95
96         debug("Setting controlling tty using TCSETCTTY.");
97         ioctl(*ttyfd, TCSETCTTY, NULL);
98         fd = open("/dev/tty", O_RDWR);
99         if (fd < 0)
100                 error("%.100s: %.100s", tty, strerror(errno));
101         close(*ttyfd);
102         *ttyfd = fd;
103 #else /* _UNICOS */
104
105         /* First disconnect from the old controlling tty. */
106 #ifdef TIOCNOTTY
107         fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
108         if (fd >= 0) {
109                 (void) ioctl(fd, TIOCNOTTY, NULL);
110                 close(fd);
111         }
112 #endif /* TIOCNOTTY */
113         if (setsid() < 0)
114                 error("setsid: %.100s", strerror(errno));
115
116         /*
117          * Verify that we are successfully disconnected from the controlling
118          * tty.
119          */
120         fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
121         if (fd >= 0) {
122                 error("Failed to disconnect from controlling tty.");
123                 close(fd);
124         }
125         /* Make it our controlling tty. */
126 #ifdef TIOCSCTTY
127         debug("Setting controlling tty using TIOCSCTTY.");
128         if (ioctl(*ttyfd, TIOCSCTTY, NULL) < 0)
129                 error("ioctl(TIOCSCTTY): %.100s", strerror(errno));
130 #endif /* TIOCSCTTY */
131 #ifdef HAVE_NEWS4
132         if (setpgrp(0,0) < 0)
133                 error("SETPGRP %s",strerror(errno));
134 #endif /* HAVE_NEWS4 */
135 #ifdef USE_VHANGUP
136         old = signal(SIGHUP, SIG_IGN);
137         vhangup();
138         signal(SIGHUP, old);
139 #endif /* USE_VHANGUP */
140         fd = open(tty, O_RDWR);
141         if (fd < 0) {
142                 error("%.100s: %.100s", tty, strerror(errno));
143         } else {
144 #ifdef USE_VHANGUP
145                 close(*ttyfd);
146                 *ttyfd = fd;
147 #else /* USE_VHANGUP */
148                 close(fd);
149 #endif /* USE_VHANGUP */
150         }
151         /* Verify that we now have a controlling tty. */
152         fd = open(_PATH_TTY, O_WRONLY);
153         if (fd < 0)
154                 error("open /dev/tty failed - could not set controlling tty: %.100s",
155                     strerror(errno));
156         else
157                 close(fd);
158 #endif /* _UNICOS */
159 }
160
161 /* Changes the window size associated with the pty. */
162
163 void
164 pty_change_window_size(int ptyfd, int row, int col,
165         int xpixel, int ypixel)
166 {
167         struct winsize w;
168
169         w.ws_row = row;
170         w.ws_col = col;
171         w.ws_xpixel = xpixel;
172         w.ws_ypixel = ypixel;
173         (void) ioctl(ptyfd, TIOCSWINSZ, &w);
174 }
175
176 void
177 pty_setowner(struct passwd *pw, const char *tty)
178 {
179         struct group *grp;
180         gid_t gid;
181         mode_t mode;
182         struct stat st;
183
184         /* Determine the group to make the owner of the tty. */
185         grp = getgrnam("tty");
186         if (grp) {
187                 gid = grp->gr_gid;
188                 mode = S_IRUSR | S_IWUSR | S_IWGRP;
189         } else {
190                 gid = pw->pw_gid;
191                 mode = S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH;
192         }
193
194         /*
195          * Change owner and mode of the tty as required.
196          * Warn but continue if filesystem is read-only and the uids match/
197          * tty is owned by root.
198          */
199         if (stat(tty, &st))
200                 fatal("stat(%.100s) failed: %.100s", tty,
201                     strerror(errno));
202
203         if (st.st_uid != pw->pw_uid || st.st_gid != gid) {
204                 if (chown(tty, pw->pw_uid, gid) < 0) {
205                         if (errno == EROFS &&
206                             (st.st_uid == pw->pw_uid || st.st_uid == 0))
207                                 debug("chown(%.100s, %u, %u) failed: %.100s",
208                                     tty, (u_int)pw->pw_uid, (u_int)gid,
209                                     strerror(errno));
210                         else
211                                 fatal("chown(%.100s, %u, %u) failed: %.100s",
212                                     tty, (u_int)pw->pw_uid, (u_int)gid,
213                                     strerror(errno));
214                 }
215         }
216
217         if ((st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != mode) {
218                 if (chmod(tty, mode) < 0) {
219                         if (errno == EROFS &&
220                             (st.st_mode & (S_IRGRP | S_IROTH)) == 0)
221                                 debug("chmod(%.100s, 0%o) failed: %.100s",
222                                     tty, (u_int)mode, strerror(errno));
223                         else
224                                 fatal("chmod(%.100s, 0%o) failed: %.100s",
225                                     tty, (u_int)mode, strerror(errno));
226                 }
227         }
228 }