Vendor import of OpenSSH 5.1p1

This commit is contained in:
Dag-Erling Smørgrav 2008-07-23 09:33:08 +00:00
parent d4033b6b6f
commit 5521539314
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor-crypto/openssh/dist/; revision=180750
137 changed files with 7932 additions and 4294 deletions

861
ChangeLog
View File

@ -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 $

View File

@ -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
View 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
View 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
View File

@ -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 $

1780
RFC.nroff

File diff suppressed because it is too large Load Diff

421
addrmatch.c Normal file
View 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;
}

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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);
}

View File

@ -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
View File

@ -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
View File

@ -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 *,

View File

@ -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

View File

@ -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",

View File

@ -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);

View File

@ -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
View File

@ -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;
}

View File

@ -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.
*/

View File

@ -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 *);

View File

@ -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);

View File

@ -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)

View File

@ -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 *);

File diff suppressed because it is too large Load Diff

View File

@ -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 *);

View File

@ -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
View File

@ -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

View File

@ -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 \

View File

@ -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 $

View File

@ -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

View File

@ -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!"

View 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

View File

@ -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

View File

@ -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*

View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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;
}

View File

@ -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.
*/

View File

@ -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

View File

@ -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"

View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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;

View File

@ -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
View File

@ -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
View File

@ -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
View 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
View 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

View File

@ -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;

View File

@ -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 */

View File

@ -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)

View File

@ -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
View 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
View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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 */

View File

@ -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

View File

@ -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"

View 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

View 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

View File

@ -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;

View File

@ -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
View 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 */

View File

@ -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

View File

@ -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"

View File

@ -44,6 +44,7 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#if 0
int

View File

@ -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)

View File

@ -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

View File

@ -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
View File

@ -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);

View File

@ -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 *);

View File

@ -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 */

View File

@ -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;

View File

@ -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
View 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
View 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
View 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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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)

View File

@ -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");
}

View File

@ -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 */

View File

@ -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
View File

@ -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) {

View File

@ -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 *);

View File

@ -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,

View File

@ -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