summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>1999-10-27 13:42:43 +1000
committerDamien Miller <djm@mindrot.org>1999-10-27 13:42:43 +1000
commitd4a8b7e34dd619a4debf9a206c81db26d1402ea6 (patch)
treea47d770a2f790f40d18b0982d4e55fa7cfb1fa3b
Initial revision
-rw-r--r--COPYING.Ylonen70
-rw-r--r--ChangeLog578
-rw-r--r--ChangeLog.linux20
-rw-r--r--Makefile13
-rw-r--r--Makefile.GNU50
-rw-r--r--Makefile.inc11
-rw-r--r--OVERVIEW164
-rw-r--r--README563
-rw-r--r--README.openssh44
-rw-r--r--RFC.nroff1780
-rw-r--r--auth-krb4.c209
-rw-r--r--auth-passwd.c209
-rw-r--r--auth-rh-rsa.c83
-rw-r--r--auth-rhosts.c298
-rw-r--r--auth-rsa.c478
-rw-r--r--auth-skey.c149
-rw-r--r--authfd.c565
-rw-r--r--authfd.h102
-rw-r--r--authfile.c350
-rw-r--r--bufaux.c141
-rw-r--r--bufaux.h51
-rw-r--r--buffer.c150
-rw-r--r--buffer.h66
-rw-r--r--canohost.c234
-rw-r--r--channels.c1500
-rw-r--r--channels.h41
-rw-r--r--cipher.c304
-rw-r--r--cipher.h84
-rw-r--r--clientloop.c924
-rw-r--r--compat.c10
-rw-r--r--compat.h7
-rw-r--r--compress.c160
-rw-r--r--compress.h46
-rw-r--r--crc32.c120
-rw-r--r--crc32.h25
-rw-r--r--deattack.c180
-rw-r--r--deattack.h27
-rw-r--r--getput.h64
-rw-r--r--helper.c108
-rw-r--r--helper.h43
-rw-r--r--hostfile.c279
-rw-r--r--includes.h78
-rw-r--r--log-client.c138
-rw-r--r--log-server.c233
-rw-r--r--login.c118
-rw-r--r--match.c78
-rw-r--r--mktemp.c181
-rw-r--r--mktemp.h7
-rw-r--r--mpaux.c46
-rw-r--r--mpaux.h32
-rw-r--r--nchan.c187
-rw-r--r--nchan.h57
-rw-r--r--nchan.ms71
-rw-r--r--openssh.spec105
-rw-r--r--packet.c762
-rw-r--r--packet.h166
-rw-r--r--pty.c264
-rw-r--r--pty.h40
-rw-r--r--radix.c258
-rw-r--r--rc4.c105
-rw-r--r--rc4.h110
-rw-r--r--readconf.c684
-rw-r--r--readconf.h116
-rw-r--r--readpass.c114
-rw-r--r--rsa.c164
-rw-r--r--rsa.h36
-rw-r--r--scp.1110
-rw-r--r--scp.c1220
-rw-r--r--servconf.c567
-rw-r--r--servconf.h86
-rw-r--r--serverloop.c644
-rw-r--r--ssh-add.1116
-rw-r--r--ssh-add.c254
-rw-r--r--ssh-agent.1124
-rw-r--r--ssh-agent.c572
-rw-r--r--ssh-keygen.1155
-rw-r--r--ssh-keygen.c552
-rw-r--r--ssh.1966
-rw-r--r--ssh.c809
-rw-r--r--ssh.h589
-rw-r--r--ssh.pam7
-rw-r--r--ssh_config30
-rw-r--r--sshconnect.c1495
-rw-r--r--sshd.8781
-rw-r--r--sshd.c2445
-rwxr-xr-xsshd.init49
-rw-r--r--sshd_config44
-rw-r--r--strlcpy.c68
-rw-r--r--strlcpy.h4
-rw-r--r--tildexpand.c70
-rw-r--r--ttymodes.c359
-rw-r--r--ttymodes.h138
-rw-r--r--uidswap.c95
-rw-r--r--uidswap.h30
-rw-r--r--version.h1
-rw-r--r--xmalloc.c56
-rw-r--r--xmalloc.h34
97 files changed, 26920 insertions, 0 deletions
diff --git a/COPYING.Ylonen b/COPYING.Ylonen
new file mode 100644
index 000000000..5e681edd2
--- /dev/null
+++ b/COPYING.Ylonen
@@ -0,0 +1,70 @@
1This file is part of the ssh software, Copyright (c) 1995 Tatu Ylonen, Finland
2
3
4COPYING POLICY AND OTHER LEGAL ISSUES
5
6As far as I am concerned, the code I have written for this software
7can be used freely for any purpose. Any derived versions of this
8software must be clearly marked as such, and if the derived work is
9incompatible with the protocol description in the RFC file, it must be
10called by a name other than "ssh" or "Secure Shell".
11
12However, I am not implying to give any licenses to any patents or
13copyrights held by third parties, and the software includes parts that
14are not under my direct control. As far as I know, all included
15source code is used in accordance with the relevant license agreements
16and can be used freely for any purpose (the GNU license being the most
17restrictive); see below for details.
18
19[ RSA is no longer included. ]
20[ IDEA is no longer included. ]
21[ DES is now external. ]
22[ GMP is now external. No more GNU licence. ]
23[ Zlib is now external. ]
24[ The make-ssh-known-hosts script is no longer included. ]
25[ TSS has been removed. ]
26[ MD5 is now external. ]
27[ RC4 support has been removed. ]
28[ Blowfish is now external. ]
29
30The 32-bit CRC implementation in crc32.c is due to Gary S. Brown.
31Comments in the file indicate it may be used for any purpose without
32restrictions.
33
34The 32-bit CRC compensation attack detector in deattack.c was
35contributed by CORE SDI S.A. under a BSD-style license. See
36http://www.core-sdi.com/english/ssh/ for details.
37
38Note that any information and cryptographic algorithms used in this
39software are publicly available on the Internet and at any major
40bookstore, scientific library, and patent office worldwide. More
41information can be found e.g. at "http://www.cs.hut.fi/crypto".
42
43The legal status of this program is some combination of all these
44permissions and restrictions. Use only at your own responsibility.
45You will be responsible for any legal consequences yourself; I am not
46making any claims whether possessing or using this is legal or not in
47your country, and I am not taking any responsibility on your behalf.
48
49
50 NO WARRANTY
51
52BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
53FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
54OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
55PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
56OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
57MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
58TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
59PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
60REPAIR OR CORRECTION.
61
62IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
63WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
64REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
65INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
66OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
67TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
68YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
69PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
70POSSIBILITY OF SUCH DAMAGES.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 000000000..08d90f78d
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,578 @@
1Fri Nov 17 16:19:20 1995 Tatu Ylonen <ylo@trance.olari.clinet.fi>
2
3 * Released 1.2.12.
4
5 * channels.c: Commented out debugging messages about output draining.
6
7 * Added file OVERVIEW to give some idea about the structure of the
8 ssh software.
9
10Thu Nov 16 16:40:17 1995 Tatu Ylonen <ylo@trance.olari.clinet.fi>
11
12 * canohost.c (get_remote_hostname): Don't ever return NULL (causes
13 segmentation violation).
14
15 * sshconnect.c: Host ip address printed incorrectly with -v.
16
17 * Implemented SSH_TTY environment variable.
18
19Wed Nov 15 01:47:40 1995 Tatu Ylonen <ylo@trance.olari.clinet.fi>
20
21 * Implemented server and client option KeepAlive to specify
22 whether to set SO_KEEPALIVE. Both default to "yes"; to disable
23 keepalives, set the value to "no" in both the server and the
24 client configuration files. Updated manual pages.
25
26 * sshd.c: Fixed Solaris utmp problem: wrong pid stored in utmp
27 (patch from Petri Virkkula <argon@bat.cs.hut.fi>).
28
29 * login.c (record_logout): Fixed removing user from utmp on BSD
30 (with HAVE_LIBUTIL_LOGIN).
31
32 * Added cleanup functions to be called from fatal(). Arranged for
33 utmp to be cleaned if sshd terminates by calling fatal (e.g.,
34 after dropping connection). Eliminated separate client-side
35 fatal() functions and moved fatal() to log-client.c. Made all
36 cleanups, including channel_stop_listening() and packet_close()
37 be called using this mechanism.
38
39Thu Nov 9 09:58:05 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
40
41 * sshd.c: Permit immediate login with empty password only if
42 password authentication is allowed.
43
44Wed Nov 8 00:43:55 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
45
46 * Eliminated unix-domain X11 forwarding. Inet-domain forwarding is
47 now the only supported form. Renamed server option
48 X11InetForwarding to X11Forwarding, and eliminated
49 X11UnixForwarding. Updated documentation. Updated RFC (marked
50 the SSH_CMSG_X11_REQUEST_FORWARDING message (code 26) as
51 obsolete, and removed all references to it). Increased protocol
52 version number to 1.3.
53
54 * scp.c (main): Added -B (BatchMode). Updated manual page.
55
56 * Cleaned up and updated all manual pages.
57
58 * clientloop.c: Added new escape sequences ~# (lists forwarded
59 connections), ~& (background ssh when waiting for forwarded
60 connections to terminate), ~? (list available escapes).
61 Polished the output of the connection listing. Updated
62 documentation.
63
64 * uidswap.c: If _POSIX_SAVED_IDS is defined, don't change the real
65 uid. Assume that _POSIX_SAVED_IDS also applies to seteuid.
66 This may solve problems with tcp_wrappers (libwrap) showing
67 connections as coming from root.
68
69Tue Nov 7 20:28:57 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
70
71 * Added RandomSeed server configuration option. The argument
72 specifies the location of the random seed file. Updated
73 documentation.
74
75 * Locate perl5 in configure. Generate make-ssh-known-hosts (with
76 the correct path for perl5) in Makefile.in, and install it with
77 the other programs. Updated manual page.
78
79 * sshd.c (main): Added a call to umask to set the umask to a
80 reasonable value.
81
82 * compress.c (buffer_compress): Fixed to follow the zlib
83 documentation (which is slightly confusing).
84
85 * INSTALL: Added information about Linux libc.so.4 problem.
86
87Mon Nov 6 15:42:36 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
88
89 * (Actually autoconf fix) Installed patch to AC_ARG_PROGRAM.
90
91 * sshd.c, sshd.8.in: Renamed $HOME/.environment ->
92 $HOME/.ssh/environment.
93
94 * configure.in: Disable shadow password checking on convex.
95 Convex has /etc/shadow, but sets pw_passwd automatically if
96 running as root.
97
98 * Eliminated HAVE_ETC_MASTER_PASSWD (NetBSD, FreeBSD); the
99 pw_passwd field is automatically filled if running as root.
100 Put explicit code in configure.in to prevent shadow password
101 checking on FreeBSD and NetBSD.
102
103 * serverloop.c (signchld_handler): Don't print error if wait
104 returns -1.
105
106 * Makefile.in (install): Fixed modes of data files.
107
108 * Makefile.in (install): Make links for slogin.1.
109
110 * make-ssh-known-hosts: Merged a patch from melo@ci.uminho.pt to
111 fix the ping command.
112
113Fri Nov 3 16:25:28 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
114
115 * ssh.1.in: Added more information about X11 forwarding.
116
117Thu Nov 2 18:42:13 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
118
119 * Changes to use O_NONBLOCK_BROKEN consistently.
120
121 * pty.c (pty_make_controlling_tty): Use setpgid instead of
122 setsid() on Ultrix.
123
124 * includes.h: Removed redundant #undefs for Ultrix and Sony News;
125 these are already handled in configure.in.
126
127Tue Oct 31 13:31:28 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
128
129 * configure.in: Define SSH_WTMP to /var/adm/wtmp is wtmp not found.
130
131 * configure.in: Disable vhangup on Ultrix. I am told this fixes
132 the server problems.
133
134Sat Oct 28 14:22:05 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
135
136 * sshconnect.c: Fixed a bug in connecting to a multi-homed host.
137 Restructured the connecting code to never try to use the same
138 socket a second time after a failed connection.
139
140 * Makefile.in: Added explicit -m option to install, and umask 022
141 when creating directories and the host key.
142
143Fri Oct 27 01:05:10 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
144
145 * Makefile.in: Added cleaning of $(ZLIBDIR) to clean and distclean.
146
147 * login.c (get_last_login_time): Fixed a typo (define -> defined).
148
149Thu Oct 26 01:28:07 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
150
151 * configure.in: Moved testing for ANSI C compiler after the host
152 specific code (problems on HPUX).
153
154 * Minor fixes to /etc/default/login stuff from Bryan O'Sullivan.
155
156 * Fixed .SH NAME sections in manual pages.
157
158 * compress.c: Trying to fix a mysterious bug in the compression
159 glue.
160
161 * ssh-1.2.11.
162
163 * scp.c: disable agent forwarding when running ssh from scp.
164
165 * Added compression of plaintext packets using the gzip library
166 (zlib). Client configuration options Compression and
167 CompressionLevel (1-9 as in gzip). New ssh and scp option -C
168 (to enable compression). Updated RFC.
169
170Wed Oct 25 05:11:55 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
171
172 * Implemented ProxyCommand stuff based on patches from Bryan
173 O'Sullivan <bos@serpentine.com>.
174
175 * Merged BSD login/logout/lastlog patches from Mark Treacy
176 <mark@labtam.oz.au>.
177
178 * sshd.c: Added chdir("/").
179
180Tue Oct 24 00:29:01 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
181
182 * Merged RSA environment= patches from Felix Leitner
183 <leitner@prz.tu-berlin.de> with some changes.
184
185 * sshd.c: Made the packet code use two separate descriptors for
186 the connection (one for input, the other for output). This will
187 make future extensions easier (e.g., non-socket transports, etc.).
188 sshd -i now uses both stdin and stdout separately.
189
190Mon Oct 23 21:29:28 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
191
192 * sshd.c: Merged execle -> execve patches from Mark Martinec
193 <Mark.Martinec@nsc.ijs.si>. This may help with execle bugs on
194 Convex (environment not getting passed properly). This might
195 also solve similar problems on Sonys; please test!
196
197 * Removed all compatibility code for protocol version 1.0.
198 THIS MEANS THAT WE ARE NO LONGER COMPATIBLE WITH SSH VERSIONS
199 PRIOR TO 1.1.0.
200
201 * randoms.c (random_acquire_light_environmental_noise): If
202 /dev/random is available, read up to 32 bytes (256 bits) from
203 there in non-blocking mode, and mix the new random bytes into
204 the pool.
205
206 * Added client configuration option StrictHostKeyChecking
207 (disabled by default). If this is enabled, the client will not
208 automatically add new host keys to $HOME/.ssh/known_hosts;
209 instead the connection will be refused if the host key is not
210 known. Similarly, if the host key has changed, the connection
211 will be refused instead if just issuing a warning. This
212 provides additional security against man-in-the-middle/trojan
213 horse attacks (especially in scripts where there is no-one to
214 see the warnings), but may be quite inconvenient in everyday
215 interactive use unless /etc/ssh_known_hosts is very complete,
216 because new host keys must now be added manually.
217
218 * sshconnect.c (ssh_connect): Use the user's uid when creating the
219 socket and connecting it. I am hoping that this might help with
220 tcp_wrappers showing the remote user as root.
221
222 * ssh.c: Try inet-domain X11 forwarding regardless of whether we
223 can get local authorization information. If we don't, we just
224 come up with fake information; the forwarding code will anyway
225 generate its own fake information and validate that the client
226 knows that information. It will then substitute our fake
227 information for that, but that info should get ignored by the
228 server if it doesn't support it.
229
230 * Added option BatchMode to disable password/passphrase querying
231 in scripts.
232
233 * auth-rh-rsa.c: Changed to use uid-swapping when reading
234 .ssh/known_hosts.
235
236 * sshd.8.in (command): Improved documentation of file permissions
237 on the manual pages.
238
239Thu Oct 19 21:05:51 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
240
241 * ssh-add.c (add_file): Fixed a bug causing ssh to sometimes refer
242 to freed memory (comment -> saved_comment).
243
244 * log-server.c: Added a prefix to debug/warning/error/fatal
245 messages describing message types. Syslog does not include that
246 information automatically.
247
248Sun Oct 8 01:56:01 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
249
250 * Merged /etc/default/login and MAIL environment variable changes
251 from Bryan O'Sullivan <bos@serpentine.com>.
252 - mail spool file location
253 - process /etc/default/login
254 - add HAVE_ETC_DEFAULT_LOGIN
255 - new function child_get_env and read_etc_default_login (sshd.c)
256
257 * ssh-add.c (add_file): Fixed asking for passphrase.
258
259 * Makefile.in: Fixed installing configure-generated man pages when
260 compiling in a separate object directory.
261
262 * sshd.c (main): Moved RSA key generation until after allocating
263 the port number. (Actually, the code got duplicated because we
264 never listen when run from inetd.)
265
266 * ssh.c: Fixed a problem that caused scp to hang when called with
267 stdin closed.
268
269Sat Oct 7 03:08:06 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
270
271 * Added server config option StrictModes. It specifies whether to
272 check ownership and modes of home directory and .rhosts files.
273
274 * ssh.c: If ssh is renamed/linked to a host name, connect to that
275 host.
276
277 * serverloop.c, clientloop.c: Ignore EAGAIN reported on read from
278 connection. Solaris has a kernel bug which causes select() to
279 sometimes wake up even though there is no data available.
280
281 * Display all open connections when printing the "Waiting for
282 forwarded connections to terminate" message.
283
284 * sshd.c, readconf.c: Added X11InetForwarding and
285 X11UnixForwarding server config options.
286
287Thu Oct 5 17:41:16 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
288
289 * Some more SCO fixes.
290
291Tue Oct 3 01:04:34 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
292
293 * Fixes and cleanups in README, INSTALL, COPYING.
294
295Mon Oct 2 03:36:08 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
296
297 * ssh-add.c (add_file): Fixed a bug in ssh-add (xfree: NULL ...).
298
299 * Removed .BR from ".SH NAME" in man pages.
300
301Sun Oct 1 04:16:07 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
302
303 * ssh-1.2.10.
304
305 * configure.in: When checking that the compiler works, check that
306 it understands ANSI C prototypes.
307
308 * Made uidswap error message a debug() to avoid confusing errors
309 on AIX (AIX geteuid is brain-damaged and fails even for root).
310
311 * Fixed an error in sshd.8 (FacistLogging -> FascistLogging).
312
313 * Fixed distribution in Makefile.in (missing manual page .in files).
314
315Sat Sep 30 17:38:46 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
316
317 * auth-rhosts.c: Fixed serious security problem in
318 /etc/hosts.equiv authentication.
319
320Fri Sep 29 00:41:02 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
321
322 * Include machine/endian.h on Paragon.
323
324 * ssh-add.c (add_file): Made ssh-add keep asking for the
325 passphrase until the user just types return or cancels.
326 Make the dialog display the comment of the key.
327
328 * Read use shosts.equiv in addition to /etc/hosts.equiv.
329
330 * sshd.8 is now sshd.8.in and is processed by configure to
331 substitute the proper paths for various files. Ditto for ssh.1.
332 Ditto for make-ssh-known-hosts.1.
333
334 * configure.in: Moved /etc/sshd_pid to PIDDIR/sshd.pid. PIDDIR
335 will be /var/run if it exists, and ETCDIR otherwise.
336
337Thu Sep 28 21:52:42 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
338
339 * On Ultrix, check if sys/syslog.h needs to be included in
340 addition to syslog.h.
341
342 * make-ssh-known-hosts.pl: Merged Kivinen's fixes for HPUX.
343
344 * configure.in: Put -lwrap, -lsocks, etc. at the head of LIBS.
345
346 * Fixed case-insensitivity in auth-rhosts.c.
347
348 * Added missing socketpair.c to EXTRA_SRCS (needed on SCO), plus
349 other SCO fixes.
350
351 * Makefile.in: Fixed missing install_prefixes.
352
353Wed Sep 27 03:57:00 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
354
355 * ssh-1.2.9.
356
357 * Added SOCKS support.
358
359 * Fixed default setting of IgnoreRhosts option.
360
361 * Pass the magic cookie to xauth in stdin instead of command line;
362 the command line is visible in ps.
363
364 * Added processing $HOME/.ssh/rc and /etc/sshrc.
365
366 * Added a section to sshd.8 on what happens at login time.
367
368Tue Sep 26 01:27:40 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
369
370 * Don't define speed_t on SunOS 4.1.1; it conflicts with system
371 headers.
372
373 * Added support for .hushlogin.
374
375 * Added --with-etcdir.
376
377 * Read $HOME/.environment after /etc/environment.
378
379Mon Sep 25 03:26:06 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
380
381 * Merged patches for SCO Unix (from Michael Henits).
382
383Sun Sep 24 22:28:02 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
384
385 * Added ssh option ConnectionAttempts.
386
387Sat Sep 23 12:30:15 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
388
389 * sshd.c: Don't print last login time and /etc/motd if a command
390 has been specified (with ssh -t host command).
391
392 * Added support for passing the screen number in X11 forwarding.
393 It is implemented as a compatible protocol extension, signalled
394 by SSH_PROTOFLAG_SCREEN_NUMBER by the child.
395
396 * clientloop.c: Fixed bugs in the order in which things were
397 processed. This may solve problems with some data not getting
398 sent to the server as soon as possible (probably solves the TCP
399 forwarding delayed close problem). Also, it looked like window
400 changes might not get transmitted as early as possible in some
401 cases.
402
403 * clientloop.c: Changed to detect window size change that
404 happened while ssh was suspended.
405
406 * ssh.c: Moved the do_session function (client main loop) to
407 clientloop.c. Divided it into smaller functions. General cleanup.
408
409 * ssh-1.2.8
410
411Fri Sep 22 22:07:46 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
412
413 * sshconnect.c (ssh_login): Made ssh_login take the options
414 structure as argument, instead of the individual arguments.
415
416 * auth-rhosts.c (check_rhosts_file): Added support for netgroups.
417
418 * auth-rhosts.c (check_rhosts_file): Added support for negated
419 entries.
420
421Thu Sep 21 00:07:56 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
422
423 * auth-rhosts.c: Restructured rhosts authentication code.
424 Hosts.equiv now has same format as .rhosts: user names are allowed.
425
426 * Added support for the Intel Paragon.
427
428 * sshd.c: Don't use X11 forwarding with spoofing if no xauth
429 program. Changed configure.in to not define XAUTH_PATH if
430 there is no xauth program.
431
432 * ssh-1.2.7
433
434 * sshd.c: Rewrote the code to build the environment. Now also reads
435 /etc/environment.
436
437 * sshd.c: Fixed problems in libwrap code. --with-libwrap now
438 takes optional library name/path.
439
440 * ssh-1.2.6
441
442 * Define USE_PIPES by default.
443
444 * Added support for Univel Unixware and MachTen.
445
446 * Added IgnoreRhosts server option.
447
448 * Added USE_STRLEN_FOR_AF_UNIX; it is needed at least on MachTen.
449
450Wed Sep 20 02:41:02 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
451
452 * sshd.c (do_child): don't call packet_close when /etc/nologin,
453 because packet_close does shutdown, and the message does not get
454 sent.
455
456 * pty.c (pty_allocate): Push ttcompat streams module.
457
458 * randoms.c (random_acquire_light_environmental_noise): Don't use
459 the second argument to gettimeofday as it is not supported on
460 all systems.
461
462 * login.c (record_login): Added NULL second argument to gettimeofday.
463
464Tue Sep 19 13:25:48 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
465
466 * fixed pclose wait() in sshd key regeneration (now only collects
467 easily available noise).
468
469 * configure.in: test for bsdi before bsd*.
470
471 * ssh.c: Don't print "Connection closed" if -q.
472
473Wed Sep 13 04:19:52 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
474
475 * Released ssh-1.2.5.
476
477 * Hopefully fixed "Waiting for forwarded connections to terminate"
478 message.
479
480 * randoms.c, md5.c: Large modifications to make these work on Cray
481 (which has no 32 bit integer type).
482
483 * Fixed a problem with forwarded connection closes not being
484 reported immediately.
485
486 * ssh.c: fixed rhosts authentication (broken by uid-swapping).
487
488 * scp.c: Don't use -l if server user not specified (it made
489 setting User in the configuration file not work).
490
491 * configure.in: don't use -pipe on BSDI.
492
493 * randoms.c: Major modifications to make it work without 32 bit
494 integers (e.g. Cray).
495
496 * md5.c: Major modifications to make it work without 32 bit
497 integers (e.g. Cray).
498
499 * Eliminated HPSUX_BROKEN_PTYS. The code is now enabled by
500 default on all systems.
501
502Mon Sep 11 00:53:12 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
503
504 * sshd.c: don't include sshd pathname in log messages.
505
506 * Added libwrap stuff (includes support for identd).
507
508 * Added OSF/1 C2 extended security stuff.
509
510 * Fixed interactions between getuid() and uid-swap stuff.
511
512Sun Sep 10 00:29:27 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
513
514 * serverloop.c: Don't send stdout data to client until after a few
515 milliseconds if there is very little data. This is because some
516 systems give data from pty one character at a time, which would
517 multiply data size by about 16.
518
519 * serverloop.c: Moved server do_session to a separate file and
520 renamed it server_loop. Split it into several functions and
521 partially rewrote it. Fixed "cat /etc/termcap | ssh foo cat" hangup.
522
523 * Screwed up something while checking stuff in under cvs. No harm,
524 but bogus log entries...
525
526Sat Sep 9 02:24:51 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
527
528 * minfd.c (_get_permanent_fd): Use SHELL environment variable.
529
530 * channels.c (x11_create_display_inet): Created
531 HPSUX_NONSTANDARD_X11_KLUDGE; it causes DISPLAY to contain the
532 IP address of the host instead of the name, because HPSUX uses
533 some magic shared memory communication for local connections.
534
535 * Changed SIGHUP processing in server; it should now work multiple
536 times.
537
538 * Added length limits in many debug/log/error/fatal calls just in
539 case.
540
541 * login.c (get_last_login_time): Fixed location of lastlog.
542
543 * Rewrote all uid-swapping code. New files uidswap.h, uidswap.c.
544
545 * Fixed several security problems involving chmod and chgrp (race
546 conditions). Added warnings about dubious modes for /tmp/.X11-unix.
547
548Fri Sep 8 20:03:36 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
549
550 * Changed readconf.c to never display anything from the config
551 file. This should now be prevented otherwise, but let's play safe.
552
553 * log-server.c: Use %.500s in syslog() just to be sure (they
554 should already be shorter than 1024 though).
555
556 * sshd.c: Moved setuid in child a little earlier (just to be
557 conservative, there was no security problem that I could detect).
558
559 * README, INSTALL: Added info about mailing list and WWW page.
560
561 * sshd.c: Added code to use SIGCHLD and wait zombies immediately.
562
563 * Merged patch to set ut_addr in utmp.
564
565 * Created ChangeLog and added it to Makefile.in.
566
567 * Use read_passphrase instead of getpass().
568
569 * Added SSH_FALLBACK_CIPHER. Fixed a bug in default cipher
570 selection (IDEA used to be selected even if not supported by the
571 server).
572
573 * Use no encryption for key files if empty passphrase.
574
575 * Added section about --without-idea in INSTALL.
576
577 * Version 1.2.0 was released a couple of days ago.
578
diff --git a/ChangeLog.linux b/ChangeLog.linux
new file mode 100644
index 000000000..a28e577ac
--- /dev/null
+++ b/ChangeLog.linux
@@ -0,0 +1,20 @@
119991027
2 - Adapted PAM patch.
3 - Released 1.0pre2
4
5 - Excised my buggy replacements for strlcpy and mkdtemp
6 - Imported correct OpenBSD strlcpy and mkdtemp routines.
7 - Reduced arc4random_stir entropy read to 32 bytes (256 bits)
8 - Picked up correct version number from OpenBSD
9 - Added sshd.pam PAM configuration file
10 - Added sshd.init Redhat init script
11 - Added openssh.spec RPM spec file
12 - Released 1.2pre3
13
1419991026
15 - Fixed include paths of OpenSSL functions
16 - Use OpenSSL MD5 routines
17 - Imported RC4 code from nanocrypt
18 - Wrote replacements for OpenBSD arc4random* functions
19 - Wrote replacements for strlcpy and mkdtemp
20 - Released 1.0pre1
diff --git a/Makefile b/Makefile
new file mode 100644
index 000000000..668900c3b
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,13 @@
1# $OpenBSD: Makefile,v 1.5 1999/10/25 20:27:26 markus Exp $
2
3.include <bsd.own.mk>
4
5SUBDIR= lib ssh sshd ssh-add ssh-keygen ssh-agent scp
6
7distribution:
8 install -C -o root -g wheel -m 0644 ${.CURDIR}/ssh_config \
9 ${DESTDIR}/etc/ssh_config
10 install -C -o root -g wheel -m 0644 ${.CURDIR}/sshd_config \
11 ${DESTDIR}/etc/sshd_config
12
13.include <bsd.subdir.mk>
diff --git a/Makefile.GNU b/Makefile.GNU
new file mode 100644
index 000000000..f36bdb3df
--- /dev/null
+++ b/Makefile.GNU
@@ -0,0 +1,50 @@
1OPT_FLAGS=-g
2CFLAGS=$(OPT_FLAGS) -Wall -DETCDIR=\"/etc/ssh\" -DHAVE_PAM
3TARGETS=bin/libssh.a bin/ssh bin/sshd bin/ssh-add bin/ssh-keygen bin/ssh-agent bin/scp
4LFLAGS=-L./bin
5LIBS=-lssh -lcrypto -lz -lutil -lpam -ldl
6AR=ar
7RANLIB=ranlib
8
9OBJS= authfd.o authfile.o auth-passwd.o auth-rhosts.o auth-rh-rsa.o \
10 auth-rsa.o bufaux.o buffer.o canohost.o channels.o cipher.o \
11 clientloop.o compress.o crc32.o deattack.o hostfile.o \
12 log-client.o login.o log-server.o match.o mpaux.o packet.o pty.o \
13 readconf.o readpass.o rsa.o servconf.o serverloop.o \
14 sshconnect.o tildexpand.o ttymodes.o uidswap.o xmalloc.o \
15 helper.o mktemp.o strlcpy.o rc4.o
16
17all: $(OBJS) $(TARGETS)
18
19bin/libssh.a: authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o hostfile.o match.o mpaux.o nchan.o packet.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o xmalloc.o helper.o rc4.o mktemp.o strlcpy.o
20 [ -d bin ] || mkdir bin
21 $(AR) rv $@ $^
22 $(RANLIB) $@
23
24bin/ssh: ssh.o sshconnect.o log-client.o readconf.o clientloop.o
25 [ -d bin ] || mkdir bin
26 $(CC) -o $@ $^ $(LFLAGS) $(LIBS)
27
28bin/sshd: sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o pty.o log-server.o login.o servconf.o serverloop.o
29 [ -d bin ] || mkdir bin
30 $(CC) -o $@ $^ $(LFLAGS) $(LIBS)
31
32bin/scp: scp.o
33 [ -d bin ] || mkdir bin
34 $(CC) -o $@ $^ $(LFLAGS) $(LIBS)
35
36bin/ssh-add: ssh-add.o log-client.o
37 [ -d bin ] || mkdir bin
38 $(CC) -o $@ $^ $(LFLAGS) $(LIBS)
39
40bin/ssh-agent: ssh-agent.o log-client.o
41 [ -d bin ] || mkdir bin
42 $(CC) -o $@ $^ $(LFLAGS) $(LIBS)
43
44bin/ssh-keygen: ssh-keygen.o log-client.o
45 [ -d bin ] || mkdir bin
46 $(CC) -o $@ $^ $(LFLAGS) $(LIBS)
47
48clean:
49 rm -f *.o core bin/*
50
diff --git a/Makefile.inc b/Makefile.inc
new file mode 100644
index 000000000..fddf3da2f
--- /dev/null
+++ b/Makefile.inc
@@ -0,0 +1,11 @@
1CFLAGS+= -I${.CURDIR}/..
2
3.include <bsd.obj.mk>
4
5.if exists(${.CURDIR}/../lib/${__objdir})
6LDADD+= -L${.CURDIR}/../lib/${__objdir} -lssh
7DPADD+= ${.CURDIR}/../lib/${__objdir}/libssh.a
8.else
9LDADD+= -L${.CURDIR}/../lib -lssh
10DPADD+= ${.CURDIR}/../lib/libssh.a
11.endif
diff --git a/OVERVIEW b/OVERVIEW
new file mode 100644
index 000000000..a8b67e4e2
--- /dev/null
+++ b/OVERVIEW
@@ -0,0 +1,164 @@
1This document is inteded for those who wish to read the ssh source
2code. This tries to give an overview of the structure of the code.
3
4Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>
5Updated 17 Nov 1995.
6Updated 19 Oct 1999 for OpenSSH-1.2
7
8The software consists of ssh (client), sshd (server), scp, sdist, and
9the auxiliary programs ssh-keygen, ssh-agent, ssh-add, and
10make-ssh-known-hosts. The main program for each of these is in a .c
11file with the same name.
12
13There are some subsystems/abstractions that are used by a number of
14these programs.
15
16 Buffer manipulation routines
17
18 - These provide an arbitrary size buffer, where data can be appended.
19 Data can be consumed from either end. The code is used heavily
20 throughout ssh. The basic buffer manipulation functions are in
21 buffer.c (header buffer.h), and additional code to manipulate specific
22 data types is in bufaux.c.
23
24 Compression Library
25
26 - Ssh uses the GNU GZIP compression library (ZLIB).
27
28 Encryption/Decryption
29
30 - Ssh contains several encryption algorithms. These are all
31 accessed through the cipher.h interface. The interface code is
32 in cipher.c, and the implementations are in libc.
33
34 Multiple Precision Integer Library
35
36 - Uses the SSLeay BIGNUM sublibrary.
37 - Some auxiliary functions for mp-int manipulation are in mpaux.c.
38
39 Random Numbers
40
41 - Uses arc4random() and such.
42
43 RSA key generation, encryption, decryption
44
45 - Ssh uses the RSA routines in libssl.
46
47 RSA key files
48
49 - RSA keys are stored in files with a special format. The code to
50 read/write these files is in authfile.c. The files are normally
51 encrypted with a passphrase. The functions to read passphrases
52 are in readpass.c (the same code is used to read passwords).
53
54 Binary packet protocol
55
56 - The ssh binary packet protocol is implemented in packet.c. The
57 code in packet.c does not concern itself with packet types or their
58 execution; it contains code to build packets, to receive them and
59 extract data from them, and the code to compress and/or encrypt
60 packets. CRC code comes from crc32.c.
61
62 - The code in packet.c calls the buffer manipulation routines
63 (buffer.c, bufaux.c), compression routines (compress.c, zlib),
64 and the encryption routines.
65
66 X11, TCP/IP, and Agent forwarding
67
68 - Code for various types of channel forwarding is in channels.c.
69 The file defines a generic framework for arbitrary communication
70 channels inside the secure channel, and uses this framework to
71 implement X11 forwarding, TCP/IP forwarding, and authentication
72 agent forwarding.
73 The new, Protocol 1.5, channel close implementation is in nchan.c
74
75 Authentication agent
76
77 - Code to communicate with the authentication agent is in authfd.c.
78
79 Authentication methods
80
81 - Code for various authentication methods resides in auth-*.c
82 (auth-passwd.c, auth-rh-rsa.c, auth-rhosts.c, auth-rsa.c). This
83 code is linked into the server. The routines also manipulate
84 known hosts files using code in hostfile.c. Code in canohost.c
85 is used to retrieve the canonical host name of the remote host.
86 Code in match.c is used to match host names.
87
88 - In the client end, authentication code is in sshconnect.c. It
89 reads Passwords/passphrases using code in readpass.c. It reads
90 RSA key files with authfile.c. It communicates the
91 authentication agent using authfd.c.
92
93 The ssh client
94
95 - The client main program is in ssh.c. It first parses arguments
96 and reads configuration (readconf.c), then calls ssh_connect (in
97 sshconnect.c) to open a connection to the server (possibly via a
98 proxy), and performs authentication (ssh_login in sshconnect.c).
99 It then makes any pty, forwarding, etc. requests. It may call
100 code in ttymodes.c to encode current tty modes. Finally it
101 calls client_loop in clientloop.c. This does the real work for
102 the session.
103
104 - The client is suid root. It tries to temporarily give up this
105 rights while reading the configuration data. The root
106 privileges are only used to make the connection (from a
107 privileged socket). Any extra privileges are dropped before
108 calling ssh_login.
109
110 Pseudo-tty manipulation and tty modes
111
112 - Code to allocate and use a pseudo tty is in pty.c. Code to
113 encode and set terminal modes is in ttymodes.c.
114
115 Logging in (updating utmp, lastlog, etc.)
116
117 - The code to do things that are done when a user logs in are in
118 login.c. This includes things such as updating the utmp, wtmp,
119 and lastlog files. Some of the code is in sshd.c.
120
121 Writing to the system log and terminal
122
123 - The programs use the functions fatal(), log(), debug(), error()
124 in many places to write messages to system log or user's
125 terminal. The implementation that logs to system log is in
126 log-server.c; it is used in the server program. The other
127 programs use an implementation that sends output to stderr; it
128 is in log-client.c. The definitions are in ssh.h.
129
130 The sshd server (daemon)
131
132 - The sshd daemon starts by processing arguments and reading the
133 configuration file (servconf.c). It then reads the host key,
134 starts listening for connections, and generates the server key.
135 The server key will be regenerated every hour by an alarm.
136
137 - When the server receives a connection, it forks, disables the
138 regeneration alarm, and starts communicating with the client.
139 They first perform identification string exchange, then
140 negotiate encryption, then perform authentication, preparatory
141 operations, and finally the server enters the normal session
142 mode by calling server_loop in serverloop.c. This does the real
143 work, calling functions in other modules.
144
145 - The code for the server is in sshd.c. It contains a lot of
146 stuff, including:
147 - server main program
148 - waiting for connections
149 - processing new connection
150 - authentication
151 - preparatory operations
152 - building up the execution environment for the user program
153 - starting the user program.
154
155 Auxiliary files
156
157 - There are several other files in the distribution that contain
158 various auxiliary routines:
159 ssh.h the main header file for ssh (various definitions)
160 getput.h byte-order independent storage of integers
161 includes.h includes most system headers. Lots of #ifdefs.
162 tildexpand.c expand tilde in file names
163 uidswap.c uid-swapping
164 xmalloc.c "safe" malloc routines
diff --git a/README b/README
new file mode 100644
index 000000000..ed3608441
--- /dev/null
+++ b/README
@@ -0,0 +1,563 @@
1Ssh (Secure Shell) is a program to log into another computer over a
2network, to execute commands in a remote machine, and to move files
3from one machine to another. It provides strong authentication and
4secure communications over insecure channels. It is inteded as a
5replacement for rlogin, rsh, rcp, and rdist.
6
7See the file INSTALL for installation instructions. See COPYING for
8license terms and other legal issues. See RFC for a description of
9the protocol. There is a WWW page for ssh; see http://www.cs.hut.fi/ssh.
10
11This file has been updated to match ssh-1.2.12.
12
13
14FEATURES
15
16 o Strong authentication. Closes several security holes (e.g., IP,
17 routing, and DNS spoofing). New authentication methods: .rhosts
18 together with RSA based host authentication, and pure RSA
19 authentication.
20
21 o Improved privacy. All communications are automatically and
22 transparently encrypted. RSA is used for key exchange, and a
23 conventional cipher (normally IDEA, DES, or triple-DES) for
24 encrypting the session. Encryption is started before
25 authentication, and no passwords or other information is
26 transmitted in the clear. Encryption is also used to protect
27 against spoofed packets.
28
29 o Secure X11 sessions. The program automatically sets DISPLAY on
30 the server machine, and forwards any X11 connections over the
31 secure channel. Fake Xauthority information is automatically
32 generated and forwarded to the remote machine; the local client
33 automatically examines incoming X11 connections and replaces the
34 fake authorization data with the real data (never telling the
35 remote machine the real information).
36
37 o Arbitrary TCP/IP ports can be redirected through the encrypted channel
38 in both directions (e.g., for e-cash transactions).
39
40 o No retraining needed for normal users; everything happens
41 automatically, and old .rhosts files will work with strong
42 authentication if administration installs host key files.
43
44 o Never trusts the network. Minimal trust on the remote side of
45 the connection. Minimal trust on domain name servers. Pure RSA
46 authentication never trusts anything but the private key.
47
48 o Client RSA-authenticates the server machine in the beginning of
49 every connection to prevent trojan horses (by routing or DNS
50 spoofing) and man-in-the-middle attacks, and the server
51 RSA-authenticates the client machine before accepting .rhosts or
52 /etc/hosts.equiv authentication (to prevent DNS, routing, or
53 IP-spoofing).
54
55 o Host authentication key distribution can be centrally by the
56 administration, automatically when the first connection is made
57 to a machine (the key obtained on the first connection will be
58 recorded and used for authentication in the future), or manually
59 by each user for his/her own use. The central and per-user host
60 key repositories are both used and complement each other. Host
61 keys can be generated centrally or automatically when the software
62 is installed. Host authentication keys are typically 1024 bits.
63
64 o Any user can create any number of user authentication RSA keys for
65 his/her own use. Each user has a file which lists the RSA public
66 keys for which proof of possession of the corresponding private
67 key is accepted as authentication. User authentication keys are
68 typically 1024 bits.
69
70 o The server program has its own server RSA key which is
71 automatically regenerated every hour. This key is never saved in
72 any file. Exchanged session keys are encrypted using both the
73 server key and the server host key. The purpose of the separate
74 server key is to make it impossible to decipher a captured session by
75 breaking into the server machine at a later time; one hour from
76 the connection even the server machine cannot decipher the session
77 key. The key regeneration interval is configurable. The server
78 key is normally 768 bits.
79
80 o An authentication agent, running in the user's laptop or local
81 workstation, can be used to hold the user's RSA authentication
82 keys. Ssh automatically forwards the connection to the
83 authentication agent over any connections, and there is no need to
84 store the RSA authentication keys on any machine in the network
85 (except the user's own local machine). The authentication
86 protocols never reveal the keys; they can only be used to verify
87 that the user's agent has a certain key. Eventually the agent
88 could rely on a smart card to perform all authentication
89 computations.
90
91 o The software can be installed and used (with restricted
92 functionality) even without root privileges.
93
94 o The client is customizable in system-wide and per-user
95 configuration files. Most aspects of the client's operation can
96 be configured. Different options can be specified on a per-host basis.
97
98 o Automatically executes conventional rsh (after displaying a
99 warning) if the server machine is not running sshd.
100
101 o Optional compression of all data with gzip (including forwarded X11
102 and TCP/IP port data), which may result in significant speedups on
103 slow connections.
104
105 o Complete replacement for rlogin, rsh, and rcp.
106
107
108WHY TO USE SECURE SHELL
109
110Currently, almost all communications in computer networks are done
111without encryption. As a consequence, anyone who has access to any
112machine connected to the network can listen in on any communication.
113This is being done by hackers, curious administrators, employers,
114criminals, industrial spies, and governments. Some networks leak off
115enough electromagnetic radiation that data may be captured even from a
116distance.
117
118When you log in, your password goes in the network in plain
119text. Thus, any listener can then use your account to do any evil he
120likes. Many incidents have been encountered worldwide where crackers
121have started programs on workstations without the owners knowledge
122just to listen to the network and collect passwords. Programs for
123doing this are available on the Internet, or can be built by a
124competent programmer in a few hours.
125
126Any information that you type or is printed on your screen can be
127monitored, recorded, and analyzed. For example, an intruder who has
128penetrated a host connected to a major network can start a program
129that listens to all data flowing in the network, and whenever it
130encounters a 16-digit string, it checks if it is a valid credit card
131number (using the check digit), and saves the number plus any
132surrounding text (to catch expiration date and holder) in a file.
133When the intruder has collected a few thousand credit card numbers, he
134makes smallish mail-order purchases from a few thousand stores around
135the world, and disappears when the goods arrive but before anyone
136suspects anything.
137
138Businesses have trade secrets, patent applications in preparation,
139pricing information, subcontractor information, client data, personnel
140data, financial information, etc. Currently, anyone with access to
141the network (any machine on the network) can listen to anything that
142goes in the network, without any regard to normal access restrictions.
143
144Many companies are not aware that information can so easily be
145recovered from the network. They trust that their data is safe
146since nobody is supposed to know that there is sensitive information
147in the network, or because so much other data is transferred in the
148network. This is not a safe policy.
149
150Individual persons also have confidential information, such as
151diaries, love letters, health care documents, information about their
152personal interests and habits, professional data, job applications,
153tax reports, political documents, unpublished manuscripts, etc.
154
155One should also be aware that economical intelligence and industrial
156espionage has recently become a major priority of the intelligence
157agencies of major governments. President Clinton recently assigned
158economical espionage as the primary task of the CIA, and the French
159have repeatedly been publicly boasting about their achievements on
160this field.
161
162
163There is also another frightening aspect about the poor security of
164communications. Computer storage and analysis capability has
165increased so much that it is feasible for governments, major
166companies, and criminal organizations to automatically analyze,
167identify, classify, and file information about millions of people over
168the years. Because most of the work can be automated, the cost of
169collecting this information is getting very low.
170
171Government agencies may be able to monitor major communication
172systems, telephones, fax, computer networks, etc., and passively
173collect huge amounts of information about all people with any
174significant position in the society. Most of this information is not
175sensitive, and many people would say there is no harm in someone
176getting that information. However, the information starts to get
177sensitive when someone has enough of it. You may not mind someone
178knowing what you bought from the shop one random day, but you might
179not like someone knowing every small thing you have bought in the last
180ten years.
181
182If the government some day starts to move into a more totalitarian
183direction (one should remember that Nazi Germany was created by
184democratic elections), there is considerable danger of an ultimate
185totalitarian state. With enough information (the automatically
186collected records of an individual can be manually analyzed when the
187person becomes interesting), one can form a very detailed picture of
188the individual's interests, opinions, beliefs, habits, friends,
189lovers, weaknesses, etc. This information can be used to 1) locate
190any persons who might oppose the new system 2) use deception to
191disturb any organizations which might rise against the government 3)
192eliminate difficult individuals without anyone understanding what
193happened. Additionally, if the government can monitor communications
194too effectively, it becomes too easy to locate and eliminate any
195persons distributing information contrary to the official truth.
196
197Fighting crime and terrorism are often used as grounds for domestic
198surveillance and restricting encryption. These are good goals, but
199there is considerable danger that the surveillance data starts to get
200used for questionable purposes. I find that it is better to tolerate
201a small amount of crime in the society than to let the society become
202fully controlled. I am in favor of a fairly strong state, but the
203state must never get so strong that people become unable to spread
204contra-offical information and unable to overturn the government if it
205is bad. The danger is that when you notice that the government is
206too powerful, it is too late. Also, the real power may not be where
207the official government is.
208
209For these reasons (privacy, protecting trade secrets, and making it
210more difficult to create a totalitarian state), I think that strong
211cryptography should be integrated to the tools we use every day.
212Using it causes no harm (except for those who wish to monitor
213everything), but not using it can cause huge problems. If the society
214changes in undesirable ways, then it will be to late to start
215encrypting.
216
217Encryption has had a "military" or "classified" flavor to it. There
218are no longer any grounds for this. The military can and will use its
219own encryption; that is no excuse to prevent the civilians from
220protecting their privacy and secrets. Information on strong
221encryption is available in every major bookstore, scientific library,
222and patent office around the world, and strong encryption software is
223available in every country on the Internet.
224
225Some people would like to make it illegal to use encryption, or to
226force people to use encryption that governments can break. This
227approach offers no protection if the government turns bad. Also, the
228"bad guys" will be using true strong encryption anyway. Good
229encryption techniques are too widely known to make them disappear.
230Thus, any "key escrow encryption" or other restrictions will only help
231monitor ordinary people and petty criminals. It does not help against
232powerful criminals, terrorists, or espionage, because they will know
233how to use strong encryption anyway. (One source for internationally
234available encryption software is http://www.cs.hut.fi/crypto.)
235
236
237OVERVIEW OF SECURE SHELL
238
239The software consists of a number of programs.
240
241 sshd Server program run on the server machine. This
242 listens for connections from client machines, and
243 whenever it receives a connection, it performs
244 authentication and starts serving the client.
245
246 ssh This is the client program used to log into another
247 machine or to execute commands on the other machine.
248 "slogin" is another name for this program.
249
250 scp Securely copies files from one machine to another.
251
252 ssh-keygen Used to create RSA keys (host keys and user
253 authentication keys).
254
255 ssh-agent Authentication agent. This can be used to hold RSA
256 keys for authentication.
257
258 ssh-add Used to register new keys with the agent.
259
260 make-ssh-known-hosts
261 Used to create the /etc/ssh_known_hosts file.
262
263
264Ssh is the program users normally use. It is started as
265
266 ssh host
267
268or
269
270 ssh host command
271
272The first form opens a new shell on the remote machine (after
273authentication). The latter form executes the command on the remote
274machine.
275
276When started, the ssh connects sshd on the server machine, verifies
277that the server machine really is the machine it wanted to connect,
278exchanges encryption keys (in a manner which prevents an outside
279listener from getting the keys), performs authentication using .rhosts
280and /etc/hosts.equiv, RSA authentication, or conventional password
281based authentication. The server then (normally) allocates a
282pseudo-terminal and starts an interactive shell or user program.
283
284The TERM environment variable (describing the type of the user's
285terminal) is passed from the client side to the remote side. Also,
286terminal modes will be copied from the client side to the remote side
287to preserve user preferences (e.g., the erase character).
288
289If the DISPLAY variable is set on the client side, the server will
290create a dummy X server and set DISPLAY accordingly. Any connections
291to the dummy X server will be forwarded through the secure channel,
292and will be made to the real X server from the client side. An
293arbitrary number of X programs can be started during the session, and
294starting them does not require anything special from the user. (Note
295that the user must not manually set DISPLAY, because then it would
296connect directly to the real display instead of going through the
297encrypted channel). This behavior can be disabled in the
298configuration file or by giving the -x option to the client.
299
300Arbitrary IP ports can be forwarded over the secure channel. The
301program then creates a port on one side, and whenever a connection is
302opened to this port, it will be passed over the secure channel, and a
303connection will be made from the other side to a specified host:port
304pair. Arbitrary IP forwarding must always be explicitly requested,
305and cannot be used to forward privileged ports (unless the user is
306root). It is possible to specify automatic forwards in a per-user
307configuration file, for example to make electronic cash systems work
308securely.
309
310If there is an authentication agent on the client side, connection to
311it will be automatically forwarded to the server side.
312
313For more infomation, see the manual pages ssh(1), sshd(8), scp(1),
314ssh-keygen(1), ssh-agent(1), ssh-add(1), and make-ssh-known-hosts(1)
315included in this distribution.
316
317
318X11 CONNECTION FORWARDING
319
320X11 forwarding serves two purposes: it is a convenience to the user
321because there is no need to set the DISPLAY variable, and it provides
322encrypted X11 connections. I cannot think of any other easy way to
323make X11 connections encrypted; modifying the X server, clients or
324libraries would require special work for each machine, vendor and
325application. Widely used IP-level encryption does not seem likely for
326several years. Thus what we have left is faking an X server on the
327same machine where the clients are run, and forwarding the connections
328to a real X server over the secure channel.
329
330X11 forwarding works as follows. The client extracts Xauthority
331information for the server. It then creates random authorization
332data, and sends the random data to the server. The server allocates
333an X11 display number, and stores the (fake) Xauthority data for this
334display. Whenever an X11 connection is opened, the server forwards
335the connection over the secure channel to the client, and the client
336parses the first packet of the X11 protocol, substitutes real
337authentication data for the fake data (if the fake data matched), and
338forwards the connection to the real X server.
339
340If the display does not have Xauthority data, the server will create a
341unix domain socket in /tmp/.X11-unix, and use the unix domain socket
342as the display. No authentication information is forwarded in this
343case. X11 connections are again forwarded over the secure channel.
344To the X server the connections appear to come from the client
345machine, and the server must have connections allowed from the local
346machine. Using authentication data is always recommended because not
347using it makes the display insecure. If XDM is used, it automatically
348generates the authentication data.
349
350One should be careful not to use "xin" or "xstart" or other similar
351scripts that explicitly set DISPLAY to start X sessions in a remote
352machine, because the connection will then not go over the secure
353channel. The recommended way to start a shell in a remote machine is
354
355 xterm -e ssh host &
356
357and the recommended way to execute an X11 application in a remote
358machine is
359
360 ssh -n host emacs &
361
362If you need to type a password/passphrase for the remote machine,
363
364 ssh -f host emacs
365
366may be useful.
367
368
369
370RSA AUTHENTICATION
371
372RSA authentication is based on public key cryptograpy. The idea is
373that there are two encryption keys, one for encryption and another for
374decryption. It is not possible (on human timescale) to derive the
375decryption key from the encryption key. The encryption key is called
376the public key, because it can be given to anyone and it is not
377secret. The decryption key, on the other hand, is secret, and is
378called the private key.
379
380RSA authentication is based on the impossibility of deriving the
381private key from the public key. The public key is stored on the
382server machine in the user's $HOME/.ssh/authorized_keys file. The
383private key is only kept on the user's local machine, laptop, or other
384secure storage. Then the user tries to log in, the client tells the
385server the public key that the user wishes to use for authentication.
386The server then checks if this public key is admissible. If so, it
387generates a 256 bit random number, encrypts it with the public key,
388and sends the value to the client. The client then decrypts the
389number with its private key, computes a 128 bit MD5 checksum from the
390resulting data, and sends the checksum back to the server. (Only a
391checksum is sent to prevent chosen-plaintext attacks against RSA.)
392The server checks computes a checksum from the correct data,
393and compares the checksums. Authentication is accepted if the
394checksums match. (Theoretically this indicates that the client
395only probably knows the correct key, but for all practical purposes
396there is no doubt.)
397
398The RSA private key can be protected with a passphrase. The
399passphrase can be any string; it is hashed with MD5 to produce an
400encryption key for IDEA, which is used to encrypt the private part of
401the key file. With passphrase, authorization requires access to the key
402file and the passphrase. Without passphrase, authorization only
403depends on possession of the key file.
404
405RSA authentication is the most secure form of authentication supported
406by this software. It does not rely on the network, routers, domain
407name servers, or the client machine. The only thing that matters is
408access to the private key.
409
410All this, of course, depends on the security of the RSA algorithm
411itself. RSA has been widely known since about 1978, and no effective
412methods for breaking it are known if it is used properly. Care has
413been taken to avoid the well-known pitfalls. Breaking RSA is widely
414believed to be equivalent to factoring, which is a very hard
415mathematical problem that has received considerable public research.
416So far, no effective methods are known for numbers bigger than about
417512 bits. However, as computer speeds and factoring methods are
418increasing, 512 bits can no longer be considered secure. The
419factoring work is exponential, and 768 or 1024 bits are widely
420considered to be secure in the near future.
421
422
423RHOSTS AUTHENTICATION
424
425Conventional .rhosts and hosts.equiv based authentication mechanisms
426are fundamentally insecure due to IP, DNS (domain name server) and
427routing spoofing attacks. Additionally this authentication method
428relies on the integrity of the client machine. These weaknesses is
429tolerable, and been known and exploited for a long time.
430
431Ssh provides an improved version of these types of authentication,
432because they are very convenient for the user (and allow easy
433transition from rsh and rlogin). It permits these types of
434authentication, but additionally requires that the client host be
435authenticated using RSA.
436
437The server has a list of host keys stored in /etc/ssh_known_host, and
438additionally each user has host keys in $HOME/.ssh/known_hosts. Ssh
439uses the name servers to obtain the canonical name of the client host,
440looks for its public key in its known host files, and requires the
441client to prove that it knows the private host key. This prevents IP
442and routing spoofing attacks (as long as the client machine private
443host key has not been compromized), but is still vulnerable to DNS
444attacks (to a limited extent), and relies on the integrity of the
445client machine as to who is requesting to log in. This prevents
446outsiders from attacking, but does not protect against very powerful
447attackers. If maximal security is desired, only RSA authentication
448should be used.
449
450It is possible to enable conventional .rhosts and /etc/hosts.equiv
451authentication (without host authentication) at compile time by giving
452the option --with-rhosts to configure. However, this is not
453recommended, and is not done by default.
454
455These weaknesses are present in rsh and rlogin. No improvement in
456security will be obtained unless rlogin and rsh are completely
457disabled (commented out in /etc/inetd.conf). This is highly
458recommended.
459
460
461WEAKEST LINKS IN SECURITY
462
463One should understand that while this software may provide
464cryptographically secure communications, it may be easy to
465monitor the communications at their endpoints.
466
467Basically, anyone with root access on the local machine on which you
468are running the software may be able to do anything. Anyone with root
469access on the server machine may be able to monitor your
470communications, and a very talented root user might even be able to
471send his/her own requests to your authentication agent.
472
473One should also be aware that computers send out electromagnetic
474radition that can sometimes be picked up hundreds of meters away.
475Your keyboard is particularly easy to listen to. The image on your
476monitor might also be seen on another monitor in a van parked behind
477your house.
478
479Beware that unwanted visitors might come to your home or office and
480use your machine while you are away. They might also make
481modifications or install bugs in your hardware or software.
482
483Beware that the most effective way for someone to decrypt your data
484may be with a rubber hose.
485
486
487LEGAL ISSUES
488
489As far as I am concerned, anyone is permitted to use this software
490freely. However, see the file COPYING for detailed copying,
491licensing, and distribution information.
492
493In some countries, particularly France, Russia, Iraq, and Pakistan,
494it may be illegal to use any encryption at all without a special
495permit, and the rumor has it that you cannot get a permit for any
496strong encryption.
497
498This software may be freely imported into the United States; however,
499the United States Government may consider re-exporting it a criminal
500offence.
501
502Note that any information and cryptographic algorithms used in this
503software are publicly available on the Internet and at any major
504bookstore, scientific library, or patent office worldwide.
505
506THERE IS NO WARRANTY FOR THIS PROGRAM. Please consult the file
507COPYING for more information.
508
509
510MAILING LISTS AND OTHER INFORMATION
511
512There is a mailing list for ossh. It is ossh@sics.se. If you would
513like to join, send a message to majordomo@sics.se with "subscribe
514ssh" in body.
515
516The WWW home page for ssh is http://www.cs.hut.fi/ssh. It contains an
517archive of the mailing list, and detailed information about new
518releases, mailing lists, and other relevant issues.
519
520Bug reports should be sent to ossh-bugs@sics.se.
521
522
523ABOUT THE AUTHOR
524
525This software was written by Tatu Ylonen <ylo@cs.hut.fi>. I work as a
526researcher at Helsinki University of Technology, Finland. For more
527information, see http://www.cs.hut.fi/~ylo/. My PGP public key is
528available via finger from ylo@cs.hut.fi and from the key servers. I
529prefer PGP encrypted mail.
530
531The author can be contacted via ordinary mail at
532 Tatu Ylonen
533 Helsinki University of Technology
534 Otakaari 1
535 FIN-02150 ESPOO
536 Finland
537
538 Fax. +358-0-4513293
539
540
541ACKNOWLEDGEMENTS
542
543I thank Tero Kivinen, Timo Rinne, Janne Snabb, and Heikki Suonsivu for
544their help and comments in the design, implementation and porting of
545this software. I also thank numerous contributors, including but not
546limited to Walker Aumann, Jurgen Botz, Hans-Werner Braun, Stephane
547Bortzmeyer, Adrian Colley, Michael Cooper, David Dombek, Jerome
548Etienne, Bill Fithen, Mark Fullmer, Bert Gijsbers, Andreas Gustafsson,
549Michael Henits, Steve Johnson, Thomas Koenig, Felix Leitner, Gunnar
550Lindberg, Andrew Macpherson, Marc Martinec, Paul Mauvais, Donald
551McKillican, Leon Mlakar, Robert Muchsel, Mark Treacy, Bryan
552O'Sullivan, Mikael Suokas, Ollivier Robert, Jakob Schlyter, Tomasz
553Surmacz, Alvar Vinacua, Petri Virkkula, Michael Warfield, and
554Cristophe Wolfhugel.
555
556Thanks also go to Philip Zimmermann, whose PGP software and the
557associated legal battle provided inspiration, motivation, and many
558useful techniques, and to Bruce Schneier whose book Applied
559Cryptography has done a great service in widely distributing knowledge
560about cryptographic methods.
561
562
563Copyright (c) 1995 Tatu Ylonen, Espoo, Finland.
diff --git a/README.openssh b/README.openssh
new file mode 100644
index 000000000..02cb3c603
--- /dev/null
+++ b/README.openssh
@@ -0,0 +1,44 @@
1This is a Linux port of OpenBSD's excellent OpenSSH.
2
3OpenSSH is based on the last free version of Tatu Ylonen's SSH with all
4patent-encumbered algorithms removed, all known security bugs fixed, new
5features reintroduced and many other clean-ups.
6
7This Linux port basically consists of a few fixes to deal with the way that
8OpenSSL is usually installed on Linux systems, a few replacements for
9OpenBSD library functions and the introduction of partial PAM support.
10
11The PAM support is less than optimal - it is only used when password
12authentication is requested, so things like pam_limits will not apply if a
13user authenticates with a RSA key. OTOH this is exactly the level of support
14that the popular Linux SSH packages have. Perhaps a PAM hacker can rectify
15this?
16
17All new code is released under a XFree style license, which is very liberal.
18This code is released with no warranties of any kind, neither I nor my
19employer (Internet Business Solutions) will take any responsibility for
20any loss, damage or liability arising from the use or abuse of this software.
21
22OpenSSH depends on Zlib, OpenSSL and PAM. Use the Makefile.GNU to build it.
23
24Damien Miller <djm@ibs.com.au>
25Internet Business Solutions
26
27
28Credits -
29
30The OpenBSD team
31'jonchen' - the original author of PAM support of SSH
32
33Miscellania -
34
35This version of SSH is based upon code retrieved from the OpenBSD CVS
36repository on 1999-10-26, which in turn was based on the last free
37version of SSH released by Tatu Ylonen.
38
39Code in helper.[ch] is Copyright 1999 Internet Business Solutions and
40is released under a X11-style license (see source file for details).
41
42(A)RC4 code in rc4.[ch] is Copyright 1999 Damien Miller. It too is
43under a X11-style license (see source file for details).
44
diff --git a/RFC.nroff b/RFC.nroff
new file mode 100644
index 000000000..cc197aaff
--- /dev/null
+++ b/RFC.nroff
@@ -0,0 +1,1780 @@
1.\" -*- nroff -*-
2.\"
3.\" $Id: RFC.nroff,v 1.1 1999/10/27 03:42:43 damien Exp $
4.\"
5.pl 10.0i
6.po 0
7.ll 7.2i
8.lt 7.2i
9.nr LL 7.2i
10.nr LT 7.2i
11.ds LF Ylonen
12.ds RF FORMFEED[Page %]
13.ds CF
14.ds LH Internet-Draft
15.ds RH 15 November 1995
16.ds CH SSH (Secure Shell) Remote Login Protocol
17.na
18.hy 0
19.in 0
20Network Working Group T. Ylonen
21Internet-Draft Helsinki University of Technology
22draft-ylonen-ssh-protocol-00.txt 15 November 1995
23Expires: 15 May 1996
24
25.in 3
26
27.ce
28The SSH (Secure Shell) Remote Login Protocol
29
30.ti 0
31Status of This Memo
32
33This document is an Internet-Draft. Internet-Drafts are working
34documents of the Internet Engineering Task Force (IETF), its areas,
35and its working groups. Note that other groups may also distribute
36working documents as Internet-Drafts.
37
38Internet-Drafts are draft documents valid for a maximum of six
39months and may be updated, replaced, or obsoleted by other docu-
40ments at any time. It is inappropriate to use Internet-Drafts as
41reference material or to cite them other than as ``work in pro-
42gress.''
43
44To learn the current status of any Internet-Draft, please check the
45``1id-abstracts.txt'' listing contained in the Internet- Drafts Shadow
46Directories on ftp.is.co.za (Africa), nic.nordu.net (Europe),
47munnari.oz.au (Pacific Rim), ds.internic.net (US East Coast), or
48ftp.isi.edu (US West Coast).
49
50The distribution of this memo is unlimited.
51
52.ti 0
53Introduction
54
55SSH (Secure Shell) is a program to log into another computer over a
56network, to execute commands in a remote machine, and to move files
57from one machine to another. It provides strong authentication and
58secure communications over insecure networks. Its features include
59the following:
60.IP o
61Closes several security holes (e.g., IP, routing, and DNS spoofing).
62New authentication methods: .rhosts together with RSA [RSA] based host
63authentication, and pure RSA authentication.
64.IP o
65All communications are automatically and transparently encrypted.
66Encryption is also used to protect integrity.
67.IP o
68X11 connection forwarding provides secure X11 sessions.
69.IP o
70Arbitrary TCP/IP ports can be redirected over the encrypted channel
71in both directions.
72.IP o
73Client RSA-authenticates the server machine in the beginning of every
74connection to prevent trojan horses (by routing or DNS spoofing) and
75man-in-the-middle attacks, and the server RSA-authenticates the client
76machine before accepting .rhosts or /etc/hosts.equiv authentication
77(to prevent DNS, routing, or IP spoofing).
78.IP o
79An authentication agent, running in the user's local workstation or
80laptop, can be used to hold the user's RSA authentication keys.
81.RT
82
83The goal has been to make the software as easy to use as possible for
84ordinary users. The protocol has been designed to be as secure as
85possible while making it possible to create implementations that
86are easy to use and install. The sample implementation has a number
87of convenient features that are not described in this document as they
88are not relevant for the protocol.
89
90
91.ti 0
92Overview of the Protocol
93
94The software consists of a server program running on a server machine,
95and a client program running on a client machine (plus a few auxiliary
96programs). The machines are connected by an insecure IP [RFC0791]
97network (that can be monitored, tampered with, and spoofed by hostile
98parties).
99
100A connection is always initiated by the client side. The server
101listens on a specific port waiting for connections. Many clients may
102connect to the same server machine.
103
104The client and the server are connected via a TCP/IP [RFC0793] socket
105that is used for bidirectional communication. Other types of
106transport can be used but are currently not defined.
107
108When the client connects the server, the server accepts the connection
109and responds by sending back its version identification string. The
110client parses the server's identification, and sends its own
111identification. The purpose of the identification strings is to
112validate that the connection was to the correct port, declare the
113protocol version number used, and to declare the software version used
114on each side (for debugging purposes). The identification strings are
115human-readable. If either side fails to understand or support the
116other side's version, it closes the connection.
117
118After the protocol identification phase, both sides switch to a packet
119based binary protocol. The server starts by sending its host key
120(every host has an RSA key used to authenticate the host), server key
121(an RSA key regenerated every hour), and other information to the
122client. The client then generates a 256 bit session key, encrypts it
123using both RSA keys (see below for details), and sends the encrypted
124session key and selected cipher type to the server. Both sides then
125turn on encryption using the selected algorithm and key. The server
126sends an encrypted confirmation message to the client.
127
128The client then authenticates itself using any of a number of
129authentication methods. The currently supported authentication
130methods are .rhosts or /etc/hosts.equiv authentication (disabled by
131default), the same with RSA-based host authentication, RSA
132authentication, and password authentication.
133
134After successful authentication, the client makes a number of requests
135to prepare for the session. Typical requests include allocating a
136pseudo tty, starting X11 [X11] or TCP/IP port forwarding, starting
137authentication agent forwarding, and executing the shell or a command.
138
139When a shell or command is executed, the connection enters interactive
140session mode. In this mode, data is passed in both directions,
141new forwarded connections may be opened, etc. The interactive session
142normally terminates when the server sends the exit status of the
143program to the client.
144
145
146The protocol makes several reservations for future extensibility.
147First of all, the initial protocol identification messages include the
148protocol version number. Second, the first packet by both sides
149includes a protocol flags field, which can be used to agree on
150extensions in a compatible manner. Third, the authentication and
151session preparation phases work so that the client sends requests to
152the server, and the server responds with success or failure. If the
153client sends a request that the server does not support, the server
154simply returns failure for it. This permits compatible addition of
155new authentication methods and preparation operations. The
156interactive session phase, on the other hand, works asynchronously and
157does not permit the use of any extensions (because there is no easy
158and reliable way to signal rejection to the other side and problems
159would be hard to debug). Any compatible extensions to this phase must
160be agreed upon during any of the earlier phases.
161
162.ti 0
163The Binary Packet Protocol
164
165After the protocol identification strings, both sides only send
166specially formatted packets. The packet layout is as follows:
167.IP o
168Packet length: 32 bit unsigned integer, coded as four 8-bit bytes, msb
169first. Gives the length of the packet, not including the length field
170and padding. The maximum length of a packet (not including the length
171field and padding) is 262144 bytes.
172.IP o
173Padding: 1-8 bytes of random data (or zeroes if not encrypting). The
174amount of padding is (8 - (length % 8)) bytes (where % stands for the
175modulo operator). The rationale for always having some random padding
176at the beginning of each packet is to make known plaintext attacks
177more difficult.
178.IP o
179Packet type: 8-bit unsigned byte. The value 255 is reserved for
180future extension.
181.IP o
182Data: binary data bytes, depending on the packet type. The number of
183data bytes is the "length" field minus 5.
184.IP o
185Check bytes: 32-bit crc, four 8-bit bytes, msb first. The crc is the
186Cyclic Redundancy Check, with the polynomial 0xedb88320, of the
187Padding, Packet type, and Data fields. The crc is computed before
188any encryption.
189.RT
190
191The packet, except for the length field, may be encrypted using any of
192a number of algorithms. The length of the encrypted part (Padding +
193Type + Data + Check) is always a multiple of 8 bytes. Typically the
194cipher is used in a chained mode, with all packets chained together as
195if it was a single data stream (the length field is never included in
196the encryption process). Details of encryption are described below.
197
198When the session starts, encryption is turned off. Encryption is
199enabled after the client has sent the session key. The encryption
200algorithm to use is selected by the client.
201
202
203.ti 0
204Packet Compression
205
206If compression is supported (it is an optional feature, see
207SSH_CMSG_REQUEST_COMPRESSION below), the packet type and data fields
208of the packet are compressed using the gzip deflate algorithm [GZIP].
209If compression is in effect, the packet length field indicates the
210length of the compressed data, plus 4 for the crc. The amount of
211padding is computed from the compressed data, so that the amount of
212data to be encrypted becomes a multiple of 8 bytes.
213
214When compressing, the packets (type + data portions) in each direction
215are compressed as if they formed a continuous data stream, with only the
216current compression block flushed between packets. This corresponds
217to the GNU ZLIB library Z_PARTIAL_FLUSH option. The compression
218dictionary is not flushed between packets. The two directions are
219compressed independently of each other.
220
221
222.ti 0
223Packet Encryption
224
225The protocol supports several encryption methods. During session
226initialization, the server sends a bitmask of all encryption methods
227that it supports, and the client selects one of these methods. The
228client also generates a 256-bit random session key (32 8-bit bytes) and
229sends it to the server.
230
231The encryption methods supported by the current implementation, and
232their codes are:
233.TS
234center;
235l r l.
236SSH_CIPHER_NONE 0 No encryption
237SSH_CIPHER_IDEA 1 IDEA in CFB mode
238SSH_CIPHER_DES 2 DES in CBC mode
239SSH_CIPHER_3DES 3 Triple-DES in CBC mode
240SSH_CIPHER_TSS 4 An experimental stream cipher
241SSH_CIPHER_RC4 5 RC4
242.TE
243
244All implementations are required to support SSH_CIPHER_DES and
245SSH_CIPHER_3DES. Supporting SSH_CIPHER_IDEA, SSH_CIPHER_RC4, and
246SSH_CIPHER_NONE is recommended. Support for SSH_CIPHER_TSS is
247optional (and it is not described in this document). Other ciphers
248may be added at a later time; support for them is optional.
249
250For encryption, the encrypted portion of the packet is considered a
251linear byte stream. The length of the stream is always a multiple of
2528. The encrypted portions of consecutive packets (in the same
253direction) are encrypted as if they were a continuous buffer (that is,
254any initialization vectors are passed from the previous packet to the
255next packet). Data in each direction is encrypted independently.
256.IP SSH_CIPHER_DES
257The key is taken from the first 8 bytes of the session key. The least
258significant bit of each byte is ignored. This results in 56 bits of
259key data. DES [DES] is used in CBC mode. The iv (initialization vector) is
260initialized to all zeroes.
261.IP SSH_CIPHER_3DES
262The variant of triple-DES used here works as follows: there are three
263independent DES-CBC ciphers, with independent initialization vectors.
264The data (the whole encrypted data stream) is first encrypted with the
265first cipher, then decrypted with the second cipher, and finally
266encrypted with the third cipher. All these operations are performed
267in CBC mode.
268
269The key for the first cipher is taken from the first 8 bytes of the
270session key; the key for the next cipher from the next 8 bytes, and
271the key for the third cipher from the following 8 bytes. All three
272initialization vectors are initialized to zero.
273
274(Note: the variant of 3DES used here differs from some other
275descriptions.)
276.IP SSH_CIPHER_IDEA
277The key is taken from the first 16 bytes of the session key. IDEA
278[IDEA] is used in CFB mode. The initialization vector is initialized
279to all zeroes.
280.IP SSH_CIPHER_TSS
281All 32 bytes of the session key are used as the key.
282
283There is no reference available for the TSS algorithm; it is currently
284only documented in the sample implementation source code. The
285security of this cipher is unknown (but it is quite fast). The cipher
286is basically a stream cipher that uses MD5 as a random number
287generator and takes feedback from the data.
288.IP SSH_CIPHER_RC4
289The first 16 bytes of the session key are used as the key for the
290server to client direction. The remaining 16 bytes are used as the
291key for the client to server direction. This gives independent
292128-bit keys for each direction.
293
294This algorithm is the alleged RC4 cipher posted to the Usenet in 1995.
295It is widely believed to be equivalent with the original RSADSI RC4
296cipher. This is a very fast algorithm.
297.RT
298
299
300.ti 0
301Data Type Encodings
302
303The Data field of each packet contains data encoded as described in
304this section. There may be several data items; each item is coded as
305described here, and their representations are concatenated together
306(without any alignment or padding).
307
308Each data type is stored as follows:
309.IP "8-bit byte"
310The byte is stored directly as a single byte.
311.IP "32-bit unsigned integer"
312Stored in 4 bytes, msb first.
313.IP "Arbitrary length binary string"
314First 4 bytes are the length of the string, msb first (not including
315the length itself). The following "length" bytes are the string
316value. There are no terminating null characters.
317.IP "Multiple-precision integer"
318First 2 bytes are the number of bits in the integer, msb first (for
319example, the value 0x00012345 would have 17 bits). The value zero has
320zero bits. It is permissible that the number of bits be larger than the
321real number of bits.
322
323The number of bits is followed by (bits + 7) / 8 bytes of binary data,
324msb first, giving the value of the integer.
325.RT
326
327
328.ti 0
329TCP/IP Port Number and Other Options
330
331The server listens for connections on TCP/IP port 22.
332
333The client may connect the server from any port. However, if the
334client wishes to use any form of .rhosts or /etc/hosts.equiv
335authentication, it must connect from a privileged port (less than
3361024).
337
338For the IP Type of Service field [RFC0791], it is recommended that
339interactive sessions (those having a user terminal or forwarding X11
340connections) use the IPTOS_LOWDELAY, and non-interactive connections
341use IPTOS_THROUGHPUT.
342
343It is recommended that keepalives are used, because otherwise programs
344on the server may never notice if the other end of the connection is
345rebooted.
346
347
348.ti 0
349Protocol Version Identification
350
351After the socket is opened, the server sends an identification string,
352which is of the form
353"SSH-<protocolmajor>.<protocolminor>-<version>\\n", where
354<protocolmajor> and <protocolminor> are integers and specify the
355protocol version number (not software distribution version).
356<version> is server side software version string (max 40 characters);
357it is not interpreted by the remote side but may be useful for
358debugging.
359
360The client parses the server's string, and sends a corresponding
361string with its own information in response. If the server has lower
362version number, and the client contains special code to emulate it,
363the client responds with the lower number; otherwise it responds with
364its own number. The server then compares the version number the
365client sent with its own, and determines whether they can work
366together. The server either disconnects, or sends the first packet
367using the binary packet protocol and both sides start working
368according to the lower of the protocol versions.
369
370By convention, changes which keep the protocol compatible with
371previous versions keep the same major protocol version; changes that
372are not compatible increment the major version (which will hopefully
373never happen). The version described in this document is 1.3.
374
375The client will
376
377.ti 0
378Key Exchange and Server Host Authentication
379
380The first message sent by the server using the packet protocol is
381SSH_SMSG_PUBLIC_KEY. It declares the server's host key, server public
382key, supported ciphers, supported authentication methods, and flags
383for protocol extensions. It also contains a 64-bit random number
384(cookie) that must be returned in the client's reply (to make IP
385spoofing more difficult). No encryption is used for this message.
386
387Both sides compute a session id as follows. The modulus of the server
388key is interpreted as a byte string (without explicit length field,
389with minimum length able to hold the whole value), most significant
390byte first. This string is concatenated with the server host key
391interpreted the same way. Additionally, the cookie is concatenated
392with this. Both sides compute MD5 of the resulting string. The
393resulting 16 bytes (128 bits) are stored by both parties and are
394called the session id.
395
396The client responds with a SSH_CMSG_SESSION_KEY message, which
397contains the selected cipher type, a copy of the 64-bit cookie sent by
398the server, client's protocol flags, and a session key encrypted
399with both the server's host key and server key. No encryption is used
400for this message.
401
402The session key is 32 8-bit bytes (a total of 256 random bits
403generated by the client). The client first xors the 16 bytes of the
404session id with the first 16 bytes of the session key. The resulting
405string is then encrypted using the smaller key (one with smaller
406modulus), and the result is then encrypted using the other key. The
407number of bits in the public modulus of the two keys must differ by at
408least 128 bits.
409
410At each encryption step, a multiple-precision integer is constructed
411from the data to be encrypted as follows (the integer is here
412interpreted as a sequence of bytes, msb first; the number of bytes is
413the number of bytes needed to represent the modulus).
414
415The most significant byte (which is only partial as the value must be
416less than the public modulus, which is never a power of two) is zero.
417
418The next byte contains the value 2 (which stands for public-key
419encrypted data in the PKCS standard [PKCS#1]). Then, there are
420non-zero random bytes to fill any unused space, a zero byte, and the
421data to be encrypted in the least significant bytes, the last byte of
422the data in the least significant byte.
423
424This algorithm is used twice. First, it is used to encrypt the 32
425random bytes generated by the client to be used as the session key
426(xored by the session id). This value is converted to an integer as
427described above, and encrypted with RSA using the key with the smaller
428modulus. The resulting integer is converted to a byte stream, msb
429first. This byte stream is padded and encrypted identically using the
430key with the larger modulus.
431
432After the client has sent the session key, it starts to use the
433selected algorithm and key for decrypting any received packets, and
434for encrypting any sent packets. Separate ciphers are used for
435different directions (that is, both directions have separate
436initialization vectors or other state for the ciphers).
437
438When the server has received the session key message, and has turned
439on encryption, it sends a SSH_SMSG_SUCCESS message to the client.
440
441The recommended size of the host key is 1024 bits, and 768 bits for
442the server key. The minimum size is 512 bits for the smaller key.
443
444
445.ti 0
446Declaring the User Name
447
448The client then sends a SSH_CMSG_USER message to the server. This
449message specifies the user name to log in as.
450
451The server validates that such a user exists, checks whether
452authentication is needed, and responds with either SSH_SMSG_SUCCESS or
453SSH_SMSG_FAILURE. SSH_SMSG_SUCCESS indicates that no authentication
454is needed for this user (no password), and authentication phase has
455now been completed. SSH_SMSG_FAILURE indicates that authentication is
456needed (or the user does not exist).
457
458If the user does not exist, it is recommended that this returns
459failure, but the server keeps reading messages from the client, and
460responds to any messages (except SSH_MSG_DISCONNECT, SSH_MSG_IGNORE,
461and SSH_MSG_DEBUG) with SSH_SMSG_FAILURE. This way the client cannot
462be certain whether the user exists.
463
464
465.ti 0
466Authentication Phase
467
468Provided the server didn't immediately accept the login, an
469authentication exchange begins. The client sends messages to the
470server requesting different types of authentication in arbitrary order as
471many times as desired (however, the server may close the connection
472after a timeout). The server always responds with SSH_SMSG_SUCCESS if
473it has accepted the authentication, and with SSH_SMSG_FAILURE if it has
474denied authentication with the requested method or it does not
475recognize the message. Some authentication methods cause an exchange
476of further messages before the final result is sent. The
477authentication phase ends when the server responds with success.
478
479The recommended value for the authentication timeout (timeout before
480disconnecting if no successful authentication has been made) is 5
481minutes.
482
483The following authentication methods are currently supported:
484.TS
485center;
486l r l.
487SSH_AUTH_RHOSTS 1 .rhosts or /etc/hosts.equiv
488SSH_AUTH_RSA 2 pure RSA authentication
489SSH_AUTH_PASSWORD 3 password authentication
490SSH_AUTH_RHOSTS_RSA 4 .rhosts with RSA host authentication
491.TE
492.IP SSH_AUTH_RHOSTS
493
494This is the authentication method used by rlogin and rsh [RFC1282].
495
496The client sends SSH_CMSG_AUTH_RHOSTS with the client-side user name
497as an argument.
498
499The server checks whether to permit authentication. On UNIX systems,
500this is usually done by checking /etc/hosts.equiv, and .rhosts in the
501user's home directory. The connection must come from a privileged
502port.
503
504It is recommended that the server checks that there are no IP options
505(such as source routing) specified for the socket before accepting
506this type of authentication. The client host name should be
507reverse-mapped and then forward mapped to ensure that it has the
508proper IP-address.
509
510This authentication method trusts the remote host (root on the remote
511host can pretend to be any other user on that host), the name
512services, and partially the network: anyone who can see packets coming
513out from the server machine can do IP-spoofing and pretend to be any
514machine; however, the protocol prevents blind IP-spoofing (which used
515to be possible with rlogin).
516
517Many sites probably want to disable this authentication method because
518of the fundamental insecurity of conventional .rhosts or
519/etc/hosts.equiv authentication when faced with spoofing. It is
520recommended that this method not be supported by the server by
521default.
522.IP SSH_AUTH_RHOSTS_RSA
523
524In addition to conventional .rhosts and hosts.equiv authentication,
525this method additionally requires that the client host be
526authenticated using RSA.
527
528The client sends SSH_CMSG_AUTH_RHOSTS_RSA specifying the client-side
529user name, and the public host key of the client host.
530
531The server first checks if normal .rhosts or /etc/hosts.equiv
532authentication would be accepted, and if not, responds with
533SSH_SMSG_FAILURE. Otherwise, it checks whether it knows the host key
534for the client machine (using the same name for the host that was used
535for checking the .rhosts and /etc/hosts.equiv files). If it does not
536know the RSA key for the client, access is denied and SSH_SMSG_FAILURE
537is sent.
538
539If the server knows the host key of the client machine, it verifies
540that the given host key matches that known for the client. If not,
541access is denied and SSH_SMSG_FAILURE is sent.
542
543The server then sends a SSH_SMSG_AUTH_RSA_CHALLENGE message containing
544an encrypted challenge for the client. The challenge is 32 8-bit
545random bytes (256 bits). When encrypted, the highest (partial) byte
546is left as zero, the next byte contains the value 2, the following are
547non-zero random bytes, followed by a zero byte, and the challenge put
548in the remaining bytes. This is then encrypted using RSA with the
549client host's public key. (The padding and encryption algorithm is
550the same as that used for the session key.)
551
552The client decrypts the challenge using its private host key,
553concatenates this with the session id, and computes an MD5 checksum
554of the resulting 48 bytes. The MD5 output is returned as 16 bytes in
555a SSH_CMSG_AUTH_RSA_RESPONSE message. (MD5 is used to deter chosen
556plaintext attacks against RSA; the session id binds it to a specific
557session).
558
559The server verifies that the MD5 of the decrypted challenge returned by
560the client matches that of the original value, and sends SSH_SMSG_SUCCESS if
561so. Otherwise it sends SSH_SMSG_FAILURE and refuses the
562authentication attempt.
563
564This authentication method trusts the client side machine in that root
565on that machine can pretend to be any user on that machine.
566Additionally, it trusts the client host key. The name and/or IP
567address of the client host is only used to select the public host key.
568The same host name is used when scanning .rhosts or /etc/hosts.equiv
569and when selecting the host key. It would in principle be possible to
570eliminate the host name entirely and substitute it directly by the
571host key. IP and/or DNS [RFC1034] spoofing can only be used
572to pretend to be a host for which the attacker has the private host
573key.
574.IP SSH_AUTH_RSA
575
576The idea behind RSA authentication is that the server recognizes the
577public key offered by the client, generates a random challenge, and
578encrypts the challenge with the public key. The client must then
579prove that it has the corresponding private key by decrypting the
580challenge.
581
582The client sends SSH_CMSG_AUTH_RSA with public key modulus (n) as an
583argument.
584
585The server may respond immediately with SSH_SMSG_FAILURE if it does
586not permit authentication with this key. Otherwise it generates a
587challenge, encrypts it using the user's public key (stored on the
588server and identified using the modulus), and sends
589SSH_SMSG_AUTH_RSA_CHALLENGE with the challenge (mp-int) as an
590argument.
591
592The challenge is 32 8-bit random bytes (256 bits). When encrypted,
593the highest (partial) byte is left as zero, the next byte contains the
594value 2, the following are non-zero random bytes, followed by a zero
595byte, and the challenge put in the remaining bytes. This is then
596encrypted with the public key. (The padding and encryption algorithm
597is the same as that used for the session key.)
598
599The client decrypts the challenge using its private key, concatenates
600it with the session id, and computes an MD5 checksum of the resulting
60148 bytes. The MD5 output is returned as 16 bytes in a
602SSH_CMSG_AUTH_RSA_RESPONSE message. (Note that the MD5 is necessary
603to avoid chosen plaintext attacks against RSA; the session id binds it
604to a specific session.)
605
606The server verifies that the MD5 of the decrypted challenge returned
607by the client matches that of the original value, and sends
608SSH_SMSG_SUCCESS if so. Otherwise it sends SSH_SMSG_FAILURE and
609refuses the authentication attempt.
610
611This authentication method does not trust the remote host, the
612network, name services, or anything else. Authentication is based
613solely on the possession of the private identification keys. Anyone
614in possession of the private keys can log in, but nobody else.
615
616The server may have additional requirements for a successful
617authentiation. For example, to limit damage due to a compromised RSA
618key, a server might restrict access to a limited set of hosts.
619.IP SSH_AUTH_PASSWORD
620
621The client sends a SSH_CMSG_AUTH_PASSWORD message with the plain text
622password. (Note that even though the password is plain text inside
623the message, it is normally encrypted by the packet mechanism.)
624
625The server verifies the password, and sends SSH_SMSG_SUCCESS if
626authentication was accepted and SSH_SMSG_FAILURE otherwise.
627
628Note that the password is read from the user by the client; the user
629never interacts with a login program.
630
631This authentication method does not trust the remote host, the
632network, name services or anything else. Authentication is based
633solely on the possession of the password. Anyone in possession of the
634password can log in, but nobody else.
635.RT
636
637.ti 0
638Preparatory Operations
639
640After successful authentication, the server waits for a request from
641the client, processes the request, and responds with SSH_SMSG_SUCCESS
642whenever a request has been successfully processed. If it receives a
643message that it does not recognize or it fails to honor a request, it
644returns SSH_SMSG_FAILURE. It is expected that new message types might
645be added to this phase in future.
646
647The following messages are currently defined for this phase.
648.IP SSH_CMSG_REQUEST_COMPRESSION
649Requests that compression be enabled for this session. A
650gzip-compatible compression level (1-9) is passed as an argument.
651.IP SSH_CMSG_REQUEST_PTY
652Requests that a pseudo terminal device be allocated for this session.
653The user terminal type and terminal modes are supplied as arguments.
654.IP SSH_CMSG_X11_REQUEST_FORWARDING
655Requests forwarding of X11 connections from the remote machine to the
656local machine over the secure channel. Causes an internet-domain
657socket to be allocated and the DISPLAY variable to be set on the server.
658X11 authentication data is automatically passed to the server, and the
659client may implement spoofing of authentication data for added
660security. The authentication data is passed as arguments.
661.IP SSH_CMSG_PORT_FORWARD_REQUEST
662Requests forwarding of a TCP/IP port on the server host over the
663secure channel. What happens is that whenever a connection is made to
664the port on the server, a connection will be made from the client end
665to the specified host/port. Any user can forward unprivileged ports;
666only the root can forward privileged ports (as determined by
667authentication done earlier).
668.IP SSH_CMSG_AGENT_REQUEST_FORWARDING
669Requests forwarding of the connection to the authentication agent.
670.IP SSH_CMSG_EXEC_SHELL
671Starts a shell (command interpreter) for the user, and moves into
672interactive session mode.
673.IP SSH_CMSG_EXEC_CMD
674Executes the given command (actually "<shell> -c <command>" or
675equivalent) for the user, and moves into interactive session mode.
676.RT
677
678
679.ti 0
680Interactive Session and Exchange of Data
681
682During the interactive session, any data written by the shell or
683command running on the server machine is forwarded to stdin or
684stderr on the client machine, and any input available from stdin on
685the client machine is forwarded to the program on the server machine.
686
687All exchange is asynchronous; either side can send at any time, and
688there are no acknowledgements (TCP/IP already provides reliable
689transport, and the packet protocol protects against tampering or IP
690spoofing).
691
692When the client receives EOF from its standard input, it will send
693SSH_CMSG_EOF; however, this in no way terminates the exchange. The
694exchange terminates and interactive mode is left when the server sends
695SSH_SMSG_EXITSTATUS to indicate that the client program has
696terminated. Alternatively, either side may disconnect at any time by
697sending SSH_MSG_DISCONNECT or closing the connection.
698
699The server may send any of the following messages:
700.IP SSH_SMSG_STDOUT_DATA
701Data written to stdout by the program running on the server. The data
702is passed as a string argument. The client writes this data to
703stdout.
704.IP SSH_SMSG_STDERR_DATA
705Data written to stderr by the program running on the server. The data
706is passed as a string argument. The client writes this data to
707stderr. (Note that if the program is running on a tty, it is not
708possible to separate stdout and stderr data, and all data will be sent
709as stdout data.)
710.IP SSH_SMSG_EXITSTATUS
711Indicates that the shell or command has exited. Exit status is passed
712as an integer argument. This message causes termination of the
713interactive session.
714.IP SSH_SMSG_AGENT_OPEN
715Indicates that someone on the server side is requesting a connection
716to the authentication agent. The server-side channel number is passed
717as an argument. The client must respond with either
718SSH_CHANNEL_OPEN_CONFIRMATION or SSH_CHANNEL_OPEN_FAILURE.
719.IP SSH_SMSG_X11_OPEN
720Indicates that a connection has been made to the X11 socket on the
721server side and should be forwarded to the real X server. An integer
722argument indicates the channel number allocated for this connection on
723the server side. The client should send back either
724SSH_MSG_CHANNEL_OPEN_CONFIRMATION or SSH_MSG_CHANNEL_OPEN_FAILURE with
725the same server side channel number.
726.IP SSH_MSG_PORT_OPEN
727Indicates that a connection has been made to a port on the server side
728for which forwarding has been requested. Arguments are server side
729channel number, host name to connect to, and port to connect to. The
730client should send back either
731SSH_MSG_CHANNEL_OPEN_CONFIRMATION or SSH_MSG_CHANNEL_OPEN_FAILURE with
732the same server side channel number.
733.IP SSH_MSG_CHANNEL_OPEN_CONFIRMATION
734This is sent by the server to indicate that it has opened a connection
735as requested in a previous message. The first argument indicates the
736client side channel number, and the second argument is the channel number
737that the server has allocated for this connection.
738.IP SSH_MSG_CHANNEL_OPEN_FAILURE
739This is sent by the server to indicate that it failed to open a
740connection as requested in a previous message. The client-side
741channel number is passed as an argument. The client will close the
742descriptor associated with the channel and free the channel.
743.IP SSH_MSG_CHANNEL_DATA
744This packet contains data for a channel from the server. The first
745argument is the client-side channel number, and the second argument (a
746string) is the data.
747.IP SSH_MSG_CHANNEL_CLOSE
748This is sent by the server to indicate that whoever was in the other
749end of the channel has closed it. The argument is the client side channel
750number. The client will let all buffered data in the channel to
751drain, and when ready, will close the socket, free the channel, and
752send the server a SSH_MSG_CHANNEL_CLOSE_CONFIRMATION message for the
753channel.
754.IP SSH_MSG_CHANNEL_CLOSE_CONFIRMATION
755This is send by the server to indicate that a channel previously
756closed by the client has now been closed on the server side as well.
757The argument indicates the client channel number. The client frees
758the channel.
759.RT
760
761The client may send any of the following messages:
762.IP SSH_CMSG_STDIN_DATA
763This is data to be sent as input to the program running on the server.
764The data is passed as a string.
765.IP SSH_CMSG_EOF
766Indicates that the client has encountered EOF while reading standard
767input. The server will allow any buffered input data to drain, and
768will then close the input to the program.
769.IP SSH_CMSG_WINDOW_SIZE
770Indicates that window size on the client has been changed. The server
771updates the window size of the tty and causes SIGWINCH to be sent to
772the program. The new window size is passed as four integer arguments:
773row, col, xpixel, ypixel.
774.IP SSH_MSG_PORT_OPEN
775Indicates that a connection has been made to a port on the client side
776for which forwarding has been requested. Arguments are client side
777channel number, host name to connect to, and port to connect to. The
778server should send back either SSH_MSG_CHANNEL_OPEN_CONFIRMATION or
779SSH_MSG_CHANNEL_OPEN_FAILURE with the same client side channel number.
780.IP SSH_MSG_CHANNEL_OPEN_CONFIRMATION
781This is sent by the client to indicate that it has opened a connection
782as requested in a previous message. The first argument indicates the
783server side channel number, and the second argument is the channel
784number that the client has allocated for this connection.
785.IP SSH_MSG_CHANNEL_OPEN_FAILURE
786This is sent by the client to indicate that it failed to open a
787connection as requested in a previous message. The server side
788channel number is passed as an argument. The server will close the
789descriptor associated with the channel and free the channel.
790.IP SSH_MSG_CHANNEL_DATA
791This packet contains data for a channel from the client. The first
792argument is the server side channel number, and the second argument (a
793string) is the data.
794.IP SSH_MSG_CHANNEL_CLOSE
795This is sent by the client to indicate that whoever was in the other
796end of the channel has closed it. The argument is the server channel
797number. The server will allow buffered data to drain, and when ready,
798will close the socket, free the channel, and send the client a
799SSH_MSG_CHANNEL_CLOSE_CONFIRMATION message for the channel.
800.IP SSH_MSG_CHANNEL_CLOSE_CONFIRMATION
801This is send by the client to indicate that a channel previously
802closed by the server has now been closed on the client side as well.
803The argument indicates the server channel number. The server frees
804the channel.
805.RT
806
807Any unsupported messages during interactive mode cause the connection
808to be terminated with SSH_MSG_DISCONNECT and an error message.
809Compatible protocol upgrades should agree about any extensions during
810the preparation phase or earlier.
811
812
813.ti 0
814Termination of the Connection
815
816Normal termination of the connection is always initiated by the server
817by sending SSH_SMSG_EXITSTATUS after the program has exited. The
818client responds to this message by sending SSH_CMSG_EXIT_CONFIRMATION
819and closes the socket; the server then closes the socket. There are
820two purposes for the confirmation: some systems may lose previously
821sent data when the socket is closed, and closing the client side first
822causes any TCP/IP TIME_WAIT [RFC0793] waits to occur on the client side, not
823consuming server resources.
824
825If the program terminates due to a signal, the server will send
826SSH_MSG_DISCONNECT with an appropriate message. If the connection is
827closed, all file descriptors to the program will be closed and the
828server will exit. If the program runs on a tty, the kernel sends it
829the SIGHUP signal when the pty master side is closed.
830
831.ti 0
832Protocol Flags
833
834Both the server and the client pass 32 bits of protocol flags to the
835other side. The flags are intended for compatible protocol extension;
836the server first announces which added capabilities it supports, and
837the client then sends the capabilities that it supports.
838
839The following flags are currently defined (the values are bit masks):
840.IP "1 SSH_PROTOFLAG_SCREEN_NUMBER"
841This flag can only be sent by the client. It indicates that the X11
842forwarding requests it sends will include the screen number.
843.IP "2 SSH_PROTOFLAG_HOST_IN_FWD_OPEN"
844If both sides specify this flag, SSH_SMSG_X11_OPEN and
845SSH_MSG_PORT_OPEN messages will contain an additional field containing
846a description of the host at the other end of the connection.
847.RT
848
849.ti 0
850Detailed Description of Packet Types and Formats
851
852The supported packet types and the corresponding message numbers are
853given in the following table. Messages with _MSG_ in their name may
854be sent by either side. Messages with _CMSG_ are only sent by the
855client, and messages with _SMSG_ only by the server.
856
857A packet may contain additional data after the arguments specified
858below. Any such data should be ignored by the receiver. However, it
859is recommended that no such data be stored without good reason. (This
860helps build compatible extensions.)
861.IP "0 SSH_MSG_NONE"
862This code is reserved. This message type is never sent.
863.IP "1 SSH_MSG_DISCONNECT"
864.TS
865;
866l l.
867string Cause of disconnection
868.TE
869This message may be sent by either party at any time. It causes the
870immediate disconnection of the connection. The message is intended to
871be displayed to a human, and describes the reason for disconnection.
872.IP "2 SSH_SMSG_PUBLIC_KEY"
873.TS
874;
875l l.
8768 bytes anti_spoofing_cookie
87732-bit int server_key_bits
878mp-int server_key_public_exponent
879mp-int server_key_public_modulus
88032-bit int host_key_bits
881mp-int host_key_public_exponent
882mp-int host_key_public_modulus
88332-bit int protocol_flags
88432-bit int supported_ciphers_mask
88532-bit int supported_authentications_mask
886.TE
887Sent as the first message by the server. This message gives the
888server's host key, server key, protocol flags (intended for compatible
889protocol extension), supported_ciphers_mask (which is the
890bitwise or of (1 << cipher_number), where << is the left shift
891operator, for all supported ciphers), and
892supported_authentications_mask (which is the bitwise or of (1 <<
893authentication_type) for all supported authentication types). The
894anti_spoofing_cookie is 64 random bytes, and must be sent back
895verbatim by the client in its reply. It is used to make IP-spoofing
896more difficult (encryption and host keys are the real defense against
897spoofing).
898.IP "3 SSH_CMSG_SESSION_KEY"
899.TS
900;
901l l.
9021 byte cipher_type (must be one of the supported values)
9038 bytes anti_spoofing_cookie (must match data sent by the server)
904mp-int double-encrypted session key
90532-bit int protocol_flags
906.TE
907Sent by the client as the first message in the session. Selects the
908cipher to use, and sends the encrypted session key to the server. The
909anti_spoofing_cookie must be the same bytes that were sent by the
910server. Protocol_flags is intended for negotiating compatible
911protocol extensions.
912.IP "4 SSH_CMSG_USER"
913.TS
914;
915l l.
916string user login name on server
917.TE
918Sent by the client to begin authentication. Specifies the user name
919on the server to log in as. The server responds with SSH_SMSG_SUCCESS
920if no authentication is needed for this user, or SSH_SMSG_FAILURE if
921authentication is needed (or the user does not exist). [Note to the
922implementator: the user name is of arbitrary size. The implementation
923must be careful not to overflow internal buffers.]
924.IP "5 SSH_CMSG_AUTH_RHOSTS"
925.TS
926;
927l l.
928string client-side user name
929.TE
930Requests authentication using /etc/hosts.equiv and .rhosts (or
931equivalent mechanisms). This authentication method is normally
932disabled in the server because it is not secure (but this is the
933method used by rsh and rlogin). The server responds with
934SSH_SMSG_SUCCESS if authentication was successful, and
935SSH_SMSG_FAILURE if access was not granted. The server should check
936that the client side port number is less than 1024 (a privileged
937port), and immediately reject authentication if it is not. Supporting
938this authentication method is optional. This method should normally
939not be enabled in the server because it is not safe. (However, not
940enabling this only helps if rlogind and rshd are disabled.)
941.IP "6 SSH_CMSG_AUTH_RSA"
942.TS
943;
944l l.
945mp-int identity_public_modulus
946.TE
947Requests authentication using pure RSA authentication. The server
948checks if the given key is permitted to log in, and if so, responds
949with SSH_SMSG_AUTH_RSA_CHALLENGE. Otherwise, it responds with
950SSH_SMSG_FAILURE. The client often tries several different keys in
951sequence until one supported by the server is found. Authentication
952is accepted if the client gives the correct response to the challenge.
953The server is free to add other criteria for authentication, such as a
954requirement that the connection must come from a certain host. Such
955additions are not visible at the protocol level. Supporting this
956authentication method is optional but recommended.
957.IP "7 SSH_SMSG_AUTH_RSA_CHALLENGE"
958.TS
959;
960l l.
961mp-int encrypted challenge
962.TE
963Presents an RSA authentication challenge to the client. The challenge
964is a 256-bit random value encrypted as described elsewhere in this
965document. The client must decrypt the challenge using the RSA private
966key, compute MD5 of the challenge plus session id, and send back the
967resulting 16 bytes using SSH_CMSG_AUTH_RSA_RESPONSE.
968.IP "8 SSH_CMSG_AUTH_RSA_RESPONSE"
969.TS
970;
971l l.
97216 bytes MD5 of decrypted challenge
973.TE
974This message is sent by the client in response to an RSA challenge.
975The MD5 checksum is returned instead of the decrypted challenge to
976deter known-plaintext attacks against the RSA key. The server
977responds to this message with either SSH_SMSG_SUCCESS or
978SSH_SMSG_FAILURE.
979.IP "9 SSH_CMSG_AUTH_PASSWORD"
980.TS
981;
982l l.
983string plain text password
984.TE
985Requests password authentication using the given password. Note that
986even though the password is plain text inside the packet, the whole
987packet is normally encrypted by the packet layer. It would not be
988possible for the client to perform password encryption/hashing,
989because it cannot know which kind of encryption/hashing, if any, the
990server uses. The server responds to this message with
991SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE.
992.IP "10 SSH_CMSG_REQUEST_PTY"
993.TS
994;
995l l.
996string TERM environment variable value (e.g. vt100)
99732-bit int terminal height, rows (e.g., 24)
99832-bit int terminal width, columns (e.g., 80)
99932-bit int terminal width, pixels (0 if no graphics) (e.g., 480)
100032-bit int terminal height, pixels (0 if no graphics) (e.g., 640)
1001n bytes tty modes encoded in binary
1002.TE
1003Requests a pseudo-terminal to be allocated for this command. This
1004message can be used regardless of whether the session will later
1005execute the shell or a command. If a pty has been requested with this
1006message, the shell or command will run on a pty. Otherwise it will
1007communicate with the server using pipes, sockets or some other similar
1008mechanism.
1009
1010The terminal type gives the type of the user's terminal. In the UNIX
1011environment it is passed to the shell or command in the TERM
1012environment variable.
1013
1014The width and height values give the initial size of the user's
1015terminal or window. All values can be zero if not supported by the
1016operating system. The server will pass these values to the kernel if
1017supported.
1018
1019Terminal modes are encoded into a byte stream in a portable format.
1020The exact format is described later in this document.
1021
1022The server responds to the request with either SSH_SMSG_SUCCESS or
1023SSH_SMSG_FAILURE. If the server does not have the concept of pseudo
1024terminals, it should return success if it is possible to execute a
1025shell or a command so that it looks to the client as if it was running
1026on a pseudo terminal.
1027.IP "11 SSH_CMSG_WINDOW_SIZE"
1028.TS
1029;
1030l l.
103132-bit int terminal height, rows
103232-bit int terminal width, columns
103332-bit int terminal width, pixels
103432-bit int terminal height, pixels
1035.TE
1036This message can only be sent by the client during the interactive
1037session. This indicates that the size of the user's window has
1038changed, and provides the new size. The server will update the
1039kernel's notion of the window size, and a SIGWINCH signal or
1040equivalent will be sent to the shell or command (if supported by the
1041operating system).
1042.IP "12 SSH_CMSG_EXEC_SHELL"
1043
1044(no arguments)
1045
1046Starts a shell (command interpreter), and enters interactive session
1047mode.
1048.IP "13 SSH_CMSG_EXEC_CMD"
1049.TS
1050;
1051l l.
1052string command to execute
1053.TE
1054Starts executing the given command, and enters interactive session
1055mode. On UNIX, the command is run as "<shell> -c <command>", where
1056<shell> is the user's login shell.
1057.IP "14 SSH_SMSG_SUCCESS"
1058
1059(no arguments)
1060
1061This message is sent by the server in response to the session key, a
1062successful authentication request, and a successfully completed
1063preparatory operation.
1064.IP "15 SSH_SMSG_FAILURE"
1065
1066(no arguments)
1067
1068This message is sent by the server in response to a failed
1069authentication operation to indicate that the user has not yet been
1070successfully authenticated, and in response to a failed preparatory
1071operation. This is also sent in response to an authentication or
1072preparatory operation request that is not recognized or supported.
1073.IP "16 SSH_CMSG_STDIN_DATA"
1074.TS
1075;
1076l l.
1077string data
1078.TE
1079Delivers data from the client to be supplied as input to the shell or
1080program running on the server side. This message can only be used in
1081the interactive session mode. No acknowledgement is sent for this
1082message.
1083.IP "17 SSH_SMSG_STDOUT_DATA"
1084.TS
1085;
1086l l.
1087string data
1088.TE
1089Delivers data from the server that was read from the standard output of
1090the shell or program running on the server side. This message can
1091only be used in the interactive session mode. No acknowledgement is
1092sent for this message.
1093.IP "18 SSH_SMSG_STDERR_DATA"
1094.TS
1095;
1096l l.
1097string data
1098.TE
1099Delivers data from the server that was read from the standard error of
1100the shell or program running on the server side. This message can
1101only be used in the interactive session mode. No acknowledgement is
1102sent for this message.
1103.IP "19 SSH_CMSG_EOF"
1104
1105(no arguments)
1106
1107This message is sent by the client to indicate that EOF has been
1108reached on the input. Upon receiving this message, and after all
1109buffered input data has been sent to the shell or program, the server
1110will close the input file descriptor to the program. This message can
1111only be used in the interactive session mode. No acknowledgement is
1112sent for this message.
1113.IP "20 SSH_SMSG_EXITSTATUS"
1114.TS
1115;
1116l l.
111732-bit int exit status of the command
1118.TE
1119Returns the exit status of the shell or program after it has exited.
1120The client should respond with SSH_CMSG_EXIT_CONFIRMATION when it has
1121received this message. This will be the last message sent by the
1122server. If the program being executed dies with a signal instead of
1123exiting normally, the server should terminate the session with
1124SSH_MSG_DISCONNECT (which can be used to pass a human-readable string
1125indicating that the program died due to a signal) instead of using
1126this message.
1127.IP "21 SSH_MSG_CHANNEL_OPEN_CONFIRMATION"
1128.TS
1129;
1130l l.
113132-bit int remote_channel
113232-bit int local_channel
1133.TE
1134This is sent in response to any channel open request if the channel
1135has been successfully opened. Remote_channel is the channel number
1136received in the initial open request; local_channel is the channel
1137number the side sending this message has allocated for the channel.
1138Data can be transmitted on the channel after this message.
1139.IP "22 SSH_MSG_CHANNEL_OPEN_FAILURE"
1140.TS
1141;
1142l l.
114332-bit int remote_channel
1144.TE
1145This message indicates that an earlier channel open request by the
1146other side has failed or has been denied. Remote_channel is the
1147channel number given in the original request.
1148.IP "23 SSH_MSG_CHANNEL_DATA"
1149.TS
1150;
1151l l.
115232-bit int remote_channel
1153string data
1154.TE
1155Data is transmitted in a channel in these messages. A channel is
1156bidirectional, and both sides can send these messages. There is no
1157acknowledgement for these messages. It is possible that either side
1158receives these messages after it has sent SSH_MSG_CHANNEL_CLOSE for
1159the channel. These messages cannot be received after the party has
1160sent or received SSH_MSG_CHANNEL_CLOSE_CONFIRMATION.
1161.IP "24 SSH_MSG_CHANNEL_CLOSE"
1162.TS
1163;
1164l l.
116532-bit int remote_channel
1166.TE
1167When a channel is closed at one end of the connection, that side sends
1168this message. Upon receiving this message, the channel should be
1169closed. When this message is received, if the channel is already
1170closed (the receiving side has sent this message for the same channel
1171earlier), the channel is freed and no further action is taken;
1172otherwise the channel is freed and SSH_MSG_CHANNEL_CLOSE_CONFIRMATION
1173is sent in response. (It is possible that the channel is closed
1174simultaneously at both ends.)
1175.IP "25 SSH_MSG_CHANNEL_CLOSE_CONFIRMATION"
1176.TS
1177;
1178l l.
117932-bit int remote_channel
1180.TE
1181This message is sent in response to SSH_MSG_CHANNEL_CLOSE unless the
1182channel was already closed. When this message is sent or received,
1183the channel is freed.
1184.IP "26 (OBSOLETED; was unix-domain X11 forwarding)
1185.IP "27 SSH_SMSG_X11_OPEN"
1186.TS
1187;
1188l l.
118932-bit int local_channel
1190string originator_string (see below)
1191.TE
1192This message can be sent by the server during the interactive session
1193mode to indicate that a client has connected the fake X server.
1194Local_channel is the channel number that the server has allocated for
1195the connection. The client should try to open a connection to the
1196real X server, and respond with SSH_MSG_CHANNEL_OPEN_CONFIRMATION or
1197SSH_MSG_CHANNEL_OPEN_FAILURE.
1198
1199The field originator_string is present if both sides
1200specified SSH_PROTOFLAG_HOST_IN_FWD_OPEN in the protocol flags. It
1201contains a description of the host originating the connection.
1202.IP "28 SSH_CMSG_PORT_FORWARD_REQUEST"
1203.TS
1204;
1205l l.
120632-bit int server_port
1207string host_to_connect
120832-bit int port_to_connect
1209.TE
1210Sent by the client in the preparatory phase, this message requests
1211that server_port on the server machine be forwarded over the secure
1212channel to the client machine, and from there to the specified host
1213and port. The server should start listening on the port, and send
1214SSH_MSG_PORT_OPEN whenever a connection is made to it. Supporting
1215this message is optional, and the server is free to reject any forward
1216request. For example, it is highly recommended that unless the user
1217has been authenticated as root, forwarding any privileged port numbers
1218(below 1024) is denied.
1219.IP "29 SSH_MSG_PORT_OPEN"
1220.TS
1221;
1222l l.
122332-bit int local_channel
1224string host_name
122532-bit int port
1226string originator_string (see below)
1227.TE
1228Sent by either party in interactive session mode, this message
1229indicates that a connection has been opened to a forwarded TCP/IP
1230port. Local_channel is the channel number that the sending party has
1231allocated for the connection. Host_name is the host the connection
1232should be be forwarded to, and the port is the port on that host to
1233connect. The receiving party should open the connection, and respond
1234with SSH_MSG_CHANNEL_OPEN_CONFIRMATION or
1235SSH_MSG_CHANNEL_OPEN_FAILURE. It is recommended that the receiving
1236side check the host_name and port for validity to avoid compromising
1237local security by compromised remote side software. Particularly, it
1238is recommended that the client permit connections only to those ports
1239for which it has requested forwarding with SSH_CMSG_PORT_FORWARD_REQUEST.
1240
1241The field originator_string is present if both sides
1242specified SSH_PROTOFLAG_HOST_IN_FWD_OPEN in the protocol flags. It
1243contains a description of the host originating the connection.
1244.IP "30 SSH_CMSG_AGENT_REQUEST_FORWARDING"
1245
1246(no arguments)
1247
1248Requests that the connection to the authentication agent be forwarded
1249over the secure channel. The method used by clients to contact the
1250authentication agent within each machine is implementation and machine
1251dependent. If the server accepts this request, it should arrange that
1252any clients run from this session will actually contact the server
1253program when they try to contact the authentication agent. The server
1254should then send a SSH_SMSG_AGENT_OPEN to open a channel to the agent,
1255and the client should forward the connection to the real
1256authentication agent. Supporting this message is optional.
1257.IP "31 SSH_SMSG_AGENT_OPEN"
1258.TS
1259;
1260l l.
126132-bit int local_channel
1262.TE
1263Sent by the server in interactive session mode, this message requests
1264opening a channel to the authentication agent. The client should open
1265a channel, and respond with either SSH_MSG_CHANNEL_OPEN_CONFIRMATION
1266or SSH_MSG_CHANNEL_OPEN_FAILURE.
1267.IP "32 SSH_MSG_IGNORE"
1268.TS
1269;
1270l l.
1271string data
1272.TE
1273Either party may send this message at any time. This message, and the
1274argument string, is silently ignored. This message might be used in
1275some implementations to make traffic analysis more difficult. This
1276message is not currently sent by the implementation, but all
1277implementations are required to recognize and ignore it.
1278.IP "33 SSH_CMSG_EXIT_CONFIRMATION"
1279
1280(no arguments)
1281
1282Sent by the client in response to SSH_SMSG_EXITSTATUS. This is the
1283last message sent by the client.
1284.IP "34 SSH_CMSG_X11_REQUEST_FORWARDING"
1285.TS
1286;
1287l l.
1288string x11_authentication_protocol
1289string x11_authentication_data
129032-bit int screen number (if SSH_PROTOFLAG_SCREEN_NUMBER)
1291.TE
1292Sent by the client during the preparatory phase, this message requests
1293that the server create a fake X11 display and set the DISPLAY
1294environment variable accordingly. An internet-domain display is
1295preferable. The given authentication protocol and the associated data
1296should be recorded by the server so that it is used as authentication
1297on connections (e.g., in .Xauthority). The authentication protocol
1298must be one of the supported X11 authentication protocols, e.g.,
1299"MIT-MAGIC-COOKIE-1". Authentication data must be a lowercase hex
1300string of even length. Its interpretation is protocol dependent.
1301The data is in a format that can be used with e.g. the xauth program.
1302Supporting this message is optional.
1303
1304The client is permitted (and recommended) to generate fake
1305authentication information and send fake information to the server.
1306This way, a corrupt server will not have access to the user's terminal
1307after the connection has terminated. The correct authorization codes
1308will also not be left hanging around in files on the server (many
1309users keep the same X session for months, thus protecting the
1310authorization data becomes important).
1311
1312X11 authentication spoofing works by initially sending fake (random)
1313authentication data to the server, and interpreting the first packet
1314sent by the X11 client after the connection has been opened. The
1315first packet contains the client's authentication. If the packet
1316contains the correct fake data, it is replaced by the client by the
1317correct authentication data, and then sent to the X server.
1318.IP "35 SSH_CMSG_AUTH_RHOSTS_RSA"
1319.TS
1320;
1321l l.
1322string clint-side user name
132332-bit int client_host_key_bits
1324mp-int client_host_key_public_exponent
1325mp-int client_host_key_public_modulus
1326.TE
1327Requests authentication using /etc/hosts.equiv and .rhosts (or
1328equivalent) together with RSA host authentication. The server should
1329check that the client side port number is less than 1024 (a privileged
1330port), and immediately reject authentication if it is not. The server
1331responds with SSH_SMSG_FAILURE or SSH_SMSG_AUTH_RSA_CHALLENGE. The
1332client must respond to the challenge with the proper
1333SSH_CMSG_AUTH_RSA_RESPONSE. The server then responds with success if
1334access was granted, or failure if the client gave a wrong response.
1335Supporting this authentication method is optional but recommended in
1336most environments.
1337.IP "36 SSH_MSG_DEBUG"
1338.TS
1339;
1340l l.
1341string debugging message sent to the other side
1342.TE
1343This message may be sent by either party at any time. It is used to
1344send debugging messages that may be informative to the user in
1345solving various problems. For example, if authentication fails
1346because of some configuration error (e.g., incorrect permissions for
1347some file), it can be very helpful for the user to make the cause of
1348failure available. On the other hand, one should not make too much
1349information available for security reasons. It is recommended that
1350the client provides an option to display the debugging information
1351sent by the sender (the user probably does not want to see it by default).
1352The server can log debugging data sent by the client (if any). Either
1353party is free to ignore any received debugging data. Every
1354implementation must be able to receive this message, but no
1355implementation is required to send these.
1356.IP "37 SSH_CMSG_REQUEST_COMPRESSION"
1357.TS
1358;
1359l l.
136032-bit int gzip compression level (1-9)
1361.TE
1362This message can be sent by the client in the preparatory operations
1363phase. The server responds with SSH_SMSG_FAILURE if it does not
1364support compression or does not want to compress; it responds with
1365SSH_SMSG_SUCCESS if it accepted the compression request. In the
1366latter case the response to this packet will still be uncompressed,
1367but all further packets in either direction will be compressed by gzip.
1368.RT
1369
1370
1371.ti 0
1372Encoding of Terminal Modes
1373
1374Terminal modes (as passed in SSH_CMSG_REQUEST_PTY) are encoded into a
1375byte stream. It is intended that the coding be portable across
1376different environments.
1377
1378The tty mode description is a stream of bytes. The stream consists of
1379opcode-argument pairs. It is terminated by opcode TTY_OP_END (0).
1380Opcodes 1-127 have one-byte arguments. Opcodes 128-159 have 32-bit
1381integer arguments (stored msb first). Opcodes 160-255 are not yet
1382defined, and cause parsing to stop (they should only be used after any
1383other data).
1384
1385The client puts in the stream any modes it knows about, and the server
1386ignores any modes it does not know about. This allows some degree of
1387machine-independence, at least between systems that use a POSIX-like
1388[POSIX] tty interface. The protocol can support other systems as
1389well, but the client may need to fill reasonable values for a number
1390of parameters so the server pty gets set to a reasonable mode (the
1391server leaves all unspecified mode bits in their default values, and
1392only some combinations make sense).
1393
1394The following opcodes have been defined. The naming of opcodes mostly
1395follows the POSIX terminal mode flags.
1396.IP "0 TTY_OP_END"
1397Indicates end of options.
1398.IP "1 VINTR"
1399Interrupt character; 255 if none. Similarly for the other characters.
1400Not all of these characters are supported on all systems.
1401.IP "2 VQUIT"
1402The quit character (sends SIGQUIT signal on UNIX systems).
1403.IP "3 VERASE"
1404Erase the character to left of the cursor.
1405.IP "4 VKILL"
1406Kill the current input line.
1407.IP "5 VEOF "
1408End-of-file character (sends EOF from the terminal).
1409.IP "6 VEOL "
1410End-of-line character in addition to carriage return and/or linefeed.
1411.IP "7 VEOL2"
1412Additional end-of-line character.
1413.IP "8 VSTART"
1414Continues paused output (normally ^Q).
1415.IP "9 VSTOP"
1416Pauses output (^S).
1417.IP "10 VSUSP"
1418Suspends the current program.
1419.IP "11 VDSUSP"
1420Another suspend character.
1421.IP "12 VREPRINT"
1422Reprints the current input line.
1423.IP "13 VWERASE"
1424Erases a word left of cursor.
1425.IP "14 VLNEXT"
1426More special input characters; these are probably not supported on
1427most systems.
1428.IP "15 VFLUSH"
1429.IP "16 VSWTCH"
1430.IP "17 VSTATUS"
1431.IP "18 VDISCARD"
1432
1433.IP "30 IGNPAR"
1434The ignore parity flag. The next byte should be 0 if this flag is not
1435set, and 1 if it is set.
1436.IP "31 PARMRK"
1437More flags. The exact definitions can be found in the POSIX standard.
1438.IP "32 INPCK"
1439.IP "33 ISTRIP"
1440.IP "34 INLCR"
1441.IP "35 IGNCR"
1442.IP "36 ICRNL"
1443.IP "37 IUCLC"
1444.IP "38 IXON"
1445.IP "39 IXANY"
1446.IP "40 IXOFF"
1447.IP "41 IMAXBEL"
1448
1449.IP "50 ISIG"
1450.IP "51 ICANON"
1451.IP "52 XCASE"
1452.IP "53 ECHO"
1453.IP "54 ECHOE"
1454.IP "55 ECHOK"
1455.IP "56 ECHONL"
1456.IP "57 NOFLSH"
1457.IP "58 TOSTOP"
1458.IP "59 IEXTEN"
1459.IP "60 ECHOCTL"
1460.IP "61 ECHOKE"
1461.IP "62 PENDIN"
1462
1463.IP "70 OPOST"
1464.IP "71 OLCUC"
1465.IP "72 ONLCR"
1466.IP "73 OCRNL"
1467.IP "74 ONOCR"
1468.IP "75 ONLRET"
1469
1470.IP "90 CS7"
1471.IP "91 CS8"
1472.IP "92 PARENB"
1473.IP "93 PARODD"
1474
1475.IP "192 TTY_OP_ISPEED"
1476Specifies the input baud rate in bits per second.
1477.IP "193 TTY_OP_OSPEED"
1478Specifies the output baud rate in bits per second.
1479.RT
1480
1481
1482.ti 0
1483The Authentication Agent Protocol
1484
1485The authentication agent is a program that can be used to hold RSA
1486authentication keys for the user (in future, it might hold data for
1487other authentication types as well). An authorized program can send
1488requests to the agent to generate a proper response to an RSA
1489challenge. How the connection is made to the agent (or its
1490representative) inside a host and how access control is done inside a
1491host is implementation-dependent; however, how it is forwarded and how
1492one interacts with it is specified in this protocol. The connection
1493to the agent is normally automatically forwarded over the secure
1494channel.
1495
1496A program that wishes to use the agent first opens a connection to its
1497local representative (typically, the agent itself or an SSH server).
1498It then writes a request to the connection, and waits for response.
1499It is recommended that at least five minutes of timeout are provided
1500waiting for the agent to respond to an authentication challenge (this
1501gives sufficient time for the user to cut-and-paste the challenge to a
1502separate machine, perform the computation there, and cut-and-paste the
1503result back if so desired).
1504
1505Messages sent to and by the agent are in the following format:
1506.TS
1507;
1508l l.
15094 bytes Length, msb first. Does not include length itself.
15101 byte Packet type. The value 255 is reserved for future extensions.
1511data Any data, depending on packet type. Encoding as in the ssh packet
1512protocol.
1513.TE
1514
1515The following message types are currently defined:
1516.IP "1 SSH_AGENTC_REQUEST_RSA_IDENTITIES"
1517
1518(no arguments)
1519
1520Requests the agent to send a list of all RSA keys for which it can
1521answer a challenge.
1522.IP "2 SSH_AGENT_RSA_IDENTITIES_ANSWER"
1523.TS
1524;
1525l l.
152632-bit int howmany
1527howmany times:
152832-bit int bits
1529mp-int public exponent
1530mp-int public modulus
1531string comment
1532.TE
1533The agent sends this message in response to the to
1534SSH_AGENTC_REQUEST_RSA_IDENTITIES. The answer lists all RSA keys for
1535which the agent can answer a challenge. The comment field is intended
1536to help identify each key; it may be printed by an application to
1537indicate which key is being used. If the agent is not holding any
1538keys, howmany will be zero.
1539.IP "3 SSH_AGENTC_RSA_CHALLENGE
1540.TS
1541;
1542l l.
154332-bit int bits
1544mp-int public exponent
1545mp-int public modulus
1546mp-int challenge
154716 bytes session_id
154832-bit int response_type
1549.TE
1550Requests RSA decryption of random challenge to authenticate the other
1551side. The challenge will be decrypted with the RSA private key
1552corresponding to the given public key.
1553
1554The decrypted challenge must contain a zero in the highest (partial)
1555byte, 2 in the next byte, followed by non-zero random bytes, a zero
1556byte, and then the real challenge value in the lowermost bytes. The
1557real challenge must be 32 8-bit bytes (256 bits).
1558
1559Response_type indicates the format of the response to be returned.
1560Currently the only supported value is 1, which means to compute MD5 of
1561the real challenge plus session id, and return the resulting 16 bytes
1562in a SSH_AGENT_RSA_RESPONSE message.
1563.IP "4 SSH_AGENT_RSA_RESPONSE"
1564.TS
1565;
1566l l.
156716 bytes MD5 of decrypted challenge
1568.TE
1569Answers an RSA authentication challenge. The response is 16 bytes:
1570the MD5 checksum of the 32-byte challenge.
1571.IP "5 SSH_AGENT_FAILURE"
1572
1573(no arguments)
1574
1575This message is sent whenever the agent fails to answer a request
1576properly. For example, if the agent cannot answer a challenge (e.g.,
1577no longer has the proper key), it can respond with this. The agent
1578also responds with this message if it receives a message it does not
1579recognize.
1580.IP "6 SSH_AGENT_SUCCESS"
1581
1582(no arguments)
1583
1584This message is sent by the agent as a response to certain requests
1585that do not otherwise cause a message be sent. Currently, this is
1586only sent in response to SSH_AGENTC_ADD_RSA_IDENTITY and
1587SSH_AGENTC_REMOVE_RSA_IDENTITY.
1588.IP "7 SSH_AGENTC_ADD_RSA_IDENTITY"
1589.TS
1590;
1591l l.
159232-bit int bits
1593mp-int public modulus
1594mp-int public exponent
1595mp-int private exponent
1596mp-int multiplicative inverse of p mod q
1597mp-int p
1598mp-int q
1599string comment
1600.TE
1601Registers an RSA key with the agent. After this request, the agent can
1602use this RSA key to answer requests. The agent responds with
1603SSH_AGENT_SUCCESS or SSH_AGENT_FAILURE.
1604.IP "8 SSH_AGENT_REMOVE_RSA_IDENTITY"
1605.TS
1606;
1607l l.
160832-bit int bits
1609mp-int public exponent
1610mp-int public modulus
1611.TE
1612Removes an RSA key from the agent. The agent will no longer accept
1613challenges for this key and will not list it as a supported identity.
1614The agent responds with SSH_AGENT_SUCCESS or SSH_AGENT_FAILURE.
1615.RT
1616
1617If the agent receives a message that it does not understand, it
1618responds with SSH_AGENT_FAILURE. This permits compatible future
1619extensions.
1620
1621It is possible that several clients have a connection open to the
1622authentication agent simultaneously. Each client will use a separate
1623connection (thus, any SSH connection can have multiple agent
1624connections active simultaneously).
1625
1626
1627.ti 0
1628References
1629
1630.IP "[DES] "
1631FIPS PUB 46-1: Data Encryption Standard. National Bureau of
1632Standards, January 1988. FIPS PUB 81: DES Modes of Operation.
1633National Bureau of Standards, December 1980. Bruce Schneier: Applied
1634Cryptography. John Wiley & Sons, 1994. J. Seberry and J. Pieprzyk:
1635Cryptography: An Introduction to Computer Security. Prentice-Hall,
16361989.
1637.IP "[GZIP] "
1638The GNU GZIP program; available for anonymous ftp at prep.ai.mit.edu.
1639Please let me know if you know a paper describing the algorithm.
1640.IP "[IDEA] "
1641Xuejia Lai: On the Design and Security of Block Ciphers, ETH Series in
1642Information Processing, vol. 1, Hartung-Gorre Verlag, Konstanz,
1643Switzerland, 1992. Bruce Schneier: Applied Cryptography, John Wiley &
1644Sons, 1994. See also the following patents: PCT/CH91/00117, EP 0 482
1645154 B1, US Pat. 5,214,703.
1646.IP [PKCS#1]
1647PKCS #1: RSA Encryption Standard. Version 1.5, RSA Laboratories,
1648November 1993. Available for anonymous ftp at ftp.rsa.com.
1649.IP [POSIX]
1650Portable Operating System Interface (POSIX) - Part 1: Application
1651Program Interface (API) [C language], ISO/IEC 9945-1, IEEE Std 1003.1,
16521990.
1653.IP [RFC0791]
1654J. Postel: Internet Protocol, RFC 791, USC/ISI, September 1981.
1655.IP [RFC0793]
1656J. Postel: Transmission Control Protocol, RFC 793, USC/ISI, September
16571981.
1658.IP [RFC1034]
1659P. Mockapetris: Domain Names - Concepts and Facilities, RFC 1034,
1660USC/ISI, November 1987.
1661.IP [RFC1282]
1662B. Kantor: BSD Rlogin, RFC 1258, UCSD, December 1991.
1663.IP "[RSA] "
1664Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1994. See
1665also R. Rivest, A. Shamir, and L. M. Adleman: Cryptographic
1666Communications System and Method. US Patent 4,405,829, 1983.
1667.IP "[X11] "
1668R. Scheifler: X Window System Protocol, X Consortium Standard, Version
166911, Release 6. Massachusetts Institute of Technology, Laboratory of
1670Computer Science, 1994.
1671.RT
1672
1673
1674.ti 0
1675Security Considerations
1676
1677This protocol deals with the very issue of user authentication and
1678security.
1679
1680First of all, as an implementation issue, the server program will have
1681to run as root (or equivalent) on the server machine. This is because
1682the server program will need be able to change to an arbitrary user
1683id. The server must also be able to create a privileged TCP/IP port.
1684
1685The client program will need to run as root if any variant of .rhosts
1686authentication is to be used. This is because the client program will
1687need to create a privileged port. The client host key is also usually
1688stored in a file which is readable by root only. The client needs the
1689host key in .rhosts authentication only. Root privileges can be
1690dropped as soon as the privileged port has been created and the host
1691key has been read.
1692
1693The SSH protocol offers major security advantages over existing telnet
1694and rlogin protocols.
1695.IP o
1696IP spoofing is restricted to closing a connection (by encryption, host
1697keys, and the special random cookie). If encryption is not used, IP
1698spoofing is possible for those who can hear packets going out from the
1699server.
1700.IP o
1701DNS spoofing is made ineffective (by host keys).
1702.IP o
1703Routing spoofing is made ineffective (by host keys).
1704.IP o
1705All data is encrypted with strong algorithms to make eavesdropping as
1706difficult as possible. This includes encrypting any authentication
1707information such as passwords. The information for decrypting session
1708keys is destroyed every hour.
1709.IP o
1710Strong authentication methods: .rhosts combined with RSA host
1711authentication, and pure RSA authentication.
1712.IP o
1713X11 connections and arbitrary TCP/IP ports can be forwarded securely.
1714.IP o
1715Man-in-the-middle attacks are deterred by using the server host key to
1716encrypt the session key.
1717.IP o
1718Trojan horses to catch a password by routing manipulation are deterred
1719by checking that the host key of the server machine matches that
1720stored on the client host.
1721.RT
1722
1723The security of SSH against man-in-the-middle attacks and the security
1724of the new form of .rhosts authentication, as well as server host
1725validation, depends on the integrity of the host key and the files
1726containing known host keys.
1727
1728The host key is normally stored in a root-readable file. If the host
1729key is compromised, it permits attackers to use IP, DNS and routing
1730spoofing as with current rlogin and rsh. It should never be any worse
1731than the current situation.
1732
1733The files containing known host keys are not sensitive. However, if an
1734attacker gets to modify the known host key files, it has the same
1735consequences as a compromised host key, because the attacker can then
1736change the recorded host key.
1737
1738The security improvements obtained by this protocol for X11 are of
1739particular significance. Previously, there has been no way to protect
1740data communicated between an X server and a client running on a remote
1741machine. By creating a fake display on the server, and forwarding all
1742X11 requests over the secure channel, SSH can be used to run any X11
1743applications securely without any cooperation with the vendors of the
1744X server or the application.
1745
1746Finally, the security of this program relies on the strength of the
1747underlying cryptographic algorithms. The RSA algorithm is used for
1748authentication key exchange. It is widely believed to be secure. Of
1749the algorithms used to encrypt the session, DES has a rather small key
1750these days, probably permitting governments and organized criminals to
1751break it in very short time with specialized hardware. 3DES is
1752probably safe (but slower). IDEA is widely believed to be secure.
1753People have varying degrees of confidence in the other algorithms.
1754This program is not secure if used with no encryption at all.
1755
1756
1757.ti 0
1758Additional Information
1759
1760Additional information (especially on the implementation and mailing
1761lists) is available via WWW at http://www.cs.hut.fi/ssh.
1762
1763Comments should be sent to Tatu Ylonen <ylo@cs.hut.fi> or the SSH
1764Mailing List <ssh@clinet.fi>.
1765
1766.ti 0
1767Author's Address
1768
1769.TS
1770;
1771l.
1772Tatu Ylonen
1773Helsinki University of Technology
1774Otakaari 1
1775FIN-02150 Espoo, Finland
1776
1777Phone: +358-0-451-3374
1778Fax: +358-0-451-3293
1779EMail: ylo@cs.hut.fi
1780.TE
diff --git a/auth-krb4.c b/auth-krb4.c
new file mode 100644
index 000000000..720f3a4c4
--- /dev/null
+++ b/auth-krb4.c
@@ -0,0 +1,209 @@
1/*
2
3 auth-kerberos.c
4
5 Dug Song <dugsong@UMICH.EDU>
6
7 Kerberos v4 authentication and ticket-passing routines.
8
9 $Id: auth-krb4.c,v 1.1 1999/10/27 03:42:43 damien Exp $
10*/
11
12#include "includes.h"
13#include "packet.h"
14#include "xmalloc.h"
15#include "ssh.h"
16
17#ifdef KRB4
18int ssh_tf_init(uid_t uid)
19{
20 extern char *ticket;
21 char *tkt_root = TKT_ROOT;
22 struct stat st;
23 int fd;
24
25 /* Set unique ticket string manually since we're still root. */
26 ticket = xmalloc(MAXPATHLEN);
27#ifdef AFS
28 if (lstat("/ticket", &st) != -1)
29 tkt_root = "/ticket/";
30#endif /* AFS */
31 snprintf(ticket, MAXPATHLEN, "%s%d_%d", tkt_root, uid, getpid());
32 (void) krb_set_tkt_string(ticket);
33
34 /* Make sure we own this ticket file, and we created it. */
35 if (lstat(ticket, &st) == -1 && errno == ENOENT) {
36 /* good, no ticket file exists. create it. */
37 if ((fd = open(ticket, O_RDWR|O_CREAT|O_EXCL, 0600)) != -1) {
38 close(fd);
39 return 1;
40 }
41 }
42 else {
43 /* file exists. make sure server_user owns it (e.g. just passed ticket),
44 and that it isn't a symlink, and that it is mode 600. */
45 if (st.st_mode == (S_IFREG|S_IRUSR|S_IWUSR) && st.st_uid == uid)
46 return 1;
47 }
48 /* Failure. */
49 log("WARNING: bad ticket file %s", ticket);
50 return 0;
51}
52
53int auth_krb4(const char *server_user, KTEXT auth, char **client)
54{
55 AUTH_DAT adat = { 0 };
56 KTEXT_ST reply;
57 char instance[INST_SZ];
58 int r, s;
59 u_int cksum;
60 Key_schedule schedule;
61 struct sockaddr_in local, foreign;
62
63 s = packet_get_connection_in();
64
65 r = sizeof(local);
66 memset(&local, 0, sizeof(local));
67 if (getsockname(s, (struct sockaddr *) &local, &r) < 0)
68 debug("getsockname failed: %.100s", strerror(errno));
69 r = sizeof(foreign);
70 memset(&foreign, 0, sizeof(foreign));
71 if (getpeername(s, (struct sockaddr *)&foreign, &r) < 0)
72 debug("getpeername failed: %.100s", strerror(errno));
73
74 instance[0] = '*'; instance[1] = 0;
75
76 /* Get the encrypted request, challenge, and session key. */
77 if ((r = krb_rd_req(auth, KRB4_SERVICE_NAME, instance, 0, &adat, ""))) {
78 packet_send_debug("Kerberos V4 krb_rd_req: %.100s", krb_err_txt[r]);
79 return 0;
80 }
81 des_key_sched((des_cblock *)adat.session, schedule);
82
83 *client = xmalloc(MAX_K_NAME_SZ);
84 (void) snprintf(*client, MAX_K_NAME_SZ, "%s%s%s@%s", adat.pname,
85 *adat.pinst ? "." : "", adat.pinst, adat.prealm);
86
87 /* Check ~/.klogin authorization now. */
88 if (kuserok(&adat, (char *)server_user) != KSUCCESS) {
89 packet_send_debug("Kerberos V4 .klogin authorization failed!");
90 log("Kerberos V4 .klogin authorization failed for %s to account %s",
91 *client, server_user);
92 return 0;
93 }
94 /* Increment the checksum, and return it encrypted with the session key. */
95 cksum = adat.checksum + 1;
96 cksum = htonl(cksum);
97
98 /* If we can't successfully encrypt the checksum, we send back an empty
99 message, admitting our failure. */
100 if ((r = krb_mk_priv((u_char *)&cksum, reply.dat, sizeof(cksum)+1,
101 schedule, &adat.session, &local, &foreign)) < 0) {
102 packet_send_debug("Kerberos V4 mk_priv: (%d) %s", r, krb_err_txt[r]);
103 reply.dat[0] = 0;
104 reply.length = 0;
105 }
106 else
107 reply.length = r;
108
109 /* Clear session key. */
110 memset(&adat.session, 0, sizeof(&adat.session));
111
112 packet_start(SSH_SMSG_AUTH_KERBEROS_RESPONSE);
113 packet_put_string((char *) reply.dat, reply.length);
114 packet_send();
115 packet_write_wait();
116 return 1;
117}
118#endif /* KRB4 */
119
120#ifdef AFS
121int auth_kerberos_tgt(struct passwd *pw, const char *string)
122{
123 CREDENTIALS creds;
124 extern char *ticket;
125 int r;
126
127 if (!radix_to_creds(string, &creds)) {
128 log("Protocol error decoding Kerberos V4 tgt");
129 packet_send_debug("Protocol error decoding Kerberos V4 tgt");
130 goto auth_kerberos_tgt_failure;
131 }
132 if (strncmp(creds.service, "", 1) == 0) /* backward compatibility */
133 strlcpy(creds.service, "krbtgt", sizeof creds.service);
134
135 if (strcmp(creds.service, "krbtgt")) {
136 log("Kerberos V4 tgt (%s%s%s@%s) rejected for uid %d",
137 creds.pname, creds.pinst[0] ? "." : "", creds.pinst, creds.realm,
138 pw->pw_uid);
139 packet_send_debug("Kerberos V4 tgt (%s%s%s@%s) rejected for uid %d",
140 creds.pname, creds.pinst[0] ? "." : "", creds.pinst,
141 creds.realm, pw->pw_uid);
142 goto auth_kerberos_tgt_failure;
143 }
144 if (!ssh_tf_init(pw->pw_uid) ||
145 (r = in_tkt(creds.pname, creds.pinst)) ||
146 (r = save_credentials(creds.service, creds.instance, creds.realm,
147 creds.session, creds.lifetime, creds.kvno,
148 &creds.ticket_st, creds.issue_date))) {
149 xfree(ticket);
150 ticket = NULL;
151 packet_send_debug("Kerberos V4 tgt refused: couldn't save credentials");
152 goto auth_kerberos_tgt_failure;
153 }
154 /* Successful authentication, passed all checks. */
155 chown(ticket, pw->pw_uid, pw->pw_gid);
156 packet_send_debug("Kerberos V4 tgt accepted (%s.%s@%s, %s%s%s@%s)",
157 creds.service, creds.instance, creds.realm,
158 creds.pname, creds.pinst[0] ? "." : "",
159 creds.pinst, creds.realm);
160
161 packet_start(SSH_SMSG_SUCCESS);
162 packet_send();
163 packet_write_wait();
164 return 1;
165
166auth_kerberos_tgt_failure:
167 memset(&creds, 0, sizeof(creds));
168 packet_start(SSH_SMSG_FAILURE);
169 packet_send();
170 packet_write_wait();
171 return 0;
172}
173
174int auth_afs_token(char *server_user, uid_t uid, const char *string)
175{
176 CREDENTIALS creds;
177
178 if (!radix_to_creds(string, &creds)) {
179 log("Protocol error decoding AFS token");
180 packet_send_debug("Protocol error decoding AFS token");
181 packet_start(SSH_SMSG_FAILURE);
182 packet_send();
183 packet_write_wait();
184 return 0;
185 }
186 if (strncmp(creds.service, "", 1) == 0) /* backward compatibility */
187 strlcpy(creds.service, "afs", sizeof creds.service);
188
189 if (strncmp(creds.pname, "AFS ID ", 7) == 0)
190 uid = atoi(creds.pname + 7);
191
192 if (kafs_settoken(creds.realm, uid, &creds)) {
193 log("AFS token (%s@%s) rejected for uid %d", creds.pname,
194 creds.realm, uid);
195 packet_send_debug("AFS token (%s@%s) rejected for uid %d", creds.pname,
196 creds.realm, uid);
197 packet_start(SSH_SMSG_FAILURE);
198 packet_send();
199 packet_write_wait();
200 return 0;
201 }
202 packet_send_debug("AFS token accepted (%s@%s, %s@%s)", creds.service,
203 creds.realm, creds.pname, creds.realm);
204 packet_start(SSH_SMSG_SUCCESS);
205 packet_send();
206 packet_write_wait();
207 return 1;
208}
209#endif /* AFS */
diff --git a/auth-passwd.c b/auth-passwd.c
new file mode 100644
index 000000000..7d6846789
--- /dev/null
+++ b/auth-passwd.c
@@ -0,0 +1,209 @@
1/*
2
3auth-passwd.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Sat Mar 18 05:11:38 1995 ylo
11
12Password authentication. This file contains the functions to check whether
13the password is valid for the user.
14
15*/
16
17#include "includes.h"
18RCSID("$Id: auth-passwd.c,v 1.1 1999/10/27 03:42:43 damien Exp $");
19
20#include "packet.h"
21#include "ssh.h"
22#include "servconf.h"
23#include "xmalloc.h"
24
25#ifdef KRB4
26extern char *ticket;
27#endif /* KRB4 */
28
29#ifdef HAVE_PAM
30#include <security/pam_appl.h>
31extern pam_handle_t *pamh;
32extern int retval;
33extern char* pampasswd;
34extern int origretval;
35#endif /* HAVE_PAM */
36
37/* Tries to authenticate the user using password. Returns true if
38 authentication succeeds. */
39
40int auth_password(struct passwd *pw, const char *password)
41{
42 extern ServerOptions options;
43 char *encrypted_password;
44
45 if (pw->pw_uid == 0 && options.permit_root_login == 2)
46 {
47 /*packet_send_debug("Server does not permit root login with password.");*/
48 return 0;
49 }
50
51 if (*password == '\0' && options.permit_empty_passwd == 0)
52 {
53 /*packet_send_debug("Server does not permit empty password login.");*/
54 return 0;
55 }
56
57 /* deny if no user. */
58 if (pw == NULL)
59 return 0;
60
61#ifdef HAVE_PAM
62 retval = origretval;
63
64 pampasswd = xstrdup(password);
65
66 if (retval == PAM_SUCCESS)
67 retval = pam_authenticate ((pam_handle_t *)pamh, 0);
68
69 if (retval == PAM_SUCCESS)
70 retval = pam_acct_mgmt ((pam_handle_t *)pamh, 0);
71
72 xfree(pampasswd);
73
74 if (retval == PAM_SUCCESS)
75 retval = pam_open_session ((pam_handle_t *)pamh, 0);
76
77 return (retval == PAM_SUCCESS);
78
79#else /* HAVE_PAM */
80
81#ifdef SKEY
82 if (options.skey_authentication == 1) {
83 if (strncasecmp(password, "s/key", 5) == 0) {
84 char *skeyinfo = skey_keyinfo(pw->pw_name);
85 if(skeyinfo == NULL){
86 debug("generating fake skeyinfo for %.100s.", pw->pw_name);
87 skeyinfo = skey_fake_keyinfo(pw->pw_name);
88 }
89 if(skeyinfo != NULL)
90 packet_send_debug(skeyinfo);
91 /* Try again. */
92 return 0;
93 }
94 else if (skey_haskey(pw->pw_name) == 0 &&
95 skey_passcheck(pw->pw_name, (char *)password) != -1) {
96 /* Authentication succeeded. */
97 return 1;
98 }
99 /* Fall back to ordinary passwd authentication. */
100 }
101#endif
102
103#if defined(KRB4)
104 /* Support for Kerberos v4 authentication - Dug Song <dugsong@UMICH.EDU> */
105 if (options.kerberos_authentication)
106 {
107 AUTH_DAT adata;
108 KTEXT_ST tkt;
109 struct hostent *hp;
110 unsigned long faddr;
111 char localhost[MAXHOSTNAMELEN]; /* local host name */
112 char phost[INST_SZ]; /* host instance */
113 char realm[REALM_SZ]; /* local Kerberos realm */
114 int r;
115
116 /* Try Kerberos password authentication only for non-root
117 users and only if Kerberos is installed. */
118 if (pw->pw_uid != 0 && krb_get_lrealm(realm, 1) == KSUCCESS) {
119
120 /* Set up our ticket file. */
121 if (!ssh_tf_init(pw->pw_uid)) {
122 log("Couldn't initialize Kerberos ticket file for %s!",
123 pw->pw_name);
124 goto kerberos_auth_failure;
125 }
126 /* Try to get TGT using our password. */
127 r = krb_get_pw_in_tkt((char *)pw->pw_name, "", realm, "krbtgt", realm,
128 DEFAULT_TKT_LIFE, (char *)password);
129 if (r != INTK_OK) {
130 packet_send_debug("Kerberos V4 password authentication for %s "
131 "failed: %s", pw->pw_name, krb_err_txt[r]);
132 goto kerberos_auth_failure;
133 }
134 /* Successful authentication. */
135 chown(ticket, pw->pw_uid, pw->pw_gid);
136
137 (void) gethostname(localhost, sizeof(localhost));
138 (void) strlcpy(phost, (char *)krb_get_phost(localhost), INST_SZ);
139
140 /* Now that we have a TGT, try to get a local "rcmd" ticket to
141 ensure that we are not talking to a bogus Kerberos server. */
142 r = krb_mk_req(&tkt, KRB4_SERVICE_NAME, phost, realm, 33);
143
144 if (r == KSUCCESS) {
145 if (!(hp = gethostbyname(localhost))) {
146 log("Couldn't get local host address!");
147 goto kerberos_auth_failure;
148 }
149 memmove((void *)&faddr, (void *)hp->h_addr, sizeof(faddr));
150
151 /* Verify our "rcmd" ticket. */
152 r = krb_rd_req(&tkt, KRB4_SERVICE_NAME, phost, faddr, &adata, "");
153 if (r == RD_AP_UNDEC) {
154 /* Probably didn't have a srvtab on localhost. Allow login. */
155 log("Kerberos V4 TGT for %s unverifiable, no srvtab installed? "
156 "krb_rd_req: %s", pw->pw_name, krb_err_txt[r]);
157 }
158 else if (r != KSUCCESS) {
159 log("Kerberos V4 %s ticket unverifiable: %s",
160 KRB4_SERVICE_NAME, krb_err_txt[r]);
161 goto kerberos_auth_failure;
162 }
163 }
164 else if (r == KDC_PR_UNKNOWN) {
165 /* Allow login if no rcmd service exists, but log the error. */
166 log("Kerberos V4 TGT for %s unverifiable: %s; %s.%s "
167 "not registered, or srvtab is wrong?", pw->pw_name,
168 krb_err_txt[r], KRB4_SERVICE_NAME, phost);
169 }
170 else {
171 /* TGT is bad, forget it. Possibly spoofed! */
172 packet_send_debug("WARNING: Kerberos V4 TGT possibly spoofed for"
173 "%s: %s", pw->pw_name, krb_err_txt[r]);
174 goto kerberos_auth_failure;
175 }
176
177 /* Authentication succeeded. */
178 return 1;
179
180 kerberos_auth_failure:
181 (void) dest_tkt();
182 xfree(ticket);
183 ticket = NULL;
184 if (!options.kerberos_or_local_passwd ) return 0;
185 }
186 else {
187 /* Logging in as root or no local Kerberos realm. */
188 packet_send_debug("Unable to authenticate to Kerberos.");
189 }
190 /* Fall back to ordinary passwd authentication. */
191 }
192#endif /* KRB4 */
193
194 /* Check for users with no password. */
195 if (strcmp(password, "") == 0 && strcmp(pw->pw_passwd, "") == 0)
196 {
197 packet_send_debug("Login permitted without a password because the account has no password.");
198 return 1; /* The user has no password and an empty password was tried. */
199 }
200
201 /* Encrypt the candidate password using the proper salt. */
202 encrypted_password = crypt(password,
203 (pw->pw_passwd[0] && pw->pw_passwd[1]) ?
204 pw->pw_passwd : "xx");
205
206 /* Authentication is accepted if the encrypted passwords are identical. */
207 return (strcmp(encrypted_password, pw->pw_passwd) == 0);
208#endif /* HAVE_PAM */
209}
diff --git a/auth-rh-rsa.c b/auth-rh-rsa.c
new file mode 100644
index 000000000..c433578bf
--- /dev/null
+++ b/auth-rh-rsa.c
@@ -0,0 +1,83 @@
1/*
2
3auth-rh-rsa.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Sun May 7 03:08:06 1995 ylo
11
12Rhosts or /etc/hosts.equiv authentication combined with RSA host
13authentication.
14
15*/
16
17#include "includes.h"
18RCSID("$Id: auth-rh-rsa.c,v 1.1 1999/10/27 03:42:43 damien Exp $");
19
20#include "packet.h"
21#include "ssh.h"
22#include "xmalloc.h"
23#include "uidswap.h"
24
25/* Tries to authenticate the user using the .rhosts file and the host using
26 its host key. Returns true if authentication succeeds.
27 .rhosts and .shosts will be ignored if ignore_rhosts is non-zero. */
28
29int auth_rhosts_rsa(struct passwd *pw, const char *client_user,
30 unsigned int client_host_key_bits,
31 BIGNUM *client_host_key_e, BIGNUM *client_host_key_n,
32 int ignore_rhosts, int strict_modes)
33{
34 const char *canonical_hostname;
35 HostStatus host_status;
36 BIGNUM *ke, *kn;
37
38 debug("Trying rhosts with RSA host authentication for %.100s", client_user);
39
40 /* Check if we would accept it using rhosts authentication. */
41 if (!auth_rhosts(pw, client_user, ignore_rhosts, strict_modes))
42 return 0;
43
44 canonical_hostname = get_canonical_hostname();
45
46 debug("Rhosts RSA authentication: canonical host %.900s",
47 canonical_hostname);
48
49 /* Check if we know the host and its host key. */
50 /* Check system-wide host file. */
51 ke = BN_new();
52 kn = BN_new();
53 host_status = check_host_in_hostfile(SSH_SYSTEM_HOSTFILE, canonical_hostname,
54 client_host_key_bits, client_host_key_e,
55 client_host_key_n, ke, kn);
56 BN_free(ke);
57 BN_free(kn);
58 if (host_status != HOST_OK) {
59 /* The host key was not found. */
60 debug("Rhosts with RSA host authentication denied: unknown or invalid host key");
61 packet_send_debug("Your host key cannot be verified: unknown or invalid host key.");
62 return 0;
63 }
64
65 /* A matching host key was found and is known. */
66
67 /* Perform the challenge-response dialog with the client for the host key. */
68 if (!auth_rsa_challenge_dialog(client_host_key_bits,
69 client_host_key_e, client_host_key_n))
70 {
71 log("Client on %.800s failed to respond correctly to host authentication.",
72 canonical_hostname);
73 return 0;
74 }
75
76 /* We have authenticated the user using .rhosts or /etc/hosts.equiv, and
77 the host using RSA. We accept the authentication. */
78
79 log("Rhosts with RSA host authentication accepted for %.100s, %.100s on %.700s.",
80 pw->pw_name, client_user, canonical_hostname);
81 packet_send_debug("Rhosts with RSA host authentication accepted.");
82 return 1;
83}
diff --git a/auth-rhosts.c b/auth-rhosts.c
new file mode 100644
index 000000000..ebf2fcbc2
--- /dev/null
+++ b/auth-rhosts.c
@@ -0,0 +1,298 @@
1/*
2
3auth-rhosts.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Fri Mar 17 05:12:18 1995 ylo
11
12Rhosts authentication. This file contains code to check whether to admit
13the login based on rhosts authentication. This file also processes
14/etc/hosts.equiv.
15
16*/
17
18#include "includes.h"
19RCSID("$Id: auth-rhosts.c,v 1.1 1999/10/27 03:42:43 damien Exp $");
20
21#include "packet.h"
22#include "ssh.h"
23#include "xmalloc.h"
24#include "uidswap.h"
25
26/* This function processes an rhosts-style file (.rhosts, .shosts, or
27 /etc/hosts.equiv). This returns true if authentication can be granted
28 based on the file, and returns zero otherwise. */
29
30int check_rhosts_file(const char *filename, const char *hostname,
31 const char *ipaddr, const char *client_user,
32 const char *server_user)
33{
34 FILE *f;
35 char buf[1024]; /* Must not be larger than host, user, dummy below. */
36
37 /* Open the .rhosts file. */
38 f = fopen(filename, "r");
39 if (!f)
40 return 0; /* Cannot read the .rhosts - deny access. */
41
42 /* Go through the file, checking every entry. */
43 while (fgets(buf, sizeof(buf), f))
44 {
45 /* All three must be at least as big as buf to avoid overflows. */
46 char hostbuf[1024], userbuf[1024], dummy[1024], *host, *user, *cp;
47 int negated;
48
49 for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
50 ;
51 if (*cp == '#' || *cp == '\n' || !*cp)
52 continue;
53
54 /* NO_PLUS is supported at least on OSF/1. We skip it (we don't ever
55 support the plus syntax). */
56 if (strncmp(cp, "NO_PLUS", 7) == 0)
57 continue;
58
59 /* This should be safe because each buffer is as big as the whole
60 string, and thus cannot be overwritten. */
61 switch (sscanf(buf, "%s %s %s", hostbuf, userbuf, dummy))
62 {
63 case 0:
64 packet_send_debug("Found empty line in %.100s.", filename);
65 continue; /* Empty line? */
66 case 1:
67 /* Host name only. */
68 strlcpy(userbuf, server_user, sizeof(userbuf));
69 break;
70 case 2:
71 /* Got both host and user name. */
72 break;
73 case 3:
74 packet_send_debug("Found garbage in %.100s.", filename);
75 continue; /* Extra garbage */
76 default:
77 continue; /* Weird... */
78 }
79
80 host = hostbuf;
81 user = userbuf;
82 negated = 0;
83
84 /* Process negated host names, or positive netgroups. */
85 if (host[0] == '-')
86 {
87 negated = 1;
88 host++;
89 }
90 else
91 if (host[0] == '+')
92 host++;
93
94 if (user[0] == '-')
95 {
96 negated = 1;
97 user++;
98 }
99 else
100 if (user[0] == '+')
101 user++;
102
103 /* Check for empty host/user names (particularly '+'). */
104 if (!host[0] || !user[0])
105 {
106 /* We come here if either was '+' or '-'. */
107 packet_send_debug("Ignoring wild host/user names in %.100s.",
108 filename);
109 continue;
110 }
111
112 /* Verify that host name matches. */
113 if (host[0] == '@')
114 {
115 if (!innetgr(host + 1, hostname, NULL, NULL) &&
116 !innetgr(host + 1, ipaddr, NULL, NULL))
117 continue;
118 }
119 else
120 if (strcasecmp(host, hostname) && strcmp(host, ipaddr) != 0)
121 continue; /* Different hostname. */
122
123 /* Verify that user name matches. */
124 if (user[0] == '@')
125 {
126 if (!innetgr(user + 1, NULL, client_user, NULL))
127 continue;
128 }
129 else
130 if (strcmp(user, client_user) != 0)
131 continue; /* Different username. */
132
133 /* Found the user and host. */
134 fclose(f);
135
136 /* If the entry was negated, deny access. */
137 if (negated)
138 {
139 packet_send_debug("Matched negative entry in %.100s.",
140 filename);
141 return 0;
142 }
143
144 /* Accept authentication. */
145 return 1;
146 }
147
148 /* Authentication using this file denied. */
149 fclose(f);
150 return 0;
151}
152
153/* Tries to authenticate the user using the .shosts or .rhosts file.
154 Returns true if authentication succeeds. If ignore_rhosts is
155 true, only /etc/hosts.equiv will be considered (.rhosts and .shosts
156 are ignored). */
157
158int auth_rhosts(struct passwd *pw, const char *client_user,
159 int ignore_rhosts, int strict_modes)
160{
161 char buf[1024];
162 const char *hostname, *ipaddr;
163 int port;
164 struct stat st;
165 static const char *rhosts_files[] = { ".shosts", ".rhosts", NULL };
166 unsigned int rhosts_file_index;
167
168 /* Quick check: if the user has no .shosts or .rhosts files, return failure
169 immediately without doing costly lookups from name servers. */
170 /* Switch to the user's uid. */
171 temporarily_use_uid(pw->pw_uid);
172 for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
173 rhosts_file_index++)
174 {
175 /* Check users .rhosts or .shosts. */
176 snprintf(buf, sizeof buf, "%.500s/%.100s",
177 pw->pw_dir, rhosts_files[rhosts_file_index]);
178 if (stat(buf, &st) >= 0)
179 break;
180 }
181 /* Switch back to privileged uid. */
182 restore_uid();
183
184 if (!rhosts_files[rhosts_file_index] && stat("/etc/hosts.equiv", &st) < 0 &&
185 stat(SSH_HOSTS_EQUIV, &st) < 0)
186 return 0; /* The user has no .shosts or .rhosts file and there are no
187 system-wide files. */
188
189 /* Get the name, address, and port of the remote host. */
190 hostname = get_canonical_hostname();
191 ipaddr = get_remote_ipaddr();
192 port = get_remote_port();
193
194 /* Check that the connection comes from a privileged port.
195 Rhosts authentication only makes sense for priviledged programs.
196 Of course, if the intruder has root access on his local machine,
197 he can connect from any port. So do not use .rhosts
198 authentication from machines that you do not trust. */
199 if (port >= IPPORT_RESERVED ||
200 port < IPPORT_RESERVED / 2)
201 {
202 log("Connection from %.100s from nonpriviledged port %d",
203 hostname, port);
204 packet_send_debug("Your ssh client is not running as root.");
205 return 0;
206 }
207
208 /* If not logging in as superuser, try /etc/hosts.equiv and shosts.equiv. */
209 if (pw->pw_uid != 0)
210 {
211 if (check_rhosts_file("/etc/hosts.equiv", hostname, ipaddr, client_user,
212 pw->pw_name))
213 {
214 packet_send_debug("Accepted for %.100s [%.100s] by /etc/hosts.equiv.",
215 hostname, ipaddr);
216 return 1;
217 }
218 if (check_rhosts_file(SSH_HOSTS_EQUIV, hostname, ipaddr, client_user,
219 pw->pw_name))
220 {
221 packet_send_debug("Accepted for %.100s [%.100s] by %.100s.",
222 hostname, ipaddr, SSH_HOSTS_EQUIV);
223 return 1;
224 }
225 }
226
227 /* Check that the home directory is owned by root or the user, and is not
228 group or world writable. */
229 if (stat(pw->pw_dir, &st) < 0)
230 {
231 log("Rhosts authentication refused for %.100: no home directory %.200s",
232 pw->pw_name, pw->pw_dir);
233 packet_send_debug("Rhosts authentication refused for %.100: no home directory %.200s",
234 pw->pw_name, pw->pw_dir);
235 return 0;
236 }
237 if (strict_modes &&
238 ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
239 (st.st_mode & 022) != 0))
240 {
241 log("Rhosts authentication refused for %.100s: bad ownership or modes for home directory.",
242 pw->pw_name);
243 packet_send_debug("Rhosts authentication refused for %.100s: bad ownership or modes for home directory.",
244 pw->pw_name);
245 return 0;
246 }
247
248 /* Check all .rhosts files (currently .shosts and .rhosts). */
249 /* Temporarily use the user's uid. */
250 temporarily_use_uid(pw->pw_uid);
251 for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
252 rhosts_file_index++)
253 {
254 /* Check users .rhosts or .shosts. */
255 snprintf(buf, sizeof buf, "%.500s/%.100s",
256 pw->pw_dir, rhosts_files[rhosts_file_index]);
257 if (stat(buf, &st) < 0)
258 continue; /* No such file. */
259
260 /* Make sure that the file is either owned by the user or by root,
261 and make sure it is not writable by anyone but the owner. This is
262 to help avoid novices accidentally allowing access to their account
263 by anyone. */
264 if (strict_modes &&
265 ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
266 (st.st_mode & 022) != 0))
267 {
268 log("Rhosts authentication refused for %.100s: bad modes for %.200s",
269 pw->pw_name, buf);
270 packet_send_debug("Bad file modes for %.200s", buf);
271 continue;
272 }
273
274 /* Check if we have been configured to ignore .rhosts and .shosts
275 files. */
276 if (ignore_rhosts)
277 {
278 packet_send_debug("Server has been configured to ignore %.100s.",
279 rhosts_files[rhosts_file_index]);
280 continue;
281 }
282
283 /* Check if authentication is permitted by the file. */
284 if (check_rhosts_file(buf, hostname, ipaddr, client_user, pw->pw_name))
285 {
286 packet_send_debug("Accepted by %.100s.",
287 rhosts_files[rhosts_file_index]);
288 /* Restore the privileged uid. */
289 restore_uid();
290 return 1;
291 }
292 }
293
294 /* Rhosts authentication denied. */
295 /* Restore the privileged uid. */
296 restore_uid();
297 return 0;
298}
diff --git a/auth-rsa.c b/auth-rsa.c
new file mode 100644
index 000000000..8de86d2de
--- /dev/null
+++ b/auth-rsa.c
@@ -0,0 +1,478 @@
1/*
2
3auth-rsa.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Mon Mar 27 01:46:52 1995 ylo
11
12RSA-based authentication. This code determines whether to admit a login
13based on RSA authentication. This file also contains functions to check
14validity of the host key.
15
16*/
17
18#include "includes.h"
19RCSID("$Id: auth-rsa.c,v 1.1 1999/10/27 03:42:43 damien Exp $");
20
21#include "rsa.h"
22#include "packet.h"
23#include "xmalloc.h"
24#include "ssh.h"
25#include "mpaux.h"
26#include "uidswap.h"
27
28#include <openssl/rsa.h>
29#include <openssl/md5.h>
30
31/* Flags that may be set in authorized_keys options. */
32extern int no_port_forwarding_flag;
33extern int no_agent_forwarding_flag;
34extern int no_x11_forwarding_flag;
35extern int no_pty_flag;
36extern char *forced_command;
37extern struct envstring *custom_environment;
38
39/* Session identifier that is used to bind key exchange and authentication
40 responses to a particular session. */
41extern unsigned char session_id[16];
42
43/* The .ssh/authorized_keys file contains public keys, one per line, in the
44 following format:
45 options bits e n comment
46 where bits, e and n are decimal numbers,
47 and comment is any string of characters up to newline. The maximum
48 length of a line is 8000 characters. See the documentation for a
49 description of the options.
50*/
51
52/* Performs the RSA authentication challenge-response dialog with the client,
53 and returns true (non-zero) if the client gave the correct answer to
54 our challenge; returns zero if the client gives a wrong answer. */
55
56int
57auth_rsa_challenge_dialog(unsigned int bits, BIGNUM *e, BIGNUM *n)
58{
59 BIGNUM *challenge, *encrypted_challenge, *aux;
60 RSA *pk;
61 BN_CTX *ctx = BN_CTX_new();
62 unsigned char buf[32], mdbuf[16], response[16];
63 MD5_CTX md;
64 unsigned int i;
65 int plen, len;
66
67 encrypted_challenge = BN_new();
68 challenge = BN_new();
69 aux = BN_new();
70
71 /* Generate a random challenge. */
72 BN_rand(challenge, 256, 0, 0);
73 BN_mod(challenge, challenge, n, ctx);
74
75 /* Create the public key data structure. */
76 pk = RSA_new();
77 pk->e = BN_new();
78 BN_copy(pk->e, e);
79 pk->n = BN_new();
80 BN_copy(pk->n, n);
81
82 /* Encrypt the challenge with the public key. */
83 rsa_public_encrypt(encrypted_challenge, challenge, pk);
84 RSA_free(pk);
85
86 /* Send the encrypted challenge to the client. */
87 packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE);
88 packet_put_bignum(encrypted_challenge);
89 packet_send();
90 packet_write_wait();
91
92 /* The response is MD5 of decrypted challenge plus session id. */
93 len = BN_num_bytes(challenge);
94 assert(len <= 32 && len);
95 memset(buf, 0, 32);
96 BN_bn2bin(challenge, buf + 32 - len);
97 MD5_Init(&md);
98 MD5_Update(&md, buf, 32);
99 MD5_Update(&md, session_id, 16);
100 MD5_Final(mdbuf, &md);
101
102 /* We will no longer need these. */
103 BN_clear_free(encrypted_challenge);
104 BN_clear_free(challenge);
105 BN_clear_free(aux);
106 BN_CTX_free(ctx);
107
108 /* Wait for a response. */
109 packet_read_expect(&plen, SSH_CMSG_AUTH_RSA_RESPONSE);
110 packet_integrity_check(plen, 16, SSH_CMSG_AUTH_RSA_RESPONSE);
111 for (i = 0; i < 16; i++)
112 response[i] = packet_get_char();
113
114 /* Verify that the response is the original challenge. */
115 if (memcmp(response, mdbuf, 16) != 0)
116 {
117 /* Wrong answer. */
118 return 0;
119 }
120
121 /* Correct answer. */
122 return 1;
123}
124
125/* Performs the RSA authentication dialog with the client. This returns
126 0 if the client could not be authenticated, and 1 if authentication was
127 successful. This may exit if there is a serious protocol violation. */
128
129int
130auth_rsa(struct passwd *pw, BIGNUM *client_n, int strict_modes)
131{
132 char line[8192];
133 int authenticated;
134 unsigned int bits;
135 FILE *f;
136 unsigned long linenum = 0;
137 struct stat st;
138 BIGNUM *e, *n;
139
140 /* Temporarily use the user's uid. */
141 temporarily_use_uid(pw->pw_uid);
142
143 /* The authorized keys. */
144 snprintf(line, sizeof line, "%.500s/%.100s", pw->pw_dir,
145 SSH_USER_PERMITTED_KEYS);
146
147 /* Fail quietly if file does not exist */
148 if (stat(line, &st) < 0)
149 {
150 /* Restore the privileged uid. */
151 restore_uid();
152 return 0;
153 }
154
155 /* Open the file containing the authorized keys. */
156 f = fopen(line, "r");
157 if (!f)
158 {
159 /* Restore the privileged uid. */
160 restore_uid();
161 packet_send_debug("Could not open %.900s for reading.", line);
162 packet_send_debug("If your home is on an NFS volume, it may need to be world-readable.");
163 return 0;
164 }
165
166 if (strict_modes) {
167 int fail=0;
168 char buf[1024];
169 /* Check open file in order to avoid open/stat races */
170 if (fstat(fileno(f), &st) < 0 ||
171 (st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
172 (st.st_mode & 022) != 0) {
173 snprintf(buf, sizeof buf, "RSA authentication refused for %.100s: "
174 "bad ownership or modes for '%s'.", pw->pw_name, line);
175 fail=1;
176 }else{
177 /* Check path to SSH_USER_PERMITTED_KEYS */
178 int i;
179 static const char *check[] = {
180 "", SSH_USER_DIR, NULL
181 };
182 for (i=0; check[i]; i++) {
183 snprintf(line, sizeof line, "%.500s/%.100s", pw->pw_dir, check[i]);
184 if (stat(line, &st) < 0 ||
185 (st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
186 (st.st_mode & 022) != 0) {
187 snprintf(buf, sizeof buf, "RSA authentication refused for %.100s: "
188 "bad ownership or modes for '%s'.", pw->pw_name, line);
189 fail=1;
190 break;
191 }
192 }
193 }
194 if (fail) {
195 log(buf);
196 packet_send_debug(buf);
197 restore_uid();
198 return 0;
199 }
200 }
201
202 /* Flag indicating whether authentication has succeeded. */
203 authenticated = 0;
204
205 /* Initialize mp-int variables. */
206 e = BN_new();
207 n = BN_new();
208
209 /* Go though the accepted keys, looking for the current key. If found,
210 perform a challenge-response dialog to verify that the user really has
211 the corresponding private key. */
212 while (fgets(line, sizeof(line), f))
213 {
214 char *cp;
215 char *options;
216
217 linenum++;
218
219 /* Skip leading whitespace. */
220 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
221 ;
222
223 /* Skip empty and comment lines. */
224 if (!*cp || *cp == '\n' || *cp == '#')
225 continue;
226
227 /* Check if there are options for this key, and if so, save their
228 starting address and skip the option part for now. If there are no
229 options, set the starting address to NULL. */
230 if (*cp < '0' || *cp > '9')
231 {
232 int quoted = 0;
233 options = cp;
234 for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++)
235 {
236 if (*cp == '\\' && cp[1] == '"')
237 cp++; /* Skip both */
238 else
239 if (*cp == '"')
240 quoted = !quoted;
241 }
242 }
243 else
244 options = NULL;
245
246 /* Parse the key from the line. */
247 if (!auth_rsa_read_key(&cp, &bits, e, n))
248 {
249 debug("%.100s, line %lu: bad key syntax",
250 SSH_USER_PERMITTED_KEYS, linenum);
251 packet_send_debug("%.100s, line %lu: bad key syntax",
252 SSH_USER_PERMITTED_KEYS, linenum);
253 continue;
254 }
255 /* cp now points to the comment part. */
256
257 /* Check if the we have found the desired key (identified by its
258 modulus). */
259 if (BN_cmp(n, client_n) != 0)
260 continue; /* Wrong key. */
261
262 /* We have found the desired key. */
263
264 /* Perform the challenge-response dialog for this key. */
265 if (!auth_rsa_challenge_dialog(bits, e, n))
266 {
267 /* Wrong response. */
268 log("Wrong response to RSA authentication challenge.");
269 packet_send_debug("Wrong response to RSA authentication challenge.");
270 continue;
271 }
272
273 /* Correct response. The client has been successfully authenticated.
274 Note that we have not yet processed the options; this will be reset
275 if the options cause the authentication to be rejected. */
276 authenticated = 1;
277
278 /* RSA part of authentication was accepted. Now process the options. */
279 if (options)
280 {
281 while (*options && *options != ' ' && *options != '\t')
282 {
283 cp = "no-port-forwarding";
284 if (strncmp(options, cp, strlen(cp)) == 0)
285 {
286 packet_send_debug("Port forwarding disabled.");
287 no_port_forwarding_flag = 1;
288 options += strlen(cp);
289 goto next_option;
290 }
291 cp = "no-agent-forwarding";
292 if (strncmp(options, cp, strlen(cp)) == 0)
293 {
294 packet_send_debug("Agent forwarding disabled.");
295 no_agent_forwarding_flag = 1;
296 options += strlen(cp);
297 goto next_option;
298 }
299 cp = "no-X11-forwarding";
300 if (strncmp(options, cp, strlen(cp)) == 0)
301 {
302 packet_send_debug("X11 forwarding disabled.");
303 no_x11_forwarding_flag = 1;
304 options += strlen(cp);
305 goto next_option;
306 }
307 cp = "no-pty";
308 if (strncmp(options, cp, strlen(cp)) == 0)
309 {
310 packet_send_debug("Pty allocation disabled.");
311 no_pty_flag = 1;
312 options += strlen(cp);
313 goto next_option;
314 }
315 cp = "command=\"";
316 if (strncmp(options, cp, strlen(cp)) == 0)
317 {
318 int i;
319 options += strlen(cp);
320 forced_command = xmalloc(strlen(options) + 1);
321 i = 0;
322 while (*options)
323 {
324 if (*options == '"')
325 break;
326 if (*options == '\\' && options[1] == '"')
327 {
328 options += 2;
329 forced_command[i++] = '"';
330 continue;
331 }
332 forced_command[i++] = *options++;
333 }
334 if (!*options)
335 {
336 debug("%.100s, line %lu: missing end quote",
337 SSH_USER_PERMITTED_KEYS, linenum);
338 packet_send_debug("%.100s, line %lu: missing end quote",
339 SSH_USER_PERMITTED_KEYS, linenum);
340 continue;
341 }
342 forced_command[i] = 0;
343 packet_send_debug("Forced command: %.900s", forced_command);
344 options++;
345 goto next_option;
346 }
347 cp = "environment=\"";
348 if (strncmp(options, cp, strlen(cp)) == 0)
349 {
350 int i;
351 char *s;
352 struct envstring *new_envstring;
353 options += strlen(cp);
354 s = xmalloc(strlen(options) + 1);
355 i = 0;
356 while (*options)
357 {
358 if (*options == '"')
359 break;
360 if (*options == '\\' && options[1] == '"')
361 {
362 options += 2;
363 s[i++] = '"';
364 continue;
365 }
366 s[i++] = *options++;
367 }
368 if (!*options)
369 {
370 debug("%.100s, line %lu: missing end quote",
371 SSH_USER_PERMITTED_KEYS, linenum);
372 packet_send_debug("%.100s, line %lu: missing end quote",
373 SSH_USER_PERMITTED_KEYS, linenum);
374 continue;
375 }
376 s[i] = 0;
377 packet_send_debug("Adding to environment: %.900s", s);
378 debug("Adding to environment: %.900s", s);
379 options++;
380 new_envstring = xmalloc(sizeof(struct envstring));
381 new_envstring->s = s;
382 new_envstring->next = custom_environment;
383 custom_environment = new_envstring;
384 goto next_option;
385 }
386 cp = "from=\"";
387 if (strncmp(options, cp, strlen(cp)) == 0)
388 {
389 char *patterns = xmalloc(strlen(options) + 1);
390 int i;
391 options += strlen(cp);
392 i = 0;
393 while (*options)
394 {
395 if (*options == '"')
396 break;
397 if (*options == '\\' && options[1] == '"')
398 {
399 options += 2;
400 patterns[i++] = '"';
401 continue;
402 }
403 patterns[i++] = *options++;
404 }
405 if (!*options)
406 {
407 debug("%.100s, line %lu: missing end quote",
408 SSH_USER_PERMITTED_KEYS, linenum);
409 packet_send_debug("%.100s, line %lu: missing end quote",
410 SSH_USER_PERMITTED_KEYS, linenum);
411 continue;
412 }
413 patterns[i] = 0;
414 options++;
415 if (!match_hostname(get_canonical_hostname(), patterns,
416 strlen(patterns)) &&
417 !match_hostname(get_remote_ipaddr(), patterns,
418 strlen(patterns)))
419 {
420 log("RSA authentication tried for %.100s with correct key but not from a permitted host (host=%.200s, ip=%.200s).",
421 pw->pw_name, get_canonical_hostname(),
422 get_remote_ipaddr());
423 packet_send_debug("Your host '%.200s' is not permitted to use this key for login.",
424 get_canonical_hostname());
425 xfree(patterns);
426 authenticated = 0;
427 break;
428 }
429 xfree(patterns);
430 /* Host name matches. */
431 goto next_option;
432 }
433 bad_option:
434 /* Unknown option. */
435 log("Bad options in %.100s file, line %lu: %.50s",
436 SSH_USER_PERMITTED_KEYS, linenum, options);
437 packet_send_debug("Bad options in %.100s file, line %lu: %.50s",
438 SSH_USER_PERMITTED_KEYS, linenum, options);
439 authenticated = 0;
440 break;
441
442 next_option:
443 /* Skip the comma, and move to the next option (or break out
444 if there are no more). */
445 if (!*options)
446 fatal("Bugs in auth-rsa.c option processing.");
447 if (*options == ' ' || *options == '\t')
448 break; /* End of options. */
449 if (*options != ',')
450 goto bad_option;
451 options++;
452 /* Process the next option. */
453 continue;
454 }
455 }
456
457 /* Break out of the loop if authentication was successful; otherwise
458 continue searching. */
459 if (authenticated)
460 break;
461 }
462
463 /* Restore the privileged uid. */
464 restore_uid();
465
466 /* Close the file. */
467 fclose(f);
468
469 /* Clear any mp-int variables. */
470 BN_clear_free(n);
471 BN_clear_free(e);
472
473 if (authenticated)
474 packet_send_debug("RSA authentication accepted.");
475
476 /* Return authentication result. */
477 return authenticated;
478}
diff --git a/auth-skey.c b/auth-skey.c
new file mode 100644
index 000000000..9ec170494
--- /dev/null
+++ b/auth-skey.c
@@ -0,0 +1,149 @@
1#include "includes.h"
2RCSID("$Id: auth-skey.c,v 1.2 1999/10/16 20:57:52 deraadt Exp $");
3
4#include "ssh.h"
5#include <sha1.h>
6
7/* from %OpenBSD: skeylogin.c,v 1.32 1999/08/16 14:46:56 millert Exp % */
8
9
10#define ROUND(x) (((x)[0] << 24) + (((x)[1]) << 16) + (((x)[2]) << 8) + \
11 ((x)[3]))
12
13/*
14 * hash_collapse()
15 */
16static u_int32_t
17hash_collapse(s)
18 u_char *s;
19{
20 int len, target;
21 u_int32_t i;
22
23 if ((strlen(s) % sizeof(u_int32_t)) == 0)
24 target = strlen(s); /* Multiple of 4 */
25 else
26 target = strlen(s) - (strlen(s) % sizeof(u_int32_t));
27
28 for (i = 0, len = 0; len < target; len += 4)
29 i ^= ROUND(s + len);
30
31 return i;
32}
33char *
34skey_fake_keyinfo(char *username)
35{
36 int i;
37 u_int ptr;
38 u_char hseed[SKEY_MAX_SEED_LEN], flg = 1, *up;
39 char pbuf[SKEY_MAX_PW_LEN+1];
40 static char skeyprompt[SKEY_MAX_CHALLENGE+1];
41 char *secret = NULL;
42 size_t secretlen = 0;
43 SHA1_CTX ctx;
44 char *p, *u;
45
46 /*
47 * Base first 4 chars of seed on hostname.
48 * Add some filler for short hostnames if necessary.
49 */
50 if (gethostname(pbuf, sizeof(pbuf)) == -1)
51 *(p = pbuf) = '.';
52 else
53 for (p = pbuf; *p && isalnum(*p); p++)
54 if (isalpha(*p) && isupper(*p))
55 *p = tolower(*p);
56 if (*p && pbuf - p < 4)
57 (void)strncpy(p, "asjd", 4 - (pbuf - p));
58 pbuf[4] = '\0';
59
60 /* Hash the username if possible */
61 if ((up = SHA1Data(username, strlen(username), NULL)) != NULL) {
62 struct stat sb;
63 time_t t;
64 int fd;
65
66 /* Collapse the hash */
67 ptr = hash_collapse(up);
68 memset(up, 0, strlen(up));
69
70 /* See if the random file's there, else use ctime */
71 if ((fd = open(_SKEY_RAND_FILE_PATH_, O_RDONLY)) != -1
72 && fstat(fd, &sb) == 0 &&
73 sb.st_size > (off_t)SKEY_MAX_SEED_LEN &&
74 lseek(fd, ptr % (sb.st_size - SKEY_MAX_SEED_LEN),
75 SEEK_SET) != -1 && read(fd, hseed,
76 SKEY_MAX_SEED_LEN) == SKEY_MAX_SEED_LEN) {
77 close(fd);
78 secret = hseed;
79 secretlen = SKEY_MAX_SEED_LEN;
80 flg = 0;
81 } else if (!stat(_PATH_MEM, &sb) || !stat("/", &sb)) {
82 t = sb.st_ctime;
83 secret = ctime(&t);
84 secretlen = strlen(secret);
85 flg = 0;
86 }
87 }
88
89 /* Put that in your pipe and smoke it */
90 if (flg == 0) {
91 /* Hash secret value with username */
92 SHA1Init(&ctx);
93 SHA1Update(&ctx, secret, secretlen);
94 SHA1Update(&ctx, username, strlen(username));
95 SHA1End(&ctx, up);
96
97 /* Zero out */
98 memset(secret, 0, secretlen);
99
100 /* Now hash the hash */
101 SHA1Init(&ctx);
102 SHA1Update(&ctx, up, strlen(up));
103 SHA1End(&ctx, up);
104
105 ptr = hash_collapse(up + 4);
106
107 for (i = 4; i < 9; i++) {
108 pbuf[i] = (ptr % 10) + '0';
109 ptr /= 10;
110 }
111 pbuf[i] = '\0';
112
113 /* Sequence number */
114 ptr = ((up[2] + up[3]) % 99) + 1;
115
116 memset(up, 0, 20); /* SHA1 specific */
117 free(up);
118
119 (void)snprintf(skeyprompt, sizeof skeyprompt,
120 "otp-%.*s %d %.*s",
121 SKEY_MAX_HASHNAME_LEN,
122 skey_get_algorithm(),
123 ptr, SKEY_MAX_SEED_LEN,
124 pbuf);
125 } else {
126 /* Base last 8 chars of seed on username */
127 u = username;
128 i = 8;
129 p = &pbuf[4];
130 do {
131 if (*u == 0) {
132 /* Pad remainder with zeros */
133 while (--i >= 0)
134 *p++ = '0';
135 break;
136 }
137
138 *p++ = (*u++ % 10) + '0';
139 } while (--i != 0);
140 pbuf[12] = '\0';
141
142 (void)snprintf(skeyprompt, sizeof skeyprompt,
143 "otp-%.*s %d %.*s",
144 SKEY_MAX_HASHNAME_LEN,
145 skey_get_algorithm(),
146 99, SKEY_MAX_SEED_LEN, pbuf);
147 }
148 return skeyprompt;
149}
diff --git a/authfd.c b/authfd.c
new file mode 100644
index 000000000..07893caf3
--- /dev/null
+++ b/authfd.c
@@ -0,0 +1,565 @@
1/*
2
3authfd.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Wed Mar 29 01:30:28 1995 ylo
11
12Functions for connecting the local authentication agent.
13
14*/
15
16#include "includes.h"
17RCSID("$Id: authfd.c,v 1.1 1999/10/27 03:42:43 damien Exp $");
18
19#include "ssh.h"
20#include "rsa.h"
21#include "authfd.h"
22#include "buffer.h"
23#include "bufaux.h"
24#include "xmalloc.h"
25#include "getput.h"
26
27#include <openssl/rsa.h>
28
29/* Returns the number of the authentication fd, or -1 if there is none. */
30
31int
32ssh_get_authentication_socket()
33{
34 const char *authsocket;
35 int sock;
36 struct sockaddr_un sunaddr;
37
38 authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
39 if (!authsocket)
40 return -1;
41
42 sunaddr.sun_family = AF_UNIX;
43 strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
44
45 sock = socket(AF_UNIX, SOCK_STREAM, 0);
46 if (sock < 0)
47 return -1;
48
49 if (connect(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0)
50 {
51 close(sock);
52 return -1;
53 }
54
55 return sock;
56}
57
58/* Closes the agent socket if it should be closed (depends on how it was
59 obtained). The argument must have been returned by
60 ssh_get_authentication_socket(). */
61
62void ssh_close_authentication_socket(int sock)
63{
64 if (getenv(SSH_AUTHSOCKET_ENV_NAME))
65 close(sock);
66}
67
68/* Opens and connects a private socket for communication with the
69 authentication agent. Returns the file descriptor (which must be
70 shut down and closed by the caller when no longer needed).
71 Returns NULL if an error occurred and the connection could not be
72 opened. */
73
74AuthenticationConnection *ssh_get_authentication_connection()
75{
76 AuthenticationConnection *auth;
77 int sock;
78
79 sock = ssh_get_authentication_socket();
80
81 /* Fail if we couldn't obtain a connection. This happens if we exited
82 due to a timeout. */
83 if (sock < 0)
84 return NULL;
85
86 /* Applocate the connection structure and initialize it. */
87 auth = xmalloc(sizeof(*auth));
88 auth->fd = sock;
89 buffer_init(&auth->packet);
90 buffer_init(&auth->identities);
91 auth->howmany = 0;
92
93 return auth;
94}
95
96/* Closes the connection to the authentication agent and frees any associated
97 memory. */
98
99void ssh_close_authentication_connection(AuthenticationConnection *ac)
100{
101 buffer_free(&ac->packet);
102 buffer_free(&ac->identities);
103 close(ac->fd);
104 /* Free the connection data structure. */
105 xfree(ac);
106}
107
108/* Returns the first authentication identity held by the agent.
109 Returns true if an identity is available, 0 otherwise.
110 The caller must initialize the integers before the call, and free the
111 comment after a successful call (before calling ssh_get_next_identity). */
112
113int
114ssh_get_first_identity(AuthenticationConnection *auth,
115 int *bitsp, BIGNUM *e, BIGNUM *n, char **comment)
116{
117 unsigned char msg[8192];
118 int len, l;
119
120 /* Send a message to the agent requesting for a list of the identities
121 it can represent. */
122 msg[0] = 0;
123 msg[1] = 0;
124 msg[2] = 0;
125 msg[3] = 1;
126 msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
127 if (write(auth->fd, msg, 5) != 5)
128 {
129 error("write auth->fd: %.100s", strerror(errno));
130 return 0;
131 }
132
133 /* Read the length of the response. XXX implement timeouts here. */
134 len = 4;
135 while (len > 0)
136 {
137 l = read(auth->fd, msg + 4 - len, len);
138 if (l <= 0)
139 {
140 error("read auth->fd: %.100s", strerror(errno));
141 return 0;
142 }
143 len -= l;
144 }
145
146 /* Extract the length, and check it for sanity. (We cannot trust
147 authentication agents). */
148 len = GET_32BIT(msg);
149 if (len < 1 || len > 256*1024)
150 fatal("Authentication reply message too long: %d\n", len);
151
152 /* Read the packet itself. */
153 buffer_clear(&auth->identities);
154 while (len > 0)
155 {
156 l = len;
157 if (l > sizeof(msg))
158 l = sizeof(msg);
159 l = read(auth->fd, msg, l);
160 if (l <= 0)
161 fatal("Incomplete authentication reply.");
162 buffer_append(&auth->identities, (char *)msg, l);
163 len -= l;
164 }
165
166 /* Get message type, and verify that we got a proper answer. */
167 buffer_get(&auth->identities, (char *)msg, 1);
168 if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER)
169 fatal("Bad authentication reply message type: %d", msg[0]);
170
171 /* Get the number of entries in the response and check it for sanity. */
172 auth->howmany = buffer_get_int(&auth->identities);
173 if (auth->howmany > 1024)
174 fatal("Too many identities in authentication reply: %d\n", auth->howmany);
175
176 /* Return the first entry (if any). */
177 return ssh_get_next_identity(auth, bitsp, e, n, comment);
178}
179
180/* Returns the next authentication identity for the agent. Other functions
181 can be called between this and ssh_get_first_identity or two calls of this
182 function. This returns 0 if there are no more identities. The caller
183 must free comment after a successful return. */
184
185int
186ssh_get_next_identity(AuthenticationConnection *auth,
187 int *bitsp, BIGNUM *e, BIGNUM *n, char **comment)
188{
189 /* Return failure if no more entries. */
190 if (auth->howmany <= 0)
191 return 0;
192
193 /* Get the next entry from the packet. These will abort with a fatal
194 error if the packet is too short or contains corrupt data. */
195 *bitsp = buffer_get_int(&auth->identities);
196 buffer_get_bignum(&auth->identities, e);
197 buffer_get_bignum(&auth->identities, n);
198 *comment = buffer_get_string(&auth->identities, NULL);
199
200 /* Decrement the number of remaining entries. */
201 auth->howmany--;
202
203 return 1;
204}
205
206/* Generates a random challenge, sends it to the agent, and waits for response
207 from the agent. Returns true (non-zero) if the agent gave the correct
208 answer, zero otherwise. Response type selects the style of response
209 desired, with 0 corresponding to protocol version 1.0 (no longer supported)
210 and 1 corresponding to protocol version 1.1. */
211
212int
213ssh_decrypt_challenge(AuthenticationConnection *auth,
214 int bits, BIGNUM *e, BIGNUM *n, BIGNUM *challenge,
215 unsigned char session_id[16],
216 unsigned int response_type,
217 unsigned char response[16])
218{
219 Buffer buffer;
220 unsigned char buf[8192];
221 int len, l, i;
222
223 /* Response type 0 is no longer supported. */
224 if (response_type == 0)
225 fatal("Compatibility with ssh protocol version 1.0 no longer supported.");
226
227 /* Format a message to the agent. */
228 buf[0] = SSH_AGENTC_RSA_CHALLENGE;
229 buffer_init(&buffer);
230 buffer_append(&buffer, (char *)buf, 1);
231 buffer_put_int(&buffer, bits);
232 buffer_put_bignum(&buffer, e);
233 buffer_put_bignum(&buffer, n);
234 buffer_put_bignum(&buffer, challenge);
235 buffer_append(&buffer, (char *)session_id, 16);
236 buffer_put_int(&buffer, response_type);
237
238 /* Get the length of the message, and format it in the buffer. */
239 len = buffer_len(&buffer);
240 PUT_32BIT(buf, len);
241
242 /* Send the length and then the packet to the agent. */
243 if (write(auth->fd, buf, 4) != 4 ||
244 write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
245 buffer_len(&buffer))
246 {
247 error("Error writing to authentication socket.");
248 error_cleanup:
249 buffer_free(&buffer);
250 return 0;
251 }
252
253 /* Wait for response from the agent. First read the length of the
254 response packet. */
255 len = 4;
256 while (len > 0)
257 {
258 l = read(auth->fd, buf + 4 - len, len);
259 if (l <= 0)
260 {
261 error("Error reading response length from authentication socket.");
262 goto error_cleanup;
263 }
264 len -= l;
265 }
266
267 /* Extract the length, and check it for sanity. */
268 len = GET_32BIT(buf);
269 if (len > 256*1024)
270 fatal("Authentication response too long: %d", len);
271
272 /* Read the rest of the response in tothe buffer. */
273 buffer_clear(&buffer);
274 while (len > 0)
275 {
276 l = len;
277 if (l > sizeof(buf))
278 l = sizeof(buf);
279 l = read(auth->fd, buf, l);
280 if (l <= 0)
281 {
282 error("Error reading response from authentication socket.");
283 goto error_cleanup;
284 }
285 buffer_append(&buffer, (char *)buf, l);
286 len -= l;
287 }
288
289 /* Get the type of the packet. */
290 buffer_get(&buffer, (char *)buf, 1);
291
292 /* Check for agent failure message. */
293 if (buf[0] == SSH_AGENT_FAILURE)
294 {
295 log("Agent admitted failure to authenticate using the key.");
296 goto error_cleanup;
297 }
298
299 /* Now it must be an authentication response packet. */
300 if (buf[0] != SSH_AGENT_RSA_RESPONSE)
301 fatal("Bad authentication response: %d", buf[0]);
302
303 /* Get the response from the packet. This will abort with a fatal error
304 if the packet is corrupt. */
305 for (i = 0; i < 16; i++)
306 response[i] = buffer_get_char(&buffer);
307
308 /* The buffer containing the packet is no longer needed. */
309 buffer_free(&buffer);
310
311 /* Correct answer. */
312 return 1;
313}
314
315/* Adds an identity to the authentication server. This call is not meant to
316 be used by normal applications. */
317
318int ssh_add_identity(AuthenticationConnection *auth,
319 RSA *key, const char *comment)
320{
321 Buffer buffer;
322 unsigned char buf[8192];
323 int len, l, type;
324
325 /* Format a message to the agent. */
326 buffer_init(&buffer);
327 buffer_put_char(&buffer, SSH_AGENTC_ADD_RSA_IDENTITY);
328 buffer_put_int(&buffer, BN_num_bits(key->n));
329 buffer_put_bignum(&buffer, key->n);
330 buffer_put_bignum(&buffer, key->e);
331 buffer_put_bignum(&buffer, key->d);
332 /* To keep within the protocol: p < q for ssh. in SSL p > q */
333 buffer_put_bignum(&buffer, key->iqmp); /* ssh key->u */
334 buffer_put_bignum(&buffer, key->q); /* ssh key->p, SSL key->q */
335 buffer_put_bignum(&buffer, key->p); /* ssh key->q, SSL key->p */
336 buffer_put_string(&buffer, comment, strlen(comment));
337
338 /* Get the length of the message, and format it in the buffer. */
339 len = buffer_len(&buffer);
340 PUT_32BIT(buf, len);
341
342 /* Send the length and then the packet to the agent. */
343 if (write(auth->fd, buf, 4) != 4 ||
344 write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
345 buffer_len(&buffer))
346 {
347 error("Error writing to authentication socket.");
348 error_cleanup:
349 buffer_free(&buffer);
350 return 0;
351 }
352
353 /* Wait for response from the agent. First read the length of the
354 response packet. */
355 len = 4;
356 while (len > 0)
357 {
358 l = read(auth->fd, buf + 4 - len, len);
359 if (l <= 0)
360 {
361 error("Error reading response length from authentication socket.");
362 goto error_cleanup;
363 }
364 len -= l;
365 }
366
367 /* Extract the length, and check it for sanity. */
368 len = GET_32BIT(buf);
369 if (len > 256*1024)
370 fatal("Add identity response too long: %d", len);
371
372 /* Read the rest of the response in tothe buffer. */
373 buffer_clear(&buffer);
374 while (len > 0)
375 {
376 l = len;
377 if (l > sizeof(buf))
378 l = sizeof(buf);
379 l = read(auth->fd, buf, l);
380 if (l <= 0)
381 {
382 error("Error reading response from authentication socket.");
383 goto error_cleanup;
384 }
385 buffer_append(&buffer, (char *)buf, l);
386 len -= l;
387 }
388
389 /* Get the type of the packet. */
390 type = buffer_get_char(&buffer);
391 switch (type)
392 {
393 case SSH_AGENT_FAILURE:
394 buffer_free(&buffer);
395 return 0;
396 case SSH_AGENT_SUCCESS:
397 buffer_free(&buffer);
398 return 1;
399 default:
400 fatal("Bad response to add identity from authentication agent: %d",
401 type);
402 }
403 /*NOTREACHED*/
404 return 0;
405}
406
407/* Removes an identity from the authentication server. This call is not meant
408 to be used by normal applications. */
409
410int ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
411{
412 Buffer buffer;
413 unsigned char buf[8192];
414 int len, l, type;
415
416 /* Format a message to the agent. */
417 buffer_init(&buffer);
418 buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY);
419 buffer_put_int(&buffer, BN_num_bits(key->n));
420 buffer_put_bignum(&buffer, key->e);
421 buffer_put_bignum(&buffer, key->n);
422
423 /* Get the length of the message, and format it in the buffer. */
424 len = buffer_len(&buffer);
425 PUT_32BIT(buf, len);
426
427 /* Send the length and then the packet to the agent. */
428 if (write(auth->fd, buf, 4) != 4 ||
429 write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
430 buffer_len(&buffer))
431 {
432 error("Error writing to authentication socket.");
433 error_cleanup:
434 buffer_free(&buffer);
435 return 0;
436 }
437
438 /* Wait for response from the agent. First read the length of the
439 response packet. */
440 len = 4;
441 while (len > 0)
442 {
443 l = read(auth->fd, buf + 4 - len, len);
444 if (l <= 0)
445 {
446 error("Error reading response length from authentication socket.");
447 goto error_cleanup;
448 }
449 len -= l;
450 }
451
452 /* Extract the length, and check it for sanity. */
453 len = GET_32BIT(buf);
454 if (len > 256*1024)
455 fatal("Remove identity response too long: %d", len);
456
457 /* Read the rest of the response in tothe buffer. */
458 buffer_clear(&buffer);
459 while (len > 0)
460 {
461 l = len;
462 if (l > sizeof(buf))
463 l = sizeof(buf);
464 l = read(auth->fd, buf, l);
465 if (l <= 0)
466 {
467 error("Error reading response from authentication socket.");
468 goto error_cleanup;
469 }
470 buffer_append(&buffer, (char *)buf, l);
471 len -= l;
472 }
473
474 /* Get the type of the packet. */
475 type = buffer_get_char(&buffer);
476 switch (type)
477 {
478 case SSH_AGENT_FAILURE:
479 buffer_free(&buffer);
480 return 0;
481 case SSH_AGENT_SUCCESS:
482 buffer_free(&buffer);
483 return 1;
484 default:
485 fatal("Bad response to remove identity from authentication agent: %d",
486 type);
487 }
488 /*NOTREACHED*/
489 return 0;
490}
491
492/* Removes all identities from the agent. This call is not meant
493 to be used by normal applications. */
494
495int ssh_remove_all_identities(AuthenticationConnection *auth)
496{
497 Buffer buffer;
498 unsigned char buf[8192];
499 int len, l, type;
500
501 /* Get the length of the message, and format it in the buffer. */
502 PUT_32BIT(buf, 1);
503 buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;
504
505 /* Send the length and then the packet to the agent. */
506 if (write(auth->fd, buf, 5) != 5)
507 {
508 error("Error writing to authentication socket.");
509 return 0;
510 }
511
512 /* Wait for response from the agent. First read the length of the
513 response packet. */
514 len = 4;
515 while (len > 0)
516 {
517 l = read(auth->fd, buf + 4 - len, len);
518 if (l <= 0)
519 {
520 error("Error reading response length from authentication socket.");
521 return 0;
522 }
523 len -= l;
524 }
525
526 /* Extract the length, and check it for sanity. */
527 len = GET_32BIT(buf);
528 if (len > 256*1024)
529 fatal("Remove identity response too long: %d", len);
530
531 /* Read the rest of the response into the buffer. */
532 buffer_init(&buffer);
533 while (len > 0)
534 {
535 l = len;
536 if (l > sizeof(buf))
537 l = sizeof(buf);
538 l = read(auth->fd, buf, l);
539 if (l <= 0)
540 {
541 error("Error reading response from authentication socket.");
542 buffer_free(&buffer);
543 return 0;
544 }
545 buffer_append(&buffer, (char *)buf, l);
546 len -= l;
547 }
548
549 /* Get the type of the packet. */
550 type = buffer_get_char(&buffer);
551 switch (type)
552 {
553 case SSH_AGENT_FAILURE:
554 buffer_free(&buffer);
555 return 0;
556 case SSH_AGENT_SUCCESS:
557 buffer_free(&buffer);
558 return 1;
559 default:
560 fatal("Bad response to remove identity from authentication agent: %d",
561 type);
562 }
563 /*NOTREACHED*/
564 return 0;
565}
diff --git a/authfd.h b/authfd.h
new file mode 100644
index 000000000..1def920e3
--- /dev/null
+++ b/authfd.h
@@ -0,0 +1,102 @@
1/*
2
3authfd.h
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Wed Mar 29 01:17:41 1995 ylo
11
12Functions to interface with the SSH_AUTHENTICATION_FD socket.
13
14*/
15
16/* RCSID("$Id: authfd.h,v 1.1 1999/10/27 03:42:43 damien Exp $"); */
17
18#ifndef AUTHFD_H
19#define AUTHFD_H
20
21#include "buffer.h"
22
23/* Messages for the authentication agent connection. */
24#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
25#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2
26#define SSH_AGENTC_RSA_CHALLENGE 3
27#define SSH_AGENT_RSA_RESPONSE 4
28#define SSH_AGENT_FAILURE 5
29#define SSH_AGENT_SUCCESS 6
30#define SSH_AGENTC_ADD_RSA_IDENTITY 7
31#define SSH_AGENTC_REMOVE_RSA_IDENTITY 8
32#define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9
33
34typedef struct
35{
36 int fd;
37 Buffer packet;
38 Buffer identities;
39 int howmany;
40} AuthenticationConnection;
41
42/* Returns the number of the authentication fd, or -1 if there is none. */
43int ssh_get_authentication_socket();
44
45/* This should be called for any descriptor returned by
46 ssh_get_authentication_socket(). Depending on the way the descriptor was
47 obtained, this may close the descriptor. */
48void ssh_close_authentication_socket(int authfd);
49
50/* Opens and connects a private socket for communication with the
51 authentication agent. Returns NULL if an error occurred and the
52 connection could not be opened. The connection should be closed by
53 the caller by calling ssh_close_authentication_connection(). */
54AuthenticationConnection *ssh_get_authentication_connection();
55
56/* Closes the connection to the authentication agent and frees any associated
57 memory. */
58void ssh_close_authentication_connection(AuthenticationConnection *ac);
59
60/* Returns the first authentication identity held by the agent.
61 Returns true if an identity is available, 0 otherwise.
62 The caller must initialize the integers before the call, and free the
63 comment after a successful call (before calling ssh_get_next_identity). */
64int ssh_get_first_identity(AuthenticationConnection *connection,
65 int *bitsp, BIGNUM *e, BIGNUM *n, char **comment);
66
67/* Returns the next authentication identity for the agent. Other functions
68 can be called between this and ssh_get_first_identity or two calls of this
69 function. This returns 0 if there are no more identities. The caller
70 must free comment after a successful return. */
71int ssh_get_next_identity(AuthenticationConnection *connection,
72 int *bitsp, BIGNUM *e, BIGNUM *n, char **comment);
73
74/* Requests the agent to decrypt the given challenge. Returns true if
75 the agent claims it was able to decrypt it. */
76int ssh_decrypt_challenge(AuthenticationConnection *auth,
77 int bits, BIGNUM *e, BIGNUM *n, BIGNUM *challenge,
78 unsigned char session_id[16],
79 unsigned int response_type,
80 unsigned char response[16]);
81
82/* Adds an identity to the authentication server. This call is not meant to
83 be used by normal applications. This returns true if the identity
84 was successfully added. */
85int ssh_add_identity(AuthenticationConnection *connection,
86 RSA *key, const char *comment);
87
88/* Removes the identity from the authentication server. This call is
89 not meant to be used by normal applications. This returns true if the
90 identity was successfully added. */
91int ssh_remove_identity(AuthenticationConnection *connection,
92 RSA *key);
93
94/* Removes all identities from the authentication agent. This call is not
95 meant to be used by normal applications. This returns true if the
96 operation was successful. */
97int ssh_remove_all_identities(AuthenticationConnection *connection);
98
99/* Closes the connection to the authentication agent. */
100void ssh_close_authentication(AuthenticationConnection *connection);
101
102#endif /* AUTHFD_H */
diff --git a/authfile.c b/authfile.c
new file mode 100644
index 000000000..49390e083
--- /dev/null
+++ b/authfile.c
@@ -0,0 +1,350 @@
1/*
2
3authfile.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Mon Mar 27 03:52:05 1995 ylo
11
12This file contains functions for reading and writing identity files, and
13for reading the passphrase from the user.
14
15*/
16
17#include "includes.h"
18RCSID("$Id: authfile.c,v 1.1 1999/10/27 03:42:43 damien Exp $");
19
20#include <openssl/bn.h>
21#include "xmalloc.h"
22#include "buffer.h"
23#include "bufaux.h"
24#include "cipher.h"
25#include "ssh.h"
26
27/* Version identification string for identity files. */
28#define AUTHFILE_ID_STRING "SSH PRIVATE KEY FILE FORMAT 1.1\n"
29
30/* Saves the authentication (private) key in a file, encrypting it with
31 passphrase. The identification of the file (lowest 64 bits of n)
32 will precede the key to provide identification of the key without
33 needing a passphrase. */
34
35int
36save_private_key(const char *filename, const char *passphrase,
37 RSA *key, const char *comment)
38{
39 Buffer buffer, encrypted;
40 char buf[100], *cp;
41 int f, i;
42 CipherContext cipher;
43 int cipher_type;
44 u_int32_t rand;
45
46 /* If the passphrase is empty, use SSH_CIPHER_NONE to ease converting to
47 another cipher; otherwise use SSH_AUTHFILE_CIPHER. */
48 if (strcmp(passphrase, "") == 0)
49 cipher_type = SSH_CIPHER_NONE;
50 else
51 cipher_type = SSH_AUTHFILE_CIPHER;
52
53 /* This buffer is used to built the secret part of the private key. */
54 buffer_init(&buffer);
55
56 /* Put checkbytes for checking passphrase validity. */
57 rand = arc4random();
58 buf[0] = rand & 0xff;
59 buf[1] = (rand >> 8) & 0xff;
60 buf[2] = buf[0];
61 buf[3] = buf[1];
62 buffer_append(&buffer, buf, 4);
63
64 /* Store the private key (n and e will not be stored because they will
65 be stored in plain text, and storing them also in encrypted format
66 would just give known plaintext). */
67 buffer_put_bignum(&buffer, key->d);
68 buffer_put_bignum(&buffer, key->iqmp);
69 buffer_put_bignum(&buffer, key->q); /* reverse from SSL p */
70 buffer_put_bignum(&buffer, key->p); /* reverse from SSL q */
71
72 /* Pad the part to be encrypted until its size is a multiple of 8. */
73 while (buffer_len(&buffer) % 8 != 0)
74 buffer_put_char(&buffer, 0);
75
76 /* This buffer will be used to contain the data in the file. */
77 buffer_init(&encrypted);
78
79 /* First store keyfile id string. */
80 cp = AUTHFILE_ID_STRING;
81 for (i = 0; cp[i]; i++)
82 buffer_put_char(&encrypted, cp[i]);
83 buffer_put_char(&encrypted, 0);
84
85 /* Store cipher type. */
86 buffer_put_char(&encrypted, cipher_type);
87 buffer_put_int(&encrypted, 0); /* For future extension */
88
89 /* Store public key. This will be in plain text. */
90 buffer_put_int(&encrypted, BN_num_bits(key->n));
91 buffer_put_bignum(&encrypted, key->n);
92 buffer_put_bignum(&encrypted, key->e);
93 buffer_put_string(&encrypted, comment, strlen(comment));
94
95 /* Allocate space for the private part of the key in the buffer. */
96 buffer_append_space(&encrypted, &cp, buffer_len(&buffer));
97
98 cipher_set_key_string(&cipher, cipher_type, passphrase, 1);
99 cipher_encrypt(&cipher, (unsigned char *)cp,
100 (unsigned char *)buffer_ptr(&buffer),
101 buffer_len(&buffer));
102 memset(&cipher, 0, sizeof(cipher));
103
104 /* Destroy temporary data. */
105 memset(buf, 0, sizeof(buf));
106 buffer_free(&buffer);
107
108 /* Write to a file. */
109 f = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0600);
110 if (f < 0)
111 return 0;
112
113 if (write(f, buffer_ptr(&encrypted), buffer_len(&encrypted)) !=
114 buffer_len(&encrypted))
115 {
116 debug("Write to key file %.200s failed: %.100s", filename,
117 strerror(errno));
118 buffer_free(&encrypted);
119 close(f);
120 remove(filename);
121 return 0;
122 }
123 close(f);
124 buffer_free(&encrypted);
125 return 1;
126}
127
128/* Loads the public part of the key file. Returns 0 if an error
129 was encountered (the file does not exist or is not readable), and
130 non-zero otherwise. */
131
132int
133load_public_key(const char *filename, RSA *pub,
134 char **comment_return)
135{
136 int f, i;
137 off_t len;
138 Buffer buffer;
139 char *cp;
140
141 /* Read data from the file into the buffer. */
142 f = open(filename, O_RDONLY);
143 if (f < 0)
144 return 0;
145
146 len = lseek(f, (off_t)0, SEEK_END);
147 lseek(f, (off_t)0, SEEK_SET);
148
149 buffer_init(&buffer);
150 buffer_append_space(&buffer, &cp, len);
151
152 if (read(f, cp, (size_t)len) != (size_t)len)
153 {
154 debug("Read from key file %.200s failed: %.100s", filename,
155 strerror(errno));
156 buffer_free(&buffer);
157 close(f);
158 return 0;
159 }
160 close(f);
161
162 /* Check that it is at least big enought to contain the ID string. */
163 if (len < strlen(AUTHFILE_ID_STRING) + 1)
164 {
165 debug("Bad key file %.200s.", filename);
166 buffer_free(&buffer);
167 return 0;
168 }
169
170 /* Make sure it begins with the id string. Consume the id string from
171 the buffer. */
172 for (i = 0; i < (unsigned int)strlen(AUTHFILE_ID_STRING) + 1; i++)
173 if (buffer_get_char(&buffer) != (unsigned char)AUTHFILE_ID_STRING[i])
174 {
175 debug("Bad key file %.200s.", filename);
176 buffer_free(&buffer);
177 return 0;
178 }
179
180 /* Skip cipher type and reserved data. */
181 (void)buffer_get_char(&buffer); /* cipher type */
182 (void)buffer_get_int(&buffer); /* reserved */
183
184 /* Read the public key from the buffer. */
185 buffer_get_int(&buffer);
186 pub->n = BN_new();
187 buffer_get_bignum(&buffer, pub->n);
188 pub->e = BN_new();
189 buffer_get_bignum(&buffer, pub->e);
190 if (comment_return)
191 *comment_return = buffer_get_string(&buffer, NULL);
192 /* The encrypted private part is not parsed by this function. */
193
194 buffer_free(&buffer);
195
196 return 1;
197}
198
199/* Loads the private key from the file. Returns 0 if an error is encountered
200 (file does not exist or is not readable, or passphrase is bad).
201 This initializes the private key. */
202
203int
204load_private_key(const char *filename, const char *passphrase,
205 RSA *prv, char **comment_return)
206{
207 int f, i, check1, check2, cipher_type;
208 off_t len;
209 Buffer buffer, decrypted;
210 char *cp;
211 CipherContext cipher;
212 BN_CTX *ctx;
213 BIGNUM *aux;
214 struct stat st;
215
216 /* Read the file into the buffer. */
217 f = open(filename, O_RDONLY);
218 if (f < 0)
219 return 0;
220
221 /* We assume we are called under uid of the owner of the file */
222 if (fstat(f, &st) < 0 ||
223 (st.st_uid != 0 && st.st_uid != getuid()) ||
224 (st.st_mode & 077) != 0) {
225 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
226 error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");
227 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
228 error("Bad ownership or mode(0%3.3o) for '%s'.",
229 st.st_mode & 0777, filename);
230 error("It is recommended that your private key files are NOT accessible by others.");
231 return 0;
232 }
233
234 len = lseek(f, (off_t)0, SEEK_END);
235 lseek(f, (off_t)0, SEEK_SET);
236
237 buffer_init(&buffer);
238 buffer_append_space(&buffer, &cp, len);
239
240 if (read(f, cp, (size_t)len) != (size_t)len)
241 {
242 debug("Read from key file %.200s failed: %.100s", filename,
243 strerror(errno));
244 buffer_free(&buffer);
245 close(f);
246 return 0;
247 }
248 close(f);
249
250 /* Check that it is at least big enought to contain the ID string. */
251 if (len < strlen(AUTHFILE_ID_STRING) + 1)
252 {
253 debug("Bad key file %.200s.", filename);
254 buffer_free(&buffer);
255 return 0;
256 }
257
258 /* Make sure it begins with the id string. Consume the id string from
259 the buffer. */
260 for (i = 0; i < (unsigned int)strlen(AUTHFILE_ID_STRING) + 1; i++)
261 if (buffer_get_char(&buffer) != (unsigned char)AUTHFILE_ID_STRING[i])
262 {
263 debug("Bad key file %.200s.", filename);
264 buffer_free(&buffer);
265 return 0;
266 }
267
268 /* Read cipher type. */
269 cipher_type = buffer_get_char(&buffer);
270 (void)buffer_get_int(&buffer); /* Reserved data. */
271
272 /* Read the public key from the buffer. */
273 buffer_get_int(&buffer);
274 prv->n = BN_new();
275 buffer_get_bignum(&buffer, prv->n);
276 prv->e = BN_new();
277 buffer_get_bignum(&buffer, prv->e);
278 if (comment_return)
279 *comment_return = buffer_get_string(&buffer, NULL);
280 else
281 xfree(buffer_get_string(&buffer, NULL));
282
283 /* Check that it is a supported cipher. */
284 if (((cipher_mask() | SSH_CIPHER_NONE | SSH_AUTHFILE_CIPHER) &
285 (1 << cipher_type)) == 0)
286 {
287 debug("Unsupported cipher %.100s used in key file %.200s.",
288 cipher_name(cipher_type), filename);
289 buffer_free(&buffer);
290 goto fail;
291 }
292
293 /* Initialize space for decrypted data. */
294 buffer_init(&decrypted);
295 buffer_append_space(&decrypted, &cp, buffer_len(&buffer));
296
297 /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
298 cipher_set_key_string(&cipher, cipher_type, passphrase, 0);
299 cipher_decrypt(&cipher, (unsigned char *)cp,
300 (unsigned char *)buffer_ptr(&buffer),
301 buffer_len(&buffer));
302
303 buffer_free(&buffer);
304
305 check1 = buffer_get_char(&decrypted);
306 check2 = buffer_get_char(&decrypted);
307 if (check1 != buffer_get_char(&decrypted) ||
308 check2 != buffer_get_char(&decrypted))
309 {
310 if (strcmp(passphrase, "") != 0)
311 debug("Bad passphrase supplied for key file %.200s.", filename);
312 /* Bad passphrase. */
313 buffer_free(&decrypted);
314 fail:
315 BN_clear_free(prv->n);
316 BN_clear_free(prv->e);
317 if (comment_return)
318 xfree(*comment_return);
319 return 0;
320 }
321
322 /* Read the rest of the private key. */
323 prv->d = BN_new();
324 buffer_get_bignum(&decrypted, prv->d);
325 prv->iqmp = BN_new();
326 buffer_get_bignum(&decrypted, prv->iqmp); /* u */
327 /* in SSL and SSH p and q are exchanged */
328 prv->q = BN_new();
329 buffer_get_bignum(&decrypted, prv->q); /* p */
330 prv->p = BN_new();
331 buffer_get_bignum(&decrypted, prv->p); /* q */
332
333 ctx = BN_CTX_new();
334 aux = BN_new();
335
336 BN_sub(aux, prv->q, BN_value_one());
337 prv->dmq1 = BN_new();
338 BN_mod(prv->dmq1, prv->d, aux, ctx);
339
340 BN_sub(aux, prv->p, BN_value_one());
341 prv->dmp1 = BN_new();
342 BN_mod(prv->dmp1, prv->d, aux, ctx);
343
344 BN_clear_free(aux);
345 BN_CTX_free(ctx);
346
347 buffer_free(&decrypted);
348
349 return 1;
350}
diff --git a/bufaux.c b/bufaux.c
new file mode 100644
index 000000000..1ae39d67a
--- /dev/null
+++ b/bufaux.c
@@ -0,0 +1,141 @@
1/*
2
3bufaux.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Wed Mar 29 02:24:47 1995 ylo
11
12Auxiliary functions for storing and retrieving various data types to/from
13Buffers.
14
15*/
16
17#include "includes.h"
18RCSID("$Id: bufaux.c,v 1.1 1999/10/27 03:42:43 damien Exp $");
19
20#include "ssh.h"
21#include <openssl/bn.h>
22#include "bufaux.h"
23#include "xmalloc.h"
24#include "getput.h"
25
26/* Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed
27 by (bits+7)/8 bytes of binary data, msb first. */
28
29void
30buffer_put_bignum(Buffer *buffer, BIGNUM *value)
31{
32 int bits = BN_num_bits(value);
33 int bin_size = (bits + 7) / 8;
34 char *buf = xmalloc(bin_size);
35 int oi;
36 char msg[2];
37
38 /* Get the value of in binary */
39 oi = BN_bn2bin(value, buf);
40 assert(oi == bin_size);
41
42 /* Store the number of bits in the buffer in two bytes, msb first. */
43 PUT_16BIT(msg, bits);
44 buffer_append(buffer, msg, 2);
45 /* Store the binary data. */
46 buffer_append(buffer, buf, oi);
47 /* Clear the temporary data. */
48 memset(buf, 0, bin_size);
49 xfree(buf);
50}
51
52/* Retrieves an BIGNUM from the buffer. */
53
54int
55buffer_get_bignum(Buffer *buffer, BIGNUM *value)
56{
57 int bits, bytes;
58 unsigned char buf[2], *bin;
59
60 /* Get the number for bits. */
61 buffer_get(buffer, (char *)buf, 2);
62 bits = GET_16BIT(buf);
63 /* Compute the number of binary bytes that follow. */
64 bytes = (bits + 7) / 8;
65 bin = xmalloc(bytes);
66 buffer_get(buffer, bin, bytes);
67 BN_bin2bn(bin, bytes, value);
68 xfree(bin);
69
70 return 2 + bytes;
71}
72
73/* Returns an integer from the buffer (4 bytes, msb first). */
74
75unsigned int buffer_get_int(Buffer *buffer)
76{
77 unsigned char buf[4];
78 buffer_get(buffer, (char *)buf, 4);
79 return GET_32BIT(buf);
80}
81
82/* Stores an integer in the buffer in 4 bytes, msb first. */
83
84void buffer_put_int(Buffer *buffer, unsigned int value)
85{
86 char buf[4];
87 PUT_32BIT(buf, value);
88 buffer_append(buffer, buf, 4);
89}
90
91/* Returns an arbitrary binary string from the buffer. The string cannot
92 be longer than 256k. The returned value points to memory allocated
93 with xmalloc; it is the responsibility of the calling function to free
94 the data. If length_ptr is non-NULL, the length of the returned data
95 will be stored there. A null character will be automatically appended
96 to the returned string, and is not counted in length. */
97
98char *buffer_get_string(Buffer *buffer, unsigned int *length_ptr)
99{
100 unsigned int len;
101 char *value;
102 /* Get the length. */
103 len = buffer_get_int(buffer);
104 if (len > 256*1024)
105 fatal("Received packet with bad string length %d", len);
106 /* Allocate space for the string. Add one byte for a null character. */
107 value = xmalloc(len + 1);
108 /* Get the string. */
109 buffer_get(buffer, value, len);
110 /* Append a null character to make processing easier. */
111 value[len] = 0;
112 /* Optionally return the length of the string. */
113 if (length_ptr)
114 *length_ptr = len;
115 return value;
116}
117
118/* Stores and arbitrary binary string in the buffer. */
119
120void buffer_put_string(Buffer *buffer, const void *buf, unsigned int len)
121{
122 buffer_put_int(buffer, len);
123 buffer_append(buffer, buf, len);
124}
125
126/* Returns a character from the buffer (0 - 255). */
127
128int buffer_get_char(Buffer *buffer)
129{
130 char ch;
131 buffer_get(buffer, &ch, 1);
132 return (unsigned char)ch;
133}
134
135/* Stores a character in the buffer. */
136
137void buffer_put_char(Buffer *buffer, int value)
138{
139 char ch = value;
140 buffer_append(buffer, &ch, 1);
141}
diff --git a/bufaux.h b/bufaux.h
new file mode 100644
index 000000000..bfc668485
--- /dev/null
+++ b/bufaux.h
@@ -0,0 +1,51 @@
1/*
2
3bufaux.h
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Wed Mar 29 02:18:23 1995 ylo
11
12*/
13
14/* RCSID("$Id: bufaux.h,v 1.1 1999/10/27 03:42:43 damien Exp $"); */
15
16#ifndef BUFAUX_H
17#define BUFAUX_H
18
19#include "buffer.h"
20
21/* Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed
22 by (bits+7)/8 bytes of binary data, msb first. */
23void buffer_put_bignum(Buffer *buffer, BIGNUM *value);
24
25/* Retrieves an BIGNUM from the buffer. */
26int buffer_get_bignum(Buffer *buffer, BIGNUM *value);
27
28/* Returns an integer from the buffer (4 bytes, msb first). */
29unsigned int buffer_get_int(Buffer *buffer);
30
31/* Stores an integer in the buffer in 4 bytes, msb first. */
32void buffer_put_int(Buffer *buffer, unsigned int value);
33
34/* Returns a character from the buffer (0 - 255). */
35int buffer_get_char(Buffer *buffer);
36
37/* Stores a character in the buffer. */
38void buffer_put_char(Buffer *buffer, int value);
39
40/* Returns an arbitrary binary string from the buffer. The string cannot
41 be longer than 256k. The returned value points to memory allocated
42 with xmalloc; it is the responsibility of the calling function to free
43 the data. If length_ptr is non-NULL, the length of the returned data
44 will be stored there. A null character will be automatically appended
45 to the returned string, and is not counted in length. */
46char *buffer_get_string(Buffer *buffer, unsigned int *length_ptr);
47
48/* Stores and arbitrary binary string in the buffer. */
49void buffer_put_string(Buffer *buffer, const void *buf, unsigned int len);
50
51#endif /* BUFAUX_H */
diff --git a/buffer.c b/buffer.c
new file mode 100644
index 000000000..e183d1017
--- /dev/null
+++ b/buffer.c
@@ -0,0 +1,150 @@
1/*
2
3buffer.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Sat Mar 18 04:15:33 1995 ylo
11
12Functions for manipulating fifo buffers (that can grow if needed).
13
14*/
15
16#include "includes.h"
17RCSID("$Id: buffer.c,v 1.1 1999/10/27 03:42:43 damien Exp $");
18
19#include "xmalloc.h"
20#include "buffer.h"
21#include "ssh.h"
22
23/* Initializes the buffer structure. */
24
25void buffer_init(Buffer *buffer)
26{
27 buffer->alloc = 4096;
28 buffer->buf = xmalloc(buffer->alloc);
29 buffer->offset = 0;
30 buffer->end = 0;
31}
32
33/* Frees any memory used for the buffer. */
34
35void buffer_free(Buffer *buffer)
36{
37 memset(buffer->buf, 0, buffer->alloc);
38 xfree(buffer->buf);
39}
40
41/* Clears any data from the buffer, making it empty. This does not actually
42 zero the memory. */
43
44void buffer_clear(Buffer *buffer)
45{
46 buffer->offset = 0;
47 buffer->end = 0;
48}
49
50/* Appends data to the buffer, expanding it if necessary. */
51
52void buffer_append(Buffer *buffer, const char *data, unsigned int len)
53{
54 char *cp;
55 buffer_append_space(buffer, &cp, len);
56 memcpy(cp, data, len);
57}
58
59/* Appends space to the buffer, expanding the buffer if necessary.
60 This does not actually copy the data into the buffer, but instead
61 returns a pointer to the allocated region. */
62
63void buffer_append_space(Buffer *buffer, char **datap, unsigned int len)
64{
65 /* If the buffer is empty, start using it from the beginning. */
66 if (buffer->offset == buffer->end)
67 {
68 buffer->offset = 0;
69 buffer->end = 0;
70 }
71
72 restart:
73 /* If there is enough space to store all data, store it now. */
74 if (buffer->end + len < buffer->alloc)
75 {
76 *datap = buffer->buf + buffer->end;
77 buffer->end += len;
78 return;
79 }
80
81 /* If the buffer is quite empty, but all data is at the end, move the
82 data to the beginning and retry. */
83 if (buffer->offset > buffer->alloc / 2)
84 {
85 memmove(buffer->buf, buffer->buf + buffer->offset,
86 buffer->end - buffer->offset);
87 buffer->end -= buffer->offset;
88 buffer->offset = 0;
89 goto restart;
90 }
91
92 /* Increase the size of the buffer and retry. */
93 buffer->alloc += len + 32768;
94 buffer->buf = xrealloc(buffer->buf, buffer->alloc);
95 goto restart;
96}
97
98/* Returns the number of bytes of data in the buffer. */
99
100unsigned int buffer_len(Buffer *buffer)
101{
102 return buffer->end - buffer->offset;
103}
104
105/* Gets data from the beginning of the buffer. */
106
107void buffer_get(Buffer *buffer, char *buf, unsigned int len)
108{
109 if (len > buffer->end - buffer->offset)
110 fatal("buffer_get trying to get more bytes than in buffer");
111 memcpy(buf, buffer->buf + buffer->offset, len);
112 buffer->offset += len;
113}
114
115/* Consumes the given number of bytes from the beginning of the buffer. */
116
117void buffer_consume(Buffer *buffer, unsigned int bytes)
118{
119 if (bytes > buffer->end - buffer->offset)
120 fatal("buffer_get trying to get more bytes than in buffer");
121 buffer->offset += bytes;
122}
123
124/* Consumes the given number of bytes from the end of the buffer. */
125
126void buffer_consume_end(Buffer *buffer, unsigned int bytes)
127{
128 if (bytes > buffer->end - buffer->offset)
129 fatal("buffer_get trying to get more bytes than in buffer");
130 buffer->end -= bytes;
131}
132
133/* Returns a pointer to the first used byte in the buffer. */
134
135char *buffer_ptr(Buffer *buffer)
136{
137 return buffer->buf + buffer->offset;
138}
139
140/* Dumps the contents of the buffer to stderr. */
141
142void buffer_dump(Buffer *buffer)
143{
144 int i;
145 unsigned char *ucp = (unsigned char *)buffer->buf;
146
147 for (i = buffer->offset; i < buffer->end; i++)
148 fprintf(stderr, " %02x", ucp[i]);
149 fprintf(stderr, "\n");
150}
diff --git a/buffer.h b/buffer.h
new file mode 100644
index 000000000..d0369dc35
--- /dev/null
+++ b/buffer.h
@@ -0,0 +1,66 @@
1/*
2
3buffer.h
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Sat Mar 18 04:12:25 1995 ylo
11
12Code for manipulating FIFO buffers.
13
14*/
15
16/* RCSID("$Id: buffer.h,v 1.1 1999/10/27 03:42:43 damien Exp $"); */
17
18#ifndef BUFFER_H
19#define BUFFER_H
20
21typedef struct
22{
23 char *buf; /* Buffer for data. */
24 unsigned int alloc; /* Number of bytes allocated for data. */
25 unsigned int offset; /* Offset of first byte containing data. */
26 unsigned int end; /* Offset of last byte containing data. */
27} Buffer;
28
29/* Initializes the buffer structure. */
30void buffer_init(Buffer *buffer);
31
32/* Frees any memory used for the buffer. */
33void buffer_free(Buffer *buffer);
34
35/* Clears any data from the buffer, making it empty. This does not actually
36 zero the memory. */
37void buffer_clear(Buffer *buffer);
38
39/* Appends data to the buffer, expanding it if necessary. */
40void buffer_append(Buffer *buffer, const char *data, unsigned int len);
41
42/* Appends space to the buffer, expanding the buffer if necessary.
43 This does not actually copy the data into the buffer, but instead
44 returns a pointer to the allocated region. */
45void buffer_append_space(Buffer *buffer, char **datap, unsigned int len);
46
47/* Returns the number of bytes of data in the buffer. */
48unsigned int buffer_len(Buffer *buffer);
49
50/* Gets data from the beginning of the buffer. */
51void buffer_get(Buffer *buffer, char *buf, unsigned int len);
52
53/* Consumes the given number of bytes from the beginning of the buffer. */
54void buffer_consume(Buffer *buffer, unsigned int bytes);
55
56/* Consumes the given number of bytes from the end of the buffer. */
57void buffer_consume_end(Buffer *buffer, unsigned int bytes);
58
59/* Returns a pointer to the first used byte in the buffer. */
60char *buffer_ptr(Buffer *buffer);
61
62/* Dumps the contents of the buffer to stderr in hex. This intended for
63 debugging purposes only. */
64void buffer_dump(Buffer *buffer);
65
66#endif /* BUFFER_H */
diff --git a/canohost.c b/canohost.c
new file mode 100644
index 000000000..85d97292b
--- /dev/null
+++ b/canohost.c
@@ -0,0 +1,234 @@
1/*
2
3canohost.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Sun Jul 2 17:52:22 1995 ylo
11
12Functions for returning the canonical host name of the remote site.
13
14*/
15
16#include "includes.h"
17RCSID("$Id: canohost.c,v 1.1 1999/10/27 03:42:43 damien Exp $");
18
19#include "packet.h"
20#include "xmalloc.h"
21#include "ssh.h"
22
23/* Return the canonical name of the host at the other end of the socket.
24 The caller should free the returned string with xfree. */
25
26char *get_remote_hostname(int socket)
27{
28 struct sockaddr_in from;
29 int fromlen, i;
30 struct hostent *hp;
31 char name[MAXHOSTNAMELEN];
32
33 /* Get IP address of client. */
34 fromlen = sizeof(from);
35 memset(&from, 0, sizeof(from));
36 if (getpeername(socket, (struct sockaddr *)&from, &fromlen) < 0)
37 {
38 error("getpeername failed: %.100s", strerror(errno));
39 strlcpy(name, "UNKNOWN", sizeof name);
40 goto check_ip_options;
41 }
42
43 /* Map the IP address to a host name. */
44 hp = gethostbyaddr((char *)&from.sin_addr, sizeof(struct in_addr),
45 from.sin_family);
46 if (hp)
47 {
48 /* Got host name, find canonic host name. */
49 if (strchr(hp->h_name, '.') != 0)
50 strlcpy(name, hp->h_name, sizeof(name));
51 else if (hp->h_aliases != 0
52 && hp->h_aliases[0] != 0
53 && strchr(hp->h_aliases[0], '.') != 0)
54 strlcpy(name, hp->h_aliases[0], sizeof(name));
55 else
56 strlcpy(name, hp->h_name, sizeof(name));
57
58 /* Convert it to all lowercase (which is expected by the rest of this
59 software). */
60 for (i = 0; name[i]; i++)
61 if (isupper(name[i]))
62 name[i] = tolower(name[i]);
63
64 /* Map it back to an IP address and check that the given address actually
65 is an address of this host. This is necessary because anyone with
66 access to a name server can define arbitrary names for an IP address.
67 Mapping from name to IP address can be trusted better (but can still
68 be fooled if the intruder has access to the name server of the
69 domain). */
70 hp = gethostbyname(name);
71 if (!hp)
72 {
73 log("reverse mapping checking gethostbyname for %.700s failed - POSSIBLE BREAKIN ATTEMPT!", name);
74 strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);
75 goto check_ip_options;
76 }
77 /* Look for the address from the list of addresses. */
78 for (i = 0; hp->h_addr_list[i]; i++)
79 if (memcmp(hp->h_addr_list[i], &from.sin_addr, sizeof(from.sin_addr))
80 == 0)
81 break;
82 /* If we reached the end of the list, the address was not there. */
83 if (!hp->h_addr_list[i])
84 {
85 /* Address not found for the host name. */
86 log("Address %.100s maps to %.600s, but this does not map back to the address - POSSIBLE BREAKIN ATTEMPT!",
87 inet_ntoa(from.sin_addr), name);
88 strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);
89 goto check_ip_options;
90 }
91 /* Address was found for the host name. We accept the host name. */
92 }
93 else
94 {
95 /* Host name not found. Use ascii representation of the address. */
96 strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);
97 log("Could not reverse map address %.100s.", name);
98 }
99
100 check_ip_options:
101
102 /* If IP options are supported, make sure there are none (log and clear
103 them if any are found). Basically we are worried about source routing;
104 it can be used to pretend you are somebody (ip-address) you are not.
105 That itself may be "almost acceptable" under certain circumstances,
106 but rhosts autentication is useless if source routing is accepted.
107 Notice also that if we just dropped source routing here, the other
108 side could use IP spoofing to do rest of the interaction and could still
109 bypass security. So we exit here if we detect any IP options. */
110 {
111 unsigned char options[200], *ucp;
112 char text[1024], *cp;
113 int option_size, ipproto;
114 struct protoent *ip;
115
116 if ((ip = getprotobyname("ip")) != NULL)
117 ipproto = ip->p_proto;
118 else
119 ipproto = IPPROTO_IP;
120 option_size = sizeof(options);
121 if (getsockopt(0, ipproto, IP_OPTIONS, (char *)options,
122 &option_size) >= 0 && option_size != 0)
123 {
124 cp = text;
125 /* Note: "text" buffer must be at least 3x as big as options. */
126 for (ucp = options; option_size > 0; ucp++, option_size--, cp += 3)
127 sprintf(cp, " %2.2x", *ucp);
128 log("Connection from %.100s with IP options:%.800s",
129 inet_ntoa(from.sin_addr), text);
130 packet_disconnect("Connection from %.100s with IP options:%.800s",
131 inet_ntoa(from.sin_addr), text);
132 }
133 }
134
135 return xstrdup(name);
136}
137
138static char *canonical_host_name = NULL;
139static char *canonical_host_ip = NULL;
140
141/* Return the canonical name of the host in the other side of the current
142 connection. The host name is cached, so it is efficient to call this
143 several times. */
144
145const char *get_canonical_hostname()
146{
147 /* Check if we have previously retrieved this same name. */
148 if (canonical_host_name != NULL)
149 return canonical_host_name;
150
151 /* Get the real hostname if socket; otherwise return UNKNOWN. */
152 if (packet_get_connection_in() == packet_get_connection_out())
153 canonical_host_name = get_remote_hostname(packet_get_connection_in());
154 else
155 canonical_host_name = xstrdup("UNKNOWN");
156
157 return canonical_host_name;
158}
159
160/* Returns the IP-address of the remote host as a string. The returned
161 string need not be freed. */
162
163const char *get_remote_ipaddr()
164{
165 struct sockaddr_in from;
166 int fromlen, socket;
167
168 /* Check if we have previously retrieved this same name. */
169 if (canonical_host_ip != NULL)
170 return canonical_host_ip;
171
172 /* If not a socket, return UNKNOWN. */
173 if (packet_get_connection_in() != packet_get_connection_out())
174 {
175 canonical_host_ip = xstrdup("UNKNOWN");
176 return canonical_host_ip;
177 }
178
179 /* Get client socket. */
180 socket = packet_get_connection_in();
181
182 /* Get IP address of client. */
183 fromlen = sizeof(from);
184 memset(&from, 0, sizeof(from));
185 if (getpeername(socket, (struct sockaddr *)&from, &fromlen) < 0)
186 {
187 error("getpeername failed: %.100s", strerror(errno));
188 return NULL;
189 }
190
191 /* Get the IP address in ascii. */
192 canonical_host_ip = xstrdup(inet_ntoa(from.sin_addr));
193
194 /* Return ip address string. */
195 return canonical_host_ip;
196}
197
198/* Returns the port of the peer of the socket. */
199
200int get_peer_port(int sock)
201{
202 struct sockaddr_in from;
203 int fromlen;
204
205 /* Get IP address of client. */
206 fromlen = sizeof(from);
207 memset(&from, 0, sizeof(from));
208 if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0)
209 {
210 error("getpeername failed: %.100s", strerror(errno));
211 return 0;
212 }
213
214 /* Return port number. */
215 return ntohs(from.sin_port);
216}
217
218/* Returns the port number of the remote host. */
219
220int get_remote_port()
221{
222 int socket;
223
224 /* If the connection is not a socket, return 65535. This is intentionally
225 chosen to be an unprivileged port number. */
226 if (packet_get_connection_in() != packet_get_connection_out())
227 return 65535;
228
229 /* Get client socket. */
230 socket = packet_get_connection_in();
231
232 /* Get and return the peer port number. */
233 return get_peer_port(socket);
234}
diff --git a/channels.c b/channels.c
new file mode 100644
index 000000000..38a65a07f
--- /dev/null
+++ b/channels.c
@@ -0,0 +1,1500 @@
1/*
2
3channels.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Fri Mar 24 16:35:24 1995 ylo
11
12This file contains functions for generic socket connection forwarding.
13There is also code for initiating connection forwarding for X11 connections,
14arbitrary tcp/ip connections, and the authentication agent connection.
15
16*/
17
18#include "includes.h"
19RCSID("$Id: channels.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
20
21#include "ssh.h"
22#include "packet.h"
23#include "xmalloc.h"
24#include "buffer.h"
25#include "authfd.h"
26#include "uidswap.h"
27#include "servconf.h"
28
29#include "channels.h"
30#include "nchan.h"
31#include "compat.h"
32
33/* Maximum number of fake X11 displays to try. */
34#define MAX_DISPLAYS 1000
35
36/* Max len of agent socket */
37#define MAX_SOCKET_NAME 100
38
39/* Pointer to an array containing all allocated channels. The array is
40 dynamically extended as needed. */
41static Channel *channels = NULL;
42
43/* Size of the channel array. All slots of the array must always be
44 initialized (at least the type field); unused slots are marked with
45 type SSH_CHANNEL_FREE. */
46static int channels_alloc = 0;
47
48/* Maximum file descriptor value used in any of the channels. This is updated
49 in channel_allocate. */
50static int channel_max_fd_value = 0;
51
52/* Name and directory of socket for authentication agent forwarding. */
53static char *channel_forwarded_auth_socket_name = NULL;
54static char *channel_forwarded_auth_socket_dir = NULL;
55
56/* Saved X11 authentication protocol name. */
57char *x11_saved_proto = NULL;
58
59/* Saved X11 authentication data. This is the real data. */
60char *x11_saved_data = NULL;
61unsigned int x11_saved_data_len = 0;
62
63/* Fake X11 authentication data. This is what the server will be sending
64 us; we should replace any occurrences of this by the real data. */
65char *x11_fake_data = NULL;
66unsigned int x11_fake_data_len;
67
68/* Data structure for storing which hosts are permitted for forward requests.
69 The local sides of any remote forwards are stored in this array to prevent
70 a corrupt remote server from accessing arbitrary TCP/IP ports on our
71 local network (which might be behind a firewall). */
72typedef struct
73{
74 char *host; /* Host name. */
75 int port; /* Port number. */
76} ForwardPermission;
77
78/* List of all permitted host/port pairs to connect. */
79static ForwardPermission permitted_opens[SSH_MAX_FORWARDS_PER_DIRECTION];
80/* Number of permitted host/port pairs in the array. */
81static int num_permitted_opens = 0;
82/* If this is true, all opens are permitted. This is the case on the
83 server on which we have to trust the client anyway, and the user could
84 do anything after logging in anyway. */
85static int all_opens_permitted = 0;
86
87/* This is set to true if both sides support SSH_PROTOFLAG_HOST_IN_FWD_OPEN. */
88static int have_hostname_in_open = 0;
89
90/* Sets specific protocol options. */
91
92void channel_set_options(int hostname_in_open)
93{
94 have_hostname_in_open = hostname_in_open;
95}
96
97/* Permits opening to any host/port in SSH_MSG_PORT_OPEN. This is usually
98 called by the server, because the user could connect to any port anyway,
99 and the server has no way to know but to trust the client anyway. */
100
101void channel_permit_all_opens()
102{
103 all_opens_permitted = 1;
104}
105
106/* Allocate a new channel object and set its type and socket.
107 This will cause remote_name to be freed. */
108
109int channel_allocate(int type, int sock, char *remote_name)
110{
111 int i, old_channels;
112
113 /* Update the maximum file descriptor value. */
114 if (sock > channel_max_fd_value)
115 channel_max_fd_value = sock;
116
117 /* Do initial allocation if this is the first call. */
118 if (channels_alloc == 0)
119 {
120 channels_alloc = 10;
121 channels = xmalloc(channels_alloc * sizeof(Channel));
122 for (i = 0; i < channels_alloc; i++)
123 channels[i].type = SSH_CHANNEL_FREE;
124
125 /* Kludge: arrange a call to channel_stop_listening if we terminate
126 with fatal(). */
127 fatal_add_cleanup((void (*)(void *))channel_stop_listening, NULL);
128 }
129
130 /* Try to find a free slot where to put the new channel. */
131 for (i = 0; i < channels_alloc; i++)
132 if (channels[i].type == SSH_CHANNEL_FREE)
133 {
134 /* Found a free slot. Initialize the fields and return its number. */
135 buffer_init(&channels[i].input);
136 buffer_init(&channels[i].output);
137 channels[i].self = i;
138 channels[i].type = type;
139 channels[i].x11 = 0;
140 channels[i].sock = sock;
141 channels[i].remote_id = -1;
142 channels[i].remote_name = remote_name;
143 chan_init_iostates(&channels[i]);
144 return i;
145 }
146
147 /* There are no free slots. Must expand the array. */
148 old_channels = channels_alloc;
149 channels_alloc += 10;
150 channels = xrealloc(channels, channels_alloc * sizeof(Channel));
151 for (i = old_channels; i < channels_alloc; i++)
152 channels[i].type = SSH_CHANNEL_FREE;
153
154 /* We know that the next one after the old maximum channel number is now
155 available. Initialize and return its number. */
156 buffer_init(&channels[old_channels].input);
157 buffer_init(&channels[old_channels].output);
158 channels[old_channels].self = old_channels;
159 channels[old_channels].type = type;
160 channels[old_channels].x11 = 0;
161 channels[old_channels].sock = sock;
162 channels[old_channels].remote_id = -1;
163 channels[old_channels].remote_name = remote_name;
164 chan_init_iostates(&channels[old_channels]);
165 return old_channels;
166}
167
168/* Free the channel and close its socket. */
169
170void channel_free(int channel)
171{
172 assert(channel >= 0 && channel < channels_alloc &&
173 channels[channel].type != SSH_CHANNEL_FREE);
174 if(compat13)
175 shutdown(channels[channel].sock, SHUT_RDWR);
176 close(channels[channel].sock);
177 buffer_free(&channels[channel].input);
178 buffer_free(&channels[channel].output);
179 channels[channel].type = SSH_CHANNEL_FREE;
180 if (channels[channel].remote_name)
181 {
182 xfree(channels[channel].remote_name);
183 channels[channel].remote_name = NULL;
184 }
185}
186
187/* This is called just before select() to add any bits relevant to
188 channels in the select bitmasks. */
189
190void channel_prepare_select(fd_set *readset, fd_set *writeset)
191{
192 int i;
193 Channel *ch;
194 unsigned char *ucp;
195 unsigned int proto_len, data_len;
196
197 for (i = 0; i < channels_alloc; i++)
198 {
199 ch = &channels[i];
200 redo:
201 switch (ch->type)
202 {
203 case SSH_CHANNEL_X11_LISTENER:
204 case SSH_CHANNEL_PORT_LISTENER:
205 case SSH_CHANNEL_AUTH_SOCKET:
206 FD_SET(ch->sock, readset);
207 break;
208
209 case SSH_CHANNEL_OPEN:
210 if(compat13){
211 if (buffer_len(&ch->input) < 32768)
212 FD_SET(ch->sock, readset);
213 if (buffer_len(&ch->output) > 0)
214 FD_SET(ch->sock, writeset);
215 break;
216 }
217 /* test whether sockets are 'alive' for read/write */
218 if (ch->istate == CHAN_INPUT_OPEN)
219 if (buffer_len(&ch->input) < 32768)
220 FD_SET(ch->sock, readset);
221 if (ch->ostate == CHAN_OUTPUT_OPEN || ch->ostate == CHAN_OUTPUT_WAIT_DRAIN){
222 if (buffer_len(&ch->output) > 0){
223 FD_SET(ch->sock, writeset);
224 }else if(ch->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
225 chan_obuf_empty(ch);
226 }
227 }
228 break;
229
230 case SSH_CHANNEL_INPUT_DRAINING:
231 if (!compat13)
232 fatal("cannot happen: IN_DRAIN");
233 if (buffer_len(&ch->input) == 0)
234 {
235 packet_start(SSH_MSG_CHANNEL_CLOSE);
236 packet_put_int(ch->remote_id);
237 packet_send();
238 ch->type = SSH_CHANNEL_CLOSED;
239 debug("Closing channel %d after input drain.", i);
240 break;
241 }
242 break;
243
244 case SSH_CHANNEL_OUTPUT_DRAINING:
245 if (!compat13)
246 fatal("cannot happen: OUT_DRAIN");
247 if (buffer_len(&ch->output) == 0)
248 {
249 /* debug("Freeing channel %d after output drain.", i); */
250 channel_free(i);
251 break;
252 }
253 FD_SET(ch->sock, writeset);
254 break;
255
256 case SSH_CHANNEL_X11_OPEN:
257 /* This is a special state for X11 authentication spoofing. An
258 opened X11 connection (when authentication spoofing is being
259 done) remains in this state until the first packet has been
260 completely read. The authentication data in that packet is
261 then substituted by the real data if it matches the fake data,
262 and the channel is put into normal mode. */
263
264 /* Check if the fixed size part of the packet is in buffer. */
265 if (buffer_len(&ch->output) < 12)
266 break;
267
268 /* Parse the lengths of variable-length fields. */
269 ucp = (unsigned char *)buffer_ptr(&ch->output);
270 if (ucp[0] == 0x42)
271 { /* Byte order MSB first. */
272 proto_len = 256 * ucp[6] + ucp[7];
273 data_len = 256 * ucp[8] + ucp[9];
274 }
275 else
276 if (ucp[0] == 0x6c)
277 { /* Byte order LSB first. */
278 proto_len = ucp[6] + 256 * ucp[7];
279 data_len = ucp[8] + 256 * ucp[9];
280 }
281 else
282 {
283 debug("Initial X11 packet contains bad byte order byte: 0x%x",
284 ucp[0]);
285 ch->type = SSH_CHANNEL_OPEN;
286 goto reject;
287 }
288
289 /* Check if the whole packet is in buffer. */
290 if (buffer_len(&ch->output) <
291 12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3))
292 break;
293
294 /* Check if authentication protocol matches. */
295 if (proto_len != strlen(x11_saved_proto) ||
296 memcmp(ucp + 12, x11_saved_proto, proto_len) != 0)
297 {
298 debug("X11 connection uses different authentication protocol.");
299 ch->type = SSH_CHANNEL_OPEN;
300 goto reject;
301 }
302
303 /* Check if authentication data matches our fake data. */
304 if (data_len != x11_fake_data_len ||
305 memcmp(ucp + 12 + ((proto_len + 3) & ~3),
306 x11_fake_data, x11_fake_data_len) != 0)
307 {
308 debug("X11 auth data does not match fake data.");
309 ch->type = SSH_CHANNEL_OPEN;
310 goto reject;
311 }
312
313 /* Received authentication protocol and data match our fake data.
314 Substitute the fake data with real data. */
315 assert(x11_fake_data_len == x11_saved_data_len);
316 memcpy(ucp + 12 + ((proto_len + 3) & ~3),
317 x11_saved_data, x11_saved_data_len);
318
319 /* Start normal processing for the channel. */
320 ch->type = SSH_CHANNEL_OPEN;
321 /* Enable X11 Problem FIX */
322 ch->x11 = 1;
323 goto redo;
324
325 reject:
326 /* We have received an X11 connection that has bad authentication
327 information. */
328 log("X11 connection rejected because of wrong authentication.\r\n");
329 buffer_clear(&ch->input);
330 buffer_clear(&ch->output);
331 if (compat13) {
332 close(ch->sock);
333 ch->sock = -1;
334 ch->type = SSH_CHANNEL_CLOSED;
335 packet_start(SSH_MSG_CHANNEL_CLOSE);
336 packet_put_int(ch->remote_id);
337 packet_send();
338 }else{
339 debug("X11 rejected %d 0x%x 0x%x", ch->self, ch->istate, ch->ostate);
340 chan_read_failed(ch);
341 chan_write_failed(ch);
342 debug("X11 rejected %d 0x%x 0x%x", ch->self, ch->istate, ch->ostate);
343 }
344 break;
345
346 case SSH_CHANNEL_FREE:
347 default:
348 continue;
349 }
350 }
351}
352
353/* After select, perform any appropriate operations for channels which
354 have events pending. */
355
356void channel_after_select(fd_set *readset, fd_set *writeset)
357{
358 struct sockaddr addr;
359 int addrlen, newsock, i, newch, len;
360 Channel *ch;
361 char buf[16384], *remote_hostname;
362
363 /* Loop over all channels... */
364 for (i = 0; i < channels_alloc; i++)
365 {
366 ch = &channels[i];
367 switch (ch->type)
368 {
369 case SSH_CHANNEL_X11_LISTENER:
370 /* This is our fake X11 server socket. */
371 if (FD_ISSET(ch->sock, readset))
372 {
373 debug("X11 connection requested.");
374 addrlen = sizeof(addr);
375 newsock = accept(ch->sock, &addr, &addrlen);
376 if (newsock < 0)
377 {
378 error("accept: %.100s", strerror(errno));
379 break;
380 }
381 remote_hostname = get_remote_hostname(newsock);
382 snprintf(buf, sizeof buf, "X11 connection from %.200s port %d",
383 remote_hostname, get_peer_port(newsock));
384 xfree(remote_hostname);
385 newch = channel_allocate(SSH_CHANNEL_OPENING, newsock,
386 xstrdup(buf));
387 packet_start(SSH_SMSG_X11_OPEN);
388 packet_put_int(newch);
389 if (have_hostname_in_open)
390 packet_put_string(buf, strlen(buf));
391 packet_send();
392 }
393 break;
394
395 case SSH_CHANNEL_PORT_LISTENER:
396 /* This socket is listening for connections to a forwarded TCP/IP
397 port. */
398 if (FD_ISSET(ch->sock, readset))
399 {
400 debug("Connection to port %d forwarding to %.100s:%d requested.",
401 ch->listening_port, ch->path, ch->host_port);
402 addrlen = sizeof(addr);
403 newsock = accept(ch->sock, &addr, &addrlen);
404 if (newsock < 0)
405 {
406 error("accept: %.100s", strerror(errno));
407 break;
408 }
409 remote_hostname = get_remote_hostname(newsock);
410 snprintf(buf, sizeof buf, "port %d, connection from %.200s port %d",
411 ch->listening_port, remote_hostname,
412 get_peer_port(newsock));
413 xfree(remote_hostname);
414 newch = channel_allocate(SSH_CHANNEL_OPENING, newsock,
415 xstrdup(buf));
416 packet_start(SSH_MSG_PORT_OPEN);
417 packet_put_int(newch);
418 packet_put_string(ch->path, strlen(ch->path));
419 packet_put_int(ch->host_port);
420 if (have_hostname_in_open)
421 packet_put_string(buf, strlen(buf));
422 packet_send();
423 }
424 break;
425
426 case SSH_CHANNEL_AUTH_SOCKET:
427 /* This is the authentication agent socket listening for connections
428 from clients. */
429 if (FD_ISSET(ch->sock, readset))
430 {
431 int nchan;
432 len = sizeof(addr);
433 newsock = accept(ch->sock, &addr, &len);
434 if (newsock < 0)
435 {
436 error("accept from auth socket: %.100s", strerror(errno));
437 break;
438 }
439
440 nchan = channel_allocate(SSH_CHANNEL_OPENING, newsock,
441 xstrdup("accepted auth socket"));
442 packet_start(SSH_SMSG_AGENT_OPEN);
443 packet_put_int(nchan);
444 packet_send();
445 }
446 break;
447
448 case SSH_CHANNEL_OPEN:
449 /* This is an open two-way communication channel. It is not of
450 interest to us at this point what kind of data is being
451 transmitted. */
452
453 /* Read available incoming data and append it to buffer;
454 shutdown socket, if read or write failes */
455 if (FD_ISSET(ch->sock, readset))
456 {
457 len = read(ch->sock, buf, sizeof(buf));
458 if (len <= 0)
459 {
460 if (compat13) {
461 buffer_consume(&ch->output, buffer_len(&ch->output));
462 ch->type = SSH_CHANNEL_INPUT_DRAINING;
463 debug("Channel %d status set to input draining.", i);
464 }else{
465 chan_read_failed(ch);
466 }
467 break;
468 }
469 buffer_append(&ch->input, buf, len);
470 }
471 /* Send buffered output data to the socket. */
472 if (FD_ISSET(ch->sock, writeset) && buffer_len(&ch->output) > 0)
473 {
474 len = write(ch->sock, buffer_ptr(&ch->output),
475 buffer_len(&ch->output));
476 if (len <= 0)
477 {
478 if (compat13) {
479 buffer_consume(&ch->output, buffer_len(&ch->output));
480 debug("Channel %d status set to input draining.", i);
481 ch->type = SSH_CHANNEL_INPUT_DRAINING;
482 }else{
483 chan_write_failed(ch);
484 }
485 break;
486 }
487 buffer_consume(&ch->output, len);
488 }
489 break;
490
491 case SSH_CHANNEL_OUTPUT_DRAINING:
492 if (!compat13)
493 fatal("cannot happen: OUT_DRAIN");
494 /* Send buffered output data to the socket. */
495 if (FD_ISSET(ch->sock, writeset) && buffer_len(&ch->output) > 0)
496 {
497 len = write(ch->sock, buffer_ptr(&ch->output),
498 buffer_len(&ch->output));
499 if (len <= 0)
500 buffer_consume(&ch->output, buffer_len(&ch->output));
501 else
502 buffer_consume(&ch->output, len);
503 }
504 break;
505
506 case SSH_CHANNEL_X11_OPEN:
507 case SSH_CHANNEL_FREE:
508 default:
509 continue;
510 }
511 }
512}
513
514/* If there is data to send to the connection, send some of it now. */
515
516void channel_output_poll()
517{
518 int len, i;
519 Channel *ch;
520
521 for (i = 0; i < channels_alloc; i++)
522 {
523 ch = &channels[i];
524 /* We are only interested in channels that can have buffered incoming
525 data. */
526 if (ch->type != SSH_CHANNEL_OPEN &&
527 ch->type != SSH_CHANNEL_INPUT_DRAINING)
528 continue;
529
530 /* Get the amount of buffered data for this channel. */
531 len = buffer_len(&ch->input);
532 if (len > 0)
533 {
534 /* Send some data for the other side over the secure connection. */
535 if (packet_is_interactive())
536 {
537 if (len > 1024)
538 len = 512;
539 }
540 else
541 {
542 if (len > 16384)
543 len = 16384; /* Keep the packets at reasonable size. */
544 }
545 packet_start(SSH_MSG_CHANNEL_DATA);
546 packet_put_int(ch->remote_id);
547 packet_put_string(buffer_ptr(&ch->input), len);
548 packet_send();
549 buffer_consume(&ch->input, len);
550 }
551 else if(ch->istate == CHAN_INPUT_WAIT_DRAIN)
552 {
553 if (compat13)
554 fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3");
555 /* input-buffer is empty and read-socket shutdown:
556 tell peer, that we will not send more data: send IEOF */
557 chan_ibuf_empty(ch);
558 }
559 }
560}
561
562/* This is called when a packet of type CHANNEL_DATA has just been received.
563 The message type has already been consumed, but channel number and data
564 is still there. */
565
566void channel_input_data(int payload_len)
567{
568 int channel;
569 char *data;
570 unsigned int data_len;
571
572 /* Get the channel number and verify it. */
573 channel = packet_get_int();
574 if (channel < 0 || channel >= channels_alloc ||
575 channels[channel].type == SSH_CHANNEL_FREE)
576 packet_disconnect("Received data for nonexistent channel %d.", channel);
577
578 /* Ignore any data for non-open channels (might happen on close) */
579 if (channels[channel].type != SSH_CHANNEL_OPEN &&
580 channels[channel].type != SSH_CHANNEL_X11_OPEN)
581 return;
582
583 /* Get the data. */
584 data = packet_get_string(&data_len);
585 packet_integrity_check(payload_len, 4 + 4+data_len, SSH_MSG_CHANNEL_DATA);
586 buffer_append(&channels[channel].output, data, data_len);
587 xfree(data);
588}
589
590/* Returns true if no channel has too much buffered data, and false if
591 one or more channel is overfull. */
592
593int channel_not_very_much_buffered_data()
594{
595 unsigned int i;
596 Channel *ch;
597
598 for (i = 0; i < channels_alloc; i++)
599 {
600 ch = &channels[i];
601 switch (ch->type)
602 {
603 case SSH_CHANNEL_X11_LISTENER:
604 case SSH_CHANNEL_PORT_LISTENER:
605 case SSH_CHANNEL_AUTH_SOCKET:
606 continue;
607 case SSH_CHANNEL_OPEN:
608 if (buffer_len(&ch->input) > 32768)
609 return 0;
610 if (buffer_len(&ch->output) > 32768)
611 return 0;
612 continue;
613 case SSH_CHANNEL_INPUT_DRAINING:
614 case SSH_CHANNEL_OUTPUT_DRAINING:
615 case SSH_CHANNEL_X11_OPEN:
616 case SSH_CHANNEL_FREE:
617 default:
618 continue;
619 }
620 }
621 return 1;
622}
623
624/* This is called after receiving CHANNEL_CLOSE/IEOF. */
625
626void channel_input_close()
627{
628 int channel;
629
630 /* Get the channel number and verify it. */
631 channel = packet_get_int();
632 if (channel < 0 || channel >= channels_alloc ||
633 channels[channel].type == SSH_CHANNEL_FREE)
634 packet_disconnect("Received data for nonexistent channel %d.", channel);
635
636 if(!compat13){
637 /* proto version 1.5 overloads CLOSE with IEOF */
638 chan_rcvd_ieof(&channels[channel]);
639 return;
640 }
641
642 /* Send a confirmation that we have closed the channel and no more data is
643 coming for it. */
644 packet_start(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION);
645 packet_put_int(channels[channel].remote_id);
646 packet_send();
647
648 /* If the channel is in closed state, we have sent a close request, and
649 the other side will eventually respond with a confirmation. Thus,
650 we cannot free the channel here, because then there would be no-one to
651 receive the confirmation. The channel gets freed when the confirmation
652 arrives. */
653 if (channels[channel].type != SSH_CHANNEL_CLOSED)
654 {
655 /* Not a closed channel - mark it as draining, which will cause it to
656 be freed later. */
657 buffer_consume(&channels[channel].input,
658 buffer_len(&channels[channel].input));
659 channels[channel].type = SSH_CHANNEL_OUTPUT_DRAINING;
660 /* debug("Setting status to output draining; output len = %d",
661 buffer_len(&channels[channel].output)); */
662 }
663}
664
665/* This is called after receiving CHANNEL_CLOSE_CONFIRMATION/OCLOSE. */
666
667void channel_input_close_confirmation()
668{
669 int channel;
670
671 /* Get the channel number and verify it. */
672 channel = packet_get_int();
673 if (channel < 0 || channel >= channels_alloc)
674 packet_disconnect("Received close confirmation for out-of-range channel %d.",
675 channel);
676
677 if(!compat13){
678 /* proto version 1.5 overloads CLOSE_CONFIRMATION with OCLOSE */
679 chan_rcvd_oclose(&channels[channel]);
680 return;
681 }
682
683 if (channels[channel].type != SSH_CHANNEL_CLOSED)
684 packet_disconnect("Received close confirmation for non-closed channel %d (type %d).",
685 channel, channels[channel].type);
686
687 /* Free the channel. */
688 channel_free(channel);
689}
690
691/* This is called after receiving CHANNEL_OPEN_CONFIRMATION. */
692
693void channel_input_open_confirmation()
694{
695 int channel, remote_channel;
696
697 /* Get the channel number and verify it. */
698 channel = packet_get_int();
699 if (channel < 0 || channel >= channels_alloc ||
700 channels[channel].type != SSH_CHANNEL_OPENING)
701 packet_disconnect("Received open confirmation for non-opening channel %d.",
702 channel);
703
704 /* Get remote side's id for this channel. */
705 remote_channel = packet_get_int();
706
707 /* Record the remote channel number and mark that the channel is now open. */
708 channels[channel].remote_id = remote_channel;
709 channels[channel].type = SSH_CHANNEL_OPEN;
710}
711
712/* This is called after receiving CHANNEL_OPEN_FAILURE from the other side. */
713
714void channel_input_open_failure()
715{
716 int channel;
717
718 /* Get the channel number and verify it. */
719 channel = packet_get_int();
720 if (channel < 0 || channel >= channels_alloc ||
721 channels[channel].type != SSH_CHANNEL_OPENING)
722 packet_disconnect("Received open failure for non-opening channel %d.",
723 channel);
724
725 /* Free the channel. This will also close the socket. */
726 channel_free(channel);
727}
728
729/* Stops listening for channels, and removes any unix domain sockets that
730 we might have. */
731
732void channel_stop_listening()
733{
734 int i;
735 for (i = 0; i < channels_alloc; i++)
736 {
737 switch (channels[i].type)
738 {
739 case SSH_CHANNEL_AUTH_SOCKET:
740 close(channels[i].sock);
741 remove(channels[i].path);
742 channel_free(i);
743 break;
744 case SSH_CHANNEL_PORT_LISTENER:
745 case SSH_CHANNEL_X11_LISTENER:
746 close(channels[i].sock);
747 channel_free(i);
748 break;
749 default:
750 break;
751 }
752 }
753}
754
755/* Closes the sockets of all channels. This is used to close extra file
756 descriptors after a fork. */
757
758void channel_close_all()
759{
760 int i;
761 for (i = 0; i < channels_alloc; i++)
762 {
763 if (channels[i].type != SSH_CHANNEL_FREE)
764 close(channels[i].sock);
765 }
766}
767
768/* Returns the maximum file descriptor number used by the channels. */
769
770int channel_max_fd()
771{
772 return channel_max_fd_value;
773}
774
775/* Returns true if any channel is still open. */
776
777int channel_still_open()
778{
779 unsigned int i;
780 for (i = 0; i < channels_alloc; i++)
781 switch (channels[i].type)
782 {
783 case SSH_CHANNEL_FREE:
784 case SSH_CHANNEL_X11_LISTENER:
785 case SSH_CHANNEL_PORT_LISTENER:
786 case SSH_CHANNEL_CLOSED:
787 case SSH_CHANNEL_AUTH_SOCKET:
788 continue;
789 case SSH_CHANNEL_OPENING:
790 case SSH_CHANNEL_OPEN:
791 case SSH_CHANNEL_X11_OPEN:
792 return 1;
793 case SSH_CHANNEL_INPUT_DRAINING:
794 case SSH_CHANNEL_OUTPUT_DRAINING:
795 if (!compat13)
796 fatal("cannot happen: OUT_DRAIN");
797 return 1;
798 default:
799 fatal("channel_still_open: bad channel type %d", channels[i].type);
800 /*NOTREACHED*/
801 }
802 return 0;
803}
804
805/* Returns a message describing the currently open forwarded
806 connections, suitable for sending to the client. The message
807 contains crlf pairs for newlines. */
808
809char *channel_open_message()
810{
811 Buffer buffer;
812 int i;
813 char buf[512], *cp;
814
815 buffer_init(&buffer);
816 snprintf(buf, sizeof buf, "The following connections are open:\r\n");
817 buffer_append(&buffer, buf, strlen(buf));
818 for (i = 0; i < channels_alloc; i++){
819 Channel *c=&channels[i];
820 switch (c->type)
821 {
822 case SSH_CHANNEL_FREE:
823 case SSH_CHANNEL_X11_LISTENER:
824 case SSH_CHANNEL_PORT_LISTENER:
825 case SSH_CHANNEL_CLOSED:
826 case SSH_CHANNEL_AUTH_SOCKET:
827 continue;
828 case SSH_CHANNEL_OPENING:
829 case SSH_CHANNEL_OPEN:
830 case SSH_CHANNEL_X11_OPEN:
831 case SSH_CHANNEL_INPUT_DRAINING:
832 case SSH_CHANNEL_OUTPUT_DRAINING:
833 snprintf(buf, sizeof buf, " #%d/%d %.300s\r\n",
834 c->self,c->type,c->remote_name);
835 buffer_append(&buffer, buf, strlen(buf));
836 continue;
837 default:
838 fatal("channel_still_open: bad channel type %d", c->type);
839 /*NOTREACHED*/
840 }
841 }
842 buffer_append(&buffer, "\0", 1);
843 cp = xstrdup(buffer_ptr(&buffer));
844 buffer_free(&buffer);
845 return cp;
846}
847
848/* Initiate forwarding of connections to local port "port" through the secure
849 channel to host:port from remote side. */
850
851void channel_request_local_forwarding(int port, const char *host,
852 int host_port)
853{
854 int ch, sock;
855 struct sockaddr_in sin;
856 extern Options options;
857
858 if (strlen(host) > sizeof(channels[0].path) - 1)
859 packet_disconnect("Forward host name too long.");
860
861 /* Create a port to listen for the host. */
862 sock = socket(AF_INET, SOCK_STREAM, 0);
863 if (sock < 0)
864 packet_disconnect("socket: %.100s", strerror(errno));
865
866 /* Initialize socket address. */
867 memset(&sin, 0, sizeof(sin));
868 sin.sin_family = AF_INET;
869 if (options.gateway_ports == 1)
870 sin.sin_addr.s_addr = htonl(INADDR_ANY);
871 else
872 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
873 sin.sin_port = htons(port);
874
875 /* Bind the socket to the address. */
876 if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
877 packet_disconnect("bind: %.100s", strerror(errno));
878
879 /* Start listening for connections on the socket. */
880 if (listen(sock, 5) < 0)
881 packet_disconnect("listen: %.100s", strerror(errno));
882
883 /* Allocate a channel number for the socket. */
884 ch = channel_allocate(SSH_CHANNEL_PORT_LISTENER, sock,
885 xstrdup("port listener"));
886 strcpy(channels[ch].path, host); /* note: host name stored here */
887 channels[ch].host_port = host_port; /* port on host to connect to */
888 channels[ch].listening_port = port; /* port being listened */
889}
890
891/* Initiate forwarding of connections to port "port" on remote host through
892 the secure channel to host:port from local side. */
893
894void channel_request_remote_forwarding(int port, const char *host,
895 int remote_port)
896{
897 int payload_len;
898 /* Record locally that connection to this host/port is permitted. */
899 if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION)
900 fatal("channel_request_remote_forwarding: too many forwards");
901 permitted_opens[num_permitted_opens].host = xstrdup(host);
902 permitted_opens[num_permitted_opens].port = remote_port;
903 num_permitted_opens++;
904
905 /* Send the forward request to the remote side. */
906 packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);
907 packet_put_int(port);
908 packet_put_string(host, strlen(host));
909 packet_put_int(remote_port);
910 packet_send();
911 packet_write_wait();
912
913 /* Wait for response from the remote side. It will send a disconnect
914 message on failure, and we will never see it here. */
915 packet_read_expect(&payload_len, SSH_SMSG_SUCCESS);
916}
917
918/* This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates
919 listening for the port, and sends back a success reply (or disconnect
920 message if there was an error). This never returns if there was an
921 error. */
922
923void channel_input_port_forward_request(int is_root)
924{
925 int port, host_port;
926 char *hostname;
927
928 /* Get arguments from the packet. */
929 port = packet_get_int();
930 hostname = packet_get_string(NULL);
931 host_port = packet_get_int();
932
933 /* Port numbers are 16 bit quantities. */
934 if ((port & 0xffff) != port)
935 packet_disconnect("Requested forwarding of nonexistent port %d.", port);
936
937 /* Check that an unprivileged user is not trying to forward a privileged
938 port. */
939 if (port < IPPORT_RESERVED && !is_root)
940 packet_disconnect("Requested forwarding of port %d but user is not root.",
941 port);
942
943 /* Initiate forwarding. */
944 channel_request_local_forwarding(port, hostname, host_port);
945
946 /* Free the argument string. */
947 xfree(hostname);
948}
949
950/* This is called after receiving PORT_OPEN message. This attempts to connect
951 to the given host:port, and sends back CHANNEL_OPEN_CONFIRMATION or
952 CHANNEL_OPEN_FAILURE. */
953
954void channel_input_port_open(int payload_len)
955{
956 int remote_channel, sock, newch, host_port, i;
957 struct sockaddr_in sin;
958 char *host, *originator_string;
959 struct hostent *hp;
960 int host_len, originator_len;
961
962 /* Get remote channel number. */
963 remote_channel = packet_get_int();
964
965 /* Get host name to connect to. */
966 host = packet_get_string(&host_len);
967
968 /* Get port to connect to. */
969 host_port = packet_get_int();
970
971 /* Get remote originator name. */
972 if (have_hostname_in_open)
973 originator_string = packet_get_string(&originator_len);
974 else
975 originator_string = xstrdup("unknown (remote did not supply name)");
976
977 packet_integrity_check(payload_len,
978 4 + 4 + host_len + 4 + 4 + originator_len,
979 SSH_MSG_PORT_OPEN);
980
981 /* Check if opening that port is permitted. */
982 if (!all_opens_permitted)
983 {
984 /* Go trough all permitted ports. */
985 for (i = 0; i < num_permitted_opens; i++)
986 if (permitted_opens[i].port == host_port &&
987 strcmp(permitted_opens[i].host, host) == 0)
988 break;
989
990 /* Check if we found the requested port among those permitted. */
991 if (i >= num_permitted_opens)
992 {
993 /* The port is not permitted. */
994 log("Received request to connect to %.100s:%d, but the request was denied.",
995 host, host_port);
996 packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
997 packet_put_int(remote_channel);
998 packet_send();
999 }
1000 }
1001
1002 memset(&sin, 0, sizeof(sin));
1003 sin.sin_addr.s_addr = inet_addr(host);
1004 if ((sin.sin_addr.s_addr & 0xffffffff) != 0xffffffff)
1005 {
1006 /* It was a valid numeric host address. */
1007 sin.sin_family = AF_INET;
1008 }
1009 else
1010 {
1011 /* Look up the host address from the name servers. */
1012 hp = gethostbyname(host);
1013 if (!hp)
1014 {
1015 error("%.100s: unknown host.", host);
1016 goto fail;
1017 }
1018 if (!hp->h_addr_list[0])
1019 {
1020 error("%.100s: host has no IP address.", host);
1021 goto fail;
1022 }
1023 sin.sin_family = hp->h_addrtype;
1024 memcpy(&sin.sin_addr, hp->h_addr_list[0],
1025 sizeof(sin.sin_addr));
1026 }
1027 sin.sin_port = htons(host_port);
1028
1029 /* Create the socket. */
1030 sock = socket(sin.sin_family, SOCK_STREAM, 0);
1031 if (sock < 0)
1032 {
1033 error("socket: %.100s", strerror(errno));
1034 goto fail;
1035 }
1036
1037 /* Connect to the host/port. */
1038 if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
1039 {
1040 error("connect %.100s:%d: %.100s", host, host_port,
1041 strerror(errno));
1042 close(sock);
1043 goto fail;
1044 }
1045
1046 /* Successful connection. */
1047
1048 /* Allocate a channel for this connection. */
1049 newch = channel_allocate(SSH_CHANNEL_OPEN, sock, originator_string);
1050 channels[newch].remote_id = remote_channel;
1051
1052 /* Send a confirmation to the remote host. */
1053 packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
1054 packet_put_int(remote_channel);
1055 packet_put_int(newch);
1056 packet_send();
1057
1058 /* Free the argument string. */
1059 xfree(host);
1060
1061 return;
1062
1063 fail:
1064 /* Free the argument string. */
1065 xfree(host);
1066
1067 /* Send refusal to the remote host. */
1068 packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
1069 packet_put_int(remote_channel);
1070 packet_send();
1071}
1072
1073/* Creates an internet domain socket for listening for X11 connections.
1074 Returns a suitable value for the DISPLAY variable, or NULL if an error
1075 occurs. */
1076
1077char *x11_create_display_inet(int screen_number)
1078{
1079 extern ServerOptions options;
1080 int display_number, port, sock;
1081 struct sockaddr_in sin;
1082 char buf[512];
1083 char hostname[MAXHOSTNAMELEN];
1084
1085 for (display_number = options.x11_display_offset; display_number < MAX_DISPLAYS; display_number++)
1086 {
1087 port = 6000 + display_number;
1088 memset(&sin, 0, sizeof(sin));
1089 sin.sin_family = AF_INET;
1090 sin.sin_addr.s_addr = htonl(INADDR_ANY);
1091 sin.sin_port = htons(port);
1092
1093 sock = socket(AF_INET, SOCK_STREAM, 0);
1094 if (sock < 0)
1095 {
1096 error("socket: %.100s", strerror(errno));
1097 return NULL;
1098 }
1099
1100 if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
1101 {
1102 debug("bind port %d: %.100s", port, strerror(errno));
1103 shutdown(sock, SHUT_RDWR);
1104 close(sock);
1105 continue;
1106 }
1107 break;
1108 }
1109 if (display_number >= MAX_DISPLAYS)
1110 {
1111 error("Failed to allocate internet-domain X11 display socket.");
1112 return NULL;
1113 }
1114
1115 /* Start listening for connections on the socket. */
1116 if (listen(sock, 5) < 0)
1117 {
1118 error("listen: %.100s", strerror(errno));
1119 shutdown(sock, SHUT_RDWR);
1120 close(sock);
1121 return NULL;
1122 }
1123
1124 /* Set up a suitable value for the DISPLAY variable. */
1125 if (gethostname(hostname, sizeof(hostname)) < 0)
1126 fatal("gethostname: %.100s", strerror(errno));
1127 snprintf(buf, sizeof buf, "%.400s:%d.%d", hostname,
1128 display_number, screen_number);
1129
1130 /* Allocate a channel for the socket. */
1131 (void)channel_allocate(SSH_CHANNEL_X11_LISTENER, sock,
1132 xstrdup("X11 inet listener"));
1133
1134 /* Return a suitable value for the DISPLAY environment variable. */
1135 return xstrdup(buf);
1136}
1137
1138#ifndef X_UNIX_PATH
1139#define X_UNIX_PATH "/tmp/.X11-unix/X"
1140#endif
1141
1142static
1143int
1144connect_local_xsocket(unsigned dnr)
1145{
1146 static const char *const x_sockets[] = {
1147 X_UNIX_PATH "%u",
1148 "/var/X/.X11-unix/X" "%u",
1149 "/usr/spool/sockets/X11/" "%u",
1150 NULL
1151 };
1152 int sock;
1153 struct sockaddr_un addr;
1154 const char *const *path;
1155
1156 for (path = x_sockets; *path; ++path)
1157 {
1158 sock = socket(AF_UNIX, SOCK_STREAM, 0);
1159 if (sock < 0)
1160 error("socket: %.100s", strerror(errno));
1161 memset(&addr, 0, sizeof(addr));
1162 addr.sun_family = AF_UNIX;
1163 snprintf(addr.sun_path, sizeof addr.sun_path, *path, dnr);
1164 if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0)
1165 return sock;
1166 close(sock);
1167 }
1168 error("connect %.100s: %.100s", addr.sun_path, strerror(errno));
1169 return -1;
1170}
1171
1172
1173/* This is called when SSH_SMSG_X11_OPEN is received. The packet contains
1174 the remote channel number. We should do whatever we want, and respond
1175 with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE. */
1176
1177void x11_input_open(int payload_len)
1178{
1179 int remote_channel, display_number, sock, newch;
1180 const char *display;
1181 struct sockaddr_in sin;
1182 char buf[1024], *cp, *remote_host;
1183 struct hostent *hp;
1184 int remote_len;
1185
1186 /* Get remote channel number. */
1187 remote_channel = packet_get_int();
1188
1189 /* Get remote originator name. */
1190 if (have_hostname_in_open)
1191 remote_host = packet_get_string(&remote_len);
1192 else
1193 remote_host = xstrdup("unknown (remote did not supply name)");
1194
1195 debug("Received X11 open request.");
1196 packet_integrity_check(payload_len, 4 + 4+remote_len, SSH_SMSG_X11_OPEN);
1197
1198 /* Try to open a socket for the local X server. */
1199 display = getenv("DISPLAY");
1200 if (!display)
1201 {
1202 error("DISPLAY not set.");
1203 goto fail;
1204 }
1205
1206 /* Now we decode the value of the DISPLAY variable and make a connection
1207 to the real X server. */
1208
1209 /* Check if it is a unix domain socket. Unix domain displays are in one
1210 of the following formats: unix:d[.s], :d[.s], ::d[.s] */
1211 if (strncmp(display, "unix:", 5) == 0 ||
1212 display[0] == ':')
1213 {
1214 /* Connect to the unix domain socket. */
1215 if (sscanf(strrchr(display, ':') + 1, "%d", &display_number) != 1)
1216 {
1217 error("Could not parse display number from DISPLAY: %.100s",
1218 display);
1219 goto fail;
1220 }
1221 /* Create a socket. */
1222 sock = connect_local_xsocket(display_number);
1223 if (sock < 0)
1224 goto fail;
1225
1226 /* OK, we now have a connection to the display. */
1227 goto success;
1228 }
1229
1230 /* Connect to an inet socket. The DISPLAY value is supposedly
1231 hostname:d[.s], where hostname may also be numeric IP address. */
1232 strncpy(buf, display, sizeof(buf));
1233 buf[sizeof(buf) - 1] = 0;
1234 cp = strchr(buf, ':');
1235 if (!cp)
1236 {
1237 error("Could not find ':' in DISPLAY: %.100s", display);
1238 goto fail;
1239 }
1240 *cp = 0;
1241 /* buf now contains the host name. But first we parse the display number. */
1242 if (sscanf(cp + 1, "%d", &display_number) != 1)
1243 {
1244 error("Could not parse display number from DISPLAY: %.100s",
1245 display);
1246 goto fail;
1247 }
1248
1249 /* Try to parse the host name as a numeric IP address. */
1250 memset(&sin, 0, sizeof(sin));
1251 sin.sin_addr.s_addr = inet_addr(buf);
1252 if ((sin.sin_addr.s_addr & 0xffffffff) != 0xffffffff)
1253 {
1254 /* It was a valid numeric host address. */
1255 sin.sin_family = AF_INET;
1256 }
1257 else
1258 {
1259 /* Not a numeric IP address. */
1260 /* Look up the host address from the name servers. */
1261 hp = gethostbyname(buf);
1262 if (!hp)
1263 {
1264 error("%.100s: unknown host.", buf);
1265 goto fail;
1266 }
1267 if (!hp->h_addr_list[0])
1268 {
1269 error("%.100s: host has no IP address.", buf);
1270 goto fail;
1271 }
1272 sin.sin_family = hp->h_addrtype;
1273 memcpy(&sin.sin_addr, hp->h_addr_list[0],
1274 sizeof(sin.sin_addr));
1275 }
1276 /* Set port number. */
1277 sin.sin_port = htons(6000 + display_number);
1278
1279 /* Create a socket. */
1280 sock = socket(sin.sin_family, SOCK_STREAM, 0);
1281 if (sock < 0)
1282 {
1283 error("socket: %.100s", strerror(errno));
1284 goto fail;
1285 }
1286 /* Connect it to the display. */
1287 if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
1288 {
1289 error("connect %.100s:%d: %.100s", buf, 6000 + display_number,
1290 strerror(errno));
1291 close(sock);
1292 goto fail;
1293 }
1294
1295 success:
1296 /* We have successfully obtained a connection to the real X display. */
1297
1298 /* Allocate a channel for this connection. */
1299 if (x11_saved_proto == NULL)
1300 newch = channel_allocate(SSH_CHANNEL_OPEN, sock, remote_host);
1301 else
1302 newch = channel_allocate(SSH_CHANNEL_X11_OPEN, sock, remote_host);
1303 channels[newch].remote_id = remote_channel;
1304
1305 /* Send a confirmation to the remote host. */
1306 packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
1307 packet_put_int(remote_channel);
1308 packet_put_int(newch);
1309 packet_send();
1310
1311 return;
1312
1313 fail:
1314 /* Send refusal to the remote host. */
1315 packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
1316 packet_put_int(remote_channel);
1317 packet_send();
1318}
1319
1320/* Requests forwarding of X11 connections, generates fake authentication
1321 data, and enables authentication spoofing. */
1322
1323void x11_request_forwarding_with_spoofing(const char *proto, const char *data)
1324{
1325 unsigned int data_len = (unsigned int)strlen(data) / 2;
1326 unsigned int i, value;
1327 char *new_data;
1328 int screen_number;
1329 const char *cp;
1330 u_int32_t rand = 0;
1331
1332 cp = getenv("DISPLAY");
1333 if (cp)
1334 cp = strchr(cp, ':');
1335 if (cp)
1336 cp = strchr(cp, '.');
1337 if (cp)
1338 screen_number = atoi(cp + 1);
1339 else
1340 screen_number = 0;
1341
1342 /* Save protocol name. */
1343 x11_saved_proto = xstrdup(proto);
1344
1345 /* Extract real authentication data and generate fake data of the same
1346 length. */
1347 x11_saved_data = xmalloc(data_len);
1348 x11_fake_data = xmalloc(data_len);
1349 for (i = 0; i < data_len; i++)
1350 {
1351 if (sscanf(data + 2 * i, "%2x", &value) != 1)
1352 fatal("x11_request_forwarding: bad authentication data: %.100s", data);
1353 if (i % 4 == 0)
1354 rand = arc4random();
1355 x11_saved_data[i] = value;
1356 x11_fake_data[i] = rand & 0xff;
1357 rand >>= 8;
1358 }
1359 x11_saved_data_len = data_len;
1360 x11_fake_data_len = data_len;
1361
1362 /* Convert the fake data into hex. */
1363 new_data = xmalloc(2 * data_len + 1);
1364 for (i = 0; i < data_len; i++)
1365 sprintf(new_data + 2 * i, "%02x", (unsigned char)x11_fake_data[i]);
1366
1367 /* Send the request packet. */
1368 packet_start(SSH_CMSG_X11_REQUEST_FORWARDING);
1369 packet_put_string(proto, strlen(proto));
1370 packet_put_string(new_data, strlen(new_data));
1371 packet_put_int(screen_number);
1372 packet_send();
1373 packet_write_wait();
1374 xfree(new_data);
1375}
1376
1377/* Sends a message to the server to request authentication fd forwarding. */
1378
1379void auth_request_forwarding()
1380{
1381 packet_start(SSH_CMSG_AGENT_REQUEST_FORWARDING);
1382 packet_send();
1383 packet_write_wait();
1384}
1385
1386/* Returns the name of the forwarded authentication socket. Returns NULL
1387 if there is no forwarded authentication socket. The returned value
1388 points to a static buffer. */
1389
1390char *auth_get_socket_name()
1391{
1392 return channel_forwarded_auth_socket_name;
1393}
1394
1395/* removes the agent forwarding socket */
1396
1397void cleanup_socket(void) {
1398 remove(channel_forwarded_auth_socket_name);
1399 rmdir(channel_forwarded_auth_socket_dir);
1400}
1401
1402/* This if called to process SSH_CMSG_AGENT_REQUEST_FORWARDING on the server.
1403 This starts forwarding authentication requests. */
1404
1405void auth_input_request_forwarding(struct passwd *pw)
1406{
1407 int sock, newch;
1408 struct sockaddr_un sunaddr;
1409
1410 if (auth_get_socket_name() != NULL)
1411 fatal("Protocol error: authentication forwarding requested twice.");
1412
1413 /* Temporarily drop privileged uid for mkdir/bind. */
1414 temporarily_use_uid(pw->pw_uid);
1415
1416 /* Allocate a buffer for the socket name, and format the name. */
1417 channel_forwarded_auth_socket_name = xmalloc(MAX_SOCKET_NAME);
1418 channel_forwarded_auth_socket_dir = xmalloc(MAX_SOCKET_NAME);
1419 strlcpy(channel_forwarded_auth_socket_dir, "/tmp/ssh-XXXXXXXX", MAX_SOCKET_NAME);
1420
1421 /* Create private directory for socket */
1422 if (mkdtemp(channel_forwarded_auth_socket_dir) == NULL)
1423 packet_disconnect("mkdtemp: %.100s", strerror(errno));
1424 snprintf(channel_forwarded_auth_socket_name, MAX_SOCKET_NAME,
1425 "%s/agent.%d", channel_forwarded_auth_socket_dir, (int)getpid());
1426
1427 if (atexit(cleanup_socket) < 0) {
1428 int saved=errno;
1429 cleanup_socket();
1430 packet_disconnect("socket: %.100s", strerror(saved));
1431 }
1432
1433 /* Create the socket. */
1434 sock = socket(AF_UNIX, SOCK_STREAM, 0);
1435 if (sock < 0)
1436 packet_disconnect("socket: %.100s", strerror(errno));
1437
1438 /* Bind it to the name. */
1439 memset(&sunaddr, 0, sizeof(sunaddr));
1440 sunaddr.sun_family = AF_UNIX;
1441 strncpy(sunaddr.sun_path, channel_forwarded_auth_socket_name,
1442 sizeof(sunaddr.sun_path));
1443
1444 if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0)
1445 packet_disconnect("bind: %.100s", strerror(errno));
1446
1447 /* Restore the privileged uid. */
1448 restore_uid();
1449
1450 /* Start listening on the socket. */
1451 if (listen(sock, 5) < 0)
1452 packet_disconnect("listen: %.100s", strerror(errno));
1453
1454 /* Allocate a channel for the authentication agent socket. */
1455 newch = channel_allocate(SSH_CHANNEL_AUTH_SOCKET, sock,
1456 xstrdup("auth socket"));
1457 strcpy(channels[newch].path, channel_forwarded_auth_socket_name);
1458}
1459
1460/* This is called to process an SSH_SMSG_AGENT_OPEN message. */
1461
1462void auth_input_open_request()
1463{
1464 int remch, sock, newch;
1465 char *dummyname;
1466
1467 /* Read the remote channel number from the message. */
1468 remch = packet_get_int();
1469
1470 /* Get a connection to the local authentication agent (this may again get
1471 forwarded). */
1472 sock = ssh_get_authentication_socket();
1473
1474 /* If we could not connect the agent, send an error message back to
1475 the server. This should never happen unless the agent
1476 dies, because authentication forwarding is only enabled if we have an
1477 agent. */
1478 if (sock < 0){
1479 packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
1480 packet_put_int(remch);
1481 packet_send();
1482 return;
1483 }
1484
1485 debug("Forwarding authentication connection.");
1486
1487 /* Dummy host name. This will be freed when the channel is freed; it will
1488 still be valid in the packet_put_string below since the channel cannot
1489 yet be freed at that point. */
1490 dummyname = xstrdup("authentication agent connection");
1491
1492 newch = channel_allocate(SSH_CHANNEL_OPEN, sock, dummyname);
1493 channels[newch].remote_id = remch;
1494
1495 /* Send a confirmation to the remote host. */
1496 packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
1497 packet_put_int(remch);
1498 packet_put_int(newch);
1499 packet_send();
1500}
diff --git a/channels.h b/channels.h
new file mode 100644
index 000000000..9794ef50d
--- /dev/null
+++ b/channels.h
@@ -0,0 +1,41 @@
1/* RCSID("$Id: channels.h,v 1.1 1999/10/27 03:42:44 damien Exp $"); */
2
3#ifndef CHANNELS_H
4#define CHANNELS_H
5
6/* Definitions for channel types. */
7#define SSH_CHANNEL_FREE 0 /* This channel is free (unused). */
8#define SSH_CHANNEL_X11_LISTENER 1 /* Listening for inet X11 conn. */
9#define SSH_CHANNEL_PORT_LISTENER 2 /* Listening on a port. */
10#define SSH_CHANNEL_OPENING 3 /* waiting for confirmation */
11#define SSH_CHANNEL_OPEN 4 /* normal open two-way channel */
12#define SSH_CHANNEL_CLOSED 5 /* waiting for close confirmation */
13/* SSH_CHANNEL_AUTH_FD 6 authentication fd */
14#define SSH_CHANNEL_AUTH_SOCKET 7 /* authentication socket */
15/* SSH_CHANNEL_AUTH_SOCKET_FD 8 connection to auth socket */
16#define SSH_CHANNEL_X11_OPEN 9 /* reading first X11 packet */
17#define SSH_CHANNEL_INPUT_DRAINING 10 /* sending remaining data to conn */
18#define SSH_CHANNEL_OUTPUT_DRAINING 11 /* sending remaining data to app */
19
20/* Data structure for channel data. This is iniailized in channel_allocate
21 and cleared in channel_free. */
22
23typedef struct Channel
24{
25 int type; /* channel type/state */
26 int self; /* my own channel identifier */
27 int remote_id; /* channel identifier for remote peer */
28 /* peer can be reached over encrypted connection, via packet-sent */
29 int istate;
30 int ostate;
31 int x11;
32 int sock; /* data socket, linked to this channel */
33 Buffer input; /* data read from socket, to be sent over encrypted connection */
34 Buffer output; /* data received over encrypted connection for send on socket */
35 char path[200]; /* path for unix domain sockets, or host name for forwards */
36 int listening_port; /* port being listened for forwards */
37 int host_port; /* remote port to connect for forwards */
38 char *remote_name; /* remote hostname */
39} Channel;
40
41#endif
diff --git a/cipher.c b/cipher.c
new file mode 100644
index 000000000..b47e7ecd8
--- /dev/null
+++ b/cipher.c
@@ -0,0 +1,304 @@
1/*
2
3cipher.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Wed Apr 19 17:41:39 1995 ylo
11
12*/
13
14#include "includes.h"
15RCSID("$Id: cipher.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
16
17#include "ssh.h"
18#include "cipher.h"
19
20#include <openssl/md5.h>
21
22/*
23 * What kind of tripple DES are these 2 routines?
24 *
25 * Why is there a redundant initialization vector?
26 *
27 * If only iv3 was used, then, this would till effect have been
28 * outer-cbc. However, there is also a private iv1 == iv2 which
29 * perhaps makes differential analysis easier. On the other hand, the
30 * private iv1 probably makes the CRC-32 attack ineffective. This is a
31 * result of that there is no longer any known iv1 to use when
32 * choosing the X block.
33 */
34void
35SSH_3CBC_ENCRYPT(des_key_schedule ks1,
36 des_key_schedule ks2, des_cblock *iv2,
37 des_key_schedule ks3, des_cblock *iv3,
38 void *dest, void *src,
39 unsigned int len)
40{
41 des_cblock iv1;
42
43 memcpy(&iv1, iv2, 8);
44
45 des_cbc_encrypt(src, dest, len, ks1, &iv1, DES_ENCRYPT);
46 memcpy(&iv1, dest + len - 8, 8);
47
48 des_cbc_encrypt(dest, dest, len, ks2, iv2, DES_DECRYPT);
49 memcpy(iv2, &iv1, 8); /* Note how iv1 == iv2 on entry and exit. */
50
51 des_cbc_encrypt(dest, dest, len, ks3, iv3, DES_ENCRYPT);
52 memcpy(iv3, dest + len - 8, 8);
53}
54
55void
56SSH_3CBC_DECRYPT(des_key_schedule ks1,
57 des_key_schedule ks2, des_cblock *iv2,
58 des_key_schedule ks3, des_cblock *iv3,
59 void *dest, void *src,
60 unsigned int len)
61{
62 des_cblock iv1;
63
64 memcpy(&iv1, iv2, 8);
65
66 des_cbc_encrypt(src, dest, len, ks3, iv3, DES_DECRYPT);
67 memcpy(iv3, src + len - 8, 8);
68
69 des_cbc_encrypt(dest, dest, len, ks2, iv2, DES_ENCRYPT);
70 memcpy(iv2, dest + len - 8, 8);
71
72 des_cbc_encrypt(dest, dest, len, ks1, &iv1, DES_DECRYPT);
73 /* memcpy(&iv1, iv2, 8); */ /* Note how iv1 == iv2 on entry and exit. */
74}
75
76/*
77 * SSH uses a variation on Blowfish, all bytes must be swapped before
78 * and after encryption/decryption. Thus the swap_bytes stuff (yuk).
79 */
80static
81void
82swap_bytes(const unsigned char *src, unsigned char *dst_, int n)
83{
84 u_int32_t *dst = (u_int32_t *)dst_; /* dst must be properly aligned. */
85 union {
86 u_int32_t i;
87 char c[4];
88 } t;
89
90 /* assert((n & 7) == 0); */
91
92 /* Process 8 bytes every lap. */
93 for (n = n / 8; n > 0; n--)
94 {
95 t.c[3] = *src++;
96 t.c[2] = *src++;
97 t.c[1] = *src++;
98 t.c[0] = *src++;
99 *dst++ = t.i;
100
101 t.c[3] = *src++;
102 t.c[2] = *src++;
103 t.c[1] = *src++;
104 t.c[0] = *src++;
105 *dst++ = t.i;
106 }
107}
108
109void (*cipher_attack_detected)(const char *fmt, ...) = fatal;
110
111static inline
112void
113detect_cbc_attack(const unsigned char *src,
114 unsigned int len)
115{
116 return;
117
118 log("CRC-32 CBC insertion attack detected");
119 cipher_attack_detected("CRC-32 CBC insertion attack detected");
120}
121
122/* Names of all encryption algorithms. These must match the numbers defined
123 int cipher.h. */
124static char *cipher_names[] =
125{
126 "none",
127 "idea",
128 "des",
129 "3des",
130 "tss",
131 "rc4",
132 "blowfish"
133};
134
135/* Returns a bit mask indicating which ciphers are supported by this
136 implementation. The bit mask has the corresponding bit set of each
137 supported cipher. */
138
139unsigned int cipher_mask()
140{
141 unsigned int mask = 0;
142 mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */
143 mask |= 1 << SSH_CIPHER_BLOWFISH;
144 return mask;
145}
146
147/* Returns the name of the cipher. */
148
149const
150char *cipher_name(int cipher)
151{
152 if (cipher < 0 || cipher >= sizeof(cipher_names) / sizeof(cipher_names[0]) ||
153 cipher_names[cipher] == NULL)
154 fatal("cipher_name: bad cipher number: %d", cipher);
155 return cipher_names[cipher];
156}
157
158/* Parses the name of the cipher. Returns the number of the corresponding
159 cipher, or -1 on error. */
160
161int
162cipher_number(const char *name)
163{
164 int i;
165 for (i = 0; i < sizeof(cipher_names) / sizeof(cipher_names[0]); i++)
166 if (strcmp(cipher_names[i], name) == 0 &&
167 (cipher_mask() & (1 << i)))
168 return i;
169 return -1;
170}
171
172/* Selects the cipher, and keys if by computing the MD5 checksum of the
173 passphrase and using the resulting 16 bytes as the key. */
174
175void cipher_set_key_string(CipherContext *context, int cipher,
176 const char *passphrase, int for_encryption)
177{
178 MD5_CTX md;
179 unsigned char digest[16];
180
181 MD5_Init(&md);
182 MD5_Update(&md, (const unsigned char *)passphrase, strlen(passphrase));
183 MD5_Final(digest, &md);
184
185 cipher_set_key(context, cipher, digest, 16, for_encryption);
186
187 memset(digest, 0, sizeof(digest));
188 memset(&md, 0, sizeof(md));
189}
190
191/* Selects the cipher to use and sets the key. */
192
193void cipher_set_key(CipherContext *context, int cipher,
194 const unsigned char *key, int keylen, int for_encryption)
195{
196 unsigned char padded[32];
197
198 /* Set cipher type. */
199 context->type = cipher;
200
201 /* Get 32 bytes of key data. Pad if necessary. (So that code below does
202 not need to worry about key size). */
203 memset(padded, 0, sizeof(padded));
204 memcpy(padded, key, keylen < sizeof(padded) ? keylen : sizeof(padded));
205
206 /* Initialize the initialization vector. */
207 switch (cipher)
208 {
209 case SSH_CIPHER_NONE:
210 /* Has to stay for authfile saving of private key with no passphrase */
211 break;
212
213 case SSH_CIPHER_3DES:
214 /* Note: the least significant bit of each byte of key is parity,
215 and must be ignored by the implementation. 16 bytes of key are
216 used (first and last keys are the same). */
217 if (keylen < 16)
218 error("Key length %d is insufficient for 3DES.", keylen);
219 des_set_key((void*)padded, context->u.des3.key1);
220 des_set_key((void*)(padded + 8), context->u.des3.key2);
221 if (keylen <= 16)
222 des_set_key((void*)padded, context->u.des3.key3);
223 else
224 des_set_key((void*)(padded + 16), context->u.des3.key3);
225 memset(context->u.des3.iv2, 0, sizeof(context->u.des3.iv2));
226 memset(context->u.des3.iv3, 0, sizeof(context->u.des3.iv3));
227 break;
228
229 case SSH_CIPHER_BLOWFISH:
230 BF_set_key(&context->u.bf.key, keylen, padded);
231 memset(context->u.bf.iv, 0, 8);
232 break;
233
234 default:
235 fatal("cipher_set_key: unknown cipher: %d", cipher);
236 }
237 memset(padded, 0, sizeof(padded));
238}
239
240/* Encrypts data using the cipher. */
241
242void cipher_encrypt(CipherContext *context, unsigned char *dest,
243 const unsigned char *src, unsigned int len)
244{
245 assert((len & 7) == 0);
246
247 switch (context->type)
248 {
249 case SSH_CIPHER_NONE:
250 memcpy(dest, src, len);
251 break;
252
253 case SSH_CIPHER_3DES:
254 SSH_3CBC_ENCRYPT(context->u.des3.key1,
255 context->u.des3.key2, &context->u.des3.iv2,
256 context->u.des3.key3, &context->u.des3.iv3,
257 dest, (void*)src, len);
258 break;
259
260 case SSH_CIPHER_BLOWFISH:
261 swap_bytes(src, dest, len);
262 BF_cbc_encrypt(dest, dest, len,
263 &context->u.bf.key, context->u.bf.iv, BF_ENCRYPT);
264 swap_bytes(dest, dest, len);
265 break;
266
267 default:
268 fatal("cipher_encrypt: unknown cipher: %d", context->type);
269 }
270}
271
272/* Decrypts data using the cipher. */
273
274void cipher_decrypt(CipherContext *context, unsigned char *dest,
275 const unsigned char *src, unsigned int len)
276{
277 assert((len & 7) == 0);
278
279 switch (context->type)
280 {
281 case SSH_CIPHER_NONE:
282 memcpy(dest, src, len);
283 break;
284
285 case SSH_CIPHER_3DES:
286 /* CRC-32 attack? */
287 SSH_3CBC_DECRYPT(context->u.des3.key1,
288 context->u.des3.key2, &context->u.des3.iv2,
289 context->u.des3.key3, &context->u.des3.iv3,
290 dest, (void*)src, len);
291 break;
292
293 case SSH_CIPHER_BLOWFISH:
294 detect_cbc_attack(src, len);
295 swap_bytes(src, dest, len);
296 BF_cbc_encrypt((void*)dest, dest, len,
297 &context->u.bf.key, context->u.bf.iv, BF_DECRYPT);
298 swap_bytes(dest, dest, len);
299 break;
300
301 default:
302 fatal("cipher_decrypt: unknown cipher: %d", context->type);
303 }
304}
diff --git a/cipher.h b/cipher.h
new file mode 100644
index 000000000..4ecb8f8da
--- /dev/null
+++ b/cipher.h
@@ -0,0 +1,84 @@
1/*
2
3cipher.h
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Wed Apr 19 16:50:42 1995 ylo
11
12*/
13
14/* RCSID("$Id: cipher.h,v 1.1 1999/10/27 03:42:44 damien Exp $"); */
15
16#ifndef CIPHER_H
17#define CIPHER_H
18
19#include <openssl/des.h>
20#include <openssl/blowfish.h>
21
22/* Cipher types. New types can be added, but old types should not be removed
23 for compatibility. The maximum allowed value is 31. */
24#define SSH_CIPHER_NOT_SET -1 /* None selected (invalid number). */
25#define SSH_CIPHER_NONE 0 /* no encryption */
26#define SSH_CIPHER_IDEA 1 /* IDEA CFB */
27#define SSH_CIPHER_DES 2 /* DES CBC */
28#define SSH_CIPHER_3DES 3 /* 3DES CBC */
29#define SSH_CIPHER_TSS 4 /* TRI's Simple Stream encryption CBC */
30#define SSH_CIPHER_RC4 5 /* Alleged RC4 */
31#define SSH_CIPHER_BLOWFISH 6
32
33typedef struct {
34 unsigned int type;
35 union {
36 struct {
37 des_key_schedule key1;
38 des_key_schedule key2;
39 des_cblock iv2;
40 des_key_schedule key3;
41 des_cblock iv3;
42 } des3;
43 struct {
44 struct bf_key_st key;
45 unsigned char iv[8];
46 } bf;
47 } u;
48} CipherContext;
49
50/* Returns a bit mask indicating which ciphers are supported by this
51 implementation. The bit mask has the corresponding bit set of each
52 supported cipher. */
53unsigned int cipher_mask();
54
55/* Returns the name of the cipher. */
56const char *cipher_name(int cipher);
57
58/* Parses the name of the cipher. Returns the number of the corresponding
59 cipher, or -1 on error. */
60int cipher_number(const char *name);
61
62/* Selects the cipher to use and sets the key. If for_encryption is true,
63 the key is setup for encryption; otherwise it is setup for decryption. */
64void cipher_set_key(CipherContext *context, int cipher,
65 const unsigned char *key, int keylen, int for_encryption);
66
67/* Sets key for the cipher by computing the MD5 checksum of the passphrase,
68 and using the resulting 16 bytes as the key. */
69void cipher_set_key_string(CipherContext *context, int cipher,
70 const char *passphrase, int for_encryption);
71
72/* Encrypts data using the cipher. */
73void cipher_encrypt(CipherContext *context, unsigned char *dest,
74 const unsigned char *src, unsigned int len);
75
76/* Decrypts data using the cipher. */
77void cipher_decrypt(CipherContext *context, unsigned char *dest,
78 const unsigned char *src, unsigned int len);
79
80/* If and CRC-32 attack is detected this function is called. Defaults
81 * to fatal, changed to packet_disconnect in sshd and ssh. */
82extern void (*cipher_attack_detected)(const char *fmt, ...);
83
84#endif /* CIPHER_H */
diff --git a/clientloop.c b/clientloop.c
new file mode 100644
index 000000000..43373b72e
--- /dev/null
+++ b/clientloop.c
@@ -0,0 +1,924 @@
1/*
2
3clientloop.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10
11Created: Sat Sep 23 12:23:57 1995 ylo
12
13The main loop for the interactive session (client side).
14
15*/
16
17#include "includes.h"
18RCSID("$Id: clientloop.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
19
20#include "xmalloc.h"
21#include "ssh.h"
22#include "packet.h"
23#include "buffer.h"
24#include "authfd.h"
25
26/* Flag indicating whether quiet mode is on. */
27extern int quiet_flag;
28
29/* Flag indicating that stdin should be redirected from /dev/null. */
30extern int stdin_null_flag;
31
32/* Name of the host we are connecting to. This is the name given on the
33 command line, or the HostName specified for the user-supplied name
34 in a configuration file. */
35extern char *host;
36
37/* Flag to indicate that we have received a window change signal which has
38 not yet been processed. This will cause a message indicating the new
39 window size to be sent to the server a little later. This is volatile
40 because this is updated in a signal handler. */
41static volatile int received_window_change_signal = 0;
42
43/* Terminal modes, as saved by enter_raw_mode. */
44static struct termios saved_tio;
45
46/* Flag indicating whether we are in raw mode. This is used by enter_raw_mode
47 and leave_raw_mode. */
48static int in_raw_mode = 0;
49
50/* Flag indicating whether the user\'s terminal is in non-blocking mode. */
51static int in_non_blocking_mode = 0;
52
53/* Common data for the client loop code. */
54static int escape_pending; /* Last character was the escape character */
55static int last_was_cr; /* Last character was a newline. */
56static int exit_status; /* Used to store the exit status of the command. */
57static int stdin_eof; /* EOF has been encountered on standard error. */
58static Buffer stdin_buffer; /* Buffer for stdin data. */
59static Buffer stdout_buffer; /* Buffer for stdout data. */
60static Buffer stderr_buffer; /* Buffer for stderr data. */
61static unsigned int buffer_high; /* Soft max buffer size. */
62static int max_fd; /* Maximum file descriptor number in select(). */
63static int connection_in; /* Connection to server (input). */
64static int connection_out; /* Connection to server (output). */
65static unsigned long stdin_bytes, stdout_bytes, stderr_bytes;
66static int quit_pending; /* Set to non-zero to quit the client loop. */
67static int escape_char; /* Escape character. */
68
69/* Returns the user\'s terminal to normal mode if it had been put in raw
70 mode. */
71
72void leave_raw_mode()
73{
74 if (!in_raw_mode)
75 return;
76 in_raw_mode = 0;
77 if (tcsetattr(fileno(stdin), TCSADRAIN, &saved_tio) < 0)
78 perror("tcsetattr");
79
80 fatal_remove_cleanup((void (*)(void *))leave_raw_mode, NULL);
81}
82
83/* Puts the user\'s terminal in raw mode. */
84
85void enter_raw_mode()
86{
87 struct termios tio;
88
89 if (tcgetattr(fileno(stdin), &tio) < 0)
90 perror("tcgetattr");
91 saved_tio = tio;
92 tio.c_iflag |= IGNPAR;
93 tio.c_iflag &= ~(ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXANY|IXOFF);
94 tio.c_lflag &= ~(ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHONL);
95#ifdef IEXTEN
96 tio.c_lflag &= ~IEXTEN;
97#endif /* IEXTEN */
98 tio.c_oflag &= ~OPOST;
99 tio.c_cc[VMIN] = 1;
100 tio.c_cc[VTIME] = 0;
101 if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) < 0)
102 perror("tcsetattr");
103 in_raw_mode = 1;
104
105 fatal_add_cleanup((void (*)(void *))leave_raw_mode, NULL);
106}
107
108/* Puts stdin terminal in non-blocking mode. */
109
110/* Restores stdin to blocking mode. */
111
112void leave_non_blocking()
113{
114 if (in_non_blocking_mode)
115 {
116 (void)fcntl(fileno(stdin), F_SETFL, 0);
117 in_non_blocking_mode = 0;
118 fatal_remove_cleanup((void (*)(void *))leave_non_blocking, NULL);
119 }
120}
121
122void enter_non_blocking()
123{
124 in_non_blocking_mode = 1;
125 (void)fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
126 fatal_add_cleanup((void (*)(void *))leave_non_blocking, NULL);
127}
128
129/* Signal handler for the window change signal (SIGWINCH). This just
130 sets a flag indicating that the window has changed. */
131
132void window_change_handler(int sig)
133{
134 received_window_change_signal = 1;
135 signal(SIGWINCH, window_change_handler);
136}
137
138/* Signal handler for signals that cause the program to terminate. These
139 signals must be trapped to restore terminal modes. */
140
141void signal_handler(int sig)
142{
143 if (in_raw_mode)
144 leave_raw_mode();
145 if (in_non_blocking_mode)
146 leave_non_blocking();
147 channel_stop_listening();
148 packet_close();
149 fatal("Killed by signal %d.", sig);
150}
151
152/* Returns current time in seconds from Jan 1, 1970 with the maximum available
153 resolution. */
154
155double get_current_time()
156{
157 struct timeval tv;
158 gettimeofday(&tv, NULL);
159 return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
160}
161
162/* This is called when the interactive is entered. This checks if there
163 is an EOF coming on stdin. We must check this explicitly, as select()
164 does not appear to wake up when redirecting from /dev/null. */
165
166void client_check_initial_eof_on_stdin()
167{
168 int len;
169 char buf[1];
170
171 /* If standard input is to be "redirected from /dev/null", we simply
172 mark that we have seen an EOF and send an EOF message to the server.
173 Otherwise, we try to read a single character; it appears that for some
174 files, such /dev/null, select() never wakes up for read for this
175 descriptor, which means that we never get EOF. This way we will get
176 the EOF if stdin comes from /dev/null or similar. */
177 if (stdin_null_flag)
178 {
179 /* Fake EOF on stdin. */
180 debug("Sending eof.");
181 stdin_eof = 1;
182 packet_start(SSH_CMSG_EOF);
183 packet_send();
184 }
185 else
186 {
187 /* Enter non-blocking mode for stdin. */
188 enter_non_blocking();
189
190 /* Check for immediate EOF on stdin. */
191 len = read(fileno(stdin), buf, 1);
192 if (len == 0)
193 {
194 /* EOF. Record that we have seen it and send EOF to server. */
195 debug("Sending eof.");
196 stdin_eof = 1;
197 packet_start(SSH_CMSG_EOF);
198 packet_send();
199 }
200 else
201 if (len > 0)
202 {
203 /* Got data. We must store the data in the buffer, and also
204 process it as an escape character if appropriate. */
205 if ((unsigned char)buf[0] == escape_char)
206 escape_pending = 1;
207 else
208 {
209 buffer_append(&stdin_buffer, buf, 1);
210 stdin_bytes += 1;
211 }
212 }
213
214 /* Leave non-blocking mode. */
215 leave_non_blocking();
216 }
217}
218
219/* Get packets from the connection input buffer, and process them as long
220 as there are packets available. */
221
222void client_process_buffered_input_packets()
223{
224 int type;
225 char *data;
226 unsigned int data_len;
227 int payload_len;
228
229 /* Process any buffered packets from the server. */
230 while (!quit_pending && (type = packet_read_poll(&payload_len)) != SSH_MSG_NONE)
231 {
232 switch (type)
233 {
234
235 case SSH_SMSG_STDOUT_DATA:
236 data = packet_get_string(&data_len);
237 packet_integrity_check(payload_len, 4 + data_len, type);
238 buffer_append(&stdout_buffer, data, data_len);
239 stdout_bytes += data_len;
240 memset(data, 0, data_len);
241 xfree(data);
242 break;
243
244 case SSH_SMSG_STDERR_DATA:
245 data = packet_get_string(&data_len);
246 packet_integrity_check(payload_len, 4 + data_len, type);
247 buffer_append(&stderr_buffer, data, data_len);
248 stdout_bytes += data_len;
249 memset(data, 0, data_len);
250 xfree(data);
251 break;
252
253 case SSH_SMSG_EXITSTATUS:
254 packet_integrity_check(payload_len, 4, type);
255 exit_status = packet_get_int();
256 /* Acknowledge the exit. */
257 packet_start(SSH_CMSG_EXIT_CONFIRMATION);
258 packet_send();
259 /* Must wait for packet to be sent since we are exiting the
260 loop. */
261 packet_write_wait();
262 /* Flag that we want to exit. */
263 quit_pending = 1;
264 break;
265
266 case SSH_SMSG_X11_OPEN:
267 x11_input_open(payload_len);
268 break;
269
270 case SSH_MSG_PORT_OPEN:
271 channel_input_port_open(payload_len);
272 break;
273
274 case SSH_SMSG_AGENT_OPEN:
275 packet_integrity_check(payload_len, 4, type);
276 auth_input_open_request();
277 break;
278
279 case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
280 packet_integrity_check(payload_len, 4 + 4, type);
281 channel_input_open_confirmation();
282 break;
283
284 case SSH_MSG_CHANNEL_OPEN_FAILURE:
285 packet_integrity_check(payload_len, 4, type);
286 channel_input_open_failure();
287 break;
288
289 case SSH_MSG_CHANNEL_DATA:
290 channel_input_data(payload_len);
291 break;
292
293 case SSH_MSG_CHANNEL_CLOSE:
294 packet_integrity_check(payload_len, 4, type);
295 channel_input_close();
296 break;
297
298 case SSH_MSG_CHANNEL_CLOSE_CONFIRMATION:
299 packet_integrity_check(payload_len, 4, type);
300 channel_input_close_confirmation();
301 break;
302
303 default:
304 /* Any unknown packets received during the actual session
305 cause the session to terminate. This is intended to make
306 debugging easier since no confirmations are sent. Any
307 compatible protocol extensions must be negotiated during
308 the preparatory phase. */
309 packet_disconnect("Protocol error during session: type %d",
310 type);
311 }
312 }
313}
314
315/* Make packets from buffered stdin data, and buffer them for sending to
316 the connection. */
317
318void client_make_packets_from_stdin_data()
319{
320 unsigned int len;
321
322 /* Send buffered stdin data to the server. */
323 while (buffer_len(&stdin_buffer) > 0 &&
324 packet_not_very_much_data_to_write())
325 {
326 len = buffer_len(&stdin_buffer);
327 if (len > 32768)
328 len = 32768; /* Keep the packets at reasonable size. */
329 packet_start(SSH_CMSG_STDIN_DATA);
330 packet_put_string(buffer_ptr(&stdin_buffer), len);
331 packet_send();
332 buffer_consume(&stdin_buffer, len);
333 /* If we have a pending EOF, send it now. */
334 if (stdin_eof && buffer_len(&stdin_buffer) == 0)
335 {
336 packet_start(SSH_CMSG_EOF);
337 packet_send();
338 }
339 }
340}
341
342/* Checks if the client window has changed, and sends a packet about it to
343 the server if so. The actual change is detected elsewhere (by a software
344 interrupt on Unix); this just checks the flag and sends a message if
345 appropriate. */
346
347void client_check_window_change()
348{
349 /* Send possible window change message to the server. */
350 if (received_window_change_signal)
351 {
352 struct winsize ws;
353
354 /* Clear the window change indicator. */
355 received_window_change_signal = 0;
356
357 /* Read new window size. */
358 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) >= 0)
359 {
360 /* Successful, send the packet now. */
361 packet_start(SSH_CMSG_WINDOW_SIZE);
362 packet_put_int(ws.ws_row);
363 packet_put_int(ws.ws_col);
364 packet_put_int(ws.ws_xpixel);
365 packet_put_int(ws.ws_ypixel);
366 packet_send();
367 }
368 }
369}
370
371/* Waits until the client can do something (some data becomes available on
372 one of the file descriptors). */
373
374void client_wait_until_can_do_something(fd_set *readset, fd_set *writeset)
375{
376 /* Initialize select masks. */
377 FD_ZERO(readset);
378
379 /* Read from the connection, unless our buffers are full. */
380 if (buffer_len(&stdout_buffer) < buffer_high &&
381 buffer_len(&stderr_buffer) < buffer_high &&
382 channel_not_very_much_buffered_data())
383 FD_SET(connection_in, readset);
384
385 /* Read from stdin, unless we have seen EOF or have very much buffered
386 data to send to the server. */
387 if (!stdin_eof && packet_not_very_much_data_to_write())
388 FD_SET(fileno(stdin), readset);
389
390 FD_ZERO(writeset);
391
392 /* Add any selections by the channel mechanism. */
393 channel_prepare_select(readset, writeset);
394
395 /* Select server connection if have data to write to the server. */
396 if (packet_have_data_to_write())
397 FD_SET(connection_out, writeset);
398
399 /* Select stdout if have data in buffer. */
400 if (buffer_len(&stdout_buffer) > 0)
401 FD_SET(fileno(stdout), writeset);
402
403 /* Select stderr if have data in buffer. */
404 if (buffer_len(&stderr_buffer) > 0)
405 FD_SET(fileno(stderr), writeset);
406
407 /* Update maximum file descriptor number, if appropriate. */
408 if (channel_max_fd() > max_fd)
409 max_fd = channel_max_fd();
410
411 /* Wait for something to happen. This will suspend the process until
412 some selected descriptor can be read, written, or has some other
413 event pending. Note: if you want to implement SSH_MSG_IGNORE
414 messages to fool traffic analysis, this might be the place to do
415 it: just have a random timeout for the select, and send a random
416 SSH_MSG_IGNORE packet when the timeout expires. */
417 if (select(max_fd + 1, readset, writeset, NULL, NULL) < 0)
418 {
419 char buf[100];
420 /* Some systems fail to clear these automatically. */
421 FD_ZERO(readset);
422 FD_ZERO(writeset);
423 if (errno == EINTR)
424 return;
425 /* Note: we might still have data in the buffers. */
426 snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno));
427 buffer_append(&stderr_buffer, buf, strlen(buf));
428 stderr_bytes += strlen(buf);
429 quit_pending = 1;
430 }
431}
432
433void client_suspend_self()
434{
435 struct winsize oldws, newws;
436
437 /* Flush stdout and stderr buffers. */
438 if (buffer_len(&stdout_buffer) > 0)
439 write(fileno(stdout),
440 buffer_ptr(&stdout_buffer),
441 buffer_len(&stdout_buffer));
442 if (buffer_len(&stderr_buffer) > 0)
443 write(fileno(stderr),
444 buffer_ptr(&stderr_buffer),
445 buffer_len(&stderr_buffer));
446
447 /* Leave raw mode. */
448 leave_raw_mode();
449
450 /* Free (and clear) the buffer to reduce the
451 amount of data that gets written to swap. */
452 buffer_free(&stdin_buffer);
453 buffer_free(&stdout_buffer);
454 buffer_free(&stderr_buffer);
455
456 /* Save old window size. */
457 ioctl(fileno(stdin), TIOCGWINSZ, &oldws);
458
459 /* Send the suspend signal to the program
460 itself. */
461 kill(getpid(), SIGTSTP);
462
463 /* Check if the window size has changed. */
464 if (ioctl(fileno(stdin), TIOCGWINSZ, &newws) >= 0 &&
465 (oldws.ws_row != newws.ws_row || oldws.ws_col != newws.ws_col ||
466 oldws.ws_xpixel != newws.ws_xpixel ||
467 oldws.ws_ypixel != newws.ws_ypixel))
468 received_window_change_signal = 1;
469
470 /* OK, we have been continued by the user.
471 Reinitialize buffers. */
472 buffer_init(&stdin_buffer);
473 buffer_init(&stdout_buffer);
474 buffer_init(&stderr_buffer);
475
476 /* Re-enter raw mode. */
477 enter_raw_mode();
478}
479
480void client_process_input(fd_set *readset)
481{
482 int len, pid;
483 char buf[8192], *s;
484
485 /* Read input from the server, and add any such data to the buffer of the
486 packet subsystem. */
487 if (FD_ISSET(connection_in, readset))
488 {
489 /* Read as much as possible. */
490 len = read(connection_in, buf, sizeof(buf));
491 if (len == 0)
492 {
493 /* Received EOF. The remote host has closed the connection. */
494 snprintf(buf, sizeof buf, "Connection to %.300s closed by remote host.\r\n",
495 host);
496 buffer_append(&stderr_buffer, buf, strlen(buf));
497 stderr_bytes += strlen(buf);
498 quit_pending = 1;
499 return;
500 }
501
502 /* There is a kernel bug on Solaris that causes select to sometimes
503 wake up even though there is no data available. */
504 if (len < 0 && errno == EAGAIN)
505 len = 0;
506
507 if (len < 0)
508 {
509 /* An error has encountered. Perhaps there is a network
510 problem. */
511 snprintf(buf, sizeof buf, "Read from remote host %.300s: %.100s\r\n",
512 host, strerror(errno));
513 buffer_append(&stderr_buffer, buf, strlen(buf));
514 stderr_bytes += strlen(buf);
515 quit_pending = 1;
516 return;
517 }
518 packet_process_incoming(buf, len);
519 }
520
521 /* Read input from stdin. */
522 if (FD_ISSET(fileno(stdin), readset))
523 {
524 /* Read as much as possible. */
525 len = read(fileno(stdin), buf, sizeof(buf));
526 if (len <= 0)
527 {
528 /* Received EOF or error. They are treated similarly,
529 except that an error message is printed if it was
530 an error condition. */
531 if (len < 0)
532 {
533 snprintf(buf, sizeof buf, "read: %.100s\r\n", strerror(errno));
534 buffer_append(&stderr_buffer, buf, strlen(buf));
535 stderr_bytes += strlen(buf);
536 }
537 /* Mark that we have seen EOF. */
538 stdin_eof = 1;
539 /* Send an EOF message to the server unless there is data
540 in the buffer. If there is data in the buffer, no message
541 will be sent now. Code elsewhere will send the EOF
542 when the buffer becomes empty if stdin_eof is set. */
543 if (buffer_len(&stdin_buffer) == 0)
544 {
545 packet_start(SSH_CMSG_EOF);
546 packet_send();
547 }
548 }
549 else
550 if (escape_char == -1)
551 {
552 /* Normal successful read, and no escape character. Just
553 append the data to buffer. */
554 buffer_append(&stdin_buffer, buf, len);
555 stdin_bytes += len;
556 }
557 else
558 {
559 /* Normal, successful read. But we have an escape character
560 and have to process the characters one by one. */
561 unsigned int i;
562 for (i = 0; i < len; i++)
563 {
564 unsigned char ch;
565 /* Get one character at a time. */
566 ch = buf[i];
567
568 /* Check if we have a pending escape character. */
569 if (escape_pending)
570 {
571 /* We have previously seen an escape character. */
572 /* Clear the flag now. */
573 escape_pending = 0;
574 /* Process the escaped character. */
575 switch (ch)
576 {
577 case '.':
578 /* Terminate the connection. */
579 snprintf(buf, sizeof buf, "%c.\r\n", escape_char);
580 buffer_append(&stderr_buffer, buf, strlen(buf));
581 stderr_bytes += strlen(buf);
582 quit_pending = 1;
583 return;
584
585 case 'Z' - 64:
586 /* Suspend the program. */
587 /* Print a message to that effect to the user. */
588 snprintf(buf, sizeof buf, "%c^Z\r\n", escape_char);
589 buffer_append(&stderr_buffer, buf, strlen(buf));
590 stderr_bytes += strlen(buf);
591
592 /* Restore terminal modes and suspend. */
593 client_suspend_self();
594
595 /* We have been continued. */
596 continue;
597
598 case '&':
599 /* Detach the program (continue to serve connections,
600 but put in background and no more new
601 connections). */
602 if (!stdin_eof)
603 {
604 /* Sending SSH_CMSG_EOF alone does not always
605 appear to be enough. So we try to send an
606 EOF character first. */
607 packet_start(SSH_CMSG_STDIN_DATA);
608 packet_put_string("\004", 1);
609 packet_send();
610 /* Close stdin. */
611 stdin_eof = 1;
612 if (buffer_len(&stdin_buffer) == 0)
613 {
614 packet_start(SSH_CMSG_EOF);
615 packet_send();
616 }
617 }
618 /* Restore tty modes. */
619 leave_raw_mode();
620
621 /* Stop listening for new connections. */
622 channel_stop_listening();
623
624 printf("%c& [backgrounded]\n", escape_char);
625
626 /* Fork into background. */
627 pid = fork();
628 if (pid < 0)
629 {
630 error("fork: %.100s", strerror(errno));
631 continue;
632 }
633 if (pid != 0)
634 { /* This is the parent. */
635 /* The parent just exits. */
636 exit(0);
637 }
638
639 /* The child continues serving connections. */
640 continue;
641
642 case '?':
643 snprintf(buf, sizeof buf, "%c?\r\n\
644Supported escape sequences:\r\n\
645~. - terminate connection\r\n\
646~^Z - suspend ssh\r\n\
647~# - list forwarded connections\r\n\
648~& - background ssh (when waiting for connections to terminate)\r\n\
649~? - this message\r\n\
650~~ - send the escape character by typing it twice\r\n\
651(Note that escapes are only recognized immediately after newline.)\r\n",
652 escape_char);
653 buffer_append(&stderr_buffer, buf, strlen(buf));
654 continue;
655
656 case '#':
657 snprintf(buf, sizeof buf, "%c#\r\n", escape_char);
658 buffer_append(&stderr_buffer, buf, strlen(buf));
659 s = channel_open_message();
660 buffer_append(&stderr_buffer, s, strlen(s));
661 xfree(s);
662 continue;
663
664 default:
665 if (ch != escape_char)
666 {
667 /* Escape character followed by non-special
668 character. Append both to the input
669 buffer. */
670 buf[0] = escape_char;
671 buf[1] = ch;
672 buffer_append(&stdin_buffer, buf, 2);
673 stdin_bytes += 2;
674 continue;
675 }
676 /* Note that escape character typed twice falls through
677 here; the latter gets processed as a normal
678 character below. */
679 break;
680 }
681 }
682 else
683 {
684 /* The previous character was not an escape char.
685 Check if this is an escape. */
686 if (last_was_cr && ch == escape_char)
687 {
688 /* It is. Set the flag and continue to next
689 character. */
690 escape_pending = 1;
691 continue;
692 }
693 }
694
695 /* Normal character. Record whether it was a newline,
696 and append it to the buffer. */
697 last_was_cr = (ch == '\r' || ch == '\n');
698 buf[0] = ch;
699 buffer_append(&stdin_buffer, buf, 1);
700 stdin_bytes += 1;
701 continue;
702 }
703 }
704 }
705}
706
707void client_process_output(fd_set *writeset)
708{
709 int len;
710 char buf[100];
711
712 /* Write buffered output to stdout. */
713 if (FD_ISSET(fileno(stdout), writeset))
714 {
715 /* Write as much data as possible. */
716 len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
717 buffer_len(&stdout_buffer));
718 if (len <= 0)
719 {
720 if (errno == EAGAIN)
721 len = 0;
722 else
723 {
724 /* An error or EOF was encountered. Put an error message
725 to stderr buffer. */
726 snprintf(buf, sizeof buf, "write stdout: %.50s\r\n", strerror(errno));
727 buffer_append(&stderr_buffer, buf, strlen(buf));
728 stderr_bytes += strlen(buf);
729 quit_pending = 1;
730 return;
731 }
732 }
733 /* Consume printed data from the buffer. */
734 buffer_consume(&stdout_buffer, len);
735 }
736
737 /* Write buffered output to stderr. */
738 if (FD_ISSET(fileno(stderr), writeset))
739 {
740 /* Write as much data as possible. */
741 len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
742 buffer_len(&stderr_buffer));
743 if (len <= 0) {
744 if (errno == EAGAIN)
745 len = 0;
746 else
747 {
748 /* EOF or error, but can't even print error message. */
749 quit_pending = 1;
750 return;
751 }
752 }
753 /* Consume printed characters from the buffer. */
754 buffer_consume(&stderr_buffer, len);
755 }
756}
757
758/* Implements the interactive session with the server. This is called
759 after the user has been authenticated, and a command has been
760 started on the remote host. If escape_char != -1, it is the character
761 used as an escape character for terminating or suspending the
762 session. */
763
764int client_loop(int have_pty, int escape_char_arg)
765{
766 double start_time, total_time;
767 int len;
768 char buf[100];
769
770 debug("Entering interactive session.");
771
772 start_time = get_current_time();
773
774 /* Initialize variables. */
775 escape_pending = 0;
776 last_was_cr = 1;
777 exit_status = -1;
778 stdin_eof = 0;
779 buffer_high = 64 * 1024;
780 connection_in = packet_get_connection_in();
781 connection_out = packet_get_connection_out();
782 max_fd = connection_in;
783 if (connection_out > max_fd)
784 max_fd = connection_out;
785 stdin_bytes = 0;
786 stdout_bytes = 0;
787 stderr_bytes = 0;
788 quit_pending = 0;
789 escape_char = escape_char_arg;
790
791 /* Initialize buffers. */
792 buffer_init(&stdin_buffer);
793 buffer_init(&stdout_buffer);
794 buffer_init(&stderr_buffer);
795
796 /* Set signal handlers to restore non-blocking mode. */
797 signal(SIGINT, signal_handler);
798 signal(SIGQUIT, signal_handler);
799 signal(SIGTERM, signal_handler);
800 signal(SIGPIPE, SIG_IGN);
801 if (have_pty)
802 signal(SIGWINCH, window_change_handler);
803
804 /* Enter raw mode if have a pseudo terminal. */
805 if (have_pty)
806 enter_raw_mode();
807
808 /* Check if we should immediately send of on stdin. */
809 client_check_initial_eof_on_stdin();
810
811 /* Main loop of the client for the interactive session mode. */
812 while (!quit_pending)
813 {
814 fd_set readset, writeset;
815
816 /* Precess buffered packets sent by the server. */
817 client_process_buffered_input_packets();
818
819 /* Make packets of buffered stdin data, and buffer them for sending
820 to the server. */
821 client_make_packets_from_stdin_data();
822
823 /* Make packets from buffered channel data, and buffer them for sending
824 to the server. */
825 if (packet_not_very_much_data_to_write())
826 channel_output_poll();
827
828 /* Check if the window size has changed, and buffer a message about
829 it to the server if so. */
830 client_check_window_change();
831
832 if (quit_pending)
833 break;
834
835 /* Wait until we have something to do (something becomes available
836 on one of the descriptors). */
837 client_wait_until_can_do_something(&readset, &writeset);
838
839 if (quit_pending)
840 break;
841
842 /* Do channel operations. */
843 channel_after_select(&readset, &writeset);
844
845 /* Process input from the connection and from stdin. Buffer any data
846 that is available. */
847 client_process_input(&readset);
848
849 /* Process output to stdout and stderr. Output to the connection
850 is processed elsewhere (above). */
851 client_process_output(&writeset);
852
853 /* Send as much buffered packet data as possible to the sender. */
854 if (FD_ISSET(connection_out, &writeset))
855 packet_write_poll();
856 }
857
858 /* Terminate the session. */
859
860 /* Stop watching for window change. */
861 if (have_pty)
862 signal(SIGWINCH, SIG_DFL);
863
864 /* Stop listening for connections. */
865 channel_stop_listening();
866
867 /* In interactive mode (with pseudo tty) display a message indicating that
868 the connection has been closed. */
869 if (have_pty && !quiet_flag)
870 {
871 snprintf(buf, sizeof buf, "Connection to %.64s closed.\r\n", host);
872 buffer_append(&stderr_buffer, buf, strlen(buf));
873 stderr_bytes += strlen(buf);
874 }
875
876 /* Output any buffered data for stdout. */
877 while (buffer_len(&stdout_buffer) > 0)
878 {
879 len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
880 buffer_len(&stdout_buffer));
881 if (len <= 0)
882 {
883 error("Write failed flushing stdout buffer.");
884 break;
885 }
886 buffer_consume(&stdout_buffer, len);
887 }
888
889 /* Output any buffered data for stderr. */
890 while (buffer_len(&stderr_buffer) > 0)
891 {
892 len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
893 buffer_len(&stderr_buffer));
894 if (len <= 0)
895 {
896 error("Write failed flushing stderr buffer.");
897 break;
898 }
899 buffer_consume(&stderr_buffer, len);
900 }
901
902 /* Leave raw mode. */
903 if (have_pty)
904 leave_raw_mode();
905
906 /* Clear and free any buffers. */
907 memset(buf, 0, sizeof(buf));
908 buffer_free(&stdin_buffer);
909 buffer_free(&stdout_buffer);
910 buffer_free(&stderr_buffer);
911
912 /* Report bytes transferred, and transfer rates. */
913 total_time = get_current_time() - start_time;
914 debug("Transferred: stdin %lu, stdout %lu, stderr %lu bytes in %.1f seconds",
915 stdin_bytes, stdout_bytes, stderr_bytes, total_time);
916 if (total_time > 0)
917 debug("Bytes per second: stdin %.1f, stdout %.1f, stderr %.1f",
918 stdin_bytes / total_time, stdout_bytes / total_time,
919 stderr_bytes / total_time);
920
921 /* Return the exit status of the program. */
922 debug("Exit status %d", exit_status);
923 return exit_status;
924}
diff --git a/compat.c b/compat.c
new file mode 100644
index 000000000..4974b1cba
--- /dev/null
+++ b/compat.c
@@ -0,0 +1,10 @@
1#include "includes.h"
2RCSID("$Id: compat.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
3
4#include "ssh.h"
5
6int compat13=0;
7void enable_compat13(void){
8 log("Enabling compatibility mode for protocol 1.3");
9 compat13=1;
10}
diff --git a/compat.h b/compat.h
new file mode 100644
index 000000000..9d896c7dd
--- /dev/null
+++ b/compat.h
@@ -0,0 +1,7 @@
1/* RCSID("$Id: compat.h,v 1.1 1999/10/27 03:42:44 damien Exp $"); */
2
3#ifndef COMPAT_H
4#define COMPAT_H
5void enable_compat13(void);
6extern int compat13;
7#endif
diff --git a/compress.c b/compress.c
new file mode 100644
index 000000000..c3267f73f
--- /dev/null
+++ b/compress.c
@@ -0,0 +1,160 @@
1/*
2
3compress.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Wed Oct 25 22:12:46 1995 ylo
11
12Interface to packet compression for ssh.
13
14*/
15
16#include "includes.h"
17RCSID("$Id: compress.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
18
19#include "ssh.h"
20#include "buffer.h"
21#include "zlib.h"
22
23static z_stream incoming_stream;
24static z_stream outgoing_stream;
25
26/* Initializes compression; level is compression level from 1 to 9 (as in
27 gzip). */
28
29void buffer_compress_init(int level)
30{
31 debug("Enabling compression at level %d.", level);
32 if (level < 1 || level > 9)
33 fatal("Bad compression level %d.", level);
34 inflateInit(&incoming_stream);
35 deflateInit(&outgoing_stream, level);
36}
37
38/* Frees any data structures allocated for compression. */
39
40void buffer_compress_uninit()
41{
42 debug("compress outgoing: raw data %lu, compressed %lu, factor %.2f",
43 outgoing_stream.total_in, outgoing_stream.total_out,
44 outgoing_stream.total_in == 0 ? 0.0 :
45 (double)outgoing_stream.total_out / outgoing_stream.total_in);
46 debug("compress incoming: raw data %lu, compressed %lu, factor %.2f",
47 incoming_stream.total_out, incoming_stream.total_in,
48 incoming_stream.total_out == 0 ? 0.0 :
49 (double)incoming_stream.total_in / incoming_stream.total_out);
50 inflateEnd(&incoming_stream);
51 deflateEnd(&outgoing_stream);
52}
53
54/* Compresses the contents of input_buffer into output_buffer. All
55 packets compressed using this function will form a single
56 compressed data stream; however, data will be flushed at the end of
57 every call so that each output_buffer can be decompressed
58 independently (but in the appropriate order since they together
59 form a single compression stream) by the receiver. This appends
60 the compressed data to the output buffer. */
61
62void buffer_compress(Buffer *input_buffer, Buffer *output_buffer)
63{
64 char buf[4096];
65 int status;
66
67 /* This case is not handled below. */
68 if (buffer_len(input_buffer) == 0)
69 return;
70
71 /* Input is the contents of the input buffer. */
72 outgoing_stream.next_in = buffer_ptr(input_buffer);
73 outgoing_stream.avail_in = buffer_len(input_buffer);
74
75 /* Loop compressing until deflate() returns with avail_out != 0. */
76 do
77 {
78 /* Set up fixed-size output buffer. */
79 outgoing_stream.next_out = buf;
80 outgoing_stream.avail_out = sizeof(buf);
81
82 /* Compress as much data into the buffer as possible. */
83 status = deflate(&outgoing_stream, Z_PARTIAL_FLUSH);
84 switch (status)
85 {
86 case Z_OK:
87 /* Append compressed data to output_buffer. */
88 buffer_append(output_buffer, buf,
89 sizeof(buf) - outgoing_stream.avail_out);
90 break;
91 case Z_STREAM_END:
92 fatal("buffer_compress: deflate returned Z_STREAM_END");
93 /*NOTREACHED*/
94 case Z_STREAM_ERROR:
95 fatal("buffer_compress: deflate returned Z_STREAM_ERROR");
96 /*NOTREACHED*/
97 case Z_BUF_ERROR:
98 fatal("buffer_compress: deflate returned Z_BUF_ERROR");
99 /*NOTREACHED*/
100 default:
101 fatal("buffer_compress: deflate returned %d", status);
102 /*NOTREACHED*/
103 }
104 }
105 while (outgoing_stream.avail_out == 0);
106}
107
108/* Uncompresses the contents of input_buffer into output_buffer. All
109 packets uncompressed using this function will form a single
110 compressed data stream; however, data will be flushed at the end of
111 every call so that each output_buffer. This must be called for the
112 same size units that the buffer_compress was called, and in the
113 same order that buffers compressed with that. This appends the
114 uncompressed data to the output buffer. */
115
116void buffer_uncompress(Buffer *input_buffer, Buffer *output_buffer)
117{
118 char buf[4096];
119 int status;
120
121 incoming_stream.next_in = buffer_ptr(input_buffer);
122 incoming_stream.avail_in = buffer_len(input_buffer);
123
124 incoming_stream.next_out = buf;
125 incoming_stream.avail_out = sizeof(buf);
126
127 for (;;)
128 {
129 status = inflate(&incoming_stream, Z_PARTIAL_FLUSH);
130 switch (status)
131 {
132 case Z_OK:
133 buffer_append(output_buffer, buf,
134 sizeof(buf) - incoming_stream.avail_out);
135 incoming_stream.next_out = buf;
136 incoming_stream.avail_out = sizeof(buf);
137 break;
138 case Z_STREAM_END:
139 fatal("buffer_uncompress: inflate returned Z_STREAM_END");
140 /*NOTREACHED*/
141 case Z_DATA_ERROR:
142 fatal("buffer_uncompress: inflate returned Z_DATA_ERROR");
143 /*NOTREACHED*/
144 case Z_STREAM_ERROR:
145 fatal("buffer_uncompress: inflate returned Z_STREAM_ERROR");
146 /*NOTREACHED*/
147 case Z_BUF_ERROR:
148 /* Comments in zlib.h say that we should keep calling inflate()
149 until we get an error. This appears to be the error that we
150 get. */
151 return;
152 case Z_MEM_ERROR:
153 fatal("buffer_uncompress: inflate returned Z_MEM_ERROR");
154 /*NOTREACHED*/
155 default:
156 fatal("buffer_uncompress: inflate returned %d", status);
157 }
158 }
159}
160
diff --git a/compress.h b/compress.h
new file mode 100644
index 000000000..b3144d621
--- /dev/null
+++ b/compress.h
@@ -0,0 +1,46 @@
1/*
2
3compress.h
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Wed Oct 25 22:12:46 1995 ylo
11
12Interface to packet compression for ssh.
13
14*/
15
16/* RCSID("$Id: compress.h,v 1.1 1999/10/27 03:42:44 damien Exp $"); */
17
18#ifndef COMPRESS_H
19#define COMPRESS_H
20
21/* Initializes compression; level is compression level from 1 to 9 (as in
22 gzip). */
23void buffer_compress_init(int level);
24
25/* Frees any data structures allocated by buffer_compress_init. */
26void buffer_compress_uninit();
27
28/* Compresses the contents of input_buffer into output_buffer. All
29 packets compressed using this function will form a single
30 compressed data stream; however, data will be flushed at the end of
31 every call so that each output_buffer can be decompressed
32 independently (but in the appropriate order since they together
33 form a single compression stream) by the receiver. This appends
34 the compressed data to the output buffer. */
35void buffer_compress(Buffer *input_buffer, Buffer *output_buffer);
36
37/* Uncompresses the contents of input_buffer into output_buffer. All
38 packets uncompressed using this function will form a single
39 compressed data stream; however, data will be flushed at the end of
40 every call so that each output_buffer. This must be called for the
41 same size units that the buffer_compress was called, and in the
42 same order that buffers compressed with that. This appends the
43 uncompressed data to the output buffer. */
44void buffer_uncompress(Buffer *input_buffer, Buffer *output_buffer);
45
46#endif /* COMPRESS_H */
diff --git a/crc32.c b/crc32.c
new file mode 100644
index 000000000..dbb1e6b7b
--- /dev/null
+++ b/crc32.c
@@ -0,0 +1,120 @@
1/* The implementation here was originally done by Gary S. Brown. I have
2 borrowed the tables directly, and made some minor changes to the
3 crc32-function (including changing the interface). //ylo */
4
5#include "includes.h"
6RCSID("$Id: crc32.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
7
8#include "crc32.h"
9
10 /* ============================================================= */
11 /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or */
12 /* code or tables extracted from it, as desired without restriction. */
13 /* */
14 /* First, the polynomial itself and its table of feedback terms. The */
15 /* polynomial is */
16 /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
17 /* */
18 /* Note that we take it "backwards" and put the highest-order term in */
19 /* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
20 /* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
21 /* the MSB being 1. */
22 /* */
23 /* Note that the usual hardware shift register implementation, which */
24 /* is what we're using (we're merely optimizing it by doing eight-bit */
25 /* chunks at a time) shifts bits into the lowest-order term. In our */
26 /* implementation, that means shifting towards the right. Why do we */
27 /* do it this way? Because the calculated CRC must be transmitted in */
28 /* order from highest-order term to lowest-order term. UARTs transmit */
29 /* characters in order from LSB to MSB. By storing the CRC this way, */
30 /* we hand it to the UART in the order low-byte to high-byte; the UART */
31 /* sends each low-bit to hight-bit; and the result is transmission bit */
32 /* by bit from highest- to lowest-order term without requiring any bit */
33 /* shuffling on our part. Reception works similarly. */
34 /* */
35 /* The feedback terms table consists of 256, 32-bit entries. Notes: */
36 /* */
37 /* The table can be generated at runtime if desired; code to do so */
38 /* is shown later. It might not be obvious, but the feedback */
39 /* terms simply represent the results of eight shift/xor opera- */
40 /* tions for all combinations of data and CRC register values. */
41 /* */
42 /* The values must be right-shifted by eight bits by the "updcrc" */
43 /* logic; the shift must be unsigned (bring in zeroes). On some */
44 /* hardware you could probably optimize the shift in assembler by */
45 /* using byte-swap instructions. */
46 /* polynomial $edb88320 */
47 /* */
48 /* -------------------------------------------------------------------- */
49
50static unsigned int crc32_tab[] = {
51 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
52 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
53 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
54 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
55 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
56 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
57 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
58 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
59 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
60 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
61 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
62 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
63 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
64 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
65 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
66 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
67 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
68 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
69 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
70 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
71 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
72 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
73 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
74 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
75 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
76 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
77 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
78 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
79 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
80 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
81 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
82 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
83 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
84 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
85 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
86 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
87 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
88 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
89 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
90 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
91 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
92 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
93 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
94 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
95 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
96 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
97 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
98 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
99 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
100 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
101 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
102 0x2d02ef8dL
103 };
104
105/* Return a 32-bit CRC of the contents of the buffer. */
106
107unsigned int crc32(const unsigned char *s, unsigned int len)
108{
109 unsigned int i;
110 unsigned int crc32val;
111
112 crc32val = 0;
113 for (i = 0; i < len; i ++)
114 {
115 crc32val =
116 crc32_tab[(crc32val ^ s[i]) & 0xff] ^
117 (crc32val >> 8);
118 }
119 return crc32val;
120}
diff --git a/crc32.h b/crc32.h
new file mode 100644
index 000000000..456b20b86
--- /dev/null
+++ b/crc32.h
@@ -0,0 +1,25 @@
1/*
2
3crc32.h
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1992 Tatu Ylonen, Espoo, Finland
8 All rights reserved
9
10Created: Tue Feb 11 14:37:27 1992 ylo
11
12Functions for computing 32-bit CRC.
13
14*/
15
16/* RCSID("$Id: crc32.h,v 1.1 1999/10/27 03:42:44 damien Exp $"); */
17
18#ifndef CRC32_H
19#define CRC32_H
20
21/* This computes a 32 bit CRC of the data in the buffer, and returns the
22 CRC. The polynomial used is 0xedb88320. */
23unsigned int crc32(const unsigned char *buf, unsigned int len);
24
25#endif /* CRC32_H */
diff --git a/deattack.c b/deattack.c
new file mode 100644
index 000000000..d5f8608ca
--- /dev/null
+++ b/deattack.c
@@ -0,0 +1,180 @@
1/*
2 * $Id: deattack.c,v 1.1 1999/10/27 03:42:44 damien Exp $
3 * Cryptographic attack detector for ssh - source code
4 *
5 * Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina.
6 *
7 * All rights reserved. Redistribution and use in source and binary
8 * forms, with or without modification, are permitted provided that
9 * this copyright notice is retained.
10 *
11 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
12 * WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE
13 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR
14 * CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OR MISUSE OF THIS
15 * SOFTWARE.
16 *
17 * Ariel Futoransky <futo@core-sdi.com>
18 * <http://www.core-sdi.com> */
19
20#include "includes.h"
21#include "deattack.h"
22#include "ssh.h"
23#include "crc32.h"
24#include "getput.h"
25#include "xmalloc.h"
26
27/* SSH Constants */
28#define SSH_MAXBLOCKS (32 * 1024)
29#define SSH_BLOCKSIZE (8)
30
31/* Hashing constants */
32#define HASH_MINSIZE (8 * 1024)
33#define HASH_ENTRYSIZE (2)
34#define HASH_FACTOR(x) ((x)*3/2)
35#define HASH_UNUSEDCHAR (0xff)
36#define HASH_UNUSED (0xffff)
37#define HASH_IV (0xfffe)
38
39#define HASH_MINBLOCKS (7*SSH_BLOCKSIZE)
40
41
42/* Hash function (Input keys are cipher results) */
43#define HASH(x) GET_32BIT(x)
44
45#define CMP(a,b) (memcmp(a, b, SSH_BLOCKSIZE))
46
47
48void
49crc_update(u_int32_t * a, u_int32_t b)
50{
51 b ^= *a;
52 *a = crc32((unsigned char *) &b, sizeof(b));
53}
54
55/*
56 check_crc
57 detects if a block is used in a particular pattern
58 */
59
60int
61check_crc(unsigned char *S, unsigned char *buf, u_int32_t len, unsigned char *IV)
62{
63 u_int32_t crc;
64 unsigned char *c;
65
66 crc = 0;
67 if (IV && !CMP(S, IV))
68 {
69 crc_update(&crc, 1);
70 crc_update(&crc, 0);
71 }
72 for (c = buf; c < buf + len; c += SSH_BLOCKSIZE)
73 {
74 if (!CMP(S, c))
75 {
76 crc_update(&crc, 1);
77 crc_update(&crc, 0);
78 } else
79 {
80 crc_update(&crc, 0);
81 crc_update(&crc, 0);
82 }
83 }
84
85 return (crc == 0);
86}
87
88
89/*
90 detect_attack
91 Detects a crc32 compensation attack on a packet
92 */
93int
94detect_attack(unsigned char *buf, u_int32_t len, unsigned char *IV)
95{
96 static u_int16_t *h = (u_int16_t *) NULL;
97 static u_int16_t n = HASH_MINSIZE / HASH_ENTRYSIZE;
98 register u_int32_t i, j;
99 u_int32_t l;
100 register unsigned char *c;
101 unsigned char *d;
102
103
104 assert(len <= (SSH_MAXBLOCKS * SSH_BLOCKSIZE));
105 assert(len % SSH_BLOCKSIZE == 0);
106
107 for (l = n; l < HASH_FACTOR(len / SSH_BLOCKSIZE); l = l << 2);
108
109 if (h == NULL)
110 {
111 debug("Installing crc compensation attack detector.");
112 n = l;
113 h = (u_int16_t *) xmalloc(n * HASH_ENTRYSIZE);
114 } else
115 {
116 if (l > n)
117 {
118 n = l;
119 h = (u_int16_t *) xrealloc(h, n * HASH_ENTRYSIZE);
120 }
121 }
122
123
124 if (len <= HASH_MINBLOCKS)
125 {
126 for (c = buf; c < buf + len; c += SSH_BLOCKSIZE)
127 {
128 if (IV && (!CMP(c, IV)))
129 {
130 if ((check_crc(c, buf, len, IV)))
131 return (DEATTACK_DETECTED);
132 else
133 break;
134 }
135 for (d = buf; d < c; d += SSH_BLOCKSIZE)
136 {
137 if (!CMP(c, d))
138 {
139 if ((check_crc(c, buf, len, IV)))
140 return (DEATTACK_DETECTED);
141 else
142 break;
143 }
144 }
145 }
146 return (DEATTACK_OK);
147 }
148 memset(h, HASH_UNUSEDCHAR, n * HASH_ENTRYSIZE);
149
150 if (IV)
151 h[HASH(IV) & (n - 1)] = HASH_IV;
152
153
154 for (c = buf, j = 0; c < (buf + len); c += SSH_BLOCKSIZE, j++)
155 {
156 for (i = HASH(c) & (n - 1); h[i] != HASH_UNUSED;
157 i = (i + 1) & (n - 1))
158 {
159 if (h[i] == HASH_IV)
160 {
161 if (!CMP(c, IV))
162 {
163 if (check_crc(c, buf, len, IV))
164 return (DEATTACK_DETECTED);
165 else
166 break;
167 }
168 } else if (!CMP(c, buf + h[i] * SSH_BLOCKSIZE))
169 {
170 if (check_crc(c, buf, len, IV))
171 return (DEATTACK_DETECTED);
172 else
173 break;
174 }
175 }
176 h[i] = j;
177 }
178
179 return (DEATTACK_OK);
180}
diff --git a/deattack.h b/deattack.h
new file mode 100644
index 000000000..a0dcf5b6f
--- /dev/null
+++ b/deattack.h
@@ -0,0 +1,27 @@
1/* $Id: deattack.h,v 1.1 1999/10/27 03:42:44 damien Exp $
2 * Cryptographic attack detector for ssh - Header file
3 *
4 * Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina.
5 *
6 * All rights reserved. Redistribution and use in source and binary
7 * forms, with or without modification, are permitted provided that
8 * this copyright notice is retained.
9 *
10 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
11 * WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE
12 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR
13 * CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OR MISUSE OF THIS
14 * SOFTWARE.
15 *
16 * Ariel Futoransky <futo@core-sdi.com>
17 * <http://www.core-sdi.com> */
18
19#ifndef _DEATTACK_H
20#define _DEATTACK_H
21
22/* Return codes */
23#define DEATTACK_OK 0
24#define DEATTACK_DETECTED 1
25
26int detect_attack(unsigned char *buf, u_int32_t len, unsigned char IV[8]);
27#endif
diff --git a/getput.h b/getput.h
new file mode 100644
index 000000000..7b5d74252
--- /dev/null
+++ b/getput.h
@@ -0,0 +1,64 @@
1/*
2
3getput.h
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Wed Jun 28 22:36:30 1995 ylo
11
12Macros for storing and retrieving data in msb first and lsb first order.
13
14*/
15
16/* RCSID("$Id: getput.h,v 1.1 1999/10/27 03:42:44 damien Exp $"); */
17
18#ifndef GETPUT_H
19#define GETPUT_H
20
21/*------------ macros for storing/extracting msb first words -------------*/
22
23#define GET_32BIT(cp) (((unsigned long)(unsigned char)(cp)[0] << 24) | \
24 ((unsigned long)(unsigned char)(cp)[1] << 16) | \
25 ((unsigned long)(unsigned char)(cp)[2] << 8) | \
26 ((unsigned long)(unsigned char)(cp)[3]))
27
28#define GET_16BIT(cp) (((unsigned long)(unsigned char)(cp)[0] << 8) | \
29 ((unsigned long)(unsigned char)(cp)[1]))
30
31#define PUT_32BIT(cp, value) do { \
32 (cp)[0] = (value) >> 24; \
33 (cp)[1] = (value) >> 16; \
34 (cp)[2] = (value) >> 8; \
35 (cp)[3] = (value); } while (0)
36
37#define PUT_16BIT(cp, value) do { \
38 (cp)[0] = (value) >> 8; \
39 (cp)[1] = (value); } while (0)
40
41/*------------ macros for storing/extracting lsb first words -------------*/
42
43#define GET_32BIT_LSB_FIRST(cp) \
44 (((unsigned long)(unsigned char)(cp)[0]) | \
45 ((unsigned long)(unsigned char)(cp)[1] << 8) | \
46 ((unsigned long)(unsigned char)(cp)[2] << 16) | \
47 ((unsigned long)(unsigned char)(cp)[3] << 24))
48
49#define GET_16BIT_LSB_FIRST(cp) \
50 (((unsigned long)(unsigned char)(cp)[0]) | \
51 ((unsigned long)(unsigned char)(cp)[1] << 8))
52
53#define PUT_32BIT_LSB_FIRST(cp, value) do { \
54 (cp)[0] = (value); \
55 (cp)[1] = (value) >> 8; \
56 (cp)[2] = (value) >> 16; \
57 (cp)[3] = (value) >> 24; } while (0)
58
59#define PUT_16BIT_LSB_FIRST(cp, value) do { \
60 (cp)[0] = (value); \
61 (cp)[1] = (value) >> 8; } while (0)
62
63#endif /* GETPUT_H */
64
diff --git a/helper.c b/helper.c
new file mode 100644
index 000000000..3b0402ecf
--- /dev/null
+++ b/helper.c
@@ -0,0 +1,108 @@
1/*
2**
3** OpenBSD emulation routines
4**
5** Damien Miller <djm@ibs.com.au>
6**
7** Copyright 1999 Internet Business Solutions
8**
9** Permission is hereby granted, free of charge, to any person
10** obtaining a copy of this software and associated documentation
11** files (the "Software"), to deal in the Software without
12** restriction, including without limitation the rights to use, copy,
13** modify, merge, publish, distribute, sublicense, and/or sell copies
14** of the Software, and to permit persons to whom the Software is
15** furnished to do so, subject to the following conditions:
16**
17** The above copyright notice and this permission notice shall be
18** included in all copies or substantial portions of the Software.
19**
20** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
21** KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
22** WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
23** AND NONINFRINGEMENT. IN NO EVENT SHALL DAMIEN MILLER OR INTERNET
24** BUSINESS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
27** OR OTHER DEALINGS IN THE SOFTWARE.
28**
29** Except as contained in this notice, the name of Internet Business
30** Solutions shall not be used in advertising or otherwise to promote
31** the sale, use or other dealings in this Software without prior
32** written authorization from Internet Business Solutions.
33**
34*/
35
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <errno.h>
40#include <unistd.h>
41
42#include <sys/types.h>
43#include <sys/stat.h>
44#include <fcntl.h>
45
46#include "rc4.h"
47#include "xmalloc.h"
48
49#include "helper.h"
50
51void get_random_bytes(unsigned char *buf, int len);
52
53static rc4_t *rc4 = NULL;
54
55void setproctitle(const char *fmt, ...)
56{
57 /* FIXME */
58}
59
60unsigned char arc4random(void)
61{
62 unsigned char r;
63
64 if (rc4 == NULL)
65 arc4random_stir();
66
67 rc4_getbytes(rc4, &r, 1);
68
69 return(r);
70}
71
72void arc4random_stir(void)
73{
74 unsigned char rand_buf[32];
75
76 if (rc4 == NULL)
77 rc4 = xmalloc(sizeof(*rc4));
78
79 get_random_bytes(rand_buf, sizeof(rand_buf));
80 rc4_key(rc4, rand_buf, sizeof(rand_buf));
81}
82
83void get_random_bytes(unsigned char *buf, int len)
84{
85 int urandom;
86 int c;
87
88 urandom = open("/dev/urandom", O_RDONLY);
89 if (urandom == -1)
90 {
91 fprintf(stderr, "Couldn't open /dev/urandom: %s", strerror(errno));
92 exit(1);
93 }
94
95 c = read(urandom, buf, len);
96 if (c == -1)
97 {
98 fprintf(stderr, "Couldn't read from /dev/urandom: %s", strerror(errno));
99 exit(1);
100 }
101
102 if (c != len)
103 {
104 fprintf(stderr, "Short read from /dev/urandom");
105 exit(1);
106 }
107}
108
diff --git a/helper.h b/helper.h
new file mode 100644
index 000000000..2f09daa8e
--- /dev/null
+++ b/helper.h
@@ -0,0 +1,43 @@
1/*
2**
3** OpenBSD emulation routines
4**
5** Damien Miller <djm@ibs.com.au>
6**
7** Copyright 1999 Internet Business Solutions
8**
9** Permission is hereby granted, free of charge, to any person
10** obtaining a copy of this software and associated documentation
11** files (the "Software"), to deal in the Software without
12** restriction, including without limitation the rights to use, copy,
13** modify, merge, publish, distribute, sublicense, and/or sell copies
14** of the Software, and to permit persons to whom the Software is
15** furnished to do so, subject to the following conditions:
16**
17** The above copyright notice and this permission notice shall be
18** included in all copies or substantial portions of the Software.
19**
20** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
21** KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
22** WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
23** AND NONINFRINGEMENT. IN NO EVENT SHALL DAMIEN MILLER OR INTERNET
24** BUSINESS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
27** OR OTHER DEALINGS IN THE SOFTWARE.
28**
29** Except as contained in this notice, the name of Internet Business
30** Solutions shall not be used in advertising or otherwise to promote
31** the sale, use or other dealings in this Software without prior
32** written authorization from Internet Business Solutions.
33**
34*/
35
36#ifndef _HELPER_H
37#define _HELPER_H
38
39unsigned char arc4random(void);
40void arc4random_stir(void);
41void setproctitle(const char *fmt, ...);
42
43#endif /* _HELPER_H */
diff --git a/hostfile.c b/hostfile.c
new file mode 100644
index 000000000..ca0fe88a2
--- /dev/null
+++ b/hostfile.c
@@ -0,0 +1,279 @@
1/*
2
3hostfile.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Thu Jun 29 07:10:56 1995 ylo
11
12Functions for manipulating the known hosts files.
13
14*/
15
16#include "includes.h"
17RCSID("$Id: hostfile.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
18
19#include "packet.h"
20#include "ssh.h"
21
22/* Reads a multiple-precision integer in hex from the buffer, and advances the
23 pointer. The integer must already be initialized. This function is
24 permitted to modify the buffer. This leaves *cpp to point just beyond
25 the last processed (and maybe modified) character. Note that this may
26 modify the buffer containing the number. */
27
28int
29auth_rsa_read_bignum(char **cpp, BIGNUM *value)
30{
31 char *cp = *cpp;
32 int len, old;
33
34 /* Skip any leading whitespace. */
35 for (; *cp == ' ' || *cp == '\t'; cp++)
36 ;
37
38 /* Check that it begins with a hex digit. */
39 if (*cp < '0' || *cp > '9')
40 return 0;
41
42 /* Save starting position. */
43 *cpp = cp;
44
45 /* Move forward until all hex digits skipped. */
46 for (; *cp >= '0' && *cp <= '9'; cp++)
47 ;
48
49 /* Compute the length of the hex number. */
50 len = cp - *cpp;
51
52 /* Save the old terminating character, and replace it by \0. */
53 old = *cp;
54 *cp = 0;
55
56
57 /* Parse the number. */
58 if (BN_dec2bn(&value, *cpp) == 0)
59 return 0;
60
61 /* Restore old terminating character. */
62 *cp = old;
63
64 /* Move beyond the number and return success. */
65 *cpp = cp;
66 return 1;
67}
68
69/* Parses an RSA key (number of bits, e, n) from a string. Moves the pointer
70 over the key. Skips any whitespace at the beginning and at end. */
71
72int
73auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM *e, BIGNUM *n)
74{
75 unsigned int bits;
76 char *cp;
77
78 /* Skip leading whitespace. */
79 for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
80 ;
81
82 /* Get number of bits. */
83 if (*cp < '0' || *cp > '9')
84 return 0; /* Bad bit count... */
85 for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
86 bits = 10 * bits + *cp - '0';
87
88 /* Get public exponent. */
89 if (!auth_rsa_read_bignum(&cp, e))
90 return 0;
91
92 /* Get public modulus. */
93 if (!auth_rsa_read_bignum(&cp, n))
94 return 0;
95
96 /* Skip trailing whitespace. */
97 for (; *cp == ' ' || *cp == '\t'; cp++)
98 ;
99
100 /* Return results. */
101 *cpp = cp;
102 *bitsp = bits;
103 return 1;
104}
105
106/* Tries to match the host name (which must be in all lowercase) against the
107 comma-separated sequence of subpatterns (each possibly preceded by ! to
108 indicate negation). Returns true if there is a positive match; zero
109 otherwise. */
110
111int
112match_hostname(const char *host, const char *pattern, unsigned int len)
113{
114 char sub[1024];
115 int negated;
116 int got_positive;
117 unsigned int i, subi;
118
119 got_positive = 0;
120 for (i = 0; i < len;)
121 {
122 /* Check if the subpattern is negated. */
123 if (pattern[i] == '!')
124 {
125 negated = 1;
126 i++;
127 }
128 else
129 negated = 0;
130
131 /* Extract the subpattern up to a comma or end. Convert the subpattern
132 to lowercase. */
133 for (subi = 0;
134 i < len && subi < sizeof(sub) - 1 && pattern[i] != ',';
135 subi++, i++)
136 sub[subi] = isupper(pattern[i]) ? tolower(pattern[i]) : pattern[i];
137 /* If subpattern too long, return failure (no match). */
138 if (subi >= sizeof(sub) - 1)
139 return 0;
140
141 /* If the subpattern was terminated by a comma, skip the comma. */
142 if (i < len && pattern[i] == ',')
143 i++;
144
145 /* Null-terminate the subpattern. */
146 sub[subi] = '\0';
147
148 /* Try to match the subpattern against the host name. */
149 if (match_pattern(host, sub)) {
150 if (negated)
151 return 0; /* Fail if host matches any negated subpattern. */
152 else
153 got_positive = 1;
154 }
155 }
156
157 /* Return success if got a positive match. If there was a negative match,
158 we have already returned zero and never get here. */
159 return got_positive;
160}
161
162/* Checks whether the given host (which must be in all lowercase) is
163 already in the list of our known hosts.
164 Returns HOST_OK if the host is known and has the specified key,
165 HOST_NEW if the host is not known, and HOST_CHANGED if the host is known
166 but used to have a different host key. */
167
168HostStatus
169check_host_in_hostfile(const char *filename,
170 const char *host, unsigned int bits,
171 BIGNUM *e, BIGNUM *n,
172 BIGNUM *ke, BIGNUM *kn)
173{
174 FILE *f;
175 char line[8192];
176 unsigned int kbits, hostlen;
177 char *cp, *cp2;
178 HostStatus end_return;
179 struct stat st;
180
181 /* Open the file containing the list of known hosts. */
182 f = fopen(filename, "r");
183 if (!f)
184 {
185 if (stat(filename, &st) >= 0)
186 {
187 packet_send_debug("Could not open %.900s for reading.", filename);
188 packet_send_debug("If your home directory is on an NFS volume, it may need to be world-readable.");
189 }
190 return HOST_NEW;
191 }
192
193 /* Cache the length of the host name. */
194 hostlen = strlen(host);
195
196 /* Return value when the loop terminates. This is set to HOST_CHANGED if
197 we have seen a different key for the host and have not found the proper
198 one. */
199 end_return = HOST_NEW;
200
201 /* Go trough the file. */
202 while (fgets(line, sizeof(line), f))
203 {
204 cp = line;
205
206 /* Skip any leading whitespace. */
207 for (; *cp == ' ' || *cp == '\t'; cp++)
208 ;
209
210 /* Ignore comment lines and empty lines. */
211 if (!*cp || *cp == '#' || *cp == '\n')
212 continue;
213
214 /* Find the end of the host name portion. */
215 for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++)
216 ;
217
218 /* Check if the host name matches. */
219 if (!match_hostname(host, cp, (unsigned int)(cp2 - cp)))
220 continue;
221
222 /* Got a match. Skip host name. */
223 cp = cp2;
224
225 /* Extract the key from the line. This will skip any leading
226 whitespace. Ignore badly formatted lines. */
227 if (!auth_rsa_read_key(&cp, &kbits, ke, kn))
228 continue;
229
230 /* Check if the current key is the same as the previous one. */
231 if (kbits == bits && BN_cmp(ke, e) == 0 && BN_cmp(kn, n) == 0)
232 {
233 /* Ok, they match. */
234 fclose(f);
235 return HOST_OK;
236 }
237
238 /* They do not match. We will continue to go through the file; however,
239 we note that we will not return that it is new. */
240 end_return = HOST_CHANGED;
241 }
242 /* Clear variables and close the file. */
243 fclose(f);
244
245 /* Return either HOST_NEW or HOST_CHANGED, depending on whether we saw a
246 different key for the host. */
247 return end_return;
248}
249
250/* Appends an entry to the host file. Returns false if the entry
251 could not be appended. */
252
253int
254add_host_to_hostfile(const char *filename, const char *host,
255 unsigned int bits, BIGNUM *e, BIGNUM *n)
256{
257 FILE *f;
258 char *buf;
259
260 /* Open the file for appending. */
261 f = fopen(filename, "a");
262 if (!f)
263 return 0;
264
265 /* Print the host name and key to the file. */
266 fprintf(f, "%s %u ", host, bits);
267 buf = BN_bn2dec(e);
268 assert(buf != NULL);
269 fprintf(f, "%s ", buf);
270 free (buf);
271 buf = BN_bn2dec(n);
272 assert(buf != NULL);
273 fprintf(f, "%s\n", buf);
274 free (buf);
275
276 /* Close the file. */
277 fclose(f);
278 return 1;
279}
diff --git a/includes.h b/includes.h
new file mode 100644
index 000000000..862dbd64f
--- /dev/null
+++ b/includes.h
@@ -0,0 +1,78 @@
1/*
2
3includes.h
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Thu Mar 23 16:29:37 1995 ylo
11
12This file includes most of the needed system headers.
13
14*/
15
16#ifndef INCLUDES_H
17#define INCLUDES_H
18
19#define RCSID(msg) \
20static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
21
22#include <sys/types.h>
23#include <sys/socket.h>
24#include <sys/select.h>
25#include <sys/param.h>
26#include <sys/ioctl.h>
27#include <sys/stat.h>
28#include <sys/wait.h>
29#include <sys/time.h>
30#include <sys/un.h>
31#include <sys/resource.h>
32
33#include <netinet/in.h>
34#include <netinet/in_systm.h>
35#include <netinet/tcp.h>
36#include <netinet/ip.h>
37#include <arpa/inet.h>
38#include <netdb.h>
39
40#include <endian.h>
41#include <stdio.h>
42#include <ctype.h>
43#include <errno.h>
44#include <fcntl.h>
45#include <assert.h>
46#include <signal.h>
47#include <termios.h>
48#include <stdlib.h>
49#include <string.h>
50#include <stdarg.h>
51#include <pwd.h>
52#include <grp.h>
53#include <unistd.h>
54#include <time.h>
55#include <paths.h>
56#include <dirent.h>
57
58#include "version.h"
59
60#include "helper.h"
61#include "mktemp.h"
62#include "strlcpy.h"
63
64/* Define this to be the path of the xauth program. */
65#ifndef XAUTH_PATH
66#define XAUTH_PATH "/usr/X11R6/bin/xauth"
67#endif /* XAUTH_PATH */
68
69/* Define this to be the path of the rsh program. */
70#ifndef _PATH_RSH
71#define _PATH_RSH "/usr/bin/rsh"
72#endif /* _PATH_RSH */
73
74/* Define this to use pipes instead of socketpairs for communicating with the
75 client program. Socketpairs do not seem to work on all systems. */
76#define USE_PIPES 1
77
78#endif /* INCLUDES_H */
diff --git a/log-client.c b/log-client.c
new file mode 100644
index 000000000..1792ba847
--- /dev/null
+++ b/log-client.c
@@ -0,0 +1,138 @@
1/*
2
3log-client.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Mon Mar 20 21:13:40 1995 ylo
11
12Client-side versions of debug(), log(), etc. These print to stderr.
13
14*/
15
16#include "includes.h"
17RCSID("$Id: log-client.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
18
19#include "xmalloc.h"
20#include "ssh.h"
21
22static int log_debug = 0;
23static int log_quiet = 0;
24
25void log_init(char *av0, int on_stderr, int debug, int quiet,
26 SyslogFacility facility)
27{
28 log_debug = debug;
29 log_quiet = quiet;
30}
31
32void log(const char *fmt, ...)
33{
34 va_list args;
35
36 if (log_quiet)
37 return;
38 va_start(args, fmt);
39 vfprintf(stderr, fmt, args);
40 fprintf(stderr, "\r\n");
41 va_end(args);
42}
43
44void debug(const char *fmt, ...)
45{
46 va_list args;
47 if (log_quiet || !log_debug)
48 return;
49 va_start(args, fmt);
50 fprintf(stderr, "debug: ");
51 vfprintf(stderr, fmt, args);
52 fprintf(stderr, "\r\n");
53 va_end(args);
54}
55
56void error(const char *fmt, ...)
57{
58 va_list args;
59 if (log_quiet)
60 return;
61 va_start(args, fmt);
62 vfprintf(stderr, fmt, args);
63 fprintf(stderr, "\r\n");
64 va_end(args);
65}
66
67struct fatal_cleanup
68{
69 struct fatal_cleanup *next;
70 void (*proc)(void *);
71 void *context;
72};
73
74static struct fatal_cleanup *fatal_cleanups = NULL;
75
76/* Registers a cleanup function to be called by fatal() before exiting. */
77
78void fatal_add_cleanup(void (*proc)(void *), void *context)
79{
80 struct fatal_cleanup *cu;
81
82 cu = xmalloc(sizeof(*cu));
83 cu->proc = proc;
84 cu->context = context;
85 cu->next = fatal_cleanups;
86 fatal_cleanups = cu;
87}
88
89/* Removes a cleanup frunction to be called at fatal(). */
90
91void fatal_remove_cleanup(void (*proc)(void *context), void *context)
92{
93 struct fatal_cleanup **cup, *cu;
94
95 for (cup = &fatal_cleanups; *cup; cup = &cu->next)
96 {
97 cu = *cup;
98 if (cu->proc == proc && cu->context == context)
99 {
100 *cup = cu->next;
101 xfree(cu);
102 return;
103 }
104 }
105 fatal("fatal_remove_cleanup: no such cleanup function: 0x%lx 0x%lx\n",
106 (unsigned long)proc, (unsigned long)context);
107}
108
109/* Function to display an error message and exit. This is in this file because
110 this needs to restore terminal modes before exiting. See log-client.c
111 for other related functions. */
112
113void fatal(const char *fmt, ...)
114{
115 va_list args;
116 struct fatal_cleanup *cu, *next_cu;
117 static int fatal_called = 0;
118
119 if (!fatal_called)
120 {
121 fatal_called = 1;
122
123 /* Call cleanup functions. */
124 for (cu = fatal_cleanups; cu; cu = next_cu)
125 {
126 next_cu = cu->next;
127 (*cu->proc)(cu->context);
128 }
129 }
130
131 va_start(args, fmt);
132 vfprintf(stderr, fmt, args);
133 fprintf(stderr, "\r\n");
134 va_end(args);
135 exit(255);
136}
137
138/* fatal() is in ssh.c so that it can properly reset terminal modes. */
diff --git a/log-server.c b/log-server.c
new file mode 100644
index 000000000..fce96b01d
--- /dev/null
+++ b/log-server.c
@@ -0,0 +1,233 @@
1/*
2
3log-server.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Mon Mar 20 21:19:30 1995 ylo
11
12Server-side versions of debug(), log(), etc. These normally send the output
13to the system log.
14
15*/
16
17#include "includes.h"
18RCSID("$Id: log-server.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
19
20#include <syslog.h>
21#include "packet.h"
22#include "xmalloc.h"
23#include "ssh.h"
24
25static int log_debug = 0;
26static int log_quiet = 0;
27static int log_on_stderr = 0;
28
29/* Initialize the log.
30 av0 program name (should be argv[0])
31 on_stderr print also on stderr
32 debug send debugging messages to system log
33 quiet don\'t log anything
34 */
35
36void log_init(char *av0, int on_stderr, int debug, int quiet,
37 SyslogFacility facility)
38{
39 int log_facility;
40
41 switch (facility)
42 {
43 case SYSLOG_FACILITY_DAEMON:
44 log_facility = LOG_DAEMON;
45 break;
46 case SYSLOG_FACILITY_USER:
47 log_facility = LOG_USER;
48 break;
49 case SYSLOG_FACILITY_AUTH:
50 log_facility = LOG_AUTH;
51 break;
52 case SYSLOG_FACILITY_LOCAL0:
53 log_facility = LOG_LOCAL0;
54 break;
55 case SYSLOG_FACILITY_LOCAL1:
56 log_facility = LOG_LOCAL1;
57 break;
58 case SYSLOG_FACILITY_LOCAL2:
59 log_facility = LOG_LOCAL2;
60 break;
61 case SYSLOG_FACILITY_LOCAL3:
62 log_facility = LOG_LOCAL3;
63 break;
64 case SYSLOG_FACILITY_LOCAL4:
65 log_facility = LOG_LOCAL4;
66 break;
67 case SYSLOG_FACILITY_LOCAL5:
68 log_facility = LOG_LOCAL5;
69 break;
70 case SYSLOG_FACILITY_LOCAL6:
71 log_facility = LOG_LOCAL6;
72 break;
73 case SYSLOG_FACILITY_LOCAL7:
74 log_facility = LOG_LOCAL7;
75 break;
76 default:
77 fprintf(stderr, "Unrecognized internal syslog facility code %d\n",
78 (int)facility);
79 exit(1);
80 }
81
82 log_debug = debug;
83 log_quiet = quiet;
84 log_on_stderr = on_stderr;
85 closelog(); /* Close any previous log. */
86 openlog(av0, LOG_PID, log_facility);
87}
88
89#define MSGBUFSIZE 1024
90
91#define DECL_MSGBUF char msgbuf[MSGBUFSIZE]
92
93/* Log this message (information that usually should go to the log). */
94
95void log(const char *fmt, ...)
96{
97 va_list args;
98 DECL_MSGBUF;
99 if (log_quiet)
100 return;
101 va_start(args, fmt);
102 vsnprintf(msgbuf, MSGBUFSIZE, fmt, args);
103 va_end(args);
104 if (log_on_stderr)
105 fprintf(stderr, "log: %s\n", msgbuf);
106 syslog(LOG_INFO, "log: %.500s", msgbuf);
107}
108
109/* Debugging messages that should not be logged during normal operation. */
110
111void debug(const char *fmt, ...)
112{
113 va_list args;
114 DECL_MSGBUF;
115 if (!log_debug || log_quiet)
116 return;
117 va_start(args, fmt);
118 vsnprintf(msgbuf, MSGBUFSIZE, fmt, args);
119 va_end(args);
120 if (log_on_stderr)
121 fprintf(stderr, "debug: %s\n", msgbuf);
122 syslog(LOG_DEBUG, "debug: %.500s", msgbuf);
123}
124
125/* Error messages that should be logged. */
126
127void error(const char *fmt, ...)
128{
129 va_list args;
130 DECL_MSGBUF;
131 if (log_quiet)
132 return;
133 va_start(args, fmt);
134 vsnprintf(msgbuf, MSGBUFSIZE, fmt, args);
135 va_end(args);
136 if (log_on_stderr)
137 fprintf(stderr, "error: %s\n", msgbuf);
138 syslog(LOG_ERR, "error: %.500s", msgbuf);
139}
140
141struct fatal_cleanup
142{
143 struct fatal_cleanup *next;
144 void (*proc)(void *);
145 void *context;
146};
147
148static struct fatal_cleanup *fatal_cleanups = NULL;
149
150/* Registers a cleanup function to be called by fatal() before exiting. */
151
152void fatal_add_cleanup(void (*proc)(void *), void *context)
153{
154 struct fatal_cleanup *cu;
155
156 cu = xmalloc(sizeof(*cu));
157 cu->proc = proc;
158 cu->context = context;
159 cu->next = fatal_cleanups;
160 fatal_cleanups = cu;
161}
162
163/* Removes a cleanup frunction to be called at fatal(). */
164
165void fatal_remove_cleanup(void (*proc)(void *context), void *context)
166{
167 struct fatal_cleanup **cup, *cu;
168
169 for (cup = &fatal_cleanups; *cup; cup = &cu->next)
170 {
171 cu = *cup;
172 if (cu->proc == proc && cu->context == context)
173 {
174 *cup = cu->next;
175 xfree(cu);
176 return;
177 }
178 }
179 fatal("fatal_remove_cleanup: no such cleanup function: 0x%lx 0x%lx\n",
180 (unsigned long)proc, (unsigned long)context);
181}
182
183/* Fatal messages. This function never returns. */
184
185void fatal(const char *fmt, ...)
186{
187 va_list args;
188 struct fatal_cleanup *cu, *next_cu;
189 static int fatal_called = 0;
190#if defined(KRB4)
191 extern char *ticket;
192#endif /* KRB4 */
193 DECL_MSGBUF;
194
195 if (log_quiet)
196 exit(1);
197 va_start(args, fmt);
198 vsnprintf(msgbuf, MSGBUFSIZE, fmt, args);
199 va_end(args);
200 if (log_on_stderr)
201 fprintf(stderr, "fatal: %s\n", msgbuf);
202 syslog(LOG_ERR, "fatal: %.500s", msgbuf);
203
204 if (fatal_called)
205 exit(1);
206 fatal_called = 1;
207
208 /* Call cleanup functions. */
209 for (cu = fatal_cleanups; cu; cu = next_cu)
210 {
211 next_cu = cu->next;
212 debug("Calling cleanup 0x%lx(0x%lx)",
213 (unsigned long)cu->proc, (unsigned long)cu->context);
214 (*cu->proc)(cu->context);
215 }
216#if defined(KRB4)
217 /* If you forwarded a ticket you get one shot for proper
218 authentication. */
219 /* If tgt was passed unlink file */
220 if (ticket)
221 {
222 if (strcmp(ticket,"none"))
223 unlink(ticket);
224 else
225 ticket = NULL;
226 }
227#endif /* KRB4 */
228
229 /* If local XAUTHORITY was created, remove it. */
230 if (xauthfile) unlink(xauthfile);
231
232 exit(1);
233}
diff --git a/login.c b/login.c
new file mode 100644
index 000000000..0c1e61b77
--- /dev/null
+++ b/login.c
@@ -0,0 +1,118 @@
1/*
2
3login.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Fri Mar 24 14:51:08 1995 ylo
11
12This file performs some of the things login(1) normally does. We cannot
13easily use something like login -p -h host -f user, because there are
14several different logins around, and it is hard to determined what kind of
15login the current system has. Also, we want to be able to execute commands
16on a tty.
17
18*/
19
20#include "includes.h"
21RCSID("$Id: login.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
22
23#include <utmp.h>
24#include "ssh.h"
25
26/* Returns the time when the user last logged in. Returns 0 if the
27 information is not available. This must be called before record_login.
28 The host the user logged in from will be returned in buf. */
29
30/* Returns the time when the user last logged in (or 0 if no previous login
31 is found). The name of the host used last time is returned in buf. */
32
33unsigned long get_last_login_time(uid_t uid, const char *logname,
34 char *buf, unsigned int bufsize)
35{
36 struct lastlog ll;
37 char *lastlog;
38 int fd;
39
40 lastlog = _PATH_LASTLOG;
41
42 buf[0] = '\0';
43
44 fd = open(lastlog, O_RDONLY);
45 if (fd < 0)
46 return 0;
47 lseek(fd, (off_t)((long)uid * sizeof(ll)), SEEK_SET);
48 if (read(fd, &ll, sizeof(ll)) != sizeof(ll))
49 {
50 close(fd);
51 return 0;
52 }
53 close(fd);
54 if (bufsize > sizeof(ll.ll_host) + 1)
55 bufsize = sizeof(ll.ll_host) + 1;
56 strncpy(buf, ll.ll_host, bufsize - 1);
57 buf[bufsize - 1] = 0;
58 return ll.ll_time;
59}
60
61/* Records that the user has logged in. I these parts of operating systems
62 were more standardized. */
63
64void record_login(int pid, const char *ttyname, const char *user, uid_t uid,
65 const char *host, struct sockaddr_in *addr)
66{
67 int fd;
68 struct lastlog ll;
69 char *lastlog;
70
71 struct utmp u;
72 const char *utmp, *wtmp;
73
74 /* Construct an utmp/wtmp entry. */
75 memset(&u, 0, sizeof(u));
76 strncpy(u.ut_line, ttyname + 5, sizeof(u.ut_line));
77 u.ut_time = time(NULL);
78 strncpy(u.ut_name, user, sizeof(u.ut_name));
79 strncpy(u.ut_host, host, sizeof(u.ut_host));
80
81 /* Figure out the file names. */
82 utmp = _PATH_UTMP;
83 wtmp = _PATH_WTMP;
84
85 login(&u);
86
87 lastlog = _PATH_LASTLOG;
88
89 /* Update lastlog unless actually recording a logout. */
90 if (strcmp(user, "") != 0)
91 {
92 /* It is safer to bzero the lastlog structure first because some
93 systems might have some extra fields in it (e.g. SGI) */
94 memset(&ll, 0, sizeof(ll));
95
96 /* Update lastlog. */
97 ll.ll_time = time(NULL);
98 strncpy(ll.ll_line, ttyname + 5, sizeof(ll.ll_line));
99 strncpy(ll.ll_host, host, sizeof(ll.ll_host));
100 fd = open(lastlog, O_RDWR);
101 if (fd >= 0)
102 {
103 lseek(fd, (off_t)((long)uid * sizeof(ll)), SEEK_SET);
104 if (write(fd, &ll, sizeof(ll)) != sizeof(ll))
105 log("Could not write %.100s: %.100s", lastlog, strerror(errno));
106 close(fd);
107 }
108 }
109}
110
111/* Records that the user has logged out. */
112
113void record_logout(int pid, const char *ttyname)
114{
115 const char *line = ttyname + 5; /* /dev/ttyq8 -> ttyq8 */
116 if (logout(line))
117 logwtmp(line, "", "");
118}
diff --git a/match.c b/match.c
new file mode 100644
index 000000000..b7a7d3389
--- /dev/null
+++ b/match.c
@@ -0,0 +1,78 @@
1/*
2
3match.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Thu Jun 22 01:17:50 1995 ylo
11
12Simple pattern matching, with '*' and '?' as wildcards.
13
14*/
15
16#include "includes.h"
17RCSID("$Id: match.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
18
19#include "ssh.h"
20
21/* Returns true if the given string matches the pattern (which may contain
22 ? and * as wildcards), and zero if it does not match. */
23
24int match_pattern(const char *s, const char *pattern)
25{
26 while (1)
27 {
28 /* If at end of pattern, accept if also at end of string. */
29 if (!*pattern)
30 return !*s;
31
32 /* Process '*'. */
33 if (*pattern == '*')
34 {
35 /* Skip the asterisk. */
36 pattern++;
37
38 /* If at end of pattern, accept immediately. */
39 if (!*pattern)
40 return 1;
41
42 /* If next character in pattern is known, optimize. */
43 if (*pattern != '?' && *pattern != '*')
44 {
45 /* Look instances of the next character in pattern, and try
46 to match starting from those. */
47 for (; *s; s++)
48 if (*s == *pattern &&
49 match_pattern(s + 1, pattern + 1))
50 return 1;
51 /* Failed. */
52 return 0;
53 }
54
55 /* Move ahead one character at a time and try to match at each
56 position. */
57 for (; *s; s++)
58 if (match_pattern(s, pattern))
59 return 1;
60 /* Failed. */
61 return 0;
62 }
63
64 /* There must be at least one more character in the string. If we are
65 at the end, fail. */
66 if (!*s)
67 return 0;
68
69 /* Check if the next character of the string is acceptable. */
70 if (*pattern != '?' && *pattern != *s)
71 return 0;
72
73 /* Move to the next character, both in string and in pattern. */
74 s++;
75 pattern++;
76 }
77 /*NOTREACHED*/
78}
diff --git a/mktemp.c b/mktemp.c
new file mode 100644
index 000000000..919c53178
--- /dev/null
+++ b/mktemp.c
@@ -0,0 +1,181 @@
1/* THIS FILE HAS BEEN MODIFIED FROM THE ORIGINAL OPENBSD SOURCE */
2/* Changes: Removed mktemp */
3
4/*
5 * Copyright (c) 1987, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#if defined(LIBC_SCCS) && !defined(lint)
38static char rcsid[] = "$OpenBSD: mktemp.c,v 1.13 1998/06/30 23:03:13 deraadt Exp $";
39#endif /* LIBC_SCCS and not lint */
40
41#include <sys/types.h>
42#include <sys/stat.h>
43#include <fcntl.h>
44#include <errno.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <ctype.h>
48#include <unistd.h>
49
50static int _gettemp __P((char *, int *, int, int));
51
52int
53mkstemps(path, slen)
54 char *path;
55 int slen;
56{
57 int fd;
58
59 return (_gettemp(path, &fd, 0, slen) ? fd : -1);
60}
61
62int
63mkstemp(path)
64 char *path;
65{
66 int fd;
67
68 return (_gettemp(path, &fd, 0, 0) ? fd : -1);
69}
70
71char *
72mkdtemp(path)
73 char *path;
74{
75 return(_gettemp(path, (int *)NULL, 1, 0) ? path : (char *)NULL);
76}
77
78static int
79_gettemp(path, doopen, domkdir, slen)
80 char *path;
81 register int *doopen;
82 int domkdir;
83 int slen;
84{
85 register char *start, *trv, *suffp;
86 struct stat sbuf;
87 int pid, rval;
88
89 if (doopen && domkdir) {
90 errno = EINVAL;
91 return(0);
92 }
93
94 for (trv = path; *trv; ++trv)
95 ;
96 trv -= slen;
97 suffp = trv;
98 --trv;
99 if (trv < path) {
100 errno = EINVAL;
101 return (0);
102 }
103 pid = getpid();
104 while (*trv == 'X' && pid != 0) {
105 *trv-- = (pid % 10) + '0';
106 pid /= 10;
107 }
108 while (*trv == 'X') {
109 char c;
110
111 pid = (arc4random() & 0xffff) % (26+26);
112 if (pid < 26)
113 c = pid + 'A';
114 else
115 c = (pid - 26) + 'a';
116 *trv-- = c;
117 }
118 start = trv + 1;
119
120 /*
121 * check the target directory; if you have six X's and it
122 * doesn't exist this runs for a *very* long time.
123 */
124 if (doopen || domkdir) {
125 for (;; --trv) {
126 if (trv <= path)
127 break;
128 if (*trv == '/') {
129 *trv = '\0';
130 rval = stat(path, &sbuf);
131 *trv = '/';
132 if (rval != 0)
133 return(0);
134 if (!S_ISDIR(sbuf.st_mode)) {
135 errno = ENOTDIR;
136 return(0);
137 }
138 break;
139 }
140 }
141 }
142
143 for (;;) {
144 if (doopen) {
145 if ((*doopen =
146 open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
147 return(1);
148 if (errno != EEXIST)
149 return(0);
150 } else if (domkdir) {
151 if (mkdir(path, 0700) == 0)
152 return(1);
153 if (errno != EEXIST)
154 return(0);
155 } else if (lstat(path, &sbuf))
156 return(errno == ENOENT ? 1 : 0);
157
158 /* tricky little algorithm for backward compatibility */
159 for (trv = start;;) {
160 if (!*trv)
161 return (0);
162 if (*trv == 'Z') {
163 if (trv == suffp)
164 return (0);
165 *trv++ = 'a';
166 } else {
167 if (isdigit(*trv))
168 *trv = 'a';
169 else if (*trv == 'z') /* inc from z to A */
170 *trv = 'A';
171 else {
172 if (trv == suffp)
173 return (0);
174 ++*trv;
175 }
176 break;
177 }
178 }
179 }
180 /*NOTREACHED*/
181}
diff --git a/mktemp.h b/mktemp.h
new file mode 100644
index 000000000..5d380058e
--- /dev/null
+++ b/mktemp.h
@@ -0,0 +1,7 @@
1#ifndef _MKTEMP_H
2#define _MKTEMP_H
3int mkstemps(char *path, int slen);
4int mkstemp(char *path);
5char *mkdtemp(char *path);
6
7#endif /* _MKTEMP_H */
diff --git a/mpaux.c b/mpaux.c
new file mode 100644
index 000000000..fd2c18031
--- /dev/null
+++ b/mpaux.c
@@ -0,0 +1,46 @@
1/*
2
3mpaux.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Sun Jul 16 04:29:30 1995 ylo
11
12This file contains various auxiliary functions related to multiple
13precision integers.
14
15*/
16
17#include "includes.h"
18RCSID("$Id: mpaux.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
19
20#include <openssl/bn.h>
21#include "getput.h"
22#include "xmalloc.h"
23
24#include <openssl/md5.h>
25
26void
27compute_session_id(unsigned char session_id[16],
28 unsigned char cookie[8],
29 unsigned int host_key_bits,
30 BIGNUM *host_key_n,
31 unsigned int session_key_bits,
32 BIGNUM *session_key_n)
33{
34 unsigned int bytes = (host_key_bits + 7) / 8 + (session_key_bits + 7) / 8 + 8;
35 unsigned char *buf = xmalloc(bytes);
36 MD5_CTX md;
37
38 BN_bn2bin(host_key_n, buf);
39 BN_bn2bin(session_key_n, buf + (host_key_bits + 7 ) / 8);
40 memcpy(buf + (host_key_bits + 7) / 8 + (session_key_bits + 7) / 8,
41 cookie, 8);
42 MD5_Init(&md);
43 MD5_Update(&md, buf, bytes);
44 MD5_Final(session_id, &md);
45 xfree(buf);
46}
diff --git a/mpaux.h b/mpaux.h
new file mode 100644
index 000000000..3ad06813b
--- /dev/null
+++ b/mpaux.h
@@ -0,0 +1,32 @@
1/*
2
3mpaux.h
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Sun Jul 16 04:29:30 1995 ylo
11
12This file contains various auxiliary functions related to multiple
13precision integers.
14
15*/
16
17/* RCSID("$Id: mpaux.h,v 1.1 1999/10/27 03:42:44 damien Exp $"); */
18
19#ifndef MPAUX_H
20#define MPAUX_H
21
22/* Computes a 16-byte session id in the global variable session_id.
23 The session id is computed by concatenating the linearized, msb
24 first representations of host_key_n, session_key_n, and the cookie. */
25void compute_session_id(unsigned char session_id[16],
26 unsigned char cookie[8],
27 unsigned int host_key_bits,
28 BIGNUM *host_key_n,
29 unsigned int session_key_bits,
30 BIGNUM *session_key_n);
31
32#endif /* MPAUX_H */
diff --git a/nchan.c b/nchan.c
new file mode 100644
index 000000000..fcaeae405
--- /dev/null
+++ b/nchan.c
@@ -0,0 +1,187 @@
1#include "includes.h"
2RCSID("$Id: nchan.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
3
4#include "ssh.h"
5
6#include "buffer.h"
7#include "packet.h"
8#include "channels.h"
9#include "nchan.h"
10
11static void chan_send_ieof(Channel *c);
12static void chan_send_oclose(Channel *c);
13static void chan_shutdown_write(Channel *c);
14static void chan_shutdown_read(Channel *c);
15static void chan_delele_if_full_closed(Channel *c);
16
17/*
18 * EVENTS: update channel input/output states
19 * execute ACTIONS
20 */
21/* events concerning the INPUT from socket for channel (istate) */
22void
23chan_rcvd_oclose(Channel *c){
24 switch(c->istate){
25 case CHAN_INPUT_WAIT_OCLOSE:
26 debug("channel %d: INPUT_WAIT_OCLOSE -> INPUT_CLOSED [rcvd OCLOSE]", c->self);
27 c->istate=CHAN_INPUT_CLOSED;
28 chan_delele_if_full_closed(c);
29 break;
30 case CHAN_INPUT_OPEN:
31 debug("channel %d: INPUT_OPEN -> INPUT_CLOSED [rvcd OCLOSE, send IEOF]", c->self);
32 chan_shutdown_read(c);
33 chan_send_ieof(c);
34 c->istate=CHAN_INPUT_CLOSED;
35 chan_delele_if_full_closed(c);
36 break;
37 default:
38 debug("protocol error: chan_rcvd_oclose %d for istate %d",c->self,c->istate);
39 break;
40 }
41}
42void
43chan_read_failed(Channel *c){
44 switch(c->istate){
45 case CHAN_INPUT_OPEN:
46 debug("channel %d: INPUT_OPEN -> INPUT_WAIT_DRAIN [read failed]", c->self);
47 chan_shutdown_read(c);
48 c->istate=CHAN_INPUT_WAIT_DRAIN;
49 break;
50 default:
51 debug("internal error: we do not read, but chan_read_failed %d for istate %d",
52 c->self,c->istate);
53 break;
54 }
55}
56void
57chan_ibuf_empty(Channel *c){
58 if(buffer_len(&c->input)){
59 debug("internal error: chan_ibuf_empty %d for non empty buffer",c->self);
60 return;
61 }
62 switch(c->istate){
63 case CHAN_INPUT_WAIT_DRAIN:
64 debug("channel %d: INPUT_WAIT_DRAIN -> INPUT_WAIT_OCLOSE [inbuf empty, send IEOF]", c->self);
65 chan_send_ieof(c);
66 c->istate=CHAN_INPUT_WAIT_OCLOSE;
67 break;
68 default:
69 debug("internal error: chan_ibuf_empty %d for istate %d",c->self,c->istate);
70 break;
71 }
72}
73/* events concerning the OUTPUT from channel for socket (ostate) */
74void
75chan_rcvd_ieof(Channel *c){
76 switch(c->ostate){
77 case CHAN_OUTPUT_OPEN:
78 debug("channel %d: OUTPUT_OPEN -> OUTPUT_WAIT_DRAIN [rvcd IEOF]", c->self);
79 c->ostate=CHAN_OUTPUT_WAIT_DRAIN;
80 break;
81 case CHAN_OUTPUT_WAIT_IEOF:
82 debug("channel %d: OUTPUT_WAIT_IEOF -> OUTPUT_CLOSED [rvcd IEOF]", c->self);
83 c->ostate=CHAN_OUTPUT_CLOSED;
84 chan_delele_if_full_closed(c);
85 break;
86 default:
87 debug("protocol error: chan_rcvd_ieof %d for ostate %d", c->self,c->ostate);
88 break;
89 }
90}
91void
92chan_write_failed(Channel *c){
93 switch(c->ostate){
94 case CHAN_OUTPUT_OPEN:
95 debug("channel %d: OUTPUT_OPEN -> OUTPUT_WAIT_IEOF [write failed]", c->self);
96 chan_send_oclose(c);
97 c->ostate=CHAN_OUTPUT_WAIT_IEOF;
98 break;
99 case CHAN_OUTPUT_WAIT_DRAIN:
100 debug("channel %d: OUTPUT_WAIT_DRAIN -> OUTPUT_CLOSED [write failed]", c->self);
101 chan_send_oclose(c);
102 c->ostate=CHAN_OUTPUT_CLOSED;
103 chan_delele_if_full_closed(c);
104 break;
105 default:
106 debug("internal error: chan_write_failed %d for ostate %d",c->self,c->ostate);
107 break;
108 }
109}
110void
111chan_obuf_empty(Channel *c){
112 if(buffer_len(&c->output)){
113 debug("internal error: chan_obuf_empty %d for non empty buffer",c->self);
114 return;
115 }
116 switch(c->ostate){
117 case CHAN_OUTPUT_WAIT_DRAIN:
118 debug("channel %d: OUTPUT_WAIT_DRAIN -> OUTPUT_CLOSED [obuf empty, send OCLOSE]", c->self);
119 chan_send_oclose(c);
120 c->ostate=CHAN_OUTPUT_CLOSED;
121 chan_delele_if_full_closed(c);
122 break;
123 default:
124 debug("internal error: chan_obuf_empty %d for ostate %d",c->self,c->ostate);
125 break;
126 }
127}
128/*
129 * ACTIONS: should never update c->istate or c->ostate
130 */
131static void
132chan_send_ieof(Channel *c){
133 switch(c->istate){
134 case CHAN_INPUT_OPEN:
135 case CHAN_INPUT_WAIT_DRAIN:
136 packet_start(SSH_MSG_CHANNEL_INPUT_EOF);
137 packet_put_int(c->remote_id);
138 packet_send();
139 break;
140 default:
141 debug("internal error: channel %d: cannot send IEOF for istate %d",c->self,c->istate);
142 break;
143 }
144}
145static void
146chan_send_oclose(Channel *c){
147 switch(c->ostate){
148 case CHAN_OUTPUT_OPEN:
149 case CHAN_OUTPUT_WAIT_DRAIN:
150 chan_shutdown_write(c);
151 buffer_consume(&c->output, buffer_len(&c->output));
152 packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE);
153 packet_put_int(c->remote_id);
154 packet_send();
155 break;
156 default:
157 debug("internal error: channel %d: cannot send OCLOSE for ostate %d",c->self,c->istate);
158 break;
159 }
160}
161/* helper */
162static void
163chan_shutdown_write(Channel *c){
164 debug("channel %d: shutdown_write", c->self);
165 if(shutdown(c->sock, SHUT_WR)<0)
166 error("chan_shutdown_write failed for #%d/fd%d: %.100s",
167 c->self, c->sock, strerror(errno));
168}
169static void
170chan_shutdown_read(Channel *c){
171 debug("channel %d: shutdown_read", c->self);
172 if(shutdown(c->sock, SHUT_RD)<0)
173 error("chan_shutdown_read failed for #%d/fd%d: %.100s",
174 c->self, c->sock, strerror(errno));
175}
176static void
177chan_delele_if_full_closed(Channel *c){
178 if(c->istate==CHAN_INPUT_CLOSED && c->ostate==CHAN_OUTPUT_CLOSED){
179 debug("channel %d: closing", c->self);
180 channel_free(c->self);
181 }
182}
183void
184chan_init_iostates(Channel *c){
185 c->ostate=CHAN_OUTPUT_OPEN;
186 c->istate=CHAN_INPUT_OPEN;
187}
diff --git a/nchan.h b/nchan.h
new file mode 100644
index 000000000..16d360d30
--- /dev/null
+++ b/nchan.h
@@ -0,0 +1,57 @@
1/* RCSID("$Id: nchan.h,v 1.1 1999/10/27 03:42:44 damien Exp $"); */
2
3#ifndef NCHAN_H
4#define NCHAN_H
5
6/*
7 * SSH Protocol 1.5 aka New Channel Protocol
8 * Thanks to Martina, Axel and everyone who left Erlangen, leaving me bored.
9 * Written by Markus Friedl in October 1999
10 *
11 * Protocol versions 1.3 and 1.5 differ in the handshake protocol used for the
12 * tear down of channels:
13 *
14 * 1.3: strict request-ack-protocol:
15 * CLOSE ->
16 * <- CLOSE_CONFIRM
17 *
18 * 1.5: uses variations of:
19 * IEOF ->
20 * <- OCLOSE
21 * <- IEOF
22 * OCLOSE ->
23 * i.e. both sides have to close the channel
24 *
25 * See the debugging output from 'ssh -v' and 'sshd -d' of
26 * ssh-1.2.27 as an example.
27 *
28 */
29
30/* ssh-proto-1.5 overloads prot-1.3-message-types */
31#define SSH_MSG_CHANNEL_INPUT_EOF SSH_MSG_CHANNEL_CLOSE
32#define SSH_MSG_CHANNEL_OUTPUT_CLOSE SSH_MSG_CHANNEL_CLOSE_CONFIRMATION
33
34/* possible input states */
35#define CHAN_INPUT_OPEN 0x01
36#define CHAN_INPUT_WAIT_DRAIN 0x02
37#define CHAN_INPUT_WAIT_OCLOSE 0x04
38#define CHAN_INPUT_CLOSED 0x08
39
40/* possible output states */
41#define CHAN_OUTPUT_OPEN 0x10
42#define CHAN_OUTPUT_WAIT_DRAIN 0x20
43#define CHAN_OUTPUT_WAIT_IEOF 0x40
44#define CHAN_OUTPUT_CLOSED 0x80
45
46/* EVENTS for the input state */
47void chan_rcvd_oclose(Channel *c);
48void chan_read_failed(Channel *c);
49void chan_ibuf_empty(Channel *c);
50
51/* EVENTS for the output state */
52void chan_rcvd_ieof(Channel *c);
53void chan_write_failed(Channel *c);
54void chan_obuf_empty(Channel *c);
55
56void chan_init_iostates(Channel *c);
57#endif
diff --git a/nchan.ms b/nchan.ms
new file mode 100644
index 000000000..b01512f78
--- /dev/null
+++ b/nchan.ms
@@ -0,0 +1,71 @@
1.TL
2OpenSSH Channel Close Protocol 1.5 Implementation
3.SH
4Channel Input State Diagram
5.PS
6reset
7l=1
8s=1.2
9ellipsewid=s*ellipsewid
10boxwid=s*boxwid
11ellipseht=s*ellipseht
12S1: ellipse "INPUT" "OPEN"
13move right 2*l from last ellipse.e
14S4: ellipse "INPUT" "CLOSED"
15move down l from last ellipse.s
16S3: ellipse "INPUT" "WAIT" "OCLOSED"
17move down l from 1st ellipse.s
18S2: ellipse "INPUT" "WAIT" "DRAIN"
19arrow "" "rcvd OCLOSE/" "shutdown_read" "send IEOF" from S1.e to S4.w
20arrow "ibuf_empty/" "send IEOF" from S2.e to S3.w
21arrow from S1.s to S2.n
22box invis "read_failed/" "shutdown_read" with .e at last arrow.c
23arrow from S3.n to S4.s
24box invis "rcvd OCLOSE/" "-" with .w at last arrow.c
25ellipse wid .9*ellipsewid ht .9*ellipseht at S4
26arrow "start" "" from S1.w+(-0.5,0) to S1.w
27.PE
28.SH
29Channel Output State Diagram
30.PS
31S1: ellipse "OUTPUT" "OPEN"
32move right 2*l from last ellipse.e
33S3: ellipse "OUTPUT" "WAIT" "IEOF"
34move down l from last ellipse.s
35S4: ellipse "OUTPUT" "CLOSED"
36move down l from 1st ellipse.s
37S2: ellipse "OUTPUT" "WAIT" "DRAIN"
38arrow "" "write_failed/" "shutdown_write" "send OCLOSE" from S1.e to S3.w
39arrow "obuf_empty ||" "write_failed/" "shutdown_write" "send OCLOSE" from S2.e to S4.w
40arrow from S1.s to S2.n
41box invis "rcvd IEOF/" "-" with .e at last arrow.c
42arrow from S3.s to S4.n
43box invis "rcvd IEOF/" "-" with .w at last arrow.c
44ellipse wid .9*ellipsewid ht .9*ellipseht at S4
45arrow "start" "" from S1.w+(-0.5,0) to S1.w
46.PE
47.SH
48Notes
49.PP
50The input buffer is filled with data from the socket
51(the socket represents the local comsumer/producer of the
52forwarded channel).
53The data is then sent over the INPUT-end of the channel to the
54remote peer.
55Data sent by the peer is received on the OUTPUT-end,
56saved in the output buffer and written to the socket.
57.PP
58If the local protocol instance has forwarded all data on the
59INPUT-end of the channel, it sends an IEOF message to the peer.
60If the peer receives the IEOF and has comsumed all
61data he replies with an OCLOSE.
62When the local instance receives the OCLOSE
63he considers the INPUT-half of the channel closed.
64The peer has his OUTOUT-half closed.
65.PP
66A channel can be deallocated by a protocol instance
67if both the INPUT- and the OUTOUT-half on his
68side of the channel are closed.
69Note that when an instance is unable to comsume the
70received data, he is permitted to send an OCLOSE
71before the matching IEOF is received.
diff --git a/openssh.spec b/openssh.spec
new file mode 100644
index 000000000..7ce58849f
--- /dev/null
+++ b/openssh.spec
@@ -0,0 +1,105 @@
1Summary: OpenSSH free Secure Shell (SSH) implementation
2Name: openssh
3Version: 1.2pre3
4Release: 1
5Packager: Damien Miller <djm@ibs.com.au>
6Source0: openssh-%{version}-linux.tar.gz
7Copyright: BSD
8Group: Applications/Internet
9BuildRoot: /tmp/openssh-%{version}-buildroot
10
11%description
12Ssh (Secure Shell) a program for logging into a remote machine and for
13executing commands in a remote machine. It is intended to replace
14rlogin and rsh, and provide secure encrypted communications between
15two untrusted hosts over an insecure network. X11 connections and
16arbitrary TCP/IP ports can also be forwarded over the secure channel.
17
18OpenSSH is OpenBSD's rework of the last free version of SSH, bringing it
19up to date in terms of security and features, as well as removing all
20patented algorithms to seperate libraries (OpenSSL).
21
22%changelog
23* Wed Oct 27 1999 Damien Miller <djm@ibs.com.au>
24- Initial RPMification, based on Jan "Yenya" Kasprzak's <kas@fi.muni.cz> spec.
25
26%prep
27
28%setup -n openssh
29
30%build
31
32make -f Makefile.GNU OPT_FLAGS="$RPM_OPT_FLAGS"
33
34%install
35rm -rf $RPM_BUILD_ROOT
36mkdir -p $RPM_BUILD_ROOT/usr/bin
37mkdir -p $RPM_BUILD_ROOT/usr/sbin
38mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d
39mkdir -p $RPM_BUILD_ROOT/etc/pam.d
40mkdir -p $RPM_BUILD_ROOT/etc/ssh
41mkdir -p $RPM_BUILD_ROOT/usr/man/man1
42mkdir -p $RPM_BUILD_ROOT/usr/man/man8
43
44install -m644 ssh.pam $RPM_BUILD_ROOT/etc/pam.d/ssh
45install -m755 sshd.init $RPM_BUILD_ROOT/etc/rc.d/init.d/sshd
46install -m600 ssh_config $RPM_BUILD_ROOT/etc/ssh/ssh_config
47install -m600 sshd_config $RPM_BUILD_ROOT/etc/ssh/sshd_config
48
49install -s -m755 bin/sshd $RPM_BUILD_ROOT/usr/sbin
50install -s -m755 bin/ssh $RPM_BUILD_ROOT/usr/bin
51install -s -m755 bin/scp $RPM_BUILD_ROOT/usr/bin
52install -s -m755 bin/ssh-agent $RPM_BUILD_ROOT/usr/bin
53install -s -m755 bin/ssh-add $RPM_BUILD_ROOT/usr/bin
54install -s -m755 bin/ssh-keygen $RPM_BUILD_ROOT/usr/bin
55
56install -m644 sshd.8 $RPM_BUILD_ROOT/usr/man/man8
57install -m644 ssh.1 $RPM_BUILD_ROOT/usr/man/man1
58install -m644 scp.1 $RPM_BUILD_ROOT/usr/man/man1
59install -m644 ssh-agent.1 $RPM_BUILD_ROOT/usr/man/man1
60install -m644 ssh-add.1 $RPM_BUILD_ROOT/usr/man/man1
61install -m644 ssh-keygen.1 $RPM_BUILD_ROOT/usr/man/man1
62
63%clean
64rm -rf $RPM_BUILD_ROOT
65
66%post
67/sbin/chkconfig --add sshd
68if [ ! -f /etc/ssh/ssh_host_key -o ! -s /etc/ssh/ssh_host_key ]; then
69 /usr/bin/ssh-keygen -b 1024 -f /etc/ssh/ssh_host_key -N '' >&2
70fi
71if test -r /var/run/sshd.pid
72then
73 /etc/rc.d/init.d/sshd restart >&2
74fi
75
76%preun
77if [ "$1" = 0 ]
78then
79 /etc/rc.d/init.d/sshd stop >&2
80 /sbin/chkconfig --del sshd
81fi
82
83%files
84%defattr(-,root,root)
85%doc COPYING.Ylonen ChangeLog ChangeLog.linux OVERVIEW
86%doc README README.openssh
87%attr(0755,root,root) /usr/sbin/sshd
88%attr(0755,root,root) /usr/bin/ssh
89%attr(0755,root,root) /usr/bin/ssh-agent
90%attr(0755,root,root) /usr/bin/ssh-keygen
91%attr(0755,root,root) /usr/bin/ssh-add
92%attr(0755,root,root) /usr/bin/scp
93
94%attr(0755,root,root) /usr/man/man8/sshd.8
95%attr(0755,root,root) /usr/man/man1/ssh.1
96%attr(0755,root,root) /usr/man/man1/ssh-agent.1
97%attr(0755,root,root) /usr/man/man1/ssh-keygen.1
98%attr(0755,root,root) /usr/man/man1/ssh-add.1
99%attr(0755,root,root) /usr/man/man1/scp.1
100
101%attr(0600,root,root) %config /etc/ssh/sshd_config
102%attr(0600,root,root) %config /etc/pam.d/ssh
103%attr(0755,root,root) %config /etc/rc.d/init.d/sshd
104%attr(0644,root,root) %config /etc/ssh/ssh_config
105
diff --git a/packet.c b/packet.c
new file mode 100644
index 000000000..7e74c73b3
--- /dev/null
+++ b/packet.c
@@ -0,0 +1,762 @@
1/*
2
3packet.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Sat Mar 18 02:40:40 1995 ylo
11
12This file contains code implementing the packet protocol and communication
13with the other side. This same code is used both on client and server side.
14
15*/
16
17#include "includes.h"
18RCSID("$Id: packet.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
19
20#include "xmalloc.h"
21#include "buffer.h"
22#include "packet.h"
23#include "bufaux.h"
24#include "ssh.h"
25#include "crc32.h"
26#include "cipher.h"
27#include "getput.h"
28
29#include "compress.h"
30#include "deattack.h"
31
32/* This variable contains the file descriptors used for communicating with
33 the other side. connection_in is used for reading; connection_out
34 for writing. These can be the same descriptor, in which case it is
35 assumed to be a socket. */
36static int connection_in = -1;
37static int connection_out = -1;
38
39/* Cipher type. This value is only used to determine whether to pad the
40 packets with zeroes or random data. */
41static int cipher_type = SSH_CIPHER_NONE;
42
43/* Protocol flags for the remote side. */
44static unsigned int remote_protocol_flags = 0;
45
46/* Encryption context for receiving data. This is only used for decryption. */
47static CipherContext receive_context;
48/* Encryption coontext for sending data. This is only used for encryption. */
49static CipherContext send_context;
50
51/* Buffer for raw input data from the socket. */
52static Buffer input;
53
54/* Buffer for raw output data going to the socket. */
55static Buffer output;
56
57/* Buffer for the partial outgoing packet being constructed. */
58static Buffer outgoing_packet;
59
60/* Buffer for the incoming packet currently being processed. */
61static Buffer incoming_packet;
62
63/* Scratch buffer for packet compression/decompression. */
64static Buffer compression_buffer;
65
66/* Flag indicating whether packet compression/decompression is enabled. */
67static int packet_compression = 0;
68
69/* Flag indicating whether this module has been initialized. */
70static int initialized = 0;
71
72/* Set to true if the connection is interactive. */
73static int interactive_mode = 0;
74
75/* Sets the descriptors used for communication. Disables encryption until
76 packet_set_encryption_key is called. */
77
78void
79packet_set_connection(int fd_in, int fd_out)
80{
81 connection_in = fd_in;
82 connection_out = fd_out;
83 cipher_type = SSH_CIPHER_NONE;
84 cipher_set_key(&send_context, SSH_CIPHER_NONE, (unsigned char *)"", 0, 1);
85 cipher_set_key(&receive_context, SSH_CIPHER_NONE, (unsigned char *)"", 0, 0);
86 if (!initialized)
87 {
88 initialized = 1;
89 buffer_init(&input);
90 buffer_init(&output);
91 buffer_init(&outgoing_packet);
92 buffer_init(&incoming_packet);
93 }
94
95 /* Kludge: arrange the close function to be called from fatal(). */
96 fatal_add_cleanup((void (*)(void *))packet_close, NULL);
97}
98
99/* Sets the connection into non-blocking mode. */
100
101void
102packet_set_nonblocking()
103{
104 /* Set the socket into non-blocking mode. */
105 if (fcntl(connection_in, F_SETFL, O_NONBLOCK) < 0)
106 error("fcntl O_NONBLOCK: %.100s", strerror(errno));
107
108 if (connection_out != connection_in)
109 {
110 if (fcntl(connection_out, F_SETFL, O_NONBLOCK) < 0)
111 error("fcntl O_NONBLOCK: %.100s", strerror(errno));
112 }
113}
114
115/* Returns the socket used for reading. */
116
117int
118packet_get_connection_in()
119{
120 return connection_in;
121}
122
123/* Returns the descriptor used for writing. */
124
125int
126packet_get_connection_out()
127{
128 return connection_out;
129}
130
131/* Closes the connection and clears and frees internal data structures. */
132
133void
134packet_close()
135{
136 if (!initialized)
137 return;
138 initialized = 0;
139 if (connection_in == connection_out)
140 {
141 shutdown(connection_out, SHUT_RDWR);
142 close(connection_out);
143 }
144 else
145 {
146 close(connection_in);
147 close(connection_out);
148 }
149 buffer_free(&input);
150 buffer_free(&output);
151 buffer_free(&outgoing_packet);
152 buffer_free(&incoming_packet);
153 if (packet_compression)
154 {
155 buffer_free(&compression_buffer);
156 buffer_compress_uninit();
157 }
158}
159
160/* Sets remote side protocol flags. */
161
162void
163packet_set_protocol_flags(unsigned int protocol_flags)
164{
165 remote_protocol_flags = protocol_flags;
166 channel_set_options((protocol_flags & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) != 0);
167}
168
169/* Returns the remote protocol flags set earlier by the above function. */
170
171unsigned int
172packet_get_protocol_flags()
173{
174 return remote_protocol_flags;
175}
176
177/* Starts packet compression from the next packet on in both directions.
178 Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. */
179
180void
181packet_start_compression(int level)
182{
183 if (packet_compression)
184 fatal("Compression already enabled.");
185 packet_compression = 1;
186 buffer_init(&compression_buffer);
187 buffer_compress_init(level);
188}
189
190/* Encrypts the given number of bytes, copying from src to dest.
191 bytes is known to be a multiple of 8. */
192
193void
194packet_encrypt(CipherContext *cc, void *dest, void *src,
195 unsigned int bytes)
196{
197 assert((bytes % 8) == 0);
198 cipher_encrypt(cc, dest, src, bytes);
199}
200
201/* Decrypts the given number of bytes, copying from src to dest.
202 bytes is known to be a multiple of 8. */
203
204void
205packet_decrypt(CipherContext *cc, void *dest, void *src,
206 unsigned int bytes)
207{
208 int i;
209
210 assert((bytes % 8) == 0);
211
212 /*
213 Cryptographic attack detector for ssh - Modifications for packet.c
214 (C)1998 CORE-SDI, Buenos Aires Argentina
215 Ariel Futoransky(futo@core-sdi.com)
216 */
217 switch (cc->type)
218 {
219 case SSH_CIPHER_NONE:
220 i = DEATTACK_OK;
221 break;
222 default:
223 i = detect_attack(src, bytes, NULL);
224 break;
225 }
226
227 if (i == DEATTACK_DETECTED)
228 packet_disconnect("crc32 compensation attack: network attack detected");
229
230 cipher_decrypt(cc, dest, src, bytes);
231}
232
233/* Causes any further packets to be encrypted using the given key. The same
234 key is used for both sending and reception. However, both directions
235 are encrypted independently of each other. */
236
237void
238packet_set_encryption_key(const unsigned char *key, unsigned int keylen,
239 int cipher, int is_client)
240{
241 cipher_type = cipher;
242 if (cipher == SSH_CIPHER_RC4)
243 {
244 if (is_client)
245 { /* In client: use first half for receiving, second for sending. */
246 cipher_set_key(&receive_context, cipher, key, keylen / 2, 0);
247 cipher_set_key(&send_context, cipher, key + keylen / 2,
248 keylen / 2, 1);
249 }
250 else
251 { /* In server: use first half for sending, second for receiving. */
252 cipher_set_key(&receive_context, cipher, key + keylen / 2,
253 keylen / 2, 0);
254 cipher_set_key(&send_context, cipher, key, keylen / 2, 1);
255 }
256 }
257 else
258 {
259 /* All other ciphers use the same key in both directions for now. */
260 cipher_set_key(&receive_context, cipher, key, keylen, 0);
261 cipher_set_key(&send_context, cipher, key, keylen, 1);
262 }
263}
264
265/* Starts constructing a packet to send. */
266
267void
268packet_start(int type)
269{
270 char buf[9];
271
272 buffer_clear(&outgoing_packet);
273 memset(buf, 0, 8);
274 buf[8] = type;
275 buffer_append(&outgoing_packet, buf, 9);
276}
277
278/* Appends a character to the packet data. */
279
280void
281packet_put_char(int value)
282{
283 char ch = value;
284 buffer_append(&outgoing_packet, &ch, 1);
285}
286
287/* Appends an integer to the packet data. */
288
289void
290packet_put_int(unsigned int value)
291{
292 buffer_put_int(&outgoing_packet, value);
293}
294
295/* Appends a string to packet data. */
296
297void
298packet_put_string(const char *buf, unsigned int len)
299{
300 buffer_put_string(&outgoing_packet, buf, len);
301}
302
303/* Appends an arbitrary precision integer to packet data. */
304
305void
306packet_put_bignum(BIGNUM *value)
307{
308 buffer_put_bignum(&outgoing_packet, value);
309}
310
311/* Finalizes and sends the packet. If the encryption key has been set,
312 encrypts the packet before sending. */
313
314void
315packet_send()
316{
317 char buf[8], *cp;
318 int i, padding, len;
319 unsigned int checksum;
320 u_int32_t rand = 0;
321
322 /* If using packet compression, compress the payload of the outgoing
323 packet. */
324 if (packet_compression)
325 {
326 buffer_clear(&compression_buffer);
327 buffer_consume(&outgoing_packet, 8); /* Skip padding. */
328 buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8); /* padding */
329 buffer_compress(&outgoing_packet, &compression_buffer);
330 buffer_clear(&outgoing_packet);
331 buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),
332 buffer_len(&compression_buffer));
333 }
334
335 /* Compute packet length without padding (add checksum, remove padding). */
336 len = buffer_len(&outgoing_packet) + 4 - 8;
337
338 /* Insert padding. */
339 padding = 8 - len % 8;
340 if (cipher_type != SSH_CIPHER_NONE)
341 {
342 cp = buffer_ptr(&outgoing_packet);
343 for (i = 0; i < padding; i++) {
344 if (i % 4 == 0)
345 rand = arc4random();
346 cp[7 - i] = rand & 0xff;
347 rand >>= 8;
348 }
349 }
350 buffer_consume(&outgoing_packet, 8 - padding);
351
352 /* Add check bytes. */
353 checksum = crc32((unsigned char *)buffer_ptr(&outgoing_packet),
354 buffer_len(&outgoing_packet));
355 PUT_32BIT(buf, checksum);
356 buffer_append(&outgoing_packet, buf, 4);
357
358#ifdef PACKET_DEBUG
359 fprintf(stderr, "packet_send plain: ");
360 buffer_dump(&outgoing_packet);
361#endif
362
363 /* Append to output. */
364 PUT_32BIT(buf, len);
365 buffer_append(&output, buf, 4);
366 buffer_append_space(&output, &cp, buffer_len(&outgoing_packet));
367 packet_encrypt(&send_context, cp, buffer_ptr(&outgoing_packet),
368 buffer_len(&outgoing_packet));
369
370#ifdef PACKET_DEBUG
371 fprintf(stderr, "encrypted: "); buffer_dump(&output);
372#endif
373
374 buffer_clear(&outgoing_packet);
375
376 /* Note that the packet is now only buffered in output. It won\'t be
377 actually sent until packet_write_wait or packet_write_poll is called. */
378}
379
380/* Waits until a packet has been received, and returns its type. Note that
381 no other data is processed until this returns, so this function should
382 not be used during the interactive session. */
383
384int
385packet_read(int *payload_len_ptr)
386{
387 int type, len;
388 fd_set set;
389 char buf[8192];
390
391 /* Since we are blocking, ensure that all written packets have been sent. */
392 packet_write_wait();
393
394 /* Stay in the loop until we have received a complete packet. */
395 for (;;)
396 {
397 /* Try to read a packet from the buffer. */
398 type = packet_read_poll(payload_len_ptr);
399 if (type == SSH_SMSG_SUCCESS
400 || type == SSH_SMSG_FAILURE
401 || type == SSH_CMSG_EOF
402 || type == SSH_CMSG_EXIT_CONFIRMATION)
403 packet_integrity_check(*payload_len_ptr, 0, type);
404 /* If we got a packet, return it. */
405 if (type != SSH_MSG_NONE)
406 return type;
407 /* Otherwise, wait for some data to arrive, add it to the buffer,
408 and try again. */
409 FD_ZERO(&set);
410 FD_SET(connection_in, &set);
411 /* Wait for some data to arrive. */
412 select(connection_in + 1, &set, NULL, NULL, NULL);
413 /* Read data from the socket. */
414 len = read(connection_in, buf, sizeof(buf));
415 if (len == 0)
416 fatal("Connection closed by remote host.");
417 if (len < 0)
418 fatal("Read from socket failed: %.100s", strerror(errno));
419 /* Append it to the buffer. */
420 packet_process_incoming(buf, len);
421 }
422 /*NOTREACHED*/
423}
424
425/* Waits until a packet has been received, verifies that its type matches
426 that given, and gives a fatal error and exits if there is a mismatch. */
427
428void
429packet_read_expect(int *payload_len_ptr, int expected_type)
430{
431 int type;
432
433 type = packet_read(payload_len_ptr);
434 if (type != expected_type)
435 packet_disconnect("Protocol error: expected packet type %d, got %d",
436 expected_type, type);
437}
438
439/* Checks if a full packet is available in the data received so far via
440 packet_process_incoming. If so, reads the packet; otherwise returns
441 SSH_MSG_NONE. This does not wait for data from the connection.
442
443 SSH_MSG_DISCONNECT is handled specially here. Also,
444 SSH_MSG_IGNORE messages are skipped by this function and are never returned
445 to higher levels.
446
447 The returned payload_len does include space consumed by:
448 Packet length
449 Padding
450 Packet type
451 Check bytes
452
453
454 */
455
456int
457packet_read_poll(int *payload_len_ptr)
458{
459 unsigned int len, padded_len;
460 unsigned char *ucp;
461 char buf[8], *cp;
462 unsigned int checksum, stored_checksum;
463
464 restart:
465
466 /* Check if input size is less than minimum packet size. */
467 if (buffer_len(&input) < 4 + 8)
468 return SSH_MSG_NONE;
469 /* Get length of incoming packet. */
470 ucp = (unsigned char *)buffer_ptr(&input);
471 len = GET_32BIT(ucp);
472 if (len < 1 + 2 + 2 || len > 256*1024)
473 packet_disconnect("Bad packet length %d.", len);
474 padded_len = (len + 8) & ~7;
475
476 /* Check if the packet has been entirely received. */
477 if (buffer_len(&input) < 4 + padded_len)
478 return SSH_MSG_NONE;
479
480 /* The entire packet is in buffer. */
481
482 /* Consume packet length. */
483 buffer_consume(&input, 4);
484
485 /* Copy data to incoming_packet. */
486 buffer_clear(&incoming_packet);
487 buffer_append_space(&incoming_packet, &cp, padded_len);
488 packet_decrypt(&receive_context, cp, buffer_ptr(&input), padded_len);
489 buffer_consume(&input, padded_len);
490
491#ifdef PACKET_DEBUG
492 fprintf(stderr, "read_poll plain: "); buffer_dump(&incoming_packet);
493#endif
494
495 /* Compute packet checksum. */
496 checksum = crc32((unsigned char *)buffer_ptr(&incoming_packet),
497 buffer_len(&incoming_packet) - 4);
498
499 /* Skip padding. */
500 buffer_consume(&incoming_packet, 8 - len % 8);
501
502 /* Test check bytes. */
503 assert(len == buffer_len(&incoming_packet));
504 ucp = (unsigned char *)buffer_ptr(&incoming_packet) + len - 4;
505 stored_checksum = GET_32BIT(ucp);
506 if (checksum != stored_checksum)
507 packet_disconnect("Corrupted check bytes on input.");
508 buffer_consume_end(&incoming_packet, 4);
509
510 /* If using packet compression, decompress the packet. */
511 if (packet_compression)
512 {
513 buffer_clear(&compression_buffer);
514 buffer_uncompress(&incoming_packet, &compression_buffer);
515 buffer_clear(&incoming_packet);
516 buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
517 buffer_len(&compression_buffer));
518 }
519
520 /* Get packet type. */
521 buffer_get(&incoming_packet, &buf[0], 1);
522
523 /* Return length of payload (without type field). */
524 *payload_len_ptr = buffer_len(&incoming_packet);
525
526 /* Handle disconnect message. */
527 if ((unsigned char)buf[0] == SSH_MSG_DISCONNECT)
528 fatal("%.900s", packet_get_string(NULL));
529
530 /* Ignore ignore messages. */
531 if ((unsigned char)buf[0] == SSH_MSG_IGNORE)
532 goto restart;
533
534 /* Send debug messages as debugging output. */
535 if ((unsigned char)buf[0] == SSH_MSG_DEBUG)
536 {
537 debug("Remote: %.900s", packet_get_string(NULL));
538 goto restart;
539 }
540
541 /* Return type. */
542 return (unsigned char)buf[0];
543}
544
545/* Buffers the given amount of input characters. This is intended to be
546 used together with packet_read_poll. */
547
548void
549packet_process_incoming(const char *buf, unsigned int len)
550{
551 buffer_append(&input, buf, len);
552}
553
554/* Returns a character from the packet. */
555
556unsigned int
557packet_get_char()
558{
559 char ch;
560 buffer_get(&incoming_packet, &ch, 1);
561 return (unsigned char)ch;
562}
563
564/* Returns an integer from the packet data. */
565
566unsigned int
567packet_get_int()
568{
569 return buffer_get_int(&incoming_packet);
570}
571
572/* Returns an arbitrary precision integer from the packet data. The integer
573 must have been initialized before this call. */
574
575void
576packet_get_bignum(BIGNUM *value, int *length_ptr)
577{
578 *length_ptr = buffer_get_bignum(&incoming_packet, value);
579}
580
581/* Returns a string from the packet data. The string is allocated using
582 xmalloc; it is the responsibility of the calling program to free it when
583 no longer needed. The length_ptr argument may be NULL, or point to an
584 integer into which the length of the string is stored. */
585
586char
587*packet_get_string(unsigned int *length_ptr)
588{
589 return buffer_get_string(&incoming_packet, length_ptr);
590}
591
592/* Sends a diagnostic message from the server to the client. This message
593 can be sent at any time (but not while constructing another message).
594 The message is printed immediately, but only if the client is being
595 executed in verbose mode. These messages are primarily intended to
596 ease debugging authentication problems. The length of the formatted
597 message must not exceed 1024 bytes. This will automatically call
598 packet_write_wait. */
599
600void
601packet_send_debug(const char *fmt, ...)
602{
603 char buf[1024];
604 va_list args;
605
606 va_start(args, fmt);
607 vsnprintf(buf, sizeof(buf), fmt, args);
608 va_end(args);
609
610 packet_start(SSH_MSG_DEBUG);
611 packet_put_string(buf, strlen(buf));
612 packet_send();
613 packet_write_wait();
614}
615
616/* Logs the error plus constructs and sends a disconnect
617 packet, closes the connection, and exits. This function never returns.
618 The error message should not contain a newline. The length of the
619 formatted message must not exceed 1024 bytes. */
620
621void
622packet_disconnect(const char *fmt, ...)
623{
624 char buf[1024];
625 va_list args;
626 static int disconnecting = 0;
627 if (disconnecting) /* Guard against recursive invocations. */
628 fatal("packet_disconnect called recursively.");
629 disconnecting = 1;
630
631 /* Format the message. Note that the caller must make sure the message
632 is of limited size. */
633 va_start(args, fmt);
634 vsnprintf(buf, sizeof(buf), fmt, args);
635 va_end(args);
636
637 /* Send the disconnect message to the other side, and wait for it to get
638 sent. */
639 packet_start(SSH_MSG_DISCONNECT);
640 packet_put_string(buf, strlen(buf));
641 packet_send();
642 packet_write_wait();
643
644 /* Stop listening for connections. */
645 channel_stop_listening();
646
647 /* Close the connection. */
648 packet_close();
649
650 /* Display the error locally and exit. */
651 fatal("Local: %.100s", buf);
652}
653
654/* Checks if there is any buffered output, and tries to write some of the
655 output. */
656
657void
658packet_write_poll()
659{
660 int len = buffer_len(&output);
661 if (len > 0)
662 {
663 len = write(connection_out, buffer_ptr(&output), len);
664 if (len <= 0) {
665 if (errno == EAGAIN)
666 return;
667 else
668 fatal("Write failed: %.100s", strerror(errno));
669 }
670 buffer_consume(&output, len);
671 }
672}
673
674/* Calls packet_write_poll repeatedly until all pending output data has
675 been written. */
676
677void
678packet_write_wait()
679{
680 packet_write_poll();
681 while (packet_have_data_to_write())
682 {
683 fd_set set;
684 FD_ZERO(&set);
685 FD_SET(connection_out, &set);
686 select(connection_out + 1, NULL, &set, NULL, NULL);
687 packet_write_poll();
688 }
689}
690
691/* Returns true if there is buffered data to write to the connection. */
692
693int
694packet_have_data_to_write()
695{
696 return buffer_len(&output) != 0;
697}
698
699/* Returns true if there is not too much data to write to the connection. */
700
701int
702packet_not_very_much_data_to_write()
703{
704 if (interactive_mode)
705 return buffer_len(&output) < 16384;
706 else
707 return buffer_len(&output) < 128*1024;
708}
709
710/* Informs that the current session is interactive. Sets IP flags for that. */
711
712void
713packet_set_interactive(int interactive, int keepalives)
714{
715 int on = 1;
716
717 /* Record that we are in interactive mode. */
718 interactive_mode = interactive;
719
720 /* Only set socket options if using a socket (as indicated by the descriptors
721 being the same). */
722 if (connection_in != connection_out)
723 return;
724
725 if (keepalives)
726 {
727 /* Set keepalives if requested. */
728 if (setsockopt(connection_in, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
729 sizeof(on)) < 0)
730 error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
731 }
732
733 if (interactive)
734 {
735 /* Set IP options for an interactive connection. Use IPTOS_LOWDELAY
736 and TCP_NODELAY. */
737 int lowdelay = IPTOS_LOWDELAY;
738 if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *)&lowdelay,
739 sizeof(lowdelay)) < 0)
740 error("setsockopt IPTOS_LOWDELAY: %.100s", strerror(errno));
741 if (setsockopt(connection_in, IPPROTO_TCP, TCP_NODELAY, (void *)&on,
742 sizeof(on)) < 0)
743 error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
744 }
745 else
746 {
747 /* Set IP options for a non-interactive connection. Use
748 IPTOS_THROUGHPUT. */
749 int throughput = IPTOS_THROUGHPUT;
750 if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *)&throughput,
751 sizeof(throughput)) < 0)
752 error("setsockopt IPTOS_THROUGHPUT: %.100s", strerror(errno));
753 }
754}
755
756/* Returns true if the current connection is interactive. */
757
758int
759packet_is_interactive()
760{
761 return interactive_mode;
762}
diff --git a/packet.h b/packet.h
new file mode 100644
index 000000000..fb84e6c11
--- /dev/null
+++ b/packet.h
@@ -0,0 +1,166 @@
1/*
2
3packet.h
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Sat Mar 18 02:02:14 1995 ylo
11
12Interface for the packet protocol functions.
13
14*/
15
16/* RCSID("$Id: packet.h,v 1.1 1999/10/27 03:42:44 damien Exp $"); */
17
18#ifndef PACKET_H
19#define PACKET_H
20
21#include <openssl/bn.h>
22
23/* Sets the socket used for communication. Disables encryption until
24 packet_set_encryption_key is called. It is permissible that fd_in
25 and fd_out are the same descriptor; in that case it is assumed to
26 be a socket. */
27void packet_set_connection(int fd_in, int fd_out);
28
29/* Puts the connection file descriptors into non-blocking mode. */
30void packet_set_nonblocking(void);
31
32/* Returns the file descriptor used for input. */
33int packet_get_connection_in(void);
34
35/* Returns the file descriptor used for output. */
36int packet_get_connection_out(void);
37
38/* Closes the connection (both descriptors) and clears and frees
39 internal data structures. */
40void packet_close(void);
41
42/* Causes any further packets to be encrypted using the given key. The same
43 key is used for both sending and reception. However, both directions
44 are encrypted independently of each other. Cipher types are
45 defined in ssh.h. */
46void packet_set_encryption_key(const unsigned char *key, unsigned int keylen,
47 int cipher_type, int is_client);
48
49/* Sets remote side protocol flags for the current connection. This can
50 be called at any time. */
51void packet_set_protocol_flags(unsigned int flags);
52
53/* Returns the remote protocol flags set earlier by the above function. */
54unsigned int packet_get_protocol_flags(void);
55
56/* Enables compression in both directions starting from the next packet. */
57void packet_start_compression(int level);
58
59/* Informs that the current session is interactive. Sets IP flags for optimal
60 performance in interactive use. */
61void packet_set_interactive(int interactive, int keepalives);
62
63/* Returns true if the current connection is interactive. */
64int packet_is_interactive(void);
65
66/* Starts constructing a packet to send. */
67void packet_start(int type);
68
69/* Appends a character to the packet data. */
70void packet_put_char(int ch);
71
72/* Appends an integer to the packet data. */
73void packet_put_int(unsigned int value);
74
75/* Appends an arbitrary precision integer to packet data. */
76void packet_put_bignum(BIGNUM *value);
77
78/* Appends a string to packet data. */
79void packet_put_string(const char *buf, unsigned int len);
80
81/* Finalizes and sends the packet. If the encryption key has been set,
82 encrypts the packet before sending. */
83void packet_send(void);
84
85/* Waits until a packet has been received, and returns its type. */
86int packet_read(int *payload_len_ptr);
87
88/* Waits until a packet has been received, verifies that its type matches
89 that given, and gives a fatal error and exits if there is a mismatch. */
90void packet_read_expect(int *payload_len_ptr, int type);
91
92/* Checks if a full packet is available in the data received so far via
93 packet_process_incoming. If so, reads the packet; otherwise returns
94 SSH_MSG_NONE. This does not wait for data from the connection.
95
96 SSH_MSG_DISCONNECT is handled specially here. Also,
97 SSH_MSG_IGNORE messages are skipped by this function and are never returned
98 to higher levels. */
99int packet_read_poll(int *packet_len_ptr);
100
101/* Buffers the given amount of input characters. This is intended to be
102 used together with packet_read_poll. */
103void packet_process_incoming(const char *buf, unsigned int len);
104
105/* Returns a character (0-255) from the packet data. */
106unsigned int packet_get_char(void);
107
108/* Returns an integer from the packet data. */
109unsigned int packet_get_int(void);
110
111/* Returns an arbitrary precision integer from the packet data. The integer
112 must have been initialized before this call. */
113void packet_get_bignum(BIGNUM *value, int *length_ptr);
114
115/* Returns a string from the packet data. The string is allocated using
116 xmalloc; it is the responsibility of the calling program to free it when
117 no longer needed. The length_ptr argument may be NULL, or point to an
118 integer into which the length of the string is stored. */
119char *packet_get_string(unsigned int *length_ptr);
120
121/* Logs the error in syslog using LOG_INFO, constructs and sends a disconnect
122 packet, closes the connection, and exits. This function never returns.
123 The error message should not contain a newline. The total length of the
124 message must not exceed 1024 bytes. */
125void packet_disconnect(const char *fmt, ...);
126
127/* Sends a diagnostic message to the other side. This message
128 can be sent at any time (but not while constructing another message).
129 The message is printed immediately, but only if the client is being
130 executed in verbose mode. These messages are primarily intended to
131 ease debugging authentication problems. The total length of the message
132 must not exceed 1024 bytes. This will automatically call
133 packet_write_wait. If the remote side protocol flags do not indicate
134 that it supports SSH_MSG_DEBUG, this will do nothing. */
135void packet_send_debug(const char *fmt, ...);
136
137/* Checks if there is any buffered output, and tries to write some of the
138 output. */
139void packet_write_poll(void);
140
141/* Waits until all pending output data has been written. */
142void packet_write_wait(void);
143
144/* Returns true if there is buffered data to write to the connection. */
145int packet_have_data_to_write(void);
146
147/* Returns true if there is not too much data to write to the connection. */
148int packet_not_very_much_data_to_write(void);
149
150/* Stores tty modes from the fd into current packet. */
151void tty_make_modes(int fd);
152
153/* Parses tty modes for the fd from the current packet. */
154void tty_parse_modes(int fd, int *n_bytes_ptr);
155
156#define packet_integrity_check(payload_len, expected_len, type) \
157do { \
158 int _p = (payload_len), _e = (expected_len); \
159 if (_p != _e) { \
160 log("Packet integrity error (%d != %d) at %s:%d", \
161 _p, _e, __FILE__, __LINE__); \
162 packet_disconnect("Packet integrity error. (%d)", (type)); \
163 } \
164} while (0)
165
166#endif /* PACKET_H */
diff --git a/pty.c b/pty.c
new file mode 100644
index 000000000..440994b51
--- /dev/null
+++ b/pty.c
@@ -0,0 +1,264 @@
1/*
2
3pty.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Fri Mar 17 04:37:25 1995 ylo
11
12Allocating a pseudo-terminal, and making it the controlling tty.
13
14*/
15
16#include "includes.h"
17RCSID("$Id: pty.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
18
19#include "pty.h"
20#include "ssh.h"
21
22/* Pty allocated with _getpty gets broken if we do I_PUSH:es to it. */
23#if defined(HAVE__GETPTY) || defined(HAVE_OPENPTY)
24#undef HAVE_DEV_PTMX
25#endif
26
27#ifndef O_NOCTTY
28#define O_NOCTTY 0
29#endif
30
31/* Allocates and opens a pty. Returns 0 if no pty could be allocated,
32 or nonzero if a pty was successfully allocated. On success, open file
33 descriptors for the pty and tty sides and the name of the tty side are
34 returned (the buffer must be able to hold at least 64 characters). */
35
36int pty_allocate(int *ptyfd, int *ttyfd, char *namebuf)
37{
38#ifdef HAVE_OPENPTY
39
40 /* openpty(3) exists in OSF/1 and some other os'es */
41
42 int i;
43
44 i = openpty(ptyfd, ttyfd, namebuf, NULL, NULL);
45
46 if (i < 0)
47 {
48 error("openpty: %.100s", strerror(errno));
49 return 0;
50 }
51
52 return 1;
53
54#else /* HAVE_OPENPTY */
55#ifdef HAVE__GETPTY
56
57 /* _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more
58 pty's automagically when needed */
59
60 char *slave;
61
62 slave = _getpty(ptyfd, O_RDWR, 0622, 0);
63 if (slave == NULL)
64 {
65 error("_getpty: %.100s", strerror(errno));
66 return 0;
67 }
68 strcpy(namebuf, slave);
69 /* Open the slave side. */
70 *ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
71 if (*ttyfd < 0)
72 {
73 error("%.200s: %.100s", namebuf, strerror(errno));
74 close(*ptyfd);
75 return 0;
76 }
77 return 1;
78
79#else /* HAVE__GETPTY */
80#ifdef HAVE_DEV_PTMX
81 /* This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 also has
82 bsd-style ptys, but they simply do not work.) */
83
84 int ptm;
85 char *pts;
86
87 ptm = open("/dev/ptmx", O_RDWR|O_NOCTTY);
88 if (ptm < 0)
89 {
90 error("/dev/ptmx: %.100s", strerror(errno));
91 return 0;
92 }
93 if (grantpt(ptm) < 0)
94 {
95 error("grantpt: %.100s", strerror(errno));
96 return 0;
97 }
98 if (unlockpt(ptm) < 0)
99 {
100 error("unlockpt: %.100s", strerror(errno));
101 return 0;
102 }
103 pts = ptsname(ptm);
104 if (pts == NULL)
105 error("Slave pty side name could not be obtained.");
106 strcpy(namebuf, pts);
107 *ptyfd = ptm;
108
109 /* Open the slave side. */
110 *ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
111 if (*ttyfd < 0)
112 {
113 error("%.100s: %.100s", namebuf, strerror(errno));
114 close(*ptyfd);
115 return 0;
116 }
117 /* Push the appropriate streams modules, as described in Solaris pts(7). */
118 if (ioctl(*ttyfd, I_PUSH, "ptem") < 0)
119 error("ioctl I_PUSH ptem: %.100s", strerror(errno));
120 if (ioctl(*ttyfd, I_PUSH, "ldterm") < 0)
121 error("ioctl I_PUSH ldterm: %.100s", strerror(errno));
122 if (ioctl(*ttyfd, I_PUSH, "ttcompat") < 0)
123 error("ioctl I_PUSH ttcompat: %.100s", strerror(errno));
124 return 1;
125
126#else /* HAVE_DEV_PTMX */
127#ifdef HAVE_DEV_PTS_AND_PTC
128
129 /* AIX-style pty code. */
130
131 const char *name;
132
133 *ptyfd = open("/dev/ptc", O_RDWR|O_NOCTTY);
134 if (*ptyfd < 0)
135 {
136 error("Could not open /dev/ptc: %.100s", strerror(errno));
137 return 0;
138 }
139 name = ttyname(*ptyfd);
140 if (!name)
141 fatal("Open of /dev/ptc returns device for which ttyname fails.");
142 strcpy(namebuf, name);
143 *ttyfd = open(name, O_RDWR|O_NOCTTY);
144 if (*ttyfd < 0)
145 {
146 error("Could not open pty slave side %.100s: %.100s",
147 name, strerror(errno));
148 close(*ptyfd);
149 return 0;
150 }
151 return 1;
152
153#else /* HAVE_DEV_PTS_AND_PTC */
154 /* BSD-style pty code. */
155
156 char buf[64];
157 int i;
158 const char *ptymajors =
159 "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ";
160 const char *ptyminors = "0123456789abcdef";
161 int num_minors = strlen(ptyminors);
162 int num_ptys = strlen(ptymajors) * num_minors;
163
164 for (i = 0; i < num_ptys; i++)
165 {
166 snprintf(buf, sizeof buf, "/dev/pty%c%c", ptymajors[i / num_minors],
167 ptyminors[i % num_minors]);
168 *ptyfd = open(buf, O_RDWR|O_NOCTTY);
169 if (*ptyfd < 0)
170 continue;
171 snprintf(namebuf, sizeof buf, "/dev/tty%c%c", ptymajors[i / num_minors],
172 ptyminors[i % num_minors]);
173
174 /* Open the slave side. */
175 *ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
176 if (*ttyfd < 0)
177 {
178 error("%.100s: %.100s", namebuf, strerror(errno));
179 close(*ptyfd);
180 return 0;
181 }
182 return 1;
183 }
184 return 0;
185#endif /* HAVE_DEV_PTS_AND_PTC */
186#endif /* HAVE_DEV_PTMX */
187#endif /* HAVE__GETPTY */
188#endif /* HAVE_OPENPTY */
189}
190
191/* Releases the tty. Its ownership is returned to root, and permissions to
192 0666. */
193
194void pty_release(const char *ttyname)
195{
196 if (chown(ttyname, (uid_t)0, (gid_t)0) < 0)
197 debug("chown %.100s 0 0 failed: %.100s", ttyname, strerror(errno));
198 if (chmod(ttyname, (mode_t)0666) < 0)
199 debug("chmod %.100s 0666 failed: %.100s", ttyname, strerror(errno));
200}
201
202/* Makes the tty the processes controlling tty and sets it to sane modes. */
203
204void pty_make_controlling_tty(int *ttyfd, const char *ttyname)
205{
206 int fd;
207
208 /* First disconnect from the old controlling tty. */
209#ifdef TIOCNOTTY
210 fd = open("/dev/tty", O_RDWR|O_NOCTTY);
211 if (fd >= 0)
212 {
213 (void)ioctl(fd, TIOCNOTTY, NULL);
214 close(fd);
215 }
216#endif /* TIOCNOTTY */
217 if (setsid() < 0)
218 error("setsid: %.100s", strerror(errno));
219
220 /* Verify that we are successfully disconnected from the controlling tty. */
221 fd = open("/dev/tty", O_RDWR|O_NOCTTY);
222 if (fd >= 0)
223 {
224 error("Failed to disconnect from controlling tty.");
225 close(fd);
226 }
227
228 /* Make it our controlling tty. */
229#ifdef TIOCSCTTY
230 debug("Setting controlling tty using TIOCSCTTY.");
231 /* We ignore errors from this, because HPSUX defines TIOCSCTTY, but returns
232 EINVAL with these arguments, and there is absolutely no documentation. */
233 ioctl(*ttyfd, TIOCSCTTY, NULL);
234#endif /* TIOCSCTTY */
235 fd = open(ttyname, O_RDWR);
236 if (fd < 0)
237 error("%.100s: %.100s", ttyname, strerror(errno));
238 else
239 close(fd);
240
241 /* Verify that we now have a controlling tty. */
242 fd = open("/dev/tty", O_WRONLY);
243 if (fd < 0)
244 error("open /dev/tty failed - could not set controlling tty: %.100s",
245 strerror(errno));
246 else
247 {
248 close(fd);
249 }
250}
251
252/* Changes the window size associated with the pty. */
253
254void pty_change_window_size(int ptyfd, int row, int col,
255 int xpixel, int ypixel)
256{
257 struct winsize w;
258 w.ws_row = row;
259 w.ws_col = col;
260 w.ws_xpixel = xpixel;
261 w.ws_ypixel = ypixel;
262 (void)ioctl(ptyfd, TIOCSWINSZ, &w);
263}
264
diff --git a/pty.h b/pty.h
new file mode 100644
index 000000000..20ee90a1d
--- /dev/null
+++ b/pty.h
@@ -0,0 +1,40 @@
1/*
2
3pty.h
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Fri Mar 17 05:03:28 1995 ylo
11
12Functions for allocating a pseudo-terminal and making it the controlling
13tty.
14
15*/
16
17/* RCSID("$Id: pty.h,v 1.1 1999/10/27 03:42:44 damien Exp $"); */
18
19#ifndef PTY_H
20#define PTY_H
21
22/* Allocates and opens a pty. Returns 0 if no pty could be allocated,
23 or nonzero if a pty was successfully allocated. On success, open file
24 descriptors for the pty and tty sides and the name of the tty side are
25 returned (the buffer must be able to hold at least 64 characters). */
26int pty_allocate(int *ptyfd, int *ttyfd, char *ttyname);
27
28/* Releases the tty. Its ownership is returned to root, and permissions to
29 0666. */
30void pty_release(const char *ttyname);
31
32/* Makes the tty the processes controlling tty and sets it to sane modes.
33 This may need to reopen the tty to get rid of possible eavesdroppers. */
34void pty_make_controlling_tty(int *ttyfd, const char *ttyname);
35
36/* Changes the window size associated with the pty. */
37void pty_change_window_size(int ptyfd, int row, int col,
38 int xpixel, int ypixel);
39
40#endif /* PTY_H */
diff --git a/radix.c b/radix.c
new file mode 100644
index 000000000..1c497945e
--- /dev/null
+++ b/radix.c
@@ -0,0 +1,258 @@
1/*
2 radix.c
3
4 base-64 encoding pinched from lynx2-7-2, who pinched it from rpem.
5 Originally written by Mark Riordan 12 August 1990 and 17 Feb 1991
6 and placed in the public domain.
7
8 Dug Song <dugsong@UMICH.EDU>
9*/
10
11#include "includes.h"
12
13#ifdef AFS
14#include <krb.h>
15
16char six2pr[64] = {
17 'A','B','C','D','E','F','G','H','I','J','K','L','M',
18 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
19 'a','b','c','d','e','f','g','h','i','j','k','l','m',
20 'n','o','p','q','r','s','t','u','v','w','x','y','z',
21 '0','1','2','3','4','5','6','7','8','9','+','/'
22};
23
24unsigned char pr2six[256];
25
26int uuencode(unsigned char *bufin, unsigned int nbytes, char *bufcoded)
27{
28 /* ENC is the basic 1 character encoding function to make a char printing */
29#define ENC(c) six2pr[c]
30
31 register char *outptr = bufcoded;
32 unsigned int i;
33
34 for (i=0; i<nbytes; i += 3) {
35 *(outptr++) = ENC(*bufin >> 2); /* c1 */
36 *(outptr++) = ENC(((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)); /*c2*/
37 *(outptr++) = ENC(((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03));/*c3*/
38 *(outptr++) = ENC(bufin[2] & 077); /* c4 */
39 bufin += 3;
40 }
41 if (i == nbytes+1) {
42 outptr[-1] = '=';
43 } else if (i == nbytes+2) {
44 outptr[-1] = '=';
45 outptr[-2] = '=';
46 }
47 *outptr = '\0';
48 return(outptr - bufcoded);
49}
50
51int uudecode(const char *bufcoded, unsigned char *bufplain, int outbufsize)
52{
53 /* single character decode */
54#define DEC(c) pr2six[(unsigned char)c]
55#define MAXVAL 63
56
57 static int first = 1;
58 int nbytesdecoded, j;
59 const char *bufin = bufcoded;
60 register unsigned char *bufout = bufplain;
61 register int nprbytes;
62
63 /* If this is the first call, initialize the mapping table. */
64 if (first) {
65 first = 0;
66 for(j=0; j<256; j++) pr2six[j] = MAXVAL+1;
67 for(j=0; j<64; j++) pr2six[(unsigned char)six2pr[j]] = (unsigned char)j;
68 }
69
70 /* Strip leading whitespace. */
71 while (*bufcoded==' ' || *bufcoded == '\t') bufcoded++;
72
73 /* Figure out how many characters are in the input buffer.
74 If this would decode into more bytes than would fit into
75 the output buffer, adjust the number of input bytes downwards. */
76 bufin = bufcoded;
77 while (DEC(*(bufin++)) <= MAXVAL);
78 nprbytes = bufin - bufcoded - 1;
79 nbytesdecoded = ((nprbytes+3)/4) * 3;
80 if (nbytesdecoded > outbufsize)
81 nprbytes = (outbufsize*4)/3;
82
83 bufin = bufcoded;
84
85 while (nprbytes > 0) {
86 *(bufout++) = (unsigned char) (DEC(*bufin) << 2 | DEC(bufin[1]) >> 4);
87 *(bufout++) = (unsigned char) (DEC(bufin[1]) << 4 | DEC(bufin[2]) >> 2);
88 *(bufout++) = (unsigned char) (DEC(bufin[2]) << 6 | DEC(bufin[3]));
89 bufin += 4;
90 nprbytes -= 4;
91 }
92 if (nprbytes & 03) {
93 if (DEC(bufin[-2]) > MAXVAL)
94 nbytesdecoded -= 2;
95 else
96 nbytesdecoded -= 1;
97 }
98 return(nbytesdecoded);
99}
100
101typedef unsigned char my_u_char;
102typedef unsigned int my_u_int32_t;
103typedef unsigned short my_u_short;
104
105/* Nasty macros from BIND-4.9.2 */
106
107#define GETSHORT(s, cp) { \
108 register my_u_char *t_cp = (my_u_char*)(cp); \
109 (s) = (((my_u_short)t_cp[0]) << 8) \
110 | (((my_u_short)t_cp[1])) \
111 ; \
112 (cp) += 2; \
113}
114
115#define GETLONG(l, cp) { \
116 register my_u_char *t_cp = (my_u_char*)(cp); \
117 (l) = (((my_u_int32_t)t_cp[0]) << 24) \
118 | (((my_u_int32_t)t_cp[1]) << 16) \
119 | (((my_u_int32_t)t_cp[2]) << 8) \
120 | (((my_u_int32_t)t_cp[3])) \
121 ; \
122 (cp) += 4; \
123}
124
125#define PUTSHORT(s, cp) { \
126 register my_u_short t_s = (my_u_short)(s); \
127 register my_u_char *t_cp = (my_u_char*)(cp); \
128 *t_cp++ = t_s >> 8; \
129 *t_cp = t_s; \
130 (cp) += 2; \
131}
132
133#define PUTLONG(l, cp) { \
134 register my_u_int32_t t_l = (my_u_int32_t)(l); \
135 register my_u_char *t_cp = (my_u_char*)(cp); \
136 *t_cp++ = t_l >> 24; \
137 *t_cp++ = t_l >> 16; \
138 *t_cp++ = t_l >> 8; \
139 *t_cp = t_l; \
140 (cp) += 4; \
141}
142
143#define GETSTRING(s, p, p_l) { \
144 register char* p_targ = (p) + p_l; \
145 register char* s_c = (s); \
146 register char* p_c = (p); \
147 while (*p_c && (p_c < p_targ)) { \
148 *s_c++ = *p_c++; \
149 } \
150 if (p_c == p_targ) { \
151 return 1; \
152 } \
153 *s_c = *p_c++; \
154 (p_l) = (p_l) - (p_c - (p)); \
155 (p) = p_c; \
156}
157
158
159int creds_to_radix(CREDENTIALS *creds, unsigned char *buf)
160{
161 char *p, *s;
162 int len;
163 char temp[2048];
164
165 p = temp;
166 *p++ = 1; /* version */
167 s = creds->service; while (*s) *p++ = *s++; *p++ = *s;
168 s = creds->instance; while (*s) *p++ = *s++; *p++ = *s;
169 s = creds->realm; while (*s) *p++ = *s++; *p++ = *s;
170
171 s = creds->pname; while (*s) *p++ = *s++; *p++ = *s;
172 s = creds->pinst; while (*s) *p++ = *s++; *p++ = *s;
173 /* Null string to repeat the realm. */
174 *p++ = '\0';
175
176 PUTLONG(creds->issue_date,p);
177 {
178 unsigned int endTime ;
179 endTime = (unsigned int)krb_life_to_time(creds->issue_date,
180 creds->lifetime);
181 PUTLONG(endTime,p);
182 }
183
184 memcpy(p,&creds->session, sizeof(creds->session));
185 p += sizeof(creds->session);
186
187 PUTSHORT(creds->kvno,p);
188 PUTLONG(creds->ticket_st.length,p);
189
190 memcpy(p,creds->ticket_st.dat, creds->ticket_st.length);
191 p += creds->ticket_st.length;
192 len = p - temp;
193
194 return(uuencode(temp, len, buf));
195}
196
197int radix_to_creds(const char *buf, CREDENTIALS *creds)
198{
199
200 char *p;
201 int len, tl;
202 char version;
203 char temp[2048];
204
205 if (!(len = uudecode(buf, temp, sizeof(temp))))
206 return 0;
207
208 p = temp;
209
210 /* check version and length! */
211 if (len < 1) return 0;
212 version = *p; p++; len--;
213
214 GETSTRING(creds->service, p, len);
215 GETSTRING(creds->instance, p, len);
216 GETSTRING(creds->realm, p, len);
217
218 GETSTRING(creds->pname, p, len);
219 GETSTRING(creds->pinst, p, len);
220 /* Ignore possibly different realm. */
221 while (*p && len) p++, len--;
222 if (len == 0) return 0;
223 p++, len--;
224
225 /* Enough space for remaining fixed-length parts? */
226 if (len < (4 + 4 + sizeof(creds->session) + 2 + 4))
227 return 0;
228
229 GETLONG(creds->issue_date,p);
230 len -= 4;
231 {
232 unsigned int endTime;
233 GETLONG(endTime,p);
234 len -= 4;
235 creds->lifetime = krb_time_to_life(creds->issue_date, endTime);
236 }
237
238 memcpy(&creds->session, p, sizeof(creds->session));
239 p += sizeof(creds->session);
240 len -= sizeof(creds->session);
241
242 GETSHORT(creds->kvno,p);
243 len -= 2;
244 GETLONG(creds->ticket_st.length,p);
245 len -= 4;
246
247 tl = creds->ticket_st.length;
248 if (tl < 0 || tl > len || tl > sizeof(creds->ticket_st.dat))
249 return 0;
250
251 memcpy(creds->ticket_st.dat, p, tl);
252 p += tl;
253 len -= tl;
254
255 return 1;
256}
257
258#endif /* AFS */
diff --git a/rc4.c b/rc4.c
new file mode 100644
index 000000000..a426188aa
--- /dev/null
+++ b/rc4.c
@@ -0,0 +1,105 @@
1/*! \file rc4.c
2 \brief Source file for RC4 stream cipher routines
3 \author Damien Miller <djm@mindrot.org>
4 \version 0.0.0
5 \date 1999
6
7 A simple implementation of the RC4 stream cipher, based on the
8 description given in _Bruce Schneier's_ "Applied Cryptography"
9 2nd edition.
10
11 Copyright 1999 Damien Miller
12
13 Permission is hereby granted, free of charge, to any person
14 obtaining a copy of this software and associated documentation
15 files (the "Software"), to deal in the Software without
16 restriction, including without limitation the rights to use, copy,
17 modify, merge, publish, distribute, sublicense, and/or sell copies
18 of the Software, and to permit persons to whom the Software is
19 furnished to do so, subject to the following conditions:
20
21 The above copyright notice and this permission notice shall be
22 included in all copies or substantial portions of the Software.
23
24 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
25 KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
26 WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
27 AND NONINFRINGEMENT. IN NO EVENT SHALL DAMIEN MILLER BE LIABLE
28 FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
29 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
32 \warning None of these functions clears its memory after use. It
33 \warning is the responsability of the calling routines to ensure
34 \warning that any sensitive data (keystream, key or plaintext) is
35 \warning properly erased after use.
36
37 \warning The name "RC4" is trademarked in the United States,
38 \warning you may need to use "RC4 compatible" or "ARC4"
39 \warning (Alleged RC4).
40*/
41
42/* $Id: rc4.c,v 1.1.1.1 1999/10/26 05:48:13 damien Exp $ */
43
44#include "rc4.h"
45
46
47void rc4_key(rc4_t *r, unsigned char *key, int len)
48{
49 int t;
50
51 for(r->i = 0; r->i < 256; r->i++)
52 r->s[r->i] = r->i;
53
54 r->j = 0;
55 for(r->i = 0; r->i < 256; r->i++)
56 {
57 r->j = (r->j + r->s[r->i] + key[r->i % len]) % 256;
58 t = r->s[r->i];
59 r->s[r->i] = r->s[r->j];
60 r->s[r->j] = t;
61 }
62 r->i = r->j = 0;
63}
64
65void rc4_crypt(rc4_t *r, unsigned char *plaintext, int len)
66{
67 int t;
68 int c;
69
70 c = 0;
71 while(c < len)
72 {
73 r->i = (r->i + 1) % 256;
74 r->j = (r->j + r->s[r->i]) % 256;
75 t = r->s[r->i];
76 r->s[r->i] = r->s[r->j];
77 r->s[r->j] = t;
78
79 t = (r->s[r->i] + r->s[r->j]) % 256;
80
81 plaintext[c] ^= r->s[t];
82 c++;
83 }
84}
85
86void rc4_getbytes(rc4_t *r, unsigned char *buffer, int len)
87{
88 int t;
89 int c;
90
91 c = 0;
92 while(c < len)
93 {
94 r->i = (r->i + 1) % 256;
95 r->j = (r->j + r->s[r->i]) % 256;
96 t = r->s[r->i];
97 r->s[r->i] = r->s[r->j];
98 r->s[r->j] = t;
99
100 t = (r->s[r->i] + r->s[r->j]) % 256;
101
102 buffer[c] = r->s[t];
103 c++;
104 }
105}
diff --git a/rc4.h b/rc4.h
new file mode 100644
index 000000000..904affec3
--- /dev/null
+++ b/rc4.h
@@ -0,0 +1,110 @@
1/*! \file rc4.h
2 \brief Header file for RC4 stream cipher routines
3 \author Damien Miller <djm@mindrot.org>
4 \version 0.0.0
5 \date 1999
6
7 A simple implementation of the RC4 stream cipher, based on the
8 description given in _Bruce Schneier's_ "Applied Cryptography"
9 2nd edition.
10
11 Copyright 1999 Damien Miller
12
13 Permission is hereby granted, free of charge, to any person
14 obtaining a copy of this software and associated documentation
15 files (the "Software"), to deal in the Software without
16 restriction, including without limitation the rights to use, copy,
17 modify, merge, publish, distribute, sublicense, and/or sell copies
18 of the Software, and to permit persons to whom the Software is
19 furnished to do so, subject to the following conditions:
20
21 The above copyright notice and this permission notice shall be
22 included in all copies or substantial portions of the Software.
23
24 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
25 KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
26 WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
27 AND NONINFRINGEMENT. IN NO EVENT SHALL DAMIEN MILLER BE LIABLE
28 FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
29 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
32 \warning None of these functions clears its memory after use. It
33 \warning is the responsability of the calling routines to ensure
34 \warning that any sensitive data (keystream, key or plaintext) is
35 \warning properly erased after use.
36
37 \warning The name "RC4" is trademarked in the United States,
38 \warning you may need to use "RC4 compatible" or "ARC4"
39 \warning (Alleged RC4).
40*/
41
42/* $Id: rc4.h,v 1.1.1.1 1999/10/26 05:48:13 damien Exp $ */
43
44#ifndef _RC4_H
45#define _RC4_H
46
47/*! \struct rc4_t
48 \brief RC4 stream cipher state object
49 \var s State array
50 \var i Monotonic index
51 \var j Randomised index
52
53 \warning This structure should not be accessed directly. To
54 \warning initialise a rc4_t object, you should use the rc4_key()
55 \warning function
56
57 This structure holds the current state of the RC4 algorithm.
58*/
59typedef struct
60{
61 unsigned int s[256];
62 int i;
63 int j;
64} rc4_t;
65
66/*! \fn void rc4_key(rc4_t *r, unsigned char *key, int len);
67 \brief Set up key structure of RC4 stream cipher
68 \param r pointer to RC4 structure to be seeded
69 \param key pointer to buffer containing raw key
70 \param len length of key
71
72 This function set the internal state of the RC4 data structure
73 pointed to by \a r using the specified \a key of length \a len.
74
75 This function can use up to 256 bytes of key, any more are ignored.
76
77 \warning Stream ciphers (such as RC4) can be insecure if the same
78 \warning key is used repeatedly. Ensure that any key specified has
79 \warning an reasonably sized Initialisation Vector component.
80*/
81void rc4_key(rc4_t *r, unsigned char *key, int len);
82
83/*! \fn rc4_crypt(rc4_t *r, unsigned char *plaintext, int len);
84 \brief Crypt bytes using RC4 algorithm
85 \param r pointer to RC4 structure to be used
86 \param plaintext Pointer to bytes to encrypt
87 \param len number of bytes to crypt
88
89 This function encrypts one or more bytes (pointed to by \a plaintext)
90 using the RC4 algorithm. \a r is a state structure that must be
91 initialiased using the rc4_key() function prior to use.
92
93 Since RC4 XORs each byte of plaintext with a byte of keystream,
94 this function can be used for both encryption and decryption.
95*/
96void rc4_crypt(rc4_t *r, unsigned char *plaintext, int len);
97
98/*! \fn rc4_getbytes(rc4_t *r, unsigned char *buffer, int len);
99 \brief Generate key stream using the RC4 stream cipher
100 \param r pointer to RC4 structure to be used
101 \param buffer pointer to buffer in which to deposit keystream
102 \param len number of bytes to deposit
103
104 This function gives access to the raw RC4 key stream. In this
105 consiguration RC4 can be used as a fast, strong pseudo-random
106 number generator with a very long period.
107*/
108void rc4_getbytes(rc4_t *r, unsigned char *buffer, int len);
109
110#endif /* _RC4_H */
diff --git a/readconf.c b/readconf.c
new file mode 100644
index 000000000..281548d2a
--- /dev/null
+++ b/readconf.c
@@ -0,0 +1,684 @@
1/*
2
3readconf.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Sat Apr 22 00:03:10 1995 ylo
11
12Functions for reading the configuration files.
13
14*/
15
16#include "includes.h"
17RCSID("$Id: readconf.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
18
19#include "ssh.h"
20#include "cipher.h"
21#include "readconf.h"
22#include "xmalloc.h"
23
24/* Format of the configuration file:
25
26 # Configuration data is parsed as follows:
27 # 1. command line options
28 # 2. user-specific file
29 # 3. system-wide file
30 # Any configuration value is only changed the first time it is set.
31 # Thus, host-specific definitions should be at the beginning of the
32 # configuration file, and defaults at the end.
33
34 # Host-specific declarations. These may override anything above. A single
35 # host may match multiple declarations; these are processed in the order
36 # that they are given in.
37
38 Host *.ngs.fi ngs.fi
39 FallBackToRsh no
40
41 Host fake.com
42 HostName another.host.name.real.org
43 User blaah
44 Port 34289
45 ForwardX11 no
46 ForwardAgent no
47
48 Host books.com
49 RemoteForward 9999 shadows.cs.hut.fi:9999
50 Cipher 3des
51
52 Host fascist.blob.com
53 Port 23123
54 User tylonen
55 RhostsAuthentication no
56 PasswordAuthentication no
57
58 Host puukko.hut.fi
59 User t35124p
60 ProxyCommand ssh-proxy %h %p
61
62 Host *.fr
63 UseRsh yes
64
65 Host *.su
66 Cipher none
67 PasswordAuthentication no
68
69 # Defaults for various options
70 Host *
71 ForwardAgent no
72 ForwardX11 yes
73 RhostsAuthentication yes
74 PasswordAuthentication yes
75 RSAAuthentication yes
76 RhostsRSAAuthentication yes
77 FallBackToRsh no
78 UseRsh no
79 StrictHostKeyChecking yes
80 KeepAlives no
81 IdentityFile ~/.ssh/identity
82 Port 22
83 EscapeChar ~
84
85*/
86
87/* Keyword tokens. */
88
89typedef enum
90{
91 oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
92 oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
93#ifdef KRB4
94 oKerberosAuthentication,
95#endif /* KRB4 */
96#ifdef AFS
97 oKerberosTgtPassing, oAFSTokenPassing,
98#endif
99 oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
100 oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
101 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
102 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
103 oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication,
104 oUsePrivilegedPort
105} OpCodes;
106
107/* Textual representations of the tokens. */
108
109static struct
110{
111 const char *name;
112 OpCodes opcode;
113} keywords[] =
114{
115 { "forwardagent", oForwardAgent },
116 { "forwardx11", oForwardX11 },
117 { "gatewayports", oGatewayPorts },
118 { "useprivilegedport", oUsePrivilegedPort },
119 { "rhostsauthentication", oRhostsAuthentication },
120 { "passwordauthentication", oPasswordAuthentication },
121 { "rsaauthentication", oRSAAuthentication },
122#ifdef KRB4
123 { "kerberosauthentication", oKerberosAuthentication },
124#endif /* KRB4 */
125#ifdef AFS
126 { "kerberostgtpassing", oKerberosTgtPassing },
127 { "afstokenpassing", oAFSTokenPassing },
128#endif
129 { "fallbacktorsh", oFallBackToRsh },
130 { "usersh", oUseRsh },
131 { "identityfile", oIdentityFile },
132 { "hostname", oHostName },
133 { "proxycommand", oProxyCommand },
134 { "port", oPort },
135 { "cipher", oCipher },
136 { "remoteforward", oRemoteForward },
137 { "localforward", oLocalForward },
138 { "user", oUser },
139 { "host", oHost },
140 { "escapechar", oEscapeChar },
141 { "rhostsrsaauthentication", oRhostsRSAAuthentication },
142 { "globalknownhostsfile", oGlobalKnownHostsFile },
143 { "userknownhostsfile", oUserKnownHostsFile },
144 { "connectionattempts", oConnectionAttempts },
145 { "batchmode", oBatchMode },
146 { "checkhostip", oCheckHostIP },
147 { "stricthostkeychecking", oStrictHostKeyChecking },
148 { "compression", oCompression },
149 { "compressionlevel", oCompressionLevel },
150 { "keepalive", oKeepAlives },
151 { "numberofpasswordprompts", oNumberOfPasswordPrompts },
152 { "tisauthentication", oTISAuthentication },
153 { NULL, 0 }
154};
155
156/* Characters considered whitespace in strtok calls. */
157#define WHITESPACE " \t\r\n"
158
159
160/* Adds a local TCP/IP port forward to options. Never returns if there
161 is an error. */
162
163void add_local_forward(Options *options, int port, const char *host,
164 int host_port)
165{
166 Forward *fwd;
167 extern uid_t original_real_uid;
168 if ((port & 0xffff) != port)
169 fatal("Requested forwarding of nonexistent port %d.", port);
170 if (port < IPPORT_RESERVED && original_real_uid != 0)
171 fatal("Privileged ports can only be forwarded by root.\n");
172 if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
173 fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
174 fwd = &options->local_forwards[options->num_local_forwards++];
175 fwd->port = port;
176 fwd->host = xstrdup(host);
177 fwd->host_port = host_port;
178}
179
180/* Adds a remote TCP/IP port forward to options. Never returns if there
181 is an error. */
182
183void add_remote_forward(Options *options, int port, const char *host,
184 int host_port)
185{
186 Forward *fwd;
187 if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
188 fatal("Too many remote forwards (max %d).",
189 SSH_MAX_FORWARDS_PER_DIRECTION);
190 fwd = &options->remote_forwards[options->num_remote_forwards++];
191 fwd->port = port;
192 fwd->host = xstrdup(host);
193 fwd->host_port = host_port;
194}
195
196/* Returns the number of the token pointed to by cp of length len.
197 Never returns if the token is not known. */
198
199static OpCodes parse_token(const char *cp, const char *filename, int linenum)
200{
201 unsigned int i;
202
203 for (i = 0; keywords[i].name; i++)
204 if (strcmp(cp, keywords[i].name) == 0)
205 return keywords[i].opcode;
206
207 fatal("%.200s line %d: Bad configuration option.",
208 filename, linenum);
209 /*NOTREACHED*/
210 return 0;
211}
212
213/* Processes a single option line as used in the configuration files.
214 This only sets those values that have not already been set. */
215
216void process_config_line(Options *options, const char *host,
217 char *line, const char *filename, int linenum,
218 int *activep)
219{
220 char buf[256], *cp, *string, **charptr;
221 int opcode, *intptr, value, fwd_port, fwd_host_port;
222
223 /* Skip leading whitespace. */
224 cp = line + strspn(line, WHITESPACE);
225 if (!*cp || *cp == '\n' || *cp == '#')
226 return;
227
228 /* Get the keyword. (Each line is supposed to begin with a keyword). */
229 cp = strtok(cp, WHITESPACE);
230 {
231 char *t = cp;
232 for (; *t != 0; t++)
233 if ('A' <= *t && *t <= 'Z')
234 *t = *t - 'A' + 'a'; /* tolower */
235
236 }
237 opcode = parse_token(cp, filename, linenum);
238
239 switch (opcode)
240 {
241
242 case oForwardAgent:
243 intptr = &options->forward_agent;
244 parse_flag:
245 cp = strtok(NULL, WHITESPACE);
246 if (!cp)
247 fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
248 value = 0; /* To avoid compiler warning... */
249 if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
250 value = 1;
251 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
252 value = 0;
253 else
254 fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
255 if (*activep && *intptr == -1)
256 *intptr = value;
257 break;
258
259 case oForwardX11:
260 intptr = &options->forward_x11;
261 goto parse_flag;
262
263 case oGatewayPorts:
264 intptr = &options->gateway_ports;
265 goto parse_flag;
266
267 case oUsePrivilegedPort:
268 intptr = &options->use_privileged_port;
269 goto parse_flag;
270
271 case oRhostsAuthentication:
272 intptr = &options->rhosts_authentication;
273 goto parse_flag;
274
275 case oPasswordAuthentication:
276 intptr = &options->password_authentication;
277 goto parse_flag;
278
279 case oRSAAuthentication:
280 intptr = &options->rsa_authentication;
281 goto parse_flag;
282
283 case oRhostsRSAAuthentication:
284 intptr = &options->rhosts_rsa_authentication;
285 goto parse_flag;
286
287#ifdef KRB4
288 case oKerberosAuthentication:
289 intptr = &options->kerberos_authentication;
290 goto parse_flag;
291#endif /* KRB4 */
292
293#ifdef AFS
294 case oKerberosTgtPassing:
295 intptr = &options->kerberos_tgt_passing;
296 goto parse_flag;
297
298 case oAFSTokenPassing:
299 intptr = &options->afs_token_passing;
300 goto parse_flag;
301#endif
302
303 case oFallBackToRsh:
304 intptr = &options->fallback_to_rsh;
305 goto parse_flag;
306
307 case oUseRsh:
308 intptr = &options->use_rsh;
309 goto parse_flag;
310
311 case oBatchMode:
312 intptr = &options->batch_mode;
313 goto parse_flag;
314
315 case oCheckHostIP:
316 intptr = &options->check_host_ip;
317 goto parse_flag;
318
319 case oStrictHostKeyChecking:
320 intptr = &options->strict_host_key_checking;
321 cp = strtok(NULL, WHITESPACE);
322 if (!cp)
323 fatal("%.200s line %d: Missing yes/no argument.",
324 filename, linenum);
325 value = 0; /* To avoid compiler warning... */
326 if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
327 value = 1;
328 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
329 value = 0;
330 else if (strcmp(cp, "ask") == 0)
331 value = 2;
332 else
333 fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
334 if (*activep && *intptr == -1)
335 *intptr = value;
336 break;
337
338 case oCompression:
339 intptr = &options->compression;
340 goto parse_flag;
341
342 case oKeepAlives:
343 intptr = &options->keepalives;
344 goto parse_flag;
345
346 case oNumberOfPasswordPrompts:
347 intptr = &options->number_of_password_prompts;
348 goto parse_int;
349
350 case oTISAuthentication:
351 cp = strtok(NULL, WHITESPACE);
352 if (cp != 0 && (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0))
353 fprintf(stderr,
354 "%.99s line %d: Warning, TIS is not supported.\n",
355 filename,
356 linenum);
357 break;
358
359 case oCompressionLevel:
360 intptr = &options->compression_level;
361 goto parse_int;
362
363 case oIdentityFile:
364 cp = strtok(NULL, WHITESPACE);
365 if (!cp)
366 fatal("%.200s line %d: Missing argument.", filename, linenum);
367 if (*activep)
368 {
369 if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
370 fatal("%.200s line %d: Too many identity files specified (max %d).",
371 filename, linenum, SSH_MAX_IDENTITY_FILES);
372 options->identity_files[options->num_identity_files++] = xstrdup(cp);
373 }
374 break;
375
376 case oUser:
377 charptr = &options->user;
378 parse_string:
379 cp = strtok(NULL, WHITESPACE);
380 if (!cp)
381 fatal("%.200s line %d: Missing argument.", filename, linenum);
382 if (*activep && *charptr == NULL)
383 *charptr = xstrdup(cp);
384 break;
385
386 case oGlobalKnownHostsFile:
387 charptr = &options->system_hostfile;
388 goto parse_string;
389
390 case oUserKnownHostsFile:
391 charptr = &options->user_hostfile;
392 goto parse_string;
393
394 case oHostName:
395 charptr = &options->hostname;
396 goto parse_string;
397
398 case oProxyCommand:
399 charptr = &options->proxy_command;
400 string = xstrdup("");
401 while ((cp = strtok(NULL, WHITESPACE)) != NULL)
402 {
403 string = xrealloc(string, strlen(string) + strlen(cp) + 2);
404 strcat(string, " ");
405 strcat(string, cp);
406 }
407 if (*activep && *charptr == NULL)
408 *charptr = string;
409 else
410 xfree(string);
411 return;
412
413 case oPort:
414 intptr = &options->port;
415 parse_int:
416 cp = strtok(NULL, WHITESPACE);
417 if (!cp)
418 fatal("%.200s line %d: Missing argument.", filename, linenum);
419 if (cp[0] < '0' || cp[0] > '9')
420 fatal("%.200s line %d: Bad number.", filename, linenum);
421#if 0
422 value = atoi(cp);
423#else
424 {
425 char *ptr;
426 value = strtol(cp, &ptr, 0); /* Octal, decimal, or hex format? */
427 if (cp == ptr)
428 fatal("%.200s line %d: Bad number.", filename, linenum);
429 }
430#endif
431 if (*activep && *intptr == -1)
432 *intptr = value;
433 break;
434
435 case oConnectionAttempts:
436 intptr = &options->connection_attempts;
437 goto parse_int;
438
439 case oCipher:
440 intptr = &options->cipher;
441 cp = strtok(NULL, WHITESPACE);
442 value = cipher_number(cp);
443 if (value == -1)
444 fatal("%.200s line %d: Bad cipher.", filename, linenum);
445 if (*activep && *intptr == -1)
446 *intptr = value;
447 break;
448
449 case oRemoteForward:
450 cp = strtok(NULL, WHITESPACE);
451 if (!cp)
452 fatal("%.200s line %d: Missing argument.", filename, linenum);
453 if (cp[0] < '0' || cp[0] > '9')
454 fatal("%.200s line %d: Badly formatted port number.",
455 filename, linenum);
456 fwd_port = atoi(cp);
457 cp = strtok(NULL, WHITESPACE);
458 if (!cp)
459 fatal("%.200s line %d: Missing second argument.",
460 filename, linenum);
461 if (sscanf(cp, "%255[^:]:%d", buf, &fwd_host_port) != 2)
462 fatal("%.200s line %d: Badly formatted host:port.",
463 filename, linenum);
464 if (*activep)
465 add_remote_forward(options, fwd_port, buf, fwd_host_port);
466 break;
467
468 case oLocalForward:
469 cp = strtok(NULL, WHITESPACE);
470 if (!cp)
471 fatal("%.200s line %d: Missing argument.", filename, linenum);
472 if (cp[0] < '0' || cp[0] > '9')
473 fatal("%.200s line %d: Badly formatted port number.",
474 filename, linenum);
475 fwd_port = atoi(cp);
476 cp = strtok(NULL, WHITESPACE);
477 if (!cp)
478 fatal("%.200s line %d: Missing second argument.",
479 filename, linenum);
480 if (sscanf(cp, "%255[^:]:%d", buf, &fwd_host_port) != 2)
481 fatal("%.200s line %d: Badly formatted host:port.",
482 filename, linenum);
483 if (*activep)
484 add_local_forward(options, fwd_port, buf, fwd_host_port);
485 break;
486
487 case oHost:
488 *activep = 0;
489 while ((cp = strtok(NULL, WHITESPACE)) != NULL)
490 if (match_pattern(host, cp))
491 {
492 debug("Applying options for %.100s", cp);
493 *activep = 1;
494 break;
495 }
496 /* Avoid garbage check below, as strtok already returned NULL. */
497 return;
498
499 case oEscapeChar:
500 intptr = &options->escape_char;
501 cp = strtok(NULL, WHITESPACE);
502 if (!cp)
503 fatal("%.200s line %d: Missing argument.", filename, linenum);
504 if (cp[0] == '^' && cp[2] == 0 &&
505 (unsigned char)cp[1] >= 64 && (unsigned char)cp[1] < 128)
506 value = (unsigned char)cp[1] & 31;
507 else
508 if (strlen(cp) == 1)
509 value = (unsigned char)cp[0];
510 else
511 if (strcmp(cp, "none") == 0)
512 value = -2;
513 else
514 {
515 fatal("%.200s line %d: Bad escape character.",
516 filename, linenum);
517 /*NOTREACHED*/
518 value = 0; /* Avoid compiler warning. */
519 }
520 if (*activep && *intptr == -1)
521 *intptr = value;
522 break;
523
524 default:
525 fatal("parse_config_file: Unimplemented opcode %d", opcode);
526 }
527
528 /* Check that there is no garbage at end of line. */
529 if (strtok(NULL, WHITESPACE) != NULL)
530 fatal("%.200s line %d: garbage at end of line.",
531 filename, linenum);
532}
533
534
535/* Reads the config file and modifies the options accordingly. Options should
536 already be initialized before this call. This never returns if there
537 is an error. If the file does not exist, this returns immediately. */
538
539void read_config_file(const char *filename, const char *host, Options *options)
540{
541 FILE *f;
542 char line[1024];
543 int active, linenum;
544
545 /* Open the file. */
546 f = fopen(filename, "r");
547 if (!f)
548 return;
549
550 debug("Reading configuration data %.200s", filename);
551
552 /* Mark that we are now processing the options. This flag is turned on/off
553 by Host specifications. */
554 active = 1;
555 linenum = 0;
556 while (fgets(line, sizeof(line), f))
557 {
558 /* Update line number counter. */
559 linenum++;
560
561 process_config_line(options, host, line, filename, linenum, &active);
562 }
563 fclose(f);
564}
565
566/* Initializes options to special values that indicate that they have not
567 yet been set. Read_config_file will only set options with this value.
568 Options are processed in the following order: command line, user config
569 file, system config file. Last, fill_default_options is called. */
570
571void initialize_options(Options *options)
572{
573 memset(options, 'X', sizeof(*options));
574 options->forward_agent = -1;
575 options->forward_x11 = -1;
576 options->gateway_ports = -1;
577 options->use_privileged_port = -1;
578 options->rhosts_authentication = -1;
579 options->rsa_authentication = -1;
580#ifdef KRB4
581 options->kerberos_authentication = -1;
582#endif
583#ifdef AFS
584 options->kerberos_tgt_passing = -1;
585 options->afs_token_passing = -1;
586#endif
587 options->password_authentication = -1;
588 options->rhosts_rsa_authentication = -1;
589 options->fallback_to_rsh = -1;
590 options->use_rsh = -1;
591 options->batch_mode = -1;
592 options->check_host_ip = -1;
593 options->strict_host_key_checking = -1;
594 options->compression = -1;
595 options->keepalives = -1;
596 options->compression_level = -1;
597 options->port = -1;
598 options->connection_attempts = -1;
599 options->number_of_password_prompts = -1;
600 options->cipher = -1;
601 options->num_identity_files = 0;
602 options->hostname = NULL;
603 options->proxy_command = NULL;
604 options->user = NULL;
605 options->escape_char = -1;
606 options->system_hostfile = NULL;
607 options->user_hostfile = NULL;
608 options->num_local_forwards = 0;
609 options->num_remote_forwards = 0;
610}
611
612/* Called after processing other sources of option data, this fills those
613 options for which no value has been specified with their default values. */
614
615void fill_default_options(Options *options)
616{
617 if (options->forward_agent == -1)
618 options->forward_agent = 1;
619 if (options->forward_x11 == -1)
620 options->forward_x11 = 1;
621 if (options->gateway_ports == -1)
622 options->gateway_ports = 0;
623 if (options->use_privileged_port == -1)
624 options->use_privileged_port = 1;
625 if (options->rhosts_authentication == -1)
626 options->rhosts_authentication = 1;
627 if (options->rsa_authentication == -1)
628 options->rsa_authentication = 1;
629#ifdef KRB4
630 if (options->kerberos_authentication == -1)
631 options->kerberos_authentication = 1;
632#endif /* KRB4 */
633#ifdef AFS
634 if (options->kerberos_tgt_passing == -1)
635 options->kerberos_tgt_passing = 1;
636 if (options->afs_token_passing == -1)
637 options->afs_token_passing = 1;
638#endif /* AFS */
639 if (options->password_authentication == -1)
640 options->password_authentication = 1;
641 if (options->rhosts_rsa_authentication == -1)
642 options->rhosts_rsa_authentication = 1;
643 if (options->fallback_to_rsh == -1)
644 options->fallback_to_rsh = 1;
645 if (options->use_rsh == -1)
646 options->use_rsh = 0;
647 if (options->batch_mode == -1)
648 options->batch_mode = 0;
649 if (options->check_host_ip == -1)
650 options->check_host_ip = 1;
651 if (options->strict_host_key_checking == -1)
652 options->strict_host_key_checking = 2; /* 2 is default */
653 if (options->compression == -1)
654 options->compression = 0;
655 if (options->keepalives == -1)
656 options->keepalives = 1;
657 if (options->compression_level == -1)
658 options->compression_level = 6;
659 if (options->port == -1)
660 options->port = 0; /* Filled in ssh_connect. */
661 if (options->connection_attempts == -1)
662 options->connection_attempts = 4;
663 if (options->number_of_password_prompts == -1)
664 options->number_of_password_prompts = 3;
665 if (options->cipher == -1)
666 options->cipher = SSH_CIPHER_NOT_SET; /* Selected in ssh_login(). */
667 if (options->num_identity_files == 0)
668 {
669 options->identity_files[0] =
670 xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1);
671 sprintf(options->identity_files[0], "~/%.100s", SSH_CLIENT_IDENTITY);
672 options->num_identity_files = 1;
673 }
674 if (options->escape_char == -1)
675 options->escape_char = '~';
676 if (options->system_hostfile == NULL)
677 options->system_hostfile = SSH_SYSTEM_HOSTFILE;
678 if (options->user_hostfile == NULL)
679 options->user_hostfile = SSH_USER_HOSTFILE;
680 /* options->proxy_command should not be set by default */
681 /* options->user will be set in the main program if appropriate */
682 /* options->hostname will be set in the main program if appropriate */
683}
684
diff --git a/readconf.h b/readconf.h
new file mode 100644
index 000000000..71655bd28
--- /dev/null
+++ b/readconf.h
@@ -0,0 +1,116 @@
1/*
2
3readconf.h
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Sat Apr 22 00:25:29 1995 ylo
11
12Functions for reading the configuration file.
13
14*/
15
16/* RCSID("$Id: readconf.h,v 1.1 1999/10/27 03:42:44 damien Exp $"); */
17
18#ifndef READCONF_H
19#define READCONF_H
20
21/* Data structure for representing a forwarding request. */
22
23typedef struct
24{
25 int port; /* Port to forward. */
26 char *host; /* Host to connect. */
27 int host_port; /* Port to connect on host. */
28} Forward;
29
30/* Data structure for representing option data. */
31
32typedef struct
33{
34 int forward_agent; /* Forward authentication agent. */
35 int forward_x11; /* Forward X11 display. */
36 int gateway_ports; /* Allow remote connects to forwarded ports. */
37 int use_privileged_port; /* Don't use privileged port if false. */
38 int rhosts_authentication; /* Try rhosts authentication. */
39 int rhosts_rsa_authentication;/* Try rhosts with RSA authentication. */
40 int rsa_authentication; /* Try RSA authentication. */
41#ifdef KRB4
42 int kerberos_authentication; /* Try Kerberos authentication. */
43#endif
44#ifdef AFS
45 int kerberos_tgt_passing; /* Try Kerberos tgt passing. */
46 int afs_token_passing; /* Try AFS token passing. */
47#endif
48 int password_authentication; /* Try password authentication. */
49 int fallback_to_rsh; /* Use rsh if cannot connect with ssh. */
50 int use_rsh; /* Always use rsh (don\'t try ssh). */
51 int batch_mode; /* Batch mode: do not ask for passwords. */
52 int check_host_ip; /* Also keep track of keys for IP address */
53 int strict_host_key_checking; /* Strict host key checking. */
54 int compression; /* Compress packets in both directions. */
55 int compression_level; /* Compression level 1 (fast) to 9 (best). */
56 int keepalives; /* Set SO_KEEPALIVE. */
57
58 int port; /* Port to connect. */
59 int connection_attempts; /* Max attempts (seconds) before giving up */
60 int number_of_password_prompts; /* Max number of password prompts. */
61 int cipher; /* Cipher to use. */
62 char *hostname; /* Real host to connect. */
63 char *proxy_command; /* Proxy command for connecting the host. */
64 char *user; /* User to log in as. */
65 int escape_char; /* Escape character; -2 = none */
66
67 char *system_hostfile; /* Path for /etc/ssh_known_hosts. */
68 char *user_hostfile; /* Path for $HOME/.ssh/known_hosts. */
69
70 int num_identity_files; /* Number of files for RSA identities. */
71 char *identity_files[SSH_MAX_IDENTITY_FILES];
72
73 /* Local TCP/IP forward requests. */
74 int num_local_forwards;
75 Forward local_forwards[SSH_MAX_FORWARDS_PER_DIRECTION];
76
77 /* Remote TCP/IP forward requests. */
78 int num_remote_forwards;
79 Forward remote_forwards[SSH_MAX_FORWARDS_PER_DIRECTION];
80} Options;
81
82
83/* Initializes options to special values that indicate that they have not
84 yet been set. Read_config_file will only set options with this value.
85 Options are processed in the following order: command line, user config
86 file, system config file. Last, fill_default_options is called. */
87void initialize_options(Options *options);
88
89/* Called after processing other sources of option data, this fills those
90 options for which no value has been specified with their default values. */
91void fill_default_options(Options *options);
92
93/* Processes a single option line as used in the configuration files.
94 This only sets those values that have not already been set. */
95void process_config_line(Options *options, const char *host,
96 char *line, const char *filename, int linenum,
97 int *activep);
98
99/* Reads the config file and modifies the options accordingly. Options should
100 already be initialized before this call. This never returns if there
101 is an error. If the file does not exist, this returns immediately. */
102void read_config_file(const char *filename, const char *host,
103 Options *options);
104
105/* Adds a local TCP/IP port forward to options. Never returns if there
106 is an error. */
107void add_local_forward(Options *options, int port, const char *host,
108 int host_port);
109
110/* Adds a remote TCP/IP port forward to options. Never returns if there
111 is an error. */
112void add_remote_forward(Options *options, int port, const char *host,
113 int host_port);
114
115
116#endif /* READCONF_H */
diff --git a/readpass.c b/readpass.c
new file mode 100644
index 000000000..3031825e5
--- /dev/null
+++ b/readpass.c
@@ -0,0 +1,114 @@
1/*
2
3readpass.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Mon Jul 10 22:08:59 1995 ylo
11
12Functions for reading passphrases and passwords.
13
14*/
15
16#include "includes.h"
17RCSID("$Id: readpass.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
18
19#include "xmalloc.h"
20#include "ssh.h"
21
22/* Saved old terminal mode for read_passphrase. */
23static struct termios saved_tio;
24
25/* Old interrupt signal handler for read_passphrase. */
26static void (*old_handler)(int sig) = NULL;
27
28/* Interrupt signal handler for read_passphrase. */
29
30void intr_handler(int sig)
31{
32 /* Restore terminal modes. */
33 tcsetattr(fileno(stdin), TCSANOW, &saved_tio);
34 /* Restore the old signal handler. */
35 signal(sig, old_handler);
36 /* Resend the signal, with the old handler. */
37 kill(getpid(), sig);
38}
39
40/* Reads a passphrase from /dev/tty with echo turned off. Returns the
41 passphrase (allocated with xmalloc). Exits if EOF is encountered.
42 The passphrase if read from stdin if from_stdin is true (as is the
43 case with ssh-keygen). */
44
45char *read_passphrase(const char *prompt, int from_stdin)
46{
47 char buf[1024], *cp;
48 struct termios tio;
49 FILE *f;
50
51 if (from_stdin)
52 f = stdin;
53 else
54 {
55 /* Read the passphrase from /dev/tty to make it possible to ask it even
56 when stdin has been redirected. */
57 f = fopen("/dev/tty", "r");
58 if (!f)
59 {
60 /* No controlling terminal and no DISPLAY. Nowhere to read. */
61 fprintf(stderr, "You have no controlling tty and no DISPLAY. Cannot read passphrase.\n");
62 exit(1);
63 }
64 }
65
66 /* Display the prompt (on stderr because stdout might be redirected). */
67 fflush(stdout);
68 fprintf(stderr, "%s", prompt);
69 fflush(stderr);
70
71 /* Get terminal modes. */
72 tcgetattr(fileno(f), &tio);
73 saved_tio = tio;
74 /* Save signal handler and set the new handler. */
75 old_handler = signal(SIGINT, intr_handler);
76
77 /* Set new terminal modes disabling all echo. */
78 tio.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
79 tcsetattr(fileno(f), TCSANOW, &tio);
80
81 /* Read the passphrase from the terminal. */
82 if (fgets(buf, sizeof(buf), f) == NULL)
83 {
84 /* Got EOF. Just exit. */
85 /* Restore terminal modes. */
86 tcsetattr(fileno(f), TCSANOW, &saved_tio);
87 /* Restore the signal handler. */
88 signal(SIGINT, old_handler);
89 /* Print a newline (the prompt probably didn\'t have one). */
90 fprintf(stderr, "\n");
91 /* Close the file. */
92 if (f != stdin)
93 fclose(f);
94 exit(1);
95 }
96 /* Restore terminal modes. */
97 tcsetattr(fileno(f), TCSANOW, &saved_tio);
98 /* Restore the signal handler. */
99 (void)signal(SIGINT, old_handler);
100 /* Remove newline from the passphrase. */
101 if (strchr(buf, '\n'))
102 *strchr(buf, '\n') = 0;
103 /* Allocate a copy of the passphrase. */
104 cp = xstrdup(buf);
105 /* Clear the buffer so we don\'t leave copies of the passphrase laying
106 around. */
107 memset(buf, 0, sizeof(buf));
108 /* Print a newline since the prompt probably didn\'t have one. */
109 fprintf(stderr, "\n");
110 /* Close the file. */
111 if (f != stdin)
112 fclose(f);
113 return cp;
114}
diff --git a/rsa.c b/rsa.c
new file mode 100644
index 000000000..6d4b70442
--- /dev/null
+++ b/rsa.c
@@ -0,0 +1,164 @@
1/*
2
3rsa.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Fri Mar 3 22:07:06 1995 ylo
11
12Description of the RSA algorithm can be found e.g. from the following sources:
13
14 Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1994.
15
16 Jennifer Seberry and Josed Pieprzyk: Cryptography: An Introduction to
17 Computer Security. Prentice-Hall, 1989.
18
19 Man Young Rhee: Cryptography and Secure Data Communications. McGraw-Hill,
20 1994.
21
22 R. Rivest, A. Shamir, and L. M. Adleman: Cryptographic Communications
23 System and Method. US Patent 4,405,829, 1983.
24
25 Hans Riesel: Prime Numbers and Computer Methods for Factorization.
26 Birkhauser, 1994.
27
28 The RSA Frequently Asked Questions document by RSA Data Security, Inc., 1995.
29
30 RSA in 3 lines of perl by Adam Back <aba@atlax.ex.ac.uk>, 1995, as included
31 below:
32
33 gone - had to be deleted - what a pity
34
35*/
36
37#include "includes.h"
38RCSID("$Id: rsa.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
39
40#include "rsa.h"
41#include "ssh.h"
42#include "xmalloc.h"
43
44int rsa_verbose = 1;
45
46int
47rsa_alive()
48{
49 RSA *key;
50
51 key = RSA_generate_key(32, 3, NULL, NULL);
52 if (key == NULL)
53 return (0);
54 RSA_free(key);
55 return (1);
56}
57
58/* Generates RSA public and private keys. This initializes the data
59 structures; they should be freed with rsa_clear_private_key and
60 rsa_clear_public_key. */
61
62void
63rsa_generate_key(RSA *prv, RSA *pub, unsigned int bits)
64{
65 RSA *key;
66
67 if (rsa_verbose) {
68 printf("Generating RSA keys: ");
69 fflush(stdout);
70 }
71
72 key = RSA_generate_key(bits, 35, NULL, NULL);
73
74 assert(key != NULL);
75
76 /* Copy public key parameters */
77 pub->n = BN_new();
78 BN_copy(pub->n, key->n);
79 pub->e = BN_new();
80 BN_copy(pub->e, key->e);
81
82 /* Copy private key parameters */
83 prv->n = BN_new();
84 BN_copy(prv->n, key->n);
85 prv->e = BN_new();
86 BN_copy(prv->e, key->e);
87 prv->d = BN_new();
88 BN_copy(prv->d, key->d);
89 prv->p = BN_new();
90 BN_copy(prv->p, key->p);
91 prv->q = BN_new();
92 BN_copy(prv->q, key->q);
93
94 prv->dmp1 = BN_new();
95 BN_copy(prv->dmp1, key->dmp1);
96
97 prv->dmq1 = BN_new();
98 BN_copy(prv->dmq1, key->dmq1);
99
100 prv->iqmp = BN_new();
101 BN_copy(prv->iqmp, key->iqmp);
102
103 RSA_free(key);
104
105 if (rsa_verbose)
106 printf("Key generation complete.\n");
107}
108
109void
110rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA* key)
111{
112 char *inbuf, *outbuf;
113 int len;
114
115 if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e))
116 fatal("rsa_public_encrypt() exponent too small or not odd");
117
118 len = BN_num_bytes(key->n);
119 outbuf = xmalloc(len);
120
121 len = BN_num_bytes(in);
122 inbuf = xmalloc(len);
123 BN_bn2bin(in, inbuf);
124
125 if ((len = RSA_public_encrypt(len, inbuf, outbuf, key,
126 RSA_PKCS1_PADDING)) <= 0)
127 fatal("rsa_public_encrypt() failed");
128
129 BN_bin2bn(outbuf, len, out);
130
131 xfree(outbuf);
132 xfree(inbuf);
133}
134
135void
136rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
137{
138 char *inbuf, *outbuf;
139 int len;
140
141 len = BN_num_bytes(key->n);
142 outbuf = xmalloc(len);
143
144 len = BN_num_bytes(in);
145 inbuf = xmalloc(len);
146 BN_bn2bin(in, inbuf);
147
148 if ((len = RSA_private_decrypt(len, inbuf, outbuf, key,
149 RSA_SSLV23_PADDING)) <= 0)
150 fatal("rsa_private_decrypt() failed");
151
152 BN_bin2bn(outbuf, len, out);
153
154 xfree(outbuf);
155 xfree(inbuf);
156}
157
158/* Set whether to output verbose messages during key generation. */
159
160void
161rsa_set_verbose(int verbose)
162{
163 rsa_verbose = verbose;
164}
diff --git a/rsa.h b/rsa.h
new file mode 100644
index 000000000..6aaabfae5
--- /dev/null
+++ b/rsa.h
@@ -0,0 +1,36 @@
1/*
2
3rsa.h
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Fri Mar 3 22:01:06 1995 ylo
11
12RSA key generation, encryption and decryption.
13
14*/
15
16/* RCSID("$Id: rsa.h,v 1.1 1999/10/27 03:42:44 damien Exp $"); */
17
18#ifndef RSA_H
19#define RSA_H
20
21#include <openssl/bn.h>
22#include <openssl/rsa.h>
23
24/* Calls SSL RSA_generate_key, only copies to prv and pub */
25void rsa_generate_key(RSA *prv, RSA *pub, unsigned int bits);
26
27/* Indicates whether the rsa module is permitted to show messages on
28 the terminal. */
29void rsa_set_verbose __P((int verbose));
30
31int rsa_alive __P((void));
32
33void rsa_public_encrypt __P((BIGNUM *out, BIGNUM *in, RSA *prv));
34void rsa_private_decrypt __P((BIGNUM *out, BIGNUM *in, RSA *prv));
35
36#endif /* RSA_H */
diff --git a/scp.1 b/scp.1
new file mode 100644
index 000000000..45cd2ad3d
--- /dev/null
+++ b/scp.1
@@ -0,0 +1,110 @@
1.\" -*- nroff -*-
2.\"
3.\" scp.1
4.\"
5.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
6.\"
7.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8.\" All rights reserved
9.\"
10.\" Created: Sun May 7 00:14:37 1995 ylo
11.\"
12.\" $Id: scp.1,v 1.1 1999/10/27 03:42:44 damien Exp $
13.\"
14.Dd September 25, 1999
15.Dt SCP 1
16.Os
17.Sh NAME
18.Nm scp
19.Nd secure copy (remote file copy program)
20.Sh SYNOPSIS
21.Nm scp
22.Op Fl pqrvC
23.Op Fl P Ar port
24.Op Fl c Ar cipher
25.Op Fl i Ar identity_file
26.Sm off
27.Oo
28.Op Ar user@
29.Ar host1 No :
30.Oc Ns Ar file1
31.Sm on
32.Op Ar ...
33.Sm off
34.Oo
35.Op Ar user@
36.Ar host2 No :
37.Oc Ar file2
38.Sm on
39.Sh DESCRIPTION
40.Nm
41copies files between hosts on a network. It uses
42.Xr ssh 1
43for data transfer, and uses the same authentication and provides the
44same security as
45.Xr ssh 1 .
46Unlike
47.Xr rcp 1 ,
48.Nm
49will ask for passwords or passphrases if they are needed for
50authentication.
51.Pp
52Any file name may contain a host and user specification to indicate
53that the file is to be copied to/from that host. Copies between two
54remote hosts are permitted.
55.Pp
56The options are as follows:
57.Bl -tag -width Ds
58.It Fl c Ar cipher
59Selects the cipher to use for encrypting the data transfer. This
60option is directly passed to
61.Xr ssh 1 .
62.It Fl i Ar identity_file
63Selects the file from which the identity (private key) for RSA
64authentication is read. This option is directly passed to
65.Xr ssh 1 .
66.It Fl p
67Preserves modification times, access times, and modes from the
68original file.
69.It Fl r
70Recursively copy entire directories.
71.It Fl v
72Verbose mode. Causes
73.Nm
74and
75.Xr ssh 1
76to print debugging messages about their progress. This is helpful in
77debugging connection, authentication, and configuration problems.
78.It Fl B
79Selects batch mode (prevents asking for passwords or passphrases).
80.It Fl q
81Disables the progress meter.
82.It Fl C
83Compression enable. Passes the
84.Fl C
85flag to
86.Xr ssh 1
87to enable compression.
88.It Fl P Ar port
89Specifies the port to connect to on the remote host. Note that this
90option is written with a capital
91.Sq P ,
92because
93.Fl p
94is already reserved for preserving the times and modes of the file in
95.Xr rcp 1 .
96.Sh AUTHORS
97Timo Rinne <tri@iki.fi> and Tatu Ylonen <ylo@cs.hut.fi>
98.Sh HISTORY
99.Nm
100is based on the
101.Xr rcp 1
102program in BSD source code from the Regents of the University of
103California.
104.Sh SEE ALSO
105.Xr rcp 1 ,
106.Xr ssh 1 ,
107.Xr ssh-add 1 ,
108.Xr ssh-agent 1 ,
109.Xr ssh-keygen 1 ,
110.Xr sshd 8
diff --git a/scp.c b/scp.c
new file mode 100644
index 000000000..6145fdebd
--- /dev/null
+++ b/scp.c
@@ -0,0 +1,1220 @@
1/*
2
3scp - secure remote copy. This is basically patched BSD rcp which uses ssh
4to do the data transfer (instead of using rcmd).
5
6NOTE: This version should NOT be suid root. (This uses ssh to do the transfer
7and ssh has the necessary privileges.)
8
91995 Timo Rinne <tri@iki.fi>, Tatu Ylonen <ylo@cs.hut.fi>
10
11*/
12
13/*
14 * Copyright (c) 1983, 1990, 1992, 1993, 1995
15 * The Regents of the University of California. All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
25 * 3. All advertising materials mentioning features or use of this software
26 * must display the following acknowledgement:
27 * This product includes software developed by the University of
28 * California, Berkeley and its contributors.
29 * 4. Neither the name of the University nor the names of its contributors
30 * may be used to endorse or promote products derived from this software
31 * without specific prior written permission.
32 *
33 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
34 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
37 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * SUCH DAMAGE.
44 *
45 * $Id: scp.c,v 1.1 1999/10/27 03:42:45 damien Exp $
46 */
47
48#include "includes.h"
49RCSID("$Id: scp.c,v 1.1 1999/10/27 03:42:45 damien Exp $");
50
51#include "ssh.h"
52#include "xmalloc.h"
53#include <utime.h>
54
55#define _PATH_CP "cp"
56
57/* For progressmeter() -- number of seconds before xfer considered "stalled" */
58#define STALLTIME 5
59
60/* Visual statistics about files as they are transferred. */
61void progressmeter(int);
62
63/* Returns width of the terminal (for progress meter calculations). */
64int getttywidth(void);
65
66/* Time a transfer started. */
67static struct timeval start;
68
69/* Number of bytes of current file transferred so far. */
70volatile unsigned long statbytes;
71
72/* Total size of current file. */
73unsigned long totalbytes = 0;
74
75/* Name of current file being transferred. */
76char *curfile;
77
78/* This is set to non-zero to enable verbose mode. */
79int verbose = 0;
80
81/* This is set to non-zero if compression is desired. */
82int compress = 0;
83
84/* This is set to zero if the progressmeter is not desired. */
85int showprogress = 1;
86
87/* This is set to non-zero if running in batch mode (that is, password
88 and passphrase queries are not allowed). */
89int batchmode = 0;
90
91/* This is set to the cipher type string if given on the command line. */
92char *cipher = NULL;
93
94/* This is set to the RSA authentication identity file name if given on
95 the command line. */
96char *identity = NULL;
97
98/* This is the port to use in contacting the remote site (is non-NULL). */
99char *port = NULL;
100
101/* This function executes the given command as the specified user on the given
102 host. This returns < 0 if execution fails, and >= 0 otherwise.
103 This assigns the input and output file descriptors on success. */
104
105int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
106{
107 int pin[2], pout[2], reserved[2];
108
109 if (verbose)
110 fprintf(stderr, "Executing: host %s, user %s, command %s\n",
111 host, remuser ? remuser : "(unspecified)", cmd);
112
113 /* Reserve two descriptors so that the real pipes won't get descriptors
114 0 and 1 because that will screw up dup2 below. */
115 pipe(reserved);
116
117 /* Create a socket pair for communicating with ssh. */
118 if (pipe(pin) < 0)
119 fatal("pipe: %s", strerror(errno));
120 if (pipe(pout) < 0)
121 fatal("pipe: %s", strerror(errno));
122
123 /* Free the reserved descriptors. */
124 close(reserved[0]);
125 close(reserved[1]);
126
127 /* For a child to execute the command on the remote host using ssh. */
128 if (fork() == 0)
129 {
130 char *args[100];
131 unsigned int i;
132
133 /* Child. */
134 close(pin[1]);
135 close(pout[0]);
136 dup2(pin[0], 0);
137 dup2(pout[1], 1);
138 close(pin[0]);
139 close(pout[1]);
140
141 i = 0;
142 args[i++] = SSH_PROGRAM;
143 args[i++] = "-x";
144 args[i++] = "-oFallBackToRsh no";
145 if (verbose)
146 args[i++] = "-v";
147 if (compress)
148 args[i++] = "-C";
149 if (batchmode)
150 args[i++] = "-oBatchMode yes";
151 if (cipher != NULL)
152 {
153 args[i++] = "-c";
154 args[i++] = cipher;
155 }
156 if (identity != NULL)
157 {
158 args[i++] = "-i";
159 args[i++] = identity;
160 }
161 if (port != NULL)
162 {
163 args[i++] = "-p";
164 args[i++] = port;
165 }
166 if (remuser != NULL)
167 {
168 args[i++] = "-l";
169 args[i++] = remuser;
170 }
171 args[i++] = host;
172 args[i++] = cmd;
173 args[i++] = NULL;
174
175 execvp(SSH_PROGRAM, args);
176 perror(SSH_PROGRAM);
177 exit(1);
178 }
179 /* Parent. Close the other side, and return the local side. */
180 close(pin[0]);
181 *fdout = pin[1];
182 close(pout[1]);
183 *fdin = pout[0];
184 return 0;
185}
186
187void fatal(const char *fmt, ...)
188{
189 va_list ap;
190 char buf[1024];
191
192 va_start(ap, fmt);
193 vsnprintf(buf, sizeof(buf), fmt, ap);
194 va_end(ap);
195 fprintf(stderr, "%s\n", buf);
196 exit(255);
197}
198
199/* This stuff used to be in BSD rcp extern.h. */
200
201typedef struct {
202 int cnt;
203 char *buf;
204} BUF;
205
206extern int iamremote;
207
208BUF *allocbuf(BUF *, int, int);
209char *colon(char *);
210void lostconn(int);
211void nospace(void);
212int okname(char *);
213void run_err(const char *, ...);
214void verifydir(char *);
215
216/* Stuff from BSD rcp.c continues. */
217
218struct passwd *pwd;
219uid_t userid;
220int errs, remin, remout;
221int pflag, iamremote, iamrecursive, targetshouldbedirectory;
222
223#define CMDNEEDS 64
224char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
225
226int response(void);
227void rsource(char *, struct stat *);
228void sink(int, char *[]);
229void source(int, char *[]);
230void tolocal(int, char *[]);
231void toremote(char *, int, char *[]);
232void usage(void);
233
234int
235main(argc, argv)
236 int argc;
237 char *argv[];
238{
239 int ch, fflag, tflag;
240 char *targ;
241 extern char *optarg;
242 extern int optind;
243
244 fflag = tflag = 0;
245 while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q")) != EOF)
246 switch(ch) { /* User-visible flags. */
247 case 'p':
248 pflag = 1;
249 break;
250 case 'P':
251 port = optarg;
252 break;
253 case 'r':
254 iamrecursive = 1;
255 break;
256 /* Server options. */
257 case 'd':
258 targetshouldbedirectory = 1;
259 break;
260 case 'f': /* "from" */
261 iamremote = 1;
262 fflag = 1;
263 break;
264 case 't': /* "to" */
265 iamremote = 1;
266 tflag = 1;
267 break;
268 case 'c':
269 cipher = optarg;
270 break;
271 case 'i':
272 identity = optarg;
273 break;
274 case 'v':
275 verbose = 1;
276 break;
277 case 'B':
278 batchmode = 1;
279 break;
280 case 'C':
281 compress = 1;
282 break;
283 case 'q':
284 showprogress = 0;
285 break;
286 case '?':
287 default:
288 usage();
289 }
290 argc -= optind;
291 argv += optind;
292
293 if ((pwd = getpwuid(userid = getuid())) == NULL)
294 fatal("unknown user %d", (int)userid);
295
296 if (! isatty(STDERR_FILENO))
297 showprogress = 0;
298
299 remin = STDIN_FILENO;
300 remout = STDOUT_FILENO;
301
302 if (fflag) { /* Follow "protocol", send data. */
303 (void)response();
304 source(argc, argv);
305 exit(errs != 0);
306 }
307
308 if (tflag) { /* Receive data. */
309 sink(argc, argv);
310 exit(errs != 0);
311 }
312
313 if (argc < 2)
314 usage();
315 if (argc > 2)
316 targetshouldbedirectory = 1;
317
318 remin = remout = -1;
319 /* Command to be executed on remote system using "ssh". */
320 (void)sprintf(cmd, "scp%s%s%s%s", verbose ? " -v" : "",
321 iamrecursive ? " -r" : "", pflag ? " -p" : "",
322 targetshouldbedirectory ? " -d" : "");
323
324 (void)signal(SIGPIPE, lostconn);
325
326 if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */
327 toremote(targ, argc, argv);
328 else {
329 tolocal(argc, argv); /* Dest is local host. */
330 if (targetshouldbedirectory)
331 verifydir(argv[argc - 1]);
332 }
333 exit(errs != 0);
334}
335
336void
337toremote(targ, argc, argv)
338 char *targ, *argv[];
339 int argc;
340{
341 int i, len;
342 char *bp, *host, *src, *suser, *thost, *tuser;
343
344 *targ++ = 0;
345 if (*targ == 0)
346 targ = ".";
347
348 if ((thost = strchr(argv[argc - 1], '@'))) {
349 /* user@host */
350 *thost++ = 0;
351 tuser = argv[argc - 1];
352 if (*tuser == '\0')
353 tuser = NULL;
354 else if (!okname(tuser))
355 exit(1);
356 } else {
357 thost = argv[argc - 1];
358 tuser = NULL;
359 }
360
361 for (i = 0; i < argc - 1; i++) {
362 src = colon(argv[i]);
363 if (src) { /* remote to remote */
364 *src++ = 0;
365 if (*src == 0)
366 src = ".";
367 host = strchr(argv[i], '@');
368 len = strlen(SSH_PROGRAM) + strlen(argv[i]) +
369 strlen(src) + (tuser ? strlen(tuser) : 0) +
370 strlen(thost) + strlen(targ) + CMDNEEDS + 32;
371 bp = xmalloc(len);
372 if (host) {
373 *host++ = 0;
374 suser = argv[i];
375 if (*suser == '\0')
376 suser = pwd->pw_name;
377 else if (!okname(suser))
378 continue;
379 (void)sprintf(bp,
380 "%s%s -x -o'FallBackToRsh no' -n -l %s %s %s %s '%s%s%s:%s'",
381 SSH_PROGRAM, verbose ? " -v" : "",
382 suser, host, cmd, src,
383 tuser ? tuser : "", tuser ? "@" : "",
384 thost, targ);
385 } else
386 (void)sprintf(bp,
387 "exec %s%s -x -o'FallBackToRsh no' -n %s %s %s '%s%s%s:%s'",
388 SSH_PROGRAM, verbose ? " -v" : "",
389 argv[i], cmd, src,
390 tuser ? tuser : "", tuser ? "@" : "",
391 thost, targ);
392 if (verbose)
393 fprintf(stderr, "Executing: %s\n", bp);
394 (void)system(bp);
395 (void)xfree(bp);
396 } else { /* local to remote */
397 if (remin == -1) {
398 len = strlen(targ) + CMDNEEDS + 20;
399 bp = xmalloc(len);
400 (void)sprintf(bp, "%s -t %s", cmd, targ);
401 host = thost;
402 if (do_cmd(host, tuser,
403 bp, &remin, &remout) < 0)
404 exit(1);
405 if (response() < 0)
406 exit(1);
407 (void)xfree(bp);
408 }
409 source(1, argv+i);
410 }
411 }
412}
413
414void
415tolocal(argc, argv)
416 int argc;
417 char *argv[];
418{
419 int i, len;
420 char *bp, *host, *src, *suser;
421
422 for (i = 0; i < argc - 1; i++) {
423 if (!(src = colon(argv[i]))) { /* Local to local. */
424 len = strlen(_PATH_CP) + strlen(argv[i]) +
425 strlen(argv[argc - 1]) + 20;
426 bp = xmalloc(len);
427 (void)sprintf(bp, "exec %s%s%s %s %s", _PATH_CP,
428 iamrecursive ? " -r" : "", pflag ? " -p" : "",
429 argv[i], argv[argc - 1]);
430 if (verbose)
431 fprintf(stderr, "Executing: %s\n", bp);
432 if (system(bp))
433 ++errs;
434 (void)xfree(bp);
435 continue;
436 }
437 *src++ = 0;
438 if (*src == 0)
439 src = ".";
440 if ((host = strchr(argv[i], '@')) == NULL) {
441 host = argv[i];
442 suser = NULL;
443 } else {
444 *host++ = 0;
445 suser = argv[i];
446 if (*suser == '\0')
447 suser = pwd->pw_name;
448 else if (!okname(suser))
449 continue;
450 }
451 len = strlen(src) + CMDNEEDS + 20;
452 bp = xmalloc(len);
453 (void)sprintf(bp, "%s -f %s", cmd, src);
454 if (do_cmd(host, suser, bp, &remin, &remout) < 0) {
455 (void)xfree(bp);
456 ++errs;
457 continue;
458 }
459 xfree(bp);
460 sink(1, argv + argc - 1);
461 (void)close(remin);
462 remin = remout = -1;
463 }
464}
465
466void
467source(argc, argv)
468 int argc;
469 char *argv[];
470{
471 struct stat stb;
472 static BUF buffer;
473 BUF *bp;
474 off_t i;
475 int amt, fd, haderr, indx, result;
476 char *last, *name, buf[2048];
477
478 for (indx = 0; indx < argc; ++indx) {
479 name = argv[indx];
480 statbytes = 0;
481 if ((fd = open(name, O_RDONLY, 0)) < 0)
482 goto syserr;
483 if (fstat(fd, &stb) < 0) {
484syserr: run_err("%s: %s", name, strerror(errno));
485 goto next;
486 }
487 switch (stb.st_mode & S_IFMT) {
488 case S_IFREG:
489 break;
490 case S_IFDIR:
491 if (iamrecursive) {
492 rsource(name, &stb);
493 goto next;
494 }
495 /* FALLTHROUGH */
496 default:
497 run_err("%s: not a regular file", name);
498 goto next;
499 }
500 if ((last = strrchr(name, '/')) == NULL)
501 last = name;
502 else
503 ++last;
504 curfile = last;
505 if (pflag) {
506 /*
507 * Make it compatible with possible future
508 * versions expecting microseconds.
509 */
510 (void)sprintf(buf, "T%lu 0 %lu 0\n",
511 (unsigned long)stb.st_mtime,
512 (unsigned long)stb.st_atime);
513 (void)write(remout, buf, strlen(buf));
514 if (response() < 0)
515 goto next;
516 }
517#define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
518 (void)sprintf(buf, "C%04o %lu %s\n",
519 (unsigned int)(stb.st_mode & FILEMODEMASK),
520 (unsigned long)stb.st_size,
521 last);
522 if (verbose)
523 {
524 fprintf(stderr, "Sending file modes: %s", buf);
525 fflush(stderr);
526 }
527 (void)write(remout, buf, strlen(buf));
528 if (response() < 0)
529 goto next;
530 if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) {
531next: (void)close(fd);
532 continue;
533 }
534
535 if (showprogress) {
536 totalbytes = stb.st_size;
537 progressmeter(-1);
538 }
539
540 /* Keep writing after an error so that we stay sync'd up. */
541 for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
542 amt = bp->cnt;
543 if (i + amt > stb.st_size)
544 amt = stb.st_size - i;
545 if (!haderr) {
546 result = read(fd, bp->buf, amt);
547 if (result != amt)
548 haderr = result >= 0 ? EIO : errno;
549 }
550 if (haderr)
551 (void)write(remout, bp->buf, amt);
552 else {
553 result = write(remout, bp->buf, amt);
554 if (result != amt)
555 haderr = result >= 0 ? EIO : errno;
556 statbytes += result;
557 }
558 }
559 if(showprogress)
560 progressmeter(1);
561
562 if (close(fd) < 0 && !haderr)
563 haderr = errno;
564 if (!haderr)
565 (void)write(remout, "", 1);
566 else
567 run_err("%s: %s", name, strerror(haderr));
568 (void)response();
569 }
570}
571
572void
573rsource(name, statp)
574 char *name;
575 struct stat *statp;
576{
577 DIR *dirp;
578 struct dirent *dp;
579 char *last, *vect[1], path[1100];
580
581 if (!(dirp = opendir(name))) {
582 run_err("%s: %s", name, strerror(errno));
583 return;
584 }
585 last = strrchr(name, '/');
586 if (last == 0)
587 last = name;
588 else
589 last++;
590 if (pflag) {
591 (void)sprintf(path, "T%lu 0 %lu 0\n",
592 (unsigned long)statp->st_mtime,
593 (unsigned long)statp->st_atime);
594 (void)write(remout, path, strlen(path));
595 if (response() < 0) {
596 closedir(dirp);
597 return;
598 }
599 }
600 (void)sprintf(path,
601 "D%04o %d %.1024s\n", (unsigned int)(statp->st_mode & FILEMODEMASK),
602 0, last);
603 if (verbose)
604 fprintf(stderr, "Entering directory: %s", path);
605 (void)write(remout, path, strlen(path));
606 if (response() < 0) {
607 closedir(dirp);
608 return;
609 }
610 while ((dp = readdir(dirp))) {
611 if (dp->d_ino == 0)
612 continue;
613 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
614 continue;
615 if (strlen(name) + 1 + strlen(dp->d_name) >= sizeof(path) - 1) {
616 run_err("%s/%s: name too long", name, dp->d_name);
617 continue;
618 }
619 (void)sprintf(path, "%s/%s", name, dp->d_name);
620 vect[0] = path;
621 source(1, vect);
622 }
623 (void)closedir(dirp);
624 (void)write(remout, "E\n", 2);
625 (void)response();
626}
627
628void
629sink(argc, argv)
630 int argc;
631 char *argv[];
632{
633 static BUF buffer;
634 struct stat stb;
635 enum { YES, NO, DISPLAYED } wrerr;
636 BUF *bp;
637 off_t i, j;
638 int amt, count, exists, first, mask, mode, ofd, omode;
639 int setimes, size, targisdir, wrerrno = 0;
640 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048];
641 struct utimbuf ut;
642 int dummy_usec;
643
644#define SCREWUP(str) { why = str; goto screwup; }
645
646 setimes = targisdir = 0;
647 mask = umask(0);
648 if (!pflag)
649 (void)umask(mask);
650 if (argc != 1) {
651 run_err("ambiguous target");
652 exit(1);
653 }
654 targ = *argv;
655 if (targetshouldbedirectory)
656 verifydir(targ);
657
658 (void)write(remout, "", 1);
659 if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
660 targisdir = 1;
661 for (first = 1;; first = 0) {
662 cp = buf;
663 if (read(remin, cp, 1) <= 0)
664 return;
665 if (*cp++ == '\n')
666 SCREWUP("unexpected <newline>");
667 do {
668 if (read(remin, &ch, sizeof(ch)) != sizeof(ch))
669 SCREWUP("lost connection");
670 *cp++ = ch;
671 } while (cp < &buf[sizeof(buf) - 1] && ch != '\n');
672 *cp = 0;
673
674 if (buf[0] == '\01' || buf[0] == '\02') {
675 if (iamremote == 0)
676 (void)write(STDERR_FILENO,
677 buf + 1, strlen(buf + 1));
678 if (buf[0] == '\02')
679 exit(1);
680 ++errs;
681 continue;
682 }
683 if (buf[0] == 'E') {
684 (void)write(remout, "", 1);
685 return;
686 }
687
688 if (ch == '\n')
689 *--cp = 0;
690
691#define getnum(t) (t) = 0; \
692 while (*cp >= '0' && *cp <= '9') (t) = (t) * 10 + (*cp++ - '0');
693 cp = buf;
694 if (*cp == 'T') {
695 setimes++;
696 cp++;
697 getnum(ut.modtime);
698 if (*cp++ != ' ')
699 SCREWUP("mtime.sec not delimited");
700 getnum(dummy_usec);
701 if (*cp++ != ' ')
702 SCREWUP("mtime.usec not delimited");
703 getnum(ut.actime);
704 if (*cp++ != ' ')
705 SCREWUP("atime.sec not delimited");
706 getnum(dummy_usec);
707 if (*cp++ != '\0')
708 SCREWUP("atime.usec not delimited");
709 (void)write(remout, "", 1);
710 continue;
711 }
712 if (*cp != 'C' && *cp != 'D') {
713 /*
714 * Check for the case "rcp remote:foo\* local:bar".
715 * In this case, the line "No match." can be returned
716 * by the shell before the rcp command on the remote is
717 * executed so the ^Aerror_message convention isn't
718 * followed.
719 */
720 if (first) {
721 run_err("%s", cp);
722 exit(1);
723 }
724 SCREWUP("expected control record");
725 }
726 mode = 0;
727 for (++cp; cp < buf + 5; cp++) {
728 if (*cp < '0' || *cp > '7')
729 SCREWUP("bad mode");
730 mode = (mode << 3) | (*cp - '0');
731 }
732 if (*cp++ != ' ')
733 SCREWUP("mode not delimited");
734
735 for (size = 0; *cp >= '0' && *cp <= '9';)
736 size = size * 10 + (*cp++ - '0');
737 if (*cp++ != ' ')
738 SCREWUP("size not delimited");
739 if (targisdir) {
740 static char *namebuf;
741 static int cursize;
742 size_t need;
743
744 need = strlen(targ) + strlen(cp) + 250;
745 if (need > cursize)
746 namebuf = xmalloc(need);
747 (void)sprintf(namebuf, "%s%s%s", targ,
748 *targ ? "/" : "", cp);
749 np = namebuf;
750 } else
751 np = targ;
752 curfile = cp;
753 exists = stat(np, &stb) == 0;
754 if (buf[0] == 'D') {
755 int mod_flag = pflag;
756 if (exists) {
757 if (!S_ISDIR(stb.st_mode)) {
758 errno = ENOTDIR;
759 goto bad;
760 }
761 if (pflag)
762 (void)chmod(np, mode);
763 } else {
764 /* Handle copying from a read-only directory */
765 mod_flag = 1;
766 if (mkdir(np, mode | S_IRWXU) < 0)
767 goto bad;
768 }
769 vect[0] = np;
770 sink(1, vect);
771 if (setimes) {
772 setimes = 0;
773 if (utime(np, &ut) < 0)
774 run_err("%s: set times: %s",
775 np, strerror(errno));
776 }
777 if (mod_flag)
778 (void)chmod(np, mode);
779 continue;
780 }
781 omode = mode;
782 mode |= S_IWRITE;
783 if ((ofd = open(np, O_WRONLY|O_CREAT|O_TRUNC, mode)) < 0) {
784bad: run_err("%s: %s", np, strerror(errno));
785 continue;
786 }
787 (void)write(remout, "", 1);
788 if ((bp = allocbuf(&buffer, ofd, 4096)) == NULL) {
789 (void)close(ofd);
790 continue;
791 }
792 cp = bp->buf;
793 wrerr = NO;
794
795 if (showprogress) {
796 totalbytes = size;
797 progressmeter(-1);
798 }
799 statbytes = 0;
800 for (count = i = 0; i < size; i += 4096) {
801 amt = 4096;
802 if (i + amt > size)
803 amt = size - i;
804 count += amt;
805 do {
806 j = read(remin, cp, amt);
807 if (j <= 0) {
808 run_err("%s", j ? strerror(errno) :
809 "dropped connection");
810 exit(1);
811 }
812 amt -= j;
813 cp += j;
814 statbytes += j;
815 } while (amt > 0);
816 if (count == bp->cnt) {
817 /* Keep reading so we stay sync'd up. */
818 if (wrerr == NO) {
819 j = write(ofd, bp->buf, count);
820 if (j != count) {
821 wrerr = YES;
822 wrerrno = j >= 0 ? EIO : errno;
823 }
824 }
825 count = 0;
826 cp = bp->buf;
827 }
828 }
829 if (showprogress)
830 progressmeter(1);
831 if (count != 0 && wrerr == NO &&
832 (j = write(ofd, bp->buf, count)) != count) {
833 wrerr = YES;
834 wrerrno = j >= 0 ? EIO : errno;
835 }
836#if 0
837 if (ftruncate(ofd, size)) {
838 run_err("%s: truncate: %s", np, strerror(errno));
839 wrerr = DISPLAYED;
840 }
841#endif
842 if (pflag) {
843 if (exists || omode != mode)
844 if (fchmod(ofd, omode))
845 run_err("%s: set mode: %s",
846 np, strerror(errno));
847 } else {
848 if (!exists && omode != mode)
849 if (fchmod(ofd, omode & ~mask))
850 run_err("%s: set mode: %s",
851 np, strerror(errno));
852 }
853 (void)close(ofd);
854 (void)response();
855 if (setimes && wrerr == NO) {
856 setimes = 0;
857 if (utime(np, &ut) < 0) {
858 run_err("%s: set times: %s",
859 np, strerror(errno));
860 wrerr = DISPLAYED;
861 }
862 }
863 switch(wrerr) {
864 case YES:
865 run_err("%s: %s", np, strerror(wrerrno));
866 break;
867 case NO:
868 (void)write(remout, "", 1);
869 break;
870 case DISPLAYED:
871 break;
872 }
873 }
874screwup:
875 run_err("protocol error: %s", why);
876 exit(1);
877}
878
879int
880response()
881{
882 char ch, *cp, resp, rbuf[2048];
883
884 if (read(remin, &resp, sizeof(resp)) != sizeof(resp))
885 lostconn(0);
886
887 cp = rbuf;
888 switch(resp) {
889 case 0: /* ok */
890 return (0);
891 default:
892 *cp++ = resp;
893 /* FALLTHROUGH */
894 case 1: /* error, followed by error msg */
895 case 2: /* fatal error, "" */
896 do {
897 if (read(remin, &ch, sizeof(ch)) != sizeof(ch))
898 lostconn(0);
899 *cp++ = ch;
900 } while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n');
901
902 if (!iamremote)
903 (void)write(STDERR_FILENO, rbuf, cp - rbuf);
904 ++errs;
905 if (resp == 1)
906 return (-1);
907 exit(1);
908 }
909 /* NOTREACHED */
910}
911
912void
913usage()
914{
915 (void)fprintf(stderr,
916 "usage: scp [-pqrvC] [-P port] [-c cipher] [-i identity] f1 f2; or:\n scp [options] f1 ... fn directory\n");
917 exit(1);
918}
919
920void
921run_err(const char *fmt, ...)
922{
923 static FILE *fp;
924 va_list ap;
925 va_start(ap, fmt);
926
927 ++errs;
928 if (fp == NULL && !(fp = fdopen(remout, "w")))
929 return;
930 (void)fprintf(fp, "%c", 0x01);
931 (void)fprintf(fp, "scp: ");
932 (void)vfprintf(fp, fmt, ap);
933 (void)fprintf(fp, "\n");
934 (void)fflush(fp);
935
936 if (!iamremote)
937 {
938 vfprintf(stderr, fmt, ap);
939 fprintf(stderr, "\n");
940 }
941
942 va_end(ap);
943}
944
945/* Stuff below is from BSD rcp util.c. */
946
947/*-
948 * Copyright (c) 1992, 1993
949 * The Regents of the University of California. All rights reserved.
950 *
951 * Redistribution and use in source and binary forms, with or without
952 * modification, are permitted provided that the following conditions
953 * are met:
954 * 1. Redistributions of source code must retain the above copyright
955 * notice, this list of conditions and the following disclaimer.
956 * 2. Redistributions in binary form must reproduce the above copyright
957 * notice, this list of conditions and the following disclaimer in the
958 * documentation and/or other materials provided with the distribution.
959 * 3. All advertising materials mentioning features or use of this software
960 * must display the following acknowledgement:
961 * This product includes software developed by the University of
962 * California, Berkeley and its contributors.
963 * 4. Neither the name of the University nor the names of its contributors
964 * may be used to endorse or promote products derived from this software
965 * without specific prior written permission.
966 *
967 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
968 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
969 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
970 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
971 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
972 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
973 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
974 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
975 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
976 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
977 * SUCH DAMAGE.
978 *
979 * $Id: scp.c,v 1.1 1999/10/27 03:42:45 damien Exp $
980 */
981
982char *
983colon(cp)
984 char *cp;
985{
986 if (*cp == ':') /* Leading colon is part of file name. */
987 return (0);
988
989 for (; *cp; ++cp) {
990 if (*cp == ':')
991 return (cp);
992 if (*cp == '/')
993 return (0);
994 }
995 return (0);
996}
997
998void
999verifydir(cp)
1000 char *cp;
1001{
1002 struct stat stb;
1003
1004 if (!stat(cp, &stb)) {
1005 if (S_ISDIR(stb.st_mode))
1006 return;
1007 errno = ENOTDIR;
1008 }
1009 run_err("%s: %s", cp, strerror(errno));
1010 exit(1);
1011}
1012
1013int
1014okname(cp0)
1015 char *cp0;
1016{
1017 int c;
1018 char *cp;
1019
1020 cp = cp0;
1021 do {
1022 c = *cp;
1023 if (c & 0200)
1024 goto bad;
1025 if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-')
1026 goto bad;
1027 } while (*++cp);
1028 return (1);
1029
1030bad: fprintf(stderr, "%s: invalid user name", cp0);
1031 return (0);
1032}
1033
1034BUF *
1035allocbuf(bp, fd, blksize)
1036 BUF *bp;
1037 int fd, blksize;
1038{
1039 size_t size;
1040 struct stat stb;
1041
1042 if (fstat(fd, &stb) < 0) {
1043 run_err("fstat: %s", strerror(errno));
1044 return (0);
1045 }
1046 if (stb.st_blksize == 0)
1047 size = blksize;
1048 else
1049 size = blksize + (stb.st_blksize - blksize % stb.st_blksize) %
1050 stb.st_blksize;
1051 if (bp->cnt >= size)
1052 return (bp);
1053 if (bp->buf == NULL)
1054 bp->buf = xmalloc(size);
1055 else
1056 bp->buf = xrealloc(bp->buf, size);
1057 bp->cnt = size;
1058 return (bp);
1059}
1060
1061void
1062lostconn(signo)
1063 int signo;
1064{
1065 if (!iamremote)
1066 fprintf(stderr, "lost connection\n");
1067 exit(1);
1068}
1069
1070/*
1071 * ensure all of data on socket comes through. f==read || f==write
1072 */
1073int
1074atomicio(f, fd, s, n)
1075int (*f)();
1076char *s;
1077{
1078 int res, pos = 0;
1079
1080 while (n>pos) {
1081 res = (f)(fd, s+pos, n-pos);
1082 switch (res) {
1083 case -1:
1084 if (errno==EINTR || errno==EAGAIN)
1085 continue;
1086 case 0:
1087 return (res);
1088 default:
1089 pos += res;
1090 }
1091 }
1092 return (pos);
1093}
1094
1095void
1096alarmtimer(int wait)
1097{
1098 struct itimerval itv;
1099
1100 itv.it_value.tv_sec = wait;
1101 itv.it_value.tv_usec = 0;
1102 itv.it_interval = itv.it_value;
1103 setitimer(ITIMER_REAL, &itv, NULL);
1104}
1105
1106void
1107updateprogressmeter(void)
1108{
1109 int save_errno = errno;
1110
1111 progressmeter(0);
1112 errno = save_errno;
1113}
1114
1115void
1116progressmeter(int flag)
1117{
1118 static const char prefixes[] = " KMGTP";
1119 static struct timeval lastupdate;
1120 static off_t lastsize;
1121 struct timeval now, td, wait;
1122 off_t cursize, abbrevsize;
1123 double elapsed;
1124 int ratio, barlength, i, remaining;
1125 char buf[256];
1126
1127 if (flag == -1) {
1128 (void)gettimeofday(&start, (struct timezone *)0);
1129 lastupdate = start;
1130 lastsize = 0;
1131 }
1132 (void)gettimeofday(&now, (struct timezone *)0);
1133 cursize = statbytes;
1134 if (totalbytes != 0) {
1135 ratio = cursize * 100 / totalbytes;
1136 ratio = MAX(ratio, 0);
1137 ratio = MIN(ratio, 100);
1138 }
1139 else
1140 ratio = 100;
1141
1142 snprintf(buf, sizeof(buf), "\r%-20.20s %3d%% ", curfile, ratio);
1143
1144 barlength = getttywidth() - 51;
1145 if (barlength > 0) {
1146 i = barlength * ratio / 100;
1147 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1148 "|%.*s%*s|", i,
1149"*****************************************************************************"
1150"*****************************************************************************",
1151 barlength - i, "");
1152 }
1153
1154 i = 0;
1155 abbrevsize = cursize;
1156 while (abbrevsize >= 100000 && i < sizeof(prefixes)) {
1157 i++;
1158 abbrevsize >>= 10;
1159 }
1160 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %5qd %c%c ",
1161 (quad_t)abbrevsize, prefixes[i], prefixes[i] == ' ' ? ' ' :
1162 'B');
1163
1164 timersub(&now, &lastupdate, &wait);
1165 if (cursize > lastsize) {
1166 lastupdate = now;
1167 lastsize = cursize;
1168 if (wait.tv_sec >= STALLTIME) {
1169 start.tv_sec += wait.tv_sec;
1170 start.tv_usec += wait.tv_usec;
1171 }
1172 wait.tv_sec = 0;
1173 }
1174
1175 timersub(&now, &start, &td);
1176 elapsed = td.tv_sec + (td.tv_usec / 1000000.0);
1177
1178 if (statbytes <= 0 || elapsed <= 0.0 || cursize > totalbytes) {
1179 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1180 " --:-- ETA");
1181 } else if (wait.tv_sec >= STALLTIME) {
1182 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1183 " - stalled -");
1184 } else {
1185 remaining = (int)(totalbytes / (statbytes / elapsed) - elapsed);
1186 i = elapsed / 3600;
1187 if (i)
1188 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1189 "%2d:", i);
1190 else
1191 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1192 " ");
1193 i = remaining % 3600;
1194 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1195 "%02d:%02d ETA", i / 60, i % 60);
1196 }
1197 atomicio(write, fileno(stdout), buf, strlen(buf));
1198
1199 if (flag == -1) {
1200 signal(SIGALRM, (void *)updateprogressmeter);
1201 alarmtimer(1);
1202 } else if (flag == 1) {
1203 alarmtimer(0);
1204 write(fileno(stdout), "\n", 1);
1205 statbytes = 0;
1206 }
1207}
1208
1209int
1210getttywidth(void)
1211{
1212 struct winsize winsize;
1213
1214 if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1)
1215 return(winsize.ws_col ? winsize.ws_col : 80);
1216 else
1217 return(80);
1218}
1219
1220
diff --git a/servconf.c b/servconf.c
new file mode 100644
index 000000000..5fa48790f
--- /dev/null
+++ b/servconf.c
@@ -0,0 +1,567 @@
1/*
2
3servconf.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Mon Aug 21 15:48:58 1995 ylo
11
12*/
13
14#include "includes.h"
15RCSID("$Id: servconf.c,v 1.1 1999/10/27 03:42:45 damien Exp $");
16
17#include "ssh.h"
18#include "servconf.h"
19#include "xmalloc.h"
20
21/* Initializes the server options to their default values. */
22
23void initialize_server_options(ServerOptions *options)
24{
25 memset(options, 0, sizeof(*options));
26 options->port = -1;
27 options->listen_addr.s_addr = htonl(INADDR_ANY);
28 options->host_key_file = NULL;
29 options->server_key_bits = -1;
30 options->login_grace_time = -1;
31 options->key_regeneration_time = -1;
32 options->permit_root_login = -1;
33 options->ignore_rhosts = -1;
34 options->quiet_mode = -1;
35 options->fascist_logging = -1;
36 options->print_motd = -1;
37 options->check_mail = -1;
38 options->x11_forwarding = -1;
39 options->x11_display_offset = -1;
40 options->strict_modes = -1;
41 options->keepalives = -1;
42 options->log_facility = (SyslogFacility)-1;
43 options->rhosts_authentication = -1;
44 options->rhosts_rsa_authentication = -1;
45 options->rsa_authentication = -1;
46#ifdef KRB4
47 options->kerberos_authentication = -1;
48 options->kerberos_or_local_passwd = -1;
49 options->kerberos_ticket_cleanup = -1;
50#endif
51#ifdef AFS
52 options->kerberos_tgt_passing = -1;
53 options->afs_token_passing = -1;
54#endif
55 options->password_authentication = -1;
56#ifdef SKEY
57 options->skey_authentication = -1;
58#endif
59 options->permit_empty_passwd = -1;
60 options->use_login = -1;
61 options->num_allow_users = 0;
62 options->num_deny_users = 0;
63 options->num_allow_groups = 0;
64 options->num_deny_groups = 0;
65}
66
67void fill_default_server_options(ServerOptions *options)
68{
69 if (options->port == -1)
70 {
71 struct servent *sp;
72
73 sp = getservbyname(SSH_SERVICE_NAME, "tcp");
74 if (sp)
75 options->port = ntohs(sp->s_port);
76 else
77 options->port = SSH_DEFAULT_PORT;
78 endservent();
79 }
80 if (options->host_key_file == NULL)
81 options->host_key_file = HOST_KEY_FILE;
82 if (options->server_key_bits == -1)
83 options->server_key_bits = 768;
84 if (options->login_grace_time == -1)
85 options->login_grace_time = 600;
86 if (options->key_regeneration_time == -1)
87 options->key_regeneration_time = 3600;
88 if (options->permit_root_login == -1)
89 options->permit_root_login = 1; /* yes */
90 if (options->ignore_rhosts == -1)
91 options->ignore_rhosts = 0;
92 if (options->quiet_mode == -1)
93 options->quiet_mode = 0;
94 if (options->check_mail == -1)
95 options->check_mail = 0;
96 if (options->fascist_logging == -1)
97 options->fascist_logging = 1;
98 if (options->print_motd == -1)
99 options->print_motd = 1;
100 if (options->x11_forwarding == -1)
101 options->x11_forwarding = 1;
102 if (options->x11_display_offset == -1)
103 options->x11_display_offset = 1;
104 if (options->strict_modes == -1)
105 options->strict_modes = 1;
106 if (options->keepalives == -1)
107 options->keepalives = 1;
108 if (options->log_facility == (SyslogFacility)(-1))
109 options->log_facility = SYSLOG_FACILITY_AUTH;
110 if (options->rhosts_authentication == -1)
111 options->rhosts_authentication = 0;
112 if (options->rhosts_rsa_authentication == -1)
113 options->rhosts_rsa_authentication = 1;
114 if (options->rsa_authentication == -1)
115 options->rsa_authentication = 1;
116#ifdef KRB4
117 if (options->kerberos_authentication == -1)
118 options->kerberos_authentication = (access(KEYFILE, R_OK) == 0);
119 if (options->kerberos_or_local_passwd == -1)
120 options->kerberos_or_local_passwd = 1;
121 if (options->kerberos_ticket_cleanup == -1)
122 options->kerberos_ticket_cleanup = 1;
123#endif /* KRB4 */
124#ifdef AFS
125 if (options->kerberos_tgt_passing == -1)
126 options->kerberos_tgt_passing = 0;
127 if (options->afs_token_passing == -1)
128 options->afs_token_passing = k_hasafs();
129#endif /* AFS */
130 if (options->password_authentication == -1)
131 options->password_authentication = 1;
132#ifdef SKEY
133 if (options->skey_authentication == -1)
134 options->skey_authentication = 1;
135#endif
136 if (options->permit_empty_passwd == -1)
137 options->permit_empty_passwd = 1;
138 if (options->use_login == -1)
139 options->use_login = 0;
140}
141
142#define WHITESPACE " \t\r\n"
143
144/* Keyword tokens. */
145typedef enum
146{
147 sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
148 sPermitRootLogin, sQuietMode, sFascistLogging, sLogFacility,
149 sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication,
150#ifdef KRB4
151 sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
152#endif
153#ifdef AFS
154 sKerberosTgtPassing, sAFSTokenPassing,
155#endif
156#ifdef SKEY
157 sSkeyAuthentication,
158#endif
159 sPasswordAuthentication, sListenAddress,
160 sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset,
161 sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
162 sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups
163
164} ServerOpCodes;
165
166/* Textual representation of the tokens. */
167static struct
168{
169 const char *name;
170 ServerOpCodes opcode;
171} keywords[] =
172{
173 { "port", sPort },
174 { "hostkey", sHostKeyFile },
175 { "serverkeybits", sServerKeyBits },
176 { "logingracetime", sLoginGraceTime },
177 { "keyregenerationinterval", sKeyRegenerationTime },
178 { "permitrootlogin", sPermitRootLogin },
179 { "quietmode", sQuietMode },
180 { "fascistlogging", sFascistLogging },
181 { "syslogfacility", sLogFacility },
182 { "rhostsauthentication", sRhostsAuthentication },
183 { "rhostsrsaauthentication", sRhostsRSAAuthentication },
184 { "rsaauthentication", sRSAAuthentication },
185#ifdef KRB4
186 { "kerberosauthentication", sKerberosAuthentication },
187 { "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
188 { "kerberosticketcleanup", sKerberosTicketCleanup },
189#endif
190#ifdef AFS
191 { "kerberostgtpassing", sKerberosTgtPassing },
192 { "afstokenpassing", sAFSTokenPassing },
193#endif
194 { "passwordauthentication", sPasswordAuthentication },
195#ifdef SKEY
196 { "skeyauthentication", sSkeyAuthentication },
197#endif
198 { "checkmail", sCheckMail },
199 { "listenaddress", sListenAddress },
200 { "printmotd", sPrintMotd },
201 { "ignorerhosts", sIgnoreRhosts },
202 { "x11forwarding", sX11Forwarding },
203 { "x11displayoffset", sX11DisplayOffset },
204 { "strictmodes", sStrictModes },
205 { "permitemptypasswords", sEmptyPasswd },
206 { "uselogin", sUseLogin },
207 { "randomseed", sRandomSeedFile },
208 { "keepalive", sKeepAlives },
209 { "allowusers", sAllowUsers },
210 { "denyusers", sDenyUsers },
211 { "allowgroups", sAllowGroups },
212 { "denygroups", sDenyGroups },
213 { NULL, 0 }
214};
215
216static struct
217{
218 const char *name;
219 SyslogFacility facility;
220} log_facilities[] =
221{
222 { "DAEMON", SYSLOG_FACILITY_DAEMON },
223 { "USER", SYSLOG_FACILITY_USER },
224 { "AUTH", SYSLOG_FACILITY_AUTH },
225 { "LOCAL0", SYSLOG_FACILITY_LOCAL0 },
226 { "LOCAL1", SYSLOG_FACILITY_LOCAL1 },
227 { "LOCAL2", SYSLOG_FACILITY_LOCAL2 },
228 { "LOCAL3", SYSLOG_FACILITY_LOCAL3 },
229 { "LOCAL4", SYSLOG_FACILITY_LOCAL4 },
230 { "LOCAL5", SYSLOG_FACILITY_LOCAL5 },
231 { "LOCAL6", SYSLOG_FACILITY_LOCAL6 },
232 { "LOCAL7", SYSLOG_FACILITY_LOCAL7 },
233 { NULL, 0 }
234};
235
236/* Returns the number of the token pointed to by cp of length len.
237 Never returns if the token is not known. */
238
239static ServerOpCodes parse_token(const char *cp, const char *filename,
240 int linenum)
241{
242 unsigned int i;
243
244 for (i = 0; keywords[i].name; i++)
245 if (strcmp(cp, keywords[i].name) == 0)
246 return keywords[i].opcode;
247
248 fprintf(stderr, "%s line %d: Bad configuration option: %s\n",
249 filename, linenum, cp);
250 exit(1);
251}
252
253/* Reads the server configuration file. */
254
255void read_server_config(ServerOptions *options, const char *filename)
256{
257 FILE *f;
258 char line[1024];
259 char *cp, **charptr;
260 int linenum, *intptr, i, value;
261 ServerOpCodes opcode;
262
263 f = fopen(filename, "r");
264 if (!f)
265 {
266 perror(filename);
267 exit(1);
268 }
269
270 linenum = 0;
271 while (fgets(line, sizeof(line), f))
272 {
273 linenum++;
274 cp = line + strspn(line, WHITESPACE);
275 if (!*cp || *cp == '#')
276 continue;
277 cp = strtok(cp, WHITESPACE);
278 {
279 char *t = cp;
280 for (; *t != 0; t++)
281 if ('A' <= *t && *t <= 'Z')
282 *t = *t - 'A' + 'a'; /* tolower */
283
284 }
285 opcode = parse_token(cp, filename, linenum);
286 switch (opcode)
287 {
288 case sPort:
289 intptr = &options->port;
290 parse_int:
291 cp = strtok(NULL, WHITESPACE);
292 if (!cp)
293 {
294 fprintf(stderr, "%s line %d: missing integer value.\n",
295 filename, linenum);
296 exit(1);
297 }
298 value = atoi(cp);
299 if (*intptr == -1)
300 *intptr = value;
301 break;
302
303 case sServerKeyBits:
304 intptr = &options->server_key_bits;
305 goto parse_int;
306
307 case sLoginGraceTime:
308 intptr = &options->login_grace_time;
309 goto parse_int;
310
311 case sKeyRegenerationTime:
312 intptr = &options->key_regeneration_time;
313 goto parse_int;
314
315 case sListenAddress:
316 cp = strtok(NULL, WHITESPACE);
317 if (!cp)
318 {
319 fprintf(stderr, "%s line %d: missing inet addr.\n",
320 filename, linenum);
321 exit(1);
322 }
323 options->listen_addr.s_addr = inet_addr(cp);
324 break;
325
326 case sHostKeyFile:
327 charptr = &options->host_key_file;
328 cp = strtok(NULL, WHITESPACE);
329 if (!cp)
330 {
331 fprintf(stderr, "%s line %d: missing file name.\n",
332 filename, linenum);
333 exit(1);
334 }
335 if (*charptr == NULL)
336 *charptr = tilde_expand_filename(cp, getuid());
337 break;
338
339 case sRandomSeedFile:
340 fprintf(stderr, "%s line %d: \"randomseed\" option is obsolete.\n",
341 filename, linenum);
342 cp = strtok(NULL, WHITESPACE);
343 break;
344
345 case sPermitRootLogin:
346 intptr = &options->permit_root_login;
347 cp = strtok(NULL, WHITESPACE);
348 if (!cp)
349 {
350 fprintf(stderr, "%s line %d: missing yes/without-password/no argument.\n",
351 filename, linenum);
352 exit(1);
353 }
354 if (strcmp(cp, "without-password") == 0)
355 value = 2;
356 else if (strcmp(cp, "yes") == 0)
357 value = 1;
358 else if (strcmp(cp, "no") == 0)
359 value = 0;
360 else
361 {
362 fprintf(stderr, "%s line %d: Bad yes/without-password/no argument: %s\n",
363 filename, linenum, cp);
364 exit(1);
365 }
366 if (*intptr == -1)
367 *intptr = value;
368 break;
369
370 case sIgnoreRhosts:
371 intptr = &options->ignore_rhosts;
372 parse_flag:
373 cp = strtok(NULL, WHITESPACE);
374 if (!cp)
375 {
376 fprintf(stderr, "%s line %d: missing yes/no argument.\n",
377 filename, linenum);
378 exit(1);
379 }
380 if (strcmp(cp, "yes") == 0)
381 value = 1;
382 else
383 if (strcmp(cp, "no") == 0)
384 value = 0;
385 else
386 {
387 fprintf(stderr, "%s line %d: Bad yes/no argument: %s\n",
388 filename, linenum, cp);
389 exit(1);
390 }
391 if (*intptr == -1)
392 *intptr = value;
393 break;
394
395 case sQuietMode:
396 intptr = &options->quiet_mode;
397 goto parse_flag;
398
399 case sFascistLogging:
400 intptr = &options->fascist_logging;
401 goto parse_flag;
402
403 case sRhostsAuthentication:
404 intptr = &options->rhosts_authentication;
405 goto parse_flag;
406
407 case sRhostsRSAAuthentication:
408 intptr = &options->rhosts_rsa_authentication;
409 goto parse_flag;
410
411 case sRSAAuthentication:
412 intptr = &options->rsa_authentication;
413 goto parse_flag;
414
415#ifdef KRB4
416 case sKerberosAuthentication:
417 intptr = &options->kerberos_authentication;
418 goto parse_flag;
419
420 case sKerberosOrLocalPasswd:
421 intptr = &options->kerberos_or_local_passwd;
422 goto parse_flag;
423
424 case sKerberosTicketCleanup:
425 intptr = &options->kerberos_ticket_cleanup;
426 goto parse_flag;
427#endif
428
429#ifdef AFS
430 case sKerberosTgtPassing:
431 intptr = &options->kerberos_tgt_passing;
432 goto parse_flag;
433
434 case sAFSTokenPassing:
435 intptr = &options->afs_token_passing;
436 goto parse_flag;
437#endif
438
439 case sPasswordAuthentication:
440 intptr = &options->password_authentication;
441 goto parse_flag;
442
443 case sCheckMail:
444 intptr = &options->check_mail;
445 goto parse_flag;
446
447#ifdef SKEY
448 case sSkeyAuthentication:
449 intptr = &options->skey_authentication;
450 goto parse_flag;
451#endif
452
453 case sPrintMotd:
454 intptr = &options->print_motd;
455 goto parse_flag;
456
457 case sX11Forwarding:
458 intptr = &options->x11_forwarding;
459 goto parse_flag;
460
461 case sX11DisplayOffset:
462 intptr = &options->x11_display_offset;
463 goto parse_int;
464
465 case sStrictModes:
466 intptr = &options->strict_modes;
467 goto parse_flag;
468
469 case sKeepAlives:
470 intptr = &options->keepalives;
471 goto parse_flag;
472
473 case sEmptyPasswd:
474 intptr = &options->permit_empty_passwd;
475 goto parse_flag;
476
477 case sUseLogin:
478 intptr = &options->use_login;
479 goto parse_flag;
480
481 case sLogFacility:
482 cp = strtok(NULL, WHITESPACE);
483 if (!cp)
484 {
485 fprintf(stderr, "%s line %d: missing facility name.\n",
486 filename, linenum);
487 exit(1);
488 }
489 for (i = 0; log_facilities[i].name; i++)
490 if (strcmp(log_facilities[i].name, cp) == 0)
491 break;
492 if (!log_facilities[i].name)
493 {
494 fprintf(stderr, "%s line %d: unsupported log facility %s\n",
495 filename, linenum, cp);
496 exit(1);
497 }
498 if (options->log_facility == (SyslogFacility)(-1))
499 options->log_facility = log_facilities[i].facility;
500 break;
501
502 case sAllowUsers:
503 while ((cp = strtok(NULL, WHITESPACE)))
504 {
505 if (options->num_allow_users >= MAX_ALLOW_USERS)
506 {
507 fprintf(stderr, "%s line %d: too many allow users.\n",
508 filename, linenum);
509 exit(1);
510 }
511 options->allow_users[options->num_allow_users++] = xstrdup(cp);
512 }
513 break;
514
515 case sDenyUsers:
516 while ((cp = strtok(NULL, WHITESPACE)))
517 {
518 if (options->num_deny_users >= MAX_DENY_USERS)
519 {
520 fprintf(stderr, "%s line %d: too many deny users.\n",
521 filename, linenum);
522 exit(1);
523 }
524 options->deny_users[options->num_deny_users++] = xstrdup(cp);
525 }
526 break;
527
528 case sAllowGroups:
529 while ((cp = strtok(NULL, WHITESPACE)))
530 {
531 if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
532 {
533 fprintf(stderr, "%s line %d: too many allow groups.\n",
534 filename, linenum);
535 exit(1);
536 }
537 options->allow_groups[options->num_allow_groups++] = xstrdup(cp);
538 }
539 break;
540
541 case sDenyGroups:
542 while ((cp = strtok(NULL, WHITESPACE)))
543 {
544 if (options->num_deny_groups >= MAX_DENY_GROUPS)
545 {
546 fprintf(stderr, "%s line %d: too many deny groups.\n",
547 filename, linenum);
548 exit(1);
549 }
550 options->deny_groups[options->num_deny_groups++] = xstrdup(cp);
551 }
552 break;
553
554 default:
555 fprintf(stderr, "%s line %d: Missing handler for opcode %s (%d)\n",
556 filename, linenum, cp, opcode);
557 exit(1);
558 }
559 if (strtok(NULL, WHITESPACE) != NULL)
560 {
561 fprintf(stderr, "%s line %d: garbage at end of line.\n",
562 filename, linenum);
563 exit(1);
564 }
565 }
566 fclose(f);
567}
diff --git a/servconf.h b/servconf.h
new file mode 100644
index 000000000..22c73fd73
--- /dev/null
+++ b/servconf.h
@@ -0,0 +1,86 @@
1/*
2
3servconf.h
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Mon Aug 21 15:35:03 1995 ylo
11
12Definitions for server configuration data and for the functions reading it.
13
14*/
15
16/* RCSID("$Id: servconf.h,v 1.1 1999/10/27 03:42:45 damien Exp $"); */
17
18#ifndef SERVCONF_H
19#define SERVCONF_H
20
21#define MAX_ALLOW_USERS 256 /* Max # users on allow list. */
22#define MAX_DENY_USERS 256 /* Max # users on deny list. */
23#define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */
24#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */
25
26typedef struct
27{
28 int port; /* Port number to listen on. */
29 struct in_addr listen_addr; /* Address on which the server listens. */
30 char *host_key_file; /* File containing host key. */
31 int server_key_bits; /* Size of the server key. */
32 int login_grace_time; /* Disconnect if no auth in this time (sec). */
33 int key_regeneration_time; /* Server key lifetime (seconds). */
34 int permit_root_login; /* If true, permit root login. */
35 int ignore_rhosts; /* Ignore .rhosts and .shosts. */
36 int quiet_mode; /* If true, don't log anything but fatals. */
37 int fascist_logging; /* Perform very verbose logging. */
38 int print_motd; /* If true, print /etc/motd. */
39 int check_mail; /* If true, check for new mail. */
40 int x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */
41 int x11_display_offset; /* What DISPLAY number to start searching at */
42 int strict_modes; /* If true, require string home dir modes. */
43 int keepalives; /* If true, set SO_KEEPALIVE. */
44 SyslogFacility log_facility; /* Facility for system logging. */
45 int rhosts_authentication; /* If true, permit rhosts authentication. */
46 int rhosts_rsa_authentication;/* If true, permit rhosts RSA authentication.*/
47 int rsa_authentication; /* If true, permit RSA authentication. */
48#ifdef KRB4
49 int kerberos_authentication; /* If true, permit Kerberos authentication. */
50 int kerberos_or_local_passwd; /* If true, permit kerberos and any other
51 password authentication mechanism, such
52 as SecurID or /etc/passwd */
53 int kerberos_ticket_cleanup; /* If true, destroy ticket file on logout. */
54#endif
55#ifdef AFS
56 int kerberos_tgt_passing; /* If true, permit Kerberos tgt passing. */
57 int afs_token_passing; /* If true, permit AFS token passing. */
58#endif
59 int password_authentication; /* If true, permit password authentication. */
60#ifdef SKEY
61 int skey_authentication; /* If true, permit s/key authentication. */
62#endif
63 int permit_empty_passwd; /* If false, do not permit empty passwords. */
64 int use_login; /* If true, login(1) is used */
65 unsigned int num_allow_users;
66 char *allow_users[MAX_ALLOW_USERS];
67 unsigned int num_deny_users;
68 char *deny_users[MAX_DENY_USERS];
69 unsigned int num_allow_groups;
70 char *allow_groups[MAX_ALLOW_GROUPS];
71 unsigned int num_deny_groups;
72 char *deny_groups[MAX_DENY_GROUPS];
73} ServerOptions;
74
75/* Initializes the server options to special values that indicate that they
76 have not yet been set. */
77void initialize_server_options(ServerOptions *options);
78
79/* Reads the server configuration file. This only sets the values for those
80 options that have the special value indicating they have not been set. */
81void read_server_config(ServerOptions *options, const char *filename);
82
83/* Sets values for those values that have not yet been set. */
84void fill_default_server_options(ServerOptions *options);
85
86#endif /* SERVCONF_H */
diff --git a/serverloop.c b/serverloop.c
new file mode 100644
index 000000000..552c69c29
--- /dev/null
+++ b/serverloop.c
@@ -0,0 +1,644 @@
1/*
2
3serverloop.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Sun Sep 10 00:30:37 1995 ylo
11
12Server main loop for handling the interactive session.
13
14*/
15
16#include "includes.h"
17#include "xmalloc.h"
18#include "ssh.h"
19#include "packet.h"
20#include "buffer.h"
21#include "servconf.h"
22#include "pty.h"
23
24static Buffer stdin_buffer; /* Buffer for stdin data. */
25static Buffer stdout_buffer; /* Buffer for stdout data. */
26static Buffer stderr_buffer; /* Buffer for stderr data. */
27static int fdin; /* Descriptor for stdin (for writing) */
28static int fdout; /* Descriptor for stdout (for reading);
29 May be same number as fdin. */
30static int fderr; /* Descriptor for stderr. May be -1. */
31static long stdin_bytes = 0; /* Number of bytes written to stdin. */
32static long stdout_bytes = 0; /* Number of stdout bytes sent to client. */
33static long stderr_bytes = 0; /* Number of stderr bytes sent to client. */
34static long fdout_bytes = 0; /* Number of stdout bytes read from program. */
35static int stdin_eof = 0; /* EOF message received from client. */
36static int fdout_eof = 0; /* EOF encountered reading from fdout. */
37static int fderr_eof = 0; /* EOF encountered readung from fderr. */
38static int connection_in; /* Connection to client (input). */
39static int connection_out; /* Connection to client (output). */
40static unsigned int buffer_high;/* "Soft" max buffer size. */
41static int max_fd; /* Max file descriptor number for select(). */
42
43/* This SIGCHLD kludge is used to detect when the child exits. The server
44 will exit after that, as soon as forwarded connections have terminated. */
45
46static int child_pid; /* Pid of the child. */
47static volatile int child_terminated; /* The child has terminated. */
48static volatile int child_wait_status; /* Status from wait(). */
49
50void sigchld_handler(int sig)
51{
52 int save_errno = errno;
53 int wait_pid;
54 debug("Received SIGCHLD.");
55 wait_pid = wait((int *)&child_wait_status);
56 if (wait_pid != -1)
57 {
58 if (wait_pid != child_pid)
59 error("Strange, got SIGCHLD and wait returned pid %d but child is %d",
60 wait_pid, child_pid);
61 if (WIFEXITED(child_wait_status) ||
62 WIFSIGNALED(child_wait_status))
63 child_terminated = 1;
64 }
65 signal(SIGCHLD, sigchld_handler);
66 errno = save_errno;
67}
68
69/* Process any buffered packets that have been received from the client. */
70
71void process_buffered_input_packets()
72{
73 int type;
74 char *data;
75 unsigned int data_len;
76 int row, col, xpixel, ypixel;
77 int payload_len;
78
79 /* Process buffered packets from the client. */
80 while ((type = packet_read_poll(&payload_len)) != SSH_MSG_NONE)
81 {
82 switch (type)
83 {
84 case SSH_CMSG_STDIN_DATA:
85 /* Stdin data from the client. Append it to the buffer. */
86 if (fdin == -1)
87 break; /* Ignore any data if the client has closed stdin. */
88 data = packet_get_string(&data_len);
89 packet_integrity_check(payload_len, (4 + data_len), type);
90 buffer_append(&stdin_buffer, data, data_len);
91 memset(data, 0, data_len);
92 xfree(data);
93 break;
94
95 case SSH_CMSG_EOF:
96 /* Eof from the client. The stdin descriptor to the program
97 will be closed when all buffered data has drained. */
98 debug("EOF received for stdin.");
99 packet_integrity_check(payload_len, 0, type);
100 stdin_eof = 1;
101 break;
102
103 case SSH_CMSG_WINDOW_SIZE:
104 debug("Window change received.");
105 packet_integrity_check(payload_len, 4*4, type);
106 row = packet_get_int();
107 col = packet_get_int();
108 xpixel = packet_get_int();
109 ypixel = packet_get_int();
110 if (fdin != -1)
111 pty_change_window_size(fdin, row, col, xpixel, ypixel);
112 break;
113
114 case SSH_MSG_PORT_OPEN:
115 debug("Received port open request.");
116 channel_input_port_open(payload_len);
117 break;
118
119 case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
120 debug("Received channel open confirmation.");
121 packet_integrity_check(payload_len, 4 + 4, type);
122 channel_input_open_confirmation();
123 break;
124
125 case SSH_MSG_CHANNEL_OPEN_FAILURE:
126 debug("Received channel open failure.");
127 packet_integrity_check(payload_len, 4, type);
128 channel_input_open_failure();
129 break;
130
131 case SSH_MSG_CHANNEL_DATA:
132 channel_input_data(payload_len);
133 break;
134
135 case SSH_MSG_CHANNEL_CLOSE:
136 debug("Received channel close.");
137 packet_integrity_check(payload_len, 4, type);
138 channel_input_close();
139 break;
140
141 case SSH_MSG_CHANNEL_CLOSE_CONFIRMATION:
142 debug("Received channel close confirmation.");
143 packet_integrity_check(payload_len, 4, type);
144 channel_input_close_confirmation();
145 break;
146
147 default:
148 /* In this phase, any unexpected messages cause a protocol
149 error. This is to ease debugging; also, since no
150 confirmations are sent messages, unprocessed unknown
151 messages could cause strange problems. Any compatible
152 protocol extensions must be negotiated before entering the
153 interactive session. */
154 packet_disconnect("Protocol error during session: type %d",
155 type);
156 }
157 }
158}
159
160/* Make packets from buffered stderr data, and buffer it for sending
161 to the client. */
162
163void make_packets_from_stderr_data()
164{
165 int len;
166
167 /* Send buffered stderr data to the client. */
168 while (buffer_len(&stderr_buffer) > 0 &&
169 packet_not_very_much_data_to_write())
170 {
171 len = buffer_len(&stderr_buffer);
172 if (packet_is_interactive())
173 {
174 if (len > 512)
175 len = 512;
176 }
177 else
178 {
179 if (len > 32768)
180 len = 32768; /* Keep the packets at reasonable size. */
181 }
182 packet_start(SSH_SMSG_STDERR_DATA);
183 packet_put_string(buffer_ptr(&stderr_buffer), len);
184 packet_send();
185 buffer_consume(&stderr_buffer, len);
186 stderr_bytes += len;
187 }
188}
189
190/* Make packets from buffered stdout data, and buffer it for sending to the
191 client. */
192
193void make_packets_from_stdout_data()
194{
195 int len;
196
197 /* Send buffered stdout data to the client. */
198 while (buffer_len(&stdout_buffer) > 0 &&
199 packet_not_very_much_data_to_write())
200 {
201 len = buffer_len(&stdout_buffer);
202 if (packet_is_interactive())
203 {
204 if (len > 512)
205 len = 512;
206 }
207 else
208 {
209 if (len > 32768)
210 len = 32768; /* Keep the packets at reasonable size. */
211 }
212 packet_start(SSH_SMSG_STDOUT_DATA);
213 packet_put_string(buffer_ptr(&stdout_buffer), len);
214 packet_send();
215 buffer_consume(&stdout_buffer, len);
216 stdout_bytes += len;
217 }
218}
219
220/* Sleep in select() until we can do something. This will initialize the
221 select masks. Upon return, the masks will indicate which descriptors
222 have data or can accept data. Optionally, a maximum time can be specified
223 for the duration of the wait (0 = infinite). */
224
225void wait_until_can_do_something(fd_set *readset, fd_set *writeset,
226 unsigned int max_time_milliseconds)
227{
228 struct timeval tv, *tvp;
229 int ret;
230
231 /* When select fails we restart from here. */
232retry_select:
233
234 /* Initialize select() masks. */
235 FD_ZERO(readset);
236
237 /* Read packets from the client unless we have too much buffered stdin
238 or channel data. */
239 if (buffer_len(&stdin_buffer) < 4096 &&
240 channel_not_very_much_buffered_data())
241 FD_SET(connection_in, readset);
242
243 /* If there is not too much data already buffered going to the client,
244 try to get some more data from the program. */
245 if (packet_not_very_much_data_to_write())
246 {
247 if (!fdout_eof)
248 FD_SET(fdout, readset);
249 if (!fderr_eof)
250 FD_SET(fderr, readset);
251 }
252
253 FD_ZERO(writeset);
254
255 /* Set masks for channel descriptors. */
256 channel_prepare_select(readset, writeset);
257
258 /* If we have buffered packet data going to the client, mark that
259 descriptor. */
260 if (packet_have_data_to_write())
261 FD_SET(connection_out, writeset);
262
263 /* If we have buffered data, try to write some of that data to the
264 program. */
265 if (fdin != -1 && buffer_len(&stdin_buffer) > 0)
266 FD_SET(fdin, writeset);
267
268 /* Update the maximum descriptor number if appropriate. */
269 if (channel_max_fd() > max_fd)
270 max_fd = channel_max_fd();
271
272 /* If child has terminated, read as much as is available and then exit. */
273 if (child_terminated)
274 if (max_time_milliseconds == 0)
275 max_time_milliseconds = 100;
276
277 if (max_time_milliseconds == 0)
278 tvp = NULL;
279 else
280 {
281 tv.tv_sec = max_time_milliseconds / 1000;
282 tv.tv_usec = 1000 * (max_time_milliseconds % 1000);
283 tvp = &tv;
284 }
285
286 /* Wait for something to happen, or the timeout to expire. */
287 ret = select(max_fd + 1, readset, writeset, NULL, tvp);
288
289 if (ret < 0)
290 {
291 if (errno != EINTR)
292 error("select: %.100s", strerror(errno));
293 else
294 goto retry_select;
295 }
296}
297
298/* Processes input from the client and the program. Input data is stored
299 in buffers and processed later. */
300
301void process_input(fd_set *readset)
302{
303 int len;
304 char buf[16384];
305
306 /* Read and buffer any input data from the client. */
307 if (FD_ISSET(connection_in, readset))
308 {
309 len = read(connection_in, buf, sizeof(buf));
310 if (len == 0)
311 fatal("Connection closed by remote host.");
312
313 /* There is a kernel bug on Solaris that causes select to sometimes
314 wake up even though there is no data available. */
315 if (len < 0 && errno == EAGAIN)
316 len = 0;
317
318 if (len < 0)
319 fatal("Read error from remote host: %.100s", strerror(errno));
320
321 /* Buffer any received data. */
322 packet_process_incoming(buf, len);
323 }
324
325 /* Read and buffer any available stdout data from the program. */
326 if (!fdout_eof && FD_ISSET(fdout, readset))
327 {
328 len = read(fdout, buf, sizeof(buf));
329 if (len <= 0)
330 fdout_eof = 1;
331 else
332 {
333 buffer_append(&stdout_buffer, buf, len);
334 fdout_bytes += len;
335 }
336 }
337
338 /* Read and buffer any available stderr data from the program. */
339 if (!fderr_eof && FD_ISSET(fderr, readset))
340 {
341 len = read(fderr, buf, sizeof(buf));
342 if (len <= 0)
343 fderr_eof = 1;
344 else
345 buffer_append(&stderr_buffer, buf, len);
346 }
347}
348
349/* Sends data from internal buffers to client program stdin. */
350
351void process_output(fd_set *writeset)
352{
353 int len;
354
355 /* Write buffered data to program stdin. */
356 if (fdin != -1 && FD_ISSET(fdin, writeset))
357 {
358 len = write(fdin, buffer_ptr(&stdin_buffer),
359 buffer_len(&stdin_buffer));
360 if (len <= 0)
361 {
362#ifdef USE_PIPES
363 close(fdin);
364#else
365 if (fdout == -1)
366 close(fdin);
367 else
368 shutdown(fdin, SHUT_WR); /* We will no longer send. */
369#endif
370 fdin = -1;
371 }
372 else
373 {
374 /* Successful write. Consume the data from the buffer. */
375 buffer_consume(&stdin_buffer, len);
376 /* Update the count of bytes written to the program. */
377 stdin_bytes += len;
378 }
379 }
380
381 /* Send any buffered packet data to the client. */
382 if (FD_ISSET(connection_out, writeset))
383 packet_write_poll();
384}
385
386/* Wait until all buffered output has been sent to the client.
387 This is used when the program terminates. */
388
389void drain_output()
390{
391 /* Send any buffered stdout data to the client. */
392 if (buffer_len(&stdout_buffer) > 0)
393 {
394 packet_start(SSH_SMSG_STDOUT_DATA);
395 packet_put_string(buffer_ptr(&stdout_buffer),
396 buffer_len(&stdout_buffer));
397 packet_send();
398 /* Update the count of sent bytes. */
399 stdout_bytes += buffer_len(&stdout_buffer);
400 }
401
402 /* Send any buffered stderr data to the client. */
403 if (buffer_len(&stderr_buffer) > 0)
404 {
405 packet_start(SSH_SMSG_STDERR_DATA);
406 packet_put_string(buffer_ptr(&stderr_buffer),
407 buffer_len(&stderr_buffer));
408 packet_send();
409 /* Update the count of sent bytes. */
410 stderr_bytes += buffer_len(&stderr_buffer);
411 }
412
413 /* Wait until all buffered data has been written to the client. */
414 packet_write_wait();
415}
416
417/* Performs the interactive session. This handles data transmission between
418 the client and the program. Note that the notion of stdin, stdout, and
419 stderr in this function is sort of reversed: this function writes to
420 stdin (of the child program), and reads from stdout and stderr (of the
421 child program). */
422
423void server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
424{
425 int wait_status, wait_pid; /* Status and pid returned by wait(). */
426 int waiting_termination = 0; /* Have displayed waiting close message. */
427 unsigned int max_time_milliseconds;
428 unsigned int previous_stdout_buffer_bytes;
429 unsigned int stdout_buffer_bytes;
430 int type;
431
432 debug("Entering interactive session.");
433
434 /* Initialize the SIGCHLD kludge. */
435 child_pid = pid;
436 child_terminated = 0;
437 signal(SIGCHLD, sigchld_handler);
438
439 /* Initialize our global variables. */
440 fdin = fdin_arg;
441 fdout = fdout_arg;
442 fderr = fderr_arg;
443 connection_in = packet_get_connection_in();
444 connection_out = packet_get_connection_out();
445
446 previous_stdout_buffer_bytes = 0;
447
448 /* Set approximate I/O buffer size. */
449 if (packet_is_interactive())
450 buffer_high = 4096;
451 else
452 buffer_high = 64 * 1024;
453
454 /* Initialize max_fd to the maximum of the known file descriptors. */
455 max_fd = fdin;
456 if (fdout > max_fd)
457 max_fd = fdout;
458 if (fderr != -1 && fderr > max_fd)
459 max_fd = fderr;
460 if (connection_in > max_fd)
461 max_fd = connection_in;
462 if (connection_out > max_fd)
463 max_fd = connection_out;
464
465 /* Initialize Initialize buffers. */
466 buffer_init(&stdin_buffer);
467 buffer_init(&stdout_buffer);
468 buffer_init(&stderr_buffer);
469
470 /* If we have no separate fderr (which is the case when we have a pty - there
471 we cannot make difference between data sent to stdout and stderr),
472 indicate that we have seen an EOF from stderr. This way we don\'t
473 need to check the descriptor everywhere. */
474 if (fderr == -1)
475 fderr_eof = 1;
476
477 /* Main loop of the server for the interactive session mode. */
478 for (;;)
479 {
480 fd_set readset, writeset;
481
482 /* Process buffered packets from the client. */
483 process_buffered_input_packets();
484
485 /* If we have received eof, and there is no more pending input data,
486 cause a real eof by closing fdin. */
487 if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0)
488 {
489#ifdef USE_PIPES
490 close(fdin);
491#else
492 if (fdout == -1)
493 close(fdin);
494 else
495 shutdown(fdin, SHUT_WR); /* We will no longer send. */
496#endif
497 fdin = -1;
498 }
499
500 /* Make packets from buffered stderr data to send to the client. */
501 make_packets_from_stderr_data();
502
503 /* Make packets from buffered stdout data to send to the client.
504 If there is very little to send, this arranges to not send them
505 now, but to wait a short while to see if we are getting more data.
506 This is necessary, as some systems wake up readers from a pty after
507 each separate character. */
508 max_time_milliseconds = 0;
509 stdout_buffer_bytes = buffer_len(&stdout_buffer);
510 if (stdout_buffer_bytes != 0 && stdout_buffer_bytes < 256 &&
511 stdout_buffer_bytes != previous_stdout_buffer_bytes)
512 max_time_milliseconds = 10; /* try again after a while */
513 else
514 make_packets_from_stdout_data(); /* Send it now. */
515 previous_stdout_buffer_bytes = buffer_len(&stdout_buffer);
516
517 /* Send channel data to the client. */
518 if (packet_not_very_much_data_to_write())
519 channel_output_poll();
520
521 /* Bail out of the loop if the program has closed its output descriptors,
522 and we have no more data to send to the client, and there is no
523 pending buffered data. */
524 if (fdout_eof && fderr_eof && !packet_have_data_to_write() &&
525 buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0)
526 {
527 if (!channel_still_open())
528 goto quit;
529 if (!waiting_termination)
530 {
531 const char *s =
532 "Waiting for forwarded connections to terminate...\r\n";
533 char *cp;
534 waiting_termination = 1;
535 buffer_append(&stderr_buffer, s, strlen(s));
536
537 /* Display list of open channels. */
538 cp = channel_open_message();
539 buffer_append(&stderr_buffer, cp, strlen(cp));
540 xfree(cp);
541 }
542 }
543
544 /* Sleep in select() until we can do something. */
545 wait_until_can_do_something(&readset, &writeset,
546 max_time_milliseconds);
547
548 /* Process any channel events. */
549 channel_after_select(&readset, &writeset);
550
551 /* Process input from the client and from program stdout/stderr. */
552 process_input(&readset);
553
554 /* Process output to the client and to program stdin. */
555 process_output(&writeset);
556 }
557
558 quit:
559 /* Cleanup and termination code. */
560
561 /* Wait until all output has been sent to the client. */
562 drain_output();
563
564 debug("End of interactive session; stdin %ld, stdout (read %ld, sent %ld), stderr %ld bytes.",
565 stdin_bytes, fdout_bytes, stdout_bytes, stderr_bytes);
566
567 /* Free and clear the buffers. */
568 buffer_free(&stdin_buffer);
569 buffer_free(&stdout_buffer);
570 buffer_free(&stderr_buffer);
571
572 /* Close the file descriptors. */
573 if (fdout != -1)
574 close(fdout);
575 fdout = -1;
576 fdout_eof = 1;
577 if (fderr != -1)
578 close(fderr);
579 fderr = -1;
580 fderr_eof = 1;
581 if (fdin != -1)
582 close(fdin);
583 fdin = -1;
584
585 /* Stop listening for channels; this removes unix domain sockets. */
586 channel_stop_listening();
587
588 /* Wait for the child to exit. Get its exit status. */
589 wait_pid = wait(&wait_status);
590 if (wait_pid < 0)
591 {
592 /* It is possible that the wait was handled by SIGCHLD handler. This
593 may result in either: this call returning with EINTR, or: this
594 call returning ECHILD. */
595 if (child_terminated)
596 wait_status = child_wait_status;
597 else
598 packet_disconnect("wait: %.100s", strerror(errno));
599 }
600 else
601 {
602 /* Check if it matches the process we forked. */
603 if (wait_pid != pid)
604 error("Strange, wait returned pid %d, expected %d", wait_pid, pid);
605 }
606
607 /* We no longer want our SIGCHLD handler to be called. */
608 signal(SIGCHLD, SIG_DFL);
609
610 /* Check if it exited normally. */
611 if (WIFEXITED(wait_status))
612 {
613 /* Yes, normal exit. Get exit status and send it to the client. */
614 debug("Command exited with status %d.", WEXITSTATUS(wait_status));
615 packet_start(SSH_SMSG_EXITSTATUS);
616 packet_put_int(WEXITSTATUS(wait_status));
617 packet_send();
618 packet_write_wait();
619
620 /* Wait for exit confirmation. Note that there might be other
621 packets coming before it; however, the program has already died
622 so we just ignore them. The client is supposed to respond with
623 the confirmation when it receives the exit status. */
624 do
625 {
626 int plen;
627 type = packet_read(&plen);
628 }
629 while (type != SSH_CMSG_EXIT_CONFIRMATION);
630
631 debug("Received exit confirmation.");
632 return;
633 }
634
635 /* Check if the program terminated due to a signal. */
636 if (WIFSIGNALED(wait_status))
637 packet_disconnect("Command terminated on signal %d.",
638 WTERMSIG(wait_status));
639
640 /* Some weird exit cause. Just exit. */
641 packet_disconnect("wait returned status %04x.", wait_status);
642 /*NOTREACHED*/
643}
644
diff --git a/ssh-add.1 b/ssh-add.1
new file mode 100644
index 000000000..4c64ab2b3
--- /dev/null
+++ b/ssh-add.1
@@ -0,0 +1,116 @@
1.\" -*- nroff -*-
2.\"
3.\" ssh-add.1
4.\"
5.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
6.\"
7.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8.\" All rights reserved
9.\"
10.\" Created: Sat Apr 22 23:55:14 1995 ylo
11.\"
12.\" $Id: ssh-add.1,v 1.1 1999/10/27 03:42:45 damien Exp $
13.\"
14.Dd September 25, 1999
15.Dt SSH-ADD 1
16.Os
17.Sh NAME
18.Nm ssh-add
19.Nd adds identities for the authentication agent
20.Sh SYNOPSIS
21.Nm ssh-add
22.Op Fl ldD
23.Op Ar
24.Sh DESCRIPTION
25.Nm
26adds identities to the authentication agent,
27.Xr ssh-agent 1 .
28When run without arguments, it adds the file
29.Pa $HOME/.ssh/identity .
30Alternative file names can be given on the
31command line. If any file requires a passphrase,
32.Nm
33asks for the passphrase from the user.
34The Passphrase it is read from the user's tty.
35.Pp
36The authentication agent must be running and must be an ancestor of
37the current process for
38.Nm
39to work.
40.Pp
41The options are as follows:
42.Bl -tag -width Ds
43.It Fl l
44Lists all identities currently represented by the agent.
45.It Fl d
46Instead of adding the identity, removes the identity from the agent.
47.It Fl D
48Deletes all identities from the agent.
49.El
50.Sh FILES
51.Bl -tag -width Ds
52.Pa $HOME/.ssh/identity
53Contains the RSA authentication identity of the user. This file
54should not be readable by anyone but the user.
55Note that
56.Nm
57ignores this file if it is accessible by others.
58It is possible to
59specify a passphrase when generating the key; that passphrase will be
60used to encrypt the private part of this file. This is the
61default file added by
62.Nm
63when no other files have been specified.
64.Pp
65If
66.Nm
67needs a passphrase, it will read the passphrase from the current
68terminal if it was run from a terminal. If
69.Nm
70does not have a terminal associated with it but
71.Ev DISPLAY
72is set, it
73will open an X11 window to read the passphrase. This is particularly
74useful when calling
75.Nm
76from a
77.Pa .Xsession
78or related script. (Note that on some machines it
79may be necessary to redirect the input from
80.Pa /dev/null
81to make this work.)
82.Sh AUTHOR
83Tatu Ylonen <ylo@cs.hut.fi>
84.Pp
85OpenSSH
86is a derivative of the original (free) ssh 1.2.12 release, but with bugs
87removed and newer features re-added. Rapidly after the 1.2.12 release,
88newer versions bore successively more restrictive licenses. This version
89of OpenSSH
90.Bl -bullet
91.It
92has all components of a restrictive nature (ie. patents, see
93.Xr ssl 8 )
94directly removed from the source code; any licensed or patented components
95are chosen from
96external libraries.
97.It
98has been updated to support ssh protocol 1.5.
99.It
100contains added support for
101.Xr kerberos 8
102authentication and ticket passing.
103.It
104supports one-time password authentication with
105.Xr skey 1 .
106.El
107.Pp
108The libraries described in
109.Xr ssl 8
110are required for proper operation.
111.Sh SEE ALSO
112.Xr ssh 1 ,
113.Xr ssh-agent 1 ,
114.Xr ssh-keygen 1 ,
115.Xr sshd 8 ,
116.Xr ssl 8
diff --git a/ssh-add.c b/ssh-add.c
new file mode 100644
index 000000000..5ac3c303a
--- /dev/null
+++ b/ssh-add.c
@@ -0,0 +1,254 @@
1/*
2
3ssh-add.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Thu Apr 6 00:52:24 1995 ylo
11
12Adds an identity to the authentication server, or removes an identity.
13
14*/
15
16#include "includes.h"
17RCSID("$Id: ssh-add.c,v 1.1 1999/10/27 03:42:45 damien Exp $");
18
19#include "rsa.h"
20#include "ssh.h"
21#include "xmalloc.h"
22#include "authfd.h"
23
24void
25delete_file(const char *filename)
26{
27 RSA *key;
28 char *comment;
29 AuthenticationConnection *ac;
30
31 key = RSA_new();
32 if (!load_public_key(filename, key, &comment))
33 {
34 printf("Bad key file %s: %s\n", filename, strerror(errno));
35 return;
36 }
37
38 /* Send the request to the authentication agent. */
39 ac = ssh_get_authentication_connection();
40 if (!ac)
41 {
42 fprintf(stderr,
43 "Could not open a connection to your authentication agent.\n");
44 RSA_free(key);
45 xfree(comment);
46 return;
47 }
48 if (ssh_remove_identity(ac, key))
49 fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
50 else
51 fprintf(stderr, "Could not remove identity: %s\n", filename);
52 RSA_free(key);
53 xfree(comment);
54 ssh_close_authentication_connection(ac);
55}
56
57void
58delete_all()
59{
60 AuthenticationConnection *ac;
61
62 /* Get a connection to the agent. */
63 ac = ssh_get_authentication_connection();
64 if (!ac)
65 {
66 fprintf(stderr,
67 "Could not open a connection to your authentication agent.\n");
68 return;
69 }
70
71 /* Send a request to remove all identities. */
72 if (ssh_remove_all_identities(ac))
73 fprintf(stderr, "All identities removed.\n");
74 else
75 fprintf(stderr, "Failed to remove all identitities.\n");
76
77 /* Close the connection to the agent. */
78 ssh_close_authentication_connection(ac);
79}
80
81void
82add_file(const char *filename)
83{
84 RSA *key;
85 RSA *public_key;
86 AuthenticationConnection *ac;
87 char *saved_comment, *comment, *pass;
88 int first;
89
90 key = RSA_new();
91 public_key = RSA_new();
92 if (!load_public_key(filename, public_key, &saved_comment))
93 {
94 printf("Bad key file %s: %s\n", filename, strerror(errno));
95 return;
96 }
97 RSA_free(public_key);
98
99 pass = xstrdup("");
100 first = 1;
101 while (!load_private_key(filename, pass, key, &comment))
102 {
103 /* Free the old passphrase. */
104 memset(pass, 0, strlen(pass));
105 xfree(pass);
106
107 /* Ask for a passphrase. */
108 if (getenv("DISPLAY") && !isatty(fileno(stdin)))
109 {
110 xfree(saved_comment);
111 return;
112 }
113 else
114 {
115 if (first)
116 printf("Need passphrase for %s (%s).\n", filename, saved_comment);
117 else
118 printf("Bad passphrase.\n");
119 pass = read_passphrase("Enter passphrase: ", 1);
120 if (strcmp(pass, "") == 0)
121 {
122 xfree(saved_comment);
123 xfree(pass);
124 return;
125 }
126 }
127 first = 0;
128 }
129 memset(pass, 0, strlen(pass));
130 xfree(pass);
131
132 xfree(saved_comment);
133
134 /* Send the key to the authentication agent. */
135 ac = ssh_get_authentication_connection();
136 if (!ac)
137 {
138 fprintf(stderr,
139 "Could not open a connection to your authentication agent.\n");
140 RSA_free(key);
141 xfree(comment);
142 return;
143 }
144 if (ssh_add_identity(ac, key, comment))
145 fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
146 else
147 fprintf(stderr, "Could not add identity: %s\n", filename);
148 RSA_free(key);
149 xfree(comment);
150 ssh_close_authentication_connection(ac);
151}
152
153void
154list_identities()
155{
156 AuthenticationConnection *ac;
157 BIGNUM *e, *n;
158 int bits, status;
159 char *comment;
160 int had_identities;
161
162 ac = ssh_get_authentication_connection();
163 if (!ac)
164 {
165 fprintf(stderr, "Could not connect to authentication server.\n");
166 return;
167 }
168 e = BN_new();
169 n = BN_new();
170 had_identities = 0;
171 for (status = ssh_get_first_identity(ac, &bits, e, n, &comment);
172 status;
173 status = ssh_get_next_identity(ac, &bits, e, n, &comment))
174 {
175 char *buf;
176 had_identities = 1;
177 printf("%d ", bits);
178 buf = BN_bn2dec(e);
179 assert(buf != NULL);
180 printf("%s ", buf);
181 free (buf);
182 buf = BN_bn2dec(n);
183 assert(buf != NULL);
184 printf("%s %s\n", buf, comment);
185 free (buf);
186 xfree(comment);
187 }
188 BN_clear_free(e);
189 BN_clear_free(n);
190 if (!had_identities)
191 printf("The agent has no identities.\n");
192 ssh_close_authentication_connection(ac);
193}
194
195int
196main(int ac, char **av)
197{
198 struct passwd *pw;
199 char buf[1024];
200 int no_files = 1;
201 int i;
202 int deleting = 0;
203
204 /* check if RSA support exists */
205 if (rsa_alive() == 0) {
206 extern char *__progname;
207
208 fprintf(stderr,
209 "%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
210 __progname);
211 exit(1);
212 }
213
214 for (i = 1; i < ac; i++)
215 {
216 if (strcmp(av[i], "-l") == 0)
217 {
218 list_identities();
219 no_files = 0; /* Don't default-add/delete if -l. */
220 continue;
221 }
222 if (strcmp(av[i], "-d") == 0)
223 {
224 deleting = 1;
225 continue;
226 }
227 if (strcmp(av[i], "-D") == 0)
228 {
229 delete_all();
230 no_files = 0;
231 continue;
232 }
233 no_files = 0;
234 if (deleting)
235 delete_file(av[i]);
236 else
237 add_file(av[i]);
238 }
239 if (no_files)
240 {
241 pw = getpwuid(getuid());
242 if (!pw)
243 {
244 fprintf(stderr, "No user found with uid %d\n", (int)getuid());
245 exit(1);
246 }
247 snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);
248 if (deleting)
249 delete_file(buf);
250 else
251 add_file(buf);
252 }
253 exit(0);
254}
diff --git a/ssh-agent.1 b/ssh-agent.1
new file mode 100644
index 000000000..01c43cdee
--- /dev/null
+++ b/ssh-agent.1
@@ -0,0 +1,124 @@
1.\" -*- nroff -*-
2.\"
3.\" ssh-agent.1
4.\"
5.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
6.\"
7.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8.\" All rights reserved
9.\"
10.\" Created: Sat Apr 23 20:10:43 1995 ylo
11.\"
12.\" $Id: ssh-agent.1,v 1.1 1999/10/27 03:42:45 damien Exp $
13.\"
14.Dd September 25, 1999
15.Dt SSH-AGENT 1
16.Os
17.Sh NAME
18.Nm ssh-agent
19.Nd authentication agent
20.Sh SYNOPSIS
21.Nm ssh-agent
22.Ar command
23.Sh DESCRIPTION
24.Nm
25is a program to hold authentication private keys. The
26idea is that
27.Nm
28is started in the beginning of an X-session or a login session, and
29all other windows or programs are started as children of the ssh-agent
30program (the
31.Ar command
32normally starts X or is the user shell). Programs started under
33the agent inherit a connection to the agent, and the agent is
34automatically used for RSA authentication when logging to other
35machines using
36.Xr ssh 1 .
37.Pp
38The agent initially does not have any private keys. Keys are added
39using
40.Xr ssh-add 1 .
41When executed without arguments,
42.Xr ssh-add 1
43adds the
44.Pa $HOME/.ssh/identity
45file. If the identity has a passphrase,
46.Xr ssh-add 1
47asks for the passphrase (using a small X11 application if running
48under X11, or from the terminal if running without X). It then sends
49the identity to the agent. Several identities can be stored in the
50agent; the agent can automatically use any of these identities.
51.Ic ssh-add -l
52displays the identities currently held by the agent.
53.Pp
54The idea is that the agent is run in the user's local PC, laptop, or
55terminal. Authentication data need not be stored on any other
56machine, and authentication passphrases never go over the network.
57However, the connection to the agent is forwarded over SSH
58remote logins, and the user can thus use the privileges given by the
59identities anywhere in the network in a secure way.
60.Pp
61A connection to the agent is inherited by child programs:
62A unix-domain socket is created
63.Pq Pa /tmp/ssh-XXXX/agent.<pid> ,
64and the name of this socket is stored in the
65.Ev SSH_AUTH_SOCK
66environment
67variable. The socket is made accessible only to the current user.
68This method is easily abused by root or another instance of the same
69user.
70.Pp
71The agent exits automatically when the command given on the command
72line terminates.
73.Sh FILES
74.Bl -tag -width Ds
75.It Pa $HOME/.ssh/identity
76Contains the RSA authentication identity of the user. This file
77should not be readable by anyone but the user. It is possible to
78specify a passphrase when generating the key; that passphrase will be
79used to encrypt the private part of this file. This file
80is not used by
81.Nm
82but is normally added to the agent using
83.Xr ssh-add 1
84at login time.
85.It Pa /tmp/ssh-XXXX/agent.<pid> ,
86Unix-domain sockets used to contain the connection to the
87authentication agent. These sockets should only be readable by the
88owner. The sockets should get automatically removed when the agent
89exits.
90.Sh AUTHOR
91Tatu Ylonen <ylo@cs.hut.fi>
92.Pp
93OpenSSH
94is a derivative of the original (free) ssh 1.2.12 release, but with bugs
95removed and newer features re-added. Rapidly after the 1.2.12 release,
96newer versions bore successively more restrictive licenses. This version
97of OpenSSH
98.Bl -bullet
99.It
100has all components of a restrictive nature (ie. patents, see
101.Xr ssl 8 )
102directly removed from the source code; any licensed or patented components
103are chosen from
104external libraries.
105.It
106has been updated to support ssh protocol 1.5.
107.It
108contains added support for
109.Xr kerberos 8
110authentication and ticket passing.
111.It
112supports one-time password authentication with
113.Xr skey 1 .
114.El
115.Pp
116The libraries described in
117.Xr ssl 8
118are required for proper operation.
119.Sh SEE ALSO
120.Xr ssh 1 ,
121.Xr ssh-add 1 ,
122.Xr ssh-keygen 1 ,
123.Xr sshd 8 ,
124.Xr ssl 8
diff --git a/ssh-agent.c b/ssh-agent.c
new file mode 100644
index 000000000..19165b8f1
--- /dev/null
+++ b/ssh-agent.c
@@ -0,0 +1,572 @@
1/*
2
3ssh-agent.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Wed Mar 29 03:46:59 1995 ylo
11
12The authentication agent program.
13
14*/
15
16#include "includes.h"
17RCSID("$Id: ssh-agent.c,v 1.1 1999/10/27 03:42:45 damien Exp $");
18
19#include "ssh.h"
20#include "rsa.h"
21#include "authfd.h"
22#include "buffer.h"
23#include "bufaux.h"
24#include "xmalloc.h"
25#include "packet.h"
26#include "getput.h"
27#include "mpaux.h"
28
29#include <openssl/md5.h>
30
31typedef struct
32{
33 int fd;
34 enum { AUTH_UNUSED, AUTH_SOCKET, AUTH_CONNECTION } type;
35 Buffer input;
36 Buffer output;
37} SocketEntry;
38
39unsigned int sockets_alloc = 0;
40SocketEntry *sockets = NULL;
41
42typedef struct
43{
44 RSA *key;
45 char *comment;
46} Identity;
47
48unsigned int num_identities = 0;
49Identity *identities = NULL;
50
51int max_fd = 0;
52
53/* pid of shell == parent of agent */
54int parent_pid = -1;
55
56/* pathname and directory for AUTH_SOCKET */
57char socket_name[1024];
58char socket_dir[1024];
59
60void
61process_request_identity(SocketEntry *e)
62{
63 Buffer msg;
64 int i;
65
66 buffer_init(&msg);
67 buffer_put_char(&msg, SSH_AGENT_RSA_IDENTITIES_ANSWER);
68 buffer_put_int(&msg, num_identities);
69 for (i = 0; i < num_identities; i++)
70 {
71 buffer_put_int(&msg, BN_num_bits(identities[i].key->n));
72 buffer_put_bignum(&msg, identities[i].key->e);
73 buffer_put_bignum(&msg, identities[i].key->n);
74 buffer_put_string(&msg, identities[i].comment,
75 strlen(identities[i].comment));
76 }
77 buffer_put_int(&e->output, buffer_len(&msg));
78 buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
79 buffer_free(&msg);
80}
81
82void
83process_authentication_challenge(SocketEntry *e)
84{
85 int i, pub_bits, len;
86 BIGNUM *pub_e, *pub_n, *challenge;
87 Buffer msg;
88 MD5_CTX md;
89 unsigned char buf[32], mdbuf[16], session_id[16];
90 unsigned int response_type;
91
92 buffer_init(&msg);
93 pub_e = BN_new();
94 pub_n = BN_new();
95 challenge = BN_new();
96 pub_bits = buffer_get_int(&e->input);
97 buffer_get_bignum(&e->input, pub_e);
98 buffer_get_bignum(&e->input, pub_n);
99 buffer_get_bignum(&e->input, challenge);
100 if (buffer_len(&e->input) == 0)
101 {
102 /* Compatibility code for old servers. */
103 memset(session_id, 0, 16);
104 response_type = 0;
105 }
106 else
107 {
108 /* New code. */
109 buffer_get(&e->input, (char *)session_id, 16);
110 response_type = buffer_get_int(&e->input);
111 }
112 for (i = 0; i < num_identities; i++)
113 if (pub_bits == BN_num_bits(identities[i].key->n) &&
114 BN_cmp(pub_e, identities[i].key->e) == 0 &&
115 BN_cmp(pub_n, identities[i].key->n) == 0)
116 {
117 /* Decrypt the challenge using the private key. */
118 rsa_private_decrypt(challenge, challenge, identities[i].key);
119
120 /* Compute the desired response. */
121 switch (response_type)
122 {
123 case 0: /* As of protocol 1.0 */
124 /* This response type is no longer supported. */
125 log("Compatibility with ssh protocol 1.0 no longer supported.");
126 buffer_put_char(&msg, SSH_AGENT_FAILURE);
127 goto send;
128
129 case 1: /* As of protocol 1.1 */
130 /* The response is MD5 of decrypted challenge plus session id. */
131 len = BN_num_bytes(challenge);
132 assert(len <= 32 && len);
133 memset(buf, 0, 32);
134 BN_bn2bin(challenge, buf + 32 - len);
135 MD5_Init(&md);
136 MD5_Update(&md, buf, 32);
137 MD5_Update(&md, session_id, 16);
138 MD5_Final(mdbuf, &md);
139 break;
140
141 default:
142 fatal("process_authentication_challenge: bad response_type %d",
143 response_type);
144 break;
145 }
146
147 /* Send the response. */
148 buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE);
149 for (i = 0; i < 16; i++)
150 buffer_put_char(&msg, mdbuf[i]);
151
152 goto send;
153 }
154 /* Unknown identity. Send failure. */
155 buffer_put_char(&msg, SSH_AGENT_FAILURE);
156 send:
157 buffer_put_int(&e->output, buffer_len(&msg));
158 buffer_append(&e->output, buffer_ptr(&msg),
159 buffer_len(&msg));
160 buffer_free(&msg);
161 BN_clear_free(pub_e);
162 BN_clear_free(pub_n);
163 BN_clear_free(challenge);
164}
165
166void
167process_remove_identity(SocketEntry *e)
168{
169 unsigned int bits;
170 unsigned int i;
171 BIGNUM *dummy, *n;
172
173 dummy = BN_new();
174 n = BN_new();
175
176 /* Get the key from the packet. */
177 bits = buffer_get_int(&e->input);
178 buffer_get_bignum(&e->input, dummy);
179 buffer_get_bignum(&e->input, n);
180
181 /* Check if we have the key. */
182 for (i = 0; i < num_identities; i++)
183 if (BN_cmp(identities[i].key->n, n) == 0)
184 {
185 /* We have this key. Free the old key. Since we don\'t want to leave
186 empty slots in the middle of the array, we actually free the
187 key there and copy data from the last entry. */
188 RSA_free(identities[i].key);
189 xfree(identities[i].comment);
190 if (i < num_identities - 1)
191 identities[i] = identities[num_identities - 1];
192 num_identities--;
193 BN_clear_free(dummy);
194 BN_clear_free(n);
195
196 /* Send success. */
197 buffer_put_int(&e->output, 1);
198 buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
199 return;
200 }
201 /* We did not have the key. */
202 BN_clear(dummy);
203 BN_clear(n);
204
205 /* Send failure. */
206 buffer_put_int(&e->output, 1);
207 buffer_put_char(&e->output, SSH_AGENT_FAILURE);
208}
209
210/* Removes all identities from the agent. */
211
212void
213process_remove_all_identities(SocketEntry *e)
214{
215 unsigned int i;
216
217 /* Loop over all identities and clear the keys. */
218 for (i = 0; i < num_identities; i++)
219 {
220 RSA_free(identities[i].key);
221 xfree(identities[i].comment);
222 }
223
224 /* Mark that there are no identities. */
225 num_identities = 0;
226
227 /* Send success. */
228 buffer_put_int(&e->output, 1);
229 buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
230 return;
231}
232
233/* Adds an identity to the agent. */
234
235void
236process_add_identity(SocketEntry *e)
237{
238 RSA *k;
239 int i;
240 BIGNUM *aux;
241 BN_CTX *ctx;
242
243 if (num_identities == 0)
244 identities = xmalloc(sizeof(Identity));
245 else
246 identities = xrealloc(identities, (num_identities + 1) * sizeof(Identity));
247
248 identities[num_identities].key = RSA_new();
249 k = identities[num_identities].key;
250 buffer_get_int(&e->input); /* bits */
251 k->n = BN_new();
252 buffer_get_bignum(&e->input, k->n);
253 k->e = BN_new();
254 buffer_get_bignum(&e->input, k->e);
255 k->d = BN_new();
256 buffer_get_bignum(&e->input, k->d);
257 k->iqmp = BN_new();
258 buffer_get_bignum(&e->input, k->iqmp);
259 /* SSH and SSL have p and q swapped */
260 k->q = BN_new();
261 buffer_get_bignum(&e->input, k->q); /* p */
262 k->p = BN_new();
263 buffer_get_bignum(&e->input, k->p); /* q */
264
265 /* Generate additional parameters */
266 aux = BN_new();
267 ctx = BN_CTX_new();
268
269 BN_sub(aux, k->q, BN_value_one());
270 k->dmq1 = BN_new();
271 BN_mod(k->dmq1, k->d, aux, ctx);
272
273 BN_sub(aux, k->p, BN_value_one());
274 k->dmp1 = BN_new();
275 BN_mod(k->dmp1, k->d, aux, ctx);
276
277 BN_clear_free(aux);
278 BN_CTX_free(ctx);
279
280 identities[num_identities].comment = buffer_get_string(&e->input, NULL);
281
282 /* Check if we already have the key. */
283 for (i = 0; i < num_identities; i++)
284 if (BN_cmp(identities[i].key->n, k->n) == 0)
285 {
286 /* We already have this key. Clear and free the new data and
287 return success. */
288 RSA_free(k);
289 xfree(identities[num_identities].comment);
290
291 /* Send success. */
292 buffer_put_int(&e->output, 1);
293 buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
294 return;
295 }
296
297 /* Increment the number of identities. */
298 num_identities++;
299
300 /* Send a success message. */
301 buffer_put_int(&e->output, 1);
302 buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
303}
304
305void
306process_message(SocketEntry *e)
307{
308 unsigned int msg_len;
309 unsigned int type;
310 unsigned char *cp;
311 if (buffer_len(&e->input) < 5)
312 return; /* Incomplete message. */
313 cp = (unsigned char *)buffer_ptr(&e->input);
314 msg_len = GET_32BIT(cp);
315 if (msg_len > 256 * 1024)
316 {
317 shutdown(e->fd, SHUT_RDWR);
318 close(e->fd);
319 e->type = AUTH_UNUSED;
320 return;
321 }
322 if (buffer_len(&e->input) < msg_len + 4)
323 return;
324 buffer_consume(&e->input, 4);
325 type = buffer_get_char(&e->input);
326
327 switch (type)
328 {
329 case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
330 process_request_identity(e);
331 break;
332 case SSH_AGENTC_RSA_CHALLENGE:
333 process_authentication_challenge(e);
334 break;
335 case SSH_AGENTC_ADD_RSA_IDENTITY:
336 process_add_identity(e);
337 break;
338 case SSH_AGENTC_REMOVE_RSA_IDENTITY:
339 process_remove_identity(e);
340 break;
341 case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
342 process_remove_all_identities(e);
343 break;
344 default:
345 /* Unknown message. Respond with failure. */
346 error("Unknown message %d", type);
347 buffer_clear(&e->input);
348 buffer_put_int(&e->output, 1);
349 buffer_put_char(&e->output, SSH_AGENT_FAILURE);
350 break;
351 }
352}
353
354void
355new_socket(int type, int fd)
356{
357 unsigned int i, old_alloc;
358 if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
359 error("fcntl O_NONBLOCK: %s", strerror(errno));
360
361 if (fd > max_fd)
362 max_fd = fd;
363
364 for (i = 0; i < sockets_alloc; i++)
365 if (sockets[i].type == AUTH_UNUSED)
366 {
367 sockets[i].fd = fd;
368 sockets[i].type = type;
369 buffer_init(&sockets[i].input);
370 buffer_init(&sockets[i].output);
371 return;
372 }
373 old_alloc = sockets_alloc;
374 sockets_alloc += 10;
375 if (sockets)
376 sockets = xrealloc(sockets, sockets_alloc * sizeof(sockets[0]));
377 else
378 sockets = xmalloc(sockets_alloc * sizeof(sockets[0]));
379 for (i = old_alloc; i < sockets_alloc; i++)
380 sockets[i].type = AUTH_UNUSED;
381 sockets[old_alloc].type = type;
382 sockets[old_alloc].fd = fd;
383 buffer_init(&sockets[old_alloc].input);
384 buffer_init(&sockets[old_alloc].output);
385}
386
387void
388prepare_select(fd_set *readset, fd_set *writeset)
389{
390 unsigned int i;
391 for (i = 0; i < sockets_alloc; i++)
392 switch (sockets[i].type)
393 {
394 case AUTH_SOCKET:
395 case AUTH_CONNECTION:
396 FD_SET(sockets[i].fd, readset);
397 if (buffer_len(&sockets[i].output) > 0)
398 FD_SET(sockets[i].fd, writeset);
399 break;
400 case AUTH_UNUSED:
401 break;
402 default:
403 fatal("Unknown socket type %d", sockets[i].type);
404 break;
405 }
406}
407
408void after_select(fd_set *readset, fd_set *writeset)
409{
410 unsigned int i;
411 int len, sock;
412 char buf[1024];
413 struct sockaddr_un sunaddr;
414
415 for (i = 0; i < sockets_alloc; i++)
416 switch (sockets[i].type)
417 {
418 case AUTH_UNUSED:
419 break;
420 case AUTH_SOCKET:
421 if (FD_ISSET(sockets[i].fd, readset))
422 {
423 len = sizeof(sunaddr);
424 sock = accept(sockets[i].fd, (struct sockaddr *)&sunaddr, &len);
425 if (sock < 0)
426 {
427 perror("accept from AUTH_SOCKET");
428 break;
429 }
430 new_socket(AUTH_CONNECTION, sock);
431 }
432 break;
433 case AUTH_CONNECTION:
434 if (buffer_len(&sockets[i].output) > 0 &&
435 FD_ISSET(sockets[i].fd, writeset))
436 {
437 len = write(sockets[i].fd, buffer_ptr(&sockets[i].output),
438 buffer_len(&sockets[i].output));
439 if (len <= 0)
440 {
441 shutdown(sockets[i].fd, SHUT_RDWR);
442 close(sockets[i].fd);
443 sockets[i].type = AUTH_UNUSED;
444 break;
445 }
446 buffer_consume(&sockets[i].output, len);
447 }
448 if (FD_ISSET(sockets[i].fd, readset))
449 {
450 len = read(sockets[i].fd, buf, sizeof(buf));
451 if (len <= 0)
452 {
453 shutdown(sockets[i].fd, SHUT_RDWR);
454 close(sockets[i].fd);
455 sockets[i].type = AUTH_UNUSED;
456 break;
457 }
458 buffer_append(&sockets[i].input, buf, len);
459 process_message(&sockets[i]);
460 }
461 break;
462 default:
463 fatal("Unknown type %d", sockets[i].type);
464 }
465}
466
467void
468check_parent_exists(int sig)
469{
470 if (kill(parent_pid, 0) < 0)
471 {
472 /* printf("Parent has died - Authentication agent exiting.\n"); */
473 exit(1);
474 }
475 signal(SIGALRM, check_parent_exists);
476 alarm(10);
477}
478
479void cleanup_socket(void) {
480 remove(socket_name);
481 rmdir(socket_dir);
482}
483
484int
485main(int ac, char **av)
486{
487 fd_set readset, writeset;
488 int sock;
489 struct sockaddr_un sunaddr;
490
491 /* check if RSA support exists */
492 if (rsa_alive() == 0) {
493 extern char *__progname;
494 fprintf(stderr,
495 "%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
496 __progname);
497 exit(1);
498 }
499
500 if (ac < 2)
501 {
502 fprintf(stderr, "ssh-agent version %s\n", SSH_VERSION);
503 fprintf(stderr, "Usage: %s command\n", av[0]);
504 exit(1);
505 }
506
507 parent_pid = getpid();
508
509 /* Create private directory for agent socket */
510 strlcpy(socket_dir, "/tmp/ssh-XXXXXXXX", sizeof socket_dir);
511 if (mkdtemp(socket_dir) == NULL) {
512 perror("mkdtemp: private socket dir");
513 exit(1);
514 }
515 snprintf(socket_name, sizeof socket_name, "%s/agent.%d", socket_dir, parent_pid);
516
517 /* Fork, and have the parent execute the command. The child continues as
518 the authentication agent. */
519 if (fork() != 0)
520 { /* Parent - execute the given command. */
521 setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1);
522 execvp(av[1], av + 1);
523 perror(av[1]);
524 exit(1);
525 }
526
527 if (atexit(cleanup_socket) < 0) {
528 perror("atexit");
529 cleanup_socket();
530 exit(1);
531 }
532
533 sock = socket(AF_UNIX, SOCK_STREAM, 0);
534 if (sock < 0)
535 {
536 perror("socket");
537 exit(1);
538 }
539 memset(&sunaddr, 0, sizeof(sunaddr));
540 sunaddr.sun_family = AF_UNIX;
541 strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path));
542 if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0)
543 {
544 perror("bind");
545 exit(1);
546 }
547 if (listen(sock, 5) < 0)
548 {
549 perror("listen");
550 exit(1);
551 }
552 new_socket(AUTH_SOCKET, sock);
553 signal(SIGALRM, check_parent_exists);
554 alarm(10);
555
556 signal(SIGINT, SIG_IGN);
557 while (1)
558 {
559 FD_ZERO(&readset);
560 FD_ZERO(&writeset);
561 prepare_select(&readset, &writeset);
562 if (select(max_fd + 1, &readset, &writeset, NULL, NULL) < 0)
563 {
564 if (errno == EINTR)
565 continue;
566 perror("select");
567 exit(1);
568 }
569 after_select(&readset, &writeset);
570 }
571 /*NOTREACHED*/
572}
diff --git a/ssh-keygen.1 b/ssh-keygen.1
new file mode 100644
index 000000000..67fbfd2c7
--- /dev/null
+++ b/ssh-keygen.1
@@ -0,0 +1,155 @@
1.\" -*- nroff -*-
2.\"
3.\" ssh-keygen.1
4.\"
5.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
6.\"
7.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8.\" All rights reserved
9.\"
10.\" Created: Sat Apr 22 23:55:14 1995 ylo
11.\"
12.\" $Id: ssh-keygen.1,v 1.1 1999/10/27 03:42:45 damien Exp $
13.\"
14.Dd September 25, 1999
15.Dt SSH-KEYGEN 1
16.Os
17.Sh NAME
18.Nm ssh-keygen
19.Nd authentication key generation
20.Sh SYNOPSIS
21.Nm ssh-keygen
22.Op Fl q
23.Op Fl b Ar bits
24.Op Fl N Ar new_passphrase
25.Op Fl C Ar comment
26.Nm ssh-keygen
27.Fl p
28.Op Fl P Ar old_passphrase
29.Op Fl N Ar new_passphrase
30.Nm ssh-keygen
31.Fl c
32.Op Fl P Ar passphrase
33.Op Fl C Ar comment
34.Sh DESCRIPTION
35.Nm
36generates and manages authentication keys for
37.Xr ssh 1 .
38Normally each user wishing to use SSH
39with RSA authentication runs this once to create the authentication
40key in
41.Pa $HOME/.ssh/identity .
42Additionally, the system administrator may use this to generate host keys.
43.Pp
44Normally this program generates the key and asks for a file in which
45to store the private key. The public key is stored in a file with the
46same name but
47.Dq .pub
48appended. The program also asks for a
49passphrase. The passphrase may be empty to indicate no passphrase
50(host keys must have empty passphrase), or it may be a string of
51arbitrary length. Good passphrases are 10-30 characters long and are
52not simple sentences or otherwise easily guessable (English
53prose has only 1-2 bits of entropy per word, and provides very bad
54passphrases). The passphrase can be changed later by using the
55.Fl p
56option.
57.Pp
58There is no way to recover a lost passphrase. If the passphrase is
59lost or forgotten, you will have to generate a new key and copy the
60corresponding public key to other machines.
61.Pp
62There is also a comment field in the key file that is only for
63convenience to the user to help identify the key. The comment can
64tell what the key is for, or whatever is useful. The comment is
65initialized to
66.Dq user@host
67when the key is created, but can be changed using the
68.Fl c
69option.
70.Pp
71The options are as follows:
72.Bl -tag -width Ds
73.It Fl b Ar bits
74Specifies the number of bits in the key to create. Minimum is 512
75bits. Generally 1024 bits is considered sufficient, and key sizes
76above that no longer improve security but make things slower. The
77default is 1024 bits.
78.It Fl c
79Requests changing the comment in the private and public key files.
80The program will prompt for the file containing the private keys, for
81passphrase if the key has one, and for the new comment.
82.It Fl p
83Requests changing the passphrase of a private key file instead of
84creating a new private key. The program will prompt for the file
85containing the private key, for the old passphrase, and twice for the
86new passphrase.
87.It Fl q
88Silence
89.Nm ssh-keygen .
90Used by
91.Pa /etc/rc
92when creating a new key.
93.It Fl C Ar comment
94Provides the new comment.
95.It Fl N Ar new_passphrase
96Provides the new passphrase.
97.It Fl P Ar passphrase
98Provides the (old) passphrase.
99.El
100.Sh FILES
101.Bl -tag -width Ds
102.It Pa $HOME/.ssh/random_seed
103Used for seeding the random number generator. This file should not be
104readable by anyone but the user. This file is created the first time
105the program is run, and is updated every time.
106.It Pa $HOME/.ssh/identity
107Contains the RSA authentication identity of the user. This file
108should not be readable by anyone but the user. It is possible to
109specify a passphrase when generating the key; that passphrase will be
110used to encrypt the private part of this file using 3DES. This file
111is not automatically accessed by
112.Nm
113but it is offered as the default file for the private key.
114.It Pa $HOME/.ssh/identity.pub
115Contains the public key for authentication. The contents of this file
116should be added to
117.Pa $HOME/.ssh/authorized_keys
118on all machines
119where you wish to log in using RSA authentication. There is no
120need to keep the contents of this file secret.
121.Sh AUTHOR
122Tatu Ylonen <ylo@cs.hut.fi>
123.Pp
124OpenSSH
125is a derivative of the original (free) ssh 1.2.12 release, but with bugs
126removed and newer features re-added. Rapidly after the 1.2.12 release,
127newer versions bore successively more restrictive licenses. This version
128of OpenSSH
129.Bl -bullet
130.It
131has all components of a restrictive nature (ie. patents, see
132.Xr ssl 8 )
133directly removed from the source code; any licensed or patented components
134are chosen from
135external libraries.
136.It
137has been updated to support ssh protocol 1.5.
138.It
139contains added support for
140.Xr kerberos 8
141authentication and ticket passing.
142.It
143supports one-time password authentication with
144.Xr skey 1 .
145.El
146.Pp
147The libraries described in
148.Xr ssl 8
149are required for proper operation.
150.Sh SEE ALSO
151.Xr ssh 1 ,
152.Xr ssh-add 1 ,
153.Xr ssh-agent 1,
154.Xr sshd 8 ,
155.Xr ssl 8
diff --git a/ssh-keygen.c b/ssh-keygen.c
new file mode 100644
index 000000000..2ba64e756
--- /dev/null
+++ b/ssh-keygen.c
@@ -0,0 +1,552 @@
1/*
2
3ssh-keygen.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Mon Mar 27 02:26:40 1995 ylo
11
12Identity and host key generation and maintenance.
13
14*/
15
16#include "includes.h"
17RCSID("$Id: ssh-keygen.c,v 1.1 1999/10/27 03:42:45 damien Exp $");
18
19#include "rsa.h"
20#include "ssh.h"
21#include "xmalloc.h"
22
23/* Generated private key. */
24RSA *private_key;
25
26/* Generated public key. */
27RSA *public_key;
28
29/* Number of bits in the RSA key. This value can be changed on the command
30 line. */
31int bits = 1024;
32
33/* Flag indicating that we just want to change the passphrase. This can be
34 set on the command line. */
35int change_passphrase = 0;
36
37/* Flag indicating that we just want to change the comment. This can be set
38 on the command line. */
39int change_comment = 0;
40
41int quiet = 0;
42
43/* This is set to the identity file name if given on the command line. */
44char *identity_file = NULL;
45
46/* This is set to the passphrase if given on the command line. */
47char *identity_passphrase = NULL;
48
49/* This is set to the new passphrase if given on the command line. */
50char *identity_new_passphrase = NULL;
51
52/* This is set to the new comment if given on the command line. */
53char *identity_comment = NULL;
54
55/* Perform changing a passphrase. The argument is the passwd structure
56 for the current user. */
57
58void
59do_change_passphrase(struct passwd *pw)
60{
61 char buf[1024], *comment;
62 char *old_passphrase, *passphrase1, *passphrase2;
63 struct stat st;
64 RSA *private_key;
65
66 /* Read key file name. */
67 if (identity_file != NULL) {
68 strncpy(buf, identity_file, sizeof(buf));
69 buf[sizeof(buf) - 1] = '\0';
70 } else {
71 printf("Enter file in which the key is ($HOME/%s): ", SSH_CLIENT_IDENTITY);
72 fflush(stdout);
73 if (fgets(buf, sizeof(buf), stdin) == NULL)
74 exit(1);
75 if (strchr(buf, '\n'))
76 *strchr(buf, '\n') = 0;
77 if (strcmp(buf, "") == 0)
78 snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);
79 }
80
81 /* Check if the file exists. */
82 if (stat(buf, &st) < 0)
83 {
84 perror(buf);
85 exit(1);
86 }
87
88 /* Try to load the public key from the file the verify that it is
89 readable and of the proper format. */
90 public_key = RSA_new();
91 if (!load_public_key(buf, public_key, NULL))
92 {
93 printf("%s is not a valid key file.\n", buf);
94 exit(1);
95 }
96 /* Clear the public key since we are just about to load the whole file. */
97 RSA_free(public_key);
98
99 /* Try to load the file with empty passphrase. */
100 private_key = RSA_new();
101 if (!load_private_key(buf, "", private_key, &comment)) {
102 /* Read passphrase from the user. */
103 if (identity_passphrase)
104 old_passphrase = xstrdup(identity_passphrase);
105 else
106 old_passphrase = read_passphrase("Enter old passphrase: ", 1);
107 /* Try to load using the passphrase. */
108 if (!load_private_key(buf, old_passphrase, private_key, &comment))
109 {
110 memset(old_passphrase, 0, strlen(old_passphrase));
111 xfree(old_passphrase);
112 printf("Bad passphrase.\n");
113 exit(1);
114 }
115 /* Destroy the passphrase. */
116 memset(old_passphrase, 0, strlen(old_passphrase));
117 xfree(old_passphrase);
118 }
119 printf("Key has comment '%s'\n", comment);
120
121 /* Ask the new passphrase (twice). */
122 if (identity_new_passphrase)
123 {
124 passphrase1 = xstrdup(identity_new_passphrase);
125 passphrase2 = NULL;
126 }
127 else
128 {
129 passphrase1 =
130 read_passphrase("Enter new passphrase (empty for no passphrase): ", 1);
131 passphrase2 = read_passphrase("Enter same passphrase again: ", 1);
132
133 /* Verify that they are the same. */
134 if (strcmp(passphrase1, passphrase2) != 0)
135 {
136 memset(passphrase1, 0, strlen(passphrase1));
137 memset(passphrase2, 0, strlen(passphrase2));
138 xfree(passphrase1);
139 xfree(passphrase2);
140 printf("Pass phrases do not match. Try again.\n");
141 exit(1);
142 }
143 /* Destroy the other copy. */
144 memset(passphrase2, 0, strlen(passphrase2));
145 xfree(passphrase2);
146 }
147
148 /* Save the file using the new passphrase. */
149 if (!save_private_key(buf, passphrase1, private_key, comment))
150 {
151 printf("Saving the key failed: %s: %s.\n",
152 buf, strerror(errno));
153 memset(passphrase1, 0, strlen(passphrase1));
154 xfree(passphrase1);
155 RSA_free(private_key);
156 xfree(comment);
157 exit(1);
158 }
159 /* Destroy the passphrase and the copy of the key in memory. */
160 memset(passphrase1, 0, strlen(passphrase1));
161 xfree(passphrase1);
162 RSA_free(private_key); /* Destroys contents */
163 xfree(comment);
164
165 printf("Your identification has been saved with the new passphrase.\n");
166 exit(0);
167}
168
169/* Change the comment of a private key file. */
170
171void
172do_change_comment(struct passwd *pw)
173{
174 char buf[1024], new_comment[1024], *comment;
175 RSA *private_key;
176 char *passphrase;
177 struct stat st;
178 FILE *f;
179 char *tmpbuf;
180
181 /* Read key file name. */
182 if (identity_file)
183 {
184 strncpy(buf, identity_file, sizeof(buf));
185 buf[sizeof(buf) - 1] = '\0';
186 }
187 else
188 {
189 printf("Enter file in which the key is ($HOME/%s): ",
190 SSH_CLIENT_IDENTITY);
191 fflush(stdout);
192 if (fgets(buf, sizeof(buf), stdin) == NULL)
193 exit(1);
194 if (strchr(buf, '\n'))
195 *strchr(buf, '\n') = 0;
196 if (strcmp(buf, "") == 0)
197 snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);
198 }
199
200 /* Check if the file exists. */
201 if (stat(buf, &st) < 0)
202 {
203 perror(buf);
204 exit(1);
205 }
206
207 /* Try to load the public key from the file the verify that it is
208 readable and of the proper format. */
209 public_key = RSA_new();
210 if (!load_public_key(buf, public_key, NULL))
211 {
212 printf("%s is not a valid key file.\n", buf);
213 exit(1);
214 }
215
216 private_key = RSA_new();
217 /* Try to load the file with empty passphrase. */
218 if (load_private_key(buf, "", private_key, &comment))
219 passphrase = xstrdup("");
220 else
221 {
222 /* Read passphrase from the user. */
223 if (identity_passphrase)
224 passphrase = xstrdup(identity_passphrase);
225 else
226 if (identity_new_passphrase)
227 passphrase = xstrdup(identity_new_passphrase);
228 else
229 passphrase = read_passphrase("Enter passphrase: ", 1);
230 /* Try to load using the passphrase. */
231 if (!load_private_key(buf, passphrase, private_key, &comment))
232 {
233 memset(passphrase, 0, strlen(passphrase));
234 xfree(passphrase);
235 printf("Bad passphrase.\n");
236 exit(1);
237 }
238 }
239 printf("Key now has comment '%s'\n", comment);
240
241 if (identity_comment)
242 {
243 strncpy(new_comment, identity_comment, sizeof(new_comment));
244 new_comment[sizeof(new_comment) - 1] = '\0';
245 }
246 else
247 {
248 printf("Enter new comment: ");
249 fflush(stdout);
250 if (!fgets(new_comment, sizeof(new_comment), stdin))
251 {
252 memset(passphrase, 0, strlen(passphrase));
253 RSA_free(private_key);
254 exit(1);
255 }
256
257 /* Remove terminating newline from comment. */
258 if (strchr(new_comment, '\n'))
259 *strchr(new_comment, '\n') = 0;
260 }
261
262 /* Save the file using the new passphrase. */
263 if (!save_private_key(buf, passphrase, private_key, new_comment))
264 {
265 printf("Saving the key failed: %s: %s.\n",
266 buf, strerror(errno));
267 memset(passphrase, 0, strlen(passphrase));
268 xfree(passphrase);
269 RSA_free(private_key);
270 xfree(comment);
271 exit(1);
272 }
273
274 /* Destroy the passphrase and the private key in memory. */
275 memset(passphrase, 0, strlen(passphrase));
276 xfree(passphrase);
277 RSA_free(private_key);
278
279 /* Save the public key in text format in a file with the same name but
280 .pub appended. */
281 strcat(buf, ".pub");
282 f = fopen(buf, "w");
283 if (!f)
284 {
285 printf("Could not save your public key in %s\n", buf);
286 exit(1);
287 }
288 fprintf(f, "%d ", BN_num_bits(public_key->n));
289 tmpbuf = BN_bn2dec(public_key->e);
290 fprintf(f, "%s ", tmpbuf);
291 free (tmpbuf);
292 tmpbuf = BN_bn2dec(public_key->n);
293 fprintf(f, "%s %s\n", tmpbuf, new_comment);
294 free (tmpbuf);
295 fclose(f);
296
297 xfree(comment);
298
299 printf("The comment in your key file has been changed.\n");
300 exit(0);
301}
302
303/* Main program for key management. */
304
305int
306main(int ac, char **av)
307{
308 char buf[16384], buf2[1024], *passphrase1, *passphrase2;
309 struct passwd *pw;
310 char *tmpbuf;
311 int opt;
312 struct stat st;
313 FILE *f;
314 char hostname[MAXHOSTNAMELEN];
315 extern int optind;
316 extern char *optarg;
317
318 /* check if RSA support exists */
319 if (rsa_alive() == 0) {
320 extern char *__progname;
321
322 fprintf(stderr,
323 "%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
324 __progname);
325 exit(1);
326 }
327
328 /* Get user\'s passwd structure. We need this for the home directory. */
329 pw = getpwuid(getuid());
330 if (!pw)
331 {
332 printf("You don't exist, go away!\n");
333 exit(1);
334 }
335
336 /* Create ~/.ssh directory if it doesn\'t already exist. */
337 snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, SSH_USER_DIR);
338 if (stat(buf, &st) < 0)
339 if (mkdir(buf, 0755) < 0)
340 error("Could not create directory '%s'.", buf);
341
342 /* Parse command line arguments. */
343 while ((opt = getopt(ac, av, "qpcb:f:P:N:C:")) != EOF)
344 {
345 switch (opt)
346 {
347 case 'b':
348 bits = atoi(optarg);
349 if (bits < 512 || bits > 32768)
350 {
351 printf("Bits has bad value.\n");
352 exit(1);
353 }
354 break;
355
356 case 'p':
357 change_passphrase = 1;
358 break;
359
360 case 'c':
361 change_comment = 1;
362 break;
363
364 case 'f':
365 identity_file = optarg;
366 break;
367
368 case 'P':
369 identity_passphrase = optarg;
370 break;
371
372 case 'N':
373 identity_new_passphrase = optarg;
374 break;
375
376 case 'C':
377 identity_comment = optarg;
378 break;
379
380 case 'q':
381 quiet = 1;
382 break;
383
384 case '?':
385 default:
386 printf("ssh-keygen version %s\n", SSH_VERSION);
387 printf("Usage: %s [-b bits] [-p] [-c] [-f file] [-P pass] [-N new-pass] [-C comment]\n", av[0]);
388 exit(1);
389 }
390 }
391 if (optind < ac)
392 {
393 printf("Too many arguments.\n");
394 exit(1);
395 }
396 if (change_passphrase && change_comment)
397 {
398 printf("Can only have one of -p and -c.\n");
399 exit(1);
400 }
401
402 /* If the user requested to change the passphrase, do it now. This
403 function never returns. */
404 if (change_passphrase)
405 do_change_passphrase(pw);
406
407 /* If the user requested to change the comment, do it now. This function
408 never returns. */
409 if (change_comment)
410 do_change_comment(pw);
411
412 arc4random_stir();
413
414 if (quiet)
415 rsa_set_verbose(0);
416
417 /* Generate the rsa key pair. */
418 private_key = RSA_new();
419 public_key = RSA_new();
420 rsa_generate_key(private_key, public_key, bits);
421
422 ask_file_again:
423
424 /* Ask for a file to save the key in. */
425 if (identity_file)
426 {
427 strncpy(buf, identity_file, sizeof(buf));
428 buf[sizeof(buf) - 1] = '\0';
429 }
430 else
431 {
432 printf("Enter file in which to save the key ($HOME/%s): ",
433 SSH_CLIENT_IDENTITY);
434 fflush(stdout);
435 if (fgets(buf, sizeof(buf), stdin) == NULL)
436 exit(1);
437 if (strchr(buf, '\n'))
438 *strchr(buf, '\n') = 0;
439 if (strcmp(buf, "") == 0)
440 snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);
441 }
442
443 /* If the file aready exists, ask the user to confirm. */
444 if (stat(buf, &st) >= 0)
445 {
446 printf("%s already exists.\n", buf);
447 printf("Overwrite (y/n)? ");
448 fflush(stdout);
449 if (fgets(buf2, sizeof(buf2), stdin) == NULL)
450 exit(1);
451 if (buf2[0] != 'y' && buf2[0] != 'Y')
452 exit(1);
453 }
454
455 /* Ask for a passphrase (twice). */
456 if (identity_passphrase)
457 passphrase1 = xstrdup(identity_passphrase);
458 else
459 if (identity_new_passphrase)
460 passphrase1 = xstrdup(identity_new_passphrase);
461 else
462 {
463 passphrase_again:
464 passphrase1 =
465 read_passphrase("Enter passphrase (empty for no passphrase): ", 1);
466 passphrase2 = read_passphrase("Enter same passphrase again: ", 1);
467 if (strcmp(passphrase1, passphrase2) != 0)
468 {
469 /* The passphrases do not match. Clear them and retry. */
470 memset(passphrase1, 0, strlen(passphrase1));
471 memset(passphrase2, 0, strlen(passphrase2));
472 xfree(passphrase1);
473 xfree(passphrase2);
474 printf("Passphrases do not match. Try again.\n");
475 goto passphrase_again;
476 }
477 /* Clear the other copy of the passphrase. */
478 memset(passphrase2, 0, strlen(passphrase2));
479 xfree(passphrase2);
480 }
481
482 /* Create default commend field for the passphrase. The user can later
483 edit this field. */
484 if (identity_comment)
485 {
486 strlcpy(buf2, identity_comment, sizeof(buf2));
487 }
488 else
489 {
490 if (gethostname(hostname, sizeof(hostname)) < 0)
491 {
492 perror("gethostname");
493 exit(1);
494 }
495 snprintf(buf2, sizeof buf2, "%s@%s", pw->pw_name, hostname);
496 }
497
498 /* Save the key with the given passphrase and comment. */
499 if (!save_private_key(buf, passphrase1, private_key, buf2))
500 {
501 printf("Saving the key failed: %s: %s.\n",
502 buf, strerror(errno));
503 memset(passphrase1, 0, strlen(passphrase1));
504 xfree(passphrase1);
505 goto ask_file_again;
506 }
507 /* Clear the passphrase. */
508 memset(passphrase1, 0, strlen(passphrase1));
509 xfree(passphrase1);
510
511 /* Clear the private key and the random number generator. */
512 RSA_free(private_key);
513 arc4random_stir();
514
515 if (!quiet)
516 printf("Your identification has been saved in %s.\n", buf);
517
518 /* Display the public key on the screen. */
519 if (!quiet) {
520 printf("Your public key is:\n");
521 printf("%d ", BN_num_bits(public_key->n));
522 tmpbuf = BN_bn2dec(public_key->e);
523 printf("%s ", tmpbuf);
524 free(tmpbuf);
525 tmpbuf = BN_bn2dec(public_key->n);
526 printf("%s %s\n", tmpbuf, buf2);
527 free(tmpbuf);
528 }
529
530 /* Save the public key in text format in a file with the same name but
531 .pub appended. */
532 strcat(buf, ".pub");
533 f = fopen(buf, "w");
534 if (!f)
535 {
536 printf("Could not save your public key in %s\n", buf);
537 exit(1);
538 }
539 fprintf(f, "%d ", BN_num_bits(public_key->n));
540 tmpbuf = BN_bn2dec(public_key->e);
541 fprintf(f, "%s ", tmpbuf);
542 free(tmpbuf);
543 tmpbuf = BN_bn2dec(public_key->n);
544 fprintf(f, "%s %s\n", tmpbuf, buf2);
545 free(tmpbuf);
546 fclose(f);
547
548 if (!quiet)
549 printf("Your public key has been saved in %s\n", buf);
550
551 exit(0);
552}
diff --git a/ssh.1 b/ssh.1
new file mode 100644
index 000000000..a6d76a97f
--- /dev/null
+++ b/ssh.1
@@ -0,0 +1,966 @@
1.\" -*- nroff -*-
2.\"
3.\" ssh.1.in
4.\"
5.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
6.\"
7.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8.\" All rights reserved
9.\"
10.\" Created: Sat Apr 22 21:55:14 1995 ylo
11.\"
12.\" $Id: ssh.1,v 1.1 1999/10/27 03:42:45 damien Exp $
13.\"
14.Dd September 25, 1999
15.Dt SSH 1
16.Os
17.Sh NAME
18.Nm ssh
19.Nd OpenSSH secure shell client (remote login program)
20.Sh SYNOPSIS
21.Nm ssh
22.Op Fl l Ar login_name
23.Op Ar hostname | user@hostname
24.Op Ar command
25.Pp
26.Nm ssh
27.Op Fl afgknqtvxCPX
28.Op Fl c Ar blowfish | 3des
29.Op Fl e Ar escape_char
30.Op Fl i Ar identity_file
31.Op Fl l Ar login_name
32.Op Fl o Ar option
33.Op Fl p Ar port
34.Oo Fl L Xo
35.Sm off
36.Ar host :
37.Ar port :
38.Ar hostport
39.Sm on
40.Xc
41.Oc
42.Oo Fl R Xo
43.Sm off
44.Ar host :
45.Ar port :
46.Ar hostport
47.Sm on
48.Xc
49.Oc
50.Op Ar hostname | user@hostname
51.Op Ar command
52.Sh DESCRIPTION
53.Nm
54(Secure Shell) is a program for logging into a remote machine and for
55executing commands on a remote machine. It is intended to replace
56rlogin and rsh, and provide secure encrypted communications between
57two untrusted hosts over an insecure network. X11 connections and
58arbitrary TCP/IP ports can also be forwarded over the secure channel.
59.Pp
60.Nm
61connects and logs into the specified
62.Ar hostname .
63The user must prove
64his/her identity to the remote machine using one of several methods.
65.Pp
66First, if the machine the user logs in from is listed in
67.Pa /etc/hosts.equiv
68or
69.Pa /etc/shosts.equiv
70on the remote machine, and the user names are
71the same on both sides, the user is immediately permitted to log in.
72Second, if
73.Pa \&.rhosts
74or
75.Pa \&.shosts
76exists in the user's home directory on the
77remote machine and contains a line containing the name of the client
78machine and the name of the user on that machine, the user is
79permitted to log in. This form of authentication alone is normally not
80allowed by the server because it is not secure.
81.Pp
82The second (and primary) authentication method is the
83.Pa rhosts
84or
85.Pa hosts.equiv
86method combined with RSA-based host authentication. It
87means that if the login would be permitted by
88.Pa \&.rhosts ,
89.Pa \&.shosts ,
90.Pa /etc/hosts.equiv ,
91or
92.Pa /etc/shosts.equiv ,
93and if additionally the server can verify the client's
94host key (see
95.Pa /etc/ssh_known_hosts
96in the
97.Sx FILES
98section), only then login is
99permitted. This authentication method closes security holes due to IP
100spoofing, DNS spoofing and routing spoofing. [Note to the
101administrator:
102.Pa /etc/hosts.equiv ,
103.Pa \&.rhosts ,
104and the rlogin/rsh protocol in general, are inherently insecure and should be
105disabled if security is desired.]
106.Pp
107As a third authentication method,
108.Nm
109supports RSA based authentication.
110The scheme is based on public-key cryptography: there are cryptosystems
111where encryption and decryption are done using separate keys, and it
112is not possible to derive the decryption key from the encryption key.
113RSA is one such system. The idea is that each user creates a public/private
114key pair for authentication purposes. The
115server knows the public key, and only the user knows the private key.
116The file
117.Pa $HOME/.ssh/authorized_keys
118lists the public keys that are permitted for logging
119in. When the user logs in, the
120.Nm
121program tells the server which key pair it would like to use for
122authentication. The server checks if this key is permitted, and if
123so, sends the user (actually the
124.Nm
125program running on behalf of the user) a challenge, a random number,
126encrypted by the user's public key. The challenge can only be
127decrypted using the proper private key. The user's client then decrypts the
128challenge using the private key, proving that he/she knows the private
129key but without disclosing it to the server.
130.Pp
131.Nm
132implements the RSA authentication protocol automatically. The user
133creates his/her RSA key pair by running
134.Xr ssh-keygen 1 .
135This stores the private key in
136.Pa \&.ssh/identity
137and the public key in
138.Pa \&.ssh/identity.pub
139in the user's home directory. The user should then
140copy the
141.Pa identity.pub
142to
143.Pa \&.ssh/authorized_keys
144in his/her home directory on the remote machine (the
145.Pa authorized_keys
146file corresponds to the conventional
147.Pa \&.rhosts
148file, and has one key
149per line, though the lines can be very long). After this, the user
150can log in without giving the password. RSA authentication is much
151more secure than rhosts authentication.
152.Pp
153The most convenient way to use RSA authentication may be with an
154authentication agent. See
155.Xr ssh-agent 1
156for more information.
157.Pp
158If other authentication methods fail,
159.Nm
160prompts the user for a password. The password is sent to the remote
161host for checking; however, since all communications are encrypted,
162the password cannot be seen by someone listening on the network.
163.Pp
164When the user's identity has been accepted by the server, the server
165either executes the given command, or logs into the machine and gives
166the user a normal shell on the remote machine. All communication with
167the remote command or shell will be automatically encrypted.
168.Pp
169If a pseudo-terminal has been allocated (normal login session), the
170user can disconnect with
171.Ic ~. ,
172and suspend
173.Nm
174with
175.Ic ~^Z .
176All forwarded connections can be listed with
177.Ic ~#
178and if
179the session blocks waiting for forwarded X11 or TCP/IP
180connections to terminate, it can be backgrounded with
181.Ic ~&
182(this should not be used while the user shell is active, as it can cause the
183shell to hang). All available escapes can be listed with
184.Ic ~? .
185.Pp
186A single tilde character can be sent as
187.Ic ~~
188(or by following the tilde by a character other than those described above).
189The escape character must always follow a newline to be interpreted as
190special. The escape character can be changed in configuration files
191or on the command line.
192.Pp
193If no pseudo tty has been allocated, the
194session is transparent and can be used to reliably transfer binary
195data. On most systems, setting the escape character to
196.Dq none
197will also make the session transparent even if a tty is used.
198.Pp
199The session terminates when the command or shell in on the remote
200machine exists and all X11 and TCP/IP connections have been closed.
201The exit status of the remote program is returned as the exit status
202of
203.Nm ssh .
204.Pp
205If the user is using X11 (the
206.Ev DISPLAY
207environment variable is set), the connection to the X11 display is
208automatically forwarded to the remote side in such a way that any X11
209programs started from the shell (or command) will go through the
210encrypted channel, and the connection to the real X server will be made
211from the local machine. The user should not manually set
212.Ev DISPLAY .
213Forwarding of X11 connections can be
214configured on the command line or in configuration files.
215.Pp
216The
217.Ev DISPLAY
218value set by
219.Nm
220will point to the server machine, but with a display number greater
221than zero. This is normal, and happens because
222.Nm
223creates a
224.Dq proxy
225X server on the server machine for forwarding the
226connections over the encrypted channel.
227.Pp
228.Nm
229will also automatically set up Xauthority data on the server machine.
230For this purpose, it will generate a random authorization cookie,
231store it in Xauthority on the server, and verify that any forwarded
232connections carry this cookie and replace it by the real cookie when
233the connection is opened. The real authentication cookie is never
234sent to the server machine (and no cookies are sent in the plain).
235.Pp
236If the user is using an authentication agent, the connection to the agent
237is automatically forwarded to the remote side unless disabled on
238command line or in a configuration file.
239.Pp
240Forwarding of arbitrary TCP/IP connections over the secure channel can
241be specified either on command line or in a configuration file. One
242possible application of TCP/IP forwarding is a secure connection to an
243electronic purse; another is going trough firewalls.
244.Pp
245.Nm
246automatically maintains and checks a database containing RSA-based
247identifications for all hosts it has ever been used with. The
248database is stored in
249.Pa \&.ssh/known_hosts
250in the user's home directory. Additionally, the file
251.Pa /etc/ssh_known_hosts
252is automatically checked for known hosts. Any new hosts are
253automatically added to the user's file. If a host's identification
254ever changes,
255.Nm
256warns about this and disables password authentication to prevent a
257trojan horse from getting the user's password. Another purpose of
258this mechanism is to prevent man-in-the-middle attacks which could
259otherwise be used to circumvent the encryption. The
260.Cm StrictHostKeyChecking
261option (see below) can be used to prevent logins to machines whose
262host key is not known or has changed.
263.Sh OPTIONS
264.Bl -tag -width Ds
265.It Fl a
266Disables forwarding of the authentication agent connection. This may
267also be specified on a per-host basis in the configuration file.
268.It Fl c Ar blowfish|3des
269Selects the cipher to use for encrypting the session.
270.Ar 3des
271is used by default. It is believed to be secure.
272.Ar 3des
273(triple-des) is an encrypt-decrypt-encrypt triple with three different keys.
274It is presumably more secure than the
275.Ar des
276cipher which is no longer supported in ssh.
277.Ar blowfish
278is a fast block cipher, it appears very secure and is much faster than
279.Ar 3des .
280.It Fl e Ar ch|^ch|none
281Sets the escape character for sessions with a pty (default:
282.Ql ~ ) .
283The escape character is only recognized at the beginning of a line. The
284escape character followed by a dot
285.Pq Ql \&.
286closes the connection, followed
287by control-Z suspends the connection, and followed by itself sends the
288escape character once. Setting the character to
289.Dq none
290disables any escapes and makes the session fully transparent.
291.It Fl f
292Requests
293.Nm
294to go to background after authentication. This is useful
295if
296.Nm
297is going to ask for passwords or passphrases, but the user
298wants it in the background. This implies
299.Fl n .
300The recommended way to start X11 programs at a remote site is with
301something like
302.Ic ssh -f host xterm .
303.It Fl i Ar identity_file
304Selects the file from which the identity (private key) for
305RSA authentication is read. Default is
306.Pa \&.ssh/identity
307in the user's home directory. Identity files may also be specified on
308a per-host basis in the configuration file. It is possible to have
309multiple
310.Fl i
311options (and multiple identities specified in
312configuration files).
313.It Fl g
314Allows remote hosts to connect to local forwarded ports.
315.It Fl k
316Disables forwarding of Kerberos tickets and AFS tokens. This may
317also be specified on a per-host basis in the configuration file.
318.It Fl l Ar login_name
319Specifies the user to log in as on the remote machine. This may also
320be specified on a per-host basis in the configuration file.
321.It Fl n
322Redirects stdin from
323.Pa /dev/null
324(actually, prevents reading from stdin).
325This must be used when
326.Nm
327is run in the background. A common trick is to use this to run X11
328programs in a remote machine. For example,
329.Ic ssh -n shadows.cs.hut.fi emacs &
330will start an emacs on shadows.cs.hut.fi, and the X11
331connection will be automatically forwarded over an encrypted channel.
332The
333.Nm
334program will be put in the background.
335(This does not work if
336.Nm
337needs to ask for a password or passphrase; see also the
338.Fl f
339option.)
340.It Fl o Ar option
341Can be used to give options in the format used in the config file.
342This is useful for specifying options for which there is no separate
343command-line flag. The option has the same format as a line in the
344configuration file.
345.It Fl p Ar port
346Port to connect to on the remote host. This can be specified on a
347per-host basis in the configuration file.
348.It Fl P
349Use a non-privileged port for outgoing connections.
350This can be used if your firewall does
351not permit connections from privileged ports.
352Note that this option turns of
353.Cm RhostsAuthentication
354and
355.Cm RhostsRSAAuthentication .
356.It Fl q
357Quiet mode. Causes all warning and diagnostic messages to be
358suppressed. Only fatal errors are displayed.
359.It Fl t
360Force pseudo-tty allocation. This can be used to execute arbitary
361screen-based programs on a remote machine, which can be very useful
362e.g. when implementing menu services.
363.It Fl v
364Verbose mode. Causes
365.Nm
366to print debugging messages about its progress. This is helpful in
367debugging connection, authentication, and configuration problems.
368The verbose mode is also used to display
369.Xr skey 1
370challenges, if the user entered "s/key" as password.
371.It Fl x
372Disables X11 forwarding. This can also be specified on a per-host
373basis in a configuration file.
374.It Fl X
375Enables X11 forwarding.
376.It Fl C
377Requests compression of all data (including stdin, stdout, stderr, and
378data for forwarded X11 and TCP/IP connections). The compression
379algorithm is the same used by gzip, and the
380.Dq level
381can be controlled by the
382.Cm CompressionLevel
383option (see below). Compression is desirable on modem lines and other
384slow connections, but will only slow down things on fast networks.
385The default value can be set on a host-by-host basis in the
386configuration files; see the
387.Cm Compress
388option below.
389.It Fl L Ar port:host:hostport
390Specifies that the given port on the local (client) host is to be
391forwarded to the given host and port on the remote side. This works
392by allocating a socket to listen to
393.Ar port
394on the local side, and whenever a connection is made to this port, the
395connection is forwarded over the secure channel, and a connection is
396made to
397.Ar host:hostport
398from the remote machine. Port forwardings can also be specified in the
399configuration file. Only root can forward privileged ports.
400.It Fl R Ar port:host:hostport
401Specifies that the given port on the remote (server) host is to be
402forwarded to the given host and port on the local side. This works
403by allocating a socket to listen to
404.Ar port
405on the remote side, and whenever a connection is made to this port, the
406connection is forwarded over the secure channel, and a connection is
407made to
408.Ar host:hostport
409from the local machine. Port forwardings can also be specified in the
410configuration file. Privileged ports can be forwarded only when
411logging in as root on the remote machine.
412.El
413.Sh CONFIGURATION FILES
414.Nm
415obtains configuration data from the following sources (in this order):
416command line options, user's configuration file
417.Pq Pa $HOME/.ssh/config ,
418and system-wide configuration file
419.Pq Pa /etc/ssh_config .
420For each parameter, the first obtained value
421will be used. The configuration files contain sections bracketed by
422"Host" specifications, and that section is only applied for hosts that
423match one of the patterns given in the specification. The matched
424host name is the one given on the command line.
425.Pp
426Since the first obtained value for each parameter is used, more
427host-specific declarations should be given near the beginning of the
428file, and general defaults at the end.
429.Pp
430The configuration file has the following format:
431.Pp
432Empty lines and lines starting with
433.Ql #
434are comments.
435.Pp
436Otherwise a line is of the format
437.Dq keyword arguments .
438The possible
439keywords and their meanings are as follows (note that the
440configuration files are case-sensitive):
441.Bl -tag -width Ds
442.It Cm Host
443Restricts the following declarations (up to the next
444.Cm Host
445keyword) to be only for those hosts that match one of the patterns
446given after the keyword.
447.Ql \&*
448and
449.Ql ?
450can be used as wildcards in the
451patterns. A single
452.Ql \&*
453as a pattern can be used to provide global
454defaults for all hosts. The host is the
455.Ar hostname
456argument given on the command line (i.e., the name is not converted to
457a canonicalized host name before matching).
458.It Cm AFSTokenPassing
459Specifies whether to pass AFS tokens to remote host. The argument to
460this keyword must be
461.Dq yes
462or
463.Dq no .
464.It Cm BatchMode
465If set to
466.Dq yes ,
467passphrase/password querying will be disabled. This
468option is useful in scripts and other batch jobs where you have no
469user to supply the password. The argument must be
470.Dq yes
471or
472.Dq no .
473.It Cm Cipher
474Specifies the cipher to use for encrypting the session. Currently,
475.Dq blowfish ,
476and
477.Dq 3des
478are supported. The default is
479.Dq 3des .
480.It Cm Compression
481Specifies whether to use compression. The argument must be
482.Dq yes
483or
484.Dq no .
485.It Cm CompressionLevel
486Specifies the compression level to use if compression is enable. The
487argument must be an integer from 1 (fast) to 9 (slow, best). The
488default level is 6, which is good for most applications. The meaning
489of the values is the same as in GNU GZIP.
490.It Cm ConnectionAttempts
491Specifies the number of tries (one per second) to make before falling
492back to rsh or exiting. The argument must be an integer. This may be
493useful in scripts if the connection sometimes fails.
494.It Cm EscapeChar
495Sets the escape character (default:
496.Ql ~ ) .
497The escape character can also
498be set on the command line. The argument should be a single
499character,
500.Ql ^
501followed by a letter, or
502.Dq none
503to disable the escape
504character entirely (making the connection transparent for binary
505data).
506.It Cm FallBackToRsh
507Specifies that if connecting via
508.Nm
509fails due to a connection refused error (there is no
510.Xr sshd 8
511listening on the remote host),
512.Xr rsh 1
513should automatically be used instead (after a suitable warning about
514the session being unencrypted). The argument must be
515.Dq yes
516or
517.Dq no .
518.It Cm ForwardAgent
519Specifies whether the connection to the authentication agent (if any)
520will be forwarded to the remote machine. The argument must be
521.Dq yes
522or
523.Dq no .
524.It Cm ForwardX11
525Specifies whether X11 connections will be automatically redirected
526over the secure channel and
527.Ev DISPLAY
528set. The argument must be
529.Dq yes
530or
531.Dq no .
532.It Cm GatewayPorts
533Specifies whether remote hosts are allowed to connect to local
534forwarded ports.
535The argument must be
536.Dq yes
537or
538.Dq no .
539The default is
540.Dq no .
541.It Cm GlobalKnownHostsFile
542Specifies a file to use instead of
543.Pa /etc/ssh_known_hosts .
544.It Cm HostName
545Specifies the real host name to log into. This can be used to specify
546nicnames or abbreviations for hosts. Default is the name given on the
547command line. Numeric IP addresses are also permitted (both on the
548command line and in
549.Cm HostName
550specifications).
551.It Cm IdentityFile
552Specifies the file from which the user's RSA authentication identity
553is read (default
554.Pa .ssh/identity
555in the user's home directory).
556Additionally, any identities represented by the authentication agent
557will be used for authentication. The file name may use the tilde
558syntax to refer to a user's home directory. It is possible to have
559multiple identity files specified in configuration files; all these
560identities will be tried in sequence.
561.It Cm KeepAlive
562Specifies whether the system should send keepalive messages to the
563other side. If they are sent, death of the connection or crash of one
564of the machines will be properly noticed. However, this means that
565connections will die if the route is down temporarily, and some people
566find it annoying.
567.Pp
568The default is
569.Dq yes
570(to send keepalives), and the client will notice
571if the network goes down or the remote host dies. This is important
572in scripts, and many users want it too.
573.Pp
574To disable keepalives, the value should be set to
575.Dq no
576in both the server and the client configuration files.
577.It Cm KerberosAuthentication
578Specifies whether Kerberos authentication will be used. The argument to
579this keyword must be
580.Dq yes
581or
582.Dq no .
583.It Cm KerberosTgtPassing
584Specifies whether a Kerberos TGT will be forwarded to the server. This
585will only work if the Kerberos server is actually an AFS kaserver. The
586argument to this keyword must be
587.Dq yes
588or
589.Dq no .
590.It Cm LocalForward
591Specifies that a TCP/IP port on the local machine be forwarded over
592the secure channel to given host:port from the remote machine. The
593first argument must be a port number, and the second must be
594host:port. Multiple forwardings may be specified, and additional
595forwardings can be given on the command line. Only the root can
596forward privileged ports.
597.It Cm PasswordAuthentication
598Specifies whether to use password authentication. The argument to
599this keyword must be
600.Dq yes
601or
602.Dq no .
603.It Cm NumberOfPasswordPrompts
604Specifies the number of password prompts before giving up. The
605argument to this keyword must be an integer. Default is 3.
606.It Cm Port
607Specifies the port number to connect on the remote host. Default is
60822.
609.It Cm ProxyCommand
610Specifies the command to use to connect to the server. The command
611string extends to the end of the line, and is executed with /bin/sh.
612In the command string, %h will be substituted by the host name to
613connect and %p by the port. The command can be basically anything,
614and should read from its stdin and write to its stdout. It should
615eventually connect an
616.Xr sshd 8
617server running on some machine, or execute
618.Ic sshd -i
619somewhere. Host key management will be done using the
620HostName of the host being connected (defaulting to the name typed by
621the user).
622.Pp
623.It Cm RemoteForward
624Specifies that a TCP/IP port on the remote machine be forwarded over
625the secure channel to given host:port from the local machine. The
626first argument must be a port number, and the second must be
627host:port. Multiple forwardings may be specified, and additional
628forwardings can be given on the command line. Only the root can
629forward privileged ports.
630.It Cm RhostsAuthentication
631Specifies whether to try rhosts based authentication. Note that this
632declaration only affects the client side and has no effect whatsoever
633on security. Disabling rhosts authentication may reduce
634authentication time on slow connections when rhosts authentication is
635not used. Most servers do not permit RhostsAuthentication because it
636is not secure (see RhostsRSAAuthentication). The argument to this
637keyword must be
638.Dq yes
639or
640.Dq no .
641.It Cm RhostsRSAAuthentication
642Specifies whether to try rhosts based authentication with RSA host
643authentication. This is the primary authentication method for most
644sites. The argument must be
645.Dq yes
646or
647.Dq no .
648.It Cm RSAAuthentication
649Specifies whether to try RSA authentication. The argument to this
650keyword must be
651.Dq yes
652or
653.Dq no .
654RSA authentication will only be
655attempted if the identity file exists, or an authentication agent is
656running.
657.It Cm CheckHostIP
658If this flag is set to
659.Dq yes ,
660ssh will additionally check the host ip address in the
661.Pa known_hosts
662file. This allows ssh to detect if a host key changed due to DNS spoofing.
663If the option is set to
664.Dq no ,
665the check will not be executed.
666.It Cm StrictHostKeyChecking
667If this flag is set to
668.Dq yes ,
669.Nm
670ssh will never automatically add host keys to the
671.Pa $HOME/.ssh/known_hosts
672file, and refuses to connect hosts whose host key has changed. This
673provides maximum protection against trojan horse attacks. However, it
674can be somewhat annoying if you don't have good
675.Pa /etc/ssh_known_hosts
676files installed and frequently
677connect new hosts. Basically this option forces the user to manually
678add any new hosts. Normally this option is disabled, and new hosts
679will automatically be added to the known host files. The host keys of
680known hosts will be verified automatically in either case. The
681argument must be
682.Dq yes
683or
684.Dq no .
685.It Cm User
686Specifies the user to log in as. This can be useful if you have a
687different user name in different machines. This saves the trouble of
688having to remember to give the user name on the command line.
689.It Cm UserKnownHostsFile
690Specifies a file to use instead of
691.Pa $HOME/.ssh/known_hosts .
692.It Cm UsePrivilegedPort
693Specifies whether to use a privileged port for outgoing connections.
694The argument must be
695.Dq yes
696or
697.Dq no .
698The default is
699.Dq yes .
700Note that setting this option to
701.Dq no
702turns of
703.Cm RhostsAuthentication
704and
705.Cm RhostsRSAAuthentication .
706.It Cm UseRsh
707Specifies that rlogin/rsh should be used for this host. It is
708possible that the host does not at all support the
709.Nm
710protocol. This causes
711.Nm
712to immediately exec
713.Xr rsh 1 .
714All other options (except
715.Cm HostName )
716are ignored if this has been specified. The argument must be
717.Dq yes
718or
719.Dq no .
720.Sh ENVIRONMENT
721.Nm
722will normally set the following environment variables:
723.Bl -tag -width Ds
724.It Ev DISPLAY
725The
726.Ev DISPLAY
727variable indicates the location of the X11 server. It is
728automatically set by
729.Nm
730to point to a value of the form
731.Dq hostname:n
732where hostname indicates
733the host where the shell runs, and n is an integer >= 1. Ssh uses
734this special value to forward X11 connections over the secure
735channel. The user should normally not set DISPLAY explicitly, as that
736will render the X11 connection insecure (and will require the user to
737manually copy any required authorization cookies).
738.It Ev HOME
739Set to the path of the user's home directory.
740.It Ev LOGNAME
741Synonym for
742.Ev USER ;
743set for compatibility with systems that use this variable.
744.It Ev MAIL
745Set to point the user's mailbox.
746.It Ev PATH
747Set to the default
748.Ev PATH ,
749as specified when compiling
750.Nm ssh .
751.It Ev SSH_AUTH_SOCK
752indicates the path of a unix-domain socket used to communicate with the
753agent.
754.It Ev SSH_CLIENT
755Identifies the client end of the connection. The variable contains
756three space-separated values: client ip-address, client port number,
757and server port number.
758.It Ev SSH_TTY
759This is set to the name of the tty (path to the device) associated
760with the current shell or command. If the current session has no tty,
761this variable is not set.
762.It Ev TZ
763The timezone variable is set to indicate the present timezone if it
764was set when the daemon was started (e.i., the daemon passes the value
765on to new connections).
766.It Ev USER
767Set to the name of the user logging in.
768.El
769.Pp
770Additionally,
771.Nm
772reads
773.Pa $HOME/.ssh/environment ,
774and adds lines of the format
775.Dq VARNAME=value
776to the environment.
777.Sh FILES
778.Bl -tag -width $HOME/.ssh/known_hosts
779.It Pa $HOME/.ssh/known_hosts
780Records host keys for all hosts the user has logged into (that are not
781in
782.Pa /etc/ssh_known_hosts ) .
783See
784.Xr sshd 8 .
785.It Pa $HOME/.ssh/random_seed
786Used for seeding the random number generator. This file contains
787sensitive data and should read/write for the user and not accessible
788for others. This file is created the first time the program is run
789and updated automatically. The user should never need to read or
790modify this file.
791.It Pa $HOME/.ssh/identity
792Contains the RSA authentication identity of the user. This file
793contains sensitive data and should be readable by the user but not
794accessible by others (read/write/execute).
795Note that
796.Nm
797ignores this file if it is accessible by others.
798It is possible to specify a passphrase when
799generating the key; the passphrase will be used to encrypt the
800sensitive part of this file using 3DES.
801.It Pa $HOME/.ssh/identity.pub
802Contains the public key for authentication (public part of the
803identity file in human-readable form). The contents of this file
804should be added to
805.Pa $HOME/.ssh/authorized_keys
806on all machines
807where you wish to log in using RSA authentication. This file is not
808sensitive and can (but need not) be readable by anyone. This file is
809never used automatically and is not necessary; it is only provided for
810the convenience of the user.
811.It Pa $HOME/.ssh/config
812This is the per-user configuration file. The format of this file is
813described above. This file is used by the
814.Nm
815client. This file does not usually contain any sensitive information,
816but the recommended permissions are read/write for the user, and not
817accessible by others.
818.It Pa $HOME/.ssh/authorized_keys
819Lists the RSA keys that can be used for logging in as this user. The
820format of this file is described in the
821.Xr sshd 8
822manual page. In the simplest form the format is the same as the .pub
823identity files (that is, each line contains the number of bits in
824modulus, public exponent, modulus, and comment fields, separated by
825spaces). This file is not highly sensitive, but the recommended
826permissions are read/write for the user, and not accessible by others.
827.It Pa /etc/ssh_known_hosts
828Systemwide list of known host keys. This file should be prepared by the
829system administrator to contain the public host keys of all machines in the
830organization. This file should be world-readable. This file contains
831public keys, one per line, in the following format (fields separated
832by spaces): system name, number of bits in modulus, public exponent,
833modulus, and optional comment field. When different names are used
834for the same machine, all such names should be listed, separated by
835commas. The format is described on the
836.Xr sshd 8
837manual page.
838.Pp
839The canonical system name (as returned by name servers) is used by
840.Xr sshd 8
841to verify the client host when logging in; other names are needed because
842.Nm
843does not convert the user-supplied name to a canonical name before
844checking the key, because someone with access to the name servers
845would then be able to fool host authentication.
846.It Pa /etc/ssh_config
847Systemwide configuration file. This file provides defaults for those
848values that are not specified in the user's configuration file, and
849for those users who do not have a configuration file. This file must
850be world-readable.
851.It Pa $HOME/.rhosts
852This file is used in
853.Pa \&.rhosts
854authentication to list the
855host/user pairs that are permitted to log in. (Note that this file is
856also used by rlogin and rsh, which makes using this file insecure.)
857Each line of the file contains a host name (in the canonical form
858returned by name servers), and then a user name on that host,
859separated by a space. One some machines this file may need to be
860world-readable if the user's home directory is on a NFS partition,
861because
862.Xr sshd 8
863reads it as root. Additionally, this file must be owned by the user,
864and must not have write permissions for anyone else. The recommended
865permission for most machines is read/write for the user, and not
866accessible by others.
867.Pp
868Note that by default
869.Xr sshd 8
870will be installed so that it requires successful RSA host
871authentication before permitting \s+2.\s0rhosts authentication. If your
872server machine does not have the client's host key in
873.Pa /etc/ssh_known_hosts ,
874you can store it in
875.Pa $HOME/.ssh/known_hosts .
876The easiest way to do this is to
877connect back to the client from the server machine using ssh; this
878will automatically add the host key inxi
879.Pa $HOME/.ssh/known_hosts .
880.It Pa $HOME/.shosts
881This file is used exactly the same way as
882.Pa \&.rhosts .
883The purpose for
884having this file is to be able to use rhosts authentication with
885.Nm
886without permitting login with
887.Xr rlogin 1
888or
889.Xr rsh 1 .
890.It Pa /etc/hosts.equiv
891This file is used during
892.Pa \&.rhosts authentication. It contains
893canonical hosts names, one per line (the full format is described on
894the
895.Xr sshd 8
896manual page). If the client host is found in this file, login is
897automatically permitted provided client and server user names are the
898same. Additionally, successful RSA host authentication is normally
899required. This file should only be writable by root.
900.It Pa /etc/shosts.equiv
901This file is processed exactly as
902.Pa /etc/hosts.equiv .
903This file may be useful to permit logins using
904.Nm
905but not using rsh/rlogin.
906.It Pa /etc/sshrc
907Commands in this file are executed by
908.Nm
909when the user logs in just before the user's shell (or command) is started.
910See the
911.Xr sshd 8
912manual page for more information.
913.It Pa $HOME/.ssh/rc
914Commands in this file are executed by
915.Nm
916when the user logs in just before the user's shell (or command) is
917started.
918See the
919.Xr sshd 8
920manual page for more information.
921.It Pa libcrypto.so.X.1
922A version of this library which includes support for the RSA algorithm
923is required for proper operation.
924.Sh AUTHOR
925Tatu Ylonen <ylo@cs.hut.fi>
926.Pp
927Issues can be found from the SSH WWW home page:
928.Pp
929.Dl http://www.cs.hut.fi/ssh
930.Pp
931OpenSSH
932is a derivative of the original (free) ssh 1.2.12 release, but with bugs
933removed and newer features re-added. Rapidly after the 1.2.12 release,
934newer versions bore successively more restrictive licenses. This version
935of OpenSSH
936.Bl -bullet
937.It
938has all components of a restrictive nature (ie. patents, see
939.Xr ssl 8 )
940directly removed from the source code; any licensed or patented components
941are chosen from
942external libraries.
943.It
944has been updated to support ssh protocol 1.5.
945.It
946contains added support for
947.Xr kerberos 8
948authentication and ticket passing.
949.It
950supports one-time password authentication with
951.Xr skey 1 .
952.El
953.Pp
954The libraries described in
955.Xr ssl 8
956are required for proper operation.
957.Sh SEE ALSO
958.Xr rlogin 1 ,
959.Xr rsh 1 ,
960.Xr scp 1 ,
961.Xr ssh-add 1 ,
962.Xr ssh-agent 1 ,
963.Xr ssh-keygen 1 ,
964.Xr telnet 1 ,
965.Xr sshd 8 ,
966.Xr ssl 8
diff --git a/ssh.c b/ssh.c
new file mode 100644
index 000000000..c5a92b5c6
--- /dev/null
+++ b/ssh.c
@@ -0,0 +1,809 @@
1/*
2
3ssh.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Sat Mar 18 16:36:11 1995 ylo
11
12Ssh client program. This program can be used to log into a remote machine.
13The software supports strong authentication, encryption, and forwarding
14of X11, TCP/IP, and authentication connections.
15
16Modified to work with SSL by Niels Provos <provos@citi.umich.edu> in Canada.
17
18*/
19
20#include "includes.h"
21RCSID("$Id: ssh.c,v 1.1 1999/10/27 03:42:45 damien Exp $");
22
23#include "xmalloc.h"
24#include "ssh.h"
25#include "packet.h"
26#include "buffer.h"
27#include "authfd.h"
28#include "readconf.h"
29#include "uidswap.h"
30
31/* Flag indicating whether debug mode is on. This can be set on the
32 command line. */
33int debug_flag = 0;
34
35/* Flag indicating whether quiet mode is on. */
36int quiet_flag = 0;
37
38/* Flag indicating whether to allocate a pseudo tty. This can be set on the
39 command line, and is automatically set if no command is given on the command
40 line. */
41int tty_flag = 0;
42
43/* Flag indicating that nothing should be read from stdin. This can be set
44 on the command line. */
45int stdin_null_flag = 0;
46
47/* Flag indicating that ssh should fork after authentication. This is useful
48 so that the pasphrase can be entered manually, and then ssh goes to the
49 background. */
50int fork_after_authentication_flag = 0;
51
52/* General data structure for command line options and options configurable
53 in configuration files. See readconf.h. */
54Options options;
55
56/* Name of the host we are connecting to. This is the name given on the
57 command line, or the HostName specified for the user-supplied name
58 in a configuration file. */
59char *host;
60
61/* socket address the host resolves to */
62struct sockaddr_in hostaddr;
63
64/* Flag to indicate that we have received a window change signal which has
65 not yet been processed. This will cause a message indicating the new
66 window size to be sent to the server a little later. This is volatile
67 because this is updated in a signal handler. */
68volatile int received_window_change_signal = 0;
69
70/* Value of argv[0] (set in the main program). */
71char *av0;
72
73/* Flag indicating whether we have a valid host private key loaded. */
74int host_private_key_loaded = 0;
75
76/* Host private key. */
77RSA *host_private_key = NULL;
78
79/* Original real UID. */
80uid_t original_real_uid;
81
82/* Prints a help message to the user. This function never returns. */
83
84void
85usage()
86{
87 fprintf(stderr, "Usage: %s [options] host [command]\n", av0);
88 fprintf(stderr, "Options:\n");
89 fprintf(stderr, " -l user Log in using this user name.\n");
90 fprintf(stderr, " -n Redirect input from /dev/null.\n");
91 fprintf(stderr, " -a Disable authentication agent forwarding.\n");
92#ifdef AFS
93 fprintf(stderr, " -k Disable Kerberos ticket and AFS token forwarding.\n");
94#endif /* AFS */
95 fprintf(stderr, " -x Disable X11 connection forwarding.\n");
96 fprintf(stderr, " -i file Identity for RSA authentication (default: ~/.ssh/identity).\n");
97 fprintf(stderr, " -t Tty; allocate a tty even if command is given.\n");
98 fprintf(stderr, " -v Verbose; display verbose debugging messages.\n");
99 fprintf(stderr, " -V Display version number only.\n");
100 fprintf(stderr, " -P Don't allocate a privileged port.\n");
101 fprintf(stderr, " -q Quiet; don't display any warning messages.\n");
102 fprintf(stderr, " -f Fork into background after authentication.\n");
103 fprintf(stderr, " -e char Set escape character; ``none'' = disable (default: ~).\n");
104
105 fprintf(stderr, " -c cipher Select encryption algorithm: "
106 "``3des'', "
107 "``blowfish''\n");
108 fprintf(stderr, " -p port Connect to this port. Server must be on the same port.\n");
109 fprintf(stderr, " -L listen-port:host:port Forward local port to remote address\n");
110 fprintf(stderr, " -R listen-port:host:port Forward remote port to local address\n");
111 fprintf(stderr, " These cause %s to listen for connections on a port, and\n", av0);
112 fprintf(stderr, " forward them to the other side by connecting to host:port.\n");
113 fprintf(stderr, " -C Enable compression.\n");
114 fprintf(stderr, " -g Allow remote hosts to connect to forwarded ports.\n");
115 fprintf(stderr, " -o 'option' Process the option as if it was read from a configuration file.\n");
116 exit(1);
117}
118
119/* Connects to the given host using rsh (or prints an error message and exits
120 if rsh is not available). This function never returns. */
121
122void
123rsh_connect(char *host, char *user, Buffer *command)
124{
125 char *args[10];
126 int i;
127
128 log("Using rsh. WARNING: Connection will not be encrypted.");
129 /* Build argument list for rsh. */
130 i = 0;
131 args[i++] = _PATH_RSH;
132 args[i++] = host; /* may have to come after user on some systems */
133 if (user)
134 {
135 args[i++] = "-l";
136 args[i++] = user;
137 }
138 if (buffer_len(command) > 0)
139 {
140 buffer_append(command, "\0", 1);
141 args[i++] = buffer_ptr(command);
142 }
143 args[i++] = NULL;
144 if (debug_flag)
145 {
146 for (i = 0; args[i]; i++)
147 {
148 if (i != 0)
149 fprintf(stderr, " ");
150 fprintf(stderr, "%s", args[i]);
151 }
152 fprintf(stderr, "\n");
153 }
154 execv(_PATH_RSH, args);
155 perror(_PATH_RSH);
156 exit(1);
157}
158
159/* Main program for the ssh client. */
160
161uid_t original_real_uid;
162
163int
164main(int ac, char **av)
165{
166 int i, opt, optind, type, exit_status, ok, fwd_port, fwd_host_port, authfd;
167 char *optarg, *cp, buf[256];
168 Buffer command;
169 struct winsize ws;
170 struct stat st;
171 struct passwd *pw, pwcopy;
172 int interactive = 0, dummy;
173 uid_t original_effective_uid;
174 int plen;
175
176 /* Save the original real uid. It will be needed later (uid-swapping may
177 clobber the real uid). */
178 original_real_uid = getuid();
179 original_effective_uid = geteuid();
180
181 /* If we are installed setuid root be careful to not drop core. */
182 if (original_real_uid != original_effective_uid)
183 {
184 struct rlimit rlim;
185 rlim.rlim_cur = rlim.rlim_max = 0;
186 if (setrlimit(RLIMIT_CORE, &rlim) < 0)
187 fatal("setrlimit failed: %.100s", strerror(errno));
188 }
189
190 /* Use uid-swapping to give up root privileges for the duration of option
191 processing. We will re-instantiate the rights when we are ready to
192 create the privileged port, and will permanently drop them when the
193 port has been created (actually, when the connection has been made, as
194 we may need to create the port several times). */
195 temporarily_use_uid(original_real_uid);
196
197 /* Set our umask to something reasonable, as some files are created with
198 the default umask. This will make them world-readable but writable
199 only by the owner, which is ok for all files for which we don't set
200 the modes explicitly. */
201 umask(022);
202
203 /* Save our own name. */
204 av0 = av[0];
205
206 /* Initialize option structure to indicate that no values have been set. */
207 initialize_options(&options);
208
209 /* Parse command-line arguments. */
210 host = NULL;
211
212 /* If program name is not one of the standard names, use it as host name. */
213 if (strchr(av0, '/'))
214 cp = strrchr(av0, '/') + 1;
215 else
216 cp = av0;
217 if (strcmp(cp, "rsh") != 0 && strcmp(cp, "ssh") != 0 &&
218 strcmp(cp, "rlogin") != 0 && strcmp(cp, "slogin") != 0)
219 host = cp;
220
221 for (optind = 1; optind < ac; optind++)
222 {
223 if (av[optind][0] != '-')
224 {
225 if (host)
226 break;
227 if ((cp = strchr(av[optind], '@'))) {
228 options.user = av[optind];
229 *cp = '\0';
230 host = ++cp;
231 }
232 else
233 host = av[optind];
234 continue;
235 }
236 opt = av[optind][1];
237 if (!opt)
238 usage();
239 if (strchr("eilcpLRo", opt)) /* options with arguments */
240 {
241 optarg = av[optind] + 2;
242 if (strcmp(optarg, "") == 0)
243 {
244 if (optind >= ac - 1)
245 usage();
246 optarg = av[++optind];
247 }
248 }
249 else
250 {
251 if (av[optind][2])
252 usage();
253 optarg = NULL;
254 }
255 switch (opt)
256 {
257 case 'n':
258 stdin_null_flag = 1;
259 break;
260
261 case 'f':
262 fork_after_authentication_flag = 1;
263 stdin_null_flag = 1;
264 break;
265
266 case 'x':
267 options.forward_x11 = 0;
268 break;
269
270 case 'X':
271 options.forward_x11 = 1;
272 break;
273
274 case 'g':
275 options.gateway_ports = 1;
276 break;
277
278 case 'P':
279 options.use_privileged_port = 0;
280 break;
281
282 case 'a':
283 options.forward_agent = 0;
284 break;
285#ifdef AFS
286 case 'k':
287 options.kerberos_tgt_passing = 0;
288 options.afs_token_passing = 0;
289 break;
290#endif
291 case 'i':
292 if (stat(optarg, &st) < 0)
293 {
294 fprintf(stderr, "Warning: Identity file %s does not exist.\n",
295 optarg);
296 break;
297 }
298 if (options.num_identity_files >= SSH_MAX_IDENTITY_FILES)
299 fatal("Too many identity files specified (max %d)",
300 SSH_MAX_IDENTITY_FILES);
301 options.identity_files[options.num_identity_files++] =
302 xstrdup(optarg);
303 break;
304
305 case 't':
306 tty_flag = 1;
307 break;
308
309 case 'v':
310 case 'V':
311 debug_flag = 1;
312 fprintf(stderr, "SSH Version %s, protocol version %d.%d.\n",
313 SSH_VERSION, PROTOCOL_MAJOR, PROTOCOL_MINOR);
314 fprintf(stderr, "Compiled with SSL.\n");
315 if (opt == 'V')
316 exit(0);
317 break;
318
319 case 'q':
320 quiet_flag = 1;
321 break;
322
323 case 'e':
324 if (optarg[0] == '^' && optarg[2] == 0 &&
325 (unsigned char)optarg[1] >= 64 && (unsigned char)optarg[1] < 128)
326 options.escape_char = (unsigned char)optarg[1] & 31;
327 else
328 if (strlen(optarg) == 1)
329 options.escape_char = (unsigned char)optarg[0];
330 else
331 if (strcmp(optarg, "none") == 0)
332 options.escape_char = -2;
333 else
334 {
335 fprintf(stderr, "Bad escape character '%s'.\n", optarg);
336 exit(1);
337 }
338 break;
339
340 case 'c':
341 options.cipher = cipher_number(optarg);
342 if (options.cipher == -1)
343 {
344 fprintf(stderr, "Unknown cipher type '%s'\n", optarg);
345 exit(1);
346 }
347 break;
348
349 case 'p':
350 options.port = atoi(optarg);
351 if (options.port < 1 || options.port > 65535)
352 {
353 fprintf(stderr, "Bad port %s.\n", optarg);
354 exit(1);
355 }
356 break;
357
358 case 'l':
359 options.user = optarg;
360 break;
361
362 case 'R':
363 if (sscanf(optarg, "%d:%255[^:]:%d", &fwd_port, buf,
364 &fwd_host_port) != 3)
365 {
366 fprintf(stderr, "Bad forwarding specification '%s'.\n", optarg);
367 usage();
368 /*NOTREACHED*/
369 }
370 add_remote_forward(&options, fwd_port, buf, fwd_host_port);
371 break;
372
373 case 'L':
374 if (sscanf(optarg, "%d:%255[^:]:%d", &fwd_port, buf,
375 &fwd_host_port) != 3)
376 {
377 fprintf(stderr, "Bad forwarding specification '%s'.\n", optarg);
378 usage();
379 /*NOTREACHED*/
380 }
381 add_local_forward(&options, fwd_port, buf, fwd_host_port);
382 break;
383
384 case 'C':
385 options.compression = 1;
386 break;
387
388 case 'o':
389 dummy = 1;
390 process_config_line(&options, host ? host : "", optarg,
391 "command-line", 0, &dummy);
392 break;
393
394 default:
395 usage();
396 }
397 }
398
399 /* Check that we got a host name. */
400 if (!host)
401 usage();
402
403 /* check if RSA support exists */
404 if (rsa_alive() == 0) {
405 extern char *__progname;
406
407 fprintf(stderr,
408 "%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
409 __progname);
410 exit(1);
411 }
412
413 /* Initialize the command to execute on remote host. */
414 buffer_init(&command);
415
416 /* Save the command to execute on the remote host in a buffer. There is
417 no limit on the length of the command, except by the maximum packet
418 size. Also sets the tty flag if there is no command. */
419 if (optind == ac)
420 {
421 /* No command specified - execute shell on a tty. */
422 tty_flag = 1;
423 }
424 else
425 {
426 /* A command has been specified. Store it into the buffer. */
427 for (i = optind; i < ac; i++)
428 {
429 if (i > optind)
430 buffer_append(&command, " ", 1);
431 buffer_append(&command, av[i], strlen(av[i]));
432 }
433 }
434
435 /* Cannot fork to background if no command. */
436 if (fork_after_authentication_flag && buffer_len(&command) == 0)
437 fatal("Cannot fork into background without a command to execute.");
438
439 /* Allocate a tty by default if no command specified. */
440 if (buffer_len(&command) == 0)
441 tty_flag = 1;
442
443 /* Do not allocate a tty if stdin is not a tty. */
444 if (!isatty(fileno(stdin)))
445 {
446 if (tty_flag)
447 fprintf(stderr, "Pseudo-terminal will not be allocated because stdin is not a terminal.\n");
448 tty_flag = 0;
449 }
450
451 /* Get user data. */
452 pw = getpwuid(original_real_uid);
453 if (!pw)
454 {
455 fprintf(stderr, "You don't exist, go away!\n");
456 exit(1);
457 }
458
459 /* Take a copy of the returned structure. */
460 memset(&pwcopy, 0, sizeof(pwcopy));
461 pwcopy.pw_name = xstrdup(pw->pw_name);
462 pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
463 pwcopy.pw_uid = pw->pw_uid;
464 pwcopy.pw_gid = pw->pw_gid;
465 pwcopy.pw_dir = xstrdup(pw->pw_dir);
466 pwcopy.pw_shell = xstrdup(pw->pw_shell);
467 pw = &pwcopy;
468
469 /* Initialize "log" output. Since we are the client all output actually
470 goes to the terminal. */
471 log_init(av[0], 1, debug_flag, quiet_flag, SYSLOG_FACILITY_USER);
472
473 /* Read per-user configuration file. */
474 snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_CONFFILE);
475 read_config_file(buf, host, &options);
476
477 /* Read systemwide configuration file. */
478 read_config_file(HOST_CONFIG_FILE, host, &options);
479
480 /* Fill configuration defaults. */
481 fill_default_options(&options);
482 if (options.user == NULL)
483 options.user = xstrdup(pw->pw_name);
484
485 if (options.hostname != NULL)
486 host = options.hostname;
487
488 /* Find canonic host name. */
489 if (strchr(host, '.') == 0)
490 {
491 struct hostent *hp = gethostbyname(host);
492 if (hp != 0)
493 {
494 if (strchr(hp->h_name, '.') != 0)
495 host = xstrdup(hp->h_name);
496 else if (hp->h_aliases != 0
497 && hp->h_aliases[0] != 0
498 && strchr(hp->h_aliases[0], '.') != 0)
499 host = xstrdup(hp->h_aliases[0]);
500 }
501 }
502
503 /* Disable rhosts authentication if not running as root. */
504 if (original_effective_uid != 0)
505 {
506 options.rhosts_authentication = 0;
507 options.rhosts_rsa_authentication = 0;
508 }
509
510 /* If using rsh has been selected, exec it now (without trying anything
511 else). Note that we must release privileges first. */
512 if (options.use_rsh)
513 {
514 /* Restore our superuser privileges. This must be done before
515 permanently setting the uid. */
516 restore_uid();
517
518 /* Switch to the original uid permanently. */
519 permanently_set_uid(original_real_uid);
520
521 /* Execute rsh. */
522 rsh_connect(host, options.user, &command);
523 fatal("rsh_connect returned");
524 }
525
526 /* Restore our superuser privileges. */
527 restore_uid();
528
529 /* Open a connection to the remote host. This needs root privileges if
530 rhosts_{rsa_}authentication is true. */
531
532 if (!options.use_privileged_port)
533 {
534 options.rhosts_authentication = 0;
535 options.rhosts_rsa_authentication = 0;
536 }
537
538 ok = ssh_connect(host, &hostaddr, options.port, options.connection_attempts,
539 !options.rhosts_authentication &&
540 !options.rhosts_rsa_authentication,
541 original_real_uid, options.proxy_command);
542
543 /* If we successfully made the connection, load the host private key in
544 case we will need it later for combined rsa-rhosts authentication.
545 This must be done before releasing extra privileges, because the file
546 is only readable by root. */
547 if (ok)
548 {
549 host_private_key = RSA_new();
550 if (load_private_key(HOST_KEY_FILE, "", host_private_key, NULL))
551 host_private_key_loaded = 1;
552 }
553
554 /* Get rid of any extra privileges that we may have. We will no longer need
555 them. Also, extra privileges could make it very hard to read identity
556 files and other non-world-readable files from the user's home directory
557 if it happens to be on a NFS volume where root is mapped to nobody. */
558 permanently_set_uid(original_real_uid);
559
560 /* Now that we are back to our own permissions, create ~/.ssh directory
561 if it doesn\'t already exist. */
562 snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_DIR);
563 if (stat(buf, &st) < 0)
564 if (mkdir(buf, 0755) < 0)
565 error("Could not create directory '%.200s'.", buf);
566
567 /* Check if the connection failed, and try "rsh" if appropriate. */
568 if (!ok)
569 {
570 if (options.port != 0)
571 log("Secure connection to %.100s on port %d refused%.100s.",
572 host, options.port,
573 options.fallback_to_rsh ? "; reverting to insecure method" : "");
574 else
575 log("Secure connection to %.100s refused%.100s.", host,
576 options.fallback_to_rsh ? "; reverting to insecure method" : "");
577
578 if (options.fallback_to_rsh)
579 {
580 rsh_connect(host, options.user, &command);
581 fatal("rsh_connect returned");
582 }
583 exit(1);
584 }
585
586 /* Expand ~ in options.identity_files. */
587 for (i = 0; i < options.num_identity_files; i++)
588 options.identity_files[i] =
589 tilde_expand_filename(options.identity_files[i], original_real_uid);
590
591 /* Expand ~ in known host file names. */
592 options.system_hostfile = tilde_expand_filename(options.system_hostfile,
593 original_real_uid);
594 options.user_hostfile = tilde_expand_filename(options.user_hostfile,
595 original_real_uid);
596
597 /* Log into the remote system. This never returns if the login fails. */
598 ssh_login(host_private_key_loaded, host_private_key,
599 host, &hostaddr, &options, original_real_uid);
600
601 /* We no longer need the host private key. Clear it now. */
602 if (host_private_key_loaded)
603 RSA_free(host_private_key); /* Destroys contents safely */
604
605 /* Close connection cleanly after attack. */
606 cipher_attack_detected = packet_disconnect;
607
608 /* If requested, fork and let ssh continue in the background. */
609 if (fork_after_authentication_flag)
610 {
611 int ret = fork();
612 if (ret == -1)
613 fatal("fork failed: %.100s", strerror(errno));
614 if (ret != 0)
615 exit(0);
616 setsid();
617 }
618
619 /* Enable compression if requested. */
620 if (options.compression)
621 {
622 debug("Requesting compression at level %d.", options.compression_level);
623
624 if (options.compression_level < 1 || options.compression_level > 9)
625 fatal("Compression level must be from 1 (fast) to 9 (slow, best).");
626
627 /* Send the request. */
628 packet_start(SSH_CMSG_REQUEST_COMPRESSION);
629 packet_put_int(options.compression_level);
630 packet_send();
631 packet_write_wait();
632 type = packet_read(&plen);
633 if (type == SSH_SMSG_SUCCESS)
634 packet_start_compression(options.compression_level);
635 else if (type == SSH_SMSG_FAILURE)
636 log("Warning: Remote host refused compression.");
637 else
638 packet_disconnect("Protocol error waiting for compression response.");
639 }
640
641 /* Allocate a pseudo tty if appropriate. */
642 if (tty_flag)
643 {
644 debug("Requesting pty.");
645
646 /* Start the packet. */
647 packet_start(SSH_CMSG_REQUEST_PTY);
648
649 /* Store TERM in the packet. There is no limit on the length of the
650 string. */
651 cp = getenv("TERM");
652 if (!cp)
653 cp = "";
654 packet_put_string(cp, strlen(cp));
655
656 /* Store window size in the packet. */
657 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
658 memset(&ws, 0, sizeof(ws));
659 packet_put_int(ws.ws_row);
660 packet_put_int(ws.ws_col);
661 packet_put_int(ws.ws_xpixel);
662 packet_put_int(ws.ws_ypixel);
663
664 /* Store tty modes in the packet. */
665 tty_make_modes(fileno(stdin));
666
667 /* Send the packet, and wait for it to leave. */
668 packet_send();
669 packet_write_wait();
670
671 /* Read response from the server. */
672 type = packet_read(&plen);
673 if (type == SSH_SMSG_SUCCESS)
674 interactive = 1;
675 else if (type == SSH_SMSG_FAILURE)
676 log("Warning: Remote host failed or refused to allocate a pseudo tty.");
677 else
678 packet_disconnect("Protocol error waiting for pty request response.");
679 }
680
681 /* Request X11 forwarding if enabled and DISPLAY is set. */
682 if (options.forward_x11 && getenv("DISPLAY") != NULL)
683 {
684 char line[512], proto[512], data[512];
685 FILE *f;
686 int forwarded = 0, got_data = 0, i;
687
688#ifdef XAUTH_PATH
689 /* Try to get Xauthority information for the display. */
690 snprintf(line, sizeof line, "%.100s list %.200s 2>/dev/null",
691 XAUTH_PATH, getenv("DISPLAY"));
692 f = popen(line, "r");
693 if (f && fgets(line, sizeof(line), f) &&
694 sscanf(line, "%*s %s %s", proto, data) == 2)
695 got_data = 1;
696 if (f)
697 pclose(f);
698#endif /* XAUTH_PATH */
699 /* If we didn't get authentication data, just make up some data. The
700 forwarding code will check the validity of the response anyway, and
701 substitute this data. The X11 server, however, will ignore this
702 fake data and use whatever authentication mechanisms it was using
703 otherwise for the local connection. */
704 if (!got_data)
705 {
706 u_int32_t rand = 0;
707
708 strlcpy(proto, "MIT-MAGIC-COOKIE-1", sizeof proto);
709 for (i = 0; i < 16; i++) {
710 if (i % 4 == 0)
711 rand = arc4random();
712 snprintf(data + 2 * i, sizeof data - 2 * i, "%02x", rand & 0xff);
713 rand >>= 8;
714 }
715 }
716
717 /* Got local authentication reasonable information. Request forwarding
718 with authentication spoofing. */
719 debug("Requesting X11 forwarding with authentication spoofing.");
720 x11_request_forwarding_with_spoofing(proto, data);
721
722 /* Read response from the server. */
723 type = packet_read(&plen);
724 if (type == SSH_SMSG_SUCCESS)
725 {
726 forwarded = 1;
727 interactive = 1;
728 }
729 else if (type == SSH_SMSG_FAILURE)
730 log("Warning: Remote host denied X11 forwarding.");
731 else
732 packet_disconnect("Protocol error waiting for X11 forwarding");
733 }
734
735 /* Tell the packet module whether this is an interactive session. */
736 packet_set_interactive(interactive, options.keepalives);
737
738 /* Clear agent forwarding if we don\'t have an agent. */
739 authfd = ssh_get_authentication_socket();
740 if (authfd < 0)
741 options.forward_agent = 0;
742 else
743 ssh_close_authentication_socket(authfd);
744
745 /* Request authentication agent forwarding if appropriate. */
746 if (options.forward_agent)
747 {
748 debug("Requesting authentication agent forwarding.");
749 auth_request_forwarding();
750
751 /* Read response from the server. */
752 type = packet_read(&plen);
753 packet_integrity_check(plen, 0, type);
754 if (type != SSH_SMSG_SUCCESS)
755 log("Warning: Remote host denied authentication agent forwarding.");
756 }
757
758 /* Initiate local TCP/IP port forwardings. */
759 for (i = 0; i < options.num_local_forwards; i++)
760 {
761 debug("Connections to local port %d forwarded to remote address %.200s:%d",
762 options.local_forwards[i].port, options.local_forwards[i].host,
763 options.local_forwards[i].host_port);
764 channel_request_local_forwarding(options.local_forwards[i].port,
765 options.local_forwards[i].host,
766 options.local_forwards[i].host_port);
767 }
768
769 /* Initiate remote TCP/IP port forwardings. */
770 for (i = 0; i < options.num_remote_forwards; i++)
771 {
772 debug("Connections to remote port %d forwarded to local address %.200s:%d",
773 options.remote_forwards[i].port, options.remote_forwards[i].host,
774 options.remote_forwards[i].host_port);
775 channel_request_remote_forwarding(options.remote_forwards[i].port,
776 options.remote_forwards[i].host,
777 options.remote_forwards[i].host_port);
778 }
779
780 /* If a command was specified on the command line, execute the command now.
781 Otherwise request the server to start a shell. */
782 if (buffer_len(&command) > 0)
783 {
784 int len = buffer_len(&command);
785 if (len > 900)
786 len = 900;
787 debug("Sending command: %.*s", len, buffer_ptr(&command));
788 packet_start(SSH_CMSG_EXEC_CMD);
789 packet_put_string(buffer_ptr(&command), buffer_len(&command));
790 packet_send();
791 packet_write_wait();
792 }
793 else
794 {
795 debug("Requesting shell.");
796 packet_start(SSH_CMSG_EXEC_SHELL);
797 packet_send();
798 packet_write_wait();
799 }
800
801 /* Enter the interactive session. */
802 exit_status = client_loop(tty_flag, tty_flag ? options.escape_char : -1);
803
804 /* Close the connection to the remote host. */
805 packet_close();
806
807 /* Exit with the status returned by the program on the remote side. */
808 exit(exit_status);
809}
diff --git a/ssh.h b/ssh.h
new file mode 100644
index 000000000..a4bf136e4
--- /dev/null
+++ b/ssh.h
@@ -0,0 +1,589 @@
1/*
2
3ssh.h
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Fri Mar 17 17:09:37 1995 ylo
11
12Generic header file for ssh.
13
14*/
15
16/* RCSID("$Id: ssh.h,v 1.1 1999/10/27 03:42:45 damien Exp $"); */
17
18#ifndef SSH_H
19#define SSH_H
20
21#include "rsa.h"
22#include "cipher.h"
23
24/* The default cipher used if IDEA is not supported by the remote host.
25 It is recommended that this be one of the mandatory ciphers (DES, 3DES),
26 though that is not required. */
27#define SSH_FALLBACK_CIPHER SSH_CIPHER_3DES
28
29/* Cipher used for encrypting authentication files. */
30#define SSH_AUTHFILE_CIPHER SSH_CIPHER_3DES
31
32/* Default port number. */
33#define SSH_DEFAULT_PORT 22
34
35/* Maximum number of TCP/IP ports forwarded per direction. */
36#define SSH_MAX_FORWARDS_PER_DIRECTION 100
37
38/* Maximum number of RSA authentication identity files that can be specified
39 in configuration files or on the command line. */
40#define SSH_MAX_IDENTITY_FILES 100
41
42/* Major protocol version. Different version indicates major incompatiblity
43 that prevents communication. */
44#define PROTOCOL_MAJOR 1
45
46/* Minor protocol version. Different version indicates minor incompatibility
47 that does not prevent interoperation. */
48#define PROTOCOL_MINOR 5
49
50/* Name for the service. The port named by this service overrides the default
51 port if present. */
52#define SSH_SERVICE_NAME "ssh"
53
54#ifndef ETCDIR
55#define ETCDIR "/etc"
56#endif /* ETCDIR */
57
58#define PIDDIR "/var/run"
59
60/* System-wide file containing host keys of known hosts. This file should be
61 world-readable. */
62#define SSH_SYSTEM_HOSTFILE ETCDIR "/ssh_known_hosts"
63
64/* HOST_KEY_FILE /etc/ssh_host_key,
65 SERVER_CONFIG_FILE /etc/sshd_config,
66and HOST_CONFIG_FILE /etc/ssh_config
67are all defined in Makefile.in. Of these, ssh_host_key should be readable
68only by root, whereas ssh_config should be world-readable. */
69
70#define HOST_KEY_FILE ETCDIR "/ssh_host_key"
71#define SERVER_CONFIG_FILE ETCDIR "/sshd_config"
72#define HOST_CONFIG_FILE ETCDIR "/ssh_config"
73
74#define SSH_PROGRAM "/usr/bin/ssh"
75
76/* The process id of the daemon listening for connections is saved
77 here to make it easier to kill the correct daemon when necessary. */
78#define SSH_DAEMON_PID_FILE PIDDIR "/sshd.pid"
79
80/* The directory in user\'s home directory in which the files reside.
81 The directory should be world-readable (though not all files are). */
82#define SSH_USER_DIR ".ssh"
83
84/* Per-user file containing host keys of known hosts. This file need
85 not be readable by anyone except the user him/herself, though this does
86 not contain anything particularly secret. */
87#define SSH_USER_HOSTFILE "~/.ssh/known_hosts"
88
89/* Name of the default file containing client-side authentication key.
90 This file should only be readable by the user him/herself. */
91#define SSH_CLIENT_IDENTITY ".ssh/identity"
92
93/* Configuration file in user\'s home directory. This file need not be
94 readable by anyone but the user him/herself, but does not contain
95 anything particularly secret. If the user\'s home directory resides
96 on an NFS volume where root is mapped to nobody, this may need to be
97 world-readable. */
98#define SSH_USER_CONFFILE ".ssh/config"
99
100/* File containing a list of those rsa keys that permit logging in as
101 this user. This file need not be
102 readable by anyone but the user him/herself, but does not contain
103 anything particularly secret. If the user\'s home directory resides
104 on an NFS volume where root is mapped to nobody, this may need to be
105 world-readable. (This file is read by the daemon which is running as
106 root.) */
107#define SSH_USER_PERMITTED_KEYS ".ssh/authorized_keys"
108
109/* Per-user and system-wide ssh "rc" files. These files are executed with
110 /bin/sh before starting the shell or command if they exist. They
111 will be passed "proto cookie" as arguments if X11 forwarding with
112 spoofing is in use. xauth will be run if neither of these exists. */
113#define SSH_USER_RC ".ssh/rc"
114#define SSH_SYSTEM_RC ETCDIR "/sshrc"
115
116/* Ssh-only version of /etc/hosts.equiv. */
117#define SSH_HOSTS_EQUIV ETCDIR "/shosts.equiv"
118
119/* Additionally, the daemon may use ~/.rhosts and /etc/hosts.equiv if
120 rhosts authentication is enabled. */
121
122/* Name of the environment variable containing the pathname of the
123 authentication socket. */
124#define SSH_AUTHSOCKET_ENV_NAME "SSH_AUTH_SOCK"
125
126/* Force host key length and server key length to differ by at least this
127 many bits. This is to make double encryption with rsaref work. */
128#define SSH_KEY_BITS_RESERVED 128
129
130/* Length of the session key in bytes. (Specified as 256 bits in the
131 protocol.) */
132#define SSH_SESSION_KEY_LENGTH 32
133
134/* Name of Kerberos service for SSH to use. */
135#define KRB4_SERVICE_NAME "rcmd"
136
137/* Authentication methods. New types can be added, but old types should not
138 be removed for compatibility. The maximum allowed value is 31. */
139#define SSH_AUTH_RHOSTS 1
140#define SSH_AUTH_RSA 2
141#define SSH_AUTH_PASSWORD 3
142#define SSH_AUTH_RHOSTS_RSA 4
143 /* 5 is TIS */
144#define SSH_AUTH_KERBEROS 6
145#define SSH_PASS_KERBEROS_TGT 7
146 /* 8 to 15 are reserved */
147#define SSH_PASS_AFS_TOKEN 21
148
149/* Protocol flags. These are bit masks. */
150#define SSH_PROTOFLAG_SCREEN_NUMBER 1 /* X11 forwarding includes screen */
151#define SSH_PROTOFLAG_HOST_IN_FWD_OPEN 2 /* forwarding opens contain host */
152
153/* Definition of message types. New values can be added, but old values
154 should not be removed or without careful consideration of the consequences
155 for compatibility. The maximum value is 254; value 255 is reserved
156 for future extension. */
157/* Message name */ /* msg code */ /* arguments */
158#define SSH_MSG_NONE 0 /* no message */
159#define SSH_MSG_DISCONNECT 1 /* cause (string) */
160#define SSH_SMSG_PUBLIC_KEY 2 /* ck,msk,srvk,hostk */
161#define SSH_CMSG_SESSION_KEY 3 /* key (BIGNUM) */
162#define SSH_CMSG_USER 4 /* user (string) */
163#define SSH_CMSG_AUTH_RHOSTS 5 /* user (string) */
164#define SSH_CMSG_AUTH_RSA 6 /* modulus (BIGNUM) */
165#define SSH_SMSG_AUTH_RSA_CHALLENGE 7 /* int (BIGNUM) */
166#define SSH_CMSG_AUTH_RSA_RESPONSE 8 /* int (BIGNUM) */
167#define SSH_CMSG_AUTH_PASSWORD 9 /* pass (string) */
168#define SSH_CMSG_REQUEST_PTY 10 /* TERM, tty modes */
169#define SSH_CMSG_WINDOW_SIZE 11 /* row,col,xpix,ypix */
170#define SSH_CMSG_EXEC_SHELL 12 /* */
171#define SSH_CMSG_EXEC_CMD 13 /* cmd (string) */
172#define SSH_SMSG_SUCCESS 14 /* */
173#define SSH_SMSG_FAILURE 15 /* */
174#define SSH_CMSG_STDIN_DATA 16 /* data (string) */
175#define SSH_SMSG_STDOUT_DATA 17 /* data (string) */
176#define SSH_SMSG_STDERR_DATA 18 /* data (string) */
177#define SSH_CMSG_EOF 19 /* */
178#define SSH_SMSG_EXITSTATUS 20 /* status (int) */
179#define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 21 /* channel (int) */
180#define SSH_MSG_CHANNEL_OPEN_FAILURE 22 /* channel (int) */
181#define SSH_MSG_CHANNEL_DATA 23 /* ch,data (int,str) */
182#define SSH_MSG_CHANNEL_CLOSE 24 /* channel (int) */
183#define SSH_MSG_CHANNEL_CLOSE_CONFIRMATION 25 /* channel (int) */
184/* SSH_CMSG_X11_REQUEST_FORWARDING 26 OBSOLETE */
185#define SSH_SMSG_X11_OPEN 27 /* channel (int) */
186#define SSH_CMSG_PORT_FORWARD_REQUEST 28 /* p,host,hp (i,s,i) */
187#define SSH_MSG_PORT_OPEN 29 /* ch,h,p (i,s,i) */
188#define SSH_CMSG_AGENT_REQUEST_FORWARDING 30 /* */
189#define SSH_SMSG_AGENT_OPEN 31 /* port (int) */
190#define SSH_MSG_IGNORE 32 /* string */
191#define SSH_CMSG_EXIT_CONFIRMATION 33 /* */
192#define SSH_CMSG_X11_REQUEST_FORWARDING 34 /* proto,data (s,s) */
193#define SSH_CMSG_AUTH_RHOSTS_RSA 35 /* user,mod (s,mpi) */
194#define SSH_MSG_DEBUG 36 /* string */
195#define SSH_CMSG_REQUEST_COMPRESSION 37 /* level 1-9 (int) */
196#define SSH_CMSG_MAX_PACKET_SIZE 38 /* size 4k-1024k (int) */
197#define SSH_CMSG_AUTH_TIS 39 /* this is proto-1.5, but we ignore TIS */
198#define SSH_SMSG_AUTH_TIS_CHALLENGE 40
199#define SSH_CMSG_AUTH_TIS_RESPONSE 41
200
201#define SSH_CMSG_AUTH_KERBEROS 42 /* (KTEXT) */
202#define SSH_SMSG_AUTH_KERBEROS_RESPONSE 43 /* (KTEXT) */
203#define SSH_CMSG_HAVE_KERBEROS_TGT 44 /* credentials (s) */
204#define SSH_CMSG_HAVE_AFS_TOKEN 65 /* token (s) */
205
206
207/* Includes that need definitions above. */
208
209#include "readconf.h"
210
211/*------------ definitions for login.c -------------*/
212
213/* Returns the time when the user last logged in. Returns 0 if the
214 information is not available. This must be called before record_login.
215 The host from which the user logged in is stored in buf. */
216unsigned long get_last_login_time(uid_t uid, const char *logname,
217 char *buf, unsigned int bufsize);
218
219/* Records that the user has logged in. This does many things normally
220 done by login(1). */
221void record_login(int pid, const char *ttyname, const char *user, uid_t uid,
222 const char *host, struct sockaddr_in *addr);
223
224/* Records that the user has logged out. This does many thigs normally
225 done by login(1) or init. */
226void record_logout(int pid, const char *ttyname);
227
228/*------------ definitions for sshconnect.c ----------*/
229
230/* Opens a TCP/IP connection to the remote server on the given host. If
231 port is 0, the default port will be used. If anonymous is zero,
232 a privileged port will be allocated to make the connection.
233 This requires super-user privileges if anonymous is false.
234 Connection_attempts specifies the maximum number of tries, one per
235 second. This returns true on success, and zero on failure. If the
236 connection is successful, this calls packet_set_connection for the
237 connection. */
238int ssh_connect(const char *host, struct sockaddr_in *hostaddr,
239 int port, int connection_attempts,
240 int anonymous, uid_t original_real_uid,
241 const char *proxy_command);
242
243/* Starts a dialog with the server, and authenticates the current user on the
244 server. This does not need any extra privileges. The basic connection
245 to the server must already have been established before this is called.
246 If login fails, this function prints an error and never returns.
247 This initializes the random state, and leaves it initialized (it will also
248 have references from the packet module). */
249void ssh_login(int host_key_valid, RSA *host_key, const char *host,
250 struct sockaddr_in *hostaddr, Options *options,
251 uid_t original_real_uid);
252
253/*------------ Definitions for various authentication methods. -------*/
254
255/* Tries to authenticate the user using the .rhosts file. Returns true if
256 authentication succeeds. If ignore_rhosts is non-zero, this will not
257 consider .rhosts and .shosts (/etc/hosts.equiv will still be used).
258 If strict_modes is true, checks ownership and modes of .rhosts/.shosts. */
259int auth_rhosts(struct passwd *pw, const char *client_user,
260 int ignore_rhosts, int strict_modes);
261
262/* Tries to authenticate the user using the .rhosts file and the host using
263 its host key. Returns true if authentication succeeds. */
264int auth_rhosts_rsa(struct passwd *pw, const char *client_user,
265 unsigned int bits, BIGNUM *client_host_key_e,
266 BIGNUM *client_host_key_n, int ignore_rhosts,
267 int strict_modes);
268
269/* Tries to authenticate the user using password. Returns true if
270 authentication succeeds. */
271int auth_password(struct passwd *pw, const char *password);
272
273/* Performs the RSA authentication dialog with the client. This returns
274 0 if the client could not be authenticated, and 1 if authentication was
275 successful. This may exit if there is a serious protocol violation. */
276int auth_rsa(struct passwd *pw, BIGNUM *client_n, int strict_modes);
277
278/* Parses an RSA key (number of bits, e, n) from a string. Moves the pointer
279 over the key. Skips any whitespace at the beginning and at end. */
280int auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM *e, BIGNUM *n);
281
282/* Returns the name of the machine at the other end of the socket. The
283 returned string should be freed by the caller. */
284char *get_remote_hostname(int socket);
285
286/* Return the canonical name of the host in the other side of the current
287 connection (as returned by packet_get_connection). The host name is
288 cached, so it is efficient to call this several times. */
289const char *get_canonical_hostname(void);
290
291/* Returns the remote IP address as an ascii string. The value need not be
292 freed by the caller. */
293const char *get_remote_ipaddr(void);
294
295/* Returns the port number of the peer of the socket. */
296int get_peer_port(int sock);
297
298/* Returns the port number of the remote host. */
299int get_remote_port(void);
300
301/* Tries to match the host name (which must be in all lowercase) against the
302 comma-separated sequence of subpatterns (each possibly preceded by ! to
303 indicate negation). Returns true if there is a positive match; zero
304 otherwise. */
305int match_hostname(const char *host, const char *pattern, unsigned int len);
306
307/* Checks whether the given host is already in the list of our known hosts.
308 Returns HOST_OK if the host is known and has the specified key,
309 HOST_NEW if the host is not known, and HOST_CHANGED if the host is known
310 but used to have a different host key. The host must be in all lowercase. */
311typedef enum { HOST_OK, HOST_NEW, HOST_CHANGED } HostStatus;
312HostStatus check_host_in_hostfile(const char *filename,
313 const char *host, unsigned int bits,
314 BIGNUM *e, BIGNUM *n,
315 BIGNUM *ke, BIGNUM *kn);
316
317/* Appends an entry to the host file. Returns false if the entry
318 could not be appended. */
319int add_host_to_hostfile(const char *filename, const char *host,
320 unsigned int bits, BIGNUM *e, BIGNUM *n);
321
322/* Performs the RSA authentication challenge-response dialog with the client,
323 and returns true (non-zero) if the client gave the correct answer to
324 our challenge; returns zero if the client gives a wrong answer. */
325int auth_rsa_challenge_dialog(unsigned int bits, BIGNUM *e, BIGNUM *n);
326
327/* Reads a passphrase from /dev/tty with echo turned off. Returns the
328 passphrase (allocated with xmalloc). Exits if EOF is encountered.
329 If from_stdin is true, the passphrase will be read from stdin instead. */
330char *read_passphrase(const char *prompt, int from_stdin);
331
332/* Saves the authentication (private) key in a file, encrypting it with
333 passphrase. The identification of the file (lowest 64 bits of n)
334 will precede the key to provide identification of the key without
335 needing a passphrase. */
336int save_private_key(const char *filename, const char *passphrase,
337 RSA *private_key, const char *comment);
338
339/* Loads the public part of the key file (public key and comment).
340 Returns 0 if an error occurred; zero if the public key was successfully
341 read. The comment of the key is returned in comment_return if it is
342 non-NULL; the caller must free the value with xfree. */
343int load_public_key(const char *filename, RSA *pub,
344 char **comment_return);
345
346/* Loads the private key from the file. Returns 0 if an error is encountered
347 (file does not exist or is not readable, or passphrase is bad).
348 This initializes the private key. The comment of the key is returned
349 in comment_return if it is non-NULL; the caller must free the value
350 with xfree. */
351int load_private_key(const char *filename, const char *passphrase,
352 RSA *private_key, char **comment_return);
353
354/*------------ Definitions for logging. -----------------------*/
355
356/* Supported syslog facilities. */
357typedef enum
358{
359 SYSLOG_FACILITY_DAEMON,
360 SYSLOG_FACILITY_USER,
361 SYSLOG_FACILITY_AUTH,
362 SYSLOG_FACILITY_LOCAL0,
363 SYSLOG_FACILITY_LOCAL1,
364 SYSLOG_FACILITY_LOCAL2,
365 SYSLOG_FACILITY_LOCAL3,
366 SYSLOG_FACILITY_LOCAL4,
367 SYSLOG_FACILITY_LOCAL5,
368 SYSLOG_FACILITY_LOCAL6,
369 SYSLOG_FACILITY_LOCAL7
370} SyslogFacility;
371
372/* Initializes logging. If debug is non-zero, debug() will output something.
373 If quiet is non-zero, none of these will log send anything to syslog
374 (but maybe to stderr). */
375void log_init(char *av0, int on_stderr, int debug, int quiet,
376 SyslogFacility facility);
377
378/* Outputs a message to syslog or stderr, depending on the implementation.
379 The format must guarantee that the final message does not exceed 1024
380 characters. The message should not contain newline. */
381void log(const char *fmt, ...);
382
383/* Outputs a message to syslog or stderr, depending on the implementation.
384 The format must guarantee that the final message does not exceed 1024
385 characters. The message should not contain newline. */
386void debug(const char *fmt, ...);
387
388/* Outputs a message to syslog or stderr, depending on the implementation.
389 The format must guarantee that the final message does not exceed 1024
390 characters. The message should not contain newline. */
391void error(const char *fmt, ...);
392
393/* Outputs a message to syslog or stderr, depending on the implementation.
394 The format must guarantee that the final message does not exceed 1024
395 characters. The message should not contain newline.
396 This call never returns. */
397void fatal(const char *fmt, ...);
398
399/* Registers a cleanup function to be called by fatal() before exiting.
400 It is permissible to call fatal_remove_cleanup for the function itself
401 from the function. */
402void fatal_add_cleanup(void (*proc)(void *context), void *context);
403
404/* Removes a cleanup frunction to be called at fatal(). */
405void fatal_remove_cleanup(void (*proc)(void *context), void *context);
406
407/*---------------- definitions for channels ------------------*/
408
409/* Sets specific protocol options. */
410void channel_set_options(int hostname_in_open);
411
412/* Allocate a new channel object and set its type and socket. Remote_name
413 must have been allocated with xmalloc; this will free it when the channel
414 is freed. */
415int channel_allocate(int type, int sock, char *remote_name);
416
417/* Free the channel and close its socket. */
418void channel_free(int channel);
419
420/* Add any bits relevant to channels in select bitmasks. */
421void channel_prepare_select(fd_set *readset, fd_set *writeset);
422
423/* After select, perform any appropriate operations for channels which
424 have events pending. */
425void channel_after_select(fd_set *readset, fd_set *writeset);
426
427/* If there is data to send to the connection, send some of it now. */
428void channel_output_poll(void);
429
430/* This is called when a packet of type CHANNEL_DATA has just been received.
431 The message type has already been consumed, but channel number and data
432 is still there. */
433void channel_input_data(int payload_len);
434
435/* Returns true if no channel has too much buffered data. */
436int channel_not_very_much_buffered_data(void);
437
438/* This is called after receiving CHANNEL_CLOSE. */
439void channel_input_close(void);
440
441/* This is called after receiving CHANNEL_CLOSE_CONFIRMATION. */
442void channel_input_close_confirmation(void);
443
444/* This is called after receiving CHANNEL_OPEN_CONFIRMATION. */
445void channel_input_open_confirmation(void);
446
447/* This is called after receiving CHANNEL_OPEN_FAILURE from the other side. */
448void channel_input_open_failure(void);
449
450/* This closes any sockets that are listening for connections; this removes
451 any unix domain sockets. */
452void channel_stop_listening(void);
453
454/* Closes the sockets of all channels. This is used to close extra file
455 descriptors after a fork. */
456void channel_close_all(void);
457
458/* Returns the maximum file descriptor number used by the channels. */
459int channel_max_fd(void);
460
461/* Returns true if there is still an open channel over the connection. */
462int channel_still_open(void);
463
464/* Returns a string containing a list of all open channels. The list is
465 suitable for displaying to the user. It uses crlf instead of newlines.
466 The caller should free the string with xfree. */
467char *channel_open_message(void);
468
469/* Initiate forwarding of connections to local port "port" through the secure
470 channel to host:port from remote side. This never returns if there
471 was an error. */
472void channel_request_local_forwarding(int port, const char *host,
473 int remote_port);
474
475/* Initiate forwarding of connections to port "port" on remote host through
476 the secure channel to host:port from local side. This never returns
477 if there was an error. This registers that open requests for that
478 port are permitted. */
479void channel_request_remote_forwarding(int port, const char *host,
480 int remote_port);
481
482/* Permits opening to any host/port in SSH_MSG_PORT_OPEN. This is usually
483 called by the server, because the user could connect to any port anyway,
484 and the server has no way to know but to trust the client anyway. */
485void channel_permit_all_opens(void);
486
487/* This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates
488 listening for the port, and sends back a success reply (or disconnect
489 message if there was an error). This never returns if there was an
490 error. */
491void channel_input_port_forward_request(int is_root);
492
493/* This is called after receiving PORT_OPEN message. This attempts to connect
494 to the given host:port, and sends back CHANNEL_OPEN_CONFIRMATION or
495 CHANNEL_OPEN_FAILURE. */
496void channel_input_port_open(int payload_len);
497
498/* Creates a port for X11 connections, and starts listening for it.
499 Returns the display name, or NULL if an error was encountered. */
500char *x11_create_display(int screen);
501
502/* Creates an internet domain socket for listening for X11 connections.
503 Returns a suitable value for the DISPLAY variable, or NULL if an error
504 occurs. */
505char *x11_create_display_inet(int screen);
506
507/* This is called when SSH_SMSG_X11_OPEN is received. The packet contains
508 the remote channel number. We should do whatever we want, and respond
509 with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE. */
510void x11_input_open(int payload_len);
511
512/* Requests forwarding of X11 connections. This should be called on the
513 client only. */
514void x11_request_forwarding(void);
515
516/* Requests forwarding for X11 connections, with authentication spoofing.
517 This should be called in the client only. */
518void x11_request_forwarding_with_spoofing(const char *proto, const char *data);
519
520/* Local Xauthority file (server only). */
521extern char *xauthfile;
522
523/* Sends a message to the server to request authentication fd forwarding. */
524void auth_request_forwarding(void);
525
526/* Returns the name of the forwarded authentication socket. Returns NULL
527 if there is no forwarded authentication socket. The returned value points
528 to a static buffer. */
529char *auth_get_socket_name(void);
530
531/* This if called to process SSH_CMSG_AGENT_REQUEST_FORWARDING on the server.
532 This starts forwarding authentication requests. */
533void auth_input_request_forwarding(struct passwd *pw);
534
535/* This is called to process an SSH_SMSG_AGENT_OPEN message. */
536void auth_input_open_request(void);
537
538/* Returns true if the given string matches the pattern (which may contain
539 ? and * as wildcards), and zero if it does not match. */
540int match_pattern(const char *s, const char *pattern);
541
542/* Expands tildes in the file name. Returns data allocated by xmalloc.
543 Warning: this calls getpw*. */
544char *tilde_expand_filename(const char *filename, uid_t my_uid);
545
546/* Performs the interactive session. This handles data transmission between
547 the client and the program. Note that the notion of stdin, stdout, and
548 stderr in this function is sort of reversed: this function writes to
549 stdin (of the child program), and reads from stdout and stderr (of the
550 child program). */
551void server_loop(int pid, int fdin, int fdout, int fderr);
552
553/* Client side main loop for the interactive session. */
554int client_loop(int have_pty, int escape_char);
555
556/* Linked list of custom environment strings (see auth-rsa.c). */
557struct envstring {
558 struct envstring *next;
559 char *s;
560};
561
562#ifdef KRB4
563#include <krb.h>
564
565/* Performs Kerberos v4 mutual authentication with the client. This returns
566 0 if the client could not be authenticated, and 1 if authentication was
567 successful. This may exit if there is a serious protocol violation. */
568int auth_krb4(const char *server_user, KTEXT auth, char **client);
569int ssh_tf_init(uid_t uid);
570
571#ifdef AFS
572#include <kafs.h>
573
574/* Accept passed Kerberos v4 ticket-granting ticket and AFS tokens. */
575int auth_kerberos_tgt(struct passwd *pw, const char *string);
576int auth_afs_token(char *server_user, uid_t uid, const char *string);
577
578int creds_to_radix(CREDENTIALS *creds, unsigned char *buf);
579int radix_to_creds(const char *buf, CREDENTIALS *creds);
580#endif /* AFS */
581
582#endif /* KRB4 */
583
584#ifdef SKEY
585#include <skey.h>
586char *skey_fake_keyinfo(char *username);
587#endif /* SKEY */
588
589#endif /* SSH_H */
diff --git a/ssh.pam b/ssh.pam
new file mode 100644
index 000000000..2a7d1fbd7
--- /dev/null
+++ b/ssh.pam
@@ -0,0 +1,7 @@
1#%PAM-1.0
2auth required /lib/security/pam_pwdb.so shadow
3auth required /lib/security/pam_nologin.so
4account required /lib/security/pam_pwdb.so
5password required /lib/security/pam_cracklib.so
6password required /lib/security/pam_pwdb.so shadow nullok use_authtok
7session required /lib/security/pam_pwdb.so
diff --git a/ssh_config b/ssh_config
new file mode 100644
index 000000000..9fb064deb
--- /dev/null
+++ b/ssh_config
@@ -0,0 +1,30 @@
1# This is ssh client systemwide configuration file. This file provides
2# defaults for users, and the values can be changed in per-user configuration
3# files or on the command line.
4
5# Configuration data is parsed as follows:
6# 1. command line options
7# 2. user-specific file
8# 3. system-wide file
9# Any configuration value is only changed the first time it is set.
10# Thus, host-specific definitions should be at the beginning of the
11# configuration file, and defaults at the end.
12
13# Site-wide defaults for various options
14
15# Host *
16# ForwardAgent yes
17# ForwardX11 yes
18# RhostsAuthentication yes
19# RhostsRSAAuthentication yes
20# RSAAuthentication yes
21# PasswordAuthentication yes
22# FallBackToRsh yes
23# UseRsh no
24# BatchMode no
25# CheckHostIP yes
26# StrictHostKeyChecking no
27# IdentityFile ~/.ssh/identity
28# Port 22
29# Cipher blowfish
30# EscapeChar ~
diff --git a/sshconnect.c b/sshconnect.c
new file mode 100644
index 000000000..3437b04ca
--- /dev/null
+++ b/sshconnect.c
@@ -0,0 +1,1495 @@
1/*
2
3sshconnect.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Sat Mar 18 22:15:47 1995 ylo
11
12Code to connect to a remote host, and to perform the client side of the
13login (authentication) dialog.
14
15*/
16
17#include "includes.h"
18RCSID("$Id: sshconnect.c,v 1.1 1999/10/27 03:42:45 damien Exp $");
19
20#include <openssl/bn.h>
21#include "xmalloc.h"
22#include "rsa.h"
23#include "ssh.h"
24#include "packet.h"
25#include "authfd.h"
26#include "cipher.h"
27#include "mpaux.h"
28#include "uidswap.h"
29#include "compat.h"
30
31#include <openssl/md5.h>
32
33/* Session id for the current session. */
34unsigned char session_id[16];
35
36/* Connect to the given ssh server using a proxy command. */
37
38int
39ssh_proxy_connect(const char *host, int port, uid_t original_real_uid,
40 const char *proxy_command)
41{
42 Buffer command;
43 const char *cp;
44 char *command_string;
45 int pin[2], pout[2];
46 int pid;
47 char portstring[100];
48
49 /* Convert the port number into a string. */
50 snprintf(portstring, sizeof portstring, "%d", port);
51
52 /* Build the final command string in the buffer by making the appropriate
53 substitutions to the given proxy command. */
54 buffer_init(&command);
55 for (cp = proxy_command; *cp; cp++)
56 {
57 if (cp[0] == '%' && cp[1] == '%')
58 {
59 buffer_append(&command, "%", 1);
60 cp++;
61 continue;
62 }
63 if (cp[0] == '%' && cp[1] == 'h')
64 {
65 buffer_append(&command, host, strlen(host));
66 cp++;
67 continue;
68 }
69 if (cp[0] == '%' && cp[1] == 'p')
70 {
71 buffer_append(&command, portstring, strlen(portstring));
72 cp++;
73 continue;
74 }
75 buffer_append(&command, cp, 1);
76 }
77 buffer_append(&command, "\0", 1);
78
79 /* Get the final command string. */
80 command_string = buffer_ptr(&command);
81
82 /* Create pipes for communicating with the proxy. */
83 if (pipe(pin) < 0 || pipe(pout) < 0)
84 fatal("Could not create pipes to communicate with the proxy: %.100s",
85 strerror(errno));
86
87 debug("Executing proxy command: %.500s", command_string);
88
89 /* Fork and execute the proxy command. */
90 if ((pid = fork()) == 0)
91 {
92 char *argv[10];
93
94 /* Child. Permanently give up superuser privileges. */
95 permanently_set_uid(original_real_uid);
96
97 /* Redirect stdin and stdout. */
98 close(pin[1]);
99 if (pin[0] != 0)
100 {
101 if (dup2(pin[0], 0) < 0)
102 perror("dup2 stdin");
103 close(pin[0]);
104 }
105 close(pout[0]);
106 if (dup2(pout[1], 1) < 0)
107 perror("dup2 stdout");
108 close(pout[1]); /* Cannot be 1 because pin allocated two descriptors. */
109
110 /* Stderr is left as it is so that error messages get printed on
111 the user's terminal. */
112 argv[0] = "/bin/sh";
113 argv[1] = "-c";
114 argv[2] = command_string;
115 argv[3] = NULL;
116
117 /* Execute the proxy command. Note that we gave up any extra
118 privileges above. */
119 execv("/bin/sh", argv);
120 perror("/bin/sh");
121 exit(1);
122 }
123 /* Parent. */
124 if (pid < 0)
125 fatal("fork failed: %.100s", strerror(errno));
126
127 /* Close child side of the descriptors. */
128 close(pin[0]);
129 close(pout[1]);
130
131 /* Free the command name. */
132 buffer_free(&command);
133
134 /* Set the connection file descriptors. */
135 packet_set_connection(pout[0], pin[1]);
136
137 return 1;
138}
139
140/* Creates a (possibly privileged) socket for use as the ssh connection. */
141
142int ssh_create_socket(uid_t original_real_uid, int privileged)
143{
144 int sock;
145
146 /* If we are running as root and want to connect to a privileged port,
147 bind our own socket to a privileged port. */
148 if (privileged)
149 {
150 int p = IPPORT_RESERVED - 1;
151
152 sock = rresvport(&p);
153 if (sock < 0)
154 fatal("rresvport: %.100s", strerror(errno));
155 debug("Allocated local port %d.", p);
156 }
157 else
158 {
159 /* Just create an ordinary socket on arbitrary port. We use the
160 user's uid to create the socket. */
161 temporarily_use_uid(original_real_uid);
162 sock = socket(AF_INET, SOCK_STREAM, 0);
163 if (sock < 0)
164 fatal("socket: %.100s", strerror(errno));
165 restore_uid();
166 }
167 return sock;
168}
169
170/* Opens a TCP/IP connection to the remote server on the given host. If
171 port is 0, the default port will be used. If anonymous is zero,
172 a privileged port will be allocated to make the connection.
173 This requires super-user privileges if anonymous is false.
174 Connection_attempts specifies the maximum number of tries (one per
175 second). If proxy_command is non-NULL, it specifies the command (with %h
176 and %p substituted for host and port, respectively) to use to contact
177 the daemon. */
178
179int ssh_connect(const char *host, struct sockaddr_in *hostaddr,
180 int port, int connection_attempts,
181 int anonymous, uid_t original_real_uid,
182 const char *proxy_command)
183{
184 int sock = -1, attempt, i;
185 int on = 1;
186 struct servent *sp;
187 struct hostent *hp;
188 struct linger linger;
189
190 debug("ssh_connect: getuid %d geteuid %d anon %d",
191 (int)getuid(), (int)geteuid(), anonymous);
192
193 /* Get default port if port has not been set. */
194 if (port == 0)
195 {
196 sp = getservbyname(SSH_SERVICE_NAME, "tcp");
197 if (sp)
198 port = ntohs(sp->s_port);
199 else
200 port = SSH_DEFAULT_PORT;
201 }
202
203 /* If a proxy command is given, connect using it. */
204 if (proxy_command != NULL)
205 return ssh_proxy_connect(host, port, original_real_uid, proxy_command);
206
207 /* No proxy command. */
208
209 /* No host lookup made yet. */
210 hp = NULL;
211
212 /* Try to connect several times. On some machines, the first time will
213 sometimes fail. In general socket code appears to behave quite
214 magically on many machines. */
215 for (attempt = 0; attempt < connection_attempts; attempt++)
216 {
217 if (attempt > 0)
218 debug("Trying again...");
219
220 /* Try to parse the host name as a numeric inet address. */
221 memset(hostaddr, 0, sizeof(hostaddr));
222 hostaddr->sin_family = AF_INET;
223 hostaddr->sin_port = htons(port);
224 hostaddr->sin_addr.s_addr = inet_addr(host);
225 if ((hostaddr->sin_addr.s_addr & 0xffffffff) != 0xffffffff)
226 {
227 /* Valid numeric IP address */
228 debug("Connecting to %.100s port %d.",
229 inet_ntoa(hostaddr->sin_addr), port);
230
231 /* Create a socket. */
232 sock = ssh_create_socket(original_real_uid,
233 !anonymous && geteuid() == 0 &&
234 port < IPPORT_RESERVED);
235
236 /* Connect to the host. We use the user's uid in the hope that
237 it will help with the problems of tcp_wrappers showing the
238 remote uid as root. */
239 temporarily_use_uid(original_real_uid);
240 if (connect(sock, (struct sockaddr *)hostaddr, sizeof(*hostaddr))
241 >= 0)
242 {
243 /* Successful connect. */
244 restore_uid();
245 break;
246 }
247 debug("connect: %.100s", strerror(errno));
248 restore_uid();
249
250 /* Destroy the failed socket. */
251 shutdown(sock, SHUT_RDWR);
252 close(sock);
253 }
254 else
255 {
256 /* Not a valid numeric inet address. */
257 /* Map host name to an address. */
258 if (!hp)
259 hp = gethostbyname(host);
260 if (!hp)
261 fatal("Bad host name: %.100s", host);
262 if (!hp->h_addr_list[0])
263 fatal("Host does not have an IP address: %.100s", host);
264
265 /* Loop through addresses for this host, and try each one in
266 sequence until the connection succeeds. */
267 for (i = 0; hp->h_addr_list[i]; i++)
268 {
269 /* Set the address to connect to. */
270 hostaddr->sin_family = hp->h_addrtype;
271 memcpy(&hostaddr->sin_addr, hp->h_addr_list[i],
272 sizeof(hostaddr->sin_addr));
273
274 debug("Connecting to %.200s [%.100s] port %d.",
275 host, inet_ntoa(hostaddr->sin_addr), port);
276
277 /* Create a socket for connecting. */
278 sock = ssh_create_socket(original_real_uid,
279 !anonymous && geteuid() == 0 &&
280 port < IPPORT_RESERVED);
281
282 /* Connect to the host. We use the user's uid in the hope that
283 it will help with tcp_wrappers showing the remote uid as
284 root. */
285 temporarily_use_uid(original_real_uid);
286 if (connect(sock, (struct sockaddr *)hostaddr,
287 sizeof(*hostaddr)) >= 0)
288 {
289 /* Successful connection. */
290 restore_uid();
291 break;
292 }
293 debug("connect: %.100s", strerror(errno));
294 restore_uid();
295
296 /* Close the failed socket; there appear to be some problems
297 when reusing a socket for which connect() has already
298 returned an error. */
299 shutdown(sock, SHUT_RDWR);
300 close(sock);
301 }
302 if (hp->h_addr_list[i])
303 break; /* Successful connection. */
304 }
305
306 /* Sleep a moment before retrying. */
307 sleep(1);
308 }
309 /* Return failure if we didn't get a successful connection. */
310 if (attempt >= connection_attempts)
311 return 0;
312
313 debug("Connection established.");
314
315 /* Set socket options. We would like the socket to disappear as soon as
316 it has been closed for whatever reason. */
317 /* setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */
318 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(on));
319 linger.l_onoff = 1;
320 linger.l_linger = 5;
321 setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger));
322
323 /* Set the connection. */
324 packet_set_connection(sock, sock);
325
326 return 1;
327}
328
329/* Checks if the user has an authentication agent, and if so, tries to
330 authenticate using the agent. */
331
332int
333try_agent_authentication()
334{
335 int status, type, bits;
336 char *comment;
337 AuthenticationConnection *auth;
338 unsigned char response[16];
339 unsigned int i;
340 BIGNUM *e, *n, *challenge;
341
342 /* Get connection to the agent. */
343 auth = ssh_get_authentication_connection();
344 if (!auth)
345 return 0;
346
347 e = BN_new();
348 n = BN_new();
349 challenge = BN_new();
350
351 /* Loop through identities served by the agent. */
352 for (status = ssh_get_first_identity(auth, &bits, e, n, &comment);
353 status;
354 status = ssh_get_next_identity(auth, &bits, e, n, &comment))
355 {
356 int plen, clen;
357
358 /* Try this identity. */
359 debug("Trying RSA authentication via agent with '%.100s'", comment);
360 xfree(comment);
361
362 /* Tell the server that we are willing to authenticate using this key. */
363 packet_start(SSH_CMSG_AUTH_RSA);
364 packet_put_bignum(n);
365 packet_send();
366 packet_write_wait();
367
368 /* Wait for server's response. */
369 type = packet_read(&plen);
370
371 /* The server sends failure if it doesn\'t like our key or does not
372 support RSA authentication. */
373 if (type == SSH_SMSG_FAILURE)
374 {
375 debug("Server refused our key.");
376 continue;
377 }
378
379 /* Otherwise it should have sent a challenge. */
380 if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
381 packet_disconnect("Protocol error during RSA authentication: %d",
382 type);
383
384 packet_get_bignum(challenge, &clen);
385
386 packet_integrity_check(plen, clen, type);
387
388 debug("Received RSA challenge from server.");
389
390 /* Ask the agent to decrypt the challenge. */
391 if (!ssh_decrypt_challenge(auth, bits, e, n, challenge,
392 session_id, 1, response))
393 {
394 /* The agent failed to authenticate this identifier although it
395 advertised it supports this. Just return a wrong value. */
396 log("Authentication agent failed to decrypt challenge.");
397 memset(response, 0, sizeof(response));
398 }
399
400 debug("Sending response to RSA challenge.");
401
402 /* Send the decrypted challenge back to the server. */
403 packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
404 for (i = 0; i < 16; i++)
405 packet_put_char(response[i]);
406 packet_send();
407 packet_write_wait();
408
409 /* Wait for response from the server. */
410 type = packet_read(&plen);
411
412 /* The server returns success if it accepted the authentication. */
413 if (type == SSH_SMSG_SUCCESS)
414 {
415 debug("RSA authentication accepted by server.");
416 BN_clear_free(e);
417 BN_clear_free(n);
418 BN_clear_free(challenge);
419 return 1;
420 }
421
422 /* Otherwise it should return failure. */
423 if (type != SSH_SMSG_FAILURE)
424 packet_disconnect("Protocol error waiting RSA auth response: %d",
425 type);
426 }
427
428 BN_clear_free(e);
429 BN_clear_free(n);
430 BN_clear_free(challenge);
431
432 debug("RSA authentication using agent refused.");
433 return 0;
434}
435
436/* Computes the proper response to a RSA challenge, and sends the response to
437 the server. */
438
439void
440respond_to_rsa_challenge(BIGNUM *challenge, RSA *prv)
441{
442 unsigned char buf[32], response[16];
443 MD5_CTX md;
444 int i, len;
445
446 /* Decrypt the challenge using the private key. */
447 rsa_private_decrypt(challenge, challenge, prv);
448
449 /* Compute the response. */
450 /* The response is MD5 of decrypted challenge plus session id. */
451 len = BN_num_bytes(challenge);
452 assert(len <= sizeof(buf) && len);
453 memset(buf, 0, sizeof(buf));
454 BN_bn2bin(challenge, buf + sizeof(buf) - len);
455 MD5_Init(&md);
456 MD5_Update(&md, buf, 32);
457 MD5_Update(&md, session_id, 16);
458 MD5_Final(response, &md);
459
460 debug("Sending response to host key RSA challenge.");
461
462 /* Send the response back to the server. */
463 packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
464 for (i = 0; i < 16; i++)
465 packet_put_char(response[i]);
466 packet_send();
467 packet_write_wait();
468
469 memset(buf, 0, sizeof(buf));
470 memset(response, 0, sizeof(response));
471 memset(&md, 0, sizeof(md));
472}
473
474/* Checks if the user has authentication file, and if so, tries to authenticate
475 the user using it. */
476
477int
478try_rsa_authentication(struct passwd *pw, const char *authfile,
479 int may_ask_passphrase)
480{
481 BIGNUM *challenge;
482 RSA *private_key;
483 RSA *public_key;
484 char *passphrase, *comment;
485 int type, i;
486 int plen, clen;
487
488 /* Try to load identification for the authentication key. */
489 public_key = RSA_new();
490 if (!load_public_key(authfile, public_key, &comment)) {
491 RSA_free(public_key);
492 return 0; /* Could not load it. Fail. */
493 }
494
495 debug("Trying RSA authentication with key '%.100s'", comment);
496
497 /* Tell the server that we are willing to authenticate using this key. */
498 packet_start(SSH_CMSG_AUTH_RSA);
499 packet_put_bignum(public_key->n);
500 packet_send();
501 packet_write_wait();
502
503 /* We no longer need the public key. */
504 RSA_free(public_key);
505
506 /* Wait for server's response. */
507 type = packet_read(&plen);
508
509 /* The server responds with failure if it doesn\'t like our key or doesn\'t
510 support RSA authentication. */
511 if (type == SSH_SMSG_FAILURE)
512 {
513 debug("Server refused our key.");
514 xfree(comment);
515 return 0; /* Server refuses to authenticate with this key. */
516 }
517
518 /* Otherwise, the server should respond with a challenge. */
519 if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
520 packet_disconnect("Protocol error during RSA authentication: %d", type);
521
522 /* Get the challenge from the packet. */
523 challenge = BN_new();
524 packet_get_bignum(challenge, &clen);
525
526 packet_integrity_check(plen, clen, type);
527
528 debug("Received RSA challenge from server.");
529
530 private_key = RSA_new();
531 /* Load the private key. Try first with empty passphrase; if it fails,
532 ask for a passphrase. */
533 if (!load_private_key(authfile, "", private_key, NULL))
534 {
535 char buf[300];
536 /* Request passphrase from the user. We read from /dev/tty to make
537 this work even if stdin has been redirected. If running in
538 batch mode, we just use the empty passphrase, which will fail and
539 return. */
540 snprintf(buf, sizeof buf,
541 "Enter passphrase for RSA key '%.100s': ", comment);
542 if (may_ask_passphrase)
543 passphrase = read_passphrase(buf, 0);
544 else
545 {
546 debug("Will not query passphrase for %.100s in batch mode.",
547 comment);
548 passphrase = xstrdup("");
549 }
550
551 /* Load the authentication file using the pasphrase. */
552 if (!load_private_key(authfile, passphrase, private_key, NULL))
553 {
554 memset(passphrase, 0, strlen(passphrase));
555 xfree(passphrase);
556 error("Bad passphrase.");
557
558 /* Send a dummy response packet to avoid protocol error. */
559 packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
560 for (i = 0; i < 16; i++)
561 packet_put_char(0);
562 packet_send();
563 packet_write_wait();
564
565 /* Expect the server to reject it... */
566 packet_read_expect(&plen, SSH_SMSG_FAILURE);
567 xfree(comment);
568 return 0;
569 }
570
571 /* Destroy the passphrase. */
572 memset(passphrase, 0, strlen(passphrase));
573 xfree(passphrase);
574 }
575
576 /* We no longer need the comment. */
577 xfree(comment);
578
579 /* Compute and send a response to the challenge. */
580 respond_to_rsa_challenge(challenge, private_key);
581
582 /* Destroy the private key. */
583 RSA_free(private_key);
584
585 /* We no longer need the challenge. */
586 BN_clear_free(challenge);
587
588 /* Wait for response from the server. */
589 type = packet_read(&plen);
590 if (type == SSH_SMSG_SUCCESS)
591 {
592 debug("RSA authentication accepted by server.");
593 return 1;
594 }
595 if (type != SSH_SMSG_FAILURE)
596 packet_disconnect("Protocol error waiting RSA auth response: %d", type);
597 debug("RSA authentication refused.");
598 return 0;
599}
600
601/* Tries to authenticate the user using combined rhosts or /etc/hosts.equiv
602 authentication and RSA host authentication. */
603
604int
605try_rhosts_rsa_authentication(const char *local_user, RSA *host_key)
606{
607 int type;
608 BIGNUM *challenge;
609 int plen, clen;
610
611 debug("Trying rhosts or /etc/hosts.equiv with RSA host authentication.");
612
613 /* Tell the server that we are willing to authenticate using this key. */
614 packet_start(SSH_CMSG_AUTH_RHOSTS_RSA);
615 packet_put_string(local_user, strlen(local_user));
616 packet_put_int(BN_num_bits(host_key->n));
617 packet_put_bignum(host_key->e);
618 packet_put_bignum(host_key->n);
619 packet_send();
620 packet_write_wait();
621
622 /* Wait for server's response. */
623 type = packet_read(&plen);
624
625 /* The server responds with failure if it doesn't admit our .rhosts
626 authentication or doesn't know our host key. */
627 if (type == SSH_SMSG_FAILURE)
628 {
629 debug("Server refused our rhosts authentication or host key.");
630 return 0; /* Server refuses to authenticate us with this method. */
631 }
632
633 /* Otherwise, the server should respond with a challenge. */
634 if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
635 packet_disconnect("Protocol error during RSA authentication: %d", type);
636
637 /* Get the challenge from the packet. */
638 challenge = BN_new();
639 packet_get_bignum(challenge, &clen);
640
641 packet_integrity_check(plen, clen, type);
642
643 debug("Received RSA challenge for host key from server.");
644
645 /* Compute a response to the challenge. */
646 respond_to_rsa_challenge(challenge, host_key);
647
648 /* We no longer need the challenge. */
649 BN_clear_free(challenge);
650
651 /* Wait for response from the server. */
652 type = packet_read(&plen);
653 if (type == SSH_SMSG_SUCCESS)
654 {
655 debug("Rhosts or /etc/hosts.equiv with RSA host authentication accepted by server.");
656 return 1;
657 }
658 if (type != SSH_SMSG_FAILURE)
659 packet_disconnect("Protocol error waiting RSA auth response: %d", type);
660 debug("Rhosts or /etc/hosts.equiv with RSA host authentication refused.");
661 return 0;
662}
663
664#ifdef KRB4
665int try_kerberos_authentication()
666{
667 KTEXT_ST auth; /* Kerberos data */
668 char *reply;
669 char inst[INST_SZ];
670 char *realm;
671 CREDENTIALS cred;
672 int r, type, plen;
673 Key_schedule schedule;
674 u_long checksum, cksum;
675 MSG_DAT msg_data;
676 struct sockaddr_in local, foreign;
677 struct stat st;
678
679 /* Don't do anything if we don't have any tickets. */
680 if (stat(tkt_string(), &st) < 0) return 0;
681
682 strncpy(inst, (char *) krb_get_phost(get_canonical_hostname()), INST_SZ);
683
684 realm = (char *)krb_realmofhost(get_canonical_hostname());
685 if (!realm) {
686 debug("Kerberos V4: no realm for %s", get_canonical_hostname());
687 return 0;
688 }
689 /* This can really be anything. */
690 checksum = (u_long) getpid();
691
692 r = krb_mk_req(&auth, KRB4_SERVICE_NAME, inst, realm, checksum);
693 if (r != KSUCCESS) {
694 debug("Kerberos V4 krb_mk_req failed: %s", krb_err_txt[r]);
695 return 0;
696 }
697 /* Get session key to decrypt the server's reply with. */
698 r = krb_get_cred(KRB4_SERVICE_NAME, inst, realm, &cred);
699 if (r != KSUCCESS) {
700 debug("get_cred failed: %s", krb_err_txt[r]);
701 return 0;
702 }
703 des_key_sched((des_cblock *)cred.session, schedule);
704
705 /* Send authentication info to server. */
706 packet_start(SSH_CMSG_AUTH_KERBEROS);
707 packet_put_string((char *)auth.dat, auth.length);
708 packet_send();
709 packet_write_wait();
710
711 /* Zero the buffer. */
712 (void) memset(auth.dat, 0, MAX_KTXT_LEN);
713
714 r = sizeof(local);
715 memset(&local, 0, sizeof(local));
716 if (getsockname(packet_get_connection_in(),
717 (struct sockaddr *) &local, &r) < 0)
718 debug("getsockname failed: %s", strerror(errno));
719
720 r = sizeof(foreign);
721 memset(&foreign, 0, sizeof(foreign));
722 if (getpeername(packet_get_connection_in(),
723 (struct sockaddr *)&foreign, &r) < 0)
724 debug("getpeername failed: %s", strerror(errno));
725
726 /* Get server reply. */
727 type = packet_read(&plen);
728 switch(type) {
729
730 case SSH_SMSG_FAILURE: /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */
731 debug("Kerberos V4 authentication failed.");
732 return 0;
733 break;
734
735 case SSH_SMSG_AUTH_KERBEROS_RESPONSE: /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */
736 debug("Kerberos V4 authentication accepted.");
737
738 /* Get server's response. */
739 reply = packet_get_string((unsigned int *)&auth.length);
740 memcpy(auth.dat, reply, auth.length);
741 xfree(reply);
742
743 packet_integrity_check(plen, 4 + auth.length, type);
744
745 /* If his response isn't properly encrypted with the session key,
746 and the decrypted checksum fails to match, he's bogus. Bail out. */
747 r = krb_rd_priv(auth.dat, auth.length, schedule, &cred.session,
748 &foreign, &local, &msg_data);
749 if (r != KSUCCESS) {
750 debug("Kerberos V4 krb_rd_priv failed: %s", krb_err_txt[r]);
751 packet_disconnect("Kerberos V4 challenge failed!");
752 }
753 /* Fetch the (incremented) checksum that we supplied in the request. */
754 (void)memcpy((char *)&cksum, (char *)msg_data.app_data, sizeof(cksum));
755 cksum = ntohl(cksum);
756
757 /* If it matches, we're golden. */
758 if (cksum == checksum + 1) {
759 debug("Kerberos V4 challenge successful.");
760 return 1;
761 }
762 else
763 packet_disconnect("Kerberos V4 challenge failed!");
764 break;
765
766 default:
767 packet_disconnect("Protocol error on Kerberos V4 response: %d", type);
768 }
769 return 0;
770}
771#endif /* KRB4 */
772
773#ifdef AFS
774int send_kerberos_tgt()
775{
776 CREDENTIALS *creds;
777 char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
778 int r, type, plen;
779 unsigned char buffer[8192];
780 struct stat st;
781
782 /* Don't do anything if we don't have any tickets. */
783 if (stat(tkt_string(), &st) < 0) return 0;
784
785 creds = xmalloc(sizeof(*creds));
786
787 if ((r = krb_get_tf_fullname(TKT_FILE, pname, pinst, prealm)) != KSUCCESS) {
788 debug("Kerberos V4 tf_fullname failed: %s",krb_err_txt[r]);
789 return 0;
790 }
791 if ((r = krb_get_cred("krbtgt", prealm, prealm, creds)) != GC_OK) {
792 debug("Kerberos V4 get_cred failed: %s", krb_err_txt[r]);
793 return 0;
794 }
795 if (time(0) > krb_life_to_time(creds->issue_date, creds->lifetime)) {
796 debug("Kerberos V4 ticket expired: %s", TKT_FILE);
797 return 0;
798 }
799
800 creds_to_radix(creds, buffer);
801 xfree(creds);
802
803 packet_start(SSH_CMSG_HAVE_KERBEROS_TGT);
804 packet_put_string((char *)buffer, strlen(buffer));
805 packet_send();
806 packet_write_wait();
807
808 type = packet_read(&plen);
809
810 if (type == SSH_SMSG_FAILURE)
811 debug("Kerberos TGT for realm %s rejected.", prealm);
812 else if (type != SSH_SMSG_SUCCESS)
813 packet_disconnect("Protocol error on Kerberos TGT response: %d", type);
814
815 return 1;
816}
817
818void send_afs_tokens(void)
819{
820 CREDENTIALS creds;
821 struct ViceIoctl parms;
822 struct ClearToken ct;
823 int i, type, len, plen;
824 char buf[2048], *p, *server_cell;
825 unsigned char buffer[8192];
826
827 /* Move over ktc_GetToken, here's something leaner. */
828 for (i = 0; i < 100; i++) { /* just in case */
829 parms.in = (char *)&i;
830 parms.in_size = sizeof(i);
831 parms.out = buf;
832 parms.out_size = sizeof(buf);
833 if (k_pioctl(0, VIOCGETTOK, &parms, 0) != 0) break;
834 p = buf;
835
836 /* Get secret token. */
837 memcpy(&creds.ticket_st.length, p, sizeof(unsigned int));
838 if (creds.ticket_st.length > MAX_KTXT_LEN) break;
839 p += sizeof(unsigned int);
840 memcpy(creds.ticket_st.dat, p, creds.ticket_st.length);
841 p += creds.ticket_st.length;
842
843 /* Get clear token. */
844 memcpy(&len, p, sizeof(len));
845 if (len != sizeof(struct ClearToken)) break;
846 p += sizeof(len);
847 memcpy(&ct, p, len);
848 p += len;
849 p += sizeof(len); /* primary flag */
850 server_cell = p;
851
852 /* Flesh out our credentials. */
853 strlcpy(creds.service, "afs", sizeof creds.service);
854 creds.instance[0] = '\0';
855 strlcpy(creds.realm, server_cell, REALM_SZ);
856 memcpy(creds.session, ct.HandShakeKey, DES_KEY_SZ);
857 creds.issue_date = ct.BeginTimestamp;
858 creds.lifetime = krb_time_to_life(creds.issue_date, ct.EndTimestamp);
859 creds.kvno = ct.AuthHandle;
860 snprintf(creds.pname, sizeof(creds.pname), "AFS ID %d", ct.ViceId);
861 creds.pinst[0] = '\0';
862
863 /* Encode token, ship it off. */
864 if (!creds_to_radix(&creds, buffer)) break;
865 packet_start(SSH_CMSG_HAVE_AFS_TOKEN);
866 packet_put_string((char *)buffer, strlen(buffer));
867 packet_send();
868 packet_write_wait();
869
870 /* Roger, Roger. Clearance, Clarence. What's your vector, Victor? */
871 type = packet_read(&plen);
872
873 if (type == SSH_SMSG_FAILURE)
874 debug("AFS token for cell %s rejected.", server_cell);
875 else if (type != SSH_SMSG_SUCCESS)
876 packet_disconnect("Protocol error on AFS token response: %d", type);
877 }
878}
879#endif /* AFS */
880
881/* Waits for the server identification string, and sends our own identification
882 string. */
883
884void ssh_exchange_identification()
885{
886 char buf[256], remote_version[256]; /* must be same size! */
887 int remote_major, remote_minor, i;
888 int connection_in = packet_get_connection_in();
889 int connection_out = packet_get_connection_out();
890 extern Options options;
891
892 /* Read other side\'s version identification. */
893 for (i = 0; i < sizeof(buf) - 1; i++)
894 {
895 if (read(connection_in, &buf[i], 1) != 1)
896 fatal("read: %.100s", strerror(errno));
897 if (buf[i] == '\r')
898 {
899 buf[i] = '\n';
900 buf[i + 1] = 0;
901 break;
902 }
903 if (buf[i] == '\n')
904 {
905 buf[i + 1] = 0;
906 break;
907 }
908 }
909 buf[sizeof(buf) - 1] = 0;
910
911 /* Check that the versions match. In future this might accept several
912 versions and set appropriate flags to handle them. */
913 if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor,
914 remote_version) != 3)
915 fatal("Bad remote protocol version identification: '%.100s'", buf);
916 debug("Remote protocol version %d.%d, remote software version %.100s",
917 remote_major, remote_minor, remote_version);
918
919 /* Check if the remote protocol version is too old. */
920 if (remote_major == 1 && remote_minor < 3)
921 fatal("Remote machine has too old SSH software version.");
922
923 /* We speak 1.3, too. */
924 if (remote_major == 1 && remote_minor == 3) {
925 enable_compat13();
926 if (options.forward_agent && strcmp(remote_version, SSH_VERSION) != 0) {
927 log("Agent forwarding disabled, remote version '%s' is not compatible.",
928 remote_version);
929 options.forward_agent = 0;
930 }
931 }
932#if 0
933 /* Removed for now, to permit compatibility with latter versions. The server
934 will reject our version and disconnect if it doesn't support it. */
935 if (remote_major != PROTOCOL_MAJOR)
936 fatal("Protocol major versions differ: %d vs. %d",
937 PROTOCOL_MAJOR, remote_major);
938#endif
939
940 /* Send our own protocol version identification. */
941 snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
942 PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION);
943 if (write(connection_out, buf, strlen(buf)) != strlen(buf))
944 fatal("write: %.100s", strerror(errno));
945}
946
947int ssh_cipher_default = SSH_CIPHER_3DES;
948
949int read_yes_or_no(const char *prompt, int defval)
950{
951 char buf[1024];
952 FILE *f;
953 int retval = -1;
954
955 if (isatty(0))
956 f = stdin;
957 else
958 f = fopen("/dev/tty", "rw");
959
960 if (f == NULL)
961 return 0;
962
963 fflush(stdout);
964
965 while (1)
966 {
967 fprintf(stderr, "%s", prompt);
968 if (fgets(buf, sizeof(buf), f) == NULL)
969 {
970 /* Print a newline (the prompt probably didn\'t have one). */
971 fprintf(stderr, "\n");
972 strlcpy(buf, "no", sizeof buf);
973 }
974 /* Remove newline from response. */
975 if (strchr(buf, '\n'))
976 *strchr(buf, '\n') = 0;
977
978 if (buf[0] == 0)
979 retval = defval;
980 if (strcmp(buf, "yes") == 0)
981 retval = 1;
982 if (strcmp(buf, "no") == 0)
983 retval = 0;
984
985 if (retval != -1)
986 {
987 if (f != stdin)
988 fclose(f);
989 return retval;
990 }
991 }
992}
993
994/* Starts a dialog with the server, and authenticates the current user on the
995 server. This does not need any extra privileges. The basic connection
996 to the server must already have been established before this is called.
997 User is the remote user; if it is NULL, the current local user name will
998 be used. Anonymous indicates that no rhosts authentication will be used.
999 If login fails, this function prints an error and never returns.
1000 This function does not require super-user privileges. */
1001
1002void ssh_login(int host_key_valid,
1003 RSA *own_host_key,
1004 const char *orighost,
1005 struct sockaddr_in *hostaddr,
1006 Options *options, uid_t original_real_uid)
1007{
1008 int i, type;
1009 char *password;
1010 struct passwd *pw;
1011 BIGNUM *key;
1012 RSA *host_key, *file_key;
1013 RSA *public_key;
1014 unsigned char session_key[SSH_SESSION_KEY_LENGTH];
1015 const char *server_user, *local_user;
1016 char *cp, *host, *ip = NULL;
1017 unsigned char check_bytes[8];
1018 unsigned int supported_ciphers, supported_authentications, protocol_flags;
1019 HostStatus host_status;
1020 HostStatus ip_status;
1021 int host_ip_differ = 0;
1022 int local = (ntohl(hostaddr->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;
1023 int payload_len, clen, sum_len = 0;
1024 u_int32_t rand = 0;
1025
1026 if (options->check_host_ip)
1027 ip = xstrdup(inet_ntoa(hostaddr->sin_addr));
1028
1029 /* Convert the user-supplied hostname into all lowercase. */
1030 host = xstrdup(orighost);
1031 for (cp = host; *cp; cp++)
1032 if (isupper(*cp))
1033 *cp = tolower(*cp);
1034
1035 /* Exchange protocol version identification strings with the server. */
1036 ssh_exchange_identification();
1037
1038 /* Put the connection into non-blocking mode. */
1039 packet_set_nonblocking();
1040
1041 /* Get local user name. Use it as server user if no user name
1042 was given. */
1043 pw = getpwuid(original_real_uid);
1044 if (!pw)
1045 fatal("User id %d not found from user database.", original_real_uid);
1046 local_user = xstrdup(pw->pw_name);
1047 server_user = options->user ? options->user : local_user;
1048
1049 debug("Waiting for server public key.");
1050
1051 /* Wait for a public key packet from the server. */
1052 packet_read_expect(&payload_len, SSH_SMSG_PUBLIC_KEY);
1053
1054 /* Get check bytes from the packet. */
1055 for (i = 0; i < 8; i++)
1056 check_bytes[i] = packet_get_char();
1057
1058 /* Get the public key. */
1059 public_key = RSA_new();
1060 packet_get_int(); /* bits */
1061 public_key->e = BN_new();
1062 packet_get_bignum(public_key->e, &clen);
1063 sum_len += clen;
1064 public_key->n = BN_new();
1065 packet_get_bignum(public_key->n, &clen);
1066 sum_len += clen;
1067
1068 /* Get the host key. */
1069 host_key = RSA_new();
1070 packet_get_int(); /* bits */
1071 host_key->e = BN_new();
1072 packet_get_bignum(host_key->e, &clen);
1073 sum_len += clen;
1074 host_key->n = BN_new();
1075 packet_get_bignum(host_key->n, &clen);
1076 sum_len += clen;
1077
1078 /* Store the host key from the known host file in here
1079 * so that we can compare it with the key for the IP
1080 * address. */
1081 file_key = RSA_new();
1082 file_key->n = BN_new();
1083 file_key->e = BN_new();
1084
1085 /* Get protocol flags. */
1086 protocol_flags = packet_get_int();
1087 packet_set_protocol_flags(protocol_flags);
1088
1089 /* Get supported cipher types. */
1090 supported_ciphers = packet_get_int();
1091
1092 /* Get supported authentication types. */
1093 supported_authentications = packet_get_int();
1094
1095 debug("Received server public key (%d bits) and host key (%d bits).",
1096 BN_num_bits(public_key->n), BN_num_bits(host_key->n));
1097
1098 packet_integrity_check(payload_len,
1099 8 + 4 + sum_len + 0 + 4 + 0 + 0 + 4 + 4 + 4,
1100 SSH_SMSG_PUBLIC_KEY);
1101
1102 /* Compute the session id. */
1103 compute_session_id(session_id, check_bytes,
1104 BN_num_bits(host_key->n), host_key->n,
1105 BN_num_bits(public_key->n), public_key->n);
1106
1107 /* Check if the host key is present in the user\'s list of known hosts
1108 or in the systemwide list. */
1109 host_status = check_host_in_hostfile(options->user_hostfile,
1110 host, BN_num_bits(host_key->n),
1111 host_key->e, host_key->n,
1112 file_key->e, file_key->n);
1113 if (host_status == HOST_NEW)
1114 host_status = check_host_in_hostfile(options->system_hostfile, host,
1115 BN_num_bits(host_key->n),
1116 host_key->e, host_key->n,
1117 file_key->e, file_key->n);
1118 /* Force accepting of the host key for localhost and 127.0.0.1.
1119 The problem is that if the home directory is NFS-mounted to multiple
1120 machines, localhost will refer to a different machine in each of them,
1121 and the user will get bogus HOST_CHANGED warnings. This essentially
1122 disables host authentication for localhost; however, this is probably
1123 not a real problem. */
1124 if (local) {
1125 debug("Forcing accepting of host key for localhost.");
1126 host_status = HOST_OK;
1127 }
1128
1129 /* Also perform check for the ip address, skip the check if we are
1130 localhost or the hostname was an ip address to begin with */
1131 if (options->check_host_ip && !local && strcmp(host, ip)) {
1132 RSA *ip_key = RSA_new();
1133 ip_key->n = BN_new();
1134 ip_key->e = BN_new();
1135 ip_status = check_host_in_hostfile(options->user_hostfile, ip,
1136 BN_num_bits(host_key->n),
1137 host_key->e, host_key->n,
1138 ip_key->e, ip_key->n);
1139
1140 if (ip_status == HOST_NEW)
1141 ip_status = check_host_in_hostfile(options->system_hostfile, ip,
1142 BN_num_bits(host_key->n),
1143 host_key->e, host_key->n,
1144 ip_key->e, ip_key->n);
1145 if (host_status == HOST_CHANGED &&
1146 (ip_status != HOST_CHANGED ||
1147 (BN_cmp(ip_key->e, file_key->e) || BN_cmp(ip_key->n, file_key->n))))
1148 host_ip_differ = 1;
1149
1150 RSA_free(ip_key);
1151 } else
1152 ip_status = host_status;
1153
1154 RSA_free(file_key);
1155
1156 switch (host_status) {
1157 case HOST_OK:
1158 /* The host is known and the key matches. */
1159 debug("Host '%.200s' is known and matches the host key.", host);
1160 if (options->check_host_ip) {
1161 if (ip_status == HOST_NEW) {
1162 if (!add_host_to_hostfile(options->user_hostfile, ip,
1163 BN_num_bits(host_key->n),
1164 host_key->e, host_key->n))
1165 log("Failed to add the host ip to the list of known hosts (%.30s).",
1166 options->user_hostfile);
1167 else
1168 log("Warning: Permanently added host ip '%.30s' to the list of known hosts.", ip);
1169 } else if (ip_status != HOST_OK)
1170 log("Warning: the host key differ from the key of the ip address '%.30s' differs", ip);
1171 }
1172
1173 break;
1174 case HOST_NEW:
1175 {
1176 char hostline[1000], *hostp = hostline;
1177 /* The host is new. */
1178 if (options->strict_host_key_checking == 1) {
1179 /* User has requested strict host key checking. We will not
1180 add the host key automatically. The only alternative left
1181 is to abort. */
1182 fatal("No host key is known for %.200s and you have requested strict checking.", host);
1183 } else if (options->strict_host_key_checking == 2) { /* The default */
1184 char prompt[1024];
1185 snprintf(prompt, sizeof(prompt),
1186 "The authenticity of host '%.200s' can't be established.\n"
1187 "Are you sure you want to continue connecting (yes/no)? ",
1188 host);
1189 if (!read_yes_or_no(prompt, -1))
1190 fatal("Aborted by user!\n");
1191 }
1192
1193 if (options->check_host_ip && ip_status == HOST_NEW && strcmp(host, ip))
1194 snprintf(hostline, sizeof(hostline), "%s,%s", host, ip);
1195 else
1196 hostp = host;
1197
1198 /* If not in strict mode, add the key automatically to the local
1199 known_hosts file. */
1200 if (!add_host_to_hostfile(options->user_hostfile, hostp,
1201 BN_num_bits(host_key->n),
1202 host_key->e, host_key->n))
1203 log("Failed to add the host to the list of known hosts (%.500s).",
1204 options->user_hostfile);
1205 else
1206 log("Warning: Permanently added '%.200s' to the list of known hosts.",
1207 hostp);
1208 break;
1209 }
1210 case HOST_CHANGED:
1211 if (options->check_host_ip) {
1212 if (host_ip_differ) {
1213 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1214 error("@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @");
1215 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1216 error("The host key for %s has changed,", host);
1217 error("but the key for the according IP address %s has", ip);
1218 error("a different status. This could either mean that DNS");
1219 error("SPOOFING is happening or the IP address for the host");
1220 error("and its host key have changed at the same time");
1221 }
1222 }
1223
1224 /* The host key has changed. */
1225 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1226 error("@ WARNING: HOST IDENTIFICATION HAS CHANGED! @");
1227 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1228 error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
1229 error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
1230 error("It is also possible that the host key has just been changed.");
1231 error("Please contact your system administrator.");
1232 error("Add correct host key in %.100s to get rid of this message.",
1233 options->user_hostfile);
1234
1235 /* If strict host key checking is in use, the user will have to edit
1236 the key manually and we can only abort. */
1237 if (options->strict_host_key_checking)
1238 fatal("Host key for %.200s has changed and you have requested strict checking.", host);
1239
1240 /* If strict host key checking has not been requested, allow the
1241 connection but without password authentication or
1242 agent forwarding. */
1243 if (options->password_authentication) {
1244 error("Password authentication is disabled to avoid trojan horses.");
1245 options->password_authentication = 0;
1246 }
1247 if (options->forward_agent) {
1248 error("Agent forwarding is disabled to avoid trojan horses.");
1249 options->forward_agent = 0;
1250 }
1251 /* XXX Should permit the user to change to use the new id. This could
1252 be done by converting the host key to an identifying sentence, tell
1253 that the host identifies itself by that sentence, and ask the user
1254 if he/she whishes to accept the authentication. */
1255 break;
1256 }
1257
1258 if (options->check_host_ip)
1259 xfree(ip);
1260
1261 /* Generate a session key. */
1262 arc4random_stir();
1263
1264 /* Generate an encryption key for the session. The key is a 256 bit
1265 random number, interpreted as a 32-byte key, with the least significant
1266 8 bits being the first byte of the key. */
1267 for (i = 0; i < 32; i++) {
1268 if (i % 4 == 0)
1269 rand = arc4random();
1270 session_key[i] = rand & 0xff;
1271 rand >>= 8;
1272 }
1273
1274 /* According to the protocol spec, the first byte of the session key is
1275 the highest byte of the integer. The session key is xored with the
1276 first 16 bytes of the session id. */
1277 key = BN_new();
1278 BN_set_word(key, 0);
1279 for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++)
1280 {
1281 BN_lshift(key, key, 8);
1282 if (i < 16)
1283 BN_add_word(key, session_key[i] ^ session_id[i]);
1284 else
1285 BN_add_word(key, session_key[i]);
1286 }
1287
1288 /* Encrypt the integer using the public key and host key of the server
1289 (key with smaller modulus first). */
1290 if (BN_cmp(public_key->n, host_key->n) < 0)
1291 {
1292 /* Public key has smaller modulus. */
1293 assert(BN_num_bits(host_key->n) >=
1294 BN_num_bits(public_key->n) + SSH_KEY_BITS_RESERVED);
1295
1296 rsa_public_encrypt(key, key, public_key);
1297 rsa_public_encrypt(key, key, host_key);
1298 }
1299 else
1300 {
1301 /* Host key has smaller modulus (or they are equal). */
1302 assert(BN_num_bits(public_key->n) >=
1303 BN_num_bits(host_key->n) + SSH_KEY_BITS_RESERVED);
1304
1305 rsa_public_encrypt(key, key, host_key);
1306 rsa_public_encrypt(key, key, public_key);
1307 }
1308
1309 if (options->cipher == SSH_CIPHER_NOT_SET) {
1310 if (cipher_mask() & supported_ciphers & (1 << ssh_cipher_default))
1311 options->cipher = ssh_cipher_default;
1312 else {
1313 debug("Cipher %d not supported, using %.100s instead.",
1314 cipher_name(ssh_cipher_default),
1315 cipher_name(SSH_FALLBACK_CIPHER));
1316 options->cipher = SSH_FALLBACK_CIPHER;
1317 }
1318 }
1319
1320 /* Check that the selected cipher is supported. */
1321 if (!(supported_ciphers & (1 << options->cipher)))
1322 fatal("Selected cipher type %.100s not supported by server.",
1323 cipher_name(options->cipher));
1324
1325 debug("Encryption type: %.100s", cipher_name(options->cipher));
1326
1327 /* Send the encrypted session key to the server. */
1328 packet_start(SSH_CMSG_SESSION_KEY);
1329 packet_put_char(options->cipher);
1330
1331 /* Send the check bytes back to the server. */
1332 for (i = 0; i < 8; i++)
1333 packet_put_char(check_bytes[i]);
1334
1335 /* Send the encrypted encryption key. */
1336 packet_put_bignum(key);
1337
1338 /* Send protocol flags. */
1339 packet_put_int(SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
1340
1341 /* Send the packet now. */
1342 packet_send();
1343 packet_write_wait();
1344
1345 /* Destroy the session key integer and the public keys since we no longer
1346 need them. */
1347 BN_clear_free(key);
1348 RSA_free(public_key);
1349 RSA_free(host_key);
1350
1351 debug("Sent encrypted session key.");
1352
1353 /* Set the encryption key. */
1354 packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH,
1355 options->cipher, 1);
1356
1357 /* We will no longer need the session key here. Destroy any extra copies. */
1358 memset(session_key, 0, sizeof(session_key));
1359
1360 /* Expect a success message from the server. Note that this message will
1361 be received in encrypted form. */
1362 packet_read_expect(&payload_len, SSH_SMSG_SUCCESS);
1363
1364 debug("Received encrypted confirmation.");
1365
1366 /* Send the name of the user to log in as on the server. */
1367 packet_start(SSH_CMSG_USER);
1368 packet_put_string(server_user, strlen(server_user));
1369 packet_send();
1370 packet_write_wait();
1371
1372 /* The server should respond with success if no authentication is needed
1373 (the user has no password). Otherwise the server responds with
1374 failure. */
1375 type = packet_read(&payload_len);
1376 if (type == SSH_SMSG_SUCCESS)
1377 return; /* Connection was accepted without authentication. */
1378 if (type != SSH_SMSG_FAILURE)
1379 packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER",
1380 type);
1381
1382#ifdef AFS
1383 /* Try Kerberos tgt passing if the server supports it. */
1384 if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) &&
1385 options->kerberos_tgt_passing)
1386 {
1387 if (options->cipher == SSH_CIPHER_NONE)
1388 log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!");
1389 (void)send_kerberos_tgt();
1390 }
1391
1392 /* Try AFS token passing if the server supports it. */
1393 if ((supported_authentications & (1 << SSH_PASS_AFS_TOKEN)) &&
1394 options->afs_token_passing && k_hasafs()) {
1395 if (options->cipher == SSH_CIPHER_NONE)
1396 log("WARNING: Encryption is disabled! Token will be transmitted in the clear!");
1397 send_afs_tokens();
1398 }
1399#endif /* AFS */
1400
1401#ifdef KRB4
1402 if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) &&
1403 options->kerberos_authentication)
1404 {
1405 debug("Trying Kerberos authentication.");
1406 if (try_kerberos_authentication()) {
1407 /* The server should respond with success or failure. */
1408 type = packet_read(&payload_len);
1409 if (type == SSH_SMSG_SUCCESS)
1410 return; /* Successful connection. */
1411 if (type != SSH_SMSG_FAILURE)
1412 packet_disconnect("Protocol error: got %d in response to Kerberos auth", type);
1413 }
1414 }
1415#endif /* KRB4 */
1416
1417 /* Use rhosts authentication if running in privileged socket and we do not
1418 wish to remain anonymous. */
1419 if ((supported_authentications & (1 << SSH_AUTH_RHOSTS)) &&
1420 options->rhosts_authentication)
1421 {
1422 debug("Trying rhosts authentication.");
1423 packet_start(SSH_CMSG_AUTH_RHOSTS);
1424 packet_put_string(local_user, strlen(local_user));
1425 packet_send();
1426 packet_write_wait();
1427
1428 /* The server should respond with success or failure. */
1429 type = packet_read(&payload_len);
1430 if (type == SSH_SMSG_SUCCESS)
1431 return; /* Successful connection. */
1432 if (type != SSH_SMSG_FAILURE)
1433 packet_disconnect("Protocol error: got %d in response to rhosts auth",
1434 type);
1435 }
1436
1437 /* Try .rhosts or /etc/hosts.equiv authentication with RSA host
1438 authentication. */
1439 if ((supported_authentications & (1 << SSH_AUTH_RHOSTS_RSA)) &&
1440 options->rhosts_rsa_authentication && host_key_valid)
1441 {
1442 if (try_rhosts_rsa_authentication(local_user, own_host_key))
1443 return; /* Successful authentication. */
1444 }
1445
1446 /* Try RSA authentication if the server supports it. */
1447 if ((supported_authentications & (1 << SSH_AUTH_RSA)) &&
1448 options->rsa_authentication)
1449 {
1450 /* Try RSA authentication using the authentication agent. The agent
1451 is tried first because no passphrase is needed for it, whereas
1452 identity files may require passphrases. */
1453 if (try_agent_authentication())
1454 return; /* Successful connection. */
1455
1456 /* Try RSA authentication for each identity. */
1457 for (i = 0; i < options->num_identity_files; i++)
1458 if (try_rsa_authentication(pw, options->identity_files[i],
1459 !options->batch_mode))
1460 return; /* Successful connection. */
1461 }
1462
1463 /* Try password authentication if the server supports it. */
1464 if ((supported_authentications & (1 << SSH_AUTH_PASSWORD)) &&
1465 options->password_authentication && !options->batch_mode)
1466 {
1467 char prompt[80];
1468 snprintf(prompt, sizeof(prompt), "%.30s@%.30s's password: ",
1469 server_user, host);
1470 debug("Doing password authentication.");
1471 if (options->cipher == SSH_CIPHER_NONE)
1472 log("WARNING: Encryption is disabled! Password will be transmitted in clear text.");
1473 for (i = 0; i < options->number_of_password_prompts; i++) {
1474 if (i != 0)
1475 error("Permission denied, please try again.");
1476 password = read_passphrase(prompt, 0);
1477 packet_start(SSH_CMSG_AUTH_PASSWORD);
1478 packet_put_string(password, strlen(password));
1479 memset(password, 0, strlen(password));
1480 xfree(password);
1481 packet_send();
1482 packet_write_wait();
1483
1484 type = packet_read(&payload_len);
1485 if (type == SSH_SMSG_SUCCESS)
1486 return; /* Successful connection. */
1487 if (type != SSH_SMSG_FAILURE)
1488 packet_disconnect("Protocol error: got %d in response to passwd auth", type);
1489 }
1490 }
1491
1492 /* All authentication methods have failed. Exit with an error message. */
1493 fatal("Permission denied.");
1494 /*NOTREACHED*/
1495}
diff --git a/sshd.8 b/sshd.8
new file mode 100644
index 000000000..981c5ff72
--- /dev/null
+++ b/sshd.8
@@ -0,0 +1,781 @@
1.\" -*- nroff -*-
2.\"
3.\" sshd.8.in
4.\"
5.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
6.\"
7.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8.\" All rights reserved
9.\"
10.\" Created: Sat Apr 22 21:55:14 1995 ylo
11.\"
12.\" $Id: sshd.8,v 1.1 1999/10/27 03:42:46 damien Exp $
13.\"
14.Dd September 25, 1999
15.Dt SSHD 8
16.Os
17.Sh NAME
18.Nm sshd
19.Nd secure shell daemon
20.Sh SYNOPSIS
21.Nm sshd
22.Op Fl diq
23.Op Fl b Ar bits
24.Op Fl f Ar config_file
25.Op Fl g Ar login_grace_time
26.Op Fl h Ar host_key_file
27.Op Fl k Ar key_gen_time
28.Op Fl p Ar port
29.Sh DESCRIPTION
30.Nm
31(Secure Shell Daemon) is the daemon program for
32.Xr ssh 1 .
33Together these programs replace rlogin and rsh programs, and
34provide secure encrypted communications between two untrusted hosts
35over an insecure network. The programs are intended to be as easy to
36install and use as possible.
37.Pp
38.Nm
39is the daemon that listens for connections from clients. It is
40normally started at boot from
41.Pa /etc/rc .
42It forks a new
43daemon for each incoming connection. The forked daemons handle
44key exchange, encryption, authentication, command execution,
45and data exchange.
46.Pp
47.Nm
48works as follows. Each host has a host-specific RSA key
49(normally 1024 bits) used to identify the host. Additionally, when
50the daemon starts, it generates a server RSA key (normally 768 bits).
51This key is normally regenerated every hour if it has been used, and
52is never stored on disk.
53.Pp
54Whenever a client connects the daemon, the daemon sends its host
55and server public keys to the client. The client compares the
56host key against its own database to verify that it has not changed.
57The client then generates a 256 bit random number. It encrypts this
58random number using both the host key and the server key, and sends
59the encrypted number to the server. Both sides then start to use this
60random number as a session key which is used to encrypt all further
61communications in the session. The rest of the session is encrypted
62using a conventional cipher, currently Blowfish and 3DES, with 3DES
63being is used by default. The client selects the encryption algorithm
64to use from those offered by the server.
65.Pp
66Next, the server and the client enter an authentication dialog. The
67client tries to authenticate itself using
68.Pa .rhosts
69authentication,
70.Pa .rhosts
71authentication combined with RSA host
72authentication, RSA challenge-response authentication, or password
73based authentication.
74.Pp
75Rhosts authentication is normally disabled
76because it is fundamentally insecure, but can be enabled in the server
77configuration file if desired. System security is not improved unless
78.Xr rshd 8 ,
79.Xr rlogind 8 ,
80.Xr rexecd 8 ,
81and
82.Xr rexd 8
83are disabled (thus completely disabling
84.Xr rlogin 1
85and
86.Xr rsh 1
87into that machine).
88.Pp
89If the client successfully authenticates itself, a dialog for
90preparing the session is entered. At this time the client may request
91things like allocating a pseudo-tty, forwarding X11 connections,
92forwarding TCP/IP connections, or forwarding the authentication agent
93connection over the secure channel.
94.Pp
95Finally, the client either requests a shell or execution of a command.
96The sides then enter session mode. In this mode, either side may send
97data at any time, and such data is forwarded to/from the shell or
98command on the server side, and the user terminal in the client side.
99.Pp
100When the user program terminates and all forwarded X11 and other
101connections have been closed, the server sends command exit status to
102the client, and both sides exit.
103.Pp
104.Nm
105can be configured using command-line options or a configuration
106file. Command-line options override values specified in the
107configuration file.
108.Pp
109The options are as follows:
110.Bl -tag -width Ds
111.It Fl b Ar bits
112Specifies the number of bits in the server key (default 768).
113.Pp
114.It Fl d
115Debug mode. The server sends verbose debug output to the system
116log, and does not put itself in the background. The server also will
117not fork and will only process one connection. This option is only
118intended for debugging for the server.
119.It Fl f Ar configuration_file
120Specifies the name of the configuration file. The default is
121.Pa /etc/sshd_config .
122.Nm
123refuses to start if there is no configuration file.
124.It Fl g Ar login_grace_time
125Gives the grace time for clients to authenticate themselves (default
126300 seconds). If the client fails to authenticate the user within
127this many seconds, the server disconnects and exits. A value of zero
128indicates no limit.
129.It Fl h Ar host_key_file
130Specifies the file from which the host key is read (default
131.Pa /etc/ssh_host_key ) .
132This option must be given if
133.Nm
134is not run as root (as the normal
135host file is normally not readable by anyone but root).
136.It Fl i
137Specifies that
138.Nm
139is being run from inetd.
140.Nm
141is normally not run
142from inetd because it needs to generate the server key before it can
143respond to the client, and this may take tens of seconds. Clients
144would have to wait too long if the key was regenerated every time.
145However, with small key sizes (e.g. 512) using
146.Nm
147from inetd may
148be feasible.
149.It Fl k Ar key_gen_time
150Specifies how often the server key is regenerated (default 3600
151seconds, or one hour). The motivation for regenerating the key fairly
152often is that the key is not stored anywhere, and after about an hour,
153it becomes impossible to recover the key for decrypting intercepted
154communications even if the machine is cracked into or physically
155seized. A value of zero indicates that the key will never be regenerated.
156.It Fl p Ar port
157Specifies the port on which the server listens for connections
158(default 22).
159.It Fl q
160Quiet mode. Nothing is sent to the system log. Normally the beginning,
161authentication, and termination of each connection is logged.
162.It Fl Q
163Do not print an error message if RSA support is missing.
164.El
165.Sh CONFIGURATION FILE
166.Nm
167reads configuration data from
168.Pa /etc/sshd_config
169(or the file specified with
170.Fl f
171on the command line). The file
172contains keyword-value pairs, one per line. Lines starting with
173.Ql #
174and empty lines are interpreted as comments.
175.Pp
176The following keywords are possible.
177.Bl -tag -width Ds
178.It Cm AFSTokenPassing
179Specifies whether an AFS token may be forwarded to the server. Default is
180.Dq yes .
181.It Cm AllowGroups
182This keyword can be followed by a number of group names, separated
183by spaces. If specified, login is allowed only for users whose primary
184group matches one of the patterns.
185.Ql \&*
186and
187.Ql ?
188can be used as
189wildcards in the patterns. Only group names are valid, a numerical group
190id isn't recognized. By default login is allowed regardless of
191the primary group.
192.Pp
193.It Cm AllowUsers
194This keyword can be followed by a number of user names, separated
195by spaces. If specified, login is allowed only for users names that
196match one of the patterns.
197.Ql \&*
198and
199.Ql ?
200can be used as
201wildcards in the patterns. Only user names are valid, a numerical user
202id isn't recognized. By default login is allowed regardless of
203the user name.
204.Pp
205.It Cm CheckMail
206Specifies whether
207.Nm
208should check for new mail for interactive logins.
209The default is
210.Dq no .
211.It Cm DenyGroups
212This keyword can be followed by a number of group names, separated
213by spaces. Users whose primary group matches one of the patterns
214aren't allowed to log in.
215.Ql \&*
216and
217.Ql ?
218can be used as
219wildcards in the patterns. Only group names are valid, a numerical group
220id isn't recognized. By default login is allowed regardless of
221the primary group.
222.Pp
223.It Cm DenyUsers
224This keyword can be followed by a number of user names, separated
225by spaces. Login is allowed disallowed for user names that match
226one of the patterns.
227.Ql \&*
228and
229.Ql ?
230can be used as
231wildcards in the patterns. Only user names are valid, a numerical user
232id isn't recognized. By default login is allowed regardless of
233the user name.
234.Pp
235.It Cm FascistLogging
236Specifies whether to use verbose logging. Verbose logging violates
237the privacy of users and is not recommended. The argument must be
238.Dq yes
239or
240.Dq no .
241The default is
242.Dq no .
243.It Cm HostKey
244Specifies the file containing the private host key (default
245.Pa /etc/ssh_host_key ) .
246Note that
247.Nm
248does not start if this file is group/world-accessible.
249.It Cm IgnoreRhosts
250Specifies that rhosts and shosts files will not be used in
251authentication.
252.Pa /etc/hosts.equiv
253and
254.Pa /etc/shosts.equiv
255are still used. The default is
256.Dq no .
257.It Cm KeepAlive
258Specifies whether the system should send keepalive messages to the
259other side. If they are sent, death of the connection or crash of one
260of the machines will be properly noticed. However, this means that
261connections will die if the route is down temporarily, and some people
262find it annoying. On the other hand, if keepalives are not send,
263sessions may hang indefinitely on the server, leaving
264.Dq ghost
265users and consuming server resources.
266.Pp
267The default is
268.Dq yes
269(to send keepalives), and the server will notice
270if the network goes down or the client host reboots. This avoids
271infinitely hanging sessions.
272.Pp
273To disable keepalives, the value should be set to
274.Dq no
275in both the server and the client configuration files.
276.It Cm KerberosAuthentication
277Specifies whether Kerberos authentication is allowed. This can
278be in the form of a Kerberos ticket, or if
279.Cm PasswordAuthentication
280is yes, the password provided by the user will be validated through
281the Kerberos KDC. Default is
282.Dq yes .
283.It Cm KerberosOrLocalPasswd
284If set then if password authentication through Kerberos fails then
285the password will be validated via any additional local mechanism
286such as
287.Pa /etc/passwd
288or SecurID. Default is
289.Dq yes .
290.It Cm KerberosTgtPassing
291Specifies whether a Kerberos TGT may be forwarded to the server.
292Default is
293.Dq no ,
294as this only works when the Kerberos KDC is actually an AFS kaserver.
295.It Cm KerberosTicketCleanup
296Specifies whether to automatically destroy the user's ticket cache
297file on logout. Default is
298.Dq yes .
299.It Cm KeyRegenerationInterval
300The server key is automatically regenerated after this many seconds
301(if it has been used). The purpose of regeneration is to prevent
302decrypting captured sessions by later breaking into the machine and
303stealing the keys. The key is never stored anywhere. If the value is
3040, the key is never regenerated. The default is 3600
305(seconds).
306.It Cm ListenAddress
307Specifies what local address
308.Nm
309should listen on.
310The default is to listen to all local addresses.
311.It Cm LoginGraceTime
312The server disconnects after this time if the user has not
313successfully logged in. If the value is 0, there is no time limit.
314The default is 600 (seconds).
315.It Cm PasswordAuthentication
316Specifies whether password authentication is allowed.
317The default is
318.Dq yes .
319.It Cm PermitEmptyPasswords
320When password authentication is allowed, it specifies whether the
321server allows login to accounts with empty password strings. The default
322is
323.Dq yes .
324.It Cm PermitRootLogin
325Specifies whether the root can log in using
326.Xr ssh 1 .
327The argument must be
328.Dq yes ,
329.Dq without-password
330or
331.Dq no .
332The default is
333.Dq yes .
334If this options is set to
335.Dq without-password
336only password authentication is disabled for root.
337.Pp
338Root login with RSA authentication when the
339.Ar command
340option has been
341specified will be allowed regardless of the value of this setting
342(which may be useful for taking remote backups even if root login is
343normally not allowed).
344.It Cm Port
345Specifies the port number that
346.Nm
347listens on. The default is 22.
348.It Cm PrintMotd
349Specifies whether
350.Nm
351should print
352.Pa /etc/motd
353when a user logs in interactively. (On some systems it is also
354printed by the shell,
355.Pa /etc/profile ,
356or equivalent.) The default is
357.Dq yes .
358.It Cm QuietMode
359Specifies whether the system runs in quiet mode. In quiet mode,
360nothing is logged in the system log, except fatal errors. The default
361is
362.Dq no .
363.It Cm RandomSeed
364Obsolete. Random number generation uses other techniques.
365.It Cm RhostsAuthentication
366Specifies whether authentication using rhosts or /etc/hosts.equiv
367files is sufficient. Normally, this method should not be permitted
368because it is insecure.
369.Cm RhostsRSAAuthentication
370should be used
371instead, because it performs RSA-based host authentication in addition
372to normal rhosts or /etc/hosts.equiv authentication.
373The default is
374.Dq no .
375.It Cm RhostsRSAAuthentication
376Specifies whether rhosts or /etc/hosts.equiv authentication together
377with successful RSA host authentication is allowed. The default is
378.Dq yes .
379.It Cm RSAAuthentication
380Specifies whether pure RSA authentication is allowed. The default is
381.Dq yes .
382.It Cm ServerKeyBits
383Defines the number of bits in the server key. The minimum value is
384512, and the default is 768.
385.It Cm SkeyAuthentication
386Specifies whether
387.Xr skey 1
388authentication is allowed. The default is
389.Dq yes .
390Note that s/key authentication is enabled only if
391.Cm PasswordAuthentication
392is allowed, too.
393.It Cm StrictModes
394Specifies whether
395.Nm
396should check file modes and ownership of the
397user's files and home directory before accepting login. This
398is normally desirable because novices sometimes accidentally leave their
399directory or files world-writable. The default is
400.Dq yes .
401.It Cm SyslogFacility
402Gives the facility code that is used when logging messages from
403.Nm sshd .
404The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
405LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The default is AUTH.
406.It Cm UseLogin
407Specifies whether
408.Xr login 1
409is used. The default is
410.Dq no .
411.It Cm X11Forwarding
412Specifies whether X11 forwarding is permitted. The default is
413.Dq yes .
414Note that disabling X11 forwarding does not improve security in any
415way, as users can always install their own forwarders.
416.It Cm X11DisplayOffset
417Specifies the first display number available for
418.Nm sshd Ns 's
419X11 forwarding. This prevents
420.Nm
421from interfering with real X11 servers.
422.El
423.Sh LOGIN PROCESS
424When a user successfully logs in,
425.Nm
426does the following:
427.Bl -enum -offset indent
428.It
429If the login is on a tty, and no command has been specified,
430prints last login time and
431.Pa /etc/motd
432(unless prevented in the configuration file or by
433.Pa $HOME/.hushlogin ;
434see the
435.Sx FILES
436section).
437.It
438If the login is on a tty, records login time.
439.It
440Checks
441.Pa /etc/nologin ;
442if it exists, prints contents and quits
443(unless root).
444.It
445Changes to run with normal user privileges.
446.It
447Sets up basic environment.
448.It
449Reads
450.Pa $HOME/.ssh/environment
451if it exists.
452.It
453Changes to user's home directory.
454.It
455If
456.Pa $HOME/.ssh/rc
457exists, runs it; else if
458.Pa /etc/sshrc
459exists, runs
460it; otherwise runs xauth. The
461.Dq rc
462files are given the X11
463authentication protocol and cookie in standard input.
464.It
465Runs user's shell or command.
466.El
467.Sh AUTHORIZED_KEYS FILE FORMAT
468The
469.Pa $HOME/.ssh/authorized_keys
470file lists the RSA keys that are
471permitted for RSA authentication. Each line of the file contains one
472key (empty lines and lines starting with a
473.Ql #
474are ignored as
475comments). Each line consists of the following fields, separated by
476spaces: options, bits, exponent, modulus, comment. The options field
477is optional; its presence is determined by whether the line starts
478with a number or not (the option field never starts with a number).
479The bits, exponent, modulus and comment fields give the RSA key; the
480comment field is not used for anything (but may be convenient for the
481user to identify the key).
482.Pp
483Note that lines in this file are usually several hundred bytes long
484(because of the size of the RSA key modulus). You don't want to type
485them in; instead, copy the
486.Pa identity.pub
487file and edit it.
488.Pp
489The options (if present) consists of comma-separated option
490specifications. No spaces are permitted, except within double quotes.
491The following option specifications are supported:
492.Bl -tag -width Ds
493.It Cm from="pattern-list"
494Specifies that in addition to RSA authentication, the canonical name
495of the remote host must be present in the comma-separated list of
496patterns ('*' and '?' serve as wildcards). The list may also contain
497patterns negated by prefixing them with '!'; if the canonical host
498name matches a negated pattern, the key is not accepted. The purpose
499of this option is to optionally increase security: RSA authentication
500by itself does not trust the network or name servers or anything (but
501the key); however, if somebody somehow steals the key, the key
502permits an intruder to log in from anywhere in the world. This
503additional option makes using a stolen key more difficult (name
504servers and/or routers would have to be compromised in addition to
505just the key).
506.It Cm command="command"
507Specifies that the command is executed whenever this key is used for
508authentication. The command supplied by the user (if any) is ignored.
509The command is run on a pty if the connection requests a pty;
510otherwise it is run without a tty. A quote may be included in the
511command by quoting it with a backslash. This option might be useful
512to restrict certain RSA keys to perform just a specific operation. An
513example might be a key that permits remote backups but nothing
514else. Notice that the client may specify TCP/IP and/or X11
515forwardings unless they are explicitly prohibited.
516.It Cm environment="NAME=value"
517Specifies that the string is to be added to the environment when
518logging in using this key. Environment variables set this way
519override other default environment values. Multiple options of this
520type are permitted.
521.It Cm no-port-forwarding
522Forbids TCP/IP forwarding when this key is used for authentication.
523Any port forward requests by the client will return an error. This
524might be used, e.g., in connection with the
525.Cm command
526option.
527.It Cm no-X11-forwarding
528Forbids X11 forwarding when this key is used for authentication.
529Any X11 forward requests by the client will return an error.
530.It Cm no-agent-forwarding
531Forbids authentication agent forwarding when this key is used for
532authentication.
533.It Cm no-pty
534Prevents tty allocation (a request to allocate a pty will fail).
535.El
536.Ss Examples
5371024 33 12121.\|.\|.\|312314325 ylo@foo.bar
538.Pp
539from="*.niksula.hut.fi,!pc.niksula.hut.fi" 1024 35 23.\|.\|.\|2334 ylo@niksula
540.Pp
541command="dump /home",no-pty,no-port-forwarding 1024 33 23.\|.\|.\|2323 backup.hut.fi
542.Sh SSH_KNOWN_HOSTS FILE FORMAT
543The
544.Pa /etc/ssh_known_hosts
545and
546.Pa $HOME/.ssh/known_hosts
547files contain host public keys for all known hosts. The global file should
548be prepared by the admistrator (optional), and the per-user file is
549maintained automatically: whenever the user connects an unknown host
550its key is added to the per-user file.
551.Pp
552Each line in these files contains the following fields: hostnames,
553bits, exponent, modulus, comment. The fields are separated by spaces.
554.Pp
555Hostnames is a comma-separated list of patterns ('*' and '?' act as
556wildcards); each pattern in turn is matched against the canonical host
557name (when authenticating a client) or against the user-supplied
558name (when authenticating a server). A pattern may also be preceded
559by
560.Ql !
561to indicate negation: if the host name matches a negated
562pattern, it is not accepted (by that line) even if it matched another
563pattern on the line.
564.Pp
565Bits, exponent, and modulus are taken directly from the host key; they
566can be obtained, e.g., from
567.Pa /etc/ssh_host_key.pub .
568The optional comment field continues to the end of the line, and is not used.
569.Pp
570Lines starting with
571.Ql #
572and empty lines are ignored as comments.
573.Pp
574When performing host authentication, authentication is accepted if any
575matching line has the proper key. It is thus permissible (but not
576recommended) to have several lines or different host keys for the same
577names. This will inevitably happen when short forms of host names
578from different domains are put in the file. It is possible
579that the files contain conflicting information; authentication is
580accepted if valid information can be found from either file.
581.Pp
582Note that the lines in these files are typically hundreds of characters
583long, and you definitely don't want to type in the host keys by hand.
584Rather, generate them by a script
585or by taking
586.Pa /etc/ssh_host_key.pub
587and adding the host names at the front.
588.Ss Examples
589closenet,closenet.hut.fi,.\|.\|.\|,130.233.208.41 1024 37 159.\|.\|.93 closenet.hut.fi
590.Sh FILES
591.Bl -tag -width Ds
592.It Pa /etc/sshd_config
593Contains configuration data for
594.Nm sshd .
595This file should be writable by root only, but it is recommended
596(though not necessary) that it be world-readable.
597.It Pa /etc/ssh_host_key
598Contains the private part of the host key.
599This file should only be owned by root, readable only by root, and not
600accessible to others.
601Note that
602.Nm
603does not start if this file is group/world-accessible.
604.It Pa /etc/ssh_host_key.pub
605Contains the public part of the host key.
606This file should be world-readable but writable only by
607root. Its contents should match the private part. This file is not
608really used for anything; it is only provided for the convenience of
609the user so its contents can be copied to known hosts files.
610These two files are created using
611.Xr ssh-keygen 1 .
612.It Pa /var/run/sshd.pid
613Contains the process ID of the
614.Nm
615listening for connections (if there are several daemons running
616concurrently for different ports, this contains the pid of the one
617started last). The contents of this file are not sensitive; it can be
618world-readable.
619.It Pa $HOME/.ssh/authorized_keys
620Lists the RSA keys that can be used to log into the user's account.
621This file must be readable by root (which may on some machines imply
622it being world-readable if the user's home directory resides on an NFS
623volume). It is recommended that it not be accessible by others. The
624format of this file is described above.
625.It Pa /etc/ssh_known_hosts
626This file is consulted when using rhosts with RSA host
627authentication to check the public key of the host. The key must be
628listed in this file to be accepted.
629.It Pa $HOME/.ssh/known_hosts
630The client uses this file
631and
632.Pa /etc/ssh_known_hosts
633to verify that the remote host is the one we intended to
634connect. These files should be writable only by root/the owner.
635.Pa /etc/ssh_known_hosts
636should be world-readable, and
637.Pa $HOME/.ssh/known_hosts
638can but need not be world-readable.
639.It Pa /etc/nologin
640If this file exists,
641.Nm
642refuses to let anyone except root log in. The contents of the file
643are displayed to anyone trying to log in, and non-root connections are
644refused. The file should be world-readable.
645.It Pa /etc/hosts.allow, /etc/hosts.deny
646If compiled with
647.Sy LIBWRAP
648support, tcp-wrappers access controls may be defined here as described in
649.Xr hosts_access 5 .
650.It Pa $HOME/.rhosts
651This file contains host-username pairs, separated by a space, one per
652line. The given user on the corresponding host is permitted to log in
653without password. The same file is used by rlogind and rshd.
654The file must
655be writable only by the user; it is recommended that it not be
656accessible by others.
657.Pp
658If is also possible to use netgroups in the file. Either host or user
659name may be of the form +@groupname to specify all hosts or all users
660in the group.
661.It Pa $HOME/.shosts
662For ssh,
663this file is exactly the same as for
664.Pa .rhosts .
665However, this file is
666not used by rlogin and rshd, so using this permits access using SSH only.
667.Pa /etc/hosts.equiv
668This file is used during
669.Pa .rhosts
670authentication. In the
671simplest form, this file contains host names, one per line. Users on
672those hosts are permitted to log in without a password, provided they
673have the same user name on both machines. The host name may also be
674followed by a user name; such users are permitted to log in as
675.Em any
676user on this machine (except root). Additionally, the syntax
677.Dq +@group
678can be used to specify netgroups. Negated entries start with
679.Ql \&- .
680.Pp
681If the client host/user is successfully matched in this file, login is
682automatically permitted provided the client and server user names are the
683same. Additionally, successful RSA host authentication is normally
684required. This file must be writable only by root; it is recommended
685that it be world-readable.
686.Pp
687.Sy "Warning: It is almost never a good idea to use user names in"
688.Pa hosts.equiv .
689Beware that it really means that the named user(s) can log in as
690.Em anybody ,
691which includes bin, daemon, adm, and other accounts that own critical
692binaries and directories. Using a user name practically grants the
693user root access. The only valid use for user names that I can think
694of is in negative entries.
695.Pp
696Note that this warning also applies to rsh/rlogin.
697.It Pa /etc/shosts.equiv
698This is processed exactly as
699.Pa /etc/hosts.equiv .
700However, this file may be useful in environments that want to run both
701rsh/rlogin and ssh.
702.It Pa $HOME/.ssh/environment
703This file is read into the environment at login (if it exists). It
704can only contain empty lines, comment lines (that start with
705.Ql # ) ,
706and assignment lines of the form name=value. The file should be writable
707only by the user; it need not be readable by anyone else.
708.It Pa $HOME/.ssh/rc
709If this file exists, it is run with /bin/sh after reading the
710environment files but before starting the user's shell or command. If
711X11 spoofing is in use, this will receive the "proto cookie" pair in
712standard input (and
713.Ev DISPLAY
714in environment). This must call
715.Xr xauth 1
716in that case.
717.Pp
718The primary purpose of this file is to run any initialization routines
719which may be needed before the user's home directory becomes
720accessible; AFS is a particular example of such an environment.
721.Pp
722This file will probably contain some initialization code followed by
723something similar to: "if read proto cookie; then echo add $DISPLAY
724$proto $cookie | xauth -q -; fi".
725.Pp
726If this file does not exist,
727.Pa /etc/sshrc
728is run, and if that
729does not exist either, xauth is used to store the cookie.
730.Pp
731This file should be writable only by the user, and need not be
732readable by anyone else.
733.It Pa /etc/sshrc
734Like
735.Pa $HOME/.ssh/rc .
736This can be used to specify
737machine-specific login-time initializations globally. This file
738should be writable only by root, and should be world-readable.
739.Sh AUTHOR
740Tatu Ylonen <ylo@cs.hut.fi>
741.Pp
742Information about new releases, mailing lists, and other related
743issues can be found from the SSH WWW home page:
744.Pp
745.Dl http://www.cs.hut.fi/ssh.
746.Pp
747OpenSSH
748is a derivative of the original (free) ssh 1.2.12 release, but with bugs
749removed and newer features re-added. Rapidly after the 1.2.12 release,
750newer versions bore successively more restrictive licenses. This version
751of OpenSSH
752.Bl -bullet
753.It
754has all components of a restrictive nature (ie. patents, see
755.Xr ssl 8 )
756directly removed from the source code; any licensed or patented components
757are chosen from
758external libraries.
759.It
760has been updated to support ssh protocol 1.5.
761.It
762contains added support for
763.Xr kerberos 8
764authentication and ticket passing.
765.It
766supports one-time password authentication with
767.Xr skey 1 .
768.El
769.Pp
770The libraries described in
771.Xr ssl 8
772are required for proper operation.
773.Sh SEE ALSO
774.Xr rlogin 1 ,
775.Xr rsh 1 ,
776.Xr scp 1 ,
777.Xr ssh 1 ,
778.Xr ssh-add 1 ,
779.Xr ssh-agent 1 ,
780.Xr ssh-keygen 1 ,
781.Xr ssl 8
diff --git a/sshd.c b/sshd.c
new file mode 100644
index 000000000..059f31195
--- /dev/null
+++ b/sshd.c
@@ -0,0 +1,2445 @@
1/*
2
3sshd.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Fri Mar 17 17:09:28 1995 ylo
11
12This program is the ssh daemon. It listens for connections from clients, and
13performs authentication, executes use commands or shell, and forwards
14information to/from the application to the user client over an encrypted
15connection. This can also handle forwarding of X11, TCP/IP, and authentication
16agent connections.
17
18*/
19
20#include "includes.h"
21RCSID("$Id: sshd.c,v 1.1 1999/10/27 03:42:46 damien Exp $");
22
23#include "xmalloc.h"
24#include "rsa.h"
25#include "ssh.h"
26#include "pty.h"
27#include "packet.h"
28#include "buffer.h"
29#include "cipher.h"
30#include "mpaux.h"
31#include "servconf.h"
32#include "uidswap.h"
33#include "compat.h"
34
35#ifdef LIBWRAP
36#include <tcpd.h>
37#include <syslog.h>
38int allow_severity = LOG_INFO;
39int deny_severity = LOG_WARNING;
40#endif /* LIBWRAP */
41
42#ifndef O_NOCTTY
43#define O_NOCTTY 0
44#endif
45
46#ifdef KRB4
47char *ticket = NULL;
48#endif /* KRB4 */
49
50#ifdef HAVE_PAM
51#include <security/pam_appl.h>
52struct pam_handle_t *pamh=NULL;
53char *pampasswd=NULL;
54int retval;
55int origretval;
56#endif /* HAVE_PAM */
57
58/* Local Xauthority file. */
59char *xauthfile = NULL;
60
61/* Server configuration options. */
62ServerOptions options;
63
64/* Name of the server configuration file. */
65char *config_file_name = SERVER_CONFIG_FILE;
66
67/* Debug mode flag. This can be set on the command line. If debug
68 mode is enabled, extra debugging output will be sent to the system
69 log, the daemon will not go to background, and will exit after processing
70 the first connection. */
71int debug_flag = 0;
72
73/* Flag indicating that the daemon is being started from inetd. */
74int inetd_flag = 0;
75
76/* argv[0] without path. */
77char *av0;
78
79/* Saved arguments to main(). */
80char **saved_argv;
81
82/* This is set to the socket that the server is listening; this is used in
83 the SIGHUP signal handler. */
84int listen_sock;
85
86/* Flags set in auth-rsa from authorized_keys flags. These are set in
87 auth-rsa.c. */
88int no_port_forwarding_flag = 0;
89int no_agent_forwarding_flag = 0;
90int no_x11_forwarding_flag = 0;
91int no_pty_flag = 0;
92char *forced_command = NULL; /* RSA authentication "command=" option. */
93struct envstring *custom_environment = NULL;
94 /* RSA authentication "environment=" options. */
95
96/* Session id for the current session. */
97unsigned char session_id[16];
98
99/* Any really sensitive data in the application is contained in this structure.
100 The idea is that this structure could be locked into memory so that the
101 pages do not get written into swap. However, there are some problems.
102 The private key contains BIGNUMs, and we do not (in principle) have
103 access to the internals of them, and locking just the structure is not
104 very useful. Currently, memory locking is not implemented. */
105struct
106{
107 /* Private part of server key. */
108 RSA *private_key;
109
110 /* Private part of host key. */
111 RSA *host_key;
112} sensitive_data;
113
114/* Flag indicating whether the current session key has been used. This flag
115 is set whenever the key is used, and cleared when the key is regenerated. */
116int key_used = 0;
117
118/* This is set to true when SIGHUP is received. */
119int received_sighup = 0;
120
121/* Public side of the server key. This value is regenerated regularly with
122 the private key. */
123RSA *public_key;
124
125/* Prototypes for various functions defined later in this file. */
126void do_connection(int privileged_port);
127void do_authentication(char *user, int privileged_port);
128void do_authenticated(struct passwd *pw);
129void do_exec_pty(const char *command, int ptyfd, int ttyfd,
130 const char *ttyname, struct passwd *pw, const char *term,
131 const char *display, const char *auth_proto,
132 const char *auth_data);
133void do_exec_no_pty(const char *command, struct passwd *pw,
134 const char *display, const char *auth_proto,
135 const char *auth_data);
136void do_child(const char *command, struct passwd *pw, const char *term,
137 const char *display, const char *auth_proto,
138 const char *auth_data, const char *ttyname);
139#ifdef HAVE_PAM
140static int pamconv(int num_msg, const struct pam_message **msg,
141 struct pam_response **resp, void *appdata_ptr);
142
143static struct pam_conv conv = {
144 pamconv,
145 NULL
146};
147
148static int pamconv(int num_msg, const struct pam_message **msg,
149 struct pam_response **resp, void *appdata_ptr)
150{
151 int count = 0;
152 int replies = 0;
153 struct pam_response *reply = NULL;
154 int size = sizeof(struct pam_response);
155
156 for(count = 0; count < num_msg; count++)
157 {
158 switch (msg[count]->msg_style)
159 {
160 case PAM_PROMPT_ECHO_ON:
161 case PAM_PROMPT_ECHO_OFF:
162 if (reply == NULL)
163 reply = xmalloc(size);
164 else
165 reply = realloc(reply, size);
166
167 if (reply == NULL)
168 return PAM_CONV_ERR;
169
170 size += sizeof(struct pam_response);
171
172 reply[replies].resp_retcode = PAM_SUCCESS;
173
174 reply[replies++].resp = xstrdup(pampasswd);
175 /* PAM frees resp */
176 break;
177
178 case PAM_TEXT_INFO:
179 /* ignore it... */
180 break;
181
182 case PAM_ERROR_MSG:
183 default:
184 /* Must be an error of some sort... */
185 if (reply != NULL)
186 free(reply);
187
188 return PAM_CONV_ERR;
189 }
190 }
191
192 if (reply != NULL)
193 *resp = reply;
194
195 return PAM_SUCCESS;
196}
197
198void pam_cleanup_proc(void *context)
199{
200 if (retval == PAM_SUCCESS)
201 retval = pam_close_session((pam_handle_t *)pamh, 0);
202
203 if (pam_end((pam_handle_t *)pamh, retval) != PAM_SUCCESS)
204 log("Cannot release PAM authentication.");
205}
206#endif /* HAVE_PAM */
207
208/* Signal handler for SIGHUP. Sshd execs itself when it receives SIGHUP;
209 the effect is to reread the configuration file (and to regenerate
210 the server key). */
211
212void sighup_handler(int sig)
213{
214 received_sighup = 1;
215 signal(SIGHUP, sighup_handler);
216}
217
218/* Called from the main program after receiving SIGHUP. Restarts the
219 server. */
220
221void sighup_restart()
222{
223 log("Received SIGHUP; restarting.");
224 close(listen_sock);
225 execv(saved_argv[0], saved_argv);
226 log("RESTART FAILED: av0='%s', error: %s.", av0, strerror(errno));
227 exit(1);
228}
229
230/* Generic signal handler for terminating signals in the master daemon.
231 These close the listen socket; not closing it seems to cause "Address
232 already in use" problems on some machines, which is inconvenient. */
233
234void sigterm_handler(int sig)
235{
236 log("Received signal %d; terminating.", sig);
237 close(listen_sock);
238 exit(255);
239}
240
241/* SIGCHLD handler. This is called whenever a child dies. This will then
242 reap any zombies left by exited c. */
243
244void main_sigchld_handler(int sig)
245{
246 int save_errno = errno;
247 int status;
248 wait(&status);
249 signal(SIGCHLD, main_sigchld_handler);
250 errno = save_errno;
251}
252
253/* Signal handler for the alarm after the login grace period has expired. */
254
255void grace_alarm_handler(int sig)
256{
257 /* Close the connection. */
258 packet_close();
259
260 /* Log error and exit. */
261 fatal("Timeout before authentication.");
262}
263
264/* Signal handler for the key regeneration alarm. Note that this
265 alarm only occurs in the daemon waiting for connections, and it does not
266 do anything with the private key or random state before forking. Thus there
267 should be no concurrency control/asynchronous execution problems. */
268
269void key_regeneration_alarm(int sig)
270{
271 int save_errno = errno;
272
273 /* Check if we should generate a new key. */
274 if (key_used)
275 {
276 /* This should really be done in the background. */
277 log("Generating new %d bit RSA key.", options.server_key_bits);
278
279 if (sensitive_data.private_key != NULL)
280 RSA_free(sensitive_data.private_key);
281 sensitive_data.private_key = RSA_new();
282
283 if (public_key != NULL)
284 RSA_free(public_key);
285 public_key = RSA_new();
286
287 rsa_generate_key(sensitive_data.private_key, public_key,
288 options.server_key_bits);
289 arc4random_stir();
290 key_used = 0;
291 log("RSA key generation complete.");
292 }
293
294 /* Reschedule the alarm. */
295 signal(SIGALRM, key_regeneration_alarm);
296 alarm(options.key_regeneration_time);
297 errno = save_errno;
298}
299
300/* Main program for the daemon. */
301
302int
303main(int ac, char **av)
304{
305 extern char *optarg;
306 extern int optind;
307 int opt, aux, sock_in, sock_out, newsock, i, pid, on = 1;
308 int remote_major, remote_minor;
309 int silentrsa = 0;
310 struct sockaddr_in sin;
311 char buf[100]; /* Must not be larger than remote_version. */
312 char remote_version[100]; /* Must be at least as big as buf. */
313 char *comment;
314 FILE *f;
315 struct linger linger;
316
317 /* Save argv[0]. */
318 saved_argv = av;
319 if (strchr(av[0], '/'))
320 av0 = strrchr(av[0], '/') + 1;
321 else
322 av0 = av[0];
323
324 /* Initialize configuration options to their default values. */
325 initialize_server_options(&options);
326
327 /* Parse command-line arguments. */
328 while ((opt = getopt(ac, av, "f:p:b:k:h:g:diqQ")) != EOF)
329 {
330 switch (opt)
331 {
332 case 'f':
333 config_file_name = optarg;
334 break;
335 case 'd':
336 debug_flag = 1;
337 break;
338 case 'i':
339 inetd_flag = 1;
340 break;
341 case 'Q':
342 silentrsa = 1;
343 break;
344 case 'q':
345 options.quiet_mode = 1;
346 break;
347 case 'b':
348 options.server_key_bits = atoi(optarg);
349 break;
350 case 'p':
351 options.port = atoi(optarg);
352 break;
353 case 'g':
354 options.login_grace_time = atoi(optarg);
355 break;
356 case 'k':
357 options.key_regeneration_time = atoi(optarg);
358 break;
359 case 'h':
360 options.host_key_file = optarg;
361 break;
362 case '?':
363 default:
364 fprintf(stderr, "sshd version %s\n", SSH_VERSION);
365 fprintf(stderr, "Usage: %s [options]\n", av0);
366 fprintf(stderr, "Options:\n");
367 fprintf(stderr, " -f file Configuration file (default %s/sshd_config)\n", ETCDIR);
368 fprintf(stderr, " -d Debugging mode\n");
369 fprintf(stderr, " -i Started from inetd\n");
370 fprintf(stderr, " -q Quiet (no logging)\n");
371 fprintf(stderr, " -p port Listen on the specified port (default: 22)\n");
372 fprintf(stderr, " -k seconds Regenerate server key every this many seconds (default: 3600)\n");
373 fprintf(stderr, " -g seconds Grace period for authentication (default: 300)\n");
374 fprintf(stderr, " -b bits Size of server RSA key (default: 768 bits)\n");
375 fprintf(stderr, " -h file File from which to read host key (default: %s)\n",
376 HOST_KEY_FILE);
377 exit(1);
378 }
379 }
380
381 /* check if RSA support exists */
382 if (rsa_alive() == 0) {
383 if (silentrsa == 0)
384 printf("sshd: no RSA support in libssl and libcrypto -- exiting. See ssl(8)\n");
385 log("no RSA support in libssl and libcrypto -- exiting. See ssl(8)");
386 exit(1);
387 }
388
389 /* Read server configuration options from the configuration file. */
390 read_server_config(&options, config_file_name);
391
392 /* Fill in default values for those options not explicitly set. */
393 fill_default_server_options(&options);
394
395 /* Check certain values for sanity. */
396 if (options.server_key_bits < 512 ||
397 options.server_key_bits > 32768)
398 {
399 fprintf(stderr, "Bad server key size.\n");
400 exit(1);
401 }
402 if (options.port < 1 || options.port > 65535)
403 {
404 fprintf(stderr, "Bad port number.\n");
405 exit(1);
406 }
407
408 /* Check that there are no remaining arguments. */
409 if (optind < ac)
410 {
411 fprintf(stderr, "Extra argument %s.\n", av[optind]);
412 exit(1);
413 }
414
415 /* Initialize the log (it is reinitialized below in case we forked). */
416 log_init(av0, debug_flag && !inetd_flag,
417 debug_flag || options.fascist_logging,
418 options.quiet_mode, options.log_facility);
419
420 debug("sshd version %.100s", SSH_VERSION);
421
422 sensitive_data.host_key = RSA_new();
423 /* Load the host key. It must have empty passphrase. */
424 if (!load_private_key(options.host_key_file, "",
425 sensitive_data.host_key, &comment))
426 {
427 if (debug_flag)
428 fprintf(stderr, "Could not load host key: %s: %s\n",
429 options.host_key_file, strerror(errno));
430 else
431 {
432 int err = errno;
433 log_init(av0, !inetd_flag, 1, 0, options.log_facility);
434 error("Could not load host key: %.200s: %.100s",
435 options.host_key_file, strerror(err));
436 }
437 exit(1);
438 }
439 xfree(comment);
440
441 /* If not in debugging mode, and not started from inetd, disconnect from
442 the controlling terminal, and fork. The original process exits. */
443 if (!debug_flag && !inetd_flag)
444 {
445#ifdef TIOCNOTTY
446 int fd;
447#endif /* TIOCNOTTY */
448 if (daemon(0, 0) < 0)
449 fatal("daemon() failed: %.200s", strerror(errno));
450
451 /* Disconnect from the controlling tty. */
452#ifdef TIOCNOTTY
453 fd = open("/dev/tty", O_RDWR|O_NOCTTY);
454 if (fd >= 0)
455 {
456 (void)ioctl(fd, TIOCNOTTY, NULL);
457 close(fd);
458 }
459#endif /* TIOCNOTTY */
460 }
461
462 /* Reinitialize the log (because of the fork above). */
463 log_init(av0, debug_flag && !inetd_flag,
464 debug_flag || options.fascist_logging,
465 options.quiet_mode, options.log_facility);
466
467 /* Check that server and host key lengths differ sufficiently. This is
468 necessary to make double encryption work with rsaref. Oh, I hate
469 software patents. I dont know if this can go? Niels */
470 if (options.server_key_bits >
471 BN_num_bits(sensitive_data.host_key->n) - SSH_KEY_BITS_RESERVED &&
472 options.server_key_bits <
473 BN_num_bits(sensitive_data.host_key->n) + SSH_KEY_BITS_RESERVED)
474 {
475 options.server_key_bits =
476 BN_num_bits(sensitive_data.host_key->n) + SSH_KEY_BITS_RESERVED;
477 debug("Forcing server key to %d bits to make it differ from host key.",
478 options.server_key_bits);
479 }
480
481 /* Do not display messages to stdout in RSA code. */
482 rsa_set_verbose(0);
483
484 /* Initialize the random number generator. */
485 arc4random_stir();
486
487 /* Chdir to the root directory so that the current disk can be unmounted
488 if desired. */
489 chdir("/");
490
491 /* Close connection cleanly after attack. */
492 cipher_attack_detected = packet_disconnect;
493
494 /* Start listening for a socket, unless started from inetd. */
495 if (inetd_flag)
496 {
497 int s1, s2;
498 s1 = dup(0); /* Make sure descriptors 0, 1, and 2 are in use. */
499 s2 = dup(s1);
500 sock_in = dup(0);
501 sock_out = dup(1);
502 /* We intentionally do not close the descriptors 0, 1, and 2 as our
503 code for setting the descriptors won\'t work if ttyfd happens to
504 be one of those. */
505 debug("inetd sockets after dupping: %d, %d", sock_in, sock_out);
506
507 public_key = RSA_new();
508 sensitive_data.private_key = RSA_new();
509 /* Generate an rsa key. */
510 log("Generating %d bit RSA key.", options.server_key_bits);
511 rsa_generate_key(sensitive_data.private_key, public_key,
512 options.server_key_bits);
513 arc4random_stir();
514 log("RSA key generation complete.");
515 }
516 else
517 {
518 /* Create socket for listening. */
519 listen_sock = socket(AF_INET, SOCK_STREAM, 0);
520 if (listen_sock < 0)
521 fatal("socket: %.100s", strerror(errno));
522
523 /* Set socket options. We try to make the port reusable and have it
524 close as fast as possible without waiting in unnecessary wait states
525 on close. */
526 setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
527 sizeof(on));
528 linger.l_onoff = 1;
529 linger.l_linger = 5;
530 setsockopt(listen_sock, SOL_SOCKET, SO_LINGER, (void *)&linger,
531 sizeof(linger));
532
533 /* Initialize the socket address. */
534 memset(&sin, 0, sizeof(sin));
535 sin.sin_family = AF_INET;
536 sin.sin_addr = options.listen_addr;
537 sin.sin_port = htons(options.port);
538
539 /* Bind the socket to the desired port. */
540 if (bind(listen_sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
541 {
542 error("bind: %.100s", strerror(errno));
543 shutdown(listen_sock, SHUT_RDWR);
544 close(listen_sock);
545 fatal("Bind to port %d failed.", options.port);
546 }
547
548 if (!debug_flag)
549 {
550 /* Record our pid in /etc/sshd_pid to make it easier to kill the
551 correct sshd. We don\'t want to do this before the bind above
552 because the bind will fail if there already is a daemon, and this
553 will overwrite any old pid in the file. */
554 f = fopen(SSH_DAEMON_PID_FILE, "w");
555 if (f)
556 {
557 fprintf(f, "%u\n", (unsigned int)getpid());
558 fclose(f);
559 }
560 }
561
562 /* Start listening on the port. */
563 log("Server listening on port %d.", options.port);
564 if (listen(listen_sock, 5) < 0)
565 fatal("listen: %.100s", strerror(errno));
566
567 public_key = RSA_new();
568 sensitive_data.private_key = RSA_new();
569 /* Generate an rsa key. */
570 log("Generating %d bit RSA key.", options.server_key_bits);
571 rsa_generate_key(sensitive_data.private_key, public_key,
572 options.server_key_bits);
573 arc4random_stir();
574 log("RSA key generation complete.");
575
576 /* Schedule server key regeneration alarm. */
577 signal(SIGALRM, key_regeneration_alarm);
578 alarm(options.key_regeneration_time);
579
580 /* Arrange to restart on SIGHUP. The handler needs listen_sock. */
581 signal(SIGHUP, sighup_handler);
582 signal(SIGTERM, sigterm_handler);
583 signal(SIGQUIT, sigterm_handler);
584
585 /* Arrange SIGCHLD to be caught. */
586 signal(SIGCHLD, main_sigchld_handler);
587
588 /* Stay listening for connections until the system crashes or the
589 daemon is killed with a signal. */
590 for (;;)
591 {
592 if (received_sighup)
593 sighup_restart();
594 /* Wait in accept until there is a connection. */
595 aux = sizeof(sin);
596 newsock = accept(listen_sock, (struct sockaddr *)&sin, &aux);
597 if (received_sighup)
598 sighup_restart();
599 if (newsock < 0)
600 {
601 if (errno == EINTR)
602 continue;
603 error("accept: %.100s", strerror(errno));
604 continue;
605 }
606
607 /* Got connection. Fork a child to handle it, unless we are in
608 debugging mode. */
609 if (debug_flag)
610 {
611 /* In debugging mode. Close the listening socket, and start
612 processing the connection without forking. */
613 debug("Server will not fork when running in debugging mode.");
614 close(listen_sock);
615 sock_in = newsock;
616 sock_out = newsock;
617 pid = getpid();
618 break;
619 }
620 else
621 {
622 /* Normal production daemon. Fork, and have the child process
623 the connection. The parent continues listening. */
624 if ((pid = fork()) == 0)
625 {
626 /* Child. Close the listening socket, and start using
627 the accepted socket. Reinitialize logging (since our
628 pid has changed). We break out of the loop to handle
629 the connection. */
630 close(listen_sock);
631 sock_in = newsock;
632 sock_out = newsock;
633 log_init(av0, debug_flag && !inetd_flag,
634 options.fascist_logging || debug_flag,
635 options.quiet_mode, options.log_facility);
636 break;
637 }
638 }
639
640 /* Parent. Stay in the loop. */
641 if (pid < 0)
642 error("fork: %.100s", strerror(errno));
643 else
644 debug("Forked child %d.", pid);
645
646 /* Mark that the key has been used (it was "given" to the child). */
647 key_used = 1;
648
649 arc4random_stir();
650
651 /* Close the new socket (the child is now taking care of it). */
652 close(newsock);
653 }
654 }
655
656 /* This is the child processing a new connection. */
657
658 /* Disable the key regeneration alarm. We will not regenerate the key
659 since we are no longer in a position to give it to anyone. We will
660 not restart on SIGHUP since it no longer makes sense. */
661 alarm(0);
662 signal(SIGALRM, SIG_DFL);
663 signal(SIGHUP, SIG_DFL);
664 signal(SIGTERM, SIG_DFL);
665 signal(SIGQUIT, SIG_DFL);
666 signal(SIGCHLD, SIG_DFL);
667
668 /* Set socket options for the connection. We want the socket to close
669 as fast as possible without waiting for anything. If the connection
670 is not a socket, these will do nothing. */
671 /* setsockopt(sock_in, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */
672 linger.l_onoff = 1;
673 linger.l_linger = 5;
674 setsockopt(sock_in, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger));
675
676 /* Register our connection. This turns encryption off because we do not
677 have a key. */
678 packet_set_connection(sock_in, sock_out);
679
680 /* Check whether logins are denied from this host. */
681#ifdef LIBWRAP
682 {
683 struct request_info req;
684
685 request_init(&req, RQ_DAEMON, av0, RQ_FILE, sock_in, NULL);
686 fromhost(&req);
687
688 if (!hosts_access(&req)) {
689 close(sock_in);
690 close(sock_out);
691 refuse(&req);
692 }
693 log("Connection from %.500s port %d",
694 eval_client(&req), get_remote_port());
695 }
696#else
697 /* Log the connection. */
698 log("Connection from %.100s port %d",
699 get_remote_ipaddr(), get_remote_port());
700#endif /* LIBWRAP */
701
702 /* We don\'t want to listen forever unless the other side successfully
703 authenticates itself. So we set up an alarm which is cleared after
704 successful authentication. A limit of zero indicates no limit.
705 Note that we don\'t set the alarm in debugging mode; it is just annoying
706 to have the server exit just when you are about to discover the bug. */
707 signal(SIGALRM, grace_alarm_handler);
708 if (!debug_flag)
709 alarm(options.login_grace_time);
710
711 /* Send our protocol version identification. */
712 snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
713 PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION);
714 if (write(sock_out, buf, strlen(buf)) != strlen(buf))
715 fatal("Could not write ident string.");
716
717 /* Read other side\'s version identification. */
718 for (i = 0; i < sizeof(buf) - 1; i++)
719 {
720 if (read(sock_in, &buf[i], 1) != 1)
721 fatal("Did not receive ident string.");
722 if (buf[i] == '\r')
723 {
724 buf[i] = '\n';
725 buf[i + 1] = 0;
726 break;
727 }
728 if (buf[i] == '\n')
729 {
730 /* buf[i] == '\n' */
731 buf[i + 1] = 0;
732 break;
733 }
734 }
735 buf[sizeof(buf) - 1] = 0;
736
737 /* Check that the versions match. In future this might accept several
738 versions and set appropriate flags to handle them. */
739 if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor,
740 remote_version) != 3)
741 {
742 const char *s = "Protocol mismatch.\n";
743 (void) write(sock_out, s, strlen(s));
744 close(sock_in);
745 close(sock_out);
746 fatal("Bad protocol version identification: %.100s", buf);
747 }
748 debug("Client protocol version %d.%d; client software version %.100s",
749 remote_major, remote_minor, remote_version);
750 if (remote_major != PROTOCOL_MAJOR)
751 {
752 const char *s = "Protocol major versions differ.\n";
753 (void) write(sock_out, s, strlen(s));
754 close(sock_in);
755 close(sock_out);
756 fatal("Protocol major versions differ: %d vs. %d",
757 PROTOCOL_MAJOR, remote_major);
758 }
759
760 /* Check that the client has sufficiently high software version. */
761 if (remote_major == 1 && remote_minor < 3)
762 packet_disconnect("Your ssh version is too old and is no longer supported. Please install a newer version.");
763
764 if (remote_major == 1 && remote_minor == 3) {
765 enable_compat13();
766 if (strcmp(remote_version, "OpenSSH-1.1") != 0) {
767 debug("Agent forwarding disabled, remote version is not compatible.");
768 no_agent_forwarding_flag = 1;
769 }
770 }
771
772 packet_set_nonblocking();
773
774 /* Handle the connection. We pass as argument whether the connection
775 came from a privileged port. */
776 do_connection(get_remote_port() < IPPORT_RESERVED);
777
778#ifdef KRB4
779 /* Cleanup user's ticket cache file. */
780 if (options.kerberos_ticket_cleanup)
781 (void) dest_tkt();
782#endif /* KRB4 */
783
784 /* Cleanup user's local Xauthority file. */
785 if (xauthfile) unlink(xauthfile);
786
787 /* The connection has been terminated. */
788 log("Closing connection to %.100s", inet_ntoa(sin.sin_addr));
789
790#ifdef HAVE_PAM
791 if (retval == PAM_SUCCESS)
792 retval = pam_close_session((pam_handle_t *)pamh, 0);
793
794 if (pam_end((pam_handle_t *)pamh, retval) != PAM_SUCCESS)
795 log("Cannot release PAM authentication.");
796
797 fatal_remove_cleanup(&pam_cleanup_proc, NULL);
798#endif /* HAVE_PAM */
799
800 packet_close();
801
802 exit(0);
803}
804
805/* Process an incoming connection. Protocol version identifiers have already
806 been exchanged. This sends server key and performs the key exchange.
807 Server and host keys will no longer be needed after this functions. */
808
809void do_connection(int privileged_port)
810{
811 int i;
812 BIGNUM *session_key_int;
813 unsigned char session_key[SSH_SESSION_KEY_LENGTH];
814 unsigned char check_bytes[8];
815 char *user;
816 unsigned int cipher_type, auth_mask, protocol_flags;
817 int plen, slen;
818 u_int32_t rand = 0;
819
820 /* Generate check bytes that the client must send back in the user packet
821 in order for it to be accepted; this is used to defy ip spoofing
822 attacks. Note that this only works against somebody doing IP spoofing
823 from a remote machine; any machine on the local network can still see
824 outgoing packets and catch the random cookie. This only affects
825 rhosts authentication, and this is one of the reasons why it is
826 inherently insecure. */
827 for (i = 0; i < 8; i++) {
828 if (i % 4 == 0)
829 rand = arc4random();
830 check_bytes[i] = rand & 0xff;
831 rand >>= 8;
832 }
833
834 /* Send our public key. We include in the packet 64 bits of random
835 data that must be matched in the reply in order to prevent IP spoofing. */
836 packet_start(SSH_SMSG_PUBLIC_KEY);
837 for (i = 0; i < 8; i++)
838 packet_put_char(check_bytes[i]);
839
840 /* Store our public server RSA key. */
841 packet_put_int(BN_num_bits(public_key->n));
842 packet_put_bignum(public_key->e);
843 packet_put_bignum(public_key->n);
844
845 /* Store our public host RSA key. */
846 packet_put_int(BN_num_bits(sensitive_data.host_key->n));
847 packet_put_bignum(sensitive_data.host_key->e);
848 packet_put_bignum(sensitive_data.host_key->n);
849
850 /* Put protocol flags. */
851 packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
852
853 /* Declare which ciphers we support. */
854 packet_put_int(cipher_mask());
855
856 /* Declare supported authentication types. */
857 auth_mask = 0;
858 if (options.rhosts_authentication)
859 auth_mask |= 1 << SSH_AUTH_RHOSTS;
860 if (options.rhosts_rsa_authentication)
861 auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA;
862 if (options.rsa_authentication)
863 auth_mask |= 1 << SSH_AUTH_RSA;
864#ifdef KRB4
865 if (options.kerberos_authentication)
866 auth_mask |= 1 << SSH_AUTH_KERBEROS;
867#endif
868#ifdef AFS
869 if (options.kerberos_tgt_passing)
870 auth_mask |= 1 << SSH_PASS_KERBEROS_TGT;
871 if (options.afs_token_passing)
872 auth_mask |= 1 << SSH_PASS_AFS_TOKEN;
873#endif
874 if (options.password_authentication)
875 auth_mask |= 1 << SSH_AUTH_PASSWORD;
876 packet_put_int(auth_mask);
877
878 /* Send the packet and wait for it to be sent. */
879 packet_send();
880 packet_write_wait();
881
882 debug("Sent %d bit public key and %d bit host key.",
883 BN_num_bits(public_key->n), BN_num_bits(sensitive_data.host_key->n));
884
885 /* Read clients reply (cipher type and session key). */
886 packet_read_expect(&plen, SSH_CMSG_SESSION_KEY);
887
888 /* Get cipher type. */
889 cipher_type = packet_get_char();
890
891 /* Get check bytes from the packet. These must match those we sent earlier
892 with the public key packet. */
893 for (i = 0; i < 8; i++)
894 if (check_bytes[i] != packet_get_char())
895 packet_disconnect("IP Spoofing check bytes do not match.");
896
897 debug("Encryption type: %.200s", cipher_name(cipher_type));
898
899 /* Get the encrypted integer. */
900 session_key_int = BN_new();
901 packet_get_bignum(session_key_int, &slen);
902
903 /* Get protocol flags. */
904 protocol_flags = packet_get_int();
905 packet_set_protocol_flags(protocol_flags);
906
907 packet_integrity_check(plen, 1 + 8 + slen + 4, SSH_CMSG_SESSION_KEY);
908
909 /* Decrypt it using our private server key and private host key (key with
910 larger modulus first). */
911 if (BN_cmp(sensitive_data.private_key->n, sensitive_data.host_key->n) > 0)
912 {
913 /* Private key has bigger modulus. */
914 assert(BN_num_bits(sensitive_data.private_key->n) >=
915 BN_num_bits(sensitive_data.host_key->n) + SSH_KEY_BITS_RESERVED);
916 rsa_private_decrypt(session_key_int, session_key_int,
917 sensitive_data.private_key);
918 rsa_private_decrypt(session_key_int, session_key_int,
919 sensitive_data.host_key);
920 }
921 else
922 {
923 /* Host key has bigger modulus (or they are equal). */
924 assert(BN_num_bits(sensitive_data.host_key->n) >=
925 BN_num_bits(sensitive_data.private_key->n) +
926 SSH_KEY_BITS_RESERVED);
927 rsa_private_decrypt(session_key_int, session_key_int,
928 sensitive_data.host_key);
929 rsa_private_decrypt(session_key_int, session_key_int,
930 sensitive_data.private_key);
931 }
932
933 /* Compute session id for this session. */
934 compute_session_id(session_id, check_bytes,
935 BN_num_bits(sensitive_data.host_key->n),
936 sensitive_data.host_key->n,
937 BN_num_bits(sensitive_data.private_key->n),
938 sensitive_data.private_key->n);
939
940 /* Extract session key from the decrypted integer. The key is in the
941 least significant 256 bits of the integer; the first byte of the
942 key is in the highest bits. */
943 BN_mask_bits(session_key_int, sizeof(session_key) * 8);
944 assert(BN_num_bytes(session_key_int) == sizeof(session_key));
945 BN_bn2bin(session_key_int, session_key);
946
947 /* Xor the first 16 bytes of the session key with the session id. */
948 for (i = 0; i < 16; i++)
949 session_key[i] ^= session_id[i];
950
951 /* Destroy the decrypted integer. It is no longer needed. */
952 BN_clear_free(session_key_int);
953
954 /* Set the session key. From this on all communications will be
955 encrypted. */
956 packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH,
957 cipher_type, 0);
958
959 /* Destroy our copy of the session key. It is no longer needed. */
960 memset(session_key, 0, sizeof(session_key));
961
962 debug("Received session key; encryption turned on.");
963
964 /* Send an acknowledgement packet. Note that this packet is sent
965 encrypted. */
966 packet_start(SSH_SMSG_SUCCESS);
967 packet_send();
968 packet_write_wait();
969
970 /* Get the name of the user that we wish to log in as. */
971 packet_read_expect(&plen, SSH_CMSG_USER);
972
973 /* Get the user name. */
974 {
975 int ulen;
976 user = packet_get_string(&ulen);
977 packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER);
978 }
979
980 /* Destroy the private and public keys. They will no longer be needed. */
981 RSA_free(public_key);
982 RSA_free(sensitive_data.private_key);
983 RSA_free(sensitive_data.host_key);
984
985 setproctitle("%s", user);
986 /* Do the authentication. */
987 do_authentication(user, privileged_port);
988}
989
990/* Check if the user is allowed to log in via ssh. If user is listed in
991 DenyUsers or user's primary group is listed in DenyGroups, false will
992 be returned. If AllowUsers isn't empty and user isn't listed there, or
993 if AllowGroups isn't empty and user isn't listed there, false will be
994 returned. Otherwise true is returned.
995 XXX This function should also check if user has a valid shell */
996
997static int
998allowed_user(struct passwd *pw)
999{
1000 struct group *grp;
1001 int i;
1002
1003 /* Shouldn't be called if pw is NULL, but better safe than sorry... */
1004 if (!pw)
1005 return 0;
1006
1007 /* XXX Should check for valid login shell */
1008
1009 /* Return false if user is listed in DenyUsers */
1010 if (options.num_deny_users > 0)
1011 {
1012 if (!pw->pw_name)
1013 return 0;
1014 for (i = 0; i < options.num_deny_users; i++)
1015 if (match_pattern(pw->pw_name, options.deny_users[i]))
1016 return 0;
1017 }
1018
1019 /* Return false if AllowUsers isn't empty and user isn't listed there */
1020 if (options.num_allow_users > 0)
1021 {
1022 if (!pw->pw_name)
1023 return 0;
1024 for (i = 0; i < options.num_allow_users; i++)
1025 if (match_pattern(pw->pw_name, options.allow_users[i]))
1026 break;
1027 /* i < options.num_allow_users iff we break for loop */
1028 if (i >= options.num_allow_users)
1029 return 0;
1030 }
1031
1032 /* Get the primary group name if we need it. Return false if it fails */
1033 if (options.num_deny_groups > 0 || options.num_allow_groups > 0 )
1034 {
1035 grp = getgrgid(pw->pw_gid);
1036 if (!grp)
1037 return 0;
1038
1039 /* Return false if user's group is listed in DenyGroups */
1040 if (options.num_deny_groups > 0)
1041 {
1042 if (!grp->gr_name)
1043 return 0;
1044 for (i = 0; i < options.num_deny_groups; i++)
1045 if (match_pattern(grp->gr_name, options.deny_groups[i]))
1046 return 0;
1047 }
1048
1049 /* Return false if AllowGroups isn't empty and user's group isn't
1050 listed there */
1051 if (options.num_allow_groups > 0)
1052 {
1053 if (!grp->gr_name)
1054 return 0;
1055 for (i = 0; i < options.num_allow_groups; i++)
1056 if (match_pattern(grp->gr_name, options.allow_groups[i]))
1057 break;
1058 /* i < options.num_allow_groups iff we break for loop */
1059 if (i >= options.num_allow_groups)
1060 return 0;
1061 }
1062 }
1063
1064 /* We found no reason not to let this user try to log on... */
1065 return 1;
1066}
1067
1068/* Performs authentication of an incoming connection. Session key has already
1069 been exchanged and encryption is enabled. User is the user name to log
1070 in as (received from the clinet). Privileged_port is true if the
1071 connection comes from a privileged port (used for .rhosts authentication).*/
1072
1073#define MAX_AUTH_FAILURES 5
1074
1075void
1076do_authentication(char *user, int privileged_port)
1077{
1078 int type;
1079 int authenticated = 0;
1080 int authentication_failures = 0;
1081 char *password;
1082 struct passwd *pw, pwcopy;
1083 char *client_user;
1084 unsigned int client_host_key_bits;
1085 BIGNUM *client_host_key_e, *client_host_key_n;
1086#ifdef HAVE_PAM
1087 int pam_auth_ok;
1088#endif /* HAVE_PAM */
1089
1090#ifdef AFS
1091 /* If machine has AFS, set process authentication group. */
1092 if (k_hasafs()) {
1093 k_setpag();
1094 k_unlog();
1095 }
1096#endif /* AFS */
1097
1098 /* Verify that the user is a valid user. */
1099 pw = getpwnam(user);
1100#ifdef HAVE_PAM
1101 if ((pw != NULL) && allowed_user(pw))
1102 {
1103 /* Initialise PAM */
1104 retval = pam_start("ssh", pw->pw_name, &conv, (pam_handle_t **)&pamh);
1105 fatal_add_cleanup(&pam_cleanup_proc, NULL);
1106 origretval = retval;
1107 if (retval == PAM_SUCCESS)
1108 pam_auth_ok = 1;
1109 }
1110
1111 if (pam_auth_ok == 0)
1112#else /* HAVE_PAM */
1113 if (!pw || !allowed_user(pw))
1114#endif /* HAVE_PAM */
1115 {
1116 /* The user does not exist or access is denied,
1117 but fake indication that authentication is needed. */
1118 packet_start(SSH_SMSG_FAILURE);
1119 packet_send();
1120 packet_write_wait();
1121
1122 /* Keep reading packets, and always respond with a failure. This is to
1123 avoid disclosing whether such a user really exists. */
1124 for (;;)
1125 {
1126 /* Read a packet. This will not return if the client disconnects. */
1127 int plen;
1128 int type = packet_read(&plen);
1129#ifdef SKEY
1130 int passw_len;
1131 char *password, *skeyinfo;
1132 if (options.password_authentication &&
1133 options.skey_authentication == 1 &&
1134 type == SSH_CMSG_AUTH_PASSWORD &&
1135 (password = packet_get_string(&passw_len)) != NULL &&
1136 passw_len == 5 &&
1137 strncasecmp(password, "s/key", 5) == 0 &&
1138 (skeyinfo = skey_fake_keyinfo(user)) != NULL ){
1139 /* Send a fake s/key challenge. */
1140 packet_send_debug(skeyinfo);
1141 }
1142#endif
1143 /* Send failure. This should be indistinguishable from a failed
1144 authentication. */
1145 packet_start(SSH_SMSG_FAILURE);
1146 packet_send();
1147 packet_write_wait();
1148 if (++authentication_failures >= MAX_AUTH_FAILURES) {
1149 packet_disconnect("Too many authentication failures for %.100s from %.200s",
1150 user, get_canonical_hostname());
1151 }
1152 }
1153 /*NOTREACHED*/
1154 abort();
1155 }
1156
1157 /* Take a copy of the returned structure. */
1158 memset(&pwcopy, 0, sizeof(pwcopy));
1159 pwcopy.pw_name = xstrdup(pw->pw_name);
1160 pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
1161 pwcopy.pw_uid = pw->pw_uid;
1162 pwcopy.pw_gid = pw->pw_gid;
1163 pwcopy.pw_dir = xstrdup(pw->pw_dir);
1164 pwcopy.pw_shell = xstrdup(pw->pw_shell);
1165 pw = &pwcopy;
1166
1167 /* If we are not running as root, the user must have the same uid as the
1168 server. */
1169 if (getuid() != 0 && pw->pw_uid != getuid())
1170 packet_disconnect("Cannot change user when server not running as root.");
1171
1172 debug("Attempting authentication for %.100s.", user);
1173
1174 /* If the user has no password, accept authentication immediately. */
1175 if (options.password_authentication &&
1176#ifdef KRB4
1177 (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
1178#endif /* KRB4 */
1179 auth_password(pw, ""))
1180 {
1181 /* Authentication with empty password succeeded. */
1182 debug("Login for user %.100s accepted without authentication.", user);
1183 /* authentication_type = SSH_AUTH_PASSWORD; */
1184 authenticated = 1;
1185 /* Success packet will be sent after loop below. */
1186 }
1187 else
1188 {
1189 /* Indicate that authentication is needed. */
1190 packet_start(SSH_SMSG_FAILURE);
1191 packet_send();
1192 packet_write_wait();
1193 }
1194
1195 /* Loop until the user has been authenticated or the connection is closed. */
1196 while (!authenticated)
1197 {
1198 int plen;
1199 /* Get a packet from the client. */
1200 type = packet_read(&plen);
1201
1202 /* Process the packet. */
1203 switch (type)
1204 {
1205
1206#ifdef AFS
1207 case SSH_CMSG_HAVE_KERBEROS_TGT:
1208 if (!options.kerberos_tgt_passing)
1209 {
1210 /* packet_get_all(); */
1211 log("Kerberos tgt passing disabled.");
1212 break;
1213 }
1214 else {
1215 /* Accept Kerberos tgt. */
1216 int dlen;
1217 char *tgt = packet_get_string(&dlen);
1218 packet_integrity_check(plen, 4 + dlen, type);
1219 if (!auth_kerberos_tgt(pw, tgt))
1220 debug("Kerberos tgt REFUSED for %s", user);
1221 xfree(tgt);
1222 }
1223 continue;
1224
1225 case SSH_CMSG_HAVE_AFS_TOKEN:
1226 if (!options.afs_token_passing || !k_hasafs()) {
1227 /* packet_get_all(); */
1228 log("AFS token passing disabled.");
1229 break;
1230 }
1231 else {
1232 /* Accept AFS token. */
1233 int dlen;
1234 char *token_string = packet_get_string(&dlen);
1235 packet_integrity_check(plen, 4 + dlen, type);
1236 if (!auth_afs_token(user, pw->pw_uid, token_string))
1237 debug("AFS token REFUSED for %s", user);
1238 xfree(token_string);
1239 continue;
1240 }
1241#endif /* AFS */
1242
1243#ifdef KRB4
1244 case SSH_CMSG_AUTH_KERBEROS:
1245 if (!options.kerberos_authentication)
1246 {
1247 /* packet_get_all(); */
1248 log("Kerberos authentication disabled.");
1249 break;
1250 }
1251 else {
1252 /* Try Kerberos v4 authentication. */
1253 KTEXT_ST auth;
1254 char *tkt_user = NULL;
1255 char *kdata = packet_get_string((unsigned int *)&auth.length);
1256 packet_integrity_check(plen, 4 + auth.length, type);
1257
1258 if (auth.length < MAX_KTXT_LEN)
1259 memcpy(auth.dat, kdata, auth.length);
1260 xfree(kdata);
1261
1262 if (auth_krb4(user, &auth, &tkt_user)) {
1263 /* Client has successfully authenticated to us. */
1264 log("Kerberos authentication accepted %s for account "
1265 "%s from %s", tkt_user, user, get_canonical_hostname());
1266 /* authentication_type = SSH_AUTH_KERBEROS; */
1267 authenticated = 1;
1268 xfree(tkt_user);
1269 }
1270 else {
1271 log("Kerberos authentication failed for account "
1272 "%s from %s", user, get_canonical_hostname());
1273 }
1274 }
1275 break;
1276#endif /* KRB4 */
1277
1278 case SSH_CMSG_AUTH_RHOSTS:
1279 if (!options.rhosts_authentication)
1280 {
1281 log("Rhosts authentication disabled.");
1282 break;
1283 }
1284
1285 /* Rhosts authentication (also uses /etc/hosts.equiv). */
1286 if (!privileged_port)
1287 {
1288 log("Rhosts authentication not available for connections from unprivileged port.");
1289 break;
1290 }
1291
1292 /* Get client user name. Note that we just have to trust the client;
1293 this is one reason why rhosts authentication is insecure.
1294 (Another is IP-spoofing on a local network.) */
1295 {
1296 int dlen;
1297 client_user = packet_get_string(&dlen);
1298 packet_integrity_check(plen, 4 + dlen, type);
1299 }
1300
1301 /* Try to authenticate using /etc/hosts.equiv and .rhosts. */
1302 if (auth_rhosts(pw, client_user, options.ignore_rhosts,
1303 options.strict_modes))
1304 {
1305 /* Authentication accepted. */
1306 log("Rhosts authentication accepted for %.100s, remote %.100s on %.700s.",
1307 user, client_user, get_canonical_hostname());
1308 authenticated = 1;
1309 xfree(client_user);
1310 break;
1311 }
1312 log("Rhosts authentication failed for %.100s, remote %.100s.",
1313 user, client_user);
1314 xfree(client_user);
1315 break;
1316
1317 case SSH_CMSG_AUTH_RHOSTS_RSA:
1318 if (!options.rhosts_rsa_authentication)
1319 {
1320 log("Rhosts with RSA authentication disabled.");
1321 break;
1322 }
1323
1324 /* Rhosts authentication (also uses /etc/hosts.equiv) with RSA
1325 host authentication. */
1326 if (!privileged_port)
1327 {
1328 log("Rhosts authentication not available for connections from unprivileged port.");
1329 break;
1330 }
1331
1332 {
1333 int ulen, elen, nlen;
1334 /* Get client user name. Note that we just have to trust
1335 the client; root on the client machine can claim to be
1336 any user. */
1337 client_user = packet_get_string(&ulen);
1338
1339 /* Get the client host key. */
1340 client_host_key_e = BN_new();
1341 client_host_key_n = BN_new();
1342 client_host_key_bits = packet_get_int();
1343 packet_get_bignum(client_host_key_e, &elen);
1344 packet_get_bignum(client_host_key_n, &nlen);
1345
1346 packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type);
1347 }
1348
1349 /* Try to authenticate using /etc/hosts.equiv and .rhosts. */
1350 if (auth_rhosts_rsa(pw, client_user,
1351 client_host_key_bits, client_host_key_e,
1352 client_host_key_n, options.ignore_rhosts,
1353 options.strict_modes))
1354 {
1355 /* Authentication accepted. */
1356 authenticated = 1;
1357 xfree(client_user);
1358 BN_clear_free(client_host_key_e);
1359 BN_clear_free(client_host_key_n);
1360 break;
1361 }
1362 log("Rhosts authentication failed for %.100s, remote %.100s.",
1363 user, client_user);
1364 xfree(client_user);
1365 BN_clear_free(client_host_key_e);
1366 BN_clear_free(client_host_key_n);
1367 break;
1368
1369 case SSH_CMSG_AUTH_RSA:
1370 if (!options.rsa_authentication)
1371 {
1372 log("RSA authentication disabled.");
1373 break;
1374 }
1375
1376 /* RSA authentication requested. */
1377 {
1378 int nlen;
1379 BIGNUM *n;
1380 n = BN_new();
1381 packet_get_bignum(n, &nlen);
1382
1383 packet_integrity_check(plen, nlen, type);
1384
1385 if (auth_rsa(pw, n, options.strict_modes))
1386 {
1387 /* Successful authentication. */
1388 BN_clear_free(n);
1389 log("RSA authentication for %.100s accepted.", user);
1390 authenticated = 1;
1391 break;
1392 }
1393 BN_clear_free(n);
1394 log("RSA authentication for %.100s failed.", user);
1395 }
1396 break;
1397
1398 case SSH_CMSG_AUTH_PASSWORD:
1399 if (!options.password_authentication)
1400 {
1401 log("Password authentication disabled.");
1402 break;
1403 }
1404
1405 /* Password authentication requested. */
1406 /* Read user password. It is in plain text, but was transmitted
1407 over the encrypted channel so it is not visible to an outside
1408 observer. */
1409 {
1410 int passw_len;
1411 password = packet_get_string(&passw_len);
1412 packet_integrity_check(plen, 4 + passw_len, type);
1413 }
1414
1415 /* Try authentication with the password. */
1416 if (auth_password(pw, password))
1417 {
1418 /* Successful authentication. */
1419 /* Clear the password from memory. */
1420 memset(password, 0, strlen(password));
1421 xfree(password);
1422 log("Password authentication for %.100s accepted.", user);
1423 authenticated = 1;
1424 break;
1425 }
1426 log("Password authentication for %.100s failed.", user);
1427 memset(password, 0, strlen(password));
1428 xfree(password);
1429 break;
1430
1431 case SSH_CMSG_AUTH_TIS:
1432 /* TIS Authentication is unsupported */
1433 log("TIS authentication disabled.");
1434 break;
1435
1436 default:
1437 /* Any unknown messages will be ignored (and failure returned)
1438 during authentication. */
1439 log("Unknown message during authentication: type %d", type);
1440 break; /* Respond with a failure message. */
1441 }
1442 /* If successfully authenticated, break out of loop. */
1443 if (authenticated)
1444 break;
1445
1446 /* Send a message indicating that the authentication attempt failed. */
1447 packet_start(SSH_SMSG_FAILURE);
1448 packet_send();
1449 packet_write_wait();
1450
1451 if (++authentication_failures >= MAX_AUTH_FAILURES) {
1452 packet_disconnect("Too many authentication failures for %.100s from %.200s",
1453 pw->pw_name, get_canonical_hostname());
1454 }
1455 }
1456
1457 /* Check if the user is logging in as root and root logins are disallowed. */
1458 if (pw->pw_uid == 0 && !options.permit_root_login)
1459 {
1460 if (forced_command)
1461 log("Root login accepted for forced command.", forced_command);
1462 else
1463 packet_disconnect("ROOT LOGIN REFUSED FROM %.200s",
1464 get_canonical_hostname());
1465 }
1466
1467 /* The user has been authenticated and accepted. */
1468 packet_start(SSH_SMSG_SUCCESS);
1469 packet_send();
1470 packet_write_wait();
1471
1472 /* Perform session preparation. */
1473 do_authenticated(pw);
1474}
1475
1476/* Prepares for an interactive session. This is called after the user has
1477 been successfully authenticated. During this message exchange, pseudo
1478 terminals are allocated, X11, TCP/IP, and authentication agent forwardings
1479 are requested, etc. */
1480
1481void do_authenticated(struct passwd *pw)
1482{
1483 int type;
1484 int compression_level = 0, enable_compression_after_reply = 0;
1485 int have_pty = 0, ptyfd = -1, ttyfd = -1, xauthfd = -1;
1486 int row, col, xpixel, ypixel, screen;
1487 char ttyname[64];
1488 char *command, *term = NULL, *display = NULL, *proto = NULL, *data = NULL;
1489 struct group *grp;
1490 gid_t tty_gid;
1491 mode_t tty_mode;
1492 int n_bytes;
1493
1494 /* Cancel the alarm we set to limit the time taken for authentication. */
1495 alarm(0);
1496
1497 /* Inform the channel mechanism that we are the server side and that
1498 the client may request to connect to any port at all. (The user could
1499 do it anyway, and we wouldn\'t know what is permitted except by the
1500 client telling us, so we can equally well trust the client not to request
1501 anything bogus.) */
1502 channel_permit_all_opens();
1503
1504 /* We stay in this loop until the client requests to execute a shell or a
1505 command. */
1506 while (1)
1507 {
1508 int plen, dlen;
1509
1510 /* Get a packet from the client. */
1511 type = packet_read(&plen);
1512
1513 /* Process the packet. */
1514 switch (type)
1515 {
1516 case SSH_CMSG_REQUEST_COMPRESSION:
1517 packet_integrity_check(plen, 4, type);
1518 compression_level = packet_get_int();
1519 if (compression_level < 1 || compression_level > 9)
1520 {
1521 packet_send_debug("Received illegal compression level %d.",
1522 compression_level);
1523 goto fail;
1524 }
1525 /* Enable compression after we have responded with SUCCESS. */
1526 enable_compression_after_reply = 1;
1527 break;
1528
1529 case SSH_CMSG_REQUEST_PTY:
1530 if (no_pty_flag)
1531 {
1532 debug("Allocating a pty not permitted for this authentication.");
1533 goto fail;
1534 }
1535 if (have_pty)
1536 packet_disconnect("Protocol error: you already have a pty.");
1537
1538 debug("Allocating pty.");
1539
1540 /* Allocate a pty and open it. */
1541 if (!pty_allocate(&ptyfd, &ttyfd, ttyname))
1542 {
1543 error("Failed to allocate pty.");
1544 goto fail;
1545 }
1546
1547 /* Determine the group to make the owner of the tty. */
1548 grp = getgrnam("tty");
1549 if (grp)
1550 {
1551 tty_gid = grp->gr_gid;
1552 tty_mode = S_IRUSR|S_IWUSR|S_IWGRP;
1553 }
1554 else
1555 {
1556 tty_gid = pw->pw_gid;
1557 tty_mode = S_IRUSR|S_IWUSR|S_IWGRP|S_IWOTH;
1558 }
1559
1560 /* Change ownership of the tty. */
1561 if (chown(ttyname, pw->pw_uid, tty_gid) < 0)
1562 fatal("chown(%.100s, %d, %d) failed: %.100s",
1563 ttyname, pw->pw_uid, tty_gid, strerror(errno));
1564 if (chmod(ttyname, tty_mode) < 0)
1565 fatal("chmod(%.100s, 0%o) failed: %.100s",
1566 ttyname, tty_mode, strerror(errno));
1567
1568 /* Get TERM from the packet. Note that the value may be of arbitrary
1569 length. */
1570
1571 term = packet_get_string(&dlen);
1572 packet_integrity_check(dlen, strlen(term), type);
1573 /* packet_integrity_check(plen, 4 + dlen + 4*4 + n_bytes, type); */
1574 /* Remaining bytes */
1575 n_bytes = plen - (4 + dlen + 4*4);
1576
1577 if (strcmp(term, "") == 0)
1578 term = NULL;
1579
1580 /* Get window size from the packet. */
1581 row = packet_get_int();
1582 col = packet_get_int();
1583 xpixel = packet_get_int();
1584 ypixel = packet_get_int();
1585 pty_change_window_size(ptyfd, row, col, xpixel, ypixel);
1586
1587 /* Get tty modes from the packet. */
1588 tty_parse_modes(ttyfd, &n_bytes);
1589 packet_integrity_check(plen, 4 + dlen + 4*4 + n_bytes, type);
1590
1591 /* Indicate that we now have a pty. */
1592 have_pty = 1;
1593 break;
1594
1595 case SSH_CMSG_X11_REQUEST_FORWARDING:
1596 if (!options.x11_forwarding)
1597 {
1598 packet_send_debug("X11 forwarding disabled in server configuration file.");
1599 goto fail;
1600 }
1601#ifdef XAUTH_PATH
1602 if (no_x11_forwarding_flag)
1603 {
1604 packet_send_debug("X11 forwarding not permitted for this authentication.");
1605 goto fail;
1606 }
1607 debug("Received request for X11 forwarding with auth spoofing.");
1608 if (display)
1609 packet_disconnect("Protocol error: X11 display already set.");
1610 {
1611 int proto_len, data_len;
1612 proto = packet_get_string(&proto_len);
1613 data = packet_get_string(&data_len);
1614 packet_integrity_check(plen, 4+proto_len + 4+data_len + 4, type);
1615 }
1616 if (packet_get_protocol_flags() & SSH_PROTOFLAG_SCREEN_NUMBER)
1617 screen = packet_get_int();
1618 else
1619 screen = 0;
1620 display = x11_create_display_inet(screen);
1621 if (!display)
1622 goto fail;
1623
1624 /* Setup to always have a local .Xauthority. */
1625 xauthfile = xmalloc(MAXPATHLEN);
1626 snprintf(xauthfile, MAXPATHLEN, "/tmp/XauthXXXXXX");
1627
1628 if ((xauthfd = mkstemp(xauthfile)) != -1) {
1629 fchown(xauthfd, pw->pw_uid, pw->pw_gid);
1630 close(xauthfd);
1631 }
1632 else {
1633 xfree(xauthfile);
1634 xauthfile = NULL;
1635 }
1636 break;
1637#else /* XAUTH_PATH */
1638 /* No xauth program; we won't accept forwarding with spoofing. */
1639 packet_send_debug("No xauth program; cannot forward with spoofing.");
1640 goto fail;
1641#endif /* XAUTH_PATH */
1642
1643 case SSH_CMSG_AGENT_REQUEST_FORWARDING:
1644 if (no_agent_forwarding_flag)
1645 {
1646 debug("Authentication agent forwarding not permitted for this authentication.");
1647 goto fail;
1648 }
1649 debug("Received authentication agent forwarding request.");
1650 auth_input_request_forwarding(pw);
1651 break;
1652
1653 case SSH_CMSG_PORT_FORWARD_REQUEST:
1654 if (no_port_forwarding_flag)
1655 {
1656 debug("Port forwarding not permitted for this authentication.");
1657 goto fail;
1658 }
1659 debug("Received TCP/IP port forwarding request.");
1660 channel_input_port_forward_request(pw->pw_uid == 0);
1661 break;
1662
1663 case SSH_CMSG_EXEC_SHELL:
1664 /* Set interactive/non-interactive mode. */
1665 packet_set_interactive(have_pty || display != NULL,
1666 options.keepalives);
1667
1668 if (forced_command != NULL)
1669 goto do_forced_command;
1670 debug("Forking shell.");
1671 packet_integrity_check(plen, 0, type);
1672 if (have_pty)
1673 do_exec_pty(NULL, ptyfd, ttyfd, ttyname, pw, term, display, proto,
1674 data);
1675 else
1676 do_exec_no_pty(NULL, pw, display, proto, data);
1677 return;
1678
1679 case SSH_CMSG_EXEC_CMD:
1680 /* Set interactive/non-interactive mode. */
1681 packet_set_interactive(have_pty || display != NULL,
1682 options.keepalives);
1683
1684 if (forced_command != NULL)
1685 goto do_forced_command;
1686 /* Get command from the packet. */
1687 {
1688 int dlen;
1689 command = packet_get_string(&dlen);
1690 debug("Executing command '%.500s'", command);
1691 packet_integrity_check(plen, 4 + dlen, type);
1692 }
1693 if (have_pty)
1694 do_exec_pty(command, ptyfd, ttyfd, ttyname, pw, term, display,
1695 proto, data);
1696 else
1697 do_exec_no_pty(command, pw, display, proto, data);
1698 xfree(command);
1699 return;
1700
1701 case SSH_CMSG_MAX_PACKET_SIZE:
1702 debug("The server does not support limiting packet size.");
1703 goto fail;
1704
1705 default:
1706 /* Any unknown messages in this phase are ignored, and a failure
1707 message is returned. */
1708 log("Unknown packet type received after authentication: %d", type);
1709 goto fail;
1710 }
1711
1712 /* The request was successfully processed. */
1713 packet_start(SSH_SMSG_SUCCESS);
1714 packet_send();
1715 packet_write_wait();
1716
1717 /* Enable compression now that we have replied if appropriate. */
1718 if (enable_compression_after_reply)
1719 {
1720 enable_compression_after_reply = 0;
1721 packet_start_compression(compression_level);
1722 }
1723
1724 continue;
1725
1726 fail:
1727 /* The request failed. */
1728 packet_start(SSH_SMSG_FAILURE);
1729 packet_send();
1730 packet_write_wait();
1731 continue;
1732
1733 do_forced_command:
1734 /* There is a forced command specified for this login. Execute it. */
1735 debug("Executing forced command: %.900s", forced_command);
1736 if (have_pty)
1737 do_exec_pty(forced_command, ptyfd, ttyfd, ttyname, pw, term, display,
1738 proto, data);
1739 else
1740 do_exec_no_pty(forced_command, pw, display, proto, data);
1741 return;
1742 }
1743}
1744
1745/* This is called to fork and execute a command when we have no tty. This
1746 will call do_child from the child, and server_loop from the parent after
1747 setting up file descriptors and such. */
1748
1749void do_exec_no_pty(const char *command, struct passwd *pw,
1750 const char *display, const char *auth_proto,
1751 const char *auth_data)
1752{
1753 int pid;
1754
1755#ifdef USE_PIPES
1756 int pin[2], pout[2], perr[2];
1757 /* Allocate pipes for communicating with the program. */
1758 if (pipe(pin) < 0 || pipe(pout) < 0 || pipe(perr) < 0)
1759 packet_disconnect("Could not create pipes: %.100s",
1760 strerror(errno));
1761#else /* USE_PIPES */
1762 int inout[2], err[2];
1763 /* Uses socket pairs to communicate with the program. */
1764 if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0 ||
1765 socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0)
1766 packet_disconnect("Could not create socket pairs: %.100s",
1767 strerror(errno));
1768#endif /* USE_PIPES */
1769
1770 setproctitle("%s@notty", pw->pw_name);
1771
1772 /* Fork the child. */
1773 if ((pid = fork()) == 0)
1774 {
1775 /* Child. Reinitialize the log since the pid has changed. */
1776 log_init(av0, debug_flag && !inetd_flag, debug_flag,
1777 options.quiet_mode, options.log_facility);
1778
1779 /* Create a new session and process group since the 4.4BSD setlogin()
1780 affects the entire process group. */
1781 if (setsid() < 0)
1782 error("setsid failed: %.100s", strerror(errno));
1783
1784#ifdef USE_PIPES
1785 /* Redirect stdin. We close the parent side of the socket pair,
1786 and make the child side the standard input. */
1787 close(pin[1]);
1788 if (dup2(pin[0], 0) < 0)
1789 perror("dup2 stdin");
1790 close(pin[0]);
1791
1792 /* Redirect stdout. */
1793 close(pout[0]);
1794 if (dup2(pout[1], 1) < 0)
1795 perror("dup2 stdout");
1796 close(pout[1]);
1797
1798 /* Redirect stderr. */
1799 close(perr[0]);
1800 if (dup2(perr[1], 2) < 0)
1801 perror("dup2 stderr");
1802 close(perr[1]);
1803#else /* USE_PIPES */
1804 /* Redirect stdin, stdout, and stderr. Stdin and stdout will use the
1805 same socket, as some programs (particularly rdist) seem to depend
1806 on it. */
1807 close(inout[1]);
1808 close(err[1]);
1809 if (dup2(inout[0], 0) < 0) /* stdin */
1810 perror("dup2 stdin");
1811 if (dup2(inout[0], 1) < 0) /* stdout. Note: same socket as stdin. */
1812 perror("dup2 stdout");
1813 if (dup2(err[0], 2) < 0) /* stderr */
1814 perror("dup2 stderr");
1815#endif /* USE_PIPES */
1816
1817 /* Do processing for the child (exec command etc). */
1818 do_child(command, pw, NULL, display, auth_proto, auth_data, NULL);
1819 /*NOTREACHED*/
1820 }
1821 if (pid < 0)
1822 packet_disconnect("fork failed: %.100s", strerror(errno));
1823#ifdef USE_PIPES
1824 /* We are the parent. Close the child sides of the pipes. */
1825 close(pin[0]);
1826 close(pout[1]);
1827 close(perr[1]);
1828
1829 /* Enter the interactive session. */
1830 server_loop(pid, pin[1], pout[0], perr[0]);
1831 /* server_loop has closed pin[1], pout[1], and perr[1]. */
1832#else /* USE_PIPES */
1833 /* We are the parent. Close the child sides of the socket pairs. */
1834 close(inout[0]);
1835 close(err[0]);
1836
1837 /* Enter the interactive session. Note: server_loop must be able to handle
1838 the case that fdin and fdout are the same. */
1839 server_loop(pid, inout[1], inout[1], err[1]);
1840 /* server_loop has closed inout[1] and err[1]. */
1841#endif /* USE_PIPES */
1842}
1843
1844struct pty_cleanup_context
1845{
1846 const char *ttyname;
1847 int pid;
1848};
1849
1850/* Function to perform cleanup if we get aborted abnormally (e.g., due to a
1851 dropped connection). */
1852
1853void pty_cleanup_proc(void *context)
1854{
1855 struct pty_cleanup_context *cu = context;
1856
1857 debug("pty_cleanup_proc called");
1858
1859#if defined(KRB4)
1860 /* Destroy user's ticket cache file. */
1861 (void) dest_tkt();
1862#endif /* KRB4 */
1863
1864 /* Record that the user has logged out. */
1865 record_logout(cu->pid, cu->ttyname);
1866
1867 /* Release the pseudo-tty. */
1868 pty_release(cu->ttyname);
1869}
1870
1871/* This is called to fork and execute a command when we have a tty. This
1872 will call do_child from the child, and server_loop from the parent after
1873 setting up file descriptors, controlling tty, updating wtmp, utmp,
1874 lastlog, and other such operations. */
1875
1876void do_exec_pty(const char *command, int ptyfd, int ttyfd,
1877 const char *ttyname, struct passwd *pw, const char *term,
1878 const char *display, const char *auth_proto,
1879 const char *auth_data)
1880{
1881 int pid, fdout;
1882 const char *hostname;
1883 time_t last_login_time;
1884 char buf[100], *time_string;
1885 FILE *f;
1886 char line[256];
1887 struct stat st;
1888 int quiet_login;
1889 struct sockaddr_in from;
1890 int fromlen;
1891 struct pty_cleanup_context cleanup_context;
1892
1893 /* Get remote host name. */
1894 hostname = get_canonical_hostname();
1895
1896 /* Get the time when the user last logged in. Buf will be set to contain
1897 the hostname the last login was from. */
1898 if(!options.use_login) {
1899 last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name,
1900 buf, sizeof(buf));
1901 }
1902
1903 setproctitle("%s@%s", pw->pw_name, strrchr(ttyname, '/') + 1);
1904
1905 /* Fork the child. */
1906 if ((pid = fork()) == 0)
1907 {
1908 pid = getpid();
1909
1910 /* Child. Reinitialize the log because the pid has changed. */
1911 log_init(av0, debug_flag && !inetd_flag, debug_flag, options.quiet_mode,
1912 options.log_facility);
1913
1914 /* Close the master side of the pseudo tty. */
1915 close(ptyfd);
1916
1917 /* Make the pseudo tty our controlling tty. */
1918 pty_make_controlling_tty(&ttyfd, ttyname);
1919
1920 /* Redirect stdin from the pseudo tty. */
1921 if (dup2(ttyfd, fileno(stdin)) < 0)
1922 error("dup2 stdin failed: %.100s", strerror(errno));
1923
1924 /* Redirect stdout to the pseudo tty. */
1925 if (dup2(ttyfd, fileno(stdout)) < 0)
1926 error("dup2 stdin failed: %.100s", strerror(errno));
1927
1928 /* Redirect stderr to the pseudo tty. */
1929 if (dup2(ttyfd, fileno(stderr)) < 0)
1930 error("dup2 stdin failed: %.100s", strerror(errno));
1931
1932 /* Close the extra descriptor for the pseudo tty. */
1933 close(ttyfd);
1934
1935 /* Get IP address of client. This is needed because we want to record
1936 where the user logged in from. If the connection is not a socket,
1937 let the ip address be 0.0.0.0. */
1938 memset(&from, 0, sizeof(from));
1939 if (packet_get_connection_in() == packet_get_connection_out())
1940 {
1941 fromlen = sizeof(from);
1942 if (getpeername(packet_get_connection_in(),
1943 (struct sockaddr *)&from, &fromlen) < 0)
1944 fatal("getpeername: %.100s", strerror(errno));
1945 }
1946
1947 /* Record that there was a login on that terminal. */
1948 record_login(pid, ttyname, pw->pw_name, pw->pw_uid, hostname,
1949 &from);
1950
1951 /* Check if .hushlogin exists. */
1952 snprintf(line, sizeof line, "%.200s/.hushlogin", pw->pw_dir);
1953 quiet_login = stat(line, &st) >= 0;
1954
1955 /* If the user has logged in before, display the time of last login.
1956 However, don't display anything extra if a command has been
1957 specified (so that ssh can be used to execute commands on a remote
1958 machine without users knowing they are going to another machine).
1959 Login(1) will do this for us as well, so check if login(1) is used */
1960 if (command == NULL && last_login_time != 0 && !quiet_login &&
1961 !options.use_login)
1962 {
1963 /* Convert the date to a string. */
1964 time_string = ctime(&last_login_time);
1965 /* Remove the trailing newline. */
1966 if (strchr(time_string, '\n'))
1967 *strchr(time_string, '\n') = 0;
1968 /* Display the last login time. Host if displayed if known. */
1969 if (strcmp(buf, "") == 0)
1970 printf("Last login: %s\r\n", time_string);
1971 else
1972 printf("Last login: %s from %s\r\n", time_string, buf);
1973 }
1974
1975 /* Print /etc/motd unless a command was specified or printing it was
1976 disabled in server options or login(1) will be used. Note that
1977 some machines appear to print it in /etc/profile or similar. */
1978 if (command == NULL && options.print_motd && !quiet_login &&
1979 !options.use_login)
1980 {
1981 /* Print /etc/motd if it exists. */
1982 f = fopen("/etc/motd", "r");
1983 if (f)
1984 {
1985 while (fgets(line, sizeof(line), f))
1986 fputs(line, stdout);
1987 fclose(f);
1988 }
1989 }
1990
1991 /* Do common processing for the child, such as execing the command. */
1992 do_child(command, pw, term, display, auth_proto, auth_data, ttyname);
1993 /*NOTREACHED*/
1994 }
1995 if (pid < 0)
1996 packet_disconnect("fork failed: %.100s", strerror(errno));
1997 /* Parent. Close the slave side of the pseudo tty. */
1998 close(ttyfd);
1999
2000 /* Create another descriptor of the pty master side for use as the standard
2001 input. We could use the original descriptor, but this simplifies code
2002 in server_loop. The descriptor is bidirectional. */
2003 fdout = dup(ptyfd);
2004 if (fdout < 0)
2005 packet_disconnect("dup failed: %.100s", strerror(errno));
2006
2007 /* Add a cleanup function to clear the utmp entry and record logout time
2008 in case we call fatal() (e.g., the connection gets closed). */
2009 cleanup_context.pid = pid;
2010 cleanup_context.ttyname = ttyname;
2011 fatal_add_cleanup(pty_cleanup_proc, (void *)&cleanup_context);
2012
2013 /* Enter interactive session. */
2014 server_loop(pid, ptyfd, fdout, -1);
2015 /* server_loop has not closed ptyfd and fdout. */
2016
2017 /* Cancel the cleanup function. */
2018 fatal_remove_cleanup(pty_cleanup_proc, (void *)&cleanup_context);
2019
2020 /* Record that the user has logged out. */
2021 record_logout(pid, ttyname);
2022
2023 /* Release the pseudo-tty. */
2024 pty_release(ttyname);
2025
2026 /* Close the server side of the socket pairs. We must do this after the
2027 pty cleanup, so that another process doesn't get this pty while we're
2028 still cleaning up. */
2029 close(ptyfd);
2030 close(fdout);
2031}
2032
2033/* Sets the value of the given variable in the environment. If the variable
2034 already exists, its value is overriden. */
2035
2036void child_set_env(char ***envp, unsigned int *envsizep, const char *name,
2037 const char *value)
2038{
2039 unsigned int i, namelen;
2040 char **env;
2041
2042 /* Find the slot where the value should be stored. If the variable already
2043 exists, we reuse the slot; otherwise we append a new slot at the end
2044 of the array, expanding if necessary. */
2045 env = *envp;
2046 namelen = strlen(name);
2047 for (i = 0; env[i]; i++)
2048 if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')
2049 break;
2050 if (env[i])
2051 {
2052 /* Name already exists. Reuse the slot. */
2053 xfree(env[i]);
2054 }
2055 else
2056 {
2057 /* New variable. Expand the array if necessary. */
2058 if (i >= (*envsizep) - 1)
2059 {
2060 (*envsizep) += 50;
2061 env = (*envp) = xrealloc(env, (*envsizep) * sizeof(char *));
2062 }
2063
2064 /* Need to set the NULL pointer at end of array beyond the new
2065 slot. */
2066 env[i + 1] = NULL;
2067 }
2068
2069 /* Allocate space and format the variable in the appropriate slot. */
2070 env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1);
2071 snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value);
2072}
2073
2074/* Reads environment variables from the given file and adds/overrides them
2075 into the environment. If the file does not exist, this does nothing.
2076 Otherwise, it must consist of empty lines, comments (line starts with '#')
2077 and assignments of the form name=value. No other forms are allowed. */
2078
2079void read_environment_file(char ***env, unsigned int *envsize,
2080 const char *filename)
2081{
2082 FILE *f;
2083 char buf[4096];
2084 char *cp, *value;
2085
2086 /* Open the environment file. */
2087 f = fopen(filename, "r");
2088 if (!f)
2089 return; /* Not found. */
2090
2091 /* Process each line. */
2092 while (fgets(buf, sizeof(buf), f))
2093 {
2094 /* Skip leading whitespace. */
2095 for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
2096 ;
2097
2098 /* Ignore empty and comment lines. */
2099 if (!*cp || *cp == '#' || *cp == '\n')
2100 continue;
2101
2102 /* Remove newline. */
2103 if (strchr(cp, '\n'))
2104 *strchr(cp, '\n') = '\0';
2105
2106 /* Find the equals sign. Its lack indicates badly formatted line. */
2107 value = strchr(cp, '=');
2108 if (value == NULL)
2109 {
2110 fprintf(stderr, "Bad line in %.100s: %.200s\n", filename, buf);
2111 continue;
2112 }
2113
2114 /* Replace the equals sign by nul, and advance value to the value
2115 string. */
2116 *value = '\0';
2117 value++;
2118
2119 /* Set the value in environment. */
2120 child_set_env(env, envsize, cp, value);
2121 }
2122
2123 fclose(f);
2124}
2125
2126/* Performs common processing for the child, such as setting up the
2127 environment, closing extra file descriptors, setting the user and group
2128 ids, and executing the command or shell. */
2129
2130void do_child(const char *command, struct passwd *pw, const char *term,
2131 const char *display, const char *auth_proto,
2132 const char *auth_data, const char *ttyname)
2133{
2134 const char *shell, *cp = NULL;
2135 char buf[256];
2136 FILE *f;
2137 unsigned int envsize, i;
2138 char **env;
2139 extern char **environ;
2140 struct stat st;
2141 char *argv[10];
2142
2143 /* Check /etc/nologin. */
2144 f = fopen("/etc/nologin", "r");
2145 if (f)
2146 { /* /etc/nologin exists. Print its contents and exit. */
2147 while (fgets(buf, sizeof(buf), f))
2148 fputs(buf, stderr);
2149 fclose(f);
2150 if (pw->pw_uid != 0)
2151 exit(254);
2152 }
2153
2154 /* Set login name in the kernel. */
2155 if (setlogin(pw->pw_name) < 0)
2156 error("setlogin failed: %s", strerror(errno));
2157
2158 /* Set uid, gid, and groups. */
2159 /* Login(1) does this as well, and it needs uid 0 for the "-h" switch,
2160 so we let login(1) to this for us. */
2161 if(!options.use_login) {
2162 if (getuid() == 0 || geteuid() == 0)
2163 {
2164 if (setgid(pw->pw_gid) < 0)
2165 {
2166 perror("setgid");
2167 exit(1);
2168 }
2169 /* Initialize the group list. */
2170 if (initgroups(pw->pw_name, pw->pw_gid) < 0)
2171 {
2172 perror("initgroups");
2173 exit(1);
2174 }
2175 endgrent();
2176
2177 /* Permanently switch to the desired uid. */
2178 permanently_set_uid(pw->pw_uid);
2179 }
2180
2181 if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
2182 fatal("Failed to set uids to %d.", (int)pw->pw_uid);
2183 }
2184
2185 /* Get the shell from the password data. An empty shell field is legal,
2186 and means /bin/sh. */
2187 shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
2188
2189#ifdef AFS
2190 /* Try to get AFS tokens for the local cell. */
2191 if (k_hasafs()) {
2192 char cell[64];
2193
2194 if (k_afs_cell_of_file(pw->pw_dir, cell, sizeof(cell)) == 0)
2195 krb_afslog(cell, 0);
2196
2197 krb_afslog(0, 0);
2198 }
2199#endif /* AFS */
2200
2201 /* Initialize the environment. In the first part we allocate space for
2202 all environment variables. */
2203 envsize = 100;
2204 env = xmalloc(envsize * sizeof(char *));
2205 env[0] = NULL;
2206
2207 if(!options.use_login) {
2208 /* Set basic environment. */
2209 child_set_env(&env, &envsize, "USER", pw->pw_name);
2210 child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
2211 child_set_env(&env, &envsize, "HOME", pw->pw_dir);
2212 child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
2213
2214 snprintf(buf, sizeof buf, "%.200s/%.50s",
2215 _PATH_MAILDIR, pw->pw_name);
2216 child_set_env(&env, &envsize, "MAIL", buf);
2217
2218 /* Normal systems set SHELL by default. */
2219 child_set_env(&env, &envsize, "SHELL", shell);
2220 }
2221
2222 /* Let it inherit timezone if we have one. */
2223 if (getenv("TZ"))
2224 child_set_env(&env, &envsize, "TZ", getenv("TZ"));
2225
2226 /* Set custom environment options from RSA authentication. */
2227 while (custom_environment)
2228 {
2229 struct envstring *ce = custom_environment;
2230 char *s = ce->s;
2231 int i;
2232 for (i = 0; s[i] != '=' && s[i]; i++)
2233 ;
2234 if (s[i] == '=')
2235 {
2236 s[i] = 0;
2237 child_set_env(&env, &envsize, s, s + i + 1);
2238 }
2239 custom_environment = ce->next;
2240 xfree(ce->s);
2241 xfree(ce);
2242 }
2243
2244 /* Set SSH_CLIENT. */
2245 snprintf(buf, sizeof buf, "%.50s %d %d",
2246 get_remote_ipaddr(), get_remote_port(), options.port);
2247 child_set_env(&env, &envsize, "SSH_CLIENT", buf);
2248
2249 /* Set SSH_TTY if we have a pty. */
2250 if (ttyname)
2251 child_set_env(&env, &envsize, "SSH_TTY", ttyname);
2252
2253 /* Set TERM if we have a pty. */
2254 if (term)
2255 child_set_env(&env, &envsize, "TERM", term);
2256
2257 /* Set DISPLAY if we have one. */
2258 if (display)
2259 child_set_env(&env, &envsize, "DISPLAY", display);
2260
2261#ifdef KRB4
2262 if (ticket)
2263 child_set_env(&env, &envsize, "KRBTKFILE", ticket);
2264#endif /* KRB4 */
2265
2266 /* Set XAUTHORITY to always be a local file. */
2267 if (xauthfile)
2268 child_set_env(&env, &envsize, "XAUTHORITY", xauthfile);
2269
2270 /* Set variable for forwarded authentication connection, if we have one. */
2271 if (auth_get_socket_name() != NULL)
2272 child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
2273 auth_get_socket_name());
2274
2275 /* Read $HOME/.ssh/environment. */
2276 if(!options.use_login) {
2277 snprintf(buf, sizeof buf, "%.200s/.ssh/environment", pw->pw_dir);
2278 read_environment_file(&env, &envsize, buf);
2279 }
2280
2281 /* If debugging, dump the environment to stderr. */
2282 if (debug_flag)
2283 {
2284 fprintf(stderr, "Environment:\n");
2285 for (i = 0; env[i]; i++)
2286 fprintf(stderr, " %.200s\n", env[i]);
2287 }
2288
2289 /* Close the connection descriptors; note that this is the child, and the
2290 server will still have the socket open, and it is important that we
2291 do not shutdown it. Note that the descriptors cannot be closed before
2292 building the environment, as we call get_remote_ipaddr there. */
2293 if (packet_get_connection_in() == packet_get_connection_out())
2294 close(packet_get_connection_in());
2295 else
2296 {
2297 close(packet_get_connection_in());
2298 close(packet_get_connection_out());
2299 }
2300 /* Close all descriptors related to channels. They will still remain
2301 open in the parent. */
2302 channel_close_all();
2303
2304 /* Close any extra file descriptors. Note that there may still be
2305 descriptors left by system functions. They will be closed later. */
2306 endpwent();
2307 endhostent();
2308
2309 /* Close any extra open file descriptors so that we don\'t have them
2310 hanging around in clients. Note that we want to do this after
2311 initgroups, because at least on Solaris 2.3 it leaves file descriptors
2312 open. */
2313 for (i = 3; i < 64; i++)
2314 close(i);
2315
2316 /* Change current directory to the user\'s home directory. */
2317 if (chdir(pw->pw_dir) < 0)
2318 fprintf(stderr, "Could not chdir to home directory %s: %s\n",
2319 pw->pw_dir, strerror(errno));
2320
2321 /* Must take new environment into use so that .ssh/rc, /etc/sshrc and
2322 xauth are run in the proper environment. */
2323 environ = env;
2324
2325 /* Run $HOME/.ssh/rc, /etc/sshrc, or xauth (whichever is found first
2326 in this order). */
2327 if(!options.use_login) {
2328 if (stat(SSH_USER_RC, &st) >= 0)
2329 {
2330 if (debug_flag)
2331 fprintf(stderr, "Running /bin/sh %s\n", SSH_USER_RC);
2332
2333 f = popen("/bin/sh " SSH_USER_RC, "w");
2334 if (f)
2335 {
2336 if (auth_proto != NULL && auth_data != NULL)
2337 fprintf(f, "%s %s\n", auth_proto, auth_data);
2338 pclose(f);
2339 }
2340 else
2341 fprintf(stderr, "Could not run %s\n", SSH_USER_RC);
2342 }
2343 else
2344 if (stat(SSH_SYSTEM_RC, &st) >= 0)
2345 {
2346 if (debug_flag)
2347 fprintf(stderr, "Running /bin/sh %s\n", SSH_SYSTEM_RC);
2348
2349 f = popen("/bin/sh " SSH_SYSTEM_RC, "w");
2350 if (f)
2351 {
2352 if (auth_proto != NULL && auth_data != NULL)
2353 fprintf(f, "%s %s\n", auth_proto, auth_data);
2354 pclose(f);
2355 }
2356 else
2357 fprintf(stderr, "Could not run %s\n", SSH_SYSTEM_RC);
2358 }
2359#ifdef XAUTH_PATH
2360 else
2361 {
2362 /* Add authority data to .Xauthority if appropriate. */
2363 if (auth_proto != NULL && auth_data != NULL)
2364 {
2365 if (debug_flag)
2366 fprintf(stderr, "Running %.100s add %.100s %.100s %.100s\n",
2367 XAUTH_PATH, display, auth_proto, auth_data);
2368
2369 f = popen(XAUTH_PATH " -q -", "w");
2370 if (f)
2371 {
2372 fprintf(f, "add %s %s %s\n", display, auth_proto, auth_data);
2373 fclose(f);
2374 }
2375 else
2376 fprintf(stderr, "Could not run %s -q -\n", XAUTH_PATH);
2377 }
2378 }
2379#endif /* XAUTH_PATH */
2380
2381 /* Get the last component of the shell name. */
2382 cp = strrchr(shell, '/');
2383 if (cp)
2384 cp++;
2385 else
2386 cp = shell;
2387 }
2388
2389 /* If we have no command, execute the shell. In this case, the shell name
2390 to be passed in argv[0] is preceded by '-' to indicate that this is
2391 a login shell. */
2392 if (!command)
2393 {
2394 if(!options.use_login) {
2395 char buf[256];
2396
2397 /* Check for mail if we have a tty and it was enabled in server options. */
2398 if (ttyname && options.check_mail) {
2399 char *mailbox;
2400 struct stat mailstat;
2401 mailbox = getenv("MAIL");
2402 if(mailbox != NULL) {
2403 if(stat(mailbox, &mailstat) != 0 || mailstat.st_size == 0) {
2404 printf("No mail.\n");
2405 } else if(mailstat.st_mtime < mailstat.st_atime) {
2406 printf("You have mail.\n");
2407 } else {
2408 printf("You have new mail.\n");
2409 }
2410 }
2411 }
2412 /* Start the shell. Set initial character to '-'. */
2413 buf[0] = '-';
2414 strncpy(buf + 1, cp, sizeof(buf) - 1);
2415 buf[sizeof(buf) - 1] = 0;
2416 /* Execute the shell. */
2417 argv[0] = buf;
2418 argv[1] = NULL;
2419 execve(shell, argv, env);
2420 /* Executing the shell failed. */
2421 perror(shell);
2422 exit(1);
2423
2424 } else {
2425 /* Launch login(1). */
2426
2427 execl("/usr/bin/login", "login", "-h", get_remote_ipaddr(), "-p", "-f", "--", pw->pw_name, NULL);
2428
2429 /* Login couldn't be executed, die. */
2430
2431 perror("login");
2432 exit(1);
2433 }
2434 }
2435
2436 /* Execute the command using the user's shell. This uses the -c option
2437 to execute the command. */
2438 argv[0] = (char *)cp;
2439 argv[1] = "-c";
2440 argv[2] = (char *)command;
2441 argv[3] = NULL;
2442 execve(shell, argv, env);
2443 perror(shell);
2444 exit(1);
2445}
diff --git a/sshd.init b/sshd.init
new file mode 100755
index 000000000..b36b57aa6
--- /dev/null
+++ b/sshd.init
@@ -0,0 +1,49 @@
1#!/bin/bash
2
3# Init file for OpenSSH sshd
4#
5# chkconfig: 2345 55 25
6# description: OpenSSH server daemon
7#
8# processname: sshd
9# config: /etc/ssh/ssh_host_key
10# config: /etc/ssh/ssh_host_key.pub
11# config: /etc/ssh/ssh_random_seed
12# config: /etc/ssh/sshd_config
13# pidfile: /var/run/sshd.pid
14
15# source function library
16. /etc/rc.d/init.d/functions
17
18RETVAL=0
19
20case "$1" in
21 start)
22 echo -n "Starting sshd: "
23 daemon /usr/sbin/sshd
24 RETVAL=$?
25 [ $RETVAL -eq 0 ] && touch /var/lock/subsys/sshd
26 echo
27 ;;
28 stop)
29 echo -n "Shutting down sshd: "
30 killproc sshd
31 RETVAL=$?
32 [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/sshd
33 echo
34 ;;
35 restart)
36 $0 stop
37 $0 start
38 RETVAL=$?
39 ;;
40 status)
41 status sshd
42 RETVAL=$?
43 ;;
44 *)
45 echo "Usage: sshd {start|stop|restart|status}"
46 exit 1
47esac
48
49exit $RETVAL
diff --git a/sshd_config b/sshd_config
new file mode 100644
index 000000000..97f6f8e1c
--- /dev/null
+++ b/sshd_config
@@ -0,0 +1,44 @@
1# This is ssh server systemwide configuration file.
2
3Port 22
4ListenAddress 0.0.0.0
5HostKey /etc/ssh/ssh_host_key
6ServerKeyBits 768
7LoginGraceTime 600
8KeyRegenerationInterval 3600
9PermitRootLogin yes
10#
11# Don't read ~/.rhosts and ~/.shosts files
12IgnoreRhosts yes
13StrictModes yes
14QuietMode no
15X11Forwarding yes
16X11DisplayOffset 10
17FascistLogging no
18PrintMotd yes
19KeepAlive yes
20SyslogFacility AUTH
21RhostsAuthentication no
22#
23# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
24RhostsRSAAuthentication no
25#
26RSAAuthentication yes
27
28# To disable tunneled clear text passwords, change to no here!
29PasswordAuthentication yes
30PermitEmptyPasswords no
31# Uncomment to disable s/key passwords
32#SkeyAuthentication no
33
34# To change Kerberos options
35#KerberosAuthentication no
36#KerberosOrLocalPasswd yes
37#AFSTokenPassing no
38#KerberosTicketCleanup no
39
40# Kerberos TGT Passing does only work with the AFS kaserver
41#KerberosTgtPassing yes
42
43#CheckMail yes
44#UseLogin no
diff --git a/strlcpy.c b/strlcpy.c
new file mode 100644
index 000000000..300a28bc3
--- /dev/null
+++ b/strlcpy.c
@@ -0,0 +1,68 @@
1/* $OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $ */
2
3/*
4 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <string.h>
36
37/*
38 * Copy src to string dst of size siz. At most siz-1 characters
39 * will be copied. Always NUL terminates (unless siz == 0).
40 * Returns strlen(src); if retval >= siz, truncation occurred.
41 */
42size_t strlcpy(dst, src, siz)
43 char *dst;
44 const char *src;
45 size_t siz;
46{
47 register char *d = dst;
48 register const char *s = src;
49 register size_t n = siz;
50
51 /* Copy as many bytes as will fit */
52 if (n != 0 && --n != 0) {
53 do {
54 if ((*d++ = *s++) == 0)
55 break;
56 } while (--n != 0);
57 }
58
59 /* Not enough room in dst, add NUL and traverse rest of src */
60 if (n == 0) {
61 if (siz != 0)
62 *d = '\0'; /* NUL-terminate dst */
63 while (*s++)
64 ;
65 }
66
67 return(s - src - 1); /* count does not include NUL */
68}
diff --git a/strlcpy.h b/strlcpy.h
new file mode 100644
index 000000000..824df300c
--- /dev/null
+++ b/strlcpy.h
@@ -0,0 +1,4 @@
1#ifndef _STRLCPY_H
2#define _STRLCPY_H
3size_t strlcpy(char *dst, const char *src, size_t siz);
4#endif /* _STRLCPY_H */
diff --git a/tildexpand.c b/tildexpand.c
new file mode 100644
index 000000000..e4b57091e
--- /dev/null
+++ b/tildexpand.c
@@ -0,0 +1,70 @@
1/*
2
3tildexpand.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Wed Jul 12 01:07:36 1995 ylo
11
12*/
13
14#include "includes.h"
15RCSID("$Id: tildexpand.c,v 1.1 1999/10/27 03:42:46 damien Exp $");
16
17#include "xmalloc.h"
18#include "ssh.h"
19
20/* Expands tildes in the file name. Returns data allocated by xmalloc.
21 Warning: this calls getpw*. */
22
23char *tilde_expand_filename(const char *filename, uid_t my_uid)
24{
25 const char *cp;
26 unsigned int userlen;
27 char *expanded;
28 struct passwd *pw;
29 char user[100];
30
31 /* Return immediately if no tilde. */
32 if (filename[0] != '~')
33 return xstrdup(filename);
34
35 /* Skip the tilde. */
36 filename++;
37
38 /* Find where the username ends. */
39 cp = strchr(filename, '/');
40 if (cp)
41 userlen = cp - filename; /* Have something after username. */
42 else
43 userlen = strlen(filename); /* Nothign after username. */
44 if (userlen == 0)
45 pw = getpwuid(my_uid); /* Own home directory. */
46 else
47 {
48 /* Tilde refers to someone elses home directory. */
49 if (userlen > sizeof(user) - 1)
50 fatal("User name after tilde too long.");
51 memcpy(user, filename, userlen);
52 user[userlen] = 0;
53 pw = getpwnam(user);
54 }
55
56 /* Check that we found the user. */
57 if (!pw)
58 fatal("Unknown user %100s.", user);
59
60 /* If referring to someones home directory, return it now. */
61 if (!cp)
62 { /* Only home directory specified */
63 return xstrdup(pw->pw_dir);
64 }
65
66 /* Build a path combining the specified directory and path. */
67 expanded = xmalloc(strlen(pw->pw_dir) + strlen(cp + 1) + 2);
68 sprintf(expanded, "%s/%s", pw->pw_dir, cp + 1);
69 return expanded;
70}
diff --git a/ttymodes.c b/ttymodes.c
new file mode 100644
index 000000000..cbb7f2f64
--- /dev/null
+++ b/ttymodes.c
@@ -0,0 +1,359 @@
1/*
2
3ttymodes.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Tue Mar 21 15:59:15 1995 ylo
11
12Encoding and decoding of terminal modes in a portable way.
13Much of the format is defined in ttymodes.h; it is included multiple times
14into this file with the appropriate macro definitions to generate the
15suitable code.
16
17*/
18
19#include "includes.h"
20RCSID("$Id: ttymodes.c,v 1.1 1999/10/27 03:42:46 damien Exp $");
21
22#include "packet.h"
23#include "ssh.h"
24
25#define TTY_OP_END 0
26#define TTY_OP_ISPEED 192 /* int follows */
27#define TTY_OP_OSPEED 193 /* int follows */
28
29/* Converts POSIX speed_t to a baud rate. The values of the constants
30 for speed_t are not themselves portable. */
31
32static int speed_to_baud(speed_t speed)
33{
34 switch (speed)
35 {
36 case B0:
37 return 0;
38 case B50:
39 return 50;
40 case B75:
41 return 75;
42 case B110:
43 return 110;
44 case B134:
45 return 134;
46 case B150:
47 return 150;
48 case B200:
49 return 200;
50 case B300:
51 return 300;
52 case B600:
53 return 600;
54 case B1200:
55 return 1200;
56 case B1800:
57 return 1800;
58 case B2400:
59 return 2400;
60 case B4800:
61 return 4800;
62 case B9600:
63 return 9600;
64
65#ifdef B19200
66 case B19200:
67 return 19200;
68#else /* B19200 */
69#ifdef EXTA
70 case EXTA:
71 return 19200;
72#endif /* EXTA */
73#endif /* B19200 */
74
75#ifdef B38400
76 case B38400:
77 return 38400;
78#else /* B38400 */
79#ifdef EXTB
80 case EXTB:
81 return 38400;
82#endif /* EXTB */
83#endif /* B38400 */
84
85#ifdef B7200
86 case B7200:
87 return 7200;
88#endif /* B7200 */
89#ifdef B14400
90 case B14400:
91 return 14400;
92#endif /* B14400 */
93#ifdef B28800
94 case B28800:
95 return 28800;
96#endif /* B28800 */
97#ifdef B57600
98 case B57600:
99 return 57600;
100#endif /* B57600 */
101#ifdef B76800
102 case B76800:
103 return 76800;
104#endif /* B76800 */
105#ifdef B115200
106 case B115200:
107 return 115200;
108#endif /* B115200 */
109#ifdef B230400
110 case B230400:
111 return 230400;
112#endif /* B230400 */
113 default:
114 return 9600;
115 }
116}
117
118/* Converts a numeric baud rate to a POSIX speed_t. */
119
120static speed_t baud_to_speed(int baud)
121{
122 switch (baud)
123 {
124 case 0:
125 return B0;
126 case 50:
127 return B50;
128 case 75:
129 return B75;
130 case 110:
131 return B110;
132 case 134:
133 return B134;
134 case 150:
135 return B150;
136 case 200:
137 return B200;
138 case 300:
139 return B300;
140 case 600:
141 return B600;
142 case 1200:
143 return B1200;
144 case 1800:
145 return B1800;
146 case 2400:
147 return B2400;
148 case 4800:
149 return B4800;
150 case 9600:
151 return B9600;
152
153#ifdef B19200
154 case 19200:
155 return B19200;
156#else /* B19200 */
157#ifdef EXTA
158 case 19200:
159 return EXTA;
160#endif /* EXTA */
161#endif /* B19200 */
162
163#ifdef B38400
164 case 38400:
165 return B38400;
166#else /* B38400 */
167#ifdef EXTB
168 case 38400:
169 return EXTB;
170#endif /* EXTB */
171#endif /* B38400 */
172
173#ifdef B7200
174 case 7200:
175 return B7200;
176#endif /* B7200 */
177#ifdef B14400
178 case 14400:
179 return B14400;
180#endif /* B14400 */
181#ifdef B28800
182 case 28800:
183 return B28800;
184#endif /* B28800 */
185#ifdef B57600
186 case 57600:
187 return B57600;
188#endif /* B57600 */
189#ifdef B76800
190 case 76800:
191 return B76800;
192#endif /* B76800 */
193#ifdef B115200
194 case 115200:
195 return B115200;
196#endif /* B115200 */
197#ifdef B230400
198 case 230400:
199 return B230400;
200#endif /* B230400 */
201 default:
202 return B9600;
203 }
204}
205
206/* Encodes terminal modes for the terminal referenced by fd in a portable
207 manner, and appends the modes to a packet being constructed. */
208
209void tty_make_modes(int fd)
210{
211 struct termios tio;
212 int baud;
213
214 /* Get the modes. */
215 if (tcgetattr(fd, &tio) < 0)
216 {
217 packet_put_char(TTY_OP_END);
218 log("tcgetattr: %.100s", strerror(errno));
219 return;
220 }
221
222 /* Store input and output baud rates. */
223 baud = speed_to_baud(cfgetospeed(&tio));
224 packet_put_char(TTY_OP_OSPEED);
225 packet_put_int(baud);
226 baud = speed_to_baud(cfgetispeed(&tio));
227 packet_put_char(TTY_OP_ISPEED);
228 packet_put_int(baud);
229
230 /* Store values of mode flags. */
231#define TTYCHAR(NAME, OP) \
232 packet_put_char(OP); packet_put_char(tio.c_cc[NAME]);
233#define TTYMODE(NAME, FIELD, OP) \
234 packet_put_char(OP); packet_put_char((tio.FIELD & NAME) != 0);
235#define SGTTYCHAR(NAME, OP)
236#define SGTTYMODE(NAME, FIELD, OP)
237#define SGTTYMODEN(NAME, FIELD, OP)
238
239#include "ttymodes.h"
240
241#undef TTYCHAR
242#undef TTYMODE
243#undef SGTTYCHAR
244#undef SGTTYMODE
245#undef SGTTYMODEN
246
247 /* Mark end of mode data. */
248 packet_put_char(TTY_OP_END);
249}
250
251/* Decodes terminal modes for the terminal referenced by fd in a portable
252 manner from a packet being read. */
253
254void tty_parse_modes(int fd, int *n_bytes_ptr)
255{
256 struct termios tio;
257 int opcode, baud;
258 int n_bytes = 0;
259 int failure = 0;
260
261 /* Get old attributes for the terminal. We will modify these flags.
262 I am hoping that if there are any machine-specific modes, they will
263 initially have reasonable values. */
264 if (tcgetattr(fd, &tio) < 0)
265 failure = -1;
266
267 for (;;)
268 {
269 n_bytes += 1;
270 opcode = packet_get_char();
271 switch (opcode)
272 {
273 case TTY_OP_END:
274 goto set;
275
276 case TTY_OP_ISPEED:
277 n_bytes += 4;
278 baud = packet_get_int();
279 if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) < 0)
280 error("cfsetispeed failed for %d", baud);
281 break;
282
283 case TTY_OP_OSPEED:
284 n_bytes += 4;
285 baud = packet_get_int();
286 if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) < 0)
287 error("cfsetospeed failed for %d", baud);
288 break;
289
290#define TTYCHAR(NAME, OP) \
291 case OP: \
292 n_bytes += 1; \
293 tio.c_cc[NAME] = packet_get_char(); \
294 break;
295#define TTYMODE(NAME, FIELD, OP) \
296 case OP: \
297 n_bytes += 1; \
298 if (packet_get_char()) \
299 tio.FIELD |= NAME; \
300 else \
301 tio.FIELD &= ~NAME; \
302 break;
303#define SGTTYCHAR(NAME, OP)
304#define SGTTYMODE(NAME, FIELD, OP)
305#define SGTTYMODEN(NAME, FIELD, OP)
306
307#include "ttymodes.h"
308
309#undef TTYCHAR
310#undef TTYMODE
311#undef SGTTYCHAR
312#undef SGTTYMODE
313#undef SGTTYMODEN
314
315 default:
316 debug("Ignoring unsupported tty mode opcode %d (0x%x)",
317 opcode, opcode);
318 /* Opcodes 0 to 127 are defined to have a one-byte argument. */
319 if (opcode >= 0 && opcode < 128)
320 {
321 n_bytes += 1;
322 (void)packet_get_char();
323 break;
324 }
325 else
326 {
327 /* Opcodes 128 to 159 are defined to have an integer argument. */
328 if (opcode >= 128 && opcode < 160)
329 {
330 n_bytes += 4;
331 (void)packet_get_int();
332 break;
333 }
334 }
335 /* It is a truly undefined opcode (160 to 255). We have no idea
336 about its arguments. So we must stop parsing. Note that some
337 data may be left in the packet; hopefully there is nothing more
338 coming after the mode data. */
339 log("parse_tty_modes: unknown opcode %d", opcode);
340 packet_integrity_check(0, 1, SSH_CMSG_REQUEST_PTY);
341 goto set;
342 }
343 }
344
345 set:
346 if (*n_bytes_ptr != n_bytes)
347 {
348 *n_bytes_ptr = n_bytes;
349 return; /* Don't process bytes passed */
350 }
351
352 if (failure == -1)
353 return; /* Packet parsed ok but tty stuff failed */
354
355 /* Set the new modes for the terminal. */
356 if (tcsetattr(fd, TCSANOW, &tio) < 0)
357 log("Setting tty modes failed: %.100s", strerror(errno));
358 return;
359}
diff --git a/ttymodes.h b/ttymodes.h
new file mode 100644
index 000000000..2a33eb78d
--- /dev/null
+++ b/ttymodes.h
@@ -0,0 +1,138 @@
1/*
2
3ttymodes.h
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6 SGTTY stuff contributed by Janne Snabb <snabb@niksula.hut.fi>
7
8Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
9 All rights reserved
10
11Created: Tue Mar 21 15:42:09 1995 ylo
12
13*/
14
15/* RCSID("$Id: ttymodes.h,v 1.1 1999/10/27 03:42:46 damien Exp $"); */
16
17/* The tty mode description is a stream of bytes. The stream consists of
18 opcode-arguments pairs. It is terminated by opcode TTY_OP_END (0).
19 Opcodes 1-127 have one-byte arguments. Opcodes 128-159 have integer
20 arguments. Opcodes 160-255 are not yet defined, and cause parsing to
21 stop (they should only be used after any other data).
22
23 The client puts in the stream any modes it knows about, and the
24 server ignores any modes it does not know about. This allows some degree
25 of machine-independence, at least between systems that use a posix-like
26 tty interface. The protocol can support other systems as well, but might
27 require reimplementing as mode names would likely be different. */
28
29/* Some constants and prototypes are defined in packet.h; this file
30 is only intended for including from ttymodes.h. */
31
32/* termios macro */ /* sgtty macro */
33/* name, op */
34TTYCHAR(VINTR, 1) SGTTYCHAR(tiotc.t_intrc, 1)
35TTYCHAR(VQUIT, 2) SGTTYCHAR(tiotc.t_quitc, 2)
36TTYCHAR(VERASE, 3) SGTTYCHAR(tio.sg_erase, 3)
37#if defined(VKILL)
38TTYCHAR(VKILL, 4) SGTTYCHAR(tio.sg_kill, 4)
39#endif /* VKILL */
40TTYCHAR(VEOF, 5) SGTTYCHAR(tiotc.t_eofc, 5)
41#if defined(VEOL)
42TTYCHAR(VEOL, 6) SGTTYCHAR(tiotc.t_brkc, 6)
43#endif /* VEOL */
44#ifdef VEOL2 /* n/a */
45TTYCHAR(VEOL2, 7)
46#endif /* VEOL2 */
47TTYCHAR(VSTART, 8) SGTTYCHAR(tiotc.t_startc, 8)
48TTYCHAR(VSTOP, 9) SGTTYCHAR(tiotc.t_stopc, 9)
49#if defined(VSUSP)
50TTYCHAR(VSUSP, 10) SGTTYCHAR(tioltc.t_suspc, 10)
51#endif /* VSUSP */
52#if defined(VDSUSP)
53TTYCHAR(VDSUSP, 11) SGTTYCHAR(tioltc.t_dsuspc, 11)
54#endif /* VDSUSP */
55#if defined(VREPRINT)
56TTYCHAR(VREPRINT, 12) SGTTYCHAR(tioltc.t_rprntc, 12)
57#endif /* VREPRINT */
58#if defined(VWERASE)
59TTYCHAR(VWERASE, 13) SGTTYCHAR(tioltc.t_werasc, 13)
60#endif /* VWERASE */
61#if defined(VLNEXT)
62TTYCHAR(VLNEXT, 14) SGTTYCHAR(tioltc.t_lnextc, 14)
63#endif /* VLNEXT */
64#if defined(VFLUSH)
65TTYCHAR(VFLUSH, 15) SGTTYCHAR(tioltc.t_flushc, 15)
66#endif /* VFLUSH */
67#ifdef VSWTCH
68TTYCHAR(VSWTCH, 16) /* n/a */
69#endif /* VSWTCH */
70#if defined(VSTATUS)
71TTYCHAR(VSTATUS, 17) SGTTYCHAR(tiots.tc_statusc, 17)
72#endif /* VSTATUS */
73#ifdef VDISCARD
74TTYCHAR(VDISCARD, 18) /* n/a */
75#endif /* VDISCARD */
76
77/* name, field, op */
78TTYMODE(IGNPAR, c_iflag, 30) /* n/a */
79TTYMODE(PARMRK, c_iflag, 31) /* n/a */
80TTYMODE(INPCK, c_iflag, 32) SGTTYMODEN(ANYP, tio.sg_flags, 32)
81TTYMODE(ISTRIP, c_iflag, 33) SGTTYMODEN(LPASS8, tiolm, 33)
82TTYMODE(INLCR, c_iflag, 34) /* n/a */
83TTYMODE(IGNCR, c_iflag, 35) /* n/a */
84TTYMODE(ICRNL, c_iflag, 36) SGTTYMODE(CRMOD, tio.sg_flags, 36)
85#if defined(IUCLC)
86TTYMODE(IUCLC, c_iflag, 37) SGTTYMODE(LCASE, tio.sg_flags, 37)
87#endif
88TTYMODE(IXON, c_iflag, 38) /* n/a */
89TTYMODE(IXANY, c_iflag, 39) SGTTYMODEN(LDECCTQ, tiolm, 39)
90TTYMODE(IXOFF, c_iflag, 40) SGTTYMODE(TANDEM, tio.sg_flags, 40)
91#ifdef IMAXBEL
92TTYMODE(IMAXBEL,c_iflag, 41) /* n/a */
93#endif /* IMAXBEL */
94
95TTYMODE(ISIG, c_lflag, 50) /* n/a */
96TTYMODE(ICANON, c_lflag, 51) SGTTYMODEN(CBREAK, tio.sg_flags, 51)
97#ifdef XCASE
98TTYMODE(XCASE, c_lflag, 52) /* n/a */
99#endif
100TTYMODE(ECHO, c_lflag, 53) SGTTYMODE(ECHO, tio.sg_flags, 53)
101TTYMODE(ECHOE, c_lflag, 54) SGTTYMODE(LCRTERA, tiolm, 54)
102TTYMODE(ECHOK, c_lflag, 55) SGTTYMODE(LCRTKIL, tiolm, 55)
103TTYMODE(ECHONL, c_lflag, 56) /* n/a */
104TTYMODE(NOFLSH, c_lflag, 57) SGTTYMODE(LNOFLSH, tiolm, 57)
105TTYMODE(TOSTOP, c_lflag, 58) SGTTYMODE(LTOSTOP, tiolm, 58)
106#ifdef IEXTEN
107TTYMODE(IEXTEN, c_lflag, 59) /* n/a */
108#endif /* IEXTEN */
109#if defined(ECHOCTL)
110TTYMODE(ECHOCTL,c_lflag, 60) SGTTYMODE(LCTLECH, tiolm, 60)
111#endif /* ECHOCTL */
112#ifdef ECHOKE
113TTYMODE(ECHOKE, c_lflag, 61) /* n/a */
114#endif /* ECHOKE */
115#if defined(PENDIN)
116TTYMODE(PENDIN, c_lflag, 62) SGTTYMODE(LPENDIN, tiolm, 62)
117#endif /* PENDIN */
118
119TTYMODE(OPOST, c_oflag, 70) /* n/a */
120#if defined(OLCUC)
121TTYMODE(OLCUC, c_oflag, 71) SGTTYMODE(LCASE, tio.sg_flags, 71)
122#endif
123TTYMODE(ONLCR, c_oflag, 72) SGTTYMODE(CRMOD, tio.sg_flags, 72)
124#ifdef OCRNL
125TTYMODE(OCRNL, c_oflag, 73) /* n/a */
126#endif
127#ifdef ONOCR
128TTYMODE(ONOCR, c_oflag, 74) /* n/a */
129#endif
130#ifdef ONLRET
131TTYMODE(ONLRET, c_oflag, 75) /* n/a */
132#endif
133
134TTYMODE(CS7, c_cflag, 90) /* n/a */
135TTYMODE(CS8, c_cflag, 91) SGTTYMODE(LPASS8, tiolm, 91)
136TTYMODE(PARENB, c_cflag, 92) /* n/a */
137TTYMODE(PARODD, c_cflag, 93) SGTTYMODE(ODDP, tio.sg_flags, 93)
138
diff --git a/uidswap.c b/uidswap.c
new file mode 100644
index 000000000..0eb1fd085
--- /dev/null
+++ b/uidswap.c
@@ -0,0 +1,95 @@
1/*
2
3uidswap.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Sat Sep 9 01:56:14 1995 ylo
11
12Code for uid-swapping.
13
14*/
15
16#include "includes.h"
17RCSID("$Id: uidswap.c,v 1.1 1999/10/27 03:42:46 damien Exp $");
18
19#include "ssh.h"
20#include "uidswap.h"
21
22/* Note: all these functions must work in all of the following cases:
23
24 1. euid=0, ruid=0
25 2. euid=0, ruid!=0
26 3. euid!=0, ruid!=0
27
28 Additionally, they must work regardless of whether the system has
29 POSIX saved uids or not. */
30
31#ifdef _POSIX_SAVED_IDS
32/* Lets assume that posix saved ids also work with seteuid, even though that
33 is not part of the posix specification. */
34#define SAVED_IDS_WORK_WITH_SETEUID
35#endif /* _POSIX_SAVED_IDS */
36
37/* Saved effective uid. */
38static uid_t saved_euid = 0;
39
40/* Temporarily changes to the given uid. If the effective user id is not
41 root, this does nothing. This call cannot be nested. */
42
43void temporarily_use_uid(uid_t uid)
44{
45#ifdef SAVED_IDS_WORK_WITH_SETEUID
46
47 /* Save the current euid. */
48 saved_euid = geteuid();
49
50 /* Set the effective uid to the given (unprivileged) uid. */
51 if (seteuid(uid) == -1)
52 debug("seteuid %d: %.100s", (int)uid, strerror(errno));
53
54#else /* SAVED_IDS_WORK_WITH_SETUID */
55
56 /* Propagate the privileged uid to all of our uids. */
57 if (setuid(geteuid()) < 0)
58 debug("setuid %d: %.100s", (int)geteuid(), strerror(errno));
59
60 /* Set the effective uid to the given (unprivileged) uid. */
61 if (seteuid(uid) == -1)
62 debug("seteuid %d: %.100s", (int)uid, strerror(errno));
63
64#endif /* SAVED_IDS_WORK_WITH_SETEUID */
65
66}
67
68/* Restores to the original uid. */
69
70void restore_uid()
71{
72#ifdef SAVED_IDS_WORK_WITH_SETEUID
73
74 /* Set the effective uid back to the saved uid. */
75 if (seteuid(saved_euid) < 0)
76 debug("seteuid %d: %.100s", (int)saved_euid, strerror(errno));
77
78#else /* SAVED_IDS_WORK_WITH_SETEUID */
79
80 /* We are unable to restore the real uid to its unprivileged value. */
81 /* Propagate the real uid (usually more privileged) to effective uid
82 as well. */
83 setuid(getuid());
84
85#endif /* SAVED_IDS_WORK_WITH_SETEUID */
86}
87
88/* Permanently sets all uids to the given uid. This cannot be called while
89 temporarily_use_uid is effective. */
90
91void permanently_set_uid(uid_t uid)
92{
93 if (setuid(uid) < 0)
94 debug("setuid %d: %.100s", (int)uid, strerror(errno));
95}
diff --git a/uidswap.h b/uidswap.h
new file mode 100644
index 000000000..af4f924f0
--- /dev/null
+++ b/uidswap.h
@@ -0,0 +1,30 @@
1/*
2
3uidswap.h
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Sat Sep 9 01:43:15 1995 ylo
11Last modified: Sat Sep 9 02:34:04 1995 ylo
12
13*/
14
15#ifndef UIDSWAP_H
16#define UIDSWAP_H
17
18/* Temporarily changes to the given uid. If the effective user id is not
19 root, this does nothing. This call cannot be nested. */
20void temporarily_use_uid(uid_t uid);
21
22/* Restores the original effective user id after temporarily_use_uid().
23 This should only be called while temporarily_use_uid is effective. */
24void restore_uid();
25
26/* Permanently sets all uids to the given uid. This cannot be called while
27 temporarily_use_uid is effective. This must also clear any saved uids. */
28void permanently_set_uid(uid_t uid);
29
30#endif /* UIDSWAP_H */
diff --git a/version.h b/version.h
new file mode 100644
index 000000000..8d2fc5c2c
--- /dev/null
+++ b/version.h
@@ -0,0 +1 @@
#define SSH_VERSION "OpenSSH-1.2"
diff --git a/xmalloc.c b/xmalloc.c
new file mode 100644
index 000000000..b536f9d19
--- /dev/null
+++ b/xmalloc.c
@@ -0,0 +1,56 @@
1/*
2
3xmalloc.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Mon Mar 20 21:23:10 1995 ylo
11
12Versions of malloc and friends that check their results, and never return
13failure (they call fatal if they encounter an error).
14
15*/
16
17#include "includes.h"
18RCSID("$Id: xmalloc.c,v 1.1 1999/10/27 03:42:46 damien Exp $");
19
20#include "ssh.h"
21
22void *xmalloc(size_t size)
23{
24 void *ptr = malloc(size);
25 if (ptr == NULL)
26 fatal("xmalloc: out of memory (allocating %d bytes)", (int)size);
27 return ptr;
28}
29
30void *xrealloc(void *ptr, size_t new_size)
31{
32 void *new_ptr;
33
34 if (ptr == NULL)
35 fatal("xrealloc: NULL pointer given as argument");
36 new_ptr = realloc(ptr, new_size);
37 if (new_ptr == NULL)
38 fatal("xrealloc: out of memory (new_size %d bytes)", (int)new_size);
39 return new_ptr;
40}
41
42void xfree(void *ptr)
43{
44 if (ptr == NULL)
45 fatal("xfree: NULL pointer given as argument");
46 free(ptr);
47}
48
49char *xstrdup(const char *str)
50{
51 int len = strlen(str) + 1;
52
53 char *cp = xmalloc(len);
54 strlcpy(cp, str, len);
55 return cp;
56}
diff --git a/xmalloc.h b/xmalloc.h
new file mode 100644
index 000000000..7a9610e7e
--- /dev/null
+++ b/xmalloc.h
@@ -0,0 +1,34 @@
1/*
2
3xmalloc.h
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Mon Mar 20 22:09:17 1995 ylo
11
12Versions of malloc and friends that check their results, and never return
13failure (they call fatal if they encounter an error).
14
15*/
16
17/* RCSID("$Id: xmalloc.h,v 1.1 1999/10/27 03:42:46 damien Exp $"); */
18
19#ifndef XMALLOC_H
20#define XMALLOC_H
21
22/* Like malloc, but calls fatal() if out of memory. */
23void *xmalloc(size_t size);
24
25/* Like realloc, but calls fatal() if out of memory. */
26void *xrealloc(void *ptr, size_t new_size);
27
28/* Frees memory allocated using xmalloc or xrealloc. */
29void xfree(void *ptr);
30
31/* Allocates memory using xmalloc, and copies the string into that memory. */
32char *xstrdup(const char *str);
33
34#endif /* XMALLOC_H */