Upgrade to OpenSSH 5.4p1.
MFC after: 1 month
This commit is contained in:
commit
b15c83408c
@ -1,3 +1,982 @@
|
||||
20100307
|
||||
- (djm) OpenBSD CVS Sync
|
||||
- djm@cvs.openbsd.org 2010/03/07 22:16:01
|
||||
[ssh-keygen.c]
|
||||
make internal strptime string match strftime format;
|
||||
suggested by vinschen AT redhat.com and markus@
|
||||
- djm@cvs.openbsd.org 2010/03/08 00:28:55
|
||||
[ssh-keygen.1]
|
||||
document permit-agent-forwarding certificate constraint; patch from
|
||||
stevesk@
|
||||
- djm@cvs.openbsd.org 2010/03/07 22:01:32
|
||||
[version.h]
|
||||
openssh-5.4
|
||||
- (djm) [README contrib/caldera/openssh.spec contrib/redhat/openssh.spec]
|
||||
crank version numbers
|
||||
- (djm) Release OpenSSH-5.4p1
|
||||
|
||||
20100307
|
||||
- (dtucker) [auth.c] Bug #1710: call setauthdb on AIX before getpwuid so that
|
||||
it gets the passwd struct from the LAM that knows about the user which is
|
||||
not necessarily the default. Patch from Alexandre Letourneau.
|
||||
- (dtucker) [session.c] Bug #1567: move setpcred call to before chroot and
|
||||
do not set real uid, since that's needed for the chroot, and will be set
|
||||
by permanently_set_uid.
|
||||
- (dtucker) [session.c] Also initialize creds to NULL for handing to
|
||||
setpcred.
|
||||
- (dtucker) OpenBSD CVS Sync
|
||||
- dtucker@cvs.openbsd.org 2010/03/07 11:57:13
|
||||
[auth-rhosts.c monitor.c monitor_wrap.c session.c auth-options.c sshd.c]
|
||||
Hold authentication debug messages until after successful authentication.
|
||||
Fixes an info leak of environment variables specified in authorized_keys,
|
||||
reported by Jacob Appelbaum. ok djm@
|
||||
|
||||
20100305
|
||||
- OpenBSD CVS Sync
|
||||
- jmc@cvs.openbsd.org 2010/03/04 12:51:25
|
||||
[ssh.1 sshd_config.5]
|
||||
tweak previous;
|
||||
- djm@cvs.openbsd.org 2010/03/04 20:35:08
|
||||
[ssh-keygen.1 ssh-keygen.c]
|
||||
Add a -L flag to print the contents of a certificate; ok markus@
|
||||
- jmc@cvs.openbsd.org 2010/03/04 22:52:40
|
||||
[ssh-keygen.1]
|
||||
fix Bk/Ek;
|
||||
- djm@cvs.openbsd.org 2010/03/04 23:17:25
|
||||
[sshd_config.5]
|
||||
missing word; spotted by jmc@
|
||||
- djm@cvs.openbsd.org 2010/03/04 23:19:29
|
||||
[ssh.1 sshd.8]
|
||||
move section on CA and revoked keys from ssh.1 to sshd.8's known hosts
|
||||
format section and rework it a bit; requested by jmc@
|
||||
- djm@cvs.openbsd.org 2010/03/04 23:27:25
|
||||
[auth-options.c ssh-keygen.c]
|
||||
"force-command" is not spelled "forced-command"; spotted by
|
||||
imorgan AT nas.nasa.gov
|
||||
- djm@cvs.openbsd.org 2010/03/05 02:58:11
|
||||
[auth.c]
|
||||
make the warning for a revoked key louder and more noticable
|
||||
- jmc@cvs.openbsd.org 2010/03/05 06:50:35
|
||||
[ssh.1 sshd.8]
|
||||
tweak previous;
|
||||
- jmc@cvs.openbsd.org 2010/03/05 08:31:20
|
||||
[ssh.1]
|
||||
document certificate authentication; help/ok djm
|
||||
- djm@cvs.openbsd.org 2010/03/05 10:28:21
|
||||
[ssh-add.1 ssh.1 ssh_config.5]
|
||||
mention loading of certificate files from [private]-cert.pub when
|
||||
they are present; feedback and ok jmc@
|
||||
- (tim) [ssh-pkcs11.c] Fix "non-constant initializer" errors in older
|
||||
compilers. OK djm@
|
||||
- (djm) [ssh-rand-helper.c] declare optind, avoiding compilation failure
|
||||
on some platforms
|
||||
- (djm) [configure.ac] set -fno-strict-aliasing for gcc4; ok dtucker@
|
||||
|
||||
20100304
|
||||
- (djm) [ssh-keygen.c] Use correct local variable, instead of
|
||||
maybe-undefined global "optarg"
|
||||
- (djm) [contrib/redhat/openssh.spec] Replace obsolete BuildPreReq
|
||||
on XFree86-devel with neutral /usr/include/X11/Xlib.h;
|
||||
imorgan AT nas.nasa.gov in bz#1731
|
||||
- (djm) [.cvsignore] Ignore ssh-pkcs11-helper
|
||||
- (djm) [regress/Makefile] Cleanup sshd_proxy_orig
|
||||
- OpenBSD CVS Sync
|
||||
- djm@cvs.openbsd.org 2010/03/03 01:44:36
|
||||
[auth-options.c key.c]
|
||||
reject strings with embedded ASCII nul chars in certificate key IDs,
|
||||
principal names and constraints
|
||||
- djm@cvs.openbsd.org 2010/03/03 22:49:50
|
||||
[sshd.8]
|
||||
the authorized_keys option for CA keys is "cert-authority", not
|
||||
"from=cert-authority". spotted by imorgan AT nas.nasa.gov
|
||||
- djm@cvs.openbsd.org 2010/03/03 22:50:40
|
||||
[PROTOCOL.certkeys]
|
||||
s/similar same/similar/; from imorgan AT nas.nasa.gov
|
||||
- djm@cvs.openbsd.org 2010/03/04 01:44:57
|
||||
[key.c]
|
||||
use buffer_get_string_ptr_ret() where we are checking the return
|
||||
value explicitly instead of the fatal()-causing buffer_get_string_ptr()
|
||||
- djm@cvs.openbsd.org 2010/03/04 10:36:03
|
||||
[auth-rh-rsa.c auth-rsa.c auth.c auth.h auth2-hostbased.c auth2-pubkey.c]
|
||||
[authfile.c authfile.h hostfile.c hostfile.h servconf.c servconf.h]
|
||||
[ssh-keygen.c ssh.1 sshconnect.c sshd_config.5]
|
||||
Add a TrustedUserCAKeys option to sshd_config to specify CA keys that
|
||||
are trusted to authenticate users (in addition than doing it per-user
|
||||
in authorized_keys).
|
||||
|
||||
Add a RevokedKeys option to sshd_config and a @revoked marker to
|
||||
known_hosts to allow keys to me revoked and banned for user or host
|
||||
authentication.
|
||||
|
||||
feedback and ok markus@
|
||||
- djm@cvs.openbsd.org 2010/03/03 00:47:23
|
||||
[regress/cert-hostkey.sh regress/cert-userkey.sh]
|
||||
add an extra test to ensure that authentication with the wrong
|
||||
certificate fails as it should (and it does)
|
||||
- djm@cvs.openbsd.org 2010/03/04 10:38:23
|
||||
[regress/cert-hostkey.sh regress/cert-userkey.sh]
|
||||
additional regression tests for revoked keys and TrustedUserCAKeys
|
||||
|
||||
20100303
|
||||
- (djm) [PROTOCOL.certkeys] Add RCS Ident
|
||||
- OpenBSD CVS Sync
|
||||
- jmc@cvs.openbsd.org 2010/02/26 22:09:28
|
||||
[ssh-keygen.1 ssh.1 sshd.8]
|
||||
tweak previous;
|
||||
- otto@cvs.openbsd.org 2010/03/01 11:07:06
|
||||
[ssh-add.c]
|
||||
zap what seems to be a left-over debug message; ok markus@
|
||||
- djm@cvs.openbsd.org 2010/03/02 23:20:57
|
||||
[ssh-keygen.c]
|
||||
POSIX strptime is stricter than OpenBSD's so do a little dance to
|
||||
appease it.
|
||||
- (djm) [regress/cert-userkey.sh] s/echo -n/echon/ here too
|
||||
|
||||
20100302
|
||||
- (tim) [config.guess config.sub] Bug 1722: Update to latest versions from
|
||||
http://git.savannah.gnu.org/gitweb/ (2009-12-30 and 2010-01-22
|
||||
respectively).
|
||||
|
||||
20100301
|
||||
- (dtucker) [regress/{cert-hostkey,cfgmatch,cipher-speed}.sh} Replace
|
||||
"echo -n" with "echon" for portability.
|
||||
- (dtucker) [openbsd-compat/port-linux.c] Make failure to write to the OOM
|
||||
adjust log at verbose only, since according to cjwatson in bug #1470
|
||||
some virtualization platforms don't allow writes.
|
||||
|
||||
20100228
|
||||
- (djm) [auth.c] On Cygwin, refuse usernames that have differences in
|
||||
case from that matched in the system password database. On this
|
||||
platform, passwords are stored case-insensitively, but sshd requires
|
||||
exact case matching for Match blocks in sshd_config(5). Based on
|
||||
a patch from vinschen AT redhat.com.
|
||||
- (tim) [ssh-pkcs11-helper.c] Move declarations before calling functions
|
||||
to make older compilers (gcc 2.95) happy.
|
||||
|
||||
20100227
|
||||
- (djm) [ssh-pkcs11-helper.c ] Ensure RNG is initialised and seeded
|
||||
- (djm) [openbsd-compat/bsd-cygwin_util.c] Reduce the set of environment
|
||||
variables copied into sshd child processes. From vinschen AT redhat.com
|
||||
|
||||
20100226
|
||||
- OpenBSD CVS Sync
|
||||
- djm@cvs.openbsd.org 2010/02/26 20:29:54
|
||||
[PROTOCOL PROTOCOL.agent PROTOCOL.certkeys addrmatch.c auth-options.c]
|
||||
[auth-options.h auth.h auth2-pubkey.c authfd.c dns.c dns.h hostfile.c]
|
||||
[hostfile.h kex.h kexdhs.c kexgexs.c key.c key.h match.h monitor.c]
|
||||
[myproposal.h servconf.c servconf.h ssh-add.c ssh-agent.c ssh-dss.c]
|
||||
[ssh-keygen.1 ssh-keygen.c ssh-rsa.c ssh.1 ssh.c ssh2.h sshconnect.c]
|
||||
[sshconnect2.c sshd.8 sshd.c sshd_config.5]
|
||||
Add support for certificate key types for users and hosts.
|
||||
|
||||
OpenSSH certificate key types are not X.509 certificates, but a much
|
||||
simpler format that encodes a public key, identity information and
|
||||
some validity constraints and signs it with a CA key. CA keys are
|
||||
regular SSH keys. This certificate style avoids the attack surface
|
||||
of X.509 certificates and is very easy to deploy.
|
||||
|
||||
Certified host keys allow automatic acceptance of new host keys
|
||||
when a CA certificate is marked as trusted in ~/.ssh/known_hosts.
|
||||
see VERIFYING HOST KEYS in ssh(1) for details.
|
||||
|
||||
Certified user keys allow authentication of users when the signing
|
||||
CA key is marked as trusted in authorized_keys. See "AUTHORIZED_KEYS
|
||||
FILE FORMAT" in sshd(8) for details.
|
||||
|
||||
Certificates are minted using ssh-keygen(1), documentation is in
|
||||
the "CERTIFICATES" section of that manpage.
|
||||
|
||||
Documentation on the format of certificates is in the file
|
||||
PROTOCOL.certkeys
|
||||
|
||||
feedback and ok markus@
|
||||
- djm@cvs.openbsd.org 2010/02/26 20:33:21
|
||||
[Makefile regress/cert-hostkey.sh regress/cert-userkey.sh]
|
||||
regression tests for certified keys
|
||||
|
||||
20100224
|
||||
- (djm) [pkcs11.h ssh-pkcs11-client.c ssh-pkcs11-helper.c ssh-pkcs11.c]
|
||||
[ssh-pkcs11.h] Add $OpenBSD$ RCS idents so we can sync portable
|
||||
- (djm) OpenBSD CVS Sync
|
||||
- djm@cvs.openbsd.org 2010/02/11 20:37:47
|
||||
[pathnames.h]
|
||||
correct comment
|
||||
- dtucker@cvs.openbsd.org 2009/11/09 04:20:04
|
||||
[regress/Makefile]
|
||||
add regression test for ssh-keygen pubkey conversions
|
||||
- dtucker@cvs.openbsd.org 2010/01/11 02:53:44
|
||||
[regress/forwarding.sh]
|
||||
regress test for stdio forwarding
|
||||
- djm@cvs.openbsd.org 2010/02/09 04:57:36
|
||||
[regress/addrmatch.sh]
|
||||
clean up droppings
|
||||
- djm@cvs.openbsd.org 2010/02/09 06:29:02
|
||||
[regress/Makefile]
|
||||
turn on all the malloc(3) checking options when running regression
|
||||
tests. this has caught a few bugs for me in the past; ok dtucker@
|
||||
- djm@cvs.openbsd.org 2010/02/24 06:21:56
|
||||
[regress/test-exec.sh]
|
||||
wait for sshd to fully stop in cleanup() function; avoids races in tests
|
||||
that do multiple start_sshd/cleanup cycles; "I hate pidfiles" deraadt@
|
||||
- markus@cvs.openbsd.org 2010/02/08 10:52:47
|
||||
[regress/agent-pkcs11.sh]
|
||||
test for PKCS#11 support (currently disabled)
|
||||
- (djm) [Makefile.in ssh-pkcs11-helper.8] Add manpage for PKCS#11 helper
|
||||
- (djm) [contrib/caldera/openssh.spec contrib/redhat/openssh.spec]
|
||||
[contrib/suse/openssh.spec] Add PKCS#11 helper binary and manpage
|
||||
|
||||
20100212
|
||||
- (djm) OpenBSD CVS Sync
|
||||
- djm@cvs.openbsd.org 2010/02/02 22:49:34
|
||||
[bufaux.c]
|
||||
make buffer_get_string_ret() really non-fatal in all cases (it was
|
||||
using buffer_get_int(), which could fatal() on buffer empty);
|
||||
ok markus dtucker
|
||||
- markus@cvs.openbsd.org 2010/02/08 10:50:20
|
||||
[pathnames.h readconf.c readconf.h scp.1 sftp.1 ssh-add.1 ssh-add.c]
|
||||
[ssh-agent.c ssh-keygen.1 ssh-keygen.c ssh.1 ssh.c ssh_config.5]
|
||||
replace our obsolete smartcard code with PKCS#11.
|
||||
ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/v2-20/pkcs-11v2-20.pdf
|
||||
ssh(1) and ssh-keygen(1) use dlopen(3) directly to talk to a PKCS#11
|
||||
provider (shared library) while ssh-agent(1) delegates PKCS#11 to
|
||||
a forked a ssh-pkcs11-helper process.
|
||||
PKCS#11 is currently a compile time option.
|
||||
feedback and ok djm@; inspired by patches from Alon Bar-Lev
|
||||
- jmc@cvs.openbsd.org 2010/02/08 22:03:05
|
||||
[ssh-add.1 ssh-keygen.1 ssh.1 ssh.c]
|
||||
tweak previous; ok markus
|
||||
- djm@cvs.openbsd.org 2010/02/09 00:50:36
|
||||
[ssh-agent.c]
|
||||
fallout from PKCS#11: unbreak -D
|
||||
- djm@cvs.openbsd.org 2010/02/09 00:50:59
|
||||
[ssh-keygen.c]
|
||||
fix -Wall
|
||||
- djm@cvs.openbsd.org 2010/02/09 03:56:28
|
||||
[buffer.c buffer.h]
|
||||
constify the arguments to buffer_len, buffer_ptr and buffer_dump
|
||||
- djm@cvs.openbsd.org 2010/02/09 06:18:46
|
||||
[auth.c]
|
||||
unbreak ChrootDirectory+internal-sftp by skipping check for executable
|
||||
shell when chrooting; reported by danh AT wzrd.com; ok dtucker@
|
||||
- markus@cvs.openbsd.org 2010/02/10 23:20:38
|
||||
[ssh-add.1 ssh-keygen.1 ssh.1 ssh_config.5]
|
||||
pkcs#11 is no longer optional; improve wording; ok jmc@
|
||||
- jmc@cvs.openbsd.org 2010/02/11 13:23:29
|
||||
[ssh.1]
|
||||
libarary -> library;
|
||||
- (djm) [INSTALL Makefile.in README.smartcard configure.ac scard-opensc.c]
|
||||
[scard.c scard.h pkcs11.h scard/Makefile.in scard/Ssh.bin.uu scard/Ssh.java]
|
||||
Remove obsolete smartcard support
|
||||
- (djm) [ssh-pkcs11-client.c ssh-pkcs11-helper.c ssh-pkcs11.c]
|
||||
Make it compile on OSX
|
||||
- (djm) [ssh-pkcs11-client.c ssh-pkcs11-helper.c ssh-pkcs11.c]
|
||||
Use ssh_get_progname to fill __progname
|
||||
- (djm) [configure.ac] Enable PKCS#11 support only when we find a working
|
||||
dlopen()
|
||||
|
||||
20100210
|
||||
- (djm) add -lselinux to LIBS before calling AC_CHECK_FUNCS for
|
||||
getseuserbyname; patch from calebcase AT gmail.com via
|
||||
cjwatson AT debian.org
|
||||
|
||||
20100202
|
||||
- (djm) OpenBSD CVS Sync
|
||||
- djm@cvs.openbsd.org 2010/01/30 21:08:33
|
||||
[sshd.8]
|
||||
debug output goes to stderr, not "the system log"; ok markus dtucker
|
||||
- djm@cvs.openbsd.org 2010/01/30 21:12:08
|
||||
[channels.c]
|
||||
fake local addr:port when stdio fowarding as some servers (Tectia at
|
||||
least) validate that they are well-formed;
|
||||
reported by imorgan AT nas.nasa.gov
|
||||
ok dtucker
|
||||
|
||||
20100130
|
||||
- (djm) OpenBSD CVS Sync
|
||||
- djm@cvs.openbsd.org 2010/01/28 00:21:18
|
||||
[clientloop.c]
|
||||
downgrade an error() to a debug() - this particular case can be hit in
|
||||
normal operation for certain sequences of mux slave vs session closure
|
||||
and is harmless
|
||||
- djm@cvs.openbsd.org 2010/01/29 00:20:41
|
||||
[sshd.c]
|
||||
set FD_CLOEXEC on sock_in/sock_out; bz#1706 from jchadima AT redhat.com
|
||||
ok dtucker@
|
||||
- djm@cvs.openbsd.org 2010/01/29 20:16:17
|
||||
[mux.c]
|
||||
kill correct channel (was killing already-dead mux channel, not
|
||||
its session channel)
|
||||
- djm@cvs.openbsd.org 2010/01/30 02:54:53
|
||||
[mux.c]
|
||||
don't mark channel as read failed if it is already closing; suppresses
|
||||
harmless error messages when connecting to SSH.COM Tectia server
|
||||
report by imorgan AT nas.nasa.gov
|
||||
|
||||
20100129
|
||||
- (dtucker) [openbsd-compat/openssl-compat.c] Bug #1707: Call OPENSSL_config()
|
||||
after registering the hardware engines, which causes the openssl.cnf file to
|
||||
be processed. See OpenSSL's man page for OPENSSL_config(3) for details.
|
||||
Patch from Solomon Peachy, ok djm@.
|
||||
|
||||
20100128
|
||||
- (djm) OpenBSD CVS Sync
|
||||
- djm@cvs.openbsd.org 2010/01/26 02:15:20
|
||||
[mux.c]
|
||||
-Wuninitialized and remove a // comment; from portable
|
||||
(Id sync only)
|
||||
- djm@cvs.openbsd.org 2010/01/27 13:26:17
|
||||
[mux.c]
|
||||
fix bug introduced in mux rewrite:
|
||||
|
||||
In a mux master, when a socket to a mux slave closes before its server
|
||||
session (as may occur when the slave has been signalled), gracefully
|
||||
close the server session rather than deleting its channel immediately.
|
||||
A server may have more messages on that channel to send (e.g. an exit
|
||||
message) that will fatal() the client if they are sent to a channel that
|
||||
has been prematurely deleted.
|
||||
|
||||
spotted by imorgan AT nas.nasa.gov
|
||||
- djm@cvs.openbsd.org 2010/01/27 19:21:39
|
||||
[sftp.c]
|
||||
add missing "p" flag to getopt optstring;
|
||||
bz#1704 from imorgan AT nas.nasa.gov
|
||||
|
||||
20100126
|
||||
- (djm) OpenBSD CVS Sync
|
||||
- tedu@cvs.openbsd.org 2010/01/17 21:49:09
|
||||
[ssh-agent.1]
|
||||
Correct and clarify ssh-add's password asking behavior.
|
||||
Improved text dtucker and ok jmc
|
||||
- dtucker@cvs.openbsd.org 2010/01/18 01:50:27
|
||||
[roaming_client.c]
|
||||
s/long long unsigned/unsigned long long/, from tim via portable
|
||||
(Id sync only, change already in portable)
|
||||
- djm@cvs.openbsd.org 2010/01/26 01:28:35
|
||||
[channels.c channels.h clientloop.c clientloop.h mux.c nchan.c ssh.c]
|
||||
rewrite ssh(1) multiplexing code to a more sensible protocol.
|
||||
|
||||
The new multiplexing code uses channels for the listener and
|
||||
accepted control sockets to make the mux master non-blocking, so
|
||||
no stalls when processing messages from a slave.
|
||||
|
||||
avoid use of fatal() in mux master protocol parsing so an errant slave
|
||||
process cannot take down a running master.
|
||||
|
||||
implement requesting of port-forwards over multiplexed sessions. Any
|
||||
port forwards requested by the slave are added to those the master has
|
||||
established.
|
||||
|
||||
add support for stdio forwarding ("ssh -W host:port ...") in mux slaves.
|
||||
|
||||
document master/slave mux protocol so that other tools can use it to
|
||||
control a running ssh(1). Note: there are no guarantees that this
|
||||
protocol won't be incompatibly changed (though it is versioned).
|
||||
|
||||
feedback Salvador Fandino, dtucker@
|
||||
channel changes ok markus@
|
||||
|
||||
20100122
|
||||
- (tim) [configure.ac] Due to constraints in Windows Sockets in terms of
|
||||
socket inheritance, reduce the default SO_RCVBUF/SO_SNDBUF buffer size
|
||||
in Cygwin to 65535. Patch from Corinna Vinschen.
|
||||
|
||||
20100117
|
||||
- (tim) [configure.ac] OpenServer 5 needs BROKEN_GETADDRINFO too.
|
||||
- (tim) [configure.ac] On SVR5 systems, use the C99-conforming functions
|
||||
snprintf() and vsnprintf() named _xsnprintf() and _xvsnprintf().
|
||||
|
||||
20100116
|
||||
- (dtucker) [openbsd-compat/pwcache.c] Pull in includes.h and thus defines.h
|
||||
so we correctly detect whether or not we have a native user_from_uid.
|
||||
- (dtucker) [openbsd-compat/openbsd-compat.h] Prototypes for user_from_uid
|
||||
and group_from_gid.
|
||||
- (dtucker) [openbsd-compat/openbsd-compat.h] Fix prototypes, spotted by
|
||||
Tim.
|
||||
- (dtucker) OpenBSD CVS Sync
|
||||
- markus@cvs.openbsd.org 2010/01/15 09:24:23
|
||||
[sftp-common.c]
|
||||
unused
|
||||
- (dtucker) [openbsd-compat/pwcache.c] Shrink ifdef area to prevent unused
|
||||
variable warnings.
|
||||
- (dtucker) [openbsd-compat/openbsd-compat.h] Typo.
|
||||
- (tim) [regress/portnum.sh] Shell portability fix.
|
||||
- (tim) [configure.ac] Define BROKEN_GETADDRINFO on SVR5 systems. The native
|
||||
getaddrinfo() is too old and limited for addr_pton() in addrmatch.c.
|
||||
- (tim) [roaming_client.c] Use of <sys/queue.h> is not really portable so we
|
||||
use "openbsd-compat/sys-queue.h". s/long long unsigned/unsigned long long/
|
||||
to keep USL compilers happy.
|
||||
|
||||
20100115
|
||||
- (dtucker) OpenBSD CVS Sync
|
||||
- jmc@cvs.openbsd.org 2010/01/13 12:48:34
|
||||
[sftp.1 sftp.c]
|
||||
sftp.1: put ls -h in the right place
|
||||
sftp.c: as above, plus add -p to get/put, and shorten their arg names
|
||||
to keep the help usage nicely aligned
|
||||
ok djm
|
||||
- djm@cvs.openbsd.org 2010/01/13 23:47:26
|
||||
[auth.c]
|
||||
when using ChrootDirectory, make sure we test for the existence of the
|
||||
user's shell inside the chroot; bz #1679, patch from alex AT rtfs.hu;
|
||||
ok dtucker
|
||||
- dtucker@cvs.openbsd.org 2010/01/14 23:41:49
|
||||
[sftp-common.c]
|
||||
use user_from{uid,gid} to lookup up ids since it keeps a small cache.
|
||||
ok djm
|
||||
- guenther@cvs.openbsd.org 2010/01/15 00:05:22
|
||||
[sftp.c]
|
||||
Reset SIGTERM to SIG_DFL before executing ssh, so that even if sftp
|
||||
inherited SIGTERM as ignored it will still be able to kill the ssh it
|
||||
starts.
|
||||
ok dtucker@
|
||||
- (dtucker) [openbsd-compat/pwcache.c] Pull in pwcache.c from OpenBSD (no
|
||||
changes yet but there will be some to come).
|
||||
- (dtucker) [configure.ac openbsd-compat/{Makefile.in,pwcache.c} Portability
|
||||
for pwcache. Also, added caching of negative hits.
|
||||
|
||||
20100114
|
||||
- (djm) [platform.h] Add missing prototype for
|
||||
platform_krb5_get_principal_name
|
||||
|
||||
20100113
|
||||
- (dtucker) [monitor_fdpass.c] Wrap poll.h include in ifdefs.
|
||||
- (dtucker) [openbsd-compat/readpassphrase.c] Resync against OpenBSD's r1.18:
|
||||
missing restore of SIGTTOU and some whitespace.
|
||||
- (dtucker) [openbsd-compat/readpassphrase.c] Update to OpenBSD's r1.21.
|
||||
- (dtucker) [openbsd-compat/readpassphrase.c] Update to OpenBSD's r1.22.
|
||||
Fixes bz #1590, where sometimes you could not interrupt a connection while
|
||||
ssh was prompting for a passphrase or password.
|
||||
- (dtucker) OpenBSD CVS Sync
|
||||
- dtucker@cvs.openbsd.org 2010/01/13 00:19:04
|
||||
[sshconnect.c auth.c]
|
||||
Fix a couple of typos/mispellings in comments
|
||||
- dtucker@cvs.openbsd.org 2010/01/13 01:10:56
|
||||
[key.c]
|
||||
Ignore and log any Protocol 1 keys where the claimed size is not equal to
|
||||
the actual size. Noted by Derek Martin, ok djm@
|
||||
- dtucker@cvs.openbsd.org 2010/01/13 01:20:20
|
||||
[canohost.c ssh-keysign.c sshconnect2.c]
|
||||
Make HostBased authentication work with a ProxyCommand. bz #1569, patch
|
||||
from imorgan at nas nasa gov, ok djm@
|
||||
- djm@cvs.openbsd.org 2010/01/13 01:40:16
|
||||
[sftp.c sftp-server.c sftp.1 sftp-common.c sftp-common.h]
|
||||
support '-h' (human-readable units) for sftp's ls command, just like
|
||||
ls(1); ok dtucker@
|
||||
- djm@cvs.openbsd.org 2010/01/13 03:48:13
|
||||
[servconf.c servconf.h sshd.c]
|
||||
avoid run-time failures when specifying hostkeys via a relative
|
||||
path by prepending the cwd in these cases; bz#1290; ok dtucker@
|
||||
- djm@cvs.openbsd.org 2010/01/13 04:10:50
|
||||
[sftp.c]
|
||||
don't append a space after inserting a completion of a directory (i.e.
|
||||
a path ending in '/') for a slightly better user experience; ok dtucker@
|
||||
- (dtucker) [sftp-common.c] Wrap include of util.h in an ifdef.
|
||||
- (tim) [defines.h] openbsd-compat/readpassphrase.c now needs _NSIG.
|
||||
feedback and ok dtucker@
|
||||
|
||||
20100112
|
||||
- (dtucker) OpenBSD CVS Sync
|
||||
- dtucker@cvs.openbsd.org 2010/01/11 01:39:46
|
||||
[ssh_config channels.c ssh.1 channels.h ssh.c]
|
||||
Add a 'netcat mode' (ssh -W). This connects stdio on the client to a
|
||||
single port forward on the server. This allows, for example, using ssh as
|
||||
a ProxyCommand to route connections via intermediate servers.
|
||||
bz #1618, man page help from jmc@, ok markus@
|
||||
- dtucker@cvs.openbsd.org 2010/01/11 04:46:45
|
||||
[authfile.c sshconnect2.c]
|
||||
Do not prompt for a passphrase if we fail to open a keyfile, and log the
|
||||
reason the open failed to debug.
|
||||
bz #1693, found by tj AT castaglia org, ok djm@
|
||||
- djm@cvs.openbsd.org 2010/01/11 10:51:07
|
||||
[ssh-keygen.c]
|
||||
when converting keys, truncate key comments at 72 chars as per RFC4716;
|
||||
bz#1630 reported by tj AT castaglia.org; ok markus@
|
||||
- dtucker@cvs.openbsd.org 2010/01/12 00:16:47
|
||||
[authfile.c]
|
||||
Fix bug introduced in r1.78 (incorrect brace location) that broke key auth.
|
||||
Patch from joachim joachimschipper nl.
|
||||
- djm@cvs.openbsd.org 2010/01/12 00:58:25
|
||||
[monitor_fdpass.c]
|
||||
avoid spinning when fd passing on nonblocking sockets by calling poll()
|
||||
in the EINTR/EAGAIN path, much like we do in atomicio; ok dtucker@
|
||||
- djm@cvs.openbsd.org 2010/01/12 00:59:29
|
||||
[roaming_common.c]
|
||||
delete with extreme prejudice a debug() that fired with every keypress;
|
||||
ok dtucker deraadt
|
||||
- dtucker@cvs.openbsd.org 2010/01/12 01:31:05
|
||||
[session.c]
|
||||
Do not allow logins if /etc/nologin exists but is not readable by the user
|
||||
logging in. Noted by Jan.Pechanec at Sun, ok djm@ deraadt@
|
||||
- djm@cvs.openbsd.org 2010/01/12 01:36:08
|
||||
[buffer.h bufaux.c]
|
||||
add a buffer_get_string_ptr_ret() that does the same as
|
||||
buffer_get_string_ptr() but does not fatal() on error; ok dtucker@
|
||||
- dtucker@cvs.openbsd.org 2010/01/12 08:33:17
|
||||
[session.c]
|
||||
Add explicit stat so we reliably detect nologin with bad perms.
|
||||
ok djm markus
|
||||
|
||||
20100110
|
||||
- (dtucker) [configure.ac misc.c readconf.c servconf.c ssh-keyscan.c]
|
||||
Remove hacks add for RoutingDomain in preparation for its removal.
|
||||
- (dtucker) OpenBSD CVS Sync
|
||||
- dtucker@cvs.openbsd.org 2010/01/09 23:04:13
|
||||
[channels.c ssh.1 servconf.c sshd_config.5 sshd.c channels.h servconf.h
|
||||
ssh-keyscan.1 ssh-keyscan.c readconf.c sshconnect.c misc.c ssh.c
|
||||
readconf.h scp.1 sftp.1 ssh_config.5 misc.h]
|
||||
Remove RoutingDomain from ssh since it's now not needed. It can be
|
||||
replaced with "route exec" or "nc -V" as a proxycommand. "route exec"
|
||||
also ensures that trafic such as DNS lookups stays withing the specified
|
||||
routingdomain. For example (from reyk):
|
||||
# route -T 2 exec /usr/sbin/sshd
|
||||
or inherited from the parent process
|
||||
$ route -T 2 exec sh
|
||||
$ ssh 10.1.2.3
|
||||
ok deraadt@ markus@ stevesk@ reyk@
|
||||
- dtucker@cvs.openbsd.org 2010/01/10 03:51:17
|
||||
[servconf.c]
|
||||
Add ChrootDirectory to sshd.c test-mode output
|
||||
- dtucker@cvs.openbsd.org 2010/01/10 07:15:56
|
||||
[auth.c]
|
||||
Output a debug if we can't open an existing keyfile. bz#1694, ok djm@
|
||||
|
||||
20100109
|
||||
- (dtucker) Wrap use of IPPROTO_IPV6 in an ifdef for platforms that don't
|
||||
have it.
|
||||
- (dtucker) [defines.h] define PRIu64 for platforms that don't have it.
|
||||
- (dtucker) [roaming_client.c] Wrap inttypes.h in an ifdef.
|
||||
- (dtucker) [loginrec.c] Use the SUSv3 specified name for the user name
|
||||
when using utmpx. Patch from Ed Schouten.
|
||||
- (dtucker) OpenBSD CVS Sync
|
||||
- djm@cvs.openbsd.org 2010/01/09 00:20:26
|
||||
[sftp-server.c sftp-server.8]
|
||||
add a 'read-only' mode to sftp-server(8) that disables open in write mode
|
||||
and all other fs-modifying protocol methods. bz#430 ok dtucker@
|
||||
- djm@cvs.openbsd.org 2010/01/09 00:57:10
|
||||
[PROTOCOL]
|
||||
tweak language
|
||||
- jmc@cvs.openbsd.org 2010/01/09 03:36:00
|
||||
[sftp-server.8]
|
||||
bad place to forget a comma...
|
||||
- djm@cvs.openbsd.org 2010/01/09 05:04:24
|
||||
[mux.c sshpty.h clientloop.c sshtty.c]
|
||||
quell tc[gs]etattr warnings when forcing a tty (ssh -tt), since we
|
||||
usually don't actually have a tty to read/set; bz#1686 ok dtucker@
|
||||
- dtucker@cvs.openbsd.org 2010/01/09 05:17:00
|
||||
[roaming_client.c]
|
||||
Remove a PRIu64 format string that snuck in with roaming. ok djm@
|
||||
- dtucker@cvs.openbsd.org 2010/01/09 11:13:02
|
||||
[sftp.c]
|
||||
Prevent sftp from derefing a null pointer when given a "-" without a
|
||||
command. Also, allow whitespace to follow a "-". bz#1691, path from
|
||||
Colin Watson via Debian. ok djm@ deraadt@
|
||||
- dtucker@cvs.openbsd.org 2010/01/09 11:17:56
|
||||
[sshd.c]
|
||||
Afer sshd receives a SIGHUP, ignore subsequent HUPs while sshd re-execs
|
||||
itself. Prevents two HUPs in quick succession from resulting in sshd
|
||||
dying. bz#1692, patch from Colin Watson via Ubuntu.
|
||||
- (dtucker) [defines.h] Remove now-undeeded PRIu64 define.
|
||||
|
||||
20100108
|
||||
- (dtucker) OpenBSD CVS Sync
|
||||
- andreas@cvs.openbsd.org 2009/10/24 11:11:58
|
||||
[roaming.h]
|
||||
Declarations needed for upcoming changes.
|
||||
ok markus@
|
||||
- andreas@cvs.openbsd.org 2009/10/24 11:13:54
|
||||
[sshconnect2.c kex.h kex.c]
|
||||
Let the client detect if the server supports roaming by looking
|
||||
for the resume@appgate.com kex algorithm.
|
||||
ok markus@
|
||||
- andreas@cvs.openbsd.org 2009/10/24 11:15:29
|
||||
[clientloop.c]
|
||||
client_loop() must detect if the session has been suspended and resumed,
|
||||
and take appropriate action in that case.
|
||||
From Martin Forssen, maf at appgate dot com
|
||||
- andreas@cvs.openbsd.org 2009/10/24 11:19:17
|
||||
[ssh2.h]
|
||||
Define the KEX messages used when resuming a suspended connection.
|
||||
ok markus@
|
||||
- andreas@cvs.openbsd.org 2009/10/24 11:22:37
|
||||
[roaming_common.c]
|
||||
Do the actual suspend/resume in the client. This won't be useful until
|
||||
the server side supports roaming.
|
||||
Most code from Martin Forssen, maf at appgate dot com. Some changes by
|
||||
me and markus@
|
||||
ok markus@
|
||||
- andreas@cvs.openbsd.org 2009/10/24 11:23:42
|
||||
[ssh.c]
|
||||
Request roaming to be enabled if UseRoaming is true and the server
|
||||
supports it.
|
||||
ok markus@
|
||||
- reyk@cvs.openbsd.org 2009/10/28 16:38:18
|
||||
[ssh_config.5 sshd.c misc.h ssh-keyscan.1 readconf.h sshconnect.c
|
||||
channels.c channels.h servconf.h servconf.c ssh.1 ssh-keyscan.c scp.1
|
||||
sftp.1 sshd_config.5 readconf.c ssh.c misc.c]
|
||||
Allow to set the rdomain in ssh/sftp/scp/sshd and ssh-keyscan.
|
||||
ok markus@
|
||||
- jmc@cvs.openbsd.org 2009/10/28 21:45:08
|
||||
[sshd_config.5 sftp.1]
|
||||
tweak previous;
|
||||
- djm@cvs.openbsd.org 2009/11/10 02:56:22
|
||||
[ssh_config.5]
|
||||
explain the constraints on LocalCommand some more so people don't
|
||||
try to abuse it.
|
||||
- djm@cvs.openbsd.org 2009/11/10 02:58:56
|
||||
[sshd_config.5]
|
||||
clarify that StrictModes does not apply to ChrootDirectory. Permissions
|
||||
and ownership are always checked when chrooting. bz#1532
|
||||
- dtucker@cvs.openbsd.org 2009/11/10 04:30:45
|
||||
[sshconnect2.c channels.c sshconnect.c]
|
||||
Set close-on-exec on various descriptors so they don't get leaked to
|
||||
child processes. bz #1643, patch from jchadima at redhat, ok deraadt.
|
||||
- markus@cvs.openbsd.org 2009/11/11 21:37:03
|
||||
[channels.c channels.h]
|
||||
fix race condition in x11/agent channel allocation: don't read after
|
||||
the end of the select read/write fdset and make sure a reused FD
|
||||
is not touched before the pre-handlers are called.
|
||||
with and ok djm@
|
||||
- djm@cvs.openbsd.org 2009/11/17 05:31:44
|
||||
[clientloop.c]
|
||||
fix incorrect exit status when multiplexing and channel ID 0 is recycled
|
||||
bz#1570 reported by peter.oliver AT eon-is.co.uk; ok dtucker
|
||||
- djm@cvs.openbsd.org 2009/11/19 23:39:50
|
||||
[session.c]
|
||||
bz#1606: error when an attempt is made to connect to a server
|
||||
with ForceCommand=internal-sftp with a shell session (i.e. not a
|
||||
subsystem session). Avoids stuck client when attempting to ssh to such a
|
||||
service. ok dtucker@
|
||||
- dtucker@cvs.openbsd.org 2009/11/20 00:15:41
|
||||
[session.c]
|
||||
Warn but do not fail if stat()ing the subsystem binary fails. This helps
|
||||
with chrootdirectory+forcecommand=sftp-server and restricted shells.
|
||||
bz #1599, ok djm.
|
||||
- djm@cvs.openbsd.org 2009/11/20 00:54:01
|
||||
[sftp.c]
|
||||
bz#1588 change "Connecting to host..." message to "Connected to host."
|
||||
and delay it until after the sftp protocol connection has been established.
|
||||
Avoids confusing sequence of messages when the underlying ssh connection
|
||||
experiences problems. ok dtucker@
|
||||
- dtucker@cvs.openbsd.org 2009/11/20 00:59:36
|
||||
[sshconnect2.c]
|
||||
Use the HostKeyAlias when prompting for passwords. bz#1039, ok djm@
|
||||
- djm@cvs.openbsd.org 2009/11/20 03:24:07
|
||||
[misc.c]
|
||||
correct off-by-one in percent_expand(): we would fatal() when trying
|
||||
to expand EXPAND_MAX_KEYS, allowing only EXPAND_MAX_KEYS-1 to actually
|
||||
work. Note that nothing in OpenSSH actually uses close to this limit at
|
||||
present. bz#1607 from Jan.Pechanec AT Sun.COM
|
||||
- halex@cvs.openbsd.org 2009/11/22 13:18:00
|
||||
[sftp.c]
|
||||
make passing of zero-length arguments to ssh safe by
|
||||
passing "-<switch>" "<value>" rather than "-<switch><value>"
|
||||
ok dtucker@, guenther@, djm@
|
||||
- dtucker@cvs.openbsd.org 2009/12/06 23:41:15
|
||||
[sshconnect2.c]
|
||||
zap unused variable and strlen; from Steve McClellan, ok djm
|
||||
- djm@cvs.openbsd.org 2009/12/06 23:53:45
|
||||
[roaming_common.c]
|
||||
use socklen_t for getsockopt optlen parameter; reported by
|
||||
Steve.McClellan AT radisys.com, ok dtucker@
|
||||
- dtucker@cvs.openbsd.org 2009/12/06 23:53:54
|
||||
[sftp.c]
|
||||
fix potential divide-by-zero in sftp's "df" output when talking to a server
|
||||
that reports zero files on the filesystem (Unix filesystems always have at
|
||||
least the root inode). From Steve McClellan at radisys, ok djm@
|
||||
- markus@cvs.openbsd.org 2009/12/11 18:16:33
|
||||
[key.c]
|
||||
switch from 35 to the more common value of RSA_F4 == (2**16)+1 == 65537
|
||||
for the RSA public exponent; discussed with provos; ok djm@
|
||||
- guenther@cvs.openbsd.org 2009/12/20 07:28:36
|
||||
[ssh.c sftp.c scp.c]
|
||||
When passing user-controlled options with arguments to other programs,
|
||||
pass the option and option argument as separate argv entries and
|
||||
not smashed into one (e.g., as -l foo and not -lfoo). Also, always
|
||||
pass a "--" argument to stop option parsing, so that a positional
|
||||
argument that starts with a '-' isn't treated as an option. This
|
||||
fixes some error cases as well as the handling of hostnames and
|
||||
filenames that start with a '-'.
|
||||
Based on a diff by halex@
|
||||
ok halex@ djm@ deraadt@
|
||||
- djm@cvs.openbsd.org 2009/12/20 23:20:40
|
||||
[PROTOCOL]
|
||||
fix an incorrect magic number and typo in PROTOCOL; bz#1688
|
||||
report and fix from ueno AT unixuser.org
|
||||
- stevesk@cvs.openbsd.org 2009/12/25 19:40:21
|
||||
[readconf.c servconf.c misc.h ssh-keyscan.c misc.c]
|
||||
validate routing domain is in range 0-RT_TABLEID_MAX.
|
||||
'Looks right' deraadt@
|
||||
- stevesk@cvs.openbsd.org 2009/12/29 16:38:41
|
||||
[sshd_config.5 readconf.c ssh_config.5 scp.1 servconf.c sftp.1 ssh.1]
|
||||
Rename RDomain config option to RoutingDomain to be more clear and
|
||||
consistent with other options.
|
||||
NOTE: if you currently use RDomain in the ssh client or server config,
|
||||
or ssh/sshd -o, you must update to use RoutingDomain.
|
||||
ok markus@ djm@
|
||||
- jmc@cvs.openbsd.org 2009/12/29 18:03:32
|
||||
[sshd_config.5 ssh_config.5]
|
||||
sort previous;
|
||||
- dtucker@cvs.openbsd.org 2010/01/04 01:45:30
|
||||
[sshconnect2.c]
|
||||
Don't escape backslashes in the SSH2 banner. bz#1533, patch from
|
||||
Michal Gorny via Gentoo.
|
||||
- djm@cvs.openbsd.org 2010/01/04 02:03:57
|
||||
[sftp.c]
|
||||
Implement tab-completion of commands, local and remote filenames for sftp.
|
||||
Hacked on and off for some time by myself, mouring, Carlos Silva (via 2009
|
||||
Google Summer of Code) and polished to a fine sheen by myself again.
|
||||
It should deal more-or-less correctly with the ikky corner-cases presented
|
||||
by quoted filenames, but the UI could still be slightly improved.
|
||||
In particular, it is quite slow for remote completion on large directories.
|
||||
bz#200; ok markus@
|
||||
- djm@cvs.openbsd.org 2010/01/04 02:25:15
|
||||
[sftp-server.c]
|
||||
bz#1566 don't unnecessarily dup() in and out fds for sftp-server;
|
||||
ok markus@
|
||||
- dtucker@cvs.openbsd.org 2010/01/08 21:50:49
|
||||
[sftp.c]
|
||||
Fix two warnings: possibly used unitialized and use a nul byte instead of
|
||||
NULL pointer. ok djm@
|
||||
- (dtucker) [Makefile.in added roaming_client.c roaming_serv.c] Import new
|
||||
files for roaming and add to Makefile.
|
||||
- (dtucker) [Makefile.in] .c files do not belong in the OBJ lines.
|
||||
- (dtucker) [sftp.c] ifdef out the sftp completion bits for platforms that
|
||||
don't have libedit.
|
||||
- (dtucker) [configure.ac misc.c readconf.c servconf.c ssh-keyscan.c] Make
|
||||
RoutingDomain an unsupported option on platforms that don't have it.
|
||||
- (dtucker) [sftp.c] Expand ifdef for libedit to cover complete_is_remote
|
||||
too.
|
||||
- (dtucker) [misc.c] Move the routingdomain ifdef to allow the socket to
|
||||
be created.
|
||||
- (dtucker] [misc.c] Shrink the area covered by USE_ROUTINGDOMAIN more
|
||||
to eliminate an unused variable warning.
|
||||
- (dtucker) [roaming_serv.c] Include includes.h for u_intXX_t types.
|
||||
|
||||
20091226
|
||||
- (tim) [contrib/cygwin/Makefile] Install ssh-copy-id and ssh-copy-id.1
|
||||
Gzip all man pages. Patch from Corinna Vinschen.
|
||||
|
||||
20091221
|
||||
- (dtucker) [auth-krb5.c platform.{c,h} openbsd-compat/port-aix.{c,h}]
|
||||
Bug #1583: Use system's kerberos principal name on AIX if it's available.
|
||||
Based on a patch from and tested by Miguel Sanders
|
||||
|
||||
20091208
|
||||
- (dtucker) Bug #1470: Disable OOM-killing of the listening sshd on Linux,
|
||||
based on a patch from Vaclav Ovsik and Colin Watson. ok djm.
|
||||
|
||||
20091207
|
||||
- (dtucker) Bug #1160: use pkg-config for opensc config if it's available.
|
||||
Tested by Martin Paljak.
|
||||
- (dtucker) Bug #1677: add conditionals around the source for ssh-askpass.
|
||||
|
||||
20091121
|
||||
- (tim) [opensshd.init.in] If PidFile is set in sshd_config, use it.
|
||||
Bug 1628. OK dtucker@
|
||||
|
||||
20091120
|
||||
- (djm) [ssh-rand-helper.c] Print error and usage() when passed command-
|
||||
line arguments as none are supported. Exit when passed unrecognised
|
||||
commandline flags. bz#1568 from gson AT araneus.fi
|
||||
|
||||
20091118
|
||||
- (djm) [channels.c misc.c misc.h sshd.c] add missing setsockopt() to
|
||||
set IPV6_V6ONLY for local forwarding with GatwayPorts=yes. Unify
|
||||
setting IPV6_V6ONLY behind a new function misc.c:sock_set_v6only()
|
||||
bz#1648, report and fix from jan.kratochvil AT redhat.com
|
||||
- (djm) [contrib/gnome-ssh-askpass2.c] Make askpass dialog desktop-modal.
|
||||
bz#1645, patch from jchadima AT redhat.com
|
||||
|
||||
20091107
|
||||
- (dtucker) [authfile.c] Fall back to 3DES for the encryption of private
|
||||
keys when built with OpenSSL versions that don't do AES.
|
||||
|
||||
20091105
|
||||
- (dtucker) [authfile.c] Add OpenSSL compat header so this still builds with
|
||||
older versions of OpenSSL.
|
||||
|
||||
20091024
|
||||
- (dtucker) OpenBSD CVS Sync
|
||||
- djm@cvs.openbsd.org 2009/10/11 23:03:15
|
||||
[hostfile.c]
|
||||
mention the host name that we are looking for in check_host_in_hostfile()
|
||||
- sobrado@cvs.openbsd.org 2009/10/17 12:10:39
|
||||
[sftp-server.c]
|
||||
sort flags.
|
||||
- sobrado@cvs.openbsd.org 2009/10/22 12:35:53
|
||||
[ssh.1 ssh-agent.1 ssh-add.1]
|
||||
use the UNIX-related macros (.At and .Ux) where appropriate.
|
||||
ok jmc@
|
||||
- sobrado@cvs.openbsd.org 2009/10/22 15:02:12
|
||||
[ssh-agent.1 ssh-add.1 ssh.1]
|
||||
write UNIX-domain in a more consistent way; while here, replace a
|
||||
few remaining ".Tn UNIX" macros with ".Ux" ones.
|
||||
pointed out by ratchov@, thanks!
|
||||
ok jmc@
|
||||
- djm@cvs.openbsd.org 2009/10/22 22:26:13
|
||||
[authfile.c]
|
||||
switch from 3DES to AES-128 for encryption of passphrase-protected
|
||||
SSH protocol 2 private keys; ok several
|
||||
- djm@cvs.openbsd.org 2009/10/23 01:57:11
|
||||
[sshconnect2.c]
|
||||
disallow a hostile server from checking jpake auth by sending an
|
||||
out-of-sequence success message. (doesn't affect code enabled by default)
|
||||
- dtucker@cvs.openbsd.org 2009/10/24 00:48:34
|
||||
[ssh-keygen.1]
|
||||
ssh-keygen now uses AES-128 for private keys
|
||||
- (dtucker) [mdoc2man.awk] Teach it to understand the .Ux macro.
|
||||
- (dtucker) [session.c openbsd-compat/port-linux.{c,h}] Bug #1637: if selinux
|
||||
is enabled set the security context to "sftpd_t" before running the
|
||||
internal sftp server Based on a patch from jchadima at redhat.
|
||||
|
||||
20091011
|
||||
- (dtucker) [configure.ac sftp-client.c] Remove the gyrations required for
|
||||
dirent d_type and DTTOIF as we've switched OpenBSD to the more portable
|
||||
lstat.
|
||||
- (dtucker) OpenBSD CVS Sync
|
||||
- markus@cvs.openbsd.org 2009/10/08 14:03:41
|
||||
[sshd_config readconf.c ssh_config.5 servconf.c sshd_config.5]
|
||||
disable protocol 1 by default (after a transition period of about 10 years)
|
||||
ok deraadt
|
||||
- jmc@cvs.openbsd.org 2009/10/08 20:42:12
|
||||
[sshd_config.5 ssh_config.5 sshd.8 ssh.1]
|
||||
some tweaks now that protocol 1 is not offered by default; ok markus
|
||||
- dtucker@cvs.openbsd.org 2009/10/11 10:41:26
|
||||
[sftp-client.c]
|
||||
d_type isn't portable so use lstat to get dirent modes. Suggested by and
|
||||
"looks sane" deraadt@
|
||||
- markus@cvs.openbsd.org 2009/10/08 18:04:27
|
||||
[regress/test-exec.sh]
|
||||
re-enable protocol v1 for the tests.
|
||||
|
||||
20091007
|
||||
- (dtucker) OpenBSD CVS Sync
|
||||
- djm@cvs.openbsd.org 2009/08/12 00:13:00
|
||||
[sftp.c sftp.1]
|
||||
support most of scp(1)'s commandline arguments in sftp(1), as a first
|
||||
step towards making sftp(1) a drop-in replacement for scp(1).
|
||||
One conflicting option (-P) has not been changed, pending further
|
||||
discussion.
|
||||
Patch from carlosvsilvapt@gmail.com as part of his work in the
|
||||
Google Summer of Code
|
||||
- jmc@cvs.openbsd.org 2009/08/12 06:31:42
|
||||
[sftp.1]
|
||||
sort options;
|
||||
- djm@cvs.openbsd.org 2009/08/13 01:11:19
|
||||
[sftp.1 sftp.c]
|
||||
Swizzle options: "-P sftp_server_path" moves to "-D sftp_server_path",
|
||||
add "-P port" to match scp(1). Fortunately, the -P option is only really
|
||||
used by our regression scripts.
|
||||
part of larger patch from carlosvsilvapt@gmail.com for his Google Summer
|
||||
of Code work; ok deraadt markus
|
||||
- jmc@cvs.openbsd.org 2009/08/13 13:39:54
|
||||
[sftp.1 sftp.c]
|
||||
sync synopsis and usage();
|
||||
- djm@cvs.openbsd.org 2009/08/14 18:17:49
|
||||
[sftp-client.c]
|
||||
make the "get_handle: ..." error messages vaguely useful by allowing
|
||||
callers to specify their own error message strings.
|
||||
- fgsch@cvs.openbsd.org 2009/08/15 18:56:34
|
||||
[auth.h]
|
||||
remove unused define. markus@ ok.
|
||||
(Id sync only, Portable still uses this.)
|
||||
- dtucker@cvs.openbsd.org 2009/08/16 23:29:26
|
||||
[sshd_config.5]
|
||||
Add PubkeyAuthentication to the list allowed in a Match block (bz #1577)
|
||||
- djm@cvs.openbsd.org 2009/08/18 18:36:21
|
||||
[sftp-client.h sftp.1 sftp-client.c sftp.c]
|
||||
recursive transfer support for get/put and on the commandline
|
||||
work mostly by carlosvsilvapt@gmail.com for the Google Summer of Code
|
||||
with some tweaks by me; "go for it" deraadt@
|
||||
- djm@cvs.openbsd.org 2009/08/18 21:15:59
|
||||
[sftp.1]
|
||||
fix "get" command usage, spotted by jmc@
|
||||
- jmc@cvs.openbsd.org 2009/08/19 04:56:03
|
||||
[sftp.1]
|
||||
ether -> either;
|
||||
- dtucker@cvs.openbsd.org 2009/08/20 23:54:28
|
||||
[mux.c]
|
||||
subsystem_flag is defined in ssh.c so it's extern; ok djm
|
||||
- djm@cvs.openbsd.org 2009/08/27 17:28:52
|
||||
[sftp-server.c]
|
||||
allow setting an explicit umask on the commandline to override whatever
|
||||
default the user has. bz#1229; ok dtucker@ deraadt@ markus@
|
||||
- djm@cvs.openbsd.org 2009/08/27 17:33:49
|
||||
[ssh-keygen.c]
|
||||
force use of correct hash function for random-art signature display
|
||||
as it was inheriting the wrong one when bubblebabble signatures were
|
||||
activated; bz#1611 report and patch from fwojcik+openssh AT besh.com;
|
||||
ok markus@
|
||||
- djm@cvs.openbsd.org 2009/08/27 17:43:00
|
||||
[sftp-server.8]
|
||||
allow setting an explicit umask on the commandline to override whatever
|
||||
default the user has. bz#1229; ok dtucker@ deraadt@ markus@
|
||||
- djm@cvs.openbsd.org 2009/08/27 17:44:52
|
||||
[authfd.c ssh-add.c authfd.h]
|
||||
Do not fall back to adding keys without contraints (ssh-add -c / -t ...)
|
||||
when the agent refuses the constrained add request. This was a useful
|
||||
migration measure back in 2002 when constraints were new, but just
|
||||
adds risk now.
|
||||
bz #1612, report and patch from dkg AT fifthhorseman.net; ok markus@
|
||||
- djm@cvs.openbsd.org 2009/08/31 20:56:02
|
||||
[sftp-server.c]
|
||||
check correct variable for error message, spotted by martynas@
|
||||
- djm@cvs.openbsd.org 2009/08/31 21:01:29
|
||||
[sftp-server.8]
|
||||
document -e and -h; prodded by jmc@
|
||||
- djm@cvs.openbsd.org 2009/09/01 14:43:17
|
||||
[ssh-agent.c]
|
||||
fix a race condition in ssh-agent that could result in a wedged or
|
||||
spinning agent: don't read off the end of the allocated fd_sets, and
|
||||
don't issue blocking read/write on agent sockets - just fall back to
|
||||
select() on retriable read/write errors. bz#1633 reported and tested
|
||||
by "noodle10000 AT googlemail.com"; ok dtucker@ markus@
|
||||
- grunk@cvs.openbsd.org 2009/10/01 11:37:33
|
||||
[dh.c]
|
||||
fix a cast
|
||||
ok djm@ markus@
|
||||
- djm@cvs.openbsd.org 2009/10/06 04:46:40
|
||||
[session.c]
|
||||
bz#1596: fflush(NULL) before exec() to ensure that everying (motd
|
||||
in particular) has made it out before the streams go away.
|
||||
- djm@cvs.openbsd.org 2008/12/07 22:17:48
|
||||
[regress/addrmatch.sh]
|
||||
match string "passwordauthentication" only at start of line, not anywhere
|
||||
in sshd -T output
|
||||
- dtucker@cvs.openbsd.org 2009/05/05 07:51:36
|
||||
[regress/multiplex.sh]
|
||||
Always specify ssh_config for multiplex tests: prevents breakage caused
|
||||
by options in ~/.ssh/config. From Dan Peterson.
|
||||
- djm@cvs.openbsd.org 2009/08/13 00:57:17
|
||||
[regress/Makefile]
|
||||
regression test for port number parsing. written as part of the a2port
|
||||
change that went into 5.2 but I forgot to commit it at the time...
|
||||
- djm@cvs.openbsd.org 2009/08/13 01:11:55
|
||||
[regress/sftp-batch.sh regress/sftp-badcmds.sh regress/sftp.sh
|
||||
regress/sftp-cmds.sh regres/sftp-glob.sh]
|
||||
date: 2009/08/13 01:11:19; author: djm; state: Exp; lines: +10 -7
|
||||
Swizzle options: "-P sftp_server_path" moves to "-D sftp_server_path",
|
||||
add "-P port" to match scp(1). Fortunately, the -P option is only really
|
||||
used by our regression scripts.
|
||||
part of larger patch from carlosvsilvapt@gmail.com for his Google Summer
|
||||
of Code work; ok deraadt markus
|
||||
- djm@cvs.openbsd.org 2009/08/20 18:43:07
|
||||
[regress/ssh-com-sftp.sh]
|
||||
fix one sftp -D ... => sftp -P ... conversion that I missed; from Carlos
|
||||
Silva for Google Summer of Code
|
||||
- dtucker@cvs.openbsd.org 2009/10/06 23:51:49
|
||||
[regress/ssh2putty.sh]
|
||||
Add OpenBSD tag to make syncs easier
|
||||
- (dtucker) [regress/portnum.sh] Import new test.
|
||||
- (dtucker) [configure.ac sftp-client.c] DTOTIF is in fs/ffs/dir.h on at
|
||||
least dragonflybsd.
|
||||
- (dtucker) d_type is not mandated by POSIX, so add fallback code using
|
||||
stat(), needed on at least cygwin.
|
||||
|
||||
20091002
|
||||
- (djm) [Makefile.in] Mention readconf.o in ssh-keysign's make deps.
|
||||
spotted by des AT des.no
|
||||
|
||||
20090926
|
||||
- (djm) [contrib/caldera/openssh.spec contrib/redhat/openssh.spec]
|
||||
[contrib/suse/openssh.spec] Update for release
|
||||
|
@ -208,10 +208,6 @@ are installed.
|
||||
--with-4in6 Check for IPv4 in IPv6 mapped addresses and convert them to
|
||||
real (AF_INET) IPv4 addresses. Works around some quirks on Linux.
|
||||
|
||||
--with-opensc=DIR
|
||||
--with-sectok=DIR allows for OpenSC or sectok smartcard libraries to
|
||||
be used with OpenSSH. See 'README.smartcard' for more details.
|
||||
|
||||
If you need to pass special options to the compiler or linker, you
|
||||
can specify these as environment variables before running ./configure.
|
||||
For example:
|
||||
@ -266,4 +262,4 @@ Please refer to the "reporting bugs" section of the webpage at
|
||||
http://www.openssh.com/
|
||||
|
||||
|
||||
$Id: INSTALL,v 1.84 2007/08/17 12:52:05 dtucker Exp $
|
||||
$Id: INSTALL,v 1.85 2010/02/11 22:34:22 djm Exp $
|
||||
|
@ -6,8 +6,8 @@ filexfer protocol described in:
|
||||
|
||||
http://www.openssh.com/txt/draft-ietf-secsh-filexfer-02.txt
|
||||
|
||||
Features from newer versions of the draft are not supported, unless
|
||||
explicitly implemented as extensions described below.
|
||||
Newer versions of the draft will not be supported, though some features
|
||||
are individually implemented as extensions described below.
|
||||
|
||||
The protocol used by OpenSSH's ssh-agent is described in the file
|
||||
PROTOCOL.agent
|
||||
@ -31,7 +31,14 @@ The method is documented in:
|
||||
|
||||
http://www.openssh.com/txt/draft-miller-secsh-compression-delayed-00.txt
|
||||
|
||||
3. connection: Channel write close extension "eow@openssh.com"
|
||||
3. transport: New public key algorithms "ssh-rsa-cert-v00@openssh.com" and
|
||||
"ssh-dsa-cert-v00@openssh.com"
|
||||
|
||||
OpenSSH introduces two new public key algorithms to support certificate
|
||||
authentication for users and hostkeys. These methods are documented in
|
||||
the file PROTOCOL.certkeys
|
||||
|
||||
4. connection: Channel write close extension "eow@openssh.com"
|
||||
|
||||
The SSH connection protocol (rfc4254) provides the SSH_MSG_CHANNEL_EOF
|
||||
message to allow an endpoint to signal its peer that it will send no
|
||||
@ -70,7 +77,7 @@ message is only sent to OpenSSH peers (identified by banner).
|
||||
Other SSH implementations may be whitelisted to receive this message
|
||||
upon request.
|
||||
|
||||
4. connection: disallow additional sessions extension
|
||||
5. connection: disallow additional sessions extension
|
||||
"no-more-sessions@openssh.com"
|
||||
|
||||
Most SSH connections will only ever request a single session, but a
|
||||
@ -98,7 +105,7 @@ of this message, the no-more-sessions request is only sent to OpenSSH
|
||||
servers (identified by banner). Other SSH implementations may be
|
||||
whitelisted to receive this message upon request.
|
||||
|
||||
5. connection: Tunnel forward extension "tun@openssh.com"
|
||||
6. connection: Tunnel forward extension "tun@openssh.com"
|
||||
|
||||
OpenSSH supports layer 2 and layer 3 tunnelling via the "tun@openssh.com"
|
||||
channel type. This channel type supports forwarding of network packets
|
||||
@ -121,10 +128,10 @@ layer 2 frames or layer 3 packets. It may take one of the following values:
|
||||
SSH_TUNMODE_ETHERNET 2 /* layer 2 frames */
|
||||
|
||||
The "tunnel unit number" specifies the remote interface number, or may
|
||||
be zero to allow the server to automatically chose an interface. A server
|
||||
that is not willing to open a client-specified unit should refuse the
|
||||
request with a SSH_MSG_CHANNEL_OPEN_FAILURE error. On successful open,
|
||||
the server should reply with SSH_MSG_CHANNEL_OPEN_SUCCESS.
|
||||
be 0x7fffffff to allow the server to automatically chose an interface. A
|
||||
server that is not willing to open a client-specified unit should refuse
|
||||
the request with a SSH_MSG_CHANNEL_OPEN_FAILURE error. On successful
|
||||
open, the server should reply with SSH_MSG_CHANNEL_OPEN_SUCCESS.
|
||||
|
||||
Once established the client and server may exchange packet or frames
|
||||
over the tunnel channel by encapsulating them in SSH protocol strings
|
||||
@ -151,7 +158,7 @@ It may be one of:
|
||||
The "packet data" field consists of the IPv4/IPv6 datagram itself
|
||||
without any link layer header.
|
||||
|
||||
The contents of the "data" field for layer 3 packets is:
|
||||
The contents of the "data" field for layer 2 packets is:
|
||||
|
||||
uint32 packet length
|
||||
byte[packet length] frame
|
||||
@ -159,7 +166,7 @@ The contents of the "data" field for layer 3 packets is:
|
||||
The "frame" field contains an IEEE 802.3 Ethernet frame, including
|
||||
header.
|
||||
|
||||
6. sftp: Reversal of arguments to SSH_FXP_SYMLINK
|
||||
7. sftp: Reversal of arguments to SSH_FXP_SYMLINK
|
||||
|
||||
When OpenSSH's sftp-server was implemented, the order of the arguments
|
||||
to the SSH_FXP_SYMLINK method was inadvertently reversed. Unfortunately,
|
||||
@ -172,7 +179,7 @@ SSH_FXP_SYMLINK as follows:
|
||||
string targetpath
|
||||
string linkpath
|
||||
|
||||
7. sftp: Server extension announcement in SSH_FXP_VERSION
|
||||
8. sftp: Server extension announcement in SSH_FXP_VERSION
|
||||
|
||||
OpenSSH's sftp-server lists the extensions it supports using the
|
||||
standard extension announcement mechanism in the SSH_FXP_VERSION server
|
||||
@ -193,7 +200,7 @@ ever changed in an incompatible way. The server MAY advertise the same
|
||||
extension with multiple versions (though this is unlikely). Clients MUST
|
||||
check the version number before attempting to use the extension.
|
||||
|
||||
8. sftp: Extension request "posix-rename@openssh.com"
|
||||
9. sftp: Extension request "posix-rename@openssh.com"
|
||||
|
||||
This operation provides a rename operation with POSIX semantics, which
|
||||
are different to those provided by the standard SSH_FXP_RENAME in
|
||||
@ -210,7 +217,7 @@ rename(oldpath, newpath) and will respond with a SSH_FXP_STATUS message.
|
||||
This extension is advertised in the SSH_FXP_VERSION hello with version
|
||||
"1".
|
||||
|
||||
9. sftp: Extension requests "statvfs@openssh.com" and
|
||||
10. sftp: Extension requests "statvfs@openssh.com" and
|
||||
"fstatvfs@openssh.com"
|
||||
|
||||
These requests correspond to the statvfs and fstatvfs POSIX system
|
||||
@ -251,4 +258,4 @@ The values of the f_flag bitmask are as follows:
|
||||
Both the "statvfs@openssh.com" and "fstatvfs@openssh.com" extensions are
|
||||
advertised in the SSH_FXP_VERSION hello with version "2".
|
||||
|
||||
$OpenBSD: PROTOCOL,v 1.12 2009/02/14 06:35:49 djm Exp $
|
||||
$OpenBSD: PROTOCOL,v 1.15 2010/02/26 20:29:54 djm Exp $
|
||||
|
@ -173,6 +173,15 @@ be added using the following request
|
||||
string key_comment
|
||||
constraint[] key_constraints
|
||||
|
||||
DSA certificates may be added with:
|
||||
byte SSH2_AGENTC_ADD_IDENTITY or
|
||||
SSH2_AGENTC_ADD_ID_CONSTRAINED
|
||||
string "ssh-dss-cert-v00@openssh.com"
|
||||
string certificate
|
||||
mpint dsa_private_key
|
||||
string key_comment
|
||||
constraint[] key_constraints
|
||||
|
||||
RSA keys may be added with this request:
|
||||
|
||||
byte SSH2_AGENTC_ADD_IDENTITY or
|
||||
@ -187,6 +196,19 @@ RSA keys may be added with this request:
|
||||
string key_comment
|
||||
constraint[] key_constraints
|
||||
|
||||
RSA certificates may be added with this request:
|
||||
|
||||
byte SSH2_AGENTC_ADD_IDENTITY or
|
||||
SSH2_AGENTC_ADD_ID_CONSTRAINED
|
||||
string "ssh-rsa-cert-v00@openssh.com"
|
||||
string certificate
|
||||
mpint rsa_d
|
||||
mpint rsa_iqmp
|
||||
mpint rsa_p
|
||||
mpint rsa_q
|
||||
string key_comment
|
||||
constraint[] key_constraints
|
||||
|
||||
Note that the 'rsa_p' and 'rsa_q' parameters are sent in the reverse
|
||||
order to the protocol 1 add keys message. As with the corresponding
|
||||
protocol 1 "add key" request, the private key is overspecified to avoid
|
||||
@ -513,4 +535,4 @@ Locking and unlocking affects both protocol 1 and protocol 2 keys.
|
||||
SSH_AGENT_CONSTRAIN_LIFETIME 1
|
||||
SSH_AGENT_CONSTRAIN_CONFIRM 2
|
||||
|
||||
$OpenBSD: PROTOCOL.agent,v 1.4 2008/07/01 23:12:47 stevesk Exp $
|
||||
$OpenBSD: PROTOCOL.agent,v 1.5 2010/02/26 20:29:54 djm Exp $
|
||||
|
193
crypto/openssh/PROTOCOL.certkeys
Normal file
193
crypto/openssh/PROTOCOL.certkeys
Normal file
@ -0,0 +1,193 @@
|
||||
This document describes a simple public-key certificate authentication
|
||||
system for use by SSH.
|
||||
|
||||
Background
|
||||
----------
|
||||
|
||||
The SSH protocol currently supports a simple public key authentication
|
||||
mechanism. Unlike other public key implementations, SSH eschews the
|
||||
use of X.509 certificates and uses raw keys. This approach has some
|
||||
benefits relating to simplicity of configuration and minimisation
|
||||
of attack surface, but it does not support the important use-cases
|
||||
of centrally managed, passwordless authentication and centrally
|
||||
certified host keys.
|
||||
|
||||
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
|
||||
that have been signed with some other trusted key.
|
||||
|
||||
A sshd server may be configured to allow authentication via certified
|
||||
keys, by extending the existing ~/.ssh/authorized_keys mechanism
|
||||
to allow specification of certification authority keys in addition
|
||||
to raw user keys. The ssh client will support automatic verification
|
||||
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
|
||||
include certification information along with the public key that is used
|
||||
to sign challenges. ssh-keygen performs the CA signing operation.
|
||||
|
||||
Protocol extensions
|
||||
-------------------
|
||||
|
||||
The SSH wire protocol includes several extensibility mechanisms.
|
||||
These modifications shall take advantage of namespaced public key
|
||||
algorithm names to add support for certificate authentication without
|
||||
breaking the protocol - implementations that do not support the
|
||||
extensions will simply ignore them.
|
||||
|
||||
Authentication using the new key formats described below proceeds
|
||||
using the existing SSH "publickey" authentication method described
|
||||
in RFC4252 section 7.
|
||||
|
||||
New public key formats
|
||||
----------------------
|
||||
|
||||
The ssh-rsa-cert-v00@openssh.com and ssh-dss-cert-v00@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.
|
||||
|
||||
#define SSH_CERT_TYPE_USER 1
|
||||
#define SSH_CERT_TYPE_HOST 2
|
||||
|
||||
RSA certificate
|
||||
|
||||
string "ssh-rsa-cert-v00@openssh.com"
|
||||
mpint e
|
||||
mpint n
|
||||
uint32 type
|
||||
string key id
|
||||
string valid principals
|
||||
uint64 valid after
|
||||
uint64 valid before
|
||||
string constraints
|
||||
string nonce
|
||||
string reserved
|
||||
string signature key
|
||||
string signature
|
||||
|
||||
DSA certificate
|
||||
|
||||
string "ssh-dss-cert-v00@openssh.com"
|
||||
mpint p
|
||||
mpint q
|
||||
mpint g
|
||||
mpint y
|
||||
uint32 type
|
||||
string key id
|
||||
string valid principals
|
||||
uint64 valid after
|
||||
uint64 valid before
|
||||
string constraints
|
||||
string nonce
|
||||
string reserved
|
||||
string signature key
|
||||
string signature
|
||||
|
||||
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.
|
||||
|
||||
type specifies whether this certificate is for identification of a user
|
||||
or a host using a SSH_CERT_TYPE_... value.
|
||||
|
||||
key id is a free-form text field that is filled in by the CA at the time
|
||||
of signing; the intention is that the contents of this field are used to
|
||||
identify the identity principal in log messages.
|
||||
|
||||
"valid principals" is a string containing zero or more principals as
|
||||
strings packed inside it. These principals list the names for which this
|
||||
certificate is valid; hostnames for SSH_CERT_TYPE_HOST certificates and
|
||||
usernames for SSH_CERT_TYPE_USER certificates. As a special case, a
|
||||
zero-length "valid principals" field means the certificate is valid for
|
||||
any principal of the specified type. XXX DNS wildcards?
|
||||
|
||||
"valid after" and "valid before" specify a validity period for the
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
The reserved field is current unused and is ignored in this version of
|
||||
the protocol.
|
||||
|
||||
signature key contains the CA key used to sign the certificate.
|
||||
The valid key types for CA keys are ssh-rsa and ssh-dss. "Chained"
|
||||
certificates, where the signature key type is a certificate type itself
|
||||
are NOT supported. Note that it is possible for a RSA certificate key to
|
||||
be signed by a DSS CA key and vice-versa.
|
||||
|
||||
signature is computed over all preceding fields from the initial string
|
||||
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
|
||||
-----------
|
||||
|
||||
The constraints section of the certificate specifies zero or more
|
||||
constraints 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
|
||||
then the validating party should refuse to accept the certificate.
|
||||
|
||||
The supported constraints and the contents and structure of their
|
||||
data fields are:
|
||||
|
||||
Name Format Description
|
||||
-----------------------------------------------------------------------------
|
||||
force-command string Specifies a command that is executed
|
||||
(replacing any the user specified on the
|
||||
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
|
||||
certificates may be presented from any
|
||||
source address.
|
||||
|
||||
$OpenBSD: PROTOCOL.certkeys,v 1.3 2010/03/03 22:50:40 djm Exp $
|
196
crypto/openssh/PROTOCOL.mux
Normal file
196
crypto/openssh/PROTOCOL.mux
Normal file
@ -0,0 +1,196 @@
|
||||
This document describes the multiplexing protocol used by ssh(1)'s
|
||||
ControlMaster connection-sharing.
|
||||
|
||||
Most messages from the client to the server contain a "request id" field.
|
||||
This field is returned in replies as "client request id" to facilitate
|
||||
matching of responses to requests.
|
||||
|
||||
1. Connection setup
|
||||
|
||||
When a multiplexing connection is made to a ssh(1) operating as a
|
||||
ControlMaster from a ssh(1) in multiplex slave mode, the first
|
||||
action of each is to exchange hello messages:
|
||||
|
||||
uint32 MUX_MSG_HELLO
|
||||
uint32 protocol version
|
||||
string extension name [optional]
|
||||
string extension value [optional]
|
||||
...
|
||||
|
||||
The current version of the mux protocol is 4. A slave should refuse
|
||||
to connect to a master that speaks an unsupported protocol version.
|
||||
Following the version identifier are zero or more extensions
|
||||
represented as a name/value pair. No extensions are currently
|
||||
defined.
|
||||
|
||||
2. Opening sessions
|
||||
|
||||
To open a new multiplexed session, a client may send the following
|
||||
request:
|
||||
|
||||
uint32 MUX_C_MSG_NEW_SESSION
|
||||
uint32 request id
|
||||
string reserved
|
||||
bool want tty flag
|
||||
bool want X11 forwarding flag
|
||||
bool want agent flag
|
||||
bool subsystem flag
|
||||
uint32 escape char
|
||||
string terminal type
|
||||
string command
|
||||
string environment string 0 [optional]
|
||||
...
|
||||
|
||||
To disable the use of an escape character, "escape char" may be set
|
||||
to 0xffffffff. "terminal type" is generally set to the value of
|
||||
$TERM. zero or more environment strings may follow the command.
|
||||
|
||||
The client then sends its standard input, output and error file
|
||||
descriptors (in that order) using Unix domain socket control messages.
|
||||
|
||||
The contents of "reserved" are currently ignored.
|
||||
|
||||
If successful, the server will reply with MUX_S_SESSION_OPENED
|
||||
|
||||
uint32 MUX_S_SESSION_OPENED
|
||||
uint32 client request id
|
||||
uint32 session id
|
||||
|
||||
Otherwise it will reply with an error: MUX_S_PERMISSION_DENIED or
|
||||
MUX_S_FAILURE.
|
||||
|
||||
Once the server has received the fds, it will respond with MUX_S_OK
|
||||
indicating that the session is up. The client now waits for the
|
||||
session to end. When it does, the server will send an exit status
|
||||
message:
|
||||
|
||||
uint32 MUX_S_EXIT_MESSAGE
|
||||
uint32 session id
|
||||
uint32 exit value
|
||||
|
||||
The client should exit with this value to mimic the behaviour of a
|
||||
non-multiplexed ssh(1) connection. Two additional cases that the
|
||||
client must cope with are it receiving a signal itself and the
|
||||
server disconnecting without sending an exit message.
|
||||
|
||||
3. Health checks
|
||||
|
||||
The client may request a health check/PID report from a server:
|
||||
|
||||
uint32 MUX_C_ALIVE_CHECK
|
||||
uint32 request id
|
||||
|
||||
The server replies with:
|
||||
|
||||
uint32 MUX_S_ALIVE
|
||||
uint32 client request id
|
||||
uint32 server pid
|
||||
|
||||
4. Remotely terminating a master
|
||||
|
||||
A client may request that a master terminate immediately:
|
||||
|
||||
uint32 MUX_C_TERMINATE
|
||||
uint32 request id
|
||||
|
||||
The server will reply with one of MUX_S_OK or MUX_S_PERMISSION_DENIED.
|
||||
|
||||
5. Requesting establishment of port forwards
|
||||
|
||||
A client may request the master to establish a port forward:
|
||||
|
||||
uint32 MUX_C_OPEN_FORWARD
|
||||
uint32 request id
|
||||
uint32 forwarding type
|
||||
string listen host
|
||||
string listen port
|
||||
string connect host
|
||||
string connect port
|
||||
|
||||
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.
|
||||
|
||||
5. Requesting closure of port forwards
|
||||
|
||||
A client may request the master to establish a port forward:
|
||||
|
||||
uint32 MUX_C_OPEN_FORWARD
|
||||
uint32 request id
|
||||
uint32 forwarding type
|
||||
string listen host
|
||||
string listen port
|
||||
string connect host
|
||||
string connect port
|
||||
|
||||
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.
|
||||
|
||||
6. Requesting stdio forwarding
|
||||
|
||||
A client may request the master to establish a stdio forwarding:
|
||||
|
||||
uint32 MUX_C_NEW_STDIO_FWD
|
||||
uint32 request id
|
||||
string reserved
|
||||
string connect host
|
||||
string connect port
|
||||
|
||||
The client then sends its standard input and output file descriptors
|
||||
(in that order) using Unix domain socket control messages.
|
||||
|
||||
The contents of "reserved" are currently ignored.
|
||||
|
||||
A server may reply with a MUX_S_SESSION_OPEED, a MUX_S_PERMISSION_DENIED
|
||||
or a MUX_S_FAILURE.
|
||||
|
||||
7. Status messages
|
||||
|
||||
The MUX_S_OK message is empty:
|
||||
|
||||
uint32 MUX_S_OK
|
||||
uint32 client request id
|
||||
|
||||
The MUX_S_PERMISSION_DENIED and MUX_S_FAILURE include a reason:
|
||||
|
||||
uint32 MUX_S_PERMISSION_DENIED
|
||||
uint32 client request id
|
||||
string reason
|
||||
|
||||
uint32 MUX_S_FAILURE
|
||||
uint32 client request id
|
||||
string reason
|
||||
|
||||
7. Protocol numbers
|
||||
|
||||
#define MUX_MSG_HELLO 0x00000001
|
||||
#define MUX_C_NEW_SESSION 0x10000002
|
||||
#define MUX_C_ALIVE_CHECK 0x10000004
|
||||
#define MUX_C_TERMINATE 0x10000005
|
||||
#define MUX_C_OPEN_FORWARD 0x10000006
|
||||
#define MUX_C_CLOSE_FORWARD 0x10000007
|
||||
#define MUX_S_OK 0x80000001
|
||||
#define MUX_S_PERMISSION_DENIED 0x80000002
|
||||
#define MUX_S_FAILURE 0x80000003
|
||||
#define MUX_S_EXIT_MESSAGE 0x80000004
|
||||
#define MUX_S_ALIVE 0x80000005
|
||||
#define MUX_S_SESSION_OPENED 0x80000006
|
||||
|
||||
#define MUX_FWD_LOCAL 1
|
||||
#define MUX_FWD_REMOTE 2
|
||||
#define MUX_FWD_DYNAMIC 3
|
||||
|
||||
XXX TODO
|
||||
XXX extended status (e.g. report open channels / forwards)
|
||||
XXX graceful close (delete listening socket, but keep existing sessions active)
|
||||
XXX lock (maybe)
|
||||
XXX watch in/out traffic (pre/post crypto)
|
||||
XXX inject packet (what about replies)
|
||||
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 $
|
@ -1,4 +1,4 @@
|
||||
See http://www.openssh.com/txt/release-5.3 for the release notes.
|
||||
See http://www.openssh.com/txt/release-5.4 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.70.4.1 2009/09/26 04:11:47 djm Exp $
|
||||
$Id: README,v 1.72 2010/03/07 22:41:02 djm Exp $
|
||||
|
@ -1,93 +0,0 @@
|
||||
How to use smartcards with OpenSSH?
|
||||
|
||||
OpenSSH contains experimental support for authentication using
|
||||
Cyberflex smartcards and TODOS card readers, in addition to the cards
|
||||
with PKCS#15 structure supported by OpenSC. To enable this you
|
||||
need to:
|
||||
|
||||
Using libsectok:
|
||||
|
||||
(1) enable sectok support in OpenSSH:
|
||||
|
||||
$ ./configure --with-sectok
|
||||
|
||||
(2) If you have used a previous version of ssh with your card, you
|
||||
must remove the old applet and keys.
|
||||
|
||||
$ sectok
|
||||
sectok> login -d
|
||||
sectok> junload Ssh.bin
|
||||
sectok> delete 0012
|
||||
sectok> delete sh
|
||||
sectok> quit
|
||||
|
||||
(3) load the Java Cardlet to the Cyberflex card and set card passphrase:
|
||||
|
||||
$ sectok
|
||||
sectok> login -d
|
||||
sectok> jload /usr/libdata/ssh/Ssh.bin
|
||||
sectok> setpass
|
||||
Enter new AUT0 passphrase:
|
||||
Re-enter passphrase:
|
||||
sectok> quit
|
||||
|
||||
Do not forget the passphrase. There is no way to
|
||||
recover if you do.
|
||||
|
||||
IMPORTANT WARNING: If you attempt to login with the
|
||||
wrong passphrase three times in a row, you will
|
||||
destroy your card.
|
||||
|
||||
(4) load a RSA key to the card:
|
||||
|
||||
$ ssh-keygen -f /path/to/rsakey -U 1
|
||||
(where 1 is the reader number, you can also try 0)
|
||||
|
||||
In spite of the name, this does not generate a key.
|
||||
It just loads an already existing key on to the card.
|
||||
|
||||
(5) Optional: If you don't want to use a card passphrase, change the
|
||||
acl on the private key file:
|
||||
|
||||
$ sectok
|
||||
sectok> login -d
|
||||
sectok> acl 0012 world: w
|
||||
world: w
|
||||
AUT0: w inval
|
||||
sectok> quit
|
||||
|
||||
If you do this, anyone who has access to your card
|
||||
can assume your identity. This is not recommended.
|
||||
|
||||
|
||||
Using OpenSC:
|
||||
|
||||
(1) install OpenSC:
|
||||
|
||||
Sources and instructions are available from
|
||||
http://www.opensc.org/
|
||||
|
||||
(2) enable OpenSC support in OpenSSH:
|
||||
|
||||
$ ./configure --with-opensc[=/path/to/opensc] [options]
|
||||
|
||||
(3) load a RSA key to the card:
|
||||
|
||||
Not supported yet.
|
||||
|
||||
|
||||
Common operations:
|
||||
|
||||
(1) tell the ssh client to use the card reader:
|
||||
|
||||
$ ssh -I 1 otherhost
|
||||
|
||||
(2) or tell the agent (don't forget to restart) to use the smartcard:
|
||||
|
||||
$ ssh-add -s 1
|
||||
|
||||
|
||||
-markus,
|
||||
Tue Jul 17 23:54:51 CEST 2001
|
||||
|
||||
$OpenBSD: README.smartcard,v 1.9 2003/11/21 11:57:02 djm Exp $
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: addrmatch.c,v 1.4 2008/12/10 03:55:20 stevesk Exp $ */
|
||||
/* $OpenBSD: addrmatch.c,v 1.5 2010/02/26 20:29:54 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004-2008 Damien Miller <djm@mindrot.org>
|
||||
@ -126,6 +126,8 @@ addr_netmask(int af, u_int l, struct xaddr *n)
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
n->af = AF_INET;
|
||||
if (l == 0)
|
||||
return 0;
|
||||
n->v4.s_addr = htonl((0xffffffff << (32 - l)) & 0xffffffff);
|
||||
return 0;
|
||||
case AF_INET6:
|
||||
@ -422,3 +424,77 @@ addr_match_list(const char *addr, const char *_list)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Match "addr" against list CIDR list "_list". Lexical wildcards and
|
||||
* negation are not supported. If "addr" == NULL, will verify structure
|
||||
* of "_list".
|
||||
*
|
||||
* Returns 1 on match found (never returned when addr == NULL).
|
||||
* Returns 0 on if no match found, or no errors found when addr == NULL.
|
||||
* Returns -1 on error
|
||||
*/
|
||||
int
|
||||
addr_match_cidr_list(const char *addr, const char *_list)
|
||||
{
|
||||
char *list, *cp, *o;
|
||||
struct xaddr try_addr, match_addr;
|
||||
u_int masklen;
|
||||
int ret = 0, r;
|
||||
|
||||
if (addr != NULL && addr_pton(addr, &try_addr) != 0) {
|
||||
debug2("%s: couldn't parse address %.100s", __func__, addr);
|
||||
return 0;
|
||||
}
|
||||
if ((o = list = strdup(_list)) == NULL)
|
||||
return -1;
|
||||
while ((cp = strsep(&list, ",")) != NULL) {
|
||||
if (*cp == '\0') {
|
||||
error("%s: empty entry in list \"%.100s\"",
|
||||
__func__, o);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* NB. This function is called in pre-auth with untrusted data,
|
||||
* so be extra paranoid about junk reaching getaddrino (via
|
||||
* addr_pton_cidr).
|
||||
*/
|
||||
|
||||
/* Stop junk from reaching getaddrinfo. +3 is for masklen */
|
||||
if (strlen(cp) > INET6_ADDRSTRLEN + 3) {
|
||||
error("%s: list entry \"%.100s\" too long",
|
||||
__func__, cp);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
#define VALID_CIDR_CHARS "0123456789abcdefABCDEF.:/"
|
||||
if (strspn(cp, VALID_CIDR_CHARS) != strlen(cp)) {
|
||||
error("%s: list entry \"%.100s\" contains invalid "
|
||||
"characters", __func__, cp);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
/* Prefer CIDR address matching */
|
||||
r = addr_pton_cidr(cp, &match_addr, &masklen);
|
||||
if (r == -1) {
|
||||
error("Invalid network entry \"%.100s\"", cp);
|
||||
ret = -1;
|
||||
break;
|
||||
} else if (r == -2) {
|
||||
error("Inconsistent mask length for "
|
||||
"network \"%.100s\"", cp);
|
||||
ret = -1;
|
||||
break;
|
||||
} else if (r == 0 && addr != NULL) {
|
||||
if (addr_netmatch(&try_addr, &match_addr,
|
||||
masklen) == 0)
|
||||
ret = 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
xfree(o);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -78,6 +78,11 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
|
||||
krb5_error_code problem;
|
||||
krb5_ccache ccache = NULL;
|
||||
int len;
|
||||
char *client, *platform_client;
|
||||
|
||||
/* get platform-specific kerberos client principal name (if it exists) */
|
||||
platform_client = platform_krb5_get_principal_name(authctxt->pw->pw_name);
|
||||
client = platform_client ? platform_client : authctxt->pw->pw_name;
|
||||
|
||||
temporarily_use_uid(authctxt->pw);
|
||||
|
||||
@ -85,7 +90,7 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
|
||||
if (problem)
|
||||
goto out;
|
||||
|
||||
problem = krb5_parse_name(authctxt->krb5_ctx, authctxt->pw->pw_name,
|
||||
problem = krb5_parse_name(authctxt->krb5_ctx, client,
|
||||
&authctxt->krb5_user);
|
||||
if (problem)
|
||||
goto out;
|
||||
@ -141,8 +146,7 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
|
||||
if (problem)
|
||||
goto out;
|
||||
|
||||
if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user,
|
||||
authctxt->pw->pw_name)) {
|
||||
if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, client)) {
|
||||
problem = -1;
|
||||
goto out;
|
||||
}
|
||||
@ -176,6 +180,9 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
|
||||
|
||||
out:
|
||||
restore_uid();
|
||||
|
||||
if (platform_client != NULL)
|
||||
xfree(platform_client);
|
||||
|
||||
if (problem) {
|
||||
if (ccache)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth-options.c,v 1.44 2009/01/22 10:09:16 djm Exp $ */
|
||||
/* $OpenBSD: auth-options.c,v 1.48 2010/03/07 11:57:13 dtucker Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -44,6 +44,7 @@ int no_agent_forwarding_flag = 0;
|
||||
int no_x11_forwarding_flag = 0;
|
||||
int no_pty_flag = 0;
|
||||
int no_user_rc = 0;
|
||||
int key_is_cert_authority = 0;
|
||||
|
||||
/* "command=" option. */
|
||||
char *forced_command = NULL;
|
||||
@ -64,6 +65,7 @@ auth_clear_options(void)
|
||||
no_pty_flag = 0;
|
||||
no_x11_forwarding_flag = 0;
|
||||
no_user_rc = 0;
|
||||
key_is_cert_authority = 0;
|
||||
while (custom_environment) {
|
||||
struct envstring *ce = custom_environment;
|
||||
custom_environment = ce->next;
|
||||
@ -76,7 +78,6 @@ auth_clear_options(void)
|
||||
}
|
||||
forced_tun_device = -1;
|
||||
channel_clear_permitted_opens();
|
||||
auth_debug_reset();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -96,6 +97,12 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
|
||||
return 1;
|
||||
|
||||
while (*opts && *opts != ' ' && *opts != '\t') {
|
||||
cp = "cert-authority";
|
||||
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
|
||||
key_is_cert_authority = 1;
|
||||
opts += strlen(cp);
|
||||
goto next_option;
|
||||
}
|
||||
cp = "no-port-forwarding";
|
||||
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
|
||||
auth_debug_add("Port forwarding disabled.");
|
||||
@ -356,9 +363,6 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
|
||||
/* Process the next option. */
|
||||
}
|
||||
|
||||
if (!use_privsep)
|
||||
auth_debug_send();
|
||||
|
||||
/* grant access */
|
||||
return 1;
|
||||
|
||||
@ -368,9 +372,158 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
|
||||
auth_debug_add("Bad options in %.100s file, line %lu: %.50s",
|
||||
file, linenum, opts);
|
||||
|
||||
if (!use_privsep)
|
||||
auth_debug_send();
|
||||
|
||||
/* deny access */
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
buffer_init(&data);
|
||||
|
||||
/* Make copy to avoid altering original */
|
||||
buffer_init(&c);
|
||||
buffer_append(&c, buffer_ptr(c_orig), buffer_len(c_orig));
|
||||
|
||||
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");
|
||||
goto out;
|
||||
}
|
||||
buffer_append(&data, data_blob, dlen);
|
||||
debug3("found certificate constraint \"%.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;
|
||||
}
|
||||
if (strlen(command) != clen) {
|
||||
error("force-command constrain contains \\0");
|
||||
goto out;
|
||||
}
|
||||
if (cert_forced_command != NULL) {
|
||||
error("Certificate has multiple "
|
||||
"force-command constraints");
|
||||
xfree(command);
|
||||
goto out;
|
||||
}
|
||||
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 constrain 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 "
|
||||
"(extra data)", name);
|
||||
goto out;
|
||||
}
|
||||
buffer_clear(&data);
|
||||
xfree(name);
|
||||
xfree(data_blob);
|
||||
name = data_blob = NULL;
|
||||
}
|
||||
|
||||
/* successfully parsed all constraints */
|
||||
ret = 0;
|
||||
|
||||
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;
|
||||
no_pty_flag |= cert_no_pty_flag;
|
||||
no_user_rc |= cert_no_user_rc;
|
||||
/* CA-specified forced command supersedes key option */
|
||||
if (cert_forced_command != NULL) {
|
||||
if (forced_command != NULL)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth-options.h,v 1.17 2008/03/26 21:28:14 djm Exp $ */
|
||||
/* $OpenBSD: auth-options.h,v 1.18 2010/02/26 20:29:54 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -30,8 +30,10 @@ extern int no_user_rc;
|
||||
extern char *forced_command;
|
||||
extern struct envstring *custom_environment;
|
||||
extern int forced_tun_device;
|
||||
extern int key_is_cert_authority;
|
||||
|
||||
int auth_parse_options(struct passwd *, char *, char *, u_long);
|
||||
void auth_clear_options(void);
|
||||
int auth_cert_constraints(Buffer *, struct passwd *);
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth-rh-rsa.c,v 1.42 2006/08/03 03:34:41 deraadt Exp $ */
|
||||
/* $OpenBSD: auth-rh-rsa.c,v 1.43 2010/03/04 10:36:03 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -44,6 +44,9 @@ auth_rhosts_rsa_key_allowed(struct passwd *pw, char *cuser, char *chost,
|
||||
{
|
||||
HostStatus host_status;
|
||||
|
||||
if (auth_key_is_revoked(client_host_key))
|
||||
return 0;
|
||||
|
||||
/* Check if we would accept it using rhosts authentication. */
|
||||
if (!auth_rhosts(pw, cuser))
|
||||
return 0;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth-rhosts.c,v 1.43 2008/06/13 14:18:51 dtucker Exp $ */
|
||||
/* $OpenBSD: auth-rhosts.c,v 1.44 2010/03/07 11:57:13 dtucker Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -317,11 +317,5 @@ int
|
||||
auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
|
||||
const char *ipaddr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
auth_debug_reset();
|
||||
ret = auth_rhosts2_raw(pw, client_user, hostname, ipaddr);
|
||||
if (!use_privsep)
|
||||
auth_debug_send();
|
||||
return ret;
|
||||
return auth_rhosts2_raw(pw, client_user, hostname, ipaddr);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth-rsa.c,v 1.73 2008/07/02 12:03:51 dtucker Exp $ */
|
||||
/* $OpenBSD: auth-rsa.c,v 1.74 2010/03/04 10:36:03 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -94,6 +94,9 @@ auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
|
||||
MD5_CTX md;
|
||||
int len;
|
||||
|
||||
if (auth_key_is_revoked(key))
|
||||
return 0;
|
||||
|
||||
/* don't allow short keys */
|
||||
if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
|
||||
error("auth_rsa_verify_response: RSA modulus too small: %d < minimum %d bits",
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth.c,v 1.80 2008/11/04 07:58:09 djm Exp $ */
|
||||
/* $OpenBSD: auth.c,v 1.86 2010/03/05 02:58:11 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -70,6 +70,7 @@ __RCSID("$FreeBSD$");
|
||||
#ifdef GSSAPI
|
||||
#include "ssh-gss.h"
|
||||
#endif
|
||||
#include "authfile.h"
|
||||
#include "monitor_wrap.h"
|
||||
|
||||
/* import */
|
||||
@ -96,7 +97,6 @@ allowed_user(struct passwd * pw)
|
||||
{
|
||||
struct stat st;
|
||||
const char *hostname = NULL, *ipaddr = NULL, *passwd = NULL;
|
||||
char *shell;
|
||||
u_int i;
|
||||
#ifdef USE_SHADOW
|
||||
struct spwd *spw = NULL;
|
||||
@ -154,22 +154,28 @@ allowed_user(struct passwd * pw)
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the shell from the password data. An empty shell field is
|
||||
* legal, and means /bin/sh.
|
||||
* Deny if shell does not exist or is not executable unless we
|
||||
* are chrooting.
|
||||
*/
|
||||
shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
|
||||
if (options.chroot_directory == NULL ||
|
||||
strcasecmp(options.chroot_directory, "none") == 0) {
|
||||
char *shell = xstrdup((pw->pw_shell[0] == '\0') ?
|
||||
_PATH_BSHELL : pw->pw_shell); /* empty = /bin/sh */
|
||||
|
||||
/* deny if shell does not exists or is not executable */
|
||||
if (stat(shell, &st) != 0) {
|
||||
logit("User %.100s not allowed because shell %.100s does not exist",
|
||||
pw->pw_name, shell);
|
||||
return 0;
|
||||
}
|
||||
if (S_ISREG(st.st_mode) == 0 ||
|
||||
(st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
|
||||
logit("User %.100s not allowed because shell %.100s is not executable",
|
||||
pw->pw_name, shell);
|
||||
return 0;
|
||||
if (stat(shell, &st) != 0) {
|
||||
logit("User %.100s not allowed because shell %.100s "
|
||||
"does not exist", pw->pw_name, shell);
|
||||
xfree(shell);
|
||||
return 0;
|
||||
}
|
||||
if (S_ISREG(st.st_mode) == 0 ||
|
||||
(st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
|
||||
logit("User %.100s not allowed because shell %.100s "
|
||||
"is not executable", pw->pw_name, shell);
|
||||
xfree(shell);
|
||||
return 0;
|
||||
}
|
||||
xfree(shell);
|
||||
}
|
||||
|
||||
if (options.num_deny_users > 0 || options.num_allow_users > 0 ||
|
||||
@ -456,7 +462,7 @@ secure_filename(FILE *f, const char *file, struct passwd *pw,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If are passed the homedir then we can stop */
|
||||
/* If are past the homedir then we can stop */
|
||||
if (comparehome && strcmp(homedir, buf) == 0) {
|
||||
debug3("secure_filename: terminating check at '%s'",
|
||||
buf);
|
||||
@ -484,8 +490,12 @@ auth_openkeyfile(const char *file, struct passwd *pw, int strict_modes)
|
||||
* Open the file containing the authorized keys
|
||||
* Fail quietly if file does not exist
|
||||
*/
|
||||
if ((fd = open(file, O_RDONLY|O_NONBLOCK)) == -1)
|
||||
if ((fd = open(file, O_RDONLY|O_NONBLOCK)) == -1) {
|
||||
if (errno != ENOENT)
|
||||
debug("Could not open keyfile '%s': %s", file,
|
||||
strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fstat(fd, &st) < 0) {
|
||||
close(fd);
|
||||
@ -526,7 +536,28 @@ getpwnamallow(const char *user)
|
||||
parse_server_match_config(&options, user,
|
||||
get_canonical_hostname(options.use_dns), get_remote_ipaddr());
|
||||
|
||||
#if defined(_AIX) && defined(HAVE_SETAUTHDB)
|
||||
aix_setauthdb(user);
|
||||
#endif
|
||||
|
||||
pw = getpwnam(user);
|
||||
|
||||
#if defined(_AIX) && defined(HAVE_SETAUTHDB)
|
||||
aix_restoreauthdb();
|
||||
#endif
|
||||
#ifdef HAVE_CYGWIN
|
||||
/*
|
||||
* Windows usernames are case-insensitive. To avoid later problems
|
||||
* when trying to match the username, the user is only allowed to
|
||||
* login if the username is given in the same case as stored in the
|
||||
* user database.
|
||||
*/
|
||||
if (pw != NULL && strcmp(user, pw->pw_name) != 0) {
|
||||
logit("Login name %.100s does not match stored username %.100s",
|
||||
user, pw->pw_name);
|
||||
pw = NULL;
|
||||
}
|
||||
#endif
|
||||
if (pw == NULL) {
|
||||
logit("Invalid user %.100s from %.100s",
|
||||
user, get_remote_ipaddr());
|
||||
@ -561,6 +592,35 @@ getpwnamallow(const char *user)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Returns 1 if key is revoked by revoked_keys_file, 0 otherwise */
|
||||
int
|
||||
auth_key_is_revoked(Key *key)
|
||||
{
|
||||
char *key_fp;
|
||||
|
||||
if (options.revoked_keys_file == NULL)
|
||||
return 0;
|
||||
|
||||
switch (key_in_file(key, options.revoked_keys_file, 0)) {
|
||||
case 0:
|
||||
/* key not revoked */
|
||||
return 0;
|
||||
case -1:
|
||||
/* Error opening revoked_keys_file: refuse all keys */
|
||||
error("Revoked keys file is unreadable: refusing public key "
|
||||
"authentication");
|
||||
return 1;
|
||||
case 1:
|
||||
/* Key revoked */
|
||||
key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
|
||||
error("WARNING: authentication attempt with a revoked "
|
||||
"%s key %s ", key_type(key), key_fp);
|
||||
xfree(key_fp);
|
||||
return 1;
|
||||
}
|
||||
fatal("key_in_file returned junk");
|
||||
}
|
||||
|
||||
void
|
||||
auth_debug_add(const char *fmt,...)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth.h,v 1.62 2008/11/04 08:22:12 djm Exp $ */
|
||||
/* $OpenBSD: auth.h,v 1.65 2010/03/04 10:36:03 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
@ -171,6 +171,7 @@ char *authorized_keys_file(struct passwd *);
|
||||
char *authorized_keys_file2(struct passwd *);
|
||||
|
||||
FILE *auth_openkeyfile(const char *, struct passwd *, int);
|
||||
int auth_key_is_revoked(Key *);
|
||||
|
||||
HostStatus
|
||||
check_key_in_hostfiles(struct passwd *, Key *, const char *,
|
||||
@ -178,7 +179,8 @@ check_key_in_hostfiles(struct passwd *, Key *, const char *,
|
||||
|
||||
/* hostkey handling */
|
||||
Key *get_hostkey_by_index(int);
|
||||
Key *get_hostkey_by_type(int);
|
||||
Key *get_hostkey_public_by_type(int);
|
||||
Key *get_hostkey_private_by_type(int);
|
||||
int get_hostkey_index(Key *);
|
||||
int ssh1_session_key(BIGNUM *);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth2-hostbased.c,v 1.12 2008/07/17 08:51:07 djm Exp $ */
|
||||
/* $OpenBSD: auth2-hostbased.c,v 1.13 2010/03/04 10:36:03 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -145,6 +145,9 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
|
||||
HostStatus host_status;
|
||||
int len;
|
||||
|
||||
if (auth_key_is_revoked(key))
|
||||
return 0;
|
||||
|
||||
resolvedname = get_canonical_hostname(options.use_dns);
|
||||
ipaddr = get_remote_ipaddr();
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth2-pubkey.c,v 1.19 2008/07/03 21:46:58 otto Exp $ */
|
||||
/* $OpenBSD: auth2-pubkey.c,v 1.21 2010/03/04 10:36:03 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -32,6 +32,8 @@
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "xmalloc.h"
|
||||
@ -54,6 +56,7 @@
|
||||
#endif
|
||||
#include "monitor_wrap.h"
|
||||
#include "misc.h"
|
||||
#include "authfile.h"
|
||||
|
||||
/* import */
|
||||
extern ServerOptions options;
|
||||
@ -178,6 +181,7 @@ static int
|
||||
user_key_allowed2(struct passwd *pw, Key *key, char *file)
|
||||
{
|
||||
char line[SSH_MAX_PUBKEY_BYTES];
|
||||
const char *reason;
|
||||
int found_key = 0;
|
||||
FILE *f;
|
||||
u_long linenum = 0;
|
||||
@ -196,11 +200,13 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
|
||||
}
|
||||
|
||||
found_key = 0;
|
||||
found = key_new(key->type);
|
||||
found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
|
||||
|
||||
while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
|
||||
char *cp, *key_options = NULL;
|
||||
|
||||
auth_clear_options();
|
||||
|
||||
/* Skip leading whitespace, empty and comment lines. */
|
||||
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
|
||||
;
|
||||
@ -227,8 +233,32 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (key_equal(found, key) &&
|
||||
auth_parse_options(pw, key_options, file, linenum) == 1) {
|
||||
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_equal(found, key->cert->signature_key))
|
||||
continue;
|
||||
debug("matching CA found: file %s, line %lu",
|
||||
file, linenum);
|
||||
fp = key_fingerprint(found, SSH_FP_MD5,
|
||||
SSH_FP_HEX);
|
||||
verbose("Found matching %s CA: %s",
|
||||
key_type(found), fp);
|
||||
xfree(fp);
|
||||
if (key_cert_check_authority(key, 0, 0, pw->pw_name,
|
||||
&reason) != 0) {
|
||||
error("%s", reason);
|
||||
auth_debug_add("%s", reason);
|
||||
continue;
|
||||
}
|
||||
if (auth_cert_constraints(&key->cert->constraints,
|
||||
pw) != 0)
|
||||
continue;
|
||||
found_key = 1;
|
||||
break;
|
||||
} else if (!key_is_cert_authority && key_equal(found, key)) {
|
||||
found_key = 1;
|
||||
debug("matching key found: file %s, line %lu",
|
||||
file, linenum);
|
||||
@ -247,6 +277,47 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
|
||||
return found_key;
|
||||
}
|
||||
|
||||
/* Authenticate a certificate key against TrustedUserCAKeys */
|
||||
static int
|
||||
user_cert_trusted_ca(struct passwd *pw, Key *key)
|
||||
{
|
||||
char *key_fp, *ca_fp;
|
||||
const char *reason;
|
||||
int ret = 0;
|
||||
|
||||
if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL)
|
||||
return 0;
|
||||
|
||||
key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
|
||||
ca_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
|
||||
|
||||
if (key_in_file(key->cert->signature_key,
|
||||
options.trusted_user_ca_keys, 1) != 1) {
|
||||
debug2("%s: CA %s %s is not listed in %s", __func__,
|
||||
key_type(key->cert->signature_key), ca_fp,
|
||||
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 (auth_cert_constraints(&key->cert->constraints, pw) != 0)
|
||||
goto out;
|
||||
|
||||
verbose("%s certificate %s allowed by trusted %s key %s",
|
||||
key_type(key), key_fp, key_type(key->cert->signature_key), ca_fp);
|
||||
ret = 1;
|
||||
|
||||
out:
|
||||
if (key_fp != NULL)
|
||||
xfree(key_fp);
|
||||
if (ca_fp != NULL)
|
||||
xfree(ca_fp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* check whether given key is in .ssh/authorized_keys* */
|
||||
int
|
||||
user_key_allowed(struct passwd *pw, Key *key)
|
||||
@ -254,6 +325,15 @@ user_key_allowed(struct passwd *pw, Key *key)
|
||||
int success;
|
||||
char *file;
|
||||
|
||||
if (auth_key_is_revoked(key))
|
||||
return 0;
|
||||
if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key))
|
||||
return 0;
|
||||
|
||||
success = user_cert_trusted_ca(pw, key);
|
||||
if (success)
|
||||
return success;
|
||||
|
||||
file = authorized_keys_file(pw);
|
||||
success = user_key_allowed2(pw, key, file);
|
||||
xfree(file);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: authfd.c,v 1.80 2006/08/03 03:34:41 deraadt Exp $ */
|
||||
/* $OpenBSD: authfd.c,v 1.82 2010/02/26 20:29:54 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -483,6 +483,16 @@ 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:
|
||||
if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)
|
||||
fatal("%s: no cert/certblob", __func__);
|
||||
buffer_put_string(b, buffer_ptr(&key->cert->certblob),
|
||||
buffer_len(&key->cert->certblob));
|
||||
buffer_put_bignum2(b, key->rsa->d);
|
||||
buffer_put_bignum2(b, key->rsa->iqmp);
|
||||
buffer_put_bignum2(b, key->rsa->p);
|
||||
buffer_put_bignum2(b, key->rsa->q);
|
||||
break;
|
||||
case KEY_DSA:
|
||||
buffer_put_bignum2(b, key->dsa->p);
|
||||
buffer_put_bignum2(b, key->dsa->q);
|
||||
@ -490,6 +500,13 @@ 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:
|
||||
if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)
|
||||
fatal("%s: no cert/certblob", __func__);
|
||||
buffer_put_string(b, buffer_ptr(&key->cert->certblob),
|
||||
buffer_len(&key->cert->certblob));
|
||||
buffer_put_bignum2(b, key->dsa->priv_key);
|
||||
break;
|
||||
}
|
||||
buffer_put_cstring(b, comment);
|
||||
}
|
||||
@ -517,7 +534,9 @@ ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key,
|
||||
ssh_encode_identity_rsa1(&msg, key->rsa, comment);
|
||||
break;
|
||||
case KEY_RSA:
|
||||
case KEY_RSA_CERT:
|
||||
case KEY_DSA:
|
||||
case KEY_DSA_CERT:
|
||||
type = constrained ?
|
||||
SSH2_AGENTC_ADD_ID_CONSTRAINED :
|
||||
SSH2_AGENTC_ADD_IDENTITY;
|
||||
@ -545,12 +564,6 @@ ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key,
|
||||
return decode_reply(type);
|
||||
}
|
||||
|
||||
int
|
||||
ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
|
||||
{
|
||||
return ssh_add_identity_constrained(auth, key, comment, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes an identity from the authentication server. This call is not
|
||||
* meant to be used by normal applications.
|
||||
@ -571,7 +584,8 @@ ssh_remove_identity(AuthenticationConnection *auth, Key *key)
|
||||
buffer_put_int(&msg, BN_num_bits(key->rsa->n));
|
||||
buffer_put_bignum(&msg, key->rsa->e);
|
||||
buffer_put_bignum(&msg, key->rsa->n);
|
||||
} else if (key->type == KEY_DSA || key->type == KEY_RSA) {
|
||||
} else if (key_type_plain(key->type) == KEY_DSA ||
|
||||
key_type_plain(key->type) == KEY_RSA) {
|
||||
key_to_blob(key, &blob, &blen);
|
||||
buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY);
|
||||
buffer_put_string(&msg, blob, blen);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: authfd.h,v 1.36 2006/08/03 03:34:41 deraadt Exp $ */
|
||||
/* $OpenBSD: authfd.h,v 1.37 2009/08/27 17:44:52 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -75,7 +75,6 @@ void ssh_close_authentication_connection(AuthenticationConnection *);
|
||||
int ssh_get_num_identities(AuthenticationConnection *, int);
|
||||
Key *ssh_get_first_identity(AuthenticationConnection *, char **, int);
|
||||
Key *ssh_get_next_identity(AuthenticationConnection *, char **, int);
|
||||
int ssh_add_identity(AuthenticationConnection *, Key *, const char *);
|
||||
int ssh_add_identity_constrained(AuthenticationConnection *, Key *,
|
||||
const char *, u_int, u_int);
|
||||
int ssh_remove_identity(AuthenticationConnection *, Key *);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: authfile.c,v 1.76 2006/08/03 03:34:41 deraadt Exp $ */
|
||||
/* $OpenBSD: authfile.c,v 1.80 2010/03/04 10:36:03 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -47,6 +47,9 @@
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
|
||||
/* compatibility with old or broken OpenSSL versions */
|
||||
#include "openbsd-compat/openssl-compat.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
@ -184,7 +187,11 @@ key_save_private_pem(Key *key, const char *filename, const char *_passphrase,
|
||||
int success = 0;
|
||||
int len = strlen(_passphrase);
|
||||
u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x00907000L)
|
||||
const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL;
|
||||
#else
|
||||
const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
|
||||
#endif
|
||||
|
||||
if (len > 0 && len <= 4) {
|
||||
error("passphrase too short: have %d bytes, need > 4", len);
|
||||
@ -552,8 +559,13 @@ key_load_private_type(int type, const char *filename, const char *passphrase,
|
||||
int fd;
|
||||
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0)
|
||||
if (fd < 0) {
|
||||
debug("could not open key file '%s': %s", filename,
|
||||
strerror(errno));
|
||||
if (perm_ok != NULL)
|
||||
*perm_ok = 0;
|
||||
return NULL;
|
||||
}
|
||||
if (!key_perm_ok(fd, filename)) {
|
||||
if (perm_ok != NULL)
|
||||
*perm_ok = 0;
|
||||
@ -588,8 +600,11 @@ key_load_private(const char *filename, const char *passphrase,
|
||||
int fd;
|
||||
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0)
|
||||
if (fd < 0) {
|
||||
debug("could not open key file '%s': %s", filename,
|
||||
strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
if (!key_perm_ok(fd, filename)) {
|
||||
error("bad permissions: ignore key: %s", filename);
|
||||
close(fd);
|
||||
@ -677,3 +692,65 @@ key_load_public(const char *filename, char **commentp)
|
||||
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.
|
||||
* If strict_type is set then the key type must match exactly,
|
||||
* otherwise a comparison that ignores certficiate data is performed.
|
||||
*/
|
||||
int
|
||||
key_in_file(Key *key, const char *filename, int strict_type)
|
||||
{
|
||||
FILE *f;
|
||||
char line[SSH_MAX_PUBKEY_BYTES];
|
||||
char *cp;
|
||||
u_long linenum = 0;
|
||||
int ret = 0;
|
||||
Key *pub;
|
||||
int (*key_compare)(const Key *, const Key *) = strict_type ?
|
||||
key_equal : key_equal_public;
|
||||
|
||||
if ((f = fopen(filename, "r")) == NULL) {
|
||||
if (errno == ENOENT) {
|
||||
debug("%s: keyfile \"%s\" missing", __func__, filename);
|
||||
return 0;
|
||||
} else {
|
||||
error("%s: could not open keyfile \"%s\": %s", __func__,
|
||||
filename, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
while (read_keyfile_line(f, filename, line, sizeof(line),
|
||||
&linenum) != -1) {
|
||||
cp = line;
|
||||
|
||||
/* Skip leading whitespace. */
|
||||
for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
|
||||
;
|
||||
|
||||
/* Skip comments and empty lines */
|
||||
switch (*cp) {
|
||||
case '#':
|
||||
case '\n':
|
||||
case '\0':
|
||||
continue;
|
||||
}
|
||||
|
||||
pub = key_new(KEY_UNSPEC);
|
||||
if (key_read(pub, &cp) != 1) {
|
||||
key_free(pub);
|
||||
continue;
|
||||
}
|
||||
if (key_compare(key, pub)) {
|
||||
ret = 1;
|
||||
key_free(pub);
|
||||
break;
|
||||
}
|
||||
key_free(pub);
|
||||
}
|
||||
fclose(f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: authfile.h,v 1.13 2006/04/25 08:02:27 dtucker Exp $ */
|
||||
/* $OpenBSD: authfile.h,v 1.14 2010/03/04 10:36:03 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -22,5 +22,6 @@ Key *key_load_private(const char *, const char *, char **);
|
||||
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 *);
|
||||
int key_in_file(Key *, const char *, int);
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: bufaux.c,v 1.46 2008/06/10 23:21:34 dtucker Exp $ */
|
||||
/* $OpenBSD: bufaux.c,v 1.48 2010/02/02 22:49:34 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -166,7 +166,10 @@ buffer_get_string_ret(Buffer *buffer, u_int *length_ptr)
|
||||
u_int len;
|
||||
|
||||
/* Get the length. */
|
||||
len = buffer_get_int(buffer);
|
||||
if (buffer_get_int_ret(&len, buffer) != 0) {
|
||||
error("buffer_get_string_ret: cannot extract length");
|
||||
return (NULL);
|
||||
}
|
||||
if (len > 256 * 1024) {
|
||||
error("buffer_get_string_ret: bad string length %u", len);
|
||||
return (NULL);
|
||||
@ -198,14 +201,17 @@ buffer_get_string(Buffer *buffer, u_int *length_ptr)
|
||||
}
|
||||
|
||||
void *
|
||||
buffer_get_string_ptr(Buffer *buffer, u_int *length_ptr)
|
||||
buffer_get_string_ptr_ret(Buffer *buffer, u_int *length_ptr)
|
||||
{
|
||||
void *ptr;
|
||||
u_int len;
|
||||
|
||||
len = buffer_get_int(buffer);
|
||||
if (len > 256 * 1024)
|
||||
fatal("buffer_get_string_ptr: bad string length %u", len);
|
||||
if (buffer_get_int_ret(&len, buffer) != 0)
|
||||
return NULL;
|
||||
if (len > 256 * 1024) {
|
||||
error("buffer_get_string_ptr: bad string length %u", len);
|
||||
return NULL;
|
||||
}
|
||||
ptr = buffer_ptr(buffer);
|
||||
buffer_consume(buffer, len);
|
||||
if (length_ptr)
|
||||
@ -213,6 +219,16 @@ buffer_get_string_ptr(Buffer *buffer, u_int *length_ptr)
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
void *
|
||||
buffer_get_string_ptr(Buffer *buffer, u_int *length_ptr)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
if ((ret = buffer_get_string_ptr_ret(buffer, length_ptr)) == NULL)
|
||||
fatal("buffer_get_string_ptr: buffer error");
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Stores and arbitrary binary string in the buffer.
|
||||
*/
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: buffer.c,v 1.31 2006/08/03 03:34:41 deraadt Exp $ */
|
||||
/* $OpenBSD: buffer.c,v 1.32 2010/02/09 03:56:28 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -160,7 +160,7 @@ buffer_check_alloc(Buffer *buffer, u_int len)
|
||||
/* Returns the number of bytes of data in the buffer. */
|
||||
|
||||
u_int
|
||||
buffer_len(Buffer *buffer)
|
||||
buffer_len(const Buffer *buffer)
|
||||
{
|
||||
return buffer->end - buffer->offset;
|
||||
}
|
||||
@ -228,7 +228,7 @@ buffer_consume_end(Buffer *buffer, u_int bytes)
|
||||
/* Returns a pointer to the first used byte in the buffer. */
|
||||
|
||||
void *
|
||||
buffer_ptr(Buffer *buffer)
|
||||
buffer_ptr(const Buffer *buffer)
|
||||
{
|
||||
return buffer->buf + buffer->offset;
|
||||
}
|
||||
@ -236,7 +236,7 @@ buffer_ptr(Buffer *buffer)
|
||||
/* Dumps the contents of the buffer to stderr. */
|
||||
|
||||
void
|
||||
buffer_dump(Buffer *buffer)
|
||||
buffer_dump(const Buffer *buffer)
|
||||
{
|
||||
u_int i;
|
||||
u_char *ucp = buffer->buf;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: buffer.h,v 1.17 2008/05/08 06:59:01 markus Exp $ */
|
||||
/* $OpenBSD: buffer.h,v 1.19 2010/02/09 03:56:28 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -27,8 +27,8 @@ void buffer_init(Buffer *);
|
||||
void buffer_clear(Buffer *);
|
||||
void buffer_free(Buffer *);
|
||||
|
||||
u_int buffer_len(Buffer *);
|
||||
void *buffer_ptr(Buffer *);
|
||||
u_int buffer_len(const Buffer *);
|
||||
void *buffer_ptr(const Buffer *);
|
||||
|
||||
void buffer_append(Buffer *, const void *, u_int);
|
||||
void *buffer_append_space(Buffer *, u_int);
|
||||
@ -40,7 +40,7 @@ void buffer_get(Buffer *, void *, u_int);
|
||||
void buffer_consume(Buffer *, u_int);
|
||||
void buffer_consume_end(Buffer *, u_int);
|
||||
|
||||
void buffer_dump(Buffer *);
|
||||
void buffer_dump(const Buffer *);
|
||||
|
||||
int buffer_get_ret(Buffer *, void *, u_int);
|
||||
int buffer_consume_ret(Buffer *, u_int);
|
||||
@ -81,6 +81,7 @@ int buffer_get_short_ret(u_short *, Buffer *);
|
||||
int buffer_get_int_ret(u_int *, Buffer *);
|
||||
int buffer_get_int64_ret(u_int64_t *, Buffer *);
|
||||
void *buffer_get_string_ret(Buffer *, u_int *);
|
||||
void *buffer_get_string_ptr_ret(Buffer *, u_int *);
|
||||
int buffer_get_char_ret(char *, Buffer *);
|
||||
|
||||
#endif /* BUFFER_H */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: canohost.c,v 1.65 2009/05/27 06:31:25 andreas Exp $ */
|
||||
/* $OpenBSD: canohost.c,v 1.66 2010/01/13 01:20:20 dtucker Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -27,6 +27,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "packet.h"
|
||||
@ -301,9 +302,22 @@ get_local_ipaddr(int sock)
|
||||
}
|
||||
|
||||
char *
|
||||
get_local_name(int sock)
|
||||
get_local_name(int fd)
|
||||
{
|
||||
return get_socket_address(sock, 0, NI_NAMEREQD);
|
||||
char *host, myname[NI_MAXHOST];
|
||||
|
||||
/* Assume we were passed a socket */
|
||||
if ((host = get_socket_address(fd, 0, NI_NAMEREQD)) != NULL)
|
||||
return host;
|
||||
|
||||
/* Handle the case where we were passed a pipe */
|
||||
if (gethostname(myname, sizeof(myname)) == -1) {
|
||||
verbose("get_local_name: gethostname: %s", strerror(errno));
|
||||
} else {
|
||||
host = xstrdup(myname);
|
||||
}
|
||||
|
||||
return host;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: channels.c,v 1.296 2009/05/25 06:48:00 andreas Exp $ */
|
||||
/* $OpenBSD: channels.c,v 1.303 2010/01/30 21:12:08 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -53,6 +53,7 @@
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -228,12 +229,16 @@ channel_register_fds(Channel *c, int rfd, int wfd, int efd,
|
||||
channel_max_fd = MAX(channel_max_fd, wfd);
|
||||
channel_max_fd = MAX(channel_max_fd, efd);
|
||||
|
||||
/* XXX set close-on-exec -markus */
|
||||
if (rfd != -1)
|
||||
fcntl(rfd, F_SETFD, FD_CLOEXEC);
|
||||
if (wfd != -1 && wfd != rfd)
|
||||
fcntl(wfd, F_SETFD, FD_CLOEXEC);
|
||||
if (efd != -1 && efd != rfd && efd != wfd)
|
||||
fcntl(efd, F_SETFD, FD_CLOEXEC);
|
||||
|
||||
c->rfd = rfd;
|
||||
c->wfd = wfd;
|
||||
c->sock = (rfd == wfd) ? rfd : -1;
|
||||
c->ctl_fd = -1; /* XXX: set elsewhere */
|
||||
c->efd = efd;
|
||||
c->extended_usage = extusage;
|
||||
|
||||
@ -322,6 +327,10 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd,
|
||||
c->output_filter = NULL;
|
||||
c->filter_ctx = NULL;
|
||||
c->filter_cleanup = NULL;
|
||||
c->ctl_chan = -1;
|
||||
c->mux_rcb = NULL;
|
||||
c->mux_ctx = NULL;
|
||||
c->delayed = 1; /* prevent call to channel_post handler */
|
||||
TAILQ_INIT(&c->status_confirms);
|
||||
debug("channel %d: new [%s]", found, remote_name);
|
||||
return c;
|
||||
@ -363,11 +372,10 @@ channel_close_fd(int *fdp)
|
||||
static void
|
||||
channel_close_fds(Channel *c)
|
||||
{
|
||||
debug3("channel %d: close_fds r %d w %d e %d c %d",
|
||||
c->self, c->rfd, c->wfd, c->efd, c->ctl_fd);
|
||||
debug3("channel %d: close_fds r %d w %d e %d",
|
||||
c->self, c->rfd, c->wfd, c->efd);
|
||||
|
||||
channel_close_fd(&c->sock);
|
||||
channel_close_fd(&c->ctl_fd);
|
||||
channel_close_fd(&c->rfd);
|
||||
channel_close_fd(&c->wfd);
|
||||
channel_close_fd(&c->efd);
|
||||
@ -393,8 +401,6 @@ channel_free(Channel *c)
|
||||
|
||||
if (c->sock != -1)
|
||||
shutdown(c->sock, SHUT_RDWR);
|
||||
if (c->ctl_fd != -1)
|
||||
shutdown(c->ctl_fd, SHUT_RDWR);
|
||||
channel_close_fds(c);
|
||||
buffer_free(&c->input);
|
||||
buffer_free(&c->output);
|
||||
@ -516,6 +522,7 @@ channel_still_open(void)
|
||||
case SSH_CHANNEL_X11_LISTENER:
|
||||
case SSH_CHANNEL_PORT_LISTENER:
|
||||
case SSH_CHANNEL_RPORT_LISTENER:
|
||||
case SSH_CHANNEL_MUX_LISTENER:
|
||||
case SSH_CHANNEL_CLOSED:
|
||||
case SSH_CHANNEL_AUTH_SOCKET:
|
||||
case SSH_CHANNEL_DYNAMIC:
|
||||
@ -529,6 +536,7 @@ channel_still_open(void)
|
||||
case SSH_CHANNEL_OPENING:
|
||||
case SSH_CHANNEL_OPEN:
|
||||
case SSH_CHANNEL_X11_OPEN:
|
||||
case SSH_CHANNEL_MUX_CLIENT:
|
||||
return 1;
|
||||
case SSH_CHANNEL_INPUT_DRAINING:
|
||||
case SSH_CHANNEL_OUTPUT_DRAINING:
|
||||
@ -560,6 +568,8 @@ channel_find_open(void)
|
||||
case SSH_CHANNEL_X11_LISTENER:
|
||||
case SSH_CHANNEL_PORT_LISTENER:
|
||||
case SSH_CHANNEL_RPORT_LISTENER:
|
||||
case SSH_CHANNEL_MUX_LISTENER:
|
||||
case SSH_CHANNEL_MUX_CLIENT:
|
||||
case SSH_CHANNEL_OPENING:
|
||||
case SSH_CHANNEL_CONNECTING:
|
||||
case SSH_CHANNEL_ZOMBIE:
|
||||
@ -610,6 +620,8 @@ channel_open_message(void)
|
||||
case SSH_CHANNEL_CLOSED:
|
||||
case SSH_CHANNEL_AUTH_SOCKET:
|
||||
case SSH_CHANNEL_ZOMBIE:
|
||||
case SSH_CHANNEL_MUX_CLIENT:
|
||||
case SSH_CHANNEL_MUX_LISTENER:
|
||||
continue;
|
||||
case SSH_CHANNEL_LARVAL:
|
||||
case SSH_CHANNEL_OPENING:
|
||||
@ -620,12 +632,12 @@ channel_open_message(void)
|
||||
case SSH_CHANNEL_INPUT_DRAINING:
|
||||
case SSH_CHANNEL_OUTPUT_DRAINING:
|
||||
snprintf(buf, sizeof buf,
|
||||
" #%d %.300s (t%d r%d i%d/%d o%d/%d fd %d/%d cfd %d)\r\n",
|
||||
" #%d %.300s (t%d r%d i%d/%d o%d/%d fd %d/%d cc %d)\r\n",
|
||||
c->self, c->remote_name,
|
||||
c->type, c->remote_id,
|
||||
c->istate, buffer_len(&c->input),
|
||||
c->ostate, buffer_len(&c->output),
|
||||
c->rfd, c->wfd, c->ctl_fd);
|
||||
c->rfd, c->wfd, c->ctl_chan);
|
||||
buffer_append(&buffer, buf, strlen(buf));
|
||||
continue;
|
||||
default:
|
||||
@ -832,9 +844,6 @@ channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
FD_SET(c->efd, readset);
|
||||
}
|
||||
/* XXX: What about efd? races? */
|
||||
if (compat20 && c->ctl_fd != -1 &&
|
||||
c->istate == CHAN_INPUT_OPEN && c->ostate == CHAN_OUTPUT_OPEN)
|
||||
FD_SET(c->ctl_fd, readset);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
@ -979,6 +988,28 @@ 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 &&
|
||||
buffer_check_alloc(&c->input, CHAN_RBUF))
|
||||
FD_SET(c->rfd, readset);
|
||||
if (c->istate == CHAN_INPUT_WAIT_DRAIN) {
|
||||
/* clear buffer immediately (discard any partial packet) */
|
||||
buffer_clear(&c->input);
|
||||
chan_ibuf_empty(c);
|
||||
/* Start output drain. XXX just kill chan? */
|
||||
chan_rcvd_oclose(c);
|
||||
}
|
||||
if (c->ostate == CHAN_OUTPUT_OPEN ||
|
||||
c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
|
||||
if (buffer_len(&c->output) > 0)
|
||||
FD_SET(c->wfd, writeset);
|
||||
else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN)
|
||||
chan_obuf_empty(c);
|
||||
}
|
||||
}
|
||||
|
||||
/* try to decode a socks4 header */
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
@ -1210,6 +1241,30 @@ channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
return 1;
|
||||
}
|
||||
|
||||
Channel *
|
||||
channel_connect_stdio_fwd(const char *host_to_connect, u_short port_to_connect,
|
||||
int in, int out)
|
||||
{
|
||||
Channel *c;
|
||||
|
||||
debug("channel_connect_stdio_fwd %s:%d", host_to_connect,
|
||||
port_to_connect);
|
||||
|
||||
c = channel_new("stdio-forward", SSH_CHANNEL_OPENING, in, out,
|
||||
-1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
|
||||
0, "stdio-forward", /*nonblock*/0);
|
||||
|
||||
c->path = xstrdup(host_to_connect);
|
||||
c->host_port = port_to_connect;
|
||||
c->listening_port = 0;
|
||||
c->force_drain = 1;
|
||||
|
||||
channel_register_fds(c, in, out, -1, 0, 1, 0);
|
||||
port_open_helper(c, "direct-tcpip");
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/* dynamic port forwarding */
|
||||
static void
|
||||
channel_pre_dynamic(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
@ -1219,7 +1274,6 @@ channel_pre_dynamic(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
int ret;
|
||||
|
||||
have = buffer_len(&c->input);
|
||||
c->delayed = 0;
|
||||
debug2("channel %d: pre_dynamic: have %d", c->self, have);
|
||||
/* buffer_dump(&c->input); */
|
||||
/* check if the fixed size part of the packet is in buffer. */
|
||||
@ -1322,6 +1376,13 @@ port_open_helper(Channel *c, char *rtype)
|
||||
char *remote_ipaddr = get_peer_ipaddr(c->sock);
|
||||
int remote_port = get_peer_port(c->sock);
|
||||
|
||||
if (remote_port == -1) {
|
||||
/* Fake addr/port to appease peers that validate it (Tectia) */
|
||||
xfree(remote_ipaddr);
|
||||
remote_ipaddr = xstrdup("127.0.0.1");
|
||||
remote_port = 65535;
|
||||
}
|
||||
|
||||
direct = (strcmp(rtype, "direct-tcpip") == 0);
|
||||
|
||||
snprintf(buf, sizeof buf,
|
||||
@ -1423,16 +1484,8 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
if (c->path != NULL)
|
||||
nc->path = xstrdup(c->path);
|
||||
|
||||
if (nextstate == SSH_CHANNEL_DYNAMIC) {
|
||||
/*
|
||||
* do not call the channel_post handler until
|
||||
* this flag has been reset by a pre-handler.
|
||||
* otherwise the FD_ISSET calls might overflow
|
||||
*/
|
||||
nc->delayed = 1;
|
||||
} else {
|
||||
if (nextstate != SSH_CHANNEL_DYNAMIC)
|
||||
port_open_helper(nc, rtype);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1722,36 +1775,6 @@ channel_handle_efd(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
channel_handle_ctl(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
{
|
||||
char buf[16];
|
||||
int len;
|
||||
|
||||
/* Monitor control fd to detect if the slave client exits */
|
||||
if (c->ctl_fd != -1 && FD_ISSET(c->ctl_fd, readset)) {
|
||||
len = read(c->ctl_fd, buf, sizeof(buf));
|
||||
if (len < 0 &&
|
||||
(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
|
||||
return 1;
|
||||
if (len <= 0) {
|
||||
debug2("channel %d: ctl read<=0", c->self);
|
||||
if (c->type != SSH_CHANNEL_OPEN) {
|
||||
debug2("channel %d: not open", c->self);
|
||||
chan_mark_dead(c);
|
||||
return -1;
|
||||
} else {
|
||||
chan_read_failed(c);
|
||||
chan_write_failed(c);
|
||||
}
|
||||
return -1;
|
||||
} else
|
||||
fatal("%s: unexpected data on ctl fd", __func__);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
channel_check_window(Channel *c)
|
||||
{
|
||||
@ -1777,17 +1800,136 @@ channel_check_window(Channel *c)
|
||||
static void
|
||||
channel_post_open(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
{
|
||||
if (c->delayed)
|
||||
return;
|
||||
channel_handle_rfd(c, readset, writeset);
|
||||
channel_handle_wfd(c, readset, writeset);
|
||||
if (!compat20)
|
||||
return;
|
||||
channel_handle_efd(c, readset, writeset);
|
||||
channel_handle_ctl(c, readset, writeset);
|
||||
channel_check_window(c);
|
||||
}
|
||||
|
||||
static u_int
|
||||
read_mux(Channel *c, u_int need)
|
||||
{
|
||||
char buf[CHAN_RBUF];
|
||||
int len;
|
||||
u_int rlen;
|
||||
|
||||
if (buffer_len(&c->input) < need) {
|
||||
rlen = need - buffer_len(&c->input);
|
||||
len = read(c->rfd, buf, MIN(rlen, CHAN_RBUF));
|
||||
if (len <= 0) {
|
||||
if (errno != EINTR && errno != EAGAIN) {
|
||||
debug2("channel %d: ctl read<=0 rfd %d len %d",
|
||||
c->self, c->rfd, len);
|
||||
chan_read_failed(c);
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
buffer_append(&c->input, buf, len);
|
||||
}
|
||||
return buffer_len(&c->input);
|
||||
}
|
||||
|
||||
static void
|
||||
channel_post_mux_client(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
{
|
||||
u_int need;
|
||||
ssize_t len;
|
||||
|
||||
if (!compat20)
|
||||
fatal("%s: entered with !compat20", __func__);
|
||||
|
||||
if (c->rfd != -1 && FD_ISSET(c->rfd, readset) &&
|
||||
(c->istate == CHAN_INPUT_OPEN ||
|
||||
c->istate == CHAN_INPUT_WAIT_DRAIN)) {
|
||||
/*
|
||||
* Don't not read past the precise end of packets to
|
||||
* avoid disrupting fd passing.
|
||||
*/
|
||||
if (read_mux(c, 4) < 4) /* read header */
|
||||
return;
|
||||
need = get_u32(buffer_ptr(&c->input));
|
||||
#define CHANNEL_MUX_MAX_PACKET (256 * 1024)
|
||||
if (need > CHANNEL_MUX_MAX_PACKET) {
|
||||
debug2("channel %d: packet too big %u > %u",
|
||||
c->self, CHANNEL_MUX_MAX_PACKET, need);
|
||||
chan_rcvd_oclose(c);
|
||||
return;
|
||||
}
|
||||
if (read_mux(c, need + 4) < need + 4) /* read body */
|
||||
return;
|
||||
if (c->mux_rcb(c) != 0) {
|
||||
debug("channel %d: mux_rcb failed", c->self);
|
||||
chan_mark_dead(c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (c->wfd != -1 && FD_ISSET(c->wfd, writeset) &&
|
||||
buffer_len(&c->output) > 0) {
|
||||
len = write(c->wfd, buffer_ptr(&c->output),
|
||||
buffer_len(&c->output));
|
||||
if (len < 0 && (errno == EINTR || errno == EAGAIN))
|
||||
return;
|
||||
if (len <= 0) {
|
||||
chan_mark_dead(c);
|
||||
return;
|
||||
}
|
||||
buffer_consume(&c->output, len);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
channel_post_mux_listener(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
{
|
||||
Channel *nc;
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addrlen;
|
||||
int newsock;
|
||||
uid_t euid;
|
||||
gid_t egid;
|
||||
|
||||
if (!FD_ISSET(c->sock, readset))
|
||||
return;
|
||||
|
||||
debug("multiplexing control connection");
|
||||
|
||||
/*
|
||||
* Accept connection on control socket
|
||||
*/
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addrlen = sizeof(addr);
|
||||
if ((newsock = accept(c->sock, (struct sockaddr*)&addr,
|
||||
&addrlen)) == -1) {
|
||||
error("%s accept: %s", __func__, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if (getpeereid(newsock, &euid, &egid) < 0) {
|
||||
error("%s getpeereid failed: %s", __func__,
|
||||
strerror(errno));
|
||||
close(newsock);
|
||||
return;
|
||||
}
|
||||
if ((euid != 0) && (getuid() != euid)) {
|
||||
error("multiplex uid mismatch: peer euid %u != uid %u",
|
||||
(u_int)euid, (u_int)getuid());
|
||||
close(newsock);
|
||||
return;
|
||||
}
|
||||
nc = channel_new("multiplex client", SSH_CHANNEL_MUX_CLIENT,
|
||||
newsock, newsock, -1, c->local_window_max,
|
||||
c->local_maxpacket, 0, "mux-control", 1);
|
||||
nc->mux_rcb = c->mux_rcb;
|
||||
debug3("%s: new mux channel %d fd %d", __func__,
|
||||
nc->self, nc->sock);
|
||||
/* establish state */
|
||||
nc->mux_rcb(nc);
|
||||
/* mux state transitions must not elicit protocol messages */
|
||||
nc->flags |= CHAN_LOCAL;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
channel_post_output_drain_13(Channel *c, fd_set *readset, fd_set *writeset)
|
||||
@ -1816,6 +1958,8 @@ channel_handler_init_20(void)
|
||||
channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
|
||||
channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
|
||||
channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
|
||||
channel_pre[SSH_CHANNEL_MUX_LISTENER] = &channel_pre_listener;
|
||||
channel_pre[SSH_CHANNEL_MUX_CLIENT] = &channel_pre_mux_client;
|
||||
|
||||
channel_post[SSH_CHANNEL_OPEN] = &channel_post_open;
|
||||
channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
|
||||
@ -1824,6 +1968,8 @@ channel_handler_init_20(void)
|
||||
channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
|
||||
channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
|
||||
channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open;
|
||||
channel_post[SSH_CHANNEL_MUX_LISTENER] = &channel_post_mux_listener;
|
||||
channel_post[SSH_CHANNEL_MUX_CLIENT] = &channel_post_mux_client;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1910,17 +2056,23 @@ static void
|
||||
channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset)
|
||||
{
|
||||
static int did_init = 0;
|
||||
u_int i;
|
||||
u_int i, oalloc;
|
||||
Channel *c;
|
||||
|
||||
if (!did_init) {
|
||||
channel_handler_init();
|
||||
did_init = 1;
|
||||
}
|
||||
for (i = 0; i < channels_alloc; i++) {
|
||||
for (i = 0, oalloc = channels_alloc; i < oalloc; i++) {
|
||||
c = channels[i];
|
||||
if (c == NULL)
|
||||
continue;
|
||||
if (c->delayed) {
|
||||
if (ftab == channel_pre)
|
||||
c->delayed = 0;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
if (ftab[c->type] != NULL)
|
||||
(*ftab[c->type])(c, readset, writeset);
|
||||
channel_garbage_collect(c);
|
||||
@ -2577,6 +2729,8 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
|
||||
}
|
||||
|
||||
channel_set_reuseaddr(sock);
|
||||
if (ai->ai_family == AF_INET6)
|
||||
sock_set_v6only(sock);
|
||||
|
||||
debug("Local forwarding listening on %s port %s.",
|
||||
ntop, strport);
|
||||
@ -3108,13 +3262,8 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#ifdef IPV6_V6ONLY
|
||||
if (ai->ai_family == AF_INET6) {
|
||||
int on = 1;
|
||||
if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0)
|
||||
error("setsockopt IPV6_V6ONLY: %.100s", strerror(errno));
|
||||
}
|
||||
#endif
|
||||
if (ai->ai_family == AF_INET6)
|
||||
sock_set_v6only(sock);
|
||||
if (x11_use_localhost)
|
||||
channel_set_reuseaddr(sock);
|
||||
if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: channels.h,v 1.98 2009/02/12 03:00:56 djm Exp $ */
|
||||
/* $OpenBSD: channels.h,v 1.103 2010/01/26 01:28:35 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -53,7 +53,9 @@
|
||||
#define SSH_CHANNEL_CONNECTING 12
|
||||
#define SSH_CHANNEL_DYNAMIC 13
|
||||
#define SSH_CHANNEL_ZOMBIE 14 /* Almost dead. */
|
||||
#define SSH_CHANNEL_MAX_TYPE 15
|
||||
#define SSH_CHANNEL_MUX_LISTENER 15 /* Listener for mux conn. */
|
||||
#define SSH_CHANNEL_MUX_CLIENT 16 /* Conn. to mux slave */
|
||||
#define SSH_CHANNEL_MAX_TYPE 17
|
||||
|
||||
struct Channel;
|
||||
typedef struct Channel Channel;
|
||||
@ -81,6 +83,9 @@ struct channel_connect {
|
||||
struct addrinfo *ai, *aitop;
|
||||
};
|
||||
|
||||
/* Callbacks for mux channels back into client-specific code */
|
||||
typedef int mux_callback_fn(struct Channel *);
|
||||
|
||||
struct Channel {
|
||||
int type; /* channel type/state */
|
||||
int self; /* my own channel identifier */
|
||||
@ -92,12 +97,16 @@ struct Channel {
|
||||
int wfd; /* write fd */
|
||||
int efd; /* extended fd */
|
||||
int sock; /* sock fd */
|
||||
int ctl_fd; /* control fd (client sharing) */
|
||||
int ctl_chan; /* control channel (multiplexed connections) */
|
||||
int isatty; /* rfd is a tty */
|
||||
int wfd_isatty; /* wfd is a tty */
|
||||
int client_tty; /* (client) TTY has been requested */
|
||||
int force_drain; /* force close on iEOF */
|
||||
int delayed; /* fdset hack */
|
||||
int delayed; /* post-select handlers for newly created
|
||||
* channels are delayed until the first call
|
||||
* to a matching pre-select handler.
|
||||
* this way post-select handlers are not
|
||||
* accidenly called if a FD gets reused */
|
||||
Buffer input; /* data read from socket, to be sent over
|
||||
* encrypted connection */
|
||||
Buffer output; /* data received over encrypted connection for
|
||||
@ -138,6 +147,10 @@ struct Channel {
|
||||
|
||||
/* non-blocking connect */
|
||||
struct channel_connect connect_ctx;
|
||||
|
||||
/* multiplexing protocol hook, called for each packet received */
|
||||
mux_callback_fn *mux_rcb;
|
||||
void *mux_ctx;
|
||||
};
|
||||
|
||||
#define CHAN_EXTENDED_IGNORE 0
|
||||
@ -168,6 +181,7 @@ struct Channel {
|
||||
#define CHAN_CLOSE_RCVD 0x02
|
||||
#define CHAN_EOF_SENT 0x04
|
||||
#define CHAN_EOF_RCVD 0x08
|
||||
#define CHAN_LOCAL 0x10
|
||||
|
||||
#define CHAN_RBUF 16*1024
|
||||
|
||||
@ -239,6 +253,7 @@ void channel_clear_adm_permitted_opens(void);
|
||||
void channel_print_adm_permitted_opens(void);
|
||||
int channel_input_port_forward_request(int, int);
|
||||
Channel *channel_connect_to(const char *, u_short, char *, char *);
|
||||
Channel *channel_connect_stdio_fwd(const char*, u_short, int, int);
|
||||
Channel *channel_connect_by_listen_address(u_short, char *, char *);
|
||||
int channel_request_remote_forwarding(const char *, u_short,
|
||||
const char *, u_short);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: clientloop.c,v 1.213 2009/07/05 19:28:33 stevesk Exp $ */
|
||||
/* $OpenBSD: clientloop.c,v 1.218 2010/01/28 00:21:18 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -121,7 +121,7 @@ extern int stdin_null_flag;
|
||||
extern int no_shell_flag;
|
||||
|
||||
/* Control socket */
|
||||
extern int muxserver_sock;
|
||||
extern int muxserver_sock; /* XXX use mux_client_cleanup() instead */
|
||||
|
||||
/*
|
||||
* Name of the host we are connecting to. This is the name given on the
|
||||
@ -130,6 +130,9 @@ extern int muxserver_sock;
|
||||
*/
|
||||
extern char *host;
|
||||
|
||||
/* Force TTY allocation */
|
||||
extern int force_tty_flag;
|
||||
|
||||
/*
|
||||
* Flag to indicate that we have received a window change signal which has
|
||||
* not yet been processed. This will cause a message indicating the new
|
||||
@ -143,7 +146,7 @@ static volatile sig_atomic_t received_signal = 0;
|
||||
static int in_non_blocking_mode = 0;
|
||||
|
||||
/* Common data for the client loop code. */
|
||||
static volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */
|
||||
volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */
|
||||
static int escape_char1; /* Escape character. (proto1 only) */
|
||||
static int escape_pending1; /* Last character was an escape (proto1 only) */
|
||||
static int last_was_cr; /* Last character was a newline. */
|
||||
@ -161,6 +164,8 @@ static int session_closed = 0; /* In SSH2: login session closed. */
|
||||
static void client_init_dispatch(void);
|
||||
int session_ident = -1;
|
||||
|
||||
int session_resumed = 0;
|
||||
|
||||
/* Track escape per proto2 channel */
|
||||
struct escape_filter_ctx {
|
||||
int escape_pending;
|
||||
@ -559,9 +564,6 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
|
||||
if (packet_have_data_to_write())
|
||||
FD_SET(connection_out, *writesetp);
|
||||
|
||||
if (muxserver_sock != -1)
|
||||
FD_SET(muxserver_sock, *readsetp);
|
||||
|
||||
/*
|
||||
* Wait for something to happen. This will suspend the process until
|
||||
* some selected descriptor can be read, written, or has some other
|
||||
@ -608,7 +610,7 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
|
||||
atomicio(vwrite, fileno(stderr), buffer_ptr(berr),
|
||||
buffer_len(berr));
|
||||
|
||||
leave_raw_mode();
|
||||
leave_raw_mode(force_tty_flag);
|
||||
|
||||
/*
|
||||
* Free (and clear) the buffer to reduce the amount of data that gets
|
||||
@ -629,7 +631,7 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
|
||||
buffer_init(bout);
|
||||
buffer_init(berr);
|
||||
|
||||
enter_raw_mode();
|
||||
enter_raw_mode(force_tty_flag);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -690,7 +692,7 @@ client_status_confirm(int type, Channel *c, void *ctx)
|
||||
|
||||
/* XXX supress on mux _client_ quietmode */
|
||||
tochan = options.log_level >= SYSLOG_LEVEL_ERROR &&
|
||||
c->ctl_fd != -1 && c->extended_usage == CHAN_EXTENDED_WRITE;
|
||||
c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE;
|
||||
|
||||
if (type == SSH2_MSG_CHANNEL_SUCCESS) {
|
||||
debug2("%s request accepted on channel %d",
|
||||
@ -772,7 +774,7 @@ process_cmdline(void)
|
||||
bzero(&fwd, sizeof(fwd));
|
||||
fwd.listen_host = fwd.connect_host = NULL;
|
||||
|
||||
leave_raw_mode();
|
||||
leave_raw_mode(force_tty_flag);
|
||||
handler = signal(SIGINT, SIG_IGN);
|
||||
cmd = s = read_passphrase("\r\nssh> ", RP_ECHO);
|
||||
if (s == NULL)
|
||||
@ -834,6 +836,7 @@ process_cmdline(void)
|
||||
while (isspace(*++s))
|
||||
;
|
||||
|
||||
/* XXX update list of forwards in options */
|
||||
if (delete) {
|
||||
cancel_port = 0;
|
||||
cancel_host = hpdelim(&s); /* may be NULL */
|
||||
@ -875,7 +878,7 @@ process_cmdline(void)
|
||||
|
||||
out:
|
||||
signal(SIGINT, handler);
|
||||
enter_raw_mode();
|
||||
enter_raw_mode(force_tty_flag);
|
||||
if (cmd)
|
||||
xfree(cmd);
|
||||
if (fwd.listen_host != NULL)
|
||||
@ -931,7 +934,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
|
||||
escape_char);
|
||||
buffer_append(berr, string, strlen(string));
|
||||
|
||||
if (c && c->ctl_fd != -1) {
|
||||
if (c && c->ctl_chan != -1) {
|
||||
chan_read_failed(c);
|
||||
chan_write_failed(c);
|
||||
return 0;
|
||||
@ -941,7 +944,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
|
||||
|
||||
case 'Z' - 64:
|
||||
/* XXX support this for mux clients */
|
||||
if (c && c->ctl_fd != -1) {
|
||||
if (c && c->ctl_chan != -1) {
|
||||
noescape:
|
||||
snprintf(string, sizeof string,
|
||||
"%c%c escape not available to "
|
||||
@ -986,7 +989,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
|
||||
continue;
|
||||
|
||||
case '&':
|
||||
if (c && c->ctl_fd != -1)
|
||||
if (c && c->ctl_chan != -1)
|
||||
goto noescape;
|
||||
/*
|
||||
* Detach the program (continue to serve
|
||||
@ -994,7 +997,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
|
||||
* more new connections).
|
||||
*/
|
||||
/* Restore tty modes. */
|
||||
leave_raw_mode();
|
||||
leave_raw_mode(force_tty_flag);
|
||||
|
||||
/* Stop listening for new connections. */
|
||||
channel_stop_listening();
|
||||
@ -1037,7 +1040,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
|
||||
continue;
|
||||
|
||||
case '?':
|
||||
if (c && c->ctl_fd != -1) {
|
||||
if (c && c->ctl_chan != -1) {
|
||||
snprintf(string, sizeof string,
|
||||
"%c?\r\n\
|
||||
Supported escape sequences:\r\n\
|
||||
@ -1086,7 +1089,7 @@ Supported escape sequences:\r\n\
|
||||
continue;
|
||||
|
||||
case 'C':
|
||||
if (c && c->ctl_fd != -1)
|
||||
if (c && c->ctl_chan != -1)
|
||||
goto noescape;
|
||||
process_cmdline();
|
||||
continue;
|
||||
@ -1289,7 +1292,7 @@ client_channel_closed(int id, void *arg)
|
||||
{
|
||||
channel_cancel_cleanup(id);
|
||||
session_closed = 1;
|
||||
leave_raw_mode();
|
||||
leave_raw_mode(force_tty_flag);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1322,8 +1325,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
|
||||
connection_in = packet_get_connection_in();
|
||||
connection_out = packet_get_connection_out();
|
||||
max_fd = MAX(connection_in, connection_out);
|
||||
if (muxserver_sock != -1)
|
||||
max_fd = MAX(max_fd, muxserver_sock);
|
||||
|
||||
if (!compat20) {
|
||||
/* enable nonblocking unless tty */
|
||||
@ -1362,7 +1363,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
|
||||
signal(SIGWINCH, window_change_handler);
|
||||
|
||||
if (have_pty)
|
||||
enter_raw_mode();
|
||||
enter_raw_mode(force_tty_flag);
|
||||
|
||||
if (compat20) {
|
||||
session_ident = ssh2_chan_id;
|
||||
@ -1441,12 +1442,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
|
||||
/* Buffer input from the connection. */
|
||||
client_process_net_input(readset);
|
||||
|
||||
/* Accept control connections. */
|
||||
if (muxserver_sock != -1 &&FD_ISSET(muxserver_sock, readset)) {
|
||||
if (muxserver_accept_control())
|
||||
quit_pending = 1;
|
||||
}
|
||||
|
||||
if (quit_pending)
|
||||
break;
|
||||
|
||||
@ -1460,6 +1455,14 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
|
||||
client_process_output(writeset);
|
||||
}
|
||||
|
||||
if (session_resumed) {
|
||||
connection_in = packet_get_connection_in();
|
||||
connection_out = packet_get_connection_out();
|
||||
max_fd = MAX(max_fd, connection_out);
|
||||
max_fd = MAX(max_fd, connection_in);
|
||||
session_resumed = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send as much buffered packet data as possible to the
|
||||
* sender.
|
||||
@ -1488,7 +1491,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
|
||||
channel_free_all();
|
||||
|
||||
if (have_pty)
|
||||
leave_raw_mode();
|
||||
leave_raw_mode(force_tty_flag);
|
||||
|
||||
/* restore blocking io */
|
||||
if (!isatty(fileno(stdin)))
|
||||
@ -1846,15 +1849,17 @@ client_input_channel_req(int type, u_int32_t seq, void *ctxt)
|
||||
chan_rcvd_eow(c);
|
||||
} else if (strcmp(rtype, "exit-status") == 0) {
|
||||
exitval = packet_get_int();
|
||||
if (id == session_ident) {
|
||||
if (c->ctl_chan != -1) {
|
||||
mux_exit_message(c, exitval);
|
||||
success = 1;
|
||||
} else if (id == session_ident) {
|
||||
/* Record exit value of local session */
|
||||
success = 1;
|
||||
exit_status = exitval;
|
||||
} else if (c->ctl_fd == -1) {
|
||||
error("client_input_channel_req: unexpected channel %d",
|
||||
session_ident);
|
||||
} else {
|
||||
atomicio(vwrite, c->ctl_fd, &exitval, sizeof(exitval));
|
||||
success = 1;
|
||||
/* Probably for a mux channel that has already closed */
|
||||
debug("%s: no sink for exit-status on channel %d",
|
||||
__func__, id);
|
||||
}
|
||||
packet_check_eom();
|
||||
}
|
||||
@ -2050,7 +2055,7 @@ client_init_dispatch(void)
|
||||
void
|
||||
cleanup_exit(int i)
|
||||
{
|
||||
leave_raw_mode();
|
||||
leave_raw_mode(force_tty_flag);
|
||||
leave_non_blocking();
|
||||
if (options.control_path != NULL && muxserver_sock != -1)
|
||||
unlink(options.control_path);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: clientloop.h,v 1.22 2008/06/12 15:19:17 djm Exp $ */
|
||||
/* $OpenBSD: clientloop.h,v 1.23 2010/01/26 01:28:35 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -56,18 +56,14 @@ typedef void global_confirm_cb(int, u_int32_t seq, void *);
|
||||
void client_register_global_confirm(global_confirm_cb *, void *);
|
||||
|
||||
/* Multiplexing protocol version */
|
||||
#define SSHMUX_VER 2
|
||||
#define SSHMUX_VER 4
|
||||
|
||||
/* Multiplexing control protocol flags */
|
||||
#define SSHMUX_COMMAND_OPEN 1 /* Open new connection */
|
||||
#define SSHMUX_COMMAND_ALIVE_CHECK 2 /* Check master is alive */
|
||||
#define SSHMUX_COMMAND_TERMINATE 3 /* Ask master to exit */
|
||||
|
||||
#define SSHMUX_FLAG_TTY (1) /* Request tty on open */
|
||||
#define SSHMUX_FLAG_SUBSYS (1<<1) /* Subsystem request on open */
|
||||
#define SSHMUX_FLAG_X11_FWD (1<<2) /* Request X11 forwarding */
|
||||
#define SSHMUX_FLAG_AGENT_FWD (1<<3) /* Request agent forwarding */
|
||||
#define SSHMUX_COMMAND_STDIO_FWD 4 /* Open stdio fwd (ssh -W) */
|
||||
|
||||
void muxserver_listen(void);
|
||||
int muxserver_accept_control(void);
|
||||
void muxclient(const char *);
|
||||
void mux_exit_message(Channel *, int);
|
||||
|
238
crypto/openssh/config.guess
vendored
238
crypto/openssh/config.guess
vendored
@ -1,10 +1,10 @@
|
||||
#! /bin/sh
|
||||
# Attempt to guess a canonical system name.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
# Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2008-04-14'
|
||||
timestamp='2009-12-30'
|
||||
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
@ -27,16 +27,16 @@ timestamp='2008-04-14'
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
|
||||
# Originally written by Per Bothner <per@bothner.com>.
|
||||
# Please send patches to <config-patches@gnu.org>. Submit a context
|
||||
# diff and a properly formatted ChangeLog entry.
|
||||
# Originally written by Per Bothner. Please send patches (context
|
||||
# diff format) to <config-patches@gnu.org> and include a ChangeLog
|
||||
# entry.
|
||||
#
|
||||
# This script attempts to guess a canonical system name similar to
|
||||
# config.sub. If it succeeds, it prints the system name on stdout, and
|
||||
# exits with 0. Otherwise, it exits with 1.
|
||||
#
|
||||
# The plan is that this can be called by configure scripts if you
|
||||
# don't specify an explicit build system type.
|
||||
# You can get the latest version of this script from:
|
||||
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
|
||||
|
||||
me=`echo "$0" | sed -e 's,.*/,,'`
|
||||
|
||||
@ -56,8 +56,9 @@ version="\
|
||||
GNU config.guess ($timestamp)
|
||||
|
||||
Originally written by Per Bothner.
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
||||
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
@ -170,7 +171,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
|
||||
eval $set_cc_for_build
|
||||
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||
| grep __ELF__ >/dev/null
|
||||
| grep -q __ELF__
|
||||
then
|
||||
# Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
|
||||
# Return netbsd for either. FIX?
|
||||
@ -324,14 +325,33 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
case `/usr/bin/uname -p` in
|
||||
sparc) echo sparc-icl-nx7; exit ;;
|
||||
esac ;;
|
||||
s390x:SunOS:*:*)
|
||||
echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit ;;
|
||||
sun4H:SunOS:5.*:*)
|
||||
echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit ;;
|
||||
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
|
||||
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit ;;
|
||||
i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
|
||||
echo i386-pc-auroraux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
|
||||
echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
eval $set_cc_for_build
|
||||
SUN_ARCH="i386"
|
||||
# If there is a compiler, see if it is configured for 64-bit objects.
|
||||
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
|
||||
# This test works for both compilers.
|
||||
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
|
||||
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
|
||||
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
grep IS_64BIT_ARCH >/dev/null
|
||||
then
|
||||
SUN_ARCH="x86_64"
|
||||
fi
|
||||
fi
|
||||
echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit ;;
|
||||
sun4*:SunOS:6*:*)
|
||||
# According to config.sub, this is the proper way to canonicalize
|
||||
@ -640,7 +660,7 @@ EOF
|
||||
# => hppa64-hp-hpux11.23
|
||||
|
||||
if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
|
||||
grep __LP64__ >/dev/null
|
||||
grep -q __LP64__
|
||||
then
|
||||
HP_ARCH="hppa2.0w"
|
||||
else
|
||||
@ -791,12 +811,12 @@ EOF
|
||||
i*:PW*:*)
|
||||
echo ${UNAME_MACHINE}-pc-pw32
|
||||
exit ;;
|
||||
*:Interix*:[3456]*)
|
||||
*:Interix*:*)
|
||||
case ${UNAME_MACHINE} in
|
||||
x86)
|
||||
echo i586-pc-interix${UNAME_RELEASE}
|
||||
exit ;;
|
||||
EM64T | authenticamd)
|
||||
authenticamd | genuineintel | EM64T)
|
||||
echo x86_64-unknown-interix${UNAME_RELEASE}
|
||||
exit ;;
|
||||
IA64)
|
||||
@ -806,6 +826,9 @@ EOF
|
||||
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
|
||||
echo i${UNAME_MACHINE}-pc-mks
|
||||
exit ;;
|
||||
8664:Windows_NT:*)
|
||||
echo x86_64-pc-mks
|
||||
exit ;;
|
||||
i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
|
||||
# How do we know it's Interix rather than the generic POSIX subsystem?
|
||||
# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
|
||||
@ -835,6 +858,20 @@ EOF
|
||||
i*86:Minix:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-minix
|
||||
exit ;;
|
||||
alpha:Linux:*:*)
|
||||
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
|
||||
EV5) UNAME_MACHINE=alphaev5 ;;
|
||||
EV56) UNAME_MACHINE=alphaev56 ;;
|
||||
PCA56) UNAME_MACHINE=alphapca56 ;;
|
||||
PCA57) UNAME_MACHINE=alphapca56 ;;
|
||||
EV6) UNAME_MACHINE=alphaev6 ;;
|
||||
EV67) UNAME_MACHINE=alphaev67 ;;
|
||||
EV68*) UNAME_MACHINE=alphaev68 ;;
|
||||
esac
|
||||
objdump --private-headers /bin/sh | grep -q ld.so.1
|
||||
if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
|
||||
exit ;;
|
||||
arm*:Linux:*:*)
|
||||
eval $set_cc_for_build
|
||||
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||
@ -857,6 +894,17 @@ EOF
|
||||
frv:Linux:*:*)
|
||||
echo frv-unknown-linux-gnu
|
||||
exit ;;
|
||||
i*86:Linux:*:*)
|
||||
LIBC=gnu
|
||||
eval $set_cc_for_build
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
#ifdef __dietlibc__
|
||||
LIBC=dietlibc
|
||||
#endif
|
||||
EOF
|
||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
|
||||
echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
|
||||
exit ;;
|
||||
ia64:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
exit ;;
|
||||
@ -866,74 +914,33 @@ EOF
|
||||
m68*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
exit ;;
|
||||
mips:Linux:*:*)
|
||||
mips:Linux:*:* | mips64:Linux:*:*)
|
||||
eval $set_cc_for_build
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
#undef CPU
|
||||
#undef mips
|
||||
#undef mipsel
|
||||
#undef ${UNAME_MACHINE}
|
||||
#undef ${UNAME_MACHINE}el
|
||||
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
|
||||
CPU=mipsel
|
||||
CPU=${UNAME_MACHINE}el
|
||||
#else
|
||||
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
|
||||
CPU=mips
|
||||
CPU=${UNAME_MACHINE}
|
||||
#else
|
||||
CPU=
|
||||
#endif
|
||||
#endif
|
||||
EOF
|
||||
eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
|
||||
/^CPU/{
|
||||
s: ::g
|
||||
p
|
||||
}'`"
|
||||
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
|
||||
;;
|
||||
mips64:Linux:*:*)
|
||||
eval $set_cc_for_build
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
#undef CPU
|
||||
#undef mips64
|
||||
#undef mips64el
|
||||
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
|
||||
CPU=mips64el
|
||||
#else
|
||||
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
|
||||
CPU=mips64
|
||||
#else
|
||||
CPU=
|
||||
#endif
|
||||
#endif
|
||||
EOF
|
||||
eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
|
||||
/^CPU/{
|
||||
s: ::g
|
||||
p
|
||||
}'`"
|
||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
|
||||
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
|
||||
;;
|
||||
or32:Linux:*:*)
|
||||
echo or32-unknown-linux-gnu
|
||||
exit ;;
|
||||
ppc:Linux:*:*)
|
||||
echo powerpc-unknown-linux-gnu
|
||||
padre:Linux:*:*)
|
||||
echo sparc-unknown-linux-gnu
|
||||
exit ;;
|
||||
ppc64:Linux:*:*)
|
||||
echo powerpc64-unknown-linux-gnu
|
||||
exit ;;
|
||||
alpha:Linux:*:*)
|
||||
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
|
||||
EV5) UNAME_MACHINE=alphaev5 ;;
|
||||
EV56) UNAME_MACHINE=alphaev56 ;;
|
||||
PCA56) UNAME_MACHINE=alphapca56 ;;
|
||||
PCA57) UNAME_MACHINE=alphapca56 ;;
|
||||
EV6) UNAME_MACHINE=alphaev6 ;;
|
||||
EV67) UNAME_MACHINE=alphaev67 ;;
|
||||
EV68*) UNAME_MACHINE=alphaev68 ;;
|
||||
esac
|
||||
objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
|
||||
if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
|
||||
parisc64:Linux:*:* | hppa64:Linux:*:*)
|
||||
echo hppa64-unknown-linux-gnu
|
||||
exit ;;
|
||||
parisc:Linux:*:* | hppa:Linux:*:*)
|
||||
# Look for CPU level
|
||||
@ -943,8 +950,11 @@ EOF
|
||||
*) echo hppa-unknown-linux-gnu ;;
|
||||
esac
|
||||
exit ;;
|
||||
parisc64:Linux:*:* | hppa64:Linux:*:*)
|
||||
echo hppa64-unknown-linux-gnu
|
||||
ppc64:Linux:*:*)
|
||||
echo powerpc64-unknown-linux-gnu
|
||||
exit ;;
|
||||
ppc:Linux:*:*)
|
||||
echo powerpc-unknown-linux-gnu
|
||||
exit ;;
|
||||
s390:Linux:*:* | s390x:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-ibm-linux
|
||||
@ -967,66 +977,6 @@ EOF
|
||||
xtensa*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
exit ;;
|
||||
i*86:Linux:*:*)
|
||||
# The BFD linker knows what the default object file format is, so
|
||||
# first see if it will tell us. cd to the root directory to prevent
|
||||
# problems with other programs or directories called `ld' in the path.
|
||||
# Set LC_ALL=C to ensure ld outputs messages in English.
|
||||
ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
|
||||
| sed -ne '/supported targets:/!d
|
||||
s/[ ][ ]*/ /g
|
||||
s/.*supported targets: *//
|
||||
s/ .*//
|
||||
p'`
|
||||
case "$ld_supported_targets" in
|
||||
elf32-i386)
|
||||
TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
|
||||
;;
|
||||
a.out-i386-linux)
|
||||
echo "${UNAME_MACHINE}-pc-linux-gnuaout"
|
||||
exit ;;
|
||||
"")
|
||||
# Either a pre-BFD a.out linker (linux-gnuoldld) or
|
||||
# one that does not give us useful --help.
|
||||
echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
|
||||
exit ;;
|
||||
esac
|
||||
# Determine whether the default compiler is a.out or elf
|
||||
eval $set_cc_for_build
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
#include <features.h>
|
||||
#ifdef __ELF__
|
||||
# ifdef __GLIBC__
|
||||
# if __GLIBC__ >= 2
|
||||
LIBC=gnu
|
||||
# else
|
||||
LIBC=gnulibc1
|
||||
# endif
|
||||
# else
|
||||
LIBC=gnulibc1
|
||||
# endif
|
||||
#else
|
||||
#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
LIBC=gnu
|
||||
#else
|
||||
LIBC=gnuaout
|
||||
#endif
|
||||
#endif
|
||||
#ifdef __dietlibc__
|
||||
LIBC=dietlibc
|
||||
#endif
|
||||
EOF
|
||||
eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
|
||||
/^LIBC/{
|
||||
s: ::g
|
||||
p
|
||||
}'`"
|
||||
test x"${LIBC}" != x && {
|
||||
echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
|
||||
exit
|
||||
}
|
||||
test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
|
||||
;;
|
||||
i*86:DYNIX/ptx:4*:*)
|
||||
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
|
||||
# earlier versions are messed up and put the nodename in both
|
||||
@ -1055,7 +1005,7 @@ EOF
|
||||
i*86:syllable:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-syllable
|
||||
exit ;;
|
||||
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
|
||||
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
|
||||
echo i386-unknown-lynxos${UNAME_RELEASE}
|
||||
exit ;;
|
||||
i*86:*DOS:*:*)
|
||||
@ -1099,8 +1049,11 @@ EOF
|
||||
pc:*:*:*)
|
||||
# Left here for compatibility:
|
||||
# uname -m prints for DJGPP always 'pc', but it prints nothing about
|
||||
# the processor, so we play safe by assuming i386.
|
||||
echo i386-pc-msdosdjgpp
|
||||
# the processor, so we play safe by assuming i586.
|
||||
# Note: whatever this is, it MUST be the same as what config.sub
|
||||
# prints for the "djgpp" host, or else GDB configury will decide that
|
||||
# this is a cross-build.
|
||||
echo i586-pc-msdosdjgpp
|
||||
exit ;;
|
||||
Intel:Mach:3*:*)
|
||||
echo i386-pc-mach3
|
||||
@ -1138,6 +1091,16 @@ EOF
|
||||
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
|
||||
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
|
||||
&& { echo i486-ncr-sysv4; exit; } ;;
|
||||
NCR*:*:4.2:* | MPRAS*:*:4.2:*)
|
||||
OS_REL='.3'
|
||||
test -r /etc/.relid \
|
||||
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
|
||||
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
|
||||
&& { echo i486-ncr-sysv4.3${OS_REL}; exit; }
|
||||
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
|
||||
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; }
|
||||
/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
|
||||
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
|
||||
m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
|
||||
echo m68k-unknown-lynxos${UNAME_RELEASE}
|
||||
exit ;;
|
||||
@ -1150,7 +1113,7 @@ EOF
|
||||
rs6000:LynxOS:2.*:*)
|
||||
echo rs6000-unknown-lynxos${UNAME_RELEASE}
|
||||
exit ;;
|
||||
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
|
||||
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
|
||||
echo powerpc-unknown-lynxos${UNAME_RELEASE}
|
||||
exit ;;
|
||||
SM[BE]S:UNIX_SV:*:*)
|
||||
@ -1243,6 +1206,16 @@ EOF
|
||||
*:Darwin:*:*)
|
||||
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
|
||||
case $UNAME_PROCESSOR in
|
||||
i386)
|
||||
eval $set_cc_for_build
|
||||
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
|
||||
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
|
||||
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
grep IS_64BIT_ARCH >/dev/null
|
||||
then
|
||||
UNAME_PROCESSOR="x86_64"
|
||||
fi
|
||||
fi ;;
|
||||
unknown) UNAME_PROCESSOR=powerpc ;;
|
||||
esac
|
||||
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
|
||||
@ -1324,6 +1297,9 @@ EOF
|
||||
i*86:rdos:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-rdos
|
||||
exit ;;
|
||||
i*86:AROS:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-aros
|
||||
exit ;;
|
||||
esac
|
||||
|
||||
#echo '(No uname command or uname output not recognized.)' 1>&2
|
||||
|
@ -123,6 +123,9 @@
|
||||
/* Define if you don't want to use wtmpx */
|
||||
#define DISABLE_WTMPX 1
|
||||
|
||||
/* Enable for PKCS#11 support */
|
||||
#define ENABLE_PKCS11
|
||||
|
||||
/* Builtin PRNG command timeout */
|
||||
#define ENTROPY_TIMEOUT_MSEC 200
|
||||
|
||||
@ -462,6 +465,9 @@
|
||||
/* Define to 1 if you have the <glob.h> header file. */
|
||||
#define HAVE_GLOB_H 1
|
||||
|
||||
/* Define to 1 if you have the `group_from_gid' function. */
|
||||
#define HAVE_GROUP_FROM_GID 1
|
||||
|
||||
/* Define to 1 if you have the <gssapi_generic.h> header file. */
|
||||
/* #undef HAVE_GSSAPI_GENERIC_H */
|
||||
|
||||
@ -552,9 +558,6 @@
|
||||
/* Define to 1 if you have the `pam' library (-lpam). */
|
||||
#define HAVE_LIBPAM 1
|
||||
|
||||
/* Define to 1 if you have the `sectok' library (-lsectok). */
|
||||
/* #undef HAVE_LIBSECTOK */
|
||||
|
||||
/* Define to 1 if you have the `socket' library (-lsocket). */
|
||||
/* #undef HAVE_LIBSOCKET */
|
||||
|
||||
@ -736,9 +739,6 @@
|
||||
/* define if you have sa_family_t data type */
|
||||
#define HAVE_SA_FAMILY_T 1
|
||||
|
||||
/* Define to 1 if you have the <sectok.h> header file. */
|
||||
/* #undef HAVE_SECTOK_H */
|
||||
|
||||
/* Define if you have SecureWare-based protected password database */
|
||||
/* #undef HAVE_SECUREWARE */
|
||||
|
||||
@ -763,6 +763,9 @@
|
||||
/* Define to 1 if you have the `seteuid' function. */
|
||||
#define HAVE_SETEUID 1
|
||||
|
||||
/* Define to 1 if you have the `setgroupent' function. */
|
||||
#define HAVE_SETGROUPENT 1
|
||||
|
||||
/* Define to 1 if you have the `setgroups' function. */
|
||||
#define HAVE_SETGROUPS 1
|
||||
|
||||
@ -772,6 +775,9 @@
|
||||
/* Define to 1 if you have the `setluid' function. */
|
||||
/* #undef HAVE_SETLUID */
|
||||
|
||||
/* Define to 1 if you have the `setpassent' function. */
|
||||
#define HAVE_SETPASSENT 1
|
||||
|
||||
/* Define to 1 if you have the `setpcred' function. */
|
||||
/* #undef HAVE_SETPCRED */
|
||||
|
||||
@ -1075,6 +1081,9 @@
|
||||
/* Define to 1 if you have the <usersec.h> header file. */
|
||||
/* #undef HAVE_USERSEC_H */
|
||||
|
||||
/* Define to 1 if you have the `user_from_uid' function. */
|
||||
#define HAVE_USER_FROM_UID 1
|
||||
|
||||
/* Define to 1 if you have the <util.h> header file. */
|
||||
/* #undef HAVE_UTIL_H */
|
||||
|
||||
@ -1184,6 +1193,9 @@
|
||||
EOPNOTSUPP. */
|
||||
/* #undef LINK_OPNOTSUPP_ERRNO */
|
||||
|
||||
/* Adjust Linux out-of-memory killer */
|
||||
/* #undef LINUX_OOM_ADJUST */
|
||||
|
||||
/* max value of long long calculated by configure */
|
||||
/* #undef LLONG_MAX */
|
||||
|
||||
@ -1303,9 +1315,6 @@
|
||||
/* Define if your skeychallenge() function takes 4 arguments (NetBSD) */
|
||||
/* #undef SKEYCHALLENGE_4ARG */
|
||||
|
||||
/* Define if you want smartcard support */
|
||||
/* #undef SMARTCARD */
|
||||
|
||||
/* Define as const if snprintf() can declare const char *fmt */
|
||||
#define SNPRINTF_CONST const
|
||||
|
||||
@ -1373,9 +1382,6 @@
|
||||
/* Use libedit for sftp */
|
||||
#define USE_LIBEDIT 1
|
||||
|
||||
/* Define if you want smartcard support using OpenSC */
|
||||
/* #undef USE_OPENSC */
|
||||
|
||||
/* Enable OpenSSL engine support */
|
||||
#define USE_OPENSSL_ENGINE 1
|
||||
|
||||
@ -1385,9 +1391,6 @@
|
||||
/* Use PIPES instead of a socketpair() */
|
||||
/* #undef USE_PIPES */
|
||||
|
||||
/* Define if you want smartcard support using sectok */
|
||||
/* #undef USE_SECTOK */
|
||||
|
||||
/* Define if you have Solaris process contracts */
|
||||
/* #undef USE_SOLARIS_PROCESS_CONTRACTS */
|
||||
|
||||
@ -1413,8 +1416,8 @@
|
||||
/* Define if you want SELinux support. */
|
||||
/* #undef WITH_SELINUX */
|
||||
|
||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||
significant byte first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||
/* Define to 1 if your processor stores words with the most significant byte
|
||||
first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||
#if defined __BIG_ENDIAN__
|
||||
# define WORDS_BIGENDIAN 1
|
||||
#elif ! defined __LITTLE_ENDIAN__
|
||||
|
@ -1,8 +1,5 @@
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define if building universal (internal helper macro) */
|
||||
#undef AC_APPLE_UNIVERSAL_BUILD
|
||||
|
||||
/* Define if you have a getaddrinfo that fails for the all-zeros IPv6 address
|
||||
*/
|
||||
#undef AIX_GETNAMEINFO_HACK
|
||||
@ -125,6 +122,9 @@
|
||||
/* Define if you don't want to use wtmpx */
|
||||
#undef DISABLE_WTMPX
|
||||
|
||||
/* Enable for PKCS#11 support */
|
||||
#undef ENABLE_PKCS11
|
||||
|
||||
/* Builtin PRNG command timeout */
|
||||
#undef ENTROPY_TIMEOUT_MSEC
|
||||
|
||||
@ -464,6 +464,9 @@
|
||||
/* Define to 1 if you have the <glob.h> header file. */
|
||||
#undef HAVE_GLOB_H
|
||||
|
||||
/* Define to 1 if you have the `group_from_gid' function. */
|
||||
#undef HAVE_GROUP_FROM_GID
|
||||
|
||||
/* Define to 1 if you have the <gssapi_generic.h> header file. */
|
||||
#undef HAVE_GSSAPI_GENERIC_H
|
||||
|
||||
@ -554,9 +557,6 @@
|
||||
/* Define to 1 if you have the `pam' library (-lpam). */
|
||||
#undef HAVE_LIBPAM
|
||||
|
||||
/* Define to 1 if you have the `sectok' library (-lsectok). */
|
||||
#undef HAVE_LIBSECTOK
|
||||
|
||||
/* Define to 1 if you have the `socket' library (-lsocket). */
|
||||
#undef HAVE_LIBSOCKET
|
||||
|
||||
@ -738,9 +738,6 @@
|
||||
/* define if you have sa_family_t data type */
|
||||
#undef HAVE_SA_FAMILY_T
|
||||
|
||||
/* Define to 1 if you have the <sectok.h> header file. */
|
||||
#undef HAVE_SECTOK_H
|
||||
|
||||
/* Define if you have SecureWare-based protected password database */
|
||||
#undef HAVE_SECUREWARE
|
||||
|
||||
@ -765,6 +762,9 @@
|
||||
/* Define to 1 if you have the `seteuid' function. */
|
||||
#undef HAVE_SETEUID
|
||||
|
||||
/* Define to 1 if you have the `setgroupent' function. */
|
||||
#undef HAVE_SETGROUPENT
|
||||
|
||||
/* Define to 1 if you have the `setgroups' function. */
|
||||
#undef HAVE_SETGROUPS
|
||||
|
||||
@ -774,6 +774,9 @@
|
||||
/* Define to 1 if you have the `setluid' function. */
|
||||
#undef HAVE_SETLUID
|
||||
|
||||
/* Define to 1 if you have the `setpassent' function. */
|
||||
#undef HAVE_SETPASSENT
|
||||
|
||||
/* Define to 1 if you have the `setpcred' function. */
|
||||
#undef HAVE_SETPCRED
|
||||
|
||||
@ -1077,6 +1080,9 @@
|
||||
/* Define to 1 if you have the <usersec.h> header file. */
|
||||
#undef HAVE_USERSEC_H
|
||||
|
||||
/* Define to 1 if you have the `user_from_uid' function. */
|
||||
#undef HAVE_USER_FROM_UID
|
||||
|
||||
/* Define to 1 if you have the <util.h> header file. */
|
||||
#undef HAVE_UTIL_H
|
||||
|
||||
@ -1186,6 +1192,9 @@
|
||||
EOPNOTSUPP. */
|
||||
#undef LINK_OPNOTSUPP_ERRNO
|
||||
|
||||
/* Adjust Linux out-of-memory killer */
|
||||
#undef LINUX_OOM_ADJUST
|
||||
|
||||
/* max value of long long calculated by configure */
|
||||
#undef LLONG_MAX
|
||||
|
||||
@ -1305,9 +1314,6 @@
|
||||
/* Define if your skeychallenge() function takes 4 arguments (NetBSD) */
|
||||
#undef SKEYCHALLENGE_4ARG
|
||||
|
||||
/* Define if you want smartcard support */
|
||||
#undef SMARTCARD
|
||||
|
||||
/* Define as const if snprintf() can declare const char *fmt */
|
||||
#undef SNPRINTF_CONST
|
||||
|
||||
@ -1375,9 +1381,6 @@
|
||||
/* Use libedit for sftp */
|
||||
#undef USE_LIBEDIT
|
||||
|
||||
/* Define if you want smartcard support using OpenSC */
|
||||
#undef USE_OPENSC
|
||||
|
||||
/* Enable OpenSSL engine support */
|
||||
#undef USE_OPENSSL_ENGINE
|
||||
|
||||
@ -1387,9 +1390,6 @@
|
||||
/* Use PIPES instead of a socketpair() */
|
||||
#undef USE_PIPES
|
||||
|
||||
/* Define if you want smartcard support using sectok */
|
||||
#undef USE_SECTOK
|
||||
|
||||
/* Define if you have Solaris process contracts */
|
||||
#undef USE_SOLARIS_PROCESS_CONTRACTS
|
||||
|
||||
@ -1415,17 +1415,9 @@
|
||||
/* Define if you want SELinux support. */
|
||||
#undef WITH_SELINUX
|
||||
|
||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||
significant byte first (like Motorola and SPARC, unlike Intel). */
|
||||
#if defined AC_APPLE_UNIVERSAL_BUILD
|
||||
# if defined __BIG_ENDIAN__
|
||||
# define WORDS_BIGENDIAN 1
|
||||
# endif
|
||||
#else
|
||||
# ifndef WORDS_BIGENDIAN
|
||||
# undef WORDS_BIGENDIAN
|
||||
# endif
|
||||
#endif
|
||||
/* Define to 1 if your processor stores words with the most significant byte
|
||||
first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||
#undef WORDS_BIGENDIAN
|
||||
|
||||
/* Define if xauth is found in your path */
|
||||
#undef XAUTH_PATH
|
||||
|
@ -25,7 +25,7 @@
|
||||
#ifndef _DEFINES_H
|
||||
#define _DEFINES_H
|
||||
|
||||
/* $Id: defines.h,v 1.156 2009/08/28 01:21:07 dtucker Exp $ */
|
||||
/* $Id: defines.h,v 1.159 2010/01/13 23:44:34 tim Exp $ */
|
||||
|
||||
|
||||
/* Constants */
|
||||
@ -753,4 +753,12 @@ struct winsize {
|
||||
# define SSH_IOBUFSZ 8192
|
||||
#endif
|
||||
|
||||
#ifndef _NSIG
|
||||
# ifdef NSIG
|
||||
# define _NSIG NSIG
|
||||
# else
|
||||
# define _NSIG 128
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* _DEFINES_H */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: dh.c,v 1.47 2008/06/26 09:19:39 djm Exp $ */
|
||||
/* $OpenBSD: dh.c,v 1.48 2009/10/01 11:37:33 grunk Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Niels Provos. All rights reserved.
|
||||
*
|
||||
@ -83,7 +83,7 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg)
|
||||
goto fail;
|
||||
strsize = strsep(&cp, " "); /* size */
|
||||
if (cp == NULL || *strsize == '\0' ||
|
||||
(dhg->size = (u_int)strtonum(strsize, 0, 64*1024, &errstr)) == 0 ||
|
||||
(dhg->size = (int)strtonum(strsize, 0, 64*1024, &errstr)) == 0 ||
|
||||
errstr)
|
||||
goto fail;
|
||||
/* The whole group is one bit larger */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: dns.c,v 1.25 2008/06/12 00:03:49 dtucker Exp $ */
|
||||
/* $OpenBSD: dns.c,v 1.26 2010/02/26 20:29:54 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
|
||||
@ -75,7 +75,7 @@ dns_result_totext(unsigned int res)
|
||||
*/
|
||||
static int
|
||||
dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
|
||||
u_char **digest, u_int *digest_len, const Key *key)
|
||||
u_char **digest, u_int *digest_len, Key *key)
|
||||
{
|
||||
int success = 0;
|
||||
|
||||
@ -172,7 +172,7 @@ is_numeric_hostname(const char *hostname)
|
||||
*/
|
||||
int
|
||||
verify_host_key_dns(const char *hostname, struct sockaddr *address,
|
||||
const Key *hostkey, int *flags)
|
||||
Key *hostkey, int *flags)
|
||||
{
|
||||
u_int counter;
|
||||
int result;
|
||||
@ -271,7 +271,7 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
|
||||
* Export the fingerprint of a key as a DNS resource record
|
||||
*/
|
||||
int
|
||||
export_dns_rr(const char *hostname, const Key *key, FILE *f, int generic)
|
||||
export_dns_rr(const char *hostname, Key *key, FILE *f, int generic)
|
||||
{
|
||||
u_int8_t rdata_pubkey_algorithm = 0;
|
||||
u_int8_t rdata_digest_type = SSHFP_HASH_SHA1;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: dns.h,v 1.10 2006/08/03 03:34:42 deraadt Exp $ */
|
||||
/* $OpenBSD: dns.h,v 1.11 2010/02/26 20:29:54 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
|
||||
@ -46,7 +46,7 @@ enum sshfp_hashes {
|
||||
#define DNS_VERIFY_MATCH 0x00000002
|
||||
#define DNS_VERIFY_SECURE 0x00000004
|
||||
|
||||
int verify_host_key_dns(const char *, struct sockaddr *, const Key *, int *);
|
||||
int export_dns_rr(const char *, const Key *, FILE *, int);
|
||||
int verify_host_key_dns(const char *, struct sockaddr *, Key *, int *);
|
||||
int export_dns_rr(const char *, Key *, FILE *, int);
|
||||
|
||||
#endif /* DNS_H */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: hostfile.c,v 1.45 2006/08/03 03:34:42 deraadt Exp $ */
|
||||
/* $OpenBSD: hostfile.c,v 1.48 2010/03/04 10:36:03 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -183,6 +183,41 @@ hostfile_check_key(int bits, const Key *key, const char *host, const char *filen
|
||||
return 1;
|
||||
}
|
||||
|
||||
static enum { MRK_ERROR, MRK_NONE, MRK_REVOKE, MRK_CA }
|
||||
check_markers(char **cpp)
|
||||
{
|
||||
char marker[32], *sp, *cp = *cpp;
|
||||
int ret = MRK_NONE;
|
||||
|
||||
while (*cp == '@') {
|
||||
/* Only one marker is allowed */
|
||||
if (ret != MRK_NONE)
|
||||
return MRK_ERROR;
|
||||
/* Markers are terminated by whitespace */
|
||||
if ((sp = strchr(cp, ' ')) == NULL &&
|
||||
(sp = strchr(cp, '\t')) == NULL)
|
||||
return MRK_ERROR;
|
||||
/* Extract marker for comparison */
|
||||
if (sp <= cp + 1 || sp >= cp + sizeof(marker))
|
||||
return MRK_ERROR;
|
||||
memcpy(marker, cp, sp - cp);
|
||||
marker[sp - cp] = '\0';
|
||||
if (strcmp(marker, CA_MARKER) == 0)
|
||||
ret = MRK_CA;
|
||||
else if (strcmp(marker, REVOKE_MARKER) == 0)
|
||||
ret = MRK_REVOKE;
|
||||
else
|
||||
return MRK_ERROR;
|
||||
|
||||
/* Skip past marker and any whitespace that follows it */
|
||||
cp = sp;
|
||||
for (; *cp == ' ' || *cp == '\t'; cp++)
|
||||
;
|
||||
}
|
||||
*cpp = cp;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks whether the given host (which must be in all lowercase) is already
|
||||
* in the list of our known hosts. Returns HOST_OK if the host is known and
|
||||
@ -195,16 +230,20 @@ hostfile_check_key(int bits, const Key *key, const char *host, const char *filen
|
||||
|
||||
static HostStatus
|
||||
check_host_in_hostfile_by_key_or_type(const char *filename,
|
||||
const char *host, const Key *key, int keytype, Key *found, int *numret)
|
||||
const char *host, const Key *key, int keytype, Key *found,
|
||||
int want_revocation, int *numret)
|
||||
{
|
||||
FILE *f;
|
||||
char line[8192];
|
||||
int linenum = 0;
|
||||
int want, have, linenum = 0, want_cert = key_is_cert(key);
|
||||
u_int kbits;
|
||||
char *cp, *cp2, *hashed_host;
|
||||
HostStatus end_return;
|
||||
|
||||
debug3("check_host_in_hostfile: filename %s", filename);
|
||||
debug3("check_host_in_hostfile: host %s filename %s", host, filename);
|
||||
|
||||
if (want_revocation && (key == NULL || keytype != 0 || found != NULL))
|
||||
fatal("%s: invalid arguments", __func__);
|
||||
|
||||
/* Open the file containing the list of known hosts. */
|
||||
f = fopen(filename, "r");
|
||||
@ -229,6 +268,20 @@ check_host_in_hostfile_by_key_or_type(const char *filename,
|
||||
if (!*cp || *cp == '#' || *cp == '\n')
|
||||
continue;
|
||||
|
||||
if (want_revocation)
|
||||
want = MRK_REVOKE;
|
||||
else if (want_cert)
|
||||
want = MRK_CA;
|
||||
else
|
||||
want = MRK_NONE;
|
||||
|
||||
if ((have = check_markers(&cp)) == MRK_ERROR) {
|
||||
verbose("%s: invalid marker at %s:%d",
|
||||
__func__, filename, linenum);
|
||||
continue;
|
||||
} else if (want != have)
|
||||
continue;
|
||||
|
||||
/* Find the end of the host name portion. */
|
||||
for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++)
|
||||
;
|
||||
@ -250,6 +303,9 @@ check_host_in_hostfile_by_key_or_type(const char *filename,
|
||||
/* Got a match. Skip host name. */
|
||||
cp = cp2;
|
||||
|
||||
if (want_revocation)
|
||||
found = key_new(KEY_UNSPEC);
|
||||
|
||||
/*
|
||||
* Extract the key from the line. This will skip any leading
|
||||
* whitespace. Ignore badly formatted lines.
|
||||
@ -272,9 +328,33 @@ check_host_in_hostfile_by_key_or_type(const char *filename,
|
||||
if (!hostfile_check_key(kbits, found, host, filename, linenum))
|
||||
continue;
|
||||
|
||||
if (want_revocation) {
|
||||
if (key_is_cert(key) &&
|
||||
key_equal_public(key->cert->signature_key, found)) {
|
||||
verbose("check_host_in_hostfile: revoked CA "
|
||||
"line %d", linenum);
|
||||
key_free(found);
|
||||
return HOST_REVOKED;
|
||||
}
|
||||
if (key_equal_public(key, found)) {
|
||||
verbose("check_host_in_hostfile: revoked key "
|
||||
"line %d", linenum);
|
||||
key_free(found);
|
||||
return HOST_REVOKED;
|
||||
}
|
||||
key_free(found);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check if the current key is the same as the given key. */
|
||||
if (key_equal(key, found)) {
|
||||
/* Ok, they match. */
|
||||
if (want_cert && key_equal(key->cert->signature_key, found)) {
|
||||
/* Found CA cert for key */
|
||||
debug3("check_host_in_hostfile: CA match line %d",
|
||||
linenum);
|
||||
fclose(f);
|
||||
return HOST_OK;
|
||||
} else if (!want_cert && key_equal(key, found)) {
|
||||
/* Found identical key */
|
||||
debug3("check_host_in_hostfile: match line %d", linenum);
|
||||
fclose(f);
|
||||
return HOST_OK;
|
||||
@ -302,8 +382,11 @@ check_host_in_hostfile(const char *filename, const char *host, const Key *key,
|
||||
{
|
||||
if (key == NULL)
|
||||
fatal("no key to look up");
|
||||
return (check_host_in_hostfile_by_key_or_type(filename, host, key, 0,
|
||||
found, numret));
|
||||
if (check_host_in_hostfile_by_key_or_type(filename, host,
|
||||
key, 0, NULL, 1, NULL) == HOST_REVOKED)
|
||||
return HOST_REVOKED;
|
||||
return check_host_in_hostfile_by_key_or_type(filename, host, key, 0,
|
||||
found, 0, numret);
|
||||
}
|
||||
|
||||
int
|
||||
@ -311,7 +394,7 @@ lookup_key_in_hostfile_by_type(const char *filename, const char *host,
|
||||
int keytype, Key *found, int *numret)
|
||||
{
|
||||
return (check_host_in_hostfile_by_key_or_type(filename, host, NULL,
|
||||
keytype, found, numret) == HOST_FOUND);
|
||||
keytype, found, 0, numret) == HOST_FOUND);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: hostfile.h,v 1.16 2006/03/25 22:22:43 djm Exp $ */
|
||||
/* $OpenBSD: hostfile.h,v 1.18 2010/03/04 10:36:03 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -15,7 +15,7 @@
|
||||
#define HOSTFILE_H
|
||||
|
||||
typedef enum {
|
||||
HOST_OK, HOST_NEW, HOST_CHANGED, HOST_FOUND
|
||||
HOST_OK, HOST_NEW, HOST_CHANGED, HOST_REVOKED, HOST_FOUND
|
||||
} HostStatus;
|
||||
|
||||
int hostfile_read_key(char **, u_int *, Key *);
|
||||
@ -28,6 +28,9 @@ int lookup_key_in_hostfile_by_type(const char *, const char *,
|
||||
#define HASH_MAGIC "|1|"
|
||||
#define HASH_DELIM '|'
|
||||
|
||||
#define CA_MARKER "@cert-authority"
|
||||
#define REVOKE_MARKER "@revoked"
|
||||
|
||||
char *host_hash(const char *, const char *, u_int);
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: kex.c,v 1.81 2009/05/27 06:34:36 andreas Exp $ */
|
||||
/* $OpenBSD: kex.c,v 1.82 2009/10/24 11:13:54 andreas Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -48,6 +48,7 @@
|
||||
#include "match.h"
|
||||
#include "dispatch.h"
|
||||
#include "monitor.h"
|
||||
#include "roaming.h"
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
|
||||
# if defined(HAVE_EVP_SHA256)
|
||||
@ -386,6 +387,16 @@ kex_choose_conf(Kex *kex)
|
||||
sprop=peer;
|
||||
}
|
||||
|
||||
/* Check whether server offers roaming */
|
||||
if (!kex->server) {
|
||||
char *roaming;
|
||||
roaming = match_list(KEX_RESUME, peer[PROPOSAL_KEX_ALGS], NULL);
|
||||
if (roaming) {
|
||||
kex->roaming = 1;
|
||||
xfree(roaming);
|
||||
}
|
||||
}
|
||||
|
||||
/* Algorithm Negotiation */
|
||||
for (mode = 0; mode < MODE_MAX; mode++) {
|
||||
newkeys = xcalloc(1, sizeof(*newkeys));
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: kex.h,v 1.47 2009/05/27 06:34:36 andreas Exp $ */
|
||||
/* $OpenBSD: kex.h,v 1.49 2010/02/26 20:29:54 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
@ -36,6 +36,7 @@
|
||||
#define KEX_DH14 "diffie-hellman-group14-sha1"
|
||||
#define KEX_DHGEX_SHA1 "diffie-hellman-group-exchange-sha1"
|
||||
#define KEX_DHGEX_SHA256 "diffie-hellman-group-exchange-sha256"
|
||||
#define KEX_RESUME "resume@appgate.com"
|
||||
|
||||
#define COMP_NONE 0
|
||||
#define COMP_ZLIB 1
|
||||
@ -116,6 +117,7 @@ struct Kex {
|
||||
char *name;
|
||||
int hostkey_type;
|
||||
int kex_type;
|
||||
int roaming;
|
||||
Buffer my;
|
||||
Buffer peer;
|
||||
sig_atomic_t done;
|
||||
@ -124,7 +126,8 @@ struct Kex {
|
||||
char *client_version_string;
|
||||
char *server_version_string;
|
||||
int (*verify_host_key)(Key *);
|
||||
Key *(*load_host_key)(int);
|
||||
Key *(*load_host_public_key)(int);
|
||||
Key *(*load_host_private_key)(int);
|
||||
int (*host_key_index)(Key *);
|
||||
void (*kex[KEX_MAX])(Kex *);
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: kexdhs.c,v 1.10 2009/06/21 07:37:15 dtucker Exp $ */
|
||||
/* $OpenBSD: kexdhs.c,v 1.11 2010/02/26 20:29:54 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -50,7 +50,7 @@ kexdh_server(Kex *kex)
|
||||
{
|
||||
BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
|
||||
DH *dh;
|
||||
Key *server_host_key;
|
||||
Key *server_host_public, *server_host_private;
|
||||
u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
|
||||
u_int sbloblen, klen, hashlen, slen;
|
||||
int kout;
|
||||
@ -71,11 +71,16 @@ kexdh_server(Kex *kex)
|
||||
debug("expecting SSH2_MSG_KEXDH_INIT");
|
||||
packet_read_expect(SSH2_MSG_KEXDH_INIT);
|
||||
|
||||
if (kex->load_host_key == NULL)
|
||||
if (kex->load_host_public_key == NULL ||
|
||||
kex->load_host_private_key == NULL)
|
||||
fatal("Cannot load hostkey");
|
||||
server_host_key = kex->load_host_key(kex->hostkey_type);
|
||||
if (server_host_key == NULL)
|
||||
server_host_public = kex->load_host_public_key(kex->hostkey_type);
|
||||
if (server_host_public == NULL)
|
||||
fatal("Unsupported hostkey type %d", kex->hostkey_type);
|
||||
server_host_private = kex->load_host_private_key(kex->hostkey_type);
|
||||
if (server_host_private == NULL)
|
||||
fatal("Missing private key for hostkey type %d",
|
||||
kex->hostkey_type);
|
||||
|
||||
/* key, cert */
|
||||
if ((dh_client_pub = BN_new()) == NULL)
|
||||
@ -113,7 +118,7 @@ kexdh_server(Kex *kex)
|
||||
memset(kbuf, 0, klen);
|
||||
xfree(kbuf);
|
||||
|
||||
key_to_blob(server_host_key, &server_host_key_blob, &sbloblen);
|
||||
key_to_blob(server_host_public, &server_host_key_blob, &sbloblen);
|
||||
|
||||
/* calc H */
|
||||
kex_dh_hash(
|
||||
@ -137,7 +142,7 @@ kexdh_server(Kex *kex)
|
||||
}
|
||||
|
||||
/* sign H */
|
||||
if (PRIVSEP(key_sign(server_host_key, &signature, &slen, hash,
|
||||
if (PRIVSEP(key_sign(server_host_private, &signature, &slen, hash,
|
||||
hashlen)) < 0)
|
||||
fatal("kexdh_server: key_sign failed");
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: kexgexs.c,v 1.12 2009/06/21 07:37:15 dtucker Exp $ */
|
||||
/* $OpenBSD: kexgexs.c,v 1.13 2010/02/26 20:29:54 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Niels Provos. All rights reserved.
|
||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||
@ -52,18 +52,24 @@ void
|
||||
kexgex_server(Kex *kex)
|
||||
{
|
||||
BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
|
||||
Key *server_host_key;
|
||||
Key *server_host_public, *server_host_private;
|
||||
DH *dh;
|
||||
u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
|
||||
u_int sbloblen, klen, slen, hashlen;
|
||||
int omin = -1, min = -1, omax = -1, max = -1, onbits = -1, nbits = -1;
|
||||
int type, kout;
|
||||
|
||||
if (kex->load_host_key == NULL)
|
||||
if (kex->load_host_public_key == NULL ||
|
||||
kex->load_host_private_key == NULL)
|
||||
fatal("Cannot load hostkey");
|
||||
server_host_key = kex->load_host_key(kex->hostkey_type);
|
||||
if (server_host_key == NULL)
|
||||
server_host_public = kex->load_host_public_key(kex->hostkey_type);
|
||||
if (server_host_public == NULL)
|
||||
fatal("Unsupported hostkey type %d", kex->hostkey_type);
|
||||
server_host_private = kex->load_host_private_key(kex->hostkey_type);
|
||||
if (server_host_private == NULL)
|
||||
fatal("Missing private key for hostkey type %d",
|
||||
kex->hostkey_type);
|
||||
|
||||
|
||||
type = packet_read();
|
||||
switch (type) {
|
||||
@ -149,7 +155,7 @@ kexgex_server(Kex *kex)
|
||||
memset(kbuf, 0, klen);
|
||||
xfree(kbuf);
|
||||
|
||||
key_to_blob(server_host_key, &server_host_key_blob, &sbloblen);
|
||||
key_to_blob(server_host_public, &server_host_key_blob, &sbloblen);
|
||||
|
||||
if (type == SSH2_MSG_KEX_DH_GEX_REQUEST_OLD)
|
||||
omin = min = omax = max = -1;
|
||||
@ -179,7 +185,7 @@ kexgex_server(Kex *kex)
|
||||
}
|
||||
|
||||
/* sign H */
|
||||
if (PRIVSEP(key_sign(server_host_key, &signature, &slen, hash,
|
||||
if (PRIVSEP(key_sign(server_host_private, &signature, &slen, hash,
|
||||
hashlen)) < 0)
|
||||
fatal("kexgex_server: key_sign failed");
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: key.c,v 1.80 2008/10/10 05:00:12 stevesk Exp $ */
|
||||
/* $OpenBSD: key.c,v 1.85 2010/03/04 01:44:57 djm Exp $ */
|
||||
/*
|
||||
* read_bignum():
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -52,6 +52,21 @@
|
||||
#include "uuencode.h"
|
||||
#include "buffer.h"
|
||||
#include "log.h"
|
||||
#include "ssh2.h"
|
||||
|
||||
static struct KeyCert *
|
||||
cert_new(void)
|
||||
{
|
||||
struct KeyCert *cert;
|
||||
|
||||
cert = xcalloc(1, sizeof(*cert));
|
||||
buffer_init(&cert->certblob);
|
||||
buffer_init(&cert->constraints);
|
||||
cert->key_id = NULL;
|
||||
cert->principals = NULL;
|
||||
cert->signature_key = NULL;
|
||||
return cert;
|
||||
}
|
||||
|
||||
Key *
|
||||
key_new(int type)
|
||||
@ -63,9 +78,11 @@ key_new(int type)
|
||||
k->type = type;
|
||||
k->dsa = NULL;
|
||||
k->rsa = NULL;
|
||||
k->cert = NULL;
|
||||
switch (k->type) {
|
||||
case KEY_RSA1:
|
||||
case KEY_RSA:
|
||||
case KEY_RSA_CERT:
|
||||
if ((rsa = RSA_new()) == NULL)
|
||||
fatal("key_new: RSA_new failed");
|
||||
if ((rsa->n = BN_new()) == NULL)
|
||||
@ -75,6 +92,7 @@ key_new(int type)
|
||||
k->rsa = rsa;
|
||||
break;
|
||||
case KEY_DSA:
|
||||
case KEY_DSA_CERT:
|
||||
if ((dsa = DSA_new()) == NULL)
|
||||
fatal("key_new: DSA_new failed");
|
||||
if ((dsa->p = BN_new()) == NULL)
|
||||
@ -93,16 +111,20 @@ key_new(int type)
|
||||
fatal("key_new: bad key type %d", k->type);
|
||||
break;
|
||||
}
|
||||
|
||||
if (key_is_cert(k))
|
||||
k->cert = cert_new();
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
Key *
|
||||
key_new_private(int type)
|
||||
void
|
||||
key_add_private(Key *k)
|
||||
{
|
||||
Key *k = key_new(type);
|
||||
switch (k->type) {
|
||||
case KEY_RSA1:
|
||||
case KEY_RSA:
|
||||
case KEY_RSA_CERT:
|
||||
if ((k->rsa->d = BN_new()) == NULL)
|
||||
fatal("key_new_private: BN_new failed");
|
||||
if ((k->rsa->iqmp = BN_new()) == NULL)
|
||||
@ -117,6 +139,7 @@ key_new_private(int type)
|
||||
fatal("key_new_private: BN_new failed");
|
||||
break;
|
||||
case KEY_DSA:
|
||||
case KEY_DSA_CERT:
|
||||
if ((k->dsa->priv_key = BN_new()) == NULL)
|
||||
fatal("key_new_private: BN_new failed");
|
||||
break;
|
||||
@ -125,9 +148,34 @@ key_new_private(int type)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Key *
|
||||
key_new_private(int type)
|
||||
{
|
||||
Key *k = key_new(type);
|
||||
|
||||
key_add_private(k);
|
||||
return k;
|
||||
}
|
||||
|
||||
static void
|
||||
cert_free(struct KeyCert *cert)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
buffer_free(&cert->certblob);
|
||||
buffer_free(&cert->constraints);
|
||||
if (cert->key_id != NULL)
|
||||
xfree(cert->key_id);
|
||||
for (i = 0; i < cert->nprincipals; i++)
|
||||
xfree(cert->principals[i]);
|
||||
if (cert->principals != NULL)
|
||||
xfree(cert->principals);
|
||||
if (cert->signature_key != NULL)
|
||||
key_free(cert->signature_key);
|
||||
}
|
||||
|
||||
void
|
||||
key_free(Key *k)
|
||||
{
|
||||
@ -136,11 +184,13 @@ key_free(Key *k)
|
||||
switch (k->type) {
|
||||
case KEY_RSA1:
|
||||
case KEY_RSA:
|
||||
case KEY_RSA_CERT:
|
||||
if (k->rsa != NULL)
|
||||
RSA_free(k->rsa);
|
||||
k->rsa = NULL;
|
||||
break;
|
||||
case KEY_DSA:
|
||||
case KEY_DSA_CERT:
|
||||
if (k->dsa != NULL)
|
||||
DSA_free(k->dsa);
|
||||
k->dsa = NULL;
|
||||
@ -151,20 +201,49 @@ key_free(Key *k)
|
||||
fatal("key_free: bad key type %d", k->type);
|
||||
break;
|
||||
}
|
||||
if (key_is_cert(k)) {
|
||||
if (k->cert != NULL)
|
||||
cert_free(k->cert);
|
||||
k->cert = NULL;
|
||||
}
|
||||
|
||||
xfree(k);
|
||||
}
|
||||
|
||||
int
|
||||
key_equal(const Key *a, const Key *b)
|
||||
static int
|
||||
cert_compare(struct KeyCert *a, struct KeyCert *b)
|
||||
{
|
||||
if (a == NULL || b == NULL || a->type != b->type)
|
||||
if (a == NULL && b == NULL)
|
||||
return 1;
|
||||
if (a == NULL || b == NULL)
|
||||
return 0;
|
||||
if (buffer_len(&a->certblob) != buffer_len(&b->certblob))
|
||||
return 0;
|
||||
if (memcmp(buffer_ptr(&a->certblob), buffer_ptr(&b->certblob),
|
||||
buffer_len(&a->certblob)) != 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare public portions of key only, allowing comparisons between
|
||||
* certificates and plain keys too.
|
||||
*/
|
||||
int
|
||||
key_equal_public(const Key *a, const Key *b)
|
||||
{
|
||||
if (a == NULL || b == NULL ||
|
||||
key_type_plain(a->type) != key_type_plain(b->type))
|
||||
return 0;
|
||||
|
||||
switch (a->type) {
|
||||
case KEY_RSA1:
|
||||
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:
|
||||
case KEY_DSA:
|
||||
return a->dsa != NULL && b->dsa != NULL &&
|
||||
BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
|
||||
@ -177,16 +256,27 @@ key_equal(const Key *a, const Key *b)
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
int
|
||||
key_equal(const Key *a, const Key *b)
|
||||
{
|
||||
if (a == NULL || b == NULL || a->type != b->type)
|
||||
return 0;
|
||||
if (key_is_cert(a)) {
|
||||
if (!cert_compare(a->cert, b->cert))
|
||||
return 0;
|
||||
}
|
||||
return key_equal_public(a, b);
|
||||
}
|
||||
|
||||
u_char*
|
||||
key_fingerprint_raw(const Key *k, enum fp_type dgst_type,
|
||||
u_int *dgst_raw_length)
|
||||
key_fingerprint_raw(Key *k, enum fp_type dgst_type, u_int *dgst_raw_length)
|
||||
{
|
||||
const EVP_MD *md = NULL;
|
||||
EVP_MD_CTX ctx;
|
||||
u_char *blob = NULL;
|
||||
u_char *retval = NULL;
|
||||
u_int len = 0;
|
||||
int nlen, elen;
|
||||
int nlen, elen, otype;
|
||||
|
||||
*dgst_raw_length = 0;
|
||||
|
||||
@ -214,6 +304,14 @@ key_fingerprint_raw(const Key *k, enum fp_type dgst_type,
|
||||
case KEY_RSA:
|
||||
key_to_blob(k, &blob, &len);
|
||||
break;
|
||||
case KEY_DSA_CERT:
|
||||
case KEY_RSA_CERT:
|
||||
/* We want a fingerprint of the _key_ not of the cert */
|
||||
otype = k->type;
|
||||
k->type = key_type_plain(k->type);
|
||||
key_to_blob(k, &blob, &len);
|
||||
k->type = otype;
|
||||
break;
|
||||
case KEY_UNSPEC:
|
||||
return retval;
|
||||
default:
|
||||
@ -408,7 +506,7 @@ key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k)
|
||||
}
|
||||
|
||||
char *
|
||||
key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
|
||||
key_fingerprint(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
|
||||
{
|
||||
char *retval = NULL;
|
||||
u_char *dgst_raw;
|
||||
@ -522,11 +620,19 @@ key_read(Key *ret, char **cpp)
|
||||
return -1;
|
||||
if (!read_bignum(cpp, ret->rsa->n))
|
||||
return -1;
|
||||
/* validate the claimed number of bits */
|
||||
if ((u_int)BN_num_bits(ret->rsa->n) != bits) {
|
||||
verbose("key_read: claimed key size %d does not match "
|
||||
"actual %d", bits, BN_num_bits(ret->rsa->n));
|
||||
return -1;
|
||||
}
|
||||
success = 1;
|
||||
break;
|
||||
case KEY_UNSPEC:
|
||||
case KEY_RSA:
|
||||
case KEY_DSA:
|
||||
case KEY_DSA_CERT:
|
||||
case KEY_RSA_CERT:
|
||||
space = strchr(cp, ' ');
|
||||
if (space == NULL) {
|
||||
debug3("key_read: missing whitespace");
|
||||
@ -571,25 +677,36 @@ key_read(Key *ret, char **cpp)
|
||||
return -1;
|
||||
}
|
||||
/*XXXX*/
|
||||
if (ret->type == KEY_RSA) {
|
||||
if (key_is_cert(ret)) {
|
||||
if (!key_is_cert(k)) {
|
||||
error("key_read: loaded key is not a cert");
|
||||
key_free(k);
|
||||
return -1;
|
||||
}
|
||||
if (ret->cert != NULL)
|
||||
cert_free(ret->cert);
|
||||
ret->cert = k->cert;
|
||||
k->cert = NULL;
|
||||
}
|
||||
if (key_type_plain(ret->type) == KEY_RSA) {
|
||||
if (ret->rsa != NULL)
|
||||
RSA_free(ret->rsa);
|
||||
ret->rsa = k->rsa;
|
||||
k->rsa = NULL;
|
||||
success = 1;
|
||||
#ifdef DEBUG_PK
|
||||
RSA_print_fp(stderr, ret->rsa, 8);
|
||||
#endif
|
||||
} else {
|
||||
}
|
||||
if (key_type_plain(ret->type) == KEY_DSA) {
|
||||
if (ret->dsa != NULL)
|
||||
DSA_free(ret->dsa);
|
||||
ret->dsa = k->dsa;
|
||||
k->dsa = NULL;
|
||||
success = 1;
|
||||
#ifdef DEBUG_PK
|
||||
DSA_print_fp(stderr, ret->dsa, 8);
|
||||
#endif
|
||||
}
|
||||
success = 1;
|
||||
/*XXXX*/
|
||||
key_free(k);
|
||||
if (success != 1)
|
||||
@ -616,28 +733,53 @@ key_write(const Key *key, FILE *f)
|
||||
u_char *blob;
|
||||
char *uu;
|
||||
|
||||
if (key->type == KEY_RSA1 && key->rsa != NULL) {
|
||||
if (key_is_cert(key)) {
|
||||
if (key->cert == NULL) {
|
||||
error("%s: no cert data", __func__);
|
||||
return 0;
|
||||
}
|
||||
if (buffer_len(&key->cert->certblob) == 0) {
|
||||
error("%s: no signed certificate blob", __func__);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
switch (key->type) {
|
||||
case KEY_RSA1:
|
||||
if (key->rsa == NULL)
|
||||
return 0;
|
||||
/* size of modulus 'n' */
|
||||
bits = BN_num_bits(key->rsa->n);
|
||||
fprintf(f, "%u", bits);
|
||||
if (write_bignum(f, key->rsa->e) &&
|
||||
write_bignum(f, key->rsa->n)) {
|
||||
success = 1;
|
||||
} else {
|
||||
error("key_write: failed for RSA key");
|
||||
}
|
||||
} else if ((key->type == KEY_DSA && key->dsa != NULL) ||
|
||||
(key->type == KEY_RSA && key->rsa != NULL)) {
|
||||
key_to_blob(key, &blob, &len);
|
||||
uu = xmalloc(2*len);
|
||||
n = uuencode(blob, len, uu, 2*len);
|
||||
if (n > 0) {
|
||||
fprintf(f, "%s %s", key_ssh_name(key), uu);
|
||||
success = 1;
|
||||
}
|
||||
xfree(blob);
|
||||
xfree(uu);
|
||||
write_bignum(f, key->rsa->n))
|
||||
return 1;
|
||||
error("key_write: failed for RSA key");
|
||||
return 0;
|
||||
case KEY_DSA:
|
||||
case KEY_DSA_CERT:
|
||||
if (key->dsa == NULL)
|
||||
return 0;
|
||||
break;
|
||||
case KEY_RSA:
|
||||
case KEY_RSA_CERT:
|
||||
if (key->rsa == NULL)
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
key_to_blob(key, &blob, &len);
|
||||
uu = xmalloc(2*len);
|
||||
n = uuencode(blob, len, uu, 2*len);
|
||||
if (n > 0) {
|
||||
fprintf(f, "%s %s", key_ssh_name(key), uu);
|
||||
success = 1;
|
||||
}
|
||||
xfree(blob);
|
||||
xfree(uu);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@ -651,6 +793,10 @@ key_type(const Key *k)
|
||||
return "RSA";
|
||||
case KEY_DSA:
|
||||
return "DSA";
|
||||
case KEY_RSA_CERT:
|
||||
return "RSA-CERT";
|
||||
case KEY_DSA_CERT:
|
||||
return "DSA-CERT";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
@ -663,6 +809,10 @@ key_ssh_name(const Key *k)
|
||||
return "ssh-rsa";
|
||||
case KEY_DSA:
|
||||
return "ssh-dss";
|
||||
case KEY_RSA_CERT:
|
||||
return "ssh-rsa-cert-v00@openssh.com";
|
||||
case KEY_DSA_CERT:
|
||||
return "ssh-dss-cert-v00@openssh.com";
|
||||
}
|
||||
return "ssh-unknown";
|
||||
}
|
||||
@ -673,8 +823,10 @@ key_size(const Key *k)
|
||||
switch (k->type) {
|
||||
case KEY_RSA1:
|
||||
case KEY_RSA:
|
||||
case KEY_RSA_CERT:
|
||||
return BN_num_bits(k->rsa->n);
|
||||
case KEY_DSA:
|
||||
case KEY_DSA_CERT:
|
||||
return BN_num_bits(k->dsa->p);
|
||||
}
|
||||
return 0;
|
||||
@ -685,7 +837,7 @@ rsa_generate_private_key(u_int bits)
|
||||
{
|
||||
RSA *private;
|
||||
|
||||
private = RSA_generate_key(bits, 35, NULL, NULL);
|
||||
private = RSA_generate_key(bits, RSA_F4, NULL, NULL);
|
||||
if (private == NULL)
|
||||
fatal("rsa_generate_private_key: key generation failed.");
|
||||
return private;
|
||||
@ -717,6 +869,9 @@ key_generate(int type, u_int bits)
|
||||
case KEY_RSA1:
|
||||
k->rsa = rsa_generate_private_key(bits);
|
||||
break;
|
||||
case KEY_RSA_CERT:
|
||||
case KEY_DSA_CERT:
|
||||
fatal("key_generate: cert keys cannot be generated directly");
|
||||
default:
|
||||
fatal("key_generate: unknown type %d", type);
|
||||
}
|
||||
@ -724,12 +879,55 @@ key_generate(int type, u_int bits)
|
||||
return k;
|
||||
}
|
||||
|
||||
void
|
||||
key_cert_copy(const Key *from_key, struct Key *to_key)
|
||||
{
|
||||
u_int i;
|
||||
const struct KeyCert *from;
|
||||
struct KeyCert *to;
|
||||
|
||||
if (to_key->cert != NULL) {
|
||||
cert_free(to_key->cert);
|
||||
to_key->cert = NULL;
|
||||
}
|
||||
|
||||
if ((from = from_key->cert) == NULL)
|
||||
return;
|
||||
|
||||
to = to_key->cert = cert_new();
|
||||
|
||||
buffer_append(&to->certblob, buffer_ptr(&from->certblob),
|
||||
buffer_len(&from->certblob));
|
||||
|
||||
buffer_append(&to->constraints, buffer_ptr(&from->constraints),
|
||||
buffer_len(&from->constraints));
|
||||
|
||||
to->type = from->type;
|
||||
to->key_id = from->key_id == NULL ? NULL : xstrdup(from->key_id);
|
||||
to->valid_after = from->valid_after;
|
||||
to->valid_before = from->valid_before;
|
||||
to->signature_key = from->signature_key == NULL ?
|
||||
NULL : key_from_private(from->signature_key);
|
||||
|
||||
to->nprincipals = from->nprincipals;
|
||||
if (to->nprincipals > CERT_MAX_PRINCIPALS)
|
||||
fatal("%s: nprincipals (%u) > CERT_MAX_PRINCIPALS (%u)",
|
||||
__func__, to->nprincipals, CERT_MAX_PRINCIPALS);
|
||||
if (to->nprincipals > 0) {
|
||||
to->principals = xcalloc(from->nprincipals,
|
||||
sizeof(*to->principals));
|
||||
for (i = 0; i < to->nprincipals; i++)
|
||||
to->principals[i] = xstrdup(from->principals[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Key *
|
||||
key_from_private(const Key *k)
|
||||
{
|
||||
Key *n = NULL;
|
||||
switch (k->type) {
|
||||
case KEY_DSA:
|
||||
case KEY_DSA_CERT:
|
||||
n = key_new(k->type);
|
||||
if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) ||
|
||||
(BN_copy(n->dsa->q, k->dsa->q) == NULL) ||
|
||||
@ -739,6 +937,7 @@ key_from_private(const Key *k)
|
||||
break;
|
||||
case KEY_RSA:
|
||||
case KEY_RSA1:
|
||||
case KEY_RSA_CERT:
|
||||
n = key_new(k->type);
|
||||
if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
|
||||
(BN_copy(n->rsa->e, k->rsa->e) == NULL))
|
||||
@ -748,6 +947,8 @@ key_from_private(const Key *k)
|
||||
fatal("key_from_private: unknown type %d", k->type);
|
||||
break;
|
||||
}
|
||||
if (key_is_cert(k))
|
||||
key_cert_copy(k, n);
|
||||
return n;
|
||||
}
|
||||
|
||||
@ -764,6 +965,10 @@ key_type_from_name(char *name)
|
||||
return KEY_RSA;
|
||||
} 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;
|
||||
} else if (strcmp(name, "ssh-dss-cert-v00@openssh.com") == 0) {
|
||||
return KEY_DSA_CERT;
|
||||
}
|
||||
debug2("key_type_from_name: unknown key type '%s'", name);
|
||||
return KEY_UNSPEC;
|
||||
@ -791,6 +996,127 @@ key_names_valid2(const char *names)
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
Buffer tmp;
|
||||
char *principal;
|
||||
int ret = -1;
|
||||
|
||||
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 ||
|
||||
(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 ||
|
||||
(sig_key = buffer_get_string_ret(b, &sklen)) == NULL) {
|
||||
error("%s: parse error", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (kidlen != strlen(key->cert->key_id)) {
|
||||
error("%s: key ID contains \\0 character", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Signature is left in the buffer so we can calculate this length */
|
||||
signed_len = buffer_len(&key->cert->certblob) - buffer_len(b);
|
||||
|
||||
if ((sig = buffer_get_string_ret(b, &slen)) == NULL) {
|
||||
error("%s: parse error", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (key->cert->type != SSH2_CERT_TYPE_USER &&
|
||||
key->cert->type != SSH2_CERT_TYPE_HOST) {
|
||||
error("Unknown certificate type %u", key->cert->type);
|
||||
goto out;
|
||||
}
|
||||
|
||||
buffer_append(&tmp, principals, plen);
|
||||
while (buffer_len(&tmp) > 0) {
|
||||
if (key->cert->nprincipals >= CERT_MAX_PRINCIPALS) {
|
||||
error("%s: Too many principals", __func__);
|
||||
goto out;
|
||||
}
|
||||
if ((principal = buffer_get_string_ret(&tmp, &plen)) == NULL) {
|
||||
error("%s: Principals data invalid", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (strlen(principal) != plen) {
|
||||
error("%s: Principal contains \\0 character",
|
||||
__func__);
|
||||
goto out;
|
||||
}
|
||||
key->cert->principals = xrealloc(key->cert->principals,
|
||||
key->cert->nprincipals + 1, sizeof(*key->cert->principals));
|
||||
key->cert->principals[key->cert->nprincipals++] = principal;
|
||||
}
|
||||
|
||||
buffer_clear(&tmp);
|
||||
|
||||
buffer_append(&key->cert->constraints, constraints, clen);
|
||||
buffer_append(&tmp, constraints, 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__);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
buffer_clear(&tmp);
|
||||
|
||||
if ((key->cert->signature_key = key_from_blob(sig_key,
|
||||
sklen)) == NULL) {
|
||||
error("%s: Signature key invalid", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (key->cert->signature_key->type != KEY_RSA &&
|
||||
key->cert->signature_key->type != KEY_DSA) {
|
||||
error("%s: Invalid signature key type %s (%d)", __func__,
|
||||
key_type(key->cert->signature_key),
|
||||
key->cert->signature_key->type);
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (key_verify(key->cert->signature_key, sig, slen,
|
||||
buffer_ptr(&key->cert->certblob), signed_len)) {
|
||||
case 1:
|
||||
ret = 0;
|
||||
break; /* Good signature */
|
||||
case 0:
|
||||
error("%s: Invalid signature on certificate", __func__);
|
||||
goto out;
|
||||
case -1:
|
||||
error("%s: Certificate signature verification failed",
|
||||
__func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
buffer_free(&tmp);
|
||||
if (principals != NULL)
|
||||
xfree(principals);
|
||||
if (constraints != NULL)
|
||||
xfree(constraints);
|
||||
if (sig_key != NULL)
|
||||
xfree(sig_key);
|
||||
if (sig != NULL)
|
||||
xfree(sig);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Key *
|
||||
key_from_blob(const u_char *blob, u_int blen)
|
||||
{
|
||||
@ -813,10 +1139,12 @@ key_from_blob(const u_char *blob, u_int blen)
|
||||
|
||||
switch (type) {
|
||||
case KEY_RSA:
|
||||
case KEY_RSA_CERT:
|
||||
key = key_new(type);
|
||||
if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 ||
|
||||
buffer_get_bignum2_ret(&b, key->rsa->n) == -1) {
|
||||
error("key_from_blob: can't read rsa key");
|
||||
badkey:
|
||||
key_free(key);
|
||||
key = NULL;
|
||||
goto out;
|
||||
@ -826,15 +1154,14 @@ key_from_blob(const u_char *blob, u_int blen)
|
||||
#endif
|
||||
break;
|
||||
case KEY_DSA:
|
||||
case KEY_DSA_CERT:
|
||||
key = key_new(type);
|
||||
if (buffer_get_bignum2_ret(&b, key->dsa->p) == -1 ||
|
||||
buffer_get_bignum2_ret(&b, key->dsa->q) == -1 ||
|
||||
buffer_get_bignum2_ret(&b, key->dsa->g) == -1 ||
|
||||
buffer_get_bignum2_ret(&b, key->dsa->pub_key) == -1) {
|
||||
error("key_from_blob: can't read dsa key");
|
||||
key_free(key);
|
||||
key = NULL;
|
||||
goto out;
|
||||
goto badkey;
|
||||
}
|
||||
#ifdef DEBUG_PK
|
||||
DSA_print_fp(stderr, key->dsa, 8);
|
||||
@ -847,6 +1174,10 @@ key_from_blob(const u_char *blob, u_int blen)
|
||||
error("key_from_blob: cannot handle type %s", ktype);
|
||||
goto out;
|
||||
}
|
||||
if (key_is_cert(key) && cert_parse(&b, key, blob, blen) == -1) {
|
||||
error("key_from_blob: can't parse cert data");
|
||||
goto badkey;
|
||||
}
|
||||
rlen = buffer_len(&b);
|
||||
if (key != NULL && rlen != 0)
|
||||
error("key_from_blob: remaining bytes in key blob %d", rlen);
|
||||
@ -869,6 +1200,12 @@ key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
|
||||
}
|
||||
buffer_init(&b);
|
||||
switch (key->type) {
|
||||
case KEY_DSA_CERT:
|
||||
case KEY_RSA_CERT:
|
||||
/* Use the existing blob */
|
||||
buffer_append(&b, buffer_ptr(&key->cert->certblob),
|
||||
buffer_len(&key->cert->certblob));
|
||||
break;
|
||||
case KEY_DSA:
|
||||
buffer_put_cstring(&b, key_ssh_name(key));
|
||||
buffer_put_bignum2(&b, key->dsa->p);
|
||||
@ -905,8 +1242,10 @@ key_sign(
|
||||
const u_char *data, u_int datalen)
|
||||
{
|
||||
switch (key->type) {
|
||||
case KEY_DSA_CERT:
|
||||
case KEY_DSA:
|
||||
return ssh_dss_sign(key, sigp, lenp, data, datalen);
|
||||
case KEY_RSA_CERT:
|
||||
case KEY_RSA:
|
||||
return ssh_rsa_sign(key, sigp, lenp, data, datalen);
|
||||
default:
|
||||
@ -929,8 +1268,10 @@ key_verify(
|
||||
return -1;
|
||||
|
||||
switch (key->type) {
|
||||
case KEY_DSA_CERT:
|
||||
case KEY_DSA:
|
||||
return ssh_dss_verify(key, signature, signaturelen, data, datalen);
|
||||
case KEY_RSA_CERT:
|
||||
case KEY_RSA:
|
||||
return ssh_rsa_verify(key, signature, signaturelen, data, datalen);
|
||||
default:
|
||||
@ -952,6 +1293,9 @@ key_demote(const Key *k)
|
||||
pk->rsa = NULL;
|
||||
|
||||
switch (k->type) {
|
||||
case KEY_RSA_CERT:
|
||||
key_cert_copy(k, pk);
|
||||
/* FALLTHROUGH */
|
||||
case KEY_RSA1:
|
||||
case KEY_RSA:
|
||||
if ((pk->rsa = RSA_new()) == NULL)
|
||||
@ -961,6 +1305,9 @@ 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:
|
||||
key_cert_copy(k, pk);
|
||||
/* FALLTHROUGH */
|
||||
case KEY_DSA:
|
||||
if ((pk->dsa = DSA_new()) == NULL)
|
||||
fatal("key_demote: DSA_new failed");
|
||||
@ -980,3 +1327,199 @@ key_demote(const Key *k)
|
||||
|
||||
return (pk);
|
||||
}
|
||||
|
||||
int
|
||||
key_is_cert(const Key *k)
|
||||
{
|
||||
return k != NULL &&
|
||||
(k->type == KEY_RSA_CERT || k->type == KEY_DSA_CERT);
|
||||
}
|
||||
|
||||
/* Return the cert-less equivalent to a certified key type */
|
||||
int
|
||||
key_type_plain(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case KEY_RSA_CERT:
|
||||
return KEY_RSA;
|
||||
case KEY_DSA_CERT:
|
||||
return KEY_DSA;
|
||||
default:
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert a KEY_RSA or KEY_DSA to their _CERT equivalent */
|
||||
int
|
||||
key_to_certified(Key *k)
|
||||
{
|
||||
switch (k->type) {
|
||||
case KEY_RSA:
|
||||
k->cert = cert_new();
|
||||
k->type = KEY_RSA_CERT;
|
||||
return 0;
|
||||
case KEY_DSA:
|
||||
k->cert = cert_new();
|
||||
k->type = KEY_DSA_CERT;
|
||||
return 0;
|
||||
default:
|
||||
error("%s: key has incorrect type %s", __func__, key_type(k));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert a KEY_RSA_CERT or KEY_DSA_CERT to their raw key equivalent */
|
||||
int
|
||||
key_drop_cert(Key *k)
|
||||
{
|
||||
switch (k->type) {
|
||||
case KEY_RSA_CERT:
|
||||
cert_free(k->cert);
|
||||
k->type = KEY_RSA;
|
||||
return 0;
|
||||
case KEY_DSA_CERT:
|
||||
cert_free(k->cert);
|
||||
k->type = KEY_DSA;
|
||||
return 0;
|
||||
default:
|
||||
error("%s: key has incorrect type %s", __func__, key_type(k));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sign a KEY_RSA_CERT or KEY_DSA_CERT, (re-)generating the signed certblob */
|
||||
int
|
||||
key_certify(Key *k, Key *ca)
|
||||
{
|
||||
Buffer principals;
|
||||
u_char *ca_blob, *sig_blob, nonce[32];
|
||||
u_int i, ca_len, sig_len;
|
||||
|
||||
if (k->cert == NULL) {
|
||||
error("%s: key lacks cert info", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!key_is_cert(k)) {
|
||||
error("%s: certificate has unknown type %d", __func__,
|
||||
k->cert->type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ca->type != KEY_RSA && ca->type != KEY_DSA) {
|
||||
error("%s: CA key has unsupported type %s", __func__,
|
||||
key_type(ca));
|
||||
return -1;
|
||||
}
|
||||
|
||||
key_to_blob(ca, &ca_blob, &ca_len);
|
||||
|
||||
buffer_clear(&k->cert->certblob);
|
||||
buffer_put_cstring(&k->cert->certblob, key_ssh_name(k));
|
||||
|
||||
switch (k->type) {
|
||||
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:
|
||||
buffer_put_bignum2(&k->cert->certblob, k->rsa->e);
|
||||
buffer_put_bignum2(&k->cert->certblob, k->rsa->n);
|
||||
break;
|
||||
default:
|
||||
error("%s: key has incorrect type %s", __func__, key_type(k));
|
||||
buffer_clear(&k->cert->certblob);
|
||||
xfree(ca_blob);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer_put_int(&k->cert->certblob, k->cert->type);
|
||||
buffer_put_cstring(&k->cert->certblob, k->cert->key_id);
|
||||
|
||||
buffer_init(&principals);
|
||||
for (i = 0; i < k->cert->nprincipals; i++)
|
||||
buffer_put_cstring(&principals, k->cert->principals[i]);
|
||||
buffer_put_string(&k->cert->certblob, buffer_ptr(&principals),
|
||||
buffer_len(&principals));
|
||||
buffer_free(&principals);
|
||||
|
||||
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));
|
||||
|
||||
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);
|
||||
|
||||
/* Sign the whole mess */
|
||||
if (key_sign(ca, &sig_blob, &sig_len, buffer_ptr(&k->cert->certblob),
|
||||
buffer_len(&k->cert->certblob)) != 0) {
|
||||
error("%s: signature operation failed", __func__);
|
||||
buffer_clear(&k->cert->certblob);
|
||||
return -1;
|
||||
}
|
||||
/* Append signature and we are done */
|
||||
buffer_put_string(&k->cert->certblob, sig_blob, sig_len);
|
||||
xfree(sig_blob);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
key_cert_check_authority(const Key *k, int want_host, int require_principal,
|
||||
const char *name, const char **reason)
|
||||
{
|
||||
u_int i, principal_matches;
|
||||
time_t now = time(NULL);
|
||||
|
||||
if (want_host) {
|
||||
if (k->cert->type != SSH2_CERT_TYPE_HOST) {
|
||||
*reason = "Certificate invalid: not a host certificate";
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (k->cert->type != SSH2_CERT_TYPE_USER) {
|
||||
*reason = "Certificate invalid: not a user certificate";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (now < 0) {
|
||||
error("%s: system clock lies before epoch", __func__);
|
||||
*reason = "Certificate invalid: not yet valid";
|
||||
return -1;
|
||||
}
|
||||
if ((u_int64_t)now < k->cert->valid_after) {
|
||||
*reason = "Certificate invalid: not yet valid";
|
||||
return -1;
|
||||
}
|
||||
if ((u_int64_t)now >= k->cert->valid_before) {
|
||||
*reason = "Certificate invalid: expired";
|
||||
return -1;
|
||||
}
|
||||
if (k->cert->nprincipals == 0) {
|
||||
if (require_principal) {
|
||||
*reason = "Certificate lacks principal list";
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
principal_matches = 0;
|
||||
for (i = 0; i < k->cert->nprincipals; i++) {
|
||||
if (strcmp(name, k->cert->principals[i]) == 0) {
|
||||
principal_matches = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!principal_matches) {
|
||||
*reason = "Certificate invalid: name is not a listed "
|
||||
"principal";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: key.h,v 1.27 2008/06/11 21:01:35 grunk Exp $ */
|
||||
/* $OpenBSD: key.h,v 1.28 2010/02/26 20:29:54 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
@ -26,6 +26,7 @@
|
||||
#ifndef KEY_H
|
||||
#define KEY_H
|
||||
|
||||
#include "buffer.h"
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/dsa.h>
|
||||
|
||||
@ -34,6 +35,8 @@ enum types {
|
||||
KEY_RSA1,
|
||||
KEY_RSA,
|
||||
KEY_DSA,
|
||||
KEY_RSA_CERT,
|
||||
KEY_DSA_CERT,
|
||||
KEY_UNSPEC
|
||||
};
|
||||
enum fp_type {
|
||||
@ -49,20 +52,35 @@ enum fp_rep {
|
||||
/* key is stored in external hardware */
|
||||
#define KEY_FLAG_EXT 0x0001
|
||||
|
||||
#define CERT_MAX_PRINCIPALS 256
|
||||
struct KeyCert {
|
||||
Buffer certblob; /* Kept around for use on wire */
|
||||
u_int type; /* SSH2_CERT_TYPE_USER or SSH2_CERT_TYPE_HOST */
|
||||
char *key_id;
|
||||
u_int nprincipals;
|
||||
char **principals;
|
||||
u_int64_t valid_after, valid_before;
|
||||
Buffer constraints;
|
||||
Key *signature_key;
|
||||
};
|
||||
|
||||
struct Key {
|
||||
int type;
|
||||
int flags;
|
||||
RSA *rsa;
|
||||
DSA *dsa;
|
||||
struct KeyCert *cert;
|
||||
};
|
||||
|
||||
Key *key_new(int);
|
||||
void key_add_private(Key *);
|
||||
Key *key_new_private(int);
|
||||
void key_free(Key *);
|
||||
Key *key_demote(const Key *);
|
||||
int key_equal_public(const Key *, const Key *);
|
||||
int key_equal(const Key *, const Key *);
|
||||
char *key_fingerprint(const Key *, enum fp_type, enum fp_rep);
|
||||
u_char *key_fingerprint_raw(const Key *, enum fp_type, u_int *);
|
||||
char *key_fingerprint(Key *, enum fp_type, enum fp_rep);
|
||||
u_char *key_fingerprint_raw(Key *, enum fp_type, u_int *);
|
||||
const char *key_type(const Key *);
|
||||
int key_write(const Key *, FILE *);
|
||||
int key_read(Key *, char **);
|
||||
@ -71,6 +89,14 @@ u_int key_size(const Key *);
|
||||
Key *key_generate(int, u_int);
|
||||
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_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 **);
|
||||
|
||||
Key *key_from_blob(const u_char *, u_int);
|
||||
int key_to_blob(const Key *, u_char **, u_int *);
|
||||
|
@ -1322,8 +1322,8 @@ wtmpx_write_entry(struct logininfo *li)
|
||||
static int
|
||||
wtmpx_islogin(struct logininfo *li, struct utmpx *utx)
|
||||
{
|
||||
if (strncmp(li->username, utx->ut_name,
|
||||
MIN_SIZEOF(li->username, utx->ut_name)) == 0 ) {
|
||||
if (strncmp(li->username, utx->ut_user,
|
||||
MIN_SIZEOF(li->username, utx->ut_user)) == 0 ) {
|
||||
# ifdef HAVE_TYPE_IN_UTMPX
|
||||
if (utx->ut_type == USER_PROCESS)
|
||||
return (1);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: match.h,v 1.14 2008/06/10 03:57:27 djm Exp $ */
|
||||
/* $OpenBSD: match.h,v 1.15 2010/02/26 20:29:54 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -23,5 +23,5 @@ char *match_list(const char *, const char *, u_int *);
|
||||
|
||||
/* addrmatch.c */
|
||||
int addr_match_list(const char *, const char *);
|
||||
|
||||
int addr_match_cidr_list(const char *, const char *);
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: misc.c,v 1.71 2009/02/21 19:32:04 tobias Exp $ */
|
||||
/* $OpenBSD: misc.c,v 1.75 2010/01/09 23:04:13 dtucker Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2005,2006 Damien Miller. All rights reserved.
|
||||
@ -560,11 +560,11 @@ char *
|
||||
percent_expand(const char *string, ...)
|
||||
{
|
||||
#define EXPAND_MAX_KEYS 16
|
||||
u_int num_keys, i, j;
|
||||
struct {
|
||||
const char *key;
|
||||
const char *repl;
|
||||
} keys[EXPAND_MAX_KEYS];
|
||||
u_int num_keys, i, j;
|
||||
char buf[4096];
|
||||
va_list ap;
|
||||
|
||||
@ -576,13 +576,12 @@ percent_expand(const char *string, ...)
|
||||
break;
|
||||
keys[num_keys].repl = va_arg(ap, char *);
|
||||
if (keys[num_keys].repl == NULL)
|
||||
fatal("percent_expand: NULL replacement");
|
||||
fatal("%s: NULL replacement", __func__);
|
||||
}
|
||||
if (num_keys == EXPAND_MAX_KEYS && va_arg(ap, char *) != NULL)
|
||||
fatal("%s: too many keys", __func__);
|
||||
va_end(ap);
|
||||
|
||||
if (num_keys >= EXPAND_MAX_KEYS)
|
||||
fatal("percent_expand: too many keys");
|
||||
|
||||
/* Expand string */
|
||||
*buf = '\0';
|
||||
for (i = 0; *string != '\0'; string++) {
|
||||
@ -590,23 +589,24 @@ percent_expand(const char *string, ...)
|
||||
append:
|
||||
buf[i++] = *string;
|
||||
if (i >= sizeof(buf))
|
||||
fatal("percent_expand: string too long");
|
||||
fatal("%s: string too long", __func__);
|
||||
buf[i] = '\0';
|
||||
continue;
|
||||
}
|
||||
string++;
|
||||
/* %% case */
|
||||
if (*string == '%')
|
||||
goto append;
|
||||
for (j = 0; j < num_keys; j++) {
|
||||
if (strchr(keys[j].key, *string) != NULL) {
|
||||
i = strlcat(buf, keys[j].repl, sizeof(buf));
|
||||
if (i >= sizeof(buf))
|
||||
fatal("percent_expand: string too long");
|
||||
fatal("%s: string too long", __func__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j >= num_keys)
|
||||
fatal("percent_expand: unknown key %%%c", *string);
|
||||
fatal("%s: unknown key %%%c", __func__, *string);
|
||||
}
|
||||
return (xstrdup(buf));
|
||||
#undef EXPAND_MAX_KEYS
|
||||
@ -849,3 +849,14 @@ ms_to_timeval(struct timeval *tv, int ms)
|
||||
tv->tv_usec = (ms % 1000) * 1000;
|
||||
}
|
||||
|
||||
void
|
||||
sock_set_v6only(int s)
|
||||
{
|
||||
#ifdef IPV6_V6ONLY
|
||||
int on = 1;
|
||||
|
||||
debug3("%s: set socket %d IPV6_V6ONLY", __func__, s);
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1)
|
||||
error("setsockopt IPV6_V6ONLY: %s", strerror(errno));
|
||||
#endif
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: misc.h,v 1.38 2008/06/12 20:38:28 dtucker Exp $ */
|
||||
/* $OpenBSD: misc.h,v 1.41 2010/01/09 23:04:13 dtucker Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -35,6 +35,7 @@ char *tohex(const void *, size_t);
|
||||
void sanitise_stdfd(void);
|
||||
void ms_subtract_diff(struct timeval *, int *);
|
||||
void ms_to_timeval(struct timeval *, int);
|
||||
void sock_set_v6only(int);
|
||||
|
||||
struct passwd *pwcopy(struct passwd *);
|
||||
const char *ssh_gai_strerror(int);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: monitor.c,v 1.104 2009/06/12 20:43:22 andreas Exp $ */
|
||||
/* $OpenBSD: monitor.c,v 1.106 2010/03/07 11:57:13 dtucker Exp $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright 2002 Markus Friedl <markus@openbsd.org>
|
||||
@ -997,17 +997,6 @@ mm_answer_pam_free_ctx(int sock, Buffer *m)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
mm_append_debug(Buffer *m)
|
||||
{
|
||||
if (auth_debug_init && buffer_len(&auth_debug)) {
|
||||
debug3("%s: Appending debug messages for child", __func__);
|
||||
buffer_append(m, buffer_ptr(&auth_debug),
|
||||
buffer_len(&auth_debug));
|
||||
buffer_clear(&auth_debug);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
mm_answer_keyallowed(int sock, Buffer *m)
|
||||
{
|
||||
@ -1090,8 +1079,6 @@ mm_answer_keyallowed(int sock, Buffer *m)
|
||||
buffer_put_int(m, allowed);
|
||||
buffer_put_int(m, forced_command != NULL);
|
||||
|
||||
mm_append_debug(m);
|
||||
|
||||
mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m);
|
||||
|
||||
if (type == MM_RSAHOSTKEY)
|
||||
@ -1475,8 +1462,6 @@ mm_answer_rsa_keyallowed(int sock, Buffer *m)
|
||||
if (key != NULL)
|
||||
key_free(key);
|
||||
|
||||
mm_append_debug(m);
|
||||
|
||||
mm_request_send(sock, MONITOR_ANS_RSAKEYALLOWED, m);
|
||||
|
||||
monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed);
|
||||
@ -1721,7 +1706,8 @@ mm_get_kex(Buffer *m)
|
||||
kex->flags = buffer_get_int(m);
|
||||
kex->client_version_string = buffer_get_string(m, NULL);
|
||||
kex->server_version_string = buffer_get_string(m, NULL);
|
||||
kex->load_host_key=&get_hostkey_by_type;
|
||||
kex->load_host_public_key=&get_hostkey_public_by_type;
|
||||
kex->load_host_private_key=&get_hostkey_private_by_type;
|
||||
kex->host_key_index=&get_hostkey_index;
|
||||
|
||||
return (kex);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: monitor_fdpass.c,v 1.18 2008/11/30 11:59:26 dtucker Exp $ */
|
||||
/* $OpenBSD: monitor_fdpass.c,v 1.19 2010/01/12 00:58:25 djm Exp $ */
|
||||
/*
|
||||
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
@ -34,6 +34,9 @@
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_POLL_H
|
||||
#include <poll.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
@ -55,6 +58,7 @@ mm_send_fd(int sock, int fd)
|
||||
struct iovec vec;
|
||||
char ch = '\0';
|
||||
ssize_t n;
|
||||
struct pollfd pfd;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
#ifdef HAVE_ACCRIGHTS_IN_MSGHDR
|
||||
@ -75,9 +79,13 @@ mm_send_fd(int sock, int fd)
|
||||
msg.msg_iov = &vec;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
while ((n = sendmsg(sock, &msg, 0)) == -1 && (errno == EAGAIN ||
|
||||
errno == EINTR))
|
||||
pfd.fd = sock;
|
||||
pfd.events = POLLOUT;
|
||||
while ((n = sendmsg(sock, &msg, 0)) == -1 &&
|
||||
(errno == EAGAIN || errno == EINTR)) {
|
||||
debug3("%s: sendmsg(%d): %s", __func__, fd, strerror(errno));
|
||||
(void)poll(&pfd, 1, -1);
|
||||
}
|
||||
if (n == -1) {
|
||||
error("%s: sendmsg(%d): %s", __func__, fd,
|
||||
strerror(errno));
|
||||
@ -112,6 +120,7 @@ mm_receive_fd(int sock)
|
||||
ssize_t n;
|
||||
char ch;
|
||||
int fd;
|
||||
struct pollfd pfd;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
vec.iov_base = &ch;
|
||||
@ -126,9 +135,13 @@ mm_receive_fd(int sock)
|
||||
msg.msg_controllen = sizeof(cmsgbuf.buf);
|
||||
#endif
|
||||
|
||||
while ((n = recvmsg(sock, &msg, 0)) == -1 && (errno == EAGAIN ||
|
||||
errno == EINTR))
|
||||
pfd.fd = sock;
|
||||
pfd.events = POLLIN;
|
||||
while ((n = recvmsg(sock, &msg, 0)) == -1 &&
|
||||
(errno == EAGAIN || errno == EINTR)) {
|
||||
debug3("%s: recvmsg: %s", __func__, strerror(errno));
|
||||
(void)poll(&pfd, 1, -1);
|
||||
}
|
||||
if (n == -1) {
|
||||
error("%s: recvmsg: %s", __func__, strerror(errno));
|
||||
return -1;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: monitor_wrap.c,v 1.68 2009/06/22 05:39:28 dtucker Exp $ */
|
||||
/* $OpenBSD: monitor_wrap.c,v 1.69 2010/03/07 11:57:13 dtucker Exp $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright 2002 Markus Friedl <markus@openbsd.org>
|
||||
@ -347,19 +347,6 @@ mm_auth_rhosts_rsa_key_allowed(struct passwd *pw, char *user,
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
mm_send_debug(Buffer *m)
|
||||
{
|
||||
char *msg;
|
||||
|
||||
while (buffer_len(m)) {
|
||||
msg = buffer_get_string(m, NULL);
|
||||
debug3("%s: Sending debug: %s", __func__, msg);
|
||||
packet_send_debug("%s", msg);
|
||||
xfree(msg);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
mm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key)
|
||||
{
|
||||
@ -393,9 +380,6 @@ mm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key)
|
||||
have_forced = buffer_get_int(&m);
|
||||
forced_command = have_forced ? xstrdup("true") : NULL;
|
||||
|
||||
/* Send potential debug messages */
|
||||
mm_send_debug(&m);
|
||||
|
||||
buffer_free(&m);
|
||||
|
||||
return (allowed);
|
||||
@ -1085,7 +1069,6 @@ mm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
|
||||
*rkey = key;
|
||||
xfree(blob);
|
||||
}
|
||||
mm_send_debug(&m);
|
||||
buffer_free(&m);
|
||||
|
||||
return (allowed);
|
||||
|
1923
crypto/openssh/mux.c
1923
crypto/openssh/mux.c
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: myproposal.h,v 1.23 2009/01/23 07:58:11 djm Exp $ */
|
||||
/* $OpenBSD: myproposal.h,v 1.24 2010/02/26 20:29:54 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
@ -40,7 +40,9 @@
|
||||
"diffie-hellman-group1-sha1"
|
||||
#endif
|
||||
|
||||
#define KEX_DEFAULT_PK_ALG "ssh-rsa,ssh-dss"
|
||||
#define KEX_DEFAULT_PK_ALG "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," \
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: nchan.c,v 1.62 2008/11/07 18:50:18 stevesk Exp $ */
|
||||
/* $OpenBSD: nchan.c,v 1.63 2010/01/26 01:28:35 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -161,7 +161,7 @@ chan_ibuf_empty(Channel *c)
|
||||
switch (c->istate) {
|
||||
case CHAN_INPUT_WAIT_DRAIN:
|
||||
if (compat20) {
|
||||
if (!(c->flags & CHAN_CLOSE_SENT))
|
||||
if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL)))
|
||||
chan_send_eof2(c);
|
||||
chan_set_istate(c, CHAN_INPUT_CLOSED);
|
||||
} else {
|
||||
@ -278,9 +278,12 @@ static void
|
||||
chan_rcvd_close2(Channel *c)
|
||||
{
|
||||
debug2("channel %d: rcvd close", c->self);
|
||||
if (c->flags & CHAN_CLOSE_RCVD)
|
||||
error("channel %d: protocol error: close rcvd twice", c->self);
|
||||
c->flags |= CHAN_CLOSE_RCVD;
|
||||
if (!(c->flags & CHAN_LOCAL)) {
|
||||
if (c->flags & CHAN_CLOSE_RCVD)
|
||||
error("channel %d: protocol error: close rcvd twice",
|
||||
c->self);
|
||||
c->flags |= CHAN_CLOSE_RCVD;
|
||||
}
|
||||
if (c->type == SSH_CHANNEL_LARVAL) {
|
||||
/* tear down larval channels immediately */
|
||||
chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
|
||||
@ -302,11 +305,13 @@ chan_rcvd_close2(Channel *c)
|
||||
chan_set_istate(c, CHAN_INPUT_CLOSED);
|
||||
break;
|
||||
case CHAN_INPUT_WAIT_DRAIN:
|
||||
chan_send_eof2(c);
|
||||
if (!(c->flags & CHAN_LOCAL))
|
||||
chan_send_eof2(c);
|
||||
chan_set_istate(c, CHAN_INPUT_CLOSED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
chan_rcvd_eow(Channel *c)
|
||||
{
|
||||
@ -454,6 +459,10 @@ chan_is_dead(Channel *c, int do_send)
|
||||
c->self, c->efd, buffer_len(&c->extended));
|
||||
return 0;
|
||||
}
|
||||
if (c->flags & CHAN_LOCAL) {
|
||||
debug2("channel %d: is dead (local)", c->self);
|
||||
return 1;
|
||||
}
|
||||
if (!(c->flags & CHAN_CLOSE_SENT)) {
|
||||
if (do_send) {
|
||||
chan_send_close2(c);
|
||||
|
@ -85,23 +85,14 @@ static struct wenv {
|
||||
size_t namelen;
|
||||
} wenv_arr[] = {
|
||||
{ NL("ALLUSERSPROFILE=") },
|
||||
{ NL("COMMONPROGRAMFILES=") },
|
||||
{ NL("COMPUTERNAME=") },
|
||||
{ NL("COMSPEC=") },
|
||||
{ NL("CYGWIN=") },
|
||||
{ NL("NUMBER_OF_PROCESSORS=") },
|
||||
{ NL("OS=") },
|
||||
{ NL("PATH=") },
|
||||
{ NL("PATHEXT=") },
|
||||
{ NL("PROCESSOR_ARCHITECTURE=") },
|
||||
{ NL("PROCESSOR_IDENTIFIER=") },
|
||||
{ NL("PROCESSOR_LEVEL=") },
|
||||
{ NL("PROCESSOR_REVISION=") },
|
||||
{ NL("PROGRAMFILES=") },
|
||||
{ NL("SYSTEMDRIVE=") },
|
||||
{ NL("SYSTEMROOT=") },
|
||||
{ NL("TMP=") },
|
||||
{ NL("TEMP=") },
|
||||
{ NL("WINDIR=") }
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: openbsd-compat.h,v 1.46 2008/06/08 17:32:29 dtucker Exp $ */
|
||||
/* $Id: openbsd-compat.h,v 1.49 2010/01/16 12:58:37 dtucker Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999-2003 Damien Miller. All rights reserved.
|
||||
@ -200,6 +200,14 @@ int vasprintf(char **, const char *, va_list);
|
||||
int vsnprintf(char *, size_t, const char *, va_list);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_USER_FROM_UID
|
||||
char *user_from_uid(uid_t, int);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GROUP_FROM_GID
|
||||
char *group_from_gid(gid_t, int);
|
||||
#endif
|
||||
|
||||
void *xmmap(size_t size);
|
||||
char *xcrypt(const char *password, const char *salt);
|
||||
char *shadow_pw(struct passwd *pw);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: openssl-compat.c,v 1.8 2009/03/07 11:22:35 dtucker Exp $ */
|
||||
/* $Id: openssl-compat.c,v 1.9 2010/01/28 23:54:11 dtucker Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au>
|
||||
@ -67,5 +67,6 @@ ssh_SSLeay_add_all_algorithms(void)
|
||||
/* Enable use of crypto hardware */
|
||||
ENGINE_load_builtin_engines();
|
||||
ENGINE_register_all_complete();
|
||||
OPENSSL_config(NULL);
|
||||
}
|
||||
#endif
|
||||
|
@ -374,6 +374,31 @@ aix_restoreauthdb(void)
|
||||
|
||||
# endif /* WITH_AIXAUTHENTICATE */
|
||||
|
||||
# ifdef USE_AIX_KRB_NAME
|
||||
/*
|
||||
* aix_krb5_get_principal_name: returns the user's kerberos client principal name if
|
||||
* configured, otherwise NULL. Caller must free returned string.
|
||||
*/
|
||||
char *
|
||||
aix_krb5_get_principal_name(char *pw_name)
|
||||
{
|
||||
char *authname = NULL, *authdomain = NULL, *principal = NULL;
|
||||
|
||||
setuserdb(S_READ);
|
||||
if (getuserattr(pw_name, S_AUTHDOMAIN, &authdomain, SEC_CHAR) != 0)
|
||||
debug("AIX getuserattr S_AUTHDOMAIN: %s", strerror(errno));
|
||||
if (getuserattr(pw_name, S_AUTHNAME, &authname, SEC_CHAR) != 0)
|
||||
debug("AIX getuserattr S_AUTHNAME: %s", strerror(errno));
|
||||
|
||||
if (authdomain != NULL)
|
||||
xasprintf(&principal, "%s@%s", authname ? authname : pw_name, authdomain);
|
||||
else if (authname != NULL)
|
||||
principal = xstrdup(authname);
|
||||
enduserdb();
|
||||
return principal;
|
||||
}
|
||||
# endif /* USE_AIX_KRB_NAME */
|
||||
|
||||
# if defined(AIX_GETNAMEINFO_HACK) && !defined(BROKEN_ADDRINFO)
|
||||
# undef getnameinfo
|
||||
/*
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: port-aix.h,v 1.31 2009/08/20 06:20:50 dtucker Exp $ */
|
||||
/* $Id: port-aix.h,v 1.32 2009/12/20 23:49:22 dtucker Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
@ -95,6 +95,10 @@ int sys_auth_record_login(const char *, const char *, const char *, Buffer *);
|
||||
# define CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG
|
||||
char *sys_auth_get_lastlogin_msg(const char *, uid_t);
|
||||
# define CUSTOM_FAILED_LOGIN 1
|
||||
# if defined(S_AUTHDOMAIN) && defined (S_AUTHNAME)
|
||||
# define USE_AIX_KRB_NAME
|
||||
char *aix_krb5_get_principal_name(char *);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
void aix_setauthdb(const char *);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: port-linux.c,v 1.5 2008/03/26 20:27:21 dtucker Exp $ */
|
||||
/* $Id: port-linux.c,v 1.8 2010/03/01 04:52:50 dtucker Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005 Daniel Walsh <dwalsh@redhat.com>
|
||||
@ -23,14 +23,17 @@
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#if defined(WITH_SELINUX) || defined(LINUX_OOM_ADJUST)
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef WITH_SELINUX
|
||||
#include "log.h"
|
||||
#include "xmalloc.h"
|
||||
#include "port-linux.h"
|
||||
|
||||
#ifdef WITH_SELINUX
|
||||
#include <selinux/selinux.h>
|
||||
#include <selinux/flask.h>
|
||||
#include <selinux/get_context_list.h>
|
||||
@ -168,4 +171,95 @@ ssh_selinux_setup_pty(char *pwname, const char *tty)
|
||||
freecon(user_ctx);
|
||||
debug3("%s: done", __func__);
|
||||
}
|
||||
|
||||
void
|
||||
ssh_selinux_change_context(const char *newname)
|
||||
{
|
||||
int len, newlen;
|
||||
char *oldctx, *newctx, *cx;
|
||||
|
||||
if (!ssh_selinux_enabled())
|
||||
return;
|
||||
|
||||
if (getcon((security_context_t *)&oldctx) < 0) {
|
||||
logit("%s: getcon failed with %s", __func__, strerror (errno));
|
||||
return;
|
||||
}
|
||||
if ((cx = index(oldctx, ':')) == NULL || (cx = index(cx + 1, ':')) ==
|
||||
NULL) {
|
||||
logit ("%s: unparseable context %s", __func__, oldctx);
|
||||
return;
|
||||
}
|
||||
|
||||
newlen = strlen(oldctx) + strlen(newname) + 1;
|
||||
newctx = xmalloc(newlen);
|
||||
len = cx - oldctx + 1;
|
||||
memcpy(newctx, oldctx, len);
|
||||
strlcpy(newctx + len, newname, newlen - len);
|
||||
if ((cx = index(cx + 1, ':')))
|
||||
strlcat(newctx, cx, newlen);
|
||||
debug3("%s: setting context from '%s' to '%s'", __func__, oldctx,
|
||||
newctx);
|
||||
if (setcon(newctx) < 0)
|
||||
logit("%s: setcon failed with %s", __func__, strerror (errno));
|
||||
xfree(oldctx);
|
||||
xfree(newctx);
|
||||
}
|
||||
#endif /* WITH_SELINUX */
|
||||
|
||||
#ifdef LINUX_OOM_ADJUST
|
||||
#define OOM_ADJ_PATH "/proc/self/oom_adj"
|
||||
/*
|
||||
* The magic "don't kill me", as documented in eg:
|
||||
* http://lxr.linux.no/#linux+v2.6.32/Documentation/filesystems/proc.txt
|
||||
*/
|
||||
#define OOM_ADJ_NOKILL -17
|
||||
|
||||
static int oom_adj_save = INT_MIN;
|
||||
|
||||
/*
|
||||
* Tell the kernel's out-of-memory killer to avoid sshd.
|
||||
* Returns the previous oom_adj value or zero.
|
||||
*/
|
||||
void
|
||||
oom_adjust_setup(void)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
debug3("%s", __func__);
|
||||
if ((fp = fopen(OOM_ADJ_PATH, "r+")) != NULL) {
|
||||
if (fscanf(fp, "%d", &oom_adj_save) != 1)
|
||||
verbose("error reading %s: %s", OOM_ADJ_PATH, strerror(errno));
|
||||
else {
|
||||
rewind(fp);
|
||||
if (fprintf(fp, "%d\n", OOM_ADJ_NOKILL) <= 0)
|
||||
verbose("error writing %s: %s",
|
||||
OOM_ADJ_PATH, strerror(errno));
|
||||
else
|
||||
verbose("Set %s from %d to %d",
|
||||
OOM_ADJ_PATH, oom_adj_save, OOM_ADJ_NOKILL);
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore the saved OOM adjustment */
|
||||
void
|
||||
oom_adjust_restore(void)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
debug3("%s", __func__);
|
||||
if (oom_adj_save == INT_MIN || (fp = fopen(OOM_ADJ_PATH, "w")) == NULL)
|
||||
return;
|
||||
|
||||
if (fprintf(fp, "%d\n", oom_adj_save) <= 0)
|
||||
verbose("error writing %s: %s", OOM_ADJ_PATH, strerror(errno));
|
||||
else
|
||||
verbose("Set %s to %d", OOM_ADJ_PATH, oom_adj_save);
|
||||
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
#endif /* LINUX_OOM_ADJUST */
|
||||
#endif /* WITH_SELINUX || LINUX_OOM_ADJUST */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: port-linux.h,v 1.2 2008/03/26 20:27:21 dtucker Exp $ */
|
||||
/* $Id: port-linux.h,v 1.4 2009/12/08 02:39:48 dtucker Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Damien Miller <djm@openbsd.org>
|
||||
@ -23,6 +23,12 @@
|
||||
int ssh_selinux_enabled(void);
|
||||
void ssh_selinux_setup_pty(char *, const char *);
|
||||
void ssh_selinux_setup_exec_context(char *);
|
||||
void ssh_selinux_change_context(const char *);
|
||||
#endif
|
||||
|
||||
#ifdef LINUX_OOM_ADJUST
|
||||
void oom_adjust_restore(void);
|
||||
void oom_adjust_setup(void);
|
||||
#endif
|
||||
|
||||
#endif /* ! _PORT_LINUX_H */
|
||||
|
114
crypto/openssh/openbsd-compat/pwcache.c
Normal file
114
crypto/openssh/openbsd-compat/pwcache.c
Normal file
@ -0,0 +1,114 @@
|
||||
/* $OpenBSD: pwcache.c,v 1.9 2005/08/08 08:05:34 espie Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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/gen/pwcache.c */
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define NCACHE 64 /* power of 2 */
|
||||
#define MASK (NCACHE - 1) /* bits to store with */
|
||||
|
||||
#ifndef HAVE_USER_FROM_UID
|
||||
char *
|
||||
user_from_uid(uid_t uid, int nouser)
|
||||
{
|
||||
static struct ncache {
|
||||
uid_t uid;
|
||||
char *name;
|
||||
} c_uid[NCACHE];
|
||||
static int pwopen;
|
||||
static char nbuf[15]; /* 32 bits == 10 digits */
|
||||
struct passwd *pw;
|
||||
struct ncache *cp;
|
||||
|
||||
cp = c_uid + (uid & MASK);
|
||||
if (cp->uid != uid || cp->name == NULL) {
|
||||
if (pwopen == 0) {
|
||||
#ifdef HAVE_SETPASSENT
|
||||
setpassent(1);
|
||||
#endif
|
||||
pwopen = 1;
|
||||
}
|
||||
if ((pw = getpwuid(uid)) == NULL) {
|
||||
if (nouser)
|
||||
return (NULL);
|
||||
(void)snprintf(nbuf, sizeof(nbuf), "%u", uid);
|
||||
}
|
||||
cp->uid = uid;
|
||||
if (cp->name != NULL)
|
||||
free(cp->name);
|
||||
cp->name = strdup(pw ? pw->pw_name : nbuf);
|
||||
}
|
||||
return (cp->name);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GROUP_FROM_GID
|
||||
char *
|
||||
group_from_gid(gid_t gid, int nogroup)
|
||||
{
|
||||
static struct ncache {
|
||||
gid_t gid;
|
||||
char *name;
|
||||
} c_gid[NCACHE];
|
||||
static int gropen;
|
||||
static char nbuf[15]; /* 32 bits == 10 digits */
|
||||
struct group *gr;
|
||||
struct ncache *cp;
|
||||
|
||||
cp = c_gid + (gid & MASK);
|
||||
if (cp->gid != gid || cp->name == NULL) {
|
||||
if (gropen == 0) {
|
||||
#ifdef HAVE_SETGROUPENT
|
||||
setgroupent(1);
|
||||
#endif
|
||||
gropen = 1;
|
||||
}
|
||||
if ((gr = getgrgid(gid)) == NULL) {
|
||||
if (nogroup)
|
||||
return (NULL);
|
||||
(void)snprintf(nbuf, sizeof(nbuf), "%u", gid);
|
||||
}
|
||||
cp->gid = gid;
|
||||
if (cp->name != NULL)
|
||||
free(cp->name);
|
||||
cp->name = strdup(gr ? gr->gr_name : nbuf);
|
||||
}
|
||||
return (cp->name);
|
||||
}
|
||||
#endif
|
@ -1,7 +1,7 @@
|
||||
/* $OpenBSD: readpassphrase.c,v 1.18 2005/08/08 08:05:34 espie Exp $ */
|
||||
/* $OpenBSD: readpassphrase.c,v 1.22 2010/01/13 10:20:54 dtucker Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000-2002 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
* Copyright (c) 2000-2002, 2007 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -46,7 +46,7 @@
|
||||
# define _POSIX_VDISABLE VDISABLE
|
||||
#endif
|
||||
|
||||
static volatile sig_atomic_t signo;
|
||||
static volatile sig_atomic_t signo[_NSIG];
|
||||
|
||||
static void handler(int);
|
||||
|
||||
@ -54,7 +54,7 @@ char *
|
||||
readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
|
||||
{
|
||||
ssize_t nr;
|
||||
int input, output, save_errno;
|
||||
int input, output, save_errno, i, need_restart;
|
||||
char ch, *p, *end;
|
||||
struct termios term, oterm;
|
||||
struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm;
|
||||
@ -67,7 +67,11 @@ readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
|
||||
}
|
||||
|
||||
restart:
|
||||
signo = 0;
|
||||
for (i = 0; i < _NSIG; i++)
|
||||
signo[i] = 0;
|
||||
nr = -1;
|
||||
save_errno = 0;
|
||||
need_restart = 0;
|
||||
/*
|
||||
* Read and write to /dev/tty if available. If not, read from
|
||||
* stdin and write to stderr unless a tty is required.
|
||||
@ -117,26 +121,30 @@ readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
|
||||
oterm.c_lflag |= ECHO;
|
||||
}
|
||||
|
||||
if (!(flags & RPP_STDIN))
|
||||
(void)write(output, prompt, strlen(prompt));
|
||||
end = buf + bufsiz - 1;
|
||||
for (p = buf; (nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r';) {
|
||||
if (p < end) {
|
||||
if ((flags & RPP_SEVENBIT))
|
||||
ch &= 0x7f;
|
||||
if (isalpha(ch)) {
|
||||
if ((flags & RPP_FORCELOWER))
|
||||
ch = tolower(ch);
|
||||
if ((flags & RPP_FORCEUPPER))
|
||||
ch = toupper(ch);
|
||||
/* No I/O if we are already backgrounded. */
|
||||
if (signo[SIGTTOU] != 1 && signo[SIGTTIN] != 1) {
|
||||
if (!(flags & RPP_STDIN))
|
||||
(void)write(output, prompt, strlen(prompt));
|
||||
end = buf + bufsiz - 1;
|
||||
p = buf;
|
||||
while ((nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r') {
|
||||
if (p < end) {
|
||||
if ((flags & RPP_SEVENBIT))
|
||||
ch &= 0x7f;
|
||||
if (isalpha(ch)) {
|
||||
if ((flags & RPP_FORCELOWER))
|
||||
ch = (char)tolower(ch);
|
||||
if ((flags & RPP_FORCEUPPER))
|
||||
ch = (char)toupper(ch);
|
||||
}
|
||||
*p++ = ch;
|
||||
}
|
||||
*p++ = ch;
|
||||
}
|
||||
*p = '\0';
|
||||
save_errno = errno;
|
||||
if (!(term.c_lflag & ECHO))
|
||||
(void)write(output, "\n", 1);
|
||||
}
|
||||
*p = '\0';
|
||||
save_errno = errno;
|
||||
if (!(term.c_lflag & ECHO))
|
||||
(void)write(output, "\n", 1);
|
||||
|
||||
/* Restore old terminal settings and signals. */
|
||||
if (memcmp(&term, &oterm, sizeof(term)) != 0) {
|
||||
@ -152,6 +160,7 @@ readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
|
||||
(void)sigaction(SIGTERM, &saveterm, NULL);
|
||||
(void)sigaction(SIGTSTP, &savetstp, NULL);
|
||||
(void)sigaction(SIGTTIN, &savettin, NULL);
|
||||
(void)sigaction(SIGTTOU, &savettou, NULL);
|
||||
if (input != STDIN_FILENO)
|
||||
(void)close(input);
|
||||
|
||||
@ -159,20 +168,25 @@ readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
|
||||
* If we were interrupted by a signal, resend it to ourselves
|
||||
* now that we have restored the signal handlers.
|
||||
*/
|
||||
if (signo) {
|
||||
kill(getpid(), signo);
|
||||
switch (signo) {
|
||||
case SIGTSTP:
|
||||
case SIGTTIN:
|
||||
case SIGTTOU:
|
||||
goto restart;
|
||||
for (i = 0; i < _NSIG; i++) {
|
||||
if (signo[i]) {
|
||||
kill(getpid(), i);
|
||||
switch (i) {
|
||||
case SIGTSTP:
|
||||
case SIGTTIN:
|
||||
case SIGTTOU:
|
||||
need_restart = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (need_restart)
|
||||
goto restart;
|
||||
|
||||
errno = save_errno;
|
||||
if (save_errno)
|
||||
errno = save_errno;
|
||||
return(nr == -1 ? NULL : buf);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
char *
|
||||
getpass(const char *prompt)
|
||||
@ -186,6 +200,6 @@ getpass(const char *prompt)
|
||||
static void handler(int s)
|
||||
{
|
||||
|
||||
signo = s;
|
||||
signo[s] = 1;
|
||||
}
|
||||
#endif /* HAVE_READPASSPHRASE */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pathnames.h,v 1.17 2008/12/29 02:23:26 stevesk Exp $ */
|
||||
/* $OpenBSD: pathnames.h,v 1.19 2010/02/11 20:37:47 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -125,6 +125,11 @@
|
||||
#define _PATH_SSH_KEY_SIGN "/usr/libexec/ssh-keysign"
|
||||
#endif
|
||||
|
||||
/* Location of ssh-pkcs11-helper to support keys in tokens */
|
||||
#ifndef _PATH_SSH_PKCS11_HELPER
|
||||
#define _PATH_SSH_PKCS11_HELPER "/usr/libexec/ssh-pkcs11-helper"
|
||||
#endif
|
||||
|
||||
/* xauth for X11 forwarding */
|
||||
#ifndef _PATH_XAUTH
|
||||
#define _PATH_XAUTH "/usr/local/bin/xauth"
|
||||
|
1357
crypto/openssh/pkcs11.h
Normal file
1357
crypto/openssh/pkcs11.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/* $Id: platform.c,v 1.1 2006/08/30 17:24:41 djm Exp $ */
|
||||
/* $Id: platform.c,v 1.3 2009/12/20 23:49:22 dtucker Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Darren Tucker. All rights reserved.
|
||||
@ -21,6 +21,15 @@
|
||||
|
||||
#include "openbsd-compat/openbsd-compat.h"
|
||||
|
||||
void
|
||||
platform_pre_listen(void)
|
||||
{
|
||||
#ifdef LINUX_OOM_ADJUST
|
||||
/* Adjust out-of-memory killer so listening process is not killed */
|
||||
oom_adjust_setup();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
platform_pre_fork(void)
|
||||
{
|
||||
@ -43,4 +52,17 @@ platform_post_fork_child(void)
|
||||
#ifdef USE_SOLARIS_PROCESS_CONTRACTS
|
||||
solaris_contract_post_fork_child();
|
||||
#endif
|
||||
#ifdef LINUX_OOM_ADJUST
|
||||
oom_adjust_restore();
|
||||
#endif
|
||||
}
|
||||
|
||||
char *
|
||||
platform_krb5_get_principal_name(const char *pw_name)
|
||||
{
|
||||
#ifdef USE_AIX_KRB_NAME
|
||||
return aix_krb5_get_principal_name(pw_name);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: platform.h,v 1.1 2006/08/30 17:24:41 djm Exp $ */
|
||||
/* $Id: platform.h,v 1.4 2010/01/14 01:44:16 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Darren Tucker. All rights reserved.
|
||||
@ -18,6 +18,11 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
void platform_pre_listen(void);
|
||||
void platform_pre_fork(void);
|
||||
void platform_post_fork_parent(pid_t child_pid);
|
||||
void platform_post_fork_child(void);
|
||||
char *platform_get_krb5_client(const char *);
|
||||
char *platform_krb5_get_principal_name(const char *);
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: readconf.c,v 1.177 2009/06/27 09:35:06 andreas Exp $ */
|
||||
/* $OpenBSD: readconf.c,v 1.183 2010/02/08 10:50:20 markus Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -126,7 +126,7 @@ typedef enum {
|
||||
oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
|
||||
oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
|
||||
oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
|
||||
oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
|
||||
oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
|
||||
oClearAllForwardings, oNoHostAuthenticationForLocalhost,
|
||||
oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
|
||||
oAddressFamily, oGssAuthentication, oGssDelegateCreds,
|
||||
@ -209,10 +209,12 @@ static struct {
|
||||
{ "preferredauthentications", oPreferredAuthentications },
|
||||
{ "hostkeyalgorithms", oHostKeyAlgorithms },
|
||||
{ "bindaddress", oBindAddress },
|
||||
#ifdef SMARTCARD
|
||||
{ "smartcarddevice", oSmartcardDevice },
|
||||
#ifdef ENABLE_PKCS11
|
||||
{ "smartcarddevice", oPKCS11Provider },
|
||||
{ "pkcs11provider", oPKCS11Provider },
|
||||
#else
|
||||
{ "smartcarddevice", oUnsupported },
|
||||
{ "pkcs11provider", oUnsupported },
|
||||
#endif
|
||||
{ "clearallforwardings", oClearAllForwardings },
|
||||
{ "enablesshkeysign", oEnableSSHKeysign },
|
||||
@ -626,8 +628,8 @@ process_config_line(Options *options, const char *host,
|
||||
charptr = &options->bind_address;
|
||||
goto parse_string;
|
||||
|
||||
case oSmartcardDevice:
|
||||
charptr = &options->smartcard_device;
|
||||
case oPKCS11Provider:
|
||||
charptr = &options->pkcs11_provider;
|
||||
goto parse_string;
|
||||
|
||||
case oProxyCommand:
|
||||
@ -1075,7 +1077,7 @@ initialize_options(Options * options)
|
||||
options->log_level = SYSLOG_LEVEL_NOT_SET;
|
||||
options->preferred_authentications = NULL;
|
||||
options->bind_address = NULL;
|
||||
options->smartcard_device = NULL;
|
||||
options->pkcs11_provider = NULL;
|
||||
options->enable_ssh_keysign = - 1;
|
||||
options->no_host_authentication_for_localhost = - 1;
|
||||
options->identities_only = - 1;
|
||||
@ -1166,7 +1168,7 @@ fill_default_options(Options * options)
|
||||
/* options->macs, default set in myproposals.h */
|
||||
/* options->hostkeyalgorithms, default set in myproposals.h */
|
||||
if (options->protocol == SSH_PROTO_UNKNOWN)
|
||||
options->protocol = SSH_PROTO_1|SSH_PROTO_2;
|
||||
options->protocol = SSH_PROTO_2;
|
||||
if (options->num_identity_files == 0) {
|
||||
if (options->protocol & SSH_PROTO_1) {
|
||||
len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: readconf.h,v 1.79 2009/06/27 09:35:06 andreas Exp $ */
|
||||
/* $OpenBSD: readconf.h,v 1.82 2010/02/08 10:50:20 markus Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -84,7 +84,7 @@ typedef struct {
|
||||
char *user_hostfile2;
|
||||
char *preferred_authentications;
|
||||
char *bind_address; /* local socket address for connection to sshd */
|
||||
char *smartcard_device; /* Smartcard reader device */
|
||||
char *pkcs11_provider; /* PKCS#11 provider */
|
||||
int verify_host_key_dns; /* Verify host key using DNS */
|
||||
|
||||
int num_identity_files; /* Number of files for RSA/DSA identities. */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: roaming.h,v 1.4 2009/06/27 09:32:43 andreas Exp $ */
|
||||
/* $OpenBSD: roaming.h,v 1.5 2009/10/24 11:11:58 andreas Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2004-2009 AppGate Network Security AB
|
||||
*
|
||||
@ -19,12 +19,17 @@
|
||||
#define ROAMING_H
|
||||
|
||||
#define DEFAULT_ROAMBUF 65536
|
||||
#define ROAMING_REQUEST "roaming@appgate.com"
|
||||
|
||||
extern int roaming_enabled;
|
||||
extern int resume_in_progress;
|
||||
|
||||
void request_roaming(void);
|
||||
int get_snd_buf_size(void);
|
||||
int get_recv_buf_size(void);
|
||||
void add_recv_bytes(u_int64_t);
|
||||
int wait_for_roaming_reconnect(void);
|
||||
void roaming_reply(int, u_int32_t, void *);
|
||||
void set_out_buffer_size(size_t);
|
||||
ssize_t roaming_write(int, const void *, size_t, int *);
|
||||
ssize_t roaming_read(int, void *, size_t, int *);
|
||||
@ -33,6 +38,7 @@ u_int64_t get_recv_bytes(void);
|
||||
u_int64_t get_sent_bytes(void);
|
||||
void roam_set_bytes(u_int64_t, u_int64_t);
|
||||
void resend_bytes(int, u_int64_t *);
|
||||
void calculate_new_key(u_int64_t *, u_int64_t, u_int64_t);
|
||||
int resume_kex(void);
|
||||
|
||||
#endif /* ROAMING */
|
||||
|
280
crypto/openssh/roaming_client.c
Normal file
280
crypto/openssh/roaming_client.c
Normal file
@ -0,0 +1,280 @@
|
||||
/* $OpenBSD: roaming_client.c,v 1.3 2010/01/18 01:50:27 dtucker Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2004-2009 AppGate Network Security AB
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "openbsd-compat/sys-queue.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "buffer.h"
|
||||
#include "channels.h"
|
||||
#include "cipher.h"
|
||||
#include "dispatch.h"
|
||||
#include "clientloop.h"
|
||||
#include "log.h"
|
||||
#include "match.h"
|
||||
#include "misc.h"
|
||||
#include "packet.h"
|
||||
#include "ssh.h"
|
||||
#include "key.h"
|
||||
#include "kex.h"
|
||||
#include "readconf.h"
|
||||
#include "roaming.h"
|
||||
#include "ssh2.h"
|
||||
#include "sshconnect.h"
|
||||
|
||||
/* import */
|
||||
extern Options options;
|
||||
extern char *host;
|
||||
extern struct sockaddr_storage hostaddr;
|
||||
extern int session_resumed;
|
||||
|
||||
static u_int32_t roaming_id;
|
||||
static u_int64_t cookie;
|
||||
static u_int64_t lastseenchall;
|
||||
static u_int64_t key1, key2, oldkey1, oldkey2;
|
||||
|
||||
void
|
||||
roaming_reply(int type, u_int32_t seq, void *ctxt)
|
||||
{
|
||||
if (type == SSH2_MSG_REQUEST_FAILURE) {
|
||||
logit("Server denied roaming");
|
||||
return;
|
||||
}
|
||||
verbose("Roaming enabled");
|
||||
roaming_id = packet_get_int();
|
||||
cookie = packet_get_int64();
|
||||
key1 = oldkey1 = packet_get_int64();
|
||||
key2 = oldkey2 = packet_get_int64();
|
||||
set_out_buffer_size(packet_get_int() + get_snd_buf_size());
|
||||
roaming_enabled = 1;
|
||||
}
|
||||
|
||||
void
|
||||
request_roaming(void)
|
||||
{
|
||||
packet_start(SSH2_MSG_GLOBAL_REQUEST);
|
||||
packet_put_cstring(ROAMING_REQUEST);
|
||||
packet_put_char(1);
|
||||
packet_put_int(get_recv_buf_size());
|
||||
packet_send();
|
||||
client_register_global_confirm(roaming_reply, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
roaming_auth_required(void)
|
||||
{
|
||||
u_char digest[SHA_DIGEST_LENGTH];
|
||||
EVP_MD_CTX md;
|
||||
Buffer b;
|
||||
const EVP_MD *evp_md = EVP_sha1();
|
||||
u_int64_t chall, oldchall;
|
||||
|
||||
chall = packet_get_int64();
|
||||
oldchall = packet_get_int64();
|
||||
if (oldchall != lastseenchall) {
|
||||
key1 = oldkey1;
|
||||
key2 = oldkey2;
|
||||
}
|
||||
lastseenchall = chall;
|
||||
|
||||
buffer_init(&b);
|
||||
buffer_put_int64(&b, cookie);
|
||||
buffer_put_int64(&b, chall);
|
||||
EVP_DigestInit(&md, evp_md);
|
||||
EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
|
||||
EVP_DigestFinal(&md, digest, NULL);
|
||||
buffer_free(&b);
|
||||
|
||||
packet_start(SSH2_MSG_KEX_ROAMING_AUTH);
|
||||
packet_put_int64(key1 ^ get_recv_bytes());
|
||||
packet_put_raw(digest, sizeof(digest));
|
||||
packet_send();
|
||||
|
||||
oldkey1 = key1;
|
||||
oldkey2 = key2;
|
||||
calculate_new_key(&key1, cookie, chall);
|
||||
calculate_new_key(&key2, cookie, chall);
|
||||
|
||||
debug("Received %llu bytes", (unsigned long long)get_recv_bytes());
|
||||
debug("Sent roaming_auth packet");
|
||||
}
|
||||
|
||||
int
|
||||
resume_kex(void)
|
||||
{
|
||||
/*
|
||||
* This should not happen - if the client sends the kex method
|
||||
* resume@appgate.com then the kex is done in roaming_resume().
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
roaming_resume(void)
|
||||
{
|
||||
u_int64_t recv_bytes;
|
||||
char *str = NULL, *kexlist = NULL, *c;
|
||||
int i, type;
|
||||
int timeout_ms = options.connection_timeout * 1000;
|
||||
u_int len;
|
||||
u_int32_t rnd = 0;
|
||||
|
||||
resume_in_progress = 1;
|
||||
|
||||
/* Exchange banners */
|
||||
ssh_exchange_identification(timeout_ms);
|
||||
packet_set_nonblocking();
|
||||
|
||||
/* Send a kexinit message with resume@appgate.com as only kex algo */
|
||||
packet_start(SSH2_MSG_KEXINIT);
|
||||
for (i = 0; i < KEX_COOKIE_LEN; i++) {
|
||||
if (i % 4 == 0)
|
||||
rnd = arc4random();
|
||||
packet_put_char(rnd & 0xff);
|
||||
rnd >>= 8;
|
||||
}
|
||||
packet_put_cstring(KEX_RESUME);
|
||||
for (i = 1; i < PROPOSAL_MAX; i++) {
|
||||
/* kex algorithm added so start with i=1 and not 0 */
|
||||
packet_put_cstring(""); /* Not used when we resume */
|
||||
}
|
||||
packet_put_char(1); /* first kex_packet follows */
|
||||
packet_put_int(0); /* reserved */
|
||||
packet_send();
|
||||
|
||||
/* Assume that resume@appgate.com will be accepted */
|
||||
packet_start(SSH2_MSG_KEX_ROAMING_RESUME);
|
||||
packet_put_int(roaming_id);
|
||||
packet_send();
|
||||
|
||||
/* Read the server's kexinit and check for resume@appgate.com */
|
||||
if ((type = packet_read()) != SSH2_MSG_KEXINIT) {
|
||||
debug("expected kexinit on resume, got %d", type);
|
||||
goto fail;
|
||||
}
|
||||
for (i = 0; i < KEX_COOKIE_LEN; i++)
|
||||
(void)packet_get_char();
|
||||
kexlist = packet_get_string(&len);
|
||||
if (!kexlist
|
||||
|| (str = match_list(KEX_RESUME, kexlist, NULL)) == NULL) {
|
||||
debug("server doesn't allow resume");
|
||||
goto fail;
|
||||
}
|
||||
xfree(str);
|
||||
for (i = 1; i < PROPOSAL_MAX; i++) {
|
||||
/* kex algorithm taken care of so start with i=1 and not 0 */
|
||||
xfree(packet_get_string(&len));
|
||||
}
|
||||
i = packet_get_char(); /* first_kex_packet_follows */
|
||||
if (i && (c = strchr(kexlist, ',')))
|
||||
*c = 0;
|
||||
if (i && strcmp(kexlist, KEX_RESUME)) {
|
||||
debug("server's kex guess (%s) was wrong, skipping", kexlist);
|
||||
(void)packet_read(); /* Wrong guess - discard packet */
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the ROAMING_AUTH_REQUIRED challenge from the server and
|
||||
* send ROAMING_AUTH
|
||||
*/
|
||||
if ((type = packet_read()) != SSH2_MSG_KEX_ROAMING_AUTH_REQUIRED) {
|
||||
debug("expected roaming_auth_required, got %d", type);
|
||||
goto fail;
|
||||
}
|
||||
roaming_auth_required();
|
||||
|
||||
/* Read ROAMING_AUTH_OK from the server */
|
||||
if ((type = packet_read()) != SSH2_MSG_KEX_ROAMING_AUTH_OK) {
|
||||
debug("expected roaming_auth_ok, got %d", type);
|
||||
goto fail;
|
||||
}
|
||||
recv_bytes = packet_get_int64() ^ oldkey2;
|
||||
debug("Peer received %llu bytes", (unsigned long long)recv_bytes);
|
||||
resend_bytes(packet_get_connection_out(), &recv_bytes);
|
||||
|
||||
resume_in_progress = 0;
|
||||
|
||||
session_resumed = 1; /* Tell clientloop */
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (kexlist)
|
||||
xfree(kexlist);
|
||||
if (packet_get_connection_in() == packet_get_connection_out())
|
||||
close(packet_get_connection_in());
|
||||
else {
|
||||
close(packet_get_connection_in());
|
||||
close(packet_get_connection_out());
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
wait_for_roaming_reconnect(void)
|
||||
{
|
||||
static int reenter_guard = 0;
|
||||
int timeout_ms = options.connection_timeout * 1000;
|
||||
int c;
|
||||
|
||||
if (reenter_guard != 0)
|
||||
fatal("Server refused resume, roaming timeout may be exceeded");
|
||||
reenter_guard = 1;
|
||||
|
||||
fprintf(stderr, "[connection suspended, press return to resume]");
|
||||
fflush(stderr);
|
||||
packet_backup_state();
|
||||
/* TODO Perhaps we should read from tty here */
|
||||
while ((c = fgetc(stdin)) != EOF) {
|
||||
if (c == 'Z' - 64) {
|
||||
kill(getpid(), SIGTSTP);
|
||||
continue;
|
||||
}
|
||||
if (c != '\n' && c != '\r')
|
||||
continue;
|
||||
|
||||
if (ssh_connect(host, &hostaddr, options.port,
|
||||
options.address_family, 1, &timeout_ms,
|
||||
options.tcp_keep_alive, options.use_privileged_port,
|
||||
options.proxy_command) == 0 && roaming_resume() == 0) {
|
||||
packet_restore_state();
|
||||
reenter_guard = 0;
|
||||
fprintf(stderr, "[connection resumed]\n");
|
||||
fflush(stderr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr, "[reconnect failed, press return to retry]");
|
||||
fflush(stderr);
|
||||
}
|
||||
fprintf(stderr, "[exiting]\n");
|
||||
fflush(stderr);
|
||||
exit(0);
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: roaming_common.c,v 1.5 2009/06/27 09:32:43 andreas Exp $ */
|
||||
/* $OpenBSD: roaming_common.c,v 1.8 2010/01/12 00:59:29 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2004-2009 AppGate Network Security AB
|
||||
*
|
||||
@ -52,9 +52,9 @@ int
|
||||
get_snd_buf_size()
|
||||
{
|
||||
int fd = packet_get_connection_out();
|
||||
int optval, optvallen;
|
||||
int optval;
|
||||
socklen_t optvallen = sizeof(optval);
|
||||
|
||||
optvallen = sizeof(optval);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &optval, &optvallen) != 0)
|
||||
optval = DEFAULT_ROAMBUF;
|
||||
return optval;
|
||||
@ -64,9 +64,9 @@ int
|
||||
get_recv_buf_size()
|
||||
{
|
||||
int fd = packet_get_connection_in();
|
||||
int optval, optvallen;
|
||||
int optval;
|
||||
socklen_t optvallen = sizeof(optval);
|
||||
|
||||
optvallen = sizeof(optval);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &optval, &optvallen) != 0)
|
||||
optval = DEFAULT_ROAMBUF;
|
||||
return optval;
|
||||
@ -145,8 +145,16 @@ roaming_write(int fd, const void *buf, size_t count, int *cont)
|
||||
if (out_buf_size > 0)
|
||||
buf_append(buf, ret);
|
||||
}
|
||||
debug3("Wrote %ld bytes for a total of %llu", (long)ret,
|
||||
(unsigned long long)write_bytes);
|
||||
if (out_buf_size > 0 &&
|
||||
(ret == 0 || (ret == -1 && errno == EPIPE))) {
|
||||
if (wait_for_roaming_reconnect() != 0) {
|
||||
ret = 0;
|
||||
*cont = 1;
|
||||
} else {
|
||||
ret = -1;
|
||||
errno = EAGAIN;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -158,6 +166,15 @@ roaming_read(int fd, void *buf, size_t count, int *cont)
|
||||
if (!resume_in_progress) {
|
||||
read_bytes += ret;
|
||||
}
|
||||
} else if (out_buf_size > 0 &&
|
||||
(ret == 0 || (ret == -1 && (errno == ECONNRESET
|
||||
|| errno == ECONNABORTED || errno == ETIMEDOUT
|
||||
|| errno == EHOSTUNREACH)))) {
|
||||
debug("roaming_read failed for %d ret=%ld errno=%d",
|
||||
fd, (long)ret, errno);
|
||||
ret = 0;
|
||||
if (wait_for_roaming_reconnect() == 0)
|
||||
*cont = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -199,3 +216,29 @@ resend_bytes(int fd, u_int64_t *offset)
|
||||
atomicio(vwrite, fd, out_buf + (out_last - needed), needed);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Caclulate a new key after a reconnect
|
||||
*/
|
||||
void
|
||||
calculate_new_key(u_int64_t *key, u_int64_t cookie, u_int64_t challenge)
|
||||
{
|
||||
const EVP_MD *md = EVP_sha1();
|
||||
EVP_MD_CTX ctx;
|
||||
char hash[EVP_MAX_MD_SIZE];
|
||||
Buffer b;
|
||||
|
||||
buffer_init(&b);
|
||||
buffer_put_int64(&b, *key);
|
||||
buffer_put_int64(&b, cookie);
|
||||
buffer_put_int64(&b, challenge);
|
||||
|
||||
EVP_DigestInit(&ctx, md);
|
||||
EVP_DigestUpdate(&ctx, buffer_ptr(&b), buffer_len(&b));
|
||||
EVP_DigestFinal(&ctx, hash, NULL);
|
||||
|
||||
buffer_clear(&b);
|
||||
buffer_append(&b, hash, EVP_MD_size(md));
|
||||
*key = buffer_get_int64(&b);
|
||||
buffer_free(&b);
|
||||
}
|
||||
|
31
crypto/openssh/roaming_serv.c
Normal file
31
crypto/openssh/roaming_serv.c
Normal file
@ -0,0 +1,31 @@
|
||||
/* $OpenBSD: roaming_serv.c,v 1.1 2009/10/24 11:18:23 andreas Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2004-2009 AppGate Network Security AB
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "roaming.h"
|
||||
|
||||
/*
|
||||
* Wait for the roaming client to reconnect. Returns 0 if a connect ocurred.
|
||||
*/
|
||||
int
|
||||
wait_for_roaming_reconnect(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
@ -1,532 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Juha Yrjölä. All rights reserved.
|
||||
* Copyright (c) 2001 Markus Friedl.
|
||||
*
|
||||
* 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 AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#if defined(SMARTCARD) && defined(USE_OPENSC)
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <opensc/opensc.h>
|
||||
#include <opensc/pkcs15.h>
|
||||
|
||||
#include "key.h"
|
||||
#include "log.h"
|
||||
#include "xmalloc.h"
|
||||
#include "misc.h"
|
||||
#include "scard.h"
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x00907000L && defined(CRYPTO_LOCK_ENGINE)
|
||||
#define USE_ENGINE
|
||||
#define RSA_get_default_method RSA_get_default_openssl_method
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef USE_ENGINE
|
||||
#include <openssl/engine.h>
|
||||
#define sc_get_rsa sc_get_engine
|
||||
#else
|
||||
#define sc_get_rsa sc_get_rsa_method
|
||||
#endif
|
||||
|
||||
static int sc_reader_id;
|
||||
static sc_context_t *ctx = NULL;
|
||||
static sc_card_t *card = NULL;
|
||||
static sc_pkcs15_card_t *p15card = NULL;
|
||||
|
||||
static char *sc_pin = NULL;
|
||||
|
||||
struct sc_priv_data
|
||||
{
|
||||
struct sc_pkcs15_id cert_id;
|
||||
int ref_count;
|
||||
};
|
||||
|
||||
void
|
||||
sc_close(void)
|
||||
{
|
||||
if (p15card) {
|
||||
sc_pkcs15_unbind(p15card);
|
||||
p15card = NULL;
|
||||
}
|
||||
if (card) {
|
||||
sc_disconnect_card(card, 0);
|
||||
card = NULL;
|
||||
}
|
||||
if (ctx) {
|
||||
sc_release_context(ctx);
|
||||
ctx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
sc_init(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = sc_establish_context(&ctx, "openssh");
|
||||
if (r)
|
||||
goto err;
|
||||
if (sc_reader_id >= ctx->reader_count) {
|
||||
r = SC_ERROR_NO_READERS_FOUND;
|
||||
error("Illegal reader number %d (max %d)", sc_reader_id,
|
||||
ctx->reader_count -1);
|
||||
goto err;
|
||||
}
|
||||
r = sc_connect_card(ctx->reader[sc_reader_id], 0, &card);
|
||||
if (r)
|
||||
goto err;
|
||||
r = sc_pkcs15_bind(card, &p15card);
|
||||
if (r)
|
||||
goto err;
|
||||
return 0;
|
||||
err:
|
||||
sc_close();
|
||||
return r;
|
||||
}
|
||||
|
||||
/* private key operations */
|
||||
|
||||
static int
|
||||
sc_prkey_op_init(RSA *rsa, struct sc_pkcs15_object **key_obj_out,
|
||||
unsigned int usage)
|
||||
{
|
||||
int r;
|
||||
struct sc_priv_data *priv;
|
||||
struct sc_pkcs15_object *key_obj;
|
||||
struct sc_pkcs15_prkey_info *key;
|
||||
struct sc_pkcs15_object *pin_obj;
|
||||
struct sc_pkcs15_pin_info *pin;
|
||||
|
||||
priv = (struct sc_priv_data *) RSA_get_app_data(rsa);
|
||||
if (priv == NULL)
|
||||
return -1;
|
||||
if (p15card == NULL) {
|
||||
sc_close();
|
||||
r = sc_init();
|
||||
if (r) {
|
||||
error("SmartCard init failed: %s", sc_strerror(r));
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
r = sc_pkcs15_find_prkey_by_id_usage(p15card, &priv->cert_id,
|
||||
usage, &key_obj);
|
||||
if (r) {
|
||||
error("Unable to find private key from SmartCard: %s",
|
||||
sc_strerror(r));
|
||||
goto err;
|
||||
}
|
||||
key = key_obj->data;
|
||||
r = sc_pkcs15_find_pin_by_auth_id(p15card, &key_obj->auth_id,
|
||||
&pin_obj);
|
||||
if (r == SC_ERROR_OBJECT_NOT_FOUND) {
|
||||
/* no pin required */
|
||||
r = sc_lock(card);
|
||||
if (r) {
|
||||
error("Unable to lock smartcard: %s", sc_strerror(r));
|
||||
goto err;
|
||||
}
|
||||
*key_obj_out = key_obj;
|
||||
return 0;
|
||||
} else if (r) {
|
||||
error("Unable to find PIN object from SmartCard: %s",
|
||||
sc_strerror(r));
|
||||
goto err;
|
||||
}
|
||||
pin = pin_obj->data;
|
||||
r = sc_lock(card);
|
||||
if (r) {
|
||||
error("Unable to lock smartcard: %s", sc_strerror(r));
|
||||
goto err;
|
||||
}
|
||||
if (sc_pin != NULL) {
|
||||
r = sc_pkcs15_verify_pin(p15card, pin, sc_pin,
|
||||
strlen(sc_pin));
|
||||
if (r) {
|
||||
sc_unlock(card);
|
||||
error("PIN code verification failed: %s",
|
||||
sc_strerror(r));
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
*key_obj_out = key_obj;
|
||||
return 0;
|
||||
err:
|
||||
sc_close();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define SC_USAGE_DECRYPT SC_PKCS15_PRKEY_USAGE_DECRYPT | \
|
||||
SC_PKCS15_PRKEY_USAGE_UNWRAP
|
||||
|
||||
static int
|
||||
sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa,
|
||||
int padding)
|
||||
{
|
||||
struct sc_pkcs15_object *key_obj;
|
||||
int r;
|
||||
|
||||
if (padding != RSA_PKCS1_PADDING)
|
||||
return -1;
|
||||
r = sc_prkey_op_init(rsa, &key_obj, SC_USAGE_DECRYPT);
|
||||
if (r)
|
||||
return -1;
|
||||
r = sc_pkcs15_decipher(p15card, key_obj, SC_ALGORITHM_RSA_PAD_PKCS1,
|
||||
from, flen, to, flen);
|
||||
sc_unlock(card);
|
||||
if (r < 0) {
|
||||
error("sc_pkcs15_decipher() failed: %s", sc_strerror(r));
|
||||
goto err;
|
||||
}
|
||||
return r;
|
||||
err:
|
||||
sc_close();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define SC_USAGE_SIGN SC_PKCS15_PRKEY_USAGE_SIGN | \
|
||||
SC_PKCS15_PRKEY_USAGE_SIGNRECOVER
|
||||
|
||||
static int
|
||||
sc_sign(int type, u_char *m, unsigned int m_len,
|
||||
unsigned char *sigret, unsigned int *siglen, RSA *rsa)
|
||||
{
|
||||
struct sc_pkcs15_object *key_obj;
|
||||
int r;
|
||||
unsigned long flags = 0;
|
||||
|
||||
/* XXX: sc_prkey_op_init will search for a pkcs15 private
|
||||
* key object with the sign or signrecover usage flag set.
|
||||
* If the signing key has only the non-repudiation flag set
|
||||
* the key will be rejected as using a non-repudiation key
|
||||
* for authentication is not recommended. Note: This does not
|
||||
* prevent the use of a non-repudiation key for authentication
|
||||
* if the sign or signrecover flag is set as well.
|
||||
*/
|
||||
r = sc_prkey_op_init(rsa, &key_obj, SC_USAGE_SIGN);
|
||||
if (r)
|
||||
return -1;
|
||||
/* FIXME: length of sigret correct? */
|
||||
/* FIXME: check 'type' and modify flags accordingly */
|
||||
flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_SHA1;
|
||||
r = sc_pkcs15_compute_signature(p15card, key_obj, flags,
|
||||
m, m_len, sigret, RSA_size(rsa));
|
||||
sc_unlock(card);
|
||||
if (r < 0) {
|
||||
error("sc_pkcs15_compute_signature() failed: %s",
|
||||
sc_strerror(r));
|
||||
goto err;
|
||||
}
|
||||
*siglen = r;
|
||||
return 1;
|
||||
err:
|
||||
sc_close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sc_private_encrypt(int flen, u_char *from, u_char *to, RSA *rsa,
|
||||
int padding)
|
||||
{
|
||||
error("Private key encryption not supported");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* called on free */
|
||||
|
||||
static int (*orig_finish)(RSA *rsa) = NULL;
|
||||
|
||||
static int
|
||||
sc_finish(RSA *rsa)
|
||||
{
|
||||
struct sc_priv_data *priv;
|
||||
|
||||
priv = RSA_get_app_data(rsa);
|
||||
priv->ref_count--;
|
||||
if (priv->ref_count == 0) {
|
||||
free(priv);
|
||||
sc_close();
|
||||
}
|
||||
if (orig_finish)
|
||||
orig_finish(rsa);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* engine for overloading private key operations */
|
||||
|
||||
static RSA_METHOD *
|
||||
sc_get_rsa_method(void)
|
||||
{
|
||||
static RSA_METHOD smart_rsa;
|
||||
const RSA_METHOD *def = RSA_get_default_method();
|
||||
|
||||
/* use the OpenSSL version */
|
||||
memcpy(&smart_rsa, def, sizeof(smart_rsa));
|
||||
|
||||
smart_rsa.name = "opensc";
|
||||
|
||||
/* overload */
|
||||
smart_rsa.rsa_priv_enc = sc_private_encrypt;
|
||||
smart_rsa.rsa_priv_dec = sc_private_decrypt;
|
||||
smart_rsa.rsa_sign = sc_sign;
|
||||
|
||||
/* save original */
|
||||
orig_finish = def->finish;
|
||||
smart_rsa.finish = sc_finish;
|
||||
|
||||
return &smart_rsa;
|
||||
}
|
||||
|
||||
#ifdef USE_ENGINE
|
||||
static ENGINE *
|
||||
sc_get_engine(void)
|
||||
{
|
||||
static ENGINE *smart_engine = NULL;
|
||||
|
||||
if ((smart_engine = ENGINE_new()) == NULL)
|
||||
fatal("ENGINE_new failed");
|
||||
|
||||
ENGINE_set_id(smart_engine, "opensc");
|
||||
ENGINE_set_name(smart_engine, "OpenSC");
|
||||
|
||||
ENGINE_set_RSA(smart_engine, sc_get_rsa_method());
|
||||
ENGINE_set_DSA(smart_engine, DSA_get_default_openssl_method());
|
||||
ENGINE_set_DH(smart_engine, DH_get_default_openssl_method());
|
||||
ENGINE_set_RAND(smart_engine, RAND_SSLeay());
|
||||
ENGINE_set_BN_mod_exp(smart_engine, BN_mod_exp);
|
||||
|
||||
return smart_engine;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
convert_rsa_to_rsa1(Key * in, Key * out)
|
||||
{
|
||||
struct sc_priv_data *priv;
|
||||
|
||||
out->rsa->flags = in->rsa->flags;
|
||||
out->flags = in->flags;
|
||||
RSA_set_method(out->rsa, RSA_get_method(in->rsa));
|
||||
BN_copy(out->rsa->n, in->rsa->n);
|
||||
BN_copy(out->rsa->e, in->rsa->e);
|
||||
priv = RSA_get_app_data(in->rsa);
|
||||
priv->ref_count++;
|
||||
RSA_set_app_data(out->rsa, priv);
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
sc_read_pubkey(Key * k, const struct sc_pkcs15_object *cert_obj)
|
||||
{
|
||||
int r;
|
||||
sc_pkcs15_cert_t *cert = NULL;
|
||||
struct sc_priv_data *priv = NULL;
|
||||
sc_pkcs15_cert_info_t *cinfo = cert_obj->data;
|
||||
|
||||
X509 *x509 = NULL;
|
||||
EVP_PKEY *pubkey = NULL;
|
||||
u8 *p;
|
||||
char *tmp;
|
||||
|
||||
debug("sc_read_pubkey() with cert id %02X", cinfo->id.value[0]);
|
||||
r = sc_pkcs15_read_certificate(p15card, cinfo, &cert);
|
||||
if (r) {
|
||||
logit("Certificate read failed: %s", sc_strerror(r));
|
||||
goto err;
|
||||
}
|
||||
x509 = X509_new();
|
||||
if (x509 == NULL) {
|
||||
r = -1;
|
||||
goto err;
|
||||
}
|
||||
p = cert->data;
|
||||
if (!d2i_X509(&x509, &p, cert->data_len)) {
|
||||
logit("Unable to parse X.509 certificate");
|
||||
r = -1;
|
||||
goto err;
|
||||
}
|
||||
sc_pkcs15_free_certificate(cert);
|
||||
cert = NULL;
|
||||
pubkey = X509_get_pubkey(x509);
|
||||
X509_free(x509);
|
||||
x509 = NULL;
|
||||
if (pubkey->type != EVP_PKEY_RSA) {
|
||||
logit("Public key is of unknown type");
|
||||
r = -1;
|
||||
goto err;
|
||||
}
|
||||
k->rsa = EVP_PKEY_get1_RSA(pubkey);
|
||||
EVP_PKEY_free(pubkey);
|
||||
|
||||
k->rsa->flags |= RSA_FLAG_SIGN_VER;
|
||||
RSA_set_method(k->rsa, sc_get_rsa_method());
|
||||
priv = xmalloc(sizeof(struct sc_priv_data));
|
||||
priv->cert_id = cinfo->id;
|
||||
priv->ref_count = 1;
|
||||
RSA_set_app_data(k->rsa, priv);
|
||||
|
||||
k->flags = KEY_FLAG_EXT;
|
||||
tmp = key_fingerprint(k, SSH_FP_MD5, SSH_FP_HEX);
|
||||
debug("fingerprint %d %s", key_size(k), tmp);
|
||||
xfree(tmp);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
if (cert)
|
||||
sc_pkcs15_free_certificate(cert);
|
||||
if (pubkey)
|
||||
EVP_PKEY_free(pubkey);
|
||||
if (x509)
|
||||
X509_free(x509);
|
||||
return r;
|
||||
}
|
||||
|
||||
Key **
|
||||
sc_get_keys(const char *id, const char *pin)
|
||||
{
|
||||
Key *k, **keys;
|
||||
int i, r, real_count = 0, key_count;
|
||||
sc_pkcs15_id_t cert_id;
|
||||
sc_pkcs15_object_t *certs[32];
|
||||
char *buf = xstrdup(id), *p;
|
||||
|
||||
debug("sc_get_keys called: id = %s", id);
|
||||
|
||||
if (sc_pin != NULL)
|
||||
xfree(sc_pin);
|
||||
sc_pin = (pin == NULL) ? NULL : xstrdup(pin);
|
||||
|
||||
cert_id.len = 0;
|
||||
if ((p = strchr(buf, ':')) != NULL) {
|
||||
*p = 0;
|
||||
p++;
|
||||
sc_pkcs15_hex_string_to_id(p, &cert_id);
|
||||
}
|
||||
r = sscanf(buf, "%d", &sc_reader_id);
|
||||
xfree(buf);
|
||||
if (r != 1)
|
||||
goto err;
|
||||
if (p15card == NULL) {
|
||||
sc_close();
|
||||
r = sc_init();
|
||||
if (r) {
|
||||
error("Smartcard init failed: %s", sc_strerror(r));
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (cert_id.len) {
|
||||
r = sc_pkcs15_find_cert_by_id(p15card, &cert_id, &certs[0]);
|
||||
if (r < 0)
|
||||
goto err;
|
||||
key_count = 1;
|
||||
} else {
|
||||
r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_CERT_X509,
|
||||
certs, 32);
|
||||
if (r == 0) {
|
||||
logit("No certificates found on smartcard");
|
||||
r = -1;
|
||||
goto err;
|
||||
} else if (r < 0) {
|
||||
error("Certificate enumeration failed: %s",
|
||||
sc_strerror(r));
|
||||
goto err;
|
||||
}
|
||||
key_count = r;
|
||||
}
|
||||
if (key_count > 1024)
|
||||
fatal("Too many keys (%u), expected <= 1024", key_count);
|
||||
keys = xcalloc(key_count * 2 + 1, sizeof(Key *));
|
||||
for (i = 0; i < key_count; i++) {
|
||||
sc_pkcs15_object_t *tmp_obj = NULL;
|
||||
cert_id = ((sc_pkcs15_cert_info_t *)(certs[i]->data))->id;
|
||||
if (sc_pkcs15_find_prkey_by_id(p15card, &cert_id, &tmp_obj))
|
||||
/* skip the public key (certificate) if no
|
||||
* corresponding private key is present */
|
||||
continue;
|
||||
k = key_new(KEY_RSA);
|
||||
if (k == NULL)
|
||||
break;
|
||||
r = sc_read_pubkey(k, certs[i]);
|
||||
if (r) {
|
||||
error("sc_read_pubkey failed: %s", sc_strerror(r));
|
||||
key_free(k);
|
||||
continue;
|
||||
}
|
||||
keys[real_count] = k;
|
||||
real_count++;
|
||||
k = key_new(KEY_RSA1);
|
||||
if (k == NULL)
|
||||
break;
|
||||
convert_rsa_to_rsa1(keys[real_count-1], k);
|
||||
keys[real_count] = k;
|
||||
real_count++;
|
||||
}
|
||||
keys[real_count] = NULL;
|
||||
|
||||
return keys;
|
||||
err:
|
||||
sc_close();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
sc_put_key(Key *prv, const char *id)
|
||||
{
|
||||
error("key uploading not yet supported");
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *
|
||||
sc_get_key_label(Key *key)
|
||||
{
|
||||
int r;
|
||||
const struct sc_priv_data *priv;
|
||||
struct sc_pkcs15_object *key_obj;
|
||||
|
||||
priv = (const struct sc_priv_data *) RSA_get_app_data(key->rsa);
|
||||
if (priv == NULL || p15card == NULL) {
|
||||
logit("SmartCard key not loaded");
|
||||
/* internal error => return default label */
|
||||
return xstrdup("smartcard key");
|
||||
}
|
||||
r = sc_pkcs15_find_prkey_by_id(p15card, &priv->cert_id, &key_obj);
|
||||
if (r) {
|
||||
logit("Unable to find private key from SmartCard: %s",
|
||||
sc_strerror(r));
|
||||
return xstrdup("smartcard key");
|
||||
}
|
||||
if (key_obj == NULL || key_obj->label == NULL)
|
||||
/* the optional PKCS#15 label does not exists
|
||||
* => return the default label */
|
||||
return xstrdup("smartcard key");
|
||||
return xstrdup(key_obj->label);
|
||||
}
|
||||
|
||||
#endif /* SMARTCARD */
|
@ -1,571 +0,0 @@
|
||||
/* $OpenBSD: scard.c,v 1.36 2006/11/06 21:25:28 markus Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#if defined(SMARTCARD) && defined(USE_SECTOK)
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <sectok.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "key.h"
|
||||
#include "log.h"
|
||||
#include "misc.h"
|
||||
#include "scard.h"
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x00907000L
|
||||
#define USE_ENGINE
|
||||
#define RSA_get_default_method RSA_get_default_openssl_method
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef USE_ENGINE
|
||||
#include <openssl/engine.h>
|
||||
#define sc_get_rsa sc_get_engine
|
||||
#else
|
||||
#define sc_get_rsa sc_get_rsa_method
|
||||
#endif
|
||||
|
||||
#define CLA_SSH 0x05
|
||||
#define INS_DECRYPT 0x10
|
||||
#define INS_GET_KEYLENGTH 0x20
|
||||
#define INS_GET_PUBKEY 0x30
|
||||
#define INS_GET_RESPONSE 0xc0
|
||||
|
||||
#define MAX_BUF_SIZE 256
|
||||
|
||||
u_char DEFAUT0[] = {0xad, 0x9f, 0x61, 0xfe, 0xfa, 0x20, 0xce, 0x63};
|
||||
|
||||
static int sc_fd = -1;
|
||||
static char *sc_reader_id = NULL;
|
||||
static char *sc_pin = NULL;
|
||||
static int cla = 0x00; /* class */
|
||||
|
||||
static void sc_mk_digest(const char *pin, u_char *digest);
|
||||
static int get_AUT0(u_char *aut0);
|
||||
static int try_AUT0(void);
|
||||
|
||||
/* interface to libsectok */
|
||||
|
||||
static int
|
||||
sc_open(void)
|
||||
{
|
||||
int sw;
|
||||
|
||||
if (sc_fd >= 0)
|
||||
return sc_fd;
|
||||
|
||||
sc_fd = sectok_friendly_open(sc_reader_id, STONOWAIT, &sw);
|
||||
if (sc_fd < 0) {
|
||||
error("sectok_open failed: %s", sectok_get_sw(sw));
|
||||
return SCARD_ERROR_FAIL;
|
||||
}
|
||||
if (! sectok_cardpresent(sc_fd)) {
|
||||
debug("smartcard in reader %s not present, skipping",
|
||||
sc_reader_id);
|
||||
sc_close();
|
||||
return SCARD_ERROR_NOCARD;
|
||||
}
|
||||
if (sectok_reset(sc_fd, 0, NULL, &sw) <= 0) {
|
||||
error("sectok_reset failed: %s", sectok_get_sw(sw));
|
||||
sc_fd = -1;
|
||||
return SCARD_ERROR_FAIL;
|
||||
}
|
||||
if ((cla = cyberflex_inq_class(sc_fd)) < 0)
|
||||
cla = 0;
|
||||
|
||||
debug("sc_open ok %d", sc_fd);
|
||||
return sc_fd;
|
||||
}
|
||||
|
||||
static int
|
||||
sc_enable_applet(void)
|
||||
{
|
||||
static u_char aid[] = {0xfc, 0x53, 0x73, 0x68, 0x2e, 0x62, 0x69, 0x6e};
|
||||
int sw = 0;
|
||||
|
||||
/* select applet id */
|
||||
sectok_apdu(sc_fd, cla, 0xa4, 0x04, 0, sizeof aid, aid, 0, NULL, &sw);
|
||||
if (!sectok_swOK(sw)) {
|
||||
error("sectok_apdu failed: %s", sectok_get_sw(sw));
|
||||
sc_close();
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sc_init(void)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = sc_open();
|
||||
if (status == SCARD_ERROR_NOCARD) {
|
||||
return SCARD_ERROR_NOCARD;
|
||||
}
|
||||
if (status < 0) {
|
||||
error("sc_open failed");
|
||||
return status;
|
||||
}
|
||||
if (sc_enable_applet() < 0) {
|
||||
error("sc_enable_applet failed");
|
||||
return SCARD_ERROR_APPLET;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sc_read_pubkey(Key * k)
|
||||
{
|
||||
u_char buf[2], *n;
|
||||
char *p;
|
||||
int len, sw, status = -1;
|
||||
|
||||
len = sw = 0;
|
||||
n = NULL;
|
||||
|
||||
if (sc_fd < 0) {
|
||||
if (sc_init() < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* get key size */
|
||||
sectok_apdu(sc_fd, CLA_SSH, INS_GET_KEYLENGTH, 0, 0, 0, NULL,
|
||||
sizeof(buf), buf, &sw);
|
||||
if (!sectok_swOK(sw)) {
|
||||
error("could not obtain key length: %s", sectok_get_sw(sw));
|
||||
goto err;
|
||||
}
|
||||
len = (buf[0] << 8) | buf[1];
|
||||
len /= 8;
|
||||
debug("INS_GET_KEYLENGTH: len %d sw %s", len, sectok_get_sw(sw));
|
||||
|
||||
n = xmalloc(len);
|
||||
/* get n */
|
||||
sectok_apdu(sc_fd, CLA_SSH, INS_GET_PUBKEY, 0, 0, 0, NULL, len, n, &sw);
|
||||
|
||||
if (sw == 0x6982) {
|
||||
if (try_AUT0() < 0)
|
||||
goto err;
|
||||
sectok_apdu(sc_fd, CLA_SSH, INS_GET_PUBKEY, 0, 0, 0, NULL, len, n, &sw);
|
||||
}
|
||||
if (!sectok_swOK(sw)) {
|
||||
error("could not obtain public key: %s", sectok_get_sw(sw));
|
||||
goto err;
|
||||
}
|
||||
|
||||
debug("INS_GET_KEYLENGTH: sw %s", sectok_get_sw(sw));
|
||||
|
||||
if (BN_bin2bn(n, len, k->rsa->n) == NULL) {
|
||||
error("c_read_pubkey: BN_bin2bn failed");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* currently the java applet just stores 'n' */
|
||||
if (!BN_set_word(k->rsa->e, 35)) {
|
||||
error("c_read_pubkey: BN_set_word(e, 35) failed");
|
||||
goto err;
|
||||
}
|
||||
|
||||
status = 0;
|
||||
p = key_fingerprint(k, SSH_FP_MD5, SSH_FP_HEX);
|
||||
debug("fingerprint %u %s", key_size(k), p);
|
||||
xfree(p);
|
||||
|
||||
err:
|
||||
if (n != NULL)
|
||||
xfree(n);
|
||||
sc_close();
|
||||
return status;
|
||||
}
|
||||
|
||||
/* private key operations */
|
||||
|
||||
static int
|
||||
sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa,
|
||||
int padding)
|
||||
{
|
||||
u_char *padded = NULL;
|
||||
int sw, len, olen, status = -1;
|
||||
|
||||
debug("sc_private_decrypt called");
|
||||
|
||||
olen = len = sw = 0;
|
||||
if (sc_fd < 0) {
|
||||
status = sc_init();
|
||||
if (status < 0)
|
||||
goto err;
|
||||
}
|
||||
if (padding != RSA_PKCS1_PADDING)
|
||||
goto err;
|
||||
|
||||
len = BN_num_bytes(rsa->n);
|
||||
padded = xmalloc(len);
|
||||
|
||||
sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, from, len, padded, &sw);
|
||||
|
||||
if (sw == 0x6982) {
|
||||
if (try_AUT0() < 0)
|
||||
goto err;
|
||||
sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, from, len, padded, &sw);
|
||||
}
|
||||
if (!sectok_swOK(sw)) {
|
||||
error("sc_private_decrypt: INS_DECRYPT failed: %s",
|
||||
sectok_get_sw(sw));
|
||||
goto err;
|
||||
}
|
||||
olen = RSA_padding_check_PKCS1_type_2(to, len, padded + 1, len - 1,
|
||||
len);
|
||||
err:
|
||||
if (padded)
|
||||
xfree(padded);
|
||||
sc_close();
|
||||
return (olen >= 0 ? olen : status);
|
||||
}
|
||||
|
||||
static int
|
||||
sc_private_encrypt(int flen, u_char *from, u_char *to, RSA *rsa,
|
||||
int padding)
|
||||
{
|
||||
u_char *padded = NULL;
|
||||
int sw, len, status = -1;
|
||||
|
||||
len = sw = 0;
|
||||
if (sc_fd < 0) {
|
||||
status = sc_init();
|
||||
if (status < 0)
|
||||
goto err;
|
||||
}
|
||||
if (padding != RSA_PKCS1_PADDING)
|
||||
goto err;
|
||||
|
||||
debug("sc_private_encrypt called");
|
||||
len = BN_num_bytes(rsa->n);
|
||||
padded = xmalloc(len);
|
||||
|
||||
if (RSA_padding_add_PKCS1_type_1(padded, len, (u_char *)from, flen) <= 0) {
|
||||
error("RSA_padding_add_PKCS1_type_1 failed");
|
||||
goto err;
|
||||
}
|
||||
sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, padded, len, to, &sw);
|
||||
if (sw == 0x6982) {
|
||||
if (try_AUT0() < 0)
|
||||
goto err;
|
||||
sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, padded, len, to, &sw);
|
||||
}
|
||||
if (!sectok_swOK(sw)) {
|
||||
error("sc_private_encrypt: INS_DECRYPT failed: %s",
|
||||
sectok_get_sw(sw));
|
||||
goto err;
|
||||
}
|
||||
err:
|
||||
if (padded)
|
||||
xfree(padded);
|
||||
sc_close();
|
||||
return (len >= 0 ? len : status);
|
||||
}
|
||||
|
||||
/* called on free */
|
||||
|
||||
static int (*orig_finish)(RSA *rsa) = NULL;
|
||||
|
||||
static int
|
||||
sc_finish(RSA *rsa)
|
||||
{
|
||||
if (orig_finish)
|
||||
orig_finish(rsa);
|
||||
sc_close();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* engine for overloading private key operations */
|
||||
|
||||
static RSA_METHOD *
|
||||
sc_get_rsa_method(void)
|
||||
{
|
||||
static RSA_METHOD smart_rsa;
|
||||
const RSA_METHOD *def = RSA_get_default_method();
|
||||
|
||||
/* use the OpenSSL version */
|
||||
memcpy(&smart_rsa, def, sizeof(smart_rsa));
|
||||
|
||||
smart_rsa.name = "sectok";
|
||||
|
||||
/* overload */
|
||||
smart_rsa.rsa_priv_enc = sc_private_encrypt;
|
||||
smart_rsa.rsa_priv_dec = sc_private_decrypt;
|
||||
|
||||
/* save original */
|
||||
orig_finish = def->finish;
|
||||
smart_rsa.finish = sc_finish;
|
||||
|
||||
return &smart_rsa;
|
||||
}
|
||||
|
||||
#ifdef USE_ENGINE
|
||||
static ENGINE *
|
||||
sc_get_engine(void)
|
||||
{
|
||||
static ENGINE *smart_engine = NULL;
|
||||
|
||||
if ((smart_engine = ENGINE_new()) == NULL)
|
||||
fatal("ENGINE_new failed");
|
||||
|
||||
ENGINE_set_id(smart_engine, "sectok");
|
||||
ENGINE_set_name(smart_engine, "libsectok");
|
||||
|
||||
ENGINE_set_RSA(smart_engine, sc_get_rsa_method());
|
||||
ENGINE_set_DSA(smart_engine, DSA_get_default_openssl_method());
|
||||
ENGINE_set_DH(smart_engine, DH_get_default_openssl_method());
|
||||
ENGINE_set_RAND(smart_engine, RAND_SSLeay());
|
||||
ENGINE_set_BN_mod_exp(smart_engine, BN_mod_exp);
|
||||
|
||||
return smart_engine;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
sc_close(void)
|
||||
{
|
||||
if (sc_fd >= 0) {
|
||||
sectok_close(sc_fd);
|
||||
sc_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
Key **
|
||||
sc_get_keys(const char *id, const char *pin)
|
||||
{
|
||||
Key *k, *n, **keys;
|
||||
int status, nkeys = 2;
|
||||
|
||||
if (sc_reader_id != NULL)
|
||||
xfree(sc_reader_id);
|
||||
sc_reader_id = xstrdup(id);
|
||||
|
||||
if (sc_pin != NULL)
|
||||
xfree(sc_pin);
|
||||
sc_pin = (pin == NULL) ? NULL : xstrdup(pin);
|
||||
|
||||
k = key_new(KEY_RSA);
|
||||
if (k == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
status = sc_read_pubkey(k);
|
||||
if (status == SCARD_ERROR_NOCARD) {
|
||||
key_free(k);
|
||||
return NULL;
|
||||
}
|
||||
if (status < 0) {
|
||||
error("sc_read_pubkey failed");
|
||||
key_free(k);
|
||||
return NULL;
|
||||
}
|
||||
keys = xcalloc((nkeys+1), sizeof(Key *));
|
||||
|
||||
n = key_new(KEY_RSA1);
|
||||
if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
|
||||
(BN_copy(n->rsa->e, k->rsa->e) == NULL))
|
||||
fatal("sc_get_keys: BN_copy failed");
|
||||
RSA_set_method(n->rsa, sc_get_rsa());
|
||||
n->flags |= KEY_FLAG_EXT;
|
||||
keys[0] = n;
|
||||
|
||||
n = key_new(KEY_RSA);
|
||||
if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
|
||||
(BN_copy(n->rsa->e, k->rsa->e) == NULL))
|
||||
fatal("sc_get_keys: BN_copy failed");
|
||||
RSA_set_method(n->rsa, sc_get_rsa());
|
||||
n->flags |= KEY_FLAG_EXT;
|
||||
keys[1] = n;
|
||||
|
||||
keys[2] = NULL;
|
||||
|
||||
key_free(k);
|
||||
return keys;
|
||||
}
|
||||
|
||||
#define NUM_RSA_KEY_ELEMENTS 5+1
|
||||
#define COPY_RSA_KEY(x, i) \
|
||||
do { \
|
||||
len = BN_num_bytes(prv->rsa->x); \
|
||||
elements[i] = xmalloc(len); \
|
||||
debug("#bytes %d", len); \
|
||||
if (BN_bn2bin(prv->rsa->x, elements[i]) < 0) \
|
||||
goto done; \
|
||||
} while (0)
|
||||
|
||||
static void
|
||||
sc_mk_digest(const char *pin, u_char *digest)
|
||||
{
|
||||
const EVP_MD *evp_md = EVP_sha1();
|
||||
EVP_MD_CTX md;
|
||||
|
||||
EVP_DigestInit(&md, evp_md);
|
||||
EVP_DigestUpdate(&md, pin, strlen(pin));
|
||||
EVP_DigestFinal(&md, digest, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
get_AUT0(u_char *aut0)
|
||||
{
|
||||
char *pass;
|
||||
|
||||
pass = read_passphrase("Enter passphrase for smartcard: ", RP_ALLOW_STDIN);
|
||||
if (pass == NULL)
|
||||
return -1;
|
||||
if (!strcmp(pass, "-")) {
|
||||
memcpy(aut0, DEFAUT0, sizeof DEFAUT0);
|
||||
return 0;
|
||||
}
|
||||
sc_mk_digest(pass, aut0);
|
||||
memset(pass, 0, strlen(pass));
|
||||
xfree(pass);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
try_AUT0(void)
|
||||
{
|
||||
u_char aut0[EVP_MAX_MD_SIZE];
|
||||
|
||||
/* permission denied; try PIN if provided */
|
||||
if (sc_pin && strlen(sc_pin) > 0) {
|
||||
sc_mk_digest(sc_pin, aut0);
|
||||
if (cyberflex_verify_AUT0(sc_fd, cla, aut0, 8) < 0) {
|
||||
error("smartcard passphrase incorrect");
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
/* try default AUT0 key */
|
||||
if (cyberflex_verify_AUT0(sc_fd, cla, DEFAUT0, 8) < 0) {
|
||||
/* default AUT0 key failed; prompt for passphrase */
|
||||
if (get_AUT0(aut0) < 0 ||
|
||||
cyberflex_verify_AUT0(sc_fd, cla, aut0, 8) < 0) {
|
||||
error("smartcard passphrase incorrect");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
sc_put_key(Key *prv, const char *id)
|
||||
{
|
||||
u_char *elements[NUM_RSA_KEY_ELEMENTS];
|
||||
u_char key_fid[2];
|
||||
u_char AUT0[EVP_MAX_MD_SIZE];
|
||||
int len, status = -1, i, fd = -1, ret;
|
||||
int sw = 0, cla = 0x00;
|
||||
|
||||
for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++)
|
||||
elements[i] = NULL;
|
||||
|
||||
COPY_RSA_KEY(q, 0);
|
||||
COPY_RSA_KEY(p, 1);
|
||||
COPY_RSA_KEY(iqmp, 2);
|
||||
COPY_RSA_KEY(dmq1, 3);
|
||||
COPY_RSA_KEY(dmp1, 4);
|
||||
COPY_RSA_KEY(n, 5);
|
||||
len = BN_num_bytes(prv->rsa->n);
|
||||
fd = sectok_friendly_open(id, STONOWAIT, &sw);
|
||||
if (fd < 0) {
|
||||
error("sectok_open failed: %s", sectok_get_sw(sw));
|
||||
goto done;
|
||||
}
|
||||
if (! sectok_cardpresent(fd)) {
|
||||
error("smartcard in reader %s not present", id);
|
||||
goto done;
|
||||
}
|
||||
ret = sectok_reset(fd, 0, NULL, &sw);
|
||||
if (ret <= 0) {
|
||||
error("sectok_reset failed: %s", sectok_get_sw(sw));
|
||||
goto done;
|
||||
}
|
||||
if ((cla = cyberflex_inq_class(fd)) < 0) {
|
||||
error("cyberflex_inq_class failed");
|
||||
goto done;
|
||||
}
|
||||
memcpy(AUT0, DEFAUT0, sizeof(DEFAUT0));
|
||||
if (cyberflex_verify_AUT0(fd, cla, AUT0, sizeof(DEFAUT0)) < 0) {
|
||||
if (get_AUT0(AUT0) < 0 ||
|
||||
cyberflex_verify_AUT0(fd, cla, AUT0, sizeof(DEFAUT0)) < 0) {
|
||||
memset(AUT0, 0, sizeof(DEFAUT0));
|
||||
error("smartcard passphrase incorrect");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
memset(AUT0, 0, sizeof(DEFAUT0));
|
||||
key_fid[0] = 0x00;
|
||||
key_fid[1] = 0x12;
|
||||
if (cyberflex_load_rsa_priv(fd, cla, key_fid, 5, 8*len, elements,
|
||||
&sw) < 0) {
|
||||
error("cyberflex_load_rsa_priv failed: %s", sectok_get_sw(sw));
|
||||
goto done;
|
||||
}
|
||||
if (!sectok_swOK(sw))
|
||||
goto done;
|
||||
logit("cyberflex_load_rsa_priv done");
|
||||
key_fid[0] = 0x73;
|
||||
key_fid[1] = 0x68;
|
||||
if (cyberflex_load_rsa_pub(fd, cla, key_fid, len, elements[5],
|
||||
&sw) < 0) {
|
||||
error("cyberflex_load_rsa_pub failed: %s", sectok_get_sw(sw));
|
||||
goto done;
|
||||
}
|
||||
if (!sectok_swOK(sw))
|
||||
goto done;
|
||||
logit("cyberflex_load_rsa_pub done");
|
||||
status = 0;
|
||||
|
||||
done:
|
||||
memset(elements[0], '\0', BN_num_bytes(prv->rsa->q));
|
||||
memset(elements[1], '\0', BN_num_bytes(prv->rsa->p));
|
||||
memset(elements[2], '\0', BN_num_bytes(prv->rsa->iqmp));
|
||||
memset(elements[3], '\0', BN_num_bytes(prv->rsa->dmq1));
|
||||
memset(elements[4], '\0', BN_num_bytes(prv->rsa->dmp1));
|
||||
memset(elements[5], '\0', BN_num_bytes(prv->rsa->n));
|
||||
|
||||
for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++)
|
||||
if (elements[i])
|
||||
xfree(elements[i]);
|
||||
if (fd != -1)
|
||||
sectok_close(fd);
|
||||
return (status);
|
||||
}
|
||||
|
||||
char *
|
||||
sc_get_key_label(Key *key)
|
||||
{
|
||||
return xstrdup("smartcard key");
|
||||
}
|
||||
|
||||
#endif /* SMARTCARD && USE_SECTOK */
|
@ -1,39 +0,0 @@
|
||||
/* $OpenBSD: scard.h,v 1.14 2006/08/03 03:34:42 deraadt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SCARD_H
|
||||
#define SCARD_H
|
||||
|
||||
#define SCARD_ERROR_FAIL -1
|
||||
#define SCARD_ERROR_NOCARD -2
|
||||
#define SCARD_ERROR_APPLET -3
|
||||
|
||||
Key **sc_get_keys(const char *, const char *);
|
||||
void sc_close(void);
|
||||
int sc_put_key(Key *, const char *);
|
||||
char *sc_get_key_label(Key *);
|
||||
|
||||
#endif
|
@ -9,9 +9,9 @@
|
||||
.\"
|
||||
.\" Created: Sun May 7 00:14:37 1995 ylo
|
||||
.\"
|
||||
.\" $OpenBSD: scp.1,v 1.46 2008/07/12 05:33:41 djm Exp $
|
||||
.\" $OpenBSD: scp.1,v 1.50 2010/02/08 10:50:20 markus Exp $
|
||||
.\"
|
||||
.Dd July 12 2008
|
||||
.Dd February 8 2010
|
||||
.Dt SCP 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -153,6 +153,7 @@ For full details of the options listed below, and their possible values, see
|
||||
.It NoHostAuthenticationForLocalhost
|
||||
.It NumberOfPasswordPrompts
|
||||
.It PasswordAuthentication
|
||||
.It PKCS11Provider
|
||||
.It Port
|
||||
.It PreferredAuthentications
|
||||
.It Protocol
|
||||
@ -164,7 +165,6 @@ For full details of the options listed below, and their possible values, see
|
||||
.It SendEnv
|
||||
.It ServerAliveInterval
|
||||
.It ServerAliveCountMax
|
||||
.It SmartcardDevice
|
||||
.It StrictHostKeyChecking
|
||||
.It TCPKeepAlive
|
||||
.It UsePrivilegedPort
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: scp.c,v 1.164 2008/10/10 04:55:16 stevesk Exp $ */
|
||||
/* $OpenBSD: scp.c,v 1.165 2009/12/20 07:28:36 guenther Exp $ */
|
||||
/*
|
||||
* scp - secure remote copy. This is basically patched BSD rcp which
|
||||
* uses ssh to do the data transfer (instead of using rcmd).
|
||||
@ -244,8 +244,11 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
|
||||
close(pout[1]);
|
||||
|
||||
replacearg(&args, 0, "%s", ssh_program);
|
||||
if (remuser != NULL)
|
||||
addargs(&args, "-l%s", remuser);
|
||||
if (remuser != NULL) {
|
||||
addargs(&args, "-l");
|
||||
addargs(&args, "%s", remuser);
|
||||
}
|
||||
addargs(&args, "--");
|
||||
addargs(&args, "%s", host);
|
||||
addargs(&args, "%s", cmd);
|
||||
|
||||
@ -337,10 +340,12 @@ main(int argc, char **argv)
|
||||
case 'c':
|
||||
case 'i':
|
||||
case 'F':
|
||||
addargs(&args, "-%c%s", ch, optarg);
|
||||
addargs(&args, "-%c", ch);
|
||||
addargs(&args, "%s", optarg);
|
||||
break;
|
||||
case 'P':
|
||||
addargs(&args, "-p%s", optarg);
|
||||
addargs(&args, "-p");
|
||||
addargs(&args, "%s", optarg);
|
||||
break;
|
||||
case 'B':
|
||||
addargs(&args, "-oBatchmode yes");
|
||||
@ -548,6 +553,7 @@ toremote(char *targ, int argc, char **argv)
|
||||
} else {
|
||||
host = cleanhostname(argv[i]);
|
||||
}
|
||||
addargs(&alist, "--");
|
||||
addargs(&alist, "%s", host);
|
||||
addargs(&alist, "%s", cmd);
|
||||
addargs(&alist, "%s", src);
|
||||
@ -558,7 +564,7 @@ toremote(char *targ, int argc, char **argv)
|
||||
errs = 1;
|
||||
} else { /* local to remote */
|
||||
if (remin == -1) {
|
||||
xasprintf(&bp, "%s -t %s", cmd, targ);
|
||||
xasprintf(&bp, "%s -t -- %s", cmd, targ);
|
||||
host = cleanhostname(thost);
|
||||
if (do_cmd(host, tuser, bp, &remin,
|
||||
&remout) < 0)
|
||||
@ -591,6 +597,7 @@ tolocal(int argc, char **argv)
|
||||
addargs(&alist, "-r");
|
||||
if (pflag)
|
||||
addargs(&alist, "-p");
|
||||
addargs(&alist, "--");
|
||||
addargs(&alist, "%s", argv[i]);
|
||||
addargs(&alist, "%s", argv[argc-1]);
|
||||
if (do_local_cmd(&alist))
|
||||
@ -610,7 +617,7 @@ tolocal(int argc, char **argv)
|
||||
suser = pwd->pw_name;
|
||||
}
|
||||
host = cleanhostname(host);
|
||||
xasprintf(&bp, "%s -f %s", cmd, src);
|
||||
xasprintf(&bp, "%s -f -- %s", cmd, src);
|
||||
if (do_cmd(host, suser, bp, &remin, &remout) < 0) {
|
||||
(void) xfree(bp);
|
||||
++errs;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: servconf.c,v 1.195 2009/04/14 21:10:54 jj Exp $ */
|
||||
/* $OpenBSD: servconf.c,v 1.204 2010/03/04 10:36:03 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
* All rights reserved
|
||||
@ -42,6 +42,7 @@ __RCSID("$FreeBSD$");
|
||||
#include "match.h"
|
||||
#include "channels.h"
|
||||
#include "groupaccess.h"
|
||||
#include "version.h"
|
||||
|
||||
static void add_listen_addr(ServerOptions *, char *, int);
|
||||
static void add_one_listen_addr(ServerOptions *, char *, int);
|
||||
@ -66,6 +67,7 @@ initialize_server_options(ServerOptions *options)
|
||||
options->listen_addrs = NULL;
|
||||
options->address_family = -1;
|
||||
options->num_host_key_files = 0;
|
||||
options->num_host_cert_files = 0;
|
||||
options->pid_file = NULL;
|
||||
options->server_key_bits = -1;
|
||||
options->login_grace_time = -1;
|
||||
@ -129,6 +131,8 @@ initialize_server_options(ServerOptions *options)
|
||||
options->adm_forced_command = NULL;
|
||||
options->chroot_directory = NULL;
|
||||
options->zero_knowledge_password_authentication = -1;
|
||||
options->revoked_keys_file = NULL;
|
||||
options->trusted_user_ca_keys = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
@ -153,6 +157,7 @@ fill_default_server_options(ServerOptions *options)
|
||||
_PATH_HOST_DSA_KEY_FILE;
|
||||
}
|
||||
}
|
||||
/* No certificates by default */
|
||||
if (options->num_ports == 0)
|
||||
options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
|
||||
if (options->listen_addrs == NULL)
|
||||
@ -306,7 +311,8 @@ typedef enum {
|
||||
sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
|
||||
sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
|
||||
sUsePrivilegeSeparation, sAllowAgentForwarding,
|
||||
sZeroKnowledgePasswordAuthentication,
|
||||
sZeroKnowledgePasswordAuthentication, sHostCertificate,
|
||||
sRevokedKeys, sTrustedUserCAKeys,
|
||||
sVersionAddendum,
|
||||
sDeprecated, sUnsupported
|
||||
} ServerOpCodes;
|
||||
@ -426,6 +432,9 @@ static struct {
|
||||
{ "permitopen", sPermitOpen, SSHCFG_ALL },
|
||||
{ "forcecommand", sForceCommand, SSHCFG_ALL },
|
||||
{ "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
|
||||
{ "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
|
||||
{ "revokedkeys", sRevokedKeys, SSHCFG_ALL },
|
||||
{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
|
||||
{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
|
||||
{ NULL, sBadOption, 0 }
|
||||
};
|
||||
@ -462,6 +471,22 @@ parse_token(const char *cp, const char *filename,
|
||||
return sBadOption;
|
||||
}
|
||||
|
||||
char *
|
||||
derelativise_path(const char *path)
|
||||
{
|
||||
char *expanded, *ret, *cwd;
|
||||
|
||||
expanded = tilde_expand_filename(path, getuid());
|
||||
if (*expanded == '/')
|
||||
return expanded;
|
||||
if ((cwd = getcwd(NULL, 0)) == NULL)
|
||||
fatal("%s: getcwd: %s", __func__, strerror(errno));
|
||||
xasprintf(&ret, "%s/%s", cwd, expanded);
|
||||
xfree(cwd);
|
||||
xfree(expanded);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
add_listen_addr(ServerOptions *options, char *addr, int port)
|
||||
{
|
||||
@ -796,13 +821,23 @@ process_server_config_line(ServerOptions *options, char *line,
|
||||
fatal("%s line %d: missing file name.",
|
||||
filename, linenum);
|
||||
if (*activep && *charptr == NULL) {
|
||||
*charptr = tilde_expand_filename(arg, getuid());
|
||||
*charptr = derelativise_path(arg);
|
||||
/* increase optional counter */
|
||||
if (intptr != NULL)
|
||||
*intptr = *intptr + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case sHostCertificate:
|
||||
intptr = &options->num_host_cert_files;
|
||||
if (*intptr >= MAX_HOSTKEYS)
|
||||
fatal("%s line %d: too many host certificates "
|
||||
"specified (max %d).", filename, linenum,
|
||||
MAX_HOSTCERTS);
|
||||
charptr = &options->host_cert_files[*intptr];
|
||||
goto parse_filename;
|
||||
break;
|
||||
|
||||
case sPidFile:
|
||||
charptr = &options->pid_file;
|
||||
goto parse_filename;
|
||||
@ -1297,6 +1332,14 @@ process_server_config_line(ServerOptions *options, char *line,
|
||||
*charptr = xstrdup(arg);
|
||||
break;
|
||||
|
||||
case sTrustedUserCAKeys:
|
||||
charptr = &options->trusted_user_ca_keys;
|
||||
goto parse_filename;
|
||||
|
||||
case sRevokedKeys:
|
||||
charptr = &options->revoked_keys_file;
|
||||
goto parse_filename;
|
||||
|
||||
case sVersionAddendum:
|
||||
ssh_version_set_addendum(strtok(cp, "\n"));
|
||||
do {
|
||||
@ -1418,6 +1461,8 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
|
||||
return;
|
||||
M_CP_STROPT(adm_forced_command);
|
||||
M_CP_STROPT(chroot_directory);
|
||||
M_CP_STROPT(trusted_user_ca_keys);
|
||||
M_CP_STROPT(revoked_keys_file);
|
||||
}
|
||||
|
||||
#undef M_CP_INTOPT
|
||||
@ -1636,6 +1681,9 @@ dump_config(ServerOptions *o)
|
||||
dump_cfg_string(sAuthorizedKeysFile, o->authorized_keys_file);
|
||||
dump_cfg_string(sAuthorizedKeysFile2, o->authorized_keys_file2);
|
||||
dump_cfg_string(sForceCommand, o->adm_forced_command);
|
||||
dump_cfg_string(sChrootDirectory, o->chroot_directory);
|
||||
dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);
|
||||
dump_cfg_string(sRevokedKeys, o->revoked_keys_file);
|
||||
|
||||
/* string arguments requiring a lookup */
|
||||
dump_cfg_string(sLogLevel, log_level_name(o->log_level));
|
||||
@ -1644,6 +1692,8 @@ dump_config(ServerOptions *o)
|
||||
/* string array arguments */
|
||||
dump_cfg_strarray(sHostKeyFile, o->num_host_key_files,
|
||||
o->host_key_files);
|
||||
dump_cfg_strarray(sHostKeyFile, o->num_host_cert_files,
|
||||
o->host_cert_files);
|
||||
dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users);
|
||||
dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users);
|
||||
dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: servconf.h,v 1.87 2009/01/22 10:02:34 djm Exp $ */
|
||||
/* $OpenBSD: servconf.h,v 1.92 2010/03/04 10:36:03 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -24,6 +24,7 @@
|
||||
#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */
|
||||
#define MAX_SUBSYSTEMS 256 /* Max # subsystems. */
|
||||
#define MAX_HOSTKEYS 256 /* Max # hostkeys. */
|
||||
#define MAX_HOSTCERTS 256 /* Max # host certificates. */
|
||||
#define MAX_ACCEPT_ENV 256 /* Max # of env vars. */
|
||||
#define MAX_MATCH_GROUPS 256 /* Max # of groups for Match. */
|
||||
|
||||
@ -49,6 +50,8 @@ typedef struct {
|
||||
int address_family; /* Address family used by the server. */
|
||||
char *host_key_files[MAX_HOSTKEYS]; /* Files containing host keys. */
|
||||
int num_host_key_files; /* Number of files for host keys. */
|
||||
char *host_cert_files[MAX_HOSTCERTS]; /* Files containing host certs. */
|
||||
int num_host_cert_files; /* Number of files for host certs. */
|
||||
char *pid_file; /* Where to put our pid */
|
||||
int server_key_bits;/* Size of the server key. */
|
||||
int login_grace_time; /* Disconnect if no auth in this time
|
||||
@ -151,6 +154,8 @@ typedef struct {
|
||||
int num_permitted_opens;
|
||||
|
||||
char *chroot_directory;
|
||||
char *revoked_keys_file;
|
||||
char *trusted_user_ca_keys;
|
||||
} ServerOptions;
|
||||
|
||||
void initialize_server_options(ServerOptions *);
|
||||
@ -164,5 +169,6 @@ void parse_server_match_config(ServerOptions *, const char *, const char *,
|
||||
const char *);
|
||||
void copy_set_server_options(ServerOptions *, ServerOptions *, int);
|
||||
void dump_config(ServerOptions *);
|
||||
char *derelativise_path(const char *);
|
||||
|
||||
#endif /* SERVCONF_H */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: session.c,v 1.246 2009/04/17 19:23:06 stevesk Exp $ */
|
||||
/* $OpenBSD: session.c,v 1.252 2010/03/07 11:57:13 dtucker Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
* All rights reserved
|
||||
@ -143,9 +143,10 @@ static int sessions_first_unused = -1;
|
||||
static int sessions_nalloc = 0;
|
||||
static Session *sessions = NULL;
|
||||
|
||||
#define SUBSYSTEM_NONE 0
|
||||
#define SUBSYSTEM_EXT 1
|
||||
#define SUBSYSTEM_INT_SFTP 2
|
||||
#define SUBSYSTEM_NONE 0
|
||||
#define SUBSYSTEM_EXT 1
|
||||
#define SUBSYSTEM_INT_SFTP 2
|
||||
#define SUBSYSTEM_INT_SFTP_ERROR 3
|
||||
|
||||
#ifdef HAVE_LOGIN_CAP
|
||||
login_cap_t *lc;
|
||||
@ -271,6 +272,8 @@ do_authenticated(Authctxt *authctxt)
|
||||
if (!no_port_forwarding_flag && options.allow_tcp_forwarding)
|
||||
channel_permit_all_opens();
|
||||
|
||||
auth_debug_send();
|
||||
|
||||
if (compat20)
|
||||
do_authenticated2(authctxt);
|
||||
else
|
||||
@ -786,17 +789,19 @@ do_exec(Session *s, const char *command)
|
||||
if (options.adm_forced_command) {
|
||||
original_command = command;
|
||||
command = options.adm_forced_command;
|
||||
if (IS_INTERNAL_SFTP(command))
|
||||
s->is_subsystem = SUBSYSTEM_INT_SFTP;
|
||||
else if (s->is_subsystem)
|
||||
if (IS_INTERNAL_SFTP(command)) {
|
||||
s->is_subsystem = s->is_subsystem ?
|
||||
SUBSYSTEM_INT_SFTP : SUBSYSTEM_INT_SFTP_ERROR;
|
||||
} else if (s->is_subsystem)
|
||||
s->is_subsystem = SUBSYSTEM_EXT;
|
||||
debug("Forced command (config) '%.900s'", command);
|
||||
} else if (forced_command) {
|
||||
original_command = command;
|
||||
command = forced_command;
|
||||
if (IS_INTERNAL_SFTP(command))
|
||||
s->is_subsystem = SUBSYSTEM_INT_SFTP;
|
||||
else if (s->is_subsystem)
|
||||
if (IS_INTERNAL_SFTP(command)) {
|
||||
s->is_subsystem = s->is_subsystem ?
|
||||
SUBSYSTEM_INT_SFTP : SUBSYSTEM_INT_SFTP_ERROR;
|
||||
} else if (s->is_subsystem)
|
||||
s->is_subsystem = SUBSYSTEM_EXT;
|
||||
debug("Forced command (key option) '%.900s'", command);
|
||||
}
|
||||
@ -1404,26 +1409,32 @@ static void
|
||||
do_nologin(struct passwd *pw)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
char buf[1024];
|
||||
char buf[1024], *nl, *def_nl = _PATH_NOLOGIN;
|
||||
struct stat sb;
|
||||
|
||||
#ifdef HAVE_LOGIN_CAP
|
||||
if (!login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid)
|
||||
f = fopen(login_getcapstr(lc, "nologin", _PATH_NOLOGIN,
|
||||
_PATH_NOLOGIN), "r");
|
||||
if (login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid)
|
||||
return;
|
||||
nl = login_getcapstr(lc, "nologin", def_nl, def_nl);
|
||||
#else
|
||||
if (pw->pw_uid)
|
||||
f = fopen(_PATH_NOLOGIN, "r");
|
||||
if (pw->pw_uid == 0)
|
||||
return;
|
||||
nl = def_nl;
|
||||
#endif
|
||||
if (f) {
|
||||
/* /etc/nologin exists. Print its contents and exit. */
|
||||
logit("User %.100s not allowed because %s exists",
|
||||
pw->pw_name, _PATH_NOLOGIN);
|
||||
while (fgets(buf, sizeof(buf), f))
|
||||
fputs(buf, stderr);
|
||||
fclose(f);
|
||||
fflush(NULL);
|
||||
exit(254);
|
||||
if (stat(nl, &sb) == -1) {
|
||||
if (nl != def_nl)
|
||||
xfree(nl);
|
||||
return;
|
||||
}
|
||||
|
||||
/* /etc/nologin exists. Print its contents if we can and exit. */
|
||||
logit("User %.100s not allowed because %s exists", pw->pw_name, nl);
|
||||
if ((f = fopen(nl, "r")) != NULL) {
|
||||
while (fgets(buf, sizeof(buf), f))
|
||||
fputs(buf, stderr);
|
||||
fclose(f);
|
||||
}
|
||||
exit(254);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1551,6 +1562,24 @@ do_setusercontext(struct passwd *pw)
|
||||
}
|
||||
# endif /* USE_LIBIAF */
|
||||
#endif
|
||||
#ifdef HAVE_SETPCRED
|
||||
/*
|
||||
* If we have a chroot directory, we set all creds except real
|
||||
* uid which we will need for chroot. If we don't have a
|
||||
* chroot directory, we don't override anything.
|
||||
*/
|
||||
{
|
||||
char **creds = NULL, *chroot_creds[] =
|
||||
{ "REAL_USER=root", NULL };
|
||||
|
||||
if (options.chroot_directory != NULL &&
|
||||
strcasecmp(options.chroot_directory, "none") != 0)
|
||||
creds = chroot_creds;
|
||||
|
||||
if (setpcred(pw->pw_name, creds) == -1)
|
||||
fatal("Failed to set process credentials");
|
||||
}
|
||||
#endif /* HAVE_SETPCRED */
|
||||
|
||||
if (options.chroot_directory != NULL &&
|
||||
strcasecmp(options.chroot_directory, "none") != 0) {
|
||||
@ -1563,10 +1592,6 @@ do_setusercontext(struct passwd *pw)
|
||||
free(chroot_path);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SETPCRED
|
||||
if (setpcred(pw->pw_name, (char **)NULL) == -1)
|
||||
fatal("Failed to set process credentials");
|
||||
#endif /* HAVE_SETPCRED */
|
||||
#ifdef HAVE_LOGIN_CAP
|
||||
if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETUSER) < 0) {
|
||||
perror("unable to set user context (setuser)");
|
||||
@ -1813,7 +1838,11 @@ do_child(Session *s, const char *command)
|
||||
/* restore SIGPIPE for child */
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
|
||||
if (s->is_subsystem == SUBSYSTEM_INT_SFTP) {
|
||||
if (s->is_subsystem == SUBSYSTEM_INT_SFTP_ERROR) {
|
||||
printf("This service allows sftp connections only.\n");
|
||||
fflush(NULL);
|
||||
exit(1);
|
||||
} else if (s->is_subsystem == SUBSYSTEM_INT_SFTP) {
|
||||
extern int optind, optreset;
|
||||
int i;
|
||||
char *p, *args;
|
||||
@ -1826,9 +1855,14 @@ do_child(Session *s, const char *command)
|
||||
argv[i] = NULL;
|
||||
optind = optreset = 1;
|
||||
__progname = argv[0];
|
||||
#ifdef WITH_SELINUX
|
||||
ssh_selinux_change_context("sftpd_t");
|
||||
#endif
|
||||
exit(sftp_server_main(i, argv, s->pw));
|
||||
}
|
||||
|
||||
fflush(NULL);
|
||||
|
||||
if (options.use_login) {
|
||||
launch_login(pw, hostname);
|
||||
/* NEVERREACHED */
|
||||
@ -2139,16 +2173,16 @@ session_subsystem_req(Session *s)
|
||||
if (strcmp(subsys, options.subsystem_name[i]) == 0) {
|
||||
prog = options.subsystem_command[i];
|
||||
cmd = options.subsystem_args[i];
|
||||
if (!strcmp(INTERNAL_SFTP_NAME, prog)) {
|
||||
if (strcmp(INTERNAL_SFTP_NAME, prog) == 0) {
|
||||
s->is_subsystem = SUBSYSTEM_INT_SFTP;
|
||||
} else if (stat(prog, &st) < 0) {
|
||||
error("subsystem: cannot stat %s: %s", prog,
|
||||
strerror(errno));
|
||||
break;
|
||||
debug("subsystem: %s", prog);
|
||||
} else {
|
||||
if (stat(prog, &st) < 0)
|
||||
debug("subsystem: cannot stat %s: %s",
|
||||
prog, strerror(errno));
|
||||
s->is_subsystem = SUBSYSTEM_EXT;
|
||||
debug("subsystem: exec() %s", cmd);
|
||||
}
|
||||
debug("subsystem: exec() %s", cmd);
|
||||
success = do_exec(s, cmd) == 0;
|
||||
break;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: sftp-client.c,v 1.87 2009/06/22 05:39:28 dtucker Exp $ */
|
||||
/* $OpenBSD: sftp-client.c,v 1.90 2009/10/11 10:41:26 dtucker Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
||||
*
|
||||
@ -36,6 +36,7 @@
|
||||
#endif
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
@ -61,6 +62,9 @@ extern int showprogress;
|
||||
/* Minimum amount of data to read at a time */
|
||||
#define MIN_READ_SIZE 512
|
||||
|
||||
/* Maximum depth to descend in directory trees */
|
||||
#define MAX_DIR_DEPTH 64
|
||||
|
||||
struct sftp_conn {
|
||||
int fd_in;
|
||||
int fd_out;
|
||||
@ -74,6 +78,10 @@ struct sftp_conn {
|
||||
u_int exts;
|
||||
};
|
||||
|
||||
static char *
|
||||
get_handle(int fd, u_int expected_id, u_int *len, const char *errfmt, ...)
|
||||
__attribute__((format(printf, 4, 5)));
|
||||
|
||||
static void
|
||||
send_msg(int fd, Buffer *m)
|
||||
{
|
||||
@ -179,11 +187,18 @@ get_status(int fd, u_int expected_id)
|
||||
}
|
||||
|
||||
static char *
|
||||
get_handle(int fd, u_int expected_id, u_int *len)
|
||||
get_handle(int fd, u_int expected_id, u_int *len, const char *errfmt, ...)
|
||||
{
|
||||
Buffer msg;
|
||||
u_int type, id;
|
||||
char *handle;
|
||||
char *handle, errmsg[256];
|
||||
va_list args;
|
||||
int status;
|
||||
|
||||
va_start(args, errfmt);
|
||||
if (errfmt != NULL)
|
||||
vsnprintf(errmsg, sizeof(errmsg), errfmt, args);
|
||||
va_end(args);
|
||||
|
||||
buffer_init(&msg);
|
||||
get_msg(fd, &msg);
|
||||
@ -191,16 +206,17 @@ get_handle(int fd, u_int expected_id, u_int *len)
|
||||
id = buffer_get_int(&msg);
|
||||
|
||||
if (id != expected_id)
|
||||
fatal("ID mismatch (%u != %u)", id, expected_id);
|
||||
fatal("%s: ID mismatch (%u != %u)",
|
||||
errfmt == NULL ? __func__ : errmsg, id, expected_id);
|
||||
if (type == SSH2_FXP_STATUS) {
|
||||
int status = buffer_get_int(&msg);
|
||||
|
||||
error("Couldn't get handle: %s", fx2txt(status));
|
||||
status = buffer_get_int(&msg);
|
||||
if (errfmt != NULL)
|
||||
error("%s: %s", errmsg, fx2txt(status));
|
||||
buffer_free(&msg);
|
||||
return(NULL);
|
||||
} else if (type != SSH2_FXP_HANDLE)
|
||||
fatal("Expected SSH2_FXP_HANDLE(%u) packet, got %u",
|
||||
SSH2_FXP_HANDLE, type);
|
||||
fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u",
|
||||
errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type);
|
||||
|
||||
handle = buffer_get_string(&msg, len);
|
||||
buffer_free(&msg);
|
||||
@ -418,7 +434,8 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
|
||||
|
||||
buffer_clear(&msg);
|
||||
|
||||
handle = get_handle(conn->fd_in, id, &handle_len);
|
||||
handle = get_handle(conn->fd_in, id, &handle_len,
|
||||
"remote readdir(\"%s\")", path);
|
||||
if (handle == NULL)
|
||||
return(-1);
|
||||
|
||||
@ -484,6 +501,17 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
|
||||
if (printflag)
|
||||
printf("%s\n", longname);
|
||||
|
||||
/*
|
||||
* Directory entries should never contain '/'
|
||||
* These can be used to attack recursive ops
|
||||
* (e.g. send '../../../../etc/passwd')
|
||||
*/
|
||||
if (strchr(filename, '/') != NULL) {
|
||||
error("Server sent suspect path \"%s\" "
|
||||
"during readdir of \"%s\"", filename, path);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (dir) {
|
||||
*dir = xrealloc(*dir, ents + 2, sizeof(**dir));
|
||||
(*dir)[ents] = xmalloc(sizeof(***dir));
|
||||
@ -492,7 +520,7 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
|
||||
memcpy(&(*dir)[ents]->a, a, sizeof(*a));
|
||||
(*dir)[++ents] = NULL;
|
||||
}
|
||||
|
||||
next:
|
||||
xfree(filename);
|
||||
xfree(longname);
|
||||
}
|
||||
@ -547,7 +575,7 @@ do_rm(struct sftp_conn *conn, char *path)
|
||||
}
|
||||
|
||||
int
|
||||
do_mkdir(struct sftp_conn *conn, char *path, Attrib *a)
|
||||
do_mkdir(struct sftp_conn *conn, char *path, Attrib *a, int printflag)
|
||||
{
|
||||
u_int status, id;
|
||||
|
||||
@ -556,7 +584,7 @@ do_mkdir(struct sftp_conn *conn, char *path, Attrib *a)
|
||||
strlen(path), a);
|
||||
|
||||
status = get_status(conn->fd_in, id);
|
||||
if (status != SSH2_FX_OK)
|
||||
if (status != SSH2_FX_OK && printflag)
|
||||
error("Couldn't create directory: %s", fx2txt(status));
|
||||
|
||||
return(status);
|
||||
@ -895,9 +923,9 @@ send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len,
|
||||
|
||||
int
|
||||
do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
|
||||
int pflag)
|
||||
Attrib *a, int pflag)
|
||||
{
|
||||
Attrib junk, *a;
|
||||
Attrib junk;
|
||||
Buffer msg;
|
||||
char *handle;
|
||||
int local_fd, status = 0, write_error;
|
||||
@ -916,9 +944,8 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
|
||||
|
||||
TAILQ_INIT(&requests);
|
||||
|
||||
a = do_stat(conn, remote_path, 0);
|
||||
if (a == NULL)
|
||||
return(-1);
|
||||
if (a == NULL && (a = do_stat(conn, remote_path, 0)) == NULL)
|
||||
return -1;
|
||||
|
||||
/* Do not preserve set[ug]id here, as we do not preserve ownership */
|
||||
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
|
||||
@ -951,7 +978,8 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
|
||||
send_msg(conn->fd_out, &msg);
|
||||
debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
|
||||
|
||||
handle = get_handle(conn->fd_in, id, &handle_len);
|
||||
handle = get_handle(conn->fd_in, id, &handle_len,
|
||||
"remote open(\"%s\")", remote_path);
|
||||
if (handle == NULL) {
|
||||
buffer_free(&msg);
|
||||
return(-1);
|
||||
@ -1132,6 +1160,114 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
|
||||
return(status);
|
||||
}
|
||||
|
||||
static int
|
||||
download_dir_internal(struct sftp_conn *conn, char *src, char *dst,
|
||||
Attrib *dirattrib, int pflag, int printflag, int depth)
|
||||
{
|
||||
int i, ret = 0;
|
||||
SFTP_DIRENT **dir_entries;
|
||||
char *filename, *new_src, *new_dst;
|
||||
mode_t mode = 0777;
|
||||
|
||||
if (depth >= MAX_DIR_DEPTH) {
|
||||
error("Maximum directory depth exceeded: %d levels", depth);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dirattrib == NULL &&
|
||||
(dirattrib = do_stat(conn, src, 1)) == NULL) {
|
||||
error("Unable to stat remote directory \"%s\"", src);
|
||||
return -1;
|
||||
}
|
||||
if (!S_ISDIR(dirattrib->perm)) {
|
||||
error("\"%s\" is not a directory", src);
|
||||
return -1;
|
||||
}
|
||||
if (printflag)
|
||||
printf("Retrieving %s\n", src);
|
||||
|
||||
if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
|
||||
mode = dirattrib->perm & 01777;
|
||||
else {
|
||||
debug("Server did not send permissions for "
|
||||
"directory \"%s\"", dst);
|
||||
}
|
||||
|
||||
if (mkdir(dst, mode) == -1 && errno != EEXIST) {
|
||||
error("mkdir %s: %s", dst, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (do_readdir(conn, src, &dir_entries) == -1) {
|
||||
error("%s: Failed to get directory contents", src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; dir_entries[i] != NULL && !interrupted; i++) {
|
||||
filename = dir_entries[i]->filename;
|
||||
|
||||
new_dst = path_append(dst, filename);
|
||||
new_src = path_append(src, filename);
|
||||
|
||||
if (S_ISDIR(dir_entries[i]->a.perm)) {
|
||||
if (strcmp(filename, ".") == 0 ||
|
||||
strcmp(filename, "..") == 0)
|
||||
continue;
|
||||
if (download_dir_internal(conn, new_src, new_dst,
|
||||
&(dir_entries[i]->a), pflag, printflag,
|
||||
depth + 1) == -1)
|
||||
ret = -1;
|
||||
} else if (S_ISREG(dir_entries[i]->a.perm) ) {
|
||||
if (do_download(conn, new_src, new_dst,
|
||||
&(dir_entries[i]->a), pflag) == -1) {
|
||||
error("Download of file %s to %s failed",
|
||||
new_src, new_dst);
|
||||
ret = -1;
|
||||
}
|
||||
} else
|
||||
logit("%s: not a regular file\n", new_src);
|
||||
|
||||
xfree(new_dst);
|
||||
xfree(new_src);
|
||||
}
|
||||
|
||||
if (pflag) {
|
||||
if (dirattrib->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
|
||||
struct timeval tv[2];
|
||||
tv[0].tv_sec = dirattrib->atime;
|
||||
tv[1].tv_sec = dirattrib->mtime;
|
||||
tv[0].tv_usec = tv[1].tv_usec = 0;
|
||||
if (utimes(dst, tv) == -1)
|
||||
error("Can't set times on \"%s\": %s",
|
||||
dst, strerror(errno));
|
||||
} else
|
||||
debug("Server did not send times for directory "
|
||||
"\"%s\"", dst);
|
||||
}
|
||||
|
||||
free_sftp_dirents(dir_entries);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
download_dir(struct sftp_conn *conn, char *src, char *dst,
|
||||
Attrib *dirattrib, int pflag, int printflag)
|
||||
{
|
||||
char *src_canon;
|
||||
int ret;
|
||||
|
||||
if ((src_canon = do_realpath(conn, src)) == NULL) {
|
||||
error("Unable to canonicalise path \"%s\"", src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = download_dir_internal(conn, src_canon, dst,
|
||||
dirattrib, pflag, printflag, 0);
|
||||
xfree(src_canon);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
|
||||
int pflag)
|
||||
@ -1195,7 +1331,8 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
|
||||
|
||||
buffer_clear(&msg);
|
||||
|
||||
handle = get_handle(conn->fd_in, id, &handle_len);
|
||||
handle = get_handle(conn->fd_in, id, &handle_len,
|
||||
"remote open(\"%s\")", remote_path);
|
||||
if (handle == NULL) {
|
||||
close(local_fd);
|
||||
buffer_free(&msg);
|
||||
@ -1313,3 +1450,127 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int
|
||||
upload_dir_internal(struct sftp_conn *conn, char *src, char *dst,
|
||||
int pflag, int printflag, int depth)
|
||||
{
|
||||
int ret = 0, status;
|
||||
DIR *dirp;
|
||||
struct dirent *dp;
|
||||
char *filename, *new_src, *new_dst;
|
||||
struct stat sb;
|
||||
Attrib a;
|
||||
|
||||
if (depth >= MAX_DIR_DEPTH) {
|
||||
error("Maximum directory depth exceeded: %d levels", depth);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (stat(src, &sb) == -1) {
|
||||
error("Couldn't stat directory \"%s\": %s",
|
||||
src, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (!S_ISDIR(sb.st_mode)) {
|
||||
error("\"%s\" is not a directory", src);
|
||||
return -1;
|
||||
}
|
||||
if (printflag)
|
||||
printf("Entering %s\n", src);
|
||||
|
||||
attrib_clear(&a);
|
||||
stat_to_attrib(&sb, &a);
|
||||
a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
|
||||
a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
|
||||
a.perm &= 01777;
|
||||
if (!pflag)
|
||||
a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
|
||||
|
||||
status = do_mkdir(conn, dst, &a, 0);
|
||||
/*
|
||||
* we lack a portable status for errno EEXIST,
|
||||
* so if we get a SSH2_FX_FAILURE back we must check
|
||||
* if it was created successfully.
|
||||
*/
|
||||
if (status != SSH2_FX_OK) {
|
||||
if (status != SSH2_FX_FAILURE)
|
||||
return -1;
|
||||
if (do_stat(conn, dst, 0) == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((dirp = opendir(src)) == NULL) {
|
||||
error("Failed to open dir \"%s\": %s", src, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (((dp = readdir(dirp)) != NULL) && !interrupted) {
|
||||
if (dp->d_ino == 0)
|
||||
continue;
|
||||
filename = dp->d_name;
|
||||
new_dst = path_append(dst, filename);
|
||||
new_src = path_append(src, filename);
|
||||
|
||||
if (lstat(new_src, &sb) == -1) {
|
||||
logit("%s: lstat failed: %s", filename,
|
||||
strerror(errno));
|
||||
ret = -1;
|
||||
} else if (S_ISDIR(sb.st_mode)) {
|
||||
if (strcmp(filename, ".") == 0 ||
|
||||
strcmp(filename, "..") == 0)
|
||||
continue;
|
||||
|
||||
if (upload_dir_internal(conn, new_src, new_dst,
|
||||
pflag, depth + 1, printflag) == -1)
|
||||
ret = -1;
|
||||
} else if (S_ISREG(sb.st_mode)) {
|
||||
if (do_upload(conn, new_src, new_dst, pflag) == -1) {
|
||||
error("Uploading of file %s to %s failed!",
|
||||
new_src, new_dst);
|
||||
ret = -1;
|
||||
}
|
||||
} else
|
||||
logit("%s: not a regular file\n", filename);
|
||||
xfree(new_dst);
|
||||
xfree(new_src);
|
||||
}
|
||||
|
||||
do_setstat(conn, dst, &a);
|
||||
|
||||
(void) closedir(dirp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
upload_dir(struct sftp_conn *conn, char *src, char *dst, int printflag,
|
||||
int pflag)
|
||||
{
|
||||
char *dst_canon;
|
||||
int ret;
|
||||
|
||||
if ((dst_canon = do_realpath(conn, dst)) == NULL) {
|
||||
error("Unable to canonicalise path \"%s\"", dst);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = upload_dir_internal(conn, src, dst_canon, pflag, printflag, 0);
|
||||
xfree(dst_canon);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *
|
||||
path_append(char *p1, char *p2)
|
||||
{
|
||||
char *ret;
|
||||
size_t len = strlen(p1) + strlen(p2) + 2;
|
||||
|
||||
ret = xmalloc(len);
|
||||
strlcpy(ret, p1, len);
|
||||
if (p1[0] != '\0' && p1[strlen(p1) - 1] != '/')
|
||||
strlcat(ret, "/", len);
|
||||
strlcat(ret, p2, len);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: sftp-client.h,v 1.17 2008/06/08 20:15:29 dtucker Exp $ */
|
||||
/* $OpenBSD: sftp-client.h,v 1.18 2009/08/18 18:36:20 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
||||
@ -68,7 +68,7 @@ void free_sftp_dirents(SFTP_DIRENT **);
|
||||
int do_rm(struct sftp_conn *, char *);
|
||||
|
||||
/* Create directory 'path' */
|
||||
int do_mkdir(struct sftp_conn *, char *, Attrib *);
|
||||
int do_mkdir(struct sftp_conn *, char *, Attrib *, int);
|
||||
|
||||
/* Remove directory 'path' */
|
||||
int do_rmdir(struct sftp_conn *, char *);
|
||||
@ -103,7 +103,13 @@ int do_symlink(struct sftp_conn *, char *, char *);
|
||||
* Download 'remote_path' to 'local_path'. Preserve permissions and times
|
||||
* if 'pflag' is set
|
||||
*/
|
||||
int do_download(struct sftp_conn *, char *, char *, int);
|
||||
int do_download(struct sftp_conn *, char *, char *, Attrib *, int);
|
||||
|
||||
/*
|
||||
* Recursively download 'remote_directory' to 'local_directory'. Preserve
|
||||
* times if 'pflag' is set
|
||||
*/
|
||||
int download_dir(struct sftp_conn *, char *, char *, Attrib *, int, int);
|
||||
|
||||
/*
|
||||
* Upload 'local_path' to 'remote_path'. Preserve permissions and times
|
||||
@ -111,4 +117,13 @@ int do_download(struct sftp_conn *, char *, char *, int);
|
||||
*/
|
||||
int do_upload(struct sftp_conn *, char *, char *, int);
|
||||
|
||||
/*
|
||||
* Recursively upload 'local_directory' to 'remote_directory'. Preserve
|
||||
* times if 'pflag' is set
|
||||
*/
|
||||
int upload_dir(struct sftp_conn *, char *, char *, int, int);
|
||||
|
||||
/* Concatenate paths, taking care of slashes. Caller must free result. */
|
||||
char *path_append(char *, char *);
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: sftp-common.c,v 1.20 2006/08/03 03:34:42 deraadt Exp $ */
|
||||
/* $OpenBSD: sftp-common.c,v 1.23 2010/01/15 09:24:23 markus Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2001 Damien Miller. All rights reserved.
|
||||
@ -36,6 +36,9 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef HAVE_UTIL_H
|
||||
#include <util.h>
|
||||
#endif
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "buffer.h"
|
||||
@ -184,24 +187,23 @@ fx2txt(int status)
|
||||
* drwxr-xr-x 5 markus markus 1024 Jan 13 18:39 .ssh
|
||||
*/
|
||||
char *
|
||||
ls_file(const char *name, const struct stat *st, int remote)
|
||||
ls_file(const char *name, const struct stat *st, int remote, int si_units)
|
||||
{
|
||||
int ulen, glen, sz = 0;
|
||||
struct passwd *pw;
|
||||
struct group *gr;
|
||||
struct tm *ltime = localtime(&st->st_mtime);
|
||||
char *user, *group;
|
||||
char buf[1024], mode[11+1], tbuf[12+1], ubuf[11+1], gbuf[11+1];
|
||||
char sbuf[FMT_SCALED_STRSIZE];
|
||||
|
||||
strmode(st->st_mode, mode);
|
||||
if (!remote && (pw = getpwuid(st->st_uid)) != NULL) {
|
||||
user = pw->pw_name;
|
||||
if (!remote) {
|
||||
user = user_from_uid(st->st_uid, 0);
|
||||
} else {
|
||||
snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid);
|
||||
user = ubuf;
|
||||
}
|
||||
if (!remote && (gr = getgrgid(st->st_gid)) != NULL) {
|
||||
group = gr->gr_name;
|
||||
if (!remote) {
|
||||
group = group_from_gid(st->st_gid, 0);
|
||||
} else {
|
||||
snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid);
|
||||
group = gbuf;
|
||||
@ -216,8 +218,15 @@ ls_file(const char *name, const struct stat *st, int remote)
|
||||
tbuf[0] = '\0';
|
||||
ulen = MAX(strlen(user), 8);
|
||||
glen = MAX(strlen(group), 8);
|
||||
snprintf(buf, sizeof buf, "%s %3u %-*s %-*s %8llu %s %s", mode,
|
||||
(u_int)st->st_nlink, ulen, user, glen, group,
|
||||
(unsigned long long)st->st_size, tbuf, name);
|
||||
if (si_units) {
|
||||
fmt_scaled((long long)st->st_size, sbuf);
|
||||
snprintf(buf, sizeof buf, "%s %3u %-*s %-*s %8s %s %s", mode,
|
||||
(u_int)st->st_nlink, ulen, user, glen, group,
|
||||
sbuf, tbuf, name);
|
||||
} else {
|
||||
snprintf(buf, sizeof buf, "%s %3u %-*s %-*s %8llu %s %s", mode,
|
||||
(u_int)st->st_nlink, ulen, user, glen, group,
|
||||
(unsigned long long)st->st_size, tbuf, name);
|
||||
}
|
||||
return xstrdup(buf);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: sftp-common.h,v 1.10 2006/08/03 03:34:42 deraadt Exp $ */
|
||||
/* $OpenBSD: sftp-common.h,v 1.11 2010/01/13 01:40:16 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||
@ -46,6 +46,6 @@ void stat_to_attrib(const struct stat *, Attrib *);
|
||||
void attrib_to_stat(const Attrib *, struct stat *);
|
||||
Attrib *decode_attrib(Buffer *);
|
||||
void encode_attrib(Buffer *, const Attrib *);
|
||||
char *ls_file(const char *, const struct stat *, int);
|
||||
char *ls_file(const char *, const struct stat *, int, int);
|
||||
|
||||
const char *fx2txt(int);
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: sftp-server.8,v 1.15 2009/03/26 08:38:39 sobrado Exp $
|
||||
.\" $OpenBSD: sftp-server.8,v 1.19 2010/01/09 03:36:00 jmc Exp $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.\" Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
@ -23,7 +23,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 March 26 2009
|
||||
.Dd January 9 2010
|
||||
.Dt SFTP-SERVER 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -31,8 +31,10 @@
|
||||
.Nd SFTP server subsystem
|
||||
.Sh SYNOPSIS
|
||||
.Nm sftp-server
|
||||
.Op Fl ehR
|
||||
.Op Fl f Ar log_facility
|
||||
.Op Fl l Ar log_level
|
||||
.Op Fl u Ar umask
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a program that speaks the server side of SFTP protocol
|
||||
@ -55,12 +57,20 @@ for more information.
|
||||
.Pp
|
||||
Valid options are:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl e
|
||||
Causes
|
||||
.Nm
|
||||
to print logging information to stderr instead of syslog for debugging.
|
||||
.It Fl f Ar log_facility
|
||||
Specifies the facility code that is used when logging messages from
|
||||
.Nm .
|
||||
The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
|
||||
LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
|
||||
The default is AUTH.
|
||||
.It Fl h
|
||||
Displays
|
||||
.Nm
|
||||
usage information.
|
||||
.It Fl l Ar log_level
|
||||
Specifies which messages will be logged by
|
||||
.Nm .
|
||||
@ -72,6 +82,17 @@ performs on behalf of the client.
|
||||
DEBUG and DEBUG1 are equivalent.
|
||||
DEBUG2 and DEBUG3 each specify higher levels of debugging output.
|
||||
The default is ERROR.
|
||||
.It Fl R
|
||||
Places this instance of
|
||||
.Nm
|
||||
into a read-only mode.
|
||||
Attempts to open files for writing, as well as other operations that change
|
||||
the state of the filesystem, will be denied.
|
||||
.It Fl u Ar umask
|
||||
Sets an explicit
|
||||
.Xr umask 2
|
||||
to be applied to newly-created files and directories, instead of the
|
||||
user's default mask.
|
||||
.El
|
||||
.Pp
|
||||
For logging to work,
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: sftp-server.c,v 1.85 2009/04/14 16:33:42 stevesk Exp $ */
|
||||
/* $OpenBSD: sftp-server.c,v 1.91 2010/01/13 01:40:16 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000-2004 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -70,6 +70,9 @@ Buffer oqueue;
|
||||
/* Version of client */
|
||||
int version;
|
||||
|
||||
/* Disable writes */
|
||||
int readonly;
|
||||
|
||||
/* portable attributes, etc. */
|
||||
|
||||
typedef struct Stat Stat;
|
||||
@ -553,16 +556,21 @@ process_open(void)
|
||||
mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666;
|
||||
logit("open \"%s\" flags %s mode 0%o",
|
||||
name, string_from_portable(pflags), mode);
|
||||
fd = open(name, flags, mode);
|
||||
if (fd < 0) {
|
||||
status = errno_to_portable(errno);
|
||||
} else {
|
||||
handle = handle_new(HANDLE_FILE, name, fd, NULL);
|
||||
if (handle < 0) {
|
||||
close(fd);
|
||||
if (readonly &&
|
||||
((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR))
|
||||
status = SSH2_FX_PERMISSION_DENIED;
|
||||
else {
|
||||
fd = open(name, flags, mode);
|
||||
if (fd < 0) {
|
||||
status = errno_to_portable(errno);
|
||||
} else {
|
||||
send_handle(id, handle);
|
||||
status = SSH2_FX_OK;
|
||||
handle = handle_new(HANDLE_FILE, name, fd, NULL);
|
||||
if (handle < 0) {
|
||||
close(fd);
|
||||
} else {
|
||||
send_handle(id, handle);
|
||||
status = SSH2_FX_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (status != SSH2_FX_OK)
|
||||
@ -632,7 +640,7 @@ process_write(void)
|
||||
u_int32_t id;
|
||||
u_int64_t off;
|
||||
u_int len;
|
||||
int handle, fd, ret, status = SSH2_FX_FAILURE;
|
||||
int handle, fd, ret, status;
|
||||
char *data;
|
||||
|
||||
id = get_int();
|
||||
@ -643,7 +651,12 @@ process_write(void)
|
||||
debug("request %u: write \"%s\" (handle %d) off %llu len %d",
|
||||
id, handle_to_name(handle), handle, (unsigned long long)off, len);
|
||||
fd = handle_to_fd(handle);
|
||||
if (fd >= 0) {
|
||||
|
||||
if (fd < 0)
|
||||
status = SSH2_FX_FAILURE;
|
||||
else if (readonly)
|
||||
status = SSH2_FX_PERMISSION_DENIED;
|
||||
else {
|
||||
if (lseek(fd, off, SEEK_SET) < 0) {
|
||||
status = errno_to_portable(errno);
|
||||
error("process_write: seek failed");
|
||||
@ -658,6 +671,7 @@ process_write(void)
|
||||
handle_update_write(handle, ret);
|
||||
} else {
|
||||
debug2("nothing at all written");
|
||||
status = SSH2_FX_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -754,6 +768,10 @@ process_setstat(void)
|
||||
name = get_string(NULL);
|
||||
a = get_attrib();
|
||||
debug("request %u: setstat name \"%s\"", id, name);
|
||||
if (readonly) {
|
||||
status = SSH2_FX_PERMISSION_DENIED;
|
||||
a->flags = 0;
|
||||
}
|
||||
if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
|
||||
logit("set \"%s\" size %llu",
|
||||
name, (unsigned long long)a->size);
|
||||
@ -802,9 +820,11 @@ process_fsetstat(void)
|
||||
a = get_attrib();
|
||||
debug("request %u: fsetstat handle %d", id, handle);
|
||||
fd = handle_to_fd(handle);
|
||||
if (fd < 0) {
|
||||
if (fd < 0)
|
||||
status = SSH2_FX_FAILURE;
|
||||
} else {
|
||||
else if (readonly)
|
||||
status = SSH2_FX_PERMISSION_DENIED;
|
||||
else {
|
||||
char *name = handle_to_name(handle);
|
||||
|
||||
if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
|
||||
@ -920,7 +940,7 @@ process_readdir(void)
|
||||
continue;
|
||||
stat_to_attrib(&st, &(stats[count].attrib));
|
||||
stats[count].name = xstrdup(dp->d_name);
|
||||
stats[count].long_name = ls_file(dp->d_name, &st, 0);
|
||||
stats[count].long_name = ls_file(dp->d_name, &st, 0, 0);
|
||||
count++;
|
||||
/* send up to 100 entries in one message */
|
||||
/* XXX check packet size instead */
|
||||
@ -952,8 +972,12 @@ process_remove(void)
|
||||
name = get_string(NULL);
|
||||
debug3("request %u: remove", id);
|
||||
logit("remove name \"%s\"", name);
|
||||
ret = unlink(name);
|
||||
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
|
||||
if (readonly)
|
||||
status = SSH2_FX_PERMISSION_DENIED;
|
||||
else {
|
||||
ret = unlink(name);
|
||||
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
|
||||
}
|
||||
send_status(id, status);
|
||||
xfree(name);
|
||||
}
|
||||
@ -973,8 +997,12 @@ process_mkdir(void)
|
||||
a->perm & 07777 : 0777;
|
||||
debug3("request %u: mkdir", id);
|
||||
logit("mkdir name \"%s\" mode 0%o", name, mode);
|
||||
ret = mkdir(name, mode);
|
||||
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
|
||||
if (readonly)
|
||||
status = SSH2_FX_PERMISSION_DENIED;
|
||||
else {
|
||||
ret = mkdir(name, mode);
|
||||
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
|
||||
}
|
||||
send_status(id, status);
|
||||
xfree(name);
|
||||
}
|
||||
@ -990,8 +1018,12 @@ process_rmdir(void)
|
||||
name = get_string(NULL);
|
||||
debug3("request %u: rmdir", id);
|
||||
logit("rmdir name \"%s\"", name);
|
||||
ret = rmdir(name);
|
||||
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
|
||||
if (readonly)
|
||||
status = SSH2_FX_PERMISSION_DENIED;
|
||||
else {
|
||||
ret = rmdir(name);
|
||||
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
|
||||
}
|
||||
send_status(id, status);
|
||||
xfree(name);
|
||||
}
|
||||
@ -1036,7 +1068,9 @@ process_rename(void)
|
||||
debug3("request %u: rename", id);
|
||||
logit("rename old \"%s\" new \"%s\"", oldpath, newpath);
|
||||
status = SSH2_FX_FAILURE;
|
||||
if (lstat(oldpath, &sb) == -1)
|
||||
if (readonly)
|
||||
status = SSH2_FX_PERMISSION_DENIED;
|
||||
else if (lstat(oldpath, &sb) == -1)
|
||||
status = errno_to_portable(errno);
|
||||
else if (S_ISREG(sb.st_mode)) {
|
||||
/* Race-free rename of regular files */
|
||||
@ -1120,8 +1154,12 @@ process_symlink(void)
|
||||
debug3("request %u: symlink", id);
|
||||
logit("symlink old \"%s\" new \"%s\"", oldpath, newpath);
|
||||
/* this will fail if 'newpath' exists */
|
||||
ret = symlink(oldpath, newpath);
|
||||
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
|
||||
if (readonly)
|
||||
status = SSH2_FX_PERMISSION_DENIED;
|
||||
else {
|
||||
ret = symlink(oldpath, newpath);
|
||||
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
|
||||
}
|
||||
send_status(id, status);
|
||||
xfree(oldpath);
|
||||
xfree(newpath);
|
||||
@ -1131,15 +1169,19 @@ static void
|
||||
process_extended_posix_rename(u_int32_t id)
|
||||
{
|
||||
char *oldpath, *newpath;
|
||||
int ret, status;
|
||||
|
||||
oldpath = get_string(NULL);
|
||||
newpath = get_string(NULL);
|
||||
debug3("request %u: posix-rename", id);
|
||||
logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath);
|
||||
if (rename(oldpath, newpath) == -1)
|
||||
send_status(id, errno_to_portable(errno));
|
||||
else
|
||||
send_status(id, SSH2_FX_OK);
|
||||
if (readonly)
|
||||
status = SSH2_FX_PERMISSION_DENIED;
|
||||
else {
|
||||
ret = rename(oldpath, newpath);
|
||||
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
|
||||
}
|
||||
send_status(id, status);
|
||||
xfree(oldpath);
|
||||
xfree(newpath);
|
||||
}
|
||||
@ -1322,7 +1364,8 @@ sftp_server_usage(void)
|
||||
extern char *__progname;
|
||||
|
||||
fprintf(stderr,
|
||||
"usage: %s [-he] [-l log_level] [-f log_facility]\n", __progname);
|
||||
"usage: %s [-ehR] [-f log_facility] [-l log_level] [-u umask]\n",
|
||||
__progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -1334,6 +1377,8 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
|
||||
ssize_t len, olen, set_size;
|
||||
SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
|
||||
char *cp, buf[4*4096];
|
||||
const char *errmsg;
|
||||
mode_t mask;
|
||||
|
||||
extern char *optarg;
|
||||
extern char *__progname;
|
||||
@ -1341,8 +1386,11 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
|
||||
__progname = ssh_get_progname(argv[0]);
|
||||
log_init(__progname, log_level, log_facility, log_stderr);
|
||||
|
||||
while (!skipargs && (ch = getopt(argc, argv, "f:l:che")) != -1) {
|
||||
while (!skipargs && (ch = getopt(argc, argv, "f:l:u:cehR")) != -1) {
|
||||
switch (ch) {
|
||||
case 'R':
|
||||
readonly = 1;
|
||||
break;
|
||||
case 'c':
|
||||
/*
|
||||
* Ignore all arguments if we are invoked as a
|
||||
@ -1363,6 +1411,13 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
|
||||
if (log_facility == SYSLOG_FACILITY_NOT_SET)
|
||||
error("Invalid log facility \"%s\"", optarg);
|
||||
break;
|
||||
case 'u':
|
||||
mask = (mode_t)strtonum(optarg, 0, 0777, &errmsg);
|
||||
if (errmsg != NULL)
|
||||
fatal("Invalid umask \"%s\": %s",
|
||||
optarg, errmsg);
|
||||
(void)umask(mask);
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
sftp_server_usage();
|
||||
@ -1387,8 +1442,8 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
|
||||
logit("session opened for local user %s from [%s]",
|
||||
pw->pw_name, client_addr);
|
||||
|
||||
in = dup(STDIN_FILENO);
|
||||
out = dup(STDOUT_FILENO);
|
||||
in = STDIN_FILENO;
|
||||
out = STDOUT_FILENO;
|
||||
|
||||
#ifdef HAVE_CYGWIN
|
||||
setmode(in, O_BINARY);
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: sftp.1,v 1.69 2008/12/09 15:35:00 sobrado Exp $
|
||||
.\" $OpenBSD: sftp.1,v 1.83 2010/02/08 10:50:20 markus Exp $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.\" Copyright (c) 2001 Damien Miller. All rights reserved.
|
||||
@ -23,7 +23,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 December 9 2008
|
||||
.Dd February 8 2010
|
||||
.Dt SFTP 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -32,12 +32,15 @@
|
||||
.Sh SYNOPSIS
|
||||
.Nm sftp
|
||||
.Bk -words
|
||||
.Op Fl 1Cv
|
||||
.Op Fl 1246Cpqrv
|
||||
.Op Fl B Ar buffer_size
|
||||
.Op Fl b Ar batchfile
|
||||
.Op Fl c Ar cipher
|
||||
.Op Fl D Ar sftp_server_path
|
||||
.Op Fl F Ar ssh_config
|
||||
.Op Fl i Ar identity_file
|
||||
.Op Fl o Ar ssh_option
|
||||
.Op Fl P Ar sftp_server_path
|
||||
.Op Fl P Ar port
|
||||
.Op Fl R Ar num_requests
|
||||
.Op Fl S Ar program
|
||||
.Op Fl s Ar subsystem | sftp_server
|
||||
@ -88,6 +91,16 @@ The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl 1
|
||||
Specify the use of protocol version 1.
|
||||
.It Fl 2
|
||||
Specify the use of protocol version 2.
|
||||
.It Fl 4
|
||||
Forces
|
||||
.Nm
|
||||
to use IPv4 addresses only.
|
||||
.It Fl 6
|
||||
Forces
|
||||
.Nm
|
||||
to use IPv6 addresses only.
|
||||
.It Fl B Ar buffer_size
|
||||
Specify the size of the buffer that
|
||||
.Nm
|
||||
@ -125,12 +138,26 @@ character (for example,
|
||||
Enables compression (via ssh's
|
||||
.Fl C
|
||||
flag).
|
||||
.It Fl c Ar cipher
|
||||
Selects the cipher to use for encrypting the data transfers.
|
||||
This option is directly passed to
|
||||
.Xr ssh 1 .
|
||||
.It Fl D Ar sftp_server_path
|
||||
Connect directly to a local sftp server
|
||||
(rather than via
|
||||
.Xr ssh 1 ) .
|
||||
This option may be useful in debugging the client and server.
|
||||
.It Fl F Ar ssh_config
|
||||
Specifies an alternative
|
||||
per-user configuration file for
|
||||
.Xr ssh 1 .
|
||||
This option is directly passed to
|
||||
.Xr ssh 1 .
|
||||
.It Fl i Ar identity_file
|
||||
Selects the file from which the identity (private key) for public key
|
||||
authentication is read.
|
||||
This option is directly passed to
|
||||
.Xr ssh 1 .
|
||||
.It Fl o Ar ssh_option
|
||||
Can be used to pass options to
|
||||
.Nm ssh
|
||||
@ -176,6 +203,7 @@ For full details of the options listed below, and their possible values, see
|
||||
.It NoHostAuthenticationForLocalhost
|
||||
.It NumberOfPasswordPrompts
|
||||
.It PasswordAuthentication
|
||||
.It PKCS11Provider
|
||||
.It Port
|
||||
.It PreferredAuthentications
|
||||
.It Protocol
|
||||
@ -187,7 +215,6 @@ For full details of the options listed below, and their possible values, see
|
||||
.It SendEnv
|
||||
.It ServerAliveInterval
|
||||
.It ServerAliveCountMax
|
||||
.It SmartcardDevice
|
||||
.It StrictHostKeyChecking
|
||||
.It TCPKeepAlive
|
||||
.It UsePrivilegedPort
|
||||
@ -195,16 +222,25 @@ For full details of the options listed below, and their possible values, see
|
||||
.It UserKnownHostsFile
|
||||
.It VerifyHostKeyDNS
|
||||
.El
|
||||
.It Fl P Ar sftp_server_path
|
||||
Connect directly to a local sftp server
|
||||
(rather than via
|
||||
.Xr ssh 1 ) .
|
||||
This option may be useful in debugging the client and server.
|
||||
.It Fl P Ar port
|
||||
Specifies the port to connect to on the remote host.
|
||||
.It Fl p
|
||||
Preserves modification times, access times, and modes from the
|
||||
original files transferred.
|
||||
.It Fl q
|
||||
Quiet mode: disables the progress meter as well as warning and
|
||||
diagnostic messages from
|
||||
.Xr ssh 1 .
|
||||
.It Fl R Ar num_requests
|
||||
Specify how many requests may be outstanding at any one time.
|
||||
Increasing this may slightly improve file transfer speed
|
||||
but will increase memory usage.
|
||||
The default is 64 outstanding requests.
|
||||
.It Fl r
|
||||
Recursively copy entire directories when uploading and downloading.
|
||||
Note that
|
||||
.Nm
|
||||
does not follow symbolic links encountered in the tree traversal.
|
||||
.It Fl S Ar program
|
||||
Name of the
|
||||
.Ar program
|
||||
@ -295,7 +331,7 @@ extension.
|
||||
Quit
|
||||
.Nm sftp .
|
||||
.It Xo Ic get
|
||||
.Op Fl P
|
||||
.Op Fl Ppr
|
||||
.Ar remote-path
|
||||
.Op Ar local-path
|
||||
.Xc
|
||||
@ -314,10 +350,20 @@ If it does and
|
||||
is specified, then
|
||||
.Ar local-path
|
||||
must specify a directory.
|
||||
If the
|
||||
.Pp
|
||||
If either the
|
||||
.Fl P
|
||||
or
|
||||
.Fl p
|
||||
flag is specified, then full file permissions and access times are
|
||||
copied too.
|
||||
.Pp
|
||||
If the
|
||||
.Fl r
|
||||
flag is specified then directories will be copied recursively.
|
||||
Note that
|
||||
.Nm
|
||||
does not follow symbolic links when performing recursive transfers.
|
||||
.It Ic help
|
||||
Display help text.
|
||||
.It Ic lcd Ar path
|
||||
@ -348,7 +394,7 @@ to
|
||||
.It Ic lpwd
|
||||
Print local working directory.
|
||||
.It Xo Ic ls
|
||||
.Op Fl 1aflnrSt
|
||||
.Op Fl 1afhlnrSt
|
||||
.Op Ar path
|
||||
.Xc
|
||||
Display a remote directory listing of either
|
||||
@ -373,6 +419,11 @@ List files beginning with a dot
|
||||
.It Fl f
|
||||
Do not sort the listing.
|
||||
The default sort order is lexicographical.
|
||||
.It Fl h
|
||||
When used with a long format option, use unit suffixes: Byte, Kilobyte,
|
||||
Megabyte, Gigabyte, Terabyte, Petabyte, and Exabyte in order to reduce
|
||||
the number of digits to four or fewer using powers of 2 for sizes (K=1024,
|
||||
M=1048576, etc.).
|
||||
.It Fl l
|
||||
Display additional details including permissions
|
||||
and ownership information.
|
||||
@ -395,7 +446,7 @@ Create remote directory specified by
|
||||
.It Ic progress
|
||||
Toggle display of progress meter.
|
||||
.It Xo Ic put
|
||||
.Op Fl P
|
||||
.Op Fl Ppr
|
||||
.Ar local-path
|
||||
.Op Ar remote-path
|
||||
.Xc
|
||||
@ -413,10 +464,20 @@ If it does and
|
||||
is specified, then
|
||||
.Ar remote-path
|
||||
must specify a directory.
|
||||
If the
|
||||
.Pp
|
||||
If ether the
|
||||
.Fl P
|
||||
flag is specified, then the file's full permission and access time are
|
||||
or
|
||||
.Fl p
|
||||
flag is specified, then full file permissions and access times are
|
||||
copied too.
|
||||
.Pp
|
||||
If the
|
||||
.Fl r
|
||||
flag is specified then directories will be copied recursively.
|
||||
Note that
|
||||
.Nm
|
||||
does not follow symbolic links when performing recursive transfers.
|
||||
.It Ic pwd
|
||||
Display remote working directory.
|
||||
.It Ic quit
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: ssh-add.1,v 1.46 2007/06/12 13:41:03 jmc Exp $
|
||||
.\" $OpenBSD: ssh-add.1,v 1.52 2010/03/05 10:28:21 djm Exp $
|
||||
.\"
|
||||
.\" -*- nroff -*-
|
||||
.\"
|
||||
@ -37,7 +37,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 June 12 2007
|
||||
.Dd March 5 2010
|
||||
.Dt SSH-ADD 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -49,9 +49,9 @@
|
||||
.Op Fl t Ar life
|
||||
.Op Ar
|
||||
.Nm ssh-add
|
||||
.Fl s Ar reader
|
||||
.Fl s Ar pkcs11
|
||||
.Nm ssh-add
|
||||
.Fl e Ar reader
|
||||
.Fl e Ar pkcs11
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
adds RSA or DSA identities to the authentication agent,
|
||||
@ -61,7 +61,14 @@ When run without arguments, it adds the files
|
||||
.Pa ~/.ssh/id_dsa
|
||||
and
|
||||
.Pa ~/.ssh/identity .
|
||||
After loading a private key,
|
||||
.Nm
|
||||
will try to load corresponding certificate information from the
|
||||
filename obtained by appending
|
||||
.Pa -cert.pub
|
||||
to the name of the private key file.
|
||||
Alternative file names can be given on the command line.
|
||||
.Pp
|
||||
If any file requires a passphrase,
|
||||
.Nm
|
||||
asks for the passphrase from the user.
|
||||
@ -101,17 +108,17 @@ If no public key is found at a given path,
|
||||
will append
|
||||
.Pa .pub
|
||||
and retry.
|
||||
.It Fl e Ar reader
|
||||
Remove key in smartcard
|
||||
.Ar reader .
|
||||
.It Fl e Ar pkcs11
|
||||
Remove keys provided by the PKCS#11 shared library
|
||||
.Ar pkcs11 .
|
||||
.It Fl L
|
||||
Lists public key parameters of all identities currently represented
|
||||
by the agent.
|
||||
.It Fl l
|
||||
Lists fingerprints of all identities currently represented by the agent.
|
||||
.It Fl s Ar reader
|
||||
Add key in smartcard
|
||||
.Ar reader .
|
||||
.It Fl s Ar pkcs11
|
||||
Add keys provided by the PKCS#11 shared library
|
||||
.Ar pkcs11 .
|
||||
.It Fl t Ar life
|
||||
Set a maximum lifetime when adding identities to an agent.
|
||||
The lifetime may be specified in seconds or in a time format
|
||||
@ -148,8 +155,9 @@ may be necessary to redirect the input from
|
||||
.Pa /dev/null
|
||||
to make this work.)
|
||||
.It Ev SSH_AUTH_SOCK
|
||||
Identifies the path of a unix-domain socket used to communicate with the
|
||||
agent.
|
||||
Identifies the path of a
|
||||
.Ux Ns -domain
|
||||
socket used to communicate with the agent.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width Ds
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ssh-add.c,v 1.90 2007/09/09 11:38:01 sobrado Exp $ */
|
||||
/* $OpenBSD: ssh-add.c,v 1.94 2010/03/01 11:07:06 otto Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -138,9 +138,9 @@ delete_all(AuthenticationConnection *ac)
|
||||
static int
|
||||
add_file(AuthenticationConnection *ac, const char *filename)
|
||||
{
|
||||
Key *private;
|
||||
Key *private, *cert;
|
||||
char *comment = NULL;
|
||||
char msg[1024];
|
||||
char msg[1024], *certpath;
|
||||
int fd, perms_ok, ret = -1;
|
||||
|
||||
if ((fd = open(filename, O_RDONLY)) < 0) {
|
||||
@ -195,13 +195,37 @@ add_file(AuthenticationConnection *ac, const char *filename)
|
||||
if (confirm != 0)
|
||||
fprintf(stderr,
|
||||
"The user has to confirm each use of the key\n");
|
||||
} else if (ssh_add_identity(ac, private, comment)) {
|
||||
fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
|
||||
ret = 0;
|
||||
} else {
|
||||
fprintf(stderr, "Could not add identity: %s\n", 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);
|
||||
key_free(cert);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
xfree(certpath);
|
||||
xfree(comment);
|
||||
key_free(private);
|
||||
|
||||
@ -214,7 +238,7 @@ update_card(AuthenticationConnection *ac, int add, const char *id)
|
||||
char *pin;
|
||||
int ret = -1;
|
||||
|
||||
pin = read_passphrase("Enter passphrase for smartcard: ", RP_ALLOW_STDIN);
|
||||
pin = read_passphrase("Enter passphrase for PKCS#11: ", RP_ALLOW_STDIN);
|
||||
if (pin == NULL)
|
||||
return -1;
|
||||
|
||||
@ -320,10 +344,8 @@ usage(void)
|
||||
fprintf(stderr, " -X Unlock agent.\n");
|
||||
fprintf(stderr, " -t life Set lifetime (in seconds) when adding identities.\n");
|
||||
fprintf(stderr, " -c Require confirmation to sign using identities\n");
|
||||
#ifdef SMARTCARD
|
||||
fprintf(stderr, " -s reader Add key in smartcard reader.\n");
|
||||
fprintf(stderr, " -e reader Remove key in smartcard reader.\n");
|
||||
#endif
|
||||
fprintf(stderr, " -s pkcs11 Add keys from PKCS#11 provider.\n");
|
||||
fprintf(stderr, " -e pkcs11 Remove keys provided by PKCS#11 provider.\n");
|
||||
}
|
||||
|
||||
int
|
||||
@ -332,7 +354,7 @@ main(int argc, char **argv)
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
AuthenticationConnection *ac = NULL;
|
||||
char *sc_reader_id = NULL;
|
||||
char *pkcs11provider = NULL;
|
||||
int i, ch, deleting = 0, ret = 0;
|
||||
|
||||
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
|
||||
@ -374,11 +396,11 @@ main(int argc, char **argv)
|
||||
ret = 1;
|
||||
goto done;
|
||||
case 's':
|
||||
sc_reader_id = optarg;
|
||||
pkcs11provider = optarg;
|
||||
break;
|
||||
case 'e':
|
||||
deleting = 1;
|
||||
sc_reader_id = optarg;
|
||||
pkcs11provider = optarg;
|
||||
break;
|
||||
case 't':
|
||||
if ((lifetime = convtime(optarg)) == -1) {
|
||||
@ -395,8 +417,8 @@ main(int argc, char **argv)
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if (sc_reader_id != NULL) {
|
||||
if (update_card(ac, !deleting, sc_reader_id) == -1)
|
||||
if (pkcs11provider != NULL) {
|
||||
if (update_card(ac, !deleting, pkcs11provider) == -1)
|
||||
ret = 1;
|
||||
goto done;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: ssh-agent.1,v 1.47 2009/03/26 08:38:39 sobrado Exp $
|
||||
.\" $OpenBSD: ssh-agent.1,v 1.50 2010/01/17 21:49:09 tedu Exp $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -35,7 +35,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 March 26 2009
|
||||
.Dd January 17 2010
|
||||
.Dt SSH-AGENT 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -68,7 +68,9 @@ machines using
|
||||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl a Ar bind_address
|
||||
Bind the agent to the unix-domain socket
|
||||
Bind the agent to the
|
||||
.Ux Ns -domain
|
||||
socket
|
||||
.Ar bind_address .
|
||||
The default is
|
||||
.Pa /tmp/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt .
|
||||
@ -118,8 +120,9 @@ and
|
||||
.Pa ~/.ssh/identity .
|
||||
If the identity has a passphrase,
|
||||
.Xr ssh-add 1
|
||||
asks for the passphrase (using a small X11 application if running
|
||||
under X11, or from the terminal if running without X).
|
||||
asks for the passphrase on the terminal if it has one or from a small X11
|
||||
program if running under X11.
|
||||
If neither of these is the case then the authentication will fail.
|
||||
It then sends the identity to the agent.
|
||||
Several identities can be stored in the
|
||||
agent; the agent can automatically use any of these identities.
|
||||
@ -163,8 +166,9 @@ Instead, operations that require a private key will be performed
|
||||
by the agent, and the result will be returned to the requester.
|
||||
This way, private keys are not exposed to clients using the agent.
|
||||
.Pp
|
||||
A unix-domain socket is created
|
||||
and the name of this socket is stored in the
|
||||
A
|
||||
.Ux Ns -domain
|
||||
socket is created and the name of this socket is stored in the
|
||||
.Ev SSH_AUTH_SOCK
|
||||
environment
|
||||
variable.
|
||||
@ -187,8 +191,8 @@ Contains the protocol version 2 DSA authentication identity of the user.
|
||||
.It Pa ~/.ssh/id_rsa
|
||||
Contains the protocol version 2 RSA authentication identity of the user.
|
||||
.It Pa /tmp/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt
|
||||
Unix-domain sockets used to contain the connection to the
|
||||
authentication agent.
|
||||
.Ux Ns -domain
|
||||
sockets used to contain the connection to the authentication agent.
|
||||
These sockets should only be readable by the owner.
|
||||
The sockets should get automatically removed when the agent exits.
|
||||
.El
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ssh-agent.c,v 1.161 2009/03/23 19:38:04 tobias Exp $ */
|
||||
/* $OpenBSD: ssh-agent.c,v 1.165 2010/02/26 20:29:54 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -77,8 +77,8 @@ __RCSID("$FreeBSD$");
|
||||
#include "log.h"
|
||||
#include "misc.h"
|
||||
|
||||
#ifdef SMARTCARD
|
||||
#include "scard.h"
|
||||
#ifdef ENABLE_PKCS11
|
||||
#include "ssh-pkcs11.h"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SYS_PRCTL_H)
|
||||
@ -106,6 +106,7 @@ typedef struct identity {
|
||||
TAILQ_ENTRY(identity) next;
|
||||
Key *key;
|
||||
char *comment;
|
||||
char *provider;
|
||||
u_int death;
|
||||
u_int confirm;
|
||||
} Identity;
|
||||
@ -172,6 +173,8 @@ static void
|
||||
free_identity(Identity *id)
|
||||
{
|
||||
key_free(id->key);
|
||||
if (id->provider != NULL)
|
||||
xfree(id->provider);
|
||||
xfree(id->comment);
|
||||
xfree(id);
|
||||
}
|
||||
@ -466,6 +469,8 @@ process_add_identity(SocketEntry *e, int version)
|
||||
int type, success = 0, death = 0, confirm = 0;
|
||||
char *type_name, *comment;
|
||||
Key *k = NULL;
|
||||
u_char *cert;
|
||||
u_int len;
|
||||
|
||||
switch (version) {
|
||||
case 1:
|
||||
@ -496,6 +501,14 @@ 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:
|
||||
cert = buffer_get_string(&e->request, &len);
|
||||
if ((k = key_from_blob(cert, len)) == NULL)
|
||||
fatal("Certificate parse failed");
|
||||
xfree(cert);
|
||||
key_add_private(k);
|
||||
buffer_get_bignum2(&e->request, k->dsa->priv_key);
|
||||
break;
|
||||
case KEY_RSA:
|
||||
k = key_new_private(type);
|
||||
buffer_get_bignum2(&e->request, k->rsa->n);
|
||||
@ -508,6 +521,17 @@ process_add_identity(SocketEntry *e, int version)
|
||||
/* Generate additional parameters */
|
||||
rsa_generate_additional_parameters(k->rsa);
|
||||
break;
|
||||
case KEY_RSA_CERT:
|
||||
cert = buffer_get_string(&e->request, &len);
|
||||
if ((k = key_from_blob(cert, len)) == NULL)
|
||||
fatal("Certificate parse failed");
|
||||
xfree(cert);
|
||||
key_add_private(k);
|
||||
buffer_get_bignum2(&e->request, k->rsa->d);
|
||||
buffer_get_bignum2(&e->request, k->rsa->iqmp);
|
||||
buffer_get_bignum2(&e->request, k->rsa->p);
|
||||
buffer_get_bignum2(&e->request, k->rsa->q);
|
||||
break;
|
||||
default:
|
||||
buffer_clear(&e->request);
|
||||
goto send;
|
||||
@ -517,6 +541,7 @@ process_add_identity(SocketEntry *e, int version)
|
||||
/* enable blinding */
|
||||
switch (k->type) {
|
||||
case KEY_RSA:
|
||||
case KEY_RSA_CERT:
|
||||
case KEY_RSA1:
|
||||
if (RSA_blinding_on(k->rsa, NULL) != 1) {
|
||||
error("process_add_identity: RSA_blinding_on failed");
|
||||
@ -550,7 +575,7 @@ process_add_identity(SocketEntry *e, int version)
|
||||
if (lifetime && !death)
|
||||
death = time(NULL) + lifetime;
|
||||
if ((id = lookup_identity(k, version)) == NULL) {
|
||||
id = xmalloc(sizeof(Identity));
|
||||
id = xcalloc(1, sizeof(Identity));
|
||||
id->key = k;
|
||||
TAILQ_INSERT_TAIL(&tab->idlist, id, next);
|
||||
/* Increment the number of identities. */
|
||||
@ -610,17 +635,17 @@ no_identities(SocketEntry *e, u_int type)
|
||||
buffer_free(&msg);
|
||||
}
|
||||
|
||||
#ifdef SMARTCARD
|
||||
#ifdef ENABLE_PKCS11
|
||||
static void
|
||||
process_add_smartcard_key(SocketEntry *e)
|
||||
{
|
||||
char *sc_reader_id = NULL, *pin;
|
||||
int i, type, version, success = 0, death = 0, confirm = 0;
|
||||
Key **keys, *k;
|
||||
char *provider = NULL, *pin;
|
||||
int i, type, version, count = 0, success = 0, death = 0, confirm = 0;
|
||||
Key **keys = NULL, *k;
|
||||
Identity *id;
|
||||
Idtab *tab;
|
||||
|
||||
sc_reader_id = buffer_get_string(&e->request, NULL);
|
||||
provider = buffer_get_string(&e->request, NULL);
|
||||
pin = buffer_get_string(&e->request, NULL);
|
||||
|
||||
while (buffer_len(&e->request)) {
|
||||
@ -634,30 +659,22 @@ process_add_smartcard_key(SocketEntry *e)
|
||||
default:
|
||||
error("process_add_smartcard_key: "
|
||||
"Unknown constraint type %d", type);
|
||||
xfree(sc_reader_id);
|
||||
xfree(pin);
|
||||
goto send;
|
||||
}
|
||||
}
|
||||
if (lifetime && !death)
|
||||
death = time(NULL) + lifetime;
|
||||
|
||||
keys = sc_get_keys(sc_reader_id, pin);
|
||||
xfree(sc_reader_id);
|
||||
xfree(pin);
|
||||
|
||||
if (keys == NULL || keys[0] == NULL) {
|
||||
error("sc_get_keys failed");
|
||||
goto send;
|
||||
}
|
||||
for (i = 0; keys[i] != NULL; i++) {
|
||||
count = pkcs11_add_provider(provider, pin, &keys);
|
||||
for (i = 0; i < count; i++) {
|
||||
k = keys[i];
|
||||
version = k->type == KEY_RSA1 ? 1 : 2;
|
||||
tab = idtab_lookup(version);
|
||||
if (lookup_identity(k, version) == NULL) {
|
||||
id = xmalloc(sizeof(Identity));
|
||||
id = xcalloc(1, sizeof(Identity));
|
||||
id->key = k;
|
||||
id->comment = sc_get_key_label(k);
|
||||
id->provider = xstrdup(provider);
|
||||
id->comment = xstrdup(provider); /* XXX */
|
||||
id->death = death;
|
||||
id->confirm = confirm;
|
||||
TAILQ_INSERT_TAIL(&tab->idlist, id, next);
|
||||
@ -668,8 +685,13 @@ process_add_smartcard_key(SocketEntry *e)
|
||||
}
|
||||
keys[i] = NULL;
|
||||
}
|
||||
xfree(keys);
|
||||
send:
|
||||
if (pin)
|
||||
xfree(pin);
|
||||
if (provider)
|
||||
xfree(provider);
|
||||
if (keys)
|
||||
xfree(keys);
|
||||
buffer_put_int(&e->output, 1);
|
||||
buffer_put_char(&e->output,
|
||||
success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
|
||||
@ -678,42 +700,37 @@ process_add_smartcard_key(SocketEntry *e)
|
||||
static void
|
||||
process_remove_smartcard_key(SocketEntry *e)
|
||||
{
|
||||
char *sc_reader_id = NULL, *pin;
|
||||
int i, version, success = 0;
|
||||
Key **keys, *k = NULL;
|
||||
Identity *id;
|
||||
char *provider = NULL, *pin = NULL;
|
||||
int version, success = 0;
|
||||
Identity *id, *nxt;
|
||||
Idtab *tab;
|
||||
|
||||
sc_reader_id = buffer_get_string(&e->request, NULL);
|
||||
provider = buffer_get_string(&e->request, NULL);
|
||||
pin = buffer_get_string(&e->request, NULL);
|
||||
keys = sc_get_keys(sc_reader_id, pin);
|
||||
xfree(sc_reader_id);
|
||||
xfree(pin);
|
||||
|
||||
if (keys == NULL || keys[0] == NULL) {
|
||||
error("sc_get_keys failed");
|
||||
goto send;
|
||||
}
|
||||
for (i = 0; keys[i] != NULL; i++) {
|
||||
k = keys[i];
|
||||
version = k->type == KEY_RSA1 ? 1 : 2;
|
||||
if ((id = lookup_identity(k, version)) != NULL) {
|
||||
tab = idtab_lookup(version);
|
||||
TAILQ_REMOVE(&tab->idlist, id, next);
|
||||
tab->nentries--;
|
||||
free_identity(id);
|
||||
success = 1;
|
||||
for (version = 1; version < 3; version++) {
|
||||
tab = idtab_lookup(version);
|
||||
for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) {
|
||||
nxt = TAILQ_NEXT(id, next);
|
||||
if (!strcmp(provider, id->provider)) {
|
||||
TAILQ_REMOVE(&tab->idlist, id, next);
|
||||
free_identity(id);
|
||||
tab->nentries--;
|
||||
}
|
||||
}
|
||||
key_free(k);
|
||||
keys[i] = NULL;
|
||||
}
|
||||
xfree(keys);
|
||||
send:
|
||||
if (pkcs11_del_provider(provider) == 0)
|
||||
success = 1;
|
||||
else
|
||||
error("process_remove_smartcard_key:"
|
||||
" pkcs11_del_provider failed");
|
||||
xfree(provider);
|
||||
buffer_put_int(&e->output, 1);
|
||||
buffer_put_char(&e->output,
|
||||
success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
|
||||
}
|
||||
#endif /* SMARTCARD */
|
||||
#endif /* ENABLE_PKCS11 */
|
||||
|
||||
/* dispatch incoming messages */
|
||||
|
||||
@ -798,7 +815,7 @@ process_message(SocketEntry *e)
|
||||
case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
|
||||
process_remove_all_identities(e, 2);
|
||||
break;
|
||||
#ifdef SMARTCARD
|
||||
#ifdef ENABLE_PKCS11
|
||||
case SSH_AGENTC_ADD_SMARTCARD_KEY:
|
||||
case SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED:
|
||||
process_add_smartcard_key(e);
|
||||
@ -806,7 +823,7 @@ process_message(SocketEntry *e)
|
||||
case SSH_AGENTC_REMOVE_SMARTCARD_KEY:
|
||||
process_remove_smartcard_key(e);
|
||||
break;
|
||||
#endif /* SMARTCARD */
|
||||
#endif /* ENABLE_PKCS11 */
|
||||
default:
|
||||
/* Unknown message. Respond with failure. */
|
||||
error("Unknown message %d", type);
|
||||
@ -920,11 +937,11 @@ after_select(fd_set *readset, fd_set *writeset)
|
||||
socklen_t slen;
|
||||
char buf[1024];
|
||||
int len, sock;
|
||||
u_int i;
|
||||
u_int i, orig_alloc;
|
||||
uid_t euid;
|
||||
gid_t egid;
|
||||
|
||||
for (i = 0; i < sockets_alloc; i++)
|
||||
for (i = 0, orig_alloc = sockets_alloc; i < orig_alloc; i++)
|
||||
switch (sockets[i].type) {
|
||||
case AUTH_UNUSED:
|
||||
break;
|
||||
@ -957,16 +974,13 @@ after_select(fd_set *readset, fd_set *writeset)
|
||||
case AUTH_CONNECTION:
|
||||
if (buffer_len(&sockets[i].output) > 0 &&
|
||||
FD_ISSET(sockets[i].fd, writeset)) {
|
||||
do {
|
||||
len = write(sockets[i].fd,
|
||||
buffer_ptr(&sockets[i].output),
|
||||
buffer_len(&sockets[i].output));
|
||||
if (len == -1 && (errno == EAGAIN ||
|
||||
errno == EINTR ||
|
||||
errno == EWOULDBLOCK))
|
||||
continue;
|
||||
break;
|
||||
} while (1);
|
||||
len = write(sockets[i].fd,
|
||||
buffer_ptr(&sockets[i].output),
|
||||
buffer_len(&sockets[i].output));
|
||||
if (len == -1 && (errno == EAGAIN ||
|
||||
errno == EWOULDBLOCK ||
|
||||
errno == EINTR))
|
||||
continue;
|
||||
if (len <= 0) {
|
||||
close_socket(&sockets[i]);
|
||||
break;
|
||||
@ -974,14 +988,11 @@ after_select(fd_set *readset, fd_set *writeset)
|
||||
buffer_consume(&sockets[i].output, len);
|
||||
}
|
||||
if (FD_ISSET(sockets[i].fd, readset)) {
|
||||
do {
|
||||
len = read(sockets[i].fd, buf, sizeof(buf));
|
||||
if (len == -1 && (errno == EAGAIN ||
|
||||
errno == EINTR ||
|
||||
errno == EWOULDBLOCK))
|
||||
continue;
|
||||
break;
|
||||
} while (1);
|
||||
len = read(sockets[i].fd, buf, sizeof(buf));
|
||||
if (len == -1 && (errno == EAGAIN ||
|
||||
errno == EWOULDBLOCK ||
|
||||
errno == EINTR))
|
||||
continue;
|
||||
if (len <= 0) {
|
||||
close_socket(&sockets[i]);
|
||||
break;
|
||||
@ -1016,6 +1027,9 @@ static void
|
||||
cleanup_handler(int sig)
|
||||
{
|
||||
cleanup_socket();
|
||||
#ifdef ENABLE_PKCS11
|
||||
pkcs11_terminate();
|
||||
#endif
|
||||
_exit(2);
|
||||
}
|
||||
|
||||
@ -1263,6 +1277,10 @@ main(int ac, char **av)
|
||||
#endif
|
||||
|
||||
skip:
|
||||
|
||||
#ifdef ENABLE_PKCS11
|
||||
pkcs11_init(0);
|
||||
#endif
|
||||
new_socket(AUTH_SOCKET, sock);
|
||||
if (ac > 0)
|
||||
parent_alive_interval = 10;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ssh-dss.c,v 1.24 2006/11/06 21:25:28 markus Exp $ */
|
||||
/* $OpenBSD: ssh-dss.c,v 1.25 2010/02/26 20:29:54 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -53,7 +53,9 @@ 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->dsa == NULL) {
|
||||
if (key == NULL ||
|
||||
(key->type != KEY_DSA && key->type != KEY_DSA_CERT) ||
|
||||
key->dsa == NULL) {
|
||||
error("ssh_dss_sign: no DSA key");
|
||||
return -1;
|
||||
}
|
||||
@ -116,7 +118,9 @@ 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->dsa == NULL) {
|
||||
if (key == NULL ||
|
||||
(key->type != KEY_DSA && key->type != KEY_DSA_CERT) ||
|
||||
key->dsa == NULL) {
|
||||
error("ssh_dss_verify: no DSA key");
|
||||
return -1;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: ssh-keygen.1,v 1.79 2008/07/24 23:55:30 sthen Exp $
|
||||
.\" $OpenBSD: ssh-keygen.1,v 1.88 2010/03/08 00:28:55 djm Exp $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.\" -*- nroff -*-
|
||||
@ -38,7 +38,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 July 24 2008
|
||||
.Dd March 8 2010
|
||||
.Dt SSH-KEYGEN 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -53,7 +53,6 @@
|
||||
.Op Fl N Ar new_passphrase
|
||||
.Op Fl C Ar comment
|
||||
.Op Fl f Ar output_keyfile
|
||||
.Ek
|
||||
.Nm ssh-keygen
|
||||
.Fl p
|
||||
.Op Fl P Ar old_passphrase
|
||||
@ -80,7 +79,7 @@
|
||||
.Fl B
|
||||
.Op Fl f Ar input_keyfile
|
||||
.Nm ssh-keygen
|
||||
.Fl D Ar reader
|
||||
.Fl D Ar pkcs11
|
||||
.Nm ssh-keygen
|
||||
.Fl F Ar hostname
|
||||
.Op Fl f Ar known_hosts_file
|
||||
@ -92,9 +91,6 @@
|
||||
.Fl R Ar hostname
|
||||
.Op Fl f Ar known_hosts_file
|
||||
.Nm ssh-keygen
|
||||
.Fl U Ar reader
|
||||
.Op Fl f Ar input_keyfile
|
||||
.Nm ssh-keygen
|
||||
.Fl r Ar hostname
|
||||
.Op Fl f Ar input_keyfile
|
||||
.Op Fl g
|
||||
@ -110,6 +106,18 @@
|
||||
.Op Fl v
|
||||
.Op Fl a Ar num_trials
|
||||
.Op Fl W Ar generator
|
||||
.Nm ssh-keygen
|
||||
.Fl s Ar ca_key
|
||||
.Fl I Ar certificate_identity
|
||||
.Op Fl h
|
||||
.Op Fl n Ar principals
|
||||
.Op Fl O Ar constraint
|
||||
.Op Fl V Ar validity_interval
|
||||
.Ar
|
||||
.Nm ssh-keygen
|
||||
.Fl L
|
||||
.Op Fl f Ar input_keyfile
|
||||
.Ek
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
generates, manages and converts authentication keys for
|
||||
@ -202,9 +210,9 @@ Requests changing the comment in the private and public key files.
|
||||
This operation is only supported for RSA1 keys.
|
||||
The program will prompt for the file containing the private keys, for
|
||||
the passphrase if the key has one, and for the new comment.
|
||||
.It Fl D Ar reader
|
||||
Download the RSA public key stored in the smartcard in
|
||||
.Ar reader .
|
||||
.It Fl D Ar pkcs11
|
||||
Download the RSA public keys provided by the PKCS#11 shared library
|
||||
.Ar pkcs11 .
|
||||
.It Fl e
|
||||
This option will read a private or public OpenSSH key file and
|
||||
print the key in
|
||||
@ -249,6 +257,17 @@ but they do not reveal identifying information should the file's contents
|
||||
be disclosed.
|
||||
This option will not modify existing hashed hostnames and is therefore safe
|
||||
to use on files that mix hashed and non-hashed names.
|
||||
.It Fl h
|
||||
When signing a key, create a host certificate instead of a user
|
||||
certificate.
|
||||
Please see the
|
||||
.Sx CERTIFICATES
|
||||
section for details.
|
||||
.It Fl I Ar certificate_identity
|
||||
Specify the key identity when signing a public key.
|
||||
Please see the
|
||||
.Sx CERTIFICATES
|
||||
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
|
||||
@ -258,6 +277,8 @@ also reads the
|
||||
RFC 4716 SSH Public Key File Format.
|
||||
This option allows importing keys from several commercial
|
||||
SSH implementations.
|
||||
.It Fl L
|
||||
Prints the contents of a certificate.
|
||||
.It Fl l
|
||||
Show fingerprint of specified public key file.
|
||||
Private RSA1 keys are also supported.
|
||||
@ -272,6 +293,71 @@ Specify the amount of memory to use (in megabytes) when generating
|
||||
candidate moduli for DH-GEX.
|
||||
.It Fl N Ar new_passphrase
|
||||
Provides the new passphrase.
|
||||
.It Fl n Ar principals
|
||||
Specify one or more principals (user or host names) to be included in
|
||||
a certificate when signing a key.
|
||||
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.
|
||||
This option may be specified multiple times.
|
||||
Please see the
|
||||
.Sx CERTIFICATES
|
||||
section for details.
|
||||
The constraints that are valid for user certificates are:
|
||||
.Bl -tag -width Ds
|
||||
.It Ic no-x11-forwarding
|
||||
Disable X11 forwarding (permitted by default).
|
||||
.It Ic no-agent-forwarding
|
||||
Disable
|
||||
.Xr ssh-agent 1
|
||||
forwarding (permitted by default).
|
||||
.It Ic no-port-forwarding
|
||||
Disable port forwarding (permitted by default).
|
||||
.It Ic no-pty
|
||||
Disable PTY allocation (permitted by default).
|
||||
.It Ic no-user-rc
|
||||
Disable execution of
|
||||
.Pa ~/.ssh/rc
|
||||
by
|
||||
.Xr sshd 8
|
||||
(permitted by default).
|
||||
.It Ic clear
|
||||
Clear all enabled permissions.
|
||||
This is useful for clearing the default set of permissions so permissions may
|
||||
be added individually.
|
||||
.It Ic permit-x11-forwarding
|
||||
Allows X11 forwarding.
|
||||
.It Ic permit-agent-forwarding
|
||||
Allows
|
||||
.Xr ssh-agent 1
|
||||
forwarding.
|
||||
.It Ic permit-port-forwarding
|
||||
Allows port forwarding.
|
||||
.It Ic permit-pty
|
||||
Allows PTY allocation.
|
||||
.It Ic permit-user-rc
|
||||
Allows execution of
|
||||
.Pa ~/.ssh/rc
|
||||
by
|
||||
.Xr sshd 8 .
|
||||
.It Ic force-command=command
|
||||
Forces the execution of
|
||||
.Ar command
|
||||
instead of any shell or command specified by the user when
|
||||
the certificate is used for authentication.
|
||||
.It Ic source-address=address_list
|
||||
Restrict the source addresses from which the certificate is considered valid
|
||||
from.
|
||||
The
|
||||
.Ar address_list
|
||||
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.
|
||||
.It Fl P Ar passphrase
|
||||
Provides the (old) passphrase.
|
||||
.It Fl p
|
||||
@ -301,6 +387,11 @@ Print the SSHFP fingerprint resource record named
|
||||
for the specified public key file.
|
||||
.It Fl S Ar start
|
||||
Specify start point (in hex) when generating candidate moduli for DH-GEX.
|
||||
.It Fl s Ar ca_key
|
||||
Certify (sign) a public key using the specified CA key.
|
||||
Please see the
|
||||
.Sx CERTIFICATES
|
||||
section for details.
|
||||
.It Fl T Ar output_file
|
||||
Test DH group exchange candidate primes (generated using the
|
||||
.Fl G
|
||||
@ -314,9 +405,29 @@ for protocol version 1 and
|
||||
or
|
||||
.Dq dsa
|
||||
for protocol version 2.
|
||||
.It Fl U Ar reader
|
||||
Upload an existing RSA private key into the smartcard in
|
||||
.Ar reader .
|
||||
.It Fl V Ar validity_interval
|
||||
Specify a validity interval when signing a certificate.
|
||||
A validity interval may consist of a single time, indicating that the
|
||||
certificate is valid beginning now and expiring at that time, or may consist
|
||||
of two times separated by a colon to indicate an explicit time interval.
|
||||
The start time may be specified as a date in YYYYMMDD format, a time
|
||||
in YYYYMMDDHHMMSS format or a relative time (to the current time) consisting
|
||||
of a minus sign followed by a relative time in the format described in the
|
||||
.Sx TIME FORMATS
|
||||
section of
|
||||
.Xr ssh_config 5 .
|
||||
The end time may be specified as a YYYYMMDD date, a YYYYMMDDHHMMSS time or
|
||||
a relative time starting with a plus character.
|
||||
.Pp
|
||||
For example:
|
||||
.Dq +52w1d
|
||||
(valid from now to 52 weeks and one day from now),
|
||||
.Dq -4w:+4w
|
||||
(valid from four weeks ago to four weeks from now),
|
||||
.Dq 20100101123000:20110101123000
|
||||
(valid from 12:30 PM, January 1st, 2010 to 12:30 PM, January 1st, 2011),
|
||||
.Dq -1d:20110101
|
||||
(valid from yesterday to midnight, January 1st, 2011).
|
||||
.It Fl v
|
||||
Verbose mode.
|
||||
Causes
|
||||
@ -387,6 +498,73 @@ Screened DH groups may be installed in
|
||||
.Pa /etc/moduli .
|
||||
It is important that this file contains moduli of a range of bit lengths and
|
||||
that both ends of a connection share common moduli.
|
||||
.Sh CERTIFICATES
|
||||
.Nm
|
||||
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
|
||||
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.
|
||||
Note that OpenSSH certificates are a different, and much simpler, format to
|
||||
the X.509 certificates used in
|
||||
.Xr ssl 8 .
|
||||
.Pp
|
||||
.Nm
|
||||
supports two types of certificates: user and host.
|
||||
User certificates authenticate users to servers, whereas host certificates
|
||||
authenticate server hosts to users.
|
||||
To generate a user certificate:
|
||||
.Pp
|
||||
.Dl $ ssh-keygen -s /path/to/ca_key -I key_id /path/to/user_key.pub
|
||||
.Pp
|
||||
The resultant certificate will be placed in
|
||||
.Pa /path/to/user_key_cert.pub .
|
||||
A host certificate requires the
|
||||
.Fl h
|
||||
option:
|
||||
.Pp
|
||||
.Dl $ ssh-keygen -s /path/to/ca_key -I key_id -h /path/to/host_key.pub
|
||||
.Pp
|
||||
The host certificate will be output to
|
||||
.Pa /path/to/host_key_cert.pub .
|
||||
In both cases,
|
||||
.Ar key_id
|
||||
is a "key identifier" that is logged by the server when the certificate
|
||||
is used for authentication.
|
||||
.Pp
|
||||
Certificates may be limited to be valid for a set of principal (user/host)
|
||||
names.
|
||||
By default, generated certificates are valid for all users or hosts.
|
||||
To generate a certificate for a specified set of principals:
|
||||
.Pp
|
||||
.Dl $ ssh-keygen -s ca_key -I key_id -n user1,user2 user_key.pub
|
||||
.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
|
||||
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
|
||||
.Fl O
|
||||
option above.
|
||||
.Pp
|
||||
Finally, certificates may be defined with a validity lifetime.
|
||||
The
|
||||
.Fl V
|
||||
option allows specification of certificate start and end times.
|
||||
A certificate that is presented at a time outside this range will not be
|
||||
considered valid.
|
||||
By default, certificates have a maximum validity interval.
|
||||
.Pp
|
||||
For certificates to be used for user or host authentication, the CA
|
||||
public key must be trusted by
|
||||
.Xr sshd 8
|
||||
or
|
||||
.Xr ssh 1 .
|
||||
Please refer to those manual pages for details.
|
||||
.Sh FILES
|
||||
.Bl -tag -width Ds
|
||||
.It Pa ~/.ssh/identity
|
||||
@ -394,7 +572,7 @@ Contains the protocol version 1 RSA authentication identity of the user.
|
||||
This file should not be readable by anyone but the user.
|
||||
It is possible to
|
||||
specify a passphrase when generating the key; that passphrase will be
|
||||
used to encrypt the private part of this file using 3DES.
|
||||
used to encrypt the private part of this file using 128-bit AES.
|
||||
This file is not automatically accessed by
|
||||
.Nm
|
||||
but it is offered as the default file for the private key.
|
||||
@ -412,7 +590,7 @@ Contains the protocol version 2 DSA authentication identity of the user.
|
||||
This file should not be readable by anyone but the user.
|
||||
It is possible to
|
||||
specify a passphrase when generating the key; that passphrase will be
|
||||
used to encrypt the private part of this file using 3DES.
|
||||
used to encrypt the private part of this file using 128-bit AES.
|
||||
This file is not automatically accessed by
|
||||
.Nm
|
||||
but it is offered as the default file for the private key.
|
||||
@ -430,7 +608,7 @@ Contains the protocol version 2 RSA authentication identity of the user.
|
||||
This file should not be readable by anyone but the user.
|
||||
It is possible to
|
||||
specify a passphrase when generating the key; that passphrase will be
|
||||
used to encrypt the private part of this file using 3DES.
|
||||
used to encrypt the private part of this file using 128-bit AES.
|
||||
This file is not automatically accessed by
|
||||
.Nm
|
||||
but it is offered as the default file for the private key.
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ssh-keygen.c,v 1.174 2009/06/22 05:39:28 dtucker Exp $ */
|
||||
/* $OpenBSD: ssh-keygen.c,v 1.184 2010/03/07 22:16:01 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -48,9 +48,10 @@
|
||||
#include "match.h"
|
||||
#include "hostfile.h"
|
||||
#include "dns.h"
|
||||
#include "ssh2.h"
|
||||
|
||||
#ifdef SMARTCARD
|
||||
#include "scard.h"
|
||||
#ifdef ENABLE_PKCS11
|
||||
#include "ssh-pkcs11.h"
|
||||
#endif
|
||||
|
||||
/* Number of bits in the RSA/DSA key. This value can be set on the command line. */
|
||||
@ -81,6 +82,9 @@ int find_host = 0;
|
||||
/* Flag indicating that we want to delete a host from a known_hosts file */
|
||||
int delete_host = 0;
|
||||
|
||||
/* Flag indicating that we want to show the contents of a certificate */
|
||||
int show_cert = 0;
|
||||
|
||||
/* Flag indicating that we just want to see the key fingerprint */
|
||||
int print_fingerprint = 0;
|
||||
int print_bubblebabble = 0;
|
||||
@ -98,6 +102,35 @@ char *identity_new_passphrase = NULL;
|
||||
/* This is set to the new comment if given on the command line. */
|
||||
char *identity_comment = NULL;
|
||||
|
||||
/* Path to CA key when certifying keys. */
|
||||
char *ca_key_path = NULL;
|
||||
|
||||
/* Key type when certifying */
|
||||
u_int cert_key_type = SSH2_CERT_TYPE_USER;
|
||||
|
||||
/* "key ID" of signed key */
|
||||
char *cert_key_id = NULL;
|
||||
|
||||
/* Comma-separated list of principal names for certifying keys */
|
||||
char *cert_principals = NULL;
|
||||
|
||||
/* Validity period for certificates */
|
||||
u_int64_t cert_valid_from = 0;
|
||||
u_int64_t cert_valid_to = ~0ULL;
|
||||
|
||||
/* Certificate constraints */
|
||||
#define CONSTRAINT_X_FWD (1)
|
||||
#define CONSTRAINT_AGENT_FWD (1<<1)
|
||||
#define CONSTRAINT_PORT_FWD (1<<2)
|
||||
#define CONSTRAINT_PTY (1<<3)
|
||||
#define CONSTRAINT_USER_RC (1<<4)
|
||||
#define CONSTRAINT_DEFAULT (CONSTRAINT_X_FWD|CONSTRAINT_AGENT_FWD| \
|
||||
CONSTRAINT_PORT_FWD|CONSTRAINT_PTY| \
|
||||
CONSTRAINT_USER_RC)
|
||||
u_int32_t constraint_flags = CONSTRAINT_DEFAULT;
|
||||
char *constraint_command = NULL;
|
||||
char *constraint_src_addr = NULL;
|
||||
|
||||
/* Dump public key file in format used by real and the original SSH 2 */
|
||||
int convert_to_ssh2 = 0;
|
||||
int convert_from_ssh2 = 0;
|
||||
@ -181,6 +214,7 @@ do_convert_to_ssh2(struct passwd *pw)
|
||||
Key *k;
|
||||
u_int len;
|
||||
u_char *blob;
|
||||
char comment[61];
|
||||
struct stat st;
|
||||
|
||||
if (!have_identity)
|
||||
@ -203,11 +237,14 @@ do_convert_to_ssh2(struct passwd *pw)
|
||||
fprintf(stderr, "key_to_blob failed\n");
|
||||
exit(1);
|
||||
}
|
||||
fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
|
||||
fprintf(stdout,
|
||||
"Comment: \"%u-bit %s, converted from OpenSSH by %s@%s\"\n",
|
||||
/* Comment + surrounds must fit into 72 chars (RFC 4716 sec 3.3) */
|
||||
snprintf(comment, sizeof(comment),
|
||||
"%u-bit %s, converted by %s@%s from OpenSSH",
|
||||
key_size(k), key_type(k),
|
||||
pw->pw_name, hostname);
|
||||
|
||||
fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
|
||||
fprintf(stdout, "Comment: \"%s\"\n", comment);
|
||||
dump_base64(stdout, blob, len);
|
||||
fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END);
|
||||
key_free(k);
|
||||
@ -455,51 +492,29 @@ do_print_public(struct passwd *pw)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#ifdef SMARTCARD
|
||||
static void
|
||||
do_upload(struct passwd *pw, const char *sc_reader_id)
|
||||
{
|
||||
Key *prv = NULL;
|
||||
struct stat st;
|
||||
int ret;
|
||||
|
||||
if (!have_identity)
|
||||
ask_filename(pw, "Enter file in which the key is");
|
||||
if (stat(identity_file, &st) < 0) {
|
||||
perror(identity_file);
|
||||
exit(1);
|
||||
}
|
||||
prv = load_identity(identity_file);
|
||||
if (prv == NULL) {
|
||||
error("load failed");
|
||||
exit(1);
|
||||
}
|
||||
ret = sc_put_key(prv, sc_reader_id);
|
||||
key_free(prv);
|
||||
if (ret < 0)
|
||||
exit(1);
|
||||
logit("loading key done");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void
|
||||
do_download(struct passwd *pw, const char *sc_reader_id)
|
||||
do_download(struct passwd *pw, char *pkcs11provider)
|
||||
{
|
||||
#ifdef ENABLE_PKCS11
|
||||
Key **keys = NULL;
|
||||
int i;
|
||||
int i, nkeys;
|
||||
|
||||
keys = sc_get_keys(sc_reader_id, NULL);
|
||||
if (keys == NULL)
|
||||
fatal("cannot read public key from smartcard");
|
||||
for (i = 0; keys[i]; i++) {
|
||||
pkcs11_init(0);
|
||||
nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys);
|
||||
if (nkeys <= 0)
|
||||
fatal("cannot read public key from pkcs11");
|
||||
for (i = 0; i < nkeys; i++) {
|
||||
key_write(keys[i], stdout);
|
||||
key_free(keys[i]);
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
xfree(keys);
|
||||
pkcs11_terminate();
|
||||
exit(0);
|
||||
#else
|
||||
fatal("no pkcs11 support");
|
||||
#endif /* ENABLE_PKCS11 */
|
||||
}
|
||||
#endif /* SMARTCARD */
|
||||
|
||||
static void
|
||||
do_fingerprint(struct passwd *pw)
|
||||
@ -524,7 +539,7 @@ do_fingerprint(struct passwd *pw)
|
||||
public = key_load_public(identity_file, &comment);
|
||||
if (public != NULL) {
|
||||
fp = key_fingerprint(public, fptype, rep);
|
||||
ra = key_fingerprint(public, fptype, SSH_FP_RANDOMART);
|
||||
ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
|
||||
printf("%u %s %s (%s)\n", key_size(public), fp, comment,
|
||||
key_type(public));
|
||||
if (log_level >= SYSLOG_LEVEL_VERBOSE)
|
||||
@ -589,7 +604,7 @@ do_fingerprint(struct passwd *pw)
|
||||
}
|
||||
comment = *cp ? cp : comment;
|
||||
fp = key_fingerprint(public, fptype, rep);
|
||||
ra = key_fingerprint(public, fptype, SSH_FP_RANDOMART);
|
||||
ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
|
||||
printf("%u %s %s (%s)\n", key_size(public), fp,
|
||||
comment ? comment : "no comment", key_type(public));
|
||||
if (log_level >= SYSLOG_LEVEL_VERBOSE)
|
||||
@ -609,7 +624,7 @@ do_fingerprint(struct passwd *pw)
|
||||
}
|
||||
|
||||
static void
|
||||
print_host(FILE *f, const char *name, Key *public, int hash)
|
||||
printhost(FILE *f, const char *name, Key *public, int ca, int hash)
|
||||
{
|
||||
if (print_fingerprint) {
|
||||
enum fp_rep rep;
|
||||
@ -619,7 +634,7 @@ print_host(FILE *f, const char *name, Key *public, int hash)
|
||||
fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
|
||||
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
|
||||
fp = key_fingerprint(public, fptype, rep);
|
||||
ra = key_fingerprint(public, fptype, SSH_FP_RANDOMART);
|
||||
ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
|
||||
printf("%u %s %s (%s)\n", key_size(public), fp, name,
|
||||
key_type(public));
|
||||
if (log_level >= SYSLOG_LEVEL_VERBOSE)
|
||||
@ -629,7 +644,7 @@ print_host(FILE *f, const char *name, Key *public, int hash)
|
||||
} else {
|
||||
if (hash && (name = host_hash(name, NULL, 0)) == NULL)
|
||||
fatal("hash_host failed");
|
||||
fprintf(f, "%s ", name);
|
||||
fprintf(f, "%s%s%s ", ca ? CA_MARKER : "", ca ? " " : "", name);
|
||||
if (!key_write(public, f))
|
||||
fatal("key_write failed");
|
||||
fprintf(f, "\n");
|
||||
@ -640,10 +655,11 @@ static void
|
||||
do_known_hosts(struct passwd *pw, const char *name)
|
||||
{
|
||||
FILE *in, *out = stdout;
|
||||
Key *public;
|
||||
Key *pub;
|
||||
char *cp, *cp2, *kp, *kp2;
|
||||
char line[16*1024], tmp[MAXPATHLEN], old[MAXPATHLEN];
|
||||
int c, skip = 0, inplace = 0, num = 0, invalid = 0, has_unhashed = 0;
|
||||
int ca;
|
||||
|
||||
if (!have_identity) {
|
||||
cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid);
|
||||
@ -699,9 +715,19 @@ do_known_hosts(struct passwd *pw, const char *name)
|
||||
fprintf(out, "%s\n", cp);
|
||||
continue;
|
||||
}
|
||||
/* Check whether this is a CA key */
|
||||
if (strncasecmp(cp, CA_MARKER, sizeof(CA_MARKER) - 1) == 0 &&
|
||||
(cp[sizeof(CA_MARKER) - 1] == ' ' ||
|
||||
cp[sizeof(CA_MARKER) - 1] == '\t')) {
|
||||
ca = 1;
|
||||
cp += sizeof(CA_MARKER);
|
||||
} else
|
||||
ca = 0;
|
||||
|
||||
/* Find the end of the host name portion. */
|
||||
for (kp = cp; *kp && *kp != ' ' && *kp != '\t'; kp++)
|
||||
;
|
||||
|
||||
if (*kp == '\0' || *(kp + 1) == '\0') {
|
||||
error("line %d missing key: %.40s...",
|
||||
num, line);
|
||||
@ -711,15 +737,15 @@ do_known_hosts(struct passwd *pw, const char *name)
|
||||
*kp++ = '\0';
|
||||
kp2 = kp;
|
||||
|
||||
public = key_new(KEY_RSA1);
|
||||
if (key_read(public, &kp) != 1) {
|
||||
pub = key_new(KEY_RSA1);
|
||||
if (key_read(pub, &kp) != 1) {
|
||||
kp = kp2;
|
||||
key_free(public);
|
||||
public = key_new(KEY_UNSPEC);
|
||||
if (key_read(public, &kp) != 1) {
|
||||
key_free(pub);
|
||||
pub = key_new(KEY_UNSPEC);
|
||||
if (key_read(pub, &kp) != 1) {
|
||||
error("line %d invalid key: %.40s...",
|
||||
num, line);
|
||||
key_free(public);
|
||||
key_free(pub);
|
||||
invalid = 1;
|
||||
continue;
|
||||
}
|
||||
@ -737,43 +763,52 @@ do_known_hosts(struct passwd *pw, const char *name)
|
||||
c = (strcmp(cp2, cp) == 0);
|
||||
if (find_host && c) {
|
||||
printf("# Host %s found: "
|
||||
"line %d type %s\n", name,
|
||||
num, key_type(public));
|
||||
print_host(out, cp, public, 0);
|
||||
"line %d type %s%s\n", name,
|
||||
num, key_type(pub),
|
||||
ca ? " (CA key)" : "");
|
||||
printhost(out, cp, pub, ca, 0);
|
||||
}
|
||||
if (delete_host && !c)
|
||||
print_host(out, cp, public, 0);
|
||||
if (delete_host && !c && !ca)
|
||||
printhost(out, cp, pub, ca, 0);
|
||||
} else if (hash_hosts)
|
||||
print_host(out, cp, public, 0);
|
||||
printhost(out, cp, pub, ca, 0);
|
||||
} else {
|
||||
if (find_host || delete_host) {
|
||||
c = (match_hostname(name, cp,
|
||||
strlen(cp)) == 1);
|
||||
if (find_host && c) {
|
||||
printf("# Host %s found: "
|
||||
"line %d type %s\n", name,
|
||||
num, key_type(public));
|
||||
print_host(out, name, public,
|
||||
hash_hosts);
|
||||
"line %d type %s%s\n", name,
|
||||
num, key_type(pub),
|
||||
ca ? " (CA key)" : "");
|
||||
printhost(out, name, pub,
|
||||
ca, hash_hosts && !ca);
|
||||
}
|
||||
if (delete_host && !c)
|
||||
print_host(out, cp, public, 0);
|
||||
if (delete_host && !c && !ca)
|
||||
printhost(out, cp, pub, ca, 0);
|
||||
} else if (hash_hosts) {
|
||||
for (cp2 = strsep(&cp, ",");
|
||||
cp2 != NULL && *cp2 != '\0';
|
||||
cp2 = strsep(&cp, ",")) {
|
||||
if (strcspn(cp2, "*?!") != strlen(cp2))
|
||||
if (ca) {
|
||||
fprintf(stderr, "Warning: "
|
||||
"ignoring CA key for host: "
|
||||
"%.64s\n", cp2);
|
||||
printhost(out, cp2, pub, ca, 0);
|
||||
} else if (strcspn(cp2, "*?!") !=
|
||||
strlen(cp2)) {
|
||||
fprintf(stderr, "Warning: "
|
||||
"ignoring host name with "
|
||||
"metacharacters: %.64s\n",
|
||||
cp2);
|
||||
else
|
||||
print_host(out, cp2, public, 1);
|
||||
printhost(out, cp2, pub, ca, 0);
|
||||
} else
|
||||
printhost(out, cp2, pub, ca, 1);
|
||||
}
|
||||
has_unhashed = 1;
|
||||
}
|
||||
}
|
||||
key_free(public);
|
||||
key_free(pub);
|
||||
}
|
||||
fclose(in);
|
||||
|
||||
@ -1030,6 +1065,391 @@ do_change_comment(struct passwd *pw)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static const char *
|
||||
fmt_validity(u_int64_t valid_from, u_int64_t valid_to)
|
||||
{
|
||||
char from[32], to[32];
|
||||
static char ret[64];
|
||||
time_t tt;
|
||||
struct tm *tm;
|
||||
|
||||
*from = *to = '\0';
|
||||
if (valid_from == 0 && valid_to == 0xffffffffffffffffULL)
|
||||
return "forever";
|
||||
|
||||
if (valid_from != 0) {
|
||||
/* XXX revisit INT_MAX in 2038 :) */
|
||||
tt = valid_from > INT_MAX ? INT_MAX : valid_from;
|
||||
tm = localtime(&tt);
|
||||
strftime(from, sizeof(from), "%Y-%m-%dT%H:%M:%S", tm);
|
||||
}
|
||||
if (valid_to != 0xffffffffffffffffULL) {
|
||||
/* XXX revisit INT_MAX in 2038 :) */
|
||||
tt = valid_to > INT_MAX ? INT_MAX : valid_to;
|
||||
tm = localtime(&tt);
|
||||
strftime(to, sizeof(to), "%Y-%m-%dT%H:%M:%S", tm);
|
||||
}
|
||||
|
||||
if (valid_from == 0) {
|
||||
snprintf(ret, sizeof(ret), "before %s", to);
|
||||
return ret;
|
||||
}
|
||||
if (valid_to == 0xffffffffffffffffULL) {
|
||||
snprintf(ret, sizeof(ret), "after %s", from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
snprintf(ret, sizeof(ret), "from %s to %s", from, to);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
add_flag_constraint(Buffer *c, const char *name)
|
||||
{
|
||||
debug3("%s: %s", __func__, name);
|
||||
buffer_put_cstring(c, name);
|
||||
buffer_put_string(c, NULL, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
add_string_constraint(Buffer *c, const char *name, const char *value)
|
||||
{
|
||||
Buffer b;
|
||||
|
||||
debug3("%s: %s=%s", __func__, name, value);
|
||||
buffer_init(&b);
|
||||
buffer_put_cstring(&b, value);
|
||||
|
||||
buffer_put_cstring(c, name);
|
||||
buffer_put_string(c, buffer_ptr(&b), buffer_len(&b));
|
||||
|
||||
buffer_free(&b);
|
||||
}
|
||||
|
||||
static void
|
||||
prepare_constraint_buf(Buffer *c)
|
||||
{
|
||||
|
||||
buffer_clear(c);
|
||||
if ((constraint_flags & CONSTRAINT_X_FWD) != 0)
|
||||
add_flag_constraint(c, "permit-X11-forwarding");
|
||||
if ((constraint_flags & CONSTRAINT_AGENT_FWD) != 0)
|
||||
add_flag_constraint(c, "permit-agent-forwarding");
|
||||
if ((constraint_flags & CONSTRAINT_PORT_FWD) != 0)
|
||||
add_flag_constraint(c, "permit-port-forwarding");
|
||||
if ((constraint_flags & CONSTRAINT_PTY) != 0)
|
||||
add_flag_constraint(c, "permit-pty");
|
||||
if ((constraint_flags & CONSTRAINT_USER_RC) != 0)
|
||||
add_flag_constraint(c, "permit-user-rc");
|
||||
if (constraint_command != NULL)
|
||||
add_string_constraint(c, "force-command", constraint_command);
|
||||
if (constraint_src_addr != NULL)
|
||||
add_string_constraint(c, "source-address", constraint_src_addr);
|
||||
}
|
||||
|
||||
static void
|
||||
do_ca_sign(struct passwd *pw, int argc, char **argv)
|
||||
{
|
||||
int i, fd;
|
||||
u_int n;
|
||||
Key *ca, *public;
|
||||
char *otmp, *tmp, *cp, *out, *comment, **plist = NULL;
|
||||
FILE *f;
|
||||
|
||||
tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
|
||||
if ((ca = load_identity(tmp)) == NULL)
|
||||
fatal("Couldn't load CA key \"%s\"", tmp);
|
||||
xfree(tmp);
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
/* Split list of principals */
|
||||
n = 0;
|
||||
if (cert_principals != NULL) {
|
||||
otmp = tmp = xstrdup(cert_principals);
|
||||
plist = NULL;
|
||||
for (; (cp = strsep(&tmp, ",")) != NULL; n++) {
|
||||
plist = xrealloc(plist, n + 1, sizeof(*plist));
|
||||
if (*(plist[n] = xstrdup(cp)) == '\0')
|
||||
fatal("Empty principal name");
|
||||
}
|
||||
xfree(otmp);
|
||||
}
|
||||
|
||||
tmp = tilde_expand_filename(argv[i], pw->pw_uid);
|
||||
if ((public = key_load_public(tmp, &comment)) == NULL)
|
||||
fatal("%s: unable to open \"%s\"", __func__, tmp);
|
||||
if (public->type != KEY_RSA && public->type != KEY_DSA)
|
||||
fatal("%s: key \"%s\" type %s cannot be certified",
|
||||
__func__, tmp, key_type(public));
|
||||
|
||||
/* Prepare certificate to sign */
|
||||
if (key_to_certified(public) != 0)
|
||||
fatal("Could not upgrade key %s to certificate", tmp);
|
||||
public->cert->type = cert_key_type;
|
||||
public->cert->key_id = xstrdup(cert_key_id);
|
||||
public->cert->nprincipals = n;
|
||||
public->cert->principals = plist;
|
||||
public->cert->valid_after = cert_valid_from;
|
||||
public->cert->valid_before = cert_valid_to;
|
||||
prepare_constraint_buf(&public->cert->constraints);
|
||||
public->cert->signature_key = key_from_private(ca);
|
||||
|
||||
if (key_certify(public, ca) != 0)
|
||||
fatal("Couldn't not certify key %s", tmp);
|
||||
|
||||
if ((cp = strrchr(tmp, '.')) != NULL && strcmp(cp, ".pub") == 0)
|
||||
*cp = '\0';
|
||||
xasprintf(&out, "%s-cert.pub", tmp);
|
||||
xfree(tmp);
|
||||
|
||||
if ((fd = open(out, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
|
||||
fatal("Could not open \"%s\" for writing: %s", out,
|
||||
strerror(errno));
|
||||
if ((f = fdopen(fd, "w")) == NULL)
|
||||
fatal("%s: fdopen: %s", __func__, strerror(errno));
|
||||
if (!key_write(public, f))
|
||||
fatal("Could not write certified key to %s", out);
|
||||
fprintf(f, " %s\n", comment);
|
||||
fclose(f);
|
||||
|
||||
if (!quiet)
|
||||
logit("Signed %s key %s: id \"%s\"%s%s valid %s",
|
||||
cert_key_type == SSH2_CERT_TYPE_USER?"user":"host",
|
||||
out, cert_key_id,
|
||||
cert_principals != NULL ? " for " : "",
|
||||
cert_principals != NULL ? cert_principals : "",
|
||||
fmt_validity(cert_valid_from, cert_valid_to));
|
||||
|
||||
key_free(public);
|
||||
xfree(out);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static u_int64_t
|
||||
parse_relative_time(const char *s, time_t now)
|
||||
{
|
||||
int64_t mul, secs;
|
||||
|
||||
mul = *s == '-' ? -1 : 1;
|
||||
|
||||
if ((secs = convtime(s + 1)) == -1)
|
||||
fatal("Invalid relative certificate time %s", s);
|
||||
if (mul == -1 && secs > now)
|
||||
fatal("Certificate time %s cannot be represented", s);
|
||||
return now + (u_int64_t)(secs * mul);
|
||||
}
|
||||
|
||||
static u_int64_t
|
||||
parse_absolute_time(const char *s)
|
||||
{
|
||||
struct tm tm;
|
||||
time_t tt;
|
||||
char buf[32], *fmt;
|
||||
|
||||
/*
|
||||
* POSIX strptime says "The application shall ensure that there
|
||||
* is white-space or other non-alphanumeric characters between
|
||||
* any two conversion specifications" so arrange things this way.
|
||||
*/
|
||||
switch (strlen(s)) {
|
||||
case 8:
|
||||
fmt = "%Y-%m-%d";
|
||||
snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2s", s, s + 4, s + 6);
|
||||
break;
|
||||
case 14:
|
||||
fmt = "%Y-%m-%dT%H:%M:%S";
|
||||
snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2sT%.2s:%.2s:%.2s",
|
||||
s, s + 4, s + 6, s + 8, s + 10, s + 12);
|
||||
break;
|
||||
default:
|
||||
fatal("Invalid certificate time format %s", s);
|
||||
}
|
||||
|
||||
bzero(&tm, sizeof(tm));
|
||||
if (strptime(buf, fmt, &tm) == NULL)
|
||||
fatal("Invalid certificate time %s", s);
|
||||
if ((tt = mktime(&tm)) < 0)
|
||||
fatal("Certificate time %s cannot be represented", s);
|
||||
return (u_int64_t)tt;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_cert_times(char *timespec)
|
||||
{
|
||||
char *from, *to;
|
||||
time_t now = time(NULL);
|
||||
int64_t secs;
|
||||
|
||||
/* +timespec relative to now */
|
||||
if (*timespec == '+' && strchr(timespec, ':') == NULL) {
|
||||
if ((secs = convtime(timespec + 1)) == -1)
|
||||
fatal("Invalid relative certificate life %s", timespec);
|
||||
cert_valid_to = now + secs;
|
||||
/*
|
||||
* Backdate certificate one minute to avoid problems on hosts
|
||||
* with poorly-synchronised clocks.
|
||||
*/
|
||||
cert_valid_from = ((now - 59)/ 60) * 60;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* from:to, where
|
||||
* from := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS
|
||||
* to := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS
|
||||
*/
|
||||
from = xstrdup(timespec);
|
||||
to = strchr(from, ':');
|
||||
if (to == NULL || from == to || *(to + 1) == '\0')
|
||||
fatal("Invalid certificate life specification %s", timespec);
|
||||
*to++ = '\0';
|
||||
|
||||
if (*from == '-' || *from == '+')
|
||||
cert_valid_from = parse_relative_time(from, now);
|
||||
else
|
||||
cert_valid_from = parse_absolute_time(from);
|
||||
|
||||
if (*to == '-' || *to == '+')
|
||||
cert_valid_to = parse_relative_time(to, cert_valid_from);
|
||||
else
|
||||
cert_valid_to = parse_absolute_time(to);
|
||||
|
||||
if (cert_valid_to <= cert_valid_from)
|
||||
fatal("Empty certificate validity interval");
|
||||
xfree(from);
|
||||
}
|
||||
|
||||
static void
|
||||
add_cert_constraint(char *opt)
|
||||
{
|
||||
char *val;
|
||||
|
||||
if (strcmp(opt, "clear") == 0)
|
||||
constraint_flags = 0;
|
||||
else if (strcasecmp(opt, "no-x11-forwarding") == 0)
|
||||
constraint_flags &= ~CONSTRAINT_X_FWD;
|
||||
else if (strcasecmp(opt, "permit-x11-forwarding") == 0)
|
||||
constraint_flags |= CONSTRAINT_X_FWD;
|
||||
else if (strcasecmp(opt, "no-agent-forwarding") == 0)
|
||||
constraint_flags &= ~CONSTRAINT_AGENT_FWD;
|
||||
else if (strcasecmp(opt, "permit-agent-forwarding") == 0)
|
||||
constraint_flags |= CONSTRAINT_AGENT_FWD;
|
||||
else if (strcasecmp(opt, "no-port-forwarding") == 0)
|
||||
constraint_flags &= ~CONSTRAINT_PORT_FWD;
|
||||
else if (strcasecmp(opt, "permit-port-forwarding") == 0)
|
||||
constraint_flags |= CONSTRAINT_PORT_FWD;
|
||||
else if (strcasecmp(opt, "no-pty") == 0)
|
||||
constraint_flags &= ~CONSTRAINT_PTY;
|
||||
else if (strcasecmp(opt, "permit-pty") == 0)
|
||||
constraint_flags |= CONSTRAINT_PTY;
|
||||
else if (strcasecmp(opt, "no-user-rc") == 0)
|
||||
constraint_flags &= ~CONSTRAINT_USER_RC;
|
||||
else if (strcasecmp(opt, "permit-user-rc") == 0)
|
||||
constraint_flags |= CONSTRAINT_USER_RC;
|
||||
else if (strncasecmp(opt, "force-command=", 14) == 0) {
|
||||
val = opt + 14;
|
||||
if (*val == '\0')
|
||||
fatal("Empty force-command constraint");
|
||||
if (constraint_command != NULL)
|
||||
fatal("force-command already specified");
|
||||
constraint_command = xstrdup(val);
|
||||
} else if (strncasecmp(opt, "source-address=", 15) == 0) {
|
||||
val = opt + 15;
|
||||
if (*val == '\0')
|
||||
fatal("Empty source-address constraint");
|
||||
if (constraint_src_addr != NULL)
|
||||
fatal("source-address already specified");
|
||||
if (addr_match_cidr_list(NULL, val) != 0)
|
||||
fatal("Invalid source-address list");
|
||||
constraint_src_addr = xstrdup(val);
|
||||
} else
|
||||
fatal("Unsupported certificate constraint \"%s\"", opt);
|
||||
}
|
||||
|
||||
static void
|
||||
do_show_cert(struct passwd *pw)
|
||||
{
|
||||
Key *key;
|
||||
struct stat st;
|
||||
char *key_fp, *ca_fp;
|
||||
Buffer constraints, constraint;
|
||||
u_char *name, *data;
|
||||
u_int i, dlen;
|
||||
|
||||
if (!have_identity)
|
||||
ask_filename(pw, "Enter file in which the key is");
|
||||
if (stat(identity_file, &st) < 0) {
|
||||
perror(identity_file);
|
||||
exit(1);
|
||||
}
|
||||
if ((key = key_load_public(identity_file, NULL)) == NULL)
|
||||
fatal("%s is not a public key", identity_file);
|
||||
if (!key_is_cert(key))
|
||||
fatal("%s is not a certificate", identity_file);
|
||||
|
||||
key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
|
||||
ca_fp = key_fingerprint(key->cert->signature_key,
|
||||
SSH_FP_MD5, SSH_FP_HEX);
|
||||
|
||||
printf("%s:\n", identity_file);
|
||||
printf(" %s certificate %s\n", key_type(key), key_fp);
|
||||
printf(" Signed by %s CA %s\n",
|
||||
key_type(key->cert->signature_key), ca_fp);
|
||||
printf(" Key ID \"%s\"\n", key->cert->key_id);
|
||||
printf(" Valid: %s\n",
|
||||
fmt_validity(key->cert->valid_after, key->cert->valid_before));
|
||||
printf(" Principals: ");
|
||||
if (key->cert->nprincipals == 0)
|
||||
printf("(none)\n");
|
||||
else {
|
||||
for (i = 0; i < key->cert->nprincipals; i++)
|
||||
printf("\n %s",
|
||||
key->cert->principals[i]);
|
||||
printf("\n");
|
||||
}
|
||||
printf(" Constraints: ");
|
||||
if (buffer_len(&key->cert->constraints) == 0)
|
||||
printf("(none)\n");
|
||||
else {
|
||||
printf("\n");
|
||||
buffer_init(&constraints);
|
||||
buffer_append(&constraints,
|
||||
buffer_ptr(&key->cert->constraints),
|
||||
buffer_len(&key->cert->constraints));
|
||||
buffer_init(&constraint);
|
||||
while (buffer_len(&constraints) != 0) {
|
||||
name = buffer_get_string(&constraints, NULL);
|
||||
data = buffer_get_string_ptr(&constraints, &dlen);
|
||||
buffer_append(&constraint, data, dlen);
|
||||
printf(" %s", name);
|
||||
if (strcmp(name, "permit-X11-forwarding") == 0 ||
|
||||
strcmp(name, "permit-agent-forwarding") == 0 ||
|
||||
strcmp(name, "permit-port-forwarding") == 0 ||
|
||||
strcmp(name, "permit-pty") == 0 ||
|
||||
strcmp(name, "permit-user-rc") == 0)
|
||||
printf("\n");
|
||||
else if (strcmp(name, "force-command") == 0 ||
|
||||
strcmp(name, "source-address") == 0) {
|
||||
data = buffer_get_string(&constraint, NULL);
|
||||
printf(" %s\n", data);
|
||||
xfree(data);
|
||||
} else {
|
||||
printf(" UNKNOWN CONSTRAINT (len %u)\n",
|
||||
buffer_len(&constraint));
|
||||
buffer_clear(&constraint);
|
||||
}
|
||||
xfree(name);
|
||||
if (buffer_len(&constraint) != 0)
|
||||
fatal("Constraint corrupt: extra data at end");
|
||||
}
|
||||
buffer_free(&constraint);
|
||||
buffer_free(&constraints);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
@ -1040,30 +1460,34 @@ usage(void)
|
||||
fprintf(stderr, " -b bits Number of bits in the key to create.\n");
|
||||
fprintf(stderr, " -C comment Provide new comment.\n");
|
||||
fprintf(stderr, " -c Change comment in private and public key files.\n");
|
||||
#ifdef SMARTCARD
|
||||
fprintf(stderr, " -D reader Download public key from smartcard.\n");
|
||||
#endif /* SMARTCARD */
|
||||
#ifdef ENABLE_PKCS11
|
||||
fprintf(stderr, " -D pkcs11 Download public key from pkcs11 token.\n");
|
||||
#endif
|
||||
fprintf(stderr, " -e Convert OpenSSH to RFC 4716 key file.\n");
|
||||
fprintf(stderr, " -F hostname Find hostname in known hosts file.\n");
|
||||
fprintf(stderr, " -f filename Filename of the key file.\n");
|
||||
fprintf(stderr, " -G file Generate candidates for DH-GEX moduli.\n");
|
||||
fprintf(stderr, " -g Use generic DNS resource record format.\n");
|
||||
fprintf(stderr, " -H Hash names in known_hosts file.\n");
|
||||
fprintf(stderr, " -h Generate host certificate instead of a user certificate.\n");
|
||||
fprintf(stderr, " -I key_id Key identifier to include in certificate.\n");
|
||||
fprintf(stderr, " -i Convert RFC 4716 to OpenSSH key file.\n");
|
||||
fprintf(stderr, " -L Print the contents of a certificate.\n");
|
||||
fprintf(stderr, " -l Show fingerprint of key file.\n");
|
||||
fprintf(stderr, " -M memory Amount of memory (MB) to use for generating DH-GEX moduli.\n");
|
||||
fprintf(stderr, " -n name,... User/host principal names to include in certificate\n");
|
||||
fprintf(stderr, " -N phrase Provide new passphrase.\n");
|
||||
fprintf(stderr, " -O cnstr Specify a certificate constraint.\n");
|
||||
fprintf(stderr, " -P phrase Provide old passphrase.\n");
|
||||
fprintf(stderr, " -p Change passphrase of private key file.\n");
|
||||
fprintf(stderr, " -q Quiet.\n");
|
||||
fprintf(stderr, " -R hostname Remove host from known_hosts file.\n");
|
||||
fprintf(stderr, " -r hostname Print DNS resource record.\n");
|
||||
fprintf(stderr, " -s ca_key Certify keys with CA key.\n");
|
||||
fprintf(stderr, " -S start Start point (hex) for generating DH-GEX moduli.\n");
|
||||
fprintf(stderr, " -T file Screen candidates for DH-GEX moduli.\n");
|
||||
fprintf(stderr, " -t type Specify type of key to create.\n");
|
||||
#ifdef SMARTCARD
|
||||
fprintf(stderr, " -U reader Upload private key to smartcard.\n");
|
||||
#endif /* SMARTCARD */
|
||||
fprintf(stderr, " -V from:to Specify certificate validity interval.\n");
|
||||
fprintf(stderr, " -v Verbose.\n");
|
||||
fprintf(stderr, " -W gen Generator to use for generating DH-GEX moduli.\n");
|
||||
fprintf(stderr, " -y Read private key file and print public key.\n");
|
||||
@ -1078,12 +1502,12 @@ int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2;
|
||||
char out_file[MAXPATHLEN], *reader_id = NULL;
|
||||
char out_file[MAXPATHLEN], *pkcs11provider = NULL;
|
||||
char *rr_hostname = NULL;
|
||||
Key *private, *public;
|
||||
struct passwd *pw;
|
||||
struct stat st;
|
||||
int opt, type, fd, download = 0;
|
||||
int opt, type, fd;
|
||||
u_int32_t memory = 0, generator_wanted = 0, trials = 100;
|
||||
int do_gen_candidates = 0, do_screen_candidates = 0;
|
||||
BIGNUM *start = NULL;
|
||||
@ -1115,8 +1539,8 @@ main(int argc, char **argv)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while ((opt = getopt(argc, argv,
|
||||
"degiqpclBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "degiqpclBHLhvxXyF:b:f:t:D:I:P:N:n:"
|
||||
"O:C:r:g:R:T:G:M:S:s:a:V:W:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'b':
|
||||
bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr);
|
||||
@ -1131,16 +1555,25 @@ main(int argc, char **argv)
|
||||
case 'H':
|
||||
hash_hosts = 1;
|
||||
break;
|
||||
case 'I':
|
||||
cert_key_id = optarg;
|
||||
break;
|
||||
case 'R':
|
||||
delete_host = 1;
|
||||
rr_hostname = optarg;
|
||||
break;
|
||||
case 'L':
|
||||
show_cert = 1;
|
||||
break;
|
||||
case 'l':
|
||||
print_fingerprint = 1;
|
||||
break;
|
||||
case 'B':
|
||||
print_bubblebabble = 1;
|
||||
break;
|
||||
case 'n':
|
||||
cert_principals = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
change_passphrase = 1;
|
||||
break;
|
||||
@ -1162,6 +1595,9 @@ main(int argc, char **argv)
|
||||
case 'N':
|
||||
identity_new_passphrase = optarg;
|
||||
break;
|
||||
case 'O':
|
||||
add_cert_constraint(optarg);
|
||||
break;
|
||||
case 'C':
|
||||
identity_comment = optarg;
|
||||
break;
|
||||
@ -1173,6 +1609,10 @@ main(int argc, char **argv)
|
||||
/* export key */
|
||||
convert_to_ssh2 = 1;
|
||||
break;
|
||||
case 'h':
|
||||
cert_key_type = SSH2_CERT_TYPE_HOST;
|
||||
constraint_flags = 0;
|
||||
break;
|
||||
case 'i':
|
||||
case 'X':
|
||||
/* import key */
|
||||
@ -1184,14 +1624,14 @@ main(int argc, char **argv)
|
||||
case 'd':
|
||||
key_type_name = "dsa";
|
||||
break;
|
||||
case 's':
|
||||
ca_key_path = optarg;
|
||||
break;
|
||||
case 't':
|
||||
key_type_name = optarg;
|
||||
break;
|
||||
case 'D':
|
||||
download = 1;
|
||||
/*FALLTHROUGH*/
|
||||
case 'U':
|
||||
reader_id = optarg;
|
||||
pkcs11provider = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
if (log_level == SYSLOG_LEVEL_INFO)
|
||||
@ -1241,6 +1681,9 @@ main(int argc, char **argv)
|
||||
if (BN_hex2bn(&start, optarg) == 0)
|
||||
fatal("Invalid start point.");
|
||||
break;
|
||||
case 'V':
|
||||
parse_cert_times(optarg);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
@ -1250,7 +1693,15 @@ main(int argc, char **argv)
|
||||
/* reinit */
|
||||
log_init(argv[0], log_level, SYSLOG_FACILITY_USER, 1);
|
||||
|
||||
if (optind < argc) {
|
||||
argv += optind;
|
||||
argc -= optind;
|
||||
|
||||
if (ca_key_path != NULL) {
|
||||
if (argc < 1) {
|
||||
printf("Too few arguments.\n");
|
||||
usage();
|
||||
}
|
||||
} else if (argc > 0) {
|
||||
printf("Too many arguments.\n");
|
||||
usage();
|
||||
}
|
||||
@ -1262,6 +1713,13 @@ main(int argc, char **argv)
|
||||
printf("Cannot use -l with -D or -R.\n");
|
||||
usage();
|
||||
}
|
||||
if (ca_key_path != NULL) {
|
||||
if (cert_key_id == NULL)
|
||||
fatal("Must specify key id (-I) when certifying");
|
||||
do_ca_sign(pw, argc, argv);
|
||||
}
|
||||
if (show_cert)
|
||||
do_show_cert(pw);
|
||||
if (delete_host || hash_hosts || find_host)
|
||||
do_known_hosts(pw, rr_hostname);
|
||||
if (print_fingerprint || print_bubblebabble)
|
||||
@ -1299,16 +1757,8 @@ main(int argc, char **argv)
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
if (reader_id != NULL) {
|
||||
#ifdef SMARTCARD
|
||||
if (download)
|
||||
do_download(pw, reader_id);
|
||||
else
|
||||
do_upload(pw, reader_id);
|
||||
#else /* SMARTCARD */
|
||||
fatal("no support for smartcards.");
|
||||
#endif /* SMARTCARD */
|
||||
}
|
||||
if (pkcs11provider != NULL)
|
||||
do_download(pw, pkcs11provider);
|
||||
|
||||
if (do_gen_candidates) {
|
||||
FILE *out = fopen(out_file, "w");
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: ssh-keyscan.1,v 1.26 2008/12/29 01:12:36 stevesk Exp $
|
||||
.\" $OpenBSD: ssh-keyscan.1,v 1.28 2010/01/09 23:04:13 dtucker Exp $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.\" Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
|
||||
@ -7,7 +7,7 @@
|
||||
.\" permitted provided that due credit is given to the author and the
|
||||
.\" OpenBSD project by leaving this copyright notice intact.
|
||||
.\"
|
||||
.Dd December 29 2008
|
||||
.Dd January 9 2010
|
||||
.Dt SSH-KEYSCAN 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ssh-keyscan.c,v 1.78 2009/01/22 10:02:34 djm Exp $ */
|
||||
/* $OpenBSD: ssh-keyscan.c,v 1.81 2010/01/09 23:04:13 dtucker Exp $ */
|
||||
/*
|
||||
* Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
|
||||
*
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user