Vendor import of OpenSSH 5.1p1
This commit is contained in:
parent
d4033b6b6f
commit
5521539314
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor-crypto/openssh/dist/; revision=180750
861
ChangeLog
861
ChangeLog
@ -1,3 +1,862 @@
|
||||
20080721
|
||||
- (djm) OpenBSD CVS Sync
|
||||
- jmc@cvs.openbsd.org 2008/07/18 22:51:01
|
||||
[sftp-server.8]
|
||||
no need for .Pp before or after .Sh;
|
||||
- djm@cvs.openbsd.org 2008/07/21 08:19:07
|
||||
[version.h]
|
||||
openssh-5.1
|
||||
- (djm) [README contrib/caldera/openssh.spec contrib/redhat/openssh.spec]
|
||||
[contrib/suse/openssh.spec] Update version number in README and RPM specs
|
||||
- (djm) Release OpenSSH-5.1
|
||||
|
||||
20080717
|
||||
- (djm) OpenBSD CVS Sync
|
||||
- djm@cvs.openbsd.org 2008/07/17 08:48:00
|
||||
[sshconnect2.c]
|
||||
strnvis preauth banner; pointed out by mpf@ ok markus@
|
||||
- djm@cvs.openbsd.org 2008/07/17 08:51:07
|
||||
[auth2-hostbased.c]
|
||||
strip trailing '.' from hostname when HostbasedUsesNameFromPacketOnly=yes
|
||||
report and patch from res AT qoxp.net (bz#1200); ok markus@
|
||||
- (dtucker) [openbsd-compat/bsd-cygwin_util.c] Remove long-unneeded compat
|
||||
code, replace with equivalent cygwin library call. Patch from vinschen
|
||||
at redhat.com, ok djm@.
|
||||
- (djm) [sshconnect2.c] vis.h isn't available everywhere
|
||||
|
||||
20080716
|
||||
- OpenBSD CVS Sync
|
||||
- djm@cvs.openbsd.org 2008/07/15 02:23:14
|
||||
[sftp.1]
|
||||
number of pipelined requests is now 64;
|
||||
prodded by Iain.Morgan AT nasa.gov
|
||||
- djm@cvs.openbsd.org 2008/07/16 11:51:14
|
||||
[clientloop.c]
|
||||
rename variable first_gc -> last_gc (since it is actually the last
|
||||
in the list).
|
||||
- djm@cvs.openbsd.org 2008/07/16 11:52:19
|
||||
[channels.c]
|
||||
this loop index should be automatic, not static
|
||||
|
||||
20080714
|
||||
- (djm) OpenBSD CVS Sync
|
||||
- sthen@cvs.openbsd.org 2008/07/13 21:22:52
|
||||
[ssh-keygen.c]
|
||||
Change "ssh-keygen -F [host] -l" to not display random art unless
|
||||
-v is also specified, making it consistent with the manual and other
|
||||
uses of -l.
|
||||
ok grunk@
|
||||
- djm@cvs.openbsd.org 2008/07/13 22:13:07
|
||||
[channels.c]
|
||||
use struct sockaddr_storage instead of struct sockaddr for accept(2)
|
||||
address argument. from visibilis AT yahoo.com in bz#1485; ok markus@
|
||||
- djm@cvs.openbsd.org 2008/07/13 22:16:03
|
||||
[sftp.c]
|
||||
increase number of piplelined requests so they properly fill the
|
||||
(recently increased) channel window. prompted by rapier AT psc.edu;
|
||||
ok markus@
|
||||
- djm@cvs.openbsd.org 2008/07/14 01:55:56
|
||||
[sftp-server.8]
|
||||
mention requirement for /dev/log inside chroot when using sftp-server
|
||||
with ChrootDirectory
|
||||
- (djm) [openbsd-compat/bindresvport.c] Rename variables s/sin/in/ to
|
||||
avoid clash with sin(3) function; reported by
|
||||
cristian.ionescu-idbohrn AT axis.com
|
||||
- (djm) [openbsd-compat/rresvport.c] Add unistd.h for missing close()
|
||||
prototype; reported by cristian.ionescu-idbohrn AT axis.com
|
||||
- (djm) [umac.c] Rename variable s/buffer_ptr/bufp/ to avoid clash;
|
||||
reported by cristian.ionescu-idbohrn AT axis.com
|
||||
- (djm) [contrib/cygwin/Makefile contrib/cygwin/ssh-host-config]
|
||||
[contrib/cygwin/ssh-user-config contrib/cygwin/sshd-inetd]
|
||||
Revamped and simplified Cygwin ssh-host-config script that uses
|
||||
unified csih configuration tool. Requires recent Cygwin.
|
||||
Patch from vinschen AT redhat.com
|
||||
|
||||
20080712
|
||||
- (djm) OpenBSD CVS Sync
|
||||
- djm@cvs.openbsd.org 2008/07/12 04:52:50
|
||||
[channels.c]
|
||||
unbreak; move clearing of cctx struct to before first use
|
||||
reported by dkrause@
|
||||
- djm@cvs.openbsd.org 2008/07/12 05:33:41
|
||||
[scp.1]
|
||||
better description for -i flag:
|
||||
s/RSA authentication/public key authentication/
|
||||
- (djm) [openbsd-compat/fake-rfc2553.c openbsd-compat/fake-rfc2553.h]
|
||||
return EAI_FAMILY when trying to lookup unsupported address family;
|
||||
from vinschen AT redhat.com
|
||||
|
||||
20080711
|
||||
- (djm) OpenBSD CVS Sync
|
||||
- stevesk@cvs.openbsd.org 2008/07/07 00:31:41
|
||||
[ttymodes.c]
|
||||
we don't need arg after the debug3() was removed. from lint.
|
||||
ok djm@
|
||||
- stevesk@cvs.openbsd.org 2008/07/07 23:32:51
|
||||
[key.c]
|
||||
/*NOTREACHED*/ for lint warning:
|
||||
warning: function key_equal falls off bottom without returning value
|
||||
ok djm@
|
||||
- markus@cvs.openbsd.org 2008/07/10 18:05:58
|
||||
[channels.c]
|
||||
missing bzero; from mickey; ok djm@
|
||||
- markus@cvs.openbsd.org 2008/07/10 18:08:11
|
||||
[clientloop.c monitor.c monitor_wrap.c packet.c packet.h sshd.c]
|
||||
sync v1 and v2 traffic accounting; add it to sshd, too;
|
||||
ok djm@, dtucker@
|
||||
|
||||
20080709
|
||||
- (djm) [Makefile.in] Print "all tests passed" when all regress tests pass
|
||||
- (djm) [auth1.c] Fix format string vulnerability in protocol 1 PAM
|
||||
account check failure path. The vulnerable format buffer is supplied
|
||||
from PAM and should not contain attacker-supplied data.
|
||||
- (djm) [auth.c] Missing unistd.h for close()
|
||||
- (djm) [configure.ac] Add -Wformat-security to CFLAGS for gcc 3.x and 4.x
|
||||
|
||||
20080705
|
||||
- (djm) [auth.c] Fixed test for locked account on HP/UX with shadowed
|
||||
passwords disabled. bz#1083 report & patch from senthilkumar_sen AT
|
||||
hotpop.com, w/ dtucker@
|
||||
- (djm) [atomicio.c configure.ac] Disable poll() fallback in atomiciov for
|
||||
Tru64. readv doesn't seem to be a comparable object there.
|
||||
bz#1386, patch from dtucker@ ok me
|
||||
- (djm) [Makefile.in] Pass though pass to conch for interop tests
|
||||
- (djm) [configure.ac] unbreak: remove extra closing brace
|
||||
- (djm) OpenBSD CVS Sync
|
||||
- djm@cvs.openbsd.org 2008/07/04 23:08:25
|
||||
[packet.c]
|
||||
handle EINTR in packet_write_poll()l ok dtucker@
|
||||
- djm@cvs.openbsd.org 2008/07/04 23:30:16
|
||||
[auth1.c auth2.c]
|
||||
Make protocol 1 MaxAuthTries logic match protocol 2's.
|
||||
Do not treat the first protocol 2 authentication attempt as
|
||||
a failure IFF it is for method "none".
|
||||
Makes MaxAuthTries' user-visible behaviour identical for
|
||||
protocol 1 vs 2.
|
||||
ok dtucker@
|
||||
- djm@cvs.openbsd.org 2008/07/05 05:16:01
|
||||
[PROTOCOL]
|
||||
grammar
|
||||
|
||||
20080704
|
||||
- (dtucker) OpenBSD CVS Sync
|
||||
- djm@cvs.openbsd.org 2008/07/02 13:30:34
|
||||
[auth2.c]
|
||||
really really remove the freebie "none" auth try for protocol 2
|
||||
- djm@cvs.openbsd.org 2008/07/02 13:47:39
|
||||
[ssh.1 ssh.c]
|
||||
When forking after authentication ("ssh -f") with ExitOnForwardFailure
|
||||
enabled, delay the fork until after replies for any -R forwards have
|
||||
been seen. Allows for robust detection of -R forward failure when
|
||||
using -f (similar to bz#92); ok dtucker@
|
||||
- otto@cvs.openbsd.org 2008/07/03 21:46:58
|
||||
[auth2-pubkey.c]
|
||||
avoid nasty double free; ok dtucker@ djm@
|
||||
- djm@cvs.openbsd.org 2008/07/04 03:44:59
|
||||
[servconf.c groupaccess.h groupaccess.c]
|
||||
support negation of groups in "Match group" block (bz#1315); ok dtucker@
|
||||
- dtucker@cvs.openbsd.org 2008/07/04 03:47:02
|
||||
[monitor.c]
|
||||
Make debug a little clearer. ok djm@
|
||||
- djm@cvs.openbsd.org 2008/06/30 08:07:34
|
||||
[regress/key-options.sh]
|
||||
shell portability: use "=" instead of "==" in test(1) expressions,
|
||||
double-quote string with backslash escaped /
|
||||
- djm@cvs.openbsd.org 2008/06/30 10:31:11
|
||||
[regress/{putty-transfer,putty-kex,putty-ciphers}.sh]
|
||||
remove "set -e" left over from debugging
|
||||
- djm@cvs.openbsd.org 2008/06/30 10:43:03
|
||||
[regress/conch-ciphers.sh]
|
||||
explicitly disable conch options that could interfere with the test
|
||||
- (dtucker) [sftp-server.c] Bug #1447: fall back to racy rename if link
|
||||
returns EXDEV. Patch from Mike Garrison, ok djm@
|
||||
- (djm) [atomicio.c channels.c clientloop.c defines.h includes.h]
|
||||
[packet.c scp.c serverloop.c sftp-client.c ssh-agent.c ssh-keyscan.c]
|
||||
[sshd.c] Explicitly handle EWOULDBLOCK wherever we handle EAGAIN, on
|
||||
some platforms (HP nonstop) it is a distinct errno;
|
||||
bz#1467 reported by sconeu AT yahoo.com; ok dtucker@
|
||||
|
||||
20080702
|
||||
- (dtucker) OpenBSD CVS Sync
|
||||
- djm@cvs.openbsd.org 2008/06/30 08:05:59
|
||||
[PROTOCOL.agent]
|
||||
typo: s/constraint_date/constraint_data/
|
||||
- djm@cvs.openbsd.org 2008/06/30 12:15:39
|
||||
[serverloop.c]
|
||||
only pass channel requests on session channels through to the session
|
||||
channel handler, avoiding spurious log messages; ok! markus@
|
||||
- djm@cvs.openbsd.org 2008/06/30 12:16:02
|
||||
[nchan.c]
|
||||
only send eow@openssh.com notifications for session channels; ok! markus@
|
||||
- djm@cvs.openbsd.org 2008/06/30 12:18:34
|
||||
[PROTOCOL]
|
||||
clarify that eow@openssh.com is only sent on session channels
|
||||
- dtucker@cvs.openbsd.org 2008/07/01 07:20:52
|
||||
[sshconnect.c]
|
||||
Check ExitOnForwardFailure if forwardings are disabled due to a failed
|
||||
host key check. ok djm@
|
||||
- dtucker@cvs.openbsd.org 2008/07/01 07:24:22
|
||||
[sshconnect.c sshd.c]
|
||||
Send CR LF during protocol banner exchanges, but only for Protocol 2 only,
|
||||
in order to comply with RFC 4253. bz #1443, ok djm@
|
||||
- stevesk@cvs.openbsd.org 2008/07/01 23:12:47
|
||||
[PROTOCOL.agent]
|
||||
fix some typos; ok djm@
|
||||
- djm@cvs.openbsd.org 2008/07/02 02:24:18
|
||||
[sshd_config sshd_config.5 sshd.8 servconf.c]
|
||||
increase default size of ssh protocol 1 ephemeral key from 768 to 1024
|
||||
bits; prodded by & ok dtucker@ ok deraadt@
|
||||
- dtucker@cvs.openbsd.org 2008/07/02 12:03:51
|
||||
[auth-rsa.c auth.c auth2-pubkey.c auth.h]
|
||||
Merge duplicate host key file checks, based in part on a patch from Rob
|
||||
Holland via bz #1348 . Also checks for non-regular files during protocol
|
||||
1 RSA auth. ok djm@
|
||||
- djm@cvs.openbsd.org 2008/07/02 12:36:39
|
||||
[auth2-none.c auth2.c]
|
||||
Make protocol 2 MaxAuthTries behaviour a little more sensible:
|
||||
Check whether client has exceeded MaxAuthTries before running
|
||||
an authentication method and skip it if they have, previously it
|
||||
would always allow one try (for "none" auth).
|
||||
Preincrement failure count before post-auth test - previously this
|
||||
checked and postincremented, also to allow one "none" try.
|
||||
Together, these two changes always count the "none" auth method
|
||||
which could be skipped by a malicious client (e.g. an SSH worm)
|
||||
to get an extra attempt at a real auth method. They also make
|
||||
MaxAuthTries=0 a useful way to block users entirely (esp. in a
|
||||
sshd_config Match block).
|
||||
Also, move sending of any preauth banner from "none" auth method
|
||||
to the first call to input_userauth_request(), so worms that skip
|
||||
the "none" method get to see it too.
|
||||
|
||||
20080630
|
||||
- (djm) OpenBSD CVS Sync
|
||||
- dtucker@cvs.openbsd.org 2008/06/10 23:13:43
|
||||
[regress/Makefile regress/key-options.sh]
|
||||
Add regress test for key options. ok djm@
|
||||
- dtucker@cvs.openbsd.org 2008/06/11 23:11:40
|
||||
[regress/Makefile]
|
||||
Don't run cipher-speed test by default; mistakenly enabled by me
|
||||
- djm@cvs.openbsd.org 2008/06/28 13:57:25
|
||||
[regress/Makefile regress/test-exec.sh regress/conch-ciphers.sh]
|
||||
very basic regress test against Twisted Conch in "make interop"
|
||||
target (conch is available in ports/devel/py-twisted/conch);
|
||||
ok markus@
|
||||
- (djm) [regress/Makefile] search for conch by path, like we do putty
|
||||
|
||||
20080629
|
||||
- (djm) OpenBSD CVS Sync
|
||||
- martynas@cvs.openbsd.org 2008/06/21 07:46:46
|
||||
[sftp.c]
|
||||
use optopt to get invalid flag, instead of return value of getopt,
|
||||
which is always '?'; ok djm@
|
||||
- otto@cvs.openbsd.org 2008/06/25 11:13:43
|
||||
[key.c]
|
||||
add key length to visual fingerprint; zap magical constants;
|
||||
ok grunk@ djm@
|
||||
- djm@cvs.openbsd.org 2008/06/26 06:10:09
|
||||
[sftp-client.c sftp-server.c]
|
||||
allow the sftp chmod(2)-equivalent operation to set set[ug]id/sticky
|
||||
bits. Note that this only affects explicit setting of modes (e.g. via
|
||||
sftp(1)'s chmod command) and not file transfers. (bz#1310)
|
||||
ok deraadt@ at c2k8
|
||||
- djm@cvs.openbsd.org 2008/06/26 09:19:40
|
||||
[dh.c dh.h moduli.c]
|
||||
when loading moduli from /etc/moduli in sshd(8), check that they
|
||||
are of the expected "safe prime" structure and have had
|
||||
appropriate primality tests performed;
|
||||
feedback and ok dtucker@
|
||||
- grunk@cvs.openbsd.org 2008/06/26 11:46:31
|
||||
[readconf.c readconf.h ssh.1 ssh_config.5 sshconnect.c]
|
||||
Move SSH Fingerprint Visualization away from sharing the config option
|
||||
CheckHostIP to an own config option named VisualHostKey.
|
||||
While there, fix the behaviour that ssh would draw a random art picture
|
||||
on every newly seen host even when the option was not enabled.
|
||||
prodded by deraadt@, discussions,
|
||||
help and ok markus@ djm@ dtucker@
|
||||
- jmc@cvs.openbsd.org 2008/06/26 21:11:46
|
||||
[ssh.1]
|
||||
add VisualHostKey to the list of options listed in -o;
|
||||
- djm@cvs.openbsd.org 2008/06/28 07:25:07
|
||||
[PROTOCOL]
|
||||
spelling fixes
|
||||
- djm@cvs.openbsd.org 2008/06/28 13:58:23
|
||||
[ssh-agent.c]
|
||||
refuse to add a key that has unknown constraints specified;
|
||||
ok markus
|
||||
- djm@cvs.openbsd.org 2008/06/28 14:05:15
|
||||
[ssh-agent.c]
|
||||
reset global compat flag after processing a protocol 2 signature
|
||||
request with the legacy DSA encoding flag set; ok markus
|
||||
- djm@cvs.openbsd.org 2008/06/28 14:08:30
|
||||
[PROTOCOL PROTOCOL.agent]
|
||||
document the protocol used by ssh-agent; "looks ok" markus@
|
||||
|
||||
20080628
|
||||
- (djm) [RFC.nroff contrib/cygwin/Makefile contrib/suse/openssh.spec]
|
||||
RFC.nroff lacks a license, remove it (it is long gone in OpenBSD).
|
||||
|
||||
20080626
|
||||
- (djm) [Makefile.in moduli.5] Include moduli(5) manpage from OpenBSD.
|
||||
(bz#1372)
|
||||
- (djm) [ contrib/caldera/openssh.spec contrib/redhat/openssh.spec]
|
||||
[contrib/suse/openssh.spec] Include moduli.5 in RPM spec files.
|
||||
|
||||
20080616
|
||||
- (dtucker) OpenBSD CVS Sync
|
||||
- dtucker@cvs.openbsd.org 2008/06/16 13:22:53
|
||||
[session.c channels.c]
|
||||
Rename the isatty argument to is_tty so we don't shadow
|
||||
isatty(3). ok markus@
|
||||
- (dtucker) [channels.c] isatty -> is_tty here too.
|
||||
|
||||
20080615
|
||||
- (dtucker) [configure.ac] Enable -fno-builtin-memset when using gcc.
|
||||
- OpenBSD CVS Sync
|
||||
- dtucker@cvs.openbsd.org 2008/06/14 15:49:48
|
||||
[sshd.c]
|
||||
wrap long line at 80 chars
|
||||
- dtucker@cvs.openbsd.org 2008/06/14 17:07:11
|
||||
[sshd.c]
|
||||
ensure default umask disallows at least group and world write; ok djm@
|
||||
- djm@cvs.openbsd.org 2008/06/14 18:33:43
|
||||
[session.c]
|
||||
suppress the warning message from chdir(homedir) failures
|
||||
when chrooted (bz#1461); ok dtucker
|
||||
- dtucker@cvs.openbsd.org 2008/06/14 19:42:10
|
||||
[scp.1]
|
||||
Mention that scp follows symlinks during -r. bz #1466,
|
||||
from nectar at apple
|
||||
- dtucker@cvs.openbsd.org 2008/06/15 16:55:38
|
||||
[sshd_config.5]
|
||||
MaxSessions is allowed in a Match block too
|
||||
- dtucker@cvs.openbsd.org 2008/06/15 16:58:40
|
||||
[servconf.c sshd_config.5]
|
||||
Allow MaxAuthTries within a Match block. ok djm@
|
||||
- djm@cvs.openbsd.org 2008/06/15 20:06:26
|
||||
[channels.c channels.h session.c]
|
||||
don't call isatty() on a pty master, instead pass a flag down to
|
||||
channel_set_fds() indicating that te fds refer to a tty. Fixes a
|
||||
hang on exit on Solaris (bz#1463) in portable but is actually
|
||||
a generic bug; ok dtucker deraadt markus
|
||||
|
||||
20080614
|
||||
- (djm) [openbsd-compat/sigact.c] Avoid NULL derefs in ancient sigaction
|
||||
replacement code; patch from ighighi AT gmail.com in bz#1240;
|
||||
ok dtucker
|
||||
|
||||
20080613
|
||||
- (dtucker) OpenBSD CVS Sync
|
||||
- deraadt@cvs.openbsd.org 2008/06/13 09:44:36
|
||||
[packet.c]
|
||||
compile on older gcc; no decl after code
|
||||
- dtucker@cvs.openbsd.org 2008/06/13 13:56:59
|
||||
[monitor.c]
|
||||
Clear key options in the monitor on failed authentication, prevents
|
||||
applying additional restrictions to non-pubkey authentications in
|
||||
the case where pubkey fails but another method subsequently succeeds.
|
||||
bz #1472, found by Colin Watson, ok markus@ djm@
|
||||
- dtucker@cvs.openbsd.org 2008/06/13 14:18:51
|
||||
[auth2-pubkey.c auth-rhosts.c]
|
||||
Include unistd.h for close(), prevents warnings in -portable
|
||||
- dtucker@cvs.openbsd.org 2008/06/13 17:21:20
|
||||
[mux.c]
|
||||
Friendlier error messages for mux fallback. ok djm@
|
||||
- dtucker@cvs.openbsd.org 2008/06/13 18:55:22
|
||||
[scp.c]
|
||||
Prevent -Wsign-compare warnings on LP64 systems. bz #1192, ok deraadt@
|
||||
- grunk@cvs.openbsd.org 2008/06/13 20:13:26
|
||||
[ssh.1]
|
||||
Explain the use of SSH fpr visualization using random art, and cite the
|
||||
original scientific paper inspiring that technique.
|
||||
Much help with English and nroff by jmc@, thanks.
|
||||
- (dtucker) [configure.ac] Bug #1276: avoid linking against libgssapi, which
|
||||
despite its name doesn't seem to implement all of GSSAPI. Patch from
|
||||
Jan Engelhardt, sanity checked by Simon Wilkinson.
|
||||
|
||||
20080612
|
||||
- (dtucker) OpenBSD CVS Sync
|
||||
- jmc@cvs.openbsd.org 2008/06/11 07:30:37
|
||||
[sshd.8]
|
||||
kill trailing whitespace;
|
||||
- grunk@cvs.openbsd.org 2008/06/11 21:01:35
|
||||
[ssh_config.5 key.h readconf.c readconf.h ssh-keygen.1 ssh-keygen.c key.c
|
||||
sshconnect.c]
|
||||
Introduce SSH Fingerprint ASCII Visualization, a technique inspired by the
|
||||
graphical hash visualization schemes known as "random art", and by
|
||||
Dan Kaminsky's musings on the subject during a BlackOp talk at the
|
||||
23C3 in Berlin.
|
||||
Scientific publication (original paper):
|
||||
"Hash Visualization: a New Technique to improve Real-World Security",
|
||||
Perrig A. and Song D., 1999, International Workshop on Cryptographic
|
||||
Techniques and E-Commerce (CrypTEC '99)
|
||||
http://sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
|
||||
The algorithm used here is a worm crawling over a discrete plane,
|
||||
leaving a trace (augmenting the field) everywhere it goes.
|
||||
Movement is taken from dgst_raw 2bit-wise. Bumping into walls
|
||||
makes the respective movement vector be ignored for this turn,
|
||||
thus switching to the other color of the chessboard.
|
||||
Graphs are not unambiguous for now, because circles in graphs can be
|
||||
walked in either direction.
|
||||
discussions with several people,
|
||||
help, corrections and ok markus@ djm@
|
||||
- grunk@cvs.openbsd.org 2008/06/11 21:38:25
|
||||
[ssh-keygen.c]
|
||||
ssh-keygen -lv -f /etc/ssh/ssh_host_rsa_key.pub
|
||||
would not display you the random art as intended, spotted by canacar@
|
||||
- grunk@cvs.openbsd.org 2008/06/11 22:20:46
|
||||
[ssh-keygen.c ssh-keygen.1]
|
||||
ssh-keygen would write fingerprints to STDOUT, and random art to STDERR,
|
||||
that is not how it was envisioned.
|
||||
Also correct manpage saying that -v is needed along with -l for it to work.
|
||||
spotted by naddy@
|
||||
- otto@cvs.openbsd.org 2008/06/11 23:02:22
|
||||
[key.c]
|
||||
simpler way of computing the augmentations; ok grunk@
|
||||
- grunk@cvs.openbsd.org 2008/06/11 23:03:56
|
||||
[ssh_config.5]
|
||||
CheckHostIP set to ``fingerprint'' will display both hex and random art
|
||||
spotted by naddy@
|
||||
- grunk@cvs.openbsd.org 2008/06/11 23:51:57
|
||||
[key.c]
|
||||
#define statements that are not atoms need braces around them, else they
|
||||
will cause trouble in some cases.
|
||||
Also do a computation of -1 once, and not in a loop several times.
|
||||
spotted by otto@
|
||||
- dtucker@cvs.openbsd.org 2008/06/12 00:03:49
|
||||
[dns.c canohost.c sshconnect.c]
|
||||
Do not pass "0" strings as ports to getaddrinfo because the lookups
|
||||
can slow things down and we never use the service info anyway. bz
|
||||
#859, patch from YOSHIFUJI Hideaki and John Devitofranceschi. ok
|
||||
deraadt@ djm@
|
||||
djm belives that the reason for the "0" strings is to ensure that
|
||||
it's not possible to call getaddrinfo with both host and port being
|
||||
NULL. In the case of canohost.c host is a local array. In the
|
||||
case of sshconnect.c, it's checked for null immediately before use.
|
||||
In dns.c it ultimately comes from ssh.c:main() and is guaranteed to
|
||||
be non-null but it's not obvious, so I added a warning message in
|
||||
case it is ever passed a null.
|
||||
- grunk@cvs.openbsd.org 2008/06/12 00:13:55
|
||||
[sshconnect.c]
|
||||
Make ssh print the random art also when ssh'ing to a host using IP only.
|
||||
spotted by naddy@, ok and help djm@ dtucker@
|
||||
- otto@cvs.openbsd.org 2008/06/12 00:13:13
|
||||
[key.c]
|
||||
use an odd number of rows and columns and a separate start marker, looks
|
||||
better; ok grunk@
|
||||
- djm@cvs.openbsd.org 2008/06/12 03:40:52
|
||||
[clientloop.h mux.c channels.c clientloop.c channels.h]
|
||||
Enable ~ escapes for multiplex slave sessions; give each channel
|
||||
its own escape state and hook the escape filters up to muxed
|
||||
channels. bz #1331
|
||||
Mux slaves do not currently support the ~^Z and ~& escapes.
|
||||
NB. this change cranks the mux protocol version, so a new ssh
|
||||
mux client will not be able to connect to a running old ssh
|
||||
mux master.
|
||||
ok dtucker@
|
||||
- djm@cvs.openbsd.org 2008/06/12 04:06:00
|
||||
[clientloop.h ssh.c clientloop.c]
|
||||
maintain an ordered queue of outstanding global requests that we
|
||||
expect replies to, similar to the per-channel confirmation queue.
|
||||
Use this queue to verify success or failure for remote forward
|
||||
establishment in a race free way.
|
||||
ok dtucker@
|
||||
- djm@cvs.openbsd.org 2008/06/12 04:17:47
|
||||
[clientloop.c]
|
||||
thall shalt not code past the eightieth column
|
||||
- djm@cvs.openbsd.org 2008/06/12 04:24:06
|
||||
[ssh.c]
|
||||
thal shalt not code past the eightieth column
|
||||
- djm@cvs.openbsd.org 2008/06/12 05:15:41
|
||||
[PROTOCOL]
|
||||
document tun@openssh.com forwarding method
|
||||
- djm@cvs.openbsd.org 2008/06/12 05:32:30
|
||||
[mux.c]
|
||||
some more TODO for me
|
||||
- grunk@cvs.openbsd.org 2008/06/12 05:42:46
|
||||
[key.c]
|
||||
supply the key type (rsa1, rsa, dsa) as a caption in the frame of the
|
||||
random art. while there, stress the fact that the field base should at
|
||||
least be 8 characters for the pictures to make sense.
|
||||
comment and ok djm@
|
||||
- grunk@cvs.openbsd.org 2008/06/12 06:32:59
|
||||
[key.c]
|
||||
We already mark the start of the worm, now also mark the end of the worm
|
||||
in our random art drawings.
|
||||
ok djm@
|
||||
- djm@cvs.openbsd.org 2008/06/12 15:19:17
|
||||
[clientloop.h channels.h clientloop.c channels.c mux.c]
|
||||
The multiplexing escape char handler commit last night introduced a
|
||||
small memory leak per session; plug it.
|
||||
- dtucker@cvs.openbsd.org 2008/06/12 16:35:31
|
||||
[ssh_config.5 ssh.c]
|
||||
keyword expansion for localcommand. ok djm@
|
||||
- jmc@cvs.openbsd.org 2008/06/12 19:10:09
|
||||
[ssh_config.5 ssh-keygen.1]
|
||||
tweak the ascii art text; ok grunk
|
||||
- dtucker@cvs.openbsd.org 2008/06/12 20:38:28
|
||||
[sshd.c sshconnect.c packet.h misc.c misc.h packet.c]
|
||||
Make keepalive timeouts apply while waiting for a packet, particularly
|
||||
during key renegotiation (bz #1363). With djm and Matt Day, ok djm@
|
||||
- djm@cvs.openbsd.org 2008/06/12 20:47:04
|
||||
[sftp-client.c]
|
||||
print extension revisions for extensions that we understand
|
||||
- djm@cvs.openbsd.org 2008/06/12 21:06:25
|
||||
[clientloop.c]
|
||||
I was coalescing expected global request confirmation replies at
|
||||
the wrong end of the queue - fix; prompted by markus@
|
||||
- grunk@cvs.openbsd.org 2008/06/12 21:14:46
|
||||
[ssh-keygen.c]
|
||||
make ssh-keygen -lf show the key type just as ssh-add -l would do it
|
||||
ok djm@ markus@
|
||||
- grunk@cvs.openbsd.org 2008/06/12 22:03:36
|
||||
[key.c]
|
||||
add my copyright, ok djm@
|
||||
- ian@cvs.openbsd.org 2008/06/12 23:24:58
|
||||
[sshconnect.c]
|
||||
tweak wording in message, ok deraadt@ jmc@
|
||||
- dtucker@cvs.openbsd.org 2008/06/13 00:12:02
|
||||
[sftp.h log.h]
|
||||
replace __dead with __attribute__((noreturn)), makes things
|
||||
a little easier to port. Also, add it to sigdie(). ok djm@
|
||||
- djm@cvs.openbsd.org 2008/06/13 00:16:49
|
||||
[mux.c]
|
||||
fall back to creating a new TCP connection on most multiplexing errors
|
||||
(socket connect fail, invalid version, refused permittion, corrupted
|
||||
messages, etc.); bz #1329 ok dtucker@
|
||||
- dtucker@cvs.openbsd.org 2008/06/13 00:47:53
|
||||
[mux.c]
|
||||
upcast size_t to u_long to match format arg; ok djm@
|
||||
- dtucker@cvs.openbsd.org 2008/06/13 00:51:47
|
||||
[mac.c]
|
||||
upcast another size_t to u_long to match format
|
||||
- dtucker@cvs.openbsd.org 2008/06/13 01:38:23
|
||||
[misc.c]
|
||||
upcast uid to long with matching %ld, prevents warnings in portable
|
||||
- djm@cvs.openbsd.org 2008/06/13 04:40:22
|
||||
[auth2-pubkey.c auth-rhosts.c]
|
||||
refuse to read ~/.shosts or ~/.ssh/authorized_keys that are not
|
||||
regular files; report from Solar Designer via Colin Watson in bz#1471
|
||||
ok dtucker@ deraadt
|
||||
- (dtucker) [clientloop.c serverloop.c] channel_register_filter now
|
||||
takes 2 more args. with djm@
|
||||
- (dtucker) [defines.h] Bug #1112: __dead is, well dead. Based on a patch
|
||||
from Todd Vierling.
|
||||
- (dtucker) [auth-sia.c] Bug #1241: support password expiry on Tru64 SIA
|
||||
systems. Patch from R. Scott Bailey.
|
||||
- (dtucker) [umac.c] STORE_UINT32_REVERSED and endian_convert are never used
|
||||
on big endian machines, so ifdef them for little-endian only to prevent
|
||||
unused function warnings on big-endians.
|
||||
- (dtucker) [openbsd-compat/setenv.c] Make offsets size_t to prevent
|
||||
compiler warnings on some platforms. Based on a discussion with otto@
|
||||
|
||||
20080611
|
||||
- (djm) [channels.c configure.ac]
|
||||
Do not set SO_REUSEADDR on wildcard X11 listeners (X11UseLocalhost=no)
|
||||
bz#1464; ok dtucker
|
||||
|
||||
20080610
|
||||
- (dtucker) OpenBSD CVS Sync
|
||||
- djm@cvs.openbsd.org 2008/06/10 03:57:27
|
||||
[servconf.c match.h sshd_config.5]
|
||||
support CIDR address matching in sshd_config "Match address" blocks, with
|
||||
full support for negation and fall-back to classic wildcard matching.
|
||||
For example:
|
||||
Match address 192.0.2.0/24,3ffe:ffff::/32,!10.*
|
||||
PasswordAuthentication yes
|
||||
addrmatch.c code mostly lifted from flowd's addr.c
|
||||
feedback and ok dtucker@
|
||||
- djm@cvs.openbsd.org 2008/06/10 04:17:46
|
||||
[sshd_config.5]
|
||||
better reference for pattern-list
|
||||
- dtucker@cvs.openbsd.org 2008/06/10 04:50:25
|
||||
[sshd.c channels.h channels.c log.c servconf.c log.h servconf.h sshd.8]
|
||||
Add extended test mode (-T) and connection parameters for test mode (-C).
|
||||
-T causes sshd to write its effective configuration to stdout and exit.
|
||||
-C causes any relevant Match rules to be applied before output. The
|
||||
combination allows tesing of the parser and config files. ok deraadt djm
|
||||
- jmc@cvs.openbsd.org 2008/06/10 07:12:00
|
||||
[sshd_config.5]
|
||||
tweak previous;
|
||||
- jmc@cvs.openbsd.org 2008/06/10 08:17:40
|
||||
[sshd.8 sshd.c]
|
||||
- update usage()
|
||||
- fix SYNOPSIS, and sort options
|
||||
- some minor additional fixes
|
||||
- dtucker@cvs.openbsd.org 2008/06/09 18:06:32
|
||||
[regress/test-exec.sh]
|
||||
Don't generate putty keys if we're not going to use them. ok djm
|
||||
- dtucker@cvs.openbsd.org 2008/06/10 05:23:32
|
||||
[regress/addrmatch.sh regress/Makefile]
|
||||
Regress test for Match CIDR rules. ok djm@
|
||||
- dtucker@cvs.openbsd.org 2008/06/10 15:21:41
|
||||
[test-exec.sh]
|
||||
Use a more portable construct for checking if we're running a putty test
|
||||
- dtucker@cvs.openbsd.org 2008/06/10 15:28:49
|
||||
[test-exec.sh]
|
||||
Add quotes
|
||||
- dtucker@cvs.openbsd.org 2008/06/10 18:21:24
|
||||
[ssh_config.5]
|
||||
clarify that Host patterns are space-separated. ok deraadt
|
||||
- djm@cvs.openbsd.org 2008/06/10 22:15:23
|
||||
[PROTOCOL ssh.c serverloop.c]
|
||||
Add a no-more-sessions@openssh.com global request extension that the
|
||||
client sends when it knows that it will never request another session
|
||||
(i.e. when session multiplexing is disabled). This allows a server to
|
||||
disallow further session requests and terminate the session.
|
||||
Why would a non-multiplexing client ever issue additional session
|
||||
requests? It could have been attacked with something like SSH'jack:
|
||||
http://www.storm.net.nz/projects/7
|
||||
feedback & ok markus
|
||||
- djm@cvs.openbsd.org 2008/06/10 23:06:19
|
||||
[auth-options.c match.c servconf.c addrmatch.c sshd.8]
|
||||
support CIDR address matching in .ssh/authorized_keys from="..." stanzas
|
||||
ok and extensive testing dtucker@
|
||||
- dtucker@cvs.openbsd.org 2008/06/10 23:21:34
|
||||
[bufaux.c]
|
||||
Use '\0' for a nul byte rather than unadorned 0. ok djm@
|
||||
- dtucker@cvs.openbsd.org 2008/06/10 23:13:43
|
||||
[Makefile regress/key-options.sh]
|
||||
Add regress test for key options. ok djm@
|
||||
- (dtucker) [openbsd-compat/fake-rfc2553.h] Add sin6_scope_id to sockaddr_in6
|
||||
since the new CIDR code in addmatch.c references it.
|
||||
- (dtucker) [Makefile.in configure.ac regress/addrmatch.sh] Skip IPv6
|
||||
specific tests on platforms that don't do IPv6.
|
||||
- (dtucker) [Makefile.in] Define TEST_SSH_IPV6 in make's arguments as well
|
||||
as environment.
|
||||
- (dtucker) [Makefile.in] Move addrmatch.o to libssh.a where it's needed now.
|
||||
|
||||
20080609
|
||||
- (dtucker) OpenBSD CVS Sync
|
||||
- dtucker@cvs.openbsd.org 2008/06/08 17:04:41
|
||||
[sftp-server.c]
|
||||
Add case for ENOSYS in errno_to_portable; ok deraadt
|
||||
- dtucker@cvs.openbsd.org 2008/06/08 20:15:29
|
||||
[sftp.c sftp-client.c sftp-client.h]
|
||||
Have the sftp client store the statvfs replies in wire format,
|
||||
which prevents problems when the server's native sizes exceed the
|
||||
client's.
|
||||
Also extends the sizes of the remaining 32bit wire format to 64bit,
|
||||
they're specified as unsigned long in the standard.
|
||||
- dtucker@cvs.openbsd.org 2008/06/09 13:02:39
|
||||
[sftp-server.c]
|
||||
Extend 32bit -> 64bit values for statvfs extension missed in previous
|
||||
commit.
|
||||
- dtucker@cvs.openbsd.org 2008/06/09 13:38:46
|
||||
[PROTOCOL]
|
||||
Use a $OpenBSD tag so our scripts will sync changes.
|
||||
|
||||
20080608
|
||||
- (dtucker) [configure.ac defines.h sftp-client.c sftp-server.c sftp.c
|
||||
openbsd-compat/Makefile.in openbsd-compat/openbsd-compat.h
|
||||
openbsd-compat/bsd-statvfs.{c,h}] Add a null implementation of statvfs and
|
||||
fstatvfs and remove #defines around statvfs code. ok djm@
|
||||
- (dtucker) [configure.ac defines.h sftp-client.c M sftp-server.c] Add a
|
||||
macro to convert fsid to unsigned long for platforms where fsid is a
|
||||
2-member array.
|
||||
|
||||
20080607
|
||||
- (dtucker) [mux.c] Include paths.h inside ifdef HAVE_PATHS_H.
|
||||
- (dtucker) [configure.ac defines.h sftp-client.c sftp-server.c sftp.c]
|
||||
Do not enable statvfs extensions on platforms that do not have statvfs.
|
||||
- (dtucker) OpenBSD CVS Sync
|
||||
- djm@cvs.openbsd.org 2008/05/19 06:14:02
|
||||
[packet.c] unbreak protocol keepalive timeouts bz#1465; ok dtucker@
|
||||
- djm@cvs.openbsd.org 2008/05/19 15:45:07
|
||||
[sshtty.c ttymodes.c sshpty.h]
|
||||
Fix sending tty modes when stdin is not a tty (bz#1199). Previously
|
||||
we would send the modes corresponding to a zeroed struct termios,
|
||||
whereas we should have been sending an empty list of modes.
|
||||
Based on patch from daniel.ritz AT alcatel.ch; ok dtucker@ markus@
|
||||
- djm@cvs.openbsd.org 2008/05/19 15:46:31
|
||||
[ssh-keygen.c]
|
||||
support -l (print fingerprint) in combination with -F (find host) to
|
||||
search for a host in ~/.ssh/known_hosts and display its fingerprint;
|
||||
ok markus@
|
||||
- djm@cvs.openbsd.org 2008/05/19 20:53:52
|
||||
[clientloop.c]
|
||||
unbreak tree by committing this bit that I missed from:
|
||||
Fix sending tty modes when stdin is not a tty (bz#1199). Previously
|
||||
we would send the modes corresponding to a zeroed struct termios,
|
||||
whereas we should have been sending an empty list of modes.
|
||||
Based on patch from daniel.ritz AT alcatel.ch; ok dtucker@ markus@
|
||||
|
||||
20080604
|
||||
- (djm) [openbsd-compat/bsd-arc4random.c] Fix math bug that caused bias
|
||||
in arc4random_uniform with upper_bound in (2^30,2*31). Note that
|
||||
OpenSSH did not make requests with upper bounds in this range.
|
||||
|
||||
20080519
|
||||
- (djm) [configure.ac mux.c sftp.c openbsd-compat/Makefile.in]
|
||||
[openbsd-compat/fmt_scaled.c openbsd-compat/openbsd-compat.h]
|
||||
Fix compilation on Linux, including pulling in fmt_scaled(3)
|
||||
implementation from OpenBSD's libutil.
|
||||
|
||||
20080518
|
||||
- (djm) OpenBSD CVS Sync
|
||||
- djm@cvs.openbsd.org 2008/04/04 05:14:38
|
||||
[sshd_config.5]
|
||||
ChrootDirectory is supported in Match blocks (in fact, it is most useful
|
||||
there). Spotted by Minstrel AT minstrel.org.uk
|
||||
- djm@cvs.openbsd.org 2008/04/04 06:44:26
|
||||
[sshd_config.5]
|
||||
oops, some unrelated stuff crept into that commit - backout.
|
||||
spotted by jmc@
|
||||
- djm@cvs.openbsd.org 2008/04/05 02:46:02
|
||||
[sshd_config.5]
|
||||
HostbasedAuthentication is supported under Match too
|
||||
- (djm) [openbsd-compat/bsd-arc4random.c openbsd-compat/openbsd-compat.c]
|
||||
[configure.ac] Implement arc4random_buf(), import implementation of
|
||||
arc4random_uniform() from OpenBSD
|
||||
- (djm) [openbsd-compat/bsd-arc4random.c] Warning fixes
|
||||
- (djm) [openbsd-compat/port-tun.c] needs sys/queue.h
|
||||
- (djm) OpenBSD CVS Sync
|
||||
- djm@cvs.openbsd.org 2008/04/13 00:22:17
|
||||
[dh.c sshd.c]
|
||||
Use arc4random_buf() when requesting more than a single word of output
|
||||
Use arc4random_uniform() when the desired random number upper bound
|
||||
is not a power of two
|
||||
ok deraadt@ millert@
|
||||
- djm@cvs.openbsd.org 2008/04/18 12:32:11
|
||||
[sftp-client.c sftp-client.h sftp-server.c sftp.1 sftp.c sftp.h]
|
||||
introduce sftp extension methods statvfs@openssh.com and
|
||||
fstatvfs@openssh.com that implement statvfs(2)-like operations,
|
||||
based on a patch from miklos AT szeredi.hu (bz#1399)
|
||||
also add a "df" command to the sftp client that uses the
|
||||
statvfs@openssh.com to produce a df(1)-like display of filesystem
|
||||
space and inode utilisation
|
||||
ok markus@
|
||||
- jmc@cvs.openbsd.org 2008/04/18 17:15:47
|
||||
[sftp.1]
|
||||
macro fixage;
|
||||
- djm@cvs.openbsd.org 2008/04/18 22:01:33
|
||||
[session.c]
|
||||
remove unneccessary parentheses
|
||||
- otto@cvs.openbsd.org 2008/04/29 11:20:31
|
||||
[monitor_mm.h]
|
||||
garbage collect two unused fields in struct mm_master; ok markus@
|
||||
- djm@cvs.openbsd.org 2008/04/30 10:14:03
|
||||
[ssh-keyscan.1 ssh-keyscan.c]
|
||||
default to rsa (protocol 2) keys, instead of rsa1 keys; spotted by
|
||||
larsnooden AT openoffice.org
|
||||
- pyr@cvs.openbsd.org 2008/05/07 05:49:37
|
||||
[servconf.c servconf.h session.c sshd_config.5]
|
||||
Enable the AllowAgentForwarding option in sshd_config (global and match
|
||||
context), to specify if agents should be permitted on the server.
|
||||
As the man page states:
|
||||
``Note that disabling Agent forwarding does not improve security
|
||||
unless users are also denied shell access, as they can always install
|
||||
their own forwarders.''
|
||||
ok djm@, ok and a mild frown markus@
|
||||
- pyr@cvs.openbsd.org 2008/05/07 06:43:35
|
||||
[sshd_config]
|
||||
push the sshd_config bits in, spotted by ajacoutot@
|
||||
- jmc@cvs.openbsd.org 2008/05/07 08:00:14
|
||||
[sshd_config.5]
|
||||
sort;
|
||||
- markus@cvs.openbsd.org 2008/05/08 06:59:01
|
||||
[bufaux.c buffer.h channels.c packet.c packet.h]
|
||||
avoid extra malloc/copy/free when receiving data over the net;
|
||||
~10% speedup for localhost-scp; ok djm@
|
||||
- djm@cvs.openbsd.org 2008/05/08 12:02:23
|
||||
[auth-options.c auth1.c channels.c channels.h clientloop.c gss-serv.c]
|
||||
[monitor.c monitor_wrap.c nchan.c servconf.c serverloop.c session.c]
|
||||
[ssh.c sshd.c]
|
||||
Implement a channel success/failure status confirmation callback
|
||||
mechanism. Each channel maintains a queue of callbacks, which will
|
||||
be drained in order (RFC4253 guarantees confirm messages are not
|
||||
reordered within an channel).
|
||||
Also includes a abandonment callback to clean up if a channel is
|
||||
closed without sending confirmation messages. This probably
|
||||
shouldn't happen in compliant implementations, but it could be
|
||||
abused to leak memory.
|
||||
ok markus@ (as part of a larger diff)
|
||||
- djm@cvs.openbsd.org 2008/05/08 12:21:16
|
||||
[monitor.c monitor_wrap.c session.h servconf.c servconf.h session.c]
|
||||
[sshd_config sshd_config.5]
|
||||
Make the maximum number of sessions run-time controllable via
|
||||
a sshd_config MaxSessions knob. This is useful for disabling
|
||||
login/shell/subsystem access while leaving port-forwarding working
|
||||
(MaxSessions 0), disabling connection multiplexing (MaxSessions 1) or
|
||||
simply increasing the number of allows multiplexed sessions.
|
||||
Because some bozos are sure to configure MaxSessions in excess of the
|
||||
number of available file descriptors in sshd (which, at peak, might be
|
||||
as many as 9*MaxSessions), audit sshd to ensure that it doesn't leak fds
|
||||
on error paths, and make it fail gracefully on out-of-fd conditions -
|
||||
sending channel errors instead of than exiting with fatal().
|
||||
bz#1090; MaxSessions config bits and manpage from junyer AT gmail.com
|
||||
ok markus@
|
||||
- djm@cvs.openbsd.org 2008/05/08 13:06:11
|
||||
[clientloop.c clientloop.h ssh.c]
|
||||
Use new channel status confirmation callback system to properly deal
|
||||
with "important" channel requests that fail, in particular command exec,
|
||||
shell and subsystem requests. Previously we would optimistically assume
|
||||
that the requests would always succeed, which could cause hangs if they
|
||||
did not (e.g. when the server runs out of fds) or were unimplemented by
|
||||
the server (bz #1384)
|
||||
Also, properly report failing multiplex channel requests via the mux
|
||||
client stderr (subject to LogLevel in the mux master) - better than
|
||||
silently failing.
|
||||
most bits ok markus@ (as part of a larger diff)
|
||||
- djm@cvs.openbsd.org 2008/05/09 04:55:56
|
||||
[channels.c channels.h clientloop.c serverloop.c]
|
||||
Try additional addresses when connecting to a port forward destination
|
||||
whose DNS name resolves to more than one address. The previous behaviour
|
||||
was to try the first address and give up.
|
||||
Reported by stig AT venaas.com in bz#343
|
||||
great feedback and ok markus@
|
||||
- djm@cvs.openbsd.org 2008/05/09 14:18:44
|
||||
[clientloop.c clientloop.h ssh.c mux.c]
|
||||
tidy up session multiplexing code, moving it into its own file and
|
||||
making the function names more consistent - making ssh.c and
|
||||
clientloop.c a fair bit more readable.
|
||||
ok markus@
|
||||
- djm@cvs.openbsd.org 2008/05/09 14:26:08
|
||||
[ssh.c]
|
||||
dingo stole my diff hunk
|
||||
- markus@cvs.openbsd.org 2008/05/09 16:16:06
|
||||
[session.c]
|
||||
re-add the USE_PIPES code and enable it.
|
||||
without pipes shutdown-read from the sshd does not trigger
|
||||
a SIGPIPE when the forked program does a write.
|
||||
ok djm@
|
||||
(Id sync only, USE_PIPES never left portable OpenSSH)
|
||||
- markus@cvs.openbsd.org 2008/05/09 16:17:51
|
||||
[channels.c]
|
||||
error-fd race: don't enable the error fd in the select bitmask
|
||||
for channels with both in- and output closed, since the channel
|
||||
will go away before we call select();
|
||||
report, lots of debugging help and ok djm@
|
||||
- markus@cvs.openbsd.org 2008/05/09 16:21:13
|
||||
[channels.h clientloop.c nchan.c serverloop.c]
|
||||
unbreak
|
||||
ssh -2 localhost od /bin/ls | true
|
||||
ignoring SIGPIPE by adding a new channel message (EOW) that signals
|
||||
the peer that we're not interested in any data it might send.
|
||||
fixes bz #85; discussion, debugging and ok djm@
|
||||
- pvalchev@cvs.openbsd.org 2008/05/12 20:52:20
|
||||
[umac.c]
|
||||
Ensure nh_result lies on a 64-bit boundary (fixes warnings observed
|
||||
on Itanium on Linux); from Dale Talcott (bug #1462); ok djm@
|
||||
- djm@cvs.openbsd.org 2008/05/15 23:52:24
|
||||
[nchan2.ms]
|
||||
document eow message in ssh protocol 2 channel state machine;
|
||||
feedback and ok markus@
|
||||
- djm@cvs.openbsd.org 2008/05/18 21:29:05
|
||||
[sftp-server.c]
|
||||
comment extension announcement
|
||||
- djm@cvs.openbsd.org 2008/05/16 08:30:42
|
||||
[PROTOCOL]
|
||||
document our protocol extensions and deviations; ok markus@
|
||||
- djm@cvs.openbsd.org 2008/05/17 01:31:56
|
||||
[PROTOCOL]
|
||||
grammar and correctness fixes from stevesk@
|
||||
|
||||
20080403
|
||||
- (djm) [openbsd-compat/bsd-poll.c] Include stdlib.h to avoid compile-
|
||||
time warnings on LynxOS. Patch from ops AT iki.fi
|
||||
- (djm) Force string arguments to replacement setproctitle() though
|
||||
strnvis first. Ok dtucker@
|
||||
|
||||
20080403
|
||||
- (djm) OpenBSD CVS sync:
|
||||
- markus@cvs.openbsd.org 2008/04/02 15:36:51
|
||||
@ -3851,4 +4710,4 @@
|
||||
OpenServer 6 and add osr5bigcrypt support so when someone migrates
|
||||
passwords between UnixWare and OpenServer they will still work. OK dtucker@
|
||||
|
||||
$Id: ChangeLog,v 1.4903 2008/04/03 09:57:05 djm Exp $
|
||||
$Id: ChangeLog,v 1.5095 2008/07/21 08:22:25 djm Exp $
|
||||
|
18
Makefile.in
18
Makefile.in
@ -1,4 +1,4 @@
|
||||
# $Id: Makefile.in,v 1.289 2008/03/13 01:41:31 djm Exp $
|
||||
# $Id: Makefile.in,v 1.297 2008/07/08 14:21:12 djm Exp $
|
||||
|
||||
# uncomment if you run a non bourne compatable shell. Ie. csh
|
||||
#SHELL = @SH@
|
||||
@ -67,14 +67,14 @@ LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
|
||||
cipher-bf1.o cipher-ctr.o cipher-3des1.o cleanup.o \
|
||||
compat.o compress.o crc32.o deattack.o fatal.o hostfile.o \
|
||||
log.o match.o md-sha256.o moduli.o nchan.o packet.o \
|
||||
readpass.o rsa.o ttymodes.o xmalloc.o \
|
||||
readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \
|
||||
atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
|
||||
monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \
|
||||
kexgex.o kexdhc.o kexgexc.o scard.o msg.o progressmeter.o dns.o \
|
||||
entropy.o scard-opensc.o gss-genr.o umac.o
|
||||
|
||||
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
|
||||
sshconnect.o sshconnect1.o sshconnect2.o
|
||||
sshconnect.o sshconnect1.o sshconnect2.o mux.o
|
||||
|
||||
SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
|
||||
sshpty.o sshlogin.o servconf.o serverloop.o \
|
||||
@ -88,8 +88,8 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
|
||||
loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
|
||||
audit.o audit-bsm.o platform.o sftp-server.o sftp-common.o
|
||||
|
||||
MANPAGES = scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out ssh-keysign.8.out sshd_config.5.out ssh_config.5.out
|
||||
MANPAGES_IN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 sshd_config.5 ssh_config.5
|
||||
MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out ssh-keysign.8.out sshd_config.5.out ssh_config.5.out
|
||||
MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 sshd_config.5 ssh_config.5
|
||||
MANTYPE = @MANTYPE@
|
||||
|
||||
CONFIGFILES=sshd_config.out ssh_config.out moduli.out
|
||||
@ -106,6 +106,7 @@ PATHSUBS = \
|
||||
-e 's|/etc/ssh/ssh_host_dsa_key|$(sysconfdir)/ssh_host_dsa_key|g' \
|
||||
-e 's|/etc/ssh/ssh_host_rsa_key|$(sysconfdir)/ssh_host_rsa_key|g' \
|
||||
-e 's|/var/run/sshd.pid|$(piddir)/sshd.pid|g' \
|
||||
-e 's|/etc/moduli|$(sysconfdir)/moduli|g' \
|
||||
-e 's|/etc/ssh/moduli|$(sysconfdir)/moduli|g' \
|
||||
-e 's|/etc/ssh/sshrc|$(sysconfdir)/sshrc|g' \
|
||||
-e 's|/usr/X11R6/bin/xauth|$(XAUTH_PATH)|g' \
|
||||
@ -270,6 +271,7 @@ install-files: scard-install
|
||||
$(INSTALL) -m 644 ssh-agent.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1
|
||||
$(INSTALL) -m 644 ssh-keygen.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1
|
||||
$(INSTALL) -m 644 ssh-keyscan.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1
|
||||
$(INSTALL) -m 644 moduli.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/moduli.5
|
||||
$(INSTALL) -m 644 sshd_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/sshd_config.5
|
||||
$(INSTALL) -m 644 ssh_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh_config.5
|
||||
$(INSTALL) -m 644 sshd.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
|
||||
@ -394,6 +396,8 @@ tests interop-tests: $(TARGETS)
|
||||
TEST_SSH_SFTPSERVER="$${BUILDDIR}/sftp-server"; \
|
||||
TEST_SSH_PLINK="plink"; \
|
||||
TEST_SSH_PUTTYGEN="puttygen"; \
|
||||
TEST_SSH_CONCH="conch"; \
|
||||
TEST_SSH_IPV6="@TEST_SSH_IPV6@" ; \
|
||||
cd $(srcdir)/regress || exit $$?; \
|
||||
$(MAKE) \
|
||||
.OBJDIR="$${BUILDDIR}/regress" \
|
||||
@ -412,8 +416,10 @@ tests interop-tests: $(TARGETS)
|
||||
TEST_SSH_SFTPSERVER="$${TEST_SSH_SFTPSERVER}" \
|
||||
TEST_SSH_PLINK="$${TEST_SSH_PLINK}" \
|
||||
TEST_SSH_PUTTYGEN="$${TEST_SSH_PUTTYGEN}" \
|
||||
TEST_SSH_CONCH="$${TEST_SSH_CONCH}" \
|
||||
TEST_SSH_IPV6="@TEST_SSH_IPV6@" \
|
||||
EXEEXT="$(EXEEXT)" \
|
||||
$@
|
||||
$@ && echo all tests passed
|
||||
|
||||
compat-tests: $(LIBCOMPAT)
|
||||
(cd openbsd-compat/regress && $(MAKE))
|
||||
|
243
PROTOCOL
Normal file
243
PROTOCOL
Normal file
@ -0,0 +1,243 @@
|
||||
This documents OpenSSH's deviations and extensions to the published SSH
|
||||
protocol.
|
||||
|
||||
Note that OpenSSH's sftp and sftp-server implement revision 3 of the SSH
|
||||
filexfer protocol described in:
|
||||
|
||||
http://www.openssh.com/txt/draft-ietf-secsh-filexfer-02.txt
|
||||
|
||||
Features from newer versions of the draft are not supported, unless
|
||||
explicitly implemented as extensions described below.
|
||||
|
||||
The protocol used by OpenSSH's ssh-agent is described in the file
|
||||
PROTOCOL.agent
|
||||
|
||||
1. transport: Protocol 2 MAC algorithm "umac-64@openssh.com"
|
||||
|
||||
This is a new transport-layer MAC method using the UMAC algorithm
|
||||
(rfc4418). This method is identical to the "umac-64" method documented
|
||||
in:
|
||||
|
||||
http://www.openssh.com/txt/draft-miller-secsh-umac-01.txt
|
||||
|
||||
2. transport: Protocol 2 compression algorithm "zlib@openssh.com"
|
||||
|
||||
This transport-layer compression method uses the zlib compression
|
||||
algorithm (identical to the "zlib" method in rfc4253), but delays the
|
||||
start of compression until after authentication has completed. This
|
||||
avoids exposing compression code to attacks from unauthenticated users.
|
||||
|
||||
The method is documented in:
|
||||
|
||||
http://www.openssh.com/txt/draft-miller-secsh-compression-delayed-00.txt
|
||||
|
||||
3. connection: Channel write close extension "eow@openssh.com"
|
||||
|
||||
The SSH connection protocol (rfc4254) provides the SSH_MSG_CHANNEL_EOF
|
||||
message to allow an endpoint to signal its peer that it will send no
|
||||
more data over a channel. Unfortunately, there is no symmetric way for
|
||||
an endpoint to request that its peer should cease sending data to it
|
||||
while still keeping the channel open for the endpoint to send data to
|
||||
the peer.
|
||||
|
||||
This is desirable, since it saves the transmission of data that would
|
||||
otherwise need to be discarded and it allows an endpoint to signal local
|
||||
processes of the condition, e.g. by closing the corresponding file
|
||||
descriptor.
|
||||
|
||||
OpenSSH implements a channel extension message to perform this
|
||||
signalling: "eow@openssh.com" (End Of Write). This message is sent by
|
||||
an endpoint when the local output of a session channel is closed or
|
||||
experiences a write error. The message is formatted as follows:
|
||||
|
||||
byte SSH_MSG_CHANNEL_REQUEST
|
||||
uint32 recipient channel
|
||||
string "eow@openssh.com"
|
||||
boolean FALSE
|
||||
|
||||
On receiving this message, the peer SHOULD cease sending data of
|
||||
the channel and MAY signal the process from which the channel data
|
||||
originates (e.g. by closing its read file descriptor).
|
||||
|
||||
As with the symmetric SSH_MSG_CHANNEL_EOF message, the channel does
|
||||
remain open after a "eow@openssh.com" has been sent and more data may
|
||||
still be sent in the other direction. This message does not consume
|
||||
window space and may be sent even if no window space is available.
|
||||
|
||||
4. connection: disallow additional sessions extension
|
||||
"no-more-sessions@openssh.com"
|
||||
|
||||
Most SSH connections will only ever request a single session, but a
|
||||
attacker may abuse a running ssh client to surreptitiously open
|
||||
additional sessions under their control. OpenSSH provides a global
|
||||
request "no-more-sessions@openssh.com" to mitigate this attack.
|
||||
|
||||
When an OpenSSH client expects that it will never open another session
|
||||
(i.e. it has been started with connection multiplexing disabled), it
|
||||
will send the following global request:
|
||||
|
||||
byte SSH_MSG_GLOBAL_REQUEST
|
||||
string "no-more-sessions@openssh.com"
|
||||
char want-reply
|
||||
|
||||
On receipt of such a message, an OpenSSH server will refuse to open
|
||||
future channels of type "session" and instead immediately abort the
|
||||
connection.
|
||||
|
||||
Note that this is not a general defence against compromised clients
|
||||
(that is impossible), but it thwarts a simple attack.
|
||||
|
||||
5. connection: Tunnel forward extension "tun@openssh.com"
|
||||
|
||||
OpenSSH supports layer 2 and layer 3 tunnelling via the "tun@openssh.com"
|
||||
channel type. This channel type supports forwarding of network packets
|
||||
with datagram boundaries intact between endpoints equipped with
|
||||
interfaces like the BSD tun(4) device. Tunnel forwarding channels are
|
||||
requested by the client with the following packet:
|
||||
|
||||
byte SSH_MSG_CHANNEL_OPEN
|
||||
string "tun@openssh.com"
|
||||
uint32 sender channel
|
||||
uint32 initial window size
|
||||
uint32 maximum packet size
|
||||
uint32 tunnel mode
|
||||
uint32 remote unit number
|
||||
|
||||
The "tunnel mode" parameter specifies whether the tunnel should forward
|
||||
layer 2 frames or layer 3 packets. It may take one of the following values:
|
||||
|
||||
SSH_TUNMODE_POINTOPOINT 1 /* layer 3 packets */
|
||||
SSH_TUNMODE_ETHERNET 2 /* layer 2 frames */
|
||||
|
||||
The "tunnel unit number" specifies the remote interface number, or may
|
||||
be zero to allow the server to automatically chose an interface. A server
|
||||
that is not willing to open a client-specified unit should refuse the
|
||||
request with a SSH_MSG_CHANNEL_OPEN_FAILURE error. On successful open,
|
||||
the server should reply with SSH_MSG_CHANNEL_OPEN_SUCCESS.
|
||||
|
||||
Once established the client and server may exchange packet or frames
|
||||
over the tunnel channel by encapsulating them in SSH protocol strings
|
||||
and sending them as channel data. This ensures that packet boundaries
|
||||
are kept intact. Specifically, packets are transmitted using normal
|
||||
SSH_MSG_CHANNEL_DATA packets:
|
||||
|
||||
byte SSH_MSG_CHANNEL_DATA
|
||||
uint32 recipient channel
|
||||
string data
|
||||
|
||||
The contents of the "data" field for layer 3 packets is:
|
||||
|
||||
uint32 packet length
|
||||
uint32 address family
|
||||
byte[packet length - 4] packet data
|
||||
|
||||
The "address family" field identifies the type of packet in the message.
|
||||
It may be one of:
|
||||
|
||||
SSH_TUN_AF_INET 2 /* IPv4 */
|
||||
SSH_TUN_AF_INET6 24 /* IPv6 */
|
||||
|
||||
The "packet data" field consists of the IPv4/IPv6 datagram itself
|
||||
without any link layer header.
|
||||
|
||||
The contents of the "data" field for layer 3 packets is:
|
||||
|
||||
uint32 packet length
|
||||
byte[packet length] frame
|
||||
|
||||
The "frame" field contains an IEEE 802.3 Ethernet frame, including
|
||||
header.
|
||||
|
||||
6. sftp: Reversal of arguments to SSH_FXP_SYMLINK
|
||||
|
||||
When OpenSSH's sftp-server was implemented, the order of the arguments
|
||||
to the SSH_FXP_SYMLINK method was inadvertently reversed. Unfortunately,
|
||||
the reversal was not noticed until the server was widely deployed. Since
|
||||
fixing this to follow the specification would cause incompatibility, the
|
||||
current order was retained. For correct operation, clients should send
|
||||
SSH_FXP_SYMLINK as follows:
|
||||
|
||||
uint32 id
|
||||
string targetpath
|
||||
string linkpath
|
||||
|
||||
7. sftp: Server extension announcement in SSH_FXP_VERSION
|
||||
|
||||
OpenSSH's sftp-server lists the extensions it supports using the
|
||||
standard extension announcement mechanism in the SSH_FXP_VERSION server
|
||||
hello packet:
|
||||
|
||||
uint32 3 /* protocol version */
|
||||
string ext1-name
|
||||
string ext1-version
|
||||
string ext2-name
|
||||
string ext2-version
|
||||
...
|
||||
string extN-name
|
||||
string extN-version
|
||||
|
||||
Each extension reports its integer version number as an ASCII encoded
|
||||
string, e.g. "1". The version will be incremented if the extension is
|
||||
ever changed in an incompatible way. The server MAY advertise the same
|
||||
extension with multiple versions (though this is unlikely). Clients MUST
|
||||
check the version number before attempting to use the extension.
|
||||
|
||||
8. sftp: Extension request "posix-rename@openssh.com"
|
||||
|
||||
This operation provides a rename operation with POSIX semantics, which
|
||||
are different to those provided by the standard SSH_FXP_RENAME in
|
||||
draft-ietf-secsh-filexfer-02.txt. This request is implemented as a
|
||||
SSH_FXP_EXTENDED request with the following format:
|
||||
|
||||
uint32 id
|
||||
string "posix-rename@openssh.com"
|
||||
string oldpath
|
||||
string newpath
|
||||
|
||||
On receiving this request the server will perform the POSIX operation
|
||||
rename(oldpath, newpath) and will respond with a SSH_FXP_STATUS message.
|
||||
This extension is advertised in the SSH_FXP_VERSION hello with version
|
||||
"1".
|
||||
|
||||
9. sftp: Extension requests "statvfs@openssh.com" and
|
||||
"fstatvfs@openssh.com"
|
||||
|
||||
These requests correspond to the statvfs and fstatvfs POSIX system
|
||||
interfaces. The "statvfs@openssh.com" request operates on an explicit
|
||||
pathname, and is formatted as follows:
|
||||
|
||||
uint32 id
|
||||
string "statvfs@openssh.com"
|
||||
string path
|
||||
|
||||
The "fstatvfs@openssh.com" operates on an open file handle:
|
||||
|
||||
uint32 id
|
||||
string "fstatvfs@openssh.com"
|
||||
string handle
|
||||
|
||||
These requests return a SSH_FXP_STATUS reply on failure. On success they
|
||||
return the following SSH_FXP_EXTENDED_REPLY reply:
|
||||
|
||||
uint32 id
|
||||
uint64 f_bsize /* file system block size */
|
||||
uint64 f_frsize /* fundamental fs block size */
|
||||
uint64 f_blocks /* number of blocks (unit f_frsize) */
|
||||
uint64 f_bfree /* free blocks in file system */
|
||||
uint64 f_bavail /* free blocks for non-root */
|
||||
uint64 f_files /* total file inodes */
|
||||
uint64 f_ffree /* free file inodes */
|
||||
uint64 f_favail /* free file inodes for to non-root */
|
||||
uint64 f_fsid /* file system id */
|
||||
uint64 f_flag /* bit mask of f_flag values */
|
||||
uint64 f_namemax /* maximum filename length */
|
||||
|
||||
The values of the f_flag bitmask are as follows:
|
||||
|
||||
#define SSH_FXE_STATVFS_ST_RDONLY 0x1 /* read-only */
|
||||
#define SSH_FXE_STATVFS_ST_NOSUID 0x2 /* no setuid */
|
||||
|
||||
Both the "statvfs@openssh.com" and "fstatvfs@openssh.com" extensions are
|
||||
advertised in the SSH_FXP_VERSION hello with version "2".
|
||||
|
||||
$OpenBSD: PROTOCOL,v 1.11 2008/07/05 05:16:01 djm Exp $
|
516
PROTOCOL.agent
Normal file
516
PROTOCOL.agent
Normal file
@ -0,0 +1,516 @@
|
||||
This describes the protocol used by OpenSSH's ssh-agent.
|
||||
|
||||
OpenSSH's agent supports managing keys for the standard SSH protocol
|
||||
2 as well as the legacy SSH protocol 1. Support for these key types
|
||||
is almost completely disjoint - in all but a few cases, operations on
|
||||
protocol 2 keys cannot see or affect protocol 1 keys and vice-versa.
|
||||
|
||||
Protocol 1 and protocol 2 keys are separated because of the differing
|
||||
cryptographic usage: protocol 1 private RSA keys are used to decrypt
|
||||
challenges that were encrypted with the corresponding public key,
|
||||
whereas protocol 2 RSA private keys are used to sign challenges with
|
||||
a private key for verification with the corresponding public key. It
|
||||
is considered unsound practice to use the same key for signing and
|
||||
encryption.
|
||||
|
||||
With a couple of exceptions, the protocol message names used in this
|
||||
document indicate which type of key the message relates to. SSH_*
|
||||
messages refer to protocol 1 keys only. SSH2_* messages refer to
|
||||
protocol 2 keys. Furthermore, the names also indicate whether the
|
||||
message is a request to the agent (*_AGENTC_*) or a reply from the
|
||||
agent (*_AGENT_*). Section 3 below contains the mapping of the
|
||||
protocol message names to their integer values.
|
||||
|
||||
1. Data types
|
||||
|
||||
Because of support for legacy SSH protocol 1 keys, OpenSSH's agent
|
||||
protocol makes use of some data types not defined in RFC 4251.
|
||||
|
||||
1.1 uint16
|
||||
|
||||
The "uint16" data type is a simple MSB-first 16 bit unsigned integer
|
||||
encoded in two bytes.
|
||||
|
||||
1.2 mpint1
|
||||
|
||||
The "mpint1" type represents an arbitrary precision integer (bignum).
|
||||
Its format is as follows:
|
||||
|
||||
uint16 bits
|
||||
byte[(bits + 7) / 8] bignum
|
||||
|
||||
"bignum" contains an unsigned arbitrary precision integer encoded as
|
||||
eight bits per byte in big-endian (MSB first) format.
|
||||
|
||||
Note the difference between the "mpint1" encoding and the "mpint"
|
||||
encoding defined in RFC 4251. Also note that the length of the encoded
|
||||
integer is specified in bits, not bytes and that the byte length of
|
||||
the integer must be calculated by rounding up the number of bits to the
|
||||
nearest eight.
|
||||
|
||||
2. Protocol Messages
|
||||
|
||||
All protocol messages are prefixed with their length in bytes, encoded
|
||||
as a 32 bit unsigned integer. Specifically:
|
||||
|
||||
uint32 message_length
|
||||
byte[message_length] message
|
||||
|
||||
The following message descriptions refer only to the content the
|
||||
"message" field.
|
||||
|
||||
2.1 Generic server responses
|
||||
|
||||
The following generic messages may be sent by the server in response to
|
||||
requests from the client. On success the agent may reply either with:
|
||||
|
||||
byte SSH_AGENT_SUCCESS
|
||||
|
||||
or a request-specific success message.
|
||||
|
||||
On failure, the agent may reply with:
|
||||
|
||||
byte SSH_AGENT_FAILURE
|
||||
|
||||
SSH_AGENT_FAILURE messages are also sent in reply to unknown request
|
||||
types.
|
||||
|
||||
2.2 Adding keys to the agent
|
||||
|
||||
Keys are added to the agent using the SSH_AGENTC_ADD_RSA_IDENTITY and
|
||||
SSH2_AGENTC_ADD_IDENTITY requests for protocol 1 and protocol 2 keys
|
||||
respectively.
|
||||
|
||||
Two variants of these requests are SSH_AGENTC_ADD_RSA_ID_CONSTRAINED
|
||||
and SSH2_AGENTC_ADD_ID_CONSTRAINED - these add keys with optional
|
||||
"constraints" on their usage.
|
||||
|
||||
OpenSSH may be built with support for keys hosted on a smartcard
|
||||
or other hardware security module. These keys may be added
|
||||
to the agent using the SSH_AGENTC_ADD_SMARTCARD_KEY and
|
||||
SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED requests.
|
||||
|
||||
2.2.1 Key constraints
|
||||
|
||||
The OpenSSH agent supports some basic optional constraints on key usage.
|
||||
At present there are two constraints defined.
|
||||
|
||||
The first constraint limits the validity duration of a key. It is
|
||||
encoded as:
|
||||
|
||||
byte SSH_AGENT_CONSTRAIN_LIFETIME
|
||||
uint32 seconds
|
||||
|
||||
Where "seconds" contains the number of seconds that the key shall remain
|
||||
valid measured from the moment that the agent receives it. After the
|
||||
validity period has expired, OpenSSH's agent will erase these keys from
|
||||
memory.
|
||||
|
||||
The second constraint requires the agent to seek explicit user
|
||||
confirmation before performing private key operations with the loaded
|
||||
key. This constraint is encoded as:
|
||||
|
||||
byte SSH_AGENT_CONSTRAIN_CONFIRM
|
||||
|
||||
Zero or more constraints may be specified when adding a key with one
|
||||
of the *_CONSTRAINED requests. Multiple constraints are appended
|
||||
consecutively to the end of the request:
|
||||
|
||||
byte constraint1_type
|
||||
.... constraint1_data
|
||||
byte constraint2_type
|
||||
.... constraint2_data
|
||||
....
|
||||
byte constraintN_type
|
||||
.... constraintN_data
|
||||
|
||||
Such a sequence of zero or more constraints will be referred to below
|
||||
as "constraint[]". Agents may determine whether there are constraints
|
||||
by checking whether additional data exists in the "add key" request
|
||||
after the key data itself. OpenSSH will refuse to add a key if it
|
||||
contains unknown constraints.
|
||||
|
||||
2.2.2 Add protocol 1 key
|
||||
|
||||
A client may add a protocol 1 key to an agent with the following
|
||||
request:
|
||||
|
||||
byte SSH_AGENTC_ADD_RSA_IDENTITY or
|
||||
SSH_AGENTC_ADD_RSA_ID_CONSTRAINED
|
||||
uint32 ignored
|
||||
mpint1 rsa_n
|
||||
mpint1 rsa_e
|
||||
mpint1 rsa_d
|
||||
mpint1 rsa_iqmp
|
||||
mpint1 rsa_q
|
||||
mpint1 rsa_p
|
||||
string key_comment
|
||||
constraint[] key_constraints
|
||||
|
||||
Note that there is some redundancy in the key parameters; a key could be
|
||||
fully specified using just rsa_q, rsa_p and rsa_e at the cost of extra
|
||||
computation.
|
||||
|
||||
"key_constraints" may only be present if the request type is
|
||||
SSH_AGENTC_ADD_RSA_IDENTITY.
|
||||
|
||||
The agent will reply with a SSH_AGENT_SUCCESS if the key has been
|
||||
successfully added or a SSH_AGENT_FAILURE if an error occurred.
|
||||
|
||||
2.2.3 Add protocol 2 key
|
||||
|
||||
The OpenSSH agent supports DSA and RSA keys for protocol 2. DSA keys may
|
||||
be added using the following request
|
||||
|
||||
byte SSH2_AGENTC_ADD_IDENTITY or
|
||||
SSH2_AGENTC_ADD_ID_CONSTRAINED
|
||||
string "ssh-dss"
|
||||
mpint dsa_p
|
||||
mpint dsa_q
|
||||
mpint dsa_g
|
||||
mpint dsa_public_key
|
||||
mpint dsa_private_key
|
||||
string key_comment
|
||||
constraint[] key_constraints
|
||||
|
||||
RSA keys may be added with this request:
|
||||
|
||||
byte SSH2_AGENTC_ADD_IDENTITY or
|
||||
SSH2_AGENTC_ADD_ID_CONSTRAINED
|
||||
string "ssh-rsa"
|
||||
mpint rsa_n
|
||||
mpint rsa_e
|
||||
mpint rsa_d
|
||||
mpint rsa_iqmp
|
||||
mpint rsa_p
|
||||
mpint rsa_q
|
||||
string key_comment
|
||||
constraint[] key_constraints
|
||||
|
||||
Note that the 'rsa_p' and 'rsa_q' parameters are sent in the reverse
|
||||
order to the protocol 1 add keys message. As with the corresponding
|
||||
protocol 1 "add key" request, the private key is overspecified to avoid
|
||||
redundant processing.
|
||||
|
||||
For both DSA and RSA key add requests, "key_constraints" may only be
|
||||
present if the request type is SSH2_AGENTC_ADD_ID_CONSTRAINED.
|
||||
|
||||
The agent will reply with a SSH_AGENT_SUCCESS if the key has been
|
||||
successfully added or a SSH_AGENT_FAILURE if an error occurred.
|
||||
|
||||
2.2.4 Loading keys from a smartcard
|
||||
|
||||
The OpenSSH agent may have optional smartcard support built in to it. If
|
||||
so, it supports an operation to load keys from a smartcard. Technically,
|
||||
only the public components of the keys are loaded into the agent so
|
||||
this operation really arranges for future private key operations to be
|
||||
delegated to the smartcard.
|
||||
|
||||
byte SSH_AGENTC_ADD_SMARTCARD_KEY or
|
||||
SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED
|
||||
string reader_id
|
||||
string pin
|
||||
constraint[] key_constraints
|
||||
|
||||
"reader_id" is an identifier to a smartcard reader and "pin"
|
||||
is a PIN or passphrase used to unlock the private key(s) on the
|
||||
device. "key_constraints" may only be present if the request type is
|
||||
SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED.
|
||||
|
||||
This operation may load all SSH keys that are unlocked using the
|
||||
"pin" on the specified reader. The type of key loaded (protocol 1
|
||||
or protocol 2) will be specified by the smartcard itself, it is not
|
||||
client-specified.
|
||||
|
||||
The agent will reply with a SSH_AGENT_SUCCESS if one or more keys have
|
||||
been successfully loaded or a SSH_AGENT_FAILURE if an error occurred.
|
||||
The agent will also return SSH_AGENT_FAILURE if it does not support
|
||||
smartcards.
|
||||
|
||||
2.3 Removing multiple keys
|
||||
|
||||
A client may request that an agent delete all protocol 1 keys using the
|
||||
following request:
|
||||
|
||||
byte SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES
|
||||
|
||||
This message requests the deletion of all protocol 2 keys:
|
||||
|
||||
byte SSH2_AGENTC_REMOVE_ALL_IDENTITIES
|
||||
|
||||
On success, the agent will delete all keys of the requested type and
|
||||
reply with a SSH_AGENT_SUCCESS message. If an error occurred, the agent
|
||||
will reply with SSH_AGENT_FAILURE.
|
||||
|
||||
Note that, to delete all keys (both protocol 1 and 2), a client
|
||||
must send both a SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES and a
|
||||
SSH2_AGENTC_REMOVE_ALL_IDENTITIES request.
|
||||
|
||||
2.4 Removing specific keys
|
||||
|
||||
2.4.1 Removing a protocol 1 key
|
||||
|
||||
Removal of a protocol 1 key may be requested with the following message:
|
||||
|
||||
byte SSH_AGENTC_REMOVE_RSA_IDENTITY
|
||||
uint32 key_bits
|
||||
mpint1 rsa_e
|
||||
mpint1 rsa_n
|
||||
|
||||
Note that key_bits is strictly redundant, as it may be inferred by the
|
||||
length of rsa_n.
|
||||
|
||||
The agent will delete any private key matching the specified public key
|
||||
and return SSH_AGENT_SUCCESS. If no such key was found, the agent will
|
||||
return SSH_AGENT_FAILURE.
|
||||
|
||||
2.4.2 Removing a protocol 2 key
|
||||
|
||||
Protocol 2 keys may be removed with the following request:
|
||||
|
||||
byte SSH2_AGENTC_REMOVE_IDENTITY
|
||||
string key_blob
|
||||
|
||||
Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
|
||||
Algorithms" for either of the supported key types: "ssh-dss" or
|
||||
"ssh-rsa".
|
||||
|
||||
The agent will delete any private key matching the specified public key
|
||||
and return SSH_AGENT_SUCCESS. If no such key was found, the agent will
|
||||
return SSH_AGENT_FAILURE.
|
||||
|
||||
2.4.3 Removing keys loaded from a smartcard
|
||||
|
||||
A client may request that a server remove one or more smartcard-hosted
|
||||
keys using this message:
|
||||
|
||||
byte SSH_AGENTC_REMOVE_SMARTCARD_KEY
|
||||
string reader_id
|
||||
string pin
|
||||
|
||||
"reader_id" the an identifier to a smartcard reader and "pin" is a PIN
|
||||
or passphrase used to unlock the private key(s) on the device.
|
||||
|
||||
When this message is received, and if the agent supports
|
||||
smartcard-hosted keys, it will delete all keys that are hosted on the
|
||||
specified smartcard that may be accessed with the given "pin".
|
||||
|
||||
The agent will reply with a SSH_AGENT_SUCCESS if one or more keys have
|
||||
been successfully removed or a SSH_AGENT_FAILURE if an error occurred.
|
||||
The agent will also return SSH_AGENT_FAILURE if it does not support
|
||||
smartcards.
|
||||
|
||||
2.5 Requesting a list of known keys
|
||||
|
||||
An agent may be requested to list which keys it holds. Different
|
||||
requests exist for protocol 1 and protocol 2 keys.
|
||||
|
||||
2.5.1 Requesting a list of protocol 1 keys
|
||||
|
||||
To request a list of protocol 1 keys that are held in the agent, a
|
||||
client may send the following message:
|
||||
|
||||
byte SSH_AGENTC_REQUEST_RSA_IDENTITIES
|
||||
|
||||
The agent will reply with the following message:
|
||||
|
||||
byte SSH_AGENT_RSA_IDENTITIES_ANSWER
|
||||
uint32 num_keys
|
||||
|
||||
Followed by zero or more consecutive keys, encoded as:
|
||||
|
||||
uint32 bits
|
||||
mpint1 rsa_e
|
||||
mpint1 rsa_n
|
||||
string key_comment
|
||||
|
||||
2.5.2 Requesting a list of protocol 2 keys
|
||||
|
||||
A client may send the following message to request a list of
|
||||
protocol 2 keys that are stored in the agent:
|
||||
|
||||
byte SSH2_AGENTC_REQUEST_IDENTITIES
|
||||
|
||||
The agent will reply with the following message header:
|
||||
|
||||
byte SSH2_AGENT_IDENTITIES_ANSWER
|
||||
uint32 num_keys
|
||||
|
||||
Followed by zero or more consecutive keys, encoded as:
|
||||
|
||||
string key_blob
|
||||
string key_comment
|
||||
|
||||
Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
|
||||
Algorithms" for either of the supported key types: "ssh-dss" or
|
||||
"ssh-rsa".
|
||||
|
||||
2.6 Private key operations
|
||||
|
||||
The purpose of the agent is to perform private key operations, such as
|
||||
signing and encryption without requiring a passphrase to unlock the
|
||||
key and without allowing the private key itself to be exposed. There
|
||||
are separate requests for the protocol 1 and protocol 2 private key
|
||||
operations.
|
||||
|
||||
2.6.1 Protocol 1 private key challenge
|
||||
|
||||
The private key operation used in version 1 of the SSH protocol is
|
||||
decrypting a challenge that has been encrypted with a public key.
|
||||
It may be requested using this message:
|
||||
|
||||
byte SSH_AGENTC_RSA_CHALLENGE
|
||||
uint32 ignored
|
||||
mpint1 rsa_e
|
||||
mpint1 rsa_n
|
||||
mpint1 encrypted_challenge
|
||||
byte[16] session_id
|
||||
uint32 response_type /* must be 1 */
|
||||
|
||||
"rsa_e" and "rsa_n" are used to identify which private key to use.
|
||||
"encrypted_challenge" is a challenge blob that has (presumably)
|
||||
been encrypted with the public key and must be in the range
|
||||
1 <= encrypted_challenge < 2^256. "session_id" is the SSH protocol 1
|
||||
session ID (computed from the server host key, the server semi-ephemeral
|
||||
key and the session cookie).
|
||||
|
||||
"ignored" and "response_type" exist for compatibility with legacy
|
||||
implementations. "response_type" must be equal to 1; other response
|
||||
types are not supported.
|
||||
|
||||
On receiving this request, the server decrypts the "encrypted_challenge"
|
||||
using the private key matching the supplied (rsa_e, rsa_n) values. For
|
||||
the response derivation, the decrypted challenge is represented as an
|
||||
unsigned, big-endian integer encoded in a 32 byte buffer (i.e. values
|
||||
smaller than 2^248 will have leading 0 bytes).
|
||||
|
||||
The response value is then calculated as:
|
||||
|
||||
response = MD5(decrypted_challenge || session_id)
|
||||
|
||||
and returned in the following message
|
||||
|
||||
byte SSH_AGENT_RSA_RESPONSE
|
||||
byte[16] response
|
||||
|
||||
If the agent cannot find the key specified by the supplied (rsa_e,
|
||||
rsa_n) then it will return SSH_AGENT_FAILURE.
|
||||
|
||||
2.6.2 Protocol 2 private key signature request
|
||||
|
||||
A client may use the following message to request signing of data using
|
||||
a protocol 2 key:
|
||||
|
||||
byte SSH2_AGENTC_SIGN_REQUEST
|
||||
string key_blob
|
||||
string data
|
||||
uint32 flags
|
||||
|
||||
Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
|
||||
Algorithms" for either of the supported key types: "ssh-dss" or
|
||||
"ssh-rsa". "flags" is a bit-mask, but at present only one possible value
|
||||
is defined (see below for its meaning):
|
||||
|
||||
SSH_AGENT_OLD_SIGNATURE 1
|
||||
|
||||
Upon receiving this request, the agent will look up the private key that
|
||||
corresponds to the public key contained in key_blob. It will use this
|
||||
private key to sign the "data" and produce a signature blob using the
|
||||
key type-specific method described in RFC 4253 section 6.6 "Public Key
|
||||
Algorithms".
|
||||
|
||||
An exception to this is for "ssh-dss" keys where the "flags" word
|
||||
contains the value SSH_AGENT_OLD_SIGNATURE. In this case, a legacy
|
||||
signature encoding is used in lieu of the standard one. In this case,
|
||||
the DSA signature blob is encoded as:
|
||||
|
||||
byte[40] signature
|
||||
|
||||
The signature will be returned in the response message:
|
||||
|
||||
byte SSH2_AGENT_SIGN_RESPONSE
|
||||
string signature_blob
|
||||
|
||||
If the agent cannot find the key specified by the supplied key_blob then
|
||||
it will return SSH_AGENT_FAILURE.
|
||||
|
||||
2.7 Locking or unlocking an agent
|
||||
|
||||
The agent supports temporary locking with a passphrase to suspend
|
||||
processing of sensitive operations until it has been unlocked with the
|
||||
same passphrase. To lock an agent, a client send the following request:
|
||||
|
||||
byte SSH_AGENTC_LOCK
|
||||
string passphrase
|
||||
|
||||
Upon receipt of this message and if the agent is not already locked,
|
||||
it will suspend processing requests and return a SSH_AGENT_SUCCESS
|
||||
reply. If the agent is already locked, it will return SSH_AGENT_FAILURE.
|
||||
|
||||
While locked, the agent will refuse all requests except
|
||||
SSH_AGENTC_UNLOCK, SSH_AGENTC_REQUEST_RSA_IDENTITIES and
|
||||
SSH2_AGENTC_REQUEST_IDENTITIES. The "request identities" requests are
|
||||
treated specially by a locked agent: it will always return an empty list
|
||||
of keys.
|
||||
|
||||
To unlock an agent, a client may request:
|
||||
|
||||
byte SSH_AGENTC_UNLOCK
|
||||
string passphrase
|
||||
|
||||
If the passphrase matches and the agent is locked, then it will resume
|
||||
processing all requests and return SSH_AGENT_SUCCESS. If the agent
|
||||
is not locked or the passphrase does not match then it will return
|
||||
SSH_AGENT_FAILURE.
|
||||
|
||||
Locking and unlocking affects both protocol 1 and protocol 2 keys.
|
||||
|
||||
3. Protocol message numbers
|
||||
|
||||
3.1 Requests from client to agent for protocol 1 key operations
|
||||
|
||||
SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
|
||||
SSH_AGENTC_RSA_CHALLENGE 3
|
||||
SSH_AGENTC_ADD_RSA_IDENTITY 7
|
||||
SSH_AGENTC_REMOVE_RSA_IDENTITY 8
|
||||
SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9
|
||||
SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24
|
||||
|
||||
3.2 Requests from client to agent for protocol 2 key operations
|
||||
|
||||
SSH2_AGENTC_REQUEST_IDENTITIES 11
|
||||
SSH2_AGENTC_SIGN_REQUEST 13
|
||||
SSH2_AGENTC_ADD_IDENTITY 17
|
||||
SSH2_AGENTC_REMOVE_IDENTITY 18
|
||||
SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19
|
||||
SSH2_AGENTC_ADD_ID_CONSTRAINED 25
|
||||
|
||||
3.3 Key-type independent requests from client to agent
|
||||
|
||||
SSH_AGENTC_ADD_SMARTCARD_KEY 20
|
||||
SSH_AGENTC_REMOVE_SMARTCARD_KEY 21
|
||||
SSH_AGENTC_LOCK 22
|
||||
SSH_AGENTC_UNLOCK 23
|
||||
SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
|
||||
|
||||
3.4 Generic replies from agent to client
|
||||
|
||||
SSH_AGENT_FAILURE 5
|
||||
SSH_AGENT_SUCCESS 6
|
||||
|
||||
3.5 Replies from agent to client for protocol 1 key operations
|
||||
|
||||
SSH_AGENT_RSA_IDENTITIES_ANSWER 2
|
||||
SSH_AGENT_RSA_RESPONSE 4
|
||||
|
||||
3.6 Replies from agent to client for protocol 2 key operations
|
||||
|
||||
SSH2_AGENT_IDENTITIES_ANSWER 12
|
||||
SSH2_AGENT_SIGN_RESPONSE 14
|
||||
|
||||
3.7 Key constraint identifiers
|
||||
|
||||
SSH_AGENT_CONSTRAIN_LIFETIME 1
|
||||
SSH_AGENT_CONSTRAIN_CONFIRM 2
|
||||
|
||||
$OpenBSD: PROTOCOL.agent,v 1.4 2008/07/01 23:12:47 stevesk Exp $
|
4
README
4
README
@ -1,4 +1,4 @@
|
||||
See http://www.openssh.com/txt/release-5.0 for the release notes.
|
||||
See http://www.openssh.com/txt/release-5.1 for the release notes.
|
||||
|
||||
- A Japanese translation of this document and of the OpenSSH FAQ is
|
||||
- available at http://www.unixuser.org/~haruyama/security/openssh/index.html
|
||||
@ -62,4 +62,4 @@ References -
|
||||
[6] http://www.openbsd.org/cgi-bin/man.cgi?query=style&sektion=9
|
||||
[7] http://www.openssh.com/faq.html
|
||||
|
||||
$Id: README,v 1.68 2008/04/03 09:56:38 djm Exp $
|
||||
$Id: README,v 1.69 2008/07/21 08:21:52 djm Exp $
|
||||
|
421
addrmatch.c
Normal file
421
addrmatch.c
Normal file
@ -0,0 +1,421 @@
|
||||
/* $OpenBSD: addrmatch.c,v 1.3 2008/06/10 23:06:19 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004-2008 Damien Miller <djm@mindrot.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "match.h"
|
||||
#include "log.h"
|
||||
|
||||
struct xaddr {
|
||||
sa_family_t af;
|
||||
union {
|
||||
struct in_addr v4;
|
||||
struct in6_addr v6;
|
||||
u_int8_t addr8[16];
|
||||
u_int32_t addr32[4];
|
||||
} xa; /* 128-bit address */
|
||||
u_int32_t scope_id; /* iface scope id for v6 */
|
||||
#define v4 xa.v4
|
||||
#define v6 xa.v6
|
||||
#define addr8 xa.addr8
|
||||
#define addr32 xa.addr32
|
||||
};
|
||||
|
||||
static int
|
||||
addr_unicast_masklen(int af)
|
||||
{
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
return 32;
|
||||
case AF_INET6:
|
||||
return 128;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
masklen_valid(int af, u_int masklen)
|
||||
{
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
return masklen <= 32 ? 0 : -1;
|
||||
case AF_INET6:
|
||||
return masklen <= 128 ? 0 : -1;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert struct sockaddr to struct xaddr
|
||||
* Returns 0 on success, -1 on failure.
|
||||
*/
|
||||
static int
|
||||
addr_sa_to_xaddr(struct sockaddr *sa, socklen_t slen, struct xaddr *xa)
|
||||
{
|
||||
struct sockaddr_in *in4 = (struct sockaddr_in *)sa;
|
||||
struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
|
||||
|
||||
memset(xa, '\0', sizeof(*xa));
|
||||
|
||||
switch (sa->sa_family) {
|
||||
case AF_INET:
|
||||
if (slen < sizeof(*in4))
|
||||
return -1;
|
||||
xa->af = AF_INET;
|
||||
memcpy(&xa->v4, &in4->sin_addr, sizeof(xa->v4));
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (slen < sizeof(*in6))
|
||||
return -1;
|
||||
xa->af = AF_INET6;
|
||||
memcpy(&xa->v6, &in6->sin6_addr, sizeof(xa->v6));
|
||||
xa->scope_id = in6->sin6_scope_id;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate a netmask of length 'l' for address family 'af' and
|
||||
* store it in 'n'.
|
||||
* Returns 0 on success, -1 on failure.
|
||||
*/
|
||||
static int
|
||||
addr_netmask(int af, u_int l, struct xaddr *n)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (masklen_valid(af, l) != 0 || n == NULL)
|
||||
return -1;
|
||||
|
||||
memset(n, '\0', sizeof(*n));
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
n->af = AF_INET;
|
||||
n->v4.s_addr = htonl((0xffffffff << (32 - l)) & 0xffffffff);
|
||||
return 0;
|
||||
case AF_INET6:
|
||||
n->af = AF_INET6;
|
||||
for (i = 0; i < 4 && l >= 32; i++, l -= 32)
|
||||
n->addr32[i] = 0xffffffffU;
|
||||
if (i < 4 && l != 0)
|
||||
n->addr32[i] = htonl((0xffffffff << (32 - l)) &
|
||||
0xffffffff);
|
||||
return 0;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform logical AND of addresses 'a' and 'b', storing result in 'dst'.
|
||||
* Returns 0 on success, -1 on failure.
|
||||
*/
|
||||
static int
|
||||
addr_and(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (dst == NULL || a == NULL || b == NULL || a->af != b->af)
|
||||
return -1;
|
||||
|
||||
memcpy(dst, a, sizeof(*dst));
|
||||
switch (a->af) {
|
||||
case AF_INET:
|
||||
dst->v4.s_addr &= b->v4.s_addr;
|
||||
return 0;
|
||||
case AF_INET6:
|
||||
dst->scope_id = a->scope_id;
|
||||
for (i = 0; i < 4; i++)
|
||||
dst->addr32[i] &= b->addr32[i];
|
||||
return 0;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare addresses 'a' and 'b'
|
||||
* Return 0 if addresses are identical, -1 if (a < b) or 1 if (a > b)
|
||||
*/
|
||||
static int
|
||||
addr_cmp(const struct xaddr *a, const struct xaddr *b)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (a->af != b->af)
|
||||
return a->af == AF_INET6 ? 1 : -1;
|
||||
|
||||
switch (a->af) {
|
||||
case AF_INET:
|
||||
if (a->v4.s_addr == b->v4.s_addr)
|
||||
return 0;
|
||||
return ntohl(a->v4.s_addr) > ntohl(b->v4.s_addr) ? 1 : -1;
|
||||
case AF_INET6:
|
||||
for (i = 0; i < 16; i++)
|
||||
if (a->addr8[i] - b->addr8[i] != 0)
|
||||
return a->addr8[i] > b->addr8[i] ? 1 : -1;
|
||||
if (a->scope_id == b->scope_id)
|
||||
return 0;
|
||||
return a->scope_id > b->scope_id ? 1 : -1;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse string address 'p' into 'n'
|
||||
* Returns 0 on success, -1 on failure.
|
||||
*/
|
||||
static int
|
||||
addr_pton(const char *p, struct xaddr *n)
|
||||
{
|
||||
struct addrinfo hints, *ai;
|
||||
|
||||
memset(&hints, '\0', sizeof(hints));
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
|
||||
if (p == NULL || getaddrinfo(p, NULL, &hints, &ai) != 0)
|
||||
return -1;
|
||||
|
||||
if (ai == NULL || ai->ai_addr == NULL)
|
||||
return -1;
|
||||
|
||||
if (n != NULL &&
|
||||
addr_sa_to_xaddr(ai->ai_addr, ai->ai_addrlen, n) == -1) {
|
||||
freeaddrinfo(ai);
|
||||
return -1;
|
||||
}
|
||||
|
||||
freeaddrinfo(ai);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform bitwise negation of address
|
||||
* Returns 0 on success, -1 on failure.
|
||||
*/
|
||||
static int
|
||||
addr_invert(struct xaddr *n)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (n == NULL)
|
||||
return (-1);
|
||||
|
||||
switch (n->af) {
|
||||
case AF_INET:
|
||||
n->v4.s_addr = ~n->v4.s_addr;
|
||||
return (0);
|
||||
case AF_INET6:
|
||||
for (i = 0; i < 4; i++)
|
||||
n->addr32[i] = ~n->addr32[i];
|
||||
return (0);
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate a netmask of length 'l' for address family 'af' and
|
||||
* store it in 'n'.
|
||||
* Returns 0 on success, -1 on failure.
|
||||
*/
|
||||
static int
|
||||
addr_hostmask(int af, u_int l, struct xaddr *n)
|
||||
{
|
||||
if (addr_netmask(af, l, n) == -1 || addr_invert(n) == -1)
|
||||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether address 'a' is all zeros (i.e. 0.0.0.0 or ::)
|
||||
* Returns 0 on if address is all-zeros, -1 if not all zeros or on failure.
|
||||
*/
|
||||
static int
|
||||
addr_is_all0s(const struct xaddr *a)
|
||||
{
|
||||
int i;
|
||||
|
||||
switch (a->af) {
|
||||
case AF_INET:
|
||||
return (a->v4.s_addr == 0 ? 0 : -1);
|
||||
case AF_INET6:;
|
||||
for (i = 0; i < 4; i++)
|
||||
if (a->addr32[i] != 0)
|
||||
return (-1);
|
||||
return (0);
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether host portion of address 'a', as determined by 'masklen'
|
||||
* is all zeros.
|
||||
* Returns 0 on if host portion of address is all-zeros,
|
||||
* -1 if not all zeros or on failure.
|
||||
*/
|
||||
static int
|
||||
addr_host_is_all0s(const struct xaddr *a, u_int masklen)
|
||||
{
|
||||
struct xaddr tmp_addr, tmp_mask, tmp_result;
|
||||
|
||||
memcpy(&tmp_addr, a, sizeof(tmp_addr));
|
||||
if (addr_hostmask(a->af, masklen, &tmp_mask) == -1)
|
||||
return (-1);
|
||||
if (addr_and(&tmp_result, &tmp_addr, &tmp_mask) == -1)
|
||||
return (-1);
|
||||
return (addr_is_all0s(&tmp_result));
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a CIDR address (x.x.x.x/y or xxxx:yyyy::/z).
|
||||
* Return -1 on parse error, -2 on inconsistency or 0 on success.
|
||||
*/
|
||||
static int
|
||||
addr_pton_cidr(const char *p, struct xaddr *n, u_int *l)
|
||||
{
|
||||
struct xaddr tmp;
|
||||
long unsigned int masklen = 999;
|
||||
char addrbuf[64], *mp, *cp;
|
||||
|
||||
/* Don't modify argument */
|
||||
if (p == NULL || strlcpy(addrbuf, p, sizeof(addrbuf)) > sizeof(addrbuf))
|
||||
return -1;
|
||||
|
||||
if ((mp = strchr(addrbuf, '/')) != NULL) {
|
||||
*mp = '\0';
|
||||
mp++;
|
||||
masklen = strtoul(mp, &cp, 10);
|
||||
if (*mp == '\0' || *cp != '\0' || masklen > 128)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (addr_pton(addrbuf, &tmp) == -1)
|
||||
return -1;
|
||||
|
||||
if (mp == NULL)
|
||||
masklen = addr_unicast_masklen(tmp.af);
|
||||
if (masklen_valid(tmp.af, masklen) == -1)
|
||||
return -2;
|
||||
if (addr_host_is_all0s(&tmp, masklen) != 0)
|
||||
return -2;
|
||||
|
||||
if (n != NULL)
|
||||
memcpy(n, &tmp, sizeof(*n));
|
||||
if (l != NULL)
|
||||
*l = masklen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
addr_netmatch(const struct xaddr *host, const struct xaddr *net, u_int masklen)
|
||||
{
|
||||
struct xaddr tmp_mask, tmp_result;
|
||||
|
||||
if (host->af != net->af)
|
||||
return -1;
|
||||
|
||||
if (addr_netmask(host->af, masklen, &tmp_mask) == -1)
|
||||
return -1;
|
||||
if (addr_and(&tmp_result, host, &tmp_mask) == -1)
|
||||
return -1;
|
||||
return addr_cmp(&tmp_result, net);
|
||||
}
|
||||
|
||||
/*
|
||||
* Match "addr" against list pattern list "_list", which may contain a
|
||||
* mix of CIDR addresses and old-school wildcards.
|
||||
*
|
||||
* If addr is NULL, then no matching is performed, but _list is parsed
|
||||
* and checked for well-formedness.
|
||||
*
|
||||
* Returns 1 on match found (never returned when addr == NULL).
|
||||
* Returns 0 on if no match found, or no errors found when addr == NULL.
|
||||
* Returns -1 on negated match found (never returned when addr == NULL).
|
||||
* Returns -2 on invalid list entry.
|
||||
*/
|
||||
int
|
||||
addr_match_list(const char *addr, const char *_list)
|
||||
{
|
||||
char *list, *cp, *o;
|
||||
struct xaddr try_addr, match_addr;
|
||||
u_int masklen, neg;
|
||||
int ret = 0, r;
|
||||
|
||||
if (addr != NULL && addr_pton(addr, &try_addr) != 0) {
|
||||
debug2("%s: couldn't parse address %.100s", __func__, addr);
|
||||
return 0;
|
||||
}
|
||||
if ((o = list = strdup(_list)) == NULL)
|
||||
return -1;
|
||||
while ((cp = strsep(&list, ",")) != NULL) {
|
||||
neg = *cp == '!';
|
||||
if (neg)
|
||||
cp++;
|
||||
if (*cp == '\0') {
|
||||
ret = -2;
|
||||
break;
|
||||
}
|
||||
/* Prefer CIDR address matching */
|
||||
r = addr_pton_cidr(cp, &match_addr, &masklen);
|
||||
if (r == -2) {
|
||||
error("Inconsistent mask length for "
|
||||
"network \"%.100s\"", cp);
|
||||
ret = -2;
|
||||
break;
|
||||
} else if (r == 0) {
|
||||
if (addr != NULL && addr_netmatch(&try_addr,
|
||||
&match_addr, masklen) == 0) {
|
||||
foundit:
|
||||
if (neg) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
ret = 1;
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
/* If CIDR parse failed, try wildcard string match */
|
||||
if (addr != NULL && match_pattern(addr, cp) == 1)
|
||||
goto foundit;
|
||||
}
|
||||
}
|
||||
free(o);
|
||||
|
||||
return ret;
|
||||
}
|
12
atomicio.c
12
atomicio.c
@ -63,11 +63,7 @@ atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
|
||||
case -1:
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
#ifdef EWOULDBLOCK
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
#else
|
||||
if (errno == EAGAIN) {
|
||||
#endif
|
||||
(void)poll(&pfd, 1, -1);
|
||||
continue;
|
||||
}
|
||||
@ -101,20 +97,20 @@ atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd,
|
||||
/* Make a copy of the iov array because we may modify it below */
|
||||
memcpy(iov, _iov, iovcnt * sizeof(*_iov));
|
||||
|
||||
#ifndef BROKEN_READV_COMPARISON
|
||||
pfd.fd = fd;
|
||||
pfd.events = f == readv ? POLLIN : POLLOUT;
|
||||
#endif
|
||||
for (; iovcnt > 0 && iov[0].iov_len > 0;) {
|
||||
res = (f) (fd, iov, iovcnt);
|
||||
switch (res) {
|
||||
case -1:
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
#ifdef EWOULDBLOCK
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
#else
|
||||
if (errno == EAGAIN) {
|
||||
#endif
|
||||
#ifndef BROKEN_READV_COMPARISON
|
||||
(void)poll(&pfd, 1, -1);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth-options.c,v 1.41 2008/03/26 21:28:14 djm Exp $ */
|
||||
/* $OpenBSD: auth-options.c,v 1.43 2008/06/10 23:06:19 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -20,6 +20,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "openbsd-compat/sys-queue.h"
|
||||
#include "xmalloc.h"
|
||||
#include "match.h"
|
||||
#include "log.h"
|
||||
@ -225,8 +226,19 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
|
||||
}
|
||||
patterns[i] = '\0';
|
||||
opts++;
|
||||
if (match_host_and_ip(remote_host, remote_ip,
|
||||
patterns) != 1) {
|
||||
switch (match_host_and_ip(remote_host, remote_ip,
|
||||
patterns)) {
|
||||
case 1:
|
||||
xfree(patterns);
|
||||
/* Host name matches. */
|
||||
goto next_option;
|
||||
case -1:
|
||||
debug("%.100s, line %lu: invalid criteria",
|
||||
file, linenum);
|
||||
auth_debug_add("%.100s, line %lu: "
|
||||
"invalid criteria", file, linenum);
|
||||
/* FALLTHROUGH */
|
||||
case 0:
|
||||
xfree(patterns);
|
||||
logit("Authentication tried for %.100s with "
|
||||
"correct key but not from a permitted "
|
||||
@ -235,12 +247,10 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
|
||||
auth_debug_add("Your host '%.200s' is not "
|
||||
"permitted to use this key for login.",
|
||||
remote_host);
|
||||
/* deny access */
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
xfree(patterns);
|
||||
/* Host name matches. */
|
||||
goto next_option;
|
||||
/* deny access */
|
||||
return 0;
|
||||
}
|
||||
cp = "permitopen=\"";
|
||||
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth-rhosts.c,v 1.41 2006/08/03 03:34:41 deraadt Exp $ */
|
||||
/* $OpenBSD: auth-rhosts.c,v 1.43 2008/06/13 14:18:51 dtucker Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -26,6 +26,8 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "packet.h"
|
||||
#include "buffer.h"
|
||||
@ -37,6 +39,7 @@
|
||||
#include "key.h"
|
||||
#include "hostfile.h"
|
||||
#include "auth.h"
|
||||
#include "misc.h"
|
||||
|
||||
/* import */
|
||||
extern ServerOptions options;
|
||||
@ -55,12 +58,27 @@ check_rhosts_file(const char *filename, const char *hostname,
|
||||
{
|
||||
FILE *f;
|
||||
char buf[1024]; /* Must not be larger than host, user, dummy below. */
|
||||
int fd;
|
||||
struct stat st;
|
||||
|
||||
/* Open the .rhosts file, deny if unreadable */
|
||||
f = fopen(filename, "r");
|
||||
if (!f)
|
||||
if ((fd = open(filename, O_RDONLY|O_NONBLOCK)) == -1)
|
||||
return 0;
|
||||
|
||||
if (fstat(fd, &st) == -1) {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
logit("User %s hosts file %s is not a regular file",
|
||||
server_user, filename);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
unset_nonblock(fd);
|
||||
if ((f = fdopen(fd, "r")) == NULL) {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
while (fgets(buf, sizeof(buf), f)) {
|
||||
/* All three must be at least as big as buf to avoid overflows. */
|
||||
char hostbuf[1024], userbuf[1024], dummy[1024], *host, *user, *cp;
|
||||
|
23
auth-rsa.c
23
auth-rsa.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth-rsa.c,v 1.72 2006/11/06 21:25:27 markus Exp $ */
|
||||
/* $OpenBSD: auth-rsa.c,v 1.73 2008/07/02 12:03:51 dtucker Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -173,7 +173,6 @@ auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
|
||||
u_int bits;
|
||||
FILE *f;
|
||||
u_long linenum = 0;
|
||||
struct stat st;
|
||||
Key *key;
|
||||
|
||||
/* Temporarily use the user's uid. */
|
||||
@ -182,27 +181,9 @@ auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
|
||||
/* The authorized keys. */
|
||||
file = authorized_keys_file(pw);
|
||||
debug("trying public RSA key file %s", file);
|
||||
|
||||
/* Fail quietly if file does not exist */
|
||||
if (stat(file, &st) < 0) {
|
||||
/* Restore the privileged uid. */
|
||||
restore_uid();
|
||||
xfree(file);
|
||||
return (0);
|
||||
}
|
||||
/* Open the file containing the authorized keys. */
|
||||
f = fopen(file, "r");
|
||||
f = auth_openkeyfile(file, pw, options.strict_modes);
|
||||
if (!f) {
|
||||
/* Restore the privileged uid. */
|
||||
restore_uid();
|
||||
xfree(file);
|
||||
return (0);
|
||||
}
|
||||
if (options.strict_modes &&
|
||||
secure_filename(f, file, pw, line, sizeof(line)) != 0) {
|
||||
xfree(file);
|
||||
fclose(f);
|
||||
logit("Authentication refused: %s", line);
|
||||
restore_uid();
|
||||
return (0);
|
||||
}
|
||||
|
53
auth-sia.c
53
auth-sia.c
@ -34,6 +34,10 @@
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/security.h>
|
||||
#include <prot.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "ssh.h"
|
||||
#include "key.h"
|
||||
@ -49,6 +53,52 @@ extern ServerOptions options;
|
||||
extern int saved_argc;
|
||||
extern char **saved_argv;
|
||||
|
||||
static int
|
||||
sia_password_change_required(const char *user)
|
||||
{
|
||||
struct es_passwd *acct;
|
||||
time_t pw_life;
|
||||
time_t pw_date;
|
||||
|
||||
set_auth_parameters(saved_argc, saved_argv);
|
||||
|
||||
if ((acct = getespwnam(user)) == NULL) {
|
||||
error("Couldn't access protected database entry for %s", user);
|
||||
endprpwent();
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* If forced password change flag is set, honor it */
|
||||
if (acct->uflg->fg_psw_chg_reqd && acct->ufld->fd_psw_chg_reqd) {
|
||||
endprpwent();
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Obtain password lifetime; if none, it can't have expired */
|
||||
if (acct->uflg->fg_expire)
|
||||
pw_life = acct->ufld->fd_expire;
|
||||
else if (acct->sflg->fg_expire)
|
||||
pw_life = acct->sfld->fd_expire;
|
||||
else {
|
||||
endprpwent();
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Offset from last change; if none, it must be expired */
|
||||
if (acct->uflg->fg_schange)
|
||||
pw_date = acct->ufld->fd_schange + pw_life;
|
||||
else {
|
||||
endprpwent();
|
||||
return (1);
|
||||
}
|
||||
|
||||
endprpwent();
|
||||
|
||||
/* If expiration date is prior to now, change password */
|
||||
|
||||
return (pw_date <= time((time_t *) NULL));
|
||||
}
|
||||
|
||||
int
|
||||
sys_auth_passwd(Authctxt *authctxt, const char *pass)
|
||||
{
|
||||
@ -76,6 +126,9 @@ sys_auth_passwd(Authctxt *authctxt, const char *pass)
|
||||
|
||||
sia_ses_release(&ent);
|
||||
|
||||
authctxt->force_pwchange = sia_password_change_required(
|
||||
authctxt->user);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
49
auth.c
49
auth.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth.c,v 1.78 2007/09/21 08:15:29 djm Exp $ */
|
||||
/* $OpenBSD: auth.c,v 1.79 2008/07/02 12:03:51 dtucker Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -32,6 +32,7 @@
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_PATHS_H
|
||||
# include <paths.h>
|
||||
#endif
|
||||
@ -48,6 +49,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "match.h"
|
||||
@ -113,6 +115,7 @@ allowed_user(struct passwd * pw)
|
||||
#endif /* USE_SHADOW */
|
||||
|
||||
/* grab passwd field for locked account check */
|
||||
passwd = pw->pw_passwd;
|
||||
#ifdef USE_SHADOW
|
||||
if (spw != NULL)
|
||||
#ifdef USE_LIBIAF
|
||||
@ -120,8 +123,6 @@ allowed_user(struct passwd * pw)
|
||||
#else
|
||||
passwd = spw->sp_pwdp;
|
||||
#endif /* USE_LIBIAF */
|
||||
#else
|
||||
passwd = pw->pw_passwd;
|
||||
#endif
|
||||
|
||||
/* check for locked account */
|
||||
@ -410,7 +411,7 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
|
||||
*
|
||||
* Returns 0 on success and -1 on failure
|
||||
*/
|
||||
int
|
||||
static int
|
||||
secure_filename(FILE *f, const char *file, struct passwd *pw,
|
||||
char *err, size_t errlen)
|
||||
{
|
||||
@ -470,6 +471,46 @@ secure_filename(FILE *f, const char *file, struct passwd *pw,
|
||||
return 0;
|
||||
}
|
||||
|
||||
FILE *
|
||||
auth_openkeyfile(const char *file, struct passwd *pw, int strict_modes)
|
||||
{
|
||||
char line[1024];
|
||||
struct stat st;
|
||||
int fd;
|
||||
FILE *f;
|
||||
|
||||
/*
|
||||
* Open the file containing the authorized keys
|
||||
* Fail quietly if file does not exist
|
||||
*/
|
||||
if ((fd = open(file, O_RDONLY|O_NONBLOCK)) == -1)
|
||||
return NULL;
|
||||
|
||||
if (fstat(fd, &st) < 0) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
logit("User %s authorized keys %s is not a regular file",
|
||||
pw->pw_name, file);
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
unset_nonblock(fd);
|
||||
if ((f = fdopen(fd, "r")) == NULL) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
if (options.strict_modes &&
|
||||
secure_filename(f, file, pw, line, sizeof(line)) != 0) {
|
||||
fclose(f);
|
||||
logit("Authentication refused: %s", line);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
struct passwd *
|
||||
getpwnamallow(const char *user)
|
||||
{
|
||||
|
5
auth.h
5
auth.h
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth.h,v 1.60 2007/09/21 08:15:29 djm Exp $ */
|
||||
/* $OpenBSD: auth.h,v 1.61 2008/07/02 12:03:51 dtucker Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
@ -166,8 +166,7 @@ void abandon_challenge_response(Authctxt *);
|
||||
char *authorized_keys_file(struct passwd *);
|
||||
char *authorized_keys_file2(struct passwd *);
|
||||
|
||||
int
|
||||
secure_filename(FILE *, const char *, struct passwd *, char *, size_t);
|
||||
FILE *auth_openkeyfile(const char *, struct passwd *, int);
|
||||
|
||||
HostStatus
|
||||
check_key_in_hostfiles(struct passwd *, Key *, const char *,
|
||||
|
9
auth1.c
9
auth1.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth1.c,v 1.71 2007/09/21 08:15:29 djm Exp $ */
|
||||
/* $OpenBSD: auth1.c,v 1.73 2008/07/04 23:30:16 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
* All rights reserved
|
||||
@ -20,6 +20,7 @@
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include "openbsd-compat/sys-queue.h"
|
||||
#include "xmalloc.h"
|
||||
#include "rsa.h"
|
||||
#include "ssh1.h"
|
||||
@ -283,6 +284,8 @@ do_authloop(Authctxt *authctxt)
|
||||
type != SSH_CMSG_AUTH_TIS_RESPONSE)
|
||||
abandon_challenge_response(authctxt);
|
||||
|
||||
if (authctxt->failures >= options.max_authtries)
|
||||
goto skip;
|
||||
if ((meth = lookup_authmethod1(type)) == NULL) {
|
||||
logit("Unknown message during authentication: "
|
||||
"type %d", type);
|
||||
@ -351,7 +354,7 @@ do_authloop(Authctxt *authctxt)
|
||||
msg[len] = '\0';
|
||||
else
|
||||
msg = "Access denied.";
|
||||
packet_disconnect(msg);
|
||||
packet_disconnect("%s", msg);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -367,7 +370,7 @@ do_authloop(Authctxt *authctxt)
|
||||
if (authenticated)
|
||||
return;
|
||||
|
||||
if (authctxt->failures++ > options.max_authtries) {
|
||||
if (++authctxt->failures >= options.max_authtries) {
|
||||
#ifdef SSH_AUDIT_EVENTS
|
||||
PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth2-hostbased.c,v 1.11 2006/08/03 03:34:41 deraadt Exp $ */
|
||||
/* $OpenBSD: auth2-hostbased.c,v 1.12 2008/07/17 08:51:07 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -151,15 +151,16 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
|
||||
debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s",
|
||||
chost, resolvedname, ipaddr);
|
||||
|
||||
if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
|
||||
debug2("stripping trailing dot from chost %s", chost);
|
||||
chost[len - 1] = '\0';
|
||||
}
|
||||
|
||||
if (options.hostbased_uses_name_from_packet_only) {
|
||||
if (auth_rhosts2(pw, cuser, chost, chost) == 0)
|
||||
return 0;
|
||||
lookup = chost;
|
||||
} else {
|
||||
if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
|
||||
debug2("stripping trailing dot from chost %s", chost);
|
||||
chost[len - 1] = '\0';
|
||||
}
|
||||
if (strcasecmp(resolvedname, chost) != 0)
|
||||
logit("userauth_hostbased mismatch: "
|
||||
"client sends %s, but we resolve %s to %s",
|
||||
|
72
auth2-none.c
72
auth2-none.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth2-none.c,v 1.14 2007/08/23 03:22:16 djm Exp $ */
|
||||
/* $OpenBSD: auth2-none.c,v 1.15 2008/07/02 12:36:39 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -31,9 +31,10 @@
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "atomicio.h"
|
||||
#include "xmalloc.h"
|
||||
#include "key.h"
|
||||
#include "hostfile.h"
|
||||
@ -42,7 +43,6 @@
|
||||
#include "log.h"
|
||||
#include "buffer.h"
|
||||
#include "servconf.h"
|
||||
#include "atomicio.h"
|
||||
#include "compat.h"
|
||||
#include "ssh2.h"
|
||||
#ifdef GSSAPI
|
||||
@ -56,77 +56,11 @@ extern ServerOptions options;
|
||||
/* "none" is allowed only one time */
|
||||
static int none_enabled = 1;
|
||||
|
||||
char *
|
||||
auth2_read_banner(void)
|
||||
{
|
||||
struct stat st;
|
||||
char *banner = NULL;
|
||||
size_t len, n;
|
||||
int fd;
|
||||
|
||||
if ((fd = open(options.banner, O_RDONLY)) == -1)
|
||||
return (NULL);
|
||||
if (fstat(fd, &st) == -1) {
|
||||
close(fd);
|
||||
return (NULL);
|
||||
}
|
||||
if (st.st_size > 1*1024*1024) {
|
||||
close(fd);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
len = (size_t)st.st_size; /* truncate */
|
||||
banner = xmalloc(len + 1);
|
||||
n = atomicio(read, fd, banner, len);
|
||||
close(fd);
|
||||
|
||||
if (n != len) {
|
||||
xfree(banner);
|
||||
return (NULL);
|
||||
}
|
||||
banner[n] = '\0';
|
||||
|
||||
return (banner);
|
||||
}
|
||||
|
||||
void
|
||||
userauth_send_banner(const char *msg)
|
||||
{
|
||||
if (datafellows & SSH_BUG_BANNER)
|
||||
return;
|
||||
|
||||
packet_start(SSH2_MSG_USERAUTH_BANNER);
|
||||
packet_put_cstring(msg);
|
||||
packet_put_cstring(""); /* language, unused */
|
||||
packet_send();
|
||||
debug("%s: sent", __func__);
|
||||
}
|
||||
|
||||
static void
|
||||
userauth_banner(void)
|
||||
{
|
||||
char *banner = NULL;
|
||||
|
||||
if (options.banner == NULL ||
|
||||
strcasecmp(options.banner, "none") == 0 ||
|
||||
(datafellows & SSH_BUG_BANNER) != 0)
|
||||
return;
|
||||
|
||||
if ((banner = PRIVSEP(auth2_read_banner())) == NULL)
|
||||
goto done;
|
||||
userauth_send_banner(banner);
|
||||
|
||||
done:
|
||||
if (banner)
|
||||
xfree(banner);
|
||||
}
|
||||
|
||||
static int
|
||||
userauth_none(Authctxt *authctxt)
|
||||
{
|
||||
none_enabled = 0;
|
||||
packet_check_eom();
|
||||
userauth_banner();
|
||||
#ifdef HAVE_CYGWIN
|
||||
if (check_nt_auth(1, authctxt->pw) == 0)
|
||||
return (0);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth2-pubkey.c,v 1.15 2006/08/03 03:34:41 deraadt Exp $ */
|
||||
/* $OpenBSD: auth2-pubkey.c,v 1.19 2008/07/03 21:46:58 otto Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -28,9 +28,11 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "ssh.h"
|
||||
@ -183,7 +185,6 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
|
||||
int found_key = 0;
|
||||
FILE *f;
|
||||
u_long linenum = 0;
|
||||
struct stat st;
|
||||
Key *found;
|
||||
char *fp;
|
||||
|
||||
@ -191,24 +192,9 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
|
||||
temporarily_use_uid(pw);
|
||||
|
||||
debug("trying public key file %s", file);
|
||||
f = auth_openkeyfile(file, pw, options.strict_modes);
|
||||
|
||||
/* Fail quietly if file does not exist */
|
||||
if (stat(file, &st) < 0) {
|
||||
/* Restore the privileged uid. */
|
||||
restore_uid();
|
||||
return 0;
|
||||
}
|
||||
/* Open the file containing the authorized keys. */
|
||||
f = fopen(file, "r");
|
||||
if (!f) {
|
||||
/* Restore the privileged uid. */
|
||||
restore_uid();
|
||||
return 0;
|
||||
}
|
||||
if (options.strict_modes &&
|
||||
secure_filename(f, file, pw, line, sizeof(line)) != 0) {
|
||||
fclose(f);
|
||||
logit("Authentication refused: %s", line);
|
||||
restore_uid();
|
||||
return 0;
|
||||
}
|
||||
|
83
auth2.c
83
auth2.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth2.c,v 1.116 2007/09/29 00:25:51 dtucker Exp $ */
|
||||
/* $OpenBSD: auth2.c,v 1.119 2008/07/04 23:30:16 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -26,12 +26,17 @@
|
||||
#include "includes.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <pwd.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "atomicio.h"
|
||||
#include "ssh2.h"
|
||||
#include "packet.h"
|
||||
#include "log.h"
|
||||
@ -88,10 +93,74 @@ static void input_userauth_request(int, u_int32_t, void *);
|
||||
static Authmethod *authmethod_lookup(const char *);
|
||||
static char *authmethods_get(void);
|
||||
|
||||
char *
|
||||
auth2_read_banner(void)
|
||||
{
|
||||
struct stat st;
|
||||
char *banner = NULL;
|
||||
size_t len, n;
|
||||
int fd;
|
||||
|
||||
if ((fd = open(options.banner, O_RDONLY)) == -1)
|
||||
return (NULL);
|
||||
if (fstat(fd, &st) == -1) {
|
||||
close(fd);
|
||||
return (NULL);
|
||||
}
|
||||
if (st.st_size > 1*1024*1024) {
|
||||
close(fd);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
len = (size_t)st.st_size; /* truncate */
|
||||
banner = xmalloc(len + 1);
|
||||
n = atomicio(read, fd, banner, len);
|
||||
close(fd);
|
||||
|
||||
if (n != len) {
|
||||
xfree(banner);
|
||||
return (NULL);
|
||||
}
|
||||
banner[n] = '\0';
|
||||
|
||||
return (banner);
|
||||
}
|
||||
|
||||
void
|
||||
userauth_send_banner(const char *msg)
|
||||
{
|
||||
if (datafellows & SSH_BUG_BANNER)
|
||||
return;
|
||||
|
||||
packet_start(SSH2_MSG_USERAUTH_BANNER);
|
||||
packet_put_cstring(msg);
|
||||
packet_put_cstring(""); /* language, unused */
|
||||
packet_send();
|
||||
debug("%s: sent", __func__);
|
||||
}
|
||||
|
||||
static void
|
||||
userauth_banner(void)
|
||||
{
|
||||
char *banner = NULL;
|
||||
|
||||
if (options.banner == NULL ||
|
||||
strcasecmp(options.banner, "none") == 0 ||
|
||||
(datafellows & SSH_BUG_BANNER) != 0)
|
||||
return;
|
||||
|
||||
if ((banner = PRIVSEP(auth2_read_banner())) == NULL)
|
||||
goto done;
|
||||
userauth_send_banner(banner);
|
||||
|
||||
done:
|
||||
if (banner)
|
||||
xfree(banner);
|
||||
}
|
||||
|
||||
/*
|
||||
* loop until authctxt->success == TRUE
|
||||
*/
|
||||
|
||||
void
|
||||
do_authentication2(Authctxt *authctxt)
|
||||
{
|
||||
@ -179,6 +248,7 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
|
||||
authctxt->style = style ? xstrdup(style) : NULL;
|
||||
if (use_privsep)
|
||||
mm_inform_authserv(service, style);
|
||||
userauth_banner();
|
||||
} else if (strcmp(user, authctxt->user) != 0 ||
|
||||
strcmp(service, authctxt->service) != 0) {
|
||||
packet_disconnect("Change of username or service not allowed: "
|
||||
@ -197,7 +267,7 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
|
||||
|
||||
/* try to authenticate user */
|
||||
m = authmethod_lookup(method);
|
||||
if (m != NULL) {
|
||||
if (m != NULL && authctxt->failures < options.max_authtries) {
|
||||
debug2("input_userauth_request: try method %s", method);
|
||||
authenticated = m->userauth(authctxt);
|
||||
}
|
||||
@ -264,7 +334,11 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
|
||||
/* now we can break out */
|
||||
authctxt->success = 1;
|
||||
} else {
|
||||
if (authctxt->failures++ > options.max_authtries) {
|
||||
|
||||
/* Allow initial try of "none" auth without failure penalty */
|
||||
if (authctxt->attempt > 1 || strcmp(method, "none") != 0)
|
||||
authctxt->failures++;
|
||||
if (authctxt->failures >= options.max_authtries) {
|
||||
#ifdef SSH_AUDIT_EVENTS
|
||||
PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
|
||||
#endif
|
||||
@ -320,3 +394,4 @@ authmethod_lookup(const char *name)
|
||||
name ? name : "NULL");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
20
bufaux.c
20
bufaux.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: bufaux.c,v 1.44 2006/08/03 03:34:41 deraadt Exp $ */
|
||||
/* $OpenBSD: bufaux.c,v 1.46 2008/06/10 23:21:34 dtucker Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -180,7 +180,7 @@ buffer_get_string_ret(Buffer *buffer, u_int *length_ptr)
|
||||
return (NULL);
|
||||
}
|
||||
/* Append a null character to make processing easier. */
|
||||
value[len] = 0;
|
||||
value[len] = '\0';
|
||||
/* Optionally return the length of the string. */
|
||||
if (length_ptr)
|
||||
*length_ptr = len;
|
||||
@ -197,6 +197,22 @@ buffer_get_string(Buffer *buffer, u_int *length_ptr)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void *
|
||||
buffer_get_string_ptr(Buffer *buffer, u_int *length_ptr)
|
||||
{
|
||||
void *ptr;
|
||||
u_int len;
|
||||
|
||||
len = buffer_get_int(buffer);
|
||||
if (len > 256 * 1024)
|
||||
fatal("buffer_get_string_ptr: bad string length %u", len);
|
||||
ptr = buffer_ptr(buffer);
|
||||
buffer_consume(buffer, len);
|
||||
if (length_ptr)
|
||||
*length_ptr = len;
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Stores and arbitrary binary string in the buffer.
|
||||
*/
|
||||
|
3
buffer.h
3
buffer.h
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: buffer.h,v 1.16 2006/08/03 03:34:41 deraadt Exp $ */
|
||||
/* $OpenBSD: buffer.h,v 1.17 2008/05/08 06:59:01 markus Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -66,6 +66,7 @@ int buffer_get_char(Buffer *);
|
||||
void buffer_put_char(Buffer *, int);
|
||||
|
||||
void *buffer_get_string(Buffer *, u_int *);
|
||||
void *buffer_get_string_ptr(Buffer *, u_int *);
|
||||
void buffer_put_string(Buffer *, const void *, u_int);
|
||||
void buffer_put_cstring(Buffer *, const char *);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: canohost.c,v 1.62 2007/12/27 14:22:08 dtucker Exp $ */
|
||||
/* $OpenBSD: canohost.c,v 1.63 2008/06/12 00:03:49 dtucker Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -89,7 +89,7 @@ get_remote_hostname(int sock, int use_dns)
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
if (getaddrinfo(name, "0", &hints, &ai) == 0) {
|
||||
if (getaddrinfo(name, NULL, &hints, &ai) == 0) {
|
||||
logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
|
||||
name, ntop);
|
||||
freeaddrinfo(ai);
|
||||
|
358
channels.c
358
channels.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: channels.c,v 1.273 2008/04/02 21:36:51 markus Exp $ */
|
||||
/* $OpenBSD: channels.c,v 1.286 2008/07/16 11:52:19 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -61,6 +61,7 @@
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "openbsd-compat/sys-queue.h"
|
||||
#include "xmalloc.h"
|
||||
#include "ssh.h"
|
||||
#include "ssh1.h"
|
||||
@ -164,6 +165,10 @@ static int IPv4or6 = AF_UNSPEC;
|
||||
/* helper */
|
||||
static void port_open_helper(Channel *c, char *rtype);
|
||||
|
||||
/* non-blocking connect helpers */
|
||||
static int connect_next(struct channel_connect *);
|
||||
static void channel_connect_ctx_free(struct channel_connect *);
|
||||
|
||||
/* -- channel core */
|
||||
|
||||
Channel *
|
||||
@ -216,7 +221,7 @@ channel_lookup(int id)
|
||||
*/
|
||||
static void
|
||||
channel_register_fds(Channel *c, int rfd, int wfd, int efd,
|
||||
int extusage, int nonblock)
|
||||
int extusage, int nonblock, int is_tty)
|
||||
{
|
||||
/* Update the maximum file descriptor value. */
|
||||
channel_max_fd = MAX(channel_max_fd, rfd);
|
||||
@ -232,18 +237,9 @@ channel_register_fds(Channel *c, int rfd, int wfd, int efd,
|
||||
c->efd = efd;
|
||||
c->extended_usage = extusage;
|
||||
|
||||
/* XXX ugly hack: nonblock is only set by the server */
|
||||
if (nonblock && isatty(c->rfd)) {
|
||||
if ((c->isatty = is_tty) != 0)
|
||||
debug2("channel %d: rfd %d isatty", c->self, c->rfd);
|
||||
c->isatty = 1;
|
||||
if (!isatty(c->wfd)) {
|
||||
error("channel %d: wfd %d is not a tty?",
|
||||
c->self, c->wfd);
|
||||
}
|
||||
} else {
|
||||
c->isatty = 0;
|
||||
}
|
||||
c->wfd_isatty = isatty(c->wfd);
|
||||
c->wfd_isatty = is_tty || isatty(c->wfd);
|
||||
|
||||
/* enable nonblocking mode */
|
||||
if (nonblock) {
|
||||
@ -303,7 +299,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd,
|
||||
c->ostate = CHAN_OUTPUT_OPEN;
|
||||
c->istate = CHAN_INPUT_OPEN;
|
||||
c->flags = 0;
|
||||
channel_register_fds(c, rfd, wfd, efd, extusage, nonblock);
|
||||
channel_register_fds(c, rfd, wfd, efd, extusage, nonblock, 0);
|
||||
c->self = found;
|
||||
c->type = type;
|
||||
c->ctype = ctype;
|
||||
@ -319,10 +315,13 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd,
|
||||
c->single_connection = 0;
|
||||
c->detach_user = NULL;
|
||||
c->detach_close = 0;
|
||||
c->confirm = NULL;
|
||||
c->confirm_ctx = NULL;
|
||||
c->open_confirm = NULL;
|
||||
c->open_confirm_ctx = NULL;
|
||||
c->input_filter = NULL;
|
||||
c->output_filter = NULL;
|
||||
c->filter_ctx = NULL;
|
||||
c->filter_cleanup = NULL;
|
||||
TAILQ_INIT(&c->status_confirms);
|
||||
debug("channel %d: new [%s]", found, remote_name);
|
||||
return c;
|
||||
}
|
||||
@ -379,6 +378,7 @@ channel_free(Channel *c)
|
||||
{
|
||||
char *s;
|
||||
u_int i, n;
|
||||
struct channel_confirm *cc;
|
||||
|
||||
for (n = 0, i = 0; i < channels_alloc; i++)
|
||||
if (channels[i])
|
||||
@ -402,6 +402,15 @@ channel_free(Channel *c)
|
||||
xfree(c->remote_name);
|
||||
c->remote_name = NULL;
|
||||
}
|
||||
while ((cc = TAILQ_FIRST(&c->status_confirms)) != NULL) {
|
||||
if (cc->abandon_cb != NULL)
|
||||
cc->abandon_cb(c, cc->ctx);
|
||||
TAILQ_REMOVE(&c->status_confirms, cc, entry);
|
||||
bzero(cc, sizeof(*cc));
|
||||
xfree(cc);
|
||||
}
|
||||
if (c->filter_cleanup != NULL && c->filter_ctx != NULL)
|
||||
c->filter_cleanup(c->self, c->filter_ctx);
|
||||
channels[c->self] = NULL;
|
||||
xfree(c);
|
||||
}
|
||||
@ -660,16 +669,33 @@ channel_request_start(int id, char *service, int wantconfirm)
|
||||
}
|
||||
|
||||
void
|
||||
channel_register_confirm(int id, channel_callback_fn *fn, void *ctx)
|
||||
channel_register_status_confirm(int id, channel_confirm_cb *cb,
|
||||
channel_confirm_abandon_cb *abandon_cb, void *ctx)
|
||||
{
|
||||
struct channel_confirm *cc;
|
||||
Channel *c;
|
||||
|
||||
if ((c = channel_lookup(id)) == NULL)
|
||||
fatal("channel_register_expect: %d: bad id", id);
|
||||
|
||||
cc = xmalloc(sizeof(*cc));
|
||||
cc->cb = cb;
|
||||
cc->abandon_cb = abandon_cb;
|
||||
cc->ctx = ctx;
|
||||
TAILQ_INSERT_TAIL(&c->status_confirms, cc, entry);
|
||||
}
|
||||
|
||||
void
|
||||
channel_register_open_confirm(int id, channel_callback_fn *fn, void *ctx)
|
||||
{
|
||||
Channel *c = channel_lookup(id);
|
||||
|
||||
if (c == NULL) {
|
||||
logit("channel_register_comfirm: %d: bad id", id);
|
||||
logit("channel_register_open_comfirm: %d: bad id", id);
|
||||
return;
|
||||
}
|
||||
c->confirm = fn;
|
||||
c->confirm_ctx = ctx;
|
||||
c->open_confirm = fn;
|
||||
c->open_confirm_ctx = ctx;
|
||||
}
|
||||
|
||||
void
|
||||
@ -700,7 +726,7 @@ channel_cancel_cleanup(int id)
|
||||
|
||||
void
|
||||
channel_register_filter(int id, channel_infilter_fn *ifn,
|
||||
channel_outfilter_fn *ofn)
|
||||
channel_outfilter_fn *ofn, channel_filter_cleanup_fn *cfn, void *ctx)
|
||||
{
|
||||
Channel *c = channel_lookup(id);
|
||||
|
||||
@ -710,17 +736,19 @@ channel_register_filter(int id, channel_infilter_fn *ifn,
|
||||
}
|
||||
c->input_filter = ifn;
|
||||
c->output_filter = ofn;
|
||||
c->filter_ctx = ctx;
|
||||
c->filter_cleanup = cfn;
|
||||
}
|
||||
|
||||
void
|
||||
channel_set_fds(int id, int rfd, int wfd, int efd,
|
||||
int extusage, int nonblock, u_int window_max)
|
||||
int extusage, int nonblock, int is_tty, u_int window_max)
|
||||
{
|
||||
Channel *c = channel_lookup(id);
|
||||
|
||||
if (c == NULL || c->type != SSH_CHANNEL_LARVAL)
|
||||
fatal("channel_activate for non-larval channel %d.", id);
|
||||
channel_register_fds(c, rfd, wfd, efd, extusage, nonblock);
|
||||
channel_register_fds(c, rfd, wfd, efd, extusage, nonblock, is_tty);
|
||||
c->type = SSH_CHANNEL_OPEN;
|
||||
c->local_window = c->local_window_max = window_max;
|
||||
packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
|
||||
@ -788,7 +816,8 @@ channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
}
|
||||
}
|
||||
/** XXX check close conditions, too */
|
||||
if (compat20 && c->efd != -1) {
|
||||
if (compat20 && c->efd != -1 &&
|
||||
!(c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED)) {
|
||||
if (c->extended_usage == CHAN_EXTENDED_WRITE &&
|
||||
buffer_len(&c->extended) > 0)
|
||||
FD_SET(c->efd, writeset);
|
||||
@ -1181,7 +1210,7 @@ static void
|
||||
channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
{
|
||||
Channel *nc;
|
||||
struct sockaddr addr;
|
||||
struct sockaddr_storage addr;
|
||||
int newsock;
|
||||
socklen_t addrlen;
|
||||
char buf[16384], *remote_ipaddr;
|
||||
@ -1190,7 +1219,7 @@ channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
if (FD_ISSET(c->sock, readset)) {
|
||||
debug("X11 connection requested.");
|
||||
addrlen = sizeof(addr);
|
||||
newsock = accept(c->sock, &addr, &addrlen);
|
||||
newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
|
||||
if (c->single_connection) {
|
||||
debug2("single_connection: closing X11 listener.");
|
||||
channel_close_fd(&c->sock);
|
||||
@ -1307,7 +1336,7 @@ static void
|
||||
channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
{
|
||||
Channel *nc;
|
||||
struct sockaddr addr;
|
||||
struct sockaddr_storage addr;
|
||||
int newsock, nextstate;
|
||||
socklen_t addrlen;
|
||||
char *rtype;
|
||||
@ -1331,7 +1360,7 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
}
|
||||
|
||||
addrlen = sizeof(addr);
|
||||
newsock = accept(c->sock, &addr, &addrlen);
|
||||
newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
|
||||
if (newsock < 0) {
|
||||
error("accept: %.100s", strerror(errno));
|
||||
return;
|
||||
@ -1366,12 +1395,12 @@ channel_post_auth_listener(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
{
|
||||
Channel *nc;
|
||||
int newsock;
|
||||
struct sockaddr addr;
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addrlen;
|
||||
|
||||
if (FD_ISSET(c->sock, readset)) {
|
||||
addrlen = sizeof(addr);
|
||||
newsock = accept(c->sock, &addr, &addrlen);
|
||||
newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
|
||||
if (newsock < 0) {
|
||||
error("accept from auth socket: %.100s", strerror(errno));
|
||||
return;
|
||||
@ -1398,7 +1427,7 @@ channel_post_auth_listener(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
static void
|
||||
channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
{
|
||||
int err = 0;
|
||||
int err = 0, sock;
|
||||
socklen_t sz = sizeof(err);
|
||||
|
||||
if (FD_ISSET(c->sock, writeset)) {
|
||||
@ -1407,7 +1436,9 @@ channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
error("getsockopt SO_ERROR failed");
|
||||
}
|
||||
if (err == 0) {
|
||||
debug("channel %d: connected", c->self);
|
||||
debug("channel %d: connected to %s port %d",
|
||||
c->self, c->connect_ctx.host, c->connect_ctx.port);
|
||||
channel_connect_ctx_free(&c->connect_ctx);
|
||||
c->type = SSH_CHANNEL_OPEN;
|
||||
if (compat20) {
|
||||
packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
|
||||
@ -1421,8 +1452,19 @@ channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
packet_put_int(c->self);
|
||||
}
|
||||
} else {
|
||||
debug("channel %d: not connected: %s",
|
||||
debug("channel %d: connection failed: %s",
|
||||
c->self, strerror(err));
|
||||
/* Try next address, if any */
|
||||
if ((sock = connect_next(&c->connect_ctx)) > 0) {
|
||||
close(c->sock);
|
||||
c->sock = c->rfd = c->wfd = sock;
|
||||
channel_max_fd = channel_find_maxfd();
|
||||
return;
|
||||
}
|
||||
/* Exhausted all addresses */
|
||||
error("connect_to %.100s port %d: failed.",
|
||||
c->connect_ctx.host, c->connect_ctx.port);
|
||||
channel_connect_ctx_free(&c->connect_ctx);
|
||||
if (compat20) {
|
||||
packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
|
||||
packet_put_int(c->remote_id);
|
||||
@ -1452,7 +1494,8 @@ channel_handle_rfd(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
if (c->rfd != -1 && (force || FD_ISSET(c->rfd, readset))) {
|
||||
errno = 0;
|
||||
len = read(c->rfd, buf, sizeof(buf));
|
||||
if (len < 0 && (errno == EINTR || (errno == EAGAIN && !force)))
|
||||
if (len < 0 && (errno == EINTR ||
|
||||
((errno == EAGAIN || errno == EWOULDBLOCK) && !force)))
|
||||
return 1;
|
||||
#ifndef PTY_ZEROREAD
|
||||
if (len <= 0) {
|
||||
@ -1523,7 +1566,8 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
c->local_consumed += dlen + 4;
|
||||
len = write(c->wfd, buf, dlen);
|
||||
xfree(data);
|
||||
if (len < 0 && (errno == EINTR || errno == EAGAIN))
|
||||
if (len < 0 && (errno == EINTR || errno == EAGAIN ||
|
||||
errno == EWOULDBLOCK))
|
||||
return 1;
|
||||
if (len <= 0) {
|
||||
if (c->type != SSH_CHANNEL_OPEN)
|
||||
@ -1541,7 +1585,8 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
#endif
|
||||
|
||||
len = write(c->wfd, buf, dlen);
|
||||
if (len < 0 && (errno == EINTR || errno == EAGAIN))
|
||||
if (len < 0 &&
|
||||
(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
|
||||
return 1;
|
||||
if (len <= 0) {
|
||||
if (c->type != SSH_CHANNEL_OPEN) {
|
||||
@ -1593,7 +1638,8 @@ channel_handle_efd(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
buffer_len(&c->extended));
|
||||
debug2("channel %d: written %d to efd %d",
|
||||
c->self, len, c->efd);
|
||||
if (len < 0 && (errno == EINTR || errno == EAGAIN))
|
||||
if (len < 0 && (errno == EINTR || errno == EAGAIN ||
|
||||
errno == EWOULDBLOCK))
|
||||
return 1;
|
||||
if (len <= 0) {
|
||||
debug2("channel %d: closing write-efd %d",
|
||||
@ -1608,8 +1654,8 @@ channel_handle_efd(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
len = read(c->efd, buf, sizeof(buf));
|
||||
debug2("channel %d: read %d from efd %d",
|
||||
c->self, len, c->efd);
|
||||
if (len < 0 && (errno == EINTR ||
|
||||
(errno == EAGAIN && !c->detach_close)))
|
||||
if (len < 0 && (errno == EINTR || ((errno == EAGAIN ||
|
||||
errno == EWOULDBLOCK) && !c->detach_close)))
|
||||
return 1;
|
||||
if (len <= 0) {
|
||||
debug2("channel %d: closing read-efd %d",
|
||||
@ -1633,7 +1679,8 @@ channel_handle_ctl(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
/* Monitor control fd to detect if the slave client exits */
|
||||
if (c->ctl_fd != -1 && FD_ISSET(c->ctl_fd, readset)) {
|
||||
len = read(c->ctl_fd, buf, sizeof(buf));
|
||||
if (len < 0 && (errno == EINTR || errno == EAGAIN))
|
||||
if (len < 0 &&
|
||||
(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
|
||||
return 1;
|
||||
if (len <= 0) {
|
||||
debug2("channel %d: ctl read<=0", c->self);
|
||||
@ -2012,7 +2059,7 @@ channel_input_data(int type, u_int32_t seq, void *ctxt)
|
||||
return;
|
||||
|
||||
/* Get the data. */
|
||||
data = packet_get_string(&data_len);
|
||||
data = packet_get_string_ptr(&data_len);
|
||||
|
||||
/*
|
||||
* Ignore data for protocol > 1.3 if output end is no longer open.
|
||||
@ -2026,7 +2073,6 @@ channel_input_data(int type, u_int32_t seq, void *ctxt)
|
||||
c->local_window -= data_len;
|
||||
c->local_consumed += data_len;
|
||||
}
|
||||
xfree(data);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2038,17 +2084,15 @@ channel_input_data(int type, u_int32_t seq, void *ctxt)
|
||||
if (data_len > c->local_window) {
|
||||
logit("channel %d: rcvd too much data %d, win %d",
|
||||
c->self, data_len, c->local_window);
|
||||
xfree(data);
|
||||
return;
|
||||
}
|
||||
c->local_window -= data_len;
|
||||
}
|
||||
packet_check_eom();
|
||||
if (c->datagram)
|
||||
buffer_put_string(&c->output, data, data_len);
|
||||
else
|
||||
buffer_append(&c->output, data, data_len);
|
||||
xfree(data);
|
||||
packet_check_eom();
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
@ -2212,9 +2256,9 @@ channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt)
|
||||
if (compat20) {
|
||||
c->remote_window = packet_get_int();
|
||||
c->remote_maxpacket = packet_get_int();
|
||||
if (c->confirm) {
|
||||
if (c->open_confirm) {
|
||||
debug2("callback start");
|
||||
c->confirm(c->self, c->confirm_ctx);
|
||||
c->open_confirm(c->self, c->open_confirm_ctx);
|
||||
debug2("callback done");
|
||||
}
|
||||
debug2("channel %d: open confirm rwindow %u rmax %u", c->self,
|
||||
@ -2303,7 +2347,7 @@ channel_input_port_open(int type, u_int32_t seq, void *ctxt)
|
||||
Channel *c = NULL;
|
||||
u_short host_port;
|
||||
char *host, *originator_string;
|
||||
int remote_id, sock = -1;
|
||||
int remote_id;
|
||||
|
||||
remote_id = packet_get_int();
|
||||
host = packet_get_string(NULL);
|
||||
@ -2315,22 +2359,46 @@ channel_input_port_open(int type, u_int32_t seq, void *ctxt)
|
||||
originator_string = xstrdup("unknown (remote did not supply name)");
|
||||
}
|
||||
packet_check_eom();
|
||||
sock = channel_connect_to(host, host_port);
|
||||
if (sock != -1) {
|
||||
c = channel_new("connected socket",
|
||||
SSH_CHANNEL_CONNECTING, sock, sock, -1, 0, 0, 0,
|
||||
originator_string, 1);
|
||||
c->remote_id = remote_id;
|
||||
}
|
||||
c = channel_connect_to(host, host_port,
|
||||
"connected socket", originator_string);
|
||||
xfree(originator_string);
|
||||
xfree(host);
|
||||
if (c == NULL) {
|
||||
packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
|
||||
packet_put_int(remote_id);
|
||||
packet_send();
|
||||
}
|
||||
xfree(host);
|
||||
} else
|
||||
c->remote_id = remote_id;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
channel_input_status_confirm(int type, u_int32_t seq, void *ctxt)
|
||||
{
|
||||
Channel *c;
|
||||
struct channel_confirm *cc;
|
||||
int remote_id;
|
||||
|
||||
/* Reset keepalive timeout */
|
||||
keep_alive_timeouts = 0;
|
||||
|
||||
remote_id = packet_get_int();
|
||||
packet_check_eom();
|
||||
|
||||
debug2("channel_input_confirm: type %d id %d", type, remote_id);
|
||||
|
||||
if ((c = channel_lookup(remote_id)) == NULL) {
|
||||
logit("channel_input_success_failure: %d: unknown", remote_id);
|
||||
return;
|
||||
}
|
||||
;
|
||||
if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL)
|
||||
return;
|
||||
cc->cb(type, c, cc->ctx);
|
||||
TAILQ_REMOVE(&c->status_confirms, cc, entry);
|
||||
bzero(cc, sizeof(*cc));
|
||||
xfree(cc);
|
||||
}
|
||||
|
||||
/* -- tcp forwarding */
|
||||
|
||||
@ -2718,35 +2786,37 @@ channel_clear_adm_permitted_opens(void)
|
||||
num_adm_permitted_opens = 0;
|
||||
}
|
||||
|
||||
/* return socket to remote host, port */
|
||||
static int
|
||||
connect_to(const char *host, u_short port)
|
||||
void
|
||||
channel_print_adm_permitted_opens(void)
|
||||
{
|
||||
struct addrinfo hints, *ai, *aitop;
|
||||
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
|
||||
int gaierr;
|
||||
int sock = -1;
|
||||
int i;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = IPv4or6;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
snprintf(strport, sizeof strport, "%d", port);
|
||||
if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) {
|
||||
error("connect_to %.100s: unknown host (%s)", host,
|
||||
ssh_gai_strerror(gaierr));
|
||||
return -1;
|
||||
}
|
||||
for (ai = aitop; ai; ai = ai->ai_next) {
|
||||
if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
|
||||
for (i = 0; i < num_adm_permitted_opens; i++)
|
||||
if (permitted_adm_opens[i].host_to_connect != NULL)
|
||||
printf(" %s:%d", permitted_adm_opens[i].host_to_connect,
|
||||
permitted_adm_opens[i].port_to_connect);
|
||||
}
|
||||
|
||||
/* Try to start non-blocking connect to next host in cctx list */
|
||||
static int
|
||||
connect_next(struct channel_connect *cctx)
|
||||
{
|
||||
int sock, saved_errno;
|
||||
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
|
||||
|
||||
for (; cctx->ai; cctx->ai = cctx->ai->ai_next) {
|
||||
if (cctx->ai->ai_family != AF_INET &&
|
||||
cctx->ai->ai_family != AF_INET6)
|
||||
continue;
|
||||
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
|
||||
strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
|
||||
error("connect_to: getnameinfo failed");
|
||||
if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen,
|
||||
ntop, sizeof(ntop), strport, sizeof(strport),
|
||||
NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
|
||||
error("connect_next: getnameinfo failed");
|
||||
continue;
|
||||
}
|
||||
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||
if (sock < 0) {
|
||||
if (ai->ai_next == NULL)
|
||||
if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype,
|
||||
cctx->ai->ai_protocol)) == -1) {
|
||||
if (cctx->ai->ai_next == NULL)
|
||||
error("socket: %.100s", strerror(errno));
|
||||
else
|
||||
verbose("socket: %.100s", strerror(errno));
|
||||
@ -2754,45 +2824,95 @@ connect_to(const char *host, u_short port)
|
||||
}
|
||||
if (set_nonblock(sock) == -1)
|
||||
fatal("%s: set_nonblock(%d)", __func__, sock);
|
||||
if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0 &&
|
||||
errno != EINPROGRESS) {
|
||||
error("connect_to %.100s port %s: %.100s", ntop, strport,
|
||||
if (connect(sock, cctx->ai->ai_addr,
|
||||
cctx->ai->ai_addrlen) == -1 && errno != EINPROGRESS) {
|
||||
debug("connect_next: host %.100s ([%.100s]:%s): "
|
||||
"%.100s", cctx->host, ntop, strport,
|
||||
strerror(errno));
|
||||
saved_errno = errno;
|
||||
close(sock);
|
||||
errno = saved_errno;
|
||||
continue; /* fail -- try next */
|
||||
}
|
||||
break; /* success */
|
||||
|
||||
debug("connect_next: host %.100s ([%.100s]:%s) "
|
||||
"in progress, fd=%d", cctx->host, ntop, strport, sock);
|
||||
cctx->ai = cctx->ai->ai_next;
|
||||
set_nodelay(sock);
|
||||
return sock;
|
||||
}
|
||||
freeaddrinfo(aitop);
|
||||
if (!ai) {
|
||||
error("connect_to %.100s port %d: failed.", host, port);
|
||||
return -1;
|
||||
}
|
||||
/* success */
|
||||
set_nodelay(sock);
|
||||
return sock;
|
||||
}
|
||||
|
||||
int
|
||||
channel_connect_by_listen_address(u_short listen_port)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_permitted_opens; i++)
|
||||
if (permitted_opens[i].host_to_connect != NULL &&
|
||||
permitted_opens[i].listen_port == listen_port)
|
||||
return connect_to(
|
||||
permitted_opens[i].host_to_connect,
|
||||
permitted_opens[i].port_to_connect);
|
||||
error("WARNING: Server requests forwarding for unknown listen_port %d",
|
||||
listen_port);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
channel_connect_ctx_free(struct channel_connect *cctx)
|
||||
{
|
||||
xfree(cctx->host);
|
||||
if (cctx->aitop)
|
||||
freeaddrinfo(cctx->aitop);
|
||||
bzero(cctx, sizeof(*cctx));
|
||||
cctx->host = NULL;
|
||||
cctx->ai = cctx->aitop = NULL;
|
||||
}
|
||||
|
||||
/* Return CONNECTING channel to remote host, port */
|
||||
static Channel *
|
||||
connect_to(const char *host, u_short port, char *ctype, char *rname)
|
||||
{
|
||||
struct addrinfo hints;
|
||||
int gaierr;
|
||||
int sock = -1;
|
||||
char strport[NI_MAXSERV];
|
||||
struct channel_connect cctx;
|
||||
Channel *c;
|
||||
|
||||
memset(&cctx, 0, sizeof(cctx));
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = IPv4or6;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
snprintf(strport, sizeof strport, "%d", port);
|
||||
if ((gaierr = getaddrinfo(host, strport, &hints, &cctx.aitop)) != 0) {
|
||||
error("connect_to %.100s: unknown host (%s)", host,
|
||||
ssh_gai_strerror(gaierr));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cctx.host = xstrdup(host);
|
||||
cctx.port = port;
|
||||
cctx.ai = cctx.aitop;
|
||||
|
||||
if ((sock = connect_next(&cctx)) == -1) {
|
||||
error("connect to %.100s port %d failed: %s",
|
||||
host, port, strerror(errno));
|
||||
channel_connect_ctx_free(&cctx);
|
||||
return NULL;
|
||||
}
|
||||
c = channel_new(ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1,
|
||||
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1);
|
||||
c->connect_ctx = cctx;
|
||||
return c;
|
||||
}
|
||||
|
||||
Channel *
|
||||
channel_connect_by_listen_address(u_short listen_port, char *ctype, char *rname)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_permitted_opens; i++) {
|
||||
if (permitted_opens[i].host_to_connect != NULL &&
|
||||
permitted_opens[i].listen_port == listen_port) {
|
||||
return connect_to(
|
||||
permitted_opens[i].host_to_connect,
|
||||
permitted_opens[i].port_to_connect, ctype, rname);
|
||||
}
|
||||
}
|
||||
error("WARNING: Server requests forwarding for unknown listen_port %d",
|
||||
listen_port);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check if connecting to that port is permitted and connect. */
|
||||
int
|
||||
channel_connect_to(const char *host, u_short port)
|
||||
Channel *
|
||||
channel_connect_to(const char *host, u_short port, char *ctype, char *rname)
|
||||
{
|
||||
int i, permit, permit_adm = 1;
|
||||
|
||||
@ -2818,9 +2938,9 @@ channel_connect_to(const char *host, u_short port)
|
||||
if (!permit || !permit_adm) {
|
||||
logit("Received request to connect to host %.100s port %d, "
|
||||
"but the request was denied.", host, port);
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
return connect_to(host, port);
|
||||
return connect_to(host, port, ctype, rname);
|
||||
}
|
||||
|
||||
void
|
||||
@ -2901,7 +3021,8 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
|
||||
error("setsockopt IPV6_V6ONLY: %.100s", strerror(errno));
|
||||
}
|
||||
#endif
|
||||
channel_set_reuseaddr(sock);
|
||||
if (x11_use_localhost)
|
||||
channel_set_reuseaddr(sock);
|
||||
if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
|
||||
debug2("bind port %d: %.100s", port, strerror(errno));
|
||||
close(sock);
|
||||
@ -2913,17 +3034,8 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
|
||||
break;
|
||||
}
|
||||
socks[num_socks++] = sock;
|
||||
#ifndef DONT_TRY_OTHER_AF
|
||||
if (num_socks == NUM_SOCKS)
|
||||
break;
|
||||
#else
|
||||
if (x11_use_localhost) {
|
||||
if (num_socks == NUM_SOCKS)
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
freeaddrinfo(aitop);
|
||||
if (num_socks > 0)
|
||||
|
52
channels.h
52
channels.h
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: channels.h,v 1.89 2007/06/11 09:14:00 markus Exp $ */
|
||||
/* $OpenBSD: channels.h,v 1.96 2008/06/15 20:06:26 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -62,8 +62,27 @@ typedef struct Channel Channel;
|
||||
|
||||
typedef void channel_callback_fn(int, void *);
|
||||
typedef int channel_infilter_fn(struct Channel *, char *, int);
|
||||
typedef void channel_filter_cleanup_fn(int, void *);
|
||||
typedef u_char *channel_outfilter_fn(struct Channel *, u_char **, u_int *);
|
||||
|
||||
/* Channel success/failure callbacks */
|
||||
typedef void channel_confirm_cb(int, struct Channel *, void *);
|
||||
typedef void channel_confirm_abandon_cb(struct Channel *, void *);
|
||||
struct channel_confirm {
|
||||
TAILQ_ENTRY(channel_confirm) entry;
|
||||
channel_confirm_cb *cb;
|
||||
channel_confirm_abandon_cb *abandon_cb;
|
||||
void *ctx;
|
||||
};
|
||||
TAILQ_HEAD(channel_confirms, channel_confirm);
|
||||
|
||||
/* Context for non-blocking connects */
|
||||
struct channel_connect {
|
||||
char *host;
|
||||
int port;
|
||||
struct addrinfo *ai, *aitop;
|
||||
};
|
||||
|
||||
struct Channel {
|
||||
int type; /* channel type/state */
|
||||
int self; /* my own channel identifier */
|
||||
@ -104,16 +123,23 @@ struct Channel {
|
||||
char *ctype; /* type */
|
||||
|
||||
/* callback */
|
||||
channel_callback_fn *confirm;
|
||||
void *confirm_ctx;
|
||||
channel_callback_fn *open_confirm;
|
||||
void *open_confirm_ctx;
|
||||
channel_callback_fn *detach_user;
|
||||
int detach_close;
|
||||
struct channel_confirms status_confirms;
|
||||
|
||||
/* filter */
|
||||
channel_infilter_fn *input_filter;
|
||||
channel_outfilter_fn *output_filter;
|
||||
void *filter_ctx;
|
||||
channel_filter_cleanup_fn *filter_cleanup;
|
||||
|
||||
int datagram; /* keep boundaries */
|
||||
/* keep boundaries */
|
||||
int datagram;
|
||||
|
||||
/* non-blocking connect */
|
||||
struct channel_connect connect_ctx;
|
||||
};
|
||||
|
||||
#define CHAN_EXTENDED_IGNORE 0
|
||||
@ -162,7 +188,7 @@ struct Channel {
|
||||
Channel *channel_by_id(int);
|
||||
Channel *channel_lookup(int);
|
||||
Channel *channel_new(char *, int, int, int, int, u_int, u_int, int, char *, int);
|
||||
void channel_set_fds(int, int, int, int, int, int, u_int);
|
||||
void channel_set_fds(int, int, int, int, int, int, int, u_int);
|
||||
void channel_free(Channel *);
|
||||
void channel_free_all(void);
|
||||
void channel_stop_listening(void);
|
||||
@ -170,8 +196,11 @@ void channel_stop_listening(void);
|
||||
void channel_send_open(int);
|
||||
void channel_request_start(int, char *, int);
|
||||
void channel_register_cleanup(int, channel_callback_fn *, int);
|
||||
void channel_register_confirm(int, channel_callback_fn *, void *);
|
||||
void channel_register_filter(int, channel_infilter_fn *, channel_outfilter_fn *);
|
||||
void channel_register_open_confirm(int, channel_callback_fn *, void *);
|
||||
void channel_register_filter(int, channel_infilter_fn *,
|
||||
channel_outfilter_fn *, channel_filter_cleanup_fn *, void *);
|
||||
void channel_register_status_confirm(int, channel_confirm_cb *,
|
||||
channel_confirm_abandon_cb *, void *);
|
||||
void channel_cancel_cleanup(int);
|
||||
int channel_close_fd(int *);
|
||||
void channel_send_window_changes(void);
|
||||
@ -188,6 +217,7 @@ void channel_input_open_confirmation(int, u_int32_t, void *);
|
||||
void channel_input_open_failure(int, u_int32_t, void *);
|
||||
void channel_input_port_open(int, u_int32_t, void *);
|
||||
void channel_input_window_adjust(int, u_int32_t, void *);
|
||||
void channel_input_status_confirm(int, u_int32_t, void *);
|
||||
|
||||
/* file descriptor handling (read/write) */
|
||||
|
||||
@ -208,9 +238,10 @@ void channel_add_permitted_opens(char *, int);
|
||||
int channel_add_adm_permitted_opens(char *, int);
|
||||
void channel_clear_permitted_opens(void);
|
||||
void channel_clear_adm_permitted_opens(void);
|
||||
void channel_print_adm_permitted_opens(void);
|
||||
int channel_input_port_forward_request(int, int);
|
||||
int channel_connect_to(const char *, u_short);
|
||||
int channel_connect_by_listen_address(u_short);
|
||||
Channel *channel_connect_to(const char *, u_short, char *, char *);
|
||||
Channel *channel_connect_by_listen_address(u_short, char *, char *);
|
||||
int channel_request_remote_forwarding(const char *, u_short,
|
||||
const char *, u_short);
|
||||
int channel_setup_local_fwd_listener(const char *, u_short,
|
||||
@ -225,7 +256,7 @@ int x11_connect_display(void);
|
||||
int x11_create_display_inet(int, int, int, u_int *, int **);
|
||||
void x11_input_open(int, u_int32_t, void *);
|
||||
void x11_request_forwarding_with_spoofing(int, const char *, const char *,
|
||||
const char *);
|
||||
const char *);
|
||||
void deny_input_open(int, u_int32_t, void *);
|
||||
|
||||
/* agent forwarding */
|
||||
@ -240,6 +271,7 @@ void chan_mark_dead(Channel *);
|
||||
/* channel events */
|
||||
|
||||
void chan_rcvd_oclose(Channel *);
|
||||
void chan_rcvd_eow(Channel *); /* SSH2-only */
|
||||
void chan_read_failed(Channel *);
|
||||
void chan_ibuf_empty(Channel *);
|
||||
|
||||
|
753
clientloop.c
753
clientloop.c
File diff suppressed because it is too large
Load Diff
19
clientloop.h
19
clientloop.h
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: clientloop.h,v 1.17 2007/08/07 07:32:53 djm Exp $ */
|
||||
/* $OpenBSD: clientloop.h,v 1.22 2008/06/12 15:19:17 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -43,11 +43,20 @@ void client_x11_get_proto(const char *, const char *, u_int,
|
||||
char **, char **);
|
||||
void client_global_request_reply_fwd(int, u_int32_t, void *);
|
||||
void client_session2_setup(int, int, int, const char *, struct termios *,
|
||||
int, Buffer *, char **, dispatch_fn *);
|
||||
int, Buffer *, char **);
|
||||
int client_request_tun_fwd(int, int, int);
|
||||
|
||||
/* Escape filter for protocol 2 sessions */
|
||||
void *client_new_escape_filter_ctx(int);
|
||||
void client_filter_cleanup(int, void *);
|
||||
int client_simple_escape_filter(Channel *, char *, int);
|
||||
|
||||
/* Global request confirmation callbacks */
|
||||
typedef void global_confirm_cb(int, u_int32_t seq, void *);
|
||||
void client_register_global_confirm(global_confirm_cb *, void *);
|
||||
|
||||
/* Multiplexing protocol version */
|
||||
#define SSHMUX_VER 1
|
||||
#define SSHMUX_VER 2
|
||||
|
||||
/* Multiplexing control protocol flags */
|
||||
#define SSHMUX_COMMAND_OPEN 1 /* Open new connection */
|
||||
@ -58,3 +67,7 @@ int client_request_tun_fwd(int, int, int);
|
||||
#define SSHMUX_FLAG_SUBSYS (1<<1) /* Subsystem request on open */
|
||||
#define SSHMUX_FLAG_X11_FWD (1<<2) /* Request X11 forwarding */
|
||||
#define SSHMUX_FLAG_AGENT_FWD (1<<3) /* Request agent forwarding */
|
||||
|
||||
void muxserver_listen(void);
|
||||
int muxserver_accept_control(void);
|
||||
void muxclient(const char *);
|
||||
|
39
config.h.in
39
config.h.in
@ -38,6 +38,9 @@
|
||||
*/
|
||||
#undef BROKEN_ONE_BYTE_DIRENT_D_NAME
|
||||
|
||||
/* Can't do comparisons on readv */
|
||||
#undef BROKEN_READV_COMPARISON
|
||||
|
||||
/* Define if you have a broken realpath. */
|
||||
#undef BROKEN_REALPATH
|
||||
|
||||
@ -116,12 +119,12 @@
|
||||
/* Define if you don't want to use wtmpx */
|
||||
#undef DISABLE_WTMPX
|
||||
|
||||
/* Workaround more Linux IPv6 quirks */
|
||||
#undef DONT_TRY_OTHER_AF
|
||||
|
||||
/* Builtin PRNG command timeout */
|
||||
#undef ENTROPY_TIMEOUT_MSEC
|
||||
|
||||
/* f_fsid has members */
|
||||
#undef FSID_HAS_VAL
|
||||
|
||||
/* Define to 1 if the `getpgrp' function requires zero arguments. */
|
||||
#undef GETPGRP_VOID
|
||||
|
||||
@ -158,6 +161,12 @@
|
||||
/* Define to 1 if you have the `arc4random' function. */
|
||||
#undef HAVE_ARC4RANDOM
|
||||
|
||||
/* Define to 1 if you have the `arc4random_buf' function. */
|
||||
#undef HAVE_ARC4RANDOM_BUF
|
||||
|
||||
/* Define to 1 if you have the `arc4random_uniform' function. */
|
||||
#undef HAVE_ARC4RANDOM_UNIFORM
|
||||
|
||||
/* Define to 1 if you have the `asprintf' function. */
|
||||
#undef HAVE_ASPRINTF
|
||||
|
||||
@ -332,9 +341,21 @@
|
||||
/* Define to 1 if you have the <floatingpoint.h> header file. */
|
||||
#undef HAVE_FLOATINGPOINT_H
|
||||
|
||||
/* Define to 1 if you have the `fmt_scaled' function. */
|
||||
#undef HAVE_FMT_SCALED
|
||||
|
||||
/* Define to 1 if you have the `freeaddrinfo' function. */
|
||||
#undef HAVE_FREEADDRINFO
|
||||
|
||||
/* Define to 1 if the system has the type `fsblkcnt_t'. */
|
||||
#undef HAVE_FSBLKCNT_T
|
||||
|
||||
/* Define to 1 if the system has the type `fsfilcnt_t'. */
|
||||
#undef HAVE_FSFILCNT_T
|
||||
|
||||
/* Define to 1 if you have the `fstatvfs' function. */
|
||||
#undef HAVE_FSTATVFS
|
||||
|
||||
/* Define to 1 if you have the `futimes' function. */
|
||||
#undef HAVE_FUTIMES
|
||||
|
||||
@ -810,6 +831,12 @@
|
||||
/* Fields in struct sockaddr_storage */
|
||||
#undef HAVE_SS_FAMILY_IN_SS
|
||||
|
||||
/* Define to 1 if you have the `statfs' function. */
|
||||
#undef HAVE_STATFS
|
||||
|
||||
/* Define to 1 if you have the `statvfs' function. */
|
||||
#undef HAVE_STATVFS
|
||||
|
||||
/* Define to 1 if you have the <stddef.h> header file. */
|
||||
#undef HAVE_STDDEF_H
|
||||
|
||||
@ -912,6 +939,9 @@
|
||||
/* Define to 1 if you have the <sys/mman.h> header file. */
|
||||
#undef HAVE_SYS_MMAN_H
|
||||
|
||||
/* Define to 1 if you have the <sys/mount.h> header file. */
|
||||
#undef HAVE_SYS_MOUNT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/ndir.h> header file. */
|
||||
#undef HAVE_SYS_NDIR_H
|
||||
|
||||
@ -933,6 +963,9 @@
|
||||
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||
#undef HAVE_SYS_SELECT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/statvfs.h> header file. */
|
||||
#undef HAVE_SYS_STATVFS_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
|
435
configure
vendored
435
configure
vendored
@ -1,5 +1,5 @@
|
||||
#! /bin/sh
|
||||
# From configure.ac Revision: 1.397 .
|
||||
# From configure.ac Revision: 1.409 .
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.61 for OpenSSH Portable.
|
||||
#
|
||||
@ -723,6 +723,7 @@ MANTYPE
|
||||
mansubdir
|
||||
user_path
|
||||
piddir
|
||||
TEST_SSH_IPV6
|
||||
LIBOBJS
|
||||
LTLIBOBJS'
|
||||
ac_subst_files=''
|
||||
@ -5405,11 +5406,59 @@ if test "$GCC" = "yes" || test "$GCC" = "egcs"; then
|
||||
no_attrib_nonnull=1
|
||||
;;
|
||||
2.*) no_attrib_nonnull=1 ;;
|
||||
3.*) CFLAGS="$CFLAGS -Wsign-compare" ;;
|
||||
4.*) CFLAGS="$CFLAGS -Wsign-compare -Wno-pointer-sign" ;;
|
||||
3.*) CFLAGS="$CFLAGS -Wsign-compare -Wformat-security" ;;
|
||||
4.*) CFLAGS="$CFLAGS -Wsign-compare -Wno-pointer-sign -Wformat-security" ;;
|
||||
*) ;;
|
||||
esac
|
||||
|
||||
{ echo "$as_me:$LINENO: checking if $CC accepts -fno-builtin-memset" >&5
|
||||
echo $ECHO_N "checking if $CC accepts -fno-builtin-memset... $ECHO_C" >&6; }
|
||||
saved_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -fno-builtin-memset"
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
|
||||
#include <string.h>
|
||||
int main(void){char b[10]; memset(b, 0, sizeof(b));}
|
||||
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (ac_try="$ac_link"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_link") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_c_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest$ac_exeext &&
|
||||
$as_test_x conftest$ac_exeext; then
|
||||
{ echo "$as_me:$LINENO: result: yes" >&5
|
||||
echo "${ECHO_T}yes" >&6; }
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
{ echo "$as_me:$LINENO: result: no" >&5
|
||||
echo "${ECHO_T}no" >&6; }
|
||||
CFLAGS="$saved_CFLAGS"
|
||||
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
|
||||
# -fstack-protector-all doesn't always work for some GCC versions
|
||||
# and/or platforms, so we test if we can. If it's not supported
|
||||
# on a give platform gcc will emit a warning so we use -Werror.
|
||||
@ -5740,6 +5789,8 @@ fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -5782,6 +5833,7 @@ for ac_header in \
|
||||
sys/cdefs.h \
|
||||
sys/dir.h \
|
||||
sys/mman.h \
|
||||
sys/mount.h \
|
||||
sys/ndir.h \
|
||||
sys/poll.h \
|
||||
sys/prctl.h \
|
||||
@ -5791,6 +5843,7 @@ for ac_header in \
|
||||
sys/stream.h \
|
||||
sys/stropts.h \
|
||||
sys/strtio.h \
|
||||
sys/statvfs.h \
|
||||
sys/sysmacros.h \
|
||||
sys/time.h \
|
||||
sys/timers.h \
|
||||
@ -7633,11 +7686,6 @@ _ACEOF
|
||||
check_for_libcrypt_later=1
|
||||
check_for_openpty_ctty_bug=1
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define DONT_TRY_OTHER_AF 1
|
||||
_ACEOF
|
||||
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define PAM_TTY_KLUDGE 1
|
||||
_ACEOF
|
||||
@ -9045,6 +9093,11 @@ _ACEOF
|
||||
#define BROKEN_SETREGID 1
|
||||
_ACEOF
|
||||
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define BROKEN_READV_COMPARISON 1
|
||||
_ACEOF
|
||||
|
||||
;;
|
||||
|
||||
*-*-nto-qnx*)
|
||||
@ -11249,7 +11302,8 @@ fi
|
||||
|
||||
|
||||
|
||||
for ac_func in logout updwtmp logwtmp
|
||||
|
||||
for ac_func in fmt_scaled logout updwtmp logwtmp
|
||||
do
|
||||
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
{ echo "$as_me:$LINENO: checking for $ac_func" >&5
|
||||
@ -12592,6 +12646,11 @@ fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -12600,6 +12659,8 @@ fi
|
||||
|
||||
for ac_func in \
|
||||
arc4random \
|
||||
arc4random_buf \
|
||||
arc4random_uniform \
|
||||
asprintf \
|
||||
b64_ntop \
|
||||
__b64_ntop \
|
||||
@ -12613,6 +12674,7 @@ for ac_func in \
|
||||
fchmod \
|
||||
fchown \
|
||||
freeaddrinfo \
|
||||
fstatvfs \
|
||||
futimes \
|
||||
getaddrinfo \
|
||||
getcwd \
|
||||
@ -12664,6 +12726,8 @@ for ac_func in \
|
||||
sigvec \
|
||||
snprintf \
|
||||
socketpair \
|
||||
statfs \
|
||||
statvfs \
|
||||
strdup \
|
||||
strerror \
|
||||
strlcat \
|
||||
@ -21616,6 +21680,153 @@ cat >>confdefs.h <<_ACEOF
|
||||
_ACEOF
|
||||
|
||||
|
||||
fi
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for fsblkcnt_t" >&5
|
||||
echo $ECHO_N "checking for fsblkcnt_t... $ECHO_C" >&6; }
|
||||
if test "${ac_cv_type_fsblkcnt_t+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_BITYPES_H
|
||||
#include <sys/bitypes.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_STATFS_H
|
||||
#include <sys/statfs.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_STATVFS_H
|
||||
#include <sys/statvfs.h>
|
||||
#endif
|
||||
|
||||
|
||||
typedef fsblkcnt_t ac__type_new_;
|
||||
int
|
||||
main ()
|
||||
{
|
||||
if ((ac__type_new_ *) 0)
|
||||
return 0;
|
||||
if (sizeof (ac__type_new_))
|
||||
return 0;
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext
|
||||
if { (ac_try="$ac_compile"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_compile") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_c_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
ac_cv_type_fsblkcnt_t=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_cv_type_fsblkcnt_t=no
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $ac_cv_type_fsblkcnt_t" >&5
|
||||
echo "${ECHO_T}$ac_cv_type_fsblkcnt_t" >&6; }
|
||||
if test $ac_cv_type_fsblkcnt_t = yes; then
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_FSBLKCNT_T 1
|
||||
_ACEOF
|
||||
|
||||
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: checking for fsfilcnt_t" >&5
|
||||
echo $ECHO_N "checking for fsfilcnt_t... $ECHO_C" >&6; }
|
||||
if test "${ac_cv_type_fsfilcnt_t+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_BITYPES_H
|
||||
#include <sys/bitypes.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_STATFS_H
|
||||
#include <sys/statfs.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_STATVFS_H
|
||||
#include <sys/statvfs.h>
|
||||
#endif
|
||||
|
||||
|
||||
typedef fsfilcnt_t ac__type_new_;
|
||||
int
|
||||
main ()
|
||||
{
|
||||
if ((ac__type_new_ *) 0)
|
||||
return 0;
|
||||
if (sizeof (ac__type_new_))
|
||||
return 0;
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext
|
||||
if { (ac_try="$ac_compile"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_compile") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_c_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
ac_cv_type_fsfilcnt_t=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_cv_type_fsfilcnt_t=no
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $ac_cv_type_fsfilcnt_t" >&5
|
||||
echo "${ECHO_T}$ac_cv_type_fsfilcnt_t" >&6; }
|
||||
if test $ac_cv_type_fsfilcnt_t = yes; then
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_FSFILCNT_T 1
|
||||
_ACEOF
|
||||
|
||||
|
||||
fi
|
||||
|
||||
|
||||
@ -23925,6 +24136,60 @@ _ACEOF
|
||||
|
||||
fi
|
||||
|
||||
{ echo "$as_me:$LINENO: checking if f_fsid has val members" >&5
|
||||
echo $ECHO_N "checking if f_fsid has val members... $ECHO_C" >&6; }
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/statvfs.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
struct fsid_t t; t.val[0] = 0;
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext
|
||||
if { (ac_try="$ac_compile"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_compile") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_c_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
{ echo "$as_me:$LINENO: result: yes" >&5
|
||||
echo "${ECHO_T}yes" >&6; }
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define FSID_HAS_VAL 1
|
||||
_ACEOF
|
||||
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
{ echo "$as_me:$LINENO: result: no" >&5
|
||||
echo "${ECHO_T}no" >&6; }
|
||||
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for msg_control field in struct msghdr" >&5
|
||||
echo $ECHO_N "checking for msg_control field in struct msghdr... $ECHO_C" >&6; }
|
||||
if test "${ac_cv_have_control_in_msghdr+set}" = set; then
|
||||
@ -26203,75 +26468,7 @@ if test "$ac_res" != no; then
|
||||
fi
|
||||
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for gss_init_sec_context in -lgssapi" >&5
|
||||
echo $ECHO_N "checking for gss_init_sec_context in -lgssapi... $ECHO_C" >&6; }
|
||||
if test "${ac_cv_lib_gssapi_gss_init_sec_context+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lgssapi $K5LIBS $LIBS"
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char gss_init_sec_context ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return gss_init_sec_context ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (ac_try="$ac_link"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_link") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_c_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest$ac_exeext &&
|
||||
$as_test_x conftest$ac_exeext; then
|
||||
ac_cv_lib_gssapi_gss_init_sec_context=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_cv_lib_gssapi_gss_init_sec_context=no
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $ac_cv_lib_gssapi_gss_init_sec_context" >&5
|
||||
echo "${ECHO_T}$ac_cv_lib_gssapi_gss_init_sec_context" >&6; }
|
||||
if test $ac_cv_lib_gssapi_gss_init_sec_context = yes; then
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define GSSAPI 1
|
||||
_ACEOF
|
||||
|
||||
K5LIBS="-lgssapi $K5LIBS"
|
||||
else
|
||||
{ echo "$as_me:$LINENO: checking for gss_init_sec_context in -lgssapi_krb5" >&5
|
||||
{ echo "$as_me:$LINENO: checking for gss_init_sec_context in -lgssapi_krb5" >&5
|
||||
echo $ECHO_N "checking for gss_init_sec_context in -lgssapi_krb5... $ECHO_C" >&6; }
|
||||
if test "${ac_cv_lib_gssapi_krb5_gss_init_sec_context+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
@ -26337,7 +26534,75 @@ if test $ac_cv_lib_gssapi_krb5_gss_init_sec_context = yes; then
|
||||
#define GSSAPI 1
|
||||
_ACEOF
|
||||
|
||||
K5LIBS="-lgssapi_krb5 $K5LIBS"
|
||||
K5LIBS="-lgssapi_krb5 $K5LIBS"
|
||||
else
|
||||
{ echo "$as_me:$LINENO: checking for gss_init_sec_context in -lgssapi" >&5
|
||||
echo $ECHO_N "checking for gss_init_sec_context in -lgssapi... $ECHO_C" >&6; }
|
||||
if test "${ac_cv_lib_gssapi_gss_init_sec_context+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lgssapi $K5LIBS $LIBS"
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char gss_init_sec_context ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return gss_init_sec_context ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (ac_try="$ac_link"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_link") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_c_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest$ac_exeext &&
|
||||
$as_test_x conftest$ac_exeext; then
|
||||
ac_cv_lib_gssapi_gss_init_sec_context=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_cv_lib_gssapi_gss_init_sec_context=no
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $ac_cv_lib_gssapi_gss_init_sec_context" >&5
|
||||
echo "${ECHO_T}$ac_cv_lib_gssapi_gss_init_sec_context" >&6; }
|
||||
if test $ac_cv_lib_gssapi_gss_init_sec_context = yes; then
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define GSSAPI 1
|
||||
_ACEOF
|
||||
|
||||
K5LIBS="-lgssapi $K5LIBS"
|
||||
else
|
||||
{ echo "$as_me:$LINENO: WARNING: Cannot find any suitable gss-api library - build may fail" >&5
|
||||
echo "$as_me: WARNING: Cannot find any suitable gss-api library - build may fail" >&2;}
|
||||
@ -28607,6 +28872,15 @@ fi
|
||||
|
||||
CFLAGS="$CFLAGS $werror_flags"
|
||||
|
||||
if grep "#define BROKEN_GETADDRINFO 1" confdefs.h >/dev/null || \
|
||||
test "x$ac_cv_func_getaddrinfo" != "xyes" ; then
|
||||
TEST_SSH_IPV6=no
|
||||
|
||||
else
|
||||
TEST_SSH_IPV6=yes
|
||||
|
||||
fi
|
||||
|
||||
|
||||
ac_config_files="$ac_config_files Makefile buildpkg.sh opensshd.init openssh.xml openbsd-compat/Makefile openbsd-compat/regress/Makefile scard/Makefile ssh_prng_cmds survey.sh"
|
||||
|
||||
@ -29382,11 +29656,12 @@ MANTYPE!$MANTYPE$ac_delim
|
||||
mansubdir!$mansubdir$ac_delim
|
||||
user_path!$user_path$ac_delim
|
||||
piddir!$piddir$ac_delim
|
||||
TEST_SSH_IPV6!$TEST_SSH_IPV6$ac_delim
|
||||
LIBOBJS!$LIBOBJS$ac_delim
|
||||
LTLIBOBJS!$LTLIBOBJS$ac_delim
|
||||
_ACEOF
|
||||
|
||||
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 12; then
|
||||
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 13; then
|
||||
break
|
||||
elif $ac_last_try; then
|
||||
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
|
||||
|
68
configure.ac
68
configure.ac
@ -1,4 +1,4 @@
|
||||
# $Id: configure.ac,v 1.397 2008/03/27 01:33:07 djm Exp $
|
||||
# $Id: configure.ac,v 1.409 2008/07/09 11:07:19 djm Exp $
|
||||
#
|
||||
# Copyright (c) 1999-2004 Damien Miller
|
||||
#
|
||||
@ -15,7 +15,7 @@
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
AC_INIT(OpenSSH, Portable, openssh-unix-dev@mindrot.org)
|
||||
AC_REVISION($Revision: 1.397 $)
|
||||
AC_REVISION($Revision: 1.409 $)
|
||||
AC_CONFIG_SRCDIR([ssh.c])
|
||||
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
@ -107,11 +107,23 @@ if test "$GCC" = "yes" || test "$GCC" = "egcs"; then
|
||||
no_attrib_nonnull=1
|
||||
;;
|
||||
2.*) no_attrib_nonnull=1 ;;
|
||||
3.*) CFLAGS="$CFLAGS -Wsign-compare" ;;
|
||||
4.*) CFLAGS="$CFLAGS -Wsign-compare -Wno-pointer-sign" ;;
|
||||
3.*) CFLAGS="$CFLAGS -Wsign-compare -Wformat-security" ;;
|
||||
4.*) CFLAGS="$CFLAGS -Wsign-compare -Wno-pointer-sign -Wformat-security" ;;
|
||||
*) ;;
|
||||
esac
|
||||
|
||||
AC_MSG_CHECKING(if $CC accepts -fno-builtin-memset)
|
||||
saved_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -fno-builtin-memset"
|
||||
AC_LINK_IFELSE( [AC_LANG_SOURCE([[
|
||||
#include <string.h>
|
||||
int main(void){char b[10]; memset(b, 0, sizeof(b));}
|
||||
]])],
|
||||
[ AC_MSG_RESULT(yes) ],
|
||||
[ AC_MSG_RESULT(no)
|
||||
CFLAGS="$saved_CFLAGS" ]
|
||||
)
|
||||
|
||||
# -fstack-protector-all doesn't always work for some GCC versions
|
||||
# and/or platforms, so we test if we can. If it's not supported
|
||||
# on a give platform gcc will emit a warning so we use -Werror.
|
||||
@ -267,6 +279,7 @@ AC_CHECK_HEADERS( \
|
||||
sys/cdefs.h \
|
||||
sys/dir.h \
|
||||
sys/mman.h \
|
||||
sys/mount.h \
|
||||
sys/ndir.h \
|
||||
sys/poll.h \
|
||||
sys/prctl.h \
|
||||
@ -276,6 +289,7 @@ AC_CHECK_HEADERS( \
|
||||
sys/stream.h \
|
||||
sys/stropts.h \
|
||||
sys/strtio.h \
|
||||
sys/statvfs.h \
|
||||
sys/sysmacros.h \
|
||||
sys/time.h \
|
||||
sys/timers.h \
|
||||
@ -551,7 +565,6 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
|
||||
no_dev_ptmx=1
|
||||
check_for_libcrypt_later=1
|
||||
check_for_openpty_ctty_bug=1
|
||||
AC_DEFINE(DONT_TRY_OTHER_AF, 1, [Workaround more Linux IPv6 quirks])
|
||||
AC_DEFINE(PAM_TTY_KLUDGE, 1,
|
||||
[Work around problematic Linux PAM modules handling of PAM_TTY])
|
||||
AC_DEFINE(LOCKED_PASSWD_PREFIX, "!",
|
||||
@ -828,6 +841,7 @@ mips-sony-bsd|mips-sony-newsos4)
|
||||
AC_DEFINE(SETEUID_BREAKS_SETUID)
|
||||
AC_DEFINE(BROKEN_SETREUID)
|
||||
AC_DEFINE(BROKEN_SETREGID)
|
||||
AC_DEFINE(BROKEN_READV_COMPARISON, 1, [Can't do comparisons on readv])
|
||||
;;
|
||||
|
||||
*-*-nto-qnx*)
|
||||
@ -1034,7 +1048,7 @@ dnl Checks for libutil functions
|
||||
AC_CHECK_HEADERS(libutil.h)
|
||||
AC_SEARCH_LIBS(login, util bsd, [AC_DEFINE(HAVE_LOGIN, 1,
|
||||
[Define if your libraries define login()])])
|
||||
AC_CHECK_FUNCS(logout updwtmp logwtmp)
|
||||
AC_CHECK_FUNCS(fmt_scaled logout updwtmp logwtmp)
|
||||
|
||||
AC_FUNC_STRFTIME
|
||||
|
||||
@ -1288,6 +1302,8 @@ AC_ARG_WITH(audit,
|
||||
dnl Checks for library functions. Please keep in alphabetical order
|
||||
AC_CHECK_FUNCS( \
|
||||
arc4random \
|
||||
arc4random_buf \
|
||||
arc4random_uniform \
|
||||
asprintf \
|
||||
b64_ntop \
|
||||
__b64_ntop \
|
||||
@ -1301,6 +1317,7 @@ AC_CHECK_FUNCS( \
|
||||
fchmod \
|
||||
fchown \
|
||||
freeaddrinfo \
|
||||
fstatvfs \
|
||||
futimes \
|
||||
getaddrinfo \
|
||||
getcwd \
|
||||
@ -1352,6 +1369,8 @@ AC_CHECK_FUNCS( \
|
||||
sigvec \
|
||||
snprintf \
|
||||
socketpair \
|
||||
statfs \
|
||||
statvfs \
|
||||
strdup \
|
||||
strerror \
|
||||
strlcat \
|
||||
@ -2645,6 +2664,18 @@ fi
|
||||
TYPE_SOCKLEN_T
|
||||
|
||||
AC_CHECK_TYPES(sig_atomic_t,,,[#include <signal.h>])
|
||||
AC_CHECK_TYPES([fsblkcnt_t, fsfilcnt_t],,,[
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_BITYPES_H
|
||||
#include <sys/bitypes.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_STATFS_H
|
||||
#include <sys/statfs.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_STATVFS_H
|
||||
#include <sys/statvfs.h>
|
||||
#endif
|
||||
])
|
||||
|
||||
AC_CHECK_TYPES(in_addr_t,,,
|
||||
[#include <sys/types.h>
|
||||
@ -3007,6 +3038,16 @@ if test "x$ac_cv_have_accrights_in_msghdr" = "xyes" ; then
|
||||
file descriptor passing])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(if f_fsid has val members)
|
||||
AC_TRY_COMPILE([
|
||||
#include <sys/types.h>
|
||||
#include <sys/statvfs.h>],
|
||||
[struct fsid_t t; t.val[0] = 0;],
|
||||
[ AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(FSID_HAS_VAL, 1, f_fsid has members) ],
|
||||
[ AC_MSG_RESULT(no) ]
|
||||
)
|
||||
|
||||
AC_CACHE_CHECK([for msg_control field in struct msghdr],
|
||||
ac_cv_have_control_in_msghdr, [
|
||||
AC_COMPILE_IFELSE(
|
||||
@ -3335,12 +3376,12 @@ AC_ARG_WITH(kerberos5,
|
||||
)
|
||||
AC_SEARCH_LIBS(dn_expand, resolv)
|
||||
|
||||
AC_CHECK_LIB(gssapi,gss_init_sec_context,
|
||||
AC_CHECK_LIB(gssapi_krb5, gss_init_sec_context,
|
||||
[ AC_DEFINE(GSSAPI)
|
||||
K5LIBS="-lgssapi $K5LIBS" ],
|
||||
[ AC_CHECK_LIB(gssapi_krb5,gss_init_sec_context,
|
||||
K5LIBS="-lgssapi_krb5 $K5LIBS" ],
|
||||
[ AC_CHECK_LIB(gssapi, gss_init_sec_context,
|
||||
[ AC_DEFINE(GSSAPI)
|
||||
K5LIBS="-lgssapi_krb5 $K5LIBS" ],
|
||||
K5LIBS="-lgssapi $K5LIBS" ],
|
||||
AC_MSG_WARN([Cannot find any suitable gss-api library - build may fail]),
|
||||
$K5LIBS)
|
||||
],
|
||||
@ -4039,6 +4080,13 @@ dnl Adding -Werror to CFLAGS early prevents configure tests from running.
|
||||
dnl Add now.
|
||||
CFLAGS="$CFLAGS $werror_flags"
|
||||
|
||||
if grep "#define BROKEN_GETADDRINFO 1" confdefs.h >/dev/null || \
|
||||
test "x$ac_cv_func_getaddrinfo" != "xyes" ; then
|
||||
AC_SUBST(TEST_SSH_IPV6, no)
|
||||
else
|
||||
AC_SUBST(TEST_SSH_IPV6, yes)
|
||||
fi
|
||||
|
||||
AC_EXEEXT
|
||||
AC_CONFIG_FILES([Makefile buildpkg.sh opensshd.init openssh.xml \
|
||||
openbsd-compat/Makefile openbsd-compat/regress/Makefile \
|
||||
|
@ -17,11 +17,11 @@
|
||||
#old cvs stuff. please update before use. may be deprecated.
|
||||
%define use_stable 1
|
||||
%if %{use_stable}
|
||||
%define version 5.0p1
|
||||
%define version 5.1p1
|
||||
%define cvs %{nil}
|
||||
%define release 1
|
||||
%else
|
||||
%define version 5.0p1
|
||||
%define version 5.1p1
|
||||
%define cvs cvs20050315
|
||||
%define release 0r1
|
||||
%endif
|
||||
@ -342,6 +342,7 @@ fi
|
||||
%config %{SVIcdir}/sshd
|
||||
%{_libexecdir}/sftp-server
|
||||
%{_sbindir}/sshd
|
||||
%{_mandir}/man5/moduli.5.gz
|
||||
%{_mandir}/man5/sshd_config.5.gz
|
||||
%{_mandir}/man8/sftp-server.8.gz
|
||||
%{_mandir}/man8/sshd.8.gz
|
||||
@ -357,4 +358,4 @@ fi
|
||||
* Mon Jan 01 1998 ...
|
||||
Template Version: 1.31
|
||||
|
||||
$Id: openssh.spec,v 1.63 2008/04/03 09:55:46 djm Exp $
|
||||
$Id: openssh.spec,v 1.65 2008/07/21 08:21:53 djm Exp $
|
||||
|
@ -8,6 +8,7 @@ sshdocdir=$(docdir)/openssh
|
||||
cygdocdir=$(docdir)/Cygwin
|
||||
sysconfdir=/etc
|
||||
defaultsdir=$(sysconfdir)/defaults/etc
|
||||
inetdefdir=$(defaultsdir)/inetd.d
|
||||
PRIVSEP_PATH=/var/empty
|
||||
INSTALL=/usr/bin/install -c
|
||||
|
||||
@ -27,6 +28,10 @@ move-config-files: $(DESTDIR)$(sysconfdir)/ssh_config $(DESTDIR)$(sysconfdir)/ss
|
||||
remove-empty-dir:
|
||||
rm -rf $(DESTDIR)$(PRIVSEP_PATH)
|
||||
|
||||
install-inetd-config:
|
||||
$(srcdir)/mkinstalldirs $(DESTDIR)$(inetdefdir)
|
||||
$(INSTALL) -m 644 sshd-inetd $(DESTDIR)$(inetdefdir)/sshd-inetd
|
||||
|
||||
install-sshdoc:
|
||||
$(srcdir)/mkinstalldirs $(DESTDIR)$(sshdocdir)
|
||||
$(INSTALL) -m 644 $(srcdir)/CREDITS $(DESTDIR)$(sshdocdir)/CREDITS
|
||||
@ -52,5 +57,5 @@ install-scripts: ssh-host-config ssh-user-config
|
||||
$(INSTALL) -m 755 ssh-host-config $(DESTDIR)$(bindir)/ssh-host-config
|
||||
$(INSTALL) -m 755 ssh-user-config $(DESTDIR)$(bindir)/ssh-user-config
|
||||
|
||||
cygwin-postinstall: move-config-files remove-empty-dir install-doc install-scripts
|
||||
cygwin-postinstall: move-config-files remove-empty-dir install-inetd-config install-doc install-scripts
|
||||
@echo "Cygwin specific configuration finished."
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,52 +1,235 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
#
|
||||
# ssh-user-config, Copyright 2000, 2001, 2002, 2003, Red Hat Inc.
|
||||
#
|
||||
# This file is part of the Cygwin port of OpenSSH.
|
||||
|
||||
# ======================================================================
|
||||
# Initialization
|
||||
# ======================================================================
|
||||
PROGNAME=$(basename -- $0)
|
||||
_tdir=$(dirname -- $0)
|
||||
PROGDIR=$(cd $_tdir && pwd)
|
||||
|
||||
CSIH_SCRIPT=/usr/share/csih/cygwin-service-installation-helper.sh
|
||||
|
||||
# Subdirectory where the new package is being installed
|
||||
PREFIX=/usr
|
||||
|
||||
# Directory where the config files are stored
|
||||
SYSCONFDIR=/etc
|
||||
|
||||
progname=$0
|
||||
auto_answer=""
|
||||
source ${CSIH_SCRIPT}
|
||||
|
||||
auto_passphrase="no"
|
||||
passphrase=""
|
||||
pwdhome=
|
||||
with_passphrase=
|
||||
|
||||
request()
|
||||
{
|
||||
if [ "${auto_answer}" = "yes" ]
|
||||
# ======================================================================
|
||||
# Routine: create_ssh1_identity
|
||||
# optionally create ~/.ssh/identity[.pub]
|
||||
# optionally add result to ~/.ssh/authorized_keys
|
||||
# ======================================================================
|
||||
create_ssh1_identity() {
|
||||
if [ ! -f "${pwdhome}/.ssh/identity" ]
|
||||
then
|
||||
return 0
|
||||
elif [ "${auto_answer}" = "no" ]
|
||||
then
|
||||
return 1
|
||||
if csih_request "Shall I create an SSH1 RSA identity file for you?"
|
||||
then
|
||||
csih_inform "Generating ${pwdhome}/.ssh/identity"
|
||||
if [ "${with_passphrase}" = "yes" ]
|
||||
then
|
||||
ssh-keygen -t rsa1 -N "${passphrase}" -f "${pwdhome}/.ssh/identity" > /dev/null
|
||||
else
|
||||
ssh-keygen -t rsa1 -f "${pwdhome}/.ssh/identity" > /dev/null
|
||||
fi
|
||||
if csih_request "Do you want to use this identity to login to this machine?"
|
||||
then
|
||||
csih_inform "Adding to ${pwdhome}/.ssh/authorized_keys"
|
||||
cat "${pwdhome}/.ssh/identity.pub" >> "${pwdhome}/.ssh/authorized_keys"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
} # === End of create_ssh1_identity() === #
|
||||
readonly -f create_ssh1_identity
|
||||
|
||||
answer=""
|
||||
while [ "X${answer}" != "Xyes" -a "X${answer}" != "Xno" ]
|
||||
do
|
||||
echo -n "$1 (yes/no) "
|
||||
read answer
|
||||
done
|
||||
if [ "X${answer}" = "Xyes" ]
|
||||
# ======================================================================
|
||||
# Routine: create_ssh2_rsa_identity
|
||||
# optionally create ~/.ssh/id_rsa[.pub]
|
||||
# optionally add result to ~/.ssh/authorized_keys
|
||||
# ======================================================================
|
||||
create_ssh2_rsa_identity() {
|
||||
if [ ! -f "${pwdhome}/.ssh/id_rsa" ]
|
||||
then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
if csih_request "Shall I create an SSH2 RSA identity file for you?"
|
||||
then
|
||||
csih_inform "Generating ${pwdhome}/.ssh/id_rsa"
|
||||
if [ "${with_passphrase}" = "yes" ]
|
||||
then
|
||||
ssh-keygen -t rsa -N "${passphrase}" -f "${pwdhome}/.ssh/id_rsa" > /dev/null
|
||||
else
|
||||
ssh-keygen -t rsa -f "${pwdhome}/.ssh/id_rsa" > /dev/null
|
||||
fi
|
||||
if csih_request "Do you want to use this identity to login to this machine?"
|
||||
then
|
||||
csih_inform "Adding to ${pwdhome}/.ssh/authorized_keys"
|
||||
cat "${pwdhome}/.ssh/id_rsa.pub" >> "${pwdhome}/.ssh/authorized_keys"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
} # === End of create_ssh2_rsa_identity() === #
|
||||
readonly -f create_ssh2_rsa_identity
|
||||
|
||||
# Check if running on NT
|
||||
_sys="`uname -a`"
|
||||
_nt=`expr "$_sys" : "CYGWIN_NT"`
|
||||
# If running on NT, check if running under 2003 Server or later
|
||||
if [ $_nt -gt 0 ]
|
||||
# ======================================================================
|
||||
# Routine: create_ssh2_dsa_identity
|
||||
# optionally create ~/.ssh/id_dsa[.pub]
|
||||
# optionally add result to ~/.ssh/authorized_keys
|
||||
# ======================================================================
|
||||
create_ssh2_dsa_identity() {
|
||||
if [ ! -f "${pwdhome}/.ssh/id_dsa" ]
|
||||
then
|
||||
if csih_request "Shall I create an SSH2 DSA identity file for you?"
|
||||
then
|
||||
csih_inform "Generating ${pwdhome}/.ssh/id_dsa"
|
||||
if [ "${with_passphrase}" = "yes" ]
|
||||
then
|
||||
ssh-keygen -t dsa -N "${passphrase}" -f "${pwdhome}/.ssh/id_dsa" > /dev/null
|
||||
else
|
||||
ssh-keygen -t dsa -f "${pwdhome}/.ssh/id_dsa" > /dev/null
|
||||
fi
|
||||
if csih_request "Do you want to use this identity to login to this machine?"
|
||||
then
|
||||
csih_inform "Adding to ${pwdhome}/.ssh/authorized_keys"
|
||||
cat "${pwdhome}/.ssh/id_dsa.pub" >> "${pwdhome}/.ssh/authorized_keys"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
} # === End of create_ssh2_dsa_identity() === #
|
||||
readonly -f create_ssh2_dsa_identity
|
||||
|
||||
# ======================================================================
|
||||
# Routine: check_user_homedir
|
||||
# Perform various checks on the user's home directory
|
||||
# SETS GLOBAL VARIABLE:
|
||||
# pwdhome
|
||||
# ======================================================================
|
||||
check_user_homedir() {
|
||||
local uid=$(id -u)
|
||||
pwdhome=$(awk -F: '{ if ( $3 == '${uid}' ) print $6; }' < ${SYSCONFDIR}/passwd)
|
||||
if [ "X${pwdhome}" = "X" ]
|
||||
then
|
||||
csih_error_multiline \
|
||||
"There is no home directory set for you in ${SYSCONFDIR}/passwd." \
|
||||
'Setting $HOME is not sufficient!'
|
||||
fi
|
||||
|
||||
if [ ! -d "${pwdhome}" ]
|
||||
then
|
||||
csih_error_multiline \
|
||||
"${pwdhome} is set in ${SYSCONFDIR}/passwd as your home directory" \
|
||||
'but it is not a valid directory. Cannot create user identity files.'
|
||||
fi
|
||||
|
||||
# If home is the root dir, set home to empty string to avoid error messages
|
||||
# in subsequent parts of that script.
|
||||
if [ "X${pwdhome}" = "X/" ]
|
||||
then
|
||||
# But first raise a warning!
|
||||
csih_warning "Your home directory in ${SYSCONFDIR}/passwd is set to root (/). This is not recommended!"
|
||||
if csih_request "Would you like to proceed anyway?"
|
||||
then
|
||||
pwdhome=''
|
||||
else
|
||||
csih_warning "Exiting. Configuration is not complete"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -d "${pwdhome}" -a csih_is_nt -a -n "`chmod -c g-w,o-w "${pwdhome}"`" ]
|
||||
then
|
||||
echo
|
||||
csih_warning 'group and other have been revoked write permission to your home'
|
||||
csih_warning "directory ${pwdhome}."
|
||||
csih_warning 'This is required by OpenSSH to allow public key authentication using'
|
||||
csih_warning 'the key files stored in your .ssh subdirectory.'
|
||||
csih_warning 'Revert this change ONLY if you know what you are doing!'
|
||||
echo
|
||||
fi
|
||||
} # === End of check_user_homedir() === #
|
||||
readonly -f check_user_homedir
|
||||
|
||||
# ======================================================================
|
||||
# Routine: check_user_dot_ssh_dir
|
||||
# Perform various checks on the ~/.ssh directory
|
||||
# PREREQUISITE:
|
||||
# pwdhome -- check_user_homedir()
|
||||
# ======================================================================
|
||||
check_user_dot_ssh_dir() {
|
||||
if [ -e "${pwdhome}/.ssh" -a ! -d "${pwdhome}/.ssh" ]
|
||||
then
|
||||
csih_error "${pwdhome}/.ssh is existant but not a directory. Cannot create user identity files."
|
||||
fi
|
||||
|
||||
if [ ! -e "${pwdhome}/.ssh" ]
|
||||
then
|
||||
mkdir "${pwdhome}/.ssh"
|
||||
if [ ! -e "${pwdhome}/.ssh" ]
|
||||
then
|
||||
csih_error "Creating users ${pwdhome}/.ssh directory failed"
|
||||
fi
|
||||
fi
|
||||
} # === End of check_user_dot_ssh_dir() === #
|
||||
readonly -f check_user_dot_ssh_dir
|
||||
|
||||
# ======================================================================
|
||||
# Routine: fix_authorized_keys_perms
|
||||
# Corrects the permissions of ~/.ssh/authorized_keys
|
||||
# PREREQUISITE:
|
||||
# pwdhome -- check_user_homedir()
|
||||
# ======================================================================
|
||||
fix_authorized_keys_perms() {
|
||||
if [ csih_is_nt -a -e "${pwdhome}/.ssh/authorized_keys" ]
|
||||
then
|
||||
if ! setfacl -m "u::rw-,g::---,o::---" "${pwdhome}/.ssh/authorized_keys"
|
||||
then
|
||||
csih_warning "Setting correct permissions to ${pwdhome}/.ssh/authorized_keys"
|
||||
csih_warning "failed. Please care for the correct permissions. The minimum requirement"
|
||||
csih_warning "is, the owner needs read permissions."
|
||||
echo
|
||||
fi
|
||||
fi
|
||||
} # === End of fix_authorized_keys_perms() === #
|
||||
readonly -f fix_authorized_keys_perms
|
||||
|
||||
|
||||
# ======================================================================
|
||||
# Main Entry Point
|
||||
# ======================================================================
|
||||
|
||||
# Check how the script has been started. If
|
||||
# (1) it has been started by giving the full path and
|
||||
# that path is /etc/postinstall, OR
|
||||
# (2) Otherwise, if the environment variable
|
||||
# SSH_USER_CONFIG_AUTO_ANSWER_NO is set
|
||||
# then set auto_answer to "no". This allows automatic
|
||||
# creation of the config files in /etc w/o overwriting
|
||||
# them if they already exist. In both cases, color
|
||||
# escape sequences are suppressed, so as to prevent
|
||||
# cluttering setup's logfiles.
|
||||
if [ "$PROGDIR" = "/etc/postinstall" ]
|
||||
then
|
||||
_nt2003=`uname | awk -F- '{print ( $2 >= 5.2 ) ? 1 : 0;}'`
|
||||
csih_auto_answer="no"
|
||||
csih_disable_color
|
||||
fi
|
||||
if [ -n "${SSH_USER_CONFIG_AUTO_ANSWER_NO}" ]
|
||||
then
|
||||
csih_auto_answer="no"
|
||||
csih_disable_color
|
||||
fi
|
||||
|
||||
# Check options
|
||||
|
||||
# ======================================================================
|
||||
# Parse options
|
||||
# ======================================================================
|
||||
while :
|
||||
do
|
||||
case $# in
|
||||
@ -61,14 +244,15 @@ do
|
||||
case "$option" in
|
||||
-d | --debug )
|
||||
set -x
|
||||
csih_trace_on
|
||||
;;
|
||||
|
||||
-y | --yes )
|
||||
auto_answer=yes
|
||||
csih_auto_answer=yes
|
||||
;;
|
||||
|
||||
-n | --no )
|
||||
auto_answer=no
|
||||
csih_auto_answer=no
|
||||
;;
|
||||
|
||||
-p | --passphrase )
|
||||
@ -77,8 +261,12 @@ do
|
||||
shift
|
||||
;;
|
||||
|
||||
--privileged )
|
||||
csih_FORCE_PRIVILEGED_USER=yes
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "usage: ${progname} [OPTION]..."
|
||||
echo "usage: ${PROGNAME} [OPTION]..."
|
||||
echo
|
||||
echo "This script creates an OpenSSH user configuration."
|
||||
echo
|
||||
@ -87,6 +275,8 @@ do
|
||||
echo " --yes -y Answer all questions with \"yes\" automatically."
|
||||
echo " --no -n Answer all questions with \"no\" automatically."
|
||||
echo " --passphrase -p word Use \"word\" as passphrase automatically."
|
||||
echo " --privileged On Windows NT/2k/XP, assume privileged user"
|
||||
echo " instead of LocalSystem for sshd service."
|
||||
echo
|
||||
exit 1
|
||||
;;
|
||||
@ -94,157 +284,27 @@ do
|
||||
esac
|
||||
done
|
||||
|
||||
# Ask user if user identity should be generated
|
||||
# ======================================================================
|
||||
# Action!
|
||||
# ======================================================================
|
||||
|
||||
# Check passwd file
|
||||
if [ ! -f ${SYSCONFDIR}/passwd ]
|
||||
then
|
||||
echo "${SYSCONFDIR}/passwd is nonexistant. Please generate an ${SYSCONFDIR}/passwd file"
|
||||
echo 'first using mkpasswd. Check if it contains an entry for you and'
|
||||
echo 'please care for the home directory in your entry as well.'
|
||||
exit 1
|
||||
csih_error_multiline \
|
||||
"${SYSCONFDIR}/passwd is nonexistant. Please generate an ${SYSCONFDIR}/passwd file" \
|
||||
'first using mkpasswd. Check if it contains an entry for you and' \
|
||||
'please care for the home directory in your entry as well.'
|
||||
fi
|
||||
|
||||
uid=`id -u`
|
||||
pwdhome=`awk -F: '{ if ( $3 == '${uid}' ) print $6; }' < ${SYSCONFDIR}/passwd`
|
||||
|
||||
if [ "X${pwdhome}" = "X" ]
|
||||
then
|
||||
echo "There is no home directory set for you in ${SYSCONFDIR}/passwd."
|
||||
echo 'Setting $HOME is not sufficient!'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "${pwdhome}" ]
|
||||
then
|
||||
echo "${pwdhome} is set in ${SYSCONFDIR}/passwd as your home directory"
|
||||
echo 'but it is not a valid directory. Cannot create user identity files.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# If home is the root dir, set home to empty string to avoid error messages
|
||||
# in subsequent parts of that script.
|
||||
if [ "X${pwdhome}" = "X/" ]
|
||||
then
|
||||
# But first raise a warning!
|
||||
echo "Your home directory in ${SYSCONFDIR}/passwd is set to root (/). This is not recommended!"
|
||||
if request "Would you like to proceed anyway?"
|
||||
then
|
||||
pwdhome=''
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -d "${pwdhome}" -a $_nt -gt 0 -a -n "`chmod -c g-w,o-w "${pwdhome}"`" ]
|
||||
then
|
||||
echo
|
||||
echo 'WARNING: group and other have been revoked write permission to your home'
|
||||
echo " directory ${pwdhome}."
|
||||
echo ' This is required by OpenSSH to allow public key authentication using'
|
||||
echo ' the key files stored in your .ssh subdirectory.'
|
||||
echo ' Revert this change ONLY if you know what you are doing!'
|
||||
echo
|
||||
fi
|
||||
|
||||
if [ -e "${pwdhome}/.ssh" -a ! -d "${pwdhome}/.ssh" ]
|
||||
then
|
||||
echo "${pwdhome}/.ssh is existant but not a directory. Cannot create user identity files."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -e "${pwdhome}/.ssh" ]
|
||||
then
|
||||
mkdir "${pwdhome}/.ssh"
|
||||
if [ ! -e "${pwdhome}/.ssh" ]
|
||||
then
|
||||
echo "Creating users ${pwdhome}/.ssh directory failed"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $_nt -gt 0 ]
|
||||
then
|
||||
_user="system"
|
||||
if [ $_nt2003 -gt 0 ]
|
||||
then
|
||||
grep -q '^sshd_server:' ${SYSCONFDIR}/passwd && _user="sshd_server"
|
||||
fi
|
||||
if ! setfacl -m "u::rwx,u:${_user}:r--,g::---,o::---" "${pwdhome}/.ssh"
|
||||
then
|
||||
echo "${pwdhome}/.ssh couldn't be given the correct permissions."
|
||||
echo "Please try to solve this problem first."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "${pwdhome}/.ssh/identity" ]
|
||||
then
|
||||
if request "Shall I create an SSH1 RSA identity file for you?"
|
||||
then
|
||||
echo "Generating ${pwdhome}/.ssh/identity"
|
||||
if [ "${with_passphrase}" = "yes" ]
|
||||
then
|
||||
ssh-keygen -t rsa1 -N "${passphrase}" -f "${pwdhome}/.ssh/identity" > /dev/null
|
||||
else
|
||||
ssh-keygen -t rsa1 -f "${pwdhome}/.ssh/identity" > /dev/null
|
||||
fi
|
||||
if request "Do you want to use this identity to login to this machine?"
|
||||
then
|
||||
echo "Adding to ${pwdhome}/.ssh/authorized_keys"
|
||||
cat "${pwdhome}/.ssh/identity.pub" >> "${pwdhome}/.ssh/authorized_keys"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "${pwdhome}/.ssh/id_rsa" ]
|
||||
then
|
||||
if request "Shall I create an SSH2 RSA identity file for you?"
|
||||
then
|
||||
echo "Generating ${pwdhome}/.ssh/id_rsa"
|
||||
if [ "${with_passphrase}" = "yes" ]
|
||||
then
|
||||
ssh-keygen -t rsa -N "${passphrase}" -f "${pwdhome}/.ssh/id_rsa" > /dev/null
|
||||
else
|
||||
ssh-keygen -t rsa -f "${pwdhome}/.ssh/id_rsa" > /dev/null
|
||||
fi
|
||||
if request "Do you want to use this identity to login to this machine?"
|
||||
then
|
||||
echo "Adding to ${pwdhome}/.ssh/authorized_keys"
|
||||
cat "${pwdhome}/.ssh/id_rsa.pub" >> "${pwdhome}/.ssh/authorized_keys"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "${pwdhome}/.ssh/id_dsa" ]
|
||||
then
|
||||
if request "Shall I create an SSH2 DSA identity file for you?"
|
||||
then
|
||||
echo "Generating ${pwdhome}/.ssh/id_dsa"
|
||||
if [ "${with_passphrase}" = "yes" ]
|
||||
then
|
||||
ssh-keygen -t dsa -N "${passphrase}" -f "${pwdhome}/.ssh/id_dsa" > /dev/null
|
||||
else
|
||||
ssh-keygen -t dsa -f "${pwdhome}/.ssh/id_dsa" > /dev/null
|
||||
fi
|
||||
if request "Do you want to use this identity to login to this machine?"
|
||||
then
|
||||
echo "Adding to ${pwdhome}/.ssh/authorized_keys"
|
||||
cat "${pwdhome}/.ssh/id_dsa.pub" >> "${pwdhome}/.ssh/authorized_keys"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $_nt -gt 0 -a -e "${pwdhome}/.ssh/authorized_keys" ]
|
||||
then
|
||||
if ! setfacl -m "u::rw-,u:${_user}:r--,g::---,o::---" "${pwdhome}/.ssh/authorized_keys"
|
||||
then
|
||||
echo
|
||||
echo "WARNING: Setting correct permissions to ${pwdhome}/.ssh/authorized_keys"
|
||||
echo "failed. Please care for the correct permissions. The minimum requirement"
|
||||
echo "is, the owner and ${_user} both need read permissions."
|
||||
echo
|
||||
fi
|
||||
fi
|
||||
check_user_homedir
|
||||
check_user_dot_ssh_dir
|
||||
create_ssh1_identity
|
||||
create_ssh2_rsa_identity
|
||||
create_ssh2_dsa_identity
|
||||
fix_authorized_keys_perms
|
||||
|
||||
echo
|
||||
echo "Configuration finished. Have fun!"
|
||||
csih_inform "Configuration finished. Have fun!"
|
||||
|
||||
|
||||
|
4
contrib/cygwin/sshd-inetd
Normal file
4
contrib/cygwin/sshd-inetd
Normal file
@ -0,0 +1,4 @@
|
||||
# This file can be used to enable sshd as a slave of the inetd service
|
||||
# To do so, the line below should be uncommented.
|
||||
@COMMENT@ ssh stream tcp nowait root /usr/sbin/sshd sshd -i
|
||||
|
@ -1,4 +1,4 @@
|
||||
%define ver 5.0p1
|
||||
%define ver 5.1p1
|
||||
%define rel 1
|
||||
|
||||
# OpenSSH privilege separation requires a user & group ID
|
||||
@ -376,6 +376,7 @@ fi
|
||||
%attr(0755,root,root) %{_sbindir}/sshd
|
||||
%attr(0755,root,root) %{_libexecdir}/openssh/sftp-server
|
||||
%attr(0644,root,root) %{_mandir}/man8/sshd.8*
|
||||
%attr(0644,root,root) %{_mandir}/man5/moduli.5*
|
||||
%attr(0644,root,root) %{_mandir}/man5/sshd_config.5*
|
||||
%attr(0644,root,root) %{_mandir}/man8/sftp-server.8*
|
||||
%attr(0755,root,root) %dir %{_sysconfdir}/ssh
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation
|
||||
Name: openssh
|
||||
Version: 5.0p1
|
||||
Version: 5.1p1
|
||||
URL: http://www.openssh.com/
|
||||
Release: 1
|
||||
Source0: openssh-%{version}.tar.gz
|
||||
@ -201,7 +201,7 @@ fi
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%doc ChangeLog OVERVIEW README*
|
||||
%doc RFC.nroff TODO CREDITS LICENCE
|
||||
%doc TODO CREDITS LICENCE
|
||||
%attr(0755,root,root) %dir %{_sysconfdir}/ssh
|
||||
%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh/ssh_config
|
||||
%attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/sshd_config
|
||||
@ -228,6 +228,7 @@ fi
|
||||
%attr(0644,root,root) %doc %{_mandir}/man1/ssh-agent.1*
|
||||
%attr(0644,root,root) %doc %{_mandir}/man1/ssh-keygen.1*
|
||||
%attr(0644,root,root) %doc %{_mandir}/man1/ssh-keyscan.1*
|
||||
%attr(0644,root,root) %doc %{_mandir}/man5/moduli.5*
|
||||
%attr(0644,root,root) %doc %{_mandir}/man5/ssh_config.5*
|
||||
%attr(0644,root,root) %doc %{_mandir}/man5/sshd_config.5*
|
||||
%attr(0644,root,root) %doc %{_mandir}/man8/sftp-server.8*
|
||||
|
19
defines.h
19
defines.h
@ -25,7 +25,7 @@
|
||||
#ifndef _DEFINES_H
|
||||
#define _DEFINES_H
|
||||
|
||||
/* $Id: defines.h,v 1.146 2008/02/28 08:22:04 dtucker Exp $ */
|
||||
/* $Id: defines.h,v 1.151 2008/07/04 13:10:49 djm Exp $ */
|
||||
|
||||
|
||||
/* Constants */
|
||||
@ -431,10 +431,6 @@ struct winsize {
|
||||
# define __attribute__(x)
|
||||
#endif /* !defined(__GNUC__) || (__GNUC__ < 2) */
|
||||
|
||||
#ifndef __dead
|
||||
# define __dead __attribute__((noreturn))
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_ATTRIBUTE__SENTINEL__) && !defined(__sentinel__)
|
||||
# define __sentinel__
|
||||
#endif
|
||||
@ -590,6 +586,15 @@ struct winsize {
|
||||
# define SSH_SYSFDMAX 10000
|
||||
#endif
|
||||
|
||||
#ifdef FSID_HAS_VAL
|
||||
/* encode f_fsid into a 64 bit value */
|
||||
#define FSID_TO_ULONG(f) \
|
||||
((((u_int64_t)(f).val[0] & 0xffffffffUL) << 32) | \
|
||||
((f).val[1] & 0xffffffffUL))
|
||||
#else
|
||||
# define FSID_TO_ULONG(f) ((f))
|
||||
#endif
|
||||
|
||||
#if defined(__Lynx__)
|
||||
/*
|
||||
* LynxOS defines these in param.h which we do not want to include since
|
||||
@ -729,4 +734,8 @@ struct winsize {
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef EWOULDBLOCK
|
||||
# define EWOULDBLOCK EAGAIN
|
||||
#endif
|
||||
|
||||
#endif /* _DEFINES_H */
|
||||
|
17
dh.c
17
dh.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: dh.c,v 1.45 2007/09/27 00:15:57 ray Exp $ */
|
||||
/* $OpenBSD: dh.c,v 1.47 2008/06/26 09:19:39 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Niels Provos. All rights reserved.
|
||||
*
|
||||
@ -46,6 +46,7 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg)
|
||||
char *cp, *arg;
|
||||
char *strsize, *gen, *prime;
|
||||
const char *errstr = NULL;
|
||||
long long n;
|
||||
|
||||
cp = line;
|
||||
if ((arg = strdelim(&cp)) == NULL)
|
||||
@ -62,12 +63,24 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg)
|
||||
arg = strsep(&cp, " "); /* type */
|
||||
if (cp == NULL || *arg == '\0')
|
||||
goto fail;
|
||||
/* Ensure this is a safe prime */
|
||||
n = strtonum(arg, 0, 5, &errstr);
|
||||
if (errstr != NULL || n != MODULI_TYPE_SAFE)
|
||||
goto fail;
|
||||
arg = strsep(&cp, " "); /* tests */
|
||||
if (cp == NULL || *arg == '\0')
|
||||
goto fail;
|
||||
/* Ensure prime has been tested and is not composite */
|
||||
n = strtonum(arg, 0, 0x1f, &errstr);
|
||||
if (errstr != NULL ||
|
||||
(n & MODULI_TESTS_COMPOSITE) || !(n & ~MODULI_TESTS_COMPOSITE))
|
||||
goto fail;
|
||||
arg = strsep(&cp, " "); /* tries */
|
||||
if (cp == NULL || *arg == '\0')
|
||||
goto fail;
|
||||
n = strtonum(arg, 0, 1<<30, &errstr);
|
||||
if (errstr != NULL || n == 0)
|
||||
goto fail;
|
||||
strsize = strsep(&cp, " "); /* size */
|
||||
if (cp == NULL || *strsize == '\0' ||
|
||||
(dhg->size = (u_int)strtonum(strsize, 0, 64*1024, &errstr)) == 0 ||
|
||||
@ -153,7 +166,7 @@ choose_dh(int min, int wantbits, int max)
|
||||
}
|
||||
|
||||
linenum = 0;
|
||||
which = arc4random() % bestcount;
|
||||
which = arc4random_uniform(bestcount);
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
if (!parse_prime(linenum, line, &dhg))
|
||||
continue;
|
||||
|
26
dh.h
26
dh.h
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: dh.h,v 1.9 2006/03/25 22:22:43 djm Exp $ */
|
||||
/* $OpenBSD: dh.h,v 1.10 2008/06/26 09:19:40 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000 Niels Provos. All rights reserved.
|
||||
@ -46,4 +46,28 @@ int dh_estimate(int);
|
||||
#define DH_GRP_MIN 1024
|
||||
#define DH_GRP_MAX 8192
|
||||
|
||||
/*
|
||||
* Values for "type" field of moduli(5)
|
||||
* Specifies the internal structure of the prime modulus.
|
||||
*/
|
||||
#define MODULI_TYPE_UNKNOWN (0)
|
||||
#define MODULI_TYPE_UNSTRUCTURED (1)
|
||||
#define MODULI_TYPE_SAFE (2)
|
||||
#define MODULI_TYPE_SCHNORR (3)
|
||||
#define MODULI_TYPE_SOPHIE_GERMAIN (4)
|
||||
#define MODULI_TYPE_STRONG (5)
|
||||
|
||||
/*
|
||||
* Values for "tests" field of moduli(5)
|
||||
* Specifies the methods used in checking for primality.
|
||||
* Usually, more than one test is used.
|
||||
*/
|
||||
#define MODULI_TESTS_UNTESTED (0x00)
|
||||
#define MODULI_TESTS_COMPOSITE (0x01)
|
||||
#define MODULI_TESTS_SIEVE (0x02)
|
||||
#define MODULI_TESTS_MILLER_RABIN (0x04)
|
||||
#define MODULI_TESTS_JACOBI (0x08)
|
||||
#define MODULI_TESTS_ELLIPTIC (0x10)
|
||||
|
||||
|
||||
#endif
|
||||
|
13
dns.c
13
dns.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: dns.c,v 1.24 2007/01/03 03:01:40 stevesk Exp $ */
|
||||
/* $OpenBSD: dns.c,v 1.25 2008/06/12 00:03:49 dtucker Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
|
||||
@ -145,11 +145,20 @@ is_numeric_hostname(const char *hostname)
|
||||
{
|
||||
struct addrinfo hints, *ai;
|
||||
|
||||
/*
|
||||
* We shouldn't ever get a null host but if we do then log an error
|
||||
* and return -1 which stops DNS key fingerprint processing.
|
||||
*/
|
||||
if (hostname == NULL) {
|
||||
error("is_numeric_hostname called with NULL hostname");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
|
||||
if (getaddrinfo(hostname, "0", &hints, &ai) == 0) {
|
||||
if (getaddrinfo(hostname, NULL, &hints, &ai) == 0) {
|
||||
freeaddrinfo(ai);
|
||||
return -1;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: groupaccess.c,v 1.12 2006/08/03 03:34:42 deraadt Exp $ */
|
||||
/* $OpenBSD: groupaccess.c,v 1.13 2008/07/04 03:44:59 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001 Kevin Steves. All rights reserved.
|
||||
*
|
||||
@ -31,6 +31,7 @@
|
||||
#include <grp.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "groupaccess.h"
|
||||
@ -87,6 +88,30 @@ ga_match(char * const *groups, int n)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 1 if one of user's groups matches group_pattern list.
|
||||
* Return 0 on negated or no match.
|
||||
*/
|
||||
int
|
||||
ga_match_pattern_list(const char *group_pattern)
|
||||
{
|
||||
int i, found = 0;
|
||||
size_t len = strlen(group_pattern);
|
||||
|
||||
for (i = 0; i < ngroups; i++) {
|
||||
switch (match_pattern_list(groups_byname[i],
|
||||
group_pattern, len, 0)) {
|
||||
case -1:
|
||||
return 0; /* Negated match wins */
|
||||
case 0:
|
||||
continue;
|
||||
case 1:
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free memory allocated for group access list.
|
||||
*/
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: groupaccess.h,v 1.7 2006/08/03 03:34:42 deraadt Exp $ */
|
||||
/* $OpenBSD: groupaccess.h,v 1.8 2008/07/04 03:44:59 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Kevin Steves. All rights reserved.
|
||||
@ -29,6 +29,7 @@
|
||||
|
||||
int ga_init(const char *, gid_t);
|
||||
int ga_match(char * const *, int);
|
||||
int ga_match_pattern_list(const char *);
|
||||
void ga_free(void);
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: gss-serv.c,v 1.21 2007/06/12 08:20:00 djm Exp $ */
|
||||
/* $OpenBSD: gss-serv.c,v 1.22 2008/05/08 12:02:23 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
|
||||
@ -35,6 +35,7 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "openbsd-compat/sys-queue.h"
|
||||
#include "xmalloc.h"
|
||||
#include "buffer.h"
|
||||
#include "key.h"
|
||||
|
@ -149,6 +149,8 @@
|
||||
# include <sys/syslog.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* On HP-UX 11.11, shadow.h and prot.h provide conflicting declarations
|
||||
* of getspnam when _INCLUDE__STDC__ is defined, so we unset it here.
|
||||
|
116
key.c
116
key.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: key.c,v 1.69 2007/07/12 05:48:05 ray Exp $ */
|
||||
/* $OpenBSD: key.c,v 1.78 2008/07/07 23:32:51 stevesk Exp $ */
|
||||
/*
|
||||
* read_bignum():
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -11,6 +11,7 @@
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -35,6 +36,7 @@
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <openssl/evp.h>
|
||||
@ -172,6 +174,7 @@ key_equal(const Key *a, const Key *b)
|
||||
default:
|
||||
fatal("key_equal: bad key type %d", a->type);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
u_char*
|
||||
@ -295,6 +298,114 @@ key_fingerprint_bubblebabble(u_char *dgst_raw, u_int dgst_raw_len)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw an ASCII-Art representing the fingerprint so human brain can
|
||||
* profit from its built-in pattern recognition ability.
|
||||
* This technique is called "random art" and can be found in some
|
||||
* scientific publications like this original paper:
|
||||
*
|
||||
* "Hash Visualization: a New Technique to improve Real-World Security",
|
||||
* Perrig A. and Song D., 1999, International Workshop on Cryptographic
|
||||
* Techniques and E-Commerce (CrypTEC '99)
|
||||
* sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
|
||||
*
|
||||
* The subject came up in a talk by Dan Kaminsky, too.
|
||||
*
|
||||
* If you see the picture is different, the key is different.
|
||||
* If the picture looks the same, you still know nothing.
|
||||
*
|
||||
* The algorithm used here is a worm crawling over a discrete plane,
|
||||
* leaving a trace (augmenting the field) everywhere it goes.
|
||||
* Movement is taken from dgst_raw 2bit-wise. Bumping into walls
|
||||
* makes the respective movement vector be ignored for this turn.
|
||||
* Graphs are not unambiguous, because circles in graphs can be
|
||||
* walked in either direction.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Field sizes for the random art. Have to be odd, so the starting point
|
||||
* can be in the exact middle of the picture, and FLDBASE should be >=8 .
|
||||
* Else pictures would be too dense, and drawing the frame would
|
||||
* fail, too, because the key type would not fit in anymore.
|
||||
*/
|
||||
#define FLDBASE 8
|
||||
#define FLDSIZE_Y (FLDBASE + 1)
|
||||
#define FLDSIZE_X (FLDBASE * 2 + 1)
|
||||
static char *
|
||||
key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k)
|
||||
{
|
||||
/*
|
||||
* Chars to be used after each other every time the worm
|
||||
* intersects with itself. Matter of taste.
|
||||
*/
|
||||
char *augmentation_string = " .o+=*BOX@%&#/^SE";
|
||||
char *retval, *p;
|
||||
u_char field[FLDSIZE_X][FLDSIZE_Y];
|
||||
u_int i, b;
|
||||
int x, y;
|
||||
size_t len = strlen(augmentation_string) - 1;
|
||||
|
||||
retval = xcalloc(1, (FLDSIZE_X + 3) * (FLDSIZE_Y + 2));
|
||||
|
||||
/* initialize field */
|
||||
memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
|
||||
x = FLDSIZE_X / 2;
|
||||
y = FLDSIZE_Y / 2;
|
||||
|
||||
/* process raw key */
|
||||
for (i = 0; i < dgst_raw_len; i++) {
|
||||
int input;
|
||||
/* each byte conveys four 2-bit move commands */
|
||||
input = dgst_raw[i];
|
||||
for (b = 0; b < 4; b++) {
|
||||
/* evaluate 2 bit, rest is shifted later */
|
||||
x += (input & 0x1) ? 1 : -1;
|
||||
y += (input & 0x2) ? 1 : -1;
|
||||
|
||||
/* assure we are still in bounds */
|
||||
x = MAX(x, 0);
|
||||
y = MAX(y, 0);
|
||||
x = MIN(x, FLDSIZE_X - 1);
|
||||
y = MIN(y, FLDSIZE_Y - 1);
|
||||
|
||||
/* augment the field */
|
||||
field[x][y]++;
|
||||
input = input >> 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* mark starting point and end point*/
|
||||
field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
|
||||
field[x][y] = len;
|
||||
|
||||
/* fill in retval */
|
||||
snprintf(retval, FLDSIZE_X, "+--[%4s %4u]", key_type(k), key_size(k));
|
||||
p = strchr(retval, '\0');
|
||||
|
||||
/* output upper border */
|
||||
for (i = p - retval - 1; i < FLDSIZE_X; i++)
|
||||
*p++ = '-';
|
||||
*p++ = '+';
|
||||
*p++ = '\n';
|
||||
|
||||
/* output content */
|
||||
for (y = 0; y < FLDSIZE_Y; y++) {
|
||||
*p++ = '|';
|
||||
for (x = 0; x < FLDSIZE_X; x++)
|
||||
*p++ = augmentation_string[MIN(field[x][y], len)];
|
||||
*p++ = '|';
|
||||
*p++ = '\n';
|
||||
}
|
||||
|
||||
/* output lower border */
|
||||
*p++ = '+';
|
||||
for (i = 0; i < FLDSIZE_X; i++)
|
||||
*p++ = '-';
|
||||
*p++ = '+';
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
char *
|
||||
key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
|
||||
{
|
||||
@ -312,6 +423,9 @@ key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
|
||||
case SSH_FP_BUBBLEBABBLE:
|
||||
retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
|
||||
break;
|
||||
case SSH_FP_RANDOMART:
|
||||
retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len, k);
|
||||
break;
|
||||
default:
|
||||
fatal("key_fingerprint_ex: bad digest representation %d",
|
||||
dgst_rep);
|
||||
|
5
key.h
5
key.h
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: key.h,v 1.26 2006/08/03 03:34:42 deraadt Exp $ */
|
||||
/* $OpenBSD: key.h,v 1.27 2008/06/11 21:01:35 grunk Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
@ -42,7 +42,8 @@ enum fp_type {
|
||||
};
|
||||
enum fp_rep {
|
||||
SSH_FP_HEX,
|
||||
SSH_FP_BUBBLEBABBLE
|
||||
SSH_FP_BUBBLEBABBLE,
|
||||
SSH_FP_RANDOMART
|
||||
};
|
||||
|
||||
/* key is stored in external hardware */
|
||||
|
24
log.c
24
log.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: log.c,v 1.40 2007/05/17 07:50:31 djm Exp $ */
|
||||
/* $OpenBSD: log.c,v 1.41 2008/06/10 04:50:25 dtucker Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -114,6 +114,17 @@ log_facility_number(char *name)
|
||||
return SYSLOG_FACILITY_NOT_SET;
|
||||
}
|
||||
|
||||
const char *
|
||||
log_facility_name(SyslogFacility facility)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
for (i = 0; log_facilities[i].name; i++)
|
||||
if (log_facilities[i].val == facility)
|
||||
return log_facilities[i].name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LogLevel
|
||||
log_level_number(char *name)
|
||||
{
|
||||
@ -126,6 +137,17 @@ log_level_number(char *name)
|
||||
return SYSLOG_LEVEL_NOT_SET;
|
||||
}
|
||||
|
||||
const char *
|
||||
log_level_name(LogLevel level)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
for (i = 0; log_levels[i].name != NULL; i++)
|
||||
if (log_levels[i].val == level)
|
||||
return log_levels[i].name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Error messages that should be logged. */
|
||||
|
||||
void
|
||||
|
14
log.h
14
log.h
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: log.h,v 1.15 2006/08/18 09:13:25 deraadt Exp $ */
|
||||
/* $OpenBSD: log.h,v 1.17 2008/06/13 00:12:02 dtucker Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -49,11 +49,15 @@ typedef enum {
|
||||
void log_init(char *, LogLevel, SyslogFacility, int);
|
||||
|
||||
SyslogFacility log_facility_number(char *);
|
||||
LogLevel log_level_number(char *);
|
||||
const char * log_facility_name(SyslogFacility);
|
||||
LogLevel log_level_number(char *);
|
||||
const char * log_level_name(LogLevel);
|
||||
|
||||
void fatal(const char *, ...) __dead __attribute__((format(printf, 1, 2)));
|
||||
void fatal(const char *, ...) __attribute__((noreturn))
|
||||
__attribute__((format(printf, 1, 2)));
|
||||
void error(const char *, ...) __attribute__((format(printf, 1, 2)));
|
||||
void sigdie(const char *, ...) __attribute__((format(printf, 1, 2)));
|
||||
void sigdie(const char *, ...) __attribute__((noreturn))
|
||||
__attribute__((format(printf, 1, 2)));
|
||||
void logit(const char *, ...) __attribute__((format(printf, 1, 2)));
|
||||
void verbose(const char *, ...) __attribute__((format(printf, 1, 2)));
|
||||
void debug(const char *, ...) __attribute__((format(printf, 1, 2)));
|
||||
@ -61,5 +65,5 @@ void debug2(const char *, ...) __attribute__((format(printf, 1, 2)));
|
||||
void debug3(const char *, ...) __attribute__((format(printf, 1, 2)));
|
||||
|
||||
void do_log(LogLevel, const char *, va_list);
|
||||
void cleanup_exit(int) __dead;
|
||||
void cleanup_exit(int) __attribute__((noreturn));
|
||||
#endif
|
||||
|
4
mac.c
4
mac.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: mac.c,v 1.14 2007/06/07 19:37:34 pvalchev Exp $ */
|
||||
/* $OpenBSD: mac.c,v 1.15 2008/06/13 00:51:47 dtucker Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -128,7 +128,7 @@ mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen)
|
||||
|
||||
if (mac->mac_len > sizeof(m))
|
||||
fatal("mac_compute: mac too long %u %lu",
|
||||
mac->mac_len, sizeof(m));
|
||||
mac->mac_len, (u_long)sizeof(m));
|
||||
|
||||
switch (mac->type) {
|
||||
case SSH_EVP:
|
||||
|
12
match.c
12
match.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: match.c,v 1.26 2006/08/03 03:34:42 deraadt Exp $ */
|
||||
/* $OpenBSD: match.c,v 1.27 2008/06/10 23:06:19 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -183,7 +183,8 @@ match_hostname(const char *host, const char *pattern, u_int len)
|
||||
|
||||
/*
|
||||
* returns 0 if we get a negative match for the hostname or the ip
|
||||
* or if we get no match at all. returns 1 otherwise.
|
||||
* or if we get no match at all. returns -1 on error, or 1 on
|
||||
* successful match.
|
||||
*/
|
||||
int
|
||||
match_host_and_ip(const char *host, const char *ipaddr,
|
||||
@ -191,9 +192,12 @@ match_host_and_ip(const char *host, const char *ipaddr,
|
||||
{
|
||||
int mhost, mip;
|
||||
|
||||
/* negative ipaddr match */
|
||||
if ((mip = match_hostname(ipaddr, patterns, strlen(patterns))) == -1)
|
||||
/* error in ipaddr match */
|
||||
if ((mip = addr_match_list(ipaddr, patterns)) == -2)
|
||||
return -1;
|
||||
else if (mip == -1) /* negative ip address match */
|
||||
return 0;
|
||||
|
||||
/* negative hostname match */
|
||||
if ((mhost = match_hostname(host, patterns, strlen(patterns))) == -1)
|
||||
return 0;
|
||||
|
5
match.h
5
match.h
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: match.h,v 1.13 2006/03/25 22:22:43 djm Exp $ */
|
||||
/* $OpenBSD: match.h,v 1.14 2008/06/10 03:57:27 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -21,4 +21,7 @@ int match_host_and_ip(const char *, const char *, const char *);
|
||||
int match_user(const char *, const char *, const char *, const char *);
|
||||
char *match_list(const char *, const char *, u_int *);
|
||||
|
||||
/* addrmatch.c */
|
||||
int addr_match_list(const char *, const char *);
|
||||
|
||||
#endif
|
||||
|
24
misc.c
24
misc.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: misc.c,v 1.67 2008/01/01 08:47:04 dtucker Exp $ */
|
||||
/* $OpenBSD: misc.c,v 1.69 2008/06/13 01:38:23 dtucker Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2005,2006 Damien Miller. All rights reserved.
|
||||
@ -534,7 +534,7 @@ tilde_expand_filename(const char *filename, uid_t uid)
|
||||
if ((pw = getpwnam(user)) == NULL)
|
||||
fatal("tilde_expand_filename: No such user %s", user);
|
||||
} else if ((pw = getpwuid(uid)) == NULL) /* ~/path */
|
||||
fatal("tilde_expand_filename: No such uid %d", uid);
|
||||
fatal("tilde_expand_filename: No such uid %ld", (long)uid);
|
||||
|
||||
if (strlcpy(ret, pw->pw_dir, sizeof(ret)) >= sizeof(ret))
|
||||
fatal("tilde_expand_filename: Path too long");
|
||||
@ -832,3 +832,23 @@ put_u16(void *vp, u_int16_t v)
|
||||
p[0] = (u_char)(v >> 8) & 0xff;
|
||||
p[1] = (u_char)v & 0xff;
|
||||
}
|
||||
|
||||
void
|
||||
ms_subtract_diff(struct timeval *start, int *ms)
|
||||
{
|
||||
struct timeval diff, finish;
|
||||
|
||||
gettimeofday(&finish, NULL);
|
||||
timersub(&finish, start, &diff);
|
||||
*ms -= (diff.tv_sec * 1000) + (diff.tv_usec / 1000);
|
||||
}
|
||||
|
||||
void
|
||||
ms_to_timeval(struct timeval *tv, int ms)
|
||||
{
|
||||
if (ms < 0)
|
||||
ms = 0;
|
||||
tv->tv_sec = ms / 1000;
|
||||
tv->tv_usec = (ms % 1000) * 1000;
|
||||
}
|
||||
|
||||
|
4
misc.h
4
misc.h
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: misc.h,v 1.37 2007/12/27 14:22:08 dtucker Exp $ */
|
||||
/* $OpenBSD: misc.h,v 1.38 2008/06/12 20:38:28 dtucker Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -33,6 +33,8 @@ char *tilde_expand_filename(const char *, uid_t);
|
||||
char *percent_expand(const char *, ...) __attribute__((__sentinel__));
|
||||
char *tohex(const void *, size_t);
|
||||
void sanitise_stdfd(void);
|
||||
void ms_subtract_diff(struct timeval *, int *);
|
||||
void ms_to_timeval(struct timeval *, int);
|
||||
|
||||
struct passwd *pwcopy(struct passwd *);
|
||||
const char *ssh_gai_strerror(int);
|
||||
|
72
moduli.0
Normal file
72
moduli.0
Normal file
@ -0,0 +1,72 @@
|
||||
MODULI(5) OpenBSD Programmer's Manual MODULI(5)
|
||||
|
||||
NAME
|
||||
moduli - Diffie Hellman moduli
|
||||
|
||||
DESCRIPTION
|
||||
The /etc/moduli file contains prime numbers and generators for use by
|
||||
sshd(8) in the Diffie-Hellman Group Exchange key exchange method.
|
||||
|
||||
New moduli may be generated with ssh-keygen(1) using a two-step process.
|
||||
An initial candidate generation pass, using ssh-keygen -G, calculates
|
||||
numbers that are likely to be useful. A second primality testing pass,
|
||||
using ssh-keygen -T provides a high degree of assurance that the numbers
|
||||
are prime and are safe for use in Diffie Hellman operations by sshd(8).
|
||||
This moduli format is used as the output from each pass.
|
||||
|
||||
The file consists of newline-separated records, one per modulus, contain-
|
||||
ing seven space separated fields. These fields are as follows:
|
||||
|
||||
timestamp The time that the modulus was last processed as YYYYM-
|
||||
MDDHHMMSS.
|
||||
|
||||
type Decimal number specifying the internal structure of
|
||||
the prime modulus. Supported types are:
|
||||
|
||||
0 Unknown, not tested
|
||||
2 "Safe" prime; (p-1)/2 is also prime.
|
||||
4 Sophie Germain; (p+1)*2 is also prime.
|
||||
|
||||
Moduli candidates initially produced by ssh-keygen(1)
|
||||
are Sophie Germain primes (type 4). Futher primality
|
||||
testing with ssh-keygen(1) produces safe prime moduli
|
||||
(type 2) that are ready for use in sshd(8). Other
|
||||
types are not used by OpenSSH.
|
||||
|
||||
tests Decimal number indicating the type of primality tests
|
||||
that the number has been subjected to represented as a
|
||||
bitmask of the following values:
|
||||
|
||||
0x00 Not tested
|
||||
0x01 Composite number - not prime.
|
||||
0x02 Sieve of Eratosthenes
|
||||
0x04 Probabalistic Miller-Rabin primality tests.
|
||||
|
||||
The ssh-keygen(1) moduli candidate generation uses the
|
||||
Sieve of Eratosthenes (flag 0x02). Subsequent
|
||||
ssh-keygen(1) primality tests are Miller-Rabin tests
|
||||
(flag 0x04).
|
||||
|
||||
trials Decimal number indicating of primaility trials that
|
||||
have been performed on the modulus.
|
||||
|
||||
size Decimal number indicating the size of the prime in
|
||||
bits.
|
||||
|
||||
generator The recommended generator for use with this modulus
|
||||
(hexadecimal).
|
||||
|
||||
modulus The modulus itself in hexadecimal.
|
||||
|
||||
When performing Diffie Hellman Group Exchange, sshd(8) first estimates
|
||||
the size of the modulus required to produce enough Diffie Hellman output
|
||||
to sufficiently key the selected symmetric cipher. sshd(8) then randomly
|
||||
selects a modulus from /etc/moduli that best meets the size requirement.
|
||||
|
||||
SEE ALSO
|
||||
ssh-keygen(1), sshd(8),
|
||||
|
||||
Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer
|
||||
Protocol, RFC 4419, 2006.
|
||||
|
||||
OpenBSD 4.4 June 26, 2008 2
|
124
moduli.5
Normal file
124
moduli.5
Normal file
@ -0,0 +1,124 @@
|
||||
.\" $OpenBSD: moduli.5,v 1.12 2008/06/26 05:57:54 djm Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2008 Damien Miller <djm@mindrot.org>
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and distribute this software for any
|
||||
.\" purpose with or without fee is hereby granted, provided that the above
|
||||
.\" copyright notice and this permission notice appear in all copies.
|
||||
.\"
|
||||
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.Dd $Mdocdate: June 26 2008 $
|
||||
.Dt MODULI 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm moduli
|
||||
.Nd Diffie Hellman moduli
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Pa /etc/moduli
|
||||
file contains prime numbers and generators for use by
|
||||
.Xr sshd 8
|
||||
in the Diffie-Hellman Group Exchange key exchange method.
|
||||
.Pp
|
||||
New moduli may be generated with
|
||||
.Xr ssh-keygen 1
|
||||
using a two-step process.
|
||||
An initial
|
||||
.Em candidate generation
|
||||
pass, using
|
||||
.Ic ssh-keygen -G ,
|
||||
calculates numbers that are likely to be useful.
|
||||
A second
|
||||
.Em primality testing
|
||||
pass, using
|
||||
.Ic ssh-keygen -T
|
||||
provides a high degree of assurance that the numbers are prime and are
|
||||
safe for use in Diffie Hellman operations by
|
||||
.Xr sshd 8 .
|
||||
This
|
||||
.Nm
|
||||
format is used as the output from each pass.
|
||||
.Pp
|
||||
The file consists of newline-separated records, one per modulus,
|
||||
containing seven space separated fields.
|
||||
These fields are as follows:
|
||||
.Pp
|
||||
.Bl -tag -width Description -offset indent
|
||||
.It timestamp
|
||||
The time that the modulus was last processed as YYYYMMDDHHMMSS.
|
||||
.It type
|
||||
Decimal number specifying the internal structure of the prime modulus.
|
||||
Supported types are:
|
||||
.Pp
|
||||
.Bl -tag -width 0x00 -compact
|
||||
.It 0
|
||||
Unknown, not tested
|
||||
.It 2
|
||||
"Safe" prime; (p-1)/2 is also prime.
|
||||
.It 4
|
||||
Sophie Germain; (p+1)*2 is also prime.
|
||||
.El
|
||||
.Pp
|
||||
Moduli candidates initially produced by
|
||||
.Xr ssh-keygen 1
|
||||
are Sophie Germain primes (type 4).
|
||||
Futher primality testing with
|
||||
.Xr ssh-keygen 1
|
||||
produces safe prime moduli (type 2) that are ready for use in
|
||||
.Xr sshd 8 .
|
||||
Other types are not used by OpenSSH.
|
||||
.It tests
|
||||
Decimal number indicating the type of primality tests that the number
|
||||
has been subjected to represented as a bitmask of the following values:
|
||||
.Pp
|
||||
.Bl -tag -width 0x00 -compact
|
||||
.It 0x00
|
||||
Not tested
|
||||
.It 0x01
|
||||
Composite number - not prime.
|
||||
.It 0x02
|
||||
Sieve of Eratosthenes
|
||||
.It 0x04
|
||||
Probabalistic Miller-Rabin primality tests.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Xr ssh-keygen 1
|
||||
moduli candidate generation uses the Sieve of Eratosthenes (flag 0x02).
|
||||
Subsequent
|
||||
.Xr ssh-keygen 1
|
||||
primality tests are Miller-Rabin tests (flag 0x04).
|
||||
.It trials
|
||||
Decimal number indicating of primaility trials that have been performed
|
||||
on the modulus.
|
||||
.It size
|
||||
Decimal number indicating the size of the prime in bits.
|
||||
.It generator
|
||||
The recommended generator for use with this modulus (hexadecimal).
|
||||
.It modulus
|
||||
The modulus itself in hexadecimal.
|
||||
.El
|
||||
.Pp
|
||||
When performing Diffie Hellman Group Exchange,
|
||||
.Xr sshd 8
|
||||
first estimates the size of the modulus required to produce enough
|
||||
Diffie Hellman output to sufficiently key the selected symmetric cipher.
|
||||
.Xr sshd 8
|
||||
then randomly selects a modulus from
|
||||
.Fa /etc/moduli
|
||||
that best meets the size requirement.
|
||||
.Pp
|
||||
.Sh SEE ALSO
|
||||
.Xr ssh-keygen 1 ,
|
||||
.Xr sshd 8 ,
|
||||
.Rs
|
||||
.%R RFC 4419
|
||||
.%T "Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol"
|
||||
.%D 2006
|
||||
.Re
|
49
moduli.c
49
moduli.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: moduli.c,v 1.20 2007/02/24 03:30:11 ray Exp $ */
|
||||
/* $OpenBSD: moduli.c,v 1.21 2008/06/26 09:19:40 djm Exp $ */
|
||||
/*
|
||||
* Copyright 1994 Phil Karn <karn@qualcomm.com>
|
||||
* Copyright 1996-1998, 2003 William Allen Simpson <wsimpson@greendragon.com>
|
||||
@ -42,6 +42,7 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dh.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -50,6 +51,7 @@
|
||||
#include <time.h>
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "dh.h"
|
||||
#include "log.h"
|
||||
|
||||
/*
|
||||
@ -59,27 +61,6 @@
|
||||
/* need line long enough for largest moduli plus headers */
|
||||
#define QLINESIZE (100+8192)
|
||||
|
||||
/* Type: decimal.
|
||||
* Specifies the internal structure of the prime modulus.
|
||||
*/
|
||||
#define QTYPE_UNKNOWN (0)
|
||||
#define QTYPE_UNSTRUCTURED (1)
|
||||
#define QTYPE_SAFE (2)
|
||||
#define QTYPE_SCHNORR (3)
|
||||
#define QTYPE_SOPHIE_GERMAIN (4)
|
||||
#define QTYPE_STRONG (5)
|
||||
|
||||
/* Tests: decimal (bit field).
|
||||
* Specifies the methods used in checking for primality.
|
||||
* Usually, more than one test is used.
|
||||
*/
|
||||
#define QTEST_UNTESTED (0x00)
|
||||
#define QTEST_COMPOSITE (0x01)
|
||||
#define QTEST_SIEVE (0x02)
|
||||
#define QTEST_MILLER_RABIN (0x04)
|
||||
#define QTEST_JACOBI (0x08)
|
||||
#define QTEST_ELLIPTIC (0x10)
|
||||
|
||||
/*
|
||||
* Size: decimal.
|
||||
* Specifies the number of the most significant bit (0 to M).
|
||||
@ -434,8 +415,9 @@ gen_candidates(FILE *out, u_int32_t memory, u_int32_t power, BIGNUM *start)
|
||||
fatal("BN_set_word failed");
|
||||
if (BN_add(q, q, largebase) == 0)
|
||||
fatal("BN_add failed");
|
||||
if (qfileout(out, QTYPE_SOPHIE_GERMAIN, QTEST_SIEVE,
|
||||
largetries, (power - 1) /* MSB */, (0), q) == -1) {
|
||||
if (qfileout(out, MODULI_TYPE_SOPHIE_GERMAIN,
|
||||
MODULI_TESTS_SIEVE, largetries,
|
||||
(power - 1) /* MSB */, (0), q) == -1) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
@ -507,7 +489,7 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted)
|
||||
/* tests */
|
||||
in_tests = strtoul(cp, &cp, 10);
|
||||
|
||||
if (in_tests & QTEST_COMPOSITE) {
|
||||
if (in_tests & MODULI_TESTS_COMPOSITE) {
|
||||
debug2("%10u: known composite", count_in);
|
||||
continue;
|
||||
}
|
||||
@ -526,7 +508,7 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted)
|
||||
|
||||
/* modulus (hex) */
|
||||
switch (in_type) {
|
||||
case QTYPE_SOPHIE_GERMAIN:
|
||||
case MODULI_TYPE_SOPHIE_GERMAIN:
|
||||
debug2("%10u: (%u) Sophie-Germain", count_in, in_type);
|
||||
a = q;
|
||||
if (BN_hex2bn(&a, cp) == 0)
|
||||
@ -539,11 +521,11 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted)
|
||||
in_size += 1;
|
||||
generator_known = 0;
|
||||
break;
|
||||
case QTYPE_UNSTRUCTURED:
|
||||
case QTYPE_SAFE:
|
||||
case QTYPE_SCHNORR:
|
||||
case QTYPE_STRONG:
|
||||
case QTYPE_UNKNOWN:
|
||||
case MODULI_TYPE_UNSTRUCTURED:
|
||||
case MODULI_TYPE_SAFE:
|
||||
case MODULI_TYPE_SCHNORR:
|
||||
case MODULI_TYPE_STRONG:
|
||||
case MODULI_TYPE_UNKNOWN:
|
||||
debug2("%10u: (%u)", count_in, in_type);
|
||||
a = p;
|
||||
if (BN_hex2bn(&a, cp) == 0)
|
||||
@ -570,7 +552,7 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in_tests & QTEST_MILLER_RABIN)
|
||||
if (in_tests & MODULI_TESTS_MILLER_RABIN)
|
||||
in_tries += trials;
|
||||
else
|
||||
in_tries = trials;
|
||||
@ -644,7 +626,8 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted)
|
||||
}
|
||||
debug("%10u: q is almost certainly prime", count_in);
|
||||
|
||||
if (qfileout(out, QTYPE_SAFE, (in_tests | QTEST_MILLER_RABIN),
|
||||
if (qfileout(out, MODULI_TYPE_SAFE,
|
||||
in_tests | MODULI_TESTS_MILLER_RABIN,
|
||||
in_tries, in_size, generator_known, p)) {
|
||||
res = -1;
|
||||
break;
|
||||
|
19
monitor.c
19
monitor.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: monitor.c,v 1.94 2007/10/29 04:08:08 dtucker Exp $ */
|
||||
/* $OpenBSD: monitor.c,v 1.99 2008/07/10 18:08:11 markus Exp $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright 2002 Markus Friedl <markus@openbsd.org>
|
||||
@ -51,6 +51,7 @@
|
||||
|
||||
#include <openssl/dh.h>
|
||||
|
||||
#include "openbsd-compat/sys-queue.h"
|
||||
#include "xmalloc.h"
|
||||
#include "ssh.h"
|
||||
#include "key.h"
|
||||
@ -1014,6 +1015,8 @@ mm_answer_keyallowed(int sock, Buffer *m)
|
||||
allowed = options.pubkey_authentication &&
|
||||
user_key_allowed(authctxt->pw, key);
|
||||
auth_method = "publickey";
|
||||
if (options.pubkey_authentication && allowed != 1)
|
||||
auth_clear_options();
|
||||
break;
|
||||
case MM_HOSTKEY:
|
||||
allowed = options.hostbased_authentication &&
|
||||
@ -1026,6 +1029,8 @@ mm_answer_keyallowed(int sock, Buffer *m)
|
||||
allowed = options.rhosts_rsa_authentication &&
|
||||
auth_rhosts_rsa_key_allowed(authctxt->pw,
|
||||
cuser, chost, key);
|
||||
if (options.rhosts_rsa_authentication && allowed != 1)
|
||||
auth_clear_options();
|
||||
auth_method = "rsa";
|
||||
break;
|
||||
default:
|
||||
@ -1055,7 +1060,7 @@ mm_answer_keyallowed(int sock, Buffer *m)
|
||||
}
|
||||
|
||||
debug3("%s: key %p is %s",
|
||||
__func__, key, allowed ? "allowed" : "disallowed");
|
||||
__func__, key, allowed ? "allowed" : "not allowed");
|
||||
|
||||
buffer_clear(m);
|
||||
buffer_put_int(m, allowed);
|
||||
@ -1272,7 +1277,7 @@ mm_session_close(Session *s)
|
||||
debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd);
|
||||
session_pty_cleanup2(s);
|
||||
}
|
||||
s->used = 0;
|
||||
session_unused(s->self);
|
||||
}
|
||||
|
||||
int
|
||||
@ -1700,7 +1705,7 @@ mm_get_keystate(struct monitor *pmonitor)
|
||||
u_char *blob, *p;
|
||||
u_int bloblen, plen;
|
||||
u_int32_t seqnr, packets;
|
||||
u_int64_t blocks;
|
||||
u_int64_t blocks, bytes;
|
||||
|
||||
debug3("%s: Waiting for new keys", __func__);
|
||||
|
||||
@ -1733,11 +1738,13 @@ mm_get_keystate(struct monitor *pmonitor)
|
||||
seqnr = buffer_get_int(&m);
|
||||
blocks = buffer_get_int64(&m);
|
||||
packets = buffer_get_int(&m);
|
||||
packet_set_state(MODE_OUT, seqnr, blocks, packets);
|
||||
bytes = buffer_get_int64(&m);
|
||||
packet_set_state(MODE_OUT, seqnr, blocks, packets, bytes);
|
||||
seqnr = buffer_get_int(&m);
|
||||
blocks = buffer_get_int64(&m);
|
||||
packets = buffer_get_int(&m);
|
||||
packet_set_state(MODE_IN, seqnr, blocks, packets);
|
||||
bytes = buffer_get_int64(&m);
|
||||
packet_set_state(MODE_IN, seqnr, blocks, packets, bytes);
|
||||
|
||||
skip:
|
||||
/* Get the key context */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: monitor_mm.h,v 1.4 2006/08/03 03:34:42 deraadt Exp $ */
|
||||
/* $OpenBSD: monitor_mm.h,v 1.5 2008/04/29 11:20:31 otto Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
@ -41,9 +41,6 @@ struct mm_master {
|
||||
size_t size;
|
||||
|
||||
struct mm_master *mmalloc; /* Used to completely share */
|
||||
|
||||
int write; /* used to writing to other party */
|
||||
int read; /* used for reading from other party */
|
||||
};
|
||||
|
||||
RB_PROTOTYPE(mmtree, mm_share, next, mm_compare)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: monitor_wrap.c,v 1.60 2007/10/29 04:08:08 dtucker Exp $ */
|
||||
/* $OpenBSD: monitor_wrap.c,v 1.63 2008/07/10 18:08:11 markus Exp $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright 2002 Markus Friedl <markus@openbsd.org>
|
||||
@ -41,6 +41,7 @@
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dh.h>
|
||||
|
||||
#include "openbsd-compat/sys-queue.h"
|
||||
#include "xmalloc.h"
|
||||
#include "ssh.h"
|
||||
#include "dh.h"
|
||||
@ -572,7 +573,7 @@ mm_send_keystate(struct monitor *monitor)
|
||||
u_char *blob, *p;
|
||||
u_int bloblen, plen;
|
||||
u_int32_t seqnr, packets;
|
||||
u_int64_t blocks;
|
||||
u_int64_t blocks, bytes;
|
||||
|
||||
buffer_init(&m);
|
||||
|
||||
@ -621,14 +622,16 @@ mm_send_keystate(struct monitor *monitor)
|
||||
buffer_put_string(&m, blob, bloblen);
|
||||
xfree(blob);
|
||||
|
||||
packet_get_state(MODE_OUT, &seqnr, &blocks, &packets);
|
||||
packet_get_state(MODE_OUT, &seqnr, &blocks, &packets, &bytes);
|
||||
buffer_put_int(&m, seqnr);
|
||||
buffer_put_int64(&m, blocks);
|
||||
buffer_put_int(&m, packets);
|
||||
packet_get_state(MODE_IN, &seqnr, &blocks, &packets);
|
||||
buffer_put_int64(&m, bytes);
|
||||
packet_get_state(MODE_IN, &seqnr, &blocks, &packets, &bytes);
|
||||
buffer_put_int(&m, seqnr);
|
||||
buffer_put_int64(&m, blocks);
|
||||
buffer_put_int(&m, packets);
|
||||
buffer_put_int64(&m, bytes);
|
||||
|
||||
debug3("%s: New keys have been sent", __func__);
|
||||
skip:
|
||||
@ -665,7 +668,20 @@ mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
|
||||
{
|
||||
Buffer m;
|
||||
char *p, *msg;
|
||||
int success = 0;
|
||||
int success = 0, tmp1 = -1, tmp2 = -1;
|
||||
|
||||
/* Kludge: ensure there are fds free to receive the pty/tty */
|
||||
if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 ||
|
||||
(tmp2 = dup(pmonitor->m_recvfd)) == -1) {
|
||||
error("%s: cannot allocate fds for pty", __func__);
|
||||
if (tmp1 > 0)
|
||||
close(tmp1);
|
||||
if (tmp2 > 0)
|
||||
close(tmp2);
|
||||
return 0;
|
||||
}
|
||||
close(tmp1);
|
||||
close(tmp2);
|
||||
|
||||
buffer_init(&m);
|
||||
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m);
|
||||
@ -710,8 +726,9 @@ mm_session_pty_cleanup2(Session *s)
|
||||
buffer_free(&m);
|
||||
|
||||
/* closed dup'ed master */
|
||||
if (close(s->ptymaster) < 0)
|
||||
error("close(s->ptymaster): %s", strerror(errno));
|
||||
if (s->ptymaster != -1 && close(s->ptymaster) < 0)
|
||||
error("close(s->ptymaster/%d): %s",
|
||||
s->ptymaster, strerror(errno));
|
||||
|
||||
/* unlink pty from session */
|
||||
s->ttyfd = -1;
|
||||
|
728
mux.c
Normal file
728
mux.c
Normal file
@ -0,0 +1,728 @@
|
||||
/* $OpenBSD: mux.c,v 1.7 2008/06/13 17:21:20 dtucker Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* ssh session multiplexing support */
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* 1. partial reads in muxserver_accept_control (maybe make channels
|
||||
* from accepted connections)
|
||||
* 2. Better signalling from master to slave, especially passing of
|
||||
* error messages
|
||||
* 3. Better fall-back from mux slave error to new connection.
|
||||
* 3. Add/delete forwardings via slave
|
||||
* 4. ExitOnForwardingFailure (after #3 obviously)
|
||||
* 5. Maybe extension mechanisms for multi-X11/multi-agent forwarding
|
||||
* 6. Document the mux mini-protocol somewhere.
|
||||
* 7. Support ~^Z in mux slaves.
|
||||
* 8. Inspect or control sessions in master.
|
||||
* 9. If we ever support the "signal" channel request, send signals on
|
||||
* sessions in master.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#ifdef HAVE_PATHS_H
|
||||
#include <paths.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UTIL_H
|
||||
# include <util.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBUTIL_H
|
||||
# include <libutil.h>
|
||||
#endif
|
||||
|
||||
#include "openbsd-compat/sys-queue.h"
|
||||
#include "xmalloc.h"
|
||||
#include "log.h"
|
||||
#include "ssh.h"
|
||||
#include "pathnames.h"
|
||||
#include "misc.h"
|
||||
#include "match.h"
|
||||
#include "buffer.h"
|
||||
#include "channels.h"
|
||||
#include "msg.h"
|
||||
#include "packet.h"
|
||||
#include "monitor_fdpass.h"
|
||||
#include "sshpty.h"
|
||||
#include "key.h"
|
||||
#include "readconf.h"
|
||||
#include "clientloop.h"
|
||||
|
||||
/* from ssh.c */
|
||||
extern int tty_flag;
|
||||
extern Options options;
|
||||
extern int stdin_null_flag;
|
||||
extern char *host;
|
||||
int subsystem_flag;
|
||||
extern Buffer command;
|
||||
|
||||
/* Context for session open confirmation callback */
|
||||
struct mux_session_confirm_ctx {
|
||||
int want_tty;
|
||||
int want_subsys;
|
||||
int want_x_fwd;
|
||||
int want_agent_fwd;
|
||||
Buffer cmd;
|
||||
char *term;
|
||||
struct termios tio;
|
||||
char **env;
|
||||
};
|
||||
|
||||
/* fd to control socket */
|
||||
int muxserver_sock = -1;
|
||||
|
||||
/* Multiplexing control command */
|
||||
u_int muxclient_command = 0;
|
||||
|
||||
/* Set when signalled. */
|
||||
static volatile sig_atomic_t muxclient_terminate = 0;
|
||||
|
||||
/* PID of multiplex server */
|
||||
static u_int muxserver_pid = 0;
|
||||
|
||||
|
||||
/* ** Multiplexing master support */
|
||||
|
||||
/* Prepare a mux master to listen on a Unix domain socket. */
|
||||
void
|
||||
muxserver_listen(void)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
mode_t old_umask;
|
||||
int addr_len;
|
||||
|
||||
if (options.control_path == NULL ||
|
||||
options.control_master == SSHCTL_MASTER_NO)
|
||||
return;
|
||||
|
||||
debug("setting up multiplex master socket");
|
||||
|
||||
memset(&addr, '\0', sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
addr_len = offsetof(struct sockaddr_un, sun_path) +
|
||||
strlen(options.control_path) + 1;
|
||||
|
||||
if (strlcpy(addr.sun_path, options.control_path,
|
||||
sizeof(addr.sun_path)) >= sizeof(addr.sun_path))
|
||||
fatal("ControlPath too long");
|
||||
|
||||
if ((muxserver_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
|
||||
fatal("%s socket(): %s", __func__, strerror(errno));
|
||||
|
||||
old_umask = umask(0177);
|
||||
if (bind(muxserver_sock, (struct sockaddr *)&addr, addr_len) == -1) {
|
||||
muxserver_sock = -1;
|
||||
if (errno == EINVAL || errno == EADDRINUSE) {
|
||||
error("ControlSocket %s already exists, "
|
||||
"disabling multiplexing", options.control_path);
|
||||
close(muxserver_sock);
|
||||
muxserver_sock = -1;
|
||||
xfree(options.control_path);
|
||||
options.control_path = NULL;
|
||||
options.control_master = SSHCTL_MASTER_NO;
|
||||
return;
|
||||
} else
|
||||
fatal("%s bind(): %s", __func__, strerror(errno));
|
||||
}
|
||||
umask(old_umask);
|
||||
|
||||
if (listen(muxserver_sock, 64) == -1)
|
||||
fatal("%s listen(): %s", __func__, strerror(errno));
|
||||
|
||||
set_nonblock(muxserver_sock);
|
||||
}
|
||||
|
||||
/* Callback on open confirmation in mux master for a mux client session. */
|
||||
static void
|
||||
mux_session_confirm(int id, void *arg)
|
||||
{
|
||||
struct mux_session_confirm_ctx *cctx = arg;
|
||||
const char *display;
|
||||
Channel *c;
|
||||
int i;
|
||||
|
||||
if (cctx == NULL)
|
||||
fatal("%s: cctx == NULL", __func__);
|
||||
if ((c = channel_lookup(id)) == NULL)
|
||||
fatal("%s: no channel for id %d", __func__, id);
|
||||
|
||||
display = getenv("DISPLAY");
|
||||
if (cctx->want_x_fwd && options.forward_x11 && display != NULL) {
|
||||
char *proto, *data;
|
||||
/* Get reasonable local authentication information. */
|
||||
client_x11_get_proto(display, options.xauth_location,
|
||||
options.forward_x11_trusted, &proto, &data);
|
||||
/* Request forwarding with authentication spoofing. */
|
||||
debug("Requesting X11 forwarding with authentication spoofing.");
|
||||
x11_request_forwarding_with_spoofing(id, display, proto, data);
|
||||
/* XXX wait for reply */
|
||||
}
|
||||
|
||||
if (cctx->want_agent_fwd && options.forward_agent) {
|
||||
debug("Requesting authentication agent forwarding.");
|
||||
channel_request_start(id, "auth-agent-req@openssh.com", 0);
|
||||
packet_send();
|
||||
}
|
||||
|
||||
client_session2_setup(id, cctx->want_tty, cctx->want_subsys,
|
||||
cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env);
|
||||
|
||||
c->open_confirm_ctx = NULL;
|
||||
buffer_free(&cctx->cmd);
|
||||
xfree(cctx->term);
|
||||
if (cctx->env != NULL) {
|
||||
for (i = 0; cctx->env[i] != NULL; i++)
|
||||
xfree(cctx->env[i]);
|
||||
xfree(cctx->env);
|
||||
}
|
||||
xfree(cctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Accept a connection on the mux master socket and process the
|
||||
* client's request. Returns flag indicating whether mux master should
|
||||
* begin graceful close.
|
||||
*/
|
||||
int
|
||||
muxserver_accept_control(void)
|
||||
{
|
||||
Buffer m;
|
||||
Channel *c;
|
||||
int client_fd, new_fd[3], ver, allowed, window, packetmax;
|
||||
socklen_t addrlen;
|
||||
struct sockaddr_storage addr;
|
||||
struct mux_session_confirm_ctx *cctx;
|
||||
char *cmd;
|
||||
u_int i, j, len, env_len, mux_command, flags, escape_char;
|
||||
uid_t euid;
|
||||
gid_t egid;
|
||||
int start_close = 0;
|
||||
|
||||
/*
|
||||
* Accept connection on control socket
|
||||
*/
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addrlen = sizeof(addr);
|
||||
if ((client_fd = accept(muxserver_sock,
|
||||
(struct sockaddr*)&addr, &addrlen)) == -1) {
|
||||
error("%s accept: %s", __func__, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (getpeereid(client_fd, &euid, &egid) < 0) {
|
||||
error("%s getpeereid failed: %s", __func__, strerror(errno));
|
||||
close(client_fd);
|
||||
return 0;
|
||||
}
|
||||
if ((euid != 0) && (getuid() != euid)) {
|
||||
error("control mode uid mismatch: peer euid %u != uid %u",
|
||||
(u_int) euid, (u_int) getuid());
|
||||
close(client_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* XXX handle asynchronously */
|
||||
unset_nonblock(client_fd);
|
||||
|
||||
/* Read command */
|
||||
buffer_init(&m);
|
||||
if (ssh_msg_recv(client_fd, &m) == -1) {
|
||||
error("%s: client msg_recv failed", __func__);
|
||||
close(client_fd);
|
||||
buffer_free(&m);
|
||||
return 0;
|
||||
}
|
||||
if ((ver = buffer_get_char(&m)) != SSHMUX_VER) {
|
||||
error("%s: wrong client version %d", __func__, ver);
|
||||
buffer_free(&m);
|
||||
close(client_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
allowed = 1;
|
||||
mux_command = buffer_get_int(&m);
|
||||
flags = buffer_get_int(&m);
|
||||
|
||||
buffer_clear(&m);
|
||||
|
||||
switch (mux_command) {
|
||||
case SSHMUX_COMMAND_OPEN:
|
||||
if (options.control_master == SSHCTL_MASTER_ASK ||
|
||||
options.control_master == SSHCTL_MASTER_AUTO_ASK)
|
||||
allowed = ask_permission("Allow shared connection "
|
||||
"to %s? ", host);
|
||||
/* continue below */
|
||||
break;
|
||||
case SSHMUX_COMMAND_TERMINATE:
|
||||
if (options.control_master == SSHCTL_MASTER_ASK ||
|
||||
options.control_master == SSHCTL_MASTER_AUTO_ASK)
|
||||
allowed = ask_permission("Terminate shared connection "
|
||||
"to %s? ", host);
|
||||
if (allowed)
|
||||
start_close = 1;
|
||||
/* FALLTHROUGH */
|
||||
case SSHMUX_COMMAND_ALIVE_CHECK:
|
||||
/* Reply for SSHMUX_COMMAND_TERMINATE and ALIVE_CHECK */
|
||||
buffer_clear(&m);
|
||||
buffer_put_int(&m, allowed);
|
||||
buffer_put_int(&m, getpid());
|
||||
if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
|
||||
error("%s: client msg_send failed", __func__);
|
||||
close(client_fd);
|
||||
buffer_free(&m);
|
||||
return start_close;
|
||||
}
|
||||
buffer_free(&m);
|
||||
close(client_fd);
|
||||
return start_close;
|
||||
default:
|
||||
error("Unsupported command %d", mux_command);
|
||||
buffer_free(&m);
|
||||
close(client_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Reply for SSHMUX_COMMAND_OPEN */
|
||||
buffer_clear(&m);
|
||||
buffer_put_int(&m, allowed);
|
||||
buffer_put_int(&m, getpid());
|
||||
if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
|
||||
error("%s: client msg_send failed", __func__);
|
||||
close(client_fd);
|
||||
buffer_free(&m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!allowed) {
|
||||
error("Refused control connection");
|
||||
close(client_fd);
|
||||
buffer_free(&m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
buffer_clear(&m);
|
||||
if (ssh_msg_recv(client_fd, &m) == -1) {
|
||||
error("%s: client msg_recv failed", __func__);
|
||||
close(client_fd);
|
||||
buffer_free(&m);
|
||||
return 0;
|
||||
}
|
||||
if ((ver = buffer_get_char(&m)) != SSHMUX_VER) {
|
||||
error("%s: wrong client version %d", __func__, ver);
|
||||
buffer_free(&m);
|
||||
close(client_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cctx = xcalloc(1, sizeof(*cctx));
|
||||
cctx->want_tty = (flags & SSHMUX_FLAG_TTY) != 0;
|
||||
cctx->want_subsys = (flags & SSHMUX_FLAG_SUBSYS) != 0;
|
||||
cctx->want_x_fwd = (flags & SSHMUX_FLAG_X11_FWD) != 0;
|
||||
cctx->want_agent_fwd = (flags & SSHMUX_FLAG_AGENT_FWD) != 0;
|
||||
cctx->term = buffer_get_string(&m, &len);
|
||||
escape_char = buffer_get_int(&m);
|
||||
|
||||
cmd = buffer_get_string(&m, &len);
|
||||
buffer_init(&cctx->cmd);
|
||||
buffer_append(&cctx->cmd, cmd, strlen(cmd));
|
||||
|
||||
env_len = buffer_get_int(&m);
|
||||
env_len = MIN(env_len, 4096);
|
||||
debug3("%s: receiving %d env vars", __func__, env_len);
|
||||
if (env_len != 0) {
|
||||
cctx->env = xcalloc(env_len + 1, sizeof(*cctx->env));
|
||||
for (i = 0; i < env_len; i++)
|
||||
cctx->env[i] = buffer_get_string(&m, &len);
|
||||
cctx->env[i] = NULL;
|
||||
}
|
||||
|
||||
debug2("%s: accepted tty %d, subsys %d, cmd %s", __func__,
|
||||
cctx->want_tty, cctx->want_subsys, cmd);
|
||||
xfree(cmd);
|
||||
|
||||
/* Gather fds from client */
|
||||
for(i = 0; i < 3; i++) {
|
||||
if ((new_fd[i] = mm_receive_fd(client_fd)) == -1) {
|
||||
error("%s: failed to receive fd %d from slave",
|
||||
__func__, i);
|
||||
for (j = 0; j < i; j++)
|
||||
close(new_fd[j]);
|
||||
for (j = 0; j < env_len; j++)
|
||||
xfree(cctx->env[j]);
|
||||
if (env_len > 0)
|
||||
xfree(cctx->env);
|
||||
xfree(cctx->term);
|
||||
buffer_free(&cctx->cmd);
|
||||
close(client_fd);
|
||||
xfree(cctx);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
debug2("%s: got fds stdin %d, stdout %d, stderr %d", __func__,
|
||||
new_fd[0], new_fd[1], new_fd[2]);
|
||||
|
||||
/* Try to pick up ttymodes from client before it goes raw */
|
||||
if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1)
|
||||
error("%s: tcgetattr: %s", __func__, strerror(errno));
|
||||
|
||||
/* This roundtrip is just for synchronisation of ttymodes */
|
||||
buffer_clear(&m);
|
||||
if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
|
||||
error("%s: client msg_send failed", __func__);
|
||||
close(client_fd);
|
||||
close(new_fd[0]);
|
||||
close(new_fd[1]);
|
||||
close(new_fd[2]);
|
||||
buffer_free(&m);
|
||||
xfree(cctx->term);
|
||||
if (env_len != 0) {
|
||||
for (i = 0; i < env_len; i++)
|
||||
xfree(cctx->env[i]);
|
||||
xfree(cctx->env);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
buffer_free(&m);
|
||||
|
||||
/* enable nonblocking unless tty */
|
||||
if (!isatty(new_fd[0]))
|
||||
set_nonblock(new_fd[0]);
|
||||
if (!isatty(new_fd[1]))
|
||||
set_nonblock(new_fd[1]);
|
||||
if (!isatty(new_fd[2]))
|
||||
set_nonblock(new_fd[2]);
|
||||
|
||||
set_nonblock(client_fd);
|
||||
|
||||
window = CHAN_SES_WINDOW_DEFAULT;
|
||||
packetmax = CHAN_SES_PACKET_DEFAULT;
|
||||
if (cctx->want_tty) {
|
||||
window >>= 1;
|
||||
packetmax >>= 1;
|
||||
}
|
||||
|
||||
c = channel_new("session", SSH_CHANNEL_OPENING,
|
||||
new_fd[0], new_fd[1], new_fd[2], window, packetmax,
|
||||
CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0);
|
||||
|
||||
c->ctl_fd = client_fd;
|
||||
if (cctx->want_tty && escape_char != 0xffffffff) {
|
||||
channel_register_filter(c->self,
|
||||
client_simple_escape_filter, NULL,
|
||||
client_filter_cleanup,
|
||||
client_new_escape_filter_ctx((int)escape_char));
|
||||
}
|
||||
|
||||
debug3("%s: channel_new: %d", __func__, c->self);
|
||||
|
||||
channel_send_open(c->self);
|
||||
channel_register_open_confirm(c->self, mux_session_confirm, cctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ** Multiplexing client support */
|
||||
|
||||
/* Exit signal handler */
|
||||
static void
|
||||
control_client_sighandler(int signo)
|
||||
{
|
||||
muxclient_terminate = signo;
|
||||
}
|
||||
|
||||
/*
|
||||
* Relay signal handler - used to pass some signals from mux client to
|
||||
* mux master.
|
||||
*/
|
||||
static void
|
||||
control_client_sigrelay(int signo)
|
||||
{
|
||||
int save_errno = errno;
|
||||
|
||||
if (muxserver_pid > 1)
|
||||
kill(muxserver_pid, signo);
|
||||
|
||||
errno = save_errno;
|
||||
}
|
||||
|
||||
/* Check mux client environment variables before passing them to mux master. */
|
||||
static int
|
||||
env_permitted(char *env)
|
||||
{
|
||||
int i, ret;
|
||||
char name[1024], *cp;
|
||||
|
||||
if ((cp = strchr(env, '=')) == NULL || cp == env)
|
||||
return (0);
|
||||
ret = snprintf(name, sizeof(name), "%.*s", (int)(cp - env), env);
|
||||
if (ret <= 0 || (size_t)ret >= sizeof(name))
|
||||
fatal("env_permitted: name '%.100s...' too long", env);
|
||||
|
||||
for (i = 0; i < options.num_send_env; i++)
|
||||
if (match_pattern(name, options.send_env[i]))
|
||||
return (1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Multiplex client main loop. */
|
||||
void
|
||||
muxclient(const char *path)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
int i, r, fd, sock, exitval[2], num_env, addr_len;
|
||||
Buffer m;
|
||||
char *term;
|
||||
extern char **environ;
|
||||
u_int allowed, flags;
|
||||
|
||||
if (muxclient_command == 0)
|
||||
muxclient_command = SSHMUX_COMMAND_OPEN;
|
||||
|
||||
switch (options.control_master) {
|
||||
case SSHCTL_MASTER_AUTO:
|
||||
case SSHCTL_MASTER_AUTO_ASK:
|
||||
debug("auto-mux: Trying existing master");
|
||||
/* FALLTHROUGH */
|
||||
case SSHCTL_MASTER_NO:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&addr, '\0', sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
addr_len = offsetof(struct sockaddr_un, sun_path) +
|
||||
strlen(path) + 1;
|
||||
|
||||
if (strlcpy(addr.sun_path, path,
|
||||
sizeof(addr.sun_path)) >= sizeof(addr.sun_path))
|
||||
fatal("ControlPath too long");
|
||||
|
||||
if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
|
||||
fatal("%s socket(): %s", __func__, strerror(errno));
|
||||
|
||||
if (connect(sock, (struct sockaddr *)&addr, addr_len) == -1) {
|
||||
if (muxclient_command != SSHMUX_COMMAND_OPEN) {
|
||||
fatal("Control socket connect(%.100s): %s", path,
|
||||
strerror(errno));
|
||||
}
|
||||
if (errno == ENOENT)
|
||||
debug("Control socket \"%.100s\" does not exist", path);
|
||||
else {
|
||||
error("Control socket connect(%.100s): %s", path,
|
||||
strerror(errno));
|
||||
}
|
||||
close(sock);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stdin_null_flag) {
|
||||
if ((fd = open(_PATH_DEVNULL, O_RDONLY)) == -1)
|
||||
fatal("open(/dev/null): %s", strerror(errno));
|
||||
if (dup2(fd, STDIN_FILENO) == -1)
|
||||
fatal("dup2: %s", strerror(errno));
|
||||
if (fd > STDERR_FILENO)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
term = getenv("TERM");
|
||||
|
||||
flags = 0;
|
||||
if (tty_flag)
|
||||
flags |= SSHMUX_FLAG_TTY;
|
||||
if (subsystem_flag)
|
||||
flags |= SSHMUX_FLAG_SUBSYS;
|
||||
if (options.forward_x11)
|
||||
flags |= SSHMUX_FLAG_X11_FWD;
|
||||
if (options.forward_agent)
|
||||
flags |= SSHMUX_FLAG_AGENT_FWD;
|
||||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
buffer_init(&m);
|
||||
|
||||
/* Send our command to server */
|
||||
buffer_put_int(&m, muxclient_command);
|
||||
buffer_put_int(&m, flags);
|
||||
if (ssh_msg_send(sock, SSHMUX_VER, &m) == -1) {
|
||||
error("%s: msg_send", __func__);
|
||||
muxerr:
|
||||
close(sock);
|
||||
buffer_free(&m);
|
||||
if (muxclient_command != SSHMUX_COMMAND_OPEN)
|
||||
cleanup_exit(255);
|
||||
logit("Falling back to non-multiplexed connection");
|
||||
xfree(options.control_path);
|
||||
options.control_path = NULL;
|
||||
options.control_master = SSHCTL_MASTER_NO;
|
||||
return;
|
||||
}
|
||||
buffer_clear(&m);
|
||||
|
||||
/* Get authorisation status and PID of controlee */
|
||||
if (ssh_msg_recv(sock, &m) == -1) {
|
||||
error("%s: Did not receive reply from master", __func__);
|
||||
goto muxerr;
|
||||
}
|
||||
if (buffer_get_char(&m) != SSHMUX_VER) {
|
||||
error("%s: Master replied with wrong version", __func__);
|
||||
goto muxerr;
|
||||
}
|
||||
if (buffer_get_int_ret(&allowed, &m) != 0) {
|
||||
error("%s: bad server reply", __func__);
|
||||
goto muxerr;
|
||||
}
|
||||
if (allowed != 1) {
|
||||
error("Connection to master denied");
|
||||
goto muxerr;
|
||||
}
|
||||
muxserver_pid = buffer_get_int(&m);
|
||||
|
||||
buffer_clear(&m);
|
||||
|
||||
switch (muxclient_command) {
|
||||
case SSHMUX_COMMAND_ALIVE_CHECK:
|
||||
fprintf(stderr, "Master running (pid=%d)\r\n",
|
||||
muxserver_pid);
|
||||
exit(0);
|
||||
case SSHMUX_COMMAND_TERMINATE:
|
||||
fprintf(stderr, "Exit request sent.\r\n");
|
||||
exit(0);
|
||||
case SSHMUX_COMMAND_OPEN:
|
||||
buffer_put_cstring(&m, term ? term : "");
|
||||
if (options.escape_char == SSH_ESCAPECHAR_NONE)
|
||||
buffer_put_int(&m, 0xffffffff);
|
||||
else
|
||||
buffer_put_int(&m, options.escape_char);
|
||||
buffer_append(&command, "\0", 1);
|
||||
buffer_put_cstring(&m, buffer_ptr(&command));
|
||||
|
||||
if (options.num_send_env == 0 || environ == NULL) {
|
||||
buffer_put_int(&m, 0);
|
||||
} else {
|
||||
/* Pass environment */
|
||||
num_env = 0;
|
||||
for (i = 0; environ[i] != NULL; i++) {
|
||||
if (env_permitted(environ[i]))
|
||||
num_env++; /* Count */
|
||||
}
|
||||
buffer_put_int(&m, num_env);
|
||||
for (i = 0; environ[i] != NULL && num_env >= 0; i++) {
|
||||
if (env_permitted(environ[i])) {
|
||||
num_env--;
|
||||
buffer_put_cstring(&m, environ[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fatal("unrecognised muxclient_command %d", muxclient_command);
|
||||
}
|
||||
|
||||
if (ssh_msg_send(sock, SSHMUX_VER, &m) == -1) {
|
||||
error("%s: msg_send", __func__);
|
||||
goto muxerr;
|
||||
}
|
||||
|
||||
if (mm_send_fd(sock, STDIN_FILENO) == -1 ||
|
||||
mm_send_fd(sock, STDOUT_FILENO) == -1 ||
|
||||
mm_send_fd(sock, STDERR_FILENO) == -1) {
|
||||
error("%s: send fds failed", __func__);
|
||||
goto muxerr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mux errors are non-recoverable from this point as the master
|
||||
* has ownership of the session now.
|
||||
*/
|
||||
|
||||
/* Wait for reply, so master has a chance to gather ttymodes */
|
||||
buffer_clear(&m);
|
||||
if (ssh_msg_recv(sock, &m) == -1)
|
||||
fatal("%s: msg_recv", __func__);
|
||||
if (buffer_get_char(&m) != SSHMUX_VER)
|
||||
fatal("%s: wrong version", __func__);
|
||||
buffer_free(&m);
|
||||
|
||||
signal(SIGHUP, control_client_sighandler);
|
||||
signal(SIGINT, control_client_sighandler);
|
||||
signal(SIGTERM, control_client_sighandler);
|
||||
signal(SIGWINCH, control_client_sigrelay);
|
||||
|
||||
if (tty_flag)
|
||||
enter_raw_mode();
|
||||
|
||||
/*
|
||||
* Stick around until the controlee closes the client_fd.
|
||||
* Before it does, it is expected to write this process' exit
|
||||
* value (one int). This process must read the value and wait for
|
||||
* the closure of the client_fd; if this one closes early, the
|
||||
* multiplex master will terminate early too (possibly losing data).
|
||||
*/
|
||||
exitval[0] = 0;
|
||||
for (i = 0; !muxclient_terminate && i < (int)sizeof(exitval);) {
|
||||
r = read(sock, (char *)exitval + i, sizeof(exitval) - i);
|
||||
if (r == 0) {
|
||||
debug2("Received EOF from master");
|
||||
break;
|
||||
}
|
||||
if (r == -1) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
fatal("%s: read %s", __func__, strerror(errno));
|
||||
}
|
||||
i += r;
|
||||
}
|
||||
|
||||
close(sock);
|
||||
leave_raw_mode();
|
||||
if (i > (int)sizeof(int))
|
||||
fatal("%s: master returned too much data (%d > %lu)",
|
||||
__func__, i, (u_long)sizeof(int));
|
||||
if (muxclient_terminate) {
|
||||
debug2("Exiting on signal %d", muxclient_terminate);
|
||||
exitval[0] = 255;
|
||||
} else if (i < (int)sizeof(int)) {
|
||||
debug2("Control master terminated unexpectedly");
|
||||
exitval[0] = 255;
|
||||
} else
|
||||
debug2("Received exit status from master %d", exitval[0]);
|
||||
|
||||
if (tty_flag && options.log_level != SYSLOG_LEVEL_QUIET)
|
||||
fprintf(stderr, "Shared connection to %s closed.\r\n", host);
|
||||
|
||||
exit(exitval[0]);
|
||||
}
|
32
nchan.c
32
nchan.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: nchan.c,v 1.57 2006/08/03 03:34:42 deraadt Exp $ */
|
||||
/* $OpenBSD: nchan.c,v 1.60 2008/06/30 12:16:02 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -32,6 +32,7 @@
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "openbsd-compat/sys-queue.h"
|
||||
#include "ssh1.h"
|
||||
#include "ssh2.h"
|
||||
#include "buffer.h"
|
||||
@ -77,6 +78,7 @@ static void chan_send_ieof1(Channel *);
|
||||
static void chan_send_oclose1(Channel *);
|
||||
static void chan_send_close2(Channel *);
|
||||
static void chan_send_eof2(Channel *);
|
||||
static void chan_send_eow2(Channel *);
|
||||
|
||||
/* helper */
|
||||
static void chan_shutdown_write(Channel *);
|
||||
@ -305,6 +307,17 @@ chan_rcvd_close2(Channel *c)
|
||||
break;
|
||||
}
|
||||
}
|
||||
void
|
||||
chan_rcvd_eow(Channel *c)
|
||||
{
|
||||
debug2("channel %d: rcvd eow", c->self);
|
||||
switch (c->istate) {
|
||||
case CHAN_INPUT_OPEN:
|
||||
chan_shutdown_read(c);
|
||||
chan_set_istate(c, CHAN_INPUT_CLOSED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void
|
||||
chan_rcvd_eof2(Channel *c)
|
||||
{
|
||||
@ -321,6 +334,8 @@ chan_write_failed2(Channel *c)
|
||||
case CHAN_OUTPUT_OPEN:
|
||||
case CHAN_OUTPUT_WAIT_DRAIN:
|
||||
chan_shutdown_write(c);
|
||||
if (strcmp(c->ctype, "session") == 0)
|
||||
chan_send_eow2(c);
|
||||
chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
|
||||
break;
|
||||
default:
|
||||
@ -363,6 +378,21 @@ chan_send_close2(Channel *c)
|
||||
c->flags |= CHAN_CLOSE_SENT;
|
||||
}
|
||||
}
|
||||
static void
|
||||
chan_send_eow2(Channel *c)
|
||||
{
|
||||
debug2("channel %d: send eow", c->self);
|
||||
if (c->ostate == CHAN_OUTPUT_CLOSED) {
|
||||
error("channel %d: must not sent eow on closed output",
|
||||
c->self);
|
||||
return;
|
||||
}
|
||||
packet_start(SSH2_MSG_CHANNEL_REQUEST);
|
||||
packet_put_int(c->remote_id);
|
||||
packet_put_cstring("eow@openssh.com");
|
||||
packet_put_char(0);
|
||||
packet_send();
|
||||
}
|
||||
|
||||
/* shared */
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: nchan2.ms,v 1.3 2003/11/21 11:57:03 djm Exp $
|
||||
.\" $OpenBSD: nchan2.ms,v 1.4 2008/05/15 23:52:24 djm Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
.\"
|
||||
@ -44,7 +44,7 @@ arrow from S1.e to S4.n
|
||||
box invis "rcvd CLOSE/" "shutdown_read" with .sw at last arrow.c
|
||||
arrow "ibuf_empty ||" "rcvd CLOSE/" "send EOF" "" from S2.e to S4.w
|
||||
arrow from S1.s to S2.n
|
||||
box invis "read_failed/" "shutdown_read" with .e at last arrow.c
|
||||
box invis "read_failed ||" "rcvd EOW/" "shutdown_read" with .e at last arrow.c
|
||||
ellipse wid .9*ellipsewid ht .9*ellipseht at S4
|
||||
arrow "start" "" from S1.w+(-0.5,0) to S1.w
|
||||
.PE
|
||||
@ -59,7 +59,7 @@ S4: ellipse "OUTPUT" "CLOSED"
|
||||
move down l from 1st ellipse.s
|
||||
S2: ellipse "OUTPUT" "WAIT" "DRAIN"
|
||||
arrow from S1.e to S4.n
|
||||
box invis "write_failed/" "shutdown_write" with .sw at last arrow.c
|
||||
box invis "write_failed/" "shutdown_write" "send EOW" with .sw at last arrow.c
|
||||
arrow "obuf_empty ||" "write_failed/" "shutdown_write" "" from S2.e to S4.w
|
||||
arrow from S1.s to S2.n
|
||||
box invis "rcvd EOF ||" "rcvd CLOSE/" "-" with .e at last arrow.c
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: Makefile.in,v 1.41 2007/06/25 12:15:13 dtucker Exp $
|
||||
# $Id: Makefile.in,v 1.43 2008/06/08 17:32:29 dtucker Exp $
|
||||
|
||||
sysconfdir=@sysconfdir@
|
||||
piddir=@piddir@
|
||||
@ -16,9 +16,9 @@ RANLIB=@RANLIB@
|
||||
INSTALL=@INSTALL@
|
||||
LDFLAGS=-L. @LDFLAGS@
|
||||
|
||||
OPENBSD=base64.o basename.o bindresvport.o daemon.o dirname.o getcwd.o getgrouplist.o getopt.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sha2.o sigact.o strlcat.o strlcpy.o strmode.o strsep.o strtonum.o strtoll.o strtoul.o vis.o
|
||||
OPENBSD=base64.o basename.o bindresvport.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sha2.o sigact.o strlcat.o strlcpy.o strmode.o strsep.o strtonum.o strtoll.o strtoul.o vis.o
|
||||
|
||||
COMPAT=bsd-arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-snprintf.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o
|
||||
COMPAT=bsd-arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o
|
||||
|
||||
PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-tun.o port-uw.o
|
||||
|
||||
|
@ -54,8 +54,8 @@ bindresvport_sa(int sd, struct sockaddr *sa)
|
||||
{
|
||||
int error, af;
|
||||
struct sockaddr_storage myaddr;
|
||||
struct sockaddr_in *sin;
|
||||
struct sockaddr_in6 *sin6;
|
||||
struct sockaddr_in *in;
|
||||
struct sockaddr_in6 *in6;
|
||||
u_int16_t *portp;
|
||||
u_int16_t port;
|
||||
socklen_t salen;
|
||||
@ -74,13 +74,13 @@ bindresvport_sa(int sd, struct sockaddr *sa)
|
||||
af = sa->sa_family;
|
||||
|
||||
if (af == AF_INET) {
|
||||
sin = (struct sockaddr_in *)sa;
|
||||
in = (struct sockaddr_in *)sa;
|
||||
salen = sizeof(struct sockaddr_in);
|
||||
portp = &sin->sin_port;
|
||||
portp = &in->sin_port;
|
||||
} else if (af == AF_INET6) {
|
||||
sin6 = (struct sockaddr_in6 *)sa;
|
||||
in6 = (struct sockaddr_in6 *)sa;
|
||||
salen = sizeof(struct sockaddr_in6);
|
||||
portp = &sin6->sin6_port;
|
||||
portp = &in6->sin6_port;
|
||||
} else {
|
||||
errno = EPFNOSUPPORT;
|
||||
return (-1);
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "log.h"
|
||||
@ -82,3 +83,68 @@ arc4random_stir(void)
|
||||
rc4_ready = REKEY_BYTES;
|
||||
}
|
||||
#endif /* !HAVE_ARC4RANDOM */
|
||||
|
||||
#ifndef ARC4RANDOM_BUF
|
||||
void
|
||||
arc4random_buf(void *_buf, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
u_int32_t r = 0;
|
||||
char *buf = (char *)_buf;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (i % 4 == 0)
|
||||
r = arc4random();
|
||||
buf[i] = r & 0xff;
|
||||
r >>= 8;
|
||||
}
|
||||
i = r = 0;
|
||||
}
|
||||
#endif /* !HAVE_ARC4RANDOM_BUF */
|
||||
|
||||
#ifndef ARC4RANDOM_UNIFORM
|
||||
/*
|
||||
* Calculate a uniformly distributed random number less than upper_bound
|
||||
* avoiding "modulo bias".
|
||||
*
|
||||
* Uniformity is achieved by generating new random numbers until the one
|
||||
* returned is outside the range [0, 2**32 % upper_bound). This
|
||||
* guarantees the selected random number will be inside
|
||||
* [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
|
||||
* after reduction modulo upper_bound.
|
||||
*/
|
||||
u_int32_t
|
||||
arc4random_uniform(u_int32_t upper_bound)
|
||||
{
|
||||
u_int32_t r, min;
|
||||
|
||||
if (upper_bound < 2)
|
||||
return 0;
|
||||
|
||||
#if (ULONG_MAX > 0xffffffffUL)
|
||||
min = 0x100000000UL % upper_bound;
|
||||
#else
|
||||
/* Calculate (2**32 % upper_bound) avoiding 64-bit math */
|
||||
if (upper_bound > 0x80000000)
|
||||
min = 1 + ~upper_bound; /* 2**32 - upper_bound */
|
||||
else {
|
||||
/* (2**32 - (x * 2)) % x == 2**32 % x when x <= 2**31 */
|
||||
min = ((0xffffffff - (upper_bound * 2)) + 1) % upper_bound;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This could theoretically loop forever but each retry has
|
||||
* p > 0.5 (worst case, usually far better) of selecting a
|
||||
* number inside the range we need, so it should rarely need
|
||||
* to re-roll.
|
||||
*/
|
||||
for (;;) {
|
||||
r = arc4random();
|
||||
if (r >= min)
|
||||
break;
|
||||
}
|
||||
|
||||
return r % upper_bound;
|
||||
}
|
||||
#endif /* !HAVE_ARC4RANDOM_UNIFORM */
|
||||
|
@ -175,45 +175,7 @@ check_nt_auth(int pwd_authenticated, struct passwd *pw)
|
||||
int
|
||||
check_ntsec(const char *filename)
|
||||
{
|
||||
char *cygwin;
|
||||
int allow_ntea = 0, allow_ntsec = 0;
|
||||
struct statfs fsstat;
|
||||
|
||||
/* Windows 95/98/ME don't support file system security at all. */
|
||||
if (!is_winnt)
|
||||
return (0);
|
||||
|
||||
/* Evaluate current CYGWIN settings. */
|
||||
cygwin = getenv("CYGWIN");
|
||||
allow_ntea = ntea_on(cygwin);
|
||||
allow_ntsec = ntsec_on(cygwin) ||
|
||||
(has_capability(HAS_NTSEC_BY_DEFAULT) && !ntsec_off(cygwin));
|
||||
|
||||
/*
|
||||
* `ntea' is an emulation of POSIX attributes. It doesn't support
|
||||
* real file level security as ntsec on NTFS file systems does
|
||||
* but it supports FAT filesystems. `ntea' is minimum requirement
|
||||
* for security checks.
|
||||
*/
|
||||
if (allow_ntea)
|
||||
return (1);
|
||||
|
||||
/*
|
||||
* Retrieve file system flags. In Cygwin, file system flags are
|
||||
* copied to f_type which has no meaning in Win32 itself.
|
||||
*/
|
||||
if (statfs(filename, &fsstat))
|
||||
return (1);
|
||||
|
||||
/*
|
||||
* Only file systems supporting ACLs are able to set permissions.
|
||||
* `ntsec' is the setting in Cygwin which switches using of NTFS
|
||||
* ACLs to support POSIX permissions on files.
|
||||
*/
|
||||
if (fsstat.f_type & FS_PERSISTENT_ACLS)
|
||||
return (allow_ntsec);
|
||||
|
||||
return (0);
|
||||
return (pathconf(filename, _PC_POSIX_PERMISSIONS));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: bsd-poll.c,v 1.2 2008/02/29 02:57:47 dtucker Exp $ */
|
||||
/* $Id: bsd-poll.c,v 1.3 2008/04/04 05:16:36 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004, 2005, 2007 Darren Tucker (dtucker at zip com au).
|
||||
@ -23,6 +23,7 @@
|
||||
# include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include "bsd-poll.h"
|
||||
|
||||
|
37
openbsd-compat/bsd-statvfs.c
Normal file
37
openbsd-compat/bsd-statvfs.c
Normal file
@ -0,0 +1,37 @@
|
||||
/* $Id: bsd-statvfs.c,v 1.1 2008/06/08 17:32:29 dtucker Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Darren Tucker <dtucker@zip.com.au>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef HAVE_STATVFS
|
||||
int statvfs(const char *path, struct statvfs *buf)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_FSTATVFS
|
||||
int fstatvfs(int fd, struct statvfs *buf)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
68
openbsd-compat/bsd-statvfs.h
Normal file
68
openbsd-compat/bsd-statvfs.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* $Id: bsd-statvfs.h,v 1.1 2008/06/08 17:32:29 dtucker Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Darren Tucker <dtucker@zip.com.au>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef HAVE_SYS_STATFS_H
|
||||
#include <sys/statfs.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STATVFS
|
||||
|
||||
#ifndef HAVE_FSBLKCNT_T
|
||||
typedef unsigned long fsblkcnt_t;
|
||||
#endif
|
||||
#ifndef HAVE_FSFILCNT_T
|
||||
typedef unsigned long fsfilcnt_t;
|
||||
#endif
|
||||
|
||||
#ifndef ST_RDONLY
|
||||
#define ST_RDONLY 1
|
||||
#endif
|
||||
#ifndef ST_NOSUID
|
||||
#define ST_NOSUID 2
|
||||
#endif
|
||||
|
||||
/* as defined in IEEE Std 1003.1, 2004 Edition */
|
||||
struct statvfs {
|
||||
unsigned long f_bsize; /* File system block size. */
|
||||
unsigned long f_frsize; /* Fundamental file system block size. */
|
||||
fsblkcnt_t f_blocks; /* Total number of blocks on file system in */
|
||||
/* units of f_frsize. */
|
||||
fsblkcnt_t f_bfree; /* Total number of free blocks. */
|
||||
fsblkcnt_t f_bavail; /* Number of free blocks available to */
|
||||
/* non-privileged process. */
|
||||
fsfilcnt_t f_files; /* Total number of file serial numbers. */
|
||||
fsfilcnt_t f_ffree; /* Total number of free file serial numbers. */
|
||||
fsfilcnt_t f_favail; /* Number of file serial numbers available to */
|
||||
/* non-privileged process. */
|
||||
unsigned long f_fsid; /* File system ID. */
|
||||
unsigned long f_flag; /* BBit mask of f_flag values. */
|
||||
unsigned long f_namemax;/* Maximum filename length. */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STATVFS
|
||||
int statvfs(const char *, struct statvfs *);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_FSTATVFS
|
||||
int fstatvfs(int, struct statvfs *);
|
||||
#endif
|
@ -51,6 +51,8 @@ int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
|
||||
struct hostent *hp;
|
||||
char tmpserv[16];
|
||||
|
||||
if (sa->sa_family != AF_UNSPEC && sa->sa_family != AF_INET)
|
||||
return (EAI_FAMILY);
|
||||
if (serv != NULL) {
|
||||
snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port));
|
||||
if (strlcpy(serv, tmpserv, servlen) >= servlen)
|
||||
@ -95,6 +97,8 @@ gai_strerror(int err)
|
||||
return ("memory allocation failure.");
|
||||
case EAI_NONAME:
|
||||
return ("nodename nor servname provided, or not known");
|
||||
case EAI_FAMILY:
|
||||
return ("ai_family not supported");
|
||||
default:
|
||||
return ("unknown/invalid error.");
|
||||
}
|
||||
@ -159,6 +163,9 @@ getaddrinfo(const char *hostname, const char *servname,
|
||||
u_long addr;
|
||||
|
||||
port = 0;
|
||||
if (hints && hints->ai_family != AF_UNSPEC &&
|
||||
hints->ai_family != AF_INET)
|
||||
return (EAI_FAMILY);
|
||||
if (servname != NULL) {
|
||||
char *cp;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: fake-rfc2553.h,v 1.14 2008/02/25 09:21:20 dtucker Exp $ */
|
||||
/* $Id: fake-rfc2553.h,v 1.16 2008/07/14 11:37:37 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000-2003 Damien Miller. All rights reserved.
|
||||
@ -77,6 +77,7 @@ struct sockaddr_in6 {
|
||||
u_int16_t sin6_port;
|
||||
u_int32_t sin6_flowinfo;
|
||||
struct in6_addr sin6_addr;
|
||||
u_int32_t sin6_scope_id;
|
||||
};
|
||||
#endif /* !HAVE_STRUCT_SOCKADDR_IN6 */
|
||||
|
||||
@ -128,6 +129,9 @@ struct sockaddr_in6 {
|
||||
#ifndef EAI_SYSTEM
|
||||
# define EAI_SYSTEM (INT_MAX - 4)
|
||||
#endif
|
||||
#ifndef EAI_FAMILY
|
||||
# define EAI_FAMILY (INT_MAX - 5)
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRUCT_ADDRINFO
|
||||
struct addrinfo {
|
||||
|
274
openbsd-compat/fmt_scaled.c
Normal file
274
openbsd-compat/fmt_scaled.c
Normal file
@ -0,0 +1,274 @@
|
||||
/* $OpenBSD: fmt_scaled.c,v 1.9 2007/03/20 03:42:52 tedu Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001, 2002, 2003 Ian F. Darwin. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* OPENBSD ORIGINAL: lib/libutil/fmt_scaled.c */
|
||||
|
||||
/*
|
||||
* fmt_scaled: Format numbers scaled for human comprehension
|
||||
* scan_scaled: Scan numbers in this format.
|
||||
*
|
||||
* "Human-readable" output uses 4 digits max, and puts a unit suffix at
|
||||
* the end. Makes output compact and easy-to-read esp. on huge disks.
|
||||
* Formatting code was originally in OpenBSD "df", converted to library routine.
|
||||
* Scanning code written for OpenBSD libutil.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#ifndef HAVE_FMT_SCALED
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
|
||||
typedef enum {
|
||||
NONE = 0, KILO = 1, MEGA = 2, GIGA = 3, TERA = 4, PETA = 5, EXA = 6
|
||||
} unit_type;
|
||||
|
||||
/* These three arrays MUST be in sync! XXX make a struct */
|
||||
static unit_type units[] = { NONE, KILO, MEGA, GIGA, TERA, PETA, EXA };
|
||||
static char scale_chars[] = "BKMGTPE";
|
||||
static long long scale_factors[] = {
|
||||
1LL,
|
||||
1024LL,
|
||||
1024LL*1024,
|
||||
1024LL*1024*1024,
|
||||
1024LL*1024*1024*1024,
|
||||
1024LL*1024*1024*1024*1024,
|
||||
1024LL*1024*1024*1024*1024*1024,
|
||||
};
|
||||
#define SCALE_LENGTH (sizeof(units)/sizeof(units[0]))
|
||||
|
||||
#define MAX_DIGITS (SCALE_LENGTH * 3) /* XXX strlen(sprintf("%lld", -1)? */
|
||||
|
||||
/** Convert the given input string "scaled" into numeric in "result".
|
||||
* Return 0 on success, -1 and errno set on error.
|
||||
*/
|
||||
int
|
||||
scan_scaled(char *scaled, long long *result)
|
||||
{
|
||||
char *p = scaled;
|
||||
int sign = 0;
|
||||
unsigned int i, ndigits = 0, fract_digits = 0;
|
||||
long long scale_fact = 1, whole = 0, fpart = 0;
|
||||
|
||||
/* Skip leading whitespace */
|
||||
while (isascii(*p) && isspace(*p))
|
||||
++p;
|
||||
|
||||
/* Then at most one leading + or - */
|
||||
while (*p == '-' || *p == '+') {
|
||||
if (*p == '-') {
|
||||
if (sign) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
sign = -1;
|
||||
++p;
|
||||
} else if (*p == '+') {
|
||||
if (sign) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
sign = +1;
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
/* Main loop: Scan digits, find decimal point, if present.
|
||||
* We don't allow exponentials, so no scientific notation
|
||||
* (but note that E for Exa might look like e to some!).
|
||||
* Advance 'p' to end, to get scale factor.
|
||||
*/
|
||||
for (; isascii(*p) && (isdigit(*p) || *p=='.'); ++p) {
|
||||
if (*p == '.') {
|
||||
if (fract_digits > 0) { /* oops, more than one '.' */
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
fract_digits = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
i = (*p) - '0'; /* whew! finally a digit we can use */
|
||||
if (fract_digits > 0) {
|
||||
if (fract_digits >= MAX_DIGITS-1)
|
||||
/* ignore extra fractional digits */
|
||||
continue;
|
||||
fract_digits++; /* for later scaling */
|
||||
fpart *= 10;
|
||||
fpart += i;
|
||||
} else { /* normal digit */
|
||||
if (++ndigits >= MAX_DIGITS) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
whole *= 10;
|
||||
whole += i;
|
||||
}
|
||||
}
|
||||
|
||||
if (sign) {
|
||||
whole *= sign;
|
||||
fpart *= sign;
|
||||
}
|
||||
|
||||
/* If no scale factor given, we're done. fraction is discarded. */
|
||||
if (!*p) {
|
||||
*result = whole;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Validate scale factor, and scale whole and fraction by it. */
|
||||
for (i = 0; i < SCALE_LENGTH; i++) {
|
||||
|
||||
/** Are we there yet? */
|
||||
if (*p == scale_chars[i] ||
|
||||
*p == tolower(scale_chars[i])) {
|
||||
|
||||
/* If it ends with alphanumerics after the scale char, bad. */
|
||||
if (isalnum(*(p+1))) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
scale_fact = scale_factors[i];
|
||||
|
||||
/* scale whole part */
|
||||
whole *= scale_fact;
|
||||
|
||||
/* truncate fpart so it does't overflow.
|
||||
* then scale fractional part.
|
||||
*/
|
||||
while (fpart >= LLONG_MAX / scale_fact) {
|
||||
fpart /= 10;
|
||||
fract_digits--;
|
||||
}
|
||||
fpart *= scale_fact;
|
||||
if (fract_digits > 0) {
|
||||
for (i = 0; i < fract_digits -1; i++)
|
||||
fpart /= 10;
|
||||
}
|
||||
whole += fpart;
|
||||
*result = whole;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Format the given "number" into human-readable form in "result".
|
||||
* Result must point to an allocated buffer of length FMT_SCALED_STRSIZE.
|
||||
* Return 0 on success, -1 and errno set if error.
|
||||
*/
|
||||
int
|
||||
fmt_scaled(long long number, char *result)
|
||||
{
|
||||
long long abval, fract = 0;
|
||||
unsigned int i;
|
||||
unit_type unit = NONE;
|
||||
|
||||
abval = (number < 0LL) ? -number : number; /* no long long_abs yet */
|
||||
|
||||
/* Not every negative long long has a positive representation.
|
||||
* Also check for numbers that are just too darned big to format
|
||||
*/
|
||||
if (abval < 0 || abval / 1024 >= scale_factors[SCALE_LENGTH-1]) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* scale whole part; get unscaled fraction */
|
||||
for (i = 0; i < SCALE_LENGTH; i++) {
|
||||
if (abval/1024 < scale_factors[i]) {
|
||||
unit = units[i];
|
||||
fract = (i == 0) ? 0 : abval % scale_factors[i];
|
||||
number /= scale_factors[i];
|
||||
if (i > 0)
|
||||
fract /= scale_factors[i - 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fract = (10 * fract + 512) / 1024;
|
||||
/* if the result would be >= 10, round main number */
|
||||
if (fract == 10) {
|
||||
if (number >= 0)
|
||||
number++;
|
||||
else
|
||||
number--;
|
||||
fract = 0;
|
||||
}
|
||||
|
||||
if (number == 0)
|
||||
strlcpy(result, "0B", FMT_SCALED_STRSIZE);
|
||||
else if (unit == NONE || number >= 100 || number <= -100) {
|
||||
if (fract >= 5) {
|
||||
if (number >= 0)
|
||||
number++;
|
||||
else
|
||||
number--;
|
||||
}
|
||||
(void)snprintf(result, FMT_SCALED_STRSIZE, "%lld%c",
|
||||
number, scale_chars[unit]);
|
||||
} else
|
||||
(void)snprintf(result, FMT_SCALED_STRSIZE, "%lld.%1lld%c",
|
||||
number, fract, scale_chars[unit]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MAIN
|
||||
/*
|
||||
* This is the original version of the program in the man page.
|
||||
* Copy-and-paste whatever you need from it.
|
||||
*/
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *cinput = "1.5K", buf[FMT_SCALED_STRSIZE];
|
||||
long long ninput = 10483892, result;
|
||||
|
||||
if (scan_scaled(cinput, &result) == 0)
|
||||
printf("\"%s\" -> %lld\n", cinput, result);
|
||||
else
|
||||
perror(cinput);
|
||||
|
||||
if (fmt_scaled(ninput, buf) == 0)
|
||||
printf("%lld -> \"%s\"\n", ninput, buf);
|
||||
else
|
||||
fprintf(stderr, "%lld invalid (%s)\n", ninput, strerror(errno));
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_FMT_SCALED */
|
@ -1,4 +1,4 @@
|
||||
/* $Id: openbsd-compat.h,v 1.43 2007/06/25 12:15:13 dtucker Exp $ */
|
||||
/* $Id: openbsd-compat.h,v 1.46 2008/06/08 17:32:29 dtucker Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999-2003 Damien Miller. All rights reserved.
|
||||
@ -101,6 +101,11 @@ int daemon(int nochdir, int noclose);
|
||||
char *dirname(const char *path);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_FMT_SCALED
|
||||
#define FMT_SCALED_STRSIZE 7
|
||||
int fmt_scaled(long long number, char *result);
|
||||
#endif
|
||||
|
||||
#if defined(BROKEN_INET_NTOA) || !defined(HAVE_INET_NTOA)
|
||||
char *inet_ntoa(struct in_addr in);
|
||||
#endif
|
||||
@ -139,6 +144,7 @@ int writev(int, struct iovec *, int);
|
||||
|
||||
/* Home grown routines */
|
||||
#include "bsd-misc.h"
|
||||
#include "bsd-statvfs.h"
|
||||
#include "bsd-waitpid.h"
|
||||
#include "bsd-poll.h"
|
||||
|
||||
@ -151,6 +157,14 @@ unsigned int arc4random(void);
|
||||
void arc4random_stir(void);
|
||||
#endif /* !HAVE_ARC4RANDOM */
|
||||
|
||||
#ifndef HAVE_ARC4RANDOM_BUF
|
||||
void arc4random_buf(void *, size_t);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ARC4RANDOM_UNIFORM
|
||||
u_int32_t arc4random_uniform(u_int32_t);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ASPRINTF
|
||||
int asprintf(char **, const char *, ...);
|
||||
#endif
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "openbsd-compat/sys-queue.h"
|
||||
#include "log.h"
|
||||
#include "misc.h"
|
||||
#include "buffer.h"
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if 0
|
||||
int
|
||||
|
@ -47,7 +47,7 @@ extern char **environ;
|
||||
* Explicitly removes '=' in argument name.
|
||||
*/
|
||||
static char *
|
||||
__findenv(const char *name, int *offset)
|
||||
__findenv(const char *name, size_t *offset)
|
||||
{
|
||||
extern char **environ;
|
||||
int len, i;
|
||||
@ -82,7 +82,7 @@ setenv(const char *name, const char *value, int rewrite)
|
||||
{
|
||||
static char **lastenv; /* last value of environ */
|
||||
char *C;
|
||||
int l_value, offset;
|
||||
size_t l_value, offset;
|
||||
|
||||
if (*value == '=') /* no `=' in value */
|
||||
++value;
|
||||
@ -133,7 +133,7 @@ void
|
||||
unsetenv(const char *name)
|
||||
{
|
||||
char **P;
|
||||
int offset;
|
||||
size_t offset;
|
||||
|
||||
while (__findenv(name, &offset)) /* if set multiple times */
|
||||
for (P = &environ[offset];; ++P)
|
||||
|
@ -43,6 +43,8 @@
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include <vis.h>
|
||||
|
||||
#define SPT_NONE 0 /* don't use it at all */
|
||||
#define SPT_PSTAT 1 /* use pstat(PSTAT_SETCMD, ...) */
|
||||
#define SPT_REUSEARGV 2 /* cover argv with title information */
|
||||
@ -121,7 +123,7 @@ setproctitle(const char *fmt, ...)
|
||||
{
|
||||
#if SPT_TYPE != SPT_NONE
|
||||
va_list ap;
|
||||
char buf[1024];
|
||||
char buf[1024], ptitle[1024];
|
||||
size_t len;
|
||||
extern char *__progname;
|
||||
#if SPT_TYPE == SPT_PSTAT
|
||||
@ -142,14 +144,16 @@ setproctitle(const char *fmt, ...)
|
||||
vsnprintf(buf + len, sizeof(buf) - len , fmt, ap);
|
||||
}
|
||||
va_end(ap);
|
||||
strnvis(ptitle, buf, sizeof(ptitle),
|
||||
VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL);
|
||||
|
||||
#if SPT_TYPE == SPT_PSTAT
|
||||
pst.pst_command = buf;
|
||||
pstat(PSTAT_SETCMD, pst, strlen(buf), 0, 0);
|
||||
pst.pst_command = ptitle;
|
||||
pstat(PSTAT_SETCMD, pst, strlen(ptitle), 0, 0);
|
||||
#elif SPT_TYPE == SPT_REUSEARGV
|
||||
/* debug("setproctitle: copy \"%s\" into len %d",
|
||||
buf, argv_env_len); */
|
||||
len = strlcpy(argv_start, buf, argv_env_len);
|
||||
len = strlcpy(argv_start, ptitle, argv_env_len);
|
||||
for(; len < argv_env_len; len++)
|
||||
argv_start[len] = SPT_PADCHAR;
|
||||
#endif
|
||||
|
@ -36,6 +36,7 @@
|
||||
/* OPENBSD ORIGINAL: lib/libcurses/base/sigaction.c */
|
||||
|
||||
#include "includes.h"
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include "sigact.h"
|
||||
|
||||
@ -47,28 +48,39 @@
|
||||
int
|
||||
sigaction(int sig, struct sigaction *sigact, struct sigaction *osigact)
|
||||
{
|
||||
return sigvec(sig, &(sigact->sv), &(osigact->sv));
|
||||
return sigvec(sig, sigact ? &sigact->sv : NULL,
|
||||
osigact ? &osigact->sv : NULL);
|
||||
}
|
||||
|
||||
int
|
||||
sigemptyset (sigset_t * mask)
|
||||
sigemptyset (sigset_t *mask)
|
||||
{
|
||||
if (!mask) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
*mask = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sigprocmask (int mode, sigset_t * mask, sigset_t * omask)
|
||||
sigprocmask (int mode, sigset_t *mask, sigset_t *omask)
|
||||
{
|
||||
sigset_t current = sigsetmask(0);
|
||||
|
||||
if (omask) *omask = current;
|
||||
if (!mask) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mode==SIG_BLOCK)
|
||||
if (omask)
|
||||
*omask = current;
|
||||
|
||||
if (mode == SIG_BLOCK)
|
||||
current |= *mask;
|
||||
else if (mode==SIG_UNBLOCK)
|
||||
else if (mode == SIG_UNBLOCK)
|
||||
current &= ~*mask;
|
||||
else if (mode==SIG_SETMASK)
|
||||
else if (mode == SIG_SETMASK)
|
||||
current = *mask;
|
||||
|
||||
sigsetmask(current);
|
||||
@ -76,28 +88,44 @@ sigprocmask (int mode, sigset_t * mask, sigset_t * omask)
|
||||
}
|
||||
|
||||
int
|
||||
sigsuspend (sigset_t * mask)
|
||||
sigsuspend (sigset_t *mask)
|
||||
{
|
||||
if (!mask) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return sigpause(*mask);
|
||||
}
|
||||
|
||||
int
|
||||
sigdelset (sigset_t * mask, int sig)
|
||||
sigdelset (sigset_t *mask, int sig)
|
||||
{
|
||||
if (!mask) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
*mask &= ~sigmask(sig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sigaddset (sigset_t * mask, int sig)
|
||||
sigaddset (sigset_t *mask, int sig)
|
||||
{
|
||||
if (!mask) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
*mask |= sigmask(sig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sigismember (sigset_t * mask, int sig)
|
||||
sigismember (sigset_t *mask, int sig)
|
||||
{
|
||||
if (!mask) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return (*mask & sigmask(sig)) != 0;
|
||||
}
|
||||
|
||||
|
137
packet.c
137
packet.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: packet.c,v 1.151 2008/02/22 20:44:02 dtucker Exp $ */
|
||||
/* $OpenBSD: packet.c,v 1.157 2008/07/10 18:08:11 markus Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -138,12 +138,16 @@ static int after_authentication = 0;
|
||||
|
||||
int keep_alive_timeouts = 0;
|
||||
|
||||
/* Set to the maximum time that we will wait to send or receive a packet */
|
||||
static int packet_timeout_ms = -1;
|
||||
|
||||
/* Session key information for Encryption and MAC */
|
||||
Newkeys *newkeys[MODE_MAX];
|
||||
static struct packet_state {
|
||||
u_int32_t seqnr;
|
||||
u_int32_t packets;
|
||||
u_int64_t blocks;
|
||||
u_int64_t bytes;
|
||||
} p_read, p_send;
|
||||
|
||||
static u_int64_t max_blocks_in, max_blocks_out;
|
||||
@ -188,9 +192,23 @@ packet_set_connection(int fd_in, int fd_out)
|
||||
buffer_init(&outgoing_packet);
|
||||
buffer_init(&incoming_packet);
|
||||
TAILQ_INIT(&outgoing);
|
||||
p_send.packets = p_read.packets = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
packet_set_timeout(int timeout, int count)
|
||||
{
|
||||
if (timeout == 0 || count == 0) {
|
||||
packet_timeout_ms = -1;
|
||||
return;
|
||||
}
|
||||
if ((INT_MAX / 1000) / count < timeout)
|
||||
packet_timeout_ms = INT_MAX;
|
||||
else
|
||||
packet_timeout_ms = timeout * count * 1000;
|
||||
}
|
||||
|
||||
/* Returns 1 if remote host is connected via socket, 0 if not. */
|
||||
|
||||
int
|
||||
@ -295,18 +313,25 @@ packet_get_ssh1_cipher(void)
|
||||
}
|
||||
|
||||
void
|
||||
packet_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, u_int32_t *packets)
|
||||
packet_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, u_int32_t *packets,
|
||||
u_int64_t *bytes)
|
||||
{
|
||||
struct packet_state *state;
|
||||
|
||||
state = (mode == MODE_IN) ? &p_read : &p_send;
|
||||
*seqnr = state->seqnr;
|
||||
*blocks = state->blocks;
|
||||
*packets = state->packets;
|
||||
if (seqnr)
|
||||
*seqnr = state->seqnr;
|
||||
if (blocks)
|
||||
*blocks = state->blocks;
|
||||
if (packets)
|
||||
*packets = state->packets;
|
||||
if (bytes)
|
||||
*bytes = state->bytes;
|
||||
}
|
||||
|
||||
void
|
||||
packet_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets)
|
||||
packet_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets,
|
||||
u_int64_t bytes)
|
||||
{
|
||||
struct packet_state *state;
|
||||
|
||||
@ -314,6 +339,7 @@ packet_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets)
|
||||
state->seqnr = seqnr;
|
||||
state->blocks = blocks;
|
||||
state->packets = packets;
|
||||
state->bytes = bytes;
|
||||
}
|
||||
|
||||
/* returns 1 if connection is via ipv4 */
|
||||
@ -592,7 +618,8 @@ packet_send1(void)
|
||||
fprintf(stderr, "encrypted: ");
|
||||
buffer_dump(&output);
|
||||
#endif
|
||||
|
||||
p_send.packets++;
|
||||
p_send.bytes += len + buffer_len(&outgoing_packet);
|
||||
buffer_clear(&outgoing_packet);
|
||||
|
||||
/*
|
||||
@ -818,6 +845,7 @@ packet_send2_wrapped(void)
|
||||
if (!(datafellows & SSH_BUG_NOREKEY))
|
||||
fatal("XXX too many packets with same key");
|
||||
p_send.blocks += (packet_length + 4) / block_size;
|
||||
p_send.bytes += packet_length + 4;
|
||||
buffer_clear(&outgoing_packet);
|
||||
|
||||
if (type == SSH2_MSG_NEWKEYS)
|
||||
@ -891,9 +919,11 @@ packet_send(void)
|
||||
int
|
||||
packet_read_seqnr(u_int32_t *seqnr_p)
|
||||
{
|
||||
int type, len;
|
||||
int type, len, ret, ms_remain;
|
||||
fd_set *setp;
|
||||
char buf[8192];
|
||||
struct timeval timeout, start, *timeoutp = NULL;
|
||||
|
||||
DBG(debug("packet_read()"));
|
||||
|
||||
setp = (fd_set *)xcalloc(howmany(connection_in+1, NFDBITS),
|
||||
@ -925,11 +955,35 @@ packet_read_seqnr(u_int32_t *seqnr_p)
|
||||
sizeof(fd_mask));
|
||||
FD_SET(connection_in, setp);
|
||||
|
||||
if (packet_timeout_ms > 0) {
|
||||
ms_remain = packet_timeout_ms;
|
||||
timeoutp = &timeout;
|
||||
}
|
||||
/* Wait for some data to arrive. */
|
||||
while (select(connection_in + 1, setp, NULL, NULL, NULL) == -1 &&
|
||||
(errno == EAGAIN || errno == EINTR))
|
||||
;
|
||||
|
||||
for (;;) {
|
||||
if (packet_timeout_ms != -1) {
|
||||
ms_to_timeval(&timeout, ms_remain);
|
||||
gettimeofday(&start, NULL);
|
||||
}
|
||||
if ((ret = select(connection_in + 1, setp, NULL,
|
||||
NULL, timeoutp)) >= 0)
|
||||
break;
|
||||
if (errno != EAGAIN && errno != EINTR &&
|
||||
errno != EWOULDBLOCK)
|
||||
break;
|
||||
if (packet_timeout_ms == -1)
|
||||
continue;
|
||||
ms_subtract_diff(&start, &ms_remain);
|
||||
if (ms_remain <= 0) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret == 0) {
|
||||
logit("Connection to %.200s timed out while "
|
||||
"waiting to read", get_remote_ipaddr());
|
||||
cleanup_exit(255);
|
||||
}
|
||||
/* Read data from the socket. */
|
||||
len = read(connection_in, buf, sizeof(buf));
|
||||
if (len == 0) {
|
||||
@ -1054,6 +1108,8 @@ packet_read_poll1(void)
|
||||
buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
|
||||
buffer_len(&compression_buffer));
|
||||
}
|
||||
p_read.packets++;
|
||||
p_read.bytes += padded_len + 4;
|
||||
type = buffer_get_char(&incoming_packet);
|
||||
if (type < SSH_MSG_MIN || type > SSH_MSG_MAX)
|
||||
packet_disconnect("Invalid ssh1 packet type: %d", type);
|
||||
@ -1142,6 +1198,7 @@ packet_read_poll2(u_int32_t *seqnr_p)
|
||||
if (!(datafellows & SSH_BUG_NOREKEY))
|
||||
fatal("XXX too many packets with same key");
|
||||
p_read.blocks += (packet_length + 4) / block_size;
|
||||
p_read.bytes += packet_length + 4;
|
||||
|
||||
/* get padlen */
|
||||
cp = buffer_ptr(&incoming_packet);
|
||||
@ -1194,9 +1251,10 @@ packet_read_poll_seqnr(u_int32_t *seqnr_p)
|
||||
for (;;) {
|
||||
if (compat20) {
|
||||
type = packet_read_poll2(seqnr_p);
|
||||
keep_alive_timeouts = 0;
|
||||
if (type)
|
||||
if (type) {
|
||||
keep_alive_timeouts = 0;
|
||||
DBG(debug("received packet type %d", type));
|
||||
}
|
||||
switch (type) {
|
||||
case SSH2_MSG_IGNORE:
|
||||
debug3("Received SSH2_MSG_IGNORE");
|
||||
@ -1332,6 +1390,12 @@ packet_get_string(u_int *length_ptr)
|
||||
return buffer_get_string(&incoming_packet, length_ptr);
|
||||
}
|
||||
|
||||
void *
|
||||
packet_get_string_ptr(u_int *length_ptr)
|
||||
{
|
||||
return buffer_get_string_ptr(&incoming_packet, length_ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sends a diagnostic message from the server to the client. This message
|
||||
* can be sent at any time (but not while constructing another message). The
|
||||
@ -1426,16 +1490,19 @@ packet_write_poll(void)
|
||||
|
||||
if (len > 0) {
|
||||
len = write(connection_out, buffer_ptr(&output), len);
|
||||
if (len <= 0) {
|
||||
if (errno == EAGAIN)
|
||||
if (len == -1) {
|
||||
if (errno == EINTR || errno == EAGAIN ||
|
||||
errno == EWOULDBLOCK)
|
||||
return;
|
||||
else
|
||||
fatal("Write failed: %.100s", strerror(errno));
|
||||
fatal("Write failed: %.100s", strerror(errno));
|
||||
}
|
||||
if (len == 0)
|
||||
fatal("Write connection closed");
|
||||
buffer_consume(&output, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Calls packet_write_poll repeatedly until all pending output data has been
|
||||
* written.
|
||||
@ -1445,6 +1512,8 @@ void
|
||||
packet_write_wait(void)
|
||||
{
|
||||
fd_set *setp;
|
||||
int ret, ms_remain;
|
||||
struct timeval start, timeout, *timeoutp = NULL;
|
||||
|
||||
setp = (fd_set *)xcalloc(howmany(connection_out + 1, NFDBITS),
|
||||
sizeof(fd_mask));
|
||||
@ -1453,9 +1522,35 @@ packet_write_wait(void)
|
||||
memset(setp, 0, howmany(connection_out + 1, NFDBITS) *
|
||||
sizeof(fd_mask));
|
||||
FD_SET(connection_out, setp);
|
||||
while (select(connection_out + 1, NULL, setp, NULL, NULL) == -1 &&
|
||||
(errno == EAGAIN || errno == EINTR))
|
||||
;
|
||||
|
||||
if (packet_timeout_ms > 0) {
|
||||
ms_remain = packet_timeout_ms;
|
||||
timeoutp = &timeout;
|
||||
}
|
||||
for (;;) {
|
||||
if (packet_timeout_ms != -1) {
|
||||
ms_to_timeval(&timeout, ms_remain);
|
||||
gettimeofday(&start, NULL);
|
||||
}
|
||||
if ((ret = select(connection_out + 1, NULL, setp,
|
||||
NULL, timeoutp)) >= 0)
|
||||
break;
|
||||
if (errno != EAGAIN && errno != EINTR &&
|
||||
errno != EWOULDBLOCK)
|
||||
break;
|
||||
if (packet_timeout_ms == -1)
|
||||
continue;
|
||||
ms_subtract_diff(&start, &ms_remain);
|
||||
if (ms_remain <= 0) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret == 0) {
|
||||
logit("Connection to %.200s timed out while "
|
||||
"waiting to write", get_remote_ipaddr());
|
||||
cleanup_exit(255);
|
||||
}
|
||||
packet_write_poll();
|
||||
}
|
||||
xfree(setp);
|
||||
|
8
packet.h
8
packet.h
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: packet.h,v 1.46 2008/02/22 20:44:02 dtucker Exp $ */
|
||||
/* $OpenBSD: packet.h,v 1.49 2008/07/10 18:08:11 markus Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -21,6 +21,7 @@
|
||||
#include <openssl/bn.h>
|
||||
|
||||
void packet_set_connection(int, int);
|
||||
void packet_set_timeout(int, int);
|
||||
void packet_set_nonblocking(void);
|
||||
int packet_get_connection_in(void);
|
||||
int packet_get_connection_out(void);
|
||||
@ -58,6 +59,7 @@ void packet_get_bignum(BIGNUM * value);
|
||||
void packet_get_bignum2(BIGNUM * value);
|
||||
void *packet_get_raw(u_int *length_ptr);
|
||||
void *packet_get_string(u_int *length_ptr);
|
||||
void *packet_get_string_ptr(u_int *length_ptr);
|
||||
void packet_disconnect(const char *fmt,...) __attribute__((format(printf, 1, 2)));
|
||||
void packet_send_debug(const char *fmt,...) __attribute__((format(printf, 1, 2)));
|
||||
|
||||
@ -66,8 +68,8 @@ int packet_get_keyiv_len(int);
|
||||
void packet_get_keyiv(int, u_char *, u_int);
|
||||
int packet_get_keycontext(int, u_char *);
|
||||
void packet_set_keycontext(int, u_char *);
|
||||
void packet_get_state(int, u_int32_t *, u_int64_t *, u_int32_t *);
|
||||
void packet_set_state(int, u_int32_t, u_int64_t, u_int32_t);
|
||||
void packet_get_state(int, u_int32_t *, u_int64_t *, u_int32_t *, u_int64_t *);
|
||||
void packet_set_state(int, u_int32_t, u_int64_t, u_int32_t, u_int64_t);
|
||||
int packet_get_ssh1_cipher(void);
|
||||
void packet_set_iv(int, u_char *);
|
||||
|
||||
|
11
readconf.c
11
readconf.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: readconf.c,v 1.165 2008/01/19 23:09:49 djm Exp $ */
|
||||
/* $OpenBSD: readconf.c,v 1.167 2008/06/26 11:46:31 grunk Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -130,6 +130,7 @@ typedef enum {
|
||||
oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
|
||||
oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
|
||||
oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
|
||||
oVisualHostKey,
|
||||
oDeprecated, oUnsupported
|
||||
} OpCodes;
|
||||
|
||||
@ -226,6 +227,7 @@ static struct {
|
||||
{ "tunneldevice", oTunnelDevice },
|
||||
{ "localcommand", oLocalCommand },
|
||||
{ "permitlocalcommand", oPermitLocalCommand },
|
||||
{ "visualhostkey", oVisualHostKey },
|
||||
{ NULL, oBadOption }
|
||||
};
|
||||
|
||||
@ -915,6 +917,10 @@ process_config_line(Options *options, const char *host,
|
||||
intptr = &options->permit_local_command;
|
||||
goto parse_flag;
|
||||
|
||||
case oVisualHostKey:
|
||||
intptr = &options->visual_host_key;
|
||||
goto parse_flag;
|
||||
|
||||
case oDeprecated:
|
||||
debug("%s line %d: Deprecated option \"%s\"",
|
||||
filename, linenum, keyword);
|
||||
@ -1065,6 +1071,7 @@ initialize_options(Options * options)
|
||||
options->tun_remote = -1;
|
||||
options->local_command = NULL;
|
||||
options->permit_local_command = -1;
|
||||
options->visual_host_key = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1199,6 +1206,8 @@ fill_default_options(Options * options)
|
||||
options->tun_remote = SSH_TUNID_ANY;
|
||||
if (options->permit_local_command == -1)
|
||||
options->permit_local_command = 0;
|
||||
if (options->visual_host_key == -1)
|
||||
options->visual_host_key = 0;
|
||||
/* options->local_command should not be set by default */
|
||||
/* options->proxy_command should not be set by default */
|
||||
/* options->user will be set in the main program if appropriate */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: readconf.h,v 1.72 2008/01/19 23:09:49 djm Exp $ */
|
||||
/* $OpenBSD: readconf.h,v 1.74 2008/06/26 11:46:31 grunk Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -120,6 +120,7 @@ typedef struct {
|
||||
|
||||
char *local_command;
|
||||
int permit_local_command;
|
||||
int visual_host_key;
|
||||
|
||||
} Options;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $OpenBSD: Makefile,v 1.44 2007/12/21 04:13:53 djm Exp $
|
||||
# $OpenBSD: Makefile,v 1.48 2008/06/28 13:57:25 djm Exp $
|
||||
|
||||
REGRESS_TARGETS= t1 t2 t3 t4 t5 t6 t7 t-exec
|
||||
tests: $(REGRESS_TARGETS)
|
||||
@ -34,6 +34,7 @@ LTESTS= connect \
|
||||
agent-ptrace \
|
||||
keyscan \
|
||||
keygen-change \
|
||||
key-options \
|
||||
scp \
|
||||
sftp \
|
||||
sftp-cmds \
|
||||
@ -47,10 +48,11 @@ LTESTS= connect \
|
||||
reexec \
|
||||
brokenkeys \
|
||||
cfgmatch \
|
||||
addrmatch \
|
||||
localcommand \
|
||||
forcecommand
|
||||
|
||||
INTEROP_TESTS= putty-transfer putty-ciphers putty-kex
|
||||
INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers
|
||||
#INTEROP_TESTS+=ssh-com ssh-com-client ssh-com-keygen ssh-com-sftp
|
||||
|
||||
USER!= id -un
|
||||
|
42
regress/addrmatch.sh
Executable file
42
regress/addrmatch.sh
Executable file
@ -0,0 +1,42 @@
|
||||
# $OpenBSD: addrmatch.sh,v 1.1 2008/06/10 05:23:32 dtucker Exp $
|
||||
# Placed in the Public Domain.
|
||||
|
||||
tid="address match"
|
||||
|
||||
mv $OBJ/sshd_proxy $OBJ/sshd_proxy_orig
|
||||
|
||||
run_trial()
|
||||
{
|
||||
user="$1"; addr="$2"; host="$3"; expected="$4"; descr="$5"
|
||||
|
||||
verbose "test $descr for $user $addr $host"
|
||||
result=`${SSHD} -f $OBJ/sshd_proxy -T \
|
||||
-C user=${user},addr=${addr},host=${host} | \
|
||||
awk '/passwordauthentication/ {print $2}'`
|
||||
if [ "$result" != "$expected" ]; then
|
||||
fail "failed for $user $addr $host: expected $expected, got $result"
|
||||
fi
|
||||
}
|
||||
|
||||
cp $OBJ/sshd_proxy_orig $OBJ/sshd_proxy
|
||||
cat >>$OBJ/sshd_proxy <<EOD
|
||||
PasswordAuthentication no
|
||||
Match Address 192.168.0.0/16,!192.168.30.0/24,10.0.0.0/8,host.example.com
|
||||
PasswordAuthentication yes
|
||||
Match Address 1.1.1.1,::1,!::3,2000::/16
|
||||
PasswordAuthentication yes
|
||||
EOD
|
||||
|
||||
run_trial user 192.168.0.1 somehost yes "permit, first entry"
|
||||
run_trial user 192.168.30.1 somehost no "deny, negative match"
|
||||
run_trial user 19.0.0.1 somehost no "deny, no match"
|
||||
run_trial user 10.255.255.254 somehost yes "permit, list middle"
|
||||
run_trial user 192.168.30.1 192.168.0.1 no "deny, faked IP in hostname"
|
||||
run_trial user 1.1.1.1 somehost.example.com yes "permit, bare IP4 address"
|
||||
test "$TEST_SSH_IPV6" = "no" && exit
|
||||
run_trial user ::1 somehost.example.com yes "permit, bare IP6 address"
|
||||
run_trial user ::2 somehost.exaple.com no "deny IPv6"
|
||||
run_trial user ::3 somehost no "deny IP6 negated"
|
||||
run_trial user ::4 somehost no "deny, IP6 no match"
|
||||
run_trial user 2000::1 somehost yes "permit, IP6 network"
|
||||
run_trial user 2001::1 somehost no "deny, IP6 network"
|
30
regress/conch-ciphers.sh
Executable file
30
regress/conch-ciphers.sh
Executable file
@ -0,0 +1,30 @@
|
||||
# $OpenBSD: conch-ciphers.sh,v 1.2 2008/06/30 10:43:03 djm Exp $
|
||||
# Placed in the Public Domain.
|
||||
|
||||
tid="conch ciphers"
|
||||
|
||||
DATA=/bin/ls
|
||||
COPY=${OBJ}/copy
|
||||
|
||||
if test "x$REGRESS_INTEROP_CONCH" != "xyes" ; then
|
||||
fatal "conch interop tests not enabled"
|
||||
fi
|
||||
|
||||
start_sshd
|
||||
|
||||
for c in aes256-ctr aes256-cbc aes192-ctr aes192-cbc aes128-ctr aes128-cbc \
|
||||
cast128-cbc blowfish 3des-cbc ; do
|
||||
verbose "$tid: cipher $c"
|
||||
rm -f ${COPY}
|
||||
# XXX the 2nd "cat" seems to be needed because of buggy FD handling
|
||||
# in conch
|
||||
${CONCH} --identity $OBJ/rsa --port $PORT --user $USER -e none \
|
||||
--known-hosts $OBJ/known_hosts --notty --noagent --nox11 -n \
|
||||
127.0.0.1 "cat ${DATA}" 2>/dev/null | cat > ${COPY}
|
||||
if [ $? -ne 0 ]; then
|
||||
fail "ssh cat $DATA failed"
|
||||
fi
|
||||
cmp ${DATA} ${COPY} || fail "corrupted copy"
|
||||
done
|
||||
rm -f ${COPY}
|
||||
|
71
regress/key-options.sh
Executable file
71
regress/key-options.sh
Executable file
@ -0,0 +1,71 @@
|
||||
# $OpenBSD: key-options.sh,v 1.2 2008/06/30 08:07:34 djm Exp $
|
||||
# Placed in the Public Domain.
|
||||
|
||||
tid="key options"
|
||||
|
||||
origkeys="$OBJ/authkeys_orig"
|
||||
authkeys="$OBJ/authorized_keys_${USER}"
|
||||
cp $authkeys $origkeys
|
||||
|
||||
# Test command= forced command
|
||||
for p in 1 2; do
|
||||
for c in 'command="echo bar"' 'no-pty,command="echo bar"'; do
|
||||
sed "s/.*/$c &/" $origkeys >$authkeys
|
||||
verbose "key option proto $p $c"
|
||||
r=`${SSH} -$p -q -F $OBJ/ssh_proxy somehost echo foo`
|
||||
if [ "$r" = "foo" ]; then
|
||||
fail "key option forced command not restricted"
|
||||
fi
|
||||
if [ "$r" != "bar" ]; then
|
||||
fail "key option forced command not executed"
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# Test no-pty
|
||||
sed 's/.*/no-pty &/' $origkeys >$authkeys
|
||||
for p in 1 2; do
|
||||
verbose "key option proto $p no-pty"
|
||||
r=`${SSH} -$p -q -F $OBJ/ssh_proxy somehost tty`
|
||||
if [ -f "$r" ]; then
|
||||
fail "key option failed proto $p no-pty (pty $r)"
|
||||
fi
|
||||
done
|
||||
|
||||
# Test environment=
|
||||
echo 'PermitUserEnvironment yes' >> $OBJ/sshd_proxy
|
||||
sed 's/.*/environment="FOO=bar" &/' $origkeys >$authkeys
|
||||
for p in 1 2; do
|
||||
verbose "key option proto $p environment"
|
||||
r=`${SSH} -$p -q -F $OBJ/ssh_proxy somehost 'echo $FOO'`
|
||||
if [ "$r" != "bar" ]; then
|
||||
fail "key option environment not set"
|
||||
fi
|
||||
done
|
||||
|
||||
# Test from= restriction
|
||||
start_sshd
|
||||
for p in 1 2; do
|
||||
for f in 127.0.0.1 '127.0.0.0\/8'; do
|
||||
cat $origkeys >$authkeys
|
||||
${SSH} -$p -q -F $OBJ/ssh_proxy somehost true
|
||||
if [ $? -ne 0 ]; then
|
||||
fail "key option proto $p failed without restriction"
|
||||
fi
|
||||
|
||||
sed 's/.*/from="'"$f"'" &/' $origkeys >$authkeys
|
||||
from=`head -1 $authkeys | cut -f1 -d ' '`
|
||||
verbose "key option proto $p $from"
|
||||
r=`${SSH} -$p -q -F $OBJ/ssh_proxy somehost 'echo true'`
|
||||
if [ "$r" = "true" ]; then
|
||||
fail "key option proto $p $from not restricted"
|
||||
fi
|
||||
|
||||
r=`${SSH} -$p -q -F $OBJ/ssh_config somehost 'echo true'`
|
||||
if [ "$r" != "true" ]; then
|
||||
fail "key option proto $p $from not allowed but should be"
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
rm -f "$origkeys"
|
@ -1,4 +1,4 @@
|
||||
# $OpenBSD: putty-ciphers.sh,v 1.1 2007/12/21 04:13:53 djm Exp $
|
||||
# $OpenBSD: putty-ciphers.sh,v 1.2 2008/06/30 10:31:11 djm Exp $
|
||||
# Placed in the Public Domain.
|
||||
|
||||
tid="putty ciphers"
|
||||
@ -6,8 +6,6 @@ tid="putty ciphers"
|
||||
DATA=/bin/ls
|
||||
COPY=${OBJ}/copy
|
||||
|
||||
set -e
|
||||
|
||||
if test "x$REGRESS_INTEROP_PUTTY" != "xyes" ; then
|
||||
fatal "putty interop tests not enabled"
|
||||
fi
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $OpenBSD: putty-kex.sh,v 1.1 2007/12/21 04:13:53 djm Exp $
|
||||
# $OpenBSD: putty-kex.sh,v 1.2 2008/06/30 10:31:11 djm Exp $
|
||||
# Placed in the Public Domain.
|
||||
|
||||
tid="putty KEX"
|
||||
@ -6,8 +6,6 @@ tid="putty KEX"
|
||||
DATA=/bin/ls
|
||||
COPY=${OBJ}/copy
|
||||
|
||||
set -e
|
||||
|
||||
if test "x$REGRESS_INTEROP_PUTTY" != "xyes" ; then
|
||||
fatal "putty interop tests not enabled"
|
||||
fi
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $OpenBSD: putty-transfer.sh,v 1.1 2007/12/21 04:13:53 djm Exp $
|
||||
# $OpenBSD: putty-transfer.sh,v 1.2 2008/06/30 10:31:11 djm Exp $
|
||||
# Placed in the Public Domain.
|
||||
|
||||
tid="putty transfer data"
|
||||
@ -6,8 +6,6 @@ tid="putty transfer data"
|
||||
DATA=/bin/ls
|
||||
COPY=${OBJ}/copy
|
||||
|
||||
set -e
|
||||
|
||||
if test "x$REGRESS_INTEROP_PUTTY" != "xyes" ; then
|
||||
fatal "putty interop tests not enabled"
|
||||
fi
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $OpenBSD: test-exec.sh,v 1.31 2007/12/21 04:13:53 djm Exp $
|
||||
# $OpenBSD: test-exec.sh,v 1.35 2008/06/28 13:57:25 djm Exp $
|
||||
# Placed in the Public Domain.
|
||||
|
||||
#SUDO=sudo
|
||||
@ -70,8 +70,9 @@ SFTPSERVER=/usr/libexec/openssh/sftp-server
|
||||
SCP=scp
|
||||
|
||||
# Interop testing
|
||||
PLINK=/usr/local/bin/plink
|
||||
PUTTYGEN=/usr/local/bin/puttygen
|
||||
PLINK=plink
|
||||
PUTTYGEN=puttygen
|
||||
CONCH=conch
|
||||
|
||||
if [ "x$TEST_SSH_SSH" != "x" ]; then
|
||||
SSH="${TEST_SSH_SSH}"
|
||||
@ -114,6 +115,13 @@ if [ "x$TEST_SSH_PUTTYGEN" != "x" ]; then
|
||||
*) PUTTYGEN=`which ${TEST_SSH_PUTTYGEN} 2>/dev/null` ;;
|
||||
esac
|
||||
fi
|
||||
if [ "x$TEST_SSH_CONCH" != "x" ]; then
|
||||
# Find real binary, if it exists
|
||||
case "${TEST_SSH_CONCH}" in
|
||||
/*) CONCH="${TEST_SSH_CONCH}" ;;
|
||||
*) CONCH=`which ${TEST_SSH_CONCH} 2>/dev/null` ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Path to sshd must be absolute for rexec
|
||||
case "$SSHD" in
|
||||
@ -287,9 +295,24 @@ for t in rsa rsa1; do
|
||||
done
|
||||
chmod 644 $OBJ/authorized_keys_$USER
|
||||
|
||||
# If PuTTY is present, prepare keys and configuration
|
||||
# Activate Twisted Conch tests if the binary is present
|
||||
REGRESS_INTEROP_CONCH=no
|
||||
if test -x "$CONCH" ; then
|
||||
REGRESS_INTEROP_CONCH=yes
|
||||
fi
|
||||
|
||||
# If PuTTY is present and we are running a PuTTY test, prepare keys and
|
||||
# configuration
|
||||
REGRESS_INTEROP_PUTTY=no
|
||||
if test -x "$PUTTYGEN" -a -x "$PLINK" ; then
|
||||
REGRESS_INTEROP_PUTTY=yes
|
||||
fi
|
||||
case "$SCRIPT" in
|
||||
*putty*) ;;
|
||||
*) REGRESS_INTEROP_PUTTY=no ;;
|
||||
esac
|
||||
|
||||
if test "$REGRESS_INTEROP_PUTTY" = "yes" ; then
|
||||
mkdir -p ${OBJ}/.putty
|
||||
|
||||
# Add a PuTTY key to authorized_keys
|
||||
|
9
scp.0
9
scp.0
@ -45,8 +45,8 @@ DESCRIPTION
|
||||
This option is directly passed to ssh(1).
|
||||
|
||||
-i identity_file
|
||||
Selects the file from which the identity (private key) for RSA
|
||||
authentication is read. This option is directly passed to
|
||||
Selects the file from which the identity (private key) for public
|
||||
key authentication is read. This option is directly passed to
|
||||
ssh(1).
|
||||
|
||||
-l limit
|
||||
@ -120,7 +120,8 @@ DESCRIPTION
|
||||
-q Quiet mode: disables the progress meter as well as warning and
|
||||
diagnostic messages from ssh(1).
|
||||
|
||||
-r Recursively copy entire directories.
|
||||
-r Recursively copy entire directories. Note that scp follows sym-
|
||||
bolic links encountered in the tree traversal.
|
||||
|
||||
-S program
|
||||
Name of program to use for the encrypted connection. The program
|
||||
@ -144,4 +145,4 @@ AUTHORS
|
||||
Timo Rinne <tri@iki.fi>
|
||||
Tatu Ylonen <ylo@cs.hut.fi>
|
||||
|
||||
OpenBSD 4.3 February 10, 2008 3
|
||||
OpenBSD 4.4 July 12, 2008 3
|
||||
|
9
scp.1
9
scp.1
@ -9,9 +9,9 @@
|
||||
.\"
|
||||
.\" Created: Sun May 7 00:14:37 1995 ylo
|
||||
.\"
|
||||
.\" $OpenBSD: scp.1,v 1.44 2008/01/31 20:06:50 jmc Exp $
|
||||
.\" $OpenBSD: scp.1,v 1.46 2008/07/12 05:33:41 djm Exp $
|
||||
.\"
|
||||
.Dd $Mdocdate: February 10 2008 $
|
||||
.Dd $Mdocdate: July 12 2008 $
|
||||
.Dt SCP 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -104,7 +104,7 @@ per-user configuration file for
|
||||
This option is directly passed to
|
||||
.Xr ssh 1 .
|
||||
.It Fl i Ar identity_file
|
||||
Selects the file from which the identity (private key) for RSA
|
||||
Selects the file from which the identity (private key) for public key
|
||||
authentication is read.
|
||||
This option is directly passed to
|
||||
.Xr ssh 1 .
|
||||
@ -189,6 +189,9 @@ messages from
|
||||
.Xr ssh 1 .
|
||||
.It Fl r
|
||||
Recursively copy entire directories.
|
||||
Note that
|
||||
.Nm
|
||||
follows symbolic links encountered in the tree traversal.
|
||||
.It Fl S Ar program
|
||||
Name of
|
||||
.Ar program
|
||||
|
13
scp.c
13
scp.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: scp.c,v 1.162 2008/01/01 09:06:39 dtucker Exp $ */
|
||||
/* $OpenBSD: scp.c,v 1.163 2008/06/13 18:55:22 dtucker Exp $ */
|
||||
/*
|
||||
* scp - secure remote copy. This is basically patched BSD rcp which
|
||||
* uses ssh to do the data transfer (instead of using rcmd).
|
||||
@ -474,7 +474,7 @@ scpio(ssize_t (*f)(int, void *, size_t), int fd, void *_p, size_t l, off_t *c)
|
||||
if (r < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
if (errno == EAGAIN) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
(void)poll(&pfd, 1, -1); /* Ignore errors */
|
||||
continue;
|
||||
}
|
||||
@ -629,7 +629,8 @@ source(int argc, char **argv)
|
||||
struct stat stb;
|
||||
static BUF buffer;
|
||||
BUF *bp;
|
||||
off_t i, amt, statbytes;
|
||||
off_t i, statbytes;
|
||||
size_t amt;
|
||||
int fd = -1, haderr, indx;
|
||||
char *last, *name, buf[2048], encname[MAXPATHLEN];
|
||||
int len;
|
||||
@ -650,6 +651,10 @@ source(int argc, char **argv)
|
||||
syserr: run_err("%s: %s", name, strerror(errno));
|
||||
goto next;
|
||||
}
|
||||
if (stb.st_size < 0) {
|
||||
run_err("%s: %s", name, "Negative file size");
|
||||
goto next;
|
||||
}
|
||||
unset_nonblock(fd);
|
||||
switch (stb.st_mode & S_IFMT) {
|
||||
case S_IFREG:
|
||||
@ -709,7 +714,7 @@ next: if (fd != -1) {
|
||||
set_nonblock(remout);
|
||||
for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
|
||||
amt = bp->cnt;
|
||||
if (i + amt > stb.st_size)
|
||||
if (i + (off_t)amt > stb.st_size)
|
||||
amt = stb.st_size - i;
|
||||
if (!haderr) {
|
||||
if (atomicio(read, fd, bp->buf, amt) != amt)
|
||||
|
321
servconf.c
321
servconf.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: servconf.c,v 1.177 2008/02/10 10:54:28 djm Exp $ */
|
||||
/* $OpenBSD: servconf.c,v 1.186 2008/07/04 03:44:59 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
* All rights reserved
|
||||
@ -23,7 +23,9 @@
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "openbsd-compat/sys-queue.h"
|
||||
#include "xmalloc.h"
|
||||
#include "ssh.h"
|
||||
#include "log.h"
|
||||
@ -99,6 +101,7 @@ initialize_server_options(ServerOptions *options)
|
||||
options->use_login = -1;
|
||||
options->compression = -1;
|
||||
options->allow_tcp_forwarding = -1;
|
||||
options->allow_agent_forwarding = -1;
|
||||
options->num_allow_users = 0;
|
||||
options->num_deny_users = 0;
|
||||
options->num_allow_groups = 0;
|
||||
@ -112,6 +115,7 @@ initialize_server_options(ServerOptions *options)
|
||||
options->max_startups_rate = -1;
|
||||
options->max_startups = -1;
|
||||
options->max_authtries = -1;
|
||||
options->max_sessions = -1;
|
||||
options->banner = NULL;
|
||||
options->use_dns = -1;
|
||||
options->client_alive_interval = -1;
|
||||
@ -154,7 +158,7 @@ fill_default_server_options(ServerOptions *options)
|
||||
if (options->pid_file == NULL)
|
||||
options->pid_file = _PATH_SSH_DAEMON_PID_FILE;
|
||||
if (options->server_key_bits == -1)
|
||||
options->server_key_bits = 768;
|
||||
options->server_key_bits = 1024;
|
||||
if (options->login_grace_time == -1)
|
||||
options->login_grace_time = 120;
|
||||
if (options->key_regeneration_time == -1)
|
||||
@ -223,6 +227,8 @@ fill_default_server_options(ServerOptions *options)
|
||||
options->compression = COMP_DELAYED;
|
||||
if (options->allow_tcp_forwarding == -1)
|
||||
options->allow_tcp_forwarding = 1;
|
||||
if (options->allow_agent_forwarding == -1)
|
||||
options->allow_agent_forwarding = 1;
|
||||
if (options->gateway_ports == -1)
|
||||
options->gateway_ports = 0;
|
||||
if (options->max_startups == -1)
|
||||
@ -233,6 +239,8 @@ fill_default_server_options(ServerOptions *options)
|
||||
options->max_startups_begin = options->max_startups;
|
||||
if (options->max_authtries == -1)
|
||||
options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
|
||||
if (options->max_sessions == -1)
|
||||
options->max_sessions = DEFAULT_SESSIONS_MAX;
|
||||
if (options->use_dns == -1)
|
||||
options->use_dns = 1;
|
||||
if (options->client_alive_interval == -1)
|
||||
@ -287,13 +295,13 @@ typedef enum {
|
||||
sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
|
||||
sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
|
||||
sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
|
||||
sMaxStartups, sMaxAuthTries,
|
||||
sMaxStartups, sMaxAuthTries, sMaxSessions,
|
||||
sBanner, sUseDNS, sHostbasedAuthentication,
|
||||
sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
|
||||
sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
|
||||
sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
|
||||
sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
|
||||
sUsePrivilegeSeparation,
|
||||
sUsePrivilegeSeparation, sAllowAgentForwarding,
|
||||
sDeprecated, sUnsupported
|
||||
} ServerOpCodes;
|
||||
|
||||
@ -379,6 +387,7 @@ static struct {
|
||||
{ "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
|
||||
{ "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */
|
||||
{ "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL },
|
||||
{ "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL },
|
||||
{ "allowusers", sAllowUsers, SSHCFG_GLOBAL },
|
||||
{ "denyusers", sDenyUsers, SSHCFG_GLOBAL },
|
||||
{ "allowgroups", sAllowGroups, SSHCFG_GLOBAL },
|
||||
@ -389,7 +398,8 @@ static struct {
|
||||
{ "gatewayports", sGatewayPorts, SSHCFG_ALL },
|
||||
{ "subsystem", sSubsystem, SSHCFG_GLOBAL },
|
||||
{ "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
|
||||
{ "maxauthtries", sMaxAuthTries, SSHCFG_GLOBAL },
|
||||
{ "maxauthtries", sMaxAuthTries, SSHCFG_ALL },
|
||||
{ "maxsessions", sMaxSessions, SSHCFG_ALL },
|
||||
{ "banner", sBanner, SSHCFG_ALL },
|
||||
{ "usedns", sUseDNS, SSHCFG_GLOBAL },
|
||||
{ "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
|
||||
@ -408,6 +418,17 @@ static struct {
|
||||
{ NULL, sBadOption, 0 }
|
||||
};
|
||||
|
||||
static struct {
|
||||
int val;
|
||||
char *text;
|
||||
} tunmode_desc[] = {
|
||||
{ SSH_TUNMODE_NO, "no" },
|
||||
{ SSH_TUNMODE_POINTOPOINT, "point-to-point" },
|
||||
{ SSH_TUNMODE_ETHERNET, "ethernet" },
|
||||
{ SSH_TUNMODE_YES, "yes" },
|
||||
{ -1, NULL }
|
||||
};
|
||||
|
||||
/*
|
||||
* Returns the number of the token pointed to by cp or sBadOption.
|
||||
*/
|
||||
@ -504,24 +525,8 @@ static int
|
||||
match_cfg_line_group(const char *grps, int line, const char *user)
|
||||
{
|
||||
int result = 0;
|
||||
u_int ngrps = 0;
|
||||
char *arg, *p, *cp, *grplist[MAX_MATCH_GROUPS];
|
||||
struct passwd *pw;
|
||||
|
||||
/*
|
||||
* Even if we do not have a user yet, we still need to check for
|
||||
* valid syntax.
|
||||
*/
|
||||
arg = cp = xstrdup(grps);
|
||||
while ((p = strsep(&cp, ",")) != NULL && *p != '\0') {
|
||||
if (ngrps >= MAX_MATCH_GROUPS) {
|
||||
error("line %d: too many groups in Match Group", line);
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
grplist[ngrps++] = p;
|
||||
}
|
||||
|
||||
if (user == NULL)
|
||||
goto out;
|
||||
|
||||
@ -531,17 +536,16 @@ match_cfg_line_group(const char *grps, int line, const char *user)
|
||||
} else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
|
||||
debug("Can't Match group because user %.100s not in any group "
|
||||
"at line %d", user, line);
|
||||
} else if (ga_match(grplist, ngrps) != 1) {
|
||||
debug("user %.100s does not match group %.100s at line %d",
|
||||
user, arg, line);
|
||||
} else if (ga_match_pattern_list(grps) != 1) {
|
||||
debug("user %.100s does not match group list %.100s at line %d",
|
||||
user, grps, line);
|
||||
} else {
|
||||
debug("user %.100s matched group %.100s at line %d", user,
|
||||
arg, line);
|
||||
debug("user %.100s matched group list %.100s at line %d", user,
|
||||
grps, line);
|
||||
result = 1;
|
||||
}
|
||||
out:
|
||||
ga_free();
|
||||
xfree(arg);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -594,15 +598,18 @@ match_cfg_line(char **condition, int line, const char *user, const char *host,
|
||||
debug("connection from %.100s matched 'Host "
|
||||
"%.100s' at line %d", host, arg, line);
|
||||
} else if (strcasecmp(attrib, "address") == 0) {
|
||||
if (!address) {
|
||||
result = 0;
|
||||
continue;
|
||||
}
|
||||
if (match_hostname(address, arg, len) != 1)
|
||||
result = 0;
|
||||
else
|
||||
switch (addr_match_list(address, arg)) {
|
||||
case 1:
|
||||
debug("connection from %.100s matched 'Address "
|
||||
"%.100s' at line %d", address, arg, line);
|
||||
break;
|
||||
case 0:
|
||||
case -1:
|
||||
result = 0;
|
||||
break;
|
||||
case -2:
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
error("Unsupported Match attribute %s", attrib);
|
||||
return -1;
|
||||
@ -690,7 +697,7 @@ process_server_config_line(ServerOptions *options, char *line,
|
||||
|
||||
case sServerKeyBits:
|
||||
intptr = &options->server_key_bits;
|
||||
parse_int:
|
||||
parse_int:
|
||||
arg = strdelim(&cp);
|
||||
if (!arg || *arg == '\0')
|
||||
fatal("%s line %d: missing integer value.",
|
||||
@ -702,7 +709,7 @@ process_server_config_line(ServerOptions *options, char *line,
|
||||
|
||||
case sLoginGraceTime:
|
||||
intptr = &options->login_grace_time;
|
||||
parse_time:
|
||||
parse_time:
|
||||
arg = strdelim(&cp);
|
||||
if (!arg || *arg == '\0')
|
||||
fatal("%s line %d: missing time value.",
|
||||
@ -771,7 +778,7 @@ process_server_config_line(ServerOptions *options, char *line,
|
||||
fatal("%s line %d: too many host keys specified (max %d).",
|
||||
filename, linenum, MAX_HOSTKEYS);
|
||||
charptr = &options->host_key_files[*intptr];
|
||||
parse_filename:
|
||||
parse_filename:
|
||||
arg = strdelim(&cp);
|
||||
if (!arg || *arg == '\0')
|
||||
fatal("%s line %d: missing file name.",
|
||||
@ -814,7 +821,7 @@ process_server_config_line(ServerOptions *options, char *line,
|
||||
|
||||
case sIgnoreRhosts:
|
||||
intptr = &options->ignore_rhosts;
|
||||
parse_flag:
|
||||
parse_flag:
|
||||
arg = strdelim(&cp);
|
||||
if (!arg || *arg == '\0')
|
||||
fatal("%s line %d: missing yes/no argument.",
|
||||
@ -1005,6 +1012,10 @@ process_server_config_line(ServerOptions *options, char *line,
|
||||
intptr = &options->allow_tcp_forwarding;
|
||||
goto parse_flag;
|
||||
|
||||
case sAllowAgentForwarding:
|
||||
intptr = &options->allow_agent_forwarding;
|
||||
goto parse_flag;
|
||||
|
||||
case sUsePrivilegeSeparation:
|
||||
intptr = &use_privsep;
|
||||
goto parse_flag;
|
||||
@ -1146,6 +1157,10 @@ process_server_config_line(ServerOptions *options, char *line,
|
||||
intptr = &options->max_authtries;
|
||||
goto parse_int;
|
||||
|
||||
case sMaxSessions:
|
||||
intptr = &options->max_sessions;
|
||||
goto parse_int;
|
||||
|
||||
case sBanner:
|
||||
charptr = &options->banner;
|
||||
goto parse_filename;
|
||||
@ -1192,16 +1207,13 @@ process_server_config_line(ServerOptions *options, char *line,
|
||||
if (!arg || *arg == '\0')
|
||||
fatal("%s line %d: Missing yes/point-to-point/"
|
||||
"ethernet/no argument.", filename, linenum);
|
||||
value = 0; /* silence compiler */
|
||||
if (strcasecmp(arg, "ethernet") == 0)
|
||||
value = SSH_TUNMODE_ETHERNET;
|
||||
else if (strcasecmp(arg, "point-to-point") == 0)
|
||||
value = SSH_TUNMODE_POINTOPOINT;
|
||||
else if (strcasecmp(arg, "yes") == 0)
|
||||
value = SSH_TUNMODE_YES;
|
||||
else if (strcasecmp(arg, "no") == 0)
|
||||
value = SSH_TUNMODE_NO;
|
||||
else
|
||||
value = -1;
|
||||
for (i = 0; tunmode_desc[i].val != -1; i++)
|
||||
if (strcmp(tunmode_desc[i].text, arg) == 0) {
|
||||
value = tunmode_desc[i].val;
|
||||
break;
|
||||
}
|
||||
if (value == -1)
|
||||
fatal("%s line %d: Bad yes/point-to-point/ethernet/"
|
||||
"no argument: %s", filename, linenum, arg);
|
||||
if (*intptr == -1)
|
||||
@ -1368,10 +1380,13 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
|
||||
M_CP_INTOPT(permit_root_login);
|
||||
|
||||
M_CP_INTOPT(allow_tcp_forwarding);
|
||||
M_CP_INTOPT(allow_agent_forwarding);
|
||||
M_CP_INTOPT(gateway_ports);
|
||||
M_CP_INTOPT(x11_display_offset);
|
||||
M_CP_INTOPT(x11_forwarding);
|
||||
M_CP_INTOPT(x11_use_localhost);
|
||||
M_CP_INTOPT(max_sessions);
|
||||
M_CP_INTOPT(max_authtries);
|
||||
|
||||
M_CP_STROPT(banner);
|
||||
if (preauth)
|
||||
@ -1405,3 +1420,213 @@ parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
|
||||
fatal("%s: terminating, %d bad configuration options",
|
||||
filename, bad_options);
|
||||
}
|
||||
|
||||
static const char *
|
||||
fmt_intarg(ServerOpCodes code, int val)
|
||||
{
|
||||
if (code == sAddressFamily) {
|
||||
switch (val) {
|
||||
case AF_INET:
|
||||
return "inet";
|
||||
case AF_INET6:
|
||||
return "inet6";
|
||||
case AF_UNSPEC:
|
||||
return "any";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
if (code == sPermitRootLogin) {
|
||||
switch (val) {
|
||||
case PERMIT_NO_PASSWD:
|
||||
return "without-passord";
|
||||
case PERMIT_FORCED_ONLY:
|
||||
return "forced-commands-only";
|
||||
case PERMIT_YES:
|
||||
return "yes";
|
||||
}
|
||||
}
|
||||
if (code == sProtocol) {
|
||||
switch (val) {
|
||||
case SSH_PROTO_1:
|
||||
return "1";
|
||||
case SSH_PROTO_2:
|
||||
return "2";
|
||||
case (SSH_PROTO_1|SSH_PROTO_2):
|
||||
return "2,1";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
if (code == sGatewayPorts && val == 2)
|
||||
return "clientspecified";
|
||||
if (code == sCompression && val == COMP_DELAYED)
|
||||
return "delayed";
|
||||
switch (val) {
|
||||
case -1:
|
||||
return "unset";
|
||||
case 0:
|
||||
return "no";
|
||||
case 1:
|
||||
return "yes";
|
||||
}
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
static const char *
|
||||
lookup_opcode_name(ServerOpCodes code)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
for (i = 0; keywords[i].name != NULL; i++)
|
||||
if (keywords[i].opcode == code)
|
||||
return(keywords[i].name);
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
static void
|
||||
dump_cfg_int(ServerOpCodes code, int val)
|
||||
{
|
||||
printf("%s %d\n", lookup_opcode_name(code), val);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_cfg_fmtint(ServerOpCodes code, int val)
|
||||
{
|
||||
printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
|
||||
}
|
||||
|
||||
static void
|
||||
dump_cfg_string(ServerOpCodes code, const char *val)
|
||||
{
|
||||
if (val == NULL)
|
||||
return;
|
||||
printf("%s %s\n", lookup_opcode_name(code), val);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
printf("%s %s\n", lookup_opcode_name(code), vals[i]);
|
||||
}
|
||||
|
||||
void
|
||||
dump_config(ServerOptions *o)
|
||||
{
|
||||
u_int i;
|
||||
int ret;
|
||||
struct addrinfo *ai;
|
||||
char addr[NI_MAXHOST], port[NI_MAXSERV], *s = NULL;
|
||||
|
||||
/* these are usually at the top of the config */
|
||||
for (i = 0; i < o->num_ports; i++)
|
||||
printf("port %d\n", o->ports[i]);
|
||||
dump_cfg_fmtint(sProtocol, o->protocol);
|
||||
dump_cfg_fmtint(sAddressFamily, o->address_family);
|
||||
|
||||
/* ListenAddress must be after Port */
|
||||
for (ai = o->listen_addrs; ai; ai = ai->ai_next) {
|
||||
if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr,
|
||||
sizeof(addr), port, sizeof(port),
|
||||
NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
|
||||
error("getnameinfo failed: %.100s",
|
||||
(ret != EAI_SYSTEM) ? gai_strerror(ret) :
|
||||
strerror(errno));
|
||||
} else {
|
||||
if (ai->ai_family == AF_INET6)
|
||||
printf("listenaddress [%s]:%s\n", addr, port);
|
||||
else
|
||||
printf("listenaddress %s:%s\n", addr, port);
|
||||
}
|
||||
}
|
||||
|
||||
/* integer arguments */
|
||||
dump_cfg_int(sServerKeyBits, o->server_key_bits);
|
||||
dump_cfg_int(sLoginGraceTime, o->login_grace_time);
|
||||
dump_cfg_int(sKeyRegenerationTime, o->key_regeneration_time);
|
||||
dump_cfg_int(sX11DisplayOffset, o->x11_display_offset);
|
||||
dump_cfg_int(sMaxAuthTries, o->max_authtries);
|
||||
dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
|
||||
dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max);
|
||||
|
||||
/* formatted integer arguments */
|
||||
dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login);
|
||||
dump_cfg_fmtint(sIgnoreRhosts, o->ignore_rhosts);
|
||||
dump_cfg_fmtint(sIgnoreUserKnownHosts, o->ignore_user_known_hosts);
|
||||
dump_cfg_fmtint(sRhostsRSAAuthentication, o->rhosts_rsa_authentication);
|
||||
dump_cfg_fmtint(sHostbasedAuthentication, o->hostbased_authentication);
|
||||
dump_cfg_fmtint(sHostbasedUsesNameFromPacketOnly,
|
||||
o->hostbased_uses_name_from_packet_only);
|
||||
dump_cfg_fmtint(sRSAAuthentication, o->rsa_authentication);
|
||||
dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication);
|
||||
dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication);
|
||||
dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd);
|
||||
dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup);
|
||||
dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token);
|
||||
dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
|
||||
dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
|
||||
dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
|
||||
dump_cfg_fmtint(sKbdInteractiveAuthentication,
|
||||
o->kbd_interactive_authentication);
|
||||
dump_cfg_fmtint(sChallengeResponseAuthentication,
|
||||
o->challenge_response_authentication);
|
||||
dump_cfg_fmtint(sPrintMotd, o->print_motd);
|
||||
dump_cfg_fmtint(sPrintLastLog, o->print_lastlog);
|
||||
dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding);
|
||||
dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost);
|
||||
dump_cfg_fmtint(sStrictModes, o->strict_modes);
|
||||
dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive);
|
||||
dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd);
|
||||
dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
|
||||
dump_cfg_fmtint(sUseLogin, o->use_login);
|
||||
dump_cfg_fmtint(sCompression, o->compression);
|
||||
dump_cfg_fmtint(sGatewayPorts, o->gateway_ports);
|
||||
dump_cfg_fmtint(sUseDNS, o->use_dns);
|
||||
dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
|
||||
dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
|
||||
|
||||
/* string arguments */
|
||||
dump_cfg_string(sPidFile, o->pid_file);
|
||||
dump_cfg_string(sXAuthLocation, o->xauth_location);
|
||||
dump_cfg_string(sCiphers, o->ciphers);
|
||||
dump_cfg_string(sMacs, o->macs);
|
||||
dump_cfg_string(sBanner, o->banner);
|
||||
dump_cfg_string(sAuthorizedKeysFile, o->authorized_keys_file);
|
||||
dump_cfg_string(sAuthorizedKeysFile2, o->authorized_keys_file2);
|
||||
dump_cfg_string(sForceCommand, o->adm_forced_command);
|
||||
|
||||
/* string arguments requiring a lookup */
|
||||
dump_cfg_string(sLogLevel, log_level_name(o->log_level));
|
||||
dump_cfg_string(sLogFacility, log_facility_name(o->log_facility));
|
||||
|
||||
/* string array arguments */
|
||||
dump_cfg_strarray(sHostKeyFile, o->num_host_key_files,
|
||||
o->host_key_files);
|
||||
dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users);
|
||||
dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users);
|
||||
dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups);
|
||||
dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups);
|
||||
dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env);
|
||||
|
||||
/* other arguments */
|
||||
for (i = 0; i < o->num_subsystems; i++)
|
||||
printf("subsystem %s %s\n", o->subsystem_name[i],
|
||||
o->subsystem_args[i]);
|
||||
|
||||
printf("maxstartups %d:%d:%d\n", o->max_startups_begin,
|
||||
o->max_startups_rate, o->max_startups);
|
||||
|
||||
for (i = 0; tunmode_desc[i].val != -1; i++)
|
||||
if (tunmode_desc[i].val == o->permit_tun) {
|
||||
s = tunmode_desc[i].text;
|
||||
break;
|
||||
}
|
||||
dump_cfg_string(sPermitTunnel, s);
|
||||
|
||||
printf("permitopen");
|
||||
channel_print_adm_permitted_opens();
|
||||
printf("\n");
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: servconf.h,v 1.82 2008/02/13 22:38:17 djm Exp $ */
|
||||
/* $OpenBSD: servconf.h,v 1.85 2008/06/10 04:50:25 dtucker Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -35,6 +35,7 @@
|
||||
#define PERMIT_YES 3
|
||||
|
||||
#define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */
|
||||
#define DEFAULT_SESSIONS_MAX 10 /* Default for MaxSessions */
|
||||
|
||||
/* Magic name for internal sftp-server */
|
||||
#define INTERNAL_SFTP_NAME "internal-sftp"
|
||||
@ -101,6 +102,7 @@ typedef struct {
|
||||
int use_login; /* If true, login(1) is used */
|
||||
int compression; /* If true, compression is allowed */
|
||||
int allow_tcp_forwarding;
|
||||
int allow_agent_forwarding;
|
||||
u_int num_allow_users;
|
||||
char *allow_users[MAX_ALLOW_USERS];
|
||||
u_int num_deny_users;
|
||||
@ -122,6 +124,7 @@ typedef struct {
|
||||
int max_startups_rate;
|
||||
int max_startups;
|
||||
int max_authtries;
|
||||
int max_sessions;
|
||||
char *banner; /* SSH-2 banner message */
|
||||
int use_dns;
|
||||
int client_alive_interval; /*
|
||||
@ -158,5 +161,6 @@ void parse_server_config(ServerOptions *, const char *, Buffer *,
|
||||
void parse_server_match_config(ServerOptions *, const char *, const char *,
|
||||
const char *);
|
||||
void copy_set_server_options(ServerOptions *, ServerOptions *, int);
|
||||
void dump_config(ServerOptions *);
|
||||
|
||||
#endif /* SERVCONF_H */
|
||||
|
55
serverloop.c
55
serverloop.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: serverloop.c,v 1.148 2008/02/22 20:44:02 dtucker Exp $ */
|
||||
/* $OpenBSD: serverloop.c,v 1.153 2008/06/30 12:15:39 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -56,6 +56,7 @@
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "openbsd-compat/sys-queue.h"
|
||||
#include "xmalloc.h"
|
||||
#include "packet.h"
|
||||
#include "buffer.h"
|
||||
@ -104,6 +105,7 @@ static int connection_in; /* Connection to client (input). */
|
||||
static int connection_out; /* Connection to client (output). */
|
||||
static int connection_closed = 0; /* Connection to client closed. */
|
||||
static u_int buffer_high; /* "Soft" max buffer size. */
|
||||
static int no_more_sessions = 0; /* Disallow further sessions. */
|
||||
|
||||
/*
|
||||
* This SIGCHLD kludge is used to detect when the child exits. The server
|
||||
@ -398,7 +400,8 @@ process_input(fd_set *readset)
|
||||
return;
|
||||
cleanup_exit(255);
|
||||
} else if (len < 0) {
|
||||
if (errno != EINTR && errno != EAGAIN) {
|
||||
if (errno != EINTR && errno != EAGAIN &&
|
||||
errno != EWOULDBLOCK) {
|
||||
verbose("Read error from remote host "
|
||||
"%.100s: %.100s",
|
||||
get_remote_ipaddr(), strerror(errno));
|
||||
@ -416,8 +419,8 @@ process_input(fd_set *readset)
|
||||
if (!fdout_eof && FD_ISSET(fdout, readset)) {
|
||||
errno = 0;
|
||||
len = read(fdout, buf, sizeof(buf));
|
||||
if (len < 0 && (errno == EINTR ||
|
||||
(errno == EAGAIN && !child_terminated))) {
|
||||
if (len < 0 && (errno == EINTR || ((errno == EAGAIN ||
|
||||
errno == EWOULDBLOCK) && !child_terminated))) {
|
||||
/* do nothing */
|
||||
#ifndef PTY_ZEROREAD
|
||||
} else if (len <= 0) {
|
||||
@ -435,8 +438,8 @@ process_input(fd_set *readset)
|
||||
if (!fderr_eof && FD_ISSET(fderr, readset)) {
|
||||
errno = 0;
|
||||
len = read(fderr, buf, sizeof(buf));
|
||||
if (len < 0 && (errno == EINTR ||
|
||||
(errno == EAGAIN && !child_terminated))) {
|
||||
if (len < 0 && (errno == EINTR || ((errno == EAGAIN ||
|
||||
errno == EWOULDBLOCK) && !child_terminated))) {
|
||||
/* do nothing */
|
||||
#ifndef PTY_ZEROREAD
|
||||
} else if (len <= 0) {
|
||||
@ -467,7 +470,8 @@ process_output(fd_set *writeset)
|
||||
data = buffer_ptr(&stdin_buffer);
|
||||
dlen = buffer_len(&stdin_buffer);
|
||||
len = write(fdin, data, dlen);
|
||||
if (len < 0 && (errno == EINTR || errno == EAGAIN)) {
|
||||
if (len < 0 &&
|
||||
(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) {
|
||||
/* do nothing */
|
||||
} else if (len <= 0) {
|
||||
if (fdin != fdout)
|
||||
@ -937,7 +941,6 @@ static Channel *
|
||||
server_request_direct_tcpip(void)
|
||||
{
|
||||
Channel *c;
|
||||
int sock;
|
||||
char *target, *originator;
|
||||
int target_port, originator_port;
|
||||
|
||||
@ -947,18 +950,16 @@ server_request_direct_tcpip(void)
|
||||
originator_port = packet_get_int();
|
||||
packet_check_eom();
|
||||
|
||||
debug("server_request_direct_tcpip: originator %s port %d, target %s port %d",
|
||||
originator, originator_port, target, target_port);
|
||||
debug("server_request_direct_tcpip: originator %s port %d, target %s "
|
||||
"port %d", originator, originator_port, target, target_port);
|
||||
|
||||
/* XXX check permission */
|
||||
sock = channel_connect_to(target, target_port);
|
||||
xfree(target);
|
||||
c = channel_connect_to(target, target_port,
|
||||
"direct-tcpip", "direct-tcpip");
|
||||
|
||||
xfree(originator);
|
||||
if (sock < 0)
|
||||
return NULL;
|
||||
c = channel_new("direct-tcpip", SSH_CHANNEL_CONNECTING,
|
||||
sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT,
|
||||
CHAN_TCP_PACKET_DEFAULT, 0, "direct-tcpip", 1);
|
||||
xfree(target);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@ -999,7 +1000,7 @@ server_request_tun(void)
|
||||
#if defined(SSH_TUN_FILTER)
|
||||
if (mode == SSH_TUNMODE_POINTOPOINT)
|
||||
channel_register_filter(c->self, sys_tun_infilter,
|
||||
sys_tun_outfilter);
|
||||
sys_tun_outfilter, NULL, NULL);
|
||||
#endif
|
||||
|
||||
done:
|
||||
@ -1015,6 +1016,12 @@ server_request_session(void)
|
||||
|
||||
debug("input_session_request");
|
||||
packet_check_eom();
|
||||
|
||||
if (no_more_sessions) {
|
||||
packet_disconnect("Possible attack: attempt to open a session "
|
||||
"after additional sessions disabled");
|
||||
}
|
||||
|
||||
/*
|
||||
* A server session has no fd to read or write until a
|
||||
* CHANNEL_REQUEST for a shell is made, so we set the type to
|
||||
@ -1135,6 +1142,9 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt)
|
||||
success = channel_cancel_rport_listener(cancel_address,
|
||||
cancel_port);
|
||||
xfree(cancel_address);
|
||||
} else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) {
|
||||
no_more_sessions = 1;
|
||||
success = 1;
|
||||
}
|
||||
if (want_reply) {
|
||||
packet_start(success ?
|
||||
@ -1162,7 +1172,11 @@ server_input_channel_req(int type, u_int32_t seq, void *ctxt)
|
||||
if ((c = channel_lookup(id)) == NULL)
|
||||
packet_disconnect("server_input_channel_req: "
|
||||
"unknown channel %d", id);
|
||||
if (c->type == SSH_CHANNEL_LARVAL || c->type == SSH_CHANNEL_OPEN)
|
||||
if (!strcmp(rtype, "eow@openssh.com")) {
|
||||
packet_check_eom();
|
||||
chan_rcvd_eow(c);
|
||||
} else if ((c->type == SSH_CHANNEL_LARVAL ||
|
||||
c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0)
|
||||
success = session_input_channel_req(c, rtype);
|
||||
if (reply) {
|
||||
packet_start(success ?
|
||||
@ -1188,8 +1202,9 @@ server_init_dispatch_20(void)
|
||||
dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &server_input_channel_req);
|
||||
dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
|
||||
dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request);
|
||||
dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &channel_input_status_confirm);
|
||||
dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &channel_input_status_confirm);
|
||||
/* client_alive */
|
||||
dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &server_input_keep_alive);
|
||||
dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &server_input_keep_alive);
|
||||
dispatch_set(SSH2_MSG_REQUEST_FAILURE, &server_input_keep_alive);
|
||||
/* rekeying */
|
||||
|
414
session.c
414
session.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: session.c,v 1.233 2008/03/26 21:28:14 djm Exp $ */
|
||||
/* $OpenBSD: session.c,v 1.241 2008/06/16 13:22:53 dtucker Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
* All rights reserved
|
||||
@ -59,6 +59,7 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "openbsd-compat/sys-queue.h"
|
||||
#include "xmalloc.h"
|
||||
#include "ssh.h"
|
||||
#include "ssh1.h"
|
||||
@ -97,13 +98,13 @@
|
||||
/* func */
|
||||
|
||||
Session *session_new(void);
|
||||
void session_set_fds(Session *, int, int, int);
|
||||
void session_set_fds(Session *, int, int, int, int);
|
||||
void session_pty_cleanup(Session *);
|
||||
void session_proctitle(Session *);
|
||||
int session_setup_x11fwd(Session *);
|
||||
void do_exec_pty(Session *, const char *);
|
||||
void do_exec_no_pty(Session *, const char *);
|
||||
void do_exec(Session *, const char *);
|
||||
int do_exec_pty(Session *, const char *);
|
||||
int do_exec_no_pty(Session *, const char *);
|
||||
int do_exec(Session *, const char *);
|
||||
void do_login(Session *, const char *);
|
||||
#ifdef LOGIN_NEEDS_UTMPX
|
||||
static void do_pre_login(Session *s);
|
||||
@ -131,8 +132,9 @@ extern Buffer loginmsg;
|
||||
const char *original_command = NULL;
|
||||
|
||||
/* data */
|
||||
#define MAX_SESSIONS 20
|
||||
Session sessions[MAX_SESSIONS];
|
||||
static int sessions_first_unused = -1;
|
||||
static int sessions_nalloc = 0;
|
||||
static Session *sessions = NULL;
|
||||
|
||||
#define SUBSYSTEM_NONE 0
|
||||
#define SUBSYSTEM_EXT 1
|
||||
@ -166,7 +168,7 @@ static int
|
||||
auth_input_request_forwarding(struct passwd * pw)
|
||||
{
|
||||
Channel *nc;
|
||||
int sock;
|
||||
int sock = -1;
|
||||
struct sockaddr_un sunaddr;
|
||||
|
||||
if (auth_sock_name != NULL) {
|
||||
@ -178,43 +180,48 @@ auth_input_request_forwarding(struct passwd * pw)
|
||||
temporarily_use_uid(pw);
|
||||
|
||||
/* Allocate a buffer for the socket name, and format the name. */
|
||||
auth_sock_name = xmalloc(MAXPATHLEN);
|
||||
auth_sock_dir = xmalloc(MAXPATHLEN);
|
||||
strlcpy(auth_sock_dir, "/tmp/ssh-XXXXXXXXXX", MAXPATHLEN);
|
||||
auth_sock_dir = xstrdup("/tmp/ssh-XXXXXXXXXX");
|
||||
|
||||
/* Create private directory for socket */
|
||||
if (mkdtemp(auth_sock_dir) == NULL) {
|
||||
packet_send_debug("Agent forwarding disabled: "
|
||||
"mkdtemp() failed: %.100s", strerror(errno));
|
||||
restore_uid();
|
||||
xfree(auth_sock_name);
|
||||
xfree(auth_sock_dir);
|
||||
auth_sock_name = NULL;
|
||||
auth_sock_dir = NULL;
|
||||
return 0;
|
||||
goto authsock_err;
|
||||
}
|
||||
snprintf(auth_sock_name, MAXPATHLEN, "%s/agent.%ld",
|
||||
auth_sock_dir, (long) getpid());
|
||||
|
||||
xasprintf(&auth_sock_name, "%s/agent.%ld",
|
||||
auth_sock_dir, (long) getpid());
|
||||
|
||||
/* Create the socket. */
|
||||
sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (sock < 0)
|
||||
packet_disconnect("socket: %.100s", strerror(errno));
|
||||
if (sock < 0) {
|
||||
error("socket: %.100s", strerror(errno));
|
||||
restore_uid();
|
||||
goto authsock_err;
|
||||
}
|
||||
|
||||
/* Bind it to the name. */
|
||||
memset(&sunaddr, 0, sizeof(sunaddr));
|
||||
sunaddr.sun_family = AF_UNIX;
|
||||
strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path));
|
||||
|
||||
if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0)
|
||||
packet_disconnect("bind: %.100s", strerror(errno));
|
||||
if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
|
||||
error("bind: %.100s", strerror(errno));
|
||||
restore_uid();
|
||||
goto authsock_err;
|
||||
}
|
||||
|
||||
/* Restore the privileged uid. */
|
||||
restore_uid();
|
||||
|
||||
/* Start listening on the socket. */
|
||||
if (listen(sock, SSH_LISTEN_BACKLOG) < 0)
|
||||
packet_disconnect("listen: %.100s", strerror(errno));
|
||||
if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
|
||||
error("listen: %.100s", strerror(errno));
|
||||
goto authsock_err;
|
||||
}
|
||||
|
||||
/* Allocate a channel for the authentication agent socket. */
|
||||
nc = channel_new("auth socket",
|
||||
@ -223,6 +230,19 @@ auth_input_request_forwarding(struct passwd * pw)
|
||||
0, "auth socket", 1);
|
||||
strlcpy(nc->path, auth_sock_name, sizeof(nc->path));
|
||||
return 1;
|
||||
|
||||
authsock_err:
|
||||
if (auth_sock_name != NULL)
|
||||
xfree(auth_sock_name);
|
||||
if (auth_sock_dir != NULL) {
|
||||
rmdir(auth_sock_dir);
|
||||
xfree(auth_sock_dir);
|
||||
}
|
||||
if (sock != -1)
|
||||
close(sock);
|
||||
auth_sock_name = NULL;
|
||||
auth_sock_dir = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -335,7 +355,8 @@ do_authenticated1(Authctxt *authctxt)
|
||||
break;
|
||||
|
||||
case SSH_CMSG_AGENT_REQUEST_FORWARDING:
|
||||
if (no_agent_forwarding_flag || compat13) {
|
||||
if (!options.allow_agent_forwarding ||
|
||||
no_agent_forwarding_flag || compat13) {
|
||||
debug("Authentication agent forwarding not permitted for this authentication.");
|
||||
break;
|
||||
}
|
||||
@ -371,10 +392,14 @@ do_authenticated1(Authctxt *authctxt)
|
||||
if (type == SSH_CMSG_EXEC_CMD) {
|
||||
command = packet_get_string(&dlen);
|
||||
debug("Exec command '%.500s'", command);
|
||||
do_exec(s, command);
|
||||
if (do_exec(s, command) != 0)
|
||||
packet_disconnect(
|
||||
"command execution failed");
|
||||
xfree(command);
|
||||
} else {
|
||||
do_exec(s, NULL);
|
||||
if (do_exec(s, NULL) != 0)
|
||||
packet_disconnect(
|
||||
"shell execution failed");
|
||||
}
|
||||
packet_check_eom();
|
||||
session_close(s);
|
||||
@ -399,41 +424,84 @@ do_authenticated1(Authctxt *authctxt)
|
||||
}
|
||||
}
|
||||
|
||||
#define USE_PIPES
|
||||
/*
|
||||
* This is called to fork and execute a command when we have no tty. This
|
||||
* will call do_child from the child, and server_loop from the parent after
|
||||
* setting up file descriptors and such.
|
||||
*/
|
||||
void
|
||||
int
|
||||
do_exec_no_pty(Session *s, const char *command)
|
||||
{
|
||||
pid_t pid;
|
||||
|
||||
#ifdef USE_PIPES
|
||||
int pin[2], pout[2], perr[2];
|
||||
|
||||
/* Allocate pipes for communicating with the program. */
|
||||
if (pipe(pin) < 0 || pipe(pout) < 0 || pipe(perr) < 0)
|
||||
packet_disconnect("Could not create pipes: %.100s",
|
||||
strerror(errno));
|
||||
#else /* USE_PIPES */
|
||||
if (pipe(pin) < 0) {
|
||||
error("%s: pipe in: %.100s", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (pipe(pout) < 0) {
|
||||
error("%s: pipe out: %.100s", __func__, strerror(errno));
|
||||
close(pin[0]);
|
||||
close(pin[1]);
|
||||
return -1;
|
||||
}
|
||||
if (pipe(perr) < 0) {
|
||||
error("%s: pipe err: %.100s", __func__, strerror(errno));
|
||||
close(pin[0]);
|
||||
close(pin[1]);
|
||||
close(pout[0]);
|
||||
close(pout[1]);
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
int inout[2], err[2];
|
||||
|
||||
/* Uses socket pairs to communicate with the program. */
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0 ||
|
||||
socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0)
|
||||
packet_disconnect("Could not create socket pairs: %.100s",
|
||||
strerror(errno));
|
||||
#endif /* USE_PIPES */
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0) {
|
||||
error("%s: socketpair #1: %.100s", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) {
|
||||
error("%s: socketpair #2: %.100s", __func__, strerror(errno));
|
||||
close(inout[0]);
|
||||
close(inout[1]);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (s == NULL)
|
||||
fatal("do_exec_no_pty: no session");
|
||||
|
||||
session_proctitle(s);
|
||||
|
||||
/* Fork the child. */
|
||||
if ((pid = fork()) == 0) {
|
||||
switch ((pid = fork())) {
|
||||
case -1:
|
||||
error("%s: fork: %.100s", __func__, strerror(errno));
|
||||
#ifdef USE_PIPES
|
||||
close(pin[0]);
|
||||
close(pin[1]);
|
||||
close(pout[0]);
|
||||
close(pout[1]);
|
||||
close(perr[0]);
|
||||
close(perr[1]);
|
||||
#else
|
||||
close(inout[0]);
|
||||
close(inout[1]);
|
||||
close(err[0]);
|
||||
close(err[1]);
|
||||
#endif
|
||||
return -1;
|
||||
case 0:
|
||||
is_child = 1;
|
||||
|
||||
/* Child. Reinitialize the log since the pid has changed. */
|
||||
log_init(__progname, options.log_level, options.log_facility, log_stderr);
|
||||
log_init(__progname, options.log_level,
|
||||
options.log_facility, log_stderr);
|
||||
|
||||
/*
|
||||
* Create a new session and process group since the 4.4BSD
|
||||
@ -463,7 +531,7 @@ do_exec_no_pty(Session *s, const char *command)
|
||||
if (dup2(perr[1], 2) < 0)
|
||||
perror("dup2 stderr");
|
||||
close(perr[1]);
|
||||
#else /* USE_PIPES */
|
||||
#else
|
||||
/*
|
||||
* Redirect stdin, stdout, and stderr. Stdin and stdout will
|
||||
* use the same socket, as some programs (particularly rdist)
|
||||
@ -473,11 +541,14 @@ do_exec_no_pty(Session *s, const char *command)
|
||||
close(err[1]);
|
||||
if (dup2(inout[0], 0) < 0) /* stdin */
|
||||
perror("dup2 stdin");
|
||||
if (dup2(inout[0], 1) < 0) /* stdout. Note: same socket as stdin. */
|
||||
if (dup2(inout[0], 1) < 0) /* stdout (same as stdin) */
|
||||
perror("dup2 stdout");
|
||||
close(inout[0]);
|
||||
if (dup2(err[0], 2) < 0) /* stderr */
|
||||
perror("dup2 stderr");
|
||||
#endif /* USE_PIPES */
|
||||
close(err[0]);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _UNICOS
|
||||
cray_init_job(s->pw); /* set up cray jid and tmpdir */
|
||||
@ -486,7 +557,10 @@ do_exec_no_pty(Session *s, const char *command)
|
||||
/* Do processing for the child (exec command etc). */
|
||||
do_child(s, command);
|
||||
/* NOTREACHED */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef _UNICOS
|
||||
signal(WJSIGNAL, cray_job_termination_handler);
|
||||
#endif /* _UNICOS */
|
||||
@ -494,11 +568,18 @@ do_exec_no_pty(Session *s, const char *command)
|
||||
if (is_winnt)
|
||||
cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
|
||||
#endif
|
||||
if (pid < 0)
|
||||
packet_disconnect("fork failed: %.100s", strerror(errno));
|
||||
|
||||
s->pid = pid;
|
||||
/* Set interactive/non-interactive mode. */
|
||||
packet_set_interactive(s->display != NULL);
|
||||
|
||||
/*
|
||||
* Clear loginmsg, since it's the child's responsibility to display
|
||||
* it to the user, otherwise multiple sessions may accumulate
|
||||
* multiple copies of the login messages.
|
||||
*/
|
||||
buffer_clear(&loginmsg);
|
||||
|
||||
#ifdef USE_PIPES
|
||||
/* We are the parent. Close the child sides of the pipes. */
|
||||
close(pin[0]);
|
||||
@ -510,35 +591,32 @@ do_exec_no_pty(Session *s, const char *command)
|
||||
close(perr[0]);
|
||||
perr[0] = -1;
|
||||
}
|
||||
session_set_fds(s, pin[1], pout[0], perr[0]);
|
||||
session_set_fds(s, pin[1], pout[0], perr[0], 0);
|
||||
} else {
|
||||
/* Enter the interactive session. */
|
||||
server_loop(pid, pin[1], pout[0], perr[0]);
|
||||
/* server_loop has closed pin[1], pout[0], and perr[0]. */
|
||||
}
|
||||
#else /* USE_PIPES */
|
||||
#else
|
||||
/* We are the parent. Close the child sides of the socket pairs. */
|
||||
close(inout[0]);
|
||||
close(err[0]);
|
||||
|
||||
/*
|
||||
* Clear loginmsg, since it's the child's responsibility to display
|
||||
* it to the user, otherwise multiple sessions may accumulate
|
||||
* multiple copies of the login messages.
|
||||
*/
|
||||
buffer_clear(&loginmsg);
|
||||
|
||||
/*
|
||||
* Enter the interactive session. Note: server_loop must be able to
|
||||
* handle the case that fdin and fdout are the same.
|
||||
*/
|
||||
if (compat20) {
|
||||
session_set_fds(s, inout[1], inout[1], s->is_subsystem ? -1 : err[1]);
|
||||
session_set_fds(s, inout[1], inout[1],
|
||||
s->is_subsystem ? -1 : err[1], 0);
|
||||
if (s->is_subsystem)
|
||||
close(err[1]);
|
||||
} else {
|
||||
server_loop(pid, inout[1], inout[1], err[1]);
|
||||
/* server_loop has closed inout[1] and err[1]. */
|
||||
}
|
||||
#endif /* USE_PIPES */
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -547,7 +625,7 @@ do_exec_no_pty(Session *s, const char *command)
|
||||
* setting up file descriptors, controlling tty, updating wtmp, utmp,
|
||||
* lastlog, and other such operations.
|
||||
*/
|
||||
void
|
||||
int
|
||||
do_exec_pty(Session *s, const char *command)
|
||||
{
|
||||
int fdout, ptyfd, ttyfd, ptymaster;
|
||||
@ -558,12 +636,46 @@ do_exec_pty(Session *s, const char *command)
|
||||
ptyfd = s->ptyfd;
|
||||
ttyfd = s->ttyfd;
|
||||
|
||||
/*
|
||||
* Create another descriptor of the pty master side for use as the
|
||||
* standard input. We could use the original descriptor, but this
|
||||
* simplifies code in server_loop. The descriptor is bidirectional.
|
||||
* Do this before forking (and cleanup in the child) so as to
|
||||
* detect and gracefully fail out-of-fd conditions.
|
||||
*/
|
||||
if ((fdout = dup(ptyfd)) < 0) {
|
||||
error("%s: dup #1: %s", __func__, strerror(errno));
|
||||
close(ttyfd);
|
||||
close(ptyfd);
|
||||
return -1;
|
||||
}
|
||||
/* we keep a reference to the pty master */
|
||||
if ((ptymaster = dup(ptyfd)) < 0) {
|
||||
error("%s: dup #2: %s", __func__, strerror(errno));
|
||||
close(ttyfd);
|
||||
close(ptyfd);
|
||||
close(fdout);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Fork the child. */
|
||||
if ((pid = fork()) == 0) {
|
||||
switch ((pid = fork())) {
|
||||
case -1:
|
||||
error("%s: fork: %.100s", __func__, strerror(errno));
|
||||
close(fdout);
|
||||
close(ptymaster);
|
||||
close(ttyfd);
|
||||
close(ptyfd);
|
||||
return -1;
|
||||
case 0:
|
||||
is_child = 1;
|
||||
|
||||
close(fdout);
|
||||
close(ptymaster);
|
||||
|
||||
/* Child. Reinitialize the log because the pid has changed. */
|
||||
log_init(__progname, options.log_level, options.log_facility, log_stderr);
|
||||
log_init(__progname, options.log_level,
|
||||
options.log_facility, log_stderr);
|
||||
/* Close the master side of the pseudo tty. */
|
||||
close(ptyfd);
|
||||
|
||||
@ -594,11 +706,16 @@ do_exec_pty(Session *s, const char *command)
|
||||
do_pre_login(s);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Do common processing for the child, such as execing the command. */
|
||||
do_child(s, command);
|
||||
/* NOTREACHED */
|
||||
/*
|
||||
* Do common processing for the child, such as execing
|
||||
* the command.
|
||||
*/
|
||||
do_child(s, command);
|
||||
/* NOTREACHED */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef _UNICOS
|
||||
signal(WJSIGNAL, cray_job_termination_handler);
|
||||
#endif /* _UNICOS */
|
||||
@ -606,36 +723,22 @@ do_exec_pty(Session *s, const char *command)
|
||||
if (is_winnt)
|
||||
cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
|
||||
#endif
|
||||
if (pid < 0)
|
||||
packet_disconnect("fork failed: %.100s", strerror(errno));
|
||||
|
||||
s->pid = pid;
|
||||
|
||||
/* Parent. Close the slave side of the pseudo tty. */
|
||||
close(ttyfd);
|
||||
|
||||
/*
|
||||
* Create another descriptor of the pty master side for use as the
|
||||
* standard input. We could use the original descriptor, but this
|
||||
* simplifies code in server_loop. The descriptor is bidirectional.
|
||||
*/
|
||||
fdout = dup(ptyfd);
|
||||
if (fdout < 0)
|
||||
packet_disconnect("dup #1 failed: %.100s", strerror(errno));
|
||||
|
||||
/* we keep a reference to the pty master */
|
||||
ptymaster = dup(ptyfd);
|
||||
if (ptymaster < 0)
|
||||
packet_disconnect("dup #2 failed: %.100s", strerror(errno));
|
||||
s->ptymaster = ptymaster;
|
||||
|
||||
/* Enter interactive session. */
|
||||
s->ptymaster = ptymaster;
|
||||
packet_set_interactive(1);
|
||||
if (compat20) {
|
||||
session_set_fds(s, ptyfd, fdout, -1);
|
||||
session_set_fds(s, ptyfd, fdout, -1, 1);
|
||||
} else {
|
||||
server_loop(pid, ptyfd, fdout, -1);
|
||||
/* server_loop _has_ closed ptyfd and fdout. */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef LOGIN_NEEDS_UTMPX
|
||||
@ -670,9 +773,11 @@ do_pre_login(Session *s)
|
||||
* This is called to fork and execute a command. If another command is
|
||||
* to be forced, execute that instead.
|
||||
*/
|
||||
void
|
||||
int
|
||||
do_exec(Session *s, const char *command)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (options.adm_forced_command) {
|
||||
original_command = command;
|
||||
command = options.adm_forced_command;
|
||||
@ -703,9 +808,9 @@ do_exec(Session *s, const char *command)
|
||||
}
|
||||
#endif
|
||||
if (s->ttyfd != -1)
|
||||
do_exec_pty(s, command);
|
||||
ret = do_exec_pty(s, command);
|
||||
else
|
||||
do_exec_no_pty(s, command);
|
||||
ret = do_exec_no_pty(s, command);
|
||||
|
||||
original_command = NULL;
|
||||
|
||||
@ -715,6 +820,8 @@ do_exec(Session *s, const char *command)
|
||||
* multiple copies of the login messages.
|
||||
*/
|
||||
buffer_clear(&loginmsg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* administrative, login(1)-like work */
|
||||
@ -1204,7 +1311,7 @@ do_rc_files(Session *s, const char *shell)
|
||||
|
||||
/* ignore _PATH_SSH_USER_RC for subsystems and admin forced commands */
|
||||
if (!s->is_subsystem && options.adm_forced_command == NULL &&
|
||||
!no_user_rc && (stat(_PATH_SSH_USER_RC, &st) >= 0)) {
|
||||
!no_user_rc && stat(_PATH_SSH_USER_RC, &st) >= 0) {
|
||||
snprintf(cmd, sizeof cmd, "%s -c '%s %s'",
|
||||
shell, _PATH_BSHELL, _PATH_SSH_USER_RC);
|
||||
if (debug_flag)
|
||||
@ -1540,6 +1647,7 @@ do_child(Session *s, const char *command)
|
||||
char *argv[ARGV_MAX];
|
||||
const char *shell, *shell0, *hostname = NULL;
|
||||
struct passwd *pw = s->pw;
|
||||
int r = 0;
|
||||
|
||||
/* remove hostkey from the child's memory */
|
||||
destroy_sensitive_data();
|
||||
@ -1655,12 +1763,16 @@ do_child(Session *s, const char *command)
|
||||
|
||||
/* Change current directory to the user's home directory. */
|
||||
if (chdir(pw->pw_dir) < 0) {
|
||||
fprintf(stderr, "Could not chdir to home directory %s: %s\n",
|
||||
pw->pw_dir, strerror(errno));
|
||||
/* Suppress missing homedir warning for chroot case */
|
||||
#ifdef HAVE_LOGIN_CAP
|
||||
if (login_getcapbool(lc, "requirehome", 0))
|
||||
exit(1);
|
||||
r = login_getcapbool(lc, "requirehome", 0);
|
||||
#endif
|
||||
if (r || options.chroot_directory == NULL)
|
||||
fprintf(stderr, "Could not chdir to home "
|
||||
"directory %s: %s\n", pw->pw_dir,
|
||||
strerror(errno));
|
||||
if (r)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
closefrom(STDERR_FILENO + 1);
|
||||
@ -1738,43 +1850,79 @@ do_child(Session *s, const char *command)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
session_unused(int id)
|
||||
{
|
||||
debug3("%s: session id %d unused", __func__, id);
|
||||
if (id >= options.max_sessions ||
|
||||
id >= sessions_nalloc) {
|
||||
fatal("%s: insane session id %d (max %d nalloc %d)",
|
||||
__func__, id, options.max_sessions, sessions_nalloc);
|
||||
}
|
||||
bzero(&sessions[id], sizeof(*sessions));
|
||||
sessions[id].self = id;
|
||||
sessions[id].used = 0;
|
||||
sessions[id].chanid = -1;
|
||||
sessions[id].ptyfd = -1;
|
||||
sessions[id].ttyfd = -1;
|
||||
sessions[id].ptymaster = -1;
|
||||
sessions[id].x11_chanids = NULL;
|
||||
sessions[id].next_unused = sessions_first_unused;
|
||||
sessions_first_unused = id;
|
||||
}
|
||||
|
||||
Session *
|
||||
session_new(void)
|
||||
{
|
||||
int i;
|
||||
static int did_init = 0;
|
||||
if (!did_init) {
|
||||
debug("session_new: init");
|
||||
for (i = 0; i < MAX_SESSIONS; i++) {
|
||||
sessions[i].used = 0;
|
||||
Session *s, *tmp;
|
||||
|
||||
if (sessions_first_unused == -1) {
|
||||
if (sessions_nalloc >= options.max_sessions)
|
||||
return NULL;
|
||||
debug2("%s: allocate (allocated %d max %d)",
|
||||
__func__, sessions_nalloc, options.max_sessions);
|
||||
tmp = xrealloc(sessions, sessions_nalloc + 1,
|
||||
sizeof(*sessions));
|
||||
if (tmp == NULL) {
|
||||
error("%s: cannot allocate %d sessions",
|
||||
__func__, sessions_nalloc + 1);
|
||||
return NULL;
|
||||
}
|
||||
did_init = 1;
|
||||
sessions = tmp;
|
||||
session_unused(sessions_nalloc++);
|
||||
}
|
||||
for (i = 0; i < MAX_SESSIONS; i++) {
|
||||
Session *s = &sessions[i];
|
||||
if (! s->used) {
|
||||
memset(s, 0, sizeof(*s));
|
||||
s->chanid = -1;
|
||||
s->ptyfd = -1;
|
||||
s->ttyfd = -1;
|
||||
s->used = 1;
|
||||
s->self = i;
|
||||
s->x11_chanids = NULL;
|
||||
debug("session_new: session %d", i);
|
||||
return s;
|
||||
}
|
||||
|
||||
if (sessions_first_unused >= sessions_nalloc ||
|
||||
sessions_first_unused < 0) {
|
||||
fatal("%s: insane first_unused %d max %d nalloc %d",
|
||||
__func__, sessions_first_unused, options.max_sessions,
|
||||
sessions_nalloc);
|
||||
}
|
||||
return NULL;
|
||||
|
||||
s = &sessions[sessions_first_unused];
|
||||
if (s->used) {
|
||||
fatal("%s: session %d already used",
|
||||
__func__, sessions_first_unused);
|
||||
}
|
||||
sessions_first_unused = s->next_unused;
|
||||
s->used = 1;
|
||||
s->next_unused = -1;
|
||||
debug("session_new: session %d", s->self);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static void
|
||||
session_dump(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_SESSIONS; i++) {
|
||||
for (i = 0; i < sessions_nalloc; i++) {
|
||||
Session *s = &sessions[i];
|
||||
debug("dump: used %d session %d %p channel %d pid %ld",
|
||||
|
||||
debug("dump: used %d next_unused %d session %d %p "
|
||||
"channel %d pid %ld",
|
||||
s->used,
|
||||
s->next_unused,
|
||||
s->self,
|
||||
s,
|
||||
s->chanid,
|
||||
@ -1804,7 +1952,7 @@ Session *
|
||||
session_by_tty(char *tty)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_SESSIONS; i++) {
|
||||
for (i = 0; i < sessions_nalloc; i++) {
|
||||
Session *s = &sessions[i];
|
||||
if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) {
|
||||
debug("session_by_tty: session %d tty %s", i, tty);
|
||||
@ -1820,10 +1968,11 @@ static Session *
|
||||
session_by_channel(int id)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_SESSIONS; i++) {
|
||||
for (i = 0; i < sessions_nalloc; i++) {
|
||||
Session *s = &sessions[i];
|
||||
if (s->used && s->chanid == id) {
|
||||
debug("session_by_channel: session %d channel %d", i, id);
|
||||
debug("session_by_channel: session %d channel %d",
|
||||
i, id);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@ -1837,7 +1986,7 @@ session_by_x11_channel(int id)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < MAX_SESSIONS; i++) {
|
||||
for (i = 0; i < sessions_nalloc; i++) {
|
||||
Session *s = &sessions[i];
|
||||
|
||||
if (s->x11_chanids == NULL || !s->used)
|
||||
@ -1860,7 +2009,7 @@ session_by_pid(pid_t pid)
|
||||
{
|
||||
int i;
|
||||
debug("session_by_pid: pid %ld", (long)pid);
|
||||
for (i = 0; i < MAX_SESSIONS; i++) {
|
||||
for (i = 0; i < sessions_nalloc; i++) {
|
||||
Session *s = &sessions[i];
|
||||
if (s->used && s->pid == pid)
|
||||
return s;
|
||||
@ -1916,7 +2065,8 @@ session_pty_req(Session *s)
|
||||
|
||||
/* Allocate a pty and open it. */
|
||||
debug("Allocating pty.");
|
||||
if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)))) {
|
||||
if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty,
|
||||
sizeof(s->tty)))) {
|
||||
if (s->term)
|
||||
xfree(s->term);
|
||||
s->term = NULL;
|
||||
@ -1969,8 +2119,7 @@ session_subsystem_req(Session *s)
|
||||
s->is_subsystem = SUBSYSTEM_EXT;
|
||||
}
|
||||
debug("subsystem: exec() %s", cmd);
|
||||
do_exec(s, cmd);
|
||||
success = 1;
|
||||
success = do_exec(s, cmd) == 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2013,19 +2162,19 @@ static int
|
||||
session_shell_req(Session *s)
|
||||
{
|
||||
packet_check_eom();
|
||||
do_exec(s, NULL);
|
||||
return 1;
|
||||
return do_exec(s, NULL) == 0;
|
||||
}
|
||||
|
||||
static int
|
||||
session_exec_req(Session *s)
|
||||
{
|
||||
u_int len;
|
||||
u_int len, success;
|
||||
|
||||
char *command = packet_get_string(&len);
|
||||
packet_check_eom();
|
||||
do_exec(s, command);
|
||||
success = do_exec(s, command) == 0;
|
||||
xfree(command);
|
||||
return 1;
|
||||
return success;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -2035,8 +2184,7 @@ session_break_req(Session *s)
|
||||
packet_get_int(); /* ignored */
|
||||
packet_check_eom();
|
||||
|
||||
if (s->ttyfd == -1 ||
|
||||
tcsendbreak(s->ttyfd, 0) < 0)
|
||||
if (s->ttyfd == -1 || tcsendbreak(s->ttyfd, 0) < 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@ -2081,7 +2229,7 @@ session_auth_agent_req(Session *s)
|
||||
{
|
||||
static int called = 0;
|
||||
packet_check_eom();
|
||||
if (no_agent_forwarding_flag) {
|
||||
if (no_agent_forwarding_flag || !options.allow_agent_forwarding) {
|
||||
debug("session_auth_agent_req: no_agent_forwarding_flag");
|
||||
return 0;
|
||||
}
|
||||
@ -2137,7 +2285,7 @@ session_input_channel_req(Channel *c, const char *rtype)
|
||||
}
|
||||
|
||||
void
|
||||
session_set_fds(Session *s, int fdin, int fdout, int fderr)
|
||||
session_set_fds(Session *s, int fdin, int fdout, int fderr, int is_tty)
|
||||
{
|
||||
if (!compat20)
|
||||
fatal("session_set_fds: called for proto != 2.0");
|
||||
@ -2150,8 +2298,7 @@ session_set_fds(Session *s, int fdin, int fdout, int fderr)
|
||||
channel_set_fds(s->chanid,
|
||||
fdout, fdin, fderr,
|
||||
fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
|
||||
1,
|
||||
CHAN_SES_WINDOW_DEFAULT);
|
||||
1, is_tty, CHAN_SES_WINDOW_DEFAULT);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2183,8 +2330,9 @@ session_pty_cleanup2(Session *s)
|
||||
* the pty cleanup, so that another process doesn't get this pty
|
||||
* while we're still cleaning up.
|
||||
*/
|
||||
if (close(s->ptymaster) < 0)
|
||||
error("close(s->ptymaster/%d): %s", s->ptymaster, strerror(errno));
|
||||
if (s->ptymaster != -1 && close(s->ptymaster) < 0)
|
||||
error("close(s->ptymaster/%d): %s",
|
||||
s->ptymaster, strerror(errno));
|
||||
|
||||
/* unlink pty from session */
|
||||
s->ttyfd = -1;
|
||||
@ -2344,7 +2492,6 @@ session_close(Session *s)
|
||||
xfree(s->auth_data);
|
||||
if (s->auth_proto)
|
||||
xfree(s->auth_proto);
|
||||
s->used = 0;
|
||||
if (s->env != NULL) {
|
||||
for (i = 0; i < s->num_env; i++) {
|
||||
xfree(s->env[i].name);
|
||||
@ -2353,6 +2500,7 @@ session_close(Session *s)
|
||||
xfree(s->env);
|
||||
}
|
||||
session_proctitle(s);
|
||||
session_unused(s->self);
|
||||
}
|
||||
|
||||
void
|
||||
@ -2416,7 +2564,7 @@ void
|
||||
session_destroy_all(void (*closefunc)(Session *))
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_SESSIONS; i++) {
|
||||
for (i = 0; i < sessions_nalloc; i++) {
|
||||
Session *s = &sessions[i];
|
||||
if (s->used) {
|
||||
if (closefunc != NULL)
|
||||
@ -2435,7 +2583,7 @@ session_tty_list(void)
|
||||
char *cp;
|
||||
|
||||
buf[0] = '\0';
|
||||
for (i = 0; i < MAX_SESSIONS; i++) {
|
||||
for (i = 0; i < sessions_nalloc; i++) {
|
||||
Session *s = &sessions[i];
|
||||
if (s->used && s->ttyfd != -1) {
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: session.h,v 1.29 2006/08/03 03:34:42 deraadt Exp $ */
|
||||
/* $OpenBSD: session.h,v 1.30 2008/05/08 12:21:16 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
@ -31,6 +31,7 @@ typedef struct Session Session;
|
||||
struct Session {
|
||||
int used;
|
||||
int self;
|
||||
int next_unused;
|
||||
struct passwd *pw;
|
||||
Authctxt *authctxt;
|
||||
pid_t pid;
|
||||
@ -65,6 +66,7 @@ void do_authenticated(Authctxt *);
|
||||
void do_cleanup(Authctxt *);
|
||||
|
||||
int session_open(Authctxt *, int);
|
||||
void session_unused(int);
|
||||
int session_input_channel_req(Channel *, const char *);
|
||||
void session_close_by_pid(pid_t, int);
|
||||
void session_close_by_channel(int, void *);
|
||||
|
140
sftp-client.c
140
sftp-client.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: sftp-client.c,v 1.81 2008/03/23 12:54:01 djm Exp $ */
|
||||
/* $OpenBSD: sftp-client.c,v 1.86 2008/06/26 06:10:09 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
||||
*
|
||||
@ -24,6 +24,9 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#ifdef HAVE_SYS_STATVFS_H
|
||||
#include <sys/statvfs.h>
|
||||
#endif
|
||||
#include "openbsd-compat/sys-queue.h"
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
# include <sys/stat.h>
|
||||
@ -65,7 +68,9 @@ struct sftp_conn {
|
||||
u_int num_requests;
|
||||
u_int version;
|
||||
u_int msg_id;
|
||||
#define SFTP_EXT_POSIX_RENAME 1
|
||||
#define SFTP_EXT_POSIX_RENAME 0x00000001
|
||||
#define SFTP_EXT_STATVFS 0x00000002
|
||||
#define SFTP_EXT_FSTATVFS 0x00000004
|
||||
u_int exts;
|
||||
};
|
||||
|
||||
@ -238,6 +243,57 @@ get_decode_stat(int fd, u_int expected_id, int quiet)
|
||||
return(a);
|
||||
}
|
||||
|
||||
static int
|
||||
get_decode_statvfs(int fd, struct sftp_statvfs *st, u_int expected_id,
|
||||
int quiet)
|
||||
{
|
||||
Buffer msg;
|
||||
u_int type, id, flag;
|
||||
|
||||
buffer_init(&msg);
|
||||
get_msg(fd, &msg);
|
||||
|
||||
type = buffer_get_char(&msg);
|
||||
id = buffer_get_int(&msg);
|
||||
|
||||
debug3("Received statvfs reply T:%u I:%u", type, id);
|
||||
if (id != expected_id)
|
||||
fatal("ID mismatch (%u != %u)", id, expected_id);
|
||||
if (type == SSH2_FXP_STATUS) {
|
||||
int status = buffer_get_int(&msg);
|
||||
|
||||
if (quiet)
|
||||
debug("Couldn't statvfs: %s", fx2txt(status));
|
||||
else
|
||||
error("Couldn't statvfs: %s", fx2txt(status));
|
||||
buffer_free(&msg);
|
||||
return -1;
|
||||
} else if (type != SSH2_FXP_EXTENDED_REPLY) {
|
||||
fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
|
||||
SSH2_FXP_EXTENDED_REPLY, type);
|
||||
}
|
||||
|
||||
bzero(st, sizeof(*st));
|
||||
st->f_bsize = buffer_get_int64(&msg);
|
||||
st->f_frsize = buffer_get_int64(&msg);
|
||||
st->f_blocks = buffer_get_int64(&msg);
|
||||
st->f_bfree = buffer_get_int64(&msg);
|
||||
st->f_bavail = buffer_get_int64(&msg);
|
||||
st->f_files = buffer_get_int64(&msg);
|
||||
st->f_ffree = buffer_get_int64(&msg);
|
||||
st->f_favail = buffer_get_int64(&msg);
|
||||
st->f_fsid = buffer_get_int64(&msg);
|
||||
flag = buffer_get_int64(&msg);
|
||||
st->f_namemax = buffer_get_int64(&msg);
|
||||
|
||||
st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0;
|
||||
st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0;
|
||||
|
||||
buffer_free(&msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sftp_conn *
|
||||
do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
|
||||
{
|
||||
@ -270,10 +326,27 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
|
||||
while (buffer_len(&msg) > 0) {
|
||||
char *name = buffer_get_string(&msg, NULL);
|
||||
char *value = buffer_get_string(&msg, NULL);
|
||||
int known = 0;
|
||||
|
||||
debug2("Init extension: \"%s\"", name);
|
||||
if (strcmp(name, "posix-rename@openssh.com") == 0)
|
||||
if (strcmp(name, "posix-rename@openssh.com") == 0 &&
|
||||
strcmp(value, "1") == 0) {
|
||||
exts |= SFTP_EXT_POSIX_RENAME;
|
||||
known = 1;
|
||||
} else if (strcmp(name, "statvfs@openssh.com") == 0 &&
|
||||
strcmp(value, "2") == 0) {
|
||||
exts |= SFTP_EXT_STATVFS;
|
||||
known = 1;
|
||||
} if (strcmp(name, "fstatvfs@openssh.com") == 0 &&
|
||||
strcmp(value, "2") == 0) {
|
||||
exts |= SFTP_EXT_FSTATVFS;
|
||||
known = 1;
|
||||
}
|
||||
if (known) {
|
||||
debug2("Server supports extension \"%s\" revision %s",
|
||||
name, value);
|
||||
} else {
|
||||
debug2("Unrecognised server extension \"%s\"", name);
|
||||
}
|
||||
xfree(name);
|
||||
xfree(value);
|
||||
}
|
||||
@ -749,6 +822,60 @@ do_readlink(struct sftp_conn *conn, char *path)
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
|
||||
int quiet)
|
||||
{
|
||||
Buffer msg;
|
||||
u_int id;
|
||||
|
||||
if ((conn->exts & SFTP_EXT_STATVFS) == 0) {
|
||||
error("Server does not support statvfs@openssh.com extension");
|
||||
return -1;
|
||||
}
|
||||
|
||||
id = conn->msg_id++;
|
||||
|
||||
buffer_init(&msg);
|
||||
buffer_clear(&msg);
|
||||
buffer_put_char(&msg, SSH2_FXP_EXTENDED);
|
||||
buffer_put_int(&msg, id);
|
||||
buffer_put_cstring(&msg, "statvfs@openssh.com");
|
||||
buffer_put_cstring(&msg, path);
|
||||
send_msg(conn->fd_out, &msg);
|
||||
buffer_free(&msg);
|
||||
|
||||
return get_decode_statvfs(conn->fd_in, st, id, quiet);
|
||||
}
|
||||
|
||||
#ifdef notyet
|
||||
int
|
||||
do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len,
|
||||
struct sftp_statvfs *st, int quiet)
|
||||
{
|
||||
Buffer msg;
|
||||
u_int id;
|
||||
|
||||
if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) {
|
||||
error("Server does not support fstatvfs@openssh.com extension");
|
||||
return -1;
|
||||
}
|
||||
|
||||
id = conn->msg_id++;
|
||||
|
||||
buffer_init(&msg);
|
||||
buffer_clear(&msg);
|
||||
buffer_put_char(&msg, SSH2_FXP_EXTENDED);
|
||||
buffer_put_int(&msg, id);
|
||||
buffer_put_cstring(&msg, "fstatvfs@openssh.com");
|
||||
buffer_put_string(&msg, handle, handle_len);
|
||||
send_msg(conn->fd_out, &msg);
|
||||
buffer_free(&msg);
|
||||
|
||||
return get_decode_statvfs(conn->fd_in, st, id, quiet);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len,
|
||||
char *handle, u_int handle_len)
|
||||
@ -793,7 +920,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
|
||||
if (a == NULL)
|
||||
return(-1);
|
||||
|
||||
/* XXX: should we preserve set[ug]id? */
|
||||
/* Do not preserve set[ug]id here, as we do not preserve ownership */
|
||||
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
|
||||
mode = a->perm & 0777;
|
||||
else
|
||||
@ -1096,7 +1223,8 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
|
||||
len = 0;
|
||||
else do
|
||||
len = read(local_fd, data, conn->transfer_buflen);
|
||||
while ((len == -1) && (errno == EINTR || errno == EAGAIN));
|
||||
while ((len == -1) &&
|
||||
(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
|
||||
|
||||
if (len == -1)
|
||||
fatal("Couldn't read from \"%s\": %s", local_path,
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: sftp-client.h,v 1.15 2008/01/11 07:22:28 chl Exp $ */
|
||||
/* $OpenBSD: sftp-client.h,v 1.17 2008/06/08 20:15:29 dtucker Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
||||
@ -29,6 +29,24 @@ struct SFTP_DIRENT {
|
||||
Attrib a;
|
||||
};
|
||||
|
||||
/*
|
||||
* Used for statvfs responses on the wire from the server, because the
|
||||
* server's native format may be larger than the client's.
|
||||
*/
|
||||
struct sftp_statvfs {
|
||||
u_int64_t f_bsize;
|
||||
u_int64_t f_frsize;
|
||||
u_int64_t f_blocks;
|
||||
u_int64_t f_bfree;
|
||||
u_int64_t f_bavail;
|
||||
u_int64_t f_files;
|
||||
u_int64_t f_ffree;
|
||||
u_int64_t f_favail;
|
||||
u_int64_t f_fsid;
|
||||
u_int64_t f_flag;
|
||||
u_int64_t f_namemax;
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialise a SSH filexfer connection. Returns NULL on error or
|
||||
* a pointer to a initialized sftp_conn struct on success.
|
||||
@ -70,6 +88,9 @@ int do_fsetstat(struct sftp_conn *, char *, u_int, Attrib *);
|
||||
/* Canonicalise 'path' - caller must free result */
|
||||
char *do_realpath(struct sftp_conn *, char *);
|
||||
|
||||
/* Get statistics for filesystem hosting file at "path" */
|
||||
int do_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int);
|
||||
|
||||
/* Rename 'oldpath' to 'newpath' */
|
||||
int do_rename(struct sftp_conn *, char *, char *);
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user