Compare commits

...

481 Commits

Author SHA1 Message Date
Matt Johnston
0ea2e3463d try fix coverity build
--HG--
branch : coverity
2020-06-26 21:20:57 +08:00
Matt Johnston
ddb6751ab4 merge coverity from main
--HG--
branch : coverity
2020-06-26 21:07:34 +08:00
Guilhem Moulin
3727b099c5 Don't choke on disabled authorized_keys(5) options
As of 2020.79 X11 forwarding is disabled at build time, which could lock
out users with authorized_keys(5) files containing ‘no-X11-forwarding’
options.
2020-06-26 20:56:03 +08:00
Matt Johnston
45294b458a update CHANGES for 2020.80 2020-06-26 20:55:56 +08:00
Matt Johnston
d51e4a75cd Some notes on style 2020-06-26 20:41:34 +08:00
Matt Johnston
e9f2815144 Refer to libtom license files 2020-06-25 23:18:16 +08:00
Matt Johnston
2771fab0fa merge 2020-06-23 22:25:57 +08:00
Matt Johnston
a7a67585cb move GNU_SOURCE earlier 2020-06-23 22:24:58 +08:00
Ilya
366f01252e fix trace messages (#105) 2020-06-23 22:20:05 +08:00
Matt Johnston
1490c0c3a6 check for poly1305_init in other libtomcrypt configure test 2020-06-23 21:47:54 +08:00
Matt Johnston
3f5c106a88 _GNU_SOURCE for random 2020-06-23 21:38:46 +08:00
Matt Johnston
10e119f638 Disable toom and karatsuba for new libtommath 2020-06-18 19:12:07 +08:00
Matt Johnston
5b68d117c2 Added signature for changeset 4877afd51e04 2020-06-15 23:51:45 +08:00
Matt Johnston
58106b1615 Added tag DROPBEAR_2020.79 for changeset e2e4929d057b 2020-06-15 23:51:39 +08:00
Matt Johnston
1e10af850b can't call "make lint" without configure 2020-06-15 23:38:08 +08:00
Matt Johnston
ee4b4db816 changelog for 2020.79 2020-06-15 23:36:14 +08:00
Gabor Z. Papp
ab9cfce00d Fix "make install" for manpages in out-of-tree builds 2020-06-15 23:17:27 +08:00
Matt Johnston
2b8106b14e Add DEVELOPING.md 2020-06-15 22:30:28 +08:00
Matt Johnston
78c5daee52 Delay seedrandom until connections 2020-06-15 22:24:34 +08:00
Vladislav Grishenko
2301b6ac0b Disallow leading lines before the ident for server (#102)
Per RFC4253 4.2 clients must be able to process other lines of data
before the version string, server behavior is not defined neither
with MUST/SHOULD nor with MAY.
If server process up to 50 lines too - it may cause too long hanging
session with invalid/evil client that consume host resources and
potentially may lead to DDoS on poor embedded boxes.
Let's require first line from client to be version string and fail
early if it's not - matches both RFC and real OpenSSH behavior.
2020-06-15 21:22:18 +08:00
Matt Johnston
a27e8b053e Disable by default 3des, cbc, hmac-sha1-96, x11 forwarding 2020-06-11 00:09:15 +08:00
Matt Johnston
6145289e0d Remove blowfish 2020-06-10 23:42:42 +08:00
Matt Johnston
d14ebdbf0e avoid zero length array in base64_decode 2020-06-10 23:26:05 +08:00
Matt Johnston
4b305c5721 Merge libtomcrypt v1.18.2 2020-06-10 23:16:13 +08:00
Matt Johnston
615885be01 Fix whitespace changes vs upstream libtomcrypt 2020-06-10 23:01:33 +08:00
Vladislav Grishenko
6b823d617c Sync curve25519 license 2020-06-10 22:13:53 +08:00
Kazuo Kuroi
ec993dbdbc Set IOV_MAX for IRIX 2020-06-10 22:09:29 +08:00
Matt Johnston
ad1e9b7e3c void return types for curve25519 2020-05-30 00:05:49 +08:00
Matt Johnston
846b8cdbf7 Remove unused DEBUG_FORKGPROF 2020-05-29 23:32:19 +08:00
Vladislav Grishenko
b0243b0e7b Fix ChaCha20 on 32-bit platforms (#99)
* Fix ChaCha20 on 32-bit platforms

On 32-bit platforms with old compiler STORE64H() parameter is
not auto-expanded to 64-bit value, causing wrong IV data.
Spotted on BCM4706 MIPS32r2 with GCC 4.2.4:
	Exit before auth: Integrity error (bad packet size 2065808956)

* Fix Chacha20-Poly1305 and AES-GCM debug messages

Functions were renamed earlier and trace messages - not.
2020-05-29 21:26:22 +08:00
Matt Johnston
4faf06aae7 Don't warn when SO_PRIORITY fails 2020-05-28 23:26:34 +08:00
Matt Johnston
07d46f9907 Fix typo DROPBEAR_NORMAL_DH 2020-05-28 23:23:54 +08:00
Vladislav Grishenko
413eaf1ba1 Allow DH to be completely disabled (#97)
Reduces binary size by ~2kB by default and by 21kB with no other
libtommath functions users, ex. with curve25519 kex and ed25519
key only.
2020-05-28 23:01:48 +08:00
Matt Johnston
3b359050b4 Fix warning for unused prngd branch 2020-05-28 23:01:15 +08:00
Matt Johnston
a015cc7594 Fix indentation and add braces 2020-05-28 22:55:49 +08:00
Matt Johnston
dc12be0cfe merge 2020-05-28 22:52:01 +08:00
Matt Johnston
89e98a2f83 Use Linux getrandom() to ensure random device is initialised
Remove old code warning about random device being not ready,
/dev/random isn't used by default anyway.
2020-05-28 22:50:41 +08:00
Matt Johnston
5027bc4db1 set up early logging name 2020-05-28 22:02:33 +08:00
Matt Johnston
630f6aa6b9 initialise variable to stop warning 2020-05-28 22:02:03 +08:00
Matt Johnston
8048473eb9 Avoid oss-fuzz $SANITIZER causing wrong build
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=22608
2020-05-27 20:33:45 +08:00
Matt Johnston
4216c984ae Mention libtom version requirements, check for poly1305 in libtomcrypt 2020-05-27 00:05:15 +08:00
Matt Johnston
6abf756e51 Bring back -Werror and improve travis tests 2020-05-26 23:53:50 +08:00
Steffen Jaeckel
b4bd23b4d2 Update LibTomMath to 1.2.0 (#84)
* update C files

* update other files

* update headers

* update makefiles

* remove mp_set/get_double()

* use ltm 1.2.0 API

* update ltm_desc

* use bundled tommath if system-tommath is too old

* XMALLOC etc. were changed to MP_MALLOC etc.
2020-05-26 23:36:47 +08:00
Matt Johnston
724e61f8ae try rearrange travis build matrix 2020-05-26 23:27:26 +08:00
Matt Johnston
49667a82de .travis.yml needs spaces not tabs 2020-05-26 23:16:11 +08:00
Matt Johnston
a57114e7fa update travis to Ubuntu focal to provide chacha20 2020-05-26 23:13:48 +08:00
Matt Johnston
cfe90bc6bd Fix untested rsa-sha256 change to fuzzer-verify 2020-05-26 23:13:23 +08:00
Matt Johnston
0aefec6c89 Make "dbclient -m help -c help" work 2020-05-26 20:15:39 +08:00
Matt Johnston
6a3bc73a78 fix typo 2020-05-26 20:15:00 +08:00
Matt Johnston
73aa4f0de9 Get rid of unused "none" cipher option 2020-05-26 20:05:31 +08:00
Matt Johnston
9e25854b41 cast to fix warning 2020-05-26 19:57:28 +08:00
Matt Johnston
d277f140ba merge rsa-sha256 2020-05-26 00:24:02 +08:00
Vladislav Grishenko
61267f8503 CBC mode cleanup (#95)
* Fix CBC mode can't be fully disabled

* Fix CBC mode can't be the only mode
2020-05-25 23:55:13 +08:00
Vladislav Grishenko
d3d0d60076 Add Chacha20-Poly1305, AES128-GCM and AES256-GCM support (#93)
* Add Chacha20-Poly1305 authenticated encryption

* Add general AEAD approach.
* Add chacha20-poly1305@openssh.com algo using LibTomCrypt chacha and
  poly1305 routines.

Chacha20-Poly1305 is generally faster than AES256 on CPU w/o dedicated
AES instructions, having the same key size.
Compiling in will add ~5,5kB to binary size on x86-64.

function                                             old     new   delta
chacha_crypt                                           -    1397   +1397
_poly1305_block                                        -     608    +608
poly1305_done                                          -     595    +595
dropbear_chachapoly_crypt                              -     457    +457
.rodata                                            26976   27392    +416
poly1305_process                                       -     290    +290
poly1305_init                                          -     221    +221
chacha_setup                                           -     218    +218
encrypt_packet                                      1068    1270    +202
dropbear_chachapoly_getlength                          -     147    +147
decrypt_packet                                       756     897    +141
chacha_ivctr64                                         -     137    +137
read_packet                                          543     637     +94
dropbear_chachapoly_start                              -      94     +94
read_kex_algos                                       792     880     +88
chacha_keystream                                       -      69     +69
dropbear_mode_chachapoly                               -      48     +48
sshciphers                                           280     320     +40
dropbear_mode_none                                    24      48     +24
dropbear_mode_ctr                                     24      48     +24
dropbear_mode_cbc                                     24      48     +24
dropbear_chachapoly_mac                                -      24     +24
dropbear_chachapoly                                    -      24     +24
gen_new_keys                                         848     854      +6
------------------------------------------------------------------------------
(add/remove: 14/0 grow/shrink: 10/0 up/down: 5388/0)         Total: 5388 bytes

* Add AES128-GCM and AES256-GCM authenticated encryption

* Add general AES-GCM mode.
* Add aes128-gcm@openssh.com and aes256-gcm@openssh.com algo using
  LibTomCrypt gcm routines.

AES-GCM is combination of AES CTR mode and GHASH, slower than AES-CTR on
CPU w/o dedicated AES/GHASH instructions therefore disabled by default.
Compiling in will add ~6kB to binary size on x86-64.

function                                             old     new   delta
gcm_process                                            -    1060   +1060
.rodata                                            26976   27808    +832
gcm_gf_mult                                            -     820    +820
gcm_add_aad                                            -     660    +660
gcm_shift_table                                        -     512    +512
gcm_done                                               -     471    +471
gcm_add_iv                                             -     384    +384
gcm_init                                               -     347    +347
dropbear_gcm_crypt                                     -     309    +309
encrypt_packet                                      1068    1270    +202
decrypt_packet                                       756     897    +141
gcm_reset                                              -     118    +118
read_packet                                          543     637     +94
read_kex_algos                                       792     880     +88
sshciphers                                           280     360     +80
gcm_mult_h                                             -      80     +80
dropbear_gcm_start                                     -      62     +62
dropbear_mode_gcm                                      -      48     +48
dropbear_mode_none                                    24      48     +24
dropbear_mode_ctr                                     24      48     +24
dropbear_mode_cbc                                     24      48     +24
dropbear_ghash                                         -      24     +24
dropbear_gcm_getlength                                 -      24     +24
gen_new_keys                                         848     854      +6
------------------------------------------------------------------------------
(add/remove: 14/0 grow/shrink: 10/0 up/down: 6434/0)         Total: 6434 bytes
2020-05-25 23:50:25 +08:00
Vladislav Grishenko
91e537e427 Mention Ed25519 in dropbearkey man (#94) 2020-05-25 21:28:27 +08:00
jcmathews
fb9a78c3ee Add files via upload (#90)
When SSHKeepAlive is enabled, dropbear idletimeout is not working as expected.
2020-05-25 21:02:59 +08:00
Haelwenn Monnier
8f8a3dff70 scp.c: Port OpenSSH CVE-2018-20685 fix (#80) 2020-05-25 20:54:29 +08:00
Matt Johnston
c917807b1c rsa-sha256 for ssh-agent 2020-05-25 20:23:02 +08:00
Matt Johnston
701d43b859 send and handle SSH_MSG_EXT_INFO only at the correct point
- other fixes for rsa pubkey auth
- only include ext-info handling when rsa pubkey auth is compiled
2020-05-24 14:16:58 +08:00
Matt Johnston
79bedc90a1 run linter 2020-05-24 13:34:19 +08:00
Matt Johnston
545cc62671 Add linter for #ifdef 2020-05-24 13:15:24 +08:00
Matt Johnston
331d4a714f Make server send SSH_MSG_EXT_INFO
Ensure that only valid hostkey algorithms are sent in the first kex guess
2020-05-21 23:00:22 +08:00
Matt Johnston
2a81289ed3 Make DEBUG_NOFORK a #if not #ifdef 2020-05-21 22:58:56 +08:00
Matt Johnston
5acee497bf ext-info handling for server-sig-algs
only client side is handled
2020-05-19 00:31:41 +08:00
Matt Johnston
972d723484 split signkey_type and signature_type for RSA sha1 vs sha256 2020-05-17 23:58:31 +08:00
Matt Johnston
7dc2f36c3e use sigtype where appropriate 2020-04-06 23:18:26 +08:00
Alexander Dahl
90cfbe1f7a When explicitly passing --disable-fuzz to ./configure fuzz was actually
enabled.

Signed-off-by: Alexander Dahl <ada@thorsis.com>
2020-03-27 23:23:11 +08:00
Alexander Dahl
b681570899 Update remaining advise to edit options.h
You should edit localoptions.h instead.
2020-03-10 15:38:38 +01:00
Matt Johnston
201e359363 Handle early exit when addrstring isn't set 2020-03-18 23:37:45 +08:00
Kevin Darbyshire-Bryant
fa4c4646d8 Improve address logging on early exit messages (#83)
Change 'Early exit' and 'Exit before auth' messages to include the IP
address & port as part of the message.

This allows log scanning utilities such as 'fail2ban' to obtain the
offending IP address as part of the failure event instead of extracting
the PID from the message and then scanning the log again for match
'child connection from' messages

Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
2020-03-18 23:28:56 +08:00
Matt Johnston
6f6aa9db5a merge 2020-03-14 23:33:30 +08:00
Matt Johnston
e35d0784a8 Set SSH_ORIGINAL_COMMAND for "dropbear -c" too, fix build without
DROPBEAR_SVR_PUBKEY_OPTIONS
2020-03-14 23:28:18 +08:00
Matt Johnston
cc6fa57a41 Don't log authorized_keys command= every time 2020-03-14 23:26:37 +08:00
Matt Robinson
a26ad21c0a Fallback for key gen without hard link support (#89)
Add a non-atomic fallback for key generation on platforms where link()
is not permitted (such as most stock Android installs) or on filesystems
without hard link support (such as FAT).
2020-03-14 22:37:35 +08:00
zciendor
002b79e2f9 MOTD enabled by default as the manpage says (#87)
The man page (https://github.com/mkj/dropbear/blob/master/dropbear.8) says MOTD will be printed by default for any login shell, but it was disabled at compile time. Probably happened by accident when this code was moved from `options.h` to `default_options.h`.
2020-03-14 22:21:01 +08:00
Vladislav Grishenko
3d12521735 Add Ed25519 support (#91)
* Add support for Ed25519 as a public key type

Ed25519 is a elliptic curve signature scheme that offers
better security than ECDSA and DSA and good performance. It may be
used for both user and host keys.

OpenSSH key import and fuzzer are not supported yet.

Initially inspired by Peter Szabo.

* Add curve25519 and ed25519 fuzzers

* Add import and export of Ed25519 keys
2020-03-12 00:09:45 +08:00
Matt Johnston
b2007beeb0 bring back fsync_parent_dir 2019-10-18 23:48:16 +08:00
Matt Johnston
8f123fb618 Bring back Dropbear patch to avoid setting AR/LD/RANLIB in LTM 2019-09-17 22:26:03 +08:00
Steffen Jaeckel
c71258625d Prime-related bugfixes (#81)
* Merge pull request #180 from czurnieden/isprimeerror

Fixed bug in mp_prime_isprime
(cherry picked from commit f3ff7064f3301a2fc11b84d389fd67769862d437)

* do 2 MR rounds for numbers >=2048bits

* back-port modified mp_prime_next_prime()
2019-09-17 22:11:09 +08:00
Steffen Jaeckel
615ed4e46a update ltm to 1.1.0 and enable FIPS 186.4 compliant key-generation (#79)
* make key-generation compliant to FIPS 186.4

* fix includes in tommath_class.h

* update fuzzcorpus instead of error-out

* fixup fuzzing make-targets

* update Makefile.in

* apply necessary patches to ltm sources

* clean-up not required ltm files

* update to vanilla ltm 1.1.0

this already only contains the required files

* remove set/get double
2019-09-16 21:50:38 +08:00
Matt Johnston
fa116e983b Rename EPKA -> Plugin 2019-05-15 21:59:45 +08:00
fabriziobertocci
8c6aaf8d36 External Public-Key Authentication API (#72)
* Implemented dynamic loading of an external plug-in shared library to delegate public key authentication

* Moved conditional compilation of the plugin infrastructure into the configure.ac script to be able to add -ldl to dropbear build only when the flag is enabled

* Added tags file to the ignore list

* Updated API to have the constructor to return function pointers in the pliugin instance. Added support for passing user name to the checkpubkey function. Added options to the session returned by the plugin and have dropbear to parse and process them

* Added -rdynamic to the linker flags when EPKA is enabled

* Changed the API to pass a previously created session to the checkPubKey function (created during preauth)

* Added documentation to the API

* Added parameter addrstring to plugin creation function

* Modified the API to retrieve the auth options. Instead of having them as field of the EPKASession struct, they are stored internally (plugin-dependent) in the plugin/session and retrieved through a pointer to a function (in the session)

* Changed option string to be a simple char * instead of unsigned char *
2019-05-15 21:43:57 +08:00
Matt Johnston
cae6e6af10 Added signature for changeset ebcdb893992d 2019-03-27 22:15:23 +08:00
Matt Johnston
f89c5b0390 Added tag DROPBEAR_2019.78 for changeset 009d52ae26d3 2019-03-27 22:15:10 +08:00
Matt Johnston
4318631dd6 Bump to 2019.78 2019-03-27 21:47:34 +08:00
Matt Johnston
7bc6280613 Fix regression where TTY modes weren't reset for client 2019-03-24 20:41:02 +08:00
Matt Johnston
e9231f73c2 Added signature for changeset 07b0d56d186d 2019-03-23 21:54:23 +08:00
Matt Johnston
4fd40e61f7 Added tag DROPBEAR_2019.77 for changeset 6d1bbe7d5fa5 2019-03-23 21:54:21 +08:00
Matt Johnston
71f818262c 2019.77 2019-03-23 21:46:29 +08:00
Matt Johnston
07f790db5a use "openssl sha256" 2019-03-23 21:45:00 +08:00
Matt Johnston
78a3388b98 Update config.sub to 2019-01-05 and config.guess to 2019-03-04 2019-03-23 21:19:02 +08:00
Matt Johnston
6e3c3c8c51 try for coverity
--HG--
branch : coverity
2019-03-21 23:28:59 +08:00
Matt Johnston
6fecc91d10 fix constness build error 2019-03-21 00:21:38 +08:00
Matt Johnston
ef080502f8 merge coverity
--HG--
branch : coverity
2019-03-21 00:14:38 +08:00
Matt Johnston
8b4f60a7a1 limit password length to 100 2019-03-21 00:09:07 +08:00
Matt Johnston
01cd1bd11f Increase MAX_USERNAME_LEN to 100 2019-03-20 23:47:25 +08:00
Christian Hohnstädt
f6df3e1fec dropbearconvert: keyimport.c: fix BER encoding of secp521r1 keys (#69)
keysizes >= 128 octets will be encoded with a 3 byte header
which must be accounted by the optional-header

Reproduce:

master:~/build/dropbear$ ./dropbearkey -t ecdsa -s 521 -f K
Generating 521 bit ecdsa key, this may take a while...

master:~/build/dropbear$ ./dropbearconvert d o K L
Key is a ecdsa-sha2-nistp521 key
Wrote key to 'L'

master:~/build/dropbear$ openssl ec < L
read EC key
unable to load Key
139769806448384:error:0D07209B:asn1 encoding routines:ASN1_get_object:too long:crypto/asn1/asn1_lib.c:91:
2019-03-20 23:42:47 +08:00
xcko
553087b7a6 support openssh long option -o Port=XXXX (#68) 2019-03-20 23:08:25 +08:00
karel-m
16fb0b0d53 cygwin competibility fix (#64) 2019-03-20 23:05:37 +08:00
Andre McCurdy
493ab8fd81 drop obsolete definition for MAX_KEXHASHBUF (#65)
The last code to make use of MAX_KEXHASHBUF was removed in 2005:

  736f370dce

Signed-off-by: Andre McCurdy <armccurdy@gmail.com>
2019-03-20 23:01:41 +08:00
Matt Johnston
0afcfafbb9 Add a sanity check for DROPBEAR_SVR_MULTIUSER==0 mode 2019-03-20 22:57:06 +08:00
Patrick Stewart
0af22aa8e4 Support servers without multiple user support (#76) 2019-03-20 22:44:49 +08:00
Konstantin Demin
2fd3b9f560 packet: remove stale comment about "packet_type" (#63)
clean up after 7f15910541

Signed-off-by: Konstantin Demin <rockdrilla@gmail.com>
2019-03-20 22:33:15 +08:00
François Perrad
2de3bc9353 fix some gcc warnings (#73)
* tweak string size

fix gcc8 warnings

```
svr-agentfwd.c: In function 'bindagent':
svr-agentfwd.c:254:53: warning: '%s' directive output may be truncated writing up to 107 bytes into a region of size between 0 and 107 [-Wformat-truncation=]
  snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", path, sockfile);
                                                     ^~         ~~~~~~~~
svr-agentfwd.c:254:2: note: 'snprintf' output between 2 and 216 bytes into a destination of size 108
  snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", path, sockfile);
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```

* cleanup signed/unsigned comparison

fix gcc8 warnings
```
scp.c: In function 'do_local_cmd':
scp.c:132:17: warning: comparison of integer expressions of different signedness: 'u_int' {aka 'unsigned int'} and 'int' [-Wsign-compare]
   for (i = 0; i < a->num; i++)
                 ^
scpmisc.c: In function 'addargs':
scpmisc.c:161:25: warning: comparison of integer expressions of different signedness: 'int' and 'u_int' {aka 'unsigned int'} [-Wsign-compare]
  } else if (args->num+2 >= nalloc)
                         ^~
scpmisc.c: In function 'replacearg':
scpmisc.c:183:12: warning: comparison of integer expressions of different signedness: 'u_int' {aka 'unsigned int'} and 'int' [-Wsign-compare]
  if (which >= args->num)
            ^~
scpmisc.c: In function 'freeargs':
scpmisc.c:196:17: warning: comparison of integer expressions of different signedness: 'u_int' {aka 'unsigned int'} and 'int' [-Wsign-compare]
   for (i = 0; i < args->num; i++)
                 ^
```

see https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/misc.h.diff?r1=1.16&r2=1.17
2019-03-20 22:25:15 +08:00
François Perrad
28b6111db0 use strlcpy & strlcat (#74)
* refactor checkpubkeyperms() with safe BSD functions

fix gcc8 warnings
```
svr-authpubkey.c: In function 'checkpubkeyperms':
svr-authpubkey.c:427:2: warning: 'strncat' specified bound 5 equals source length [-Wstringop-overflow=]
  strncat(filename, "/.ssh", 5); /* strlen("/.ssh") == 5 */
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
svr-authpubkey.c:433:2: warning: 'strncat' specified bound 16 equals source length [-Wstringop-overflow=]
  strncat(filename, "/authorized_keys", 16);
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```

see https://www.sudo.ws/todd/papers/strlcpy.html

* restore strlcpy in xstrdup

see original https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/xmalloc.c?rev=1.16
2019-03-20 22:09:19 +08:00
vincentto13
a0aa274981 Fix for issue successfull login of disabled user (#78)
This commit introduces fix for scenario:
1. Root login disabled on dropbear
2. PAM authentication model enabled

While login as root user, after prompt for password
user is being notified about login failrue, but
after second attempt of prompt for password within
same session, login becames succesfull.

Signed-off-by: Pawel Rapkiewicz <pawel.rapkiewicz@gmail.com>
2019-03-20 22:03:40 +08:00
Michael Jones
b016ebedfd Add missing word to readme (#77) 2019-03-20 21:56:19 +08:00
François Perrad
cb945f9f67 add missing initializer (#71) 2019-01-07 23:09:45 +08:00
Matt Johnston
df0f1297eb merge 2018-11-14 22:58:35 +08:00
Matt Johnston
fe992bf4ea Split ChanType closehandler() and cleanup() so that dbclient doesn't
lose exit status messages
2018-11-14 22:57:56 +08:00
Matt Johnston
ffde4a524f Remove some cluttering TRACE printouts 2018-11-14 22:52:04 +08:00
Matt Johnston
7e03e4d443 Remove incorrect _POSIX_C_SOURCE 2018-11-06 07:25:53 +08:00
Matt Johnston
02ffdd09dc - Add adaptive authentication failure delay
- Rework monotonic_now/gettime_wrapper and use clock_gettime on more platforms
2018-11-05 23:36:34 +08:00
Matt Johnston
6f6ef4834c merge remote forward fix 2018-09-07 23:02:53 +08:00
Matt Johnston
d2e71ade72 FIx remote forward listeners 2018-09-07 23:02:20 +08:00
Matt Johnston
892c5fc1c8 Merge writev #include fix 2018-08-26 22:26:42 +08:00
Matt Johnston
e7504b3311 make writev #include consistent for variable declarations too 2018-08-23 23:59:24 +08:00
Matt Johnston
ad3eacf3d6 Merge bugfix delay invalid users 2018-08-23 23:43:45 +08:00
Matt Johnston
52adbb34c3 Wait to fail invalid usernames 2018-08-23 23:43:12 +08:00
Matt Johnston
90f04384ee fix error message to say localoptions.h 2018-08-23 22:10:07 +08:00
Matt Johnston
195934be96 avoid extended regex features to avoid caring about sed -r vs -E 2018-07-24 20:19:05 +08:00
Matt Johnston
fdbdbe5703 merge coverity
--HG--
branch : coverity
2018-03-21 00:52:02 +08:00
Matt Johnston
d740dc5489 Fix leaks in kex fuzzers 2018-03-09 23:16:37 +08:00
Matt Johnston
76933e6c0a move dictionaries to corpus repo 2018-03-09 20:43:11 +08:00
Matt Johnston
38c9408cf8 avoid leak of ecdh public key 2018-03-08 23:51:33 +08:00
Matt Johnston
397af3e6a6 kexhashbuf was much to small in kex fuzzers 2018-03-08 23:23:19 +08:00
Matt Johnston
933bc5f8a7 Disable wrapfds outside of fuzzed code 2018-03-08 23:22:53 +08:00
Matt Johnston
ba94bcd2e8 It turns out you can't have a single-quote in an #error 2018-03-08 22:37:54 +08:00
Matt Johnston
56855744b8 Only advertise a single server ecdsa key when -R (generate as required) is
specified. Fixes -R now that default ecdsa key size has changed.
2018-03-08 22:25:33 +08:00
Matt Johnston
b4b11c8155 #error if no ecc size is chosen 2018-03-08 22:22:11 +08:00
Matt Johnston
f82933108d reduce fuzzer-kexdh params count again, still hitting timeout 2018-03-07 22:50:32 +08:00
Matt Johnston
27828c742c don't allow null characters in authorized_keys 2018-03-07 22:16:21 +08:00
Matt Johnston
ed4c38ba46 fix leak in option handling 2018-03-07 22:14:36 +08:00
Matt Johnston
e9edbe8bb2 avoid leak of pubkey_options 2018-03-06 22:18:20 +08:00
Matt Johnston
4fd3160179 fix uninitialised memory in fuzzer codepath 2018-03-06 22:02:19 +08:00
Matt Johnston
a60725740b workaround memory sanitizer FD_ZERO false positives 2018-03-06 21:51:51 +08:00
Matt Johnston
5d065258da reduce number of dh parameters so fuzzer doesn't timeout 2018-03-06 21:00:09 +08:00
Matt Johnston
149b21d7cf ciphers/hashes/kex algorithms won't have string lengths, also use
dictionary for fuzzer-preauth_nomaths
2018-03-05 21:02:26 +08:00
Matt Johnston
145fb96989 Don't read uninitialised value.
From 1d03522625
2018-03-05 16:50:24 +08:00
Matt Johnston
084ff9b4c8 reduce number of params so it doesn't hit a timeout 2018-03-05 16:29:57 +08:00
Matt Johnston
6b05aa4275 fix some links 2018-03-05 14:14:26 +08:00
Matt Johnston
366fc8f335 notes on the fuzzer 2018-03-05 14:07:11 +08:00
Matt Johnston
35f479bd87 Add kexdh and kexecdh fuzzers 2018-03-05 11:50:31 +08:00
Matt Johnston
9d11cad5dc dictionary for fuzzer-preauth 2018-03-05 00:59:17 +08:00
Matt Johnston
0233dcebb4 try and improve the odds of useful fuzzer activity 2018-03-04 22:11:23 +08:00
Matt Johnston
f7dedab4a7 - fuzzer-pubkey needs to free algoname, fix build
- improve dictionary with lengths
2018-03-04 21:44:09 +08:00
Matt Johnston
129c440362 add a dictionary for fuzzer-pubkey 2018-03-04 19:38:34 +08:00
Matt Johnston
abee8093b3 use random keyblob from the fuzzer instead 2018-03-04 19:19:45 +08:00
Matt Johnston
2583b180c9 travis fuzz build clang++ 2018-03-04 17:17:37 +08:00
Matt Johnston
1e1e477d85 set up CXX for fuzzing build 2018-03-04 17:08:21 +08:00
Matt Johnston
85eda7d943 try fix travis sanitizer 2018-03-04 15:18:20 +08:00
Matt Johnston
4b36e24735 print config.log on failure 2018-03-04 15:09:41 +08:00
Matt Johnston
921592d37e merge coverity
--HG--
branch : coverity
2018-03-04 15:07:09 +08:00
Matt Johnston
a5eac0a065 add -fsanitize=address for fuzz test again 2018-03-04 15:00:51 +08:00
Matt Johnston
7f15910541 get rid of unused packet_type in encrypted write queue 2018-03-04 14:57:18 +08:00
Matt Johnston
625b38d7af merge 2018-03-03 11:11:04 +08:00
Matt Johnston
b9edf939f4 add cryptlib for all targets in fuzz build 2018-03-03 11:08:26 +08:00
François Perrad
257bba00ac some linting after fuzz merge (#60)
* fix prototype

* remove extra comma

* use m_free after m_strdup
2018-03-03 11:06:45 +08:00
Matt Johnston
8d0b48f165 Fix CFLAGS for configure 2018-03-03 10:10:16 +08:00
Matt Johnston
ce1f9cdf7c no werror for fuzzing clang 2018-03-02 00:11:27 +08:00
Matt Johnston
e612aec5d9 Attempt to fix m_free for libtomcrypt/libtommath 2018-03-02 00:02:06 +08:00
Matt Johnston
5bd0c0d25a avoid fsanitize=address for fuzzing 2018-03-01 23:47:46 +08:00
Matt Johnston
26ad6853d2 Only use malloc wrapper if fuzzing 2018-03-01 23:46:24 +08:00
Matt Johnston
8a4f7fe4f8 avoid volatile cast warning 2018-03-01 23:46:07 +08:00
Matt Johnston
294e98c397 don't try clang-5.0 2018-03-01 22:58:39 +08:00
Matt Johnston
c1a2dcb25d add fuzzers to travis 2018-03-01 22:54:57 +08:00
Matt Johnston
a0972e0ac6 mention localoptions.h being build directory, fix underscore in CHANGES 2018-03-01 22:12:30 +08:00
Matt Johnston
8062a4e8d6 mention localoptions.h being build directory, fix underscore in CHANGES 2018-03-01 22:12:30 +08:00
Matt Johnston
a0ab5e86b5 more portable for which hg test 2018-02-28 23:42:57 +08:00
Matt Johnston
a1dcaf82a0 Merge fuzzing branch 2018-02-28 22:12:05 +08:00
Matt Johnston
78e17f6ee9 merge from main
--HG--
branch : fuzz
2018-02-28 22:11:39 +08:00
Matt Johnston
5ebc48b3f2 clean some fuzzing conditionals
--HG--
branch : fuzz
2018-02-28 22:10:43 +08:00
François Perrad
1ae4237920 fix #endif (#59) 2018-02-28 15:10:14 +01:00
Matt Johnston
5ca12d8332 avoid extended regex features to avoid caring about sed -r vs -E 2018-07-24 20:19:05 +08:00
François Perrad
7f8702d3d6 fix #endif (#59) 2018-02-28 22:10:14 +08:00
Matt Johnston
5f2447edbb Fix to be able to compile normal(ish) binaries with --enable-fuzz
--HG--
branch : fuzz
2018-02-28 22:02:12 +08:00
Matt Johnston
c658b275fd - #if not #ifdef for DROPBEAR_FUZZ
- fix some unused variables

--HG--
branch : fuzz
2018-02-28 21:40:08 +08:00
Matt Johnston
9bbce01e1b merge from main
--HG--
branch : fuzz
2018-02-28 21:28:59 +08:00
Matt Johnston
bbe02dc3cf Added signature for changeset 2f0c3f3361d3 2018-02-27 22:49:06 +08:00
Matt Johnston
3d76aecaa6 Added tag DROPBEAR_2018.76 for changeset 1c66ca4f3791 2018-02-27 22:48:42 +08:00
Matt Johnston
64bd345a5d Bump version 2018-02-27 22:21:48 +08:00
Matt Johnston
152c507499 bump debian changelog 2018-02-27 22:14:46 +08:00
Matt Johnston
e2ae628b17 CHANGES for 2018.76 2018-02-27 22:14:04 +08:00
Matt Johnston
6eabc0fe87 add guard HAVE_GETGROUPLIST 2018-02-27 21:49:10 +08:00
Matt Johnston
bf6f04cbe6 Remove unused tests for headers and functions 2018-02-27 21:41:56 +08:00
Matt Johnston
e0c86670e2 only clean libtom when using bundled libraries 2018-02-26 23:13:54 +08:00
Matt Johnston
7840691420 remove references to TODO 2018-02-26 23:12:59 +08:00
Matt Johnston
96e1a7e6da avoid warning about port 2018-02-26 23:12:02 +08:00
Matt Johnston
5df73215f8 merge from main
--HG--
branch : fuzz
2018-02-26 22:44:48 +08:00
Matt Johnston
04a02730bc merge coverity
--HG--
branch : coverity
2018-02-26 22:43:12 +08:00
Matt Johnston
3996e93a20 make group1 client-only 2018-02-26 22:42:53 +08:00
Matt Johnston
246f24eda8 Change default ecdsa size to 256 2018-02-26 22:19:01 +08:00
Matt Johnston
4aa72b96c1 disable group1 in default config 2018-02-26 22:14:11 +08:00
Matt Johnston
0fc20c70af don't log server listen ports 2018-02-26 22:12:39 +08:00
Matt Johnston
ebc915baae ignore default_options_guard.h 2018-02-26 22:08:53 +08:00
Matt Johnston
7435369615 - Don't try to handle changed usernames
- Avoid logging repeated failed username messages
2018-02-26 22:07:18 +08:00
François Perrad
2e836bb553 more linting (#58)
* const parameter

* fix indentation
2018-02-26 21:31:15 +08:00
Matt Johnston
36ccfd21e7 Fix restricted group code for BSDs, move to separate function 2018-02-26 21:17:13 +08:00
Matt Johnston
44c323872a Merge branch 'stellarpower-master' 2018-02-22 23:07:13 +08:00
Matt Johnston
094972ea84 Merge branch 'master' of git://github.com/stellarpower/dropbear into stellarpower-master 2018-02-22 23:06:45 +08:00
Matt Johnston
2707f054a5 clarify that -r skips default hostkeys 2018-02-22 21:57:47 +08:00
CamVan Nguyen
4c95d595c0 Only load dropbear default host keys if a key is not specified 2018-02-22 21:55:15 +08:00
Matt Johnston
573838a027 print hg revid
--HG--
branch : fuzz
2018-02-21 21:59:52 +08:00
Matt Johnston
05f4e29a52 The fuzzer has managed to generated DSS key/signature pairs that
verify. Avoid false positives from bogus keys that wouldn't be used

--HG--
branch : fuzz
2018-02-21 21:49:24 +08:00
Matt Johnston
dbc0520992 compile fixes
--HG--
branch : fuzz
2018-02-21 21:03:42 +08:00
François Perrad
7efe873d73 use a full prototype (#56) 2018-02-20 23:13:42 +08:00
Matt Johnston
4058574cfa add curve25519-sha256 without @libssh.org 2018-02-20 19:35:26 +08:00
stellarpower
d17dedfa4f Added the -G option to allow logins only for users that are members of a certain group. This allows finer control of an instance on who can and cannot login over a certain instance (e.g. password and not key). Needs double-checking and ensuring it meets platform requirements. 2018-02-20 02:11:55 +00:00
Matt Johnston
dcce2cfd8d merge coverity
--HG--
branch : coverity
2018-02-19 23:14:49 +08:00
Matt Johnston
4768351e89 Remove bad merged libtommmath "clean" rule and leftover makefile.include 2018-02-19 23:04:46 +08:00
Matt Johnston
3f3f399231 - Fix dependencies and remove old default_options.h from version control
- Rename default_options.h.in -> default_options.h, and
  default_options.h -> default_options_guard.h
- Fix newlines in default_options.h
2018-02-19 22:16:50 +08:00
Matt Johnston
316c923188 draft CHANGES 2018-02-18 23:48:32 +08:00
Matt Johnston
8fdaf0268d missed regenerating 2018-02-18 23:48:24 +08:00
Matt Johnston
f2d86ae7d3 group14-sha256 should be higher than group14-sha1 2018-02-18 22:47:51 +08:00
Matt Johnston
34ee326075 clean up some default options
- move hmac-sha2-512, hmac-md5, twofish_ctr to sysoptions.h, off by default
- try and improve text for KEX methods
2018-02-18 22:27:51 +08:00
Matt Johnston
1656db9e58 Add dbclient '-J &fd' option for a file descriptor
Based on patch by Harald Becker
2018-02-18 15:12:15 +08:00
Matt Johnston
802dace05e include config.h for options.h. don't need to include options.h when
includes.h brings it in
2018-02-18 11:22:13 +08:00
Matt Johnston
c2f2f2b817 rename some options and move some to sysoptions.h 2018-02-18 00:29:17 +08:00
Matt Johnston
dcb41e91eb limit rsa->e size to 64 bits
--HG--
branch : fuzz
2018-02-17 19:41:44 +08:00
Matt Johnston
67111efdad limit rsa->e size to 64 bits 2018-02-17 19:41:44 +08:00
Matt Johnston
5fd677af76 12 years is too old for a TODO list 2018-02-20 19:30:34 +08:00
Matt Johnston
b080f5a047 rename default_options.h.in in docs too 2018-02-20 19:29:55 +08:00
Matt Johnston
7e8094d53a merge from main
--HG--
branch : fuzz
2018-02-17 19:29:51 +08:00
Matt Johnston
c8d852caf6 loginrec close fd on error path 2018-02-17 12:16:18 +08:00
Matt Johnston
00a1290173 merge coverity up to date
--HG--
branch : coverity
2018-02-17 11:29:17 +08:00
François Perrad
f042eb41ab more linting (#55)
* dropbear_exit: remove priority parameter

confusion with dropbear_log()

* const parameter
2018-02-17 11:27:37 +08:00
Loganaden Velvindron
017e2f07a7 Add Spectre v2 mitigations for GCC (#54) 2018-02-16 23:35:32 +08:00
Matt Johnston
3a923b72a4 Merge branch 'master' of github.com:mkj/dropbear 2018-02-16 23:33:46 +08:00
Francois Perrad
5bf1214859 use NULL instead of 0 2018-02-16 23:32:11 +08:00
Francois Perrad
2ef1ab0753 fix indentation 2018-02-16 23:31:58 +08:00
Matt Johnston
c218af6ea7 merge 2018-02-16 23:17:48 +08:00
Matt Johnston
e0748b1970 Remove accidentally committed DROPBEAR_FUZZ 2018-02-16 23:17:15 +08:00
Michael Witten
3ee685ad1c options: Complete the transition to numeric toggles (`#if')
For the sake of review, this commit alters only the code; the affiliated
comments within the source files also need to be updated, but doing so
now would obscure the operational changes that have been made here.

* All on/off options have been switched to the numeric `#if' variant;
  that is the only way to make this `default_options.h.in' thing work
  in a reasonable manner.

* There is now some very minor compile-time checking of the user's
  choice of options.

* NO_FAST_EXPTMOD doesn't seem to be used, so it has been removed.

* ENABLE_USER_ALGO_LIST was supposed to be renamed DROPBEAR_USER_ALGO_LIST,
  and this commit completes that work.

* DROPBEAR_FUZZ seems to be a relatively new, as-yet undocumented option,
  which was added by the following commit:

    commit 6e0b539e9c
    Author: Matt Johnston <matt@ucc.asn.au>
    Date:   Tue May 23 22:29:21 2017 +0800

        split out checkpubkey_line() separately

  It has now been added to `sysoptions.h' and defined as `0' by default.

* The configuration option `DROPBEAR_PASSWORD_ENV' is no longer listed in
  `default_options.h.in'; it is no longer meant to be set by the user, and
  is instead left to be defined in `sysoptions.h' (where it was already being
  defined) as merely the name of the environment variable in question:

    DROPBEAR_PASSWORD

  To enable or disable use of that environment variable, the user must now
  toggle `DROPBEAR_USE_DROPBEAR_PASSWORD'.

* The sFTP support is now toggled by setting `DROPBEAR_SFTPSERVER', and the
  path of the sFTP server program is set independently through the usual
  SFTPSERVER_PATH.
2018-02-16 23:13:47 +08:00
Matt Johnston
17be46e229 disallow inetd -v 2018-02-15 23:30:54 +08:00
Matt Johnston
370d4c7cd5 fix unused variable from merge 2018-02-14 23:09:40 +08:00
Matt Johnston
1700987bfc fix compile warnings 2018-02-14 23:09:28 +08:00
Matt Johnston
a1aa161527 make signal flags volatile, simplify handling 2018-02-14 23:06:01 +08:00
Matt Johnston
9a7972dcb8 Move DEBUG_TRACE to default_options 2018-02-14 00:24:44 +08:00
Matt Johnston
191f22e11a Update build instructions for localoptions, and tidy 2018-02-14 00:24:32 +08:00
Matt Johnston
93632660bb update some dependencies 2018-02-14 00:17:30 +08:00
Matt Johnston
84d415fb66 update default_options.h 2018-02-14 00:17:22 +08:00
Michael Witten
ad9db51434 build: Remove unused constructs: space' and AC_PROG_MAKE_SET'
The makefile variable `space' is never used.

The autoconf output variable `SET_MAKE' is never used, so the
autoconf macro `AC_PROG_MAKE_SET' has been removed.
2018-02-11 23:43:19 +08:00
Matt Johnston
1a37d7aa48 Removed commented out code 2018-02-11 23:03:31 +08:00
Matt Johnston
22eb197d6c Fix building default_options.h 2018-02-11 10:53:59 +08:00
Matt Johnston
3953018c2d simplify error handling, check mp_copy return value 2018-02-10 19:25:00 +08:00
Matt Johnston
cfe99a79bd limit travis branches 2018-02-10 19:06:30 +08:00
Matt Johnston
a3a0b26581 limit travis branches
--HG--
branch : coverity
2018-02-10 19:06:13 +08:00
Matt Johnston
276197b404 merge
--HG--
branch : coverity
2018-02-10 19:03:54 +08:00
Matt Johnston
ee812daf69 Use an explicit matrix instead, avoid bad clang combinations etc 2018-02-10 18:57:44 +08:00
Matt Johnston
df66daa26a use parent $CC etc 2018-02-10 18:57:20 +08:00
Matt Johnston
484d1e9b81 merge
--HG--
branch : coverity
2018-02-10 08:27:30 +08:00
Matt Johnston
8013009880 pass CFLAGS to LTC_CFLAGS 2018-02-10 00:12:31 +08:00
Matt Johnston
95b99cc86a cast m_burn argument away from volatile 2018-02-10 00:12:22 +08:00
Matt Johnston
6a713ad834 exclude clang rather than osx for unbundled libtom 2018-02-10 00:09:02 +08:00
Matt Johnston
278a3e43e5 merge
--HG--
branch : coverity
2018-02-09 23:58:47 +08:00
Matt Johnston
c81e530d3c missed saving a file removing none cipher 2018-02-09 23:58:13 +08:00
Matt Johnston
2df2117388 update coverity
--HG--
branch : coverity
2018-02-09 23:49:22 +08:00
Matt Johnston
4b021ae6f0 Remove none cipher 2018-02-09 23:40:23 +08:00
Matt Johnston
a36f182b36 Put Dropbear config in a separate file
Patch out MECC DER
2018-02-09 23:35:07 +08:00
Matt Johnston
d8bb6a7816 Fix commenting out 2018-02-09 23:34:48 +08:00
Matt Johnston
57d474e183 add $srcdir as needed 2018-02-09 23:34:03 +08:00
Matt Johnston
d7e12aadbe generate list of libtomcrypt directories automatically 2018-02-09 23:33:41 +08:00
Matt Johnston
c0df3902b7 Update Makefile.in 2018-02-09 22:19:42 +08:00
Matt Johnston
4f2eb1914b Update to libtomcrypt 1.18.1, merged with Dropbear changes 2018-02-09 21:44:05 +08:00
Matt Johnston
d72f50ff32 Update to libtommath v1.0.1 2018-02-08 23:11:40 +08:00
Matt Johnston
debb208553 Test for -Wno-pointer-sign, move CFLAGS tests into a macro 2018-02-08 22:21:47 +08:00
Matt Johnston
f581ef9453 define CLOCK_MONOTONIC if needed 2018-02-08 22:07:59 +08:00
Matt Johnston
b65354d237 Merge branch 'houseofkodai-cli_bind_address_connect' 2018-01-26 00:32:39 +08:00
Matt Johnston
e4ac7ea1ca bind to port as well with -b 2018-01-26 00:28:25 +08:00
houseofkodai
9c7ecf6d14 cli_bind_address_connect
* replaces -b dummy option in dbclient to be similar with openssh -b option
* useful in multi-wan connections
2018-01-26 00:28:25 +08:00
houseofkodai
917722257d Server chosen tcpfwd ports (#43)
Server chosen tcpfwd ports
2018-01-25 22:21:41 +08:00
Matt Johnston
3d61b6eab6 Merge pull request #48 from DengkeDu/dengke/configure-add-variable-to-allow-openpty-check-cached
configure: add a variable to allow openpty check to be cached
2018-01-25 21:58:00 +08:00
Matt Johnston
e64e25e4d6 Merge pull request #49 from fperrad/20170812_lint
Some linting, const parameters
2018-01-25 21:55:25 +08:00
Matt Johnston
f7a664f127 fix bad assertion
--HG--
branch : fuzz
2018-01-23 23:27:40 +08:00
Matt Johnston
89bdf3b0b9 add fuzzer-preauth_nomaths
--HG--
branch : fuzz
2018-01-23 23:05:47 +08:00
Matt Johnston
597f7eb5e9 merge up to date
--HG--
branch : fuzz
2018-01-23 22:46:07 +08:00
Matt Johnston
ba23b823dc fix updates to libtomcrypt/libtommath for out of tree builds 2018-01-23 22:44:18 +08:00
Matt Johnston
fa3b0dd3ca test close < 0, from Marco Wenzel 2017-10-18 22:41:27 +08:00
Matt Johnston
dd8988220e fix checkpubkey_line function name for TRACE 2017-10-04 22:30:18 +08:00
Matt Johnston
cc803ee802 fix pubkey authentication return value 2017-10-04 22:29:42 +08:00
Francois Perrad
598056d168 Pointer parameter could be declared as pointing to const (callback) 2017-08-19 22:39:53 +02:00
Francois Perrad
89e64c631e Pointer parameter could be declared as pointing to const 2017-08-19 17:16:13 +02:00
Matt Johnston
5cd003d9e6 check dss g range
--HG--
branch : fuzz
2017-08-14 00:00:10 +08:00
Francois Perrad
468656b4aa fix format
Argument no. 3 nominally inconsistent with format (int vs. unsigned int)
2017-08-12 20:53:52 +02:00
Eric Bénard
22037d5fba configure: add a variable to allow openpty check to be cached
Signed-off-by: Dengke Du <dengke.du@windriver.com>
2017-07-11 03:20:08 -04:00
Matt Johnston
4b7105dfea fix DROBPEAR_FUZZ auth delay
--HG--
branch : fuzz
2017-06-30 21:10:57 +08:00
Matt Johnston
a5ec3aca7d EXEEXT for a few more targets, dropbearmulti in particular for Cygwin
From William K. Foster.
2017-06-27 23:02:05 +08:00
Matt Johnston
785459d31b document --enable-static in place of STATIC=1 2017-06-27 22:42:32 +08:00
Matt Johnston
a9a3746d09 add --enable-static configure argument. disable conflicting harden flags 2017-06-27 22:37:46 +08:00
Matt Johnston
74ace058a6 Use MAX_AUTH_TRIES rather than DEFAULT_AUTH_TRIES, don't limit argument range 2017-06-27 22:20:38 +08:00
Matt Johnston
96382d52ab improve configure --help alignment 2017-06-27 22:18:18 +08:00
Matt Johnston
ddbc8113a9 Merge pull request #47 from kdarbyshirebryant/mastermaxauth
dropbear server: support -T max auth tries
2017-06-25 23:37:44 +08:00
Matt Johnston
65115b9159 Merge pull request #45 from bengardner/DROPBEAR_LISTEN_BACKLOG
sysoptions.h: Add ability to override DROPBEAR_LISTEN_BACKLOG
2017-06-25 23:22:11 +08:00
Kevin Darbyshire-Bryant
e255101299 dropbear server: support -T max auth tries
Add support for '-T n' for a run-time specification for maximum number
of authentication attempts where 'n' is between 1 and compile time
option MAX_AUTH_TRIES.

A default number of tries can be specified at compile time using
'DEFAULT_AUTH_TRIES' which itself defaults to MAX_AUTH_TRIES for
backwards compatibility.

Signed-off-by: Kevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk>
2017-06-25 11:53:58 +01:00
Matt Johnston
187fc95deb merge
--HG--
branch : coverity
2017-06-24 23:33:16 +08:00
Matt Johnston
a94338dc67 add configuration option for default RSA size.
print key size with dropbearkey
2017-06-24 23:32:25 +08:00
Matt Johnston
6ac5ea2a9f merge from main (libtommath/libtomcrypt/curve25510-donna updates)
--HG--
branch : fuzz
2017-06-24 22:51:45 +08:00
Matt Johnston
364fb6019c Update to libtommath v1.0 2017-06-24 22:37:14 +08:00
Matt Johnston
a79b61517b update to libtomcrypt 1.17 (with Dropbear changes) 2017-06-24 17:50:50 +08:00
Matt Johnston
99361f54ca Update curve25519-donna to f7837adf95a2c2dcc36233cb02a1fb34081c0c4a 2017-06-24 11:53:32 +08:00
Matt Johnston
82c06dd76b document changed default RSA key size back in 2013.61test 2017-06-24 11:00:16 +08:00
Matt Johnston
17a9b8802f fix dss debug printing
--HG--
branch : fuzz
2017-06-24 10:34:58 +08:00
Matt Johnston
9b6f7fc9af merge from main
--HG--
branch : fuzz
2017-06-24 10:34:19 +08:00
Matt Johnston
57690891ce test dss key parameter lengths exactly 2017-06-24 10:32:33 +08:00
Matt Johnston
5896a4941d test for -pie linker flag as well, for Linux 2017-06-24 01:01:11 +08:00
Matt Johnston
5ac4a71000 merge from main
--HG--
branch : fuzz
2017-06-24 00:47:07 +08:00
Matt Johnston
521e63529c set hardened compiler/linker flags by default 2017-06-24 00:42:20 +08:00
Matt Johnston
24b446705b test for linux/pkt-sched.h rather than SO_PRIORITY 2017-06-23 23:36:33 +08:00
Matt Johnston
3c5ed47804 set PAM_RHOST 2017-06-23 23:21:20 +08:00
Matt Johnston
b967dc1fa5 merge
--HG--
branch : fuzz
2017-06-23 21:31:49 +08:00
Matt Johnston
af2caaab72 Compile with -fno-strict-overflow if possible.
Needed for curve25519-donna https://github.com/agl/curve25519-donna/issues/31
2017-06-23 21:31:25 +08:00
Matt Johnston
2cbe70ba34 verify debug printing
--HG--
branch : fuzz
2017-06-20 20:07:25 +08:00
Matt Johnston
8e1ea0f27b increase min DSS and RSA lengths
--HG--
branch : fuzz
2017-06-16 22:35:32 +08:00
Matt Johnston
e3246ceb7e check p and q lengths
--HG--
branch : fuzz
2017-06-16 22:35:18 +08:00
Matt Johnston
169f41a43c fix missing arglist NULL terminator 2017-06-15 08:00:07 +08:00
Matt Johnston
88ce30beb6 merge from main
--HG--
branch : fuzz
2017-06-14 23:31:42 +08:00
Matt Johnston
d260d5148e improve value range validation 2017-06-14 23:31:15 +08:00
Matt Johnston
723ec19eed fix checkmac always failing pre-kex
--HG--
branch : fuzz
2017-06-11 21:39:40 +08:00
Ben Gardner
44f36d57e6 sysoptions.h: Add ability to override DROPBEAR_LISTEN_BACKLOG
This change allows adding DROPBEAR_LISTEN_BACKLOG to localoptions.h to
force the value.
2017-06-05 08:40:48 -05:00
Matt Johnston
7ab8f61974 Merge pull request #38 from armcc/master
Fix libtomcrypt/libtommath linking order
2017-06-03 09:45:55 +08:00
Matt Johnston
4bba3268d5 Merge pull request #40 from fperrad/20161119_lint
more lintings
2017-06-03 09:41:09 +08:00
Francois Perrad
5f76e4c1ed when pointer, use NULL instead of 0 2017-06-02 18:14:31 +02:00
Matt Johnston
b75a033787 merge
--HG--
branch : coverity
2017-06-03 00:10:58 +08:00
Matt Johnston
92c4f20089 Set configure #defines to 1. Escape some strings for m4 2017-06-02 23:35:30 +08:00
Matt Johnston
acfd372808 Merge pull request #37 from shauser88/configure-fixes
Fix configure options using AC_ARG_ENABLE
2017-06-02 23:21:31 +08:00
Matt Johnston
6054483dc7 Merge pull request #39 from fperrad/20161118_lint
fix indentation
2017-06-02 23:10:48 +08:00
Matt Johnston
25931bc1e6 Merge pull request #34 from bengardner/gitignore
Add .gitignore file
2017-06-02 23:02:34 +08:00
Matt Johnston
9250c58013 Merge pull request #33 from bengardner/termcodes
termcodes: make VEOL2, VWERASE, VLNEXT, ECHOCTL, and ECHOKE optional
2017-06-02 23:01:54 +08:00
Matt Johnston
4f226ab36a Merge pull request #32 from bengardner/ERR_label
Change label name _ERR to LBL_ERR
2017-06-02 23:00:05 +08:00
Matt Johnston
33e28fb96b Merge pull request #31 from bengardner/PATH_DEVNULL
Use DROPBEAR_PATH_DEVNULL instead of undefined _PATH_DEVNULL
2017-06-02 22:57:09 +08:00
Francois Perrad
206b9cea0d rename hidden variable
in function tcp_acceptor()
  struct sockaddr_storage addr;
  char* addr = NULL;
2017-06-01 19:15:07 +02:00
Francois Perrad
9dcb04a1e0 fix DEBUG_* condition 2017-06-01 19:10:37 +02:00
Francois Perrad
08543d0c76 use #ifdef DROPBEAR_PRNGD_SOCKET instead of #if 2017-06-01 19:10:37 +02:00
Matt Johnston
937e6cb91e fuzzer-preauth don't call getpwnam(), bring back longjmp
--HG--
branch : fuzz
2017-06-02 00:03:51 +08:00
Francois Perrad
6c43be767c fix indentation 2017-06-01 16:39:26 +02:00
Matt Johnston
81b64ea0b5 Add a flag whether to longjmp, missed that last commit
--HG--
branch : fuzz
2017-06-01 21:30:26 +08:00
Matt Johnston
ea0e23c172 don't longjmp for fuzzer-preauth (temporary to debug asan)
--HG--
branch : fuzz
2017-05-30 22:50:52 +08:00
Matt Johnston
4d07aa315b Disable setnonblocking(), get_socket_address(), set_sock_priority()
for fuzzing

--HG--
branch : fuzz
2017-05-26 22:10:51 +08:00
Matt Johnston
2e298b25e4 fix building with DEBUG_TRACE
--HG--
branch : fuzz
2017-05-26 22:09:30 +08:00
Matt Johnston
c38927da47 add m_mp_free_multi, be more careful freeing when failing to load keys 2017-05-26 21:08:43 +08:00
Matt Johnston
25607c04a7 add m_mp_free_multi, be more careful freeing when failing to load keys
--HG--
branch : fuzz
2017-05-26 21:08:43 +08:00
Matt Johnston
cbd5be1b82 add fuzzer-verify
--HG--
branch : fuzz
2017-05-26 00:20:01 +08:00
Matt Johnston
924b8469cb fix null pointer crash 2017-05-26 00:19:53 +08:00
Matt Johnston
f24d93d4e4 fix null pointer crash
--HG--
branch : fuzz
2017-05-26 00:19:53 +08:00
Matt Johnston
65baa71b58 linked list dbmalloc now
add non-free m_malloc_free_epoch() argument for leak detection

--HG--
branch : fuzz
2017-05-26 00:19:39 +08:00
Matt Johnston
b8fa712847 rearrange, all fuzzers now call fuzzer_set_input()
--HG--
branch : fuzz
2017-05-25 22:21:49 +08:00
Matt Johnston
095b067857 limit input size
--HG--
branch : fuzz
2017-05-25 22:21:23 +08:00
Matt Johnston
87c4586d61 fuzzing has a constant time
--HG--
branch : fuzz
2017-05-25 22:20:10 +08:00
Matt Johnston
b17254925d Just use memset, it should'be be optimised out in a separate file
--HG--
branch : fuzz
2017-05-25 22:19:46 +08:00
Matt Johnston
cf2c4f44a2 fuzzers disable logging by default
--HG--
branch : fuzz
2017-05-25 00:12:07 +08:00
Matt Johnston
2bc55ff428 don't exit encountering short lines
--HG--
branch : fuzz
2017-05-25 00:10:18 +08:00
Matt Johnston
ee5769f31f avoid NULL argument to base64 decode
--HG--
branch : fuzz
2017-05-25 00:09:40 +08:00
Matt Johnston
3a8517b06f create fuzzer .options files
--HG--
branch : fuzz
2017-05-23 22:43:52 +08:00
Matt Johnston
0363d3c32e fuzzer-pubkey
--HG--
branch : fuzz
2017-05-23 22:43:34 +08:00
Matt Johnston
a582c4cdb6 split out checkpubkey_line() separately
--HG--
branch : fuzz
2017-05-23 22:29:21 +08:00
Matt Johnston
a43b6b0323 define SIZE_T_MAX
--HG--
branch : fuzz
2017-05-22 22:09:46 +08:00
Matt Johnston
84a143a605 remove unneeded check
--HG--
branch : fuzz
2017-05-22 22:09:38 +08:00
Matt Johnston
114438e669 zlib can use m_malloc/m_free too
--HG--
branch : fuzz
2017-05-22 22:09:26 +08:00
Matt Johnston
50bde9976b seed_fuzz() prototype
--HG--
branch : fuzz
2017-05-21 18:53:44 +08:00
Matt Johnston
18ea116827 -v for debug_trace
--HG--
branch : fuzz
2017-05-21 18:53:33 +08:00
Matt Johnston
0ab0687a3a Fix null pointer dereference found by libfuzzer 2017-05-21 18:53:09 +08:00
Matt Johnston
72f85ad90f limit input size 2017-05-25 22:21:23 +08:00
Matt Johnston
fb4e07f7a8 don't exit encountering short lines 2017-05-25 00:10:18 +08:00
Matt Johnston
6e0b539e9c split out checkpubkey_line() separately 2017-05-23 22:29:21 +08:00
Matt Johnston
83b2c899f5 increase min DSS and RSA lengths 2017-06-16 22:35:32 +08:00
Matt Johnston
eb7ca20379 check p and q lengths 2017-06-16 22:35:18 +08:00
Matt Johnston
30d3ccd419 Fix null pointer dereference found by libfuzzer
--HG--
branch : fuzz
2017-05-21 18:53:09 +08:00
Matt Johnston
fb8fb7fed0 add dbmalloc epoch cleanup
--HG--
branch : fuzz
2017-05-21 10:54:11 +08:00
Matt Johnston
1abd239b9d ignore wrapfd_close for unknown
--HG--
branch : fuzz
2017-05-21 10:48:18 +08:00
Matt Johnston
9f1c8b2f8f make buf_getstring fail prior to malloc if the buffer is short
--HG--
branch : fuzz
2017-05-20 23:39:01 +08:00
Matt Johnston
c169423051 glaring wrapfd problems fixed
--HG--
branch : fuzz
2017-05-20 22:47:19 +08:00
Matt Johnston
fdc6f32392 closer to working
--HG--
branch : fuzz
2017-05-20 13:23:16 +08:00
Matt Johnston
ea984cfb95 add cve and patch link 2017-05-20 10:27:29 +08:00
Matt Johnston
e7cdb2ebe5 add wrapfd. improve fuzzer in makefile
--HG--
branch : fuzz
2017-05-19 00:48:46 +08:00
Matt Johnston
4dae8edb76 merge main to fuzz
--HG--
branch : fuzz
2017-05-18 23:45:10 +08:00
Matt Johnston
a3e01b8884 better harness
--HG--
branch : fuzz
2017-05-18 23:38:30 +08:00
Matt Johnston
6d33a2b0bb setup svr_dropbear_exit
--HG--
branch : fuzz
2017-05-18 23:36:54 +08:00
Matt Johnston
423be0d5e6 merge coverity
--HG--
branch : coverity
2017-05-18 23:02:39 +08:00
Matt Johnston
f7d38a1b9c merge main 2017-05-18 23:00:12 +08:00
Matt Johnston
45b27b0194 merge 2017.75 2017-05-18 22:59:38 +08:00
Matt Johnston
2a921c2c25 Added signature for changeset 5c9207ceedae 2017-05-18 22:58:18 +08:00
Matt Johnston
4c759cde1f Added tag DROPBEAR_2017.75 for changeset c31276613181 2017-05-18 22:58:14 +08:00
Matt Johnston
c3984c89f7 fix changelog for atomic dropbearkey 2017-05-18 21:31:13 +08:00
Matt Johnston
96dfbc882d bump version to 2017.75 2017-05-17 23:57:58 +08:00
Matt Johnston
d3883e54b8 changes for 2017.75 2017-05-17 23:57:18 +08:00
Matt Johnston
beaff53a79 rename fuzzer -> fuzz-target, add list-fuzz-targets
--HG--
branch : fuzz
2017-05-14 00:00:21 +08:00
Matt Johnston
b9b308f2fe Use CXX to link fuzzer, also link with $FUZZLIB
--HG--
branch : fuzz
2017-05-13 23:46:01 +08:00
Matt Johnston
a7bfd792f7 crypto_init()
--HG--
branch : fuzz
2017-05-13 23:45:51 +08:00
Matt Johnston
06fd9e3771 fix buf->pos when shrinking
--HG--
branch : fuzz
2017-05-13 23:44:12 +08:00
Matt Johnston
fb719e3d0b fuzz harness
--HG--
branch : fuzz
2017-05-13 22:50:54 +08:00
Matt Johnston
9f24cdf74c copy over some fuzzing code from AFL branch
--HG--
branch : fuzz
2017-05-12 23:14:54 +08:00
Matt Johnston
d7471c4f87 notsocket changes from afl branch
--HG--
branch : fuzz
2017-05-12 22:14:49 +08:00
Matt Johnston
5d2cb48f46 Use atomic key generation in all cases 2016-11-19 00:31:21 +08:00
Matt Johnston
597f12c44a Use atomic key generation in all cases 2016-11-19 00:31:21 +08:00
Matt Johnston
9f674382d5 Merge pull request #27 from fperrad/20160325_lint
more linting
2016-11-18 23:56:22 +08:00
Matt Johnston
6830a65923 Merge pull request #26 from fperrad/kill_kr
remove K&R old style code
2016-11-18 22:48:50 +08:00
Francois Perrad
0d9c3fe70b initialize variable and protect against NULL dereferencement 2016-11-15 15:36:05 +01:00
Francois Perrad
2e38ac7504 initialize variable 2016-11-15 15:33:27 +01:00
Francois Perrad
f208d7920c remove duplicated include 2016-11-15 15:31:50 +01:00
Francois Perrad
ecb4a6173d upgrade atomicio
in order to remove K&R code in atomicio.c

now, vwrite comes from atomicio.h
2016-11-15 14:56:25 +01:00
Francois Perrad
37a66fa5b6 upgrade strlcat
in order to remove K&R code
2016-11-15 14:56:25 +01:00
Andre McCurdy
f9e6bc2aec Fix libtomcrypt/libtommath linking order
To prevent build failures when using system libtom libraries and
linking with --as-needed, LIBTOM_LIBS should be in the order
-ltomcrypt -ltommath, not the other way around, ie libs should be
prepended to LIBTOM_LIBS as they are found, not appended.

Signed-off-by: Andre McCurdy <armccurdy@gmail.com>
2016-09-16 16:29:28 -07:00
Matt Johnston
81a0240491 add CVEs and patch urls 2016-09-15 21:43:57 +08:00
Matt Johnston
b4d31b492c merge 2016-09-09 21:08:32 +08:00
Matt Johnston
32df924d02 ses.debug_trace is wrong 2016-09-01 23:08:56 +08:00
Stefan Hauser
c60a65bc93 Fix configure options using AC_ARG_ENABLE
Configure options to disable some features, which are checked using
AC_ARG_ENABLE can be invoked with --enable-<option> as well.
The current configure script always generates a #define for such options
even though the --enable-<option> case should not generate a #define.
Fix this by properly checking if the feature should be enabled, in which
case no #define is being generated.

Signed-off-by: Stefan Hauser <stefan@shauser.net>
2016-07-27 20:08:57 +02:00
Matt Johnston
68b3ef0734 merge coverity
--HG--
branch : coverity
2016-07-22 00:08:02 +08:00
Matt Johnston
4222251d6f merge github 2016-07-22 00:04:47 +08:00
Matt Johnston
c6e912f9e2 merge 2016.74 2016-07-21 23:38:42 +08:00
Matt Johnston
1df5c97144 Added signature for changeset 9030ffdbe562 2016-07-21 23:20:25 +08:00
Matt Johnston
b840a0f500 Added tag DROPBEAR_2016.74 for changeset 0ed3d2bbf956 2016-07-21 23:19:41 +08:00
Matt Johnston
9f40bbba29 mention regression release 2016-07-21 23:16:57 +08:00
Matt Johnston
0086e1d7ca bump version 2016-07-21 23:04:47 +08:00
Matt Johnston
4732de71c6 changelogs 2016-07-21 23:04:24 +08:00
Matt Johnston
8db9415f2a merge 2016-06-21 22:04:30 +08:00
Matt Johnston
dd19d73db4 make sure socket is of the right domain 2016-06-19 20:38:38 +08:00
Ben Gardner
91450c7a95 Add .gitignore file
Ignored are all files created when building from a git checkout as well as
anything deleted by 'make clean'.

Signed-off-by: Ben Gardner <gardner.ben@gmail.com>
2016-05-25 10:17:50 -05:00
Ben Gardner
1d20df627d termcodes: make VEOL2, VWERASE, VLNEXT, ECHOCTL, and ECHOKE optional
My POSIX-like platform is missing some basic termcodes.
Make them optional.

Signed-off-by: Ben Gardner <gardner.ben@gmail.com>
2016-05-25 10:03:53 -05:00
Ben Gardner
4a10b1961c Change label name _ERR to LBL_ERR
_ERR is defined in stdio.h on my platform.

Signed-off-by: Ben Gardner <gardner.ben@gmail.com>
2016-05-25 09:57:53 -05:00
Ben Gardner
100cbc5f3f Use DROPBEAR_PATH_DEVNULL instead of undefined _PATH_DEVNULL 2016-05-25 09:52:23 -05:00
Matt Johnston
e0c6e819c2 Merge pull request #29 from hno/patch-out-of-tree
Support out-of-tree builds usign bundled libtom
2016-05-12 23:47:35 +08:00
Henrik Nordström
9025cd9b72 Support out-of-tree builds usign bundled libtom
When building out-of-tree we need both source and generated
folders in include paths to find both distributed and generated
headers.
2016-05-11 12:35:06 +02:00
Matt Johnston
2b891f5eb3 listenaddr must be malloced 2017-05-16 23:04:57 +08:00
Matt Johnston
01bde8ff94 reduce buf->pos if shrinking 2017-05-13 23:43:09 +08:00
Matt Johnston
eed0e2e431 add CVEs and patch urls 2016-09-15 21:43:57 +08:00
Matt Johnston
bda3bc4c8d free forced_command 2017-05-10 00:20:33 +08:00
Matt Johnston
93f3c31807 switch user when opening authorized_keys 2017-05-10 00:20:21 +08:00
Henrik Nordström
3aeb557196 Support out-of-tree builds usign bundled libtom
When building out-of-tree we need both source and generated
folders in include paths to find both distributed and generated
headers.
2016-05-11 12:35:06 +02:00
Matt Johnston
8c7ebc02a0 Add generated header default_options.h to version control.
This is a workaround since I cannot figure how to get dependencies
to work properly with "make -j"
2016-05-04 17:59:34 +02:00
Matt Johnston
1152e47b52 message about truncated banner 2016-05-04 15:28:33 +02:00
Matt Johnston
32a28d0d9c Convert #ifdef to #if, other build changes 2016-05-04 15:33:40 +02:00
Matt Johnston
d6daad29fc options for disabling "normal" DH 2016-05-02 23:48:16 +02:00
Matt Johnston
4664ce2c35 move group14 and group16 to options.h, group14-sha256 on by default 2016-05-02 17:03:55 +02:00
Matt Johnston
171456c683 Avoid busy loop while waiting for rekey response 2016-04-29 23:04:10 +08:00
Matt Johnston
2c73fd6fbf make sure socket is of the right domain 2016-06-19 20:38:38 +08:00
Matt Johnston
0ee860a011 make indenting consistent 2016-07-12 23:33:15 +08:00
Matt Johnston
5127943673 add length checks for ecc too 2016-07-12 23:28:42 +08:00
Matt Johnston
3ee9656250 merge fixes from PuTTY import.c
toint() from misc.c

(revids are from hggit conversion)

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

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

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

(cherry picked from commit 5b7833cd474a24ec098654dcba8cb9509f3bf2c1)

Conflicts:
	import.c

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


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

[originally from svn r9918]


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

[originally from svn r9896]


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

[originally from svn r6476]


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

[originally from svn r3847]


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

[originally from svn r3761]


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

[originally from svn r3479]
2016-07-12 23:00:01 +08:00
Matt Johnston
c0f63ee100 additional length checks 2016-07-11 23:34:18 +08:00
Matt Johnston
8fd720c3e3 Improve exit message formatting 2016-07-11 23:09:33 +08:00
Matt Johnston
4f5d0756c2 improve algorithm list parsing 2016-07-11 22:40:38 +08:00
Matt Johnston
64e6e3aca9 better TRACE of failed remote ident 2016-07-11 21:51:25 +08:00
Matt Johnston
8174300429 Avoid busy loop while waiting for rekey response 2016-04-29 23:04:10 +08:00
Matt Johnston
a453b06168 Avoid osx "install" race 2016-04-12 21:22:21 +08:00
Matt Johnston
103036c546 Add manpage and log for forced_command 2016-04-12 21:05:40 +08:00
Jeremy Kerr
ac9a4c839f Add -c <command> option to force a specific command
This change adds a -c option to dropbear, to force the session to use a
specific command, in a similar fashion to OpenSSH's ForceCommand
configuration option.

This is useful to provide a simple fixed service over ssh, without
requiring an authorized key file for the per-key forced_command option.

This setting takes precedence over the channel session's provided
command, and the per-key forced_command setting.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
2016-04-12 21:01:08 +08:00
Matt Johnston
3d2ddd15f8 Added signature for changeset 70705edee9dd 2016-03-18 23:51:50 +08:00
Matt Johnston
ea4ab22017 Added tag DROPBEAR_2016.73 for changeset 309e1c4a8768 2016-03-18 23:51:34 +08:00
Matt Johnston
d58e0497cc merge
--HG--
branch : coverity
2016-03-18 22:47:33 +08:00
Matt Johnston
af10eb8346 merge
--HG--
branch : coverity
2016-03-15 23:20:40 +08:00
Matt Johnston
8e93ac9925 merge up to date
--HG--
branch : coverity
2016-03-15 22:45:43 +08:00
Matt Johnston
6d5b27715a merge
--HG--
branch : coverity
2015-12-15 22:24:34 +08:00
Matt Johnston
f295fbe0b2 merge
--HG--
branch : coverity
2015-12-02 22:37:51 +08:00
Matt Johnston
575f0e5f92 merge
--HG--
branch : coverity
2015-11-23 23:04:48 +08:00
Matt Johnston
85374c5ba2 merge
--HG--
branch : coverity
2015-08-07 21:26:03 +08:00
Matt Johnston
83f3f55280 merge
--HG--
branch : coverity
2015-06-23 21:49:04 +08:00
Matt Johnston
b2beb2c2da coverity shouldn't have a matrix
--HG--
branch : coverity
2015-06-13 23:39:55 +08:00
Matt Johnston
48ad370a19 fix travis coverity matrix?
--HG--
branch : coverity
2015-06-13 23:36:03 +08:00
Matt Johnston
c36f94a322 fiddle with coverity travis
--HG--
branch : coverity
2015-06-13 23:32:15 +08:00
Matt Johnston
6493bbb7e7 merge up to date, attempt to fix travis.yml
--HG--
branch : coverity
2015-06-12 23:02:15 +08:00
Matt Johnston
3ec2737d54 merge main
--HG--
branch : coverity
2015-04-14 20:44:30 +08:00
Matt Johnston
72ccfda5b2 merge
--HG--
branch : coverity
2015-03-02 21:17:41 +08:00
Matt Johnston
003ec5d356 merge
--HG--
branch : coverity
2015-02-28 23:25:16 +08:00
Matt Johnston
f91d66448a merge
--HG--
branch : coverity
2015-02-24 22:48:34 +08:00
Matt Johnston
ccfdf7e039 merge
--HG--
branch : coverity
2015-02-10 21:47:43 +08:00
Matt Johnston
95ce05da40 merge
--HG--
branch : coverity
2015-01-28 22:49:55 +08:00
Matt Johnston
c5d53cf81c merge
--HG--
branch : coverity
2015-01-28 21:40:34 +08:00
Matt Johnston
5574460d25 merge
--HG--
branch : coverity
2015-01-04 22:33:12 +08:00
Matt Johnston
233fd96994 merge to coverity
--HG--
branch : coverity
2014-10-21 22:34:20 +08:00
Matt Johnston
d1b29336b1 merge
--HG--
branch : coverity
2014-08-19 23:36:46 +08:00
Matt Johnston
fa5eb62464 merge
--HG--
branch : coverity
2014-08-08 21:26:07 +08:00
Matt Johnston
0b48a4f879 merge
--HG--
branch : coverity
2014-07-28 23:38:54 +08:00
Matt Johnston
00ef081fcf merge
--HG--
branch : coverity
2014-07-28 22:56:07 +08:00
Matt Johnston
dabeaec461 merge
--HG--
branch : coverity
2014-07-26 10:23:53 +08:00
Matt Johnston
d4ed2fffe4 merge
--HG--
branch : coverity
2014-07-25 22:23:50 +08:00
Matt Johnston
0533b87b1a merge
--HG--
branch : coverity
2014-03-08 21:02:02 +08:00
Matt Johnston
7504cd1a1a Don't 'make install' for coverity
--HG--
branch : coverity
2014-03-08 21:00:32 +08:00
Matt Johnston
482dc0eff4 Fix the right build line
--HG--
branch : coverity
2014-03-08 18:16:11 +08:00
Matt Johnston
fc34d02427 Fix quoting for coverity
--HG--
branch : coverity
2014-03-08 18:09:00 +08:00
Matt Johnston
5ce5fbcba0 More for coverity
--HG--
branch : coverity
2014-03-08 16:56:15 +08:00
Matt Johnston
31d2311537 Add coverity bits
--HG--
branch : coverity
2014-03-08 14:56:27 +08:00
961 changed files with 111590 additions and 48407 deletions

27
.gitignore vendored Normal file
View File

@@ -0,0 +1,27 @@
*~
*.o
*.a
*.da
*.bb
*.bbg
*.prof
.*.swp
/autom4te.cache
/config.log
/config.status
/dbclient
/dropbear
/dropbearconvert
/dropbearkey
/dropbearmulti
/fuzzcorpus
/fuzzer-*
/fuzzer-*.options
/scp
/scp-progress
Makefile
config.h
config.h.in
configure
default_options_guard.h
tags

2
.hgignore Normal file
View File

@@ -0,0 +1,2 @@
.*\.o
.*~

View File

@@ -20,3 +20,10 @@ af074dbcb68ff8670b3818e0d66d5dc6f1bd5877 0 iQIcBAABCgAGBQJWVdQfAAoJEPSYMBLCC7qs+
5bb5976e6902a0c9fba974a880c68c9487ee1e77 0 iQIcBAABCgAGBQJWVyIKAAoJEESTFJTynGdzQosP/0k5bVTerpUKZLjyNuMU8o0eyc7njkX8EyMOyGbtcArKpzO2opSBTRsuCT9Zsk1iiQ1GMTY1quKD7aNr86Hipqo4th/+ZXmLe9mmaCDukKjD0ZYC4dBVUy6RSUAMvdkDP9sZs7CMTO/22a9SqOsKTv3s2NN6XnsBGnmNbvVx5hkAk5hMVNFrjKIaexzI/7bWQIDRo2HQCaWaL06JvWEDSEQd2mynGSXxT/+m4hBnuGg6qxn2pd4XfG0g10tDAFx64HQkWgZqSB+F8z71Cvfjondy1zjJYgtABqNlwCKQJZhRUW2+PblqQnz08TUy83XN2vtisOju4avGcHSaBgBbMvg8Wx4ZtM7sPP9pLrhhOTd5ceERHeTceTJy+iI1SQFvccjrRfs5aJ0zAQX5q6f4bV0zp5SmxkvnZUEkZIoetkM8VrPOYugqx31LtHAWfVT9NM+VkV/rrxLhk6J0giIQvC9MPWxRDileFVDszPiOgTLcxWjOziOLT+xijcj7dtx1b/f2bNCduN5G7i+icjjTlCNtyRPRqhBqn705W7F+xESP2gsscM/1BjQ7TGidU5m1njdkUjbrqm3+Qic6iqkG7SfETHmQB9mHqpJ0hACRPvZlhwB7oimNHllkrlw8UJw9f0SiuLjfERIgVS2EOp+mAia0RU7MlTt19o017M1ffEYL
926e7275cef4f4f2a4251597ee4814748394824c 0 iQIcBAABCgAGBQJWYES4AAoJEESTFJTynGdzdT0P/0O/1frevtr698DwMe6kmJx35P6Bqq8szntMxYucv0HROTfr85JRcCCSvl/2SflDS215QmOxdvYLGLUWPJNz/gURCLpzsT88KLF68Y1tC72nl4Fj+LGIOlsWsvwEqQqw0v4iQkHIfcxI6q7g1r9Hfldf/ju4bzQ4HnKLxm6KNcLLoAsuehVpQ+njHpLmlLAGHU5a84B7xeXHFR+U/EBPxSdm637rNhmpLpkuK2Mym/Mzv7BThKDstpB8lhFHIwAVNqi3Cy4nGYxFZOJpooUN9pDornqAwuzHmOAMs9+49L8GZ1de5PBRGyFKibzjBIUWPEU9EIkfJVaVwTlqYK8Q/IRi9HjITPx6GpE8cZhdSvAibrQdb6BbIDrZ8eCvD9vnod6Uk0Jb9/ui6nCF9x+CN/3Qez4epV5+JCMYsqCiXFkVPm9Lab6L2eGZis7Q2TXImA/sSV+E4BGfH2urpkKlnuXTTtDp4XRG+lOISkIBXgjVY+uy8soVKNdx1gv+LeY8hu/oQ2NyOlaOeL47aSQ3who4Pk6pVRUOl6zfcKo9Vs6xDWm35A3Z6x/mrAENaXasB0JrfY5nIbefJUpbeSmi76fYldU98HdQNHPHCSeiKVYl7v/B6gi2JXp5xngLZz/5VVAurago7sRmpIp7G/AqU6LNE85IUzG8aQz8AfR0d1dW
fd1981f41c626a969f07b4823848deaefef3c8aa 0 iQIcBAABCgAGBQJW4W2TAAoJEESTFJTynGdzuOcP/j6tvB2WRwSj39KoJuRcRebFWWv4ZHiQXYMXWa3X0Ppzz52r9W0cXDjjlp5FyGdovCQsK+IXmjPo5cCvWBrZJYA6usFr9ssnUtTC+45lvPxPYwj47ZGPngCXDt7LD+v08XhqCu4LsctXIP/zejd30KVS1eR2RHI+tnEyaIKC0Xaa0igcv74MZX7Q8/U+B730QMX5adfYAHoeyRhoctRWaxVV3To7Vadd9jNXP45MRY5auhRcK7XyQcS85vJeCRoysfDUas4ERRQWYkX+68GyzO9GrkYFle931Akw2K6ZZfUuiC2TrF5xv1eRP1Zm2GX481U4ZGFTI8IzZL8sVQ6tvzq2Mxsecu589JNui9aB2d8Gp2Su/E2zn0h0ShIRmviGzf2HiBt+Bnji5X2h/fJKWbLaWge0MdOU5Jidfyh9k0YT7xo4piJLJYSaZ3nv+j4jTYnTfL7uYvuWbYkJ1T32aQVCan7Eup3BFAgQjzbWYi1XQVg6fvu8uHPpS3tNNA9EAMeeyTyg1l6zI2EIU5gPfd/dKmdyotY2lZBkFZNJqFkKRZuzjWekcw7hAxS+Bd68GKklt/DGrQiVycAgimqwXrfkzzQagawq2fXL2uXB8ghlsyxKLSQPnAtBF2Jcn5FH2z7HOQ+e18ZrFfNy0cYa/4OdH6K5aK1igTzhZZP2Urn0
70705edee9dd29cd3d410f19fbd15cc3489313e2 0 iQIcBAABCgAGBQJW7CQRAAoJEESTFJTynGdzTj0QAJL38CKSZthBAeI9c6B+IlwIeT6kPZaPqk1pkycCTWOe87NiNU9abrsF+JrjTuRQiO1EpM2IvfQEIXTijUcMxvld3PnzrZDDv6UvBLtOkn3i++HSVRO0MOuTKI8gFDEPUxRtcaCKXEbqYnf1OTK25FT09Vb//qP9mK1thvlLJmbV+D2a9MkMK66rom1d1h+347IsuwsM+ycHjB80VVAQLA7VYLC5YIwmL17dSmcQLvetfikAMwwmUE+KES4qiLSaqOcAWcKcU67RZzgMMv5o0rESlQmv1nj0mHZtHoUR71sd21emPaRXLOr0oT5YogWUphKq2qVthRn2B06+vd3hPdtn92CmJw9j7zT2jl4OeSjNm9qfAajsRzHIANssFxkGAb7w/LxcMoO29JC+01iUUJMdOVm+4Ns6wGI7qxssWPKdB+VbQUDlHrXLR+sopO524uhkYoWB6DVfTj4R6tImaHtj5/VXON0lsYaLGj8cSH60emL6nNQ0lYV/bSlk6l0s+0x3uXGZnp9oKA+vqMzHfG3vJeMm6KUqtFVjUsYx+q8nHm5/SlWxj1EwnkH8s8ELKZAUXjd76nWEwJ7JFRNRSQWvjOUh3/rsOo4JopzZXPsjCjm+Vql9TG0X6hB21noai32oD5RvfhtR/NX6sXNS5TKZz/j/cMsMnAAsSKb6W7Jm
9030ffdbe5625e35ed7189ab84a41dfc8d413e9c 0 iQIcBAABCgAGBQJXkOg0AAoJEESTFJTynGdzc1kP/3vSKCnhOOvjCjnpTQadYcCUq8vTNnfLHYVu0R4ItPa/jT6RmxoaYP+lZnLnnBx9+aX7kzwHsa9BUX3MbMEyLrOzX2I+bDJbNPhQyupyCuPYlf5Q9KVcO9YlpbsC4q5XBzCn3j2+pT8kSfi9uD8fgY3TgE4w9meINrfQAealfjwMLT8S/I49/ni0r+usSfk/dnSShJYDUO7Ja0VWbJea/GkkZTu30bCnMUZPjRApipU3hPP63WFjkSMT1rp2mAXbWqyr9lf8z32yxzM9nMSjq4ViRFzFlkGtE3EVRJ4PwkO7JuiWAMPJpiQcEr+r52cCsmWhiGyHuINo01MwoMO9/n6uL1WVa3mJcE9se3xBOvfgDu2FRFGCAdm1tef+AGVo9EG1uJXi0sX2yUc6DMeuYaRWrXMMlZh7zp9cuNU9Y/lLui9RFmq66yeXG3Z2B72doju3Ig5QGrNNw2AOsSzeHdAtOp6ychqPcl9QfIeJQG18KyPSefZKM3G8YRKBRIwXFEH6iZJe5ZIP4iXrHDMn2JqtTRtDqKR8VNDAgb9z4Ffx8QRxFyj5JzTTMM1GddHb9udLvTQlO0ULYG7hCSMRNzvUBE2aTw8frjLRyfyyg3QpDu/hz8op8s1ecE8rTCD8RuX9DiiylNozypPtGNS+UDbAmkc1PCWaRpPVl+9K6787
5c9207ceedaea794f958224c19214d66af6e2d56 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAlkdtooACgkQRJMUlPKcZ3P6ZxAAmLy/buZB/d96DJF/pViRWt/fWdjQFC4MqWfeSLW02OZ8Qkm1vPL3ln6WPHC2thy3xZWVg2uan3pLk/XXnsIFu8Q7r1EAfFFpvlMUmdl7asE8V6ilaeqmiI7bIvGMFbf4cZkQliLjiFkJX56tFHRCNi+rb7WgRuru3/GzPXUq2AvXZvFpFJgik0B72TxVlmCKeBRZq1FvP0UhAH48RJWYJksdEyzh2paMfjX9ZO5Q2SFFrmPw6k2ArdJFC1AYcgceZC84y06RKJ0WiSntUPlEUXgQbQVVWbtQDhjfJXMr/beuroNdT/vsRraLVkAzvhaDXNnHlAJNLQxci+AcLpnzZhxMW+ax7RRtrpXGxRN4cs0lBGUcSkaDybFqMYXwEjXAE8w6fdJRWCIlxctkAW/iNEO4kAG97hI2Qwcw5oU2Ymnv09zyGR+XJE35pJqPulJHExdwanJHvmjH0QF7TNFS82yxS5dKnP954cj3Lu9SWGYWjxQJRmLtOwb+lqqol4VTxG7Ois4uef9/Tpp9skeMZXVeNlpn2wrp6iFcX3uiiVDg9VKkl3ig6UqCiqQSuiIN87RXwUOeHXlCnW3adz3Xei0ziBrwLSql7lBIHGEAlUUNmJ3CrR8IwQtcynGEMKfNIeZ/XK+uNlm9cJIqZf1fzqc8KexlyS9AS0i/kiYZTr4=
2f0c3f3361d3ea4eb9129ed8810699fda7e7a8ee 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAlqVb+IACgkQRJMUlPKcZ3OENA//R9HsOUJQB2QZjRgAvqgLn2AMLUvmWb2etTZEc3Nps957Fw1F4kjh6VGfIpWuytfsDx1W8qRx09ikTdb3YteMWCuX8/aFreSPrioYmzrAEcxkZdA7B/jciqU0iXuHiJ9saKk5TR70aNp+iRy0hjAgiYEsVMF9YKHzULOJcHr70x9XVKquubQkwNqJA+/b2JbK2j46wM5nVK/alGSI2kMmEzXmAHQxsvf1OLMvgH8ou/l0xsg/CuFEK299XKfZAbsFEXrjuoWZ1aSa6rTeOWsWli5T+czyyJHI4Eu0Sz/gaR8+MPhJSYes8YjvzEdv32rRMDVOdBq4e+HoTgFt/THYABP6/R1H5fX3Lm4K8u9F9SwJbb/YKRAIrfWDob8ApnGFHk2dyYO20Fskbbg6b1pC7ulDWsufu8lYkQyMlTc3dR6P4eTB6mKO4x+gMG6tIYZ60fiULoEnMJCgegPtevmz+TG1rzdjh3ljiw9Dxz5lNtL+W7sBKKHwhyG0u+bavgmvBMKNL/rdHEM+0yCIz1U6Lb8sVaST1E4zbdm7cWHbSozBij3G0GBSkLFEq7ZLlh8wco9rELRh0Y9fFsWY9j6H/PTOu0GfHrYluFb9WGywHAquQY8j2croRx+MrvTbR1wZrbevPNm9gqk3vgOiDWu7KwxLLqcj+dEQ7tccptVYtbM=
07b0d56d186d7eeef4106137a3eba554959ba0e3 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAlyWOo8ACgkQRJMUlPKcZ3O+MQ//c5oeDUvZuFiI4FHZqfIK/59YAciTP+9TQmoWDVSuOdkd9ZYJA7b7DCusqP2TWFEIl9M7i5hTLTMD21xuEQQtfOSP6EXpUw6JNdh/lsJs7EDlFANtwkdEozAQozFKnXbJEV3y9WldEWUlmPFjt4fJQIuG10SU7MTJHcSaQddJCh3I1//F4EvgRe+OqyrFwKekGiFdvfjcIFN3lQmk6K1Sc0MgyIO/VVZm/AQpBi0Dlg0yOl+EDcxxlmeSInbvLceWSP6op35I4dE5YWH1UetjzIsr5AIM15/k3viAKDDefY1EMAzK9b7YAF4BLw0a6XoQu0apvcWaALE/bJzWNSg/QbCm2JAZzk21WLLvR+AELzPfKXrHX3o0h51lpQ4rs7EWKUm43dJPoWkcFNOU+BDsNzffcJgChbRs48ut89DYLiGmSxhRxE77VPbA+klgTGdctOTLd8psseRlGYCuGe8zeota80bV9fUZ9WJZHwNgEWGowKUoTjy6l5k9OH3iQuQX3OXoy78ufRgWDulE7noVTMhXurQ8a0Jf2k/MW9dcnqGVkWitCFKPEvZwVmWyW2AWsdMcBJnFFGzDsNSxWTtCF9XcxieDO1IB8vGwYcb1TwEVuVzvR/wwvc3PgVikF+4Qv2NqdoQc1yn2PkocY2hwXyIZUAwz7erNumlTbeC/JK8=
ebcdb893992d286d363e60f5353d6e1401e7084b 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAlybhXAACgkQRJMUlPKcZ3O7pQ//QuNJfBVa7ROaOJOR2H/xr6PRn1Fnc6rr/GCF9cqWrbGP6wNo24dRjcu5LxviqPvzfwRXIMXwVz8L/y61/sm6XcA7VFP4+MBoltfeUOdMbfBdtwEUo3WMBdP1w2q5GgYj8ZY6MawiLEqFba5aua7dokTNBOQM3Yebj+9I16MiWEaRSnuwYPoieHW2Fo6oftcIgs/GCXwT2xYzc0n3FpYAbK7u6sEkpL16EstV0Y/G70+X1/4Mg3GM96S5fl9Zbun47W7/+gT4AQVQjE+UnPNDudObAe+2BaOZLFvEbd7iJBBcqtjpBktuP58IEAb3A3srUCy49LNLWk43lj+PtoslK/U6TShKQ2vAgfd//bbn6ieXFJY8N+wYPpJo1m7zpTiEtS7J7wu6vkGGZlqUAj6MHXZj223CgazhSAlg/XFPs9oz3Y96c33Tnd4jB9iEXNNt5jzCAMImx2huSGgnP0JFAbcniq/ug5tl1VWaracvSuJl7fmf17DbmehsLbvtZBoMlePY7Ssfb5IokfVvptt4zRpRZnjtWfHCjtC6zYhtvXTmXH/bqWwx9MMjOf5WPfZoCMvXfMqdVI15FVbxU15WnqjvdvKUCkdz1aMFzxqc4MXgyvjtB9CvO/8WwBOJ2m2nDdiZfh8/H8SawYqEHgB61FX5xA5aXecgXcjQnqWDDxw=
4877afd51e041eca7749cc46b57fd80aa23815b4 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAl7nmREACgkQRJMUlPKcZ3PG1BAAnUl0/nTnQ3CMM3S72DT1JQ1eDxZa14r6r1xEPngU83hNNzmPcnfiMDts+Vz1M3PLxNNOXVVt/MTw04+V9joPhhSWEe8O1pd3lAqTPswL7hhIEbVwZwyFCuAV4iAm+tHKzKLjtjgZfMgij6XylOmw18VBw5R+suoOMclJqeHlJ5m0Mq2wRLDE+RdVCAkulTqhGYjJNQUXMMNPx/cxUo3NHsto9pWL3d1285vBByP6BQSaeYlO012InvJRlQuEkK3lnIyzq6voIc6+tMli0q9iyBz+2GIloBQNAnb6EGaXxqAOBW5NRc+/Oauiu8Yf/6JoFlkAIcPXmGRtxiAiynJImhiTaCFdgdxaXLFzjBvq+tcwVXvvNM52fOZ4Z3QgMDu6EgNWfma0lsg4T3ar2ml2/evuWeLVut5ZmYFHarTFX+/pTVy9nAZK/F5ROJM1prTNYI18PZV4qvULta8spGV2Be0rCkQQubp9RWdKHNGZE70lrX5OnNIwE/D3g2QE04243i0IGBwhlDEpYjqujLyHk8W6XE1CORx0hQ0fUjzKZsRvOB7XyMAFpQUVOhoMFcnk5XHDW6B/U7NAxzqNqO+gbHO/UIeuy/KOVlMNJCmtRL/HYNGZ6SCZbRpyX3d8Ow0sasNfJkZrT6a0Tf6lZktWOxtPkoEDLfuCzudzn4JxGQM=

View File

@@ -52,3 +52,10 @@ cbd674d63cd4f3781464a8d4056a5506c8ae926f DROPBEAR_2015.67
79a6ef02307d05cb9dda10465cb5b807baa8f62e DROPBEAR_2015.70
9a944a243f08be6b22d32f166a0690eb4872462b DROPBEAR_2015.71
78b12b6549be08b0bea3da329b2578060a76ca31 DROPBEAR_2016.72
309e1c4a87682b6ca7d80b8555a1db416c3cb7ac DROPBEAR_2016.73
0ed3d2bbf956cb8a9bf0f4b5a86b7dd9688205cb DROPBEAR_2016.74
c31276613181c5cff7854e7ef586ace03424e55e DROPBEAR_2017.75
1c66ca4f3791c82501c88e7637312182c7294978 DROPBEAR_2018.76
6d1bbe7d5fa5827c7eae28bca044d691f7efa785 DROPBEAR_2019.77
009d52ae26d35f3381c801e02318fa9be34be93c DROPBEAR_2019.78
e2e4929d057b09422f2ea4556fb64209aff58161 DROPBEAR_2020.79

View File

@@ -1,28 +1,19 @@
language: c
os:
- linux
- osx
git:
depth: 3
env:
matrix:
- BUNDLEDLIBTOM=--disable-bundled-libtom WEXTRAFLAGS=-Werror
- BUNDLEDLIBTOM=--enable-bundled-libtom
- MULTI=1
- NOWRITEV=1
global:
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
# via the "travis encrypt" command using the project repo's public key
- secure: "F4rKQrHK/u58vPo3F9+x0WYXAeMFJvvtH9BIGZqx9yw8bUnL+gk0Ge9wnHHTXRcgCTqoc7B35uMS5njpH+Su/esVjrLAq85f/AmQctlRpmApwGK9LyxkIvx3UJN0nqfeeDXA90/8FUZ+n/qnCydXmYCEgqSaBCNydDxW1oqYUIc="
- BUNDLEDLIBTOM=--enable-bundled-libtom
- MULTI=1
# TODO: remove this section when libtomcrypt compiles on OSX: https://github.com/libtom/libtomcrypt/issues/82
matrix:
exclude:
- os: osx
env: BUNDLEDLIBTOM=--disable-bundled-libtom WEXTRAFLAGS=-Werror
before_install:
- echo -n | openssl s_client -connect https://scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-
compiler:
- gcc
- clang
# container-based builds
sudo: false
addons:
apt:
packages:
@@ -30,22 +21,16 @@ addons:
- zlib1g-dev
- libtomcrypt-dev
- libtommath-dev
coverity_scan:
project:
name: "mkj/dropbear"
description: "Dropbear SSH"
notification_email: matt@ucc.asn.au
build_command_prepend: autoconf && autoheader && ./configure --enable-bundled-libtom CFLAGS='-O2 -Wall -Wno-pointer-sign' --prefix=$HOME/inst
build_command: make MULTI=1
branch_pattern: coverity
before_install:
- if [ "$CC" = "clang" ]; then WEXTRAFLAGS="$WEXTRAFLAGS -Wno-error=incompatible-library-redeclaration" ; fi # workaround
install:
- if [ "$TRAVIS_OS_NAME" = "osx" -a "$BUNDLEDLIBTOM" = "--disable-bundled-libtom" ]; then brew update > /dev/null && brew install libtomcrypt libtommath ; fi
script:
- autoconf && autoheader && ./configure "$BUNDLEDLIBTOM" CFLAGS="-O2 -Wall -Wno-pointer-sign $WEXTRAFLAGS" --prefix="$HOME/inst"
- if [ "$NOWRITEV" = "1" ]; then sed -i -e s/HAVE_WRITEV/DONT_HAVE_WRITEV/ config.h ; fi
- make -j3 install
after_success:
- ~/inst/bin/dropbearkey -t rsa -f testrsa
- ~/inst/bin/dropbearkey -t dss -f testdss
- ~/inst/bin/dropbearkey -t ecdsa -f testec256 -s 256
- ~/inst/bin/dropbearkey -t ecdsa -f testec384 -s 384
- ~/inst/bin/dropbearkey -t ecdsa -f testec521 -s 521
branches:
only:
- master
- coverity

283
CHANGES
View File

@@ -1,3 +1,280 @@
2020.80 - 26 June 2020
- Don't block authorized_keys logins with no-X11-forwarding or no-agent-forwarding
restrictions when X11 or agent forwarding are disabled at compile time.
This is more of a problem now X11 is disabled by default, reported by Guilhem Moulin
- Reduce binary size by 4kB (x64) when using bundled libtommath
- Define GNU_SOURCE for getrandom() on uclibc, reported by Laurent Bercot and
Fabrice Fontaine
- Improve checking libtomcrypt version compatibility
- Add some style notes to DEVELOPING.md
2020.79 - 15 June 2020
- Support ed25519 hostkeys and authorized_keys, many thanks to Vladislav Grishenko.
This also replaces curve25519 with a TweetNaCl implementation that reduces code size.
- Add chacha20-poly1305 authenticated cipher. This will perform faster than AES
on many platforms. Thanks to Vladislav Grishenko
- Support using rsa-sha2 signatures. No changes are needed to hostkeys/authorized_keys
entries, existing RSA keys can be used with the new signature format (signatures
are ephemeral within a session). Old ssh-rsa signatures will no longer
be supported by OpenSSH in future so upgrading is recommended.
- Use getrandom() call on Linux to ensure sufficient entropy has been gathered at startup.
Dropbear now avoids reading from the random source at startup, instead waiting until
the first connection. It is possible that some platforms were running without enough
entropy previously, those could potentially block at first boot generating host keys.
The dropbear "-R" option is one way to avoid that.
- Upgrade libtomcrypt to 1.18.2 and libtommath to 1.2.0, many thanks to Steffen Jaeckel for
updating Dropbear to use the current API. Dropbear's configure script will check
for sufficient system library versions, otherwise using the bundled versions.
- CBC ciphers, 3DES, hmac-sha1-96, and x11 forwarding are now disabled by default.
They can be set in localoptions.h if required.
Blowfish has been removed.
- Support AES GCM, patch from Vladislav Grishenko. This is disabled by default,
Dropbear doesn't currently use hardware accelerated AES.
- Added an API for specifying user public keys as an authorized_keys replacement.
See pubkeyapi.h for details, thanks to Fabrizio Bertocci
- Fix idle detection clashing with keepalives, thanks to jcmathews
- Include IP addresses in more early exit messages making it easier for fail2ban
processing. Patch from Kevin Darbyshire-Bryant
- scp fix for CVE-2018-20685 where a server could modify name of output files
- SSH_ORIGINAL_COMMAND is set for "dropbear -c" forced command too
- Fix writing key files on systems without hard links, from Matt Robinson
- Compatibility fixes for IRIX from Kazuo Kuroi
- Re-enable printing MOTD by default, was lost moving from options.h. Thanks to zciendor
- Call fsync() is called on parent directory when writing key files to ensure they are flushed
- Fix "make install" for manpages in out-of-tree builds, from Gabor Z. Papp
- Some notes are added in DEVELOPING.md
2019.78 - 27 March 2019
- Fix dbclient regression in 2019.77. After exiting the terminal would be left
in a bad state. Reported by Ryan Woodsmall
2019.77 - 23 March 2019
- Fix server -R option with ECDSA - only advertise one key size which will be accepted.
Reported by Peter Krefting, 2018.76 regression.
- Fix server regression in 2018.76 where multiple client -R forwards were all forwarded
to the first destination. Reported by Iddo Samet.
- Make failure delay more consistent to avoid revealing valid usernames, set server password
limit of 100 characters. Problem reported by usd responsible disclosure team
- Change handling of failed authentication to avoid disclosing valid usernames,
CVE-2018-15599.
- Fix dbclient to reliably return the exit code from the remote server.
Reported by W. Mike Petullo
- Fix export of 521-bit ECDSA keys, from Christian Hohnstädt
- Add -o Port=xxx option to work with sshfs, from xcko
- Merged fuzzing code, see FUZZER-NOTES.md
- Add a DROPBEAR_SVR_MULTIUSER=0 compile option to run on
single-user Linux kernels (CONFIG_MULTIUSER disabled). From Patrick Stewart
- Increase allowed username to 100 characters, reported by W. Mike Petullo
- Update config.sub and config.guess, should now work with RISC-V
- Cygwin compile fix from karel-m
- Don't require GNU sed (accidentally in 2018.76), reported by Samuel Hsu
- Fix for IRIX and writev(), reported by Kazuo Kuroi
- Other fixes and cleanups from François Perrad, Andre McCurdy, Konstantin Demin,
Michael Jones, Pawel Rapkiewicz
2018.76 - 27 February 2018
> > > Configuration/compatibility changes
IMPORTANT
Custom configuration is now specified in localoptions.h rather than options.h
Available options and defaults can be seen in default_options.h
To migrate your configuration, compare your customised options.h against the
upstream options.h from your relevant version. Any customised options should
be put in localoptions.h in the build directory.
- "configure --enable-static" should now be used instead of "make STATIC=1"
This will avoid 'hardened build' flags that conflict with static binaries
- Set 'hardened build' flags by default if supported by the compiler.
These can be disabled with configure --disable-harden if needed.
-Wl,-pie
-Wl,-z,now -Wl,-z,relro
-fstack-protector-strong
-D_FORTIFY_SOURCE=2
# spectre v2 mitigation
-mfunction-return=thunk
-mindirect-branch=thunk
Spectre patch from Loganaden Velvindron
- "dropbear -r" option for hostkeys no longer attempts to load the default
hostkey paths as well. If desired these can be specified manually.
Patch from CamVan Nguyen
- group1-sha1 key exchange is disabled in the server by default since
the fixed 1024-bit group may be susceptible to attacks
- twofish ciphers are now disabled in the default configuration
- Default generated ECDSA key size is now 256 (rather than 521)
for better interoperability
- Minimum RSA key length has been increased to 1024 bits
> > > Other features and fixes
- Add runtime -T max_auth_tries option from Kevin Darbyshire-Bryant
- Add 'dbclient -J &fd' to allow dbclient to connect over an existing socket.
See dbclient manpage for a socat example. Patch from Harald Becker
- Add "-c forced_command" option. Patch from Jeremy Kerr
- Restricted group -G option added with patch from stellarpower
- Support server-chosen TCP forwarding ports, patch from houseofkodai
- Allow choosing outgoing address for dbclient with -b [bind_address][:bind_port]
Patch from houseofkodai
- Makefile will now rebuild object files when header files are modified
- Add group14-256 and group16 key exchange options
- curve25519-sha256 also supported without @libssh.org suffix
- Update bundled libtomcrypt to 1.18.1, libtommath to 1.0.1
This fixes building with some recent versions of clang
- Set PAM_RHOST which is needed by modules such as pam_abl
- Improvements to DSS and RSA public key validation, found by OSS-Fuzz.
- Don't exit when an authorized_keys file has malformed entries. Found by OSS-Fuzz
- Fix null-pointer crash with malformed ECDSA or DSS keys. Found by OSS-Fuzz
- Numerous code cleanups and small issues fixed by Francois Perrad
- Test for pkt_sched.h rather than SO_PRIORITY which was problematic with some musl
platforms. Reported by Oliver Schneider and Andrew Bainbridge
- Fix some platform portability problems, from Ben Gardner
- Add EXEEXT filename suffix for building dropbearmulti, from William Foster
- Support --enable-<option> properly for configure, from Stefan Hauser
- configure have_openpty result can be cached, from Eric Bénard
- handle platforms that return close() < -1 on failure, from Marco Wenzel
- Build and configuration cleanups from Michael Witten
- Fix libtomcrypt/libtommath linking order, from Andre McCurdy
- Fix old Linux platforms that have SYS_clock_gettime but not CLOCK_MONOTONIC
- Update curve25519-donna implementation to current version
2017.75 - 18 May 2017
- Security: Fix double-free in server TCP listener cleanup
A double-free in the server could be triggered by an authenticated user if
dropbear is running with -a (Allow connections to forwarded ports from any host)
This could potentially allow arbitrary code execution as root by an authenticated user.
Affects versions 2013.56 to 2016.74. Thanks to Mark Shepard for reporting the crash.
CVE-2017-9078 https://secure.ucc.asn.au/hg/dropbear/rev/c8114a48837c
- Security: Fix information disclosure with ~/.ssh/authorized_keys symlink.
Dropbear parsed authorized_keys as root, even if it were a symlink. The fix
is to switch to user permissions when opening authorized_keys
A user could symlink their ~/.ssh/authorized_keys to a root-owned file they
couldn't normally read. If they managed to get that file to contain valid
authorized_keys with command= options it might be possible to read other
contents of that file.
This information disclosure is to an already authenticated user.
Thanks to Jann Horn of Google Project Zero for reporting this.
CVE-2017-9079 https://secure.ucc.asn.au/hg/dropbear/rev/0d889b068123
- Generate hostkeys with dropbearkey atomically and flush to disk with fsync
Thanks to Andrei Gherzan for a patch
- Fix out of tree builds with bundled libtom
Thanks to Henrik Nordström and Peter Krefting for patches.
2016.74 - 21 July 2016
- Security: Message printout was vulnerable to format string injection.
If specific usernames including "%" symbols can be created on a system
(validated by getpwnam()) then an attacker could run arbitrary code as root
when connecting to Dropbear server.
A dbclient user who can control username or host arguments could potentially
run arbitrary code as the dbclient user. This could be a problem if scripts
or webpages pass untrusted input to the dbclient program.
CVE-2016-7406
https://secure.ucc.asn.au/hg/dropbear/rev/b66a483f3dcb
- Security: dropbearconvert import of OpenSSH keys could run arbitrary code as
the local dropbearconvert user when parsing malicious key files
CVE-2016-7407
https://secure.ucc.asn.au/hg/dropbear/rev/34e6127ef02e
- Security: dbclient could run arbitrary code as the local dbclient user if
particular -m or -c arguments are provided. This could be an issue where
dbclient is used in scripts.
CVE-2016-7408
https://secure.ucc.asn.au/hg/dropbear/rev/eed9376a4ad6
- Security: dbclient or dropbear server could expose process memory to the
running user if compiled with DEBUG_TRACE and running with -v
CVE-2016-7409
https://secure.ucc.asn.au/hg/dropbear/rev/6a14b1f6dc04
The security issues were reported by an anonymous researcher working with
Beyond Security's SecuriTeam Secure Disclosure www.beyondsecurity.com/ssd.html
- Fix port forwarding failure when connecting to domains that have both
IPv4 and IPv6 addresses. The bug was introduced in 2015.68
- Fix 100% CPU use while waiting for rekey to complete. Thanks to Zhang Hui P
for the patch
2016.73 - 18 March 2016
- Support syslog in dbclient, option -o usesyslog=yes. Patch from Konstantin Tokarev
@@ -32,6 +309,7 @@
- Validate X11 forwarding input. Could allow bypass of authorized_keys command= restrictions,
found by github.com/tintinweb. Thanks for Damien Miller for a patch. CVE-2016-3116
https://secure.ucc.asn.au/hg/dropbear/rev/a3e8389e01ff
2015.71 - 3 December 2015
@@ -265,6 +543,8 @@ kernels, from Steve Dover
2013.61test - Thursday 14 November 2013
- Default generated RSA key size changed from 1024 to 2048 bits
- ECC (elliptic curve) support. Supports ECDSA hostkeys (requires new keys to
be generated) and ECDH for setting up encryption keys (no intervention
required). This is significantly faster.
@@ -310,9 +590,11 @@ kernels, from Steve Dover
- Limit the size of decompressed payloads, avoids memory exhaustion denial
of service
Thanks to Logan Lamb for reporting and investigating it. CVE-2013-4421
https://secure.ucc.asn.au/hg/dropbear/rev/0bf76f54de6f
- Avoid disclosing existence of valid users through inconsistent delays
Thanks to Logan Lamb for reporting. CVE-2013-4434
https://secure.ucc.asn.au/hg/dropbear/rev/d7784616409a
- Update config.guess and config.sub for newer architectures
@@ -415,6 +697,7 @@ though probably will be soon
This bug affects releases 0.52 onwards. Ref CVE-2012-0920.
Thanks to Danny Fullerton of Mantor Organization for reporting
the bug.
https://secure.ucc.asn.au/hg/dropbear/rev/818108bf7749
- Compile fix, only apply IPV6 socket options if they are available in headers
Thanks to Gustavo Zacarias for the patch

75
DEVELOPING.md Normal file
View File

@@ -0,0 +1,75 @@
# Developer Notes
## Building
See [INSTALL](INSTALL) for build instructions.
[SMALL](SMALL) has hints for building smaller binaries, also see comments
in default_options.h.
## Debug printing
Set `#define DEBUG_TRACE 1` in localoptions.h to enable a `-v` option
for dropbear and dbclient. That prints various details of the session. For
development running `dropbear -F -E` is useful to run in the foreground. You
can set `#define DEBUG_NOFORK 1` to make dropbear a one-shot server, easy to
run under a debugger.
## Random sources
Most cryptography requires a good random entropy source, both to generate secret
keys and in the course of a session. Dropbear uses the Linux kernel's
`getrandom()` syscall to ensure that the system RNG has been initialised before
using it. On some systems there is insufficient entropy gathered during early
boot - generating hostkeys then will block for some amount of time.
Dropbear has a `-R` option to generate hostkeys upon the first connection
as required - that will allow the system more time to gather entropy.
## Algorithms
Default algorithm lists are specified in [common-algo.c](common-algo.c).
They are in priority order, the client's first matching choice is used
(see rfc4253).
Dropbear client has `-c` and `-m` arguments to choose which are enabled at
runtime (doesn't work for server as of June 2020).
Enabling/disabling algorithms is done in [localoptions.h](localoptions.h),
see [default_options.h](default_options.h).
## Style
Source code is indented with tabs, width set to 4 (though width shouldn't
matter much). Braces are on the same line as functions/loops/if - try
to keep consistency with existing code.
All `if` statements should have braces, no exceptions.
Avoid using pointer arithmetic, instead the functions in
[buffer.h](buffer.h) should be used.
Some Dropbear platforms have old compilers.
Variable declarations must be at the top of a scope and
comments must be `/* */` rather than `//`.
Pointer variables should be initialised to NULL - it can reduce the
severity of bugs.
## Third party code
Libtomcrypt and libtommath are periodically synced from upstream, so
avoid making changes to that code which will need to be maintained.
Improvements can be sent upstream to the libtom project.
## Non-root user
Dropbear server will run fine as a non-root user, allowing logins only for
that user. Password authentication probably won't work (can't read shadow
passwords). You will need to create hostkeys that are readable.
## Connection setup
Dropbear implements first_kex_packet_follows to reduce
handshake latency (rfc 4253 7.1). Some less common implementations don't
handle that, it can be a cause of problems connecting. Note also that
Dropbear may send several ssh packets within a single TCP packet - it's just a
stream.

77
FUZZER-NOTES.md Normal file
View File

@@ -0,0 +1,77 @@
# Fuzzing Dropbear
Dropbear is process-per-session so it assumes calling `dropbear_exit()`
is fine at any point to clean up. This makes fuzzing a bit trickier.
A few pieces of wrapping infrastructure are used to work around this.
The [libfuzzer](http://llvm.org/docs/LibFuzzer.html#fuzz-target) harness
expects a long running process to continually run a test function with
a string of crafted input. That process should not leak resources or exit.
## longjmp
When dropbear runs in fuzz mode it sets up a
[`setjmp()`](http://man7.org/linux/man-pages/man3/setjmp.3.html) target prior
to launching the code to be fuzzed, and then [`dropbear_exit()`](dbutil.c#L125)
calls `longjmp()` back there. This avoids exiting though it doesn't free
memory or other resources.
## malloc Wrapper
Dropbear normally uses a [`m_malloc()`](dbmalloc.c) function that is the same as `malloc()` but
exits if allocation fails. In fuzzing mode this is replaced with a tracking allocator
that stores all allocations in a linked list. After the `longjmp()` occurs the fuzzer target
calls [`m_malloc_free_epoch(1, 1)`](dbmalloc.c) to clean up any unreleased memory.
If the fuzz target runs to completion it calls `m_malloc_free_epoch(1, 0)` which will reset
the tracked allocations but will not free memory - that allows libfuzzer's leak checking
to detect leaks in normal operation.
## File Descriptor Input
As a network process Dropbear reads and writes from a socket. The wrappers for
`read()`/`write()`/`select()` in [fuzz-wrapfd.c](fuzz-wrapfd.c) will read from the
fuzzer input that has been set up with `wrapfd_add()`. `write()` output is
currently discarded.
These also test error paths such as EINTR and short reads with certain probabilities.
This allows running the entire dropbear server process with network input provided by the
fuzzer, without many modifications to the main code. At the time of writing this
only runs the pre-authentication stages, though post-authentication could be run similarly.
## Encryption and Randomness
When running in fuzzing mode Dropbear uses a [fixed seed](dbrandom.c#L185)
every time so that failures can be reproduced.
Since the fuzzer cannot generate valid encrypted input the packet decryption and
message authentication calls are disabled, see [packet.c](packet.c).
MAC failures are set to occur with a low probability to test that error path.
## Fuzzers
Current fuzzers are
- [fuzzer-preauth](fuzzer-preauth.c) - the fuzzer input is treated as a stream of session input. This will
test key exchange, packet ordering, authentication attempts etc.
- [fuzzer-preauth_nomaths](fuzzer-preauth_nomaths.c) - the same as fuzzer-preauth but with asymmetric crypto
routines replaced with dummies for faster runtime. corpora are shared
between fuzzers by [oss-fuzz](https://github.com/google/oss-fuzz) so this
will help fuzzer-preauth too.
- [fuzzer-verify](fuzzer-verify.c) - read a key and signature from fuzzer input and verify that signature.
It would not be expected to pass, though some keys with bad parameters are
able to validate with a trivial signature - extra checks are added for that.
- [fuzzer-pubkey](fuzzer-pubkey.c) - test parsing of an `authorized_keys` line.
- [fuzzer-kexdh](fuzzer-kexdh.c) - test Diffie-Hellman key exchange where the fuzz input is the
ephemeral public key that would be received over the network. This is testing `mp_expt_mod()`
and and other libtommath routines.
- [fuzzer-kexecdh](fuzzer-kexecdh.c) - test Elliptic Curve Diffie-Hellman key exchange like fuzzer-kexdh.
This is testing libtommath ECC routines.
- [fuzzer-kexcurve25519](fuzzer-kexcurve25519.c) - test Curve25519 Elliptic Curve Diffie-Hellman key exchange
like fuzzer-kexecdh. This is testing `dropbear_curve25519_scalarmult()` and other libtommath routines.

34
INSTALL
View File

@@ -1,28 +1,42 @@
Basic Dropbear build instructions:
- Edit options.h to set which features you want.
- Edit debug.h if you want any debug options (not usually required).
- Edit localoptions.h to set which features you want. Available options
are described in default_options.h, these will be overridden by
anything set in localoptions.h
localoptions.h should be located in the build directory if you are
building out of tree.
(If using a non-tarball copy, "autoconf; autoheader")
- If using a Mercurial or Git checkout, "autoconf; autoheader"
./configure (optionally with --disable-zlib or --disable-syslog,
- Configure for your system:
./configure (optionally with --disable-zlib or --disable-syslog,
or --help for other options)
Now compile:
- Compile:
make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp"
make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp"
And install (/usr/local/bin is usual default):
- Optionally install, or copy the binaries another way
make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp" install
make install (/usr/local/bin is usual default):
or
make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp" install
(you can leave items out of the PROGRAMS list to avoid compiling them. If you
recompile after changing the PROGRAMS list, you *MUST* "make clean" before
recompiling - bad things will happen otherwise)
DEVELOPING.md has some notes on other developer topics, including debugging.
See MULTI for instructions on making all-in-one binaries.
If you want to compile statically, add "STATIC=1" to the make command-line.
If you want to compile statically use ./configure --enable-static
By default Dropbear adds various build flags that improve robustness
against programming bugs (good for security). If these cause problems
they can be disabled with ./configure --disable-harden
Binaries can be stripped with "make strip"
@@ -44,7 +58,7 @@ Compiling for uClibc should be the same as normal, just set CC to the magic
uClibc toolchain compiler (ie export CC=i386-uclibc-gcc or whatever).
You can use "make STATIC=1" to make statically linked binaries, and it is
advisable to strip the binaries too. If you're looking to make a small binary,
you should remove unneeded ciphers and MD5, by editing options.h
you should remove unneeded ciphers and MD5, by editing localoptions.h
It is possible to compile zlib in, by copying zlib.h and zconf.h into a
subdirectory (ie zlibincludes), and

73
LICENSE
View File

@@ -8,7 +8,7 @@ The majority of code is written by Matt Johnston, under the license below.
Portions of the client-mode work are (c) 2004 Mihnea Stoenescu, under the
same license:
Copyright (c) 2002-2015 Matt Johnston
Copyright (c) 2002-2020 Matt Johnston
Portions copyright (c) 2004 Mihnea Stoenescu
All rights reserved.
@@ -32,7 +32,8 @@ SOFTWARE.
=====
LibTomCrypt and LibTomMath are written by Tom St Denis, and are Public Domain.
LibTomCrypt and LibTomMath are written by Tom St Denis and others, see
libtomcrypt/LICENSE and libtommath/LICENSE.
=====
@@ -90,52 +91,24 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
=====
curve25519-donna:
curve25519.c:
/* Copyright 2008, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* curve25519-donna: Curve25519 elliptic curve, public key function
*
* http://code.google.com/p/curve25519-donna/
*
* Adam Langley <agl@imperialviolet.org>
*
* Derived from public domain C code by Daniel J. Bernstein <djb@cr.yp.to>
*
* More information about curve25519 can be found here
* http://cr.yp.to/ecdh.html
*
* djb's sample implementation of curve25519 is written in a special assembly
* language called qhasm and uses the floating point registers.
*
* This is, almost, a clean room reimplementation from the curve25519 paper. It
* uses many of the tricks described therein. Only the crecip function is taken
* from the sample implementation.
*/
Modified TweetNaCl version 20140427, a self-contained public-domain C library.
https://tweetnacl.cr.yp.to/
Contributors (alphabetical order)
Daniel J. Bernstein, University of Illinois at Chicago and Technische
Universiteit Eindhoven
Bernard van Gastel, Radboud Universiteit Nijmegen
Wesley Janssen, Radboud Universiteit Nijmegen
Tanja Lange, Technische Universiteit Eindhoven
Peter Schwabe, Radboud Universiteit Nijmegen
Sjaak Smetsers, Radboud Universiteit Nijmegen
Acknowledgments
This work was supported by the U.S. National Science Foundation under grant
1018836. "Any opinions, findings, and conclusions or recommendations expressed
in this material are those of the author(s) and do not necessarily reflect the
views of the National Science Foundation."
This work was supported by the Netherlands Organisation for Scientific
Research (NWO) under grant 639.073.005 and Veni 2013 project 13114.

View File

@@ -2,12 +2,11 @@
# @configure_input@
# invocation:
# make PROGRAMS="dropbear dbclient scp" MULTI=1 STATIC=1 SCPPROGRESS=1
# make PROGRAMS="dropbear dbclient scp" MULTI=1 SCPPROGRESS=1
#
# to make a multiple-program statically linked binary "staticdropbearmulti".
# to make a multiple-program binary "dropbearmulti".
# This example will include dropbear, scp, dropbearkey, dropbearconvert, and
# dbclient functionality, and includes the progress-bar functionality in scp.
# Hopefully that seems intuitive.
ifndef PROGRAMS
PROGRAMS=dropbear dbclient dropbearkey dropbearconvert
@@ -20,8 +19,15 @@ LIBTOM_LIBS=@LIBTOM_LIBS@
ifeq (@BUNDLED_LIBTOM@, 1)
LIBTOM_DEPS=$(STATIC_LTC) $(STATIC_LTM)
LIBTOM_CLEAN=ltc-clean ltm-clean
CFLAGS+=-I$(srcdir)/libtomcrypt/src/headers/
LIBTOM_LIBS=$(STATIC_LTC) $(STATIC_LTM)
LIBTOM_LIBS=$(STATIC_LTC) $(STATIC_LTM)
endif
OPTION_HEADERS = default_options_guard.h sysoptions.h
ifneq ($(wildcard localoptions.h),)
CFLAGS+=-DLOCALOPTIONS_H_EXISTS
OPTION_HEADERS += localoptions.h
endif
COMMONOBJS=dbutil.o buffer.o dbhelpers.o \
@@ -30,7 +36,9 @@ COMMONOBJS=dbutil.o buffer.o dbhelpers.o \
queue.o \
atomicio.o compat.o fake-rfc2553.o \
ltc_prng.o ecc.o ecdsa.o crypto_desc.o \
gensignkey.o gendss.o genrsa.o
curve25519.o ed25519.o \
dbmalloc.o \
gensignkey.o gendss.o genrsa.o gened25519.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 \
@@ -45,7 +53,7 @@ CLIOBJS=cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \
CLISVROBJS=common-session.o packet.o common-algo.o common-kex.o \
common-channel.o common-chansession.o termcodes.o loginrec.o \
tcp-accept.o listener.o process-packet.o dh_groups.o \
common-runopts.o circbuffer.o curve25519-donna.o list.o netio.o
common-runopts.o circbuffer.o list.o netio.o chachapoly.o gcm.o
KEYOBJS=dropbearkey.o
@@ -53,18 +61,34 @@ CONVERTOBJS=dropbearconvert.o keyimport.o
SCPOBJS=scp.o progressmeter.o atomicio.o scpmisc.o compat.o
HEADERS=options.h dbutil.h session.h packet.h algo.h ssh.h buffer.h kex.h \
dss.h bignum.h signkey.h rsa.h dbrandom.h service.h auth.h \
debug.h channel.h chansession.h config.h queue.h sshpty.h \
termcodes.h gendss.h genrsa.h runopts.h includes.h \
loginrec.h atomicio.h x11fwd.h agentfwd.h tcpfwd.h compat.h \
listener.h fake-rfc2553.h ecc.h ecdsa.h
ifeq (@DROPBEAR_FUZZ@, 1)
allobjs = $(COMMONOBJS) fuzz-common.o fuzz-wrapfd.o $(CLISVROBJS) $(CLIOBJS) $(SVROBJS) @CRYPTLIB@
allobjs:=$(subst svr-main.o, ,$(allobjs))
allobjs:=$(subst cli-main.o, ,$(allobjs))
allobjs:=$(sort $(allobjs))
dropbearobjs=$(COMMONOBJS) $(CLISVROBJS) $(SVROBJS)
dbclientobjs=$(COMMONOBJS) $(CLISVROBJS) $(CLIOBJS)
dropbearkeyobjs=$(COMMONOBJS) $(KEYOBJS)
dropbearconvertobjs=$(COMMONOBJS) $(CONVERTOBJS)
scpobjs=$(SCPOBJS)
dropbearobjs=$(allobjs) svr-main.o
dbclientobjs=$(allobjs) cli-main.o
dropbearkeyobjs=$(allobjs) $(KEYOBJS)
dropbearconvertobjs=$(allobjs) $(CONVERTOBJS)
# CXX only set when fuzzing
CXX=@CXX@
else
dropbearobjs=$(COMMONOBJS) $(CLISVROBJS) $(SVROBJS)
dbclientobjs=$(COMMONOBJS) $(CLISVROBJS) $(CLIOBJS)
dropbearkeyobjs=$(COMMONOBJS) $(KEYOBJS)
dropbearconvertobjs=$(COMMONOBJS) $(CONVERTOBJS)
scpobjs=$(SCPOBJS)
endif
ifeq (@DROPBEAR_PLUGIN@, 1)
# rdynamic makes all the global symbols of dropbear available to all the loaded shared libraries
# this allow a plugin to reuse existing crypto/utilities like base64_decode/base64_encode without
# the need to rewrite them.
PLUGIN_LIBS=-ldl -rdynamic
else
PLUGIN_LIBS=
endif
VPATH=@srcdir@
srcdir=@srcdir@
@@ -76,6 +100,8 @@ bindir=@bindir@
sbindir=@sbindir@
mandir=@mandir@
.DELETE_ON_ERROR:
CC=@CC@
AR=@AR@
RANLIB=@RANLIB@
@@ -88,9 +114,10 @@ LDFLAGS=@LDFLAGS@
EXEEXT=@EXEEXT@
STATIC=@STATIC@
# whether we're building client, server, or both for the common objects.
# evilness so we detect 'dropbear' by itself as a word
space:= $(empty) $(empty)
ifneq (,$(strip $(foreach prog, $(PROGRAMS), $(findstring ZdropbearZ, Z$(prog)Z))))
CFLAGS+= -DDROPBEAR_SERVER
endif
@@ -98,7 +125,6 @@ ifneq (,$(strip $(foreach prog, $(PROGRAMS), $(findstring ZdbclientZ, Z$(prog)Z)
CFLAGS+= -DDROPBEAR_CLIENT
endif
# these are exported so that libtomcrypt's makefile will use them
export CC
export CFLAGS
@@ -109,7 +135,7 @@ ifeq ($(STATIC), 1)
endif
ifeq ($(MULTI), 1)
TARGETS=dropbearmulti
TARGETS=dropbearmulti$(EXEEXT)
else
TARGETS=$(PROGRAMS)
endif
@@ -121,24 +147,35 @@ endif
all: $(TARGETS)
# for simplicity assume all source depends on all headers
HEADERS=$(wildcard $(srcdir)/*.h *.h) $(OPTION_HEADERS)
%.o : %.c $(HEADERS)
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
default_options_guard.h: default_options.h
@echo Creating $@
@printf "/*\n > > > Do not edit this file (default_options_guard.h) < < <\nGenerated from "$^"\nLocal customisation goes in localoptions.h\n*/\n\n" > $@.tmp
@$(srcdir)/ifndef_wrapper.sh < $^ >> $@.tmp
@mv $@.tmp $@
strip: $(TARGETS)
$(STRIP) $(addsuffix $(EXEEXT), $(TARGETS))
install: $(addprefix inst_, $(TARGETS))
insmultidropbear: dropbearmulti
insmultidropbear: dropbearmulti$(EXEEXT)
$(INSTALL) -d $(DESTDIR)$(sbindir)
-rm -f $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
-ln -s $(bindir)/dropbearmulti$(EXEEXT) $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
$(INSTALL) -d $(DESTDIR)$(mandir)/man8
$(INSTALL) -m 644 $(srcdir)/dropbear.8 $(DESTDIR)$(mandir)/man8/dropbear.8
insmulti%: dropbearmulti
insmulti%: dropbearmulti$(EXEEXT)
$(INSTALL) -d $(DESTDIR)$(bindir)
-rm -f $(DESTDIR)$(bindir)/$*$(EXEEXT)
-ln -s $(bindir)/dropbearmulti$(EXEEXT) $(DESTDIR)$(bindir)/$*$(EXEEXT)
$(INSTALL) -d $(DESTDIR)$(mandir)/man1
if test -e $*.1; then $(INSTALL) -m 644 $*.1 $(DESTDIR)$(mandir)/man1/$*.1; fi
if test -e $(srcdir)/$*.1; then $(INSTALL) -m 644 $(srcdir)/$*.1 $(DESTDIR)$(mandir)/man1/$*.1; fi
# dropbear should go in sbin, so it needs a separate rule
inst_dropbear: dropbear
@@ -151,11 +188,10 @@ inst_%: %
$(INSTALL) -d $(DESTDIR)$(bindir)
$(INSTALL) $*$(EXEEXT) $(DESTDIR)$(bindir)
$(INSTALL) -d $(DESTDIR)$(mandir)/man1
if test -e $*.1; then $(INSTALL) -m 644 $*.1 $(DESTDIR)$(mandir)/man1/$*.1; fi
if test -e $(srcdir)/$*.1; then $(INSTALL) -m 644 $(srcdir)/$*.1 $(DESTDIR)$(mandir)/man1/$*.1; fi
inst_dropbearmulti: $(addprefix insmulti, $(PROGRAMS))
# for some reason the rule further down doesn't like $($@objs) as a prereq.
dropbear: $(dropbearobjs)
dbclient: $(dbclientobjs)
@@ -163,13 +199,13 @@ dropbearkey: $(dropbearkeyobjs)
dropbearconvert: $(dropbearconvertobjs)
dropbear: $(HEADERS) $(LIBTOM_DEPS) Makefile
$(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBTOM_LIBS) $(LIBS) @CRYPTLIB@
$(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBTOM_LIBS) $(LIBS) @CRYPTLIB@ $(PLUGIN_LIBS)
dbclient: $(HEADERS) $(LIBTOM_DEPS) Makefile
$(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBTOM_LIBS) $(LIBS)
dropbearkey dropbearconvert: $(HEADERS) $(LIBTOM_DEPS) Makefile
$(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBTOM_LIBS)
$(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBTOM_LIBS) $(LIBS)
# scp doesn't use the libs so is special.
scp: $(SCPOBJS) $(HEADERS) Makefile
@@ -194,32 +230,104 @@ link%:
-rm -f $*$(EXEEXT)
-ln -s dropbearmulti$(EXEEXT) $*$(EXEEXT)
$(STATIC_LTC): options.h
cd libtomcrypt && $(MAKE)
$(STATIC_LTC): $(OPTION_HEADERS)
$(MAKE) -C libtomcrypt
$(STATIC_LTM): options.h
cd libtommath && $(MAKE)
$(STATIC_LTM): $(OPTION_HEADERS)
$(MAKE) -C libtommath
.PHONY : clean sizes thisclean distclean tidy ltc-clean ltm-clean
.PHONY : clean sizes thisclean distclean tidy ltc-clean ltm-clean lint
ltc-clean:
cd libtomcrypt && $(MAKE) clean
$(MAKE) -C libtomcrypt clean
ltm-clean:
cd libtommath && $(MAKE) clean
$(MAKE) -C libtommath clean
sizes: dropbear
objdump -t dropbear|grep ".text"|cut -d "." -f 2|sort -rn
clean: ltc-clean ltm-clean thisclean
clean: $(LIBTOM_CLEAN) thisclean
thisclean:
-rm -f dropbear dbclient dropbearkey dropbearconvert scp scp-progress \
dropbearmulti *.o *.da *.bb *.bbg *.prof
-rm -f dropbear$(EXEEXT) dbclient$(EXEEXT) dropbearkey$(EXEEXT) \
dropbearconvert$(EXEEXT) scp$(EXEEXT) scp-progress$(EXEEXT) \
dropbearmulti$(EXEEXT) *.o *.da *.bb *.bbg *.prof
distclean: clean tidy
-rm -f config.h
-rm -f Makefile
-rm -f default_options_guard.h
tidy:
-rm -f *~ *.gcov */*~
lint:
cd $(srcdir); ./dropbear_lint.sh
## Fuzzing targets
# list of fuzz targets
FUZZ_TARGETS=fuzzer-preauth fuzzer-pubkey fuzzer-verify fuzzer-preauth_nomaths fuzzer-kexdh fuzzer-kexecdh fuzzer-kexcurve25519
FUZZER_OPTIONS = $(addsuffix .options, $(FUZZ_TARGETS))
list-fuzz-targets:
@echo $(FUZZ_TARGETS)
# fuzzers that don't use libfuzzer, just a standalone harness that feeds inputs
fuzzstandalone: FUZZLIB=fuzz-harness.o
fuzzstandalone: fuzz-harness.o fuzz-targets
# exclude svr-main.o to avoid duplicate main
svrfuzzobjs=$(subst svr-main.o, ,$(dropbearobjs))
fuzz-harness.o: $(HEADERS) $(LIBTOM_DEPS) Makefile $(svrfuzzobjs) fuzz-common.o
# build all the fuzzers. This will require fail to link unless built with
# make fuzz-targets FUZZLIB=-lFuzzer.a
# or similar - the library provides main().
fuzz-targets: $(FUZZ_TARGETS) $(FUZZER_OPTIONS)
fuzzer-preauth: fuzzer-preauth.o fuzz-harness.o
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
fuzzer-preauth_nomaths: fuzzer-preauth_nomaths.o fuzz-harness.o
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
fuzzer-pubkey: fuzzer-pubkey.o fuzz-harness.o
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
fuzzer-verify: fuzzer-verify.o fuzz-harness.o
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
fuzzer-kexdh: fuzzer-kexdh.o fuzz-harness.o
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
fuzzer-kexecdh: fuzzer-kexecdh.o fuzz-harness.o
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
fuzzer-kexcurve25519: fuzzer-kexcurve25519.o fuzz-harness.o
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
fuzzer-%.options: Makefile
echo "[libfuzzer]" > $@
echo "max_len = 50000" >> $@
# run this to update hardcoded hostkeys for for fuzzing.
# hostkeys.c is checked in to hg.
fuzz-hostkeys:
dropbearkey -t rsa -f keyr
dropbearkey -t dss -f keyd
dropbearkey -t ecdsa -size 256 -f keye
dropbearkey -t ed25519 -f keyed25519
echo > hostkeys.c
/usr/bin/xxd -i -a keyr >> hostkeys.c
/usr/bin/xxd -i -a keye >> hostkeys.c
/usr/bin/xxd -i -a keyd >> hostkeys.c
/usr/bin/xxd -i -a keyed25519 >> hostkeys.c
# to make coverity happy?
test:
true

7
README
View File

@@ -8,8 +8,8 @@ which performs multiple tasks, to save disk space)
SMALL has some tips on creating small binaries.
See TODO for a few of the things I know need looking at, and please contact
me if you have any questions/bugs found/features/ideas/comments etc :)
Please contact me if you have any questions/bugs found/features/ideas/comments etc :)
There is also a mailing list http://lists.ucc.gu.uwa.edu.au/mailman/listinfo/dropbear
Matt Johnston
matt@ucc.asn.au
@@ -51,10 +51,11 @@ dropbearkey's '-y' option.
============================================================================
To run the server, you need to server keys, this is one-off:
To run the server, you need to generate server keys, this is one-off:
./dropbearkey -t rsa -f dropbear_rsa_host_key
./dropbearkey -t dss -f dropbear_dss_host_key
./dropbearkey -t ecdsa -f dropbear_ecdsa_host_key
./dropbearkey -t ed25519 -f dropbear_ed25519_host_key
or alternatively convert OpenSSH keys to Dropbear:
./dropbearconvert openssh dropbear /etc/ssh/ssh_host_dsa_key dropbear_dss_host_key

27
TODO
View File

@@ -1,27 +0,0 @@
Current:
Things which might need doing:
- default private dbclient keys
- Make options.h generated from configure perhaps?
- handle /etc/environment in AIX
- check that there aren't timing issues with valid/invalid user authentication
feedback.
- Binding to different interfaces
- CTR mode
- SSH_MSG_IGNORE sending to improve CBC security
- DH Group Exchange possibly, or just add group14 (whatever it's called today)
- fix scp.c for IRIX
- Be able to use OpenSSH keys for the client? or at least have some form of
encrypted keys.
- Client agent forwarding
- Handle restrictions in ~/.ssh/authorized_keys ?

View File

@@ -30,7 +30,10 @@
#include "auth.h"
#include "list.h"
#ifdef ENABLE_CLI_AGENTFWD
#if DROPBEAR_CLI_AGENTFWD
/* From OpenSSH authfd.h */
#define SSH_AGENT_RSA_SHA2_256 0x02
/* An agent reply can be reasonably large, as it can
* contain a list of all public keys held by the agent.
@@ -40,8 +43,8 @@
/* client functions */
void cli_load_agent_keys(m_list * ret_list);
void agent_buf_sign(buffer *sigblob, sign_key *key,
buffer *data_buf);
void cli_setup_agent(struct Channel *channel);
const buffer *data_buf, enum signature_type type);
void cli_setup_agent(const struct Channel *channel);
#ifdef __hpux
#define seteuid(a) setresuid(-1, (a), -1)
@@ -50,14 +53,14 @@ void cli_setup_agent(struct Channel *channel);
extern const struct ChanType cli_chan_agent;
#endif /* ENABLE_CLI_AGENTFWD */
#endif /* DROPBEAR_CLI_AGENTFWD */
#ifdef ENABLE_SVR_AGENTFWD
#if DROPBEAR_SVR_AGENTFWD
int svr_agentreq(struct ChanSess * chansess);
void svr_agentcleanup(struct ChanSess * chansess);
void svr_agentset(struct ChanSess *chansess);
void svr_agentset(const struct ChanSess *chansess);
#endif /* ENABLE_SVR_AGENTFWD */
#endif /* DROPBEAR_SVR_AGENTFWD */
#endif /* DROPBEAR_AGENTFWD_H_ */

40
algo.h
View File

@@ -47,7 +47,7 @@ typedef struct Algo_Type algo_type;
/* lists mapping ssh types of algorithms to internal values */
extern algo_type sshkex[];
extern algo_type sshhostkey[];
extern algo_type sigalgs[];
extern algo_type sshciphers[];
extern algo_type sshhashes[];
extern algo_type ssh_compress[];
@@ -72,6 +72,14 @@ struct dropbear_cipher_mode {
unsigned long len, void *cipher_state);
int (*decrypt)(const unsigned char *ct, unsigned char *pt,
unsigned long len, void *cipher_state);
int (*aead_crypt)(unsigned int seq,
const unsigned char *in, unsigned char *out,
unsigned long len, unsigned long taglen,
void *cipher_state, int direction);
int (*aead_getlength)(unsigned int seq,
const unsigned char *in, unsigned int *outlen,
unsigned long len, void *cipher_state);
const struct dropbear_hash *aead_mac;
};
struct dropbear_hash {
@@ -83,9 +91,15 @@ struct dropbear_hash {
};
enum dropbear_kex_mode {
#if DROPBEAR_NORMAL_DH
DROPBEAR_KEX_NORMAL_DH,
#endif
#if DROPBEAR_ECDH
DROPBEAR_KEX_ECDH,
#endif
#if DROPBEAR_CURVE25519
DROPBEAR_KEX_CURVE25519,
#endif
};
struct dropbear_kex {
@@ -96,7 +110,7 @@ struct dropbear_kex {
const int dh_p_len;
/* elliptic curve DH KEX */
#ifdef DROPBEAR_ECDH
#if DROPBEAR_ECDH
const struct dropbear_ecc_curve *ecc_curve;
#else
const void* dummy;
@@ -106,26 +120,22 @@ struct dropbear_kex {
const struct ltc_hash_descriptor *hash_desc;
};
int have_algo(char* algo, size_t algolen, algo_type algos[]);
void buf_put_algolist(buffer * buf, algo_type localalgos[]);
enum kexguess2_used {
KEXGUESS2_LOOK,
KEXGUESS2_NO,
KEXGUESS2_YES,
};
/* Includes all algorithms is useall is set */
void buf_put_algolist_all(buffer * buf, const algo_type localalgos[], int useall);
/* Includes "usable" algorithms */
void buf_put_algolist(buffer * buf, const algo_type localalgos[]);
#define KEXGUESS2_ALGO_NAME "kexguess2@matt.ucc.asn.au"
#define KEXGUESS2_ALGO_ID 99
int buf_has_algo(buffer *buf, const char *algo);
algo_type * first_usable_algo(algo_type algos[]);
algo_type * buf_match_algo(buffer* buf, algo_type localalgos[],
enum kexguess2_used *kexguess2, int *goodguess);
int kexguess2, int *goodguess);
#ifdef ENABLE_USER_ALGO_LIST
#if DROPBEAR_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[]);
char * algolist_string(const algo_type algos[]);
#endif
enum {

View File

@@ -1,6 +1,8 @@
/* $OpenBSD: atomicio.c,v 1.17 2006/04/01 05:51:34 djm Exp $ */
/*
* Copied from OpenSSH 3.6.1p2.
* Copied from OpenSSH/OpenBSD.
*
* Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
* Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
* All rights reserved.
*
@@ -25,39 +27,32 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* RCSID("OpenBSD: atomicio.c,v 1.10 2001/05/08 22:48:07 markus Exp "); */
#include "includes.h"
#include "atomicio.h"
/*
* ensure all of data on socket comes through. f==read || f==write
* ensure all of data on socket comes through. f==read || f==vwrite
*/
ssize_t
atomicio(f, fd, _s, n)
ssize_t (*f) ();
int fd;
void *_s;
size_t n;
size_t
atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
{
char *s = _s;
ssize_t res;
size_t pos = 0;
ssize_t res;
while (n > pos) {
res = (f) (fd, s + pos, n - pos);
switch (res) {
case -1:
#ifdef EWOULDBLOCK
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
#else
if (errno == EINTR || errno == EAGAIN)
#endif
continue;
/* FALLTHROUGH */
return 0;
case 0:
return (res);
errno = EPIPE;
return pos;
default:
pos += res;
pos += (size_t)res;
}
}
return (pos);

View File

@@ -1,8 +1,7 @@
/* $OpenBSD: atomicio.h,v 1.7 2006/03/25 22:22:42 djm Exp $ */
/*
* Copied from OpenSSH 3.6.1p2, required for loginrec.c
*
* $OpenBSD: atomicio.h,v 1.4 2001/06/26 06:32:46 itojun Exp $
* Copied from OpenSSH/OpenBSD, required for loginrec.c
*
* Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
* All rights reserved.
@@ -28,9 +27,9 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
/*
* Ensure all of data on socket comes through. f==read || f==write
* Ensure all of data on socket comes through. f==read || f==vwrite
*/
ssize_t atomicio(ssize_t (*)(), int, void *, size_t);
size_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
#define vwrite (ssize_t (*)(int, void *, size_t))write

27
auth.h
View File

@@ -36,12 +36,12 @@ void cli_authinitialise(void);
void recv_msg_userauth_request(void);
void send_msg_userauth_failure(int partial, int incrfail);
void send_msg_userauth_success(void);
void send_msg_userauth_banner(buffer *msg);
void svr_auth_password(void);
void svr_auth_pubkey(void);
void svr_auth_pam(void);
void send_msg_userauth_banner(const buffer *msg);
void svr_auth_password(int valid_user);
void svr_auth_pubkey(int valid_user);
void svr_auth_pam(int valid_user);
#ifdef ENABLE_SVR_PUBKEY_OPTIONS
#if DROPBEAR_SVR_PUBKEY_OPTIONS_BUILT
int svr_pubkey_allows_agentfwd(void);
int svr_pubkey_allows_tcpfwd(void);
int svr_pubkey_allows_x11fwd(void);
@@ -74,11 +74,11 @@ void cli_pubkeyfail(void);
void cli_auth_password(void);
int cli_auth_pubkey(void);
void cli_auth_interactive(void);
char* getpass_or_cancel(char* prompt);
char* getpass_or_cancel(const char* prompt);
void cli_auth_pubkey_cleanup(void);
#define MAX_USERNAME_LEN 25 /* arbitrary for the moment */
#define MAX_USERNAME_LEN 100 /* arbitrary for the moment */
#define AUTH_TYPE_NONE 1
#define AUTH_TYPE_PUBKEY (1 << 1)
@@ -105,12 +105,17 @@ struct AuthState {
unsigned char authtypes; /* Flags indicating which auth types are still
valid */
unsigned int failcount; /* Number of (failed) authentication attempts.*/
unsigned authdone : 1; /* 0 if we haven't authed, 1 if we have. Applies for
unsigned int authdone; /* 0 if we haven't authed, 1 if we have. Applies for
client and server (though has differing
meanings). */
unsigned perm_warn : 1; /* Server only, set if bad permissions on
unsigned int perm_warn; /* Server only, set if bad permissions on
~/.ssh/authorized_keys have already been
logged. */
unsigned int checkusername_failed; /* Server only, set if checkusername
has already failed */
struct timespec auth_starttime; /* Server only, time of receiving current
SSH_MSG_USERAUTH_REQUEST */
/* These are only used for the server */
uid_t pw_uid;
@@ -119,12 +124,12 @@ struct AuthState {
char *pw_shell;
char *pw_name;
char *pw_passwd;
#ifdef ENABLE_SVR_PUBKEY_OPTIONS
#if DROPBEAR_SVR_PUBKEY_OPTIONS_BUILT
struct PubKeyOptions* pubkey_options;
#endif
};
#ifdef ENABLE_SVR_PUBKEY_OPTIONS
#if DROPBEAR_SVR_PUBKEY_OPTIONS_BUILT
struct PubKeyOptions;
struct PubKeyOptions {
/* Flags */

View File

@@ -68,9 +68,25 @@ void m_mp_alloc_init_multi(mp_int **mp, ...)
va_end(args);
}
void m_mp_free_multi(mp_int **mp, ...)
{
mp_int** cur_arg = mp;
va_list args;
va_start(args, mp); /* init args to next argument from caller */
while (cur_arg != NULL) {
if (*cur_arg) {
mp_clear(*cur_arg);
}
m_free(*cur_arg);
cur_arg = va_arg(args, mp_int**);
}
va_end(args);
}
void bytes_to_mp(mp_int *mp, const unsigned char* bytes, unsigned int len) {
if (mp_read_unsigned_bin(mp, (unsigned char*)bytes, len) != MP_OKAY) {
if (mp_from_ubin(mp, (unsigned char*)bytes, len) != MP_OKAY) {
dropbear_exit("Mem alloc error");
}
}

View File

@@ -30,6 +30,7 @@
void m_mp_init(mp_int *mp);
void m_mp_init_multi(mp_int *mp, ...) ATTRIB_SENTINEL;
void m_mp_alloc_init_multi(mp_int **mp, ...) ATTRIB_SENTINEL;
void m_mp_free_multi(mp_int **mp, ...) ATTRIB_SENTINEL;
void bytes_to_mp(mp_int *mp, const unsigned char* bytes, unsigned int len);
void hash_process_mp(const struct ltc_hash_descriptor *hash_desc,
hash_state *hs, mp_int *mp);

View File

@@ -67,7 +67,7 @@ void buf_free(buffer* buf) {
}
/* overwrite the contents of the buffer to clear it */
void buf_burn(buffer* buf) {
void buf_burn(const buffer* buf) {
m_burn(buf->data, buf->size);
@@ -91,7 +91,7 @@ buffer* buf_resize(buffer *buf, unsigned int newsize) {
/* Create a copy of buf, allocating required memory etc. */
/* The new buffer is sized the same as the length of the source buffer. */
buffer* buf_newcopy(buffer* buf) {
buffer* buf_newcopy(const buffer* buf) {
buffer* ret;
@@ -109,6 +109,7 @@ void buf_setlen(buffer* buf, unsigned int len) {
dropbear_exit("Bad buf_setlen");
}
buf->len = len;
buf->pos = MIN(buf->pos, buf->len);
}
/* Increment the length of the buffer */
@@ -141,9 +142,10 @@ void buf_incrwritepos(buffer* buf, unsigned int incr) {
/* increment the position by incr, negative values are allowed, to
* decrement the pos*/
void buf_incrpos(buffer* buf, int incr) {
if (incr > BUF_MAX_INCR ||
(unsigned int)((int)buf->pos + incr) > buf->len
|| ((int)buf->pos + incr) < 0) {
if (incr > BUF_MAX_INCR
|| incr < -BUF_MAX_INCR
|| (unsigned int)((int)buf->pos + incr) > buf->len
|| ((int)buf->pos + incr) < 0) {
dropbear_exit("Bad buf_incrpos");
}
buf->pos += incr;
@@ -182,9 +184,9 @@ void buf_putbyte(buffer* buf, unsigned char val) {
/* returns an in-place pointer to the buffer, checking that
* the next len bytes from that position can be used */
unsigned char* buf_getptr(buffer* buf, unsigned int len) {
unsigned char* buf_getptr(const buffer* buf, unsigned int len) {
if (buf->pos + len > buf->len) {
if (len > BUF_MAX_INCR || buf->pos + len > buf->len) {
dropbear_exit("Bad buf_getptr");
}
return &buf->data[buf->pos];
@@ -192,9 +194,9 @@ unsigned char* buf_getptr(buffer* buf, unsigned int len) {
/* like buf_getptr, but checks against total size, not used length.
* This allows writing past the used length, but not past the size */
unsigned char* buf_getwriteptr(buffer* buf, unsigned int len) {
unsigned char* buf_getwriteptr(const buffer* buf, unsigned int len) {
if (buf->pos + len > buf->size) {
if (len > BUF_MAX_INCR || buf->pos + len > buf->size) {
dropbear_exit("Bad buf_getwriteptr");
}
return &buf->data[buf->pos];
@@ -207,6 +209,7 @@ char* buf_getstring(buffer* buf, unsigned int *retlen) {
unsigned int len;
char* ret;
void* src = NULL;
len = buf_getint(buf);
if (len > MAX_STRING_LEN) {
dropbear_exit("String too long");
@@ -215,8 +218,9 @@ char* buf_getstring(buffer* buf, unsigned int *retlen) {
if (retlen != NULL) {
*retlen = len;
}
src = buf_getptr(buf, len);
ret = m_malloc(len+1);
memcpy(ret, buf_getptr(buf, len), len);
memcpy(ret, src, len);
buf_incrpos(buf, len);
ret[len] = '\0';
@@ -224,19 +228,37 @@ char* buf_getstring(buffer* buf, unsigned int *retlen) {
}
/* Return a string as a newly allocated buffer */
buffer * buf_getstringbuf(buffer *buf) {
static buffer * buf_getstringbuf_int(buffer *buf, int incllen) {
buffer *ret = NULL;
unsigned int len = buf_getint(buf);
int extra = 0;
if (len > MAX_STRING_LEN) {
dropbear_exit("String too long");
}
ret = buf_new(len);
if (incllen) {
extra = 4;
}
ret = buf_new(len+extra);
if (incllen) {
buf_putint(ret, len);
}
memcpy(buf_getwriteptr(ret, len), buf_getptr(buf, len), len);
buf_incrpos(buf, len);
buf_incrlen(ret, len);
buf_setpos(ret, 0);
return ret;
}
/* Return a string as a newly allocated buffer */
buffer * buf_getstringbuf(buffer *buf) {
return buf_getstringbuf_int(buf, 0);
}
/* Returns a string in a new buffer, including the length */
buffer * buf_getbuf(buffer *buf) {
return buf_getstringbuf_int(buf, 1);
}
/* Just increment the buffer position the same as if we'd used buf_getstring,
* but don't bother copying/malloc()ing for it */
void buf_eatstring(buffer *buf) {
@@ -285,18 +307,18 @@ void buf_putbytes(buffer *buf, const unsigned char *bytes, unsigned int len) {
/* for our purposes we only need positive (or 0) numbers, so will
* fail if we get negative numbers */
void buf_putmpint(buffer* buf, mp_int * mp) {
size_t written;
unsigned int len, pad = 0;
TRACE2(("enter buf_putmpint"))
dropbear_assert(mp != NULL);
if (SIGN(mp) == MP_NEG) {
if (mp_isneg(mp)) {
dropbear_exit("negative bignum");
}
/* zero check */
if (USED(mp) == 1 && DIGIT(mp, 0) == 0) {
if (mp_iszero(mp)) {
len = 0;
} else {
/* SSH spec requires padding for mpints with the MSB set, this code
@@ -317,10 +339,10 @@ void buf_putmpint(buffer* buf, mp_int * mp) {
if (pad) {
buf_putbyte(buf, 0x00);
}
if (mp_to_unsigned_bin(mp, buf_getwriteptr(buf, len-pad)) != MP_OKAY) {
if (mp_to_ubin(mp, buf_getwriteptr(buf, len-pad), len-pad, &written) != MP_OKAY) {
dropbear_exit("mpint error");
}
buf_incrwritepos(buf, len-pad);
buf_incrwritepos(buf, written);
}
TRACE2(("leave buf_putmpint"))
@@ -348,7 +370,7 @@ int buf_getmpint(buffer* buf, mp_int* mp) {
return DROPBEAR_FAILURE;
}
if (mp_read_unsigned_bin(mp, buf_getptr(buf, len), len) != MP_OKAY) {
if (mp_from_ubin(mp, buf_getptr(buf, len), len) != MP_OKAY) {
return DROPBEAR_FAILURE;
}

View File

@@ -44,8 +44,8 @@ buffer * buf_new(unsigned int size);
/* Possibly returns a new buffer*, like realloc() */
buffer * buf_resize(buffer *buf, unsigned int newsize);
void buf_free(buffer* buf);
void buf_burn(buffer* buf);
buffer* buf_newcopy(buffer* buf);
void buf_burn(const buffer* buf);
buffer* buf_newcopy(const buffer* buf);
void buf_setlen(buffer* buf, unsigned int len);
void buf_incrlen(buffer* buf, unsigned int incr);
void buf_setpos(buffer* buf, unsigned int pos);
@@ -54,10 +54,11 @@ void buf_incrwritepos(buffer* buf, unsigned int incr);
unsigned char buf_getbyte(buffer* buf);
unsigned char buf_getbool(buffer* buf);
void buf_putbyte(buffer* buf, unsigned char val);
unsigned char* buf_getptr(buffer* buf, unsigned int len);
unsigned char* buf_getwriteptr(buffer* buf, unsigned int len);
unsigned char* buf_getptr(const buffer* buf, unsigned int len);
unsigned char* buf_getwriteptr(const buffer* buf, unsigned int len);
char* buf_getstring(buffer* buf, unsigned int *retlen);
buffer * buf_getstringbuf(buffer *buf);
buffer * buf_getbuf(buffer *buf);
void buf_eatstring(buffer *buf);
void buf_putint(buffer* buf, unsigned int val);
void buf_putstring(buffer* buf, const char* str, unsigned int len);

148
chachapoly.c Normal file
View File

@@ -0,0 +1,148 @@
/*
* Dropbear SSH
*
* Copyright (c) 2002,2003 Matt Johnston
* Copyright (c) 2020 by Vladislav Grishenko
* 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 "algo.h"
#include "dbutil.h"
#include "chachapoly.h"
#if DROPBEAR_CHACHA20POLY1305
#define CHACHA20_KEY_LEN 32
#define CHACHA20_BLOCKSIZE 8
#define POLY1305_KEY_LEN 32
#define POLY1305_TAG_LEN 16
static const struct ltc_cipher_descriptor dummy = {.name = NULL};
static const struct dropbear_hash dropbear_chachapoly_mac =
{NULL, POLY1305_KEY_LEN, POLY1305_TAG_LEN};
const struct dropbear_cipher dropbear_chachapoly =
{&dummy, CHACHA20_KEY_LEN*2, CHACHA20_BLOCKSIZE};
static int dropbear_chachapoly_start(int UNUSED(cipher), const unsigned char* UNUSED(IV),
const unsigned char *key, int keylen,
int UNUSED(num_rounds), dropbear_chachapoly_state *state) {
int err;
TRACE2(("enter dropbear_chachapoly_start"))
if (keylen != CHACHA20_KEY_LEN*2) {
return CRYPT_ERROR;
}
if ((err = chacha_setup(&state->chacha, key,
CHACHA20_KEY_LEN, 20)) != CRYPT_OK) {
return err;
}
if ((err = chacha_setup(&state->header, key + CHACHA20_KEY_LEN,
CHACHA20_KEY_LEN, 20) != CRYPT_OK)) {
return err;
}
TRACE2(("leave dropbear_chachapoly_start"))
return CRYPT_OK;
}
static int dropbear_chachapoly_crypt(unsigned int seq,
const unsigned char *in, unsigned char *out,
unsigned long len, unsigned long taglen,
dropbear_chachapoly_state *state, int direction) {
poly1305_state poly;
unsigned char seqbuf[8], key[POLY1305_KEY_LEN], tag[POLY1305_TAG_LEN];
int err;
TRACE2(("enter dropbear_chachapoly_crypt"))
if (len < 4 || taglen != POLY1305_TAG_LEN) {
return CRYPT_ERROR;
}
STORE64H((uint64_t)seq, seqbuf);
chacha_ivctr64(&state->chacha, seqbuf, sizeof(seqbuf), 0);
if ((err = chacha_keystream(&state->chacha, key, sizeof(key))) != CRYPT_OK) {
return err;
}
poly1305_init(&poly, key, sizeof(key));
if (direction == LTC_DECRYPT) {
poly1305_process(&poly, in, len);
poly1305_done(&poly, tag, &taglen);
if (constant_time_memcmp(in + len, tag, taglen) != 0) {
return CRYPT_ERROR;
}
}
chacha_ivctr64(&state->header, seqbuf, sizeof(seqbuf), 0);
if ((err = chacha_crypt(&state->header, in, 4, out)) != CRYPT_OK) {
return err;
}
chacha_ivctr64(&state->chacha, seqbuf, sizeof(seqbuf), 1);
if ((err = chacha_crypt(&state->chacha, in + 4, len - 4, out + 4)) != CRYPT_OK) {
return err;
}
if (direction == LTC_ENCRYPT) {
poly1305_process(&poly, out, len);
poly1305_done(&poly, out + len, &taglen);
}
TRACE2(("leave dropbear_chachapoly_crypt"))
return CRYPT_OK;
}
static int dropbear_chachapoly_getlength(unsigned int seq,
const unsigned char *in, unsigned int *outlen,
unsigned long len, dropbear_chachapoly_state *state) {
unsigned char seqbuf[8], buf[4];
int err;
TRACE2(("enter dropbear_chachapoly_getlength"))
if (len < sizeof(buf)) {
return CRYPT_ERROR;
}
STORE64H((uint64_t)seq, seqbuf);
chacha_ivctr64(&state->header, seqbuf, sizeof(seqbuf), 0);
if ((err = chacha_crypt(&state->header, in, sizeof(buf), buf)) != CRYPT_OK) {
return err;
}
LOAD32H(*outlen, buf);
TRACE2(("leave dropbear_chachapoly_getlength"))
return CRYPT_OK;
}
const struct dropbear_cipher_mode dropbear_mode_chachapoly =
{(void *)dropbear_chachapoly_start, NULL, NULL,
(void *)dropbear_chachapoly_crypt,
(void *)dropbear_chachapoly_getlength, &dropbear_chachapoly_mac};
#endif /* DROPBEAR_CHACHA20POLY1305 */

44
chachapoly.h Normal file
View File

@@ -0,0 +1,44 @@
/*
* Dropbear SSH
*
* Copyright (c) 2002,2003 Matt Johnston
* Copyright (c) 2020 by Vladislav Grishenko
* 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. */
#ifndef DROPBEAR_DROPBEAR_CHACHAPOLY_H_
#define DROPBEAR_DROPBEAR_CHACHAPOLY_H_
#include "includes.h"
#include "algo.h"
#if DROPBEAR_CHACHA20POLY1305
typedef struct {
chacha_state chacha;
chacha_state header;
} dropbear_chachapoly_state;
extern const struct dropbear_cipher dropbear_chachapoly;
extern const struct dropbear_cipher_mode dropbear_mode_chachapoly;
#endif /* DROPBEAR_CHACHA20POLY1305 */
#endif /* DROPBEAR_DROPBEAR_CHACHAPOLY_H_ */

View File

@@ -69,10 +69,6 @@ struct Channel {
int sent_close, recv_close;
int recv_eof, sent_eof;
/* Set after running the ChanType-specific close hander
* to ensure we don't run it twice (nor type->checkclose()). */
int close_handler_done;
struct dropbear_progress_connection *conn_pending;
int initconn; /* used for TCP forwarding, whether the channel has been
fully initialised */
@@ -84,7 +80,7 @@ struct Channel {
int flushing;
/* Used by client chansession to handle ~ escaping, NULL ignored otherwise */
void (*read_mangler)(struct Channel*, unsigned char* bytes, int *len);
void (*read_mangler)(const struct Channel*, const unsigned char* bytes, int *len);
const struct ChanType* type;
@@ -94,11 +90,18 @@ struct Channel {
struct ChanType {
int sepfds; /* Whether this channel has separate pipes for in/out or not */
char *name;
const char *name;
/* Sets up the channel */
int (*inithandler)(struct Channel*);
int (*check_close)(struct Channel*);
/* Called to check whether a channel should close, separately from the FD being closed.
Used for noticing process exiting */
int (*check_close)(const struct Channel*);
/* Handler for ssh_msg_channel_request */
void (*reqhandler)(struct Channel*);
void (*closehandler)(struct Channel*);
/* Called prior to sending ssh_msg_channel_close, used for sending exit status */
void (*closehandler)(const struct Channel*);
/* Frees resources, called just prior to channel being removed */
void (*cleanup)(const struct Channel*);
};
/* Callback for connect_remote */
@@ -107,7 +110,7 @@ void channel_connect_done(int result, int sock, void* user_data, const char* err
void chaninitialise(const struct ChanType *chantypes[]);
void chancleanup(void);
void setchannelfds(fd_set *readfds, fd_set *writefds, int allow_reads);
void channelio(fd_set *readfd, fd_set *writefd);
void channelio(const fd_set *readfd, const fd_set *writefd);
struct Channel* getchannel(void);
/* Returns an arbitrary channel that is in a ready state - not
being initialised and no EOF in either direction. NULL if none. */
@@ -115,8 +118,8 @@ struct Channel* get_any_ready_channel(void);
void recv_msg_channel_open(void);
void recv_msg_channel_request(void);
void send_msg_channel_failure(struct Channel *channel);
void send_msg_channel_success(struct Channel *channel);
void send_msg_channel_failure(const struct Channel *channel);
void send_msg_channel_success(const struct Channel *channel);
void recv_msg_channel_data(void);
void recv_msg_channel_extended_data(void);
void recv_msg_channel_window_adjust(void);
@@ -126,16 +129,16 @@ void recv_msg_channel_eof(void);
void common_recv_msg_channel_data(struct Channel *channel, int fd,
circbuffer * buf);
#ifdef DROPBEAR_CLIENT
#if DROPBEAR_CLIENT
extern const struct ChanType clichansess;
#endif
#if defined(USING_LISTENERS) || defined(DROPBEAR_CLIENT)
#if DROPBEAR_LISTENERS || DROPBEAR_CLIENT
int send_msg_channel_open_init(int fd, const struct ChanType *type);
void recv_msg_channel_open_confirmation(void);
void recv_msg_channel_open_failure(void);
#endif
void start_send_channel_request(struct Channel *channel, char *type);
void start_send_channel_request(const struct Channel *channel, const char *type);
void send_msg_request_success(void);
void send_msg_request_failure(void);

View File

@@ -41,6 +41,9 @@ struct ChanSess {
char * cmd; /* command to exec */
pid_t pid; /* child process pid */
/* command that was sent by the client, if authorized_keys command= or
dropbear -c was used */
char *original_command;
/* pty details */
int master; /* the master terminal fd*/
@@ -58,7 +61,7 @@ struct ChanSess {
/* Used to set $SSH_CLIENT in the child session. */
char *client_string;
#ifndef DISABLE_X11FWD
#if DROPBEAR_X11FWD
struct Listener * x11listener;
int x11port;
char * x11authprot;
@@ -67,15 +70,11 @@ struct ChanSess {
unsigned char x11singleconn;
#endif
#ifdef ENABLE_SVR_AGENTFWD
#if DROPBEAR_SVR_AGENTFWD
struct Listener * agentlistener;
char * agentfile;
char * agentdir;
#endif
#ifdef ENABLE_SVR_PUBKEY_OPTIONS
char *original_command;
#endif
};
struct ChildPid {
@@ -89,11 +88,12 @@ void addnewvar(const char* param, const char* var);
void cli_send_chansess_request(void);
void cli_tty_cleanup(void);
void cli_chansess_winchange(void);
#ifdef ENABLE_CLI_NETCAT
#if DROPBEAR_CLI_NETCAT
void cli_send_netcat_request(void);
#endif
void svr_chansessinitialise(void);
void svr_chansess_checksignal(void);
extern const struct ChanType svrchansess;
struct SigMap {

View File

@@ -56,19 +56,19 @@ void cbuf_free(circbuffer * cbuf) {
m_free(cbuf);
}
unsigned int cbuf_getused(circbuffer * cbuf) {
unsigned int cbuf_getused(const circbuffer * cbuf) {
return cbuf->used;
}
unsigned int cbuf_getavail(circbuffer * cbuf) {
unsigned int cbuf_getavail(const circbuffer * cbuf) {
return cbuf->size - cbuf->used;
}
unsigned int cbuf_writelen(circbuffer *cbuf) {
unsigned int cbuf_writelen(const circbuffer *cbuf) {
dropbear_assert(cbuf->used <= cbuf->size);
dropbear_assert(((2*cbuf->size)+cbuf->writepos-cbuf->readpos)%cbuf->size == cbuf->used%cbuf->size);
@@ -86,7 +86,7 @@ unsigned int cbuf_writelen(circbuffer *cbuf) {
return cbuf->size - cbuf->writepos;
}
void cbuf_readptrs(circbuffer *cbuf,
void cbuf_readptrs(const circbuffer *cbuf,
unsigned char **p1, unsigned int *len1,
unsigned char **p2, unsigned int *len2) {
*p1 = &cbuf->data[cbuf->readpos];

View File

@@ -38,12 +38,12 @@ typedef struct circbuf circbuffer;
circbuffer * cbuf_new(unsigned int size);
void cbuf_free(circbuffer * cbuf);
unsigned int cbuf_getused(circbuffer * cbuf); /* how much data stored */
unsigned int cbuf_getavail(circbuffer * cbuf); /* how much we can write */
unsigned int cbuf_writelen(circbuffer *cbuf); /* max linear write len */
unsigned int cbuf_getused(const circbuffer * cbuf); /* how much data stored */
unsigned int cbuf_getavail(const circbuffer * cbuf); /* how much we can write */
unsigned int cbuf_writelen(const circbuffer *cbuf); /* max linear write len */
/* returns pointers to the two portions of the circular buffer that can be read */
void cbuf_readptrs(circbuffer *cbuf,
void cbuf_readptrs(const circbuffer *cbuf,
unsigned char **p1, unsigned int *len1,
unsigned char **p2, unsigned int *len2);
unsigned char* cbuf_writeptr(circbuffer *cbuf, unsigned int len);

View File

@@ -24,7 +24,7 @@
#include "includes.h"
#ifdef ENABLE_CLI_AGENTFWD
#if DROPBEAR_CLI_AGENTFWD
#include "agentfwd.h"
#include "session.h"
@@ -52,6 +52,7 @@ const struct ChanType cli_chan_agent = {
new_agent_chan,
NULL,
NULL,
NULL,
NULL
};
@@ -108,7 +109,7 @@ static int new_agent_chan(struct Channel * channel) {
data Any data, depending on packet type. Encoding as in the ssh packet
protocol.
*/
static buffer * agent_request(unsigned char type, buffer *data) {
static buffer * agent_request(unsigned char type, const buffer *data) {
buffer * payload = NULL;
buffer * inbuf = NULL;
@@ -130,7 +131,7 @@ static buffer * agent_request(unsigned char type, buffer *data) {
}
buf_setpos(payload, 0);
ret = atomicio(write, fd, buf_getptr(payload, payload->len), payload->len);
ret = atomicio(vwrite, fd, buf_getptr(payload, payload->len), payload->len);
if ((size_t)ret != payload->len) {
TRACE(("write failed fd %d for agent_request, %s", fd, strerror(errno)))
goto out;
@@ -230,7 +231,7 @@ out:
}
}
void cli_setup_agent(struct Channel *channel) {
void cli_setup_agent(const struct Channel *channel) {
if (!getenv("SSH_AUTH_SOCK")) {
return;
}
@@ -254,11 +255,12 @@ void cli_load_agent_keys(m_list *ret_list) {
}
void agent_buf_sign(buffer *sigblob, sign_key *key,
buffer *data_buf) {
const buffer *data_buf, enum signature_type sigtype) {
buffer *request_data = NULL;
buffer *response = NULL;
unsigned int siglen;
int packet_type;
int flags = 0;
/* Request format
byte SSH2_AGENTC_SIGN_REQUEST
@@ -270,7 +272,12 @@ void agent_buf_sign(buffer *sigblob, sign_key *key,
buf_put_pub_key(request_data, key, key->type);
buf_putbufstring(request_data, data_buf);
buf_putint(request_data, 0);
#if DROPBEAR_RSA_SHA256
if (sigtype == DROPBEAR_SIGNATURE_RSA_SHA256) {
flags |= SSH_AGENT_RSA_SHA2_256;
}
#endif
buf_putint(request_data, flags);
response = agent_request(SSH2_AGENTC_SIGN_REQUEST, request_data);

View File

@@ -51,7 +51,7 @@ void cli_auth_getmethods() {
encrypt_packet();
#ifdef DROPBEAR_CLI_IMMEDIATE_AUTH
#if DROPBEAR_CLI_IMMEDIATE_AUTH
/* We can't haven't two auth requests in-flight with delayed zlib mode
since if the first one succeeds then the remote side will
expect the second one to be compressed.
@@ -60,9 +60,11 @@ void cli_auth_getmethods() {
*/
if (ses.keys->trans.algo_comp != DROPBEAR_COMP_ZLIB_DELAY) {
ses.authstate.authtypes = AUTH_TYPE_PUBKEY;
#if DROPBEAR_USE_PASSWORD_ENV
if (getenv(DROPBEAR_PASSWORD_ENV)) {
ses.authstate.authtypes |= AUTH_TYPE_PASSWORD | AUTH_TYPE_INTERACT;
}
#endif
if (cli_auth_try() == DROPBEAR_SUCCESS) {
TRACE(("skipped initial none auth query"))
/* Note that there will be two auth responses in-flight */
@@ -78,6 +80,7 @@ void recv_msg_userauth_banner() {
char* banner = NULL;
unsigned int bannerlen;
unsigned int i, linecount;
int truncated = 0;
TRACE(("enter recv_msg_userauth_banner"))
if (ses.authstate.authdone) {
@@ -90,26 +93,29 @@ void recv_msg_userauth_banner() {
if (bannerlen > MAX_BANNER_SIZE) {
TRACE(("recv_msg_userauth_banner: bannerlen too long: %d", bannerlen))
goto out;
}
truncated = 1;
} else {
cleantext(banner);
cleantext(banner);
/* Limit to 25 lines */
linecount = 1;
for (i = 0; i < bannerlen; i++) {
if (banner[i] == '\n') {
if (linecount >= MAX_BANNER_LINES) {
banner[i] = '\0';
break;
/* Limit to 24 lines */
linecount = 1;
for (i = 0; i < bannerlen; i++) {
if (banner[i] == '\n') {
if (linecount >= MAX_BANNER_LINES) {
banner[i] = '\0';
truncated = 1;
break;
}
linecount++;
}
linecount++;
}
fprintf(stderr, "%s\n", banner);
}
fprintf(stderr, "%s\n", banner);
if (truncated) {
fprintf(stderr, "[Banner from the server is too long]\n");
}
out:
m_free(banner);
TRACE(("leave recv_msg_userauth_banner"))
}
@@ -121,21 +127,21 @@ out:
* SSH_MSG_USERAUTH_INFO_REQUEST. */
void recv_msg_userauth_specific_60() {
#ifdef ENABLE_CLI_PUBKEY_AUTH
#if DROPBEAR_CLI_PUBKEY_AUTH
if (cli_ses.lastauthtype == AUTH_TYPE_PUBKEY) {
recv_msg_userauth_pk_ok();
return;
}
#endif
#ifdef ENABLE_CLI_INTERACT_AUTH
#if DROPBEAR_CLI_INTERACT_AUTH
if (cli_ses.lastauthtype == AUTH_TYPE_INTERACT) {
recv_msg_userauth_info_request();
return;
}
#endif
#ifdef ENABLE_CLI_PASSWORD_AUTH
#if DROPBEAR_CLI_PASSWORD_AUTH
if (cli_ses.lastauthtype == AUTH_TYPE_PASSWORD) {
/* Eventually there could be proper password-changing
* support. However currently few servers seem to
@@ -179,7 +185,7 @@ void recv_msg_userauth_failure() {
TRACE(("leave recv_msg_userauth_failure, ignored response, state set to USERAUTH_REQ_SENT"));
return;
} else {
#ifdef ENABLE_CLI_PUBKEY_AUTH
#if DROPBEAR_CLI_PUBKEY_AUTH
/* If it was a pubkey auth request, we should cross that key
* off the list. */
if (cli_ses.lastauthtype == AUTH_TYPE_PUBKEY) {
@@ -187,7 +193,7 @@ void recv_msg_userauth_failure() {
}
#endif
#ifdef ENABLE_CLI_INTERACT_AUTH
#if DROPBEAR_CLI_INTERACT_AUTH
/* If we get a failure message for keyboard interactive without
* receiving any request info packet, then we don't bother trying
* keyboard interactive again */
@@ -227,19 +233,19 @@ void recv_msg_userauth_failure() {
for (i = 0; i <= methlen; i++) {
if (methods[i] == '\0') {
TRACE(("auth method '%s'", tok))
#ifdef ENABLE_CLI_PUBKEY_AUTH
#if DROPBEAR_CLI_PUBKEY_AUTH
if (strncmp(AUTH_METHOD_PUBKEY, tok,
AUTH_METHOD_PUBKEY_LEN) == 0) {
ses.authstate.authtypes |= AUTH_TYPE_PUBKEY;
}
#endif
#ifdef ENABLE_CLI_INTERACT_AUTH
#if DROPBEAR_CLI_INTERACT_AUTH
if (strncmp(AUTH_METHOD_INTERACT, tok,
AUTH_METHOD_INTERACT_LEN) == 0) {
ses.authstate.authtypes |= AUTH_TYPE_INTERACT;
}
#endif
#ifdef ENABLE_CLI_PASSWORD_AUTH
#if DROPBEAR_CLI_PASSWORD_AUTH
if (strncmp(AUTH_METHOD_PASSWORD, tok,
AUTH_METHOD_PASSWORD_LEN) == 0) {
ses.authstate.authtypes |= AUTH_TYPE_PASSWORD;
@@ -267,7 +273,7 @@ void recv_msg_userauth_success() {
cli_ses.state = USERAUTH_SUCCESS_RCVD;
cli_ses.lastauthtype = AUTH_TYPE_NONE;
#ifdef ENABLE_CLI_PUBKEY_AUTH
#if DROPBEAR_CLI_PUBKEY_AUTH
cli_auth_pubkey_cleanup();
#endif
}
@@ -281,14 +287,14 @@ int cli_auth_try() {
/* Order to try is pubkey, interactive, password.
* As soon as "finished" is set for one, we don't do any more. */
#ifdef ENABLE_CLI_PUBKEY_AUTH
#if DROPBEAR_CLI_PUBKEY_AUTH
if (ses.authstate.authtypes & AUTH_TYPE_PUBKEY) {
finished = cli_auth_pubkey();
cli_ses.lastauthtype = AUTH_TYPE_PUBKEY;
}
#endif
#ifdef ENABLE_CLI_PASSWORD_AUTH
#if DROPBEAR_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");
@@ -300,7 +306,7 @@ int cli_auth_try() {
}
#endif
#ifdef ENABLE_CLI_INTERACT_AUTH
#if DROPBEAR_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");
@@ -324,14 +330,14 @@ int cli_auth_try() {
return DROPBEAR_FAILURE;
}
#if defined(ENABLE_CLI_PASSWORD_AUTH) || defined(ENABLE_CLI_INTERACT_AUTH)
#if DROPBEAR_CLI_PASSWORD_AUTH || DROPBEAR_CLI_INTERACT_AUTH
/* A helper for getpass() that exits if the user cancels. The returned
* password is statically allocated by getpass() */
char* getpass_or_cancel(char* prompt)
char* getpass_or_cancel(const char* prompt)
{
char* password = NULL;
#ifdef DROPBEAR_PASSWORD_ENV
#if DROPBEAR_USE_PASSWORD_ENV
/* Password provided in an environment var */
password = getenv(DROPBEAR_PASSWORD_ENV);
if (password)

View File

@@ -29,7 +29,7 @@
#include "ssh.h"
#include "runopts.h"
#ifdef ENABLE_CLI_INTERACT_AUTH
#if DROPBEAR_CLI_INTERACT_AUTH
static char* get_response(char* prompt)
{
@@ -172,4 +172,4 @@ void cli_auth_interactive() {
TRACE(("leave cli_auth_interactive"))
}
#endif /* ENABLE_CLI_INTERACT_AUTH */
#endif /* DROPBEAR_CLI_INTERACT_AUTH */

View File

@@ -29,9 +29,9 @@
#include "ssh.h"
#include "runopts.h"
#ifdef ENABLE_CLI_PASSWORD_AUTH
#if DROPBEAR_CLI_PASSWORD_AUTH
#ifdef ENABLE_CLI_ASKPASS_HELPER
#if DROPBEAR_CLI_ASKPASS_HELPER
/* Returns 1 if we want to use the askpass program, 0 otherwise */
static int want_askpass()
{
@@ -113,7 +113,7 @@ static char *gui_getpass(const char *prompt) {
TRACE(("leave gui_getpass"))
return(buf);
}
#endif /* ENABLE_CLI_ASKPASS_HELPER */
#endif /* DROPBEAR_CLI_ASKPASS_HELPER */
void cli_auth_password() {
@@ -125,7 +125,7 @@ void cli_auth_password() {
snprintf(prompt, sizeof(prompt), "%s@%s's password: ",
cli_opts.username, cli_opts.remotehost);
#ifdef ENABLE_CLI_ASKPASS_HELPER
#if DROPBEAR_CLI_ASKPASS_HELPER
if (want_askpass())
{
password = gui_getpass(prompt);
@@ -158,4 +158,4 @@ void cli_auth_password() {
TRACE(("leave cli_auth_password"))
}
#endif /* ENABLE_CLI_PASSWORD_AUTH */
#endif /* DROPBEAR_CLI_PASSWORD_AUTH */

View File

@@ -32,8 +32,8 @@
#include "auth.h"
#include "agentfwd.h"
#ifdef ENABLE_CLI_PUBKEY_AUTH
static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign);
#if DROPBEAR_CLI_PUBKEY_AUTH
static void send_msg_userauth_pubkey(sign_key *key, enum signature_type sigtype, int realsign);
/* Called when we receive a SSH_MSG_USERAUTH_FAILURE for a pubkey request.
* We use it to remove the key we tried from the list */
@@ -59,13 +59,15 @@ void recv_msg_userauth_pk_ok() {
char* algotype = NULL;
unsigned int algolen;
enum signkey_type keytype;
enum signature_type sigtype;
unsigned int remotelen;
TRACE(("enter recv_msg_userauth_pk_ok"))
algotype = buf_getstring(ses.payload, &algolen);
keytype = signkey_type_from_name(algotype, algolen);
TRACE(("recv_msg_userauth_pk_ok: type %d", keytype))
sigtype = signature_type_from_name(algotype, algolen);
keytype = signkey_type_from_signature(sigtype);
TRACE(("recv_msg_userauth_pk_ok: type %d", sigtype))
m_free(algotype);
keybuf = buf_new(MAX_PUBKEY_SIZE);
@@ -112,7 +114,7 @@ void recv_msg_userauth_pk_ok() {
TRACE(("matching key"))
/* XXX TODO: if it's an encrypted key, here we ask for their
* password */
send_msg_userauth_pubkey((sign_key*)iter->item, keytype, 1);
send_msg_userauth_pubkey((sign_key*)iter->item, sigtype, 1);
} else {
TRACE(("That was whacky. We got told that a key was valid, but it didn't match our list. Sounds like dodgy code on Dropbear's part"))
}
@@ -120,31 +122,32 @@ void recv_msg_userauth_pk_ok() {
TRACE(("leave recv_msg_userauth_pk_ok"))
}
void cli_buf_put_sign(buffer* buf, sign_key *key, int type,
buffer *data_buf) {
#ifdef ENABLE_CLI_AGENTFWD
static void cli_buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype,
const buffer *data_buf) {
#if DROPBEAR_CLI_AGENTFWD
// TODO: rsa-sha256 agent
if (key->source == SIGNKEY_SOURCE_AGENT) {
/* Format the agent signature ourselves, as buf_put_sign would. */
buffer *sigblob;
sigblob = buf_new(MAX_PUBKEY_SIZE);
agent_buf_sign(sigblob, key, data_buf);
agent_buf_sign(sigblob, key, data_buf, sigtype);
buf_putbufstring(buf, sigblob);
buf_free(sigblob);
} else
#endif /* ENABLE_CLI_AGENTFWD */
#endif /* DROPBEAR_CLI_AGENTFWD */
{
buf_put_sign(buf, key, type, data_buf);
buf_put_sign(buf, key, sigtype, data_buf);
}
}
/* TODO: make it take an agent reference to use as well */
static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
static void send_msg_userauth_pubkey(sign_key *key, enum signature_type sigtype, int realsign) {
const char *algoname = NULL;
unsigned int algolen;
buffer* sigbuf = NULL;
enum signkey_type keytype = signkey_type_from_signature(sigtype);
TRACE(("enter send_msg_userauth_pubkey"))
TRACE(("enter send_msg_userauth_pubkey sigtype %d", sigtype))
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);
@@ -160,10 +163,9 @@ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
buf_putbyte(ses.writepayload, realsign);
algoname = signkey_name_from_type(type, &algolen);
algoname = signature_name_from_type(sigtype, &algolen);
buf_putstring(ses.writepayload, algoname, algolen);
buf_put_pub_key(ses.writepayload, key, type);
buf_put_pub_key(ses.writepayload, key, keytype);
if (realsign) {
TRACE(("realsign"))
@@ -172,7 +174,7 @@ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
sigbuf = buf_new(4 + ses.session_id->len + ses.writepayload->len);
buf_putbufstring(sigbuf, ses.session_id);
buf_putbytes(sigbuf, ses.writepayload->data, ses.writepayload->len);
cli_buf_put_sign(ses.writepayload, key, type, sigbuf);
cli_buf_put_sign(ses.writepayload, key, sigtype, sigbuf);
buf_free(sigbuf); /* Nothing confidential in the buffer */
}
@@ -182,21 +184,87 @@ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
/* Returns 1 if a key was tried */
int cli_auth_pubkey() {
enum signature_type sigtype = DROPBEAR_SIGNATURE_NONE;
TRACE(("enter cli_auth_pubkey"))
#ifdef ENABLE_CLI_AGENTFWD
#if DROPBEAR_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;
TRACE(("cli_auth_pubkey: agent keys loaded"))
}
#endif
/* iterate through privkeys to remove ones not allowed in server-sig-algs */
while (cli_opts.privkeys->first) {
sign_key * key = (sign_key*)cli_opts.privkeys->first->item;
if (cli_ses.server_sig_algs) {
#if DROPBEAR_RSA
if (key->type == DROPBEAR_SIGNKEY_RSA) {
#if DROPBEAR_RSA_SHA256
if (buf_has_algo(cli_ses.server_sig_algs, SSH_SIGNATURE_RSA_SHA256)
== DROPBEAR_SUCCESS) {
sigtype = DROPBEAR_SIGNATURE_RSA_SHA256;
TRACE(("server-sig-algs allows rsa sha256"))
break;
}
#endif /* DROPBEAR_RSA_SHA256 */
#if DROPBEAR_RSA_SHA1
if (buf_has_algo(cli_ses.server_sig_algs, SSH_SIGNKEY_RSA)
== DROPBEAR_SUCCESS) {
sigtype = DROPBEAR_SIGNATURE_RSA_SHA1;
TRACE(("server-sig-algs allows rsa sha1"))
break;
}
#endif /* DROPBEAR_RSA_SHA256 */
} else
#endif /* DROPBEAR_RSA */
{
/* Not RSA */
const char *name = NULL;
sigtype = signature_type_from_signkey(key->type);
name = signature_name_from_type(sigtype, NULL);
if (buf_has_algo(cli_ses.server_sig_algs, name)
== DROPBEAR_SUCCESS) {
TRACE(("server-sig-algs allows %s", name))
break;
}
}
/* No match, skip this key */
TRACE(("server-sig-algs no match keytype %d, skipping", key->type))
key = list_remove(cli_opts.privkeys->first);
sign_key_free(key);
continue;
} else {
/* Server didn't provide a server-sig-algs list, we'll
assume all except rsa-sha256 are OK. */
#if DROPBEAR_RSA
if (key->type == DROPBEAR_SIGNKEY_RSA) {
#if DROPBEAR_RSA_SHA1
sigtype = DROPBEAR_SIGNATURE_RSA_SHA1;
TRACE(("no server-sig-algs, using rsa sha1"))
break;
#else
/* only support rsa-sha256, skip this key */
TRACE(("no server-sig-algs, skipping rsa sha256"))
key = list_remove(cli_opts.privkeys->first);
sign_key_free(key);
continue;
#endif
} /* key->type == DROPBEAR_SIGNKEY_RSA */
#endif /* DROPBEAR_RSA */
sigtype = signature_type_from_signkey(key->type);
TRACE(("no server-sig-algs, using key"))
break;
}
}
if (cli_opts.privkeys->first) {
sign_key * key = (sign_key*)cli_opts.privkeys->first->item;
/* Send a trial request */
send_msg_userauth_pubkey(key, key->type, 0);
send_msg_userauth_pubkey(key, sigtype, 0);
cli_ses.lastprivkey = key;
TRACE(("leave cli_auth_pubkey-success"))
return 1;
@@ -209,7 +277,7 @@ int cli_auth_pubkey() {
void cli_auth_pubkey_cleanup() {
#ifdef ENABLE_CLI_AGENTFWD
#if DROPBEAR_CLI_AGENTFWD
m_close(cli_opts.agent_fd);
cli_opts.agent_fd = -1;
#endif

View File

@@ -35,12 +35,12 @@
#include "chansession.h"
#include "agentfwd.h"
static void cli_closechansess(struct Channel *channel);
static void cli_closechansess(const 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 send_chansess_pty_req(const struct Channel *channel);
static void send_chansess_shell_req(const struct Channel *channel);
static void cli_escape_handler(const struct Channel *channel, const unsigned char* buf, int *len);
static int cli_init_netcat(struct Channel *channel);
static void cli_tty_setup(void);
@@ -52,6 +52,7 @@ const struct ChanType clichansess = {
NULL, /* checkclosehandler */
cli_chansessreq, /* reqhandler */
cli_closechansess, /* closehandler */
NULL, /* cleanup */
};
static void cli_chansessreq(struct Channel *channel) {
@@ -83,7 +84,7 @@ out:
/* If the main session goes, we close it up */
static void cli_closechansess(struct Channel *UNUSED(channel)) {
static void cli_closechansess(const struct Channel *UNUSED(channel)) {
cli_tty_cleanup(); /* Restore tty modes etc */
/* This channel hasn't gone yet, so we have > 1 */
@@ -270,7 +271,7 @@ void cli_chansess_winchange() {
cli_ses.winchange = 0;
}
static void send_chansess_pty_req(struct Channel *channel) {
static void send_chansess_pty_req(const struct Channel *channel) {
char* term = NULL;
@@ -303,7 +304,7 @@ static void send_chansess_pty_req(struct Channel *channel) {
TRACE(("leave send_chansess_pty_req"))
}
static void send_chansess_shell_req(struct Channel *channel) {
static void send_chansess_shell_req(const struct Channel *channel) {
char* reqtype = NULL;
@@ -355,7 +356,7 @@ static int cli_initchansess(struct Channel *channel) {
cli_init_stdpipe_sess(channel);
#ifdef ENABLE_CLI_AGENTFWD
#if DROPBEAR_CLI_AGENTFWD
if (cli_opts.agent_fwd) {
cli_setup_agent(channel);
}
@@ -379,7 +380,7 @@ static int cli_initchansess(struct Channel *channel) {
return 0; /* Success */
}
#ifdef ENABLE_CLI_NETCAT
#if DROPBEAR_CLI_NETCAT
static const struct ChanType cli_chan_netcat = {
0, /* sepfds */
@@ -387,7 +388,8 @@ static const struct ChanType cli_chan_netcat = {
cli_init_netcat, /* inithandler */
NULL,
NULL,
cli_closechansess
cli_closechansess,
NULL,
};
void cli_send_netcat_request() {
@@ -452,7 +454,7 @@ do_escape(unsigned char c) {
}
static
void cli_escape_handler(struct Channel* UNUSED(channel), unsigned char* buf, int *len) {
void cli_escape_handler(const struct Channel* UNUSED(channel), const unsigned char* buf, int *len) {
char c;
int skip_char = 0;

View File

@@ -39,7 +39,7 @@
#include "ecc.h"
static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen);
static void checkhostkey(const unsigned char* keyblob, unsigned int keybloblen);
#define MAX_KNOWNHOSTS_LINE 4500
void send_msg_kexdh_init() {
@@ -48,6 +48,7 @@ void send_msg_kexdh_init() {
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT);
switch (ses.newkeys->algo_kex->mode) {
#if DROPBEAR_NORMAL_DH
case DROPBEAR_KEX_NORMAL_DH:
if (ses.newkeys->algo_kex != cli_ses.param_kex_algo
|| !cli_ses.dh_param) {
@@ -58,8 +59,9 @@ void send_msg_kexdh_init() {
}
buf_putmpint(ses.writepayload, &cli_ses.dh_param->pub);
break;
#endif
#if DROPBEAR_ECDH
case DROPBEAR_KEX_ECDH:
#ifdef DROPBEAR_ECDH
if (ses.newkeys->algo_kex != cli_ses.param_kex_algo
|| !cli_ses.ecdh_param) {
if (cli_ses.ecdh_param) {
@@ -68,9 +70,9 @@ void send_msg_kexdh_init() {
cli_ses.ecdh_param = gen_kexecdh_param();
}
buf_put_ecc_raw_pubkey_string(ses.writepayload, &cli_ses.ecdh_param->key);
#endif
break;
#ifdef DROPBEAR_CURVE25519
#endif
#if DROPBEAR_CURVE25519
case DROPBEAR_KEX_CURVE25519:
if (ses.newkeys->algo_kex != cli_ses.param_kex_algo
|| !cli_ses.curve25519_param) {
@@ -79,9 +81,9 @@ void send_msg_kexdh_init() {
}
cli_ses.curve25519_param = gen_kexcurve25519_param();
}
buf_putstring(ses.writepayload, (const char*)cli_ses.curve25519_param->pub, CURVE25519_LEN);
#endif
buf_putstring(ses.writepayload, cli_ses.curve25519_param->pub, CURVE25519_LEN);
break;
#endif
}
cli_ses.param_kex_algo = ses.newkeys->algo_kex;
@@ -92,7 +94,7 @@ void send_msg_kexdh_init() {
void recv_msg_kexdh_reply() {
sign_key *hostkey = NULL;
unsigned int type, keybloblen;
unsigned int keytype, keybloblen;
unsigned char* keyblob = NULL;
TRACE(("enter recv_msg_kexdh_reply"))
@@ -100,8 +102,8 @@ void recv_msg_kexdh_reply() {
if (cli_ses.kex_state != KEXDH_INIT_SENT) {
dropbear_exit("Received out-of-order kexdhreply");
}
type = ses.newkeys->algo_hostkey;
TRACE(("type is %d", type))
keytype = ses.newkeys->algo_hostkey;
TRACE(("keytype is %d", keytype))
hostkey = new_sign_key();
keybloblen = buf_getint(ses.payload);
@@ -112,12 +114,13 @@ void recv_msg_kexdh_reply() {
checkhostkey(keyblob, keybloblen);
}
if (buf_get_pub_key(ses.payload, hostkey, &type) != DROPBEAR_SUCCESS) {
if (buf_get_pub_key(ses.payload, hostkey, &keytype) != DROPBEAR_SUCCESS) {
TRACE(("failed getting pubkey"))
dropbear_exit("Bad KEX packet");
}
switch (ses.newkeys->algo_kex->mode) {
#if DROPBEAR_NORMAL_DH
case DROPBEAR_KEX_NORMAL_DH:
{
DEF_MP_INT(dh_f);
@@ -131,37 +134,40 @@ void recv_msg_kexdh_reply() {
mp_clear(&dh_f);
}
break;
#endif
#if DROPBEAR_ECDH
case DROPBEAR_KEX_ECDH:
#ifdef DROPBEAR_ECDH
{
buffer *ecdh_qs = buf_getstringbuf(ses.payload);
kexecdh_comb_key(cli_ses.ecdh_param, ecdh_qs, hostkey);
buf_free(ecdh_qs);
}
#endif
break;
#ifdef DROPBEAR_CURVE25519
#endif
#if DROPBEAR_CURVE25519
case DROPBEAR_KEX_CURVE25519:
{
buffer *ecdh_qs = buf_getstringbuf(ses.payload);
kexcurve25519_comb_key(cli_ses.curve25519_param, ecdh_qs, hostkey);
buf_free(ecdh_qs);
}
#endif
break;
#endif
}
#if DROPBEAR_NORMAL_DH
if (cli_ses.dh_param) {
free_kexdh_param(cli_ses.dh_param);
cli_ses.dh_param = NULL;
}
#ifdef DROPBEAR_ECDH
#endif
#if DROPBEAR_ECDH
if (cli_ses.ecdh_param) {
free_kexecdh_param(cli_ses.ecdh_param);
cli_ses.ecdh_param = NULL;
}
#endif
#ifdef DROPBEAR_CURVE25519
#if DROPBEAR_CURVE25519
if (cli_ses.curve25519_param) {
free_kexcurve25519_param(cli_ses.curve25519_param);
cli_ses.curve25519_param = NULL;
@@ -169,7 +175,8 @@ void recv_msg_kexdh_reply() {
#endif
cli_ses.param_kex_algo = NULL;
if (buf_verify(ses.payload, hostkey, ses.hash) != DROPBEAR_SUCCESS) {
if (buf_verify(ses.payload, hostkey, ses.newkeys->algo_signature,
ses.hash) != DROPBEAR_SUCCESS) {
dropbear_exit("Bad hostkey signature");
}
@@ -181,7 +188,7 @@ void recv_msg_kexdh_reply() {
TRACE(("leave recv_msg_kexdh_init"))
}
static void ask_to_confirm(unsigned char* keyblob, unsigned int keybloblen,
static void ask_to_confirm(const unsigned char* keyblob, unsigned int keybloblen,
const char* algoname) {
char* fp = NULL;
@@ -278,7 +285,7 @@ out:
return hostsfile;
}
static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
static void checkhostkey(const unsigned char* keyblob, unsigned int keybloblen) {
FILE *hostsfile = NULL;
int readonly = 0;
@@ -406,3 +413,38 @@ out:
}
m_free(fingerprint);
}
void recv_msg_ext_info(void) {
/* This message is not client-specific in the protocol but Dropbear only handles
a server-sent message at present. */
unsigned int num_ext;
unsigned int i;
TRACE(("enter recv_msg_ext_info"))
/* Must be after the first SSH_MSG_NEWKEYS */
TRACE(("last %d, donefirst %d, donescond %d", ses.lastpacket, ses.kexstate.donefirstkex, ses.kexstate.donesecondkex))
if (!(ses.lastpacket == SSH_MSG_NEWKEYS && !ses.kexstate.donesecondkex)) {
TRACE(("leave recv_msg_ext_info: ignoring packet received at the wrong time"))
return;
}
num_ext = buf_getint(ses.payload);
TRACE(("received SSH_MSG_EXT_INFO with %d items", num_ext))
for (i = 0; i < num_ext; i++) {
unsigned int name_len;
char *ext_name = buf_getstring(ses.payload, &name_len);
TRACE(("extension %d name '%s'", i, ext_name))
if (cli_ses.server_sig_algs == NULL
&& name_len == strlen(SSH_SERVER_SIG_ALGS)
&& strcmp(ext_name, SSH_SERVER_SIG_ALGS) == 0) {
cli_ses.server_sig_algs = buf_getbuf(ses.payload);
} else {
/* valid extension values could be >MAX_STRING_LEN */
buf_eatstring(ses.payload);
}
m_free(ext_name);
}
TRACE(("leave recv_msg_ext_info"))
}

View File

@@ -35,13 +35,13 @@
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
#if DROPBEAR_CLI_PROXYCMD
static void cli_proxy_cmd(int *sock_in, int *sock_out, pid_t *pid_out);
static void kill_proxy_sighandler(int signo);
#endif
#if defined(DBMULTI_dbclient) || !defined(DROPBEAR_MULTI)
#if defined(DBMULTI_dbclient) && defined(DROPBEAR_MULTI)
#if defined(DBMULTI_dbclient) || !DROPBEAR_MULTI
#if defined(DBMULTI_dbclient) && DROPBEAR_MULTI
int cli_main(int argc, char ** argv) {
#else
int main(int argc, char ** argv) {
@@ -66,15 +66,15 @@ int main(int argc, char ** argv) {
}
#endif
TRACE(("user='%s' host='%s' port='%s'", cli_opts.username,
cli_opts.remotehost, cli_opts.remoteport))
TRACE(("user='%s' host='%s' port='%s' bind_address='%s' bind_port='%s'", cli_opts.username,
cli_opts.remotehost, cli_opts.remoteport, cli_opts.bind_address, cli_opts.bind_port))
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
dropbear_exit("signal() error");
}
pid_t proxy_cmd_pid = 0;
#ifdef ENABLE_CLI_PROXYCMD
#if DROPBEAR_CLI_PROXYCMD
if (cli_opts.proxycmd) {
cli_proxy_cmd(&sock_in, &sock_out, &proxy_cmd_pid);
m_free(cli_opts.proxycmd);
@@ -86,7 +86,8 @@ int main(int argc, char ** argv) {
} else
#endif
{
progress = connect_remote(cli_opts.remotehost, cli_opts.remoteport, cli_connected, &ses);
progress = connect_remote(cli_opts.remotehost, cli_opts.remoteport,
cli_connected, &ses, cli_opts.bind_address, cli_opts.bind_port);
sock_in = sock_out = -1;
}
@@ -98,29 +99,31 @@ int main(int argc, char ** argv) {
#endif /* DBMULTI stuff */
static void cli_dropbear_exit(int exitcode, const char* format, va_list param) {
char exitmsg[150];
char fullmsg[300];
char fmtbuf[300];
char exitmsg[500];
/* Note that exit message must be rendered before session cleanup */
if (!sessinitdone) {
snprintf(fmtbuf, sizeof(fmtbuf), "Exited: %s",
format);
/* Render the formatted exit message */
vsnprintf(exitmsg, sizeof(exitmsg), format, param);
TRACE(("Exited, cleaning up: %s", exitmsg))
/* Add the prefix depending on session/auth state */
if (!ses.init_done) {
snprintf(fullmsg, sizeof(fullmsg), "Exited: %s", exitmsg);
} else {
snprintf(fmtbuf, sizeof(fmtbuf),
snprintf(fullmsg, sizeof(fullmsg),
"Connection to %s@%s:%s exited: %s",
cli_opts.username, cli_opts.remotehost,
cli_opts.remoteport, format);
cli_opts.remoteport, exitmsg);
}
/* Arguments to the exit printout may be unsafe to use after session_cleanup() */
vsnprintf(exitmsg, sizeof(exitmsg), fmtbuf, param);
/* Do the cleanup first, since then the terminal will be reset */
session_cleanup();
/* Avoid printing onwards from terminal cruft */
fprintf(stderr, "\n");
dropbear_log(LOG_INFO, "%s", exitmsg);;
dropbear_log(LOG_INFO, "%s", fullmsg);
exit(exitcode);
}
@@ -128,6 +131,12 @@ static void cli_dropbear_log(int priority,
const char* format, va_list param) {
char printbuf[1024];
const char *name;
name = cli_opts.progname;
if (!name) {
name = "dbclient";
}
vsnprintf(printbuf, sizeof(printbuf), format, param);
@@ -137,11 +146,11 @@ static void cli_dropbear_log(int priority,
}
#endif
fprintf(stderr, "%s: %s\n", cli_opts.progname, printbuf);
fprintf(stderr, "%s: %s\n", name, printbuf);
fflush(stderr);
}
static void exec_proxy_cmd(void *user_data_cmd) {
static void exec_proxy_cmd(const void *user_data_cmd) {
const char *cmd = user_data_cmd;
char *usershell;
@@ -150,12 +159,27 @@ static void exec_proxy_cmd(void *user_data_cmd) {
dropbear_exit("Failed to run '%s'\n", cmd);
}
#ifdef ENABLE_CLI_PROXYCMD
#if DROPBEAR_CLI_PROXYCMD
static void cli_proxy_cmd(int *sock_in, int *sock_out, pid_t *pid_out) {
char * ex_cmd = NULL;
size_t ex_cmdlen;
int ret;
/* File descriptor "-j &3" */
if (*cli_opts.proxycmd == '&') {
char *p = cli_opts.proxycmd + 1;
int sock = strtoul(p, &p, 10);
/* must be a single number, and not stdin/stdout/stderr */
if (sock > 2 && sock < 1024 && *p == '\0') {
*sock_in = sock;
*sock_out = sock;
return;
}
}
/* Normal proxycommand */
/* So that spawn_command knows which shell to run */
fill_passwd(cli_opts.own_user);
ex_cmdlen = strlen(cli_opts.proxycmd) + 6; /* "exec " + command + '\0' */
@@ -175,4 +199,4 @@ static void kill_proxy_sighandler(int UNUSED(signo)) {
kill_proxy_command();
_exit(1);
}
#endif /* ENABLE_CLI_PROXYCMD */
#endif /* DROPBEAR_CLI_PROXYCMD */

View File

@@ -37,13 +37,13 @@ static void printhelp(void);
static void parse_hostname(const char* orighostarg);
static void parse_multihop_hostname(const char* orighostarg, const char* argv0);
static void fill_own_user(void);
#ifdef ENABLE_CLI_PUBKEY_AUTH
#if DROPBEAR_CLI_PUBKEY_AUTH
static void loadidentityfile(const char* filename, int warnfail);
#endif
#ifdef ENABLE_CLI_ANYTCPFWD
#if DROPBEAR_CLI_ANYTCPFWD
static void addforward(const char* str, m_list *fwdlist);
#endif
#ifdef ENABLE_CLI_NETCAT
#if DROPBEAR_CLI_NETCAT
static void add_netcat(const char *str);
#endif
static void add_extendedopt(const char *str);
@@ -51,7 +51,7 @@ static void add_extendedopt(const char *str);
static void printhelp() {
fprintf(stderr, "Dropbear SSH client v%s https://matt.ucc.asn.au/dropbear/dropbear.html\n"
#ifdef ENABLE_CLI_MULTIHOP
#if DROPBEAR_CLI_MULTIHOP
"Usage: %s [options] [user@]host[/port][,[user@]host/port],...] [command]\n"
#else
"Usage: %s [options] [user@]host[/port] [command]\n"
@@ -66,38 +66,39 @@ static void printhelp() {
"-y -y Don't perform any remote host key checking (caution)\n"
"-s Request a subsystem (use by external sftp)\n"
"-o option Set option in OpenSSH-like format ('-o help' to list options)\n"
#ifdef ENABLE_CLI_PUBKEY_AUTH
#if DROPBEAR_CLI_PUBKEY_AUTH
"-i <identityfile> (multiple allowed, default %s)\n"
#endif
#ifdef ENABLE_CLI_AGENTFWD
#if DROPBEAR_CLI_AGENTFWD
"-A Enable agent auth forwarding\n"
#endif
#ifdef ENABLE_CLI_LOCALTCPFWD
#if DROPBEAR_CLI_LOCALTCPFWD
"-L <[listenaddress:]listenport:remotehost:remoteport> Local port forwarding\n"
"-g Allow remote hosts to connect to forwarded ports\n"
#endif
#ifdef ENABLE_CLI_REMOTETCPFWD
#if DROPBEAR_CLI_REMOTETCPFWD
"-R <[listenaddress:]listenport:remotehost:remoteport> Remote port forwarding\n"
#endif
"-W <receive_window_buffer> (default %d, larger may be faster, max 1MB)\n"
"-K <keepalive> (0 is never, default %d)\n"
"-I <idle_timeout> (0 is never, default %d)\n"
#ifdef ENABLE_CLI_NETCAT
#if DROPBEAR_CLI_NETCAT
"-B <endhost:endport> Netcat-alike forwarding\n"
#endif
#ifdef ENABLE_CLI_PROXYCMD
#if DROPBEAR_CLI_PROXYCMD
"-J <proxy_program> Use program pipe rather than TCP connection\n"
#endif
#ifdef ENABLE_USER_ALGO_LIST
#if DROPBEAR_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
"-b [bind_address][:bind_port]\n"
"-V Version\n"
#ifdef DEBUG_TRACE
#if DEBUG_TRACE
"-v verbose (compiled with DEBUG_TRACE)\n"
#endif
,DROPBEAR_VERSION, cli_opts.progname,
#ifdef ENABLE_CLI_PUBKEY_AUTH
#if DROPBEAR_CLI_PUBKEY_AUTH
DROPBEAR_DEFAULT_CLI_AUTHKEY,
#endif
DEFAULT_RECV_WINDOW, DEFAULT_KEEPALIVE, DEFAULT_IDLE_TIMEOUT);
@@ -106,31 +107,31 @@ static void printhelp() {
void cli_getopts(int argc, char ** argv) {
unsigned int i, j;
char ** next = 0;
char ** next = NULL;
enum {
OPT_EXTENDED_OPTIONS,
#ifdef ENABLE_CLI_PUBKEY_AUTH
#if DROPBEAR_CLI_PUBKEY_AUTH
OPT_AUTHKEY,
#endif
#ifdef ENABLE_CLI_LOCALTCPFWD
#if DROPBEAR_CLI_LOCALTCPFWD
OPT_LOCALTCPFWD,
#endif
#ifdef ENABLE_CLI_REMOTETCPFWD
#if DROPBEAR_CLI_REMOTETCPFWD
OPT_REMOTETCPFWD,
#endif
#ifdef ENABLE_CLI_NETCAT
#if DROPBEAR_CLI_NETCAT
OPT_NETCAT,
#endif
/* a flag (no arg) if 'next' is NULL, a string-valued option otherwise */
OPT_OTHER
} opt;
unsigned int cmdlen;
char* dummy = NULL; /* Not used for anything real */
char* recv_window_arg = NULL;
char* keepalive_arg = NULL;
char* idle_timeout_arg = NULL;
char *host_arg = NULL;
char *bind_arg = NULL;
char c;
/* see printhelp() for options */
@@ -145,31 +146,33 @@ void cli_getopts(int argc, char ** argv) {
cli_opts.always_accept_key = 0;
cli_opts.no_hostkey_check = 0;
cli_opts.is_subsystem = 0;
#ifdef ENABLE_CLI_PUBKEY_AUTH
#if DROPBEAR_CLI_PUBKEY_AUTH
cli_opts.privkeys = list_new();
#endif
#ifdef ENABLE_CLI_ANYTCPFWD
#if DROPBEAR_CLI_ANYTCPFWD
cli_opts.exit_on_fwd_failure = 0;
#endif
#ifdef ENABLE_CLI_LOCALTCPFWD
#if DROPBEAR_CLI_LOCALTCPFWD
cli_opts.localfwds = list_new();
opts.listen_fwd_all = 0;
#endif
#ifdef ENABLE_CLI_REMOTETCPFWD
#if DROPBEAR_CLI_REMOTETCPFWD
cli_opts.remotefwds = list_new();
#endif
#ifdef ENABLE_CLI_AGENTFWD
#if DROPBEAR_CLI_AGENTFWD
cli_opts.agent_fwd = 0;
cli_opts.agent_fd = -1;
cli_opts.agent_keys_loaded = 0;
#endif
#ifdef ENABLE_CLI_PROXYCMD
#if DROPBEAR_CLI_PROXYCMD
cli_opts.proxycmd = NULL;
#endif
cli_opts.bind_address = NULL;
cli_opts.bind_port = NULL;
#ifndef DISABLE_ZLIB
opts.compress_mode = DROPBEAR_COMPRESS_ON;
#endif
#ifdef ENABLE_USER_ALGO_LIST
#if DROPBEAR_USER_ALGO_LIST
opts.cipher_list = NULL;
opts.mac_list = NULL;
#endif
@@ -211,9 +214,9 @@ void cli_getopts(int argc, char ** argv) {
cli_opts.always_accept_key = 1;
break;
case 'p': /* remoteport */
next = &cli_opts.remoteport;
next = (char**)&cli_opts.remoteport;
break;
#ifdef ENABLE_CLI_PUBKEY_AUTH
#if DROPBEAR_CLI_PUBKEY_AUTH
case 'i': /* an identityfile */
opt = OPT_AUTHKEY;
break;
@@ -236,7 +239,7 @@ void cli_getopts(int argc, char ** argv) {
case 'o':
opt = OPT_EXTENDED_OPTIONS;
break;
#ifdef ENABLE_CLI_LOCALTCPFWD
#if DROPBEAR_CLI_LOCALTCPFWD
case 'L':
opt = OPT_LOCALTCPFWD;
break;
@@ -244,17 +247,17 @@ void cli_getopts(int argc, char ** argv) {
opts.listen_fwd_all = 1;
break;
#endif
#ifdef ENABLE_CLI_REMOTETCPFWD
#if DROPBEAR_CLI_REMOTETCPFWD
case 'R':
opt = OPT_REMOTETCPFWD;
break;
#endif
#ifdef ENABLE_CLI_NETCAT
#if DROPBEAR_CLI_NETCAT
case 'B':
opt = OPT_NETCAT;
break;
#endif
#ifdef ENABLE_CLI_PROXYCMD
#if DROPBEAR_CLI_PROXYCMD
case 'J':
next = &cli_opts.proxycmd;
break;
@@ -278,12 +281,12 @@ void cli_getopts(int argc, char ** argv) {
case 'I':
next = &idle_timeout_arg;
break;
#ifdef ENABLE_CLI_AGENTFWD
#if DROPBEAR_CLI_AGENTFWD
case 'A':
cli_opts.agent_fwd = 1;
break;
#endif
#ifdef ENABLE_USER_ALGO_LIST
#if DROPBEAR_USER_ALGO_LIST
case 'c':
next = &opts.cipher_list;
break;
@@ -291,22 +294,22 @@ void cli_getopts(int argc, char ** argv) {
next = &opts.mac_list;
break;
#endif
#ifdef DEBUG_TRACE
#if DEBUG_TRACE
case 'v':
debug_trace = 1;
break;
#endif
case 'F':
case 'e':
#ifndef ENABLE_USER_ALGO_LIST
#if !DROPBEAR_USER_ALGO_LIST
case 'c':
case 'm':
#endif
case 'D':
#ifndef ENABLE_CLI_REMOTETCPFWD
#if !DROPBEAR_CLI_REMOTETCPFWD
case 'R':
#endif
#ifndef ENABLE_CLI_LOCALTCPFWD
#if !DROPBEAR_CLI_LOCALTCPFWD
case 'L':
#endif
case 'V':
@@ -314,8 +317,8 @@ void cli_getopts(int argc, char ** argv) {
exit(EXIT_SUCCESS);
break;
case 'b':
next = &dummy;
/* FALLTHROUGH */
next = &bind_arg;
break;
default:
fprintf(stderr,
"WARNING: Ignoring unknown option -%c\n", c);
@@ -338,28 +341,28 @@ void cli_getopts(int argc, char ** argv) {
add_extendedopt(&argv[i][j]);
}
else
#ifdef ENABLE_CLI_PUBKEY_AUTH
#if DROPBEAR_CLI_PUBKEY_AUTH
if (opt == OPT_AUTHKEY) {
TRACE(("opt authkey"))
loadidentityfile(&argv[i][j], 1);
}
else
#endif
#ifdef ENABLE_CLI_REMOTETCPFWD
#if DROPBEAR_CLI_REMOTETCPFWD
if (opt == OPT_REMOTETCPFWD) {
TRACE(("opt remotetcpfwd"))
addforward(&argv[i][j], cli_opts.remotefwds);
}
else
#endif
#ifdef ENABLE_CLI_LOCALTCPFWD
#if DROPBEAR_CLI_LOCALTCPFWD
if (opt == OPT_LOCALTCPFWD) {
TRACE(("opt localtcpfwd"))
addforward(&argv[i][j], cli_opts.localfwds);
}
else
#endif
#ifdef ENABLE_CLI_NETCAT
#if DROPBEAR_CLI_NETCAT
if (opt == OPT_NETCAT) {
TRACE(("opt netcat"))
add_netcat(&argv[i][j]);
@@ -375,6 +378,11 @@ void cli_getopts(int argc, char ** argv) {
}
}
#if DROPBEAR_USER_ALGO_LIST
/* -c help doesn't need a hostname */
parse_ciphers_macs();
#endif
/* Done with options/flags; now handle the hostname (which may not
* start with a hyphen) and optional command */
@@ -405,11 +413,7 @@ void cli_getopts(int argc, char ** argv) {
/* And now a few sanity checks and setup */
#ifdef ENABLE_USER_ALGO_LIST
parse_ciphers_macs();
#endif
#ifdef ENABLE_CLI_PROXYCMD
#if DROPBEAR_CLI_PROXYCMD
if (cli_opts.proxycmd) {
/* To match the common path of m_freeing it */
cli_opts.proxycmd = m_strdup(cli_opts.proxycmd);
@@ -420,6 +424,18 @@ void cli_getopts(int argc, char ** argv) {
cli_opts.remoteport = "22";
}
if (bind_arg) {
/* split [host][:port] */
char *port = strrchr(bind_arg, ':');
if (port) {
cli_opts.bind_port = m_strdup(port+1);
*port = '\0';
}
if (strlen(bind_arg) > 0) {
cli_opts.bind_address = m_strdup(bind_arg);
}
}
/* If not explicitly specified with -t or -T, we don't want a pty if
* there's a command, but we do otherwise */
if (cli_opts.wantpty == 9) {
@@ -457,13 +473,13 @@ void cli_getopts(int argc, char ** argv) {
opts.idle_timeout_secs = val;
}
#ifdef ENABLE_CLI_NETCAT
#if DROPBEAR_CLI_NETCAT
if (cli_opts.cmd && cli_opts.netcat_host) {
dropbear_log(LOG_INFO, "Ignoring command '%s' in netcat mode", cli_opts.cmd);
}
#endif
#if defined(DROPBEAR_DEFAULT_CLI_AUTHKEY) && defined(ENABLE_CLI_PUBKEY_AUTH)
#if (DROPBEAR_CLI_PUBKEY_AUTH)
{
char *expand_path = expand_homedir_path(DROPBEAR_DEFAULT_CLI_AUTHKEY);
loadidentityfile(expand_path, 0);
@@ -474,14 +490,14 @@ void cli_getopts(int argc, char ** argv) {
/* The hostname gets set up last, since
* in multi-hop mode it will require knowledge
* of other flags such as -i */
#ifdef ENABLE_CLI_MULTIHOP
#if DROPBEAR_CLI_MULTIHOP
parse_multihop_hostname(host_arg, argv[0]);
#else
parse_hostname(host_arg);
#endif
}
#ifdef ENABLE_CLI_PUBKEY_AUTH
#if DROPBEAR_CLI_PUBKEY_AUTH
static void loadidentityfile(const char* filename, int warnfail) {
sign_key *key;
enum signkey_type keytype;
@@ -504,7 +520,7 @@ static void loadidentityfile(const char* filename, int warnfail) {
}
#endif
#ifdef ENABLE_CLI_MULTIHOP
#if DROPBEAR_CLI_MULTIHOP
static char*
multihop_passthrough_args() {
@@ -514,13 +530,13 @@ multihop_passthrough_args() {
m_list_elem *iter;
/* Fill out -i, -y, -W options that make sense for all
* the intermediate processes */
#ifdef ENABLE_CLI_PUBKEY_AUTH
#if DROPBEAR_CLI_PUBKEY_AUTH
for (iter = cli_opts.privkeys->first; iter; iter = iter->next)
{
sign_key * key = (sign_key*)iter->item;
len += 3 + strlen(key->filename);
}
#endif /* ENABLE_CLI_PUBKEY_AUTH */
#endif /* DROPBEAR_CLI_PUBKEY_AUTH */
len += 30; /* space for -W <size>, terminator. */
ret = m_malloc(len);
@@ -543,7 +559,7 @@ multihop_passthrough_args() {
total += written;
}
#ifdef ENABLE_CLI_PUBKEY_AUTH
#if DROPBEAR_CLI_PUBKEY_AUTH
for (iter = cli_opts.privkeys->first; iter; iter = iter->next)
{
sign_key * key = (sign_key*)iter->item;
@@ -552,7 +568,7 @@ multihop_passthrough_args() {
dropbear_assert((unsigned int)written < size);
total += written;
}
#endif /* ENABLE_CLI_PUBKEY_AUTH */
#endif /* DROPBEAR_CLI_PUBKEY_AUTH */
/* if args were passed, total will be not zero, and it will have a space at the end, so remove that */
if (total > 0)
@@ -636,7 +652,7 @@ static void parse_multihop_hostname(const char* orighostarg, const char* argv0)
}
m_free(hostbuf);
}
#endif /* !ENABLE_CLI_MULTIHOP */
#endif /* !DROPBEAR_CLI_MULTIHOP */
/* Parses a [user@]hostname[/port] argument. */
static void parse_hostname(const char* orighostarg) {
@@ -675,7 +691,7 @@ static void parse_hostname(const char* orighostarg) {
}
}
#ifdef ENABLE_CLI_NETCAT
#if DROPBEAR_CLI_NETCAT
static void add_netcat(const char* origstr) {
char *portstr = NULL;
@@ -728,7 +744,7 @@ static void fill_own_user() {
}
#ifdef ENABLE_CLI_ANYTCPFWD
#if DROPBEAR_CLI_ANYTCPFWD
/* Turn a "[listenaddr:]listenport:remoteaddr:remoteport" string into into a forwarding
* set, and add it to the forwarding list */
static void addforward(const char* origstr, m_list *fwdlist) {
@@ -870,17 +886,18 @@ static void add_extendedopt(const char* origstr) {
if (strcmp(origstr, "help") == 0) {
dropbear_log(LOG_INFO, "Available options:\n"
#ifdef ENABLE_CLI_ANYTCPFWD
#if DROPBEAR_CLI_ANYTCPFWD
"\tExitOnForwardFailure\n"
#endif
#ifndef DISABLE_SYSLOG
"\tUseSyslog\n"
#endif
"\tPort\n"
);
exit(EXIT_SUCCESS);
}
#ifdef ENABLE_CLI_ANYTCPFWD
#if DROPBEAR_CLI_ANYTCPFWD
if (match_extendedopt(&optstr, "ExitOnForwardFailure") == DROPBEAR_SUCCESS) {
cli_opts.exit_on_fwd_failure = parse_flag_value(optstr);
return;
@@ -894,5 +911,10 @@ static void add_extendedopt(const char* origstr) {
}
#endif
if (match_extendedopt(&optstr, "Port") == DROPBEAR_SUCCESS) {
cli_opts.remoteport = optstr;
return;
}
dropbear_log(LOG_WARNING, "Ignoring unknown configuration option '%s'", origstr);
}

View File

@@ -73,7 +73,7 @@ static const packettype cli_packettypes[] = {
{SSH_MSG_GLOBAL_REQUEST, recv_msg_global_request_cli},
{SSH_MSG_CHANNEL_SUCCESS, ignore_recv_response},
{SSH_MSG_CHANNEL_FAILURE, ignore_recv_response},
#ifdef ENABLE_CLI_REMOTETCPFWD
#if DROPBEAR_CLI_REMOTETCPFWD
{SSH_MSG_REQUEST_SUCCESS, cli_recv_msg_request_success}, /* client */
{SSH_MSG_REQUEST_FAILURE, cli_recv_msg_request_failure}, /* client */
#else
@@ -81,14 +81,15 @@ static const packettype cli_packettypes[] = {
{SSH_MSG_REQUEST_SUCCESS, ignore_recv_response},
{SSH_MSG_REQUEST_FAILURE, ignore_recv_response},
#endif
{0, 0} /* End */
{SSH_MSG_EXT_INFO, recv_msg_ext_info},
{0, NULL} /* End */
};
static const struct ChanType *cli_chantypes[] = {
#ifdef ENABLE_CLI_REMOTETCPFWD
#if DROPBEAR_CLI_REMOTETCPFWD
&cli_chan_tcpremote,
#endif
#ifdef ENABLE_CLI_AGENTFWD
#if DROPBEAR_CLI_AGENTFWD
&cli_chan_agent,
#endif
NULL /* Null termination */
@@ -118,7 +119,7 @@ void cli_session(int sock_in, int sock_out, struct dropbear_progress_connection
cli_session_init(proxy_cmd_pid);
/* Ready to go */
sessinitdone = 1;
ses.init_done = 1;
/* Exchange identification */
send_session_identification();
@@ -133,7 +134,7 @@ void cli_session(int sock_in, int sock_out, struct dropbear_progress_connection
}
#ifdef USE_KEX_FIRST_FOLLOWS
#if DROPBEAR_KEX_FIRST_FOLLOWS
static void cli_send_kex_first_guess() {
send_msg_kexdh_init();
}
@@ -165,13 +166,6 @@ static void cli_session_init(pid_t proxy_cmd_pid) {
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;
@@ -182,13 +176,13 @@ static void cli_session_init(pid_t proxy_cmd_pid) {
ses.isserver = 0;
#ifdef USE_KEX_FIRST_FOLLOWS
#if DROPBEAR_KEX_FIRST_FOLLOWS
ses.send_kex_first_guess = cli_send_kex_first_guess;
#endif
}
static void send_msg_service_request(char* servicename) {
static void send_msg_service_request(const char* servicename) {
TRACE(("enter send_msg_service_request: servicename='%s'", servicename))
@@ -275,19 +269,11 @@ static void cli_sessionloop() {
}
#endif
#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
is confusing, though stdout/stderr could be useful. */
devnull = open(_PATH_DEVNULL, O_RDONLY);
devnull = open(DROPBEAR_PATH_DEVNULL, O_RDONLY);
if (devnull < 0) {
dropbear_exit("Opening /dev/null: %d %s",
errno, strerror(errno));
@@ -299,7 +285,7 @@ static void cli_sessionloop() {
}
}
#ifdef ENABLE_CLI_NETCAT
#if DROPBEAR_CLI_NETCAT
if (cli_opts.netcat_host) {
cli_send_netcat_request();
} else
@@ -308,10 +294,10 @@ static void cli_sessionloop() {
cli_send_chansess_request();
}
#ifdef ENABLE_CLI_LOCALTCPFWD
#if DROPBEAR_CLI_LOCALTCPFWD
setup_localtcp();
#endif
#ifdef ENABLE_CLI_REMOTETCPFWD
#if DROPBEAR_CLI_REMOTETCPFWD
setup_remotetcp();
#endif
@@ -353,7 +339,7 @@ void kill_proxy_command(void) {
static void cli_session_cleanup(void) {
if (!sessinitdone) {
if (!ses.init_done) {
return;
}
@@ -367,10 +353,13 @@ static void cli_session_cleanup(void) {
(void)fcntl(cli_ses.stderrcopy, F_SETFL, cli_ses.stderrflags);
cli_tty_cleanup();
if (cli_ses.server_sig_algs) {
buf_free(cli_ses.server_sig_algs);
}
}
static void cli_finished() {
TRACE(("cli_finished()"))
session_cleanup();
fprintf(stderr, "Connection to %s@%s:%s closed.\n", cli_opts.username,

View File

@@ -23,7 +23,6 @@
* SOFTWARE. */
#include "includes.h"
#include "options.h"
#include "dbutil.h"
#include "tcpfwd.h"
#include "channel.h"
@@ -32,7 +31,7 @@
#include "ssh.h"
#include "netio.h"
#ifdef ENABLE_CLI_REMOTETCPFWD
#if DROPBEAR_CLI_REMOTETCPFWD
static int newtcpforwarded(struct Channel * channel);
const struct ChanType cli_chan_tcpremote = {
@@ -41,11 +40,12 @@ const struct ChanType cli_chan_tcpremote = {
newtcpforwarded,
NULL,
NULL,
NULL,
NULL
};
#endif
#ifdef ENABLE_CLI_LOCALTCPFWD
#if DROPBEAR_CLI_LOCALTCPFWD
static int cli_localtcp(const char* listenaddr,
unsigned int listenport,
const char* remoteaddr,
@@ -56,11 +56,12 @@ static const struct ChanType cli_chan_tcplocal = {
tcp_prio_inithandler,
NULL,
NULL,
NULL,
NULL
};
#endif
#ifdef ENABLE_CLI_ANYTCPFWD
#if DROPBEAR_CLI_ANYTCPFWD
static void fwd_failed(const char* format, ...) ATTRIB_PRINTF(1,2);
static void fwd_failed(const char* format, ...)
{
@@ -77,7 +78,7 @@ static void fwd_failed(const char* format, ...)
}
#endif
#ifdef ENABLE_CLI_LOCALTCPFWD
#if DROPBEAR_CLI_LOCALTCPFWD
void setup_localtcp() {
m_list_elem *iter;
int ret;
@@ -136,7 +137,7 @@ static int cli_localtcp(const char* listenaddr,
tcpinfo->chantype = &cli_chan_tcplocal;
tcpinfo->tcp_type = direct;
ret = listen_tcpfwd(tcpinfo);
ret = listen_tcpfwd(tcpinfo, NULL);
if (ret == DROPBEAR_FAILURE) {
m_free(tcpinfo);
@@ -144,9 +145,9 @@ static int cli_localtcp(const char* listenaddr,
TRACE(("leave cli_localtcp: %d", ret))
return ret;
}
#endif /* ENABLE_CLI_LOCALTCPFWD */
#endif /* DROPBEAR_CLI_LOCALTCPFWD */
#ifdef ENABLE_CLI_REMOTETCPFWD
#if DROPBEAR_CLI_REMOTETCPFWD
static void send_msg_global_request_remotetcp(const char *addr, int port) {
TRACE(("enter send_msg_global_request_remotetcp"))
@@ -234,7 +235,7 @@ static int newtcpforwarded(struct Channel * channel) {
char *origaddr = NULL;
unsigned int origport;
m_list_elem * iter = NULL;
struct TCPFwdEntry *fwd;
struct TCPFwdEntry *fwd = NULL;
char portstring[NI_MAXSERV];
int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
@@ -265,7 +266,7 @@ static int newtcpforwarded(struct Channel * channel) {
}
if (iter == NULL) {
if (iter == NULL || fwd == NULL) {
/* We didn't request forwarding on that port */
cleantext(origaddr);
dropbear_log(LOG_INFO, "Server sent unrequested forward from \"%s:%d\"",
@@ -274,7 +275,7 @@ static int newtcpforwarded(struct Channel * channel) {
}
snprintf(portstring, sizeof(portstring), "%u", fwd->connectport);
channel->conn_pending = connect_remote(fwd->connectaddr, portstring, channel_connect_done, channel);
channel->conn_pending = connect_remote(fwd->connectaddr, portstring, channel_connect_done, channel, NULL, NULL);
channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
@@ -285,4 +286,4 @@ out:
TRACE(("leave newtcpdirect: err %d", err))
return err;
}
#endif /* ENABLE_CLI_REMOTETCPFWD */
#endif /* DROPBEAR_CLI_REMOTETCPFWD */

View File

@@ -30,6 +30,9 @@
#include "dh_groups.h"
#include "ltc_prng.h"
#include "ecc.h"
#include "gcm.h"
#include "chachapoly.h"
#include "ssh.h"
/* This file (algo.c) organises the ciphers which can be used, and is used to
* decide which ciphers/hashes/compression/signing to use during key exchange*/
@@ -53,27 +56,23 @@ static int void_start(int UNUSED(cipher), const unsigned char* UNUSED(IV),
/* Remember to add new ciphers/hashes to regciphers/reghashes too */
#ifdef DROPBEAR_AES256
#if DROPBEAR_AES256
static const struct dropbear_cipher dropbear_aes256 =
{&aes_desc, 32, 16};
#endif
#ifdef DROPBEAR_AES128
#if DROPBEAR_AES128
static const struct dropbear_cipher dropbear_aes128 =
{&aes_desc, 16, 16};
#endif
#ifdef DROPBEAR_BLOWFISH
static const struct dropbear_cipher dropbear_blowfish =
{&blowfish_desc, 16, 8};
#endif
#ifdef DROPBEAR_TWOFISH256
#if DROPBEAR_TWOFISH256
static const struct dropbear_cipher dropbear_twofish256 =
{&twofish_desc, 32, 16};
#endif
#ifdef DROPBEAR_TWOFISH128
#if DROPBEAR_TWOFISH128
static const struct dropbear_cipher dropbear_twofish128 =
{&twofish_desc, 16, 16};
#endif
#ifdef DROPBEAR_3DES
#if DROPBEAR_3DES
static const struct dropbear_cipher dropbear_3des =
{&des3_desc, 24, 8};
#endif
@@ -84,15 +83,15 @@ const struct dropbear_cipher dropbear_nocipher =
/* A few void* s are required to silence warnings
* about the symmetric_CBC vs symmetric_CTR cipher_state pointer */
#ifdef DROPBEAR_ENABLE_CBC_MODE
#if DROPBEAR_ENABLE_CBC_MODE
const struct dropbear_cipher_mode dropbear_mode_cbc =
{(void*)cbc_start, (void*)cbc_encrypt, (void*)cbc_decrypt};
{(void*)cbc_start, (void*)cbc_encrypt, (void*)cbc_decrypt, NULL, NULL, NULL};
#endif /* DROPBEAR_ENABLE_CBC_MODE */
const struct dropbear_cipher_mode dropbear_mode_none =
{void_start, void_cipher, void_cipher};
{void_start, void_cipher, void_cipher, NULL, NULL, NULL};
#ifdef DROPBEAR_ENABLE_CTR_MODE
#if DROPBEAR_ENABLE_CTR_MODE
/* a wrapper to make ctr_start and cbc_start look the same */
static int dropbear_big_endian_ctr_start(int cipher,
const unsigned char *IV,
@@ -101,29 +100,29 @@ static int dropbear_big_endian_ctr_start(int cipher,
return ctr_start(cipher, IV, key, keylen, num_rounds, CTR_COUNTER_BIG_ENDIAN, ctr);
}
const struct dropbear_cipher_mode dropbear_mode_ctr =
{(void*)dropbear_big_endian_ctr_start, (void*)ctr_encrypt, (void*)ctr_decrypt};
{(void*)dropbear_big_endian_ctr_start, (void*)ctr_encrypt, (void*)ctr_decrypt, NULL, NULL, NULL};
#endif /* DROPBEAR_ENABLE_CTR_MODE */
/* Mapping of ssh hashes to libtomcrypt hashes, including keysize etc.
{&hash_desc, keysize, hashsize} */
#ifdef DROPBEAR_SHA1_HMAC
#if DROPBEAR_SHA1_HMAC
static const struct dropbear_hash dropbear_sha1 =
{&sha1_desc, 20, 20};
#endif
#ifdef DROPBEAR_SHA1_96_HMAC
#if DROPBEAR_SHA1_96_HMAC
static const struct dropbear_hash dropbear_sha1_96 =
{&sha1_desc, 20, 12};
#endif
#ifdef DROPBEAR_SHA2_256_HMAC
#if DROPBEAR_SHA2_256_HMAC
static const struct dropbear_hash dropbear_sha2_256 =
{&sha256_desc, 32, 32};
#endif
#ifdef DROPBEAR_SHA2_512_HMAC
#if DROPBEAR_SHA2_512_HMAC
static const struct dropbear_hash dropbear_sha2_512 =
{&sha512_desc, 64, 64};
#endif
#ifdef DROPBEAR_MD5_HMAC
#if DROPBEAR_MD5_HMAC
static const struct dropbear_hash dropbear_md5 =
{&md5_desc, 16, 16};
#endif
@@ -137,72 +136,82 @@ const struct dropbear_hash dropbear_nohash =
* that is also supported by the server will get used. */
algo_type sshciphers[] = {
#ifdef DROPBEAR_ENABLE_CTR_MODE
#ifdef DROPBEAR_AES128
#if DROPBEAR_CHACHA20POLY1305
{"chacha20-poly1305@openssh.com", 0, &dropbear_chachapoly, 1, &dropbear_mode_chachapoly},
#endif
#if DROPBEAR_ENABLE_GCM_MODE
#if DROPBEAR_AES128
{"aes128-gcm@openssh.com", 0, &dropbear_aes128, 1, &dropbear_mode_gcm},
#endif
#if DROPBEAR_AES256
{"aes256-gcm@openssh.com", 0, &dropbear_aes256, 1, &dropbear_mode_gcm},
#endif
#endif /* DROPBEAR_ENABLE_GCM_MODE */
#if DROPBEAR_ENABLE_CTR_MODE
#if DROPBEAR_AES128
{"aes128-ctr", 0, &dropbear_aes128, 1, &dropbear_mode_ctr},
#endif
#ifdef DROPBEAR_AES256
#if DROPBEAR_AES256
{"aes256-ctr", 0, &dropbear_aes256, 1, &dropbear_mode_ctr},
#endif
#ifdef DROPBEAR_TWOFISH_CTR
#if DROPBEAR_TWOFISH_CTR
/* twofish ctr is conditional as it hasn't been tested for interoperability, see options.h */
#ifdef DROPBEAR_TWOFISH256
#if DROPBEAR_TWOFISH256
{"twofish256-ctr", 0, &dropbear_twofish256, 1, &dropbear_mode_ctr},
#endif
#ifdef DROPBEAR_TWOFISH128
#if DROPBEAR_TWOFISH128
{"twofish128-ctr", 0, &dropbear_twofish128, 1, &dropbear_mode_ctr},
#endif
#endif /* DROPBEAR_TWOFISH_CTR */
#endif /* DROPBEAR_ENABLE_CTR_MODE */
#ifdef DROPBEAR_ENABLE_CBC_MODE
#ifdef DROPBEAR_AES128
#if DROPBEAR_ENABLE_CBC_MODE
#if DROPBEAR_AES128
{"aes128-cbc", 0, &dropbear_aes128, 1, &dropbear_mode_cbc},
#endif
#ifdef DROPBEAR_AES256
#if DROPBEAR_AES256
{"aes256-cbc", 0, &dropbear_aes256, 1, &dropbear_mode_cbc},
#endif
#ifdef DROPBEAR_TWOFISH256
#if DROPBEAR_TWOFISH256
{"twofish256-cbc", 0, &dropbear_twofish256, 1, &dropbear_mode_cbc},
{"twofish-cbc", 0, &dropbear_twofish256, 1, &dropbear_mode_cbc},
#endif
#ifdef DROPBEAR_TWOFISH128
#if DROPBEAR_TWOFISH128
{"twofish128-cbc", 0, &dropbear_twofish128, 1, &dropbear_mode_cbc},
#endif
#ifdef DROPBEAR_3DES
#endif /* DROPBEAR_ENABLE_CBC_MODE */
#if DROPBEAR_3DES
#if DROPBEAR_ENABLE_CTR_MODE
{"3des-ctr", 0, &dropbear_3des, 1, &dropbear_mode_ctr},
#endif
#ifdef DROPBEAR_3DES
#if DROPBEAR_ENABLE_CBC_MODE
{"3des-cbc", 0, &dropbear_3des, 1, &dropbear_mode_cbc},
#endif
#ifdef DROPBEAR_BLOWFISH
{"blowfish-cbc", 0, &dropbear_blowfish, 1, &dropbear_mode_cbc},
#endif
#endif /* DROPBEAR_3DES */
#if DROPBEAR_ENABLE_CBC_MODE
#endif /* DROPBEAR_ENABLE_CBC_MODE */
#ifdef DROPBEAR_NONE_CIPHER
{"none", 0, (void*)&dropbear_nocipher, 1, &dropbear_mode_none},
#endif
{NULL, 0, NULL, 0, NULL}
};
algo_type sshhashes[] = {
#ifdef DROPBEAR_SHA1_96_HMAC
#if DROPBEAR_SHA1_96_HMAC
{"hmac-sha1-96", 0, &dropbear_sha1_96, 1, NULL},
#endif
#ifdef DROPBEAR_SHA1_HMAC
#if DROPBEAR_SHA1_HMAC
{"hmac-sha1", 0, &dropbear_sha1, 1, NULL},
#endif
#ifdef DROPBEAR_SHA2_256_HMAC
#if DROPBEAR_SHA2_256_HMAC
{"hmac-sha2-256", 0, &dropbear_sha2_256, 1, NULL},
#endif
#ifdef DROPBEAR_SHA2_512_HMAC
#if DROPBEAR_SHA2_512_HMAC
{"hmac-sha2-512", 0, &dropbear_sha2_512, 1, NULL},
#endif
#ifdef DROPBEAR_MD5_HMAC
#if DROPBEAR_MD5_HMAC
{"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}
};
@@ -227,23 +236,31 @@ algo_type ssh_nocompress[] = {
{NULL, 0, NULL, 0, NULL}
};
algo_type sshhostkey[] = {
#ifdef DROPBEAR_ECDSA
#ifdef DROPBEAR_ECC_256
{"ecdsa-sha2-nistp256", DROPBEAR_SIGNKEY_ECDSA_NISTP256, NULL, 1, NULL},
algo_type sigalgs[] = {
#if DROPBEAR_ED25519
{"ssh-ed25519", DROPBEAR_SIGNATURE_ED25519, NULL, 1, NULL},
#endif
#ifdef DROPBEAR_ECC_384
{"ecdsa-sha2-nistp384", DROPBEAR_SIGNKEY_ECDSA_NISTP384, NULL, 1, NULL},
#if DROPBEAR_ECDSA
#if DROPBEAR_ECC_256
{"ecdsa-sha2-nistp256", DROPBEAR_SIGNATURE_ECDSA_NISTP256, NULL, 1, NULL},
#endif
#ifdef DROPBEAR_ECC_521
{"ecdsa-sha2-nistp521", DROPBEAR_SIGNKEY_ECDSA_NISTP521, NULL, 1, NULL},
#if DROPBEAR_ECC_384
{"ecdsa-sha2-nistp384", DROPBEAR_SIGNATURE_ECDSA_NISTP384, NULL, 1, NULL},
#endif
#if DROPBEAR_ECC_521
{"ecdsa-sha2-nistp521", DROPBEAR_SIGNATURE_ECDSA_NISTP521, NULL, 1, NULL},
#endif
#endif
#ifdef DROPBEAR_RSA
{"ssh-rsa", DROPBEAR_SIGNKEY_RSA, NULL, 1, NULL},
#if DROPBEAR_RSA
#if DROPBEAR_RSA_SHA256
{"rsa-sha2-256", DROPBEAR_SIGNATURE_RSA_SHA256, NULL, 1, NULL},
#endif
#ifdef DROPBEAR_DSS
{"ssh-dss", DROPBEAR_SIGNKEY_DSS, NULL, 1, NULL},
#if DROPBEAR_RSA_SHA1
{"ssh-rsa", DROPBEAR_SIGNATURE_RSA_SHA1, NULL, 1, NULL},
#endif
#endif
#if DROPBEAR_DSS
{"ssh-dss", DROPBEAR_SIGNATURE_DSS, NULL, 1, NULL},
#endif
{NULL, 0, NULL, 0, NULL}
};
@@ -251,54 +268,54 @@ algo_type sshhostkey[] = {
#if DROPBEAR_DH_GROUP1
static const struct dropbear_kex kex_dh_group1 = {DROPBEAR_KEX_NORMAL_DH, dh_p_1, DH_P_1_LEN, NULL, &sha1_desc };
#endif
#if DROPBEAR_DH_GROUP14
#if DROPBEAR_DH_GROUP14_SHA1
static const struct dropbear_kex kex_dh_group14_sha1 = {DROPBEAR_KEX_NORMAL_DH, dh_p_14, DH_P_14_LEN, NULL, &sha1_desc };
#if DROPBEAR_DH_GROUP14_256
static const struct dropbear_kex kex_dh_group14_sha256 = {DROPBEAR_KEX_NORMAL_DH, dh_p_14, DH_P_14_LEN, NULL, &sha256_desc };
#endif
#if DROPBEAR_DH_GROUP14_SHA256
static const struct dropbear_kex kex_dh_group14_sha256 = {DROPBEAR_KEX_NORMAL_DH, dh_p_14, DH_P_14_LEN, NULL, &sha256_desc };
#endif
#if DROPBEAR_DH_GROUP16
static const struct dropbear_kex kex_dh_group16_sha512 = {DROPBEAR_KEX_NORMAL_DH, dh_p_16, DH_P_16_LEN, NULL, &sha512_desc };
#endif
/* These can't be const since dropbear_ecc_fill_dp() fills out
ecc_curve at runtime */
#ifdef DROPBEAR_ECDH
#ifdef DROPBEAR_ECC_256
#if DROPBEAR_ECDH
#if DROPBEAR_ECC_256
static const struct dropbear_kex kex_ecdh_nistp256 = {DROPBEAR_KEX_ECDH, NULL, 0, &ecc_curve_nistp256, &sha256_desc };
#endif
#ifdef DROPBEAR_ECC_384
#if DROPBEAR_ECC_384
static const struct dropbear_kex kex_ecdh_nistp384 = {DROPBEAR_KEX_ECDH, NULL, 0, &ecc_curve_nistp384, &sha384_desc };
#endif
#ifdef DROPBEAR_ECC_521
#if DROPBEAR_ECC_521
static const struct dropbear_kex kex_ecdh_nistp521 = {DROPBEAR_KEX_ECDH, NULL, 0, &ecc_curve_nistp521, &sha512_desc };
#endif
#endif /* DROPBEAR_ECDH */
#ifdef DROPBEAR_CURVE25519
#if DROPBEAR_CURVE25519
/* Referred to directly */
static const struct dropbear_kex kex_curve25519 = {DROPBEAR_KEX_CURVE25519, NULL, 0, NULL, &sha256_desc };
#endif
/* data == NULL for non-kex algorithm identifiers */
algo_type sshkex[] = {
#ifdef DROPBEAR_CURVE25519
#if DROPBEAR_CURVE25519
{"curve25519-sha256", 0, &kex_curve25519, 1, NULL},
{"curve25519-sha256@libssh.org", 0, &kex_curve25519, 1, NULL},
#endif
#ifdef DROPBEAR_ECDH
#ifdef DROPBEAR_ECC_521
#if DROPBEAR_ECDH
#if DROPBEAR_ECC_521
{"ecdh-sha2-nistp521", 0, &kex_ecdh_nistp521, 1, NULL},
#endif
#ifdef DROPBEAR_ECC_384
#if DROPBEAR_ECC_384
{"ecdh-sha2-nistp384", 0, &kex_ecdh_nistp384, 1, NULL},
#endif
#ifdef DROPBEAR_ECC_256
#if DROPBEAR_ECC_256
{"ecdh-sha2-nistp256", 0, &kex_ecdh_nistp256, 1, NULL},
#endif
#endif
#if DROPBEAR_DH_GROUP14
#if DROPBEAR_DH_GROUP14_256
#if DROPBEAR_DH_GROUP14_SHA256
{"diffie-hellman-group14-sha256", 0, &kex_dh_group14_sha256, 1, NULL},
#endif
#if DROPBEAR_DH_GROUP14_SHA1
{"diffie-hellman-group14-sha1", 0, &kex_dh_group14_sha1, 1, NULL},
#endif
#if DROPBEAR_DH_GROUP1
@@ -307,49 +324,123 @@ algo_type sshkex[] = {
#if DROPBEAR_DH_GROUP16
{"diffie-hellman-group16-sha512", 0, &kex_dh_group16_sha512, 1, NULL},
#endif
#ifdef USE_KEXGUESS2
{KEXGUESS2_ALGO_NAME, KEXGUESS2_ALGO_ID, NULL, 1, NULL},
#if DROPBEAR_KEXGUESS2
{KEXGUESS2_ALGO_NAME, 0, NULL, 1, NULL},
#endif
#if DROPBEAR_EXT_INFO
#if DROPBEAR_CLIENT
/* Set unusable by svr_algos_initialise() */
{SSH_EXT_INFO_C, 0, NULL, 1, NULL},
#endif
#endif
{NULL, 0, NULL, 0, NULL}
};
/* algolen specifies the length of algo, algos is our local list to match
* against.
* Returns DROPBEAR_SUCCESS if we have a match for algo, DROPBEAR_FAILURE
* otherwise */
int have_algo(char* algo, size_t algolen, algo_type algos[]) {
int i;
for (i = 0; algos[i].name != NULL; i++) {
if (strlen(algos[i].name) == algolen
&& (strncmp(algos[i].name, algo, algolen) == 0)) {
return DROPBEAR_SUCCESS;
}
}
return DROPBEAR_FAILURE;
}
/* Output a comma separated list of algorithms to a buffer */
void buf_put_algolist(buffer * buf, algo_type localalgos[]) {
void buf_put_algolist_all(buffer * buf, const algo_type localalgos[], int useall) {
unsigned int i, len;
unsigned int donefirst = 0;
buffer *algolist = NULL;
unsigned int startpos;
algolist = buf_new(300);
startpos = buf->pos;
/* Placeholder for length */
buf_putint(buf, 0);
for (i = 0; localalgos[i].name != NULL; i++) {
if (localalgos[i].usable) {
if (donefirst)
buf_putbyte(algolist, ',');
if (localalgos[i].usable || useall) {
if (donefirst) {
buf_putbyte(buf, ',');
}
donefirst = 1;
len = strlen(localalgos[i].name);
buf_putbytes(algolist, (const unsigned char *) localalgos[i].name, len);
buf_putbytes(buf, (const unsigned char *) localalgos[i].name, len);
}
}
buf_putstring(buf, (const char*)algolist->data, algolist->len);
buf_free(algolist);
/* Fill out the length */
len = buf->pos - startpos - 4;
buf_setpos(buf, startpos);
buf_putint(buf, len);
TRACE(("algolist add %d '%*s'", len, len, buf_getptr(buf, len)))
buf_incrwritepos(buf, len);
}
void buf_put_algolist(buffer * buf, const algo_type localalgos[]) {
buf_put_algolist_all(buf, localalgos, 0);
}
/* returns a list of pointers into algolist, of null-terminated names.
ret_list should be passed in with space for *ret_count elements,
on return *ret_count has the number of names filled.
algolist is modified. */
static void get_algolist(char* algolist, unsigned int algolist_len,
const char* *ret_list, unsigned int *ret_count) {
unsigned int max_count = *ret_count;
unsigned int i;
if (*ret_count == 0) {
return;
}
if (algolist_len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
*ret_count = 0;
}
/* ret_list will contain a list of the strings parsed out.
We will have at least one string (even if it's just "") */
ret_list[0] = algolist;
*ret_count = 1;
for (i = 0; i < algolist_len; i++) {
if (algolist[i] == '\0') {
/* someone is trying something strange */
*ret_count = 0;
return;
}
if (algolist[i] == ',') {
if (*ret_count >= max_count) {
/* Too many */
*ret_count = 0;
return;
}
algolist[i] = '\0';
ret_list[*ret_count] = &algolist[i+1];
(*ret_count)++;
}
}
}
/* Return DROPBEAR_SUCCESS if the namelist contains algo,
DROPBEAR_FAILURE otherwise. buf position is not incremented. */
int buf_has_algo(buffer *buf, const char *algo) {
unsigned char* algolist = NULL;
unsigned int orig_pos = buf->pos;
unsigned int len, remotecount, i;
const char *remotenames[MAX_PROPOSED_ALGO];
int ret = DROPBEAR_FAILURE;
algolist = buf_getstring(buf, &len);
remotecount = MAX_PROPOSED_ALGO;
get_algolist(algolist, len, remotenames, &remotecount);
for (i = 0; i < remotecount; i++)
{
if (strcmp(remotenames[i], algo) == 0) {
ret = DROPBEAR_SUCCESS;
break;
}
}
if (algolist) {
m_free(algolist);
}
buf_setpos(buf, orig_pos);
return ret;
}
algo_type * first_usable_algo(algo_type algos[]) {
int i;
for (i = 0; algos[i].name != NULL; i++) {
if (algos[i].usable) {
return &algos[i];
}
}
return NULL;
}
/* match the first algorithm in the comma-separated list in buf which is
@@ -358,9 +449,7 @@ void buf_put_algolist(buffer * buf, algo_type localalgos[]) {
* 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)
{
int kexguess2, int *goodguess) {
char * algolist = NULL;
const char *remotenames[MAX_PROPOSED_ALGO], *localnames[MAX_PROPOSED_ALGO];
unsigned int len;
@@ -375,40 +464,8 @@ algo_type * buf_match_algo(buffer* buf, algo_type localalgos[],
/* 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;
}
}
remotecount = MAX_PROPOSED_ALGO;
get_algolist(algolist, len, remotenames, &remotecount);
for (i = 0; localalgos[i].name != NULL; i++) {
if (localalgos[i].usable) {
@@ -440,12 +497,11 @@ algo_type * buf_match_algo(buffer* buf, algo_type localalgos[],
}
if (strcmp(servnames[j], clinames[i]) == 0) {
/* set if it was a good guess */
if (goodguess && kexguess2) {
if (*kexguess2 == KEXGUESS2_YES) {
if (goodguess != NULL) {
if (kexguess2) {
if (i == 0) {
*goodguess = 1;
}
} else {
if (i == 0 && j == 0) {
*goodguess = 1;
@@ -468,42 +524,10 @@ out:
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
#if DROPBEAR_USER_ALGO_LIST
char *
algolist_string(algo_type algos[])
algolist_string(const algo_type algos[])
{
char *ret_list;
buffer *b = buf_new(200);
@@ -531,21 +555,6 @@ check_algo(const char* algo_name, algo_type *algos)
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. */
@@ -553,30 +562,43 @@ 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;
algo_type new_algos[MAX_PROPOSED_ALGO+1];
char *work_list = m_strdup(user_algo_list);
char *last_name = work_list;
char *start = work_list;
char *c;
for (c = work_list; *c; c++)
int n;
/* So we can iterate and look for null terminator */
memset(new_algos, 0x0, sizeof(new_algos));
for (c = work_list, n = 0; ; c++)
{
if (*c == ',')
{
char oc = *c;
if (n >= MAX_PROPOSED_ALGO) {
dropbear_exit("Too many algorithms '%s'", user_algo_list);
}
if (*c == ',' || *c == '\0') {
algo_type *match_algo = NULL;
*c = '\0';
try_add_algo(last_name, algos, algo_desc, new_algos, &num_ret);
match_algo = check_algo(start, algos);
if (match_algo) {
if (check_algo(start, new_algos)) {
TRACE(("Skip repeated algorithm '%s'", start))
} else {
new_algos[n] = *match_algo;
n++;
}
} else {
dropbear_log(LOG_WARNING, "This Dropbear program does not support '%s' %s algorithm", start, algo_desc);
}
c++;
last_name = c;
start = c;
}
if (oc == '\0') {
break;
}
}
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;
/* n+1 to include a null terminator */
memcpy(algos, new_algos, sizeof(*new_algos) * (n+1));
return n;
}
#endif /* ENABLE_USER_ALGO_LIST */
#endif /* DROPBEAR_USER_ALGO_LIST */

View File

@@ -32,25 +32,24 @@
#include "circbuffer.h"
#include "dbutil.h"
#include "channel.h"
#include "ssh.h"
#include "listener.h"
#include "runopts.h"
#include "netio.h"
static void send_msg_channel_open_failure(unsigned int remotechan, int reason,
const char *text, const char *lang);
static void send_msg_channel_open_confirmation(struct Channel* channel,
static void send_msg_channel_open_confirmation(const struct Channel* channel,
unsigned int recvwindow,
unsigned int recvmaxpacket);
static int writechannel(struct Channel* channel, int fd, circbuffer *cbuf,
const unsigned char *moredata, unsigned int *morelen);
static void send_msg_channel_window_adjust(struct Channel *channel,
static void send_msg_channel_window_adjust(const struct Channel *channel,
unsigned int incr);
static void send_msg_channel_data(struct Channel *channel, int isextended);
static void send_msg_channel_eof(struct Channel *channel);
static void send_msg_channel_close(struct Channel *channel);
static void remove_channel(struct Channel *channel);
static unsigned int write_pending(struct Channel * channel);
static unsigned int write_pending(const struct Channel * channel);
static void check_close(struct Channel *channel);
static void close_chan_fd(struct Channel *channel, int fd, int how);
@@ -78,7 +77,7 @@ void chaninitialise(const struct ChanType *chantypes[]) {
ses.chantypes = chantypes;
#ifdef USING_LISTENERS
#if DROPBEAR_LISTENERS
listeners_initialise();
#endif
@@ -145,7 +144,6 @@ static 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;
@@ -199,7 +197,7 @@ struct Channel* getchannel() {
}
/* Iterate through the channels, performing IO if available */
void channelio(fd_set *readfds, fd_set *writefds) {
void channelio(const fd_set *readfds, const fd_set *writefds) {
/* Listeners such as TCP, X11, agent-auth */
struct Channel *channel;
@@ -255,7 +253,7 @@ void channelio(fd_set *readfds, fd_set *writefds) {
}
}
#ifdef USING_LISTENERS
#if DROPBEAR_LISTENERS
handle_listeners(readfds);
#endif
}
@@ -263,7 +261,7 @@ void channelio(fd_set *readfds, fd_set *writefds) {
/* Returns true if there is data remaining to be written to stdin or
* stderr of a channel's endpoint. */
static unsigned int write_pending(struct Channel * channel) {
static unsigned int write_pending(const struct Channel * channel) {
if (channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0) {
return 1;
@@ -287,7 +285,7 @@ static void check_close(struct Channel *channel) {
channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0))
if (!channel->flushing
&& !channel->close_handler_done
&& !channel->sent_close
&& channel->type->check_close
&& channel->type->check_close(channel))
{
@@ -299,7 +297,7 @@ 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->close_handler_done
|| channel->sent_close
|| channel->type->check_close(channel)) {
close_allowed = 1;
}
@@ -386,10 +384,8 @@ void channel_connect_done(int result, int sock, void* user_data, const char* UNU
static void send_msg_channel_close(struct Channel *channel) {
TRACE(("enter send_msg_channel_close %p", (void*)channel))
if (channel->type->closehandler
&& !channel->close_handler_done) {
if (channel->type->closehandler) {
channel->type->closehandler(channel);
channel->close_handler_done = 1;
}
CHECKCLEARTOWRITE();
@@ -595,7 +591,7 @@ void setchannelfds(fd_set *readfds, fd_set *writefds, int allow_reads) {
} /* foreach channel */
#ifdef USING_LISTENERS
#if DROPBEAR_LISTENERS
set_listener_fds(readfds);
#endif
@@ -662,10 +658,8 @@ static void remove_channel(struct Channel * channel) {
m_close(channel->errfd);
}
if (!channel->close_handler_done
&& channel->type->closehandler) {
channel->type->closehandler(channel);
channel->close_handler_done = 1;
if (channel->type->cleanup) {
channel->type->cleanup(channel);
}
if (channel->conn_pending) {
@@ -691,13 +685,7 @@ void recv_msg_channel_request() {
TRACE(("enter recv_msg_channel_request %p", (void*)channel))
if (channel->sent_close) {
TRACE(("leave recv_msg_channel_request: already closed channel"))
return;
}
if (channel->type->reqhandler
&& !channel->close_handler_done) {
if (channel->type->reqhandler) {
channel->type->reqhandler(channel);
} else {
int wantreply;
@@ -904,7 +892,7 @@ void recv_msg_channel_window_adjust() {
/* Increment the incoming data window for a channel, and let the remote
* end know */
static void send_msg_channel_window_adjust(struct Channel* channel,
static void send_msg_channel_window_adjust(const struct Channel* channel,
unsigned int incr) {
TRACE(("sending window adjust %d", incr))
@@ -1009,9 +997,14 @@ cleanup:
}
/* Send a failure message */
void send_msg_channel_failure(struct Channel *channel) {
void send_msg_channel_failure(const struct Channel *channel) {
TRACE(("enter send_msg_channel_failure"))
if (channel->sent_close) {
TRACE(("Skipping sending msg_channel_failure for closed channel"))
return;
}
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_FAILURE);
@@ -1022,9 +1015,13 @@ void send_msg_channel_failure(struct Channel *channel) {
}
/* Send a success message */
void send_msg_channel_success(struct Channel *channel) {
void send_msg_channel_success(const struct Channel *channel) {
TRACE(("enter send_msg_channel_success"))
if (channel->sent_close) {
TRACE(("Skipping sending msg_channel_success for closed channel"))
return;
}
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_SUCCESS);
@@ -1054,7 +1051,7 @@ static void send_msg_channel_open_failure(unsigned int remotechan,
/* Confirm a channel open, and let the remote end know what number we've
* allocated and the receive parameters */
static void send_msg_channel_open_confirmation(struct Channel* channel,
static void send_msg_channel_open_confirmation(const struct Channel* channel,
unsigned int recvwindow,
unsigned int recvmaxpacket) {
@@ -1114,7 +1111,7 @@ static void close_chan_fd(struct Channel *channel, int fd, int how) {
}
#if defined(USING_LISTENERS) || defined(DROPBEAR_CLIENT)
#if (DROPBEAR_LISTENERS) || (DROPBEAR_CLIENT)
/* Create a new channel, and start the open request. This is intended
* for X11, agent, tcp forwarding, and should be filled with channel-specific
* options, with the calling function calling encrypt_packet() after
@@ -1210,7 +1207,7 @@ void recv_msg_channel_open_failure() {
remove_channel(channel);
}
#endif /* USING_LISTENERS */
#endif /* DROPBEAR_LISTENERS */
void send_msg_request_success() {
CHECKCLEARTOWRITE();
@@ -1240,8 +1237,8 @@ struct Channel* get_any_ready_channel() {
return NULL;
}
void start_send_channel_request(struct Channel *channel,
char *type) {
void start_send_channel_request(const struct Channel *channel,
const char *type) {
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_REQUEST);

View File

@@ -36,6 +36,7 @@
#include "dbrandom.h"
#include "runopts.h"
#include "ecc.h"
#include "curve25519.h"
#include "crypto_desc.h"
static void kexinitialise(void);
@@ -48,7 +49,6 @@ static void read_kex_algos(void);
/* helper function for gen_new_keys */
static void hashkeys(unsigned char *out, unsigned int outlen,
const hash_state * hs, const unsigned char X);
static void finish_kexhashbuf(void);
/* Send our list of algorithms we can use */
@@ -65,7 +65,7 @@ void send_msg_kexinit() {
buf_put_algolist(ses.writepayload, sshkex);
/* server_host_key_algorithms */
buf_put_algolist(ses.writepayload, sshhostkey);
buf_put_algolist(ses.writepayload, sigalgs);
/* encryption_algorithms_client_to_server */
buf_put_algolist(ses.writepayload, sshciphers);
@@ -110,8 +110,9 @@ void send_msg_kexinit() {
ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
if (ses.send_kex_first_guess) {
ses.newkeys->algo_kex = sshkex[0].data;
ses.newkeys->algo_hostkey = sshhostkey[0].val;
ses.newkeys->algo_kex = first_usable_algo(sshkex)->data;
ses.newkeys->algo_signature = first_usable_algo(sigalgs)->val;
ses.newkeys->algo_hostkey = signkey_type_from_signature(ses.newkeys->algo_signature);
ses.send_kex_first_guess();
}
@@ -152,6 +153,7 @@ static void switch_keys() {
TRACE(("switch_keys done"))
ses.keys->algo_kex = ses.newkeys->algo_kex;
ses.keys->algo_hostkey = ses.newkeys->algo_hostkey;
ses.keys->algo_signature = ses.newkeys->algo_signature;
ses.keys->allow_compress = 0;
m_free(ses.newkeys);
ses.newkeys = NULL;
@@ -173,6 +175,9 @@ void send_msg_newkeys() {
/* set up our state */
ses.kexstate.sentnewkeys = 1;
if (ses.kexstate.donefirstkex) {
ses.kexstate.donesecondkex = 1;
}
ses.kexstate.donefirstkex = 1;
ses.dataallowed = 1; /* we can send other packets again now */
gen_new_keys();
@@ -195,8 +200,6 @@ void recv_msg_newkeys() {
/* Set up the kex for the first time */
void kexfirstinitialise() {
ses.kexstate.donefirstkex = 0;
#ifdef DISABLE_ZLIB
ses.compress_algos = ssh_nocompress;
#else
@@ -329,9 +332,13 @@ static void gen_new_keys() {
hashkeys(S2C_key, sizeof(S2C_key), &hs, 'D');
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");
int recv_cipher = -1;
if (ses.newkeys->recv.algo_crypt->cipherdesc->name != NULL) {
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,
@@ -341,9 +348,13 @@ static void gen_new_keys() {
}
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");
int trans_cipher = -1;
if (ses.newkeys->trans.algo_crypt->cipherdesc->name != NULL) {
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,
@@ -391,6 +402,14 @@ int is_compress_recv() {
&& ses.keys->recv.algo_comp == DROPBEAR_COMP_ZLIB_DELAY);
}
static void* dropbear_zalloc(void* UNUSED(opaque), uInt items, uInt size) {
return m_calloc(items, size);
}
static void dropbear_zfree(void* UNUSED(opaque), void* ptr) {
m_free(ptr);
}
/* Set up new zlib compression streams, close the old ones. Only
* called from gen_new_keys() */
static void gen_new_zstream_recv() {
@@ -399,8 +418,8 @@ static void gen_new_zstream_recv() {
if (ses.newkeys->recv.algo_comp == DROPBEAR_COMP_ZLIB
|| ses.newkeys->recv.algo_comp == DROPBEAR_COMP_ZLIB_DELAY) {
ses.newkeys->recv.zstream = (z_streamp)m_malloc(sizeof(z_stream));
ses.newkeys->recv.zstream->zalloc = Z_NULL;
ses.newkeys->recv.zstream->zfree = Z_NULL;
ses.newkeys->recv.zstream->zalloc = dropbear_zalloc;
ses.newkeys->recv.zstream->zfree = dropbear_zfree;
if (inflateInit(ses.newkeys->recv.zstream) != Z_OK) {
dropbear_exit("zlib error");
@@ -423,8 +442,8 @@ static void gen_new_zstream_trans() {
if (ses.newkeys->trans.algo_comp == DROPBEAR_COMP_ZLIB
|| ses.newkeys->trans.algo_comp == DROPBEAR_COMP_ZLIB_DELAY) {
ses.newkeys->trans.zstream = (z_streamp)m_malloc(sizeof(z_stream));
ses.newkeys->trans.zstream->zalloc = Z_NULL;
ses.newkeys->trans.zstream->zfree = Z_NULL;
ses.newkeys->trans.zstream->zalloc = dropbear_zalloc;
ses.newkeys->trans.zstream->zfree = dropbear_zfree;
if (deflateInit2(ses.newkeys->trans.zstream, Z_DEFAULT_COMPRESSION,
Z_DEFLATED, DROPBEAR_ZLIB_WINDOW_BITS,
@@ -529,6 +548,7 @@ void recv_msg_kexinit() {
TRACE(("leave recv_msg_kexinit"))
}
#if DROPBEAR_NORMAL_DH
static void load_dh_p(mp_int * dh_p)
{
bytes_to_mp(dh_p, ses.newkeys->algo_kex->dh_p_bytes,
@@ -553,9 +573,7 @@ struct kex_dh_param *gen_kexdh_param() {
/* read the prime and generator*/
load_dh_p(&dh_p);
if (mp_set_int(&dh_g, DH_G_VAL) != MP_OKAY) {
dropbear_exit("Diffie-Hellman error");
}
mp_set_ul(&dh_g, DH_G_VAL);
/* calculate q = (p-1)/2 */
/* dh_priv is just a temp var here */
@@ -639,8 +657,9 @@ void kexdh_comb_key(struct kex_dh_param *param, mp_int *dh_pub_them,
/* calculate the hash H to sign */
finish_kexhashbuf();
}
#endif
#ifdef DROPBEAR_ECDH
#if DROPBEAR_ECDH
struct kex_ecdh_param *gen_kexecdh_param() {
struct kex_ecdh_param *param = m_malloc(sizeof(*param));
if (ecc_make_key_ex(NULL, dropbear_ltc_prng,
@@ -687,34 +706,32 @@ void kexecdh_comb_key(struct kex_ecdh_param *param, buffer *pub_them,
/* K, the shared secret */
buf_putmpint(ses.kexhashbuf, ses.dh_K);
ecc_free(Q_them);
m_free(Q_them);
/* calculate the hash H to sign */
finish_kexhashbuf();
}
#endif /* DROPBEAR_ECDH */
#ifdef DROPBEAR_CURVE25519
struct kex_curve25519_param *gen_kexcurve25519_param () {
#if DROPBEAR_CURVE25519
struct kex_curve25519_param *gen_kexcurve25519_param() {
/* Per http://cr.yp.to/ecdh.html */
struct kex_curve25519_param *param = m_malloc(sizeof(*param));
const unsigned char basepoint[32] = {9};
genrandom(param->priv, CURVE25519_LEN);
param->priv[0] &= 248;
param->priv[31] &= 127;
param->priv[31] |= 64;
curve25519_donna(param->pub, param->priv, basepoint);
dropbear_curve25519_scalarmult(param->pub, param->priv, basepoint);
return param;
}
void free_kexcurve25519_param(struct kex_curve25519_param *param)
{
void free_kexcurve25519_param(struct kex_curve25519_param *param) {
m_burn(param->priv, CURVE25519_LEN);
m_free(param);
}
void kexcurve25519_comb_key(struct kex_curve25519_param *param, buffer *buf_pub_them,
void kexcurve25519_comb_key(const struct kex_curve25519_param *param, const buffer *buf_pub_them,
sign_key *hostkey) {
unsigned char out[CURVE25519_LEN];
const unsigned char* Q_C = NULL;
@@ -726,7 +743,7 @@ void kexcurve25519_comb_key(struct kex_curve25519_param *param, buffer *buf_pub_
dropbear_exit("Bad curve25519");
}
curve25519_donna(out, param->priv, buf_pub_them->data);
dropbear_curve25519_scalarmult(out, param->priv, buf_pub_them->data);
if (constant_time_memcmp(zeroes, out, CURVE25519_LEN) == 0) {
dropbear_exit("Bad curve25519");
@@ -761,8 +778,7 @@ void kexcurve25519_comb_key(struct kex_curve25519_param *param, buffer *buf_pub_
#endif /* DROPBEAR_CURVE25519 */
static void finish_kexhashbuf(void) {
void finish_kexhashbuf(void) {
hash_state hs;
const struct ltc_hash_descriptor *hash_desc = ses.newkeys->algo_kex->hash_desc;
@@ -774,7 +790,7 @@ static void finish_kexhashbuf(void) {
hash_desc->done(&hs, buf_getwriteptr(ses.hash, hash_desc->hashsize));
buf_setlen(ses.hash, hash_desc->hashsize);
#if defined(DEBUG_KEXHASH) && defined(DEBUG_TRACE)
#if defined(DEBUG_KEXHASH) && DEBUG_TRACE
if (!debug_trace) {
printhex("kexhashbuf", ses.kexhashbuf->data, ses.kexhashbuf->len);
printhex("kexhash", ses.hash->data, ses.hash->len);
@@ -813,21 +829,36 @@ static void read_kex_algos() {
int goodguess = 0;
int allgood = 1; /* we AND this with each goodguess and see if its still
true after */
#ifdef USE_KEXGUESS2
enum kexguess2_used kexguess2 = KEXGUESS2_LOOK;
#else
enum kexguess2_used kexguess2 = KEXGUESS2_NO;
#endif
int kexguess2 = 0;
buf_incrpos(ses.payload, 16); /* start after the cookie */
memset(ses.newkeys, 0x0, sizeof(*ses.newkeys));
/* kex_algorithms */
algo = buf_match_algo(ses.payload, sshkex, &kexguess2, &goodguess);
#if DROPBEAR_KEXGUESS2
if (buf_has_algo(ses.payload, KEXGUESS2_ALGO_NAME) == DROPBEAR_SUCCESS) {
kexguess2 = 1;
}
#endif
#if DROPBEAR_EXT_INFO
/* Determine if SSH_MSG_EXT_INFO messages should be sent.
Should be done for the first key exchange. Only required on server side
for server-sig-algs */
if (IS_DROPBEAR_SERVER) {
if (!ses.kexstate.donefirstkex) {
if (buf_has_algo(ses.payload, SSH_EXT_INFO_C) == DROPBEAR_SUCCESS) {
ses.allow_ext_info = 1;
}
}
}
#endif
algo = buf_match_algo(ses.payload, sshkex, kexguess2, &goodguess);
allgood &= goodguess;
if (algo == NULL || algo->val == KEXGUESS2_ALGO_ID) {
if (algo == NULL || algo->data == NULL) {
/* kexguess2, ext-info-c, ext-info-s should not match negotiation */
erralgo = "kex";
goto error;
}
@@ -836,17 +867,18 @@ static void read_kex_algos() {
ses.newkeys->algo_kex = algo->data;
/* server_host_key_algorithms */
algo = buf_match_algo(ses.payload, sshhostkey, &kexguess2, &goodguess);
algo = buf_match_algo(ses.payload, sigalgs, kexguess2, &goodguess);
allgood &= goodguess;
if (algo == NULL) {
erralgo = "hostkey";
goto error;
}
TRACE(("hostkey algo %s", algo->name))
ses.newkeys->algo_hostkey = algo->val;
TRACE(("signature algo %s", algo->name))
ses.newkeys->algo_signature = algo->val;
ses.newkeys->algo_hostkey = signkey_type_from_signature(ses.newkeys->algo_signature);
/* encryption_algorithms_client_to_server */
c2s_cipher_algo = buf_match_algo(ses.payload, sshciphers, NULL, NULL);
c2s_cipher_algo = buf_match_algo(ses.payload, sshciphers, 0, NULL);
if (c2s_cipher_algo == NULL) {
erralgo = "enc c->s";
goto error;
@@ -854,7 +886,7 @@ static void read_kex_algos() {
TRACE(("enc c2s is %s", c2s_cipher_algo->name))
/* encryption_algorithms_server_to_client */
s2c_cipher_algo = buf_match_algo(ses.payload, sshciphers, NULL, NULL);
s2c_cipher_algo = buf_match_algo(ses.payload, sshciphers, 0, NULL);
if (s2c_cipher_algo == NULL) {
erralgo = "enc s->c";
goto error;
@@ -862,23 +894,33 @@ static void read_kex_algos() {
TRACE(("enc s2c is %s", s2c_cipher_algo->name))
/* mac_algorithms_client_to_server */
c2s_hash_algo = buf_match_algo(ses.payload, sshhashes, NULL, NULL);
c2s_hash_algo = buf_match_algo(ses.payload, sshhashes, 0, NULL);
#if DROPBEAR_AEAD_MODE
if (((struct dropbear_cipher_mode*)c2s_cipher_algo->mode)->aead_crypt != NULL) {
c2s_hash_algo = NULL;
} else
#endif
if (c2s_hash_algo == NULL) {
erralgo = "mac c->s";
goto error;
}
TRACE(("hash c2s is %s", c2s_hash_algo->name))
TRACE(("hash c2s is %s", c2s_hash_algo ? c2s_hash_algo->name : "<implicit>"))
/* mac_algorithms_server_to_client */
s2c_hash_algo = buf_match_algo(ses.payload, sshhashes, NULL, NULL);
s2c_hash_algo = buf_match_algo(ses.payload, sshhashes, 0, NULL);
#if DROPBEAR_AEAD_MODE
if (((struct dropbear_cipher_mode*)s2c_cipher_algo->mode)->aead_crypt != NULL) {
s2c_hash_algo = NULL;
} else
#endif
if (s2c_hash_algo == NULL) {
erralgo = "mac s->c";
goto error;
}
TRACE(("hash s2c is %s", s2c_hash_algo->name))
TRACE(("hash s2c is %s", s2c_hash_algo ? s2c_hash_algo->name : "<implicit>"))
/* compression_algorithms_client_to_server */
c2s_comp_algo = buf_match_algo(ses.payload, ses.compress_algos, NULL, NULL);
c2s_comp_algo = buf_match_algo(ses.payload, ses.compress_algos, 0, NULL);
if (c2s_comp_algo == NULL) {
erralgo = "comp c->s";
goto error;
@@ -886,7 +928,7 @@ static void read_kex_algos() {
TRACE(("hash c2s is %s", c2s_comp_algo->name))
/* compression_algorithms_server_to_client */
s2c_comp_algo = buf_match_algo(ses.payload, ses.compress_algos, NULL, NULL);
s2c_comp_algo = buf_match_algo(ses.payload, ses.compress_algos, 0, NULL);
if (s2c_comp_algo == NULL) {
erralgo = "comp s->c";
goto error;
@@ -920,8 +962,14 @@ static void read_kex_algos() {
ses.newkeys->trans.crypt_mode =
(struct dropbear_cipher_mode*)c2s_cipher_algo->mode;
ses.newkeys->recv.algo_mac =
#if DROPBEAR_AEAD_MODE
s2c_hash_algo == NULL ? ses.newkeys->recv.crypt_mode->aead_mac :
#endif
(struct dropbear_hash*)s2c_hash_algo->data;
ses.newkeys->trans.algo_mac =
#if DROPBEAR_AEAD_MODE
c2s_hash_algo == NULL ? ses.newkeys->trans.crypt_mode->aead_mac :
#endif
(struct dropbear_hash*)c2s_hash_algo->data;
ses.newkeys->recv.algo_comp = s2c_comp_algo->val;
ses.newkeys->trans.algo_comp = c2s_comp_algo->val;
@@ -936,13 +984,25 @@ static void read_kex_algos() {
ses.newkeys->trans.crypt_mode =
(struct dropbear_cipher_mode*)s2c_cipher_algo->mode;
ses.newkeys->recv.algo_mac =
#if DROPBEAR_AEAD_MODE
c2s_hash_algo == NULL ? ses.newkeys->recv.crypt_mode->aead_mac :
#endif
(struct dropbear_hash*)c2s_hash_algo->data;
ses.newkeys->trans.algo_mac =
#if DROPBEAR_AEAD_MODE
s2c_hash_algo == NULL ? ses.newkeys->trans.crypt_mode->aead_mac :
#endif
(struct dropbear_hash*)s2c_hash_algo->data;
ses.newkeys->recv.algo_comp = c2s_comp_algo->val;
ses.newkeys->trans.algo_comp = s2c_comp_algo->val;
}
#if DROPBEAR_FUZZ
if (fuzz.fuzzing) {
fuzz_kex_fakealgos();
}
#endif
/* reserved for future extensions */
buf_getint(ses.payload);

View File

@@ -62,47 +62,38 @@ out:
return ret;
}
#ifdef ENABLE_USER_ALGO_LIST
#if DROPBEAR_USER_ALGO_LIST
void
parse_ciphers_macs()
{
if (opts.cipher_list)
{
if (strcmp(opts.cipher_list, "help") == 0)
{
parse_ciphers_macs() {
int printed_help = 0;
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);
dropbear_log(LOG_INFO, "Available ciphers: %s", 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'");
printed_help = 1;
} else {
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)
{
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);
dropbear_log(LOG_INFO, "Available MACs: %s", macs);
m_free(macs);
dropbear_exit(".");
}
if (check_user_algos(opts.mac_list, sshhashes, "MAC") == 0)
{
dropbear_exit("No valid MACs specified for '-m'");
printed_help = 1;
} else {
if (check_user_algos(opts.mac_list, sshhashes, "MAC") == 0) {
dropbear_exit("No valid MACs specified for '-m'");
}
}
}
if (printed_help) {
dropbear_exit(".");
}
}
#endif

View File

@@ -43,18 +43,11 @@ static void read_session_identification(void);
struct sshsession ses; /* GLOBAL */
/* need to know if the session struct has been initialised, this way isn't the
* cleanest, but works OK */
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) {
time_t now;
#ifdef DEBUG_TRACE
#if DEBUG_TRACE
debug_start_net();
#endif
@@ -75,6 +68,16 @@ void common_session_init(int sock_in, int sock_out) {
/* Sets it to lowdelay */
update_channel_prio();
#if !DROPBEAR_SVR_MULTIUSER
/* A sanity check to prevent an accidental configuration option
leaving multiuser systems exposed */
errno = 0;
getuid();
if (errno != ENOSYS) {
dropbear_exit("Non-multiuser Dropbear requires a non-multiuser kernel");
}
#endif
now = monotonic_now();
ses.connect_time = now;
ses.last_packet_time_keepalive_recv = now;
@@ -82,14 +85,18 @@ void common_session_init(int sock_in, int sock_out) {
ses.last_packet_time_any_sent = 0;
ses.last_packet_time_keepalive_sent = 0;
#if DROPBEAR_FUZZ
if (!fuzz.fuzzing)
#endif
{
if (pipe(ses.signal_pipe) < 0) {
dropbear_exit("Signal pipe failed");
}
setnonblocking(ses.signal_pipe[0]);
setnonblocking(ses.signal_pipe[1]);
ses.maxfd = MAX(ses.maxfd, ses.signal_pipe[0]);
ses.maxfd = MAX(ses.maxfd, ses.signal_pipe[1]);
}
ses.writepayload = buf_new(TRANS_MAX_PAYLOAD_LEN);
ses.transseq = 0;
@@ -140,10 +147,14 @@ void common_session_init(int sock_in, int sock_out) {
ses.allowprivport = 0;
#if DROPBEAR_PLUGIN
ses.plugin_session = NULL;
#endif
TRACE(("leave session_init"))
}
void session_loop(void(*loophandler)()) {
void session_loop(void(*loophandler)(void)) {
fd_set readfd, writefd;
struct timeval timeout;
@@ -155,14 +166,19 @@ void session_loop(void(*loophandler)()) {
timeout.tv_sec = select_timeout();
timeout.tv_usec = 0;
FD_ZERO(&writefd);
FD_ZERO(&readfd);
DROPBEAR_FD_ZERO(&writefd);
DROPBEAR_FD_ZERO(&readfd);
dropbear_assert(ses.payload == NULL);
/* We get woken up when signal handlers write to this pipe.
SIGCHLD in svr-chansession is the only one currently. */
#if DROPBEAR_FUZZ
if (!fuzz.fuzzing)
#endif
{
FD_SET(ses.signal_pipe[0], &readfd);
ses.channel_signal_pending = 0;
}
/* set up for channels which can be read/written */
setchannelfds(&readfd, &writefd, writequeue_has_space);
@@ -190,7 +206,7 @@ void session_loop(void(*loophandler)()) {
val = select(ses.maxfd+1, &readfd, &writefd, NULL, &timeout);
if (exitflag) {
if (ses.exitflag) {
dropbear_exit("Terminated by signal");
}
@@ -203,13 +219,14 @@ void session_loop(void(*loophandler)()) {
* want to iterate over channels etc for reading, to handle
* server processes exiting etc.
* We don't want to read/write FDs. */
FD_ZERO(&writefd);
FD_ZERO(&readfd);
DROPBEAR_FD_ZERO(&writefd);
DROPBEAR_FD_ZERO(&readfd);
}
/* We'll just empty out the pipe if required. We don't do
any thing with the data, since the pipe's purpose is purely to
wake up the select() above. */
ses.channel_signal_pending = 0;
if (FD_ISSET(ses.signal_pipe[0], &readfd)) {
char x;
TRACE(("signal pipe set"))
@@ -244,6 +261,10 @@ void session_loop(void(*loophandler)()) {
handle_connect_fds(&writefd);
/* loop handler prior to channelio, in case the server loophandler closes
channels on process exit */
loophandler();
/* process pipes etc for the channels, ses.dataallowed == 0
* during rekeying ) */
channelio(&readfd, &writefd);
@@ -255,11 +276,6 @@ void session_loop(void(*loophandler)()) {
}
}
if (loophandler) {
loophandler();
}
} /* for(;;) */
/* Not reached */
@@ -280,8 +296,8 @@ void session_cleanup() {
TRACE(("enter session_cleanup"))
/* we can't cleanup if we don't know the session state */
if (!sessinitdone) {
TRACE(("leave session_cleanup: !sessinitdone"))
if (!ses.init_done) {
TRACE(("leave session_cleanup: !ses.init_done"))
return;
}
@@ -295,7 +311,7 @@ void session_cleanup() {
}
/* After these are freed most functions will fail */
#ifdef DROPBEAR_CLEANUP
#if DROPBEAR_CLEANUP
/* listeners call cleanup functions, this should occur before
other session state is freed. */
remove_all_listeners();
@@ -306,6 +322,16 @@ void session_cleanup() {
buf_free(dequeue(&ses.writequeue));
}
m_free(ses.newkeys);
#ifndef DISABLE_ZLIB
if (ses.keys->recv.zstream != NULL) {
if (inflateEnd(ses.keys->recv.zstream) == Z_STREAM_ERROR) {
dropbear_exit("Crypto error");
}
m_free(ses.keys->recv.zstream);
}
#endif
m_free(ses.remoteident);
m_free(ses.authstate.pw_dir);
m_free(ses.authstate.pw_name);
@@ -335,7 +361,7 @@ void session_cleanup() {
void send_session_identification() {
buffer *writebuf = buf_new(strlen(LOCAL_IDENT "\r\n") + 1);
buf_putbytes(writebuf, (const unsigned char *) LOCAL_IDENT "\r\n", strlen(LOCAL_IDENT "\r\n"));
writebuf_enqueue(writebuf, 0);
writebuf_enqueue(writebuf);
}
static void read_session_identification() {
@@ -344,8 +370,11 @@ static void read_session_identification() {
int len = 0;
char done = 0;
int i;
/* If they send more than 50 lines, something is wrong */
for (i = 0; i < 50; i++) {
/* Servers may send other lines of data before sending the
* version string, client must be able to process such lines.
* If they send more than 50 lines, something is wrong */
for (i = IS_DROPBEAR_CLIENT ? 50 : 1; i > 0; i--) {
len = ident_readln(ses.sock_in, linebuf, sizeof(linebuf));
if (len < 0 && errno != EINTR) {
@@ -361,7 +390,7 @@ static void read_session_identification() {
}
if (!done) {
TRACE(("err: %s for '%s'\n", strerror(errno), linebuf))
TRACE(("error reading remote ident: %s\n", strerror(errno)))
ses.remoteclosed();
} else {
/* linebuf is already null terminated */
@@ -395,7 +424,7 @@ static int ident_readln(int fd, char* buf, int count) {
return -1;
}
FD_ZERO(&fds);
DROPBEAR_FD_ZERO(&fds);
/* select since it's a non-blocking fd */
@@ -550,10 +579,12 @@ static void update_timeout(long limit, long now, long last_event, long * timeout
static long select_timeout() {
/* determine the minimum timeout that might be required, so
as to avoid waking when unneccessary */
long timeout = LONG_MAX;
long timeout = KEX_REKEY_TIMEOUT;
long now = monotonic_now();
update_timeout(KEX_REKEY_TIMEOUT, now, ses.kexstate.lastkextime, &timeout);
if (!ses.kexstate.sentkexinit) {
update_timeout(KEX_REKEY_TIMEOUT, now, ses.kexstate.lastkextime, &timeout);
}
if (ses.authstate.authdone != 1 && IS_DROPBEAR_SERVER) {
/* AUTH_TIMEOUT is only relevant before authdone */

View File

@@ -114,8 +114,8 @@ size_t strlcpy(char *dst, const char *src, size_t size) {
#endif /* HAVE_STRLCPY */
#ifndef HAVE_STRLCAT
/* taken from openbsd-compat for OpenSSH 3.6.1p1 */
/* "$OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $"
/* taken from openbsd-compat for OpenSSH 7.2p2 */
/* "$OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $"
*
* Appends src to string dst of size siz (unlike strncat, siz is the
* full size of dst, not space left). At most siz-1 characters
@@ -123,15 +123,12 @@ size_t strlcpy(char *dst, const char *src, size_t size) {
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
* If retval >= siz, truncation occurred.
*/
size_t
strlcat(dst, src, siz)
char *dst;
const char *src;
size_t siz;
size_t
strlcat(char *dst, const char *src, size_t siz)
{
register char *d = dst;
register const char *s = src;
register size_t n = siz;
char *d = dst;
const char *s = src;
size_t n = siz;
size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end */
@@ -177,7 +174,7 @@ int daemon(int nochdir, int noclose) {
if (!nochdir)
(void)chdir("/");
if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
if (!noclose && (fd = open(DROPBEAR_PATH_DEVNULL, O_RDWR, 0)) != -1) {
(void)dup2(fd, STDIN_FILENO);
(void)dup2(fd, STDOUT_FILENO);
(void)dup2(fd, STDERR_FILENO);

939
config.guess vendored

File diff suppressed because it is too large Load Diff

2752
config.sub vendored

File diff suppressed because it is too large Load Diff

View File

@@ -9,19 +9,119 @@ AC_PREREQ(2.59)
AC_INIT
AC_CONFIG_SRCDIR(buffer.c)
OLDCFLAGS=$CFLAGS
# Record which revision is being built
if test -s "`which hg`" && test -d "$srcdir/.hg"; then
hgrev=`hg id -i -R "$srcdir"`
AC_MSG_NOTICE([Source directory Mercurial base revision $hgrev])
fi
ORIGCFLAGS="$CFLAGS"
# Checks for programs.
AC_PROG_CC
AC_PROG_MAKE_SET
if test -z "$LD" ; then
LD=$CC
fi
AC_SUBST(LD)
if test -z "$OLDCFLAGS" && test "$GCC" = "yes"; then
AC_DEFUN(DB_TRYADDCFLAGS,
[{
OLDFLAGS="$CFLAGS"
TESTFLAGS="$1"
CFLAGS="$CFLAGS $TESTFLAGS"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
[AC_MSG_NOTICE([Not setting $TESTFLAGS]); CFLAGS="$OLDFLAGS" ]
)
}])
# set compile flags prior to other tests
if test -z "$ORIGCFLAGS" && test "$GCC" = "yes"; then
AC_MSG_NOTICE(No \$CFLAGS set... using "-Os -W -Wall" for GCC)
CFLAGS="-Os -W -Wall -Wno-pointer-sign"
CFLAGS="-Os -W -Wall"
fi
AC_MSG_NOTICE([Checking if compiler '$CC' supports -Wno-pointer-sign])
DB_TRYADDCFLAGS([-Wno-pointer-sign])
AC_MSG_NOTICE([Checking if compiler '$CC' supports -fno-strict-overflow])
DB_TRYADDCFLAGS([-fno-strict-overflow])
STATIC=0
AC_ARG_ENABLE(static,
[ --enable-static Build static binaries],
[
if test "x$enableval" = "xyes"; then
STATIC=1
AC_MSG_NOTICE(Static Build)
fi
], [])
AC_SUBST(STATIC)
hardenbuild=1
AC_ARG_ENABLE(harden,
[ --disable-harden Don't set hardened build flags],
[
if test "x$enableval" = "xno"; then
hardenbuild=0
AC_MSG_NOTICE(Disabling hardened build flags)
fi
], [])
if test "$hardenbuild" -eq 1; then
AC_MSG_NOTICE(Checking for available hardened build flags:)
# relocation flags don't make sense for static builds
if test "$STATIC" -ne 1; then
# pie
DB_TRYADDCFLAGS([-fPIE])
OLDLDFLAGS="$LDFLAGS"
TESTFLAGS="-Wl,-pie"
LDFLAGS="$LDFLAGS $TESTFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
[
LDFLAGS="$OLDLDFLAGS"
TESTFLAGS="-pie"
LDFLAGS="$LDFLAGS $TESTFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
[AC_MSG_NOTICE([Not setting $TESTFLAGS]); LDFLAGS="$OLDLDFLAGS" ]
)
]
)
# readonly elf relocation sections (relro)
OLDLDFLAGS="$LDFLAGS"
TESTFLAGS="-Wl,-z,now -Wl,-z,relro"
LDFLAGS="$LDFLAGS $TESTFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
[AC_MSG_NOTICE([Not setting $TESTFLAGS]); LDFLAGS="$OLDLDFLAGS" ]
)
fi # non-static
# stack protector. -strong is good but only in gcc 4.9 or later
OLDCFLAGS="$CFLAGS"
TESTFLAGS="-fstack-protector-strong"
CFLAGS="$CFLAGS $TESTFLAGS"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
[
CFLAGS="$OLDCFLAGS"
TESTFLAGS="-fstack-protector --param=ssp-buffer-size=4"
CFLAGS="$CFLAGS $TESTFLAGS"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
[AC_MSG_NOTICE([Not setting $TESTFLAGS]); CFLAGS="$OLDCFLAGS" ]
)
]
)
# FORTIFY_SOURCE
DB_TRYADDCFLAGS([-D_FORTIFY_SOURCE=2])
# Spectre v2 mitigations
DB_TRYADDCFLAGS([-mfunction-return=thunk])
DB_TRYADDCFLAGS([-mindirect-branch=thunk])
fi
# large file support is useful for scp
@@ -45,8 +145,8 @@ case "$host" in
sol2ver=`echo "$host"| sed -e 's/.*[[0-9]]\.//'`
if test "$sol2ver" -ge 8; then
AC_MSG_RESULT(yes)
AC_DEFINE(DISABLE_UTMP,,Disable utmp)
AC_DEFINE(DISABLE_WTMP,,Disable wtmp)
AC_DEFINE(DISABLE_UTMP,1,Disable utmp)
AC_DEFINE(DISABLE_WTMP,1,Disable wtmp)
else
AC_MSG_RESULT(no)
fi
@@ -55,18 +155,18 @@ case "$host" in
;;
*-*-aix*)
AC_DEFINE(AIX,,Using AIX)
AC_DEFINE(AIX,1,Using AIX)
# OpenSSH thinks it's broken. If it isn't, let me know.
AC_DEFINE(BROKEN_GETADDRINFO,,Broken getaddrinfo)
AC_DEFINE(BROKEN_GETADDRINFO,1,Broken getaddrinfo)
;;
*-*-hpux*)
LIBS="$LIBS -lsec"
# It's probably broken.
AC_DEFINE(BROKEN_GETADDRINFO,,Broken getaddrinfo)
AC_DEFINE(BROKEN_GETADDRINFO,1,Broken getaddrinfo)
;;
*-dec-osf*)
AC_DEFINE(BROKEN_GETADDRINFO,,Broken getaddrinfo)
AC_DEFINE(BROKEN_GETADDRINFO,1,Broken getaddrinfo)
;;
esac
@@ -80,7 +180,7 @@ AC_CHECK_DECL(__UCLIBC__,
[
no_loginfunc_check=1
AC_MSG_NOTICE([Using uClibc - login() and logout() probably don't work, so we won't use them.])
],,,)
],,)
dnl We test for crypt() specially. On Linux (and others?) it resides in libcrypt
dnl but we don't want link all binaries to -lcrypt, just dropbear server.
@@ -118,7 +218,7 @@ AC_ARG_ENABLE(zlib,
[ --disable-zlib Don't include zlib support],
[
if test "x$enableval" = "xno"; then
AC_DEFINE(DISABLE_ZLIB,, Use zlib)
AC_DEFINE(DISABLE_ZLIB,1,Use zlib)
AC_MSG_NOTICE(Disabling zlib)
else
AC_CHECK_LIB(z, deflate, , AC_MSG_ERROR([*** zlib missing - install first or check config.log ***]))
@@ -152,20 +252,20 @@ AC_ARG_WITH(pam,
AC_ARG_ENABLE(pam,
[ --enable-pam Try to include PAM support],
[ --enable-pam Try to include PAM support],
[
if test "x$enableval" = "xyes"; then
AC_CHECK_LIB(pam, pam_authenticate, , AC_MSG_ERROR([*** PAM missing - install first or check config.log ***]))
AC_MSG_NOTICE(Enabling PAM)
AC_CHECK_FUNCS(pam_fail_delay)
else
AC_DEFINE(DISABLE_PAM,, Use PAM)
AC_DEFINE(DISABLE_PAM,1,Use PAM)
AC_MSG_NOTICE(Disabling PAM)
fi
],
[
# disable it by default
AC_DEFINE(DISABLE_PAM,, Use PAM)
AC_DEFINE(DISABLE_PAM,1,Use PAM)
AC_MSG_NOTICE(Disabling PAM)
]
)
@@ -177,21 +277,26 @@ AC_ARG_ENABLE(openpty,
AC_MSG_NOTICE(Not using openpty)
else
AC_MSG_NOTICE(Using openpty if available)
AC_SEARCH_LIBS(openpty, util, [AC_DEFINE(HAVE_OPENPTY,,Have openpty() function)])
AC_SEARCH_LIBS(openpty, util, [dropbear_cv_func_have_openpty=yes])
fi
],
[
AC_MSG_NOTICE(Using openpty if available)
AC_SEARCH_LIBS(openpty, util, [AC_DEFINE(HAVE_OPENPTY)])
AC_SEARCH_LIBS(openpty, util, [dropbear_cv_func_have_openpty=yes])
]
)
if test "x$dropbear_cv_func_have_openpty" = "xyes"; then
AC_DEFINE(HAVE_OPENPTY,,Have openpty() function)
no_ptc_check=yes
no_ptmx_check=yes
fi
AC_ARG_ENABLE(syslog,
[ --disable-syslog Don't include syslog support],
[
if test "x$enableval" = "xno"; then
AC_DEFINE(DISABLE_SYSLOG,, Using syslog)
AC_DEFINE(DISABLE_SYSLOG,1,Using syslog)
AC_MSG_NOTICE(Disabling syslog)
else
AC_MSG_NOTICE(Enabling syslog)
@@ -217,12 +322,56 @@ AC_ARG_ENABLE(shadow,
AC_MSG_NOTICE(Using shadow passwords if available)
]
)
AC_ARG_ENABLE(plugin,
[ --enable-plugin Enable support for External Public Key Authentication plug-in],
[
AC_DEFINE(DROPBEAR_PLUGIN, 1, External Public Key Authentication)
AC_MSG_NOTICE(Enabling support for External Public Key Authentication)
DROPBEAR_PLUGIN=1
],
[
AC_DEFINE(DROPBEAR_PLUGIN, 0, External Public Key Authentication)
DROPBEAR_PLUGIN=0
]
)
AC_SUBST(DROPBEAR_PLUGIN)
AC_ARG_ENABLE(fuzz,
[ --enable-fuzz Build fuzzing. Not recommended for deployment.],
[
if test "x$enableval" = "xyes"; then
AC_DEFINE(DROPBEAR_FUZZ, 1, Fuzzing)
AC_MSG_NOTICE(Enabling fuzzing)
DROPBEAR_FUZZ=1
# libfuzzer needs linking with c++ libraries
AC_PROG_CXX
else
AC_DEFINE(DROPBEAR_FUZZ, 0, Fuzzing)
AC_MSG_NOTICE(Disabling fuzzing)
DROPBEAR_FUZZ=0
fi
],
[
AC_DEFINE(DROPBEAR_FUZZ, 0, Fuzzing)
AC_MSG_NOTICE(Disabling fuzzing)
DROPBEAR_FUZZ=0
]
)
AC_SUBST(DROPBEAR_FUZZ)
AC_SUBST(CXX)
# 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 sys/uio.h])
AC_CHECK_HEADERS([netinet/in.h netinet/tcp.h \
crypt.h \
pty.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 linux/pkt_sched.h \
sys/random.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
@@ -295,7 +444,7 @@ AC_CACHE_CHECK([for struct sockaddr_in6], ac_cv_have_struct_sockaddr_in6, [
)
])
if test "x$ac_cv_have_struct_sockaddr_in6" = "xyes" ; then
AC_DEFINE(HAVE_STRUCT_SOCKADDR_IN6,,Have struct sockaddr_in6)
AC_DEFINE(HAVE_STRUCT_SOCKADDR_IN6,1,Have struct sockaddr_in6)
fi
AC_CACHE_CHECK([for struct in6_addr], ac_cv_have_struct_in6_addr, [
@@ -309,7 +458,7 @@ AC_CACHE_CHECK([for struct in6_addr], ac_cv_have_struct_in6_addr, [
)
])
if test "x$ac_cv_have_struct_in6_addr" = "xyes" ; then
AC_DEFINE(HAVE_STRUCT_IN6_ADDR,,Have struct in6_addr)
AC_DEFINE(HAVE_STRUCT_IN6_ADDR,1,Have struct in6_addr)
fi
AC_CACHE_CHECK([for struct addrinfo], ac_cv_have_struct_addrinfo, [
@@ -324,7 +473,7 @@ AC_CACHE_CHECK([for struct addrinfo], ac_cv_have_struct_addrinfo, [
)
])
if test "x$ac_cv_have_struct_addrinfo" = "xyes" ; then
AC_DEFINE(HAVE_STRUCT_ADDRINFO,,Have struct addrinfo)
AC_DEFINE(HAVE_STRUCT_ADDRINFO,1,Have struct addrinfo)
fi
@@ -371,38 +520,41 @@ AC_CHECK_FUNCS(endutxent getutxent getutxid getutxline pututxline )
AC_CHECK_FUNCS(setutxent utmpxname)
AC_CHECK_FUNCS(logout updwtmp logwtmp)
# POSIX monotonic time
AC_CHECK_FUNCS(clock_gettime)
# OS X monotonic time
AC_CHECK_HEADERS([mach/mach_time.h])
AC_CHECK_FUNCS(mach_absolute_time)
AC_CHECK_FUNCS(explicit_bzero memset_s)
AC_CHECK_FUNCS(explicit_bzero memset_s getrandom)
AC_ARG_ENABLE(bundled-libtom,
[ --enable-bundled-libtom Force using bundled libtomcrypt/libtommath even if a system version exists.
--disable-bundled-libtom Force using system libtomcrypt/libtommath, fail if it does not exist.
Default is to use system if available, otherwise bundled.],
Default is to use system if available, otherwise bundled.
Dropbear requires system libtommath >= 1.2.0 and libtomcrypt >= 1.18.0],
[
if test "x$enableval" = "xyes"; then
BUNDLED_LIBTOM=1
AC_MSG_NOTICE(Forcing bundled libtom*)
else
BUNDLED_LIBTOM=0
AC_CHECK_LIB(tommath, mp_exptmod, LIBTOM_LIBS="$LIBTOM_LIBS -ltommath",
[AC_MSG_ERROR([Missing system libtommath and --disable-bundled-libtom was specified])] )
AC_CHECK_LIB(tomcrypt, register_cipher, LIBTOM_LIBS="$LIBTOM_LIBS -ltomcrypt",
[AC_MSG_ERROR([Missing system libtomcrypt and --disable-bundled-libtom was specified])] )
AC_CHECK_LIB(tommath, mp_to_ubin, LIBTOM_LIBS="-ltommath $LIBTOM_LIBS",
[AC_MSG_ERROR([Missing/old system libtommath and --disable-bundled-libtom was specified])] )
AC_CHECK_LIB(tomcrypt, poly1305_init, LIBTOM_LIBS="-ltomcrypt $LIBTOM_LIBS",
[AC_MSG_ERROR([Missing/old system libtomcrypt and --disable-bundled-libtom was specified])] )
fi
],
[
BUNDLED_LIBTOM=0
AC_CHECK_LIB(tommath, mp_exptmod, LIBTOM_LIBS="$LIBTOM_LIBS -ltommath", BUNDLED_LIBTOM=1)
AC_CHECK_LIB(tomcrypt, register_cipher, LIBTOM_LIBS="$LIBTOM_LIBS -ltomcrypt", BUNDLED_LIBTOM=1)
AC_CHECK_LIB(tommath, mp_to_ubin, LIBTOM_LIBS="-ltommath $LIBTOM_LIBS", BUNDLED_LIBTOM=1)
AC_CHECK_LIB(tomcrypt, poly1305_init, LIBTOM_LIBS="-ltomcrypt $LIBTOM_LIBS", BUNDLED_LIBTOM=1)
]
)
if test $BUNDLED_LIBTOM = 1 ; then
AC_DEFINE(BUNDLED_LIBTOM,,Use bundled libtom)
AC_DEFINE(BUNDLED_LIBTOM,1,Use bundled libtom)
fi
AC_SUBST(LIBTOM_LIBS)
@@ -413,36 +565,64 @@ dnl Added from OpenSSH 3.6.1p2's configure.ac
dnl allow user to disable some login recording features
AC_ARG_ENABLE(lastlog,
[ --disable-lastlog Disable use of lastlog even if detected [no]],
[ AC_DEFINE(DISABLE_LASTLOG,,Disable use of lastlog()) ]
[
if test "x$enableval" = "xno" ; then
AC_DEFINE(DISABLE_LASTLOG,1,Disable use of lastlog())
fi
]
)
AC_ARG_ENABLE(utmp,
[ --disable-utmp Disable use of utmp even if detected [no]],
[ AC_DEFINE(DISABLE_UTMP,,Disable use of utmp) ]
[
if test "x$enableval" = "xno" ; then
AC_DEFINE(DISABLE_UTMP,1,Disable use of utmp)
fi
]
)
AC_ARG_ENABLE(utmpx,
[ --disable-utmpx Disable use of utmpx even if detected [no]],
[ AC_DEFINE(DISABLE_UTMPX,,Disable use of utmpx) ]
[
if test "x$enableval" = "xno" ; then
AC_DEFINE(DISABLE_UTMPX,1,Disable use of utmpx)
fi
]
)
AC_ARG_ENABLE(wtmp,
[ --disable-wtmp Disable use of wtmp even if detected [no]],
[ AC_DEFINE(DISABLE_WTMP,,Disable use of wtmp) ]
[
if test "x$enableval" = "xno" ; then
AC_DEFINE(DISABLE_WTMP,1,Disable use of wtmp)
fi
]
)
AC_ARG_ENABLE(wtmpx,
[ --disable-wtmpx Disable use of wtmpx even if detected [no]],
[ AC_DEFINE(DISABLE_WTMPX,,Disable use of wtmpx) ]
[
if test "x$enableval" = "xno" ; then
AC_DEFINE(DISABLE_WTMPX,1,Disable use of wtmpx)
fi
]
)
AC_ARG_ENABLE(loginfunc,
[ --disable-loginfunc Disable use of login() etc. [no]],
[ no_loginfunc_check=1
AC_MSG_NOTICE(Not using login() etc) ]
AC_MSG_NOTICE([Not using login() etc]) ]
)
AC_ARG_ENABLE(pututline,
[ --disable-pututline Disable use of pututline() etc. ([uw]tmp) [no]],
[ AC_DEFINE(DISABLE_PUTUTLINE,,Disable use of pututline()) ]
[
if test "x$enableval" = "xno" ; then
AC_DEFINE(DISABLE_PUTUTLINE,1,Disable use of pututline())
fi
]
)
AC_ARG_ENABLE(pututxline,
[ --disable-pututxline Disable use of pututxline() etc. ([uw]tmpx) [no]],
[ AC_DEFINE(DISABLE_PUTUTXLINE,,Disable use of pututxline()) ]
[
if test "x$enableval" = "xno" ; then
AC_DEFINE(DISABLE_PUTUTXLINE,1,Disable use of pututxline())
fi
]
)
AC_ARG_WITH(lastlog,
[ --with-lastlog=FILE|DIR specify lastlog location [common locations]],
@@ -457,7 +637,7 @@ AC_ARG_WITH(lastlog,
if test -z "$no_loginfunc_check"; then
dnl Checks for libutil functions (login(), logout() etc, not openpty() )
AC_SEARCH_LIBS(login, util bsd, [AC_DEFINE(HAVE_LOGIN,,Have login() function)])
AC_SEARCH_LIBS(login, util bsd, [AC_DEFINE(HAVE_LOGIN,1,[Have login() function])])
AC_CHECK_FUNCS(logout updwtmp logwtmp)
fi
@@ -645,7 +825,9 @@ fi
AC_PROG_GCC_TRADITIONAL
AC_FUNC_MEMCMP
AC_FUNC_SELECT_ARGTYPES
AC_CHECK_FUNCS([dup2 getpass getspnam getusershell memset putenv select socket strdup clearenv strlcpy strlcat daemon basename _getpty getaddrinfo freeaddrinfo getnameinfo fork writev])
AC_CHECK_FUNCS([getpass getspnam getusershell putenv])
AC_CHECK_FUNCS([clearenv strlcpy strlcat daemon basename _getpty getaddrinfo ])
AC_CHECK_FUNCS([freeaddrinfo getnameinfo fork writev getgrouplist])
AC_SEARCH_LIBS(basename, gen, AC_DEFINE(HAVE_BASENAME))
@@ -653,7 +835,7 @@ AC_SEARCH_LIBS(basename, gen, AC_DEFINE(HAVE_BASENAME))
if test -z "$no_ptmx_check" ; then
if test x"$cross_compiling" = x"no" ; then
if test -e /dev/ptmx ; then
AC_DEFINE(USE_DEV_PTMX,,Use /dev/ptmx)
AC_DEFINE(USE_DEV_PTMX,1,Use /dev/ptmx)
fi
else
AC_MSG_NOTICE([Not checking for /dev/ptmx, we're cross-compiling])
@@ -663,7 +845,7 @@ fi
if test -z "$no_ptc_check" ; then
if test x"$cross_compiling" = x"no" ; then
if test -e /dev/ptc ; then
AC_DEFINE(HAVE_DEV_PTS_AND_PTC,,Use /dev/ptc & /dev/pts)
AC_DEFINE(HAVE_DEV_PTS_AND_PTC,1,Use /dev/ptc & /dev/pts)
fi
else
AC_MSG_NOTICE([Not checking for /dev/ptc & /dev/pts since we're cross-compiling])
@@ -672,60 +854,11 @@ fi
AC_EXEEXT
# XXX there must be a nicer way to do this
if test $BUNDLED_LIBTOM = 1 ; then
AS_MKDIR_P(libtomcrypt/src/ciphers/aes)
AS_MKDIR_P(libtomcrypt/src/ciphers/safer)
AS_MKDIR_P(libtomcrypt/src/ciphers/twofish)
AS_MKDIR_P(libtomcrypt/src/encauth/ccm)
AS_MKDIR_P(libtomcrypt/src/encauth/eax)
AS_MKDIR_P(libtomcrypt/src/encauth/gcm)
AS_MKDIR_P(libtomcrypt/src/encauth/ocb)
AS_MKDIR_P(libtomcrypt/src/hashes)
AS_MKDIR_P(libtomcrypt/src/hashes/chc)
AS_MKDIR_P(libtomcrypt/src/hashes/helper)
AS_MKDIR_P(libtomcrypt/src/hashes/sha2)
AS_MKDIR_P(libtomcrypt/src/hashes/whirl)
AS_MKDIR_P(libtomcrypt/src/mac/hmac)
AS_MKDIR_P(libtomcrypt/src/mac/omac)
AS_MKDIR_P(libtomcrypt/src/mac/pelican)
AS_MKDIR_P(libtomcrypt/src/mac/pmac)
AS_MKDIR_P(libtomcrypt/src/mac/f9)
AS_MKDIR_P(libtomcrypt/src/mac/xcbc)
AS_MKDIR_P(libtomcrypt/src/math/fp)
AS_MKDIR_P(libtomcrypt/src/misc/base64)
AS_MKDIR_P(libtomcrypt/src/misc/crypt)
AS_MKDIR_P(libtomcrypt/src/misc/mpi)
AS_MKDIR_P(libtomcrypt/src/misc/pkcs5)
AS_MKDIR_P(libtomcrypt/src/modes/cbc)
AS_MKDIR_P(libtomcrypt/src/modes/cfb)
AS_MKDIR_P(libtomcrypt/src/modes/ctr)
AS_MKDIR_P(libtomcrypt/src/modes/ecb)
AS_MKDIR_P(libtomcrypt/src/modes/ofb)
AS_MKDIR_P(libtomcrypt/src/modes/f8)
AS_MKDIR_P(libtomcrypt/src/modes/lrw)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/bit)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/boolean)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/choice)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/ia5)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/integer)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/object_identifier)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/octet)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/printable_string)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/sequence)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/set)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/short_integer)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/utctime)
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/utf8)
AS_MKDIR_P(libtomcrypt/src/pk/dh)
AS_MKDIR_P(libtomcrypt/src/pk/dsa)
AS_MKDIR_P(libtomcrypt/src/pk/ecc)
AS_MKDIR_P(libtomcrypt/src/pk/katja)
AS_MKDIR_P(libtomcrypt/src/pk/pkcs1)
AS_MKDIR_P(libtomcrypt/src/pk/rsa)
AS_MKDIR_P(libtomcrypt/src/prngs)
(cd $srcdir; find libtomcrypt -type d) | xargs mkdir -pv
LIBTOM_FILES="libtomcrypt/Makefile libtommath/Makefile"
fi
AC_CONFIG_HEADER(config.h)
AC_CONFIG_FILES(Makefile $LIBTOM_FILES)
AC_OUTPUT
@@ -749,4 +882,4 @@ AC_MSG_NOTICE([crypt() not available, dropbear server will not have password aut
fi
AC_MSG_NOTICE()
AC_MSG_NOTICE([Now edit options.h to choose features.])
AC_MSG_NOTICE([Now edit localoptions.h to choose features.])

View File

@@ -4,7 +4,7 @@
#include "ltc_prng.h"
#include "ecc.h"
#ifdef DROPBEAR_LTC_PRNG
#if DROPBEAR_LTC_PRNG
int dropbear_ltc_prng = -1;
#endif
@@ -14,16 +14,16 @@
void crypto_init() {
const struct ltc_cipher_descriptor *regciphers[] = {
#ifdef DROPBEAR_AES
#if DROPBEAR_AES
&aes_desc,
#endif
#ifdef DROPBEAR_BLOWFISH
#if DROPBEAR_BLOWFISH
&blowfish_desc,
#endif
#ifdef DROPBEAR_TWOFISH
#if DROPBEAR_TWOFISH
&twofish_desc,
#endif
#ifdef DROPBEAR_3DES
#if DROPBEAR_3DES
&des3_desc,
#endif
NULL
@@ -32,16 +32,16 @@ void crypto_init() {
const struct ltc_hash_descriptor *reghashes[] = {
/* we need sha1 for hostkey stuff regardless */
&sha1_desc,
#ifdef DROPBEAR_MD5_HMAC
#if DROPBEAR_MD5_HMAC
&md5_desc,
#endif
#ifdef DROPBEAR_SHA256
#if DROPBEAR_SHA256
&sha256_desc,
#endif
#ifdef DROPBEAR_SHA384
#if DROPBEAR_SHA384
&sha384_desc,
#endif
#ifdef DROPBEAR_SHA512
#if DROPBEAR_SHA512
&sha512_desc,
#endif
NULL
@@ -60,14 +60,14 @@ void crypto_init() {
}
}
#ifdef DROPBEAR_LTC_PRNG
#if DROPBEAR_LTC_PRNG
dropbear_ltc_prng = register_prng(&dropbear_prng_desc);
if (dropbear_ltc_prng == -1) {
dropbear_exit("Error registering crypto");
}
#endif
#ifdef DROPBEAR_ECC
#if DROPBEAR_ECC
ltc_mp = ltm_desc;
dropbear_ecc_fill_dp();
#endif

View File

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

497
curve25519.c Normal file
View File

@@ -0,0 +1,497 @@
/*
* Dropbear - a SSH2 server
*
* Copyright (c) 2002,2003 Matt Johnston
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#include "includes.h"
#include "dbrandom.h"
#include "curve25519.h"
#if DROPBEAR_CURVE25519 || DROPBEAR_ED25519
/* Modified TweetNaCl version 20140427, a self-contained public-domain C library.
* https://tweetnacl.cr.yp.to/ */
#define FOR(i,n) for (i = 0;i < n;++i)
#define sv static void
typedef unsigned char u8;
typedef unsigned long u32;
typedef unsigned long long u64;
typedef long long i64;
typedef i64 gf[16];
#if DROPBEAR_CURVE25519
static const gf
_121665 = {0xDB41,1};
#endif /* DROPBEAR_CURVE25519 */
#if DROPBEAR_ED25519
static const gf
gf0,
gf1 = {1},
D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406},
X = {0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169},
Y = {0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666};
#if DROPBEAR_SIGNKEY_VERIFY
static const gf
D = {0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203},
I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83};
#endif /* DROPBEAR_SIGNKEY_VERIFY */
#endif /* DROPBEAR_ED25519 */
#if DROPBEAR_ED25519
#if DROPBEAR_SIGNKEY_VERIFY
static int vn(const u8 *x,const u8 *y,u32 n)
{
u32 i,d = 0;
FOR(i,n) d |= x[i]^y[i];
return (1 & ((d - 1) >> 8)) - 1;
}
static int crypto_verify_32(const u8 *x,const u8 *y)
{
return vn(x,y,32);
}
#endif /* DROPBEAR_SIGNKEY_VERIFY */
sv set25519(gf r, const gf a)
{
int i;
FOR(i,16) r[i]=a[i];
}
#endif /* DROPBEAR_ED25519 */
sv car25519(gf o)
{
int i;
i64 c;
FOR(i,16) {
o[i]+=(1LL<<16);
c=o[i]>>16;
o[(i+1)*(i<15)]+=c-1+37*(c-1)*(i==15);
o[i]-=c<<16;
}
}
sv sel25519(gf p,gf q,int b)
{
i64 t,i,c=~(b-1);
FOR(i,16) {
t= c&(p[i]^q[i]);
p[i]^=t;
q[i]^=t;
}
}
sv pack25519(u8 *o,const gf n)
{
int i,j,b;
gf m,t;
FOR(i,16) t[i]=n[i];
car25519(t);
car25519(t);
car25519(t);
FOR(j,2) {
m[0]=t[0]-0xffed;
for(i=1;i<15;i++) {
m[i]=t[i]-0xffff-((m[i-1]>>16)&1);
m[i-1]&=0xffff;
}
m[15]=t[15]-0x7fff-((m[14]>>16)&1);
b=(m[15]>>16)&1;
m[14]&=0xffff;
sel25519(t,m,1-b);
}
FOR(i,16) {
o[2*i]=t[i]&0xff;
o[2*i+1]=t[i]>>8;
}
}
#if DROPBEAR_ED25519
#if DROPBEAR_SIGNKEY_VERIFY
static int neq25519(const gf a, const gf b)
{
u8 c[32],d[32];
pack25519(c,a);
pack25519(d,b);
return crypto_verify_32(c,d);
}
#endif /* DROPBEAR_SIGNKEY_VERIFY */
static u8 par25519(const gf a)
{
u8 d[32];
pack25519(d,a);
return d[0]&1;
}
#endif /* DROPBEAR_ED25519 */
sv unpack25519(gf o, const u8 *n)
{
int i;
FOR(i,16) o[i]=n[2*i]+((i64)n[2*i+1]<<8);
o[15]&=0x7fff;
}
sv A(gf o,const gf a,const gf b)
{
int i;
FOR(i,16) o[i]=a[i]+b[i];
}
sv Z(gf o,const gf a,const gf b)
{
int i;
FOR(i,16) o[i]=a[i]-b[i];
}
sv M(gf o,const gf a,const gf b)
{
i64 i,j,t[31];
FOR(i,31) t[i]=0;
FOR(i,16) FOR(j,16) t[i+j]+=a[i]*b[j];
FOR(i,15) t[i]+=38*t[i+16];
FOR(i,16) o[i]=t[i];
car25519(o);
car25519(o);
}
sv S(gf o,const gf a)
{
M(o,a,a);
}
sv inv25519(gf o,const gf i)
{
gf c;
int a;
FOR(a,16) c[a]=i[a];
for(a=253;a>=0;a--) {
S(c,c);
if(a!=2&&a!=4) M(c,c,i);
}
FOR(a,16) o[a]=c[a];
}
#if DROPBEAR_ED25519 && DROPBEAR_SIGNKEY_VERIFY
sv pow2523(gf o,const gf i)
{
gf c;
int a;
FOR(a,16) c[a]=i[a];
for(a=250;a>=0;a--) {
S(c,c);
if(a!=1) M(c,c,i);
}
FOR(a,16) o[a]=c[a];
}
#endif /* DROPBEAR_ED25519 && DROPBEAR_SIGNKEY_VERIFY */
#if DROPBEAR_CURVE25519
void dropbear_curve25519_scalarmult(u8 *q,const u8 *n,const u8 *p)
{
u8 z[32];
i64 x[80],r,i;
gf a,b,c,d,e,f;
FOR(i,31) z[i]=n[i];
z[31]=(n[31]&127)|64;
z[0]&=248;
unpack25519(x,p);
FOR(i,16) {
b[i]=x[i];
d[i]=a[i]=c[i]=0;
}
a[0]=d[0]=1;
for(i=254;i>=0;--i) {
r=(z[i>>3]>>(i&7))&1;
sel25519(a,b,r);
sel25519(c,d,r);
A(e,a,c);
Z(a,a,c);
A(c,b,d);
Z(b,b,d);
S(d,e);
S(f,a);
M(a,c,a);
M(c,b,e);
A(e,a,c);
Z(a,a,c);
S(b,a);
Z(c,d,f);
M(a,c,_121665);
A(a,a,d);
M(c,c,a);
M(a,d,f);
M(d,b,x);
S(b,e);
sel25519(a,b,r);
sel25519(c,d,r);
}
FOR(i,16) {
x[i+16]=a[i];
x[i+32]=c[i];
x[i+48]=b[i];
x[i+64]=d[i];
}
inv25519(x+32,x+32);
M(x+16,x+16,x+32);
pack25519(q,x+16);
}
#endif /* DROPBEAR_CURVE25519 */
#if DROPBEAR_ED25519
static int crypto_hash(u8 *out,const u8 *m,u64 n)
{
hash_state hs;
sha512_init(&hs);
sha512_process(&hs, m, n);
return sha512_done(&hs, out);
}
sv add(gf p[4],gf q[4])
{
gf a,b,c,d,t,e,f,g,h;
Z(a, p[1], p[0]);
Z(t, q[1], q[0]);
M(a, a, t);
A(b, p[0], p[1]);
A(t, q[0], q[1]);
M(b, b, t);
M(c, p[3], q[3]);
M(c, c, D2);
M(d, p[2], q[2]);
A(d, d, d);
Z(e, b, a);
Z(f, d, c);
A(g, d, c);
A(h, b, a);
M(p[0], e, f);
M(p[1], h, g);
M(p[2], g, f);
M(p[3], e, h);
}
sv cswap(gf p[4],gf q[4],u8 b)
{
int i;
FOR(i,4)
sel25519(p[i],q[i],b);
}
sv pack(u8 *r,gf p[4])
{
gf tx, ty, zi;
inv25519(zi, p[2]);
M(tx, p[0], zi);
M(ty, p[1], zi);
pack25519(r, ty);
r[31] ^= par25519(tx) << 7;
}
sv scalarmult(gf p[4],gf q[4],const u8 *s)
{
int i;
set25519(p[0],gf0);
set25519(p[1],gf1);
set25519(p[2],gf1);
set25519(p[3],gf0);
for (i = 255;i >= 0;--i) {
u8 b = (s[i/8]>>(i&7))&1;
cswap(p,q,b);
add(q,p);
add(p,p);
cswap(p,q,b);
}
}
sv scalarbase(gf p[4],const u8 *s)
{
gf q[4];
set25519(q[0],X);
set25519(q[1],Y);
set25519(q[2],gf1);
M(q[3],X,Y);
scalarmult(p,q,s);
}
void dropbear_ed25519_make_key(u8 *pk,u8 *sk)
{
u8 d[64];
gf p[4];
genrandom(sk, 32);
crypto_hash(d, sk, 32);
d[0] &= 248;
d[31] &= 127;
d[31] |= 64;
scalarbase(p,d);
pack(pk,p);
}
static const u64 L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10};
sv modL(u8 *r,i64 x[64])
{
i64 carry,i,j;
for (i = 63;i >= 32;--i) {
carry = 0;
for (j = i - 32;j < i - 12;++j) {
x[j] += carry - 16 * x[i] * L[j - (i - 32)];
carry = (x[j] + 128) >> 8;
x[j] -= carry << 8;
}
x[j] += carry;
x[i] = 0;
}
carry = 0;
FOR(j,32) {
x[j] += carry - (x[31] >> 4) * L[j];
carry = x[j] >> 8;
x[j] &= 255;
}
FOR(j,32) x[j] -= carry * L[j];
FOR(i,32) {
x[i+1] += x[i] >> 8;
r[i] = x[i] & 255;
}
}
sv reduce(u8 *r)
{
i64 x[64],i;
FOR(i,64) x[i] = (u64) r[i];
FOR(i,64) r[i] = 0;
modL(r,x);
}
void dropbear_ed25519_sign(const u8 *m,u32 mlen,u8 *s,u32 *slen,const u8 *sk, const u8 *pk)
{
hash_state hs;
u8 d[64],h[64],r[64];
i64 x[64];
gf p[4];
u32 i,j;
crypto_hash(d, sk, 32);
d[0] &= 248;
d[31] &= 127;
d[31] |= 64;
*slen = 64;
sha512_init(&hs);
sha512_process(&hs,d + 32,32);
sha512_process(&hs,m,mlen);
sha512_done(&hs,r);
reduce(r);
scalarbase(p,r);
pack(s,p);
sha512_init(&hs);
sha512_process(&hs,s,32);
sha512_process(&hs,pk,32);
sha512_process(&hs,m,mlen);
sha512_done(&hs,h);
reduce(h);
FOR(i,64) x[i] = 0;
FOR(i,32) x[i] = (u64) r[i];
FOR(i,32) FOR(j,32) x[i+j] += h[i] * (u64) d[j];
modL(s + 32,x);
}
#if DROPBEAR_SIGNKEY_VERIFY
static int unpackneg(gf r[4],const u8 p[32])
{
gf t, chk, num, den, den2, den4, den6;
set25519(r[2],gf1);
unpack25519(r[1],p);
S(num,r[1]);
M(den,num,D);
Z(num,num,r[2]);
A(den,r[2],den);
S(den2,den);
S(den4,den2);
M(den6,den4,den2);
M(t,den6,num);
M(t,t,den);
pow2523(t,t);
M(t,t,num);
M(t,t,den);
M(t,t,den);
M(r[0],t,den);
S(chk,r[0]);
M(chk,chk,den);
if (neq25519(chk, num)) M(r[0],r[0],I);
S(chk,r[0]);
M(chk,chk,den);
if (neq25519(chk, num)) return -1;
if (par25519(r[0]) == (p[31]>>7)) Z(r[0],gf0,r[0]);
M(r[3],r[0],r[1]);
return 0;
}
int dropbear_ed25519_verify(const u8 *m,u32 mlen,const u8 *s,u32 slen,const u8 *pk)
{
hash_state hs;
u8 t[32],h[64];
gf p[4],q[4];
if (slen < 64) return -1;
if (unpackneg(q,pk)) return -1;
sha512_init(&hs);
sha512_process(&hs,s,32);
sha512_process(&hs,pk,32);
sha512_process(&hs,m,mlen);
sha512_done(&hs,h);
reduce(h);
scalarmult(p,q,h);
scalarbase(q,s + 32);
add(p,q);
pack(t,p);
if (crypto_verify_32(s, t))
return -1;
return 0;
}
#endif /* DROPBEAR_SIGNKEY_VERIFY */
#endif /* DROPBEAR_ED25519 */
#endif /* DROPBEAR_CURVE25519 || DROPBEAR_ED25519 */

37
curve25519.h Normal file
View File

@@ -0,0 +1,37 @@
/*
* Dropbear - a SSH2 server
*
* Copyright (c) 2002,2003 Matt Johnston
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#ifndef DROPBEAR_CURVE25519_H
#define DROPBEAR_CURVE25519_H
void dropbear_curve25519_scalarmult(unsigned char *q, const unsigned char *n, const unsigned char *p);
void dropbear_ed25519_make_key(unsigned char *pk, unsigned char *sk);
void dropbear_ed25519_sign(const unsigned char *m, unsigned long mlen,
unsigned char *s, unsigned long *slen,
const unsigned char *sk, const unsigned char *pk);
int dropbear_ed25519_verify(const unsigned char *m, unsigned long mlen,
const unsigned char *s, unsigned long slen,
const unsigned char *pk);
#endif /* DROPBEAR_CURVE25519_H */

View File

@@ -111,11 +111,22 @@ if 0 disables keepalives. If no response is received for 3 consecutive keepalive
.B \-I \fIidle_timeout
Disconnect the session if no traffic is transmitted or received for \fIidle_timeout\fR seconds.
.TP
.\" TODO: how to avoid a line break between these two -J arguments?
.B \-J \fIproxy_command
.TP
.B \-J \fI&fd
.br
Use the standard input/output of the program \fIproxy_command\fR rather than using
a normal TCP connection. A hostname should be still be provided, as this is used for
comparing saved hostkeys. This command will be executed as "exec proxy_command ..." with the
default shell.
The second form &fd will make dbclient use the numeric file descriptor as a socket. This
can be used for more complex tunnelling scenarios. Example usage with socat is
socat EXEC:'dbclient -J &38 ev',fdin=38,fdout=38 TCP4:host.example.com:22
.TP
.B \-B \fIendhost:endport
"Netcat-alike" mode, where Dropbear will connect to the given host, then create a
@@ -133,8 +144,8 @@ Can be used to give options in the format used by OpenSSH config file. This is
useful for specifying options for which there is no separate command-line flag.
For full details of the options listed below, and their possible values, see
ssh_config(5).
The following options have currently been implemented:
For now following options have been implemented:
.RS
.TP
.B ExitOnForwardFailure
@@ -147,6 +158,10 @@ Send dbclient log messages to syslog in addition to stderr.
.B \-s
The specified command will be requested as a subsystem, used for sftp. Dropbear doesn't implement sftp itself but the OpenSSH sftp client can be used eg \fIsftp -S dbclient user@host\fR
.TP
.B \-b \fI[address][:port]
Bind to a specific local address when connecting to the remote host. This can be used to choose from
multiple outgoing interfaces. Either address or port (or both) can be given.
.TP
.B \-V
Print the version

View File

@@ -9,16 +9,9 @@ void m_burn(void *data, unsigned int len) {
#elif defined(HAVE_EXPLICIT_BZERO)
explicit_bzero(data, len);
#else
/* Based on the method in David Wheeler's
* "Secure Programming for Linux and Unix HOWTO". May not be safe
* against link-time optimisation. */
volatile char *p = data;
if (data == NULL)
return;
while (len--) {
*p++ = 0x0;
}
/* This must be volatile to avoid compiler optimisation */
volatile void *p = data;
memset((void*)p, 0x0, len);
#endif
}

View File

@@ -3,7 +3,7 @@
/* This header defines some things that are also used by libtomcrypt/math.
We avoid including normal include.h since that can result in conflicting
definitinos - only include config.h */
definitions - only include config.h */
#include "config.h"
#ifdef __GNUC__

192
dbmalloc.c Normal file
View File

@@ -0,0 +1,192 @@
#include "dbmalloc.h"
#include "dbutil.h"
void * m_calloc(size_t nmemb, size_t size) {
if (SIZE_T_MAX / nmemb < size) {
dropbear_exit("m_calloc failed");
}
return m_malloc(nmemb*size);
}
void * m_strdup(const char * str) {
char* ret;
unsigned int len;
len = strlen(str);
ret = m_malloc(len+1);
if (ret == NULL) {
dropbear_exit("m_strdup failed");
}
memcpy(ret, str, len+1);
return ret;
}
#if !DROPBEAR_TRACKING_MALLOC
/* Simple wrappers around malloc etc */
void * m_malloc(size_t size) {
void* ret;
if (size == 0) {
dropbear_exit("m_malloc failed");
}
ret = calloc(1, size);
if (ret == NULL) {
dropbear_exit("m_malloc failed");
}
return ret;
}
void * m_realloc(void* ptr, size_t size) {
void *ret;
if (size == 0) {
dropbear_exit("m_realloc failed");
}
ret = realloc(ptr, size);
if (ret == NULL) {
dropbear_exit("m_realloc failed");
}
return ret;
}
#else
/* For fuzzing */
struct dbmalloc_header {
unsigned int epoch;
struct dbmalloc_header *prev;
struct dbmalloc_header *next;
};
static void put_alloc(struct dbmalloc_header *header);
static void remove_alloc(struct dbmalloc_header *header);
/* end of the linked list */
static struct dbmalloc_header* staple;
unsigned int current_epoch = 0;
void m_malloc_set_epoch(unsigned int epoch) {
current_epoch = epoch;
}
void m_malloc_free_epoch(unsigned int epoch, int dofree) {
struct dbmalloc_header* header;
struct dbmalloc_header* nextheader = NULL;
struct dbmalloc_header* oldstaple = staple;
staple = NULL;
/* free allocations from this epoch, create a new staple-anchored list from
the remainder */
for (header = oldstaple; header; header = nextheader)
{
nextheader = header->next;
if (header->epoch == epoch) {
if (dofree) {
free(header);
}
} else {
header->prev = NULL;
header->next = NULL;
put_alloc(header);
}
}
}
static void put_alloc(struct dbmalloc_header *header) {
assert(header->next == NULL);
assert(header->prev == NULL);
if (staple) {
staple->prev = header;
}
header->next = staple;
staple = header;
}
static void remove_alloc(struct dbmalloc_header *header) {
if (header->prev) {
header->prev->next = header->next;
}
if (header->next) {
header->next->prev = header->prev;
}
if (staple == header) {
staple = header->next;
}
header->prev = NULL;
header->next = NULL;
}
static struct dbmalloc_header* get_header(void* ptr) {
char* bptr = ptr;
return (struct dbmalloc_header*)&bptr[-sizeof(struct dbmalloc_header)];
}
void * m_malloc(size_t size) {
char* mem = NULL;
struct dbmalloc_header* header = NULL;
if (size == 0 || size > 1e9) {
dropbear_exit("m_malloc failed");
}
size = size + sizeof(struct dbmalloc_header);
mem = calloc(1, size);
if (mem == NULL) {
dropbear_exit("m_malloc failed");
}
header = (struct dbmalloc_header*)mem;
put_alloc(header);
header->epoch = current_epoch;
return &mem[sizeof(struct dbmalloc_header)];
}
void * m_realloc(void* ptr, size_t size) {
char* mem = NULL;
struct dbmalloc_header* header = NULL;
if (size == 0 || size > 1e9) {
dropbear_exit("m_realloc failed");
}
header = get_header(ptr);
remove_alloc(header);
size = size + sizeof(struct dbmalloc_header);
mem = realloc(header, size);
if (mem == NULL) {
dropbear_exit("m_realloc failed");
}
header = (struct dbmalloc_header*)mem;
put_alloc(header);
return &mem[sizeof(struct dbmalloc_header)];
}
void m_free_direct(void* ptr) {
struct dbmalloc_header* header = NULL;
if (!ptr) {
return;
}
header = get_header(ptr);
remove_alloc(header);
free(header);
}
#endif /* DROPBEAR_TRACKING_MALLOC */
void * m_realloc_ltm(void* ptr, size_t oldsize, size_t newsize) {
(void)oldsize;
return m_realloc(ptr, newsize);
}
void m_free_ltm(void *mem, size_t size) {
(void)size;
m_free_direct(mem);
}

27
dbmalloc.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef DBMALLOC_H_
#define DBMALLOC_H_
#include "stdint.h"
#include "stdlib.h"
#include "options.h"
void * m_malloc(size_t size);
void * m_calloc(size_t nmemb, size_t size);
void * m_strdup(const char * str);
void * m_realloc(void* ptr, size_t size);
#if DROPBEAR_TRACKING_MALLOC
void m_free_direct(void* ptr);
void m_malloc_set_epoch(unsigned int epoch);
void m_malloc_free_epoch(unsigned int epoch, int dofree);
#else
/* plain wrapper */
#define m_free_direct free
#endif
#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
#endif /* DBMALLOC_H_ */

View File

@@ -27,7 +27,7 @@
#include "dbutil.h"
#include "bignum.h"
#include "dbrandom.h"
#include "runopts.h"
/* this is used to generate unique output from the same hashpool */
static uint32_t counter = 0;
@@ -49,24 +49,19 @@ static int donerandinit = 0;
*
*/
/* Pass len=0 to hash an entire file */
/* Pass wantlen=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 wantlen, int prngd) {
int readfd = -1;
unsigned int readcount;
int ret = DROPBEAR_FAILURE;
#ifdef DROPBEAR_PRNGD_SOCKET
if (prngd)
{
if (prngd) {
#if DROPBEAR_USE_PRNGD
readfd = connect_unix(filename);
}
else
#endif
{
} else {
readfd = open(filename, O_RDONLY);
}
@@ -75,58 +70,31 @@ process_file(hash_state *hs, const char *filename,
}
readcount = 0;
while (len == 0 || readcount < len)
{
while (wantlen == 0 || readcount < wantlen) {
int readlen, wantread;
unsigned char readbuf[4096];
if (!already_blocked && !prngd)
{
int res;
struct timeval timeout;
fd_set read_fds;
timeout.tv_sec = 2;
timeout.tv_usec = 0;
FD_ZERO(&read_fds);
FD_SET(readfd, &read_fds);
res = select(readfd + 1, &read_fds, NULL, NULL, &timeout);
if (res == 0)
{
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;
}
}
if (len == 0)
{
if (wantlen == 0) {
wantread = sizeof(readbuf);
}
else
{
wantread = MIN(sizeof(readbuf), len-readcount);
} else {
wantread = MIN(sizeof(readbuf), wantlen-readcount);
}
#ifdef DROPBEAR_PRNGD_SOCKET
if (prngd)
{
#if DROPBEAR_USE_PRNGD
if (prngd) {
char egdcmd[2];
egdcmd[0] = 0x02; /* blocking read */
egdcmd[1] = (unsigned char)wantread;
if (write(readfd, egdcmd, 2) < 0)
{
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;
}
if (readlen == 0 && len == 0)
{
if (readlen == 0 && wantlen == 0) {
/* whole file was read as requested */
break;
}
@@ -141,10 +109,16 @@ out:
return ret;
}
void addrandom(unsigned char * buf, unsigned int len)
void addrandom(const unsigned char * buf, unsigned int len)
{
hash_state hs;
#if DROPBEAR_FUZZ
if (fuzz.fuzzing) {
return;
}
#endif
/* hash in the new seed data */
sha1_init(&hs);
/* existing state (zeroes on startup) */
@@ -157,7 +131,12 @@ void addrandom(unsigned char * buf, unsigned int len)
static void write_urandom()
{
#ifndef DROPBEAR_PRNGD_SOCKET
#if DROPBEAR_FUZZ
if (fuzz.fuzzing) {
return;
}
#endif
#if !DROPBEAR_USE_PRNGD
/* This is opportunistic, don't worry about failure */
unsigned char buf[INIT_SEED_SIZE];
FILE *f = fopen(DROPBEAR_URANDOM_DEV, "w");
@@ -170,6 +149,75 @@ static void write_urandom()
#endif
}
#if DROPBEAR_FUZZ
void fuzz_seed(void) {
hash_state hs;
sha1_init(&hs);
sha1_process(&hs, "fuzzfuzzfuzz", strlen("fuzzfuzzfuzz"));
sha1_done(&hs, hashpool);
counter = 0;
donerandinit = 1;
}
#endif
#ifdef HAVE_GETRANDOM
/* Reads entropy seed with getrandom().
* May block if the kernel isn't ready.
* Return DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
static int process_getrandom(hash_state *hs) {
char buf[INIT_SEED_SIZE];
ssize_t ret;
/* First try non-blocking so that we can warn about waiting */
ret = getrandom(buf, sizeof(buf), GRND_NONBLOCK);
if (ret == -1) {
if (errno == ENOSYS) {
/* Old kernel */
return DROPBEAR_FAILURE;
}
/* Other errors fall through to blocking getrandom() */
TRACE(("first getrandom() failed: %d %s", errno, strerror(errno)))
if (errno == EAGAIN) {
dropbear_log(LOG_WARNING, "Waiting for kernel randomness to be initialised...");
}
}
/* Wait blocking if needed. Loop in case we get EINTR */
while (ret != sizeof(buf)) {
ret = getrandom(buf, sizeof(buf), 0);
if (ret == sizeof(buf)) {
/* Success */
break;
}
if (ret == -1 && errno == EINTR) {
/* Try again. */
continue;
}
if (ret >= 0) {
TRACE(("Short read %zd from getrandom() shouldn't happen", ret))
/* Try again? */
continue;
}
/* Unexpected problem, fall back to /dev/urandom */
TRACE(("2nd getrandom() failed: %d %s", errno, strerror(errno)))
break;
}
if (ret == sizeof(buf)) {
/* Success, stir in the entropy */
sha1_process(hs, (void*)buf, sizeof(buf));
return DROPBEAR_SUCCESS;
}
return DROPBEAR_FAILURE;
}
#endif /* HAVE_GETRANDOM */
/* Initialise the prng from /dev/urandom or prngd. This function can
* be called multiple times */
void seedrandom() {
@@ -179,27 +227,45 @@ void seedrandom() {
pid_t pid;
struct timeval tv;
clock_t clockval;
int urandom_seeded = 0;
#if DROPBEAR_FUZZ
if (fuzz.fuzzing) {
return;
}
#endif
/* 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);
#ifdef HAVE_GETRANDOM
if (process_getrandom(&hs) == DROPBEAR_SUCCESS) {
urandom_seeded = 1;
}
#endif
if (!urandom_seeded) {
#if DROPBEAR_USE_PRNGD
if (process_file(&hs, DROPBEAR_PRNGD_SOCKET, INIT_SEED_SIZE, 1)
!= DROPBEAR_SUCCESS) {
dropbear_exit("Failure reading random device %s",
DROPBEAR_PRNGD_SOCKET);
urandom_seeded = 1;
}
#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);
urandom_seeded = 1;
}
#endif
} /* urandom_seeded */
/* A few other sources to fall back on.
* Add more here for other platforms */
#ifdef __linux__

View File

@@ -29,7 +29,7 @@
void seedrandom(void);
void genrandom(unsigned char* buf, unsigned int len);
void addrandom(unsigned char * buf, unsigned int len);
void addrandom(const unsigned char * buf, unsigned int len);
void gen_random_mpint(mp_int *max, mp_int *rand);
#endif /* DROPBEAR_RANDOM_H_ */

168
dbutil.c
View File

@@ -79,7 +79,7 @@ void (*_dropbear_exit)(int exitcode, const char* format, va_list param) ATTRIB_N
void (*_dropbear_log)(int priority, const char* format, va_list param)
= generic_dropbear_log;
#ifdef DEBUG_TRACE
#if DEBUG_TRACE
int debug_trace = 0;
#endif
@@ -120,6 +120,13 @@ static void generic_dropbear_exit(int exitcode, const char* format,
_dropbear_log(LOG_INFO, fmtbuf, param);
#if DROPBEAR_FUZZ
/* longjmp before cleaning up svr_opts */
if (fuzz.do_jmp) {
longjmp(fuzz.jmp, 1);
}
#endif
exit(exitcode);
}
@@ -149,7 +156,7 @@ void dropbear_log(int priority, const char* format, ...) {
}
#ifdef DEBUG_TRACE
#if DEBUG_TRACE
static double debug_start_time = -1;
@@ -214,7 +221,7 @@ void dropbear_trace2(const char* format, ...) {
#endif /* DEBUG_TRACE */
/* Connect to a given unix socket. The socket is blocking */
#ifdef ENABLE_CONNECT_UNIX
#if ENABLE_CONNECT_UNIX
int connect_unix(const char* path) {
struct sockaddr_un addr;
int fd = -1;
@@ -241,7 +248,7 @@ int connect_unix(const char* path) {
* it will be run after the child has fork()ed, and is passed exec_data.
* If ret_errfd == NULL then stderr will not be captured.
* ret_pid can be passed as NULL to discard the pid. */
int spawn_command(void(*exec_fn)(void *user_data), void *exec_data,
int spawn_command(void(*exec_fn)(const void *user_data), const void *exec_data,
int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid) {
int infds[2];
int outfds[2];
@@ -262,7 +269,7 @@ int spawn_command(void(*exec_fn)(void *user_data), void *exec_data,
return DROPBEAR_FAILURE;
}
#ifdef USE_VFORK
#if DROPBEAR_VFORK
pid = vfork();
#else
pid = fork();
@@ -371,7 +378,7 @@ void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell) {
execv(usershell, argv);
}
#ifdef DEBUG_TRACE
#if DEBUG_TRACE
void printhex(const char * label, const unsigned char * buf, int len) {
int i;
@@ -392,6 +399,7 @@ void printhex(const char * label, const unsigned char * buf, int len) {
void printmpint(const char *label, mp_int *mp) {
buffer *buf = buf_new(1000);
buf_putmpint(buf, mp);
fprintf(stderr, "%d bits ", mp_count_bits(mp));
printhex(label, buf->data, buf->len);
buf_free(buf);
@@ -465,7 +473,7 @@ out:
* authkeys file.
* Will return DROPBEAR_SUCCESS if data is read, or DROPBEAR_FAILURE on EOF.*/
/* Only used for ~/.ssh/known_hosts and ~/.ssh/authorized_keys */
#if defined(DROPBEAR_CLIENT) || defined(ENABLE_SVR_PUBKEY_AUTH)
#if DROPBEAR_CLIENT || DROPBEAR_SVR_PUBKEY_AUTH
int buf_getline(buffer * line, FILE * authfile) {
int c = EOF;
@@ -506,7 +514,7 @@ out:
void m_close(int fd) {
int val;
if (fd == -1) {
if (fd < 0) {
return;
}
@@ -520,57 +528,26 @@ void m_close(int fd) {
}
}
void * m_malloc(size_t size) {
void* ret;
if (size == 0) {
dropbear_exit("m_malloc failed");
}
ret = calloc(1, size);
if (ret == NULL) {
dropbear_exit("m_malloc failed");
}
return ret;
}
void * m_strdup(const char * str) {
char* ret;
ret = strdup(str);
if (ret == NULL) {
dropbear_exit("m_strdup failed");
}
return ret;
}
void * m_realloc(void* ptr, size_t size) {
void *ret;
if (size == 0) {
dropbear_exit("m_realloc failed");
}
ret = realloc(ptr, size);
if (ret == NULL) {
dropbear_exit("m_realloc failed");
}
return ret;
}
void setnonblocking(int fd) {
TRACE(("setnonblocking: %d", fd))
#if DROPBEAR_FUZZ
if (fuzz.fuzzing) {
return;
}
#endif
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
if (errno == ENODEV) {
/* Some devices (like /dev/null redirected in)
* can't be set to non-blocking */
TRACE(("ignoring ENODEV for setnonblocking"))
} else {
{
dropbear_exit("Couldn't set nonblocking");
}
}
}
TRACE(("leave setnonblocking"))
}
@@ -628,57 +605,84 @@ int constant_time_memcmp(const void* a, const void *b, size_t n)
return c;
}
#if defined(__linux__) && defined(SYS_clock_gettime)
/* CLOCK_MONOTONIC_COARSE was added in Linux 2.6.32 but took a while to
reach userspace include headers */
#ifndef CLOCK_MONOTONIC_COARSE
#define CLOCK_MONOTONIC_COARSE 6
/* higher-resolution monotonic timestamp, falls back to gettimeofday */
void gettime_wrapper(struct timespec *now) {
struct timeval tv;
#if DROPBEAR_FUZZ
if (fuzz.fuzzing) {
/* time stands still when fuzzing */
now->tv_sec = 5;
now->tv_nsec = 0;
}
#endif
static clockid_t get_linux_clock_source() {
struct timespec ts;
if (syscall(SYS_clock_gettime, CLOCK_MONOTONIC_COARSE, &ts) == 0) {
return CLOCK_MONOTONIC_COARSE;
}
if (syscall(SYS_clock_gettime, CLOCK_MONOTONIC, &ts) == 0) {
return CLOCK_MONOTONIC;
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
/* POSIX monotonic clock. Newer Linux, BSD, MacOSX >10.12 */
if (clock_gettime(CLOCK_MONOTONIC, now) == 0) {
return;
}
return -1;
}
#endif
#endif
time_t monotonic_now() {
#if defined(__linux__) && defined(SYS_clock_gettime)
static clockid_t clock_source = -2;
if (clock_source == -2) {
/* First run, find out which one works.
-1 will fall back to time() */
clock_source = get_linux_clock_source();
}
if (clock_source >= 0) {
struct timespec ts;
if (syscall(SYS_clock_gettime, clock_source, &ts) != 0) {
/* Intermittent clock failures should not happen */
dropbear_exit("Clock broke");
{
/* Old linux toolchain - kernel might support it but not the build headers */
/* Also glibc <2.17 requires -lrt which we neglect to add */
static int linux_monotonic_failed = 0;
if (!linux_monotonic_failed) {
/* CLOCK_MONOTONIC isn't in some headers */
int clock_source_monotonic = 1;
if (syscall(SYS_clock_gettime, clock_source_monotonic, now) == 0) {
return;
} else {
/* Don't try again */
linux_monotonic_failed = 1;
}
return ts.tv_sec;
}
#endif /* linux clock_gettime */
}
#endif /* linux fallback clock_gettime */
#if defined(HAVE_MACH_ABSOLUTE_TIME)
/* OS X, see https://developer.apple.com/library/mac/qa/qa1398/_index.html */
{
/* OS X pre 10.12, see https://developer.apple.com/library/mac/qa/qa1398/_index.html */
static mach_timebase_info_data_t timebase_info;
uint64_t scaled_time;
if (timebase_info.denom == 0) {
mach_timebase_info(&timebase_info);
}
return mach_absolute_time() * timebase_info.numer / timebase_info.denom
/ 1e9;
scaled_time = mach_absolute_time() * timebase_info.numer / timebase_info.denom;
now->tv_sec = scaled_time / 1000000000;
now->tv_nsec = scaled_time % 1000000000;
}
#endif /* osx mach_absolute_time */
/* Fallback for everything else - this will sometimes go backwards */
return time(NULL);
gettimeofday(&tv, NULL);
now->tv_sec = tv.tv_sec;
now->tv_nsec = 1000*tv.tv_usec;
}
/* second-resolution monotonic timestamp */
time_t monotonic_now() {
struct timespec ts;
gettime_wrapper(&ts);
return ts.tv_sec;
}
void fsync_parent_dir(const char* fn) {
#ifdef HAVE_LIBGEN_H
char *fn_dir = m_strdup(fn);
char *dir = dirname(fn_dir);
int dirfd = open(dir, O_RDONLY);
if (dirfd != -1) {
if (fsync(dirfd) != 0) {
TRACE(("fsync of directory %s failed: %s", dir, strerror(errno)))
}
m_close(dirfd);
} else {
TRACE(("error opening directory %s for fsync: %s", dir, strerror(errno)))
}
m_free(fn_dir);
#endif
}

View File

@@ -30,6 +30,7 @@
#include "buffer.h"
#include "queue.h"
#include "dbhelpers.h"
#include "dbmalloc.h"
#ifndef DISABLE_SYSLOG
void startsyslog(const char *ident);
@@ -45,7 +46,7 @@ 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
#if DEBUG_TRACE
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);
@@ -56,20 +57,16 @@ extern int debug_trace;
char * stripcontrol(const char * text);
int spawn_command(void(*exec_fn)(void *user_data), void *exec_data,
int spawn_command(void(*exec_fn)(const void *user_data), const void *exec_data,
int *writefd, int *readfd, int *errfd, pid_t *pid);
void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell);
#ifdef ENABLE_CONNECT_UNIX
#if ENABLE_CONNECT_UNIX
int connect_unix(const char* addr);
#endif
int buf_readfile(buffer* buf, const char* filename);
int buf_getline(buffer * line, FILE * authfile);
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) do {free(X); (X) = NULL;} while (0)
void setnonblocking(int fd);
void disallow_core(void);
int m_str_to_uint(const char* str, unsigned int *val);
@@ -86,7 +83,18 @@ int constant_time_memcmp(const void* a, const void *b, size_t n);
/* Returns a time in seconds that doesn't go backwards - does not correspond to
a real-world clock */
time_t monotonic_now(void);
/* Higher resolution clock_gettime(CLOCK_MONOTONIC) wrapper */
void gettime_wrapper(struct timespec *now);
char * expand_homedir_path(const char *inpath);
void fsync_parent_dir(const char* fn);
#if DROPBEAR_MSAN
/* FD_ZERO seems to leave some memory uninitialized. clear it to avoid false positives */
#define DROPBEAR_FD_ZERO(fds) do { memset((fds), 0x0, sizeof(fd_set)); FD_ZERO(fds); } while(0)
#else
#define DROPBEAR_FD_ZERO(fds) FD_ZERO(fds)
#endif
#endif /* DROPBEAR_DBUTIL_H_ */

36
debian/changelog vendored
View File

@@ -1,3 +1,39 @@
dropbear (2020.79-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Mon, 15 Jun 2020 22:51:57 +0800
dropbear (2019.78-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Wed, 27 Mar 2019 22:51:57 +0800
dropbear (2019.77-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Sat, 23 Mar 2019 22:51:57 +0800
dropbear (2018.76-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Tue, 27 Feb 2018 22:51:57 +0800
dropbear (2017.75-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Thu, 18 May 2017 22:51:57 +0800
dropbear (2016.74-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Thu, 21 Jul 2016 22:51:57 +0800
dropbear (2016.73-0.1) unstable; urgency=low
* New upstream release.

View File

@@ -1,4 +1,3 @@
README
TODO
debian/README.runit
debian/README.Debian.diet

23
debug.h
View File

@@ -33,27 +33,15 @@
* etc. Don't use this normally, it might cause problems */
/* #define DEBUG_VALGRIND */
/* Define this to compile in trace debugging printf()s.
* You'll need to run programs with "-v" to turn this on.
*
* 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*/
/* All functions writing to the cleartext payload buffer call
* CHECKCLEARTOWRITE() before writing. This is only really useful if you're
* attempting to track down a problem */
/*#define CHECKCLEARTOWRITE() assert(ses.writepayload->len == 0 && \
ses.writepayload->pos == 0)*/
#ifndef CHECKCLEARTOWRITE
#define CHECKCLEARTOWRITE()
/* Define this, compile with -pg and set GMON_OUT_PREFIX=gmon to get gmon
* output when Dropbear forks. This will allow it gprof to be used.
* It's useful to run dropbear -F, so you don't fork as much */
/* (This is Linux specific) */
/*#define DEBUG_FORKGPROF*/
#endif
/* A couple of flags, not usually useful, and mightn't do anything */
@@ -61,7 +49,8 @@
/*#define DEBUG_RSA*/
/* you don't need to touch this block */
#ifdef DEBUG_TRACE
#if DEBUG_TRACE
extern int debug_trace;
#define TRACE(X) dropbear_trace X;
#define TRACE2(X) dropbear_trace2 X;
#else /*DEBUG_TRACE*/
@@ -71,7 +60,9 @@
/* To debug with GDB it is easier to run with no forking of child processes.
You will need to pass "-F" as well. */
/* #define DEBUG_NOFORK */
#ifndef DEBUG_NOFORK
#define DEBUG_NOFORK 0
#endif
/* For testing as non-root on shadowed systems, include the crypt of a password

314
default_options.h Normal file
View File

@@ -0,0 +1,314 @@
#ifndef DROPBEAR_DEFAULT_OPTIONS_H_
#define DROPBEAR_DEFAULT_OPTIONS_H_
/*
> > > Read This < < <
default_options.h documents compile-time options, and provides default values.
Local customisation should be added to localoptions.h which is
used if it exists in the build directory. Options defined there will override
any options in this file.
Options can also be defined with -DDROPBEAR_XXX=[0,1] in Makefile CFLAGS
IMPORTANT: Some options will require "make clean" after changes */
#define DROPBEAR_DEFPORT "22"
/* Listen on all interfaces */
#define DROPBEAR_DEFADDRESS ""
/* Default hostkey paths - these can be specified on the command line */
#define DSS_PRIV_FILENAME "/etc/dropbear/dropbear_dss_host_key"
#define RSA_PRIV_FILENAME "/etc/dropbear/dropbear_rsa_host_key"
#define ECDSA_PRIV_FILENAME "/etc/dropbear/dropbear_ecdsa_host_key"
#define ED25519_PRIV_FILENAME "/etc/dropbear/dropbear_ed25519_host_key"
/* Set NON_INETD_MODE if you require daemon functionality (ie Dropbear listens
* on chosen ports and keeps accepting connections. This is the default.
*
* Set INETD_MODE if you want to be able to run Dropbear with inetd (or
* similar), where it will use stdin/stdout for connections, and each process
* lasts for a single connection. Dropbear should be invoked with the -i flag
* for inetd, and can only accept IPv4 connections.
*
* Both of these flags can be defined at once, don't compile without at least
* one of them. */
#define NON_INETD_MODE 1
#define INETD_MODE 1
/* Include verbose debug output, enabled with -v at runtime.
* This will add a reasonable amount to your executable size. */
#define DEBUG_TRACE 0
/* Set this if you want to use the DROPBEAR_SMALL_CODE option. This can save
* several kB in binary size however will make the symmetrical ciphers and hashes
* slower, perhaps by 50%. Recommended for small systems that aren't doing
* much traffic. */
#define DROPBEAR_SMALL_CODE 1
/* Enable X11 Forwarding - server only */
#define DROPBEAR_X11FWD 0
/* Enable TCP Fowarding */
/* 'Local' is "-L" style (client listening port forwarded via server)
* 'Remote' is "-R" style (server listening port forwarded via client) */
#define DROPBEAR_CLI_LOCALTCPFWD 1
#define DROPBEAR_CLI_REMOTETCPFWD 1
#define DROPBEAR_SVR_LOCALTCPFWD 1
#define DROPBEAR_SVR_REMOTETCPFWD 1
/* Enable Authentication Agent Forwarding */
#define DROPBEAR_SVR_AGENTFWD 1
#define DROPBEAR_CLI_AGENTFWD 1
/* Note: Both DROPBEAR_CLI_PROXYCMD and DROPBEAR_CLI_NETCAT must be set to
* allow multihop dbclient connections */
/* Allow using -J <proxycommand> to run the connection through a
pipe to a program, rather the normal TCP connection */
#define DROPBEAR_CLI_PROXYCMD 1
/* Enable "Netcat mode" option. This will forward standard input/output
* to a remote TCP-forwarded connection */
#define DROPBEAR_CLI_NETCAT 1
/* Whether to support "-c" and "-m" flags to choose ciphers/MACs at runtime */
#define DROPBEAR_USER_ALGO_LIST 1
/* Encryption - at least one required.
* AES128 should be enabled, some very old implementations might only
* support 3DES.
* Including both AES keysize variants (128 and 256) will result in
* a minimal size increase */
#define DROPBEAR_AES128 1
#define DROPBEAR_AES256 1
#define DROPBEAR_3DES 0
#define DROPBEAR_TWOFISH256 0
#define DROPBEAR_TWOFISH128 0
/* Enable Chacha20-Poly1305 authenticated encryption mode. This is
* generally faster than AES256 on CPU w/o dedicated AES instructions,
* having the same key size. Recommended.
* Compiling in will add ~5,5kB to binary size on x86-64 */
#define DROPBEAR_CHACHA20POLY1305 1
/* Enable "Counter Mode" for ciphers. Recommended. */
#define DROPBEAR_ENABLE_CTR_MODE 1
/* Enable CBC mode for ciphers. This has security issues though
may be required for compatibility with old implementations */
#define DROPBEAR_ENABLE_CBC_MODE 0
/* Enable "Galois/Counter Mode" for ciphers. This authenticated
* encryption mode is combination of CTR mode and GHASH. Recommended
* for security and forwards compatibility, but slower than CTR on
* CPU w/o dedicated AES/GHASH instructions.
* Compiling in will add ~6kB to binary size on x86-64 */
#define DROPBEAR_ENABLE_GCM_MODE 0
/* Message integrity. sha2-256 is recommended as a default,
sha1 for compatibility */
#define DROPBEAR_SHA1_HMAC 1
#define DROPBEAR_SHA2_256_HMAC 1
#define DROPBEAR_SHA1_96_HMAC 0
/* 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.
* RSA is recommended
* DSS may be necessary to connect to some systems though
is not recommended for new keys */
#define DROPBEAR_RSA 1
#define DROPBEAR_DSS 1
/* ECDSA is significantly faster than RSA or DSS. Compiling in ECC
* code (either ECDSA or ECDH) increases binary size - around 30kB
* on x86-64 */
#define DROPBEAR_ECDSA 1
/* Ed25519 is faster than ECDSA. Compiling in Ed25519 code increases
binary size - around 7,5kB on x86-64 */
#define DROPBEAR_ED25519 1
/* RSA must be >=1024 */
#define DROPBEAR_DEFAULT_RSA_SIZE 2048
/* DSS is always 1024 */
/* ECDSA defaults to largest size configured, usually 521 */
/* Ed25519 is always 256 */
/* Add runtime flag "-R" to generate hostkeys as-needed when the first
connection using that key type occurs.
This avoids the need to otherwise run "dropbearkey" and avoids some problems
with badly seeded /dev/urandom when systems first boot. */
#define DROPBEAR_DELAY_HOSTKEY 1
/* Key exchange algorithm.
* group14_sha1 - 2048 bit, sha1
* group14_sha256 - 2048 bit, sha2-256
* group16 - 4096 bit, sha2-512
* group1 - 1024 bit, sha1
* curve25519 - elliptic curve DH
* ecdh - NIST elliptic curve DH (256, 384, 521)
*
* group1 is too small for security though is necessary if you need
compatibility with some implementations such as Dropbear versions < 0.53
* group14 is supported by most implementations.
* group16 provides a greater strength level but is slower and increases binary size
* curve25519 and ecdh algorithms are faster than non-elliptic curve methods
* curve25519 increases binary size by ~2,5kB on x86-64
* including either ECDH or ECDSA increases binary size by ~30kB on x86-64
* Small systems should generally include either curve25519 or ecdh for performance.
* curve25519 is less widely supported but is faster
*/
#define DROPBEAR_DH_GROUP14_SHA1 1
#define DROPBEAR_DH_GROUP14_SHA256 1
#define DROPBEAR_DH_GROUP16 0
#define DROPBEAR_CURVE25519 1
#define DROPBEAR_ECDH 1
#define DROPBEAR_DH_GROUP1 1
/* When group1 is enabled it will only be allowed by Dropbear client
not as a server, due to concerns over its strength. Set to 0 to allow
group1 in Dropbear server too */
#define DROPBEAR_DH_GROUP1_CLIENTONLY 1
/* Control the memory/performance/compression tradeoff for zlib.
* Set windowBits=8 for least memory usage, see your system's
* zlib.h for full details.
* Default settings (windowBits=15) will use 256kB for compression
* windowBits=8 will use 129kB for compression.
* Both modes will use ~35kB for decompression (using windowBits=15 for
* interoperability) */
#define DROPBEAR_ZLIB_WINDOW_BITS 15
/* Whether to do reverse DNS lookups. */
#define DO_HOST_LOOKUP 0
/* Whether to print the message of the day (MOTD). */
#define DO_MOTD 1
#define MOTD_FILENAME "/etc/motd"
/* Authentication Types - at least one required.
RFC Draft requires pubkey auth, and recommends password */
#define DROPBEAR_SVR_PASSWORD_AUTH 1
/* 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. It won't work for more complex
* PAM challenge/response.
* You can't enable both PASSWORD and PAM. */
#define DROPBEAR_SVR_PAM_AUTH 0
/* ~/.ssh/authorized_keys authentication */
#define DROPBEAR_SVR_PUBKEY_AUTH 1
/* Whether to take public key options in
* authorized_keys file into account */
#define DROPBEAR_SVR_PUBKEY_OPTIONS 1
/* Set this to 0 if your system does not have multiple user support.
(Linux kernel CONFIG_MULTIUSER option)
The resulting binary will not run on a normal system. */
#define DROPBEAR_SVR_MULTIUSER 1
/* Client authentication options */
#define DROPBEAR_CLI_PASSWORD_AUTH 1
#define DROPBEAR_CLI_PUBKEY_AUTH 1
/* A default argument for dbclient -i <privatekey>.
Homedir is prepended unless path begins with / */
#define DROPBEAR_DEFAULT_CLI_AUTHKEY ".ssh/id_dropbear"
/* Allow specifying the password for dbclient via the DROPBEAR_PASSWORD
* environment variable. */
#define DROPBEAR_USE_PASSWORD_ENV 1
/* Define this (as well as DROPBEAR_CLI_PASSWORD_AUTH) to allow the use of
* a helper program for the ssh client. The helper program should be
* specified in the SSH_ASKPASS environment variable, and dbclient
* should be run with DISPLAY set and no tty. The program should
* return the password on standard output */
#define DROPBEAR_CLI_ASKPASS_HELPER 0
/* Save a network roundtrip by sendng a real auth request immediately after
* sending a query for the available methods. This is not yet enabled by default
since it could cause problems with non-compliant servers */
#define DROPBEAR_CLI_IMMEDIATE_AUTH 0
/* Set this to use PRNGD or EGD instead of /dev/urandom */
#define DROPBEAR_USE_PRNGD 0
#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 */
#define MAX_UNAUTH_PER_IP 5
/* And then a global limit to avoid chewing memory if connections
* come from many IPs */
#define MAX_UNAUTH_CLIENTS 30
/* Default maximum number of failed authentication tries (server option) */
/* -T server option overrides */
#define MAX_AUTH_TRIES 10
/* The default file to store the daemon's process ID, for shutdown
scripts etc. This can be overridden with the -P flag */
#define DROPBEAR_PIDFILE "/var/run/dropbear.pid"
/* The command to invoke for xauth when using X11 forwarding.
* "-q" for quiet */
#define XAUTH_COMMAND "/usr/bin/xauth -q"
/* if you want to enable running an sftp server (such as the one included with
* OpenSSH), set the path below and set DROPBEAR_SFTPSERVER.
* The sftp-server program is not provided by Dropbear itself */
#define DROPBEAR_SFTPSERVER 1
#define SFTPSERVER_PATH "/usr/libexec/sftp-server"
/* This is used by the scp binary when used as a client binary. If you're
* not using the Dropbear client, you'll need to change it */
#define DROPBEAR_PATH_SSH_PROGRAM "/usr/bin/dbclient"
/* Whether to log commands executed by a client. This only logs the
* (single) command sent to the server, not what a user did in a
* shell/sftp session etc. */
#define LOG_COMMANDS 0
/* Window size limits. These tend to be a trade-off between memory
usage and network performance: */
/* Size of the network receive window. This amount of memory is allocated
as a per-channel receive buffer. Increasing this value can make a
significant difference to network performance. 24kB was empirically
chosen for a 100mbit ethernet network. The value can be altered at
runtime with the -W argument. */
#define DEFAULT_RECV_WINDOW 24576
/* Maximum size of a received SSH data packet - this _MUST_ be >= 32768
in order to interoperate with other implementations */
#define RECV_MAX_PAYLOAD_LEN 32768
/* Maximum size of a transmitted data packet - this can be any value,
though increasing it may not make a significant difference. */
#define TRANS_MAX_PAYLOAD_LEN 16384
/* Ensure that data is transmitted every KEEPALIVE seconds. This can
be overridden at runtime with -K. 0 disables keepalives */
#define DEFAULT_KEEPALIVE 0
/* If this many KEEPALIVES are sent with no packets received from the
other side, exit. Not run-time configurable - if you have a need
for runtime configuration please mail the Dropbear list */
#define DEFAULT_KEEPALIVE_LIMIT 3
/* Ensure that data is received within IDLE_TIMEOUT seconds. This can
be overridden at runtime with -I. 0 disables idle timeouts */
#define DEFAULT_IDLE_TIMEOUT 0
/* The default path. This will often get replaced by the shell */
#define DEFAULT_PATH "/usr/bin:/bin"
#endif /* DROPBEAR_DEFAULT_OPTIONS_H_ */

View File

@@ -1,6 +1,8 @@
#include "options.h"
#include "dh_groups.h"
#if DROPBEAR_NORMAL_DH
#if DROPBEAR_DH_GROUP1
/* diffie-hellman-group1-sha1 value for p */
const unsigned char dh_p_1[DH_P_1_LEN] = {
@@ -92,3 +94,4 @@ const unsigned char dh_p_16[DH_P_16_LEN] = {
/* Same for all groups */
const int DH_G_VAL = 2;
#endif /* DROPBEAR_NORMAL_DH */

View File

@@ -2,6 +2,8 @@
#define DROPBEAR_DH_GROUPS_H
#include "options.h"
#if DROPBEAR_NORMAL_DH
#if DROPBEAR_DH_GROUP1
#define DH_P_1_LEN 128
extern const unsigned char dh_p_1[DH_P_1_LEN];
@@ -17,8 +19,8 @@ extern const unsigned char dh_p_14[DH_P_14_LEN];
extern const unsigned char dh_p_16[DH_P_16_LEN];
#endif
extern const int DH_G_VAL;
#endif /* DROPBEAR_NORMAL_DH */
#endif

View File

@@ -91,6 +91,13 @@ if 0 disables keepalives. If no response is received for 3 consecutive keepalive
.B \-I \fIidle_timeout
Disconnect the session if no traffic is transmitted or received for \fIidle_timeout\fR seconds.
.TP
.B \-T \fImax_authentication_attempts
Set the number of authentication attempts allowed per connection. If unspecified the default is 10 (MAX_AUTH_TRIES)
.TP
.B \-c \fIforced_command
Disregard the command provided by the user and always run \fIforced_command\fR. This also
overrides any authorized_keys command= option.
.TP
.B \-V
Print the version
@@ -100,7 +107,7 @@ Print the version
Authorized Keys
~/.ssh/authorized_keys can be set up to allow remote login with a RSA,
ECDSA, or DSS
ECDSA, Ed25519 or DSS
key. Each line is of the form
.TP
[restrictions] ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIgAsp... [comment]
@@ -129,6 +136,7 @@ same functionality with other means even if no-pty is set.
.TP
.B command=\fR"\fIforced_command\fR"
Disregard the command provided by the user and always run \fIforced_command\fR.
The -c command line option overrides this.
The authorized_keys file and its containing ~/.ssh directory must only be
writable by the user, otherwise Dropbear will not allow a login using public
@@ -138,10 +146,12 @@ key authentication.
Host Key Files
Host key files are read at startup from a standard location, by default
/etc/dropbear/dropbear_dss_host_key, /etc/dropbear/dropbear_rsa_host_key, and
/etc/dropbear/dropbear_ecdsa_host_key
or specified on the commandline with -r. These are of the form generated
by dropbearkey. The -R option can be used to automatically generate keys
/etc/dropbear/dropbear_dss_host_key, /etc/dropbear/dropbear_rsa_host_key,
/etc/dropbear/dropbear_ecdsa_host_key and /etc/dropbear/dropbear_ed25519_host_key
If the -r command line option is specified the default files are not loaded.
Host key files are of the form generated by dropbearkey.
The -R option can be used to automatically generate keys
in the default location - keys will be generated after startup when the first
connection is established. This had the benefit that the system /dev/urandom
random number source has a better chance of being securely seeded.

8
dropbear_lint.sh Executable file
View File

@@ -0,0 +1,8 @@
#!/bin/sh
EXITCODE=0
# #ifdef instead of #if
grep '#ifdef DROPBEAR' -I *.c *.h && EXITCODE=1
exit $EXITCODE

View File

@@ -53,8 +53,8 @@ static void printhelp(char * progname) {
progname);
}
#if defined(DBMULTI_dropbearconvert) || !defined(DROPBEAR_MULTI)
#if defined(DBMULTI_dropbearconvert) && defined(DROPBEAR_MULTI)
#if defined(DBMULTI_dropbearconvert) || !DROPBEAR_MULTI
#if defined(DBMULTI_dropbearconvert) && DROPBEAR_MULTI
int dropbearconvert_main(int argc, char ** argv) {
#else
int main(int argc, char ** argv) {
@@ -67,7 +67,7 @@ int main(int argc, char ** argv) {
crypto_init();
seedrandom();
#ifdef DEBUG_TRACE
#if DEBUG_TRACE
/* It's hard for it to get in the way _too_ much */
debug_trace = 1;
#endif

View File

@@ -13,7 +13,7 @@ dropbearkey \- create private keys for the use with dropbear(8) or dbclient(1)
.SH DESCRIPTION
.B dropbearkey
generates a
\fIRSA\fR, \fIDSS\fR, or \fIECDSA\fR
\fIRSA\fR, \fIDSS\fR, \fIECDSA\fR, or \fIEd25519\fR
format SSH private key, and saves it to a file for the use with the
Dropbear client or server.
Note that
@@ -26,6 +26,7 @@ Type of key to generate.
Must be one of
.I rsa
.I ecdsa
.I ed25519
or
.IR dss .
.TP

View File

@@ -43,6 +43,10 @@
* mp_int y
* mp_int x
*
* Ed25519:
* string "ssh-ed25519"
* string k (32 bytes) + A (32 bytes)
*
*/
#include "includes.h"
#include "signkey.h"
@@ -51,6 +55,7 @@
#include "genrsa.h"
#include "gendss.h"
#include "gened25519.h"
#include "ecdsa.h"
#include "crypto_desc.h"
#include "dbrandom.h"
@@ -67,36 +72,42 @@ static void printhelp(char * progname) {
fprintf(stderr, "Usage: %s -t <type> -f <filename> [-s bits]\n"
"-t type Type of key to generate. One of:\n"
#ifdef DROPBEAR_RSA
#if DROPBEAR_RSA
" rsa\n"
#endif
#ifdef DROPBEAR_DSS
#if DROPBEAR_DSS
" dss\n"
#endif
#ifdef DROPBEAR_ECDSA
#if DROPBEAR_ECDSA
" ecdsa\n"
#endif
#if DROPBEAR_ED25519
" ed25519\n"
#endif
"-f filename Use filename for the secret key.\n"
" ~/.ssh/id_dropbear is recommended for client keys.\n"
"-s bits Key size in bits, should be a multiple of 8 (optional)\n"
#ifdef DROPBEAR_DSS
#if DROPBEAR_DSS
" DSS has a fixed size of 1024 bits\n"
#endif
#ifdef DROPBEAR_ECDSA
#if DROPBEAR_ECDSA
" ECDSA has sizes "
#ifdef DROPBEAR_ECC_256
#if DROPBEAR_ECC_256
"256 "
#endif
#ifdef DROPBEAR_ECC_384
#if DROPBEAR_ECC_384
"384 "
#endif
#ifdef DROPBEAR_ECC_521
#if DROPBEAR_ECC_521
"521 "
#endif
"\n"
#endif
#if DROPBEAR_ED25519
" Ed25519 has a fixed size of 256 bits\n"
#endif
"-y Just print the publickey and fingerprint for the\n private key in <filename>.\n"
#ifdef DEBUG_TRACE
#if DEBUG_TRACE
"-v verbose\n"
#endif
,progname);
@@ -106,7 +117,15 @@ static void printhelp(char * progname) {
static void check_signkey_bits(enum signkey_type type, int bits)
{
switch (type) {
#ifdef DROPBEAR_RSA
#if DROPBEAR_ED25519
case DROPBEAR_SIGNKEY_ED25519:
if (bits != 256) {
dropbear_exit("Ed25519 keys have a fixed size of 256 bits\n");
exit(EXIT_FAILURE);
}
break;
#endif
#if DROPBEAR_RSA
case DROPBEAR_SIGNKEY_RSA:
if (bits < 512 || bits > 4096 || (bits % 8 != 0)) {
dropbear_exit("Bits must satisfy 512 <= bits <= 4096, and be a"
@@ -114,7 +133,7 @@ static void check_signkey_bits(enum signkey_type type, int bits)
}
break;
#endif
#ifdef DROPEAR_DSS
#if DROPEAR_DSS
case DROPBEAR_SIGNKEY_DSS:
if (bits != 1024) {
dropbear_exit("DSS keys have a fixed size of 1024 bits\n");
@@ -126,20 +145,20 @@ static void check_signkey_bits(enum signkey_type type, int bits)
}
}
#if defined(DBMULTI_dropbearkey) || !defined(DROPBEAR_MULTI)
#if defined(DBMULTI_dropbearkey) && defined(DROPBEAR_MULTI)
#if defined(DBMULTI_dropbearkey) || !DROPBEAR_MULTI
#if defined(DBMULTI_dropbearkey) && DROPBEAR_MULTI
int dropbearkey_main(int argc, char ** argv) {
#else
int main(int argc, char ** argv) {
#endif
int i;
char ** next = 0;
char ** next = NULL;
char * filename = NULL;
enum signkey_type keytype = DROPBEAR_SIGNKEY_NONE;
char * typetext = NULL;
char * sizetext = NULL;
unsigned int bits = 0;
unsigned int bits = 0, genbits;
int printpub = 0;
crypto_init();
@@ -174,7 +193,7 @@ int main(int argc, char ** argv) {
printhelp(argv[0]);
exit(EXIT_SUCCESS);
break;
#ifdef DEBUG_TRACE
#if DEBUG_TRACE
case 'v':
debug_trace = 1;
break;
@@ -206,24 +225,30 @@ int main(int argc, char ** argv) {
exit(EXIT_FAILURE);
}
#ifdef DROPBEAR_RSA
#if DROPBEAR_RSA
if (strcmp(typetext, "rsa") == 0)
{
keytype = DROPBEAR_SIGNKEY_RSA;
}
#endif
#ifdef DROPBEAR_DSS
#if DROPBEAR_DSS
if (strcmp(typetext, "dss") == 0)
{
keytype = DROPBEAR_SIGNKEY_DSS;
}
#endif
#ifdef DROPBEAR_ECDSA
#if DROPBEAR_ECDSA
if (strcmp(typetext, "ecdsa") == 0)
{
keytype = DROPBEAR_SIGNKEY_ECDSA_KEYGEN;
}
#endif
#if DROPBEAR_ED25519
if (strcmp(typetext, "ed25519") == 0)
{
keytype = DROPBEAR_SIGNKEY_ED25519;
}
#endif
if (keytype == DROPBEAR_SIGNKEY_NONE) {
fprintf(stderr, "Unknown key type '%s'\n", typetext);
@@ -240,8 +265,9 @@ int main(int argc, char ** argv) {
check_signkey_bits(keytype, bits);;
}
fprintf(stderr, "Generating key, this may take a while...\n");
if (signkey_generate(keytype, bits, filename) == DROPBEAR_FAILURE)
genbits = signkey_generate_get_bits(keytype, bits);
fprintf(stderr, "Generating %u bit %s key, this may take a while...\n", genbits, typetext);
if (signkey_generate(keytype, bits, filename, 0) == DROPBEAR_FAILURE)
{
dropbear_exit("Failed to generate key.\n");
}

106
dss.c
View File

@@ -37,13 +37,14 @@
* See FIPS186 or the Handbook of Applied Cryptography for details of the
* algorithm */
#ifdef DROPBEAR_DSS
#if DROPBEAR_DSS
/* Load a dss key from a buffer, initialising the values.
* The key will have the same format as buf_put_dss_key.
* These should be freed with dss_key_free.
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
int buf_get_dss_pub_key(buffer* buf, dropbear_dss_key *key) {
int ret = DROPBEAR_FAILURE;
TRACE(("enter buf_get_dss_pub_key"))
dropbear_assert(key != NULL);
@@ -56,17 +57,41 @@ int buf_get_dss_pub_key(buffer* buf, dropbear_dss_key *key) {
|| buf_getmpint(buf, key->g) == DROPBEAR_FAILURE
|| buf_getmpint(buf, key->y) == DROPBEAR_FAILURE) {
TRACE(("leave buf_get_dss_pub_key: failed reading mpints"))
return DROPBEAR_FAILURE;
ret = DROPBEAR_FAILURE;
goto out;
}
if (mp_count_bits(key->p) < MIN_DSS_KEYLEN) {
dropbear_log(LOG_WARNING, "DSS key too short");
TRACE(("leave buf_get_dss_pub_key: short key"))
return DROPBEAR_FAILURE;
if (mp_count_bits(key->p) != DSS_P_BITS) {
dropbear_log(LOG_WARNING, "Bad DSS p");
ret = DROPBEAR_FAILURE;
goto out;
}
if (mp_count_bits(key->q) != DSS_Q_BITS) {
dropbear_log(LOG_WARNING, "Bad DSS q");
ret = DROPBEAR_FAILURE;
goto out;
}
/* test 1 < g < p */
if (mp_cmp_d(key->g, 1) != MP_GT) {
dropbear_log(LOG_WARNING, "Bad DSS g");
ret = DROPBEAR_FAILURE;
goto out;
}
if (mp_cmp(key->g, key->p) != MP_LT) {
dropbear_log(LOG_WARNING, "Bad DSS g");
ret = DROPBEAR_FAILURE;
goto out;
}
ret = DROPBEAR_SUCCESS;
TRACE(("leave buf_get_dss_pub_key: success"))
return DROPBEAR_SUCCESS;
out:
if (ret == DROPBEAR_FAILURE) {
m_mp_free_multi(&key->p, &key->q, &key->g, &key->y, NULL);
}
return ret;
}
/* Same as buf_get_dss_pub_key, but reads a private "x" key at the end.
@@ -86,7 +111,7 @@ int buf_get_dss_priv_key(buffer* buf, dropbear_dss_key *key) {
m_mp_alloc_init_multi(&key->x, NULL);
ret = buf_getmpint(buf, key->x);
if (ret == DROPBEAR_FAILURE) {
m_free(key->x);
m_mp_free_multi(&key->x, NULL);
}
return ret;
@@ -101,26 +126,7 @@ void dss_key_free(dropbear_dss_key *key) {
TRACE2(("enter dsa_key_free: key == NULL"))
return;
}
if (key->p) {
mp_clear(key->p);
m_free(key->p);
}
if (key->q) {
mp_clear(key->q);
m_free(key->q);
}
if (key->g) {
mp_clear(key->g);
m_free(key->g);
}
if (key->y) {
mp_clear(key->y);
m_free(key->y);
}
if (key->x) {
mp_clear(key->x);
m_free(key->x);
}
m_mp_free_multi(&key->p, &key->q, &key->g, &key->y, &key->x, NULL);
m_free(key);
TRACE2(("leave dsa_key_free"))
}
@@ -133,7 +139,7 @@ void dss_key_free(dropbear_dss_key *key) {
* mpint g
* mpint y
*/
void buf_put_dss_pub_key(buffer* buf, dropbear_dss_key *key) {
void buf_put_dss_pub_key(buffer* buf, const dropbear_dss_key *key) {
dropbear_assert(key != NULL);
buf_putstring(buf, SSH_SIGNKEY_DSS, SSH_SIGNKEY_DSS_LEN);
@@ -145,7 +151,7 @@ void buf_put_dss_pub_key(buffer* buf, dropbear_dss_key *key) {
}
/* Same as buf_put_dss_pub_key, but with the private "x" key appended */
void buf_put_dss_priv_key(buffer* buf, dropbear_dss_key *key) {
void buf_put_dss_priv_key(buffer* buf, const dropbear_dss_key *key) {
dropbear_assert(key != NULL);
buf_put_dss_pub_key(buf, key);
@@ -153,10 +159,10 @@ void buf_put_dss_priv_key(buffer* buf, dropbear_dss_key *key) {
}
#ifdef DROPBEAR_SIGNKEY_VERIFY
#if DROPBEAR_SIGNKEY_VERIFY
/* Verify a DSS signature (in buf) made on data by the key given.
* returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
int buf_dss_verify(buffer* buf, dropbear_dss_key *key, buffer *data_buf) {
int buf_dss_verify(buffer* buf, const dropbear_dss_key *key, const buffer *data_buf) {
unsigned char msghash[SHA1_HASH_SIZE];
hash_state hs;
int ret = DROPBEAR_FAILURE;
@@ -178,6 +184,13 @@ int buf_dss_verify(buffer* buf, dropbear_dss_key *key, buffer *data_buf) {
goto out;
}
#if DEBUG_DSS_VERIFY
printmpint("dss verify p", key->p);
printmpint("dss verify q", key->q);
printmpint("dss verify g", key->g);
printmpint("dss verify y", key->y);
#endif
/* hash the data */
sha1_init(&hs);
sha1_process(&hs, data_buf->data, data_buf->len);
@@ -187,11 +200,18 @@ int buf_dss_verify(buffer* buf, dropbear_dss_key *key, buffer *data_buf) {
/* w = (s')-1 mod q */
/* let val1 = s' */
bytes_to_mp(&val1, (const unsigned char*) &string[SHA1_HASH_SIZE], SHA1_HASH_SIZE);
#if DEBUG_DSS_VERIFY
printmpint("dss verify s'", &val1);
#endif
if (mp_cmp(&val1, key->q) != MP_LT) {
TRACE(("verify failed, s' >= q"))
goto out;
}
if (mp_cmp_d(&val1, 0) != MP_GT) {
TRACE(("verify failed, s' <= 0"))
goto out;
}
/* let val2 = w = (s')^-1 mod q*/
if (mp_invmod(&val1, key->q, &val2) != MP_OKAY) {
goto out;
@@ -200,6 +220,9 @@ int buf_dss_verify(buffer* buf, dropbear_dss_key *key, buffer *data_buf) {
/* u1 = ((SHA(M')w) mod q */
/* let val1 = SHA(M') = msghash */
bytes_to_mp(&val1, msghash, SHA1_HASH_SIZE);
#if DEBUG_DSS_VERIFY
printmpint("dss verify r'", &val1);
#endif
/* let val3 = u1 = ((SHA(M')w) mod q */
if (mp_mulmod(&val1, &val2, key->q, &val3) != MP_OKAY) {
@@ -213,6 +236,10 @@ int buf_dss_verify(buffer* buf, dropbear_dss_key *key, buffer *data_buf) {
TRACE(("verify failed, r' >= q"))
goto out;
}
if (mp_cmp_d(&val1, 0) != MP_GT) {
TRACE(("verify failed, r' <= 0"))
goto out;
}
/* let val4 = u2 = ((r')w) mod q */
if (mp_mulmod(&val1, &val2, key->q, &val4) != MP_OKAY) {
goto out;
@@ -253,10 +280,11 @@ out:
/* Sign the data presented with key, writing the signature contents
* to the buffer */
void buf_put_dss_sign(buffer* buf, dropbear_dss_key *key, buffer *data_buf) {
void buf_put_dss_sign(buffer* buf, const dropbear_dss_key *key, const buffer *data_buf) {
unsigned char msghash[SHA1_HASH_SIZE];
unsigned int writelen;
unsigned int i;
size_t written;
DEF_MP_INT(dss_k);
DEF_MP_INT(dss_m);
DEF_MP_INT(dss_temp1);
@@ -313,31 +341,31 @@ void buf_put_dss_sign(buffer* buf, dropbear_dss_key *key, buffer *data_buf) {
buf_putstring(buf, SSH_SIGNKEY_DSS, SSH_SIGNKEY_DSS_LEN);
buf_putint(buf, 2*SHA1_HASH_SIZE);
writelen = mp_unsigned_bin_size(&dss_r);
writelen = mp_ubin_size(&dss_r);
dropbear_assert(writelen <= SHA1_HASH_SIZE);
/* need to pad to 160 bits with leading zeros */
for (i = 0; i < SHA1_HASH_SIZE - writelen; i++) {
buf_putbyte(buf, 0);
}
if (mp_to_unsigned_bin(&dss_r, buf_getwriteptr(buf, writelen))
if (mp_to_ubin(&dss_r, buf_getwriteptr(buf, writelen), writelen, &written)
!= MP_OKAY) {
dropbear_exit("DSS error");
}
mp_clear(&dss_r);
buf_incrwritepos(buf, writelen);
buf_incrwritepos(buf, written);
writelen = mp_unsigned_bin_size(&dss_s);
writelen = mp_ubin_size(&dss_s);
dropbear_assert(writelen <= SHA1_HASH_SIZE);
/* need to pad to 160 bits with leading zeros */
for (i = 0; i < SHA1_HASH_SIZE - writelen; i++) {
buf_putbyte(buf, 0);
}
if (mp_to_unsigned_bin(&dss_s, buf_getwriteptr(buf, writelen))
if (mp_to_ubin(&dss_s, buf_getwriteptr(buf, writelen), writelen, &written)
!= MP_OKAY) {
dropbear_exit("DSS error");
}
mp_clear(&dss_s);
buf_incrwritepos(buf, writelen);
buf_incrwritepos(buf, written);
mp_clear_multi(&dss_k, &dss_temp1, &dss_temp2, &dss_r, &dss_s,
&dss_m, NULL);

17
dss.h
View File

@@ -28,9 +28,9 @@
#include "includes.h"
#include "buffer.h"
#ifdef DROPBEAR_DSS
#if DROPBEAR_DSS
typedef struct {
typedef struct dropbear_DSS_Key {
mp_int* p;
mp_int* q;
@@ -41,14 +41,17 @@ typedef struct {
} dropbear_dss_key;
void buf_put_dss_sign(buffer* buf, dropbear_dss_key *key, buffer *data_buf);
#ifdef DROPBEAR_SIGNKEY_VERIFY
int buf_dss_verify(buffer* buf, dropbear_dss_key *key, buffer *data_buf);
#define DSS_P_BITS 1024
#define DSS_Q_BITS 160
void buf_put_dss_sign(buffer* buf, const dropbear_dss_key *key, const buffer *data_buf);
#if DROPBEAR_SIGNKEY_VERIFY
int buf_dss_verify(buffer* buf, const dropbear_dss_key *key, const buffer *data_buf);
#endif
int buf_get_dss_pub_key(buffer* buf, dropbear_dss_key *key);
int buf_get_dss_priv_key(buffer* buf, dropbear_dss_key *key);
void buf_put_dss_pub_key(buffer* buf, dropbear_dss_key *key);
void buf_put_dss_priv_key(buffer* buf, dropbear_dss_key *key);
void buf_put_dss_pub_key(buffer* buf, const dropbear_dss_key *key);
void buf_put_dss_priv_key(buffer* buf, const dropbear_dss_key *key);
void dss_key_free(dropbear_dss_key *key);
#endif /* DROPBEAR_DSS */

60
ecc.c
View File

@@ -1,13 +1,12 @@
#include "includes.h"
#include "options.h"
#include "ecc.h"
#include "dbutil.h"
#include "bignum.h"
#ifdef DROPBEAR_ECC
#if DROPBEAR_ECC
/* .dp members are filled out by dropbear_ecc_fill_dp() at startup */
#ifdef DROPBEAR_ECC_256
#if DROPBEAR_ECC_256
struct dropbear_ecc_curve ecc_curve_nistp256 = {
32, /* .ltc_size */
NULL, /* .dp */
@@ -15,7 +14,7 @@ struct dropbear_ecc_curve ecc_curve_nistp256 = {
"nistp256" /* .name */
};
#endif
#ifdef DROPBEAR_ECC_384
#if DROPBEAR_ECC_384
struct dropbear_ecc_curve ecc_curve_nistp384 = {
48, /* .ltc_size */
NULL, /* .dp */
@@ -23,7 +22,7 @@ struct dropbear_ecc_curve ecc_curve_nistp384 = {
"nistp384" /* .name */
};
#endif
#ifdef DROPBEAR_ECC_521
#if DROPBEAR_ECC_521
struct dropbear_ecc_curve ecc_curve_nistp521 = {
66, /* .ltc_size */
NULL, /* .dp */
@@ -33,13 +32,13 @@ struct dropbear_ecc_curve ecc_curve_nistp521 = {
#endif
struct dropbear_ecc_curve *dropbear_ecc_curves[] = {
#ifdef DROPBEAR_ECC_256
#if DROPBEAR_ECC_256
&ecc_curve_nistp256,
#endif
#ifdef DROPBEAR_ECC_384
#if DROPBEAR_ECC_384
&ecc_curve_nistp384,
#endif
#ifdef DROPBEAR_ECC_521
#if DROPBEAR_ECC_521
&ecc_curve_nistp521,
#endif
NULL
@@ -82,7 +81,7 @@ ecc_key * new_ecc_key(void) {
/* Copied from libtomcrypt ecc_import.c (version there is static), modified
for different mp_int pointer without LTC_SOURCE */
static int ecc_is_point(ecc_key *key)
static int ecc_is_point(const ecc_key *key)
{
mp_int *prime, *b, *t1, *t2;
int err;
@@ -167,13 +166,13 @@ ecc_key * buf_get_ecc_raw_pubkey(buffer *buf, const struct dropbear_ecc_curve *c
key = new_ecc_key();
key->dp = curve->dp;
if (mp_read_unsigned_bin(key->pubkey.x, buf_getptr(buf, size), size) != MP_OKAY) {
if (mp_from_ubin(key->pubkey.x, buf_getptr(buf, size), size) != MP_OKAY) {
TRACE(("failed to read x"))
goto out;
}
buf_incrpos(buf, size);
if (mp_read_unsigned_bin(key->pubkey.y, buf_getptr(buf, size), size) != MP_OKAY) {
if (mp_from_ubin(key->pubkey.y, buf_getptr(buf, size), size) != MP_OKAY) {
TRACE(("failed to read y"))
goto out;
}
@@ -213,7 +212,7 @@ ecc_key * buf_get_ecc_raw_pubkey(buffer *buf, const struct dropbear_ecc_curve *c
/* a modified version of libtomcrypt's "ecc_shared_secret" to output
a mp_int instead. */
mp_int * dropbear_ecc_shared_secret(ecc_key *public_key, ecc_key *private_key)
mp_int * dropbear_ecc_shared_secret(ecc_key *public_key, const ecc_key *private_key)
{
ecc_point *result = NULL;
mp_int *prime = NULL, *shared_secret = NULL;
@@ -221,46 +220,41 @@ mp_int * dropbear_ecc_shared_secret(ecc_key *public_key, ecc_key *private_key)
/* type valid? */
if (private_key->type != PK_PRIVATE) {
goto done;
goto out;
}
if (private_key->dp != public_key->dp) {
goto done;
goto out;
}
/* make new point */
result = ltc_ecc_new_point();
if (result == NULL) {
goto done;
goto out;
}
prime = m_malloc(sizeof(*prime));
m_mp_init(prime);
if (mp_read_radix(prime, (char *)private_key->dp->prime, 16) != CRYPT_OK) {
goto done;
goto out;
}
if (ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, prime, 1) != CRYPT_OK) {
goto done;
goto out;
}
shared_secret = m_malloc(sizeof(*shared_secret));
m_mp_init(shared_secret);
if (mp_copy(result->x, shared_secret) != CRYPT_OK) {
goto out;
}
mp_clear(prime);
m_free(prime);
ltc_ecc_del_point(result);
err = DROPBEAR_SUCCESS;
done:
if (err == DROPBEAR_SUCCESS) {
shared_secret = m_malloc(sizeof(*shared_secret));
m_mp_init(shared_secret);
mp_copy(result->x, shared_secret);
}
if (prime) {
mp_clear(prime);
m_free(prime);
}
if (result)
{
ltc_ecc_del_point(result);
}
out:
if (err == DROPBEAR_FAILURE) {
dropbear_exit("ECC error");
}

5
ecc.h
View File

@@ -2,11 +2,10 @@
#define DROPBEAR_DROPBEAR_ECC_H
#include "includes.h"
#include "options.h"
#include "buffer.h"
#ifdef DROPBEAR_ECC
#if DROPBEAR_ECC
struct dropbear_ecc_curve {
int ltc_size; /* to match the byte sizes in ltc_ecc_sets[] */
@@ -29,7 +28,7 @@ void buf_put_ecc_raw_pubkey_string(buffer *buf, ecc_key *key);
ecc_key * buf_get_ecc_raw_pubkey(buffer *buf, const struct dropbear_ecc_curve *curve);
int buf_get_ecc_privkey_string(buffer *buf, ecc_key *key);
mp_int * dropbear_ecc_shared_secret(ecc_key *pub_key, ecc_key *priv_key);
mp_int * dropbear_ecc_shared_secret(ecc_key *pub_key, const ecc_key *priv_key);
#endif

27
ecdsa.c
View File

@@ -1,4 +1,3 @@
#include "options.h"
#include "includes.h"
#include "dbutil.h"
#include "crypto_desc.h"
@@ -6,7 +5,7 @@
#include "ecdsa.h"
#include "signkey.h"
#ifdef DROPBEAR_ECDSA
#if DROPBEAR_ECDSA
int signkey_is_ecdsa(enum signkey_type type)
{
@@ -15,18 +14,18 @@ int signkey_is_ecdsa(enum signkey_type type)
|| type == DROPBEAR_SIGNKEY_ECDSA_NISTP521;
}
enum signkey_type ecdsa_signkey_type(ecc_key * key) {
#ifdef DROPBEAR_ECC_256
enum signkey_type ecdsa_signkey_type(const ecc_key * key) {
#if DROPBEAR_ECC_256
if (key->dp == ecc_curve_nistp256.dp) {
return DROPBEAR_SIGNKEY_ECDSA_NISTP256;
}
#endif
#ifdef DROPBEAR_ECC_384
#if DROPBEAR_ECC_384
if (key->dp == ecc_curve_nistp384.dp) {
return DROPBEAR_SIGNKEY_ECDSA_NISTP384;
}
#endif
#ifdef DROPBEAR_ECC_521
#if DROPBEAR_ECC_521
if (key->dp == ecc_curve_nistp521.dp) {
return DROPBEAR_SIGNKEY_ECDSA_NISTP521;
}
@@ -38,17 +37,17 @@ ecc_key *gen_ecdsa_priv_key(unsigned int bit_size) {
const ltc_ecc_set_type *dp = NULL; /* curve domain parameters */
ecc_key *new_key = NULL;
switch (bit_size) {
#ifdef DROPBEAR_ECC_256
#if DROPBEAR_ECC_256
case 256:
dp = ecc_curve_nistp256.dp;
break;
#endif
#ifdef DROPBEAR_ECC_384
#if DROPBEAR_ECC_384
case 384:
dp = ecc_curve_nistp384.dp;
break;
#endif
#ifdef DROPBEAR_ECC_521
#if DROPBEAR_ECC_521
case 521:
dp = ecc_curve_nistp521.dp;
break;
@@ -56,13 +55,13 @@ ecc_key *gen_ecdsa_priv_key(unsigned int bit_size) {
}
if (!dp) {
dropbear_exit("Key size %d isn't valid. Try "
#ifdef DROPBEAR_ECC_256
#if DROPBEAR_ECC_256
"256 "
#endif
#ifdef DROPBEAR_ECC_384
#if DROPBEAR_ECC_384
"384 "
#endif
#ifdef DROPBEAR_ECC_521
#if DROPBEAR_ECC_521
"521 "
#endif
, bit_size);
@@ -154,7 +153,7 @@ void buf_put_ecdsa_priv_key(buffer *buf, ecc_key *key) {
buf_putmpint(buf, key->k);
}
void buf_put_ecdsa_sign(buffer *buf, ecc_key *key, buffer *data_buf) {
void buf_put_ecdsa_sign(buffer *buf, const ecc_key *key, const buffer *data_buf) {
/* Based on libtomcrypt's ecc_sign_hash but without the asn1 */
int err = DROPBEAR_FAILURE;
struct dropbear_ecc_curve *curve = NULL;
@@ -272,7 +271,7 @@ out:
}
int buf_ecdsa_verify(buffer *buf, ecc_key *key, buffer *data_buf) {
int buf_ecdsa_verify(buffer *buf, const ecc_key *key, const buffer *data_buf) {
/* Based on libtomcrypt's ecc_verify_hash but without the asn1 */
int ret = DROPBEAR_FAILURE;
hash_state hs;

23
ecdsa.h
View File

@@ -5,17 +5,18 @@
#include "buffer.h"
#include "signkey.h"
#ifdef DROPBEAR_ECDSA
#if DROPBEAR_ECDSA
/* Prefer the larger size - it's fast anyway */
#if defined(DROPBEAR_ECC_521)
#define ECDSA_DEFAULT_SIZE 521
#elif defined(DROPBEAR_ECC_384)
#define ECDSA_DEFAULT_SIZE 384
#elif defined(DROPBEAR_ECC_256)
/* prefer 256 or 384 since those are SHOULD for
draft-ietf-curdle-ssh-kex-sha2.txt */
#if DROPBEAR_ECC_256
#define ECDSA_DEFAULT_SIZE 256
#elif DROPBEAR_ECC_384
#define ECDSA_DEFAULT_SIZE 384
#elif DROPBEAR_ECC_521
#define ECDSA_DEFAULT_SIZE 521
#else
#define ECDSA_DEFAULT_SIZE 0
#error ECDSA cannot be enabled without enabling at least one size (256, 384, 521)
#endif
ecc_key *gen_ecdsa_priv_key(unsigned int bit_size);
@@ -23,10 +24,10 @@ ecc_key *buf_get_ecdsa_pub_key(buffer* buf);
ecc_key *buf_get_ecdsa_priv_key(buffer *buf);
void buf_put_ecdsa_pub_key(buffer *buf, ecc_key *key);
void buf_put_ecdsa_priv_key(buffer *buf, ecc_key *key);
enum signkey_type ecdsa_signkey_type(ecc_key * key);
enum signkey_type ecdsa_signkey_type(const ecc_key * key);
void buf_put_ecdsa_sign(buffer *buf, ecc_key *key, buffer *data_buf);
int buf_ecdsa_verify(buffer *buf, ecc_key *key, buffer *data_buf);
void buf_put_ecdsa_sign(buffer *buf, const ecc_key *key, const buffer *data_buf);
int buf_ecdsa_verify(buffer *buf, const ecc_key *key, const buffer *data_buf);
/* Returns 1 on success */
int signkey_is_ecdsa(enum signkey_type type);

182
ed25519.c Normal file
View File

@@ -0,0 +1,182 @@
/*
* Dropbear - a SSH2 server
*
* Copyright (c) 2002,2003 Matt Johnston
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
/* Perform Ed25519 operations on data, including reading keys, signing and
* verification. */
#include "includes.h"
#include "dbutil.h"
#include "buffer.h"
#include "ssh.h"
#include "curve25519.h"
#include "ed25519.h"
#if DROPBEAR_ED25519
/* Load a public ed25519 key from a buffer, initialising the values.
* The key will have the same format as buf_put_ed25519_key.
* These should be freed with ed25519_key_free.
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
int buf_get_ed25519_pub_key(buffer *buf, dropbear_ed25519_key *key) {
unsigned int len;
TRACE(("enter buf_get_ed25519_pub_key"))
dropbear_assert(key != NULL);
buf_incrpos(buf, 4+SSH_SIGNKEY_ED25519_LEN); /* int + "ssh-ed25519" */
len = buf_getint(buf);
if (len != CURVE25519_LEN || buf->len - buf->pos < len) {
TRACE(("leave buf_get_ed25519_pub_key: failure"))
return DROPBEAR_FAILURE;
}
m_burn(key->priv, CURVE25519_LEN);
memcpy(key->pub, buf_getptr(buf, CURVE25519_LEN), CURVE25519_LEN);
buf_incrpos(buf, CURVE25519_LEN);
TRACE(("leave buf_get_ed25519_pub_key: success"))
return DROPBEAR_SUCCESS;
}
/* Same as buf_get_ed25519_pub_key, but reads private key at the end.
* Loads a public and private ed25519 key from a buffer
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
int buf_get_ed25519_priv_key(buffer *buf, dropbear_ed25519_key *key) {
unsigned int len;
TRACE(("enter buf_get_ed25519_priv_key"))
dropbear_assert(key != NULL);
buf_incrpos(buf, 4+SSH_SIGNKEY_ED25519_LEN); /* int + "ssh-ed25519" */
len = buf_getint(buf);
if (len != CURVE25519_LEN*2 || buf->len - buf->pos < len) {
TRACE(("leave buf_get_ed25519_priv_key: failure"))
return DROPBEAR_FAILURE;
}
memcpy(key->priv, buf_getptr(buf, CURVE25519_LEN), CURVE25519_LEN);
buf_incrpos(buf, CURVE25519_LEN);
memcpy(key->pub, buf_getptr(buf, CURVE25519_LEN), CURVE25519_LEN);
buf_incrpos(buf, CURVE25519_LEN);
TRACE(("leave buf_get_ed25519_priv_key: success"))
return DROPBEAR_SUCCESS;
}
/* Clear and free the memory used by a public or private key */
void ed25519_key_free(dropbear_ed25519_key *key) {
TRACE2(("enter ed25519_key_free"))
if (key == NULL) {
TRACE2(("leave ed25519_key_free: key == NULL"))
return;
}
m_burn(key->priv, CURVE25519_LEN);
m_free(key);
TRACE2(("leave ed25519_key_free"))
}
/* Put the public ed25519 key into the buffer in the required format */
void buf_put_ed25519_pub_key(buffer *buf, const dropbear_ed25519_key *key) {
TRACE(("enter buf_put_ed25519_pub_key"))
dropbear_assert(key != NULL);
buf_putstring(buf, SSH_SIGNKEY_ED25519, SSH_SIGNKEY_ED25519_LEN);
buf_putstring(buf, key->pub, CURVE25519_LEN);
TRACE(("leave buf_put_ed25519_pub_key"))
}
/* Put the public and private ed25519 key into the buffer in the required format */
void buf_put_ed25519_priv_key(buffer *buf, const dropbear_ed25519_key *key) {
TRACE(("enter buf_put_ed25519_priv_key"))
dropbear_assert(key != NULL);
buf_putstring(buf, SSH_SIGNKEY_ED25519, SSH_SIGNKEY_ED25519_LEN);
buf_putint(buf, CURVE25519_LEN*2);
buf_putbytes(buf, key->priv, CURVE25519_LEN);
buf_putbytes(buf, key->pub, CURVE25519_LEN);
TRACE(("leave buf_put_ed25519_priv_key"))
}
/* Sign the data presented with key, writing the signature contents
* to the buffer */
void buf_put_ed25519_sign(buffer* buf, const dropbear_ed25519_key *key, const buffer *data_buf) {
unsigned char s[64];
unsigned long slen = sizeof(s);
TRACE(("enter buf_put_ed25519_sign"))
dropbear_assert(key != NULL);
dropbear_ed25519_sign(data_buf->data, data_buf->len, s, &slen, key->priv, key->pub);
buf_putstring(buf, SSH_SIGNKEY_ED25519, SSH_SIGNKEY_ED25519_LEN);
buf_putstring(buf, s, slen);
TRACE(("leave buf_put_ed25519_sign"))
}
#if DROPBEAR_SIGNKEY_VERIFY
/* Verify a signature in buf, made on data by the key given.
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
int buf_ed25519_verify(buffer *buf, const dropbear_ed25519_key *key, const buffer *data_buf) {
int ret = DROPBEAR_FAILURE;
unsigned char *s;
unsigned long slen;
TRACE(("enter buf_ed25519_verify"))
dropbear_assert(key != NULL);
slen = buf_getint(buf);
if (slen != 64 || buf->len - buf->pos < slen) {
TRACE(("leave buf_ed25519_verify: bad size"))
goto out;
}
s = buf_getptr(buf, slen);
if (dropbear_ed25519_verify(data_buf->data, data_buf->len,
s, slen, key->pub) == 0) {
/* signature is valid */
TRACE(("leave buf_ed25519_verify: success!"))
ret = DROPBEAR_SUCCESS;
}
out:
TRACE(("leave buf_ed25519_verify: ret %d", ret))
return ret;
}
#endif /* DROPBEAR_SIGNKEY_VERIFY */
#endif /* DROPBEAR_ED25519 */

54
ed25519.h Normal file
View File

@@ -0,0 +1,54 @@
/*
* Dropbear - a SSH2 server
*
* Copyright (c) 2002,2003 Matt Johnston
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#ifndef DROPBEAR_ED25519_H_
#define DROPBEAR_ED25519_H_
#include "includes.h"
#include "buffer.h"
#if DROPBEAR_ED25519
#define CURVE25519_LEN 32
typedef struct dropbear_ED25519_Key {
unsigned char priv[CURVE25519_LEN];
unsigned char pub[CURVE25519_LEN];
} dropbear_ed25519_key;
void buf_put_ed25519_sign(buffer* buf, const dropbear_ed25519_key *key, const buffer *data_buf);
#if DROPBEAR_SIGNKEY_VERIFY
int buf_ed25519_verify(buffer * buf, const dropbear_ed25519_key *key, const buffer *data_buf);
#endif
int buf_get_ed25519_pub_key(buffer* buf, dropbear_ed25519_key *key);
int buf_get_ed25519_priv_key(buffer* buf, dropbear_ed25519_key *key);
void buf_put_ed25519_pub_key(buffer* buf, const dropbear_ed25519_key *key);
void buf_put_ed25519_priv_key(buffer* buf, const dropbear_ed25519_key *key);
void ed25519_key_free(dropbear_ed25519_key *key);
#endif /* DROPBEAR_ED25519 */
#endif /* DROPBEAR_ED25519_H_ */

View File

@@ -99,6 +99,10 @@ rsa.c RSA asymmetric crypto routines
dss.c DSS asymmetric crypto routines
ed25519.c Ed25519 asymmetric crypto routines
gened25519.c Ed25519 key generation
gendss.c DSS key generation
genrsa.c RSA key generation

209
fuzz-common.c Normal file
View File

@@ -0,0 +1,209 @@
#include "includes.h"
#include "includes.h"
#include "fuzz.h"
#include "dbutil.h"
#include "runopts.h"
#include "crypto_desc.h"
#include "session.h"
#include "dbrandom.h"
#include "bignum.h"
#include "fuzz-wrapfd.h"
struct dropbear_fuzz_options fuzz;
static void fuzz_dropbear_log(int UNUSED(priority), const char* format, va_list param);
static void load_fixed_hostkeys(void);
void fuzz_common_setup(void) {
fuzz.fuzzing = 1;
fuzz.wrapfds = 1;
fuzz.do_jmp = 1;
fuzz.input = m_malloc(sizeof(buffer));
_dropbear_log = fuzz_dropbear_log;
crypto_init();
fuzz_seed();
/* let any messages get flushed */
setlinebuf(stdout);
}
int fuzz_set_input(const uint8_t *Data, size_t Size) {
fuzz.input->data = (unsigned char*)Data;
fuzz.input->size = Size;
fuzz.input->len = Size;
fuzz.input->pos = 0;
memset(&ses, 0x0, sizeof(ses));
memset(&svr_ses, 0x0, sizeof(svr_ses));
wrapfd_setup();
fuzz_seed();
return DROPBEAR_SUCCESS;
}
#if DEBUG_TRACE
static void fuzz_dropbear_log(int UNUSED(priority), const char* format, va_list param) {
if (debug_trace) {
char printbuf[1024];
vsnprintf(printbuf, sizeof(printbuf), format, param);
fprintf(stderr, "%s\n", printbuf);
}
}
#else
static void fuzz_dropbear_log(int UNUSED(priority), const char* UNUSED(format), va_list UNUSED(param)) {
/* No print */
}
#endif /* DEBUG_TRACE */
void fuzz_svr_setup(void) {
fuzz_common_setup();
_dropbear_exit = svr_dropbear_exit;
char *argv[] = {
"-E",
};
int argc = sizeof(argv) / sizeof(*argv);
svr_getopts(argc, argv);
/* user lookups might be slow, cache it */
fuzz.pw_name = m_strdup("person");
fuzz.pw_dir = m_strdup("/tmp");
fuzz.pw_shell = m_strdup("/bin/zsh");
fuzz.pw_passwd = m_strdup("!!zzznope");
load_fixed_hostkeys();
}
static void load_fixed_hostkeys(void) {
#include "fuzz-hostkeys.c"
buffer *b = buf_new(3000);
enum signkey_type type;
TRACE(("load fixed hostkeys"))
svr_opts.hostkey = new_sign_key();
buf_setlen(b, 0);
buf_putbytes(b, keyr, keyr_len);
buf_setpos(b, 0);
type = DROPBEAR_SIGNKEY_RSA;
if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) {
dropbear_exit("failed fixed rsa hostkey");
}
buf_setlen(b, 0);
buf_putbytes(b, keyd, keyd_len);
buf_setpos(b, 0);
type = DROPBEAR_SIGNKEY_DSS;
if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) {
dropbear_exit("failed fixed dss hostkey");
}
buf_setlen(b, 0);
buf_putbytes(b, keye, keye_len);
buf_setpos(b, 0);
type = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) {
dropbear_exit("failed fixed ecdsa hostkey");
}
buf_setlen(b, 0);
buf_putbytes(b, keyed25519, keyed25519_len);
buf_setpos(b, 0);
type = DROPBEAR_SIGNKEY_ED25519;
if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) {
dropbear_exit("failed fixed ed25519 hostkey");
}
buf_free(b);
}
void fuzz_kex_fakealgos(void) {
ses.newkeys->recv.crypt_mode = &dropbear_mode_none;
}
void fuzz_get_socket_address(int UNUSED(fd), char **local_host, char **local_port,
char **remote_host, char **remote_port, int UNUSED(host_lookup)) {
if (local_host) {
*local_host = m_strdup("fuzzlocalhost");
}
if (local_port) {
*local_port = m_strdup("1234");
}
if (remote_host) {
*remote_host = m_strdup("fuzzremotehost");
}
if (remote_port) {
*remote_port = m_strdup("9876");
}
}
/* cut down version of svr_send_msg_kexdh_reply() that skips slow maths. Still populates structures */
void fuzz_fake_send_kexdh_reply(void) {
assert(!ses.dh_K);
m_mp_alloc_init_multi(&ses.dh_K, NULL);
mp_set_ul(ses.dh_K, 12345678uL);
finish_kexhashbuf();
}
int fuzz_run_preauth(const uint8_t *Data, size_t Size, int skip_kexmaths) {
static int once = 0;
if (!once) {
fuzz_svr_setup();
fuzz.skip_kexmaths = skip_kexmaths;
once = 1;
}
if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
return 0;
}
/*
get prefix. input format is
string prefix
uint32 wrapfd seed
... to be extended later
[bytes] ssh input stream
*/
/* be careful to avoid triggering buffer.c assertions */
if (fuzz.input->len < 8) {
return 0;
}
size_t prefix_size = buf_getint(fuzz.input);
if (prefix_size != 4) {
return 0;
}
uint32_t wrapseed = buf_getint(fuzz.input);
wrapfd_setseed(wrapseed);
int fakesock = 20;
wrapfd_add(fakesock, fuzz.input, PLAIN);
m_malloc_set_epoch(1);
if (setjmp(fuzz.jmp) == 0) {
svr_session(fakesock, fakesock);
m_malloc_free_epoch(1, 0);
} else {
m_malloc_free_epoch(1, 1);
TRACE(("dropbear_exit longjmped"))
/* dropbear_exit jumped here */
}
return 0;
}
const void* fuzz_get_algo(const algo_type *algos, const char* name) {
const algo_type *t;
for (t = algos; t->name; t++) {
if (strcmp(t->name, name) == 0) {
return t->data;
}
}
assert(0);
}

48
fuzz-harness.c Normal file
View File

@@ -0,0 +1,48 @@
#include "includes.h"
#include "buffer.h"
#include "dbutil.h"
extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size);
int main(int argc, char ** argv) {
int i;
buffer *input = buf_new(100000);
for (i = 1; i < argc; i++) {
printf("arg %s\n", argv[i]);
#if DEBUG_TRACE
if (strcmp(argv[i], "-v") == 0) {
debug_trace = 1;
TRACE(("debug printing on"))
}
#endif
}
int old_fuzz_wrapfds = 0;
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
/* ignore arguments */
continue;
}
char* fn = argv[i];
buf_setlen(input, 0);
buf_readfile(input, fn);
buf_setpos(input, 0);
fuzz.wrapfds = old_fuzz_wrapfds;
printf("Running %s once \n", fn);
LLVMFuzzerTestOneInput(input->data, input->len);
printf("Running %s twice \n", fn);
LLVMFuzzerTestOneInput(input->data, input->len);
printf("Done %s\n", fn);
/* Disable wrapfd so it won't interfere with buf_readfile() above */
old_fuzz_wrapfds = fuzz.wrapfds;
fuzz.wrapfds = 0;
}
printf("Finished\n");
return 0;
}

139
fuzz-hostkeys.c Normal file
View File

@@ -0,0 +1,139 @@
unsigned char keyr[] = {
0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x72, 0x73, 0x61, 0x00,
0x00, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0xb1,
0x06, 0x95, 0xc9, 0xa8, 0x38, 0xb9, 0x99, 0x91, 0xb5, 0x17, 0x39, 0xb9,
0xfa, 0xa4, 0x49, 0xf8, 0x2a, 0x4c, 0x14, 0xbd, 0xb6, 0x85, 0xdb, 0x38,
0x99, 0x44, 0xfa, 0xd6, 0xaa, 0x67, 0xef, 0x00, 0x75, 0x2b, 0x6a, 0x5c,
0x1b, 0x50, 0xa8, 0x52, 0xf9, 0xa7, 0xee, 0xe2, 0xb3, 0x80, 0x38, 0x92,
0x20, 0x86, 0x7c, 0xe5, 0x89, 0xb3, 0x06, 0xe4, 0x3b, 0xd1, 0xe2, 0x45,
0xea, 0xc1, 0xd5, 0x8e, 0x05, 0xfb, 0x90, 0x29, 0xd9, 0x41, 0xb3, 0x05,
0x31, 0x1e, 0xcc, 0xeb, 0x89, 0xdc, 0xd2, 0x6a, 0x99, 0x23, 0xbd, 0x7a,
0xbe, 0x8c, 0xe3, 0x3f, 0xa1, 0xe8, 0xf5, 0xb4, 0x51, 0x40, 0xb4, 0xb1,
0xc1, 0x16, 0x9f, 0x07, 0xbb, 0x99, 0xaa, 0x4b, 0x8f, 0x11, 0x19, 0x3c,
0x18, 0xbd, 0x6e, 0xce, 0x14, 0x54, 0x2c, 0x16, 0x4a, 0x5f, 0x89, 0xe4,
0x6b, 0x9f, 0x55, 0x68, 0xcc, 0x09, 0x8e, 0x4b, 0x92, 0xc8, 0x87, 0xfe,
0x09, 0xed, 0x53, 0x6e, 0xff, 0x5f, 0x15, 0x0d, 0x19, 0x9d, 0xa6, 0x54,
0xd2, 0xea, 0x59, 0x4f, 0xa1, 0x7c, 0xf6, 0xf5, 0x7f, 0x32, 0x23, 0xed,
0x72, 0xa8, 0x96, 0x17, 0x87, 0x06, 0xf2, 0xc7, 0xcd, 0xda, 0x4a, 0x10,
0xd1, 0xfd, 0xb8, 0xf1, 0xaf, 0x25, 0x55, 0x32, 0x45, 0x39, 0x95, 0xec,
0x0c, 0xa9, 0xf0, 0x47, 0x8b, 0x66, 0xe0, 0xb7, 0xa2, 0xf6, 0x35, 0x50,
0x27, 0xe7, 0x2f, 0x90, 0x35, 0x5b, 0xd5, 0x62, 0x19, 0xb4, 0x41, 0xd4,
0x52, 0xe7, 0x7f, 0x97, 0xfc, 0x5b, 0x4a, 0x5b, 0x19, 0x06, 0x65, 0x2d,
0x23, 0x29, 0x15, 0x8b, 0x05, 0xaf, 0xbe, 0xd3, 0x4a, 0x27, 0x5b, 0xc9,
0xc0, 0xd0, 0xd2, 0xba, 0x8b, 0x00, 0x7a, 0x2f, 0x39, 0xa0, 0x13, 0xb9,
0xe6, 0xf5, 0x4b, 0x21, 0x54, 0x57, 0xb3, 0xf9, 0x6c, 0x6f, 0xd0, 0x17,
0xf4, 0x50, 0x9d, 0x00, 0x00, 0x01, 0x00, 0x01, 0xf2, 0xda, 0x5f, 0xfb,
0xe2, 0xda, 0xfc, 0xe0, 0xdf, 0x3a, 0x0e, 0x14, 0x18, 0xc1, 0xd9, 0x1f,
0x43, 0xe3, 0x65, 0x3e, 0x07, 0xe7, 0x8d, 0xdc, 0x1d, 0x11, 0xc1, 0xd6,
0xc0, 0xd8, 0xda, 0x53, 0xf5, 0x04, 0x73, 0x51, 0x1b, 0x26, 0xef, 0x4e,
0xf5, 0xce, 0x3d, 0x77, 0x21, 0x94, 0xd0, 0xc7, 0xc1, 0xda, 0x19, 0x7d,
0xf8, 0xc5, 0x4c, 0xc8, 0xee, 0x7d, 0xd1, 0xbb, 0x02, 0x90, 0x2b, 0xff,
0x4e, 0x4d, 0xd7, 0x9d, 0x72, 0x0c, 0x60, 0x0f, 0x4b, 0x83, 0xf5, 0xc2,
0x26, 0xd6, 0x22, 0xb8, 0x60, 0x3a, 0xf9, 0x2f, 0x92, 0x2a, 0x2e, 0x14,
0xa7, 0x56, 0x1c, 0x56, 0x05, 0x41, 0x92, 0xac, 0xb1, 0x4e, 0x44, 0x1e,
0x70, 0x42, 0xda, 0xc7, 0xc8, 0x9c, 0xae, 0x29, 0x2d, 0x0c, 0x3a, 0xff,
0x9b, 0xb6, 0xad, 0xb4, 0xfb, 0x49, 0x28, 0x96, 0x74, 0xf5, 0x94, 0x74,
0xb7, 0x40, 0x93, 0x2b, 0x34, 0x29, 0xd2, 0x8a, 0xf3, 0x99, 0xf9, 0xe9,
0xd8, 0xcc, 0x48, 0x1d, 0x3e, 0xc1, 0x82, 0x35, 0x4f, 0xef, 0xb1, 0x81,
0x3c, 0xe1, 0xa1, 0x03, 0x65, 0xac, 0x21, 0x21, 0x40, 0x61, 0xfb, 0xd3,
0x54, 0xac, 0xa1, 0xf2, 0xf0, 0x61, 0xd9, 0x01, 0x4e, 0xc2, 0x28, 0xb1,
0x7c, 0x27, 0x6e, 0x56, 0x68, 0x69, 0x8f, 0xc5, 0xfd, 0xca, 0x39, 0x6e,
0x22, 0x09, 0xf1, 0xb4, 0xd5, 0xac, 0xb8, 0xe0, 0x1b, 0x21, 0x86, 0xf4,
0xc8, 0x15, 0xc6, 0x1f, 0x21, 0xae, 0xcb, 0xab, 0x5a, 0x09, 0x30, 0x9e,
0xdd, 0x6c, 0x38, 0x59, 0xec, 0x59, 0x3a, 0x08, 0xee, 0x46, 0x7b, 0x78,
0x23, 0xbc, 0xfc, 0xe2, 0xda, 0xe8, 0x1a, 0x65, 0xe6, 0xe0, 0x78, 0xd3,
0xb0, 0x03, 0x2e, 0xf1, 0xb8, 0xca, 0x8e, 0x90, 0x75, 0xaf, 0xf7, 0xa8,
0x48, 0xed, 0x82, 0xc9, 0xcf, 0x44, 0x56, 0xfc, 0x05, 0xfd, 0x6b, 0x00,
0x00, 0x00, 0x81, 0x00, 0xfc, 0x94, 0xdf, 0x42, 0xc7, 0x9a, 0xa2, 0xff,
0x32, 0xdf, 0x06, 0xb6, 0x4d, 0x90, 0x31, 0x28, 0x28, 0xdb, 0x03, 0xf9,
0xa6, 0xb3, 0xa2, 0x91, 0x4c, 0xdf, 0x6e, 0xf6, 0xb9, 0x44, 0x3b, 0xdd,
0x17, 0xc1, 0xc8, 0x1d, 0xd1, 0xc0, 0xc0, 0x30, 0x22, 0xbe, 0x24, 0x2e,
0x0e, 0xdf, 0xe0, 0x18, 0x37, 0x3e, 0xb8, 0x7f, 0xb2, 0x50, 0x34, 0xc4,
0x08, 0x5e, 0x69, 0x1f, 0xd5, 0xc9, 0xce, 0x47, 0x7d, 0x75, 0x5e, 0x3b,
0x87, 0xdd, 0x46, 0x35, 0x01, 0x0f, 0x17, 0x8a, 0xf1, 0xf1, 0xc4, 0xa9,
0x94, 0xa7, 0x6e, 0xce, 0x80, 0xe3, 0x17, 0x2e, 0xb0, 0xef, 0x63, 0xa7,
0x11, 0x86, 0x96, 0x4a, 0x63, 0x2d, 0x9e, 0x92, 0x62, 0x43, 0x43, 0x72,
0xa5, 0xdc, 0xa0, 0xcd, 0x19, 0x93, 0xd7, 0xe0, 0x80, 0x41, 0x27, 0xea,
0xe4, 0xe8, 0xc1, 0x91, 0x9e, 0x13, 0xb3, 0x9c, 0xd1, 0xed, 0xcb, 0xbf,
0x00, 0x00, 0x00, 0x81, 0x00, 0xb3, 0x6b, 0xee, 0xa4, 0x70, 0x4e, 0xfb,
0xf9, 0x7e, 0x2e, 0x74, 0x5d, 0x3e, 0x8b, 0x3f, 0xff, 0x8c, 0xde, 0x68,
0x38, 0xda, 0xce, 0xc0, 0x66, 0x4b, 0xca, 0x35, 0xc3, 0x97, 0xa8, 0xf0,
0x00, 0x8e, 0xb3, 0x46, 0x60, 0xd0, 0x4d, 0x7e, 0x7b, 0xdf, 0x17, 0x7b,
0x2f, 0xc4, 0x16, 0xee, 0x45, 0xdb, 0xa5, 0x5d, 0xc0, 0x72, 0xe9, 0xc6,
0x91, 0x0f, 0xd9, 0x30, 0x74, 0x6c, 0xde, 0x93, 0xb5, 0xb6, 0xaf, 0x52,
0x53, 0x3c, 0x08, 0x55, 0xea, 0xb8, 0x66, 0x07, 0xbe, 0xce, 0xf9, 0x80,
0x8d, 0xe0, 0xca, 0xdc, 0x63, 0xe8, 0x58, 0x94, 0x22, 0x4f, 0x08, 0x66,
0x13, 0x9e, 0x63, 0x2e, 0x92, 0x7a, 0xb6, 0x66, 0x94, 0x9b, 0x71, 0x66,
0xd3, 0x08, 0xc9, 0x89, 0xea, 0x78, 0x35, 0x0d, 0xf2, 0x25, 0x55, 0xd4,
0xb0, 0x9b, 0xea, 0x18, 0x77, 0xf6, 0x25, 0x02, 0xb4, 0x5e, 0x71, 0xea,
0xa3
};
unsigned int keyr_len = 805;
unsigned char keye[] = {
0x00, 0x00, 0x00, 0x13, 0x65, 0x63, 0x64, 0x73, 0x61, 0x2d, 0x73, 0x68,
0x61, 0x32, 0x2d, 0x6e, 0x69, 0x73, 0x74, 0x70, 0x32, 0x35, 0x36, 0x00,
0x00, 0x00, 0x08, 0x6e, 0x69, 0x73, 0x74, 0x70, 0x32, 0x35, 0x36, 0x00,
0x00, 0x00, 0x41, 0x04, 0x0a, 0x00, 0x6c, 0x7c, 0x1c, 0xc4, 0x03, 0x44,
0x46, 0x70, 0xba, 0x00, 0x7c, 0x79, 0x89, 0x7b, 0xc3, 0xd6, 0x32, 0x98,
0x34, 0xe7, 0x1c, 0x60, 0x04, 0x73, 0xd9, 0xb5, 0x7e, 0x94, 0x04, 0x04,
0xea, 0xc8, 0xb8, 0xfb, 0xd4, 0x70, 0x9f, 0x29, 0xa7, 0x8d, 0x9a, 0x64,
0x3a, 0x8c, 0x45, 0x23, 0x37, 0x5a, 0x2b, 0x4f, 0x54, 0x91, 0x80, 0xf1,
0xac, 0x3a, 0xf5, 0x6d, 0xfa, 0xe8, 0x76, 0x20, 0x00, 0x00, 0x00, 0x21,
0x00, 0xc2, 0xaf, 0xbe, 0xdc, 0x06, 0xff, 0x3d, 0x08, 0x9b, 0x73, 0xe0,
0x3c, 0x58, 0x28, 0x70, 0x9b, 0x23, 0x39, 0x51, 0xd7, 0xbc, 0xa7, 0x1a,
0xf5, 0xb4, 0x23, 0xd3, 0xf6, 0x17, 0xa6, 0x9c, 0x02
};
unsigned int keye_len = 141;
unsigned char keyd[] = {
0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x64, 0x73, 0x73, 0x00,
0x00, 0x00, 0x81, 0x00, 0xb0, 0x02, 0x19, 0x8b, 0xf3, 0x46, 0xf9, 0xc5,
0x47, 0x78, 0x3d, 0x7f, 0x04, 0x10, 0x0a, 0x43, 0x8e, 0x00, 0x9e, 0xa4,
0x30, 0xfd, 0x47, 0xb9, 0x05, 0x9e, 0x95, 0xaa, 0x37, 0x9a, 0x91, 0xbf,
0xf8, 0xb9, 0xe0, 0x8d, 0x97, 0x49, 0x87, 0xe2, 0xe6, 0x90, 0xc1, 0xe4,
0x61, 0x57, 0x77, 0xfd, 0x91, 0x1d, 0xe1, 0x4b, 0xa0, 0xb2, 0xbc, 0xa1,
0x6a, 0x6a, 0xdd, 0x31, 0xda, 0xe7, 0x54, 0x03, 0xfd, 0x48, 0x62, 0x8a,
0x1d, 0x1d, 0xe2, 0x26, 0x76, 0x29, 0x08, 0xab, 0x65, 0x88, 0x74, 0x02,
0x1e, 0xa9, 0x29, 0x1b, 0x69, 0x3b, 0xb4, 0x5f, 0x62, 0x80, 0xa3, 0xa6,
0x4b, 0xc3, 0x0e, 0x89, 0x24, 0xe4, 0x8a, 0x31, 0xae, 0x89, 0x7a, 0x7a,
0x58, 0x44, 0x46, 0x77, 0x62, 0x33, 0xa2, 0x5d, 0x17, 0x0e, 0x0b, 0x64,
0xee, 0x1a, 0x02, 0xbd, 0xf8, 0x27, 0x86, 0xe1, 0x87, 0x92, 0x84, 0xc7,
0x00, 0x00, 0x00, 0x15, 0x00, 0xb3, 0x8b, 0x81, 0x39, 0x9c, 0xba, 0xe1,
0x1d, 0x9a, 0x8b, 0x89, 0xb3, 0x08, 0x9b, 0x12, 0xa8, 0x7b, 0xea, 0x25,
0x8d, 0x00, 0x00, 0x00, 0x80, 0x76, 0x3f, 0x72, 0xb2, 0xef, 0xc3, 0x16,
0xd8, 0x09, 0x36, 0x23, 0x03, 0xf9, 0x5c, 0xac, 0x8b, 0x51, 0x35, 0x2e,
0x36, 0xba, 0x39, 0xd0, 0x57, 0x19, 0x4f, 0x14, 0x8b, 0xea, 0x32, 0xfc,
0x86, 0x41, 0xea, 0x85, 0x71, 0x4d, 0x52, 0x0c, 0xff, 0xc1, 0xd3, 0xd5,
0xcd, 0x2e, 0x37, 0xcc, 0xe1, 0xcc, 0x22, 0x38, 0xa8, 0x47, 0x16, 0x34,
0x3b, 0x32, 0x9c, 0x2f, 0x0f, 0xcd, 0x5f, 0x7f, 0x06, 0x64, 0x89, 0xc5,
0x02, 0x4f, 0x9a, 0x70, 0x11, 0xf0, 0xaa, 0xe1, 0x7a, 0x75, 0x49, 0x8d,
0x0f, 0x8d, 0x5b, 0x54, 0xe2, 0xe7, 0x10, 0x6e, 0xe5, 0xbd, 0xb7, 0x62,
0xf7, 0x40, 0x59, 0x39, 0x31, 0xd9, 0x13, 0x7b, 0xa3, 0xdf, 0x0d, 0x31,
0x52, 0x43, 0xe0, 0xaf, 0x19, 0x12, 0x15, 0x12, 0x34, 0x01, 0x6f, 0xcf,
0x62, 0x21, 0xe4, 0xc8, 0x34, 0x69, 0xc9, 0x85, 0xe3, 0xde, 0xd7, 0x0c,
0xac, 0x00, 0x00, 0x00, 0x80, 0x41, 0xa3, 0xc5, 0xa4, 0x89, 0x86, 0xc8,
0x17, 0xf3, 0x8e, 0x68, 0x72, 0xbe, 0x13, 0x8b, 0x63, 0xe3, 0x07, 0xe3,
0xd5, 0xa4, 0xa2, 0xd3, 0x2c, 0x2f, 0xbe, 0x16, 0x71, 0xc9, 0x79, 0x64,
0x5a, 0x1e, 0x19, 0x82, 0x07, 0xe2, 0x93, 0xda, 0x22, 0xcf, 0x6d, 0xdd,
0x38, 0xcb, 0x6e, 0x6b, 0x0f, 0x95, 0x8d, 0xfa, 0x3f, 0xbb, 0xb8, 0x6a,
0x7d, 0xc3, 0x22, 0x1e, 0x49, 0xcf, 0x98, 0x73, 0x05, 0x5d, 0x97, 0xfa,
0x4c, 0xf2, 0x82, 0x3d, 0x98, 0x61, 0x4e, 0x96, 0x80, 0x26, 0x79, 0xda,
0x24, 0xf8, 0xa1, 0x9c, 0x71, 0x82, 0xe6, 0xc7, 0xdc, 0xc2, 0xa5, 0xd0,
0xf4, 0x36, 0xba, 0xaa, 0xee, 0xd3, 0x43, 0x46, 0x1d, 0xaa, 0x53, 0xea,
0x85, 0x2c, 0x1b, 0xc8, 0x7c, 0x3c, 0xe7, 0x06, 0x44, 0xab, 0x16, 0xad,
0xc6, 0x54, 0x91, 0x9a, 0xb9, 0xc0, 0xeb, 0x93, 0x8c, 0xca, 0x39, 0xcf,
0x6f, 0x00, 0x00, 0x00, 0x15, 0x00, 0x90, 0x26, 0x0a, 0xfc, 0x15, 0x99,
0x7b, 0xac, 0xaa, 0x0c, 0xa2, 0xca, 0x7b, 0xa8, 0xd4, 0xdf, 0x68, 0x56,
0xf9, 0x39
};
unsigned int keyd_len = 458;
unsigned char keyed25519[] = {
0x00, 0x00, 0x00, 0x0b, 0x73, 0x73, 0x68, 0x2d, 0x65, 0x64, 0x32, 0x35,
0x35, 0x31, 0x39, 0x00, 0x00, 0x00, 0x40, 0x10, 0xb3, 0x79, 0x06, 0xe5,
0x9b, 0xe7, 0xe4, 0x6e, 0xec, 0xfe, 0xa5, 0x39, 0x21, 0x7c, 0xf6, 0x66,
0x8c, 0x0b, 0x6a, 0x01, 0x09, 0x05, 0xc7, 0x4f, 0x64, 0xa8, 0x24, 0xd2,
0x8d, 0xbd, 0xdd, 0xc6, 0x3c, 0x99, 0x1b, 0x2d, 0x3e, 0x33, 0x90, 0x19,
0xa4, 0xd5, 0xe9, 0x23, 0xfe, 0x8e, 0xd6, 0xd4, 0xf9, 0xb1, 0x11, 0x69,
0x7c, 0x57, 0x52, 0x0e, 0x41, 0xdb, 0x1b, 0x12, 0x87, 0xfa, 0xc9
};
unsigned int keyed25519_len = 83;

246
fuzz-wrapfd.c Normal file
View File

@@ -0,0 +1,246 @@
#define FUZZ_SKIP_WRAP 1
#include "includes.h"
#include "fuzz-wrapfd.h"
#include "dbutil.h"
#include "fuzz.h"
#define IOWRAP_MAXFD (FD_SETSIZE-1)
static const int MAX_RANDOM_IN = 50000;
static const double CHANCE_CLOSE = 1.0 / 600;
static const double CHANCE_INTR = 1.0 / 900;
static const double CHANCE_READ1 = 0.96;
static const double CHANCE_READ2 = 0.5;
static const double CHANCE_WRITE1 = 0.96;
static const double CHANCE_WRITE2 = 0.5;
struct fdwrap {
enum wrapfd_mode mode;
buffer *buf;
int closein;
int closeout;
};
static struct fdwrap wrap_fds[IOWRAP_MAXFD+1];
/* for quick selection of in-use descriptors */
static int wrap_used[IOWRAP_MAXFD+1];
static unsigned int nused;
static unsigned short rand_state[3];
void wrapfd_setup(void) {
TRACE(("wrapfd_setup"))
nused = 0;
memset(wrap_fds, 0x0, sizeof(wrap_fds));
memset(wrap_used, 0x0, sizeof(wrap_used));
memset(rand_state, 0x0, sizeof(rand_state));
wrapfd_setseed(50);
}
void wrapfd_setseed(uint32_t seed) {
memcpy(rand_state, &seed, sizeof(seed));
nrand48(rand_state);
}
void wrapfd_add(int fd, buffer *buf, enum wrapfd_mode mode) {
TRACE(("wrapfd_add %d buf %p mode %d", fd, buf, mode))
assert(fd >= 0);
assert(fd <= IOWRAP_MAXFD);
assert(wrap_fds[fd].mode == UNUSED);
assert(buf || mode == RANDOMIN);
wrap_fds[fd].mode = mode;
wrap_fds[fd].buf = buf;
wrap_fds[fd].closein = 0;
wrap_fds[fd].closeout = 0;
wrap_used[nused] = fd;
nused++;
}
void wrapfd_remove(int fd) {
unsigned int i, j;
TRACE(("wrapfd_remove %d", fd))
assert(fd >= 0);
assert(fd <= IOWRAP_MAXFD);
assert(wrap_fds[fd].mode != UNUSED);
wrap_fds[fd].mode = UNUSED;
/* remove from used list */
for (i = 0, j = 0; i < nused; i++) {
if (wrap_used[i] != fd) {
wrap_used[j] = wrap_used[i];
j++;
}
}
nused--;
}
int wrapfd_close(int fd) {
if (fd >= 0 && fd <= IOWRAP_MAXFD && wrap_fds[fd].mode != UNUSED) {
wrapfd_remove(fd);
return 0;
} else {
return close(fd);
}
}
int wrapfd_read(int fd, void *out, size_t count) {
size_t maxread;
buffer *buf;
if (!fuzz.wrapfds) {
return read(fd, out, count);
}
if (fd < 0 || fd > IOWRAP_MAXFD || wrap_fds[fd].mode == UNUSED) {
/* XXX - assertion failure? */
TRACE(("Bad read descriptor %d\n", fd))
errno = EBADF;
return -1;
}
assert(count != 0);
if (wrap_fds[fd].closein || erand48(rand_state) < CHANCE_CLOSE) {
wrap_fds[fd].closein = 1;
errno = ECONNRESET;
return -1;
}
if (erand48(rand_state) < CHANCE_INTR) {
errno = EINTR;
return -1;
}
buf = wrap_fds[fd].buf;
if (buf) {
maxread = MIN(buf->len - buf->pos, count);
/* returns 0 if buf is EOF, as intended */
if (maxread > 0) {
maxread = nrand48(rand_state) % maxread + 1;
}
memcpy(out, buf_getptr(buf, maxread), maxread);
buf_incrpos(buf, maxread);
return maxread;
}
maxread = MIN(MAX_RANDOM_IN, count);
maxread = nrand48(rand_state) % maxread + 1;
memset(out, 0xef, maxread);
return maxread;
}
int wrapfd_write(int fd, const void* in, size_t count) {
unsigned const volatile char* volin = in;
unsigned int i;
if (!fuzz.wrapfds) {
return write(fd, in, count);
}
if (fd < 0 || fd > IOWRAP_MAXFD || wrap_fds[fd].mode == UNUSED) {
/* XXX - assertion failure? */
TRACE(("Bad read descriptor %d\n", fd))
errno = EBADF;
return -1;
}
assert(count != 0);
/* force read to exercise sanitisers */
for (i = 0; i < count; i++) {
(void)volin[i];
}
if (wrap_fds[fd].closeout || erand48(rand_state) < CHANCE_CLOSE) {
wrap_fds[fd].closeout = 1;
errno = ECONNRESET;
return -1;
}
if (erand48(rand_state) < CHANCE_INTR) {
errno = EINTR;
return -1;
}
return nrand48(rand_state) % (count+1);
}
int wrapfd_select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout) {
int i, nset, sel;
int ret = 0;
int fdlist[IOWRAP_MAXFD+1];
memset(fdlist, 0x0, sizeof(fdlist));
if (!fuzz.wrapfds) {
return select(nfds, readfds, writefds, exceptfds, timeout);
}
assert(nfds <= IOWRAP_MAXFD+1);
if (erand48(rand_state) < CHANCE_INTR) {
errno = EINTR;
return -1;
}
/* read */
if (readfds != NULL && erand48(rand_state) < CHANCE_READ1) {
for (i = 0, nset = 0; i < nfds; i++) {
if (FD_ISSET(i, readfds)) {
assert(wrap_fds[i].mode != UNUSED);
fdlist[nset] = i;
nset++;
}
}
DROPBEAR_FD_ZERO(readfds);
if (nset > 0) {
/* set one */
sel = fdlist[nrand48(rand_state) % nset];
FD_SET(sel, readfds);
ret++;
if (erand48(rand_state) < CHANCE_READ2) {
sel = fdlist[nrand48(rand_state) % nset];
if (!FD_ISSET(sel, readfds)) {
FD_SET(sel, readfds);
ret++;
}
}
}
}
/* write */
if (writefds != NULL && erand48(rand_state) < CHANCE_WRITE1) {
for (i = 0, nset = 0; i < nfds; i++) {
if (FD_ISSET(i, writefds)) {
assert(wrap_fds[i].mode != UNUSED);
fdlist[nset] = i;
nset++;
}
}
DROPBEAR_FD_ZERO(writefds);
/* set one */
if (nset > 0) {
sel = fdlist[nrand48(rand_state) % nset];
FD_SET(sel, writefds);
ret++;
if (erand48(rand_state) < CHANCE_WRITE2) {
sel = fdlist[nrand48(rand_state) % nset];
if (!FD_ISSET(sel, writefds)) {
FD_SET(sel, writefds);
ret++;
}
}
}
}
return ret;
}

25
fuzz-wrapfd.h Normal file
View File

@@ -0,0 +1,25 @@
#ifndef FUZZ_WRAPFD_H
#define FUZZ_WRAPFD_H
#include "buffer.h"
enum wrapfd_mode {
UNUSED = 0,
PLAIN,
INPROGRESS,
RANDOMIN
};
void wrapfd_setup(void);
void wrapfd_setseed(uint32_t seed);
// doesn't take ownership of buf. buf is optional.
void wrapfd_add(int fd, buffer *buf, enum wrapfd_mode mode);
// called via #defines for read/write/select
int wrapfd_read(int fd, void *out, size_t count);
int wrapfd_write(int fd, const void* in, size_t count);
int wrapfd_select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
int wrapfd_close(int fd);
#endif // FUZZ_WRAPFD_H

72
fuzz.h Normal file
View File

@@ -0,0 +1,72 @@
#ifndef DROPBEAR_FUZZ_H
#define DROPBEAR_FUZZ_H
#include "config.h"
#if DROPBEAR_FUZZ
#include "includes.h"
#include "buffer.h"
#include "algo.h"
#include "fuzz-wrapfd.h"
// once per process
void fuzz_common_setup(void);
void fuzz_svr_setup(void);
// must be called once per fuzz iteration.
// returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE
int fuzz_set_input(const uint8_t *Data, size_t Size);
int fuzz_run_preauth(const uint8_t *Data, size_t Size, int skip_kexmaths);
const void* fuzz_get_algo(const algo_type *algos, const char* name);
// fuzzer functions that intrude into general code
void fuzz_kex_fakealgos(void);
int fuzz_checkpubkey_line(buffer* line, int line_num, char* filename,
const char* algo, unsigned int algolen,
const unsigned char* keyblob, unsigned int keybloblen);
extern const char * const * fuzz_signkey_names;
void fuzz_seed(void);
void fuzz_get_socket_address(int fd, char **local_host, char **local_port,
char **remote_host, char **remote_port, int host_lookup);
void fuzz_fake_send_kexdh_reply(void);
// fake IO wrappers
#ifndef FUZZ_SKIP_WRAP
#define select(nfds, readfds, writefds, exceptfds, timeout) \
wrapfd_select(nfds, readfds, writefds, exceptfds, timeout)
#define write(fd, buf, count) wrapfd_write(fd, buf, count)
#define read(fd, buf, count) wrapfd_read(fd, buf, count)
#define close(fd) wrapfd_close(fd)
#endif // FUZZ_SKIP_WRAP
struct dropbear_fuzz_options {
int fuzzing;
// fuzzing input
buffer *input;
struct dropbear_cipher recv_cipher;
struct dropbear_hash recv_mac;
int wrapfds;
// whether to skip slow bignum maths
int skip_kexmaths;
// dropbear_exit() jumps back
int do_jmp;
sigjmp_buf jmp;
uid_t pw_uid;
gid_t pw_gid;
char* pw_name;
char* pw_dir;
char* pw_shell;
char* pw_passwd;
};
extern struct dropbear_fuzz_options fuzz;
#endif // DROPBEAR_FUZZ
#endif /* DROPBEAR_FUZZ_H */

72
fuzzer-kexcurve25519.c Normal file
View File

@@ -0,0 +1,72 @@
#include "fuzz.h"
#include "session.h"
#include "fuzz-wrapfd.h"
#include "debug.h"
#include "runopts.h"
#include "algo.h"
#include "bignum.h"
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
static int once = 0;
static struct key_context* keep_newkeys = NULL;
/* number of generated parameters is limited by the timeout for the first run.
TODO move this to the libfuzzer initialiser function instead if the timeout
doesn't apply there */
#define NUM_PARAMS 20
static struct kex_curve25519_param *curve25519_params[NUM_PARAMS];
if (!once) {
fuzz_common_setup();
fuzz_svr_setup();
keep_newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
keep_newkeys->algo_kex = fuzz_get_algo(sshkex, "curve25519-sha256");
keep_newkeys->algo_hostkey = DROPBEAR_SIGNKEY_ED25519;
ses.newkeys = keep_newkeys;
/* Pre-generate parameters */
int i;
for (i = 0; i < NUM_PARAMS; i++) {
curve25519_params[i] = gen_kexcurve25519_param();
}
once = 1;
}
if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
return 0;
}
m_malloc_set_epoch(1);
if (setjmp(fuzz.jmp) == 0) {
/* Based on recv_msg_kexdh_init()/send_msg_kexdh_reply()
with DROPBEAR_KEX_CURVE25519 */
ses.newkeys = keep_newkeys;
/* Choose from the collection of curve25519 params */
unsigned int e = buf_getint(fuzz.input);
struct kex_curve25519_param *curve25519_param = curve25519_params[e % NUM_PARAMS];
buffer * ecdh_qs = buf_getstringbuf(fuzz.input);
ses.kexhashbuf = buf_new(KEXHASHBUF_MAX_INTS);
kexcurve25519_comb_key(curve25519_param, ecdh_qs, svr_opts.hostkey);
mp_clear(ses.dh_K);
m_free(ses.dh_K);
buf_free(ecdh_qs);
buf_free(ses.hash);
buf_free(ses.session_id);
/* kexhashbuf is freed in kexdh_comb_key */
m_malloc_free_epoch(1, 0);
} else {
m_malloc_free_epoch(1, 1);
TRACE(("dropbear_exit longjmped"))
/* dropbear_exit jumped here */
}
return 0;
}

76
fuzzer-kexdh.c Normal file
View File

@@ -0,0 +1,76 @@
#include "fuzz.h"
#include "session.h"
#include "fuzz-wrapfd.h"
#include "debug.h"
#include "runopts.h"
#include "algo.h"
#include "bignum.h"
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
static int once = 0;
static struct key_context* keep_newkeys = NULL;
/* number of generated parameters is limited by the timeout for the first run.
TODO move this to the libfuzzer initialiser function instead if the timeout
doesn't apply there */
#define NUM_PARAMS 20
static struct kex_dh_param *dh_params[NUM_PARAMS];
if (!once) {
fuzz_common_setup();
fuzz_svr_setup();
keep_newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
keep_newkeys->algo_kex = fuzz_get_algo(sshkex, "diffie-hellman-group14-sha256");
keep_newkeys->algo_hostkey = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
ses.newkeys = keep_newkeys;
/* Pre-generate parameters */
int i;
for (i = 0; i < NUM_PARAMS; i++) {
dh_params[i] = gen_kexdh_param();
}
once = 1;
}
if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
return 0;
}
m_malloc_set_epoch(1);
if (setjmp(fuzz.jmp) == 0) {
/* Based on recv_msg_kexdh_init()/send_msg_kexdh_reply()
with DROPBEAR_KEX_NORMAL_DH */
ses.newkeys = keep_newkeys;
/* Choose from the collection of ecdh params */
unsigned int e = buf_getint(fuzz.input);
struct kex_dh_param * dh_param = dh_params[e % NUM_PARAMS];
DEF_MP_INT(dh_e);
m_mp_init(&dh_e);
if (buf_getmpint(fuzz.input, &dh_e) != DROPBEAR_SUCCESS) {
dropbear_exit("Bad kex value");
}
ses.kexhashbuf = buf_new(KEXHASHBUF_MAX_INTS);
kexdh_comb_key(dh_param, &dh_e, svr_opts.hostkey);
mp_clear(ses.dh_K);
m_free(ses.dh_K);
mp_clear(&dh_e);
buf_free(ses.hash);
buf_free(ses.session_id);
/* kexhashbuf is freed in kexdh_comb_key */
m_malloc_free_epoch(1, 0);
} else {
m_malloc_free_epoch(1, 1);
TRACE(("dropbear_exit longjmped"))
/* dropbear_exit jumped here */
}
return 0;
}

82
fuzzer-kexecdh.c Normal file
View File

@@ -0,0 +1,82 @@
#include "fuzz.h"
#include "session.h"
#include "fuzz-wrapfd.h"
#include "debug.h"
#include "runopts.h"
#include "algo.h"
#include "bignum.h"
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
static int once = 0;
static const struct dropbear_kex *ecdh[3]; /* 256, 384, 521 */
static struct key_context* keep_newkeys = NULL;
/* number of generated parameters is limited by the timeout for the first run */
#define NUM_PARAMS 80
static struct kex_ecdh_param *ecdh_params[NUM_PARAMS];
if (!once) {
fuzz_common_setup();
fuzz_svr_setup();
/* ses gets zeroed by fuzz_set_input */
keep_newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
ecdh[0] = fuzz_get_algo(sshkex, "ecdh-sha2-nistp256");
ecdh[1] = fuzz_get_algo(sshkex, "ecdh-sha2-nistp384");
ecdh[2] = fuzz_get_algo(sshkex, "ecdh-sha2-nistp521");
assert(ecdh[0]);
assert(ecdh[1]);
assert(ecdh[2]);
keep_newkeys->algo_hostkey = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
ses.newkeys = keep_newkeys;
/* Pre-generate parameters */
int i;
for (i = 0; i < NUM_PARAMS; i++) {
ses.newkeys->algo_kex = ecdh[i % 3];
ecdh_params[i] = gen_kexecdh_param();
}
once = 1;
}
if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
return 0;
}
m_malloc_set_epoch(1);
if (setjmp(fuzz.jmp) == 0) {
/* Based on recv_msg_kexdh_init()/send_msg_kexdh_reply()
with DROPBEAR_KEX_ECDH */
ses.newkeys = keep_newkeys;
/* random choice of ecdh 256, 384, 521 */
unsigned char b = buf_getbyte(fuzz.input);
ses.newkeys->algo_kex = ecdh[b % 3];
/* Choose from the collection of ecdh params */
unsigned int e = buf_getint(fuzz.input);
struct kex_ecdh_param *ecdh_param = ecdh_params[e % NUM_PARAMS];
buffer * ecdh_qs = buf_getstringbuf(fuzz.input);
ses.kexhashbuf = buf_new(KEXHASHBUF_MAX_INTS);
kexecdh_comb_key(ecdh_param, ecdh_qs, svr_opts.hostkey);
mp_clear(ses.dh_K);
m_free(ses.dh_K);
buf_free(ecdh_qs);
buf_free(ses.hash);
buf_free(ses.session_id);
/* kexhashbuf is freed in kexdh_comb_key */
m_malloc_free_epoch(1, 0);
} else {
m_malloc_free_epoch(1, 1);
TRACE(("dropbear_exit longjmped"))
/* dropbear_exit jumped here */
}
return 0;
}

6
fuzzer-preauth.c Normal file
View File

@@ -0,0 +1,6 @@
#include "fuzz.h"
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
return fuzz_run_preauth(Data, Size, 0);
}

6
fuzzer-preauth_nomaths.c Normal file
View File

@@ -0,0 +1,6 @@
#include "fuzz.h"
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
return fuzz_run_preauth(Data, Size, 1);
}

54
fuzzer-pubkey.c Normal file
View File

@@ -0,0 +1,54 @@
#include "fuzz.h"
#include "session.h"
#include "fuzz-wrapfd.h"
#include "debug.h"
static void setup_fuzzer(void) {
fuzz_common_setup();
}
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
static int once = 0;
if (!once) {
setup_fuzzer();
once = 1;
}
if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
return 0;
}
m_malloc_set_epoch(1);
if (setjmp(fuzz.jmp) == 0) {
buffer *line = buf_getstringbuf(fuzz.input);
buffer *keyblob = buf_getstringbuf(fuzz.input);
unsigned int algolen;
char* algoname = buf_getstring(keyblob, &algolen);
if (signature_type_from_name(algoname, algolen) == DROPBEAR_SIGNKEY_NONE) {
dropbear_exit("fuzzer imagined a bogus algorithm");
}
int ret = fuzz_checkpubkey_line(line, 5, "/home/me/authorized_keys",
algoname, algolen,
keyblob->data, keyblob->len);
if (ret == DROPBEAR_SUCCESS) {
/* fuzz_checkpubkey_line() should have cleaned up for failure */
svr_pubkey_options_cleanup();
}
buf_free(line);
buf_free(keyblob);
m_free(algoname);
m_malloc_free_epoch(1, 0);
} else {
m_malloc_free_epoch(1, 1);
TRACE(("dropbear_exit longjmped"))
/* dropbear_exit jumped here */
}
return 0;
}

79
fuzzer-verify.c Normal file
View File

@@ -0,0 +1,79 @@
#include "fuzz.h"
#include "session.h"
#include "fuzz-wrapfd.h"
#include "debug.h"
#include "dss.h"
static void setup_fuzzer(void) {
fuzz_common_setup();
}
static buffer *verifydata;
/* Tests reading a public key and verifying a signature */
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
static int once = 0;
if (!once) {
setup_fuzzer();
verifydata = buf_new(30);
buf_putstring(verifydata, "x", 1);
once = 1;
}
if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
return 0;
}
m_malloc_set_epoch(1);
if (setjmp(fuzz.jmp) == 0) {
sign_key *key = new_sign_key();
enum signkey_type keytype = DROPBEAR_SIGNKEY_ANY;
if (buf_get_pub_key(fuzz.input, key, &keytype) == DROPBEAR_SUCCESS) {
enum signature_type sigtype;
if (keytype == DROPBEAR_SIGNKEY_RSA) {
/* Flip a coin to decide rsa signature type */
int flag = buf_getbyte(fuzz.input);
if (flag & 0x01) {
sigtype = DROPBEAR_SIGNATURE_RSA_SHA256;
} else {
sigtype = DROPBEAR_SIGNATURE_RSA_SHA1;
}
} else {
sigtype = signature_type_from_signkey(keytype);
}
if (buf_verify(fuzz.input, key, sigtype, verifydata) == DROPBEAR_SUCCESS) {
/* The fuzzer is capable of generating keys with a signature to match.
We don't want false positives if the key is bogus, since a client/server
wouldn't be trusting a bogus key anyway */
int boguskey = 0;
if (keytype == DROPBEAR_SIGNKEY_DSS) {
/* So far have seen dss keys with bad p/q/g domain parameters */
int pprime, qprime, trials;
trials = mp_prime_rabin_miller_trials(mp_count_bits(key->dsskey->p));
assert(mp_prime_is_prime(key->dsskey->p, trials, &pprime) == MP_OKAY);
trials = mp_prime_rabin_miller_trials(mp_count_bits(key->dsskey->q));
assert(mp_prime_is_prime(key->dsskey->q, trials, &qprime) == MP_OKAY);
boguskey = !(pprime && qprime);
/* Could also check g**q mod p == 1 */
}
if (!boguskey) {
printf("Random key/signature managed to verify!\n");
abort();
}
}
}
sign_key_free(key);
m_malloc_free_epoch(1, 0);
} else {
m_malloc_free_epoch(1, 1);
TRACE(("dropbear_exit longjmped"))
/* dropbear_exit jumped here */
}
return 0;
}

12
fuzzers_test.sh Executable file
View File

@@ -0,0 +1,12 @@
#!/bin/sh
# runs fuzz corpus with standalone fuzzers
result=0
test -d fuzzcorpus && hg --repository fuzzcorpus/ pull || hg clone https://secure.ucc.asn.au/hg/dropbear-fuzzcorpus fuzzcorpus || exit 1
for f in `make list-fuzz-targets`; do
./$f fuzzcorpus/$f/* || result=1
done
exit $result

120
gcm.c Normal file
View File

@@ -0,0 +1,120 @@
/*
* Dropbear SSH
*
* Copyright (c) 2002,2003 Matt Johnston
* Copyright (c) 2020 by Vladislav Grishenko
* 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 "algo.h"
#include "dbutil.h"
#include "gcm.h"
#if DROPBEAR_ENABLE_GCM_MODE
#define GHASH_LEN 16
static const struct dropbear_hash dropbear_ghash =
{NULL, 0, GHASH_LEN};
static int dropbear_gcm_start(int cipher, const unsigned char *IV,
const unsigned char *key, int keylen,
int UNUSED(num_rounds), dropbear_gcm_state *state) {
int err;
TRACE2(("enter dropbear_gcm_start"))
if ((err = gcm_init(&state->gcm, cipher, key, keylen)) != CRYPT_OK) {
return err;
}
memcpy(state->iv, IV, GCM_NONCE_LEN);
TRACE2(("leave dropbear_gcm_start"))
return CRYPT_OK;
}
static int dropbear_gcm_crypt(unsigned int UNUSED(seq),
const unsigned char *in, unsigned char *out,
unsigned long len, unsigned long taglen,
dropbear_gcm_state *state, int direction) {
unsigned char *iv, tag[GHASH_LEN];
int i, err;
TRACE2(("enter dropbear_gcm_crypt"))
if (len < 4 || taglen != GHASH_LEN) {
return CRYPT_ERROR;
}
gcm_reset(&state->gcm);
if ((err = gcm_add_iv(&state->gcm,
state->iv, GCM_NONCE_LEN)) != CRYPT_OK) {
return err;
}
if ((err = gcm_add_aad(&state->gcm, in, 4)) != CRYPT_OK) {
return err;
}
if ((err = gcm_process(&state->gcm, (unsigned char *) in + 4,
len - 4, out + 4, direction)) != CRYPT_OK) {
return err;
}
if (direction == LTC_ENCRYPT) {
gcm_done(&state->gcm, out + len, &taglen);
} else {
gcm_done(&state->gcm, tag, &taglen);
if (constant_time_memcmp(in + len, tag, taglen) != 0) {
return CRYPT_ERROR;
}
}
/* increment invocation counter */
iv = state->iv + GCM_IVFIX_LEN;
for (i = GCM_IVCTR_LEN - 1; i >= 0 && ++iv[i] == 0; i--);
TRACE2(("leave dropbear_gcm_crypt"))
return CRYPT_OK;
}
static int dropbear_gcm_getlength(unsigned int UNUSED(seq),
const unsigned char *in, unsigned int *outlen,
unsigned long len, dropbear_gcm_state* UNUSED(state)) {
TRACE2(("enter dropbear_gcm_getlength"))
if (len < 4) {
return CRYPT_ERROR;
}
LOAD32H(*outlen, in);
TRACE2(("leave dropbear_gcm_getlength"))
return CRYPT_OK;
}
const struct dropbear_cipher_mode dropbear_mode_gcm =
{(void *)dropbear_gcm_start, NULL, NULL,
(void *)dropbear_gcm_crypt,
(void *)dropbear_gcm_getlength, &dropbear_ghash};
#endif /* DROPBEAR_ENABLE_GCM_MODE */

47
gcm.h Normal file
View File

@@ -0,0 +1,47 @@
/*
* Dropbear SSH
*
* Copyright (c) 2002,2003 Matt Johnston
* Copyright (c) 2020 by Vladislav Grishenko
* 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. */
#ifndef DROPBEAR_DROPBEAR_GCM_H_
#define DROPBEAR_DROPBEAR_GCM_H_
#include "includes.h"
#include "algo.h"
#if DROPBEAR_ENABLE_GCM_MODE
#define GCM_IVFIX_LEN 4
#define GCM_IVCTR_LEN 8
#define GCM_NONCE_LEN (GCM_IVFIX_LEN + GCM_IVCTR_LEN)
typedef struct {
gcm_state gcm;
unsigned char iv[GCM_NONCE_LEN];
} dropbear_gcm_state;
extern const struct dropbear_cipher_mode dropbear_mode_gcm;
#endif /* DROPBEAR_ENABLE_GCM_MODE */
#endif /* DROPBEAR_DROPBEAR_GCM_H_ */

View File

@@ -35,13 +35,13 @@
/* This is just a test */
#ifdef DROPBEAR_DSS
#if DROPBEAR_DSS
static void getq(dropbear_dss_key *key);
static void getp(dropbear_dss_key *key, unsigned int size);
static void getg(dropbear_dss_key *key);
static void getx(dropbear_dss_key *key);
static void gety(dropbear_dss_key *key);
static void getq(const dropbear_dss_key *key);
static void getp(const dropbear_dss_key *key, unsigned int size);
static void getg(const dropbear_dss_key *key);
static void getx(const dropbear_dss_key *key);
static void gety(const dropbear_dss_key *key);
dropbear_dss_key * gen_dss_priv_key(unsigned int size) {
@@ -65,9 +65,10 @@ dropbear_dss_key * gen_dss_priv_key(unsigned int size) {
}
static void getq(dropbear_dss_key *key) {
static void getq(const dropbear_dss_key *key) {
unsigned char buf[QSIZE];
int trials;
/* 160 bit prime */
genrandom(buf, QSIZE);
@@ -76,20 +77,21 @@ static void getq(dropbear_dss_key *key) {
bytes_to_mp(key->q, buf, QSIZE);
/* 18 rounds are required according to HAC */
if (mp_prime_next_prime(key->q, 18, 0) != MP_OKAY) {
/* ask FIPS 186.4 how many Rabin-Miller trials are required */
trials = mp_prime_rabin_miller_trials(mp_count_bits(key->q));
if (mp_prime_next_prime(key->q, trials, 0) != MP_OKAY) {
fprintf(stderr, "DSS key generation failed\n");
exit(1);
}
}
static void getp(dropbear_dss_key *key, unsigned int size) {
static void getp(const dropbear_dss_key *key, unsigned int size) {
DEF_MP_INT(tempX);
DEF_MP_INT(tempC);
DEF_MP_INT(tempP);
DEF_MP_INT(temp2q);
int result;
int result, trials;
unsigned char *buf;
m_mp_init_multi(&tempX, &tempC, &tempP, &temp2q, NULL);
@@ -129,9 +131,10 @@ static void getp(dropbear_dss_key *key, unsigned int size) {
exit(1);
}
/* now check for prime, 5 rounds is enough according to HAC */
/* ask FIPS 186.4 how many Rabin-Miller trials are required */
trials = mp_prime_rabin_miller_trials(mp_count_bits(key->p));
/* result == 1 => p is prime */
if (mp_prime_is_prime(key->p, 5, &result) != MP_OKAY) {
if (mp_prime_is_prime(key->p, trials, &result) != MP_OKAY) {
fprintf(stderr, "DSS key generation failed\n");
exit(1);
}
@@ -142,7 +145,7 @@ static void getp(dropbear_dss_key *key, unsigned int size) {
m_free(buf);
}
static void getg(dropbear_dss_key * key) {
static void getg(const dropbear_dss_key * key) {
DEF_MP_INT(div);
DEF_MP_INT(h);
@@ -179,12 +182,12 @@ static void getg(dropbear_dss_key * key) {
mp_clear_multi(&div, &h, &val, NULL);
}
static void getx(dropbear_dss_key *key) {
static void getx(const dropbear_dss_key *key) {
gen_random_mpint(key->q, key->x);
}
static void gety(dropbear_dss_key *key) {
static void gety(const dropbear_dss_key *key) {
if (mp_exptmod(key->g, key->x, key->p, key->y) != MP_OKAY) {
fprintf(stderr, "DSS key generation failed\n");

View File

@@ -27,7 +27,7 @@
#include "dss.h"
#ifdef DROPBEAR_DSS
#if DROPBEAR_DSS
dropbear_dss_key * gen_dss_priv_key(unsigned int size);

47
gened25519.c Normal file
View File

@@ -0,0 +1,47 @@
/*
* Dropbear - a SSH2 server
*
* Copyright (c) 2002,2003 Matt Johnston
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#include "includes.h"
#include "dbutil.h"
#include "dbrandom.h"
#include "curve25519.h"
#include "gened25519.h"
#if DROPBEAR_ED25519
dropbear_ed25519_key * gen_ed25519_priv_key(unsigned int size) {
dropbear_ed25519_key *key;
if (size != 256) {
dropbear_exit("Ed25519 keys have a fixed size of 256 bits");
}
key = m_malloc(sizeof(*key));
dropbear_ed25519_make_key(key->pub, key->priv);
return key;
}
#endif /* DROPBEAR_ED25519 */

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