Compare commits

..

186 Commits

Author SHA1 Message Date
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
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
49263b5314 Limit decompressed size 2013-05-08 23:23:14 +08:00
Matt Johnston
57166b400c Avoid segfault for locked accounts (invalid salt to crypt()) 2013-04-29 23:42:37 +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
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
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
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
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
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
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
90 changed files with 2720 additions and 1563 deletions

6
.hgsigs Normal file
View File

@@ -0,0 +1,6 @@
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

40
.hgtags Normal file
View File

@@ -0,0 +1,40 @@
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

171
CHANGES
View File

@@ -1,3 +1,170 @@
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
- Avoid disclosing existence of valid users through inconsistent delays
Thanks to Logan Lamb for reporting
- 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
@@ -565,7 +732,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
@@ -684,7 +851,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

@@ -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-2008 Matt Johnston
Copyright (c) 2002-2013 Matt Johnston
Portions copyright (c) 2004 Mihnea Stoenescu
All rights reserved.

View File

@@ -28,13 +28,13 @@ COMMONOBJS=dbutil.o buffer.o \
queue.o \
atomicio.o compat.o fake-rfc2553.o
SVROBJS=@CRYPTLIB@ svr-kex.o svr-algo.o svr-auth.o sshpty.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 \
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 list.o
@@ -56,7 +56,7 @@ HEADERS=options.h dbutil.h session.h packet.h algo.h ssh.h buffer.h kex.h \
loginrec.h atomicio.h x11fwd.h agentfwd.h tcpfwd.h compat.h \
listener.h fake-rfc2553.h
dropbearobjs=$(COMMONOBJS) $(CLISVROBJS) $(SVROBJS)
dropbearobjs=$(COMMONOBJS) $(CLISVROBJS) $(SVROBJS) @CRYPTLIB@
dbclientobjs=$(COMMONOBJS) $(CLISVROBJS) $(CLIOBJS)
dropbearkeyobjs=$(COMMONOBJS) $(KEYOBJS)
dropbearconvertobjs=$(COMMONOBJS) $(CONVERTOBJS)
@@ -66,9 +66,10 @@ VPATH=@srcdir@
srcdir=@srcdir@
prefix=@prefix@
exec_prefix=${prefix}
bindir=${exec_prefix}/bin
sbindir=${exec_prefix}/sbin
datarootdir = @datarootdir@
bindir=@bindir@
sbindir=@sbindir@
mandir=@mandir@
CC=@CC@
AR=@AR@
@@ -123,31 +124,31 @@ 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)
$(INSTALL) -d $(DESTDIR)$(bindir)
$(INSTALL) dropbearmulti$(EXEEXT) $(DESTDIR)$(bindir)
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)
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)
# dropbear should go in sbin, so it needs a seperate 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 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)
$(INSTALL) -d $(DESTDIR)$(bindir)
$(INSTALL) $*$(EXEEXT) $(DESTDIR)$(bindir)
$(INSTALL) -d $(DESTDIR)$(mandir)/man1
$(INSTALL) -m 644 $*.1 $(DESTDIR)$(mandir)/man1/$*.1
# for some reason the rule further down doesn't like $($@objs) as a prereq.
@@ -167,7 +168,7 @@ scp: $(SCPOBJS) $(HEADERS) Makefile
# multi-binary compilation.
MULTIOBJS=
ifeq ($(MULTI),1)
MULTIOBJS=dbmulti.o $(sort $(foreach prog, $(PROGRAMS), $($(prog)objs)))
MULTIOBJS=dbmulti.o $(sort $(foreach prog, $(PROGRAMS), $($(prog)objs))) @CRYPTLIB@
CFLAGS+=$(addprefix -DDBMULTI_, $(PROGRAMS)) -DDROPBEAR_MULTI
endif

6
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.
============================================================================

View File

@@ -30,22 +30,19 @@
#include "auth.h"
#include "list.h"
#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
int svr_agentreq(struct ChanSess * chansess);
void svr_agentcleanup(struct ChanSess * chansess);
void svr_agentset(struct ChanSess *chansess);
/* client functions */
void cli_load_agent_keys(m_list * ret_list);
void agent_buf_sign(buffer *sigblob, sign_key *key,
const unsigned char *data, unsigned int len);
void cli_setup_agent(struct Channel *channel);
#ifdef __hpux
#define seteuid(a) setresuid(-1, (a), -1)
#define setegid(a) setresgid(-1, (a), -1)
@@ -53,4 +50,14 @@ void cli_setup_agent(struct Channel *channel);
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 /* _AGENTFWD_H_ */

23
algo.h
View File

@@ -83,9 +83,24 @@ 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,
};
#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
#endif /* _ALGO_H_ */

4
auth.h
View File

@@ -36,6 +36,7 @@ void cli_authinitialise();
void recv_msg_userauth_request();
void send_msg_userauth_failure(int partial, int incrfail);
void send_msg_userauth_success();
void send_msg_userauth_banner(buffer *msg);
void svr_auth_password();
void svr_auth_pubkey();
void svr_auth_pam();
@@ -67,7 +68,7 @@ void recv_msg_userauth_pk_ok();
void recv_msg_userauth_info_request();
void cli_get_user();
void cli_auth_getmethods();
void cli_auth_try();
int cli_auth_try();
void recv_msg_userauth_banner();
void cli_pubkeyfail();
void cli_auth_password();
@@ -133,7 +134,6 @@ struct PubKeyOptions {
int no_pty_flag;
/* "command=" option. */
unsigned char * forced_command;
unsigned char * original_command;
};
#endif

View File

@@ -26,9 +26,10 @@
#define _BIGNUM_H_
#include "includes.h"
#include "dbutil.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 bytes_to_mp(mp_int *mp, const unsigned char* bytes, unsigned int len);
void sha1_process_mp(hash_state *hs, mp_int *mp);

View File

@@ -282,7 +282,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);
@@ -318,7 +318,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

@@ -61,7 +61,8 @@ struct Channel {
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 */
@@ -69,6 +70,10 @@ 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;
int initconn; /* used for TCP forwarding, whether the channel has been
fully initialised */
@@ -78,8 +83,10 @@ struct Channel {
int flushing;
const struct ChanType* type;
/* Used by client chansession to handle ~ escaping, NULL ignored otherwise */
void (*read_mangler)(struct Channel*, unsigned char* bytes, int *len);
const struct ChanType* type;
};
struct ChanType {
@@ -98,9 +105,6 @@ 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);
void recv_msg_channel_open();
void recv_msg_channel_request();

View File

@@ -69,6 +69,10 @@ struct ChanSess {
char * agentfile;
char * agentdir;
#endif
#ifdef ENABLE_SVR_PUBKEY_OPTIONS
char *original_command;
#endif
};
struct ChildPid {

View File

@@ -37,7 +37,9 @@ circbuffer * cbuf_new(unsigned int size) {
}
cbuf = (circbuffer*)m_malloc(sizeof(circbuffer));
cbuf->data = (unsigned char*)m_malloc(size);
if (size > 0) {
cbuf->data = (unsigned char*)m_malloc(size);
}
cbuf->used = 0;
cbuf->readpos = 0;
cbuf->writepos = 0;
@@ -48,6 +50,7 @@ circbuffer * cbuf_new(unsigned int size) {
void cbuf_free(circbuffer * cbuf) {
m_burn(cbuf->data, cbuf->size);
m_free(cbuf->data);
m_free(cbuf);
}

View File

@@ -83,7 +83,7 @@ static int new_agent_chan(struct Channel * channel) {
return SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
fd = connect_agent();
if (cli_opts.agent_fd < 0) {
if (fd < 0) {
return SSH_OPEN_CONNECT_FAILED;
}
@@ -156,8 +156,6 @@ static buffer * agent_request(unsigned char type, buffer *data) {
goto out;
}
TRACE(("agent_request readlen is %d", readlen))
buf_resize(inbuf, readlen);
buf_setpos(inbuf, 0);
ret = atomicio(read, fd, buf_getwriteptr(inbuf, readlen), readlen);
@@ -167,7 +165,6 @@ static buffer * agent_request(unsigned char type, buffer *data) {
}
buf_incrwritepos(inbuf, readlen);
buf_setpos(inbuf, 0);
TRACE(("agent_request success, length %d", readlen))
out:
if (payload)
@@ -258,9 +255,9 @@ void cli_load_agent_keys(m_list *ret_list) {
void agent_buf_sign(buffer *sigblob, sign_key *key,
const unsigned char *data, unsigned int len) {
buffer *request_data = buf_new(MAX_PUBKEY_SIZE + len + 12);
buffer *response;
unsigned int keylen, siglen;
buffer *request_data = NULL;
buffer *response = NULL;
unsigned int siglen;
int packet_type;
/* Request format
@@ -269,19 +266,13 @@ void agent_buf_sign(buffer *sigblob, sign_key *key,
string data
uint32 flags
*/
/* We write the key, then figure how long it was and write that */
//buf_putint(request_data, 0);
request_data = buf_new(MAX_PUBKEY_SIZE + len + 12);
buf_put_pub_key(request_data, key, key->type);
keylen = request_data->len - 4;
//buf_setpos(request_data, 0);
//buf_putint(request_data, keylen);
//buf_setpos(request_data, request_data->len);
buf_putstring(request_data, data, len);
buf_putint(request_data, 0);
response = agent_request(SSH2_AGENTC_SIGN_REQUEST, request_data);
buf_free(request_data);
if (!response) {
goto fail;
@@ -298,14 +289,21 @@ void agent_buf_sign(buffer *sigblob, sign_key *key,
*/
siglen = buf_getint(response);
buf_putbytes(sigblob, buf_getptr(response, siglen), siglen);
buf_free(response);
goto cleanup;
return;
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,11 +40,18 @@ void cli_authinitialise() {
/* Send a "none" auth request to get available methods */
void cli_auth_getmethods() {
TRACE(("enter cli_auth_getmethods"))
#ifdef CLI_IMMEDIATE_AUTH
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"))
return;
}
#endif
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);
buf_putstring(ses.writepayload, cli_opts.username,
strlen(cli_opts.username));
@@ -54,7 +61,6 @@ void cli_auth_getmethods() {
encrypt_packet();
TRACE(("leave cli_auth_getmethods"))
}
void recv_msg_userauth_banner() {
@@ -240,7 +246,7 @@ void recv_msg_userauth_success() {
#endif
}
void cli_auth_try() {
int cli_auth_try() {
int finished = 0;
TRACE(("enter cli_auth_try"))
@@ -256,33 +262,40 @@ 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;
}
/* A helper for getpass() that exits if the user cancels. The returned

View File

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

View File

@@ -123,6 +123,7 @@ void recv_msg_userauth_pk_ok() {
void cli_buf_put_sign(buffer* buf, sign_key *key, int type,
const unsigned char *data, unsigned int len)
{
#ifdef ENABLE_CLI_AGENTFWD
if (key->source == SIGNKEY_SOURCE_AGENT) {
/* Format the agent signature ourselves, as buf_put_sign would. */
buffer *sigblob;
@@ -133,10 +134,11 @@ void cli_buf_put_sign(buffer* buf, sign_key *key, int type,
sigblob->len);
buf_free(sigblob);
} else {
} else
#endif /* ENABLE_CLI_AGENTFWD */
{
buf_put_sign(buf, key, type, data, len);
}
}
/* TODO: make it take an agent reference to use as well */
@@ -187,11 +189,13 @@ int cli_auth_pubkey() {
TRACE(("enter cli_auth_pubkey"))
#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;

View File

@@ -38,9 +38,10 @@
static void cli_closechansess(struct Channel *channel);
static int cli_initchansess(struct Channel *channel);
static void cli_chansessreq(struct Channel *channel);
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 void cli_tty_setup();
@@ -70,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;
}
@@ -81,14 +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 */
}
void cli_start_send_channel_request(struct Channel *channel,
@@ -374,7 +375,9 @@ static int cli_initchansess(struct Channel *channel) {
if (cli_opts.wantpty) {
cli_tty_setup();
}
channel->read_mangler = cli_escape_handler;
cli_ses.last_char = '\r';
}
return 0; /* Success */
}
@@ -429,3 +432,59 @@ 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;
break;
case 0x1a:
// ctrl-z
cli_tty_cleanup();
kill(getpid(), SIGTSTP);
// after continuation
cli_tty_setup();
cli_ses.winchange = 1;
return 1;
break;
}
return 0;
}
static
void cli_escape_handler(struct Channel *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;
}
}

View File

@@ -42,18 +42,27 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen);
#define MAX_KNOWNHOSTS_LINE 4500
void send_msg_kexdh_init() {
TRACE(("send_msg_kexdh_init()"))
if ((cli_ses.dh_e && cli_ses.dh_x
&& cli_ses.dh_val_algo == ses.newkeys->algo_kex)) {
TRACE(("reusing existing dh_e from first_kex_packet_follows"))
} else {
if (!cli_ses.dh_e || !cli_ses.dh_e) {
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);
}
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);
gen_kexdh_vals(cli_ses.dh_e, cli_ses.dh_x);
cli_ses.dh_val_algo = ses.newkeys->algo_kex;
}
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT);
buf_putmpint(ses.writepayload, cli_ses.dh_e);
encrypt_packet();
ses.requirenext = SSH_MSG_KEXDH_REPLY;
ses.requirenext[0] = SSH_MSG_KEXDH_REPLY;
ses.requirenext[1] = SSH_MSG_KEXINIT;
}
/* Handle a diffie-hellman key exchange reply. */
@@ -98,6 +107,7 @@ void recv_msg_kexdh_reply() {
mp_clear_multi(cli_ses.dh_e, cli_ses.dh_x, NULL);
m_free(cli_ses.dh_e);
m_free(cli_ses.dh_x);
cli_ses.dh_val_algo = DROPBEAR_KEX_NONE;
if (buf_verify(ses.payload, hostkey, ses.hash, SHA1_HASH_SIZE)
!= DROPBEAR_SUCCESS) {
@@ -108,7 +118,8 @@ void recv_msg_kexdh_reply() {
hostkey = NULL;
send_msg_newkeys();
ses.requirenext = SSH_MSG_NEWKEYS;
ses.requirenext[0] = SSH_MSG_NEWKEYS;
ses.requirenext[1] = 0;
TRACE(("leave recv_msg_kexdh_init"))
}
@@ -217,6 +228,11 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
buffer * line = NULL;
int ret;
if (cli_opts.no_hostkey_check) {
fprintf(stderr, "Caution, skipping hostkey check for %s\n", cli_opts.remotehost);
return;
}
hostsfile = open_known_hosts_file(&readonly);
if (!hostsfile) {
ask_to_confirm(keyblob, keybloblen);
@@ -246,7 +262,6 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
/* Compare hostnames */
if (strncmp(cli_opts.remotehost, buf_getptr(line, hostlen),
hostlen) != 0) {
TRACE(("hosts don't match"))
continue;
}
@@ -309,7 +324,6 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
buf_putbytes(line, 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);

View File

@@ -29,7 +29,7 @@
#include "runopts.h"
#include "session.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
@@ -98,8 +98,7 @@ static void cli_dropbear_exit(int exitcode, const char* format, va_list param) {
}
/* Do the cleanup first, since then the terminal will be reset */
cli_session_cleanup();
common_session_cleanup();
session_cleanup();
_dropbear_log(LOG_INFO, fmtbuf, param);

View File

@@ -49,13 +49,12 @@ static void add_netcat(const char *str);
static void printhelp() {
fprintf(stderr, "Dropbear client v%s\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
"Options are:\n"
"-p <remoteport>\n"
"-l <username>\n"
"-t Allocate a pty\n"
@@ -63,7 +62,8 @@ 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"
"-s Request a subsystem (use for sftp)\n"
"-y -y Don't perform any remote host key checking (caution)\n"
"-s Request a subsystem (use by external sftp)\n"
#ifdef ENABLE_CLI_PUBKEY_AUTH
"-i <identityfile> (multiple allowed)\n"
#endif
@@ -86,6 +86,10 @@ static void printhelp() {
#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
#ifdef DEBUG_TRACE
"-v verbose (compiled with DEBUG_TRACE)\n"
#endif
@@ -127,6 +131,7 @@ 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 = list_new();
@@ -140,6 +145,7 @@ void cli_getopts(int argc, char ** argv) {
#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
@@ -147,6 +153,10 @@ void cli_getopts(int argc, char ** argv) {
#endif
#ifndef DISABLE_ZLIB
opts.enable_compress = 1;
#endif
#ifdef ENABLE_USER_ALGO_LIST
opts.cipher_list = NULL;
opts.mac_list = NULL;
#endif
/* not yet
opts.ipv4 = 1;
@@ -205,6 +215,10 @@ void cli_getopts(int argc, char ** argv) {
switch (argv[i][1]) {
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 */
@@ -282,6 +296,14 @@ void cli_getopts(int argc, char ** argv) {
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;
@@ -289,8 +311,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':
@@ -350,11 +374,22 @@ void cli_getopts(int argc, char ** argv) {
/* And now a few sanity checks and setup */
#ifdef ENABLE_USER_ALGO_LIST
parse_ciphers_macs();
#endif
if (host_arg == NULL) {
printhelp();
exit(EXIT_FAILURE);
}
#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";
}
@@ -439,20 +474,31 @@ multihop_passthrough_args() {
int total;
unsigned int len = 0;
m_list_elem *iter;
/* Fill out -i and -W options that make sense for all
/* Fill out -i, -y, -W options that make sense for all
* the intermediate processes */
for (iter = cli_opts.privkeys->first; iter; iter = iter->next)
{
sign_key * key = (sign_key*)iter->item;
len += 3 + strlen(key->filename);
}
len += 20; // space for -W <size>, terminator.
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 %d", opts.recv_window);
int written = snprintf(ret+total, len-total, "-W %d ", opts.recv_window);
total += written;
}
@@ -460,11 +506,17 @@ multihop_passthrough_args() {
{
sign_key * key = (sign_key*)iter->item;
const size_t size = len - total;
int written = snprintf(ret+total, size, "-i %s", key->filename);
int written = snprintf(ret+total, size, "-i %s ", key->filename);
dropbear_assert((unsigned int)written < size);
total += written;
}
/* 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;
}
@@ -565,7 +617,11 @@ static void parse_hostname(const char* orighostarg) {
cli_opts.username = m_strdup(cli_opts.own_user);
}
port = strchr(cli_opts.remotehost, '/');
port = strchr(cli_opts.remotehost, '%');
if (!port) {
// legacy separator
port = strchr(cli_opts.remotehost, '/');
}
if (port) {
*port = '\0';
cli_opts.remoteport = port+1;

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

@@ -41,6 +41,8 @@ static void cli_remoteclosed();
static void cli_sessionloop();
static void cli_session_init();
static void cli_finished();
static void recv_msg_service_accept(void);
static void cli_session_cleanup(void);
struct clientsession cli_ses; /* GLOBAL */
@@ -99,7 +101,7 @@ void cli_session(int sock_in, int sock_out) {
sessinitdone = 1;
/* Exchange identification */
session_identification();
send_session_identification();
send_msg_kexinit();
@@ -109,6 +111,12 @@ void cli_session(int sock_in, int sock_out) {
}
#ifdef USE_KEX_FIRST_FOLLOWS
static void cli_send_kex_first_guess() {
send_msg_kexdh_init();
}
#endif
static void cli_session_init() {
cli_ses.state = STATE_NOTHING;
@@ -133,39 +141,70 @@ static void cli_session_init() {
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;
}
@@ -175,10 +214,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;
}
@@ -188,25 +227,29 @@ 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_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:
#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;
/* keeping stdin open steals input from the terminal and
@@ -223,13 +266,6 @@ static void cli_sessionloop() {
}
}
#ifdef ENABLE_CLI_LOCALTCPFWD
setup_localtcp();
#endif
#ifdef ENABLE_CLI_REMOTETCPFWD
setup_remotetcp();
#endif
#ifdef ENABLE_CLI_NETCAT
if (cli_opts.netcat_host) {
cli_send_netcat_request();
@@ -238,6 +274,14 @@ static void cli_sessionloop() {
if (!cli_opts.no_cmd) {
cli_send_chansess_request();
}
#ifdef ENABLE_CLI_LOCALTCPFWD
setup_localtcp();
#endif
#ifdef ENABLE_CLI_REMOTETCPFWD
setup_remotetcp();
#endif
TRACE(("leave cli_sessionloop: running"))
cli_ses.state = SESSION_RUNNING;
return;
@@ -259,11 +303,11 @@ static void cli_sessionloop() {
break;
}
TRACE(("leave cli_sessionloop: fell out"))
TRACE2(("leave cli_sessionloop: fell out"))
}
void cli_session_cleanup() {
static void cli_session_cleanup(void) {
if (!sessinitdone) {
return;
@@ -281,8 +325,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);

View File

@@ -148,15 +148,26 @@ static void send_msg_global_request_remotetcp(const char *addr, int port) {
/* 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 */
* 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() {
/* Nothing in the packet. We just mark off that we have received the reply,
/* 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 requestd port 0 */
int allocport = buf_getint(ses.payload);
if (allocport > 0) {
dropbear_log(LOG_INFO, "Allocated port %d for remote forward to %s:%d",
allocport, fwd->connectaddr, fwd->connectport);
}
}
return;
}
}

View File

@@ -24,6 +24,7 @@
* SOFTWARE. */
#include "algo.h"
#include "session.h"
#include "dbutil.h"
/* This file (algo.c) organises the ciphers which can be used, and is used to
@@ -45,8 +46,8 @@ static int void_start(int cipher, const unsigned char *IV,
/* Mappings for ciphers, parameters are
{&cipher_desc, keysize, blocksize} */
/* NOTE: if keysize > 2*SHA1_HASH_SIZE, code such as hashkeys()
needs revisiting */
/* Remember to add new ciphers/hashes to regciphers/reghashes too */
#ifdef DROPBEAR_AES256
static const struct dropbear_cipher dropbear_aes256 =
@@ -106,6 +107,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};
@@ -151,11 +160,20 @@ algo_type sshciphers[] = {
#endif
#ifdef DROPBEAR_BLOWFISH
{"blowfish-cbc", 0, &dropbear_blowfish, 1, &dropbear_mode_cbc},
#endif
#ifdef DROPBEAR_NONE_CIPHER
{"none", 0, (void*)&dropbear_nocipher, 1, &dropbear_mode_none},
#endif
{NULL, 0, NULL, 0, NULL}
};
algo_type sshhashes[] = {
#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_SHA1_96_HMAC
{"hmac-sha1-96", 0, &dropbear_sha1_96, 1, NULL},
#endif
@@ -163,7 +181,10 @@ algo_type sshhashes[] = {
{"hmac-sha1", 0, &dropbear_sha1, 1, NULL},
#endif
#ifdef DROPBEAR_MD5_HMAC
{"hmac-md5", 0, &dropbear_md5, 1, NULL},
{"hmac-md5", 0, (void*)&dropbear_md5, 1, NULL},
#endif
#ifdef DROPBEAR_NONE_INTEGRITY
{"none", 0, (void*)&dropbear_nohash, 1, NULL},
#endif
{NULL, 0, NULL, 0, NULL}
};
@@ -195,6 +216,9 @@ algo_type sshhostkey[] = {
algo_type sshkex[] = {
{"diffie-hellman-group1-sha1", DROPBEAR_KEX_DH_GROUP1, NULL, 1, NULL},
{"diffie-hellman-group14-sha1", DROPBEAR_KEX_DH_GROUP14, NULL, 1, NULL},
#ifdef USE_KEXGUESS2
{KEXGUESS2_ALGO_NAME, KEXGUESS2_ALGO_ID, NULL, 1, NULL},
#endif
{NULL, 0, NULL, 0, NULL}
};
@@ -224,6 +248,12 @@ void crypto_init() {
&sha1_desc,
#ifdef DROPBEAR_MD5_HMAC
&md5_desc,
#endif
#ifdef DROPBEAR_SHA2_256_HMAC
&sha256_desc,
#endif
#ifdef DROPBEAR_SHA2_512_HMAC
&sha512_desc,
#endif
NULL
};
@@ -260,8 +290,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[]) {
@@ -282,3 +310,232 @@ void buf_put_algolist(buffer * buf, algo_type localalgos[]) {
buf_putstring(buf, 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)
{
unsigned char * algolist = NULL;
const unsigned 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 unsigned 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(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;
}
static void
try_add_algo(const char *algo_name, algo_type *algos,
const char *algo_desc, algo_type * new_algos, int *num_ret)
{
algo_type *match_algo = check_algo(algo_name, algos);
if (!match_algo)
{
dropbear_log(LOG_WARNING, "This Dropbear program does not support '%s' %s algorithm", algo_name, algo_desc);
return;
}
new_algos[*num_ret] = *match_algo;
(*num_ret)++;
}
/* 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];
/* this has two passes. first we sweep through the given list of
* algorithms and mark them as usable=2 in the algo_type[] array... */
int num_ret = 0;
char *work_list = m_strdup(user_algo_list);
char *last_name = work_list;
char *c;
for (c = work_list; *c; c++)
{
if (*c == ',')
{
*c = '\0';
try_add_algo(last_name, algos, algo_desc, new_algos, &num_ret);
c++;
last_name = c;
}
}
try_add_algo(last_name, algos, algo_desc, new_algos, &num_ret);
m_free(work_list);
new_algos[num_ret].name = NULL;
/* Copy one more as a blank delimiter */
memcpy(algos, new_algos, sizeof(*new_algos) * (num_ret+1));
return num_ret;
}
#endif // ENABLE_USER_ALGO_LIST

View File

@@ -48,7 +48,6 @@ 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);
@@ -93,11 +92,20 @@ void chancleanup() {
TRACE(("leave chancleanup"))
}
static void
chan_initwritebuf(struct Channel *channel)
{
dropbear_assert(channel->writebuf->size == 0 && channel->recvwindow == 0);
cbuf_free(channel->writebuf);
channel->writebuf = cbuf_new(opts.recv_window);
channel->recvwindow = opts.recv_window;
}
/* Create a new channel entry, send a reply confirm or failure */
/* 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) {
@@ -138,6 +146,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;
@@ -151,9 +160,10 @@ struct Channel* newchannel(unsigned int remotechan,
newchan->await_open = 0;
newchan->flushing = 0;
newchan->writebuf = cbuf_new(opts.recv_window);
newchan->writebuf = cbuf_new(0); /* resized later by chan_initwritebuf */
newchan->recvwindow = 0;
newchan->extrabuf = NULL; /* The user code can set it up */
newchan->recvwindow = opts.recv_window;
newchan->recvdonelen = 0;
newchan->recvmaxpacket = RECV_MAX_PAYLOAD_LEN;
@@ -263,14 +273,16 @@ static unsigned int write_pending(struct Channel * channel) {
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;
@@ -281,7 +293,8 @@ static void check_close(struct Channel *channel) {
channel, to ensure that the shell has exited (and the exit status
retrieved) before we close things up. */
if (!channel->type->check_close
|| channel->type->check_close(channel)) {
|| channel->close_handler_done
|| channel->type->check_close(channel)) {
close_allowed = 1;
}
@@ -294,7 +307,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);
}
@@ -323,6 +338,7 @@ static void check_close(struct Channel *channel) {
/* And if we can't receive any more data from them either, close up */
if (channel->readfd == FD_CLOSED
&& channel->writefd == FD_CLOSED
&& (ERRFD_IS_WRITE(channel) || channel->errfd == FD_CLOSED)
&& !channel->sent_close
&& close_allowed
@@ -348,9 +364,10 @@ static void check_in_progress(struct Channel *channel) {
send_msg_channel_open_failure(channel->remotechan,
SSH_OPEN_CONNECT_FAILED, "", "");
close(channel->writefd);
delete_channel(channel);
remove_channel(channel);
TRACE(("leave check_in_progress: fail"))
} else {
chan_initwritebuf(channel);
send_msg_channel_open_confirmation(channel, channel->recvwindow,
channel->recvmaxpacket);
channel->readfd = channel->writefd;
@@ -363,9 +380,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", channel))
if (channel->type->closehandler
&& !channel->close_handler_done) {
channel->type->closehandler(channel);
channel->close_handler_done = 1;
}
CHECKCLEARTOWRITE();
@@ -468,13 +487,13 @@ 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->initconn
||(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);
}
@@ -545,22 +564,18 @@ static void remove_channel(struct Channel * channel) {
TRACE(("CLOSE errfd %d", channel->errfd))
close(channel->errfd);
channel->typedata = NULL;
delete_channel(channel);
TRACE(("leave remove_channel"))
}
/* Remove a channel entry */
static void delete_channel(struct Channel *channel) {
if (!channel->close_handler_done
&& channel->type->closehandler) {
channel->type->closehandler(channel);
channel->close_handler_done = 1;
}
ses.channels[channel->index] = NULL;
m_free(channel);
ses.chancount--;
}
TRACE(("leave remove_channel"))
}
/* Handle channel specific requests, passing off to corresponding handlers
* such as chansession or x11fwd */
@@ -568,16 +583,17 @@ void recv_msg_channel_request() {
struct Channel *channel;
TRACE(("enter recv_msg_channel_request"))
channel = getchannel();
TRACE(("enter recv_msg_channel_request %p", channel))
if (channel->sent_close) {
TRACE(("leave recv_msg_channel_request: already closed channel"))
return;
}
if (channel->type->reqhandler) {
if (channel->type->reqhandler
&& !channel->close_handler_done) {
channel->type->reqhandler(channel);
} else {
send_msg_channel_failure(channel);
@@ -616,7 +632,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;
@@ -634,6 +650,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
@@ -641,11 +658,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);
@@ -691,7 +720,7 @@ void common_recv_msg_channel_data(struct Channel *channel, int fd,
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. */
@@ -829,12 +858,14 @@ void recv_msg_channel_open() {
}
if (ret > 0) {
errtype = ret;
delete_channel(channel);
remove_channel(channel);
TRACE(("inithandler returned failure %d", ret))
goto failure;
}
}
chan_initwritebuf(channel);
/* success */
send_msg_channel_open_confirmation(channel, channel->recvwindow,
channel->recvmaxpacket);
@@ -973,6 +1004,10 @@ 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 */
chan_initwritebuf(chan);
/* set fd non-blocking */
setnonblocking(fd);

View File

@@ -80,9 +80,10 @@ static const unsigned char dh_p_14[DH_P_14_LEN] = {
static const int DH_G_VAL = 2;
static void kexinitialise();
void gen_new_keys();
static void gen_new_keys();
#ifndef DISABLE_ZLIB
static void gen_new_zstreams();
static void gen_new_zstream_recv();
static void gen_new_zstream_trans();
#endif
static void read_kex_algos();
/* helper function for gen_new_keys */
@@ -118,6 +119,7 @@ void send_msg_kexinit() {
/* mac_algorithms_server_to_client */
buf_put_algolist(ses.writepayload, sshhashes);
/* compression_algorithms_client_to_server */
buf_put_algolist(ses.writepayload, ses.compress_algos);
@@ -130,8 +132,8 @@ void send_msg_kexinit() {
/* languages_server_to_client */
buf_putstring(ses.writepayload, "", 0);
/* first_kex_packet_follows - unimplemented for now */
buf_putbyte(ses.writepayload, 0x00);
/* first_kex_packet_follows */
buf_putbyte(ses.writepayload, (ses.send_kex_first_guess != NULL));
/* reserved unit32 */
buf_putint(ses.writepayload, 0);
@@ -143,16 +145,60 @@ void send_msg_kexinit() {
encrypt_packet();
ses.dataallowed = 0; /* don't send other packets during kex */
ses.kexstate.sentkexinit = 1;
ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
if (ses.send_kex_first_guess) {
ses.newkeys->algo_kex = sshkex[0].val;
ses.newkeys->algo_hostkey = sshhostkey[0].val;
ses.send_kex_first_guess();
}
TRACE(("DATAALLOWED=0"))
TRACE(("-> KEXINIT"))
ses.kexstate.sentkexinit = 1;
}
/* *** NOTE regarding (send|recv)_msg_newkeys ***
* Changed by mihnea from the original kex.c to set dataallowed after a
* completed key exchange, no matter the order in which it was performed.
* This enables client mode without affecting server functionality.
*/
static void switch_keys() {
TRACE2(("enter switch_keys"))
if (!(ses.kexstate.sentkexinit && ses.kexstate.recvkexinit)) {
dropbear_exit("Unexpected newkeys message");
}
if (!ses.keys) {
ses.keys = m_malloc(sizeof(*ses.newkeys));
}
if (ses.kexstate.recvnewkeys && ses.newkeys->recv.valid) {
TRACE(("switch_keys recv"))
#ifndef DISABLE_ZLIB
gen_new_zstream_recv();
#endif
ses.keys->recv = ses.newkeys->recv;
m_burn(&ses.newkeys->recv, sizeof(ses.newkeys->recv));
ses.newkeys->recv.valid = 0;
}
if (ses.kexstate.sentnewkeys && ses.newkeys->trans.valid) {
TRACE(("switch_keys trans"))
#ifndef DISABLE_ZLIB
gen_new_zstream_trans();
#endif
ses.keys->trans = ses.newkeys->trans;
m_burn(&ses.newkeys->trans, sizeof(ses.newkeys->trans));
ses.newkeys->trans.valid = 0;
}
if (ses.kexstate.sentnewkeys && ses.kexstate.recvnewkeys)
{
TRACE(("switch_keys done"))
ses.keys->algo_kex = ses.newkeys->algo_kex;
ses.keys->algo_hostkey = ses.newkeys->algo_hostkey;
ses.keys->allow_compress = 0;
m_free(ses.newkeys);
ses.newkeys = NULL;
kexinitialise();
}
TRACE2(("leave switch_keys"))
}
/* Bring new keys into use after a key exchange, and let the client know*/
void send_msg_newkeys() {
@@ -163,44 +209,25 @@ void send_msg_newkeys() {
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_NEWKEYS);
encrypt_packet();
/* set up our state */
if (ses.kexstate.recvnewkeys) {
TRACE(("while RECVNEWKEYS=1"))
gen_new_keys();
kexinitialise(); /* we've finished with this kex */
TRACE((" -> DATAALLOWED=1"))
ses.dataallowed = 1; /* we can send other packets again now */
ses.kexstate.donefirstkex = 1;
} else {
ses.kexstate.sentnewkeys = 1;
TRACE(("SENTNEWKEYS=1"))
}
ses.kexstate.sentnewkeys = 1;
ses.kexstate.donefirstkex = 1;
ses.dataallowed = 1; /* we can send other packets again now */
gen_new_keys();
switch_keys();
TRACE(("-> MSG_NEWKEYS"))
TRACE(("leave send_msg_newkeys"))
}
/* Bring the new keys into use after a key exchange */
void recv_msg_newkeys() {
TRACE(("<- MSG_NEWKEYS"))
TRACE(("enter recv_msg_newkeys"))
/* simply check if we've sent SSH_MSG_NEWKEYS, and if so,
* switch to the new keys */
if (ses.kexstate.sentnewkeys) {
TRACE(("while SENTNEWKEYS=1"))
gen_new_keys();
kexinitialise(); /* we've finished with this kex */
TRACE((" -> DATAALLOWED=1"))
ses.dataallowed = 1; /* we can send other packets again now */
ses.kexstate.donefirstkex = 1;
} else {
TRACE(("RECVNEWKEYS=1"))
ses.kexstate.recvnewkeys = 1;
}
ses.kexstate.recvnewkeys = 1;
switch_keys();
TRACE(("leave recv_msg_newkeys"))
}
@@ -235,11 +262,13 @@ static void kexinitialise() {
ses.kexstate.sentnewkeys = 0;
/* first_packet_follows */
ses.kexstate.firstfollows = 0;
ses.kexstate.them_firstfollows = 0;
ses.kexstate.datatrans = 0;
ses.kexstate.datarecv = 0;
ses.kexstate.our_first_follows_matches = 0;
ses.kexstate.lastkextime = time(NULL);
}
@@ -248,26 +277,28 @@ static void kexinitialise() {
* already initialised hash_state hs, which should already have processed
* the dh_K and hash, since these are common. X is the letter 'A', 'B' etc.
* out must have at least min(SHA1_HASH_SIZE, outlen) bytes allocated.
* The output will only be expanded once, as we are assured that
* outlen <= 2*SHA1_HASH_SIZE for all known hashes.
*
* See Section 7.2 of rfc4253 (ssh transport) for details */
static void hashkeys(unsigned char *out, int outlen,
const hash_state * hs, const unsigned char X) {
hash_state hs2;
unsigned char k2[SHA1_HASH_SIZE]; /* used to extending */
int offset;
memcpy(&hs2, hs, sizeof(hash_state));
sha1_process(&hs2, &X, 1);
sha1_process(&hs2, ses.session_id, SHA1_HASH_SIZE);
sha1_done(&hs2, out);
if (SHA1_HASH_SIZE < outlen) {
for (offset = SHA1_HASH_SIZE;
offset < outlen;
offset += SHA1_HASH_SIZE)
{
/* need to extend */
unsigned char k2[SHA1_HASH_SIZE];
memcpy(&hs2, hs, sizeof(hash_state));
sha1_process(&hs2, out, SHA1_HASH_SIZE);
sha1_process(&hs2, out, offset);
sha1_done(&hs2, k2);
memcpy(&out[SHA1_HASH_SIZE], k2, outlen - SHA1_HASH_SIZE);
memcpy(&out[offset], k2, MIN(outlen - offset, SHA1_HASH_SIZE));
}
}
@@ -278,8 +309,7 @@ static void hashkeys(unsigned char *out, int outlen,
* ses.newkeys is the new set of keys which are generated, these are only
* taken into use after both sides have sent a newkeys message */
/* Originally from kex.c, generalized for cli/svr mode --mihnea */
void gen_new_keys() {
static void gen_new_keys() {
unsigned char C2S_IV[MAX_IV_LEN];
unsigned char C2S_key[MAX_KEY_LEN];
@@ -291,7 +321,6 @@ void gen_new_keys() {
hash_state hs;
unsigned int C2S_keysize, S2C_keysize;
char mactransletter, macrecvletter; /* Client or server specific */
int recv_cipher = 0, trans_cipher = 0;
TRACE(("enter gen_new_keys"))
/* the dh_K and hash are the start of all hashes, we make use of that */
@@ -328,43 +357,50 @@ void gen_new_keys() {
hashkeys(C2S_key, C2S_keysize, &hs, 'C');
hashkeys(S2C_key, S2C_keysize, &hs, 'D');
recv_cipher = find_cipher(ses.newkeys->recv.algo_crypt->cipherdesc->name);
if (recv_cipher < 0)
dropbear_exit("Crypto error");
if (ses.newkeys->recv.crypt_mode->start(recv_cipher,
recv_IV, recv_key,
ses.newkeys->recv.algo_crypt->keysize, 0,
&ses.newkeys->recv.cipher_state) != CRYPT_OK) {
dropbear_exit("Crypto error");
if (ses.newkeys->recv.algo_crypt->cipherdesc != NULL) {
int recv_cipher = find_cipher(ses.newkeys->recv.algo_crypt->cipherdesc->name);
if (recv_cipher < 0)
dropbear_exit("Crypto error");
if (ses.newkeys->recv.crypt_mode->start(recv_cipher,
recv_IV, recv_key,
ses.newkeys->recv.algo_crypt->keysize, 0,
&ses.newkeys->recv.cipher_state) != CRYPT_OK) {
dropbear_exit("Crypto error");
}
}
trans_cipher = find_cipher(ses.newkeys->trans.algo_crypt->cipherdesc->name);
if (trans_cipher < 0)
dropbear_exit("Crypto error");
if (ses.newkeys->trans.crypt_mode->start(trans_cipher,
trans_IV, trans_key,
ses.newkeys->trans.algo_crypt->keysize, 0,
&ses.newkeys->trans.cipher_state) != CRYPT_OK) {
dropbear_exit("Crypto error");
if (ses.newkeys->trans.algo_crypt->cipherdesc != NULL) {
int trans_cipher = find_cipher(ses.newkeys->trans.algo_crypt->cipherdesc->name);
if (trans_cipher < 0)
dropbear_exit("Crypto error");
if (ses.newkeys->trans.crypt_mode->start(trans_cipher,
trans_IV, trans_key,
ses.newkeys->trans.algo_crypt->keysize, 0,
&ses.newkeys->trans.cipher_state) != CRYPT_OK) {
dropbear_exit("Crypto error");
}
}
/* MAC keys */
hashkeys(ses.newkeys->trans.mackey,
ses.newkeys->trans.algo_mac->keysize, &hs, mactransletter);
hashkeys(ses.newkeys->recv.mackey,
ses.newkeys->recv.algo_mac->keysize, &hs, macrecvletter);
ses.newkeys->trans.hash_index = find_hash(ses.newkeys->trans.algo_mac->hashdesc->name),
ses.newkeys->recv.hash_index = find_hash(ses.newkeys->recv.algo_mac->hashdesc->name),
#ifndef DISABLE_ZLIB
gen_new_zstreams();
#endif
/* Switch over to the new keys */
m_burn(ses.keys, sizeof(struct key_context));
m_free(ses.keys);
ses.keys = ses.newkeys;
ses.newkeys = NULL;
if (ses.newkeys->trans.algo_mac->hashdesc != NULL) {
hashkeys(ses.newkeys->trans.mackey,
ses.newkeys->trans.algo_mac->keysize, &hs, mactransletter);
ses.newkeys->trans.hash_index = find_hash(ses.newkeys->trans.algo_mac->hashdesc->name);
}
if (ses.newkeys->recv.algo_mac->hashdesc != NULL) {
hashkeys(ses.newkeys->recv.mackey,
ses.newkeys->recv.algo_mac->keysize, &hs, macrecvletter);
ses.newkeys->recv.hash_index = find_hash(ses.newkeys->recv.algo_mac->hashdesc->name);
}
/* Ready to switch over */
ses.newkeys->trans.valid = 1;
ses.newkeys->recv.valid = 1;
m_burn(C2S_IV, sizeof(C2S_IV));
m_burn(C2S_key, sizeof(C2S_key));
m_burn(S2C_IV, sizeof(S2C_IV));
m_burn(S2C_key, sizeof(S2C_key));
TRACE(("leave gen_new_keys"))
}
@@ -385,7 +421,7 @@ int is_compress_recv() {
/* Set up new zlib compression streams, close the old ones. Only
* called from gen_new_keys() */
static void gen_new_zstreams() {
static void gen_new_zstream_recv() {
/* create new zstreams */
if (ses.newkeys->recv.algo_comp == DROPBEAR_COMP_ZLIB
@@ -400,6 +436,17 @@ static void gen_new_zstreams() {
} else {
ses.newkeys->recv.zstream = NULL;
}
/* clean up old keys */
if (ses.keys->recv.zstream != NULL) {
if (inflateEnd(ses.keys->recv.zstream) == Z_STREAM_ERROR) {
/* Z_DATA_ERROR is ok, just means that stream isn't ended */
dropbear_exit("Crypto error");
}
m_free(ses.keys->recv.zstream);
}
}
static void gen_new_zstream_trans() {
if (ses.newkeys->trans.algo_comp == DROPBEAR_COMP_ZLIB
|| ses.newkeys->trans.algo_comp == DROPBEAR_COMP_ZLIB_DELAY) {
@@ -417,14 +464,6 @@ static void gen_new_zstreams() {
ses.newkeys->trans.zstream = NULL;
}
/* clean up old keys */
if (ses.keys->recv.zstream != NULL) {
if (inflateEnd(ses.keys->recv.zstream) == Z_STREAM_ERROR) {
/* Z_DATA_ERROR is ok, just means that stream isn't ended */
dropbear_exit("Crypto error");
}
m_free(ses.keys->recv.zstream);
}
if (ses.keys->trans.zstream != NULL) {
if (deflateEnd(ses.keys->trans.zstream) == Z_STREAM_ERROR) {
/* Z_DATA_ERROR is ok, just means that stream isn't ended */
@@ -507,7 +546,7 @@ void recv_msg_kexinit() {
buf_putstring(ses.kexhashbuf,
ses.transkexinit->data, ses.transkexinit->len);
ses.requirenext = SSH_MSG_KEXDH_INIT;
ses.requirenext[0] = SSH_MSG_KEXDH_INIT;
}
buf_free(ses.transkexinit);
@@ -540,7 +579,7 @@ void gen_kexdh_vals(mp_int *dh_pub, mp_int *dh_priv) {
DEF_MP_INT(dh_q);
DEF_MP_INT(dh_g);
TRACE(("enter send_msg_kexdh_reply"))
TRACE(("enter gen_kexdh_vals"))
m_mp_init_multi(&dh_g, &dh_p, &dh_q, NULL);
@@ -663,20 +702,27 @@ static void read_kex_algos() {
buf_incrpos(ses.payload, 16); /* start after the cookie */
ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
memset(ses.newkeys, 0x0, sizeof(*ses.newkeys));
#ifdef USE_KEXGUESS2
enum kexguess2_used kexguess2 = KEXGUESS2_LOOK;
#else
enum kexguess2_used kexguess2 = KEXGUESS2_NO;
#endif
/* kex_algorithms */
algo = ses.buf_match_algo(ses.payload, sshkex, &goodguess);
algo = buf_match_algo(ses.payload, sshkex, &kexguess2, &goodguess);
allgood &= goodguess;
if (algo == NULL) {
if (algo == NULL || algo->val == KEXGUESS2_ALGO_ID) {
erralgo = "kex";
goto error;
}
TRACE(("kexguess2 %d", kexguess2))
TRACE(("kex algo %s", algo->name))
ses.newkeys->algo_kex = algo->val;
/* server_host_key_algorithms */
algo = ses.buf_match_algo(ses.payload, sshhostkey, &goodguess);
algo = buf_match_algo(ses.payload, sshhostkey, &kexguess2, &goodguess);
allgood &= goodguess;
if (algo == NULL) {
erralgo = "hostkey";
@@ -686,7 +732,7 @@ static void read_kex_algos() {
ses.newkeys->algo_hostkey = algo->val;
/* encryption_algorithms_client_to_server */
c2s_cipher_algo = ses.buf_match_algo(ses.payload, sshciphers, &goodguess);
c2s_cipher_algo = buf_match_algo(ses.payload, sshciphers, NULL, NULL);
if (c2s_cipher_algo == NULL) {
erralgo = "enc c->s";
goto error;
@@ -694,7 +740,7 @@ static void read_kex_algos() {
TRACE(("enc c2s is %s", c2s_cipher_algo->name))
/* encryption_algorithms_server_to_client */
s2c_cipher_algo = ses.buf_match_algo(ses.payload, sshciphers, &goodguess);
s2c_cipher_algo = buf_match_algo(ses.payload, sshciphers, NULL, NULL);
if (s2c_cipher_algo == NULL) {
erralgo = "enc s->c";
goto error;
@@ -702,7 +748,7 @@ static void read_kex_algos() {
TRACE(("enc s2c is %s", s2c_cipher_algo->name))
/* mac_algorithms_client_to_server */
c2s_hash_algo = ses.buf_match_algo(ses.payload, sshhashes, &goodguess);
c2s_hash_algo = buf_match_algo(ses.payload, sshhashes, NULL, NULL);
if (c2s_hash_algo == NULL) {
erralgo = "mac c->s";
goto error;
@@ -710,7 +756,7 @@ static void read_kex_algos() {
TRACE(("hash c2s is %s", c2s_hash_algo->name))
/* mac_algorithms_server_to_client */
s2c_hash_algo = ses.buf_match_algo(ses.payload, sshhashes, &goodguess);
s2c_hash_algo = buf_match_algo(ses.payload, sshhashes, NULL, NULL);
if (s2c_hash_algo == NULL) {
erralgo = "mac s->c";
goto error;
@@ -718,7 +764,7 @@ static void read_kex_algos() {
TRACE(("hash s2c is %s", s2c_hash_algo->name))
/* compression_algorithms_client_to_server */
c2s_comp_algo = ses.buf_match_algo(ses.payload, ses.compress_algos, &goodguess);
c2s_comp_algo = buf_match_algo(ses.payload, ses.compress_algos, NULL, NULL);
if (c2s_comp_algo == NULL) {
erralgo = "comp c->s";
goto error;
@@ -726,7 +772,7 @@ static void read_kex_algos() {
TRACE(("hash c2s is %s", c2s_comp_algo->name))
/* compression_algorithms_server_to_client */
s2c_comp_algo = ses.buf_match_algo(ses.payload, ses.compress_algos, &goodguess);
s2c_comp_algo = buf_match_algo(ses.payload, ses.compress_algos, NULL, NULL);
if (s2c_comp_algo == NULL) {
erralgo = "comp s->c";
goto error;
@@ -739,9 +785,10 @@ static void read_kex_algos() {
/* languages_server_to_client */
buf_eatstring(ses.payload);
/* first_kex_packet_follows */
/* their first_kex_packet_follows */
if (buf_getbool(ses.payload)) {
ses.kexstate.firstfollows = 1;
TRACE(("them kex firstfollows. allgood %d", allgood))
ses.kexstate.them_firstfollows = 1;
/* if the guess wasn't good, we ignore the packet sent */
if (!allgood) {
ses.ignorenext = 1;
@@ -784,6 +831,11 @@ static void read_kex_algos() {
/* reserved for future extensions */
buf_getint(ses.payload);
if (ses.send_kex_first_guess && allgood) {
TRACE(("our_first_follows_matches 1"))
ses.kexstate.our_first_follows_matches = 1;
}
return;
error:

View File

@@ -28,6 +28,8 @@
#include "buffer.h"
#include "dbutil.h"
#include "auth.h"
#include "algo.h"
#include "random.h"
runopts opts; /* GLOBAL */
@@ -44,6 +46,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 +60,48 @@ 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

View File

@@ -33,12 +33,12 @@
#include "random.h"
#include "kex.h"
#include "channel.h"
#include "atomicio.h"
#include "runopts.h"
static void checktimeouts();
static long select_timeout();
static int ident_readln(int fd, char* buf, int count);
static void read_session_identification();
struct sshsession ses; /* GLOBAL */
@@ -49,8 +49,6 @@ 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_in, int sock_out) {
@@ -84,7 +82,7 @@ void common_session_init(int sock_in, int sock_out) {
initqueue(&ses.writequeue);
ses.requirenext = SSH_MSG_KEXINIT;
ses.requirenext[0] = SSH_MSG_KEXINIT;
ses.dataallowed = 1; /* we can send data until we actually
send the SSH_MSG_KEXINIT */
ses.ignorenext = 0;
@@ -141,7 +139,10 @@ void session_loop(void(*loophandler)()) {
FD_ZERO(&writefd);
FD_ZERO(&readfd);
dropbear_assert(ses.payload == NULL);
if (ses.sock_in != -1) {
/* during initial setup we flush out the KEXINIT packet before
* attempting to read the remote version string, which might block */
if (ses.sock_in != -1 && (ses.remoteident || isempty(&ses.writequeue))) {
FD_SET(ses.sock_in, &readfd);
}
if (ses.sock_out != -1 && !isempty(&ses.writequeue)) {
@@ -195,7 +196,12 @@ void session_loop(void(*loophandler)()) {
if (ses.sock_in != -1) {
if (FD_ISSET(ses.sock_in, &readfd)) {
read_packet();
if (!ses.remoteident) {
/* blocking read of the version string */
read_session_identification();
} else {
read_packet();
}
}
/* Process the decrypted packet. After this, the read buffer
@@ -225,7 +231,7 @@ void session_loop(void(*loophandler)()) {
}
/* clean up a session on exit */
void common_session_cleanup() {
void session_cleanup() {
TRACE(("enter session_cleanup"))
@@ -234,6 +240,10 @@ void common_session_cleanup() {
TRACE(("leave session_cleanup: !sessinitdone"))
return;
}
if (ses.extra_session_cleanup) {
ses.extra_session_cleanup();
}
m_free(ses.session_id);
m_burn(ses.keys, sizeof(struct key_context));
@@ -244,21 +254,20 @@ void common_session_cleanup() {
TRACE(("leave session_cleanup"))
}
void send_session_identification() {
buffer *writebuf = buf_new(strlen(LOCAL_IDENT "\r\n") + 1);
buf_putbytes(writebuf, LOCAL_IDENT "\r\n", strlen(LOCAL_IDENT "\r\n"));
buf_putbyte(writebuf, 0x0); // packet type
buf_setpos(writebuf, 0);
enqueue(&ses.writequeue, writebuf);
}
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_out, LOCAL_IDENT "\r\n",
strlen(LOCAL_IDENT "\r\n")) == DROPBEAR_FAILURE) {
ses.remoteclosed();
}
/* If they send more than 50 lines, something is wrong */
for (i = 0; i < 50; i++) {
len = ident_readln(ses.sock_in, linebuf, sizeof(linebuf));
@@ -453,6 +462,20 @@ void fill_passwd(const char* username) {
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);
ses.authstate.pw_passwd = m_strdup(pw->pw_passwd);
{
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);
}
}

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

601
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-04-24'
# 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."
@@ -144,7 +137,7 @@ UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
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 +163,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 +173,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
fi
;;
*)
os=netbsd
os=netbsd
;;
esac
# The OS release
@@ -201,6 +194,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 +220,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 +266,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 +295,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 +324,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 +394,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 +480,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 +494,7 @@ EOF
else
echo i586-dg-dgux${UNAME_RELEASE}
fi
exit ;;
exit ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
echo m88k-dolphin-sysv3
exit ;;
@@ -532,7 +551,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 +594,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 +659,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 +730,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 +769,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 +788,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
@@ -829,85 +862,13 @@ EOF
i*86:Minix:*:*)
echo ${UNAME_MACHINE}-pc-minix
exit ;;
arm*:Linux:*:*)
aarch64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
avr32*:Linux:*:*)
aarch64_be:Linux:*:*)
UNAME_MACHINE=aarch64_be
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
exit ;;
alpha:Linux:*:*)
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
EV5) UNAME_MACHINE=alphaev5 ;;
@@ -917,11 +878,101 @@ 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
esac
objdump --private-headers /bin/sh | grep -q ld.so.1
if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
exit ;;
arc:Linux:*:* | arceb:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
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-gnu
else
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
echo ${UNAME_MACHINE}-unknown-linux-gnueabi
else
echo ${UNAME_MACHINE}-unknown-linux-gnueabihf
fi
fi
exit ;;
avr32*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
cris:Linux:*:*)
echo ${UNAME_MACHINE}-axis-linux-gnu
exit ;;
crisv32:Linux:*:*)
echo ${UNAME_MACHINE}-axis-linux-gnu
exit ;;
frv:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
hexagon:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
i*86:Linux:*:*)
LIBC=gnu
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#ifdef __dietlibc__
LIBC=dietlibc
#endif
#else
#include <features.h>
#ifdef __UCLIBC__
LIBC=uclibc
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
exit ;;
ia64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
m32r*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
m68*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
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-gnu"; exit; }
;;
or1k:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
or32:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
padre:Linux:*:*)
echo sparc-unknown-linux-gnu
exit ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
echo hppa64-unknown-linux-gnu
exit ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
@@ -930,14 +981,17 @@ EOF
*) echo hppa-unknown-linux-gnu ;;
esac
exit ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
echo hppa64-unknown-linux-gnu
ppc64:Linux:*:*)
echo powerpc64-unknown-linux-gnu
exit ;;
ppc:Linux:*:*)
echo powerpc-unknown-linux-gnu
exit ;;
s390:Linux:*:* | s390x:Linux:*:*)
echo ${UNAME_MACHINE}-ibm-linux
exit ;;
sh64*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
sh*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
@@ -945,78 +999,20 @@ EOF
sparc:Linux:*:* | sparc64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
tile*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
vax:Linux:*:*)
echo ${UNAME_MACHINE}-dec-linux-gnu
exit ;;
x86_64:Linux:*:*)
echo x86_64-unknown-linux-gnu
exit ;;
xtensa:Linux:*:*)
echo xtensa-unknown-linux-gnu
exit ;;
i*86:Linux:*:*)
# The BFD linker knows what the default object file format is, so
# first see if it will tell us. cd to the root directory to prevent
# problems with other programs or directories called `ld' in the path.
# Set LC_ALL=C to ensure ld outputs messages in English.
ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
| sed -ne '/supported targets:/!d
s/[ ][ ]*/ /g
s/.*supported targets: *//
s/ .*//
p'`
case "$ld_supported_targets" in
elf32-i386)
TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
;;
a.out-i386-linux)
echo "${UNAME_MACHINE}-pc-linux-gnuaout"
exit ;;
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; }
;;
test -r /lib/libc.so && od -An -S13 /lib/libc.so | grep -q __uClibc_main && LIBC=uclibc
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
xtensa*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
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 +1020,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 +1041,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 +1056,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 +1084,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 +1125,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 +1149,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 +1169,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 +1198,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 +1212,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 ;;
@@ -1230,6 +1245,16 @@ EOF
*:Darwin:*:*)
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
case $UNAME_PROCESSOR in
i386)
eval $set_cc_for_build
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
UNAME_PROCESSOR="x86_64"
fi
fi ;;
unknown) UNAME_PROCESSOR=powerpc ;;
esac
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
@@ -1245,7 +1270,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 +1318,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 +1339,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 +1364,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 +1502,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

368
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-04-24'
# 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,34 @@ 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 \
| 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 \
| 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 +286,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 | picochip)
basic_machine=$basic_machine-unknown
os=-none
;;
@@ -300,6 +334,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 +363,37 @@ 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-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* \
| 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-* \
| 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 +404,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 +456,7 @@ case $basic_machine in
basic_machine=a29k-amd
os=-udi
;;
abacus)
abacus)
basic_machine=abacus-unknown
;;
adobe68k)
@@ -435,6 +502,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 +514,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 +571,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 +610,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 +729,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 +767,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 +786,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
os=-mingw32
;;
mingw32ce)
basic_machine=arm-unknown
os=-mingw32ce
;;
miniframe)
basic_machine=m68000-convergent
;;
@@ -711,10 +829,18 @@ case $basic_machine in
ms1-*)
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
;;
msys)
basic_machine=i386-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 +905,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 +941,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 +993,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 +1021,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 +1094,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 +1153,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 +1224,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 +1235,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 +1277,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 +1324,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 +1350,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 +1374,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 +1413,7 @@ case $os in
-opened*)
os=-openedition
;;
-os400*)
-os400*)
os=-os400
;;
-wince*)
@@ -1310,7 +1462,7 @@ case $os in
-sinix*)
os=-sysv4
;;
-tpf*)
-tpf*)
os=-tpf
;;
-triton*)
@@ -1346,12 +1498,14 @@ case $os in
-aros*)
os=-aros
;;
-kaos*)
os=-kaos
;;
-zvmoe)
os=-zvmoe
;;
-dicos*)
os=-dicos
;;
-nacl*)
;;
-none)
;;
*)
@@ -1374,10 +1528,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 +1543,20 @@ case $basic_machine in
arm*-semi)
os=-aout
;;
c4x-* | tic4x-*)
os=-coff
c4x-* | tic4x-*)
os=-coff
;;
hexagon-*)
os=-elf
;;
tic54x-*)
os=-coff
;;
tic55x-*)
os=-coff
;;
tic6x-*)
os=-coff
;;
# This must come before the *-dec entry.
pdp10-*)
@@ -1410,14 +1576,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 +1589,9 @@ case $basic_machine in
mips*-*)
os=-elf
;;
or1k-*)
os=-elf
;;
or32-*)
os=-coff
;;
@@ -1444,7 +1610,7 @@ case $basic_machine in
*-ibm)
os=-aix
;;
*-knuth)
*-knuth)
os=-mmixware
;;
*-wec)
@@ -1549,7 +1715,7 @@ case $basic_machine in
-sunos*)
vendor=sun
;;
-aix*)
-cnk*|-aix*)
vendor=ibm
;;
-beos*)

View File

@@ -211,7 +211,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
@@ -616,7 +616,7 @@ 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 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))

View File

@@ -1,6 +1,6 @@
.TH dbclient 1
.SH NAME
dbclient \- lightweight SSH2 client
dbclient \- lightweight SSH client
.SH SYNOPSIS
.B dbclient
[\-Tt] [\-p
@@ -15,26 +15,26 @@ dbclient \- lightweight SSH2 client
.B dbclient
[
.I args ]
.I [user1]@host1[/port1],[user2]@host2[/port2],...
.I [user1]@host1[%port1],[user2]@host2[%port2],...
.SH DESCRIPTION
.B dbclient
is a SSH 2 client designed to be small enough to be used in small memory
is a SSH client designed to be small enough to be used in small memory
environments, while still being functional and secure enough for general use.
.SH OPTIONS
.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).
.TP
.B \-L [\fIlistenaddress\fR]:\fIlistenport\fR:\fIhost\fR:\fIport\fR
Local port forwarding.
@@ -61,10 +61,10 @@ Login as
on the remote host.
.TP
.B \-t
Allocate a pty.
Allocate a PTY.
.TP
.B \-T
Don't allocate a pty.
Don't allocate a PTY.
.TP
.B \-N
Don't request a remote shell or run any commands. Any command arguments are ignored.
@@ -80,7 +80,8 @@ 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
@@ -111,12 +112,22 @@ comparing saved hostkeys.
"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 \-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
.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 slash (eg matt@martello/44 ).
A port for a host can be specified with a hash (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
@@ -126,6 +137,11 @@ Note that hostnames are resolved by the prior hop (so "canyons" would be resolve
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
@@ -146,6 +162,6 @@ 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

View File

@@ -66,7 +66,7 @@ int main(int argc, char ** argv) {
#endif
}
fprintf(stderr, "Dropbear multi-purpose version %s\n"
fprintf(stderr, "Dropbear SSH multi-purpose v%s\n"
"Make a symlink pointing at this binary with one of the following names:\n"
#ifdef DBMULTI_dropbear
"'dropbear' - the Dropbear server\n"

View File

@@ -57,11 +57,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;
@@ -138,15 +138,39 @@ void dropbear_log(int priority, const char* format, ...) {
#ifdef DEBUG_TRACE
void dropbear_trace(const char* format, ...) {
va_list param;
struct timeval tv;
if (!debug_trace) {
return;
}
gettimeofday(&tv, NULL);
va_start(param, format);
fprintf(stderr, "TRACE (%d): ", getpid());
fprintf(stderr, "TRACE (%d) %d.%d: ", getpid(), tv.tv_sec, tv.tv_usec);
vfprintf(stderr, format, param);
fprintf(stderr, "\n");
va_end(param);
}
void dropbear_trace2(const char* format, ...) {
static int trace_env = -1;
va_list param;
struct timeval tv;
if (trace_env == -1) {
trace_env = getenv("DROPBEAR_TRACE2") ? 1 : 0;
}
if (!(debug_trace && trace_env)) {
return;
}
gettimeofday(&tv, NULL);
va_start(param, format);
fprintf(stderr, "TRACE2 (%d) %d.%d: ", getpid(), tv.tv_sec, tv.tv_usec);
vfprintf(stderr, format, param);
fprintf(stderr, "\n");
va_end(param);
@@ -161,10 +185,12 @@ static void set_sock_priority(int sock) {
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. */
/* set the TOS bit for either ipv4 or ipv6 */
#ifdef IPTOS_LOWDELAY
val = IPTOS_LOWDELAY;
#if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS)
setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS, (void*)&val, sizeof(val));
#endif
setsockopt(sock, IPPROTO_IP, IP_TOS, (void*)&val, sizeof(val));
#endif
@@ -254,6 +280,16 @@ int dropbear_listen(const char* address, const char* port,
linger.l_linger = 5;
setsockopt(sock, SOL_SOCKET, SO_LINGER, (void*)&linger, sizeof(linger));
#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
if (res->ai_family == AF_INET6) {
int on = 1;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
&on, sizeof(on)) == -1) {
dropbear_log(LOG_WARNING, "Couldn't set IPV6_V6ONLY");
}
}
#endif
set_sock_priority(sock);
if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
@@ -311,6 +347,7 @@ int connect_unix(const char* path) {
}
if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
TRACE(("Failed to connect to '%s' socket", path))
m_close(fd);
return -1;
}
return fd;
@@ -430,7 +467,7 @@ int spawn_command(void(*exec_fn)(void *user_data), void *exec_data,
return DROPBEAR_FAILURE;
}
#ifdef __uClinux__
#ifdef USE_VFORK
pid = vfork();
#else
pid = fork();
@@ -712,8 +749,6 @@ int buf_getline(buffer * line, FILE * authfile) {
int c = EOF;
TRACE(("enter buf_getline"))
buf_setpos(line, 0);
buf_setlen(line, 0);
@@ -737,10 +772,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;
}
@@ -787,12 +820,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;
@@ -817,7 +844,7 @@ void m_burn(void *data, unsigned int len) {
if (data == NULL)
return;
while (len--) {
*p++ = 0x66;
*p++ = 0x0;
}
}
@@ -857,3 +884,16 @@ int m_str_to_uint(const char* str, unsigned int *val) {
return DROPBEAR_SUCCESS;
}
}
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;
}

View File

@@ -33,18 +33,33 @@
void startsyslog();
#endif
extern void (*_dropbear_exit)(int exitcode, const char* format, va_list param);
#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
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);
extern int debug_trace;
#endif
char * stripcontrol(const char * text);
void get_socket_address(int fd, char **local_host, char **local_port,
char **remote_host, char **remote_port, int host_lookup);
@@ -67,8 +82,7 @@ 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);
#define m_free(X) free(X); (X) = NULL;
void m_burn(void* data, unsigned int len);
void setnonblocking(int fd);
void disallow_core();
@@ -80,4 +94,7 @@ int m_str_to_uint(const char* str, unsigned int *val);
/* Dropbear assertion */
#define dropbear_assert(X) do { if (!(X)) { fail_assert(#X, __FILE__, __LINE__); } } while (0)
/* Returns 0 if a and b have the same contents */
int constant_time_memcmp(const void* a, const void *b, size_t n);
#endif /* _DBUTIL_H_ */

37
debian/changelog vendored
View File

@@ -1,3 +1,40 @@
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.

19
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)))
@@ -79,12 +76,12 @@ install: deb-checkdir deb-checkuid build-stamp
ln -s /var/log/dropbear '$(DIR)'/etc/dropbear/log/main
# 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

View File

@@ -39,7 +39,7 @@
* Caution: Don't use this in an unfriendly environment (ie unfirewalled),
* since the printing may not sanitise strings etc. This will add a reasonable
* amount to your executable size. */
/*#define DEBUG_TRACE */
/* #define DEBUG_TRACE */
/* All functions writing to the cleartext payload buffer call
* CHECKCLEARTOWRITE() before writing. This is only really useful if you're
@@ -63,8 +63,10 @@
/* 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.

View File

@@ -1,6 +1,6 @@
.TH dropbear 8
.SH NAME
dropbear \- lightweight SSH2 server
dropbear \- lightweight SSH server
.SH SYNOPSIS
.B dropbear
[\-FEmwsgjki] [\-b
@@ -10,7 +10,7 @@ dropbear \- lightweight SSH2 server
.IR [address:]port ]
.SH DESCRIPTION
.B dropbear
is a SSH 2 server designed to be small enough to be used in small memory
is a SSH server designed to be small enough to be used in small memory
environments, while still being functional and secure enough for general use.
.SH OPTIONS
.TP
@@ -29,7 +29,7 @@ Note that
some SSH implementations
use the term "DSA" rather than "DSS", they mean the same thing.
This file is generated with
.BR dropbearkey (8).
.BR dropbearkey (1).
.TP
.B \-r \fIrsakey
rsakeyfile.
@@ -37,7 +37,7 @@ 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).
.BR dropbearkey (1).
.TP
.B \-F
Don't fork into background.
@@ -180,13 +180,14 @@ in this variable. If a shell was requested this is set to an empty value.
.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 OPTIONS
.TP
.B input type
Either
.I dropbear
or
.I openssh
.TP
.B output type
Either
.I dropbear
or
.I openssh
.TP
.B input file
An existing Dropbear or OpenSSH private key file
.TP
.B output file
The path to write the converted private key file
.SH EXAMPLE
# dropbearconvert openssh dropbear ~/.ssh/id_rsa ~/.ssh/dropbear_priv
.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

@@ -1,6 +1,6 @@
.TH dropbearkey 8
.TH dropbearkey 1
.SH NAME
dropbearkey \- create private keys for the use with dropbear(8)
dropbearkey \- create private keys for the use with dropbear(8) or dbclient(1)
.SH SYNOPSIS
.B dropbearkey
\-t
@@ -16,8 +16,7 @@ generates a
or
.I DSS
format SSH private key, and saves it to a file for the use with the
.BR dropbear (8)
SSH 2 server.
Dropbear client or server.
Note that
some SSH implementations
use the term "DSA" rather than "DSS", they mean the same thing.
@@ -38,6 +37,10 @@ Write the secret key to the file
Set the key size to
.I bits
bits, should be multiple of 8 (optional).
.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
# dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
.SH AUTHOR
@@ -45,6 +48,6 @@ Matt Johnston (matt@ucc.asn.au).
.br
Gerrit Pape (pape@smarden.org) wrote this manual page.
.SH SEE ALSO
dropbear(8), dbclient(1)
dropbear(8), dbclient(1), dropbearconvert(1)
.P
http://matt.ucc.asn.au/dropbear/dropbear.html
https://matt.ucc.asn.au/dropbear/dropbear.html

View File

@@ -65,7 +65,6 @@ static void justprintpub(const char* filename);
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"

74
dss.c
View File

@@ -101,9 +101,9 @@ int buf_get_dss_priv_key(buffer* buf, dropbear_dss_key *key) {
/* Clear and free the memory used by a public or private 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 +127,7 @@ void dss_key_free(dropbear_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:
@@ -258,52 +258,14 @@ 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 */
* to the buffer */
void buf_put_dss_sign(buffer* buf, dropbear_dss_key *key, const unsigned char* data,
unsigned int len) {
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);
@@ -322,33 +284,9 @@ void buf_put_dss_sign(buffer* buf, dropbear_dss_key *key, const unsigned char* d
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);

View File

@@ -120,6 +120,10 @@
#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"

9
kex.h
View File

@@ -51,19 +51,22 @@ 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 */
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 */
};
#define MAX_KEXHASHBUF 2000
#endif /* _KEX_H_ */

View File

@@ -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 */
@@ -118,16 +118,20 @@
#define LTC_CTR_MODE
#endif
#if defined(DROPBEAR_DSS) && defined(DSS_PROTOK)
#define SHA512
#endif
#define SHA1
#ifdef DROPBEAR_MD5_HMAC
#ifdef DROPBEAR_MD5
#define MD5
#endif
#ifdef DROPBEAR_SHA256
#define SHA256
#endif
#ifdef DROPBEAR_SHA512
#define SHA512
#endif
#define LTC_HMAC
/* Various tidbits of modern neatoness */

View File

@@ -170,8 +170,8 @@ clean:
rm -f *.bat *.pdf *.o *.a *.obj *.lib *.exe *.dll etclib/*.o demo/demo.o test ltmtest mpitest mtest/mtest mtest/mtest.exe \
*.idx *.toc *.log *.aux *.dvi *.lof *.ind *.ilg *.ps *.log *.s mpi.c *.da *.dyn *.dpi tommath.tex `find . -type f | grep [~] | xargs` *.lo *.la
rm -rf .libs
cd etc ; MAKE=${MAKE} ${MAKE} clean
cd pics ; MAKE=${MAKE} ${MAKE} clean
-cd etc && MAKE=${MAKE} ${MAKE} clean
-cd pics && MAKE=${MAKE} ${MAKE} clean
#zipup the project (take that!)
no_oops: clean

View File

@@ -67,13 +67,13 @@ int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode
/* init M array */
/* init first cell */
if ((err = mp_init(&M[1])) != MP_OKAY) {
if ((err = mp_init_size(&M[1], P->alloc)) != MP_OKAY) {
return err;
}
/* now init the second half of the array */
for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
if ((err = mp_init(&M[x])) != MP_OKAY) {
if ((err = mp_init_size(&M[x], P->alloc)) != MP_OKAY) {
for (y = 1<<(winsize-1); y < x; y++) {
mp_clear (&M[y]);
}
@@ -133,7 +133,7 @@ int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode
}
/* setup result */
if ((err = mp_init (&res)) != MP_OKAY) {
if ((err = mp_init_size (&res, P->alloc)) != MP_OKAY) {
goto LBL_M;
}

View File

@@ -20,7 +20,7 @@ int mp_init_copy (mp_int * a, mp_int * b)
{
int res;
if ((res = mp_init (a)) != MP_OKAY) {
if ((res = mp_init_size (a, b->used)) != MP_OKAY) {
return res;
}
return mp_copy (b, a);

View File

@@ -22,7 +22,7 @@ mp_mod (mp_int * a, mp_int * b, mp_int * c)
mp_int t;
int res;
if ((res = mp_init (&t)) != MP_OKAY) {
if ((res = mp_init_size (&t, b->used)) != MP_OKAY) {
return res;
}

View File

@@ -21,7 +21,7 @@ int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
int res;
mp_int t;
if ((res = mp_init (&t)) != MP_OKAY) {
if ((res = mp_init_size (&t, c->used)) != MP_OKAY) {
return res;
}

2
list.c
View File

@@ -46,4 +46,4 @@ void * list_remove(m_list_elem *elem) {
}
m_free(elem);
return item;
}
}

2
list.h
View File

@@ -25,4 +25,4 @@ void list_append(m_list *list, void *item);
void * list_remove(m_list_elem *elem);
#endif /* _DROPBEAR_LIST_H */
#endif /* _DROPBEAR_LIST_H */

View File

@@ -329,8 +329,6 @@ login_write (struct logininfo *li)
{
#ifndef HAVE_CYGWIN
if ((int)geteuid() != 0) {
dropbear_log(LOG_WARNING,
"Attempt to write login records by non-root user (aborting)");
return 1;
}
#endif

View File

@@ -80,6 +80,9 @@ much traffic. */
* to a remote TCP-forwarded connection */
#define ENABLE_CLI_NETCAT
/* Whether to support "-c" and "-m" flags to choose ciphers/MACs at runtime */
#define ENABLE_USER_ALGO_LIST
/* Encryption - at least one required.
* Protocol RFC requires 3DES and recommends AES128 for interoperability.
* Including multiple keysize variants the same cipher
@@ -97,12 +100,18 @@ much traffic. */
* size and is recommended for most cases */
#define DROPBEAR_ENABLE_CTR_MODE
/* You can compile with no encryption if you want. In some circumstances
* this could be safe security-wise, though make sure you know what
* you're doing. Anyone can see everything that goes over the wire, so
* the only safe auth method is public key. */
/* #define DROPBEAR_NONE_CIPHER */
/* Message Integrity - at least one required.
* Protocol RFC requires sha1 and recommends sha1-96.
* sha1-96 may be of use for slow links, as it has a smaller overhead.
* sha1-96 is of use for slow links as it has a smaller overhead.
*
* Note: there's no point disabling sha1 to save space, since it's used
* for the random number generator and public-key cryptography anyway.
* There's no reason to disable sha1 or sha1-96 to save space since it's
* used for the random number generator and public-key cryptography anyway.
* Disabling it here will just stop it from being used as the integrity portion
* of the ssh protocol.
*
@@ -111,8 +120,15 @@ much traffic. */
* which are not the standard form. */
#define DROPBEAR_SHA1_HMAC
#define DROPBEAR_SHA1_96_HMAC
/*#define DROPBEAR_SHA2_256_HMAC*/
/*#define DROPBEAR_SHA2_512_HMAC*/
#define DROPBEAR_MD5_HMAC
/* You can also disable integrity. Don't bother disabling this if you're
* still using a cipher, it's relatively cheap. If you disable this it's dead
* simple to run arbitrary commands on the remote host. Beware. */
/* #define DROPBEAR_NONE_INTEGRITY */
/* Hostkey/public key algorithms - at least one required, these are used
* for hostkey as well as for verifying signatures with pubkey auth.
* Removing either of these won't save very much space.
@@ -125,13 +141,6 @@ much traffic. */
* signing operations slightly slower. */
#define RSA_BLINDING
/* Define DSS_PROTOK to use PuTTY's method of generating the value k for dss,
* rather than just from the random byte source. Undefining this will save you
* ~4k in binary size with static uclibc, but your DSS hostkey could be exposed
* if the random number source isn't good. It happened to Sony.
* On systems with a decent random source this isn't required. */
/* #define DSS_PROTOK */
/* Control the memory/performance/compression tradeoff for zlib.
* Set windowBits=8 for least memory usage, see your system's
* zlib.h for full details.
@@ -144,7 +153,7 @@ much traffic. */
#endif
/* Whether to do reverse DNS lookups. */
#define DO_HOST_LOOKUP
//#define DO_HOST_LOOKUP
/* Whether to print the message of the day (MOTD). This doesn't add much code
* size */
@@ -158,15 +167,16 @@ much traffic. */
/* Authentication Types - at least one required.
RFC Draft requires pubkey auth, and recommends password */
/* Note: PAM auth is quite simple, and only works for PAM modules which just do
/* Note: PAM auth is quite simple and only works for PAM modules which just do
* a simple "Login: " "Password: " (you can edit the strings in svr-authpam.c).
* It's useful for systems like OS X where standard password crypts don't work,
* but there's an interface via a PAM module - don't bother using it otherwise.
* It's useful for systems like OS X where standard password crypts don't work
* but there's an interface via a PAM module. It won't work for more complex
* PAM challenge/response.
* You can't enable both PASSWORD and PAM. */
#define ENABLE_SVR_PASSWORD_AUTH
/* PAM requires ./configure --enable-pam */
/*#define ENABLE_SVR_PAM_AUTH*/
//#define ENABLE_SVR_PAM_AUTH
#define ENABLE_SVR_PUBKEY_AUTH
/* Whether to take public key options in
@@ -194,21 +204,22 @@ much traffic. */
* return the password on standard output */
/*#define ENABLE_CLI_ASKPASS_HELPER*/
/* Random device to use - define either DROPBEAR_RANDOM_DEV or
* DROPBEAR_PRNGD_SOCKET.
* DROPBEAR_RANDOM_DEV is recommended on hosts with a good /dev/(u)random,
* otherwise use run prngd (or egd if you want), specifying the socket.
* The device will be queried for a few dozen bytes of seed a couple of times
* per session (or more for very long-lived sessions). */
/* Send a real auth request first rather than requesting a list of available methods.
* It saves a network round trip at login but prevents immediate login to
* accounts with no password, and might be rejected by some strict servers (none
* encountered yet) - hence it isn't enabled by default. */
/* #define CLI_IMMEDIATE_AUTH */
/* We'll use /dev/urandom by default, since /dev/random is too much hassle.
* If system developers aren't keeping seeds between boots nor getting
* any entropy from somewhere it's their own fault. */
#define DROPBEAR_RANDOM_DEV "/dev/urandom"
/* prngd must be manually set up to produce output */
/* Source for randomness. This must be able to provide hundreds of bytes per SSH
* connection without blocking. In addition /dev/random is used for seeding
* rsa/dss key generation */
#define DROPBEAR_URANDOM_DEV "/dev/urandom"
/* Set this to use PRNGD or EGD instead of /dev/urandom or /dev/random */
/*#define DROPBEAR_PRNGD_SOCKET "/var/run/dropbear-rng"*/
/* Specify the number of clients we will allow to be connected but
* not yet authenticated. After this limit, connections are rejected */
/* The first setting is per-IP, to avoid denial of service */

151
packet.c
View File

@@ -42,7 +42,7 @@ static void make_mac(unsigned int seqno, const struct key_context_directional *
static int checkmac();
#define ZLIB_COMPRESS_INCR 100
#define ZLIB_DECOMPRESS_INCR 100
#define ZLIB_DECOMPRESS_INCR 1024
#ifndef DISABLE_ZLIB
static buffer* buf_decompress(buffer* buf, unsigned int len);
static void buf_compress(buffer * dest, buffer * src, unsigned int len);
@@ -55,10 +55,62 @@ void write_packet() {
buffer * writebuf = NULL;
time_t now;
unsigned packet_type;
int all_ignore = 1;
#ifdef HAVE_WRITEV
struct iovec *iov = NULL;
int i;
struct Link *l;
#endif
TRACE(("enter write_packet"))
TRACE2(("enter write_packet"))
dropbear_assert(!isempty(&ses.writequeue));
#ifdef HAVE_WRITEV
iov = m_malloc(sizeof(*iov) * ses.writequeue.count);
for (l = ses.writequeue.head, i = 0; l; l = l->link, i++)
{
writebuf = (buffer*)l->item;
packet_type = writebuf->data[writebuf->len-1];
len = writebuf->len - 1 - writebuf->pos;
dropbear_assert(len > 0);
all_ignore &= (packet_type == SSH_MSG_IGNORE);
TRACE2(("write_packet writev #%d type %d len %d/%d", i, packet_type,
len, writebuf->len-1))
iov[i].iov_base = buf_getptr(writebuf, len);
iov[i].iov_len = len;
}
written = writev(ses.sock_out, iov, ses.writequeue.count);
if (written < 0) {
if (errno == EINTR) {
m_free(iov);
TRACE2(("leave writepacket: EINTR"))
return;
} else {
dropbear_exit("Error writing");
}
}
if (written == 0) {
ses.remoteclosed();
}
while (written > 0) {
writebuf = (buffer*)examine(&ses.writequeue);
len = writebuf->len - 1 - writebuf->pos;
if (len > written) {
// partial buffer write
buf_incrpos(writebuf, written);
written = 0;
} else {
written -= len;
dequeue(&ses.writequeue);
buf_free(writebuf);
}
}
m_free(iov);
#else
/* Get the next buffer in the queue of encrypted packets to write*/
writebuf = (buffer*)examine(&ses.writequeue);
@@ -72,19 +124,13 @@ void write_packet() {
if (written < 0) {
if (errno == EINTR) {
TRACE(("leave writepacket: EINTR"))
TRACE2(("leave writepacket: EINTR"))
return;
} else {
dropbear_exit("Error writing");
}
}
now = time(NULL);
ses.last_trx_packet_time = now;
if (packet_type != SSH_MSG_IGNORE) {
ses.last_packet_time = now;
}
all_ignore = (packet_type == SSH_MSG_IGNORE);
if (written == 0) {
ses.remoteclosed();
@@ -100,7 +146,15 @@ void write_packet() {
buf_incrpos(writebuf, written);
}
TRACE(("leave write_packet"))
#endif
now = time(NULL);
ses.last_trx_packet_time = now;
if (!all_ignore) {
ses.last_packet_time = now;
}
TRACE2(("leave write_packet"))
}
/* Non-blocking function reading available portion of a packet into the
@@ -112,7 +166,7 @@ void read_packet() {
unsigned int maxlen;
unsigned char blocksize;
TRACE(("enter read_packet"))
TRACE2(("enter read_packet"))
blocksize = ses.keys->recv.algo_crypt->blocksize;
if (ses.readbuf == NULL || ses.readbuf->len < blocksize) {
@@ -125,7 +179,7 @@ void read_packet() {
if (ret == DROPBEAR_FAILURE) {
/* didn't read enough to determine the length */
TRACE(("leave read_packet: packetinit done"))
TRACE2(("leave read_packet: packetinit done"))
return;
}
}
@@ -133,22 +187,29 @@ void read_packet() {
/* Attempt to read the remainder of the packet, note that there
* mightn't be any available (EAGAIN) */
maxlen = ses.readbuf->len - ses.readbuf->pos;
len = read(ses.sock_in, buf_getptr(ses.readbuf, maxlen), maxlen);
if (maxlen == 0) {
/* Occurs when the packet is only a single block long and has all
* been read in read_packet_init(). Usually means that MAC is disabled
*/
len = 0;
} else {
len = read(ses.sock_in, buf_getptr(ses.readbuf, maxlen), maxlen);
if (len == 0) {
ses.remoteclosed();
}
if (len < 0) {
if (errno == EINTR || errno == EAGAIN) {
TRACE(("leave read_packet: EINTR or EAGAIN"))
return;
} else {
dropbear_exit("Error reading: %s", strerror(errno));
if (len == 0) {
ses.remoteclosed();
}
}
buf_incrpos(ses.readbuf, len);
if (len < 0) {
if (errno == EINTR || errno == EAGAIN) {
TRACE2(("leave read_packet: EINTR or EAGAIN"))
return;
} else {
dropbear_exit("Error reading: %s", strerror(errno));
}
}
buf_incrpos(ses.readbuf, len);
}
if ((unsigned int)len == maxlen) {
/* The whole packet has been read */
@@ -156,7 +217,7 @@ void read_packet() {
/* The main select() loop process_packet() to
* handle the packet contents... */
}
TRACE(("leave read_packet"))
TRACE2(("leave read_packet"))
}
/* Function used to read the initial portion of a packet, and determine the
@@ -190,7 +251,7 @@ static int read_packet_init() {
}
if (slen < 0) {
if (errno == EINTR) {
TRACE(("leave read_packet_init: EINTR"))
TRACE2(("leave read_packet_init: EINTR"))
return DROPBEAR_FAILURE;
}
dropbear_exit("Error reading: %s", strerror(errno));
@@ -214,7 +275,7 @@ static int read_packet_init() {
}
len = buf_getint(ses.readbuf) + 4 + macsize;
TRACE(("packet size is %d, block %d mac %d", len, blocksize, macsize))
TRACE2(("packet size is %d, block %d mac %d", len, blocksize, macsize))
/* check packet length */
@@ -240,7 +301,7 @@ void decrypt_packet() {
unsigned int padlen;
unsigned int len;
TRACE(("enter decrypt_packet"))
TRACE2(("enter decrypt_packet"))
blocksize = ses.keys->recv.algo_crypt->blocksize;
macsize = ses.keys->recv.algo_mac->hashsize;
@@ -297,7 +358,7 @@ void decrypt_packet() {
ses.recvseq++;
TRACE(("leave decrypt_packet"))
TRACE2(("leave decrypt_packet"))
}
/* Checks the mac at the end of a decrypted readbuf.
@@ -307,7 +368,7 @@ static int checkmac() {
unsigned char mac_bytes[MAX_MAC_LEN];
unsigned int mac_size, contents_len;
mac_size = ses.keys->trans.algo_mac->hashsize;
mac_size = ses.keys->recv.algo_mac->hashsize;
contents_len = ses.readbuf->len - mac_size;
buf_setpos(ses.readbuf, 0);
@@ -315,7 +376,7 @@ static int checkmac() {
/* compare the hash */
buf_setpos(ses.readbuf, contents_len);
if (memcmp(mac_bytes, buf_getptr(ses.readbuf, mac_size), mac_size) != 0) {
if (constant_time_memcmp(mac_bytes, buf_getptr(ses.readbuf, mac_size), mac_size) != 0) {
return DROPBEAR_FAILURE;
} else {
return DROPBEAR_SUCCESS;
@@ -359,7 +420,12 @@ static buffer* buf_decompress(buffer* buf, unsigned int len) {
}
if (zstream->avail_out == 0) {
buf_resize(ret, ret->size + ZLIB_DECOMPRESS_INCR);
int new_size = 0;
if (ret->size >= RECV_MAX_PAYLOAD_LEN) {
dropbear_exit("bad packet, oversized decompressed");
}
new_size = MIN(RECV_MAX_PAYLOAD_LEN, ret->size + ZLIB_DECOMPRESS_INCR);
buf_resize(ret, new_size);
}
}
}
@@ -396,7 +462,6 @@ static void enqueue_reply_packet() {
ses.reply_queue_head = new_item;
}
ses.reply_queue_tail = new_item;
TRACE(("leave enqueue_reply_packet"))
}
void maybe_flush_reply_queue() {
@@ -433,15 +498,15 @@ void encrypt_packet() {
unsigned int len, encrypt_buf_size;
unsigned char mac_bytes[MAX_MAC_LEN];
TRACE(("enter encrypt_packet()"))
TRACE2(("enter encrypt_packet()"))
buf_setpos(ses.writepayload, 0);
packet_type = buf_getbyte(ses.writepayload);
buf_setpos(ses.writepayload, 0);
TRACE(("encrypt_packet type is %d", packet_type))
TRACE2(("encrypt_packet type is %d", packet_type))
if (!ses.dataallowed && !packet_is_okay_kex(packet_type)) {
if ((!ses.dataallowed && !packet_is_okay_kex(packet_type))) {
/* During key exchange only particular packets are allowed.
Since this packet_type isn't OK we just enqueue it to send
after the KEX, see maybe_flush_reply_queue */
@@ -546,7 +611,7 @@ void encrypt_packet() {
ses.kexstate.datatrans += writebuf->len;
ses.transseq++;
TRACE(("leave encrypt_packet()"))
TRACE2(("leave encrypt_packet()"))
}
@@ -559,8 +624,6 @@ static void make_mac(unsigned int seqno, const struct key_context_directional *
unsigned long bufsize;
hmac_state hmac;
TRACE(("enter writemac"))
if (key_state->algo_mac->hashsize > 0) {
/* calculate the mac */
if (hmac_init(&hmac,
@@ -589,7 +652,7 @@ static void make_mac(unsigned int seqno, const struct key_context_directional *
dropbear_exit("HMAC error");
}
}
TRACE(("leave writemac"))
TRACE2(("leave writemac"))
}
#ifndef DISABLE_ZLIB
@@ -600,7 +663,7 @@ static void buf_compress(buffer * dest, buffer * src, unsigned int len) {
unsigned int endpos = src->pos + len;
int result;
TRACE(("enter buf_compress"))
TRACE2(("enter buf_compress"))
while (1) {
@@ -634,6 +697,6 @@ static void buf_compress(buffer * dest, buffer * src, unsigned int len) {
buf_resize(dest, dest->size + ZLIB_COMPRESS_INCR);
}
TRACE(("leave buf_compress"))
TRACE2(("leave buf_compress"))
}
#endif

View File

@@ -45,10 +45,10 @@ void process_packet() {
unsigned char type;
unsigned int i;
TRACE(("enter process_packet"))
TRACE2(("enter process_packet"))
type = buf_getbyte(ses.payload);
TRACE(("process_packet: packet type = %d", type))
TRACE(("process_packet: packet type = %d, len %d", type, ses.payload->len))
ses.lastpacket = type;
@@ -74,14 +74,15 @@ void process_packet() {
/* This applies for KEX, where the spec says the next packet MUST be
* NEWKEYS */
if (ses.requirenext != 0) {
if (ses.requirenext != type) {
/* TODO send disconnect? */
dropbear_exit("Unexpected packet type %d, expected %d", type,
ses.requirenext);
if (ses.requirenext[0] != 0) {
if (ses.requirenext[0] != type
&& (ses.requirenext[1] == 0 || ses.requirenext[1] != type)) {
dropbear_exit("Unexpected packet type %d, expected [%d,%d]", type,
ses.requirenext[0], ses.requirenext[1]);
} else {
/* Got what we expected */
ses.requirenext = 0;
ses.requirenext[0] = 0;
ses.requirenext[1] = 0;
}
}
@@ -123,7 +124,7 @@ out:
buf_free(ses.payload);
ses.payload = NULL;
TRACE(("leave process_packet"))
TRACE2(("leave process_packet"))
}

View File

@@ -70,7 +70,6 @@ void enqueue(struct Queue* queue, void* item) {
struct Link* newlink;
TRACE(("enter enqueue"))
newlink = (struct Link*)m_malloc(sizeof(struct Link));
newlink->item = item;
@@ -85,5 +84,4 @@ void enqueue(struct Queue* queue, void* item) {
queue->head = newlink;
}
queue->count++;
TRACE(("leave enqueue"))
}

View File

@@ -36,7 +36,7 @@ struct Queue {
struct Link* head;
struct Link* tail;
unsigned int count; /* safety value */
unsigned int count;
};

241
random.c
View File

@@ -26,20 +26,18 @@
#include "buffer.h"
#include "dbutil.h"
#include "bignum.h"
static int donerandinit = 0;
#include "random.h"
/* 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
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,120 +48,199 @@ 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
readfd = connect_unix(DROPBEAR_PRNGD_SOCKET);
if (readfd < 0) {
dropbear_exit("Couldn't open random device");
if (prngd)
{
readfd = connect_unix(filename);
}
else
#endif
{
readfd = open(filename, O_RDONLY);
}
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");
#endif
if (readfd < 0) {
goto out;
}
/* read the actual random data */
readpos = 0;
do {
readcount = 0;
while (len == 0 || readcount < len)
{
int readlen, wantread;
unsigned char readbuf[4096];
if (!already_blocked)
{
int ret;
struct timeval timeout;
struct timeval timeout = { .tv_sec = 2, .tv_usec = 0};
fd_set read_fds;
timeout.tv_sec = 2; /* two seconds should be enough */
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)
{
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(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 */

View File

@@ -28,9 +28,8 @@
struct mp_int;
void seedrandom();
void reseedrandom();
void genrandom(unsigned char* buf, int len);
void addrandom(unsigned char* buf, int len);
void genrandom(unsigned char* buf, unsigned int len);
void addrandom(char * buf, unsigned int len);
void gen_random_mpint(mp_int *max, mp_int *rand);
#endif /* _RANDOM_H_ */

6
rsa.c
View File

@@ -139,10 +139,10 @@ out:
/* Clear and free the memory used by a public or private key */
void rsa_key_free(dropbear_rsa_key *key) {
TRACE(("enter rsa_key_free"))
TRACE2(("enter rsa_key_free"))
if (key == NULL) {
TRACE(("leave rsa_key_free: key == NULL"))
TRACE2(("leave rsa_key_free: key == NULL"))
return;
}
if (key->d) {
@@ -166,7 +166,7 @@ void rsa_key_free(dropbear_rsa_key *key) {
m_free(key->q);
}
m_free(key);
TRACE(("leave rsa_key_free"))
TRACE2(("leave rsa_key_free"))
}
/* Put the public rsa key into the buffer in the required format:

View File

@@ -47,6 +47,10 @@ typedef struct runopts {
int enable_compress;
#endif
#ifdef ENABLE_USER_ALGO_LIST
char *cipher_list;
char *mac_list;
#endif
} runopts;
@@ -85,6 +89,7 @@ typedef struct svr_runopts {
int noauthpass;
int norootpass;
int allowblankpass;
#ifdef ENABLE_SVR_REMOTETCPFWD
int noremotetcp;
@@ -116,6 +121,7 @@ typedef struct cli_runopts {
char *cmd;
int wantpty;
int always_accept_key;
int no_hostkey_check;
int no_cmd;
int backgrounded;
int is_subsystem;
@@ -148,4 +154,8 @@ typedef struct cli_runopts {
extern cli_runopts cli_opts;
void cli_getopts(int argc, char ** argv);
#ifdef ENABLE_USER_ALGO_LIST
void parse_ciphers_macs();
#endif
#endif /* _RUNOPTS_H_ */

65
scp.c
View File

@@ -130,22 +130,22 @@ do_local_cmd(arglist *a)
fprintf(stderr, " %s", a->list[i]);
fprintf(stderr, "\n");
}
#ifdef __uClinux__
#ifdef USE_VFORK
pid = vfork();
#else
pid = fork();
#endif /* __uClinux__ */
#endif
if (pid == -1)
fatal("do_local_cmd: fork: %s", strerror(errno));
if (pid == 0) {
execvp(a->list[0], a->list);
perror(a->list[0]);
#ifdef __uClinux__
#ifdef USE_VFORK
_exit(1);
#else
exit(1);
#endif /* __uClinux__ */
#endif
}
do_cmd_pid = pid;
@@ -171,6 +171,16 @@ do_local_cmd(arglist *a)
* assigns the input and output file descriptors on success.
*/
static void
arg_setup(char *host, char *remuser, char *cmd)
{
replacearg(&args, 0, "%s", ssh_program);
if (remuser != NULL)
addargs(&args, "-l%s", remuser);
addargs(&args, "%s", host);
addargs(&args, "%s", cmd);
}
int
do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
{
@@ -198,22 +208,18 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
close(reserved[0]);
close(reserved[1]);
/* uClinux needs to build the args here before vforking,
otherwise we do it later on. */
#ifdef __uClinux__
replacearg(&args, 0, "%s", ssh_program);
if (remuser != NULL)
addargs(&args, "-l%s", remuser);
addargs(&args, "%s", host);
addargs(&args, "%s", cmd);
#endif /* __uClinux__ */
/* uClinux needs to build the args here before vforking,
otherwise we do it later on. */
#ifdef USE_VFORK
arg_setup(host, remuser, cmd);
#endif
/* Fork a child to execute the command on the remote host using ssh. */
#ifdef __uClinux__
#ifdef USE_VFORK
do_cmd_pid = vfork();
#else
do_cmd_pid = fork();
#endif /* __uClinux__ */
#endif
if (do_cmd_pid == 0) {
/* Child. */
@@ -224,27 +230,22 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
close(pin[0]);
close(pout[1]);
#ifndef __uClinux__
replacearg(&args, 0, "%s", ssh_program);
if (remuser != NULL)
addargs(&args, "-l%s", remuser);
addargs(&args, "%s", host);
addargs(&args, "%s", cmd);
#endif /* __uClinux__ */
#ifndef USE_VFORK
arg_setup(host, remuser, cmd);
#endif
execvp(ssh_program, args.list);
perror(ssh_program);
#ifndef __uClinux__
exit(1);
#else
#ifdef USE_VFORK
_exit(1);
#endif /* __uClinux__ */
#else
exit(1);
#endif
} else if (do_cmd_pid == -1) {
fatal("fork: %s", strerror(errno));
}
#ifdef __uClinux__
#ifdef USE_VFORK
/* clean up command */
/* pop cmd */
xfree(args.list[args.num-1]);
@@ -260,7 +261,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
args.list[args.num-1]=NULL;
args.num--;
}
#endif /* __uClinux__ */
#endif
/* Parent. Close the other side, and return the local side. */
close(pin[0]);
@@ -364,12 +365,12 @@ main(int argc, char **argv)
addargs(&args, "-v");
verbose_mode = 1;
break;
#ifdef PROGRESS_METER
case 'q':
#ifdef PROGRESS_METER
addargs(&args, "-q");
showprogress = 0;
break;
#endif
break;
/* Server options. */
case 'd':
@@ -773,7 +774,7 @@ bwlimit(int amount)
{
static struct timeval bwstart, bwend;
static int lamt, thresh = 16384;
u_int64_t waitlen;
uint64_t waitlen;
struct timespec ts, rm;
if (!timerisset(&bwstart)) {

View File

@@ -40,6 +40,7 @@
/*RCSID("OpenBSD: xmalloc.c,v 1.16 2001/07/23 18:21:46 stevesk Exp ");*/
#define _GNU_SOURCE
#include "includes.h"
#include "scpmisc.h"

View File

@@ -26,7 +26,5 @@
#define _SERVICE_H_
void recv_msg_service_request(); /* Server */
void send_msg_service_request(); /* Client */
void recv_msg_service_accept(); /* Client */
#endif /* _SERVICE_H_ */

View File

@@ -37,14 +37,15 @@
#include "packet.h"
#include "tcpfwd.h"
#include "chansession.h"
#include "dbutil.h"
extern int sessinitdone; /* Is set to 0 somewhere */
extern int exitflag;
void common_session_init(int sock_in, int sock_out);
void session_loop(void(*loophandler)());
void common_session_cleanup();
void session_identification();
void session_cleanup();
void send_session_identification();
void send_msg_ignore();
const char* get_user_shell();
@@ -52,19 +53,18 @@ void fill_passwd(const char* username);
/* Server */
void svr_session(int sock, int childpipe);
void svr_dropbear_exit(int exitcode, const char* format, va_list param);
void svr_dropbear_exit(int exitcode, const char* format, va_list param) ATTRIB_NORETURN;
void svr_dropbear_log(int priority, const char* format, va_list param);
/* Client */
void cli_session(int sock_in, int sock_out);
void cli_session_cleanup();
void cleantext(unsigned char* dirtytext);
/* crypto parameters that are stored individually for transmit and receive */
struct key_context_directional {
const struct dropbear_cipher *algo_crypt; /* NULL for none */
const struct dropbear_cipher *algo_crypt;
const struct dropbear_cipher_mode *crypt_mode;
const struct dropbear_hash *algo_mac; /* NULL for none */
const struct dropbear_hash *algo_mac;
int hash_index; /* lookup for libtomcrypt */
char algo_comp; /* compression */
#ifndef DISABLE_ZLIB
@@ -77,7 +77,8 @@ struct key_context_directional {
symmetric_CTR ctr;
#endif
} cipher_state;
unsigned char mackey[MAX_MAC_KEY];
unsigned char mackey[MAX_MAC_LEN];
int valid;
};
struct key_context {
@@ -110,7 +111,10 @@ struct sshsession {
int sock_in;
int sock_out;
unsigned char *remoteident;
/* remotehost will be initially NULL as we delay
* reading the remote version string. it will be set
* by the time any recv_() packet methods are called */
unsigned char *remoteident;
int maxfd; /* the maximum file descriptor to check with select() */
@@ -131,8 +135,9 @@ struct sshsession {
unsigned dataallowed : 1; /* whether we can send data packets or we are in
the middle of a KEX or something */
unsigned char requirenext; /* byte indicating what packet we require next,
or 0x00 for any */
unsigned char requirenext[2]; /* bytes indicating what packets we require next,
or 0x00 for any. Second option can only be
used if the first byte is also set */
unsigned char ignorenext; /* whether to ignore the next packet,
used for kex_follows stuff */
@@ -168,15 +173,11 @@ struct sshsession {
concluded (ie, while dataallowed was unset)*/
struct packetlist *reply_queue_head, *reply_queue_tail;
algo_type*(*buf_match_algo)(buffer*buf, algo_type localalgos[],
int *goodguess); /* The function to use to choose which algorithm
to use from the ones presented by the remote
side. Is specific to the client/server mode,
hence the function-pointer callback.*/
void(*remoteclosed)(); /* A callback to handle closure of the
remote connection */
void(*extra_session_cleanup)(); /* client or server specific cleanup */
void(*send_kex_first_guess)();
struct AuthState authstate; /* Common amongst client and server, since most
struct elements are common */
@@ -217,7 +218,7 @@ struct serversession {
/* The resolved remote address, used for lastlog etc */
char *remotehost;
#ifdef __uClinux__
#ifdef USE_VFORK
pid_t server_pid;
#endif
@@ -232,10 +233,6 @@ typedef enum {
typedef enum {
STATE_NOTHING,
SERVICE_AUTH_REQ_SENT,
SERVICE_AUTH_ACCEPT_RCVD,
SERVICE_CONN_REQ_SENT,
SERVICE_CONN_ACCEPT_RCVD,
USERAUTH_REQ_SENT,
USERAUTH_FAIL_RCVD,
USERAUTH_SUCCESS_RCVD,
@@ -245,6 +242,7 @@ typedef enum {
struct clientsession {
mp_int *dh_e, *dh_x; /* Used during KEX */
int dh_val_algo; /* KEX algorithm corresponding to current dh_e and dh_x */
cli_kex_state kex_state; /* Used for progressing KEX */
cli_state state; /* Used to progress auth/channelsession etc */
unsigned donefirstkex : 1; /* Set when we set sentnewkeys, never reset */
@@ -258,6 +256,9 @@ struct clientsession {
int stderrcopy;
int stderrflags;
/* for escape char handling */
int last_char;
int winchange; /* Set to 1 when a windowchange signal happens */
int lastauthtype; /* either AUTH_TYPE_PUBKEY or AUTH_TYPE_PASSWORD,
@@ -268,6 +269,9 @@ struct clientsession {
int interact_request_received; /* flag whether we've received an
info request from the server for
interactive auth.*/
int cipher_none_after_auth; /* Set to 1 if the user requested "none"
auth */
#endif
sign_key *lastprivkey;

View File

@@ -98,18 +98,18 @@ int buf_get_pub_key(buffer *buf, sign_key *key, int *type) {
int keytype;
int ret = DROPBEAR_FAILURE;
TRACE(("enter buf_get_pub_key"))
TRACE2(("enter buf_get_pub_key"))
ident = buf_getstring(buf, &len);
keytype = signkey_type_from_name(ident, len);
m_free(ident);
if (*type != DROPBEAR_SIGNKEY_ANY && *type != keytype) {
TRACE(("buf_get_pub_key bad type - got %d, expected %d", keytype, type))
TRACE(("buf_get_pub_key bad type - got %d, expected %d", keytype, *type))
return DROPBEAR_FAILURE;
}
TRACE(("buf_get_pub_key keytype is %d"))
TRACE2(("buf_get_pub_key keytype is %d", keytype))
*type = keytype;
@@ -137,7 +137,7 @@ int buf_get_pub_key(buffer *buf, sign_key *key, int *type) {
}
#endif
TRACE(("leave buf_get_pub_key"))
TRACE2(("leave buf_get_pub_key"))
return ret;
@@ -153,7 +153,7 @@ int buf_get_priv_key(buffer *buf, sign_key *key, int *type) {
int keytype;
int ret = DROPBEAR_FAILURE;
TRACE(("enter buf_get_priv_key"))
TRACE2(("enter buf_get_priv_key"))
ident = buf_getstring(buf, &len);
keytype = signkey_type_from_name(ident, len);
@@ -190,7 +190,7 @@ int buf_get_priv_key(buffer *buf, sign_key *key, int *type) {
}
#endif
TRACE(("leave buf_get_priv_key"))
TRACE2(("leave buf_get_priv_key"))
return ret;
@@ -201,7 +201,7 @@ void buf_put_pub_key(buffer* buf, sign_key *key, int type) {
buffer *pubkeys;
TRACE(("enter buf_put_pub_key"))
TRACE2(("enter buf_put_pub_key"))
pubkeys = buf_new(MAX_PUBKEY_SIZE);
#ifdef DROPBEAR_DSS
@@ -223,7 +223,7 @@ void buf_put_pub_key(buffer* buf, sign_key *key, int type) {
pubkeys->len);
buf_free(pubkeys);
TRACE(("leave buf_put_pub_key"))
TRACE2(("leave buf_put_pub_key"))
}
/* type is either DROPBEAR_SIGNKEY_DSS or DROPBEAR_SIGNKEY_RSA */
@@ -251,7 +251,7 @@ void buf_put_priv_key(buffer* buf, sign_key *key, int type) {
void sign_key_free(sign_key *key) {
TRACE(("enter sign_key_free"))
TRACE2(("enter sign_key_free"))
#ifdef DROPBEAR_DSS
dss_key_free(key->dsskey);
@@ -265,7 +265,7 @@ void sign_key_free(sign_key *key) {
m_free(key->filename);
m_free(key);
TRACE(("leave sign_key_free"))
TRACE2(("leave sign_key_free"))
}
static char hexdig(unsigned char x) {

View File

@@ -133,7 +133,7 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
close(*ptyfd);
return 0;
}
#ifndef HAVE_CYGWIN
#if !defined(HAVE_CYGWIN) && defined(I_PUSH)
/*
* Push the appropriate streams modules, as described in Solaris pts(7).
* HP-UX pts(7) doesn't have ttcompat module.

View File

@@ -50,10 +50,7 @@ static void agentaccept(struct Listener * listener, int sock);
/* Handles client requests to start agent forwarding, sets up listening socket.
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
int svr_agentreq(struct ChanSess * chansess) {
int fd;
TRACE(("enter svr_agentreq"))
int fd = -1;
if (!svr_pubkey_allows_agentfwd()) {
return DROPBEAR_FAILURE;
@@ -91,10 +88,9 @@ int svr_agentreq(struct ChanSess * chansess) {
}
return DROPBEAR_SUCCESS;
TRACE(("success"))
fail:
TRACE(("fail"))
m_close(fd);
/* cleanup */
svr_agentcleanup(chansess);

View File

@@ -1,100 +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"
/* 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 * svr_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);
/* Debug this */
TRACE(("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 (i = 0; i < count; i++) {
len = strlen(remotealgos[i]);
for (j = 0; localalgos[j].name != NULL; j++) {
if (localalgos[j].usable) {
if (len == strlen(localalgos[j].name) &&
strncmp(localalgos[j].name, remotealgos[i], len) == 0) {
/* set if it was a good guess */
if (i == 0 && j == 0) {
*goodguess = 1;
}
/* set the algo to return */
ret = &localalgos[j];
goto out;
}
}
}
}
out:
m_free(algolist);
return ret;
}

View File

@@ -37,7 +37,6 @@
static void authclear();
static int checkusername(unsigned char *username, unsigned int userlen);
static void send_msg_userauth_banner();
/* initialise the first time for a session, resetting all parameters */
void svr_authinitialise() {
@@ -82,24 +81,18 @@ static void authclear() {
/* Send a banner message if specified to the client. The client might
* ignore this, but possibly serves as a legal "no trespassing" sign */
static void send_msg_userauth_banner() {
void send_msg_userauth_banner(buffer *banner) {
TRACE(("enter send_msg_userauth_banner"))
if (svr_opts.banner == NULL) {
TRACE(("leave send_msg_userauth_banner: banner is NULL"))
return;
}
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_BANNER);
buf_putstring(ses.writepayload, buf_getptr(svr_opts.banner,
svr_opts.banner->len), svr_opts.banner->len);
buf_putstring(ses.writepayload, buf_getptr(banner, banner->len),
banner->len);
buf_putstring(ses.writepayload, "en", 2);
encrypt_packet();
buf_free(svr_opts.banner);
svr_opts.banner = NULL;
TRACE(("leave send_msg_userauth_banner"))
}
@@ -110,6 +103,7 @@ void recv_msg_userauth_request() {
unsigned char *username = NULL, *servicename = NULL, *methodname = NULL;
unsigned int userlen, servicelen, methodlen;
int valid_user = 0;
TRACE(("enter recv_msg_userauth_request"))
@@ -121,10 +115,11 @@ void recv_msg_userauth_request() {
/* send the banner if it exists, it will only exist once */
if (svr_opts.banner) {
send_msg_userauth_banner();
send_msg_userauth_banner(svr_opts.banner);
buf_free(svr_opts.banner);
svr_opts.banner = NULL;
}
username = buf_getstring(ses.payload, &userlen);
servicename = buf_getstring(ses.payload, &servicelen);
methodname = buf_getstring(ses.payload, &methodlen);
@@ -141,23 +136,40 @@ void recv_msg_userauth_request() {
dropbear_exit("unknown service in auth");
}
/* check username is good before continuing.
* the 'incrfail' varies depending on the auth method to
* avoid giving away which users exist on the system through
* the time delay. */
if (checkusername(username, userlen) == DROPBEAR_SUCCESS) {
valid_user = 1;
}
/* user wants to know what methods are supported */
if (methodlen == AUTH_METHOD_NONE_LEN &&
strncmp(methodname, AUTH_METHOD_NONE,
AUTH_METHOD_NONE_LEN) == 0) {
TRACE(("recv_msg_userauth_request: 'none' request"))
send_msg_userauth_failure(0, 0);
goto out;
if (valid_user
&& svr_opts.allowblankpass
&& !svr_opts.noauthpass
&& !(svr_opts.norootpass && ses.authstate.pw_uid == 0)
&& ses.authstate.pw_passwd[0] == '\0')
{
dropbear_log(LOG_NOTICE,
"Auth succeeded with blank password for '%s' from %s",
ses.authstate.pw_name,
svr_ses.addrstring);
send_msg_userauth_success();
goto out;
}
else
{
/* 'none' has no failure delay */
send_msg_userauth_failure(0, 0);
goto out;
}
}
/* check username is good before continuing */
if (checkusername(username, userlen) == DROPBEAR_FAILURE) {
/* username is invalid/no shell/etc - send failure */
TRACE(("sending checkusername failure"))
send_msg_userauth_failure(0, 1);
goto out;
}
#ifdef ENABLE_SVR_PASSWORD_AUTH
if (!svr_opts.noauthpass &&
!(svr_opts.norootpass && ses.authstate.pw_uid == 0) ) {
@@ -165,8 +177,10 @@ void recv_msg_userauth_request() {
if (methodlen == AUTH_METHOD_PASSWORD_LEN &&
strncmp(methodname, AUTH_METHOD_PASSWORD,
AUTH_METHOD_PASSWORD_LEN) == 0) {
svr_auth_password();
goto out;
if (valid_user) {
svr_auth_password();
goto out;
}
}
}
#endif
@@ -178,8 +192,10 @@ void recv_msg_userauth_request() {
if (methodlen == AUTH_METHOD_PASSWORD_LEN &&
strncmp(methodname, AUTH_METHOD_PASSWORD,
AUTH_METHOD_PASSWORD_LEN) == 0) {
svr_auth_pam();
goto out;
if (valid_user) {
svr_auth_pam();
goto out;
}
}
}
#endif
@@ -189,12 +205,17 @@ void recv_msg_userauth_request() {
if (methodlen == AUTH_METHOD_PUBKEY_LEN &&
strncmp(methodname, AUTH_METHOD_PUBKEY,
AUTH_METHOD_PUBKEY_LEN) == 0) {
svr_auth_pubkey();
if (valid_user) {
svr_auth_pubkey();
} else {
/* pubkey has no failure delay */
send_msg_userauth_failure(0, 0);
}
goto out;
}
#endif
/* nothing matched, we just fail */
/* nothing matched, we just fail with a delay */
send_msg_userauth_failure(0, 1);
out:
@@ -205,13 +226,13 @@ out:
}
/* Check that the username exists, has a non-empty password, and has a valid
* shell.
/* Check that the username exists and isn't disallowed (root), and has a valid shell.
* returns DROPBEAR_SUCCESS on valid username, DROPBEAR_FAILURE on failure */
static int checkusername(unsigned char *username, unsigned int userlen) {
char* listshell = NULL;
char* usershell = NULL;
int uid;
TRACE(("enter checkusername"))
if (userlen > MAX_USERNAME_LEN) {
return DROPBEAR_FAILURE;
@@ -237,7 +258,17 @@ static int checkusername(unsigned char *username, unsigned int userlen) {
dropbear_log(LOG_WARNING,
"Login attempt for nonexistent user from %s",
svr_ses.addrstring);
send_msg_userauth_failure(0, 1);
return DROPBEAR_FAILURE;
}
/* check if we are running as non-root, and login user is different from the server */
uid = geteuid();
if (uid != 0 && uid != ses.authstate.pw_uid) {
TRACE(("running as nonroot, only server uid is allowed"))
dropbear_log(LOG_WARNING,
"Login attempt with wrong user %s from %s",
ses.authstate.pw_name,
svr_ses.addrstring);
return DROPBEAR_FAILURE;
}
@@ -245,16 +276,6 @@ static int checkusername(unsigned char *username, unsigned int userlen) {
if (svr_opts.norootlogin && ses.authstate.pw_uid == 0) {
TRACE(("leave checkusername: root login disabled"))
dropbear_log(LOG_WARNING, "root login rejected");
send_msg_userauth_failure(0, 1);
return DROPBEAR_FAILURE;
}
/* check for an empty password */
if (ses.authstate.pw_passwd[0] == '\0') {
TRACE(("leave checkusername: empty pword"))
dropbear_log(LOG_WARNING, "User '%s' has blank password, rejected",
ses.authstate.pw_name);
send_msg_userauth_failure(0, 1);
return DROPBEAR_FAILURE;
}
@@ -283,7 +304,6 @@ static int checkusername(unsigned char *username, unsigned int userlen) {
TRACE(("no matching shell"))
dropbear_log(LOG_WARNING, "User '%s' has invalid shell, rejected",
ses.authstate.pw_name);
send_msg_userauth_failure(0, 1);
return DROPBEAR_FAILURE;
goodshell:
@@ -293,7 +313,6 @@ goodshell:
TRACE(("uid = %d", ses.authstate.pw_uid))
TRACE(("leave checkusername"))
return DROPBEAR_SUCCESS;
}
/* Send a failure message to the client, in responds to a userauth_request.
@@ -340,8 +359,8 @@ void send_msg_userauth_failure(int partial, int incrfail) {
if (incrfail) {
unsigned int delay;
genrandom((unsigned char*)&delay, sizeof(delay));
/* We delay for 300ms +- 50ms, 0.1ms granularity */
delay = 250000 + (delay % 1000)*100;
/* We delay for 300ms +- 50ms */
delay = 250000 + (delay % 100000);
usleep(delay);
ses.authstate.failcount++;
}

View File

@@ -56,11 +56,7 @@ pamConvFunc(int num_msg,
struct UserDataS* userDatap = (struct UserDataS*) appdata_ptr;
unsigned int msg_len = 0;
unsigned int i = 0;
const char* message = (*msg)->msg;
/* make a copy we can strip */
char * compare_message = m_strdup(message);
char * compare_message = NULL;
TRACE(("enter pamConvFunc"))
@@ -71,15 +67,10 @@ pamConvFunc(int num_msg,
dropbear_log(LOG_INFO, "pamConvFunc() called with >1 messages: not supported.");
return PAM_CONV_ERR;
}
/* make a copy we can strip */
compare_message = m_strdup((*msg)->msg);
TRACE(("msg_style is %d", (*msg)->msg_style))
if (compare_message) {
TRACE(("message is '%s'", compare_message))
} else {
TRACE(("null message"))
}
/* Make the string lowercase. */
msg_len = strlen(compare_message);
for (i = 0; i < msg_len; i++) {
@@ -151,6 +142,22 @@ pamConvFunc(int num_msg,
(*respp) = resp;
break;
case PAM_ERROR_MSG:
case PAM_TEXT_INFO:
if (msg_len > 0) {
buffer * pam_err = buf_new(msg_len + 4);
buf_setpos(pam_err, 0);
buf_putbytes(pam_err, "\r\n", 2);
buf_putbytes(pam_err, (*msg)->msg, msg_len);
buf_putbytes(pam_err, "\r\n", 2);
buf_setpos(pam_err, 0);
send_msg_userauth_banner(pam_err);
buf_free(pam_err);
}
break;
default:
TRACE(("Unknown message type"))
rc = PAM_CONV_ERR;
@@ -205,14 +212,14 @@ void svr_auth_pam() {
/* Init pam */
if ((rc = pam_start("sshd", NULL, &pamConv, &pamHandlep)) != PAM_SUCCESS) {
dropbear_log(LOG_WARNING, "pam_start() failed, rc=%d, %s\n",
dropbear_log(LOG_WARNING, "pam_start() failed, rc=%d, %s",
rc, pam_strerror(pamHandlep, rc));
goto cleanup;
}
/* just to set it to something */
if ((rc = pam_set_item(pamHandlep, PAM_TTY, "ssh") != PAM_SUCCESS)) {
dropbear_log(LOG_WARNING, "pam_set_item() failed, rc=%d, %s\n",
dropbear_log(LOG_WARNING, "pam_set_item() failed, rc=%d, %s",
rc, pam_strerror(pamHandlep, rc));
goto cleanup;
}
@@ -225,7 +232,7 @@ void svr_auth_pam() {
/* (void) pam_set_item(pamHandlep, PAM_FAIL_DELAY, (void*) pamDelayFunc); */
if ((rc = pam_authenticate(pamHandlep, 0)) != PAM_SUCCESS) {
dropbear_log(LOG_WARNING, "pam_authenticate() failed, rc=%d, %s\n",
dropbear_log(LOG_WARNING, "pam_authenticate() failed, rc=%d, %s",
rc, pam_strerror(pamHandlep, rc));
dropbear_log(LOG_WARNING,
"Bad PAM password attempt for '%s' from %s",
@@ -236,7 +243,7 @@ void svr_auth_pam() {
}
if ((rc = pam_acct_mgmt(pamHandlep, 0)) != PAM_SUCCESS) {
dropbear_log(LOG_WARNING, "pam_acct_mgmt() failed, rc=%d, %s\n",
dropbear_log(LOG_WARNING, "pam_acct_mgmt() failed, rc=%d, %s",
rc, pam_strerror(pamHandlep, rc));
dropbear_log(LOG_WARNING,
"Bad PAM password attempt for '%s' from %s",

View File

@@ -29,16 +29,25 @@
#include "buffer.h"
#include "dbutil.h"
#include "auth.h"
#include "runopts.h"
#ifdef ENABLE_SVR_PASSWORD_AUTH
static int constant_time_strcmp(const char* a, const char* b) {
size_t la = strlen(a);
size_t lb = strlen(b);
if (la != lb) {
return 1;
}
return constant_time_memcmp(a, b, la);
}
/* Process a password auth request, sending success or failure messages as
* appropriate */
void svr_auth_password() {
#ifdef HAVE_SHADOW_H
struct spwd *spasswd = NULL;
#endif
char * passwdcrypt = NULL; /* the crypt from /etc/passwd or /etc/shadow */
char * testcrypt = NULL; /* crypt generated from the user's password sent */
unsigned char * password;
@@ -47,29 +56,12 @@ void svr_auth_password() {
unsigned int changepw;
passwdcrypt = ses.authstate.pw_passwd;
#ifdef HAVE_SHADOW_H
/* get the shadow password if possible */
spasswd = getspnam(ses.authstate.pw_name);
if (spasswd != NULL && spasswd->sp_pwdp != NULL) {
passwdcrypt = spasswd->sp_pwdp;
}
#endif
#ifdef DEBUG_HACKCRYPT
/* debugging crypt for non-root testing with shadows */
passwdcrypt = DEBUG_HACKCRYPT;
#endif
/* check for empty password - need to do this again here
* since the shadow password may differ to that tested
* in auth.c */
if (passwdcrypt[0] == '\0') {
dropbear_log(LOG_WARNING, "User '%s' has blank password, rejected",
ses.authstate.pw_name);
send_msg_userauth_failure(0, 1);
return;
}
/* check if client wants to change password */
changepw = buf_getbool(ses.payload);
if (changepw) {
@@ -85,7 +77,23 @@ void svr_auth_password() {
m_burn(password, passwordlen);
m_free(password);
if (strcmp(testcrypt, passwdcrypt) == 0) {
if (testcrypt == NULL) {
/* crypt() with an invalid salt like "!!" */
dropbear_log(LOG_WARNING, "User account '%s' is locked",
ses.authstate.pw_name);
send_msg_userauth_failure(0, 1);
return;
}
/* check for empty password */
if (passwdcrypt[0] == '\0') {
dropbear_log(LOG_WARNING, "User '%s' has blank password, rejected",
ses.authstate.pw_name);
send_msg_userauth_failure(0, 1);
return;
}
if (constant_time_strcmp(testcrypt, passwdcrypt) == 0) {
/* successful authentication */
dropbear_log(LOG_NOTICE,
"Password auth succeeded for '%s' from %s",
@@ -99,7 +107,6 @@ void svr_auth_password() {
svr_ses.addrstring);
send_msg_userauth_failure(0, 1);
}
}
#endif

View File

@@ -92,14 +92,15 @@ int svr_pubkey_allows_pty() {
* by any 'command' public key option. */
void svr_pubkey_set_forced_command(struct ChanSess *chansess) {
if (ses.authstate.pubkey_options) {
ses.authstate.pubkey_options->original_command = chansess->cmd;
if (!chansess->cmd)
{
ses.authstate.pubkey_options->original_command = m_strdup("");
if (chansess->cmd) {
/* original_command takes ownership */
chansess->original_command = chansess->cmd;
} else {
chansess->original_command = m_strdup("");
}
chansess->cmd = ses.authstate.pubkey_options->forced_command;
chansess->cmd = m_strdup(ses.authstate.pubkey_options->forced_command);
#ifdef LOG_COMMANDS
dropbear_log(LOG_INFO, "Command forced to '%s'", ses.authstate.pubkey_options->original_command);
dropbear_log(LOG_INFO, "Command forced to '%s'", chansess->original_command);
#endif
}
}
@@ -142,7 +143,7 @@ int svr_add_pubkey_options(buffer *options_buf, int line_num, const char* filena
ses.authstate.pubkey_options->no_port_forwarding_flag = 1;
goto next_option;
}
#ifdef ENABLE_AGENTFWD
#ifdef ENABLE_SVR_AGENTFWD
if (match_option(options_buf, "no-agent-forwarding") == DROPBEAR_SUCCESS) {
dropbear_log(LOG_WARNING, "Agent forwarding disabled.");
ses.authstate.pubkey_options->no_agent_forwarding_flag = 1;

View File

@@ -137,6 +137,7 @@ static void sesssigchild_handler(int UNUSED(dummy)) {
sa_chld.sa_handler = sesssigchild_handler;
sa_chld.sa_flags = SA_NOCLDSTOP;
sigemptyset(&sa_chld.sa_mask);
sigaction(SIGCHLD, &sa_chld, NULL);
TRACE(("leave sigchld handler"))
}
@@ -217,6 +218,8 @@ static int newchansess(struct Channel *channel) {
struct ChanSess *chansess;
TRACE(("new chansess %p", channel))
dropbear_assert(channel->typedata == NULL);
chansess = (struct ChanSess*)m_malloc(sizeof(struct ChanSess));
@@ -240,7 +243,7 @@ static int newchansess(struct Channel *channel) {
chansess->x11authcookie = NULL;
#endif
#ifdef ENABLE_AGENTFWD
#ifdef ENABLE_SVR_AGENTFWD
chansess->agentlistener = NULL;
chansess->agentfile = NULL;
chansess->agentdir = NULL;
@@ -279,6 +282,10 @@ static void closechansess(struct Channel *channel) {
m_free(chansess->cmd);
m_free(chansess->term);
#ifdef ENABLE_SVR_PUBKEY_OPTIONS
m_free(chansess->original_command);
#endif
if (chansess->tty) {
/* write the utmp/wtmp login record */
li = chansess_login_alloc(chansess);
@@ -293,7 +300,7 @@ static void closechansess(struct Channel *channel) {
x11cleanup(chansess);
#endif
#ifdef ENABLE_AGENTFWD
#ifdef ENABLE_SVR_AGENTFWD
svr_agentcleanup(chansess);
#endif
@@ -351,7 +358,7 @@ static void chansessionrequest(struct Channel *channel) {
} else if (strcmp(type, "x11-req") == 0) {
ret = x11req(chansess);
#endif
#ifdef ENABLE_AGENTFWD
#ifdef ENABLE_SVR_AGENTFWD
} else if (strcmp(type, "auth-agent-req@openssh.com") == 0) {
ret = svr_agentreq(chansess);
#endif
@@ -651,7 +658,7 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess,
/* uClinux will vfork(), so there'll be a race as
connection_string is freed below. */
#ifndef __uClinux__
#ifndef USE_VFORK
chansess->connection_string = make_connection_string();
#endif
@@ -663,7 +670,7 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess,
ret = ptycommand(channel, chansess);
}
#ifndef __uClinux__
#ifndef USE_VFORK
m_free(chansess->connection_string);
#endif
@@ -705,6 +712,7 @@ static int noptycommand(struct Channel *channel, struct ChanSess *chansess) {
TRACE(("found match for lastexitpid"))
svr_ses.childpids[i].chansess->exit = svr_ses.lastexit;
svr_ses.lastexit.exitpid = -1;
break;
}
}
}
@@ -735,7 +743,7 @@ static int ptycommand(struct Channel *channel, struct ChanSess *chansess) {
return DROPBEAR_FAILURE;
}
#ifdef __uClinux__
#ifdef USE_VFORK
pid = vfork();
#else
pid = fork();
@@ -853,15 +861,15 @@ static void execchild(void *user_data) {
struct ChanSess *chansess = user_data;
char *usershell = NULL;
/* with uClinux we'll have vfork()ed, so don't want to overwrite the
* hostkey. can't think of a workaround to clear it */
#ifndef __uClinux__
/* with uClinux we'll have vfork()ed, so don't want to overwrite the
* hostkey. can't think of a workaround to clear it */
#ifndef USE_VFORK
/* wipe the hostkey */
sign_key_free(svr_opts.hostkey);
svr_opts.hostkey = NULL;
/* overwrite the prng state */
reseedrandom();
seedrandom();
#endif
/* clear environment */
@@ -921,10 +929,8 @@ static void execchild(void *user_data) {
}
#ifdef ENABLE_SVR_PUBKEY_OPTIONS
if (ses.authstate.pubkey_options &&
ses.authstate.pubkey_options->original_command) {
addnewvar("SSH_ORIGINAL_COMMAND",
ses.authstate.pubkey_options->original_command);
if (chansess->original_command) {
addnewvar("SSH_ORIGINAL_COMMAND", chansess->original_command);
}
#endif
@@ -937,7 +943,7 @@ static void execchild(void *user_data) {
/* set up X11 forwarding if enabled */
x11setauth(chansess);
#endif
#ifdef ENABLE_AGENTFWD
#ifdef ENABLE_SVR_AGENTFWD
/* set up agent env variable */
svr_agentset(chansess);
#endif
@@ -973,6 +979,7 @@ void svr_chansessinitialise() {
svr_ses.lastexit.exitpid = -1; /* Nothing has exited yet */
sa_chld.sa_handler = sesssigchild_handler;
sa_chld.sa_flags = SA_NOCLDSTOP;
sigemptyset(&sa_chld.sa_mask);
if (sigaction(SIGCHLD, &sa_chld, NULL) < 0) {
dropbear_exit("signal() error");
}

View File

@@ -61,7 +61,8 @@ void recv_msg_kexdh_init() {
mp_clear(&dh_e);
send_msg_newkeys();
ses.requirenext = SSH_MSG_NEWKEYS;
ses.requirenext[0] = SSH_MSG_NEWKEYS;
ses.requirenext[1] = 0;
TRACE(("leave recv_msg_kexdh_init"))
}

View File

@@ -254,6 +254,8 @@ void main_noinetd() {
goto out;
}
seedrandom();
if (pipe(childpipe) < 0) {
TRACE(("error creating child pipe"))
goto out;
@@ -267,8 +269,11 @@ void main_noinetd() {
if (fork_ret < 0) {
dropbear_log(LOG_WARNING, "Error forking: %s", strerror(errno));
goto out;
}
} else if (fork_ret > 0) {
addrandom((void*)&fork_ret, sizeof(fork_ret));
if (fork_ret > 0) {
/* parent */
childpipes[conn_idx] = childpipe[0];
@@ -370,6 +375,7 @@ static void commonsetup() {
/* catch and reap zombie children */
sa_chld.sa_handler = sigchld_handler;
sa_chld.sa_flags = SA_NOCLDSTOP;
sigemptyset(&sa_chld.sa_mask);
if (sigaction(SIGCHLD, &sa_chld, NULL) < 0) {
dropbear_exit("signal() error");
}

View File

@@ -36,9 +36,8 @@ static void addportandaddress(char* spec);
static void printhelp(const char * progname) {
fprintf(stderr, "Dropbear sshd v%s\n"
fprintf(stderr, "Dropbear server v%s https://matt.ucc.asn.au/dropbear/dropbear.html\n"
"Usage: %s [options]\n"
"Options are:\n"
"-b bannerfile Display the contents of bannerfile"
" before user login\n"
" (default: none)\n"
@@ -63,6 +62,7 @@ static void printhelp(const char * progname) {
#if defined(ENABLE_SVR_PASSWORD_AUTH) || defined(ENABLE_SVR_PAM_AUTH)
"-s Disable password logins\n"
"-g Disable password logins for root\n"
"-B Allow blank password logins\n"
#endif
#ifdef ENABLE_SVR_LOCALTCPFWD
"-j Disable local port forwarding\n"
@@ -81,8 +81,8 @@ static void printhelp(const char * progname) {
"-i Start for inetd\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"
"-K <keepalive> (0 is never, default %d, in seconds)\n"
"-I <idle_timeout> (0 is never, default %d, in seconds)\n"
#ifdef DEBUG_TRACE
"-v verbose (compiled with DEBUG_TRACE)\n"
#endif
@@ -115,6 +115,7 @@ void svr_getopts(int argc, char ** argv) {
svr_opts.norootlogin = 0;
svr_opts.noauthpass = 0;
svr_opts.norootpass = 0;
svr_opts.allowblankpass = 0;
svr_opts.inetdmode = 0;
svr_opts.portcount = 0;
svr_opts.hostkey = NULL;
@@ -234,6 +235,9 @@ void svr_getopts(int argc, char ** argv) {
case 'g':
svr_opts.norootpass = 1;
break;
case 'B':
svr_opts.allowblankpass = 1;
break;
#endif
case 'h':
printhelp(argv[0]);
@@ -324,8 +328,23 @@ static void addportandaddress(char* spec) {
/* We don't free it, it becomes part of the runopt state */
myspec = m_strdup(spec);
/* search for ':', that separates address and port */
svr_opts.ports[svr_opts.portcount] = strchr(myspec, ':');
if (myspec[0] == '[') {
myspec++;
svr_opts.ports[svr_opts.portcount] = strchr(myspec, ']');
if (svr_opts.ports[svr_opts.portcount] == NULL) {
/* Unmatched [ -> exit */
dropbear_exit("Bad listen address");
}
svr_opts.ports[svr_opts.portcount][0] = '\0';
svr_opts.ports[svr_opts.portcount]++;
if (svr_opts.ports[svr_opts.portcount][0] != ':') {
/* Missing port -> exit */
dropbear_exit("Missing port");
}
} else {
/* search for ':', that separates address and port */
svr_opts.ports[svr_opts.portcount] = strrchr(myspec, ':');
}
if (svr_opts.ports[svr_opts.portcount] == NULL) {
/* no ':' -> the whole string specifies just a port */

View File

@@ -52,9 +52,7 @@ static const packettype svr_packettypes[] = {
{SSH_MSG_KEXINIT, recv_msg_kexinit},
{SSH_MSG_KEXDH_INIT, recv_msg_kexdh_init}, /* server */
{SSH_MSG_NEWKEYS, recv_msg_newkeys},
#ifdef ENABLE_SVR_REMOTETCPFWD
{SSH_MSG_GLOBAL_REQUEST, recv_msg_global_request_remotetcp},
#endif
{SSH_MSG_CHANNEL_REQUEST, recv_msg_channel_request},
{SSH_MSG_CHANNEL_OPEN, recv_msg_channel_open},
{SSH_MSG_CHANNEL_EOF, recv_msg_channel_eof},
@@ -74,17 +72,23 @@ static const struct ChanType *svr_chantypes[] = {
NULL /* Null termination is mandatory. */
};
static void
svr_session_cleanup(void)
{
/* free potential public key options */
svr_pubkey_options_cleanup();
}
void svr_session(int sock, int childpipe) {
char *host, *port;
size_t len;
reseedrandom();
crypto_init();
common_session_init(sock, sock);
/* Initialise server specific parts of the session */
svr_ses.childpipe = childpipe;
#ifdef __uClinux__
#ifdef USE_VFORK
svr_ses.server_pid = getpid();
#endif
svr_authinitialise();
@@ -106,10 +110,10 @@ void svr_session(int sock, int childpipe) {
/* set up messages etc */
ses.remoteclosed = svr_remoteclosed;
ses.extra_session_cleanup = svr_session_cleanup;
/* packet handlers */
ses.packettypes = svr_packettypes;
ses.buf_match_algo = svr_buf_match_algo;
ses.isserver = 1;
@@ -117,7 +121,7 @@ void svr_session(int sock, int childpipe) {
sessinitdone = 1;
/* exchange identification, version etc */
session_identification();
send_session_identification();
/* start off with key exchange */
send_msg_kexinit();
@@ -157,19 +161,14 @@ void svr_dropbear_exit(int exitcode, const char* format, va_list param) {
_dropbear_log(LOG_INFO, fmtbuf, param);
#ifdef __uClinux__
/* only the main server process should cleanup - we don't want
#ifdef USE_VFORK
/* For uclinux only the main server process should cleanup - we don't want
* forked children doing that */
if (svr_ses.server_pid == getpid())
#else
if (1)
#endif
{
/* free potential public key options */
svr_pubkey_options_cleanup();
/* must be after we've done with username etc */
common_session_cleanup();
session_cleanup();
}
exit(exitcode);
@@ -205,7 +204,7 @@ void svr_dropbear_log(int priority, const char* format, va_list param) {
local_tm = localtime(&timesec);
if (local_tm == NULL
|| strftime(datestr, sizeof(datestr), "%b %d %H:%M:%S",
localtime(&timesec)) == 0)
local_tm) == 0)
{
/* upon failure, just print the epoch-seconds time. */
snprintf(datestr, sizeof(datestr), "%d", (int)timesec);

View File

@@ -34,24 +34,31 @@
#include "runopts.h"
#include "auth.h"
#ifdef ENABLE_SVR_REMOTETCPFWD
static void send_msg_request_failure();
static void send_msg_request_failure() {
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_FAILURE);
encrypt_packet();
}
#ifndef ENABLE_SVR_REMOTETCPFWD
/* This is better than SSH_MSG_UNIMPLEMENTED */
void recv_msg_global_request_remotetcp() {
TRACE(("recv_msg_global_request_remotetcp: remote tcp forwarding not compiled in"))
send_msg_request_failure();
}
/* */
#endif /* !ENABLE_SVR_REMOTETCPFWD */
static void send_msg_request_success();
static void send_msg_request_failure();
static int svr_cancelremotetcp();
static int svr_remotetcpreq();
static int newtcpdirect(struct Channel * channel);
const struct ChanType svr_chan_tcpdirect = {
1, /* sepfds */
"direct-tcpip",
newtcpdirect, /* init */
NULL, /* checkclose */
NULL, /* reqhandler */
NULL /* closehandler */
};
#ifdef ENABLE_SVR_REMOTETCPFWD
static const struct ChanType svr_chan_tcpremote = {
1, /* sepfds */
"forwarded-tcpip",
@@ -117,14 +124,6 @@ static void send_msg_request_success() {
}
static void send_msg_request_failure() {
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_FAILURE);
encrypt_packet();
}
static int matchtcp(void* typedata1, void* typedata2) {
const struct TCPListener *info1 = (struct TCPListener*)typedata1;
@@ -173,14 +172,14 @@ out:
static int svr_remotetcpreq() {
int ret = DROPBEAR_FAILURE;
unsigned char * bindaddr = NULL;
unsigned char * request_addr = NULL;
unsigned int addrlen;
struct TCPListener *tcpinfo = NULL;
unsigned int port;
TRACE(("enter remotetcpreq"))
bindaddr = buf_getstring(ses.payload, &addrlen);
request_addr = buf_getstring(ses.payload, &addrlen);
if (addrlen > MAX_IP_LEN) {
TRACE(("addr len too long: %d", addrlen))
goto out;
@@ -210,15 +209,15 @@ static int svr_remotetcpreq() {
tcpinfo->chantype = &svr_chan_tcpremote;
tcpinfo->tcp_type = forwarded;
if (!opts.listen_fwd_all
|| (strcmp(tcpinfo->listenaddr, "localhost") == 0) ) {
tcpinfo->request_listenaddr = request_addr;
if (!opts.listen_fwd_all || (strcmp(request_addr, "localhost") == 0) ) {
// NULL means "localhost only"
tcpinfo->listenaddr = NULL;
tcpinfo->listenaddr = NULL;
}
else
{
tcpinfo->listenaddr = request_addr;
}
else
{
tcpinfo->listenaddr = bindaddr;
}
ret = listen_tcpfwd(tcpinfo);
@@ -226,13 +225,26 @@ out:
if (ret == DROPBEAR_FAILURE) {
/* we only free it if a listener wasn't created, since the listener
* has to remember it if it's to be cancelled */
m_free(bindaddr);
m_free(request_addr);
m_free(tcpinfo);
}
TRACE(("leave remotetcpreq"))
return ret;
}
#endif /* ENABLE_SVR_REMOTETCPFWD */
#ifdef ENABLE_SVR_LOCALTCPFWD
const struct ChanType svr_chan_tcpdirect = {
1, /* sepfds */
"direct-tcpip",
newtcpdirect, /* init */
NULL, /* checkclose */
NULL, /* reqhandler */
NULL /* closehandler */
};
/* Called upon creating a new direct tcp channel (ie we connect out to an
* address */
static int newtcpdirect(struct Channel * channel) {
@@ -297,4 +309,4 @@ out:
return err;
}
#endif
#endif /* ENABLE_SVR_LOCALTCPFWD */

View File

@@ -175,7 +175,7 @@ void x11cleanup(struct ChanSess *chansess) {
m_free(chansess->x11authprot);
m_free(chansess->x11authcookie);
TRACE(("chansess %s", chansess))
TRACE(("chansess %p", chansess))
if (chansess->x11listener != NULL) {
remove_listener(chansess->x11listener);
chansess->x11listener = NULL;

View File

@@ -4,7 +4,7 @@
*******************************************************************/
#ifndef DROPBEAR_VERSION
#define DROPBEAR_VERSION "0.53.1"
#define DROPBEAR_VERSION "2013.59"
#endif
#define LOCAL_IDENT "SSH-2.0-dropbear_" DROPBEAR_VERSION
@@ -23,6 +23,15 @@
#define AUTH_TIMEOUT 300 /* we choose 5 minutes */
#endif
/* A client should try and send an initial key exchange packet guessing
* the algorithm that will match - saves a round trip connecting, has little
* overhead if the guess was "wrong". */
#define USE_KEX_FIRST_FOLLOWS
/* Use protocol extension to allow "first follows" to succeed more frequently.
* This is currently Dropbear-specific but will gracefully fallback when connecting
* to other implementations. */
#define USE_KEXGUESS2
/* Minimum key sizes for DSS and RSA */
#ifndef MIN_DSS_KEYLEN
#define MIN_DSS_KEYLEN 512
@@ -54,13 +63,16 @@
#define _PATH_CP "/bin/cp"
#define DROPBEAR_ESCAPE_CHAR '~'
/* success/failure defines */
#define DROPBEAR_SUCCESS 0
#define DROPBEAR_FAILURE -1
/* various algorithm identifiers */
#define DROPBEAR_KEX_DH_GROUP1 0
#define DROPBEAR_KEX_DH_GROUP14 1
#define DROPBEAR_KEX_NONE 0
#define DROPBEAR_KEX_DH_GROUP1 1
#define DROPBEAR_KEX_DH_GROUP14 2
#define DROPBEAR_SIGNKEY_ANY 0
#define DROPBEAR_SIGNKEY_RSA 1
@@ -76,21 +88,20 @@
#define DROPBEAR_SIGNKEY_VERIFY
#endif
/* SHA1 is 20 bytes == 160 bits */
#define SHA1_HASH_SIZE 20
/* SHA512 is 64 bytes == 512 bits */
#define SHA512_HASH_SIZE 64
/* MD5 is 16 bytes = 128 bits */
#define MD5_HASH_SIZE 16
/* largest of MD5 and SHA1 */
#define MAX_MAC_LEN SHA1_HASH_SIZE
#define MAX_KEY_LEN 32 /* 256 bits for aes256 etc */
#define MAX_IV_LEN 20 /* must be same as max blocksize,
and >= SHA1_HASH_SIZE */
#define MAX_MAC_KEY 20
#if defined(DROPBEAR_SHA2_512_HMAC)
#define MAX_MAC_LEN 64
#elif defined(DROPBEAR_SHA2_256_HMAC)
#define MAX_MAC_LEN 32
#else
#define MAX_MAC_LEN 20
#endif
#define MAX_NAME_LEN 64 /* maximum length of a protocol name, isn't
explicitly specified for all protocols (just
@@ -144,6 +155,19 @@
#define DROPBEAR_TWOFISH
#endif
#ifdef DROPBEAR_MD5_HMAC
#define DROPBEAR_MD5
#endif
#ifdef DROPBEAR_SHA2_256_HMAC
#define DROPBEAR_SHA256
#endif
#if (defined(DROPBEAR_DSS) && defined(DSS_PROTOK)) \
|| defined(DROPBEAR_SHA2_512_HMAC)
#define DROPBEAR_SHA512
#endif
#ifndef ENABLE_X11FWD
#define DISABLE_X11FWD
#endif
@@ -162,10 +186,6 @@
#define USING_LISTENERS
#endif
#if defined(ENABLE_SVR_AGENTFWD) || defined(ENABLE_CLI_LOCALTCPFWD)
#define ENABLE_AGENTFWD
#endif
#if defined(ENABLE_CLI_NETCAT) && defined(ENABLE_CLI_PROXYCMD)
#define ENABLE_CLI_MULTIHOP
#endif
@@ -186,14 +206,6 @@
#error "You can't turn on PASSWORD and PAM auth both at once. Fix it in options.h"
#endif
#if defined(DROPBEAR_RANDOM_DEV) && defined(DROPBEAR_PRNGD_SOCKET)
#error "You can't turn on DROPBEAR_PRNGD_SOCKET and DROPBEAR_RANDOM_DEV at once"
#endif
#if !defined(DROPBEAR_RANDOM_DEV) && !defined(DROPBEAR_PRNGD_SOCKET)
#error "You must choose one of DROPBEAR_PRNGD_SOCKET or DROPBEAR_RANDOM_DEV in options.h"
#endif
/* We use dropbear_client and dropbear_server as shortcuts to avoid redundant
* code, if we're just compiling as client or server */
#if defined(DROPBEAR_SERVER) && defined(DROPBEAR_CLIENT)
@@ -216,4 +228,10 @@
#define IS_DROPBEAR_SERVER 0
#define IS_DROPBEAR_CLIENT 0
#endif
#endif /* neither DROPBEAR_SERVER nor DROPBEAR_CLIENT */
#ifndef HAVE_FORK
#define USE_VFORK
#endif /* don't HAVE_FORK */
/* no include guard for this file */

View File

@@ -40,6 +40,7 @@ static void cleanup_tcp(struct Listener *listener) {
m_free(tcpinfo->sendaddr);
m_free(tcpinfo->listenaddr);
m_free(tcpinfo->request_listenaddr);
m_free(tcpinfo);
}
@@ -61,6 +62,7 @@ static void tcp_acceptor(struct Listener *listener, int sock) {
if (getnameinfo((struct sockaddr*)&addr, len, ipstring, sizeof(ipstring),
portstring, sizeof(portstring),
NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
m_close(fd);
return;
}
@@ -77,10 +79,13 @@ static void tcp_acceptor(struct Listener *listener, int sock) {
dropbear_assert(tcpinfo->tcp_type == forwarded);
/* "forwarded-tcpip" */
/* address that was connected, port that was connected */
addr = tcpinfo->listenaddr;
addr = tcpinfo->request_listenaddr;
port = tcpinfo->listenport;
}
if (addr == NULL) {
addr = "localhost";
}
buf_putstring(ses.writepayload, addr, strlen(addr));
buf_putint(ses.writepayload, port);

View File

@@ -39,6 +39,8 @@ struct TCPListener {
* localhost, or a normal interface name. */
unsigned char *listenaddr;
unsigned int listenport;
/* The address that the remote host asked to listen on */
unsigned char *request_listenaddr;;
const struct ChanType *chantype;
enum {direct, forwarded} tcp_type;

View File

@@ -107,8 +107,14 @@ const struct TermCode termcodes[MAX_TERMCODE+1] = {
#else
{0, 0},
#endif
{0, 0}, /* 42 */
/* IUTF8 isn't standardised in rfc4254 but is likely soon.
* Implemented by linux and darwin */
#ifdef IUTF8
{IUTF8, TERMCODE_INPUT},
#else
{0, 0},
#endif
{0, 0}, /* 43 */
{0, 0},
{0, 0},
{0, 0},