Compare commits

...

806 Commits

Author SHA1 Message Date
Matt Johnston
9f40bbba29 mention regression release 2016-07-21 23:16:57 +08:00
Matt Johnston
0086e1d7ca bump version 2016-07-21 23:04:47 +08:00
Matt Johnston
4732de71c6 changelogs 2016-07-21 23:04:24 +08:00
Matt Johnston
171456c683 Avoid busy loop while waiting for rekey response 2016-04-29 23:04:10 +08:00
Matt Johnston
2c73fd6fbf make sure socket is of the right domain 2016-06-19 20:38:38 +08:00
Matt Johnston
0ee860a011 make indenting consistent 2016-07-12 23:33:15 +08:00
Matt Johnston
5127943673 add length checks for ecc too 2016-07-12 23:28:42 +08:00
Matt Johnston
3ee9656250 merge fixes from PuTTY import.c
toint() from misc.c

(revids are from hggit conversion)

changeset:   4620:60a336a6c85c
user:        Simon Tatham <anakin@pobox.com>
date:        Thu Feb 25 20:26:33 2016 +0000
files:       import.c
description:
Fix potential segfaults in reading OpenSSH's ASN.1 key format.

The length coming back from ber_read_id_len might have overflowed, so
treat it as potentially negative. Also, while I'm here, accumulate it
inside ber_read_id_len as an unsigned, so as to avoid undefined
behaviour on integer overflow, and toint() it before return.

Thanks to Hanno Böck for spotting this, with the aid of AFL.

(cherry picked from commit 5b7833cd474a24ec098654dcba8cb9509f3bf2c1)

Conflicts:
	import.c

(cherry-picker's note: resolving the conflict involved removing an
entire section of the original commit which fixed ECDSA code not
present on this branch)


changeset:   4619:9c6c638d98d8
user:        Simon Tatham <anakin@pobox.com>
date:        Sun Jul 14 10:45:54 2013 +0000
files:       import.c ssh.c sshdss.c sshpubk.c sshrsa.c
description:
Tighten up a lot of casts from unsigned to int which are read by one
of the GET_32BIT macros and then used as length fields. Missing bounds
checks against zero have been added, and also I've introduced a helper
function toint() which casts from unsigned to int in such a way as to
avoid C undefined behaviour, since I'm not sure I trust compilers any
more to do the obviously sensible thing.

[originally from svn r9918]


changeset:   4618:3957829f24d3
user:        Simon Tatham <anakin@pobox.com>
date:        Mon Jul 08 22:36:04 2013 +0000
files:       import.c sshdss.c sshrsa.c
description:
Add an assortment of extra safety checks.

[originally from svn r9896]


changeset:   4617:2cddee0bce12
user:        Jacob Nevins <jacobn@chiark.greenend.org.uk>
date:        Wed Dec 07 00:24:45 2005 +0000
files:       import.c
description:
Institutional failure to memset() things pointed at rather than pointers.
Things should now be zeroed and memory not leaked. Spotted by Brant Thomsen.

[originally from svn r6476]


changeset:   4616:24ac78a9c71d
user:        Simon Tatham <anakin@pobox.com>
date:        Wed Feb 11 13:58:27 2004 +0000
files:       import.c
description:
Jacob's last-minute testing found a couple of trivial bugs in
import.c, and my attempts to reproduce them in cmdgen found another
one there :-)

[originally from svn r3847]


changeset:   4615:088d39a73db0
user:        Simon Tatham <anakin@pobox.com>
date:        Thu Jan 22 18:52:49 2004 +0000
files:       import.c
description:
Placate some gcc warnings.

[originally from svn r3761]


changeset:   4614:e4288bad4d93
parent:      1758:108b8924593d
user:        Simon Tatham <anakin@pobox.com>
date:        Fri Oct 03 21:21:23 2003 +0000
files:       import.c
description:
My ASN.1 decoder returned wrong IDs for anything above 0x1E! Good
job it's never had to yet. Ahem.

[originally from svn r3479]
2016-07-12 23:00:01 +08:00
Matt Johnston
c0f63ee100 additional length checks 2016-07-11 23:34:18 +08:00
Matt Johnston
8fd720c3e3 Improve exit message formatting 2016-07-11 23:09:33 +08:00
Matt Johnston
4f5d0756c2 improve algorithm list parsing 2016-07-11 22:40:38 +08:00
Matt Johnston
64e6e3aca9 better TRACE of failed remote ident 2016-07-11 21:51:25 +08:00
Matt Johnston
8c53621c24 update for 2016.73 2016-03-18 22:44:36 +08:00
Matt Johnston
514baf3bf7 Fix whitespace missed in merge 2016-03-18 20:43:22 +08:00
Matt Johnston
420151dbd9 move m_burn and function attributes to dbhelpers
use m_burn for libtomcrypt zeromem() too
2016-03-17 23:21:33 +08:00
Matt Johnston
156b28c771 Fix missing paths from m_burn commit 2016-03-17 06:40:31 +08:00
Matt Johnston
ad801851a2 use m_burn for mp_clear 2016-03-17 00:06:26 +08:00
Matt Johnston
b647b753e0 Use memset_s or explicit_bzero 2016-03-16 23:39:39 +08:00
Matt Johnston
48b855c581 add CVE 2016-03-16 23:04:55 +08:00
Matt Johnston
c830d30553 merge 2016-03-16 22:53:27 +08:00
Francois Perrad
0650182289 add the idiomatic do/while(0) in the macro SCREWUP 2016-03-16 22:41:20 +08:00
Francois Perrad
3e20c442de fix empty C prototypes 2016-03-16 22:41:20 +08:00
Francois Perrad
af87369cb3 add static in function definition
like in function declaration
2016-03-16 22:41:19 +08:00
Francois Perrad
edea73b1f8 add parentheses to macro 2016-03-16 22:41:19 +08:00
Francois Perrad
893d7be5bf const variables 2016-03-16 22:41:19 +08:00
Francois Perrad
c5b77e1b49 explicitly initialization of static variables 2016-03-16 22:41:19 +08:00
Francois Perrad
a5e5bab74b Suspicious use of ; 2016-03-16 22:41:19 +08:00
Francois Perrad
8f96b8908e rename loop variable
2 nested loops with the same variable 'i',
line 219 and line 309
2016-03-16 22:41:19 +08:00
Francois Perrad
f3a6dd139c Suspicious use of & 2016-03-16 22:41:19 +08:00
Francois Perrad
1dba0d4830 add comment FALLTHROUGH which recognize by many lint tools 2016-03-16 22:41:19 +08:00
Francois Perrad
da85400e57 put default in switch/case 2016-03-16 22:41:19 +08:00
Francois Perrad
7f38caefd0 remove unreachable code 2016-03-16 22:41:19 +08:00
Francois Perrad
937594c130 use #ifdef like everywhere 2016-03-16 22:41:05 +08:00
Matt Johnston
3e7672edca merge 2016-03-15 23:23:31 +08:00
Matt Johnston
098aba47c3 assertion for case that shouldn't happen 2016-03-15 23:20:01 +08:00
Matt Johnston
c67fc5693a m_close() rather than close() 2016-03-15 23:03:59 +08:00
Matt Johnston
6b5c6af613 ignore return value from fcntl() 2016-03-15 23:03:43 +08:00
Matt Johnston
3ccc36b3b7 Fix truncated type for getc() at confirmation prompt 2016-03-15 23:03:31 +08:00
Matt Johnston
e7828bb911 cast return type to enum 2016-03-15 22:40:15 +08:00
Matt Johnston
e255f0590b remove unused loginrec_set_addr() 2016-03-15 22:04:13 +08:00
Matt Johnston
4615631d83 update CHANGES 2016-03-15 22:03:23 +08:00
Matt Johnston
e708f9542f Merge pull request #23 from Chocobo1/travis_fix
TravisCI: re-enable MULTI=1 & NOWRITEV=1 builds on OSX
2016-03-15 21:55:11 +08:00
Matt Johnston
6bfbcdbfdb Merge branch 'fperrad-20151231_indent' 2016-03-15 21:41:22 +08:00
Matt Johnston
645b254173 Merge branch '20151231_indent' of https://github.com/fperrad/dropbear into fperrad-20151231_indent 2016-03-15 21:41:06 +08:00
Matt Johnston
fdc61f3ab2 Get rid of group15, move group16 to sha512.
New groups are disabled by default pending
draft-ietf-curdle-ssh-kex-sha2-02 being finalised
2016-03-12 16:21:13 +08:00
Matt Johnston
a991d3b56b merge github master 2016-03-10 21:37:35 +08:00
Matt Johnston
26a1a0a3bc allow specifying dropbearmulti command as an argument 2016-03-10 21:35:23 +08:00
Matt Johnston
73bc3a9853 merge 2016.72 2016-03-10 20:57:47 +08:00
Matt Johnston
9cb325ee6f Added signature for changeset fd1981f41c62 2016-03-10 20:50:31 +08:00
Matt Johnston
9e1d038a65 Added tag DROPBEAR_2016.72 for changeset 78b12b6549be 2016-03-10 20:50:24 +08:00
Matt Johnston
7e5fe1d813 debian changelog 2016-03-09 22:54:51 +08:00
Matt Johnston
97dff151ae 2016.72 2016-03-09 22:54:15 +08:00
Matt Johnston
18681875e3 Validate xauth input 2016-03-09 22:45:40 +08:00
Chocobo1
9b0a2714f0 TravisCI: re-enable MULTI=1 & NOWRITEV=1 builds on OSX, fixes d416a9b 2016-01-21 00:21:39 +08:00
Matt Johnston
a84ce21aec Merge pull request #22 from Chocobo1/travis
TravisCI: Improvements
2016-01-20 21:36:58 +08:00
Matt Johnston
1fc1559d15 Merge pull request #21 from Chocobo1/fix
Fix warnings
2016-01-20 21:24:36 +08:00
Matt Johnston
de70b02c2f Don't fail if can't get the username 2016-01-19 00:34:37 +08:00
Michael Witten
6453b5b70e scp: Have `fatal()' append a newline to the message
Date: Wed, 4 Nov 2015 20:33:19 -0000
It would seem that it's standard practice not to include a newline in the message
text, but that results in poor formatting, as a shell's command line then begins
on the line of the error message itself.

This commit simply instructs `fatal()' to append a newline after the message,
which should be suitable behavior for all of the invocations I've come across.
2016-01-19 00:23:19 +08:00
Matt Johnston
61b49ea2e3 Add note about OpenSSH origin 2016-01-19 00:22:23 +08:00
Matt Johnston
21ed9480d7 add dh group15 and group16, disabled by default 2016-01-15 00:19:11 +08:00
Matt Johnston
09e83ad742 Move dh group constants to a separate file 2016-01-14 21:54:58 +08:00
Chocobo1
3360072f84 TravisCI: fix linux + clang compile 2016-01-11 13:33:00 +08:00
Chocobo1
0ba59d80b6 TravisCI: use if block 2016-01-11 13:33:00 +08:00
Chocobo1
d416a9b818 TravisCI: enable osx builds 2016-01-11 13:32:59 +08:00
Chocobo1
de1993a1fd Fix parentheses weird placement 2016-01-05 22:44:09 +08:00
Chocobo1
307c71b66a TravisCI: enable build with clang 2016-01-05 14:14:29 +08:00
Chocobo1
b41ae80399 TravisCI: enable parallel build 2016-01-05 14:12:38 +08:00
Chocobo1
bbf9ba6d8d TravisCI: modify to run builds in container 2016-01-05 14:09:38 +08:00
Chocobo1
9bcd5f3c0a Fix print format specifier 2016-01-05 12:37:48 +08:00
Chocobo1
533aebe336 Fix "Pointer to local array variable returned" 2016-01-05 12:25:10 +08:00
Matt Johnston
5f8fcef688 Merge pull request #20 from kingosticks/debian-init-short-description
Added missing Short-Description init info field to debian init script.
2016-01-04 21:18:17 +08:00
Nick Steel
f37d67ff5e Added missing init info field to debian init script.
The Short-Description init info field is used by systemd and
displayed along with the service name. When it's missing the string
'null' is displayed instead.
2016-01-03 14:42:57 +00:00
Francois Perrad
9bda22e702 more hard tab 2016-01-01 15:02:09 +01:00
Francois Perrad
23ac7f56fa refactor indentation with hard tab 2015-12-31 16:00:23 +01:00
Matt Johnston
4c4aa502d4 use exec for proxycommand 2015-12-18 21:20:46 +08:00
Matt Johnston
20bdf3a5b1 revert removal of space handling, different fix for avoiding option prefix
matches
2015-12-15 22:57:22 +08:00
Matt Johnston
da108a9327 Don't allow spaces and don't get confused by -o usesyslogd=yes
(option name has another option name as a prefix)
2015-12-15 22:23:42 +08:00
Matt Johnston
e6432b1262 unknown options should be non-fatal 2015-12-15 22:19:41 +08:00
Matt Johnston
99bc4f451a rename killchild to kill_proxy_sighandler 2015-12-15 22:15:44 +08:00
Matt Johnston
79b43270a7 A few minor style fixes 2015-12-15 22:09:55 +08:00
Matt Johnston
3d33e65a35 Merge pull request #18 from annulen/dbclient_syslog
Support syslog logging in dbclient.
2015-12-15 21:55:51 +08:00
Konstantin Tokarev
5ab562f695 Use dropbear_log instead of some fprintf's in client code. 2015-12-15 16:52:53 +03:00
Konstantin Tokarev
3cb278c35c Support syslog logging in dbclient. 2015-12-15 16:52:53 +03:00
Konstantin Tokarev
c59827334c Allow setting syslog identifier via startsyslog(). 2015-12-15 16:43:29 +03:00
Konstantin Tokarev
2d6bbf341d Moved usingsyslog from svr_runopts to runopts. 2015-12-15 16:43:29 +03:00
Matt Johnston
2f62128297 Merge pull request #17 from annulen/kill_proxy_cmd
Client: kill proxy command when exiting application.
2015-12-15 21:40:32 +08:00
Matt Johnston
ed21e75235 Merge pull request #16 from annulen/openssh_options
Implemented ExitOnForwardFailure option for local and remote forwarding.
2015-12-15 21:30:59 +08:00
Matt Johnston
87d2c9c05c diffie-hellman-group14-sha256 2015-12-11 22:12:12 +08:00
Matt Johnston
df999ed1e1 Thanks 2015-12-03 21:40:31 +08:00
Matt Johnston
154de2aee3 Added signature for changeset 926e7275cef4 2015-12-03 21:33:48 +08:00
Matt Johnston
f808b8e930 Added tag DROPBEAR_2015.71 for changeset 9a944a243f08 2015-12-03 21:33:43 +08:00
Matt Johnston
5b2e57aa2f 2015.71 2015-12-03 21:23:54 +08:00
Konstantin Tokarev
960364d953 Client: kill proxy command when exiting application. 2015-12-03 16:22:29 +03:00
Matt Johnston
0b9793ccd0 wrong breakage version 2015-12-02 23:37:04 +08:00
Matt Johnston
fff298523d preliminary 2015.71 CHANGES 2015-12-02 23:35:14 +08:00
Matt Johnston
e81b6fbc6e ports and addresses must be malloced to avoid segfault on exit 2015-12-02 22:37:20 +08:00
Konstantin Tokarev
4dc1388ac7 Implemented ExitOnForwardFailure option for local and remote forwarding. 2015-11-30 21:05:36 +03:00
Konstantin Tokarev
1b69d6d658 Added OpenSSH-like -o command line option to dbclient.
Like in OpenSSH, whitespaces are ignored, key and value may be separated
by one '=' character.

For now only yes/no flag parsing is implemented.
2015-11-30 20:36:15 +03:00
Matt Johnston
f64a50f319 Merge pull request #15 from annulen/fix_cli_remotetcpfwd
Fixed build when ENABLE_CLI_REMOTETCPFWD is the only allowed TCP forw…
2015-11-30 21:13:03 +08:00
Juergen Daubert
f299caf612 The '==' comparision operator is not defined by POSIX, use '=' instead 2015-11-30 20:55:07 +08:00
Konstantin Tokarev
f76141a704 Fixed build when ENABLE_CLI_REMOTETCPFWD is the only allowed TCP forwarding. 2015-11-27 21:40:00 +03:00
Matt Johnston
a3049d6433 Fix "Avoid queueing into circbuffer when the channel is about to close"
which broken handling EAGAIN/EINTR
2015-11-27 22:19:08 +08:00
Matt Johnston
ee353847be Fix ses.channel_signal_pending race 2015-11-27 21:26:43 +08:00
Matt Johnston
33b2fbb5ef Added signature for changeset 5bb5976e6902 2015-11-26 23:15:27 +08:00
Matt Johnston
7d84615545 Added tag DROPBEAR_2015.70 for changeset 79a6ef02307d 2015-11-26 23:15:12 +08:00
Matt Johnston
b42113119a Wrong date 2015-11-26 23:05:38 +08:00
Matt Johnston
722944f307 2015.70 2015-11-26 23:04:13 +08:00
Matt Johnston
e038c26963 Another attempt at test for crypt() 2015-11-26 23:01:13 +08:00
Matt Johnston
56b9388702 Backed out changeset fbcd0a20e667 2015-11-26 22:21:14 +08:00
Matt Johnston
0e438f6d5c AC_SEARCH_LIBS not AC_CHECK_LIB to find crypt() 2015-11-26 21:58:25 +08:00
Matt Johnston
9f1eb695b4 release.sh reminds how to sign 2015-11-25 23:30:56 +08:00
Matt Johnston
9fef5d1050 Added signature for changeset af074dbcb68f 2015-11-25 23:30:44 +08:00
Matt Johnston
0bb7f77a8f Added tag DROPBEAR_2015.69 for changeset 1637dbd26212 2015-11-25 23:30:36 +08:00
Matt Johnston
9e4e562cfb 2015.69 2015-11-25 23:07:47 +08:00
Matt Johnston
92ec446cb9 debian changelog 2015-11-25 23:07:18 +08:00
Matt Johnston
9097da0284 changelog 2015-11-25 23:06:55 +08:00
Matt Johnston
eedeb009ec mention dropbearkey too 2015-11-25 23:05:41 +08:00
Matt Johnston
d8bc6abcf0 Mention "dropbear -R" if no hostkeys 2015-11-25 23:05:14 +08:00
Matt Johnston
2293e3d105 check for zero K value from curve25519 2015-11-25 22:15:59 +08:00
Guilhem Moulin
550b3056fd Fix minor manpage formatting issues 2015-11-25 20:46:06 +08:00
Matt Johnston
1ba5e8052e Improve dbclient manpage 2015-11-23 23:02:03 +08:00
Matt Johnston
6f5abeff2e Fix flags after the hostname 2015-11-23 22:47:43 +08:00
Guilhem Moulin
7cbf6b131b Bundling for dbclient 2015-11-23 22:28:56 +08:00
Matt Johnston
a461298109 Increase channel limit to 1000 2015-11-19 23:53:06 +08:00
Matt Johnston
90c3a74b2a Avoid queueing into circbuffer when the channel is about to close 2015-11-19 23:52:52 +08:00
Matt Johnston
87373be960 lazy allocation of circbuffer 2015-11-19 23:52:11 +08:00
Matt Johnston
85d9672e47 Send SSH_OPEN_RESOURCE_SHORTAGE response when too many channels open
rather than SSH_OPEN_UNKNOWN_CHANNEL_TYPE
2015-11-19 22:39:32 +08:00
Matt Johnston
e0ae527190 Only clear channel_signal_pending after handling all channels,
from Andrzej Szombierski
2015-11-17 20:53:30 +08:00
Guilhem Moulin
7fb1bec84a Enable bundling 2015-11-06 23:54:24 +08:00
Matt Johnston
1f308fb2b4 S_IWUSR rather than S_IWRITE for scp 2015-11-04 23:22:58 +08:00
Guilhem Moulin
e2d36d493f Mention -y flag 2015-10-28 21:44:16 +08:00
Matt Johnston
7c43594075 Add comment about compression 2015-10-28 21:42:09 +08:00
Matt Johnston
e4827025be Warn rather than fail if flags have trailing parts 2015-10-28 21:37:35 +08:00
Matt Johnston
00798ca8cc Test for crypt() rather than crypt.h
Print a message from configure if getpass() or crypt() were missing
2015-10-21 23:08:22 +08:00
Mike Frysinger
e84cb3c3c2 fix default build when getpass() is unavailable
if the system doesn't support getpass, we still default on the options
that require it which causes a build failure.  instead, only default
enable these when getpass is available.
2015-10-21 22:48:15 +08:00
Mike Frysinger
78b9cecb52 fix default build when crypt() is unavailable
if the system doesn't support crypt.h/crypt, then ENABLE_SVR_PASSWORD_AUTH
cannot work.  rather than default this to on all the time, do so only when
support for the header is found.
2015-10-21 22:40:11 +08:00
Mike Frysinger
93c54fe6f6 avoid getpass when not used
some systems (like android's bionic) do not provide getpass.  you can
disable ENABLE_CLI_PASSWORD_AUTH & ENABLE_CLI_INTERACT_AUTH to avoid
its use (and rely on pubkey auth), but the link still fails because
the support file calls getpass.  do not define this func if both of
those auth methods are not used.
2015-10-21 22:39:55 +08:00
Mike Frysinger
5f97d0fbbc fix build when ENABLE_CLI_INTERACT_AUTH is disabled
The session.h defines clientsession.cipher_none_after_auth only when
ENABLE_CLI_INTERACT_AUTH is defined, but cli-session.c will always
try to set that member.  export cipher_none_after_auth all the time.
2015-10-21 22:39:31 +08:00
Guilhem Moulin
dc01a8edd4 Don't display the MOTD when an explicit command is run.
(possibly via authorized_keys(5) restrictions), even when a
pseudo-terminal has been allocated for the session.  In other words,
only display the MOTD when the server starts the user's default shell.
2015-10-21 22:08:47 +08:00
Matt Johnston
23cc2bfb8c don't silently ignore extra flag arguments 2015-10-21 22:05:50 +08:00
Matt Johnston
9e379835c4 avoid invalidated iterator when connection fails 2015-09-29 22:19:11 +08:00
Matt Johnston
8ccbd216c6 make sure that the test for queued packets to write occurs after
those packets might have been enqueued by set_connect_fds()
2015-09-29 21:53:27 +08:00
Matt Johnston
90f4da29d7 Added signature for changeset ef4b26364b0c 2015-08-08 22:14:30 +08:00
Matt Johnston
54dbd5bbc8 Added signature for changeset a687f835236c 2015-08-08 22:14:19 +08:00
Matt Johnston
849b8ec469 Added tag DROPBEAR_2015.68 for changeset 809feaa9408f 2015-08-08 22:14:10 +08:00
Matt Johnston
84e18f72ae changelog and version 2015.68 2015-08-08 20:35:28 +08:00
Guilhem Moulin
633b98ef28 Fix typo in dropbear(8)'s manpage 2015-08-07 23:07:16 +08:00
Guilhem Moulin
2a34a72bff Fix segfault with restricted authorized_key files without forced command 2015-08-07 23:00:08 +08:00
Matt Johnston
24bae46e42 only update keepalive timeout post-auth (when keepalives are sent) 2015-08-07 21:02:49 +08:00
Matt Johnston
7585d4606e Build with -Werror for the simplest case 2015-08-04 08:20:50 +08:00
Matt Johnston
94bff1df66 couple more changelog items 2015-08-03 23:17:50 +08:00
Matt Johnston
2e60d20a76 set timeouts to time remaining rather than timeout duration 2015-08-03 23:05:43 +08:00
Matt Johnston
ce59260ee9 Fix problem where auth timeout wasn't checked when waiting for ident 2015-08-03 21:59:40 +08:00
Matt Johnston
387ebccf36 increase MAX_CMD_LEN to 9000 2015-08-03 21:17:23 +08:00
Matt Johnston
2f618af086 remove .hgtags from release 2015-08-03 21:05:42 +08:00
Matt Johnston
0ac33d22f7 Don't try to send data on first ack packet of 3way handshake.
Cisco SSH on 15.4(3)M2 or similar can't handle it.
2015-08-03 20:53:37 +08:00
Matt Johnston
c7bd5ac77d remove extraneous semicolon from m_free #define 2015-08-03 20:46:29 +08:00
Matt Johnston
941c067765 change DROPBEAR_DEFAULT_CLI_AUTHKEY to just prepend homedir
rather than doing ~ expansion
2015-08-03 20:45:04 +08:00
Matt Johnston
839e023ed8 check ecc key return, fix null pointer crash 2015-06-23 21:48:13 +08:00
Matt Johnston
2e05a2b8c4 Merge pull request #11 from nshopik/patch-2
Prepend DROPBEAR for scp.c
2015-06-12 22:57:48 +08:00
Matt Johnston
fc2c67e61c a bit more changelog 2015-06-12 22:55:10 +08:00
Matt Johnston
9c3e9fcdad merge 2015-06-04 23:24:08 +08:00
Matt Johnston
1a4db21fe4 buf_getstring and buf_putstring now use non-unsigned char* 2015-06-04 23:08:50 +08:00
Matt Johnston
d96a52541f Merge pull request #13 from gazoo74/fix-warnings
Fix warnings
2015-06-04 23:08:50 +08:00
Matt Johnston
e7ac4c1ab3 Merge pull request #13 from gazoo74/fix-warnings
Fix warnings
2015-06-04 22:25:28 +08:00
Matt Johnston
ecd8505218 Disable twofish-ctr by default, add config option 2015-06-03 22:59:59 +08:00
Matt Johnston
1fa1c3f9db note about constant_time_strcmp and lengths 2015-06-03 22:15:12 +08:00
Matt Johnston
91df741926 Fix building when ENABLE_CLI_PUBKEY_AUTH is unset 2015-06-03 21:45:32 +08:00
Matt Johnston
2a431cab03 separate client/server fastopen options 2015-05-29 23:19:11 +08:00
Gaël PORTAY
9fdab3ced8 Merge branch 'fix-pointer-sign-warnings' into fix-warnings 2015-05-05 20:42:38 +02:00
Gaël PORTAY
6e15e75391 Turn modptr local variable into unsigned char * 2015-05-05 20:39:14 +02:00
Gaël PORTAY
1c2a1838fc Turn name and instruction local variables into char * 2015-05-05 20:39:14 +02:00
Gaël PORTAY
bfd730aa4c Turn type and term local variables into char * 2015-05-05 20:39:14 +02:00
Gaël PORTAY
e3c6a86b1e Turn TCPFwdEntry's connectaddr and listenaddr attributes into char * 2015-05-05 20:39:14 +02:00
Gaël PORTAY
bbaeb917ff Turn banner, methods and tok local variable into char * 2015-05-05 20:39:14 +02:00
Gaël PORTAY
20f1e49b73 Turn many local variables into char *
reqname, bindaddr, request_addr, desthost and orighost to be exhaustive.
2015-05-05 20:39:14 +02:00
Gaël PORTAY
292656d899 Turn signame local variable into char * 2015-05-05 20:39:14 +02:00
Gaël PORTAY
05b36b484e Turn ChanSess's cmd attribute into char * 2015-05-05 20:39:14 +02:00
Gaël PORTAY
be3016b8d5 Turn send_msg_service_accept()'s name argument into char * 2015-05-05 20:39:14 +02:00
Gaël PORTAY
5cf43d76bf Turn checkpubkey() and send_msg_userauth_pk_ok()'s algo argument into char * 2015-05-05 20:39:14 +02:00
Gaël PORTAY
6f05e810d9 Turn addr local variable into char * 2015-05-05 20:39:14 +02:00
Gaël PORTAY
947d2697cf Turn sshsession's remoteident attribute into char * 2015-05-05 20:39:14 +02:00
Gaël PORTAY
449ddae628 Turn dropbear_ecc_curve's name into const char * 2015-05-05 20:39:14 +02:00
Gaël PORTAY
6b90885d4f Turn Algo_Type's name attribute into const char * 2015-05-05 20:39:14 +02:00
Gaël PORTAY
bd6c37adb6 Turn local key_indent variable into char * 2015-05-05 20:39:14 +02:00
Gaël PORTAY
59235276ac Turn get_response()'s return type and prompt argument into char * 2015-05-05 20:39:14 +02:00
Gaël PORTAY
e5ce3fc51b Turn type local variable into char * 2015-05-05 20:39:14 +02:00
Gaël PORTAY
9f97511356 Turn ChanSess's tty and term attributes into char * 2015-05-05 20:39:14 +02:00
Gaël PORTAY
ef0aac432c Fix unused make_connection_string() warning [-Werror=unused-function]
This function is used when USE_VFORK is unset.
2015-05-05 20:39:13 +02:00
Gaël PORTAY
7928d83b02 Turn cleantext()'s dirtytext argument into char * 2015-05-05 20:39:13 +02:00
Gaël PORTAY
3e91ec07e4 Fix unused but set variable warnings [-Werror=unused-but-set-variable] 2015-05-05 20:39:13 +02:00
Gaël PORTAY
d680a9e3fb Turn username, servicename and methodname local variables into char *
Changing checkusername()'s username argument into char * as well.
2015-05-05 20:39:13 +02:00
Gaël PORTAY
6086851fc1 Fix unused parameters warnings [-Werror=unused-parameter] 2015-05-05 20:39:13 +02:00
Gaël PORTAY
61726df20c Turn sendaddr, listenaddr and request_listenaddr local variables into char * 2015-05-05 20:39:13 +02:00
Gaël PORTAY
1601a657d4 Turn send_msg_channel_open_failure()'s text and lang into const char * 2015-05-05 20:39:13 +02:00
Gaël PORTAY
50b14f696c Turn start_send_channel_request()'s type argument into char * 2015-05-05 20:39:13 +02:00
Gaël PORTAY
c239baf801 Turn addrandom()'s buf argument into unsigned char *
Data is usually represented as "unsigned char *" like genrandom().
2015-05-05 20:39:13 +02:00
Gaël PORTAY
18638859e6 Expect len to be a type of socklen_t [-Werror=pointer-sign] 2015-05-05 20:39:13 +02:00
Gaël PORTAY
224b16b247 Fix pointer differ in signess warnings [-Werror=pointer-sign] 2015-05-05 20:39:13 +02:00
Gaël PORTAY
d9d97969a3 Uses abort() instead of raising a SIGABRT signal [-Werror]
error: ‘noreturn’ function does return [-Werror]

abort() is a noreturn function while raise() is not.

And because crypt_argchk() is flagged as __attribute__(noreturn), abort()
appears to be a better condidate.

This compilation warning has probably been introduced by commit
1809f741cb.
2015-05-05 20:30:49 +02:00
Gaël PORTAY
897da4ee36 Uses k_size as an signed integer
buf_incrwritepos() and mp_to_unsigned_bin() functions use k_size as signed
integer argument.

k_size is also used in an assertion that compared it to curve_size which is
a signed long.

Only buf_getwriteptr() is using k_size as unsigned.

So it safe to use it as signed.
2015-05-05 20:30:49 +02:00
Gaël PORTAY
90f9f43335 Test struct existance against sizeof() operator
Instead of declaring an "unused-variable" or "unused-but-set-variable"
structure.

This avoid unexpected broken configurations when using something like:
$ ./configure CFLAGS="-Wall -Wextra -Werror"
It causes AC_COMPILE_IFELSE to fail and thus leading to a mismatch
configuration (because the CFLAGS are passed to the macro).
2015-05-05 20:23:54 +02:00
Matt Johnston
0e1dee828a Make sure kexfirstinitialise is called early enough 2015-05-03 00:00:35 +08:00
Matt Johnston
cbdc1f0753 fix travis more 2015-05-02 22:59:55 +08:00
Matt Johnston
7e306336d0 bad travis syntax 2015-05-02 22:55:53 +08:00
Matt Johnston
e7def4c211 add no-writev build 2015-05-02 22:51:46 +08:00
Matt Johnston
19e1afbd1c Fix no-writev fallback 2015-05-02 22:47:25 +08:00
Matt Johnston
fee32054e6 Should be AF_UNSPEC not PF_UNSPEC 2015-04-17 20:59:32 +08:00
Matt Johnston
9754fdd995 fastopen code was totally broken 2015-04-14 20:43:54 +08:00
Matt Johnston
ef20b9ff7a Avoid channel writev() when there is nothing to write 2015-03-21 22:43:08 +08:00
Matt Johnston
275611fbaa Make main socket nonblocking. Limit writequeue size. 2015-03-20 23:36:42 +08:00
Matt Johnston
a070159cc5 Fix when iov queue is large 2015-03-20 23:33:45 +08:00
Matt Johnston
20f9683ae0 avoid malloc for iovec 2015-03-20 22:53:32 +08:00
Matt Johnston
dce384668b dropbear_assert() rather than assert() 2015-03-16 21:33:01 +08:00
Nikolay Shopik
fdcd21e74b Prepend DROPBEAR for scp.c 2015-03-12 15:14:47 +03:00
Matt Johnston
67b4fa313e strdup strerror 2015-03-11 23:10:27 +08:00
Matt Johnston
5dff74109e Fix error handling for dbclient async connect 2015-03-03 20:53:00 +08:00
Matt Johnston
20d970a0e2 more changes 2015-03-02 21:40:06 +08:00
Matt Johnston
94734ad377 changes (also testing hg bookmarks) 2015-03-02 21:29:49 +08:00
Matt Johnston
14ad6a5972 merge 2015-03-01 23:27:08 +08:00
Matt Johnston
9e66b5a9b1 reword comment for clarity
--HG--
branch : nocircbuffer
2015-03-01 23:26:42 +08:00
Matt Johnston
f782cf375a Fix pubkey auth after change to reuse ses.readbuf as ses.payload
(4d7b4c5526c5)

--HG--
branch : nocircbuffer
2015-03-01 23:02:06 +08:00
Matt Johnston
3317916111 Fix some memory leaks in ecc code 2015-03-01 22:44:36 +08:00
Matt Johnston
f367273549 allocate buffer and data in a single allocation
--HG--
branch : nocircbuffer
2015-03-01 21:16:09 +08:00
Matt Johnston
91ef9b2fa9 Avoid malloc in hmac
--HG--
branch : nocircbuffer
2015-03-01 14:46:04 +08:00
Matt Johnston
579463933b A bit of a bodge to avoid memcpy if zlib is disabled
--HG--
branch : nocircbuffer
2015-03-01 00:57:21 +08:00
Matt Johnston
989c5c1436 Avoid copying data into circular buffer
--HG--
branch : nocircbuffer
2015-03-01 00:44:45 +08:00
Matt Johnston
3113932151 Better failure handling 2015-02-28 23:49:39 +08:00
Matt Johnston
125a970d71 merge tcp fastopen 2015-02-28 23:24:30 +08:00
Matt Johnston
89c0b2a6d8 Add cleanup
--HG--
branch : fastopen
2015-02-28 23:15:23 +08:00
Matt Johnston
31e379c300 merge from default
--HG--
branch : fastopen
2015-02-28 09:06:40 +08:00
Matt Johnston
843953379c EINPROGRESS for sendmsg() means it's working OK
--HG--
branch : fastopen
2015-02-27 00:02:48 +08:00
Matt Johnston
2a90c1ca7e ignore any sendmsg() errors
--HG--
branch : fastopen
2015-02-26 23:43:12 +08:00
Thorsten Horstmann
59bb1777be Use m_burn rather than memset 2015-02-24 22:48:14 +08:00
Thorsten Horstmann
c5f3c550a6 Avoid cppcheck warning 2015-02-24 22:41:26 +08:00
Matt Johnston
1809f741cb Add more ATTRIB_NORETURN annotations, from Thorsten Horstmann 2015-02-24 22:36:20 +08:00
Matt Johnston
9adfff5c1a Revert accidental commented out signal handlers 2015-02-24 22:23:32 +08:00
Matt Johnston
8008b595d3 Some additional cleanup functions 2015-02-24 22:17:04 +08:00
Matt Johnston
21bed0d21a Free memory before exiting. Based on patch from Thorsten Horstmann.
Client side is not complete.
2015-02-24 22:01:33 +08:00
Matt Johnston
4b1f5ec7c2 Use m_close() which will avoid close(-1) 2015-02-24 20:53:32 +08:00
Thorsten Horstmann
ab9439519a Fix for old compilers, variable declarations at beginning of functions
and /**/ comments
2015-02-24 20:51:18 +08:00
Thorsten Horstmann
abeb9d64a3 Some minor typo fixes, found by codespell. 2015-02-24 20:45:07 +08:00
Thorsten Horstmann
fdb7ffa864 DROPBEAR_ prefix for include guards to avoid collisions 2015-02-24 20:43:01 +08:00
Matt Johnston
46845fd3e8 get rid of some unnecessary code
--HG--
branch : fastopen
2015-02-21 00:43:32 +08:00
Matt Johnston
c53ca6ebc0 avoid some warnings
--HG--
branch : fastopen
2015-02-20 23:43:59 +08:00
Matt Johnston
f04a3a2cfa Fixes for backwards compatibility
--HG--
branch : fastopen
2015-02-20 23:38:05 +08:00
Matt Johnston
364a53577e Move generic network routines to netio.c
--HG--
branch : fastopen
2015-02-20 23:16:38 +08:00
Matt Johnston
1b1997bf2d Update priority once the socket is open
--HG--
branch : fastopen
2015-02-20 22:13:53 +08:00
Matt Johnston
34f9adb1c9 merge
--HG--
branch : fastopen
2015-02-19 22:42:30 +08:00
Matt Johnston
2e7d468b90 Add the missing second half of iov code
--HG--
branch : fastopen
2015-02-19 22:41:51 +08:00
Matt Johnston
86a717c80c fallback for old glibc and fastopen
memset rather than = {0} initialiser

--HG--
branch : fastopen
2015-02-19 22:33:51 +08:00
Matt Johnston
76a3eb393c In theory TFO should work. Needs platform cleanup and testing
--HG--
branch : fastopen
2015-02-19 00:32:00 +08:00
Matt Johnston
5f0cc969a0 generalise write iovec handling
--HG--
branch : fastopen
2015-02-18 23:02:49 +08:00
Matt Johnston
755c1458f0 async connections working
--HG--
branch : fastopen
2015-02-18 22:46:15 +08:00
Matt Johnston
8795d733ec work in progress for async connect
--HG--
branch : fastopen
2015-02-18 00:05:27 +08:00
Matt Johnston
28f61c8b3a tcp fastopen for the server
--HG--
branch : fastopen
2015-02-15 22:34:05 +08:00
Matt Johnston
9abcc7b909 connect_remote() is now always non-blocking 2015-02-14 09:56:11 +08:00
Matt Johnston
2c35f1c8fd Add envirnonment variable for debug timestamps to roughly match
network timestamps (in tshark)
2015-02-13 23:47:53 +08:00
Matt Johnston
136188259e Fix print that no longer works since we're not using fourCCs 2015-02-13 23:17:23 +08:00
Matt Johnston
02179b1218 merge 2015-02-13 23:15:12 +08:00
Matt Johnston
1e350de136 Make it compile 2015-02-13 23:13:58 +08:00
Matt Johnston
9aeda4c5bd piggyback data on acks when making connections on linux 2015-02-13 22:49:15 +08:00
Matt Johnston
8eb30c353a debug should be off by default 2015-02-13 21:45:15 +08:00
Matt Johnston
c44a78a2e6 Tighten validation of DH values. Odds of x==0 being generated are
improbable, roughly 2**-1023
Regression in 0.49
2015-02-10 21:46:19 +08:00
Matt Johnston
b6685bf806 twofish ctr modes 2015-02-04 22:12:06 +08:00
Matt Johnston
269d690e71 Added signature for changeset 1d2d81b1b7c1 2015-01-29 21:42:01 +08:00
Matt Johnston
4df268f10e sha256 2015-01-28 22:58:52 +08:00
Matt Johnston
19b3f01477 bump version 2015-01-28 22:57:33 +08:00
Matt Johnston
86811f4765 Added tag DROPBEAR_2015.67 for changeset cbd674d63cd4 2015-01-28 22:55:27 +08:00
Matt Johnston
dd0352d93b changelog for 2015.67 2015-01-28 22:54:23 +08:00
Matt Johnston
30ec18d938 merge 2015-01-28 22:49:40 +08:00
Matt Johnston
9d495ab2b5 changes for 2015.67 2015-01-28 22:49:28 +08:00
Matt Johnston
9174de47a9 Fix bad multi-statement define for m_free(), detected by Coverity 2015-01-28 22:43:01 +08:00
Christian Engelmayer
d857faf18e When clearing the memory of 'key' in function openssh_read(), only the size
of the pointer to the data instead of the whole size of struct openssh_key
is cleared. Correct the size calculation as detected by Coverity CID 1191543.
2015-01-28 22:42:29 +08:00
Matt Johnston
d5c8ba1690 Initialise sa_mask 2015-01-28 22:33:34 +08:00
Matt Johnston
9bb9b4829d Fix memory leak of ecdsa structure, found by Coverity 2015-01-28 22:29:18 +08:00
Matt Johnston
e25c297c3c Document ~/.ssh/id_dropbear 2015-01-28 22:22:32 +08:00
Matt Johnston
4de876f259 Keep sha1 default 2015-01-28 22:14:07 +08:00
Elan Ruusamäe
b9073961f7 Allow configure with libtomcrypt/libtommath directories missing
if using bundled libraries
2015-01-28 22:05:24 +08:00
Matt Johnston
a7a79d569a Disable non-delayed zlib for server 2015-01-28 21:38:27 +08:00
Matt Johnston
6165f53fcd Default client key path ~/.ssh/id_dropbear 2015-01-24 00:05:26 +08:00
Fedor Brunner
4122cac66b Prefer stronger algorithms in algorithm negotiation.
Prefer diffie-hellman-group14-sha1 (2048 bit) over
diffie-hellman-group1-sha1 (1024 bit).

Due to meet-in-the-middle attacks the effective key length of
three key 3DES is 112 bits. AES is stronger and faster then 3DES.

Prefer to delay the start of compression until after authentication
has completed. This avoids exposing compression code to attacks
from unauthenticated users.

(github pull request #9)
2015-01-23 23:00:25 +08:00
Like Ma
a1dcebe4f4 Fix installing dropbear.8 error when building in a separate directory.
(fix pull request #6)
2015-01-23 22:59:30 +08:00
Matt Johnston
6cbb23a819 Add config option to disable cbc. Disable twofish by default 2015-01-23 22:37:14 +08:00
Like Ma
5c57a31184 Fix variables may be uninitialized.
(fixup of pull request #7)
2015-01-23 22:23:23 +08:00
Fedor Brunner
7b2c42aa75 Integrity error (bad packet size %u) negative length
When corrupted packet is received negative length of packet is
    displayed.
    (re-apply of pull request #8)
2015-01-23 22:21:06 +08:00
Matt Johnston
1ed8d3938e Enable sha2 HMACs by default, they're required for ecdsa already 2015-01-13 20:55:04 +08:00
Matt Johnston
b24984deb3 clear hash state memory after use 2015-01-04 23:10:59 +08:00
Matt Johnston
eabd9f5e60 clarify bad/unknown 2015-01-04 22:32:38 +08:00
Catalin Patulea
d4609682af Handle invalid agent keys by skipping rather than exiting.
My agent exposes both conventional keys and certs (ecdsa-sha2-nistp256-cert-v01@openssh.com) and I want dropbear to be able to use the former.
2015-01-01 17:47:46 -05:00
Matt Johnston
634415f79e Open directories O_RDONLY for fsync, add debugging if it fails 2015-01-04 22:22:43 +08:00
Matt Johnston
4ba830fc31 Make sure hostkeys are flushed to disk to avoid empty files if the power
fails. Based on patch from Peter Korsgaard
2014-11-08 22:15:16 +08:00
Matt Johnston
3022a46039 Added signature for changeset 2d421bc0545d 2014-10-23 22:09:46 +08:00
Matt Johnston
d9a868ff60 Added tag DROPBEAR_2014.66 for changeset 735511a4c761 2014-10-23 22:09:22 +08:00
Matt Johnston
c890a0c133 changelog, version number bump 2014-10-23 21:43:00 +08:00
Matt Johnston
9ec934a94a Remove -o from scp help 2014-10-23 20:52:10 +08:00
Matt Johnston
5e606a964b increae MAX_STRING_LEN for sun ssh 2014-10-23 20:50:06 +08:00
Steven Honeyman
d88034434c Don't print "Failed loading hostkey" when -R delayed hostkey option is enabled 2014-10-22 07:12:52 +08:00
Matt Johnston
776d908703 Combine code for SSH_CONNECTION and SSH_CLIENT 2014-10-21 22:33:49 +08:00
Matt Johnston
444b15889f Merge pull request #5 from rcleere/ssh_client
Add SSH_CLIENT environment variable
2014-10-21 21:43:20 +08:00
Ryan Cleere
957450582f Add SSH_CLIENT environment variable 2014-10-20 12:59:47 -05:00
Matt Johnston
6d2d3669f3 Make keepalive handling more robust, this should now match what OpenSSH does 2014-08-19 23:08:56 +08:00
Whoopie
1387654cc8 Fix wtmp, testing for wtmp.h and wtmpx.h doesn't make sense 2014-08-13 22:07:43 +08:00
Matt Johnston
10eb218fb0 Don't send SSH_MSG_UNIMPLEMENTED for keepalive responses 2014-08-13 21:48:47 +08:00
Matt Johnston
bfb2b30de6 Added signature for changeset caac692b366c 2014-08-08 21:53:47 +08:00
Matt Johnston
426d4d72c6 Added tag DROPBEAR_2014.65 for changeset e9579816f20e 2014-08-08 21:53:42 +08:00
Matt Johnston
cce29ba38c 2014.64 2014-08-08 21:40:42 +08:00
Mike Frysinger
ed2e276b3a use xauth in /usr/bin
Since the x.org rework, X has been installed into standard paths and not
its own random prefixes.  I think it's time we update the default paths
accordingly.
2014-08-01 06:14:19 -04:00
Matt Johnston
12a020aa62 Don't warn about ENOTSOCK when setting priority 2014-08-06 22:16:38 +08:00
Matt Johnston
b969101b33 Be a bit safer in case pw_name doesn't exist 2014-08-06 22:10:57 +08:00
Matt Johnston
86a742f635 merge 2014-08-06 22:08:16 +08:00
Matt Johnston
9468f7f6d6 Merge pull request #2 from iquaba/patch-1
Try without identifying current user
2014-08-06 22:04:49 +08:00
Matt Johnston
628a3f5cca Test for EAGAIN too 2014-08-06 21:55:43 +08:00
iquaba
e815e97440 Try without identifying current user
Small change that warns the user if the current user cannot be identified rather than aborting.  This came in handy when I put dropbear on a dlink that did not have a true user environment.  Falling back on the "-l" option and user@ options works just fine as a client.  The only implication I found is that the -J option will fail ungracefully without a known own_user.
2014-08-06 08:48:43 -05:00
Matt Johnston
0e7409c7ff Make sure the check_close() handler runs when a server child process exits 2014-07-28 23:23:49 +08:00
Matt Johnston
393ca2a290 Fix some format string warnings 2014-07-28 22:59:16 +08:00
Matt Johnston
ad1d48e07b Fix clock_gettime handling 2014-07-28 22:48:48 +08:00
Matt Johnston
ac98aae160 Added signature for changeset 96584b934d04 2014-07-27 23:11:52 +08:00
Matt Johnston
c1267398a2 Added tag DROPBEAR_2014.64 for changeset 0d2d39957c02 2014-07-27 23:11:47 +08:00
Matt Johnston
8c3a2bb63e Archive should be bz2 nor gz 2014-07-27 22:56:35 +08:00
Matt Johnston
923fc9087c - Don't use multichar constants since recent gcc complains
- Add release script
- Simplify print_version
2014-07-27 22:55:29 +08:00
Matt Johnston
83511fecc0 Version 2014.64 2014-07-27 22:25:18 +08:00
Matt Johnston
ed0552f214 Add '-V' for version
-h should exit with success
Update manpages
2014-07-27 22:06:26 +08:00
Matt Johnston
5cf83a7212 Avoid use-after-free when channel inithandler fails. Thanks to Coverity 2014-07-26 10:18:55 +08:00
Matt Johnston
7808eff0a9 changes for 2014.64 2014-07-25 22:22:39 +08:00
Matt Johnston
da57dd13c5 Set tcp priority as follows:
if (connecting || ptys || x11) tos = LOWDELAY;
else if (tcp_forwards) tos = 0;
else tos = BULK;

TCP forwards could be either lowdelay or bulk, hence the default priority.
2014-07-16 22:53:32 +08:00
Matt Johnston
f1826ea389 Fix auth timeout regression 2014-07-09 22:02:22 +08:00
Matt Johnston
c884e5000e Make -K keepalive behave like OpenSSH's ServerAliveInterval 2014-07-09 00:15:20 +08:00
Matt Johnston
1ccac01cee Make sure client exit messages don't get lost 2014-07-09 00:13:17 +08:00
Matt Johnston
50a5d3756f Send a failure response if a client receives a global request 2014-07-08 21:59:36 +08:00
Matt Johnston
ca86726f9f Improve handling lots of concurrent forwarded connections. Increase
connection backlog, avoid check_close() for channels that haven't had IO
2014-06-25 23:42:39 +08:00
Matt Johnston
6b5317e7cc Fix compiling with ECDSA and DSS disabled 2014-06-25 23:37:44 +08:00
Matt Johnston
2a1d28ea3a Be more careful in case a platform doesn't define UIO_MAXIOV nor IOV_MAX 2014-05-20 21:21:02 +08:00
Ronny Meeus
0e0ff51582 Limit size of the iovect passed to writev in packet.c 2014-05-20 21:18:48 +08:00
Ronny Meeus
cd700aaf6e Print errno information in write_packet 2014-05-20 20:56:59 +08:00
Matt Johnston
188ec1e258 Fix pubkey auth if the first key presented fails (infinite loop of
auth requests). Regresssion in ff597bf2cfb0
2014-04-23 16:22:50 +08:00
Matt Johnston
d01fb265d6 Fix monotonic_now() on OS X 2014-03-21 22:16:42 +08:00
Matt Johnston
db688e3ec1 Experiment of always writing data if available. Might waste a writev() with
EAGAIN but always saves a select() - needs testing with bandwidth-limited
and CPU-limited situations.
2014-03-15 11:37:02 +08:00
Matt Johnston
e767bbb41f Add new monotonic_now() wrapper so that timeouts are unaffected by
system clock changes
2014-03-13 23:50:09 +08:00
Matt Johnston
2b599df57a Fix typo 2014-03-13 23:08:47 +08:00
Yousong Zhou
5baa10a6b6 Use AUTH_TIMEOUT only before authdone != 1.
While at it, fix a few indentations and typo.
2014-03-13 16:28:16 +08:00
Matt Johnston
3e1a389629 Don't need to mkdir 2014-03-08 21:00:57 +08:00
Matt Johnston
37e6207396 Fix env vars for travis again 2014-03-07 21:46:51 +08:00
Matt Johnston
927a2dc849 Fix "make install" dependency so that it works without prior "make" 2014-03-07 21:30:20 +08:00
Matt Johnston
ce9f9594da Add some tests for multi 2014-03-07 21:14:12 +08:00
Matt Johnston
f0bf37b6cb Install system libtom libs, run dropbearkey when it's done 2014-03-07 21:03:43 +08:00
Matt Johnston
2f0b35a105 The arguments are for configure, not make! 2014-03-07 20:52:57 +08:00
Matt Johnston
7a9ed81f5f Add Travis CI autobuilder config 2014-03-07 20:44:32 +08:00
Matt Johnston
12e7d570a2 Make some debug info conditional 2014-02-24 20:53:32 +08:00
Matt Johnston
bb7934bf04 A few fixes for cases where compression increases payload sizes, and
be more precise about maximum channel sizes
2014-02-22 18:02:09 +08:00
Matt Johnston
fb3c718963 Fix typo in Catalin's name 2014-02-19 22:18:11 +08:00
Matt Johnston
231fc607f9 Added signature for changeset 277429102f13 2014-02-19 22:14:58 +08:00
Matt Johnston
9594a3aa45 Added tag DROPBEAR_2014.63 for changeset 2351b2da8e0d 2014-02-19 22:14:52 +08:00
Matt Johnston
162fcab347 2014.63 2014-02-19 22:04:35 +08:00
Catalin Patulea
0c8bdfd7cd README: fix ecdsa key generation command 2014-02-09 03:56:50 -05:00
Matt Johnston
5e4dc71907 CHANGES for 2014.63 2014-02-19 22:01:01 +08:00
Matt Johnston
3e4433f715 - Fix dbclient with port 0 for server-allocated
- Fix port forwards with a bind address of 127.0.0.1 vs "localhost" etc
2014-02-18 21:33:56 +08:00
Matt Johnston
29062e629f Fix building with system libtomcrypt/libtommath 2014-02-18 21:03:27 +08:00
Steve Dover
47f7272ba1 Add linux/types.h to includes to avoid missing ___u64 etc 2014-02-17 22:05:59 +08:00
Matt Johnston
bf6f3f613d Read (and enqueue) packets from interactive input even when
we're waiting for a key exchange.

This should hopefully fix the situation where "~." doesn't work to terminate a
client session when a laptop wakes up. The client will be stuck waiting for a
key exchange on a dead connection, so won't have read the escape character
2014-02-17 21:41:06 +08:00
Matt Johnston
0c9a643216 Change port separator to ^ since % is used in ipv6 addresses 2014-02-15 21:42:35 +08:00
Matt Johnston
fa2d843403 Disable immediate auth for delayed-zlib mode 2014-02-15 21:23:41 +08:00
Matt Johnston
1dc5312f00 - Save errno in signal handlers
- Use _exit() in segv handler
2014-02-15 21:13:57 +08:00
Matt Johnston
73444f2957 generate RSA keys of exact length 2014-02-14 23:18:45 +08:00
Matt Johnston
a18a6b8db8 cleanup before clearing keys 2014-02-12 22:15:02 +08:00
Nicolas Boos
bf56591fb8 Fix linking -lcrypt for systems without libcrypt in /usr/lib 2014-02-07 07:57:45 +08:00
Nicolas Boos
5ea428a30d Avoid linking dropbearconvert and dropbearkey to libz or libutil 2014-02-07 07:53:32 +08:00
Matt Johnston
af524c4d65 Fix check for EINTR 2014-01-28 22:44:24 +08:00
Matt Johnston
2bc9f35052 Back out accidentally committed files 2014-01-23 22:29:04 +08:00
Matt Johnston
55a0c5068f requirenext doesn't need two values 2014-01-23 22:25:52 +08:00
Matt Johnston
8128b15e41 Fix failing rekeying when we receive a still-in-flight packet 2014-01-23 21:56:35 +08:00
Matt Johnston
8081b0e033 Forgot to save the change 2014-01-17 21:42:32 +08:00
Matt Johnston
61cecbb337 DROPBEAR_CLI_AUTH_IMMEDIATE fixed, now enabled by default 2014-01-17 21:39:27 +08:00
Mike Frysinger
aee1309c91 Fix so that "make install" for multi target won't fail on scp which doesn't
have a manpage
2013-12-11 21:50:33 +08:00
Mike Frysinger
710c1df413 Turn dropbearmulti into a real target so we don't constantly re-link it 2013-12-11 21:48:02 +08:00
Matt Johnston
0f165a95a8 Added signature for changeset 3d1d7d151c0c 2013-12-03 22:00:38 +08:00
Matt Johnston
581f04c80b Added tag DROPBEAR_2013.62 for changeset 3d1d7d151c0c 2013-12-03 22:00:29 +08:00
Matt Johnston
511be4acc6 2013.62 2013-12-03 21:39:06 +08:00
Matt Johnston
d77b29f1d7 Update to 2013-10-01 2013-12-03 21:36:12 +08:00
Matt Johnston
092a4d9a7e Fix disabling DSS key 2013-12-03 21:26:59 +08:00
Matt Johnston
b3cab3ce31 Log when generating a hostkey 2013-12-03 21:13:58 +08:00
Matt Johnston
e5279b0e2e Update README 2013-12-03 21:03:23 +08:00
Matt Johnston
9ff337aa3b Exit if we don't have keys and -R wasn't specified 2013-12-03 20:59:03 +08:00
Catalin Patulea
441facc6e0 Fix TRACEs of cli_send_netcat_request 2013-12-03 00:06:35 +08:00
Matt Johnston
998d6cdfc4 - Sockets are set to lowdelay priority initially to improve conneciton setup
time
- Set non-pty connections to bulk for client and server
2013-12-03 00:04:48 +08:00
Catalin Patulea
ddc10b2d0c Set IPTOS_LOWDELAY on PTY sessions only 2013-12-02 22:55:43 +08:00
Matt Johnston
4f6f651b7d Only define LTM_DESC if it isn't already 2013-12-02 22:15:17 +08:00
Matt Johnston
68c7667a20 merge 2013-11-27 21:32:45 +08:00
Matt Johnston
0b62d71e70 - Increase buffer size, fixes converting 521bit ECC key
- Fix assertion that key size is exactly curve size
2013-11-27 21:30:05 +08:00
Matt Johnston
be5780ef90 Fix library order of libtom* 2013-11-25 23:39:15 +08:00
Matt Johnston
e5c52796c3 Try and fix utmp handling 2013-11-25 23:30:01 +08:00
Matt Johnston
c5e36f8e3c Fix some warnings 2013-11-25 23:08:33 +08:00
Matt Johnston
5a85c4b91b Added signature for changeset 9ec083a21adf 2013-11-14 22:39:27 +08:00
Matt Johnston
0201072c1b Added tag DROPBEAR_2013.61test for changeset e894dbc015ba 2013-11-14 22:39:16 +08:00
Matt Johnston
aa029ed991 2013.61test 2013-11-14 22:24:10 +08:00
Matt Johnston
0777e896f1 docs for ecdsa 2013-11-14 22:14:09 +08:00
Matt Johnston
7f90231b8f another new config.guess 2013-06-10 2013-11-14 22:07:18 +08:00
Matt Johnston
cbe63bbabe rename random.h to dbrandom.h since some OSes have a system random.h
--HG--
rename : random.c => dbrandom.c
rename : random.h => dbrandom.h
2013-11-14 22:05:47 +08:00
Matt Johnston
de1deaf0bd use oldstyle comments 2013-11-14 22:03:30 +08:00
Matt Johnston
e00a97944a Replace some deprecated macros with other ones, from Daniel Richard G. 2013-11-14 21:45:50 +08:00
Matt Johnston
a65f84db38 - Some fixes for old compilers like tru64 v4 from Daniel Richard G.
- Don't warn about blocking random device for prngd
2013-11-14 21:36:45 +08:00
Matt Johnston
8c8ecec3e9 merge ecc again 2013-11-14 20:45:46 +08:00
Matt Johnston
b77864931b Don't exit fatally if authorized_keys has a line like
command="something" ssh-rsa

--HG--
branch : ecc
2013-11-12 23:58:51 +08:00
Matt Johnston
e60a84d0ed Various cleanups and fixes for warnings
--HG--
branch : ecc
2013-11-12 23:02:32 +08:00
Matt Johnston
f025277147 comments, turn off debugging options
--HG--
branch : ecc
2013-11-09 00:14:28 +08:00
Matt Johnston
1e00d0b926 - Make curve25519 work after fixing a typo, interoperates with OpenSSH
- comment on ecc binary size effects

--HG--
branch : ecc
2013-11-09 00:02:26 +08:00
Matt Johnston
29b1455f36 Merge
--HG--
branch : ecc
2013-11-08 23:32:13 +08:00
Matt Johnston
0162c116da curve25519
--HG--
branch : ecc
2013-11-08 23:11:43 +08:00
Matt Johnston
58fe1c2d2a Add '-R' for delayed hostkey option
--HG--
branch : keyondemand
2013-11-07 23:49:37 +08:00
Matt Johnston
4363b8b32d refactor key generation, make it generate as required.
Needs UI in server command line options

--HG--
branch : keyondemand
2013-11-07 00:18:52 +08:00
Matt Johnston
cfac8435a7 merge yet again 2013-11-01 00:21:59 +08:00
Matt Johnston
35f26ff855 merge again 2013-11-01 00:19:25 +08:00
Matt Johnston
f66fc01620 Merge 2013-11-01 00:14:48 +08:00
Matt Johnston
082a2dde35 Fix specifying a keysize for key generation, fix key name arguments
--HG--
branch : ecc
2013-11-01 00:13:09 +08:00
Matt Johnston
814ab77538 Default to some larger key sizes
--HG--
branch : ecc
2013-10-31 22:49:15 +08:00
Matt Johnston
8eefb092c8 Merge in ECC 2013-10-21 22:57:21 +08:00
Matt Johnston
55e7f0486a Fix shadowed "ret" variable
--HG--
branch : ecc
2013-10-21 22:50:52 +08:00
Matt Johnston
88ac2da7c2 A few small fixes for ECC compilation
--HG--
branch : ecc
2013-10-21 22:46:12 +08:00
Matt Johnston
27510a6e9e merge
--HG--
branch : ecc
2013-10-20 21:07:05 +08:00
Matt Johnston
7fda6418e1 writing out openssh ecc keys works
--HG--
branch : ecc
2013-10-20 21:06:18 +08:00
Matt Johnston
45bd0edae5 Merge in changes from the past couple of releases
--HG--
branch : ecc
2013-10-18 21:38:01 +08:00
Matt Johnston
3d733a16e9 Added signature for changeset a50a1dc74331 2013-10-16 22:55:03 +08:00
Matt Johnston
fe623afaad Added signature for changeset 025237c9f0a1 2013-10-16 22:52:43 +08:00
Matt Johnston
b840a980e3 Added tag DROPBEAR_2013.60 for changeset a50a1dc74331 2013-10-16 22:52:05 +08:00
Matt Johnston
2ec98eb048 Update debian changelog for 2013.60 too 2013-10-16 22:34:25 +08:00
Matt Johnston
253cd3b66b - 2013.60, update CHANGES
- Add CVE references to CHANGES
2013-10-16 22:32:31 +08:00
Matt Johnston
920120d05a Make --disable-bundled-libtom work, based on patch from Mike Frysinger 2013-10-15 22:55:44 +08:00
Matt Johnston
4ba058986e - Fix "inst_scp" target since there isn't a manpage
- Fix "make install MULTI=1"
2013-10-09 22:24:39 +08:00
Matt Johnston
03b7255ddd Add @exec_prefix@ that was missing 2013-10-09 21:58:07 +08:00
Matt Johnston
2de7f8b224 Added signature for changeset deb211f75ca1 2013-10-04 22:40:28 +08:00
Matt Johnston
bbf2f1d571 Added tag DROPBEAR_2013.59 for changeset 7b68e581985f 2013-10-04 22:39:09 +08:00
Matt Johnston
9cdd5e99a4 Fix up debian build 2013-10-04 22:22:35 +08:00
Matt Johnston
897ed7125b Fix debian installation of manpages 2013-10-04 21:49:32 +08:00
Matt Johnston
459d259185 Version 2013.59 2013-10-04 21:41:19 +08:00
Matt Johnston
aac6336e49 Don't say "SSH 2" any more since protocol version 1 is irrelevant 2013-10-03 23:50:04 +08:00
Matt Johnston
fc1155f974 Add manpage for dropbearconvert
Move dropbearkey to manual section 1
Add install target for manpages

--HG--
rename : dropbearkey.8 => dropbearkey.1
2013-10-03 23:45:25 +08:00
Matt Johnston
6a09fa23d0 Get rid of spurious newlines in pam log messages 2013-10-03 23:04:26 +08:00
Matt Johnston
142a0f8a83 Send PAM error messages as a banner messages
Patch from Martin Donnelly, modified.
2013-10-03 23:04:11 +08:00
Matt Johnston
d1dec41f76 Constant time memcmp for the hmac and password crypt 2013-10-03 22:25:30 +08:00
Matt Johnston
69a165db86 Only send a failure response to a channel request if wantreply is set. 2013-09-21 00:34:36 +08:00
Matt Johnston
dffb33cecf Improve EOF handling for half-close. Patch from Catalin Patulea
Fixes the situation
$ ./dbclient root@1.2.3.4 'cat; echo foo'
^D
<no output>
2013-09-21 00:17:22 +08:00
Matt Johnston
e7917c16c9 Remove accidental one second sleep leftover from debugging 2013-08-12 22:41:00 +08:00
Matt Johnston
e05b7f0b76 merge 2013-07-08 22:43:56 +08:00
Matt Johnston
aeea70f95f strdup the proxycmd to avoid crash when freeing, from Lluís Batlle i Rossell 2013-07-08 22:42:32 +08:00
Matt Johnston
ded40babb5 limit how much we read from rt_cache etc 2013-05-28 22:16:57 +08:00
Matt Johnston
e355f69401 merge 2013-05-26 18:43:00 +08:00
Matt Johnston
c2b1327deb merge 2013-05-26 18:42:17 +08:00
Matt Johnston
f7ba7444e8 improve auth failure delays to avoid indicating which users exist 2013-05-26 18:39:24 +08:00
Matt Johnston
aafeebd0c8 have separate ecdsa keys for each size
fix crash from the mp_alloc_init_multi change in RSA

--HG--
branch : ecc
2013-05-25 00:54:19 +08:00
Matt Johnston
6b0d47b364 hackish ECC import code from OpenSSH
--HG--
branch : ecc
2013-05-23 22:18:33 +08:00
Matt Johnston
d9e790e7dc Add m_mp_alloc_init_multi() helper
--HG--
branch : ecc
2013-05-23 22:18:16 +08:00
Matt Johnston
51b5cdd430 Enable SMALL_CODE by default
--HG--
branch : ecc
2013-05-21 13:44:48 +08:00
Matt Johnston
aced7b5b00 Fix static library order, libtomcrypt depends on libtommath
--HG--
branch : ecc
2013-05-21 13:20:02 +08:00
Matt Johnston
0475594cb2 Fix broken disablekey()
--HG--
branch : ecc
2013-05-21 12:15:48 +08:00
Matt Johnston
04518e9e80 merge in HEAD
--HG--
branch : ecc
2013-05-21 12:09:35 +08:00
Matt Johnston
a57947c513 Fix bad comma in header list 2013-05-13 21:35:13 +08:00
Matt Johnston
372e81a842 Update config.guess and config.sub 2013-05-13 21:06:35 +08:00
Matt Johnston
41f531ceaf quieten the compiler
--HG--
branch : ecc
2013-05-09 23:27:23 +08:00
Matt Johnston
b46d46667f merge
--HG--
branch : ecc
2013-05-09 23:25:39 +08:00
Matt Johnston
226671b550 Fix build for dropbearkey and ecdsa with certain options
--HG--
branch : ecc
2013-05-09 23:24:58 +08:00
Matt Johnston
916cfa6b83 Fix ecdsa verification
--HG--
branch : ecc
2013-05-09 23:24:05 +08:00
Matt Johnston
49263b5314 Limit decompressed size 2013-05-08 23:23:14 +08:00
Matt Johnston
95a21c8fd7 ecdsa is working
--HG--
branch : ecc
2013-05-03 23:07:48 +08:00
Matt Johnston
57166b400c Avoid segfault for locked accounts (invalid salt to crypt()) 2013-04-29 23:42:37 +08:00
Matt Johnston
79660f2eb1 more ecdsa signkey work, not correct
--HG--
branch : ecc
2013-04-28 23:17:43 +08:00
Matt Johnston
3ea9068e18 Save with utf8 encoding 2013-04-18 23:15:17 +08:00
Matt Johnston
e4c672bdbb Added signature for changeset f168962bab85 2013-04-18 23:10:24 +08:00
Matt Johnston
791a78ad1f Added tag DROPBEAR_2013.58 for changeset e76614145aea 2013-04-18 23:10:19 +08:00
Matt Johnston
6da90b34fe 2013.58 2013-04-18 22:57:47 +08:00
Matt Johnston
43769b5bb3 Don't enable CLI_IMMEDIATE_AUTH by default, it breaks blank password logins 2013-04-18 21:47:38 +08:00
Matt Johnston
f98eb5808b Use % rather than # for port delimiter 2013-04-17 23:17:27 +08:00
Matt Johnston
3525cabf48 Use '#' for host#port separator, document it. This fixes scp
in multihop
2013-04-17 22:48:43 +08:00
Matt Johnston
54a76342f5 If running as non-root only allow that user to log in 2013-04-17 22:29:18 +08:00
Matt Johnston
154a65fc31 Fix build when zlib is disabled, from
http://freetz.org/browser/trunk/make/dropbear/patches/350-no_zlib_fix.patch
2013-04-16 22:16:32 +08:00
Matt Johnston
bd7a46f514 Added signature for changeset 095b46180bbc 2013-04-15 22:11:11 +08:00
Matt Johnston
79a307bca2 Added tag DROPBEAR_2013.57 for changeset 96b8bcb88017 2013-04-15 22:10:49 +08:00
Matt Johnston
38f42a0fa2 Fix error message for requirenext change 2013-04-15 22:01:41 +08:00
Matt Johnston
b4cdfcb506 bump version to 2013.57 2013-04-15 21:56:04 +08:00
Matt Johnston
d3cef72f26 changelog updates for 2013.57 2013-04-15 21:51:27 +08:00
Matt Johnston
ef151888fb requirenext fixup for firstkexfollows 2013-04-14 23:16:16 +08:00
Matt Johnston
ba15bbfe33 Document escape chars 2013-04-14 23:08:57 +08:00
Matt Johnston
3bdfae61a2 merge 2013-04-14 22:49:19 +08:00
Matt Johnston
4404126501 -y -y to disable hostkey checking
fix missing trailing space when passing arguments for multihop mode
From Hans Harder
2013-04-14 22:49:10 +08:00
Matt Johnston
5c87c6a435 A bit of work on ecdsa for host/auth keys
--HG--
branch : ecc
2013-04-14 00:50:03 +08:00
Matt Johnston
adeb372a66 Fix zlib for split newkeys 2013-04-11 23:03:58 +08:00
Matt Johnston
c0d7c6693f run closehandlers on cleanup 2013-04-10 21:32:55 +08:00
Matt Johnston
3ec4670478 reset terminal modes before printing a message 2013-04-10 21:32:44 +08:00
Matt Johnston
f842712551 A bit of debugging output
--HG--
branch : ecc
2013-04-09 22:47:03 +08:00
Matt Johnston
9f01625e23 Be safer with how we handle ltc_ecc_sets[] (particularly with
system libtomcrypt)

A bit of progress with ecdsa code

--HG--
branch : ecc
2013-04-09 22:44:19 +08:00
Matt Johnston
7f091e7019 start on ecdsa keys
--HG--
branch : ecc
2013-04-09 00:36:04 +08:00
Matt Johnston
4f07805d0a - Rename buf_put_ecc_pubkey_string() to buf_put_ecc_raw_pubkey_string()
- Reindent ecc.c properly

--HG--
branch : ecc
2013-04-08 23:56:31 +08:00
Matt Johnston
a7d1a9cfcb add printmpint() for debugging
--HG--
branch : ecc
2013-04-08 23:12:35 +08:00
Matt Johnston
48c83aa9d0 ecdh works against OpenSSH
--HG--
branch : ecc
2013-04-08 23:12:20 +08:00
Matt Johnston
c797c1750c - Fix various hardcoded uses of SHA1
- rename curves to nistp256 etc
- fix svr-auth.c TRACE problem

--HG--
branch : ecc
2013-04-08 00:10:57 +08:00
Matt Johnston
c6bdc810ab ecc kind of works, needs fixing/testing
--HG--
branch : ecc
2013-04-07 01:36:42 +08:00
Matt Johnston
a8135dec1e Make _sign and _verify functions take a buffer* rather than void* and int
--HG--
branch : ecc
2013-04-06 16:00:37 +08:00
Matt Johnston
2fdb5fd6ce setup tcp after requesting a channel - might hide some DNS latency 2013-04-04 07:51:13 +08:00
Matt Johnston
7f42096d0f Take transmit and receive keys into use separately 2013-04-04 00:18:50 +08:00
Matt Johnston
e2c813df4d Fix MAC bug which would prevent asymmetric hashes 2013-04-03 23:54:58 +08:00
Matt Johnston
a2f70a3751 Just put the version string on the queue, don't use atomicio 2013-04-03 19:23:53 +08:00
Matt Johnston
286fa93a8d fix leftover kexguess debugging 2013-04-03 07:34:18 +08:00
Matt Johnston
557d86aa79 Fix a few options and headers 2013-04-03 07:33:47 +08:00
Matt Johnston
8e68d5e2d5 merge 2013-04-03 00:50:46 +08:00
Matt Johnston
1a16da38d5 merge kexguess branch 2013-04-03 00:49:24 +08:00
Matt Johnston
cbd3d5e3a5 Put some #ifdef options around first-follows options in case they
need to be disabled

--HG--
branch : kexguess
2013-04-03 00:43:31 +08:00
Matt Johnston
78fbed8c3e Don't usually need to recalculate dh_e for the repeated kexdh_init packet
--HG--
branch : kexguess
2013-04-03 00:32:55 +08:00
Matt Johnston
f267ca1f3a Add sentinel attribute
--HG--
branch : kexguess
2013-04-03 00:32:05 +08:00
Matt Johnston
a6eb824950 add IUTF8 2013-04-02 19:11:13 +08:00
Matt Johnston
dcd1527a11 fix tabs 2013-04-02 18:59:00 +08:00
Matt Johnston
f8a92d1eed merge 2013-04-02 18:54:04 +08:00
Matt Johnston
e55e468754 Fix segfault when /dev/urandom isn't writable 2013-04-02 18:53:18 +08:00
Matt Johnston
ff2aa20565 Be a bit more careful about when we want to use CLI_AUTH_IMMEDIATE
Only use it if we have pubkeys to try, or we have $DROPBEAR_PASSWORD set
2013-04-02 00:11:53 +08:00
Matt Johnston
90b5691183 Run the cleanup handler also when we close due to TCP connection being closed 2013-04-01 22:26:55 +08:00
Matt Johnston
5af0d33164 Try password before interactive - bit of a hack 2013-04-01 22:26:24 +08:00
Matt Johnston
e5072c6b12 merge from head roundtrip changes
--HG--
branch : kexguess
2013-04-01 00:13:41 +08:00
Matt Johnston
90cf7f012c Move the more verbose TRACE() statements into TRACE2() 2013-04-01 00:07:26 +08:00
Matt Johnston
484516da51 Send an auth packet straight away, save another roundtrip
This needs a bit of testing to make sure it doesn't have side-effects.
2013-03-31 23:48:25 +08:00
Matt Johnston
5abe22d1a5 Fix incorrect logic for USE_VFORK and calling arg_setup() 2013-03-31 23:29:03 +08:00
Matt Johnston
f6b304250b Try using writev() for writing packets out to tcp 2013-03-31 23:15:35 +08:00
Matt Johnston
36526700a9 Don't bother waiting for a ssh-connection service reply - the server
will disconnect if it wasn't accepted
2013-03-31 21:38:17 +08:00
Matt Johnston
32294978a3 merge
--HG--
branch : kexguess
2013-03-31 00:41:15 +08:00
Matt Johnston
a0e931005b send out our kexinit packet before blocking to read the SSH version string 2013-03-31 00:40:00 +08:00
Matt Johnston
9c7485331a Get rid of client/server specific buf_match_algo, use single
function with a couple of if statements instead

--HG--
branch : kexguess
2013-03-30 23:55:05 +08:00
Matt Johnston
99d9cf500b Add kexguess2 behaviour
--HG--
branch : kexguess
2013-03-29 23:29:48 +08:00
Matt Johnston
4f62da0f0d first_kex_packet_follows working, needs tidying
--HG--
branch : kexguess
2013-03-29 20:44:13 +08:00
Matt Johnston
b4bcc60657 More changes for KEX and ECDH. Set up hash descriptors, make ECC code work,
ses.hash and ses.session_id are now buffers (doesn't compile)

--HG--
branch : ecc
2013-03-29 00:28:09 +08:00
Matt Johnston
5139bd42f6 Set LTC_SOURCE for proper ltm_desc etc
--HG--
branch : ecc
2013-03-29 00:26:46 +08:00
Matt Johnston
cf7a271f90 ecc key import function
--HG--
branch : ecc
2013-03-27 23:50:52 +08:00
Matt Johnston
74cad1612f more bits on ecc branch
--HG--
branch : ecc
2013-03-27 00:38:03 +08:00
Matt Johnston
73e22c115c refactor kexdh code a bit, start working on ecdh etc
--HG--
branch : ecc
2013-03-26 01:35:22 +08:00
Matt Johnston
9be0d6b53d Define _GNU_SOURCE for vasprintf 2013-03-24 00:02:20 +08:00
Mike Frysinger
bbf6d5f2f5 rename configure.in -> configure.ac
Latest autotools warn now if the file is named configure.in

--HG--
rename : configure.in => configure.ac
2013-03-24 00:00:39 +08:00
Matt Johnston
c4861340e9 Fix a few compile warnings 2013-03-23 23:17:01 +08:00
Matt Johnston
5996c3824c Add ~. and ~^Z handling to exit/suspend dbclient 2013-03-23 23:16:06 +08:00
Matt Johnston
c172fb3b32 Added signature for changeset 9b80981212fe 2013-03-21 23:35:07 +08:00
Matt Johnston
03a0d11c4d Added tag DROPBEAR_2013.56 for changeset 1b8b2b9d6e94 2013-03-21 23:33:12 +08:00
Matt Johnston
156e0187bf Forgot date in CHANGES 2013-03-21 23:29:04 +08:00
Matt Johnston
fcaaa7b4c2 2013.56 changelog 2013-03-21 23:19:06 +08:00
Matt Johnston
2f098325f8 update text about authorized_keys options 2013-03-21 23:11:16 +08:00
Matt Johnston
9dc30fbd2a Add URL to usage text 2013-03-21 23:10:47 +08:00
Matt Johnston
024d268d8c Make hmac-sha2-256 and hmac-sha2-512 work 2013-03-21 22:55:12 +08:00
Matt Johnston
eaa737fecd Make sure "struct timeval" is initialised on OS X to avoid valgrind warnings 2013-03-21 21:23:34 +08:00
Matt Johnston
845ad0be39 Fix "-c none" so that it allows aes during authentication
Default for options.h shouldn't allow "none"
2013-03-20 23:52:49 +08:00
Matt Johnston
2259ce4cdf Fix "-m none" case and ugly typo 2013-03-20 23:13:45 +08:00
Matt Johnston
34f9b2a8f7 Fix "-m none" case where an entire packet fits in a block and can be
read by read_packet_init()
2013-03-20 23:13:19 +08:00
Matt Johnston
d37dcc636f Merge "none" cipher/MAC branch. Also adds sha256 and sha512 2013-03-20 22:41:07 +08:00
Matt Johnston
804a1e69f2 use an empty writebuf rather than a NULL one 2013-03-20 22:31:07 +08:00
Matt Johnston
f7b1222073 document a few more changes 2013-03-20 00:05:19 +08:00
Matt Johnston
4fd4fbc255 Fix memory leak when direct TCP connections time out on connection.
Long-standing bug probably stemming from the awkwardly named
delete_channel() versus remove_channel()
2013-03-19 23:54:32 +08:00
Matt Johnston
8393c5f016 Allow specifying server "-p" options with ipv6 bracket notation,
patch from Ben Jencks
2013-03-19 20:55:11 +08:00
Matt Johnston
5ff341206e Android returns NULL for pw_crypt, set it to something else 2013-03-19 20:15:44 +08:00
Matt Johnston
da59afe798 ignore I_PUSH if it isn't defined, for Android from Reimar Döffinger 2013-03-19 20:12:19 +08:00
Matt Johnston
6270ed2f8a Fix compat basename() to handle paths with no slashes. Thanks to Frank Teo 2013-03-19 20:04:55 +08:00
Matt Johnston
80e77b5e6d Include /proc/vmstat as another random source 2013-03-19 19:47:29 +08:00
Matt Johnston
58c7d4474c link to Dropbear webpage 2013-03-19 19:43:47 +08:00
Matt Johnston
3af964304f Removed tag t:ltc-0.95-db-merge1 2013-03-19 19:26:54 +08:00
Matt Johnston
4289324c4b Removed tag t:ltc-0.95-orig 2013-03-19 19:26:46 +08:00
Matt Johnston
9f3c817491 fix signedness error in prototype 2013-03-11 23:07:45 +08:00
Matt Johnston
a9cf0ca25f improve subsystem/sftp documentation, and multi-hop manual formatting 2013-03-03 11:47:41 +08:00
Matt Johnston
72a5612a29 fix typo 2013-02-24 00:16:02 +08:00
Matt Johnston
d7f2153631 DSS_PROTOK is not necessary now that private keys are included
in the random generation input
2013-02-23 17:55:46 +08:00
Matt Johnston
26b07ccafc add loadavg and entropy_avail as sources 2013-02-23 10:27:49 +08:00
Paul Eggleton
1205fa68df Allow configuring "allow blank password option" at runtime
Changes this from a compile-time switch to a command-line option.

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
2013-02-12 15:52:57 +00:00
Matt Johnston
f5be0fb218 Some changes since 2012.55 2013-02-22 23:54:47 +08:00
Matt Johnston
88fc38c8f0 Document "-m" and "-c"
Update URLs with https
2013-02-22 23:53:49 +08:00
Matt Johnston
545de7a3a1 /dev/random blocks on busy servers too. 2012-07-19 21:34:27 +08:00
Matt Johnston
6ba2b2b384 Add a few more files in /proc for Linux 2012-06-30 22:12:28 +08:00
Matt Johnston
d5ccc32b4d Improve RNG seeding.
Try to read from /dev/urandom multiple times, take input from extra sources,
and use /dev/random when generating private keys
2012-06-29 23:19:43 +08:00
Matt Johnston
e719a9ef6f - Only request "none" cipher after auth has succeeded
--HG--
branch : insecure-nocrypto
2012-05-17 20:52:57 +08:00
Matt Johnston
a02d38072a Add ALLOW_NONE_PASSWORD_AUTH option
--HG--
branch : insecure-nocrypto
2012-05-17 08:33:11 +08:00
Matt Johnston
f2cd610750 Merge in "-m"/"-c" code
--HG--
branch : insecure-nocrypto
2012-05-17 08:09:19 +08:00
Matt Johnston
db34044c7f ENABLE_USER_ALGO_LIST should work for the client 2012-05-17 00:26:12 +08:00
Matt Johnston
036edd6206 Add rough support for choosing ciphers/hashes with "-c" or "-m" 2012-05-17 00:12:42 +08:00
Matt Johnston
f40ed8bad7 Update insecure-nocrypto to current head
--HG--
branch : insecure-nocrypto
2012-05-16 22:54:51 +08:00
Matt Johnston
41f50057f1 Disable SHA256 and SHA512 by default in options.h
--HG--
branch : sha2
2012-05-16 21:56:50 +08:00
Matt Johnston
c62e53807f - Add hmac-sha2-256 and hmac-sha2-512. Needs debugging, seems to be
getting keyed incorrectly

--HG--
branch : sha2
2012-05-10 08:38:37 +08:00
Matt Johnston
10d7a35841 Don't TRACE() the pw_passwd 2012-05-09 22:52:58 +08:00
Matt Johnston
6b4105ffe6 Fix empty password immediate login 2012-05-09 22:51:59 +08:00
Matt Johnston
2713445e91 Return immediate success for blank passwords if allowed 2012-05-09 22:37:04 +08:00
Matt Johnston
1984aabc95 Server shouldn't return "localhost" in response to -R forward connections
if that wasn't what the client requested.
2012-05-09 21:09:34 +08:00
Matt Johnston
f4c4ca64a8 Initialise agent_fd to -1 so we don't end up closing stdin (fd 0)
if public key authentication is disabled
2012-05-09 20:34:55 +08:00
Matt Johnston
2a02c4084a - Don't sent SSH_MSG_UNIMPLEMENTED if we don't have ENABLE_SVR_REMOTETCPFWD
- Fix build if ENABLE_SVR_REMOTETCPFWD is disabled but ENABLE_SVR_LOCALTCPFWD
  is enabled
2012-05-09 20:33:16 +08:00
Matt Johnston
e242b2820c Ignore -q if SCP_PROGRESS isn't set 2012-04-24 22:05:55 +08:00
Matt Johnston
6467b8d903 Split listening port argument at the rightmost colon, allows binding to
specific IPv6 addresses.

From OpenWRT,
https://dev.openwrt.org/browser/trunk/package/dropbear/patches/300-ipv6_addr_port_split.patch
2012-04-12 22:04:16 +08:00
Matt Johnston
3e2b6a1821 Improve comment about sha1-96 2012-04-12 21:57:30 +08:00
Matt Johnston
4d009daaa0 Slight formatting change for ENABLE_CLI_AGENTFWD if statement 2012-04-09 21:29:41 +08:00
Andrey Mazo
d4a14fcb3d Fixed compilation with unset ENABLE_{SVR,CLI}_AGENTFWD.
Got rid of ENABLE_AGENTFWD macro.
2012-03-26 16:17:16 +04:00
Matt Johnston
49b79fa02d Rename HAVE_FORK to USE_VFORK
It makes it a bit more obvious why there's a test there since HAVE_FORK
is the normal case.
2012-04-09 20:35:13 +08:00
Mike Frysinger
c957edbe75 check for fork() and not __uClinux__ 2012-04-08 01:50:52 -04:00
Mike Frysinger
33ae2be52e fix out-of-tree cleaning
If we build out of tree and then run `make clean`, we hit an
infinite loop where libtommath tries to enter subdirs that don't
exist and run `make clean`.
2012-04-08 02:06:54 -04:00
Matt Johnston
496c1db974 Added signature for changeset 85f835f2fe0a 2012-02-23 21:46:02 +08:00
Matt Johnston
f381274278 Added tag DROPBEAR_2012.55 for changeset d354464b2aa6 2012-02-23 21:45:42 +08:00
Matt Johnston
398339218e - Improve CHANGES description 2012-02-23 21:45:36 +08:00
Matt Johnston
4dda424f74 2012.55 2012-02-22 22:12:15 +08:00
Matt Johnston
f403c1f18b - Fix minor leak 2012-02-22 22:05:24 +08:00
Matt Johnston
ff5d94a7a4 Fix accidentally committed change 2012-02-22 19:33:07 +08:00
Matt Johnston
a15fc009da - Initialise sa_mask properly 2011-12-04 05:41:46 +08:00
Matt Johnston
6c4390c848 - Merge 2012-02-21 23:00:30 +08:00
Matt Johnston
a3188b44f0 - Make sure sa_mask is set 2012-02-21 22:57:19 +08:00
Matt Johnston
aaa72ddbfc - Burn buffers to 0x00 instead 2012-02-21 22:56:45 +08:00
Matt Johnston
bcf3a3ab93 Merge 2012-02-10 19:09:52 +08:00
Matt Johnston
5feebd300e Clear a few buffers when possible 2012-02-10 18:32:18 +08:00
Matt Johnston
aec23e5f79 - Fix use-after-free if multiple command requests were sent. Move
the original_command into chansess struct since that makes more sense
2011-12-04 05:31:25 +08:00
Matt Johnston
52a466b8af - Remove unused variable/code 2011-12-04 05:27:57 +08:00
Matt Johnston
baa32218b0 - Make sure we don't use channel-specific data after it has been freed
with a ChanType->closehandler()
2011-12-04 05:27:29 +08:00
Matt Johnston
fd0b05943d - Fix some format strings in TRACE()s 2011-12-04 05:24:50 +08:00
Matt Johnston
2e0145fb95 - We don't need to test for NULL before free() 2011-12-04 05:23:43 +08:00
Matt Johnston
c894ea4ea2 Put better #if guards around IPv6 socket options for IPV6_TCLASS and
IPV6_V6ONLY. From Gustavo Zacarias.
2011-11-10 18:17:00 +08:00
Matt Johnston
88278dee74 Added signature for changeset 3f12086c2ef2 2011-11-08 21:06:29 +08:00
Matt Johnston
d0fadd992f Added tag DROPBEAR_2011.54 for changeset 3f12086c2ef2 2011-11-08 21:06:01 +08:00
Matt Johnston
eb45ce0e8a Changelog and version bump for 2011.54 2011-11-08 20:48:15 +08:00
Matt Johnston
194b700592 Fix symlink target created by installdropbearmulti 2011-11-08 20:33:19 +08:00
Matt Johnston
5454c2a7f1 Added signature for changeset aa2f51a6b81d 2011-11-08 00:01:47 +08:00
Matt Johnston
a6568626a5 Use "uint64_t" instead of "u_int64_t" since the Solaris doesn't have the
latter
2011-11-07 19:31:53 +08:00
Matt Johnston
59943acffe Fix crash with -R forwarding 2011-11-06 20:22:34 +08:00
Matt Johnston
d4e7654ed0 Print the server allocated port when using dbclient -R 0:....
Patch from Ali Onur Uyar
2011-11-05 23:12:15 +08:00
convert-repo
68b458ece9 update tags 2011-11-03 07:18:37 +00:00
Matt Johnston
1119ad3a2f Set IPTOS_LOWDELAY for IPv6 too
--HG--
extra : convert_revision : bebc84493fc5f4ca914ae8828e6db7204c086ac2
2011-10-26 16:02:06 +00:00
Matt Johnston
29e68e9d79 - Add ALLOW_BLANK_PASSWORD option
- Don't reject blank-password logins via public key

--HG--
extra : convert_revision : 2d4bb3ecb013a7be47a7b470fc6b23e653a43dfb
2011-10-26 15:49:47 +00:00
Matt Johnston
c1fe2ec5ae Try bind IPV6_V6ONLY
--HG--
extra : convert_revision : cfe965c1503984cafaa98b684269db99bec310eb
2011-10-20 13:45:43 +00:00
Matt Johnston
81cacd9f15 list.c also has no trailing newline
--HG--
extra : convert_revision : cfe8e94b86e98f79b18abebbcd49c6eb5908c74c
2011-07-05 12:52:06 +00:00
Matt Johnston
6def0ab5f1 Fix lost ending newline
--HG--
extra : convert_revision : eacbbecc4f4aad52a29b013beed83b7d54a98796
2011-07-05 12:50:15 +00:00
Matt Johnston
d20627585a Hopefully fix -lcrypt problem
--HG--
extra : convert_revision : 94d41df148dba424a62b442aebdb5cf0db11449a
2011-06-30 14:34:32 +00:00
Matt Johnston
2bcb60fe56 Fix case where "-K 1" would cause a SSH_MSG_IGNORE packet to be sent
with the wrong encryption key ("bad packet length" symptom) while
key exchange was happening.

--HG--
extra : convert_revision : f7d27ec094c4aba2a4289c523c722fcb3c3f58ca
2011-06-07 11:55:44 +00:00
Matt Johnston
0f83379dc0 Mention that the value is in seconds
--HG--
extra : convert_revision : fcdafc69f831ab356b34815958114cc3d75d23bb
2011-06-07 11:08:47 +00:00
Matt Johnston
ca6d5fd05c Clean up leaked FD if getnameinfo fails. From Klocwork
--HG--
extra : convert_revision : 712881a0b28aa45804bed6803fb72a4a35714e41
2011-04-07 13:52:43 +00:00
Matt Johnston
b9e21e2367 Fix crash when remote forwarding was requested
--HG--
extra : convert_revision : 5c0a794976692a54ec36111291179020e2ae6c1e
2011-04-07 13:39:10 +00:00
Matt Johnston
665b768cef Fix leak found by Klocwork
--HG--
extra : convert_revision : 51ce088e100e9ea150efc6bf3d021f019a46b2f5
2011-04-07 13:38:27 +00:00
Matt Johnston
b272b967e2 Properly fix the bug found years ago by Klocwork, refound again.
--HG--
extra : convert_revision : 65b95facde07c748c56e0bfa25c801397dc16a99
2011-04-07 13:33:26 +00:00
Matt Johnston
22c16a8b71 Clean up fd on failure. Found by Klocwork
--HG--
extra : convert_revision : 4b999175c8e91ee3ddf283b17525999499a12849
2011-04-07 13:25:00 +00:00
Matt Johnston
f924aa18f2 Define LTC_NO_FILE to avoid hmac_file() etc
--HG--
extra : convert_revision : b918fd450c1572ce055a6a1fe8c161a495ddec34
2011-04-07 13:24:41 +00:00
Matt Johnston
72c446f160 Fix FD leak if connect() fails, found by Klocwork
--HG--
extra : convert_revision : 4f7dec450bb69aee8d7789b8ab10311b1d1655bb
2011-04-07 13:05:10 +00:00
Matt Johnston
2028b1b517 Add noreturn and format attribute hints for some functions.
--HG--
extra : convert_revision : 6cc8735d01f0360b918edc26be05681725c0022a
2011-04-07 12:59:18 +00:00
Matt Johnston
72a82cc0ac Fix memory leak found by Klocwork
--HG--
extra : convert_revision : 6f1e5e6dd6462f1c35a6bfd601a0f5f8b99410d6
2011-04-07 12:34:44 +00:00
Matt Johnston
eef35883b7 Tidy error handling and get rid of some commented out code
--HG--
extra : convert_revision : beb6fc766123135d5ae455ff7ad6b48d85386f62
2011-04-07 12:30:20 +00:00
Matt Johnston
8028e07815 Change comparison to be more paranoid (and perhaps avoid Klocwork false
positive). Does not change behaviour.

--HG--
extra : convert_revision : 11d5ca4bf2f4197ed2d14b6772a351bcb59f775e
2011-04-07 11:18:35 +00:00
Matt Johnston
3fc6569d46 Fix check of wrong variable found by Klocwork
--HG--
extra : convert_revision : 6f3b074e83bb808019f49c5aca3451b70f9f1e8f
2011-04-07 11:14:22 +00:00
Matt Johnston
2303d0fd09 Avoid segfault when handling childpid race
--HG--
extra : convert_revision : 8845727a7e2b096015dbb76d8f3df13c9acee7da
2011-03-31 14:42:11 +00:00
Matt Johnston
9a007c30d4 Use mp_init_size() to avoid some mp_grow()s
--HG--
extra : convert_revision : 94b7dd79a8e970e9641d4e655b3db48190ac2531
2011-03-18 14:31:07 +00:00
Matt Johnston
8a545a0d04 Update changelog for 0.53.1
--HG--
extra : convert_revision : c7f6c45c46a2f8e2394756c68ae825d6e4dc7489
2011-03-02 13:23:27 +00:00
Matt Johnston
0993e44b4f merge of '8a608f0ed5e4b491dba4bf330e560636ec7376fd'
and 'b31879a384d3bf8cbcbe2ed731d7d79d49799b1d'

--HG--
extra : convert_revision : dfa0557e6070859d23ff096789f339e51a870177
2011-02-28 13:51:34 +00:00
Matt Johnston
d634b502cf - Don't allow setting memLevel since that doesn't work properly
- Better handling of the case where compressing makes the data
larger (possibly only happens when memLevel is adjusted, but better
to be safe)

--HG--
extra : convert_revision : b31879a384d3bf8cbcbe2ed731d7d79d49799b1d
2011-02-28 13:51:27 +00:00
Matt Johnston
53fc7eaf03 Compile fix for when both client and server agent forwarding is disabled
--HG--
extra : convert_revision : 8a608f0ed5e4b491dba4bf330e560636ec7376fd
2011-02-28 13:39:18 +00:00
Matt Johnston
3c42c5407c Refer to RFCs rather than drafts, update some section references
--HG--
extra : convert_revision : b5c5c88e702f427b9d5e8c592e2b7e1bda204ff3
2011-02-27 13:57:32 +00:00
Matt Johnston
9d9a8ff735 - Fix DROPBEAR_PRNGD_SOCKET since it doesn't need to call connect()
any more

--HG--
extra : convert_revision : 535f2029a34cba3d86eb8ce104d57c910c89c4a4
2011-02-27 13:12:17 +00:00
Matt Johnston
abed230cdb Updates changelog. Mention diffie-hellman-group14-sha1 in 0.53
release, -lcrypt order for 0.53.1

--HG--
extra : convert_revision : 2fa3bd3d29fe694a50f929a12ca249931c92311d
2011-02-25 12:16:14 +00:00
Matt Johnston
e9879cd07b -lcrypt needs to be before object files when static linking
--HG--
extra : convert_revision : 8ecc9a039f16d8492d2b7f64e8602d3f6302e212
2011-02-25 12:14:33 +00:00
Matt Johnston
84c51f933c - Set debian version to 0.53
--HG--
extra : convert_revision : bddea10d0d68b0beafbd98d694df462961e489e6
2011-02-24 14:21:36 +00:00
Matt Johnston
977c43fffb Changelog for 0.53, bump version
--HG--
extra : convert_revision : 5369d8c2cbcbc07a86fce6a1b66ebd4979866a2d
2011-02-24 14:19:36 +00:00
Matt Johnston
f99a19b6ca Mention -L/-R listenaddress argument in manpage
--HG--
extra : convert_revision : 2728be15a280f7b0d48741d033381c0ebf2281f5
2011-02-24 14:18:13 +00:00
Matt Johnston
5a7a88b843 It happened to sony
--HG--
extra : convert_revision : c2d5690ca9ed85c7d75dd9cc2c150de50503aa3b
2011-02-24 12:45:17 +00:00
Matt Johnston
0ffdf2bba9 Add diffie-hellman-group14-sha1 KEX method
--HG--
extra : convert_revision : 5b9c394ad43745e48c42d671cefac7a5c346082f
2011-02-24 12:42:42 +00:00
Matt Johnston
38ed870ffe Improve capitalisation for all logged strings
--HG--
extra : convert_revision : 997e53cec7a9efb7413ac6e17b6be60a5597bd2e
2011-02-23 15:50:30 +00:00
Matt Johnston
1e4ed404c5 merge of '8849ec659cb45b924158cc3322390a1d3d48daef'
and 'a46ca9204de0df58d8701df0d79b6b8ec601b9ce'

--HG--
extra : convert_revision : 00e4e5abea55474624e2ea0ea09f6fbc6c9e4c89
2011-02-23 15:10:31 +00:00
Matt Johnston
642920585f Don't reset last_packet_time when we're transmitting SSH_MSG_IGNORE packets
(from keepalives)

--HG--
extra : convert_revision : a46ca9204de0df58d8701df0d79b6b8ec601b9ce
2011-02-23 15:10:28 +00:00
Matt Johnston
af07eb115a remove unused variable
--HG--
extra : convert_revision : 8849ec659cb45b924158cc3322390a1d3d48daef
2010-07-21 14:07:13 +00:00
Matt Johnston
66371f9920 merge of '4b90e96a8a8afcc9feafc59cb47592a4a6d1cc30'
and '94427244d30e268c74ddade212e31ba01f6f0950'

--HG--
extra : convert_revision : 09d7a0d8401b94db3975c71f5bcafde428cb34d7
2010-07-21 13:53:29 +00:00
Matt Johnston
aabe0677c0 - Update fake-rfc2553.{c,h} from OpenSSH 5.5p1
--HG--
extra : convert_revision : 4b90e96a8a8afcc9feafc59cb47592a4a6d1cc30
2010-07-21 13:53:23 +00:00
Matt Johnston
0fa65ebd4d Fix bug in primality testing, see
http://bugs.gentoo.org/show_bug.cgi?id=328383
http://bugs.gentoo.org/show_bug.cgi?id=328409
https://bugzilla.redhat.com/show_bug.cgi?id=615088

Exact effects of the bug are uncertain.

--HG--
extra : convert_revision : 94427244d30e268c74ddade212e31ba01f6f0950
2010-07-21 13:33:07 +00:00
Matt Johnston
27fddd2c35 Work properly again with bundled libtom*. autoconf is a hassle.
--HG--
extra : convert_revision : 4077fc3332bd7c965aadbb05b02eba6d00fa9621
2010-07-21 13:27:44 +00:00
Matt Johnston
fced1113d3 Rename rsa_key to dropbear_rsa_key (and same for dss too) so
we don't conflict with libtomcrypt.

--HG--
extra : convert_revision : 77961344ec415d73d48fdc7b1ebead3099c13394
2010-07-21 12:55:25 +00:00
Matt Johnston
4d050c34cb Use system libtomcrypt/libtommath if available. Doesn't currently
build due to clash in rsa_key identifier.

--HG--
extra : convert_revision : c9a4726d1c89e17ee8e96801d1aaa8049216aae1
2010-07-21 12:38:46 +00:00
Matt Johnston
a8c28714cd Comment public/private parts
--HG--
extra : convert_revision : 914cbb822f488fa5d17affdad01fcc7dae6006b1
2010-07-20 13:54:20 +00:00
Matt Johnston
eabfd803c9 merge of '0adbc6745a5ada0b6780b0683209f5b26b1a335d'
and 'a014a978f213e6ff424e7d10794ae426375f3191'

--HG--
extra : convert_revision : eecc64377b2b55ba1d9e77855f4323cdc9f8e1c6
2010-03-21 06:07:22 +00:00
Matt Johnston
07b764ead6 - make structure static
--HG--
extra : convert_revision : 0adbc6745a5ada0b6780b0683209f5b26b1a335d
2010-03-21 06:06:42 +00:00
Matt Johnston
8bad5d61fd don't #include "utmp.h"
--HG--
extra : convert_revision : a014a978f213e6ff424e7d10794ae426375f3191
2010-03-04 14:50:19 +00:00
Matt Johnston
9f42a75ef6 - fixes for listenaddr
--HG--
extra : convert_revision : 9eebe96bb7c26c4c09c77a2e89a67a7332abcd49
2010-02-27 12:15:27 +00:00
Matt Johnston
ddbfdb0799 merge of '48fdaa8706d1acda35e9d564adc9a1fbc96c18c8'
and '658fd03abd21e0da7c4c89b9fff9dc693c72daae'

--HG--
extra : convert_revision : 8064882fcaa13d586651021462b9014b74332107
2010-02-27 11:53:18 +00:00
Matt Johnston
3b07844548 - tcpfwd bindaddr support against trunk. needs merging.
--HG--
extra : convert_revision : 658fd03abd21e0da7c4c89b9fff9dc693c72daae
2010-02-27 11:51:19 +00:00
Matt Johnston
85288d7b61 - Progress for allowing specifying a listenaddr for tcp forwards
--HG--
extra : convert_revision : 48fdaa8706d1acda35e9d564adc9a1fbc96c18c8
2010-02-24 16:13:15 +00:00
Matt Johnston
8174a2f27b Mention -p's address argument in manpage synopsis
--HG--
extra : convert_revision : abef8fc8584889de6fd92ceaec28d094419462e0
2009-09-13 15:31:29 +00:00
Matt Johnston
e3ca0513a0 - Disable compression for non-final multihops
--HG--
extra : convert_revision : c507a2aacb9e0db4c0266891b8915c614e32857e
2009-09-11 14:02:04 +00:00
Matt Johnston
95a01f9002 Remove extraneous semicolon
--HG--
extra : convert_revision : ea33f9576dd0ff344d6f1d150a01265470f56131
2009-09-10 11:12:31 +00:00
Matt Johnston
52551cb771 - Test for pam_fail_delay() function in configure
- Recognise "username:" as a PAM prompt
- Add some randomness to the auth-failure delay
- Fix wrongly committed options.h/debug.h

--HG--
extra : convert_revision : f242f0e66fb0ea5d3b374995d2f548d37dd8f3a3
2009-09-08 14:53:53 +00:00
Matt Johnston
4dfb834f7c Move remotehost into svr_ses structure since we can't look it up
once we've forked (the connection socket has been closed).
Fixes inetd mode.

--HG--
extra : convert_revision : 7d5d152ec84fb11a188966c1400d213c908cc511
2009-09-05 11:40:00 +00:00
Matt Johnston
c35e38c5e9 - Remove options that dbclient won't know about
--HG--
extra : convert_revision : 2d401308f73352e92d3c662d33920b24fc12bfa1
2009-09-02 15:17:14 +00:00
Matt Johnston
48734bb3b5 - scp progressbar needs strlcat(), so add compat.o
--HG--
extra : convert_revision : 0743230bac5ae28d1b773fb4d89c4d88b6a9a0c1
2009-09-02 15:05:14 +00:00
Matt Johnston
4e9f22c602 - Set $SSH_CONNECTION
- Document environment variables in the manpage

--HG--
extra : convert_revision : 1a93c6112f00730f5cd21a853d3bd5ca8079f725
2009-09-02 14:47:12 +00:00
Matt Johnston
f88bed7a30 Rearrange getaddrstring() etc
--HG--
extra : convert_revision : 8a18c4a60aeaec085923d13d98fa0f93c506ceba
2009-09-01 16:38:26 +00:00
Matt Johnston
ccd02552dd - set $SSH_TTY environment variable
- remove extraneous (crash causing) printf()

--HG--
extra : convert_revision : cf4b256bf6785be384eca32f7b229b89e58539eb
2009-08-31 15:25:39 +00:00
Matt Johnston
4b1f9e50f2 - set $SSH_ORIGINAL_COMMAND if a command is forced, and log it
if LOG_COMMANDS is set

--HG--
extra : convert_revision : d9e8aa0ecbe7607285fa4f96f0d6f9b1523719d8
2009-08-26 14:09:22 +00:00
Matt Johnston
0b50010436 merge of '0d7a9127af37d6e74efc5ec031a7001ce63d334d'
and 'e35cd321b6d4fab6ad854827249f610da3bb6878'

--HG--
extra : convert_revision : a0fef159e70c5d1b24d10764066290362965e879
2009-08-25 11:11:35 +00:00
Matt Johnston
d773103730 - Move netcat struct to where it stays in scope.
--HG--
extra : convert_revision : e35cd321b6d4fab6ad854827249f610da3bb6878
2009-08-25 05:24:18 +00:00
Matt Johnston
c7e3eb9b3f - Don't print warning if SSH_AUTH_SOCK is unset
--HG--
extra : convert_revision : 0d7a9127af37d6e74efc5ec031a7001ce63d334d
2009-08-13 14:57:27 +00:00
Matt Johnston
f15feb2ac6 - Handle failure to connect to forwarding socket
--HG--
extra : convert_revision : 0cc1ae25ba35931d6ddd9e989e875ef975616be6
2009-07-31 15:51:33 +00:00
Matt Johnston
2f1ed9a34b propagate from branch 'au.asn.ucc.matt.dropbear.cli-agent' (head eb0dae4b62e243ba37a897beb7ba81a4f637d8b3)
to branch 'au.asn.ucc.matt.dropbear' (head ff0abce7b29e61630e3b09e5fc5820ae6e192808)

--HG--
extra : convert_revision : 49e078caffa785d121cefaf05b64fecc71fecd63
2009-07-30 15:15:12 +00:00
Matt Johnston
bb8234c2f1 Agent forwarding works
--HG--
branch : agent-client
extra : convert_revision : eb0dae4b62e243ba37a897beb7ba81a4f637d8b3
2009-07-30 15:14:33 +00:00
Matt Johnston
bacd2a8c79 propagate from branch 'au.asn.ucc.matt.dropbear' (head bbe4e11695a7b22bd89a722600eb4a4020b6fdf3)
to branch 'au.asn.ucc.matt.dropbear.cli-agent' (head 276cf5e82276b6c879d246ba64739ec6868f5150)

--HG--
branch : agent-client
extra : convert_revision : d23b0c21649eb2f0b2d13dbf33c0a9faca25628a
2009-07-29 02:58:33 +00:00
Matt Johnston
103a829eac Use /usr/bin/X11/xauth default path instead
--HG--
extra : convert_revision : ff0abce7b29e61630e3b09e5fc5820ae6e192808
2009-07-28 16:16:14 +00:00
Matt Johnston
0dcecfa526 Turn off DEBUG_TRACE accidentally committed
--HG--
extra : convert_revision : bbe4e11695a7b22bd89a722600eb4a4020b6fdf3
2009-07-26 16:14:50 +00:00
Matt Johnston
bcd541d65f - Payload length doesn't include macsize.
--HG--
extra : convert_revision : 98ac17a573ab350cbd6e358b3943237d2ad5c9cf
2009-07-26 16:11:27 +00:00
Matt Johnston
3608775306 - Add option to change zlib windowBits/memLevel
--HG--
extra : convert_revision : 5fc51ba0b8f165426c78f8d32162e5ccb51e524f
2009-07-26 15:39:47 +00:00
Matt Johnston
8181d41bb5 Disable Blowfish by default, it has inefficient key memory use
--HG--
extra : convert_revision : a37b8ae5fb524be221dbdfd71b4f35eb6a48565c
2009-07-24 13:49:07 +00:00
Matt Johnston
a996e61a2e - For uclinux, only cleanup on exit for the main process. This avoids
trashing the state when a failing child exits.

--HG--
extra : convert_revision : 5d029ce4602908c3becf0035cf2b7e62816959bc
2009-07-09 16:01:30 +00:00
Matt Johnston
8a19a049b2 - Client auth using an agent's key works. Still need to implement client
agent forwarding.

--HG--
branch : agent-client
extra : convert_revision : 276cf5e82276b6c879d246ba64739ec6868f5150
2009-07-06 14:02:45 +00:00
Matt Johnston
c742137dc8 New standard linked list to use, rather than adhoc SignKeyList or TCPFwdList
--HG--
branch : agent-client
extra : convert_revision : 5465e639cc3f5ee0c6c55f0de6e7b6d5a8769da3
2009-07-06 12:59:13 +00:00
Matt Johnston
9dc9aff016 Talking to the agent works now. Can't interpret the pubkeys.
--HG--
branch : agent-client
extra : convert_revision : 357373f28e889108178b8627480fd24bc26dcbd7
2009-07-01 06:27:27 +00:00
Matt Johnston
c6582dbe37 Make it compile, update for changes in channel structure.
--HG--
branch : agent-client
extra : convert_revision : 84676a98a0848224078a716b1292744a34e9d80c
2009-07-01 04:53:17 +00:00
Matt Johnston
709a3e75cf propagate from branch 'au.asn.ucc.matt.dropbear' (head 899a8851a5edf840b2f7925bcc26ffe99dcac54d)
to branch 'au.asn.ucc.matt.dropbear.cli-agent' (head 6bbab8364de17bd9ecb1dee5ffb796e48c0380d2)

--HG--
branch : agent-client
extra : convert_revision : d39a49137cc36b624768d4e79e564141dde8d355
2009-07-01 04:16:32 +00:00
Matt Johnston
cb82c6e3e0 - Print banner to stderr. Probably the right way, and avoids
bad interactions with multihop or netcat-alike mode.

--HG--
extra : convert_revision : 899a8851a5edf840b2f7925bcc26ffe99dcac54d
2009-06-16 15:22:33 +00:00
Matt Johnston
d6441f4397 - Make -i and -W pass through multihop arguments
--HG--
extra : convert_revision : 70c64073c9ec07b4dfb54ee60e39cec2bd8c6910
2009-06-12 14:58:43 +00:00
Matt Johnston
08893f03a5 - Don't memcpy() in place with void_encrypt
--HG--
extra : convert_revision : d123343d78df1b5998d8dd2674fd83fd682ce0c0
2009-06-09 13:18:52 +00:00
Matt Johnston
4be3826dd5 Wrap proxycmd function in ENABLE_CLI_PROXYCMD #ifdef
(commit the right file this time)

--HG--
extra : convert_revision : d86e846566d01b739b51fa2ecdb8f62006e38dbd
2009-06-08 14:53:29 +00:00
Matt Johnston
a21cf67a6c disapproval of revision '6d6160b277bfc7c2db6888a2ac91ac618cef6de3'
--HG--
extra : convert_revision : 64088637337d7b6024a9b48b9a616eecf8621cf6
2009-06-08 14:51:22 +00:00
Matt Johnston
fe03c39241 Wrap proxycmd function in ENABLE_CLI_PROXYCMD #ifdef
--HG--
extra : convert_revision : 6d6160b277bfc7c2db6888a2ac91ac618cef6de3
2009-06-08 14:44:23 +00:00
Matt Johnston
6e78eca7c8 use memset() rather than bzero()
--HG--
extra : convert_revision : d44b31a46d0fdfcc92bf4f16e7c49fd49eb40aa1
2009-06-08 14:40:29 +00:00
Matt Johnston
5d3dae1492 merge of '0a8dfaa3e5365a2004db2b55895e11f65b5cefcc'
and 'ef3b41f37e9f4dd45358bc40f9559ee23f71c284'

--HG--
extra : convert_revision : 36f4aee4c1a6a38c7904e2482102d8555ff45fa0
2009-03-17 22:30:39 +00:00
Matt Johnston
061565865c - Add the signal pipe to maxfd
--HG--
extra : convert_revision : 0a8dfaa3e5365a2004db2b55895e11f65b5cefcc
2009-03-17 22:30:25 +00:00
Matt Johnston
b639e18d39 - Turn DROPBEAR_SMALL_CODE off by default
--HG--
extra : convert_revision : ef3b41f37e9f4dd45358bc40f9559ee23f71c284
2009-03-03 13:42:54 +00:00
Matt Johnston
2b54d3397c Remove extraneous debugging
--HG--
extra : convert_revision : 58d53a027555e98d6d274b4659d38211eea7ad11
2009-03-03 13:20:00 +00:00
Matt Johnston
ff763e4005 - Get rid of decryptreadbuf, just decrypt in-place with readbuf
- Share make_mac function for both packet creation and validation
- Split recv/trans parts of key_context into their own structures

--HG--
extra : convert_revision : 043bc598c76ed43625987e6937e32238f7ed6240
2009-03-01 16:15:57 +00:00
Matt Johnston
8e72bbaa9d Encrypt in-place, avoid an extra malloc
--HG--
extra : convert_revision : 981e3e4b44e6fdc8537775518e898a33e76a38db
2009-03-01 14:38:25 +00:00
Matt Johnston
4b37932ba1 merge of 'e1c100e6366c5d607af08f4abdbb0f4281df4fa9'
and 'fe8161b0698c9816b98f79e3cab2b9d59f2be71b'

--HG--
extra : convert_revision : 23e1a99e40fc3baad5216b2a7e7318f8243f86a3
2009-02-26 13:21:14 +00:00
Matt Johnston
d1bfb6bfb7 disapproval of revision 'a101cbd046507cf723e6362a49196dbd4b924042'
--HG--
extra : convert_revision : e1c100e6366c5d607af08f4abdbb0f4281df4fa9
2009-02-26 13:20:53 +00:00
Matt Johnston
35f3d2ff90 merge of 'a101cbd046507cf723e6362a49196dbd4b924042'
and 'c8e1b84cfe874887ad7df0dd95a00de46dbc0136'

--HG--
extra : convert_revision : fe8161b0698c9816b98f79e3cab2b9d59f2be71b
2009-02-26 12:18:34 +00:00
Matt Johnston
a60cb7dbaa - Try to write out as much as we can
--HG--
extra : convert_revision : a101cbd046507cf723e6362a49196dbd4b924042
2009-02-26 12:18:11 +00:00
Matt Johnston
cca4e1a080 - Don't be dumb and encrypt/decrypt in a while() loop - why did I do this??
--HG--
extra : convert_revision : c8e1b84cfe874887ad7df0dd95a00de46dbc0136
2009-02-25 14:04:02 +00:00
Matt Johnston
c04cc62ebf - Allow building with neither server nor client specified
--HG--
extra : convert_revision : d9a8b717bf65021efa4c61c34faf24d050d95da4
2008-11-18 12:53:39 +00:00
Matt Johnston
8158e952b9 - Use the right variable notation
--HG--
extra : convert_revision : 8d1eddd800cc6c405f2b3eaad148433c0d6bc0c8
2008-11-18 12:53:02 +00:00
Matt Johnston
b717efb577 Only use -lcrypt for Dropbear server binary
--HG--
extra : convert_revision : 7d3d93a5f58d60933277ab6f2595d662e5fb1815
2008-11-17 14:04:14 +00:00
Matt Johnston
3dbc707820 - Add a date for the release
--HG--
extra : convert_revision : f2c4b1b1304914efad934b368d3f6e4e8d91de99
2008-11-12 13:13:00 +00:00
Matt Johnston
5a2dde814d PAM shouldn't be on by default
--HG--
extra : convert_revision : 44714b1a34bf7833e6f2e4fd1c81ceaacccb15bd
2008-11-11 14:15:54 +00:00
Matt Johnston
4fc5a52850 - Bump to 0.52
- Clarify that hosts are resolved on the remote end for multihop

--HG--
extra : convert_revision : acde944b3ea0b8f673c276d2921c6bb3ede8ddde
2008-11-11 14:08:48 +00:00
Matt Johnston
d005aa139e - Document idle_timeout
--HG--
extra : convert_revision : da3bab4cab817b6a9ecede779e0524c38c9fb760
2008-11-11 13:51:55 +00:00
Matt Johnston
5efdd391eb Mention DSS and DSA being the same thing
--HG--
extra : convert_revision : 562d196de58e606c7a95671e9e7b3d1cc0f9752d
2008-11-09 10:59:19 +00:00
Matt Johnston
adc4d0194f Idle timeout patch from Farrell Aultman. Needs testing, unsure if server
code works

--HG--
extra : convert_revision : ff66e05ae040561110af70114bf83f11ed528f05
2008-11-07 14:11:06 +00:00
Matt Johnston
1912439526 Update nocrypto branch to current head
--HG--
branch : insecure-nocrypto
extra : convert_revision : 9e5e6e33be005d27cd5b3270c574edc45b5c2893
2008-11-06 13:33:06 +00:00
Matt Johnston
800810a181 propagate from branch 'au.asn.ucc.matt.dropbear' (head cdcc3c729e29544e8b98a408e2dc60e4483dfd2a)
to branch 'au.asn.ucc.matt.dropbear.insecure-nocrypto' (head 0ca38a1cf349f7426ac9de34ebe4c3e3735effab)

--HG--
branch : insecure-nocrypto
extra : convert_revision : dbb093e087a68abf2e54ab0b711af70771ddb29d
2008-11-06 13:16:55 +00:00
Matt Johnston
e80f8e8c09 - Update manuals, include section on authorized_keys
- Change default PATH to /usr/bin:/bin
- Mention DEBUG_TRACE in -v help text

--HG--
extra : convert_revision : cdcc3c729e29544e8b98a408e2dc60e4483dfd2a
2008-11-05 14:14:40 +00:00
Matt Johnston
1fdfa2ecfd LICENSE - Update copyright to 2008
cli-runopts.c - mention that -v is for DEBUG_TRACE, add multihop syntax
dbclient.1 - document some new features

--HG--
extra : convert_revision : 04ca01e638904920e0e16fea06b55c52a9b9b81d
2008-11-05 13:53:14 +00:00
Matt Johnston
51dcfc06dc - Set a default path, since bash won't export one otherwise (though it will set
one, leading to mysterious problems)
- Rearrange some options

--HG--
extra : convert_revision : 6e81becf6e96479e10d9244186a900fab7079bf8
2008-11-05 13:30:23 +00:00
Matt Johnston
8edc0c2afc Give a umask argument to open() in loginrec
--HG--
extra : convert_revision : e8ae11ccf89b916d47ff09fce1d7b2ccb966607e
2008-11-05 13:14:38 +00:00
Matt Johnston
ebc3a3ac74 - use vfork()/_exit() for uclinux
--HG--
extra : convert_revision : 1f9658a860290e6664fa9db84b9bb5b8673a1b1f
2008-11-02 13:34:02 +00:00
Matt Johnston
5cd6995fb5 Report errors if a remote request fails
--HG--
extra : convert_revision : ed1584aacf189b8f8ddee813b98342fa8bb38022
2008-11-02 12:25:08 +00:00
Matt Johnston
ed79abed76 Don't use // style comments
--HG--
extra : convert_revision : c92c7b4fef739b505d9842b45a393e1089097e3b
2008-11-02 12:01:39 +00:00
Matt Johnston
c2bd79131a - Get rid of blowfish and twofish CTR since they weren't likely
to be that useful

--HG--
extra : convert_revision : e16bd265bb6e8093b3488993dffc86662a2a7a62
2008-09-29 14:30:47 +00:00
Matt Johnston
511f6555c9 - Add Counter Mode support
--HG--
extra : convert_revision : 5225162bdf32d70b58b6d3ae375a290326c59f3a
2008-09-29 13:53:31 +00:00
Matt Johnston
049fcf1ac5 Add support for zlib@openssh.com delayed compression.
Are still advertising 'zlib' for the server, need to allow
delayed-only as an option

--HG--
extra : convert_revision : 319df675cc3c9b35a10b7d8357c94f33fdab1a46
2008-09-29 02:23:04 +00:00
Matt Johnston
e674c73ee6 propagate from branch 'au.asn.ucc.matt.dropbear' (head 4fb35083f0f46ea667e7043e7d4314aecd3df46c)
to branch 'au.asn.ucc.matt.dropbear.cli-agent' (head 833d0adef6cdbf43ea75283524c665e70b0ee1ee)

--HG--
branch : agent-client
extra : convert_revision : 6bbab8364de17bd9ecb1dee5ffb796e48c0380d2
2008-09-23 16:05:04 +00:00
Matt Johnston
90f8c1fd51 Split options.h out into sysoptions.h for options that aren't usually
user-changed

--HG--
extra : convert_revision : 4fb35083f0f46ea667e7043e7d4314aecd3df46c
2008-09-23 16:02:51 +00:00
Matt Johnston
729aa017d3 merge of '6fd2597077a4e2421bf45388e058d15606f6dd74'
and 'c7b916e6c522f16f06fe1bd52815ba13aa88b90b'

--HG--
extra : convert_revision : dd53ba272725a189d596cf96532ea165c847265c
2008-09-23 15:57:32 +00:00
Matt Johnston
efe45cddbe - Enable -s for specifying a subsystem (such as sftp)
--HG--
extra : convert_revision : c7b916e6c522f16f06fe1bd52815ba13aa88b90b
2008-09-23 15:57:26 +00:00
Matt Johnston
6fe6393acb propagate from branch 'au.asn.ucc.matt.dropbear.pubkey-options' (head 537a6ebebb46424b967ffe787f0f8560e5f447e8)
to branch 'au.asn.ucc.matt.dropbear' (head 10b2f286b9886364db39dfbb4f8f46e49e345d87)

--HG--
extra : convert_revision : 6fd2597077a4e2421bf45388e058d15606f6dd74
2008-09-23 13:16:22 +00:00
Matt Johnston
b98d13effb Don't send anything in response to a SSH_MSG_CHANNEL_REQUEST if we have
already sent a SSH_MSG_CHANNEL_CLOSE. This fixes a bug triggered by more
recent versions of putty with tcp fowarding and window adjustment request
messages.

--HG--
extra : convert_revision : 10b2f286b9886364db39dfbb4f8f46e49e345d87
2008-09-23 12:03:01 +00:00
Matt Johnston
299d26dab7 - Work around rsync and scp parsing and modifying the user@host argument,
which break's dbclient's multihop syntax

--HG--
extra : convert_revision : cf704125a4785278aeb79f62bf025638e1b28e4c
2008-09-22 15:47:35 +00:00
Matt Johnston
643626d546 Replace calls to strtoul() with a helper m_str_to_uint()
--HG--
extra : convert_revision : 1f8643c5ba7fe789c120b503c396281ac45f9730
2008-09-22 14:13:44 +00:00
Matt Johnston
e1a8bf0240 Remove an unused variable
--HG--
extra : convert_revision : 63f95bd7b4b15b61cd13cdcc86cdeef2681ce6e7
2008-09-22 14:13:14 +00:00
Matt Johnston
d54f38caf2 - Improve DNS failure message to include lookup host
--HG--
extra : convert_revision : c0555e457f4da6b618b87f2cf4bf5c4c4d0f9e28
2008-09-18 16:34:18 +00:00
Matt Johnston
d981ff2c8d - Allow specifying a port with host/port.
- Rearrange multihop hostname parsing

--HG--
extra : convert_revision : 0594a6cbca9edc235c325e02dc927060c4324741
2008-09-18 16:01:59 +00:00
Matt Johnston
bece6ddcc2 Print "Login for user@host" for keyboard interactive, since it probably
isn't clear from the remote host's prompt

--HG--
extra : convert_revision : cabaf758875b341354e57def5bad3581a7da56e3
2008-09-18 16:01:02 +00:00
Matt Johnston
f4aacaa74c Add multihop 'onion-forwarding' mode. Needs refinement, works.
--HG--
extra : convert_revision : 877947ce24297781438a75e7e9c64ba86f0dce93
2008-09-18 14:47:02 +00:00
Matt Johnston
66e2f59c7b propagate from branch 'au.asn.ucc.matt.dropbear.dbclient-netcat-alike' (head b02ba6628cf2095017c60d202ac630f231e6b553)
to branch 'au.asn.ucc.matt.dropbear' (head 636506b73e973b004cc058b07e6f36a25ff902f8)

--HG--
extra : convert_revision : eb8e95a8227df7802d79007d4dd89098759fa76b
2008-09-17 14:49:12 +00:00
Matt Johnston
af00c78e21 Rework netcat-alike to be a proper mode, with -B argument.
--HG--
branch : dbclient-netcat-alike
extra : convert_revision : b02ba6628cf2095017c60d202ac630f231e6b553
2008-09-17 14:36:49 +00:00
Matt Johnston
c7bd9ccd85 Don't capture stderr from spawned processes in proxycommand mode
--HG--
extra : convert_revision : 636506b73e973b004cc058b07e6f36a25ff902f8
2008-09-17 14:35:36 +00:00
Matt Johnston
e44aa503f0 - "-J 'nc localhost 22'" kind of works, needs fixing hostkeys, ptys etc.
--HG--
extra : convert_revision : 45069dd007ebf414330e0a7abf4fb7e0727049c3
2008-09-15 14:40:30 +00:00
Matt Johnston
12929e8cf0 - Add run_shell_command() function to run a "sh -c" command, handling
lots of the work that exechild did (and can be shared by client -J option)

--HG--
extra : convert_revision : a15dfd8017af8212b3b227f18ce2539dd471f7f6
2008-09-15 14:04:55 +00:00
Matt Johnston
7ac24b10b9 - Generalise spawn_command function
--HG--
extra : convert_revision : 9927a5fe084c8053c747a40515f0213141ef8139
2008-09-15 13:41:18 +00:00
Matt Johnston
d7c1e58217 - Get rid of some ugly #defines
--HG--
extra : convert_revision : 4cfa02494ded17cdb068ec66581b720a5a0fd70b
2008-09-15 13:06:40 +00:00
Matt Johnston
b619e88f54 - Split main socket var into ses.sock_in/ses.sock_out in preparation
for -J proxy_cmd option (and some prelim options for that)

--HG--
extra : convert_revision : 47cdea9a7d66c553c6f5eec43b899821939d4e4c
2008-09-15 12:51:50 +00:00
Matt Johnston
1c72a35ddb propagate from branch 'au.asn.ucc.matt.dropbear' (head f21045c791002d81fc6b8dde6537ea481e513eb2)
to branch 'au.asn.ucc.matt.dropbear.dbclient-netcat-alike' (head d1f69334581dc4c35f9ca16aa5355074c9dd315d)

--HG--
branch : dbclient-netcat-alike
extra : convert_revision : 22bbe895accc3995b48f07b556e45d546ff1ce5d
2008-09-14 06:47:51 +00:00
Matt Johnston
460bf43822 Remove workaround forcing rsa mpint to exactly a 8 bits multiple for putty (see
http://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/rsa-non8mult-verify-fail.html ,
was fixed in 2004)

--HG--
extra : convert_revision : f21045c791002d81fc6b8dde6537ea481e513eb2
2008-09-12 17:48:33 +00:00
Matt Johnston
31fa5e605b - Rework pubkey options to be more careful about buffer lengths. Needs review.
--HG--
branch : pubkey-options
extra : convert_revision : 537a6ebebb46424b967ffe787f0f8560e5f447e8
2008-09-12 17:23:56 +00:00
Matt Johnston
c0ce2a6a97 * Patch from Frédéric Moulins adding options to authorized_keys.
Needs review.

--HG--
branch : pubkey-options
extra : convert_revision : 26872f944d79ddacff1070aab32115a6d726392c
2008-09-08 15:14:02 +00:00
Matt Johnston
f90f64b5c1 fill_passwd() doesn't have a return value
--HG--
extra : convert_revision : ee6ec7346a5b4e7330f462ec9e4815f73038e8d0
2008-07-12 17:00:30 +00:00
Matt Johnston
96bda2af8e Forgot to bump actual version number
--HG--
extra : convert_revision : 2f31bc0e5d1c701ad8c03176bbb5722852c0c11d
2008-03-27 13:34:34 +00:00
Matt Johnston
a97603d003 Add SSH_ASKPASS and DROPBEAR_PASSWORD to the dbclient manpage
--HG--
extra : convert_revision : ecc0009ef2a41ba548230efd0fbb1ea74e973f1b
2008-03-27 13:25:02 +00:00
Matt Johnston
77892be79c 0.51
--HG--
extra : convert_revision : 52beef2562914a31aa2351bcd0e1178fbf2be718
2008-03-27 13:17:08 +00:00
Matt Johnston
3e29368cbc merge of '9879f7138f243bb2077a06e4c9ea925fa34abe2b'
and 'e28650f207028a45182fc2de545b7bd218d13077'

--HG--
extra : convert_revision : f6be8d819a89338780799d813f64be24d4b8ad84
2008-03-27 10:19:36 +00:00
Matt Johnston
b91874cedc Update to debian 0.50-4 diff
--HG--
extra : convert_revision : e28650f207028a45182fc2de545b7bd218d13077
2008-03-27 10:19:28 +00:00
Matt Johnston
acd18ce243 Mention 0.51-test2 changes
--HG--
extra : convert_revision : 9879f7138f243bb2077a06e4c9ea925fa34abe2b
2008-03-01 02:01:35 +00:00
Matt Johnston
6c9d2abc75 Don't return until the shell has quit. This will ensure that an exit status
is always returned.

--HG--
extra : convert_revision : 32fc88053016994100eb0ef17f75592881c90d97
2008-02-21 14:46:15 +00:00
Matt Johnston
e277059339 fix up after merge
--HG--
extra : convert_revision : 6107b89c1188975d0c60f50621afe593cb6e554f
2008-01-13 04:02:08 +00:00
Matt Johnston
a3b5d3c8b3 merge of '295b11312e327fe6c4f33512674ea4a1a9790344'
and '426d7aeea950d007ed7ef9f03f9f40b138a769cb'

--HG--
extra : convert_revision : d9cc9067a1a17f312a7349781f2dbbaf2890d5a6
2008-01-13 04:01:46 +00:00
Matt Johnston
bb0548b3b0 Make a copy of passwd fields since getpwnam()'s retval isn't safe to keep
--HG--
extra : convert_revision : 295b11312e327fe6c4f33512674ea4a1a9790344
2008-01-13 03:55:59 +00:00
Matt Johnston
bb84e33d99 propagate from branch 'au.asn.ucc.matt.dropbear' (head fb7080ca6e254faaf7cfaee93b0ab6ab6de4ed59)
to branch 'au.asn.ucc.matt.dropbear.cli-agent' (head 78d02301ae8310efa2639f15da0ea62dea110e4b)

--HG--
branch : agent-client
extra : convert_revision : 833d0adef6cdbf43ea75283524c665e70b0ee1ee
2007-11-29 11:38:06 +00:00
Matt Johnston
b2ac4eb29b Actually use ~/.hushlogin rather than ~/hushlogin to ignore motd.
--HG--
extra : convert_revision : 426d7aeea950d007ed7ef9f03f9f40b138a769cb
2007-11-02 15:03:16 +00:00
Matt Johnston
25554bc331 Fix to allow building from a separate directory, patch from Ricardo Martins
--HG--
extra : convert_revision : fb7080ca6e254faaf7cfaee93b0ab6ab6de4ed59
2007-10-18 12:18:44 +00:00
Matt Johnston
a018260fe9 Add support for SSH_ASKPASS_ALWAYS env variable for dbclient. If it
(and also SSH_ASKPASS) is set then dbclient will use an external askpass
program regardless of whether DISPLAY is set or stdin is a TTY. Suggested
by Davyd Madeley for handheld devices.

--HG--
extra : convert_revision : c62bdee8427eb452cca38d188affe881d9fadee8
2007-09-14 00:19:44 +00:00
Matt Johnston
9a2cdc299f Make sure declarations of variables are at the top of function,
pointed out by Alexey Rusakov.

--HG--
extra : convert_revision : 6c4d376f9c88f94c3c9b23e32f9135c132e26fa8
2007-09-11 12:00:18 +00:00
Matt Johnston
e41452afeb propagate from branch 'au.asn.ucc.matt.dropbear' (head 8a7db1e2fdc5636abb338adb636babc32f465739)
to branch 'au.asn.ucc.matt.dropbear.cli-agent' (head d82c25da2f7e4fb6da510d806c64344e80bb270d)

--HG--
branch : agent-client
extra : convert_revision : 78d02301ae8310efa2639f15da0ea62dea110e4b
2007-08-16 13:34:37 +00:00
Matt Johnston
58296a95f1 Make dropbearkey only generate 1024 bit keys
--HG--
extra : convert_revision : 8a7db1e2fdc5636abb338adb636babc32f465739
2007-08-08 15:57:50 +00:00
Matt Johnston
ddb61adcc9 Fix delayed packet queue handling
--HG--
extra : convert_revision : 53b349938dfae2256e23799fae66edd5fc3e97ee
2007-08-08 15:48:52 +00:00
Matt Johnston
790cdadace Prepare for 0.50 release
--HG--
extra : convert_revision : 72385623360b49c08f42496eb163fc702c8a0b3e
2007-08-08 15:27:41 +00:00
Matt Johnston
75ec4d6510 - Add -K keepalive flag for dropbear and dbclient
- Try to reduce the frequency of select() timeouts
- Add a max receive window size of 1MB

--HG--
extra : convert_revision : 9aa22036cb511cddb35fbc0e09ad05acb39b64d1
2007-08-08 15:12:06 +00:00
Matt Johnston
a7649c250f Stop scp passing arguments that dbclient doesn't understand
--HG--
extra : convert_revision : 8b1f7f73b80da98007864ca665f99c58d6f88382
2007-07-28 08:59:24 +00:00
Matt Johnston
57ae0bfedf Prevent invalid packets being sent during key-exchange, instead queue
them until afterwards. This could sometimes terminate connections
after 8 hours if (for example) a new TCP forwarded connection
was sent at the KEX timeout.

--HG--
extra : convert_revision : 48426bd66b8f5ba50045f7ba190d1672745132e2
2007-07-27 17:13:42 +00:00
Matt Johnston
993f58900d Add default argument for receive window
--HG--
extra : convert_revision : 83535bcee65d8f58becbb75153cf0063c57a48dc
2007-07-25 16:20:57 +00:00
Matt Johnston
876e7b99d4 Use the -W <windowsize> argument in startup scripts, with a default of 64kB
--HG--
extra : convert_revision : bbc5073267b8af362e59a46bc8328c03cfd4bd4c
2007-07-25 15:44:50 +00:00
Matt Johnston
e3e4445dc1 Add -W <windowsize> argument and document it.
--HG--
extra : convert_revision : 98d4c0f15480bf749c451034cbc565d7e9d3b8dc
2007-07-25 15:44:25 +00:00
Matt Johnston
2d4d9627a2 Rearrange the channel buffer sizes into three neat use-editable values in
options.h. Increasing RECV_MAX_WINDOW gives big network performance
increases - even with the present buffers (which haven't changed) it
performs a lot better.
Next step is to make the window size a cmdline option.

--HG--
extra : convert_revision : 24c7cb47fb56cf5b82e3bc0859b45ea83038eab0
2007-07-24 15:40:23 +00:00
Matt Johnston
762e9973ff Patch from Nicolai Ehemann to try binding before going to the background,
so that if it exits early (because something's already listening etc)
then it will return an exitcode of 1.

--HG--
extra : convert_revision : 4e68851f89a773bc502b30dec2b8f6edaa36d473
2007-07-19 15:54:18 +00:00
Matt Johnston
b04e2d14ef Just use /dev/urandom since that's what everyone ends up using anyway.
Make -u a nop.

--HG--
extra : convert_revision : ef0615311b43c8bfe1985df64a4a95ce4ec0d8e6
2007-07-19 15:47:32 +00:00
Matt Johnston
456b500902 "backgrounding" is more user-understandable than "forking"
--HG--
extra : convert_revision : 53a3f244adf908dac18f2fa7e1d94309497da790
2007-07-19 14:08:24 +00:00
Matt Johnston
0b72cf1ed2 uClinux ifdef was accidentally inverted
--HG--
extra : convert_revision : 0b32300bc2ad5a96be40f0e2b9815a8824c2c729
2007-07-19 14:08:01 +00:00
Matt Johnston
4639844208 Fix spelling typo
--HG--
extra : convert_revision : 3080d6d5d0bf6772752e5fd8e28657817b41c748
2007-07-19 14:07:41 +00:00
Matt Johnston
77c33e7750 Add -u option to specify /dev/urandom instead
--HG--
extra : convert_revision : 6925cd3fd7727fbc69db9883675aa90f594f58a0
2007-04-16 13:39:50 +00:00
Matt Johnston
a4130263bd Allow reading dbclient password from an environment var
--HG--
extra : convert_revision : 9a5277c058af96e8fb7a3ade558dd1aeeafa1d3a
2007-03-17 06:30:11 +00:00
Matt Johnston
0ffc17e481 Remove a newline from the kex prompt question, from FreeWRT
--HG--
extra : convert_revision : 98745fb712b04634b0682fe9ee0dc904ea528f10
2007-02-25 09:48:13 +00:00
Matt Johnston
3301bad391 Comment cleanups
--HG--
branch : insecure-nocrypto
extra : convert_revision : 0ca38a1cf349f7426ac9de34ebe4c3e3735effab
2006-10-02 06:40:51 +00:00
Matt Johnston
f5d75b099b explicit merge of '0501e6f661b5415eb76f3b312d183c3adfbfb712'
and '2b954d406290e6a2be8eb4a262d3675ac95ac544'

--HG--
branch : insecure-nocrypto
extra : convert_revision : 9bd1d83f67b428efb0f0e8f55c6efc4749f635d9
2006-10-02 06:39:32 +00:00
Matt Johnston
1e26b86f15 propagate from branch 'au.asn.ucc.matt.dropbear' (head 138a11bc1e2babcd8b1182e6cb2a85d4e9404b11)
to branch 'au.asn.ucc.matt.dropbear.cli-agent' (head 12b2f59db65e7339d340e95ac67d6d9ddb193c2b)

--HG--
branch : agent-client
extra : convert_revision : d82c25da2f7e4fb6da510d806c64344e80bb270d
2006-06-06 15:40:09 +00:00
Matt Johnston
f7caf6f5c6 propagate from branch 'au.asn.ucc.matt.dropbear' (head 0501e6f661b5415eb76f3b312d183c3adfbfb712)
to branch 'au.asn.ucc.matt.dropbear.cli-agent' (head 01038174ec27245b51bd43a66c01ad930880f67b)

--HG--
branch : agent-client
extra : convert_revision : 12b2f59db65e7339d340e95ac67d6d9ddb193c2b
2006-03-21 16:20:59 +00:00
Matt Johnston
cdbe853595 A hack to make dbclient to tcp forwarding netcat style.
eg

./dbclient -i testkey -L 1234:remotehost:remoteport  tunnelhost

will ssh to tunnelhost (using testkey, there's no way to ask for a password)
and then tcpfwd to remotehost:remoteport on stdin/stdout.

There's no way to give a cmdline password, so -i for a keyfile will have to do.
Yet another reason for agent forwarding.

The 1234 is a dummy var, I think it has to be a valid portnumber though.

--HG--
branch : dbclient-netcat-alike
extra : convert_revision : d1f69334581dc4c35f9ca16aa5355074c9dd315d
2006-03-21 16:16:41 +00:00
Matt Johnston
ba869e5601 propagate from branch 'au.asn.ucc.matt.dropbear' (head 7ad1775ed65e75dbece27fe6b65bf1a234db386a)
to branch 'au.asn.ucc.matt.dropbear.insecure-nocrypto' (head 88ed2b94d9bfec9a4f661caf592ed01da5eb3b6a)

--HG--
branch : insecure-nocrypto
extra : convert_revision : 2b954d406290e6a2be8eb4a262d3675ac95ac544
2006-03-10 06:30:52 +00:00
Matt Johnston
1632bd4a18 - a hack for grahame to run dropbear with "none" cipher.
DO NOT USE IF YOU DON'T KNOW THE CONSEQUENCES
  Here is your noose. Use it wisely.

--HG--
branch : insecure-nocrypto
extra : convert_revision : 88ed2b94d9bfec9a4f661caf592ed01da5eb3b6a
2005-09-23 16:29:19 +00:00
Matt Johnston
e444f0cfe6 - progress towards client agent forwarding
(incomplete and does not compile)

--HG--
branch : agent-client
extra : convert_revision : 01038174ec27245b51bd43a66c01ad930880f67b
2005-07-18 14:32:52 +00:00
168 changed files with 13726 additions and 5142 deletions

22
.hgsigs Normal file
View File

@@ -0,0 +1,22 @@
aa2f51a6b81d33de5e9898a7f27c792a173d9b26 0 iD8DBQBOuADmjPn4sExkf7wRAv/fAJ9FJFvjDoF+wd1ipDx1wkzdeBQNqgCgykUrSbXv76FBbxKntVbk9oS3GjI=
3f12086c2ef2b9ffe36a822fdb3ff647fcec1831 0 iD8DBQBOuSlQjPn4sExkf7wRAvkbAKCgE1e8xEMQ16CGeoywhIQ0QR4eNgCfZdYYlzjb/+521Uvh5/7FRYEmrho=
85f835f2fe0ac2c503c50a414de127222fb0a57c 0 iD8DBQBPRkMUjPn4sExkf7wRAvM4AJ9mw2OAkyjhSbamM1MizlEJUX18HACgoFKQkYf6BnYxN34Nv2HhM0cmzUc=
9b80981212fe6c01b7c16b3ca7c4e66af56f12f1 0 iEYEABECAAYFAlFLKKcACgkQjPn4sExkf7xK7wCfcioCmJPsysSbQO6+4qZMVe0mmLwAn2/o+wRf4MrUXlohrr7aXEF9vdSB
095b46180bbc412b029420587736a6185afc17e1 0 iEYEABECAAYFAlFsCnkACgkQjPn4sExkf7xLrwCfeMWjUaSmfU/fvseT5TdrYRqBEVQAoLz5SFLEA40C5f8zE8Ma/vgVJVIC
f168962bab857ca030829e4cd73d9b32c868c874 0 iEYEABECAAYFAlFwDNwACgkQjPn4sExkf7wJ6QCePVovn/avKXUyNwNBYCcov6JLYqkAnRCPQdkXgv20N3t10r6PRMBBo1/S
deb211f75ca194e2fcf0d2e5f71c60474e42ec95 0 iEYEABECAAYFAlJO01cACgkQjPn4sExkf7yDqACaA/P+Yl/K2Cv3OC5G0b7ck2Kb75EAoIeW7qpCyclzJLWwk95koED+4lxD
025237c9f0a1a60a616f984d82fb2a9270d3b0ea 0 iEYEABECAAYFAlJeqDYACgkQjPn4sExkf7y5nQCfW6t+TJySBTTo+gCfDUBPRVxvNe8AoIn/15aWfqH/A2G9uikfoVtWK3pd
a50a1dc743317fad9b3737bc68fbca640659bb6d 0 iEYEABECAAYFAlJeqL0ACgkQjPn4sExkf7yVqACg6IP0fU29+Feh/TDeemDA+2XAzrIAoIdZfMDvVYlDoWotZD8ACFnf5H1P
9ec083a21adfcb099f21eb03704b66d14a4ba800 0 iEYEABECAAYFAlKE4JoACgkQjPn4sExkf7wLDgCghkVGwMjI138bEv+ORVzN7zIH7cEAoLckaxZc1k1aXlmlSCRlP8cuKH3o
3d1d7d151c0ce3a79da62e86463f5632fa2b144a 0 iEYEABECAAYFAlKd5AEACgkQjPn4sExkf7wzWgCfdvPEEIdlMPqcbOQMJ7b+eAyy164An2ip1lPh1eS5g26/gSfruvWBVym4
277429102f1337bd10c89107d3e01de509cc1a7e 0 iEYEABECAAYFAlMEvF4ACgkQjPn4sExkf7xeVQCgtbxJ4G3hsFwUOM0K1WGr1J2vsbEAoMM8dEyr1mdrbgO1tzNLfD1nxbyn
96584b934d04ebab443f603e78d38fe692d36313 0 iEYEABECAAYFAlPVFrQACgkQjPn4sExkf7xr6ACglRiLE21vRrS1rJ809o2yMADIKtwAn1f5SyZUngSde8eE55JxCMwtMC5m
caac692b366c153cea0e9cd59aa2d79a7d843d4e 0 iEYEABECAAYFAlPk1mcACgkQjPn4sExkf7wLpgCeOqMYqpkf4lYUuyrn9VYThNpc7PkAn3JOSNgIqkKUcmSy6FstrI8jwJzq
2d421bc0545d1be6d59a4ebfe61606d94b124b0c 0 iEYEABECAAYFAlRJDCQACgkQjPn4sExkf7xUYACcCwVJkYWXJn5x/D5A+qMupy778lEAn0rg1oNiq96YU/4jOPsS5IMItihu
1d2d81b1b7c1b100e9c369e40b9fa5b2d491eea9 0 iEYEABECAAYFAlTKOKUACgkQjPn4sExkf7xWMACfYFozyHiRk5GaocTa5z6Ws1uyB4kAoLubxoxcnM3E7AA9mHAzc3OB5M0Y
a687f835236c7025b5cb2968fe9c4ebc4a49f0ea 0 iQIcBAABCgAGBQJVxg62AAoJEPSYMBLCC7qsC+EQAKw8YWogrVHhIFct2fx/nqybSPVrhFyKFKHhq7K/lZeVm0MGIWdSyVcQgP+Hs2jWNBWzG4AJ1BtifHWQH6IDh7W5RuwOXu5KobgPW9BsN3EVE9KIR+xe9jCAmFl9rIw0tNpy1q6R0TpYXx/sWlMilxecyEGyr2Ias2Sm19aY2mOEv8PLfh9BLfrJEKtt2NxL7TX8ScPwJXJMmVIQjN9WK4Ptx3tjcGNRivEVR/dftP5sJx2DBJx9avyDqrfloMW7Q7sPgJ88MPruCDxedOkbzH7JdHe3Humr2G4LsI0KPU7pNN6EBDjhJ+SVXuOyAgu5j/C0R+0ggGfjSrjDu8WjHyclFlwwu2MSGuHf111I1qkLtaRY3H1FZO5Y2gbLwBLQ82svA4klcBIxtP5jKAZDTh1jQMYsfKotvZdawOWrPDkNmKoUg2JXLHAtj9Dd0uGIhqfspZY3qlpzxw9uCkljWclUBD097ygotwAb2XdLoAWZ3KdvoPM+k448vIAQ7Q/aqcnm/dLQJr3Le029gpkOKoWKaQTlk0itrRGpgETHAhE2LnmWxYSKp6NYSKMgEONbfDiVNLyDTOlvpPiEb20RsOP64xA4wVDGmPenCURmMYoepQK6oJdtkNtCdth2S49KxPQAC+Dem4YZ7b+5b+cXrK5Nz7elBxZzRQWdjmZ4JDQK
ef4b26364b0cdda1084751d7de3d76c589e2d9cb 0 iQIcBAABCgAGBQJVxg7BAAoJEESTFJTynGdz9Q4P/A0Kq4H52rQqxq42PoEMFbVQIUfkFzyWjAz8eEGLmP5x5/sdpyxZDEyBSUG55uyNvOPTHE+Sd3t2h2Iieq749qwYgqggXC0P+C0zGzW3hB5Rv6dTUrKN1yCyaWE2tY488RsyVlcAs4vrp1Cum5Gv8/BUVKjzZmkZ1iq/3RyrvbLEiLoMrcLnQ+sUdaYHvfEwxDbzpOEvepg8iDJBitTrfG9xHp9otX6ucahwn1EumFvC5mvUxbiQ9jv76t4FJztjMoB24hPCH9T1FjB8uNsoM+j2Z67r81eJrGgNpJzjX0S3lY/AADZGhfGnfybTM9gFuQayIJuCJqduQibVwYkAAnPi17NmbdwPu0Rdz55oU+ft09XLVm/qkQcD1EP5bxYWnLIEMkkZQnFx7WdMpjKK9oGxZHeFYAKEgPgePCkk4TQ4PxNa+3854H19AUssQlaueGcbDLyPIRiSyqhleXawGfaJi+1jBt0DM7CNbAHAUWUE07VhQzNGWjabdEk4eXKTmDL+mZJFdHGBhyCve8sPmZBYJvM2PRgcXe8fwFh+R7gVj6kFbZJvgM9kG7EeF+4ZMEXG4yKpV/SKfMMeEPBCZjFxZhlJJ0fsZbB1Y/iLw8LXnJ0fa/5xFYv6k+iytfom/rqS4iUD7NWTjcEYHjd4EO4QlPD2Ef/AWOO8YBUBv8kA
af074dbcb68ff8670b3818e0d66d5dc6f1bd5877 0 iQIcBAABCgAGBQJWVdQfAAoJEPSYMBLCC7qs+n4P/RgZU3GsLFJN7v7Cn6NOdKdfjJBmlbCtK9KwlZZaj8fW4noqnLDcDd6a2xT4mDV3rCE6+QYialGXjNkkNCBwD9Z+gFc8spOtThrpQ54dgWzbgDlYB1y7Hp7DoWoJQIlU6Od9nWBemcSrAviOFNAX8+S6poRdEhrHgMcv2xJoqHjvT7X8gob0RnJcYxW5nLWzDaJV58QnX6QlXg4ClSB6IoCeEawdW6WzXlZ9MGsRycTtx1ool7Uo6Vo2xg48n9TaJqM/lbSsMAjHxO/fdTJMWzTId1fuZxJGFVeJbkhjSwlf7fkVXxrgDxjvIAmFDR8TSTfJo50CD82j5rPcd7KSEpQ12ImBUsntPDgOtt/mJZ3HcFds86OZ7NkPpqoJGVFFQ8yUpe//DNSB2Ovg1FrwhSKOq/9N61BBwk1INVFDp1hMq45PIa9gI9zW/99inGDeSSQlxa4iafEUEjXZTRYuX7mFjnWm5q7r134J7kyWQtN/jNUZ71F0mvhnemufgpNY/I/D7K6qkONpbDZ2nuzkhfoqugzhHYp467UePM0qmLTLdXGPPMukoGorpWeiSb2T25AEKm7N4A9NwPmdAnoFjAibjF9FAuU03sl+pu9MqFb+1ldsqjNfxhcJmoAUR5vy3pED9ailCb/OCBVTHkDPfTEhGU3waO9tPM+5x2rGB5fe
5bb5976e6902a0c9fba974a880c68c9487ee1e77 0 iQIcBAABCgAGBQJWVyIKAAoJEESTFJTynGdzQosP/0k5bVTerpUKZLjyNuMU8o0eyc7njkX8EyMOyGbtcArKpzO2opSBTRsuCT9Zsk1iiQ1GMTY1quKD7aNr86Hipqo4th/+ZXmLe9mmaCDukKjD0ZYC4dBVUy6RSUAMvdkDP9sZs7CMTO/22a9SqOsKTv3s2NN6XnsBGnmNbvVx5hkAk5hMVNFrjKIaexzI/7bWQIDRo2HQCaWaL06JvWEDSEQd2mynGSXxT/+m4hBnuGg6qxn2pd4XfG0g10tDAFx64HQkWgZqSB+F8z71Cvfjondy1zjJYgtABqNlwCKQJZhRUW2+PblqQnz08TUy83XN2vtisOju4avGcHSaBgBbMvg8Wx4ZtM7sPP9pLrhhOTd5ceERHeTceTJy+iI1SQFvccjrRfs5aJ0zAQX5q6f4bV0zp5SmxkvnZUEkZIoetkM8VrPOYugqx31LtHAWfVT9NM+VkV/rrxLhk6J0giIQvC9MPWxRDileFVDszPiOgTLcxWjOziOLT+xijcj7dtx1b/f2bNCduN5G7i+icjjTlCNtyRPRqhBqn705W7F+xESP2gsscM/1BjQ7TGidU5m1njdkUjbrqm3+Qic6iqkG7SfETHmQB9mHqpJ0hACRPvZlhwB7oimNHllkrlw8UJw9f0SiuLjfERIgVS2EOp+mAia0RU7MlTt19o017M1ffEYL
926e7275cef4f4f2a4251597ee4814748394824c 0 iQIcBAABCgAGBQJWYES4AAoJEESTFJTynGdzdT0P/0O/1frevtr698DwMe6kmJx35P6Bqq8szntMxYucv0HROTfr85JRcCCSvl/2SflDS215QmOxdvYLGLUWPJNz/gURCLpzsT88KLF68Y1tC72nl4Fj+LGIOlsWsvwEqQqw0v4iQkHIfcxI6q7g1r9Hfldf/ju4bzQ4HnKLxm6KNcLLoAsuehVpQ+njHpLmlLAGHU5a84B7xeXHFR+U/EBPxSdm637rNhmpLpkuK2Mym/Mzv7BThKDstpB8lhFHIwAVNqi3Cy4nGYxFZOJpooUN9pDornqAwuzHmOAMs9+49L8GZ1de5PBRGyFKibzjBIUWPEU9EIkfJVaVwTlqYK8Q/IRi9HjITPx6GpE8cZhdSvAibrQdb6BbIDrZ8eCvD9vnod6Uk0Jb9/ui6nCF9x+CN/3Qez4epV5+JCMYsqCiXFkVPm9Lab6L2eGZis7Q2TXImA/sSV+E4BGfH2urpkKlnuXTTtDp4XRG+lOISkIBXgjVY+uy8soVKNdx1gv+LeY8hu/oQ2NyOlaOeL47aSQ3who4Pk6pVRUOl6zfcKo9Vs6xDWm35A3Z6x/mrAENaXasB0JrfY5nIbefJUpbeSmi76fYldU98HdQNHPHCSeiKVYl7v/B6gi2JXp5xngLZz/5VVAurago7sRmpIp7G/AqU6LNE85IUzG8aQz8AfR0d1dW
fd1981f41c626a969f07b4823848deaefef3c8aa 0 iQIcBAABCgAGBQJW4W2TAAoJEESTFJTynGdzuOcP/j6tvB2WRwSj39KoJuRcRebFWWv4ZHiQXYMXWa3X0Ppzz52r9W0cXDjjlp5FyGdovCQsK+IXmjPo5cCvWBrZJYA6usFr9ssnUtTC+45lvPxPYwj47ZGPngCXDt7LD+v08XhqCu4LsctXIP/zejd30KVS1eR2RHI+tnEyaIKC0Xaa0igcv74MZX7Q8/U+B730QMX5adfYAHoeyRhoctRWaxVV3To7Vadd9jNXP45MRY5auhRcK7XyQcS85vJeCRoysfDUas4ERRQWYkX+68GyzO9GrkYFle931Akw2K6ZZfUuiC2TrF5xv1eRP1Zm2GX481U4ZGFTI8IzZL8sVQ6tvzq2Mxsecu589JNui9aB2d8Gp2Su/E2zn0h0ShIRmviGzf2HiBt+Bnji5X2h/fJKWbLaWge0MdOU5Jidfyh9k0YT7xo4piJLJYSaZ3nv+j4jTYnTfL7uYvuWbYkJ1T32aQVCan7Eup3BFAgQjzbWYi1XQVg6fvu8uHPpS3tNNA9EAMeeyTyg1l6zI2EIU5gPfd/dKmdyotY2lZBkFZNJqFkKRZuzjWekcw7hAxS+Bd68GKklt/DGrQiVycAgimqwXrfkzzQagawq2fXL2uXB8ghlsyxKLSQPnAtBF2Jcn5FH2z7HOQ+e18ZrFfNy0cYa/4OdH6K5aK1igTzhZZP2Urn0

54
.hgtags Normal file
View File

@@ -0,0 +1,54 @@
03f65e461915a940939e4cc689fc89721ffc40de DROPBEAR_0.48.1
0f967bfef5cd0056b7ec60e2305d917e51cbf30d DROPBEAR_0.44
170329dc8ce5dfcf6298e1ad6699f109bf78e73d DROPBEAR_0.51
1dbd2473482f320ea59f76ce961385cb3a0150a9 DROPBEAR_0.46
2098857ab826dd42ae05a9a22c3ce2cc835b9844 DROPBEAR_0.45
36160290a1b27451178be36752ed038840f59cdd LTC_DB_0.46
39d5d58461d6e93337636e69d4cdf184a09c8d24 LTC_1.05
55a99934db873be2e63b5968fb6532e5d9bd02e4 DROPBEAR_0.48
59400faa4b44708c5d0b595e81193bc621e752d3 libtomcrypt-1.05
66087d87c3555c78b47cf01f32bb5a32054c3ceb DROPBEAR_0.44test4
677843bfa734238a67636b461a02c110c462ffaf DROPBEAR_0.44test1
7faae8f46238e23975430876547b8950b4e75481 t:ltc-0.95-orig
8220862baae829ebc762587b99c662480d57bb23 DROPBEAR_0.53
86e0b50a9b588239c3fc9cc9cfe255ef586df17b ltm-0.30-orig
88e0a1ad951add46b795511dc2698e36b4aee922 DROPBEAR_0.44test3
8e94663164c6e106ccc5c9e997dedf6e04d77dd2 LTM_DB_0.44
91fbc376f01084037cd5f6a5bf2e2db4903e8e99 libtommath-0.35
97db060d0ef5f8cf8e67eb602ef037055a185ca9 libtommath-0.40
aa2f51a6b81d33de5e9898a7f27c792a173d9b26 DROPBEAR_0.53.1
ab370c629d363f8c9a3eca512bfa86e362034654 DROPBEAR_0.49
c2ac796b130eeb6fa840873d8c230544c8ec7e4b DROPBEAR_0.44test2
cd1143579f00b0248c79f63ca70efee4a35a57e8 LTC_DB_0.44
ce104c8b0be1ff3f2c2590b7cdc3fd6870c865cd DROPBEAR_0.52
d5faf4814ddbc5abd9e209409bb9e7a4686c8cd7 libtomcrypt-1.16
d7da3b1e15401eb234ec866d5eac992fc4cd5878 t:ltc-0.95-db-merge1
d8254fc979e99560c93ca2cece77a6df31927ea5 LTM_0.35
e109027b9edfb02f0bdf96ec45bb1cd9ad41e7da LTM_DB_0.46
e109027b9edfb02f0bdf96ec45bb1cd9ad41e7da LTM_DB_0.47
e37b160c414cab6466622f63b0c4dcbf6ebc47a9 DROPBEAR_0.47
e430a26064ee86ab79aef372118d6d03b2441996 DROPBEAR_0.50
e5d119ea4c63656bc54ecfd865d04591ac2ed225 LTC_DB_0.47
3f12086c2ef2b9ffe36a822fdb3ff647fcec1831 DROPBEAR_2011.54
d354464b2aa6f6ba0bf44d43bcae5aa798435393 DROPBEAR_2012.55
7faae8f46238e23975430876547b8950b4e75481 t:ltc-0.95-orig
0000000000000000000000000000000000000000 t:ltc-0.95-orig
d7da3b1e15401eb234ec866d5eac992fc4cd5878 t:ltc-0.95-db-merge1
0000000000000000000000000000000000000000 t:ltc-0.95-db-merge1
1b8b2b9d6e94bc3cc5e61b620476ea36cc466e1b DROPBEAR_2013.56
96b8bcb88017815040949a417caa55686271e8a9 DROPBEAR_2013.57
e76614145aea67f66e4a4257685c771efba21aa1 DROPBEAR_2013.58
7b68e581985fd4ea50869f8608ab95cda5d17876 DROPBEAR_2013.59
a50a1dc743317fad9b3737bc68fbca640659bb6d DROPBEAR_2013.60
e894dbc015ba7ff4c3bf897ee20e28ca90c55a16 DROPBEAR_2013.61test
3d1d7d151c0ce3a79da62e86463f5632fa2b144a DROPBEAR_2013.62
2351b2da8e0d08dcc6e64fcc328b53b9630bda68 DROPBEAR_2014.63
0d2d39957c029adb7f4327d37fe6b4900f0736d9 DROPBEAR_2014.64
e9579816f20ea85affc6135e87f8477992808948 DROPBEAR_2014.65
735511a4c761141416ad0e6728989d2dafa55bc2 DROPBEAR_2014.66
cbd674d63cd4f3781464a8d4056a5506c8ae926f DROPBEAR_2015.67
809feaa9408f036734129c77f2b3c7e779d4f099 DROPBEAR_2015.68
1637dbd262124d113e52967df46afd6c715e4fad DROPBEAR_2015.69
79a6ef02307d05cb9dda10465cb5b807baa8f62e DROPBEAR_2015.70
9a944a243f08be6b22d32f166a0690eb4872462b DROPBEAR_2015.71
78b12b6549be08b0bea3da329b2578060a76ca31 DROPBEAR_2016.72

51
.travis.yml Normal file
View File

@@ -0,0 +1,51 @@
language: c
os:
- linux
- osx
env:
matrix:
- BUNDLEDLIBTOM=--disable-bundled-libtom WEXTRAFLAGS=-Werror
- BUNDLEDLIBTOM=--enable-bundled-libtom
- MULTI=1
- NOWRITEV=1
# TODO: remove this section when libtomcrypt compiles on OSX: https://github.com/libtom/libtomcrypt/issues/82
matrix:
exclude:
- os: osx
env: BUNDLEDLIBTOM=--disable-bundled-libtom WEXTRAFLAGS=-Werror
compiler:
- gcc
- clang
# container-based builds
sudo: false
addons:
apt:
packages:
# packages list: https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise
- zlib1g-dev
- libtomcrypt-dev
- libtommath-dev
before_install:
- if [ "$CC" = "clang" ]; then WEXTRAFLAGS="$WEXTRAFLAGS -Wno-error=incompatible-library-redeclaration" ; fi # workaround
install:
- if [ "$TRAVIS_OS_NAME" = "osx" -a "$BUNDLEDLIBTOM" = "--disable-bundled-libtom" ]; then brew update > /dev/null && brew install libtomcrypt libtommath ; fi
script:
- autoconf && autoheader && ./configure "$BUNDLEDLIBTOM" CFLAGS="-O2 -Wall -Wno-pointer-sign $WEXTRAFLAGS" --prefix="$HOME/inst"
- if [ "$NOWRITEV" = "1" ]; then sed -i -e s/HAVE_WRITEV/DONT_HAVE_WRITEV/ config.h ; fi
- make -j3 install
after_success:
- ~/inst/bin/dropbearkey -t rsa -f testrsa
- ~/inst/bin/dropbearkey -t dss -f testdss
- ~/inst/bin/dropbearkey -t ecdsa -f testec256 -s 256
- ~/inst/bin/dropbearkey -t ecdsa -f testec384 -s 384
- ~/inst/bin/dropbearkey -t ecdsa -f testec521 -s 521

655
CHANGES
View File

@@ -1,8 +1,651 @@
2016.74 - 21 July 2016
- Security: Message printout was vulnerable to format string injection.
If specific usernames including "%" symbols can be created on a system
(validated by getpwnam()) then an attacker could run arbitrary code as root
when connecting to Dropbear server.
A dbclient user who can control username or host arguments could potentially
run arbitrary code as the dbclient user. This could be a problem if scripts
or webpages pass untrusted input to the dbclient program.
- Security: dropbearconvert import of OpenSSH keys could run arbitrary code as
the local dropbearconvert user when parsing malicious key files
- Security: dbclient could run arbitrary code as the local dbclient user if
particular -m or -c arguments are provided. This could be an issue where
dbclient is used in scripts.
- Security: dbclient or dropbear server could expose process memory to the
running user if compiled with DEBUG_TRACE and running with -v
The security issues were reported by an anonymous researcher working with
Beyond Security's SecuriTeam Secure Disclosure www.beyondsecurity.com/ssd.html
- Fix port forwarding failure when connecting to domains that have both
IPv4 and IPv6 addresses. The bug was introduced in 2015.68
- Fix 100% CPU use while waiting for rekey to complete. Thanks to Zhang Hui P
for the patch
2016.73 - 18 March 2016
- Support syslog in dbclient, option -o usesyslog=yes. Patch from Konstantin Tokarev
- Kill a proxycommand when dbclient exits, patch from Konstantin Tokarev
- Option to exit when a TCP forward fails, patch from Konstantin Tokarev
- New "-o" option parsing from Konstantin Tokarev. This allows handling some extra options
in the style of OpenSSH, though implementing all OpenSSH options is not planned.
- Fix crash when fallback initshells() is used, reported by Michael Nowak and Mike Tzou
- Allow specifying commands eg "dropbearmulti dbclient ..." instead of symlinks
- Various cleanups for issues found by a lint tool, patch from Francois Perrad
- Fix tab indent consistency, patch from Francois Perrad
- Fix issues found by cppcheck, reported by Mike Tzou
- Use system memset_s() or explicit_bzero() if available to clear memory. Also make
libtomcrypt/libtommath routines use that (or Dropbear's own m_burn()).
- Prevent scp failing when the local user doesn't exist. Based on patch from Michael Witten.
- Improved Travis CI test running, thanks to Mike Tzou
- Improve some code that was flagged by Coverity and Fortify Static Code Analyzer
2016.72 - 9 March 2016
- Validate X11 forwarding input. Could allow bypass of authorized_keys command= restrictions,
found by github.com/tintinweb. Thanks for Damien Miller for a patch. CVE-2016-3116
2015.71 - 3 December 2015
- Fix "bad buf_incrpos" when data is transferred, broke in 2015.69
- Fix crash on exit when -p address:port is used, broke in 2015.68, thanks to
Frank Stollenwerk for reporting and investigation
- Fix building with only ENABLE_CLI_REMOTETCPFWD given, patch from Konstantin Tokarev
- Fix bad configure script test which didn't work with dash shell, patch from Juergen Daubert,
broke in 2015.70
- Fix server race condition that could cause sessions to hang on exit,
https://github.com/robotframework/SSHLibrary/issues/128
2015.70 - 26 November 2015
- Fix server password authentication on Linux, broke in 2015.69
2015.69 - 25 November 2015
- Fix crash when forwarded TCP connections fail to connect (bug introduced in 2015.68)
- Avoid hang on session close when multiple sessions are started, affects Qt Creator
Patch from Andrzej Szombierski
- Reduce per-channel memory consumption in common case, increase default
channel limit from 100 to 1000 which should improve SOCKS forwarding for modern
webpages
- Handle multiple command line arguments in a single flag, thanks to Guilhem Moulin
- Manpage improvements from Guilhem Moulin
- Build fixes for Android from Mike Frysinger
- Don't display the MOTD when an explicit command is run from Guilhem Moulin
- Check curve25519 shared secret isn't zero
2015.68 - Saturday 8 August 2015
- Reduce local data copying for improved efficiency. Measured 30%
increase in throughput for connections to localhost
- Forwarded TCP ports connect asynchronously and try all available addresses
(IPv4, IPv6, round robin DNS)
- Fix all compile warnings, many patches from Gaël Portay
Note that configure with -Werror may not be successful on some platforms (OS X)
and some configuration options may still result in unused variable
warnings.
- Use TCP Fast Open on Linux if available. Saves a round trip at connection
to hosts that have previously been connected.
Needs a recent Linux kernel and possibly "sysctl -w net.ipv4.tcp_fastopen=3"
Client side is disabled by default pending further compatibility testing
with networks and systems.
- Increase maximum command length to 9000 bytes
- Free memory before exiting, patch from Thorsten Horstmann. Useful for
Dropbear ports to embedded systems and for checking memory leaks
with valgrind. Only partially implemented for dbclient.
This is disabled by default, enable with DROPBEAR_CLEANUP in sysoptions.h
- DROPBEAR_DEFAULT_CLI_AUTHKEY setting now always prepends home directory unless
there is a leading slash (~ isn't treated specially)
- Fix small ECC memory leaks
- Tighten validation of Diffie-Hellman parameters, from Florent Daigniere of
Matta Consulting. Odds of bad values are around 2**-512 -- improbable.
- Twofish-ctr cipher is supported though disabled by default
- Fix pre-authentication timeout when waiting for client SSH-2.0 banner, thanks
to CL Ouyang
- Fix null pointer crash with restrictions in authorized_keys without a command, patch from
Guilhem Moulin
- Ensure authentication timeout is handled while reading the initial banner,
thanks to CL Ouyang for finding it.
- Fix null pointer crash when handling bad ECC keys. Found by afl-fuzz
2015.67 - Wednesday 28 January 2015
- Call fsync() after generating private keys to ensure they aren't lost if a
reboot occurs. Thanks to Peter Korsgaard
- Disable non-delayed zlib compression by default on the server. Can be
enabled if required for old clients with DROPBEAR_SERVER_DELAY_ZLIB
- Default client key path ~/.ssh/id_dropbear
- Prefer stronger algorithms by default, from Fedor Brunner.
AES256 over 3DES
Diffie-hellman group14 over group1
- Add option to disable CBC ciphers.
- Disable twofish in default options.h
- Enable sha2 HMAC algorithms by default, the code was already required
for ECC key exchange. sha1 is the first preference still for performance.
- Fix installing dropbear.8 in a separate build directory, from Like Ma
- Allow configure to succeed if libtomcrypt/libtommath are missing, from Elan Ruusamäe
- Don't crash if ssh-agent provides an unknown type of key. From Catalin Patulea
- Minor bug fixes, a few issues found by Coverity scan
2014.66 - Thursday 23 October 2014
- Use the same keepalive handling behaviour as OpenSSH. This will work better
with some SSH implementations that have different behaviour with unknown
message types.
- Don't reply with SSH_MSG_UNIMPLEMENTED when we receive a reply to our own
keepalive message
- Set $SSH_CLIENT to keep bash happy, patch from Ryan Cleere
- Fix wtmp which broke since 2013.62, patch from Whoopie
2014.65 - Friday 8 August 2014
- Fix 2014.64 regression, server session hang on exit with scp (and probably
others), thanks to NiLuJe for tracking it down
- Fix 2014.64 regression, clock_gettime() error handling which broke on older
Linux kernels, reported by NiLuJe
- Fix 2014.64 regression, writev() could occassionally fail with EAGAIN which
wasn't caught
- Avoid error message when trying to set QoS on proxycommand or multihop pipes
- Use /usr/bin/xauth, thanks to Mike Frysinger
- Don't exit the client if the local user entry can't be found, thanks to iquaba
2014.64 - Sunday 27 July 2014
- Fix compiling with ECDSA and DSS disabled
- Don't exit abruptly if too many outgoing packets are queued for writev(). Patch
thanks to Ronny Meeus
- The -K keepalive option now behaves more like OpenSSH's "ServerAliveInterval".
If no response is received after 3 keepalives then the session is terminated. This
will close connections faster than waiting for a TCP timeout.
- Rework TCP priority setting. New settings are
if (connecting || ptys || x11) tos = LOWDELAY
else if (tcp_forwards) tos = 0
else tos = BULK
Thanks to Catalin Patulea for the suggestion.
- Improve handling of many concurrent new TCP forwarded connections, should now
be able to handle as many as MAX_CHANNELS. Thanks to Eduardo Silva for reporting
and investigating it.
- Make sure that exit messages from the client are printed, regression in 2013.57
- Use monotonic clock where available, timeouts won't be affected by system time
changes
- Add -V for version
2014.63 - Wednesday 19 February 2014
- Fix ~. to terminate a client interactive session after waking a laptop
from sleep.
- Changed port separator syntax again, now using host^port. This is because
IPv6 link-local addresses use %. Reported by Gui Iribarren
- Avoid constantly relinking dropbearmulti target, fix "make install"
for multi target, thanks to Mike Frysinger
- Avoid getting stuck in a loop writing huge key files, reported by Bruno
Thomsen
- Don't link dropbearkey or dropbearconvert to libz or libutil,
thanks to Nicolas Boos
- Fix linking -lcrypt on systems without /usr/lib, thanks to Nicolas Boos
- Avoid crash on exit due to cleaned up keys before last packets are sent,
debugged by Ronald Wahl
- Fix a race condition in rekeying where Dropbear would exit if it received a
still-in-flight packet after initiating rekeying. Reported by Oliver Metz.
This is a longstanding bug but is triggered more easily since 2013.57
- Fix README for ecdsa keys, from Catalin Patulea
- Ensure that generated RSA keys are always exactly the length
requested. Previously Dropbear always generated N+16 or N+15 bit keys.
Thanks to Unit 193
- Fix DROPBEAR_CLI_IMMEDIATE_AUTH mode which saves a network round trip if the
first public key succeeds. Still not enabled by default, needs more
compatibility testing with other implementations.
- Fix for port 0 forwarding in the client and port forwarding with Apache MINA SSHD. Thanks to
- Fix for bad system linux/pkt-sched.h header file with older Linux
kernels, from Steve Dover
- Fix signal handlers so that errno is saved, thanks to Erik Ahlén for a patch
and Mark Wickham for independently spotting the same problem.
2013.62 - Tuesday 3 December 2013
- Disable "interactive" QoS connection options when a connection doesn't
have a PTY (eg scp, rsync). Thanks to Catalin Patulea for the patch.
- Log when a hostkey is generated with -R, fix some bugs in handling server
hostkey commandline options
- Fix crash in Dropbearconvert and 521 bit key, reported by NiLuJe
- Update config.guess and config.sub again
2013.61test - Thursday 14 November 2013
- ECC (elliptic curve) support. Supports ECDSA hostkeys (requires new keys to
be generated) and ECDH for setting up encryption keys (no intervention
required). This is significantly faster.
- curve25519-sha256@libssh.org support for setting up encryption keys. This is
another elliptic curve mode with less potential of NSA interference in
algorithm parameters. curve25519-donna code thanks to Adam Langley
- -R option to automatically generate hostkeys. This is recommended for
embedded platforms since it allows the system random number device
/dev/urandom a longer startup time to generate a secure seed before the
hostkey is required.
- Compile fixes for old vendor compilers like Tru64 from Daniel Richard G.
- Make authorized_keys handling more robust, don't exit encountering
malformed lines. Thanks to Lorin Hochstein and Mark Stillwell
2013.60 - Wednesday 16 October 2013
- Fix "make install" so that it doesn't always install to /bin and /sbin
- Fix "make install MULTI=1", installing manpages failed
- Fix "make install" when scp is included since it has no manpage
- Make --disable-bundled-libtom work
2013.59 - Friday 4 October 2013
- Fix crash from -J command
Thanks to Lluís Batlle i Rossell and Arnaud Mouiche for patches
- Avoid reading too much from /proc/net/rt_cache since that causes
system slowness.
- Improve EOF handling for half-closed connections
Thanks to Catalin Patulea
- Send a banner message to report PAM error messages intended for the user
Patch from Martin Donnelly
- Limit the size of decompressed payloads, avoids memory exhaustion denial
of service
Thanks to Logan Lamb for reporting and investigating it. CVE-2013-4421
- Avoid disclosing existence of valid users through inconsistent delays
Thanks to Logan Lamb for reporting. CVE-2013-4434
- Update config.guess and config.sub for newer architectures
- Avoid segfault in server for locked accounts
- "make install" now installs manpages
dropbearkey.8 has been renamed to dropbearkey.1
manpage added for dropbearconvert
- Get rid of one second delay when running non-interactive commands
2013.58 - Thursday 18 April 2013
- Fix building with Zlib disabled, thanks to Hans Harder and cuma@freetz
- Use % as a separator for ports, fixes scp in multihop mode, from Hans Harder
- Reject logins for other users when running as non-root, from Hans Harder
- Disable client immediate authentication request by default, it prevents
passwordless logins from working
2013.57 - Monday 15 April 2013
- Decreased connection setup time particularly with high latency connections,
the number of round trips has been reduced for both client and server.
CPU time hasn't been changed.
- Client will send an initial key exchange guess to save a round trip.
Dropbear implements an extension kexguess2@matt.ucc.asn.au to allow the first
packet guess to succeed in wider circumstances than the standard behaviour.
When communicating with other implementations the standard behaviour is used.
- Client side: when public key or password authentication with
$DROPBEAR_PASSWORD is used an initial authentication request will
be sent immediately rather than querying the list of available methods.
This behaviour is enabled by CLI_IMMEDIATE_AUTH option (on by default),
please let the Dropbear author know if it causes any interoperability
problems.
- Implement client escape characters ~. (terminate session) and
~^Z (background session)
- Server will more reliably clean up utmp when connection is closed, reported by
Mattias Walström
- Don't crash if /dev/urandom isn't writable (RHEL5), thanks to Scott Case
- Add "-y -y" client option to skip host key checking, thanks to Hans Harder
- scp didn't work properly on systems using vfork(), thanks to Frank Van Uffelen
- Added IUTF8 terminal mode support (Linux and Mac OS). Not standardised yet
though probably will be soon
- Some verbose DROPBEAR_TRACE output is now hidden unless $DROPBEAR_TRACE2
enviroment variable is set
- Fix using asymmetric MAC algorithms (broke in )
- Renamed configure.in to configure.ac to quieten autoconf, from Mike Frysinger
2013.56 - Thursday 21 March 2013
- Allow specifying cipher (-c) and MAC (-m) lists for dbclient
- Allow using 'none' cipher or MAC (off by default, use options.h). Encryption
is used during authentication then disabled, similar to OpenSSH HPN mode
- Allow a user in immediately if the account has a blank password and blank
passwords are enabled
- Include a few extra sources of entropy from /proc on Linux, hash private keys
as well. Dropbear will also write gathered entropy back into /dev/urandom
- Added hmac-sha2-256 and hmac-sha2-512 support (off by default, use options.h)
- Don't sent bad address "localhost" for -R forward connections,
reported by Denis Bider
- Add "-B" runtime option to allow blank passwords
- Allow using IPv6 bracket notation for addresses in server "-p" option, from Ben Jencks
- A few improvements for Android from Reimar Döffinger
- Fix memory leak for TCP forwarded connections to hosts that timed out,
reported by Norbert Benczúr. Appears to be a very long-standing bug.
- Fix "make clean" for out of tree builds
- Fix compilation when ENABLE_{SVR,CLI}_AGENTFWD are unset
2012.55 - Wednesday 22 February 2012
- Security: Fix use-after-free bug that could be triggered if command="..."
authorized_keys restrictions are used. Could allow arbitrary code execution
or bypass of the command="..." restriction to an authenticated user.
This bug affects releases 0.52 onwards. Ref CVE-2012-0920.
Thanks to Danny Fullerton of Mantor Organization for reporting
the bug.
- Compile fix, only apply IPV6 socket options if they are available in headers
Thanks to Gustavo Zacarias for the patch
- Overwrite session key memory on exit
- Fix minor memory leak in unusual PAM authentication configurations.
Thanks to Stathis Voukelatos
- Other small code cleanups
2011.54 - Tuesday 8 November 2011
- Building statically works again, broke in 0.53 and 0.53.1
- Fix crash when forwarding with -R
- Fixed various leaks found by Klocwork analysis software, thanks to them for
running it
- Set IPTOS_LOWDELAY for IPv6, thanks to Dave Taht
- Bind to sockets with IPV6_V6ONLY so that it works properly on systems
regardless of the system-wide setting
- Added ALLOW_BLANK_PASSWORD option. Dropbear also now allows public key logins
to accounts with a blank password. Thanks to Rob Landley
- Fixed case where "-K 1" keepalive for dbclient would cause a SSH_MSG_IGNORE
packet to be sent
- Avoid some memory allocations in big number maths routines, improves
performance slightly
- Fix symlink target for installdropbearmulti with DESTDIR set, thanks to
Scottie Shore
- When requesting server allocated remote ports (-R 0:host:port) print a
message informing what the port is, thanks to Ali Onur Uyar.
- New version numbering scheme.
Source repository has now migrated to Mercurial at
https://secure.ucc.asn.au/hg/dropbear/graph/default
0.53.1 - Wednesday 2 March 2011
- -lcrypt needs to be before object files for static linking
- Compile fix when both client and agent forwarding are disabled
- Fix DROPBEAR_PRNGD_SOCKET mode
- Don't allow setting zlib memLevel since it seems buggy
0.53 - Thurs 24 February 2011
- Various performance/memory use improvements
- Client agent forwarding now works, using OpenSSH's ssh-agent
- Improve robustness of client multihop mode
- Fix a prime generation bug in bundled libtommath. This is unlikely to have
generated any bad keys in the wild.
See
https://bugzilla.redhat.com/show_bug.cgi?id=615088
http://bugs.gentoo.org/show_bug.cgi?id=328383
http://bugs.gentoo.org/show_bug.cgi?id=328409
- Attempt to build against system libtomcrypt/libtommath if available. This
can be disabled with ./configure --enable-bundled-libtom
- Make -K (keepalive) and -I (idle timeout) work together sensibly in the client.
The idle timeout is no longer reset by SSH_MSG_IGNORE packets.
- Add diffie-hellman-group14-sha1 key exchange method
- Compile fix if ENABLE_CLI_PROXYCMD is disabled
- /usr/bin/X11/xauth is now the default path
- Client remote forward (-L/-R) arguments now accept a listen address
- In uClinux avoid trashing the parent process when a session exits
- Blowfish is now disabled by default since it has large memory usage
- Add option to change zlib windowbits/memlevel. Use less memory by default
- DROPBEAR_SMALL_CODE is now disabled by default
- SSH_ORIGINAL_COMMAND environment variable is set by the server when an
authorized_keys command is specified.
- Set SSH_TTY and SSH_CONNECTION environment variables in the server
- Client banner is now printed to standard error rather than standard output
- Capitalisation in many log messages has been made consistent. This may affect
scripts that parse logfiles.
0.52 - Wed 12 November 2008
- Add "netcat-alike" option (-B) to dbclient, allowing Dropbear to tunnel
standard input/output to a TCP port-forwarded remote host.
- Add "proxy command" support to dbclient, to allow using a spawned process for
IO rather than a direct TCP connection. eg
dbclient remotehost
is equivalent to
dbclient -J 'nc remotehost 22' remotehost
(the hostname is still provided purely for looking up saved host keys)
- Combine netcat-alike and proxy support to allow "multihop" connections, with
comma-separated host syntax. Allows running
dbclient user1@host1,user2@host2,user3@host3
to end up at host3 via the other two, using SSH TCP forwarding. It's a bit
like onion-routing. All connections are established from the local machine.
The comma-separated syntax can also be used for scp/rsync, eg
rsync -a -e dbclient m@gateway,m2@host,martello:/home/matt/ ~/backup/
to bounce through a few hosts.
- Add -I "idle timeout" option (contributed by Farrell Aultman)
- Allow restrictions on authorized_keys logins such as restricting commands
to be run etc. This is a subset of those allowed by OpenSSH, doesn't
yet allow restricting source host.
- Use vfork() for scp on uClinux
- Default to PATH=/usr/bin:/bin for shells.
- Report errors if -R forwarding fails
- Add counter mode cipher support, which avoids some security problems with the
standard CBC mode.
- Support zlib@openssh.com delayed compression for client/server. It can be
required for the Dropbear server with the '-Z' option. This is useful for
security as it avoids exposing the server to attacks on zlib by
unauthenticated remote users, though requires client side support.
- options.h has been split into options.h (user-changable) and sysoptions.h
(less commonly changed)
- Support "dbclient -s sftp" to specify a subsystem
- Fix a bug in replies to channel requests that could be triggered by recent
versions of PuTTY
0.51 - Thu 27 March 2008
- Make a copy of password fields rather erroneously relying on getwpnam()
to be safe to call multiple times
- If $SSH_ASKPASS_ALWAYS environment variable is set (and $SSH_ASKPASS is
as well) always use that program, ignoring isatty() and $DISPLAY
- Wait until a process exits before the server closes a connection, so
that an exit code can be sent. This fixes problems with exit codes not
being returned, which could cause scp to fail.
0.50 - Wed 8 August 2007
- Add DROPBEAR_PASSWORD environment variable to specify a dbclient password
- Use /dev/urandom by default, since that's what everyone does anyway
- Correct vfork() use for uClinux in scp
(thanks to Alex Landau)
- Exit with an exit code of 1 if dropbear can't bind to any ports
(thanks to Nicolai Ehemann)
- Improve network performance and add a -W <receive_window> argument for
adjusting the tradeoff between network performance and memory consumption.
- Fix a problem where reply packets could be sent during key exchange,
in violation of the SSH spec. This could manifest itself with connections
being terminated after 8 hours with new TCP-forward connections being
established.
- Add -K <keepalive_time> argument, ensuring that data is transmitted
over the connection at least every N seconds.
- dropbearkey will no longer generate DSS keys of sizes other than 1024
bits, as required by the DSS specification. (Other sizes are still
accepted for use to provide backwards compatibility).
0.49 - Fri 23 February 2007
- Security: dbclient previously would prompt to confirm a
mismatching hostkey but wouldn't warn loudly. It will now
exit upon a mismatch.
exit upon a mismatch. CVE-2007-1099
- Compile fixes, make sure that all variable definitions are at the start
of a scope.
@@ -64,7 +707,7 @@
(thanks to Tomas Vanek for helping track it down)
- Implement per-IP pre-authentication connection limits
(after some poking from Pablo Fernandez)
(after some poking from Pablo Fernandez) CVE-2006-1206
- Exit gracefully if trying to connect to as SSH v1 server
(reported by Rushi Lala)
@@ -85,7 +728,7 @@
- SECURITY: fix for buffer allocation error in server code, could potentially
allow authenticated users to gain elevated privileges. All multi-user systems
running the server should upgrade (or apply the patch available on the
Dropbear webpage).
Dropbear webpage). CVE-2005-4178
- Fix channel handling code so that redirecting to /dev/null doesn't use
100% CPU.
@@ -292,7 +935,7 @@
- SECURITY: Don't try to free() uninitialised variables in DSS verification
code. Thanks to Arne Bernin for pointing out this bug. This is possibly
exploitable, all users with DSS and pubkey-auth compiled in are advised to
upgrade.
upgrade. CVE-2004-2486
- Clean up agent forwarding socket files correctly, patch from Gerrit Pape.
@@ -416,7 +1059,7 @@
Lobenstock and Mihnea Stoenescu
- Use daemon() function if available (or our own copy) rather than separate
code (thanks to Frédéric Lavernhe for the report and debugging, and Bernard
code (thanks to Frédéric Lavernhe for the report and debugging, and Bernard
Blackham for his suggestion on what to look at)
- Fixed up support for first_kex_packet_follows, required to talk to ssh.com
@@ -535,7 +1178,7 @@
- Various signedness fixes
- Can listen on multiple ports
- added option to disable openpty with configure script,
(from K.-P. Kirchdörfer <kapeka at epost.de>)
(from K.-P. Kirchdörfer <kapeka at epost.de>)
- Various cleanups to bignum code
(thanks to Tom St Denis <tomstdenis at iahu.ca>)
- Fix compile error when disabling RSA

View File

@@ -24,7 +24,7 @@ See MULTI for instructions on making all-in-one binaries.
If you want to compile statically, add "STATIC=1" to the make command-line.
Binaries can be strippd with "make strip"
Binaries can be stripped with "make strip"
============================================================================

54
LICENSE
View File

@@ -8,7 +8,7 @@ The majority of code is written by Matt Johnston, under the license below.
Portions of the client-mode work are (c) 2004 Mihnea Stoenescu, under the
same license:
Copyright (c) 2002-2006 Matt Johnston
Copyright (c) 2002-2015 Matt Johnston
Portions copyright (c) 2004 Mihnea Stoenescu
All rights reserved.
@@ -87,3 +87,55 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
=====
curve25519-donna:
/* Copyright 2008, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT
* OWNER 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.
*
* curve25519-donna: Curve25519 elliptic curve, public key function
*
* http://code.google.com/p/curve25519-donna/
*
* Adam Langley <agl@imperialviolet.org>
*
* Derived from public domain C code by Daniel J. Bernstein <djb@cr.yp.to>
*
* More information about curve25519 can be found here
* http://cr.yp.to/ecdh.html
*
* djb's sample implementation of curve25519 is written in a special assembly
* language called qhasm and uses the floating point registers.
*
* This is, almost, a clean room reimplementation from the curve25519 paper. It
* uses many of the tricks described therein. Only the crecip function is taken
* from the sample implementation.
*/

4
MULTI
View File

@@ -20,7 +20,3 @@ etc
then execute as normal:
./dropbear <options here>
"make install" doesn't currently work for multi-binary configuration, though
in most situations where it is being used, the target and build systems will
differ.

View File

@@ -13,43 +13,54 @@ ifndef PROGRAMS
PROGRAMS=dropbear dbclient dropbearkey dropbearconvert
endif
LTC=libtomcrypt/libtomcrypt.a
LTM=libtommath/libtommath.a
STATIC_LTC=libtomcrypt/libtomcrypt.a
STATIC_LTM=libtommath/libtommath.a
COMMONOBJS=dbutil.o buffer.o \
LIBTOM_LIBS=@LIBTOM_LIBS@
ifeq (@BUNDLED_LIBTOM@, 1)
LIBTOM_DEPS=$(STATIC_LTC) $(STATIC_LTM)
CFLAGS+=-I$(srcdir)/libtomcrypt/src/headers/
LIBTOM_LIBS=$(STATIC_LTC) $(STATIC_LTM)
endif
COMMONOBJS=dbutil.o buffer.o dbhelpers.o \
dss.o bignum.o \
signkey.o rsa.o random.o \
signkey.o rsa.o dbrandom.o \
queue.o \
atomicio.o compat.o fake-rfc2553.o
atomicio.o compat.o fake-rfc2553.o \
ltc_prng.o ecc.o ecdsa.o crypto_desc.o \
gensignkey.o gendss.o genrsa.o
SVROBJS=svr-kex.o svr-algo.o svr-auth.o sshpty.o \
svr-authpasswd.o svr-authpubkey.o svr-session.o svr-service.o \
SVROBJS=svr-kex.o svr-auth.o sshpty.o \
svr-authpasswd.o svr-authpubkey.o svr-authpubkeyoptions.o svr-session.o svr-service.o \
svr-chansession.o svr-runopts.o svr-agentfwd.o svr-main.o svr-x11fwd.o\
svr-tcpfwd.o svr-authpam.o
CLIOBJS=cli-algo.o cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \
cli-session.o cli-service.o cli-runopts.o cli-chansession.o \
cli-authpubkey.o cli-tcpfwd.o cli-channel.o cli-authinteract.o
CLIOBJS=cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \
cli-session.o cli-runopts.o cli-chansession.o \
cli-authpubkey.o cli-tcpfwd.o cli-channel.o cli-authinteract.o \
cli-agentfwd.o
CLISVROBJS=common-session.o packet.o common-algo.o common-kex.o \
common-channel.o common-chansession.o termcodes.o loginrec.o \
tcp-accept.o listener.o process-packet.o \
common-runopts.o circbuffer.o
tcp-accept.o listener.o process-packet.o dh_groups.o \
common-runopts.o circbuffer.o curve25519-donna.o list.o netio.o
KEYOBJS=dropbearkey.o gendss.o genrsa.o
KEYOBJS=dropbearkey.o
CONVERTOBJS=dropbearconvert.o keyimport.o
SCPOBJS=scp.o progressmeter.o atomicio.o scpmisc.o
SCPOBJS=scp.o progressmeter.o atomicio.o scpmisc.o compat.o
HEADERS=options.h dbutil.h session.h packet.h algo.h ssh.h buffer.h kex.h \
dss.h bignum.h signkey.h rsa.h random.h service.h auth.h \
dss.h bignum.h signkey.h rsa.h dbrandom.h service.h auth.h \
debug.h channel.h chansession.h config.h queue.h sshpty.h \
termcodes.h gendss.h genrsa.h runopts.h includes.h \
loginrec.h atomicio.h x11fwd.h agentfwd.h tcpfwd.h compat.h \
listener.h fake-rfc2553.h
listener.h fake-rfc2553.h ecc.h ecdsa.h
dropbearobjs=$(COMMONOBJS) $(CLISVROBJS) $(SVROBJS)
dropbearobjs=$(COMMONOBJS) $(CLISVROBJS) $(SVROBJS)
dbclientobjs=$(COMMONOBJS) $(CLISVROBJS) $(CLIOBJS)
dropbearkeyobjs=$(COMMONOBJS) $(KEYOBJS)
dropbearconvertobjs=$(COMMONOBJS) $(CONVERTOBJS)
@@ -59,9 +70,11 @@ VPATH=@srcdir@
srcdir=@srcdir@
prefix=@prefix@
exec_prefix=${prefix}
bindir=${exec_prefix}/bin
sbindir=${exec_prefix}/sbin
exec_prefix=@exec_prefix@
datarootdir = @datarootdir@
bindir=@bindir@
sbindir=@sbindir@
mandir=@mandir@
CC=@CC@
AR=@AR@
@@ -69,8 +82,8 @@ RANLIB=@RANLIB@
STRIP=@STRIP@
INSTALL=@INSTALL@
CPPFLAGS=@CPPFLAGS@
CFLAGS=-I. -I$(srcdir) -I$(srcdir)/libtomcrypt/src/headers/ $(CPPFLAGS) @CFLAGS@
LIBS=$(LTC) $(LTM) @LIBS@
CFLAGS+=-I. -I$(srcdir) $(CPPFLAGS) @CFLAGS@
LIBS+=@LIBS@
LDFLAGS=@LDFLAGS@
EXEEXT=@EXEEXT@
@@ -106,10 +119,6 @@ ifeq ($(SCPPROGRESS), 1)
CFLAGS+=-DPROGRESS_METER
endif
#%: $(HEADERS)
#%: $(HEADERS) Makefile
# TODO
all: $(TARGETS)
strip: $(TARGETS)
@@ -117,34 +126,34 @@ strip: $(TARGETS)
install: $(addprefix inst_, $(TARGETS))
installdropbearmulti: insdbmulti $(addprefix insmulti, $(PROGRAMS))
insdbmulti: dropbearmulti
$(INSTALL) -d -m 755 $(DESTDIR)$(bindir)
$(INSTALL) -m 755 dropbearmulti$(EXEEXT) $(DESTDIR)$(bindir)
-chown root $(DESTDIR)$(bindir)/dropbearmulti$(EXEEXT)
-chgrp 0 $(DESTDIR)$(bindir)/dropbearmulti$(EXEEXT)
insmultidropbear: dropbearmulti
$(INSTALL) -d $(DESTDIR)$(sbindir)
-rm -f $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
-ln -s $(DESTDIR)$(bindir)/dropbearmulti$(EXEEXT) $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
-ln -s $(bindir)/dropbearmulti$(EXEEXT) $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
$(INSTALL) -d $(DESTDIR)$(mandir)/man8
$(INSTALL) -m 644 $(srcdir)/dropbear.8 $(DESTDIR)$(mandir)/man8/dropbear.8
insmulti%: dropbearmulti
$(INSTALL) -d $(DESTDIR)$(bindir)
-rm -f $(DESTDIR)$(bindir)/$*$(EXEEXT)
-ln -s $(DESTDIR)$(bindir)/dropbearmulti$(EXEEXT) $(DESTDIR)$(bindir)/$*$(EXEEXT)
-ln -s $(bindir)/dropbearmulti$(EXEEXT) $(DESTDIR)$(bindir)/$*$(EXEEXT)
$(INSTALL) -d $(DESTDIR)$(mandir)/man1
if test -e $*.1; then $(INSTALL) -m 644 $*.1 $(DESTDIR)$(mandir)/man1/$*.1; fi
# dropbear should go in sbin, so it needs a seperate rule
# dropbear should go in sbin, so it needs a separate rule
inst_dropbear: dropbear
$(INSTALL) -d -m 755 $(DESTDIR)$(sbindir)
$(INSTALL) -m 755 dropbear$(EXEEXT) $(DESTDIR)$(sbindir)
-chown root $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
-chgrp 0 $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
$(INSTALL) -d $(DESTDIR)$(sbindir)
$(INSTALL) dropbear$(EXEEXT) $(DESTDIR)$(sbindir)
$(INSTALL) -d $(DESTDIR)$(mandir)/man8
$(INSTALL) -m 644 $(srcdir)/dropbear.8 $(DESTDIR)$(mandir)/man8/dropbear.8
inst_%: $*
$(INSTALL) -d -m 755 $(DESTDIR)$(bindir)
$(INSTALL) -m 755 $*$(EXEEXT) $(DESTDIR)$(bindir)
-chown root $(DESTDIR)$(bindir)/$*$(EXEEXT)
-chgrp 0 $(DESTDIR)$(bindir)/$*$(EXEEXT)
inst_%: %
$(INSTALL) -d $(DESTDIR)$(bindir)
$(INSTALL) $*$(EXEEXT) $(DESTDIR)$(bindir)
$(INSTALL) -d $(DESTDIR)$(mandir)/man1
if test -e $*.1; then $(INSTALL) -m 644 $*.1 $(DESTDIR)$(mandir)/man1/$*.1; fi
inst_dropbearmulti: $(addprefix insmulti, $(PROGRAMS))
# for some reason the rule further down doesn't like $($@objs) as a prereq.
@@ -153,9 +162,14 @@ dbclient: $(dbclientobjs)
dropbearkey: $(dropbearkeyobjs)
dropbearconvert: $(dropbearconvertobjs)
dropbear dbclient dropbearkey dropbearconvert: $(HEADERS) $(LTC) $(LTM) \
Makefile
$(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBS)
dropbear: $(HEADERS) $(LIBTOM_DEPS) Makefile
$(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBTOM_LIBS) $(LIBS) @CRYPTLIB@
dbclient: $(HEADERS) $(LIBTOM_DEPS) Makefile
$(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBTOM_LIBS) $(LIBS)
dropbearkey dropbearconvert: $(HEADERS) $(LIBTOM_DEPS) Makefile
$(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBTOM_LIBS)
# scp doesn't use the libs so is special.
scp: $(SCPOBJS) $(HEADERS) Makefile
@@ -169,10 +183,10 @@ ifeq ($(MULTI),1)
CFLAGS+=$(addprefix -DDBMULTI_, $(PROGRAMS)) -DDROPBEAR_MULTI
endif
dropbearmulti: multilink
dropbearmulti$(EXEEXT): $(HEADERS) $(MULTIOBJS) $(LIBTOM_DEPS) Makefile
$(CC) $(LDFLAGS) -o $@ $(MULTIOBJS) $(LIBTOM_LIBS) $(LIBS) @CRYPTLIB@
multibinary: $(HEADERS) $(MULTIOBJS) $(LTC) $(LTM) Makefile
$(CC) $(LDFLAGS) -o dropbearmulti$(EXEEXT) $(MULTIOBJS) $(LIBS)
multibinary: dropbearmulti$(EXEEXT)
multilink: multibinary $(addprefix link, $(PROGRAMS))
@@ -180,10 +194,10 @@ link%:
-rm -f $*$(EXEEXT)
-ln -s dropbearmulti$(EXEEXT) $*$(EXEEXT)
$(LTC): options.h
cd libtomcrypt && $(MAKE) clean && $(MAKE)
$(STATIC_LTC): options.h
cd libtomcrypt && $(MAKE)
$(LTM): options.h
$(STATIC_LTM): options.h
cd libtommath && $(MAKE)
.PHONY : clean sizes thisclean distclean tidy ltc-clean ltm-clean

16
README
View File

@@ -1,4 +1,5 @@
This is Dropbear, a smallish SSH 2 server and client.
This is Dropbear, a smallish SSH server and client.
https://matt.ucc.asn.au/dropbear/dropbear.html
INSTALL has compilation instructions.
@@ -27,8 +28,7 @@ ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAwVa6M6cGVmUcLl2cFzkxEoJd06Ub4bVDsYrWvXhvUV+Z
You must make sure that ~/.ssh, and the key file, are only writable by the
user. Beware of editors that split the key into multiple lines.
NOTE: Dropbear ignores authorized_keys options such as those described in the
OpenSSH sshd manpage, and will not allow a login for these keys.
Dropbear supports some options for authorized_keys entries, see the manpage.
============================================================================
@@ -42,8 +42,7 @@ If you have an OpenSSH-style private key ~/.ssh/id_rsa, you need to do:
dropbearconvert openssh dropbear ~/.ssh/id_rsa ~/.ssh/id_rsa.db
dbclient -i ~/.ssh/id_rsa.db <hostname>
Currently encrypted keys aren't supported, neither is agent forwarding. At some
stage both hopefully will be.
Dropbear does not support encrypted hostkeys though can connect to ssh-agent.
============================================================================
@@ -52,13 +51,18 @@ dropbearkey's '-y' option.
============================================================================
To run the server, you need to generate server keys, this is one-off:
To run the server, you need to server keys, this is one-off:
./dropbearkey -t rsa -f dropbear_rsa_host_key
./dropbearkey -t dss -f dropbear_dss_host_key
./dropbearkey -t ecdsa -f dropbear_ecdsa_host_key
or alternatively convert OpenSSH keys to Dropbear:
./dropbearconvert openssh dropbear /etc/ssh/ssh_host_dsa_key dropbear_dss_host_key
You can also get Dropbear to create keys when the first connection is made -
this is preferable to generating keys when the system boots. Make sure
/etc/dropbear/ exists and then pass '-R' to the dropbear server.
============================================================================
If the server is run as non-root, you most likely won't be able to allocate a

View File

@@ -21,23 +21,43 @@
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#ifndef _AGENTFWD_H_
#define _AGENTFWD_H_
#ifndef DISABLE_AGENTFWD
#ifndef DROPBEAR_AGENTFWD_H_
#define DROPBEAR_AGENTFWD_H_
#include "includes.h"
#include "chansession.h"
#include "channel.h"
#include "auth.h"
#include "list.h"
int agentreq(struct ChanSess * chansess);
void agentsetauth(struct ChanSess *chansess);
void agentcleanup(struct ChanSess * chansess);
void agentset(struct ChanSess *chansess);
#ifdef ENABLE_CLI_AGENTFWD
/* An agent reply can be reasonably large, as it can
* contain a list of all public keys held by the agent.
* 10000 is arbitrary */
#define MAX_AGENT_REPLY 10000
/* client functions */
void cli_load_agent_keys(m_list * ret_list);
void agent_buf_sign(buffer *sigblob, sign_key *key,
buffer *data_buf);
void cli_setup_agent(struct Channel *channel);
#ifdef __hpux
#define seteuid(a) setresuid(-1, (a), -1)
#define setegid(a) setresgid(-1, (a), -1)
#endif
#endif /* DROPBEAR_AGENTFWD */
#endif /* _AGENTFWD_H_ */
extern const struct ChanType cli_chan_agent;
#endif /* ENABLE_CLI_AGENTFWD */
#ifdef ENABLE_SVR_AGENTFWD
int svr_agentreq(struct ChanSess * chansess);
void svr_agentcleanup(struct ChanSess * chansess);
void svr_agentset(struct ChanSess *chansess);
#endif /* ENABLE_SVR_AGENTFWD */
#endif /* DROPBEAR_AGENTFWD_H_ */

99
algo.h
View File

@@ -22,20 +22,25 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#ifndef _ALGO_H_
#ifndef DROPBEAR_ALGO_H_
#define _ALGO_H_
#define DROPBEAR_ALGO_H_
#include "includes.h"
#include "buffer.h"
#define DROPBEAR_MODE_UNUSED 0
#define DROPBEAR_MODE_CBC 1
#define DROPBEAR_MODE_CTR 2
struct Algo_Type {
unsigned char *name; /* identifying name */
const char *name; /* identifying name */
char val; /* a value for this cipher, or -1 for invalid */
void *data; /* algorithm specific data */
unsigned usable : 1; /* whether we can use this algorithm */
const void *data; /* algorithm specific data */
char usable; /* whether we can use this algorithm */
const void *mode; /* the mode, currently only used for ciphers,
points to a 'struct dropbear_cipher_mode' */
};
typedef struct Algo_Type algo_type;
@@ -45,30 +50,88 @@ extern algo_type sshkex[];
extern algo_type sshhostkey[];
extern algo_type sshciphers[];
extern algo_type sshhashes[];
extern algo_type sshcompress[];
extern algo_type ssh_compress[];
extern algo_type ssh_delaycompress[];
extern algo_type ssh_nocompress[];
extern const struct dropbear_cipher dropbear_nocipher;
extern const struct dropbear_cipher_mode dropbear_mode_none;
extern const struct dropbear_hash dropbear_nohash;
struct dropbear_cipher {
const struct ltc_cipher_descriptor *cipherdesc;
unsigned long keysize;
unsigned char blocksize;
const unsigned long keysize;
const unsigned char blocksize;
};
struct dropbear_cipher_mode {
int (*start)(int cipher, const unsigned char *IV,
const unsigned char *key,
int keylen, int num_rounds, void *cipher_state);
int (*encrypt)(const unsigned char *pt, unsigned char *ct,
unsigned long len, void *cipher_state);
int (*decrypt)(const unsigned char *ct, unsigned char *pt,
unsigned long len, void *cipher_state);
};
struct dropbear_hash {
const struct ltc_hash_descriptor *hashdesc;
unsigned long keysize;
unsigned char hashsize;
const struct ltc_hash_descriptor *hash_desc;
const unsigned long keysize;
/* hashsize may be truncated from the size returned by hash_desc,
eg sha1-96 */
const unsigned char hashsize;
};
enum dropbear_kex_mode {
DROPBEAR_KEX_NORMAL_DH,
DROPBEAR_KEX_ECDH,
DROPBEAR_KEX_CURVE25519,
};
struct dropbear_kex {
enum dropbear_kex_mode mode;
/* "normal" DH KEX */
const unsigned char *dh_p_bytes;
const int dh_p_len;
/* elliptic curve DH KEX */
#ifdef DROPBEAR_ECDH
const struct dropbear_ecc_curve *ecc_curve;
#else
const void* dummy;
#endif
/* both */
const struct ltc_hash_descriptor *hash_desc;
};
void crypto_init();
int have_algo(char* algo, size_t algolen, algo_type algos[]);
void buf_put_algolist(buffer * buf, algo_type localalgos[]);
algo_type * svr_buf_match_algo(buffer* buf, algo_type localalgos[],
int *goodguess);
algo_type * cli_buf_match_algo(buffer* buf, algo_type localalgos[],
int *goodguess);
enum kexguess2_used {
KEXGUESS2_LOOK,
KEXGUESS2_NO,
KEXGUESS2_YES,
};
#endif /* _ALGO_H_ */
#define KEXGUESS2_ALGO_NAME "kexguess2@matt.ucc.asn.au"
#define KEXGUESS2_ALGO_ID 99
algo_type * buf_match_algo(buffer* buf, algo_type localalgos[],
enum kexguess2_used *kexguess2, int *goodguess);
#ifdef ENABLE_USER_ALGO_LIST
int check_user_algos(const char* user_algo_list, algo_type * algos,
const char *algo_desc);
char * algolist_string(algo_type algos[]);
#endif
enum {
DROPBEAR_COMP_NONE,
DROPBEAR_COMP_ZLIB,
DROPBEAR_COMP_ZLIB_DELAY,
};
#endif /* DROPBEAR_ALGO_H_ */

View File

@@ -53,6 +53,7 @@ atomicio(f, fd, _s, n)
if (errno == EINTR || errno == EAGAIN)
#endif
continue;
/* FALLTHROUGH */
case 0:
return (res);
default:

111
auth.h
View File

@@ -22,45 +22,68 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#ifndef _AUTH_H_
#define _AUTH_H_
#ifndef DROPBEAR_AUTH_H_
#define DROPBEAR_AUTH_H_
#include "includes.h"
#include "signkey.h"
#include "chansession.h"
void svr_authinitialise();
void cli_authinitialise();
void svr_authinitialise(void);
void cli_authinitialise(void);
/* Server functions */
void recv_msg_userauth_request();
void recv_msg_userauth_request(void);
void send_msg_userauth_failure(int partial, int incrfail);
void send_msg_userauth_success();
void svr_auth_password();
void svr_auth_pubkey();
void svr_auth_pam();
void send_msg_userauth_success(void);
void send_msg_userauth_banner(buffer *msg);
void svr_auth_password(void);
void svr_auth_pubkey(void);
void svr_auth_pam(void);
#ifdef ENABLE_SVR_PUBKEY_OPTIONS
int svr_pubkey_allows_agentfwd(void);
int svr_pubkey_allows_tcpfwd(void);
int svr_pubkey_allows_x11fwd(void);
int svr_pubkey_allows_pty(void);
void svr_pubkey_set_forced_command(struct ChanSess *chansess);
void svr_pubkey_options_cleanup(void);
int svr_add_pubkey_options(buffer *options_buf, int line_num, const char* filename);
#else
/* no option : success */
#define svr_pubkey_allows_agentfwd() 1
#define svr_pubkey_allows_tcpfwd() 1
#define svr_pubkey_allows_x11fwd() 1
#define svr_pubkey_allows_pty() 1
static inline void svr_pubkey_set_forced_command(struct ChanSess *chansess) { }
static inline void svr_pubkey_options_cleanup(void) { }
#define svr_add_pubkey_options(x,y,z) DROPBEAR_SUCCESS
#endif
/* Client functions */
void recv_msg_userauth_failure();
void recv_msg_userauth_success();
void recv_msg_userauth_specific_60();
void recv_msg_userauth_pk_ok();
void recv_msg_userauth_info_request();
void cli_get_user();
void cli_auth_getmethods();
void cli_auth_try();
void recv_msg_userauth_banner();
void cli_pubkeyfail();
void cli_auth_password();
int cli_auth_pubkey();
void cli_auth_interactive();
void recv_msg_userauth_failure(void);
void recv_msg_userauth_success(void);
void recv_msg_userauth_specific_60(void);
void recv_msg_userauth_pk_ok(void);
void recv_msg_userauth_info_request(void);
void cli_get_user(void);
void cli_auth_getmethods(void);
int cli_auth_try(void);
void recv_msg_userauth_banner(void);
void cli_pubkeyfail(void);
void cli_auth_password(void);
int cli_auth_pubkey(void);
void cli_auth_interactive(void);
char* getpass_or_cancel(char* prompt);
void cli_auth_pubkey_cleanup(void);
#define MAX_USERNAME_LEN 25 /* arbitrary for the moment */
#define AUTH_TYPE_NONE 1
#define AUTH_TYPE_PUBKEY 1 << 1
#define AUTH_TYPE_PASSWORD 1 << 2
#define AUTH_TYPE_INTERACT 1 << 3
#define AUTH_TYPE_PUBKEY (1 << 1)
#define AUTH_TYPE_PASSWORD (1 << 2)
#define AUTH_TYPE_INTERACT (1 << 3)
#define AUTH_METHOD_NONE "none"
#define AUTH_METHOD_NONE_LEN 4
@@ -77,35 +100,41 @@ char* getpass_or_cancel(char* prompt);
* relatively little extraneous bits when used for the client rather than the
* server */
struct AuthState {
char *username; /* This is the username the client presents to check. It
is updated each run through, used for auth checking */
unsigned char authtypes; /* Flags indicating which auth types are still
valid */
unsigned int failcount; /* Number of (failed) authentication attempts.*/
unsigned authdone : 1; /* 0 if we haven't authed, 1 if we have. Applies for
client and server (though has differing [obvious]
client and server (though has differing
meanings). */
unsigned perm_warn : 1; /* Server only, set if bad permissions on
~/.ssh/authorized_keys have already been
logged. */
/* These are only used for the server */
char *printableuser; /* stripped of control chars, used for logs etc */
struct passwd * pw;
uid_t pw_uid;
gid_t pw_gid;
char *pw_dir;
char *pw_shell;
char *pw_name;
char *pw_passwd;
#ifdef ENABLE_SVR_PUBKEY_OPTIONS
struct PubKeyOptions* pubkey_options;
#endif
};
struct SignKeyList;
/* A singly linked list of signing keys */
struct SignKeyList {
sign_key *key;
int type; /* The type of key */
struct SignKeyList *next;
/* filename? or the buffer? for encrypted keys, so we can later get
* the private key portion */
#ifdef ENABLE_SVR_PUBKEY_OPTIONS
struct PubKeyOptions;
struct PubKeyOptions {
/* Flags */
int no_port_forwarding_flag;
int no_agent_forwarding_flag;
int no_x11_forwarding_flag;
int no_pty_flag;
/* "command=" option. */
char * forced_command;
};
#endif
#endif /* _AUTH_H_ */
#endif /* DROPBEAR_AUTH_H_ */

View File

@@ -31,7 +31,7 @@
void m_mp_init(mp_int *mp) {
if (mp_init(mp) != MP_OKAY) {
dropbear_exit("mem alloc error");
dropbear_exit("Mem alloc error");
}
}
@@ -39,37 +39,50 @@ void m_mp_init(mp_int *mp) {
* on error */
void m_mp_init_multi(mp_int *mp, ...)
{
mp_int* cur_arg = mp;
va_list args;
mp_int* cur_arg = mp;
va_list args;
va_start(args, mp); /* init args to next argument from caller */
while (cur_arg != NULL) {
if (mp_init(cur_arg) != MP_OKAY) {
dropbear_exit("mem alloc error");
}
cur_arg = va_arg(args, mp_int*);
}
va_end(args);
va_start(args, mp); /* init args to next argument from caller */
while (cur_arg != NULL) {
if (mp_init(cur_arg) != MP_OKAY) {
dropbear_exit("Mem alloc error");
}
cur_arg = va_arg(args, mp_int*);
}
va_end(args);
}
void m_mp_alloc_init_multi(mp_int **mp, ...)
{
mp_int** cur_arg = mp;
va_list args;
va_start(args, mp); /* init args to next argument from caller */
while (cur_arg != NULL) {
*cur_arg = m_malloc(sizeof(mp_int));
if (mp_init(*cur_arg) != MP_OKAY) {
dropbear_exit("Mem alloc error");
}
cur_arg = va_arg(args, mp_int**);
}
va_end(args);
}
void bytes_to_mp(mp_int *mp, const unsigned char* bytes, unsigned int len) {
if (mp_read_unsigned_bin(mp, (unsigned char*)bytes, len) != MP_OKAY) {
dropbear_exit("mem alloc error");
dropbear_exit("Mem alloc error");
}
}
/* hash the ssh representation of the mp_int mp */
void sha1_process_mp(hash_state *hs, mp_int *mp) {
int i;
void hash_process_mp(const struct ltc_hash_descriptor *hash_desc,
hash_state *hs, mp_int *mp) {
buffer * buf;
buf = buf_new(512 + 20); /* max buffer is a 4096 bit key,
plus header + some leeway*/
buf_putmpint(buf, mp);
i = buf->pos;
buf_setpos(buf, 0);
sha1_process(hs, buf_getptr(buf, i), i);
hash_desc->process(hs, buf->data, buf->len);
buf_free(buf);
}

View File

@@ -22,14 +22,16 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#ifndef _BIGNUM_H_
#define _BIGNUM_H_
#ifndef DROPBEAR_BIGNUM_H_
#define DROPBEAR_BIGNUM_H_
#include "includes.h"
#include "dbhelpers.h"
void m_mp_init(mp_int *mp);
void m_mp_init_multi(mp_int *mp, ...);
void m_mp_init_multi(mp_int *mp, ...) ATTRIB_SENTINEL;
void m_mp_alloc_init_multi(mp_int **mp, ...) ATTRIB_SENTINEL;
void bytes_to_mp(mp_int *mp, const unsigned char* bytes, unsigned int len);
void sha1_process_mp(hash_state *hs, mp_int *mp);
void hash_process_mp(const struct ltc_hash_descriptor *hash_desc,
hash_state *hs, mp_int *mp);
#endif /* _BIGNUM_H_ */
#endif /* DROPBEAR_BIGNUM_H_ */

View File

@@ -46,17 +46,15 @@ buffer* buf_new(unsigned int size) {
dropbear_exit("buf->size too big");
}
buf = (buffer*)m_malloc(sizeof(buffer));
buf = (buffer*)m_malloc(sizeof(buffer)+size);
if (size > 0) {
buf->data = (unsigned char*)m_malloc(size);
buf->data = (unsigned char*)buf + sizeof(buffer);
} else {
buf->data = NULL;
}
buf->size = size;
buf->pos = 0;
buf->len = 0;
return buf;
@@ -65,7 +63,6 @@ buffer* buf_new(unsigned int size) {
/* free the buffer's data and the buffer itself */
void buf_free(buffer* buf) {
m_free(buf->data)
m_free(buf);
}
@@ -78,17 +75,18 @@ void buf_burn(buffer* buf) {
/* resize a buffer, pos and len will be repositioned if required when
* downsizing */
void buf_resize(buffer *buf, unsigned int newsize) {
buffer* buf_resize(buffer *buf, unsigned int newsize) {
if (newsize > BUF_MAX_SIZE) {
dropbear_exit("buf->size too big");
}
buf->data = m_realloc(buf->data, newsize);
buf = m_realloc(buf, sizeof(buffer)+newsize);
buf->data = (unsigned char*)buf + sizeof(buffer);
buf->size = newsize;
buf->len = MIN(newsize, buf->len);
buf->pos = MIN(newsize, buf->pos);
return buf;
}
/* Create a copy of buf, allocating required memory etc. */
@@ -99,14 +97,16 @@ buffer* buf_newcopy(buffer* buf) {
ret = buf_new(buf->len);
ret->len = buf->len;
memcpy(ret->data, buf->data, buf->len);
if (buf->len > 0) {
memcpy(ret->data, buf->data, buf->len);
}
return ret;
}
/* Set the length of the buffer */
void buf_setlen(buffer* buf, unsigned int len) {
if (len > buf->size) {
dropbear_exit("bad buf_setlen");
dropbear_exit("Bad buf_setlen");
}
buf->len = len;
}
@@ -114,7 +114,7 @@ void buf_setlen(buffer* buf, unsigned int len) {
/* Increment the length of the buffer */
void buf_incrlen(buffer* buf, unsigned int incr) {
if (incr > BUF_MAX_INCR || buf->len + incr > buf->size) {
dropbear_exit("bad buf_incrlen");
dropbear_exit("Bad buf_incrlen");
}
buf->len += incr;
}
@@ -122,15 +122,15 @@ void buf_incrlen(buffer* buf, unsigned int incr) {
void buf_setpos(buffer* buf, unsigned int pos) {
if (pos > buf->len) {
dropbear_exit("bad buf_setpos");
dropbear_exit("Bad buf_setpos");
}
buf->pos = pos;
}
/* increment the postion by incr, increasing the buffer length if required */
/* increment the position by incr, increasing the buffer length if required */
void buf_incrwritepos(buffer* buf, unsigned int incr) {
if (incr > BUF_MAX_INCR || buf->pos + incr > buf->size) {
dropbear_exit("bad buf_incrwritepos");
dropbear_exit("Bad buf_incrwritepos");
}
buf->pos += incr;
if (buf->pos > buf->len) {
@@ -141,10 +141,11 @@ void buf_incrwritepos(buffer* buf, unsigned int incr) {
/* increment the position by incr, negative values are allowed, to
* decrement the pos*/
void buf_incrpos(buffer* buf, int incr) {
if (incr > BUF_MAX_INCR ||
(unsigned int)((int)buf->pos + incr) > buf->len
|| ((int)buf->pos + incr) < 0) {
dropbear_exit("bad buf_incrpos");
if (incr > BUF_MAX_INCR
|| incr < -BUF_MAX_INCR
|| (unsigned int)((int)buf->pos + incr) > buf->len
|| ((int)buf->pos + incr) < 0) {
dropbear_exit("Bad buf_incrpos");
}
buf->pos += incr;
}
@@ -155,7 +156,7 @@ unsigned char buf_getbyte(buffer* buf) {
/* This check is really just ==, but the >= allows us to check for the
* bad case of pos > len, which should _never_ happen. */
if (buf->pos >= buf->len) {
dropbear_exit("bad buf_getbyte");
dropbear_exit("Bad buf_getbyte");
}
return buf->data[buf->pos++];
}
@@ -184,8 +185,8 @@ void buf_putbyte(buffer* buf, unsigned char val) {
* the next len bytes from that position can be used */
unsigned char* buf_getptr(buffer* buf, unsigned int len) {
if (buf->pos + len > buf->len) {
dropbear_exit("bad buf_getptr");
if (len > BUF_MAX_INCR || buf->pos + len > buf->len) {
dropbear_exit("Bad buf_getptr");
}
return &buf->data[buf->pos];
}
@@ -194,8 +195,8 @@ unsigned char* buf_getptr(buffer* buf, unsigned int len) {
* This allows writing past the used length, but not past the size */
unsigned char* buf_getwriteptr(buffer* buf, unsigned int len) {
if (buf->pos + len > buf->size) {
dropbear_exit("bad buf_getwriteptr");
if (len > BUF_MAX_INCR || buf->pos + len > buf->size) {
dropbear_exit("Bad buf_getwriteptr");
}
return &buf->data[buf->pos];
}
@@ -203,13 +204,13 @@ unsigned char* buf_getwriteptr(buffer* buf, unsigned int len) {
/* Return a null-terminated string, it is malloced, so must be free()ed
* Note that the string isn't checked for null bytes, hence the retlen
* may be longer than what is returned by strlen */
unsigned char* buf_getstring(buffer* buf, unsigned int *retlen) {
char* buf_getstring(buffer* buf, unsigned int *retlen) {
unsigned int len;
unsigned char* ret;
char* ret;
len = buf_getint(buf);
if (len > MAX_STRING_LEN) {
dropbear_exit("string too long");
dropbear_exit("String too long");
}
if (retlen != NULL) {
@@ -223,6 +224,20 @@ unsigned char* buf_getstring(buffer* buf, unsigned int *retlen) {
return ret;
}
/* Return a string as a newly allocated buffer */
buffer * buf_getstringbuf(buffer *buf) {
buffer *ret = NULL;
unsigned int len = buf_getint(buf);
if (len > MAX_STRING_LEN) {
dropbear_exit("String too long");
}
ret = buf_new(len);
memcpy(buf_getwriteptr(ret, len), buf_getptr(buf, len), len);
buf_incrpos(buf, len);
buf_incrlen(ret, len);
return ret;
}
/* Just increment the buffer position the same as if we'd used buf_getstring,
* but don't bother copying/malloc()ing for it */
void buf_eatstring(buffer *buf) {
@@ -248,13 +263,18 @@ void buf_putint(buffer* buf, int unsigned val) {
}
/* put a SSH style string into the buffer, increasing buffer len if required */
void buf_putstring(buffer* buf, const unsigned char* str, unsigned int len) {
void buf_putstring(buffer* buf, const char* str, unsigned int len) {
buf_putint(buf, len);
buf_putbytes(buf, str, len);
buf_putbytes(buf, (const unsigned char*)str, len);
}
/* puts an entire buffer as a SSH string. ignore pos of buf_str. */
void buf_putbufstring(buffer *buf, const buffer* buf_str) {
buf_putstring(buf, (const char*)buf_str->data, buf_str->len);
}
/* put the set of len bytes into the buffer, incrementing the pos, increasing
* len if required */
void buf_putbytes(buffer *buf, const unsigned char *bytes, unsigned int len) {
@@ -268,7 +288,7 @@ void buf_putbytes(buffer *buf, const unsigned char *bytes, unsigned int len) {
void buf_putmpint(buffer* buf, mp_int * mp) {
unsigned int len, pad = 0;
TRACE(("enter buf_putmpint"))
TRACE2(("enter buf_putmpint"))
dropbear_assert(mp != NULL);
@@ -304,7 +324,7 @@ void buf_putmpint(buffer* buf, mp_int * mp) {
buf_incrwritepos(buf, len-pad);
}
TRACE(("leave buf_putmpint"))
TRACE2(("leave buf_putmpint"))
}
/* Retrieve an mp_int from the buffer.

View File

@@ -22,14 +22,15 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#ifndef _BUFFER_H_
#ifndef DROPBEAR_BUFFER_H_
#define _BUFFER_H_
#define DROPBEAR_BUFFER_H_
#include "includes.h"
struct buf {
/* don't manipulate data member outside of buffer.c - it
is a pointer into the malloc holding buffer itself */
unsigned char * data;
unsigned int len; /* the used size */
unsigned int pos;
@@ -40,7 +41,8 @@ struct buf {
typedef struct buf buffer;
buffer * buf_new(unsigned int size);
void buf_resize(buffer *buf, unsigned int newsize);
/* Possibly returns a new buffer*, like realloc() */
buffer * buf_resize(buffer *buf, unsigned int newsize);
void buf_free(buffer* buf);
void buf_burn(buffer* buf);
buffer* buf_newcopy(buffer* buf);
@@ -54,13 +56,15 @@ unsigned char buf_getbool(buffer* buf);
void buf_putbyte(buffer* buf, unsigned char val);
unsigned char* buf_getptr(buffer* buf, unsigned int len);
unsigned char* buf_getwriteptr(buffer* buf, unsigned int len);
unsigned char* buf_getstring(buffer* buf, unsigned int *retlen);
char* buf_getstring(buffer* buf, unsigned int *retlen);
buffer * buf_getstringbuf(buffer *buf);
void buf_eatstring(buffer *buf);
void buf_putint(buffer* buf, unsigned int val);
void buf_putstring(buffer* buf, const unsigned char* str, unsigned int len);
void buf_putstring(buffer* buf, const char* str, unsigned int len);
void buf_putbufstring(buffer *buf, const buffer* buf_str);
void buf_putbytes(buffer *buf, const unsigned char *bytes, unsigned int len);
void buf_putmpint(buffer* buf, mp_int * mp);
int buf_getmpint(buffer* buf, mp_int* mp);
unsigned int buf_getint(buffer* buf);
#endif /* _BUFFER_H_ */
#endif /* DROPBEAR_BUFFER_H_ */

View File

@@ -22,21 +22,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#ifndef _CHANNEL_H_
#define _CHANNEL_H_
#ifndef DROPBEAR_CHANNEL_H_
#define DROPBEAR_CHANNEL_H_
#include "includes.h"
#include "buffer.h"
#include "circbuffer.h"
/* channel->type values */
#define CHANNEL_ID_NONE 0
#define CHANNEL_ID_SESSION 1
#define CHANNEL_ID_X11 2
#define CHANNEL_ID_AGENT 3
#define CHANNEL_ID_TCPDIRECT 4
#define CHANNEL_ID_TCPFORWARDED 5
#define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED 1
#define SSH_OPEN_CONNECT_FAILED 2
#define SSH_OPEN_UNKNOWN_CHANNEL_TYPE 3
@@ -45,18 +37,17 @@
/* Not a real type */
#define SSH_OPEN_IN_PROGRESS 99
#define MAX_CHANNELS 100 /* simple mem restriction, includes each tcp/x11
connection, so can't be _too_ small */
#define CHAN_EXTEND_SIZE 3 /* how many extra slots to add when we need more */
#define RECV_MAXWINDOW 8000 /* tweak */
#define RECV_WINDOWEXTEND 1000 /* We send a "window extend" every
RECV_WINDOWEXTEND bytes */
#define RECV_MAXPACKET RECV_MAXWINDOW /* tweak */
struct ChanType;
enum dropbear_channel_prio {
DROPBEAR_CHANNEL_PRIO_INTERACTIVE, /* pty shell, x11 */
DROPBEAR_CHANNEL_PRIO_UNKNOWABLE, /* tcp - can't know what's being forwarded */
DROPBEAR_CHANNEL_PRIO_BULK, /* the rest - probably scp or something */
DROPBEAR_CHANNEL_PRIO_EARLY, /* channel is still being set up */
};
struct Channel {
unsigned int index; /* the local channel index */
@@ -66,10 +57,11 @@ struct Channel {
unsigned int recvmaxpacket, transmaxpacket;
void* typedata; /* a pointer to type specific data */
int writefd; /* read from wire, written to insecure side */
int readfd; /* read from insecure size, written to wire */
int readfd; /* read from insecure side, written to wire */
int errfd; /* used like writefd or readfd, depending if it's client or server.
Doesn't exactly belong here, but is cleaner here */
circbuffer *writebuf; /* data from the wire, for local consumption */
circbuffer *writebuf; /* data from the wire, for local consumption. Can be
initially NULL */
circbuffer *extrabuf; /* extended-data for the program - used like writebuf
but for stderr */
@@ -77,6 +69,11 @@ struct Channel {
int sent_close, recv_close;
int recv_eof, sent_eof;
/* Set after running the ChanType-specific close hander
* to ensure we don't run it twice (nor type->checkclose()). */
int close_handler_done;
struct dropbear_progress_connection *conn_pending;
int initconn; /* used for TCP forwarding, whether the channel has been
fully initialised */
@@ -86,39 +83,45 @@ struct Channel {
int flushing;
/* Used by client chansession to handle ~ escaping, NULL ignored otherwise */
void (*read_mangler)(struct Channel*, unsigned char* bytes, int *len);
const struct ChanType* type;
enum dropbear_channel_prio prio;
};
struct ChanType {
int sepfds; /* Whether this channel has seperate pipes for in/out or not */
int sepfds; /* Whether this channel has separate pipes for in/out or not */
char *name;
int (*inithandler)(struct Channel*);
int (*check_close)(struct Channel*);
void (*reqhandler)(struct Channel*);
void (*closehandler)(struct Channel*);
};
void chaninitialise(const struct ChanType *chantypes[]);
void chancleanup();
void setchannelfds(fd_set *readfd, fd_set *writefd);
void channelio(fd_set *readfd, fd_set *writefd);
struct Channel* getchannel();
struct Channel* newchannel(unsigned int remotechan,
const struct ChanType *type,
unsigned int transwindow, unsigned int transmaxpacket);
/* Callback for connect_remote */
void channel_connect_done(int result, int sock, void* user_data, const char* errstring);
void recv_msg_channel_open();
void recv_msg_channel_request();
void chaninitialise(const struct ChanType *chantypes[]);
void chancleanup(void);
void setchannelfds(fd_set *readfds, fd_set *writefds, int allow_reads);
void channelio(fd_set *readfd, fd_set *writefd);
struct Channel* getchannel(void);
/* Returns an arbitrary channel that is in a ready state - not
being initialised and no EOF in either direction. NULL if none. */
struct Channel* get_any_ready_channel(void);
void recv_msg_channel_open(void);
void recv_msg_channel_request(void);
void send_msg_channel_failure(struct Channel *channel);
void send_msg_channel_success(struct Channel *channel);
void recv_msg_channel_data();
void recv_msg_channel_extended_data();
void recv_msg_channel_window_adjust();
void recv_msg_channel_close();
void recv_msg_channel_eof();
void recv_msg_channel_data(void);
void recv_msg_channel_extended_data(void);
void recv_msg_channel_window_adjust(void);
void recv_msg_channel_close(void);
void recv_msg_channel_eof(void);
void common_recv_msg_channel_data(struct Channel *channel, int fd,
circbuffer * buf);
@@ -129,8 +132,13 @@ extern const struct ChanType clichansess;
#if defined(USING_LISTENERS) || defined(DROPBEAR_CLIENT)
int send_msg_channel_open_init(int fd, const struct ChanType *type);
void recv_msg_channel_open_confirmation();
void recv_msg_channel_open_failure();
void recv_msg_channel_open_confirmation(void);
void recv_msg_channel_open_failure(void);
#endif
void start_send_channel_request(struct Channel *channel, char *type);
#endif /* _CHANNEL_H_ */
void send_msg_request_success(void);
void send_msg_request_failure(void);
#endif /* DROPBEAR_CHANNEL_H_ */

View File

@@ -22,8 +22,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#ifndef _CHANSESSION_H_
#define _CHANSESSION_H_
#ifndef DROPBEAR_CHANSESSION_H_
#define DROPBEAR_CHANSESSION_H_
#include "loginrec.h"
#include "channel.h"
@@ -39,17 +39,24 @@ struct exitinfo {
struct ChanSess {
unsigned char * cmd; /* command to exec */
char * cmd; /* command to exec */
pid_t pid; /* child process pid */
/* pty details */
int master; /* the master terminal fd*/
int slave;
unsigned char * tty;
unsigned char * term;
char * tty;
char * term;
/* exit details */
struct exitinfo exit;
/* These are only set temporarily before forking */
/* Used to set $SSH_CONNECTION in the child session. */
char *connection_string;
/* Used to set $SSH_CLIENT in the child session. */
char *client_string;
#ifndef DISABLE_X11FWD
struct Listener * x11listener;
@@ -60,11 +67,15 @@ struct ChanSess {
unsigned char x11singleconn;
#endif
#ifndef DISABLE_AGENTFWD
#ifdef ENABLE_SVR_AGENTFWD
struct Listener * agentlistener;
char * agentfile;
char * agentdir;
#endif
#ifdef ENABLE_SVR_PUBKEY_OPTIONS
char *original_command;
#endif
};
struct ChildPid {
@@ -75,11 +86,14 @@ struct ChildPid {
void addnewvar(const char* param, const char* var);
void cli_send_chansess_request();
void cli_tty_cleanup();
void cli_chansess_winchange();
void cli_send_chansess_request(void);
void cli_tty_cleanup(void);
void cli_chansess_winchange(void);
#ifdef ENABLE_CLI_NETCAT
void cli_send_netcat_request(void);
#endif
void svr_chansessinitialise();
void svr_chansessinitialise(void);
extern const struct ChanType svrchansess;
struct SigMap {
@@ -89,4 +103,4 @@ struct SigMap {
extern const struct SigMap signames[];
#endif /* _CHANSESSION_H_ */
#endif /* DROPBEAR_CHANSESSION_H_ */

View File

@@ -33,11 +33,12 @@ circbuffer * cbuf_new(unsigned int size) {
circbuffer *cbuf = NULL;
if (size > MAX_CBUF_SIZE) {
dropbear_exit("bad cbuf size");
dropbear_exit("Bad cbuf size");
}
cbuf = (circbuffer*)m_malloc(sizeof(circbuffer));
cbuf->data = (unsigned char*)m_malloc(size);
/* data is malloced on first write */
cbuf->data = NULL;
cbuf->used = 0;
cbuf->readpos = 0;
cbuf->writepos = 0;
@@ -48,7 +49,10 @@ circbuffer * cbuf_new(unsigned int size) {
void cbuf_free(circbuffer * cbuf) {
m_free(cbuf->data);
if (cbuf->data) {
m_burn(cbuf->data, cbuf->size);
m_free(cbuf->data);
}
m_free(cbuf);
}
@@ -64,23 +68,6 @@ unsigned int cbuf_getavail(circbuffer * cbuf) {
}
unsigned int cbuf_readlen(circbuffer *cbuf) {
dropbear_assert(((2*cbuf->size)+cbuf->writepos-cbuf->readpos)%cbuf->size == cbuf->used%cbuf->size);
dropbear_assert(((2*cbuf->size)+cbuf->readpos-cbuf->writepos)%cbuf->size == (cbuf->size-cbuf->used)%cbuf->size);
if (cbuf->used == 0) {
TRACE(("cbuf_readlen: unused buffer"))
return 0;
}
if (cbuf->readpos < cbuf->writepos) {
return cbuf->writepos - cbuf->readpos;
}
return cbuf->size - cbuf->readpos;
}
unsigned int cbuf_writelen(circbuffer *cbuf) {
dropbear_assert(cbuf->used <= cbuf->size);
@@ -99,18 +86,30 @@ unsigned int cbuf_writelen(circbuffer *cbuf) {
return cbuf->size - cbuf->writepos;
}
unsigned char* cbuf_readptr(circbuffer *cbuf, unsigned int len) {
if (len > cbuf_readlen(cbuf)) {
dropbear_exit("bad cbuf read");
}
void cbuf_readptrs(circbuffer *cbuf,
unsigned char **p1, unsigned int *len1,
unsigned char **p2, unsigned int *len2) {
*p1 = &cbuf->data[cbuf->readpos];
*len1 = MIN(cbuf->used, cbuf->size - cbuf->readpos);
return &cbuf->data[cbuf->readpos];
if (*len1 < cbuf->used) {
*p2 = cbuf->data;
*len2 = cbuf->used - *len1;
} else {
*p2 = NULL;
*len2 = 0;
}
}
unsigned char* cbuf_writeptr(circbuffer *cbuf, unsigned int len) {
if (len > cbuf_writelen(cbuf)) {
dropbear_exit("bad cbuf write");
dropbear_exit("Bad cbuf write");
}
if (!cbuf->data) {
/* lazy allocation */
cbuf->data = (unsigned char*)m_malloc(cbuf->size);
}
return &cbuf->data[cbuf->writepos];
@@ -118,7 +117,7 @@ unsigned char* cbuf_writeptr(circbuffer *cbuf, unsigned int len) {
void cbuf_incrwrite(circbuffer *cbuf, unsigned int len) {
if (len > cbuf_writelen(cbuf)) {
dropbear_exit("bad cbuf write");
dropbear_exit("Bad cbuf write");
}
cbuf->used += len;
@@ -128,10 +127,6 @@ void cbuf_incrwrite(circbuffer *cbuf, unsigned int len) {
void cbuf_incrread(circbuffer *cbuf, unsigned int len) {
if (len > cbuf_readlen(cbuf)) {
dropbear_exit("bad cbuf read");
}
dropbear_assert(cbuf->used >= len);
cbuf->used -= len;
cbuf->readpos = (cbuf->readpos + len) % cbuf->size;

View File

@@ -22,8 +22,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#ifndef _CIRCBUFFER_H_
#define _CIRCBUFFER_H_
#ifndef DROPBEAR_CIRCBUFFER_H_
#define DROPBEAR_CIRCBUFFER_H_
struct circbuf {
unsigned int size;
@@ -40,10 +40,12 @@ void cbuf_free(circbuffer * cbuf);
unsigned int cbuf_getused(circbuffer * cbuf); /* how much data stored */
unsigned int cbuf_getavail(circbuffer * cbuf); /* how much we can write */
unsigned int cbuf_readlen(circbuffer *cbuf); /* max linear read len */
unsigned int cbuf_writelen(circbuffer *cbuf); /* max linear write len */
unsigned char* cbuf_readptr(circbuffer *cbuf, unsigned int len);
/* returns pointers to the two portions of the circular buffer that can be read */
void cbuf_readptrs(circbuffer *cbuf,
unsigned char **p1, unsigned int *len1,
unsigned char **p2, unsigned int *len2);
unsigned char* cbuf_writeptr(circbuffer *cbuf, unsigned int len);
void cbuf_incrwrite(circbuffer *cbuf, unsigned int len);
void cbuf_incrread(circbuffer *cbuf, unsigned int len);

309
cli-agentfwd.c Normal file
View File

@@ -0,0 +1,309 @@
/*
* Dropbear - a SSH2 server
*
* Copyright (c) 2005 Matt Johnston
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#include "includes.h"
#ifdef ENABLE_CLI_AGENTFWD
#include "agentfwd.h"
#include "session.h"
#include "ssh.h"
#include "dbutil.h"
#include "chansession.h"
#include "channel.h"
#include "packet.h"
#include "buffer.h"
#include "dbrandom.h"
#include "listener.h"
#include "runopts.h"
#include "atomicio.h"
#include "signkey.h"
#include "auth.h"
/* The protocol implemented to talk to OpenSSH's SSH2 agent is documented in
PROTOCOL.agent in recent OpenSSH source distributions (5.1p1 has it). */
static int new_agent_chan(struct Channel * channel);
const struct ChanType cli_chan_agent = {
0, /* sepfds */
"auth-agent@openssh.com",
new_agent_chan,
NULL,
NULL,
NULL
};
static int connect_agent() {
int fd = -1;
char* agent_sock = NULL;
agent_sock = getenv("SSH_AUTH_SOCK");
if (agent_sock == NULL)
return -1;
fd = connect_unix(agent_sock);
if (fd < 0) {
dropbear_log(LOG_INFO, "Failed to connect to agent");
}
return fd;
}
/* handle a request for a connection to the locally running ssh-agent
or forward. */
static int new_agent_chan(struct Channel * channel) {
int fd = -1;
if (!cli_opts.agent_fwd)
return SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
fd = connect_agent();
if (fd < 0) {
return SSH_OPEN_CONNECT_FAILED;
}
setnonblocking(fd);
ses.maxfd = MAX(ses.maxfd, fd);
channel->readfd = fd;
channel->writefd = fd;
return 0;
}
/* Sends a request to the agent, returning a newly allocated buffer
* with the response */
/* This function will block waiting for a response - it will
* only be used by client authentication (not for forwarded requests)
* won't cause problems for interactivity. */
/* Packet format (from draft-ylonen)
4 bytes Length, msb first. Does not include length itself.
1 byte Packet type. The value 255 is reserved for future extensions.
data Any data, depending on packet type. Encoding as in the ssh packet
protocol.
*/
static buffer * agent_request(unsigned char type, buffer *data) {
buffer * payload = NULL;
buffer * inbuf = NULL;
size_t readlen = 0;
ssize_t ret;
const int fd = cli_opts.agent_fd;
unsigned int data_len = 0;
if (data)
{
data_len = data->len;
}
payload = buf_new(4 + 1 + data_len);
buf_putint(payload, 1 + data_len);
buf_putbyte(payload, type);
if (data) {
buf_putbytes(payload, data->data, data->len);
}
buf_setpos(payload, 0);
ret = atomicio(write, fd, buf_getptr(payload, payload->len), payload->len);
if ((size_t)ret != payload->len) {
TRACE(("write failed fd %d for agent_request, %s", fd, strerror(errno)))
goto out;
}
buf_free(payload);
payload = NULL;
TRACE(("Wrote out bytes for agent_request"))
/* Now we read the response */
inbuf = buf_new(4);
ret = atomicio(read, fd, buf_getwriteptr(inbuf, 4), 4);
if (ret != 4) {
TRACE(("read of length failed for agent_request"))
goto out;
}
buf_setpos(inbuf, 0);
buf_setlen(inbuf, ret);
readlen = buf_getint(inbuf);
if (readlen > MAX_AGENT_REPLY) {
TRACE(("agent reply is too big"));
goto out;
}
inbuf = buf_resize(inbuf, readlen);
buf_setpos(inbuf, 0);
ret = atomicio(read, fd, buf_getwriteptr(inbuf, readlen), readlen);
if ((size_t)ret != readlen) {
TRACE(("read of data failed for agent_request"))
goto out;
}
buf_incrwritepos(inbuf, readlen);
buf_setpos(inbuf, 0);
out:
if (payload)
buf_free(payload);
return inbuf;
}
static void agent_get_key_list(m_list * ret_list)
{
buffer * inbuf = NULL;
unsigned int num = 0;
unsigned char packet_type;
unsigned int i;
int ret;
inbuf = agent_request(SSH2_AGENTC_REQUEST_IDENTITIES, NULL);
if (!inbuf) {
TRACE(("agent_request failed returning identities"))
goto out;
}
/* The reply has a format of:
byte SSH2_AGENT_IDENTITIES_ANSWER
uint32 num_keys
Followed by zero or more consecutive keys, encoded as:
string key_blob
string key_comment
*/
packet_type = buf_getbyte(inbuf);
if (packet_type != SSH2_AGENT_IDENTITIES_ANSWER) {
goto out;
}
num = buf_getint(inbuf);
for (i = 0; i < num; i++) {
sign_key * pubkey = NULL;
enum signkey_type key_type = DROPBEAR_SIGNKEY_ANY;
buffer * key_buf;
/* each public key is encoded as a string */
key_buf = buf_getstringbuf(inbuf);
pubkey = new_sign_key();
ret = buf_get_pub_key(key_buf, pubkey, &key_type);
buf_free(key_buf);
if (ret != DROPBEAR_SUCCESS) {
TRACE(("Skipping bad/unknown type pubkey from agent"));
sign_key_free(pubkey);
} else {
pubkey->type = key_type;
pubkey->source = SIGNKEY_SOURCE_AGENT;
list_append(ret_list, pubkey);
}
/* We'll ignore the comment for now. might want it later.*/
buf_eatstring(inbuf);
}
out:
if (inbuf) {
buf_free(inbuf);
inbuf = NULL;
}
}
void cli_setup_agent(struct Channel *channel) {
if (!getenv("SSH_AUTH_SOCK")) {
return;
}
start_send_channel_request(channel, "auth-agent-req@openssh.com");
/* Don't want replies */
buf_putbyte(ses.writepayload, 0);
encrypt_packet();
}
/* Returned keys are prepended to ret_list, which will
be updated. */
void cli_load_agent_keys(m_list *ret_list) {
/* agent_fd will be closed after successful auth */
cli_opts.agent_fd = connect_agent();
if (cli_opts.agent_fd < 0) {
return;
}
agent_get_key_list(ret_list);
}
void agent_buf_sign(buffer *sigblob, sign_key *key,
buffer *data_buf) {
buffer *request_data = NULL;
buffer *response = NULL;
unsigned int siglen;
int packet_type;
/* Request format
byte SSH2_AGENTC_SIGN_REQUEST
string key_blob
string data
uint32 flags
*/
request_data = buf_new(MAX_PUBKEY_SIZE + data_buf->len + 12);
buf_put_pub_key(request_data, key, key->type);
buf_putbufstring(request_data, data_buf);
buf_putint(request_data, 0);
response = agent_request(SSH2_AGENTC_SIGN_REQUEST, request_data);
if (!response) {
goto fail;
}
packet_type = buf_getbyte(response);
if (packet_type != SSH2_AGENT_SIGN_RESPONSE) {
goto fail;
}
/* Response format
byte SSH2_AGENT_SIGN_RESPONSE
string signature_blob
*/
siglen = buf_getint(response);
buf_putbytes(sigblob, buf_getptr(response, siglen), siglen);
goto cleanup;
fail:
/* XXX don't fail badly here. instead propagate a failure code back up to
the cli auth pubkey code, and just remove this key from the list of
ones to try. */
dropbear_exit("Agent failed signing key");
cleanup:
if (request_data) {
buf_free(request_data);
}
if (response) {
buf_free(response);
}
}
#endif

View File

@@ -1,99 +0,0 @@
/*
* Dropbear - a SSH2 server
* SSH client implementation
*
* Copyright (c) 2002,2003 Matt Johnston
* Copyright (c) 2004 by Mihnea Stoenescu
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#include "algo.h"
#include "dbutil.h"
/*
* The chosen [encryption | MAC | compression] algorithm to each
* direction MUST be the first algorithm on the client's list
* that is also on the server's list.
*/
algo_type * cli_buf_match_algo(buffer* buf, algo_type localalgos[],
int *goodguess) {
unsigned char * algolist = NULL;
unsigned char * remotealgos[MAX_PROPOSED_ALGO];
unsigned int len;
unsigned int count, i, j;
algo_type * ret = NULL;
*goodguess = 0;
/* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */
algolist = buf_getstring(buf, &len);
TRACE(("cli_buf_match_algo: %s", algolist))
if (len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
goto out; /* just a sanity check, no other use */
}
/* remotealgos will contain a list of the strings parsed out */
/* We will have at least one string (even if it's just "") */
remotealgos[0] = algolist;
count = 1;
/* Iterate through, replacing ','s with NULs, to split it into
* words. */
for (i = 0; i < len; i++) {
if (algolist[i] == '\0') {
/* someone is trying something strange */
goto out;
}
if (algolist[i] == ',') {
algolist[i] = '\0';
remotealgos[count] = &algolist[i+1];
count++;
}
if (count == MAX_PROPOSED_ALGO) {
break;
}
}
/* iterate and find the first match */
for (j = 0; localalgos[j].name != NULL; j++) {
if (localalgos[j].usable) {
len = strlen(localalgos[j].name);
for (i = 0; i < count; i++) {
if (len == strlen(remotealgos[i])
&& strncmp(localalgos[j].name,
remotealgos[i], len) == 0) {
if (i == 0 && j == 0) {
/* was a good guess */
*goodguess = 1;
}
ret = &localalgos[j];
goto out;
}
}
}
}
out:
m_free(algolist);
return ret;
}

View File

@@ -40,26 +40,42 @@ void cli_authinitialise() {
/* Send a "none" auth request to get available methods */
void cli_auth_getmethods() {
TRACE(("enter cli_auth_getmethods"))
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);
buf_putstring(ses.writepayload, cli_opts.username,
buf_putstring(ses.writepayload, cli_opts.username,
strlen(cli_opts.username));
buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
SSH_SERVICE_CONNECTION_LEN);
buf_putstring(ses.writepayload, "none", 4); /* 'none' method */
encrypt_packet();
TRACE(("leave cli_auth_getmethods"))
#ifdef DROPBEAR_CLI_IMMEDIATE_AUTH
/* We can't haven't two auth requests in-flight with delayed zlib mode
since if the first one succeeds then the remote side will
expect the second one to be compressed.
Race described at
http://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/zlib-openssh.html
*/
if (ses.keys->trans.algo_comp != DROPBEAR_COMP_ZLIB_DELAY) {
ses.authstate.authtypes = AUTH_TYPE_PUBKEY;
if (getenv(DROPBEAR_PASSWORD_ENV)) {
ses.authstate.authtypes |= AUTH_TYPE_PASSWORD | AUTH_TYPE_INTERACT;
}
if (cli_auth_try() == DROPBEAR_SUCCESS) {
TRACE(("skipped initial none auth query"))
/* Note that there will be two auth responses in-flight */
cli_ses.ignore_next_auth_response = 1;
}
}
#endif
TRACE(("leave cli_auth_getmethods"))
}
void recv_msg_userauth_banner() {
unsigned char* banner = NULL;
char* banner = NULL;
unsigned int bannerlen;
unsigned int i, linecount;
@@ -91,7 +107,7 @@ void recv_msg_userauth_banner() {
}
}
printf("%s\n", banner);
fprintf(stderr, "%s\n", banner);
out:
m_free(banner);
@@ -135,8 +151,8 @@ void recv_msg_userauth_specific_60() {
void recv_msg_userauth_failure() {
unsigned char * methods = NULL;
unsigned char * tok = NULL;
char * methods = NULL;
char * tok = NULL;
unsigned int methlen = 0;
unsigned int partial = 0;
unsigned int i = 0;
@@ -144,31 +160,46 @@ void recv_msg_userauth_failure() {
TRACE(("<- MSG_USERAUTH_FAILURE"))
TRACE(("enter recv_msg_userauth_failure"))
if (ses.authstate.authdone) {
TRACE(("leave recv_msg_userauth_failure, already authdone."))
return;
}
if (cli_ses.state != USERAUTH_REQ_SENT) {
/* Perhaps we should be more fatal? */
dropbear_exit("Unexpected userauth failure");
}
/* When DROPBEAR_CLI_IMMEDIATE_AUTH is set there will be an initial response for
the "none" auth request, and then a response to the immediate auth request.
We need to be careful handling them. */
if (cli_ses.ignore_next_auth_response) {
cli_ses.state = USERAUTH_REQ_SENT;
cli_ses.ignore_next_auth_response = 0;
TRACE(("leave recv_msg_userauth_failure, ignored response, state set to USERAUTH_REQ_SENT"));
return;
} else {
#ifdef ENABLE_CLI_PUBKEY_AUTH
/* If it was a pubkey auth request, we should cross that key
* off the list. */
if (cli_ses.lastauthtype == AUTH_TYPE_PUBKEY) {
cli_pubkeyfail();
}
/* If it was a pubkey auth request, we should cross that key
* off the list. */
if (cli_ses.lastauthtype == AUTH_TYPE_PUBKEY) {
cli_pubkeyfail();
}
#endif
#ifdef ENABLE_CLI_INTERACT_AUTH
/* If we get a failure message for keyboard interactive without
* receiving any request info packet, then we don't bother trying
* keyboard interactive again */
if (cli_ses.lastauthtype == AUTH_TYPE_INTERACT
&& !cli_ses.interact_request_received) {
TRACE(("setting auth_interact_failed = 1"))
cli_ses.auth_interact_failed = 1;
}
/* If we get a failure message for keyboard interactive without
* receiving any request info packet, then we don't bother trying
* keyboard interactive again */
if (cli_ses.lastauthtype == AUTH_TYPE_INTERACT
&& !cli_ses.interact_request_received) {
TRACE(("setting auth_interact_failed = 1"))
cli_ses.auth_interact_failed = 1;
}
#endif
cli_ses.lastauthtype = AUTH_TYPE_NONE;
cli_ses.state = USERAUTH_FAIL_RCVD;
cli_ses.lastauthtype = AUTH_TYPE_NONE;
}
methods = buf_getstring(ses.payload, &methlen);
@@ -221,20 +252,27 @@ void recv_msg_userauth_failure() {
}
m_free(methods);
cli_ses.state = USERAUTH_FAIL_RCVD;
TRACE(("leave recv_msg_userauth_failure"))
}
void recv_msg_userauth_success() {
/* This function can validly get called multiple times
if DROPBEAR_CLI_IMMEDIATE_AUTH is set */
TRACE(("received msg_userauth_success"))
/* Note: in delayed-zlib mode, setting authdone here
* will enable compression in the transport layer */
ses.authstate.authdone = 1;
cli_ses.state = USERAUTH_SUCCESS_RCVD;
cli_ses.lastauthtype = AUTH_TYPE_NONE;
#ifdef ENABLE_CLI_PUBKEY_AUTH
cli_auth_pubkey_cleanup();
#endif
}
void cli_auth_try() {
int cli_auth_try() {
int finished = 0;
TRACE(("enter cli_auth_try"))
@@ -250,40 +288,57 @@ void cli_auth_try() {
}
#endif
#ifdef ENABLE_CLI_INTERACT_AUTH
if (!finished && ses.authstate.authtypes & AUTH_TYPE_INTERACT) {
if (cli_ses.auth_interact_failed) {
finished = 0;
#ifdef ENABLE_CLI_PASSWORD_AUTH
if (!finished && (ses.authstate.authtypes & AUTH_TYPE_PASSWORD)) {
if (ses.keys->trans.algo_crypt->cipherdesc == NULL) {
fprintf(stderr, "Sorry, I won't let you use password auth unencrypted.\n");
} else {
cli_auth_interactive();
cli_ses.lastauthtype = AUTH_TYPE_INTERACT;
cli_auth_password();
finished = 1;
cli_ses.lastauthtype = AUTH_TYPE_PASSWORD;
}
}
#endif
#ifdef ENABLE_CLI_PASSWORD_AUTH
if (!finished && ses.authstate.authtypes & AUTH_TYPE_PASSWORD) {
cli_auth_password();
finished = 1;
cli_ses.lastauthtype = AUTH_TYPE_PASSWORD;
#ifdef ENABLE_CLI_INTERACT_AUTH
if (!finished && (ses.authstate.authtypes & AUTH_TYPE_INTERACT)) {
if (ses.keys->trans.algo_crypt->cipherdesc == NULL) {
fprintf(stderr, "Sorry, I won't let you use interactive auth unencrypted.\n");
} else {
if (!cli_ses.auth_interact_failed) {
cli_auth_interactive();
cli_ses.lastauthtype = AUTH_TYPE_INTERACT;
finished = 1;
}
}
}
#endif
TRACE(("cli_auth_try lastauthtype %d", cli_ses.lastauthtype))
if (!finished) {
dropbear_exit("No auth methods could be used.");
if (finished) {
TRACE(("leave cli_auth_try success"))
return DROPBEAR_SUCCESS;
}
TRACE(("leave cli_auth_try"))
TRACE(("leave cli_auth_try failure"))
return DROPBEAR_FAILURE;
}
#if defined(ENABLE_CLI_PASSWORD_AUTH) || defined(ENABLE_CLI_INTERACT_AUTH)
/* A helper for getpass() that exits if the user cancels. The returned
* password is statically allocated by getpass() */
char* getpass_or_cancel(char* prompt)
{
char* password = NULL;
#ifdef DROPBEAR_PASSWORD_ENV
/* Password provided in an environment var */
password = getenv(DROPBEAR_PASSWORD_ENV);
if (password)
{
return password;
}
#endif
password = getpass(prompt);
@@ -293,3 +348,4 @@ char* getpass_or_cancel(char* prompt)
}
return password;
}
#endif

View File

@@ -31,10 +31,10 @@
#ifdef ENABLE_CLI_INTERACT_AUTH
static unsigned char* get_response(unsigned char* prompt)
static char* get_response(char* prompt)
{
FILE* tty = NULL;
unsigned char* response = NULL;
char* response = NULL;
/* not a password, but a reasonable limit */
char buf[DROPBEAR_MAX_CLI_PASS];
char* ret = NULL;
@@ -50,13 +50,13 @@ static unsigned char* get_response(unsigned char* prompt)
}
if (ret == NULL) {
response = (unsigned char*)m_strdup("");
response = m_strdup("");
} else {
unsigned int buflen = strlen(buf);
/* fgets includes newlines */
if (buflen > 0 && buf[buflen-1] == '\n')
buf[buflen-1] = '\0';
response = (unsigned char*)m_strdup(buf);
response = m_strdup(buf);
}
m_burn(buf, sizeof(buf));
@@ -66,17 +66,22 @@ static unsigned char* get_response(unsigned char* prompt)
void recv_msg_userauth_info_request() {
unsigned char *name = NULL;
unsigned char *instruction = NULL;
char *name = NULL;
char *instruction = NULL;
unsigned int num_prompts = 0;
unsigned int i;
unsigned char *prompt = NULL;
char *prompt = NULL;
unsigned int echo = 0;
unsigned char *response = NULL;
char *response = NULL;
TRACE(("enter recv_msg_recv_userauth_info_request"))
/* Let the user know what password/host they are authing for */
if (!cli_ses.interact_request_received) {
fprintf(stderr, "Login for %s@%s\n", cli_opts.username,
cli_opts.remotehost);
}
cli_ses.interact_request_received = 1;
name = buf_getstring(ses.payload, NULL);
@@ -116,7 +121,7 @@ void recv_msg_userauth_info_request() {
echo = buf_getbool(ses.payload);
if (!echo) {
unsigned char* p = getpass_or_cancel(prompt);
char* p = getpass_or_cancel(prompt);
response = m_strdup(p);
m_burn(p, strlen(p));
} else {
@@ -126,6 +131,7 @@ void recv_msg_userauth_info_request() {
response_len = strlen(response);
buf_putstring(ses.writepayload, response, response_len);
m_burn(response, response_len);
m_free(prompt);
m_free(response);
}
@@ -147,7 +153,7 @@ void cli_auth_interactive() {
strlen(cli_opts.username));
/* service name */
buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
SSH_SERVICE_CONNECTION_LEN);
/* method */

View File

@@ -38,7 +38,9 @@ static int want_askpass()
char* askpass_prog = NULL;
askpass_prog = getenv("SSH_ASKPASS");
return askpass_prog && !isatty(STDIN_FILENO) && getenv("DISPLAY");
return askpass_prog &&
((!isatty(STDIN_FILENO) && getenv("DISPLAY") )
|| getenv("SSH_ASKPASS_ALWAYS"));
}
/* returns a statically allocated password from a helper app, or NULL
@@ -125,20 +127,26 @@ void cli_auth_password() {
cli_opts.username, cli_opts.remotehost);
#ifdef ENABLE_CLI_ASKPASS_HELPER
if (want_askpass())
{
password = gui_getpass(prompt);
else
if (!password) {
dropbear_exit("No password");
}
} else
#endif
{
password = getpass_or_cancel(prompt);
}
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);
buf_putstring(ses.writepayload, cli_opts.username,
strlen(cli_opts.username));
buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
SSH_SERVICE_CONNECTION_LEN);
buf_putstring(ses.writepayload, AUTH_METHOD_PASSWORD,
buf_putstring(ses.writepayload, AUTH_METHOD_PASSWORD,
AUTH_METHOD_PASSWORD_LEN);
buf_putbyte(ses.writepayload, 0); /* FALSE - so says the spec */

View File

@@ -30,6 +30,7 @@
#include "ssh.h"
#include "runopts.h"
#include "auth.h"
#include "agentfwd.h"
#ifdef ENABLE_CLI_PUBKEY_AUTH
static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign);
@@ -37,34 +38,27 @@ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign);
/* Called when we receive a SSH_MSG_USERAUTH_FAILURE for a pubkey request.
* We use it to remove the key we tried from the list */
void cli_pubkeyfail() {
struct SignKeyList *keyitem;
struct SignKeyList **previtem;
TRACE(("enter cli_pubkeyfail"))
previtem = &cli_opts.privkeys;
/* Find the key we failed with, and remove it */
for (keyitem = cli_opts.privkeys; keyitem != NULL; keyitem = keyitem->next) {
if (keyitem == cli_ses.lastprivkey) {
*previtem = keyitem->next;
m_list_elem *iter;
for (iter = cli_opts.privkeys->first; iter; iter = iter->next) {
sign_key *iter_key = (sign_key*)iter->item;
if (iter_key == cli_ses.lastprivkey)
{
/* found the failing key */
list_remove(iter);
sign_key_free(iter_key);
cli_ses.lastprivkey = NULL;
return;
}
previtem = &keyitem;
}
sign_key_free(cli_ses.lastprivkey->key); /* It won't be used again */
m_free(cli_ses.lastprivkey);
TRACE(("leave cli_pubkeyfail"))
}
void recv_msg_userauth_pk_ok() {
struct SignKeyList *keyitem = NULL;
m_list_elem *iter;
buffer* keybuf = NULL;
char* algotype = NULL;
unsigned int algolen;
int keytype;
enum signkey_type keytype;
unsigned int remotelen;
TRACE(("enter recv_msg_userauth_pk_ok"))
@@ -80,9 +74,9 @@ void recv_msg_userauth_pk_ok() {
/* Iterate through our keys, find which one it was that matched, and
* send a real request with that key */
for (keyitem = cli_opts.privkeys; keyitem != NULL; keyitem = keyitem->next) {
if (keyitem->type != keytype) {
for (iter = cli_opts.privkeys->first; iter; iter = iter->next) {
sign_key *key = (sign_key*)iter->item;
if (key->type != keytype) {
/* Types differed */
TRACE(("types differed"))
continue;
@@ -90,7 +84,7 @@ void recv_msg_userauth_pk_ok() {
/* Now we compare the contents of the key */
keybuf->pos = keybuf->len = 0;
buf_put_pub_key(keybuf, keyitem->key, keytype);
buf_put_pub_key(keybuf, key, keytype);
buf_setpos(keybuf, 0);
buf_incrpos(keybuf, 4); /* first int is the length of the remainder (ie
remotelen) which has already been taken from
@@ -114,11 +108,11 @@ void recv_msg_userauth_pk_ok() {
}
buf_free(keybuf);
if (keyitem != NULL) {
if (iter != NULL) {
TRACE(("matching key"))
/* XXX TODO: if it's an encrypted key, here we ask for their
* password */
send_msg_userauth_pubkey(keyitem->key, keytype, 1);
send_msg_userauth_pubkey((sign_key*)iter->item, keytype, 1);
} else {
TRACE(("That was whacky. We got told that a key was valid, but it didn't match our list. Sounds like dodgy code on Dropbear's part"))
}
@@ -126,11 +120,28 @@ void recv_msg_userauth_pk_ok() {
TRACE(("leave recv_msg_userauth_pk_ok"))
}
void cli_buf_put_sign(buffer* buf, sign_key *key, int type,
buffer *data_buf) {
#ifdef ENABLE_CLI_AGENTFWD
if (key->source == SIGNKEY_SOURCE_AGENT) {
/* Format the agent signature ourselves, as buf_put_sign would. */
buffer *sigblob;
sigblob = buf_new(MAX_PUBKEY_SIZE);
agent_buf_sign(sigblob, key, data_buf);
buf_putbufstring(buf, sigblob);
buf_free(sigblob);
} else
#endif /* ENABLE_CLI_AGENTFWD */
{
buf_put_sign(buf, key, type, data_buf);
}
}
/* TODO: make it take an agent reference to use as well */
static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
const char *algoname = NULL;
int algolen;
unsigned int algolen;
buffer* sigbuf = NULL;
TRACE(("enter send_msg_userauth_pubkey"))
@@ -141,10 +152,10 @@ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
buf_putstring(ses.writepayload, cli_opts.username,
strlen(cli_opts.username));
buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
SSH_SERVICE_CONNECTION_LEN);
buf_putstring(ses.writepayload, AUTH_METHOD_PUBKEY,
buf_putstring(ses.writepayload, AUTH_METHOD_PUBKEY,
AUTH_METHOD_PUBKEY_LEN);
buf_putbyte(ses.writepayload, realsign);
@@ -158,10 +169,10 @@ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
TRACE(("realsign"))
/* We put the signature as well - this contains string(session id), then
* the contents of the write payload to this point */
sigbuf = buf_new(4 + SHA1_HASH_SIZE + ses.writepayload->len);
buf_putstring(sigbuf, ses.session_id, SHA1_HASH_SIZE);
sigbuf = buf_new(4 + ses.session_id->len + ses.writepayload->len);
buf_putbufstring(sigbuf, ses.session_id);
buf_putbytes(sigbuf, ses.writepayload->data, ses.writepayload->len);
buf_put_sign(ses.writepayload, key, type, sigbuf->data, sigbuf->len);
cli_buf_put_sign(ses.writepayload, key, type, sigbuf);
buf_free(sigbuf); /* Nothing confidential in the buffer */
}
@@ -169,20 +180,43 @@ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
TRACE(("leave send_msg_userauth_pubkey"))
}
/* Returns 1 if a key was tried */
int cli_auth_pubkey() {
TRACE(("enter cli_auth_pubkey"))
if (cli_opts.privkeys != NULL) {
#ifdef ENABLE_CLI_AGENTFWD
if (!cli_opts.agent_keys_loaded) {
/* get the list of available keys from the agent */
cli_load_agent_keys(cli_opts.privkeys);
cli_opts.agent_keys_loaded = 1;
}
#endif
if (cli_opts.privkeys->first) {
sign_key * key = (sign_key*)cli_opts.privkeys->first->item;
/* Send a trial request */
send_msg_userauth_pubkey(cli_opts.privkeys->key,
cli_opts.privkeys->type, 0);
cli_ses.lastprivkey = cli_opts.privkeys;
send_msg_userauth_pubkey(key, key->type, 0);
cli_ses.lastprivkey = key;
TRACE(("leave cli_auth_pubkey-success"))
return 1;
} else {
/* no more keys left */
TRACE(("leave cli_auth_pubkey-failure"))
return 0;
}
}
void cli_auth_pubkey_cleanup() {
#ifdef ENABLE_CLI_AGENTFWD
m_close(cli_opts.agent_fd);
cli_opts.agent_fd = -1;
#endif
while (cli_opts.privkeys->first) {
sign_key * key = list_remove(cli_opts.privkeys->first);
sign_key_free(key);
}
}
#endif /* Pubkey auth */

View File

@@ -33,17 +33,17 @@
#include "runopts.h"
#include "termcodes.h"
#include "chansession.h"
#include "agentfwd.h"
static void cli_closechansess(struct Channel *channel);
static int cli_initchansess(struct Channel *channel);
static void cli_chansessreq(struct Channel *channel);
static void start_channel_request(struct Channel *channel, unsigned char *type);
static void send_chansess_pty_req(struct Channel *channel);
static void send_chansess_shell_req(struct Channel *channel);
static void cli_escape_handler(struct Channel *channel, unsigned char* buf, int *len);
static int cli_init_netcat(struct Channel *channel);
static void cli_tty_setup();
static void cli_tty_setup(void);
const struct ChanType clichansess = {
0, /* sepfds */
@@ -56,7 +56,7 @@ const struct ChanType clichansess = {
static void cli_chansessreq(struct Channel *channel) {
unsigned char* type = NULL;
char* type = NULL;
int wantreply;
TRACE(("enter cli_chansessreq"))
@@ -71,7 +71,9 @@ static void cli_chansessreq(struct Channel *channel) {
TRACE(("got exit-signal, ignoring it"))
} else {
TRACE(("unknown request '%s'", type))
send_msg_channel_failure(channel);
if (wantreply) {
send_msg_channel_failure(channel);
}
goto out;
}
@@ -82,25 +84,12 @@ out:
/* If the main session goes, we close it up */
static void cli_closechansess(struct Channel *UNUSED(channel)) {
cli_tty_cleanup(); /* Restore tty modes etc */
/* This channel hasn't gone yet, so we have > 1 */
if (ses.chancount > 1) {
dropbear_log(LOG_INFO, "Waiting for other channels to close...");
}
cli_tty_cleanup(); /* Restore tty modes etc */
}
static void start_channel_request(struct Channel *channel,
unsigned char *type) {
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_REQUEST);
buf_putint(ses.writepayload, channel->remotechan);
buf_putstring(ses.writepayload, type, strlen(type));
}
/* Taken from OpenSSH's sshtty.c:
@@ -283,11 +272,11 @@ void cli_chansess_winchange() {
static void send_chansess_pty_req(struct Channel *channel) {
unsigned char* term = NULL;
char* term = NULL;
TRACE(("enter send_chansess_pty_req"))
start_channel_request(channel, "pty-req");
start_send_channel_request(channel, "pty-req");
/* Don't want replies */
buf_putbyte(ses.writepayload, 0);
@@ -309,24 +298,28 @@ static void send_chansess_pty_req(struct Channel *channel) {
/* Set up a window-change handler */
if (signal(SIGWINCH, sigwinch_handler) == SIG_ERR) {
dropbear_exit("signal error");
dropbear_exit("Signal error");
}
TRACE(("leave send_chansess_pty_req"))
}
static void send_chansess_shell_req(struct Channel *channel) {
unsigned char* reqtype = NULL;
char* reqtype = NULL;
TRACE(("enter send_chansess_shell_req"))
if (cli_opts.cmd) {
reqtype = "exec";
if (cli_opts.is_subsystem) {
reqtype = "subsystem";
} else {
reqtype = "exec";
}
} else {
reqtype = "shell";
}
start_channel_request(channel, reqtype);
start_send_channel_request(channel, reqtype);
/* XXX TODO */
buf_putbyte(ses.writepayload, 0); /* Don't want replies */
@@ -338,9 +331,8 @@ static void send_chansess_shell_req(struct Channel *channel) {
TRACE(("leave send_chansess_shell_req"))
}
static int cli_initchansess(struct Channel *channel) {
/* Shared for normal client channel and netcat-alike */
static int cli_init_stdpipe_sess(struct Channel *channel) {
channel->writefd = STDOUT_FILENO;
setnonblocking(STDOUT_FILENO);
@@ -350,25 +342,84 @@ static int cli_initchansess(struct Channel *channel) {
channel->errfd = STDERR_FILENO;
setnonblocking(STDERR_FILENO);
channel->extrabuf = cbuf_new(RECV_MAXWINDOW);
channel->extrabuf = cbuf_new(opts.recv_window);
return 0;
}
static int cli_init_netcat(struct Channel *channel) {
channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
return cli_init_stdpipe_sess(channel);
}
static int cli_initchansess(struct Channel *channel) {
cli_init_stdpipe_sess(channel);
#ifdef ENABLE_CLI_AGENTFWD
if (cli_opts.agent_fwd) {
cli_setup_agent(channel);
}
#endif
if (cli_opts.wantpty) {
send_chansess_pty_req(channel);
channel->prio = DROPBEAR_CHANNEL_PRIO_INTERACTIVE;
} else {
channel->prio = DROPBEAR_CHANNEL_PRIO_BULK;
}
send_chansess_shell_req(channel);
if (cli_opts.wantpty) {
cli_tty_setup();
}
channel->read_mangler = cli_escape_handler;
cli_ses.last_char = '\r';
}
return 0; /* Success */
}
#ifdef ENABLE_CLI_NETCAT
static const struct ChanType cli_chan_netcat = {
0, /* sepfds */
"direct-tcpip",
cli_init_netcat, /* inithandler */
NULL,
NULL,
cli_closechansess
};
void cli_send_netcat_request() {
const char* source_host = "127.0.0.1";
const int source_port = 22;
TRACE(("enter cli_send_netcat_request"))
cli_opts.wantpty = 0;
if (send_msg_channel_open_init(STDIN_FILENO, &cli_chan_netcat)
== DROPBEAR_FAILURE) {
dropbear_exit("Couldn't open initial channel");
}
buf_putstring(ses.writepayload, cli_opts.netcat_host,
strlen(cli_opts.netcat_host));
buf_putint(ses.writepayload, cli_opts.netcat_port);
/* originator ip - localhost is accurate enough */
buf_putstring(ses.writepayload, source_host, strlen(source_host));
buf_putint(ses.writepayload, source_port);
encrypt_packet();
TRACE(("leave cli_send_netcat_request"))
}
#endif
void cli_send_chansess_request() {
TRACE(("enter cli_send_chansess_request"))
if (send_msg_channel_open_init(STDIN_FILENO, &clichansess)
== DROPBEAR_FAILURE) {
dropbear_exit("Couldn't open initial channel");
@@ -379,3 +430,58 @@ void cli_send_chansess_request() {
TRACE(("leave cli_send_chansess_request"))
}
/* returns 1 if the character should be consumed, 0 to pass through */
static int
do_escape(unsigned char c) {
switch (c) {
case '.':
dropbear_exit("Terminated");
return 1;
case 0x1a:
/* ctrl-z */
cli_tty_cleanup();
kill(getpid(), SIGTSTP);
/* after continuation */
cli_tty_setup();
cli_ses.winchange = 1;
return 1;
default:
return 0;
}
}
static
void cli_escape_handler(struct Channel* UNUSED(channel), unsigned char* buf, int *len) {
char c;
int skip_char = 0;
/* only handle escape characters if they are read one at a time. simplifies
the code and avoids nasty people putting ~. at the start of a line to paste */
if (*len != 1) {
cli_ses.last_char = 0x0;
return;
}
c = buf[0];
if (cli_ses.last_char == DROPBEAR_ESCAPE_CHAR) {
skip_char = do_escape(c);
cli_ses.last_char = 0x0;
} else {
if (c == DROPBEAR_ESCAPE_CHAR) {
if (cli_ses.last_char == '\r') {
cli_ses.last_char = DROPBEAR_ESCAPE_CHAR;
skip_char = 1;
} else {
cli_ses.last_char = 0x0;
}
} else {
cli_ses.last_char = c;
}
}
if (skip_char) {
*len = 0;
}
}

152
cli-kex.c
View File

@@ -33,44 +33,73 @@
#include "ssh.h"
#include "packet.h"
#include "bignum.h"
#include "random.h"
#include "dbrandom.h"
#include "runopts.h"
#include "signkey.h"
#include "ecc.h"
static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen);
#define MAX_KNOWNHOSTS_LINE 4500
void send_msg_kexdh_init() {
cli_ses.dh_e = (mp_int*)m_malloc(sizeof(mp_int));
cli_ses.dh_x = (mp_int*)m_malloc(sizeof(mp_int));
m_mp_init_multi(cli_ses.dh_e, cli_ses.dh_x, NULL);
gen_kexdh_vals(cli_ses.dh_e, cli_ses.dh_x);
TRACE(("send_msg_kexdh_init()"))
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT);
buf_putmpint(ses.writepayload, cli_ses.dh_e);
switch (ses.newkeys->algo_kex->mode) {
case DROPBEAR_KEX_NORMAL_DH:
if (ses.newkeys->algo_kex != cli_ses.param_kex_algo
|| !cli_ses.dh_param) {
if (cli_ses.dh_param) {
free_kexdh_param(cli_ses.dh_param);
}
cli_ses.dh_param = gen_kexdh_param();
}
buf_putmpint(ses.writepayload, &cli_ses.dh_param->pub);
break;
case DROPBEAR_KEX_ECDH:
#ifdef DROPBEAR_ECDH
if (ses.newkeys->algo_kex != cli_ses.param_kex_algo
|| !cli_ses.ecdh_param) {
if (cli_ses.ecdh_param) {
free_kexecdh_param(cli_ses.ecdh_param);
}
cli_ses.ecdh_param = gen_kexecdh_param();
}
buf_put_ecc_raw_pubkey_string(ses.writepayload, &cli_ses.ecdh_param->key);
#endif
break;
#ifdef DROPBEAR_CURVE25519
case DROPBEAR_KEX_CURVE25519:
if (ses.newkeys->algo_kex != cli_ses.param_kex_algo
|| !cli_ses.curve25519_param) {
if (cli_ses.curve25519_param) {
free_kexcurve25519_param(cli_ses.curve25519_param);
}
cli_ses.curve25519_param = gen_kexcurve25519_param();
}
buf_putstring(ses.writepayload, (const char*)cli_ses.curve25519_param->pub, CURVE25519_LEN);
#endif
break;
}
cli_ses.param_kex_algo = ses.newkeys->algo_kex;
encrypt_packet();
ses.requirenext = SSH_MSG_KEXDH_REPLY;
}
/* Handle a diffie-hellman key exchange reply. */
void recv_msg_kexdh_reply() {
DEF_MP_INT(dh_f);
sign_key *hostkey = NULL;
unsigned int type, keybloblen;
unsigned char* keyblob = NULL;
TRACE(("enter recv_msg_kexdh_reply"))
if (cli_ses.kex_state != KEXDH_INIT_SENT) {
dropbear_exit("Received out-of-order kexdhreply");
}
m_mp_init(&dh_f);
type = ses.newkeys->algo_hostkey;
TRACE(("type is %d", type))
@@ -88,19 +117,59 @@ void recv_msg_kexdh_reply() {
dropbear_exit("Bad KEX packet");
}
if (buf_getmpint(ses.payload, &dh_f) != DROPBEAR_SUCCESS) {
TRACE(("failed getting mpint"))
dropbear_exit("Bad KEX packet");
switch (ses.newkeys->algo_kex->mode) {
case DROPBEAR_KEX_NORMAL_DH:
{
DEF_MP_INT(dh_f);
m_mp_init(&dh_f);
if (buf_getmpint(ses.payload, &dh_f) != DROPBEAR_SUCCESS) {
TRACE(("failed getting mpint"))
dropbear_exit("Bad KEX packet");
}
kexdh_comb_key(cli_ses.dh_param, &dh_f, hostkey);
mp_clear(&dh_f);
}
break;
case DROPBEAR_KEX_ECDH:
#ifdef DROPBEAR_ECDH
{
buffer *ecdh_qs = buf_getstringbuf(ses.payload);
kexecdh_comb_key(cli_ses.ecdh_param, ecdh_qs, hostkey);
buf_free(ecdh_qs);
}
#endif
break;
#ifdef DROPBEAR_CURVE25519
case DROPBEAR_KEX_CURVE25519:
{
buffer *ecdh_qs = buf_getstringbuf(ses.payload);
kexcurve25519_comb_key(cli_ses.curve25519_param, ecdh_qs, hostkey);
buf_free(ecdh_qs);
}
#endif
break;
}
kexdh_comb_key(cli_ses.dh_e, cli_ses.dh_x, &dh_f, hostkey);
mp_clear(&dh_f);
mp_clear_multi(cli_ses.dh_e, cli_ses.dh_x, NULL);
m_free(cli_ses.dh_e);
m_free(cli_ses.dh_x);
if (cli_ses.dh_param) {
free_kexdh_param(cli_ses.dh_param);
cli_ses.dh_param = NULL;
}
#ifdef DROPBEAR_ECDH
if (cli_ses.ecdh_param) {
free_kexecdh_param(cli_ses.ecdh_param);
cli_ses.ecdh_param = NULL;
}
#endif
#ifdef DROPBEAR_CURVE25519
if (cli_ses.curve25519_param) {
free_kexcurve25519_param(cli_ses.curve25519_param);
cli_ses.curve25519_param = NULL;
}
#endif
if (buf_verify(ses.payload, hostkey, ses.hash, SHA1_HASH_SIZE)
!= DROPBEAR_SUCCESS) {
cli_ses.param_kex_algo = NULL;
if (buf_verify(ses.payload, hostkey, ses.hash) != DROPBEAR_SUCCESS) {
dropbear_exit("Bad hostkey signature");
}
@@ -112,22 +181,25 @@ void recv_msg_kexdh_reply() {
TRACE(("leave recv_msg_kexdh_init"))
}
static void ask_to_confirm(unsigned char* keyblob, unsigned int keybloblen) {
static void ask_to_confirm(unsigned char* keyblob, unsigned int keybloblen,
const char* algoname) {
char* fp = NULL;
FILE *tty = NULL;
char response = 'z';
int response = 'z';
fp = sign_key_fingerprint(keyblob, keybloblen);
if (cli_opts.always_accept_key) {
fprintf(stderr, "\nHost '%s' key accepted unconditionally.\n(fingerprint %s)\n",
dropbear_log(LOG_INFO, "\nHost '%s' key accepted unconditionally.\n(%s fingerprint %s)\n",
cli_opts.remotehost,
algoname,
fp);
m_free(fp);
return;
}
fprintf(stderr, "\nHost '%s' is not in the trusted hosts file.\n(fingerprint %s)\nDo you want to continue connecting? (y/n)\n",
fprintf(stderr, "\nHost '%s' is not in the trusted hosts file.\n(%s fingerprint %s)\nDo you want to continue connecting? (y/n) ",
cli_opts.remotehost,
algoname,
fp);
m_free(fp);
@@ -217,16 +289,22 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
buffer * line = NULL;
int ret;
if (cli_opts.no_hostkey_check) {
dropbear_log(LOG_INFO, "Caution, skipping hostkey check for %s\n", cli_opts.remotehost);
return;
}
algoname = signkey_name_from_type(ses.newkeys->algo_hostkey, &algolen);
hostsfile = open_known_hosts_file(&readonly);
if (!hostsfile) {
ask_to_confirm(keyblob, keybloblen);
ask_to_confirm(keyblob, keybloblen, algoname);
/* ask_to_confirm will exit upon failure */
return;
}
line = buf_new(MAX_KNOWNHOSTS_LINE);
hostlen = strlen(cli_opts.remotehost);
algoname = signkey_name_from_type(ses.newkeys->algo_hostkey, &algolen);
do {
if (buf_getline(line, hostsfile) == DROPBEAR_FAILURE) {
@@ -244,9 +322,8 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
}
/* Compare hostnames */
if (strncmp(cli_opts.remotehost, buf_getptr(line, hostlen),
if (strncmp(cli_opts.remotehost, (const char *) buf_getptr(line, hostlen),
hostlen) != 0) {
TRACE(("hosts don't match"))
continue;
}
@@ -257,7 +334,7 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
continue;
}
if (strncmp(buf_getptr(line, algolen), algoname, algolen) != 0) {
if (strncmp((const char *) buf_getptr(line, algolen), algoname, algolen) != 0) {
TRACE(("algo doesn't match"))
continue;
}
@@ -269,7 +346,7 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
}
/* Now we're at the interesting hostkey */
ret = cmp_base64_key(keyblob, keybloblen, algoname, algolen,
ret = cmp_base64_key(keyblob, keybloblen, (const unsigned char *) algoname, algolen,
line, &fingerprint);
if (ret == DROPBEAR_SUCCESS) {
@@ -280,17 +357,18 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
/* The keys didn't match. eep. Note that we're "leaking"
the fingerprint strings here, but we're exiting anyway */
dropbear_exit("\n\nHost key mismatch for %s !\n"
dropbear_exit("\n\n%s host key mismatch for %s !\n"
"Fingerprint is %s\n"
"Expected %s\n"
"If you know that the host key is correct you can\nremove the bad entry from ~/.ssh/known_hosts",
algoname,
cli_opts.remotehost,
sign_key_fingerprint(keyblob, keybloblen),
fingerprint ? fingerprint : "UNKNOWN");
} while (1); /* keep going 'til something happens */
/* Key doesn't exist yet */
ask_to_confirm(keyblob, keybloblen);
ask_to_confirm(keyblob, keybloblen, algoname);
/* If we get here, they said yes */
@@ -304,12 +382,11 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
fseek(hostsfile, 0, SEEK_END); /* In case it wasn't opened append */
buf_setpos(line, 0);
buf_setlen(line, 0);
buf_putbytes(line, ses.remotehost, hostlen);
buf_putbytes(line, (const unsigned char *) cli_opts.remotehost, hostlen);
buf_putbyte(line, ' ');
buf_putbytes(line, algoname, algolen);
buf_putbytes(line, (const unsigned char *) algoname, algolen);
buf_putbyte(line, ' ');
len = line->size - line->pos;
TRACE(("keybloblen %d, len %d", keybloblen, len))
/* The only failure with base64 is buffer_overflow, but buf_getwriteptr
* will die horribly in the case anyway */
base64_encode(keyblob, keybloblen, buf_getwriteptr(line, len), &len);
@@ -327,4 +404,5 @@ out:
if (line != NULL) {
buf_free(line);
}
m_free(fingerprint);
}

View File

@@ -28,10 +28,18 @@
#include "dbutil.h"
#include "runopts.h"
#include "session.h"
#include "dbrandom.h"
#include "crypto_desc.h"
#include "netio.h"
static void cli_dropbear_exit(int exitcode, const char* format, va_list param);
static void cli_dropbear_exit(int exitcode, const char* format, va_list param) ATTRIB_NORETURN;
static void cli_dropbear_log(int priority, const char* format, va_list param);
#ifdef ENABLE_CLI_PROXYCMD
static void cli_proxy_cmd(int *sock_in, int *sock_out, pid_t *pid_out);
static void kill_proxy_sighandler(int signo);
#endif
#if defined(DBMULTI_dbclient) || !defined(DROPBEAR_MULTI)
#if defined(DBMULTI_dbclient) && defined(DROPBEAR_MULTI)
int cli_main(int argc, char ** argv) {
@@ -39,18 +47,25 @@ int cli_main(int argc, char ** argv) {
int main(int argc, char ** argv) {
#endif
int sock;
char* error = NULL;
char* hostandport;
int len;
int sock_in, sock_out;
struct dropbear_progress_connection *progress = NULL;
_dropbear_exit = cli_dropbear_exit;
_dropbear_log = cli_dropbear_log;
disallow_core();
seedrandom();
crypto_init();
cli_getopts(argc, argv);
#ifndef DISABLE_SYSLOG
if (opts.usingsyslog) {
startsyslog("dbclient");
}
#endif
TRACE(("user='%s' host='%s' port='%s'", cli_opts.username,
cli_opts.remotehost, cli_opts.remoteport))
@@ -58,21 +73,24 @@ int main(int argc, char ** argv) {
dropbear_exit("signal() error");
}
sock = connect_remote(cli_opts.remotehost, cli_opts.remoteport,
0, &error);
if (sock < 0) {
dropbear_exit("%s", error);
pid_t proxy_cmd_pid = 0;
#ifdef ENABLE_CLI_PROXYCMD
if (cli_opts.proxycmd) {
cli_proxy_cmd(&sock_in, &sock_out, &proxy_cmd_pid);
m_free(cli_opts.proxycmd);
if (signal(SIGINT, kill_proxy_sighandler) == SIG_ERR ||
signal(SIGTERM, kill_proxy_sighandler) == SIG_ERR ||
signal(SIGHUP, kill_proxy_sighandler) == SIG_ERR) {
dropbear_exit("signal() error");
}
} else
#endif
{
progress = connect_remote(cli_opts.remotehost, cli_opts.remoteport, cli_connected, &ses);
sock_in = sock_out = -1;
}
/* Set up the host:port log */
len = strlen(cli_opts.remotehost);
len += 10; /* 16 bit port and leeway*/
hostandport = (char*)m_malloc(len);
snprintf(hostandport, len, "%s:%s",
cli_opts.remotehost, cli_opts.remoteport);
cli_session(sock, hostandport);
cli_session(sock_in, sock_out, progress, proxy_cmd_pid);
/* not reached */
return -1;
@@ -80,35 +98,82 @@ int main(int argc, char ** argv) {
#endif /* DBMULTI stuff */
static void cli_dropbear_exit(int exitcode, const char* format, va_list param) {
char exitmsg[150];
char fullmsg[300];
char fmtbuf[300];
/* Note that exit message must be rendered before session cleanup */
/* Render the formatted exit message */
vsnprintf(exitmsg, sizeof(exitmsg), format, param);
/* Add the prefix depending on session/auth state */
if (!sessinitdone) {
snprintf(fmtbuf, sizeof(fmtbuf), "exited: %s",
format);
snprintf(fullmsg, sizeof(fullmsg), "Exited: %s", exitmsg);
} else {
snprintf(fmtbuf, sizeof(fmtbuf),
"connection to %s@%s:%s exited: %s",
snprintf(fullmsg, sizeof(fullmsg),
"Connection to %s@%s:%s exited: %s",
cli_opts.username, cli_opts.remotehost,
cli_opts.remoteport, format);
cli_opts.remoteport, exitmsg);
}
/* Do the cleanup first, since then the terminal will be reset */
cli_session_cleanup();
common_session_cleanup();
_dropbear_log(LOG_INFO, fmtbuf, param);
session_cleanup();
/* Avoid printing onwards from terminal cruft */
fprintf(stderr, "\n");
dropbear_log(LOG_INFO, "%s", fullmsg);
exit(exitcode);
}
static void cli_dropbear_log(int UNUSED(priority),
static void cli_dropbear_log(int priority,
const char* format, va_list param) {
char printbuf[1024];
vsnprintf(printbuf, sizeof(printbuf), format, param);
fprintf(stderr, "%s: %s\n", cli_opts.progname, printbuf);
#ifndef DISABLE_SYSLOG
if (opts.usingsyslog) {
syslog(priority, "%s", printbuf);
}
#endif
fprintf(stderr, "%s: %s\n", cli_opts.progname, printbuf);
fflush(stderr);
}
static void exec_proxy_cmd(void *user_data_cmd) {
const char *cmd = user_data_cmd;
char *usershell;
usershell = m_strdup(get_user_shell());
run_shell_command(cmd, ses.maxfd, usershell);
dropbear_exit("Failed to run '%s'\n", cmd);
}
#ifdef ENABLE_CLI_PROXYCMD
static void cli_proxy_cmd(int *sock_in, int *sock_out, pid_t *pid_out) {
char * ex_cmd = NULL;
size_t ex_cmdlen;
int ret;
fill_passwd(cli_opts.own_user);
ex_cmdlen = strlen(cli_opts.proxycmd) + 6; /* "exec " + command + '\0' */
ex_cmd = m_malloc(ex_cmdlen);
snprintf(ex_cmd, ex_cmdlen, "exec %s", cli_opts.proxycmd);
ret = spawn_command(exec_proxy_cmd, ex_cmd,
sock_out, sock_in, NULL, pid_out);
m_free(ex_cmd);
if (ret == DROPBEAR_FAILURE) {
dropbear_exit("Failed running proxy command");
*sock_in = *sock_out = -1;
}
}
static void kill_proxy_sighandler(int UNUSED(signo)) {
kill_proxy_command();
_exit(1);
}
#endif /* ENABLE_CLI_PROXYCMD */

View File

@@ -29,23 +29,33 @@
#include "dbutil.h"
#include "algo.h"
#include "tcpfwd.h"
#include "list.h"
cli_runopts cli_opts; /* GLOBAL */
static void printhelp();
static void parsehostname(char* userhostarg);
static void printhelp(void);
static void parse_hostname(const char* orighostarg);
static void parse_multihop_hostname(const char* orighostarg, const char* argv0);
static void fill_own_user(void);
#ifdef ENABLE_CLI_PUBKEY_AUTH
static void loadidentityfile(const char* filename);
static void loadidentityfile(const char* filename, int warnfail);
#endif
#ifdef ENABLE_CLI_ANYTCPFWD
static void addforward(char* str, struct TCPFwdList** fwdlist);
static void addforward(const char* str, m_list *fwdlist);
#endif
#ifdef ENABLE_CLI_NETCAT
static void add_netcat(const char *str);
#endif
static void add_extendedopt(const char *str);
static void printhelp() {
fprintf(stderr, "Dropbear client v%s\n"
"Usage: %s [options] [user@]host [command]\n"
"Options are:\n"
fprintf(stderr, "Dropbear SSH client v%s https://matt.ucc.asn.au/dropbear/dropbear.html\n"
#ifdef ENABLE_CLI_MULTIHOP
"Usage: %s [options] [user@]host[/port][,[user@]host/port],...] [command]\n"
#else
"Usage: %s [options] [user@]host[/port] [command]\n"
#endif
"-p <remoteport>\n"
"-l <username>\n"
"-t Allocate a pty\n"
@@ -53,38 +63,76 @@ static void printhelp() {
"-N Don't run a remote command\n"
"-f Run in background after auth\n"
"-y Always accept remote host key if unknown\n"
"-y -y Don't perform any remote host key checking (caution)\n"
"-s Request a subsystem (use by external sftp)\n"
"-o option Set option in OpenSSH-like format ('-o help' to list options)\n"
#ifdef ENABLE_CLI_PUBKEY_AUTH
"-i <identityfile> (multiple allowed)\n"
"-i <identityfile> (multiple allowed, default %s)\n"
#endif
#ifdef ENABLE_CLI_AGENTFWD
"-A Enable agent auth forwarding\n"
#endif
#ifdef ENABLE_CLI_LOCALTCPFWD
"-L <listenport:remotehost:remoteport> Local port forwarding\n"
"-L <[listenaddress:]listenport:remotehost:remoteport> Local port forwarding\n"
"-g Allow remote hosts to connect to forwarded ports\n"
#endif
#ifdef ENABLE_CLI_REMOTETCPFWD
"-R <listenport:remotehost:remoteport> Remote port forwarding\n"
"-R <[listenaddress:]listenport:remotehost:remoteport> Remote port forwarding\n"
#endif
"-W <receive_window_buffer> (default %d, larger may be faster, max 1MB)\n"
"-K <keepalive> (0 is never, default %d)\n"
"-I <idle_timeout> (0 is never, default %d)\n"
#ifdef ENABLE_CLI_NETCAT
"-B <endhost:endport> Netcat-alike forwarding\n"
#endif
#ifdef ENABLE_CLI_PROXYCMD
"-J <proxy_program> Use program pipe rather than TCP connection\n"
#endif
#ifdef ENABLE_USER_ALGO_LIST
"-c <cipher list> Specify preferred ciphers ('-c help' to list options)\n"
"-m <MAC list> Specify preferred MACs for packet verification (or '-m help')\n"
#endif
"-V Version\n"
#ifdef DEBUG_TRACE
"-v verbose\n"
"-v verbose (compiled with DEBUG_TRACE)\n"
#endif
,DROPBEAR_VERSION, cli_opts.progname);
,DROPBEAR_VERSION, cli_opts.progname,
#ifdef ENABLE_CLI_PUBKEY_AUTH
DROPBEAR_DEFAULT_CLI_AUTHKEY,
#endif
DEFAULT_RECV_WINDOW, DEFAULT_KEEPALIVE, DEFAULT_IDLE_TIMEOUT);
}
void cli_getopts(int argc, char ** argv) {
unsigned int i, j;
char ** next = 0;
unsigned int cmdlen;
enum {
OPT_EXTENDED_OPTIONS,
#ifdef ENABLE_CLI_PUBKEY_AUTH
int nextiskey = 0; /* A flag if the next argument is a keyfile */
OPT_AUTHKEY,
#endif
#ifdef ENABLE_CLI_LOCALTCPFWD
int nextislocal = 0;
OPT_LOCALTCPFWD,
#endif
#ifdef ENABLE_CLI_REMOTETCPFWD
int nextisremote = 0;
OPT_REMOTETCPFWD,
#endif
#ifdef ENABLE_CLI_NETCAT
OPT_NETCAT,
#endif
/* a flag (no arg) if 'next' is NULL, a string-valued option otherwise */
OPT_OTHER
} opt;
unsigned int cmdlen;
char* dummy = NULL; /* Not used for anything real */
char* recv_window_arg = NULL;
char* keepalive_arg = NULL;
char* idle_timeout_arg = NULL;
char *host_arg = NULL;
char c;
/* see printhelp() for options */
cli_opts.progname = argv[0];
cli_opts.remotehost = NULL;
@@ -95,62 +143,71 @@ void cli_getopts(int argc, char ** argv) {
cli_opts.backgrounded = 0;
cli_opts.wantpty = 9; /* 9 means "it hasn't been touched", gets set later */
cli_opts.always_accept_key = 0;
cli_opts.no_hostkey_check = 0;
cli_opts.is_subsystem = 0;
#ifdef ENABLE_CLI_PUBKEY_AUTH
cli_opts.privkeys = NULL;
cli_opts.privkeys = list_new();
#endif
#ifdef ENABLE_CLI_ANYTCPFWD
cli_opts.exit_on_fwd_failure = 0;
#endif
#ifdef ENABLE_CLI_LOCALTCPFWD
cli_opts.localfwds = NULL;
cli_opts.localfwds = list_new();
opts.listen_fwd_all = 0;
#endif
#ifdef ENABLE_CLI_REMOTETCPFWD
cli_opts.remotefwds = NULL;
cli_opts.remotefwds = list_new();
#endif
#ifdef ENABLE_CLI_AGENTFWD
cli_opts.agent_fwd = 0;
cli_opts.agent_fd = -1;
cli_opts.agent_keys_loaded = 0;
#endif
#ifdef ENABLE_CLI_PROXYCMD
cli_opts.proxycmd = NULL;
#endif
#ifndef DISABLE_ZLIB
opts.compress_mode = DROPBEAR_COMPRESS_ON;
#endif
#ifdef ENABLE_USER_ALGO_LIST
opts.cipher_list = NULL;
opts.mac_list = NULL;
#endif
#ifndef DISABLE_SYSLOG
opts.usingsyslog = 0;
#endif
/* not yet
opts.ipv4 = 1;
opts.ipv6 = 1;
*/
opts.recv_window = DEFAULT_RECV_WINDOW;
opts.keepalive_secs = DEFAULT_KEEPALIVE;
opts.idle_timeout_secs = DEFAULT_IDLE_TIMEOUT;
fill_own_user();
/* Iterate all the arguments */
for (i = 1; i < (unsigned int)argc; i++) {
#ifdef ENABLE_CLI_PUBKEY_AUTH
if (nextiskey) {
/* Load a hostkey since the previous argument was "-i" */
loadidentityfile(argv[i]);
nextiskey = 0;
continue;
}
#endif
#ifdef ENABLE_CLI_REMOTETCPFWD
if (nextisremote) {
TRACE(("nextisremote true"))
addforward(argv[i], &cli_opts.remotefwds);
nextisremote = 0;
continue;
}
#endif
#ifdef ENABLE_CLI_LOCALTCPFWD
if (nextislocal) {
TRACE(("nextislocal true"))
addforward(argv[i], &cli_opts.localfwds);
nextislocal = 0;
continue;
}
#endif
if (next) {
/* The previous flag set a value to assign */
*next = argv[i];
if (*next == NULL) {
dropbear_exit("Invalid null argument");
/* Handle non-flag arguments such as hostname or commands for the remote host */
if (argv[i][0] != '-')
{
if (host_arg == NULL) {
host_arg = argv[i];
continue;
}
next = NULL;
continue;
/* Commands to pass to the remote host. No more flag handling,
commands are consumed below */
break;
}
if (argv[i][0] == '-') {
/* A flag *waves* */
switch (argv[i][1]) {
/* Begins with '-' */
opt = OPT_OTHER;
for (j = 1; (c = argv[i][j]) != '\0' && !next && opt == OPT_OTHER; j++) {
switch (c) {
case 'y': /* always accept the remote hostkey */
if (cli_opts.always_accept_key) {
/* twice means no checking at all */
cli_opts.no_hostkey_check = 1;
}
cli_opts.always_accept_key = 1;
break;
case 'p': /* remoteport */
@@ -158,12 +215,7 @@ void cli_getopts(int argc, char ** argv) {
break;
#ifdef ENABLE_CLI_PUBKEY_AUTH
case 'i': /* an identityfile */
/* Keep scp happy when it changes "-i file" to "-ifile" */
if (strlen(argv[i]) > 2) {
loadidentityfile(&argv[i][2]);
} else {
nextiskey = 1;
}
opt = OPT_AUTHKEY;
break;
#endif
case 't': /* we want a pty */
@@ -178,9 +230,15 @@ void cli_getopts(int argc, char ** argv) {
case 'f':
cli_opts.backgrounded = 1;
break;
case 's':
cli_opts.is_subsystem = 1;
break;
case 'o':
opt = OPT_EXTENDED_OPTIONS;
break;
#ifdef ENABLE_CLI_LOCALTCPFWD
case 'L':
nextislocal = 1;
opt = OPT_LOCALTCPFWD;
break;
case 'g':
opts.listen_fwd_all = 1;
@@ -188,7 +246,17 @@ void cli_getopts(int argc, char ** argv) {
#endif
#ifdef ENABLE_CLI_REMOTETCPFWD
case 'R':
nextisremote = 1;
opt = OPT_REMOTETCPFWD;
break;
#endif
#ifdef ENABLE_CLI_NETCAT
case 'B':
opt = OPT_NETCAT;
break;
#endif
#ifdef ENABLE_CLI_PROXYCMD
case 'J':
next = &cli_opts.proxycmd;
break;
#endif
case 'l':
@@ -198,6 +266,31 @@ void cli_getopts(int argc, char ** argv) {
printhelp();
exit(EXIT_SUCCESS);
break;
case 'u':
/* backwards compatibility with old urandom option */
break;
case 'W':
next = &recv_window_arg;
break;
case 'K':
next = &keepalive_arg;
break;
case 'I':
next = &idle_timeout_arg;
break;
#ifdef ENABLE_CLI_AGENTFWD
case 'A':
cli_opts.agent_fwd = 1;
break;
#endif
#ifdef ENABLE_USER_ALGO_LIST
case 'c':
next = &opts.cipher_list;
break;
case 'm':
next = &opts.mac_list;
break;
#endif
#ifdef DEBUG_TRACE
case 'v':
debug_trace = 1;
@@ -205,8 +298,10 @@ void cli_getopts(int argc, char ** argv) {
#endif
case 'F':
case 'e':
#ifndef ENABLE_USER_ALGO_LIST
case 'c':
case 'm':
#endif
case 'D':
#ifndef ENABLE_CLI_REMOTETCPFWD
case 'R':
@@ -214,62 +309,112 @@ void cli_getopts(int argc, char ** argv) {
#ifndef ENABLE_CLI_LOCALTCPFWD
case 'L':
#endif
case 'o':
case 'V':
print_version();
exit(EXIT_SUCCESS);
break;
case 'b':
next = &dummy;
/* FALLTHROUGH */
default:
fprintf(stderr,
"WARNING: Ignoring unknown argument '%s'\n", argv[i]);
fprintf(stderr,
"WARNING: Ignoring unknown option -%c\n", c);
break;
} /* Switch */
/* Now we handle args where they might be "-luser" (no spaces)*/
if (next && strlen(argv[i]) > 2) {
*next = &argv[i][2];
next = NULL;
}
}
continue; /* next argument */
if (!next && opt == OPT_OTHER) /* got a flag */
continue;
} else {
TRACE(("non-flag arg: '%s'", argv[i]))
if (c == '\0') {
i++;
j = 0;
if (!argv[i])
dropbear_exit("Missing argument");
}
/* Either the hostname or commands */
if (cli_opts.remotehost == NULL) {
parsehostname(argv[i]);
} else {
/* this is part of the commands to send - after this we
* don't parse any more options, and flags are sent as the
* command */
cmdlen = 0;
for (j = i; j < (unsigned int)argc; j++) {
cmdlen += strlen(argv[j]) + 1; /* +1 for spaces */
}
/* Allocate the space */
cli_opts.cmd = (char*)m_malloc(cmdlen);
cli_opts.cmd[0] = '\0';
/* Append all the bits */
for (j = i; j < (unsigned int)argc; j++) {
strlcat(cli_opts.cmd, argv[j], cmdlen);
strlcat(cli_opts.cmd, " ", cmdlen);
}
/* It'll be null-terminated here */
/* We've eaten all the options and flags */
break;
}
if (opt == OPT_EXTENDED_OPTIONS) {
TRACE(("opt extended"))
add_extendedopt(&argv[i][j]);
}
else
#ifdef ENABLE_CLI_PUBKEY_AUTH
if (opt == OPT_AUTHKEY) {
TRACE(("opt authkey"))
loadidentityfile(&argv[i][j], 1);
}
else
#endif
#ifdef ENABLE_CLI_REMOTETCPFWD
if (opt == OPT_REMOTETCPFWD) {
TRACE(("opt remotetcpfwd"))
addforward(&argv[i][j], cli_opts.remotefwds);
}
else
#endif
#ifdef ENABLE_CLI_LOCALTCPFWD
if (opt == OPT_LOCALTCPFWD) {
TRACE(("opt localtcpfwd"))
addforward(&argv[i][j], cli_opts.localfwds);
}
else
#endif
#ifdef ENABLE_CLI_NETCAT
if (opt == OPT_NETCAT) {
TRACE(("opt netcat"))
add_netcat(&argv[i][j]);
}
else
#endif
if (next) {
/* The previous flag set a value to assign */
*next = &argv[i][j];
if (*next == NULL)
dropbear_exit("Invalid null argument");
next = NULL;
}
}
if (cli_opts.remotehost == NULL) {
/* Done with options/flags; now handle the hostname (which may not
* start with a hyphen) and optional command */
if (host_arg == NULL) { /* missing hostname */
printhelp();
exit(EXIT_FAILURE);
}
TRACE(("host is: %s", host_arg))
if (i < (unsigned int)argc) {
/* Build the command to send */
cmdlen = 0;
for (j = i; j < (unsigned int)argc; j++)
cmdlen += strlen(argv[j]) + 1; /* +1 for spaces */
/* Allocate the space */
cli_opts.cmd = (char*)m_malloc(cmdlen);
cli_opts.cmd[0] = '\0';
/* Append all the bits */
for (j = i; j < (unsigned int)argc; j++) {
strlcat(cli_opts.cmd, argv[j], cmdlen);
strlcat(cli_opts.cmd, " ", cmdlen);
}
/* It'll be null-terminated here */
TRACE(("cmd is: %s", cli_opts.cmd))
}
/* And now a few sanity checks and setup */
#ifdef ENABLE_USER_ALGO_LIST
parse_ciphers_macs();
#endif
#ifdef ENABLE_CLI_PROXYCMD
if (cli_opts.proxycmd) {
/* To match the common path of m_freeing it */
cli_opts.proxycmd = m_strdup(cli_opts.proxycmd);
}
#endif
if (cli_opts.remoteport == NULL) {
cli_opts.remoteport = "22";
@@ -287,45 +432,217 @@ void cli_getopts(int argc, char ** argv) {
if (cli_opts.backgrounded && cli_opts.cmd == NULL
&& cli_opts.no_cmd == 0) {
dropbear_exit("command required for -f");
dropbear_exit("Command required for -f");
}
if (recv_window_arg) {
opts.recv_window = atol(recv_window_arg);
if (opts.recv_window == 0 || opts.recv_window > MAX_RECV_WINDOW) {
dropbear_exit("Bad recv window '%s'", recv_window_arg);
}
}
if (keepalive_arg) {
unsigned int val;
if (m_str_to_uint(keepalive_arg, &val) == DROPBEAR_FAILURE) {
dropbear_exit("Bad keepalive '%s'", keepalive_arg);
}
opts.keepalive_secs = val;
}
if (idle_timeout_arg) {
unsigned int val;
if (m_str_to_uint(idle_timeout_arg, &val) == DROPBEAR_FAILURE) {
dropbear_exit("Bad idle_timeout '%s'", idle_timeout_arg);
}
opts.idle_timeout_secs = val;
}
#ifdef ENABLE_CLI_NETCAT
if (cli_opts.cmd && cli_opts.netcat_host) {
dropbear_log(LOG_INFO, "Ignoring command '%s' in netcat mode", cli_opts.cmd);
}
#endif
#if defined(DROPBEAR_DEFAULT_CLI_AUTHKEY) && defined(ENABLE_CLI_PUBKEY_AUTH)
{
char *expand_path = expand_homedir_path(DROPBEAR_DEFAULT_CLI_AUTHKEY);
loadidentityfile(expand_path, 0);
m_free(expand_path);
}
#endif
/* The hostname gets set up last, since
* in multi-hop mode it will require knowledge
* of other flags such as -i */
#ifdef ENABLE_CLI_MULTIHOP
parse_multihop_hostname(host_arg, argv[0]);
#else
parse_hostname(host_arg);
#endif
}
#ifdef ENABLE_CLI_PUBKEY_AUTH
static void loadidentityfile(const char* filename) {
struct SignKeyList * nextkey;
static void loadidentityfile(const char* filename, int warnfail) {
sign_key *key;
int keytype;
enum signkey_type keytype;
TRACE(("loadidentityfile %s", filename))
key = new_sign_key();
keytype = DROPBEAR_SIGNKEY_ANY;
if ( readhostkey(filename, key, &keytype) != DROPBEAR_SUCCESS ) {
fprintf(stderr, "Failed loading keyfile '%s'\n", filename);
if (warnfail) {
dropbear_log(LOG_WARNING, "Failed loading keyfile '%s'\n", filename);
}
sign_key_free(key);
} else {
nextkey = (struct SignKeyList*)m_malloc(sizeof(struct SignKeyList));
nextkey->key = key;
nextkey->next = cli_opts.privkeys;
nextkey->type = keytype;
cli_opts.privkeys = nextkey;
key->type = keytype;
key->source = SIGNKEY_SOURCE_RAW_FILE;
key->filename = m_strdup(filename);
list_append(cli_opts.privkeys, key);
}
}
#endif
#ifdef ENABLE_CLI_MULTIHOP
/* Parses a [user@]hostname argument. userhostarg is the argv[i] corresponding
* - note that it will be modified */
static void parsehostname(char* orighostarg) {
static char*
multihop_passthrough_args() {
char *ret;
int total;
unsigned int len = 0;
m_list_elem *iter;
/* Fill out -i, -y, -W options that make sense for all
* the intermediate processes */
#ifdef ENABLE_CLI_PUBKEY_AUTH
for (iter = cli_opts.privkeys->first; iter; iter = iter->next)
{
sign_key * key = (sign_key*)iter->item;
len += 3 + strlen(key->filename);
}
#endif /* ENABLE_CLI_PUBKEY_AUTH */
uid_t uid;
struct passwd *pw = NULL;
len += 30; /* space for -W <size>, terminator. */
ret = m_malloc(len);
total = 0;
if (cli_opts.no_hostkey_check)
{
int written = snprintf(ret+total, len-total, "-y -y ");
total += written;
}
else if (cli_opts.always_accept_key)
{
int written = snprintf(ret+total, len-total, "-y ");
total += written;
}
if (opts.recv_window != DEFAULT_RECV_WINDOW)
{
int written = snprintf(ret+total, len-total, "-W %u ", opts.recv_window);
total += written;
}
#ifdef ENABLE_CLI_PUBKEY_AUTH
for (iter = cli_opts.privkeys->first; iter; iter = iter->next)
{
sign_key * key = (sign_key*)iter->item;
const size_t size = len - total;
int written = snprintf(ret+total, size, "-i %s ", key->filename);
dropbear_assert((unsigned int)written < size);
total += written;
}
#endif /* ENABLE_CLI_PUBKEY_AUTH */
/* if args were passed, total will be not zero, and it will have a space at the end, so remove that */
if (total > 0)
{
total--;
}
return ret;
}
/* Sets up 'onion-forwarding' connections. This will spawn
* a separate dbclient process for each hop.
* As an example, if the cmdline is
* dbclient wrt,madako,canyons
* then we want to run:
* dbclient -J "dbclient -B canyons:22 wrt,madako" canyons
* and then the inner dbclient will recursively run:
* dbclient -J "dbclient -B madako:22 wrt" madako
* etc for as many hosts as we want.
*
* Ports for hosts can be specified as host/port.
*/
static void parse_multihop_hostname(const char* orighostarg, const char* argv0) {
char *userhostarg = NULL;
char *hostbuf = NULL;
char *last_hop = NULL;
char *remainder = NULL;
/* both scp and rsync parse a user@host argument
* and turn it into "-l user host". This breaks
* for our multihop syntax, so we suture it back together.
* This will break usernames that have both '@' and ',' in them,
* though that should be fairly uncommon. */
if (cli_opts.username
&& strchr(cli_opts.username, ',')
&& strchr(cli_opts.username, '@')) {
unsigned int len = strlen(orighostarg) + strlen(cli_opts.username) + 2;
hostbuf = m_malloc(len);
snprintf(hostbuf, len, "%s@%s", cli_opts.username, orighostarg);
} else {
hostbuf = m_strdup(orighostarg);
}
userhostarg = hostbuf;
last_hop = strrchr(userhostarg, ',');
if (last_hop) {
if (last_hop == userhostarg) {
dropbear_exit("Bad multi-hop hostnames");
}
*last_hop = '\0';
last_hop++;
remainder = userhostarg;
userhostarg = last_hop;
}
parse_hostname(userhostarg);
if (last_hop) {
/* Set up the proxycmd */
unsigned int cmd_len = 0;
char *passthrough_args = multihop_passthrough_args();
if (cli_opts.proxycmd) {
dropbear_exit("-J can't be used with multihop mode");
}
if (cli_opts.remoteport == NULL) {
cli_opts.remoteport = "22";
}
cmd_len = strlen(argv0) + strlen(remainder)
+ strlen(cli_opts.remotehost) + strlen(cli_opts.remoteport)
+ strlen(passthrough_args)
+ 30;
cli_opts.proxycmd = m_malloc(cmd_len);
snprintf(cli_opts.proxycmd, cmd_len, "%s -B %s:%s %s %s",
argv0, cli_opts.remotehost, cli_opts.remoteport,
passthrough_args, remainder);
#ifndef DISABLE_ZLIB
/* The stream will be incompressible since it's encrypted. */
opts.compress_mode = DROPBEAR_COMPRESS_OFF;
#endif
m_free(passthrough_args);
}
m_free(hostbuf);
}
#endif /* !ENABLE_CLI_MULTIHOP */
/* Parses a [user@]hostname[/port] argument. */
static void parse_hostname(const char* orighostarg) {
char *userhostarg = NULL;
char *port = NULL;
/* We probably don't want to be editing argvs */
userhostarg = m_strdup(orighostarg);
cli_opts.remotehost = strchr(userhostarg, '@');
@@ -340,14 +657,17 @@ static void parsehostname(char* orighostarg) {
}
if (cli_opts.username == NULL) {
uid = getuid();
pw = getpwuid(uid);
if (pw == NULL || pw->pw_name == NULL) {
dropbear_exit("Unknown own user");
}
cli_opts.username = m_strdup(cli_opts.own_user);
}
cli_opts.username = m_strdup(pw->pw_name);
port = strchr(cli_opts.remotehost, '^');
if (!port) {
/* legacy separator */
port = strchr(cli_opts.remotehost, '/');
}
if (port) {
*port = '\0';
cli_opts.remoteport = port+1;
}
if (cli_opts.remotehost[0] == '\0') {
@@ -355,15 +675,70 @@ static void parsehostname(char* orighostarg) {
}
}
#ifdef ENABLE_CLI_ANYTCPFWD
/* Turn a "listenport:remoteaddr:remoteport" string into into a forwarding
* set, and add it to the forwarding list */
static void addforward(char* origstr, struct TCPFwdList** fwdlist) {
#ifdef ENABLE_CLI_NETCAT
static void add_netcat(const char* origstr) {
char *portstr = NULL;
char * str = m_strdup(origstr);
portstr = strchr(str, ':');
if (portstr == NULL) {
TRACE(("No netcat port"))
goto fail;
}
*portstr = '\0';
portstr++;
if (strchr(portstr, ':')) {
TRACE(("Multiple netcat colons"))
goto fail;
}
if (m_str_to_uint(portstr, &cli_opts.netcat_port) == DROPBEAR_FAILURE) {
TRACE(("bad netcat port"))
goto fail;
}
if (cli_opts.netcat_port > 65535) {
TRACE(("too large netcat port"))
goto fail;
}
cli_opts.netcat_host = str;
return;
fail:
dropbear_exit("Bad netcat endpoint '%s'", origstr);
}
#endif
static void fill_own_user() {
uid_t uid;
struct passwd *pw = NULL;
uid = getuid();
pw = getpwuid(uid);
if (pw && pw->pw_name != NULL) {
cli_opts.own_user = m_strdup(pw->pw_name);
} else {
dropbear_log(LOG_INFO, "Warning: failed to identify current user. Trying anyway.");
cli_opts.own_user = m_strdup("unknown");
}
}
#ifdef ENABLE_CLI_ANYTCPFWD
/* Turn a "[listenaddr:]listenport:remoteaddr:remoteport" string into into a forwarding
* set, and add it to the forwarding list */
static void addforward(const char* origstr, m_list *fwdlist) {
char *part1 = NULL, *part2 = NULL, *part3 = NULL, *part4 = NULL;
char * listenaddr = NULL;
char * listenport = NULL;
char * connectport = NULL;
char * connectaddr = NULL;
struct TCPFwdList* newfwd = NULL;
char * connectport = NULL;
struct TCPFwdEntry* newfwd = NULL;
char * str = NULL;
TRACE(("enter addforward"))
@@ -372,40 +747,57 @@ static void addforward(char* origstr, struct TCPFwdList** fwdlist) {
is never free()d. */
str = m_strdup(origstr);
listenport = str;
part1 = str;
connectaddr = strchr(str, ':');
if (connectaddr == NULL) {
TRACE(("connectaddr == NULL"))
part2 = strchr(str, ':');
if (part2 == NULL) {
TRACE(("part2 == NULL"))
goto fail;
}
*connectaddr = '\0';
connectaddr++;
*part2 = '\0';
part2++;
connectport = strchr(connectaddr, ':');
if (connectport == NULL) {
TRACE(("connectport == NULL"))
part3 = strchr(part2, ':');
if (part3 == NULL) {
TRACE(("part3 == NULL"))
goto fail;
}
*connectport = '\0';
connectport++;
*part3 = '\0';
part3++;
newfwd = (struct TCPFwdList*)m_malloc(sizeof(struct TCPFwdList));
part4 = strchr(part3, ':');
if (part4) {
*part4 = '\0';
part4++;
}
if (part4) {
listenaddr = part1;
listenport = part2;
connectaddr = part3;
connectport = part4;
} else {
listenaddr = NULL;
listenport = part1;
connectaddr = part2;
connectport = part3;
}
newfwd = m_malloc(sizeof(struct TCPFwdEntry));
/* Now we check the ports - note that the port ints are unsigned,
* the check later only checks for >= MAX_PORT */
newfwd->listenport = strtol(listenport, NULL, 10);
if (errno != 0) {
TRACE(("bad listenport strtol"))
if (m_str_to_uint(listenport, &newfwd->listenport) == DROPBEAR_FAILURE) {
TRACE(("bad listenport strtoul"))
goto fail;
}
newfwd->connectport = strtol(connectport, NULL, 10);
if (errno != 0) {
TRACE(("bad connectport strtol"))
if (m_str_to_uint(connectport, &newfwd->connectport) == DROPBEAR_FAILURE) {
TRACE(("bad connectport strtoul"))
goto fail;
}
newfwd->listenaddr = listenaddr;
newfwd->connectaddr = connectaddr;
if (newfwd->listenport > 65535) {
@@ -418,8 +810,8 @@ static void addforward(char* origstr, struct TCPFwdList** fwdlist) {
goto badport;
}
newfwd->next = *fwdlist;
*fwdlist = newfwd;
newfwd->have_reply = 0;
list_append(fwdlist, newfwd);
TRACE(("leave addforward: done"))
return;
@@ -431,3 +823,76 @@ badport:
dropbear_exit("Bad TCP port in '%s'", origstr);
}
#endif
static int match_extendedopt(const char** strptr, const char *optname) {
int seen_eq = 0;
int optlen = strlen(optname);
const char *str = *strptr;
while (isspace(*str)) {
++str;
}
if (strncasecmp(str, optname, optlen) != 0) {
return DROPBEAR_FAILURE;
}
str += optlen;
while (isspace(*str) || (!seen_eq && *str == '=')) {
if (*str == '=') {
seen_eq = 1;
}
++str;
}
if (str-*strptr == optlen) {
/* matched just a prefix of optname */
return DROPBEAR_FAILURE;
}
*strptr = str;
return DROPBEAR_SUCCESS;
}
static int parse_flag_value(const char *value) {
if (strcmp(value, "yes") == 0 || strcmp(value, "true") == 0) {
return 1;
} else if (strcmp(value, "no") == 0 || strcmp(value, "false") == 0) {
return 0;
}
dropbear_exit("Bad yes/no argument '%s'", value);
}
static void add_extendedopt(const char* origstr) {
const char *optstr = origstr;
if (strcmp(origstr, "help") == 0) {
dropbear_log(LOG_INFO, "Available options:\n"
#ifdef ENABLE_CLI_ANYTCPFWD
"\tExitOnForwardFailure\n"
#endif
#ifndef DISABLE_SYSLOG
"\tUseSyslog\n"
#endif
);
exit(EXIT_SUCCESS);
}
#ifdef ENABLE_CLI_ANYTCPFWD
if (match_extendedopt(&optstr, "ExitOnForwardFailure") == DROPBEAR_SUCCESS) {
cli_opts.exit_on_fwd_failure = parse_flag_value(optstr);
return;
}
#endif
#ifndef DISABLE_SYSLOG
if (match_extendedopt(&optstr, "UseSyslog") == DROPBEAR_SUCCESS) {
opts.usingsyslog = parse_flag_value(optstr);
return;
}
#endif
dropbear_log(LOG_WARNING, "Ignoring unknown configuration option '%s'", origstr);
}

View File

@@ -1,85 +0,0 @@
/*
* Dropbear SSH
*
* Copyright (c) 2002,2003 Matt Johnston
* Copyright (c) 2004 by Mihnea Stoenescu
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#include "includes.h"
#include "service.h"
#include "dbutil.h"
#include "packet.h"
#include "buffer.h"
#include "session.h"
#include "ssh.h"
void send_msg_service_request(char* servicename) {
TRACE(("enter send_msg_service_request: servicename='%s'", servicename))
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_SERVICE_REQUEST);
buf_putstring(ses.writepayload, servicename, strlen(servicename));
encrypt_packet();
TRACE(("leave send_msg_service_request"))
}
/* This just sets up the state variables right for the main client session loop
* to deal with */
void recv_msg_service_accept() {
unsigned char* servicename;
unsigned int len;
TRACE(("enter recv_msg_service_accept"))
servicename = buf_getstring(ses.payload, &len);
/* ssh-userauth */
if (cli_ses.state == SERVICE_AUTH_REQ_SENT
&& len == SSH_SERVICE_USERAUTH_LEN
&& strncmp(SSH_SERVICE_USERAUTH, servicename, len) == 0) {
cli_ses.state = SERVICE_AUTH_ACCEPT_RCVD;
m_free(servicename);
TRACE(("leave recv_msg_service_accept: done ssh-userauth"))
return;
}
/* ssh-connection */
if (cli_ses.state == SERVICE_CONN_REQ_SENT
&& len == SSH_SERVICE_CONNECTION_LEN
&& strncmp(SSH_SERVICE_CONNECTION, servicename, len) == 0) {
if (ses.authstate.authdone != 1) {
dropbear_exit("request for connection before auth");
}
cli_ses.state = SERVICE_CONN_ACCEPT_RCVD;
m_free(servicename);
TRACE(("leave recv_msg_service_accept: done ssh-connection"))
return;
}
dropbear_exit("unrecognised service accept");
}

View File

@@ -31,15 +31,21 @@
#include "packet.h"
#include "tcpfwd.h"
#include "channel.h"
#include "random.h"
#include "dbrandom.h"
#include "service.h"
#include "runopts.h"
#include "chansession.h"
#include "agentfwd.h"
#include "crypto_desc.h"
#include "netio.h"
static void cli_remoteclosed();
static void cli_sessionloop();
static void cli_session_init();
static void cli_finished();
static void cli_remoteclosed(void) ATTRIB_NORETURN;
static void cli_sessionloop(void);
static void cli_session_init(pid_t proxy_cmd_pid);
static void cli_finished(void) ATTRIB_NORETURN;
static void recv_msg_service_accept(void);
static void cli_session_cleanup(void);
static void recv_msg_global_request_cli(void);
struct clientsession cli_ses; /* GLOBAL */
@@ -64,34 +70,60 @@ static const packettype cli_packettypes[] = {
{SSH_MSG_CHANNEL_OPEN_FAILURE, recv_msg_channel_open_failure},
{SSH_MSG_USERAUTH_BANNER, recv_msg_userauth_banner}, /* client */
{SSH_MSG_USERAUTH_SPECIFIC_60, recv_msg_userauth_specific_60}, /* client */
{SSH_MSG_GLOBAL_REQUEST, recv_msg_global_request_cli},
{SSH_MSG_CHANNEL_SUCCESS, ignore_recv_response},
{SSH_MSG_CHANNEL_FAILURE, ignore_recv_response},
#ifdef ENABLE_CLI_REMOTETCPFWD
{SSH_MSG_REQUEST_SUCCESS, cli_recv_msg_request_success}, /* client */
{SSH_MSG_REQUEST_FAILURE, cli_recv_msg_request_failure}, /* client */
#else
/* For keepalive */
{SSH_MSG_REQUEST_SUCCESS, ignore_recv_response},
{SSH_MSG_REQUEST_FAILURE, ignore_recv_response},
#endif
{0, 0} /* End */
};
static const struct ChanType *cli_chantypes[] = {
#ifdef ENABLE_CLI_REMOTETCPFWD
&cli_chan_tcpremote,
#endif
#ifdef ENABLE_CLI_AGENTFWD
&cli_chan_agent,
#endif
NULL /* Null termination */
};
void cli_session(int sock, char* remotehost) {
void cli_connected(int result, int sock, void* userdata, const char *errstring)
{
struct sshsession *myses = userdata;
if (result == DROPBEAR_FAILURE) {
dropbear_exit("Connect failed: %s", errstring);
}
myses->sock_in = myses->sock_out = sock;
update_channel_prio();
}
seedrandom();
void cli_session(int sock_in, int sock_out, struct dropbear_progress_connection *progress, pid_t proxy_cmd_pid) {
crypto_init();
common_session_init(sock_in, sock_out);
common_session_init(sock, remotehost);
if (progress) {
connect_set_writequeue(progress, &ses.writequeue);
}
chaninitialise(cli_chantypes);
/* Set up cli_ses vars */
cli_session_init();
cli_session_init(proxy_cmd_pid);
/* Ready to go */
sessinitdone = 1;
/* Exchange identification */
session_identification();
send_session_identification();
kexfirstinitialise(); /* initialise the kex state */
send_msg_kexinit();
@@ -101,7 +133,13 @@ void cli_session(int sock, char* remotehost) {
}
static void cli_session_init() {
#ifdef USE_KEX_FIRST_FOLLOWS
static void cli_send_kex_first_guess() {
send_msg_kexdh_init();
}
#endif
static void cli_session_init(pid_t proxy_cmd_pid) {
cli_ses.state = STATE_NOTHING;
cli_ses.kex_state = KEX_NOTHING;
@@ -120,44 +158,77 @@ static void cli_session_init() {
cli_ses.retval = EXIT_SUCCESS; /* Assume it's clean if we don't get a
specific exit status */
cli_ses.proxy_cmd_pid = proxy_cmd_pid;
TRACE(("proxy command PID='%d'", proxy_cmd_pid));
/* Auth */
cli_ses.lastprivkey = NULL;
cli_ses.lastauthtype = 0;
#ifdef DROPBEAR_NONE_CIPHER
cli_ses.cipher_none_after_auth = get_algo_usable(sshciphers, "none");
set_algo_usable(sshciphers, "none", 0);
#else
cli_ses.cipher_none_after_auth = 0;
#endif
/* For printing "remote host closed" for the user */
ses.remoteclosed = cli_remoteclosed;
ses.buf_match_algo = cli_buf_match_algo;
ses.extra_session_cleanup = cli_session_cleanup;
/* packet handlers */
ses.packettypes = cli_packettypes;
ses.isserver = 0;
#ifdef USE_KEX_FIRST_FOLLOWS
ses.send_kex_first_guess = cli_send_kex_first_guess;
#endif
}
static void send_msg_service_request(char* servicename) {
TRACE(("enter send_msg_service_request: servicename='%s'", servicename))
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_SERVICE_REQUEST);
buf_putstring(ses.writepayload, servicename, strlen(servicename));
encrypt_packet();
TRACE(("leave send_msg_service_request"))
}
static void recv_msg_service_accept(void) {
/* do nothing, if it failed then the server MUST have disconnected */
}
/* This function drives the progress of the session - it initiates KEX,
* service, userauth and channel requests */
static void cli_sessionloop() {
TRACE(("enter cli_sessionloop"))
TRACE2(("enter cli_sessionloop"))
if (ses.lastpacket == SSH_MSG_KEXINIT && cli_ses.kex_state == KEX_NOTHING) {
cli_ses.kex_state = KEXINIT_RCVD;
if (ses.lastpacket == 0) {
TRACE2(("exit cli_sessionloop: no real packets yet"))
return;
}
if (cli_ses.kex_state == KEXINIT_RCVD) {
if (ses.lastpacket == SSH_MSG_KEXINIT && cli_ses.kex_state == KEX_NOTHING) {
/* We initiate the KEXDH. If DH wasn't the correct type, the KEXINIT
* negotiation would have failed. */
send_msg_kexdh_init();
cli_ses.kex_state = KEXDH_INIT_SENT;
if (!ses.kexstate.our_first_follows_matches) {
send_msg_kexdh_init();
}
cli_ses.kex_state = KEXDH_INIT_SENT;
TRACE(("leave cli_sessionloop: done with KEXINIT_RCVD"))
return;
}
/* A KEX has finished, so we should go back to our KEX_NOTHING state */
if (cli_ses.kex_state != KEX_NOTHING && ses.kexstate.recvkexinit == 0
&& ses.kexstate.sentkexinit == 0) {
if (cli_ses.kex_state != KEX_NOTHING && ses.kexstate.sentnewkeys) {
cli_ses.kex_state = KEX_NOTHING;
}
@@ -167,10 +238,10 @@ static void cli_sessionloop() {
return;
}
/* We should exit if we haven't donefirstkex: we shouldn't reach here
* in normal operation */
if (ses.kexstate.donefirstkex == 0) {
TRACE(("XXX XXX might be bad! leave cli_sessionloop: haven't donefirstkex"))
/* We might reach here if we have partial packet reads or have
* received SSG_MSG_IGNORE etc. Just skip it */
TRACE2(("donefirstkex false\n"))
return;
}
@@ -180,38 +251,37 @@ static void cli_sessionloop() {
/* We've got the transport layer sorted, we now need to request
* userauth */
send_msg_service_request(SSH_SERVICE_USERAUTH);
cli_ses.state = SERVICE_AUTH_REQ_SENT;
TRACE(("leave cli_sessionloop: sent userauth service req"))
return;
/* userauth code */
case SERVICE_AUTH_ACCEPT_RCVD:
cli_auth_getmethods();
cli_ses.state = USERAUTH_REQ_SENT;
TRACE(("leave cli_sessionloop: sent userauth methods req"))
return;
case USERAUTH_REQ_SENT:
TRACE(("leave cli_sessionloop: waiting, req_sent"))
return;
case USERAUTH_FAIL_RCVD:
cli_auth_try();
if (cli_auth_try() == DROPBEAR_FAILURE) {
dropbear_exit("No auth methods could be used.");
}
cli_ses.state = USERAUTH_REQ_SENT;
TRACE(("leave cli_sessionloop: cli_auth_try"))
return;
/*
case USERAUTH_SUCCESS_RCVD:
send_msg_service_request(SSH_SERVICE_CONNECTION);
cli_ses.state = SERVICE_CONN_REQ_SENT;
TRACE(("leave cli_sessionloop: sent ssh-connection service req"))
return;
#ifndef DISABLE_SYSLOG
if (opts.usingsyslog) {
dropbear_log(LOG_INFO, "Authentication succeeded.");
}
#endif
case SERVICE_CONN_ACCEPT_RCVD:
cli_send_chansess_request();
TRACE(("leave cli_sessionloop: cli_send_chansess_request"))
cli_ses.state = SESSION_RUNNING;
return;
*/
case USERAUTH_SUCCESS_RCVD:
#ifdef DROPBEAR_NONE_CIPHER
if (cli_ses.cipher_none_after_auth)
{
set_algo_usable(sshciphers, "none", 1);
send_msg_kexinit();
}
#endif
if (cli_opts.backgrounded) {
int devnull;
@@ -219,7 +289,7 @@ static void cli_sessionloop() {
is confusing, though stdout/stderr could be useful. */
devnull = open(_PATH_DEVNULL, O_RDONLY);
if (devnull < 0) {
dropbear_exit("opening /dev/null: %d %s",
dropbear_exit("Opening /dev/null: %d %s",
errno, strerror(errno));
}
dup2(devnull, STDIN_FILENO);
@@ -229,15 +299,22 @@ static void cli_sessionloop() {
}
}
#ifdef ENABLE_CLI_NETCAT
if (cli_opts.netcat_host) {
cli_send_netcat_request();
} else
#endif
if (!cli_opts.no_cmd) {
cli_send_chansess_request();
}
#ifdef ENABLE_CLI_LOCALTCPFWD
setup_localtcp();
#endif
#ifdef ENABLE_CLI_REMOTETCPFWD
setup_remotetcp();
#endif
if (!cli_opts.no_cmd) {
cli_send_chansess_request();
}
TRACE(("leave cli_sessionloop: running"))
cli_ses.state = SESSION_RUNNING;
return;
@@ -259,21 +336,35 @@ static void cli_sessionloop() {
break;
}
TRACE(("leave cli_sessionloop: fell out"))
TRACE2(("leave cli_sessionloop: fell out"))
}
void cli_session_cleanup() {
void kill_proxy_command(void) {
/*
* Send SIGHUP to proxy command if used. We don't wait() in
* case it hangs and instead rely on init to reap the child
*/
if (cli_ses.proxy_cmd_pid > 1) {
TRACE(("killing proxy command with PID='%d'", cli_ses.proxy_cmd_pid));
kill(cli_ses.proxy_cmd_pid, SIGHUP);
}
}
static void cli_session_cleanup(void) {
if (!sessinitdone) {
return;
}
kill_proxy_command();
/* Set std{in,out,err} back to non-blocking - busybox ash dies nastily if
* we don't revert the flags */
fcntl(cli_ses.stdincopy, F_SETFL, cli_ses.stdinflags);
fcntl(cli_ses.stdoutcopy, F_SETFL, cli_ses.stdoutflags);
fcntl(cli_ses.stderrcopy, F_SETFL, cli_ses.stderrflags);
/* Ignore return value since there's nothing we can do */
(void)fcntl(cli_ses.stdincopy, F_SETFL, cli_ses.stdinflags);
(void)fcntl(cli_ses.stdoutcopy, F_SETFL, cli_ses.stdoutflags);
(void)fcntl(cli_ses.stderrcopy, F_SETFL, cli_ses.stderrflags);
cli_tty_cleanup();
@@ -281,8 +372,7 @@ void cli_session_cleanup() {
static void cli_finished() {
cli_session_cleanup();
common_session_cleanup();
session_cleanup();
fprintf(stderr, "Connection to %s@%s:%s closed.\n", cli_opts.username,
cli_opts.remotehost, cli_opts.remoteport);
exit(cli_ses.retval);
@@ -294,18 +384,20 @@ static void cli_remoteclosed() {
/* XXX TODO perhaps print a friendlier message if we get this but have
* already sent/received disconnect message(s) ??? */
close(ses.sock);
ses.sock = -1;
dropbear_exit("remote closed the connection");
m_close(ses.sock_in);
m_close(ses.sock_out);
ses.sock_in = -1;
ses.sock_out = -1;
dropbear_exit("Remote closed the connection");
}
/* Operates in-place turning dirty (untrusted potentially containing control
* characters) text into clean text.
* Note: this is safe only with ascii - other charsets could have problems. */
void cleantext(unsigned char* dirtytext) {
void cleantext(char* dirtytext) {
unsigned int i, j;
unsigned char c;
char c;
j = 0;
for (i = 0; dirtytext[i] != '\0'; i++) {
@@ -320,3 +412,9 @@ void cleantext(unsigned char* dirtytext) {
/* Null terminate */
dirtytext[j] = '\0';
}
static void recv_msg_global_request_cli(void) {
TRACE(("recv_msg_global_request_cli"))
/* Send a proper rejection */
send_msg_request_failure();
}

View File

@@ -30,6 +30,7 @@
#include "runopts.h"
#include "session.h"
#include "ssh.h"
#include "netio.h"
#ifdef ENABLE_CLI_REMOTETCPFWD
static int newtcpforwarded(struct Channel * channel);
@@ -45,47 +46,66 @@ const struct ChanType cli_chan_tcpremote = {
#endif
#ifdef ENABLE_CLI_LOCALTCPFWD
static int cli_localtcp(unsigned int listenport, const char* remoteaddr,
static int cli_localtcp(const char* listenaddr,
unsigned int listenport,
const char* remoteaddr,
unsigned int remoteport);
static const struct ChanType cli_chan_tcplocal = {
1, /* sepfds */
"direct-tcpip",
NULL,
tcp_prio_inithandler,
NULL,
NULL,
NULL
};
#endif
#ifdef ENABLE_CLI_ANYTCPFWD
static void fwd_failed(const char* format, ...) ATTRIB_PRINTF(1,2);
static void fwd_failed(const char* format, ...)
{
va_list param;
va_start(param, format);
if (cli_opts.exit_on_fwd_failure) {
_dropbear_exit(EXIT_FAILURE, format, param);
} else {
_dropbear_log(LOG_WARNING, format, param);
}
va_end(param);
}
#endif
#ifdef ENABLE_CLI_LOCALTCPFWD
void setup_localtcp() {
m_list_elem *iter;
int ret;
TRACE(("enter setup_localtcp"))
if (cli_opts.localfwds == NULL) {
TRACE(("cli_opts.localfwds == NULL"))
}
while (cli_opts.localfwds != NULL) {
ret = cli_localtcp(cli_opts.localfwds->listenport,
cli_opts.localfwds->connectaddr,
cli_opts.localfwds->connectport);
for (iter = cli_opts.localfwds->first; iter; iter = iter->next) {
struct TCPFwdEntry * fwd = (struct TCPFwdEntry*)iter->item;
ret = cli_localtcp(
fwd->listenaddr,
fwd->listenport,
fwd->connectaddr,
fwd->connectport);
if (ret == DROPBEAR_FAILURE) {
dropbear_log(LOG_WARNING, "Failed local port forward %d:%s:%d",
cli_opts.localfwds->listenport,
cli_opts.localfwds->connectaddr,
cli_opts.localfwds->connectport);
}
cli_opts.localfwds = cli_opts.localfwds->next;
fwd_failed("Failed local port forward %s:%d:%s:%d",
fwd->listenaddr,
fwd->listenport,
fwd->connectaddr,
fwd->connectport);
}
}
TRACE(("leave setup_localtcp"))
}
static int cli_localtcp(unsigned int listenport, const char* remoteaddr,
static int cli_localtcp(const char* listenaddr,
unsigned int listenport,
const char* remoteaddr,
unsigned int remoteport) {
struct TCPListener* tcpinfo = NULL;
@@ -99,10 +119,17 @@ static int cli_localtcp(unsigned int listenport, const char* remoteaddr,
tcpinfo->sendaddr = m_strdup(remoteaddr);
tcpinfo->sendport = remoteport;
if (opts.listen_fwd_all) {
tcpinfo->listenaddr = m_strdup("");
} else {
tcpinfo->listenaddr = m_strdup("localhost");
if (listenaddr)
{
tcpinfo->listenaddr = m_strdup(listenaddr);
}
else
{
if (opts.listen_fwd_all) {
tcpinfo->listenaddr = m_strdup("");
} else {
tcpinfo->listenaddr = m_strdup("localhost");
}
}
tcpinfo->listenport = listenport;
@@ -120,22 +147,15 @@ static int cli_localtcp(unsigned int listenport, const char* remoteaddr,
#endif /* ENABLE_CLI_LOCALTCPFWD */
#ifdef ENABLE_CLI_REMOTETCPFWD
static void send_msg_global_request_remotetcp(int port) {
static void send_msg_global_request_remotetcp(const char *addr, int port) {
char* listenspec = NULL;
TRACE(("enter send_msg_global_request_remotetcp"))
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST);
buf_putstring(ses.writepayload, "tcpip-forward", 13);
buf_putbyte(ses.writepayload, 0);
if (opts.listen_fwd_all) {
listenspec = "";
} else {
listenspec = "localhost";
}
/* TODO: IPv6? */;
buf_putstring(ses.writepayload, listenspec, strlen(listenspec));
buf_putbyte(ses.writepayload, 1); /* want_reply */
buf_putstring(ses.writepayload, addr, strlen(addr));
buf_putint(ses.writepayload, port);
encrypt_packet();
@@ -143,73 +163,125 @@ static void send_msg_global_request_remotetcp(int port) {
TRACE(("leave send_msg_global_request_remotetcp"))
}
/* The only global success/failure messages are for remotetcp.
* Since there isn't any identifier in these messages, we have to rely on them
* being in the same order as we sent the requests. This is the ordering
* of the cli_opts.remotefwds list.
* If the requested remote port is 0 the listen port will be
* dynamically allocated by the server and the port number will be returned
* to client and the port number reported to the user. */
void cli_recv_msg_request_success() {
/* We just mark off that we have received the reply,
* so that we can report failure for later ones. */
m_list_elem * iter = NULL;
for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) {
struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item;
if (!fwd->have_reply) {
fwd->have_reply = 1;
if (fwd->listenport == 0) {
/* The server should let us know which port was allocated if we requested port 0 */
int allocport = buf_getint(ses.payload);
if (allocport > 0) {
fwd->listenport = allocport;
dropbear_log(LOG_INFO, "Allocated port %d for remote forward to %s:%d",
allocport, fwd->connectaddr, fwd->connectport);
}
}
return;
}
}
}
void cli_recv_msg_request_failure() {
m_list_elem *iter;
for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) {
struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item;
if (!fwd->have_reply) {
fwd->have_reply = 1;
fwd_failed("Remote TCP forward request failed (port %d -> %s:%d)",
fwd->listenport,
fwd->connectaddr,
fwd->connectport);
return;
}
}
}
void setup_remotetcp() {
struct TCPFwdList * iter = NULL;
m_list_elem *iter;
TRACE(("enter setup_remotetcp"))
if (cli_opts.remotefwds == NULL) {
TRACE(("cli_opts.remotefwds == NULL"))
for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) {
struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item;
if (!fwd->listenaddr)
{
/* we store the addresses so that we can compare them
when the server sends them back */
if (opts.listen_fwd_all) {
fwd->listenaddr = m_strdup("");
} else {
fwd->listenaddr = m_strdup("localhost");
}
}
send_msg_global_request_remotetcp(fwd->listenaddr, fwd->listenport);
}
iter = cli_opts.remotefwds;
while (iter != NULL) {
send_msg_global_request_remotetcp(iter->listenport);
iter = iter->next;
}
TRACE(("leave setup_remotetcp"))
}
static int newtcpforwarded(struct Channel * channel) {
char *origaddr = NULL;
unsigned int origport;
struct TCPFwdList * iter = NULL;
m_list_elem * iter = NULL;
struct TCPFwdEntry *fwd;
char portstring[NI_MAXSERV];
int sock;
int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
/* We don't care what address they connected to */
buf_eatstring(ses.payload);
origaddr = buf_getstring(ses.payload, NULL);
origport = buf_getint(ses.payload);
/* Find which port corresponds */
iter = cli_opts.remotefwds;
while (iter != NULL) {
if (origport == iter->listenport) {
/* Find which port corresponds. First try and match address as well as port,
in case they want to forward different ports separately ... */
for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) {
fwd = (struct TCPFwdEntry*)iter->item;
if (origport == fwd->listenport
&& strcmp(origaddr, fwd->listenaddr) == 0) {
break;
}
iter = iter->next;
}
if (!iter)
{
/* ... otherwise try to generically match the only forwarded port
without address (also handles ::1 vs 127.0.0.1 vs localhost case).
rfc4254 is vague about the definition of "address that was connected" */
for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) {
fwd = (struct TCPFwdEntry*)iter->item;
if (origport == fwd->listenport) {
break;
}
}
}
if (iter == NULL) {
/* We didn't request forwarding on that port */
dropbear_log(LOG_INFO, "Server send unrequested port, from port %d",
origport);
cleantext(origaddr);
dropbear_log(LOG_INFO, "Server sent unrequested forward from \"%s:%d\"",
origaddr, origport);
goto out;
}
snprintf(portstring, sizeof(portstring), "%d", iter->connectport);
sock = connect_remote(iter->connectaddr, portstring, 1, NULL);
if (sock < 0) {
TRACE(("leave newtcpdirect: sock failed"))
err = SSH_OPEN_CONNECT_FAILED;
goto out;
}
snprintf(portstring, sizeof(portstring), "%u", fwd->connectport);
channel->conn_pending = connect_remote(fwd->connectaddr, portstring, channel_connect_done, channel);
ses.maxfd = MAX(ses.maxfd, sock);
/* We don't set readfd, that will get set after the connection's
* progress succeeds */
channel->writefd = sock;
channel->initconn = 1;
channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
err = SSH_OPEN_IN_PROGRESS;
out:
m_free(origaddr);
TRACE(("leave newtcpdirect: err %d", err))
return err;
}

View File

@@ -23,38 +23,57 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#include "includes.h"
#include "algo.h"
#include "session.h"
#include "dbutil.h"
#include "dh_groups.h"
#include "ltc_prng.h"
#include "ecc.h"
/* This file (algo.c) organises the ciphers which can be used, and is used to
* decide which ciphers/hashes/compression/signing to use during key exchange*/
static int void_cipher(const unsigned char* in, unsigned char* out,
unsigned long len, void* UNUSED(cipher_state)) {
if (in != out) {
memmove(out, in, len);
}
return CRYPT_OK;
}
static int void_start(int UNUSED(cipher), const unsigned char* UNUSED(IV),
const unsigned char* UNUSED(key),
int UNUSED(keylen), int UNUSED(num_rounds), void* UNUSED(cipher_state)) {
return CRYPT_OK;
}
/* Mappings for ciphers, parameters are
{&cipher_desc, keysize, blocksize} */
/* NOTE: if keysize > 2*SHA1_HASH_SIZE, code such as hashkeys()
needs revisiting */
#ifdef DROPBEAR_AES256_CBC
/* Remember to add new ciphers/hashes to regciphers/reghashes too */
#ifdef DROPBEAR_AES256
static const struct dropbear_cipher dropbear_aes256 =
{&aes_desc, 32, 16};
#endif
#ifdef DROPBEAR_AES128_CBC
#ifdef DROPBEAR_AES128
static const struct dropbear_cipher dropbear_aes128 =
{&aes_desc, 16, 16};
#endif
#ifdef DROPBEAR_BLOWFISH_CBC
#ifdef DROPBEAR_BLOWFISH
static const struct dropbear_cipher dropbear_blowfish =
{&blowfish_desc, 16, 8};
#endif
#ifdef DROPBEAR_TWOFISH256_CBC
#ifdef DROPBEAR_TWOFISH256
static const struct dropbear_cipher dropbear_twofish256 =
{&twofish_desc, 32, 16};
#endif
#ifdef DROPBEAR_TWOFISH128_CBC
#ifdef DROPBEAR_TWOFISH128
static const struct dropbear_cipher dropbear_twofish128 =
{&twofish_desc, 16, 16};
#endif
#ifdef DROPBEAR_3DES_CBC
#ifdef DROPBEAR_3DES
static const struct dropbear_cipher dropbear_3des =
{&des3_desc, 24, 8};
#endif
@@ -63,6 +82,28 @@ static const struct dropbear_cipher dropbear_3des =
const struct dropbear_cipher dropbear_nocipher =
{NULL, 16, 8};
/* A few void* s are required to silence warnings
* about the symmetric_CBC vs symmetric_CTR cipher_state pointer */
#ifdef DROPBEAR_ENABLE_CBC_MODE
const struct dropbear_cipher_mode dropbear_mode_cbc =
{(void*)cbc_start, (void*)cbc_encrypt, (void*)cbc_decrypt};
#endif /* DROPBEAR_ENABLE_CBC_MODE */
const struct dropbear_cipher_mode dropbear_mode_none =
{void_start, void_cipher, void_cipher};
#ifdef DROPBEAR_ENABLE_CTR_MODE
/* a wrapper to make ctr_start and cbc_start look the same */
static int dropbear_big_endian_ctr_start(int cipher,
const unsigned char *IV,
const unsigned char *key, int keylen,
int num_rounds, symmetric_CTR *ctr) {
return ctr_start(cipher, IV, key, keylen, num_rounds, CTR_COUNTER_BIG_ENDIAN, ctr);
}
const struct dropbear_cipher_mode dropbear_mode_ctr =
{(void*)dropbear_big_endian_ctr_start, (void*)ctr_encrypt, (void*)ctr_decrypt};
#endif /* DROPBEAR_ENABLE_CTR_MODE */
/* Mapping of ssh hashes to libtomcrypt hashes, including keysize etc.
{&hash_desc, keysize, hashsize} */
@@ -74,6 +115,14 @@ static const struct dropbear_hash dropbear_sha1 =
static const struct dropbear_hash dropbear_sha1_96 =
{&sha1_desc, 20, 12};
#endif
#ifdef DROPBEAR_SHA2_256_HMAC
static const struct dropbear_hash dropbear_sha2_256 =
{&sha256_desc, 32, 32};
#endif
#ifdef DROPBEAR_SHA2_512_HMAC
static const struct dropbear_hash dropbear_sha2_512 =
{&sha512_desc, 64, 64};
#endif
#ifdef DROPBEAR_MD5_HMAC
static const struct dropbear_hash dropbear_md5 =
{&md5_desc, 16, 16};
@@ -83,111 +132,187 @@ const struct dropbear_hash dropbear_nohash =
{NULL, 16, 0}; /* used initially */
/* The following map ssh names to internal values */
/* The following map ssh names to internal values.
* The ordering here is important for the client - the first mode
* that is also supported by the server will get used. */
algo_type sshciphers[] = {
#ifdef DROPBEAR_AES128_CBC
{"aes128-cbc", 0, (void*)&dropbear_aes128, 1},
#ifdef DROPBEAR_ENABLE_CTR_MODE
#ifdef DROPBEAR_AES128
{"aes128-ctr", 0, &dropbear_aes128, 1, &dropbear_mode_ctr},
#endif
#ifdef DROPBEAR_3DES_CBC
{"3des-cbc", 0, (void*)&dropbear_3des, 1},
#ifdef DROPBEAR_AES256
{"aes256-ctr", 0, &dropbear_aes256, 1, &dropbear_mode_ctr},
#endif
#ifdef DROPBEAR_AES256_CBC
{"aes256-cbc", 0, (void*)&dropbear_aes256, 1},
#ifdef DROPBEAR_TWOFISH_CTR
/* twofish ctr is conditional as it hasn't been tested for interoperability, see options.h */
#ifdef DROPBEAR_TWOFISH256
{"twofish256-ctr", 0, &dropbear_twofish256, 1, &dropbear_mode_ctr},
#endif
#ifdef DROPBEAR_TWOFISH256_CBC
{"twofish256-cbc", 0, (void*)&dropbear_twofish256, 1},
{"twofish-cbc", 0, (void*)&dropbear_twofish256, 1},
#ifdef DROPBEAR_TWOFISH128
{"twofish128-ctr", 0, &dropbear_twofish128, 1, &dropbear_mode_ctr},
#endif
#ifdef DROPBEAR_TWOFISH128_CBC
{"twofish128-cbc", 0, (void*)&dropbear_twofish128, 1},
#endif /* DROPBEAR_TWOFISH_CTR */
#endif /* DROPBEAR_ENABLE_CTR_MODE */
#ifdef DROPBEAR_ENABLE_CBC_MODE
#ifdef DROPBEAR_AES128
{"aes128-cbc", 0, &dropbear_aes128, 1, &dropbear_mode_cbc},
#endif
#ifdef DROPBEAR_BLOWFISH_CBC
{"blowfish-cbc", 0, (void*)&dropbear_blowfish, 1},
#ifdef DROPBEAR_AES256
{"aes256-cbc", 0, &dropbear_aes256, 1, &dropbear_mode_cbc},
#endif
{NULL, 0, NULL, 0}
#ifdef DROPBEAR_TWOFISH256
{"twofish256-cbc", 0, &dropbear_twofish256, 1, &dropbear_mode_cbc},
{"twofish-cbc", 0, &dropbear_twofish256, 1, &dropbear_mode_cbc},
#endif
#ifdef DROPBEAR_TWOFISH128
{"twofish128-cbc", 0, &dropbear_twofish128, 1, &dropbear_mode_cbc},
#endif
#ifdef DROPBEAR_3DES
{"3des-ctr", 0, &dropbear_3des, 1, &dropbear_mode_ctr},
#endif
#ifdef DROPBEAR_3DES
{"3des-cbc", 0, &dropbear_3des, 1, &dropbear_mode_cbc},
#endif
#ifdef DROPBEAR_BLOWFISH
{"blowfish-cbc", 0, &dropbear_blowfish, 1, &dropbear_mode_cbc},
#endif
#endif /* DROPBEAR_ENABLE_CBC_MODE */
#ifdef DROPBEAR_NONE_CIPHER
{"none", 0, (void*)&dropbear_nocipher, 1, &dropbear_mode_none},
#endif
{NULL, 0, NULL, 0, NULL}
};
algo_type sshhashes[] = {
#ifdef DROPBEAR_SHA1_96_HMAC
{"hmac-sha1-96", 0, (void*)&dropbear_sha1_96, 1},
{"hmac-sha1-96", 0, &dropbear_sha1_96, 1, NULL},
#endif
#ifdef DROPBEAR_SHA1_HMAC
{"hmac-sha1", 0, (void*)&dropbear_sha1, 1},
{"hmac-sha1", 0, &dropbear_sha1, 1, NULL},
#endif
#ifdef DROPBEAR_SHA2_256_HMAC
{"hmac-sha2-256", 0, &dropbear_sha2_256, 1, NULL},
#endif
#ifdef DROPBEAR_SHA2_512_HMAC
{"hmac-sha2-512", 0, &dropbear_sha2_512, 1, NULL},
#endif
#ifdef DROPBEAR_MD5_HMAC
{"hmac-md5", 0, (void*)&dropbear_md5, 1},
{"hmac-md5", 0, (void*)&dropbear_md5, 1, NULL},
#endif
{NULL, 0, NULL, 0}
#ifdef DROPBEAR_NONE_INTEGRITY
{"none", 0, (void*)&dropbear_nohash, 1, NULL},
#endif
{NULL, 0, NULL, 0, NULL}
};
algo_type sshcompress[] = {
#ifndef DISABLE_ZLIB
{"zlib", DROPBEAR_COMP_ZLIB, NULL, 1},
algo_type ssh_compress[] = {
{"zlib@openssh.com", DROPBEAR_COMP_ZLIB_DELAY, NULL, 1, NULL},
{"zlib", DROPBEAR_COMP_ZLIB, NULL, 1, NULL},
{"none", DROPBEAR_COMP_NONE, NULL, 1, NULL},
{NULL, 0, NULL, 0, NULL}
};
algo_type ssh_delaycompress[] = {
{"zlib@openssh.com", DROPBEAR_COMP_ZLIB_DELAY, NULL, 1, NULL},
{"none", DROPBEAR_COMP_NONE, NULL, 1, NULL},
{NULL, 0, NULL, 0, NULL}
};
#endif
{"none", DROPBEAR_COMP_NONE, NULL, 1},
{NULL, 0, NULL, 0}
algo_type ssh_nocompress[] = {
{"none", DROPBEAR_COMP_NONE, NULL, 1, NULL},
{NULL, 0, NULL, 0, NULL}
};
algo_type sshhostkey[] = {
#ifdef DROPBEAR_ECDSA
#ifdef DROPBEAR_ECC_256
{"ecdsa-sha2-nistp256", DROPBEAR_SIGNKEY_ECDSA_NISTP256, NULL, 1, NULL},
#endif
#ifdef DROPBEAR_ECC_384
{"ecdsa-sha2-nistp384", DROPBEAR_SIGNKEY_ECDSA_NISTP384, NULL, 1, NULL},
#endif
#ifdef DROPBEAR_ECC_521
{"ecdsa-sha2-nistp521", DROPBEAR_SIGNKEY_ECDSA_NISTP521, NULL, 1, NULL},
#endif
#endif
#ifdef DROPBEAR_RSA
{"ssh-rsa", DROPBEAR_SIGNKEY_RSA, NULL, 1},
{"ssh-rsa", DROPBEAR_SIGNKEY_RSA, NULL, 1, NULL},
#endif
#ifdef DROPBEAR_DSS
{"ssh-dss", DROPBEAR_SIGNKEY_DSS, NULL, 1},
{"ssh-dss", DROPBEAR_SIGNKEY_DSS, NULL, 1, NULL},
#endif
{NULL, 0, NULL, 0}
{NULL, 0, NULL, 0, NULL}
};
#if DROPBEAR_DH_GROUP1
static const struct dropbear_kex kex_dh_group1 = {DROPBEAR_KEX_NORMAL_DH, dh_p_1, DH_P_1_LEN, NULL, &sha1_desc };
#endif
#if DROPBEAR_DH_GROUP14
static const struct dropbear_kex kex_dh_group14_sha1 = {DROPBEAR_KEX_NORMAL_DH, dh_p_14, DH_P_14_LEN, NULL, &sha1_desc };
#if DROPBEAR_DH_GROUP14_256
static const struct dropbear_kex kex_dh_group14_sha256 = {DROPBEAR_KEX_NORMAL_DH, dh_p_14, DH_P_14_LEN, NULL, &sha256_desc };
#endif
#endif
#if DROPBEAR_DH_GROUP16
static const struct dropbear_kex kex_dh_group16_sha512 = {DROPBEAR_KEX_NORMAL_DH, dh_p_16, DH_P_16_LEN, NULL, &sha512_desc };
#endif
/* These can't be const since dropbear_ecc_fill_dp() fills out
ecc_curve at runtime */
#ifdef DROPBEAR_ECDH
#ifdef DROPBEAR_ECC_256
static const struct dropbear_kex kex_ecdh_nistp256 = {DROPBEAR_KEX_ECDH, NULL, 0, &ecc_curve_nistp256, &sha256_desc };
#endif
#ifdef DROPBEAR_ECC_384
static const struct dropbear_kex kex_ecdh_nistp384 = {DROPBEAR_KEX_ECDH, NULL, 0, &ecc_curve_nistp384, &sha384_desc };
#endif
#ifdef DROPBEAR_ECC_521
static const struct dropbear_kex kex_ecdh_nistp521 = {DROPBEAR_KEX_ECDH, NULL, 0, &ecc_curve_nistp521, &sha512_desc };
#endif
#endif /* DROPBEAR_ECDH */
#ifdef DROPBEAR_CURVE25519
/* Referred to directly */
static const struct dropbear_kex kex_curve25519 = {DROPBEAR_KEX_CURVE25519, NULL, 0, NULL, &sha256_desc };
#endif
algo_type sshkex[] = {
{"diffie-hellman-group1-sha1", DROPBEAR_KEX_DH_GROUP1, NULL, 1},
{NULL, 0, NULL, 0}
#ifdef DROPBEAR_CURVE25519
{"curve25519-sha256@libssh.org", 0, &kex_curve25519, 1, NULL},
#endif
#ifdef DROPBEAR_ECDH
#ifdef DROPBEAR_ECC_521
{"ecdh-sha2-nistp521", 0, &kex_ecdh_nistp521, 1, NULL},
#endif
#ifdef DROPBEAR_ECC_384
{"ecdh-sha2-nistp384", 0, &kex_ecdh_nistp384, 1, NULL},
#endif
#ifdef DROPBEAR_ECC_256
{"ecdh-sha2-nistp256", 0, &kex_ecdh_nistp256, 1, NULL},
#endif
#endif
#if DROPBEAR_DH_GROUP14
#if DROPBEAR_DH_GROUP14_256
{"diffie-hellman-group14-sha256", 0, &kex_dh_group14_sha256, 1, NULL},
#endif
{"diffie-hellman-group14-sha1", 0, &kex_dh_group14_sha1, 1, NULL},
#endif
#if DROPBEAR_DH_GROUP1
{"diffie-hellman-group1-sha1", 0, &kex_dh_group1, 1, NULL},
#endif
#if DROPBEAR_DH_GROUP16
{"diffie-hellman-group16-sha512", 0, &kex_dh_group16_sha512, 1, NULL},
#endif
#ifdef USE_KEXGUESS2
{KEXGUESS2_ALGO_NAME, KEXGUESS2_ALGO_ID, NULL, 1, NULL},
#endif
{NULL, 0, NULL, 0, NULL}
};
/* Register the compiled in ciphers.
* This should be run before using any of the ciphers/hashes */
void crypto_init() {
const struct ltc_cipher_descriptor *regciphers[] = {
#ifdef DROPBEAR_AES_CBC
&aes_desc,
#endif
#ifdef DROPBEAR_BLOWFISH_CBC
&blowfish_desc,
#endif
#ifdef DROPBEAR_TWOFISH_CBC
&twofish_desc,
#endif
#ifdef DROPBEAR_3DES_CBC
&des3_desc,
#endif
NULL
};
const struct ltc_hash_descriptor *reghashes[] = {
/* we need sha1 for hostkey stuff regardless */
&sha1_desc,
#ifdef DROPBEAR_MD5_HMAC
&md5_desc,
#endif
NULL
};
int i;
for (i = 0; regciphers[i] != NULL; i++) {
if (register_cipher(regciphers[i]) == -1) {
dropbear_exit("error registering crypto");
}
}
for (i = 0; reghashes[i] != NULL; i++) {
if (register_hash(reghashes[i]) == -1) {
dropbear_exit("error registering crypto");
}
}
}
/* algolen specifies the length of algo, algos is our local list to match
* against.
* Returns DROPBEAR_SUCCESS if we have a match for algo, DROPBEAR_FAILURE
@@ -206,8 +331,6 @@ int have_algo(char* algo, size_t algolen, algo_type algos[]) {
return DROPBEAR_FAILURE;
}
/* Output a comma separated list of algorithms to a buffer */
void buf_put_algolist(buffer * buf, algo_type localalgos[]) {
@@ -215,16 +338,243 @@ void buf_put_algolist(buffer * buf, algo_type localalgos[]) {
unsigned int donefirst = 0;
buffer *algolist = NULL;
algolist = buf_new(100);
algolist = buf_new(300);
for (i = 0; localalgos[i].name != NULL; i++) {
if (localalgos[i].usable) {
if (donefirst)
buf_putbyte(algolist, ',');
donefirst = 1;
len = strlen(localalgos[i].name);
buf_putbytes(algolist, localalgos[i].name, len);
buf_putbytes(algolist, (const unsigned char *) localalgos[i].name, len);
}
}
buf_putstring(buf, algolist->data, algolist->len);
buf_putstring(buf, (const char*)algolist->data, algolist->len);
buf_free(algolist);
}
/* match the first algorithm in the comma-separated list in buf which is
* also in localalgos[], or return NULL on failure.
* (*goodguess) is set to 1 if the preferred client/server algos match,
* 0 otherwise. This is used for checking if the kexalgo/hostkeyalgos are
* guessed correctly */
algo_type * buf_match_algo(buffer* buf, algo_type localalgos[],
enum kexguess2_used *kexguess2, int *goodguess)
{
char * algolist = NULL;
const char *remotenames[MAX_PROPOSED_ALGO], *localnames[MAX_PROPOSED_ALGO];
unsigned int len;
unsigned int remotecount, localcount, clicount, servcount, i, j;
algo_type * ret = NULL;
const char **clinames, **servnames;
if (goodguess) {
*goodguess = 0;
}
/* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */
algolist = buf_getstring(buf, &len);
TRACE(("buf_match_algo: %s", algolist))
if (len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
goto out;
}
/* remotenames will contain a list of the strings parsed out */
/* We will have at least one string (even if it's just "") */
remotenames[0] = algolist;
remotecount = 1;
for (i = 0; i < len; i++) {
if (algolist[i] == '\0') {
/* someone is trying something strange */
goto out;
}
if (algolist[i] == ',') {
algolist[i] = '\0';
remotenames[remotecount] = &algolist[i+1];
remotecount++;
}
if (remotecount >= MAX_PROPOSED_ALGO) {
break;
}
}
if (kexguess2 && *kexguess2 == KEXGUESS2_LOOK) {
for (i = 0; i < remotecount; i++)
{
if (strcmp(remotenames[i], KEXGUESS2_ALGO_NAME) == 0) {
*kexguess2 = KEXGUESS2_YES;
break;
}
}
if (*kexguess2 == KEXGUESS2_LOOK) {
*kexguess2 = KEXGUESS2_NO;
}
}
for (i = 0; localalgos[i].name != NULL; i++) {
if (localalgos[i].usable) {
localnames[i] = localalgos[i].name;
} else {
localnames[i] = NULL;
}
}
localcount = i;
if (IS_DROPBEAR_SERVER) {
clinames = remotenames;
clicount = remotecount;
servnames = localnames;
servcount = localcount;
} else {
clinames = localnames;
clicount = localcount;
servnames = remotenames;
servcount = remotecount;
}
/* iterate and find the first match */
for (i = 0; i < clicount; i++) {
for (j = 0; j < servcount; j++) {
if (!(servnames[j] && clinames[i])) {
/* unusable algos are NULL */
continue;
}
if (strcmp(servnames[j], clinames[i]) == 0) {
/* set if it was a good guess */
if (goodguess && kexguess2) {
if (*kexguess2 == KEXGUESS2_YES) {
if (i == 0) {
*goodguess = 1;
}
} else {
if (i == 0 && j == 0) {
*goodguess = 1;
}
}
}
/* set the algo to return */
if (IS_DROPBEAR_SERVER) {
ret = &localalgos[j];
} else {
ret = &localalgos[i];
}
goto out;
}
}
}
out:
m_free(algolist);
return ret;
}
#ifdef DROPBEAR_NONE_CIPHER
void
set_algo_usable(algo_type algos[], const char * algo_name, int usable)
{
algo_type *a;
for (a = algos; a->name != NULL; a++)
{
if (strcmp(a->name, algo_name) == 0)
{
a->usable = usable;
return;
}
}
}
int
get_algo_usable(algo_type algos[], const char * algo_name)
{
algo_type *a;
for (a = algos; a->name != NULL; a++)
{
if (strcmp(a->name, algo_name) == 0)
{
return a->usable;
}
}
return 0;
}
#endif /* DROPBEAR_NONE_CIPHER */
#ifdef ENABLE_USER_ALGO_LIST
char *
algolist_string(algo_type algos[])
{
char *ret_list;
buffer *b = buf_new(200);
buf_put_algolist(b, algos);
buf_setpos(b, b->len);
buf_putbyte(b, '\0');
buf_setpos(b, 4);
ret_list = m_strdup((const char *) buf_getptr(b, b->len - b->pos));
buf_free(b);
return ret_list;
}
static algo_type*
check_algo(const char* algo_name, algo_type *algos)
{
algo_type *a;
for (a = algos; a->name != NULL; a++)
{
if (strcmp(a->name, algo_name) == 0)
{
return a;
}
}
return NULL;
}
/* Checks a user provided comma-separated algorithm list for available
* options. Any that are not acceptable are removed in-place. Returns the
* number of valid algorithms. */
int
check_user_algos(const char* user_algo_list, algo_type * algos,
const char *algo_desc)
{
algo_type new_algos[MAX_PROPOSED_ALGO+1];
char *work_list = m_strdup(user_algo_list);
char *start = work_list;
char *c;
int n;
/* So we can iterate and look for null terminator */
memset(new_algos, 0x0, sizeof(new_algos));
for (c = work_list, n = 0; ; c++)
{
char oc = *c;
if (n >= MAX_PROPOSED_ALGO) {
dropbear_exit("Too many algorithms '%s'", user_algo_list);
}
if (*c == ',' || *c == '\0') {
algo_type *match_algo = NULL;
*c = '\0';
match_algo = check_algo(start, algos);
if (match_algo) {
if (check_algo(start, new_algos)) {
TRACE(("Skip repeated algorithm '%s'", start))
} else {
new_algos[n] = *match_algo;
n++;
}
} else {
dropbear_log(LOG_WARNING, "This Dropbear program does not support '%s' %s algorithm", start, algo_desc);
}
c++;
start = c;
}
if (oc == '\0') {
break;
}
}
m_free(work_list);
/* n+1 to include a null terminator */
memcpy(algos, new_algos, sizeof(*new_algos) * (n+1));
return n;
}
#endif /* ENABLE_USER_ALGO_LIST */

View File

@@ -34,21 +34,22 @@
#include "channel.h"
#include "ssh.h"
#include "listener.h"
#include "runopts.h"
#include "netio.h"
static void send_msg_channel_open_failure(unsigned int remotechan, int reason,
const unsigned char *text, const unsigned char *lang);
const char *text, const char *lang);
static void send_msg_channel_open_confirmation(struct Channel* channel,
unsigned int recvwindow,
unsigned int recvmaxpacket);
static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf);
static int writechannel(struct Channel* channel, int fd, circbuffer *cbuf,
const unsigned char *moredata, unsigned int *morelen);
static void send_msg_channel_window_adjust(struct Channel *channel,
unsigned int incr);
static void send_msg_channel_data(struct Channel *channel, int isextended);
static void send_msg_channel_eof(struct Channel *channel);
static void send_msg_channel_close(struct Channel *channel);
static void remove_channel(struct Channel *channel);
static void delete_channel(struct Channel *channel);
static void check_in_progress(struct Channel *channel);
static unsigned int write_pending(struct Channel * channel);
static void check_close(struct Channel *channel);
static void close_chan_fd(struct Channel *channel, int fd, int how);
@@ -59,6 +60,13 @@ static void close_chan_fd(struct Channel *channel, int fd, int how);
#define ERRFD_IS_READ(channel) ((channel)->extrabuf == NULL)
#define ERRFD_IS_WRITE(channel) (!ERRFD_IS_READ(channel))
/* allow space for:
* 1 byte byte SSH_MSG_CHANNEL_DATA
* 4 bytes uint32 recipient channel
* 4 bytes string data
*/
#define RECV_MAX_CHANNEL_DATA_LEN (RECV_MAX_PAYLOAD_LEN-(1+4+4))
/* Initialise all the channels */
void chaninitialise(const struct ChanType *chantypes[]) {
@@ -96,7 +104,7 @@ void chancleanup() {
/* If remotechan, transwindow and transmaxpacket are not know (for a new
* outgoing connection, with them to be filled on confirmation), they should
* all be set to 0 */
struct Channel* newchannel(unsigned int remotechan,
static struct Channel* newchannel(unsigned int remotechan,
const struct ChanType *type,
unsigned int transwindow, unsigned int transmaxpacket) {
@@ -137,6 +145,7 @@ struct Channel* newchannel(unsigned int remotechan,
newchan->index = i;
newchan->sent_close = newchan->recv_close = 0;
newchan->sent_eof = newchan->recv_eof = 0;
newchan->close_handler_done = 0;
newchan->remotechan = remotechan;
newchan->transwindow = transwindow;
@@ -146,15 +155,17 @@ struct Channel* newchannel(unsigned int remotechan,
newchan->writefd = FD_UNINIT;
newchan->readfd = FD_UNINIT;
newchan->errfd = FD_CLOSED; /* this isn't always set to start with */
newchan->initconn = 0;
newchan->await_open = 0;
newchan->flushing = 0;
newchan->writebuf = cbuf_new(RECV_MAXWINDOW);
newchan->writebuf = cbuf_new(opts.recv_window);
newchan->recvwindow = opts.recv_window;
newchan->extrabuf = NULL; /* The user code can set it up */
newchan->recvwindow = RECV_MAXWINDOW;
newchan->recvdonelen = 0;
newchan->recvmaxpacket = RECV_MAXPACKET;
newchan->recvmaxpacket = RECV_MAX_CHANNEL_DATA_LEN;
newchan->prio = DROPBEAR_CHANNEL_PRIO_EARLY; /* inithandler sets it */
ses.channels[i] = newchan;
ses.chancount++;
@@ -190,11 +201,14 @@ struct Channel* getchannel() {
/* Iterate through the channels, performing IO if available */
void channelio(fd_set *readfds, fd_set *writefds) {
/* Listeners such as TCP, X11, agent-auth */
struct Channel *channel;
unsigned int i;
/* foreach channel */
for (i = 0; i < ses.chansize; i++) {
/* Close checking only needs to occur for channels that had IO events */
int do_check_close = 0;
channel = ses.channels[i];
if (channel == NULL) {
@@ -206,6 +220,7 @@ void channelio(fd_set *readfds, fd_set *writefds) {
if (channel->readfd >= 0 && FD_ISSET(channel->readfd, readfds)) {
TRACE(("send normal readfd"))
send_msg_channel_data(channel, 0);
do_check_close = 1;
}
/* read stderr data and send it over the wire */
@@ -213,31 +228,33 @@ void channelio(fd_set *readfds, fd_set *writefds) {
&& FD_ISSET(channel->errfd, readfds)) {
TRACE(("send normal errfd"))
send_msg_channel_data(channel, 1);
do_check_close = 1;
}
/* write to program/pipe stdin */
if (channel->writefd >= 0 && FD_ISSET(channel->writefd, writefds)) {
if (channel->initconn) {
/* XXX should this go somewhere cleaner? */
check_in_progress(channel);
continue; /* Important not to use the channel after
check_in_progress(), as it may be NULL */
}
writechannel(channel, channel->writefd, channel->writebuf);
writechannel(channel, channel->writefd, channel->writebuf, NULL, NULL);
do_check_close = 1;
}
/* stderr for client mode */
if (ERRFD_IS_WRITE(channel)
&& channel->errfd >= 0 && FD_ISSET(channel->errfd, writefds)) {
writechannel(channel, channel->errfd, channel->extrabuf);
writechannel(channel, channel->errfd, channel->extrabuf, NULL, NULL);
do_check_close = 1;
}
if (ses.channel_signal_pending) {
/* SIGCHLD can change channel state for server sessions */
do_check_close = 1;
}
/* handle any channel closing etc */
check_close(channel);
if (do_check_close) {
check_close(channel);
}
}
/* Listeners such as TCP, X11, agent-auth */
#ifdef USING_LISTENERS
handle_listeners(readfds);
#endif
@@ -260,21 +277,34 @@ static unsigned int write_pending(struct Channel * channel) {
/* EOF/close handling */
static void check_close(struct Channel *channel) {
int close_allowed = 0;
TRACE(("check_close: writefd %d, readfd %d, errfd %d, sent_close %d, recv_close %d",
TRACE2(("check_close: writefd %d, readfd %d, errfd %d, sent_close %d, recv_close %d",
channel->writefd, channel->readfd,
channel->errfd, channel->sent_close, channel->recv_close))
TRACE(("writebuf size %d extrabuf size %d",
cbuf_getused(channel->writebuf),
TRACE2(("writebuf size %d extrabuf size %d",
channel->writebuf ? cbuf_getused(channel->writebuf) : 0,
channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0))
if (!channel->flushing && channel->type->check_close
if (!channel->flushing
&& !channel->close_handler_done
&& channel->type->check_close
&& channel->type->check_close(channel))
{
channel->flushing = 1;
}
/* if a type-specific check_close is defined we will only exit
once that has been triggered. this is only used for a server "session"
channel, to ensure that the shell has exited (and the exit status
retrieved) before we close things up. */
if (!channel->type->check_close
|| channel->close_handler_done
|| channel->type->check_close(channel)) {
close_allowed = 1;
}
if (channel->recv_close && !write_pending(channel)) {
if (channel->recv_close && !write_pending(channel) && close_allowed) {
if (!channel->sent_close) {
TRACE(("Sending MSG_CHANNEL_CLOSE in response to same."))
send_msg_channel_close(channel);
@@ -283,7 +313,9 @@ static void check_close(struct Channel *channel) {
return;
}
if (channel->recv_eof && !write_pending(channel)) {
if ((channel->recv_eof && !write_pending(channel))
/* have a server "session" and child has exited */
|| (channel->type->check_close && close_allowed)) {
close_chan_fd(channel, channel->writefd, SHUT_WR);
}
@@ -311,9 +343,11 @@ static void check_close(struct Channel *channel) {
}
/* And if we can't receive any more data from them either, close up */
if (!channel->sent_close
&& channel->readfd == FD_CLOSED
if (channel->readfd == FD_CLOSED
&& channel->writefd == FD_CLOSED
&& (ERRFD_IS_WRITE(channel) || channel->errfd == FD_CLOSED)
&& !channel->sent_close
&& close_allowed
&& !write_pending(channel)) {
TRACE(("sending close, readfd is closed"))
send_msg_channel_close(channel);
@@ -324,26 +358,26 @@ static void check_close(struct Channel *channel) {
* if so, set up the channel properly. Otherwise, the channel is cleaned up, so
* it is important that the channel reference isn't used after a call to this
* function */
static void check_in_progress(struct Channel *channel) {
void channel_connect_done(int result, int sock, void* user_data, const char* UNUSED(errstring)) {
int val;
socklen_t vallen = sizeof(val);
struct Channel *channel = user_data;
TRACE(("enter check_in_progress"))
TRACE(("enter channel_connect_done"))
if (getsockopt(channel->writefd, SOL_SOCKET, SO_ERROR, &val, &vallen)
|| val != 0) {
send_msg_channel_open_failure(channel->remotechan,
SSH_OPEN_CONNECT_FAILED, "", "");
close(channel->writefd);
delete_channel(channel);
TRACE(("leave check_in_progress: fail"))
} else {
if (result == DROPBEAR_SUCCESS)
{
channel->readfd = channel->writefd = sock;
channel->conn_pending = NULL;
send_msg_channel_open_confirmation(channel, channel->recvwindow,
channel->recvmaxpacket);
channel->readfd = channel->writefd;
channel->initconn = 0;
TRACE(("leave check_in_progress: success"))
TRACE(("leave channel_connect_done: success"))
}
else
{
send_msg_channel_open_failure(channel->remotechan,
SSH_OPEN_CONNECT_FAILED, "", "");
remove_channel(channel);
TRACE(("leave check_in_progress: fail"))
}
}
@@ -351,9 +385,11 @@ static void check_in_progress(struct Channel *channel) {
/* Send the close message and set the channel as closed */
static void send_msg_channel_close(struct Channel *channel) {
TRACE(("enter send_msg_channel_close"))
if (channel->type->closehandler) {
TRACE(("enter send_msg_channel_close %p", (void*)channel))
if (channel->type->closehandler
&& !channel->close_handler_done) {
channel->type->closehandler(channel);
channel->close_handler_done = 1;
}
CHECKCLEARTOWRITE();
@@ -387,51 +423,138 @@ static void send_msg_channel_eof(struct Channel *channel) {
TRACE(("leave send_msg_channel_eof"))
}
/* Called to write data out to the local side of the channel.
* Only called when we know we can write to a channel, writes as much as
* possible */
static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf) {
#ifndef HAVE_WRITEV
static int writechannel_fallback(struct Channel* channel, int fd, circbuffer *cbuf,
const unsigned char *UNUSED(moredata), unsigned int *morelen) {
int len, maxlen;
unsigned char *circ_p1, *circ_p2;
unsigned int circ_len1, circ_len2;
ssize_t written;
TRACE(("enter writechannel fd %d", fd))
maxlen = cbuf_readlen(cbuf);
/* Write the data out */
len = write(fd, cbuf_readptr(cbuf, maxlen), maxlen);
if (len <= 0) {
TRACE(("errno %d len %d", errno, len))
if (len < 0 && errno != EINTR) {
close_chan_fd(channel, fd, SHUT_WR);
}
TRACE(("leave writechannel: len <= 0"))
return;
if (morelen) {
/* fallback doesn't consume moredata */
*morelen = 0;
}
TRACE(("writechannel wrote %d", len))
cbuf_incrread(cbuf, len);
channel->recvdonelen += len;
/* Write the first portion of the circular buffer */
cbuf_readptrs(cbuf, &circ_p1, &circ_len1, &circ_p2, &circ_len2);
written = write(fd, circ_p1, circ_len1);
if (written < 0) {
if (errno != EINTR && errno != EAGAIN) {
TRACE(("channel IO write error fd %d %s", fd, strerror(errno)))
close_chan_fd(channel, fd, SHUT_WR);
return DROPBEAR_FAILURE;
}
} else {
cbuf_incrread(cbuf, written);
channel->recvdonelen += written;
}
return DROPBEAR_SUCCESS;
}
#endif /* !HAVE_WRITEV */
#ifdef HAVE_WRITEV
static int writechannel_writev(struct Channel* channel, int fd, circbuffer *cbuf,
const unsigned char *moredata, unsigned int *morelen) {
struct iovec iov[3];
unsigned char *circ_p1, *circ_p2;
unsigned int circ_len1, circ_len2;
int io_count = 0;
ssize_t written;
cbuf_readptrs(cbuf, &circ_p1, &circ_len1, &circ_p2, &circ_len2);
if (circ_len1 > 0) {
TRACE(("circ1 %d", circ_len1))
iov[io_count].iov_base = circ_p1;
iov[io_count].iov_len = circ_len1;
io_count++;
}
if (circ_len2 > 0) {
TRACE(("circ2 %d", circ_len2))
iov[io_count].iov_base = circ_p2;
iov[io_count].iov_len = circ_len2;
io_count++;
}
if (morelen) {
assert(moredata);
TRACE(("more %d", *morelen))
iov[io_count].iov_base = (void*)moredata;
iov[io_count].iov_len = *morelen;
io_count++;
}
if (io_count == 0) {
/* writechannel may sometimes be called twice in a main loop iteration.
From common_recv_msg_channel_data() then channelio().
The second call may not have any data to write, so we just return. */
TRACE(("leave writechannel, no data"))
return DROPBEAR_SUCCESS;
}
if (morelen) {
/* Default return value, none consumed */
*morelen = 0;
}
written = writev(fd, iov, io_count);
if (written < 0) {
if (errno != EINTR && errno != EAGAIN) {
TRACE(("channel IO write error fd %d %s", fd, strerror(errno)))
close_chan_fd(channel, fd, SHUT_WR);
return DROPBEAR_FAILURE;
}
} else {
int cbuf_written = MIN(circ_len1+circ_len2, (unsigned int)written);
cbuf_incrread(cbuf, cbuf_written);
if (morelen) {
*morelen = written - cbuf_written;
}
channel->recvdonelen += written;
}
return DROPBEAR_SUCCESS;
}
#endif /* HAVE_WRITEV */
/* Called to write data out to the local side of the channel.
Writes the circular buffer contents and also the "moredata" buffer
if not null. Will ignore EAGAIN.
Returns DROPBEAR_FAILURE if writing to fd had an error and the channel is being closed, DROPBEAR_SUCCESS otherwise */
static int writechannel(struct Channel* channel, int fd, circbuffer *cbuf,
const unsigned char *moredata, unsigned int *morelen) {
int ret = DROPBEAR_SUCCESS;
TRACE(("enter writechannel fd %d", fd))
#ifdef HAVE_WRITEV
ret = writechannel_writev(channel, fd, cbuf, moredata, morelen);
#else
ret = writechannel_fallback(channel, fd, cbuf, moredata, morelen);
#endif
/* Window adjust handling */
if (channel->recvdonelen >= RECV_WINDOWEXTEND) {
/* Set it back to max window */
send_msg_channel_window_adjust(channel, channel->recvdonelen);
channel->recvwindow += channel->recvdonelen;
channel->recvdonelen = 0;
}
dropbear_assert(channel->recvwindow <= RECV_MAXWINDOW);
dropbear_assert(channel->recvwindow <= opts.recv_window);
dropbear_assert(channel->recvwindow <= cbuf_getavail(channel->writebuf));
dropbear_assert(channel->extrabuf == NULL ||
channel->recvwindow <= cbuf_getavail(channel->extrabuf));
TRACE(("leave writechannel"))
return ret;
}
/* Set the file descriptors for the main select in session.c
* This avoid channels which don't have any window available, are closed, etc*/
void setchannelfds(fd_set *readfds, fd_set *writefds) {
void setchannelfds(fd_set *readfds, fd_set *writefds, int allow_reads) {
unsigned int i;
struct Channel * channel;
@@ -443,8 +566,13 @@ void setchannelfds(fd_set *readfds, fd_set *writefds) {
continue;
}
/* Stuff to put over the wire */
if (channel->transwindow > 0) {
/* Stuff to put over the wire.
Avoid queueing data to send if we're in the middle of a
key re-exchange (!dataallowed), but still read from the
FD if there's the possibility of "~."" to kill an
interactive session (the read_mangler) */
if (channel->transwindow > 0
&& ((ses.dataallowed && allow_reads) || channel->read_mangler)) {
if (channel->readfd >= 0) {
FD_SET(channel->readfd, readfds);
@@ -456,13 +584,12 @@ void setchannelfds(fd_set *readfds, fd_set *writefds) {
}
/* Stuff from the wire */
if ((channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0 )
|| channel->initconn) {
if (channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0) {
FD_SET(channel->writefd, writefds);
}
if (ERRFD_IS_WRITE(channel) && channel->errfd >= 0
&& cbuf_getused(channel->extrabuf) > 0 ) {
&& cbuf_getused(channel->extrabuf) > 0) {
FD_SET(channel->errfd, writefds);
}
@@ -524,31 +651,35 @@ static void remove_channel(struct Channel * channel) {
}
/* close the FDs in case they haven't been done
* yet (they might have been shutdown etc) */
TRACE(("CLOSE writefd %d", channel->writefd))
close(channel->writefd);
TRACE(("CLOSE readfd %d", channel->readfd))
close(channel->readfd);
TRACE(("CLOSE errfd %d", channel->errfd))
close(channel->errfd);
if (IS_DROPBEAR_SERVER || (channel->writefd != STDOUT_FILENO)) {
/* close the FDs in case they haven't been done
* yet (they might have been shutdown etc) */
TRACE(("CLOSE writefd %d", channel->writefd))
m_close(channel->writefd);
TRACE(("CLOSE readfd %d", channel->readfd))
m_close(channel->readfd);
TRACE(("CLOSE errfd %d", channel->errfd))
m_close(channel->errfd);
}
channel->typedata = NULL;
if (!channel->close_handler_done
&& channel->type->closehandler) {
channel->type->closehandler(channel);
channel->close_handler_done = 1;
}
delete_channel(channel);
TRACE(("leave remove_channel"))
}
/* Remove a channel entry */
static void delete_channel(struct Channel *channel) {
if (channel->conn_pending) {
cancel_connect(channel->conn_pending);
}
ses.channels[channel->index] = NULL;
m_free(channel);
ses.chancount--;
}
update_channel_prio();
TRACE(("leave remove_channel"))
}
/* Handle channel specific requests, passing off to corresponding handlers
* such as chansession or x11fwd */
@@ -556,14 +687,25 @@ void recv_msg_channel_request() {
struct Channel *channel;
TRACE(("enter recv_msg_channel_request"))
channel = getchannel();
if (channel->type->reqhandler) {
TRACE(("enter recv_msg_channel_request %p", (void*)channel))
if (channel->sent_close) {
TRACE(("leave recv_msg_channel_request: already closed channel"))
return;
}
if (channel->type->reqhandler
&& !channel->close_handler_done) {
channel->type->reqhandler(channel);
} else {
send_msg_channel_failure(channel);
int wantreply;
buf_eatstring(ses.payload);
wantreply = buf_getbool(ses.payload);
if (wantreply) {
send_msg_channel_failure(channel);
}
}
TRACE(("leave recv_msg_channel_request"))
@@ -599,7 +741,7 @@ static void send_msg_channel_data(struct Channel *channel, int isextended) {
* exttype if is extended */
maxlen = MIN(maxlen,
ses.writepayload->size - 1 - 4 - 4 - (isextended ? 4 : 0));
TRACE(("maxlen %d", maxlen))
TRACE(("maxlen %zd", maxlen))
if (maxlen == 0) {
TRACE(("leave send_msg_channel_data: no window"))
return;
@@ -617,6 +759,7 @@ static void send_msg_channel_data(struct Channel *channel, int isextended) {
/* read the data */
len = read(fd, buf_getwriteptr(ses.writepayload, maxlen), maxlen);
if (len <= 0) {
if (len == 0 || errno != EINTR) {
/* This will also get hit in the case of EAGAIN. The only
@@ -624,11 +767,23 @@ static void send_msg_channel_data(struct Channel *channel, int isextended) {
in which case it can be treated the same as EOF */
close_chan_fd(channel, fd, SHUT_RD);
}
ses.writepayload->len = ses.writepayload->pos = 0;
buf_setpos(ses.writepayload, 0);
buf_setlen(ses.writepayload, 0);
TRACE(("leave send_msg_channel_data: len %d read err %d or EOF for fd %d",
len, errno, fd))
return;
}
if (channel->read_mangler) {
channel->read_mangler(channel, buf_getwriteptr(ses.writepayload, len), &len);
if (len == 0) {
buf_setpos(ses.writepayload, 0);
buf_setlen(ses.writepayload, 0);
return;
}
}
TRACE(("send_msg_channel_data: len %d fd %d", len, fd))
buf_incrwritepos(ses.writepayload, len);
/* ... real size here */
buf_setpos(ses.writepayload, size_pos);
@@ -667,14 +822,16 @@ void common_recv_msg_channel_data(struct Channel *channel, int fd,
unsigned int maxdata;
unsigned int buflen;
unsigned int len;
unsigned int consumed;
int res;
TRACE(("enter recv_msg_channel_data"))
if (channel->recv_eof) {
dropbear_exit("received data after eof");
dropbear_exit("Received data after eof");
}
if (fd < 0) {
if (fd < 0 || !cbuf) {
/* If we have encountered failed write, the far side might still
* be sending data without having yet received our close notification.
* We just drop the data. */
@@ -693,24 +850,35 @@ void common_recv_msg_channel_data(struct Channel *channel, int fd,
dropbear_exit("Oversized packet");
}
/* We may have to run throught twice, if the buffer wraps around. Can't
* just "leave it for next time" like with writechannel, since this
* is payload data */
len = datalen;
while (len > 0) {
buflen = cbuf_writelen(cbuf);
buflen = MIN(buflen, len);
memcpy(cbuf_writeptr(cbuf, buflen),
buf_getptr(ses.payload, buflen), buflen);
cbuf_incrwrite(cbuf, buflen);
buf_incrpos(ses.payload, buflen);
len -= buflen;
}
dropbear_assert(channel->recvwindow >= datalen);
channel->recvwindow -= datalen;
dropbear_assert(channel->recvwindow <= RECV_MAXWINDOW);
dropbear_assert(channel->recvwindow <= opts.recv_window);
/* Attempt to write the data immediately without having to put it in the circular buffer */
consumed = datalen;
res = writechannel(channel, fd, cbuf, buf_getptr(ses.payload, datalen), &consumed);
datalen -= consumed;
buf_incrpos(ses.payload, consumed);
/* We may have to run throught twice, if the buffer wraps around. Can't
* just "leave it for next time" like with writechannel, since this
* is payload data.
* If the writechannel() failed then remaining data is discarded */
if (res == DROPBEAR_SUCCESS) {
len = datalen;
while (len > 0) {
buflen = cbuf_writelen(cbuf);
buflen = MIN(buflen, len);
memcpy(cbuf_writeptr(cbuf, buflen),
buf_getptr(ses.payload, buflen), buflen);
cbuf_incrwrite(cbuf, buflen);
buf_incrpos(ses.payload, buflen);
len -= buflen;
}
}
TRACE(("leave recv_msg_channel_data"))
}
@@ -727,10 +895,10 @@ void recv_msg_channel_window_adjust() {
incr = buf_getint(ses.payload);
TRACE(("received window increment %d", incr))
incr = MIN(incr, MAX_TRANS_WIN_INCR);
incr = MIN(incr, TRANS_MAX_WIN_INCR);
channel->transwindow += incr;
channel->transwindow = MIN(channel->transwindow, MAX_TRANS_WINDOW);
channel->transwindow = MIN(channel->transwindow, TRANS_MAX_WINDOW);
}
@@ -752,7 +920,7 @@ static void send_msg_channel_window_adjust(struct Channel* channel,
/* Handle a new channel request, performing any channel-type-specific setup */
void recv_msg_channel_open() {
unsigned char *type;
char *type;
unsigned int typelen;
unsigned int remotechan, transwindow, transmaxpacket;
struct Channel *channel;
@@ -769,9 +937,9 @@ void recv_msg_channel_open() {
remotechan = buf_getint(ses.payload);
transwindow = buf_getint(ses.payload);
transwindow = MIN(transwindow, MAX_TRANS_WINDOW);
transwindow = MIN(transwindow, TRANS_MAX_WINDOW);
transmaxpacket = buf_getint(ses.payload);
transmaxpacket = MIN(transmaxpacket, MAX_TRANS_PAYLOAD_LEN);
transmaxpacket = MIN(transmaxpacket, TRANS_MAX_PAYLOAD_LEN);
/* figure what type of packet it is */
if (typelen > MAX_NAME_LEN) {
@@ -801,6 +969,7 @@ void recv_msg_channel_open() {
if (channel == NULL) {
TRACE(("newchannel returned NULL"))
errtype = SSH_OPEN_RESOURCE_SHORTAGE;
goto failure;
}
@@ -812,12 +981,16 @@ void recv_msg_channel_open() {
}
if (ret > 0) {
errtype = ret;
delete_channel(channel);
remove_channel(channel);
TRACE(("inithandler returned failure %d", ret))
goto failure;
}
}
if (channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) {
channel->prio = DROPBEAR_CHANNEL_PRIO_BULK;
}
/* success */
send_msg_channel_open_confirmation(channel, channel->recvwindow,
channel->recvmaxpacket);
@@ -829,6 +1002,8 @@ failure:
cleanup:
m_free(type);
update_channel_prio();
TRACE(("leave recv_msg_channel_open"))
}
@@ -862,7 +1037,7 @@ void send_msg_channel_success(struct Channel *channel) {
/* Send a channel open failure message, with a corresponding reason
* code (usually resource shortage or unknown chan type) */
static void send_msg_channel_open_failure(unsigned int remotechan,
int reason, const unsigned char *text, const unsigned char *lang) {
int reason, const char *text, const char *lang) {
TRACE(("enter send_msg_channel_open_failure"))
CHECKCLEARTOWRITE();
@@ -870,8 +1045,8 @@ static void send_msg_channel_open_failure(unsigned int remotechan,
buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN_FAILURE);
buf_putint(ses.writepayload, remotechan);
buf_putint(ses.writepayload, reason);
buf_putstring(ses.writepayload, text, strlen((char*)text));
buf_putstring(ses.writepayload, lang, strlen((char*)lang));
buf_putstring(ses.writepayload, text, strlen(text));
buf_putstring(ses.writepayload, lang, strlen(lang));
encrypt_packet();
TRACE(("leave send_msg_channel_open_failure"))
@@ -911,7 +1086,7 @@ static void close_chan_fd(struct Channel *channel, int fd, int how) {
}
} else {
TRACE(("CLOSE some fd %d", fd))
close(fd);
m_close(fd);
closein = closeout = 1;
}
@@ -934,7 +1109,7 @@ static void close_chan_fd(struct Channel *channel, int fd, int how) {
if (channel->type->sepfds && channel->readfd == FD_CLOSED
&& channel->writefd == FD_CLOSED && channel->errfd == FD_CLOSED) {
TRACE(("CLOSE (finally) of %d", fd))
close(fd);
m_close(fd);
}
}
@@ -944,7 +1119,7 @@ static void close_chan_fd(struct Channel *channel, int fd, int how) {
* for X11, agent, tcp forwarding, and should be filled with channel-specific
* options, with the calling function calling encrypt_packet() after
* completion. It is mandatory for the caller to encrypt_packet() if
* DROPBEAR_SUCCESS is returned */
* a channel is returned. NULL is returned on failure. */
int send_msg_channel_open_init(int fd, const struct ChanType *type) {
struct Channel* chan;
@@ -956,6 +1131,9 @@ int send_msg_channel_open_init(int fd, const struct ChanType *type) {
return DROPBEAR_FAILURE;
}
/* Outbound opened channels don't make use of in-progress connections,
* we can set it up straight away */
/* set fd non-blocking */
setnonblocking(fd);
@@ -970,8 +1148,8 @@ int send_msg_channel_open_init(int fd, const struct ChanType *type) {
buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN);
buf_putstring(ses.writepayload, type->name, strlen(type->name));
buf_putint(ses.writepayload, chan->index);
buf_putint(ses.writepayload, RECV_MAXWINDOW);
buf_putint(ses.writepayload, RECV_MAXPACKET);
buf_putint(ses.writepayload, opts.recv_window);
buf_putint(ses.writepayload, RECV_MAX_CHANNEL_DATA_LEN);
TRACE(("leave send_msg_channel_open_init()"))
return DROPBEAR_SUCCESS;
@@ -989,7 +1167,7 @@ void recv_msg_channel_open_confirmation() {
channel = getchannel();
if (!channel->await_open) {
dropbear_exit("unexpected channel reply");
dropbear_exit("Unexpected channel reply");
}
channel->await_open = 0;
@@ -1006,9 +1184,14 @@ void recv_msg_channel_open_confirmation() {
if (ret > 0) {
remove_channel(channel);
TRACE(("inithandler returned failure %d", ret))
return;
}
}
if (channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) {
channel->prio = DROPBEAR_CHANNEL_PRIO_BULK;
}
update_channel_prio();
TRACE(("leave recv_msg_channel_open_confirmation"))
}
@@ -1021,10 +1204,49 @@ void recv_msg_channel_open_failure() {
channel = getchannel();
if (!channel->await_open) {
dropbear_exit("unexpected channel reply");
dropbear_exit("Unexpected channel reply");
}
channel->await_open = 0;
remove_channel(channel);
}
#endif /* USING_LISTENERS */
void send_msg_request_success() {
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_SUCCESS);
encrypt_packet();
}
void send_msg_request_failure() {
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_FAILURE);
encrypt_packet();
}
struct Channel* get_any_ready_channel() {
size_t i;
if (ses.chancount == 0) {
return NULL;
}
for (i = 0; i < ses.chansize; i++) {
struct Channel *chan = ses.channels[i];
if (chan
&& !(chan->sent_eof || chan->recv_eof)
&& !(chan->await_open)) {
return chan;
}
}
return NULL;
}
void start_send_channel_request(struct Channel *channel,
char *type) {
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_REQUEST);
buf_putint(ses.writepayload, channel->remotechan);
buf_putstring(ses.writepayload, type, strlen(type));
}

File diff suppressed because it is too large Load Diff

View File

@@ -28,12 +28,15 @@
#include "buffer.h"
#include "dbutil.h"
#include "auth.h"
#include "algo.h"
#include "dbrandom.h"
runopts opts; /* GLOBAL */
/* returns success or failure, and the keytype in *type. If we want
* to restrict the type, type can contain a type to return */
int readhostkey(const char * filename, sign_key * hostkey, int *type) {
int readhostkey(const char * filename, sign_key * hostkey,
enum signkey_type *type) {
int ret = DROPBEAR_FAILURE;
buffer *buf;
@@ -44,6 +47,9 @@ int readhostkey(const char * filename, sign_key * hostkey, int *type) {
goto out;
}
buf_setpos(buf, 0);
addrandom(buf_getptr(buf, buf->len), buf->len);
if (buf_get_priv_key(buf, hostkey, type) == DROPBEAR_FAILURE) {
goto out;
}
@@ -55,3 +61,53 @@ out:
buf_free(buf);
return ret;
}
#ifdef ENABLE_USER_ALGO_LIST
void
parse_ciphers_macs()
{
if (opts.cipher_list)
{
if (strcmp(opts.cipher_list, "help") == 0)
{
char *ciphers = algolist_string(sshciphers);
dropbear_log(LOG_INFO, "Available ciphers:\n%s\n", ciphers);
m_free(ciphers);
dropbear_exit(".");
}
if (strcmp(opts.cipher_list, "none") == 0)
{
/* Encryption is required during authentication */
opts.cipher_list = "none,aes128-ctr";
}
if (check_user_algos(opts.cipher_list, sshciphers, "cipher") == 0)
{
dropbear_exit("No valid ciphers specified for '-c'");
}
}
if (opts.mac_list)
{
if (strcmp(opts.mac_list, "help") == 0)
{
char *macs = algolist_string(sshhashes);
dropbear_log(LOG_INFO, "Available MACs:\n%s\n", macs);
m_free(macs);
dropbear_exit(".");
}
if (check_user_algos(opts.mac_list, sshhashes, "MAC") == 0)
{
dropbear_exit("No valid MACs specified for '-m'");
}
}
}
#endif
void print_version() {
fprintf(stderr, "Dropbear v%s\n", DROPBEAR_VERSION);
}

View File

@@ -1,7 +1,7 @@
/*
* Dropbear - a SSH2 server
*
* Copyright (c) 2002,2003 Matt Johnston
* Copyright (c) Matt Johnston
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -30,13 +30,16 @@
#include "buffer.h"
#include "dss.h"
#include "ssh.h"
#include "random.h"
#include "dbrandom.h"
#include "kex.h"
#include "channel.h"
#include "atomicio.h"
#include "runopts.h"
#include "netio.h"
static void checktimeouts();
static void checktimeouts(void);
static long select_timeout(void);
static int ident_readln(int fd, char* buf, int count);
static void read_session_identification(void);
struct sshsession ses; /* GLOBAL */
@@ -47,60 +50,83 @@ int sessinitdone = 0; /* GLOBAL */
/* this is set when we get SIGINT or SIGTERM, the handler is in main.c */
int exitflag = 0; /* GLOBAL */
/* called only at the start of a session, set up initial state */
void common_session_init(int sock, char* remotehost) {
void common_session_init(int sock_in, int sock_out) {
time_t now;
#ifdef DEBUG_TRACE
debug_start_net();
#endif
TRACE(("enter session_init"))
ses.remotehost = remotehost;
ses.sock_in = sock_in;
ses.sock_out = sock_out;
ses.maxfd = MAX(sock_in, sock_out);
ses.sock = sock;
ses.maxfd = sock;
if (sock_in >= 0) {
setnonblocking(sock_in);
}
if (sock_out >= 0) {
setnonblocking(sock_out);
}
ses.connecttimeout = 0;
ses.socket_prio = DROPBEAR_PRIO_DEFAULT;
/* Sets it to lowdelay */
update_channel_prio();
now = monotonic_now();
ses.connect_time = now;
ses.last_packet_time_keepalive_recv = now;
ses.last_packet_time_idle = now;
ses.last_packet_time_any_sent = 0;
ses.last_packet_time_keepalive_sent = 0;
if (pipe(ses.signal_pipe) < 0) {
dropbear_exit("signal pipe failed");
dropbear_exit("Signal pipe failed");
}
setnonblocking(ses.signal_pipe[0]);
setnonblocking(ses.signal_pipe[1]);
kexfirstinitialise(); /* initialise the kex state */
ses.writepayload = buf_new(MAX_TRANS_PAYLOAD_LEN);
ses.maxfd = MAX(ses.maxfd, ses.signal_pipe[0]);
ses.maxfd = MAX(ses.maxfd, ses.signal_pipe[1]);
ses.writepayload = buf_new(TRANS_MAX_PAYLOAD_LEN);
ses.transseq = 0;
ses.readbuf = NULL;
ses.decryptreadbuf = NULL;
ses.payload = NULL;
ses.recvseq = 0;
initqueue(&ses.writequeue);
ses.requirenext = SSH_MSG_KEXINIT;
ses.dataallowed = 0; /* don't send data yet, we'll wait until after kex */
ses.dataallowed = 1; /* we can send data until we actually
send the SSH_MSG_KEXINIT */
ses.ignorenext = 0;
ses.lastpacket = 0;
ses.reply_queue_head = NULL;
ses.reply_queue_tail = NULL;
/* set all the algos to none */
ses.keys = (struct key_context*)m_malloc(sizeof(struct key_context));
ses.newkeys = NULL;
ses.keys->recv_algo_crypt = &dropbear_nocipher;
ses.keys->trans_algo_crypt = &dropbear_nocipher;
ses.keys->recv.algo_crypt = &dropbear_nocipher;
ses.keys->trans.algo_crypt = &dropbear_nocipher;
ses.keys->recv.crypt_mode = &dropbear_mode_none;
ses.keys->trans.crypt_mode = &dropbear_mode_none;
ses.keys->recv_algo_mac = &dropbear_nohash;
ses.keys->trans_algo_mac = &dropbear_nohash;
ses.keys->recv.algo_mac = &dropbear_nohash;
ses.keys->trans.algo_mac = &dropbear_nohash;
ses.keys->algo_kex = -1;
ses.keys->algo_kex = NULL;
ses.keys->algo_hostkey = -1;
ses.keys->recv_algo_comp = DROPBEAR_COMP_NONE;
ses.keys->trans_algo_comp = DROPBEAR_COMP_NONE;
ses.keys->recv.algo_comp = DROPBEAR_COMP_NONE;
ses.keys->trans.algo_comp = DROPBEAR_COMP_NONE;
#ifndef DISABLE_ZLIB
ses.keys->recv_zstream = NULL;
ses.keys->trans_zstream = NULL;
ses.keys->recv.zstream = NULL;
ses.keys->trans.zstream = NULL;
#endif
/* key exchange buffers */
@@ -125,27 +151,43 @@ void session_loop(void(*loophandler)()) {
/* main loop, select()s for all sockets in use */
for(;;) {
const int writequeue_has_space = (ses.writequeue_len <= 2*TRANS_MAX_PAYLOAD_LEN);
timeout.tv_sec = SELECT_TIMEOUT;
timeout.tv_sec = select_timeout();
timeout.tv_usec = 0;
FD_ZERO(&writefd);
FD_ZERO(&readfd);
dropbear_assert(ses.payload == NULL);
if (ses.sock != -1) {
FD_SET(ses.sock, &readfd);
if (!isempty(&ses.writequeue)) {
FD_SET(ses.sock, &writefd);
}
}
/* We get woken up when signal handlers write to this pipe.
SIGCHLD in svr-chansession is the only one currently. */
FD_SET(ses.signal_pipe[0], &readfd);
ses.channel_signal_pending = 0;
/* set up for channels which require reading/writing */
if (ses.dataallowed) {
setchannelfds(&readfd, &writefd);
/* set up for channels which can be read/written */
setchannelfds(&readfd, &writefd, writequeue_has_space);
/* Pending connections to test */
set_connect_fds(&writefd);
/* We delay reading from the input socket during initial setup until
after we have written out our initial KEXINIT packet (empty writequeue).
This means our initial packet can be in-flight while we're doing a blocking
read for the remote ident.
We also avoid reading from the socket if the writequeue is full, that avoids
replies backing up */
if (ses.sock_in != -1
&& (ses.remoteident || isempty(&ses.writequeue))
&& writequeue_has_space) {
FD_SET(ses.sock_in, &readfd);
}
/* Ordering is important, this test must occur after any other function
might have queued packets (such as connection handlers) */
if (ses.sock_out != -1 && !isempty(&ses.writequeue)) {
FD_SET(ses.sock_out, &writefd);
}
val = select(ses.maxfd+1, &readfd, &writefd, NULL, &timeout);
if (exitflag) {
@@ -170,20 +212,23 @@ void session_loop(void(*loophandler)()) {
wake up the select() above. */
if (FD_ISSET(ses.signal_pipe[0], &readfd)) {
char x;
TRACE(("signal pipe set"))
while (read(ses.signal_pipe[0], &x, 1) > 0) {}
ses.channel_signal_pending = 1;
}
/* check for auth timeout, rekeying required etc */
checktimeouts();
/* process session socket's incoming/outgoing data */
if (ses.sock != -1) {
if (FD_ISSET(ses.sock, &writefd) && !isempty(&ses.writequeue)) {
write_packet();
}
if (FD_ISSET(ses.sock, &readfd)) {
read_packet();
/* process session socket's incoming data */
if (ses.sock_in != -1) {
if (FD_ISSET(ses.sock_in, &readfd)) {
if (!ses.remoteident) {
/* blocking read of the version string */
read_session_identification();
} else {
read_packet();
}
}
/* Process the decrypted packet. After this, the read buffer
@@ -193,12 +238,24 @@ void session_loop(void(*loophandler)()) {
}
}
/* if required, flush out any queued reply packets that
were being held up during a KEX */
maybe_flush_reply_queue();
handle_connect_fds(&writefd);
/* process pipes etc for the channels, ses.dataallowed == 0
* during rekeying ) */
if (ses.dataallowed) {
channelio(&readfd, &writefd);
channelio(&readfd, &writefd);
/* process session socket's outgoing data */
if (ses.sock_out != -1) {
if (!isempty(&ses.writequeue)) {
write_packet();
}
}
if (loophandler) {
loophandler();
}
@@ -208,8 +265,17 @@ void session_loop(void(*loophandler)()) {
/* Not reached */
}
static void cleanup_buf(buffer **buf) {
if (!*buf) {
return;
}
buf_burn(*buf);
buf_free(*buf);
*buf = NULL;
}
/* clean up a session on exit */
void common_session_cleanup() {
void session_cleanup() {
TRACE(("enter session_cleanup"))
@@ -218,34 +284,69 @@ void common_session_cleanup() {
TRACE(("leave session_cleanup: !sessinitdone"))
return;
}
m_free(ses.session_id);
/* BEWARE of changing order of functions here. */
/* Must be before extra_session_cleanup() */
chancleanup();
if (ses.extra_session_cleanup) {
ses.extra_session_cleanup();
}
/* After these are freed most functions will fail */
#ifdef DROPBEAR_CLEANUP
/* listeners call cleanup functions, this should occur before
other session state is freed. */
remove_all_listeners();
remove_connect_pending();
while (!isempty(&ses.writequeue)) {
buf_free(dequeue(&ses.writequeue));
}
m_free(ses.remoteident);
m_free(ses.authstate.pw_dir);
m_free(ses.authstate.pw_name);
m_free(ses.authstate.pw_shell);
m_free(ses.authstate.pw_passwd);
m_free(ses.authstate.username);
#endif
cleanup_buf(&ses.session_id);
cleanup_buf(&ses.hash);
cleanup_buf(&ses.payload);
cleanup_buf(&ses.readbuf);
cleanup_buf(&ses.writepayload);
cleanup_buf(&ses.kexhashbuf);
cleanup_buf(&ses.transkexinit);
if (ses.dh_K) {
mp_clear(ses.dh_K);
}
m_free(ses.dh_K);
m_burn(ses.keys, sizeof(struct key_context));
m_free(ses.keys);
chancleanup();
TRACE(("leave session_cleanup"))
}
void send_session_identification() {
buffer *writebuf = buf_new(strlen(LOCAL_IDENT "\r\n") + 1);
buf_putbytes(writebuf, (const unsigned char *) LOCAL_IDENT "\r\n", strlen(LOCAL_IDENT "\r\n"));
writebuf_enqueue(writebuf, 0);
}
void session_identification() {
static void read_session_identification() {
/* max length of 255 chars */
char linebuf[256];
int len = 0;
char done = 0;
int i;
/* write our version string, this blocks */
if (atomicio(write, ses.sock, LOCAL_IDENT "\r\n",
strlen(LOCAL_IDENT "\r\n")) == DROPBEAR_FAILURE) {
ses.remoteclosed();
}
/* If they send more than 50 lines, something is wrong */
/* If they send more than 50 lines, something is wrong */
for (i = 0; i < 50; i++) {
len = ident_readln(ses.sock, linebuf, sizeof(linebuf));
len = ident_readln(ses.sock_in, linebuf, sizeof(linebuf));
if (len < 0 && errno != EINTR) {
/* It failed */
@@ -260,7 +361,7 @@ void session_identification() {
}
if (!done) {
TRACE(("err: %s for '%s'\n", strerror(errno), linebuf))
TRACE(("error reading remote ident: %s\n", strerror(errno)))
ses.remoteclosed();
} else {
/* linebuf is already null terminated */
@@ -268,11 +369,11 @@ void session_identification() {
memcpy(ses.remoteident, linebuf, len);
}
/* Shall assume that 2.x will be backwards compatible. */
if (strncmp(ses.remoteident, "SSH-2.", 6) != 0
&& strncmp(ses.remoteident, "SSH-1.99-", 9) != 0) {
dropbear_exit("Incompatible remote version '%s'", ses.remoteident);
}
/* Shall assume that 2.x will be backwards compatible. */
if (strncmp(ses.remoteident, "SSH-2.", 6) != 0
&& strncmp(ses.remoteident, "SSH-1.99-", 9) != 0) {
dropbear_exit("Incompatible remote version '%s'", ses.remoteident);
}
TRACE(("remoteident: %s", ses.remoteident))
@@ -352,20 +453,48 @@ static int ident_readln(int fd, char* buf, int count) {
return pos+1;
}
void ignore_recv_response() {
/* Do nothing */
TRACE(("Ignored msg_request_response"))
}
static void send_msg_keepalive() {
time_t old_time_idle = ses.last_packet_time_idle;
struct Channel *chan = get_any_ready_channel();
CHECKCLEARTOWRITE();
if (chan) {
/* Channel requests are preferable, more implementations
handle them than SSH_MSG_GLOBAL_REQUEST */
TRACE(("keepalive channel request %d", chan->index))
start_send_channel_request(chan, DROPBEAR_KEEPALIVE_STRING);
} else {
TRACE(("keepalive global request"))
/* Some peers will reply with SSH_MSG_REQUEST_FAILURE,
some will reply with SSH_MSG_UNIMPLEMENTED, some will exit. */
buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST);
buf_putstring(ses.writepayload, DROPBEAR_KEEPALIVE_STRING,
strlen(DROPBEAR_KEEPALIVE_STRING));
}
buf_putbyte(ses.writepayload, 1); /* want_reply */
encrypt_packet();
ses.last_packet_time_keepalive_sent = monotonic_now();
/* keepalives shouldn't update idle timeout, reset it back */
ses.last_packet_time_idle = old_time_idle;
}
/* Check all timeouts which are required. Currently these are the time for
* user authentication, and the automatic rekeying. */
static void checktimeouts() {
struct timeval tv;
long secs;
if (gettimeofday(&tv, 0) < 0) {
dropbear_exit("Error getting time");
}
secs = tv.tv_sec;
time_t now;
now = monotonic_now();
if (ses.connecttimeout != 0 && secs > ses.connecttimeout) {
if (IS_DROPBEAR_SERVER && ses.connect_time != 0
&& now - ses.connect_time >= AUTH_TIMEOUT) {
dropbear_close("Timeout before auth");
}
@@ -375,10 +504,168 @@ static void checktimeouts() {
}
if (!ses.kexstate.sentkexinit
&& (secs - ses.kexstate.lastkextime >= KEX_REKEY_TIMEOUT
|| ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)){
&& (now - ses.kexstate.lastkextime >= KEX_REKEY_TIMEOUT
|| ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)) {
TRACE(("rekeying after timeout or max data reached"))
send_msg_kexinit();
}
if (opts.keepalive_secs > 0 && ses.authstate.authdone) {
/* Avoid sending keepalives prior to auth - those are
not valid pre-auth packet types */
/* Send keepalives if we've been idle */
if (now - ses.last_packet_time_any_sent >= opts.keepalive_secs) {
send_msg_keepalive();
}
/* Also send an explicit keepalive message to trigger a response
if the remote end hasn't sent us anything */
if (now - ses.last_packet_time_keepalive_recv >= opts.keepalive_secs
&& now - ses.last_packet_time_keepalive_sent >= opts.keepalive_secs) {
send_msg_keepalive();
}
if (now - ses.last_packet_time_keepalive_recv
>= opts.keepalive_secs * DEFAULT_KEEPALIVE_LIMIT) {
dropbear_exit("Keepalive timeout");
}
}
if (opts.idle_timeout_secs > 0
&& now - ses.last_packet_time_idle >= opts.idle_timeout_secs) {
dropbear_close("Idle timeout");
}
}
static void update_timeout(long limit, long now, long last_event, long * timeout) {
TRACE2(("update_timeout limit %ld, now %ld, last %ld, timeout %ld",
limit, now, last_event, *timeout))
if (last_event > 0 && limit > 0) {
*timeout = MIN(*timeout, last_event+limit-now);
TRACE2(("new timeout %ld", *timeout))
}
}
static long select_timeout() {
/* determine the minimum timeout that might be required, so
as to avoid waking when unneccessary */
long timeout = KEX_REKEY_TIMEOUT;
long now = monotonic_now();
if (!ses.kexstate.sentkexinit) {
update_timeout(KEX_REKEY_TIMEOUT, now, ses.kexstate.lastkextime, &timeout);
}
if (ses.authstate.authdone != 1 && IS_DROPBEAR_SERVER) {
/* AUTH_TIMEOUT is only relevant before authdone */
update_timeout(AUTH_TIMEOUT, now, ses.connect_time, &timeout);
}
if (ses.authstate.authdone) {
update_timeout(opts.keepalive_secs, now,
MAX(ses.last_packet_time_keepalive_recv, ses.last_packet_time_keepalive_sent),
&timeout);
}
update_timeout(opts.idle_timeout_secs, now, ses.last_packet_time_idle,
&timeout);
/* clamp negative timeouts to zero - event has already triggered */
return MAX(timeout, 0);
}
const char* get_user_shell() {
/* an empty shell should be interpreted as "/bin/sh" */
if (ses.authstate.pw_shell[0] == '\0') {
return "/bin/sh";
} else {
return ses.authstate.pw_shell;
}
}
void fill_passwd(const char* username) {
struct passwd *pw = NULL;
if (ses.authstate.pw_name)
m_free(ses.authstate.pw_name);
if (ses.authstate.pw_dir)
m_free(ses.authstate.pw_dir);
if (ses.authstate.pw_shell)
m_free(ses.authstate.pw_shell);
if (ses.authstate.pw_passwd)
m_free(ses.authstate.pw_passwd);
pw = getpwnam(username);
if (!pw) {
return;
}
ses.authstate.pw_uid = pw->pw_uid;
ses.authstate.pw_gid = pw->pw_gid;
ses.authstate.pw_name = m_strdup(pw->pw_name);
ses.authstate.pw_dir = m_strdup(pw->pw_dir);
ses.authstate.pw_shell = m_strdup(pw->pw_shell);
{
char *passwd_crypt = pw->pw_passwd;
#ifdef HAVE_SHADOW_H
/* get the shadow password if possible */
struct spwd *spasswd = getspnam(ses.authstate.pw_name);
if (spasswd && spasswd->sp_pwdp) {
passwd_crypt = spasswd->sp_pwdp;
}
#endif
if (!passwd_crypt) {
/* android supposedly returns NULL */
passwd_crypt = "!!";
}
ses.authstate.pw_passwd = m_strdup(passwd_crypt);
}
}
/* Called when channels are modified */
void update_channel_prio() {
enum dropbear_prio new_prio;
int any = 0;
unsigned int i;
TRACE(("update_channel_prio"))
if (ses.sock_out < 0) {
TRACE(("leave update_channel_prio: no socket"))
return;
}
new_prio = DROPBEAR_PRIO_BULK;
for (i = 0; i < ses.chansize; i++) {
struct Channel *channel = ses.channels[i];
if (!channel || channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) {
if (channel && channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) {
TRACE(("update_channel_prio: early %d", channel->index))
}
continue;
}
any = 1;
if (channel->prio == DROPBEAR_CHANNEL_PRIO_INTERACTIVE)
{
TRACE(("update_channel_prio: lowdelay %d", channel->index))
new_prio = DROPBEAR_PRIO_LOWDELAY;
break;
} else if (channel->prio == DROPBEAR_CHANNEL_PRIO_UNKNOWABLE
&& new_prio == DROPBEAR_PRIO_BULK)
{
TRACE(("update_channel_prio: unknowable %d", channel->index))
new_prio = DROPBEAR_PRIO_DEFAULT;
}
}
if (any == 0) {
/* lowdelay during setup */
TRACE(("update_channel_prio: not any"))
new_prio = DROPBEAR_PRIO_LOWDELAY;
}
if (new_prio != ses.socket_prio) {
TRACE(("Dropbear priority transitioning %d -> %d", ses.socket_prio, new_prio))
set_sock_priority(ses.sock_out, new_prio);
ses.socket_prio = new_prio;
}
}

View File

@@ -193,6 +193,10 @@ int daemon(int nochdir, int noclose) {
char *basename(const char *path) {
char *foo = strrchr(path, '/');
if (!foo)
{
return path;
}
return ++foo;
}
@@ -231,7 +235,7 @@ void setusershell() {
static char **initshells() {
/* don't touch this list. */
const char *okshells[] = { "/bin/sh", "/bin/csh", NULL };
static const char *okshells[] = { "/bin/sh", "/bin/csh", NULL };
register char **sp, *cp;
register FILE *fp;
struct stat statb;

View File

@@ -22,8 +22,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#ifndef _COMPAT_H_
#define _COMPAT_H_
#ifndef DROPBEAR_COMPAT_H_
#define DROPBEAR_COMPAT_H_
#include "includes.h"
@@ -44,13 +44,13 @@ char *basename(const char* path);
#endif
#ifndef HAVE_GETUSERSHELL
char *getusershell();
void setusershell();
void endusershell();
char *getusershell(void);
void setusershell(void);
void endusershell(void);
#endif
#ifndef _PATH_DEVNULL
#define _PATH_DEVNULL "/dev/null"
#ifndef DROPBEAR_PATH_DEVNULL
#define DROPBEAR_PATH_DEVNULL "/dev/null"
#endif
#endif /* _COMPAT_H_ */
#endif /* DROPBEAR_COMPAT_H_ */

645
config.guess vendored
View File

@@ -1,14 +1,12 @@
#! /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 Free Software Foundation,
# Inc.
# Copyright 1992-2013 Free Software Foundation, Inc.
timestamp='2007-01-15'
timestamp='2013-06-10'
# 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
# the Free Software Foundation; either version 2 of the License, or
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
@@ -17,26 +15,22 @@ timestamp='2007-01-15'
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program; if not, see <http://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# 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.
# the same distribution terms that you use for the rest of that
# program. This Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").
#
# 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.
# Originally written by Per Bothner.
#
# 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
#
# Please send patches with a ChangeLog entry to config-patches@gnu.org.
me=`echo "$0" | sed -e 's,.*/,,'`
@@ -56,8 +50,7 @@ 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
Free Software Foundation, Inc.
Copyright 1992-2013 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."
@@ -139,12 +132,33 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
case "${UNAME_SYSTEM}" in
Linux|GNU|GNU/*)
# If the system lacks a compiler, then just pick glibc.
# We could probably try harder.
LIBC=gnu
eval $set_cc_for_build
cat <<-EOF > $dummy.c
#include <features.h>
#if defined(__UCLIBC__)
LIBC=uclibc
#elif defined(__dietlibc__)
LIBC=dietlibc
#else
LIBC=gnu
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
;;
esac
# Note: order is significant - the case branches are not exclusive.
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
*:NetBSD:*:*)
# NetBSD (nbsd) targets should (where applicable) match one or
# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
# *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
# switched to ELF, *-*-netbsd* would select the old
# object file format. This provides both forward
@@ -170,7 +184,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?
@@ -180,7 +194,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
fi
;;
*)
os=netbsd
os=netbsd
;;
esac
# The OS release
@@ -201,6 +215,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
echo "${machine}-${os}${release}"
exit ;;
*:Bitrig:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
exit ;;
*:OpenBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
@@ -223,7 +241,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
;;
*5.*)
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
;;
esac
# According to Compaq, /usr/sbin/psrinfo has been available on
@@ -269,7 +287,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
exit ;;
# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
exitcode=$?
trap '' 0
exit $exitcode ;;
Alpha\ *:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# Should we change UNAME_MACHINE based on the output of uname instead
@@ -295,12 +316,12 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
echo s390-ibm-zvmoe
exit ;;
*:OS400:*:*)
echo powerpc-ibm-os400
echo powerpc-ibm-os400
exit ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
echo arm-acorn-riscix${UNAME_RELEASE}
exit ;;
arm:riscos:*:*|arm:RISCOS:*:*)
arm*:riscos:*:*|arm*:RISCOS:*:*)
echo arm-unknown-riscos
exit ;;
SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
@@ -324,14 +345,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:SunOS:5.*:*)
echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
echo i386-pc-auroraux${UNAME_RELEASE}
exit ;;
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
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
@@ -375,23 +415,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# MiNT. But MiNT is downward compatible to TOS, so this should
# be no problem.
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
exit ;;
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
echo m68k-milan-mint${UNAME_RELEASE}
exit ;;
echo m68k-milan-mint${UNAME_RELEASE}
exit ;;
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
echo m68k-hades-mint${UNAME_RELEASE}
exit ;;
echo m68k-hades-mint${UNAME_RELEASE}
exit ;;
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
echo m68k-unknown-mint${UNAME_RELEASE}
exit ;;
echo m68k-unknown-mint${UNAME_RELEASE}
exit ;;
m68k:machten:*:*)
echo m68k-apple-machten${UNAME_RELEASE}
exit ;;
@@ -461,8 +501,8 @@ EOF
echo m88k-motorola-sysv3
exit ;;
AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
then
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
@@ -475,7 +515,7 @@ EOF
else
echo i586-dg-dgux${UNAME_RELEASE}
fi
exit ;;
exit ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
echo m88k-dolphin-sysv3
exit ;;
@@ -532,7 +572,7 @@ EOF
echo rs6000-ibm-aix3.2
fi
exit ;;
*:AIX:*:[45])
*:AIX:*:[4567])
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
IBM_ARCH=rs6000
@@ -575,52 +615,52 @@ EOF
9000/[678][0-9][0-9])
if [ -x /usr/bin/getconf ]; then
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
case "${sc_cpu_version}" in
523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
532) # CPU_PA_RISC2_0
case "${sc_kernel_bits}" in
32) HP_ARCH="hppa2.0n" ;;
64) HP_ARCH="hppa2.0w" ;;
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
case "${sc_cpu_version}" in
523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
532) # CPU_PA_RISC2_0
case "${sc_kernel_bits}" in
32) HP_ARCH="hppa2.0n" ;;
64) HP_ARCH="hppa2.0w" ;;
'') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
esac ;;
esac
esac ;;
esac
fi
if [ "${HP_ARCH}" = "" ]; then
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
sed 's/^ //' << EOF >$dummy.c
#define _HPUX_SOURCE
#include <stdlib.h>
#include <unistd.h>
#define _HPUX_SOURCE
#include <stdlib.h>
#include <unistd.h>
int main ()
{
#if defined(_SC_KERNEL_BITS)
long bits = sysconf(_SC_KERNEL_BITS);
#endif
long cpu = sysconf (_SC_CPU_VERSION);
int main ()
{
#if defined(_SC_KERNEL_BITS)
long bits = sysconf(_SC_KERNEL_BITS);
#endif
long cpu = sysconf (_SC_CPU_VERSION);
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
case CPU_PA_RISC2_0:
#if defined(_SC_KERNEL_BITS)
switch (bits)
{
case 64: puts ("hppa2.0w"); break;
case 32: puts ("hppa2.0n"); break;
default: puts ("hppa2.0"); break;
} break;
#else /* !defined(_SC_KERNEL_BITS) */
puts ("hppa2.0"); break;
#endif
default: puts ("hppa1.0"); break;
}
exit (0);
}
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
case CPU_PA_RISC2_0:
#if defined(_SC_KERNEL_BITS)
switch (bits)
{
case 64: puts ("hppa2.0w"); break;
case 32: puts ("hppa2.0n"); break;
default: puts ("hppa2.0"); break;
} break;
#else /* !defined(_SC_KERNEL_BITS) */
puts ("hppa2.0"); break;
#endif
default: puts ("hppa1.0"); break;
}
exit (0);
}
EOF
(CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
test -z "$HP_ARCH" && HP_ARCH=hppa
@@ -640,7 +680,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
@@ -711,22 +751,22 @@ EOF
exit ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
echo c1-convex-bsd
exit ;;
exit ;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit ;;
exit ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
echo c34-convex-bsd
exit ;;
exit ;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
echo c38-convex-bsd
exit ;;
exit ;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
echo c4-convex-bsd
exit ;;
exit ;;
CRAY*Y-MP:*:*:*)
echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
@@ -750,14 +790,14 @@ EOF
exit ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
5000:UNIX_System_V:4.*:*)
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
@@ -769,37 +809,51 @@ EOF
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
exit ;;
*:FreeBSD:*:*)
case ${UNAME_MACHINE} in
pc98)
echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
UNAME_PROCESSOR=`/usr/bin/uname -p`
case ${UNAME_PROCESSOR} in
amd64)
echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
*)
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
esac
exit ;;
i*:CYGWIN*:*)
echo ${UNAME_MACHINE}-pc-cygwin
exit ;;
*:MINGW64*:*)
echo ${UNAME_MACHINE}-pc-mingw64
exit ;;
*:MINGW*:*)
echo ${UNAME_MACHINE}-pc-mingw32
exit ;;
i*:MSYS*:*)
echo ${UNAME_MACHINE}-pc-msys
exit ;;
i*:windows32*:*)
# uname -m includes "-pc" on this system.
echo ${UNAME_MACHINE}-mingw32
# uname -m includes "-pc" on this system.
echo ${UNAME_MACHINE}-mingw32
exit ;;
i*:PW*:*)
echo ${UNAME_MACHINE}-pc-pw32
exit ;;
x86:Interix*:[3456]*)
echo i586-pc-interix${UNAME_RELEASE}
exit ;;
EM64T:Interix*:[3456]* | authenticamd:Interix*:[3456]*)
echo x86_64-unknown-interix${UNAME_RELEASE}
exit ;;
*:Interix*:*)
case ${UNAME_MACHINE} in
x86)
echo i586-pc-interix${UNAME_RELEASE}
exit ;;
authenticamd | genuineintel | EM64T)
echo x86_64-unknown-interix${UNAME_RELEASE}
exit ;;
IA64)
echo ia64-unknown-interix${UNAME_RELEASE}
exit ;;
esac ;;
[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
@@ -820,93 +874,21 @@ EOF
exit ;;
*:GNU:*:*)
# the GNU system
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
exit ;;
*:GNU/*:*:*)
# other systems with GNU libc and userland
echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
exit ;;
i*86:Minix:*:*)
echo ${UNAME_MACHINE}-pc-minix
exit ;;
arm*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
aarch64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
avr32*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
cris:Linux:*:*)
echo cris-axis-linux-gnu
exit ;;
crisv32:Linux:*:*)
echo crisv32-axis-linux-gnu
exit ;;
frv:Linux:*:*)
echo frv-unknown-linux-gnu
exit ;;
ia64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
m32r*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
m68*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
mips:Linux:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#undef CPU
#undef mips
#undef mipsel
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
CPU=mipsel
#else
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
CPU=mips
#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
}'`"
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
exit ;;
ppc64:Linux:*:*)
echo powerpc64-unknown-linux-gnu
aarch64_be:Linux:*:*)
UNAME_MACHINE=aarch64_be
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
alpha:Linux:*:*)
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
@@ -917,106 +899,132 @@ EOF
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}
esac
objdump --private-headers /bin/sh | grep -q ld.so.1
if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
arc:Linux:*:* | arceb:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
arm*:Linux:*:*)
eval $set_cc_for_build
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_EABI__
then
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
else
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
else
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
fi
fi
exit ;;
avr32*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
cris:Linux:*:*)
echo ${UNAME_MACHINE}-axis-linux-${LIBC}
exit ;;
crisv32:Linux:*:*)
echo ${UNAME_MACHINE}-axis-linux-${LIBC}
exit ;;
frv:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
hexagon:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
i*86:Linux:*:*)
echo ${UNAME_MACHINE}-pc-linux-${LIBC}
exit ;;
ia64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
m32r*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
m68*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
mips:Linux:*:* | mips64:Linux:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#undef CPU
#undef ${UNAME_MACHINE}
#undef ${UNAME_MACHINE}el
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
CPU=${UNAME_MACHINE}el
#else
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
CPU=${UNAME_MACHINE}
#else
CPU=
#endif
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
;;
or1k:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
or32:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
padre:Linux:*:*)
echo sparc-unknown-linux-${LIBC}
exit ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
echo hppa64-unknown-linux-${LIBC}
exit ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
PA7*) echo hppa1.1-unknown-linux-gnu ;;
PA8*) echo hppa2.0-unknown-linux-gnu ;;
*) echo hppa-unknown-linux-gnu ;;
PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
*) echo hppa-unknown-linux-${LIBC} ;;
esac
exit ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
echo hppa64-unknown-linux-gnu
ppc64:Linux:*:*)
echo powerpc64-unknown-linux-${LIBC}
exit ;;
ppc:Linux:*:*)
echo powerpc-unknown-linux-${LIBC}
exit ;;
ppc64le:Linux:*:*)
echo powerpc64le-unknown-linux-${LIBC}
exit ;;
ppcle:Linux:*:*)
echo powerpcle-unknown-linux-${LIBC}
exit ;;
s390:Linux:*:* | s390x:Linux:*:*)
echo ${UNAME_MACHINE}-ibm-linux
echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
exit ;;
sh64*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
sh*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
sparc:Linux:*:* | sparc64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
tile*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
vax:Linux:*:*)
echo ${UNAME_MACHINE}-dec-linux-gnu
echo ${UNAME_MACHINE}-dec-linux-${LIBC}
exit ;;
x86_64:Linux:*:*)
echo x86_64-unknown-linux-gnu
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
xtensa:Linux:*:*)
echo xtensa-unknown-linux-gnu
xtensa*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
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 ;;
coff-i386)
echo "${UNAME_MACHINE}-pc-linux-gnucoff"
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
@@ -1024,11 +1032,11 @@ EOF
echo i386-sequent-sysv4
exit ;;
i*86:UNIX_SV:4.2MP:2.*)
# Unixware is an offshoot of SVR4, but it has its own version
# number series starting with 2...
# I am not positive that other SVR4 systems won't match this,
# Unixware is an offshoot of SVR4, but it has its own version
# number series starting with 2...
# I am not positive that other SVR4 systems won't match this,
# I just have to hope. -- rms.
# Use sysv4.2uw... so that sysv4* matches it.
# Use sysv4.2uw... so that sysv4* matches it.
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
exit ;;
i*86:OS/2:*:*)
@@ -1045,7 +1053,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:*:*)
@@ -1060,7 +1068,7 @@ EOF
fi
exit ;;
i*86:*:5:[678]*)
# UnixWare 7.x, OpenUNIX and OpenServer 6.
# UnixWare 7.x, OpenUNIX and OpenServer 6.
case `/bin/uname -X | grep "^Machine"` in
*486*) UNAME_MACHINE=i486 ;;
*Pentium) UNAME_MACHINE=i586 ;;
@@ -1088,10 +1096,13 @@ EOF
exit ;;
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
exit ;;
# uname -m prints for DJGPP always 'pc', but it prints nothing about
# 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
exit ;;
@@ -1126,8 +1137,18 @@ EOF
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4; exit; } ;;
/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 ;;
@@ -1140,7 +1161,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:*:*)
@@ -1160,10 +1181,10 @@ EOF
echo ns32k-sni-sysv
fi
exit ;;
PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
# says <Richard.M.Bartel@ccMail.Census.GOV>
echo i586-unisys-sysv4
exit ;;
PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
# says <Richard.M.Bartel@ccMail.Census.GOV>
echo i586-unisys-sysv4
exit ;;
*:UNIX_System_V:4*:FTX*)
# From Gerald Hewes <hewes@openmarket.com>.
# How about differentiating between stratus architectures? -djm
@@ -1189,11 +1210,11 @@ EOF
exit ;;
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
if [ -d /usr/nec ]; then
echo mips-nec-sysv${UNAME_RELEASE}
echo mips-nec-sysv${UNAME_RELEASE}
else
echo mips-unknown-sysv${UNAME_RELEASE}
echo mips-unknown-sysv${UNAME_RELEASE}
fi
exit ;;
exit ;;
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
echo powerpc-be-beos
exit ;;
@@ -1203,6 +1224,12 @@ EOF
BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
echo i586-pc-beos
exit ;;
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
echo i586-pc-haiku
exit ;;
x86_64:Haiku:*:*)
echo x86_64-unknown-haiku
exit ;;
SX-4:SUPER-UX:*:*)
echo sx4-nec-superux${UNAME_RELEASE}
exit ;;
@@ -1229,9 +1256,21 @@ EOF
exit ;;
*:Darwin:*:*)
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
case $UNAME_PROCESSOR in
unknown) UNAME_PROCESSOR=powerpc ;;
esac
eval $set_cc_for_build
if test "$UNAME_PROCESSOR" = unknown ; then
UNAME_PROCESSOR=powerpc
fi
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
case $UNAME_PROCESSOR in
i386) UNAME_PROCESSOR=x86_64 ;;
powerpc) UNAME_PROCESSOR=powerpc64 ;;
esac
fi
fi
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
exit ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
@@ -1245,7 +1284,10 @@ EOF
*:QNX:*:4*)
echo i386-pc-qnx
exit ;;
NSE-?:NONSTOP_KERNEL:*:*)
NEO-?:NONSTOP_KERNEL:*:*)
echo neo-tandem-nsk${UNAME_RELEASE}
exit ;;
NSE-*:NONSTOP_KERNEL:*:*)
echo nse-tandem-nsk${UNAME_RELEASE}
exit ;;
NSR-?:NONSTOP_KERNEL:*:*)
@@ -1290,13 +1332,13 @@ EOF
echo pdp10-unknown-its
exit ;;
SEI:*:*:SEIUX)
echo mips-sei-seiux${UNAME_RELEASE}
echo mips-sei-seiux${UNAME_RELEASE}
exit ;;
*:DragonFly:*:*)
echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
exit ;;
*:*VMS:*:*)
UNAME_MACHINE=`(uname -p) 2>/dev/null`
UNAME_MACHINE=`(uname -p) 2>/dev/null`
case "${UNAME_MACHINE}" in
A*) echo alpha-dec-vms ; exit ;;
I*) echo ia64-dec-vms ; exit ;;
@@ -1311,11 +1353,14 @@ EOF
i*86:rdos:*:*)
echo ${UNAME_MACHINE}-pc-rdos
exit ;;
i*86:AROS:*:*)
echo ${UNAME_MACHINE}-pc-aros
exit ;;
x86_64:VMkernel:*:*)
echo ${UNAME_MACHINE}-unknown-esx
exit ;;
esac
#echo '(No uname command or uname output not recognized.)' 1>&2
#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
eval $set_cc_for_build
cat >$dummy.c <<EOF
#ifdef _SEQUENT_
@@ -1333,11 +1378,11 @@ main ()
#include <sys/param.h>
printf ("m68k-sony-newsos%s\n",
#ifdef NEWSOS4
"4"
"4"
#else
""
""
#endif
); exit (0);
); exit (0);
#endif
#endif
@@ -1471,9 +1516,9 @@ This script, last modified $timestamp, has failed to recognize
the operating system you are using. It is advised that you
download the most up to date version of the config scripts from
http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
and
http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
If the version you run ($0) is already up to date, please
send the following data and any information you think might be

379
config.sub vendored
View File

@@ -1,44 +1,40 @@
#! /bin/sh
# Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
# Inc.
# Copyright 1992-2013 Free Software Foundation, Inc.
timestamp='2007-01-18'
timestamp='2013-10-01'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
# can handle that machine. It does not imply ALL GNU software can.
#
# 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
# the Free Software Foundation; either version 2 of the License, or
# 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
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program; if not, see <http://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# the same distribution terms that you use for the rest of that
# program. This Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").
# Please send patches to <config-patches@gnu.org>. Submit a context
# diff and a properly formatted ChangeLog entry.
# Please send patches with a ChangeLog entry to config-patches@gnu.org.
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
# Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from:
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
# that are meaningful with *any* GNU software.
@@ -72,8 +68,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
Copyright 1992-2013 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."
@@ -120,12 +115,18 @@ esac
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
knetbsd*-gnu* | netbsd*-gnu* | \
kopensolaris*-gnu* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
android-linux)
os=-linux-android
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
;;
*)
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
if [ $basic_machine != $1 ]
@@ -148,10 +149,13 @@ case $os in
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-apple | -axis | -knuth | -cray)
-apple | -axis | -knuth | -cray | -microblaze*)
os=
basic_machine=$1
;;
-bluegene*)
os=-cnk
;;
-sim | -cisco | -oki | -wec | -winbond)
os=
basic_machine=$1
@@ -166,10 +170,10 @@ case $os in
os=-chorusos
basic_machine=$1
;;
-chorusrdb)
os=-chorusrdb
-chorusrdb)
os=-chorusrdb
basic_machine=$1
;;
;;
-hiux*)
os=-hiuxwe2
;;
@@ -214,6 +218,12 @@ case $os in
-isc*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-lynx*178)
os=-lynxos178
;;
-lynx*5)
os=-lynxos5
;;
-lynx*)
os=-lynxos
;;
@@ -238,24 +248,35 @@ case $basic_machine in
# Some are omitted here because they have special meanings below.
1750a | 580 \
| a29k \
| aarch64 | aarch64_be \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
| arc | arceb \
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
| avr | avr32 \
| be32 | be64 \
| bfin \
| c4x | clipper \
| c4x | c8051 | clipper \
| d10v | d30v | dlx | dsp16xx \
| epiphany \
| fido | fr30 | frv \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| hexagon \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
| k1om \
| le32 | le64 \
| lm32 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
| maxq | mb | microblaze | mcore | mep \
| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
| mips64vr | mips64vrel \
| mips64octeon | mips64octeonel \
| mips64orion | mips64orionel \
| mips64r5900 | mips64r5900el \
| mips64vr | mips64vrel \
| mips64vr4100 | mips64vr4100el \
| mips64vr4300 | mips64vr4300el \
| mips64vr5000 | mips64vr5000el \
@@ -266,31 +287,45 @@ case $basic_machine in
| mipsisa64r2 | mipsisa64r2el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
| mipsr5900 | mipsr5900el \
| mipstx39 | mipstx39el \
| mn10200 | mn10300 \
| moxie \
| mt \
| msp430 \
| nios | nios2 \
| nds32 | nds32le | nds32be \
| nios | nios2 | nios2eb | nios2el \
| ns16k | ns32k \
| or32 \
| open8 \
| or1k | or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
| powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
| rl78 | rx \
| score \
| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
| spu | strongarm \
| tahoe | thumb | tic4x | tic80 | tron \
| v850 | v850e \
| spu \
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
| ubicom32 \
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
| we32k \
| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
| z8k)
| x86 | xc16x | xstormy16 | xtensa \
| z8k | z80)
basic_machine=$basic_machine-unknown
;;
m6811 | m68hc11 | m6812 | m68hc12)
# Motorola 68HC11/12.
c54x)
basic_machine=tic54x-unknown
;;
c55x)
basic_machine=tic55x-unknown
;;
c6x)
basic_machine=tic6x-unknown
;;
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
basic_machine=$basic_machine-unknown
os=-none
;;
@@ -300,6 +335,21 @@ case $basic_machine in
basic_machine=mt-unknown
;;
strongarm | thumb | xscale)
basic_machine=arm-unknown
;;
xgate)
basic_machine=$basic_machine-unknown
os=-none
;;
xscaleeb)
basic_machine=armeb-unknown
;;
xscaleel)
basic_machine=armel-unknown
;;
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
@@ -314,29 +364,38 @@ case $basic_machine in
# Recognize the basic CPU types with company name.
580-* \
| a29k-* \
| aarch64-* | aarch64_be-* \
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* | avr32-* \
| be32-* | be64-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
| clipper-* | craynv-* | cydra-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* \
| c8051-* | clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
| k1om-* \
| le32-* | le64-* \
| lm32-* \
| m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
| m88110-* | m88k-* | maxq-* | mcore-* \
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
| microblaze-* | microblazeel-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
| mips16-* \
| mips64-* | mips64el-* \
| mips64vr-* | mips64vrel-* \
| mips64octeon-* | mips64octeonel-* \
| mips64orion-* | mips64orionel-* \
| mips64r5900-* | mips64r5900el-* \
| mips64vr-* | mips64vrel-* \
| mips64vr4100-* | mips64vr4100el-* \
| mips64vr4300-* | mips64vr4300el-* \
| mips64vr5000-* | mips64vr5000el-* \
@@ -347,31 +406,41 @@ case $basic_machine in
| mipsisa64r2-* | mipsisa64r2el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipsr5900-* | mipsr5900el-* \
| mipstx39-* | mipstx39el-* \
| mmix-* \
| mt-* \
| msp430-* \
| nios-* | nios2-* \
| nds32-* | nds32le-* | nds32be-* \
| nios-* | nios2-* | nios2eb-* | nios2el-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| open8-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
| pyramid-* \
| romp-* | rs6000-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| rl78-* | romp-* | rs6000-* | rx-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
| tahoe-* | thumb-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
| tahoe-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tile*-* \
| tron-* \
| v850-* | v850e-* | vax-* \
| ubicom32-* \
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
| vax-* \
| we32k-* \
| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
| xstormy16-* | xtensa-* \
| x86-* | x86_64-* | xc16x-* | xps100-* \
| xstormy16-* | xtensa*-* \
| ymp-* \
| z8k-*)
| z8k-* | z80-*)
;;
# Recognize the basic CPU types without company name, with glob match.
xtensa*)
basic_machine=$basic_machine-unknown
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
@@ -389,7 +458,7 @@ case $basic_machine in
basic_machine=a29k-amd
os=-udi
;;
abacus)
abacus)
basic_machine=abacus-unknown
;;
adobe68k)
@@ -435,6 +504,10 @@ case $basic_machine in
basic_machine=m68k-apollo
os=-bsd
;;
aros)
basic_machine=i386-pc
os=-aros
;;
aux)
basic_machine=m68k-apple
os=-aux
@@ -443,10 +516,35 @@ case $basic_machine in
basic_machine=ns32k-sequent
os=-dynix
;;
blackfin)
basic_machine=bfin-unknown
os=-linux
;;
blackfin-*)
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
bluegene*)
basic_machine=powerpc-ibm
os=-cnk
;;
c54x-*)
basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c55x-*)
basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c6x-*)
basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c90)
basic_machine=c90-cray
os=-unicos
;;
cegcc)
basic_machine=arm-unknown
os=-cegcc
;;
convex-c1)
basic_machine=c1-convex
os=-bsd
@@ -475,8 +573,8 @@ case $basic_machine in
basic_machine=craynv-cray
os=-unicosmp
;;
cr16c)
basic_machine=cr16c-unknown
cr16 | cr16-*)
basic_machine=cr16-unknown
os=-elf
;;
crds | unos)
@@ -514,6 +612,10 @@ case $basic_machine in
basic_machine=m88k-motorola
os=-sysv3
;;
dicos)
basic_machine=i686-pc
os=-dicos
;;
djgpp)
basic_machine=i586-pc
os=-msdosdjgpp
@@ -629,7 +731,6 @@ case $basic_machine in
i370-ibm* | ibm*)
basic_machine=i370-ibm
;;
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
i*86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv32
@@ -668,6 +769,14 @@ case $basic_machine in
basic_machine=m68k-isi
os=-sysv
;;
m68knommu)
basic_machine=m68k-unknown
os=-linux
;;
m68knommu-*)
basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
m88k-omron*)
basic_machine=m88k-omron
;;
@@ -679,10 +788,21 @@ case $basic_machine in
basic_machine=ns32k-utek
os=-sysv
;;
microblaze*)
basic_machine=microblaze-xilinx
;;
mingw64)
basic_machine=x86_64-pc
os=-mingw64
;;
mingw32)
basic_machine=i386-pc
basic_machine=i686-pc
os=-mingw32
;;
mingw32ce)
basic_machine=arm-unknown
os=-mingw32ce
;;
miniframe)
basic_machine=m68000-convergent
;;
@@ -711,10 +831,18 @@ case $basic_machine in
ms1-*)
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
;;
msys)
basic_machine=i686-pc
os=-msys
;;
mvs)
basic_machine=i370-ibm
os=-mvs
;;
nacl)
basic_machine=le32-unknown
os=-nacl
;;
ncr3000)
basic_machine=i486-ncr
os=-sysv4
@@ -779,6 +907,12 @@ case $basic_machine in
np1)
basic_machine=np1-gould
;;
neo-tandem)
basic_machine=neo-tandem
;;
nse-tandem)
basic_machine=nse-tandem
;;
nsr-tandem)
basic_machine=nsr-tandem
;;
@@ -809,6 +943,14 @@ case $basic_machine in
basic_machine=i860-intel
os=-osf
;;
parisc)
basic_machine=hppa-unknown
os=-linux
;;
parisc-*)
basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
pbd)
basic_machine=sparc-tti
;;
@@ -853,9 +995,10 @@ case $basic_machine in
;;
power) basic_machine=power-ibm
;;
ppc) basic_machine=powerpc-unknown
ppc | ppcbe) basic_machine=powerpc-unknown
;;
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
ppc-* | ppcbe-*)
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppcle | powerpclittle | ppc-le | powerpc-little)
basic_machine=powerpcle-unknown
@@ -880,7 +1023,11 @@ case $basic_machine in
basic_machine=i586-unknown
os=-pw32
;;
rdos)
rdos | rdos64)
basic_machine=x86_64-pc
os=-rdos
;;
rdos32)
basic_machine=i386-pc
os=-rdos
;;
@@ -949,6 +1096,9 @@ case $basic_machine in
basic_machine=i860-stratus
os=-sysv4
;;
strongarm-* | thumb-*)
basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
sun2)
basic_machine=m68000-sun
;;
@@ -1005,17 +1155,9 @@ case $basic_machine in
basic_machine=t90-cray
os=-unicos
;;
tic54x | c54x*)
basic_machine=tic54x-unknown
os=-coff
;;
tic55x | c55x*)
basic_machine=tic55x-unknown
os=-coff
;;
tic6x | c6x*)
basic_machine=tic6x-unknown
os=-coff
tile*)
basic_machine=$basic_machine-unknown
os=-linux-gnu
;;
tx39)
basic_machine=mipstx39-unknown
@@ -1084,6 +1226,9 @@ case $basic_machine in
xps | xps100)
basic_machine=xps100-honeywell
;;
xscale-* | xscalee[bl]-*)
basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
;;
ymp)
basic_machine=ymp-cray
os=-unicos
@@ -1092,6 +1237,10 @@ case $basic_machine in
basic_machine=z8k-unknown
os=-sim
;;
z80-*-coff)
basic_machine=z80-unknown
os=-sim
;;
none)
basic_machine=none-none
os=-none
@@ -1130,7 +1279,7 @@ case $basic_machine in
we32k)
basic_machine=we32k-att
;;
sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
@@ -1177,9 +1326,12 @@ esac
if [ x"$os" != x"" ]
then
case $os in
# First match some system type aliases
# that might get confused with valid system types.
# First match some system type aliases
# that might get confused with valid system types.
# -solaris* is a basic system type, with this one exception.
-auroraux)
os=-auroraux
;;
-solaris1 | -solaris1.*)
os=`echo $os | sed -e 's|solaris1|sunos4|'`
;;
@@ -1200,21 +1352,23 @@ case $os in
# Each alternative MUST END IN A *, to match a version number.
# -sysv* is not here because it comes later, after sysvr4.
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
| -sym* | -kopensolaris* | -plan9* \
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
| -aos* \
| -aos* | -aros* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
| -openbsd* | -solidbsd* \
| -bitrig* | -openbsd* | -solidbsd* \
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* \
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
| -chorusos* | -chorusrdb* | -cegcc* \
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
@@ -1222,7 +1376,7 @@ case $os in
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
| -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@@ -1261,7 +1415,7 @@ case $os in
-opened*)
os=-openedition
;;
-os400*)
-os400*)
os=-os400
;;
-wince*)
@@ -1310,7 +1464,7 @@ case $os in
-sinix*)
os=-sysv4
;;
-tpf*)
-tpf*)
os=-tpf
;;
-triton*)
@@ -1346,12 +1500,14 @@ case $os in
-aros*)
os=-aros
;;
-kaos*)
os=-kaos
;;
-zvmoe)
os=-zvmoe
;;
-dicos*)
os=-dicos
;;
-nacl*)
;;
-none)
;;
*)
@@ -1374,10 +1530,10 @@ else
# system, and we'll never get to this point.
case $basic_machine in
score-*)
score-*)
os=-elf
;;
spu-*)
spu-*)
os=-elf
;;
*-acorn)
@@ -1389,8 +1545,23 @@ case $basic_machine in
arm*-semi)
os=-aout
;;
c4x-* | tic4x-*)
os=-coff
c4x-* | tic4x-*)
os=-coff
;;
c8051-*)
os=-elf
;;
hexagon-*)
os=-elf
;;
tic54x-*)
os=-coff
;;
tic55x-*)
os=-coff
;;
tic6x-*)
os=-coff
;;
# This must come before the *-dec entry.
pdp10-*)
@@ -1410,14 +1581,11 @@ case $basic_machine in
;;
m68000-sun)
os=-sunos3
# This also exists in the configure program, but was not the
# default.
# os=-sunos4
;;
m68*-cisco)
os=-aout
;;
mep-*)
mep-*)
os=-elf
;;
mips*-cisco)
@@ -1426,6 +1594,9 @@ case $basic_machine in
mips*-*)
os=-elf
;;
or1k-*)
os=-elf
;;
or32-*)
os=-coff
;;
@@ -1444,7 +1615,7 @@ case $basic_machine in
*-ibm)
os=-aix
;;
*-knuth)
*-knuth)
os=-mmixware
;;
*-wec)
@@ -1549,7 +1720,7 @@ case $basic_machine in
-sunos*)
vendor=sun
;;
-aix*)
-cnk*|-aix*)
vendor=ibm
;;
-beos*)

View File

@@ -5,8 +5,9 @@
# of the platform checks have been taken straight from OpenSSH's configure.ac
# Huge thanks to them for dealing with the horrible platform-specifics :)
AC_PREREQ(2.50)
AC_INIT(buffer.c)
AC_PREREQ(2.59)
AC_INIT
AC_CONFIG_SRCDIR(buffer.c)
OLDCFLAGS=$CFLAGS
# Checks for programs.
@@ -20,7 +21,7 @@ AC_SUBST(LD)
if test -z "$OLDCFLAGS" && test "$GCC" = "yes"; then
AC_MSG_NOTICE(No \$CFLAGS set... using "-Os -W -Wall" for GCC)
CFLAGS="-Os -W -Wall"
CFLAGS="-Os -W -Wall -Wno-pointer-sign"
fi
# large file support is useful for scp
@@ -81,8 +82,19 @@ AC_CHECK_DECL(__UCLIBC__,
AC_MSG_NOTICE([Using uClibc - login() and logout() probably don't work, so we won't use them.])
],,,)
# Checks for libraries.
AC_CHECK_LIB(crypt, crypt, LIBS="$LIBS -lcrypt")
dnl We test for crypt() specially. On Linux (and others?) it resides in libcrypt
dnl but we don't want link all binaries to -lcrypt, just dropbear server.
dnl OS X doesn't need -lcrypt
AC_CHECK_FUNC(crypt, found_crypt_func=here)
AC_CHECK_LIB(crypt, crypt,
[
CRYPTLIB="-lcrypt"
found_crypt_func=here
])
AC_SUBST(CRYPTLIB)
if test "t$found_crypt_func" = there; then
AC_DEFINE(HAVE_CRYPT, 1, [crypt() function])
fi
# Check if zlib is needed
AC_ARG_WITH(zlib,
@@ -145,6 +157,7 @@ AC_ARG_ENABLE(pam,
if test "x$enableval" = "xyes"; then
AC_CHECK_LIB(pam, pam_authenticate, , AC_MSG_ERROR([*** PAM missing - install first or check config.log ***]))
AC_MSG_NOTICE(Enabling PAM)
AC_CHECK_FUNCS(pam_fail_delay)
else
AC_DEFINE(DISABLE_PAM,, Use PAM)
AC_MSG_NOTICE(Disabling PAM)
@@ -209,7 +222,7 @@ AC_ARG_ENABLE(shadow,
# Checks for header files.
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS([fcntl.h limits.h netinet/in.h netinet/tcp.h stdlib.h string.h sys/socket.h sys/time.h termios.h unistd.h crypt.h pty.h ioctl.h libutil.h libgen.h inttypes.h stropts.h utmp.h utmpx.h lastlog.h paths.h util.h netdb.h security/pam_appl.h pam/pam_appl.h netinet/in_systm.h])
AC_CHECK_HEADERS([fcntl.h limits.h netinet/in.h netinet/tcp.h stdlib.h string.h sys/socket.h sys/time.h termios.h unistd.h crypt.h pty.h ioctl.h libutil.h libgen.h inttypes.h stropts.h utmp.h utmpx.h lastlog.h paths.h util.h netdb.h security/pam_appl.h pam/pam_appl.h netinet/in_systm.h sys/uio.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
@@ -219,7 +232,8 @@ AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_HEADER_TIME
AC_CHECK_TYPES([uint16_t, u_int16_t, struct sockaddr_storage])
AC_CHECK_TYPES([uint8_t, u_int8_t, uint16_t, u_int16_t, uint32_t, u_int32_t])
AC_CHECK_TYPES([struct sockaddr_storage])
AC_CHECK_TYPE([socklen_t], ,[
AC_MSG_CHECKING([for socklen_t equivalent])
AC_CACHE_VAL([curl_cv_socklen_t_equiv],
@@ -229,15 +243,15 @@ AC_CHECK_TYPE([socklen_t], ,[
curl_cv_socklen_t_equiv=
for arg2 in "struct sockaddr" void; do
for t in int size_t unsigned long "unsigned long"; do
AC_TRY_COMPILE([
#include <sys/types.h>
#include <sys/socket.h>
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <sys/socket.h>
int getpeername (int, $arg2 *, $t *);
],[
]],[[
$t len;
getpeername(0,0,&len);
],[
]])],[
curl_cv_socklen_t_equiv="$t"
break
])
@@ -257,12 +271,11 @@ AC_CHECK_TYPE([socklen_t], ,[
# for the fake-rfc2553 stuff - straight from OpenSSH
AC_CACHE_CHECK([for struct sockaddr_storage], ac_cv_have_struct_sockaddr_storage, [
AC_TRY_COMPILE(
[
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <sys/socket.h>
],
[ struct sockaddr_storage s; ],
]],
[[ if (sizeof(struct sockaddr_storage)) return 0 ]])],
[ ac_cv_have_struct_sockaddr_storage="yes" ],
[ ac_cv_have_struct_sockaddr_storage="no" ]
)
@@ -272,12 +285,11 @@ if test "x$ac_cv_have_struct_sockaddr_storage" = "xyes" ; then
fi
AC_CACHE_CHECK([for struct sockaddr_in6], ac_cv_have_struct_sockaddr_in6, [
AC_TRY_COMPILE(
[
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <netinet/in.h>
],
[ struct sockaddr_in6 s; s.sin6_family = 0; ],
]],
[[ if (sizeof(struct sockaddr_in6)) return 0 ]])],
[ ac_cv_have_struct_sockaddr_in6="yes" ],
[ ac_cv_have_struct_sockaddr_in6="no" ]
)
@@ -287,12 +299,11 @@ if test "x$ac_cv_have_struct_sockaddr_in6" = "xyes" ; then
fi
AC_CACHE_CHECK([for struct in6_addr], ac_cv_have_struct_in6_addr, [
AC_TRY_COMPILE(
[
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <netinet/in.h>
],
[ struct in6_addr s; s.s6_addr[0] = 0; ],
]],
[[ if (sizeof(struct in6_addr)) return 0 ]])],
[ ac_cv_have_struct_in6_addr="yes" ],
[ ac_cv_have_struct_in6_addr="no" ]
)
@@ -302,13 +313,12 @@ if test "x$ac_cv_have_struct_in6_addr" = "xyes" ; then
fi
AC_CACHE_CHECK([for struct addrinfo], ac_cv_have_struct_addrinfo, [
AC_TRY_COMPILE(
[
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
],
[ struct addrinfo s; s.ai_flags = AI_PASSIVE; ],
]],
[[ if (sizeof(struct addrinfo)) return 0 ]])],
[ ac_cv_have_struct_addrinfo="yes" ],
[ ac_cv_have_struct_addrinfo="no" ]
)
@@ -321,15 +331,15 @@ fi
# IRIX has a const char return value for gai_strerror()
AC_CHECK_FUNCS(gai_strerror,[
AC_DEFINE(HAVE_GAI_STRERROR)
AC_TRY_COMPILE([
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
const char *gai_strerror(int);],[
const char *gai_strerror(int);]],[[
char *str;
str = gai_strerror(0);],[
str = gai_strerror(0);]])],[
AC_DEFINE(HAVE_CONST_GAI_STRERROR_PROTO, 1,
[Define if gai_strerror() returns const char *])])])
@@ -361,6 +371,43 @@ AC_CHECK_FUNCS(endutxent getutxent getutxid getutxline pututxline )
AC_CHECK_FUNCS(setutxent utmpxname)
AC_CHECK_FUNCS(logout updwtmp logwtmp)
# OS X monotonic time
AC_CHECK_HEADERS([mach/mach_time.h])
AC_CHECK_FUNCS(mach_absolute_time)
AC_CHECK_FUNCS(explicit_bzero memset_s)
AC_ARG_ENABLE(bundled-libtom,
[ --enable-bundled-libtom Force using bundled libtomcrypt/libtommath even if a system version exists.
--disable-bundled-libtom Force using system libtomcrypt/libtommath, fail if it does not exist.
Default is to use system if available, otherwise bundled.],
[
if test "x$enableval" = "xyes"; then
BUNDLED_LIBTOM=1
AC_MSG_NOTICE(Forcing bundled libtom*)
else
BUNDLED_LIBTOM=0
AC_CHECK_LIB(tommath, mp_exptmod, LIBTOM_LIBS="$LIBTOM_LIBS -ltommath",
[AC_MSG_ERROR([Missing system libtommath and --disable-bundled-libtom was specified])] )
AC_CHECK_LIB(tomcrypt, register_cipher, LIBTOM_LIBS="$LIBTOM_LIBS -ltomcrypt",
[AC_MSG_ERROR([Missing system libtomcrypt and --disable-bundled-libtom was specified])] )
fi
],
[
BUNDLED_LIBTOM=0
AC_CHECK_LIB(tommath, mp_exptmod, LIBTOM_LIBS="$LIBTOM_LIBS -ltommath", BUNDLED_LIBTOM=1)
AC_CHECK_LIB(tomcrypt, register_cipher, LIBTOM_LIBS="$LIBTOM_LIBS -ltomcrypt", BUNDLED_LIBTOM=1)
]
)
if test $BUNDLED_LIBTOM = 1 ; then
AC_DEFINE(BUNDLED_LIBTOM,,Use bundled libtom)
fi
AC_SUBST(LIBTOM_LIBS)
AC_SUBST(BUNDLED_LIBTOM)
dnl Added from OpenSSH 3.6.1p2's configure.ac
dnl allow user to disable some login recording features
@@ -422,7 +469,7 @@ dnl lastlog and [uw]tmp are subject to a file search if all else fails
dnl lastlog detection
dnl NOTE: the code itself will detect if lastlog is a directory
AC_MSG_CHECKING([if your system defines LASTLOG_FILE])
AC_TRY_COMPILE([
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <utmp.h>
#ifdef HAVE_LASTLOG_H
@@ -434,13 +481,13 @@ AC_TRY_COMPILE([
#ifdef HAVE_LOGIN_H
# include <login.h>
#endif
],
[ char *lastlog = LASTLOG_FILE; ],
]],
[[ char *lastlog = LASTLOG_FILE; ]])],
[ AC_MSG_RESULT(yes) ],
[
AC_MSG_RESULT(no)
AC_MSG_CHECKING([if your system defines _PATH_LASTLOG])
AC_TRY_COMPILE([
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <utmp.h>
#ifdef HAVE_LASTLOG_H
@@ -449,8 +496,8 @@ AC_TRY_COMPILE([
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
],
[ char *lastlog = _PATH_LASTLOG; ],
]],
[[ char *lastlog = _PATH_LASTLOG; ]])],
[ AC_MSG_RESULT(yes) ],
[
AC_MSG_RESULT(no)
@@ -479,14 +526,14 @@ fi
dnl utmp detection
AC_MSG_CHECKING([if your system defines UTMP_FILE])
AC_TRY_COMPILE([
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <utmp.h>
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
],
[ char *utmp = UTMP_FILE; ],
]],
[[ char *utmp = UTMP_FILE; ]])],
[ AC_MSG_RESULT(yes) ],
[ AC_MSG_RESULT(no)
system_utmp_path=no ]
@@ -509,14 +556,16 @@ fi
dnl wtmp detection
AC_MSG_CHECKING([if your system defines WTMP_FILE])
AC_TRY_COMPILE([
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <utmp.h>
#ifdef HAVE_UTMP_H
# include <utmp.h>
#endif
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
],
[ char *wtmp = WTMP_FILE; ],
]],
[[ char *wtmp = WTMP_FILE; ]])],
[ AC_MSG_RESULT(yes) ],
[ AC_MSG_RESULT(no)
system_wtmp_path=no ]
@@ -542,7 +591,7 @@ dnl utmpx detection - I don't know any system so perverse as to require
dnl utmpx, but not define UTMPX_FILE (ditto wtmpx.) No doubt it's out
dnl there, though.
AC_MSG_CHECKING([if your system defines UTMPX_FILE])
AC_TRY_COMPILE([
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <utmp.h>
#ifdef HAVE_UTMPX_H
@@ -551,8 +600,8 @@ AC_TRY_COMPILE([
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
],
[ char *utmpx = UTMPX_FILE; ],
]],
[[ char *utmpx = UTMPX_FILE; ]])],
[ AC_MSG_RESULT(yes) ],
[ AC_MSG_RESULT(no)
system_utmpx_path=no ]
@@ -567,17 +616,19 @@ fi
dnl wtmpx detection
AC_MSG_CHECKING([if your system defines WTMPX_FILE])
AC_TRY_COMPILE([
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <utmp.h>
#ifdef HAVE_UTMP_H
# include <utmp.h>
#endif
#ifdef HAVE_UTMPX_H
#include <utmpx.h>
# include <utmpx.h>
#endif
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
],
[ char *wtmpx = WTMPX_FILE; ],
]],
[[ char *wtmpx = WTMPX_FILE; ]])],
[ AC_MSG_RESULT(yes) ],
[ AC_MSG_RESULT(no)
system_wtmpx_path=no ]
@@ -594,15 +645,16 @@ fi
AC_PROG_GCC_TRADITIONAL
AC_FUNC_MEMCMP
AC_FUNC_SELECT_ARGTYPES
AC_TYPE_SIGNAL
AC_CHECK_FUNCS([dup2 getspnam getusershell memset putenv select socket strdup clearenv strlcpy strlcat daemon basename _getpty getaddrinfo freeaddrinfo getnameinfo])
AC_CHECK_FUNCS([dup2 getpass getspnam getusershell memset putenv select socket strdup clearenv strlcpy strlcat daemon basename _getpty getaddrinfo freeaddrinfo getnameinfo fork writev])
AC_SEARCH_LIBS(basename, gen, AC_DEFINE(HAVE_BASENAME))
# Solaris needs ptmx
if test -z "$no_ptmx_check" ; then
if test x"$cross_compiling" = x"no" ; then
AC_CHECK_FILE("/dev/ptmx", AC_DEFINE(USE_DEV_PTMX,,Use /dev/ptmx))
if test -e /dev/ptmx ; then
AC_DEFINE(USE_DEV_PTMX,,Use /dev/ptmx)
fi
else
AC_MSG_NOTICE([Not checking for /dev/ptmx, we're cross-compiling])
fi
@@ -610,7 +662,9 @@ fi
if test -z "$no_ptc_check" ; then
if test x"$cross_compiling" = x"no" ; then
AC_CHECK_FILE("/dev/ptc", AC_DEFINE(HAVE_DEV_PTS_AND_PTC,,Use /dev/ptc & /dev/pts))
if test -e /dev/ptc ; then
AC_DEFINE(HAVE_DEV_PTS_AND_PTC,,Use /dev/ptc & /dev/pts)
fi
else
AC_MSG_NOTICE([Not checking for /dev/ptc & /dev/pts since we're cross-compiling])
fi
@@ -619,6 +673,7 @@ fi
AC_EXEEXT
# XXX there must be a nicer way to do this
if test $BUNDLED_LIBTOM = 1 ; then
AS_MKDIR_P(libtomcrypt/src/ciphers/aes)
AS_MKDIR_P(libtomcrypt/src/ciphers/safer)
AS_MKDIR_P(libtomcrypt/src/ciphers/twofish)
@@ -635,6 +690,9 @@ AS_MKDIR_P(libtomcrypt/src/mac/hmac)
AS_MKDIR_P(libtomcrypt/src/mac/omac)
AS_MKDIR_P(libtomcrypt/src/mac/pelican)
AS_MKDIR_P(libtomcrypt/src/mac/pmac)
AS_MKDIR_P(libtomcrypt/src/mac/f9)
AS_MKDIR_P(libtomcrypt/src/mac/xcbc)
AS_MKDIR_P(libtomcrypt/src/math/fp)
AS_MKDIR_P(libtomcrypt/src/misc/base64)
AS_MKDIR_P(libtomcrypt/src/misc/crypt)
AS_MKDIR_P(libtomcrypt/src/misc/mpi)
@@ -644,7 +702,10 @@ AS_MKDIR_P(libtomcrypt/src/modes/cfb)
AS_MKDIR_P(libtomcrypt/src/modes/ctr)
AS_MKDIR_P(libtomcrypt/src/modes/ecb)
AS_MKDIR_P(libtomcrypt/src/modes/ofb)
AS_MKDIR_P(libtomcrypt/src/modes/f8)
AS_MKDIR_P(libtomcrypt/src/modes/lrw)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/bit)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/boolean)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/choice)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/ia5)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/integer)
@@ -652,17 +713,40 @@ AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/object_identifier)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/octet)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/printable_string)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/sequence)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/set)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/short_integer)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/utctime)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/utf8)
AS_MKDIR_P(libtomcrypt/src/pk/dh)
AS_MKDIR_P(libtomcrypt/src/pk/dsa)
AS_MKDIR_P(libtomcrypt/src/pk/ecc)
AS_MKDIR_P(libtomcrypt/src/pk/katja)
AS_MKDIR_P(libtomcrypt/src/pk/pkcs1)
AS_MKDIR_P(libtomcrypt/src/pk/rsa)
AS_MKDIR_P(libtomcrypt/src/prng)
AS_MKDIR_P(libtomcrypt/src/prngs)
LIBTOM_FILES="libtomcrypt/Makefile libtommath/Makefile"
fi
AC_CONFIG_HEADER(config.h)
AC_OUTPUT(Makefile)
AC_OUTPUT(libtomcrypt/Makefile)
AC_OUTPUT(libtommath/Makefile)
AC_CONFIG_FILES(Makefile $LIBTOM_FILES)
AC_OUTPUT
AC_MSG_NOTICE()
AC_MSG_NOTICE(Now edit options.h to choose features.)
if test $BUNDLED_LIBTOM = 1 ; then
AC_MSG_NOTICE([Using bundled libtomcrypt and libtommath])
else
AC_MSG_NOTICE([Using system libtomcrypt and libtommath])
fi
if test "x$ac_cv_func_getpass" != xyes; then
AC_MSG_NOTICE()
AC_MSG_NOTICE([getpass() not available, dbclient will only have public-key authentication])
fi
if test "t$found_crypt_func" != there; then
AC_MSG_NOTICE()
AC_MSG_NOTICE([crypt() not available, dropbear server will not have password authentication])
fi
AC_MSG_NOTICE()
AC_MSG_NOTICE([Now edit options.h to choose features.])

75
crypto_desc.c Normal file
View File

@@ -0,0 +1,75 @@
#include "includes.h"
#include "dbutil.h"
#include "crypto_desc.h"
#include "ltc_prng.h"
#include "ecc.h"
#ifdef DROPBEAR_LTC_PRNG
int dropbear_ltc_prng = -1;
#endif
/* Register the compiled in ciphers.
* This should be run before using any of the ciphers/hashes */
void crypto_init() {
const struct ltc_cipher_descriptor *regciphers[] = {
#ifdef DROPBEAR_AES
&aes_desc,
#endif
#ifdef DROPBEAR_BLOWFISH
&blowfish_desc,
#endif
#ifdef DROPBEAR_TWOFISH
&twofish_desc,
#endif
#ifdef DROPBEAR_3DES
&des3_desc,
#endif
NULL
};
const struct ltc_hash_descriptor *reghashes[] = {
/* we need sha1 for hostkey stuff regardless */
&sha1_desc,
#ifdef DROPBEAR_MD5_HMAC
&md5_desc,
#endif
#ifdef DROPBEAR_SHA256
&sha256_desc,
#endif
#ifdef DROPBEAR_SHA384
&sha384_desc,
#endif
#ifdef DROPBEAR_SHA512
&sha512_desc,
#endif
NULL
};
int i;
for (i = 0; regciphers[i] != NULL; i++) {
if (register_cipher(regciphers[i]) == -1) {
dropbear_exit("Error registering crypto");
}
}
for (i = 0; reghashes[i] != NULL; i++) {
if (register_hash(reghashes[i]) == -1) {
dropbear_exit("Error registering crypto");
}
}
#ifdef DROPBEAR_LTC_PRNG
dropbear_ltc_prng = register_prng(&dropbear_prng_desc);
if (dropbear_ltc_prng == -1) {
dropbear_exit("Error registering crypto");
}
#endif
#ifdef DROPBEAR_ECC
ltc_mp = ltm_desc;
dropbear_ecc_fill_dp();
#endif
}

9
crypto_desc.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef DROPBEAR_CRYPTO_DESC_H
#define DROPBEAR_CRYPTO_DESC_H
void crypto_init(void);
extern int dropbear_ltc_prng;
#endif /* DROPBEAR_CRYPTO_DESC_H */

734
curve25519-donna.c Normal file
View File

@@ -0,0 +1,734 @@
/* Copyright 2008, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT
* OWNER 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.
*
* curve25519-donna: Curve25519 elliptic curve, public key function
*
* http://code.google.com/p/curve25519-donna/
*
* Adam Langley <agl@imperialviolet.org>
*
* Derived from public domain C code by Daniel J. Bernstein <djb@cr.yp.to>
*
* More information about curve25519 can be found here
* http://cr.yp.to/ecdh.html
*
* djb's sample implementation of curve25519 is written in a special assembly
* language called qhasm and uses the floating point registers.
*
* This is, almost, a clean room reimplementation from the curve25519 paper. It
* uses many of the tricks described therein. Only the crecip function is taken
* from the sample implementation.
*/
#include <string.h>
#include <stdint.h>
#ifdef _MSC_VER
#define inline __inline
#endif
typedef uint8_t u8;
typedef int32_t s32;
typedef int64_t limb;
/* Field element representation:
*
* Field elements are written as an array of signed, 64-bit limbs, least
* significant first. The value of the field element is:
* x[0] + 2^26·x[1] + x^51·x[2] + 2^102·x[3] + ...
*
* i.e. the limbs are 26, 25, 26, 25, ... bits wide.
*/
/* Sum two numbers: output += in */
static void fsum(limb *output, const limb *in) {
unsigned i;
for (i = 0; i < 10; i += 2) {
output[0+i] = (output[0+i] + in[0+i]);
output[1+i] = (output[1+i] + in[1+i]);
}
}
/* Find the difference of two numbers: output = in - output
* (note the order of the arguments!)
*/
static void fdifference(limb *output, const limb *in) {
unsigned i;
for (i = 0; i < 10; ++i) {
output[i] = (in[i] - output[i]);
}
}
/* Multiply a number by a scalar: output = in * scalar */
static void fscalar_product(limb *output, const limb *in, const limb scalar) {
unsigned i;
for (i = 0; i < 10; ++i) {
output[i] = in[i] * scalar;
}
}
/* Multiply two numbers: output = in2 * in
*
* output must be distinct to both inputs. The inputs are reduced coefficient
* form, the output is not.
*/
static void fproduct(limb *output, const limb *in2, const limb *in) {
output[0] = ((limb) ((s32) in2[0])) * ((s32) in[0]);
output[1] = ((limb) ((s32) in2[0])) * ((s32) in[1]) +
((limb) ((s32) in2[1])) * ((s32) in[0]);
output[2] = 2 * ((limb) ((s32) in2[1])) * ((s32) in[1]) +
((limb) ((s32) in2[0])) * ((s32) in[2]) +
((limb) ((s32) in2[2])) * ((s32) in[0]);
output[3] = ((limb) ((s32) in2[1])) * ((s32) in[2]) +
((limb) ((s32) in2[2])) * ((s32) in[1]) +
((limb) ((s32) in2[0])) * ((s32) in[3]) +
((limb) ((s32) in2[3])) * ((s32) in[0]);
output[4] = ((limb) ((s32) in2[2])) * ((s32) in[2]) +
2 * (((limb) ((s32) in2[1])) * ((s32) in[3]) +
((limb) ((s32) in2[3])) * ((s32) in[1])) +
((limb) ((s32) in2[0])) * ((s32) in[4]) +
((limb) ((s32) in2[4])) * ((s32) in[0]);
output[5] = ((limb) ((s32) in2[2])) * ((s32) in[3]) +
((limb) ((s32) in2[3])) * ((s32) in[2]) +
((limb) ((s32) in2[1])) * ((s32) in[4]) +
((limb) ((s32) in2[4])) * ((s32) in[1]) +
((limb) ((s32) in2[0])) * ((s32) in[5]) +
((limb) ((s32) in2[5])) * ((s32) in[0]);
output[6] = 2 * (((limb) ((s32) in2[3])) * ((s32) in[3]) +
((limb) ((s32) in2[1])) * ((s32) in[5]) +
((limb) ((s32) in2[5])) * ((s32) in[1])) +
((limb) ((s32) in2[2])) * ((s32) in[4]) +
((limb) ((s32) in2[4])) * ((s32) in[2]) +
((limb) ((s32) in2[0])) * ((s32) in[6]) +
((limb) ((s32) in2[6])) * ((s32) in[0]);
output[7] = ((limb) ((s32) in2[3])) * ((s32) in[4]) +
((limb) ((s32) in2[4])) * ((s32) in[3]) +
((limb) ((s32) in2[2])) * ((s32) in[5]) +
((limb) ((s32) in2[5])) * ((s32) in[2]) +
((limb) ((s32) in2[1])) * ((s32) in[6]) +
((limb) ((s32) in2[6])) * ((s32) in[1]) +
((limb) ((s32) in2[0])) * ((s32) in[7]) +
((limb) ((s32) in2[7])) * ((s32) in[0]);
output[8] = ((limb) ((s32) in2[4])) * ((s32) in[4]) +
2 * (((limb) ((s32) in2[3])) * ((s32) in[5]) +
((limb) ((s32) in2[5])) * ((s32) in[3]) +
((limb) ((s32) in2[1])) * ((s32) in[7]) +
((limb) ((s32) in2[7])) * ((s32) in[1])) +
((limb) ((s32) in2[2])) * ((s32) in[6]) +
((limb) ((s32) in2[6])) * ((s32) in[2]) +
((limb) ((s32) in2[0])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[0]);
output[9] = ((limb) ((s32) in2[4])) * ((s32) in[5]) +
((limb) ((s32) in2[5])) * ((s32) in[4]) +
((limb) ((s32) in2[3])) * ((s32) in[6]) +
((limb) ((s32) in2[6])) * ((s32) in[3]) +
((limb) ((s32) in2[2])) * ((s32) in[7]) +
((limb) ((s32) in2[7])) * ((s32) in[2]) +
((limb) ((s32) in2[1])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[1]) +
((limb) ((s32) in2[0])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[0]);
output[10] = 2 * (((limb) ((s32) in2[5])) * ((s32) in[5]) +
((limb) ((s32) in2[3])) * ((s32) in[7]) +
((limb) ((s32) in2[7])) * ((s32) in[3]) +
((limb) ((s32) in2[1])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[1])) +
((limb) ((s32) in2[4])) * ((s32) in[6]) +
((limb) ((s32) in2[6])) * ((s32) in[4]) +
((limb) ((s32) in2[2])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[2]);
output[11] = ((limb) ((s32) in2[5])) * ((s32) in[6]) +
((limb) ((s32) in2[6])) * ((s32) in[5]) +
((limb) ((s32) in2[4])) * ((s32) in[7]) +
((limb) ((s32) in2[7])) * ((s32) in[4]) +
((limb) ((s32) in2[3])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[3]) +
((limb) ((s32) in2[2])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[2]);
output[12] = ((limb) ((s32) in2[6])) * ((s32) in[6]) +
2 * (((limb) ((s32) in2[5])) * ((s32) in[7]) +
((limb) ((s32) in2[7])) * ((s32) in[5]) +
((limb) ((s32) in2[3])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[3])) +
((limb) ((s32) in2[4])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[4]);
output[13] = ((limb) ((s32) in2[6])) * ((s32) in[7]) +
((limb) ((s32) in2[7])) * ((s32) in[6]) +
((limb) ((s32) in2[5])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[5]) +
((limb) ((s32) in2[4])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[4]);
output[14] = 2 * (((limb) ((s32) in2[7])) * ((s32) in[7]) +
((limb) ((s32) in2[5])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[5])) +
((limb) ((s32) in2[6])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[6]);
output[15] = ((limb) ((s32) in2[7])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[7]) +
((limb) ((s32) in2[6])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[6]);
output[16] = ((limb) ((s32) in2[8])) * ((s32) in[8]) +
2 * (((limb) ((s32) in2[7])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[7]));
output[17] = ((limb) ((s32) in2[8])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[8]);
output[18] = 2 * ((limb) ((s32) in2[9])) * ((s32) in[9]);
}
/* Reduce a long form to a short form by taking the input mod 2^255 - 19. */
static void freduce_degree(limb *output) {
/* Each of these shifts and adds ends up multiplying the value by 19. */
output[8] += output[18] << 4;
output[8] += output[18] << 1;
output[8] += output[18];
output[7] += output[17] << 4;
output[7] += output[17] << 1;
output[7] += output[17];
output[6] += output[16] << 4;
output[6] += output[16] << 1;
output[6] += output[16];
output[5] += output[15] << 4;
output[5] += output[15] << 1;
output[5] += output[15];
output[4] += output[14] << 4;
output[4] += output[14] << 1;
output[4] += output[14];
output[3] += output[13] << 4;
output[3] += output[13] << 1;
output[3] += output[13];
output[2] += output[12] << 4;
output[2] += output[12] << 1;
output[2] += output[12];
output[1] += output[11] << 4;
output[1] += output[11] << 1;
output[1] += output[11];
output[0] += output[10] << 4;
output[0] += output[10] << 1;
output[0] += output[10];
}
#if (-1 & 3) != 3
#error "This code only works on a two's complement system"
#endif
/* return v / 2^26, using only shifts and adds. */
static inline limb
div_by_2_26(const limb v)
{
/* High word of v; no shift needed*/
const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32);
/* Set to all 1s if v was negative; else set to 0s. */
const int32_t sign = ((int32_t) highword) >> 31;
/* Set to 0x3ffffff if v was negative; else set to 0. */
const int32_t roundoff = ((uint32_t) sign) >> 6;
/* Should return v / (1<<26) */
return (v + roundoff) >> 26;
}
/* return v / (2^25), using only shifts and adds. */
static inline limb
div_by_2_25(const limb v)
{
/* High word of v; no shift needed*/
const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32);
/* Set to all 1s if v was negative; else set to 0s. */
const int32_t sign = ((int32_t) highword) >> 31;
/* Set to 0x1ffffff if v was negative; else set to 0. */
const int32_t roundoff = ((uint32_t) sign) >> 7;
/* Should return v / (1<<25) */
return (v + roundoff) >> 25;
}
static inline s32
div_s32_by_2_25(const s32 v)
{
const s32 roundoff = ((uint32_t)(v >> 31)) >> 7;
return (v + roundoff) >> 25;
}
/* Reduce all coefficients of the short form input so that |x| < 2^26.
*
* On entry: |output[i]| < 2^62
*/
static void freduce_coefficients(limb *output) {
unsigned i;
output[10] = 0;
for (i = 0; i < 10; i += 2) {
limb over = div_by_2_26(output[i]);
output[i] -= over << 26;
output[i+1] += over;
over = div_by_2_25(output[i+1]);
output[i+1] -= over << 25;
output[i+2] += over;
}
/* Now |output[10]| < 2 ^ 38 and all other coefficients are reduced. */
output[0] += output[10] << 4;
output[0] += output[10] << 1;
output[0] += output[10];
output[10] = 0;
/* Now output[1..9] are reduced, and |output[0]| < 2^26 + 19 * 2^38
* So |over| will be no more than 77825 */
{
limb over = div_by_2_26(output[0]);
output[0] -= over << 26;
output[1] += over;
}
/* Now output[0,2..9] are reduced, and |output[1]| < 2^25 + 77825
* So |over| will be no more than 1. */
{
/* output[1] fits in 32 bits, so we can use div_s32_by_2_25 here. */
s32 over32 = div_s32_by_2_25((s32) output[1]);
output[1] -= over32 << 25;
output[2] += over32;
}
/* Finally, output[0,1,3..9] are reduced, and output[2] is "nearly reduced":
* we have |output[2]| <= 2^26. This is good enough for all of our math,
* but it will require an extra freduce_coefficients before fcontract. */
}
/* A helpful wrapper around fproduct: output = in * in2.
*
* output must be distinct to both inputs. The output is reduced degree and
* reduced coefficient.
*/
static void
fmul(limb *output, const limb *in, const limb *in2) {
limb t[19];
fproduct(t, in, in2);
freduce_degree(t);
freduce_coefficients(t);
memcpy(output, t, sizeof(limb) * 10);
}
static void fsquare_inner(limb *output, const limb *in) {
output[0] = ((limb) ((s32) in[0])) * ((s32) in[0]);
output[1] = 2 * ((limb) ((s32) in[0])) * ((s32) in[1]);
output[2] = 2 * (((limb) ((s32) in[1])) * ((s32) in[1]) +
((limb) ((s32) in[0])) * ((s32) in[2]));
output[3] = 2 * (((limb) ((s32) in[1])) * ((s32) in[2]) +
((limb) ((s32) in[0])) * ((s32) in[3]));
output[4] = ((limb) ((s32) in[2])) * ((s32) in[2]) +
4 * ((limb) ((s32) in[1])) * ((s32) in[3]) +
2 * ((limb) ((s32) in[0])) * ((s32) in[4]);
output[5] = 2 * (((limb) ((s32) in[2])) * ((s32) in[3]) +
((limb) ((s32) in[1])) * ((s32) in[4]) +
((limb) ((s32) in[0])) * ((s32) in[5]));
output[6] = 2 * (((limb) ((s32) in[3])) * ((s32) in[3]) +
((limb) ((s32) in[2])) * ((s32) in[4]) +
((limb) ((s32) in[0])) * ((s32) in[6]) +
2 * ((limb) ((s32) in[1])) * ((s32) in[5]));
output[7] = 2 * (((limb) ((s32) in[3])) * ((s32) in[4]) +
((limb) ((s32) in[2])) * ((s32) in[5]) +
((limb) ((s32) in[1])) * ((s32) in[6]) +
((limb) ((s32) in[0])) * ((s32) in[7]));
output[8] = ((limb) ((s32) in[4])) * ((s32) in[4]) +
2 * (((limb) ((s32) in[2])) * ((s32) in[6]) +
((limb) ((s32) in[0])) * ((s32) in[8]) +
2 * (((limb) ((s32) in[1])) * ((s32) in[7]) +
((limb) ((s32) in[3])) * ((s32) in[5])));
output[9] = 2 * (((limb) ((s32) in[4])) * ((s32) in[5]) +
((limb) ((s32) in[3])) * ((s32) in[6]) +
((limb) ((s32) in[2])) * ((s32) in[7]) +
((limb) ((s32) in[1])) * ((s32) in[8]) +
((limb) ((s32) in[0])) * ((s32) in[9]));
output[10] = 2 * (((limb) ((s32) in[5])) * ((s32) in[5]) +
((limb) ((s32) in[4])) * ((s32) in[6]) +
((limb) ((s32) in[2])) * ((s32) in[8]) +
2 * (((limb) ((s32) in[3])) * ((s32) in[7]) +
((limb) ((s32) in[1])) * ((s32) in[9])));
output[11] = 2 * (((limb) ((s32) in[5])) * ((s32) in[6]) +
((limb) ((s32) in[4])) * ((s32) in[7]) +
((limb) ((s32) in[3])) * ((s32) in[8]) +
((limb) ((s32) in[2])) * ((s32) in[9]));
output[12] = ((limb) ((s32) in[6])) * ((s32) in[6]) +
2 * (((limb) ((s32) in[4])) * ((s32) in[8]) +
2 * (((limb) ((s32) in[5])) * ((s32) in[7]) +
((limb) ((s32) in[3])) * ((s32) in[9])));
output[13] = 2 * (((limb) ((s32) in[6])) * ((s32) in[7]) +
((limb) ((s32) in[5])) * ((s32) in[8]) +
((limb) ((s32) in[4])) * ((s32) in[9]));
output[14] = 2 * (((limb) ((s32) in[7])) * ((s32) in[7]) +
((limb) ((s32) in[6])) * ((s32) in[8]) +
2 * ((limb) ((s32) in[5])) * ((s32) in[9]));
output[15] = 2 * (((limb) ((s32) in[7])) * ((s32) in[8]) +
((limb) ((s32) in[6])) * ((s32) in[9]));
output[16] = ((limb) ((s32) in[8])) * ((s32) in[8]) +
4 * ((limb) ((s32) in[7])) * ((s32) in[9]);
output[17] = 2 * ((limb) ((s32) in[8])) * ((s32) in[9]);
output[18] = 2 * ((limb) ((s32) in[9])) * ((s32) in[9]);
}
static void
fsquare(limb *output, const limb *in) {
limb t[19];
fsquare_inner(t, in);
freduce_degree(t);
freduce_coefficients(t);
memcpy(output, t, sizeof(limb) * 10);
}
/* Take a little-endian, 32-byte number and expand it into polynomial form */
static void
fexpand(limb *output, const u8 *input) {
#define F(n,start,shift,mask) \
output[n] = ((((limb) input[start + 0]) | \
((limb) input[start + 1]) << 8 | \
((limb) input[start + 2]) << 16 | \
((limb) input[start + 3]) << 24) >> shift) & mask;
F(0, 0, 0, 0x3ffffff);
F(1, 3, 2, 0x1ffffff);
F(2, 6, 3, 0x3ffffff);
F(3, 9, 5, 0x1ffffff);
F(4, 12, 6, 0x3ffffff);
F(5, 16, 0, 0x1ffffff);
F(6, 19, 1, 0x3ffffff);
F(7, 22, 3, 0x1ffffff);
F(8, 25, 4, 0x3ffffff);
F(9, 28, 6, 0x3ffffff);
#undef F
}
#if (-32 >> 1) != -16
#error "This code only works when >> does sign-extension on negative numbers"
#endif
/* Take a fully reduced polynomial form number and contract it into a
* little-endian, 32-byte array
*/
static void
fcontract(u8 *output, limb *input) {
int i;
int j;
for (j = 0; j < 2; ++j) {
for (i = 0; i < 9; ++i) {
if ((i & 1) == 1) {
/* This calculation is a time-invariant way to make input[i] positive
by borrowing from the next-larger limb.
*/
const s32 mask = (s32)(input[i]) >> 31;
const s32 carry = -(((s32)(input[i]) & mask) >> 25);
input[i] = (s32)(input[i]) + (carry << 25);
input[i+1] = (s32)(input[i+1]) - carry;
} else {
const s32 mask = (s32)(input[i]) >> 31;
const s32 carry = -(((s32)(input[i]) & mask) >> 26);
input[i] = (s32)(input[i]) + (carry << 26);
input[i+1] = (s32)(input[i+1]) - carry;
}
}
{
const s32 mask = (s32)(input[9]) >> 31;
const s32 carry = -(((s32)(input[9]) & mask) >> 25);
input[9] = (s32)(input[9]) + (carry << 25);
input[0] = (s32)(input[0]) - (carry * 19);
}
}
/* The first borrow-propagation pass above ended with every limb
except (possibly) input[0] non-negative.
Since each input limb except input[0] is decreased by at most 1
by a borrow-propagation pass, the second borrow-propagation pass
could only have wrapped around to decrease input[0] again if the
first pass left input[0] negative *and* input[1] through input[9]
were all zero. In that case, input[1] is now 2^25 - 1, and this
last borrow-propagation step will leave input[1] non-negative.
*/
{
const s32 mask = (s32)(input[0]) >> 31;
const s32 carry = -(((s32)(input[0]) & mask) >> 26);
input[0] = (s32)(input[0]) + (carry << 26);
input[1] = (s32)(input[1]) - carry;
}
/* Both passes through the above loop, plus the last 0-to-1 step, are
necessary: if input[9] is -1 and input[0] through input[8] are 0,
negative values will remain in the array until the end.
*/
input[1] <<= 2;
input[2] <<= 3;
input[3] <<= 5;
input[4] <<= 6;
input[6] <<= 1;
input[7] <<= 3;
input[8] <<= 4;
input[9] <<= 6;
#define F(i, s) \
output[s+0] |= input[i] & 0xff; \
output[s+1] = (input[i] >> 8) & 0xff; \
output[s+2] = (input[i] >> 16) & 0xff; \
output[s+3] = (input[i] >> 24) & 0xff;
output[0] = 0;
output[16] = 0;
F(0,0);
F(1,3);
F(2,6);
F(3,9);
F(4,12);
F(5,16);
F(6,19);
F(7,22);
F(8,25);
F(9,28);
#undef F
}
/* Input: Q, Q', Q-Q'
* Output: 2Q, Q+Q'
*
* x2 z3: long form
* x3 z3: long form
* x z: short form, destroyed
* xprime zprime: short form, destroyed
* qmqp: short form, preserved
*/
static void fmonty(limb *x2, limb *z2, /* output 2Q */
limb *x3, limb *z3, /* output Q + Q' */
limb *x, limb *z, /* input Q */
limb *xprime, limb *zprime, /* input Q' */
const limb *qmqp /* input Q - Q' */) {
limb origx[10], origxprime[10], zzz[19], xx[19], zz[19], xxprime[19],
zzprime[19], zzzprime[19], xxxprime[19];
memcpy(origx, x, 10 * sizeof(limb));
fsum(x, z);
fdifference(z, origx); /* does x - z */
memcpy(origxprime, xprime, sizeof(limb) * 10);
fsum(xprime, zprime);
fdifference(zprime, origxprime);
fproduct(xxprime, xprime, z);
fproduct(zzprime, x, zprime);
freduce_degree(xxprime);
freduce_coefficients(xxprime);
freduce_degree(zzprime);
freduce_coefficients(zzprime);
memcpy(origxprime, xxprime, sizeof(limb) * 10);
fsum(xxprime, zzprime);
fdifference(zzprime, origxprime);
fsquare(xxxprime, xxprime);
fsquare(zzzprime, zzprime);
fproduct(zzprime, zzzprime, qmqp);
freduce_degree(zzprime);
freduce_coefficients(zzprime);
memcpy(x3, xxxprime, sizeof(limb) * 10);
memcpy(z3, zzprime, sizeof(limb) * 10);
fsquare(xx, x);
fsquare(zz, z);
fproduct(x2, xx, zz);
freduce_degree(x2);
freduce_coefficients(x2);
fdifference(zz, xx); /* does zz = xx - zz */
memset(zzz + 10, 0, sizeof(limb) * 9);
fscalar_product(zzz, zz, 121665);
/* No need to call freduce_degree here:
fscalar_product doesn't increase the degree of its input. */
freduce_coefficients(zzz);
fsum(zzz, xx);
fproduct(z2, zz, zzz);
freduce_degree(z2);
freduce_coefficients(z2);
}
/* Conditionally swap two reduced-form limb arrays if 'iswap' is 1, but leave
* them unchanged if 'iswap' is 0. Runs in data-invariant time to avoid
* side-channel attacks.
*
* NOTE that this function requires that 'iswap' be 1 or 0; other values give
* wrong results. Also, the two limb arrays must be in reduced-coefficient,
* reduced-degree form: the values in a[10..19] or b[10..19] aren't swapped,
* and all all values in a[0..9],b[0..9] must have magnitude less than
* INT32_MAX.
*/
static void
swap_conditional(limb a[19], limb b[19], limb iswap) {
unsigned i;
const s32 swap = (s32) -iswap;
for (i = 0; i < 10; ++i) {
const s32 x = swap & ( ((s32)a[i]) ^ ((s32)b[i]) );
a[i] = ((s32)a[i]) ^ x;
b[i] = ((s32)b[i]) ^ x;
}
}
/* Calculates nQ where Q is the x-coordinate of a point on the curve
*
* resultx/resultz: the x coordinate of the resulting curve point (short form)
* n: a little endian, 32-byte number
* q: a point of the curve (short form)
*/
static void
cmult(limb *resultx, limb *resultz, const u8 *n, const limb *q) {
limb a[19] = {0}, b[19] = {1}, c[19] = {1}, d[19] = {0};
limb *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t;
limb e[19] = {0}, f[19] = {1}, g[19] = {0}, h[19] = {1};
limb *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h;
unsigned i, j;
memcpy(nqpqx, q, sizeof(limb) * 10);
for (i = 0; i < 32; ++i) {
u8 byte = n[31 - i];
for (j = 0; j < 8; ++j) {
const limb bit = byte >> 7;
swap_conditional(nqx, nqpqx, bit);
swap_conditional(nqz, nqpqz, bit);
fmonty(nqx2, nqz2,
nqpqx2, nqpqz2,
nqx, nqz,
nqpqx, nqpqz,
q);
swap_conditional(nqx2, nqpqx2, bit);
swap_conditional(nqz2, nqpqz2, bit);
t = nqx;
nqx = nqx2;
nqx2 = t;
t = nqz;
nqz = nqz2;
nqz2 = t;
t = nqpqx;
nqpqx = nqpqx2;
nqpqx2 = t;
t = nqpqz;
nqpqz = nqpqz2;
nqpqz2 = t;
byte <<= 1;
}
}
memcpy(resultx, nqx, sizeof(limb) * 10);
memcpy(resultz, nqz, sizeof(limb) * 10);
}
/* -----------------------------------------------------------------------------
* Shamelessly copied from djb's code
* ----------------------------------------------------------------------------- */
static void
crecip(limb *out, const limb *z) {
limb z2[10];
limb z9[10];
limb z11[10];
limb z2_5_0[10];
limb z2_10_0[10];
limb z2_20_0[10];
limb z2_50_0[10];
limb z2_100_0[10];
limb t0[10];
limb t1[10];
int i;
/* 2 */ fsquare(z2,z);
/* 4 */ fsquare(t1,z2);
/* 8 */ fsquare(t0,t1);
/* 9 */ fmul(z9,t0,z);
/* 11 */ fmul(z11,z9,z2);
/* 22 */ fsquare(t0,z11);
/* 2^5 - 2^0 = 31 */ fmul(z2_5_0,t0,z9);
/* 2^6 - 2^1 */ fsquare(t0,z2_5_0);
/* 2^7 - 2^2 */ fsquare(t1,t0);
/* 2^8 - 2^3 */ fsquare(t0,t1);
/* 2^9 - 2^4 */ fsquare(t1,t0);
/* 2^10 - 2^5 */ fsquare(t0,t1);
/* 2^10 - 2^0 */ fmul(z2_10_0,t0,z2_5_0);
/* 2^11 - 2^1 */ fsquare(t0,z2_10_0);
/* 2^12 - 2^2 */ fsquare(t1,t0);
/* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
/* 2^20 - 2^0 */ fmul(z2_20_0,t1,z2_10_0);
/* 2^21 - 2^1 */ fsquare(t0,z2_20_0);
/* 2^22 - 2^2 */ fsquare(t1,t0);
/* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
/* 2^40 - 2^0 */ fmul(t0,t1,z2_20_0);
/* 2^41 - 2^1 */ fsquare(t1,t0);
/* 2^42 - 2^2 */ fsquare(t0,t1);
/* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t1,t0); fsquare(t0,t1); }
/* 2^50 - 2^0 */ fmul(z2_50_0,t0,z2_10_0);
/* 2^51 - 2^1 */ fsquare(t0,z2_50_0);
/* 2^52 - 2^2 */ fsquare(t1,t0);
/* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
/* 2^100 - 2^0 */ fmul(z2_100_0,t1,z2_50_0);
/* 2^101 - 2^1 */ fsquare(t1,z2_100_0);
/* 2^102 - 2^2 */ fsquare(t0,t1);
/* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fsquare(t1,t0); fsquare(t0,t1); }
/* 2^200 - 2^0 */ fmul(t1,t0,z2_100_0);
/* 2^201 - 2^1 */ fsquare(t0,t1);
/* 2^202 - 2^2 */ fsquare(t1,t0);
/* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
/* 2^250 - 2^0 */ fmul(t0,t1,z2_50_0);
/* 2^251 - 2^1 */ fsquare(t1,t0);
/* 2^252 - 2^2 */ fsquare(t0,t1);
/* 2^253 - 2^3 */ fsquare(t1,t0);
/* 2^254 - 2^4 */ fsquare(t0,t1);
/* 2^255 - 2^5 */ fsquare(t1,t0);
/* 2^255 - 21 */ fmul(out,t1,z11);
}
int curve25519_donna(u8 *, const u8 *, const u8 *);
int
curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint) {
limb bp[10], x[10], z[11], zmone[10];
uint8_t e[32];
int i;
for (i = 0; i < 32; ++i) e[i] = secret[i];
e[0] &= 248;
e[31] &= 127;
e[31] |= 64;
fexpand(bp, basepoint);
cmult(x, z, e, bp);
crecip(zmone, z);
fmul(z, x, zmone);
freduce_coefficients(z);
fcontract(mypublic, z);
return 0;
}

View File

@@ -1,35 +1,48 @@
.TH dbclient 1
.SH NAME
dbclient \- lightweight SSH2 client
dbclient \- lightweight SSH client
.SH SYNOPSIS
.B dbclient
[\-Tt] [\-p
[\fIflag arguments\fR] [\-p
.I port\fR] [\-i
.I id\fR] [\-L
.I l\fR:\fIh\fR:\fIr\fR] [\-R
.I l\fR:\fIh\fR:\fIr\fR] [\-l
.I l\fR:\fIh\fR:\fIp\fR] [\-R
.I l\fR:\fIh\fR:\fIp\fR] [\-l
.IR user ]
.I host
.RI [ \fImore\ flags\fR ]
.RI [ command ]
.B dbclient
[\fIargs\fR]
[\fIuser1\fR]@\fIhost1\fR[^\fIport1\fR],[\fIuser2\fR]@\fIhost2\fR[^\fIport2\fR],...
.SH DESCRIPTION
.B dbclient
is a SSH 2 client designed to be small enough to be used in small memory
environments, while still being functional and secure enough for general use.
is a small SSH client
.SH OPTIONS
.TP
.TP
.B command
A command to run on the remote host. This will normally be run by the remote host
using the user's shell. The command begins at the first hyphen argument after the
host argument. If no command is specified an interactive terminal will be opened
(see -t and -T).
.TP
.B \-p \fIport
Remote port.
Connect to port
Connect to
.I port
on the remote host.
on the remote host. Alternatively a port can be specified as hostname^port.
Default is 22.
.TP
.B \-i \fIidfile
Identity file.
Read the identity from file
Read the identity key from file
.I idfile
(multiple allowed).
(multiple allowed). This file is created with dropbearkey(1) or converted
from OpenSSH with dropbearconvert(1). The default path ~/.ssh/id_dropbear is used
.TP
.B \-L \fIlistenport\fR:\fIhost\fR:\fIport\fR
.B \-L\fR [\fIlistenaddress\fR]:\fIlistenport\fR:\fIhost\fR:\fIport\fR
Local port forwarding.
Forward the port
.I listenport
@@ -38,7 +51,7 @@ on the local host through the SSH connection to port
on the host
.IR host .
.TP
.B \-R \fIlistenport\fR:\fIhost\fR:\fIport\fR
.B \-R\fR [\fIlistenaddress\fR]:\fIlistenport\fR:\fIhost\fR:\fIport\fR
Remote port forwarding.
Forward the port
.I listenport
@@ -54,10 +67,12 @@ Login as
on the remote host.
.TP
.B \-t
Allocate a pty.
Allocate a PTY. This is the default when no command is given, it gives a full
interactive remote session. The main effect is that keystrokes are sent remotely
immediately as opposed to local line-based editing.
.TP
.B \-T
Don't allocate a pty.
Don't allocate a PTY. This is the default a command is given. See -t.
.TP
.B \-N
Don't request a remote shell or run any commands. Any command arguments are ignored.
@@ -73,12 +88,112 @@ by the ssh server.
.TP
.B \-y
Always accept hostkeys if they are unknown. If a hostkey mismatch occurs the
connection will abort as normal.
connection will abort as normal. If specified a second time no host key checking
is performed at all, this is usually undesirable.
.TP
.B \-A
Forward agent connections to the remote host. dbclient will use any
OpenSSH-style agent program if available ($SSH_AUTH_SOCK will be set) for
public key authentication. Forwarding is only enabled if -A is specified.
.TP
.B \-W \fIwindowsize
Specify the per-channel receive window buffer size. Increasing this
may improve network performance at the expense of memory use. Use -h to see the
default buffer size.
.TP
.B \-K \fItimeout_seconds
Ensure that traffic is transmitted at a certain interval in seconds. This is
useful for working around firewalls or routers that drop connections after
a certain period of inactivity. The trade-off is that a session may be
closed if there is a temporary lapse of network connectivity. A setting
if 0 disables keepalives. If no response is received for 3 consecutive keepalives the connection will be closed.
.TP
.B \-I \fIidle_timeout
Disconnect the session if no traffic is transmitted or received for \fIidle_timeout\fR seconds.
.TP
.B \-J \fIproxy_command
Use the standard input/output of the program \fIproxy_command\fR rather than using
a normal TCP connection. A hostname should be still be provided, as this is used for
comparing saved hostkeys. This command will be executed as "exec proxy_command ..." with the
default shell.
.TP
.B \-B \fIendhost:endport
"Netcat-alike" mode, where Dropbear will connect to the given host, then create a
forwarded connection to \fIendhost\fR. This will then be presented as dbclient's
standard input/output.
.TP
.B \-c \fIcipherlist
Specify a comma separated list of ciphers to enable. Use \fI-c help\fR to list possibilities.
.TP
.B \-m \fIMAClist
Specify a comma separated list of authentication MACs to enable. Use \fI-m help\fR to list possibilities.
.TP
.B \-o \fIoption
Can be used to give options in the format used by OpenSSH config file. This is
useful for specifying options for which there is no separate command-line flag.
For full details of the options listed below, and their possible values, see
ssh_config(5).
For now following options have been implemented:
.RS
.TP
.B ExitOnForwardFailure
Specifies whether dbclient should terminate the connection if it cannot set up all requested local and remote port forwardings. The argument must be “yes” or “no”. The default is “no”.
.TP
.B UseSyslog
Send dbclient log messages to syslog in addition to stderr.
.RE
.TP
.B \-s
The specified command will be requested as a subsystem, used for sftp. Dropbear doesn't implement sftp itself but the OpenSSH sftp client can be used eg \fIsftp -S dbclient user@host\fR
.TP
.B \-V
Print the version
.SH MULTI-HOP
Dropbear will also allow multiple "hops" to be specified, separated by commas. In
this case a connection will be made to the first host, then a TCP forwarded
connection will be made through that to the second host, and so on. Hosts other than
the final destination will not see anything other than the encrypted SSH stream.
A port for a host can be specified with a caret (eg matt@martello^44 ).
This syntax can also be used with scp or rsync (specifying dbclient as the
ssh/rsh command). A file can be "bounced" through multiple SSH hops, eg
scp -S dbclient matt@martello,root@wrt,canyons:/tmp/dump .
Note that hostnames are resolved by the prior hop (so "canyons" would be resolved by the host "wrt")
in the example above, the same way as other -L TCP forwarded hosts are. Host keys are
checked locally based on the given hostname.
.SH ESCAPE CHARACTERS
Typing a newline followed by the key sequence \fI~.\fR (tilde, dot) will terminate a connection.
The sequence \fI~^Z\fR (tilde, ctrl-z) will background the connection. This behaviour only
applies when a PTY is used.
.SH ENVIRONMENT
.TP
.B DROPBEAR_PASSWORD
A password to use for remote authentication can be specified in the environment
variable DROPBEAR_PASSWORD. Care should be taken that the password is not
exposed to other users on a multi-user system, or stored in accessible files.
.TP
.B SSH_ASKPASS
dbclient can use an external program to request a password from a user.
SSH_ASKPASS should be set to the path of a program that will return a password
on standard output. This program will only be used if either DISPLAY is set and
standard input is not a TTY, or the environment variable SSH_ASKPASS_ALWAYS is
set.
.SH NOTES
If compiled with zlib support and if the server supports it, dbclient will
always use compression.
.SH AUTHOR
Matt Johnston (matt@ucc.asn.au).
.br
Mihnea Stoenescu wrote initial Dropbear client support
.br
Gerrit Pape (pape@smarden.org) wrote this manual page.
.SH SEE ALSO
dropbear(8), dropbearkey(8)
dropbear(8), dropbearkey(1)
.P
http://matt.ucc.asn.au/dropbear/dropbear.html
https://matt.ucc.asn.au/dropbear/dropbear.html

25
dbhelpers.c Normal file
View File

@@ -0,0 +1,25 @@
#include "dbhelpers.h"
#include "includes.h"
/* Erase data */
void m_burn(void *data, unsigned int len) {
#if defined(HAVE_MEMSET_S)
memset_s(data, len, 0x0, len);
#elif defined(HAVE_EXPLICIT_BZERO)
explicit_bzero(data, len);
#else
/* Based on the method in David Wheeler's
* "Secure Programming for Linux and Unix HOWTO". May not be safe
* against link-time optimisation. */
volatile char *p = data;
if (data == NULL)
return;
while (len--) {
*p++ = 0x0;
}
#endif
}

21
dbhelpers.h Normal file
View File

@@ -0,0 +1,21 @@
#ifndef DROPBEAR_DBHELPERS_H_
#define DROPBEAR_DBHELPERS_H_
/* This header defines some things that are also used by libtomcrypt/math.
We avoid including normal include.h since that can result in conflicting
definitinos - only include config.h */
#include "config.h"
#ifdef __GNUC__
#define ATTRIB_PRINTF(fmt,args) __attribute__((format(printf, fmt, args)))
#define ATTRIB_NORETURN __attribute__((noreturn))
#define ATTRIB_SENTINEL __attribute__((sentinel))
#else
#define ATTRIB_PRINTF(fmt,args)
#define ATTRIB_NORETURN
#define ATTRIB_SENTINEL
#endif
void m_burn(void* data, unsigned int len);
#endif /* DROPBEAR_DBHELPERS_H_ */

View File

@@ -26,17 +26,13 @@
/* definitions are cleanest if we just put them here */
int dropbear_main(int argc, char ** argv);
int cli_main(int argc, char ** argv);
int dropbearkey_main(int argc, char ** argv);
int dropbearconvert_main(int argc, char ** argv);
int scp_main(int argc, char ** argv);
int main(int argc, char ** argv) {
char * progname;
if (argc > 0) {
/* figure which form we're being called as */
progname = basename(argv[0]);
static int runprog(const char *progname, int argc, char ** argv, int *match) {
*match = DROPBEAR_SUCCESS;
#ifdef DBMULTI_dropbear
if (strcmp(progname, "dropbear") == 0) {
@@ -64,10 +60,28 @@ int main(int argc, char ** argv) {
return scp_main(argc, argv);
}
#endif
*match = DROPBEAR_FAILURE;
return 1;
}
int main(int argc, char ** argv) {
int i;
for (i = 0; i < 2; i++) {
/* Try symlink first, then try as an argument eg "dropbearmulti dbclient host ..." */
if (argc > i) {
int match, res;
/* figure which form we're being called as */
const char* progname = basename(argv[i]);
res = runprog(progname, argc-i, &argv[i], &match);
if (match == DROPBEAR_SUCCESS) {
return res;
}
}
}
fprintf(stderr, "Dropbear multi-purpose version %s\n"
"Make a symlink pointing at this binary with one of the following names:\n"
fprintf(stderr, "Dropbear SSH multi-purpose v%s\n"
"Make a symlink pointing at this binary with one of the\n"
"following names or run 'dropbearmulti <command>'.\n"
#ifdef DBMULTI_dropbear
"'dropbear' - the Dropbear server\n"
#endif

View File

@@ -26,20 +26,19 @@
#include "buffer.h"
#include "dbutil.h"
#include "bignum.h"
#include "dbrandom.h"
static int donerandinit = 0;
/* this is used to generate unique output from the same hashpool */
static uint32_t counter = 0;
/* the max value for the counter, so it won't integer overflow */
#define MAX_COUNTER 1<<30
#define MAX_COUNTER (1<<30)
static unsigned char hashpool[SHA1_HASH_SIZE];
static unsigned char hashpool[SHA1_HASH_SIZE] = {0};
static int donerandinit = 0;
#define INIT_SEED_SIZE 32 /* 256 bits */
static void readrand(unsigned char* buf, unsigned int buflen);
/* The basic setup is we read some data from /dev/(u)random or prngd and hash it
* into hashpool. To read data, we hash together current hashpool contents,
* and a counter. We feed more data in by hashing the current pool and new
@@ -50,129 +49,202 @@ static void readrand(unsigned char* buf, unsigned int buflen);
*
*/
static void readrand(unsigned char* buf, unsigned int buflen) {
/* Pass len=0 to hash an entire file */
static int
process_file(hash_state *hs, const char *filename,
unsigned int len, int prngd)
{
static int already_blocked = 0;
int readfd;
unsigned int readpos;
int readlen;
#ifdef DROPBEAR_PRNGD_SOCKET
struct sockaddr_un egdsock;
char egdcmd[2];
#endif
#ifdef DROPBEAR_RANDOM_DEV
readfd = open(DROPBEAR_RANDOM_DEV, O_RDONLY);
if (readfd < 0) {
dropbear_exit("couldn't open random device");
}
#endif
unsigned int readcount;
int ret = DROPBEAR_FAILURE;
#ifdef DROPBEAR_PRNGD_SOCKET
memset((void*)&egdsock, 0x0, sizeof(egdsock));
egdsock.sun_family = AF_UNIX;
strlcpy(egdsock.sun_path, DROPBEAR_PRNGD_SOCKET,
sizeof(egdsock.sun_path));
readfd = socket(PF_UNIX, SOCK_STREAM, 0);
if (readfd < 0) {
dropbear_exit("couldn't open random device");
if (prngd)
{
readfd = connect_unix(filename);
}
/* todo - try various common locations */
if (connect(readfd, (struct sockaddr*)&egdsock,
sizeof(struct sockaddr_un)) < 0) {
dropbear_exit("couldn't open random device");
}
if (buflen > 255)
dropbear_exit("can't request more than 255 bytes from egd");
egdcmd[0] = 0x02; /* blocking read */
egdcmd[1] = (unsigned char)buflen;
if (write(readfd, egdcmd, 2) < 0)
dropbear_exit("can't send command to egd");
else
#endif
{
readfd = open(filename, O_RDONLY);
}
/* read the actual random data */
readpos = 0;
do {
if (!already_blocked)
if (readfd < 0) {
goto out;
}
readcount = 0;
while (len == 0 || readcount < len)
{
int readlen, wantread;
unsigned char readbuf[4096];
if (!already_blocked && !prngd)
{
int ret;
int res;
struct timeval timeout;
fd_set read_fds;
timeout.tv_sec = 2; /* two seconds should be enough */
timeout.tv_usec = 0;
timeout.tv_sec = 2;
timeout.tv_usec = 0;
FD_ZERO(&read_fds);
FD_SET(readfd, &read_fds);
ret = select(readfd + 1, &read_fds, NULL, NULL, &timeout);
if (ret == 0)
res = select(readfd + 1, &read_fds, NULL, NULL, &timeout);
if (res == 0)
{
dropbear_log(LOG_INFO, "Warning: Reading the random source seems to have blocked.\nIf you experience problems, you probably need to find a better entropy source.");
dropbear_log(LOG_WARNING, "Warning: Reading the randomness source '%s' seems to have blocked.\nYou may need to find a better entropy source.", filename);
already_blocked = 1;
}
}
readlen = read(readfd, &buf[readpos], buflen - readpos);
if (len == 0)
{
wantread = sizeof(readbuf);
}
else
{
wantread = MIN(sizeof(readbuf), len-readcount);
}
#ifdef DROPBEAR_PRNGD_SOCKET
if (prngd)
{
char egdcmd[2];
egdcmd[0] = 0x02; /* blocking read */
egdcmd[1] = (unsigned char)wantread;
if (write(readfd, egdcmd, 2) < 0)
{
dropbear_exit("Can't send command to egd");
}
}
#endif
readlen = read(readfd, readbuf, wantread);
if (readlen <= 0) {
if (readlen < 0 && errno == EINTR) {
continue;
}
dropbear_exit("error reading random source");
if (readlen == 0 && len == 0)
{
/* whole file was read as requested */
break;
}
goto out;
}
readpos += readlen;
} while (readpos < buflen);
close (readfd);
sha1_process(hs, readbuf, readlen);
readcount += readlen;
}
ret = DROPBEAR_SUCCESS;
out:
close(readfd);
return ret;
}
/* initialise the prng from /dev/(u)random or prngd */
void seedrandom() {
unsigned char readbuf[INIT_SEED_SIZE];
void addrandom(unsigned char * buf, unsigned int len)
{
hash_state hs;
/* initialise so that things won't warn about
* hashing an undefined buffer */
if (!donerandinit) {
m_burn(hashpool, sizeof(hashpool));
}
/* get the seed data */
readrand(readbuf, sizeof(readbuf));
/* hash in the new seed data */
sha1_init(&hs);
/* existing state (zeroes on startup) */
sha1_process(&hs, (void*)hashpool, sizeof(hashpool));
sha1_process(&hs, (void*)readbuf, sizeof(readbuf));
/* new */
sha1_process(&hs, buf, len);
sha1_done(&hs, hashpool);
}
static void write_urandom()
{
#ifndef DROPBEAR_PRNGD_SOCKET
/* This is opportunistic, don't worry about failure */
unsigned char buf[INIT_SEED_SIZE];
FILE *f = fopen(DROPBEAR_URANDOM_DEV, "w");
if (!f) {
return;
}
genrandom(buf, sizeof(buf));
fwrite(buf, sizeof(buf), 1, f);
fclose(f);
#endif
}
/* Initialise the prng from /dev/urandom or prngd. This function can
* be called multiple times */
void seedrandom() {
hash_state hs;
pid_t pid;
struct timeval tv;
clock_t clockval;
/* hash in the new seed data */
sha1_init(&hs);
/* existing state */
sha1_process(&hs, (void*)hashpool, sizeof(hashpool));
#ifdef DROPBEAR_PRNGD_SOCKET
if (process_file(&hs, DROPBEAR_PRNGD_SOCKET, INIT_SEED_SIZE, 1)
!= DROPBEAR_SUCCESS) {
dropbear_exit("Failure reading random device %s",
DROPBEAR_PRNGD_SOCKET);
}
#else
/* non-blocking random source (probably /dev/urandom) */
if (process_file(&hs, DROPBEAR_URANDOM_DEV, INIT_SEED_SIZE, 0)
!= DROPBEAR_SUCCESS) {
dropbear_exit("Failure reading random device %s",
DROPBEAR_URANDOM_DEV);
}
#endif
/* A few other sources to fall back on.
* Add more here for other platforms */
#ifdef __linux__
/* Seems to be a reasonable source of entropy from timers. Possibly hard
* for even local attackers to reproduce */
process_file(&hs, "/proc/timer_list", 0, 0);
/* Might help on systems with wireless */
process_file(&hs, "/proc/interrupts", 0, 0);
process_file(&hs, "/proc/loadavg", 0, 0);
process_file(&hs, "/proc/sys/kernel/random/entropy_avail", 0, 0);
/* Mostly network visible but useful in some situations.
* Limit size to avoid slowdowns on systems with lots of routes */
process_file(&hs, "/proc/net/netstat", 4096, 0);
process_file(&hs, "/proc/net/dev", 4096, 0);
process_file(&hs, "/proc/net/tcp", 4096, 0);
/* Also includes interface lo */
process_file(&hs, "/proc/net/rt_cache", 4096, 0);
process_file(&hs, "/proc/vmstat", 0, 0);
#endif
pid = getpid();
sha1_process(&hs, (void*)&pid, sizeof(pid));
/* gettimeofday() doesn't completely fill out struct timeval on
OS X (10.8.3), avoid valgrind warnings by clearing it first */
memset(&tv, 0x0, sizeof(tv));
gettimeofday(&tv, NULL);
sha1_process(&hs, (void*)&tv, sizeof(tv));
clockval = clock();
sha1_process(&hs, (void*)&clockval, sizeof(clockval));
/* When a private key is read by the client or server it will
* be added to the hashpool - see runopts.c */
sha1_done(&hs, hashpool);
counter = 0;
donerandinit = 1;
}
/* hash the current random pool with some unique identifiers
* for this process and point-in-time. this is used to separate
* the random pools for fork()ed processes. */
void reseedrandom() {
pid_t pid;
hash_state hs;
struct timeval tv;
if (!donerandinit) {
dropbear_exit("seedrandom not done");
}
pid = getpid();
gettimeofday(&tv, NULL);
sha1_init(&hs);
sha1_process(&hs, (void*)hashpool, sizeof(hashpool));
sha1_process(&hs, (void*)&pid, sizeof(pid));
sha1_process(&hs, (void*)&tv, sizeof(tv));
sha1_done(&hs, hashpool);
/* Feed it all back into /dev/urandom - this might help if Dropbear
* is running from inetd and gets new state each time */
write_urandom();
}
/* return len bytes of pseudo-random data */
@@ -234,7 +306,7 @@ void gen_random_mpint(mp_int *max, mp_int *rand) {
/* keep regenerating until we get one satisfying
* 0 < rand < max */
} while (mp_cmp(rand, max) != MP_LT);
} while (!(mp_cmp(rand, max) == MP_LT && mp_cmp_d(rand, 0) == MP_GT));
m_burn(randbuf, len);
m_free(randbuf);
}

View File

@@ -22,15 +22,14 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#ifndef _RANDOM_H_
#define _RANDOM_H_
#ifndef DROPBEAR_RANDOM_H_
#define DROPBEAR_RANDOM_H_
struct mp_int;
#include "includes.h"
void seedrandom();
void reseedrandom();
void genrandom(unsigned char* buf, int len);
void addrandom(unsigned char* buf, int len);
void seedrandom(void);
void genrandom(unsigned char* buf, unsigned int len);
void addrandom(unsigned char * buf, unsigned int len);
void gen_random_mpint(mp_int *max, mp_int *rand);
#endif /* _RANDOM_H_ */
#endif /* DROPBEAR_RANDOM_H_ */

661
dbutil.c
View File

@@ -48,6 +48,19 @@
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
#include "config.h"
#ifdef __linux__
#define _GNU_SOURCE
/* To call clock_gettime() directly */
#include <sys/syscall.h>
#endif /* __linux */
#ifdef HAVE_MACH_MACH_TIME_H
#include <mach/mach_time.h>
#include <mach/mach.h>
#endif
#include "includes.h"
#include "dbutil.h"
#include "buffer.h"
@@ -57,11 +70,11 @@
#define MAX_FMT 100
static void generic_dropbear_exit(int exitcode, const char* format,
va_list param);
va_list param) ATTRIB_NORETURN;
static void generic_dropbear_log(int priority, const char* format,
va_list param);
void (*_dropbear_exit)(int exitcode, const char* format, va_list param)
void (*_dropbear_exit)(int exitcode, const char* format, va_list param) ATTRIB_NORETURN
= generic_dropbear_exit;
void (*_dropbear_log)(int priority, const char* format, va_list param)
= generic_dropbear_log;
@@ -71,9 +84,9 @@ int debug_trace = 0;
#endif
#ifndef DISABLE_SYSLOG
void startsyslog() {
void startsyslog(const char *ident) {
openlog(PROGNAME, LOG_PID, LOG_AUTHPRIV);
openlog(ident, LOG_PID, LOG_AUTHPRIV);
}
#endif /* DISABLE_SYSLOG */
@@ -111,7 +124,7 @@ static void generic_dropbear_exit(int exitcode, const char* format,
}
void fail_assert(const char* expr, const char* file, int line) {
dropbear_exit("failed assertion (%s:%d): `%s'", file, line, expr);
dropbear_exit("Failed assertion (%s:%d): `%s'", file, line, expr);
}
static void generic_dropbear_log(int UNUSED(priority), const char* format,
@@ -137,8 +150,36 @@ void dropbear_log(int priority, const char* format, ...) {
#ifdef DEBUG_TRACE
void dropbear_trace(const char* format, ...) {
static double debug_start_time = -1;
void debug_start_net()
{
if (getenv("DROPBEAR_DEBUG_NET_TIMESTAMP"))
{
/* Timestamps start from first network activity */
struct timeval tv;
gettimeofday(&tv, NULL);
debug_start_time = tv.tv_sec + (tv.tv_usec / 1000000.0);
TRACE(("Resetting Dropbear TRACE timestamps"))
}
}
static double time_since_start()
{
double nowf;
struct timeval tv;
gettimeofday(&tv, NULL);
nowf = tv.tv_sec + (tv.tv_usec / 1000000.0);
if (debug_start_time < 0)
{
debug_start_time = nowf;
return 0;
}
return nowf - debug_start_time;
}
void dropbear_trace(const char* format, ...) {
va_list param;
if (!debug_trace) {
@@ -146,335 +187,188 @@ void dropbear_trace(const char* format, ...) {
}
va_start(param, format);
fprintf(stderr, "TRACE: ");
fprintf(stderr, "TRACE (%d) %f: ", getpid(), time_since_start());
vfprintf(stderr, format, param);
fprintf(stderr, "\n");
va_end(param);
}
void dropbear_trace2(const char* format, ...) {
static int trace_env = -1;
va_list param;
if (trace_env == -1) {
trace_env = getenv("DROPBEAR_TRACE2") ? 1 : 0;
}
if (!(debug_trace && trace_env)) {
return;
}
va_start(param, format);
fprintf(stderr, "TRACE2 (%d) %f: ", getpid(), time_since_start());
vfprintf(stderr, format, param);
fprintf(stderr, "\n");
va_end(param);
}
#endif /* DEBUG_TRACE */
static void set_sock_priority(int sock) {
/* Connect to a given unix socket. The socket is blocking */
#ifdef ENABLE_CONNECT_UNIX
int connect_unix(const char* path) {
struct sockaddr_un addr;
int fd = -1;
int val;
/* disable nagle */
val = 1;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*)&val, sizeof(val));
/* set the TOS bit. note that this will fail for ipv6, I can't find any
* equivalent. */
#ifdef IPTOS_LOWDELAY
val = IPTOS_LOWDELAY;
setsockopt(sock, IPPROTO_IP, IP_TOS, (void*)&val, sizeof(val));
#endif
#ifdef SO_PRIORITY
/* linux specific, sets QoS class.
* 6 looks to be optimal for interactive traffic (see tc-prio(8) ). */
val = 6;
setsockopt(sock, SOL_SOCKET, SO_PRIORITY, (void*) &val, sizeof(val));
#endif
}
/* Listen on address:port.
* Special cases are address of "" listening on everything,
* and address of NULL listening on localhost only.
* Returns the number of sockets bound on success, or -1 on failure. On
* failure, if errstring wasn't NULL, it'll be a newly malloced error
* string.*/
int dropbear_listen(const char* address, const char* port,
int *socks, unsigned int sockcount, char **errstring, int *maxfd) {
struct addrinfo hints, *res = NULL, *res0 = NULL;
int err;
unsigned int nsock;
struct linger linger;
int val;
int sock;
TRACE(("enter dropbear_listen"))
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; /* TODO: let them flag v4 only etc */
hints.ai_socktype = SOCK_STREAM;
/* for calling getaddrinfo:
address == NULL and !AI_PASSIVE: local loopback
address == NULL and AI_PASSIVE: all interfaces
address != NULL: whatever the address says */
if (!address) {
TRACE(("dropbear_listen: local loopback"))
} else {
if (address[0] == '\0') {
TRACE(("dropbear_listen: all interfaces"))
address = NULL;
}
hints.ai_flags = AI_PASSIVE;
}
err = getaddrinfo(address, port, &hints, &res0);
if (err) {
if (errstring != NULL && *errstring == NULL) {
int len;
len = 20 + strlen(gai_strerror(err));
*errstring = (char*)m_malloc(len);
snprintf(*errstring, len, "Error resolving: %s", gai_strerror(err));
}
if (res0) {
freeaddrinfo(res0);
res0 = NULL;
}
TRACE(("leave dropbear_listen: failed resolving"))
memset((void*)&addr, 0x0, sizeof(addr));
addr.sun_family = AF_UNIX;
strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
fd = socket(PF_UNIX, SOCK_STREAM, 0);
if (fd < 0) {
TRACE(("Failed to open unix socket"))
return -1;
}
nsock = 0;
for (res = res0; res != NULL && nsock < sockcount;
res = res->ai_next) {
/* Get a socket */
socks[nsock] = socket(res->ai_family, res->ai_socktype,
res->ai_protocol);
sock = socks[nsock]; /* For clarity */
if (sock < 0) {
err = errno;
TRACE(("socket() failed"))
continue;
}
/* Various useful socket options */
val = 1;
/* set to reuse, quick timeout */
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &val, sizeof(val));
linger.l_onoff = 1;
linger.l_linger = 5;
setsockopt(sock, SOL_SOCKET, SO_LINGER, (void*)&linger, sizeof(linger));
set_sock_priority(sock);
if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
err = errno;
close(sock);
TRACE(("bind(%s) failed", port))
continue;
}
if (listen(sock, 20) < 0) {
err = errno;
close(sock);
TRACE(("listen() failed"))
continue;
}
*maxfd = MAX(*maxfd, sock);
nsock++;
}
if (res0) {
freeaddrinfo(res0);
res0 = NULL;
}
if (nsock == 0) {
if (errstring != NULL && *errstring == NULL) {
int len;
len = 20 + strlen(strerror(err));
*errstring = (char*)m_malloc(len);
snprintf(*errstring, len, "Error listening: %s", strerror(err));
}
TRACE(("leave dropbear_listen: failure, %s", strerror(err)))
if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
TRACE(("Failed to connect to '%s' socket", path))
m_close(fd);
return -1;
}
TRACE(("leave dropbear_listen: success, %d socks bound", nsock))
return nsock;
return fd;
}
/* Connect via TCP to a host. Connection will try ipv4 or ipv6, will
* return immediately if nonblocking is set. On failure, if errstring
* wasn't null, it will be a newly malloced error message */
/* TODO: maxfd */
int connect_remote(const char* remotehost, const char* remoteport,
int nonblocking, char ** errstring) {
struct addrinfo *res0 = NULL, *res = NULL, hints;
int sock;
int err;
TRACE(("enter connect_remote"))
if (errstring != NULL) {
*errstring = NULL;
}
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = PF_UNSPEC;
err = getaddrinfo(remotehost, remoteport, &hints, &res0);
if (err) {
if (errstring != NULL && *errstring == NULL) {
int len;
len = 20 + strlen(gai_strerror(err));
*errstring = (char*)m_malloc(len);
snprintf(*errstring, len, "Error resolving: %s", gai_strerror(err));
}
TRACE(("Error resolving: %s", gai_strerror(err)))
return -1;
}
sock = -1;
err = EADDRNOTAVAIL;
for (res = res0; res; res = res->ai_next) {
sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sock < 0) {
err = errno;
continue;
}
if (nonblocking) {
if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
close(sock);
sock = -1;
if (errstring != NULL && *errstring == NULL) {
*errstring = m_strdup("Failed non-blocking");
}
TRACE(("Failed non-blocking: %s", strerror(errno)))
continue;
}
}
if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) {
if (errno == EINPROGRESS && nonblocking) {
TRACE(("Connect in progress"))
break;
} else {
err = errno;
close(sock);
sock = -1;
continue;
}
}
break; /* Success */
}
if (sock < 0 && !(errno == EINPROGRESS && nonblocking)) {
/* Failed */
if (errstring != NULL && *errstring == NULL) {
int len;
len = 20 + strlen(strerror(err));
*errstring = (char*)m_malloc(len);
snprintf(*errstring, len, "Error connecting: %s", strerror(err));
}
TRACE(("Error connecting: %s", strerror(err)))
} else {
/* Success */
set_sock_priority(sock);
}
freeaddrinfo(res0);
if (sock > 0 && errstring != NULL && *errstring != NULL) {
m_free(*errstring);
}
TRACE(("leave connect_remote: sock %d\n", sock))
return sock;
}
/* Return a string representation of the socket address passed. The return
* value is allocated with malloc() */
unsigned char * getaddrstring(struct sockaddr_storage* addr, int withport) {
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
char *retstring = NULL;
int ret;
unsigned int len;
len = sizeof(struct sockaddr_storage);
/* Some platforms such as Solaris 8 require that len is the length
* of the specific structure. Some older linux systems (glibc 2.1.3
* such as debian potato) have sockaddr_storage.__ss_family instead
* but we'll ignore them */
#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY
if (addr->ss_family == AF_INET) {
len = sizeof(struct sockaddr_in);
}
#ifdef AF_INET6
if (addr->ss_family == AF_INET6) {
len = sizeof(struct sockaddr_in6);
}
#endif
#endif
ret = getnameinfo((struct sockaddr*)addr, len, hbuf, sizeof(hbuf),
sbuf, sizeof(sbuf), NI_NUMERICSERV | NI_NUMERICHOST);
/* Sets up a pipe for a, returning three non-blocking file descriptors
* and the pid. exec_fn is the function that will actually execute the child process,
* it will be run after the child has fork()ed, and is passed exec_data.
* If ret_errfd == NULL then stderr will not be captured.
* ret_pid can be passed as NULL to discard the pid. */
int spawn_command(void(*exec_fn)(void *user_data), void *exec_data,
int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid) {
int infds[2];
int outfds[2];
int errfds[2];
pid_t pid;
if (ret != 0) {
/* This is a fairly bad failure - it'll fallback to IP if it
* just can't resolve */
dropbear_exit("failed lookup (%d, %d)", ret, errno);
const int FDIN = 0;
const int FDOUT = 1;
/* redirect stdin/stdout/stderr */
if (pipe(infds) != 0) {
return DROPBEAR_FAILURE;
}
if (pipe(outfds) != 0) {
return DROPBEAR_FAILURE;
}
if (ret_errfd && pipe(errfds) != 0) {
return DROPBEAR_FAILURE;
}
if (withport) {
len = strlen(hbuf) + 2 + strlen(sbuf);
retstring = (char*)m_malloc(len);
snprintf(retstring, len, "%s:%s", hbuf, sbuf);
} else {
retstring = m_strdup(hbuf);
}
return retstring;
}
/* Get the hostname corresponding to the address addr. On failure, the IP
* address is returned. The return value is allocated with strdup() */
char* getaddrhostname(struct sockaddr_storage * addr) {
char hbuf[NI_MAXHOST];
char sbuf[NI_MAXSERV];
int ret;
unsigned int len;
#ifdef DO_HOST_LOOKUP
const int flags = NI_NUMERICSERV;
#ifdef USE_VFORK
pid = vfork();
#else
const int flags = NI_NUMERICHOST | NI_NUMERICSERV;
pid = fork();
#endif
len = sizeof(struct sockaddr_storage);
/* Some platforms such as Solaris 8 require that len is the length
* of the specific structure. */
#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY
if (addr->ss_family == AF_INET) {
len = sizeof(struct sockaddr_in);
}
#ifdef AF_INET6
if (addr->ss_family == AF_INET6) {
len = sizeof(struct sockaddr_in6);
}
#endif
#endif
ret = getnameinfo((struct sockaddr*)addr, len, hbuf, sizeof(hbuf),
sbuf, sizeof(sbuf), flags);
if (ret != 0) {
/* On some systems (Darwin does it) we get EINTR from getnameinfo
* somehow. Eew. So we'll just return the IP, since that doesn't seem
* to exhibit that behaviour. */
return getaddrstring(addr, 0);
if (pid < 0) {
return DROPBEAR_FAILURE;
}
return m_strdup(hbuf);
if (!pid) {
/* child */
TRACE(("back to normal sigchld"))
/* Revert to normal sigchld handling */
if (signal(SIGCHLD, SIG_DFL) == SIG_ERR) {
dropbear_exit("signal() error");
}
/* redirect stdin/stdout */
if ((dup2(infds[FDIN], STDIN_FILENO) < 0) ||
(dup2(outfds[FDOUT], STDOUT_FILENO) < 0) ||
(ret_errfd && dup2(errfds[FDOUT], STDERR_FILENO) < 0)) {
TRACE(("leave noptycommand: error redirecting FDs"))
dropbear_exit("Child dup2() failure");
}
close(infds[FDOUT]);
close(infds[FDIN]);
close(outfds[FDIN]);
close(outfds[FDOUT]);
if (ret_errfd)
{
close(errfds[FDIN]);
close(errfds[FDOUT]);
}
exec_fn(exec_data);
/* not reached */
return DROPBEAR_FAILURE;
} else {
/* parent */
close(infds[FDIN]);
close(outfds[FDOUT]);
setnonblocking(outfds[FDIN]);
setnonblocking(infds[FDOUT]);
if (ret_errfd) {
close(errfds[FDOUT]);
setnonblocking(errfds[FDIN]);
}
if (ret_pid) {
*ret_pid = pid;
}
*ret_writefd = infds[FDOUT];
*ret_readfd = outfds[FDIN];
if (ret_errfd) {
*ret_errfd = errfds[FDIN];
}
return DROPBEAR_SUCCESS;
}
}
/* Runs a command with "sh -c". Will close FDs (except stdin/stdout/stderr) and
* re-enabled SIGPIPE. If cmd is NULL, will run a login shell.
*/
void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell) {
char * argv[4];
char * baseshell = NULL;
unsigned int i;
baseshell = basename(usershell);
if (cmd != NULL) {
argv[0] = baseshell;
} else {
/* a login shell should be "-bash" for "/bin/bash" etc */
int len = strlen(baseshell) + 2; /* 2 for "-" */
argv[0] = (char*)m_malloc(len);
snprintf(argv[0], len, "-%s", baseshell);
}
if (cmd != NULL) {
argv[1] = "-c";
argv[2] = (char*)cmd;
argv[3] = NULL;
} else {
/* construct a shell of the form "-bash" etc */
argv[1] = NULL;
}
/* Re-enable SIGPIPE for the executed process */
if (signal(SIGPIPE, SIG_DFL) == SIG_ERR) {
dropbear_exit("signal() error");
}
/* close file descriptors except stdin/stdout/stderr
* Need to be sure FDs are closed here to avoid reading files as root */
for (i = 3; i <= maxfd; i++) {
m_close(i);
}
execv(usershell, argv);
}
#ifdef DEBUG_TRACE
@@ -494,6 +388,14 @@ void printhex(const char * label, const unsigned char * buf, int len) {
}
fprintf(stderr, "\n");
}
void printmpint(const char *label, mp_int *mp) {
buffer *buf = buf_new(1000);
buf_putmpint(buf, mp);
printhex(label, buf->data, buf->len);
buf_free(buf);
}
#endif
/* Strip all control characters from text (a null-terminated string), except
@@ -568,8 +470,6 @@ int buf_getline(buffer * line, FILE * authfile) {
int c = EOF;
TRACE(("enter buf_getline"))
buf_setpos(line, 0);
buf_setlen(line, 0);
@@ -593,10 +493,8 @@ out:
/* if we didn't read anything before EOF or error, exit */
if (c == EOF && line->pos == 0) {
TRACE(("leave buf_getline: failure"))
return DROPBEAR_FAILURE;
} else {
TRACE(("leave buf_getline: success"))
buf_setpos(line, 0);
return DROPBEAR_SUCCESS;
}
@@ -606,8 +504,12 @@ out:
/* make sure that the socket closes */
void m_close(int fd) {
int val;
if (fd == -1) {
return;
}
do {
val = close(fd);
} while (val < 0 && errno == EINTR);
@@ -643,12 +545,6 @@ void * m_strdup(const char * str) {
return ret;
}
void __m_free(void* ptr) {
if (ptr != NULL) {
free(ptr);
}
}
void * m_realloc(void* ptr, size_t size) {
void *ret;
@@ -663,21 +559,6 @@ void * m_realloc(void* ptr, size_t size) {
return ret;
}
/* Clear the data, based on the method in David Wheeler's
* "Secure Programming for Linux and Unix HOWTO" */
/* Beware of calling this from within dbutil.c - things might get
* optimised away */
void m_burn(void *data, unsigned int len) {
volatile char *p = data;
if (data == NULL)
return;
while (len--) {
*p++ = 0x66;
}
}
void setnonblocking(int fd) {
TRACE(("setnonblocking: %d", fd))
@@ -699,3 +580,105 @@ void disallow_core() {
lim.rlim_cur = lim.rlim_max = 0;
setrlimit(RLIMIT_CORE, &lim);
}
/* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE, with the result in *val */
int m_str_to_uint(const char* str, unsigned int *val) {
unsigned long l;
errno = 0;
l = strtoul(str, NULL, 10);
/* The c99 spec doesn't actually seem to define EINVAL, but most platforms
* I've looked at mention it in their manpage */
if ((l == 0 && errno == EINVAL)
|| (l == ULONG_MAX && errno == ERANGE)
|| (l > UINT_MAX)) {
return DROPBEAR_FAILURE;
} else {
*val = l;
return DROPBEAR_SUCCESS;
}
}
/* Returns malloced path. inpath beginning with '/' is returned as-is,
otherwise home directory is prepended */
char * expand_homedir_path(const char *inpath) {
struct passwd *pw = NULL;
if (inpath[0] != '/') {
pw = getpwuid(getuid());
if (pw && pw->pw_dir) {
int len = strlen(inpath) + strlen(pw->pw_dir) + 2;
char *buf = m_malloc(len);
snprintf(buf, len, "%s/%s", pw->pw_dir, inpath);
return buf;
}
}
/* Fallback */
return m_strdup(inpath);
}
int constant_time_memcmp(const void* a, const void *b, size_t n)
{
const char *xa = a, *xb = b;
uint8_t c = 0;
size_t i;
for (i = 0; i < n; i++)
{
c |= (xa[i] ^ xb[i]);
}
return c;
}
#if defined(__linux__) && defined(SYS_clock_gettime)
/* CLOCK_MONOTONIC_COARSE was added in Linux 2.6.32 but took a while to
reach userspace include headers */
#ifndef CLOCK_MONOTONIC_COARSE
#define CLOCK_MONOTONIC_COARSE 6
#endif
static clockid_t get_linux_clock_source() {
struct timespec ts;
if (syscall(SYS_clock_gettime, CLOCK_MONOTONIC_COARSE, &ts) == 0) {
return CLOCK_MONOTONIC_COARSE;
}
if (syscall(SYS_clock_gettime, CLOCK_MONOTONIC, &ts) == 0) {
return CLOCK_MONOTONIC;
}
return -1;
}
#endif
time_t monotonic_now() {
#if defined(__linux__) && defined(SYS_clock_gettime)
static clockid_t clock_source = -2;
if (clock_source == -2) {
/* First run, find out which one works.
-1 will fall back to time() */
clock_source = get_linux_clock_source();
}
if (clock_source >= 0) {
struct timespec ts;
if (syscall(SYS_clock_gettime, clock_source, &ts) != 0) {
/* Intermittent clock failures should not happen */
dropbear_exit("Clock broke");
}
return ts.tv_sec;
}
#endif /* linux clock_gettime */
#if defined(HAVE_MACH_ABSOLUTE_TIME)
/* OS X, see https://developer.apple.com/library/mac/qa/qa1398/_index.html */
static mach_timebase_info_data_t timebase_info;
if (timebase_info.denom == 0) {
mach_timebase_info(&timebase_info);
}
return mach_absolute_time() * timebase_info.numer / timebase_info.denom
/ 1e9;
#endif /* osx mach_absolute_time */
/* Fallback for everything else - this will sometimes go backwards */
return time(NULL);
}

View File

@@ -22,36 +22,46 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#ifndef _DBUTIL_H_
#ifndef DROPBEAR_DBUTIL_H_
#define _DBUTIL_H_
#define DROPBEAR_DBUTIL_H_
#include "includes.h"
#include "buffer.h"
#include "queue.h"
#include "dbhelpers.h"
#ifndef DISABLE_SYSLOG
void startsyslog();
void startsyslog(const char *ident);
#endif
extern void (*_dropbear_exit)(int exitcode, const char* format, va_list param);
extern void (*_dropbear_exit)(int exitcode, const char* format, va_list param) ATTRIB_NORETURN;
extern void (*_dropbear_log)(int priority, const char* format, va_list param);
void dropbear_exit(const char* format, ...);
void dropbear_close(const char* format, ...);
void dropbear_log(int priority, const char* format, ...);
void fail_assert(const char* expr, const char* file, int line);
void dropbear_exit(const char* format, ...) ATTRIB_PRINTF(1,2) ATTRIB_NORETURN;
void dropbear_close(const char* format, ...) ATTRIB_PRINTF(1,2) ;
void dropbear_log(int priority, const char* format, ...) ATTRIB_PRINTF(2,3) ;
void fail_assert(const char* expr, const char* file, int line) ATTRIB_NORETURN;
#ifdef DEBUG_TRACE
void dropbear_trace(const char* format, ...);
void dropbear_trace(const char* format, ...) ATTRIB_PRINTF(1,2);
void dropbear_trace2(const char* format, ...) ATTRIB_PRINTF(1,2);
void printhex(const char * label, const unsigned char * buf, int len);
void printmpint(const char *label, mp_int *mp);
void debug_start_net(void);
extern int debug_trace;
#endif
char * stripcontrol(const char * text);
unsigned char * getaddrstring(struct sockaddr_storage* addr, int withport);
int dropbear_listen(const char* address, const char* port,
int *socks, unsigned int sockcount, char **errstring, int *maxfd);
int connect_remote(const char* remotehost, const char* remoteport,
int nonblocking, char ** errstring);
char* getaddrhostname(struct sockaddr_storage * addr);
int spawn_command(void(*exec_fn)(void *user_data), void *exec_data,
int *writefd, int *readfd, int *errfd, pid_t *pid);
void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell);
#ifdef ENABLE_CONNECT_UNIX
int connect_unix(const char* addr);
#endif
int buf_readfile(buffer* buf, const char* filename);
int buf_getline(buffer * line, FILE * authfile);
@@ -59,11 +69,10 @@ void m_close(int fd);
void * m_malloc(size_t size);
void * m_strdup(const char * str);
void * m_realloc(void* ptr, size_t size);
#define m_free(X) __m_free(X); (X) = NULL;
void __m_free(void* ptr);
void m_burn(void* data, unsigned int len);
#define m_free(X) do {free(X); (X) = NULL;} while (0)
void setnonblocking(int fd);
void disallow_core();
void disallow_core(void);
int m_str_to_uint(const char* str, unsigned int *val);
/* Used to force mp_ints to be initialised */
#define DEF_MP_INT(X) mp_int X = {0, 0, 0, NULL}
@@ -71,4 +80,13 @@ void disallow_core();
/* Dropbear assertion */
#define dropbear_assert(X) do { if (!(X)) { fail_assert(#X, __FILE__, __LINE__); } } while (0)
#endif /* _DBUTIL_H_ */
/* Returns 0 if a and b have the same contents */
int constant_time_memcmp(const void* a, const void *b, size_t n);
/* Returns a time in seconds that doesn't go backwards - does not correspond to
a real-world clock */
time_t monotonic_now(void);
char * expand_homedir_path(const char *inpath);
#endif /* DROPBEAR_DBUTIL_H_ */

16
debian/README.runit vendored
View File

@@ -31,16 +31,16 @@ run script
# vi /etc/dropbear/run
Finally enable the service by linking dropbear's service directory to
/var/service/. The service will be started within five seconds, and
automatically at boot time. The sysv init script is disabled; see the
runsvctrl(8) program for information on how to control services handled by
runit. See the svlogd(8) program on how to configure the log service.
Finally enable the service through runit's update-service(8) program, the
service will be started within five seconds, and automatically at boot
time, and the sysv init script will automatically be disabled; see the
sv(8) program for information on how to control services handled by runit.
See the svlogd(8) program on how to configure the log service.
# ln -s /etc/dropbear /var/service/
# update-service --add /etc/dropbear
Optionally check the status of the service a few seconds later
# runsvstat -l /var/service/dropbear
# sv status dropbear
-- Gerrit Pape <pape@smarden.org>, Sun, 16 May 2004 15:52:34 +0000
-- Gerrit Pape <pape@smarden.org>, Fri, 02 Mar 2007 20:41:08 +0000

204
debian/changelog vendored
View File

@@ -1,8 +1,208 @@
dropbear (0.49-0.1) unstable; urgency=low
dropbear (2016.74-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Fri, 23 Feb 2007 00:44:00 +0900
-- Matt Johnston <matt@ucc.asn.au> Thu, 21 Jul 2016 22:51:57 +0800
dropbear (2016.73-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Fri, 18 Mar 2016 22:52:58 +0800
dropbear (2016.72-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Wed, 10 Mar 2016 22:52:58 +0800
dropbear (2015.70-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Thu, 26 Nov 2015 22:52:58 +0800
dropbear (2015.69-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Wed, 25 Nov 2015 22:52:58 +0800
dropbear (2015.68-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Sat, 8 Aug 2015 22:52:58 +0800
dropbear (2015.67-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Wed, 28 Jan 2015 22:53:59 +0800
dropbear (2014.66-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Thu, 23 Oct 2014 22:54:00 +0800
dropbear (2014.65-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Fri, 8 Aug 2014 22:54:00 +0800
dropbear (2014.64-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Sun, 27 Jul 2014 22:54:00 +0800
dropbear (2014.63-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Wed, 19 Feb 2014 22:54:00 +0800
dropbear (2013.62) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Tue, 7 Dec 2013 22:54:00 +0800
dropbear (2013.60-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Wed, 16 Oct 2013 22:54:00 +0800
dropbear (2013.59-0.1) unstable; urgency=low
* New upstream release.
* Build with DEB_BUILD_MAINT_OPTIONS = hardening=+all
-- Matt Johnston <matt@ucc.asn.au> Fri, 4 Oct 2013 22:54:00 +0800
dropbear (2013.58-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Thu, 18 Apr 2013 22:54:00 +0800
dropbear (2013.57-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Mon, 15 Apr 2013 22:54:00 +0800
dropbear (2013.56-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Thu, 21 Mar 2013 22:54:00 +0800
dropbear (2012.55-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Wed, 22 Feb 2012 22:54:00 +0800
dropbear (2011.54-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Tues, 8 Nov 2011 22:54:00 +0800
dropbear (0.53.1-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Wed, 2 Mar 2011 22:54:00 +0900
dropbear (0.53-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Thu, 24 Feb 2011 22:54:00 +0900
dropbear (0.52-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Wed, 12 Nov 2008 22:54:00 +0900
dropbear (0.51-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Thu, 27 Mar 2008 19:14:00 +0900
dropbear (0.50-4) unstable; urgency=low
* debian/dropbear.init: apply patch from Petter Reinholdtsen: add LSB
formatted dependency info in init.d script (closes: #466257).
* debian/rules: no longer include symlinks for ./supervise/ subdirectories.
* debian/dropbear.postinst: upgrade from << 0.50-4: if dropbear is managed
by runit, remove service, and re-add using update-service(8).
* debian/control: Standards-Version: 3.7.3.0.
* debian/rules: target clean: don't ignore errors but check for readable
./Makefile.
-- Gerrit Pape <pape@smarden.org> Thu, 06 Mar 2008 19:06:58 +0000
dropbear (0.50-3) unstable; urgency=low
* debian/dropbear.init: use the update-service(8) program from the runit
package instead of directly checking for the symlink in /var/service/.
* debian/README.runit: talk about update-service(8) instead of symlinks
in /var/service/.
-- Gerrit Pape <pape@smarden.org> Fri, 15 Feb 2008 00:32:37 +0000
dropbear (0.50-2) unstable; urgency=low
* debian/dropbear.README.Debian: no longer talk about entropy from
/dev/random, /dev/urandom is now used by default (thx Joey Hess,
closes: #441515).
-- Gerrit Pape <pape@smarden.org> Mon, 24 Sep 2007 16:49:17 +0000
dropbear (0.50-1) unstable; urgency=low
* debian/README.runit: minor.
* new upstream version.
* debian/diff/0001-options.h-use-dev-urandom-instead-of-dev-random-a.diff:
remove; fixed upstream.
-- Gerrit Pape <pape@smarden.org> Thu, 09 Aug 2007 23:01:01 +0000
dropbear (0.49-2) unstable; urgency=low
* debian/rules: apply diffs from debian/diff/ with patch -p1 instead of
-p0.
* debian/diff/0001-options.h-use-dev-urandom-instead-of-dev-random-a.diff:
new; options.h: use /dev/urandom instead of /dev/random as
DROPBEAR_RANDOM_DEV (closes: #386976).
* debian/rules: target clean: remove libtomcrypt/Makefile,
libtommath/Makefile.
-- Gerrit Pape <pape@smarden.org> Sat, 09 Jun 2007 08:59:59 +0000
dropbear (0.49-1) unstable; urgency=high
* new upstream release, fixes
* CVE-2007-1099: dropbear dbclient insufficient warning on hostkey
mismatch (closes: #412899).
* dbclient uses static "Password:" prompt instead of using the server's
prompt (closes: #394996).
* debian/control: Suggests: openssh-client, not ssh (closes: #405686);
Standards-Version: 3.7.2.2.
* debian/README.Debian: ssh -> openssh-server, openssh-client; remove
'Replacing OpenSSH "sshd" with Dropbear' part, this is simply done by not
installing the openssh-server package.
* debian/README.runit: runsvstat -> sv status.
-- Gerrit Pape <pape@smarden.org> Fri, 2 Mar 2007 20:48:18 +0000
dropbear (0.48.1-1) unstable; urgency=medium

4
debian/control vendored
View File

@@ -3,12 +3,12 @@ Section: net
Priority: optional
Maintainer: Gerrit Pape <pape@smarden.org>
Build-Depends: libz-dev
Standards-Version: 3.6.2.1
Standards-Version: 3.7.3.0
Package: dropbear
Architecture: any
Depends: ${shlibs:Depends}
Suggests: ssh, runit
Suggests: openssh-client, runit
Description: lightweight SSH2 server and client
dropbear is a SSH 2 server and client designed to be small enough to
be used in small memory environments, while still being functional and

View File

@@ -1,52 +1,19 @@
Dropbear for Debian
-------------------
This package will attempt to listen on port 22. If the OpenSSH
package ("ssh") is installed, the file /etc/default/dropbear
will be set up so that the server does not start by default.
This package will attempt to setup the Dropbear ssh server to listen on
port 22. If the OpenSSH server package ("openssh-server") is installed,
the file /etc/default/dropbear will be set up so that the server does not
start by default.
You can run Dropbear concurrently with OpenSSH 'sshd' by
modifying /etc/default/dropbear so that "NO_START" is set to
"0" and changing the port number that Dropbear runs on. Follow
the instructions in the file.
You can run Dropbear concurrently with OpenSSH 'sshd' by modifying
/etc/default/dropbear so that "NO_START" is set to "0", and changing the
port number that Dropbear runs on. Follow the instructions in the file.
This package suggests you install the "ssh" package. This package
provides the "ssh" client program, as well as the "/usr/bin/scp"
binary you will need to be able to retrieve files from a server
running Dropbear via SCP.
Replacing OpenSSH "sshd" with Dropbear
--------------------------------------
You will still want to have the "ssh" package installed, as it
provides the "ssh" and "scp" binaries. When you install this
package, it checks for existing OpenSSH host keys and if found,
converts them to the Dropbear format.
If this appears to have worked, you should be able to change over
by following these steps:
1. Stop the OpenSSH server
% /etc/init.d/ssh stop
2. Prevent the OpenSSH server from starting in the future
% touch /etc/ssh/sshd_not_to_be_run
3. Modify the Dropbear defaults file, set NO_START to 0 and
ensure DROPBEAR_PORT is set to 22.
% editor /etc/default/dropbear
4. Restart the Dropbear server.
% /etc/init.d/dropbear restart
This package suggests you install the "openssh-client" package, which
provides the "ssh" client program, as well as the "/usr/bin/scp" binary
you will need to be able to retrieve files via SCP from a server running
Dropbear.
See the Dropbear homepage for more information:
http://matt.ucc.asn.au/dropbear/dropbear.html
Entropy from /dev/random
------------------------
The dropbear binary package is configured at compile time to read
entropy from /dev/random. If /dev/random on a system blocks when
reading data from it, client logins may be delayed until the client
times out. The dropbear server writes a notice to the logs when it
sees /dev/random blocking. A workaround for such systems is to
re-compile the package with DROPBEAR_RANDOM_DEV set to /dev/urandom
in options.h.

18
debian/dropbear.init vendored
View File

@@ -1,4 +1,12 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: dropbear
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Dropbear SSH server
### END INIT INFO
#
# Do not configure this file. Edit /etc/default/dropbear instead!
#
@@ -17,8 +25,8 @@ set -e
cancel() { echo "$1" >&2; exit 0; };
test ! -r /etc/default/dropbear || . /etc/default/dropbear
test -x "$DAEMON" || cancel "$DAEMON does not exist or is not executable."
test ! -h /var/service/dropbear || \
cancel '/var/service/dropbear exists, service is controlled through runit.'
test ! -x /usr/sbin/update-service || ! update-service --check dropbear ||
cancel 'The dropbear service is controlled through runit, use the sv(8) program'
test -z "$DROPBEAR_BANNER" || \
DROPBEAR_EXTRA_ARGS="$DROPBEAR_EXTRA_ARGS -b $DROPBEAR_BANNER"
@@ -26,6 +34,8 @@ test -n "$DROPBEAR_RSAKEY" || \
DROPBEAR_RSAKEY="/etc/dropbear/dropbear_rsa_host_key"
test -n "$DROPBEAR_DSSKEY" || \
DROPBEAR_DSSKEY="/etc/dropbear/dropbear_dss_host_key"
test -n "$DROPBEAR_RECEIVE_WINDOW" || \
DROPBEAR_RECEIVE_WINDOW="65536"
case "$1" in
start)
@@ -33,7 +43,7 @@ case "$1" in
echo -n "Starting $DESC: "
start-stop-daemon --start --quiet --pidfile /var/run/"$NAME".pid \
--exec "$DAEMON" -- -d "$DROPBEAR_DSSKEY" -r "$DROPBEAR_RSAKEY" \
-p "$DROPBEAR_PORT" $DROPBEAR_EXTRA_ARGS
-p "$DROPBEAR_PORT" -W "$DROPBEAR_RECEIVE_WINDOW" $DROPBEAR_EXTRA_ARGS
echo "$NAME."
;;
stop)
@@ -48,7 +58,7 @@ case "$1" in
sleep 1
start-stop-daemon --start --quiet --pidfile /var/run/"$NAME".pid \
--exec "$DAEMON" -- -d "$DROPBEAR_DSSKEY" -r "$DROPBEAR_RSAKEY" \
-p "$DROPBEAR_PORT" $DROPBEAR_EXTRA_ARGS
-p "$DROPBEAR_PORT" -W "$DROPBEAR_RECEIVE_WINDOW" $DROPBEAR_EXTRA_ARGS
echo "$NAME."
;;
*)

View File

@@ -54,6 +54,10 @@ DROPBEAR_BANNER=""
# DSS hostkey file (default: /etc/dropbear/dropbear_dss_host_key)
#DROPBEAR_DSSKEY="/etc/dropbear/dropbear_dss_host_key"
# Receive window size - this is a tradeoff between memory and
# network performance
DROPBEAR_RECEIVE_WINDOW=65536
EOT
fi
@@ -65,3 +69,11 @@ if test -x /etc/init.d/dropbear; then
/etc/init.d/dropbear restart
fi
fi
if test -n "$2" && dpkg --compare-versions "$2" lt '0.50-4' &&
update-service --check dropbear 2>/dev/null; then
update-service --remove /etc/dropbear 2>/dev/null || :
sleep 6
rm -rf /var/run/dropbear /var/run/dropbear.log
update-service --add /etc/dropbear || :
fi

28
debian/rules vendored
View File

@@ -1,5 +1,9 @@
#!/usr/bin/make -f
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
DPKG_EXPORT_BUILDFLAGS = 1
include /usr/share/dpkg/buildflags.mk
#export DH_OPTIONS
DEB_HOST_GNU_TYPE ?=$(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
DEB_BUILD_GNU_TYPE ?=$(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
@@ -9,13 +13,6 @@ ifneq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
STRIP =: nostrip
endif
CFLAGS =-Wall -g
ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
CFLAGS +=-O0
else
CFLAGS +=-O2
endif
CONFFLAGS =
CC =gcc
ifneq (,$(findstring diet,$(DEB_BUILD_OPTIONS)))
@@ -28,7 +25,7 @@ DIR =$(shell pwd)/debian/dropbear
patch: deb-checkdir patch-stamp
patch-stamp:
for i in `ls -1 debian/diff/*.diff || :`; do \
patch -p0 <$$i || exit 1; \
patch -p1 <$$i || exit 1; \
done
touch patch-stamp
@@ -46,10 +43,11 @@ build-stamp: config.status
touch build-stamp
clean: deb-checkdir deb-checkuid
-$(MAKE) distclean
test ! -r Makefile || $(MAKE) distclean
rm -f libtomcrypt/Makefile libtommath/Makefile
test ! -e patch-stamp || \
for i in `ls -1r debian/diff/*.diff || :`; do \
patch -p0 -R <$$i; \
patch -p1 -R <$$i; \
done
rm -f patch-stamp build-stamp config.log config.status
rm -rf '$(DIR)'
@@ -76,16 +74,14 @@ install: deb-checkdir deb-checkuid build-stamp
install -d -m0755 '$(DIR)'/etc/dropbear/log
install -m0755 debian/service/log '$(DIR)'/etc/dropbear/log/run
ln -s /var/log/dropbear '$(DIR)'/etc/dropbear/log/main
ln -s /var/run/dropbear '$(DIR)'/etc/dropbear/supervise
ln -s /var/run/dropbear.log '$(DIR)'/etc/dropbear/log/supervise
# man pages
install -d -m0755 '$(DIR)'/usr/share/man/man8
for i in dropbear.8 dropbearkey.8; do \
install -m644 $$i '$(DIR)'/usr/share/man/man8/ || exit 1; \
install -d -m0755 '$(DIR)'/usr/share/man/man1
install -m644 dropbear.8 '$(DIR)'/usr/share/man/man8/
for i in dbclient.1 dropbearkey.1 dropbearconvert.1; do \
install -m644 $$i '$(DIR)'/usr/share/man/man1/ || exit 1; \
done
gzip -9 '$(DIR)'/usr/share/man/man8/*.8
install -d -m0755 '$(DIR)'/usr/share/man/man1
install -m644 dbclient.1 '$(DIR)'/usr/share/man/man1/
gzip -9 '$(DIR)'/usr/share/man/man1/*.1
# copyright, changelog
cat debian/copyright.in LICENSE >debian/copyright

11
debug.h
View File

@@ -22,8 +22,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#ifndef _DEBUG_H_
#define _DEBUG_H_
#ifndef DROPBEAR_DEBUG_H_
#define DROPBEAR_DEBUG_H_
#include "includes.h"
@@ -63,10 +63,17 @@
/* you don't need to touch this block */
#ifdef DEBUG_TRACE
#define TRACE(X) dropbear_trace X;
#define TRACE2(X) dropbear_trace2 X;
#else /*DEBUG_TRACE*/
#define TRACE(X)
#define TRACE2(X)
#endif /*DEBUG_TRACE*/
/* To debug with GDB it is easier to run with no forking of child processes.
You will need to pass "-F" as well. */
/* #define DEBUG_NOFORK */
/* For testing as non-root on shadowed systems, include the crypt of a password
* here. You can then log in as any user with this password. Ensure that you
* make your own password, and are careful about using this. This will also

94
dh_groups.c Normal file
View File

@@ -0,0 +1,94 @@
#include "options.h"
#include "dh_groups.h"
#if DROPBEAR_DH_GROUP1
/* diffie-hellman-group1-sha1 value for p */
const unsigned char dh_p_1[DH_P_1_LEN] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
#endif /* DROPBEAR_DH_GROUP1 */
#if DROPBEAR_DH_GROUP14
/* diffie-hellman-group14-sha1 value for p */
const unsigned char dh_p_14[DH_P_14_LEN] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF};
#endif /* DROPBEAR_DH_GROUP14 */
#if DROPBEAR_DH_GROUP16
/* diffie-hellman-group16-256 value for p */
const unsigned char dh_p_16[DH_P_16_LEN] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21,
0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02,
0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B,
0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3,
0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F,
0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E,
0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C,
0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC,
0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA,
0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF,
0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67,
0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18,
0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77,
0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95,
0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2,
0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4,
0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB,
0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A,
0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1,
0xE4, 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94,
0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, 0x3E,
0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, 0xBB, 0xE1,
0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46,
0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC,
0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A,
0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA,
0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68,
0x34, 0xB6, 0x15, 0x0B, 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F,
0xBE, 0xCA, 0xA6, 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2,
0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7,
0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, 0x93,
0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6,
0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
#endif /* DROPBEAR_DH_GROUP16 */
/* Same for all groups */
const int DH_G_VAL = 2;

24
dh_groups.h Normal file
View File

@@ -0,0 +1,24 @@
#ifndef DROPBEAR_DH_GROUPS_H
#define DROPBEAR_DH_GROUPS_H
#include "options.h"
#if DROPBEAR_DH_GROUP1
#define DH_P_1_LEN 128
extern const unsigned char dh_p_1[DH_P_1_LEN];
#endif
#if DROPBEAR_DH_GROUP14
#define DH_P_14_LEN 256
extern const unsigned char dh_p_14[DH_P_14_LEN];
#endif
#if DROPBEAR_DH_GROUP16
#define DH_P_16_LEN 512
extern const unsigned char dh_p_16[DH_P_16_LEN];
#endif
extern const int DH_G_VAL;
#endif

View File

@@ -1,17 +1,15 @@
.TH dropbear 8
.SH NAME
dropbear \- lightweight SSH2 server
dropbear \- lightweight SSH server
.SH SYNOPSIS
.B dropbear
[\-FEmwsgjki] [\-b
.I banner\fR] [\-d
.I dsskey\fR] [\-r
.I rsakey\fR] [\-p
.IR port ]
[\fIflag arguments\fR] [\-b
.I banner\fR]
[\-r
.I hostkeyfile\fR] [\-p [\fIaddress\fR:]\fIport\fR]
.SH DESCRIPTION
.B dropbear
is a SSH 2 server designed to be small enough to be used in small memory
environments, while still being functional and secure enough for general use.
is a small SSH server
.SH OPTIONS
.TP
.B \-b \fIbanner
@@ -20,21 +18,16 @@ Display the contents of the file
.I banner
before user login (default: none).
.TP
.B \-d \fIdsskey
dsskeyfile.
.B \-r \fIhostkey
Use the contents of the file
.I dsskey
for the dss host key (default: /etc/dropbear/dropbear_dss_host_key).
.I hostkey
for the SSH hostkey.
This file is generated with
.BR dropbearkey (8).
.BR dropbearkey (1)
or automatically with the '-R' option. See "Host Key Files" below.
.TP
.B \-r \fIrsakey
rsakeyfile.
Use the contents of the file
.I rsakey
for the rsa host key (default: /etc/dropbear/dropbear_rsa_host_key).
This file is generated with
.BR dropbearkey (8).
.B \-R
Generate hostkeys automatically. See "Host Key Files" below.
.TP
.B \-F
Don't fork into background.
@@ -60,7 +53,7 @@ Disable local port forwarding.
.B \-k
Disable remote port forwarding.
.TP
.B \-p \fI[address:]port
.B \-p\fR [\fIaddress\fR:]\fIport
Listen on specified
.I address
and TCP
@@ -82,11 +75,118 @@ default is /var/run/dropbear.pid
.TP
.B \-a
Allow remote hosts to connect to forwarded ports.
.TP
.B \-W \fIwindowsize
Specify the per-channel receive window buffer size. Increasing this
may improve network performance at the expense of memory use. Use -h to see the
default buffer size.
.TP
.B \-K \fItimeout_seconds
Ensure that traffic is transmitted at a certain interval in seconds. This is
useful for working around firewalls or routers that drop connections after
a certain period of inactivity. The trade-off is that a session may be
closed if there is a temporary lapse of network connectivity. A setting
if 0 disables keepalives. If no response is received for 3 consecutive keepalives the connection will be closed.
.TP
.B \-I \fIidle_timeout
Disconnect the session if no traffic is transmitted or received for \fIidle_timeout\fR seconds.
.TP
.B \-V
Print the version
.SH FILES
.TP
Authorized Keys
~/.ssh/authorized_keys can be set up to allow remote login with a RSA,
ECDSA, or DSS
key. Each line is of the form
.TP
[restrictions] ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIgAsp... [comment]
and can be extracted from a Dropbear private host key with "dropbearkey -y". This is the same format as used by OpenSSH, though the restrictions are a subset (keys with unknown restrictions are ignored).
Restrictions are comma separated, with double quotes around spaces in arguments.
Available restrictions are:
.TP
.B no-port-forwarding
Don't allow port forwarding for this connection
.TP
.B no-agent-forwarding
Don't allow agent forwarding for this connection
.TP
.B no-X11-forwarding
Don't allow X11 forwarding for this connection
.TP
.B no-pty
Disable PTY allocation. Note that a user can still obtain most of the
same functionality with other means even if no-pty is set.
.TP
.B command=\fR"\fIforced_command\fR"
Disregard the command provided by the user and always run \fIforced_command\fR.
The authorized_keys file and its containing ~/.ssh directory must only be
writable by the user, otherwise Dropbear will not allow a login using public
key authentication.
.TP
Host Key Files
Host key files are read at startup from a standard location, by default
/etc/dropbear/dropbear_dss_host_key, /etc/dropbear/dropbear_rsa_host_key, and
/etc/dropbear/dropbear_ecdsa_host_key
or specified on the commandline with -r. These are of the form generated
by dropbearkey. The -R option can be used to automatically generate keys
in the default location - keys will be generated after startup when the first
connection is established. This had the benefit that the system /dev/urandom
random number source has a better chance of being securely seeded.
.TP
Message Of The Day
By default the file /etc/motd will be printed for any login shell (unless
disabled at compile-time). This can also be disabled per-user
by creating a file ~/.hushlogin .
.SH ENVIRONMENT VARIABLES
Dropbear sets the standard variables USER, LOGNAME, HOME, SHELL, PATH, and TERM.
The variables below are set for sessions as appropriate.
.TP
.B SSH_TTY
This is set to the allocated TTY if a PTY was used.
.TP
.B SSH_CONNECTION
Contains "<remote_ip> <remote_port> <local_ip> <local_port>".
.TP
.B DISPLAY
Set X11 forwarding is used.
.TP
.B SSH_ORIGINAL_COMMAND
If a 'command=' authorized_keys option was used, the original command is specified
in this variable. If a shell was requested this is set to an empty value.
.TP
.B SSH_AUTH_SOCK
Set to a forwarded ssh-agent connection.
.SH NOTES
Dropbear only supports SSH protocol version 2.
.SH AUTHOR
Matt Johnston (matt@ucc.asn.au).
.br
Gerrit Pape (pape@smarden.org) wrote this manual page.
.SH SEE ALSO
dropbearkey(8), dbclient(1)
dropbearkey(1), dbclient(1), dropbearconvert(1)
.P
http://matt.ucc.asn.au/dropbear/dropbear.html
https://matt.ucc.asn.au/dropbear/dropbear.html

50
dropbearconvert.1 Normal file
View File

@@ -0,0 +1,50 @@
.TH dropbearconvert 1
.SH NAME
dropbearconvert \- convert between Dropbear and OpenSSH private key formats
.SH SYNOPSIS
.B dropbearconvert
.I input_type
.I output_type
.I input_file
.I output_file
.SH DESCRIPTION
.B Dropbear
and
.B OpenSSH
SSH implementations have different private key formats.
.B dropbearconvert
can convert between the two.
.P
Dropbear uses the same SSH public key format as OpenSSH, it can be extracted
from a private key by using
.B dropbearkey \-y
.P
Encrypted private keys are not supported, use ssh-keygen(1) to decrypt them
first.
.SH ARGUMENTS
.TP
.I input_type
Either
.I dropbear
or
.I openssh
.TP
.I output_type
Either
.I dropbear
or
.I openssh
.TP
.I input_file
An existing Dropbear or OpenSSH private key file
.TP
.I output_file
The path to write the converted private key file. For client authentication ~/.ssh/id_dropbear is loaded by default
.SH EXAMPLE
# dropbearconvert openssh dropbear ~/.ssh/id_rsa ~/.ssh/id_dropbear
.SH AUTHOR
Matt Johnston (matt@ucc.asn.au).
.SH SEE ALSO
dropbearkey(1), ssh-keygen(1)
.P
https://matt.ucc.asn.au/dropbear/dropbear.html

View File

@@ -28,6 +28,8 @@
#include "buffer.h"
#include "dbutil.h"
#include "keyimport.h"
#include "crypto_desc.h"
#include "dbrandom.h"
static int do_convert(int intype, const char* infile, int outtype,
@@ -62,6 +64,9 @@ int main(int argc, char ** argv) {
const char* infile;
const char* outfile;
crypto_init();
seedrandom();
#ifdef DEBUG_TRACE
/* It's hard for it to get in the way _too_ much */
debug_trace = 1;
@@ -111,7 +116,7 @@ static int do_convert(int intype, const char* infile, int outtype,
const char* outfile) {
sign_key * key = NULL;
char * keytype = NULL;
const char * keytype = NULL;
int ret = 1;
key = import_read(infile, NULL, intype);
@@ -121,16 +126,7 @@ static int do_convert(int intype, const char* infile, int outtype,
goto out;
}
#ifdef DROPBEAR_RSA
if (key->rsakey != NULL) {
keytype = "RSA";
}
#endif
#ifdef DROPBEAR_DSS
if (key->dsskey != NULL) {
keytype = "DSS";
}
#endif
keytype = signkey_name_from_type(key->type, NULL);
fprintf(stderr, "Key is a %s key\n", keytype);

60
dropbearkey.1 Normal file
View File

@@ -0,0 +1,60 @@
.TH dropbearkey 1
.SH NAME
dropbearkey \- create private keys for the use with dropbear(8) or dbclient(1)
.SH SYNOPSIS
.B dropbearkey
\-t
.I type
\-f
.I file
[\-s
.IR bits ]
[\-y]
.SH DESCRIPTION
.B dropbearkey
generates a
\fIRSA\fR, \fIDSS\fR, or \fIECDSA\fR
format SSH private key, and saves it to a file for the use with the
Dropbear client or server.
Note that
some SSH implementations
use the term "DSA" rather than "DSS", they mean the same thing.
.SH OPTIONS
.TP
.B \-t \fItype
Type of key to generate.
Must be one of
.I rsa
.I ecdsa
or
.IR dss .
.TP
.B \-f \fIfile
Write the secret key to the file
\fIfile\fR. For client authentication ~/.ssh/id_dropbear is loaded by default
.TP
.B \-s \fIbits
Set the key size to
.I bits
bits, should be multiple of 8 (optional).
.TP
.B \-y
Just print the publickey and fingerprint for the private key in \fIfile\fR.
.SH NOTES
The program dropbearconvert(1) can be used to convert between Dropbear and OpenSSH key formats.
.P
Dropbear does not support encrypted keys.
.SH EXAMPLE
generate a host-key:
# dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
extract a public key suitable for authorized_keys from private key:
# dropbearkey -y -f id_rsa | grep "^ssh-rsa " >> authorized_keys
.SH AUTHOR
Matt Johnston (matt@ucc.asn.au).
.br
Gerrit Pape (pape@smarden.org) wrote this manual page.
.SH SEE ALSO
dropbear(8), dbclient(1), dropbearconvert(1)
.P
https://matt.ucc.asn.au/dropbear/dropbear.html

View File

@@ -1,47 +0,0 @@
.TH dropbearkey 8
.SH NAME
dropbearkey \- create private keys for the use with dropbear(8)
.SH SYNOPSIS
.B dropbearkey
\-t
.I type
\-f
.I file
[\-s
.IR bits ]
.SH DESCRIPTION
.B dropbearkey
generates a type
.I rsa
or
.I dss
SSH private key, and saves it to a file for the use with the
.BR dropbear (8)
SSH 2 server.
.SH OPTIONS
.TP
.B \-t \fItype
Type of key to generate.
Must be one of
.I rsa
or
.IR dss .
.TP
.B \-f \fIfile
Write the secret key to the file
.IR file .
.TP
.B \-s \fIbits
Set the key size to
.I bits
bits, should be multiple of 8 (optional).
.SH EXAMPLE
# dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
.SH AUTHOR
Matt Johnston (matt@ucc.asn.au).
.br
Gerrit Pape (pape@smarden.org) wrote this manual page.
.SH SEE ALSO
dropbear(8), dbclient(1)
.P
http://matt.ucc.asn.au/dropbear/dropbear.html

View File

@@ -23,7 +23,7 @@
* SOFTWARE. */
/* The format of the keyfiles is basically a raw dump of the buffer. Data types
* are specified in the transport draft - string is a 32-bit len then the
* are specified in the transport rfc 4253 - string is a 32-bit len then the
* non-null-terminated string, mp_int is a 32-bit len then the bignum data.
* The actual functions are buf_put_rsa_priv_key() and buf_put_dss_priv_key()
@@ -51,21 +51,21 @@
#include "genrsa.h"
#include "gendss.h"
#include "ecdsa.h"
#include "crypto_desc.h"
#include "dbrandom.h"
#include "gensignkey.h"
static void printhelp(char * progname);
#define RSA_SIZE (1024/8) /* 1024 bit */
#define DSS_SIZE (1024/8) /* 1024 bit */
static void buf_writefile(buffer * buf, const char * filename);
static void printpubkey(sign_key * key, int keytype);
static void justprintpub(const char* filename);
static int printpubfile(const char* filename);
/* Print a help message */
static void printhelp(char * progname) {
fprintf(stderr, "Usage: %s -t <type> -f <filename> [-s bits]\n"
"Options are:\n"
"-t type Type of key to generate. One of:\n"
#ifdef DROPBEAR_RSA
" rsa\n"
@@ -73,8 +73,28 @@ static void printhelp(char * progname) {
#ifdef DROPBEAR_DSS
" dss\n"
#endif
"-f filename Use filename for the secret key\n"
#ifdef DROPBEAR_ECDSA
" ecdsa\n"
#endif
"-f filename Use filename for the secret key.\n"
" ~/.ssh/id_dropbear is recommended for client keys.\n"
"-s bits Key size in bits, should be a multiple of 8 (optional)\n"
#ifdef DROPBEAR_DSS
" DSS has a fixed size of 1024 bits\n"
#endif
#ifdef DROPBEAR_ECDSA
" ECDSA has sizes "
#ifdef DROPBEAR_ECC_256
"256 "
#endif
#ifdef DROPBEAR_ECC_384
"384 "
#endif
#ifdef DROPBEAR_ECC_521
"521 "
#endif
"\n"
#endif
"-y Just print the publickey and fingerprint for the\n private key in <filename>.\n"
#ifdef DEBUG_TRACE
"-v verbose\n"
@@ -82,6 +102,30 @@ static void printhelp(char * progname) {
,progname);
}
/* fails fatally */
static void check_signkey_bits(enum signkey_type type, int bits)
{
switch (type) {
#ifdef DROPBEAR_RSA
case DROPBEAR_SIGNKEY_RSA:
if (bits < 512 || bits > 4096 || (bits % 8 != 0)) {
dropbear_exit("Bits must satisfy 512 <= bits <= 4096, and be a"
" multiple of 8\n");
}
break;
#endif
#ifdef DROPEAR_DSS
case DROPBEAR_SIGNKEY_DSS:
if (bits != 1024) {
dropbear_exit("DSS keys have a fixed size of 1024 bits\n");
exit(EXIT_FAILURE);
}
#endif
default:
(void)0; /* quiet, compiler. ecdsa handles checks itself */
}
}
#if defined(DBMULTI_dropbearkey) || !defined(DROPBEAR_MULTI)
#if defined(DBMULTI_dropbearkey) && defined(DROPBEAR_MULTI)
int dropbearkey_main(int argc, char ** argv) {
@@ -91,16 +135,16 @@ int main(int argc, char ** argv) {
int i;
char ** next = 0;
sign_key *key = NULL;
buffer *buf = NULL;
char * filename = NULL;
int keytype = -1;
enum signkey_type keytype = DROPBEAR_SIGNKEY_NONE;
char * typetext = NULL;
char * sizetext = NULL;
unsigned int bits;
unsigned int keysize;
unsigned int bits = 0;
int printpub = 0;
crypto_init();
seedrandom();
/* get the commandline options */
for (i = 1; i < argc; i++) {
if (argv[i] == NULL) {
@@ -151,8 +195,8 @@ int main(int argc, char ** argv) {
}
if (printpub) {
justprintpub(filename);
/* Not reached */
int ret = printpubfile(filename);
exit(ret);
}
/* check/parse args */
@@ -162,21 +206,26 @@ int main(int argc, char ** argv) {
exit(EXIT_FAILURE);
}
if (strlen(typetext) == 3) {
#ifdef DROPBEAR_RSA
if (strncmp(typetext, "rsa", 3) == 0) {
keytype = DROPBEAR_SIGNKEY_RSA;
TRACE(("type is rsa"))
}
if (strcmp(typetext, "rsa") == 0)
{
keytype = DROPBEAR_SIGNKEY_RSA;
}
#endif
#ifdef DROPBEAR_DSS
if (strncmp(typetext, "dss", 3) == 0) {
keytype = DROPBEAR_SIGNKEY_DSS;
TRACE(("type is dss"))
}
#endif
if (strcmp(typetext, "dss") == 0)
{
keytype = DROPBEAR_SIGNKEY_DSS;
}
if (keytype == -1) {
#endif
#ifdef DROPBEAR_ECDSA
if (strcmp(typetext, "ecdsa") == 0)
{
keytype = DROPBEAR_SIGNKEY_ECDSA_KEYGEN;
}
#endif
if (keytype == DROPBEAR_SIGNKEY_NONE) {
fprintf(stderr, "Unknown key type '%s'\n", typetext);
printhelp(argv[0]);
exit(EXIT_FAILURE);
@@ -187,73 +236,27 @@ int main(int argc, char ** argv) {
fprintf(stderr, "Bits must be an integer\n");
exit(EXIT_FAILURE);
}
if (bits < 512 || bits > 4096 || (bits % 8 != 0)) {
fprintf(stderr, "Bits must satisfy 512 <= bits <= 4096, and be a"
" multiple of 8\n");
exit(EXIT_FAILURE);
}
keysize = bits / 8;
} else {
if (keytype == DROPBEAR_SIGNKEY_DSS) {
keysize = DSS_SIZE;
} else if (keytype == DROPBEAR_SIGNKEY_RSA) {
keysize = RSA_SIZE;
} else {
exit(EXIT_FAILURE); /* not reached */
}
check_signkey_bits(keytype, bits);;
}
fprintf(stderr, "Will output %d bit %s secret key to '%s'\n", keysize*8,
typetext, filename);
/* don't want the file readable by others */
umask(077);
/* now we can generate the key */
key = new_sign_key();
fprintf(stderr, "Generating key, this may take a while...\n");
switch(keytype) {
#ifdef DROPBEAR_RSA
case DROPBEAR_SIGNKEY_RSA:
key->rsakey = gen_rsa_priv_key(keysize); /* 128 bytes = 1024 bit */
break;
#endif
#ifdef DROPBEAR_DSS
case DROPBEAR_SIGNKEY_DSS:
key->dsskey = gen_dss_priv_key(keysize); /* 128 bytes = 1024 bit */
break;
#endif
default:
fprintf(stderr, "Internal error, bad key type\n");
exit(EXIT_FAILURE);
if (signkey_generate(keytype, bits, filename) == DROPBEAR_FAILURE)
{
dropbear_exit("Failed to generate key.\n");
}
buf = buf_new(MAX_PRIVKEY_SIZE);
buf_put_priv_key(buf, key, keytype);
buf_setpos(buf, 0);
buf_writefile(buf, filename);
buf_burn(buf);
buf_free(buf);
printpubkey(key, keytype);
sign_key_free(key);
printpubfile(filename);
return EXIT_SUCCESS;
}
#endif
static void justprintpub(const char* filename) {
static int printpubfile(const char* filename) {
buffer *buf = NULL;
sign_key *key = NULL;
int keytype;
enum signkey_type keytype;
int ret;
int err = DROPBEAR_FAILURE;
@@ -287,7 +290,7 @@ out:
sign_key_free(key);
key = NULL;
}
exit(err);
return err;
}
static void printpubkey(sign_key * key, int keytype) {
@@ -316,7 +319,7 @@ static void printpubkey(sign_key * key, int keytype) {
fprintf(stderr, "base64 failed");
}
typestring = signkey_name_from_type(keytype, &err);
typestring = signkey_name_from_type(keytype, NULL);
fp = sign_key_fingerprint(buf_getptr(buf, len), len);
@@ -336,35 +339,3 @@ static void printpubkey(sign_key * key, int keytype) {
m_free(fp);
buf_free(buf);
}
/* Write a buffer to a file specified, failing if the file exists */
static void buf_writefile(buffer * buf, const char * filename) {
int fd;
int len;
fd = open(filename, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
if (fd < 0) {
fprintf(stderr, "Couldn't create new file %s\n", filename);
perror("Reason");
buf_burn(buf);
exit(EXIT_FAILURE);
}
/* write the file now */
while (buf->pos != buf->len) {
len = write(fd, buf_getptr(buf, buf->len - buf->pos),
buf->len - buf->pos);
if (errno == EINTR) {
continue;
}
if (len <= 0) {
fprintf(stderr, "Failed writing file '%s'\n",filename);
perror("Reason");
exit(EXIT_FAILURE);
}
buf_incrpos(buf, len);
}
close(fd);
}

129
dss.c
View File

@@ -28,7 +28,7 @@
#include "dss.h"
#include "buffer.h"
#include "ssh.h"
#include "random.h"
#include "dbrandom.h"
/* Handle DSS (Digital Signature Standard), aka DSA (D.S. Algorithm),
* operations, such as key reading, signing, verification. Key generation
@@ -43,15 +43,11 @@
* The key will have the same format as buf_put_dss_key.
* These should be freed with dss_key_free.
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
int buf_get_dss_pub_key(buffer* buf, dss_key *key) {
int buf_get_dss_pub_key(buffer* buf, dropbear_dss_key *key) {
TRACE(("enter buf_get_dss_pub_key"))
dropbear_assert(key != NULL);
key->p = m_malloc(sizeof(mp_int));
key->q = m_malloc(sizeof(mp_int));
key->g = m_malloc(sizeof(mp_int));
key->y = m_malloc(sizeof(mp_int));
m_mp_init_multi(key->p, key->q, key->g, key->y, NULL);
m_mp_alloc_init_multi(&key->p, &key->q, &key->g, &key->y, NULL);
key->x = NULL;
buf_incrpos(buf, 4+SSH_SIGNKEY_DSS_LEN); /* int + "ssh-dss" */
@@ -76,7 +72,7 @@ int buf_get_dss_pub_key(buffer* buf, dss_key *key) {
/* Same as buf_get_dss_pub_key, but reads a private "x" key at the end.
* Loads a private dss key from a buffer
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
int buf_get_dss_priv_key(buffer* buf, dss_key *key) {
int buf_get_dss_priv_key(buffer* buf, dropbear_dss_key *key) {
int ret = DROPBEAR_FAILURE;
@@ -87,8 +83,7 @@ int buf_get_dss_priv_key(buffer* buf, dss_key *key) {
return DROPBEAR_FAILURE;
}
key->x = m_malloc(sizeof(mp_int));
m_mp_init(key->x);
m_mp_alloc_init_multi(&key->x, NULL);
ret = buf_getmpint(buf, key->x);
if (ret == DROPBEAR_FAILURE) {
m_free(key->x);
@@ -99,11 +94,11 @@ int buf_get_dss_priv_key(buffer* buf, dss_key *key) {
/* Clear and free the memory used by a public or private key */
void dss_key_free(dss_key *key) {
void dss_key_free(dropbear_dss_key *key) {
TRACE(("enter dsa_key_free"))
TRACE2(("enter dsa_key_free"))
if (key == NULL) {
TRACE(("enter dsa_key_free: key == NULL"))
TRACE2(("enter dsa_key_free: key == NULL"))
return;
}
if (key->p) {
@@ -127,7 +122,7 @@ void dss_key_free(dss_key *key) {
m_free(key->x);
}
m_free(key);
TRACE(("leave dsa_key_free"))
TRACE2(("leave dsa_key_free"))
}
/* put the dss public key into the buffer in the required format:
@@ -138,7 +133,7 @@ void dss_key_free(dss_key *key) {
* mpint g
* mpint y
*/
void buf_put_dss_pub_key(buffer* buf, dss_key *key) {
void buf_put_dss_pub_key(buffer* buf, dropbear_dss_key *key) {
dropbear_assert(key != NULL);
buf_putstring(buf, SSH_SIGNKEY_DSS, SSH_SIGNKEY_DSS_LEN);
@@ -150,7 +145,7 @@ void buf_put_dss_pub_key(buffer* buf, dss_key *key) {
}
/* Same as buf_put_dss_pub_key, but with the private "x" key appended */
void buf_put_dss_priv_key(buffer* buf, dss_key *key) {
void buf_put_dss_priv_key(buffer* buf, dropbear_dss_key *key) {
dropbear_assert(key != NULL);
buf_put_dss_pub_key(buf, key);
@@ -161,9 +156,7 @@ void buf_put_dss_priv_key(buffer* buf, dss_key *key) {
#ifdef DROPBEAR_SIGNKEY_VERIFY
/* Verify a DSS signature (in buf) made on data by the key given.
* returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data,
unsigned int len) {
int buf_dss_verify(buffer* buf, dropbear_dss_key *key, buffer *data_buf) {
unsigned char msghash[SHA1_HASH_SIZE];
hash_state hs;
int ret = DROPBEAR_FAILURE;
@@ -172,7 +165,7 @@ int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data,
DEF_MP_INT(val3);
DEF_MP_INT(val4);
char * string = NULL;
int stringlen;
unsigned int stringlen;
TRACE(("enter buf_dss_verify"))
dropbear_assert(key != NULL);
@@ -187,13 +180,13 @@ int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data,
/* hash the data */
sha1_init(&hs);
sha1_process(&hs, data, len);
sha1_process(&hs, data_buf->data, data_buf->len);
sha1_done(&hs, msghash);
/* create the signature - s' and r' are the received signatures in buf */
/* w = (s')-1 mod q */
/* let val1 = s' */
bytes_to_mp(&val1, &string[SHA1_HASH_SIZE], SHA1_HASH_SIZE);
bytes_to_mp(&val1, (const unsigned char*) &string[SHA1_HASH_SIZE], SHA1_HASH_SIZE);
if (mp_cmp(&val1, key->q) != MP_LT) {
TRACE(("verify failed, s' >= q"))
@@ -215,7 +208,7 @@ int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data,
/* u2 = ((r')w) mod q */
/* let val1 = r' */
bytes_to_mp(&val1, &string[0], SHA1_HASH_SIZE);
bytes_to_mp(&val1, (const unsigned char*) &string[0], SHA1_HASH_SIZE);
if (mp_cmp(&val1, key->q) != MP_LT) {
TRACE(("verify failed, r' >= q"))
goto out;
@@ -258,52 +251,12 @@ out:
}
#endif /* DROPBEAR_SIGNKEY_VERIFY */
#ifdef DSS_PROTOK
/* convert an unsigned mp into an array of bytes, malloced.
* This array must be freed after use, len contains the length of the array,
* if len != NULL */
static unsigned char* mptobytes(mp_int *mp, int *len) {
unsigned char* ret;
int size;
size = mp_unsigned_bin_size(mp);
ret = m_malloc(size);
if (mp_to_unsigned_bin(mp, ret) != MP_OKAY) {
dropbear_exit("mem alloc error");
}
if (len != NULL) {
*len = size;
}
return ret;
}
#endif
/* Sign the data presented with key, writing the signature contents
* to the buffer
*
* When DSS_PROTOK is #defined:
* The alternate k generation method is based on the method used in PuTTY.
* In particular to avoid being vulnerable to attacks using flaws in random
* generation of k, we use the following:
*
* proto_k = SHA512 ( SHA512(x) || SHA160(message) )
* k = proto_k mod q
*
* Now we aren't relying on the random number generation to protect the private
* key x, which is a long term secret */
void buf_put_dss_sign(buffer* buf, dss_key *key, const unsigned char* data,
unsigned int len) {
* to the buffer */
void buf_put_dss_sign(buffer* buf, dropbear_dss_key *key, buffer *data_buf) {
unsigned char msghash[SHA1_HASH_SIZE];
unsigned int writelen;
unsigned int i;
#ifdef DSS_PROTOK
unsigned char privkeyhash[SHA512_HASH_SIZE];
unsigned char *privkeytmp;
unsigned char proto_k[SHA512_HASH_SIZE];
DEF_MP_INT(dss_protok);
#endif
DEF_MP_INT(dss_k);
DEF_MP_INT(dss_m);
DEF_MP_INT(dss_temp1);
@@ -317,68 +270,44 @@ void buf_put_dss_sign(buffer* buf, dss_key *key, const unsigned char* data,
/* hash the data */
sha1_init(&hs);
sha1_process(&hs, data, len);
sha1_process(&hs, data_buf->data, data_buf->len);
sha1_done(&hs, msghash);
m_mp_init_multi(&dss_k, &dss_temp1, &dss_temp2, &dss_r, &dss_s,
&dss_m, NULL);
#ifdef DSS_PROTOK
/* hash the privkey */
privkeytmp = mptobytes(key->x, &i);
sha512_init(&hs);
sha512_process(&hs, "the quick brown fox jumped over the lazy dog", 44);
sha512_process(&hs, privkeytmp, i);
sha512_done(&hs, privkeyhash);
m_burn(privkeytmp, i);
m_free(privkeytmp);
/* calculate proto_k */
sha512_init(&hs);
sha512_process(&hs, privkeyhash, SHA512_HASH_SIZE);
sha512_process(&hs, msghash, SHA1_HASH_SIZE);
sha512_done(&hs, proto_k);
/* generate k */
m_mp_init(&dss_protok);
bytes_to_mp(&dss_protok, proto_k, SHA512_HASH_SIZE);
if (mp_mod(&dss_protok, key->q, &dss_k) != MP_OKAY) {
dropbear_exit("dss error");
}
mp_clear(&dss_protok);
m_burn(proto_k, SHA512_HASH_SIZE);
#else /* DSS_PROTOK not defined*/
/* the random number generator's input has included the private key which
* avoids DSS's problem of private key exposure due to low entropy */
gen_random_mpint(key->q, &dss_k);
#endif
/* now generate the actual signature */
bytes_to_mp(&dss_m, msghash, SHA1_HASH_SIZE);
/* g^k mod p */
if (mp_exptmod(key->g, &dss_k, key->p, &dss_temp1) != MP_OKAY) {
dropbear_exit("dss error");
dropbear_exit("DSS error");
}
/* r = (g^k mod p) mod q */
if (mp_mod(&dss_temp1, key->q, &dss_r) != MP_OKAY) {
dropbear_exit("dss error");
dropbear_exit("DSS error");
}
/* x*r mod q */
if (mp_mulmod(&dss_r, key->x, key->q, &dss_temp1) != MP_OKAY) {
dropbear_exit("dss error");
dropbear_exit("DSS error");
}
/* (SHA1(M) + xr) mod q) */
if (mp_addmod(&dss_m, &dss_temp1, key->q, &dss_temp2) != MP_OKAY) {
dropbear_exit("dss error");
dropbear_exit("DSS error");
}
/* (k^-1) mod q */
if (mp_invmod(&dss_k, key->q, &dss_temp1) != MP_OKAY) {
dropbear_exit("dss error");
dropbear_exit("DSS error");
}
/* s = (k^-1(SHA1(M) + xr)) mod q */
if (mp_mulmod(&dss_temp1, &dss_temp2, key->q, &dss_s) != MP_OKAY) {
dropbear_exit("dss error");
dropbear_exit("DSS error");
}
buf_putstring(buf, SSH_SIGNKEY_DSS, SSH_SIGNKEY_DSS_LEN);
@@ -392,7 +321,7 @@ void buf_put_dss_sign(buffer* buf, dss_key *key, const unsigned char* data,
}
if (mp_to_unsigned_bin(&dss_r, buf_getwriteptr(buf, writelen))
!= MP_OKAY) {
dropbear_exit("dss error");
dropbear_exit("DSS error");
}
mp_clear(&dss_r);
buf_incrwritepos(buf, writelen);
@@ -405,7 +334,7 @@ void buf_put_dss_sign(buffer* buf, dss_key *key, const unsigned char* data,
}
if (mp_to_unsigned_bin(&dss_s, buf_getwriteptr(buf, writelen))
!= MP_OKAY) {
dropbear_exit("dss error");
dropbear_exit("DSS error");
}
mp_clear(&dss_s);
buf_incrwritepos(buf, writelen);

31
dss.h
View File

@@ -22,40 +22,35 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#ifndef _DSS_H_
#define _DSS_H_
#ifndef DROPBEAR_DSS_H_
#define DROPBEAR_DSS_H_
#include "includes.h"
#include "buffer.h"
#ifdef DROPBEAR_DSS
#define DSS_SIGNATURE_SIZE 4+SSH_SIGNKEY_DSS_LEN+4+2*SHA1_HASH_SIZE
struct DSS_key {
typedef struct {
mp_int* p;
mp_int* q;
mp_int* g;
mp_int* y;
/* x is the private part */
mp_int* x;
};
} dropbear_dss_key;
typedef struct DSS_key dss_key;
void buf_put_dss_sign(buffer* buf, dss_key *key, const unsigned char* data,
unsigned int len);
void buf_put_dss_sign(buffer* buf, dropbear_dss_key *key, buffer *data_buf);
#ifdef DROPBEAR_SIGNKEY_VERIFY
int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data,
unsigned int len);
int buf_dss_verify(buffer* buf, dropbear_dss_key *key, buffer *data_buf);
#endif
int buf_get_dss_pub_key(buffer* buf, dss_key *key);
int buf_get_dss_priv_key(buffer* buf, dss_key *key);
void buf_put_dss_pub_key(buffer* buf, dss_key *key);
void buf_put_dss_priv_key(buffer* buf, dss_key *key);
void dss_key_free(dss_key *key);
int buf_get_dss_pub_key(buffer* buf, dropbear_dss_key *key);
int buf_get_dss_priv_key(buffer* buf, dropbear_dss_key *key);
void buf_put_dss_pub_key(buffer* buf, dropbear_dss_key *key);
void buf_put_dss_priv_key(buffer* buf, dropbear_dss_key *key);
void dss_key_free(dropbear_dss_key *key);
#endif /* DROPBEAR_DSS */
#endif /* _DSS_H_ */
#endif /* DROPBEAR_DSS_H_ */

270
ecc.c Normal file
View File

@@ -0,0 +1,270 @@
#include "includes.h"
#include "options.h"
#include "ecc.h"
#include "dbutil.h"
#include "bignum.h"
#ifdef DROPBEAR_ECC
/* .dp members are filled out by dropbear_ecc_fill_dp() at startup */
#ifdef DROPBEAR_ECC_256
struct dropbear_ecc_curve ecc_curve_nistp256 = {
32, /* .ltc_size */
NULL, /* .dp */
&sha256_desc, /* .hash_desc */
"nistp256" /* .name */
};
#endif
#ifdef DROPBEAR_ECC_384
struct dropbear_ecc_curve ecc_curve_nistp384 = {
48, /* .ltc_size */
NULL, /* .dp */
&sha384_desc, /* .hash_desc */
"nistp384" /* .name */
};
#endif
#ifdef DROPBEAR_ECC_521
struct dropbear_ecc_curve ecc_curve_nistp521 = {
66, /* .ltc_size */
NULL, /* .dp */
&sha512_desc, /* .hash_desc */
"nistp521" /* .name */
};
#endif
struct dropbear_ecc_curve *dropbear_ecc_curves[] = {
#ifdef DROPBEAR_ECC_256
&ecc_curve_nistp256,
#endif
#ifdef DROPBEAR_ECC_384
&ecc_curve_nistp384,
#endif
#ifdef DROPBEAR_ECC_521
&ecc_curve_nistp521,
#endif
NULL
};
void dropbear_ecc_fill_dp() {
struct dropbear_ecc_curve **curve;
/* libtomcrypt guarantees they're ordered by size */
const ltc_ecc_set_type *dp = ltc_ecc_sets;
for (curve = dropbear_ecc_curves; *curve; curve++) {
for (;dp->size > 0; dp++) {
if (dp->size == (*curve)->ltc_size) {
(*curve)->dp = dp;
break;
}
}
if (!(*curve)->dp) {
dropbear_exit("Missing ECC params %s", (*curve)->name);
}
}
}
struct dropbear_ecc_curve* curve_for_dp(const ltc_ecc_set_type *dp) {
struct dropbear_ecc_curve **curve = NULL;
for (curve = dropbear_ecc_curves; *curve; curve++) {
if ((*curve)->dp == dp) {
break;
}
}
assert(*curve);
return *curve;
}
ecc_key * new_ecc_key(void) {
ecc_key *key = m_malloc(sizeof(*key));
m_mp_alloc_init_multi((mp_int**)&key->pubkey.x, (mp_int**)&key->pubkey.y,
(mp_int**)&key->pubkey.z, (mp_int**)&key->k, NULL);
return key;
}
/* Copied from libtomcrypt ecc_import.c (version there is static), modified
for different mp_int pointer without LTC_SOURCE */
static int ecc_is_point(ecc_key *key)
{
mp_int *prime, *b, *t1, *t2;
int err;
m_mp_alloc_init_multi(&prime, &b, &t1, &t2, NULL);
/* load prime and b */
if ((err = mp_read_radix(prime, key->dp->prime, 16)) != CRYPT_OK) { goto error; }
if ((err = mp_read_radix(b, key->dp->B, 16)) != CRYPT_OK) { goto error; }
/* compute y^2 */
if ((err = mp_sqr(key->pubkey.y, t1)) != CRYPT_OK) { goto error; }
/* compute x^3 */
if ((err = mp_sqr(key->pubkey.x, t2)) != CRYPT_OK) { goto error; }
if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) { goto error; }
if ((err = mp_mul(key->pubkey.x, t2, t2)) != CRYPT_OK) { goto error; }
/* compute y^2 - x^3 */
if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) { goto error; }
/* compute y^2 - x^3 + 3x */
if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; }
if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; }
if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; }
if ((err = mp_mod(t1, prime, t1)) != CRYPT_OK) { goto error; }
while (mp_cmp_d(t1, 0) == LTC_MP_LT) {
if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) { goto error; }
}
while (mp_cmp(t1, prime) != LTC_MP_LT) {
if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) { goto error; }
}
/* compare to b */
if (mp_cmp(t1, b) != LTC_MP_EQ) {
err = CRYPT_INVALID_PACKET;
} else {
err = CRYPT_OK;
}
error:
mp_clear_multi(prime, b, t1, t2, NULL);
m_free(prime);
m_free(b);
m_free(t1);
m_free(t2);
return err;
}
/* For the "ephemeral public key octet string" in ECDH (rfc5656 section 4) */
void buf_put_ecc_raw_pubkey_string(buffer *buf, ecc_key *key) {
unsigned long len = key->dp->size*2 + 1;
int err;
buf_putint(buf, len);
err = ecc_ansi_x963_export(key, buf_getwriteptr(buf, len), &len);
if (err != CRYPT_OK) {
dropbear_exit("ECC error");
}
buf_incrwritepos(buf, len);
}
/* For the "ephemeral public key octet string" in ECDH (rfc5656 section 4) */
ecc_key * buf_get_ecc_raw_pubkey(buffer *buf, const struct dropbear_ecc_curve *curve) {
ecc_key *key = NULL;
int ret = DROPBEAR_FAILURE;
const unsigned int size = curve->dp->size;
unsigned char first;
TRACE(("enter buf_get_ecc_raw_pubkey"))
buf_setpos(buf, 0);
first = buf_getbyte(buf);
if (first == 2 || first == 3) {
dropbear_log(LOG_WARNING, "Dropbear doesn't support ECC point compression");
return NULL;
}
if (first != 4 || buf->len != 1+2*size) {
TRACE(("leave, wrong size"))
return NULL;
}
key = new_ecc_key();
key->dp = curve->dp;
if (mp_read_unsigned_bin(key->pubkey.x, buf_getptr(buf, size), size) != MP_OKAY) {
TRACE(("failed to read x"))
goto out;
}
buf_incrpos(buf, size);
if (mp_read_unsigned_bin(key->pubkey.y, buf_getptr(buf, size), size) != MP_OKAY) {
TRACE(("failed to read y"))
goto out;
}
buf_incrpos(buf, size);
mp_set(key->pubkey.z, 1);
if (ecc_is_point(key) != CRYPT_OK) {
TRACE(("failed, not a point"))
goto out;
}
/* SEC1 3.2.3.1 Check that Q != 0 */
if (mp_cmp_d(key->pubkey.x, 0) == LTC_MP_EQ) {
TRACE(("failed, x == 0"))
goto out;
}
if (mp_cmp_d(key->pubkey.y, 0) == LTC_MP_EQ) {
TRACE(("failed, y == 0"))
goto out;
}
ret = DROPBEAR_SUCCESS;
out:
if (ret == DROPBEAR_FAILURE) {
if (key) {
ecc_free(key);
m_free(key);
key = NULL;
}
}
return key;
}
/* a modified version of libtomcrypt's "ecc_shared_secret" to output
a mp_int instead. */
mp_int * dropbear_ecc_shared_secret(ecc_key *public_key, ecc_key *private_key)
{
ecc_point *result = NULL;
mp_int *prime = NULL, *shared_secret = NULL;
int err = DROPBEAR_FAILURE;
/* type valid? */
if (private_key->type != PK_PRIVATE) {
goto done;
}
if (private_key->dp != public_key->dp) {
goto done;
}
/* make new point */
result = ltc_ecc_new_point();
if (result == NULL) {
goto done;
}
prime = m_malloc(sizeof(*prime));
m_mp_init(prime);
if (mp_read_radix(prime, (char *)private_key->dp->prime, 16) != CRYPT_OK) {
goto done;
}
if (ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, prime, 1) != CRYPT_OK) {
goto done;
}
err = DROPBEAR_SUCCESS;
done:
if (err == DROPBEAR_SUCCESS) {
shared_secret = m_malloc(sizeof(*shared_secret));
m_mp_init(shared_secret);
mp_copy(result->x, shared_secret);
}
if (prime) {
mp_clear(prime);
m_free(prime);
}
if (result)
{
ltc_ecc_del_point(result);
}
if (err == DROPBEAR_FAILURE) {
dropbear_exit("ECC error");
}
return shared_secret;
}
#endif

36
ecc.h Normal file
View File

@@ -0,0 +1,36 @@
#ifndef DROPBEAR_DROPBEAR_ECC_H
#define DROPBEAR_DROPBEAR_ECC_H
#include "includes.h"
#include "options.h"
#include "buffer.h"
#ifdef DROPBEAR_ECC
struct dropbear_ecc_curve {
int ltc_size; /* to match the byte sizes in ltc_ecc_sets[] */
const ltc_ecc_set_type *dp; /* curve domain parameters */
const struct ltc_hash_descriptor *hash_desc;
const char *name;
};
extern struct dropbear_ecc_curve ecc_curve_nistp256;
extern struct dropbear_ecc_curve ecc_curve_nistp384;
extern struct dropbear_ecc_curve ecc_curve_nistp521;
extern struct dropbear_ecc_curve *dropbear_ecc_curves[];
void dropbear_ecc_fill_dp(void);
struct dropbear_ecc_curve* curve_for_dp(const ltc_ecc_set_type *dp);
/* "pubkey" refers to a point, but LTC uses ecc_key structure for both public
and private keys */
void buf_put_ecc_raw_pubkey_string(buffer *buf, ecc_key *key);
ecc_key * buf_get_ecc_raw_pubkey(buffer *buf, const struct dropbear_ecc_curve *curve);
int buf_get_ecc_privkey_string(buffer *buf, ecc_key *key);
mp_int * dropbear_ecc_shared_secret(ecc_key *pub_key, ecc_key *priv_key);
#endif
#endif /* DROPBEAR_DROPBEAR_ECC_H */

421
ecdsa.c Normal file
View File

@@ -0,0 +1,421 @@
#include "options.h"
#include "includes.h"
#include "dbutil.h"
#include "crypto_desc.h"
#include "ecc.h"
#include "ecdsa.h"
#include "signkey.h"
#ifdef DROPBEAR_ECDSA
int signkey_is_ecdsa(enum signkey_type type)
{
return type == DROPBEAR_SIGNKEY_ECDSA_NISTP256
|| type == DROPBEAR_SIGNKEY_ECDSA_NISTP384
|| type == DROPBEAR_SIGNKEY_ECDSA_NISTP521;
}
enum signkey_type ecdsa_signkey_type(ecc_key * key) {
#ifdef DROPBEAR_ECC_256
if (key->dp == ecc_curve_nistp256.dp) {
return DROPBEAR_SIGNKEY_ECDSA_NISTP256;
}
#endif
#ifdef DROPBEAR_ECC_384
if (key->dp == ecc_curve_nistp384.dp) {
return DROPBEAR_SIGNKEY_ECDSA_NISTP384;
}
#endif
#ifdef DROPBEAR_ECC_521
if (key->dp == ecc_curve_nistp521.dp) {
return DROPBEAR_SIGNKEY_ECDSA_NISTP521;
}
#endif
return DROPBEAR_SIGNKEY_NONE;
}
ecc_key *gen_ecdsa_priv_key(unsigned int bit_size) {
const ltc_ecc_set_type *dp = NULL; /* curve domain parameters */
ecc_key *new_key = NULL;
switch (bit_size) {
#ifdef DROPBEAR_ECC_256
case 256:
dp = ecc_curve_nistp256.dp;
break;
#endif
#ifdef DROPBEAR_ECC_384
case 384:
dp = ecc_curve_nistp384.dp;
break;
#endif
#ifdef DROPBEAR_ECC_521
case 521:
dp = ecc_curve_nistp521.dp;
break;
#endif
}
if (!dp) {
dropbear_exit("Key size %d isn't valid. Try "
#ifdef DROPBEAR_ECC_256
"256 "
#endif
#ifdef DROPBEAR_ECC_384
"384 "
#endif
#ifdef DROPBEAR_ECC_521
"521 "
#endif
, bit_size);
}
new_key = m_malloc(sizeof(*new_key));
if (ecc_make_key_ex(NULL, dropbear_ltc_prng, new_key, dp) != CRYPT_OK) {
dropbear_exit("ECC error");
}
return new_key;
}
ecc_key *buf_get_ecdsa_pub_key(buffer* buf) {
unsigned char *key_ident = NULL, *identifier = NULL;
unsigned int key_ident_len, identifier_len;
buffer *q_buf = NULL;
struct dropbear_ecc_curve **curve;
ecc_key *new_key = NULL;
/* string "ecdsa-sha2-[identifier]" */
key_ident = (unsigned char*)buf_getstring(buf, &key_ident_len);
/* string "[identifier]" */
identifier = (unsigned char*)buf_getstring(buf, &identifier_len);
if (key_ident_len != identifier_len + strlen("ecdsa-sha2-")) {
TRACE(("Bad identifier lengths"))
goto out;
}
if (memcmp(&key_ident[strlen("ecdsa-sha2-")], identifier, identifier_len) != 0) {
TRACE(("mismatching identifiers"))
goto out;
}
for (curve = dropbear_ecc_curves; *curve; curve++) {
if (memcmp(identifier, (char*)(*curve)->name, strlen((char*)(*curve)->name)) == 0) {
break;
}
}
if (!*curve) {
TRACE(("couldn't match ecc curve"))
goto out;
}
/* string Q */
q_buf = buf_getstringbuf(buf);
new_key = buf_get_ecc_raw_pubkey(q_buf, *curve);
out:
m_free(key_ident);
m_free(identifier);
if (q_buf) {
buf_free(q_buf);
q_buf = NULL;
}
TRACE(("leave buf_get_ecdsa_pub_key"))
return new_key;
}
ecc_key *buf_get_ecdsa_priv_key(buffer *buf) {
ecc_key *new_key = NULL;
TRACE(("enter buf_get_ecdsa_priv_key"))
new_key = buf_get_ecdsa_pub_key(buf);
if (!new_key) {
return NULL;
}
if (buf_getmpint(buf, new_key->k) != DROPBEAR_SUCCESS) {
ecc_free(new_key);
m_free(new_key);
return NULL;
}
return new_key;
}
void buf_put_ecdsa_pub_key(buffer *buf, ecc_key *key) {
struct dropbear_ecc_curve *curve = NULL;
char key_ident[30];
curve = curve_for_dp(key->dp);
snprintf(key_ident, sizeof(key_ident), "ecdsa-sha2-%s", curve->name);
buf_putstring(buf, key_ident, strlen(key_ident));
buf_putstring(buf, curve->name, strlen(curve->name));
buf_put_ecc_raw_pubkey_string(buf, key);
}
void buf_put_ecdsa_priv_key(buffer *buf, ecc_key *key) {
buf_put_ecdsa_pub_key(buf, key);
buf_putmpint(buf, key->k);
}
void buf_put_ecdsa_sign(buffer *buf, ecc_key *key, buffer *data_buf) {
/* Based on libtomcrypt's ecc_sign_hash but without the asn1 */
int err = DROPBEAR_FAILURE;
struct dropbear_ecc_curve *curve = NULL;
hash_state hs;
unsigned char hash[64];
void *e = NULL, *p = NULL, *s = NULL, *r;
char key_ident[30];
buffer *sigbuf = NULL;
TRACE(("buf_put_ecdsa_sign"))
curve = curve_for_dp(key->dp);
if (ltc_init_multi(&r, &s, &p, &e, NULL) != CRYPT_OK) {
goto out;
}
curve->hash_desc->init(&hs);
curve->hash_desc->process(&hs, data_buf->data, data_buf->len);
curve->hash_desc->done(&hs, hash);
if (ltc_mp.unsigned_read(e, hash, curve->hash_desc->hashsize) != CRYPT_OK) {
goto out;
}
if (ltc_mp.read_radix(p, (char *)key->dp->order, 16) != CRYPT_OK) {
goto out;
}
for (;;) {
ecc_key R_key; /* ephemeral key */
if (ecc_make_key_ex(NULL, dropbear_ltc_prng, &R_key, key->dp) != CRYPT_OK) {
goto out;
}
if (ltc_mp.mpdiv(R_key.pubkey.x, p, NULL, r) != CRYPT_OK) {
goto out;
}
if (ltc_mp.compare_d(r, 0) == LTC_MP_EQ) {
/* try again */
ecc_free(&R_key);
continue;
}
/* k = 1/k */
if (ltc_mp.invmod(R_key.k, p, R_key.k) != CRYPT_OK) {
goto out;
}
/* s = xr */
if (ltc_mp.mulmod(key->k, r, p, s) != CRYPT_OK) {
goto out;
}
/* s = e + xr */
if (ltc_mp.add(e, s, s) != CRYPT_OK) {
goto out;
}
if (ltc_mp.mpdiv(s, p, NULL, s) != CRYPT_OK) {
goto out;
}
/* s = (e + xr)/k */
if (ltc_mp.mulmod(s, R_key.k, p, s) != CRYPT_OK) {
goto out;
}
ecc_free(&R_key);
if (ltc_mp.compare_d(s, 0) != LTC_MP_EQ) {
break;
}
}
snprintf(key_ident, sizeof(key_ident), "ecdsa-sha2-%s", curve->name);
buf_putstring(buf, key_ident, strlen(key_ident));
/* enough for nistp521 */
sigbuf = buf_new(200);
buf_putmpint(sigbuf, (mp_int*)r);
buf_putmpint(sigbuf, (mp_int*)s);
buf_putbufstring(buf, sigbuf);
err = DROPBEAR_SUCCESS;
out:
if (r && s && p && e) {
ltc_deinit_multi(r, s, p, e, NULL);
}
if (sigbuf) {
buf_free(sigbuf);
}
if (err == DROPBEAR_FAILURE) {
dropbear_exit("ECC error");
}
}
/* returns values in s and r
returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
static int buf_get_ecdsa_verify_params(buffer *buf,
void *r, void* s) {
int ret = DROPBEAR_FAILURE;
unsigned int sig_len;
unsigned int sig_pos;
sig_len = buf_getint(buf);
sig_pos = buf->pos;
if (buf_getmpint(buf, r) != DROPBEAR_SUCCESS) {
goto out;
}
if (buf_getmpint(buf, s) != DROPBEAR_SUCCESS) {
goto out;
}
if (buf->pos - sig_pos != sig_len) {
goto out;
}
ret = DROPBEAR_SUCCESS;
out:
return ret;
}
int buf_ecdsa_verify(buffer *buf, ecc_key *key, buffer *data_buf) {
/* Based on libtomcrypt's ecc_verify_hash but without the asn1 */
int ret = DROPBEAR_FAILURE;
hash_state hs;
struct dropbear_ecc_curve *curve = NULL;
unsigned char hash[64];
ecc_point *mG = NULL, *mQ = NULL;
void *r = NULL, *s = NULL, *v = NULL, *w = NULL, *u1 = NULL, *u2 = NULL,
*e = NULL, *p = NULL, *m = NULL;
void *mp = NULL;
/* verify
*
* w = s^-1 mod n
* u1 = xw
* u2 = rw
* X = u1*G + u2*Q
* v = X_x1 mod n
* accept if v == r
*/
TRACE(("buf_ecdsa_verify"))
curve = curve_for_dp(key->dp);
mG = ltc_ecc_new_point();
mQ = ltc_ecc_new_point();
if (ltc_init_multi(&r, &s, &v, &w, &u1, &u2, &p, &e, &m, NULL) != CRYPT_OK
|| !mG
|| !mQ) {
dropbear_exit("ECC error");
}
if (buf_get_ecdsa_verify_params(buf, r, s) != DROPBEAR_SUCCESS) {
goto out;
}
curve->hash_desc->init(&hs);
curve->hash_desc->process(&hs, data_buf->data, data_buf->len);
curve->hash_desc->done(&hs, hash);
if (ltc_mp.unsigned_read(e, hash, curve->hash_desc->hashsize) != CRYPT_OK) {
goto out;
}
/* get the order */
if (ltc_mp.read_radix(p, (char *)key->dp->order, 16) != CRYPT_OK) {
goto out;
}
/* get the modulus */
if (ltc_mp.read_radix(m, (char *)key->dp->prime, 16) != CRYPT_OK) {
goto out;
}
/* check for zero */
if (ltc_mp.compare_d(r, 0) == LTC_MP_EQ
|| ltc_mp.compare_d(s, 0) == LTC_MP_EQ
|| ltc_mp.compare(r, p) != LTC_MP_LT
|| ltc_mp.compare(s, p) != LTC_MP_LT) {
goto out;
}
/* w = s^-1 mod n */
if (ltc_mp.invmod(s, p, w) != CRYPT_OK) {
goto out;
}
/* u1 = ew */
if (ltc_mp.mulmod(e, w, p, u1) != CRYPT_OK) {
goto out;
}
/* u2 = rw */
if (ltc_mp.mulmod(r, w, p, u2) != CRYPT_OK) {
goto out;
}
/* find mG and mQ */
if (ltc_mp.read_radix(mG->x, (char *)key->dp->Gx, 16) != CRYPT_OK) {
goto out;
}
if (ltc_mp.read_radix(mG->y, (char *)key->dp->Gy, 16) != CRYPT_OK) {
goto out;
}
if (ltc_mp.set_int(mG->z, 1) != CRYPT_OK) {
goto out;
}
if (ltc_mp.copy(key->pubkey.x, mQ->x) != CRYPT_OK
|| ltc_mp.copy(key->pubkey.y, mQ->y) != CRYPT_OK
|| ltc_mp.copy(key->pubkey.z, mQ->z) != CRYPT_OK) {
goto out;
}
/* compute u1*mG + u2*mQ = mG */
if (ltc_mp.ecc_mul2add == NULL) {
if (ltc_mp.ecc_ptmul(u1, mG, mG, m, 0) != CRYPT_OK) {
goto out;
}
if (ltc_mp.ecc_ptmul(u2, mQ, mQ, m, 0) != CRYPT_OK) {
goto out;
}
/* find the montgomery mp */
if (ltc_mp.montgomery_setup(m, &mp) != CRYPT_OK) {
goto out;
}
/* add them */
if (ltc_mp.ecc_ptadd(mQ, mG, mG, m, mp) != CRYPT_OK) {
goto out;
}
/* reduce */
if (ltc_mp.ecc_map(mG, m, mp) != CRYPT_OK) {
goto out;
}
} else {
/* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */
if (ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, m) != CRYPT_OK) {
goto out;
}
}
/* v = X_x1 mod n */
if (ltc_mp.mpdiv(mG->x, p, NULL, v) != CRYPT_OK) {
goto out;
}
/* does v == r */
if (ltc_mp.compare(v, r) == LTC_MP_EQ) {
ret = DROPBEAR_SUCCESS;
}
out:
ltc_ecc_del_point(mG);
ltc_ecc_del_point(mQ);
ltc_deinit_multi(r, s, v, w, u1, u2, p, e, m, NULL);
if (mp != NULL) {
ltc_mp.montgomery_deinit(mp);
}
return ret;
}
#endif /* DROPBEAR_ECDSA */

35
ecdsa.h Normal file
View File

@@ -0,0 +1,35 @@
#ifndef DROPBEAR_ECDSA_H_
#define DROPBEAR_ECDSA_H_
#include "includes.h"
#include "buffer.h"
#include "signkey.h"
#ifdef DROPBEAR_ECDSA
/* Prefer the larger size - it's fast anyway */
#if defined(DROPBEAR_ECC_521)
#define ECDSA_DEFAULT_SIZE 521
#elif defined(DROPBEAR_ECC_384)
#define ECDSA_DEFAULT_SIZE 384
#elif defined(DROPBEAR_ECC_256)
#define ECDSA_DEFAULT_SIZE 256
#else
#define ECDSA_DEFAULT_SIZE 0
#endif
ecc_key *gen_ecdsa_priv_key(unsigned int bit_size);
ecc_key *buf_get_ecdsa_pub_key(buffer* buf);
ecc_key *buf_get_ecdsa_priv_key(buffer *buf);
void buf_put_ecdsa_pub_key(buffer *buf, ecc_key *key);
void buf_put_ecdsa_priv_key(buffer *buf, ecc_key *key);
enum signkey_type ecdsa_signkey_type(ecc_key * key);
void buf_put_ecdsa_sign(buffer *buf, ecc_key *key, buffer *data_buf);
int buf_ecdsa_verify(buffer *buf, ecc_key *key, buffer *data_buf);
/* Returns 1 on success */
int signkey_is_ecdsa(enum signkey_type type);
#endif
#endif /* DROPBEAR_ECDSA_H_ */

View File

@@ -1,7 +1,6 @@
/* Taken for Dropbear from OpenSSH 5.5p1 */
/*
*
* Taken from OpenSSH 3.8.1p1
*
* Copyright (C) 2000-2003 Damien Miller. All rights reserved.
* Copyright (C) 1999 WIDE Project. All rights reserved.
*
@@ -40,7 +39,11 @@
#include "includes.h"
/* RCSID("$.Id: fake-rfc2553.c,v 1.5 2003/09/22 02:08:23 dtucker Exp $");*/
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#ifndef HAVE_GETNAMEINFO
int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
@@ -50,6 +53,8 @@ int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
struct hostent *hp;
char tmpserv[16];
if (sa->sa_family != AF_UNSPEC && sa->sa_family != AF_INET)
return (EAI_FAMILY);
if (serv != NULL) {
snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port));
if (strlcpy(serv, tmpserv, servlen) >= servlen)
@@ -94,6 +99,8 @@ gai_strerror(int err)
return ("memory allocation failure.");
case EAI_NONAME:
return ("nodename nor servname provided, or not known");
case EAI_FAMILY:
return ("ai_family not supported");
default:
return ("unknown/invalid error.");
}
@@ -158,6 +165,9 @@ getaddrinfo(const char *hostname, const char *servname,
u_long addr;
port = 0;
if (hints && hints->ai_family != AF_UNSPEC &&
hints->ai_family != AF_INET)
return (EAI_FAMILY);
if (servname != NULL) {
char *cp;

View File

@@ -1,6 +1,6 @@
/* Taken from OpenSSH 3.8.1p1 */
/* Taken for Dropbear from OpenSSH 5.5p1 */
/* $.Id: fake-rfc2553.h,v 1.9 2004/03/10 10:06:33 dtucker Exp $ */
/* $Id: fake-rfc2553.h,v 1.16 2008/07/14 11:37:37 djm Exp $ */
/*
* Copyright (C) 2000-2003 Damien Miller. All rights reserved.
@@ -39,10 +39,14 @@
* that ai_family is AF_INET. Don't use it for another purpose.
*/
#ifndef _FAKE_RFC2553_H
#define _FAKE_RFC2553_H
#ifndef DROPBEAR_FAKE_RFC2553_H
#define DROPBEAR_FAKE_RFC2553_H
#include "includes.h"
#include <sys/types.h>
#if defined(HAVE_NETDB_H)
# include <netdb.h>
#endif
/*
* First, socket and INET6 related definitions
@@ -75,6 +79,7 @@ struct sockaddr_in6 {
u_int16_t sin6_port;
u_int32_t sin6_flowinfo;
struct in6_addr sin6_addr;
u_int32_t sin6_scope_id;
};
#endif /* !HAVE_STRUCT_SOCKADDR_IN6 */
@@ -115,9 +120,19 @@ struct sockaddr_in6 {
#endif /* !NI_MAXHOST */
#ifndef EAI_NODATA
# define EAI_NODATA 1
# define EAI_MEMORY 2
# define EAI_NONAME 3
# define EAI_NODATA (INT_MAX - 1)
#endif
#ifndef EAI_MEMORY
# define EAI_MEMORY (INT_MAX - 2)
#endif
#ifndef EAI_NONAME
# define EAI_NONAME (INT_MAX - 3)
#endif
#ifndef EAI_SYSTEM
# define EAI_SYSTEM (INT_MAX - 4)
#endif
#ifndef EAI_FAMILY
# define EAI_FAMILY (INT_MAX - 5)
#endif
#ifndef HAVE_STRUCT_ADDRINFO
@@ -143,7 +158,7 @@ int getaddrinfo(const char *, const char *,
#endif /* !HAVE_GETADDRINFO */
#if !defined(HAVE_GAI_STRERROR) && !defined(HAVE_CONST_GAI_STRERROR_PROTO)
#define gai_strerror(a) (ssh_gai_strerror(a))
#define gai_strerror(a) (_ssh_compat_gai_strerror(a))
char *gai_strerror(int);
#endif /* !HAVE_GAI_STRERROR */

View File

@@ -26,7 +26,7 @@
#include "dbutil.h"
#include "signkey.h"
#include "bignum.h"
#include "random.h"
#include "dbrandom.h"
#include "buffer.h"
#include "gendss.h"
#include "dss.h"
@@ -37,29 +37,26 @@
#ifdef DROPBEAR_DSS
static void getq(dss_key *key);
static void getp(dss_key *key, unsigned int size);
static void getg(dss_key *key);
static void getx(dss_key *key);
static void gety(dss_key *key);
static void getq(dropbear_dss_key *key);
static void getp(dropbear_dss_key *key, unsigned int size);
static void getg(dropbear_dss_key *key);
static void getx(dropbear_dss_key *key);
static void gety(dropbear_dss_key *key);
dss_key * gen_dss_priv_key(unsigned int size) {
dropbear_dss_key * gen_dss_priv_key(unsigned int size) {
dss_key *key;
dropbear_dss_key *key;
key = (dss_key*)m_malloc(sizeof(dss_key));
if (size != 1024) {
dropbear_exit("DSS keys have a fixed size of 1024 bits");
}
key->p = (mp_int*)m_malloc(sizeof(mp_int));
key->q = (mp_int*)m_malloc(sizeof(mp_int));
key->g = (mp_int*)m_malloc(sizeof(mp_int));
key->y = (mp_int*)m_malloc(sizeof(mp_int));
key->x = (mp_int*)m_malloc(sizeof(mp_int));
m_mp_init_multi(key->p, key->q, key->g, key->y, key->x, NULL);
seedrandom();
key = m_malloc(sizeof(*key));
m_mp_alloc_init_multi(&key->p, &key->q, &key->g, &key->y, &key->x, NULL);
getq(key);
getp(key, size);
getp(key, size/8);
getg(key);
getx(key);
gety(key);
@@ -68,9 +65,9 @@ dss_key * gen_dss_priv_key(unsigned int size) {
}
static void getq(dss_key *key) {
static void getq(dropbear_dss_key *key) {
char buf[QSIZE];
unsigned char buf[QSIZE];
/* 160 bit prime */
genrandom(buf, QSIZE);
@@ -81,12 +78,12 @@ static void getq(dss_key *key) {
/* 18 rounds are required according to HAC */
if (mp_prime_next_prime(key->q, 18, 0) != MP_OKAY) {
fprintf(stderr, "dss key generation failed\n");
fprintf(stderr, "DSS key generation failed\n");
exit(1);
}
}
static void getp(dss_key *key, unsigned int size) {
static void getp(dropbear_dss_key *key, unsigned int size) {
DEF_MP_INT(tempX);
DEF_MP_INT(tempC);
@@ -100,7 +97,7 @@ static void getp(dss_key *key, unsigned int size) {
/* 2*q */
if (mp_mul_d(key->q, 2, &temp2q) != MP_OKAY) {
fprintf(stderr, "dss key generation failed\n");
fprintf(stderr, "DSS key generation failed\n");
exit(1);
}
@@ -117,25 +114,25 @@ static void getp(dss_key *key, unsigned int size) {
/* C = X mod 2q */
if (mp_mod(&tempX, &temp2q, &tempC) != MP_OKAY) {
fprintf(stderr, "dss key generation failed\n");
fprintf(stderr, "DSS key generation failed\n");
exit(1);
}
/* P = X - (C - 1) = X - C + 1*/
if (mp_sub(&tempX, &tempC, &tempP) != MP_OKAY) {
fprintf(stderr, "dss key generation failed\n");
fprintf(stderr, "DSS key generation failed\n");
exit(1);
}
if (mp_add_d(&tempP, 1, key->p) != MP_OKAY) {
fprintf(stderr, "dss key generation failed\n");
fprintf(stderr, "DSS key generation failed\n");
exit(1);
}
/* now check for prime, 5 rounds is enough according to HAC */
/* result == 1 => p is prime */
if (mp_prime_is_prime(key->p, 5, &result) != MP_OKAY) {
fprintf(stderr, "dss key generation failed\n");
fprintf(stderr, "DSS key generation failed\n");
exit(1);
}
} while (!result);
@@ -145,7 +142,7 @@ static void getp(dss_key *key, unsigned int size) {
m_free(buf);
}
static void getg(dss_key * key) {
static void getg(dropbear_dss_key * key) {
DEF_MP_INT(div);
DEF_MP_INT(h);
@@ -155,11 +152,11 @@ static void getg(dss_key * key) {
/* get div=(p-1)/q */
if (mp_sub_d(key->p, 1, &val) != MP_OKAY) {
fprintf(stderr, "dss key generation failed\n");
fprintf(stderr, "DSS key generation failed\n");
exit(1);
}
if (mp_div(&val, key->q, &div, NULL) != MP_OKAY) {
fprintf(stderr, "dss key generation failed\n");
fprintf(stderr, "DSS key generation failed\n");
exit(1);
}
@@ -168,12 +165,12 @@ static void getg(dss_key * key) {
do {
/* now keep going with g=h^div mod p, until g > 1 */
if (mp_exptmod(&h, &div, key->p, key->g) != MP_OKAY) {
fprintf(stderr, "dss key generation failed\n");
fprintf(stderr, "DSS key generation failed\n");
exit(1);
}
if (mp_add_d(&h, 1, &h) != MP_OKAY) {
fprintf(stderr, "dss key generation failed\n");
fprintf(stderr, "DSS key generation failed\n");
exit(1);
}
@@ -182,15 +179,15 @@ static void getg(dss_key * key) {
mp_clear_multi(&div, &h, &val, NULL);
}
static void getx(dss_key *key) {
static void getx(dropbear_dss_key *key) {
gen_random_mpint(key->q, key->x);
}
static void gety(dss_key *key) {
static void gety(dropbear_dss_key *key) {
if (mp_exptmod(key->g, key->x, key->p, key->y) != MP_OKAY) {
fprintf(stderr, "dss key generation failed\n");
fprintf(stderr, "DSS key generation failed\n");
exit(1);
}
}

View File

@@ -22,15 +22,15 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#ifndef _GENDSS_H_
#define _GENDSS_H_
#ifndef DROPBEAR_GENDSS_H_
#define DROPBEAR_GENDSS_H_
#include "dss.h"
#ifdef DROPBEAR_DSS
dss_key * gen_dss_priv_key(unsigned int size);
dropbear_dss_key * gen_dss_priv_key(unsigned int size);
#endif /* DROPBEAR_DSS */
#endif /* _GENDSS_H_ */
#endif /* DROPBEAR_GENDSS_H_ */

View File

@@ -25,7 +25,7 @@
#include "includes.h"
#include "dbutil.h"
#include "bignum.h"
#include "random.h"
#include "dbrandom.h"
#include "rsa.h"
#include "genrsa.h"
@@ -34,56 +34,54 @@
#ifdef DROPBEAR_RSA
static void getrsaprime(mp_int* prime, mp_int *primeminus,
mp_int* rsa_e, unsigned int size);
mp_int* rsa_e, unsigned int size_bytes);
/* mostly taken from libtomcrypt's rsa key generation routine */
rsa_key * gen_rsa_priv_key(unsigned int size) {
dropbear_rsa_key * gen_rsa_priv_key(unsigned int size) {
rsa_key * key;
dropbear_rsa_key * key;
DEF_MP_INT(pminus);
DEF_MP_INT(qminus);
DEF_MP_INT(lcm);
key = (rsa_key*)m_malloc(sizeof(rsa_key));
if (size < 512 || size > 4096 || (size % 8 != 0)) {
dropbear_exit("Bits must satisfy 512 <= bits <= 4096, and be a"
" multiple of 8");
}
key->e = (mp_int*)m_malloc(sizeof(mp_int));
key->n = (mp_int*)m_malloc(sizeof(mp_int));
key->d = (mp_int*)m_malloc(sizeof(mp_int));
key->p = (mp_int*)m_malloc(sizeof(mp_int));
key->q = (mp_int*)m_malloc(sizeof(mp_int));
m_mp_init_multi(key->e, key->n, key->d, key->p, key->q,
&pminus, &lcm, &qminus, NULL);
seedrandom();
key = m_malloc(sizeof(*key));
m_mp_alloc_init_multi(&key->e, &key->n, &key->d, &key->p, &key->q, NULL);
m_mp_init_multi(&pminus, &lcm, &qminus, NULL);
if (mp_set_int(key->e, RSA_E) != MP_OKAY) {
fprintf(stderr, "rsa generation failed\n");
fprintf(stderr, "RSA generation failed\n");
exit(1);
}
/* PuTTY doesn't like it if the modulus isn't a multiple of 8 bits,
* so we just generate them until we get one which is OK */
getrsaprime(key->p, &pminus, key->e, size/2);
do {
getrsaprime(key->q, &qminus, key->e, size/2);
while (1) {
getrsaprime(key->p, &pminus, key->e, size/16);
getrsaprime(key->q, &qminus, key->e, size/16);
if (mp_mul(key->p, key->q, key->n) != MP_OKAY) {
fprintf(stderr, "rsa generation failed\n");
fprintf(stderr, "RSA generation failed\n");
exit(1);
}
} while (mp_count_bits(key->n) % 8 != 0);
if ((unsigned int)mp_count_bits(key->n) == size) {
break;
}
}
/* lcm(p-1, q-1) */
if (mp_lcm(&pminus, &qminus, &lcm) != MP_OKAY) {
fprintf(stderr, "rsa generation failed\n");
fprintf(stderr, "RSA generation failed\n");
exit(1);
}
/* de = 1 mod lcm(p-1,q-1) */
/* therefore d = (e^-1) mod lcm(p-1,q-1) */
if (mp_invmod(key->e, &lcm, key->d) != MP_OKAY) {
fprintf(stderr, "rsa generation failed\n");
fprintf(stderr, "RSA generation failed\n");
exit(1);
}
@@ -94,43 +92,43 @@ rsa_key * gen_rsa_priv_key(unsigned int size) {
/* return a prime suitable for p or q */
static void getrsaprime(mp_int* prime, mp_int *primeminus,
mp_int* rsa_e, unsigned int size) {
mp_int* rsa_e, unsigned int size_bytes) {
unsigned char *buf;
DEF_MP_INT(temp_gcd);
buf = (unsigned char*)m_malloc(size+1);
buf = (unsigned char*)m_malloc(size_bytes);
m_mp_init(&temp_gcd);
do {
/* generate a random odd number with MSB set, then find the
the next prime above it */
genrandom(buf, size+1);
buf[0] |= 0x80; /* MSB set */
genrandom(buf, size_bytes);
buf[0] |= 0x80;
bytes_to_mp(prime, buf, size+1);
bytes_to_mp(prime, buf, size_bytes);
/* find the next integer which is prime, 8 round of miller-rabin */
if (mp_prime_next_prime(prime, 8, 0) != MP_OKAY) {
fprintf(stderr, "rsa generation failed\n");
fprintf(stderr, "RSA generation failed\n");
exit(1);
}
/* subtract one to get p-1 */
if (mp_sub_d(prime, 1, primeminus) != MP_OKAY) {
fprintf(stderr, "rsa generation failed\n");
fprintf(stderr, "RSA generation failed\n");
exit(1);
}
/* check relative primality to e */
if (mp_gcd(primeminus, rsa_e, &temp_gcd) != MP_OKAY) {
fprintf(stderr, "rsa generation failed\n");
fprintf(stderr, "RSA generation failed\n");
exit(1);
}
} while (mp_cmp_d(&temp_gcd, 1) != MP_EQ); /* while gcd(p-1, e) != 1 */
/* now we have a good value for result */
mp_clear(&temp_gcd);
m_burn(buf, size+1);
m_burn(buf, size_bytes);
m_free(buf);
}

View File

@@ -22,15 +22,15 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#ifndef _GENRSA_H_
#define _GENRSA_H_
#ifndef DROPBEAR_GENRSA_H_
#define DROPBEAR_GENRSA_H_
#include "rsa.h"
#ifdef DROPBEAR_RSA
rsa_key * gen_rsa_priv_key(unsigned int size);
dropbear_rsa_key * gen_rsa_priv_key(unsigned int size);
#endif /* DROPBEAR_RSA */
#endif /* _GENRSA_H_ */
#endif /* DROPBEAR_GENRSA_H_ */

135
gensignkey.c Normal file
View File

@@ -0,0 +1,135 @@
#include "includes.h"
#include "dbutil.h"
#include "buffer.h"
#include "ecdsa.h"
#include "genrsa.h"
#include "gendss.h"
#include "signkey.h"
#include "dbrandom.h"
#define RSA_DEFAULT_SIZE 2048
#define DSS_DEFAULT_SIZE 1024
/* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
static int buf_writefile(buffer * buf, const char * filename) {
int ret = DROPBEAR_FAILURE;
int fd = -1;
fd = open(filename, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
if (fd < 0) {
dropbear_log(LOG_ERR, "Couldn't create new file %s: %s",
filename, strerror(errno));
goto out;
}
/* write the file now */
while (buf->pos != buf->len) {
int len = write(fd, buf_getptr(buf, buf->len - buf->pos),
buf->len - buf->pos);
if (len == -1 && errno == EINTR) {
continue;
}
if (len <= 0) {
dropbear_log(LOG_ERR, "Failed writing file %s: %s",
filename, strerror(errno));
goto out;
}
buf_incrpos(buf, len);
}
ret = DROPBEAR_SUCCESS;
out:
if (fd >= 0) {
if (fsync(fd) != 0) {
dropbear_log(LOG_ERR, "fsync of %s failed: %s", filename, strerror(errno));
}
m_close(fd);
}
return ret;
}
/* returns 0 on failure */
static int get_default_bits(enum signkey_type keytype)
{
switch (keytype) {
#ifdef DROPBEAR_RSA
case DROPBEAR_SIGNKEY_RSA:
return RSA_DEFAULT_SIZE;
#endif
#ifdef DROPBEAR_DSS
case DROPBEAR_SIGNKEY_DSS:
return DSS_DEFAULT_SIZE;
#endif
#ifdef DROPBEAR_ECDSA
case DROPBEAR_SIGNKEY_ECDSA_KEYGEN:
return ECDSA_DEFAULT_SIZE;
case DROPBEAR_SIGNKEY_ECDSA_NISTP521:
return 521;
case DROPBEAR_SIGNKEY_ECDSA_NISTP384:
return 384;
case DROPBEAR_SIGNKEY_ECDSA_NISTP256:
return 256;
#endif
default:
return 0;
}
}
int signkey_generate(enum signkey_type keytype, int bits, const char* filename)
{
sign_key * key = NULL;
buffer *buf = NULL;
int ret = DROPBEAR_FAILURE;
if (bits == 0)
{
bits = get_default_bits(keytype);
}
/* now we can generate the key */
key = new_sign_key();
seedrandom();
switch(keytype) {
#ifdef DROPBEAR_RSA
case DROPBEAR_SIGNKEY_RSA:
key->rsakey = gen_rsa_priv_key(bits);
break;
#endif
#ifdef DROPBEAR_DSS
case DROPBEAR_SIGNKEY_DSS:
key->dsskey = gen_dss_priv_key(bits);
break;
#endif
#ifdef DROPBEAR_ECDSA
case DROPBEAR_SIGNKEY_ECDSA_KEYGEN:
case DROPBEAR_SIGNKEY_ECDSA_NISTP521:
case DROPBEAR_SIGNKEY_ECDSA_NISTP384:
case DROPBEAR_SIGNKEY_ECDSA_NISTP256:
{
ecc_key *ecckey = gen_ecdsa_priv_key(bits);
keytype = ecdsa_signkey_type(ecckey);
*signkey_key_ptr(key, keytype) = ecckey;
}
break;
#endif
default:
dropbear_exit("Internal error");
}
seedrandom();
buf = buf_new(MAX_PRIVKEY_SIZE);
buf_put_priv_key(buf, key, keytype);
sign_key_free(key);
key = NULL;
buf_setpos(buf, 0);
ret = buf_writefile(buf, filename);
buf_burn(buf);
buf_free(buf);
buf = NULL;
return ret;
}

8
gensignkey.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef DROPBEAR_GENSIGNKEY_H
#define DROPBEAR_GENSIGNKEY_H
#include "signkey.h"
int signkey_generate(enum signkey_type type, int bits, const char* filename);
#endif

View File

@@ -22,8 +22,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#ifndef _INCLUDES_H_
#define _INCLUDES_H_
#ifndef DROPBEAR_INCLUDES_H_
#define DROPBEAR_INCLUDES_H_
#include "config.h"
@@ -56,6 +56,7 @@
#include <ctype.h>
#include <stdarg.h>
#include <dirent.h>
#include <time.h>
#ifdef HAVE_UTMP_H
#include <utmp.h>
@@ -119,19 +120,49 @@
#include <libgen.h>
#endif
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
#endif
#ifdef BUNDLED_LIBTOM
#include "libtomcrypt/src/headers/tomcrypt.h"
#include "libtommath/tommath.h"
#else
#include <tomcrypt.h>
#include <tommath.h>
#endif
#include "compat.h"
#include "fake-rfc2553.h"
#ifndef HAVE_UINT16_T
#ifndef HAVE_U_INT8_T
typedef unsigned char u_int8_t;
#endif /* HAVE_U_INT8_T */
#ifndef HAVE_UINT8_T
typedef u_int8_t uint8_t;
#endif /* HAVE_UINT8_T */
#ifndef HAVE_U_INT16_T
typedef unsigned short u_int16_t;
#endif /* HAVE_U_INT16_T */
#ifndef HAVE_UINT16_T
typedef u_int16_t uint16_t;
#endif /* HAVE_UINT16_T */
#ifndef HAVE_U_INT32_T
typedef unsigned int u_int32_t;
#endif /* HAVE_U_INT32_T */
#ifndef HAVE_UINT32_T
typedef u_int32_t uint32_t;
#endif /* HAVE_UINT32_T */
#ifdef SO_PRIORITY
#include <linux/types.h>
#include <linux/pkt_sched.h>
#endif
#include "fake-rfc2553.h"
#ifndef LOG_AUTHPRIV
#define LOG_AUTHPRIV LOG_AUTH
#endif
@@ -146,4 +177,4 @@ typedef u_int16_t uint16_t;
# define UNUSED(x) x
#endif
#endif /* _INCLUDES_H_ */
#endif /* DROPBEAR_INCLUDES_H_ */

81
kex.h
View File

@@ -22,43 +22,90 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#ifndef _KEX_H_
#define _KEX_H_
#ifndef DROPBEAR_KEX_H_
#define DROPBEAR_KEX_H_
#include "includes.h"
#include "algo.h"
#include "signkey.h"
void send_msg_kexinit();
void recv_msg_kexinit();
void send_msg_newkeys();
void recv_msg_newkeys();
void kexfirstinitialise();
void gen_kexdh_vals(mp_int *dh_pub, mp_int *dh_priv);
void kexdh_comb_key(mp_int *dh_pub_us, mp_int *dh_priv, mp_int *dh_pub_them,
void send_msg_kexinit(void);
void recv_msg_kexinit(void);
void send_msg_newkeys(void);
void recv_msg_newkeys(void);
void kexfirstinitialise(void);
struct kex_dh_param *gen_kexdh_param(void);
void free_kexdh_param(struct kex_dh_param *param);
void kexdh_comb_key(struct kex_dh_param *param, mp_int *dh_pub_them,
sign_key *hostkey);
void recv_msg_kexdh_init(); /* server */
#ifdef DROPBEAR_ECDH
struct kex_ecdh_param *gen_kexecdh_param(void);
void free_kexecdh_param(struct kex_ecdh_param *param);
void kexecdh_comb_key(struct kex_ecdh_param *param, buffer *pub_them,
sign_key *hostkey);
#endif
void send_msg_kexdh_init(); /* client */
void recv_msg_kexdh_reply(); /* client */
#ifdef DROPBEAR_CURVE25519
struct kex_curve25519_param *gen_kexcurve25519_param(void);
void free_kexcurve25519_param(struct kex_curve25519_param *param);
void kexcurve25519_comb_key(struct kex_curve25519_param *param, buffer *pub_them,
sign_key *hostkey);
#endif
#ifndef DISABLE_ZLIB
int is_compress_trans(void);
int is_compress_recv(void);
#endif
void recv_msg_kexdh_init(void); /* server */
void send_msg_kexdh_init(void); /* client */
void recv_msg_kexdh_reply(void); /* client */
struct KEXState {
unsigned sentkexinit : 1; /*set when we've sent/recv kexinit packet */
unsigned recvkexinit : 1;
unsigned firstfollows : 1; /* true when first_kex_packet_follows is set */
unsigned sentnewkeys : 1; /* set once we've send/recv'ed MSG_NEWKEYS*/
unsigned recvnewkeys : 1;
unsigned them_firstfollows : 1; /* true when first_kex_packet_follows is set */
unsigned sentnewkeys : 1; /* set once we've send MSG_NEWKEYS (will be cleared once we have also received */
unsigned recvnewkeys : 1; /* set once we've received MSG_NEWKEYS (cleared once we have also sent */
unsigned donefirstkex : 1; /* Set to 1 after the first kex has completed,
ie the transport layer has been set up */
long lastkextime; /* time of the last kex */
unsigned our_first_follows_matches : 1;
time_t lastkextime; /* time of the last kex */
unsigned int datatrans; /* data transmitted since last kex */
unsigned int datarecv; /* data received since last kex */
};
struct kex_dh_param {
mp_int pub; /* e */
mp_int priv; /* x */
};
#ifdef DROPBEAR_ECDH
struct kex_ecdh_param {
ecc_key key;
};
#endif
#ifdef DROPBEAR_CURVE25519
#define CURVE25519_LEN 32
struct kex_curve25519_param {
unsigned char priv[CURVE25519_LEN];
unsigned char pub[CURVE25519_LEN];
};
/* No header file for curve25519_donna */
int curve25519_donna(unsigned char *out, const unsigned char *secret, const unsigned char *other);
#endif
#define MAX_KEXHASHBUF 2000
#endif /* _KEX_H_ */
#endif /* DROPBEAR_KEX_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -22,8 +22,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#ifndef _KEYIMPORT_H_
#define _KEYIMPORT_H_
#ifndef DROPBEAR_KEYIMPORT_H_
#define DROPBEAR_KEYIMPORT_H_
#include "includes.h"
#include "signkey.h"
@@ -39,4 +39,4 @@ int import_write(const char *filename, sign_key *key, char *passphrase,
sign_key *import_read(const char *filename, char *passphrase, int filetype);
int import_encrypted(const char* filename, int filetype);
#endif /* _KEYIMPORT_H_ */
#endif /* DROPBEAR_KEYIMPORT_H_ */

View File

@@ -19,7 +19,7 @@ srcdir=@srcdir@
# Compilation flags. Note the += does not write over the user's CFLAGS!
# The rest of the flags come from the parent Dropbear makefile
CFLAGS += -c -I$(srcdir)/src/headers/ -I$(srcdir)/../
CFLAGS += -c -I$(srcdir)/src/headers/ -I$(srcdir)/../ -DLTC_SOURCE -I$(srcdir)/../libtommath/
# additional warnings (newer GCC 3.4 and higher)
ifdef GCC_34
@@ -157,7 +157,53 @@ src/modes/lrw/lrw_decrypt.o src/modes/lrw/lrw_done.o src/modes/lrw/lrw_encrypt.o
src/modes/lrw/lrw_getiv.o src/modes/lrw/lrw_process.o src/modes/lrw/lrw_setiv.o \
src/modes/lrw/lrw_start.o src/modes/lrw/lrw_test.o src/modes/ofb/ofb_decrypt.o src/modes/ofb/ofb_done.o \
src/modes/ofb/ofb_encrypt.o src/modes/ofb/ofb_getiv.o src/modes/ofb/ofb_setiv.o \
src/modes/ofb/ofb_start.o
src/modes/ofb/ofb_start.o src/pk/asn1/der/bit/der_decode_bit_string.o \
src/pk/asn1/der/bit/der_encode_bit_string.o src/pk/asn1/der/bit/der_length_bit_string.o \
src/pk/asn1/der/boolean/der_decode_boolean.o src/pk/asn1/der/boolean/der_encode_boolean.o \
src/pk/asn1/der/boolean/der_length_boolean.o src/pk/asn1/der/choice/der_decode_choice.o \
src/pk/asn1/der/ia5/der_decode_ia5_string.o src/pk/asn1/der/ia5/der_encode_ia5_string.o \
src/pk/asn1/der/ia5/der_length_ia5_string.o src/pk/asn1/der/integer/der_decode_integer.o \
src/pk/asn1/der/integer/der_encode_integer.o src/pk/asn1/der/integer/der_length_integer.o \
src/pk/asn1/der/object_identifier/der_decode_object_identifier.o \
src/pk/asn1/der/object_identifier/der_encode_object_identifier.o \
src/pk/asn1/der/object_identifier/der_length_object_identifier.o \
src/pk/asn1/der/octet/der_decode_octet_string.o src/pk/asn1/der/octet/der_encode_octet_string.o \
src/pk/asn1/der/octet/der_length_octet_string.o \
src/pk/asn1/der/printable_string/der_decode_printable_string.o \
src/pk/asn1/der/printable_string/der_encode_printable_string.o \
src/pk/asn1/der/printable_string/der_length_printable_string.o \
src/pk/asn1/der/sequence/der_decode_sequence_ex.o \
src/pk/asn1/der/sequence/der_decode_sequence_flexi.o \
src/pk/asn1/der/sequence/der_decode_sequence_multi.o \
src/pk/asn1/der/sequence/der_encode_sequence_ex.o \
src/pk/asn1/der/sequence/der_encode_sequence_multi.o src/pk/asn1/der/sequence/der_length_sequence.o \
src/pk/asn1/der/sequence/der_sequence_free.o src/pk/asn1/der/set/der_encode_set.o \
src/pk/asn1/der/set/der_encode_setof.o src/pk/asn1/der/short_integer/der_decode_short_integer.o \
src/pk/asn1/der/short_integer/der_encode_short_integer.o \
src/pk/asn1/der/short_integer/der_length_short_integer.o src/pk/asn1/der/utctime/der_decode_utctime.o \
src/pk/asn1/der/utctime/der_encode_utctime.o src/pk/asn1/der/utctime/der_length_utctime.o \
src/pk/asn1/der/utf8/der_decode_utf8_string.o src/pk/asn1/der/utf8/der_encode_utf8_string.o \
src/pk/asn1/der/utf8/der_length_utf8_string.o src/pk/dsa/dsa_decrypt_key.o \
src/pk/dsa/dsa_encrypt_key.o src/pk/dsa/dsa_export.o src/pk/dsa/dsa_free.o src/pk/dsa/dsa_import.o \
src/pk/dsa/dsa_make_key.o src/pk/dsa/dsa_shared_secret.o src/pk/dsa/dsa_sign_hash.o \
src/pk/dsa/dsa_verify_hash.o src/pk/dsa/dsa_verify_key.o src/pk/ecc/ecc.o \
src/pk/ecc/ecc_ansi_x963_export.o src/pk/ecc/ecc_ansi_x963_import.o src/pk/ecc/ecc_decrypt_key.o \
src/pk/ecc/ecc_encrypt_key.o src/pk/ecc/ecc_export.o src/pk/ecc/ecc_free.o src/pk/ecc/ecc_get_size.o \
src/pk/ecc/ecc_import.o src/pk/ecc/ecc_make_key.o src/pk/ecc/ecc_shared_secret.o \
src/pk/ecc/ecc_sign_hash.o src/pk/ecc/ecc_sizes.o src/pk/ecc/ecc_test.o src/pk/ecc/ecc_verify_hash.o \
src/pk/ecc/ltc_ecc_is_valid_idx.o src/pk/ecc/ltc_ecc_map.o src/pk/ecc/ltc_ecc_mul2add.o \
src/pk/ecc/ltc_ecc_mulmod.o src/pk/ecc/ltc_ecc_mulmod_timing.o src/pk/ecc/ltc_ecc_points.o \
src/pk/ecc/ltc_ecc_projective_add_point.o src/pk/ecc/ltc_ecc_projective_dbl_point.o \
src/pk/katja/katja_decrypt_key.o src/pk/katja/katja_encrypt_key.o src/pk/katja/katja_export.o \
src/pk/katja/katja_exptmod.o src/pk/katja/katja_free.o src/pk/katja/katja_import.o \
src/pk/katja/katja_make_key.o src/pk/pkcs1/pkcs_1_i2osp.o src/pk/pkcs1/pkcs_1_mgf1.o \
src/pk/pkcs1/pkcs_1_oaep_decode.o src/pk/pkcs1/pkcs_1_oaep_encode.o src/pk/pkcs1/pkcs_1_os2ip.o \
src/pk/pkcs1/pkcs_1_pss_decode.o src/pk/pkcs1/pkcs_1_pss_encode.o src/pk/pkcs1/pkcs_1_v1_5_decode.o \
src/pk/pkcs1/pkcs_1_v1_5_encode.o src/pk/rsa/rsa_decrypt_key.o src/pk/rsa/rsa_encrypt_key.o \
src/pk/rsa/rsa_export.o src/pk/rsa/rsa_exptmod.o src/pk/rsa/rsa_free.o src/pk/rsa/rsa_import.o \
src/pk/rsa/rsa_make_key.o src/pk/rsa/rsa_sign_hash.o src/pk/rsa/rsa_verify_hash.o src/prngs/fortuna.o \
src/prngs/rc4.o src/prngs/rng_get_bytes.o src/prngs/rng_make_prng.o src/prngs/sober128.o \
src/prngs/sprng.o src/prngs/yarrow.o
HEADERS=src/headers/tomcrypt_cfg.h src/headers/tomcrypt_mac.h src/headers/tomcrypt_macros.h \
src/headers/tomcrypt_custom.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cipher.h \

View File

@@ -122,9 +122,10 @@ static ulong32 setup_mix2(ulong32 temp)
*/
int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
{
int i, j;
int i;
ulong32 temp, *rk;
#ifndef ENCRYPT_ONLY
int j;
ulong32 *rrk;
#endif
LTC_ARGCHK(key != NULL);
@@ -148,7 +149,9 @@ int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *s
LOAD32H(rk[2], key + 8);
LOAD32H(rk[3], key + 12);
if (keylen == 16) {
#ifndef ENCRYPT_ONLY
j = 44;
#endif
for (;;) {
temp = rk[3];
rk[4] = rk[0] ^ setup_mix(temp) ^ rcon[i];
@@ -161,7 +164,9 @@ int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *s
rk += 4;
}
} else if (keylen == 24) {
#ifndef ENCRYPT_ONLY
j = 52;
#endif
LOAD32H(rk[4], key + 16);
LOAD32H(rk[5], key + 20);
for (;;) {
@@ -182,7 +187,9 @@ int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *s
rk += 6;
}
} else if (keylen == 32) {
#ifndef ENCRYPT_ONLY
j = 60;
#endif
LOAD32H(rk[4], key + 16);
LOAD32H(rk[5], key + 20);
LOAD32H(rk[6], key + 24);
@@ -728,6 +735,7 @@ int ECB_TEST(void)
*/
void ECB_DONE(symmetric_key *skey)
{
(void)skey;
}

View File

@@ -1871,6 +1871,7 @@ void des_done(symmetric_key *skey)
*/
void des3_done(symmetric_key *skey)
{
(void)skey;
}

View File

@@ -684,6 +684,7 @@ int twofish_test(void)
*/
void twofish_done(symmetric_key *skey)
{
(void)skey;
}
/**

View File

@@ -25,6 +25,7 @@
int hash_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen)
{
#ifdef LTC_NO_FILE
(void)hash; (void)fname; (void)out; (void)outlen;
return CRYPT_NOP;
#else
FILE *in;

View File

@@ -26,6 +26,7 @@
int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen)
{
#ifdef LTC_NO_FILE
(void)hash; (void)in; (void)out; (void)outlen;
return CRYPT_NOP;
#else
hash_state md;

View File

@@ -24,7 +24,7 @@ extern "C" {
/* descriptor table size */
/* Dropbear change - this should be smaller, saves some size */
#define TAB_SIZE 4
#define TAB_SIZE 5
/* error codes [will be expanded in future releases] */
enum {

View File

@@ -4,8 +4,16 @@
#include <signal.h>
/* portability macros for compiler-specific code attributes */
#ifdef __GNUC__
#define ATTRIB_NORETURN __attribute__((noreturn))
#else
#define ATTRIB_NORETURN
#endif
/* this is the default LibTomCrypt macro */
void crypt_argchk(char *v, char *s, int d);
void crypt_argchk(char *v, char *s, int d) ATTRIB_NORETURN;
#define LTC_ARGCHK(x) if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); }
#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)

View File

@@ -1,7 +1,7 @@
#ifndef TOMCRYPT_CUSTOM_H_
#define TOMCRYPT_CUSTOM_H_
/* this will sort out which stuff based on the user-config in options.h */
/* compile options depend on Dropbear options.h */
#include "options.h"
/* macros for various libc functions you can change for embedded targets */
@@ -78,7 +78,7 @@
/* #define LTC_CLEAN_STACK */
/* disable all file related functions */
/* #define LTC_NO_FILE */
#define LTC_NO_FILE
/* disable all forms of ASM */
/* #define LTC_NO_ASM */
@@ -90,15 +90,15 @@
/* #define LTC_NO_BSWAP */
#ifdef DROPBEAR_BLOWFISH_CBC
#ifdef DROPBEAR_BLOWFISH
#define BLOWFISH
#endif
#ifdef DROPBEAR_AES_CBC
#ifdef DROPBEAR_AES
#define RIJNDAEL
#endif
#ifdef DROPBEAR_TWOFISH_CBC
#ifdef DROPBEAR_TWOFISH
#define TWOFISH
/* enabling just TWOFISH_SMALL will make the binary ~1kB smaller, turning on
@@ -108,24 +108,51 @@
/*#define TWOFISH_TABLES*/
#endif
#ifdef DROPBEAR_3DES_CBC
#ifdef DROPBEAR_3DES
#define DES
#endif
#define LTC_CBC_MODE
#if defined(DROPBEAR_DSS) && defined(DSS_PROTOK)
#define SHA512
#ifdef DROPBEAR_ENABLE_CTR_MODE
#define LTC_CTR_MODE
#endif
#define SHA1
#ifdef DROPBEAR_MD5_HMAC
#ifdef DROPBEAR_MD5
#define MD5
#endif
#ifdef DROPBEAR_SHA256
#define SHA256
#endif
#ifdef DROPBEAR_SHA384
#define SHA384
#endif
#ifdef DROPBEAR_SHA512
#define SHA512
#endif
#define LTC_HMAC
#ifdef DROPBEAR_ECC
#define MECC
#define LTC_ECC_SHAMIR
#define LTC_ECC_TIMING_RESISTANT
#define MPI
#define LTM_DESC
#ifdef DROPBEAR_ECC_256
#define ECC256
#endif
#ifdef DROPBEAR_ECC_384
#define ECC384
#endif
#ifdef DROPBEAR_ECC_521
#define ECC521
#endif
#endif
/* Various tidbits of modern neatoness */
#define BASE64

View File

@@ -11,12 +11,9 @@
typedef void ecc_point;
#endif
/* Dropbear has its own rsa_key. We just comment this out. */
#if 0
#ifndef MRSA
typedef void rsa_key;
#endif
#endif
/** math descriptor */
typedef struct {
@@ -389,8 +386,6 @@ typedef struct {
ecc_point *C,
void *modulus);
/* Dropbear has its own rsa code */
#if 0
/* ---- (optional) rsa optimized math (for internal CRT) ---- */
/** RSA Key Generation
@@ -416,7 +411,6 @@ typedef struct {
int (*rsa_me)(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen, int which,
rsa_key *key);
#endif
} ltc_math_descriptor;
extern ltc_math_descriptor ltc_mp;

View File

@@ -28,7 +28,7 @@
*/
int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen)
{
unsigned char *buf, *isha;
unsigned char buf[MAXBLOCKSIZE], isha[MAXBLOCKSIZE];
unsigned long hashsize, i;
int hash, err;
@@ -44,19 +44,6 @@ int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen)
/* get the hash message digest size */
hashsize = hash_descriptor[hash].hashsize;
/* allocate buffers */
buf = XMALLOC(HMAC_BLOCKSIZE);
isha = XMALLOC(hashsize);
if (buf == NULL || isha == NULL) {
if (buf != NULL) {
XFREE(buf);
}
if (isha != NULL) {
XFREE(isha);
}
return CRYPT_MEM;
}
/* Get the hash of the first HMAC vector plus the data */
if ((err = hash_descriptor[hash].done(&hmac->md, isha)) != CRYPT_OK) {
goto LBL_ERR;
@@ -96,9 +83,6 @@ LBL_ERR:
zeromem(hmac, sizeof(*hmac));
#endif
XFREE(isha);
XFREE(buf);
return err;
}

Some files were not shown because too many files have changed in this diff Show More