mirror of
https://github.com/clearml/dropbear
synced 2025-06-26 18:17:32 +00:00
Compare commits
428 Commits
libtommath
...
maemo-0.52
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8deab76383 | ||
|
|
3dbc707820 | ||
|
|
5a2dde814d | ||
|
|
4fc5a52850 | ||
|
|
d005aa139e | ||
|
|
5efdd391eb | ||
|
|
adc4d0194f | ||
|
|
e80f8e8c09 | ||
|
|
1fdfa2ecfd | ||
|
|
51dcfc06dc | ||
|
|
8edc0c2afc | ||
|
|
ebc3a3ac74 | ||
|
|
5cd6995fb5 | ||
|
|
ed79abed76 | ||
|
|
c2bd79131a | ||
|
|
511f6555c9 | ||
|
|
049fcf1ac5 | ||
|
|
90f8c1fd51 | ||
|
|
729aa017d3 | ||
|
|
efe45cddbe | ||
|
|
6fe6393acb | ||
|
|
b98d13effb | ||
|
|
299d26dab7 | ||
|
|
643626d546 | ||
|
|
e1a8bf0240 | ||
|
|
d54f38caf2 | ||
|
|
d981ff2c8d | ||
|
|
bece6ddcc2 | ||
|
|
f4aacaa74c | ||
|
|
66e2f59c7b | ||
|
|
af00c78e21 | ||
|
|
c7bd9ccd85 | ||
|
|
e44aa503f0 | ||
|
|
12929e8cf0 | ||
|
|
7ac24b10b9 | ||
|
|
d7c1e58217 | ||
|
|
b619e88f54 | ||
|
|
1c72a35ddb | ||
|
|
460bf43822 | ||
|
|
31fa5e605b | ||
|
|
c0ce2a6a97 | ||
|
|
f90f64b5c1 | ||
|
|
96bda2af8e | ||
|
|
a97603d003 | ||
|
|
77892be79c | ||
|
|
3e29368cbc | ||
|
|
b91874cedc | ||
|
|
acd18ce243 | ||
|
|
6c9d2abc75 | ||
|
|
e277059339 | ||
|
|
a3b5d3c8b3 | ||
|
|
bb0548b3b0 | ||
|
|
b2ac4eb29b | ||
|
|
25554bc331 | ||
|
|
a018260fe9 | ||
|
|
9a2cdc299f | ||
|
|
58296a95f1 | ||
|
|
ddb61adcc9 | ||
|
|
790cdadace | ||
|
|
75ec4d6510 | ||
|
|
a7649c250f | ||
|
|
57ae0bfedf | ||
|
|
993f58900d | ||
|
|
876e7b99d4 | ||
|
|
e3e4445dc1 | ||
|
|
2d4d9627a2 | ||
|
|
762e9973ff | ||
|
|
b04e2d14ef | ||
|
|
456b500902 | ||
|
|
0b72cf1ed2 | ||
|
|
4639844208 | ||
|
|
77c33e7750 | ||
|
|
a4130263bd | ||
|
|
0ffc17e481 | ||
|
|
62d792fbdc | ||
|
|
7aefd496f1 | ||
|
|
70a2281823 | ||
|
|
c077f22fb4 | ||
|
|
b01a74a9d7 | ||
|
|
66643fa5c7 | ||
|
|
7f12251fbb | ||
|
|
41fd735d4b | ||
|
|
4941c43429 | ||
|
|
f5e9b12b60 | ||
|
|
6c081b4e7c | ||
|
|
769076f2ae | ||
|
|
7c1d4d1903 | ||
|
|
c3941698cd | ||
|
|
47e76de56a | ||
|
|
519ff96bcd | ||
|
|
22440a6fb2 | ||
|
|
164ea75fa6 | ||
|
|
4c8797c9ac | ||
|
|
433d5511e1 | ||
|
|
674b4d013d | ||
|
|
cd0a08896c | ||
|
|
fc0e723805 | ||
|
|
f5ad5c1553 | ||
|
|
cda7af7ca2 | ||
|
|
d199e0b119 | ||
|
|
b121787336 | ||
|
|
e9bc9e6bd7 | ||
|
|
55ed5531b5 | ||
|
|
fd304d763a | ||
|
|
60d4cd5996 | ||
|
|
16517e6760 | ||
|
|
d2f292b3ad | ||
|
|
d4bc0aec5d | ||
|
|
d0533106a8 | ||
|
|
28f1026de8 | ||
|
|
85f22c9f09 | ||
|
|
0f707bad11 | ||
|
|
ede9a990f4 | ||
|
|
4eb0f51e42 | ||
|
|
d9aeb2773e | ||
|
|
c5fd7dd554 | ||
|
|
5acf7a6aaa | ||
|
|
5092e30605 | ||
|
|
41bfa93058 | ||
|
|
056b92bd4c | ||
|
|
4a5208512b | ||
|
|
c88f3eb2a4 | ||
|
|
943636c3e1 | ||
|
|
0a60ef26bd | ||
|
|
9d5ed350a7 | ||
|
|
ca52f070ae | ||
|
|
9e9858b81c | ||
|
|
058b2bec22 | ||
|
|
5ea605d8de | ||
|
|
7f0dd15bab | ||
|
|
a938f4cfe1 | ||
|
|
28ad393b00 | ||
|
|
f3b834d536 | ||
|
|
692d737a82 | ||
|
|
d5897b9a5d | ||
|
|
7b780efb42 | ||
|
|
4e09d27c6f | ||
|
|
e1d3a8a6e9 | ||
|
|
235ac72a06 | ||
|
|
dd06653e53 | ||
|
|
7eee3ceb70 | ||
|
|
19b89a0e19 | ||
|
|
a0aefb3d3f | ||
|
|
20fb9ea351 | ||
|
|
ee6f01918c | ||
|
|
71e25058c1 | ||
|
|
35bcc463e5 | ||
|
|
5b8a26f1d1 | ||
|
|
cc340d9cdc | ||
|
|
786ea39ac4 | ||
|
|
df57eb3824 | ||
|
|
7e04c5e277 | ||
|
|
33a182674a | ||
|
|
14a790891f | ||
|
|
d1daf6531a | ||
|
|
e89b40e9c9 | ||
|
|
afb651821b | ||
|
|
92cf98c77b | ||
|
|
60797cb25f | ||
|
|
c9319fbef5 | ||
|
|
4cb673b644 | ||
|
|
cee2ec1680 | ||
|
|
934a6d417d | ||
|
|
d6ee29f5ae | ||
|
|
c5e5dc832c | ||
|
|
ac2b546a13 | ||
|
|
d0537c7506 | ||
|
|
a0ed2ca71b | ||
|
|
4313157666 | ||
|
|
e8fa3ce478 | ||
|
|
c9d3c0bc90 | ||
|
|
94d86427ff | ||
|
|
3b0e6a2969 | ||
|
|
64bdc502ad | ||
|
|
c81e058bb0 | ||
|
|
be2b7d9725 | ||
|
|
1428c01a5f | ||
|
|
4aafeb0da2 | ||
|
|
32af5c267e | ||
|
|
ba7513fdf3 | ||
|
|
b6b96f8841 | ||
|
|
c1b602145f | ||
|
|
719b47e3aa | ||
|
|
d57a56407b | ||
|
|
3cee7b6378 | ||
|
|
1e03393b68 | ||
|
|
dde673f8d7 | ||
|
|
cdbe853595 | ||
|
|
3f49fc5f2c | ||
|
|
c517ff57ca | ||
|
|
46d53c37fa | ||
|
|
94b28e420c | ||
|
|
9368e4db33 | ||
|
|
ae15e644b1 | ||
|
|
3a5c4b68bb | ||
|
|
a7a5365af2 | ||
|
|
6ae3a09ef3 | ||
|
|
8608a8e64c | ||
|
|
2481693cf2 | ||
|
|
33defd1f9b | ||
|
|
c57e1d8def | ||
|
|
882a9ced90 | ||
|
|
e4697de175 | ||
|
|
422f4f2b41 | ||
|
|
1dc0652444 | ||
|
|
b598996497 | ||
|
|
a5a56874af | ||
|
|
af485f89cd | ||
|
|
1eb9209afe | ||
|
|
fcba907998 | ||
|
|
096ac021a9 | ||
|
|
b05ab854ae | ||
|
|
fd0f873a36 | ||
|
|
d8e61e51de | ||
|
|
bf045a0564 | ||
|
|
cec27b5bb4 | ||
|
|
a75c71299b | ||
|
|
187a7dcfdc | ||
|
|
9a07b93cb3 | ||
|
|
a4bf09e7b9 | ||
|
|
6c56271e8c | ||
|
|
a673d60963 | ||
|
|
736f370dce | ||
|
|
4a4e1b49ec | ||
|
|
0314b2cf45 | ||
|
|
f1d36b1970 | ||
|
|
b131f74533 | ||
|
|
a2d343b108 | ||
|
|
a43af44e9c | ||
|
|
876b7081d8 | ||
|
|
cb2cb15916 | ||
|
|
3510531683 | ||
|
|
744268f388 | ||
|
|
18b082955b | ||
|
|
70438b7715 | ||
|
|
53681cbdb6 | ||
|
|
e7f579b75d | ||
|
|
21c4cd7cb2 | ||
|
|
5a6404712c | ||
|
|
b332e4aaf9 | ||
|
|
cff00f43c2 | ||
|
|
1cf8d6b631 | ||
|
|
f724ece386 | ||
|
|
aba295323e | ||
|
|
c804883350 | ||
|
|
cebbc4e2b7 | ||
|
|
77f4520207 | ||
|
|
ca77392bd1 | ||
|
|
71c07ed930 | ||
|
|
20ceb493b6 | ||
|
|
b8e28df43a | ||
|
|
2ed6c25c80 | ||
|
|
5002c95048 | ||
|
|
9888ffd8d1 | ||
|
|
aaa0b1ec3c | ||
|
|
03731c723b | ||
|
|
215a369c2b | ||
|
|
8f75480ebc | ||
|
|
fb1fd7f6f4 | ||
|
|
109b87d2a3 | ||
|
|
975b94c5f2 | ||
|
|
d92ca4d9d1 | ||
|
|
83f6c8cddb | ||
|
|
3d58025805 | ||
|
|
a8785cf719 | ||
|
|
0f0a8472d7 | ||
|
|
e48e25a548 | ||
|
|
7b403dc57f | ||
|
|
eb741b9cc9 | ||
|
|
68445e1e34 | ||
|
|
cf585ba1de | ||
|
|
298a5717bc | ||
|
|
347e8bd839 | ||
|
|
b952231df1 | ||
|
|
51be125ff9 | ||
|
|
8bc7b0ff5a | ||
|
|
4ef72ddc16 | ||
|
|
a1fd2da0f9 | ||
|
|
269ee62cd4 | ||
|
|
f45eafe342 | ||
|
|
a68755af2b | ||
|
|
e903109d9f | ||
|
|
a3bb3137ac | ||
|
|
074d8f0a26 | ||
|
|
2d28663f53 | ||
|
|
4127be0a95 | ||
|
|
03d78bbb31 | ||
|
|
6013d993b9 | ||
|
|
b7dbb29e68 | ||
|
|
37da919b7d | ||
|
|
9d4ef36e09 | ||
|
|
c0ddf3df0c | ||
|
|
74055a3884 | ||
|
|
8c1a429c44 | ||
|
|
b5bd8591e7 | ||
|
|
e6c957caaa | ||
|
|
6d75298284 | ||
|
|
9d43183704 | ||
|
|
e7677a5e8d | ||
|
|
7dfb2bfcda | ||
|
|
34445aa819 | ||
|
|
42c691a051 | ||
|
|
8b32e8a08c | ||
|
|
37ff2eaf2a | ||
|
|
27aa148e02 | ||
|
|
8f14a1cc38 | ||
|
|
3e53f28f6e | ||
|
|
96823c424d | ||
|
|
08cb903731 | ||
|
|
5c6e8b833e | ||
|
|
028e79ddda | ||
|
|
5ebfa4aaed | ||
|
|
c2af67efd3 | ||
|
|
6766dfae26 | ||
|
|
199b67a68c | ||
|
|
644488a5f3 | ||
|
|
1ace08645a | ||
|
|
636b041b9b | ||
|
|
a41f9dc036 | ||
|
|
448a05ae2c | ||
|
|
099c9a3232 | ||
|
|
2575e227a5 | ||
|
|
fa26b59b0c | ||
|
|
c23ffe4bc1 | ||
|
|
7ed5870ed9 | ||
|
|
8559be015a | ||
|
|
cb0657bdf3 | ||
|
|
15fb479e94 | ||
|
|
0378cffafc | ||
|
|
51fb224ef8 | ||
|
|
a4516b4261 | ||
|
|
a952d23781 | ||
|
|
69282617fd | ||
|
|
51a74b4799 | ||
|
|
2dcd6b22d9 | ||
|
|
857dfdeb9e | ||
|
|
70b7c24cb0 | ||
|
|
e089ee4d85 | ||
|
|
d254e0191d | ||
|
|
0ab18bd14c | ||
|
|
aaac206345 | ||
|
|
f3761a3eda | ||
|
|
aba8a3e2d4 | ||
|
|
545ce7d8bf | ||
|
|
3840a482c7 | ||
|
|
4dd70c433e | ||
|
|
abf66aa7a1 | ||
|
|
1e94425015 | ||
|
|
a69e355a06 | ||
|
|
e17d27d91d | ||
|
|
cc1860bc86 | ||
|
|
f3c8bb2bce | ||
|
|
ee23b01f0b | ||
|
|
3cacc54b78 | ||
|
|
4657ed1446 | ||
|
|
4a52217ed4 | ||
|
|
954a8dce0f | ||
|
|
6ec8183750 | ||
|
|
eb1f647c9c | ||
|
|
029ae35058 | ||
|
|
fdfc95df8b | ||
|
|
6d93048fe9 | ||
|
|
5f07d1c5a4 | ||
|
|
d866ad671a | ||
|
|
9ab4bbc7ff | ||
|
|
703c9a7370 | ||
|
|
403c18a300 | ||
|
|
85748aec15 | ||
|
|
084bddf1c5 | ||
|
|
8e1ec24f55 | ||
|
|
538bc5a09e | ||
|
|
d7575f95f0 | ||
|
|
96a0f77bb4 | ||
|
|
986a932636 | ||
|
|
9ea7c3bfcf | ||
|
|
e1057cd477 | ||
|
|
453261a042 | ||
|
|
a712baa8e5 | ||
|
|
254e8e3452 | ||
|
|
5a053fb6fc | ||
|
|
baae2d8703 | ||
|
|
41f5e21044 | ||
|
|
3238bed9c9 | ||
|
|
8edc352393 | ||
|
|
b8ae152c4b | ||
|
|
2a2fdc168c | ||
|
|
418f3b4042 | ||
|
|
c3169d49d3 | ||
|
|
39dce00980 | ||
|
|
333eac7f9a | ||
|
|
4936c9a3f3 | ||
|
|
0bbe2fa862 | ||
|
|
68f816e8cf | ||
|
|
7cdad3c200 | ||
|
|
7a854cb1f8 | ||
|
|
9c91ea1caf | ||
|
|
0a60e4536d | ||
|
|
55c9b45649 | ||
|
|
051b7454f8 | ||
|
|
cb071834da | ||
|
|
225452befc | ||
|
|
b601f68cda | ||
|
|
bf785cbcec | ||
|
|
e1491b8ec6 | ||
|
|
2d82f73484 | ||
|
|
a76b1ba068 | ||
|
|
052bf7df93 | ||
|
|
d244f750fc | ||
|
|
8b6ddcb066 | ||
|
|
58baa046d2 | ||
|
|
187317c2c9 | ||
|
|
471d28bd10 | ||
|
|
a9c38fb37f | ||
|
|
f6fce0981d | ||
|
|
62aab2227c | ||
|
|
9c676d0ddd | ||
|
|
09b50641ff | ||
|
|
18bfb4dd48 | ||
|
|
8977fbbd97 | ||
|
|
ae1b0b07cf | ||
|
|
9847cfe73d | ||
|
|
9f369bc42f | ||
|
|
790726519e | ||
|
|
444dbb5364 | ||
|
|
513f947d62 | ||
|
|
6152263045 | ||
|
|
40cb39d00c | ||
|
|
674a607488 |
693
CHANGES
Normal file
693
CHANGES
Normal file
@@ -0,0 +1,693 @@
|
||||
0.52 - Wed 12 November 2008
|
||||
|
||||
- Add "netcat-alike" option (-B) to dbclient, allowing Dropbear to tunnel
|
||||
standard input/output to a TCP port-forwarded remote host.
|
||||
|
||||
- Add "proxy command" support to dbclient, to allow using a spawned process for
|
||||
IO rather than a direct TCP connection. eg
|
||||
dbclient remotehost
|
||||
is equivalent to
|
||||
dbclient -J 'nc remotehost 22' remotehost
|
||||
(the hostname is still provided purely for looking up saved host keys)
|
||||
|
||||
- Combine netcat-alike and proxy support to allow "multihop" connections, with
|
||||
comma-separated host syntax. Allows running
|
||||
|
||||
dbclient user1@host1,user2@host2,user3@host3
|
||||
|
||||
to end up at host3 via the other two, using SSH TCP forwarding. It's a bit
|
||||
like onion-routing. All connections are established from the local machine.
|
||||
The comma-separated syntax can also be used for scp/rsync, eg
|
||||
|
||||
rsync -a -e dbclient m@gateway,m2@host,martello:/home/matt/ ~/backup/
|
||||
|
||||
to bounce through a few hosts.
|
||||
|
||||
- Add -I "idle timeout" option (contributed by Farrell Aultman)
|
||||
|
||||
- Allow restrictions on authorized_keys logins such as restricting commands
|
||||
to be run etc. This is a subset of those allowed by OpenSSH, doesn't
|
||||
yet allow restricting source host.
|
||||
|
||||
- Use vfork() for scp on uClinux
|
||||
|
||||
- Default to PATH=/usr/bin:/bin for shells.
|
||||
|
||||
- Report errors if -R forwarding fails
|
||||
|
||||
- Add counter mode cipher support, which avoids some security problems with the
|
||||
standard CBC mode.
|
||||
|
||||
- Support zlib@openssh.com delayed compression for client/server. It can be
|
||||
required for the Dropbear server with the '-Z' option. This is useful for
|
||||
security as it avoids exposing the server to attacks on zlib by
|
||||
unauthenticated remote users, though requires client side support.
|
||||
|
||||
- options.h has been split into options.h (user-changable) and sysoptions.h
|
||||
(less commonly changed)
|
||||
|
||||
- Support "dbclient -s sftp" to specify a subsystem
|
||||
|
||||
- Fix a bug in replies to channel requests that could be triggered by recent
|
||||
versions of PuTTY
|
||||
|
||||
0.51 - Thu 27 March 2008
|
||||
|
||||
- Make a copy of password fields rather erroneously relying on getwpnam()
|
||||
to be safe to call multiple times
|
||||
|
||||
- If $SSH_ASKPASS_ALWAYS environment variable is set (and $SSH_ASKPASS is
|
||||
as well) always use that program, ignoring isatty() and $DISPLAY
|
||||
|
||||
- Wait until a process exits before the server closes a connection, so
|
||||
that an exit code can be sent. This fixes problems with exit codes not
|
||||
being returned, which could cause scp to fail.
|
||||
|
||||
0.50 - Wed 8 August 2007
|
||||
|
||||
- Add DROPBEAR_PASSWORD environment variable to specify a dbclient password
|
||||
|
||||
- Use /dev/urandom by default, since that's what everyone does anyway
|
||||
|
||||
- Correct vfork() use for uClinux in scp
|
||||
(thanks to Alex Landau)
|
||||
|
||||
- Exit with an exit code of 1 if dropbear can't bind to any ports
|
||||
(thanks to Nicolai Ehemann)
|
||||
|
||||
- Improve network performance and add a -W <receive_window> argument for
|
||||
adjusting the tradeoff between network performance and memory consumption.
|
||||
|
||||
- Fix a problem where reply packets could be sent during key exchange,
|
||||
in violation of the SSH spec. This could manifest itself with connections
|
||||
being terminated after 8 hours with new TCP-forward connections being
|
||||
established.
|
||||
|
||||
- Add -K <keepalive_time> argument, ensuring that data is transmitted
|
||||
over the connection at least every N seconds.
|
||||
|
||||
- dropbearkey will no longer generate DSS keys of sizes other than 1024
|
||||
bits, as required by the DSS specification. (Other sizes are still
|
||||
accepted for use to provide backwards compatibility).
|
||||
|
||||
0.49 - Fri 23 February 2007
|
||||
|
||||
- Security: dbclient previously would prompt to confirm a
|
||||
mismatching hostkey but wouldn't warn loudly. It will now
|
||||
exit upon a mismatch.
|
||||
|
||||
- Compile fixes, make sure that all variable definitions are at the start
|
||||
of a scope.
|
||||
|
||||
- Added -P pidfile argument to the server (from Swen Schillig)
|
||||
|
||||
- Add -N dbclient option for "no command"
|
||||
|
||||
- Add -f dbclient option for "background after auth"
|
||||
|
||||
- Add ability to limit binding to particular addresses, use
|
||||
-p [address:]port, patch from Max-Gerd Retzlaff.
|
||||
|
||||
- Try to finally fix ss_family compilation problems (for old
|
||||
glibc systems)
|
||||
|
||||
- Fix finding relative-path server hostkeys when running daemonized
|
||||
|
||||
- Use $HOME in preference to that from /etc/passwd, so that
|
||||
dbclient can still work on broken systems.
|
||||
|
||||
- Fix various issues found by Klocwork defect analysis, mostly memory leaks
|
||||
and error-handling. Thanks to Klocwork for their service.
|
||||
|
||||
- Improve building in a separate directory
|
||||
|
||||
- Add compile-time LOG_COMMANDS option to log user commands
|
||||
|
||||
- Add '-y' flag to dbclient to unconditionally accept host keys,
|
||||
patch from Luciano Miguel Ferreira Rocha
|
||||
|
||||
- Return immediately for "sleep 10 & echo foo", rather than waiting
|
||||
for the sleep to return (pointed out by Rob Landley).
|
||||
|
||||
- Avoid hanging after exit in certain cases (such as scp)
|
||||
|
||||
- Various minor fixes, in particular various leaks reported by
|
||||
Erik Hovland
|
||||
|
||||
- Disable core dumps on startup
|
||||
|
||||
- Don't erase over every single buffer, since it was a bottleneck.
|
||||
On systems where it really matters, encrypted swap should be utilised.
|
||||
|
||||
- Read /dev/[u]random only once at startup to conserve kernel entropy
|
||||
|
||||
- Upgrade to LibTomCrypt 1.16 and LibTomMath 0.40
|
||||
|
||||
- Upgrade config.status and config.guess
|
||||
|
||||
0.48.1 - Sat 11 March 2006
|
||||
|
||||
- Compile fix for scp
|
||||
|
||||
0.48 - Thurs 9 March 2006
|
||||
|
||||
- Check that the circular buffer is properly empty before
|
||||
closing a channel, which could cause truncated transfers
|
||||
(thanks to Tomas Vanek for helping track it down)
|
||||
|
||||
- Implement per-IP pre-authentication connection limits
|
||||
(after some poking from Pablo Fernandez)
|
||||
|
||||
- Exit gracefully if trying to connect to as SSH v1 server
|
||||
(reported by Rushi Lala)
|
||||
|
||||
- Only read /dev/random once at startup when in non-inetd mode
|
||||
|
||||
- Allow ctrl-c to close a dbclient password prompt (may
|
||||
still have to press enter on some platforms)
|
||||
|
||||
- Merged in uClinux patch for inetd mode
|
||||
|
||||
- Updated to scp from OpenSSH 4.3p2 - fixes a security issue
|
||||
where use of system() could cause users to execute arbitrary
|
||||
code through malformed filenames, ref CVE-2006-0225
|
||||
|
||||
0.47 - Thurs Dec 8 2005
|
||||
|
||||
- SECURITY: fix for buffer allocation error in server code, could potentially
|
||||
allow authenticated users to gain elevated privileges. All multi-user systems
|
||||
running the server should upgrade (or apply the patch available on the
|
||||
Dropbear webpage).
|
||||
|
||||
- Fix channel handling code so that redirecting to /dev/null doesn't use
|
||||
100% CPU.
|
||||
|
||||
- Turn on zlib compression for dbclient.
|
||||
|
||||
- Set "low delay" TOS bit, can significantly improve interactivity
|
||||
over some links.
|
||||
|
||||
- Added client keyboard-interactive mode support, allows operation with
|
||||
newer OpenSSH servers in default config.
|
||||
|
||||
- Log when pubkey auth fails because of bad ~/.ssh/authorized_keys permissions
|
||||
|
||||
- Improve logging of assertions
|
||||
|
||||
- Added aes-256 cipher and sha1-96 hmac.
|
||||
|
||||
- Fix twofish so that it actually works.
|
||||
|
||||
- Improve PAM prompt comparison.
|
||||
|
||||
- Added -g (dbclient) and -a (dropbear server) options to allow
|
||||
connections to listening forwarded ports from remote machines.
|
||||
|
||||
- Various other minor fixes
|
||||
|
||||
- Compile fixes for glibc 2.1 (ss_family vs __ss_family) and NetBSD
|
||||
(netinet/in_systm.h needs to be included).
|
||||
|
||||
0.46 - Sat July 9 2005
|
||||
|
||||
- Fix long-standing bug which caused connections to be closed if an ssh-agent
|
||||
socket was no longer available
|
||||
|
||||
- Print a warning if we seem to be blocking on /dev/random
|
||||
(suggested by Paul Fox)
|
||||
|
||||
- Fixed a memory leak in DSS code (thanks to Boris Berezovsky for the patch)
|
||||
|
||||
- dbclient -L no longer segfaults, allocate correct buffer size (thanks
|
||||
to David Cook for reporting it, and Christopher Faylor for independently
|
||||
sending in a patch)
|
||||
|
||||
- Added RSA blinding to signing code (suggested by Dan Kaminsky)
|
||||
|
||||
- Rearranged bignum reading/random generation code
|
||||
|
||||
- Reset the non-blocking status on stderr and stdout as well as stdin,
|
||||
fixes a problem where the shell running dbclient will exit (thanks to
|
||||
Brent Roman for reporting it)
|
||||
|
||||
- Fix so that all file descriptors are closed so the child shell doesn't
|
||||
inherit descriptors (thanks to Linden May for the patch)
|
||||
|
||||
- Change signkey.c to avoid gcc 4 generating incorrect code
|
||||
|
||||
- After both sides of a file descriptor have been shutdown(), close()
|
||||
it to avoid leaking descriptors (thanks to Ari Hyttinen for a patch)
|
||||
|
||||
- Update to LibTomCrypt 1.05 and LibTomMath 0.35
|
||||
|
||||
0.45 - Mon March 7 2005
|
||||
|
||||
- Makefile no longer appends 'static' to statically linked binaries
|
||||
|
||||
- Add optional SSH_ASKPASS support to the client
|
||||
|
||||
- Respect HOST_LOOKUP option
|
||||
|
||||
- Fix accidentally removed "return;" statement which was removed in 0.44
|
||||
(causing clients which sent an empty terminal-modes string to fail to
|
||||
connect - including pssh, ssh.com, danger hiptop). (patches
|
||||
independently from Paul Fox, David Horwitt and Sven-Ola Tuecke)
|
||||
|
||||
- Read "y/n" response for fingerprints from /dev/tty directly so that dbclient
|
||||
will work with scp.
|
||||
|
||||
0.44 - Mon Jan 3 2005
|
||||
|
||||
- SECURITY: Fix for PAM auth so that usernames are logged and conversation
|
||||
function responses are allocated correctly - all 0.44test4 users with PAM
|
||||
compiled in (not default) are advised to upgrade.
|
||||
|
||||
- Fix calls to getnameinfo() for compatibility with Solaris
|
||||
|
||||
- Pristine compilation works (run 'configure' from a fresh dir and make it
|
||||
there)
|
||||
|
||||
- Fixes for compiling with most options disabled.
|
||||
|
||||
- Upgraded to LibTomCrypt 0.99 and LibTomMath 0.32
|
||||
|
||||
- Make sure that zeroing out of values in LTM and LTC won't get optimised away
|
||||
|
||||
- Removed unused functions from loginrec.c
|
||||
|
||||
- /dev/random is now the default entropy source rather than /dev/urandom
|
||||
|
||||
- Logging of IPs in auth success/failure messages for improved greppability
|
||||
|
||||
- Fix dbclient so that "scp -i keyfile" works. (It can handle "-ikeyfile
|
||||
properly)
|
||||
|
||||
- Avoid a race in server shell-handling code which prevents the exit-code
|
||||
from being returned to the client in some circumstances.
|
||||
|
||||
- Makefile modified so that install target works correctly (doesn't try
|
||||
to install "all" binary) - patch from Juergen Daubert
|
||||
|
||||
- Various minor fixes and compile warnings.
|
||||
|
||||
0.44test4 - Tue Sept 14 2004 21:15:54 +0800
|
||||
|
||||
- Fix inetd mode so it actually loads the hostkeys (oops)
|
||||
|
||||
- Changed DROPBEAR_DEFPORT properly everywhere
|
||||
|
||||
- Fix a small memory leak in the auth code
|
||||
|
||||
- WCOREDUMP is only used on systems which support it (ie not cygwin or AIX)
|
||||
|
||||
- Check (and fail for) cases when we can't negotiate algorithms with the
|
||||
remote side successfully (rather than bombing out ungracefully)
|
||||
|
||||
- Handle authorized_keys files without a terminating newline
|
||||
|
||||
- Fiddle the channel receive window size for possibly better performance
|
||||
|
||||
- Added in the PAM authentication code (finally! thanks to Martin Carlsson)
|
||||
|
||||
0.44test3 - Fri Aug 27 22:20:54 +0800
|
||||
|
||||
- Fixed a bunch of warnings.
|
||||
|
||||
- scp works correctly when passed a username (fix for the dbclient program
|
||||
itself as well, "-lmatt" works as well as "-l matt").
|
||||
|
||||
- Remove unrequired debian files
|
||||
|
||||
- Exit with the remote process's return code for dbclient
|
||||
|
||||
- Display stderr messages from the server in the client
|
||||
|
||||
- Add circular buffering to the channel code. This should dramatically reduce
|
||||
the amount of backtraffic sent in response to traffic incoming to the
|
||||
Dropbear end - improves high-latency performance (ie dialup).
|
||||
|
||||
- Various other related channel-handling fixups.
|
||||
|
||||
- Allow leading lines in the banner when connecting to servers
|
||||
|
||||
- Fixed printing out errors onto the network socket with stderr (for inetd
|
||||
mode when using xinetd)
|
||||
|
||||
- Remove obselete documentation
|
||||
|
||||
- Fix a null-pointer exception when trying to free non-existant listeners
|
||||
at cleanup.
|
||||
|
||||
- DEBUG_TRACE now only works if you add "-v" to the program commandline
|
||||
|
||||
- Don't leave stdin non-blocking on exit - this caused the parent shell
|
||||
of dbclient to close when dbclient exited, for some shells in BusyBox
|
||||
|
||||
- Server connections no longer timeout after 5 minutes
|
||||
|
||||
- Fixed stupid DSS hostkey typo (server couldn't load host keys)
|
||||
|
||||
0.44test2 - Tues Aug 17 2004 17:43:54 +0800
|
||||
|
||||
- Fix up dropbearmulti targets in the Makefile - symlinks are now created
|
||||
|
||||
- Compile fake-rfc2553 even with dropbearconvert/dropbearkey - this
|
||||
allows them to work on platforms without a native getaddrinfo()
|
||||
|
||||
- Create ~/.ssh/known_hosts properly if it doesn't exist
|
||||
|
||||
- Fix basename() function prototype
|
||||
|
||||
- Backport some local changes (more #ifdefs for termcodes.c, a fix for missing
|
||||
defines on AIX).
|
||||
|
||||
- Let dbclient be run as "ssh"
|
||||
|
||||
- Initialise mp_ints by default
|
||||
|
||||
0.44test1 - Sun Aug 16 2005 17:43:54 +0800
|
||||
|
||||
- TESTING RELEASE - this is the first public release of the client codebase,
|
||||
so there are sure to be bugs to be found. In addition, if you're just using
|
||||
the server portion, the final binary size probably will increase - I'll
|
||||
be trying to get it back down in future releases.
|
||||
|
||||
- Dropbear client added - lots of changes to the server code as well to
|
||||
generalise things
|
||||
|
||||
- IPv6 support added for client, server, and forwarding
|
||||
|
||||
- New makefile with more generic support for multiple-program binaries
|
||||
|
||||
0.43 - Fri Jul 16 2004 17:44:54 +0800
|
||||
|
||||
- SECURITY: Don't try to free() uninitialised variables in DSS verification
|
||||
code. Thanks to Arne Bernin for pointing out this bug. This is possibly
|
||||
exploitable, all users with DSS and pubkey-auth compiled in are advised to
|
||||
upgrade.
|
||||
|
||||
- Clean up agent forwarding socket files correctly, patch from Gerrit Pape.
|
||||
|
||||
- Don't go into an infinite loop when portforwarding to servers which don't
|
||||
send any initial data/banner. Patch from Nikola Vladov
|
||||
|
||||
- Fix for network vs. host byte order in logging remote TCP ports, also
|
||||
from Gerrit Pape.
|
||||
|
||||
- Initialise many pointers to NULL, for general safety. Also checked cleanup
|
||||
code for mp_ints (related to security issues above).
|
||||
|
||||
0.42 - Wed Jun 16 2004 12:44:54 +0800
|
||||
|
||||
- Updated to Gerrit Pape's official Debian subdirectory
|
||||
|
||||
- Fixed bad check when opening /dev/urandom - thanks to Danny Sung.
|
||||
|
||||
- Added -i inetd mode flag, and associated options in options.h . Dropbear
|
||||
can be compiled with either normal mode, inetd, or both modes. Thanks
|
||||
to Gerrit Pape for basic patch and motivation.
|
||||
|
||||
- Use <dirent.h> rather than <sys/dir.h> for POSIX compliance. Thanks to Bill
|
||||
Sommerfield.
|
||||
|
||||
- Fixed a TCP forwarding (client-local, -L style) bug which caused the whole
|
||||
session to close if the TCP connection failed. Thanks to Andrew Braund for
|
||||
reporting it and helping track it down.
|
||||
|
||||
- Re-enable sigpipe for child processes. Thanks to Gerrit Pape for some
|
||||
suggestions, and BSD manpages for a clearer explanation of the behaviour.
|
||||
|
||||
- Added manpages, thanks to Gerrit Pape.
|
||||
|
||||
- Changed license text for LibTomCrypt and LibTomMath.
|
||||
|
||||
- Added strip-static target
|
||||
|
||||
- Fixed a bug in agent-forwarding cleanup handler - would segfault
|
||||
(dereferencing a null pointer) if agent forwarding had failed.
|
||||
|
||||
- Fix behaviour of authorized_keys parsing, so larger (>1024 bit) DSA keys will
|
||||
work. Thanks to Dr. Markus Waldeck for the report.
|
||||
|
||||
- Fixed local port forwarding code so that the "-j" option will make forwarding
|
||||
attempts fail more gracefully.
|
||||
|
||||
- Allow repeated requests in a single session if previous ones fail - this fixes PuTTY and some other SCP clients, which try SFTP, then fall-back to SCP if it
|
||||
isn't available. Thanks to Stirling Westrup for the report.
|
||||
|
||||
- Updated to LibTomCrypt 0.96 and LibTomMath 0.30. The AES code now uses
|
||||
smaller non-precomputed tables if DROPBEAR_SMALL_CODE is defined in
|
||||
options.h, leading to a significant reduction in the binary size.
|
||||
|
||||
0.41 - Mon Jan 19 2004 22:40:19 +0800
|
||||
|
||||
- Fix in configure so that cross-compiling works, thanks to numerous people for
|
||||
reporting and testing
|
||||
|
||||
- Terminal mode parsing now handles empty terminal mode strings (sent by
|
||||
Windows ssh.com clients), thanks to Ricardo Derbes for the report
|
||||
|
||||
- Handling is improved for users with no shell specified in /etc/passwd,
|
||||
thanks again to Ricardo Derbes
|
||||
|
||||
- Fix for compiling with --disable-syslog, thanks to gordonfh
|
||||
|
||||
- Various minor fixes allow scp to work with irix, thanks to Paul Marinceu for
|
||||
fixing it up
|
||||
|
||||
- Use <stropts.h> not <sys/stropts.h>, since the former seems more common
|
||||
|
||||
0.40 - Tue Jan 13 2004 21:05:19 +0800
|
||||
|
||||
- Remote TCP forwarding (-R) style implemented
|
||||
|
||||
- Local and remote TCP forwarding can each be disabled at runtime (-k and -j
|
||||
switches)
|
||||
|
||||
- Fix for problems detecting openpty() with uClibc - many thanks to various
|
||||
people for reporting and testing fixes, including (in random order) Cristian
|
||||
Ionescu-Idbohrn, James Ewing, Steve Dover, Thomas Lundquist and Frederic
|
||||
Lavernhe
|
||||
|
||||
- Improved portability for IRIX, thanks to Paul Marinceu
|
||||
|
||||
- AIX and HPUX portability fixes, thanks to Darren Tucker for patches
|
||||
|
||||
- prngd should now work correctly, thanks to Darren Tucker for the patch
|
||||
|
||||
- scp compilation on systems without strlcpy() is fixed, thanks to Peter
|
||||
Jannesen and David Muse for reporting it (independently and simultaneously :)
|
||||
|
||||
- Merged in new LibTomCrypt 0.92 and LibTomMath 0.28
|
||||
|
||||
0.39 - Tue Dec 16 2003 15:19:19 +0800
|
||||
|
||||
- Better checking of key lengths and parameters for DSS and RSA auth
|
||||
|
||||
- Print fingerprint of keys used for pubkey auth
|
||||
|
||||
- More consistent logging of usernames and IPs
|
||||
|
||||
- Added option to disable password auth (or just for root) at runtime
|
||||
|
||||
- Avoid including bignum functions which don't give much speed benefit but
|
||||
take up binary size
|
||||
|
||||
- Added a stripped down version of OpenSSH's scp binary
|
||||
|
||||
- Added additional supporting functions for Irix, thanks to Paul Marinceu
|
||||
|
||||
- Don't check for unused libraries in configure script
|
||||
|
||||
- Removed trailing comma in algorithm lists (thanks to Mihnea Stoenescu)
|
||||
|
||||
- Fixed up channel close handling, always send close packet in response
|
||||
(also thanks to Mihnea Stoenescu)
|
||||
|
||||
- Various makefile improvements for cross-compiling, thanks to Friedrich
|
||||
Lobenstock and Mihnea Stoenescu
|
||||
|
||||
- Use daemon() function if available (or our own copy) rather than separate
|
||||
code (thanks to Frédéric Lavernhe for the report and debugging, and Bernard
|
||||
Blackham for his suggestion on what to look at)
|
||||
|
||||
- Fixed up support for first_kex_packet_follows, required to talk to ssh.com
|
||||
clients. Thanks to Marian Stagarescu for the bug report.
|
||||
|
||||
- Avoid using MAXPATHLEN, pointer from Ian Morris
|
||||
|
||||
- Improved input sanity checking
|
||||
|
||||
0.38 - Sat Oct 11 2003 16:28:13 +0800
|
||||
|
||||
- Default hostkey path changed to /etc/dropbear/dropbear_{rsa,dss}_host_key
|
||||
rather than /etc/dropbear_{rsa,dss}_host_key
|
||||
|
||||
- Added SMALL and MULTI text files which have info on compiling for multiple
|
||||
binaries or small binaries
|
||||
|
||||
- Allow for commandline definition of some options.h settings
|
||||
(without warnings)
|
||||
|
||||
- Be more careful handling EINTR
|
||||
|
||||
- More fixes for channel closing
|
||||
|
||||
- Added multi-binary support
|
||||
|
||||
- Improved logging of IPs, now get logged in all cases
|
||||
|
||||
- Don't chew cpu when waiting for version identification string, also
|
||||
make sure that we kick off people if they don't auth within 5 minutes.
|
||||
|
||||
- Various small fixes, warnings etc
|
||||
|
||||
- Display MOTD if requested - suggested by
|
||||
Trent Lloyd <lathiat at sixlabs.org> and
|
||||
Zach White <zwhite at darkstar.frop.org>
|
||||
|
||||
- sftp support works (relies on OpenSSH sftp binary or similar)
|
||||
|
||||
- Added --disable-shadow option (requested by the floppyfw guys)
|
||||
|
||||
0.37 - Wed Sept 24 2003 19:42:12 +0800
|
||||
|
||||
- Various portability fixes, fixes for Solaris 9, Tru64 5.1, Mac OS X 10.2,
|
||||
AIX, BSDs
|
||||
|
||||
- Updated LibTomMath to 0.27 and LibTomCrypt to 0.90
|
||||
|
||||
- Renamed util.{c,h} to dbutil.{c,h} to avoid conflicts with system util.h
|
||||
|
||||
- Added some small changes so it'll work with AIX (plus Linux Affinity).
|
||||
Thanks to Shig for them.
|
||||
|
||||
- Improved the closing messages, so a clean exit is "Exited normally"
|
||||
|
||||
- Added some more robust integer/size checking in buffer.c as a backstop for
|
||||
integer overflows
|
||||
|
||||
- X11 forwarding fixed for OSX, path for xauth changed to /usr/X11R6/bin/xauth
|
||||
|
||||
- Channel code handles closing more nicely, doesn't sit waiting for an extra
|
||||
keystroke on BSD/OSX platforms, and data is flushed fully before closing
|
||||
child processes (thanks to
|
||||
Cristian Ionescu-Idbohrn <cristian.ionescu-idbohrn at axis.com> for
|
||||
pointing that out).
|
||||
|
||||
- Changed "DISABLE_TCPFWD" to "ENABLE_TCPFWD" (and for x11/auth) so
|
||||
"disable DISABLE_TCPWD" isn't so confusing.
|
||||
|
||||
- Fix authorized_keys handling (don't crash on too-long keys, and
|
||||
use fgetc not getc to avoid strange macro-related issues), thanks to
|
||||
Cristian Ionescu-Idbohrn <cristian.ionescu-idbohrn at axis.com>
|
||||
and Steve Rodgers <hwstar at cox.net> for reporting and testing.
|
||||
|
||||
- Fixes to the README with regard to uClibc systems, thanks to
|
||||
Cristian Ionescu-Idbohrn <cristian.ionescu-idbohrn at axis.com>,
|
||||
as well as general improvements to documentation (split README/INSTALL)
|
||||
|
||||
- Fixed up some compilation problems with dropbearconvert/dropbearkey if
|
||||
DSS or RSA were disabled, reported by Patrik Karlsson <patrik at cqure.net>
|
||||
|
||||
- Fix double-free bug for hostkeys, reported by
|
||||
Vincent Sanders <vince at kyllikki.org>
|
||||
|
||||
- Fix up missing \ns from dropbearconvert help message,
|
||||
thanks to Mordy Ovits <movits at bloomberg.com> for the patch
|
||||
|
||||
0.36 - Tue August 19 2003 12:16:23 +0800
|
||||
|
||||
- Fix uninitialised temporary variable in DSS signing code
|
||||
(thanks to Matthew Franz <mdfranz at io.com> for reporting, and the authors
|
||||
of Valgrind for making it easy to track down)
|
||||
- Fix remote version-string parsing error
|
||||
(thanks to Bernard Blackham <bernard at blackham.com.au> for noticing)
|
||||
- Improved host-algorithm-matching algorithm in algo.c
|
||||
- Decreased MAX_STRING_LEN to a more realistic value
|
||||
- Fix incorrect version (0.34) in this CHANGES file for the previous release.
|
||||
|
||||
0.35 - Sun August 17 2003 05:37:47 +0800
|
||||
|
||||
- Fix for remotely exploitable format string buffer overflow.
|
||||
(thanks to Joel Eriksson <je at bitnux.com>)
|
||||
|
||||
0.34 - Fri August 15 2003 15:10:00 +0800
|
||||
|
||||
- Made syslog optional, both at compile time and as a compile option
|
||||
(suggested by Laurent Bercot <ska at skarnet.org>)
|
||||
- Fixup for bad base64 parsing in authorized_keys
|
||||
(noticed by Davyd Madeley <davyd at zdlcomputing.com>)
|
||||
- Added initial tcp forwarding code, only -L (local) at this stage
|
||||
- Improved "make install" with DESTDIR and changing ownership seperately,
|
||||
don't check for setpgrp on Linux for crosscompiling.
|
||||
(from Erik Andersen <andersen at codepoet.org>)
|
||||
- More commenting, fix minor compile warnings, make return values more
|
||||
consistent etc
|
||||
- Various signedness fixes
|
||||
- Can listen on multiple ports
|
||||
- added option to disable openpty with configure script,
|
||||
(from K.-P. Kirchdörfer <kapeka at epost.de>)
|
||||
- Various cleanups to bignum code
|
||||
(thanks to Tom St Denis <tomstdenis at iahu.ca>)
|
||||
- Fix compile error when disabling RSA
|
||||
(from Marc Kleine-Budde <kleine-budde at gmx.de>)
|
||||
- Other cleanups, splitting large functions for packet and kex handling etc
|
||||
|
||||
0.33 - Sun June 22 2003 22:24:12 +0800
|
||||
|
||||
- Fixed some invalid assertions in the channel code, fixing the server dying
|
||||
when forwarding X11 connections.
|
||||
- Add dropbearconvert to convert to/from OpenSSH host keys and Dropbear keys
|
||||
- RSA keys now keep p and q parameters for compatibility -- old Dropbear keys
|
||||
still work, but can't be converted to OpenSSH etc.
|
||||
- Debian packaging directory added, thanks to
|
||||
Grahame (grahame at angrygoats.net)
|
||||
- 'install' target added to the makefile
|
||||
- general tidying, improve consistency of functions etc
|
||||
- If RSA or DSS hostkeys don't exist, that algorithm won't be used.
|
||||
- Improved RSA and DSS key generation, more efficient and fixed some minor bugs
|
||||
(thanks to Tom St Denis for the advice)
|
||||
- Merged new versions of LibTomCrypt (0.86) and LibTomMath (0.21)
|
||||
|
||||
0.32 - Sat May 24 2003 12:44:11 +0800
|
||||
|
||||
- Don't compile unused code from libtomcrypt (test vectors etc)
|
||||
- Updated to libtommath 0.17 and libtomcrypt 0.83. New libtommath results
|
||||
in smaller binary size, due to not linking unrequired code
|
||||
- X11 forwarding added
|
||||
- Agent forwarding added (for OpenSSH.com ssh client/agent)
|
||||
- Fix incorrect buffer freeing when banners are used
|
||||
- Hostname resolution works
|
||||
- Various minor bugfixes/code size improvements etc
|
||||
|
||||
0.31 - Fri May 9 2003 17:57:16 +0800
|
||||
|
||||
- Improved syslog messages - IP logging etc
|
||||
- Strip control characters from log messages (specified username currently)
|
||||
- Login recording (utmp/wtmp) support, so last/w/who work - taken from OpenSSH
|
||||
- Shell is started as a proper login shell, so /etc/profile etc is sourced
|
||||
- Ptys work on Solaris (2.8 x86 tested) now
|
||||
- Fixed bug in specifying the rsa hostkey
|
||||
- Fixed bug in compression code, could trigger if compression resulted in
|
||||
larger output than input (uncommon but possible).
|
||||
|
||||
0.30 - Thu Apr 17 2003 18:46:15 +0800
|
||||
|
||||
- SECURITY: buffer.c had bad checking for buffer increment length - fixed
|
||||
- channel code now closes properly on EOF - scp processes don't hang around
|
||||
- syslog support added - improved auth/login/failure messages
|
||||
- general code tidying, made return codes more consistent
|
||||
- Makefile fixed for dependencies and makes libtomcrypt as well
|
||||
- Implemented sending SSH_MSG_UNIMPLEMENTED :)
|
||||
|
||||
0.29 - Wed Apr 9 2003
|
||||
|
||||
- Fixed a stupid bug in 0.28 release, 'newstr = strdup(oldstr)',
|
||||
not 'newstr=oldstr'
|
||||
|
||||
0.28 - Sun Apr 6 2003
|
||||
|
||||
- Initial public release
|
||||
|
||||
Development was started in October 2002
|
||||
79
INSTALL
Normal file
79
INSTALL
Normal file
@@ -0,0 +1,79 @@
|
||||
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).
|
||||
|
||||
(If using a non-tarball copy, "autoconf; autoheader")
|
||||
|
||||
./configure (optionally with --disable-zlib or --disable-syslog,
|
||||
or --help for other options)
|
||||
|
||||
Now compile:
|
||||
|
||||
make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp"
|
||||
|
||||
And install (/usr/local/bin is usual default):
|
||||
|
||||
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)
|
||||
|
||||
See MULTI for instructions on making all-in-one binaries.
|
||||
|
||||
If you want to compile statically, add "STATIC=1" to the make command-line.
|
||||
|
||||
Binaries can be stripped with "make strip"
|
||||
|
||||
============================================================================
|
||||
|
||||
If you're compiling for a 386-class CPU, you will probably need to add
|
||||
CFLAGS=-DLTC_NO_BSWAP so that libtomcrypt doesn't use 486+ instructions.
|
||||
|
||||
============================================================================
|
||||
|
||||
Compiling with uClibc:
|
||||
|
||||
Firstly, make sure you have at least uclibc 0.9.17, as getusershell() in prior
|
||||
versions is broken. Also note that you may get strange issues if your uClibc
|
||||
headers don't match the library you are running with, ie the headers might
|
||||
say that shadow password support exists, but the libraries don't have it.
|
||||
|
||||
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
|
||||
|
||||
It is possible to compile zlib in, by copying zlib.h and zconf.h into a
|
||||
subdirectory (ie zlibincludes), and
|
||||
|
||||
export CFLAGS="-Izlibincludes -I../zlibincludes"
|
||||
export LDFLAGS=/usr/lib/libz.a
|
||||
|
||||
before ./configure and make.
|
||||
|
||||
If you disable zlib, you must explicitly disable compression for the client -
|
||||
OpenSSH is possibly buggy in this regard, it seems you need to disable it
|
||||
globally in ~/.ssh/config, not just in the host entry in that file.
|
||||
|
||||
You may want to manually disable lastlog recording when using uClibc, configure
|
||||
with --disable-lastlog.
|
||||
|
||||
One common problem is pty allocation. There are a number of types of pty
|
||||
allocation which can be used -- if they work properly, the end result is the
|
||||
same for each type. Running configure should detect the best type to use
|
||||
automatically, however for some systems, this may be incorrect. Some
|
||||
things to note:
|
||||
|
||||
If your system expects /dev/pts to be mounted (this is a uClibc option),
|
||||
make sure that it is.
|
||||
|
||||
Make sure that your libc headers match the library version you are using.
|
||||
|
||||
If openpty() is being used (HAVE_OPENPTY defined in config.h) and it fails,
|
||||
you can try compiling with --disable-openpty. You will probably then need
|
||||
to create all the /dev/pty?? and /dev/tty?? devices, which can be
|
||||
problematic for devfs. In general, openpty() is the best way to allocate
|
||||
PTYs, so it's best to try and get it working.
|
||||
89
LICENSE
89
LICENSE
@@ -1,4 +1,89 @@
|
||||
LibTomMath is hereby released into the Public Domain.
|
||||
Dropbear contains a number of components from different sources, hence there
|
||||
are a few licenses and authors involved. All licenses are fairly
|
||||
non-restrictive.
|
||||
|
||||
-- Tom St Denis
|
||||
|
||||
The majority of code is written by Matt Johnston, under the license below.
|
||||
|
||||
Portions of the client-mode work are (c) 2004 Mihnea Stoenescu, under the
|
||||
same license:
|
||||
|
||||
Copyright (c) 2002-2008 Matt Johnston
|
||||
Portions copyright (c) 2004 Mihnea Stoenescu
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
=====
|
||||
|
||||
LibTomCrypt and LibTomMath are written by Tom St Denis, and are Public Domain.
|
||||
|
||||
=====
|
||||
|
||||
sshpty.c is taken from OpenSSH 3.5p1,
|
||||
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
All rights reserved
|
||||
"As far as I am concerned, the code I have written for this software
|
||||
can be used freely for any purpose. Any derived versions of this
|
||||
software must be clearly marked as such, and if the derived work is
|
||||
incompatible with the protocol description in the RFC file, it must be
|
||||
called by a name other than "ssh" or "Secure Shell". "
|
||||
|
||||
=====
|
||||
|
||||
loginrec.c
|
||||
loginrec.h
|
||||
atomicio.h
|
||||
atomicio.c
|
||||
and strlcat() (included in util.c) are from OpenSSH 3.6.1p2, and are licensed
|
||||
under the 2 point BSD license.
|
||||
|
||||
loginrec is written primarily by Andre Lucas, atomicio.c by Theo de Raadt.
|
||||
|
||||
strlcat() is (c) Todd C. Miller
|
||||
|
||||
=====
|
||||
|
||||
Import code in keyimport.c is modified from PuTTY's import.c, licensed as
|
||||
follows:
|
||||
|
||||
PuTTY is copyright 1997-2003 Simon Tatham.
|
||||
|
||||
Portions copyright Robert de Bath, Joris van Rantwijk, Delian
|
||||
Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
|
||||
Justin Bradford, and CORE SDI S.A.
|
||||
|
||||
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 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.
|
||||
|
||||
26
MULTI
Normal file
26
MULTI
Normal file
@@ -0,0 +1,26 @@
|
||||
Multi-binary compilation
|
||||
========================
|
||||
|
||||
To compile for systems without much space (floppy distributions etc), you
|
||||
can create a single binary. This will save disk space by avoiding repeated
|
||||
code between the various parts.
|
||||
If you are familiar with "busybox", it's the same principle.
|
||||
|
||||
To compile the multi-binary, first "make clean" (if you've compiled
|
||||
previously), then
|
||||
|
||||
make PROGRAMS="programs you want here" MULTI=1
|
||||
|
||||
To use the binary, symlink it from the desired executable:
|
||||
|
||||
ln -s dropbearmulti dropbear
|
||||
ln -s dropbearmulti dbclient
|
||||
etc
|
||||
|
||||
then execute as normal:
|
||||
|
||||
./dropbear <options here>
|
||||
|
||||
"make install" doesn't currently work for multi-binary configuration, though
|
||||
in most situations where it is being used, the target and build systems will
|
||||
differ.
|
||||
211
Makefile.in
Normal file
211
Makefile.in
Normal file
@@ -0,0 +1,211 @@
|
||||
# This Makefile is for Dropbear SSH Server and Client
|
||||
# @configure_input@
|
||||
|
||||
# invocation:
|
||||
# make PROGRAMS="dropbear dbclient scp" MULTI=1 STATIC=1 SCPPROGRESS=1
|
||||
#
|
||||
# to make a multiple-program statically linked binary "staticdropbearmulti".
|
||||
# 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
|
||||
endif
|
||||
|
||||
LTC=libtomcrypt/libtomcrypt.a
|
||||
LTM=libtommath/libtommath.a
|
||||
|
||||
COMMONOBJS=dbutil.o buffer.o \
|
||||
dss.o bignum.o \
|
||||
signkey.o rsa.o random.o \
|
||||
queue.o \
|
||||
atomicio.o compat.o fake-rfc2553.o
|
||||
|
||||
SVROBJS=svr-kex.o svr-algo.o svr-auth.o sshpty.o \
|
||||
svr-authpasswd.o svr-authpubkey.o svr-authpubkeyoptions.o svr-session.o svr-service.o \
|
||||
svr-chansession.o svr-runopts.o svr-agentfwd.o svr-main.o svr-x11fwd.o\
|
||||
svr-tcpfwd.o svr-authpam.o @CRYPTLIB@
|
||||
|
||||
CLIOBJS=cli-algo.o cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \
|
||||
cli-session.o cli-service.o cli-runopts.o cli-chansession.o \
|
||||
cli-authpubkey.o cli-tcpfwd.o cli-channel.o cli-authinteract.o
|
||||
|
||||
CLISVROBJS=common-session.o packet.o common-algo.o common-kex.o \
|
||||
common-channel.o common-chansession.o termcodes.o loginrec.o \
|
||||
tcp-accept.o listener.o process-packet.o \
|
||||
common-runopts.o circbuffer.o
|
||||
|
||||
KEYOBJS=dropbearkey.o gendss.o genrsa.o
|
||||
|
||||
CONVERTOBJS=dropbearconvert.o keyimport.o
|
||||
|
||||
SCPOBJS=scp.o progressmeter.o atomicio.o scpmisc.o
|
||||
|
||||
HEADERS=options.h dbutil.h session.h packet.h algo.h ssh.h buffer.h kex.h \
|
||||
dss.h bignum.h signkey.h rsa.h random.h service.h auth.h \
|
||||
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
|
||||
|
||||
dropbearobjs=$(COMMONOBJS) $(CLISVROBJS) $(SVROBJS)
|
||||
dbclientobjs=$(COMMONOBJS) $(CLISVROBJS) $(CLIOBJS)
|
||||
dropbearkeyobjs=$(COMMONOBJS) $(KEYOBJS)
|
||||
dropbearconvertobjs=$(COMMONOBJS) $(CONVERTOBJS)
|
||||
scpobjs=$(SCPOBJS)
|
||||
|
||||
VPATH=@srcdir@
|
||||
srcdir=@srcdir@
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=${prefix}
|
||||
bindir=${exec_prefix}/bin
|
||||
sbindir=${exec_prefix}/sbin
|
||||
|
||||
CC=@CC@
|
||||
AR=@AR@
|
||||
RANLIB=@RANLIB@
|
||||
STRIP=@STRIP@
|
||||
INSTALL=@INSTALL@
|
||||
CPPFLAGS=@CPPFLAGS@
|
||||
CFLAGS=-I. -I$(srcdir) -I$(srcdir)/libtomcrypt/src/headers/ $(CPPFLAGS) @CFLAGS@
|
||||
LIBS=$(LTC) $(LTM) @LIBS@
|
||||
LDFLAGS=@LDFLAGS@
|
||||
|
||||
EXEEXT=@EXEEXT@
|
||||
|
||||
# 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
|
||||
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
|
||||
export RANLIB AR STRIP
|
||||
|
||||
ifeq ($(STATIC), 1)
|
||||
LDFLAGS+=-static
|
||||
endif
|
||||
|
||||
ifeq ($(MULTI), 1)
|
||||
TARGETS=dropbearmulti
|
||||
else
|
||||
TARGETS=$(PROGRAMS)
|
||||
endif
|
||||
|
||||
# for the scp progress meter. The -D doesn't affect anything else.
|
||||
ifeq ($(SCPPROGRESS), 1)
|
||||
CFLAGS+=-DPROGRESS_METER
|
||||
endif
|
||||
|
||||
#%: $(HEADERS)
|
||||
#%: $(HEADERS) Makefile
|
||||
# TODO
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
strip: $(TARGETS)
|
||||
$(STRIP) $(addsuffix $(EXEEXT), $(TARGETS))
|
||||
|
||||
install: $(addprefix inst_, $(TARGETS))
|
||||
|
||||
installdropbearmulti: insdbmulti $(addprefix insmulti, $(PROGRAMS))
|
||||
|
||||
insdbmulti: dropbearmulti
|
||||
$(INSTALL) -d -m 755 $(DESTDIR)$(bindir)
|
||||
$(INSTALL) -m 755 dropbearmulti$(EXEEXT) $(DESTDIR)$(bindir)
|
||||
-chown root $(DESTDIR)$(bindir)/dropbearmulti$(EXEEXT)
|
||||
-chgrp 0 $(DESTDIR)$(bindir)/dropbearmulti$(EXEEXT)
|
||||
|
||||
insmultidropbear: dropbearmulti
|
||||
-rm -f $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
|
||||
-ln -s $(DESTDIR)$(bindir)/dropbearmulti$(EXEEXT) $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
|
||||
|
||||
insmulti%: dropbearmulti
|
||||
-rm -f $(DESTDIR)$(bindir)/$*$(EXEEXT)
|
||||
-ln -s $(DESTDIR)$(bindir)/dropbearmulti$(EXEEXT) $(DESTDIR)$(bindir)/$*$(EXEEXT)
|
||||
|
||||
# dropbear should go in sbin, so it needs a seperate rule
|
||||
inst_dropbear: dropbear
|
||||
$(INSTALL) -d -m 755 $(DESTDIR)$(sbindir)
|
||||
$(INSTALL) -m 755 dropbear$(EXEEXT) $(DESTDIR)$(sbindir)
|
||||
-chown root $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
|
||||
-chgrp 0 $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
|
||||
|
||||
inst_%: $*
|
||||
$(INSTALL) -d -m 755 $(DESTDIR)$(bindir)
|
||||
$(INSTALL) -m 755 $*$(EXEEXT) $(DESTDIR)$(bindir)
|
||||
-chown root $(DESTDIR)$(bindir)/$*$(EXEEXT)
|
||||
-chgrp 0 $(DESTDIR)$(bindir)/$*$(EXEEXT)
|
||||
|
||||
|
||||
# for some reason the rule further down doesn't like $($@objs) as a prereq.
|
||||
dropbear: $(dropbearobjs)
|
||||
dbclient: $(dbclientobjs)
|
||||
dropbearkey: $(dropbearkeyobjs)
|
||||
dropbearconvert: $(dropbearconvertobjs)
|
||||
|
||||
dropbear dbclient dropbearkey dropbearconvert: $(HEADERS) $(LTC) $(LTM) \
|
||||
Makefile
|
||||
$(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBS)
|
||||
|
||||
# scp doesn't use the libs so is special.
|
||||
scp: $(SCPOBJS) $(HEADERS) Makefile
|
||||
$(CC) $(LDFLAGS) -o $@$(EXEEXT) $(SCPOBJS)
|
||||
|
||||
|
||||
# multi-binary compilation.
|
||||
MULTIOBJS=
|
||||
ifeq ($(MULTI),1)
|
||||
MULTIOBJS=dbmulti.o $(sort $(foreach prog, $(PROGRAMS), $($(prog)objs)))
|
||||
CFLAGS+=$(addprefix -DDBMULTI_, $(PROGRAMS)) -DDROPBEAR_MULTI
|
||||
endif
|
||||
|
||||
dropbearmulti: multilink
|
||||
|
||||
multibinary: $(HEADERS) $(MULTIOBJS) $(LTC) $(LTM) Makefile
|
||||
$(CC) $(LDFLAGS) -o dropbearmulti$(EXEEXT) $(MULTIOBJS) $(LIBS)
|
||||
|
||||
multilink: multibinary $(addprefix link, $(PROGRAMS))
|
||||
|
||||
link%:
|
||||
-rm -f $*$(EXEEXT)
|
||||
-ln -s dropbearmulti$(EXEEXT) $*$(EXEEXT)
|
||||
|
||||
$(LTC): options.h
|
||||
cd libtomcrypt && $(MAKE) clean && $(MAKE)
|
||||
|
||||
$(LTM): options.h
|
||||
cd libtommath && $(MAKE)
|
||||
|
||||
.PHONY : clean sizes thisclean distclean tidy ltc-clean ltm-clean
|
||||
|
||||
ltc-clean:
|
||||
cd libtomcrypt && $(MAKE) clean
|
||||
|
||||
ltm-clean:
|
||||
cd libtommath && $(MAKE) clean
|
||||
|
||||
sizes: dropbear
|
||||
objdump -t dropbear|grep ".text"|cut -d "." -f 2|sort -rn
|
||||
|
||||
clean: ltc-clean ltm-clean thisclean
|
||||
|
||||
thisclean:
|
||||
-rm -f dropbear dbclient dropbearkey dropbearconvert scp scp-progress \
|
||||
dropbearmulti *.o *.da *.bb *.bbg *.prof
|
||||
|
||||
distclean: clean tidy
|
||||
-rm -f config.h
|
||||
-rm -f Makefile
|
||||
|
||||
tidy:
|
||||
-rm -f *~ *.gcov */*~
|
||||
74
README
Normal file
74
README
Normal file
@@ -0,0 +1,74 @@
|
||||
This is Dropbear, a smallish SSH 2 server and client.
|
||||
|
||||
INSTALL has compilation instructions.
|
||||
|
||||
MULTI has instructions on making a multi-purpose binary (ie a single binary
|
||||
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 :)
|
||||
|
||||
Matt Johnston
|
||||
matt@ucc.asn.au
|
||||
|
||||
|
||||
In the absence of detailed documentation, some notes follow:
|
||||
============================================================================
|
||||
|
||||
Server public key auth:
|
||||
|
||||
You can use ~/.ssh/authorized_keys in the same way as with OpenSSH, just put
|
||||
the key entries in that file. They should be of the form:
|
||||
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAwVa6M6cGVmUcLl2cFzkxEoJd06Ub4bVDsYrWvXhvUV+ZAM9uGuewZBDoAqNKJxoIn0Hyd0Nk/yU99UVv6NWV/5YSHtnf35LKds56j7cuzoQpFIdjNwdxAN0PCET/MG8qyskG/2IE2DPNIaJ3Wy+Ws4IZEgdJgPlTYUBWWtCWOGc= someone@hostname
|
||||
|
||||
You must make sure that ~/.ssh, and the key file, are only writable by the
|
||||
user. Beware of editors that split the key into multiple lines.
|
||||
|
||||
NOTE: Dropbear ignores authorized_keys options such as those described in the
|
||||
OpenSSH sshd manpage, and will not allow a login for these keys.
|
||||
|
||||
============================================================================
|
||||
|
||||
Client public key auth:
|
||||
|
||||
Dropbear can do public key auth as a client, but you will have to convert
|
||||
OpenSSH style keys to Dropbear format, or use dropbearkey to create them.
|
||||
|
||||
If you have an OpenSSH-style private key ~/.ssh/id_rsa, you need to do:
|
||||
|
||||
dropbearconvert openssh dropbear ~/.ssh/id_rsa ~/.ssh/id_rsa.db
|
||||
dbclient -i ~/.ssh/id_rsa.db <hostname>
|
||||
|
||||
Currently encrypted keys aren't supported, neither is agent forwarding. At some
|
||||
stage both hopefully will be.
|
||||
|
||||
============================================================================
|
||||
|
||||
If you want to get the public-key portion of a Dropbear private key, look at
|
||||
dropbearkey's '-y' option.
|
||||
|
||||
============================================================================
|
||||
|
||||
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
|
||||
|
||||
or alternatively convert OpenSSH keys to Dropbear:
|
||||
./dropbearconvert openssh dropbear /etc/ssh/ssh_host_dsa_key dropbear_dss_host_key
|
||||
|
||||
============================================================================
|
||||
|
||||
If the server is run as non-root, you most likely won't be able to allocate a
|
||||
pty, and you cannot login as any user other than that running the daemon
|
||||
(obviously). Shadow passwords will also be unusable as non-root.
|
||||
|
||||
============================================================================
|
||||
|
||||
The Dropbear distribution includes a standalone version of OpenSSH's scp
|
||||
program. You can compile it with "make scp", you may want to change the path
|
||||
of the ssh binary, specified by _PATH_SSH_PROGRAM in options.h . By default
|
||||
the progress meter isn't compiled in to save space, you can enable it by
|
||||
adding 'SCPPROGRESS=1' to the make commandline.
|
||||
53
SMALL
Normal file
53
SMALL
Normal file
@@ -0,0 +1,53 @@
|
||||
Tips for a small system:
|
||||
|
||||
If you only want server functionality (for example), compile with
|
||||
make PROGRAMS=dropbear
|
||||
rather than just
|
||||
make dropbear
|
||||
so that client functionality in shared portions of Dropbear won't be included.
|
||||
The same applies if you are compiling just a client.
|
||||
|
||||
---
|
||||
|
||||
The following are set in options.h:
|
||||
|
||||
- You can safely disable blowfish and twofish ciphers, and MD5 hmac, without
|
||||
affecting interoperability
|
||||
|
||||
- If you're compiling statically, you can turn off host lookups
|
||||
|
||||
- You can disable either password or public-key authentication, though note
|
||||
that the IETF draft states that pubkey authentication is required.
|
||||
|
||||
- Similarly with DSS and RSA, you can disable one of these if you know that
|
||||
all clients will be able to support a particular one. The IETF draft
|
||||
states that DSS is required, however you may prefer to use RSA.
|
||||
DON'T disable either of these on systems where you aren't 100% sure about
|
||||
who will be connecting and what clients they will be using.
|
||||
|
||||
- Disabling the MOTD code and SFTP-SERVER may save a small amount of codesize
|
||||
|
||||
- You can disable x11, tcp and agent forwarding as desired. None of these are
|
||||
essential, although agent-forwarding is often useful even on firewall boxes.
|
||||
|
||||
---
|
||||
|
||||
If you are compiling statically, you may want to disable zlib, as it will use
|
||||
a few tens of kB of binary-size (./configure --disable-zlib).
|
||||
|
||||
You can create a combined binary, see the file MULTI, which will put all
|
||||
the functions into one binary, avoiding repeated code.
|
||||
|
||||
If you're compiling with gcc, you might want to look at gcc's options for
|
||||
stripping unused code. The relevant vars to set before configure are:
|
||||
|
||||
LDFLAGS=-Wl,--gc-sections
|
||||
CFLAGS="-ffunction-sections -fdata-sections"
|
||||
|
||||
You can also experiment with optimisation flags such as -Os, note that in some
|
||||
cases these flags actually seem to increase size, so experiment before
|
||||
deciding.
|
||||
|
||||
Of course using small C libraries such as uClibc and dietlibc can also help.
|
||||
|
||||
If you have any queries, mail me and I'll see if I can help.
|
||||
27
TODO
Normal file
27
TODO
Normal file
@@ -0,0 +1,27 @@
|
||||
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 ?
|
||||
43
agentfwd.h
Normal file
43
agentfwd.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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 _AGENTFWD_H_
|
||||
#define _AGENTFWD_H_
|
||||
#ifndef DISABLE_AGENTFWD
|
||||
|
||||
#include "includes.h"
|
||||
#include "chansession.h"
|
||||
#include "channel.h"
|
||||
|
||||
int agentreq(struct ChanSess * chansess);
|
||||
void agentsetauth(struct ChanSess *chansess);
|
||||
void agentcleanup(struct ChanSess * chansess);
|
||||
void agentset(struct ChanSess *chansess);
|
||||
|
||||
#ifdef __hpux
|
||||
#define seteuid(a) setresuid(-1, (a), -1)
|
||||
#define setegid(a) setresgid(-1, (a), -1)
|
||||
#endif
|
||||
|
||||
#endif /* DROPBEAR_AGENTFWD */
|
||||
#endif /* _AGENTFWD_H_ */
|
||||
90
algo.h
Normal file
90
algo.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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 _ALGO_H_
|
||||
|
||||
#define _ALGO_H_
|
||||
|
||||
#include "includes.h"
|
||||
#include "buffer.h"
|
||||
|
||||
#define DROPBEAR_MODE_UNUSED 0
|
||||
#define DROPBEAR_MODE_CBC 1
|
||||
#define DROPBEAR_MODE_CTR 2
|
||||
|
||||
struct Algo_Type {
|
||||
|
||||
unsigned char *name; /* identifying name */
|
||||
char val; /* a value for this cipher, or -1 for invalid */
|
||||
const void *data; /* algorithm specific data */
|
||||
char usable; /* whether we can use this algorithm */
|
||||
const void *mode; /* the mode, currently only used for ciphers,
|
||||
points to a 'struct dropbear_cipher_mode' */
|
||||
};
|
||||
|
||||
typedef struct Algo_Type algo_type;
|
||||
|
||||
/* lists mapping ssh types of algorithms to internal values */
|
||||
extern algo_type sshkex[];
|
||||
extern algo_type sshhostkey[];
|
||||
extern algo_type sshciphers[];
|
||||
extern algo_type sshhashes[];
|
||||
extern algo_type sshcompress[];
|
||||
|
||||
extern const struct dropbear_cipher dropbear_nocipher;
|
||||
extern const struct dropbear_cipher_mode dropbear_mode_none;
|
||||
extern const struct dropbear_hash dropbear_nohash;
|
||||
|
||||
struct dropbear_cipher {
|
||||
const struct ltc_cipher_descriptor *cipherdesc;
|
||||
unsigned long keysize;
|
||||
unsigned char blocksize;
|
||||
};
|
||||
|
||||
struct dropbear_cipher_mode {
|
||||
int (*start)(int cipher, const unsigned char *IV,
|
||||
const unsigned char *key,
|
||||
int keylen, int num_rounds, void *cipher_state);
|
||||
int (*encrypt)(const unsigned char *pt, unsigned char *ct,
|
||||
unsigned long len, void *cipher_state);
|
||||
int (*decrypt)(const unsigned char *ct, unsigned char *pt,
|
||||
unsigned long len, void *cipher_state);
|
||||
};
|
||||
|
||||
struct dropbear_hash {
|
||||
const struct ltc_hash_descriptor *hashdesc;
|
||||
unsigned long keysize;
|
||||
unsigned char hashsize;
|
||||
};
|
||||
|
||||
void crypto_init();
|
||||
int have_algo(char* algo, size_t algolen, algo_type algos[]);
|
||||
void buf_put_algolist(buffer * buf, algo_type localalgos[]);
|
||||
|
||||
algo_type * svr_buf_match_algo(buffer* buf, algo_type localalgos[],
|
||||
int *goodguess);
|
||||
algo_type * cli_buf_match_algo(buffer* buf, algo_type localalgos[],
|
||||
int *goodguess);
|
||||
|
||||
#endif /* _ALGO_H_ */
|
||||
63
atomicio.c
Normal file
63
atomicio.c
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copied from OpenSSH 3.6.1p2.
|
||||
*
|
||||
* Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* RCSID("OpenBSD: atomicio.c,v 1.10 2001/05/08 22:48:07 markus Exp "); */
|
||||
|
||||
#include "atomicio.h"
|
||||
|
||||
/*
|
||||
* ensure all of data on socket comes through. f==read || f==write
|
||||
*/
|
||||
ssize_t
|
||||
atomicio(f, fd, _s, n)
|
||||
ssize_t (*f) ();
|
||||
int fd;
|
||||
void *_s;
|
||||
size_t n;
|
||||
{
|
||||
char *s = _s;
|
||||
ssize_t res;
|
||||
size_t pos = 0;
|
||||
|
||||
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;
|
||||
case 0:
|
||||
return (res);
|
||||
default:
|
||||
pos += res;
|
||||
}
|
||||
}
|
||||
return (pos);
|
||||
}
|
||||
36
atomicio.h
Normal file
36
atomicio.h
Normal file
@@ -0,0 +1,36 @@
|
||||
|
||||
/*
|
||||
* Copied from OpenSSH 3.6.1p2, required for loginrec.c
|
||||
*
|
||||
* $OpenBSD: atomicio.h,v 1.4 2001/06/26 06:32:46 itojun Exp $
|
||||
*
|
||||
* Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
/*
|
||||
* Ensure all of data on socket comes through. f==read || f==write
|
||||
*/
|
||||
ssize_t atomicio(ssize_t (*)(), int, void *, size_t);
|
||||
152
auth.h
Normal file
152
auth.h
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* 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 _AUTH_H_
|
||||
#define _AUTH_H_
|
||||
|
||||
#include "includes.h"
|
||||
#include "chansession.h"
|
||||
|
||||
void svr_authinitialise();
|
||||
void cli_authinitialise();
|
||||
|
||||
/* Server functions */
|
||||
void recv_msg_userauth_request();
|
||||
void send_msg_userauth_failure(int partial, int incrfail);
|
||||
void send_msg_userauth_success();
|
||||
void svr_auth_password();
|
||||
void svr_auth_pubkey();
|
||||
void svr_auth_pam();
|
||||
|
||||
#ifdef ENABLE_SVR_PUBKEY_OPTIONS
|
||||
int svr_pubkey_allows_agentfwd();
|
||||
int svr_pubkey_allows_tcpfwd();
|
||||
int svr_pubkey_allows_x11fwd();
|
||||
int svr_pubkey_allows_pty();
|
||||
void svr_pubkey_set_forced_command(struct ChanSess *chansess);
|
||||
void svr_pubkey_options_cleanup();
|
||||
int svr_add_pubkey_options(buffer *options_buf, int line_num, const char* filename);
|
||||
#else
|
||||
/* no option : success */
|
||||
#define svr_pubkey_allows_agentfwd() 1
|
||||
#define svr_pubkey_allows_tcpfwd() 1
|
||||
#define svr_pubkey_allows_x11fwd() 1
|
||||
#define svr_pubkey_allows_pty() 1
|
||||
static inline void svr_pubkey_set_forced_command(struct ChanSess *chansess) { }
|
||||
static inline void svr_pubkey_options_cleanup() { }
|
||||
#define svr_add_pubkey_options(x,y,z) DROPBEAR_SUCCESS
|
||||
#endif
|
||||
|
||||
/* Client functions */
|
||||
void recv_msg_userauth_failure();
|
||||
void recv_msg_userauth_success();
|
||||
void recv_msg_userauth_specific_60();
|
||||
void recv_msg_userauth_pk_ok();
|
||||
void recv_msg_userauth_info_request();
|
||||
void cli_get_user();
|
||||
void cli_auth_getmethods();
|
||||
void cli_auth_try();
|
||||
void recv_msg_userauth_banner();
|
||||
void cli_pubkeyfail();
|
||||
void cli_auth_password();
|
||||
int cli_auth_pubkey();
|
||||
void cli_auth_interactive();
|
||||
char* getpass_or_cancel(char* prompt);
|
||||
|
||||
|
||||
#define MAX_USERNAME_LEN 25 /* arbitrary for the moment */
|
||||
|
||||
#define AUTH_TYPE_NONE 1
|
||||
#define AUTH_TYPE_PUBKEY 1 << 1
|
||||
#define AUTH_TYPE_PASSWORD 1 << 2
|
||||
#define AUTH_TYPE_INTERACT 1 << 3
|
||||
|
||||
#define AUTH_METHOD_NONE "none"
|
||||
#define AUTH_METHOD_NONE_LEN 4
|
||||
#define AUTH_METHOD_PUBKEY "publickey"
|
||||
#define AUTH_METHOD_PUBKEY_LEN 9
|
||||
#define AUTH_METHOD_PASSWORD "password"
|
||||
#define AUTH_METHOD_PASSWORD_LEN 8
|
||||
#define AUTH_METHOD_INTERACT "keyboard-interactive"
|
||||
#define AUTH_METHOD_INTERACT_LEN 20
|
||||
|
||||
|
||||
|
||||
/* This structure is shared between server and client - it contains
|
||||
* relatively little extraneous bits when used for the client rather than the
|
||||
* server */
|
||||
struct AuthState {
|
||||
|
||||
char *username; /* This is the username the client presents to check. It
|
||||
is updated each run through, used for auth checking */
|
||||
unsigned char authtypes; /* Flags indicating which auth types are still
|
||||
valid */
|
||||
unsigned int failcount; /* Number of (failed) authentication attempts.*/
|
||||
unsigned authdone : 1; /* 0 if we haven't authed, 1 if we have. Applies for
|
||||
client and server (though has differing [obvious]
|
||||
meanings). */
|
||||
unsigned perm_warn : 1; /* Server only, set if bad permissions on
|
||||
~/.ssh/authorized_keys have already been
|
||||
logged. */
|
||||
|
||||
/* These are only used for the server */
|
||||
uid_t pw_uid;
|
||||
gid_t pw_gid;
|
||||
char *pw_dir;
|
||||
char *pw_shell;
|
||||
char *pw_name;
|
||||
char *pw_passwd;
|
||||
#ifdef ENABLE_SVR_PUBKEY_OPTIONS
|
||||
struct PubKeyOptions* pubkey_options;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
struct SignKeyList;
|
||||
/* A singly linked list of signing keys */
|
||||
struct SignKeyList {
|
||||
|
||||
sign_key *key;
|
||||
int type; /* The type of key */
|
||||
struct SignKeyList *next;
|
||||
/* filename? or the buffer? for encrypted keys, so we can later get
|
||||
* the private key portion */
|
||||
|
||||
};
|
||||
|
||||
#ifdef ENABLE_SVR_PUBKEY_OPTIONS
|
||||
struct PubKeyOptions;
|
||||
struct PubKeyOptions {
|
||||
/* Flags */
|
||||
int no_port_forwarding_flag;
|
||||
int no_agent_forwarding_flag;
|
||||
int no_x11_forwarding_flag;
|
||||
int no_pty_flag;
|
||||
/* "command=" option. */
|
||||
unsigned char * forced_command;
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* _AUTH_H_ */
|
||||
75
bignum.c
Normal file
75
bignum.c
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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. */
|
||||
|
||||
/* Contains helper functions for mp_int handling */
|
||||
|
||||
#include "includes.h"
|
||||
#include "dbutil.h"
|
||||
|
||||
/* wrapper for mp_init, failing fatally on errors (memory allocation) */
|
||||
void m_mp_init(mp_int *mp) {
|
||||
|
||||
if (mp_init(mp) != MP_OKAY) {
|
||||
dropbear_exit("mem alloc error");
|
||||
}
|
||||
}
|
||||
|
||||
/* simplified duplication of bn_mp_multi's mp_init_multi, but die fatally
|
||||
* on error */
|
||||
void m_mp_init_multi(mp_int *mp, ...)
|
||||
{
|
||||
mp_int* cur_arg = mp;
|
||||
va_list args;
|
||||
|
||||
va_start(args, mp); /* init args to next argument from caller */
|
||||
while (cur_arg != NULL) {
|
||||
if (mp_init(cur_arg) != MP_OKAY) {
|
||||
dropbear_exit("mem alloc error");
|
||||
}
|
||||
cur_arg = va_arg(args, mp_int*);
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void bytes_to_mp(mp_int *mp, const unsigned char* bytes, unsigned int len) {
|
||||
|
||||
if (mp_read_unsigned_bin(mp, (unsigned char*)bytes, len) != MP_OKAY) {
|
||||
dropbear_exit("mem alloc error");
|
||||
}
|
||||
}
|
||||
|
||||
/* hash the ssh representation of the mp_int mp */
|
||||
void sha1_process_mp(hash_state *hs, mp_int *mp) {
|
||||
|
||||
int i;
|
||||
buffer * buf;
|
||||
|
||||
buf = buf_new(512 + 20); /* max buffer is a 4096 bit key,
|
||||
plus header + some leeway*/
|
||||
buf_putmpint(buf, mp);
|
||||
i = buf->pos;
|
||||
buf_setpos(buf, 0);
|
||||
sha1_process(hs, buf_getptr(buf, i), i);
|
||||
buf_free(buf);
|
||||
}
|
||||
35
bignum.h
Normal file
35
bignum.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 _BIGNUM_H_
|
||||
#define _BIGNUM_H_
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
void m_mp_init(mp_int *mp);
|
||||
void m_mp_init_multi(mp_int *mp, ...);
|
||||
void bytes_to_mp(mp_int *mp, const unsigned char* bytes, unsigned int len);
|
||||
void sha1_process_mp(hash_state *hs, mp_int *mp);
|
||||
|
||||
#endif /* _BIGNUM_H_ */
|
||||
6
bn.ilg
6
bn.ilg
@@ -1,6 +0,0 @@
|
||||
This is makeindex, version 2.14 [02-Oct-2002] (kpathsea + Thai support).
|
||||
Scanning input file bn.idx....done (79 entries accepted, 0 rejected).
|
||||
Sorting entries....done (511 comparisons).
|
||||
Generating output file bn.ind....done (82 lines written, 0 warnings).
|
||||
Output written in bn.ind.
|
||||
Transcript written in bn.ilg.
|
||||
82
bn.ind
82
bn.ind
@@ -1,82 +0,0 @@
|
||||
\begin{theindex}
|
||||
|
||||
\item mp\_add, \hyperpage{31}
|
||||
\item mp\_add\_d, \hyperpage{56}
|
||||
\item mp\_and, \hyperpage{31}
|
||||
\item mp\_clear, \hyperpage{12}
|
||||
\item mp\_clear\_multi, \hyperpage{13}
|
||||
\item mp\_cmp, \hyperpage{25}
|
||||
\item mp\_cmp\_d, \hyperpage{26}
|
||||
\item mp\_cmp\_mag, \hyperpage{23}
|
||||
\item mp\_div, \hyperpage{32}
|
||||
\item mp\_div\_2, \hyperpage{28}
|
||||
\item mp\_div\_2d, \hyperpage{30}
|
||||
\item mp\_div\_d, \hyperpage{56}
|
||||
\item mp\_dr\_reduce, \hyperpage{45}
|
||||
\item mp\_dr\_setup, \hyperpage{45}
|
||||
\item MP\_EQ, \hyperpage{23}
|
||||
\item mp\_error\_to\_string, \hyperpage{9}
|
||||
\item mp\_expt\_d, \hyperpage{47}
|
||||
\item mp\_exptmod, \hyperpage{47}
|
||||
\item mp\_exteuclid, \hyperpage{55}
|
||||
\item mp\_gcd, \hyperpage{55}
|
||||
\item mp\_get\_int, \hyperpage{20}
|
||||
\item mp\_grow, \hyperpage{17}
|
||||
\item MP\_GT, \hyperpage{23}
|
||||
\item mp\_init, \hyperpage{11}
|
||||
\item mp\_init\_copy, \hyperpage{14}
|
||||
\item mp\_init\_multi, \hyperpage{13}
|
||||
\item mp\_init\_set, \hyperpage{21}
|
||||
\item mp\_init\_set\_int, \hyperpage{21}
|
||||
\item mp\_init\_size, \hyperpage{15}
|
||||
\item mp\_int, \hyperpage{10}
|
||||
\item mp\_invmod, \hyperpage{56}
|
||||
\item mp\_jacobi, \hyperpage{56}
|
||||
\item mp\_lcm, \hyperpage{56}
|
||||
\item mp\_lshd, \hyperpage{30}
|
||||
\item MP\_LT, \hyperpage{23}
|
||||
\item MP\_MEM, \hyperpage{9}
|
||||
\item mp\_mod, \hyperpage{39}
|
||||
\item mp\_mod\_d, \hyperpage{56}
|
||||
\item mp\_montgomery\_calc\_normalization, \hyperpage{42}
|
||||
\item mp\_montgomery\_reduce, \hyperpage{42}
|
||||
\item mp\_montgomery\_setup, \hyperpage{42}
|
||||
\item mp\_mul, \hyperpage{33}
|
||||
\item mp\_mul\_2, \hyperpage{28}
|
||||
\item mp\_mul\_2d, \hyperpage{29}
|
||||
\item mp\_mul\_d, \hyperpage{56}
|
||||
\item mp\_n\_root, \hyperpage{48}
|
||||
\item mp\_neg, \hyperpage{31, 32}
|
||||
\item MP\_NO, \hyperpage{9}
|
||||
\item MP\_OKAY, \hyperpage{9}
|
||||
\item mp\_or, \hyperpage{31}
|
||||
\item mp\_prime\_fermat, \hyperpage{49}
|
||||
\item mp\_prime\_is\_divisible, \hyperpage{49}
|
||||
\item mp\_prime\_is\_prime, \hyperpage{51}
|
||||
\item mp\_prime\_miller\_rabin, \hyperpage{50}
|
||||
\item mp\_prime\_next\_prime, \hyperpage{51}
|
||||
\item mp\_prime\_rabin\_miller\_trials, \hyperpage{50}
|
||||
\item mp\_prime\_random, \hyperpage{51}
|
||||
\item mp\_prime\_random\_ex, \hyperpage{52}
|
||||
\item mp\_radix\_size, \hyperpage{53}
|
||||
\item mp\_read\_radix, \hyperpage{53}
|
||||
\item mp\_read\_unsigned\_bin, \hyperpage{54}
|
||||
\item mp\_reduce, \hyperpage{40}
|
||||
\item mp\_reduce\_2k, \hyperpage{46}
|
||||
\item mp\_reduce\_2k\_setup, \hyperpage{46}
|
||||
\item mp\_reduce\_setup, \hyperpage{40}
|
||||
\item mp\_rshd, \hyperpage{30}
|
||||
\item mp\_set, \hyperpage{19}
|
||||
\item mp\_set\_int, \hyperpage{20}
|
||||
\item mp\_shrink, \hyperpage{16}
|
||||
\item mp\_sqr, \hyperpage{35}
|
||||
\item mp\_sub, \hyperpage{31}
|
||||
\item mp\_sub\_d, \hyperpage{56}
|
||||
\item mp\_to\_unsigned\_bin, \hyperpage{54}
|
||||
\item mp\_toradix, \hyperpage{53}
|
||||
\item mp\_unsigned\_bin\_size, \hyperpage{54}
|
||||
\item MP\_VAL, \hyperpage{9}
|
||||
\item mp\_xor, \hyperpage{31}
|
||||
\item MP\_YES, \hyperpage{9}
|
||||
|
||||
\end{theindex}
|
||||
338
buffer.c
Normal file
338
buffer.c
Normal file
@@ -0,0 +1,338 @@
|
||||
/*
|
||||
* Dropbear SSH
|
||||
*
|
||||
* 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. */
|
||||
|
||||
/* Buffer handling routines, designed to avoid overflows/using invalid data */
|
||||
|
||||
#include "includes.h"
|
||||
#include "dbutil.h"
|
||||
#include "buffer.h"
|
||||
|
||||
/* Prevent integer overflows when incrementing buffer position/length.
|
||||
* Calling functions should check arguments first, but this provides a
|
||||
* backstop */
|
||||
#define BUF_MAX_INCR 1000000000
|
||||
#define BUF_MAX_SIZE 1000000000
|
||||
|
||||
/* avoid excessively large numbers, > ~8192 bits */
|
||||
#define BUF_MAX_MPINT (8240 / 8)
|
||||
|
||||
/* Create (malloc) a new buffer of size */
|
||||
buffer* buf_new(unsigned int size) {
|
||||
|
||||
buffer* buf;
|
||||
|
||||
if (size > BUF_MAX_SIZE) {
|
||||
dropbear_exit("buf->size too big");
|
||||
}
|
||||
|
||||
buf = (buffer*)m_malloc(sizeof(buffer));
|
||||
|
||||
if (size > 0) {
|
||||
buf->data = (unsigned char*)m_malloc(size);
|
||||
} else {
|
||||
buf->data = NULL;
|
||||
}
|
||||
|
||||
buf->size = size;
|
||||
buf->pos = 0;
|
||||
buf->len = 0;
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
/* free the buffer's data and the buffer itself */
|
||||
void buf_free(buffer* buf) {
|
||||
|
||||
m_free(buf->data)
|
||||
m_free(buf);
|
||||
}
|
||||
|
||||
/* overwrite the contents of the buffer to clear it */
|
||||
void buf_burn(buffer* buf) {
|
||||
|
||||
m_burn(buf->data, buf->size);
|
||||
|
||||
}
|
||||
|
||||
/* resize a buffer, pos and len will be repositioned if required when
|
||||
* downsizing */
|
||||
void buf_resize(buffer *buf, unsigned int newsize) {
|
||||
|
||||
if (newsize > BUF_MAX_SIZE) {
|
||||
dropbear_exit("buf->size too big");
|
||||
}
|
||||
|
||||
buf->data = m_realloc(buf->data, newsize);
|
||||
buf->size = newsize;
|
||||
buf->len = MIN(newsize, buf->len);
|
||||
buf->pos = MIN(newsize, buf->pos);
|
||||
|
||||
}
|
||||
|
||||
/* 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* ret;
|
||||
|
||||
ret = buf_new(buf->len);
|
||||
ret->len = buf->len;
|
||||
memcpy(ret->data, buf->data, buf->len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set the length of the buffer */
|
||||
void buf_setlen(buffer* buf, unsigned int len) {
|
||||
if (len > buf->size) {
|
||||
dropbear_exit("bad buf_setlen");
|
||||
}
|
||||
buf->len = len;
|
||||
}
|
||||
|
||||
/* Increment the length of the buffer */
|
||||
void buf_incrlen(buffer* buf, unsigned int incr) {
|
||||
if (incr > BUF_MAX_INCR || buf->len + incr > buf->size) {
|
||||
dropbear_exit("bad buf_incrlen");
|
||||
}
|
||||
buf->len += incr;
|
||||
}
|
||||
/* Set the position of the buffer */
|
||||
void buf_setpos(buffer* buf, unsigned int pos) {
|
||||
|
||||
if (pos > buf->len) {
|
||||
dropbear_exit("bad buf_setpos");
|
||||
}
|
||||
buf->pos = pos;
|
||||
}
|
||||
|
||||
/* increment the postion by incr, increasing the buffer length if required */
|
||||
void buf_incrwritepos(buffer* buf, unsigned int incr) {
|
||||
if (incr > BUF_MAX_INCR || buf->pos + incr > buf->size) {
|
||||
dropbear_exit("bad buf_incrwritepos");
|
||||
}
|
||||
buf->pos += incr;
|
||||
if (buf->pos > buf->len) {
|
||||
buf->len = buf->pos;
|
||||
}
|
||||
}
|
||||
|
||||
/* increment the position by incr, negative values are allowed, to
|
||||
* decrement the pos*/
|
||||
void buf_incrpos(buffer* buf, int incr) {
|
||||
if (incr > BUF_MAX_INCR ||
|
||||
(unsigned int)((int)buf->pos + incr) > buf->len
|
||||
|| ((int)buf->pos + incr) < 0) {
|
||||
dropbear_exit("bad buf_incrpos");
|
||||
}
|
||||
buf->pos += incr;
|
||||
}
|
||||
|
||||
/* Get a byte from the buffer and increment the pos */
|
||||
unsigned char buf_getbyte(buffer* buf) {
|
||||
|
||||
/* This check is really just ==, but the >= allows us to check for the
|
||||
* bad case of pos > len, which should _never_ happen. */
|
||||
if (buf->pos >= buf->len) {
|
||||
dropbear_exit("bad buf_getbyte");
|
||||
}
|
||||
return buf->data[buf->pos++];
|
||||
}
|
||||
|
||||
/* Get a bool from the buffer and increment the pos */
|
||||
unsigned char buf_getbool(buffer* buf) {
|
||||
|
||||
unsigned char b;
|
||||
b = buf_getbyte(buf);
|
||||
if (b != 0)
|
||||
b = 1;
|
||||
return b;
|
||||
}
|
||||
|
||||
/* put a byte, incrementing the length if required */
|
||||
void buf_putbyte(buffer* buf, unsigned char val) {
|
||||
|
||||
if (buf->pos >= buf->len) {
|
||||
buf_incrlen(buf, 1);
|
||||
}
|
||||
buf->data[buf->pos] = val;
|
||||
buf->pos++;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
|
||||
if (buf->pos + len > buf->len) {
|
||||
dropbear_exit("bad buf_getptr");
|
||||
}
|
||||
return &buf->data[buf->pos];
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
|
||||
if (buf->pos + len > buf->size) {
|
||||
dropbear_exit("bad buf_getwriteptr");
|
||||
}
|
||||
return &buf->data[buf->pos];
|
||||
}
|
||||
|
||||
/* Return a null-terminated string, it is malloced, so must be free()ed
|
||||
* Note that the string isn't checked for null bytes, hence the retlen
|
||||
* may be longer than what is returned by strlen */
|
||||
unsigned char* buf_getstring(buffer* buf, unsigned int *retlen) {
|
||||
|
||||
unsigned int len;
|
||||
unsigned char* ret;
|
||||
len = buf_getint(buf);
|
||||
if (len > MAX_STRING_LEN) {
|
||||
dropbear_exit("string too long");
|
||||
}
|
||||
|
||||
if (retlen != NULL) {
|
||||
*retlen = len;
|
||||
}
|
||||
ret = m_malloc(len+1);
|
||||
memcpy(ret, buf_getptr(buf, len), len);
|
||||
buf_incrpos(buf, len);
|
||||
ret[len] = '\0';
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Just increment the buffer position the same as if we'd used buf_getstring,
|
||||
* but don't bother copying/malloc()ing for it */
|
||||
void buf_eatstring(buffer *buf) {
|
||||
|
||||
buf_incrpos( buf, buf_getint(buf) );
|
||||
}
|
||||
|
||||
/* Get an uint32 from the buffer and increment the pos */
|
||||
unsigned int buf_getint(buffer* buf) {
|
||||
unsigned int ret;
|
||||
|
||||
LOAD32H(ret, buf_getptr(buf, 4));
|
||||
buf_incrpos(buf, 4);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* put a 32bit uint into the buffer, incr bufferlen & pos if required */
|
||||
void buf_putint(buffer* buf, int unsigned val) {
|
||||
|
||||
STORE32H(val, buf_getwriteptr(buf, 4));
|
||||
buf_incrwritepos(buf, 4);
|
||||
|
||||
}
|
||||
|
||||
/* put a SSH style string into the buffer, increasing buffer len if required */
|
||||
void buf_putstring(buffer* buf, const unsigned char* str, unsigned int len) {
|
||||
|
||||
buf_putint(buf, len);
|
||||
buf_putbytes(buf, str, len);
|
||||
|
||||
}
|
||||
|
||||
/* put the set of len bytes into the buffer, incrementing the pos, increasing
|
||||
* len if required */
|
||||
void buf_putbytes(buffer *buf, const unsigned char *bytes, unsigned int len) {
|
||||
memcpy(buf_getwriteptr(buf, len), bytes, len);
|
||||
buf_incrwritepos(buf, 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) {
|
||||
|
||||
unsigned int len, pad = 0;
|
||||
TRACE(("enter buf_putmpint"))
|
||||
|
||||
dropbear_assert(mp != NULL);
|
||||
|
||||
if (SIGN(mp) == MP_NEG) {
|
||||
dropbear_exit("negative bignum");
|
||||
}
|
||||
|
||||
/* zero check */
|
||||
if (USED(mp) == 1 && DIGIT(mp, 0) == 0) {
|
||||
len = 0;
|
||||
} else {
|
||||
/* SSH spec requires padding for mpints with the MSB set, this code
|
||||
* implements it */
|
||||
len = mp_count_bits(mp);
|
||||
/* if the top bit of MSB is set, we need to pad */
|
||||
pad = (len%8 == 0) ? 1 : 0;
|
||||
len = len / 8 + 1; /* don't worry about rounding, we need it for
|
||||
padding anyway when len%8 == 0 */
|
||||
|
||||
}
|
||||
|
||||
/* store the length */
|
||||
buf_putint(buf, len);
|
||||
|
||||
/* store the actual value */
|
||||
if (len > 0) {
|
||||
if (pad) {
|
||||
buf_putbyte(buf, 0x00);
|
||||
}
|
||||
if (mp_to_unsigned_bin(mp, buf_getwriteptr(buf, len-pad)) != MP_OKAY) {
|
||||
dropbear_exit("mpint error");
|
||||
}
|
||||
buf_incrwritepos(buf, len-pad);
|
||||
}
|
||||
|
||||
TRACE(("leave buf_putmpint"))
|
||||
}
|
||||
|
||||
/* Retrieve an mp_int from the buffer.
|
||||
* Will fail for -ve since they shouldn't be required here.
|
||||
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
|
||||
int buf_getmpint(buffer* buf, mp_int* mp) {
|
||||
|
||||
unsigned int len;
|
||||
len = buf_getint(buf);
|
||||
|
||||
if (len == 0) {
|
||||
mp_zero(mp);
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
|
||||
if (len > BUF_MAX_MPINT) {
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
/* check for negative */
|
||||
if (*buf_getptr(buf, 1) & (1 << (CHAR_BIT-1))) {
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
if (mp_read_unsigned_bin(mp, buf_getptr(buf, len), len) != MP_OKAY) {
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
buf_incrpos(buf, len);
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
66
buffer.h
Normal file
66
buffer.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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 _BUFFER_H_
|
||||
|
||||
#define _BUFFER_H_
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
struct buf {
|
||||
|
||||
unsigned char * data;
|
||||
unsigned int len; /* the used size */
|
||||
unsigned int pos;
|
||||
unsigned int size; /* the memory size */
|
||||
|
||||
};
|
||||
|
||||
typedef struct buf buffer;
|
||||
|
||||
buffer * buf_new(unsigned int size);
|
||||
void buf_resize(buffer *buf, unsigned int newsize);
|
||||
void buf_free(buffer* buf);
|
||||
void buf_burn(buffer* buf);
|
||||
buffer* buf_newcopy(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);
|
||||
void buf_incrpos(buffer* buf, int incr); /* -ve is ok, to go backwards */
|
||||
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_getstring(buffer* buf, unsigned int *retlen);
|
||||
void buf_eatstring(buffer *buf);
|
||||
void buf_putint(buffer* buf, unsigned int val);
|
||||
void buf_putstring(buffer* buf, const unsigned char* str, unsigned int len);
|
||||
void buf_putbytes(buffer *buf, const unsigned char *bytes, unsigned int len);
|
||||
void buf_putmpint(buffer* buf, mp_int * mp);
|
||||
int buf_getmpint(buffer* buf, mp_int* mp);
|
||||
unsigned int buf_getint(buffer* buf);
|
||||
|
||||
#endif /* _BUFFER_H_ */
|
||||
11913
callgraph.txt
11913
callgraph.txt
File diff suppressed because it is too large
Load Diff
128
channel.h
Normal file
128
channel.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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 _CHANNEL_H_
|
||||
#define _CHANNEL_H_
|
||||
|
||||
#include "includes.h"
|
||||
#include "buffer.h"
|
||||
#include "circbuffer.h"
|
||||
|
||||
/* channel->type values */
|
||||
#define CHANNEL_ID_NONE 0
|
||||
#define CHANNEL_ID_SESSION 1
|
||||
#define CHANNEL_ID_X11 2
|
||||
#define CHANNEL_ID_AGENT 3
|
||||
#define CHANNEL_ID_TCPDIRECT 4
|
||||
#define CHANNEL_ID_TCPFORWARDED 5
|
||||
|
||||
#define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED 1
|
||||
#define SSH_OPEN_CONNECT_FAILED 2
|
||||
#define SSH_OPEN_UNKNOWN_CHANNEL_TYPE 3
|
||||
#define SSH_OPEN_RESOURCE_SHORTAGE 4
|
||||
|
||||
/* Not a real type */
|
||||
#define SSH_OPEN_IN_PROGRESS 99
|
||||
|
||||
#define CHAN_EXTEND_SIZE 3 /* how many extra slots to add when we need more */
|
||||
|
||||
struct ChanType;
|
||||
|
||||
struct Channel {
|
||||
|
||||
unsigned int index; /* the local channel index */
|
||||
unsigned int remotechan;
|
||||
unsigned int recvwindow, transwindow;
|
||||
unsigned int recvdonelen;
|
||||
unsigned int recvmaxpacket, transmaxpacket;
|
||||
void* typedata; /* a pointer to type specific data */
|
||||
int writefd; /* read from wire, written to insecure side */
|
||||
int readfd; /* read from insecure size, written to wire */
|
||||
int errfd; /* used like writefd or readfd, depending if it's client or server.
|
||||
Doesn't exactly belong here, but is cleaner here */
|
||||
circbuffer *writebuf; /* data from the wire, for local consumption */
|
||||
circbuffer *extrabuf; /* extended-data for the program - used like writebuf
|
||||
but for stderr */
|
||||
|
||||
/* whether close/eof messages have been exchanged */
|
||||
int sent_close, recv_close;
|
||||
int recv_eof, sent_eof;
|
||||
|
||||
int initconn; /* used for TCP forwarding, whether the channel has been
|
||||
fully initialised */
|
||||
|
||||
int await_open; /* flag indicating whether we've sent an open request
|
||||
for this channel (and are awaiting a confirmation
|
||||
or failure). */
|
||||
|
||||
int flushing;
|
||||
|
||||
const struct ChanType* type;
|
||||
|
||||
};
|
||||
|
||||
struct ChanType {
|
||||
|
||||
int sepfds; /* Whether this channel has seperate pipes for in/out or not */
|
||||
char *name;
|
||||
int (*inithandler)(struct Channel*);
|
||||
int (*check_close)(struct Channel*);
|
||||
void (*reqhandler)(struct Channel*);
|
||||
void (*closehandler)(struct Channel*);
|
||||
|
||||
};
|
||||
|
||||
void chaninitialise(const struct ChanType *chantypes[]);
|
||||
void chancleanup();
|
||||
void setchannelfds(fd_set *readfd, fd_set *writefd);
|
||||
void channelio(fd_set *readfd, fd_set *writefd);
|
||||
struct Channel* getchannel();
|
||||
struct Channel* newchannel(unsigned int remotechan,
|
||||
const struct ChanType *type,
|
||||
unsigned int transwindow, unsigned int transmaxpacket);
|
||||
|
||||
void recv_msg_channel_open();
|
||||
void recv_msg_channel_request();
|
||||
void send_msg_channel_failure(struct Channel *channel);
|
||||
void send_msg_channel_success(struct Channel *channel);
|
||||
void recv_msg_channel_data();
|
||||
void recv_msg_channel_extended_data();
|
||||
void recv_msg_channel_window_adjust();
|
||||
void recv_msg_channel_close();
|
||||
void recv_msg_channel_eof();
|
||||
|
||||
void common_recv_msg_channel_data(struct Channel *channel, int fd,
|
||||
circbuffer * buf);
|
||||
|
||||
#ifdef DROPBEAR_CLIENT
|
||||
extern const struct ChanType clichansess;
|
||||
#endif
|
||||
|
||||
#if defined(USING_LISTENERS) || defined(DROPBEAR_CLIENT)
|
||||
int send_msg_channel_open_init(int fd, const struct ChanType *type);
|
||||
void recv_msg_channel_open_confirmation();
|
||||
void recv_msg_channel_open_failure();
|
||||
#endif
|
||||
|
||||
#endif /* _CHANNEL_H_ */
|
||||
95
chansession.h
Normal file
95
chansession.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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 _CHANSESSION_H_
|
||||
#define _CHANSESSION_H_
|
||||
|
||||
#include "loginrec.h"
|
||||
#include "channel.h"
|
||||
#include "listener.h"
|
||||
|
||||
struct exitinfo {
|
||||
|
||||
int exitpid; /* -1 if not exited */
|
||||
int exitstatus;
|
||||
int exitsignal;
|
||||
int exitcore;
|
||||
};
|
||||
|
||||
struct ChanSess {
|
||||
|
||||
unsigned char * cmd; /* command to exec */
|
||||
pid_t pid; /* child process pid */
|
||||
|
||||
/* pty details */
|
||||
int master; /* the master terminal fd*/
|
||||
int slave;
|
||||
unsigned char * tty;
|
||||
unsigned char * term;
|
||||
|
||||
/* exit details */
|
||||
struct exitinfo exit;
|
||||
|
||||
#ifndef DISABLE_X11FWD
|
||||
struct Listener * x11listener;
|
||||
int x11port;
|
||||
char * x11authprot;
|
||||
char * x11authcookie;
|
||||
unsigned int x11screennum;
|
||||
unsigned char x11singleconn;
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_AGENTFWD
|
||||
struct Listener * agentlistener;
|
||||
char * agentfile;
|
||||
char * agentdir;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ChildPid {
|
||||
pid_t pid;
|
||||
struct ChanSess * chansess;
|
||||
};
|
||||
|
||||
|
||||
void addnewvar(const char* param, const char* var);
|
||||
|
||||
void cli_send_chansess_request();
|
||||
void cli_tty_cleanup();
|
||||
void cli_chansess_winchange();
|
||||
#ifdef ENABLE_CLI_NETCAT
|
||||
void cli_send_netcat_request();
|
||||
#endif
|
||||
|
||||
void svr_chansessinitialise();
|
||||
extern const struct ChanType svrchansess;
|
||||
|
||||
struct SigMap {
|
||||
int signal;
|
||||
char* name;
|
||||
};
|
||||
|
||||
extern const struct SigMap signames[];
|
||||
|
||||
#endif /* _CHANSESSION_H_ */
|
||||
138
circbuffer.c
Normal file
138
circbuffer.c
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Dropbear SSH
|
||||
*
|
||||
* Copyright (c) 2002-2004 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 "circbuffer.h"
|
||||
|
||||
#define MAX_CBUF_SIZE 100000000
|
||||
|
||||
circbuffer * cbuf_new(unsigned int size) {
|
||||
|
||||
circbuffer *cbuf = NULL;
|
||||
|
||||
if (size > MAX_CBUF_SIZE) {
|
||||
dropbear_exit("bad cbuf size");
|
||||
}
|
||||
|
||||
cbuf = (circbuffer*)m_malloc(sizeof(circbuffer));
|
||||
cbuf->data = (unsigned char*)m_malloc(size);
|
||||
cbuf->used = 0;
|
||||
cbuf->readpos = 0;
|
||||
cbuf->writepos = 0;
|
||||
cbuf->size = size;
|
||||
|
||||
return cbuf;
|
||||
}
|
||||
|
||||
void cbuf_free(circbuffer * cbuf) {
|
||||
|
||||
m_free(cbuf->data);
|
||||
m_free(cbuf);
|
||||
}
|
||||
|
||||
unsigned int cbuf_getused(circbuffer * cbuf) {
|
||||
|
||||
return cbuf->used;
|
||||
|
||||
}
|
||||
|
||||
unsigned int cbuf_getavail(circbuffer * cbuf) {
|
||||
|
||||
return cbuf->size - cbuf->used;
|
||||
|
||||
}
|
||||
|
||||
unsigned int cbuf_readlen(circbuffer *cbuf) {
|
||||
|
||||
dropbear_assert(((2*cbuf->size)+cbuf->writepos-cbuf->readpos)%cbuf->size == cbuf->used%cbuf->size);
|
||||
dropbear_assert(((2*cbuf->size)+cbuf->readpos-cbuf->writepos)%cbuf->size == (cbuf->size-cbuf->used)%cbuf->size);
|
||||
|
||||
if (cbuf->used == 0) {
|
||||
TRACE(("cbuf_readlen: unused buffer"))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cbuf->readpos < cbuf->writepos) {
|
||||
return cbuf->writepos - cbuf->readpos;
|
||||
}
|
||||
|
||||
return cbuf->size - cbuf->readpos;
|
||||
}
|
||||
|
||||
unsigned int cbuf_writelen(circbuffer *cbuf) {
|
||||
|
||||
dropbear_assert(cbuf->used <= cbuf->size);
|
||||
dropbear_assert(((2*cbuf->size)+cbuf->writepos-cbuf->readpos)%cbuf->size == cbuf->used%cbuf->size);
|
||||
dropbear_assert(((2*cbuf->size)+cbuf->readpos-cbuf->writepos)%cbuf->size == (cbuf->size-cbuf->used)%cbuf->size);
|
||||
|
||||
if (cbuf->used == cbuf->size) {
|
||||
TRACE(("cbuf_writelen: full buffer"))
|
||||
return 0; /* full */
|
||||
}
|
||||
|
||||
if (cbuf->writepos < cbuf->readpos) {
|
||||
return cbuf->readpos - cbuf->writepos;
|
||||
}
|
||||
|
||||
return cbuf->size - cbuf->writepos;
|
||||
}
|
||||
|
||||
unsigned char* cbuf_readptr(circbuffer *cbuf, unsigned int len) {
|
||||
if (len > cbuf_readlen(cbuf)) {
|
||||
dropbear_exit("bad cbuf read");
|
||||
}
|
||||
|
||||
return &cbuf->data[cbuf->readpos];
|
||||
}
|
||||
|
||||
unsigned char* cbuf_writeptr(circbuffer *cbuf, unsigned int len) {
|
||||
|
||||
if (len > cbuf_writelen(cbuf)) {
|
||||
dropbear_exit("bad cbuf write");
|
||||
}
|
||||
|
||||
return &cbuf->data[cbuf->writepos];
|
||||
}
|
||||
|
||||
void cbuf_incrwrite(circbuffer *cbuf, unsigned int len) {
|
||||
if (len > cbuf_writelen(cbuf)) {
|
||||
dropbear_exit("bad cbuf write");
|
||||
}
|
||||
|
||||
cbuf->used += len;
|
||||
dropbear_assert(cbuf->used <= cbuf->size);
|
||||
cbuf->writepos = (cbuf->writepos + len) % cbuf->size;
|
||||
}
|
||||
|
||||
|
||||
void cbuf_incrread(circbuffer *cbuf, unsigned int len) {
|
||||
if (len > cbuf_readlen(cbuf)) {
|
||||
dropbear_exit("bad cbuf read");
|
||||
}
|
||||
|
||||
dropbear_assert(cbuf->used >= len);
|
||||
cbuf->used -= len;
|
||||
cbuf->readpos = (cbuf->readpos + len) % cbuf->size;
|
||||
}
|
||||
50
circbuffer.h
Normal file
50
circbuffer.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Dropbear SSH
|
||||
*
|
||||
* Copyright (c) 2002-2004 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 _CIRCBUFFER_H_
|
||||
#define _CIRCBUFFER_H_
|
||||
struct circbuf {
|
||||
|
||||
unsigned int size;
|
||||
unsigned int readpos;
|
||||
unsigned int writepos;
|
||||
unsigned int used;
|
||||
unsigned char* data;
|
||||
};
|
||||
|
||||
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_readlen(circbuffer *cbuf); /* max linear read len */
|
||||
unsigned int cbuf_writelen(circbuffer *cbuf); /* max linear write len */
|
||||
|
||||
unsigned char* cbuf_readptr(circbuffer *cbuf, unsigned int len);
|
||||
unsigned char* cbuf_writeptr(circbuffer *cbuf, unsigned int len);
|
||||
void cbuf_incrwrite(circbuffer *cbuf, unsigned int len);
|
||||
void cbuf_incrread(circbuffer *cbuf, unsigned int len);
|
||||
#endif
|
||||
99
cli-algo.c
Normal file
99
cli-algo.c
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Dropbear - a SSH2 server
|
||||
* SSH client implementation
|
||||
*
|
||||
* Copyright (c) 2002,2003 Matt Johnston
|
||||
* Copyright (c) 2004 by Mihnea Stoenescu
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#include "algo.h"
|
||||
#include "dbutil.h"
|
||||
|
||||
|
||||
/*
|
||||
* The chosen [encryption | MAC | compression] algorithm to each
|
||||
* direction MUST be the first algorithm on the client's list
|
||||
* that is also on the server's list.
|
||||
*/
|
||||
algo_type * cli_buf_match_algo(buffer* buf, algo_type localalgos[],
|
||||
int *goodguess) {
|
||||
|
||||
unsigned char * algolist = NULL;
|
||||
unsigned char * remotealgos[MAX_PROPOSED_ALGO];
|
||||
unsigned int len;
|
||||
unsigned int count, i, j;
|
||||
algo_type * ret = NULL;
|
||||
|
||||
*goodguess = 0;
|
||||
|
||||
/* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */
|
||||
algolist = buf_getstring(buf, &len);
|
||||
TRACE(("cli_buf_match_algo: %s", algolist))
|
||||
if (len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
|
||||
goto out; /* just a sanity check, no other use */
|
||||
}
|
||||
|
||||
/* remotealgos will contain a list of the strings parsed out */
|
||||
/* We will have at least one string (even if it's just "") */
|
||||
remotealgos[0] = algolist;
|
||||
count = 1;
|
||||
/* Iterate through, replacing ','s with NULs, to split it into
|
||||
* words. */
|
||||
for (i = 0; i < len; i++) {
|
||||
if (algolist[i] == '\0') {
|
||||
/* someone is trying something strange */
|
||||
goto out;
|
||||
}
|
||||
if (algolist[i] == ',') {
|
||||
algolist[i] = '\0';
|
||||
remotealgos[count] = &algolist[i+1];
|
||||
count++;
|
||||
}
|
||||
if (count == MAX_PROPOSED_ALGO) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* iterate and find the first match */
|
||||
|
||||
for (j = 0; localalgos[j].name != NULL; j++) {
|
||||
if (localalgos[j].usable) {
|
||||
len = strlen(localalgos[j].name);
|
||||
for (i = 0; i < count; i++) {
|
||||
if (len == strlen(remotealgos[i])
|
||||
&& strncmp(localalgos[j].name,
|
||||
remotealgos[i], len) == 0) {
|
||||
if (i == 0 && j == 0) {
|
||||
/* was a good guess */
|
||||
*goodguess = 1;
|
||||
}
|
||||
ret = &localalgos[j];
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
m_free(algolist);
|
||||
return ret;
|
||||
}
|
||||
|
||||
306
cli-auth.c
Normal file
306
cli-auth.c
Normal file
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* Dropbear SSH
|
||||
*
|
||||
* Copyright (c) 2002,2003 Matt Johnston
|
||||
* Copyright (c) 2004 by Mihnea Stoenescu
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#include "includes.h"
|
||||
#include "session.h"
|
||||
#include "auth.h"
|
||||
#include "dbutil.h"
|
||||
#include "buffer.h"
|
||||
#include "ssh.h"
|
||||
#include "packet.h"
|
||||
#include "runopts.h"
|
||||
|
||||
void cli_authinitialise() {
|
||||
|
||||
memset(&ses.authstate, 0, sizeof(ses.authstate));
|
||||
}
|
||||
|
||||
|
||||
/* Send a "none" auth request to get available methods */
|
||||
void cli_auth_getmethods() {
|
||||
|
||||
TRACE(("enter cli_auth_getmethods"))
|
||||
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);
|
||||
buf_putstring(ses.writepayload, cli_opts.username,
|
||||
strlen(cli_opts.username));
|
||||
buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
|
||||
SSH_SERVICE_CONNECTION_LEN);
|
||||
buf_putstring(ses.writepayload, "none", 4); /* 'none' method */
|
||||
|
||||
encrypt_packet();
|
||||
TRACE(("leave cli_auth_getmethods"))
|
||||
|
||||
}
|
||||
|
||||
void recv_msg_userauth_banner() {
|
||||
|
||||
unsigned char* banner = NULL;
|
||||
unsigned int bannerlen;
|
||||
unsigned int i, linecount;
|
||||
|
||||
TRACE(("enter recv_msg_userauth_banner"))
|
||||
if (ses.authstate.authdone) {
|
||||
TRACE(("leave recv_msg_userauth_banner: banner after auth done"))
|
||||
return;
|
||||
}
|
||||
|
||||
banner = buf_getstring(ses.payload, &bannerlen);
|
||||
buf_eatstring(ses.payload); /* The language string */
|
||||
|
||||
if (bannerlen > MAX_BANNER_SIZE) {
|
||||
TRACE(("recv_msg_userauth_banner: bannerlen too long: %d", bannerlen))
|
||||
goto out;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
linecount++;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s\n", banner);
|
||||
|
||||
out:
|
||||
m_free(banner);
|
||||
TRACE(("leave recv_msg_userauth_banner"))
|
||||
}
|
||||
|
||||
/* This handles the message-specific types which
|
||||
* all have a value of 60. These are
|
||||
* SSH_MSG_USERAUTH_PASSWD_CHANGEREQ,
|
||||
* SSH_MSG_USERAUTH_PK_OK, &
|
||||
* SSH_MSG_USERAUTH_INFO_REQUEST. */
|
||||
void recv_msg_userauth_specific_60() {
|
||||
|
||||
#ifdef ENABLE_CLI_PUBKEY_AUTH
|
||||
if (cli_ses.lastauthtype == AUTH_TYPE_PUBKEY) {
|
||||
recv_msg_userauth_pk_ok();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CLI_INTERACT_AUTH
|
||||
if (cli_ses.lastauthtype == AUTH_TYPE_INTERACT) {
|
||||
recv_msg_userauth_info_request();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CLI_PASSWORD_AUTH
|
||||
if (cli_ses.lastauthtype == AUTH_TYPE_PASSWORD) {
|
||||
/* Eventually there could be proper password-changing
|
||||
* support. However currently few servers seem to
|
||||
* implement it, and password auth is last-resort
|
||||
* regardless - keyboard-interactive is more likely
|
||||
* to be used anyway. */
|
||||
dropbear_close("Your password has expired.");
|
||||
}
|
||||
#endif
|
||||
|
||||
dropbear_exit("Unexpected userauth packet");
|
||||
}
|
||||
|
||||
void recv_msg_userauth_failure() {
|
||||
|
||||
unsigned char * methods = NULL;
|
||||
unsigned char * tok = NULL;
|
||||
unsigned int methlen = 0;
|
||||
unsigned int partial = 0;
|
||||
unsigned int i = 0;
|
||||
|
||||
TRACE(("<- MSG_USERAUTH_FAILURE"))
|
||||
TRACE(("enter recv_msg_userauth_failure"))
|
||||
|
||||
if (cli_ses.state != USERAUTH_REQ_SENT) {
|
||||
/* Perhaps we should be more fatal? */
|
||||
dropbear_exit("Unexpected userauth failure");
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CLI_PUBKEY_AUTH
|
||||
/* If it was a pubkey auth request, we should cross that key
|
||||
* off the list. */
|
||||
if (cli_ses.lastauthtype == AUTH_TYPE_PUBKEY) {
|
||||
cli_pubkeyfail();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CLI_INTERACT_AUTH
|
||||
/* If we get a failure message for keyboard interactive without
|
||||
* receiving any request info packet, then we don't bother trying
|
||||
* keyboard interactive again */
|
||||
if (cli_ses.lastauthtype == AUTH_TYPE_INTERACT
|
||||
&& !cli_ses.interact_request_received) {
|
||||
TRACE(("setting auth_interact_failed = 1"))
|
||||
cli_ses.auth_interact_failed = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
cli_ses.lastauthtype = AUTH_TYPE_NONE;
|
||||
|
||||
methods = buf_getstring(ses.payload, &methlen);
|
||||
|
||||
partial = buf_getbool(ses.payload);
|
||||
|
||||
if (partial) {
|
||||
dropbear_log(LOG_INFO, "Authentication partially succeeded, more attempts required");
|
||||
} else {
|
||||
ses.authstate.failcount++;
|
||||
}
|
||||
|
||||
TRACE(("Methods (len %d): '%s'", methlen, methods))
|
||||
|
||||
ses.authstate.authdone=0;
|
||||
ses.authstate.authtypes=0;
|
||||
|
||||
/* Split with nulls rather than commas */
|
||||
for (i = 0; i < methlen; i++) {
|
||||
if (methods[i] == ',') {
|
||||
methods[i] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
tok = methods; /* tok stores the next method we'll compare */
|
||||
for (i = 0; i <= methlen; i++) {
|
||||
if (methods[i] == '\0') {
|
||||
TRACE(("auth method '%s'", tok))
|
||||
#ifdef ENABLE_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 (strncmp(AUTH_METHOD_INTERACT, tok,
|
||||
AUTH_METHOD_INTERACT_LEN) == 0) {
|
||||
ses.authstate.authtypes |= AUTH_TYPE_INTERACT;
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_CLI_PASSWORD_AUTH
|
||||
if (strncmp(AUTH_METHOD_PASSWORD, tok,
|
||||
AUTH_METHOD_PASSWORD_LEN) == 0) {
|
||||
ses.authstate.authtypes |= AUTH_TYPE_PASSWORD;
|
||||
}
|
||||
#endif
|
||||
tok = &methods[i+1]; /* Must make sure we don't use it after the
|
||||
last loop, since it'll point to something
|
||||
undefined */
|
||||
}
|
||||
}
|
||||
|
||||
m_free(methods);
|
||||
|
||||
cli_ses.state = USERAUTH_FAIL_RCVD;
|
||||
|
||||
TRACE(("leave recv_msg_userauth_failure"))
|
||||
}
|
||||
|
||||
void recv_msg_userauth_success() {
|
||||
TRACE(("received msg_userauth_success"))
|
||||
/* Note: in delayed-zlib mode, setting authdone here
|
||||
* will enable compression in the transport layer */
|
||||
ses.authstate.authdone = 1;
|
||||
cli_ses.state = USERAUTH_SUCCESS_RCVD;
|
||||
cli_ses.lastauthtype = AUTH_TYPE_NONE;
|
||||
}
|
||||
|
||||
void cli_auth_try() {
|
||||
|
||||
int finished = 0;
|
||||
TRACE(("enter cli_auth_try"))
|
||||
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
/* 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 (ses.authstate.authtypes & AUTH_TYPE_PUBKEY) {
|
||||
finished = cli_auth_pubkey();
|
||||
cli_ses.lastauthtype = AUTH_TYPE_PUBKEY;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CLI_INTERACT_AUTH
|
||||
if (!finished && ses.authstate.authtypes & AUTH_TYPE_INTERACT) {
|
||||
if (cli_ses.auth_interact_failed) {
|
||||
finished = 0;
|
||||
} else {
|
||||
cli_auth_interactive();
|
||||
cli_ses.lastauthtype = AUTH_TYPE_INTERACT;
|
||||
finished = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CLI_PASSWORD_AUTH
|
||||
if (!finished && ses.authstate.authtypes & AUTH_TYPE_PASSWORD) {
|
||||
cli_auth_password();
|
||||
finished = 1;
|
||||
cli_ses.lastauthtype = AUTH_TYPE_PASSWORD;
|
||||
}
|
||||
#endif
|
||||
|
||||
TRACE(("cli_auth_try lastauthtype %d", cli_ses.lastauthtype))
|
||||
|
||||
if (!finished) {
|
||||
dropbear_exit("No auth methods could be used.");
|
||||
}
|
||||
|
||||
TRACE(("leave cli_auth_try"))
|
||||
}
|
||||
|
||||
/* A helper for getpass() that exits if the user cancels. The returned
|
||||
* password is statically allocated by getpass() */
|
||||
char* getpass_or_cancel(char* prompt)
|
||||
{
|
||||
char* password = NULL;
|
||||
|
||||
#ifdef DROPBEAR_PASSWORD_ENV
|
||||
/* Password provided in an environment var */
|
||||
password = getenv(DROPBEAR_PASSWORD_ENV);
|
||||
if (password)
|
||||
{
|
||||
return password;
|
||||
}
|
||||
#endif
|
||||
|
||||
password = getpass(prompt);
|
||||
|
||||
/* 0x03 is a ctrl-c character in the buffer. */
|
||||
if (password == NULL || strchr(password, '\3') != NULL) {
|
||||
dropbear_close("Interrupted.");
|
||||
}
|
||||
return password;
|
||||
}
|
||||
174
cli-authinteract.c
Normal file
174
cli-authinteract.c
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Dropbear SSH
|
||||
*
|
||||
* Copyright (c) 2005 Matt Johnston
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#include "includes.h"
|
||||
#include "buffer.h"
|
||||
#include "dbutil.h"
|
||||
#include "session.h"
|
||||
#include "ssh.h"
|
||||
#include "runopts.h"
|
||||
|
||||
#ifdef ENABLE_CLI_INTERACT_AUTH
|
||||
|
||||
static unsigned char* get_response(unsigned char* prompt)
|
||||
{
|
||||
FILE* tty = NULL;
|
||||
unsigned char* response = NULL;
|
||||
/* not a password, but a reasonable limit */
|
||||
char buf[DROPBEAR_MAX_CLI_PASS];
|
||||
char* ret = NULL;
|
||||
|
||||
fprintf(stderr, "%s", prompt);
|
||||
|
||||
tty = fopen(_PATH_TTY, "r");
|
||||
if (tty) {
|
||||
ret = fgets(buf, sizeof(buf), tty);
|
||||
fclose(tty);
|
||||
} else {
|
||||
ret = fgets(buf, sizeof(buf), stdin);
|
||||
}
|
||||
|
||||
if (ret == NULL) {
|
||||
response = (unsigned char*)m_strdup("");
|
||||
} else {
|
||||
unsigned int buflen = strlen(buf);
|
||||
/* fgets includes newlines */
|
||||
if (buflen > 0 && buf[buflen-1] == '\n')
|
||||
buf[buflen-1] = '\0';
|
||||
response = (unsigned char*)m_strdup(buf);
|
||||
}
|
||||
|
||||
m_burn(buf, sizeof(buf));
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
void recv_msg_userauth_info_request() {
|
||||
|
||||
unsigned char *name = NULL;
|
||||
unsigned char *instruction = NULL;
|
||||
unsigned int num_prompts = 0;
|
||||
unsigned int i;
|
||||
|
||||
unsigned char *prompt = NULL;
|
||||
unsigned int echo = 0;
|
||||
unsigned char *response = NULL;
|
||||
|
||||
TRACE(("enter recv_msg_recv_userauth_info_request"))
|
||||
|
||||
/* Let the user know what password/host they are authing for */
|
||||
if (!cli_ses.interact_request_received) {
|
||||
fprintf(stderr, "Login for %s@%s\n", cli_opts.username,
|
||||
cli_opts.remotehost);
|
||||
}
|
||||
cli_ses.interact_request_received = 1;
|
||||
|
||||
name = buf_getstring(ses.payload, NULL);
|
||||
instruction = buf_getstring(ses.payload, NULL);
|
||||
|
||||
/* language tag */
|
||||
buf_eatstring(ses.payload);
|
||||
|
||||
num_prompts = buf_getint(ses.payload);
|
||||
|
||||
if (num_prompts >= DROPBEAR_MAX_CLI_INTERACT_PROMPTS) {
|
||||
dropbear_exit("Too many prompts received for keyboard-interactive");
|
||||
}
|
||||
|
||||
/* we'll build the response as we go */
|
||||
CHECKCLEARTOWRITE();
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_INFO_RESPONSE);
|
||||
buf_putint(ses.writepayload, num_prompts);
|
||||
|
||||
if (strlen(name) > 0) {
|
||||
cleantext(name);
|
||||
fprintf(stderr, "%s", name);
|
||||
}
|
||||
m_free(name);
|
||||
|
||||
if (strlen(instruction) > 0) {
|
||||
cleantext(instruction);
|
||||
fprintf(stderr, "%s", instruction);
|
||||
}
|
||||
m_free(instruction);
|
||||
|
||||
for (i = 0; i < num_prompts; i++) {
|
||||
unsigned int response_len = 0;
|
||||
prompt = buf_getstring(ses.payload, NULL);
|
||||
cleantext(prompt);
|
||||
|
||||
echo = buf_getbool(ses.payload);
|
||||
|
||||
if (!echo) {
|
||||
unsigned char* p = getpass_or_cancel(prompt);
|
||||
response = m_strdup(p);
|
||||
m_burn(p, strlen(p));
|
||||
} else {
|
||||
response = get_response(prompt);
|
||||
}
|
||||
|
||||
response_len = strlen(response);
|
||||
buf_putstring(ses.writepayload, response, response_len);
|
||||
m_burn(response, response_len);
|
||||
m_free(response);
|
||||
}
|
||||
|
||||
encrypt_packet();
|
||||
|
||||
|
||||
TRACE(("leave recv_msg_recv_userauth_info_request"))
|
||||
}
|
||||
|
||||
void cli_auth_interactive() {
|
||||
|
||||
TRACE(("enter cli_auth_interactive"))
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);
|
||||
|
||||
/* username */
|
||||
buf_putstring(ses.writepayload, cli_opts.username,
|
||||
strlen(cli_opts.username));
|
||||
|
||||
/* service name */
|
||||
buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
|
||||
SSH_SERVICE_CONNECTION_LEN);
|
||||
|
||||
/* method */
|
||||
buf_putstring(ses.writepayload, AUTH_METHOD_INTERACT,
|
||||
AUTH_METHOD_INTERACT_LEN);
|
||||
|
||||
/* empty language tag */
|
||||
buf_putstring(ses.writepayload, "", 0);
|
||||
|
||||
/* empty submethods */
|
||||
buf_putstring(ses.writepayload, "", 0);
|
||||
|
||||
encrypt_packet();
|
||||
cli_ses.interact_request_received = 0;
|
||||
|
||||
TRACE(("leave cli_auth_interactive"))
|
||||
|
||||
}
|
||||
#endif /* ENABLE_CLI_INTERACT_AUTH */
|
||||
161
cli-authpasswd.c
Normal file
161
cli-authpasswd.c
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Dropbear SSH
|
||||
*
|
||||
* 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 "buffer.h"
|
||||
#include "dbutil.h"
|
||||
#include "session.h"
|
||||
#include "ssh.h"
|
||||
#include "runopts.h"
|
||||
|
||||
#ifdef ENABLE_CLI_PASSWORD_AUTH
|
||||
|
||||
#ifdef ENABLE_CLI_ASKPASS_HELPER
|
||||
/* Returns 1 if we want to use the askpass program, 0 otherwise */
|
||||
static int want_askpass()
|
||||
{
|
||||
char* askpass_prog = NULL;
|
||||
|
||||
askpass_prog = getenv("SSH_ASKPASS");
|
||||
return askpass_prog &&
|
||||
((!isatty(STDIN_FILENO) && getenv("DISPLAY") )
|
||||
|| getenv("SSH_ASKPASS_ALWAYS"));
|
||||
}
|
||||
|
||||
/* returns a statically allocated password from a helper app, or NULL
|
||||
* on failure */
|
||||
static char *gui_getpass(const char *prompt) {
|
||||
|
||||
pid_t pid;
|
||||
int p[2], maxlen, len, status;
|
||||
static char buf[DROPBEAR_MAX_CLI_PASS + 1];
|
||||
char* helper = NULL;
|
||||
|
||||
TRACE(("enter gui_getpass"))
|
||||
|
||||
helper = getenv("SSH_ASKPASS");
|
||||
if (!helper)
|
||||
{
|
||||
TRACE(("leave gui_getpass: no askpass program"))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pipe(p) < 0) {
|
||||
TRACE(("error creating child pipe"))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid < 0) {
|
||||
TRACE(("fork error"))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!pid) {
|
||||
/* child */
|
||||
close(p[0]);
|
||||
if (dup2(p[1], STDOUT_FILENO) < 0) {
|
||||
TRACE(("error redirecting stdout"))
|
||||
exit(1);
|
||||
}
|
||||
close(p[1]);
|
||||
execlp(helper, helper, prompt, (char *)0);
|
||||
TRACE(("execlp error"))
|
||||
exit(1);
|
||||
}
|
||||
|
||||
close(p[1]);
|
||||
maxlen = sizeof(buf);
|
||||
while (maxlen > 0) {
|
||||
len = read(p[0], buf + sizeof(buf) - maxlen, maxlen);
|
||||
if (len > 0) {
|
||||
maxlen -= len;
|
||||
} else {
|
||||
if (errno != EINTR)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
close(p[0]);
|
||||
|
||||
while (waitpid(pid, &status, 0) < 0 && errno == EINTR)
|
||||
;
|
||||
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
|
||||
return(NULL);
|
||||
|
||||
len = sizeof(buf) - maxlen;
|
||||
buf[len] = '\0';
|
||||
if (len > 0 && buf[len - 1] == '\n')
|
||||
buf[len - 1] = '\0';
|
||||
|
||||
TRACE(("leave gui_getpass"))
|
||||
return(buf);
|
||||
}
|
||||
#endif /* ENABLE_CLI_ASKPASS_HELPER */
|
||||
|
||||
void cli_auth_password() {
|
||||
|
||||
char* password = NULL;
|
||||
char prompt[80];
|
||||
|
||||
TRACE(("enter cli_auth_password"))
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
snprintf(prompt, sizeof(prompt), "%s@%s's password: ",
|
||||
cli_opts.username, cli_opts.remotehost);
|
||||
#ifdef ENABLE_CLI_ASKPASS_HELPER
|
||||
if (want_askpass())
|
||||
{
|
||||
password = gui_getpass(prompt);
|
||||
if (!password) {
|
||||
dropbear_exit("No password");
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
password = getpass_or_cancel(prompt);
|
||||
}
|
||||
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);
|
||||
|
||||
buf_putstring(ses.writepayload, cli_opts.username,
|
||||
strlen(cli_opts.username));
|
||||
|
||||
buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
|
||||
SSH_SERVICE_CONNECTION_LEN);
|
||||
|
||||
buf_putstring(ses.writepayload, AUTH_METHOD_PASSWORD,
|
||||
AUTH_METHOD_PASSWORD_LEN);
|
||||
|
||||
buf_putbyte(ses.writepayload, 0); /* FALSE - so says the spec */
|
||||
|
||||
buf_putstring(ses.writepayload, password, strlen(password));
|
||||
|
||||
encrypt_packet();
|
||||
m_burn(password, strlen(password));
|
||||
|
||||
TRACE(("leave cli_auth_password"))
|
||||
}
|
||||
#endif /* ENABLE_CLI_PASSWORD_AUTH */
|
||||
188
cli-authpubkey.c
Normal file
188
cli-authpubkey.c
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Dropbear SSH
|
||||
*
|
||||
* Copyright (c) 2002,2003 Matt Johnston
|
||||
* Copyright (c) 2004 by Mihnea Stoenescu
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#include "includes.h"
|
||||
#include "buffer.h"
|
||||
#include "dbutil.h"
|
||||
#include "session.h"
|
||||
#include "ssh.h"
|
||||
#include "runopts.h"
|
||||
#include "auth.h"
|
||||
|
||||
#ifdef ENABLE_CLI_PUBKEY_AUTH
|
||||
static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign);
|
||||
|
||||
/* Called when we receive a SSH_MSG_USERAUTH_FAILURE for a pubkey request.
|
||||
* We use it to remove the key we tried from the list */
|
||||
void cli_pubkeyfail() {
|
||||
|
||||
struct SignKeyList *keyitem;
|
||||
struct SignKeyList **previtem;
|
||||
|
||||
TRACE(("enter cli_pubkeyfail"))
|
||||
previtem = &cli_opts.privkeys;
|
||||
|
||||
/* Find the key we failed with, and remove it */
|
||||
for (keyitem = cli_opts.privkeys; keyitem != NULL; keyitem = keyitem->next) {
|
||||
if (keyitem == cli_ses.lastprivkey) {
|
||||
*previtem = keyitem->next;
|
||||
}
|
||||
previtem = &keyitem;
|
||||
}
|
||||
|
||||
sign_key_free(cli_ses.lastprivkey->key); /* It won't be used again */
|
||||
m_free(cli_ses.lastprivkey);
|
||||
|
||||
TRACE(("leave cli_pubkeyfail"))
|
||||
}
|
||||
|
||||
void recv_msg_userauth_pk_ok() {
|
||||
|
||||
struct SignKeyList *keyitem = NULL;
|
||||
buffer* keybuf = NULL;
|
||||
char* algotype = NULL;
|
||||
unsigned int algolen;
|
||||
int keytype;
|
||||
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))
|
||||
m_free(algotype);
|
||||
|
||||
keybuf = buf_new(MAX_PUBKEY_SIZE);
|
||||
|
||||
remotelen = buf_getint(ses.payload);
|
||||
|
||||
/* Iterate through our keys, find which one it was that matched, and
|
||||
* send a real request with that key */
|
||||
for (keyitem = cli_opts.privkeys; keyitem != NULL; keyitem = keyitem->next) {
|
||||
|
||||
if (keyitem->type != keytype) {
|
||||
/* Types differed */
|
||||
TRACE(("types differed"))
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Now we compare the contents of the key */
|
||||
keybuf->pos = keybuf->len = 0;
|
||||
buf_put_pub_key(keybuf, keyitem->key, keytype);
|
||||
buf_setpos(keybuf, 0);
|
||||
buf_incrpos(keybuf, 4); /* first int is the length of the remainder (ie
|
||||
remotelen) which has already been taken from
|
||||
the remote buffer */
|
||||
|
||||
|
||||
if (keybuf->len-4 != remotelen) {
|
||||
TRACE(("lengths differed: localh %d remote %d", keybuf->len, remotelen))
|
||||
/* Lengths differed */
|
||||
continue;
|
||||
}
|
||||
if (memcmp(buf_getptr(keybuf, remotelen),
|
||||
buf_getptr(ses.payload, remotelen), remotelen) != 0) {
|
||||
/* Data didn't match this key */
|
||||
TRACE(("data differed"))
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Success */
|
||||
break;
|
||||
}
|
||||
buf_free(keybuf);
|
||||
|
||||
if (keyitem != NULL) {
|
||||
TRACE(("matching key"))
|
||||
/* XXX TODO: if it's an encrypted key, here we ask for their
|
||||
* password */
|
||||
send_msg_userauth_pubkey(keyitem->key, keytype, 1);
|
||||
} 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"))
|
||||
}
|
||||
|
||||
TRACE(("leave recv_msg_userauth_pk_ok"))
|
||||
}
|
||||
|
||||
/* TODO: make it take an agent reference to use as well */
|
||||
static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
|
||||
|
||||
const char *algoname = NULL;
|
||||
int algolen;
|
||||
buffer* sigbuf = NULL;
|
||||
|
||||
TRACE(("enter send_msg_userauth_pubkey"))
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);
|
||||
|
||||
buf_putstring(ses.writepayload, cli_opts.username,
|
||||
strlen(cli_opts.username));
|
||||
|
||||
buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
|
||||
SSH_SERVICE_CONNECTION_LEN);
|
||||
|
||||
buf_putstring(ses.writepayload, AUTH_METHOD_PUBKEY,
|
||||
AUTH_METHOD_PUBKEY_LEN);
|
||||
|
||||
buf_putbyte(ses.writepayload, realsign);
|
||||
|
||||
algoname = signkey_name_from_type(type, &algolen);
|
||||
|
||||
buf_putstring(ses.writepayload, algoname, algolen);
|
||||
buf_put_pub_key(ses.writepayload, key, type);
|
||||
|
||||
if (realsign) {
|
||||
TRACE(("realsign"))
|
||||
/* We put the signature as well - this contains string(session id), then
|
||||
* the contents of the write payload to this point */
|
||||
sigbuf = buf_new(4 + SHA1_HASH_SIZE + ses.writepayload->len);
|
||||
buf_putstring(sigbuf, ses.session_id, SHA1_HASH_SIZE);
|
||||
buf_putbytes(sigbuf, ses.writepayload->data, ses.writepayload->len);
|
||||
buf_put_sign(ses.writepayload, key, type, sigbuf->data, sigbuf->len);
|
||||
buf_free(sigbuf); /* Nothing confidential in the buffer */
|
||||
}
|
||||
|
||||
encrypt_packet();
|
||||
TRACE(("leave send_msg_userauth_pubkey"))
|
||||
}
|
||||
|
||||
int cli_auth_pubkey() {
|
||||
|
||||
TRACE(("enter cli_auth_pubkey"))
|
||||
|
||||
if (cli_opts.privkeys != NULL) {
|
||||
/* Send a trial request */
|
||||
send_msg_userauth_pubkey(cli_opts.privkeys->key,
|
||||
cli_opts.privkeys->type, 0);
|
||||
cli_ses.lastprivkey = cli_opts.privkeys;
|
||||
TRACE(("leave cli_auth_pubkey-success"))
|
||||
return 1;
|
||||
} else {
|
||||
TRACE(("leave cli_auth_pubkey-failure"))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif /* Pubkey auth */
|
||||
59
cli-channel.c
Normal file
59
cli-channel.c
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Dropbear SSH
|
||||
*
|
||||
* Copyright (c) 2002-2004 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 "channel.h"
|
||||
#include "buffer.h"
|
||||
#include "circbuffer.h"
|
||||
#include "dbutil.h"
|
||||
#include "session.h"
|
||||
#include "ssh.h"
|
||||
|
||||
/* We receive channel data - only used by the client chansession code*/
|
||||
void recv_msg_channel_extended_data() {
|
||||
|
||||
struct Channel *channel;
|
||||
unsigned int datatype;
|
||||
|
||||
TRACE(("enter recv_msg_channel_extended_data"))
|
||||
|
||||
channel = getchannel();
|
||||
|
||||
if (channel->type != &clichansess) {
|
||||
TRACE(("leave recv_msg_channel_extended_data: chantype is wrong"))
|
||||
return; /* we just ignore it */
|
||||
}
|
||||
|
||||
datatype = buf_getint(ses.payload);
|
||||
|
||||
if (datatype != SSH_EXTENDED_DATA_STDERR) {
|
||||
TRACE(("leave recv_msg_channel_extended_data: wrong datatype: %d",
|
||||
datatype))
|
||||
return;
|
||||
}
|
||||
|
||||
common_recv_msg_channel_data(channel, channel->errfd, channel->extrabuf);
|
||||
|
||||
TRACE(("leave recv_msg_channel_extended_data"))
|
||||
}
|
||||
439
cli-chansession.c
Normal file
439
cli-chansession.c
Normal file
@@ -0,0 +1,439 @@
|
||||
/*
|
||||
* Dropbear SSH
|
||||
*
|
||||
* Copyright (c) 2002,2003 Matt Johnston
|
||||
* Copyright (c) 2004 by Mihnea Stoenescu
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#include "includes.h"
|
||||
#include "packet.h"
|
||||
#include "buffer.h"
|
||||
#include "session.h"
|
||||
#include "dbutil.h"
|
||||
#include "channel.h"
|
||||
#include "ssh.h"
|
||||
#include "runopts.h"
|
||||
#include "termcodes.h"
|
||||
#include "chansession.h"
|
||||
|
||||
static void cli_closechansess(struct Channel *channel);
|
||||
static int cli_initchansess(struct Channel *channel);
|
||||
static void cli_chansessreq(struct Channel *channel);
|
||||
|
||||
static void start_channel_request(struct Channel *channel, unsigned char *type);
|
||||
|
||||
static void send_chansess_pty_req(struct Channel *channel);
|
||||
static void send_chansess_shell_req(struct Channel *channel);
|
||||
|
||||
static void cli_tty_setup();
|
||||
|
||||
const struct ChanType clichansess = {
|
||||
0, /* sepfds */
|
||||
"session", /* name */
|
||||
cli_initchansess, /* inithandler */
|
||||
NULL, /* checkclosehandler */
|
||||
cli_chansessreq, /* reqhandler */
|
||||
cli_closechansess, /* closehandler */
|
||||
};
|
||||
|
||||
static void cli_chansessreq(struct Channel *channel) {
|
||||
|
||||
unsigned char* type = NULL;
|
||||
int wantreply;
|
||||
|
||||
TRACE(("enter cli_chansessreq"))
|
||||
|
||||
type = buf_getstring(ses.payload, NULL);
|
||||
wantreply = buf_getbool(ses.payload);
|
||||
|
||||
if (strcmp(type, "exit-status") == 0) {
|
||||
cli_ses.retval = buf_getint(ses.payload);
|
||||
TRACE(("got exit-status of '%d'", cli_ses.retval))
|
||||
} else if (strcmp(type, "exit-signal") == 0) {
|
||||
TRACE(("got exit-signal, ignoring it"))
|
||||
} else {
|
||||
TRACE(("unknown request '%s'", type))
|
||||
send_msg_channel_failure(channel);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
m_free(type);
|
||||
}
|
||||
|
||||
|
||||
/* If the main session goes, we close it up */
|
||||
static void cli_closechansess(struct Channel *UNUSED(channel)) {
|
||||
|
||||
/* This channel hasn't gone yet, so we have > 1 */
|
||||
if (ses.chancount > 1) {
|
||||
dropbear_log(LOG_INFO, "Waiting for other channels to close...");
|
||||
}
|
||||
|
||||
cli_tty_cleanup(); /* Restore tty modes etc */
|
||||
|
||||
}
|
||||
|
||||
static void start_channel_request(struct Channel *channel,
|
||||
unsigned char *type) {
|
||||
|
||||
CHECKCLEARTOWRITE();
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_REQUEST);
|
||||
buf_putint(ses.writepayload, channel->remotechan);
|
||||
|
||||
buf_putstring(ses.writepayload, type, strlen(type));
|
||||
|
||||
}
|
||||
|
||||
/* Taken from OpenSSH's sshtty.c:
|
||||
* RCSID("OpenBSD: sshtty.c,v 1.5 2003/09/19 17:43:35 markus Exp "); */
|
||||
static void cli_tty_setup() {
|
||||
|
||||
struct termios tio;
|
||||
|
||||
TRACE(("enter cli_pty_setup"))
|
||||
|
||||
if (cli_ses.tty_raw_mode == 1) {
|
||||
TRACE(("leave cli_tty_setup: already in raw mode!"))
|
||||
return;
|
||||
}
|
||||
|
||||
if (tcgetattr(STDIN_FILENO, &tio) == -1) {
|
||||
dropbear_exit("Failed to set raw TTY mode");
|
||||
}
|
||||
|
||||
/* make a copy */
|
||||
cli_ses.saved_tio = tio;
|
||||
|
||||
tio.c_iflag |= IGNPAR;
|
||||
tio.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF);
|
||||
#ifdef IUCLC
|
||||
tio.c_iflag &= ~IUCLC;
|
||||
#endif
|
||||
tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL);
|
||||
#ifdef IEXTEN
|
||||
tio.c_lflag &= ~IEXTEN;
|
||||
#endif
|
||||
tio.c_oflag &= ~OPOST;
|
||||
tio.c_cc[VMIN] = 1;
|
||||
tio.c_cc[VTIME] = 0;
|
||||
if (tcsetattr(STDIN_FILENO, TCSADRAIN, &tio) == -1) {
|
||||
dropbear_exit("Failed to set raw TTY mode");
|
||||
}
|
||||
|
||||
cli_ses.tty_raw_mode = 1;
|
||||
TRACE(("leave cli_tty_setup"))
|
||||
}
|
||||
|
||||
void cli_tty_cleanup() {
|
||||
|
||||
TRACE(("enter cli_tty_cleanup"))
|
||||
|
||||
if (cli_ses.tty_raw_mode == 0) {
|
||||
TRACE(("leave cli_tty_cleanup: not in raw mode"))
|
||||
return;
|
||||
}
|
||||
|
||||
if (tcsetattr(STDIN_FILENO, TCSADRAIN, &cli_ses.saved_tio) == -1) {
|
||||
dropbear_log(LOG_WARNING, "Failed restoring TTY");
|
||||
} else {
|
||||
cli_ses.tty_raw_mode = 0;
|
||||
}
|
||||
|
||||
TRACE(("leave cli_tty_cleanup"))
|
||||
}
|
||||
|
||||
static void put_termcodes() {
|
||||
|
||||
struct termios tio;
|
||||
unsigned int sshcode;
|
||||
const struct TermCode *termcode;
|
||||
unsigned int value;
|
||||
unsigned int mapcode;
|
||||
|
||||
unsigned int bufpos1, bufpos2;
|
||||
|
||||
TRACE(("enter put_termcodes"))
|
||||
|
||||
if (tcgetattr(STDIN_FILENO, &tio) == -1) {
|
||||
dropbear_log(LOG_WARNING, "Failed reading termmodes");
|
||||
buf_putint(ses.writepayload, 1); /* Just the terminator */
|
||||
buf_putbyte(ses.writepayload, 0); /* TTY_OP_END */
|
||||
return;
|
||||
}
|
||||
|
||||
bufpos1 = ses.writepayload->pos;
|
||||
buf_putint(ses.writepayload, 0); /* A placeholder for the final length */
|
||||
|
||||
/* As with Dropbear server, we ignore baud rates for now */
|
||||
for (sshcode = 1; sshcode < MAX_TERMCODE; sshcode++) {
|
||||
|
||||
termcode = &termcodes[sshcode];
|
||||
mapcode = termcode->mapcode;
|
||||
|
||||
switch (termcode->type) {
|
||||
|
||||
case TERMCODE_NONE:
|
||||
continue;
|
||||
|
||||
case TERMCODE_CONTROLCHAR:
|
||||
value = tio.c_cc[mapcode];
|
||||
break;
|
||||
|
||||
case TERMCODE_INPUT:
|
||||
value = tio.c_iflag & mapcode;
|
||||
break;
|
||||
|
||||
case TERMCODE_OUTPUT:
|
||||
value = tio.c_oflag & mapcode;
|
||||
break;
|
||||
|
||||
case TERMCODE_LOCAL:
|
||||
value = tio.c_lflag & mapcode;
|
||||
break;
|
||||
|
||||
case TERMCODE_CONTROL:
|
||||
value = tio.c_cflag & mapcode;
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
/* If we reach here, we have something to say */
|
||||
buf_putbyte(ses.writepayload, sshcode);
|
||||
buf_putint(ses.writepayload, value);
|
||||
}
|
||||
|
||||
buf_putbyte(ses.writepayload, 0); /* THE END, aka TTY_OP_END */
|
||||
|
||||
/* Put the string length at the start of the buffer */
|
||||
bufpos2 = ses.writepayload->pos;
|
||||
|
||||
buf_setpos(ses.writepayload, bufpos1); /* Jump back */
|
||||
buf_putint(ses.writepayload, bufpos2 - bufpos1 - 4); /* len(termcodes) */
|
||||
buf_setpos(ses.writepayload, bufpos2); /* Back where we were */
|
||||
|
||||
TRACE(("leave put_termcodes"))
|
||||
}
|
||||
|
||||
static void put_winsize() {
|
||||
|
||||
struct winsize ws;
|
||||
|
||||
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0) {
|
||||
/* Some sane defaults */
|
||||
ws.ws_row = 25;
|
||||
ws.ws_col = 80;
|
||||
ws.ws_xpixel = 0;
|
||||
ws.ws_ypixel = 0;
|
||||
}
|
||||
|
||||
buf_putint(ses.writepayload, ws.ws_col); /* Cols */
|
||||
buf_putint(ses.writepayload, ws.ws_row); /* Rows */
|
||||
buf_putint(ses.writepayload, ws.ws_xpixel); /* Width */
|
||||
buf_putint(ses.writepayload, ws.ws_ypixel); /* Height */
|
||||
|
||||
}
|
||||
|
||||
static void sigwinch_handler(int UNUSED(unused)) {
|
||||
|
||||
cli_ses.winchange = 1;
|
||||
|
||||
}
|
||||
|
||||
void cli_chansess_winchange() {
|
||||
|
||||
unsigned int i;
|
||||
struct Channel *channel = NULL;
|
||||
|
||||
for (i = 0; i < ses.chansize; i++) {
|
||||
channel = ses.channels[i];
|
||||
if (channel != NULL && channel->type == &clichansess) {
|
||||
CHECKCLEARTOWRITE();
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_REQUEST);
|
||||
buf_putint(ses.writepayload, channel->remotechan);
|
||||
buf_putstring(ses.writepayload, "window-change", 13);
|
||||
buf_putbyte(ses.writepayload, 0); /* FALSE says the spec */
|
||||
put_winsize();
|
||||
encrypt_packet();
|
||||
}
|
||||
}
|
||||
cli_ses.winchange = 0;
|
||||
}
|
||||
|
||||
static void send_chansess_pty_req(struct Channel *channel) {
|
||||
|
||||
unsigned char* term = NULL;
|
||||
|
||||
TRACE(("enter send_chansess_pty_req"))
|
||||
|
||||
start_channel_request(channel, "pty-req");
|
||||
|
||||
/* Don't want replies */
|
||||
buf_putbyte(ses.writepayload, 0);
|
||||
|
||||
/* Get the terminal */
|
||||
term = getenv("TERM");
|
||||
if (term == NULL) {
|
||||
term = "vt100"; /* Seems a safe default */
|
||||
}
|
||||
buf_putstring(ses.writepayload, term, strlen(term));
|
||||
|
||||
/* Window size */
|
||||
put_winsize();
|
||||
|
||||
/* Terminal mode encoding */
|
||||
put_termcodes();
|
||||
|
||||
encrypt_packet();
|
||||
|
||||
/* Set up a window-change handler */
|
||||
if (signal(SIGWINCH, sigwinch_handler) == SIG_ERR) {
|
||||
dropbear_exit("signal error");
|
||||
}
|
||||
TRACE(("leave send_chansess_pty_req"))
|
||||
}
|
||||
|
||||
static void send_chansess_shell_req(struct Channel *channel) {
|
||||
|
||||
unsigned char* reqtype = NULL;
|
||||
|
||||
TRACE(("enter send_chansess_shell_req"))
|
||||
|
||||
if (cli_opts.cmd) {
|
||||
if (cli_opts.is_subsystem) {
|
||||
reqtype = "subsystem";
|
||||
} else {
|
||||
reqtype = "exec";
|
||||
}
|
||||
} else {
|
||||
reqtype = "shell";
|
||||
}
|
||||
|
||||
start_channel_request(channel, reqtype);
|
||||
|
||||
/* XXX TODO */
|
||||
buf_putbyte(ses.writepayload, 0); /* Don't want replies */
|
||||
if (cli_opts.cmd) {
|
||||
buf_putstring(ses.writepayload, cli_opts.cmd, strlen(cli_opts.cmd));
|
||||
}
|
||||
|
||||
encrypt_packet();
|
||||
TRACE(("leave send_chansess_shell_req"))
|
||||
}
|
||||
|
||||
/* Shared for normal client channel and netcat-alike */
|
||||
static int cli_init_stdpipe_sess(struct Channel *channel) {
|
||||
channel->writefd = STDOUT_FILENO;
|
||||
setnonblocking(STDOUT_FILENO);
|
||||
|
||||
channel->readfd = STDIN_FILENO;
|
||||
setnonblocking(STDIN_FILENO);
|
||||
|
||||
channel->errfd = STDERR_FILENO;
|
||||
setnonblocking(STDERR_FILENO);
|
||||
|
||||
channel->extrabuf = cbuf_new(opts.recv_window);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cli_initchansess(struct Channel *channel) {
|
||||
|
||||
cli_init_stdpipe_sess(channel);
|
||||
|
||||
if (cli_opts.wantpty) {
|
||||
send_chansess_pty_req(channel);
|
||||
}
|
||||
|
||||
send_chansess_shell_req(channel);
|
||||
|
||||
if (cli_opts.wantpty) {
|
||||
cli_tty_setup();
|
||||
}
|
||||
|
||||
return 0; /* Success */
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CLI_NETCAT
|
||||
|
||||
void cli_send_netcat_request() {
|
||||
|
||||
const unsigned char* source_host = "127.0.0.1";
|
||||
const int source_port = 22;
|
||||
|
||||
const struct ChanType cli_chan_netcat = {
|
||||
0, /* sepfds */
|
||||
"direct-tcpip",
|
||||
cli_init_stdpipe_sess, /* inithandler */
|
||||
NULL,
|
||||
NULL,
|
||||
cli_closechansess
|
||||
};
|
||||
|
||||
cli_opts.wantpty = 0;
|
||||
|
||||
if (send_msg_channel_open_init(STDIN_FILENO, &cli_chan_netcat)
|
||||
== DROPBEAR_FAILURE) {
|
||||
dropbear_exit("Couldn't open initial channel");
|
||||
}
|
||||
|
||||
buf_putstring(ses.writepayload, cli_opts.netcat_host,
|
||||
strlen(cli_opts.netcat_host));
|
||||
buf_putint(ses.writepayload, cli_opts.netcat_port);
|
||||
|
||||
/* originator ip - localhost is accurate enough */
|
||||
buf_putstring(ses.writepayload, source_host, strlen(source_host));
|
||||
buf_putint(ses.writepayload, source_port);
|
||||
|
||||
encrypt_packet();
|
||||
TRACE(("leave cli_send_chansess_request"))
|
||||
}
|
||||
#endif
|
||||
|
||||
void cli_send_chansess_request() {
|
||||
|
||||
TRACE(("enter cli_send_chansess_request"))
|
||||
|
||||
if (send_msg_channel_open_init(STDIN_FILENO, &clichansess)
|
||||
== DROPBEAR_FAILURE) {
|
||||
dropbear_exit("Couldn't open initial channel");
|
||||
}
|
||||
|
||||
/* No special channel request data */
|
||||
encrypt_packet();
|
||||
TRACE(("leave cli_send_chansess_request"))
|
||||
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
while (cli_opts.localfwds != NULL) {
|
||||
ret = cli_localtcp(cli_opts.localfwds->listenport,
|
||||
cli_opts.localfwds->connectaddr,
|
||||
cli_opts.localfwds->connectport);
|
||||
if (ret == DROPBEAR_FAILURE) {
|
||||
dropbear_log(LOG_WARNING, "Failed local port forward %d:%s:%d",
|
||||
cli_opts.localfwds->listenport,
|
||||
cli_opts.localfwds->connectaddr,
|
||||
cli_opts.localfwds->connectport);
|
||||
#endif
|
||||
330
cli-kex.c
Normal file
330
cli-kex.c
Normal file
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* Dropbear - a SSH2 server
|
||||
*
|
||||
* Copyright (c) 2002-2004 Matt Johnston
|
||||
* Copyright (c) 2004 by Mihnea Stoenescu
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#include "includes.h"
|
||||
#include "session.h"
|
||||
#include "dbutil.h"
|
||||
#include "algo.h"
|
||||
#include "buffer.h"
|
||||
#include "session.h"
|
||||
#include "kex.h"
|
||||
#include "ssh.h"
|
||||
#include "packet.h"
|
||||
#include "bignum.h"
|
||||
#include "random.h"
|
||||
#include "runopts.h"
|
||||
#include "signkey.h"
|
||||
|
||||
|
||||
static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen);
|
||||
#define MAX_KNOWNHOSTS_LINE 4500
|
||||
|
||||
void send_msg_kexdh_init() {
|
||||
|
||||
cli_ses.dh_e = (mp_int*)m_malloc(sizeof(mp_int));
|
||||
cli_ses.dh_x = (mp_int*)m_malloc(sizeof(mp_int));
|
||||
m_mp_init_multi(cli_ses.dh_e, cli_ses.dh_x, NULL);
|
||||
|
||||
gen_kexdh_vals(cli_ses.dh_e, cli_ses.dh_x);
|
||||
|
||||
CHECKCLEARTOWRITE();
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT);
|
||||
buf_putmpint(ses.writepayload, cli_ses.dh_e);
|
||||
encrypt_packet();
|
||||
ses.requirenext = SSH_MSG_KEXDH_REPLY;
|
||||
}
|
||||
|
||||
/* Handle a diffie-hellman key exchange reply. */
|
||||
void recv_msg_kexdh_reply() {
|
||||
|
||||
DEF_MP_INT(dh_f);
|
||||
sign_key *hostkey = NULL;
|
||||
unsigned int type, keybloblen;
|
||||
unsigned char* keyblob = NULL;
|
||||
|
||||
|
||||
TRACE(("enter recv_msg_kexdh_reply"))
|
||||
|
||||
if (cli_ses.kex_state != KEXDH_INIT_SENT) {
|
||||
dropbear_exit("Received out-of-order kexdhreply");
|
||||
}
|
||||
m_mp_init(&dh_f);
|
||||
type = ses.newkeys->algo_hostkey;
|
||||
TRACE(("type is %d", type))
|
||||
|
||||
hostkey = new_sign_key();
|
||||
keybloblen = buf_getint(ses.payload);
|
||||
|
||||
keyblob = buf_getptr(ses.payload, keybloblen);
|
||||
if (!ses.kexstate.donefirstkex) {
|
||||
/* Only makes sense the first time */
|
||||
checkhostkey(keyblob, keybloblen);
|
||||
}
|
||||
|
||||
if (buf_get_pub_key(ses.payload, hostkey, &type) != DROPBEAR_SUCCESS) {
|
||||
TRACE(("failed getting pubkey"))
|
||||
dropbear_exit("Bad KEX packet");
|
||||
}
|
||||
|
||||
if (buf_getmpint(ses.payload, &dh_f) != DROPBEAR_SUCCESS) {
|
||||
TRACE(("failed getting mpint"))
|
||||
dropbear_exit("Bad KEX packet");
|
||||
}
|
||||
|
||||
kexdh_comb_key(cli_ses.dh_e, cli_ses.dh_x, &dh_f, hostkey);
|
||||
mp_clear(&dh_f);
|
||||
mp_clear_multi(cli_ses.dh_e, cli_ses.dh_x, NULL);
|
||||
m_free(cli_ses.dh_e);
|
||||
m_free(cli_ses.dh_x);
|
||||
|
||||
if (buf_verify(ses.payload, hostkey, ses.hash, SHA1_HASH_SIZE)
|
||||
!= DROPBEAR_SUCCESS) {
|
||||
dropbear_exit("Bad hostkey signature");
|
||||
}
|
||||
|
||||
sign_key_free(hostkey);
|
||||
hostkey = NULL;
|
||||
|
||||
send_msg_newkeys();
|
||||
ses.requirenext = SSH_MSG_NEWKEYS;
|
||||
TRACE(("leave recv_msg_kexdh_init"))
|
||||
}
|
||||
|
||||
static void ask_to_confirm(unsigned char* keyblob, unsigned int keybloblen) {
|
||||
|
||||
char* fp = NULL;
|
||||
FILE *tty = NULL;
|
||||
char response = 'z';
|
||||
|
||||
fp = sign_key_fingerprint(keyblob, keybloblen);
|
||||
if (cli_opts.always_accept_key) {
|
||||
fprintf(stderr, "\nHost '%s' key accepted unconditionally.\n(fingerprint %s)\n",
|
||||
cli_opts.remotehost,
|
||||
fp);
|
||||
m_free(fp);
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "\nHost '%s' is not in the trusted hosts file.\n(fingerprint %s)\nDo you want to continue connecting? (y/n) ",
|
||||
cli_opts.remotehost,
|
||||
fp);
|
||||
m_free(fp);
|
||||
|
||||
tty = fopen(_PATH_TTY, "r");
|
||||
if (tty) {
|
||||
response = getc(tty);
|
||||
fclose(tty);
|
||||
} else {
|
||||
response = getc(stdin);
|
||||
}
|
||||
|
||||
if (response == 'y') {
|
||||
return;
|
||||
}
|
||||
|
||||
dropbear_exit("Didn't validate host key");
|
||||
}
|
||||
|
||||
static FILE* open_known_hosts_file(int * readonly)
|
||||
{
|
||||
FILE * hostsfile = NULL;
|
||||
char * filename = NULL;
|
||||
char * homedir = NULL;
|
||||
|
||||
homedir = getenv("HOME");
|
||||
|
||||
if (!homedir) {
|
||||
struct passwd * pw = NULL;
|
||||
pw = getpwuid(getuid());
|
||||
if (pw) {
|
||||
homedir = pw->pw_dir;
|
||||
}
|
||||
}
|
||||
|
||||
if (homedir) {
|
||||
unsigned int len;
|
||||
len = strlen(homedir);
|
||||
filename = m_malloc(len + 18); /* "/.ssh/known_hosts" and null-terminator*/
|
||||
|
||||
snprintf(filename, len+18, "%s/.ssh", homedir);
|
||||
/* Check that ~/.ssh exists - easiest way is just to mkdir */
|
||||
if (mkdir(filename, S_IRWXU) != 0) {
|
||||
if (errno != EEXIST) {
|
||||
dropbear_log(LOG_INFO, "Warning: failed creating %s/.ssh: %s",
|
||||
homedir, strerror(errno));
|
||||
TRACE(("mkdir didn't work: %s", strerror(errno)))
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(filename, len+18, "%s/.ssh/known_hosts", homedir);
|
||||
hostsfile = fopen(filename, "a+");
|
||||
|
||||
if (hostsfile != NULL) {
|
||||
*readonly = 0;
|
||||
fseek(hostsfile, 0, SEEK_SET);
|
||||
} else {
|
||||
/* We mightn't have been able to open it if it was read-only */
|
||||
if (errno == EACCES || errno == EROFS) {
|
||||
TRACE(("trying readonly: %s", strerror(errno)))
|
||||
*readonly = 1;
|
||||
hostsfile = fopen(filename, "r");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hostsfile == NULL) {
|
||||
TRACE(("hostsfile didn't open: %s", strerror(errno)))
|
||||
dropbear_log(LOG_WARNING, "Failed to open %s/.ssh/known_hosts",
|
||||
homedir);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
m_free(filename);
|
||||
return hostsfile;
|
||||
}
|
||||
|
||||
static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
|
||||
|
||||
FILE *hostsfile = NULL;
|
||||
int readonly = 0;
|
||||
unsigned int hostlen, algolen;
|
||||
unsigned long len;
|
||||
const char *algoname = NULL;
|
||||
char * fingerprint = NULL;
|
||||
buffer * line = NULL;
|
||||
int ret;
|
||||
|
||||
hostsfile = open_known_hosts_file(&readonly);
|
||||
if (!hostsfile) {
|
||||
ask_to_confirm(keyblob, keybloblen);
|
||||
/* ask_to_confirm will exit upon failure */
|
||||
return;
|
||||
}
|
||||
|
||||
line = buf_new(MAX_KNOWNHOSTS_LINE);
|
||||
hostlen = strlen(cli_opts.remotehost);
|
||||
algoname = signkey_name_from_type(ses.newkeys->algo_hostkey, &algolen);
|
||||
|
||||
do {
|
||||
if (buf_getline(line, hostsfile) == DROPBEAR_FAILURE) {
|
||||
TRACE(("failed reading line: prob EOF"))
|
||||
break;
|
||||
}
|
||||
|
||||
/* The line is too short to be sensible */
|
||||
/* "30" is 'enough to hold ssh-dss plus the spaces, ie so we don't
|
||||
* buf_getfoo() past the end and die horribly - the base64 parsing
|
||||
* code is what tiptoes up to the end nicely */
|
||||
if (line->len < (hostlen+30) ) {
|
||||
TRACE(("line is too short to be sensible"))
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Compare hostnames */
|
||||
if (strncmp(cli_opts.remotehost, buf_getptr(line, hostlen),
|
||||
hostlen) != 0) {
|
||||
TRACE(("hosts don't match"))
|
||||
continue;
|
||||
}
|
||||
|
||||
buf_incrpos(line, hostlen);
|
||||
if (buf_getbyte(line) != ' ') {
|
||||
/* there wasn't a space after the hostname, something dodgy */
|
||||
TRACE(("missing space afte matching hostname"))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strncmp(buf_getptr(line, algolen), algoname, algolen) != 0) {
|
||||
TRACE(("algo doesn't match"))
|
||||
continue;
|
||||
}
|
||||
|
||||
buf_incrpos(line, algolen);
|
||||
if (buf_getbyte(line) != ' ') {
|
||||
TRACE(("missing space after algo"))
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Now we're at the interesting hostkey */
|
||||
ret = cmp_base64_key(keyblob, keybloblen, algoname, algolen,
|
||||
line, &fingerprint);
|
||||
|
||||
if (ret == DROPBEAR_SUCCESS) {
|
||||
/* Good matching key */
|
||||
TRACE(("good matching key"))
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* The keys didn't match. eep. Note that we're "leaking"
|
||||
the fingerprint strings here, but we're exiting anyway */
|
||||
dropbear_exit("\n\nHost key mismatch for %s !\n"
|
||||
"Fingerprint is %s\n"
|
||||
"Expected %s\n"
|
||||
"If you know that the host key is correct you can\nremove the bad entry from ~/.ssh/known_hosts",
|
||||
cli_opts.remotehost,
|
||||
sign_key_fingerprint(keyblob, keybloblen),
|
||||
fingerprint ? fingerprint : "UNKNOWN");
|
||||
} while (1); /* keep going 'til something happens */
|
||||
|
||||
/* Key doesn't exist yet */
|
||||
ask_to_confirm(keyblob, keybloblen);
|
||||
|
||||
/* If we get here, they said yes */
|
||||
|
||||
if (readonly) {
|
||||
TRACE(("readonly"))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!cli_opts.always_accept_key) {
|
||||
/* put the new entry in the file */
|
||||
fseek(hostsfile, 0, SEEK_END); /* In case it wasn't opened append */
|
||||
buf_setpos(line, 0);
|
||||
buf_setlen(line, 0);
|
||||
buf_putbytes(line, ses.remotehost, hostlen);
|
||||
buf_putbyte(line, ' ');
|
||||
buf_putbytes(line, algoname, algolen);
|
||||
buf_putbyte(line, ' ');
|
||||
len = line->size - line->pos;
|
||||
TRACE(("keybloblen %d, len %d", keybloblen, len))
|
||||
/* The only failure with base64 is buffer_overflow, but buf_getwriteptr
|
||||
* will die horribly in the case anyway */
|
||||
base64_encode(keyblob, keybloblen, buf_getwriteptr(line, len), &len);
|
||||
buf_incrwritepos(line, len);
|
||||
buf_putbyte(line, '\n');
|
||||
buf_setpos(line, 0);
|
||||
fwrite(buf_getptr(line, line->len), line->len, 1, hostsfile);
|
||||
/* We ignore errors, since there's not much we can do about them */
|
||||
}
|
||||
|
||||
out:
|
||||
if (hostsfile != NULL) {
|
||||
fclose(hostsfile);
|
||||
}
|
||||
if (line != NULL) {
|
||||
buf_free(line);
|
||||
}
|
||||
}
|
||||
146
cli-main.c
Normal file
146
cli-main.c
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Dropbear - a SSH2 server
|
||||
* SSH client implementation
|
||||
*
|
||||
* Copyright (c) 2002,2003 Matt Johnston
|
||||
* Copyright (c) 2004 by Mihnea Stoenescu
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#include "includes.h"
|
||||
#include "dbutil.h"
|
||||
#include "runopts.h"
|
||||
#include "session.h"
|
||||
|
||||
static void cli_dropbear_exit(int exitcode, const char* format, va_list param);
|
||||
static void cli_dropbear_log(int priority, const char* format, va_list param);
|
||||
|
||||
static void cli_proxy_cmd(int *sock_in, int *sock_out);
|
||||
|
||||
#if defined(DBMULTI_dbclient) || !defined(DROPBEAR_MULTI)
|
||||
#if defined(DBMULTI_dbclient) && defined(DROPBEAR_MULTI)
|
||||
int cli_main(int argc, char ** argv) {
|
||||
#else
|
||||
int main(int argc, char ** argv) {
|
||||
#endif
|
||||
|
||||
int sock_in, sock_out;
|
||||
char* error = NULL;
|
||||
char* hostandport;
|
||||
int len;
|
||||
|
||||
_dropbear_exit = cli_dropbear_exit;
|
||||
_dropbear_log = cli_dropbear_log;
|
||||
|
||||
disallow_core();
|
||||
|
||||
cli_getopts(argc, argv);
|
||||
|
||||
TRACE(("user='%s' host='%s' port='%s'", cli_opts.username,
|
||||
cli_opts.remotehost, cli_opts.remoteport))
|
||||
|
||||
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
|
||||
dropbear_exit("signal() error");
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CLI_PROXYCMD
|
||||
if (cli_opts.proxycmd) {
|
||||
cli_proxy_cmd(&sock_in, &sock_out);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
int sock = connect_remote(cli_opts.remotehost, cli_opts.remoteport,
|
||||
0, &error);
|
||||
sock_in = sock_out = sock;
|
||||
}
|
||||
|
||||
if (sock_in < 0) {
|
||||
dropbear_exit("%s", error);
|
||||
}
|
||||
|
||||
/* Set up the host:port log */
|
||||
len = strlen(cli_opts.remotehost);
|
||||
len += 10; /* 16 bit port and leeway*/
|
||||
hostandport = (char*)m_malloc(len);
|
||||
snprintf(hostandport, len, "%s:%s",
|
||||
cli_opts.remotehost, cli_opts.remoteport);
|
||||
|
||||
cli_session(sock_in, sock_out, hostandport);
|
||||
|
||||
/* not reached */
|
||||
return -1;
|
||||
}
|
||||
#endif /* DBMULTI stuff */
|
||||
|
||||
static void cli_dropbear_exit(int exitcode, const char* format, va_list param) {
|
||||
|
||||
char fmtbuf[300];
|
||||
|
||||
if (!sessinitdone) {
|
||||
snprintf(fmtbuf, sizeof(fmtbuf), "exited: %s",
|
||||
format);
|
||||
} else {
|
||||
snprintf(fmtbuf, sizeof(fmtbuf),
|
||||
"connection to %s@%s:%s exited: %s",
|
||||
cli_opts.username, cli_opts.remotehost,
|
||||
cli_opts.remoteport, format);
|
||||
}
|
||||
|
||||
/* Do the cleanup first, since then the terminal will be reset */
|
||||
cli_session_cleanup();
|
||||
common_session_cleanup();
|
||||
|
||||
_dropbear_log(LOG_INFO, fmtbuf, param);
|
||||
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
static void cli_dropbear_log(int UNUSED(priority),
|
||||
const char* format, va_list param) {
|
||||
|
||||
char printbuf[1024];
|
||||
|
||||
vsnprintf(printbuf, sizeof(printbuf), format, param);
|
||||
|
||||
fprintf(stderr, "%s: %s\n", cli_opts.progname, printbuf);
|
||||
|
||||
}
|
||||
|
||||
static void exec_proxy_cmd(void *user_data_cmd) {
|
||||
const char *cmd = user_data_cmd;
|
||||
char *usershell;
|
||||
|
||||
usershell = m_strdup(get_user_shell());
|
||||
run_shell_command(cmd, ses.maxfd, usershell);
|
||||
dropbear_exit("Failed to run '%s'\n", cmd);
|
||||
}
|
||||
|
||||
static void cli_proxy_cmd(int *sock_in, int *sock_out) {
|
||||
int ret;
|
||||
|
||||
fill_passwd(cli_opts.own_user);
|
||||
|
||||
ret = spawn_command(exec_proxy_cmd, cli_opts.proxycmd,
|
||||
sock_out, sock_in, NULL, NULL);
|
||||
if (ret == DROPBEAR_FAILURE) {
|
||||
dropbear_exit("Failed running proxy command");
|
||||
*sock_in = *sock_out = -1;
|
||||
}
|
||||
}
|
||||
640
cli-runopts.c
Normal file
640
cli-runopts.c
Normal file
@@ -0,0 +1,640 @@
|
||||
/*
|
||||
* 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 "runopts.h"
|
||||
#include "signkey.h"
|
||||
#include "buffer.h"
|
||||
#include "dbutil.h"
|
||||
#include "algo.h"
|
||||
#include "tcpfwd.h"
|
||||
|
||||
cli_runopts cli_opts; /* GLOBAL */
|
||||
|
||||
static void printhelp();
|
||||
static void parse_hostname(const char* orighostarg);
|
||||
static void parse_multihop_hostname(const char* orighostarg, const char* argv0);
|
||||
static void fill_own_user();
|
||||
#ifdef ENABLE_CLI_PUBKEY_AUTH
|
||||
static void loadidentityfile(const char* filename);
|
||||
#endif
|
||||
#ifdef ENABLE_CLI_ANYTCPFWD
|
||||
static void addforward(const char* str, struct TCPFwdList** fwdlist);
|
||||
#endif
|
||||
#ifdef ENABLE_CLI_NETCAT
|
||||
static void add_netcat(const char *str);
|
||||
#endif
|
||||
|
||||
static void printhelp() {
|
||||
|
||||
fprintf(stderr, "Dropbear client v%s\n"
|
||||
#ifdef ENABLE_CLI_MULTIHOP
|
||||
"Usage: %s [options] [user@]host[/port][,[user@]host/port],...] [command]\n"
|
||||
#else
|
||||
"Usage: %s [options] [user@]host[/port] [command]\n"
|
||||
#endif
|
||||
"Options are:\n"
|
||||
"-p <remoteport>\n"
|
||||
"-l <username>\n"
|
||||
"-t Allocate a pty\n"
|
||||
"-T Don't allocate a pty\n"
|
||||
"-N Don't run a remote command\n"
|
||||
"-f Run in background after auth\n"
|
||||
"-y Always accept remote host key if unknown\n"
|
||||
"-s Request a subsystem (use for sftp)\n"
|
||||
#ifdef ENABLE_CLI_PUBKEY_AUTH
|
||||
"-i <identityfile> (multiple allowed)\n"
|
||||
#endif
|
||||
#ifdef ENABLE_CLI_LOCALTCPFWD
|
||||
"-L <listenport:remotehost:remoteport> Local port forwarding\n"
|
||||
"-g Allow remote hosts to connect to forwarded ports\n"
|
||||
#endif
|
||||
#ifdef ENABLE_CLI_REMOTETCPFWD
|
||||
"-R <listenport:remotehost:remoteport> Remote port forwarding\n"
|
||||
#endif
|
||||
"-W <receive_window_buffer> (default %d, larger may be faster, max 1MB)\n"
|
||||
"-K <keepalive> (0 is never, default %d)\n"
|
||||
"-I <idle_timeout> (0 is never, default %d)\n"
|
||||
#ifdef ENABLE_CLI_NETCAT
|
||||
"-B <endhost:endport> Netcat-alike forwarding\n"
|
||||
#endif
|
||||
#ifdef ENABLE_CLI_PROXYCMD
|
||||
"-J <proxy_program> Use program pipe rather than TCP connection\n"
|
||||
#endif
|
||||
#ifdef DEBUG_TRACE
|
||||
"-v verbose (compiled with DEBUG_TRACE)\n"
|
||||
#endif
|
||||
,DROPBEAR_VERSION, cli_opts.progname,
|
||||
DEFAULT_RECV_WINDOW, DEFAULT_KEEPALIVE, DEFAULT_IDLE_TIMEOUT);
|
||||
|
||||
}
|
||||
|
||||
void cli_getopts(int argc, char ** argv) {
|
||||
|
||||
unsigned int i, j;
|
||||
char ** next = 0;
|
||||
unsigned int cmdlen;
|
||||
#ifdef ENABLE_CLI_PUBKEY_AUTH
|
||||
int nextiskey = 0; /* A flag if the next argument is a keyfile */
|
||||
#endif
|
||||
#ifdef ENABLE_CLI_LOCALTCPFWD
|
||||
int nextislocal = 0;
|
||||
#endif
|
||||
#ifdef ENABLE_CLI_REMOTETCPFWD
|
||||
int nextisremote = 0;
|
||||
#endif
|
||||
#ifdef ENABLE_CLI_NETCAT
|
||||
int nextisnetcat = 0;
|
||||
#endif
|
||||
char* dummy = NULL; /* Not used for anything real */
|
||||
|
||||
char* recv_window_arg = NULL;
|
||||
char* keepalive_arg = NULL;
|
||||
char* idle_timeout_arg = NULL;
|
||||
|
||||
/* see printhelp() for options */
|
||||
cli_opts.progname = argv[0];
|
||||
cli_opts.remotehost = NULL;
|
||||
cli_opts.remoteport = NULL;
|
||||
cli_opts.username = NULL;
|
||||
cli_opts.cmd = NULL;
|
||||
cli_opts.no_cmd = 0;
|
||||
cli_opts.backgrounded = 0;
|
||||
cli_opts.wantpty = 9; /* 9 means "it hasn't been touched", gets set later */
|
||||
cli_opts.always_accept_key = 0;
|
||||
cli_opts.is_subsystem = 0;
|
||||
#ifdef ENABLE_CLI_PUBKEY_AUTH
|
||||
cli_opts.privkeys = NULL;
|
||||
#endif
|
||||
#ifdef ENABLE_CLI_LOCALTCPFWD
|
||||
cli_opts.localfwds = NULL;
|
||||
opts.listen_fwd_all = 0;
|
||||
#endif
|
||||
#ifdef ENABLE_CLI_REMOTETCPFWD
|
||||
cli_opts.remotefwds = NULL;
|
||||
#endif
|
||||
#ifdef ENABLE_CLI_PROXYCMD
|
||||
cli_opts.proxycmd = NULL;
|
||||
#endif
|
||||
/* not yet
|
||||
opts.ipv4 = 1;
|
||||
opts.ipv6 = 1;
|
||||
*/
|
||||
opts.recv_window = DEFAULT_RECV_WINDOW;
|
||||
|
||||
fill_own_user();
|
||||
|
||||
/* Iterate all the arguments */
|
||||
for (i = 1; i < (unsigned int)argc; i++) {
|
||||
#ifdef ENABLE_CLI_PUBKEY_AUTH
|
||||
if (nextiskey) {
|
||||
/* Load a hostkey since the previous argument was "-i" */
|
||||
loadidentityfile(argv[i]);
|
||||
nextiskey = 0;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_CLI_REMOTETCPFWD
|
||||
if (nextisremote) {
|
||||
TRACE(("nextisremote true"))
|
||||
addforward(argv[i], &cli_opts.remotefwds);
|
||||
nextisremote = 0;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_CLI_LOCALTCPFWD
|
||||
if (nextislocal) {
|
||||
TRACE(("nextislocal true"))
|
||||
addforward(argv[i], &cli_opts.localfwds);
|
||||
nextislocal = 0;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_CLI_NETCAT
|
||||
if (nextisnetcat) {
|
||||
TRACE(("nextisnetcat true"))
|
||||
add_netcat(argv[i]);
|
||||
nextisnetcat = 0;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (next) {
|
||||
/* The previous flag set a value to assign */
|
||||
*next = argv[i];
|
||||
if (*next == NULL) {
|
||||
dropbear_exit("Invalid null argument");
|
||||
}
|
||||
next = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argv[i][0] == '-') {
|
||||
/* A flag *waves* */
|
||||
|
||||
switch (argv[i][1]) {
|
||||
case 'y': /* always accept the remote hostkey */
|
||||
cli_opts.always_accept_key = 1;
|
||||
break;
|
||||
case 'p': /* remoteport */
|
||||
next = &cli_opts.remoteport;
|
||||
break;
|
||||
#ifdef ENABLE_CLI_PUBKEY_AUTH
|
||||
case 'i': /* an identityfile */
|
||||
/* Keep scp happy when it changes "-i file" to "-ifile" */
|
||||
if (strlen(argv[i]) > 2) {
|
||||
loadidentityfile(&argv[i][2]);
|
||||
} else {
|
||||
nextiskey = 1;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 't': /* we want a pty */
|
||||
cli_opts.wantpty = 1;
|
||||
break;
|
||||
case 'T': /* don't want a pty */
|
||||
cli_opts.wantpty = 0;
|
||||
break;
|
||||
case 'N':
|
||||
cli_opts.no_cmd = 1;
|
||||
break;
|
||||
case 'f':
|
||||
cli_opts.backgrounded = 1;
|
||||
break;
|
||||
case 's':
|
||||
cli_opts.is_subsystem = 1;
|
||||
break;
|
||||
#ifdef ENABLE_CLI_LOCALTCPFWD
|
||||
case 'L':
|
||||
nextislocal = 1;
|
||||
break;
|
||||
case 'g':
|
||||
opts.listen_fwd_all = 1;
|
||||
break;
|
||||
#endif
|
||||
#ifdef ENABLE_CLI_REMOTETCPFWD
|
||||
case 'R':
|
||||
nextisremote = 1;
|
||||
break;
|
||||
#endif
|
||||
#ifdef ENABLE_CLI_NETCAT
|
||||
case 'B':
|
||||
nextisnetcat = 1;
|
||||
break;
|
||||
#endif
|
||||
#ifdef ENABLE_CLI_PROXYCMD
|
||||
case 'J':
|
||||
next = &cli_opts.proxycmd;
|
||||
break;
|
||||
#endif
|
||||
case 'l':
|
||||
next = &cli_opts.username;
|
||||
break;
|
||||
case 'h':
|
||||
printhelp();
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case 'u':
|
||||
/* backwards compatibility with old urandom option */
|
||||
break;
|
||||
case 'W':
|
||||
next = &recv_window_arg;
|
||||
break;
|
||||
case 'K':
|
||||
next = &keepalive_arg;
|
||||
break;
|
||||
case 'I':
|
||||
next = &idle_timeout_arg;
|
||||
break;
|
||||
#ifdef DEBUG_TRACE
|
||||
case 'v':
|
||||
debug_trace = 1;
|
||||
break;
|
||||
#endif
|
||||
case 'F':
|
||||
case 'e':
|
||||
case 'c':
|
||||
case 'm':
|
||||
case 'D':
|
||||
#ifndef ENABLE_CLI_REMOTETCPFWD
|
||||
case 'R':
|
||||
#endif
|
||||
#ifndef ENABLE_CLI_LOCALTCPFWD
|
||||
case 'L':
|
||||
#endif
|
||||
case 'o':
|
||||
case 'b':
|
||||
next = &dummy;
|
||||
default:
|
||||
fprintf(stderr,
|
||||
"WARNING: Ignoring unknown argument '%s'\n", argv[i]);
|
||||
break;
|
||||
} /* Switch */
|
||||
|
||||
/* Now we handle args where they might be "-luser" (no spaces)*/
|
||||
if (next && strlen(argv[i]) > 2) {
|
||||
*next = &argv[i][2];
|
||||
next = NULL;
|
||||
}
|
||||
|
||||
continue; /* next argument */
|
||||
|
||||
} else {
|
||||
TRACE(("non-flag arg: '%s'", argv[i]))
|
||||
|
||||
/* Either the hostname or commands */
|
||||
|
||||
if (cli_opts.remotehost == NULL) {
|
||||
#ifdef ENABLE_CLI_MULTIHOP
|
||||
parse_multihop_hostname(argv[i], argv[0]);
|
||||
#else
|
||||
parse_hostname(argv[i]);
|
||||
#endif
|
||||
} else {
|
||||
|
||||
/* this is part of the commands to send - after this we
|
||||
* don't parse any more options, and flags are sent as the
|
||||
* command */
|
||||
cmdlen = 0;
|
||||
for (j = i; j < (unsigned int)argc; j++) {
|
||||
cmdlen += strlen(argv[j]) + 1; /* +1 for spaces */
|
||||
}
|
||||
/* Allocate the space */
|
||||
cli_opts.cmd = (char*)m_malloc(cmdlen);
|
||||
cli_opts.cmd[0] = '\0';
|
||||
|
||||
/* Append all the bits */
|
||||
for (j = i; j < (unsigned int)argc; j++) {
|
||||
strlcat(cli_opts.cmd, argv[j], cmdlen);
|
||||
strlcat(cli_opts.cmd, " ", cmdlen);
|
||||
}
|
||||
/* It'll be null-terminated here */
|
||||
|
||||
/* We've eaten all the options and flags */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* And now a few sanity checks and setup */
|
||||
|
||||
if (cli_opts.remotehost == NULL) {
|
||||
printhelp();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (cli_opts.remoteport == NULL) {
|
||||
cli_opts.remoteport = "22";
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
if (cli_opts.cmd == NULL) {
|
||||
cli_opts.wantpty = 1;
|
||||
} else {
|
||||
cli_opts.wantpty = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (cli_opts.backgrounded && cli_opts.cmd == NULL
|
||||
&& cli_opts.no_cmd == 0) {
|
||||
dropbear_exit("command required for -f");
|
||||
}
|
||||
|
||||
if (recv_window_arg) {
|
||||
opts.recv_window = atol(recv_window_arg);
|
||||
if (opts.recv_window == 0 || opts.recv_window > MAX_RECV_WINDOW) {
|
||||
dropbear_exit("Bad recv window '%s'", recv_window_arg);
|
||||
}
|
||||
}
|
||||
if (keepalive_arg) {
|
||||
if (m_str_to_uint(keepalive_arg, &opts.keepalive_secs) == DROPBEAR_FAILURE) {
|
||||
dropbear_exit("Bad keepalive '%s'", keepalive_arg);
|
||||
}
|
||||
}
|
||||
|
||||
if (idle_timeout_arg) {
|
||||
if (m_str_to_uint(idle_timeout_arg, &opts.idle_timeout_secs) == DROPBEAR_FAILURE) {
|
||||
dropbear_exit("Bad idle_timeout '%s'", idle_timeout_arg);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CLI_NETCAT
|
||||
if (cli_opts.cmd && cli_opts.netcat_host) {
|
||||
dropbear_log(LOG_INFO, "Ignoring command '%s' in netcat mode", cli_opts.cmd);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CLI_PUBKEY_AUTH
|
||||
static void loadidentityfile(const char* filename) {
|
||||
|
||||
struct SignKeyList * nextkey;
|
||||
sign_key *key;
|
||||
int keytype;
|
||||
|
||||
key = new_sign_key();
|
||||
keytype = DROPBEAR_SIGNKEY_ANY;
|
||||
if ( readhostkey(filename, key, &keytype) != DROPBEAR_SUCCESS ) {
|
||||
|
||||
fprintf(stderr, "Failed loading keyfile '%s'\n", filename);
|
||||
sign_key_free(key);
|
||||
|
||||
} else {
|
||||
|
||||
nextkey = (struct SignKeyList*)m_malloc(sizeof(struct SignKeyList));
|
||||
nextkey->key = key;
|
||||
nextkey->next = cli_opts.privkeys;
|
||||
nextkey->type = keytype;
|
||||
cli_opts.privkeys = nextkey;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CLI_MULTIHOP
|
||||
|
||||
/* Sets up 'onion-forwarding' connections. This will spawn
|
||||
* a separate dbclient process for each hop.
|
||||
* As an example, if the cmdline is
|
||||
* dbclient wrt,madako,canyons
|
||||
* then we want to run:
|
||||
* dbclient -J "dbclient -B canyons:22 wrt,madako" canyons
|
||||
* and then the inner dbclient will recursively run:
|
||||
* dbclient -J "dbclient -B madako:22 wrt" madako
|
||||
* etc for as many hosts as we want.
|
||||
*
|
||||
* Ports for hosts can be specified as host/port.
|
||||
*/
|
||||
static void parse_multihop_hostname(const char* orighostarg, const char* argv0) {
|
||||
char *userhostarg = NULL;
|
||||
char *last_hop = NULL;;
|
||||
char *remainder = NULL;
|
||||
|
||||
/* both scp and rsync parse a user@host argument
|
||||
* and turn it into "-l user host". This breaks
|
||||
* for our multihop syntax, so we suture it back together.
|
||||
* This will break usernames that have both '@' and ',' in them,
|
||||
* though that should be fairly uncommon. */
|
||||
if (cli_opts.username
|
||||
&& strchr(cli_opts.username, ',')
|
||||
&& strchr(cli_opts.username, '@')) {
|
||||
unsigned int len = strlen(orighostarg) + strlen(cli_opts.username) + 2;
|
||||
userhostarg = m_malloc(len);
|
||||
snprintf(userhostarg, len, "%s@%s", cli_opts.username, orighostarg);
|
||||
} else {
|
||||
userhostarg = m_strdup(orighostarg);
|
||||
}
|
||||
|
||||
last_hop = strrchr(userhostarg, ',');
|
||||
if (last_hop) {
|
||||
if (last_hop == userhostarg) {
|
||||
dropbear_exit("Bad multi-hop hostnames");
|
||||
}
|
||||
*last_hop = '\0';
|
||||
last_hop++;
|
||||
remainder = userhostarg;
|
||||
userhostarg = last_hop;
|
||||
}
|
||||
|
||||
parse_hostname(userhostarg);
|
||||
|
||||
if (last_hop) {
|
||||
/* Set up the proxycmd */
|
||||
unsigned int cmd_len = 0;
|
||||
if (cli_opts.proxycmd) {
|
||||
dropbear_exit("-J can't be used with multihop mode");
|
||||
}
|
||||
if (cli_opts.remoteport == NULL) {
|
||||
cli_opts.remoteport = "22";
|
||||
}
|
||||
cmd_len = strlen(remainder)
|
||||
+ strlen(cli_opts.remotehost) + strlen(cli_opts.remoteport)
|
||||
+ strlen(argv0) + 30;
|
||||
cli_opts.proxycmd = m_malloc(cmd_len);
|
||||
snprintf(cli_opts.proxycmd, cmd_len, "%s -B %s:%s %s",
|
||||
argv0, cli_opts.remotehost, cli_opts.remoteport, remainder);
|
||||
}
|
||||
}
|
||||
#endif /* !ENABLE_CLI_MULTIHOP */
|
||||
|
||||
/* Parses a [user@]hostname[/port] argument. */
|
||||
static void parse_hostname(const char* orighostarg) {
|
||||
char *userhostarg = NULL;
|
||||
char *port = NULL;
|
||||
|
||||
userhostarg = m_strdup(orighostarg);
|
||||
|
||||
cli_opts.remotehost = strchr(userhostarg, '@');
|
||||
if (cli_opts.remotehost == NULL) {
|
||||
/* no username portion, the cli-auth.c code can figure the
|
||||
* local user's name */
|
||||
cli_opts.remotehost = userhostarg;
|
||||
} else {
|
||||
cli_opts.remotehost[0] = '\0'; /* Split the user/host */
|
||||
cli_opts.remotehost++;
|
||||
cli_opts.username = userhostarg;
|
||||
}
|
||||
|
||||
if (cli_opts.username == NULL) {
|
||||
cli_opts.username = m_strdup(cli_opts.own_user);
|
||||
}
|
||||
|
||||
port = strchr(cli_opts.remotehost, '/');
|
||||
if (port) {
|
||||
*port = '\0';
|
||||
cli_opts.remoteport = port+1;
|
||||
}
|
||||
|
||||
if (cli_opts.remotehost[0] == '\0') {
|
||||
dropbear_exit("Bad hostname");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CLI_NETCAT
|
||||
static void add_netcat(const char* origstr) {
|
||||
char *portstr = NULL;
|
||||
|
||||
char * str = m_strdup(origstr);
|
||||
|
||||
portstr = strchr(str, ':');
|
||||
if (portstr == NULL) {
|
||||
TRACE(("No netcat port"))
|
||||
goto fail;
|
||||
}
|
||||
*portstr = '\0';
|
||||
portstr++;
|
||||
|
||||
if (strchr(portstr, ':')) {
|
||||
TRACE(("Multiple netcat colons"))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (m_str_to_uint(portstr, &cli_opts.netcat_port) == DROPBEAR_FAILURE) {
|
||||
TRACE(("bad netcat port"))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (cli_opts.netcat_port > 65535) {
|
||||
TRACE(("too large netcat port"))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
cli_opts.netcat_host = str;
|
||||
return;
|
||||
|
||||
fail:
|
||||
dropbear_exit("Bad netcat endpoint '%s'", origstr);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void fill_own_user() {
|
||||
uid_t uid;
|
||||
struct passwd *pw = NULL;
|
||||
|
||||
uid = getuid();
|
||||
|
||||
pw = getpwuid(uid);
|
||||
if (pw == NULL || pw->pw_name == NULL) {
|
||||
dropbear_exit("Unknown own user");
|
||||
}
|
||||
|
||||
cli_opts.own_user = m_strdup(pw->pw_name);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CLI_ANYTCPFWD
|
||||
/* Turn a "listenport:remoteaddr:remoteport" string into into a forwarding
|
||||
* set, and add it to the forwarding list */
|
||||
static void addforward(const char* origstr, struct TCPFwdList** fwdlist) {
|
||||
|
||||
char * listenport = NULL;
|
||||
char * connectport = NULL;
|
||||
char * connectaddr = NULL;
|
||||
struct TCPFwdList* newfwd = NULL;
|
||||
char * str = NULL;
|
||||
|
||||
TRACE(("enter addforward"))
|
||||
|
||||
/* We need to split the original argument up. This var
|
||||
is never free()d. */
|
||||
str = m_strdup(origstr);
|
||||
|
||||
listenport = str;
|
||||
|
||||
connectaddr = strchr(str, ':');
|
||||
if (connectaddr == NULL) {
|
||||
TRACE(("connectaddr == NULL"))
|
||||
goto fail;
|
||||
}
|
||||
*connectaddr = '\0';
|
||||
connectaddr++;
|
||||
|
||||
connectport = strchr(connectaddr, ':');
|
||||
if (connectport == NULL) {
|
||||
TRACE(("connectport == NULL"))
|
||||
goto fail;
|
||||
}
|
||||
*connectport = '\0';
|
||||
connectport++;
|
||||
|
||||
newfwd = (struct TCPFwdList*)m_malloc(sizeof(struct TCPFwdList));
|
||||
|
||||
/* Now we check the ports - note that the port ints are unsigned,
|
||||
* the check later only checks for >= MAX_PORT */
|
||||
if (m_str_to_uint(listenport, &newfwd->listenport) == DROPBEAR_FAILURE) {
|
||||
TRACE(("bad listenport strtoul"))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (m_str_to_uint(connectport, &newfwd->connectport) == DROPBEAR_FAILURE) {
|
||||
TRACE(("bad connectport strtoul"))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
newfwd->connectaddr = connectaddr;
|
||||
|
||||
if (newfwd->listenport > 65535) {
|
||||
TRACE(("listenport > 65535"))
|
||||
goto badport;
|
||||
}
|
||||
|
||||
if (newfwd->connectport > 65535) {
|
||||
TRACE(("connectport > 65535"))
|
||||
goto badport;
|
||||
}
|
||||
|
||||
newfwd->have_reply = 0;
|
||||
newfwd->next = *fwdlist;
|
||||
*fwdlist = newfwd;
|
||||
|
||||
TRACE(("leave addforward: done"))
|
||||
return;
|
||||
|
||||
fail:
|
||||
dropbear_exit("Bad TCP forward '%s'", origstr);
|
||||
|
||||
badport:
|
||||
dropbear_exit("Bad TCP port in '%s'", origstr);
|
||||
}
|
||||
#endif
|
||||
85
cli-service.c
Normal file
85
cli-service.c
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Dropbear SSH
|
||||
*
|
||||
* Copyright (c) 2002,2003 Matt Johnston
|
||||
* Copyright (c) 2004 by Mihnea Stoenescu
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#include "includes.h"
|
||||
#include "service.h"
|
||||
#include "dbutil.h"
|
||||
#include "packet.h"
|
||||
#include "buffer.h"
|
||||
#include "session.h"
|
||||
#include "ssh.h"
|
||||
|
||||
void send_msg_service_request(char* servicename) {
|
||||
|
||||
TRACE(("enter send_msg_service_request: servicename='%s'", servicename))
|
||||
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_SERVICE_REQUEST);
|
||||
buf_putstring(ses.writepayload, servicename, strlen(servicename));
|
||||
|
||||
encrypt_packet();
|
||||
TRACE(("leave send_msg_service_request"))
|
||||
}
|
||||
|
||||
/* This just sets up the state variables right for the main client session loop
|
||||
* to deal with */
|
||||
void recv_msg_service_accept() {
|
||||
|
||||
unsigned char* servicename;
|
||||
unsigned int len;
|
||||
|
||||
TRACE(("enter recv_msg_service_accept"))
|
||||
|
||||
servicename = buf_getstring(ses.payload, &len);
|
||||
|
||||
/* ssh-userauth */
|
||||
if (cli_ses.state == SERVICE_AUTH_REQ_SENT
|
||||
&& len == SSH_SERVICE_USERAUTH_LEN
|
||||
&& strncmp(SSH_SERVICE_USERAUTH, servicename, len) == 0) {
|
||||
|
||||
cli_ses.state = SERVICE_AUTH_ACCEPT_RCVD;
|
||||
m_free(servicename);
|
||||
TRACE(("leave recv_msg_service_accept: done ssh-userauth"))
|
||||
return;
|
||||
}
|
||||
|
||||
/* ssh-connection */
|
||||
if (cli_ses.state == SERVICE_CONN_REQ_SENT
|
||||
&& len == SSH_SERVICE_CONNECTION_LEN
|
||||
&& strncmp(SSH_SERVICE_CONNECTION, servicename, len) == 0) {
|
||||
|
||||
if (ses.authstate.authdone != 1) {
|
||||
dropbear_exit("request for connection before auth");
|
||||
}
|
||||
|
||||
cli_ses.state = SERVICE_CONN_ACCEPT_RCVD;
|
||||
m_free(servicename);
|
||||
TRACE(("leave recv_msg_service_accept: done ssh-connection"))
|
||||
return;
|
||||
}
|
||||
|
||||
dropbear_exit("unrecognised service accept");
|
||||
}
|
||||
320
cli-session.c
Normal file
320
cli-session.c
Normal file
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
* Dropbear SSH
|
||||
*
|
||||
* Copyright (c) 2002,2003 Matt Johnston
|
||||
* Copyright (c) 2004 by Mihnea Stoenescu
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#include "includes.h"
|
||||
#include "session.h"
|
||||
#include "dbutil.h"
|
||||
#include "kex.h"
|
||||
#include "ssh.h"
|
||||
#include "packet.h"
|
||||
#include "tcpfwd.h"
|
||||
#include "channel.h"
|
||||
#include "random.h"
|
||||
#include "service.h"
|
||||
#include "runopts.h"
|
||||
#include "chansession.h"
|
||||
|
||||
static void cli_remoteclosed();
|
||||
static void cli_sessionloop();
|
||||
static void cli_session_init();
|
||||
static void cli_finished();
|
||||
|
||||
struct clientsession cli_ses; /* GLOBAL */
|
||||
|
||||
/* Sorted in decreasing frequency will be more efficient - data and window
|
||||
* should be first */
|
||||
static const packettype cli_packettypes[] = {
|
||||
/* TYPE, FUNCTION */
|
||||
{SSH_MSG_CHANNEL_DATA, recv_msg_channel_data},
|
||||
{SSH_MSG_CHANNEL_EXTENDED_DATA, recv_msg_channel_extended_data},
|
||||
{SSH_MSG_CHANNEL_WINDOW_ADJUST, recv_msg_channel_window_adjust},
|
||||
{SSH_MSG_USERAUTH_FAILURE, recv_msg_userauth_failure}, /* client */
|
||||
{SSH_MSG_USERAUTH_SUCCESS, recv_msg_userauth_success}, /* client */
|
||||
{SSH_MSG_KEXINIT, recv_msg_kexinit},
|
||||
{SSH_MSG_KEXDH_REPLY, recv_msg_kexdh_reply}, /* client */
|
||||
{SSH_MSG_NEWKEYS, recv_msg_newkeys},
|
||||
{SSH_MSG_SERVICE_ACCEPT, recv_msg_service_accept}, /* client */
|
||||
{SSH_MSG_CHANNEL_REQUEST, recv_msg_channel_request},
|
||||
{SSH_MSG_CHANNEL_OPEN, recv_msg_channel_open},
|
||||
{SSH_MSG_CHANNEL_EOF, recv_msg_channel_eof},
|
||||
{SSH_MSG_CHANNEL_CLOSE, recv_msg_channel_close},
|
||||
{SSH_MSG_CHANNEL_OPEN_CONFIRMATION, recv_msg_channel_open_confirmation},
|
||||
{SSH_MSG_CHANNEL_OPEN_FAILURE, recv_msg_channel_open_failure},
|
||||
{SSH_MSG_USERAUTH_BANNER, recv_msg_userauth_banner}, /* client */
|
||||
{SSH_MSG_USERAUTH_SPECIFIC_60, recv_msg_userauth_specific_60}, /* client */
|
||||
#ifdef ENABLE_CLI_REMOTETCPFWD
|
||||
{SSH_MSG_REQUEST_SUCCESS, cli_recv_msg_request_success}, /* client */
|
||||
{SSH_MSG_REQUEST_FAILURE, cli_recv_msg_request_failure}, /* client */
|
||||
#endif
|
||||
{0, 0} /* End */
|
||||
};
|
||||
|
||||
static const struct ChanType *cli_chantypes[] = {
|
||||
#ifdef ENABLE_CLI_REMOTETCPFWD
|
||||
&cli_chan_tcpremote,
|
||||
#endif
|
||||
NULL /* Null termination */
|
||||
};
|
||||
|
||||
void cli_session(int sock_in, int sock_out, char* remotehost) {
|
||||
|
||||
seedrandom();
|
||||
|
||||
crypto_init();
|
||||
|
||||
common_session_init(sock_in, sock_out, remotehost);
|
||||
|
||||
chaninitialise(cli_chantypes);
|
||||
|
||||
/* Set up cli_ses vars */
|
||||
cli_session_init();
|
||||
|
||||
/* Ready to go */
|
||||
sessinitdone = 1;
|
||||
|
||||
/* Exchange identification */
|
||||
session_identification();
|
||||
|
||||
send_msg_kexinit();
|
||||
|
||||
session_loop(cli_sessionloop);
|
||||
|
||||
/* Not reached */
|
||||
|
||||
}
|
||||
|
||||
static void cli_session_init() {
|
||||
|
||||
cli_ses.state = STATE_NOTHING;
|
||||
cli_ses.kex_state = KEX_NOTHING;
|
||||
|
||||
cli_ses.tty_raw_mode = 0;
|
||||
cli_ses.winchange = 0;
|
||||
|
||||
/* We store std{in,out,err}'s flags, so we can set them back on exit
|
||||
* (otherwise busybox's ash isn't happy */
|
||||
cli_ses.stdincopy = dup(STDIN_FILENO);
|
||||
cli_ses.stdinflags = fcntl(STDIN_FILENO, F_GETFL, 0);
|
||||
cli_ses.stdoutcopy = dup(STDOUT_FILENO);
|
||||
cli_ses.stdoutflags = fcntl(STDOUT_FILENO, F_GETFL, 0);
|
||||
cli_ses.stderrcopy = dup(STDERR_FILENO);
|
||||
cli_ses.stderrflags = fcntl(STDERR_FILENO, F_GETFL, 0);
|
||||
|
||||
cli_ses.retval = EXIT_SUCCESS; /* Assume it's clean if we don't get a
|
||||
specific exit status */
|
||||
|
||||
/* Auth */
|
||||
cli_ses.lastprivkey = NULL;
|
||||
cli_ses.lastauthtype = 0;
|
||||
|
||||
/* For printing "remote host closed" for the user */
|
||||
ses.remoteclosed = cli_remoteclosed;
|
||||
ses.buf_match_algo = cli_buf_match_algo;
|
||||
|
||||
/* packet handlers */
|
||||
ses.packettypes = cli_packettypes;
|
||||
|
||||
ses.isserver = 0;
|
||||
}
|
||||
|
||||
/* This function drives the progress of the session - it initiates KEX,
|
||||
* service, userauth and channel requests */
|
||||
static void cli_sessionloop() {
|
||||
|
||||
TRACE(("enter cli_sessionloop"))
|
||||
|
||||
if (ses.lastpacket == SSH_MSG_KEXINIT && cli_ses.kex_state == KEX_NOTHING) {
|
||||
cli_ses.kex_state = KEXINIT_RCVD;
|
||||
}
|
||||
|
||||
if (cli_ses.kex_state == KEXINIT_RCVD) {
|
||||
|
||||
/* We initiate the KEXDH. If DH wasn't the correct type, the KEXINIT
|
||||
* negotiation would have failed. */
|
||||
send_msg_kexdh_init();
|
||||
cli_ses.kex_state = KEXDH_INIT_SENT;
|
||||
TRACE(("leave cli_sessionloop: done with KEXINIT_RCVD"))
|
||||
return;
|
||||
}
|
||||
|
||||
/* A KEX has finished, so we should go back to our KEX_NOTHING state */
|
||||
if (cli_ses.kex_state != KEX_NOTHING && ses.kexstate.recvkexinit == 0
|
||||
&& ses.kexstate.sentkexinit == 0) {
|
||||
cli_ses.kex_state = KEX_NOTHING;
|
||||
}
|
||||
|
||||
/* We shouldn't do anything else if a KEX is in progress */
|
||||
if (cli_ses.kex_state != KEX_NOTHING) {
|
||||
TRACE(("leave cli_sessionloop: kex_state != KEX_NOTHING"))
|
||||
return;
|
||||
}
|
||||
|
||||
/* We should exit if we haven't donefirstkex: we shouldn't reach here
|
||||
* in normal operation */
|
||||
if (ses.kexstate.donefirstkex == 0) {
|
||||
TRACE(("XXX XXX might be bad! leave cli_sessionloop: haven't donefirstkex"))
|
||||
return;
|
||||
}
|
||||
|
||||
switch (cli_ses.state) {
|
||||
|
||||
case STATE_NOTHING:
|
||||
/* We've got the transport layer sorted, we now need to request
|
||||
* userauth */
|
||||
send_msg_service_request(SSH_SERVICE_USERAUTH);
|
||||
cli_ses.state = SERVICE_AUTH_REQ_SENT;
|
||||
TRACE(("leave cli_sessionloop: sent userauth service req"))
|
||||
return;
|
||||
|
||||
/* userauth code */
|
||||
case SERVICE_AUTH_ACCEPT_RCVD:
|
||||
cli_auth_getmethods();
|
||||
cli_ses.state = USERAUTH_REQ_SENT;
|
||||
TRACE(("leave cli_sessionloop: sent userauth methods req"))
|
||||
return;
|
||||
|
||||
case USERAUTH_FAIL_RCVD:
|
||||
cli_auth_try();
|
||||
cli_ses.state = USERAUTH_REQ_SENT;
|
||||
TRACE(("leave cli_sessionloop: cli_auth_try"))
|
||||
return;
|
||||
|
||||
case USERAUTH_SUCCESS_RCVD:
|
||||
|
||||
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);
|
||||
if (devnull < 0) {
|
||||
dropbear_exit("opening /dev/null: %d %s",
|
||||
errno, strerror(errno));
|
||||
}
|
||||
dup2(devnull, STDIN_FILENO);
|
||||
if (daemon(0, 1) < 0) {
|
||||
dropbear_exit("Backgrounding failed: %d %s",
|
||||
errno, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CLI_LOCALTCPFWD
|
||||
setup_localtcp();
|
||||
#endif
|
||||
#ifdef ENABLE_CLI_REMOTETCPFWD
|
||||
setup_remotetcp();
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CLI_NETCAT
|
||||
if (cli_opts.netcat_host) {
|
||||
cli_send_netcat_request();
|
||||
} else
|
||||
#endif
|
||||
if (!cli_opts.no_cmd) {
|
||||
cli_send_chansess_request();
|
||||
}
|
||||
TRACE(("leave cli_sessionloop: running"))
|
||||
cli_ses.state = SESSION_RUNNING;
|
||||
return;
|
||||
|
||||
case SESSION_RUNNING:
|
||||
if (ses.chancount < 1 && !cli_opts.no_cmd) {
|
||||
cli_finished();
|
||||
}
|
||||
|
||||
if (cli_ses.winchange) {
|
||||
cli_chansess_winchange();
|
||||
}
|
||||
return;
|
||||
|
||||
/* XXX more here needed */
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
TRACE(("leave cli_sessionloop: fell out"))
|
||||
|
||||
}
|
||||
|
||||
void cli_session_cleanup() {
|
||||
|
||||
if (!sessinitdone) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set std{in,out,err} back to non-blocking - busybox ash dies nastily if
|
||||
* we don't revert the flags */
|
||||
fcntl(cli_ses.stdincopy, F_SETFL, cli_ses.stdinflags);
|
||||
fcntl(cli_ses.stdoutcopy, F_SETFL, cli_ses.stdoutflags);
|
||||
fcntl(cli_ses.stderrcopy, F_SETFL, cli_ses.stderrflags);
|
||||
|
||||
cli_tty_cleanup();
|
||||
|
||||
}
|
||||
|
||||
static void cli_finished() {
|
||||
|
||||
cli_session_cleanup();
|
||||
common_session_cleanup();
|
||||
fprintf(stderr, "Connection to %s@%s:%s closed.\n", cli_opts.username,
|
||||
cli_opts.remotehost, cli_opts.remoteport);
|
||||
exit(cli_ses.retval);
|
||||
}
|
||||
|
||||
|
||||
/* called when the remote side closes the connection */
|
||||
static void cli_remoteclosed() {
|
||||
|
||||
/* XXX TODO perhaps print a friendlier message if we get this but have
|
||||
* already sent/received disconnect message(s) ??? */
|
||||
m_close(ses.sock_in);
|
||||
m_close(ses.sock_out);
|
||||
ses.sock_in = -1;
|
||||
ses.sock_out = -1;
|
||||
dropbear_exit("remote closed the connection");
|
||||
}
|
||||
|
||||
/* Operates in-place turning dirty (untrusted potentially containing control
|
||||
* characters) text into clean text.
|
||||
* Note: this is safe only with ascii - other charsets could have problems. */
|
||||
void cleantext(unsigned char* dirtytext) {
|
||||
|
||||
unsigned int i, j;
|
||||
unsigned char c;
|
||||
|
||||
j = 0;
|
||||
for (i = 0; dirtytext[i] != '\0'; i++) {
|
||||
|
||||
c = dirtytext[i];
|
||||
/* We can ignore '\r's */
|
||||
if ( (c >= ' ' && c <= '~') || c == '\n' || c == '\t') {
|
||||
dirtytext[j] = c;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
/* Null terminate */
|
||||
dirtytext[j] = '\0';
|
||||
}
|
||||
252
cli-tcpfwd.c
Normal file
252
cli-tcpfwd.c
Normal file
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
* Dropbear SSH
|
||||
*
|
||||
* 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 "options.h"
|
||||
#include "dbutil.h"
|
||||
#include "tcpfwd.h"
|
||||
#include "channel.h"
|
||||
#include "runopts.h"
|
||||
#include "session.h"
|
||||
#include "ssh.h"
|
||||
|
||||
#ifdef ENABLE_CLI_REMOTETCPFWD
|
||||
static int newtcpforwarded(struct Channel * channel);
|
||||
|
||||
const struct ChanType cli_chan_tcpremote = {
|
||||
1, /* sepfds */
|
||||
"forwarded-tcpip",
|
||||
newtcpforwarded,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CLI_LOCALTCPFWD
|
||||
static int cli_localtcp(unsigned int listenport, const char* remoteaddr,
|
||||
unsigned int remoteport);
|
||||
static const struct ChanType cli_chan_tcplocal = {
|
||||
1, /* sepfds */
|
||||
"direct-tcpip",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CLI_LOCALTCPFWD
|
||||
void setup_localtcp() {
|
||||
|
||||
int ret;
|
||||
|
||||
TRACE(("enter setup_localtcp"))
|
||||
|
||||
if (cli_opts.localfwds == NULL) {
|
||||
TRACE(("cli_opts.localfwds == NULL"))
|
||||
}
|
||||
|
||||
while (cli_opts.localfwds != NULL) {
|
||||
ret = cli_localtcp(cli_opts.localfwds->listenport,
|
||||
cli_opts.localfwds->connectaddr,
|
||||
cli_opts.localfwds->connectport);
|
||||
if (ret == DROPBEAR_FAILURE) {
|
||||
dropbear_log(LOG_WARNING, "Failed local port forward %d:%s:%d",
|
||||
cli_opts.localfwds->listenport,
|
||||
cli_opts.localfwds->connectaddr,
|
||||
cli_opts.localfwds->connectport);
|
||||
}
|
||||
|
||||
cli_opts.localfwds = cli_opts.localfwds->next;
|
||||
}
|
||||
TRACE(("leave setup_localtcp"))
|
||||
|
||||
}
|
||||
|
||||
static int cli_localtcp(unsigned int listenport, const char* remoteaddr,
|
||||
unsigned int remoteport) {
|
||||
|
||||
struct TCPListener* tcpinfo = NULL;
|
||||
int ret;
|
||||
|
||||
TRACE(("enter cli_localtcp: %d %s %d", listenport, remoteaddr,
|
||||
remoteport));
|
||||
|
||||
tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener));
|
||||
|
||||
tcpinfo->sendaddr = m_strdup(remoteaddr);
|
||||
tcpinfo->sendport = remoteport;
|
||||
|
||||
if (opts.listen_fwd_all) {
|
||||
tcpinfo->listenaddr = m_strdup("");
|
||||
} else {
|
||||
tcpinfo->listenaddr = m_strdup("localhost");
|
||||
}
|
||||
tcpinfo->listenport = listenport;
|
||||
|
||||
tcpinfo->chantype = &cli_chan_tcplocal;
|
||||
tcpinfo->tcp_type = direct;
|
||||
|
||||
ret = listen_tcpfwd(tcpinfo);
|
||||
|
||||
if (ret == DROPBEAR_FAILURE) {
|
||||
m_free(tcpinfo);
|
||||
}
|
||||
TRACE(("leave cli_localtcp: %d", ret))
|
||||
return ret;
|
||||
}
|
||||
#endif /* ENABLE_CLI_LOCALTCPFWD */
|
||||
|
||||
#ifdef ENABLE_CLI_REMOTETCPFWD
|
||||
static void send_msg_global_request_remotetcp(int port) {
|
||||
|
||||
char* listenspec = NULL;
|
||||
TRACE(("enter send_msg_global_request_remotetcp"))
|
||||
|
||||
CHECKCLEARTOWRITE();
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST);
|
||||
buf_putstring(ses.writepayload, "tcpip-forward", 13);
|
||||
buf_putbyte(ses.writepayload, 1); /* want_reply */
|
||||
if (opts.listen_fwd_all) {
|
||||
listenspec = "";
|
||||
} else {
|
||||
listenspec = "localhost";
|
||||
}
|
||||
/* TODO: IPv6? */;
|
||||
buf_putstring(ses.writepayload, listenspec, strlen(listenspec));
|
||||
buf_putint(ses.writepayload, port);
|
||||
|
||||
encrypt_packet();
|
||||
|
||||
TRACE(("leave send_msg_global_request_remotetcp"))
|
||||
}
|
||||
|
||||
/* The only global success/failure messages are for remotetcp.
|
||||
* Since there isn't any identifier in these messages, we have to rely on them
|
||||
* being in the same order as we sent the requests. This is the ordering
|
||||
* of the cli_opts.remotefwds list */
|
||||
void cli_recv_msg_request_success() {
|
||||
|
||||
/* Nothing in the packet. We just mark off that we have received the reply,
|
||||
* so that we can report failure for later ones. */
|
||||
struct TCPFwdList * iter = NULL;
|
||||
|
||||
iter = cli_opts.remotefwds;
|
||||
while (iter != NULL) {
|
||||
if (!iter->have_reply)
|
||||
{
|
||||
iter->have_reply = 1;
|
||||
return;
|
||||
}
|
||||
iter = iter->next;
|
||||
}
|
||||
}
|
||||
|
||||
void cli_recv_msg_request_failure() {
|
||||
struct TCPFwdList * iter = NULL;
|
||||
|
||||
iter = cli_opts.remotefwds;
|
||||
while (iter != NULL) {
|
||||
if (!iter->have_reply)
|
||||
{
|
||||
iter->have_reply = 1;
|
||||
dropbear_log(LOG_WARNING, "Remote TCP forward request failed (port %d -> %s:%d)", iter->listenport, iter->connectaddr, iter->connectport);
|
||||
return;
|
||||
}
|
||||
iter = iter->next;
|
||||
}
|
||||
}
|
||||
|
||||
void setup_remotetcp() {
|
||||
|
||||
struct TCPFwdList * iter = NULL;
|
||||
|
||||
TRACE(("enter setup_remotetcp"))
|
||||
|
||||
if (cli_opts.remotefwds == NULL) {
|
||||
TRACE(("cli_opts.remotefwds == NULL"))
|
||||
}
|
||||
|
||||
iter = cli_opts.remotefwds;
|
||||
|
||||
while (iter != NULL) {
|
||||
send_msg_global_request_remotetcp(iter->listenport);
|
||||
iter = iter->next;
|
||||
}
|
||||
TRACE(("leave setup_remotetcp"))
|
||||
}
|
||||
|
||||
static int newtcpforwarded(struct Channel * channel) {
|
||||
|
||||
unsigned int origport;
|
||||
struct TCPFwdList * iter = NULL;
|
||||
char portstring[NI_MAXSERV];
|
||||
int sock;
|
||||
int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
|
||||
|
||||
/* We don't care what address they connected to */
|
||||
buf_eatstring(ses.payload);
|
||||
|
||||
origport = buf_getint(ses.payload);
|
||||
|
||||
/* Find which port corresponds */
|
||||
iter = cli_opts.remotefwds;
|
||||
|
||||
while (iter != NULL) {
|
||||
if (origport == iter->listenport) {
|
||||
break;
|
||||
}
|
||||
iter = iter->next;
|
||||
}
|
||||
|
||||
if (iter == NULL) {
|
||||
/* We didn't request forwarding on that port */
|
||||
dropbear_log(LOG_INFO, "Server send unrequested port, from port %d",
|
||||
origport);
|
||||
goto out;
|
||||
}
|
||||
|
||||
snprintf(portstring, sizeof(portstring), "%d", iter->connectport);
|
||||
sock = connect_remote(iter->connectaddr, portstring, 1, NULL);
|
||||
if (sock < 0) {
|
||||
TRACE(("leave newtcpdirect: sock failed"))
|
||||
err = SSH_OPEN_CONNECT_FAILED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ses.maxfd = MAX(ses.maxfd, sock);
|
||||
|
||||
/* We don't set readfd, that will get set after the connection's
|
||||
* progress succeeds */
|
||||
channel->writefd = sock;
|
||||
channel->initconn = 1;
|
||||
|
||||
err = SSH_OPEN_IN_PROGRESS;
|
||||
|
||||
out:
|
||||
TRACE(("leave newtcpdirect: err %d", err))
|
||||
return err;
|
||||
}
|
||||
#endif /* ENABLE_CLI_REMOTETCPFWD */
|
||||
276
common-algo.c
Normal file
276
common-algo.c
Normal file
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* Dropbear SSH
|
||||
*
|
||||
* Copyright (c) 2002,2003 Matt Johnston
|
||||
* Copyright (c) 2004 by Mihnea Stoenescu
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#include "algo.h"
|
||||
#include "dbutil.h"
|
||||
|
||||
/* This file (algo.c) organises the ciphers which can be used, and is used to
|
||||
* decide which ciphers/hashes/compression/signing to use during key exchange*/
|
||||
|
||||
static int void_cipher(const unsigned char* in, unsigned char* out,
|
||||
unsigned long len, void *cipher_state) {
|
||||
memcpy(out, in, len);
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
static int void_start(int cipher, const unsigned char *IV,
|
||||
const unsigned char *key,
|
||||
int keylen, int num_rounds, void *cipher_state) {
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
/* Mappings for ciphers, parameters are
|
||||
{&cipher_desc, keysize, blocksize} */
|
||||
/* NOTE: if keysize > 2*SHA1_HASH_SIZE, code such as hashkeys()
|
||||
needs revisiting */
|
||||
|
||||
#ifdef DROPBEAR_AES256
|
||||
static const struct dropbear_cipher dropbear_aes256 =
|
||||
{&aes_desc, 32, 16};
|
||||
#endif
|
||||
#ifdef 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
|
||||
static const struct dropbear_cipher dropbear_twofish256 =
|
||||
{&twofish_desc, 32, 16};
|
||||
#endif
|
||||
#ifdef DROPBEAR_TWOFISH128
|
||||
static const struct dropbear_cipher dropbear_twofish128 =
|
||||
{&twofish_desc, 16, 16};
|
||||
#endif
|
||||
#ifdef DROPBEAR_3DES
|
||||
static const struct dropbear_cipher dropbear_3des =
|
||||
{&des3_desc, 24, 8};
|
||||
#endif
|
||||
|
||||
/* used to indicate no encryption, as defined in rfc2410 */
|
||||
const struct dropbear_cipher dropbear_nocipher =
|
||||
{NULL, 16, 8};
|
||||
|
||||
/* A few void* s are required to silence warnings
|
||||
* about the symmetric_CBC vs symmetric_CTR cipher_state pointer */
|
||||
const struct dropbear_cipher_mode dropbear_mode_cbc =
|
||||
{(void*)cbc_start, (void*)cbc_encrypt, (void*)cbc_decrypt};
|
||||
const struct dropbear_cipher_mode dropbear_mode_none =
|
||||
{void_start, void_cipher, void_cipher};
|
||||
#ifdef DROPBEAR_ENABLE_CTR_MODE
|
||||
/* a wrapper to make ctr_start and cbc_start look the same */
|
||||
static int dropbear_big_endian_ctr_start(int cipher,
|
||||
const unsigned char *IV,
|
||||
const unsigned char *key, int keylen,
|
||||
int num_rounds, symmetric_CTR *ctr) {
|
||||
return ctr_start(cipher, IV, key, keylen, num_rounds, CTR_COUNTER_BIG_ENDIAN, ctr);
|
||||
}
|
||||
const struct dropbear_cipher_mode dropbear_mode_ctr =
|
||||
{(void*)dropbear_big_endian_ctr_start, (void*)ctr_encrypt, (void*)ctr_decrypt};
|
||||
#endif
|
||||
|
||||
/* Mapping of ssh hashes to libtomcrypt hashes, including keysize etc.
|
||||
{&hash_desc, keysize, hashsize} */
|
||||
|
||||
#ifdef DROPBEAR_SHA1_HMAC
|
||||
static const struct dropbear_hash dropbear_sha1 =
|
||||
{&sha1_desc, 20, 20};
|
||||
#endif
|
||||
#ifdef DROPBEAR_SHA1_96_HMAC
|
||||
static const struct dropbear_hash dropbear_sha1_96 =
|
||||
{&sha1_desc, 20, 12};
|
||||
#endif
|
||||
#ifdef DROPBEAR_MD5_HMAC
|
||||
static const struct dropbear_hash dropbear_md5 =
|
||||
{&md5_desc, 16, 16};
|
||||
#endif
|
||||
|
||||
const struct dropbear_hash dropbear_nohash =
|
||||
{NULL, 16, 0}; /* used initially */
|
||||
|
||||
|
||||
/* The following map ssh names to internal values.
|
||||
* The ordering here is important for the client - the first mode
|
||||
* that is also supported by the server will get used. */
|
||||
|
||||
algo_type sshciphers[] = {
|
||||
#ifdef DROPBEAR_ENABLE_CTR_MODE
|
||||
#ifdef DROPBEAR_AES128
|
||||
{"aes128-ctr", 0, &dropbear_aes128, 1, &dropbear_mode_ctr},
|
||||
#endif
|
||||
#ifdef DROPBEAR_3DES
|
||||
{"3des-ctr", 0, &dropbear_3des, 1, &dropbear_mode_ctr},
|
||||
#endif
|
||||
#ifdef DROPBEAR_AES256
|
||||
{"aes256-ctr", 0, &dropbear_aes256, 1, &dropbear_mode_ctr},
|
||||
#endif
|
||||
#endif /* DROPBEAR_ENABLE_CTR_MODE */
|
||||
|
||||
/* CBC modes are always enabled */
|
||||
#ifdef DROPBEAR_AES128
|
||||
{"aes128-cbc", 0, &dropbear_aes128, 1, &dropbear_mode_cbc},
|
||||
#endif
|
||||
#ifdef DROPBEAR_3DES
|
||||
{"3des-cbc", 0, &dropbear_3des, 1, &dropbear_mode_cbc},
|
||||
#endif
|
||||
#ifdef DROPBEAR_AES256
|
||||
{"aes256-cbc", 0, &dropbear_aes256, 1, &dropbear_mode_cbc},
|
||||
#endif
|
||||
#ifdef DROPBEAR_TWOFISH256
|
||||
{"twofish256-cbc", 0, &dropbear_twofish256, 1, &dropbear_mode_cbc},
|
||||
{"twofish-cbc", 0, &dropbear_twofish256, 1, &dropbear_mode_cbc},
|
||||
#endif
|
||||
#ifdef DROPBEAR_TWOFISH128
|
||||
{"twofish128-cbc", 0, &dropbear_twofish128, 1, &dropbear_mode_cbc},
|
||||
#endif
|
||||
#ifdef DROPBEAR_BLOWFISH
|
||||
{"blowfish-cbc", 0, &dropbear_blowfish, 1, &dropbear_mode_cbc},
|
||||
#endif
|
||||
{NULL, 0, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
algo_type sshhashes[] = {
|
||||
#ifdef DROPBEAR_SHA1_96_HMAC
|
||||
{"hmac-sha1-96", 0, &dropbear_sha1_96, 1, NULL},
|
||||
#endif
|
||||
#ifdef DROPBEAR_SHA1_HMAC
|
||||
{"hmac-sha1", 0, &dropbear_sha1, 1, NULL},
|
||||
#endif
|
||||
#ifdef DROPBEAR_MD5_HMAC
|
||||
{"hmac-md5", 0, &dropbear_md5, 1, NULL},
|
||||
#endif
|
||||
{NULL, 0, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
algo_type sshcompress[] = {
|
||||
#ifndef DISABLE_ZLIB
|
||||
{"zlib", DROPBEAR_COMP_ZLIB, NULL, 1, NULL},
|
||||
{"zlib@openssh.com", DROPBEAR_COMP_ZLIB_DELAY, NULL, 1, NULL},
|
||||
#endif
|
||||
{"none", DROPBEAR_COMP_NONE, NULL, 1, NULL},
|
||||
{NULL, 0, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
algo_type sshhostkey[] = {
|
||||
#ifdef DROPBEAR_RSA
|
||||
{"ssh-rsa", DROPBEAR_SIGNKEY_RSA, NULL, 1, NULL},
|
||||
#endif
|
||||
#ifdef DROPBEAR_DSS
|
||||
{"ssh-dss", DROPBEAR_SIGNKEY_DSS, NULL, 1, NULL},
|
||||
#endif
|
||||
{NULL, 0, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
algo_type sshkex[] = {
|
||||
{"diffie-hellman-group1-sha1", DROPBEAR_KEX_DH_GROUP1, NULL, 1, NULL},
|
||||
{NULL, 0, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
||||
/* Register the compiled in ciphers.
|
||||
* This should be run before using any of the ciphers/hashes */
|
||||
void crypto_init() {
|
||||
|
||||
const struct ltc_cipher_descriptor *regciphers[] = {
|
||||
#ifdef DROPBEAR_AES
|
||||
&aes_desc,
|
||||
#endif
|
||||
#ifdef DROPBEAR_BLOWFISH
|
||||
&blowfish_desc,
|
||||
#endif
|
||||
#ifdef DROPBEAR_TWOFISH
|
||||
&twofish_desc,
|
||||
#endif
|
||||
#ifdef DROPBEAR_3DES
|
||||
&des3_desc,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct ltc_hash_descriptor *reghashes[] = {
|
||||
/* we need sha1 for hostkey stuff regardless */
|
||||
&sha1_desc,
|
||||
#ifdef DROPBEAR_MD5_HMAC
|
||||
&md5_desc,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; regciphers[i] != NULL; i++) {
|
||||
if (register_cipher(regciphers[i]) == -1) {
|
||||
dropbear_exit("error registering crypto");
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; reghashes[i] != NULL; i++) {
|
||||
if (register_hash(reghashes[i]) == -1) {
|
||||
dropbear_exit("error registering crypto");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* algolen specifies the length of algo, algos is our local list to match
|
||||
* against.
|
||||
* Returns DROPBEAR_SUCCESS if we have a match for algo, DROPBEAR_FAILURE
|
||||
* 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[]) {
|
||||
|
||||
unsigned int i, len;
|
||||
unsigned int donefirst = 0;
|
||||
buffer *algolist = NULL;
|
||||
|
||||
algolist = buf_new(160);
|
||||
for (i = 0; localalgos[i].name != NULL; i++) {
|
||||
if (localalgos[i].usable) {
|
||||
if (donefirst)
|
||||
buf_putbyte(algolist, ',');
|
||||
donefirst = 1;
|
||||
len = strlen(localalgos[i].name);
|
||||
buf_putbytes(algolist, localalgos[i].name, len);
|
||||
}
|
||||
}
|
||||
buf_putstring(buf, algolist->data, algolist->len);
|
||||
buf_free(algolist);
|
||||
}
|
||||
1047
common-channel.c
Normal file
1047
common-channel.c
Normal file
File diff suppressed because it is too large
Load Diff
43
common-chansession.c
Normal file
43
common-chansession.c
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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 "chansession.h"
|
||||
|
||||
/* Mapping of signal values to ssh signal strings */
|
||||
const struct SigMap signames[] = {
|
||||
{SIGABRT, "ABRT"},
|
||||
{SIGALRM, "ALRM"},
|
||||
{SIGFPE, "FPE"},
|
||||
{SIGHUP, "HUP"},
|
||||
{SIGILL, "ILL"},
|
||||
{SIGINT, "INT"},
|
||||
{SIGKILL, "KILL"},
|
||||
{SIGPIPE, "PIPE"},
|
||||
{SIGQUIT, "QUIT"},
|
||||
{SIGSEGV, "SEGV"},
|
||||
{SIGTERM, "TERM"},
|
||||
{SIGUSR1, "USR1"},
|
||||
{SIGUSR2, "USR2"},
|
||||
{0, NULL}
|
||||
};
|
||||
739
common-kex.c
Normal file
739
common-kex.c
Normal file
@@ -0,0 +1,739 @@
|
||||
/*
|
||||
* Dropbear SSH
|
||||
*
|
||||
* Copyright (c) 2002-2004 Matt Johnston
|
||||
* Portions Copyright (c) 2004 by Mihnea Stoenescu
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#include "includes.h"
|
||||
#include "dbutil.h"
|
||||
#include "algo.h"
|
||||
#include "buffer.h"
|
||||
#include "session.h"
|
||||
#include "kex.h"
|
||||
#include "ssh.h"
|
||||
#include "packet.h"
|
||||
#include "bignum.h"
|
||||
#include "random.h"
|
||||
|
||||
/* diffie-hellman-group1-sha1 value for p */
|
||||
static const unsigned char dh_p_val[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
|
||||
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
||||
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
|
||||
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
||||
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
|
||||
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
||||
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
|
||||
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
|
||||
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
|
||||
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
#define DH_P_LEN sizeof(dh_p_val)
|
||||
|
||||
static const int DH_G_VAL = 2;
|
||||
|
||||
static void kexinitialise();
|
||||
void gen_new_keys();
|
||||
#ifndef DISABLE_ZLIB
|
||||
static void gen_new_zstreams();
|
||||
#endif
|
||||
static void read_kex_algos();
|
||||
/* helper function for gen_new_keys */
|
||||
static void hashkeys(unsigned char *out, int outlen,
|
||||
const hash_state * hs, unsigned const char X);
|
||||
|
||||
|
||||
/* Send our list of algorithms we can use */
|
||||
void send_msg_kexinit() {
|
||||
|
||||
CHECKCLEARTOWRITE();
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_KEXINIT);
|
||||
|
||||
/* cookie */
|
||||
genrandom(buf_getwriteptr(ses.writepayload, 16), 16);
|
||||
buf_incrwritepos(ses.writepayload, 16);
|
||||
|
||||
/* kex algos */
|
||||
buf_put_algolist(ses.writepayload, sshkex);
|
||||
|
||||
/* server_host_key_algorithms */
|
||||
buf_put_algolist(ses.writepayload, sshhostkey);
|
||||
|
||||
/* encryption_algorithms_client_to_server */
|
||||
buf_put_algolist(ses.writepayload, sshciphers);
|
||||
|
||||
/* encryption_algorithms_server_to_client */
|
||||
buf_put_algolist(ses.writepayload, sshciphers);
|
||||
|
||||
/* mac_algorithms_client_to_server */
|
||||
buf_put_algolist(ses.writepayload, sshhashes);
|
||||
|
||||
/* mac_algorithms_server_to_client */
|
||||
buf_put_algolist(ses.writepayload, sshhashes);
|
||||
|
||||
/* compression_algorithms_client_to_server */
|
||||
buf_put_algolist(ses.writepayload, sshcompress);
|
||||
|
||||
/* compression_algorithms_server_to_client */
|
||||
buf_put_algolist(ses.writepayload, sshcompress);
|
||||
|
||||
/* languages_client_to_server */
|
||||
buf_putstring(ses.writepayload, "", 0);
|
||||
|
||||
/* languages_server_to_client */
|
||||
buf_putstring(ses.writepayload, "", 0);
|
||||
|
||||
/* first_kex_packet_follows - unimplemented for now */
|
||||
buf_putbyte(ses.writepayload, 0x00);
|
||||
|
||||
/* reserved unit32 */
|
||||
buf_putint(ses.writepayload, 0);
|
||||
|
||||
/* set up transmitted kex packet buffer for hashing.
|
||||
* This is freed after the end of the kex */
|
||||
ses.transkexinit = buf_newcopy(ses.writepayload);
|
||||
|
||||
encrypt_packet();
|
||||
ses.dataallowed = 0; /* don't send other packets during kex */
|
||||
|
||||
TRACE(("DATAALLOWED=0"))
|
||||
TRACE(("-> KEXINIT"))
|
||||
ses.kexstate.sentkexinit = 1;
|
||||
}
|
||||
|
||||
/* *** NOTE regarding (send|recv)_msg_newkeys ***
|
||||
* Changed by mihnea from the original kex.c to set dataallowed after a
|
||||
* completed key exchange, no matter the order in which it was performed.
|
||||
* This enables client mode without affecting server functionality.
|
||||
*/
|
||||
|
||||
/* Bring new keys into use after a key exchange, and let the client know*/
|
||||
void send_msg_newkeys() {
|
||||
|
||||
TRACE(("enter send_msg_newkeys"))
|
||||
|
||||
/* generate the kexinit request */
|
||||
CHECKCLEARTOWRITE();
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_NEWKEYS);
|
||||
encrypt_packet();
|
||||
|
||||
|
||||
/* set up our state */
|
||||
if (ses.kexstate.recvnewkeys) {
|
||||
TRACE(("while RECVNEWKEYS=1"))
|
||||
gen_new_keys();
|
||||
kexinitialise(); /* we've finished with this kex */
|
||||
TRACE((" -> DATAALLOWED=1"))
|
||||
ses.dataallowed = 1; /* we can send other packets again now */
|
||||
ses.kexstate.donefirstkex = 1;
|
||||
} else {
|
||||
ses.kexstate.sentnewkeys = 1;
|
||||
TRACE(("SENTNEWKEYS=1"))
|
||||
}
|
||||
|
||||
TRACE(("-> MSG_NEWKEYS"))
|
||||
TRACE(("leave send_msg_newkeys"))
|
||||
}
|
||||
|
||||
/* Bring the new keys into use after a key exchange */
|
||||
void recv_msg_newkeys() {
|
||||
|
||||
TRACE(("<- MSG_NEWKEYS"))
|
||||
TRACE(("enter recv_msg_newkeys"))
|
||||
|
||||
/* simply check if we've sent SSH_MSG_NEWKEYS, and if so,
|
||||
* switch to the new keys */
|
||||
if (ses.kexstate.sentnewkeys) {
|
||||
TRACE(("while SENTNEWKEYS=1"))
|
||||
gen_new_keys();
|
||||
kexinitialise(); /* we've finished with this kex */
|
||||
TRACE((" -> DATAALLOWED=1"))
|
||||
ses.dataallowed = 1; /* we can send other packets again now */
|
||||
ses.kexstate.donefirstkex = 1;
|
||||
} else {
|
||||
TRACE(("RECVNEWKEYS=1"))
|
||||
ses.kexstate.recvnewkeys = 1;
|
||||
}
|
||||
|
||||
TRACE(("leave recv_msg_newkeys"))
|
||||
}
|
||||
|
||||
|
||||
/* Set up the kex for the first time */
|
||||
void kexfirstinitialise() {
|
||||
|
||||
ses.kexstate.donefirstkex = 0;
|
||||
kexinitialise();
|
||||
}
|
||||
|
||||
/* Reset the kex state, ready for a new negotiation */
|
||||
static void kexinitialise() {
|
||||
|
||||
TRACE(("kexinitialise()"))
|
||||
|
||||
/* sent/recv'd MSG_KEXINIT */
|
||||
ses.kexstate.sentkexinit = 0;
|
||||
ses.kexstate.recvkexinit = 0;
|
||||
|
||||
/* sent/recv'd MSG_NEWKEYS */
|
||||
ses.kexstate.recvnewkeys = 0;
|
||||
ses.kexstate.sentnewkeys = 0;
|
||||
|
||||
/* first_packet_follows */
|
||||
ses.kexstate.firstfollows = 0;
|
||||
|
||||
ses.kexstate.datatrans = 0;
|
||||
ses.kexstate.datarecv = 0;
|
||||
|
||||
ses.kexstate.lastkextime = time(NULL);
|
||||
|
||||
}
|
||||
|
||||
/* Helper function for gen_new_keys, creates a hash. It makes a copy of the
|
||||
* already initialised hash_state hs, which should already have processed
|
||||
* the dh_K and hash, since these are common. X is the letter 'A', 'B' etc.
|
||||
* out must have at least min(SHA1_HASH_SIZE, outlen) bytes allocated.
|
||||
* The output will only be expanded once, as we are assured that
|
||||
* outlen <= 2*SHA1_HASH_SIZE for all known hashes.
|
||||
*
|
||||
* See Section 7.2 of rfc4253 (ssh transport) for details */
|
||||
static void hashkeys(unsigned char *out, int outlen,
|
||||
const hash_state * hs, const unsigned char X) {
|
||||
|
||||
hash_state hs2;
|
||||
unsigned char k2[SHA1_HASH_SIZE]; /* used to extending */
|
||||
|
||||
memcpy(&hs2, hs, sizeof(hash_state));
|
||||
sha1_process(&hs2, &X, 1);
|
||||
sha1_process(&hs2, ses.session_id, SHA1_HASH_SIZE);
|
||||
sha1_done(&hs2, out);
|
||||
if (SHA1_HASH_SIZE < outlen) {
|
||||
/* need to extend */
|
||||
memcpy(&hs2, hs, sizeof(hash_state));
|
||||
sha1_process(&hs2, out, SHA1_HASH_SIZE);
|
||||
sha1_done(&hs2, k2);
|
||||
memcpy(&out[SHA1_HASH_SIZE], k2, outlen - SHA1_HASH_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate the actual encryption/integrity keys, using the results of the
|
||||
* key exchange, as specified in section 5.2 of the IETF secsh-transport
|
||||
* draft. This occurs after the DH key-exchange.
|
||||
*
|
||||
* ses.newkeys is the new set of keys which are generated, these are only
|
||||
* taken into use after both sides have sent a newkeys message */
|
||||
|
||||
/* Originally from kex.c, generalized for cli/svr mode --mihnea */
|
||||
void gen_new_keys() {
|
||||
|
||||
unsigned char C2S_IV[MAX_IV_LEN];
|
||||
unsigned char C2S_key[MAX_KEY_LEN];
|
||||
unsigned char S2C_IV[MAX_IV_LEN];
|
||||
unsigned char S2C_key[MAX_KEY_LEN];
|
||||
/* unsigned char key[MAX_KEY_LEN]; */
|
||||
unsigned char *trans_IV, *trans_key, *recv_IV, *recv_key;
|
||||
|
||||
hash_state hs;
|
||||
unsigned int C2S_keysize, S2C_keysize;
|
||||
char mactransletter, macrecvletter; /* Client or server specific */
|
||||
int recv_cipher = 0, trans_cipher = 0;
|
||||
|
||||
TRACE(("enter gen_new_keys"))
|
||||
/* the dh_K and hash are the start of all hashes, we make use of that */
|
||||
|
||||
sha1_init(&hs);
|
||||
sha1_process_mp(&hs, ses.dh_K);
|
||||
mp_clear(ses.dh_K);
|
||||
m_free(ses.dh_K);
|
||||
sha1_process(&hs, ses.hash, SHA1_HASH_SIZE);
|
||||
m_burn(ses.hash, SHA1_HASH_SIZE);
|
||||
|
||||
if (IS_DROPBEAR_CLIENT) {
|
||||
trans_IV = C2S_IV;
|
||||
recv_IV = S2C_IV;
|
||||
trans_key = C2S_key;
|
||||
recv_key = S2C_key;
|
||||
C2S_keysize = ses.newkeys->trans_algo_crypt->keysize;
|
||||
S2C_keysize = ses.newkeys->recv_algo_crypt->keysize;
|
||||
mactransletter = 'E';
|
||||
macrecvletter = 'F';
|
||||
} else {
|
||||
trans_IV = S2C_IV;
|
||||
recv_IV = C2S_IV;
|
||||
trans_key = S2C_key;
|
||||
recv_key = C2S_key;
|
||||
C2S_keysize = ses.newkeys->recv_algo_crypt->keysize;
|
||||
S2C_keysize = ses.newkeys->trans_algo_crypt->keysize;
|
||||
mactransletter = 'F';
|
||||
macrecvletter = 'E';
|
||||
}
|
||||
|
||||
hashkeys(C2S_IV, SHA1_HASH_SIZE, &hs, 'A');
|
||||
hashkeys(S2C_IV, SHA1_HASH_SIZE, &hs, 'B');
|
||||
hashkeys(C2S_key, C2S_keysize, &hs, 'C');
|
||||
hashkeys(S2C_key, S2C_keysize, &hs, 'D');
|
||||
|
||||
recv_cipher = find_cipher(ses.newkeys->recv_algo_crypt->cipherdesc->name);
|
||||
if (recv_cipher < 0)
|
||||
dropbear_exit("crypto error");
|
||||
if (ses.newkeys->recv_crypt_mode->start(recv_cipher,
|
||||
recv_IV, recv_key,
|
||||
ses.newkeys->recv_algo_crypt->keysize, 0,
|
||||
&ses.newkeys->recv_cipher_state) != CRYPT_OK) {
|
||||
dropbear_exit("crypto error");
|
||||
}
|
||||
|
||||
trans_cipher = find_cipher(ses.newkeys->trans_algo_crypt->cipherdesc->name);
|
||||
if (trans_cipher < 0)
|
||||
dropbear_exit("crypto error");
|
||||
if (ses.newkeys->trans_crypt_mode->start(trans_cipher,
|
||||
trans_IV, trans_key,
|
||||
ses.newkeys->trans_algo_crypt->keysize, 0,
|
||||
&ses.newkeys->trans_cipher_state) != CRYPT_OK) {
|
||||
dropbear_exit("crypto error");
|
||||
}
|
||||
|
||||
/* MAC keys */
|
||||
hashkeys(ses.newkeys->transmackey,
|
||||
ses.newkeys->trans_algo_mac->keysize, &hs, mactransletter);
|
||||
hashkeys(ses.newkeys->recvmackey,
|
||||
ses.newkeys->recv_algo_mac->keysize, &hs, macrecvletter);
|
||||
|
||||
#ifndef DISABLE_ZLIB
|
||||
gen_new_zstreams();
|
||||
#endif
|
||||
|
||||
/* Switch over to the new keys */
|
||||
m_burn(ses.keys, sizeof(struct key_context));
|
||||
m_free(ses.keys);
|
||||
ses.keys = ses.newkeys;
|
||||
ses.newkeys = NULL;
|
||||
|
||||
TRACE(("leave gen_new_keys"))
|
||||
}
|
||||
|
||||
#ifndef DISABLE_ZLIB
|
||||
|
||||
int is_compress_trans() {
|
||||
return ses.keys->trans_algo_comp == DROPBEAR_COMP_ZLIB
|
||||
|| (ses.authstate.authdone
|
||||
&& ses.keys->trans_algo_comp == DROPBEAR_COMP_ZLIB_DELAY);
|
||||
}
|
||||
|
||||
int is_compress_recv() {
|
||||
return ses.keys->recv_algo_comp == DROPBEAR_COMP_ZLIB
|
||||
|| (ses.authstate.authdone
|
||||
&& ses.keys->recv_algo_comp == DROPBEAR_COMP_ZLIB_DELAY);
|
||||
}
|
||||
|
||||
/* Set up new zlib compression streams, close the old ones. Only
|
||||
* called from gen_new_keys() */
|
||||
static void gen_new_zstreams() {
|
||||
|
||||
/* create new zstreams */
|
||||
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;
|
||||
|
||||
if (inflateInit(ses.newkeys->recv_zstream) != Z_OK) {
|
||||
dropbear_exit("zlib error");
|
||||
}
|
||||
} else {
|
||||
ses.newkeys->recv_zstream = NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (deflateInit(ses.newkeys->trans_zstream, Z_DEFAULT_COMPRESSION)
|
||||
!= Z_OK) {
|
||||
dropbear_exit("zlib error");
|
||||
}
|
||||
} else {
|
||||
ses.newkeys->trans_zstream = NULL;
|
||||
}
|
||||
|
||||
/* clean up old keys */
|
||||
if (ses.keys->recv_zstream != NULL) {
|
||||
if (inflateEnd(ses.keys->recv_zstream) == Z_STREAM_ERROR) {
|
||||
/* Z_DATA_ERROR is ok, just means that stream isn't ended */
|
||||
dropbear_exit("crypto error");
|
||||
}
|
||||
m_free(ses.keys->recv_zstream);
|
||||
}
|
||||
if (ses.keys->trans_zstream != NULL) {
|
||||
if (deflateEnd(ses.keys->trans_zstream) == Z_STREAM_ERROR) {
|
||||
/* Z_DATA_ERROR is ok, just means that stream isn't ended */
|
||||
dropbear_exit("crypto error");
|
||||
}
|
||||
m_free(ses.keys->trans_zstream);
|
||||
}
|
||||
}
|
||||
#endif /* DISABLE_ZLIB */
|
||||
|
||||
|
||||
/* Executed upon receiving a kexinit message from the client to initiate
|
||||
* key exchange. If we haven't already done so, we send the list of our
|
||||
* preferred algorithms. The client's requested algorithms are processed,
|
||||
* and we calculate the first portion of the key-exchange-hash for used
|
||||
* later in the key exchange. No response is sent, as the client should
|
||||
* initiate the diffie-hellman key exchange */
|
||||
|
||||
/* Originally from kex.c, generalized for cli/svr mode --mihnea */
|
||||
/* Belongs in common_kex.c where it should be moved after review */
|
||||
void recv_msg_kexinit() {
|
||||
|
||||
unsigned int kexhashbuf_len = 0;
|
||||
unsigned int remote_ident_len = 0;
|
||||
unsigned int local_ident_len = 0;
|
||||
|
||||
TRACE(("<- KEXINIT"))
|
||||
TRACE(("enter recv_msg_kexinit"))
|
||||
|
||||
if (!ses.kexstate.sentkexinit) {
|
||||
/* we need to send a kex packet */
|
||||
send_msg_kexinit();
|
||||
TRACE(("continue recv_msg_kexinit: sent kexinit"))
|
||||
}
|
||||
|
||||
/* start the kex hash */
|
||||
local_ident_len = strlen(LOCAL_IDENT);
|
||||
remote_ident_len = strlen((char*)ses.remoteident);
|
||||
|
||||
kexhashbuf_len = local_ident_len + remote_ident_len
|
||||
+ ses.transkexinit->len + ses.payload->len
|
||||
+ KEXHASHBUF_MAX_INTS;
|
||||
|
||||
ses.kexhashbuf = buf_new(kexhashbuf_len);
|
||||
|
||||
if (IS_DROPBEAR_CLIENT) {
|
||||
|
||||
/* read the peer's choice of algos */
|
||||
read_kex_algos();
|
||||
|
||||
/* V_C, the client's version string (CR and NL excluded) */
|
||||
buf_putstring(ses.kexhashbuf,
|
||||
(unsigned char*)LOCAL_IDENT, local_ident_len);
|
||||
/* V_S, the server's version string (CR and NL excluded) */
|
||||
buf_putstring(ses.kexhashbuf, ses.remoteident, remote_ident_len);
|
||||
|
||||
/* I_C, the payload of the client's SSH_MSG_KEXINIT */
|
||||
buf_putstring(ses.kexhashbuf,
|
||||
ses.transkexinit->data, ses.transkexinit->len);
|
||||
/* I_S, the payload of the server's SSH_MSG_KEXINIT */
|
||||
buf_setpos(ses.payload, 0);
|
||||
buf_putstring(ses.kexhashbuf, ses.payload->data, ses.payload->len);
|
||||
|
||||
} else {
|
||||
/* SERVER */
|
||||
|
||||
/* read the peer's choice of algos */
|
||||
read_kex_algos();
|
||||
/* V_C, the client's version string (CR and NL excluded) */
|
||||
buf_putstring(ses.kexhashbuf, ses.remoteident, remote_ident_len);
|
||||
/* V_S, the server's version string (CR and NL excluded) */
|
||||
buf_putstring(ses.kexhashbuf,
|
||||
(unsigned char*)LOCAL_IDENT, local_ident_len);
|
||||
|
||||
/* I_C, the payload of the client's SSH_MSG_KEXINIT */
|
||||
buf_setpos(ses.payload, 0);
|
||||
buf_putstring(ses.kexhashbuf, ses.payload->data, ses.payload->len);
|
||||
|
||||
/* I_S, the payload of the server's SSH_MSG_KEXINIT */
|
||||
buf_putstring(ses.kexhashbuf,
|
||||
ses.transkexinit->data, ses.transkexinit->len);
|
||||
|
||||
ses.requirenext = SSH_MSG_KEXDH_INIT;
|
||||
}
|
||||
|
||||
buf_free(ses.transkexinit);
|
||||
ses.transkexinit = NULL;
|
||||
/* the rest of ses.kexhashbuf will be done after DH exchange */
|
||||
|
||||
ses.kexstate.recvkexinit = 1;
|
||||
|
||||
TRACE(("leave recv_msg_kexinit"))
|
||||
}
|
||||
|
||||
/* Initialises and generate one side of the diffie-hellman key exchange values.
|
||||
* See the ietf-secsh-transport draft, section 6, for details */
|
||||
/* dh_pub and dh_priv MUST be already initialised */
|
||||
void gen_kexdh_vals(mp_int *dh_pub, mp_int *dh_priv) {
|
||||
|
||||
DEF_MP_INT(dh_p);
|
||||
DEF_MP_INT(dh_q);
|
||||
DEF_MP_INT(dh_g);
|
||||
|
||||
TRACE(("enter send_msg_kexdh_reply"))
|
||||
|
||||
m_mp_init_multi(&dh_g, &dh_p, &dh_q, NULL);
|
||||
|
||||
/* read the prime and generator*/
|
||||
bytes_to_mp(&dh_p, (unsigned char*)dh_p_val, DH_P_LEN);
|
||||
|
||||
if (mp_set_int(&dh_g, DH_G_VAL) != MP_OKAY) {
|
||||
dropbear_exit("Diffie-Hellman error");
|
||||
}
|
||||
|
||||
/* calculate q = (p-1)/2 */
|
||||
/* dh_priv is just a temp var here */
|
||||
if (mp_sub_d(&dh_p, 1, dh_priv) != MP_OKAY) {
|
||||
dropbear_exit("Diffie-Hellman error");
|
||||
}
|
||||
if (mp_div_2(dh_priv, &dh_q) != MP_OKAY) {
|
||||
dropbear_exit("Diffie-Hellman error");
|
||||
}
|
||||
|
||||
/* Generate a private portion 0 < dh_priv < dh_q */
|
||||
gen_random_mpint(&dh_q, dh_priv);
|
||||
|
||||
/* f = g^y mod p */
|
||||
if (mp_exptmod(&dh_g, dh_priv, &dh_p, dh_pub) != MP_OKAY) {
|
||||
dropbear_exit("Diffie-Hellman error");
|
||||
}
|
||||
mp_clear_multi(&dh_g, &dh_p, &dh_q, NULL);
|
||||
}
|
||||
|
||||
/* This function is fairly common between client/server, with some substitution
|
||||
* of dh_e/dh_f etc. Hence these arguments:
|
||||
* dh_pub_us is 'e' for the client, 'f' for the server. dh_pub_them is
|
||||
* vice-versa. dh_priv is the x/y value corresponding to dh_pub_us */
|
||||
void kexdh_comb_key(mp_int *dh_pub_us, mp_int *dh_priv, mp_int *dh_pub_them,
|
||||
sign_key *hostkey) {
|
||||
|
||||
mp_int dh_p;
|
||||
mp_int *dh_e = NULL, *dh_f = NULL;
|
||||
hash_state hs;
|
||||
|
||||
/* read the prime and generator*/
|
||||
m_mp_init(&dh_p);
|
||||
bytes_to_mp(&dh_p, dh_p_val, DH_P_LEN);
|
||||
|
||||
/* Check that dh_pub_them (dh_e or dh_f) is in the range [1, p-1] */
|
||||
if (mp_cmp(dh_pub_them, &dh_p) != MP_LT
|
||||
|| mp_cmp_d(dh_pub_them, 0) != MP_GT) {
|
||||
dropbear_exit("Diffie-Hellman error");
|
||||
}
|
||||
|
||||
/* K = e^y mod p = f^x mod p */
|
||||
ses.dh_K = (mp_int*)m_malloc(sizeof(mp_int));
|
||||
m_mp_init(ses.dh_K);
|
||||
if (mp_exptmod(dh_pub_them, dh_priv, &dh_p, ses.dh_K) != MP_OKAY) {
|
||||
dropbear_exit("Diffie-Hellman error");
|
||||
}
|
||||
|
||||
/* clear no longer needed vars */
|
||||
mp_clear_multi(&dh_p, NULL);
|
||||
|
||||
/* From here on, the code needs to work with the _same_ vars on each side,
|
||||
* not vice-versaing for client/server */
|
||||
if (IS_DROPBEAR_CLIENT) {
|
||||
dh_e = dh_pub_us;
|
||||
dh_f = dh_pub_them;
|
||||
} else {
|
||||
dh_e = dh_pub_them;
|
||||
dh_f = dh_pub_us;
|
||||
}
|
||||
|
||||
/* Create the remainder of the hash buffer, to generate the exchange hash */
|
||||
/* K_S, the host key */
|
||||
buf_put_pub_key(ses.kexhashbuf, hostkey, ses.newkeys->algo_hostkey);
|
||||
/* e, exchange value sent by the client */
|
||||
buf_putmpint(ses.kexhashbuf, dh_e);
|
||||
/* f, exchange value sent by the server */
|
||||
buf_putmpint(ses.kexhashbuf, dh_f);
|
||||
/* K, the shared secret */
|
||||
buf_putmpint(ses.kexhashbuf, ses.dh_K);
|
||||
|
||||
/* calculate the hash H to sign */
|
||||
sha1_init(&hs);
|
||||
buf_setpos(ses.kexhashbuf, 0);
|
||||
sha1_process(&hs, buf_getptr(ses.kexhashbuf, ses.kexhashbuf->len),
|
||||
ses.kexhashbuf->len);
|
||||
sha1_done(&hs, ses.hash);
|
||||
|
||||
buf_burn(ses.kexhashbuf);
|
||||
buf_free(ses.kexhashbuf);
|
||||
ses.kexhashbuf = NULL;
|
||||
|
||||
/* first time around, we set the session_id to H */
|
||||
if (ses.session_id == NULL) {
|
||||
/* create the session_id, this never needs freeing */
|
||||
ses.session_id = (unsigned char*)m_malloc(SHA1_HASH_SIZE);
|
||||
memcpy(ses.session_id, ses.hash, SHA1_HASH_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
/* read the other side's algo list. buf_match_algo is a callback to match
|
||||
* algos for the client or server. */
|
||||
static void read_kex_algos() {
|
||||
|
||||
/* for asymmetry */
|
||||
algo_type * c2s_hash_algo = NULL;
|
||||
algo_type * s2c_hash_algo = NULL;
|
||||
algo_type * c2s_cipher_algo = NULL;
|
||||
algo_type * s2c_cipher_algo = NULL;
|
||||
algo_type * c2s_comp_algo = NULL;
|
||||
algo_type * s2c_comp_algo = NULL;
|
||||
/* the generic one */
|
||||
algo_type * algo = NULL;
|
||||
|
||||
/* which algo couldn't match */
|
||||
char * erralgo = NULL;
|
||||
|
||||
int goodguess = 0;
|
||||
int allgood = 1; /* we AND this with each goodguess and see if its still
|
||||
true after */
|
||||
|
||||
buf_incrpos(ses.payload, 16); /* start after the cookie */
|
||||
|
||||
ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
|
||||
|
||||
/* kex_algorithms */
|
||||
algo = ses.buf_match_algo(ses.payload, sshkex, &goodguess);
|
||||
allgood &= goodguess;
|
||||
if (algo == NULL) {
|
||||
erralgo = "kex";
|
||||
goto error;
|
||||
}
|
||||
TRACE(("kex algo %s", algo->name))
|
||||
ses.newkeys->algo_kex = algo->val;
|
||||
|
||||
/* server_host_key_algorithms */
|
||||
algo = ses.buf_match_algo(ses.payload, sshhostkey, &goodguess);
|
||||
allgood &= goodguess;
|
||||
if (algo == NULL) {
|
||||
erralgo = "hostkey";
|
||||
goto error;
|
||||
}
|
||||
TRACE(("hostkey algo %s", algo->name))
|
||||
ses.newkeys->algo_hostkey = algo->val;
|
||||
|
||||
/* encryption_algorithms_client_to_server */
|
||||
c2s_cipher_algo = ses.buf_match_algo(ses.payload, sshciphers, &goodguess);
|
||||
if (c2s_cipher_algo == NULL) {
|
||||
erralgo = "enc c->s";
|
||||
goto error;
|
||||
}
|
||||
TRACE(("enc c2s is %s", c2s_cipher_algo->name))
|
||||
|
||||
/* encryption_algorithms_server_to_client */
|
||||
s2c_cipher_algo = ses.buf_match_algo(ses.payload, sshciphers, &goodguess);
|
||||
if (s2c_cipher_algo == NULL) {
|
||||
erralgo = "enc s->c";
|
||||
goto error;
|
||||
}
|
||||
TRACE(("enc s2c is %s", s2c_cipher_algo->name))
|
||||
|
||||
/* mac_algorithms_client_to_server */
|
||||
c2s_hash_algo = ses.buf_match_algo(ses.payload, sshhashes, &goodguess);
|
||||
if (c2s_hash_algo == NULL) {
|
||||
erralgo = "mac c->s";
|
||||
goto error;
|
||||
}
|
||||
TRACE(("hash c2s is %s", c2s_hash_algo->name))
|
||||
|
||||
/* mac_algorithms_server_to_client */
|
||||
s2c_hash_algo = ses.buf_match_algo(ses.payload, sshhashes, &goodguess);
|
||||
if (s2c_hash_algo == NULL) {
|
||||
erralgo = "mac s->c";
|
||||
goto error;
|
||||
}
|
||||
TRACE(("hash s2c is %s", s2c_hash_algo->name))
|
||||
|
||||
/* compression_algorithms_client_to_server */
|
||||
c2s_comp_algo = ses.buf_match_algo(ses.payload, sshcompress, &goodguess);
|
||||
if (c2s_comp_algo == NULL) {
|
||||
erralgo = "comp c->s";
|
||||
goto error;
|
||||
}
|
||||
TRACE(("hash c2s is %s", c2s_comp_algo->name))
|
||||
|
||||
/* compression_algorithms_server_to_client */
|
||||
s2c_comp_algo = ses.buf_match_algo(ses.payload, sshcompress, &goodguess);
|
||||
if (s2c_comp_algo == NULL) {
|
||||
erralgo = "comp s->c";
|
||||
goto error;
|
||||
}
|
||||
TRACE(("hash s2c is %s", s2c_comp_algo->name))
|
||||
|
||||
/* languages_client_to_server */
|
||||
buf_eatstring(ses.payload);
|
||||
|
||||
/* languages_server_to_client */
|
||||
buf_eatstring(ses.payload);
|
||||
|
||||
/* first_kex_packet_follows */
|
||||
if (buf_getbool(ses.payload)) {
|
||||
ses.kexstate.firstfollows = 1;
|
||||
/* if the guess wasn't good, we ignore the packet sent */
|
||||
if (!allgood) {
|
||||
ses.ignorenext = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle the asymmetry */
|
||||
if (IS_DROPBEAR_CLIENT) {
|
||||
ses.newkeys->recv_algo_crypt =
|
||||
(struct dropbear_cipher*)s2c_cipher_algo->data;
|
||||
ses.newkeys->trans_algo_crypt =
|
||||
(struct dropbear_cipher*)c2s_cipher_algo->data;
|
||||
ses.newkeys->recv_crypt_mode =
|
||||
(struct dropbear_cipher_mode*)s2c_cipher_algo->mode;
|
||||
ses.newkeys->trans_crypt_mode =
|
||||
(struct dropbear_cipher_mode*)c2s_cipher_algo->mode;
|
||||
ses.newkeys->recv_algo_mac =
|
||||
(struct dropbear_hash*)s2c_hash_algo->data;
|
||||
ses.newkeys->trans_algo_mac =
|
||||
(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;
|
||||
} else {
|
||||
/* SERVER */
|
||||
ses.newkeys->recv_algo_crypt =
|
||||
(struct dropbear_cipher*)c2s_cipher_algo->data;
|
||||
ses.newkeys->trans_algo_crypt =
|
||||
(struct dropbear_cipher*)s2c_cipher_algo->data;
|
||||
ses.newkeys->recv_crypt_mode =
|
||||
(struct dropbear_cipher_mode*)c2s_cipher_algo->mode;
|
||||
ses.newkeys->trans_crypt_mode =
|
||||
(struct dropbear_cipher_mode*)s2c_cipher_algo->mode;
|
||||
ses.newkeys->recv_algo_mac =
|
||||
(struct dropbear_hash*)c2s_hash_algo->data;
|
||||
ses.newkeys->trans_algo_mac =
|
||||
(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;
|
||||
}
|
||||
|
||||
/* reserved for future extensions */
|
||||
buf_getint(ses.payload);
|
||||
return;
|
||||
|
||||
error:
|
||||
dropbear_exit("no matching algo %s", erralgo);
|
||||
}
|
||||
57
common-runopts.c
Normal file
57
common-runopts.c
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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 "runopts.h"
|
||||
#include "signkey.h"
|
||||
#include "buffer.h"
|
||||
#include "dbutil.h"
|
||||
#include "auth.h"
|
||||
|
||||
runopts opts; /* GLOBAL */
|
||||
|
||||
/* returns success or failure, and the keytype in *type. If we want
|
||||
* to restrict the type, type can contain a type to return */
|
||||
int readhostkey(const char * filename, sign_key * hostkey, int *type) {
|
||||
|
||||
int ret = DROPBEAR_FAILURE;
|
||||
buffer *buf;
|
||||
|
||||
buf = buf_new(MAX_PRIVKEY_SIZE);
|
||||
|
||||
if (buf_readfile(buf, filename) == DROPBEAR_FAILURE) {
|
||||
goto out;
|
||||
}
|
||||
buf_setpos(buf, 0);
|
||||
if (buf_get_priv_key(buf, hostkey, type) == DROPBEAR_FAILURE) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = DROPBEAR_SUCCESS;
|
||||
out:
|
||||
|
||||
buf_burn(buf);
|
||||
buf_free(buf);
|
||||
return ret;
|
||||
}
|
||||
458
common-session.c
Normal file
458
common-session.c
Normal file
@@ -0,0 +1,458 @@
|
||||
/*
|
||||
* 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 "session.h"
|
||||
#include "dbutil.h"
|
||||
#include "packet.h"
|
||||
#include "algo.h"
|
||||
#include "buffer.h"
|
||||
#include "dss.h"
|
||||
#include "ssh.h"
|
||||
#include "random.h"
|
||||
#include "kex.h"
|
||||
#include "channel.h"
|
||||
#include "atomicio.h"
|
||||
#include "runopts.h"
|
||||
|
||||
static void checktimeouts();
|
||||
static long select_timeout();
|
||||
static int ident_readln(int fd, char* buf, int count);
|
||||
|
||||
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, char* remotehost) {
|
||||
|
||||
TRACE(("enter session_init"))
|
||||
|
||||
ses.remotehost = remotehost;
|
||||
|
||||
ses.sock_in = sock_in;
|
||||
ses.sock_out = sock_out;
|
||||
ses.maxfd = MAX(sock_in, sock_out);
|
||||
|
||||
ses.connect_time = 0;
|
||||
ses.last_trx_packet_time = 0;
|
||||
ses.last_packet_time = 0;
|
||||
|
||||
if (pipe(ses.signal_pipe) < 0) {
|
||||
dropbear_exit("signal pipe failed");
|
||||
}
|
||||
setnonblocking(ses.signal_pipe[0]);
|
||||
setnonblocking(ses.signal_pipe[1]);
|
||||
|
||||
kexfirstinitialise(); /* initialise the kex state */
|
||||
|
||||
ses.writepayload = buf_new(TRANS_MAX_PAYLOAD_LEN);
|
||||
ses.transseq = 0;
|
||||
|
||||
ses.readbuf = NULL;
|
||||
ses.decryptreadbuf = NULL;
|
||||
ses.payload = NULL;
|
||||
ses.recvseq = 0;
|
||||
|
||||
initqueue(&ses.writequeue);
|
||||
|
||||
ses.requirenext = SSH_MSG_KEXINIT;
|
||||
ses.dataallowed = 1; /* we can send data until we actually
|
||||
send the SSH_MSG_KEXINIT */
|
||||
ses.ignorenext = 0;
|
||||
ses.lastpacket = 0;
|
||||
ses.reply_queue_head = NULL;
|
||||
ses.reply_queue_tail = NULL;
|
||||
|
||||
/* set all the algos to none */
|
||||
ses.keys = (struct key_context*)m_malloc(sizeof(struct key_context));
|
||||
ses.newkeys = NULL;
|
||||
ses.keys->recv_algo_crypt = &dropbear_nocipher;
|
||||
ses.keys->trans_algo_crypt = &dropbear_nocipher;
|
||||
ses.keys->recv_crypt_mode = &dropbear_mode_none;
|
||||
ses.keys->trans_crypt_mode = &dropbear_mode_none;
|
||||
|
||||
ses.keys->recv_algo_mac = &dropbear_nohash;
|
||||
ses.keys->trans_algo_mac = &dropbear_nohash;
|
||||
|
||||
ses.keys->algo_kex = -1;
|
||||
ses.keys->algo_hostkey = -1;
|
||||
ses.keys->recv_algo_comp = DROPBEAR_COMP_NONE;
|
||||
ses.keys->trans_algo_comp = DROPBEAR_COMP_NONE;
|
||||
|
||||
#ifndef DISABLE_ZLIB
|
||||
ses.keys->recv_zstream = NULL;
|
||||
ses.keys->trans_zstream = NULL;
|
||||
#endif
|
||||
|
||||
/* key exchange buffers */
|
||||
ses.session_id = NULL;
|
||||
ses.kexhashbuf = NULL;
|
||||
ses.transkexinit = NULL;
|
||||
ses.dh_K = NULL;
|
||||
ses.remoteident = NULL;
|
||||
|
||||
ses.chantypes = NULL;
|
||||
|
||||
ses.allowprivport = 0;
|
||||
|
||||
TRACE(("leave session_init"))
|
||||
}
|
||||
|
||||
void session_loop(void(*loophandler)()) {
|
||||
|
||||
fd_set readfd, writefd;
|
||||
struct timeval timeout;
|
||||
int val;
|
||||
|
||||
/* main loop, select()s for all sockets in use */
|
||||
for(;;) {
|
||||
|
||||
timeout.tv_sec = select_timeout();
|
||||
timeout.tv_usec = 0;
|
||||
FD_ZERO(&writefd);
|
||||
FD_ZERO(&readfd);
|
||||
dropbear_assert(ses.payload == NULL);
|
||||
if (ses.sock_in != -1) {
|
||||
FD_SET(ses.sock_in, &readfd);
|
||||
}
|
||||
if (ses.sock_out != -1 && !isempty(&ses.writequeue)) {
|
||||
FD_SET(ses.sock_out, &writefd);
|
||||
}
|
||||
|
||||
/* We get woken up when signal handlers write to this pipe.
|
||||
SIGCHLD in svr-chansession is the only one currently. */
|
||||
FD_SET(ses.signal_pipe[0], &readfd);
|
||||
|
||||
/* set up for channels which require reading/writing */
|
||||
if (ses.dataallowed) {
|
||||
setchannelfds(&readfd, &writefd);
|
||||
}
|
||||
val = select(ses.maxfd+1, &readfd, &writefd, NULL, &timeout);
|
||||
|
||||
if (exitflag) {
|
||||
dropbear_exit("Terminated by signal");
|
||||
}
|
||||
|
||||
if (val < 0 && errno != EINTR) {
|
||||
dropbear_exit("Error in select");
|
||||
}
|
||||
|
||||
if (val <= 0) {
|
||||
/* If we were interrupted or the select timed out, we still
|
||||
* 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);
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
if (FD_ISSET(ses.signal_pipe[0], &readfd)) {
|
||||
char x;
|
||||
while (read(ses.signal_pipe[0], &x, 1) > 0) {}
|
||||
}
|
||||
|
||||
/* check for auth timeout, rekeying required etc */
|
||||
checktimeouts();
|
||||
|
||||
/* process session socket's incoming/outgoing data */
|
||||
if (ses.sock_out != -1) {
|
||||
if (FD_ISSET(ses.sock_out, &writefd) && !isempty(&ses.writequeue)) {
|
||||
write_packet();
|
||||
}
|
||||
}
|
||||
|
||||
if (ses.sock_in != -1) {
|
||||
if (FD_ISSET(ses.sock_in, &readfd)) {
|
||||
read_packet();
|
||||
}
|
||||
|
||||
/* Process the decrypted packet. After this, the read buffer
|
||||
* will be ready for a new packet */
|
||||
if (ses.payload != NULL) {
|
||||
process_packet();
|
||||
}
|
||||
}
|
||||
|
||||
/* if required, flush out any queued reply packets that
|
||||
were being held up during a KEX */
|
||||
maybe_flush_reply_queue();
|
||||
|
||||
/* process pipes etc for the channels, ses.dataallowed == 0
|
||||
* during rekeying ) */
|
||||
if (ses.dataallowed) {
|
||||
channelio(&readfd, &writefd);
|
||||
}
|
||||
|
||||
if (loophandler) {
|
||||
loophandler();
|
||||
}
|
||||
|
||||
} /* for(;;) */
|
||||
|
||||
/* Not reached */
|
||||
}
|
||||
|
||||
/* clean up a session on exit */
|
||||
void common_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"))
|
||||
return;
|
||||
}
|
||||
|
||||
m_free(ses.session_id);
|
||||
m_burn(ses.keys, sizeof(struct key_context));
|
||||
m_free(ses.keys);
|
||||
|
||||
chancleanup();
|
||||
|
||||
TRACE(("leave session_cleanup"))
|
||||
}
|
||||
|
||||
|
||||
void session_identification() {
|
||||
|
||||
/* max length of 255 chars */
|
||||
char linebuf[256];
|
||||
int len = 0;
|
||||
char done = 0;
|
||||
int i;
|
||||
|
||||
/* write our version string, this blocks */
|
||||
if (atomicio(write, ses.sock_out, LOCAL_IDENT "\r\n",
|
||||
strlen(LOCAL_IDENT "\r\n")) == DROPBEAR_FAILURE) {
|
||||
ses.remoteclosed();
|
||||
}
|
||||
|
||||
/* If they send more than 50 lines, something is wrong */
|
||||
for (i = 0; i < 50; i++) {
|
||||
len = ident_readln(ses.sock_in, linebuf, sizeof(linebuf));
|
||||
|
||||
if (len < 0 && errno != EINTR) {
|
||||
/* It failed */
|
||||
break;
|
||||
}
|
||||
|
||||
if (len >= 4 && memcmp(linebuf, "SSH-", 4) == 0) {
|
||||
/* start of line matches */
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!done) {
|
||||
TRACE(("err: %s for '%s'\n", strerror(errno), linebuf))
|
||||
ses.remoteclosed();
|
||||
} else {
|
||||
/* linebuf is already null terminated */
|
||||
ses.remoteident = m_malloc(len);
|
||||
memcpy(ses.remoteident, linebuf, len);
|
||||
}
|
||||
|
||||
/* Shall assume that 2.x will be backwards compatible. */
|
||||
if (strncmp(ses.remoteident, "SSH-2.", 6) != 0
|
||||
&& strncmp(ses.remoteident, "SSH-1.99-", 9) != 0) {
|
||||
dropbear_exit("Incompatible remote version '%s'", ses.remoteident);
|
||||
}
|
||||
|
||||
TRACE(("remoteident: %s", ses.remoteident))
|
||||
|
||||
}
|
||||
|
||||
/* returns the length including null-terminating zero on success,
|
||||
* or -1 on failure */
|
||||
static int ident_readln(int fd, char* buf, int count) {
|
||||
|
||||
char in;
|
||||
int pos = 0;
|
||||
int num = 0;
|
||||
fd_set fds;
|
||||
struct timeval timeout;
|
||||
|
||||
TRACE(("enter ident_readln"))
|
||||
|
||||
if (count < 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
FD_ZERO(&fds);
|
||||
|
||||
/* select since it's a non-blocking fd */
|
||||
|
||||
/* leave space to null-terminate */
|
||||
while (pos < count-1) {
|
||||
|
||||
FD_SET(fd, &fds);
|
||||
|
||||
timeout.tv_sec = 1;
|
||||
timeout.tv_usec = 0;
|
||||
if (select(fd+1, &fds, NULL, NULL, &timeout) < 0) {
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
TRACE(("leave ident_readln: select error"))
|
||||
return -1;
|
||||
}
|
||||
|
||||
checktimeouts();
|
||||
|
||||
/* Have to go one byte at a time, since we don't want to read past
|
||||
* the end, and have to somehow shove bytes back into the normal
|
||||
* packet reader */
|
||||
if (FD_ISSET(fd, &fds)) {
|
||||
num = read(fd, &in, 1);
|
||||
/* a "\n" is a newline, "\r" we want to read in and keep going
|
||||
* so that it won't be read as part of the next line */
|
||||
if (num < 0) {
|
||||
/* error */
|
||||
if (errno == EINTR) {
|
||||
continue; /* not a real error */
|
||||
}
|
||||
TRACE(("leave ident_readln: read error"))
|
||||
return -1;
|
||||
}
|
||||
if (num == 0) {
|
||||
/* EOF */
|
||||
TRACE(("leave ident_readln: EOF"))
|
||||
return -1;
|
||||
}
|
||||
if (in == '\n') {
|
||||
/* end of ident string */
|
||||
break;
|
||||
}
|
||||
/* we don't want to include '\r's */
|
||||
if (in != '\r') {
|
||||
buf[pos] = in;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buf[pos] = '\0';
|
||||
TRACE(("leave ident_readln: return %d", pos+1))
|
||||
return pos+1;
|
||||
}
|
||||
|
||||
void send_msg_ignore() {
|
||||
CHECKCLEARTOWRITE();
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_IGNORE);
|
||||
buf_putstring(ses.writepayload, "", 0);
|
||||
encrypt_packet();
|
||||
}
|
||||
|
||||
/* Check all timeouts which are required. Currently these are the time for
|
||||
* user authentication, and the automatic rekeying. */
|
||||
static void checktimeouts() {
|
||||
|
||||
time_t now;
|
||||
|
||||
now = time(NULL);
|
||||
|
||||
if (ses.connect_time != 0 && now - ses.connect_time >= AUTH_TIMEOUT) {
|
||||
dropbear_close("Timeout before auth");
|
||||
}
|
||||
|
||||
/* we can't rekey if we haven't done remote ident exchange yet */
|
||||
if (ses.remoteident == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ses.kexstate.sentkexinit
|
||||
&& (now - ses.kexstate.lastkextime >= KEX_REKEY_TIMEOUT
|
||||
|| ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)) {
|
||||
TRACE(("rekeying after timeout or max data reached"))
|
||||
send_msg_kexinit();
|
||||
}
|
||||
|
||||
if (opts.keepalive_secs > 0
|
||||
&& now - ses.last_trx_packet_time >= opts.keepalive_secs) {
|
||||
send_msg_ignore();
|
||||
}
|
||||
|
||||
if (opts.idle_timeout_secs > 0 && ses.last_packet_time > 0
|
||||
&& now - ses.last_packet_time >= opts.idle_timeout_secs) {
|
||||
dropbear_close("Idle timeout");
|
||||
}
|
||||
}
|
||||
|
||||
static long select_timeout() {
|
||||
/* determine the minimum timeout that might be required, so
|
||||
as to avoid waking when unneccessary */
|
||||
long ret = LONG_MAX;
|
||||
if (KEX_REKEY_TIMEOUT > 0)
|
||||
ret = MIN(KEX_REKEY_TIMEOUT, ret);
|
||||
if (AUTH_TIMEOUT > 0)
|
||||
ret = MIN(AUTH_TIMEOUT, ret);
|
||||
if (opts.keepalive_secs > 0)
|
||||
ret = MIN(opts.keepalive_secs, ret);
|
||||
if (opts.idle_timeout_secs > 0)
|
||||
ret = MIN(opts.idle_timeout_secs, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char* get_user_shell() {
|
||||
/* an empty shell should be interpreted as "/bin/sh" */
|
||||
if (ses.authstate.pw_shell[0] == '\0') {
|
||||
return "/bin/sh";
|
||||
} else {
|
||||
return ses.authstate.pw_shell;
|
||||
}
|
||||
}
|
||||
void fill_passwd(const char* username) {
|
||||
struct passwd *pw = NULL;
|
||||
if (ses.authstate.pw_name)
|
||||
m_free(ses.authstate.pw_name);
|
||||
if (ses.authstate.pw_dir)
|
||||
m_free(ses.authstate.pw_dir);
|
||||
if (ses.authstate.pw_shell)
|
||||
m_free(ses.authstate.pw_shell);
|
||||
if (ses.authstate.pw_passwd)
|
||||
m_free(ses.authstate.pw_passwd);
|
||||
|
||||
pw = getpwnam(username);
|
||||
if (!pw) {
|
||||
return;
|
||||
}
|
||||
ses.authstate.pw_uid = pw->pw_uid;
|
||||
ses.authstate.pw_gid = pw->pw_gid;
|
||||
ses.authstate.pw_name = m_strdup(pw->pw_name);
|
||||
ses.authstate.pw_dir = m_strdup(pw->pw_dir);
|
||||
ses.authstate.pw_shell = m_strdup(pw->pw_shell);
|
||||
ses.authstate.pw_passwd = m_strdup(pw->pw_passwd);
|
||||
}
|
||||
|
||||
281
compat.c
Normal file
281
compat.c
Normal file
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* strlcat() is copyright as follows:
|
||||
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* daemon() and getusershell() is copyright as follows:
|
||||
*
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Modifications for Dropbear to getusershell() are by Paul Marinceu
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#ifndef HAVE_GETUSERSHELL
|
||||
static char **curshell, **shells, *strings;
|
||||
static char **initshells();
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
/* Implemented by matt as specified in freebsd 4.7 manpage.
|
||||
* We don't require great speed, is simply for use with sshpty code */
|
||||
size_t strlcpy(char *dst, const char *src, size_t size) {
|
||||
|
||||
size_t i;
|
||||
|
||||
/* this is undefined, though size==0 -> return 0 */
|
||||
if (size < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < size-1; i++) {
|
||||
if (src[i] == '\0') {
|
||||
break;
|
||||
} else {
|
||||
dst[i] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
dst[i] = '\0';
|
||||
return strlen(src);
|
||||
|
||||
}
|
||||
#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 $"
|
||||
*
|
||||
* 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
|
||||
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
|
||||
* 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;
|
||||
{
|
||||
register char *d = dst;
|
||||
register const char *s = src;
|
||||
register size_t n = siz;
|
||||
size_t dlen;
|
||||
|
||||
/* Find the end of dst and adjust bytes left but don't go past end */
|
||||
while (n-- != 0 && *d != '\0')
|
||||
d++;
|
||||
dlen = d - dst;
|
||||
n = siz - dlen;
|
||||
|
||||
if (n == 0)
|
||||
return(dlen + strlen(s));
|
||||
while (*s != '\0') {
|
||||
if (n != 1) {
|
||||
*d++ = *s;
|
||||
n--;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
*d = '\0';
|
||||
|
||||
return(dlen + (s - src)); /* count does not include NUL */
|
||||
}
|
||||
#endif /* HAVE_STRLCAT */
|
||||
|
||||
#ifndef HAVE_DAEMON
|
||||
/* From NetBSD - daemonise a process */
|
||||
|
||||
int daemon(int nochdir, int noclose) {
|
||||
|
||||
int fd;
|
||||
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
return (-1);
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
if (setsid() == -1)
|
||||
return -1;
|
||||
|
||||
if (!nochdir)
|
||||
(void)chdir("/");
|
||||
|
||||
if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
|
||||
(void)dup2(fd, STDIN_FILENO);
|
||||
(void)dup2(fd, STDOUT_FILENO);
|
||||
(void)dup2(fd, STDERR_FILENO);
|
||||
if (fd > STDERR_FILENO)
|
||||
(void)close(fd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_DAEMON */
|
||||
|
||||
#ifndef HAVE_BASENAME
|
||||
|
||||
char *basename(const char *path) {
|
||||
|
||||
char *foo = strrchr(path, '/');
|
||||
return ++foo;
|
||||
}
|
||||
|
||||
#endif /* HAVE_BASENAME */
|
||||
|
||||
#ifndef HAVE_GETUSERSHELL
|
||||
|
||||
/*
|
||||
* Get a list of shells from /etc/shells, if it exists.
|
||||
*/
|
||||
char * getusershell() {
|
||||
char *ret;
|
||||
|
||||
if (curshell == NULL)
|
||||
curshell = initshells();
|
||||
ret = *curshell;
|
||||
if (ret != NULL)
|
||||
curshell++;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void endusershell() {
|
||||
|
||||
if (shells != NULL)
|
||||
free(shells);
|
||||
shells = NULL;
|
||||
if (strings != NULL)
|
||||
free(strings);
|
||||
strings = NULL;
|
||||
curshell = NULL;
|
||||
}
|
||||
|
||||
void setusershell() {
|
||||
curshell = initshells();
|
||||
}
|
||||
|
||||
static char **initshells() {
|
||||
/* don't touch this list. */
|
||||
const char *okshells[] = { "/bin/sh", "/bin/csh", NULL };
|
||||
register char **sp, *cp;
|
||||
register FILE *fp;
|
||||
struct stat statb;
|
||||
int flen;
|
||||
|
||||
if (shells != NULL)
|
||||
free(shells);
|
||||
shells = NULL;
|
||||
if (strings != NULL)
|
||||
free(strings);
|
||||
strings = NULL;
|
||||
if ((fp = fopen("/etc/shells", "rc")) == NULL)
|
||||
return (char **) okshells;
|
||||
if (fstat(fileno(fp), &statb) == -1) {
|
||||
(void)fclose(fp);
|
||||
return (char **) okshells;
|
||||
}
|
||||
if ((strings = malloc((u_int)statb.st_size + 1)) == NULL) {
|
||||
(void)fclose(fp);
|
||||
return (char **) okshells;
|
||||
}
|
||||
shells = calloc((unsigned)statb.st_size / 3, sizeof (char *));
|
||||
if (shells == NULL) {
|
||||
(void)fclose(fp);
|
||||
free(strings);
|
||||
strings = NULL;
|
||||
return (char **) okshells;
|
||||
}
|
||||
sp = shells;
|
||||
cp = strings;
|
||||
flen = statb.st_size;
|
||||
while (fgets(cp, flen - (cp - strings), fp) != NULL) {
|
||||
while (*cp != '#' && *cp != '/' && *cp != '\0')
|
||||
cp++;
|
||||
if (*cp == '#' || *cp == '\0')
|
||||
continue;
|
||||
*sp++ = cp;
|
||||
while (!isspace(*cp) && *cp != '#' && *cp != '\0')
|
||||
cp++;
|
||||
*cp++ = '\0';
|
||||
}
|
||||
*sp = NULL;
|
||||
(void)fclose(fp);
|
||||
return (shells);
|
||||
}
|
||||
|
||||
#endif /* HAVE_GETUSERSHELL */
|
||||
56
compat.h
Normal file
56
compat.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Dropbear SSH
|
||||
*
|
||||
* 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 _COMPAT_H_
|
||||
#define _COMPAT_H_
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
size_t strlcpy(char *dst, const char *src, size_t size);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRLCAT
|
||||
size_t strlcat(char *dst, const char *src, size_t siz);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_DAEMON
|
||||
int daemon(int nochdir, int noclose);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_BASENAME
|
||||
char *basename(const char* path);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETUSERSHELL
|
||||
char *getusershell();
|
||||
void setusershell();
|
||||
void endusershell();
|
||||
#endif
|
||||
|
||||
#ifndef _PATH_DEVNULL
|
||||
#define _PATH_DEVNULL "/dev/null"
|
||||
#endif
|
||||
|
||||
#endif /* _COMPAT_H_ */
|
||||
1513
config.guess
vendored
Normal file
1513
config.guess
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1622
config.sub
vendored
Normal file
1622
config.sub
vendored
Normal file
File diff suppressed because it is too large
Load Diff
674
configure.in
Normal file
674
configure.in
Normal file
@@ -0,0 +1,674 @@
|
||||
# -*- Autoconf -*-
|
||||
# Process this file with autoconf and autoheader to produce a configure script.
|
||||
|
||||
# This Autoconf file was cobbled from various locations. In particular, a bunch
|
||||
# of the platform checks have been taken straight from OpenSSH's configure.ac
|
||||
# Huge thanks to them for dealing with the horrible platform-specifics :)
|
||||
|
||||
AC_PREREQ(2.50)
|
||||
AC_INIT(buffer.c)
|
||||
|
||||
OLDCFLAGS=$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_MSG_NOTICE(No \$CFLAGS set... using "-Os -W -Wall" for GCC)
|
||||
CFLAGS="-Os -W -Wall"
|
||||
fi
|
||||
|
||||
# large file support is useful for scp
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
# Host specific options
|
||||
# this isn't a definitive list of hosts, they are just added as required
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
case "$host" in
|
||||
|
||||
*-*-linux*)
|
||||
no_ptmx_check=1
|
||||
;;
|
||||
|
||||
*-*-solaris*)
|
||||
CFLAGS="$CFLAGS -I/usr/local/include"
|
||||
LDFLAGS="$LDFLAGS -L/usr/local/lib -R/usr/local/lib"
|
||||
conf_lastlog_location="/var/adm/lastlog"
|
||||
AC_MSG_CHECKING(for obsolete utmp and wtmp in solaris2.x)
|
||||
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)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AC_CHECK_LIB(socket, socket, LIBS="$LIBS -lsocket")
|
||||
AC_CHECK_LIB(nsl, yp_match, LIBS="$LIBS -lnsl")
|
||||
;;
|
||||
|
||||
*-*-aix*)
|
||||
AC_DEFINE(AIX,,Using AIX)
|
||||
# OpenSSH thinks it's broken. If it isn't, let me know.
|
||||
AC_DEFINE(BROKEN_GETADDRINFO,,Broken getaddrinfo)
|
||||
;;
|
||||
|
||||
*-*-hpux*)
|
||||
LIBS="$LIBS -lsec"
|
||||
# It's probably broken.
|
||||
AC_DEFINE(BROKEN_GETADDRINFO,,Broken getaddrinfo)
|
||||
;;
|
||||
*-dec-osf*)
|
||||
AC_DEFINE(BROKEN_GETADDRINFO,,Broken getaddrinfo)
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_CHECK_TOOL(AR, ar, :)
|
||||
AC_CHECK_TOOL(RANLIB, ranlib, :)
|
||||
AC_CHECK_TOOL(STRIP, strip, :)
|
||||
AC_CHECK_TOOL(INSTALL, install, :)
|
||||
|
||||
dnl Can't use login() or logout() with uclibc
|
||||
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.])
|
||||
],,,)
|
||||
|
||||
# Checks for libraries.
|
||||
AC_CHECK_LIB(crypt, crypt, CRYPTLIB="-lcrypt")
|
||||
AC_SUBST(CRYPTLIB)
|
||||
|
||||
# Check if zlib is needed
|
||||
AC_ARG_WITH(zlib,
|
||||
[ --with-zlib=PATH Use zlib in PATH],
|
||||
[
|
||||
# option is given
|
||||
if test -d "$withval/lib"; then
|
||||
LDFLAGS="-L${withval}/lib ${LDFLAGS}"
|
||||
else
|
||||
LDFLAGS="-L${withval} ${LDFLAGS}"
|
||||
fi
|
||||
if test -d "$withval/include"; then
|
||||
CPPFLAGS="-I${withval}/include ${CPPFLAGS}"
|
||||
else
|
||||
CPPFLAGS="-I${withval} ${CPPFLAGS}"
|
||||
fi
|
||||
]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE(zlib,
|
||||
[ --disable-zlib Don't include zlib support],
|
||||
[
|
||||
if test "x$enableval" = "xno"; then
|
||||
AC_DEFINE(DISABLE_ZLIB,, Use zlib)
|
||||
AC_MSG_NOTICE(Disabling zlib)
|
||||
else
|
||||
AC_CHECK_LIB(z, deflate, , AC_MSG_ERROR([*** zlib missing - install first or check config.log ***]))
|
||||
AC_MSG_NOTICE(Enabling zlib)
|
||||
fi
|
||||
],
|
||||
[
|
||||
# if not disabled, check for zlib
|
||||
AC_CHECK_LIB(z, deflate, , AC_MSG_ERROR([*** zlib missing - install first or check config.log ***]))
|
||||
AC_MSG_NOTICE(Enabling zlib)
|
||||
]
|
||||
)
|
||||
|
||||
# Check if pam is needed
|
||||
AC_ARG_WITH(pam,
|
||||
[ --with-pam=PATH Use pam in PATH],
|
||||
[
|
||||
# option is given
|
||||
if test -d "$withval/lib"; then
|
||||
LDFLAGS="-L${withval}/lib ${LDFLAGS}"
|
||||
else
|
||||
LDFLAGS="-L${withval} ${LDFLAGS}"
|
||||
fi
|
||||
if test -d "$withval/include"; then
|
||||
CPPFLAGS="-I${withval}/include ${CPPFLAGS}"
|
||||
else
|
||||
CPPFLAGS="-I${withval} ${CPPFLAGS}"
|
||||
fi
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
AC_ARG_ENABLE(pam,
|
||||
[ --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)
|
||||
else
|
||||
AC_DEFINE(DISABLE_PAM,, Use PAM)
|
||||
AC_MSG_NOTICE(Disabling PAM)
|
||||
fi
|
||||
],
|
||||
[
|
||||
# disable it by default
|
||||
AC_DEFINE(DISABLE_PAM,, Use PAM)
|
||||
AC_MSG_NOTICE(Disabling PAM)
|
||||
]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE(openpty,
|
||||
[ --disable-openpty Don't use openpty, use alternative method],
|
||||
[
|
||||
if test "x$enableval" = "xno"; then
|
||||
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)])
|
||||
fi
|
||||
],
|
||||
[
|
||||
AC_MSG_NOTICE(Using openpty if available)
|
||||
AC_SEARCH_LIBS(openpty, util, [AC_DEFINE(HAVE_OPENPTY)])
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
AC_ARG_ENABLE(syslog,
|
||||
[ --disable-syslog Don't include syslog support],
|
||||
[
|
||||
if test "x$enableval" = "xno"; then
|
||||
AC_DEFINE(DISABLE_SYSLOG,, Using syslog)
|
||||
AC_MSG_NOTICE(Disabling syslog)
|
||||
else
|
||||
AC_MSG_NOTICE(Enabling syslog)
|
||||
fi
|
||||
],
|
||||
[
|
||||
AC_MSG_NOTICE(Enabling syslog)
|
||||
]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE(shadow,
|
||||
[ --disable-shadow Don't use shadow passwords (if available)],
|
||||
[
|
||||
if test "x$enableval" = "xno"; then
|
||||
AC_MSG_NOTICE(Not using shadow passwords)
|
||||
else
|
||||
AC_CHECK_HEADERS([shadow.h])
|
||||
AC_MSG_NOTICE(Using shadow passwords if available)
|
||||
fi
|
||||
],
|
||||
[
|
||||
AC_CHECK_HEADERS([shadow.h])
|
||||
AC_MSG_NOTICE(Using shadow passwords if available)
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
# 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])
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_C_CONST
|
||||
AC_TYPE_UID_T
|
||||
AC_TYPE_MODE_T
|
||||
AC_TYPE_PID_T
|
||||
AC_TYPE_SIZE_T
|
||||
AC_HEADER_TIME
|
||||
|
||||
AC_CHECK_TYPES([uint16_t, u_int16_t, struct sockaddr_storage])
|
||||
AC_CHECK_TYPE([socklen_t], ,[
|
||||
AC_MSG_CHECKING([for socklen_t equivalent])
|
||||
AC_CACHE_VAL([curl_cv_socklen_t_equiv],
|
||||
[
|
||||
# Systems have either "struct sockaddr *" or
|
||||
# "void *" as the second argument to getpeername
|
||||
curl_cv_socklen_t_equiv=
|
||||
for arg2 in "struct sockaddr" void; do
|
||||
for t in int size_t unsigned long "unsigned long"; do
|
||||
AC_TRY_COMPILE([
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
int getpeername (int, $arg2 *, $t *);
|
||||
],[
|
||||
$t len;
|
||||
getpeername(0,0,&len);
|
||||
],[
|
||||
curl_cv_socklen_t_equiv="$t"
|
||||
break
|
||||
])
|
||||
done
|
||||
done
|
||||
|
||||
if test "x$curl_cv_socklen_t_equiv" = x; then
|
||||
AC_MSG_ERROR([Cannot find a type to use in place of socklen_t])
|
||||
fi
|
||||
])
|
||||
AC_MSG_RESULT($curl_cv_socklen_t_equiv)
|
||||
AC_DEFINE_UNQUOTED(socklen_t, $curl_cv_socklen_t_equiv,
|
||||
[type to use in place of socklen_t if not defined])],
|
||||
[#include <sys/types.h>
|
||||
#include <sys/socket.h>])
|
||||
|
||||
# for the fake-rfc2553 stuff - straight from OpenSSH
|
||||
|
||||
AC_CACHE_CHECK([for struct sockaddr_storage], ac_cv_have_struct_sockaddr_storage, [
|
||||
AC_TRY_COMPILE(
|
||||
[
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
],
|
||||
[ struct sockaddr_storage s; ],
|
||||
[ ac_cv_have_struct_sockaddr_storage="yes" ],
|
||||
[ ac_cv_have_struct_sockaddr_storage="no" ]
|
||||
)
|
||||
])
|
||||
if test "x$ac_cv_have_struct_sockaddr_storage" = "xyes" ; then
|
||||
AC_DEFINE(HAVE_STRUCT_SOCKADDR_STORAGE)
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for struct sockaddr_in6], ac_cv_have_struct_sockaddr_in6, [
|
||||
AC_TRY_COMPILE(
|
||||
[
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
],
|
||||
[ struct sockaddr_in6 s; s.sin6_family = 0; ],
|
||||
[ ac_cv_have_struct_sockaddr_in6="yes" ],
|
||||
[ ac_cv_have_struct_sockaddr_in6="no" ]
|
||||
)
|
||||
])
|
||||
if test "x$ac_cv_have_struct_sockaddr_in6" = "xyes" ; then
|
||||
AC_DEFINE(HAVE_STRUCT_SOCKADDR_IN6,,Have struct sockaddr_in6)
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for struct in6_addr], ac_cv_have_struct_in6_addr, [
|
||||
AC_TRY_COMPILE(
|
||||
[
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
],
|
||||
[ struct in6_addr s; s.s6_addr[0] = 0; ],
|
||||
[ ac_cv_have_struct_in6_addr="yes" ],
|
||||
[ ac_cv_have_struct_in6_addr="no" ]
|
||||
)
|
||||
])
|
||||
if test "x$ac_cv_have_struct_in6_addr" = "xyes" ; then
|
||||
AC_DEFINE(HAVE_STRUCT_IN6_ADDR,,Have struct in6_addr)
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for struct addrinfo], ac_cv_have_struct_addrinfo, [
|
||||
AC_TRY_COMPILE(
|
||||
[
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
],
|
||||
[ struct addrinfo s; s.ai_flags = AI_PASSIVE; ],
|
||||
[ ac_cv_have_struct_addrinfo="yes" ],
|
||||
[ ac_cv_have_struct_addrinfo="no" ]
|
||||
)
|
||||
])
|
||||
if test "x$ac_cv_have_struct_addrinfo" = "xyes" ; then
|
||||
AC_DEFINE(HAVE_STRUCT_ADDRINFO,,Have struct addrinfo)
|
||||
fi
|
||||
|
||||
|
||||
# IRIX has a const char return value for gai_strerror()
|
||||
AC_CHECK_FUNCS(gai_strerror,[
|
||||
AC_DEFINE(HAVE_GAI_STRERROR)
|
||||
AC_TRY_COMPILE([
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
|
||||
const char *gai_strerror(int);],[
|
||||
char *str;
|
||||
|
||||
str = gai_strerror(0);],[
|
||||
AC_DEFINE(HAVE_CONST_GAI_STRERROR_PROTO, 1,
|
||||
[Define if gai_strerror() returns const char *])])])
|
||||
|
||||
# for loginrec.c
|
||||
|
||||
AC_CHECK_MEMBERS([struct utmp.ut_host, struct utmp.ut_pid, struct utmp.ut_type, struct utmp.ut_tv, struct utmp.ut_id, struct utmp.ut_addr, struct utmp.ut_addr_v6, struct utmp.ut_exit, struct utmp.ut_time],,,[
|
||||
#include <sys/types.h>
|
||||
#if HAVE_UTMP_H
|
||||
#include <utmp.h>
|
||||
#endif
|
||||
])
|
||||
|
||||
AC_CHECK_MEMBERS([struct utmpx.ut_host, struct utmpx.ut_syslen, struct utmpx.ut_type, struct utmpx.ut_id, struct utmpx.ut_addr, struct utmpx.ut_addr_v6, struct utmpx.ut_time, struct utmpx.ut_tv],,,[
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#if HAVE_UTMPX_H
|
||||
#include <utmpx.h>
|
||||
#endif
|
||||
])
|
||||
|
||||
AC_CHECK_MEMBERS([struct sockaddr_storage.ss_family],,,[
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
])
|
||||
|
||||
AC_CHECK_FUNCS(endutent getutent getutid getutline pututline setutent)
|
||||
AC_CHECK_FUNCS(utmpname)
|
||||
AC_CHECK_FUNCS(endutxent getutxent getutxid getutxline pututxline )
|
||||
AC_CHECK_FUNCS(setutxent utmpxname)
|
||||
AC_CHECK_FUNCS(logout updwtmp logwtmp)
|
||||
|
||||
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()) ]
|
||||
)
|
||||
AC_ARG_ENABLE(utmp,
|
||||
[ --disable-utmp Disable use of utmp even if detected [no]],
|
||||
[ AC_DEFINE(DISABLE_UTMP,,Disable use of utmp) ]
|
||||
)
|
||||
AC_ARG_ENABLE(utmpx,
|
||||
[ --disable-utmpx Disable use of utmpx even if detected [no]],
|
||||
[ AC_DEFINE(DISABLE_UTMPX,,Disable use of utmpx) ]
|
||||
)
|
||||
AC_ARG_ENABLE(wtmp,
|
||||
[ --disable-wtmp Disable use of wtmp even if detected [no]],
|
||||
[ AC_DEFINE(DISABLE_WTMP,,Disable use of wtmp) ]
|
||||
)
|
||||
AC_ARG_ENABLE(wtmpx,
|
||||
[ --disable-wtmpx Disable use of wtmpx even if detected [no]],
|
||||
[ AC_DEFINE(DISABLE_WTMPX,,Disable use of wtmpx) ]
|
||||
)
|
||||
AC_ARG_ENABLE(loginfunc,
|
||||
[ --disable-loginfunc Disable use of login() etc. [no]],
|
||||
[ no_loginfunc_check=1
|
||||
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()) ]
|
||||
)
|
||||
AC_ARG_ENABLE(pututxline,
|
||||
[ --disable-pututxline Disable use of pututxline() etc. ([uw]tmpx) [no]],
|
||||
[ AC_DEFINE(DISABLE_PUTUTXLINE,,Disable use of pututxline()) ]
|
||||
)
|
||||
AC_ARG_WITH(lastlog,
|
||||
[ --with-lastlog=FILE|DIR specify lastlog location [common locations]],
|
||||
[
|
||||
if test "x$withval" = "xno" ; then
|
||||
AC_DEFINE(DISABLE_LASTLOG)
|
||||
else
|
||||
conf_lastlog_location=$withval
|
||||
fi
|
||||
]
|
||||
)
|
||||
|
||||
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_CHECK_FUNCS(logout updwtmp logwtmp)
|
||||
fi
|
||||
|
||||
dnl lastlog, [uw]tmpx? detection
|
||||
dnl NOTE: set the paths in the platform section to avoid the
|
||||
dnl need for command-line parameters
|
||||
dnl lastlog and [uw]tmp are subject to a file search if all else fails
|
||||
|
||||
dnl lastlog detection
|
||||
dnl NOTE: the code itself will detect if lastlog is a directory
|
||||
AC_MSG_CHECKING([if your system defines LASTLOG_FILE])
|
||||
AC_TRY_COMPILE([
|
||||
#include <sys/types.h>
|
||||
#include <utmp.h>
|
||||
#ifdef HAVE_LASTLOG_H
|
||||
# include <lastlog.h>
|
||||
#endif
|
||||
#ifdef HAVE_PATHS_H
|
||||
# include <paths.h>
|
||||
#endif
|
||||
#ifdef HAVE_LOGIN_H
|
||||
# include <login.h>
|
||||
#endif
|
||||
],
|
||||
[ char *lastlog = LASTLOG_FILE; ],
|
||||
[ AC_MSG_RESULT(yes) ],
|
||||
[
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_CHECKING([if your system defines _PATH_LASTLOG])
|
||||
AC_TRY_COMPILE([
|
||||
#include <sys/types.h>
|
||||
#include <utmp.h>
|
||||
#ifdef HAVE_LASTLOG_H
|
||||
# include <lastlog.h>
|
||||
#endif
|
||||
#ifdef HAVE_PATHS_H
|
||||
# include <paths.h>
|
||||
#endif
|
||||
],
|
||||
[ char *lastlog = _PATH_LASTLOG; ],
|
||||
[ AC_MSG_RESULT(yes) ],
|
||||
[
|
||||
AC_MSG_RESULT(no)
|
||||
system_lastlog_path=no
|
||||
])
|
||||
]
|
||||
)
|
||||
|
||||
if test -z "$conf_lastlog_location"; then
|
||||
if test x"$system_lastlog_path" = x"no" ; then
|
||||
for f in /var/log/lastlog /usr/adm/lastlog /var/adm/lastlog /etc/security/lastlog ; do
|
||||
if (test -d "$f" || test -f "$f") ; then
|
||||
conf_lastlog_location=$f
|
||||
fi
|
||||
done
|
||||
if test -z "$conf_lastlog_location"; then
|
||||
AC_MSG_WARN([** Cannot find lastlog **])
|
||||
dnl Don't define DISABLE_LASTLOG - that means we don't try wtmp/wtmpx
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$conf_lastlog_location"; then
|
||||
AC_DEFINE_UNQUOTED(CONF_LASTLOG_FILE, "$conf_lastlog_location", lastlog file location)
|
||||
fi
|
||||
|
||||
dnl utmp detection
|
||||
AC_MSG_CHECKING([if your system defines UTMP_FILE])
|
||||
AC_TRY_COMPILE([
|
||||
#include <sys/types.h>
|
||||
#include <utmp.h>
|
||||
#ifdef HAVE_PATHS_H
|
||||
# include <paths.h>
|
||||
#endif
|
||||
],
|
||||
[ char *utmp = UTMP_FILE; ],
|
||||
[ AC_MSG_RESULT(yes) ],
|
||||
[ AC_MSG_RESULT(no)
|
||||
system_utmp_path=no ]
|
||||
)
|
||||
if test -z "$conf_utmp_location"; then
|
||||
if test x"$system_utmp_path" = x"no" ; then
|
||||
for f in /etc/utmp /usr/adm/utmp /var/run/utmp; do
|
||||
if test -f $f ; then
|
||||
conf_utmp_location=$f
|
||||
fi
|
||||
done
|
||||
if test -z "$conf_utmp_location"; then
|
||||
AC_DEFINE(DISABLE_UTMP)
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if test -n "$conf_utmp_location"; then
|
||||
AC_DEFINE_UNQUOTED(CONF_UTMP_FILE, "$conf_utmp_location", utmp file location)
|
||||
fi
|
||||
|
||||
dnl wtmp detection
|
||||
AC_MSG_CHECKING([if your system defines WTMP_FILE])
|
||||
AC_TRY_COMPILE([
|
||||
#include <sys/types.h>
|
||||
#include <utmp.h>
|
||||
#ifdef HAVE_PATHS_H
|
||||
# include <paths.h>
|
||||
#endif
|
||||
],
|
||||
[ char *wtmp = WTMP_FILE; ],
|
||||
[ AC_MSG_RESULT(yes) ],
|
||||
[ AC_MSG_RESULT(no)
|
||||
system_wtmp_path=no ]
|
||||
)
|
||||
if test -z "$conf_wtmp_location"; then
|
||||
if test x"$system_wtmp_path" = x"no" ; then
|
||||
for f in /usr/adm/wtmp /var/log/wtmp; do
|
||||
if test -f $f ; then
|
||||
conf_wtmp_location=$f
|
||||
fi
|
||||
done
|
||||
if test -z "$conf_wtmp_location"; then
|
||||
AC_DEFINE(DISABLE_WTMP)
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if test -n "$conf_wtmp_location"; then
|
||||
AC_DEFINE_UNQUOTED(CONF_WTMP_FILE, "$conf_wtmp_location", wtmp file location)
|
||||
fi
|
||||
|
||||
|
||||
dnl utmpx detection - I don't know any system so perverse as to require
|
||||
dnl utmpx, but not define UTMPX_FILE (ditto wtmpx.) No doubt it's out
|
||||
dnl there, though.
|
||||
AC_MSG_CHECKING([if your system defines UTMPX_FILE])
|
||||
AC_TRY_COMPILE([
|
||||
#include <sys/types.h>
|
||||
#include <utmp.h>
|
||||
#ifdef HAVE_UTMPX_H
|
||||
#include <utmpx.h>
|
||||
#endif
|
||||
#ifdef HAVE_PATHS_H
|
||||
# include <paths.h>
|
||||
#endif
|
||||
],
|
||||
[ char *utmpx = UTMPX_FILE; ],
|
||||
[ AC_MSG_RESULT(yes) ],
|
||||
[ AC_MSG_RESULT(no)
|
||||
system_utmpx_path=no ]
|
||||
)
|
||||
if test -z "$conf_utmpx_location"; then
|
||||
if test x"$system_utmpx_path" = x"no" ; then
|
||||
AC_DEFINE(DISABLE_UTMPX)
|
||||
fi
|
||||
else
|
||||
AC_DEFINE_UNQUOTED(CONF_UTMPX_FILE, "$conf_utmpx_location", utmpx file location)
|
||||
fi
|
||||
|
||||
dnl wtmpx detection
|
||||
AC_MSG_CHECKING([if your system defines WTMPX_FILE])
|
||||
AC_TRY_COMPILE([
|
||||
#include <sys/types.h>
|
||||
#include <utmp.h>
|
||||
#ifdef HAVE_UTMPX_H
|
||||
#include <utmpx.h>
|
||||
#endif
|
||||
#ifdef HAVE_PATHS_H
|
||||
# include <paths.h>
|
||||
#endif
|
||||
],
|
||||
[ char *wtmpx = WTMPX_FILE; ],
|
||||
[ AC_MSG_RESULT(yes) ],
|
||||
[ AC_MSG_RESULT(no)
|
||||
system_wtmpx_path=no ]
|
||||
)
|
||||
if test -z "$conf_wtmpx_location"; then
|
||||
if test x"$system_wtmpx_path" = x"no" ; then
|
||||
AC_DEFINE(DISABLE_WTMPX)
|
||||
fi
|
||||
else
|
||||
AC_DEFINE_UNQUOTED(CONF_WTMPX_FILE, "$conf_wtmpx_location", wtmpx file location)
|
||||
fi
|
||||
|
||||
# Checks for library functions.
|
||||
AC_PROG_GCC_TRADITIONAL
|
||||
AC_FUNC_MEMCMP
|
||||
AC_FUNC_SELECT_ARGTYPES
|
||||
AC_TYPE_SIGNAL
|
||||
AC_CHECK_FUNCS([dup2 getspnam getusershell memset putenv select socket strdup clearenv strlcpy strlcat daemon basename _getpty getaddrinfo freeaddrinfo getnameinfo])
|
||||
|
||||
AC_SEARCH_LIBS(basename, gen, AC_DEFINE(HAVE_BASENAME))
|
||||
|
||||
# Solaris needs ptmx
|
||||
if test -z "$no_ptmx_check" ; then
|
||||
if test x"$cross_compiling" = x"no" ; then
|
||||
AC_CHECK_FILE("/dev/ptmx", AC_DEFINE(USE_DEV_PTMX,,Use /dev/ptmx))
|
||||
else
|
||||
AC_MSG_NOTICE([Not checking for /dev/ptmx, we're cross-compiling])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -z "$no_ptc_check" ; then
|
||||
if test x"$cross_compiling" = x"no" ; then
|
||||
AC_CHECK_FILE("/dev/ptc", AC_DEFINE(HAVE_DEV_PTS_AND_PTC,,Use /dev/ptc & /dev/pts))
|
||||
else
|
||||
AC_MSG_NOTICE([Not checking for /dev/ptc & /dev/pts since we're cross-compiling])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_EXEEXT
|
||||
|
||||
# XXX there must be a nicer way to do this
|
||||
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/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/short_integer)
|
||||
AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/utctime)
|
||||
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/pkcs1)
|
||||
AS_MKDIR_P(libtomcrypt/src/pk/rsa)
|
||||
AS_MKDIR_P(libtomcrypt/src/prng)
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_OUTPUT(Makefile)
|
||||
AC_OUTPUT(libtomcrypt/Makefile)
|
||||
AC_OUTPUT(libtommath/Makefile)
|
||||
AC_MSG_NOTICE()
|
||||
AC_MSG_NOTICE(Now edit options.h to choose features.)
|
||||
146
dbclient.1
Normal file
146
dbclient.1
Normal file
@@ -0,0 +1,146 @@
|
||||
.TH dbclient 1
|
||||
.SH NAME
|
||||
dbclient \- lightweight SSH2 client
|
||||
.SH SYNOPSIS
|
||||
.B dbclient
|
||||
[\-Tt] [\-p
|
||||
.I port\fR] [\-i
|
||||
.I id\fR] [\-L
|
||||
.I l\fR:\fIh\fR:\fIr\fR] [\-R
|
||||
.I l\fR:\fIh\fR:\fIr\fR] [\-l
|
||||
.IR user ]
|
||||
.I host
|
||||
.RI [ command ]
|
||||
|
||||
.B dbclient
|
||||
[
|
||||
.I args ]
|
||||
.I [user1]@host1[/port1],[user2]@host2[/port2],...
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B dbclient
|
||||
is a SSH 2 client designed to be small enough to be used in small memory
|
||||
environments, while still being functional and secure enough for general use.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-p \fIport
|
||||
Remote port.
|
||||
Connect to port
|
||||
.I port
|
||||
on the remote host.
|
||||
Default is 22.
|
||||
.TP
|
||||
.B \-i \fIidfile
|
||||
Identity file.
|
||||
Read the identity from file
|
||||
.I idfile
|
||||
(multiple allowed).
|
||||
.TP
|
||||
.B \-L \fIlistenport\fR:\fIhost\fR:\fIport\fR
|
||||
Local port forwarding.
|
||||
Forward the port
|
||||
.I listenport
|
||||
on the local host through the SSH connection to port
|
||||
.I port
|
||||
on the host
|
||||
.IR host .
|
||||
.TP
|
||||
.B \-R \fIlistenport\fR:\fIhost\fR:\fIport\fR
|
||||
Remote port forwarding.
|
||||
Forward the port
|
||||
.I listenport
|
||||
on the remote host through the SSH connection to port
|
||||
.I port
|
||||
on the host
|
||||
.IR host .
|
||||
.TP
|
||||
.B \-l \fIuser
|
||||
Username.
|
||||
Login as
|
||||
.I user
|
||||
on the remote host.
|
||||
.TP
|
||||
.B \-t
|
||||
Allocate a pty.
|
||||
.TP
|
||||
.B \-T
|
||||
Don't allocate a pty.
|
||||
.TP
|
||||
.B \-N
|
||||
Don't request a remote shell or run any commands. Any command arguments are ignored.
|
||||
.TP
|
||||
.B \-f
|
||||
Fork into the background after authentication. A command argument (or -N) is required.
|
||||
This is useful when using password authentication.
|
||||
.TP
|
||||
.B \-g
|
||||
Allow non-local hosts to connect to forwarded ports. Applies to -L and -R
|
||||
forwarded ports, though remote connections to -R forwarded ports may be limited
|
||||
by the ssh server.
|
||||
.TP
|
||||
.B \-y
|
||||
Always accept hostkeys if they are unknown. If a hostkey mismatch occurs the
|
||||
connection will abort as normal.
|
||||
.TP
|
||||
.B \-W \fIwindowsize
|
||||
Specify the per-channel receive window buffer size. Increasing this
|
||||
may improve network performance at the expense of memory use. Use -h to see the
|
||||
default buffer size.
|
||||
.TP
|
||||
.B \-K \fItimeout_seconds
|
||||
Ensure that traffic is transmitted at a certain interval in seconds. This is
|
||||
useful for working around firewalls or routers that drop connections after
|
||||
a certain period of inactivity. The trade-off is that a session may be
|
||||
closed if there is a temporary lapse of network connectivity. A setting
|
||||
if 0 disables keepalives.
|
||||
.TP
|
||||
.B \-I \fIidle_timeout
|
||||
Disconnect the session if no traffic is transmitted or received for \fIidle_timeout\fR seconds.
|
||||
.TP
|
||||
.B \-J \fIproxy_command
|
||||
Use the standard input/output of the program \fIproxy_command\fR rather than using
|
||||
a normal TCP connection. A hostname should be still be provided, as this is used for
|
||||
comparing saved hostkeys.
|
||||
.TP
|
||||
.B \-B \fIendhost:endport
|
||||
"Netcat-alike" mode, where Dropbear will connect to the given host, then create a
|
||||
forwarded connection to \fIendhost\fR. This will then be presented as dbclient's
|
||||
standard input/output.
|
||||
|
||||
Dropbear will also allow multiple "hops" to be specified, separated by commas. In
|
||||
this case a connection will be made to the first host, then a TCP forwarded
|
||||
connection will be made through that to the second host, and so on. Hosts other than
|
||||
the final destination will not see anything other than the encrypted SSH stream.
|
||||
A port for a host can be specified with a slash (eg matt@martello/44 ).
|
||||
This syntax can also be used with scp or rsync (specifying dbclient as the
|
||||
ssh/rsh command). A file can be "bounced" through multiple SSH hops, eg
|
||||
|
||||
scp -S dbclient matt@martello,root@wrt,canyons:/tmp/dump .
|
||||
|
||||
Note that hostnames are resolved by the prior hop (so "canyons" would be resolved by the host "wrt")
|
||||
in the example above, the same way as other -L TCP forwarded hosts are. Host keys are
|
||||
checked locally based on the given hostname.
|
||||
|
||||
.SH ENVIRONMENT
|
||||
.TP
|
||||
.B DROPBEAR_PASSWORD
|
||||
A password to use for remote authentication can be specified in the environment
|
||||
variable DROPBEAR_PASSWORD. Care should be taken that the password is not
|
||||
exposed to other users on a multi-user system, or stored in accessible files.
|
||||
.TP
|
||||
.B SSH_ASKPASS
|
||||
dbclient can use an external program to request a password from a user.
|
||||
SSH_ASKPASS should be set to the path of a program that will return a password
|
||||
on standard output. This program will only be used if either DISPLAY is set and
|
||||
standard input is not a TTY, or the environment variable SSH_ASKPASS_ALWAYS is
|
||||
set.
|
||||
.SH AUTHOR
|
||||
Matt Johnston (matt@ucc.asn.au).
|
||||
.br
|
||||
Mihnea Stoenescu wrote initial Dropbear client support
|
||||
.br
|
||||
Gerrit Pape (pape@smarden.org) wrote this manual page.
|
||||
.SH SEE ALSO
|
||||
dropbear(8), dropbearkey(8)
|
||||
.P
|
||||
http://matt.ucc.asn.au/dropbear/dropbear.html
|
||||
90
dbmulti.c
Normal file
90
dbmulti.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Dropbear SSH
|
||||
*
|
||||
* 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"
|
||||
|
||||
/* definitions are cleanest if we just put them here */
|
||||
int dropbear_main(int argc, char ** argv);
|
||||
int dropbearkey_main(int argc, char ** argv);
|
||||
int dropbearconvert_main(int argc, char ** argv);
|
||||
int scp_main(int argc, char ** argv);
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
|
||||
char * progname;
|
||||
|
||||
if (argc > 0) {
|
||||
/* figure which form we're being called as */
|
||||
progname = basename(argv[0]);
|
||||
|
||||
#ifdef DBMULTI_dropbear
|
||||
if (strcmp(progname, "dropbear") == 0) {
|
||||
return dropbear_main(argc, argv);
|
||||
}
|
||||
#endif
|
||||
#ifdef DBMULTI_dbclient
|
||||
if (strcmp(progname, "dbclient") == 0
|
||||
|| strcmp(progname, "ssh") == 0) {
|
||||
return cli_main(argc, argv);
|
||||
}
|
||||
#endif
|
||||
#ifdef DBMULTI_dropbearkey
|
||||
if (strcmp(progname, "dropbearkey") == 0) {
|
||||
return dropbearkey_main(argc, argv);
|
||||
}
|
||||
#endif
|
||||
#ifdef DBMULTI_dropbearconvert
|
||||
if (strcmp(progname, "dropbearconvert") == 0) {
|
||||
return dropbearconvert_main(argc, argv);
|
||||
}
|
||||
#endif
|
||||
#ifdef DBMULTI_scp
|
||||
if (strcmp(progname, "scp") == 0) {
|
||||
return scp_main(argc, argv);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
fprintf(stderr, "Dropbear multi-purpose version %s\n"
|
||||
"Make a symlink pointing at this binary with one of the following names:\n"
|
||||
#ifdef DBMULTI_dropbear
|
||||
"'dropbear' - the Dropbear server\n"
|
||||
#endif
|
||||
#ifdef DBMULTI_dbclient
|
||||
"'dbclient' or 'ssh' - the Dropbear client\n"
|
||||
#endif
|
||||
#ifdef DBMULTI_dropbearkey
|
||||
"'dropbearkey' - the key generator\n"
|
||||
#endif
|
||||
#ifdef DBMULTI_dropbearconvert
|
||||
"'dropbearconvert' - the key converter\n"
|
||||
#endif
|
||||
#ifdef DBMULTI_scp
|
||||
"'scp' - secure copy\n"
|
||||
#endif
|
||||
,
|
||||
DROPBEAR_VERSION);
|
||||
exit(1);
|
||||
|
||||
}
|
||||
851
dbutil.c
Normal file
851
dbutil.c
Normal file
@@ -0,0 +1,851 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* strlcat() is copyright as follows:
|
||||
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
#include "includes.h"
|
||||
#include "dbutil.h"
|
||||
#include "buffer.h"
|
||||
#include "session.h"
|
||||
#include "atomicio.h"
|
||||
|
||||
#define MAX_FMT 100
|
||||
|
||||
static void generic_dropbear_exit(int exitcode, const char* format,
|
||||
va_list param);
|
||||
static void generic_dropbear_log(int priority, const char* format,
|
||||
va_list param);
|
||||
|
||||
void (*_dropbear_exit)(int exitcode, const char* format, va_list param)
|
||||
= generic_dropbear_exit;
|
||||
void (*_dropbear_log)(int priority, const char* format, va_list param)
|
||||
= generic_dropbear_log;
|
||||
|
||||
#ifdef DEBUG_TRACE
|
||||
int debug_trace = 0;
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_SYSLOG
|
||||
void startsyslog() {
|
||||
|
||||
openlog(PROGNAME, LOG_PID, LOG_AUTHPRIV);
|
||||
|
||||
}
|
||||
#endif /* DISABLE_SYSLOG */
|
||||
|
||||
/* the "format" string must be <= 100 characters */
|
||||
void dropbear_close(const char* format, ...) {
|
||||
|
||||
va_list param;
|
||||
|
||||
va_start(param, format);
|
||||
_dropbear_exit(EXIT_SUCCESS, format, param);
|
||||
va_end(param);
|
||||
|
||||
}
|
||||
|
||||
void dropbear_exit(const char* format, ...) {
|
||||
|
||||
va_list param;
|
||||
|
||||
va_start(param, format);
|
||||
_dropbear_exit(EXIT_FAILURE, format, param);
|
||||
va_end(param);
|
||||
}
|
||||
|
||||
static void generic_dropbear_exit(int exitcode, const char* format,
|
||||
va_list param) {
|
||||
|
||||
char fmtbuf[300];
|
||||
|
||||
snprintf(fmtbuf, sizeof(fmtbuf), "Exited: %s", format);
|
||||
|
||||
_dropbear_log(LOG_INFO, fmtbuf, param);
|
||||
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
void fail_assert(const char* expr, const char* file, int line) {
|
||||
dropbear_exit("failed assertion (%s:%d): `%s'", file, line, expr);
|
||||
}
|
||||
|
||||
static void generic_dropbear_log(int UNUSED(priority), const char* format,
|
||||
va_list param) {
|
||||
|
||||
char printbuf[1024];
|
||||
|
||||
vsnprintf(printbuf, sizeof(printbuf), format, param);
|
||||
|
||||
fprintf(stderr, "%s\n", printbuf);
|
||||
|
||||
}
|
||||
|
||||
/* this is what can be called to write arbitrary log messages */
|
||||
void dropbear_log(int priority, const char* format, ...) {
|
||||
|
||||
va_list param;
|
||||
|
||||
va_start(param, format);
|
||||
_dropbear_log(priority, format, param);
|
||||
va_end(param);
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_TRACE
|
||||
void dropbear_trace(const char* format, ...) {
|
||||
|
||||
va_list param;
|
||||
|
||||
if (!debug_trace) {
|
||||
return;
|
||||
}
|
||||
|
||||
va_start(param, format);
|
||||
fprintf(stderr, "TRACE (%d): ", getpid());
|
||||
vfprintf(stderr, format, param);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(param);
|
||||
}
|
||||
#endif /* DEBUG_TRACE */
|
||||
|
||||
static void set_sock_priority(int sock) {
|
||||
|
||||
int val;
|
||||
|
||||
/* disable nagle */
|
||||
val = 1;
|
||||
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*)&val, sizeof(val));
|
||||
|
||||
/* set the TOS bit. note that this will fail for ipv6, I can't find any
|
||||
* equivalent. */
|
||||
#ifdef IPTOS_LOWDELAY
|
||||
val = IPTOS_LOWDELAY;
|
||||
setsockopt(sock, IPPROTO_IP, IP_TOS, (void*)&val, sizeof(val));
|
||||
#endif
|
||||
|
||||
#ifdef SO_PRIORITY
|
||||
/* linux specific, sets QoS class.
|
||||
* 6 looks to be optimal for interactive traffic (see tc-prio(8) ). */
|
||||
val = 6;
|
||||
setsockopt(sock, SOL_SOCKET, SO_PRIORITY, (void*) &val, sizeof(val));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* Listen on address:port.
|
||||
* Special cases are address of "" listening on everything,
|
||||
* and address of NULL listening on localhost only.
|
||||
* Returns the number of sockets bound on success, or -1 on failure. On
|
||||
* failure, if errstring wasn't NULL, it'll be a newly malloced error
|
||||
* string.*/
|
||||
int dropbear_listen(const char* address, const char* port,
|
||||
int *socks, unsigned int sockcount, char **errstring, int *maxfd) {
|
||||
|
||||
struct addrinfo hints, *res = NULL, *res0 = NULL;
|
||||
int err;
|
||||
unsigned int nsock;
|
||||
struct linger linger;
|
||||
int val;
|
||||
int sock;
|
||||
|
||||
TRACE(("enter dropbear_listen"))
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC; /* TODO: let them flag v4 only etc */
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
/* for calling getaddrinfo:
|
||||
address == NULL and !AI_PASSIVE: local loopback
|
||||
address == NULL and AI_PASSIVE: all interfaces
|
||||
address != NULL: whatever the address says */
|
||||
if (!address) {
|
||||
TRACE(("dropbear_listen: local loopback"))
|
||||
} else {
|
||||
if (address[0] == '\0') {
|
||||
TRACE(("dropbear_listen: all interfaces"))
|
||||
address = NULL;
|
||||
}
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
}
|
||||
err = getaddrinfo(address, port, &hints, &res0);
|
||||
|
||||
if (err) {
|
||||
if (errstring != NULL && *errstring == NULL) {
|
||||
int len;
|
||||
len = 20 + strlen(gai_strerror(err));
|
||||
*errstring = (char*)m_malloc(len);
|
||||
snprintf(*errstring, len, "Error resolving: %s", gai_strerror(err));
|
||||
}
|
||||
if (res0) {
|
||||
freeaddrinfo(res0);
|
||||
res0 = NULL;
|
||||
}
|
||||
TRACE(("leave dropbear_listen: failed resolving"))
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
nsock = 0;
|
||||
for (res = res0; res != NULL && nsock < sockcount;
|
||||
res = res->ai_next) {
|
||||
|
||||
/* Get a socket */
|
||||
socks[nsock] = socket(res->ai_family, res->ai_socktype,
|
||||
res->ai_protocol);
|
||||
|
||||
sock = socks[nsock]; /* For clarity */
|
||||
|
||||
if (sock < 0) {
|
||||
err = errno;
|
||||
TRACE(("socket() failed"))
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Various useful socket options */
|
||||
val = 1;
|
||||
/* set to reuse, quick timeout */
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &val, sizeof(val));
|
||||
linger.l_onoff = 1;
|
||||
linger.l_linger = 5;
|
||||
setsockopt(sock, SOL_SOCKET, SO_LINGER, (void*)&linger, sizeof(linger));
|
||||
|
||||
set_sock_priority(sock);
|
||||
|
||||
if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
|
||||
err = errno;
|
||||
close(sock);
|
||||
TRACE(("bind(%s) failed", port))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (listen(sock, 20) < 0) {
|
||||
err = errno;
|
||||
close(sock);
|
||||
TRACE(("listen() failed"))
|
||||
continue;
|
||||
}
|
||||
|
||||
*maxfd = MAX(*maxfd, sock);
|
||||
|
||||
nsock++;
|
||||
}
|
||||
|
||||
if (res0) {
|
||||
freeaddrinfo(res0);
|
||||
res0 = NULL;
|
||||
}
|
||||
|
||||
if (nsock == 0) {
|
||||
if (errstring != NULL && *errstring == NULL) {
|
||||
int len;
|
||||
len = 20 + strlen(strerror(err));
|
||||
*errstring = (char*)m_malloc(len);
|
||||
snprintf(*errstring, len, "Error listening: %s", strerror(err));
|
||||
}
|
||||
TRACE(("leave dropbear_listen: failure, %s", strerror(err)))
|
||||
return -1;
|
||||
}
|
||||
|
||||
TRACE(("leave dropbear_listen: success, %d socks bound", nsock))
|
||||
return nsock;
|
||||
}
|
||||
|
||||
/* Connect via TCP to a host. Connection will try ipv4 or ipv6, will
|
||||
* return immediately if nonblocking is set. On failure, if errstring
|
||||
* wasn't null, it will be a newly malloced error message */
|
||||
|
||||
/* TODO: maxfd */
|
||||
int connect_remote(const char* remotehost, const char* remoteport,
|
||||
int nonblocking, char ** errstring) {
|
||||
|
||||
struct addrinfo *res0 = NULL, *res = NULL, hints;
|
||||
int sock;
|
||||
int err;
|
||||
|
||||
TRACE(("enter connect_remote"))
|
||||
|
||||
if (errstring != NULL) {
|
||||
*errstring = NULL;
|
||||
}
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
|
||||
err = getaddrinfo(remotehost, remoteport, &hints, &res0);
|
||||
if (err) {
|
||||
if (errstring != NULL && *errstring == NULL) {
|
||||
int len;
|
||||
len = 100 + strlen(gai_strerror(err));
|
||||
*errstring = (char*)m_malloc(len);
|
||||
snprintf(*errstring, len, "Error resolving '%s' port '%s'. %s",
|
||||
remotehost, remoteport, gai_strerror(err));
|
||||
}
|
||||
TRACE(("Error resolving: %s", gai_strerror(err)))
|
||||
return -1;
|
||||
}
|
||||
|
||||
sock = -1;
|
||||
err = EADDRNOTAVAIL;
|
||||
for (res = res0; res; res = res->ai_next) {
|
||||
|
||||
sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||
if (sock < 0) {
|
||||
err = errno;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nonblocking) {
|
||||
if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
|
||||
close(sock);
|
||||
sock = -1;
|
||||
if (errstring != NULL && *errstring == NULL) {
|
||||
*errstring = m_strdup("Failed non-blocking");
|
||||
}
|
||||
TRACE(("Failed non-blocking: %s", strerror(errno)))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) {
|
||||
if (errno == EINPROGRESS && nonblocking) {
|
||||
TRACE(("Connect in progress"))
|
||||
break;
|
||||
} else {
|
||||
err = errno;
|
||||
close(sock);
|
||||
sock = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
break; /* Success */
|
||||
}
|
||||
|
||||
if (sock < 0 && !(errno == EINPROGRESS && nonblocking)) {
|
||||
/* Failed */
|
||||
if (errstring != NULL && *errstring == NULL) {
|
||||
int len;
|
||||
len = 20 + strlen(strerror(err));
|
||||
*errstring = (char*)m_malloc(len);
|
||||
snprintf(*errstring, len, "Error connecting: %s", strerror(err));
|
||||
}
|
||||
TRACE(("Error connecting: %s", strerror(err)))
|
||||
} else {
|
||||
/* Success */
|
||||
set_sock_priority(sock);
|
||||
}
|
||||
|
||||
freeaddrinfo(res0);
|
||||
if (sock > 0 && errstring != NULL && *errstring != NULL) {
|
||||
m_free(*errstring);
|
||||
}
|
||||
|
||||
TRACE(("leave connect_remote: sock %d\n", sock))
|
||||
return sock;
|
||||
}
|
||||
|
||||
/* Sets up a pipe for a, returning three non-blocking file descriptors
|
||||
* and the pid. exec_fn is the function that will actually execute the child process,
|
||||
* it will be run after the child has fork()ed, and is passed exec_data.
|
||||
* If ret_errfd == NULL then stderr will not be captured.
|
||||
* ret_pid can be passed as NULL to discard the pid. */
|
||||
int spawn_command(void(*exec_fn)(void *user_data), void *exec_data,
|
||||
int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid) {
|
||||
int infds[2];
|
||||
int outfds[2];
|
||||
int errfds[2];
|
||||
pid_t pid;
|
||||
|
||||
const int FDIN = 0;
|
||||
const int FDOUT = 1;
|
||||
|
||||
/* redirect stdin/stdout/stderr */
|
||||
if (pipe(infds) != 0) {
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
if (pipe(outfds) != 0) {
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
if (ret_errfd && pipe(errfds) != 0) {
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef __uClinux__
|
||||
pid = vfork();
|
||||
#else
|
||||
pid = fork();
|
||||
#endif
|
||||
|
||||
if (pid < 0) {
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
if (!pid) {
|
||||
/* child */
|
||||
|
||||
TRACE(("back to normal sigchld"))
|
||||
/* Revert to normal sigchld handling */
|
||||
if (signal(SIGCHLD, SIG_DFL) == SIG_ERR) {
|
||||
dropbear_exit("signal() error");
|
||||
}
|
||||
|
||||
/* redirect stdin/stdout */
|
||||
|
||||
if ((dup2(infds[FDIN], STDIN_FILENO) < 0) ||
|
||||
(dup2(outfds[FDOUT], STDOUT_FILENO) < 0) ||
|
||||
(ret_errfd && dup2(errfds[FDOUT], STDERR_FILENO) < 0)) {
|
||||
TRACE(("leave noptycommand: error redirecting FDs"))
|
||||
dropbear_exit("child dup2() failure");
|
||||
}
|
||||
|
||||
close(infds[FDOUT]);
|
||||
close(infds[FDIN]);
|
||||
close(outfds[FDIN]);
|
||||
close(outfds[FDOUT]);
|
||||
if (ret_errfd)
|
||||
{
|
||||
close(errfds[FDIN]);
|
||||
close(errfds[FDOUT]);
|
||||
}
|
||||
|
||||
exec_fn(exec_data);
|
||||
/* not reached */
|
||||
return DROPBEAR_FAILURE;
|
||||
} else {
|
||||
/* parent */
|
||||
close(infds[FDIN]);
|
||||
close(outfds[FDOUT]);
|
||||
|
||||
setnonblocking(outfds[FDIN]);
|
||||
setnonblocking(infds[FDOUT]);
|
||||
|
||||
if (ret_errfd) {
|
||||
close(errfds[FDOUT]);
|
||||
setnonblocking(errfds[FDIN]);
|
||||
}
|
||||
|
||||
if (ret_pid) {
|
||||
*ret_pid = pid;
|
||||
}
|
||||
|
||||
*ret_writefd = infds[FDOUT];
|
||||
*ret_readfd = outfds[FDIN];
|
||||
if (ret_errfd) {
|
||||
*ret_errfd = errfds[FDIN];
|
||||
}
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* Runs a command with "sh -c". Will close FDs (except stdin/stdout/stderr) and
|
||||
* re-enabled SIGPIPE. If cmd is NULL, will run a login shell.
|
||||
*/
|
||||
void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell) {
|
||||
char * argv[4];
|
||||
char * baseshell = NULL;
|
||||
unsigned int i;
|
||||
|
||||
baseshell = basename(usershell);
|
||||
|
||||
if (cmd != NULL) {
|
||||
argv[0] = baseshell;
|
||||
} else {
|
||||
/* a login shell should be "-bash" for "/bin/bash" etc */
|
||||
int len = strlen(baseshell) + 2; /* 2 for "-" */
|
||||
argv[0] = (char*)m_malloc(len);
|
||||
snprintf(argv[0], len, "-%s", baseshell);
|
||||
}
|
||||
|
||||
if (cmd != NULL) {
|
||||
argv[1] = "-c";
|
||||
argv[2] = (char*)cmd;
|
||||
argv[3] = NULL;
|
||||
} else {
|
||||
/* construct a shell of the form "-bash" etc */
|
||||
argv[1] = NULL;
|
||||
}
|
||||
|
||||
/* Re-enable SIGPIPE for the executed process */
|
||||
if (signal(SIGPIPE, SIG_DFL) == SIG_ERR) {
|
||||
dropbear_exit("signal() error");
|
||||
}
|
||||
|
||||
/* close file descriptors except stdin/stdout/stderr
|
||||
* Need to be sure FDs are closed here to avoid reading files as root */
|
||||
for (i = 3; i <= maxfd; i++) {
|
||||
m_close(i);
|
||||
}
|
||||
|
||||
execv(usershell, argv);
|
||||
}
|
||||
|
||||
/* Return a string representation of the socket address passed. The return
|
||||
* value is allocated with malloc() */
|
||||
unsigned char * getaddrstring(struct sockaddr_storage* addr, int withport) {
|
||||
|
||||
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
|
||||
char *retstring = NULL;
|
||||
int ret;
|
||||
unsigned int len;
|
||||
|
||||
len = sizeof(struct sockaddr_storage);
|
||||
/* Some platforms such as Solaris 8 require that len is the length
|
||||
* of the specific structure. Some older linux systems (glibc 2.1.3
|
||||
* such as debian potato) have sockaddr_storage.__ss_family instead
|
||||
* but we'll ignore them */
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY
|
||||
if (addr->ss_family == AF_INET) {
|
||||
len = sizeof(struct sockaddr_in);
|
||||
}
|
||||
#ifdef AF_INET6
|
||||
if (addr->ss_family == AF_INET6) {
|
||||
len = sizeof(struct sockaddr_in6);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ret = getnameinfo((struct sockaddr*)addr, len, hbuf, sizeof(hbuf),
|
||||
sbuf, sizeof(sbuf), NI_NUMERICSERV | NI_NUMERICHOST);
|
||||
|
||||
if (ret != 0) {
|
||||
/* This is a fairly bad failure - it'll fallback to IP if it
|
||||
* just can't resolve */
|
||||
dropbear_exit("failed lookup (%d, %d)", ret, errno);
|
||||
}
|
||||
|
||||
if (withport) {
|
||||
len = strlen(hbuf) + 2 + strlen(sbuf);
|
||||
retstring = (char*)m_malloc(len);
|
||||
snprintf(retstring, len, "%s:%s", hbuf, sbuf);
|
||||
} else {
|
||||
retstring = m_strdup(hbuf);
|
||||
}
|
||||
|
||||
return retstring;
|
||||
|
||||
}
|
||||
|
||||
/* Get the hostname corresponding to the address addr. On failure, the IP
|
||||
* address is returned. The return value is allocated with strdup() */
|
||||
char* getaddrhostname(struct sockaddr_storage * addr) {
|
||||
|
||||
char hbuf[NI_MAXHOST];
|
||||
char sbuf[NI_MAXSERV];
|
||||
int ret;
|
||||
unsigned int len;
|
||||
#ifdef DO_HOST_LOOKUP
|
||||
const int flags = NI_NUMERICSERV;
|
||||
#else
|
||||
const int flags = NI_NUMERICHOST | NI_NUMERICSERV;
|
||||
#endif
|
||||
|
||||
len = sizeof(struct sockaddr_storage);
|
||||
/* Some platforms such as Solaris 8 require that len is the length
|
||||
* of the specific structure. */
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY
|
||||
if (addr->ss_family == AF_INET) {
|
||||
len = sizeof(struct sockaddr_in);
|
||||
}
|
||||
#ifdef AF_INET6
|
||||
if (addr->ss_family == AF_INET6) {
|
||||
len = sizeof(struct sockaddr_in6);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
ret = getnameinfo((struct sockaddr*)addr, len, hbuf, sizeof(hbuf),
|
||||
sbuf, sizeof(sbuf), flags);
|
||||
|
||||
if (ret != 0) {
|
||||
/* On some systems (Darwin does it) we get EINTR from getnameinfo
|
||||
* somehow. Eew. So we'll just return the IP, since that doesn't seem
|
||||
* to exhibit that behaviour. */
|
||||
return getaddrstring(addr, 0);
|
||||
}
|
||||
|
||||
return m_strdup(hbuf);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_TRACE
|
||||
void printhex(const char * label, const unsigned char * buf, int len) {
|
||||
|
||||
int i;
|
||||
|
||||
fprintf(stderr, "%s\n", label);
|
||||
for (i = 0; i < len; i++) {
|
||||
fprintf(stderr, "%02x", buf[i]);
|
||||
if (i % 16 == 15) {
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
else if (i % 2 == 1) {
|
||||
fprintf(stderr, " ");
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Strip all control characters from text (a null-terminated string), except
|
||||
* for '\n', '\r' and '\t'.
|
||||
* The result returned is a newly allocated string, this must be free()d after
|
||||
* use */
|
||||
char * stripcontrol(const char * text) {
|
||||
|
||||
char * ret;
|
||||
int len, pos;
|
||||
int i;
|
||||
|
||||
len = strlen(text);
|
||||
ret = m_malloc(len+1);
|
||||
|
||||
pos = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
if ((text[i] <= '~' && text[i] >= ' ') /* normal printable range */
|
||||
|| text[i] == '\n' || text[i] == '\r' || text[i] == '\t') {
|
||||
ret[pos] = text[i];
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
ret[pos] = 0x0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* reads the contents of filename into the buffer buf, from the current
|
||||
* position, either to the end of the file, or the buffer being full.
|
||||
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
|
||||
int buf_readfile(buffer* buf, const char* filename) {
|
||||
|
||||
int fd = -1;
|
||||
int len;
|
||||
int maxlen;
|
||||
int ret = DROPBEAR_FAILURE;
|
||||
|
||||
fd = open(filename, O_RDONLY);
|
||||
|
||||
if (fd < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
do {
|
||||
maxlen = buf->size - buf->pos;
|
||||
len = read(fd, buf_getwriteptr(buf, maxlen), maxlen);
|
||||
if (len < 0) {
|
||||
if (errno == EINTR || errno == EAGAIN) {
|
||||
continue;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
buf_incrwritepos(buf, len);
|
||||
} while (len < maxlen && len > 0);
|
||||
|
||||
ret = DROPBEAR_SUCCESS;
|
||||
|
||||
out:
|
||||
if (fd >= 0) {
|
||||
m_close(fd);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* get a line from the file into buffer in the style expected for an
|
||||
* 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)
|
||||
int buf_getline(buffer * line, FILE * authfile) {
|
||||
|
||||
int c = EOF;
|
||||
|
||||
TRACE(("enter buf_getline"))
|
||||
|
||||
buf_setpos(line, 0);
|
||||
buf_setlen(line, 0);
|
||||
|
||||
while (line->pos < line->size) {
|
||||
|
||||
c = fgetc(authfile); /*getc() is weird with some uClibc systems*/
|
||||
if (c == EOF || c == '\n' || c == '\r') {
|
||||
goto out;
|
||||
}
|
||||
|
||||
buf_putbyte(line, (unsigned char)c);
|
||||
}
|
||||
|
||||
TRACE(("leave getauthline: line too long"))
|
||||
/* We return success, but the line length will be zeroed - ie we just
|
||||
* ignore that line */
|
||||
buf_setlen(line, 0);
|
||||
|
||||
out:
|
||||
|
||||
|
||||
/* if we didn't read anything before EOF or error, exit */
|
||||
if (c == EOF && line->pos == 0) {
|
||||
TRACE(("leave buf_getline: failure"))
|
||||
return DROPBEAR_FAILURE;
|
||||
} else {
|
||||
TRACE(("leave buf_getline: success"))
|
||||
buf_setpos(line, 0);
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/* make sure that the socket closes */
|
||||
void m_close(int fd) {
|
||||
|
||||
int val;
|
||||
do {
|
||||
val = close(fd);
|
||||
} while (val < 0 && errno == EINTR);
|
||||
|
||||
if (val < 0 && errno != EBADF) {
|
||||
/* Linux says EIO can happen */
|
||||
dropbear_exit("Error closing fd %d, %s", fd, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
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_free(void* ptr) {
|
||||
if (ptr != NULL) {
|
||||
free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Clear the data, based on the method in David Wheeler's
|
||||
* "Secure Programming for Linux and Unix HOWTO" */
|
||||
/* Beware of calling this from within dbutil.c - things might get
|
||||
* optimised away */
|
||||
void m_burn(void *data, unsigned int len) {
|
||||
volatile char *p = data;
|
||||
|
||||
if (data == NULL)
|
||||
return;
|
||||
while (len--) {
|
||||
*p++ = 0x66;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setnonblocking(int fd) {
|
||||
|
||||
TRACE(("setnonblocking: %d", fd))
|
||||
|
||||
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"))
|
||||
}
|
||||
|
||||
void disallow_core() {
|
||||
struct rlimit lim;
|
||||
lim.rlim_cur = lim.rlim_max = 0;
|
||||
setrlimit(RLIMIT_CORE, &lim);
|
||||
}
|
||||
|
||||
/* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE, with the result in *val */
|
||||
int m_str_to_uint(const char* str, unsigned int *val) {
|
||||
errno = 0;
|
||||
*val = strtoul(str, NULL, 10);
|
||||
/* The c99 spec doesn't actually seem to define EINVAL, but most platforms
|
||||
* I've looked at mention it in their manpage */
|
||||
if ((*val == 0 && errno == EINVAL)
|
||||
|| (*val == ULONG_MAX && errno == ERANGE)) {
|
||||
return DROPBEAR_FAILURE;
|
||||
} else {
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
}
|
||||
78
dbutil.h
Normal file
78
dbutil.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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 _DBUTIL_H_
|
||||
|
||||
#define _DBUTIL_H_
|
||||
|
||||
#include "includes.h"
|
||||
#include "buffer.h"
|
||||
|
||||
#ifndef DISABLE_SYSLOG
|
||||
void startsyslog();
|
||||
#endif
|
||||
|
||||
extern void (*_dropbear_exit)(int exitcode, const char* format, va_list param);
|
||||
extern void (*_dropbear_log)(int priority, const char* format, va_list param);
|
||||
|
||||
void dropbear_exit(const char* format, ...);
|
||||
void dropbear_close(const char* format, ...);
|
||||
void dropbear_log(int priority, const char* format, ...);
|
||||
void fail_assert(const char* expr, const char* file, int line);
|
||||
#ifdef DEBUG_TRACE
|
||||
void dropbear_trace(const char* format, ...);
|
||||
void printhex(const char * label, const unsigned char * buf, int len);
|
||||
extern int debug_trace;
|
||||
#endif
|
||||
char * stripcontrol(const char * text);
|
||||
unsigned char * getaddrstring(struct sockaddr_storage* addr, int withport);
|
||||
int dropbear_listen(const char* address, const char* port,
|
||||
int *socks, unsigned int sockcount, char **errstring, int *maxfd);
|
||||
int spawn_command(void(*exec_fn)(void *user_data), void *exec_data,
|
||||
int *writefd, int *readfd, int *errfd, pid_t *pid);
|
||||
void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell);
|
||||
int connect_remote(const char* remotehost, const char* remoteport,
|
||||
int nonblocking, char ** errstring);
|
||||
char* getaddrhostname(struct sockaddr_storage * addr);
|
||||
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) __m_free(X); (X) = NULL;
|
||||
void __m_free(void* ptr);
|
||||
void m_burn(void* data, unsigned int len);
|
||||
void setnonblocking(int fd);
|
||||
void disallow_core();
|
||||
int m_str_to_uint(const char* str, unsigned int *val);
|
||||
|
||||
/* Used to force mp_ints to be initialised */
|
||||
#define DEF_MP_INT(X) mp_int X = {0, 0, 0, NULL}
|
||||
|
||||
/* Dropbear assertion */
|
||||
#define dropbear_assert(X) do { if (!(X)) { fail_assert(#X, __FILE__, __LINE__); } } while (0)
|
||||
|
||||
#endif /* _DBUTIL_H_ */
|
||||
41
debian/README.Debian
vendored
Normal file
41
debian/README.Debian
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
Dropbear for Debian
|
||||
-------------------
|
||||
|
||||
This package will attempt to listen on port 22. If the OpenSSH
|
||||
package ("ssh") is installed, the file /etc/default/dropbear
|
||||
will be set up so that the server does not start by default.
|
||||
|
||||
You can run Dropbear concurrently with OpenSSH 'sshd' by
|
||||
modifying /etc/default/dropbear so that "NO_START" is set to
|
||||
"0" and changing the port number that Dropbear runs on. Follow
|
||||
the instructions in the file.
|
||||
|
||||
This package suggests you install the "ssh" package. This package
|
||||
provides the "ssh" client program, as well as the "/usr/bin/scp"
|
||||
binary you will need to be able to retrieve files from a server
|
||||
running Dropbear via SCP.
|
||||
|
||||
Replacing OpenSSH "sshd" with Dropbear
|
||||
--------------------------------------
|
||||
|
||||
You will still want to have the "ssh" package installed, as it
|
||||
provides the "ssh" and "scp" binaries. When you install this
|
||||
package, it checks for existing OpenSSH host keys and if found,
|
||||
converts them to the Dropbear format.
|
||||
|
||||
If this appears to have worked, you should be able to change over
|
||||
by following these steps:
|
||||
|
||||
1. Stop the OpenSSH server
|
||||
% /etc/init.d/ssh stop
|
||||
2. Prevent the OpenSSH server from starting in the future
|
||||
% touch /etc/ssh/sshd_not_to_be_run
|
||||
3. Modify the Dropbear defaults file, set NO_START to 0 and
|
||||
ensure DROPBEAR_PORT is set to 22.
|
||||
% editor /etc/default/dropbear
|
||||
4. Restart the Dropbear server.
|
||||
% /etc/init.d/dropbear restart
|
||||
|
||||
See the Dropbear homepage for more information:
|
||||
http://matt.ucc.asn.au/dropbear/dropbear.html
|
||||
|
||||
15
debian/README.Debian.diet
vendored
Normal file
15
debian/README.Debian.diet
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
Building with the diet libc
|
||||
---------------------------
|
||||
|
||||
This package optionally can be built with the diet libc instead of the
|
||||
glibc to provide small statically linked programs. The resulting package
|
||||
has no dependency on any other package.
|
||||
|
||||
To use the diet libc, make sure the latest versions of the dietlibc-dev
|
||||
package is installed, and set DEB_BUILD_OPTIONS=diet in the environment
|
||||
when building the package, e.g.:
|
||||
|
||||
# apt-get install dietlibc-dev
|
||||
$ DEB_BUILD_OPTIONS=diet fakeroot apt-get source -b dropbear
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org>, Sat, 17 Jul 2004 19:09:34 +0000
|
||||
46
debian/README.runit
vendored
Normal file
46
debian/README.runit
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
Using the dropbear SSH server with runit's services supervision
|
||||
---------------------------------------------------------------
|
||||
|
||||
The dropbear SSH server is perfectly suited to be run under runit's
|
||||
service supervision, and this package already has prepared an adequate
|
||||
service directory. Follow these steps to enable the dropbear service
|
||||
using the runit package.
|
||||
|
||||
If not yet installed on your system, install the runit package, and make
|
||||
sure its service supervision is enabled (it's by default)
|
||||
|
||||
# apt-get install runit
|
||||
|
||||
Make sure the dropbear service normally handled through the sysv init
|
||||
script is stopped
|
||||
|
||||
# /etc/init.d/dropbear stop
|
||||
|
||||
Create the system user ``dropbearlog'' which will run the logger service,
|
||||
and own the logs
|
||||
|
||||
# adduser --system --home /var/log/dropbear --no-create-home dropbearlog
|
||||
|
||||
Create the log directory and make the newly created system user the owner
|
||||
of this directory
|
||||
|
||||
# mkdir -p /var/log/dropbear && chown dropbearlog /var/log/dropbear
|
||||
|
||||
Optionally adjust the configuration of the dropbear service by editing the
|
||||
run script
|
||||
|
||||
# vi /etc/dropbear/run
|
||||
|
||||
Finally enable the service through runit's update-service(8) program, the
|
||||
service will be started within five seconds, and automatically at boot
|
||||
time, and the sysv init script will automatically be disabled; see the
|
||||
sv(8) program for information on how to control services handled by runit.
|
||||
See the svlogd(8) program on how to configure the log service.
|
||||
|
||||
# update-service --add /etc/dropbear
|
||||
|
||||
Optionally check the status of the service a few seconds later
|
||||
|
||||
# sv status dropbear
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org>, Fri, 02 Mar 2007 20:41:08 +0000
|
||||
316
debian/changelog
vendored
Normal file
316
debian/changelog
vendored
Normal file
@@ -0,0 +1,316 @@
|
||||
dropbear (0.52-2) unstable; urgency=low
|
||||
|
||||
* Make key utils part of dropbear-server package (since it's
|
||||
required anyway, single binary saves space), rename -common to
|
||||
-keyutils
|
||||
* Don't make clean between builds, just rm *.o since only
|
||||
top-level files change
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Wed, 19 Nov 2008 21:54:00 +0900
|
||||
|
||||
dropbear (0.52-1) unstable; urgency=low
|
||||
|
||||
* Maemo port, split into 5 packages
|
||||
(dropbear, dropbear-server, dropbear-client, dropbear-common, dropbear-scp).
|
||||
This avoids conflicts with openssh package.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Wed, 19 Nov 2008 20:54:00 +0900
|
||||
|
||||
dropbear (0.52-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Wed, 12 Nov 2008 22:54:00 +0900
|
||||
|
||||
dropbear (0.51-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Thu, 27 Mar 2008 19:14:00 +0900
|
||||
|
||||
dropbear (0.50-4) unstable; urgency=low
|
||||
|
||||
* debian/dropbear.init: apply patch from Petter Reinholdtsen: add LSB
|
||||
formatted dependency info in init.d script (closes: #466257).
|
||||
* debian/rules: no longer include symlinks for ./supervise/ subdirectories.
|
||||
* debian/dropbear.postinst: upgrade from << 0.50-4: if dropbear is managed
|
||||
by runit, remove service, and re-add using update-service(8).
|
||||
* debian/control: Standards-Version: 3.7.3.0.
|
||||
* debian/rules: target clean: don't ignore errors but check for readable
|
||||
./Makefile.
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org> Thu, 06 Mar 2008 19:06:58 +0000
|
||||
|
||||
dropbear (0.50-3) unstable; urgency=low
|
||||
|
||||
* debian/dropbear.init: use the update-service(8) program from the runit
|
||||
package instead of directly checking for the symlink in /var/service/.
|
||||
* debian/README.runit: talk about update-service(8) instead of symlinks
|
||||
in /var/service/.
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org> Fri, 15 Feb 2008 00:32:37 +0000
|
||||
|
||||
dropbear (0.50-2) unstable; urgency=low
|
||||
|
||||
* debian/dropbear.README.Debian: no longer talk about entropy from
|
||||
/dev/random, /dev/urandom is now used by default (thx Joey Hess,
|
||||
closes: #441515).
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org> Mon, 24 Sep 2007 16:49:17 +0000
|
||||
|
||||
dropbear (0.50-1) unstable; urgency=low
|
||||
|
||||
* debian/README.runit: minor.
|
||||
* new upstream version.
|
||||
* debian/diff/0001-options.h-use-dev-urandom-instead-of-dev-random-a.diff:
|
||||
remove; fixed upstream.
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org> Thu, 09 Aug 2007 23:01:01 +0000
|
||||
|
||||
dropbear (0.49-2) unstable; urgency=low
|
||||
|
||||
* debian/rules: apply diffs from debian/diff/ with patch -p1 instead of
|
||||
-p0.
|
||||
* debian/diff/0001-options.h-use-dev-urandom-instead-of-dev-random-a.diff:
|
||||
new; options.h: use /dev/urandom instead of /dev/random as
|
||||
DROPBEAR_RANDOM_DEV (closes: #386976).
|
||||
* debian/rules: target clean: remove libtomcrypt/Makefile,
|
||||
libtommath/Makefile.
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org> Sat, 09 Jun 2007 08:59:59 +0000
|
||||
|
||||
dropbear (0.49-1) unstable; urgency=high
|
||||
|
||||
* new upstream release, fixes
|
||||
* CVE-2007-1099: dropbear dbclient insufficient warning on hostkey
|
||||
mismatch (closes: #412899).
|
||||
* dbclient uses static "Password:" prompt instead of using the server's
|
||||
prompt (closes: #394996).
|
||||
* debian/control: Suggests: openssh-client, not ssh (closes: #405686);
|
||||
Standards-Version: 3.7.2.2.
|
||||
* debian/README.Debian: ssh -> openssh-server, openssh-client; remove
|
||||
'Replacing OpenSSH "sshd" with Dropbear' part, this is simply done by not
|
||||
installing the openssh-server package.
|
||||
* debian/README.runit: runsvstat -> sv status.
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org> Fri, 2 Mar 2007 20:48:18 +0000
|
||||
|
||||
dropbear (0.48.1-1) unstable; urgency=medium
|
||||
|
||||
* new upstream point release.
|
||||
* Compile fix for scp
|
||||
* debian/diff/dbclient.1.diff: new: document -R option to dbclient
|
||||
accurately (thx Markus Schaber; closes: #351882).
|
||||
* debian/dropbear.README.Debian: document a workaround for systems with
|
||||
possibly blocking /dev/random device (closes: #355414)..
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org> Sun, 16 Apr 2006 16:16:40 +0000
|
||||
|
||||
dropbear (0.48-1) unstable; urgency=medium
|
||||
|
||||
* New upstream release.
|
||||
* SECURITY: Improve handling of denial of service attempts from a single
|
||||
IP.
|
||||
|
||||
* debian/implicit: update to revision 1.11.
|
||||
* new upstream release updates to scp from OpenSSH 4.3p2 - fixes a
|
||||
security issue where use of system() could cause users to execute
|
||||
arbitrary code through malformed filenames; CVE-2006-0225 (see also
|
||||
#349645); the scp binary is not provided by this package though.
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org> Fri, 10 Mar 2006 22:00:32 +0000
|
||||
|
||||
dropbear (0.47-1) unstable; urgency=high
|
||||
|
||||
* New upstream release.
|
||||
* SECURITY: Fix incorrect buffer sizing; CVE-2005-4178.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Thu, 8 Dec 2005 19:20:21 +0800
|
||||
|
||||
dropbear (0.46-2) unstable; urgency=low
|
||||
|
||||
* debian/control: Standards-Version: 3.6.2.1; update descriptions to
|
||||
mention included server and client (thx Tino Keitel).
|
||||
* debian/dropbear.init: allow '/etc/init.d/dropbear stop' even though
|
||||
'NO_START is not set to zero.' (closes: #336723).
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org> Tue, 6 Dec 2005 13:30:49 +0000
|
||||
|
||||
dropbear (0.46-1) unstable; urgency=medium
|
||||
|
||||
* New upstream release, various fixes.
|
||||
* debian/diff/dbclient-usage-typo.diff, debian/diff/manpages.diff: remove;
|
||||
obsolete.
|
||||
* debian/dbclient.1: move to ./dbclient.1.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Fri, 8 July 2005 21:32:55 +0800
|
||||
|
||||
dropbear (0.45-3) unstable; urgency=low
|
||||
|
||||
* debian/dropbear.init: init script prints human readable message in case
|
||||
it's disabled (closes: #309099).
|
||||
* debian/dropbear.postinst: configure: restart service through init script
|
||||
instead of start.
|
||||
* debian/dropbear.prerm: set -u -> set -e.
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org> Wed, 25 May 2005 22:38:17 +0000
|
||||
|
||||
dropbear (0.45-2) unstable; urgency=low
|
||||
|
||||
* Matt Johnston:
|
||||
* New upstream release, various fixes.
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org> Sat, 12 Mar 2005 15:17:55 +0000
|
||||
|
||||
dropbear (0.44-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* debian/rules: install /usr/bin/dbclient; handle possible patches more
|
||||
gracefully; install debian/dbclient.1 man page; enable target patch;
|
||||
minor.
|
||||
* debian/implicit: update to revision 1.10.
|
||||
* debian/dbclient.1: new; man page.
|
||||
* debian/diff/dbclient-usage-typo.diff: new; fix typo.
|
||||
* debian/diff/manpages.diff: new; add references to dbclient man page.
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org> Sat, 8 Jan 2005 22:50:43 +0000
|
||||
|
||||
dropbear (0.43-2) unstable; urgency=high
|
||||
|
||||
* Matt Johnston:
|
||||
* New upstream release 0.43
|
||||
* SECURITY: Don't attempt to free uninitialised buffers in DSS verification
|
||||
code
|
||||
* Handle portforwarding to servers which don't send any initial data
|
||||
(Closes: #258426)
|
||||
* debian/dropbear.postinst: remove code causing bothersome warning on
|
||||
package install (closes: #256752).
|
||||
* debian/README.Debian.diet: new; how to build with the diet libc.
|
||||
* debian/dropbear.docs: add debian/README.Debian.diet.
|
||||
* debian/rules: support "diet" in DEB_BUILD_OPTIONS; minor cleanup.
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org> Sat, 17 Jul 2004 19:31:19 +0000
|
||||
|
||||
dropbear (0.42-1) unstable; urgency=low
|
||||
|
||||
* New upstream release 0.42.
|
||||
* debian/diff/cvs-20040520.diff: remove; obsolete.
|
||||
* debian/rules: disable target patch.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Wed, 16 June 2004 12:44:54 +0800
|
||||
|
||||
dropbear (0.41-3) unstable; urgency=low
|
||||
|
||||
* 1st upload to the Debian archive (closes: #216553).
|
||||
* debian/diff/cvs-20040520.diff: new; stable cvs snapshot.
|
||||
* debian/rules: new target patch: apply diffs in debian/diff/, reverse
|
||||
apply in target clean; install man pages.
|
||||
* debian/control: Priority: optional.
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org> Sun, 23 May 2004 08:32:37 +0000
|
||||
|
||||
dropbear (0.41-2) unstable; urgency=low
|
||||
|
||||
* new maintainer.
|
||||
* debian/control: no longer Build-Depends: debhelper; Build-Depends:
|
||||
libz-dev; Standards-Version: 3.6.1.0; Suggests: runit; update
|
||||
descriptions.
|
||||
* debian/rules: stop using debhelper, use implicit rules; cleanup;
|
||||
install dropbearconvert into /usr/lib/dropbear/.
|
||||
* debian/impicit: new; implicit rules.
|
||||
* debian/copyright.in: adapt.
|
||||
* debian/dropbear.init: minor adaptions; test for dropbear service
|
||||
directory.
|
||||
* debian/README.runit: new; how to use dropbear with runit.
|
||||
* debian/README.Debian, debian/docs: rename to debian/dropbear.*.
|
||||
* debian/dropbear.docs: add debian/README.runit
|
||||
* debian/conffiles: rename to debian/dropbear.conffiles; add init
|
||||
script, and run scripts.
|
||||
* debian/postinst: rename to debian/dropbear.postinst; adapt; use
|
||||
invloke-rc.d dropbear start.
|
||||
* debian/dropbear.prerm: new; invoke-rc.d dropbear stop.
|
||||
* debian/postrm: rename to debian/dropbear.postrm; adapt; clean up
|
||||
service directories.
|
||||
* debian/compat, debian/dirs, dropbear.default: remove; obsolete.
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org> Sun, 16 May 2004 16:50:55 +0000
|
||||
|
||||
dropbear (0.41-1) unstable; urgency=low
|
||||
|
||||
* Updated to 0.41 release.
|
||||
* Various minor fixes
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Mon, 19 Jan 2004 23:20:54 +0800
|
||||
|
||||
dropbear (0.39-1) unstable; urgency=low
|
||||
|
||||
* updated to 0.39 release. Some new features, some bugfixes.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Tue, 16 Dec 2003 16:20:54 +0800
|
||||
|
||||
dropbear (0.38-1) unstable; urgency=medium
|
||||
|
||||
* updated to 0.38 release - various important bugfixes
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Sat, 11 Oct 2003 16:28:54 +0800
|
||||
|
||||
dropbear (0.37-1) unstable; urgency=medium
|
||||
|
||||
* updated to 0.37 release - various important bugfixes
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Wed, 24 Sept 2003 19:43:54 +0800
|
||||
|
||||
dropbear (0.36-1) unstable; urgency=high
|
||||
|
||||
* updated to 0.36 release - various important bugfixes
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Tues, 19 Aug 2003 12:20:54 +0800
|
||||
|
||||
dropbear (0.35-1) unstable; urgency=high
|
||||
|
||||
* updated to 0.35 release - contains fix for remotely exploitable
|
||||
vulnerability.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Sun, 17 Aug 2003 05:37:47 +0800
|
||||
|
||||
dropbear (0.34-1) unstable; urgency=medium
|
||||
|
||||
* updated to 0.34 release
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Fri, 15 Aug 2003 15:10:00 +0800
|
||||
|
||||
dropbear (0.33-1) unstable; urgency=medium
|
||||
|
||||
* updated to 0.33 release
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Sun, 22 Jun 2003 22:22:00 +0800
|
||||
|
||||
dropbear (0.32cvs-1) unstable; urgency=medium
|
||||
|
||||
* now maintained in UCC CVS
|
||||
* debian/copyright.in file added, generated from LICENSE
|
||||
|
||||
-- Grahame Bowland <grahame@angrygoats.net> Tue, 21 Jun 2003 17:57:02 +0800
|
||||
|
||||
dropbear (0.32cvs-1) unstable; urgency=medium
|
||||
|
||||
* sync with CVS
|
||||
* fixes X crash bug
|
||||
|
||||
-- Grahame Bowland <grahame@angrygoats.net> Tue, 20 Jun 2003 15:04:47 +0800
|
||||
|
||||
dropbear (0.32-2) unstable; urgency=low
|
||||
|
||||
* fix creation of host keys to use correct names in /etc/dropbear
|
||||
* init script "restart" function fixed
|
||||
* purging this package now deletes the host keys and /etc/dropbear
|
||||
* change priority in debian/control to 'standard'
|
||||
|
||||
-- Grahame Bowland <grahame@angrygoats.net> Tue, 17 Jun 2003 15:04:47 +0800
|
||||
|
||||
dropbear (0.32-1) unstable; urgency=low
|
||||
|
||||
* Initial Release.
|
||||
|
||||
-- Grahame Bowland <grahame@angrygoats.net> Tue, 17 Jun 2003 15:04:47 +0800
|
||||
|
||||
95
debian/control
vendored
Normal file
95
debian/control
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
Source: dropbear
|
||||
Section: user/network
|
||||
Priority: optional
|
||||
Maintainer: Matt Johnston <matt@ucc.asn.au>
|
||||
Build-Depends: libz-dev
|
||||
Standards-Version: 3.7.3.0
|
||||
|
||||
Package: dropbear
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}
|
||||
Suggests: openssh-client, runit
|
||||
Section: user/network
|
||||
Conflicts: dropbear-server, dropbear-client, dropbear-keyutils, dropbear-scp
|
||||
XB-Maemo-Display-Name: Dropbear SSH Client and Server
|
||||
Description: lightweight SSH2 server and client
|
||||
dropbear is a SSH 2 server and client designed to be small enough to
|
||||
be used in small memory environments, while still being functional and
|
||||
secure enough for general use.
|
||||
.
|
||||
It implements most required features of the SSH 2 protocol, and other
|
||||
features such as X11 and authentication agent forwarding.
|
||||
.
|
||||
This package provides Dropbear client and server as a single binary,
|
||||
as well as key utilities and SCP.
|
||||
.
|
||||
See http://matt.ucc.asn.au/dropbear/dropbear.html
|
||||
|
||||
Package: dropbear-server
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}
|
||||
Section: user/network
|
||||
Conflicts: dropbear, dropbear-keyutils
|
||||
Provides: dropbear-keyutils
|
||||
Recommends: dropbear-scp
|
||||
XB-Maemo-Display-Name: Dropbear SSH Server
|
||||
Description: lightweight SSH2 server
|
||||
dropbear is a SSH 2 server and client designed to be small enough to
|
||||
be used in small memory environments, while still being functional and
|
||||
secure enough for general use.
|
||||
.
|
||||
It implements most required features of the SSH 2 protocol, and other
|
||||
features such as X11 and authentication agent forwarding.
|
||||
.
|
||||
This package provides only the Dropbear server.
|
||||
.
|
||||
See http://matt.ucc.asn.au/dropbear/dropbear.html
|
||||
|
||||
Package: dropbear-client
|
||||
Architecture: any
|
||||
Conflicts: dropbear
|
||||
Section: user/network
|
||||
Depends: ${shlibs:Depends}
|
||||
Recommends: dropbear-scp
|
||||
Suggests: dropbear-keyutils
|
||||
XB-Maemo-Display-Name: Dropbear SSH Client
|
||||
Description: lightweight SSH2 client
|
||||
dropbear is a SSH 2 server and client designed to be small enough to
|
||||
be used in small memory environments, while still being functional and
|
||||
secure enough for general use.
|
||||
.
|
||||
It implements most required features of the SSH 2 protocol, and other
|
||||
features such as X11 and authentication agent forwarding.
|
||||
.
|
||||
This package provides only the Dropbear client.
|
||||
.
|
||||
See http://matt.ucc.asn.au/dropbear/dropbear.html
|
||||
|
||||
Package: dropbear-keyutils
|
||||
Architecture: any
|
||||
Conflicts: dropbear, dropbear-server
|
||||
Section: user/network
|
||||
XB-Maemo-Display-Name: Dropbear SSH Key Utils
|
||||
Depends: ${shlibs:Depends}
|
||||
Description: lightweight SSH2, key management utilities
|
||||
dropbear is a SSH 2 server and client designed to be small enough to
|
||||
be used in small memory environments, while still being functional and
|
||||
secure enough for general use.
|
||||
.
|
||||
This package provides dropbearkey and dropbearconvert programs,
|
||||
for generating keys and converting to/from OpenSSH keys.
|
||||
.
|
||||
See http://matt.ucc.asn.au/dropbear/dropbear.html
|
||||
|
||||
Package: dropbear-scp
|
||||
Architecture: any
|
||||
Section: user/network
|
||||
Conflicts: dropbear
|
||||
XB-Maemo-Display-Name: Dropbear SCP
|
||||
Depends: ${shlibs:Depends}
|
||||
Description: lightweight SSH2 scp
|
||||
dropbear is a SSH 2 server and client designed to be small enough to
|
||||
be used in small memory environments, while still being functional and
|
||||
secure enough for general use.
|
||||
.
|
||||
This dropbear-scp package provides /usr/bin/scp.
|
||||
11
debian/copyright.in
vendored
Normal file
11
debian/copyright.in
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
This package was debianized by Grahame Bowland <grahame.angrygoats.net> on
|
||||
Tue, 17 Jun 2003 15:04:47 +0800, maintained temporarily by Matt Johnston
|
||||
<matt@ucc.asn.au>, and was adopted by Gerrit Pape <pape@smarden.org> on
|
||||
Sun, 16 May 2004 14:38:33 +0000.
|
||||
|
||||
It was downloaded from http://matt.ucc.asn.au/dropbear/
|
||||
|
||||
Upstream Author: Matt Johnston <matt@ucc.asn.au>
|
||||
|
||||
Copyright:
|
||||
|
||||
3
debian/dropbear-server.conffiles
vendored
Normal file
3
debian/dropbear-server.conffiles
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/etc/init.d/dropbear
|
||||
/etc/dropbear/run
|
||||
/etc/dropbear/log/run
|
||||
79
debian/dropbear-server.postinst
vendored
Normal file
79
debian/dropbear-server.postinst
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
test "$1" = 'configure' || exit 0
|
||||
|
||||
if test ! -e /etc/dropbear/dropbear_rsa_host_key; then
|
||||
if test -f /etc/ssh/ssh_host_rsa_key; then
|
||||
echo "Converting existing OpenSSH RSA host key to Dropbear format."
|
||||
/usr/lib/dropbear/dropbearconvert openssh dropbear \
|
||||
/etc/ssh/ssh_host_rsa_key /etc/dropbear/dropbear_rsa_host_key
|
||||
else
|
||||
echo "Generating Dropbear RSA key. Please wait."
|
||||
dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
|
||||
fi
|
||||
fi
|
||||
if test ! -e /etc/dropbear/dropbear_dss_host_key; then
|
||||
if test -f /etc/ssh/ssh_host_dsa_key; then
|
||||
echo "Converting existing OpenSSH RSA host key to Dropbear format."
|
||||
/usr/lib/dropbear/dropbearconvert openssh dropbear \
|
||||
/etc/ssh/ssh_host_dsa_key /etc/dropbear/dropbear_dss_host_key
|
||||
else
|
||||
echo "Generating Dropbear DSS key. Please wait."
|
||||
dropbearkey -t dss -f /etc/dropbear/dropbear_dss_host_key
|
||||
fi
|
||||
fi
|
||||
if test ! -s /etc/default/dropbear; then
|
||||
# check whether OpenSSH seems to be installed.
|
||||
if test -x /usr/sbin/sshd; then
|
||||
cat <<EOT
|
||||
OpenSSH appears to be installed. Setting /etc/default/dropbear so that
|
||||
Dropbear will not start by default. Edit this file to change this behaviour.
|
||||
|
||||
EOT
|
||||
cat >>/etc/default/dropbear <<EOT
|
||||
# disabled because OpenSSH is installed
|
||||
# change to NO_START=0 to enable Dropbear
|
||||
NO_START=1
|
||||
|
||||
EOT
|
||||
fi
|
||||
cat >>/etc/default/dropbear <<EOT
|
||||
# the TCP port that Dropbear listens on
|
||||
DROPBEAR_PORT=22
|
||||
|
||||
# any additional arguments for Dropbear
|
||||
DROPBEAR_EXTRA_ARGS=
|
||||
|
||||
# specify an optional banner file containing a message to be
|
||||
# sent to clients before they connect, such as "/etc/issue.net"
|
||||
DROPBEAR_BANNER=""
|
||||
|
||||
# RSA hostkey file (default: /etc/dropbear/dropbear_rsa_host_key)
|
||||
#DROPBEAR_RSAKEY="/etc/dropbear/dropbear_rsa_host_key"
|
||||
|
||||
# DSS hostkey file (default: /etc/dropbear/dropbear_dss_host_key)
|
||||
#DROPBEAR_DSSKEY="/etc/dropbear/dropbear_dss_host_key"
|
||||
|
||||
# Receive window size - this is a tradeoff between memory and
|
||||
# network performance
|
||||
DROPBEAR_RECEIVE_WINDOW=65536
|
||||
EOT
|
||||
fi
|
||||
|
||||
if test -x /etc/init.d/dropbear; then
|
||||
update-rc.d dropbear defaults >/dev/null
|
||||
if test -x /usr/sbin/invoke-rc.d; then
|
||||
invoke-rc.d dropbear restart
|
||||
else
|
||||
/etc/init.d/dropbear restart
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$2" && dpkg --compare-versions "$2" lt '0.50-4' &&
|
||||
update-service --check dropbear 2>/dev/null; then
|
||||
update-service --remove /etc/dropbear 2>/dev/null || :
|
||||
sleep 6
|
||||
rm -rf /var/run/dropbear /var/run/dropbear.log
|
||||
update-service --add /etc/dropbear || :
|
||||
fi
|
||||
12
debian/dropbear-server.postrm
vendored
Normal file
12
debian/dropbear-server.postrm
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#! /bin/sh
|
||||
set -e
|
||||
|
||||
test "$1" = 'purge' || exit 0
|
||||
if test -e /etc/dropbear; then
|
||||
rm -f /etc/dropbear/dropbear_rsa_host_key
|
||||
rm -f /etc/dropbear/dropbear_dss_host_key
|
||||
rmdir --ignore-fail-on-non-empty /etc/dropbear
|
||||
fi
|
||||
update-rc.d dropbear remove >/dev/null
|
||||
rm -f /etc/default/dropbear
|
||||
rm -rf /etc/dropbear/supervise /etc/dropbear/log/supervise
|
||||
11
debian/dropbear-server.prerm
vendored
Normal file
11
debian/dropbear-server.prerm
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
test "$1" = 'remove' || test "$1" = 'deconfigure' || exit 0
|
||||
if test -x /etc/init.d/dropbear; then
|
||||
if test -x /usr/sbin/invoke-rc.d; then
|
||||
invoke-rc.d dropbear stop
|
||||
else
|
||||
/etc/init.d/dropbear stop
|
||||
fi
|
||||
fi
|
||||
19
debian/dropbear.README.Debian
vendored
Normal file
19
debian/dropbear.README.Debian
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Dropbear for Debian
|
||||
-------------------
|
||||
|
||||
This package will attempt to setup the Dropbear ssh server to listen on
|
||||
port 22. If the OpenSSH server package ("openssh-server") is installed,
|
||||
the file /etc/default/dropbear will be set up so that the server does not
|
||||
start by default.
|
||||
|
||||
You can run Dropbear concurrently with OpenSSH 'sshd' by modifying
|
||||
/etc/default/dropbear so that "NO_START" is set to "0", and changing the
|
||||
port number that Dropbear runs on. Follow the instructions in the file.
|
||||
|
||||
This package suggests you install the "openssh-client" package, which
|
||||
provides the "ssh" client program, as well as the "/usr/bin/scp" binary
|
||||
you will need to be able to retrieve files via SCP from a server running
|
||||
Dropbear.
|
||||
|
||||
See the Dropbear homepage for more information:
|
||||
http://matt.ucc.asn.au/dropbear/dropbear.html
|
||||
3
debian/dropbear.conffiles
vendored
Normal file
3
debian/dropbear.conffiles
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/etc/init.d/dropbear
|
||||
/etc/dropbear/run
|
||||
/etc/dropbear/log/run
|
||||
4
debian/dropbear.docs
vendored
Normal file
4
debian/dropbear.docs
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
README
|
||||
TODO
|
||||
debian/README.runit
|
||||
debian/README.Debian.diet
|
||||
70
debian/dropbear.init
vendored
Normal file
70
debian/dropbear.init
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: dropbear
|
||||
# Required-Start: $remote_fs $syslog
|
||||
# Required-Stop: $remote_fs $syslog
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
### END INIT INFO
|
||||
#
|
||||
# Do not configure this file. Edit /etc/default/dropbear instead!
|
||||
#
|
||||
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
||||
DAEMON=/usr/sbin/dropbear
|
||||
NAME=dropbear
|
||||
DESC="Dropbear SSH server"
|
||||
|
||||
DROPBEAR_PORT=22
|
||||
DROPBEAR_EXTRA_ARGS=
|
||||
NO_START=0
|
||||
|
||||
set -e
|
||||
|
||||
cancel() { echo "$1" >&2; exit 0; };
|
||||
test ! -r /etc/default/dropbear || . /etc/default/dropbear
|
||||
test -x "$DAEMON" || cancel "$DAEMON does not exist or is not executable."
|
||||
test ! -x /usr/sbin/update-service || ! update-service --check dropbear ||
|
||||
cancel 'The dropbear service is controlled through runit, use the sv(8) program'
|
||||
|
||||
test -z "$DROPBEAR_BANNER" || \
|
||||
DROPBEAR_EXTRA_ARGS="$DROPBEAR_EXTRA_ARGS -b $DROPBEAR_BANNER"
|
||||
test -n "$DROPBEAR_RSAKEY" || \
|
||||
DROPBEAR_RSAKEY="/etc/dropbear/dropbear_rsa_host_key"
|
||||
test -n "$DROPBEAR_DSSKEY" || \
|
||||
DROPBEAR_DSSKEY="/etc/dropbear/dropbear_dss_host_key"
|
||||
test -n "$DROPBEAR_RECEIVE_WINDOW" || \
|
||||
DROPBEAR_RECEIVE_WINDOW="65536"
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
test "$NO_START" = "0" || cancel '/etc/default/dropbear NO_START is set, Dropbear will not run.'
|
||||
echo -n "Starting $DESC: "
|
||||
start-stop-daemon --start --quiet --pidfile /var/run/"$NAME".pid \
|
||||
--exec "$DAEMON" -- -d "$DROPBEAR_DSSKEY" -r "$DROPBEAR_RSAKEY" \
|
||||
-p "$DROPBEAR_PORT" -W "$DROPBEAR_RECEIVE_WINDOW" $DROPBEAR_EXTRA_ARGS
|
||||
echo "$NAME."
|
||||
;;
|
||||
stop)
|
||||
echo -n "Stopping $DESC: "
|
||||
start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/"$NAME".pid
|
||||
echo "$NAME."
|
||||
;;
|
||||
restart|force-reload)
|
||||
test "$NO_START" = "0" || cancel '/etc/default/dropbear NO_START is set, Dropbear will not run.'
|
||||
echo -n "Restarting $DESC: "
|
||||
start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/"$NAME".pid
|
||||
sleep 1
|
||||
start-stop-daemon --start --quiet --pidfile /var/run/"$NAME".pid \
|
||||
--exec "$DAEMON" -- -d "$DROPBEAR_DSSKEY" -r "$DROPBEAR_RSAKEY" \
|
||||
-p "$DROPBEAR_PORT" -W "$DROPBEAR_RECEIVE_WINDOW" $DROPBEAR_EXTRA_ARGS
|
||||
echo "$NAME."
|
||||
;;
|
||||
*)
|
||||
N=/etc/init.d/$NAME
|
||||
echo "Usage: $N {start|stop|restart|force-reload}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
79
debian/dropbear.postinst
vendored
Normal file
79
debian/dropbear.postinst
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
test "$1" = 'configure' || exit 0
|
||||
|
||||
if test ! -e /etc/dropbear/dropbear_rsa_host_key; then
|
||||
if test -f /etc/ssh/ssh_host_rsa_key; then
|
||||
echo "Converting existing OpenSSH RSA host key to Dropbear format."
|
||||
/usr/lib/dropbear/dropbearconvert openssh dropbear \
|
||||
/etc/ssh/ssh_host_rsa_key /etc/dropbear/dropbear_rsa_host_key
|
||||
else
|
||||
echo "Generating Dropbear RSA key. Please wait."
|
||||
dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
|
||||
fi
|
||||
fi
|
||||
if test ! -e /etc/dropbear/dropbear_dss_host_key; then
|
||||
if test -f /etc/ssh/ssh_host_dsa_key; then
|
||||
echo "Converting existing OpenSSH RSA host key to Dropbear format."
|
||||
/usr/lib/dropbear/dropbearconvert openssh dropbear \
|
||||
/etc/ssh/ssh_host_dsa_key /etc/dropbear/dropbear_dss_host_key
|
||||
else
|
||||
echo "Generating Dropbear DSS key. Please wait."
|
||||
dropbearkey -t dss -f /etc/dropbear/dropbear_dss_host_key
|
||||
fi
|
||||
fi
|
||||
if test ! -s /etc/default/dropbear; then
|
||||
# check whether OpenSSH seems to be installed.
|
||||
if test -x /usr/sbin/sshd; then
|
||||
cat <<EOT
|
||||
OpenSSH appears to be installed. Setting /etc/default/dropbear so that
|
||||
Dropbear will not start by default. Edit this file to change this behaviour.
|
||||
|
||||
EOT
|
||||
cat >>/etc/default/dropbear <<EOT
|
||||
# disabled because OpenSSH is installed
|
||||
# change to NO_START=0 to enable Dropbear
|
||||
NO_START=1
|
||||
|
||||
EOT
|
||||
fi
|
||||
cat >>/etc/default/dropbear <<EOT
|
||||
# the TCP port that Dropbear listens on
|
||||
DROPBEAR_PORT=22
|
||||
|
||||
# any additional arguments for Dropbear
|
||||
DROPBEAR_EXTRA_ARGS=
|
||||
|
||||
# specify an optional banner file containing a message to be
|
||||
# sent to clients before they connect, such as "/etc/issue.net"
|
||||
DROPBEAR_BANNER=""
|
||||
|
||||
# RSA hostkey file (default: /etc/dropbear/dropbear_rsa_host_key)
|
||||
#DROPBEAR_RSAKEY="/etc/dropbear/dropbear_rsa_host_key"
|
||||
|
||||
# DSS hostkey file (default: /etc/dropbear/dropbear_dss_host_key)
|
||||
#DROPBEAR_DSSKEY="/etc/dropbear/dropbear_dss_host_key"
|
||||
|
||||
# Receive window size - this is a tradeoff between memory and
|
||||
# network performance
|
||||
DROPBEAR_RECEIVE_WINDOW=65536
|
||||
EOT
|
||||
fi
|
||||
|
||||
if test -x /etc/init.d/dropbear; then
|
||||
update-rc.d dropbear defaults >/dev/null
|
||||
if test -x /usr/sbin/invoke-rc.d; then
|
||||
invoke-rc.d dropbear restart
|
||||
else
|
||||
/etc/init.d/dropbear restart
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$2" && dpkg --compare-versions "$2" lt '0.50-4' &&
|
||||
update-service --check dropbear 2>/dev/null; then
|
||||
update-service --remove /etc/dropbear 2>/dev/null || :
|
||||
sleep 6
|
||||
rm -rf /var/run/dropbear /var/run/dropbear.log
|
||||
update-service --add /etc/dropbear || :
|
||||
fi
|
||||
12
debian/dropbear.postrm
vendored
Normal file
12
debian/dropbear.postrm
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#! /bin/sh
|
||||
set -e
|
||||
|
||||
test "$1" = 'purge' || exit 0
|
||||
if test -e /etc/dropbear; then
|
||||
rm -f /etc/dropbear/dropbear_rsa_host_key
|
||||
rm -f /etc/dropbear/dropbear_dss_host_key
|
||||
rmdir --ignore-fail-on-non-empty /etc/dropbear
|
||||
fi
|
||||
update-rc.d dropbear remove >/dev/null
|
||||
rm -f /etc/default/dropbear
|
||||
rm -rf /etc/dropbear/supervise /etc/dropbear/log/supervise
|
||||
11
debian/dropbear.prerm
vendored
Normal file
11
debian/dropbear.prerm
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
test "$1" = 'remove' || test "$1" = 'deconfigure' || exit 0
|
||||
if test -x /etc/init.d/dropbear; then
|
||||
if test -x /usr/sbin/invoke-rc.d; then
|
||||
invoke-rc.d dropbear stop
|
||||
else
|
||||
/etc/init.d/dropbear stop
|
||||
fi
|
||||
fi
|
||||
93
debian/implicit
vendored
Normal file
93
debian/implicit
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
# $Id: implicit,v 1.11 2005/11/29 21:57:55 pape Exp $
|
||||
|
||||
.PHONY: deb-checkdir deb-checkuid
|
||||
|
||||
deb-checkdir:
|
||||
@test -e debian/control || sh -cx '! : wrong directory'
|
||||
deb-checkuid:
|
||||
@test "`id -u`" -eq 0 || sh -cx '! : need root privileges'
|
||||
|
||||
%.deb: %.deb-docs %.deb-DEBIAN
|
||||
@rm -f $*.deb $*.deb-checkdir $*.deb-docs $*.deb-docs-base \
|
||||
$*.deb-docs-docs $*.deb-docs-examples $*.deb-DEBIAN \
|
||||
$*.deb-DEBIAN-dir $*.deb-DEBIAN-scripts $*.deb-DEBIAN-md5sums
|
||||
|
||||
%.udeb: %.deb-DEBIAN
|
||||
@rm -f $*.deb $*.deb-checkdir $*.deb-DEBIAN $*.deb-DEBIAN-dir \
|
||||
$*.deb-DEBIAN-scripts $*.deb-DEBIAN-md5sums
|
||||
|
||||
%.deb-checkdir:
|
||||
@test -d debian/$* || sh -cx '! : directory debian/$* missing'
|
||||
@test "`id -u`" -eq 0 || sh -cx '! : need root privileges'
|
||||
|
||||
%.deb-docs-base:
|
||||
: implicit
|
||||
@rm -f debian/$*/usr/share/doc/$*/* || :
|
||||
@install -d -m0755 debian/$*/usr/share/doc/$*
|
||||
: debian/$*/usr/share/doc/$*/
|
||||
@sh -cx 'install -m0644 debian/copyright debian/$*/usr/share/doc/$*/'
|
||||
@sh -cx 'install -m0644 debian/changelog \
|
||||
debian/$*/usr/share/doc/$*/changelog.Debian'
|
||||
@test ! -r changelog || \
|
||||
sh -cx 'install -m0644 changelog debian/$*/usr/share/doc/$*/'
|
||||
@test -r debian/$*/usr/share/doc/$*/changelog || \
|
||||
sh -cx 'mv debian/$*/usr/share/doc/$*/changelog.Debian \
|
||||
debian/$*/usr/share/doc/$*/changelog'
|
||||
@test -s debian/$*/usr/share/doc/$*/changelog || \
|
||||
sh -cx 'rm -f debian/$*/usr/share/doc/$*/changelog'
|
||||
@gzip -9 debian/$*/usr/share/doc/$*/changelog*
|
||||
%.deb-docs-docs:
|
||||
@for i in `cat debian/$*.docs 2>/dev/null || :`; do \
|
||||
if test -d $$i; then \
|
||||
sh -cx "install -d -m0755 debian/$*/usr/share/doc/$*/$${i##*/}" && \
|
||||
for j in $$i/*; do \
|
||||
sh -cx "install -m0644 $$j \
|
||||
debian/$*/usr/share/doc/$*/$${i##*/}/" || exit 1; \
|
||||
done || exit 1; \
|
||||
continue; \
|
||||
fi; \
|
||||
sh -cx "install -m0644 $$i debian/$*/usr/share/doc/$*/" || exit 1; \
|
||||
done
|
||||
@test ! -r debian/$*.README.Debian || \
|
||||
sh -cx 'install -m0644 debian/$*.README.Debian \
|
||||
debian/$*/usr/share/doc/$*/README.Debian'
|
||||
@if test -r debian/$*.NEWS.Debian; then \
|
||||
sh -cx 'install -m0644 debian/$*.NEWS.Debian \
|
||||
debian/$*/usr/share/doc/$*/NEWS.Debian && \
|
||||
gzip -9 debian/$*/usr/share/doc/$*/NEWS.Debian'; \
|
||||
fi
|
||||
%.deb-docs-examples:
|
||||
@rm -rf debian/$*/usr/share/doc/$*/examples
|
||||
: debian/$*/usr/share/doc/$*/examples/
|
||||
@test ! -r debian/$*.examples || \
|
||||
install -d -m0755 debian/$*/usr/share/doc/$*/examples
|
||||
@for i in `cat debian/$*.examples 2>/dev/null || :`; do \
|
||||
sh -cx "install -m0644 $$i debian/$*/usr/share/doc/$*/examples/" \
|
||||
|| exit 1; \
|
||||
done
|
||||
%.deb-docs: %.deb-checkdir %.deb-docs-base %.deb-docs-docs %.deb-docs-examples
|
||||
: debian/$*/usr/share/doc/$*/ ok
|
||||
|
||||
%.deb-DEBIAN-base:
|
||||
@rm -rf debian/$*/DEBIAN
|
||||
: debian/$*/DEBIAN/
|
||||
@install -d -m0755 debian/$*/DEBIAN
|
||||
@for i in conffiles shlibs templates; do \
|
||||
test ! -r debian/$*.$$i || \
|
||||
sh -cx "install -m0644 debian/$*.$$i debian/$*/DEBIAN/$$i" \
|
||||
|| exit 1; \
|
||||
done
|
||||
%.deb-DEBIAN-scripts:
|
||||
@for i in preinst prerm postinst postrm config; do \
|
||||
test ! -r debian/$*.$$i || \
|
||||
sh -cx "install -m0755 debian/$*.$$i debian/$*/DEBIAN/$$i" \
|
||||
|| exit 1; \
|
||||
done
|
||||
%.deb-DEBIAN-md5sums:
|
||||
: debian/$*/DEBIAN/md5sums
|
||||
@rm -f debian/$*/DEBIAN/md5sums
|
||||
@cd debian/$* && find * -path 'DEBIAN' -prune -o \
|
||||
-type f -exec md5sum {} >>DEBIAN/md5sums \;
|
||||
%.deb-DEBIAN: %.deb-checkdir %.deb-DEBIAN-base %.deb-DEBIAN-scripts \
|
||||
%.deb-DEBIAN-md5sums
|
||||
: debian/$*/DEBIAN/ ok
|
||||
208
debian/rules
vendored
Executable file
208
debian/rules
vendored
Executable file
@@ -0,0 +1,208 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
#export DH_OPTIONS
|
||||
DEB_HOST_GNU_TYPE ?=$(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
|
||||
DEB_BUILD_GNU_TYPE ?=$(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
|
||||
|
||||
STRIP =strip
|
||||
ifneq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||
STRIP =: nostrip
|
||||
endif
|
||||
|
||||
CFLAGS =-Wall -g
|
||||
ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
|
||||
CFLAGS +=-O0
|
||||
else
|
||||
CFLAGS +=-Os
|
||||
endif
|
||||
|
||||
CONFFLAGS =
|
||||
CC =gcc
|
||||
ifneq (,$(findstring diet,$(DEB_BUILD_OPTIONS)))
|
||||
CONFFLAGS =--disable-zlib
|
||||
CC =diet -v -Os gcc -nostdinc
|
||||
endif
|
||||
|
||||
patch: deb-checkdir patch-stamp
|
||||
patch-stamp:
|
||||
for i in `ls -1 debian/diff/*.diff || :`; do \
|
||||
patch -p1 <$$i || exit 1; \
|
||||
done
|
||||
touch patch-stamp
|
||||
|
||||
config.status: patch-stamp configure
|
||||
CC='$(CC)' \
|
||||
CFLAGS='$(CFLAGS)'' -DSFTPSERVER_PATH="\"/usr/lib/sftp-server\""' \
|
||||
./configure --host='$(DEB_HOST_GNU_TYPE)' \
|
||||
--build='$(DEB_BUILD_GNU_TYPE)' --prefix=/usr \
|
||||
--mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info \
|
||||
$(CONFFLAGS)
|
||||
$(MAKE) clean
|
||||
|
||||
build: deb-checkdir build-stamp
|
||||
build-stamp: config.status
|
||||
$(MAKE) CC='$(CC)' LD='$(CC)'
|
||||
touch build-stamp
|
||||
|
||||
clean: DIR=$(shell pwd)/debian/dropbear
|
||||
clean: deb-checkdir deb-checkuid
|
||||
test ! -r Makefile || $(MAKE) distclean
|
||||
rm -f libtomcrypt/Makefile libtommath/Makefile
|
||||
test ! -e patch-stamp || \
|
||||
for i in `ls -1r debian/diff/*.diff || :`; do \
|
||||
patch -p1 -R <$$i; \
|
||||
done
|
||||
rm -f patch-stamp build-stamp config.log config.status
|
||||
rm -rf '$(DIR)'
|
||||
rm -rf '$(DIR)'-client
|
||||
rm -rf '$(DIR)'-server
|
||||
rm -rf '$(DIR)'-keyutils
|
||||
rm -rf '$(DIR)'-scp
|
||||
rm -f debian/files debian/substvars debian/copyright changelog
|
||||
|
||||
install-server: DIR=$(shell pwd)/debian/dropbear-server
|
||||
install-server: deb-checkdir deb-checkuid config.status
|
||||
rm -f '$(DIR)'
|
||||
rm *.o
|
||||
$(MAKE) CC='$(CC)' LD='$(LD)' PROGRAMS="dropbear dropbearkey dropbearconvert" MULTI=1
|
||||
install -d -m0755 '$(DIR)'/etc/dropbear
|
||||
# programs
|
||||
install -d -m0755 '$(DIR)'/usr/bin
|
||||
install -d -m0755 '$(DIR)'/usr/sbin
|
||||
install -d -m0755 '$(DIR)'/usr/lib/dropbear
|
||||
install -m0755 dropbearmulti \
|
||||
'$(DIR)'/usr/lib/dropbear/dropbearmulti
|
||||
ln -s ../lib/dropbear/dropbearmulti '$(DIR)'/usr/bin/dropbearkey
|
||||
ln -s ../lib/dropbear/dropbearmulti '$(DIR)'/usr/sbin/dropbear
|
||||
ln -s dropbearmulti '$(DIR)'/usr/lib/dropbear/dropbearconvert
|
||||
# init and run scripts
|
||||
install -d -m0755 '$(DIR)'/etc/init.d
|
||||
install -m0755 debian/dropbear.init '$(DIR)'/etc/init.d/dropbear
|
||||
install -m0755 debian/service/run '$(DIR)'/etc/dropbear/run
|
||||
install -d -m0755 '$(DIR)'/etc/dropbear/log
|
||||
install -m0755 debian/service/log '$(DIR)'/etc/dropbear/log/run
|
||||
ln -s /var/log/dropbear '$(DIR)'/etc/dropbear/log/main
|
||||
install -d -m0755 '$(DIR)'/usr/share/man/man8
|
||||
for i in dropbear.8 ; do \
|
||||
install -m644 $$i '$(DIR)'/usr/share/man/man8/ || exit 1; \
|
||||
done
|
||||
gzip -9 '$(DIR)'/usr/share/man/man8/*.8
|
||||
# copyright, changelog
|
||||
cat debian/copyright.in LICENSE > debian/copyright
|
||||
test -r changelog || ln -s CHANGES changelog
|
||||
$(STRIP) -R .comment -R .note '$(DIR)'/usr/lib/dropbear/*
|
||||
|
||||
install -d -m0755 '$(DIR)'/DEBIAN
|
||||
test '$(CC)' != 'gcc' || \
|
||||
dpkg-shlibdeps '$(DIR)'/usr/lib/dropbear/*
|
||||
|
||||
install-client: DIR=$(shell pwd)/debian/dropbear-client
|
||||
install-client: deb-checkdir deb-checkuid config.status
|
||||
rm -f '$(DIR)'
|
||||
rm *.o
|
||||
$(MAKE) CC='$(CC)' LD='$(LD)' PROGRAMS=dbclient dbclient
|
||||
install -d -m0755 '$(DIR)'/usr/bin
|
||||
install -m0755 dbclient '$(DIR)'/usr/bin/dbclient
|
||||
install -d -m0755 '$(DIR)'/usr/share/man/man1
|
||||
install -m644 dbclient.1 '$(DIR)'/usr/share/man/man1/
|
||||
gzip -9 '$(DIR)'/usr/share/man/man1/*.1
|
||||
$(STRIP) -R .comment -R .note '$(DIR)'/usr/bin/*
|
||||
|
||||
install -d -m0755 '$(DIR)'/DEBIAN
|
||||
test '$(CC)' != 'gcc' || \
|
||||
dpkg-shlibdeps '$(DIR)'/usr/bin/*
|
||||
|
||||
install-keyutils: DIR=$(shell pwd)/debian/dropbear-keyutils
|
||||
install-keyutils: deb-checkdir deb-checkuid config.status
|
||||
rm -f '$(DIR)'
|
||||
rm *.o
|
||||
$(MAKE) CC='$(CC)' LD='$(LD)' PROGRAMS="dropbearkey dropbearconvert" MULTI=1
|
||||
install -d -m0755 '$(DIR)'/usr/bin
|
||||
install -d -m0755 '$(DIR)'/usr/lib/dropbear
|
||||
install -m0755 dropbearmulti \
|
||||
'$(DIR)'/usr/lib/dropbear/dropbearmulti
|
||||
ln -s ../lib/dropbear/dropbearmulti '$(DIR)'/usr/bin/dropbearkey
|
||||
ln -s dropbearmulti '$(DIR)'/usr/lib/dropbear/dropbearconvert
|
||||
install -d -m0755 '$(DIR)'/usr/share/man/man8
|
||||
for i in dropbearkey.8; do \
|
||||
install -m644 $$i '$(DIR)'/usr/share/man/man8/ || exit 1; \
|
||||
done
|
||||
gzip -9 '$(DIR)'/usr/share/man/man8/*.8
|
||||
$(STRIP) -R .comment -R .note \
|
||||
'$(DIR)'/usr/lib/dropbear/*
|
||||
|
||||
install -d -m0755 '$(DIR)'/DEBIAN
|
||||
test '$(CC)' != 'gcc' || \
|
||||
dpkg-shlibdeps '$(DIR)'/usr/lib/dropbear/*
|
||||
|
||||
install-scp: DIR=$(shell pwd)/debian/dropbear-scp
|
||||
install-scp: deb-checkdir deb-checkuid config.status
|
||||
rm -f '$(DIR)'
|
||||
rm *.o
|
||||
$(MAKE) CC='$(CC)' LD='$(LD)' PROGRAMS="scp" scp
|
||||
install -d -m0755 '$(DIR)'/usr/bin
|
||||
install -m0755 scp '$(DIR)'/usr/bin/scp
|
||||
$(STRIP) -R .comment -R .note '$(DIR)'/usr/bin/*
|
||||
|
||||
install -d -m0755 '$(DIR)'/DEBIAN
|
||||
test '$(CC)' != 'gcc' || \
|
||||
dpkg-shlibdeps '$(DIR)'/usr/bin/*
|
||||
|
||||
install-multi: DIR=$(shell pwd)/debian/dropbear
|
||||
install-multi: deb-checkdir deb-checkuid config.status
|
||||
rm -f '$(DIR)'
|
||||
rm *.o
|
||||
$(MAKE) CC='$(CC)' LD='$(LD)' PROGRAMS="dropbearkey dropbearconvert scp dropbear dbclient" MULTI=1
|
||||
install -d -m0755 '$(DIR)'/etc/dropbear
|
||||
# programs
|
||||
install -d -m0755 '$(DIR)'/usr/bin
|
||||
install -d -m0755 '$(DIR)'/usr/sbin
|
||||
install -d -m0755 '$(DIR)'/usr/lib/dropbear
|
||||
install -m0755 dropbearmulti \
|
||||
'$(DIR)'/usr/lib/dropbear/dropbearmulti
|
||||
ln -s ../lib/dropbear/dropbearmulti '$(DIR)'/usr/bin/dropbearkey
|
||||
ln -s ../lib/dropbear/dropbearmulti '$(DIR)'/usr/bin/dbclient
|
||||
ln -s ../lib/dropbear/dropbearmulti '$(DIR)'/usr/bin/scp
|
||||
ln -s ../lib/dropbear/dropbearmulti '$(DIR)'/usr/sbin/dropbear
|
||||
ln -s dropbearmulti '$(DIR)'/usr/lib/dropbear/dropbearconvert
|
||||
# init and run scripts
|
||||
install -d -m0755 '$(DIR)'/etc/init.d
|
||||
install -m0755 debian/dropbear.init '$(DIR)'/etc/init.d/dropbear
|
||||
install -m0755 debian/service/run '$(DIR)'/etc/dropbear/run
|
||||
install -d -m0755 '$(DIR)'/etc/dropbear/log
|
||||
install -m0755 debian/service/log '$(DIR)'/etc/dropbear/log/run
|
||||
ln -s /var/log/dropbear '$(DIR)'/etc/dropbear/log/main
|
||||
install -d -m0755 '$(DIR)'/usr/share/man/man8
|
||||
for i in dropbear.8 dropbearkey.8; do \
|
||||
install -m644 $$i '$(DIR)'/usr/share/man/man8/ || exit 1; \
|
||||
done
|
||||
gzip -9 '$(DIR)'/usr/share/man/man8/*.8
|
||||
install -d -m0755 '$(DIR)'/usr/share/man/man1
|
||||
install -m644 dbclient.1 '$(DIR)'/usr/share/man/man1/
|
||||
gzip -9 '$(DIR)'/usr/share/man/man1/*.1
|
||||
$(STRIP) -R .comment -R .note '$(DIR)'/usr/lib/dropbear/*
|
||||
|
||||
install -d -m0755 '$(DIR)'/DEBIAN
|
||||
test '$(CC)' != 'gcc' || \
|
||||
dpkg-shlibdeps '$(DIR)'/usr/lib/dropbear/*
|
||||
|
||||
install: install-client install-server install-keyutils install-multi install-scp
|
||||
binary-indep:
|
||||
|
||||
binary-arch: install dropbear.deb dropbear-server.deb dropbear-keyutils.deb dropbear-scp.deb dropbear-client.deb
|
||||
dpkg-gencontrol -isp -pdropbear -P'$(shell pwd)/debian'/dropbear
|
||||
dpkg-gencontrol -isp -pdropbear-server -P'$(shell pwd)/debian'/dropbear-server
|
||||
dpkg-gencontrol -isp -pdropbear-client -P'$(shell pwd)/debian'/dropbear-client
|
||||
dpkg-gencontrol -isp -pdropbear-keyutils -P'$(shell pwd)/debian'/dropbear-keyutils
|
||||
dpkg-gencontrol -isp -pdropbear-scp -P'$(shell pwd)/debian'/dropbear-scp
|
||||
dpkg -b '$(shell pwd)/debian'/dropbear ..
|
||||
dpkg -b '$(shell pwd)/debian'/dropbear-server ..
|
||||
dpkg -b '$(shell pwd)/debian'/dropbear-keyutils ..
|
||||
dpkg -b '$(shell pwd)/debian'/dropbear-scp ..
|
||||
dpkg -b '$(shell pwd)/debian'/dropbear-client ..
|
||||
|
||||
binary: binary-arch binary-indep
|
||||
|
||||
.PHONY: patch build clean install binary-indep binary-arch binary
|
||||
|
||||
include debian/implicit
|
||||
2
debian/service/log
vendored
Normal file
2
debian/service/log
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
exec chpst -udropbearlog svlogd -tt ./main
|
||||
3
debian/service/run
vendored
Normal file
3
debian/service/run
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
exec 2>&1
|
||||
exec dropbear -d ./dropbear_dss_host_key -r ./dropbear_rsa_host_key -F -E -p 22
|
||||
81
debug.h
Normal file
81
debug.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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 _DEBUG_H_
|
||||
#define _DEBUG_H_
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
/* Debugging */
|
||||
|
||||
/* Work well for valgrind - don't clear environment, be nicer with signals
|
||||
* 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)*/
|
||||
|
||||
#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*/
|
||||
|
||||
/* A couple of flags, not usually useful, and mightn't do anything */
|
||||
|
||||
/*#define DEBUG_KEXHASH*/
|
||||
/*#define DEBUG_RSA*/
|
||||
|
||||
/* you don't need to touch this block */
|
||||
#ifdef DEBUG_TRACE
|
||||
#define TRACE(X) dropbear_trace X;
|
||||
#else /*DEBUG_TRACE*/
|
||||
#define TRACE(X)
|
||||
#endif /*DEBUG_TRACE*/
|
||||
|
||||
/* To debug with GDB it is easier to run with no forking of child processes.
|
||||
You will need to pass "-F" as well. */
|
||||
/* #define DEBUG_NOFORK */
|
||||
|
||||
|
||||
/* For testing as non-root on shadowed systems, include the crypt of a password
|
||||
* here. You can then log in as any user with this password. Ensure that you
|
||||
* make your own password, and are careful about using this. This will also
|
||||
* disable some of the chown pty code etc*/
|
||||
/* #define DEBUG_HACKCRYPT "hL8nrFDt0aJ3E" */ /* this is crypt("password") */
|
||||
|
||||
#endif
|
||||
164
dropbear.8
Normal file
164
dropbear.8
Normal file
@@ -0,0 +1,164 @@
|
||||
.TH dropbear 8
|
||||
.SH NAME
|
||||
dropbear \- lightweight SSH2 server
|
||||
.SH SYNOPSIS
|
||||
.B dropbear
|
||||
[\-FEmwsgjki] [\-b
|
||||
.I banner\fR] [\-d
|
||||
.I dsskey\fR] [\-r
|
||||
.I rsakey\fR] [\-p
|
||||
.IR port ]
|
||||
.SH DESCRIPTION
|
||||
.B dropbear
|
||||
is a SSH 2 server designed to be small enough to be used in small memory
|
||||
environments, while still being functional and secure enough for general use.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-b \fIbanner
|
||||
bannerfile.
|
||||
Display the contents of the file
|
||||
.I banner
|
||||
before user login (default: none).
|
||||
.TP
|
||||
.B \-d \fIdsskey
|
||||
dsskeyfile.
|
||||
Use the contents of the file
|
||||
.I dsskey
|
||||
for the DSS host key (default: /etc/dropbear/dropbear_dss_host_key).
|
||||
Note that
|
||||
some SSH implementations
|
||||
use the term "DSA" rather than "DSS", they mean the same thing.
|
||||
This file is generated with
|
||||
.BR dropbearkey (8).
|
||||
.TP
|
||||
.B \-r \fIrsakey
|
||||
rsakeyfile.
|
||||
Use the contents of the file
|
||||
.I rsakey
|
||||
for the rsa host key (default: /etc/dropbear/dropbear_rsa_host_key).
|
||||
This file is generated with
|
||||
.BR dropbearkey (8).
|
||||
.TP
|
||||
.B \-F
|
||||
Don't fork into background.
|
||||
.TP
|
||||
.B \-E
|
||||
Log to standard error rather than syslog.
|
||||
.TP
|
||||
.B \-m
|
||||
Don't display the message of the day on login.
|
||||
.TP
|
||||
.B \-w
|
||||
Disallow root logins.
|
||||
.TP
|
||||
.B \-s
|
||||
Disable password logins.
|
||||
.TP
|
||||
.B \-g
|
||||
Disable password logins for root.
|
||||
.TP
|
||||
.B \-j
|
||||
Disable local port forwarding.
|
||||
.TP
|
||||
.B \-k
|
||||
Disable remote port forwarding.
|
||||
.TP
|
||||
.B \-p \fI[address:]port
|
||||
Listen on specified
|
||||
.I address
|
||||
and TCP
|
||||
.I port.
|
||||
If just a port is given listen
|
||||
on all addresses.
|
||||
up to 10 can be specified (default 22 if none specified).
|
||||
.TP
|
||||
.B \-i
|
||||
Service program mode.
|
||||
Use this option to run
|
||||
.B dropbear
|
||||
under TCP/IP servers like inetd, tcpsvd, or tcpserver.
|
||||
In program mode the \-F option is implied, and \-p options are ignored.
|
||||
.TP
|
||||
.B \-P \fIpidfile
|
||||
Specify a pidfile to create when running as a daemon. If not specified, the
|
||||
default is /var/run/dropbear.pid
|
||||
.TP
|
||||
.B \-a
|
||||
Allow remote hosts to connect to forwarded ports.
|
||||
.TP
|
||||
.B \-W \fIwindowsize
|
||||
Specify the per-channel receive window buffer size. Increasing this
|
||||
may improve network performance at the expense of memory use. Use -h to see the
|
||||
default buffer size.
|
||||
.TP
|
||||
.B \-K \fItimeout_seconds
|
||||
Ensure that traffic is transmitted at a certain interval in seconds. This is
|
||||
useful for working around firewalls or routers that drop connections after
|
||||
a certain period of inactivity. The trade-off is that a session may be
|
||||
closed if there is a temporary lapse of network connectivity. A setting
|
||||
if 0 disables keepalives.
|
||||
.TP
|
||||
.B \-I \fIidle_timeout
|
||||
Disconnect the session if no traffic is transmitted or received for \fIidle_timeout\fR seconds.
|
||||
.SH FILES
|
||||
|
||||
.TP
|
||||
Authorized Keys
|
||||
|
||||
~/.ssh/authorized_keys can be set up to allow remote login with a RSA or DSS
|
||||
key. Each line is of the form
|
||||
.TP
|
||||
[restrictions] ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIgAsp... [comment]
|
||||
|
||||
and can be extracted from a Dropbear private host key with "dropbearkey -y". This is the same format as used by OpenSSH, though the restrictions are a subset (keys with unknown restrictions are ignored).
|
||||
Restrictions are comma separated, with double quotes around spaces in arguments.
|
||||
Available restrictions are:
|
||||
|
||||
.TP
|
||||
.B no-port-forwarding
|
||||
Don't allow port forwarding for this connection
|
||||
|
||||
.TP
|
||||
.B no-agent-forwarding
|
||||
Don't allow agent forwarding for this connection
|
||||
|
||||
.TP
|
||||
.B no-X11-forwarding
|
||||
Don't allow X11 forwarding for this connection
|
||||
|
||||
.TP
|
||||
.B no-pty
|
||||
Disable PTY allocation. Note that a user can still obtain most of the
|
||||
same functionality with other means even if no-pty is set.
|
||||
|
||||
.TP
|
||||
.B command="\fIforced_command\fR"
|
||||
Disregard the command provided by the user and always run \fIforced_command\fR.
|
||||
|
||||
The authorized_keys file and its containing ~/.ssh directory must only be
|
||||
writable by the user, otherwise Dropbear will not allow a login using public
|
||||
key authentication.
|
||||
|
||||
.TP
|
||||
Host Key Files
|
||||
|
||||
Host key files are read at startup from a standard location, by default
|
||||
/etc/dropbear/dropbear_dss_host_key and /etc/dropbear/dropbear_rsa_host_key
|
||||
or specified on the commandline with -d or -r. These are of the form generated
|
||||
by dropbearkey.
|
||||
|
||||
.TP
|
||||
Message Of The Day
|
||||
|
||||
By default the file /etc/motd will be printed for any login shell (unless
|
||||
disabled at compile-time). This can also be disabled per-user
|
||||
by creating a file ~/.hushlogin .
|
||||
|
||||
.SH AUTHOR
|
||||
Matt Johnston (matt@ucc.asn.au).
|
||||
.br
|
||||
Gerrit Pape (pape@smarden.org) wrote this manual page.
|
||||
.SH SEE ALSO
|
||||
dropbearkey(8), dbclient(1)
|
||||
.P
|
||||
http://matt.ucc.asn.au/dropbear/dropbear.html
|
||||
149
dropbearconvert.c
Normal file
149
dropbearconvert.c
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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. */
|
||||
|
||||
/* This program converts to/from Dropbear and OpenSSH private-key formats */
|
||||
#include "includes.h"
|
||||
#include "signkey.h"
|
||||
#include "buffer.h"
|
||||
#include "dbutil.h"
|
||||
#include "keyimport.h"
|
||||
|
||||
|
||||
static int do_convert(int intype, const char* infile, int outtype,
|
||||
const char* outfile);
|
||||
|
||||
static void printhelp(char * progname);
|
||||
|
||||
static void printhelp(char * progname) {
|
||||
|
||||
fprintf(stderr, "Usage: %s <inputtype> <outputtype> <inputfile> <outputfile>\n\n"
|
||||
"CAUTION: This program is for convenience only, and is not secure if used on\n"
|
||||
"untrusted input files, ie it could allow arbitrary code execution.\n"
|
||||
"All parameters must be specified in order.\n"
|
||||
"\n"
|
||||
"The input and output types are one of:\n"
|
||||
"openssh\n"
|
||||
"dropbear\n"
|
||||
"\n"
|
||||
"Example:\n"
|
||||
"dropbearconvert openssh dropbear /etc/ssh/ssh_host_rsa_key /etc/dropbear_rsa_host_key\n",
|
||||
progname);
|
||||
}
|
||||
|
||||
#if defined(DBMULTI_dropbearconvert) || !defined(DROPBEAR_MULTI)
|
||||
#if defined(DBMULTI_dropbearconvert) && defined(DROPBEAR_MULTI)
|
||||
int dropbearconvert_main(int argc, char ** argv) {
|
||||
#else
|
||||
int main(int argc, char ** argv) {
|
||||
#endif
|
||||
|
||||
int intype, outtype;
|
||||
const char* infile;
|
||||
const char* outfile;
|
||||
|
||||
#ifdef DEBUG_TRACE
|
||||
/* It's hard for it to get in the way _too_ much */
|
||||
debug_trace = 1;
|
||||
#endif
|
||||
|
||||
/* get the commandline options */
|
||||
if (argc != 5) {
|
||||
fprintf(stderr, "All arguments must be specified\n");
|
||||
goto usage;
|
||||
}
|
||||
|
||||
/* input type */
|
||||
if (argv[1][0] == 'd') {
|
||||
intype = KEYFILE_DROPBEAR;
|
||||
} else if (argv[1][0] == 'o') {
|
||||
intype = KEYFILE_OPENSSH;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid input key type\n");
|
||||
goto usage;
|
||||
}
|
||||
|
||||
/* output type */
|
||||
if (argv[2][0] == 'd') {
|
||||
outtype = KEYFILE_DROPBEAR;
|
||||
} else if (argv[2][0] == 'o') {
|
||||
outtype = KEYFILE_OPENSSH;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid output key type\n");
|
||||
goto usage;
|
||||
}
|
||||
|
||||
/* we don't want output readable by others */
|
||||
umask(077);
|
||||
|
||||
infile = argv[3];
|
||||
outfile = argv[4];
|
||||
|
||||
return do_convert(intype, infile, outtype, outfile);
|
||||
|
||||
usage:
|
||||
printhelp(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int do_convert(int intype, const char* infile, int outtype,
|
||||
const char* outfile) {
|
||||
|
||||
sign_key * key = NULL;
|
||||
char * keytype = NULL;
|
||||
int ret = 1;
|
||||
|
||||
key = import_read(infile, NULL, intype);
|
||||
if (!key) {
|
||||
fprintf(stderr, "Error reading key from '%s'\n",
|
||||
infile);
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef DROPBEAR_RSA
|
||||
if (key->rsakey != NULL) {
|
||||
keytype = "RSA";
|
||||
}
|
||||
#endif
|
||||
#ifdef DROPBEAR_DSS
|
||||
if (key->dsskey != NULL) {
|
||||
keytype = "DSS";
|
||||
}
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "Key is a %s key\n", keytype);
|
||||
|
||||
if (import_write(outfile, key, NULL, outtype) != 1) {
|
||||
fprintf(stderr, "Error writing key to '%s'\n", outfile);
|
||||
} else {
|
||||
fprintf(stderr, "Wrote key to '%s'\n", outfile);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
out:
|
||||
if (key) {
|
||||
sign_key_free(key);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
50
dropbearkey.8
Normal file
50
dropbearkey.8
Normal file
@@ -0,0 +1,50 @@
|
||||
.TH dropbearkey 8
|
||||
.SH NAME
|
||||
dropbearkey \- create private keys for the use with dropbear(8)
|
||||
.SH SYNOPSIS
|
||||
.B dropbearkey
|
||||
\-t
|
||||
.I type
|
||||
\-f
|
||||
.I file
|
||||
[\-s
|
||||
.IR bits ]
|
||||
.SH DESCRIPTION
|
||||
.B dropbearkey
|
||||
generates a
|
||||
.I RSA
|
||||
or
|
||||
.I DSS
|
||||
format SSH private key, and saves it to a file for the use with the
|
||||
.BR dropbear (8)
|
||||
SSH 2 server.
|
||||
Note that
|
||||
some SSH implementations
|
||||
use the term "DSA" rather than "DSS", they mean the same thing.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-t \fItype
|
||||
Type of key to generate.
|
||||
Must be one of
|
||||
.I rsa
|
||||
or
|
||||
.IR dss .
|
||||
.TP
|
||||
.B \-f \fIfile
|
||||
Write the secret key to the file
|
||||
.IR file .
|
||||
.TP
|
||||
.B \-s \fIbits
|
||||
Set the key size to
|
||||
.I bits
|
||||
bits, should be multiple of 8 (optional).
|
||||
.SH EXAMPLE
|
||||
# dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
|
||||
.SH AUTHOR
|
||||
Matt Johnston (matt@ucc.asn.au).
|
||||
.br
|
||||
Gerrit Pape (pape@smarden.org) wrote this manual page.
|
||||
.SH SEE ALSO
|
||||
dropbear(8), dbclient(1)
|
||||
.P
|
||||
http://matt.ucc.asn.au/dropbear/dropbear.html
|
||||
374
dropbearkey.c
Normal file
374
dropbearkey.c
Normal file
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
* 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. */
|
||||
|
||||
/* The format of the keyfiles is basically a raw dump of the buffer. Data types
|
||||
* are specified in the transport draft - string is a 32-bit len then the
|
||||
* non-null-terminated string, mp_int is a 32-bit len then the bignum data.
|
||||
* The actual functions are buf_put_rsa_priv_key() and buf_put_dss_priv_key()
|
||||
|
||||
* RSA:
|
||||
* string "ssh-rsa"
|
||||
* mp_int e
|
||||
* mp_int n
|
||||
* mp_int d
|
||||
* mp_int p (newer versions only)
|
||||
* mp_int q (newer versions only)
|
||||
*
|
||||
* DSS:
|
||||
* string "ssh-dss"
|
||||
* mp_int p
|
||||
* mp_int q
|
||||
* mp_int g
|
||||
* mp_int y
|
||||
* mp_int x
|
||||
*
|
||||
*/
|
||||
#include "includes.h"
|
||||
#include "signkey.h"
|
||||
#include "buffer.h"
|
||||
#include "dbutil.h"
|
||||
|
||||
#include "genrsa.h"
|
||||
#include "gendss.h"
|
||||
|
||||
static void printhelp(char * progname);
|
||||
|
||||
#define RSA_SIZE (1024/8) /* 1024 bit */
|
||||
#define DSS_SIZE (1024/8) /* 1024 bit */
|
||||
|
||||
static void buf_writefile(buffer * buf, const char * filename);
|
||||
static void printpubkey(sign_key * key, int keytype);
|
||||
static void justprintpub(const char* filename);
|
||||
|
||||
/* Print a help message */
|
||||
static void printhelp(char * progname) {
|
||||
|
||||
fprintf(stderr, "Usage: %s -t <type> -f <filename> [-s bits]\n"
|
||||
"Options are:\n"
|
||||
"-t type Type of key to generate. One of:\n"
|
||||
#ifdef DROPBEAR_RSA
|
||||
" rsa\n"
|
||||
#endif
|
||||
#ifdef DROPBEAR_DSS
|
||||
" dss\n"
|
||||
#endif
|
||||
"-f filename Use filename for the secret key\n"
|
||||
"-s bits Key size in bits, should be a multiple of 8 (optional)\n"
|
||||
" (DSS has a fixed size of 1024 bits)\n"
|
||||
"-y Just print the publickey and fingerprint for the\n private key in <filename>.\n"
|
||||
#ifdef DEBUG_TRACE
|
||||
"-v verbose\n"
|
||||
#endif
|
||||
,progname);
|
||||
}
|
||||
|
||||
#if defined(DBMULTI_dropbearkey) || !defined(DROPBEAR_MULTI)
|
||||
#if defined(DBMULTI_dropbearkey) && defined(DROPBEAR_MULTI)
|
||||
int dropbearkey_main(int argc, char ** argv) {
|
||||
#else
|
||||
int main(int argc, char ** argv) {
|
||||
#endif
|
||||
|
||||
int i;
|
||||
char ** next = 0;
|
||||
sign_key *key = NULL;
|
||||
buffer *buf = NULL;
|
||||
char * filename = NULL;
|
||||
int keytype = -1;
|
||||
char * typetext = NULL;
|
||||
char * sizetext = NULL;
|
||||
unsigned int bits;
|
||||
unsigned int keysize;
|
||||
int printpub = 0;
|
||||
|
||||
/* get the commandline options */
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (argv[i] == NULL) {
|
||||
continue; /* Whack */
|
||||
}
|
||||
if (next) {
|
||||
*next = argv[i];
|
||||
next = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argv[i][0] == '-') {
|
||||
switch (argv[i][1]) {
|
||||
case 'f':
|
||||
next = &filename;
|
||||
break;
|
||||
case 't':
|
||||
next = &typetext;
|
||||
break;
|
||||
case 's':
|
||||
next = &sizetext;
|
||||
break;
|
||||
case 'y':
|
||||
printpub = 1;
|
||||
break;
|
||||
case 'h':
|
||||
printhelp(argv[0]);
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
#ifdef DEBUG_TRACE
|
||||
case 'v':
|
||||
debug_trace = 1;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(stderr, "Unknown argument %s\n", argv[i]);
|
||||
printhelp(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!filename) {
|
||||
fprintf(stderr, "Must specify a key filename\n");
|
||||
printhelp(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (printpub) {
|
||||
justprintpub(filename);
|
||||
/* Not reached */
|
||||
}
|
||||
|
||||
/* check/parse args */
|
||||
if (!typetext) {
|
||||
fprintf(stderr, "Must specify key type\n");
|
||||
printhelp(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (strlen(typetext) == 3) {
|
||||
#ifdef DROPBEAR_RSA
|
||||
if (strncmp(typetext, "rsa", 3) == 0) {
|
||||
keytype = DROPBEAR_SIGNKEY_RSA;
|
||||
TRACE(("type is rsa"))
|
||||
}
|
||||
#endif
|
||||
#ifdef DROPBEAR_DSS
|
||||
if (strncmp(typetext, "dss", 3) == 0) {
|
||||
keytype = DROPBEAR_SIGNKEY_DSS;
|
||||
TRACE(("type is dss"))
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (keytype == -1) {
|
||||
fprintf(stderr, "Unknown key type '%s'\n", typetext);
|
||||
printhelp(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (sizetext) {
|
||||
if (sscanf(sizetext, "%u", &bits) != 1) {
|
||||
fprintf(stderr, "Bits must be an integer\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (keytype == DROPBEAR_SIGNKEY_DSS && bits != 1024) {
|
||||
fprintf(stderr, "DSS keys have a fixed size of 1024 bits\n");
|
||||
exit(EXIT_FAILURE);
|
||||
} else if (bits < 512 || bits > 4096 || (bits % 8 != 0)) {
|
||||
fprintf(stderr, "Bits must satisfy 512 <= bits <= 4096, and be a"
|
||||
" multiple of 8\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
keysize = bits / 8;
|
||||
} else {
|
||||
if (keytype == DROPBEAR_SIGNKEY_DSS) {
|
||||
keysize = DSS_SIZE;
|
||||
} else if (keytype == DROPBEAR_SIGNKEY_RSA) {
|
||||
keysize = RSA_SIZE;
|
||||
} else {
|
||||
exit(EXIT_FAILURE); /* not reached */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fprintf(stderr, "Will output %d bit %s secret key to '%s'\n", keysize*8,
|
||||
typetext, filename);
|
||||
|
||||
/* don't want the file readable by others */
|
||||
umask(077);
|
||||
|
||||
/* now we can generate the key */
|
||||
key = new_sign_key();
|
||||
|
||||
fprintf(stderr, "Generating key, this may take a while...\n");
|
||||
switch(keytype) {
|
||||
#ifdef DROPBEAR_RSA
|
||||
case DROPBEAR_SIGNKEY_RSA:
|
||||
key->rsakey = gen_rsa_priv_key(keysize); /* 128 bytes = 1024 bit */
|
||||
break;
|
||||
#endif
|
||||
#ifdef DROPBEAR_DSS
|
||||
case DROPBEAR_SIGNKEY_DSS:
|
||||
key->dsskey = gen_dss_priv_key(keysize); /* 128 bytes = 1024 bit */
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(stderr, "Internal error, bad key type\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
buf = buf_new(MAX_PRIVKEY_SIZE);
|
||||
|
||||
buf_put_priv_key(buf, key, keytype);
|
||||
buf_setpos(buf, 0);
|
||||
buf_writefile(buf, filename);
|
||||
|
||||
buf_burn(buf);
|
||||
buf_free(buf);
|
||||
|
||||
printpubkey(key, keytype);
|
||||
|
||||
sign_key_free(key);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void justprintpub(const char* filename) {
|
||||
|
||||
buffer *buf = NULL;
|
||||
sign_key *key = NULL;
|
||||
int keytype;
|
||||
int ret;
|
||||
int err = DROPBEAR_FAILURE;
|
||||
|
||||
buf = buf_new(MAX_PRIVKEY_SIZE);
|
||||
ret = buf_readfile(buf, filename);
|
||||
|
||||
if (ret != DROPBEAR_SUCCESS) {
|
||||
fprintf(stderr, "Failed reading '%s'\n", filename);
|
||||
goto out;
|
||||
}
|
||||
|
||||
key = new_sign_key();
|
||||
keytype = DROPBEAR_SIGNKEY_ANY;
|
||||
|
||||
buf_setpos(buf, 0);
|
||||
ret = buf_get_priv_key(buf, key, &keytype);
|
||||
if (ret == DROPBEAR_FAILURE) {
|
||||
fprintf(stderr, "Bad key in '%s'\n", filename);
|
||||
goto out;
|
||||
}
|
||||
|
||||
printpubkey(key, keytype);
|
||||
|
||||
err = DROPBEAR_SUCCESS;
|
||||
|
||||
out:
|
||||
buf_burn(buf);
|
||||
buf_free(buf);
|
||||
buf = NULL;
|
||||
if (key) {
|
||||
sign_key_free(key);
|
||||
key = NULL;
|
||||
}
|
||||
exit(err);
|
||||
}
|
||||
|
||||
static void printpubkey(sign_key * key, int keytype) {
|
||||
|
||||
buffer * buf = NULL;
|
||||
unsigned char base64key[MAX_PUBKEY_SIZE*2];
|
||||
unsigned long base64len;
|
||||
int err;
|
||||
const char * typestring = NULL;
|
||||
char *fp = NULL;
|
||||
int len;
|
||||
struct passwd * pw = NULL;
|
||||
char * username = NULL;
|
||||
char hostname[100];
|
||||
|
||||
buf = buf_new(MAX_PUBKEY_SIZE);
|
||||
buf_put_pub_key(buf, key, keytype);
|
||||
buf_setpos(buf, 4);
|
||||
|
||||
len = buf->len - buf->pos;
|
||||
|
||||
base64len = sizeof(base64key);
|
||||
err = base64_encode(buf_getptr(buf, len), len, base64key, &base64len);
|
||||
|
||||
if (err != CRYPT_OK) {
|
||||
fprintf(stderr, "base64 failed");
|
||||
}
|
||||
|
||||
typestring = signkey_name_from_type(keytype, &err);
|
||||
|
||||
fp = sign_key_fingerprint(buf_getptr(buf, len), len);
|
||||
|
||||
/* a user@host comment is informative */
|
||||
username = "";
|
||||
pw = getpwuid(getuid());
|
||||
if (pw) {
|
||||
username = pw->pw_name;
|
||||
}
|
||||
|
||||
gethostname(hostname, sizeof(hostname));
|
||||
hostname[sizeof(hostname)-1] = '\0';
|
||||
|
||||
printf("Public key portion is:\n%s %s %s@%s\nFingerprint: %s\n",
|
||||
typestring, base64key, username, hostname, fp);
|
||||
|
||||
m_free(fp);
|
||||
buf_free(buf);
|
||||
}
|
||||
|
||||
/* Write a buffer to a file specified, failing if the file exists */
|
||||
static void buf_writefile(buffer * buf, const char * filename) {
|
||||
|
||||
int fd;
|
||||
int len;
|
||||
|
||||
fd = open(filename, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Couldn't create new file %s\n", filename);
|
||||
perror("Reason");
|
||||
buf_burn(buf);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* write the file now */
|
||||
while (buf->pos != buf->len) {
|
||||
len = write(fd, buf_getptr(buf, buf->len - buf->pos),
|
||||
buf->len - buf->pos);
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
if (len <= 0) {
|
||||
fprintf(stderr, "Failed writing file '%s'\n",filename);
|
||||
perror("Reason");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
buf_incrpos(buf, len);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
421
dss.c
Normal file
421
dss.c
Normal file
@@ -0,0 +1,421 @@
|
||||
/*
|
||||
* 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 "bignum.h"
|
||||
#include "dss.h"
|
||||
#include "buffer.h"
|
||||
#include "ssh.h"
|
||||
#include "random.h"
|
||||
|
||||
/* Handle DSS (Digital Signature Standard), aka DSA (D.S. Algorithm),
|
||||
* operations, such as key reading, signing, verification. Key generation
|
||||
* is in gendss.c, since it isn't required in the server itself.
|
||||
*
|
||||
* See FIPS186 or the Handbook of Applied Cryptography for details of the
|
||||
* algorithm */
|
||||
|
||||
#ifdef 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, dss_key *key) {
|
||||
|
||||
TRACE(("enter buf_get_dss_pub_key"))
|
||||
dropbear_assert(key != NULL);
|
||||
key->p = m_malloc(sizeof(mp_int));
|
||||
key->q = m_malloc(sizeof(mp_int));
|
||||
key->g = m_malloc(sizeof(mp_int));
|
||||
key->y = m_malloc(sizeof(mp_int));
|
||||
m_mp_init_multi(key->p, key->q, key->g, key->y, NULL);
|
||||
key->x = NULL;
|
||||
|
||||
buf_incrpos(buf, 4+SSH_SIGNKEY_DSS_LEN); /* int + "ssh-dss" */
|
||||
if (buf_getmpint(buf, key->p) == DROPBEAR_FAILURE
|
||||
|| buf_getmpint(buf, key->q) == DROPBEAR_FAILURE
|
||||
|| 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
TRACE(("leave buf_get_dss_pub_key: success"))
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
|
||||
/* Same as buf_get_dss_pub_key, but reads a private "x" key at the end.
|
||||
* Loads a private dss key from a buffer
|
||||
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
|
||||
int buf_get_dss_priv_key(buffer* buf, dss_key *key) {
|
||||
|
||||
int ret = DROPBEAR_FAILURE;
|
||||
|
||||
dropbear_assert(key != NULL);
|
||||
|
||||
ret = buf_get_dss_pub_key(buf, key);
|
||||
if (ret == DROPBEAR_FAILURE) {
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
key->x = m_malloc(sizeof(mp_int));
|
||||
m_mp_init(key->x);
|
||||
ret = buf_getmpint(buf, key->x);
|
||||
if (ret == DROPBEAR_FAILURE) {
|
||||
m_free(key->x);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Clear and free the memory used by a public or private key */
|
||||
void dss_key_free(dss_key *key) {
|
||||
|
||||
TRACE(("enter dsa_key_free"))
|
||||
if (key == NULL) {
|
||||
TRACE(("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_free(key);
|
||||
TRACE(("leave dsa_key_free"))
|
||||
}
|
||||
|
||||
/* put the dss public key into the buffer in the required format:
|
||||
*
|
||||
* string "ssh-dss"
|
||||
* mpint p
|
||||
* mpint q
|
||||
* mpint g
|
||||
* mpint y
|
||||
*/
|
||||
void buf_put_dss_pub_key(buffer* buf, dss_key *key) {
|
||||
|
||||
dropbear_assert(key != NULL);
|
||||
buf_putstring(buf, SSH_SIGNKEY_DSS, SSH_SIGNKEY_DSS_LEN);
|
||||
buf_putmpint(buf, key->p);
|
||||
buf_putmpint(buf, key->q);
|
||||
buf_putmpint(buf, key->g);
|
||||
buf_putmpint(buf, key->y);
|
||||
|
||||
}
|
||||
|
||||
/* Same as buf_put_dss_pub_key, but with the private "x" key appended */
|
||||
void buf_put_dss_priv_key(buffer* buf, dss_key *key) {
|
||||
|
||||
dropbear_assert(key != NULL);
|
||||
buf_put_dss_pub_key(buf, key);
|
||||
buf_putmpint(buf, key->x);
|
||||
|
||||
}
|
||||
|
||||
#ifdef DROPBEAR_SIGNKEY_VERIFY
|
||||
/* Verify a DSS signature (in buf) made on data by the key given.
|
||||
* returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
|
||||
int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data,
|
||||
unsigned int len) {
|
||||
|
||||
unsigned char msghash[SHA1_HASH_SIZE];
|
||||
hash_state hs;
|
||||
int ret = DROPBEAR_FAILURE;
|
||||
DEF_MP_INT(val1);
|
||||
DEF_MP_INT(val2);
|
||||
DEF_MP_INT(val3);
|
||||
DEF_MP_INT(val4);
|
||||
char * string = NULL;
|
||||
int stringlen;
|
||||
|
||||
TRACE(("enter buf_dss_verify"))
|
||||
dropbear_assert(key != NULL);
|
||||
|
||||
m_mp_init_multi(&val1, &val2, &val3, &val4, NULL);
|
||||
|
||||
/* get blob, check length */
|
||||
string = buf_getstring(buf, &stringlen);
|
||||
if (stringlen != 2*SHA1_HASH_SIZE) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* hash the data */
|
||||
sha1_init(&hs);
|
||||
sha1_process(&hs, data, len);
|
||||
sha1_done(&hs, msghash);
|
||||
|
||||
/* create the signature - s' and r' are the received signatures in buf */
|
||||
/* w = (s')-1 mod q */
|
||||
/* let val1 = s' */
|
||||
bytes_to_mp(&val1, &string[SHA1_HASH_SIZE], SHA1_HASH_SIZE);
|
||||
|
||||
if (mp_cmp(&val1, key->q) != MP_LT) {
|
||||
TRACE(("verify failed, s' >= q"))
|
||||
goto out;
|
||||
}
|
||||
/* let val2 = w = (s')^-1 mod q*/
|
||||
if (mp_invmod(&val1, key->q, &val2) != MP_OKAY) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* u1 = ((SHA(M')w) mod q */
|
||||
/* let val1 = SHA(M') = msghash */
|
||||
bytes_to_mp(&val1, msghash, SHA1_HASH_SIZE);
|
||||
|
||||
/* let val3 = u1 = ((SHA(M')w) mod q */
|
||||
if (mp_mulmod(&val1, &val2, key->q, &val3) != MP_OKAY) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* u2 = ((r')w) mod q */
|
||||
/* let val1 = r' */
|
||||
bytes_to_mp(&val1, &string[0], SHA1_HASH_SIZE);
|
||||
if (mp_cmp(&val1, key->q) != MP_LT) {
|
||||
TRACE(("verify failed, r' >= q"))
|
||||
goto out;
|
||||
}
|
||||
/* let val4 = u2 = ((r')w) mod q */
|
||||
if (mp_mulmod(&val1, &val2, key->q, &val4) != MP_OKAY) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* v = (((g)^u1 (y)^u2) mod p) mod q */
|
||||
/* val2 = g^u1 mod p */
|
||||
if (mp_exptmod(key->g, &val3, key->p, &val2) != MP_OKAY) {
|
||||
goto out;
|
||||
}
|
||||
/* val3 = y^u2 mod p */
|
||||
if (mp_exptmod(key->y, &val4, key->p, &val3) != MP_OKAY) {
|
||||
goto out;
|
||||
}
|
||||
/* val4 = ((g)^u1 (y)^u2) mod p */
|
||||
if (mp_mulmod(&val2, &val3, key->p, &val4) != MP_OKAY) {
|
||||
goto out;
|
||||
}
|
||||
/* val2 = v = (((g)^u1 (y)^u2) mod p) mod q */
|
||||
if (mp_mod(&val4, key->q, &val2) != MP_OKAY) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* check whether signatures verify */
|
||||
if (mp_cmp(&val2, &val1) == MP_EQ) {
|
||||
/* good sig */
|
||||
ret = DROPBEAR_SUCCESS;
|
||||
}
|
||||
|
||||
out:
|
||||
mp_clear_multi(&val1, &val2, &val3, &val4, NULL);
|
||||
m_free(string);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
#endif /* DROPBEAR_SIGNKEY_VERIFY */
|
||||
|
||||
#ifdef DSS_PROTOK
|
||||
/* convert an unsigned mp into an array of bytes, malloced.
|
||||
* This array must be freed after use, len contains the length of the array,
|
||||
* if len != NULL */
|
||||
static unsigned char* mptobytes(mp_int *mp, int *len) {
|
||||
|
||||
unsigned char* ret;
|
||||
int size;
|
||||
|
||||
size = mp_unsigned_bin_size(mp);
|
||||
ret = m_malloc(size);
|
||||
if (mp_to_unsigned_bin(mp, ret) != MP_OKAY) {
|
||||
dropbear_exit("mem alloc error");
|
||||
}
|
||||
if (len != NULL) {
|
||||
*len = size;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Sign the data presented with key, writing the signature contents
|
||||
* to the buffer
|
||||
*
|
||||
* When DSS_PROTOK is #defined:
|
||||
* The alternate k generation method is based on the method used in PuTTY.
|
||||
* In particular to avoid being vulnerable to attacks using flaws in random
|
||||
* generation of k, we use the following:
|
||||
*
|
||||
* proto_k = SHA512 ( SHA512(x) || SHA160(message) )
|
||||
* k = proto_k mod q
|
||||
*
|
||||
* Now we aren't relying on the random number generation to protect the private
|
||||
* key x, which is a long term secret */
|
||||
void buf_put_dss_sign(buffer* buf, dss_key *key, const unsigned char* data,
|
||||
unsigned int len) {
|
||||
|
||||
unsigned char msghash[SHA1_HASH_SIZE];
|
||||
unsigned int writelen;
|
||||
unsigned int i;
|
||||
#ifdef DSS_PROTOK
|
||||
unsigned char privkeyhash[SHA512_HASH_SIZE];
|
||||
unsigned char *privkeytmp;
|
||||
unsigned char proto_k[SHA512_HASH_SIZE];
|
||||
DEF_MP_INT(dss_protok);
|
||||
#endif
|
||||
DEF_MP_INT(dss_k);
|
||||
DEF_MP_INT(dss_m);
|
||||
DEF_MP_INT(dss_temp1);
|
||||
DEF_MP_INT(dss_temp2);
|
||||
DEF_MP_INT(dss_r);
|
||||
DEF_MP_INT(dss_s);
|
||||
hash_state hs;
|
||||
|
||||
TRACE(("enter buf_put_dss_sign"))
|
||||
dropbear_assert(key != NULL);
|
||||
|
||||
/* hash the data */
|
||||
sha1_init(&hs);
|
||||
sha1_process(&hs, data, len);
|
||||
sha1_done(&hs, msghash);
|
||||
|
||||
m_mp_init_multi(&dss_k, &dss_temp1, &dss_temp2, &dss_r, &dss_s,
|
||||
&dss_m, NULL);
|
||||
#ifdef DSS_PROTOK
|
||||
/* hash the privkey */
|
||||
privkeytmp = mptobytes(key->x, &i);
|
||||
sha512_init(&hs);
|
||||
sha512_process(&hs, "the quick brown fox jumped over the lazy dog", 44);
|
||||
sha512_process(&hs, privkeytmp, i);
|
||||
sha512_done(&hs, privkeyhash);
|
||||
m_burn(privkeytmp, i);
|
||||
m_free(privkeytmp);
|
||||
|
||||
/* calculate proto_k */
|
||||
sha512_init(&hs);
|
||||
sha512_process(&hs, privkeyhash, SHA512_HASH_SIZE);
|
||||
sha512_process(&hs, msghash, SHA1_HASH_SIZE);
|
||||
sha512_done(&hs, proto_k);
|
||||
|
||||
/* generate k */
|
||||
m_mp_init(&dss_protok);
|
||||
bytes_to_mp(&dss_protok, proto_k, SHA512_HASH_SIZE);
|
||||
if (mp_mod(&dss_protok, key->q, &dss_k) != MP_OKAY) {
|
||||
dropbear_exit("dss error");
|
||||
}
|
||||
mp_clear(&dss_protok);
|
||||
m_burn(proto_k, SHA512_HASH_SIZE);
|
||||
#else /* DSS_PROTOK not defined*/
|
||||
gen_random_mpint(key->q, &dss_k);
|
||||
#endif
|
||||
|
||||
/* now generate the actual signature */
|
||||
bytes_to_mp(&dss_m, msghash, SHA1_HASH_SIZE);
|
||||
|
||||
/* g^k mod p */
|
||||
if (mp_exptmod(key->g, &dss_k, key->p, &dss_temp1) != MP_OKAY) {
|
||||
dropbear_exit("dss error");
|
||||
}
|
||||
/* r = (g^k mod p) mod q */
|
||||
if (mp_mod(&dss_temp1, key->q, &dss_r) != MP_OKAY) {
|
||||
dropbear_exit("dss error");
|
||||
}
|
||||
|
||||
/* x*r mod q */
|
||||
if (mp_mulmod(&dss_r, key->x, key->q, &dss_temp1) != MP_OKAY) {
|
||||
dropbear_exit("dss error");
|
||||
}
|
||||
/* (SHA1(M) + xr) mod q) */
|
||||
if (mp_addmod(&dss_m, &dss_temp1, key->q, &dss_temp2) != MP_OKAY) {
|
||||
dropbear_exit("dss error");
|
||||
}
|
||||
|
||||
/* (k^-1) mod q */
|
||||
if (mp_invmod(&dss_k, key->q, &dss_temp1) != MP_OKAY) {
|
||||
dropbear_exit("dss error");
|
||||
}
|
||||
|
||||
/* s = (k^-1(SHA1(M) + xr)) mod q */
|
||||
if (mp_mulmod(&dss_temp1, &dss_temp2, key->q, &dss_s) != MP_OKAY) {
|
||||
dropbear_exit("dss error");
|
||||
}
|
||||
|
||||
buf_putstring(buf, SSH_SIGNKEY_DSS, SSH_SIGNKEY_DSS_LEN);
|
||||
buf_putint(buf, 2*SHA1_HASH_SIZE);
|
||||
|
||||
writelen = mp_unsigned_bin_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))
|
||||
!= MP_OKAY) {
|
||||
dropbear_exit("dss error");
|
||||
}
|
||||
mp_clear(&dss_r);
|
||||
buf_incrwritepos(buf, writelen);
|
||||
|
||||
writelen = mp_unsigned_bin_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))
|
||||
!= MP_OKAY) {
|
||||
dropbear_exit("dss error");
|
||||
}
|
||||
mp_clear(&dss_s);
|
||||
buf_incrwritepos(buf, writelen);
|
||||
|
||||
mp_clear_multi(&dss_k, &dss_temp1, &dss_temp2, &dss_r, &dss_s,
|
||||
&dss_m, NULL);
|
||||
|
||||
/* create the signature to return */
|
||||
|
||||
TRACE(("leave buf_put_dss_sign"))
|
||||
}
|
||||
|
||||
#endif /* DROPBEAR_DSS */
|
||||
61
dss.h
Normal file
61
dss.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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 _DSS_H_
|
||||
#define _DSS_H_
|
||||
|
||||
#include "includes.h"
|
||||
#include "buffer.h"
|
||||
|
||||
#ifdef DROPBEAR_DSS
|
||||
|
||||
#define DSS_SIGNATURE_SIZE 4+SSH_SIGNKEY_DSS_LEN+4+2*SHA1_HASH_SIZE
|
||||
|
||||
struct DSS_key {
|
||||
|
||||
mp_int* p;
|
||||
mp_int* q;
|
||||
mp_int* g;
|
||||
mp_int* y;
|
||||
mp_int* x;
|
||||
|
||||
};
|
||||
|
||||
typedef struct DSS_key dss_key;
|
||||
|
||||
void buf_put_dss_sign(buffer* buf, dss_key *key, const unsigned char* data,
|
||||
unsigned int len);
|
||||
#ifdef DROPBEAR_SIGNKEY_VERIFY
|
||||
int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data,
|
||||
unsigned int len);
|
||||
#endif
|
||||
int buf_get_dss_pub_key(buffer* buf, dss_key *key);
|
||||
int buf_get_dss_priv_key(buffer* buf, dss_key *key);
|
||||
void buf_put_dss_pub_key(buffer* buf, dss_key *key);
|
||||
void buf_put_dss_priv_key(buffer* buf, dss_key *key);
|
||||
void dss_key_free(dss_key *key);
|
||||
|
||||
#endif /* DROPBEAR_DSS */
|
||||
|
||||
#endif /* _DSS_H_ */
|
||||
227
fake-rfc2553.c
Normal file
227
fake-rfc2553.c
Normal file
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
*
|
||||
* Taken from OpenSSH 3.8.1p1
|
||||
*
|
||||
* Copyright (C) 2000-2003 Damien Miller. All rights reserved.
|
||||
* Copyright (C) 1999 WIDE Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Pseudo-implementation of RFC2553 name / address resolution functions
|
||||
*
|
||||
* But these functions are not implemented correctly. The minimum subset
|
||||
* is implemented for ssh use only. For example, this routine assumes
|
||||
* that ai_family is AF_INET. Don't use it for another purpose.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
/* RCSID("$.Id: fake-rfc2553.c,v 1.5 2003/09/22 02:08:23 dtucker Exp $");*/
|
||||
|
||||
#ifndef HAVE_GETNAMEINFO
|
||||
int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
|
||||
size_t hostlen, char *serv, size_t servlen, int flags)
|
||||
{
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
|
||||
struct hostent *hp;
|
||||
char tmpserv[16];
|
||||
|
||||
if (serv != NULL) {
|
||||
snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port));
|
||||
if (strlcpy(serv, tmpserv, servlen) >= servlen)
|
||||
return (EAI_MEMORY);
|
||||
}
|
||||
|
||||
if (host != NULL) {
|
||||
if (flags & NI_NUMERICHOST) {
|
||||
if (strlcpy(host, inet_ntoa(sin->sin_addr),
|
||||
hostlen) >= hostlen)
|
||||
return (EAI_MEMORY);
|
||||
else
|
||||
return (0);
|
||||
} else {
|
||||
hp = gethostbyaddr((char *)&sin->sin_addr,
|
||||
sizeof(struct in_addr), AF_INET);
|
||||
if (hp == NULL)
|
||||
return (EAI_NODATA);
|
||||
|
||||
if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
|
||||
return (EAI_MEMORY);
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif /* !HAVE_GETNAMEINFO */
|
||||
|
||||
#ifndef HAVE_GAI_STRERROR
|
||||
#ifdef HAVE_CONST_GAI_STRERROR_PROTO
|
||||
const char *
|
||||
#else
|
||||
char *
|
||||
#endif
|
||||
gai_strerror(int err)
|
||||
{
|
||||
switch (err) {
|
||||
case EAI_NODATA:
|
||||
return ("no address associated with name");
|
||||
case EAI_MEMORY:
|
||||
return ("memory allocation failure.");
|
||||
case EAI_NONAME:
|
||||
return ("nodename nor servname provided, or not known");
|
||||
default:
|
||||
return ("unknown/invalid error.");
|
||||
}
|
||||
}
|
||||
#endif /* !HAVE_GAI_STRERROR */
|
||||
|
||||
#ifndef HAVE_FREEADDRINFO
|
||||
void
|
||||
freeaddrinfo(struct addrinfo *ai)
|
||||
{
|
||||
struct addrinfo *next;
|
||||
|
||||
for(; ai != NULL;) {
|
||||
next = ai->ai_next;
|
||||
free(ai);
|
||||
ai = next;
|
||||
}
|
||||
}
|
||||
#endif /* !HAVE_FREEADDRINFO */
|
||||
|
||||
#ifndef HAVE_GETADDRINFO
|
||||
static struct
|
||||
addrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints)
|
||||
{
|
||||
struct addrinfo *ai;
|
||||
|
||||
ai = malloc(sizeof(*ai) + sizeof(struct sockaddr_in));
|
||||
if (ai == NULL)
|
||||
return (NULL);
|
||||
|
||||
memset(ai, '\0', sizeof(*ai) + sizeof(struct sockaddr_in));
|
||||
|
||||
ai->ai_addr = (struct sockaddr *)(ai + 1);
|
||||
/* XXX -- ssh doesn't use sa_len */
|
||||
ai->ai_addrlen = sizeof(struct sockaddr_in);
|
||||
ai->ai_addr->sa_family = ai->ai_family = AF_INET;
|
||||
|
||||
((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
|
||||
((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
|
||||
|
||||
/* XXX: the following is not generally correct, but does what we want */
|
||||
if (hints->ai_socktype)
|
||||
ai->ai_socktype = hints->ai_socktype;
|
||||
else
|
||||
ai->ai_socktype = SOCK_STREAM;
|
||||
|
||||
if (hints->ai_protocol)
|
||||
ai->ai_protocol = hints->ai_protocol;
|
||||
|
||||
return (ai);
|
||||
}
|
||||
|
||||
int
|
||||
getaddrinfo(const char *hostname, const char *servname,
|
||||
const struct addrinfo *hints, struct addrinfo **res)
|
||||
{
|
||||
struct hostent *hp;
|
||||
struct servent *sp;
|
||||
struct in_addr in;
|
||||
int i;
|
||||
long int port;
|
||||
u_long addr;
|
||||
|
||||
port = 0;
|
||||
if (servname != NULL) {
|
||||
char *cp;
|
||||
|
||||
port = strtol(servname, &cp, 10);
|
||||
if (port > 0 && port <= 65535 && *cp == '\0')
|
||||
port = htons(port);
|
||||
else if ((sp = getservbyname(servname, NULL)) != NULL)
|
||||
port = sp->s_port;
|
||||
else
|
||||
port = 0;
|
||||
}
|
||||
|
||||
if (hints && hints->ai_flags & AI_PASSIVE) {
|
||||
addr = htonl(0x00000000);
|
||||
if (hostname && inet_aton(hostname, &in) != 0)
|
||||
addr = in.s_addr;
|
||||
*res = malloc_ai(port, addr, hints);
|
||||
if (*res == NULL)
|
||||
return (EAI_MEMORY);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (!hostname) {
|
||||
*res = malloc_ai(port, htonl(0x7f000001), hints);
|
||||
if (*res == NULL)
|
||||
return (EAI_MEMORY);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (inet_aton(hostname, &in)) {
|
||||
*res = malloc_ai(port, in.s_addr, hints);
|
||||
if (*res == NULL)
|
||||
return (EAI_MEMORY);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Don't try DNS if AI_NUMERICHOST is set */
|
||||
if (hints && hints->ai_flags & AI_NUMERICHOST)
|
||||
return (EAI_NONAME);
|
||||
|
||||
hp = gethostbyname(hostname);
|
||||
if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
|
||||
struct addrinfo *cur, *prev;
|
||||
|
||||
cur = prev = *res = NULL;
|
||||
for (i = 0; hp->h_addr_list[i]; i++) {
|
||||
struct in_addr *in = (struct in_addr *)hp->h_addr_list[i];
|
||||
|
||||
cur = malloc_ai(port, in->s_addr, hints);
|
||||
if (cur == NULL) {
|
||||
if (*res != NULL)
|
||||
freeaddrinfo(*res);
|
||||
return (EAI_MEMORY);
|
||||
}
|
||||
if (prev)
|
||||
prev->ai_next = cur;
|
||||
else
|
||||
*res = cur;
|
||||
|
||||
prev = cur;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (EAI_NODATA);
|
||||
}
|
||||
#endif /* !HAVE_GETADDRINFO */
|
||||
162
fake-rfc2553.h
Normal file
162
fake-rfc2553.h
Normal file
@@ -0,0 +1,162 @@
|
||||
/* Taken from OpenSSH 3.8.1p1 */
|
||||
|
||||
/* $.Id: fake-rfc2553.h,v 1.9 2004/03/10 10:06:33 dtucker Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000-2003 Damien Miller. All rights reserved.
|
||||
* Copyright (C) 1999 WIDE Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Pseudo-implementation of RFC2553 name / address resolution functions
|
||||
*
|
||||
* But these functions are not implemented correctly. The minimum subset
|
||||
* is implemented for ssh use only. For example, this routine assumes
|
||||
* that ai_family is AF_INET. Don't use it for another purpose.
|
||||
*/
|
||||
|
||||
#ifndef _FAKE_RFC2553_H
|
||||
#define _FAKE_RFC2553_H
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
/*
|
||||
* First, socket and INET6 related definitions
|
||||
*/
|
||||
#ifndef HAVE_STRUCT_SOCKADDR_STORAGE
|
||||
# define _SS_MAXSIZE 128 /* Implementation specific max size */
|
||||
# define _SS_PADSIZE (_SS_MAXSIZE - sizeof (struct sockaddr))
|
||||
struct sockaddr_storage {
|
||||
struct sockaddr ss_sa;
|
||||
char __ss_pad2[_SS_PADSIZE];
|
||||
};
|
||||
# define ss_family ss_sa.sa_family
|
||||
#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */
|
||||
|
||||
#ifndef IN6_IS_ADDR_LOOPBACK
|
||||
# define IN6_IS_ADDR_LOOPBACK(a) \
|
||||
(((u_int32_t *)(a))[0] == 0 && ((u_int32_t *)(a))[1] == 0 && \
|
||||
((u_int32_t *)(a))[2] == 0 && ((u_int32_t *)(a))[3] == htonl(1))
|
||||
#endif /* !IN6_IS_ADDR_LOOPBACK */
|
||||
|
||||
#ifndef HAVE_STRUCT_IN6_ADDR
|
||||
struct in6_addr {
|
||||
u_int8_t s6_addr[16];
|
||||
};
|
||||
#endif /* !HAVE_STRUCT_IN6_ADDR */
|
||||
|
||||
#ifndef HAVE_STRUCT_SOCKADDR_IN6
|
||||
struct sockaddr_in6 {
|
||||
unsigned short sin6_family;
|
||||
u_int16_t sin6_port;
|
||||
u_int32_t sin6_flowinfo;
|
||||
struct in6_addr sin6_addr;
|
||||
};
|
||||
#endif /* !HAVE_STRUCT_SOCKADDR_IN6 */
|
||||
|
||||
#ifndef AF_INET6
|
||||
/* Define it to something that should never appear */
|
||||
#define AF_INET6 AF_MAX
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Next, RFC2553 name / address resolution API
|
||||
*/
|
||||
|
||||
#ifndef NI_NUMERICHOST
|
||||
# define NI_NUMERICHOST (1)
|
||||
#endif
|
||||
#ifndef NI_NAMEREQD
|
||||
# define NI_NAMEREQD (1<<1)
|
||||
#endif
|
||||
#ifndef NI_NUMERICSERV
|
||||
# define NI_NUMERICSERV (1<<2)
|
||||
#endif
|
||||
|
||||
#ifndef AI_PASSIVE
|
||||
# define AI_PASSIVE (1)
|
||||
#endif
|
||||
#ifndef AI_CANONNAME
|
||||
# define AI_CANONNAME (1<<1)
|
||||
#endif
|
||||
#ifndef AI_NUMERICHOST
|
||||
# define AI_NUMERICHOST (1<<2)
|
||||
#endif
|
||||
|
||||
#ifndef NI_MAXSERV
|
||||
# define NI_MAXSERV 32
|
||||
#endif /* !NI_MAXSERV */
|
||||
#ifndef NI_MAXHOST
|
||||
# define NI_MAXHOST 1025
|
||||
#endif /* !NI_MAXHOST */
|
||||
|
||||
#ifndef EAI_NODATA
|
||||
# define EAI_NODATA 1
|
||||
# define EAI_MEMORY 2
|
||||
# define EAI_NONAME 3
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRUCT_ADDRINFO
|
||||
struct addrinfo {
|
||||
int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
|
||||
int ai_family; /* PF_xxx */
|
||||
int ai_socktype; /* SOCK_xxx */
|
||||
int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
|
||||
size_t ai_addrlen; /* length of ai_addr */
|
||||
char *ai_canonname; /* canonical name for hostname */
|
||||
struct sockaddr *ai_addr; /* binary address */
|
||||
struct addrinfo *ai_next; /* next structure in linked list */
|
||||
};
|
||||
#endif /* !HAVE_STRUCT_ADDRINFO */
|
||||
|
||||
#ifndef HAVE_GETADDRINFO
|
||||
#ifdef getaddrinfo
|
||||
# undef getaddrinfo
|
||||
#endif
|
||||
#define getaddrinfo(a,b,c,d) (ssh_getaddrinfo(a,b,c,d))
|
||||
int getaddrinfo(const char *, const char *,
|
||||
const struct addrinfo *, struct addrinfo **);
|
||||
#endif /* !HAVE_GETADDRINFO */
|
||||
|
||||
#if !defined(HAVE_GAI_STRERROR) && !defined(HAVE_CONST_GAI_STRERROR_PROTO)
|
||||
#define gai_strerror(a) (ssh_gai_strerror(a))
|
||||
char *gai_strerror(int);
|
||||
#endif /* !HAVE_GAI_STRERROR */
|
||||
|
||||
#ifndef HAVE_FREEADDRINFO
|
||||
#define freeaddrinfo(a) (ssh_freeaddrinfo(a))
|
||||
void freeaddrinfo(struct addrinfo *);
|
||||
#endif /* !HAVE_FREEADDRINFO */
|
||||
|
||||
#ifndef HAVE_GETNAMEINFO
|
||||
#define getnameinfo(a,b,c,d,e,f,g) (ssh_getnameinfo(a,b,c,d,e,f,g))
|
||||
int getnameinfo(const struct sockaddr *, size_t, char *, size_t,
|
||||
char *, size_t, int);
|
||||
#endif /* !HAVE_GETNAMEINFO */
|
||||
|
||||
#endif /* !_FAKE_RFC2553_H */
|
||||
|
||||
117
filelist.txt
Normal file
117
filelist.txt
Normal file
@@ -0,0 +1,117 @@
|
||||
This file is out of date - it remains here in case it is still of use.
|
||||
The basic naming convention is svr- and cli- for seperate parts,
|
||||
then common- for common parts. Some files have no prefix.
|
||||
|
||||
A brief rundown on which files do what, and their corresponding sections
|
||||
in the IETF drafts. The .c files usually have corresponding .h files.
|
||||
|
||||
Transport layer draft-ietf-secsh-transport-16.txt
|
||||
===============
|
||||
|
||||
session.c Contains the main select() loop, and handles setting
|
||||
up/closing down ssh connections
|
||||
|
||||
algo.c Framework for handling various ciphers/hashes/algos,
|
||||
and choosing between the lists of client/server
|
||||
preferred ones
|
||||
|
||||
kex.c Key exchange routines, used at startup to negotiate
|
||||
which algorithms to use, and also to obtain session
|
||||
keys. This also runs when rekeying during the
|
||||
connection.
|
||||
|
||||
packet.c Handles the basic packet encryption/decryption,
|
||||
and switching to the appropriate packet handlers.
|
||||
Called from session.c's main select loop.
|
||||
|
||||
service.c Handles service requests (userauth or connection)
|
||||
|
||||
|
||||
Authentication draft-ietf-secsh-userauth-17.txt
|
||||
==============
|
||||
|
||||
auth.c General auth handling, including user checking etc,
|
||||
passes different auth types to auth{passwd,pubkey}
|
||||
|
||||
authpasswd.c Handles /etc/passwd or /etc/shadow auth
|
||||
|
||||
authpubkey.c Handles ~/.ssh/authorized_keys auth
|
||||
|
||||
|
||||
Connection draft-ietf-secsh-connect-17.txt
|
||||
==========
|
||||
|
||||
channel.c Channel handling routines - each shell/tcp conn/agent
|
||||
etc is a channel.
|
||||
|
||||
chansession.c Handles shell/exec requests
|
||||
|
||||
sshpty.c From OpenSSH, allocates PTYs etc
|
||||
|
||||
termcodes.c Mapping of POSIX terminal codes to SSH terminal codes
|
||||
|
||||
loginrec.c From OpenSSH, handles utmp/wtmp logging
|
||||
|
||||
x11fwd.c Handles X11 forwarding
|
||||
|
||||
agentfwd.c Handles auth-agent forwarding requests
|
||||
|
||||
localtcpfwd.c Handles -L style tcp forwarding requests, setting
|
||||
up the listening port and also handling connections
|
||||
to that port (and subsequent channels)
|
||||
|
||||
|
||||
Program-related
|
||||
===============
|
||||
|
||||
dbmulti.c Combination binary chooser main() function
|
||||
|
||||
dbutil.c Various utility functions, incl logging, memory etc
|
||||
|
||||
dropbearconvert.c Conversion from dropbear<->openssh keys, uses
|
||||
keyimport.c to do most of the work
|
||||
|
||||
dropbearkey.c Generates keys, calling gen{dss,rsa}
|
||||
|
||||
keyimport.c Modified from PuTTY, converts between key types
|
||||
|
||||
main.c dropbear's main(), handles listening, forking for
|
||||
new connections, child-process limits
|
||||
|
||||
runopts.c Parses commandline options
|
||||
|
||||
options.h Compile-time feature selection
|
||||
|
||||
config.h Features selected from configure
|
||||
|
||||
debug.h Compile-time selection of debug features
|
||||
|
||||
includes.h Included system headers etc
|
||||
|
||||
|
||||
Generic Routines
|
||||
================
|
||||
|
||||
signkey.c A generic handler for pubkeys, switches to dss or rsa
|
||||
depending on the key type
|
||||
|
||||
rsa.c RSA asymmetric crypto routines
|
||||
|
||||
dss.c DSS asymmetric crypto routines
|
||||
|
||||
gendss.c DSS key generation
|
||||
|
||||
genrsa.c RSA key generation
|
||||
|
||||
bignum.c Some bignum helper functions
|
||||
|
||||
queue.c A queue, used to enqueue encrypted packets to send
|
||||
|
||||
random.c PRNG, based on /dev/urandom or prngd
|
||||
|
||||
atomicio.c From OpenSSH, does `blocking' IO on non-blocking fds
|
||||
|
||||
buffer.c Buffer-usage routines, with size checking etc
|
||||
|
||||
|
||||
vim:set ts=8:
|
||||
198
gendss.c
Normal file
198
gendss.c
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* 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 "signkey.h"
|
||||
#include "bignum.h"
|
||||
#include "random.h"
|
||||
#include "buffer.h"
|
||||
#include "gendss.h"
|
||||
#include "dss.h"
|
||||
|
||||
#define QSIZE 20 /* 160 bit */
|
||||
|
||||
/* This is just a test */
|
||||
|
||||
#ifdef DROPBEAR_DSS
|
||||
|
||||
static void getq(dss_key *key);
|
||||
static void getp(dss_key *key, unsigned int size);
|
||||
static void getg(dss_key *key);
|
||||
static void getx(dss_key *key);
|
||||
static void gety(dss_key *key);
|
||||
|
||||
dss_key * gen_dss_priv_key(unsigned int size) {
|
||||
|
||||
dss_key *key;
|
||||
|
||||
key = (dss_key*)m_malloc(sizeof(dss_key));
|
||||
|
||||
key->p = (mp_int*)m_malloc(sizeof(mp_int));
|
||||
key->q = (mp_int*)m_malloc(sizeof(mp_int));
|
||||
key->g = (mp_int*)m_malloc(sizeof(mp_int));
|
||||
key->y = (mp_int*)m_malloc(sizeof(mp_int));
|
||||
key->x = (mp_int*)m_malloc(sizeof(mp_int));
|
||||
m_mp_init_multi(key->p, key->q, key->g, key->y, key->x, NULL);
|
||||
|
||||
seedrandom();
|
||||
|
||||
getq(key);
|
||||
getp(key, size);
|
||||
getg(key);
|
||||
getx(key);
|
||||
gety(key);
|
||||
|
||||
return key;
|
||||
|
||||
}
|
||||
|
||||
static void getq(dss_key *key) {
|
||||
|
||||
char buf[QSIZE];
|
||||
|
||||
/* 160 bit prime */
|
||||
genrandom(buf, QSIZE);
|
||||
buf[0] |= 0x80; /* top bit high */
|
||||
buf[QSIZE-1] |= 0x01; /* bottom bit high */
|
||||
|
||||
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) {
|
||||
fprintf(stderr, "dss key generation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void getp(dss_key *key, unsigned int size) {
|
||||
|
||||
DEF_MP_INT(tempX);
|
||||
DEF_MP_INT(tempC);
|
||||
DEF_MP_INT(tempP);
|
||||
DEF_MP_INT(temp2q);
|
||||
int result;
|
||||
unsigned char *buf;
|
||||
|
||||
m_mp_init_multi(&tempX, &tempC, &tempP, &temp2q, NULL);
|
||||
|
||||
|
||||
/* 2*q */
|
||||
if (mp_mul_d(key->q, 2, &temp2q) != MP_OKAY) {
|
||||
fprintf(stderr, "dss key generation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
buf = (unsigned char*)m_malloc(size);
|
||||
|
||||
result = 0;
|
||||
do {
|
||||
|
||||
genrandom(buf, size);
|
||||
buf[0] |= 0x80; /* set the top bit high */
|
||||
|
||||
/* X is a random mp_int */
|
||||
bytes_to_mp(&tempX, buf, size);
|
||||
|
||||
/* C = X mod 2q */
|
||||
if (mp_mod(&tempX, &temp2q, &tempC) != MP_OKAY) {
|
||||
fprintf(stderr, "dss key generation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* P = X - (C - 1) = X - C + 1*/
|
||||
if (mp_sub(&tempX, &tempC, &tempP) != MP_OKAY) {
|
||||
fprintf(stderr, "dss key generation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (mp_add_d(&tempP, 1, key->p) != MP_OKAY) {
|
||||
fprintf(stderr, "dss key generation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* now check for prime, 5 rounds is enough according to HAC */
|
||||
/* result == 1 => p is prime */
|
||||
if (mp_prime_is_prime(key->p, 5, &result) != MP_OKAY) {
|
||||
fprintf(stderr, "dss key generation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
} while (!result);
|
||||
|
||||
mp_clear_multi(&tempX, &tempC, &tempP, &temp2q, NULL);
|
||||
m_burn(buf, size);
|
||||
m_free(buf);
|
||||
}
|
||||
|
||||
static void getg(dss_key * key) {
|
||||
|
||||
DEF_MP_INT(div);
|
||||
DEF_MP_INT(h);
|
||||
DEF_MP_INT(val);
|
||||
|
||||
m_mp_init_multi(&div, &h, &val, NULL);
|
||||
|
||||
/* get div=(p-1)/q */
|
||||
if (mp_sub_d(key->p, 1, &val) != MP_OKAY) {
|
||||
fprintf(stderr, "dss key generation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
if (mp_div(&val, key->q, &div, NULL) != MP_OKAY) {
|
||||
fprintf(stderr, "dss key generation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* initialise h=1 */
|
||||
mp_set(&h, 1);
|
||||
do {
|
||||
/* now keep going with g=h^div mod p, until g > 1 */
|
||||
if (mp_exptmod(&h, &div, key->p, key->g) != MP_OKAY) {
|
||||
fprintf(stderr, "dss key generation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (mp_add_d(&h, 1, &h) != MP_OKAY) {
|
||||
fprintf(stderr, "dss key generation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
} while (mp_cmp_d(key->g, 1) != MP_GT);
|
||||
|
||||
mp_clear_multi(&div, &h, &val, NULL);
|
||||
}
|
||||
|
||||
static void getx(dss_key *key) {
|
||||
|
||||
gen_random_mpint(key->q, key->x);
|
||||
}
|
||||
|
||||
static void gety(dss_key *key) {
|
||||
|
||||
if (mp_exptmod(key->g, key->x, key->p, key->y) != MP_OKAY) {
|
||||
fprintf(stderr, "dss key generation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* DROPBEAR_DSS */
|
||||
36
gendss.h
Normal file
36
gendss.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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 _GENDSS_H_
|
||||
#define _GENDSS_H_
|
||||
|
||||
#include "dss.h"
|
||||
|
||||
#ifdef DROPBEAR_DSS
|
||||
|
||||
dss_key * gen_dss_priv_key(unsigned int size);
|
||||
|
||||
#endif /* DROPBEAR_DSS */
|
||||
|
||||
#endif /* _GENDSS_H_ */
|
||||
133
genrsa.c
Normal file
133
genrsa.c
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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 "bignum.h"
|
||||
#include "random.h"
|
||||
#include "rsa.h"
|
||||
#include "genrsa.h"
|
||||
|
||||
#define RSA_E 65537
|
||||
|
||||
#ifdef DROPBEAR_RSA
|
||||
|
||||
static void getrsaprime(mp_int* prime, mp_int *primeminus,
|
||||
mp_int* rsa_e, unsigned int size);
|
||||
|
||||
/* mostly taken from libtomcrypt's rsa key generation routine */
|
||||
rsa_key * gen_rsa_priv_key(unsigned int size) {
|
||||
|
||||
rsa_key * key;
|
||||
DEF_MP_INT(pminus);
|
||||
DEF_MP_INT(qminus);
|
||||
DEF_MP_INT(lcm);
|
||||
|
||||
key = (rsa_key*)m_malloc(sizeof(rsa_key));
|
||||
|
||||
key->e = (mp_int*)m_malloc(sizeof(mp_int));
|
||||
key->n = (mp_int*)m_malloc(sizeof(mp_int));
|
||||
key->d = (mp_int*)m_malloc(sizeof(mp_int));
|
||||
key->p = (mp_int*)m_malloc(sizeof(mp_int));
|
||||
key->q = (mp_int*)m_malloc(sizeof(mp_int));
|
||||
|
||||
m_mp_init_multi(key->e, key->n, key->d, key->p, key->q,
|
||||
&pminus, &lcm, &qminus, NULL);
|
||||
|
||||
seedrandom();
|
||||
|
||||
if (mp_set_int(key->e, RSA_E) != MP_OKAY) {
|
||||
fprintf(stderr, "rsa generation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
getrsaprime(key->p, &pminus, key->e, size/2);
|
||||
getrsaprime(key->q, &qminus, key->e, size/2);
|
||||
|
||||
if (mp_mul(key->p, key->q, key->n) != MP_OKAY) {
|
||||
fprintf(stderr, "rsa generation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* lcm(p-1, q-1) */
|
||||
if (mp_lcm(&pminus, &qminus, &lcm) != MP_OKAY) {
|
||||
fprintf(stderr, "rsa generation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* de = 1 mod lcm(p-1,q-1) */
|
||||
/* therefore d = (e^-1) mod lcm(p-1,q-1) */
|
||||
if (mp_invmod(key->e, &lcm, key->d) != MP_OKAY) {
|
||||
fprintf(stderr, "rsa generation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
mp_clear_multi(&pminus, &qminus, &lcm, NULL);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
/* return a prime suitable for p or q */
|
||||
static void getrsaprime(mp_int* prime, mp_int *primeminus,
|
||||
mp_int* rsa_e, unsigned int size) {
|
||||
|
||||
unsigned char *buf;
|
||||
DEF_MP_INT(temp_gcd);
|
||||
|
||||
buf = (unsigned char*)m_malloc(size+1);
|
||||
|
||||
m_mp_init(&temp_gcd);
|
||||
do {
|
||||
/* generate a random odd number with MSB set, then find the
|
||||
the next prime above it */
|
||||
genrandom(buf, size+1);
|
||||
buf[0] |= 0x80; /* MSB set */
|
||||
|
||||
bytes_to_mp(prime, buf, size+1);
|
||||
|
||||
/* find the next integer which is prime, 8 round of miller-rabin */
|
||||
if (mp_prime_next_prime(prime, 8, 0) != MP_OKAY) {
|
||||
fprintf(stderr, "rsa generation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* subtract one to get p-1 */
|
||||
if (mp_sub_d(prime, 1, primeminus) != MP_OKAY) {
|
||||
fprintf(stderr, "rsa generation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
/* check relative primality to e */
|
||||
if (mp_gcd(primeminus, rsa_e, &temp_gcd) != MP_OKAY) {
|
||||
fprintf(stderr, "rsa generation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
} while (mp_cmp_d(&temp_gcd, 1) != MP_EQ); /* while gcd(p-1, e) != 1 */
|
||||
|
||||
/* now we have a good value for result */
|
||||
mp_clear(&temp_gcd);
|
||||
m_burn(buf, size+1);
|
||||
m_free(buf);
|
||||
}
|
||||
|
||||
#endif /* DROPBEAR_RSA */
|
||||
36
genrsa.h
Normal file
36
genrsa.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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 _GENRSA_H_
|
||||
#define _GENRSA_H_
|
||||
|
||||
#include "rsa.h"
|
||||
|
||||
#ifdef DROPBEAR_RSA
|
||||
|
||||
rsa_key * gen_rsa_priv_key(unsigned int size);
|
||||
|
||||
#endif /* DROPBEAR_RSA */
|
||||
|
||||
#endif /* _GENRSA_H_ */
|
||||
150
includes.h
Normal file
150
includes.h
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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 _INCLUDES_H_
|
||||
#define _INCLUDES_H_
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include "options.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/param.h> /* required for BSD4_4 define */
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <grp.h>
|
||||
#include <limits.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <syslog.h>
|
||||
#include <netdb.h>
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <dirent.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef HAVE_UTMP_H
|
||||
#include <utmp.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UTMPX_H
|
||||
#include <utmpx.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PATHS_H
|
||||
#include <paths.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LASTLOG_H
|
||||
#include <lastlog.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
/* netbsd 1.6 needs this to be included before netinet/ip.h for some
|
||||
* undocumented reason */
|
||||
#ifdef HAVE_NETINET_IN_SYSTM_H
|
||||
#include <netinet/in_systm.h>
|
||||
#endif
|
||||
|
||||
#include <netinet/ip.h>
|
||||
|
||||
#ifdef HAVE_NETINET_TCP_H
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBUTIL_H
|
||||
#include <libutil.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CRYPT_H
|
||||
#include <crypt.h>
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_ZLIB
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UTIL_H
|
||||
#include <util.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SHADOW_H
|
||||
#include <shadow.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBGEN_H
|
||||
#include <libgen.h>
|
||||
#endif
|
||||
|
||||
#include "libtomcrypt/src/headers/tomcrypt.h"
|
||||
#include "libtommath/tommath.h"
|
||||
|
||||
#include "compat.h"
|
||||
#include "fake-rfc2553.h"
|
||||
|
||||
#ifndef HAVE_UINT16_T
|
||||
#ifndef HAVE_U_INT16_T
|
||||
typedef unsigned short u_int16_t;
|
||||
#endif /* HAVE_U_INT16_T */
|
||||
typedef u_int16_t uint16_t;
|
||||
#endif /* HAVE_UINT16_T */
|
||||
|
||||
#ifndef LOG_AUTHPRIV
|
||||
#define LOG_AUTHPRIV LOG_AUTH
|
||||
#endif
|
||||
|
||||
/* so we can avoid warnings about unused params (ie in signal handlers etc) */
|
||||
#ifdef UNUSED
|
||||
#elif defined(__GNUC__)
|
||||
# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
|
||||
#elif defined(__LCLINT__)
|
||||
# define UNUSED(x) /*@unused@*/ x
|
||||
#else
|
||||
# define UNUSED(x) x
|
||||
#endif
|
||||
|
||||
#endif /* _INCLUDES_H_ */
|
||||
251
install-sh
Normal file
251
install-sh
Normal file
@@ -0,0 +1,251 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# install - install a program, script, or datafile
|
||||
# This comes from X11R5 (mit/util/scripts/install.sh).
|
||||
#
|
||||
# Copyright 1991 by the Massachusetts Institute of Technology
|
||||
#
|
||||
# Permission to use, copy, modify, distribute, and sell this software and its
|
||||
# documentation for any purpose is hereby granted without fee, provided that
|
||||
# the above copyright notice appear in all copies and that both that
|
||||
# copyright notice and this permission notice appear in supporting
|
||||
# documentation, and that the name of M.I.T. not be used in advertising or
|
||||
# publicity pertaining to distribution of the software without specific,
|
||||
# written prior permission. M.I.T. makes no representations about the
|
||||
# suitability of this software for any purpose. It is provided "as is"
|
||||
# without express or implied warranty.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch. It can only install one file at a time, a restriction
|
||||
# shared with many OS's install programs.
|
||||
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit="${DOITPROG-}"
|
||||
|
||||
|
||||
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||
|
||||
mvprog="${MVPROG-mv}"
|
||||
cpprog="${CPPROG-cp}"
|
||||
chmodprog="${CHMODPROG-chmod}"
|
||||
chownprog="${CHOWNPROG-chown}"
|
||||
chgrpprog="${CHGRPPROG-chgrp}"
|
||||
stripprog="${STRIPPROG-strip}"
|
||||
rmprog="${RMPROG-rm}"
|
||||
mkdirprog="${MKDIRPROG-mkdir}"
|
||||
|
||||
transformbasename=""
|
||||
transform_arg=""
|
||||
instcmd="$mvprog"
|
||||
chmodcmd="$chmodprog 0755"
|
||||
chowncmd=""
|
||||
chgrpcmd=""
|
||||
stripcmd=""
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
src=""
|
||||
dst=""
|
||||
dir_arg=""
|
||||
|
||||
while [ x"$1" != x ]; do
|
||||
case $1 in
|
||||
-c) instcmd="$cpprog"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-s) stripcmd="$stripprog"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
*) if [ x"$src" = x ]
|
||||
then
|
||||
src=$1
|
||||
else
|
||||
# this colon is to work around a 386BSD /bin/sh bug
|
||||
:
|
||||
dst=$1
|
||||
fi
|
||||
shift
|
||||
continue;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ x"$src" = x ]
|
||||
then
|
||||
echo "install: no input file specified"
|
||||
exit 1
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]; then
|
||||
dst=$src
|
||||
src=""
|
||||
|
||||
if [ -d $dst ]; then
|
||||
instcmd=:
|
||||
chmodcmd=""
|
||||
else
|
||||
instcmd=mkdir
|
||||
fi
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
|
||||
if [ -f $src -o -d $src ]
|
||||
then
|
||||
true
|
||||
else
|
||||
echo "install: $src does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ x"$dst" = x ]
|
||||
then
|
||||
echo "install: no destination specified"
|
||||
exit 1
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
# If destination is a directory, append the input filename; if your system
|
||||
# does not like double slashes in filenames, you may need to add some logic
|
||||
|
||||
if [ -d $dst ]
|
||||
then
|
||||
dst="$dst"/`basename $src`
|
||||
else
|
||||
true
|
||||
fi
|
||||
fi
|
||||
|
||||
## this sed command emulates the dirname command
|
||||
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||
|
||||
# Make sure that the destination directory exists.
|
||||
# this part is taken from Noah Friedman's mkinstalldirs script
|
||||
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if [ ! -d "$dstdir" ]; then
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-${defaultIFS}}"
|
||||
|
||||
oIFS="${IFS}"
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
IFS="${oIFS}"
|
||||
|
||||
pathcomp=''
|
||||
|
||||
while [ $# -ne 0 ] ; do
|
||||
pathcomp="${pathcomp}${1}"
|
||||
shift
|
||||
|
||||
if [ ! -d "${pathcomp}" ] ;
|
||||
then
|
||||
$mkdirprog "${pathcomp}"
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
pathcomp="${pathcomp}/"
|
||||
done
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]
|
||||
then
|
||||
$doit $instcmd $dst &&
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
|
||||
else
|
||||
|
||||
# If we're going to rename the final executable, determine the name now.
|
||||
|
||||
if [ x"$transformarg" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
else
|
||||
dstfile=`basename $dst $transformbasename |
|
||||
sed $transformarg`$transformbasename
|
||||
fi
|
||||
|
||||
# don't allow the sed command to completely eliminate the filename
|
||||
|
||||
if [ x"$dstfile" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
# Make a temp file name in the proper directory.
|
||||
|
||||
dsttmp=$dstdir/#inst.$$#
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
|
||||
$doit $instcmd $src $dsttmp &&
|
||||
|
||||
trap "rm -f ${dsttmp}" 0 &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits
|
||||
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $instcmd $src $dsttmp" command.
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
|
||||
$doit $rmcmd -f $dstdir/$dstfile &&
|
||||
$doit $mvcmd $dsttmp $dstdir/$dstfile
|
||||
|
||||
fi &&
|
||||
|
||||
|
||||
exit 0
|
||||
69
kex.h
Normal file
69
kex.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 _KEX_H_
|
||||
#define _KEX_H_
|
||||
|
||||
#include "includes.h"
|
||||
#include "algo.h"
|
||||
|
||||
void send_msg_kexinit();
|
||||
void recv_msg_kexinit();
|
||||
void send_msg_newkeys();
|
||||
void recv_msg_newkeys();
|
||||
void kexfirstinitialise();
|
||||
void gen_kexdh_vals(mp_int *dh_pub, mp_int *dh_priv);
|
||||
void kexdh_comb_key(mp_int *dh_pub_us, mp_int *dh_priv, mp_int *dh_pub_them,
|
||||
sign_key *hostkey);
|
||||
|
||||
#ifndef DISABLE_ZLIB
|
||||
int is_compress_trans();
|
||||
int is_compress_recv();
|
||||
#endif
|
||||
|
||||
void recv_msg_kexdh_init(); /* server */
|
||||
|
||||
void send_msg_kexdh_init(); /* client */
|
||||
void recv_msg_kexdh_reply(); /* client */
|
||||
|
||||
struct KEXState {
|
||||
|
||||
unsigned sentkexinit : 1; /*set when we've sent/recv kexinit packet */
|
||||
unsigned recvkexinit : 1;
|
||||
unsigned firstfollows : 1; /* true when first_kex_packet_follows is set */
|
||||
unsigned sentnewkeys : 1; /* set once we've send/recv'ed MSG_NEWKEYS*/
|
||||
unsigned recvnewkeys : 1;
|
||||
|
||||
unsigned donefirstkex : 1; /* Set to 1 after the first kex has completed,
|
||||
ie the transport layer has been set up */
|
||||
|
||||
time_t lastkextime; /* time of the last kex */
|
||||
unsigned int datatrans; /* data transmitted since last kex */
|
||||
unsigned int datarecv; /* data received since last kex */
|
||||
|
||||
};
|
||||
|
||||
#define MAX_KEXHASHBUF 2000
|
||||
|
||||
#endif /* _KEX_H_ */
|
||||
1692
keyimport.c
Normal file
1692
keyimport.c
Normal file
File diff suppressed because it is too large
Load Diff
42
keyimport.h
Normal file
42
keyimport.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Dropbear SSH
|
||||
*
|
||||
* 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 _KEYIMPORT_H_
|
||||
#define _KEYIMPORT_H_
|
||||
|
||||
#include "includes.h"
|
||||
#include "signkey.h"
|
||||
|
||||
enum {
|
||||
KEYFILE_DROPBEAR,
|
||||
KEYFILE_OPENSSH,
|
||||
KEYFILE_SSHCOM
|
||||
};
|
||||
|
||||
int import_write(const char *filename, sign_key *key, char *passphrase,
|
||||
int filetype);
|
||||
sign_key *import_read(const char *filename, char *passphrase, int filetype);
|
||||
int import_encrypted(const char* filename, int filetype);
|
||||
|
||||
#endif /* _KEYIMPORT_H_ */
|
||||
1155
libtomcrypt/Doxyfile
Normal file
1155
libtomcrypt/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
5
libtomcrypt/LICENSE
Normal file
5
libtomcrypt/LICENSE
Normal file
@@ -0,0 +1,5 @@
|
||||
LibTomCrypt is public domain. As should all quality software be.
|
||||
|
||||
Tom St Denis
|
||||
|
||||
|
||||
317
libtomcrypt/Makefile.in
Normal file
317
libtomcrypt/Makefile.in
Normal file
@@ -0,0 +1,317 @@
|
||||
# MAKEFILE for linux GCC
|
||||
#
|
||||
# Tom St Denis
|
||||
# Modified by Clay Culver
|
||||
|
||||
# The version
|
||||
VERSION=1.16
|
||||
|
||||
VPATH=@srcdir@
|
||||
srcdir=@srcdir@
|
||||
|
||||
# Compiler and Linker Names
|
||||
#CC=gcc
|
||||
#LD=ld
|
||||
|
||||
# Archiver [makes .a files]
|
||||
#AR=ar
|
||||
#ARFLAGS=r
|
||||
|
||||
# Compilation flags. Note the += does not write over the user's CFLAGS!
|
||||
# The rest of the flags come from the parent Dropbear makefile
|
||||
CFLAGS += -c -I$(srcdir)/src/headers/ -I$(srcdir)/../
|
||||
|
||||
# additional warnings (newer GCC 3.4 and higher)
|
||||
ifdef GCC_34
|
||||
CFLAGS += -Wsystem-headers -Wdeclaration-after-statement -Wbad-function-cast -Wcast-align -Wstrict-prototypes -Wmissing-prototypes \
|
||||
-Wmissing-declarations -Wpointer-arith
|
||||
endif
|
||||
|
||||
ifndef IGNORE_SPEED
|
||||
|
||||
# optimize for SPEED
|
||||
#CFLAGS += -O3 -funroll-loops
|
||||
|
||||
# add -fomit-frame-pointer. hinders debugging!
|
||||
#CFLAGS += -fomit-frame-pointer
|
||||
|
||||
# optimize for SIZE
|
||||
#CFLAGS += -Os -DLTC_SMALL_CODE
|
||||
|
||||
endif
|
||||
|
||||
# older GCCs can't handle the "rotate with immediate" ROLc/RORc/etc macros
|
||||
# define this to help
|
||||
#CFLAGS += -DLTC_NO_ROLC
|
||||
|
||||
# compile for DEBUGING (required for ccmalloc checking!!!)
|
||||
#CFLAGS += -g3 -DLTC_NO_ASM
|
||||
|
||||
#Output filenames for various targets.
|
||||
ifndef LIBNAME
|
||||
LIBNAME=libtomcrypt.a
|
||||
endif
|
||||
ifndef LIBTEST
|
||||
LIBTEST=libtomcrypt_prof.a
|
||||
endif
|
||||
LIBTEST_S=$(LIBTEST)
|
||||
|
||||
HASH=hashsum
|
||||
CRYPT=encrypt
|
||||
SMALL=small
|
||||
PROF=x86_prof
|
||||
TV=tv_gen
|
||||
MULTI=multi
|
||||
TIMING=timing
|
||||
TEST=test
|
||||
|
||||
#LIBPATH-The directory for libtomcrypt to be installed to.
|
||||
#INCPATH-The directory to install the header files for libtomcrypt.
|
||||
#DATAPATH-The directory to install the pdf docs.
|
||||
ifndef DESTDIR
|
||||
DESTDIR=
|
||||
endif
|
||||
|
||||
ifndef LIBPATH
|
||||
LIBPATH=/usr/lib
|
||||
endif
|
||||
ifndef INCPATH
|
||||
INCPATH=/usr/include
|
||||
endif
|
||||
ifndef DATAPATH
|
||||
DATAPATH=/usr/share/doc/libtomcrypt/pdf
|
||||
endif
|
||||
|
||||
#Who do we install as?
|
||||
ifdef INSTALL_USER
|
||||
USER=$(INSTALL_USER)
|
||||
else
|
||||
USER=root
|
||||
endif
|
||||
|
||||
ifdef INSTALL_GROUP
|
||||
GROUP=$(INSTALL_GROUP)
|
||||
else
|
||||
GROUP=wheel
|
||||
endif
|
||||
|
||||
#List of objects to compile.
|
||||
#START_INS
|
||||
OBJECTS=src/ciphers/aes/aes_enc.o src/ciphers/aes/aes.o src/ciphers/anubis.o src/ciphers/blowfish.o \
|
||||
src/ciphers/cast5.o src/ciphers/des.o src/ciphers/kasumi.o src/ciphers/khazad.o src/ciphers/kseed.o \
|
||||
src/ciphers/noekeon.o src/ciphers/rc2.o src/ciphers/rc5.o src/ciphers/rc6.o src/ciphers/safer/safer.o \
|
||||
src/ciphers/safer/safer_tab.o src/ciphers/safer/saferp.o src/ciphers/skipjack.o \
|
||||
src/ciphers/twofish/twofish.o src/ciphers/xtea.o src/encauth/ccm/ccm_memory.o \
|
||||
src/encauth/ccm/ccm_test.o src/encauth/eax/eax_addheader.o src/encauth/eax/eax_decrypt.o \
|
||||
src/encauth/eax/eax_decrypt_verify_memory.o src/encauth/eax/eax_done.o src/encauth/eax/eax_encrypt.o \
|
||||
src/encauth/eax/eax_encrypt_authenticate_memory.o src/encauth/eax/eax_init.o \
|
||||
src/encauth/eax/eax_test.o src/encauth/gcm/gcm_add_aad.o src/encauth/gcm/gcm_add_iv.o \
|
||||
src/encauth/gcm/gcm_done.o src/encauth/gcm/gcm_gf_mult.o src/encauth/gcm/gcm_init.o \
|
||||
src/encauth/gcm/gcm_memory.o src/encauth/gcm/gcm_mult_h.o src/encauth/gcm/gcm_process.o \
|
||||
src/encauth/gcm/gcm_reset.o src/encauth/gcm/gcm_test.o src/encauth/ocb/ocb_decrypt.o \
|
||||
src/encauth/ocb/ocb_decrypt_verify_memory.o src/encauth/ocb/ocb_done_decrypt.o \
|
||||
src/encauth/ocb/ocb_done_encrypt.o src/encauth/ocb/ocb_encrypt.o \
|
||||
src/encauth/ocb/ocb_encrypt_authenticate_memory.o src/encauth/ocb/ocb_init.o src/encauth/ocb/ocb_ntz.o \
|
||||
src/encauth/ocb/ocb_shift_xor.o src/encauth/ocb/ocb_test.o src/encauth/ocb/s_ocb_done.o \
|
||||
src/hashes/chc/chc.o src/hashes/helper/hash_file.o src/hashes/helper/hash_filehandle.o \
|
||||
src/hashes/helper/hash_memory.o src/hashes/helper/hash_memory_multi.o src/hashes/md2.o src/hashes/md4.o \
|
||||
src/hashes/md5.o src/hashes/rmd128.o src/hashes/rmd160.o src/hashes/rmd256.o src/hashes/rmd320.o \
|
||||
src/hashes/sha1.o src/hashes/sha2/sha256.o src/hashes/sha2/sha512.o src/hashes/tiger.o \
|
||||
src/hashes/whirl/whirl.o src/mac/f9/f9_done.o src/mac/f9/f9_file.o src/mac/f9/f9_init.o \
|
||||
src/mac/f9/f9_memory.o src/mac/f9/f9_memory_multi.o src/mac/f9/f9_process.o src/mac/f9/f9_test.o \
|
||||
src/mac/hmac/hmac_done.o src/mac/hmac/hmac_file.o src/mac/hmac/hmac_init.o src/mac/hmac/hmac_memory.o \
|
||||
src/mac/hmac/hmac_memory_multi.o src/mac/hmac/hmac_process.o src/mac/hmac/hmac_test.o \
|
||||
src/mac/omac/omac_done.o src/mac/omac/omac_file.o src/mac/omac/omac_init.o src/mac/omac/omac_memory.o \
|
||||
src/mac/omac/omac_memory_multi.o src/mac/omac/omac_process.o src/mac/omac/omac_test.o \
|
||||
src/mac/pelican/pelican.o src/mac/pelican/pelican_memory.o src/mac/pelican/pelican_test.o \
|
||||
src/mac/pmac/pmac_done.o src/mac/pmac/pmac_file.o src/mac/pmac/pmac_init.o src/mac/pmac/pmac_memory.o \
|
||||
src/mac/pmac/pmac_memory_multi.o src/mac/pmac/pmac_ntz.o src/mac/pmac/pmac_process.o \
|
||||
src/mac/pmac/pmac_shift_xor.o src/mac/pmac/pmac_test.o src/mac/xcbc/xcbc_done.o \
|
||||
src/mac/xcbc/xcbc_file.o src/mac/xcbc/xcbc_init.o src/mac/xcbc/xcbc_memory.o \
|
||||
src/mac/xcbc/xcbc_memory_multi.o src/mac/xcbc/xcbc_process.o src/mac/xcbc/xcbc_test.o \
|
||||
src/math/fp/ltc_ecc_fp_mulmod.o src/math/gmp_desc.o src/math/ltm_desc.o src/math/multi.o \
|
||||
src/math/rand_prime.o src/math/tfm_desc.o src/misc/base64/base64_decode.o \
|
||||
src/misc/base64/base64_encode.o src/misc/burn_stack.o src/misc/crypt/crypt.o \
|
||||
src/misc/crypt/crypt_argchk.o src/misc/crypt/crypt_cipher_descriptor.o \
|
||||
src/misc/crypt/crypt_cipher_is_valid.o src/misc/crypt/crypt_find_cipher.o \
|
||||
src/misc/crypt/crypt_find_cipher_any.o src/misc/crypt/crypt_find_cipher_id.o \
|
||||
src/misc/crypt/crypt_find_hash.o src/misc/crypt/crypt_find_hash_any.o \
|
||||
src/misc/crypt/crypt_find_hash_id.o src/misc/crypt/crypt_find_hash_oid.o \
|
||||
src/misc/crypt/crypt_find_prng.o src/misc/crypt/crypt_fsa.o src/misc/crypt/crypt_hash_descriptor.o \
|
||||
src/misc/crypt/crypt_hash_is_valid.o src/misc/crypt/crypt_ltc_mp_descriptor.o \
|
||||
src/misc/crypt/crypt_prng_descriptor.o src/misc/crypt/crypt_prng_is_valid.o \
|
||||
src/misc/crypt/crypt_register_cipher.o src/misc/crypt/crypt_register_hash.o \
|
||||
src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_unregister_cipher.o \
|
||||
src/misc/crypt/crypt_unregister_hash.o src/misc/crypt/crypt_unregister_prng.o \
|
||||
src/misc/error_to_string.o src/misc/pkcs5/pkcs_5_1.o src/misc/pkcs5/pkcs_5_2.o src/misc/zeromem.o \
|
||||
src/modes/cbc/cbc_decrypt.o src/modes/cbc/cbc_done.o src/modes/cbc/cbc_encrypt.o \
|
||||
src/modes/cbc/cbc_getiv.o src/modes/cbc/cbc_setiv.o src/modes/cbc/cbc_start.o \
|
||||
src/modes/cfb/cfb_decrypt.o src/modes/cfb/cfb_done.o src/modes/cfb/cfb_encrypt.o \
|
||||
src/modes/cfb/cfb_getiv.o src/modes/cfb/cfb_setiv.o src/modes/cfb/cfb_start.o \
|
||||
src/modes/ctr/ctr_decrypt.o src/modes/ctr/ctr_done.o src/modes/ctr/ctr_encrypt.o \
|
||||
src/modes/ctr/ctr_getiv.o src/modes/ctr/ctr_setiv.o src/modes/ctr/ctr_start.o src/modes/ctr/ctr_test.o \
|
||||
src/modes/ecb/ecb_decrypt.o src/modes/ecb/ecb_done.o src/modes/ecb/ecb_encrypt.o \
|
||||
src/modes/ecb/ecb_start.o src/modes/f8/f8_decrypt.o src/modes/f8/f8_done.o src/modes/f8/f8_encrypt.o \
|
||||
src/modes/f8/f8_getiv.o src/modes/f8/f8_setiv.o src/modes/f8/f8_start.o src/modes/f8/f8_test_mode.o \
|
||||
src/modes/lrw/lrw_decrypt.o src/modes/lrw/lrw_done.o src/modes/lrw/lrw_encrypt.o \
|
||||
src/modes/lrw/lrw_getiv.o src/modes/lrw/lrw_process.o src/modes/lrw/lrw_setiv.o \
|
||||
src/modes/lrw/lrw_start.o src/modes/lrw/lrw_test.o src/modes/ofb/ofb_decrypt.o src/modes/ofb/ofb_done.o \
|
||||
src/modes/ofb/ofb_encrypt.o src/modes/ofb/ofb_getiv.o src/modes/ofb/ofb_setiv.o \
|
||||
src/modes/ofb/ofb_start.o
|
||||
|
||||
HEADERS=src/headers/tomcrypt_cfg.h src/headers/tomcrypt_mac.h src/headers/tomcrypt_macros.h \
|
||||
src/headers/tomcrypt_custom.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cipher.h \
|
||||
src/headers/tomcrypt_pk.h src/headers/tomcrypt_hash.h src/headers/tomcrypt_math.h \
|
||||
src/headers/tomcrypt_misc.h src/headers/tomcrypt.h src/headers/tomcrypt_pkcs.h \
|
||||
src/headers/tomcrypt_prng.h testprof/tomcrypt_test.h
|
||||
|
||||
#END_INS
|
||||
|
||||
TESTOBJECTS=demos/test.o
|
||||
HASHOBJECTS=demos/hashsum.o
|
||||
CRYPTOBJECTS=demos/encrypt.o
|
||||
SMALLOBJECTS=demos/small.o
|
||||
TVS=demos/tv_gen.o
|
||||
MULTIS=demos/multi.o
|
||||
TIMINGS=demos/timing.o
|
||||
TESTS=demos/test.o
|
||||
|
||||
#Files left over from making the crypt.pdf.
|
||||
LEFTOVERS=*.dvi *.log *.aux *.toc *.idx *.ilg *.ind *.out
|
||||
|
||||
#Compressed filenames
|
||||
COMPRESSED=crypt-$(VERSION).tar.bz2 crypt-$(VERSION).zip
|
||||
|
||||
#The default rule for make builds the libtomcrypt library.
|
||||
default:library
|
||||
|
||||
#ciphers come in two flavours... enc+dec and enc
|
||||
src/ciphers/aes/aes_enc.o: src/ciphers/aes/aes.c src/ciphers/aes/aes_tab.c
|
||||
$(CC) $(CFLAGS) -DENCRYPT_ONLY -c $< -o src/ciphers/aes/aes_enc.o
|
||||
|
||||
#These are the rules to make certain object files.
|
||||
src/ciphers/aes/aes.o: src/ciphers/aes/aes.c src/ciphers/aes/aes_tab.c
|
||||
src/ciphers/twofish/twofish.o: src/ciphers/twofish/twofish.c src/ciphers/twofish/twofish_tab.c
|
||||
src/hashes/whirl/whirl.o: src/hashes/whirl/whirl.c src/hashes/whirl/whirltab.c
|
||||
src/hashes/sha2/sha512.o: src/hashes/sha2/sha512.c src/hashes/sha2/sha384.c
|
||||
src/hashes/sha2/sha256.o: src/hashes/sha2/sha256.c src/hashes/sha2/sha224.c
|
||||
|
||||
#This rule makes the libtomcrypt library.
|
||||
library: $(LIBNAME)
|
||||
|
||||
testprof/$(LIBTEST):
|
||||
cd testprof ; CFLAGS="$(CFLAGS)" LIBTEST_S=$(LIBTEST_S) $(MAKE)
|
||||
|
||||
$(LIBNAME): $(OBJECTS)
|
||||
$(AR) $(ARFLAGS) $@ $(OBJECTS)
|
||||
$(RANLIB) $@
|
||||
|
||||
#This rule makes the hash program included with libtomcrypt
|
||||
hashsum: library $(HASHOBJECTS)
|
||||
$(CC) $(HASHOBJECTS) $(LIBNAME) $(EXTRALIBS) -o $(HASH) $(WARN)
|
||||
|
||||
#makes the crypt program
|
||||
crypt: library $(CRYPTOBJECTS)
|
||||
$(CC) $(CRYPTOBJECTS) $(LIBNAME) $(EXTRALIBS) -o $(CRYPT) $(WARN)
|
||||
|
||||
#makes the small program
|
||||
small: library $(SMALLOBJECTS)
|
||||
$(CC) $(SMALLOBJECTS) $(LIBNAME) $(EXTRALIBS) -o $(SMALL) $(WARN)
|
||||
|
||||
tv_gen: library $(TVS)
|
||||
$(CC) $(LDFLAGS) $(TVS) $(LIBNAME) $(EXTRALIBS) -o $(TV)
|
||||
|
||||
multi: library $(MULTIS)
|
||||
$(CC) $(MULTIS) $(LIBNAME) $(EXTRALIBS) -o $(MULTI)
|
||||
|
||||
timing: library testprof/$(LIBTEST) $(TIMINGS)
|
||||
$(CC) $(LDFLAGS) $(TIMINGS) testprof/$(LIBTEST) $(LIBNAME) $(EXTRALIBS) -o $(TIMING)
|
||||
|
||||
test: library testprof/$(LIBTEST) $(TESTS)
|
||||
$(CC) $(LDFLAGS) $(TESTS) testprof/$(LIBTEST) $(LIBNAME) $(EXTRALIBS) -o $(TEST)
|
||||
|
||||
#This rule installs the library and the header files. This must be run
|
||||
#as root in order to have a high enough permission to write to the correct
|
||||
#directories and to set the owner and group to root.
|
||||
ifndef NODOCS
|
||||
install: library docs
|
||||
else
|
||||
install: library
|
||||
endif
|
||||
install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(LIBPATH)
|
||||
install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(INCPATH)
|
||||
install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(DATAPATH)
|
||||
install -g $(GROUP) -o $(USER) $(LIBNAME) $(DESTDIR)$(LIBPATH)
|
||||
install -g $(GROUP) -o $(USER) $(HEADERS) $(DESTDIR)$(INCPATH)
|
||||
ifndef NODOCS
|
||||
install -g $(GROUP) -o $(USER) doc/crypt.pdf $(DESTDIR)$(DATAPATH)
|
||||
endif
|
||||
|
||||
install_test: testprof/$(LIBTEST)
|
||||
install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(LIBPATH)
|
||||
install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(INCPATH)
|
||||
install -g $(GROUP) -o $(USER) testprof/$(LIBTEST) $(DESTDIR)$(LIBPATH)
|
||||
|
||||
profile:
|
||||
CFLAGS="$(CFLAGS) -fprofile-generate" $(MAKE) timing EXTRALIBS="$(EXTRALIBS) -lgcov"
|
||||
./timing
|
||||
rm -f timing `find . -type f | grep [.][ao] | xargs`
|
||||
CFLAGS="$(CFLAGS) -fprofile-use" $(MAKE) timing EXTRALIBS="$(EXTRALIBS) -lgcov"
|
||||
|
||||
|
||||
#This rule cleans the source tree of all compiled code, not including the pdf
|
||||
#documentation.
|
||||
clean:
|
||||
-rm -f $(OBJECTS)
|
||||
-rm -f libtomcrypt.a
|
||||
|
||||
#build the doxy files (requires Doxygen, tetex and patience)
|
||||
doxy:
|
||||
doxygen
|
||||
cd doc/doxygen/latex ; ${MAKE} ; mv -f refman.pdf ../../.
|
||||
echo The huge doxygen PDF should be available as doc/refman.pdf
|
||||
|
||||
#This builds the crypt.pdf file. Note that the rm -f *.pdf has been removed
|
||||
#from the clean command! This is because most people would like to keep the
|
||||
#nice pre-compiled crypt.pdf that comes with libtomcrypt! We only need to
|
||||
#delete it if we are rebuilding it.
|
||||
docs: crypt.tex
|
||||
rm -f doc/crypt.pdf $(LEFTOVERS)
|
||||
echo "hello" > crypt.ind
|
||||
latex crypt > /dev/null
|
||||
latex crypt > /dev/null
|
||||
makeindex crypt.idx > /dev/null
|
||||
perl fixupind.pl
|
||||
latex crypt > /dev/null
|
||||
dvipdf crypt
|
||||
mv -ivf crypt.pdf doc/crypt.pdf
|
||||
rm -f $(LEFTOVERS)
|
||||
|
||||
docdvi: crypt.tex
|
||||
echo hello > crypt.ind
|
||||
latex crypt > /dev/null
|
||||
latex crypt > /dev/null
|
||||
makeindex crypt.idx
|
||||
perl fixupind.pl
|
||||
latex crypt > /dev/null
|
||||
latex crypt > /dev/null
|
||||
|
||||
#zipup the project (take that!)
|
||||
no_oops: clean
|
||||
cd .. ; cvs commit
|
||||
echo Scanning for scratch/dirty files
|
||||
find . -type f | grep -v CVS | xargs -n 1 bash mess.sh
|
||||
|
||||
zipup: no_oops docs
|
||||
cd .. ; rm -rf crypt* libtomcrypt-$(VERSION) ; mkdir libtomcrypt-$(VERSION) ; \
|
||||
cp -R ./libtomcrypt/* ./libtomcrypt-$(VERSION)/ ; \
|
||||
cd libtomcrypt-$(VERSION) ; rm -rf `find . -type d | grep CVS | xargs` ; cd .. ; \
|
||||
tar -cjvf crypt-$(VERSION).tar.bz2 libtomcrypt-$(VERSION) ; \
|
||||
zip -9r crypt-$(VERSION).zip libtomcrypt-$(VERSION) ; \
|
||||
gpg -b -a crypt-$(VERSION).tar.bz2 ; gpg -b -a crypt-$(VERSION).zip ; \
|
||||
mv -fv crypt* ~ ; rm -rf libtomcrypt-$(VERSION)
|
||||
|
||||
|
||||
# $Source: /cvs/libtom/libtomcrypt/makefile,v $
|
||||
# $Revision: 1.145 $
|
||||
# $Date: 2006/12/02 19:23:21 $
|
||||
3
libtomcrypt/README
Normal file
3
libtomcrypt/README
Normal file
@@ -0,0 +1,3 @@
|
||||
See doc/crypt.pdf
|
||||
|
||||
|
||||
11
libtomcrypt/TODO
Normal file
11
libtomcrypt/TODO
Normal file
@@ -0,0 +1,11 @@
|
||||
stopped at ch12
|
||||
-- needs examples for ecc/dsa!!! (and for asn.1)
|
||||
|
||||
must have for v1.16
|
||||
- document PK build flags
|
||||
- document makefile flags [INSTALL_* for instance]
|
||||
- prepare manual for printing (both soft and hard cover)
|
||||
|
||||
Nice to have [in order of precedence]
|
||||
- add X9.63 IES
|
||||
- add CPP macros like OpenSSL has for ASN1 (e.g. encode/decode functions, etc) shameless ripoff :-)
|
||||
20
libtomcrypt/build.sh
Normal file
20
libtomcrypt/build.sh
Normal file
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
echo "$1 ($2, $3)..."
|
||||
make clean 1>/dev/null 2>/dev/null
|
||||
echo -n "building..."
|
||||
CFLAGS="$2 $CFLAGS $4" EXTRALIBS="$5" make -j4 -f $3 test tv_gen 1>gcc_1.txt 2>gcc_2.txt || (echo "build $1 failed see gcc_2.txt for more information" && cat gcc_2.txt && exit 1)
|
||||
echo -n "testing..."
|
||||
if [ -a test ] && [ -f test ] && [ -x test ]; then
|
||||
((./test >test_std.txt 2>test_err.txt && ./tv_gen > tv.txt) && echo "$1 test passed." && echo "y" > testok.txt) || (echo "$1 test failed" && cat test_err.txt && exit 1)
|
||||
if find *_tv.txt -type f 1>/dev/null 2>/dev/null ; then
|
||||
for f in *_tv.txt; do if (diff --ignore-case $f notes/$f) then true; else (echo "tv_gen $f failed" && rm -f testok.txt && exit 1); fi; done
|
||||
fi
|
||||
fi
|
||||
if [ -a testok.txt ] && [ -f testok.txt ]; then
|
||||
exit 0
|
||||
fi
|
||||
exit 1
|
||||
|
||||
# $Source: /cvs/libtom/libtomcrypt/build.sh,v $
|
||||
# $Revision: 1.9 $
|
||||
# $Date: 2006/03/18 14:10:55 $
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user