Upgrade to OpenSSH 5.6p1.

This commit is contained in:
Dag-Erling Smørgrav 2010-11-11 11:46:19 +00:00
commit e2f6069c09
68 changed files with 3251 additions and 994 deletions

View File

@ -1,3 +1,522 @@
20100823
- (djm) Release OpenSSH-5.6p1
20100816
- (dtucker) [configure.ac openbsd-compat/Makefile.in
openbsd-compat/openbsd-compat.h openbsd-compat/strptime.c] Add strptime to
the compat library which helps on platforms like old IRIX. Based on work
by djm, tested by Tom Christensen.
- OpenBSD CVS Sync
- djm@cvs.openbsd.org 2010/08/12 21:49:44
[ssh.c]
close any extra file descriptors inherited from parent at start and
reopen stdin/stdout to /dev/null when forking for ControlPersist.
prevents tools that fork and run a captive ssh for communication from
failing to exit when the ssh completes while they wait for these fds to
close. The inherited fds may persist arbitrarily long if a background
mux master has been started by ControlPersist. cvs and scp were effected
by this.
"please commit" markus@
- (djm) [regress/README.regress] typo
20100812
- (tim) [regress/login-timeout.sh regress/reconfigure.sh regress/reexec.sh
regress/test-exec.sh] Under certain conditions when testing with sudo
tests would fail because the pidfile could not be read by a regular user.
"cat: cannot open ...../regress/pidfile: Permission denied (error 13)"
Make sure cat is run by $SUDO. no objection from me. djm@
- (tim) [auth.c] add cast to quiet compiler. Change only affects SVR5 systems.
20100809
- (djm) bz#1561: don't bother setting IFF_UP on tun(4) device if it is
already set. Makes FreeBSD user openable tunnels useful; patch from
richard.burakowski+ossh AT mrburak.net, ok dtucker@
- (dtucker) bug #1530: strip trailing ":" from hostname in ssh-copy-id.
based in part on a patch from Colin Watson, ok djm@
20100809
- OpenBSD CVS Sync
- djm@cvs.openbsd.org 2010/08/08 16:26:42
[version.h]
crank to 5.6
- (djm) [README contrib/caldera/openssh.spec contrib/redhat/openssh.spec]
[contrib/suse/openssh.spec] Crank version numbers
20100805
- OpenBSD CVS Sync
- djm@cvs.openbsd.org 2010/08/04 05:37:01
[ssh.1 ssh_config.5 sshd.8]
Remove mentions of weird "addr/port" alternate address format for IPv6
addresses combinations. It hasn't worked for ages and we have supported
the more commen "[addr]:port" format for a long time. ok jmc@ markus@
- djm@cvs.openbsd.org 2010/08/04 05:40:39
[PROTOCOL.certkeys ssh-keygen.c]
tighten the rules for certificate encoding by requiring that options
appear in lexical order and make our ssh-keygen comply. ok markus@
- djm@cvs.openbsd.org 2010/08/04 05:42:47
[auth.c auth2-hostbased.c authfile.c authfile.h ssh-keysign.8]
[ssh-keysign.c ssh.c]
enable certificates for hostbased authentication, from Iain Morgan;
"looks ok" markus@
- djm@cvs.openbsd.org 2010/08/04 05:49:22
[authfile.c]
commited the wrong version of the hostbased certificate diff; this
version replaces some strlc{py,at} verbosity with xasprintf() at
the request of markus@
- djm@cvs.openbsd.org 2010/08/04 06:07:11
[ssh-keygen.1 ssh-keygen.c]
Support CA keys in PKCS#11 tokens; feedback and ok markus@
- djm@cvs.openbsd.org 2010/08/04 06:08:40
[ssh-keysign.c]
clean for -Wuninitialized (Id sync only; portable had this change)
- djm@cvs.openbsd.org 2010/08/05 13:08:42
[channels.c]
Fix a trio of bugs in the local/remote window calculation for datagram
data channels (i.e. TunnelForward):
Calculate local_consumed correctly in channel_handle_wfd() by measuring
the delta to buffer_len(c->output) from when we start to when we finish.
The proximal problem here is that the output_filter we use in portable
modified the length of the dequeued datagram (to futz with the headers
for !OpenBSD).
In channel_output_poll(), don't enqueue datagrams that won't fit in the
peer's advertised packet size (highly unlikely to ever occur) or which
won't fit in the peer's remaining window (more likely).
In channel_input_data(), account for the 4-byte string header in
datagram packets that we accept from the peer and enqueue in c->output.
report, analysis and testing 2/3 cases from wierbows AT us.ibm.com;
"looks good" markus@
20100803
- (dtucker) [monitor.c] Bug #1795: Initialize the values to be returned from
PAM to sane values in case the PAM method doesn't write to them. Spotted by
Bitman Zhou, ok djm@.
- OpenBSD CVS Sync
- djm@cvs.openbsd.org 2010/07/16 04:45:30
[ssh-keygen.c]
avoid bogus compiler warning
- djm@cvs.openbsd.org 2010/07/16 14:07:35
[ssh-rsa.c]
more timing paranoia - compare all parts of the expected decrypted
data before returning. AFAIK not exploitable in the SSH protocol.
"groovy" deraadt@
- djm@cvs.openbsd.org 2010/07/19 03:16:33
[sftp-client.c]
bz#1797: fix swapped args in upload_dir_internal(), breaking recursive
upload depth checks and causing verbose printing of transfers to always
be turned on; patch from imorgan AT nas.nasa.gov
- djm@cvs.openbsd.org 2010/07/19 09:15:12
[clientloop.c readconf.c readconf.h ssh.c ssh_config.5]
add a "ControlPersist" option that automatically starts a background
ssh(1) multiplex master when connecting. This connection can stay alive
indefinitely, or can be set to automatically close after a user-specified
duration of inactivity. bz#1330 - patch by dwmw2 AT infradead.org, but
further hacked on by wmertens AT cisco.com, apb AT cequrux.com,
martin-mindrot-bugzilla AT earth.li and myself; "looks ok" markus@
- djm@cvs.openbsd.org 2010/07/21 02:10:58
[misc.c]
sync timingsafe_bcmp() with the one dempsky@ committed to sys/lib/libkern
- dtucker@cvs.openbsd.org 2010/07/23 08:49:25
[ssh.1]
Ciphers is documented in ssh_config(5) these days
20100819
- (dtucker) [contrib/ssh-copy-ud.1] Bug #1786: update ssh-copy-id.1 with more
details about its behaviour WRT existing directories. Patch from
asguthrie at gmail com, ok djm.
20100716
- (djm) OpenBSD CVS Sync
- djm@cvs.openbsd.org 2010/07/02 04:32:44
[misc.c]
unbreak strdelim() skipping past quoted strings, e.g.
AllowUsers "blah blah" blah
was broken; report and fix in bz#1757 from bitman.zhou AT centrify.com
ok dtucker;
- djm@cvs.openbsd.org 2010/07/12 22:38:52
[ssh.c]
Make ExitOnForwardFailure work with fork-after-authentication ("ssh -f")
for protocol 2. ok markus@
- djm@cvs.openbsd.org 2010/07/12 22:41:13
[ssh.c ssh_config.5]
expand %h to the hostname in ssh_config Hostname options. While this
sounds useless, it is actually handy for working with unqualified
hostnames:
Host *.*
Hostname %h
Host *
Hostname %h.example.org
"I like it" markus@
- djm@cvs.openbsd.org 2010/07/13 11:52:06
[auth-rsa.c channels.c jpake.c key.c misc.c misc.h monitor.c]
[packet.c ssh-rsa.c]
implement a timing_safe_cmp() function to compare memory without leaking
timing information by short-circuiting like memcmp() and use it for
some of the more sensitive comparisons (though nothing high-value was
readily attackable anyway); "looks ok" markus@
- djm@cvs.openbsd.org 2010/07/13 23:13:16
[auth-rsa.c channels.c jpake.c key.c misc.c misc.h monitor.c packet.c]
[ssh-rsa.c]
s/timing_safe_cmp/timingsafe_bcmp/g
- jmc@cvs.openbsd.org 2010/07/14 17:06:58
[ssh.1]
finally ssh synopsis looks nice again! this commit just removes a ton of
hacks we had in place to make it work with old groff;
- schwarze@cvs.openbsd.org 2010/07/15 21:20:38
[ssh-keygen.1]
repair incorrect block nesting, which screwed up indentation;
problem reported and fix OK by jmc@
20100714
- (tim) [contrib/redhat/openssh.spec] Bug 1796: Test for skip_x11_askpass
(line 77) should have been for no_x11_askpass.
20100702
- (djm) OpenBSD CVS Sync
- jmc@cvs.openbsd.org 2010/06/26 00:57:07
[ssh_config.5]
tweak previous;
- djm@cvs.openbsd.org 2010/06/26 23:04:04
[ssh.c]
oops, forgot to #include <canohost.h>; spotted and patch from chl@
- djm@cvs.openbsd.org 2010/06/29 23:15:30
[ssh-keygen.1 ssh-keygen.c]
allow import (-i) and export (-e) of PEM and PKCS#8 encoded keys;
bz#1749; ok markus@
- djm@cvs.openbsd.org 2010/06/29 23:16:46
[auth2-pubkey.c sshd_config.5]
allow key options (command="..." and friends) in AuthorizedPrincipals;
ok markus@
- jmc@cvs.openbsd.org 2010/06/30 07:24:25
[ssh-keygen.1]
tweak previous;
- jmc@cvs.openbsd.org 2010/06/30 07:26:03
[ssh-keygen.c]
sort usage();
- jmc@cvs.openbsd.org 2010/06/30 07:28:34
[sshd_config.5]
tweak previous;
- millert@cvs.openbsd.org 2010/07/01 13:06:59
[scp.c]
Fix a longstanding problem where if you suspend scp at the
password/passphrase prompt the terminal mode is not restored.
OK djm@
- phessler@cvs.openbsd.org 2010/06/27 19:19:56
[regress/Makefile]
fix how we run the tests so we can successfully use SUDO='sudo -E'
in our env
- djm@cvs.openbsd.org 2010/06/29 23:59:54
[cert-userkey.sh]
regress tests for key options in AuthorizedPrincipals
20100627
- (tim) [openbsd-compat/port-uw.c] Reorder includes. auth-options.h now needs
key.h.
20100626
- (djm) OpenBSD CVS Sync
- djm@cvs.openbsd.org 2010/05/21 05:00:36
[misc.c]
colon() returns char*, so s/return (0)/return NULL/
- markus@cvs.openbsd.org 2010/06/08 21:32:19
[ssh-pkcs11.c]
check length of value returned C_GetAttributValue for != 0
from mdrtbugzilla@codefive.co.uk; bugzilla #1773; ok dtucker@
- djm@cvs.openbsd.org 2010/06/17 07:07:30
[mux.c]
Correct sizing of object to be allocated by calloc(), replacing
sizeof(state) with sizeof(*state). This worked by accident since
the struct contained a single int at present, but could have broken
in the future. patch from hyc AT symas.com
- djm@cvs.openbsd.org 2010/06/18 00:58:39
[sftp.c]
unbreak ls in working directories that contains globbing characters in
their pathnames. bz#1655 reported by vgiffin AT apple.com
- djm@cvs.openbsd.org 2010/06/18 03:16:03
[session.c]
Missing check for chroot_director == "none" (we already checked against
NULL); bz#1564 from Jan.Pechanec AT Sun.COM
- djm@cvs.openbsd.org 2010/06/18 04:43:08
[sftp-client.c]
fix memory leak in do_realpath() error path; bz#1771, patch from
anicka AT suse.cz
- djm@cvs.openbsd.org 2010/06/22 04:22:59
[servconf.c sshd_config.5]
expose some more sshd_config options inside Match blocks:
AuthorizedKeysFile AuthorizedPrincipalsFile
HostbasedUsesNameFromPacketOnly PermitTunnel
bz#1764; feedback from imorgan AT nas.nasa.gov; ok dtucker@
- djm@cvs.openbsd.org 2010/06/22 04:32:06
[ssh-keygen.c]
standardise error messages when attempting to open private key
files to include "progname: filename: error reason"
bz#1783; ok dtucker@
- djm@cvs.openbsd.org 2010/06/22 04:49:47
[auth.c]
queue auth debug messages for bad ownership or permissions on the user's
keyfiles. These messages will be sent after the user has successfully
authenticated (where our client will display them with LogLevel=debug).
bz#1554; ok dtucker@
- djm@cvs.openbsd.org 2010/06/22 04:54:30
[ssh-keyscan.c]
replace verbose and overflow-prone Linebuf code with read_keyfile_line()
based on patch from joachim AT joachimschipper.nl; bz#1565; ok dtucker@
- djm@cvs.openbsd.org 2010/06/22 04:59:12
[session.c]
include the user name on "subsystem request for ..." log messages;
bz#1571; ok dtucker@
- djm@cvs.openbsd.org 2010/06/23 02:59:02
[ssh-keygen.c]
fix printing of extensions in v01 certificates that I broke in r1.190
- djm@cvs.openbsd.org 2010/06/25 07:14:46
[channels.c mux.c readconf.c readconf.h ssh.h]
bz#1327: remove hardcoded limit of 100 permitopen clauses and port
forwards per direction; ok markus@ stevesk@
- djm@cvs.openbsd.org 2010/06/25 07:20:04
[channels.c session.c]
bz#1750: fix requirement for /dev/null inside ChrootDirectory for
internal-sftp accidentally introduced in r1.253 by removing the code
that opens and dup /dev/null to stderr and modifying the channels code
to read stderr but discard it instead; ok markus@
- djm@cvs.openbsd.org 2010/06/25 08:46:17
[auth1.c auth2-none.c]
skip the initial check for access with an empty password when
PermitEmptyPasswords=no; bz#1638; ok markus@
- djm@cvs.openbsd.org 2010/06/25 23:10:30
[ssh.c]
log the hostname and address that we connected to at LogLevel=verbose
after authentication is successful to mitigate "phishing" attacks by
servers with trusted keys that accept authentication silently and
automatically before presenting fake password/passphrase prompts;
"nice!" markus@
- djm@cvs.openbsd.org 2010/06/25 23:10:30
[ssh.c]
log the hostname and address that we connected to at LogLevel=verbose
after authentication is successful to mitigate "phishing" attacks by
servers with trusted keys that accept authentication silently and
automatically before presenting fake password/passphrase prompts;
"nice!" markus@
20100622
- (djm) [loginrec.c] crank LINFO_NAMESIZE (username length) to 512
bz#1579; ok dtucker
20100618
- (djm) [contrib/ssh-copy-id] Update key file explicitly under ~
rather than assuming that $CWD == $HOME. bz#1500, patch from
timothy AT gelter.com
20100617
- (tim) [contrib/cygwin/README] Remove a reference to the obsolete
minires-devel package, and to add the reference to the libedit-devel
package since CYgwin now provides libedit. Patch from Corinna Vinschen.
20100521
- (djm) OpenBSD CVS Sync
- djm@cvs.openbsd.org 2010/05/07 11:31:26
[regress/Makefile regress/cert-userkey.sh]
regress tests for AuthorizedPrincipalsFile and "principals=" key option.
feedback and ok markus@
- djm@cvs.openbsd.org 2010/05/11 02:58:04
[auth-rsa.c]
don't accept certificates marked as "cert-authority" here; ok markus@
- djm@cvs.openbsd.org 2010/05/14 00:47:22
[ssh-add.c]
check that the certificate matches the corresponding private key before
grafting it on
- djm@cvs.openbsd.org 2010/05/14 23:29:23
[channels.c channels.h mux.c ssh.c]
Pause the mux channel while waiting for reply from aynch callbacks.
Prevents misordering of replies if new requests arrive while waiting.
Extend channel open confirm callback to allow signalling failure
conditions as well as success. Use this to 1) fix a memory leak, 2)
start using the above pause mechanism and 3) delay sending a success/
failure message on mux slave session open until we receive a reply from
the server.
motivated by and with feedback from markus@
- markus@cvs.openbsd.org 2010/05/16 12:55:51
[PROTOCOL.mux clientloop.h mux.c readconf.c readconf.h ssh.1 ssh.c]
mux support for remote forwarding with dynamic port allocation,
use with
LPORT=`ssh -S muxsocket -R0:localhost:25 -O forward somehost`
feedback and ok djm@
- djm@cvs.openbsd.org 2010/05/20 11:25:26
[auth2-pubkey.c]
fix logspam when key options (from="..." especially) deny non-matching
keys; reported by henning@ also bz#1765; ok markus@ dtucker@
- djm@cvs.openbsd.org 2010/05/20 23:46:02
[PROTOCOL.certkeys auth-options.c ssh-keygen.c]
Move the permit-* options to the non-critical "extensions" field for v01
certificates. The logic is that if another implementation fails to
implement them then the connection just loses features rather than fails
outright.
ok markus@
20100511
- (dtucker) [Makefile.in] Bug #1770: Link libopenbsd-compat twice to solve
circular dependency problem on old or odd platforms. From Tom Lane, ok
djm@.
- (djm) [openbsd-compat/openssl-compat.h] Fix build breakage on older
libcrypto by defining OPENSSL_[DR]SA_MAX_MODULUS_BITS if they aren't
already. ok dtucker@
20100510
- OpenBSD CVS Sync
- djm@cvs.openbsd.org 2010/04/23 01:47:41
[ssh-keygen.c]
bz#1740: display a more helpful error message when $HOME is
inaccessible while trying to create .ssh directory. Based on patch
from jchadima AT redhat.com; ok dtucker@
- djm@cvs.openbsd.org 2010/04/23 22:27:38
[mux.c]
set "detach_close" flag when registering channel cleanup callbacks.
This causes the channel to close normally when its fds close and
hangs when terminating a mux slave using ~. bz#1758; ok markus@
- djm@cvs.openbsd.org 2010/04/23 22:42:05
[session.c]
set stderr to /dev/null for subsystems rather than just closing it.
avoids hangs if a subsystem or shell initialisation writes to stderr.
bz#1750; ok markus@
- djm@cvs.openbsd.org 2010/04/23 22:48:31
[ssh-keygen.c]
refuse to generate keys longer than OPENSSL_[RD]SA_MAX_MODULUS_BITS,
since we would refuse to use them anyway. bz#1516; ok dtucker@
- djm@cvs.openbsd.org 2010/04/26 22:28:24
[sshconnect2.c]
bz#1502: authctxt.success is declared as an int, but passed by
reference to function that accepts sig_atomic_t*. Convert it to
the latter; ok markus@ dtucker@
- djm@cvs.openbsd.org 2010/05/01 02:50:50
[PROTOCOL.certkeys]
typo; jmeltzer@
- dtucker@cvs.openbsd.org 2010/05/05 04:22:09
[sftp.c]
restore mput and mget which got lost in the tab-completion changes.
found by Kenneth Whitaker, ok djm@
- djm@cvs.openbsd.org 2010/05/07 11:30:30
[auth-options.c auth-options.h auth.c auth.h auth2-pubkey.c]
[key.c servconf.c servconf.h sshd.8 sshd_config.5]
add some optional indirection to matching of principal names listed
in certificates. Currently, a certificate must include the a user's name
to be accepted for authentication. This change adds the ability to
specify a list of certificate principal names that are acceptable.
When authenticating using a CA trusted through ~/.ssh/authorized_keys,
this adds a new principals="name1[,name2,...]" key option.
For CAs listed through sshd_config's TrustedCAKeys option, a new config
option "AuthorizedPrincipalsFile" specifies a per-user file containing
the list of acceptable names.
If either option is absent, the current behaviour of requiring the
username to appear in principals continues to apply.
These options are useful for role accounts, disjoint account namespaces
and "user@realm"-style naming policies in certificates.
feedback and ok markus@
- jmc@cvs.openbsd.org 2010/05/07 12:49:17
[sshd_config.5]
tweak previous;
20100423
- (dtucker) [configure.ac] Bug #1756: Check for the existence of a lib64 dir
in the openssl install directory (some newer openssl versions do this on at
least some amd64 platforms).
20100418
- OpenBSD CVS Sync
- jmc@cvs.openbsd.org 2010/04/16 06:45:01
[ssh_config.5]
tweak previous; ok djm
- jmc@cvs.openbsd.org 2010/04/16 06:47:04
[ssh-keygen.1 ssh-keygen.c]
tweak previous; ok djm
- djm@cvs.openbsd.org 2010/04/16 21:14:27
[sshconnect.c]
oops, %r => remote username, not %u
- djm@cvs.openbsd.org 2010/04/16 01:58:45
[regress/cert-hostkey.sh regress/cert-userkey.sh]
regression tests for v01 certificate format
includes interop tests for v00 certs
- (dtucker) [contrib/aix/buildbff.sh] Fix creation of ssh_prng_cmds.default
file.
20100416
- (djm) Release openssh-5.5p1
- OpenBSD CVS Sync
- djm@cvs.openbsd.org 2010/03/26 03:13:17
[bufaux.c]
allow buffer_get_int_ret/buffer_get_int64_ret to take a NULL pointer
argument to allow skipping past values in a buffer
- jmc@cvs.openbsd.org 2010/03/26 06:54:36
[ssh.1]
tweak previous;
- jmc@cvs.openbsd.org 2010/03/27 14:26:55
[ssh_config.5]
tweak previous; ok dtucker
- djm@cvs.openbsd.org 2010/04/10 00:00:16
[ssh.c]
bz#1746 - suppress spurious tty warning when using -O and stdin
is not a tty; ok dtucker@ markus@
- djm@cvs.openbsd.org 2010/04/10 00:04:30
[sshconnect.c]
fix terminology: we didn't find a certificate in known_hosts, we found
a CA key
- djm@cvs.openbsd.org 2010/04/10 02:08:44
[clientloop.c]
bz#1698: kill channel when pty allocation requests fail. Fixed
stuck client if the server refuses pty allocation.
ok dtucker@ "think so" markus@
- djm@cvs.openbsd.org 2010/04/10 02:10:56
[sshconnect2.c]
show the key type that we are offering in debug(), helps distinguish
between certs and plain keys as the path to the private key is usually
the same.
- djm@cvs.openbsd.org 2010/04/10 05:48:16
[mux.c]
fix NULL dereference; from matthew.haub AT alumni.adelaide.edu.au
- djm@cvs.openbsd.org 2010/04/14 22:27:42
[ssh_config.5 sshconnect.c]
expand %r => remote username in ssh_config:ProxyCommand;
ok deraadt markus
- markus@cvs.openbsd.org 2010/04/15 20:32:55
[ssh-pkcs11.c]
retry lookup for private key if there's no matching key with CKA_SIGN
attribute enabled; this fixes fixes MuscleCard support (bugzilla #1736)
ok djm@
- djm@cvs.openbsd.org 2010/04/16 01:47:26
[PROTOCOL.certkeys auth-options.c auth-options.h auth-rsa.c]
[auth2-pubkey.c authfd.c key.c key.h myproposal.h ssh-add.c]
[ssh-agent.c ssh-dss.c ssh-keygen.1 ssh-keygen.c ssh-rsa.c]
[sshconnect.c sshconnect2.c sshd.c]
revised certificate format ssh-{dss,rsa}-cert-v01@openssh.com with the
following changes:
move the nonce field to the beginning of the certificate where it can
better protect against chosen-prefix attacks on the signature hash
Rename "constraints" field to "critical options"
Add a new non-critical "extensions" field
Add a serial number
The older format is still support for authentication and cert generation
(use "ssh-keygen -t v00 -s ca_key ..." to generate a v00 certificate)
ok markus@
20100410
- (dtucker) [configure.ac] Put the check for the existence of getaddrinfo
back so we disable the IPv6 tests if we don't have it.

View File

@ -16,7 +16,7 @@ These protocol extensions build on the simple public key authentication
system already in SSH to allow certificate-based authentication.
The certificates used are not traditional X.509 certificates, with
numerous options and complex encoding rules, but something rather
more minimal: a key, some identity information and usage constraints
more minimal: a key, some identity information and usage options
that have been signed with some other trusted key.
A sshd server may be configured to allow authentication via certified
@ -27,7 +27,7 @@ of acceptance of certified host keys, by adding a similar ability
to specify CA keys in ~/.ssh/known_hosts.
Certified keys are represented using two new key types:
ssh-rsa-cert-v00@openssh.com and ssh-dss-cert-v00@openssh.com that
ssh-rsa-cert-v01@openssh.com and ssh-dss-cert-v01@openssh.com that
include certification information along with the public key that is used
to sign challenges. ssh-keygen performs the CA signing operation.
@ -47,7 +47,7 @@ in RFC4252 section 7.
New public key formats
----------------------
The ssh-rsa-cert-v00@openssh.com and ssh-dss-cert-v00@openssh.com key
The ssh-rsa-cert-v01@openssh.com and ssh-dss-cert-v01@openssh.com key
types take a similar high-level format (note: data types and
encoding are as per RFC4251 section 5). The serialised wire encoding of
these certificates is also used for storing them on disk.
@ -57,42 +57,55 @@ these certificates is also used for storing them on disk.
RSA certificate
string "ssh-rsa-cert-v00@openssh.com"
string "ssh-rsa-cert-v01@openssh.com"
string nonce
mpint e
mpint n
uint64 serial
uint32 type
string key id
string valid principals
uint64 valid after
uint64 valid before
string constraints
string nonce
string critical options
string extensions
string reserved
string signature key
string signature
DSA certificate
string "ssh-dss-cert-v00@openssh.com"
string "ssh-dss-cert-v01@openssh.com"
string nonce
mpint p
mpint q
mpint g
mpint y
uint64 serial
uint32 type
string key id
string valid principals
uint64 valid after
uint64 valid before
string constraints
string nonce
string critical options
string extensions
string reserved
string signature key
string signature
The nonce field is a CA-provided random bitstring of arbitrary length
(but typically 16 or 32 bytes) included to make attacks that depend on
inducing collisions in the signature hash infeasible.
e and n are the RSA exponent and public modulus respectively.
p, q, g, y are the DSA parameters as described in FIPS-186-2.
serial is an optional certificate serial number set by the CA to
provide an abbreviated way to refer to certificates from that CA.
If a CA does not wish to number its certificates it must set this
field to zero.
type specifies whether this certificate is for identification of a user
or a host using a SSH_CERT_TYPE_... value.
@ -112,13 +125,15 @@ certificate. Each represents a time in seconds since 1970-01-01
00:00:00. A certificate is considered valid if:
valid after <= current time < valid before
constraints is a set of zero or more key constraints encoded as below.
criticial options is a set of zero or more key options encoded as
below. All such options are "critical" in the sense that an implementation
must refuse to authorise a key that has an unrecognised option.
The nonce field is a CA-provided random bitstring of arbitrary length
(but typically 16 or 32 bytes) included to make attacks that depend on
inducing collisions in the signature hash infeasible.
extensions is a set of zero or more optional extensions. These extensions
are not critical, and an implementation that encounters one that it does
not recognise may safely ignore it.
The reserved field is current unused and is ignored in this version of
The reserved field is currently unused and is ignored in this version of
the protocol.
signature key contains the CA key used to sign the certificate.
@ -132,22 +147,25 @@ up to, and including the signature key. Signatures are computed and
encoded according to the rules defined for the CA's public key algorithm
(RFC4253 section 6.6 for ssh-rsa and ssh-dss).
Constraints
-----------
Critical options
----------------
The constraints section of the certificate specifies zero or more
constraints on the certificates validity. The format of this field
The critical options section of the certificate specifies zero or more
options on the certificates validity. The format of this field
is a sequence of zero or more tuples:
string name
string data
The name field identifies the constraint and the data field encodes
constraint-specific information (see below). All constraints are
"critical", if an implementation does not recognise a constraint
Options must be lexically ordered by "name" if they appear in the
sequence.
The name field identifies the option and the data field encodes
option-specific information (see below). All options are
"critical", if an implementation does not recognise a option
then the validating party should refuse to accept the certificate.
The supported constraints and the contents and structure of their
The supported options and the contents and structure of their
data fields are:
Name Format Description
@ -157,37 +175,51 @@ force-command string Specifies a command that is executed
ssh command-line) whenever this key is
used for authentication.
permit-X11-forwarding empty Flag indicating that X11 forwarding
should be permitted. X11 forwarding will
be refused if this constraint is absent.
permit-agent-forwarding empty Flag indicating that agent forwarding
should be allowed. Agent forwarding
must not be permitted unless this
constraint is present.
permit-port-forwarding empty Flag indicating that port-forwarding
should be allowed. If this constraint is
not present then no port forwarding will
be allowed.
permit-pty empty Flag indicating that PTY allocation
should be permitted. In the absence of
this constraint PTY allocation will be
disabled.
permit-user-rc empty Flag indicating that execution of
~/.ssh/rc should be permitted. Execution
of this script will not be permitted if
this constraint is not present.
source-address string Comma-separated list of source addresses
from which this certificate is accepted
for authentication. Addresses are
specified in CIDR format (nn.nn.nn.nn/nn
or hhhh::hhhh/nn).
If this constraint is not present then
If this option is not present then
certificates may be presented from any
source address.
$OpenBSD: PROTOCOL.certkeys,v 1.3 2010/03/03 22:50:40 djm Exp $
Extensions
----------
The extensions section of the certificate specifies zero or more
non-critical certificate extensions. The encoding and ordering of
extensions in this field is identical to that of the critical options.
If an implementation does not recognise an extension, then it should
ignore it.
The supported extensions and the contents and structure of their data
fields are:
Name Format Description
-----------------------------------------------------------------------------
permit-X11-forwarding empty Flag indicating that X11 forwarding
should be permitted. X11 forwarding will
be refused if this option is absent.
permit-agent-forwarding empty Flag indicating that agent forwarding
should be allowed. Agent forwarding
must not be permitted unless this
option is present.
permit-port-forwarding empty Flag indicating that port-forwarding
should be allowed. If this option is
not present then no port forwarding will
be allowed.
permit-pty empty Flag indicating that PTY allocation
should be permitted. In the absence of
this option PTY allocation will be
disabled.
permit-user-rc empty Flag indicating that execution of
~/.ssh/rc should be permitted. Execution
of this script will not be permitted if
this option is not present.
$OpenBSD: PROTOCOL.certkeys,v 1.7 2010/08/04 05:40:39 djm Exp $

View File

@ -109,8 +109,14 @@ A client may request the master to establish a port forward:
forwarding type may be MUX_FWD_LOCAL, MUX_FWD_REMOTE, MUX_FWD_DYNAMIC.
A server may reply with a MUX_S_OK, a MUX_S_PERMISSION_DENIED or a
MUX_S_FAILURE.
A server may reply with a MUX_S_OK, a MUX_S_REMOTE_PORT, a
MUX_S_PERMISSION_DENIED or a MUX_S_FAILURE.
For dynamically allocated listen port the server replies with
uint32 MUX_S_REMOTE_PORT
uint32 client request id
uint32 allocated remote listen port
5. Requesting closure of port forwards
@ -178,6 +184,7 @@ The MUX_S_PERMISSION_DENIED and MUX_S_FAILURE include a reason:
#define MUX_S_EXIT_MESSAGE 0x80000004
#define MUX_S_ALIVE 0x80000005
#define MUX_S_SESSION_OPENED 0x80000006
#define MUX_S_REMOTE_PORT 0x80000007
#define MUX_FWD_LOCAL 1
#define MUX_FWD_REMOTE 2
@ -193,4 +200,4 @@ XXX server->client error/warning notifications
XXX port0 rfwd (need custom response message)
XXX send signals via mux
$OpenBSD: PROTOCOL.mux,v 1.1 2010/01/26 01:28:35 djm Exp $
$OpenBSD: PROTOCOL.mux,v 1.2 2010/05/16 12:55:51 markus Exp $

View File

@ -1,4 +1,4 @@
See http://www.openssh.com/txt/release-5.5 for the release notes.
See http://www.openssh.com/txt/release-5.6 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.73 2010/03/21 19:11:55 djm Exp $
$Id: README,v 1.74 2010/08/08 16:32:06 djm Exp $

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-options.c,v 1.49 2010/03/16 15:46:52 stevesk Exp $ */
/* $OpenBSD: auth-options.c,v 1.52 2010/05/20 23:46:02 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -27,10 +27,10 @@
#include "canohost.h"
#include "buffer.h"
#include "channels.h"
#include "auth-options.h"
#include "servconf.h"
#include "misc.h"
#include "key.h"
#include "auth-options.h"
#include "hostfile.h"
#include "auth.h"
#ifdef GSSAPI
@ -55,6 +55,9 @@ struct envstring *custom_environment = NULL;
/* "tunnel=" option. */
int forced_tun_device = -1;
/* "principals=" option. */
char *authorized_principals = NULL;
extern ServerOptions options;
void
@ -76,6 +79,10 @@ auth_clear_options(void)
xfree(forced_command);
forced_command = NULL;
}
if (authorized_principals) {
xfree(authorized_principals);
authorized_principals = NULL;
}
forced_tun_device = -1;
channel_clear_permitted_opens();
}
@ -141,6 +148,8 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
cp = "command=\"";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
opts += strlen(cp);
if (forced_command != NULL)
xfree(forced_command);
forced_command = xmalloc(strlen(opts) + 1);
i = 0;
while (*opts) {
@ -167,6 +176,38 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
opts++;
goto next_option;
}
cp = "principals=\"";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
opts += strlen(cp);
if (authorized_principals != NULL)
xfree(authorized_principals);
authorized_principals = xmalloc(strlen(opts) + 1);
i = 0;
while (*opts) {
if (*opts == '"')
break;
if (*opts == '\\' && opts[1] == '"') {
opts += 2;
authorized_principals[i++] = '"';
continue;
}
authorized_principals[i++] = *opts++;
}
if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
xfree(authorized_principals);
authorized_principals = NULL;
goto bad_option;
}
authorized_principals[i] = '\0';
auth_debug_add("principals: %.900s",
authorized_principals);
opts++;
goto next_option;
}
cp = "environment=\"";
if (options.permit_user_env &&
strncasecmp(opts, cp, strlen(cp)) == 0) {
@ -376,123 +417,147 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
return 0;
}
/*
* Set options from certificate constraints. These supersede user key options
* so this must be called after auth_parse_options().
*/
int
auth_cert_constraints(Buffer *c_orig, struct passwd *pw)
#define OPTIONS_CRITICAL 1
#define OPTIONS_EXTENSIONS 2
static int
parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
u_int which, int crit,
int *cert_no_port_forwarding_flag,
int *cert_no_agent_forwarding_flag,
int *cert_no_x11_forwarding_flag,
int *cert_no_pty_flag,
int *cert_no_user_rc,
char **cert_forced_command,
int *cert_source_address_done)
{
char *command, *allowed;
const char *remote_ip;
u_char *name = NULL, *data_blob = NULL;
u_int nlen, dlen, clen;
Buffer c, data;
int ret = -1;
int cert_no_port_forwarding_flag = 1;
int cert_no_agent_forwarding_flag = 1;
int cert_no_x11_forwarding_flag = 1;
int cert_no_pty_flag = 1;
int cert_no_user_rc = 1;
char *cert_forced_command = NULL;
int cert_source_address_done = 0;
int ret = -1, found;
buffer_init(&data);
/* Make copy to avoid altering original */
buffer_init(&c);
buffer_append(&c, buffer_ptr(c_orig), buffer_len(c_orig));
buffer_append(&c, optblob, optblob_len);
while (buffer_len(&c) > 0) {
if ((name = buffer_get_string_ret(&c, &nlen)) == NULL ||
(data_blob = buffer_get_string_ret(&c, &dlen)) == NULL) {
error("Certificate constraints corrupt");
error("Certificate options corrupt");
goto out;
}
buffer_append(&data, data_blob, dlen);
debug3("found certificate constraint \"%.100s\" len %u",
debug3("found certificate option \"%.100s\" len %u",
name, dlen);
if (strlen(name) != nlen) {
error("Certificate constraint name contains \\0");
goto out;
}
if (strcmp(name, "permit-X11-forwarding") == 0)
cert_no_x11_forwarding_flag = 0;
else if (strcmp(name, "permit-agent-forwarding") == 0)
cert_no_agent_forwarding_flag = 0;
else if (strcmp(name, "permit-port-forwarding") == 0)
cert_no_port_forwarding_flag = 0;
else if (strcmp(name, "permit-pty") == 0)
cert_no_pty_flag = 0;
else if (strcmp(name, "permit-user-rc") == 0)
cert_no_user_rc = 0;
else if (strcmp(name, "force-command") == 0) {
char *command = buffer_get_string_ret(&data, &clen);
if (command == NULL) {
error("Certificate constraint \"%s\" corrupt",
name);
goto out;
found = 0;
if ((which & OPTIONS_EXTENSIONS) != 0) {
if (strcmp(name, "permit-X11-forwarding") == 0) {
*cert_no_x11_forwarding_flag = 0;
found = 1;
} else if (strcmp(name,
"permit-agent-forwarding") == 0) {
*cert_no_agent_forwarding_flag = 0;
found = 1;
} else if (strcmp(name,
"permit-port-forwarding") == 0) {
*cert_no_port_forwarding_flag = 0;
found = 1;
} else if (strcmp(name, "permit-pty") == 0) {
*cert_no_pty_flag = 0;
found = 1;
} else if (strcmp(name, "permit-user-rc") == 0) {
*cert_no_user_rc = 0;
found = 1;
}
if (strlen(command) != clen) {
error("force-command constraint contains \\0");
goto out;
}
if (!found && (which & OPTIONS_CRITICAL) != 0) {
if (strcmp(name, "force-command") == 0) {
if ((command = buffer_get_string_ret(&data,
&clen)) == NULL) {
error("Certificate constraint \"%s\" "
"corrupt", name);
goto out;
}
if (strlen(command) != clen) {
error("force-command constraint "
"contains \\0");
goto out;
}
if (*cert_forced_command != NULL) {
error("Certificate has multiple "
"force-command options");
xfree(command);
goto out;
}
*cert_forced_command = command;
found = 1;
}
if (cert_forced_command != NULL) {
error("Certificate has multiple "
"force-command constraints");
xfree(command);
goto out;
if (strcmp(name, "source-address") == 0) {
if ((allowed = buffer_get_string_ret(&data,
&clen)) == NULL) {
error("Certificate constraint "
"\"%s\" corrupt", name);
goto out;
}
if (strlen(allowed) != clen) {
error("source-address constraint "
"contains \\0");
goto out;
}
if ((*cert_source_address_done)++) {
error("Certificate has multiple "
"source-address options");
xfree(allowed);
goto out;
}
remote_ip = get_remote_ipaddr();
switch (addr_match_cidr_list(remote_ip,
allowed)) {
case 1:
/* accepted */
xfree(allowed);
break;
case 0:
/* no match */
logit("Authentication tried for %.100s "
"with valid certificate but not "
"from a permitted host "
"(ip=%.200s).", pw->pw_name,
remote_ip);
auth_debug_add("Your address '%.200s' "
"is not permitted to use this "
"certificate for login.",
remote_ip);
xfree(allowed);
goto out;
case -1:
error("Certificate source-address "
"contents invalid");
xfree(allowed);
goto out;
}
found = 1;
}
cert_forced_command = command;
} else if (strcmp(name, "source-address") == 0) {
char *allowed = buffer_get_string_ret(&data, &clen);
const char *remote_ip = get_remote_ipaddr();
if (allowed == NULL) {
error("Certificate constraint \"%s\" corrupt",
name);
goto out;
}
if (strlen(allowed) != clen) {
error("source-address constraint contains \\0");
goto out;
}
if (cert_source_address_done++) {
error("Certificate has multiple "
"source-address constraints");
xfree(allowed);
goto out;
}
switch (addr_match_cidr_list(remote_ip, allowed)) {
case 1:
/* accepted */
xfree(allowed);
break;
case 0:
/* no match */
logit("Authentication tried for %.100s with "
"valid certificate but not from a "
"permitted host (ip=%.200s).",
pw->pw_name, remote_ip);
auth_debug_add("Your address '%.200s' is not "
"permitted to use this certificate for "
"login.", remote_ip);
xfree(allowed);
goto out;
case -1:
error("Certificate source-address contents "
"invalid");
xfree(allowed);
goto out;
}
} else {
error("Certificate constraint \"%s\" is not supported",
name);
goto out;
}
if (buffer_len(&data) != 0) {
error("Certificate constraint \"%s\" corrupt "
if (!found) {
if (crit) {
error("Certificate critical option \"%s\" "
"is not supported", name);
goto out;
} else {
logit("Certificate extension \"%s\" "
"is not supported", name);
}
} else if (buffer_len(&data) != 0) {
error("Certificate option \"%s\" corrupt "
"(extra data)", name);
goto out;
}
@ -501,10 +566,73 @@ auth_cert_constraints(Buffer *c_orig, struct passwd *pw)
xfree(data_blob);
name = data_blob = NULL;
}
/* successfully parsed all constraints */
/* successfully parsed all options */
ret = 0;
out:
if (ret != 0 &&
cert_forced_command != NULL &&
*cert_forced_command != NULL) {
xfree(*cert_forced_command);
*cert_forced_command = NULL;
}
if (name != NULL)
xfree(name);
if (data_blob != NULL)
xfree(data_blob);
buffer_free(&data);
buffer_free(&c);
return ret;
}
/*
* Set options from critical certificate options. These supersede user key
* options so this must be called after auth_parse_options().
*/
int
auth_cert_options(Key *k, struct passwd *pw)
{
int cert_no_port_forwarding_flag = 1;
int cert_no_agent_forwarding_flag = 1;
int cert_no_x11_forwarding_flag = 1;
int cert_no_pty_flag = 1;
int cert_no_user_rc = 1;
char *cert_forced_command = NULL;
int cert_source_address_done = 0;
if (key_cert_is_legacy(k)) {
/* All options are in the one field for v00 certs */
if (parse_option_list(buffer_ptr(&k->cert->critical),
buffer_len(&k->cert->critical), pw,
OPTIONS_CRITICAL|OPTIONS_EXTENSIONS, 1,
&cert_no_port_forwarding_flag,
&cert_no_agent_forwarding_flag,
&cert_no_x11_forwarding_flag,
&cert_no_pty_flag,
&cert_no_user_rc,
&cert_forced_command,
&cert_source_address_done) == -1)
return -1;
} else {
/* Separate options and extensions for v01 certs */
if (parse_option_list(buffer_ptr(&k->cert->critical),
buffer_len(&k->cert->critical), pw,
OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL,
&cert_forced_command,
&cert_source_address_done) == -1)
return -1;
if (parse_option_list(buffer_ptr(&k->cert->extensions),
buffer_len(&k->cert->extensions), pw,
OPTIONS_EXTENSIONS, 1,
&cert_no_port_forwarding_flag,
&cert_no_agent_forwarding_flag,
&cert_no_x11_forwarding_flag,
&cert_no_pty_flag,
&cert_no_user_rc,
NULL, NULL) == -1)
return -1;
}
no_port_forwarding_flag |= cert_no_port_forwarding_flag;
no_agent_forwarding_flag |= cert_no_agent_forwarding_flag;
no_x11_forwarding_flag |= cert_no_x11_forwarding_flag;
@ -516,14 +644,6 @@ auth_cert_constraints(Buffer *c_orig, struct passwd *pw)
xfree(forced_command);
forced_command = cert_forced_command;
}
out:
if (name != NULL)
xfree(name);
if (data_blob != NULL)
xfree(data_blob);
buffer_free(&data);
buffer_free(&c);
return ret;
return 0;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-options.h,v 1.18 2010/02/26 20:29:54 djm Exp $ */
/* $OpenBSD: auth-options.h,v 1.20 2010/05/07 11:30:29 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -31,9 +31,10 @@ extern char *forced_command;
extern struct envstring *custom_environment;
extern int forced_tun_device;
extern int key_is_cert_authority;
extern char *authorized_principals;
int auth_parse_options(struct passwd *, char *, char *, u_long);
void auth_clear_options(void);
int auth_cert_constraints(Buffer *, struct passwd *);
int auth_cert_options(Key *, struct passwd *);
#endif

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-rsa.c,v 1.74 2010/03/04 10:36:03 djm Exp $ */
/* $OpenBSD: auth-rsa.c,v 1.78 2010/07/13 23:13:16 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -34,11 +34,11 @@
#include "uidswap.h"
#include "match.h"
#include "buffer.h"
#include "auth-options.h"
#include "pathnames.h"
#include "log.h"
#include "servconf.h"
#include "key.h"
#include "auth-options.h"
#include "hostfile.h"
#include "auth.h"
#ifdef GSSAPI
@ -116,7 +116,7 @@ auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
MD5_Final(mdbuf, &md);
/* Verify that the response is the original challenge. */
if (memcmp(response, mdbuf, 16) != 0) {
if (timingsafe_bcmp(response, mdbuf, 16) != 0) {
/* Wrong answer. */
return (0);
}
@ -256,7 +256,8 @@ auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
*/
if (!auth_parse_options(pw, key_options, file, linenum))
continue;
if (key_is_cert_authority)
continue;
/* break out, this key is allowed */
allowed = 1;
break;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth.c,v 1.86 2010/03/05 02:58:11 djm Exp $ */
/* $OpenBSD: auth.c,v 1.89 2010/08/04 05:42:47 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -144,7 +144,7 @@ allowed_user(struct passwd * pw)
locked = 1;
#endif
#ifdef USE_LIBIAF
free(passwd);
free((void *) passwd);
#endif /* USE_LIBIAF */
if (locked) {
logit("User %.100s not allowed because account is locked",
@ -367,6 +367,14 @@ authorized_keys_file2(struct passwd *pw)
return expand_authorized_keys(options.authorized_keys_file2, pw);
}
char *
authorized_principals_file(struct passwd *pw)
{
if (options.authorized_principals_file == NULL)
return NULL;
return expand_authorized_keys(options.authorized_principals_file, pw);
}
/* return ok if key exists in sysfile or userfile */
HostStatus
check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
@ -378,7 +386,7 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
HostStatus host_status;
/* Check if we know the host and its host key. */
found = key_new(key->type);
found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
host_status = check_host_in_hostfile(sysfile, host, key, found, NULL);
if (host_status != HOST_OK && userfile != NULL) {
@ -390,6 +398,8 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
logit("Authentication refused for %.100s: "
"bad owner or modes for %.200s",
pw->pw_name, user_hostfile);
auth_debug_add("Ignored %.200s: bad ownership or modes",
user_hostfile);
} else {
temporarily_use_uid(pw);
host_status = check_host_in_hostfile(user_hostfile,
@ -478,21 +488,18 @@ secure_filename(FILE *f, const char *file, struct passwd *pw,
return 0;
}
FILE *
auth_openkeyfile(const char *file, struct passwd *pw, int strict_modes)
static FILE *
auth_openfile(const char *file, struct passwd *pw, int strict_modes,
int log_missing, char *file_type)
{
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) {
if (errno != ENOENT)
debug("Could not open keyfile '%s': %s", file,
if (log_missing || errno != ENOENT)
debug("Could not open %s '%s': %s", file_type, file,
strerror(errno));
return NULL;
}
@ -502,8 +509,8 @@ auth_openkeyfile(const char *file, struct passwd *pw, int strict_modes)
return NULL;
}
if (!S_ISREG(st.st_mode)) {
logit("User %s authorized keys %s is not a regular file",
pw->pw_name, file);
logit("User %s %s %s is not a regular file",
pw->pw_name, file_type, file);
close(fd);
return NULL;
}
@ -516,12 +523,27 @@ auth_openkeyfile(const char *file, struct passwd *pw, int strict_modes)
secure_filename(f, file, pw, line, sizeof(line)) != 0) {
fclose(f);
logit("Authentication refused: %s", line);
auth_debug_add("Ignored %s: %s", file_type, line);
return NULL;
}
return f;
}
FILE *
auth_openkeyfile(const char *file, struct passwd *pw, int strict_modes)
{
return auth_openfile(file, pw, strict_modes, 1, "authorized keys");
}
FILE *
auth_openprincipals(const char *file, struct passwd *pw, int strict_modes)
{
return auth_openfile(file, pw, strict_modes, 0,
"authorized principals");
}
struct passwd *
getpwnamallow(const char *user)
{

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth.h,v 1.65 2010/03/04 10:36:03 djm Exp $ */
/* $OpenBSD: auth.h,v 1.66 2010/05/07 11:30:29 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@ -169,8 +169,10 @@ void abandon_challenge_response(Authctxt *);
char *authorized_keys_file(struct passwd *);
char *authorized_keys_file2(struct passwd *);
char *authorized_principals_file(struct passwd *);
FILE *auth_openkeyfile(const char *, struct passwd *, int);
FILE *auth_openprincipals(const char *, struct passwd *, int);
int auth_key_is_revoked(Key *);
HostStatus

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth1.c,v 1.73 2008/07/04 23:30:16 djm Exp $ */
/* $OpenBSD: auth1.c,v 1.74 2010/06/25 08:46:17 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@ -244,7 +244,7 @@ do_authloop(Authctxt *authctxt)
authctxt->valid ? "" : "invalid user ", authctxt->user);
/* If the user has no password, accept authentication immediately. */
if (options.password_authentication &&
if (options.permit_empty_passwd && options.password_authentication &&
#ifdef KRB5
(!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
#endif

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-hostbased.c,v 1.13 2010/03/04 10:36:03 djm Exp $ */
/* $OpenBSD: auth2-hostbased.c,v 1.14 2010/08/04 05:42:47 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -141,9 +141,10 @@ int
hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
Key *key)
{
const char *resolvedname, *ipaddr, *lookup;
const char *resolvedname, *ipaddr, *lookup, *reason;
HostStatus host_status;
int len;
char *fp;
if (auth_key_is_revoked(key))
return 0;
@ -174,16 +175,40 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
}
debug2("userauth_hostbased: access allowed by auth_rhosts2");
if (key_is_cert(key) &&
key_cert_check_authority(key, 1, 0, lookup, &reason)) {
error("%s", reason);
auth_debug_add("%s", reason);
return 0;
}
host_status = check_key_in_hostfiles(pw, key, lookup,
_PATH_SSH_SYSTEM_HOSTFILE,
options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
/* backward compat if no key has been found. */
if (host_status == HOST_NEW)
if (host_status == HOST_NEW) {
host_status = check_key_in_hostfiles(pw, key, lookup,
_PATH_SSH_SYSTEM_HOSTFILE2,
options.ignore_user_known_hosts ? NULL :
_PATH_SSH_USER_HOSTFILE2);
}
if (host_status == HOST_OK) {
if (key_is_cert(key)) {
fp = key_fingerprint(key->cert->signature_key,
SSH_FP_MD5, SSH_FP_HEX);
verbose("Accepted certificate ID \"%s\" signed by "
"%s CA %s from %s@%s", key->cert->key_id,
key_type(key->cert->signature_key), fp,
cuser, lookup);
} else {
fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
verbose("Accepted %s public key %s from %s@%s",
key_type(key), fp, cuser, lookup);
}
xfree(fp);
}
return (host_status == HOST_OK);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-none.c,v 1.15 2008/07/02 12:36:39 djm Exp $ */
/* $OpenBSD: auth2-none.c,v 1.16 2010/06/25 08:46:17 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -61,7 +61,7 @@ userauth_none(Authctxt *authctxt)
{
none_enabled = 0;
packet_check_eom();
if (options.password_authentication)
if (options.permit_empty_passwd && options.password_authentication)
return (PRIVSEP(auth_password(authctxt, "")));
return (0);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-pubkey.c,v 1.22 2010/03/10 23:27:17 djm Exp $ */
/* $OpenBSD: auth2-pubkey.c,v 1.26 2010/06/29 23:16:46 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -57,6 +57,7 @@
#include "monitor_wrap.h"
#include "misc.h"
#include "authfile.h"
#include "match.h"
/* import */
extern ServerOptions options;
@ -176,6 +177,83 @@ userauth_pubkey(Authctxt *authctxt)
return authenticated;
}
static int
match_principals_option(const char *principal_list, struct KeyCert *cert)
{
char *result;
u_int i;
/* XXX percent_expand() sequences for authorized_principals? */
for (i = 0; i < cert->nprincipals; i++) {
if ((result = match_list(cert->principals[i],
principal_list, NULL)) != NULL) {
debug3("matched principal from key options \"%.100s\"",
result);
xfree(result);
return 1;
}
}
return 0;
}
static int
match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert)
{
FILE *f;
char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts;
u_long linenum = 0;
u_int i;
temporarily_use_uid(pw);
debug("trying authorized principals file %s", file);
if ((f = auth_openprincipals(file, pw, options.strict_modes)) == NULL) {
restore_uid();
return 0;
}
while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
/* Skip leading whitespace. */
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
;
/* Skip blank and comment lines. */
if ((ep = strchr(cp, '#')) != NULL)
*ep = '\0';
if (!*cp || *cp == '\n')
continue;
/* Trim trailing whitespace. */
ep = cp + strlen(cp) - 1;
while (ep > cp && (*ep == '\n' || *ep == ' ' || *ep == '\t'))
*ep-- = '\0';
/*
* If the line has internal whitespace then assume it has
* key options.
*/
line_opts = NULL;
if ((ep = strrchr(cp, ' ')) != NULL ||
(ep = strrchr(cp, '\t')) != NULL) {
for (; *ep == ' ' || *ep == '\t'; ep++)
;;
line_opts = cp;
cp = ep;
}
for (i = 0; i < cert->nprincipals; i++) {
if (strcmp(cp, cert->principals[i]) == 0) {
debug3("matched principal from file \"%.100s\"",
cert->principals[i]);
if (auth_parse_options(pw, line_opts,
file, linenum) != 1)
continue;
fclose(f);
restore_uid();
return 1;
}
}
}
fclose(f);
restore_uid();
return 0;
}
/* return 1 if user allows given key */
static int
user_key_allowed2(struct passwd *pw, Key *key, char *file)
@ -233,26 +311,39 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
continue;
}
}
if (auth_parse_options(pw, key_options, file, linenum) != 1)
continue;
if (key->type == KEY_RSA_CERT || key->type == KEY_DSA_CERT) {
if (!key_is_cert_authority)
continue;
if (key_is_cert(key)) {
if (!key_equal(found, key->cert->signature_key))
continue;
if (auth_parse_options(pw, key_options, file,
linenum) != 1)
continue;
if (!key_is_cert_authority)
continue;
fp = key_fingerprint(found, SSH_FP_MD5,
SSH_FP_HEX);
debug("matching CA found: file %s, line %lu, %s %s",
file, linenum, key_type(found), fp);
if (key_cert_check_authority(key, 0, 0, pw->pw_name,
&reason) != 0) {
/*
* If the user has specified a list of principals as
* a key option, then prefer that list to matching
* their username in the certificate principals list.
*/
if (authorized_principals != NULL &&
!match_principals_option(authorized_principals,
key->cert)) {
reason = "Certificate does not contain an "
"authorized principal";
fail_reason:
xfree(fp);
error("%s", reason);
auth_debug_add("%s", reason);
continue;
}
if (auth_cert_constraints(&key->cert->constraints,
pw) != 0) {
if (key_cert_check_authority(key, 0, 0,
authorized_principals == NULL ? pw->pw_name : NULL,
&reason) != 0)
goto fail_reason;
if (auth_cert_options(key, pw) != 0) {
xfree(fp);
continue;
}
@ -262,7 +353,12 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
xfree(fp);
found_key = 1;
break;
} else if (!key_is_cert_authority && key_equal(found, key)) {
} else if (key_equal(found, key)) {
if (auth_parse_options(pw, key_options, file,
linenum) != 1)
continue;
if (key_is_cert_authority)
continue;
found_key = 1;
debug("matching key found: file %s, line %lu",
file, linenum);
@ -285,7 +381,7 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
static int
user_cert_trusted_ca(struct passwd *pw, Key *key)
{
char *ca_fp;
char *ca_fp, *principals_file = NULL;
const char *reason;
int ret = 0;
@ -302,12 +398,25 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
options.trusted_user_ca_keys);
goto out;
}
if (key_cert_check_authority(key, 0, 1, pw->pw_name, &reason) != 0) {
error("%s", reason);
auth_debug_add("%s", reason);
goto out;
/*
* If AuthorizedPrincipals is in use, then compare the certificate
* principals against the names in that file rather than matching
* against the username.
*/
if ((principals_file = authorized_principals_file(pw)) != NULL) {
if (!match_principals_file(principals_file, pw, key->cert)) {
reason = "Certificate does not contain an "
"authorized principal";
fail_reason:
error("%s", reason);
auth_debug_add("%s", reason);
goto out;
}
}
if (auth_cert_constraints(&key->cert->constraints, pw) != 0)
if (key_cert_check_authority(key, 0, 1,
principals_file == NULL ? pw->pw_name : NULL, &reason) != 0)
goto fail_reason;
if (auth_cert_options(key, pw) != 0)
goto out;
verbose("Accepted certificate ID \"%s\" signed by %s CA %s via %s",
@ -316,6 +425,8 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
ret = 1;
out:
if (principals_file != NULL)
xfree(principals_file);
if (ca_fp != NULL)
xfree(ca_fp);
return ret;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: authfd.c,v 1.82 2010/02/26 20:29:54 djm Exp $ */
/* $OpenBSD: authfd.c,v 1.83 2010/04/16 01:47:26 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -483,6 +483,7 @@ ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment)
buffer_put_bignum2(b, key->rsa->p);
buffer_put_bignum2(b, key->rsa->q);
break;
case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)
fatal("%s: no cert/certblob", __func__);
@ -500,6 +501,7 @@ ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment)
buffer_put_bignum2(b, key->dsa->pub_key);
buffer_put_bignum2(b, key->dsa->priv_key);
break;
case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)
fatal("%s: no cert/certblob", __func__);
@ -535,8 +537,10 @@ ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key,
break;
case KEY_RSA:
case KEY_RSA_CERT:
case KEY_RSA_CERT_V00:
case KEY_DSA:
case KEY_DSA_CERT:
case KEY_DSA_CERT_V00:
type = constrained ?
SSH2_AGENTC_ADD_ID_CONSTRAINED :
SSH2_AGENTC_ADD_IDENTITY;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: authfile.c,v 1.80 2010/03/04 10:36:03 djm Exp $ */
/* $OpenBSD: authfile.c,v 1.82 2010/08/04 05:49:22 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -693,6 +693,66 @@ key_load_public(const char *filename, char **commentp)
return NULL;
}
/* Load the certificate associated with the named private key */
Key *
key_load_cert(const char *filename)
{
Key *pub;
char *file;
pub = key_new(KEY_UNSPEC);
xasprintf(&file, "%s-cert.pub", filename);
if (key_try_load_public(pub, file, NULL) == 1) {
xfree(file);
return pub;
}
xfree(file);
key_free(pub);
return NULL;
}
/* Load private key and certificate */
Key *
key_load_private_cert(int type, const char *filename, const char *passphrase,
int *perm_ok)
{
Key *key, *pub;
switch (type) {
case KEY_RSA:
case KEY_DSA:
break;
default:
error("%s: unsupported key type", __func__);
return NULL;
}
if ((key = key_load_private_type(type, filename,
passphrase, NULL, perm_ok)) == NULL)
return NULL;
if ((pub = key_load_cert(filename)) == NULL) {
key_free(key);
return NULL;
}
/* Make sure the private key matches the certificate */
if (key_equal_public(key, pub) == 0) {
error("%s: certificate does not match private key %s",
__func__, filename);
} else if (key_to_certified(key, key_cert_is_legacy(pub)) != 0) {
error("%s: key_to_certified failed", __func__);
} else {
key_cert_copy(pub, key);
key_free(pub);
return key;
}
key_free(key);
key_free(pub);
return NULL;
}
/*
* Returns 1 if the specified "key" is listed in the file "filename",
* 0 if the key is not listed or -1 on error.

View File

@ -1,4 +1,4 @@
/* $OpenBSD: authfile.h,v 1.14 2010/03/04 10:36:03 djm Exp $ */
/* $OpenBSD: authfile.h,v 1.15 2010/08/04 05:42:47 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -16,9 +16,11 @@
#define AUTHFILE_H
int key_save_private(Key *, const char *, const char *, const char *);
Key *key_load_cert(const char *);
Key *key_load_public(const char *, char **);
Key *key_load_public_type(int, const char *, char **);
Key *key_load_private(const char *, const char *, char **);
Key *key_load_private_cert(int, const char *, const char *, int *);
Key *key_load_private_type(int, const char *, const char *, char **, int *);
Key *key_load_private_pem(int, int, const char *, char **);
int key_perm_ok(int, const char *);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: bufaux.c,v 1.48 2010/02/02 22:49:34 djm Exp $ */
/* $OpenBSD: bufaux.c,v 1.49 2010/03/26 03:13:17 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -84,7 +84,8 @@ buffer_get_int_ret(u_int *ret, Buffer *buffer)
if (buffer_get_ret(buffer, (char *) buf, 4) == -1)
return (-1);
*ret = get_u32(buf);
if (ret != NULL)
*ret = get_u32(buf);
return (0);
}
@ -106,7 +107,8 @@ buffer_get_int64_ret(u_int64_t *ret, Buffer *buffer)
if (buffer_get_ret(buffer, (char *) buf, 8) == -1)
return (-1);
*ret = get_u64(buf);
if (ret != NULL)
*ret = get_u64(buf);
return (0);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: channels.c,v 1.303 2010/01/30 21:12:08 djm Exp $ */
/* $OpenBSD: channels.c,v 1.309 2010/08/05 13:08:42 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -114,10 +114,10 @@ typedef struct {
} ForwardPermission;
/* List of all permitted host/port pairs to connect by the user. */
static ForwardPermission permitted_opens[SSH_MAX_FORWARDS_PER_DIRECTION];
static ForwardPermission *permitted_opens = NULL;
/* List of all permitted host/port pairs to connect by the admin. */
static ForwardPermission permitted_adm_opens[SSH_MAX_FORWARDS_PER_DIRECTION];
static ForwardPermission *permitted_adm_opens = NULL;
/* Number of permitted host/port pairs in the array permitted by the user. */
static int num_permitted_opens = 0;
@ -330,6 +330,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd,
c->ctl_chan = -1;
c->mux_rcb = NULL;
c->mux_ctx = NULL;
c->mux_pause = 0;
c->delayed = 1; /* prevent call to channel_post handler */
TAILQ_INIT(&c->status_confirms);
debug("channel %d: new [%s]", found, remote_name);
@ -703,7 +704,7 @@ channel_register_status_confirm(int id, channel_confirm_cb *cb,
}
void
channel_register_open_confirm(int id, channel_callback_fn *fn, void *ctx)
channel_register_open_confirm(int id, channel_open_fn *fn, void *ctx)
{
Channel *c = channel_lookup(id);
@ -838,8 +839,9 @@ channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset)
if (c->extended_usage == CHAN_EXTENDED_WRITE &&
buffer_len(&c->extended) > 0)
FD_SET(c->efd, writeset);
else if (!(c->flags & CHAN_EOF_SENT) &&
c->extended_usage == CHAN_EXTENDED_READ &&
else if (c->efd != -1 && !(c->flags & CHAN_EOF_SENT) &&
(c->extended_usage == CHAN_EXTENDED_READ ||
c->extended_usage == CHAN_EXTENDED_IGNORE) &&
buffer_len(&c->extended) < c->remote_window)
FD_SET(c->efd, readset);
}
@ -915,7 +917,7 @@ x11_open_helper(Buffer *b)
}
/* Check if authentication data matches our fake data. */
if (data_len != x11_fake_data_len ||
memcmp(ucp + 12 + ((proto_len + 3) & ~3),
timingsafe_bcmp(ucp + 12 + ((proto_len + 3) & ~3),
x11_fake_data, x11_fake_data_len) != 0) {
debug2("X11 auth data does not match fake data.");
return -1;
@ -991,7 +993,7 @@ channel_pre_x11_open(Channel *c, fd_set *readset, fd_set *writeset)
static void
channel_pre_mux_client(Channel *c, fd_set *readset, fd_set *writeset)
{
if (c->istate == CHAN_INPUT_OPEN &&
if (c->istate == CHAN_INPUT_OPEN && !c->mux_pause &&
buffer_check_alloc(&c->input, CHAN_RBUF))
FD_SET(c->rfd, readset);
if (c->istate == CHAN_INPUT_WAIT_DRAIN) {
@ -1642,13 +1644,14 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset)
{
struct termios tio;
u_char *data = NULL, *buf;
u_int dlen;
u_int dlen, olen = 0;
int len;
/* Send buffered output data to the socket. */
if (c->wfd != -1 &&
FD_ISSET(c->wfd, writeset) &&
buffer_len(&c->output) > 0) {
olen = buffer_len(&c->output);
if (c->output_filter != NULL) {
if ((buf = c->output_filter(c, &data, &dlen)) == NULL) {
debug2("channel %d: filter stops", c->self);
@ -1667,7 +1670,6 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset)
if (c->datagram) {
/* ignore truncated writes, datagrams might get lost */
c->local_consumed += dlen + 4;
len = write(c->wfd, buf, dlen);
xfree(data);
if (len < 0 && (errno == EINTR || errno == EAGAIN ||
@ -1680,7 +1682,7 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset)
chan_write_failed(c);
return -1;
}
return 1;
goto out;
}
#ifdef _AIX
/* XXX: Later AIX versions can't push as much data to tty */
@ -1722,10 +1724,10 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset)
}
#endif
buffer_consume(&c->output, len);
if (compat20 && len > 0) {
c->local_consumed += len;
}
}
out:
if (compat20 && olen > 0)
c->local_consumed += olen - buffer_len(&c->output);
return 1;
}
@ -1755,7 +1757,9 @@ channel_handle_efd(Channel *c, fd_set *readset, fd_set *writeset)
buffer_consume(&c->extended, len);
c->local_consumed += len;
}
} else if (c->extended_usage == CHAN_EXTENDED_READ &&
} else if (c->efd != -1 &&
(c->extended_usage == CHAN_EXTENDED_READ ||
c->extended_usage == CHAN_EXTENDED_IGNORE) &&
(c->detach_close || FD_ISSET(c->efd, readset))) {
len = read(c->efd, buf, sizeof(buf));
debug2("channel %d: read %d from efd %d",
@ -1768,7 +1772,11 @@ channel_handle_efd(Channel *c, fd_set *readset, fd_set *writeset)
c->self, c->efd);
channel_close_fd(&c->efd);
} else {
buffer_append(&c->extended, buf, len);
if (c->extended_usage == CHAN_EXTENDED_IGNORE) {
debug3("channel %d: discard efd",
c->self);
} else
buffer_append(&c->extended, buf, len);
}
}
}
@ -1840,7 +1848,7 @@ channel_post_mux_client(Channel *c, fd_set *readset, fd_set *writeset)
if (!compat20)
fatal("%s: entered with !compat20", __func__);
if (c->rfd != -1 && FD_ISSET(c->rfd, readset) &&
if (c->rfd != -1 && !c->mux_pause && FD_ISSET(c->rfd, readset) &&
(c->istate == CHAN_INPUT_OPEN ||
c->istate == CHAN_INPUT_WAIT_DRAIN)) {
/*
@ -2164,6 +2172,14 @@ channel_output_poll(void)
data = buffer_get_string(&c->input,
&dlen);
if (dlen > c->remote_window ||
dlen > c->remote_maxpacket) {
debug("channel %d: datagram "
"too big for channel",
c->self);
xfree(data);
continue;
}
packet_start(SSH2_MSG_CHANNEL_DATA);
packet_put_int(c->remote_id);
packet_put_string(data, dlen);
@ -2249,7 +2265,7 @@ channel_input_data(int type, u_int32_t seq, void *ctxt)
{
int id;
char *data;
u_int data_len;
u_int data_len, win_len;
Channel *c;
/* Get the channel number and verify it. */
@ -2265,6 +2281,9 @@ channel_input_data(int type, u_int32_t seq, void *ctxt)
/* Get the data. */
data = packet_get_string_ptr(&data_len);
win_len = data_len;
if (c->datagram)
win_len += 4; /* string length header */
/*
* Ignore data for protocol > 1.3 if output end is no longer open.
@ -2275,23 +2294,23 @@ channel_input_data(int type, u_int32_t seq, void *ctxt)
*/
if (!compat13 && c->ostate != CHAN_OUTPUT_OPEN) {
if (compat20) {
c->local_window -= data_len;
c->local_consumed += data_len;
c->local_window -= win_len;
c->local_consumed += win_len;
}
return;
}
if (compat20) {
if (data_len > c->local_maxpacket) {
if (win_len > c->local_maxpacket) {
logit("channel %d: rcvd big packet %d, maxpack %d",
c->self, data_len, c->local_maxpacket);
c->self, win_len, c->local_maxpacket);
}
if (data_len > c->local_window) {
if (win_len > c->local_window) {
logit("channel %d: rcvd too much data %d, win %d",
c->self, data_len, c->local_window);
c->self, win_len, c->local_window);
return;
}
c->local_window -= data_len;
c->local_window -= win_len;
}
if (c->datagram)
buffer_put_string(&c->output, data, data_len);
@ -2463,7 +2482,7 @@ channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt)
c->remote_maxpacket = packet_get_int();
if (c->open_confirm) {
debug2("callback start");
c->open_confirm(c->self, c->open_confirm_ctx);
c->open_confirm(c->self, 1, c->open_confirm_ctx);
debug2("callback done");
}
debug2("channel %d: open confirm rwindow %u rmax %u", c->self,
@ -2514,6 +2533,11 @@ channel_input_open_failure(int type, u_int32_t seq, void *ctxt)
xfree(msg);
if (lang != NULL)
xfree(lang);
if (c->open_confirm) {
debug2("callback start");
c->open_confirm(c->self, 0, c->open_confirm_ctx);
debug2("callback done");
}
}
packet_check_eom();
/* Schedule the channel for cleanup/deletion. */
@ -2832,10 +2856,6 @@ channel_request_remote_forwarding(const char *listen_host, u_short listen_port,
{
int type, success = 0;
/* Record locally that connection to this host/port is permitted. */
if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION)
fatal("channel_request_remote_forwarding: too many forwards");
/* Send the forward request to the remote side. */
if (compat20) {
const char *address_to_bind;
@ -2885,6 +2905,9 @@ channel_request_remote_forwarding(const char *listen_host, u_short listen_port,
}
}
if (success) {
/* Record that connection to this host/port is permitted. */
permitted_opens = xrealloc(permitted_opens,
num_permitted_opens + 1, sizeof(*permitted_opens));
permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host_to_connect);
permitted_opens[num_permitted_opens].port_to_connect = port_to_connect;
permitted_opens[num_permitted_opens].listen_port = listen_port;
@ -2982,10 +3005,10 @@ channel_permit_all_opens(void)
void
channel_add_permitted_opens(char *host, int port)
{
if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION)
fatal("channel_add_permitted_opens: too many forwards");
debug("allow port forwarding to host %s port %d", host, port);
permitted_opens = xrealloc(permitted_opens,
num_permitted_opens + 1, sizeof(*permitted_opens));
permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host);
permitted_opens[num_permitted_opens].port_to_connect = port;
num_permitted_opens++;
@ -2996,10 +3019,10 @@ channel_add_permitted_opens(char *host, int port)
int
channel_add_adm_permitted_opens(char *host, int port)
{
if (num_adm_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION)
fatal("channel_add_adm_permitted_opens: too many forwards");
debug("config allows port forwarding to host %s port %d", host, port);
permitted_adm_opens = xrealloc(permitted_adm_opens,
num_adm_permitted_opens + 1, sizeof(*permitted_adm_opens));
permitted_adm_opens[num_adm_permitted_opens].host_to_connect
= xstrdup(host);
permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port;
@ -3014,6 +3037,10 @@ channel_clear_permitted_opens(void)
for (i = 0; i < num_permitted_opens; i++)
if (permitted_opens[i].host_to_connect != NULL)
xfree(permitted_opens[i].host_to_connect);
if (num_permitted_opens > 0) {
xfree(permitted_opens);
permitted_opens = NULL;
}
num_permitted_opens = 0;
}
@ -3025,6 +3052,10 @@ channel_clear_adm_permitted_opens(void)
for (i = 0; i < num_adm_permitted_opens; i++)
if (permitted_adm_opens[i].host_to_connect != NULL)
xfree(permitted_adm_opens[i].host_to_connect);
if (num_adm_permitted_opens > 0) {
xfree(permitted_adm_opens);
permitted_adm_opens = NULL;
}
num_adm_permitted_opens = 0;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: channels.h,v 1.103 2010/01/26 01:28:35 djm Exp $ */
/* $OpenBSD: channels.h,v 1.104 2010/05/14 23:29:23 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -60,6 +60,7 @@
struct Channel;
typedef struct Channel Channel;
typedef void channel_open_fn(int, int, void *);
typedef void channel_callback_fn(int, void *);
typedef int channel_infilter_fn(struct Channel *, char *, int);
typedef void channel_filter_cleanup_fn(int, void *);
@ -130,7 +131,7 @@ struct Channel {
char *ctype; /* type */
/* callback */
channel_callback_fn *open_confirm;
channel_open_fn *open_confirm;
void *open_confirm_ctx;
channel_callback_fn *detach_user;
int detach_close;
@ -151,6 +152,7 @@ struct Channel {
/* multiplexing protocol hook, called for each packet received */
mux_callback_fn *mux_rcb;
void *mux_ctx;
int mux_pause;
};
#define CHAN_EXTENDED_IGNORE 0
@ -208,7 +210,7 @@ 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_open_confirm(int, channel_callback_fn *, void *);
void channel_register_open_confirm(int, channel_open_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 *,

View File

@ -1,4 +1,4 @@
/* $OpenBSD: clientloop.c,v 1.219 2010/03/13 21:10:38 djm Exp $ */
/* $OpenBSD: clientloop.c,v 1.222 2010/07/19 09:15:12 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -145,6 +145,9 @@ static volatile sig_atomic_t received_signal = 0;
/* Flag indicating whether the user's terminal is in non-blocking mode. */
static int in_non_blocking_mode = 0;
/* Time when backgrounded control master using ControlPersist should exit */
static time_t control_persist_exit_time = 0;
/* Common data for the client loop code. */
volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */
static int escape_char1; /* Escape character. (proto1 only) */
@ -155,11 +158,12 @@ static int stdin_eof; /* EOF has been encountered on stderr. */
static Buffer stdin_buffer; /* Buffer for stdin data. */
static Buffer stdout_buffer; /* Buffer for stdout data. */
static Buffer stderr_buffer; /* Buffer for stderr data. */
static u_int buffer_high;/* Soft max buffer size. */
static u_int buffer_high; /* Soft max buffer size. */
static int connection_in; /* Connection to server (input). */
static int connection_out; /* Connection to server (output). */
static int need_rekeying; /* Set to non-zero if rekeying is requested. */
static int session_closed = 0; /* In SSH2: login session closed. */
static int session_closed; /* In SSH2: login session closed. */
static int x11_refuse_time; /* If >0, refuse x11 opens after this time. */
static void client_init_dispatch(void);
int session_ident = -1;
@ -251,10 +255,38 @@ get_current_time(void)
return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
}
/*
* Sets control_persist_exit_time to the absolute time when the
* backgrounded control master should exit due to expiry of the
* ControlPersist timeout. Sets it to 0 if we are not a backgrounded
* control master process, or if there is no ControlPersist timeout.
*/
static void
set_control_persist_exit_time(void)
{
if (muxserver_sock == -1 || !options.control_persist
|| options.control_persist_timeout == 0)
/* not using a ControlPersist timeout */
control_persist_exit_time = 0;
else if (channel_still_open()) {
/* some client connections are still open */
if (control_persist_exit_time > 0)
debug2("%s: cancel scheduled exit", __func__);
control_persist_exit_time = 0;
} else if (control_persist_exit_time <= 0) {
/* a client connection has recently closed */
control_persist_exit_time = time(NULL) +
(time_t)options.control_persist_timeout;
debug2("%s: schedule exit in %d seconds", __func__,
options.control_persist_timeout);
}
/* else we are already counting down to the timeout */
}
#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
void
client_x11_get_proto(const char *display, const char *xauth_path,
u_int trusted, char **_proto, char **_data)
u_int trusted, u_int timeout, char **_proto, char **_data)
{
char cmd[1024];
char line[512];
@ -264,6 +296,7 @@ client_x11_get_proto(const char *display, const char *xauth_path,
int got_data = 0, generated = 0, do_unlink = 0, i;
char *xauthdir, *xauthfile;
struct stat st;
u_int now;
xauthdir = xauthfile = NULL;
*_proto = proto;
@ -299,11 +332,18 @@ client_x11_get_proto(const char *display, const char *xauth_path,
xauthdir);
snprintf(cmd, sizeof(cmd),
"%s -f %s generate %s " SSH_X11_PROTO
" untrusted timeout 1200 2>" _PATH_DEVNULL,
xauth_path, xauthfile, display);
" untrusted timeout %u 2>" _PATH_DEVNULL,
xauth_path, xauthfile, display, timeout);
debug2("x11_get_proto: %s", cmd);
if (system(cmd) == 0)
generated = 1;
if (x11_refuse_time == 0) {
now = time(NULL) + 1;
if (UINT_MAX - timeout < now)
x11_refuse_time = UINT_MAX;
else
x11_refuse_time = now + timeout;
}
}
}
@ -524,6 +564,7 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
int *maxfdp, u_int *nallocp, int rekeying)
{
struct timeval tv, *tvp;
int timeout_secs;
int ret;
/* Add any selections by the channel mechanism. */
@ -567,16 +608,27 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
/*
* Wait for something to happen. This will suspend the process until
* some selected descriptor can be read, written, or has some other
* event pending.
* event pending, or a timeout expires.
*/
if (options.server_alive_interval == 0 || !compat20)
timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */
if (options.server_alive_interval > 0 && compat20)
timeout_secs = options.server_alive_interval;
set_control_persist_exit_time();
if (control_persist_exit_time > 0) {
timeout_secs = MIN(timeout_secs,
control_persist_exit_time - time(NULL));
if (timeout_secs < 0)
timeout_secs = 0;
}
if (timeout_secs == INT_MAX)
tvp = NULL;
else {
tv.tv_sec = options.server_alive_interval;
tv.tv_sec = timeout_secs;
tv.tv_usec = 0;
tvp = &tv;
}
ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
if (ret < 0) {
char buf[100];
@ -1469,6 +1521,18 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
*/
if (FD_ISSET(connection_out, writeset))
packet_write_poll();
/*
* If we are a backgrounded control master, and the
* timeout has expired without any active client
* connections, then quit.
*/
if (control_persist_exit_time > 0) {
if (time(NULL) >= control_persist_exit_time) {
debug("ControlPersist timeout expired");
break;
}
}
}
if (readset)
xfree(readset);
@ -1686,6 +1750,11 @@ client_request_x11(const char *request_type, int rchan)
"malicious server.");
return NULL;
}
if (x11_refuse_time != 0 && time(NULL) >= x11_refuse_time) {
verbose("Rejected X11 connection after ForwardX11Timeout "
"expired");
return NULL;
}
originator = packet_get_string(NULL);
if (datafellows & SSH_BUG_X11FWD) {
debug2("buggy server: x11 request w/o originator_port");
@ -1912,7 +1981,7 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
memset(&ws, 0, sizeof(ws));
channel_request_start(id, "pty-req", 1);
client_expect_confirm(id, "PTY allocation", 0);
client_expect_confirm(id, "PTY allocation", 1);
packet_put_cstring(term != NULL ? term : "");
packet_put_int((u_int)ws.ws_col);
packet_put_int((u_int)ws.ws_row);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: clientloop.h,v 1.23 2010/01/26 01:28:35 djm Exp $ */
/* $OpenBSD: clientloop.h,v 1.25 2010/06/25 23:15:36 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -39,7 +39,7 @@
/* Client side main loop for the interactive session. */
int client_loop(int, int, int);
void client_x11_get_proto(const char *, const char *, u_int,
void client_x11_get_proto(const char *, const char *, u_int, 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 *,
@ -63,6 +63,7 @@ void client_register_global_confirm(global_confirm_cb *, void *);
#define SSHMUX_COMMAND_ALIVE_CHECK 2 /* Check master is alive */
#define SSHMUX_COMMAND_TERMINATE 3 /* Ask master to exit */
#define SSHMUX_COMMAND_STDIO_FWD 4 /* Open stdio fwd (ssh -W) */
#define SSHMUX_COMMAND_FORWARD 5 /* Forward only, no command */
void muxserver_listen(void);
void muxclient(const char *);

View File

@ -904,6 +904,9 @@
/* Define to 1 if you have the `strnvis' function. */
/* #undef HAVE_STRNVIS */
/* Define to 1 if you have the `strptime' function. */
#define HAVE_STRPTIME 1
/* Define to 1 if you have the `strsep' function. */
#define HAVE_STRSEP 1

View File

@ -900,6 +900,9 @@
/* Define to 1 if you have the `strnvis' function. */
#undef HAVE_STRNVIS
/* Define to 1 if you have the `strptime' function. */
#undef HAVE_STRPTIME
/* Define to 1 if you have the `strsep' function. */
#undef HAVE_STRSEP

View File

@ -1,4 +1,4 @@
/* $OpenBSD: jpake.c,v 1.2 2009/03/05 07:18:19 djm Exp $ */
/* $OpenBSD: jpake.c,v 1.4 2010/07/13 23:13:16 djm Exp $ */
/*
* Copyright (c) 2008 Damien Miller. All rights reserved.
*
@ -434,7 +434,7 @@ jpake_check_confirm(const BIGNUM *k,
if (peer_confirm_hash_len != expected_confirm_hash_len)
error("%s: confirmation length mismatch (my %u them %u)",
__func__, expected_confirm_hash_len, peer_confirm_hash_len);
else if (memcmp(peer_confirm_hash, expected_confirm_hash,
else if (timingsafe_bcmp(peer_confirm_hash, expected_confirm_hash,
expected_confirm_hash_len) == 0)
success = 1;
bzero(expected_confirm_hash, expected_confirm_hash_len);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: key.c,v 1.86 2010/03/15 19:40:02 stevesk Exp $ */
/* $OpenBSD: key.c,v 1.90 2010/07/13 23:13:16 djm Exp $ */
/*
* read_bignum():
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -52,6 +52,7 @@
#include "uuencode.h"
#include "buffer.h"
#include "log.h"
#include "misc.h"
#include "ssh2.h"
static struct KeyCert *
@ -61,7 +62,8 @@ cert_new(void)
cert = xcalloc(1, sizeof(*cert));
buffer_init(&cert->certblob);
buffer_init(&cert->constraints);
buffer_init(&cert->critical);
buffer_init(&cert->extensions);
cert->key_id = NULL;
cert->principals = NULL;
cert->signature_key = NULL;
@ -82,6 +84,7 @@ key_new(int type)
switch (k->type) {
case KEY_RSA1:
case KEY_RSA:
case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
if ((rsa = RSA_new()) == NULL)
fatal("key_new: RSA_new failed");
@ -92,6 +95,7 @@ key_new(int type)
k->rsa = rsa;
break;
case KEY_DSA:
case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
if ((dsa = DSA_new()) == NULL)
fatal("key_new: DSA_new failed");
@ -124,6 +128,7 @@ key_add_private(Key *k)
switch (k->type) {
case KEY_RSA1:
case KEY_RSA:
case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
if ((k->rsa->d = BN_new()) == NULL)
fatal("key_new_private: BN_new failed");
@ -139,6 +144,7 @@ key_add_private(Key *k)
fatal("key_new_private: BN_new failed");
break;
case KEY_DSA:
case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
if ((k->dsa->priv_key = BN_new()) == NULL)
fatal("key_new_private: BN_new failed");
@ -165,7 +171,8 @@ cert_free(struct KeyCert *cert)
u_int i;
buffer_free(&cert->certblob);
buffer_free(&cert->constraints);
buffer_free(&cert->critical);
buffer_free(&cert->extensions);
if (cert->key_id != NULL)
xfree(cert->key_id);
for (i = 0; i < cert->nprincipals; i++)
@ -184,12 +191,14 @@ key_free(Key *k)
switch (k->type) {
case KEY_RSA1:
case KEY_RSA:
case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
if (k->rsa != NULL)
RSA_free(k->rsa);
k->rsa = NULL;
break;
case KEY_DSA:
case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
if (k->dsa != NULL)
DSA_free(k->dsa);
@ -219,7 +228,7 @@ cert_compare(struct KeyCert *a, struct KeyCert *b)
return 0;
if (buffer_len(&a->certblob) != buffer_len(&b->certblob))
return 0;
if (memcmp(buffer_ptr(&a->certblob), buffer_ptr(&b->certblob),
if (timingsafe_bcmp(buffer_ptr(&a->certblob), buffer_ptr(&b->certblob),
buffer_len(&a->certblob)) != 0)
return 0;
return 1;
@ -238,11 +247,13 @@ key_equal_public(const Key *a, const Key *b)
switch (a->type) {
case KEY_RSA1:
case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
case KEY_RSA:
return a->rsa != NULL && b->rsa != NULL &&
BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
BN_cmp(a->rsa->n, b->rsa->n) == 0;
case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
case KEY_DSA:
return a->dsa != NULL && b->dsa != NULL &&
@ -304,6 +315,8 @@ key_fingerprint_raw(Key *k, enum fp_type dgst_type, u_int *dgst_raw_length)
case KEY_RSA:
key_to_blob(k, &blob, &len);
break;
case KEY_DSA_CERT_V00:
case KEY_RSA_CERT_V00:
case KEY_DSA_CERT:
case KEY_RSA_CERT:
/* We want a fingerprint of the _key_ not of the cert */
@ -631,6 +644,8 @@ key_read(Key *ret, char **cpp)
case KEY_UNSPEC:
case KEY_RSA:
case KEY_DSA:
case KEY_DSA_CERT_V00:
case KEY_RSA_CERT_V00:
case KEY_DSA_CERT:
case KEY_RSA_CERT:
space = strchr(cp, ' ');
@ -757,11 +772,13 @@ key_write(const Key *key, FILE *f)
error("key_write: failed for RSA key");
return 0;
case KEY_DSA:
case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
if (key->dsa == NULL)
return 0;
break;
case KEY_RSA:
case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
if (key->rsa == NULL)
return 0;
@ -793,6 +810,10 @@ key_type(const Key *k)
return "RSA";
case KEY_DSA:
return "DSA";
case KEY_RSA_CERT_V00:
return "RSA-CERT-V00";
case KEY_DSA_CERT_V00:
return "DSA-CERT-V00";
case KEY_RSA_CERT:
return "RSA-CERT";
case KEY_DSA_CERT:
@ -822,10 +843,14 @@ key_ssh_name(const Key *k)
return "ssh-rsa";
case KEY_DSA:
return "ssh-dss";
case KEY_RSA_CERT:
case KEY_RSA_CERT_V00:
return "ssh-rsa-cert-v00@openssh.com";
case KEY_DSA_CERT:
case KEY_DSA_CERT_V00:
return "ssh-dss-cert-v00@openssh.com";
case KEY_RSA_CERT:
return "ssh-rsa-cert-v01@openssh.com";
case KEY_DSA_CERT:
return "ssh-dss-cert-v01@openssh.com";
}
return "ssh-unknown";
}
@ -836,9 +861,11 @@ key_size(const Key *k)
switch (k->type) {
case KEY_RSA1:
case KEY_RSA:
case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
return BN_num_bits(k->rsa->n);
case KEY_DSA:
case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
return BN_num_bits(k->dsa->p);
}
@ -882,6 +909,8 @@ key_generate(int type, u_int bits)
case KEY_RSA1:
k->rsa = rsa_generate_private_key(bits);
break;
case KEY_RSA_CERT_V00:
case KEY_DSA_CERT_V00:
case KEY_RSA_CERT:
case KEY_DSA_CERT:
fatal("key_generate: cert keys cannot be generated directly");
@ -912,9 +941,12 @@ key_cert_copy(const Key *from_key, struct Key *to_key)
buffer_append(&to->certblob, buffer_ptr(&from->certblob),
buffer_len(&from->certblob));
buffer_append(&to->constraints, buffer_ptr(&from->constraints),
buffer_len(&from->constraints));
buffer_append(&to->critical,
buffer_ptr(&from->critical), buffer_len(&from->critical));
buffer_append(&to->extensions,
buffer_ptr(&from->extensions), buffer_len(&from->extensions));
to->serial = from->serial;
to->type = from->type;
to->key_id = from->key_id == NULL ? NULL : xstrdup(from->key_id);
to->valid_after = from->valid_after;
@ -940,6 +972,7 @@ key_from_private(const Key *k)
Key *n = NULL;
switch (k->type) {
case KEY_DSA:
case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
n = key_new(k->type);
if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) ||
@ -950,6 +983,7 @@ key_from_private(const Key *k)
break;
case KEY_RSA:
case KEY_RSA1:
case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
n = key_new(k->type);
if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
@ -979,8 +1013,12 @@ key_type_from_name(char *name)
} else if (strcmp(name, "ssh-dss") == 0) {
return KEY_DSA;
} else if (strcmp(name, "ssh-rsa-cert-v00@openssh.com") == 0) {
return KEY_RSA_CERT;
return KEY_RSA_CERT_V00;
} else if (strcmp(name, "ssh-dss-cert-v00@openssh.com") == 0) {
return KEY_DSA_CERT_V00;
} else if (strcmp(name, "ssh-rsa-cert-v01@openssh.com") == 0) {
return KEY_RSA_CERT;
} else if (strcmp(name, "ssh-dss-cert-v01@openssh.com") == 0) {
return KEY_DSA_CERT;
}
debug2("key_type_from_name: unknown key type '%s'", name);
@ -1012,26 +1050,31 @@ key_names_valid2(const char *names)
static int
cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen)
{
u_char *principals, *constraints, *sig_key, *sig;
u_int signed_len, plen, clen, sklen, slen, kidlen;
u_char *principals, *critical, *exts, *sig_key, *sig;
u_int signed_len, plen, clen, sklen, slen, kidlen, elen;
Buffer tmp;
char *principal;
int ret = -1;
int v00 = key->type == KEY_DSA_CERT_V00 ||
key->type == KEY_RSA_CERT_V00;
buffer_init(&tmp);
/* Copy the entire key blob for verification and later serialisation */
buffer_append(&key->cert->certblob, blob, blen);
principals = constraints = sig_key = sig = NULL;
if (buffer_get_int_ret(&key->cert->type, b) != 0 ||
elen = 0; /* Not touched for v00 certs */
principals = exts = critical = sig_key = sig = NULL;
if ((!v00 && buffer_get_int64_ret(&key->cert->serial, b) != 0) ||
buffer_get_int_ret(&key->cert->type, b) != 0 ||
(key->cert->key_id = buffer_get_string_ret(b, &kidlen)) == NULL ||
(principals = buffer_get_string_ret(b, &plen)) == NULL ||
buffer_get_int64_ret(&key->cert->valid_after, b) != 0 ||
buffer_get_int64_ret(&key->cert->valid_before, b) != 0 ||
(constraints = buffer_get_string_ret(b, &clen)) == NULL ||
/* skip nonce */ buffer_get_string_ptr_ret(b, NULL) == NULL ||
/* skip reserved */ buffer_get_string_ptr_ret(b, NULL) == NULL ||
(critical = buffer_get_string_ret(b, &clen)) == NULL ||
(!v00 && (exts = buffer_get_string_ret(b, &elen)) == NULL) ||
(v00 && buffer_get_string_ptr_ret(b, NULL) == NULL) || /* nonce */
buffer_get_string_ptr_ret(b, NULL) == NULL || /* reserved */
(sig_key = buffer_get_string_ret(b, &sklen)) == NULL) {
error("%s: parse error", __func__);
goto out;
@ -1078,13 +1121,25 @@ cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen)
buffer_clear(&tmp);
buffer_append(&key->cert->constraints, constraints, clen);
buffer_append(&tmp, constraints, clen);
buffer_append(&key->cert->critical, critical, clen);
buffer_append(&tmp, critical, clen);
/* validate structure */
while (buffer_len(&tmp) != 0) {
if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL ||
buffer_get_string_ptr_ret(&tmp, NULL) == NULL) {
error("%s: Constraints data invalid", __func__);
error("%s: critical option data invalid", __func__);
goto out;
}
}
buffer_clear(&tmp);
buffer_append(&key->cert->extensions, exts, elen);
buffer_append(&tmp, exts, elen);
/* validate structure */
while (buffer_len(&tmp) != 0) {
if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL ||
buffer_get_string_ptr_ret(&tmp, NULL) == NULL) {
error("%s: extension data invalid", __func__);
goto out;
}
}
@ -1121,8 +1176,10 @@ cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen)
buffer_free(&tmp);
if (principals != NULL)
xfree(principals);
if (constraints != NULL)
xfree(constraints);
if (critical != NULL)
xfree(critical);
if (exts != NULL)
xfree(exts);
if (sig_key != NULL)
xfree(sig_key);
if (sig != NULL)
@ -1151,8 +1208,11 @@ key_from_blob(const u_char *blob, u_int blen)
type = key_type_from_name(ktype);
switch (type) {
case KEY_RSA:
case KEY_RSA_CERT:
(void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
/* FALLTHROUGH */
case KEY_RSA:
case KEY_RSA_CERT_V00:
key = key_new(type);
if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 ||
buffer_get_bignum2_ret(&b, key->rsa->n) == -1) {
@ -1166,8 +1226,11 @@ key_from_blob(const u_char *blob, u_int blen)
RSA_print_fp(stderr, key->rsa, 8);
#endif
break;
case KEY_DSA:
case KEY_DSA_CERT:
(void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
/* FALLTHROUGH */
case KEY_DSA:
case KEY_DSA_CERT_V00:
key = key_new(type);
if (buffer_get_bignum2_ret(&b, key->dsa->p) == -1 ||
buffer_get_bignum2_ret(&b, key->dsa->q) == -1 ||
@ -1213,6 +1276,8 @@ key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
}
buffer_init(&b);
switch (key->type) {
case KEY_DSA_CERT_V00:
case KEY_RSA_CERT_V00:
case KEY_DSA_CERT:
case KEY_RSA_CERT:
/* Use the existing blob */
@ -1255,9 +1320,11 @@ key_sign(
const u_char *data, u_int datalen)
{
switch (key->type) {
case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
case KEY_DSA:
return ssh_dss_sign(key, sigp, lenp, data, datalen);
case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
case KEY_RSA:
return ssh_rsa_sign(key, sigp, lenp, data, datalen);
@ -1281,9 +1348,11 @@ key_verify(
return -1;
switch (key->type) {
case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
case KEY_DSA:
return ssh_dss_verify(key, signature, signaturelen, data, datalen);
case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
case KEY_RSA:
return ssh_rsa_verify(key, signature, signaturelen, data, datalen);
@ -1306,6 +1375,7 @@ key_demote(const Key *k)
pk->rsa = NULL;
switch (k->type) {
case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
key_cert_copy(k, pk);
/* FALLTHROUGH */
@ -1318,6 +1388,7 @@ key_demote(const Key *k)
if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL)
fatal("key_demote: BN_dup failed");
break;
case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
key_cert_copy(k, pk);
/* FALLTHROUGH */
@ -1344,8 +1415,17 @@ key_demote(const Key *k)
int
key_is_cert(const Key *k)
{
return k != NULL &&
(k->type == KEY_RSA_CERT || k->type == KEY_DSA_CERT);
if (k == NULL)
return 0;
switch (k->type) {
case KEY_RSA_CERT_V00:
case KEY_DSA_CERT_V00:
case KEY_RSA_CERT:
case KEY_DSA_CERT:
return 1;
default:
return 0;
}
}
/* Return the cert-less equivalent to a certified key type */
@ -1353,8 +1433,10 @@ int
key_type_plain(int type)
{
switch (type) {
case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
return KEY_RSA;
case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
return KEY_DSA;
default:
@ -1364,16 +1446,16 @@ key_type_plain(int type)
/* Convert a KEY_RSA or KEY_DSA to their _CERT equivalent */
int
key_to_certified(Key *k)
key_to_certified(Key *k, int legacy)
{
switch (k->type) {
case KEY_RSA:
k->cert = cert_new();
k->type = KEY_RSA_CERT;
k->type = legacy ? KEY_RSA_CERT_V00 : KEY_RSA_CERT;
return 0;
case KEY_DSA:
k->cert = cert_new();
k->type = KEY_DSA_CERT;
k->type = legacy ? KEY_DSA_CERT_V00 : KEY_DSA_CERT;
return 0;
default:
error("%s: key has incorrect type %s", __func__, key_type(k));
@ -1386,10 +1468,12 @@ int
key_drop_cert(Key *k)
{
switch (k->type) {
case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
cert_free(k->cert);
k->type = KEY_RSA;
return 0;
case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
cert_free(k->cert);
k->type = KEY_DSA;
@ -1430,13 +1514,21 @@ key_certify(Key *k, Key *ca)
buffer_clear(&k->cert->certblob);
buffer_put_cstring(&k->cert->certblob, key_ssh_name(k));
/* -v01 certs put nonce first */
if (k->type == KEY_DSA_CERT || k->type == KEY_RSA_CERT) {
arc4random_buf(&nonce, sizeof(nonce));
buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
}
switch (k->type) {
case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
buffer_put_bignum2(&k->cert->certblob, k->dsa->p);
buffer_put_bignum2(&k->cert->certblob, k->dsa->q);
buffer_put_bignum2(&k->cert->certblob, k->dsa->g);
buffer_put_bignum2(&k->cert->certblob, k->dsa->pub_key);
break;
case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
buffer_put_bignum2(&k->cert->certblob, k->rsa->e);
buffer_put_bignum2(&k->cert->certblob, k->rsa->n);
@ -1448,6 +1540,10 @@ key_certify(Key *k, Key *ca)
return -1;
}
/* -v01 certs have a serial number next */
if (k->type == KEY_DSA_CERT || k->type == KEY_RSA_CERT)
buffer_put_int64(&k->cert->certblob, k->cert->serial);
buffer_put_int(&k->cert->certblob, k->cert->type);
buffer_put_cstring(&k->cert->certblob, k->cert->key_id);
@ -1461,11 +1557,19 @@ key_certify(Key *k, Key *ca)
buffer_put_int64(&k->cert->certblob, k->cert->valid_after);
buffer_put_int64(&k->cert->certblob, k->cert->valid_before);
buffer_put_string(&k->cert->certblob,
buffer_ptr(&k->cert->constraints),
buffer_len(&k->cert->constraints));
buffer_ptr(&k->cert->critical), buffer_len(&k->cert->critical));
/* -v01 certs have non-critical options here */
if (k->type == KEY_DSA_CERT || k->type == KEY_RSA_CERT) {
buffer_put_string(&k->cert->certblob,
buffer_ptr(&k->cert->extensions),
buffer_len(&k->cert->extensions));
}
/* -v00 certs put the nonce at the end */
if (k->type == KEY_DSA_CERT_V00 || k->type == KEY_RSA_CERT_V00)
buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
arc4random_buf(&nonce, sizeof(nonce));
buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
buffer_put_string(&k->cert->certblob, NULL, 0); /* reserved */
buffer_put_string(&k->cert->certblob, ca_blob, ca_len);
xfree(ca_blob);
@ -1520,7 +1624,7 @@ key_cert_check_authority(const Key *k, int want_host, int require_principal,
*reason = "Certificate lacks principal list";
return -1;
}
} else {
} else if (name != NULL) {
principal_matches = 0;
for (i = 0; i < k->cert->nprincipals; i++) {
if (strcmp(name, k->cert->principals[i]) == 0) {
@ -1536,3 +1640,15 @@ key_cert_check_authority(const Key *k, int want_host, int require_principal,
}
return 0;
}
int
key_cert_is_legacy(Key *k)
{
switch (k->type) {
case KEY_DSA_CERT_V00:
case KEY_RSA_CERT_V00:
return 1;
default:
return 0;
}
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: key.h,v 1.29 2010/03/15 19:40:02 stevesk Exp $ */
/* $OpenBSD: key.h,v 1.30 2010/04/16 01:47:26 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@ -37,6 +37,8 @@ enum types {
KEY_DSA,
KEY_RSA_CERT,
KEY_DSA_CERT,
KEY_RSA_CERT_V00,
KEY_DSA_CERT_V00,
KEY_UNSPEC
};
enum fp_type {
@ -56,11 +58,13 @@ enum fp_rep {
struct KeyCert {
Buffer certblob; /* Kept around for use on wire */
u_int type; /* SSH2_CERT_TYPE_USER or SSH2_CERT_TYPE_HOST */
u_int64_t serial;
char *key_id;
u_int nprincipals;
char **principals;
u_int64_t valid_after, valid_before;
Buffer constraints;
Buffer critical;
Buffer extensions;
Key *signature_key;
};
@ -92,12 +96,13 @@ Key *key_from_private(const Key *);
int key_type_from_name(char *);
int key_is_cert(const Key *);
int key_type_plain(int);
int key_to_certified(Key *);
int key_to_certified(Key *, int);
int key_drop_cert(Key *);
int key_certify(Key *, Key *);
void key_cert_copy(const Key *, struct Key *);
int key_cert_check_authority(const Key *, int, int, const char *,
const char **);
int key_cert_is_legacy(Key *);
Key *key_from_blob(const u_char *, u_int);
int key_to_blob(const Key *, u_char **, u_int *);

View File

@ -56,7 +56,7 @@ union login_netinfo {
/* string lengths - set very long */
#define LINFO_PROGSIZE 64
#define LINFO_LINESIZE 64
#define LINFO_NAMESIZE 128
#define LINFO_NAMESIZE 512
#define LINFO_HOSTSIZE 256
struct logininfo {

View File

@ -1,4 +1,4 @@
/* $OpenBSD: misc.c,v 1.75 2010/01/09 23:04:13 dtucker Exp $ */
/* $OpenBSD: misc.c,v 1.80 2010/07/21 02:10:58 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2005,2006 Damien Miller. All rights reserved.
@ -178,6 +178,7 @@ strdelim(char **s)
return (NULL); /* no matching quote */
} else {
*s[0] = '\0';
*s += strspn(*s + 1, WHITESPACE) + 1;
return (old);
}
}
@ -425,7 +426,7 @@ colon(char *cp)
int flag = 0;
if (*cp == ':') /* Leading colon is part of file name. */
return (0);
return NULL;
if (*cp == '[')
flag = 1;
@ -437,9 +438,9 @@ colon(char *cp)
if (*cp == ':' && !flag)
return (cp);
if (*cp == '/')
return (0);
return NULL;
}
return (0);
return NULL;
}
/* function to assist building execv() arguments */
@ -849,6 +850,16 @@ ms_to_timeval(struct timeval *tv, int ms)
tv->tv_usec = (ms % 1000) * 1000;
}
int
timingsafe_bcmp(const void *b1, const void *b2, size_t n)
{
const unsigned char *p1 = b1, *p2 = b2;
int ret = 0;
for (; n > 0; n--)
ret |= *p1++ ^ *p2++;
return (ret != 0);
}
void
sock_set_v6only(int s)
{

View File

@ -1,4 +1,4 @@
/* $OpenBSD: misc.h,v 1.41 2010/01/09 23:04:13 dtucker Exp $ */
/* $OpenBSD: misc.h,v 1.43 2010/07/13 23:13:16 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -36,6 +36,7 @@ void sanitise_stdfd(void);
void ms_subtract_diff(struct timeval *, int *);
void ms_to_timeval(struct timeval *, int);
void sock_set_v6only(int);
int timingsafe_bcmp(const void *, const void *, size_t);
struct passwd *pwcopy(struct passwd *);
const char *ssh_gai_strerror(int);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: monitor.c,v 1.106 2010/03/07 11:57:13 dtucker Exp $ */
/* $OpenBSD: monitor.c,v 1.108 2010/07/13 23:13:16 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
@ -518,7 +518,7 @@ monitor_allowed_key(u_char *blob, u_int bloblen)
{
/* make sure key is allowed */
if (key_blob == NULL || key_bloblen != bloblen ||
memcmp(key_blob, blob, key_bloblen))
timingsafe_bcmp(key_blob, blob, key_bloblen))
return (0);
return (1);
}
@ -922,8 +922,8 @@ mm_answer_pam_init_ctx(int sock, Buffer *m)
int
mm_answer_pam_query(int sock, Buffer *m)
{
char *name, *info, **prompts;
u_int i, num, *echo_on;
char *name = NULL, *info = NULL, **prompts = NULL;
u_int i, num = 0, *echo_on = 0;
int ret;
debug3("%s", __func__);
@ -1103,14 +1103,14 @@ monitor_valid_userblob(u_char *data, u_int datalen)
len = buffer_len(&b);
if ((session_id2 == NULL) ||
(len < session_id2_len) ||
(memcmp(p, session_id2, session_id2_len) != 0))
(timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
fail++;
buffer_consume(&b, session_id2_len);
} else {
p = buffer_get_string(&b, &len);
if ((session_id2 == NULL) ||
(len != session_id2_len) ||
(memcmp(p, session_id2, session_id2_len) != 0))
(timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
fail++;
xfree(p);
}
@ -1158,7 +1158,7 @@ monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser,
p = buffer_get_string(&b, &len);
if ((session_id2 == NULL) ||
(len != session_id2_len) ||
(memcmp(p, session_id2, session_id2_len) != 0))
(timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
fail++;
xfree(p);
@ -1682,9 +1682,9 @@ mm_get_kex(Buffer *m)
kex = xcalloc(1, sizeof(*kex));
kex->session_id = buffer_get_string(m, &kex->session_id_len);
if ((session_id2 == NULL) ||
(kex->session_id_len != session_id2_len) ||
(memcmp(kex->session_id, session_id2, session_id2_len) != 0))
if (session_id2 == NULL ||
kex->session_id_len != session_id2_len ||
timingsafe_bcmp(kex->session_id, session_id2, session_id2_len) != 0)
fatal("mm_get_get: internal error: bad session id");
kex->we_need = buffer_get_int(m);
kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: mux.c,v 1.14 2010/01/30 02:54:53 djm Exp $ */
/* $OpenBSD: mux.c,v 1.21 2010/06/25 23:15:36 djm Exp $ */
/*
* Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
*
@ -71,6 +71,7 @@
#include "xmalloc.h"
#include "log.h"
#include "ssh.h"
#include "ssh2.h"
#include "pathnames.h"
#include "misc.h"
#include "match.h"
@ -106,6 +107,14 @@ struct mux_session_confirm_ctx {
char *term;
struct termios tio;
char **env;
u_int rid;
};
/* Context for global channel callback */
struct mux_channel_confirm_ctx {
u_int cid; /* channel id */
u_int rid; /* request id */
int fid; /* forward id */
};
/* fd to control socket */
@ -143,13 +152,14 @@ struct mux_master_state {
#define MUX_S_EXIT_MESSAGE 0x80000004
#define MUX_S_ALIVE 0x80000005
#define MUX_S_SESSION_OPENED 0x80000006
#define MUX_S_REMOTE_PORT 0x80000007
/* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */
#define MUX_FWD_LOCAL 1
#define MUX_FWD_REMOTE 2
#define MUX_FWD_DYNAMIC 3
static void mux_session_confirm(int, void *);
static void mux_session_confirm(int, int, void *);
static int process_mux_master_hello(u_int, Channel *, Buffer *, Buffer *);
static int process_mux_new_session(u_int, Channel *, Buffer *, Buffer *);
@ -206,7 +216,7 @@ mux_master_control_cleanup_cb(int cid, void *unused)
fatal("%s: channel_by_id(%i) == NULL", __func__, cid);
if (c->remote_id != -1) {
if ((sc = channel_by_id(c->remote_id)) == NULL)
debug2("%s: channel %d n session channel %d",
fatal("%s: channel %d missing session channel %d",
__func__, c->self, c->remote_id);
c->remote_id = -1;
sc->ctl_chan = -1;
@ -301,6 +311,7 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
/* Reply for SSHMUX_COMMAND_OPEN */
cctx = xcalloc(1, sizeof(*cctx));
cctx->term = NULL;
cctx->rid = rid;
cmd = reserved = NULL;
if ((reserved = buffer_get_string_ret(m, NULL)) == NULL ||
buffer_get_int_ret(&cctx->want_tty, m) != 0 ||
@ -454,14 +465,10 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
channel_send_open(nc->self);
channel_register_open_confirm(nc->self, mux_session_confirm, cctx);
channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 0);
/* prepare reply */
/* XXX defer until mux_session_confirm() fires */
buffer_put_int(r, MUX_S_SESSION_OPENED);
buffer_put_int(r, rid);
buffer_put_int(r, nc->self);
c->mux_pause = 1; /* stop handling messages until open_confirm done */
channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1);
/* reply is deferred, sent by mux_session_confirm */
return 0;
}
@ -559,6 +566,61 @@ compare_forward(Forward *a, Forward *b)
return 1;
}
static void
mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
{
struct mux_channel_confirm_ctx *fctx = ctxt;
char *failmsg = NULL;
Forward *rfwd;
Channel *c;
Buffer out;
if ((c = channel_by_id(fctx->cid)) == NULL) {
/* no channel for reply */
error("%s: unknown channel", __func__);
return;
}
buffer_init(&out);
if (fctx->fid >= options.num_remote_forwards) {
xasprintf(&failmsg, "unknown forwarding id %d", fctx->fid);
goto fail;
}
rfwd = &options.remote_forwards[fctx->fid];
debug("%s: %s for: listen %d, connect %s:%d", __func__,
type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
rfwd->listen_port, rfwd->connect_host, rfwd->connect_port);
if (type == SSH2_MSG_REQUEST_SUCCESS) {
if (rfwd->listen_port == 0) {
rfwd->allocated_port = packet_get_int();
logit("Allocated port %u for mux remote forward"
" to %s:%d", rfwd->allocated_port,
rfwd->connect_host, rfwd->connect_port);
buffer_put_int(&out, MUX_S_REMOTE_PORT);
buffer_put_int(&out, fctx->rid);
buffer_put_int(&out, rfwd->allocated_port);
} else {
buffer_put_int(&out, MUX_S_OK);
buffer_put_int(&out, fctx->rid);
}
goto out;
} else {
xasprintf(&failmsg, "remote port forwarding failed for "
"listen port %d", rfwd->listen_port);
}
fail:
error("%s: %s", __func__, failmsg);
buffer_put_int(&out, MUX_S_FAILURE);
buffer_put_int(&out, fctx->rid);
buffer_put_cstring(&out, failmsg);
xfree(failmsg);
out:
buffer_put_string(&c->output, buffer_ptr(&out), buffer_len(&out));
buffer_free(&out);
if (c->mux_pause <= 0)
fatal("%s: mux_pause %d", __func__, c->mux_pause);
c->mux_pause = 0; /* start processing messages again */
}
static int
process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
{
@ -594,15 +656,16 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
ftype != MUX_FWD_DYNAMIC) {
logit("%s: invalid forwarding type %u", __func__, ftype);
invalid:
xfree(fwd.listen_host);
xfree(fwd.connect_host);
if (fwd.listen_host)
xfree(fwd.listen_host);
if (fwd.connect_host)
xfree(fwd.connect_host);
buffer_put_int(r, MUX_S_FAILURE);
buffer_put_int(r, rid);
buffer_put_cstring(r, "Invalid forwarding request");
return 0;
}
/* XXX support rport0 forwarding with reply of port assigned */
if (fwd.listen_port == 0 || fwd.listen_port >= 65536) {
if (fwd.listen_port >= 65536) {
logit("%s: invalid listen port %u", __func__,
fwd.listen_port);
goto invalid;
@ -637,8 +700,17 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
case MUX_FWD_REMOTE:
for (i = 0; i < options.num_remote_forwards; i++) {
if (compare_forward(&fwd,
options.remote_forwards + i))
goto exists;
options.remote_forwards + i)) {
if (fwd.listen_port != 0)
goto exists;
debug2("%s: found allocated port",
__func__);
buffer_put_int(r, MUX_S_REMOTE_PORT);
buffer_put_int(r, rid);
buffer_put_int(r,
options.remote_forwards[i].allocated_port);
goto out;
}
}
break;
}
@ -655,9 +727,7 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
}
if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) {
if (options.num_local_forwards + 1 >=
SSH_MAX_FORWARDS_PER_DIRECTION ||
channel_setup_local_fwd_listener(fwd.listen_host,
if (channel_setup_local_fwd_listener(fwd.listen_host,
fwd.listen_port, fwd.connect_host, fwd.connect_port,
options.gateway_ports) < 0) {
fail:
@ -670,14 +740,22 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
add_local_forward(&options, &fwd);
freefwd = 0;
} else {
/* XXX wait for remote to confirm */
if (options.num_remote_forwards + 1 >=
SSH_MAX_FORWARDS_PER_DIRECTION ||
channel_request_remote_forwarding(fwd.listen_host,
struct mux_channel_confirm_ctx *fctx;
if (channel_request_remote_forwarding(fwd.listen_host,
fwd.listen_port, fwd.connect_host, fwd.connect_port) < 0)
goto fail;
add_remote_forward(&options, &fwd);
fctx = xcalloc(1, sizeof(*fctx));
fctx->cid = c->self;
fctx->rid = rid;
fctx->fid = options.num_remote_forwards - 1;
client_register_global_confirm(mux_confirm_remote_forward,
fctx);
freefwd = 0;
c->mux_pause = 1; /* wait for mux_confirm_remote_forward */
/* delayed reply in mux_confirm_remote_forward */
goto out;
}
buffer_put_int(r, MUX_S_OK);
buffer_put_int(r, rid);
@ -826,7 +904,7 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
debug2("%s: channel_new: %d linked to control channel %d",
__func__, nc->self, nc->ctl_chan);
channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 0);
channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1);
/* prepare reply */
/* XXX defer until channel confirmed */
@ -849,7 +927,7 @@ mux_master_read_cb(Channel *c)
/* Setup ctx and */
if (c->mux_ctx == NULL) {
state = xcalloc(1, sizeof(state));
state = xcalloc(1, sizeof(*state));
c->mux_ctx = state;
channel_register_cleanup(c->self,
mux_master_control_cleanup_cb, 0);
@ -1000,26 +1078,43 @@ muxserver_listen(void)
/* Callback on open confirmation in mux master for a mux client session. */
static void
mux_session_confirm(int id, void *arg)
mux_session_confirm(int id, int success, void *arg)
{
struct mux_session_confirm_ctx *cctx = arg;
const char *display;
Channel *c;
Channel *c, *cc;
int i;
Buffer reply;
if (cctx == NULL)
fatal("%s: cctx == NULL", __func__);
if ((c = channel_by_id(id)) == NULL)
fatal("%s: no channel for id %d", __func__, id);
if ((cc = channel_by_id(c->ctl_chan)) == NULL)
fatal("%s: channel %d lacks control channel %d", __func__,
id, c->ctl_chan);
if (!success) {
debug3("%s: sending failure reply", __func__);
/* prepare reply */
buffer_init(&reply);
buffer_put_int(&reply, MUX_S_FAILURE);
buffer_put_int(&reply, cctx->rid);
buffer_put_cstring(&reply, "Session open refused by peer");
goto done;
}
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);
options.forward_x11_trusted, options.forward_x11_timeout,
&proto, &data);
/* Request forwarding with authentication spoofing. */
debug("Requesting X11 forwarding with authentication spoofing.");
debug("Requesting X11 forwarding with authentication "
"spoofing.");
x11_request_forwarding_with_spoofing(id, display, proto, data);
/* XXX wait for reply */
}
@ -1033,6 +1128,21 @@ mux_session_confirm(int id, void *arg)
client_session2_setup(id, cctx->want_tty, cctx->want_subsys,
cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env);
debug3("%s: sending success reply", __func__);
/* prepare reply */
buffer_init(&reply);
buffer_put_int(&reply, MUX_S_SESSION_OPENED);
buffer_put_int(&reply, cctx->rid);
buffer_put_int(&reply, c->self);
done:
/* Send reply */
buffer_put_string(&cc->output, buffer_ptr(&reply), buffer_len(&reply));
buffer_free(&reply);
if (cc->mux_pause <= 0)
fatal("%s: mux_pause %d", __func__, cc->mux_pause);
cc->mux_pause = 0; /* start processing messages again */
c->open_confirm_ctx = NULL;
buffer_free(&cctx->cmd);
xfree(cctx->term);
@ -1365,6 +1475,15 @@ mux_client_request_forward(int fd, u_int ftype, Forward *fwd)
switch (type) {
case MUX_S_OK:
break;
case MUX_S_REMOTE_PORT:
fwd->allocated_port = buffer_get_int(&m);
logit("Allocated port %u for remote forward to %s:%d",
fwd->allocated_port,
fwd->connect_host ? fwd->connect_host : "",
fwd->connect_port);
if (muxclient_command == SSHMUX_COMMAND_FORWARD)
fprintf(stdout, "%u\n", fwd->allocated_port);
break;
case MUX_S_PERMISSION_DENIED:
e = buffer_get_string(&m, NULL);
buffer_free(&m);
@ -1731,6 +1850,10 @@ muxclient(const char *path)
mux_client_request_terminate(sock);
fprintf(stderr, "Exit request sent.\r\n");
exit(0);
case SSHMUX_COMMAND_FORWARD:
if (mux_client_request_forwards(sock) != 0)
fatal("%s: master forward request failed", __func__);
exit(0);
case SSHMUX_COMMAND_OPEN:
if (mux_client_request_forwards(sock) != 0) {
error("%s: master forward request failed", __func__);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: myproposal.h,v 1.24 2010/02/26 20:29:54 djm Exp $ */
/* $OpenBSD: myproposal.h,v 1.25 2010/04/16 01:47:26 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@ -40,9 +40,12 @@
"diffie-hellman-group1-sha1"
#endif
#define KEX_DEFAULT_PK_ALG "ssh-rsa-cert-v00@openssh.com," \
"ssh-dss-cert-v00@openssh.com," \
"ssh-rsa,ssh-dss"
#define KEX_DEFAULT_PK_ALG \
"ssh-rsa-cert-v01@openssh.com," \
"ssh-dss-cert-v01@openssh.com," \
"ssh-rsa-cert-v00@openssh.com," \
"ssh-dss-cert-v00@openssh.com," \
"ssh-rsa,ssh-dss"
#define KEX_DEFAULT_ENCRYPT \
"aes128-ctr,aes192-ctr,aes256-ctr," \

View File

@ -1,4 +1,4 @@
/* $Id: openbsd-compat.h,v 1.49 2010/01/16 12:58:37 dtucker Exp $ */
/* $Id: openbsd-compat.h,v 1.50 2010/08/16 03:15:23 dtucker Exp $ */
/*
* Copyright (c) 1999-2003 Damien Miller. All rights reserved.
@ -87,6 +87,11 @@ int setenv(register const char *name, register const char *value, int rewrite);
void strmode(int mode, char *p);
#endif
#ifndef HAVE_STRPTIME
#include <time.h>
char *strptime(const char *buf, const char *fmt, struct tm *tm);
#endif
#if !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP)
int mkstemps(char *path, int slen);
int mkstemp(char *path);

View File

@ -1,4 +1,4 @@
/* $Id: openssl-compat.h,v 1.14 2009/03/07 11:22:35 dtucker Exp $ */
/* $Id: openssl-compat.h,v 1.15 2010/05/12 07:50:02 djm Exp $ */
/*
* Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au>
@ -18,6 +18,16 @@
#include "includes.h"
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
/* Only in 0.9.8 */
#ifndef OPENSSL_DSA_MAX_MODULUS_BITS
# define OPENSSL_DSA_MAX_MODULUS_BITS 10000
#endif
#ifndef OPENSSL_RSA_MAX_MODULUS_BITS
# define OPENSSL_RSA_MAX_MODULUS_BITS 16384
#endif
/* OPENSSL_free() is Free() in versions before OpenSSL 0.9.6 */
#if !defined(OPENSSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x0090600f)
@ -97,3 +107,4 @@ int ssh_EVP_Cipher(EVP_CIPHER_CTX *, char *, char *, int);
int ssh_EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *);
void ssh_SSLeay_add_all_algorithms(void);
#endif /* SSH_DONT_OVERLOAD_OPENSSL_FUNCS */

View File

@ -173,9 +173,11 @@ sys_tun_open(int tun, int mode)
if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)
goto failed;
ifr.ifr_flags |= IFF_UP;
if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
goto failed;
if ((ifr.ifr_flags & IFF_UP) == 0) {
ifr.ifr_flags |= IFF_UP;
if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
goto failed;
}
close(sock);
return (fd);

View File

@ -39,10 +39,10 @@
#include "xmalloc.h"
#include "packet.h"
#include "buffer.h"
#include "key.h"
#include "auth-options.h"
#include "log.h"
#include "servconf.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "ssh.h"

View File

@ -0,0 +1,401 @@
/* $OpenBSD: strptime.c,v 1.12 2008/06/26 05:42:05 ray Exp $ */
/* $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $ */
/*-
* Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code was contributed to The NetBSD Foundation by Klaus Klein.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``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 FOUNDATION OR CONTRIBUTORS
* 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/libc/time/strptime.c */
#include "includes.h"
#ifndef HAVE_STRPTIME
#define TM_YEAR_BASE 1900 /* from tzfile.h */
#include <ctype.h>
#include <locale.h>
#include <string.h>
#include <time.h>
/* #define _ctloc(x) (_CurrentTimeLocale->x) */
/*
* We do not implement alternate representations. However, we always
* check whether a given modifier is allowed for a certain conversion.
*/
#define _ALT_E 0x01
#define _ALT_O 0x02
#define _LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); }
static int _conv_num(const unsigned char **, int *, int, int);
static char *_strptime(const char *, const char *, struct tm *, int);
char *
strptime(const char *buf, const char *fmt, struct tm *tm)
{
return(_strptime(buf, fmt, tm, 1));
}
static char *
_strptime(const char *buf, const char *fmt, struct tm *tm, int initialize)
{
unsigned char c;
const unsigned char *bp;
size_t len;
int alt_format, i;
static int century, relyear;
if (initialize) {
century = TM_YEAR_BASE;
relyear = -1;
}
bp = (unsigned char *)buf;
while ((c = *fmt) != '\0') {
/* Clear `alternate' modifier prior to new conversion. */
alt_format = 0;
/* Eat up white-space. */
if (isspace(c)) {
while (isspace(*bp))
bp++;
fmt++;
continue;
}
if ((c = *fmt++) != '%')
goto literal;
again: switch (c = *fmt++) {
case '%': /* "%%" is converted to "%". */
literal:
if (c != *bp++)
return (NULL);
break;
/*
* "Alternative" modifiers. Just set the appropriate flag
* and start over again.
*/
case 'E': /* "%E?" alternative conversion modifier. */
_LEGAL_ALT(0);
alt_format |= _ALT_E;
goto again;
case 'O': /* "%O?" alternative conversion modifier. */
_LEGAL_ALT(0);
alt_format |= _ALT_O;
goto again;
/*
* "Complex" conversion rules, implemented through recursion.
*/
#if 0
case 'c': /* Date and time, using the locale's format. */
_LEGAL_ALT(_ALT_E);
if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, 0)))
return (NULL);
break;
#endif
case 'D': /* The date as "%m/%d/%y". */
_LEGAL_ALT(0);
if (!(bp = _strptime(bp, "%m/%d/%y", tm, 0)))
return (NULL);
break;
case 'R': /* The time as "%H:%M". */
_LEGAL_ALT(0);
if (!(bp = _strptime(bp, "%H:%M", tm, 0)))
return (NULL);
break;
case 'r': /* The time as "%I:%M:%S %p". */
_LEGAL_ALT(0);
if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, 0)))
return (NULL);
break;
case 'T': /* The time as "%H:%M:%S". */
_LEGAL_ALT(0);
if (!(bp = _strptime(bp, "%H:%M:%S", tm, 0)))
return (NULL);
break;
#if 0
case 'X': /* The time, using the locale's format. */
_LEGAL_ALT(_ALT_E);
if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, 0)))
return (NULL);
break;
case 'x': /* The date, using the locale's format. */
_LEGAL_ALT(_ALT_E);
if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, 0)))
return (NULL);
break;
#endif
/*
* "Elementary" conversion rules.
*/
#if 0
case 'A': /* The day of week, using the locale's form. */
case 'a':
_LEGAL_ALT(0);
for (i = 0; i < 7; i++) {
/* Full name. */
len = strlen(_ctloc(day[i]));
if (strncasecmp(_ctloc(day[i]), bp, len) == 0)
break;
/* Abbreviated name. */
len = strlen(_ctloc(abday[i]));
if (strncasecmp(_ctloc(abday[i]), bp, len) == 0)
break;
}
/* Nothing matched. */
if (i == 7)
return (NULL);
tm->tm_wday = i;
bp += len;
break;
case 'B': /* The month, using the locale's form. */
case 'b':
case 'h':
_LEGAL_ALT(0);
for (i = 0; i < 12; i++) {
/* Full name. */
len = strlen(_ctloc(mon[i]));
if (strncasecmp(_ctloc(mon[i]), bp, len) == 0)
break;
/* Abbreviated name. */
len = strlen(_ctloc(abmon[i]));
if (strncasecmp(_ctloc(abmon[i]), bp, len) == 0)
break;
}
/* Nothing matched. */
if (i == 12)
return (NULL);
tm->tm_mon = i;
bp += len;
break;
#endif
case 'C': /* The century number. */
_LEGAL_ALT(_ALT_E);
if (!(_conv_num(&bp, &i, 0, 99)))
return (NULL);
century = i * 100;
break;
case 'd': /* The day of month. */
case 'e':
_LEGAL_ALT(_ALT_O);
if (!(_conv_num(&bp, &tm->tm_mday, 1, 31)))
return (NULL);
break;
case 'k': /* The hour (24-hour clock representation). */
_LEGAL_ALT(0);
/* FALLTHROUGH */
case 'H':
_LEGAL_ALT(_ALT_O);
if (!(_conv_num(&bp, &tm->tm_hour, 0, 23)))
return (NULL);
break;
case 'l': /* The hour (12-hour clock representation). */
_LEGAL_ALT(0);
/* FALLTHROUGH */
case 'I':
_LEGAL_ALT(_ALT_O);
if (!(_conv_num(&bp, &tm->tm_hour, 1, 12)))
return (NULL);
break;
case 'j': /* The day of year. */
_LEGAL_ALT(0);
if (!(_conv_num(&bp, &tm->tm_yday, 1, 366)))
return (NULL);
tm->tm_yday--;
break;
case 'M': /* The minute. */
_LEGAL_ALT(_ALT_O);
if (!(_conv_num(&bp, &tm->tm_min, 0, 59)))
return (NULL);
break;
case 'm': /* The month. */
_LEGAL_ALT(_ALT_O);
if (!(_conv_num(&bp, &tm->tm_mon, 1, 12)))
return (NULL);
tm->tm_mon--;
break;
#if 0
case 'p': /* The locale's equivalent of AM/PM. */
_LEGAL_ALT(0);
/* AM? */
len = strlen(_ctloc(am_pm[0]));
if (strncasecmp(_ctloc(am_pm[0]), bp, len) == 0) {
if (tm->tm_hour > 12) /* i.e., 13:00 AM ?! */
return (NULL);
else if (tm->tm_hour == 12)
tm->tm_hour = 0;
bp += len;
break;
}
/* PM? */
len = strlen(_ctloc(am_pm[1]));
if (strncasecmp(_ctloc(am_pm[1]), bp, len) == 0) {
if (tm->tm_hour > 12) /* i.e., 13:00 PM ?! */
return (NULL);
else if (tm->tm_hour < 12)
tm->tm_hour += 12;
bp += len;
break;
}
/* Nothing matched. */
return (NULL);
#endif
case 'S': /* The seconds. */
_LEGAL_ALT(_ALT_O);
if (!(_conv_num(&bp, &tm->tm_sec, 0, 61)))
return (NULL);
break;
case 'U': /* The week of year, beginning on sunday. */
case 'W': /* The week of year, beginning on monday. */
_LEGAL_ALT(_ALT_O);
/*
* XXX This is bogus, as we can not assume any valid
* information present in the tm structure at this
* point to calculate a real value, so just check the
* range for now.
*/
if (!(_conv_num(&bp, &i, 0, 53)))
return (NULL);
break;
case 'w': /* The day of week, beginning on sunday. */
_LEGAL_ALT(_ALT_O);
if (!(_conv_num(&bp, &tm->tm_wday, 0, 6)))
return (NULL);
break;
case 'Y': /* The year. */
_LEGAL_ALT(_ALT_E);
if (!(_conv_num(&bp, &i, 0, 9999)))
return (NULL);
relyear = -1;
tm->tm_year = i - TM_YEAR_BASE;
break;
case 'y': /* The year within the century (2 digits). */
_LEGAL_ALT(_ALT_E | _ALT_O);
if (!(_conv_num(&bp, &relyear, 0, 99)))
return (NULL);
break;
/*
* Miscellaneous conversions.
*/
case 'n': /* Any kind of white-space. */
case 't':
_LEGAL_ALT(0);
while (isspace(*bp))
bp++;
break;
default: /* Unknown/unsupported conversion. */
return (NULL);
}
}
/*
* We need to evaluate the two digit year spec (%y)
* last as we can get a century spec (%C) at any time.
*/
if (relyear != -1) {
if (century == TM_YEAR_BASE) {
if (relyear <= 68)
tm->tm_year = relyear + 2000 - TM_YEAR_BASE;
else
tm->tm_year = relyear + 1900 - TM_YEAR_BASE;
} else {
tm->tm_year = relyear + century - TM_YEAR_BASE;
}
}
return ((char *)bp);
}
static int
_conv_num(const unsigned char **buf, int *dest, int llim, int ulim)
{
int result = 0;
int rulim = ulim;
if (**buf < '0' || **buf > '9')
return (0);
/* we use rulim to break out of the loop when we run out of digits */
do {
result *= 10;
result += *(*buf)++ - '0';
rulim /= 10;
} while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
if (result < llim || result > ulim)
return (0);
*dest = result;
return (1);
}
#endif /* HAVE_STRPTIME */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: packet.c,v 1.166 2009/06/27 09:29:06 andreas Exp $ */
/* $OpenBSD: packet.c,v 1.168 2010/07/13 23:13:16 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -1307,7 +1307,7 @@ packet_read_poll2(u_int32_t *seqnr_p)
macbuf = mac_compute(mac, active_state->p_read.seqnr,
buffer_ptr(&active_state->incoming_packet),
buffer_len(&active_state->incoming_packet));
if (memcmp(macbuf, buffer_ptr(&active_state->input),
if (timingsafe_bcmp(macbuf, buffer_ptr(&active_state->input),
mac->mac_len) != 0) {
logit("Corrupted MAC on input.");
if (need > PACKET_MAX_SIZE)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readconf.c,v 1.183 2010/02/08 10:50:20 markus Exp $ */
/* $OpenBSD: readconf.c,v 1.187 2010/07/19 09:15:12 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -113,8 +113,8 @@ __RCSID("$FreeBSD$");
typedef enum {
oBadOption,
oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts,
oExitOnForwardFailure,
oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
oGatewayPorts, oExitOnForwardFailure,
oPasswordAuthentication, oRSAAuthentication,
oChallengeResponseAuthentication, oXAuthLocation,
oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
@ -131,7 +131,8 @@ typedef enum {
oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
oAddressFamily, oGssAuthentication, oGssDelegateCreds,
oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
oSendEnv, oControlPath, oControlMaster, oControlPersist,
oHashKnownHosts,
oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
oVersionAddendum,
@ -147,6 +148,7 @@ static struct {
{ "forwardagent", oForwardAgent },
{ "forwardx11", oForwardX11 },
{ "forwardx11trusted", oForwardX11Trusted },
{ "forwardx11timeout", oForwardX11Timeout },
{ "exitonforwardfailure", oExitOnForwardFailure },
{ "xauthlocation", oXAuthLocation },
{ "gatewayports", oGatewayPorts },
@ -228,6 +230,7 @@ static struct {
{ "sendenv", oSendEnv },
{ "controlpath", oControlPath },
{ "controlmaster", oControlMaster },
{ "controlpersist", oControlPersist },
{ "hashknownhosts", oHashKnownHosts },
{ "tunnel", oTunnel },
{ "tunneldevice", oTunnelDevice },
@ -272,8 +275,9 @@ add_local_forward(Options *options, const Forward *newfwd)
if (newfwd->listen_port < ipport_reserved && original_real_uid != 0)
fatal("Privileged ports can only be forwarded by root.");
#endif
if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
options->local_forwards = xrealloc(options->local_forwards,
options->num_local_forwards + 1,
sizeof(*options->local_forwards));
fwd = &options->local_forwards[options->num_local_forwards++];
fwd->listen_host = newfwd->listen_host;
@ -291,15 +295,17 @@ void
add_remote_forward(Options *options, const Forward *newfwd)
{
Forward *fwd;
if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
fatal("Too many remote forwards (max %d).",
SSH_MAX_FORWARDS_PER_DIRECTION);
options->remote_forwards = xrealloc(options->remote_forwards,
options->num_remote_forwards + 1,
sizeof(*options->remote_forwards));
fwd = &options->remote_forwards[options->num_remote_forwards++];
fwd->listen_host = newfwd->listen_host;
fwd->listen_port = newfwd->listen_port;
fwd->connect_host = newfwd->connect_host;
fwd->connect_port = newfwd->connect_port;
fwd->allocated_port = 0;
}
static void
@ -312,12 +318,20 @@ clear_forwardings(Options *options)
xfree(options->local_forwards[i].listen_host);
xfree(options->local_forwards[i].connect_host);
}
if (options->num_local_forwards > 0) {
xfree(options->local_forwards);
options->local_forwards = NULL;
}
options->num_local_forwards = 0;
for (i = 0; i < options->num_remote_forwards; i++) {
if (options->remote_forwards[i].listen_host != NULL)
xfree(options->remote_forwards[i].listen_host);
xfree(options->remote_forwards[i].connect_host);
}
if (options->num_remote_forwards > 0) {
xfree(options->remote_forwards);
options->remote_forwards = NULL;
}
options->num_remote_forwards = 0;
options->tun_open = SSH_TUNMODE_NO;
}
@ -420,6 +434,10 @@ process_config_line(Options *options, const char *host,
case oForwardX11Trusted:
intptr = &options->forward_x11_trusted;
goto parse_flag;
case oForwardX11Timeout:
intptr = &options->forward_x11_timeout;
goto parse_time;
case oGatewayPorts:
intptr = &options->gateway_ports;
@ -883,6 +901,30 @@ process_config_line(Options *options, const char *host,
*intptr = value;
break;
case oControlPersist:
/* no/false/yes/true, or a time spec */
intptr = &options->control_persist;
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing ControlPersist"
" argument.", filename, linenum);
value = 0;
value2 = 0; /* timeout */
if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
value = 0;
else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
value = 1;
else if ((value2 = convtime(arg)) >= 0)
value = 1;
else
fatal("%.200s line %d: Bad ControlPersist argument.",
filename, linenum);
if (*activep && *intptr == -1) {
*intptr = value;
options->control_persist_timeout = value2;
}
break;
case oHashKnownHosts:
intptr = &options->hash_known_hosts;
goto parse_flag;
@ -1031,6 +1073,7 @@ initialize_options(Options * options)
options->forward_agent = -1;
options->forward_x11 = -1;
options->forward_x11_trusted = -1;
options->forward_x11_timeout = -1;
options->exit_on_forward_failure = -1;
options->xauth_location = NULL;
options->gateway_ports = -1;
@ -1071,7 +1114,9 @@ initialize_options(Options * options)
options->user_hostfile = NULL;
options->system_hostfile2 = NULL;
options->user_hostfile2 = NULL;
options->local_forwards = NULL;
options->num_local_forwards = 0;
options->remote_forwards = NULL;
options->num_remote_forwards = 0;
options->clear_forwardings = -1;
options->log_level = SYSLOG_LEVEL_NOT_SET;
@ -1088,6 +1133,8 @@ initialize_options(Options * options)
options->num_send_env = 0;
options->control_path = NULL;
options->control_master = -1;
options->control_persist = -1;
options->control_persist_timeout = 0;
options->hash_known_hosts = -1;
options->tun_open = -1;
options->tun_local = -1;
@ -1115,6 +1162,8 @@ fill_default_options(Options * options)
options->forward_x11 = 0;
if (options->forward_x11_trusted == -1)
options->forward_x11_trusted = 0;
if (options->forward_x11_timeout == -1)
options->forward_x11_timeout = 1200;
if (options->exit_on_forward_failure == -1)
options->exit_on_forward_failure = 0;
if (options->xauth_location == NULL)
@ -1221,6 +1270,10 @@ fill_default_options(Options * options)
options->server_alive_count_max = 3;
if (options->control_master == -1)
options->control_master = 0;
if (options->control_persist == -1) {
options->control_persist = 0;
options->control_persist_timeout = 0;
}
if (options->hash_known_hosts == -1)
options->hash_known_hosts = 0;
if (options->tun_open == -1)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readconf.h,v 1.82 2010/02/08 10:50:20 markus Exp $ */
/* $OpenBSD: readconf.h,v 1.86 2010/07/19 09:15:12 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -23,6 +23,7 @@ typedef struct {
int listen_port; /* Port to forward. */
char *connect_host; /* Host to connect. */
int connect_port; /* Port to connect on connect_host. */
int allocated_port; /* Dynamically allocated listen port */
} Forward;
/* Data structure for representing option data. */
@ -31,6 +32,7 @@ typedef struct {
typedef struct {
int forward_agent; /* Forward authentication agent. */
int forward_x11; /* Forward X11 display. */
int forward_x11_timeout; /* Expiration for Cookies */
int forward_x11_trusted; /* Trust Forward X11 display. */
int exit_on_forward_failure; /* Exit if bind(2) fails for -L/-R */
char *xauth_location; /* Location for xauth program */
@ -93,11 +95,11 @@ typedef struct {
/* Local TCP/IP forward requests. */
int num_local_forwards;
Forward local_forwards[SSH_MAX_FORWARDS_PER_DIRECTION];
Forward *local_forwards;
/* Remote TCP/IP forward requests. */
int num_remote_forwards;
Forward remote_forwards[SSH_MAX_FORWARDS_PER_DIRECTION];
Forward *remote_forwards;
int clear_forwardings;
int enable_ssh_keysign;
@ -112,6 +114,8 @@ typedef struct {
char *control_path;
int control_master;
int control_persist; /* ControlPersist flag */
int control_persist_timeout; /* ControlPersist timeout (seconds) */
int hash_known_hosts;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: scp.c,v 1.165 2009/12/20 07:28:36 guenther Exp $ */
/* $OpenBSD: scp.c,v 1.166 2010/07/01 13:06:59 millert Exp $ */
/*
* scp - secure remote copy. This is basically patched BSD rcp which
* uses ssh to do the data transfer (instead of using rcmd).
@ -156,6 +156,20 @@ killchild(int signo)
exit(1);
}
static void
suspchild(int signo)
{
int status;
if (do_cmd_pid > 1) {
kill(do_cmd_pid, signo);
while (waitpid(do_cmd_pid, &status, WUNTRACED) == -1 &&
errno == EINTR)
;
kill(getpid(), SIGSTOP);
}
}
static int
do_local_cmd(arglist *a)
{
@ -232,6 +246,10 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
close(reserved[0]);
close(reserved[1]);
signal(SIGTSTP, suspchild);
signal(SIGTTIN, suspchild);
signal(SIGTTOU, suspchild);
/* Fork a child to execute the command on the remote host using ssh. */
do_cmd_pid = fork();
if (do_cmd_pid == 0) {

View File

@ -1,4 +1,4 @@
/* $OpenBSD: servconf.c,v 1.207 2010/03/25 23:38:28 djm Exp $ */
/* $OpenBSD: servconf.c,v 1.209 2010/06/22 04:22:59 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@ -133,6 +133,7 @@ initialize_server_options(ServerOptions *options)
options->zero_knowledge_password_authentication = -1;
options->revoked_keys_file = NULL;
options->trusted_user_ca_keys = NULL;
options->authorized_principals_file = NULL;
}
void
@ -312,7 +313,7 @@ typedef enum {
sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
sUsePrivilegeSeparation, sAllowAgentForwarding,
sZeroKnowledgePasswordAuthentication, sHostCertificate,
sRevokedKeys, sTrustedUserCAKeys,
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
sVersionAddendum,
sDeprecated, sUnsupported
} ServerOpCodes;
@ -348,7 +349,7 @@ static struct {
{ "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
{ "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL },
{ "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
{ "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_GLOBAL },
{ "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL },
{ "rsaauthentication", sRSAAuthentication, SSHCFG_ALL },
{ "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
{ "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
@ -423,11 +424,11 @@ static struct {
{ "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
{ "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL },
{ "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL },
{ "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_GLOBAL },
{ "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL },
{ "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL },
{ "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_ALL },
{ "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL},
{ "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
{ "permittunnel", sPermitTunnel, SSHCFG_GLOBAL },
{ "permittunnel", sPermitTunnel, SSHCFG_ALL },
{ "match", sMatch, SSHCFG_ALL },
{ "permitopen", sPermitOpen, SSHCFG_ALL },
{ "forcecommand", sForceCommand, SSHCFG_ALL },
@ -435,6 +436,7 @@ static struct {
{ "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
{ "revokedkeys", sRevokedKeys, SSHCFG_ALL },
{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
{ "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
{ NULL, sBadOption, 0 }
};
@ -1222,10 +1224,14 @@ process_server_config_line(ServerOptions *options, char *line,
* AuthorizedKeysFile /etc/ssh_keys/%u
*/
case sAuthorizedKeysFile:
charptr = &options->authorized_keys_file;
goto parse_tilde_filename;
case sAuthorizedKeysFile2:
charptr = (opcode == sAuthorizedKeysFile) ?
&options->authorized_keys_file :
&options->authorized_keys_file2;
charptr = &options->authorized_keys_file2;
goto parse_tilde_filename;
case sAuthorizedPrincipalsFile:
charptr = &options->authorized_principals_file;
parse_tilde_filename:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing file name.",
@ -1451,6 +1457,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
M_CP_INTOPT(pubkey_authentication);
M_CP_INTOPT(kerberos_authentication);
M_CP_INTOPT(hostbased_authentication);
M_CP_INTOPT(hostbased_uses_name_from_packet_only);
M_CP_INTOPT(kbd_interactive_authentication);
M_CP_INTOPT(zero_knowledge_password_authentication);
M_CP_INTOPT(permit_root_login);
@ -1458,6 +1465,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
M_CP_INTOPT(allow_tcp_forwarding);
M_CP_INTOPT(allow_agent_forwarding);
M_CP_INTOPT(permit_tun);
M_CP_INTOPT(gateway_ports);
M_CP_INTOPT(x11_display_offset);
M_CP_INTOPT(x11_forwarding);
@ -1472,6 +1480,9 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
M_CP_STROPT(chroot_directory);
M_CP_STROPT(trusted_user_ca_keys);
M_CP_STROPT(revoked_keys_file);
M_CP_STROPT(authorized_keys_file);
M_CP_STROPT(authorized_keys_file2);
M_CP_STROPT(authorized_principals_file);
}
#undef M_CP_INTOPT
@ -1693,6 +1704,8 @@ dump_config(ServerOptions *o)
dump_cfg_string(sChrootDirectory, o->chroot_directory);
dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);
dump_cfg_string(sRevokedKeys, o->revoked_keys_file);
dump_cfg_string(sAuthorizedPrincipalsFile,
o->authorized_principals_file);
/* string arguments requiring a lookup */
dump_cfg_string(sLogLevel, log_level_name(o->log_level));

View File

@ -1,4 +1,4 @@
/* $OpenBSD: servconf.h,v 1.92 2010/03/04 10:36:03 djm Exp $ */
/* $OpenBSD: servconf.h,v 1.93 2010/05/07 11:30:30 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -156,6 +156,7 @@ typedef struct {
char *chroot_directory;
char *revoked_keys_file;
char *trusted_user_ca_keys;
char *authorized_principals_file;
} ServerOptions;
void initialize_server_options(ServerOptions *);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: session.c,v 1.252 2010/03/07 11:57:13 dtucker Exp $ */
/* $OpenBSD: session.c,v 1.256 2010/06/25 07:20:04 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@ -48,6 +48,7 @@ __RCSID("$FreeBSD$");
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#ifdef HAVE_PATHS_H
#include <paths.h>
@ -105,7 +106,7 @@ __RCSID("$FreeBSD$");
/* func */
Session *session_new(void);
void session_set_fds(Session *, int, int, int, int);
void session_set_fds(Session *, int, int, int, int, int);
void session_pty_cleanup(Session *);
void session_proctitle(Session *);
int session_setup_x11fwd(Session *);
@ -448,6 +449,9 @@ do_exec_no_pty(Session *s, const char *command)
#ifdef USE_PIPES
int pin[2], pout[2], perr[2];
if (s == NULL)
fatal("do_exec_no_pty: no session");
/* Allocate pipes for communicating with the program. */
if (pipe(pin) < 0) {
error("%s: pipe in: %.100s", __func__, strerror(errno));
@ -460,7 +464,8 @@ do_exec_no_pty(Session *s, const char *command)
return -1;
}
if (pipe(perr) < 0) {
error("%s: pipe err: %.100s", __func__, strerror(errno));
error("%s: pipe err: %.100s", __func__,
strerror(errno));
close(pin[0]);
close(pin[1]);
close(pout[0]);
@ -470,22 +475,23 @@ do_exec_no_pty(Session *s, const char *command)
#else
int inout[2], err[2];
if (s == NULL)
fatal("do_exec_no_pty: no session");
/* Uses socket pairs to communicate with the program. */
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));
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. */
@ -596,11 +602,8 @@ do_exec_no_pty(Session *s, const char *command)
close(perr[1]);
if (compat20) {
if (s->is_subsystem) {
close(perr[0]);
perr[0] = -1;
}
session_set_fds(s, pin[1], pout[0], perr[0], 0);
session_set_fds(s, pin[1], pout[0], perr[0],
s->is_subsystem, 0);
} else {
/* Enter the interactive session. */
server_loop(pid, pin[1], pout[0], perr[0]);
@ -616,10 +619,8 @@ do_exec_no_pty(Session *s, const char *command)
* 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], 0);
if (s->is_subsystem)
close(err[1]);
session_set_fds(s, inout[1], inout[1], err[1],
s->is_subsystem, 0);
} else {
server_loop(pid, inout[1], inout[1], err[1]);
/* server_loop has closed inout[1] and err[1]. */
@ -741,7 +742,7 @@ do_exec_pty(Session *s, const char *command)
s->ptymaster = ptymaster;
packet_set_interactive(1);
if (compat20) {
session_set_fds(s, ptyfd, fdout, -1, 1);
session_set_fds(s, ptyfd, fdout, -1, 1, 1);
} else {
server_loop(pid, ptyfd, fdout, -1);
/* server_loop _has_ closed ptyfd and fdout. */
@ -1804,7 +1805,8 @@ do_child(Session *s, const char *command)
#ifdef HAVE_LOGIN_CAP
r = login_getcapbool(lc, "requirehome", 0);
#endif
if (r || options.chroot_directory == NULL)
if (r || options.chroot_directory == NULL ||
strcasecmp(options.chroot_directory, "none") == 0)
fprintf(stderr, "Could not chdir to home "
"directory %s: %s\n", pw->pw_dir,
strerror(errno));
@ -2149,7 +2151,8 @@ session_subsystem_req(Session *s)
u_int i;
packet_check_eom();
logit("subsystem request for %.100s", subsys);
logit("subsystem request for %.100s by user %s", subsys,
s->pw->pw_name);
for (i = 0; i < options.num_subsystems; i++) {
if (strcmp(subsys, options.subsystem_name[i]) == 0) {
@ -2331,7 +2334,8 @@ session_input_channel_req(Channel *c, const char *rtype)
}
void
session_set_fds(Session *s, int fdin, int fdout, int fderr, int is_tty)
session_set_fds(Session *s, int fdin, int fdout, int fderr, int ignore_fderr,
int is_tty)
{
if (!compat20)
fatal("session_set_fds: called for proto != 2.0");
@ -2343,7 +2347,7 @@ session_set_fds(Session *s, int fdin, int fdout, int fderr, int is_tty)
fatal("no channel for session %d", s->self);
channel_set_fds(s->chanid,
fdout, fdin, fderr,
fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
1, is_tty, CHAN_SES_WINDOW_DEFAULT);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sftp-client.c,v 1.90 2009/10/11 10:41:26 dtucker Exp $ */
/* $OpenBSD: sftp-client.c,v 1.92 2010/07/19 03:16:33 djm Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
@ -713,7 +713,8 @@ do_realpath(struct sftp_conn *conn, char *path)
u_int status = buffer_get_int(&msg);
error("Couldn't canonicalise: %s", fx2txt(status));
return(NULL);
buffer_free(&msg);
return NULL;
} else if (type != SSH2_FXP_NAME)
fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
SSH2_FXP_NAME, type);
@ -1522,7 +1523,7 @@ upload_dir_internal(struct sftp_conn *conn, char *src, char *dst,
continue;
if (upload_dir_internal(conn, new_src, new_dst,
pflag, depth + 1, printflag) == -1)
pflag, printflag, depth + 1) == -1)
ret = -1;
} else if (S_ISREG(sb.st_mode)) {
if (do_upload(conn, new_src, new_dst, pflag) == -1) {

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sftp.c,v 1.123 2010/01/27 19:21:39 djm Exp $ */
/* $OpenBSD: sftp.c,v 1.125 2010/06/18 00:58:39 djm Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
@ -181,6 +181,8 @@ static const struct CMD cmds[] = {
{ "ls", I_LS, REMOTE },
{ "lumask", I_LUMASK, NOARGS },
{ "mkdir", I_MKDIR, REMOTE },
{ "mget", I_GET, REMOTE },
{ "mput", I_PUT, LOCAL },
{ "progress", I_PROGRESS, NOARGS },
{ "put", I_PUT, LOCAL },
{ "pwd", I_PWD, REMOTE },
@ -1366,7 +1368,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
break;
case I_LS:
if (!path1) {
do_globbed_ls(conn, *pwd, *pwd, lflag);
do_ls_dir(conn, *pwd, *pwd, lflag);
break;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-add.c,v 1.94 2010/03/01 11:07:06 otto Exp $ */
/* $OpenBSD: ssh-add.c,v 1.96 2010/05/14 00:47:22 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -194,7 +194,7 @@ add_file(AuthenticationConnection *ac, const char *filename)
"Lifetime set to %d seconds\n", lifetime);
if (confirm != 0)
fprintf(stderr,
"The user has to confirm each use of the key\n");
"The user must confirm each use of the key\n");
} else {
fprintf(stderr, "Could not add identity: %s\n", filename);
}
@ -202,29 +202,37 @@ add_file(AuthenticationConnection *ac, const char *filename)
/* Now try to add the certificate flavour too */
xasprintf(&certpath, "%s-cert.pub", filename);
if ((cert = key_load_public(certpath, NULL)) != NULL) {
/* Graft with private bits */
if (key_to_certified(private) != 0)
fatal("%s: key_to_certified failed", __func__);
key_cert_copy(cert, private);
if ((cert = key_load_public(certpath, NULL)) == NULL)
goto out;
if (!key_equal_public(cert, private)) {
error("Certificate %s does not match private key %s",
certpath, filename);
key_free(cert);
goto out;
}
if (ssh_add_identity_constrained(ac, private, comment,
lifetime, confirm)) {
fprintf(stderr, "Certificate added: %s (%s)\n",
certpath, private->cert->key_id);
if (lifetime != 0)
fprintf(stderr, "Lifetime set to %d seconds\n",
lifetime);
if (confirm != 0)
fprintf(stderr, "The user has to confirm each "
"use of the key\n");
} else {
error("Certificate %s (%s) add failed", certpath,
private->cert->key_id);
}
/* Graft with private bits */
if (key_to_certified(private, key_cert_is_legacy(cert)) != 0) {
error("%s: key_to_certified failed", __func__);
key_free(cert);
goto out;
}
key_cert_copy(cert, private);
key_free(cert);
if (!ssh_add_identity_constrained(ac, private, comment,
lifetime, confirm)) {
error("Certificate %s (%s) add failed", certpath,
private->cert->key_id);
}
fprintf(stderr, "Certificate added: %s (%s)\n", certpath,
private->cert->key_id);
if (lifetime != 0)
fprintf(stderr, "Lifetime set to %d seconds\n", lifetime);
if (confirm != 0)
fprintf(stderr, "The user must confirm each use of the key\n");
out:
xfree(certpath);
xfree(comment);
key_free(private);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-agent.c,v 1.165 2010/02/26 20:29:54 djm Exp $ */
/* $OpenBSD: ssh-agent.c,v 1.166 2010/04/16 01:47:26 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -501,6 +501,7 @@ process_add_identity(SocketEntry *e, int version)
buffer_get_bignum2(&e->request, k->dsa->pub_key);
buffer_get_bignum2(&e->request, k->dsa->priv_key);
break;
case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
cert = buffer_get_string(&e->request, &len);
if ((k = key_from_blob(cert, len)) == NULL)
@ -521,6 +522,7 @@ process_add_identity(SocketEntry *e, int version)
/* Generate additional parameters */
rsa_generate_additional_parameters(k->rsa);
break;
case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
cert = buffer_get_string(&e->request, &len);
if ((k = key_from_blob(cert, len)) == NULL)
@ -541,6 +543,7 @@ process_add_identity(SocketEntry *e, int version)
/* enable blinding */
switch (k->type) {
case KEY_RSA:
case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
case KEY_RSA1:
if (RSA_blinding_on(k->rsa, NULL) != 1) {

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-dss.c,v 1.25 2010/02/26 20:29:54 djm Exp $ */
/* $OpenBSD: ssh-dss.c,v 1.26 2010/04/16 01:47:26 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -53,9 +53,8 @@ ssh_dss_sign(const Key *key, u_char **sigp, u_int *lenp,
u_int rlen, slen, len, dlen;
Buffer b;
if (key == NULL ||
(key->type != KEY_DSA && key->type != KEY_DSA_CERT) ||
key->dsa == NULL) {
if (key == NULL || key->dsa == NULL || (key->type != KEY_DSA &&
key->type != KEY_DSA_CERT && key->type != KEY_DSA_CERT_V00)) {
error("ssh_dss_sign: no DSA key");
return -1;
}
@ -118,9 +117,8 @@ ssh_dss_verify(const Key *key, const u_char *signature, u_int signaturelen,
int rlen, ret;
Buffer b;
if (key == NULL ||
(key->type != KEY_DSA && key->type != KEY_DSA_CERT) ||
key->dsa == NULL) {
if (key == NULL || key->dsa == NULL || (key->type != KEY_DSA &&
key->type != KEY_DSA_CERT && key->type != KEY_DSA_CERT_V00)) {
error("ssh_dss_verify: no DSA key");
return -1;
}

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: ssh-keygen.1,v 1.92 2010/03/13 23:38:13 jmc Exp $
.\" $OpenBSD: ssh-keygen.1,v 1.98 2010/08/04 06:07:11 djm Exp $
.\" $FreeBSD$
.\"
.\" -*- nroff -*-
@ -38,15 +38,15 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd March 13, 2010
.Dd August 4, 2010
.Dt SSH-KEYGEN 1
.Os
.Sh NAME
.Nm ssh-keygen
.Nd authentication key generation, management and conversion
.Sh SYNOPSIS
.Nm ssh-keygen
.Bk -words
.Nm ssh-keygen
.Op Fl q
.Op Fl b Ar bits
.Fl t Ar type
@ -60,9 +60,11 @@
.Op Fl f Ar keyfile
.Nm ssh-keygen
.Fl i
.Op Fl m Ar key_format
.Op Fl f Ar input_keyfile
.Nm ssh-keygen
.Fl e
.Op Fl m Ar key_format
.Op Fl f Ar input_keyfile
.Nm ssh-keygen
.Fl y
@ -111,8 +113,9 @@
.Fl I Ar certificate_identity
.Op Fl h
.Op Fl n Ar principals
.Op Fl O Ar constraint
.Op Fl O Ar option
.Op Fl V Ar validity_interval
.Op Fl z Ar serial_number
.Ar
.Nm ssh-keygen
.Fl L
@ -213,13 +216,20 @@ the passphrase if the key has one, and for the new comment.
.It Fl D Ar pkcs11
Download the RSA public keys provided by the PKCS#11 shared library
.Ar pkcs11 .
When used in combination with
.Fl s ,
this option indicates that a CA key resides in a PKCS#11 token (see the
.Sx CERTIFICATES
section for details).
.It Fl e
This option will read a private or public OpenSSH key file and
print the key in
RFC 4716 SSH Public Key File Format
to stdout.
This option allows exporting keys for use by several commercial
SSH implementations.
print to stdout the key in one of the formats specified by the
.Fl m
option.
The default export format is
.Dq RFC4716 .
This option allows exporting OpenSSH keys for use by other programs, including
several commercial SSH implementations.
.It Fl F Ar hostname
Search for the specified
.Ar hostname
@ -270,13 +280,14 @@ Please see the
section for details.
.It Fl i
This option will read an unencrypted private (or public) key file
in SSH2-compatible format and print an OpenSSH compatible private
in the format specified by the
.Fl m
option and print an OpenSSH compatible private
(or public) key to stdout.
.Nm
also reads the
RFC 4716 SSH Public Key File Format.
This option allows importing keys from several commercial
SSH implementations.
This option allows importing keys from other software, including several
commercial SSH implementations.
The default import format is
.Dq RFC4716 .
.It Fl L
Prints the contents of a certificate.
.It Fl l
@ -291,6 +302,22 @@ an ASCII art representation of the key is supplied with the fingerprint.
.It Fl M Ar memory
Specify the amount of memory to use (in megabytes) when generating
candidate moduli for DH-GEX.
.It Fl m Ar key_format
Specify a key format for the
.Fl i
(import) or
.Fl e
(export) conversion options.
The supported key formats are:
.Dq RFC4716
(RFC 4716/SSH2 public or private key),
.Dq PKCS8
(PEM PKCS8 public key)
or
.Dq PEM
(PEM public key).
The default conversion format is
.Dq RFC4716 .
.It Fl N Ar new_passphrase
Provides the new passphrase.
.It Fl n Ar principals
@ -300,13 +327,13 @@ Multiple principals may be specified, separated by commas.
Please see the
.Sx CERTIFICATES
section for details.
.It Fl O Ar constraint
Specify a certificate constraint when signing a key.
.It Fl O Ar option
Specify a certificate option when signing a key.
This option may be specified multiple times.
Please see the
.Sx CERTIFICATES
section for details.
The constraints that are valid for user certificates are:
The options that are valid for user certificates are:
.Bl -tag -width Ds
.It Ic clear
Clear all enabled permissions.
@ -356,7 +383,7 @@ is a comma-separated list of one or more address/netmask pairs in CIDR
format.
.El
.Pp
At present, no constraints are valid for host keys.
At present, no options are valid for host keys.
.It Fl P Ar passphrase
Provides the (old) passphrase.
.It Fl p
@ -442,6 +469,10 @@ Specify desired generator when testing candidate moduli for DH-GEX.
.It Fl y
This option will read a private
OpenSSH format file and print an OpenSSH public key to stdout.
.It Fl z Ar serial_number
Specifies a serial number to be embedded in the certificate to distinguish
this certificate from others from the same CA.
The default serial number is zero.
.El
.Sh MODULI GENERATION
.Nm
@ -502,7 +533,7 @@ that both ends of a connection share common moduli.
supports signing of keys to produce certificates that may be used for
user or host authentication.
Certificates consist of a public key, some identity information, zero or
more principal (user or host) names and an optional set of constraints that
more principal (user or host) names and a set of options that
are signed by a Certification Authority (CA) key.
Clients or servers may then trust only the CA key and verify its signature
on a certificate rather than trusting many user/host keys.
@ -528,7 +559,17 @@ option:
.Pp
The host certificate will be output to
.Pa /path/to/host_key-cert.pub .
In both cases,
.Pp
It is possible to sign using a CA key stored in a PKCS#11 token by
providing the token library using
.Fl D
and identifying the CA key by providing its public half as an argument
to
.Fl s :
.Pp
.Dl $ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id host_key.pub
.Pp
In all cases,
.Ar key_id
is a "key identifier" that is logged by the server when the certificate
is used for authentication.
@ -542,11 +583,11 @@ To generate a certificate for a specified set of principals:
.Dl "$ ssh-keygen -s ca_key -I key_id -h -n host.domain user_key.pub"
.Pp
Additional limitations on the validity and use of user certificates may
be specified through certificate constraints.
A constrained certificate may disable features of the SSH session, may be
be specified through certificate options.
A certificate option may disable features of the SSH session, may be
valid only when presented from particular source addresses or may
force the use of a specific command.
For a list of valid certificate constraints, see the documentation for the
For a list of valid certificate options, see the documentation for the
.Fl O
option above.
.Pp

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-keyscan.c,v 1.81 2010/01/09 23:04:13 dtucker Exp $ */
/* $OpenBSD: ssh-keyscan.c,v 1.82 2010/06/22 04:54:30 djm Exp $ */
/*
* Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
*
@ -104,122 +104,6 @@ typedef struct Connection {
TAILQ_HEAD(conlist, Connection) tq; /* Timeout Queue */
con *fdcon;
/*
* This is just a wrapper around fgets() to make it usable.
*/
/* Stress-test. Increase this later. */
#define LINEBUF_SIZE 16
typedef struct {
char *buf;
u_int size;
int lineno;
const char *filename;
FILE *stream;
void (*errfun) (const char *,...);
} Linebuf;
static Linebuf *
Linebuf_alloc(const char *filename, void (*errfun) (const char *,...))
{
Linebuf *lb;
if (!(lb = malloc(sizeof(*lb)))) {
if (errfun)
(*errfun) ("linebuf (%s): malloc failed\n",
filename ? filename : "(stdin)");
return (NULL);
}
if (filename) {
lb->filename = filename;
if (!(lb->stream = fopen(filename, "r"))) {
xfree(lb);
if (errfun)
(*errfun) ("%s: %s\n", filename, strerror(errno));
return (NULL);
}
} else {
lb->filename = "(stdin)";
lb->stream = stdin;
}
if (!(lb->buf = malloc((lb->size = LINEBUF_SIZE)))) {
if (errfun)
(*errfun) ("linebuf (%s): malloc failed\n", lb->filename);
xfree(lb);
return (NULL);
}
lb->errfun = errfun;
lb->lineno = 0;
return (lb);
}
static void
Linebuf_free(Linebuf * lb)
{
fclose(lb->stream);
xfree(lb->buf);
xfree(lb);
}
#if 0
static void
Linebuf_restart(Linebuf * lb)
{
clearerr(lb->stream);
rewind(lb->stream);
lb->lineno = 0;
}
static int
Linebuf_lineno(Linebuf * lb)
{
return (lb->lineno);
}
#endif
static char *
Linebuf_getline(Linebuf * lb)
{
size_t n = 0;
void *p;
lb->lineno++;
for (;;) {
/* Read a line */
if (!fgets(&lb->buf[n], lb->size - n, lb->stream)) {
if (ferror(lb->stream) && lb->errfun)
(*lb->errfun)("%s: %s\n", lb->filename,
strerror(errno));
return (NULL);
}
n = strlen(lb->buf);
/* Return it or an error if it fits */
if (n > 0 && lb->buf[n - 1] == '\n') {
lb->buf[n - 1] = '\0';
return (lb->buf);
}
if (n != lb->size - 1) {
if (lb->errfun)
(*lb->errfun)("%s: skipping incomplete last line\n",
lb->filename);
return (NULL);
}
/* Double the buffer if we need more space */
lb->size *= 2;
if ((p = realloc(lb->buf, lb->size)) == NULL) {
lb->size /= 2;
if (lb->errfun)
(*lb->errfun)("linebuf (%s): realloc failed\n",
lb->filename);
return (NULL);
}
lb->buf = p;
}
}
static int
fdlim_get(int hard)
{
@ -724,8 +608,10 @@ int
main(int argc, char **argv)
{
int debug_flag = 0, log_level = SYSLOG_LEVEL_INFO;
int opt, fopt_count = 0;
char *tname;
int opt, fopt_count = 0, j;
char *tname, *cp, line[NI_MAXHOST];
FILE *fp;
u_long linenum;
extern int optind;
extern char *optarg;
@ -826,19 +712,40 @@ main(int argc, char **argv)
read_wait_nfdset = howmany(maxfd, NFDBITS);
read_wait = xcalloc(read_wait_nfdset, sizeof(fd_mask));
if (fopt_count) {
Linebuf *lb;
char *line;
int j;
for (j = 0; j < fopt_count; j++) {
if (argv[j] == NULL)
fp = stdin;
else if ((fp = fopen(argv[j], "r")) == NULL)
fatal("%s: %s: %s", __progname, argv[j],
strerror(errno));
linenum = 0;
for (j = 0; j < fopt_count; j++) {
lb = Linebuf_alloc(argv[j], error);
if (!lb)
while (read_keyfile_line(fp,
argv[j] == NULL ? "(stdin)" : argv[j], line, sizeof(line),
&linenum) != -1) {
/* Chomp off trailing whitespace and comments */
if ((cp = strchr(line, '#')) == NULL)
cp = line + strlen(line) - 1;
while (cp >= line) {
if (*cp == ' ' || *cp == '\t' ||
*cp == '\n' || *cp == '#')
*cp-- = '\0';
else
break;
}
/* Skip empty lines */
if (*line == '\0')
continue;
while ((line = Linebuf_getline(lb)) != NULL)
do_host(line);
Linebuf_free(lb);
do_host(line);
}
if (ferror(fp))
fatal("%s: %s: %s", __progname, argv[j],
strerror(errno));
fclose(fp);
}
while (optind < argc)

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: ssh-keysign.8,v 1.9 2007/05/31 19:20:16 jmc Exp $
.\" $OpenBSD: ssh-keysign.8,v 1.10 2010/08/04 05:42:47 djm Exp $
.\"
.\" Copyright (c) 2002 Markus Friedl. All rights reserved.
.\"
@ -22,7 +22,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd May 31, 2007
.Dd August 4, 2010
.Dt SSH-KEYSIGN 8
.Os
.Sh NAME
@ -68,6 +68,9 @@ accessible to others.
Since they are readable only by root,
.Nm
must be set-uid root if host-based authentication is used.
.It Pa /etc/ssh/ssh_host_dsa_key-cert.pub, /etc/ssh/ssh_host_rsa_key-cert.pub
If these files exist they are assumed to contain public certificate
information corresponding with the private keys above.
.El
.Sh SEE ALSO
.Xr ssh 1 ,

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-keysign.c,v 1.30 2010/01/13 01:20:20 dtucker Exp $ */
/* $OpenBSD: ssh-keysign.c,v 1.32 2010/08/04 06:08:40 djm Exp $ */
/*
* Copyright (c) 2002 Markus Friedl. All rights reserved.
*
@ -232,7 +232,7 @@ main(int argc, char **argv)
found = 0;
for (i = 0; i < 2; i++) {
if (keys[i] != NULL &&
key_equal(key, keys[i])) {
key_equal_public(key, keys[i])) {
found = 1;
break;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-pkcs11.c,v 1.4 2010/02/24 06:12:53 djm Exp $ */
/* $OpenBSD: ssh-pkcs11.c,v 1.6 2010/06/08 21:32:19 markus Exp $ */
/*
* Copyright (c) 2010 Markus Friedl. All rights reserved.
*
@ -187,6 +187,34 @@ pkcs11_rsa_finish(RSA *rsa)
return (rv);
}
/* find a single 'obj' for given attributes */
static int
pkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr,
CK_ULONG nattr, CK_OBJECT_HANDLE *obj)
{
CK_FUNCTION_LIST *f;
CK_SESSION_HANDLE session;
CK_ULONG nfound = 0;
CK_RV rv;
int ret = -1;
f = p->function_list;
session = p->slotinfo[slotidx].session;
if ((rv = f->C_FindObjectsInit(session, attr, nattr)) != CKR_OK) {
error("C_FindObjectsInit failed (nattr %lu): %lu", nattr, rv);
return (-1);
}
if ((rv = f->C_FindObjects(session, obj, 1, &nfound)) != CKR_OK ||
nfound != 1) {
debug("C_FindObjects failed (nfound %lu nattr %lu): %lu",
nfound, nattr, rv);
} else
ret = 0;
if ((rv = f->C_FindObjectsFinal(session)) != CKR_OK)
error("C_FindObjectsFinal failed: %lu", rv);
return (ret);
}
/* openssl callback doing the actual signing operation */
static int
pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
@ -196,7 +224,7 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
struct pkcs11_slotinfo *si;
CK_FUNCTION_LIST *f;
CK_OBJECT_HANDLE obj;
CK_ULONG tlen = 0, nfound = 0;
CK_ULONG tlen = 0;
CK_RV rv;
CK_OBJECT_CLASS private_key_class = CKO_PRIVATE_KEY;
CK_BBOOL true_val = CK_TRUE;
@ -247,13 +275,10 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
}
key_filter[1].pValue = k11->keyid;
key_filter[1].ulValueLen = k11->keyid_len;
if ((rv = f->C_FindObjectsInit(si->session, key_filter, 3)) != CKR_OK) {
error("C_FindObjectsInit failed: %lu", rv);
return (-1);
}
if ((rv = f->C_FindObjects(si->session, &obj, 1, &nfound)) != CKR_OK ||
nfound != 1) {
error("C_FindObjects failed (%lu nfound): %lu", nfound, rv);
/* try to find object w/CKA_SIGN first, retry w/o */
if (pkcs11_find(k11->provider, k11->slotidx, key_filter, 3, &obj) < 0 &&
pkcs11_find(k11->provider, k11->slotidx, key_filter, 2, &obj) < 0) {
error("cannot find private key");
} else if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) {
error("C_SignInit failed: %lu", rv);
} else {
@ -265,8 +290,6 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
else
error("C_Sign failed: %lu", rv);
}
if ((rv = f->C_FindObjectsFinal(si->session)) != CKR_OK)
error("C_FindObjectsFinal failed: %lu", rv);
return (rval);
}
@ -410,7 +433,13 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, Key ***keysp,
error("C_GetAttributeValue failed: %lu", rv);
continue;
}
/* allocate buffers for attributes, XXX check ulValueLen? */
/* check that none of the attributes are zero length */
if (attribs[0].ulValueLen == 0 ||
attribs[1].ulValueLen == 0 ||
attribs[2].ulValueLen == 0) {
continue;
}
/* allocate buffers for attributes */
for (i = 0; i < 3; i++)
attribs[i].pValue = xmalloc(attribs[i].ulValueLen);
/* retrieve ID, modulus and public exponent of RSA key */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-rsa.c,v 1.40 2010/02/26 20:29:54 djm Exp $ */
/* $OpenBSD: ssh-rsa.c,v 1.44 2010/07/16 14:07:35 djm Exp $ */
/*
* Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
*
@ -30,6 +30,7 @@
#include "buffer.h"
#include "key.h"
#include "compat.h"
#include "misc.h"
#include "ssh.h"
static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int, RSA *);
@ -46,9 +47,8 @@ ssh_rsa_sign(const Key *key, u_char **sigp, u_int *lenp,
int ok, nid;
Buffer b;
if (key == NULL ||
(key->type != KEY_RSA && key->type != KEY_RSA_CERT) ||
key->rsa == NULL) {
if (key == NULL || key->rsa == NULL || (key->type != KEY_RSA &&
key->type != KEY_RSA_CERT && key->type != KEY_RSA_CERT_V00)) {
error("ssh_rsa_sign: no RSA key");
return -1;
}
@ -115,9 +115,8 @@ ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
u_int len, dlen, modlen;
int rlen, ret, nid;
if (key == NULL ||
(key->type != KEY_RSA && key->type != KEY_RSA_CERT) ||
key->rsa == NULL) {
if (key == NULL || key->rsa == NULL || (key->type != KEY_RSA &&
key->type != KEY_RSA_CERT && key->type != KEY_RSA_CERT_V00)) {
error("ssh_rsa_verify: no RSA key");
return -1;
}
@ -212,7 +211,7 @@ openssh_RSA_verify(int type, u_char *hash, u_int hashlen,
u_char *sigbuf, u_int siglen, RSA *rsa)
{
u_int ret, rsasize, oidlen = 0, hlen = 0;
int len;
int len, oidmatch, hashmatch;
const u_char *oid = NULL;
u_char *decrypted = NULL;
@ -251,11 +250,13 @@ openssh_RSA_verify(int type, u_char *hash, u_int hashlen,
error("bad decrypted len: %d != %d + %d", len, hlen, oidlen);
goto done;
}
if (memcmp(decrypted, oid, oidlen) != 0) {
oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0;
hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0;
if (!oidmatch) {
error("oid mismatch");
goto done;
}
if (memcmp(decrypted + oidlen, hash, hlen) != 0) {
if (!hashmatch) {
error("hash mismatch");
goto done;
}

View File

@ -34,9 +34,9 @@
.\" (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: ssh.1,v 1.303 2010/03/26 00:26:58 djm Exp $
.\" $OpenBSD: ssh.1,v 1.308 2010/08/04 05:37:01 djm Exp $
.\" $FreeBSD$
.Dd March 26, 2010
.Dd August 4 2010
.Dt SSH 1
.Os
.Sh NAME
@ -44,46 +44,28 @@
.Nd OpenSSH SSH client (remote login program)
.Sh SYNOPSIS
.Nm ssh
.Bk -words
.Op Fl 1246AaCfgKkMNnqsTtVvXxYy
.Op Fl b Ar bind_address
.Op Fl c Ar cipher_spec
.Oo Fl D\ \&
.Sm off
.Oo Ar bind_address : Oc
.Ar port
.Sm on
.Oc
.Op Fl D Oo Ar bind_address : Oc Ns Ar port
.Op Fl e Ar escape_char
.Op Fl F Ar configfile
.Op Fl I Ar pkcs11
.Bk -words
.Op Fl i Ar identity_file
.Ek
.Oo Fl L\ \&
.Sm off
.Oo Ar bind_address : Oc
.Ar port : host : hostport
.Sm on
.Oc
.Bk -words
.Op Fl L Oo Ar bind_address : Oc Ns Ar port : Ns Ar host : Ns Ar hostport
.Op Fl l Ar login_name
.Ek
.Op Fl m Ar mac_spec
.Op Fl O Ar ctl_cmd
.Op Fl o Ar option
.Op Fl p Ar port
.Oo Fl R\ \&
.Sm off
.Oo Ar bind_address : Oc
.Ar port : host : hostport
.Sm on
.Oc
.Op Fl R Oo Ar bind_address : Oc Ns Ar port : Ns Ar host : Ns Ar hostport
.Op Fl S Ar ctl_path
.Op Fl W Ar host : Ns Ar port
.Oo Fl w Ar local_tun Ns
.Op : Ns Ar remote_tun Oc
.Op Fl w Ar local_tun Ns Op : Ns Ar remote_tun
.Oo Ar user Ns @ Oc Ns Ar hostname
.Op Ar command
.Ek
.Sh DESCRIPTION
.Nm
(SSH client) is a program for logging into a remote machine and for
@ -195,7 +177,9 @@ is a comma-separated list of ciphers
listed in order of preference.
See the
.Cm Ciphers
keyword for more information.
keyword in
.Xr ssh_config 5
for more information.
.It Fl D Xo
.Sm off
.Oo Ar bind_address : Oc
@ -219,14 +203,7 @@ will act as a SOCKS server.
Only root can forward privileged ports.
Dynamic port forwardings can also be specified in the configuration file.
.Pp
IPv6 addresses can be specified with an alternative syntax:
.Sm off
.Xo
.Op Ar bind_address No /
.Ar port
.Xc
.Sm on
or by enclosing the address in square brackets.
IPv6 addresses can be specified by enclosing the address in square brackets.
Only the superuser can forward privileged ports.
By default, the local port is bound in accordance with the
.Cm GatewayPorts
@ -337,15 +314,7 @@ port
.Ar hostport
from the remote machine.
Port forwardings can also be specified in the configuration file.
IPv6 addresses can be specified with an alternative syntax:
.Sm off
.Xo
.Op Ar bind_address No /
.Ar port No / Ar host No /
.Ar hostport
.Xc
.Sm on
or by enclosing the address in square brackets.
IPv6 addresses can be specified by enclosing the address in square brackets.
Only the superuser can forward privileged ports.
By default, the local port is bound in accordance with the
.Cm GatewayPorts
@ -422,7 +391,9 @@ option is specified, the
argument is interpreted and passed to the master process.
Valid commands are:
.Dq check
(check that the master process is running) and
(check that the master process is running),
.Dq forward
(request forwardings without command execution) and
.Dq exit
(request the master to exit).
.It Fl o Ar option
@ -527,15 +498,7 @@ from the local machine.
Port forwardings can also be specified in the configuration file.
Privileged ports can be forwarded only when
logging in as root on the remote machine.
IPv6 addresses can be specified by enclosing the address in square braces or
using an alternative syntax:
.Sm off
.Xo
.Op Ar bind_address No /
.Ar host No / Ar port No /
.Ar hostport
.Xc .
.Sm on
IPv6 addresses can be specified by enclosing the address in square braces.
.Pp
By default, the listening socket on the server will be bound to the loopback
interface only.
@ -559,8 +522,11 @@ argument is
.Ql 0 ,
the listen port will be dynamically allocated on the server and reported
to the client at run time.
When used together with
.Ic -O forward
the allocated port will be printed to the standard output.
.It Fl S Ar ctl_path
Specifies the location of a control socket for connection sharing
Specifies the location of a control socket for connection sharing,
or the string
.Dq none
to disable connection sharing.

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh.c,v 1.335 2010/02/26 20:29:54 djm Exp $ */
/* $OpenBSD: ssh.c,v 1.346 2010/08/12 21:49:44 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -80,6 +80,7 @@ __RCSID("$FreeBSD$");
#include "ssh.h"
#include "ssh1.h"
#include "ssh2.h"
#include "canohost.h"
#include "compat.h"
#include "cipher.h"
#include "packet.h"
@ -127,6 +128,15 @@ int no_shell_flag = 0;
*/
int stdin_null_flag = 0;
/*
* Flag indicating that the current process should be backgrounded and
* a new slave launched in the foreground for ControlPersist.
*/
int need_controlpersist_detach = 0;
/* Copies of flags for ControlPersist foreground slave */
int ostdin_null_flag, ono_shell_flag, ono_tty_flag, otty_flag;
/*
* Flag indicating that ssh should fork after authentication. This is useful
* so that the passphrase can be entered manually, and then ssh goes to the
@ -228,6 +238,12 @@ main(int ac, char **av)
__progname = ssh_get_progname(av[0]);
init_rng();
/*
* Discard other fds that are hanging around. These can cause problem
* with backgrounded ssh processes started by ControlPersist.
*/
closefrom(STDERR_FILENO + 1);
/*
* Save the original real uid. It will be needed later (uid-swapping
* may clobber the real uid).
@ -328,6 +344,8 @@ main(int ac, char **av)
fatal("Multiplexing command already specified");
if (strcmp(optarg, "check") == 0)
muxclient_command = SSHMUX_COMMAND_ALIVE_CHECK;
else if (strcmp(optarg, "forward") == 0)
muxclient_command = SSHMUX_COMMAND_FORWARD;
else if (strcmp(optarg, "exit") == 0)
muxclient_command = SSHMUX_COMMAND_TERMINATE;
else
@ -621,7 +639,7 @@ main(int ac, char **av)
tty_flag = 1;
/* Force no tty */
if (no_tty_flag)
if (no_tty_flag || muxclient_command != 0)
tty_flag = 0;
/* Do not allocate a tty if stdin is not a tty. */
if ((!isatty(fileno(stdin)) || stdin_null_flag) && !force_tty_flag) {
@ -677,6 +695,11 @@ main(int ac, char **av)
options.port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
}
if (options.hostname != NULL) {
host = percent_expand(options.hostname,
"h", host, (char *)NULL);
}
if (options.local_command != NULL) {
char thishost[NI_MAXHOST];
@ -686,16 +709,12 @@ main(int ac, char **av)
debug3("expanding LocalCommand: %s", options.local_command);
cp = options.local_command;
options.local_command = percent_expand(cp, "d", pw->pw_dir,
"h", options.hostname? options.hostname : host,
"l", thishost, "n", host, "r", options.user, "p", buf,
"u", pw->pw_name, (char *)NULL);
"h", host, "l", thishost, "n", host, "r", options.user,
"p", buf, "u", pw->pw_name, (char *)NULL);
debug3("expanded LocalCommand: %s", options.local_command);
xfree(cp);
}
if (options.hostname != NULL)
host = options.hostname;
/* Find canonic host name. */
if (strchr(host, '.') == 0) {
struct addrinfo hints;
@ -779,26 +798,34 @@ main(int ac, char **av)
sensitive_data.external_keysign = 0;
if (options.rhosts_rsa_authentication ||
options.hostbased_authentication) {
sensitive_data.nkeys = 3;
sensitive_data.nkeys = 5;
sensitive_data.keys = xcalloc(sensitive_data.nkeys,
sizeof(Key));
PRIV_START;
sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
_PATH_HOST_KEY_FILE, "", NULL, NULL);
sensitive_data.keys[1] = key_load_private_type(KEY_DSA,
sensitive_data.keys[1] = key_load_private_cert(KEY_DSA,
_PATH_HOST_DSA_KEY_FILE, "", NULL);
sensitive_data.keys[2] = key_load_private_cert(KEY_RSA,
_PATH_HOST_RSA_KEY_FILE, "", NULL);
sensitive_data.keys[3] = key_load_private_type(KEY_DSA,
_PATH_HOST_DSA_KEY_FILE, "", NULL, NULL);
sensitive_data.keys[2] = key_load_private_type(KEY_RSA,
sensitive_data.keys[4] = key_load_private_type(KEY_RSA,
_PATH_HOST_RSA_KEY_FILE, "", NULL, NULL);
PRIV_END;
if (options.hostbased_authentication == 1 &&
sensitive_data.keys[0] == NULL &&
sensitive_data.keys[1] == NULL &&
sensitive_data.keys[2] == NULL) {
sensitive_data.keys[1] = key_load_public(
sensitive_data.keys[3] == NULL &&
sensitive_data.keys[4] == NULL) {
sensitive_data.keys[1] = key_load_cert(
_PATH_HOST_DSA_KEY_FILE);
sensitive_data.keys[2] = key_load_cert(
_PATH_HOST_RSA_KEY_FILE);
sensitive_data.keys[3] = key_load_public(
_PATH_HOST_DSA_KEY_FILE, NULL);
sensitive_data.keys[2] = key_load_public(
sensitive_data.keys[4] = key_load_public(
_PATH_HOST_RSA_KEY_FILE, NULL);
sensitive_data.external_keysign = 1;
}
@ -845,6 +872,13 @@ main(int ac, char **av)
ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr,
pw, timeout_ms);
if (packet_connection_is_on_socket()) {
verbose("Authenticated to %s ([%s]:%d).", host,
get_remote_ipaddr(), get_remote_port());
} else {
verbose("Authenticated to %s (via proxy).", host);
}
/* We no longer need the private host keys. Clear them now. */
if (sensitive_data.nkeys != 0) {
for (i = 0; i < sensitive_data.nkeys; i++) {
@ -884,6 +918,61 @@ main(int ac, char **av)
return exit_status;
}
static void
control_persist_detach(void)
{
pid_t pid;
int devnull;
debug("%s: backgrounding master process", __func__);
/*
* master (current process) into the background, and make the
* foreground process a client of the backgrounded master.
*/
switch ((pid = fork())) {
case -1:
fatal("%s: fork: %s", __func__, strerror(errno));
case 0:
/* Child: master process continues mainloop */
break;
default:
/* Parent: set up mux slave to connect to backgrounded master */
debug2("%s: background process is %ld", __func__, (long)pid);
stdin_null_flag = ostdin_null_flag;
no_shell_flag = ono_shell_flag;
no_tty_flag = ono_tty_flag;
tty_flag = otty_flag;
close(muxserver_sock);
muxserver_sock = -1;
muxclient(options.control_path);
/* muxclient() doesn't return on success. */
fatal("Failed to connect to new control master");
}
if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
error("%s: open(\"/dev/null\"): %s", __func__,
strerror(errno));
} else {
if (dup2(devnull, STDIN_FILENO) == -1 ||
dup2(devnull, STDOUT_FILENO) == -1)
error("%s: dup2: %s", __func__, strerror(errno));
if (devnull > STDERR_FILENO)
close(devnull);
}
}
/* Do fork() after authentication. Used by "ssh -f" */
static void
fork_postauth(void)
{
if (need_controlpersist_detach)
control_persist_detach();
debug("forking to background");
fork_after_authentication_flag = 0;
if (daemon(1, 1) < 0)
fatal("daemon() failed: %.200s", strerror(errno));
}
/* Callback for remote forward global requests */
static void
ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
@ -895,9 +984,10 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
rfwd->listen_port, rfwd->connect_host, rfwd->connect_port);
if (type == SSH2_MSG_REQUEST_SUCCESS && rfwd->listen_port == 0) {
rfwd->allocated_port = packet_get_int();
logit("Allocated port %u for remote forward to %s:%d",
packet_get_int(),
rfwd->connect_host, rfwd->connect_port);
rfwd->allocated_port,
rfwd->connect_host, rfwd->connect_port);
}
if (type == SSH2_MSG_REQUEST_FAILURE) {
@ -910,12 +1000,8 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
}
if (++remote_forward_confirms_received == options.num_remote_forwards) {
debug("All remote forwarding requests processed");
if (fork_after_authentication_flag) {
fork_after_authentication_flag = 0;
if (daemon(1, 1) < 0)
fatal("daemon() failed: %.200s",
strerror(errno));
}
if (fork_after_authentication_flag)
fork_postauth();
}
}
@ -1111,7 +1197,9 @@ ssh_session(void)
char *proto, *data;
/* Get reasonable local authentication information. */
client_x11_get_proto(display, options.xauth_location,
options.forward_x11_trusted, &proto, &data);
options.forward_x11_trusted,
options.forward_x11_timeout,
&proto, &data);
/* Request forwarding with authentication spoofing. */
debug("Requesting X11 forwarding with authentication "
"spoofing.");
@ -1157,12 +1245,13 @@ ssh_session(void)
* If requested and we are not interested in replies to remote
* forwarding requests, then let ssh continue in the background.
*/
if (fork_after_authentication_flag &&
(!options.exit_on_forward_failure ||
options.num_remote_forwards == 0)) {
fork_after_authentication_flag = 0;
if (daemon(1, 1) < 0)
fatal("daemon() failed: %.200s", strerror(errno));
if (fork_after_authentication_flag) {
if (options.exit_on_forward_failure &&
options.num_remote_forwards > 0) {
debug("deferring postauth fork until remote forward "
"confirmation received");
} else
fork_postauth();
}
/*
@ -1193,18 +1282,22 @@ ssh_session(void)
/* request pty/x11/agent/tcpfwd/shell for channel */
static void
ssh_session2_setup(int id, void *arg)
ssh_session2_setup(int id, int success, void *arg)
{
extern char **environ;
const char *display;
int interactive = tty_flag;
if (!success)
return; /* No need for error message, channels code sens one */
display = getenv("DISPLAY");
if (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);
options.forward_x11_trusted,
options.forward_x11_timeout, &proto, &data);
/* Request forwarding with authentication spoofing. */
debug("Requesting X11 forwarding with authentication "
"spoofing.");
@ -1281,6 +1374,31 @@ ssh_session2(void)
/* XXX should be pre-session */
ssh_init_forwarding();
/* Start listening for multiplex clients */
muxserver_listen();
/*
* If we are in control persist mode, then prepare to background
* ourselves and have a foreground client attach as a control
* slave. NB. we must save copies of the flags that we override for
* the backgrounding, since we defer attachment of the slave until
* after the connection is fully established (in particular,
* async rfwd replies have been received for ExitOnForwardFailure).
*/
if (options.control_persist && muxserver_sock != -1) {
ostdin_null_flag = stdin_null_flag;
ono_shell_flag = no_shell_flag;
ono_tty_flag = no_tty_flag;
otty_flag = tty_flag;
stdin_null_flag = 1;
no_shell_flag = 1;
no_tty_flag = 1;
tty_flag = 0;
if (!fork_after_authentication_flag)
need_controlpersist_detach = 1;
fork_after_authentication_flag = 1;
}
if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN))
id = ssh_session2_open();
@ -1299,14 +1417,17 @@ ssh_session2(void)
options.permit_local_command)
ssh_local_cmd(options.local_command);
/* Start listening for multiplex clients */
muxserver_listen();
/* If requested, let ssh continue in the background. */
/*
* If requested and we are not interested in replies to remote
* forwarding requests, then let ssh continue in the background.
*/
if (fork_after_authentication_flag) {
fork_after_authentication_flag = 0;
if (daemon(1, 1) < 0)
fatal("daemon() failed: %.200s", strerror(errno));
if (options.exit_on_forward_failure &&
options.num_remote_forwards > 0) {
debug("deferring postauth fork until remote forward "
"confirmation received");
} else
fork_postauth();
}
if (options.use_roaming)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh.h,v 1.78 2006/08/03 03:34:42 deraadt Exp $ */
/* $OpenBSD: ssh.h,v 1.79 2010/06/25 07:14:46 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -18,9 +18,6 @@
/* Default port number. */
#define SSH_DEFAULT_PORT 22
/* Maximum number of TCP/IP ports forwarded per direction. */
#define SSH_MAX_FORWARDS_PER_DIRECTION 100
/*
* Maximum number of RSA authentication identity files that can be specified
* in configuration files or on the command line.

View File

@ -46,4 +46,4 @@
# PermitLocalCommand no
# VisualHostKey no
# ProxyCommand ssh -q -W %h:%p gateway.example.com
# VersionAddendum FreeBSD-20100428
# VersionAddendum FreeBSD-20101111

View File

@ -34,9 +34,9 @@
.\" (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: ssh_config.5,v 1.130 2010/03/26 01:06:13 dtucker Exp $
.\" $OpenBSD: ssh_config.5,v 1.138 2010/08/04 05:37:01 djm Exp $
.\" $FreeBSD$
.Dd March 26, 2010
.Dd August 4, 2010
.Dt SSH_CONFIG 5
.Os
.Sh NAME
@ -320,6 +320,28 @@ It is recommended that any
used for opportunistic connection sharing include
at least %h, %p, and %r.
This ensures that shared connections are uniquely identified.
.It Cm ControlPersist
When used in conjunction with
.Cm ControlMaster ,
specifies that the master connection should remain open
in the background (waiting for future client connections)
after the initial client connection has been closed.
If set to
.Dq no ,
then the master connection will not be placed into the background,
and will close as soon as the initial client connection is closed.
If set to
.Dq yes ,
then the master connection will remain in the background indefinitely
(until killed or closed via a mechanism such as the
.Xr ssh 1
.Dq Fl O No exit
option).
If set to a time in seconds, or a time in any of the formats documented in
.Xr sshd_config 5 ,
then the backgrounded master connection will automatically terminate
after it has remained idle (with no client connections) for the
specified time.
.It Cm DynamicForward
Specifies that a TCP port on the local machine be forwarded
over the secure channel, and the application
@ -330,9 +352,7 @@ The argument must be
.Sm off
.Oo Ar bind_address : Oc Ar port .
.Sm on
IPv6 addresses can be specified by enclosing addresses in square brackets or
by using an alternative syntax:
.Oo Ar bind_address Ns / Oc Ns Ar port .
IPv6 addresses can be specified by enclosing addresses in square brackets.
By default, the local port is bound in accordance with the
.Cm GatewayPorts
setting.
@ -433,6 +453,17 @@ An attacker may then be able to perform activities such as keystroke monitoring
if the
.Cm ForwardX11Trusted
option is also enabled.
.It Cm ForwardX11Timeout
Specify a timeout for untrusted X11 forwarding
using the format described in the
.Sx TIME FORMATS
section of
.Xr sshd_config 5 .
X11 connections received by
.Xr ssh 1
after this time will be refused.
The default is to disable untrusted X11 forwarding after twenty minutes has
elapsed.
.It Cm ForwardX11Trusted
If this option is set to
.Dq yes ,
@ -527,6 +558,10 @@ or for multiple servers running on a single host.
.It Cm HostName
Specifies the real host name to log into.
This can be used to specify nicknames or abbreviations for hosts.
If the hostname contains the character sequence
.Ql %h ,
then this will be replaced with the host name specified on the commandline
(this is useful for manipulating unqualified names).
The default is the name given on the command line.
Numeric IP addresses are also permitted (both on the command line and in
.Cm HostName
@ -642,11 +677,7 @@ The first argument must be
.Sm on
and the second argument must be
.Ar host : Ns Ar hostport .
IPv6 addresses can be specified by enclosing addresses in square brackets or
by using an alternative syntax:
.Oo Ar bind_address Ns / Oc Ns Ar port
and
.Ar host Ns / Ns Ar hostport .
IPv6 addresses can be specified by enclosing addresses in square brackets.
Multiple forwardings may be specified, and additional forwardings can be
given on the command line.
Only the superuser can forward privileged ports.
@ -733,10 +764,12 @@ authentication methods.
This allows a client to prefer one method (e.g.\&
.Cm keyboard-interactive )
over another method (e.g.\&
.Cm password )
The default for this option is:
.Do gssapi-with-mic,hostbased,publickey,keyboard-interactive,password
.Dc .
.Cm password ) .
The default is:
.Bd -literal -offset indent
gssapi-with-mic,hostbased,publickey,
keyboard-interactive,password
.Ed
.It Cm Protocol
Specifies the protocol versions
.Xr ssh 1
@ -758,12 +791,14 @@ Specifies the command to use to connect to the server.
The command
string extends to the end of the line, and is executed with
the user's shell.
In the command string,
In the command string, any occurrence of
.Ql %h
will be substituted by the host name to
connect and
connect,
.Ql %p
by the port.
by the port, and
.Ql %r
by the remote user name.
The command can be basically anything,
and should read from its standard input and write to its standard output.
It should eventually connect an
@ -822,11 +857,7 @@ The first argument must be
.Sm on
and the second argument must be
.Ar host : Ns Ar hostport .
IPv6 addresses can be specified by enclosing addresses in square brackets
or by using an alternative syntax:
.Oo Ar bind_address Ns / Oc Ns Ar port
and
.Ar host Ns / Ns Ar hostport .
IPv6 addresses can be specified by enclosing addresses in square brackets.
Multiple forwardings may be specified, and additional
forwardings can be given on the command line.
Privileged ports can be forwarded only when
@ -1083,7 +1114,7 @@ in
Specifies a string to append to the regular version string to identify
OS- or site-specific modifications.
The default is
.Dq FreeBSD-20100428 .
.Dq FreeBSD-20101111 .
.It Cm VisualHostKey
If this flag is set to
.Dq yes ,

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshconnect.c,v 1.220 2010/03/04 10:36:03 djm Exp $ */
/* $OpenBSD: sshconnect.c,v 1.224 2010/04/16 21:14:27 djm Exp $ */
/* $FreeBSD$ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -102,8 +102,8 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
* (e.g. Solaris)
*/
xasprintf(&tmp, "exec %s", proxy_command);
command_string = percent_expand(tmp, "h", host,
"p", strport, (char *)NULL);
command_string = percent_expand(tmp, "h", host, "p", strport,
"r", options.user, (char *)NULL);
xfree(tmp);
/* Create pipes for communicating with the proxy. */
@ -587,9 +587,9 @@ check_host_cert(const char *host, const Key *host_key)
error("%s", reason);
return 0;
}
if (buffer_len(&host_key->cert->constraints) != 0) {
error("Certificate for %s contains unsupported constraint(s)",
host);
if (buffer_len(&host_key->cert->critical) != 0) {
error("Certificate for %s contains unsupported "
"critical options(s)", host);
return 0;
}
return 1;
@ -740,7 +740,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
debug("Host '%.200s' is known and matches the %s host %s.",
host, type, want_cert ? "certificate" : "key");
debug("Found %s in %s:%d",
want_cert ? "certificate" : "key", host_file, host_line);
want_cert ? "CA key" : "key", host_file, host_line);
if (want_cert && !check_host_cert(hostname, host_key))
goto fail;
if (options.check_host_ip && ip_status == HOST_NEW) {

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshconnect2.c,v 1.180 2010/02/26 20:29:54 djm Exp $ */
/* $OpenBSD: sshconnect2.c,v 1.183 2010/04/26 22:28:24 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Damien Miller. All rights reserved.
@ -195,7 +195,7 @@ struct Authctxt {
const char *host;
const char *service;
Authmethod *method;
int success;
sig_atomic_t success;
char *authlist;
/* pubkey */
Idlist keys;
@ -1140,8 +1140,11 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
u_int skip = 0;
int ret = -1;
int have_sig = 1;
char *fp;
debug3("sign_and_send_pubkey");
fp = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp);
xfree(fp);
if (key_to_blob(id->key, &blob, &bloblen) == 0) {
/* we cannot handle this key */
@ -1398,7 +1401,8 @@ userauth_pubkey(Authctxt *authctxt)
* private key instead
*/
if (id->key && id->key->type != KEY_RSA1) {
debug("Offering public key: %s", id->filename);
debug("Offering %s public key: %s", key_type(id->key),
id->filename);
sent = send_pubkey_test(authctxt, id);
} else if (id->key == NULL) {
debug("Trying private key: %s", id->filename);

View File

@ -34,9 +34,9 @@
.\" (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: sshd.8,v 1.255 2010/03/05 06:50:35 jmc Exp $
.\" $OpenBSD: sshd.8,v 1.257 2010/08/04 05:37:01 djm Exp $
.\" $FreeBSD$
.Dd March 5, 2010
.Dd August 4, 2010
.Dt SSHD 8
.Os
.Sh NAME
@ -598,13 +598,23 @@ Limit local
.Li ``ssh -L''
port forwarding such that it may only connect to the specified host and
port.
IPv6 addresses can be specified with an alternative syntax:
.Ar host Ns / Ns Ar port .
IPv6 addresses can be specified by enclosing the address in square brackets.
Multiple
.Cm permitopen
options may be applied separated by commas.
No pattern matching is performed on the specified hostnames,
they must be literal domains or addresses.
.It Cm principals="principals"
On a
.Cm cert-authority
line, specifies allowed principals for certificate authentication as a
comma-separated list.
At least one name from the list must appear in the certificate's
list of principals for the certificate to be accepted.
This option is ignored for keys that are not marked as trusted certificate
signers using the
.Cm cert-authority
option.
.It Cm tunnel="n"
Force a
.Xr tun 4

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshd.c,v 1.374 2010/03/07 11:57:13 dtucker Exp $ */
/* $OpenBSD: sshd.c,v 1.375 2010/04/16 01:47:26 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -755,6 +755,8 @@ list_hostkey_types(void)
if (key == NULL)
continue;
switch (key->type) {
case KEY_RSA_CERT_V00:
case KEY_DSA_CERT_V00:
case KEY_RSA_CERT:
case KEY_DSA_CERT:
if (buffer_len(&b) > 0)
@ -778,10 +780,17 @@ get_hostkey_by_type(int type, int need_private)
Key *key;
for (i = 0; i < options.num_host_key_files; i++) {
if (type == KEY_RSA_CERT || type == KEY_DSA_CERT)
switch (type) {
case KEY_RSA_CERT_V00:
case KEY_DSA_CERT_V00:
case KEY_RSA_CERT:
case KEY_DSA_CERT:
key = sensitive_data.host_certificates[i];
else
break;
default:
key = sensitive_data.host_keys[i];
break;
}
if (key != NULL && key->type == type)
return need_private ?
sensitive_data.host_keys[i] : key;

View File

@ -14,7 +14,7 @@
# Note that some of FreeBSD's defaults differ from OpenBSD's, and
# FreeBSD has a few additional options.
#VersionAddendum FreeBSD-20100428
#VersionAddendum FreeBSD-20101111
#Port 22
#AddressFamily any

View File

@ -34,9 +34,9 @@
.\" (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: sshd_config.5,v 1.120 2010/03/04 23:17:25 djm Exp $
.\" $OpenBSD: sshd_config.5,v 1.125 2010/06/30 07:28:34 jmc Exp $
.\" $FreeBSD$
.Dd March 4, 2010
.Dd June 30, 2010
.Dt SSHD_CONFIG 5
.Os
.Sh NAME
@ -156,6 +156,10 @@ for more information on patterns.
.It Cm AuthorizedKeysFile
Specifies the file that contains the public keys that can be used
for user authentication.
The format is described in the
.Sx AUTHORIZED_KEYS FILE FORMAT
section of
.Xr sshd 8 .
.Cm AuthorizedKeysFile
may contain tokens of the form %T which are substituted during connection
setup.
@ -168,6 +172,47 @@ is taken to be an absolute path or one relative to the user's home
directory.
The default is
.Dq .ssh/authorized_keys .
.It Cm AuthorizedPrincipalsFile
Specifies a file that lists principal names that are accepted for
certificate authentication.
When using certificates signed by a key listed in
.Cm TrustedUserCAKeys ,
this file lists names, one of which must appear in the certificate for it
to be accepted for authentication.
Names are listed one per line preceded by key options (as described
in
.Sx AUTHORIZED_KEYS FILE FORMAT
in
.Xr sshd 8 ) .
Empty lines and comments starting with
.Ql #
are ignored.
.Pp
.Cm AuthorizedPrincipalsFile
may contain tokens of the form %T which are substituted during connection
setup.
The following tokens are defined: %% is replaced by a literal '%',
%h is replaced by the home directory of the user being authenticated, and
%u is replaced by the username of that user.
After expansion,
.Cm AuthorizedPrincipalsFile
is taken to be an absolute path or one relative to the user's home
directory.
.Pp
The default is not to use a principals file \(en in this case, the username
of the user must appear in a certificate's principals list for it to be
accepted.
Note that
.Cm AuthorizedPrincipalsFile
is only used when authentication proceeds using a CA listed in
.Cm TrustedUserCAKeys
and is not consulted for certification authorities trusted via
.Pa ~/.ssh/authorized_keys ,
though the
.Cm principals=
key option offers a similar facility (see
.Xr sshd 8
for details).
.It Cm Banner
The contents of the specified file are sent to the remote user before
authentication is allowed.
@ -609,12 +654,15 @@ keyword.
Available keywords are
.Cm AllowAgentForwarding ,
.Cm AllowTcpForwarding ,
.Cm AuthorizedKeysFile ,
.Cm AuthorizedPrincipalsFile ,
.Cm Banner ,
.Cm ChrootDirectory ,
.Cm ForceCommand ,
.Cm GatewayPorts ,
.Cm GSSAPIAuthentication ,
.Cm HostbasedAuthentication ,
.Cm HostbasedUsesNameFromPacketOnly ,
.Cm KbdInteractiveAuthentication ,
.Cm KerberosAuthentication ,
.Cm MaxAuthTries ,
@ -623,6 +671,7 @@ Available keywords are
.Cm PermitEmptyPasswords ,
.Cm PermitOpen ,
.Cm PermitRootLogin ,
.Cm PermitTunnel ,
.Cm PubkeyAuthentication ,
.Cm RhostsRSAAuthentication ,
.Cm RSAAuthentication ,
@ -988,7 +1037,7 @@ The default is
Specifies a string to append to the regular version string to identify
OS- or site-specific modifications.
The default is
.Dq FreeBSD-20100428 .
.Dq FreeBSD-20101111 .
.It Cm X11DisplayOffset
Specifies the first display number available for
.Xr sshd 8 Ns 's

View File

@ -1,12 +1,12 @@
/* $OpenBSD: version.h,v 1.58 2010/03/16 16:36:49 djm Exp $ */
/* $OpenBSD: version.h,v 1.59 2010/08/08 16:26:42 djm Exp $ */
/* $FreeBSD$ */
#ifndef SSH_VERSION
#define SSH_VERSION (ssh_version_get())
#define SSH_RELEASE (ssh_version_get())
#define SSH_VERSION_BASE "OpenSSH_5.5p1"
#define SSH_VERSION_ADDENDUM "FreeBSD-20100428"
#define SSH_VERSION_BASE "OpenSSH_5.6p1"
#define SSH_VERSION_ADDENDUM "FreeBSD-20101111"
const char *ssh_version_get(void);
void ssh_version_set_addendum(const char *);