mirror of
https://github.com/clearml/dropbear
synced 2025-06-26 18:17:32 +00:00
Compare commits
1734 Commits
DROPBEAR_0
...
DROPBEAR_C
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31e3a973c1 | ||
|
|
9defeb477a | ||
|
|
7a53c7f0f4 | ||
|
|
febb805742 | ||
|
|
923a65ea0d | ||
|
|
39d955c49f | ||
|
|
f7b1ba6aad | ||
|
|
01415ef826 | ||
|
|
6fa49f98c5 | ||
|
|
8607215588 | ||
|
|
c043efb47c | ||
|
|
ec2215726c | ||
|
|
bd94cb712c | ||
|
|
cf7f9350b8 | ||
|
|
5a07edfa2b | ||
|
|
a7659fb581 | ||
|
|
1034024029 | ||
|
|
36a0313263 | ||
|
|
a4689e25ec | ||
|
|
e360dffff2 | ||
|
|
5a3bc9fa9c | ||
|
|
aa6559db66 | ||
|
|
b2b94acc97 | ||
|
|
960d374e65 | ||
|
|
fd234018a4 | ||
|
|
54a90ddac5 | ||
|
|
cda8070898 | ||
|
|
b5e941c0b1 | ||
|
|
e87a222ce7 | ||
|
|
e85f329e5c | ||
|
|
1d22801101 | ||
|
|
787391ea3b | ||
|
|
c9a16e661a | ||
|
|
b966cce3ae | ||
|
|
e5e6b6c1b8 | ||
|
|
c29c4e1024 | ||
|
|
1cdd95f997 | ||
|
|
86ac8411a0 | ||
|
|
2864c3d154 | ||
|
|
0e70732e1e | ||
|
|
cdaf52aead | ||
|
|
cdc83ad98a | ||
|
|
80fa169cb9 | ||
|
|
50a07a4889 | ||
|
|
dacc10a8cf | ||
|
|
0058cc69c8 | ||
|
|
963b9eafaa | ||
|
|
7c9bd09af6 | ||
|
|
72b28448a1 | ||
|
|
dc3c1a30cf | ||
|
|
71d78653c7 | ||
|
|
9f55ff216b | ||
|
|
b4c30b5e7e | ||
|
|
561ef41230 | ||
|
|
ab6ea4d697 | ||
|
|
9d320a73be | ||
|
|
f19a0494d7 | ||
|
|
ab70167534 | ||
|
|
d1fed8b451 | ||
|
|
5284a3da56 | ||
|
|
f7d306e963 | ||
|
|
86efbae708 | ||
|
|
64e270b6f2 | ||
|
|
b36707ba46 | ||
|
|
acf50a4f98 | ||
|
|
b734e5a423 | ||
|
|
4c67d03656 | ||
|
|
17e02fe614 | ||
|
|
e520d035e7 | ||
|
|
d48a2ba8b7 | ||
|
|
7de29c2686 | ||
|
|
1e4d64d300 | ||
|
|
a7e3b06b04 | ||
|
|
427e49003a | ||
|
|
808bc392a0 | ||
|
|
e03abf0d1a | ||
|
|
62ea53c1e5 | ||
|
|
544f28a051 | ||
|
|
f2318d831b | ||
|
|
1622c80be4 | ||
|
|
c77d02bb11 | ||
|
|
50c6e8d3c3 | ||
|
|
258f6127b4 | ||
|
|
b81c81c047 | ||
|
|
3c3e4f6e6b | ||
|
|
d8d1db2cf8 | ||
|
|
0c9318a0b2 | ||
|
|
46654cda85 | ||
|
|
72d8cae7a4 | ||
|
|
2e0a16c334 | ||
|
|
c4a0304b3f | ||
|
|
46106f71ab | ||
|
|
0292aacdf0 | ||
|
|
b8669b063b | ||
|
|
c6e2d50310 | ||
|
|
dd305c1533 | ||
|
|
7894254afa | ||
|
|
ac2433cb8d | ||
|
|
552385280a | ||
|
|
c93103746e | ||
|
|
abb577fcba | ||
|
|
0e042476a0 | ||
|
|
0fc4e35c94 | ||
|
|
9007a80616 | ||
|
|
ecc85f91e6 | ||
|
|
82bff01242 | ||
|
|
02a8c6cadd | ||
|
|
85f56f438a | ||
|
|
0de8d44297 | ||
|
|
8b202f86e2 | ||
|
|
f4be5a3c8b | ||
|
|
2f68f6693f | ||
|
|
6f793d42d0 | ||
|
|
04a4548ba2 | ||
|
|
6ad6210901 | ||
|
|
8b68eb55d9 | ||
|
|
6dc029f2cb | ||
|
|
9d36e94deb | ||
|
|
6ac92cf606 | ||
|
|
cb9a00951f | ||
|
|
81e3977360 | ||
|
|
bcbae1f4ba | ||
|
|
ee3828b3f8 | ||
|
|
81425365de | ||
|
|
3189d12c9f | ||
|
|
a70b9e34c8 | ||
|
|
ce745e98c0 | ||
|
|
d142639e38 | ||
|
|
bceba1f2ed | ||
|
|
3521b58690 | ||
|
|
635ae3d500 | ||
|
|
02eb74fbec | ||
|
|
515db2d706 | ||
|
|
9411bc21a8 | ||
|
|
0d4ab4fc09 | ||
|
|
be4f9ce8e7 | ||
|
|
f030618543 | ||
|
|
193d967123 | ||
|
|
94b693b43c | ||
|
|
1f169dafa8 | ||
|
|
9ea30b8932 | ||
|
|
098263950f | ||
|
|
d597b66571 | ||
|
|
98ef42a856 | ||
|
|
678cc6fcc0 | ||
|
|
b58f96526a | ||
|
|
10875e8524 | ||
|
|
355b248318 | ||
|
|
212583544a | ||
|
|
ae8a0abc34 | ||
|
|
488ffce133 | ||
|
|
360d60fb34 | ||
|
|
fa4a1ab435 | ||
|
|
35631a21a2 | ||
|
|
80e7143fd2 | ||
|
|
19cfb22d30 | ||
|
|
8d11116dcb | ||
|
|
26feb8f13e | ||
|
|
9124997602 | ||
|
|
12b094f0bf | ||
|
|
5334d58a15 | ||
|
|
3939321750 | ||
|
|
a95ca34a10 | ||
|
|
4c2d2fc3ac | ||
|
|
e93b03cb00 | ||
|
|
2b0238706a | ||
|
|
3fb2406717 | ||
|
|
d367503fb0 | ||
|
|
2a6dac19b5 | ||
|
|
da7f77a50d | ||
|
|
c7b7c9a99d | ||
|
|
ebb4018889 | ||
|
|
1c8f00bd59 | ||
|
|
a4362d3019 | ||
|
|
14bdd5a8ae | ||
|
|
f3a4ea511b | ||
|
|
f972813ecd | ||
|
|
8727f49dec | ||
|
|
5edd2ce32e | ||
|
|
c06d8254d8 | ||
|
|
18be2a6509 | ||
|
|
483b427335 | ||
|
|
27ffea3223 | ||
|
|
742e296115 | ||
|
|
0e43d68d81 | ||
|
|
bcb9d78d83 | ||
|
|
8da9646c83 | ||
|
|
da482ede60 | ||
|
|
f0495697e5 | ||
|
|
f9ced2c880 | ||
|
|
17e0c7e76f | ||
|
|
30adc15860 | ||
|
|
6138bdc62f | ||
|
|
e05945f67a | ||
|
|
3e640acd17 | ||
|
|
ae25761c7c | ||
|
|
e6152ccd7d | ||
|
|
8b0d31ab20 | ||
|
|
65f6e48a06 | ||
|
|
a7ef149463 | ||
|
|
043b0fbd1b | ||
|
|
110b55214b | ||
|
|
c08177a3af | ||
|
|
3c2436cd05 | ||
|
|
f3b72bfd18 | ||
|
|
f17400e738 | ||
|
|
8e6f73e879 | ||
|
|
7c2470ba3a | ||
|
|
cc59c08605 | ||
|
|
661d8ca225 | ||
|
|
41d4b4e7f7 | ||
|
|
dc016f900b | ||
|
|
4c8c879b38 | ||
|
|
210a983349 | ||
|
|
69e5709f75 | ||
|
|
2157d52352 | ||
|
|
846d38fe43 | ||
|
|
a8d6dac2c5 | ||
|
|
ee49a1b16d | ||
|
|
325d0c1d02 | ||
|
|
17f209f9b7 | ||
|
|
924d5a06a6 | ||
|
|
1bf7acc5bd | ||
|
|
8d0013bbe0 | ||
|
|
9262ffe861 | ||
|
|
1eb369272b | ||
|
|
c0ed29ea02 | ||
|
|
91ca561d7a | ||
|
|
ba260bd67b | ||
|
|
898bff3d4e | ||
|
|
67a8de30b7 | ||
|
|
6c571c54e5 | ||
|
|
d2bfa6aedc | ||
|
|
d0d1ede191 | ||
|
|
3c2f113a78 | ||
|
|
f193e95a3e | ||
|
|
03481aba06 | ||
|
|
8b0fdf8010 | ||
|
|
934cc87db3 | ||
|
|
ae94f64145 | ||
|
|
8552a0e9eb | ||
|
|
d20420e709 | ||
|
|
e8640bdca3 | ||
|
|
e4edbf2e57 | ||
|
|
5d60e5f312 | ||
|
|
38d7da5fe5 | ||
|
|
a6b2eeb190 | ||
|
|
e12ff23e7d | ||
|
|
007a5925dc | ||
|
|
d439ed26e4 | ||
|
|
f9ff3fa23d | ||
|
|
2c64335d9c | ||
|
|
286b6b9f80 | ||
|
|
220ba993a2 | ||
|
|
3c88d6536a | ||
|
|
f49b576e93 | ||
|
|
8ec9016585 | ||
|
|
15ea6d1106 | ||
|
|
24cfda9e3c | ||
|
|
121e6e6202 | ||
|
|
1b6e16ae7c | ||
|
|
b8352f8164 | ||
|
|
6aa065b1b4 | ||
|
|
6cf29061c2 | ||
|
|
f92f0777de | ||
|
|
9c70e4bed1 | ||
|
|
a51833c51a | ||
|
|
d852d69b50 | ||
|
|
1b603069db | ||
|
|
bf4058d1df | ||
|
|
4d716b6302 | ||
|
|
1260fbc5cd | ||
|
|
acd6a22a0c | ||
|
|
4e8a1da551 | ||
|
|
754dc50b93 | ||
|
|
c7cfa75e92 | ||
|
|
b070bcd570 | ||
|
|
037d26f055 | ||
|
|
cb252296c5 | ||
|
|
f37def57b0 | ||
|
|
1a208c460b | ||
|
|
34f24b1841 | ||
|
|
1a7b944917 | ||
|
|
3b400bd64e | ||
|
|
f74baa5830 | ||
|
|
4c5b8fb6d6 | ||
|
|
d5cc5eb25c | ||
|
|
9f642e2bd4 | ||
|
|
6ca24af24a | ||
|
|
400c7c161f | ||
|
|
5567c238a7 | ||
|
|
33eba22966 | ||
|
|
282fc81981 | ||
|
|
cc1b07dcf1 | ||
|
|
0e3e8db5bf | ||
|
|
17873e8c92 | ||
|
|
80e9281701 | ||
|
|
926c477188 | ||
|
|
d999575e34 | ||
|
|
5d095e9a27 | ||
|
|
3727b099c5 | ||
|
|
45294b458a | ||
|
|
d51e4a75cd | ||
|
|
e9f2815144 | ||
|
|
2771fab0fa | ||
|
|
a7a67585cb | ||
|
|
366f01252e | ||
|
|
1490c0c3a6 | ||
|
|
3f5c106a88 | ||
|
|
10e119f638 | ||
|
|
5b68d117c2 | ||
|
|
58106b1615 | ||
|
|
1e10af850b | ||
|
|
ee4b4db816 | ||
|
|
ab9cfce00d | ||
|
|
2b8106b14e | ||
|
|
78c5daee52 | ||
|
|
2301b6ac0b | ||
|
|
a27e8b053e | ||
|
|
6145289e0d | ||
|
|
d14ebdbf0e | ||
|
|
4b305c5721 | ||
|
|
615885be01 | ||
|
|
6b823d617c | ||
|
|
ec993dbdbc | ||
|
|
ad1e9b7e3c | ||
|
|
846b8cdbf7 | ||
|
|
b0243b0e7b | ||
|
|
4faf06aae7 | ||
|
|
07d46f9907 | ||
|
|
413eaf1ba1 | ||
|
|
3b359050b4 | ||
|
|
a015cc7594 | ||
|
|
dc12be0cfe | ||
|
|
89e98a2f83 | ||
|
|
5027bc4db1 | ||
|
|
630f6aa6b9 | ||
|
|
8048473eb9 | ||
|
|
4216c984ae | ||
|
|
6abf756e51 | ||
|
|
b4bd23b4d2 | ||
|
|
724e61f8ae | ||
|
|
49667a82de | ||
|
|
a57114e7fa | ||
|
|
cfe90bc6bd | ||
|
|
0aefec6c89 | ||
|
|
6a3bc73a78 | ||
|
|
73aa4f0de9 | ||
|
|
9e25854b41 | ||
|
|
d277f140ba | ||
|
|
61267f8503 | ||
|
|
d3d0d60076 | ||
|
|
91e537e427 | ||
|
|
fb9a78c3ee | ||
|
|
8f8a3dff70 | ||
|
|
c917807b1c | ||
|
|
701d43b859 | ||
|
|
79bedc90a1 | ||
|
|
545cc62671 | ||
|
|
331d4a714f | ||
|
|
2a81289ed3 | ||
|
|
5acee497bf | ||
|
|
972d723484 | ||
|
|
7dc2f36c3e | ||
|
|
90cfbe1f7a | ||
|
|
b681570899 | ||
|
|
201e359363 | ||
|
|
fa4c4646d8 | ||
|
|
6f6aa9db5a | ||
|
|
e35d0784a8 | ||
|
|
cc6fa57a41 | ||
|
|
a26ad21c0a | ||
|
|
002b79e2f9 | ||
|
|
3d12521735 | ||
|
|
b2007beeb0 | ||
|
|
8f123fb618 | ||
|
|
c71258625d | ||
|
|
615ed4e46a | ||
|
|
fa116e983b | ||
|
|
8c6aaf8d36 | ||
|
|
cae6e6af10 | ||
|
|
f89c5b0390 | ||
|
|
4318631dd6 | ||
|
|
7bc6280613 | ||
|
|
e9231f73c2 | ||
|
|
4fd40e61f7 | ||
|
|
71f818262c | ||
|
|
07f790db5a | ||
|
|
78a3388b98 | ||
|
|
6fecc91d10 | ||
|
|
8b4f60a7a1 | ||
|
|
01cd1bd11f | ||
|
|
f6df3e1fec | ||
|
|
553087b7a6 | ||
|
|
16fb0b0d53 | ||
|
|
493ab8fd81 | ||
|
|
0afcfafbb9 | ||
|
|
0af22aa8e4 | ||
|
|
2fd3b9f560 | ||
|
|
2de3bc9353 | ||
|
|
28b6111db0 | ||
|
|
a0aa274981 | ||
|
|
b016ebedfd | ||
|
|
cb945f9f67 | ||
|
|
df0f1297eb | ||
|
|
fe992bf4ea | ||
|
|
ffde4a524f | ||
|
|
7e03e4d443 | ||
|
|
02ffdd09dc | ||
|
|
6f6ef4834c | ||
|
|
d2e71ade72 | ||
|
|
892c5fc1c8 | ||
|
|
e7504b3311 | ||
|
|
ad3eacf3d6 | ||
|
|
52adbb34c3 | ||
|
|
90f04384ee | ||
|
|
195934be96 | ||
|
|
d740dc5489 | ||
|
|
76933e6c0a | ||
|
|
38c9408cf8 | ||
|
|
397af3e6a6 | ||
|
|
933bc5f8a7 | ||
|
|
ba94bcd2e8 | ||
|
|
56855744b8 | ||
|
|
b4b11c8155 | ||
|
|
f82933108d | ||
|
|
27828c742c | ||
|
|
ed4c38ba46 | ||
|
|
e9edbe8bb2 | ||
|
|
4fd3160179 | ||
|
|
a60725740b | ||
|
|
5d065258da | ||
|
|
149b21d7cf | ||
|
|
145fb96989 | ||
|
|
084ff9b4c8 | ||
|
|
6b05aa4275 | ||
|
|
366fc8f335 | ||
|
|
35f479bd87 | ||
|
|
9d11cad5dc | ||
|
|
0233dcebb4 | ||
|
|
f7dedab4a7 | ||
|
|
129c440362 | ||
|
|
abee8093b3 | ||
|
|
2583b180c9 | ||
|
|
1e1e477d85 | ||
|
|
85eda7d943 | ||
|
|
4b36e24735 | ||
|
|
a5eac0a065 | ||
|
|
7f15910541 | ||
|
|
625b38d7af | ||
|
|
b9edf939f4 | ||
|
|
257bba00ac | ||
|
|
8d0b48f165 | ||
|
|
ce1f9cdf7c | ||
|
|
e612aec5d9 | ||
|
|
5bd0c0d25a | ||
|
|
26ad6853d2 | ||
|
|
8a4f7fe4f8 | ||
|
|
294e98c397 | ||
|
|
c1a2dcb25d | ||
|
|
a0972e0ac6 | ||
|
|
8062a4e8d6 | ||
|
|
a0ab5e86b5 | ||
|
|
a1dcaf82a0 | ||
|
|
78e17f6ee9 | ||
|
|
5ebc48b3f2 | ||
|
|
1ae4237920 | ||
|
|
5ca12d8332 | ||
|
|
7f8702d3d6 | ||
|
|
5f2447edbb | ||
|
|
c658b275fd | ||
|
|
9bbce01e1b | ||
|
|
bbe02dc3cf | ||
|
|
3d76aecaa6 | ||
|
|
64bd345a5d | ||
|
|
152c507499 | ||
|
|
e2ae628b17 | ||
|
|
6eabc0fe87 | ||
|
|
bf6f04cbe6 | ||
|
|
e0c86670e2 | ||
|
|
7840691420 | ||
|
|
96e1a7e6da | ||
|
|
5df73215f8 | ||
|
|
3996e93a20 | ||
|
|
246f24eda8 | ||
|
|
4aa72b96c1 | ||
|
|
0fc20c70af | ||
|
|
ebc915baae | ||
|
|
7435369615 | ||
|
|
2e836bb553 | ||
|
|
36ccfd21e7 | ||
|
|
44c323872a | ||
|
|
094972ea84 | ||
|
|
2707f054a5 | ||
|
|
4c95d595c0 | ||
|
|
573838a027 | ||
|
|
05f4e29a52 | ||
|
|
dbc0520992 | ||
|
|
7efe873d73 | ||
|
|
4058574cfa | ||
|
|
d17dedfa4f | ||
|
|
4768351e89 | ||
|
|
3f3f399231 | ||
|
|
316c923188 | ||
|
|
8fdaf0268d | ||
|
|
f2d86ae7d3 | ||
|
|
34ee326075 | ||
|
|
1656db9e58 | ||
|
|
802dace05e | ||
|
|
c2f2f2b817 | ||
|
|
dcb41e91eb | ||
|
|
67111efdad | ||
|
|
5fd677af76 | ||
|
|
b080f5a047 | ||
|
|
7e8094d53a | ||
|
|
c8d852caf6 | ||
|
|
f042eb41ab | ||
|
|
017e2f07a7 | ||
|
|
3a923b72a4 | ||
|
|
5bf1214859 | ||
|
|
2ef1ab0753 | ||
|
|
c218af6ea7 | ||
|
|
e0748b1970 | ||
|
|
3ee685ad1c | ||
|
|
17be46e229 | ||
|
|
370d4c7cd5 | ||
|
|
1700987bfc | ||
|
|
a1aa161527 | ||
|
|
9a7972dcb8 | ||
|
|
191f22e11a | ||
|
|
93632660bb | ||
|
|
84d415fb66 | ||
|
|
ad9db51434 | ||
|
|
1a37d7aa48 | ||
|
|
22eb197d6c | ||
|
|
3953018c2d | ||
|
|
cfe99a79bd | ||
|
|
ee812daf69 | ||
|
|
df66daa26a | ||
|
|
8013009880 | ||
|
|
95b99cc86a | ||
|
|
6a713ad834 | ||
|
|
c81e530d3c | ||
|
|
4b021ae6f0 | ||
|
|
a36f182b36 | ||
|
|
d8bb6a7816 | ||
|
|
57d474e183 | ||
|
|
d7e12aadbe | ||
|
|
c0df3902b7 | ||
|
|
4f2eb1914b | ||
|
|
d72f50ff32 | ||
|
|
debb208553 | ||
|
|
f581ef9453 | ||
|
|
b65354d237 | ||
|
|
e4ac7ea1ca | ||
|
|
9c7ecf6d14 | ||
|
|
917722257d | ||
|
|
3d61b6eab6 | ||
|
|
e64e25e4d6 | ||
|
|
f7a664f127 | ||
|
|
89bdf3b0b9 | ||
|
|
597f7eb5e9 | ||
|
|
ba23b823dc | ||
|
|
fa3b0dd3ca | ||
|
|
dd8988220e | ||
|
|
cc803ee802 | ||
|
|
598056d168 | ||
|
|
89e64c631e | ||
|
|
5cd003d9e6 | ||
|
|
468656b4aa | ||
|
|
22037d5fba | ||
|
|
4b7105dfea | ||
|
|
a5ec3aca7d | ||
|
|
785459d31b | ||
|
|
a9a3746d09 | ||
|
|
74ace058a6 | ||
|
|
96382d52ab | ||
|
|
ddbc8113a9 | ||
|
|
65115b9159 | ||
|
|
e255101299 | ||
|
|
a94338dc67 | ||
|
|
6ac5ea2a9f | ||
|
|
364fb6019c | ||
|
|
a79b61517b | ||
|
|
99361f54ca | ||
|
|
82c06dd76b | ||
|
|
17a9b8802f | ||
|
|
9b6f7fc9af | ||
|
|
57690891ce | ||
|
|
5896a4941d | ||
|
|
5ac4a71000 | ||
|
|
521e63529c | ||
|
|
24b446705b | ||
|
|
3c5ed47804 | ||
|
|
b967dc1fa5 | ||
|
|
af2caaab72 | ||
|
|
2cbe70ba34 | ||
|
|
8e1ea0f27b | ||
|
|
e3246ceb7e | ||
|
|
169f41a43c | ||
|
|
88ce30beb6 | ||
|
|
d260d5148e | ||
|
|
723ec19eed | ||
|
|
44f36d57e6 | ||
|
|
7ab8f61974 | ||
|
|
4bba3268d5 | ||
|
|
5f76e4c1ed | ||
|
|
92c4f20089 | ||
|
|
acfd372808 | ||
|
|
6054483dc7 | ||
|
|
25931bc1e6 | ||
|
|
9250c58013 | ||
|
|
4f226ab36a | ||
|
|
33e28fb96b | ||
|
|
206b9cea0d | ||
|
|
9dcb04a1e0 | ||
|
|
08543d0c76 | ||
|
|
937e6cb91e | ||
|
|
6c43be767c | ||
|
|
81b64ea0b5 | ||
|
|
ea0e23c172 | ||
|
|
4d07aa315b | ||
|
|
2e298b25e4 | ||
|
|
c38927da47 | ||
|
|
25607c04a7 | ||
|
|
cbd5be1b82 | ||
|
|
924b8469cb | ||
|
|
f24d93d4e4 | ||
|
|
65baa71b58 | ||
|
|
b8fa712847 | ||
|
|
095b067857 | ||
|
|
87c4586d61 | ||
|
|
b17254925d | ||
|
|
cf2c4f44a2 | ||
|
|
2bc55ff428 | ||
|
|
ee5769f31f | ||
|
|
3a8517b06f | ||
|
|
0363d3c32e | ||
|
|
a582c4cdb6 | ||
|
|
a43b6b0323 | ||
|
|
84a143a605 | ||
|
|
114438e669 | ||
|
|
50bde9976b | ||
|
|
18ea116827 | ||
|
|
0ab0687a3a | ||
|
|
72f85ad90f | ||
|
|
fb4e07f7a8 | ||
|
|
6e0b539e9c | ||
|
|
83b2c899f5 | ||
|
|
eb7ca20379 | ||
|
|
30d3ccd419 | ||
|
|
fb8fb7fed0 | ||
|
|
1abd239b9d | ||
|
|
9f1c8b2f8f | ||
|
|
c169423051 | ||
|
|
fdc6f32392 | ||
|
|
ea984cfb95 | ||
|
|
e7cdb2ebe5 | ||
|
|
4dae8edb76 | ||
|
|
a3e01b8884 | ||
|
|
6d33a2b0bb | ||
|
|
f7d38a1b9c | ||
|
|
45b27b0194 | ||
|
|
2a921c2c25 | ||
|
|
4c759cde1f | ||
|
|
c3984c89f7 | ||
|
|
96dfbc882d | ||
|
|
d3883e54b8 | ||
|
|
beaff53a79 | ||
|
|
b9b308f2fe | ||
|
|
a7bfd792f7 | ||
|
|
06fd9e3771 | ||
|
|
fb719e3d0b | ||
|
|
9f24cdf74c | ||
|
|
d7471c4f87 | ||
|
|
49177312fb | ||
|
|
5d2cb48f46 | ||
|
|
597f12c44a | ||
|
|
9f674382d5 | ||
|
|
6830a65923 | ||
|
|
0d9c3fe70b | ||
|
|
2e38ac7504 | ||
|
|
f208d7920c | ||
|
|
ecb4a6173d | ||
|
|
37a66fa5b6 | ||
|
|
f9e6bc2aec | ||
|
|
81a0240491 | ||
|
|
b4d31b492c | ||
|
|
32df924d02 | ||
|
|
c60a65bc93 | ||
|
|
4222251d6f | ||
|
|
c6e912f9e2 | ||
|
|
1df5c97144 | ||
|
|
b840a0f500 | ||
|
|
9f40bbba29 | ||
|
|
0086e1d7ca | ||
|
|
4732de71c6 | ||
|
|
8db9415f2a | ||
|
|
dd19d73db4 | ||
|
|
91450c7a95 | ||
|
|
1d20df627d | ||
|
|
4a10b1961c | ||
|
|
100cbc5f3f | ||
|
|
e0c6e819c2 | ||
|
|
9025cd9b72 | ||
|
|
2b891f5eb3 | ||
|
|
01bde8ff94 | ||
|
|
eed0e2e431 | ||
|
|
bda3bc4c8d | ||
|
|
93f3c31807 | ||
|
|
3aeb557196 | ||
|
|
8c7ebc02a0 | ||
|
|
1152e47b52 | ||
|
|
32a28d0d9c | ||
|
|
d6daad29fc | ||
|
|
4664ce2c35 | ||
|
|
171456c683 | ||
|
|
2c73fd6fbf | ||
|
|
0ee860a011 | ||
|
|
5127943673 | ||
|
|
3ee9656250 | ||
|
|
c0f63ee100 | ||
|
|
8fd720c3e3 | ||
|
|
4f5d0756c2 | ||
|
|
64e6e3aca9 | ||
|
|
8174300429 | ||
|
|
a453b06168 | ||
|
|
103036c546 | ||
|
|
ac9a4c839f | ||
|
|
3d2ddd15f8 | ||
|
|
ea4ab22017 | ||
|
|
8c53621c24 | ||
|
|
514baf3bf7 | ||
|
|
420151dbd9 | ||
|
|
156b28c771 | ||
|
|
ad801851a2 | ||
|
|
b647b753e0 | ||
|
|
48b855c581 | ||
|
|
c830d30553 | ||
|
|
0650182289 | ||
|
|
3e20c442de | ||
|
|
af87369cb3 | ||
|
|
edea73b1f8 | ||
|
|
893d7be5bf | ||
|
|
c5b77e1b49 | ||
|
|
a5e5bab74b | ||
|
|
8f96b8908e | ||
|
|
f3a6dd139c | ||
|
|
1dba0d4830 | ||
|
|
da85400e57 | ||
|
|
7f38caefd0 | ||
|
|
937594c130 | ||
|
|
3e7672edca | ||
|
|
098aba47c3 | ||
|
|
c67fc5693a | ||
|
|
6b5c6af613 | ||
|
|
3ccc36b3b7 | ||
|
|
e7828bb911 | ||
|
|
e255f0590b | ||
|
|
4615631d83 | ||
|
|
e708f9542f | ||
|
|
6bfbcdbfdb | ||
|
|
645b254173 | ||
|
|
fdc61f3ab2 | ||
|
|
a991d3b56b | ||
|
|
26a1a0a3bc | ||
|
|
73bc3a9853 | ||
|
|
9cb325ee6f | ||
|
|
9e1d038a65 | ||
|
|
7e5fe1d813 | ||
|
|
97dff151ae | ||
|
|
18681875e3 | ||
|
|
9b0a2714f0 | ||
|
|
a84ce21aec | ||
|
|
1fc1559d15 | ||
|
|
de70b02c2f | ||
|
|
6453b5b70e | ||
|
|
61b49ea2e3 | ||
|
|
21ed9480d7 | ||
|
|
09e83ad742 | ||
|
|
3360072f84 | ||
|
|
0ba59d80b6 | ||
|
|
d416a9b818 | ||
|
|
de1993a1fd | ||
|
|
307c71b66a | ||
|
|
b41ae80399 | ||
|
|
bbf9ba6d8d | ||
|
|
9bcd5f3c0a | ||
|
|
533aebe336 | ||
|
|
5f8fcef688 | ||
|
|
f37d67ff5e | ||
|
|
9bda22e702 | ||
|
|
23ac7f56fa | ||
|
|
4c4aa502d4 | ||
|
|
20bdf3a5b1 | ||
|
|
da108a9327 | ||
|
|
e6432b1262 | ||
|
|
99bc4f451a | ||
|
|
79b43270a7 | ||
|
|
3d33e65a35 | ||
|
|
5ab562f695 | ||
|
|
3cb278c35c | ||
|
|
c59827334c | ||
|
|
2d6bbf341d | ||
|
|
2f62128297 | ||
|
|
ed21e75235 | ||
|
|
87d2c9c05c | ||
|
|
df999ed1e1 | ||
|
|
154de2aee3 | ||
|
|
f808b8e930 | ||
|
|
5b2e57aa2f | ||
|
|
960364d953 | ||
|
|
0b9793ccd0 | ||
|
|
fff298523d | ||
|
|
e81b6fbc6e | ||
|
|
4dc1388ac7 | ||
|
|
1b69d6d658 | ||
|
|
f64a50f319 | ||
|
|
f299caf612 | ||
|
|
f76141a704 | ||
|
|
a3049d6433 | ||
|
|
ee353847be | ||
|
|
33b2fbb5ef | ||
|
|
7d84615545 | ||
|
|
b42113119a | ||
|
|
722944f307 | ||
|
|
e038c26963 | ||
|
|
56b9388702 | ||
|
|
0e438f6d5c | ||
|
|
9f1eb695b4 | ||
|
|
9fef5d1050 | ||
|
|
0bb7f77a8f | ||
|
|
9e4e562cfb | ||
|
|
92ec446cb9 | ||
|
|
9097da0284 | ||
|
|
eedeb009ec | ||
|
|
d8bc6abcf0 | ||
|
|
2293e3d105 | ||
|
|
550b3056fd | ||
|
|
1ba5e8052e | ||
|
|
6f5abeff2e | ||
|
|
7cbf6b131b | ||
|
|
a461298109 | ||
|
|
90c3a74b2a | ||
|
|
87373be960 | ||
|
|
85d9672e47 | ||
|
|
e0ae527190 | ||
|
|
7fb1bec84a | ||
|
|
1f308fb2b4 | ||
|
|
e2d36d493f | ||
|
|
7c43594075 | ||
|
|
e4827025be | ||
|
|
00798ca8cc | ||
|
|
e84cb3c3c2 | ||
|
|
78b9cecb52 | ||
|
|
93c54fe6f6 | ||
|
|
5f97d0fbbc | ||
|
|
dc01a8edd4 | ||
|
|
23cc2bfb8c | ||
|
|
9e379835c4 | ||
|
|
8ccbd216c6 | ||
|
|
90f4da29d7 | ||
|
|
54dbd5bbc8 | ||
|
|
849b8ec469 | ||
|
|
84e18f72ae | ||
|
|
633b98ef28 | ||
|
|
2a34a72bff | ||
|
|
24bae46e42 | ||
|
|
7585d4606e | ||
|
|
94bff1df66 | ||
|
|
2e60d20a76 | ||
|
|
ce59260ee9 | ||
|
|
387ebccf36 | ||
|
|
2f618af086 | ||
|
|
0ac33d22f7 | ||
|
|
c7bd5ac77d | ||
|
|
941c067765 | ||
|
|
839e023ed8 | ||
|
|
2e05a2b8c4 | ||
|
|
fc2c67e61c | ||
|
|
9c3e9fcdad | ||
|
|
1a4db21fe4 | ||
|
|
d96a52541f | ||
|
|
e7ac4c1ab3 | ||
|
|
ecd8505218 | ||
|
|
1fa1c3f9db | ||
|
|
91df741926 | ||
|
|
2a431cab03 | ||
|
|
9fdab3ced8 | ||
|
|
6e15e75391 | ||
|
|
1c2a1838fc | ||
|
|
bfd730aa4c | ||
|
|
e3c6a86b1e | ||
|
|
bbaeb917ff | ||
|
|
20f1e49b73 | ||
|
|
292656d899 | ||
|
|
05b36b484e | ||
|
|
be3016b8d5 | ||
|
|
5cf43d76bf | ||
|
|
6f05e810d9 | ||
|
|
947d2697cf | ||
|
|
449ddae628 | ||
|
|
6b90885d4f | ||
|
|
bd6c37adb6 | ||
|
|
59235276ac | ||
|
|
e5ce3fc51b | ||
|
|
9f97511356 | ||
|
|
ef0aac432c | ||
|
|
7928d83b02 | ||
|
|
3e91ec07e4 | ||
|
|
d680a9e3fb | ||
|
|
6086851fc1 | ||
|
|
61726df20c | ||
|
|
1601a657d4 | ||
|
|
50b14f696c | ||
|
|
c239baf801 | ||
|
|
18638859e6 | ||
|
|
224b16b247 | ||
|
|
d9d97969a3 | ||
|
|
897da4ee36 | ||
|
|
90f9f43335 | ||
|
|
0e1dee828a | ||
|
|
cbdc1f0753 | ||
|
|
7e306336d0 | ||
|
|
e7def4c211 | ||
|
|
19e1afbd1c | ||
|
|
fee32054e6 | ||
|
|
9754fdd995 | ||
|
|
ef20b9ff7a | ||
|
|
275611fbaa | ||
|
|
a070159cc5 | ||
|
|
20f9683ae0 | ||
|
|
dce384668b | ||
|
|
fdcd21e74b | ||
|
|
67b4fa313e | ||
|
|
5dff74109e | ||
|
|
20d970a0e2 | ||
|
|
94734ad377 | ||
|
|
14ad6a5972 | ||
|
|
9e66b5a9b1 | ||
|
|
f782cf375a | ||
|
|
3317916111 | ||
|
|
f367273549 | ||
|
|
91ef9b2fa9 | ||
|
|
579463933b | ||
|
|
989c5c1436 | ||
|
|
3113932151 | ||
|
|
125a970d71 | ||
|
|
89c0b2a6d8 | ||
|
|
31e379c300 | ||
|
|
843953379c | ||
|
|
2a90c1ca7e | ||
|
|
59bb1777be | ||
|
|
c5f3c550a6 | ||
|
|
1809f741cb | ||
|
|
9adfff5c1a | ||
|
|
8008b595d3 | ||
|
|
21bed0d21a | ||
|
|
4b1f5ec7c2 | ||
|
|
ab9439519a | ||
|
|
abeb9d64a3 | ||
|
|
fdb7ffa864 | ||
|
|
46845fd3e8 | ||
|
|
c53ca6ebc0 | ||
|
|
f04a3a2cfa | ||
|
|
364a53577e | ||
|
|
1b1997bf2d | ||
|
|
34f9adb1c9 | ||
|
|
2e7d468b90 | ||
|
|
86a717c80c | ||
|
|
76a3eb393c | ||
|
|
5f0cc969a0 | ||
|
|
755c1458f0 | ||
|
|
8795d733ec | ||
|
|
28f61c8b3a | ||
|
|
9abcc7b909 | ||
|
|
2c35f1c8fd | ||
|
|
136188259e | ||
|
|
02179b1218 | ||
|
|
1e350de136 | ||
|
|
9aeda4c5bd | ||
|
|
8eb30c353a | ||
|
|
c44a78a2e6 | ||
|
|
b6685bf806 | ||
|
|
269d690e71 | ||
|
|
4df268f10e | ||
|
|
19b3f01477 | ||
|
|
86811f4765 | ||
|
|
dd0352d93b | ||
|
|
30ec18d938 | ||
|
|
9d495ab2b5 | ||
|
|
9174de47a9 | ||
|
|
d857faf18e | ||
|
|
d5c8ba1690 | ||
|
|
9bb9b4829d | ||
|
|
e25c297c3c | ||
|
|
4de876f259 | ||
|
|
b9073961f7 | ||
|
|
a7a79d569a | ||
|
|
6165f53fcd | ||
|
|
4122cac66b | ||
|
|
a1dcebe4f4 | ||
|
|
6cbb23a819 | ||
|
|
5c57a31184 | ||
|
|
7b2c42aa75 | ||
|
|
1ed8d3938e | ||
|
|
b24984deb3 | ||
|
|
eabd9f5e60 | ||
|
|
d4609682af | ||
|
|
634415f79e | ||
|
|
4ba830fc31 | ||
|
|
3022a46039 | ||
|
|
d9a868ff60 | ||
|
|
c890a0c133 | ||
|
|
9ec934a94a | ||
|
|
5e606a964b | ||
|
|
d88034434c | ||
|
|
776d908703 | ||
|
|
444b15889f | ||
|
|
957450582f | ||
|
|
6d2d3669f3 | ||
|
|
1387654cc8 | ||
|
|
10eb218fb0 | ||
|
|
bfb2b30de6 | ||
|
|
426d4d72c6 | ||
|
|
cce29ba38c | ||
|
|
ed2e276b3a | ||
|
|
12a020aa62 | ||
|
|
b969101b33 | ||
|
|
86a742f635 | ||
|
|
9468f7f6d6 | ||
|
|
628a3f5cca | ||
|
|
e815e97440 | ||
|
|
0e7409c7ff | ||
|
|
393ca2a290 | ||
|
|
ad1d48e07b | ||
|
|
ac98aae160 | ||
|
|
c1267398a2 | ||
|
|
8c3a2bb63e | ||
|
|
923fc9087c | ||
|
|
83511fecc0 | ||
|
|
ed0552f214 | ||
|
|
5cf83a7212 | ||
|
|
7808eff0a9 | ||
|
|
da57dd13c5 | ||
|
|
f1826ea389 | ||
|
|
c884e5000e | ||
|
|
1ccac01cee | ||
|
|
50a5d3756f | ||
|
|
ca86726f9f | ||
|
|
6b5317e7cc | ||
|
|
2a1d28ea3a | ||
|
|
0e0ff51582 | ||
|
|
cd700aaf6e | ||
|
|
188ec1e258 | ||
|
|
d01fb265d6 | ||
|
|
db688e3ec1 | ||
|
|
e767bbb41f | ||
|
|
2b599df57a | ||
|
|
5baa10a6b6 | ||
|
|
3e1a389629 | ||
|
|
37e6207396 | ||
|
|
927a2dc849 | ||
|
|
ce9f9594da | ||
|
|
f0bf37b6cb | ||
|
|
2f0b35a105 | ||
|
|
7a9ed81f5f | ||
|
|
12e7d570a2 | ||
|
|
bb7934bf04 | ||
|
|
fb3c718963 | ||
|
|
231fc607f9 | ||
|
|
9594a3aa45 | ||
|
|
162fcab347 | ||
|
|
0c8bdfd7cd | ||
|
|
5e4dc71907 | ||
|
|
3e4433f715 | ||
|
|
29062e629f | ||
|
|
47f7272ba1 | ||
|
|
bf6f3f613d | ||
|
|
0c9a643216 | ||
|
|
fa2d843403 | ||
|
|
1dc5312f00 | ||
|
|
73444f2957 | ||
|
|
a18a6b8db8 | ||
|
|
bf56591fb8 | ||
|
|
5ea428a30d | ||
|
|
af524c4d65 | ||
|
|
2bc9f35052 | ||
|
|
55a0c5068f | ||
|
|
8128b15e41 | ||
|
|
8081b0e033 | ||
|
|
61cecbb337 | ||
|
|
aee1309c91 | ||
|
|
710c1df413 | ||
|
|
0f165a95a8 | ||
|
|
581f04c80b | ||
|
|
511be4acc6 | ||
|
|
d77b29f1d7 | ||
|
|
092a4d9a7e | ||
|
|
b3cab3ce31 | ||
|
|
e5279b0e2e | ||
|
|
9ff337aa3b | ||
|
|
441facc6e0 | ||
|
|
998d6cdfc4 | ||
|
|
ddc10b2d0c | ||
|
|
4f6f651b7d | ||
|
|
68c7667a20 | ||
|
|
0b62d71e70 | ||
|
|
be5780ef90 | ||
|
|
e5c52796c3 | ||
|
|
c5e36f8e3c | ||
|
|
5a85c4b91b | ||
|
|
0201072c1b | ||
|
|
aa029ed991 | ||
|
|
0777e896f1 | ||
|
|
7f90231b8f | ||
|
|
cbe63bbabe | ||
|
|
de1deaf0bd | ||
|
|
e00a97944a | ||
|
|
a65f84db38 | ||
|
|
8c8ecec3e9 | ||
|
|
b77864931b | ||
|
|
e60a84d0ed | ||
|
|
f025277147 | ||
|
|
1e00d0b926 | ||
|
|
29b1455f36 | ||
|
|
0162c116da | ||
|
|
58fe1c2d2a | ||
|
|
4363b8b32d | ||
|
|
cfac8435a7 | ||
|
|
35f26ff855 | ||
|
|
f66fc01620 | ||
|
|
082a2dde35 | ||
|
|
814ab77538 | ||
|
|
8eefb092c8 | ||
|
|
55e7f0486a | ||
|
|
88ac2da7c2 | ||
|
|
27510a6e9e | ||
|
|
7fda6418e1 | ||
|
|
45bd0edae5 | ||
|
|
3d733a16e9 | ||
|
|
fe623afaad | ||
|
|
b840a980e3 | ||
|
|
2ec98eb048 | ||
|
|
253cd3b66b | ||
|
|
920120d05a | ||
|
|
4ba058986e | ||
|
|
03b7255ddd | ||
|
|
2de7f8b224 | ||
|
|
bbf2f1d571 | ||
|
|
9cdd5e99a4 | ||
|
|
897ed7125b | ||
|
|
459d259185 | ||
|
|
aac6336e49 | ||
|
|
fc1155f974 | ||
|
|
6a09fa23d0 | ||
|
|
142a0f8a83 | ||
|
|
d1dec41f76 | ||
|
|
69a165db86 | ||
|
|
dffb33cecf | ||
|
|
e7917c16c9 | ||
|
|
e05b7f0b76 | ||
|
|
aeea70f95f | ||
|
|
ded40babb5 | ||
|
|
e355f69401 | ||
|
|
c2b1327deb | ||
|
|
f7ba7444e8 | ||
|
|
aafeebd0c8 | ||
|
|
6b0d47b364 | ||
|
|
d9e790e7dc | ||
|
|
51b5cdd430 | ||
|
|
aced7b5b00 | ||
|
|
0475594cb2 | ||
|
|
04518e9e80 | ||
|
|
a57947c513 | ||
|
|
372e81a842 | ||
|
|
41f531ceaf | ||
|
|
b46d46667f | ||
|
|
226671b550 | ||
|
|
916cfa6b83 | ||
|
|
49263b5314 | ||
|
|
95a21c8fd7 | ||
|
|
57166b400c | ||
|
|
79660f2eb1 | ||
|
|
3ea9068e18 | ||
|
|
e4c672bdbb | ||
|
|
791a78ad1f | ||
|
|
6da90b34fe | ||
|
|
43769b5bb3 | ||
|
|
f98eb5808b | ||
|
|
3525cabf48 | ||
|
|
54a76342f5 | ||
|
|
154a65fc31 | ||
|
|
bd7a46f514 | ||
|
|
79a307bca2 | ||
|
|
38f42a0fa2 | ||
|
|
b4cdfcb506 | ||
|
|
d3cef72f26 | ||
|
|
ef151888fb | ||
|
|
ba15bbfe33 | ||
|
|
3bdfae61a2 | ||
|
|
4404126501 | ||
|
|
5c87c6a435 | ||
|
|
adeb372a66 | ||
|
|
c0d7c6693f | ||
|
|
3ec4670478 | ||
|
|
f842712551 | ||
|
|
9f01625e23 | ||
|
|
7f091e7019 | ||
|
|
4f07805d0a | ||
|
|
a7d1a9cfcb | ||
|
|
48c83aa9d0 | ||
|
|
c797c1750c | ||
|
|
c6bdc810ab | ||
|
|
a8135dec1e | ||
|
|
2fdb5fd6ce | ||
|
|
7f42096d0f | ||
|
|
e2c813df4d | ||
|
|
a2f70a3751 | ||
|
|
286fa93a8d | ||
|
|
557d86aa79 | ||
|
|
8e68d5e2d5 | ||
|
|
1a16da38d5 | ||
|
|
cbd3d5e3a5 | ||
|
|
78fbed8c3e | ||
|
|
f267ca1f3a | ||
|
|
a6eb824950 | ||
|
|
dcd1527a11 | ||
|
|
f8a92d1eed | ||
|
|
e55e468754 | ||
|
|
ff2aa20565 | ||
|
|
90b5691183 | ||
|
|
5af0d33164 | ||
|
|
e5072c6b12 | ||
|
|
90cf7f012c | ||
|
|
484516da51 | ||
|
|
5abe22d1a5 | ||
|
|
f6b304250b | ||
|
|
36526700a9 | ||
|
|
32294978a3 | ||
|
|
a0e931005b | ||
|
|
9c7485331a | ||
|
|
99d9cf500b | ||
|
|
4f62da0f0d | ||
|
|
b4bcc60657 | ||
|
|
5139bd42f6 | ||
|
|
cf7a271f90 | ||
|
|
74cad1612f | ||
|
|
73e22c115c | ||
|
|
9be0d6b53d | ||
|
|
bbf6d5f2f5 | ||
|
|
c4861340e9 | ||
|
|
5996c3824c | ||
|
|
c172fb3b32 | ||
|
|
03a0d11c4d | ||
|
|
156e0187bf | ||
|
|
fcaaa7b4c2 | ||
|
|
2f098325f8 | ||
|
|
9dc30fbd2a | ||
|
|
024d268d8c | ||
|
|
eaa737fecd | ||
|
|
845ad0be39 | ||
|
|
2259ce4cdf | ||
|
|
34f9b2a8f7 | ||
|
|
d37dcc636f | ||
|
|
804a1e69f2 | ||
|
|
f7b1222073 | ||
|
|
4fd4fbc255 | ||
|
|
8393c5f016 | ||
|
|
5ff341206e | ||
|
|
da59afe798 | ||
|
|
6270ed2f8a | ||
|
|
80e77b5e6d | ||
|
|
58c7d4474c | ||
|
|
3af964304f | ||
|
|
4289324c4b | ||
|
|
9f3c817491 | ||
|
|
a9cf0ca25f | ||
|
|
72a5612a29 | ||
|
|
d7f2153631 | ||
|
|
26b07ccafc | ||
|
|
1205fa68df | ||
|
|
f5be0fb218 | ||
|
|
88fc38c8f0 | ||
|
|
545de7a3a1 | ||
|
|
6ba2b2b384 | ||
|
|
d5ccc32b4d | ||
|
|
e719a9ef6f | ||
|
|
a02d38072a | ||
|
|
f2cd610750 | ||
|
|
db34044c7f | ||
|
|
036edd6206 | ||
|
|
f40ed8bad7 | ||
|
|
41f50057f1 | ||
|
|
c62e53807f | ||
|
|
10d7a35841 | ||
|
|
6b4105ffe6 | ||
|
|
2713445e91 | ||
|
|
1984aabc95 | ||
|
|
f4c4ca64a8 | ||
|
|
2a02c4084a | ||
|
|
e242b2820c | ||
|
|
6467b8d903 | ||
|
|
3e2b6a1821 | ||
|
|
4d009daaa0 | ||
|
|
d4a14fcb3d | ||
|
|
49b79fa02d | ||
|
|
c957edbe75 | ||
|
|
33ae2be52e | ||
|
|
496c1db974 | ||
|
|
f381274278 | ||
|
|
398339218e | ||
|
|
4dda424f74 | ||
|
|
f403c1f18b | ||
|
|
ff5d94a7a4 | ||
|
|
a15fc009da | ||
|
|
6c4390c848 | ||
|
|
a3188b44f0 | ||
|
|
aaa72ddbfc | ||
|
|
bcf3a3ab93 | ||
|
|
5feebd300e | ||
|
|
aec23e5f79 | ||
|
|
52a466b8af | ||
|
|
baa32218b0 | ||
|
|
fd0b05943d | ||
|
|
2e0145fb95 | ||
|
|
c894ea4ea2 | ||
|
|
88278dee74 | ||
|
|
d0fadd992f | ||
|
|
eb45ce0e8a | ||
|
|
194b700592 | ||
|
|
5454c2a7f1 | ||
|
|
a6568626a5 | ||
|
|
59943acffe | ||
|
|
d4e7654ed0 | ||
|
|
68b458ece9 | ||
|
|
1119ad3a2f | ||
|
|
29e68e9d79 | ||
|
|
c1fe2ec5ae | ||
|
|
81cacd9f15 | ||
|
|
6def0ab5f1 | ||
|
|
d20627585a | ||
|
|
2bcb60fe56 | ||
|
|
0f83379dc0 | ||
|
|
ca6d5fd05c | ||
|
|
b9e21e2367 | ||
|
|
665b768cef | ||
|
|
b272b967e2 | ||
|
|
22c16a8b71 | ||
|
|
f924aa18f2 | ||
|
|
72c446f160 | ||
|
|
2028b1b517 | ||
|
|
72a82cc0ac | ||
|
|
eef35883b7 | ||
|
|
8028e07815 | ||
|
|
3fc6569d46 | ||
|
|
2303d0fd09 | ||
|
|
9a007c30d4 | ||
|
|
8a545a0d04 | ||
|
|
0993e44b4f | ||
|
|
d634b502cf | ||
|
|
53fc7eaf03 | ||
|
|
3c42c5407c | ||
|
|
9d9a8ff735 | ||
|
|
abed230cdb | ||
|
|
e9879cd07b | ||
|
|
84c51f933c | ||
|
|
977c43fffb | ||
|
|
f99a19b6ca | ||
|
|
5a7a88b843 | ||
|
|
0ffdf2bba9 | ||
|
|
38ed870ffe | ||
|
|
1e4ed404c5 | ||
|
|
642920585f | ||
|
|
af07eb115a | ||
|
|
66371f9920 | ||
|
|
aabe0677c0 | ||
|
|
0fa65ebd4d | ||
|
|
27fddd2c35 | ||
|
|
fced1113d3 | ||
|
|
4d050c34cb | ||
|
|
a8c28714cd | ||
|
|
eabfd803c9 | ||
|
|
07b764ead6 | ||
|
|
8bad5d61fd | ||
|
|
9f42a75ef6 | ||
|
|
ddbfdb0799 | ||
|
|
3b07844548 | ||
|
|
85288d7b61 | ||
|
|
8174a2f27b | ||
|
|
e3ca0513a0 | ||
|
|
95a01f9002 | ||
|
|
52551cb771 | ||
|
|
4dfb834f7c | ||
|
|
c35e38c5e9 | ||
|
|
48734bb3b5 | ||
|
|
4e9f22c602 | ||
|
|
f88bed7a30 | ||
|
|
ccd02552dd | ||
|
|
4b1f9e50f2 | ||
|
|
0b50010436 | ||
|
|
d773103730 | ||
|
|
c7e3eb9b3f | ||
|
|
f15feb2ac6 | ||
|
|
2f1ed9a34b | ||
|
|
bb8234c2f1 | ||
|
|
bacd2a8c79 | ||
|
|
103a829eac | ||
|
|
0dcecfa526 | ||
|
|
bcd541d65f | ||
|
|
3608775306 | ||
|
|
8181d41bb5 | ||
|
|
a996e61a2e | ||
|
|
8a19a049b2 | ||
|
|
c742137dc8 | ||
|
|
9dc9aff016 | ||
|
|
c6582dbe37 | ||
|
|
709a3e75cf | ||
|
|
cb82c6e3e0 | ||
|
|
d6441f4397 | ||
|
|
08893f03a5 | ||
|
|
4be3826dd5 | ||
|
|
a21cf67a6c | ||
|
|
fe03c39241 | ||
|
|
6e78eca7c8 | ||
|
|
5d3dae1492 | ||
|
|
061565865c | ||
|
|
b639e18d39 | ||
|
|
2b54d3397c | ||
|
|
ff763e4005 | ||
|
|
8e72bbaa9d | ||
|
|
4b37932ba1 | ||
|
|
d1bfb6bfb7 | ||
|
|
35f3d2ff90 | ||
|
|
a60cb7dbaa | ||
|
|
cca4e1a080 | ||
|
|
c04cc62ebf | ||
|
|
8158e952b9 | ||
|
|
b717efb577 | ||
|
|
3dbc707820 | ||
|
|
5a2dde814d | ||
|
|
4fc5a52850 | ||
|
|
d005aa139e | ||
|
|
5efdd391eb | ||
|
|
adc4d0194f | ||
|
|
1912439526 | ||
|
|
800810a181 | ||
|
|
e80f8e8c09 | ||
|
|
1fdfa2ecfd | ||
|
|
51dcfc06dc | ||
|
|
8edc0c2afc | ||
|
|
ebc3a3ac74 | ||
|
|
5cd6995fb5 | ||
|
|
ed79abed76 | ||
|
|
c2bd79131a | ||
|
|
511f6555c9 | ||
|
|
049fcf1ac5 | ||
|
|
e674c73ee6 | ||
|
|
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 | ||
|
|
bb84e33d99 | ||
|
|
b2ac4eb29b | ||
|
|
25554bc331 | ||
|
|
a018260fe9 | ||
|
|
9a2cdc299f | ||
|
|
e41452afeb | ||
|
|
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 | ||
|
|
ea8cd283eb | ||
|
|
058b2bec22 | ||
|
|
5ea605d8de | ||
|
|
7f0dd15bab | ||
|
|
a938f4cfe1 | ||
|
|
28ad393b00 | ||
|
|
f3b834d536 | ||
|
|
692d737a82 | ||
|
|
d5897b9a5d | ||
|
|
7b780efb42 | ||
|
|
4e09d27c6f | ||
|
|
e1d3a8a6e9 | ||
|
|
235ac72a06 | ||
|
|
dd06653e53 | ||
|
|
7eee3ceb70 | ||
|
|
19b89a0e19 | ||
|
|
a0aefb3d3f | ||
|
|
20fb9ea351 | ||
|
|
ee6f01918c | ||
|
|
71e25058c1 | ||
|
|
35bcc463e5 | ||
|
|
5b8a26f1d1 | ||
|
|
cc340d9cdc | ||
|
|
786ea39ac4 | ||
|
|
df57eb3824 | ||
|
|
3301bad391 | ||
|
|
f5d75b099b | ||
|
|
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 | ||
|
|
1e26b86f15 | ||
|
|
b6b96f8841 | ||
|
|
c1b602145f | ||
|
|
719b47e3aa | ||
|
|
d57a56407b | ||
|
|
3cee7b6378 | ||
|
|
1e03393b68 | ||
|
|
dde673f8d7 | ||
|
|
f7caf6f5c6 | ||
|
|
cdbe853595 | ||
|
|
3f49fc5f2c | ||
|
|
c517ff57ca | ||
|
|
ba869e5601 | ||
|
|
46d53c37fa | ||
|
|
94b28e420c | ||
|
|
9368e4db33 | ||
|
|
ae15e644b1 | ||
|
|
3a5c4b68bb | ||
|
|
a7a5365af2 | ||
|
|
6ae3a09ef3 | ||
|
|
8608a8e64c | ||
|
|
2481693cf2 | ||
|
|
1c5fda515f | ||
|
|
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 | ||
|
|
1632bd4a18 | ||
|
|
a2d343b108 | ||
|
|
a43af44e9c | ||
|
|
876b7081d8 | ||
|
|
cb2cb15916 | ||
|
|
3510531683 | ||
|
|
744268f388 | ||
|
|
18b082955b | ||
|
|
70438b7715 | ||
|
|
53681cbdb6 | ||
|
|
e7f579b75d | ||
|
|
21c4cd7cb2 | ||
|
|
5a6404712c | ||
|
|
b332e4aaf9 | ||
|
|
cff00f43c2 | ||
|
|
1cf8d6b631 | ||
|
|
f724ece386 | ||
|
|
aba295323e | ||
|
|
c804883350 | ||
|
|
cebbc4e2b7 | ||
|
|
77f4520207 | ||
|
|
ca77392bd1 | ||
|
|
71c07ed930 | ||
|
|
20ceb493b6 | ||
|
|
e444f0cfe6 | ||
|
|
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 | ||
|
|
074d8f0a26 |
9
.github/multiwrapper
vendored
Executable file
9
.github/multiwrapper
vendored
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
# symlink this to dropbear/dbclient/dropbearkey next to dropbearmulti
|
||||
# good enough for testing purposes.
|
||||
|
||||
DIR=$(dirname $0)
|
||||
PROG=$(basename $0)
|
||||
exec $DIR/dropbearmulti $PROG "$@"
|
||||
|
||||
25
.github/workflows/autoconf.yml
vendored
Normal file
25
.github/workflows/autoconf.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# Checks that autoconf has been run if configure.ac was updated
|
||||
# Assumes that autoconf 2.69 was run, the same as ubuntu 20.04
|
||||
name: Autoconf Up To Date
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
autoconf:
|
||||
runs-on: 'ubuntu-22.04'
|
||||
|
||||
steps:
|
||||
- name: deps
|
||||
run: |
|
||||
sudo apt-get -y update
|
||||
sudo apt-get -y install autoconf
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: run autoconf
|
||||
run: autoconf && autoheader
|
||||
|
||||
- name: check no difference
|
||||
run: git diff --exit-code
|
||||
268
.github/workflows/build.yml
vendored
Normal file
268
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
# Can be used locally with https://github.com/nektos/act
|
||||
# Note the XXX line below.
|
||||
|
||||
name: BuildTest
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os || 'ubuntu-22.04' }}
|
||||
strategy:
|
||||
matrix:
|
||||
# XXX uncomment the line below to work with act, see https://github.com/nektos/act/issues/996
|
||||
# name: []
|
||||
|
||||
# Rather than a boolean False we use eg
|
||||
# runcheck: 'no'
|
||||
# Otherwise GH expressions will make a None var
|
||||
# compare with False. We want an undefined default of True.
|
||||
|
||||
# MULTI and NOWRITEV are passed as integers to the build
|
||||
include:
|
||||
- name: plain linux
|
||||
|
||||
- name: multi binary
|
||||
multi: 1
|
||||
multilink: 1
|
||||
|
||||
- name: multi binary, dropbearmulti argv0
|
||||
multi: 1
|
||||
multiwrapper: 1
|
||||
|
||||
- name: client only
|
||||
runcheck: 'no'
|
||||
make_target: PROGRAMS=dbclient
|
||||
|
||||
- name: server only
|
||||
runcheck: 'no'
|
||||
make_target: PROGRAMS=dropbear
|
||||
|
||||
- name: bundled libtom, bionic , no writev()
|
||||
# test can use an older distro with bundled libtommath
|
||||
os: ubuntu-18.04
|
||||
configure_flags: --enable-bundled-libtom --enable-werror
|
||||
# NOWRITEV is unrelated, test here to save a job
|
||||
nowritev: 1
|
||||
# our tests expect >= python3.7
|
||||
runcheck: 'no'
|
||||
|
||||
- name: linux clang
|
||||
cc: clang
|
||||
|
||||
# Some platforms only have old compilers, we try to keep
|
||||
# compatibilty. For some reason -std=c89 doesn't enforce
|
||||
# early declarations so we specify it anyway.
|
||||
- name: c89
|
||||
extracflags: -std=c89 -Wdeclaration-after-statement
|
||||
|
||||
- name: macos 12
|
||||
os: macos-12
|
||||
cc: clang
|
||||
# OS X says daemon() and utmp are deprecated.
|
||||
# OS X tests for undefined TARGET_OS_EMBEDDED in libc headers
|
||||
extracflags: -Wno-deprecated-declarations -Wno-undef
|
||||
runcheck: 'no'
|
||||
apt: 'no'
|
||||
# fails with:
|
||||
# .../ranlib: file: libtomcrypt.a(cbc_setiv.o) has no symbols
|
||||
ranlib: ranlib -no_warning_for_no_symbols
|
||||
|
||||
- name: macos 11
|
||||
os: macos-11
|
||||
cc: clang
|
||||
extracflags: -Wno-deprecated-declarations -Wno-undef
|
||||
runcheck: 'no'
|
||||
apt: 'no'
|
||||
ranlib: ranlib -no_warning_for_no_symbols
|
||||
|
||||
# Check that debug code doesn't bitrot
|
||||
- name: DEBUG_TRACE
|
||||
localoptions: |
|
||||
#define DEBUG_TRACE 5
|
||||
|
||||
# Check off-by-default options don't bitrot
|
||||
- name: nondefault options
|
||||
nondefault: 1
|
||||
configure_flags: --enable-pam
|
||||
|
||||
- name: most options disabled
|
||||
configure_flags: --disable-harden --disable-zlib --disable-openpty --disable-lastlog
|
||||
runcheck: 'no'
|
||||
localoptions: |
|
||||
#define DROPBEAR_RSA 0
|
||||
#define INETD_MODE 0
|
||||
#define DROPBEAR_REEXEC 0
|
||||
#define DROPBEAR_SMALL_CODE 0
|
||||
#define DROPBEAR_CLI_LOCALTCPFWD 0
|
||||
#define DROPBEAR_CLI_REMOTETCPFWD 0
|
||||
#define DROPBEAR_SVR_LOCALTCPFWD 0
|
||||
#define DROPBEAR_SVR_REMOTETCPFWD 0
|
||||
#define DROPBEAR_SVR_AGENTFWD 0
|
||||
#define DROPBEAR_CLI_AGENTFWD 0
|
||||
#define DROPBEAR_CLI_PROXYCMD 0
|
||||
#define DROPBEAR_USER_ALGO_LIST 0
|
||||
#define DROPBEAR_AES128 0
|
||||
#define DROPBEAR_AES256 0
|
||||
#define DROPBEAR_ENABLE_CTR_MODE 0
|
||||
#define DROPBEAR_SHA1_HMAC 0
|
||||
#define DROPBEAR_SHA2_256_HMAC 0
|
||||
#define DROPBEAR_RSA 0
|
||||
#define DROPBEAR_ECDSA 0
|
||||
#define DROPBEAR_SK_KEYS 0
|
||||
#define DROPBEAR_DELAY_HOSTKEY 0
|
||||
#define DROPBEAR_DH_GROUP14_SHA1 0
|
||||
#define DROPBEAR_DH_GROUP14_SHA256 0
|
||||
#define DROPBEAR_ECDH 0
|
||||
#define DROPBEAR_DH_GROUP1_CLIENTONLY 0
|
||||
#define DO_MOTD 0
|
||||
#define DROPBEAR_SVR_PUBKEY_AUTH 0
|
||||
#define DROPBEAR_CLI_PASSWORD_AUTH 0
|
||||
#define DROPBEAR_CLI_PUBKEY_AUTH 0
|
||||
#define DROPBEAR_USE_PASSWORD_ENV 0
|
||||
#define DROPBEAR_SFTPSERVER 0
|
||||
|
||||
# # Fuzzers run standalone. A bit superfluous with cifuzz, but
|
||||
# # good to run the whole corpus to keep it working.
|
||||
# - name: fuzzing with address sanitizer
|
||||
# configure_flags: --enable-fuzz --disable-harden --enable-bundled-libtom --enable-werror
|
||||
# ldflags: -fsanitize=address
|
||||
# extracflags: -fsanitize=address
|
||||
# # -fsanitize=address prevents aslr, don't test it
|
||||
# pytest_addopts: -k "not aslr"
|
||||
# fuzz: True
|
||||
# cc: clang
|
||||
|
||||
# # Undefined Behaviour sanitizer
|
||||
# - name: fuzzing with undefined behaviour sanitizer
|
||||
# configure_flags: --enable-fuzz --disable-harden --enable-bundled-libtom --enable-werror
|
||||
# ldflags: -fsanitize=undefined
|
||||
# # don't fail with alignment due to https://github.com/libtom/libtomcrypt/issues/549
|
||||
# extracflags: -fsanitize=undefined -fno-sanitize-recover=undefined -fsanitize-recover=alignment
|
||||
# pytest_addopts: -k "not aslr"
|
||||
# fuzz: True
|
||||
# cc: clang
|
||||
|
||||
env:
|
||||
MULTI: ${{ matrix.multi }}
|
||||
CC: ${{ matrix.cc || 'gcc' }}
|
||||
LDFLAGS: ${{ matrix.ldflags }}
|
||||
EXTRACFLAGS: ${{ matrix.extracflags }}
|
||||
CONFIGURE_FLAGS: ${{ matrix.configure_flags || '--enable-werror' }}
|
||||
MAKE_TARGET: ${{ matrix.make_target }}
|
||||
# for fuzzing
|
||||
CXX: clang++
|
||||
RANLIB: ${{ matrix.ranlib || 'ranlib' }}
|
||||
# pytest in "make check" recognises this for extra arguments
|
||||
PYTEST_ADDOPTS: ${{ matrix.pytest_addopts }}
|
||||
# some pytests depend on special setup from this file. see authorized_keys below.
|
||||
DBTEST_IN_ACTION: true
|
||||
LOCALOPTIONS: ${{ matrix.localoptions }}
|
||||
|
||||
steps:
|
||||
- name: deps
|
||||
if: ${{ matrix.apt != 'no' }}
|
||||
run: |
|
||||
sudo apt-get -y update
|
||||
sudo apt-get -y install zlib1g-dev libtomcrypt-dev libtommath-dev mercurial python3-venv libpam0g-dev $CC
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: configure
|
||||
run: ./configure $CONFIGURE_FLAGS CFLAGS="-O2 -Wall -Wno-pointer-sign $EXTRACFLAGS" --prefix="$HOME/inst" || (cat config.log; exit 1)
|
||||
|
||||
- name: nowritev
|
||||
if: ${{ matrix.nowritev }}
|
||||
run: sed -i -e s/HAVE_WRITEV/DONT_HAVE_WRITEV/ config.h
|
||||
|
||||
- name: localoptions
|
||||
run: |
|
||||
echo "$LOCALOPTIONS" > localoptions.h
|
||||
echo "#define DROPBEAR_DSS 1" >> localoptions.h
|
||||
cat localoptions.h
|
||||
|
||||
- name: nondefault
|
||||
if: ${{ matrix.nondefault }}
|
||||
run: |
|
||||
# Turn on anything that's off by default. Rough but seems sufficient
|
||||
grep ' 0$' default_options.h | sed 's/0$/1/' > localoptions.h
|
||||
# PAM clashes with password
|
||||
echo "#define DROPBEAR_SVR_PASSWORD_AUTH 0" >> localoptions.h
|
||||
# 1 second timeout is too short
|
||||
sed -i "s/DEFAULT_IDLE_TIMEOUT 1/DEFAULT_IDLE_TIMEOUT 99/" localoptions.h
|
||||
|
||||
- name: make
|
||||
run: make -j3 $MAKE_TARGET
|
||||
|
||||
- name: multilink
|
||||
if: ${{ matrix.multilink }}
|
||||
run: make multilink
|
||||
|
||||
- name: multi wrapper script
|
||||
if: ${{ matrix.multiwrapper }}
|
||||
run: |
|
||||
cp .github/multiwrapper dropbear
|
||||
cp .github/multiwrapper dbclient
|
||||
cp .github/multiwrapper dropbearkey
|
||||
cp .github/multiwrapper dropbearconvert
|
||||
|
||||
- name: makefuzz
|
||||
run: make fuzzstandalone
|
||||
if: ${{ matrix.fuzz }}
|
||||
|
||||
# avoid concurrent install, osx/freebsd is racey (https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=208093)
|
||||
- name: make install
|
||||
run: make install
|
||||
|
||||
- name: keys
|
||||
if: ${{ matrix.runcheck != 'no' }}
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
# remove old files so we can rerun in-place with "act -r" during test development
|
||||
rm -vf ~/.ssh/id_dropbear*
|
||||
~/inst/bin/dropbearkey -t ecdsa -f ~/.ssh/id_dropbear | grep ^ecdsa > ~/.ssh/authorized_keys
|
||||
|
||||
# to test setting SSH_PUBKEYINFO, replace the trailing comment
|
||||
~/inst/bin/dropbearkey -t ecdsa -f ~/.ssh/id_dropbear_key2 | grep ^ecdsa | sed 's/[^ ]*$/key2 extra/' >> ~/.ssh/authorized_keys
|
||||
~/inst/bin/dropbearkey -t ecdsa -f ~/.ssh/id_dropbear_key3 | grep ^ecdsa | sed 's/[^ ]*$/key3%char/' >> ~/.ssh/authorized_keys
|
||||
~/inst/bin/dropbearkey -t ecdsa -f ~/.ssh/id_dropbear_key4 | grep ^ecdsa | sed 's/[^ ]*$/key4,char/' >> ~/.ssh/authorized_keys
|
||||
chmod 700 ~ ~/.ssh ~/.ssh/authorized_keys
|
||||
ls -ld ~ ~/.ssh ~/.ssh/authorized_keys
|
||||
|
||||
# upload config.log if something has failed
|
||||
- name: config.log
|
||||
if: ${{ !env.ACT && (failure() || cancelled()) }}
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: config.log
|
||||
path: config.log
|
||||
|
||||
- name: check
|
||||
if: ${{ matrix.runcheck != 'no' }}
|
||||
run: make check
|
||||
|
||||
# Sanity check that the binary runs
|
||||
- name: genrsa
|
||||
if: ${{ matrix.runcheck != 'no' }}
|
||||
run: ~/inst/bin/dropbearkey -t rsa -f testrsa
|
||||
- name: gendss
|
||||
if: ${{ matrix.runcheck != 'no' }}
|
||||
run: ~/inst/bin/dropbearkey -t dss -f testdss
|
||||
- name: genecdsa256
|
||||
if: ${{ matrix.runcheck != 'no' }}
|
||||
run: ~/inst/bin/dropbearkey -t ecdsa -f testec256 -s 256
|
||||
- name: genecdsa384
|
||||
if: ${{ matrix.runcheck != 'no' }}
|
||||
run: ~/inst/bin/dropbearkey -t ecdsa -f testec384 -s 384
|
||||
- name: genecdsa521
|
||||
if: ${{ matrix.runcheck != 'no' }}
|
||||
run: ~/inst/bin/dropbearkey -t ecdsa -f testec521 -s 521
|
||||
- name: gened25519
|
||||
if: ${{ matrix.runcheck != 'no' }}
|
||||
run: ~/inst/bin/dropbearkey -t ed25519 -f tested25519
|
||||
|
||||
- name: fuzz
|
||||
if: ${{ matrix.fuzz }}
|
||||
run: ./fuzzers_test.sh
|
||||
30
.github/workflows/cifuzz.yml
vendored
Normal file
30
.github/workflows/cifuzz.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
# Runs fuzzers for a little while on pull requests.
|
||||
# From https://google.github.io/oss-fuzz/getting-started/continuous-integration/
|
||||
name: CIFuzz
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
Fuzzing:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Build Fuzzers
|
||||
id: build
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'dropbear'
|
||||
dry-run: false
|
||||
- name: Run Fuzzers
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'dropbear'
|
||||
fuzz-seconds: 1200
|
||||
dry-run: false
|
||||
- name: Upload Crash
|
||||
uses: actions/upload-artifact@v1
|
||||
if: failure() && steps.build.outcome == 'success'
|
||||
with:
|
||||
name: artifacts
|
||||
path: ./out/artifacts
|
||||
36
.github/workflows/tarball.yml
vendored
Normal file
36
.github/workflows/tarball.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
name: tarball sha256sum
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
tarball:
|
||||
runs-on: 'ubuntu-22.04'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: release.sh
|
||||
run: ./release.sh --testrel | tee log1.txt
|
||||
|
||||
- name: extract output
|
||||
run: |
|
||||
grep ^SHA256 log1.txt > sha256sum.txt
|
||||
sed 's/.*= *//' < sha256sum.txt > hash.txt
|
||||
mv `tail -n1 log1.txt` rel.tar.bz2
|
||||
|
||||
- name: sha256sum
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: sha256sum
|
||||
path: |
|
||||
sha256sum.txt
|
||||
hash.txt
|
||||
|
||||
- name: tarball
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: tarball
|
||||
# only keep for debugging
|
||||
retention-days: 3
|
||||
path: rel.tar.bz2
|
||||
29
.gitignore
vendored
Normal file
29
.gitignore
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
*~
|
||||
*.o
|
||||
*.a
|
||||
*.da
|
||||
*.bb
|
||||
*.bbg
|
||||
*.prof
|
||||
.*.swp
|
||||
/autom4te.cache
|
||||
/config.log
|
||||
/config.status
|
||||
/dbclient
|
||||
/dropbear
|
||||
/dropbearconvert
|
||||
/dropbearkey
|
||||
/dropbearmulti
|
||||
/fuzzcorpus
|
||||
/fuzzer-*
|
||||
/fuzzer-*.options
|
||||
/scp
|
||||
/scp-progress
|
||||
config.h
|
||||
default_options_guard.h
|
||||
localoptions.h
|
||||
Makefile
|
||||
tags
|
||||
.pytest*
|
||||
*.pyc
|
||||
/test/venv
|
||||
31
.hgsigs
Normal file
31
.hgsigs
Normal file
@@ -0,0 +1,31 @@
|
||||
aa2f51a6b81d33de5e9898a7f27c792a173d9b26 0 iD8DBQBOuADmjPn4sExkf7wRAv/fAJ9FJFvjDoF+wd1ipDx1wkzdeBQNqgCgykUrSbXv76FBbxKntVbk9oS3GjI=
|
||||
3f12086c2ef2b9ffe36a822fdb3ff647fcec1831 0 iD8DBQBOuSlQjPn4sExkf7wRAvkbAKCgE1e8xEMQ16CGeoywhIQ0QR4eNgCfZdYYlzjb/+521Uvh5/7FRYEmrho=
|
||||
85f835f2fe0ac2c503c50a414de127222fb0a57c 0 iD8DBQBPRkMUjPn4sExkf7wRAvM4AJ9mw2OAkyjhSbamM1MizlEJUX18HACgoFKQkYf6BnYxN34Nv2HhM0cmzUc=
|
||||
9b80981212fe6c01b7c16b3ca7c4e66af56f12f1 0 iEYEABECAAYFAlFLKKcACgkQjPn4sExkf7xK7wCfcioCmJPsysSbQO6+4qZMVe0mmLwAn2/o+wRf4MrUXlohrr7aXEF9vdSB
|
||||
095b46180bbc412b029420587736a6185afc17e1 0 iEYEABECAAYFAlFsCnkACgkQjPn4sExkf7xLrwCfeMWjUaSmfU/fvseT5TdrYRqBEVQAoLz5SFLEA40C5f8zE8Ma/vgVJVIC
|
||||
f168962bab857ca030829e4cd73d9b32c868c874 0 iEYEABECAAYFAlFwDNwACgkQjPn4sExkf7wJ6QCePVovn/avKXUyNwNBYCcov6JLYqkAnRCPQdkXgv20N3t10r6PRMBBo1/S
|
||||
deb211f75ca194e2fcf0d2e5f71c60474e42ec95 0 iEYEABECAAYFAlJO01cACgkQjPn4sExkf7yDqACaA/P+Yl/K2Cv3OC5G0b7ck2Kb75EAoIeW7qpCyclzJLWwk95koED+4lxD
|
||||
025237c9f0a1a60a616f984d82fb2a9270d3b0ea 0 iEYEABECAAYFAlJeqDYACgkQjPn4sExkf7y5nQCfW6t+TJySBTTo+gCfDUBPRVxvNe8AoIn/15aWfqH/A2G9uikfoVtWK3pd
|
||||
a50a1dc743317fad9b3737bc68fbca640659bb6d 0 iEYEABECAAYFAlJeqL0ACgkQjPn4sExkf7yVqACg6IP0fU29+Feh/TDeemDA+2XAzrIAoIdZfMDvVYlDoWotZD8ACFnf5H1P
|
||||
9ec083a21adfcb099f21eb03704b66d14a4ba800 0 iEYEABECAAYFAlKE4JoACgkQjPn4sExkf7wLDgCghkVGwMjI138bEv+ORVzN7zIH7cEAoLckaxZc1k1aXlmlSCRlP8cuKH3o
|
||||
3d1d7d151c0ce3a79da62e86463f5632fa2b144a 0 iEYEABECAAYFAlKd5AEACgkQjPn4sExkf7wzWgCfdvPEEIdlMPqcbOQMJ7b+eAyy164An2ip1lPh1eS5g26/gSfruvWBVym4
|
||||
277429102f1337bd10c89107d3e01de509cc1a7e 0 iEYEABECAAYFAlMEvF4ACgkQjPn4sExkf7xeVQCgtbxJ4G3hsFwUOM0K1WGr1J2vsbEAoMM8dEyr1mdrbgO1tzNLfD1nxbyn
|
||||
96584b934d04ebab443f603e78d38fe692d36313 0 iEYEABECAAYFAlPVFrQACgkQjPn4sExkf7xr6ACglRiLE21vRrS1rJ809o2yMADIKtwAn1f5SyZUngSde8eE55JxCMwtMC5m
|
||||
caac692b366c153cea0e9cd59aa2d79a7d843d4e 0 iEYEABECAAYFAlPk1mcACgkQjPn4sExkf7wLpgCeOqMYqpkf4lYUuyrn9VYThNpc7PkAn3JOSNgIqkKUcmSy6FstrI8jwJzq
|
||||
2d421bc0545d1be6d59a4ebfe61606d94b124b0c 0 iEYEABECAAYFAlRJDCQACgkQjPn4sExkf7xUYACcCwVJkYWXJn5x/D5A+qMupy778lEAn0rg1oNiq96YU/4jOPsS5IMItihu
|
||||
1d2d81b1b7c1b100e9c369e40b9fa5b2d491eea9 0 iEYEABECAAYFAlTKOKUACgkQjPn4sExkf7xWMACfYFozyHiRk5GaocTa5z6Ws1uyB4kAoLubxoxcnM3E7AA9mHAzc3OB5M0Y
|
||||
a687f835236c7025b5cb2968fe9c4ebc4a49f0ea 0 iQIcBAABCgAGBQJVxg62AAoJEPSYMBLCC7qsC+EQAKw8YWogrVHhIFct2fx/nqybSPVrhFyKFKHhq7K/lZeVm0MGIWdSyVcQgP+Hs2jWNBWzG4AJ1BtifHWQH6IDh7W5RuwOXu5KobgPW9BsN3EVE9KIR+xe9jCAmFl9rIw0tNpy1q6R0TpYXx/sWlMilxecyEGyr2Ias2Sm19aY2mOEv8PLfh9BLfrJEKtt2NxL7TX8ScPwJXJMmVIQjN9WK4Ptx3tjcGNRivEVR/dftP5sJx2DBJx9avyDqrfloMW7Q7sPgJ88MPruCDxedOkbzH7JdHe3Humr2G4LsI0KPU7pNN6EBDjhJ+SVXuOyAgu5j/C0R+0ggGfjSrjDu8WjHyclFlwwu2MSGuHf111I1qkLtaRY3H1FZO5Y2gbLwBLQ82svA4klcBIxtP5jKAZDTh1jQMYsfKotvZdawOWrPDkNmKoUg2JXLHAtj9Dd0uGIhqfspZY3qlpzxw9uCkljWclUBD097ygotwAb2XdLoAWZ3KdvoPM+k448vIAQ7Q/aqcnm/dLQJr3Le029gpkOKoWKaQTlk0itrRGpgETHAhE2LnmWxYSKp6NYSKMgEONbfDiVNLyDTOlvpPiEb20RsOP64xA4wVDGmPenCURmMYoepQK6oJdtkNtCdth2S49KxPQAC+Dem4YZ7b+5b+cXrK5Nz7elBxZzRQWdjmZ4JDQK
|
||||
ef4b26364b0cdda1084751d7de3d76c589e2d9cb 0 iQIcBAABCgAGBQJVxg7BAAoJEESTFJTynGdz9Q4P/A0Kq4H52rQqxq42PoEMFbVQIUfkFzyWjAz8eEGLmP5x5/sdpyxZDEyBSUG55uyNvOPTHE+Sd3t2h2Iieq749qwYgqggXC0P+C0zGzW3hB5Rv6dTUrKN1yCyaWE2tY488RsyVlcAs4vrp1Cum5Gv8/BUVKjzZmkZ1iq/3RyrvbLEiLoMrcLnQ+sUdaYHvfEwxDbzpOEvepg8iDJBitTrfG9xHp9otX6ucahwn1EumFvC5mvUxbiQ9jv76t4FJztjMoB24hPCH9T1FjB8uNsoM+j2Z67r81eJrGgNpJzjX0S3lY/AADZGhfGnfybTM9gFuQayIJuCJqduQibVwYkAAnPi17NmbdwPu0Rdz55oU+ft09XLVm/qkQcD1EP5bxYWnLIEMkkZQnFx7WdMpjKK9oGxZHeFYAKEgPgePCkk4TQ4PxNa+3854H19AUssQlaueGcbDLyPIRiSyqhleXawGfaJi+1jBt0DM7CNbAHAUWUE07VhQzNGWjabdEk4eXKTmDL+mZJFdHGBhyCve8sPmZBYJvM2PRgcXe8fwFh+R7gVj6kFbZJvgM9kG7EeF+4ZMEXG4yKpV/SKfMMeEPBCZjFxZhlJJ0fsZbB1Y/iLw8LXnJ0fa/5xFYv6k+iytfom/rqS4iUD7NWTjcEYHjd4EO4QlPD2Ef/AWOO8YBUBv8kA
|
||||
af074dbcb68ff8670b3818e0d66d5dc6f1bd5877 0 iQIcBAABCgAGBQJWVdQfAAoJEPSYMBLCC7qs+n4P/RgZU3GsLFJN7v7Cn6NOdKdfjJBmlbCtK9KwlZZaj8fW4noqnLDcDd6a2xT4mDV3rCE6+QYialGXjNkkNCBwD9Z+gFc8spOtThrpQ54dgWzbgDlYB1y7Hp7DoWoJQIlU6Od9nWBemcSrAviOFNAX8+S6poRdEhrHgMcv2xJoqHjvT7X8gob0RnJcYxW5nLWzDaJV58QnX6QlXg4ClSB6IoCeEawdW6WzXlZ9MGsRycTtx1ool7Uo6Vo2xg48n9TaJqM/lbSsMAjHxO/fdTJMWzTId1fuZxJGFVeJbkhjSwlf7fkVXxrgDxjvIAmFDR8TSTfJo50CD82j5rPcd7KSEpQ12ImBUsntPDgOtt/mJZ3HcFds86OZ7NkPpqoJGVFFQ8yUpe//DNSB2Ovg1FrwhSKOq/9N61BBwk1INVFDp1hMq45PIa9gI9zW/99inGDeSSQlxa4iafEUEjXZTRYuX7mFjnWm5q7r134J7kyWQtN/jNUZ71F0mvhnemufgpNY/I/D7K6qkONpbDZ2nuzkhfoqugzhHYp467UePM0qmLTLdXGPPMukoGorpWeiSb2T25AEKm7N4A9NwPmdAnoFjAibjF9FAuU03sl+pu9MqFb+1ldsqjNfxhcJmoAUR5vy3pED9ailCb/OCBVTHkDPfTEhGU3waO9tPM+5x2rGB5fe
|
||||
5bb5976e6902a0c9fba974a880c68c9487ee1e77 0 iQIcBAABCgAGBQJWVyIKAAoJEESTFJTynGdzQosP/0k5bVTerpUKZLjyNuMU8o0eyc7njkX8EyMOyGbtcArKpzO2opSBTRsuCT9Zsk1iiQ1GMTY1quKD7aNr86Hipqo4th/+ZXmLe9mmaCDukKjD0ZYC4dBVUy6RSUAMvdkDP9sZs7CMTO/22a9SqOsKTv3s2NN6XnsBGnmNbvVx5hkAk5hMVNFrjKIaexzI/7bWQIDRo2HQCaWaL06JvWEDSEQd2mynGSXxT/+m4hBnuGg6qxn2pd4XfG0g10tDAFx64HQkWgZqSB+F8z71Cvfjondy1zjJYgtABqNlwCKQJZhRUW2+PblqQnz08TUy83XN2vtisOju4avGcHSaBgBbMvg8Wx4ZtM7sPP9pLrhhOTd5ceERHeTceTJy+iI1SQFvccjrRfs5aJ0zAQX5q6f4bV0zp5SmxkvnZUEkZIoetkM8VrPOYugqx31LtHAWfVT9NM+VkV/rrxLhk6J0giIQvC9MPWxRDileFVDszPiOgTLcxWjOziOLT+xijcj7dtx1b/f2bNCduN5G7i+icjjTlCNtyRPRqhBqn705W7F+xESP2gsscM/1BjQ7TGidU5m1njdkUjbrqm3+Qic6iqkG7SfETHmQB9mHqpJ0hACRPvZlhwB7oimNHllkrlw8UJw9f0SiuLjfERIgVS2EOp+mAia0RU7MlTt19o017M1ffEYL
|
||||
926e7275cef4f4f2a4251597ee4814748394824c 0 iQIcBAABCgAGBQJWYES4AAoJEESTFJTynGdzdT0P/0O/1frevtr698DwMe6kmJx35P6Bqq8szntMxYucv0HROTfr85JRcCCSvl/2SflDS215QmOxdvYLGLUWPJNz/gURCLpzsT88KLF68Y1tC72nl4Fj+LGIOlsWsvwEqQqw0v4iQkHIfcxI6q7g1r9Hfldf/ju4bzQ4HnKLxm6KNcLLoAsuehVpQ+njHpLmlLAGHU5a84B7xeXHFR+U/EBPxSdm637rNhmpLpkuK2Mym/Mzv7BThKDstpB8lhFHIwAVNqi3Cy4nGYxFZOJpooUN9pDornqAwuzHmOAMs9+49L8GZ1de5PBRGyFKibzjBIUWPEU9EIkfJVaVwTlqYK8Q/IRi9HjITPx6GpE8cZhdSvAibrQdb6BbIDrZ8eCvD9vnod6Uk0Jb9/ui6nCF9x+CN/3Qez4epV5+JCMYsqCiXFkVPm9Lab6L2eGZis7Q2TXImA/sSV+E4BGfH2urpkKlnuXTTtDp4XRG+lOISkIBXgjVY+uy8soVKNdx1gv+LeY8hu/oQ2NyOlaOeL47aSQ3who4Pk6pVRUOl6zfcKo9Vs6xDWm35A3Z6x/mrAENaXasB0JrfY5nIbefJUpbeSmi76fYldU98HdQNHPHCSeiKVYl7v/B6gi2JXp5xngLZz/5VVAurago7sRmpIp7G/AqU6LNE85IUzG8aQz8AfR0d1dW
|
||||
fd1981f41c626a969f07b4823848deaefef3c8aa 0 iQIcBAABCgAGBQJW4W2TAAoJEESTFJTynGdzuOcP/j6tvB2WRwSj39KoJuRcRebFWWv4ZHiQXYMXWa3X0Ppzz52r9W0cXDjjlp5FyGdovCQsK+IXmjPo5cCvWBrZJYA6usFr9ssnUtTC+45lvPxPYwj47ZGPngCXDt7LD+v08XhqCu4LsctXIP/zejd30KVS1eR2RHI+tnEyaIKC0Xaa0igcv74MZX7Q8/U+B730QMX5adfYAHoeyRhoctRWaxVV3To7Vadd9jNXP45MRY5auhRcK7XyQcS85vJeCRoysfDUas4ERRQWYkX+68GyzO9GrkYFle931Akw2K6ZZfUuiC2TrF5xv1eRP1Zm2GX481U4ZGFTI8IzZL8sVQ6tvzq2Mxsecu589JNui9aB2d8Gp2Su/E2zn0h0ShIRmviGzf2HiBt+Bnji5X2h/fJKWbLaWge0MdOU5Jidfyh9k0YT7xo4piJLJYSaZ3nv+j4jTYnTfL7uYvuWbYkJ1T32aQVCan7Eup3BFAgQjzbWYi1XQVg6fvu8uHPpS3tNNA9EAMeeyTyg1l6zI2EIU5gPfd/dKmdyotY2lZBkFZNJqFkKRZuzjWekcw7hAxS+Bd68GKklt/DGrQiVycAgimqwXrfkzzQagawq2fXL2uXB8ghlsyxKLSQPnAtBF2Jcn5FH2z7HOQ+e18ZrFfNy0cYa/4OdH6K5aK1igTzhZZP2Urn0
|
||||
70705edee9dd29cd3d410f19fbd15cc3489313e2 0 iQIcBAABCgAGBQJW7CQRAAoJEESTFJTynGdzTj0QAJL38CKSZthBAeI9c6B+IlwIeT6kPZaPqk1pkycCTWOe87NiNU9abrsF+JrjTuRQiO1EpM2IvfQEIXTijUcMxvld3PnzrZDDv6UvBLtOkn3i++HSVRO0MOuTKI8gFDEPUxRtcaCKXEbqYnf1OTK25FT09Vb//qP9mK1thvlLJmbV+D2a9MkMK66rom1d1h+347IsuwsM+ycHjB80VVAQLA7VYLC5YIwmL17dSmcQLvetfikAMwwmUE+KES4qiLSaqOcAWcKcU67RZzgMMv5o0rESlQmv1nj0mHZtHoUR71sd21emPaRXLOr0oT5YogWUphKq2qVthRn2B06+vd3hPdtn92CmJw9j7zT2jl4OeSjNm9qfAajsRzHIANssFxkGAb7w/LxcMoO29JC+01iUUJMdOVm+4Ns6wGI7qxssWPKdB+VbQUDlHrXLR+sopO524uhkYoWB6DVfTj4R6tImaHtj5/VXON0lsYaLGj8cSH60emL6nNQ0lYV/bSlk6l0s+0x3uXGZnp9oKA+vqMzHfG3vJeMm6KUqtFVjUsYx+q8nHm5/SlWxj1EwnkH8s8ELKZAUXjd76nWEwJ7JFRNRSQWvjOUh3/rsOo4JopzZXPsjCjm+Vql9TG0X6hB21noai32oD5RvfhtR/NX6sXNS5TKZz/j/cMsMnAAsSKb6W7Jm
|
||||
9030ffdbe5625e35ed7189ab84a41dfc8d413e9c 0 iQIcBAABCgAGBQJXkOg0AAoJEESTFJTynGdzc1kP/3vSKCnhOOvjCjnpTQadYcCUq8vTNnfLHYVu0R4ItPa/jT6RmxoaYP+lZnLnnBx9+aX7kzwHsa9BUX3MbMEyLrOzX2I+bDJbNPhQyupyCuPYlf5Q9KVcO9YlpbsC4q5XBzCn3j2+pT8kSfi9uD8fgY3TgE4w9meINrfQAealfjwMLT8S/I49/ni0r+usSfk/dnSShJYDUO7Ja0VWbJea/GkkZTu30bCnMUZPjRApipU3hPP63WFjkSMT1rp2mAXbWqyr9lf8z32yxzM9nMSjq4ViRFzFlkGtE3EVRJ4PwkO7JuiWAMPJpiQcEr+r52cCsmWhiGyHuINo01MwoMO9/n6uL1WVa3mJcE9se3xBOvfgDu2FRFGCAdm1tef+AGVo9EG1uJXi0sX2yUc6DMeuYaRWrXMMlZh7zp9cuNU9Y/lLui9RFmq66yeXG3Z2B72doju3Ig5QGrNNw2AOsSzeHdAtOp6ychqPcl9QfIeJQG18KyPSefZKM3G8YRKBRIwXFEH6iZJe5ZIP4iXrHDMn2JqtTRtDqKR8VNDAgb9z4Ffx8QRxFyj5JzTTMM1GddHb9udLvTQlO0ULYG7hCSMRNzvUBE2aTw8frjLRyfyyg3QpDu/hz8op8s1ecE8rTCD8RuX9DiiylNozypPtGNS+UDbAmkc1PCWaRpPVl+9K6787
|
||||
5c9207ceedaea794f958224c19214d66af6e2d56 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAlkdtooACgkQRJMUlPKcZ3P6ZxAAmLy/buZB/d96DJF/pViRWt/fWdjQFC4MqWfeSLW02OZ8Qkm1vPL3ln6WPHC2thy3xZWVg2uan3pLk/XXnsIFu8Q7r1EAfFFpvlMUmdl7asE8V6ilaeqmiI7bIvGMFbf4cZkQliLjiFkJX56tFHRCNi+rb7WgRuru3/GzPXUq2AvXZvFpFJgik0B72TxVlmCKeBRZq1FvP0UhAH48RJWYJksdEyzh2paMfjX9ZO5Q2SFFrmPw6k2ArdJFC1AYcgceZC84y06RKJ0WiSntUPlEUXgQbQVVWbtQDhjfJXMr/beuroNdT/vsRraLVkAzvhaDXNnHlAJNLQxci+AcLpnzZhxMW+ax7RRtrpXGxRN4cs0lBGUcSkaDybFqMYXwEjXAE8w6fdJRWCIlxctkAW/iNEO4kAG97hI2Qwcw5oU2Ymnv09zyGR+XJE35pJqPulJHExdwanJHvmjH0QF7TNFS82yxS5dKnP954cj3Lu9SWGYWjxQJRmLtOwb+lqqol4VTxG7Ois4uef9/Tpp9skeMZXVeNlpn2wrp6iFcX3uiiVDg9VKkl3ig6UqCiqQSuiIN87RXwUOeHXlCnW3adz3Xei0ziBrwLSql7lBIHGEAlUUNmJ3CrR8IwQtcynGEMKfNIeZ/XK+uNlm9cJIqZf1fzqc8KexlyS9AS0i/kiYZTr4=
|
||||
2f0c3f3361d3ea4eb9129ed8810699fda7e7a8ee 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAlqVb+IACgkQRJMUlPKcZ3OENA//R9HsOUJQB2QZjRgAvqgLn2AMLUvmWb2etTZEc3Nps957Fw1F4kjh6VGfIpWuytfsDx1W8qRx09ikTdb3YteMWCuX8/aFreSPrioYmzrAEcxkZdA7B/jciqU0iXuHiJ9saKk5TR70aNp+iRy0hjAgiYEsVMF9YKHzULOJcHr70x9XVKquubQkwNqJA+/b2JbK2j46wM5nVK/alGSI2kMmEzXmAHQxsvf1OLMvgH8ou/l0xsg/CuFEK299XKfZAbsFEXrjuoWZ1aSa6rTeOWsWli5T+czyyJHI4Eu0Sz/gaR8+MPhJSYes8YjvzEdv32rRMDVOdBq4e+HoTgFt/THYABP6/R1H5fX3Lm4K8u9F9SwJbb/YKRAIrfWDob8ApnGFHk2dyYO20Fskbbg6b1pC7ulDWsufu8lYkQyMlTc3dR6P4eTB6mKO4x+gMG6tIYZ60fiULoEnMJCgegPtevmz+TG1rzdjh3ljiw9Dxz5lNtL+W7sBKKHwhyG0u+bavgmvBMKNL/rdHEM+0yCIz1U6Lb8sVaST1E4zbdm7cWHbSozBij3G0GBSkLFEq7ZLlh8wco9rELRh0Y9fFsWY9j6H/PTOu0GfHrYluFb9WGywHAquQY8j2croRx+MrvTbR1wZrbevPNm9gqk3vgOiDWu7KwxLLqcj+dEQ7tccptVYtbM=
|
||||
07b0d56d186d7eeef4106137a3eba554959ba0e3 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAlyWOo8ACgkQRJMUlPKcZ3O+MQ//c5oeDUvZuFiI4FHZqfIK/59YAciTP+9TQmoWDVSuOdkd9ZYJA7b7DCusqP2TWFEIl9M7i5hTLTMD21xuEQQtfOSP6EXpUw6JNdh/lsJs7EDlFANtwkdEozAQozFKnXbJEV3y9WldEWUlmPFjt4fJQIuG10SU7MTJHcSaQddJCh3I1//F4EvgRe+OqyrFwKekGiFdvfjcIFN3lQmk6K1Sc0MgyIO/VVZm/AQpBi0Dlg0yOl+EDcxxlmeSInbvLceWSP6op35I4dE5YWH1UetjzIsr5AIM15/k3viAKDDefY1EMAzK9b7YAF4BLw0a6XoQu0apvcWaALE/bJzWNSg/QbCm2JAZzk21WLLvR+AELzPfKXrHX3o0h51lpQ4rs7EWKUm43dJPoWkcFNOU+BDsNzffcJgChbRs48ut89DYLiGmSxhRxE77VPbA+klgTGdctOTLd8psseRlGYCuGe8zeota80bV9fUZ9WJZHwNgEWGowKUoTjy6l5k9OH3iQuQX3OXoy78ufRgWDulE7noVTMhXurQ8a0Jf2k/MW9dcnqGVkWitCFKPEvZwVmWyW2AWsdMcBJnFFGzDsNSxWTtCF9XcxieDO1IB8vGwYcb1TwEVuVzvR/wwvc3PgVikF+4Qv2NqdoQc1yn2PkocY2hwXyIZUAwz7erNumlTbeC/JK8=
|
||||
ebcdb893992d286d363e60f5353d6e1401e7084b 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAlybhXAACgkQRJMUlPKcZ3O7pQ//QuNJfBVa7ROaOJOR2H/xr6PRn1Fnc6rr/GCF9cqWrbGP6wNo24dRjcu5LxviqPvzfwRXIMXwVz8L/y61/sm6XcA7VFP4+MBoltfeUOdMbfBdtwEUo3WMBdP1w2q5GgYj8ZY6MawiLEqFba5aua7dokTNBOQM3Yebj+9I16MiWEaRSnuwYPoieHW2Fo6oftcIgs/GCXwT2xYzc0n3FpYAbK7u6sEkpL16EstV0Y/G70+X1/4Mg3GM96S5fl9Zbun47W7/+gT4AQVQjE+UnPNDudObAe+2BaOZLFvEbd7iJBBcqtjpBktuP58IEAb3A3srUCy49LNLWk43lj+PtoslK/U6TShKQ2vAgfd//bbn6ieXFJY8N+wYPpJo1m7zpTiEtS7J7wu6vkGGZlqUAj6MHXZj223CgazhSAlg/XFPs9oz3Y96c33Tnd4jB9iEXNNt5jzCAMImx2huSGgnP0JFAbcniq/ug5tl1VWaracvSuJl7fmf17DbmehsLbvtZBoMlePY7Ssfb5IokfVvptt4zRpRZnjtWfHCjtC6zYhtvXTmXH/bqWwx9MMjOf5WPfZoCMvXfMqdVI15FVbxU15WnqjvdvKUCkdz1aMFzxqc4MXgyvjtB9CvO/8WwBOJ2m2nDdiZfh8/H8SawYqEHgB61FX5xA5aXecgXcjQnqWDDxw=
|
||||
4877afd51e041eca7749cc46b57fd80aa23815b4 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAl7nmREACgkQRJMUlPKcZ3PG1BAAnUl0/nTnQ3CMM3S72DT1JQ1eDxZa14r6r1xEPngU83hNNzmPcnfiMDts+Vz1M3PLxNNOXVVt/MTw04+V9joPhhSWEe8O1pd3lAqTPswL7hhIEbVwZwyFCuAV4iAm+tHKzKLjtjgZfMgij6XylOmw18VBw5R+suoOMclJqeHlJ5m0Mq2wRLDE+RdVCAkulTqhGYjJNQUXMMNPx/cxUo3NHsto9pWL3d1285vBByP6BQSaeYlO012InvJRlQuEkK3lnIyzq6voIc6+tMli0q9iyBz+2GIloBQNAnb6EGaXxqAOBW5NRc+/Oauiu8Yf/6JoFlkAIcPXmGRtxiAiynJImhiTaCFdgdxaXLFzjBvq+tcwVXvvNM52fOZ4Z3QgMDu6EgNWfma0lsg4T3ar2ml2/evuWeLVut5ZmYFHarTFX+/pTVy9nAZK/F5ROJM1prTNYI18PZV4qvULta8spGV2Be0rCkQQubp9RWdKHNGZE70lrX5OnNIwE/D3g2QE04243i0IGBwhlDEpYjqujLyHk8W6XE1CORx0hQ0fUjzKZsRvOB7XyMAFpQUVOhoMFcnk5XHDW6B/U7NAxzqNqO+gbHO/UIeuy/KOVlMNJCmtRL/HYNGZ6SCZbRpyX3d8Ow0sasNfJkZrT6a0Tf6lZktWOxtPkoEDLfuCzudzn4JxGQM=
|
||||
88f63b8b0f131f24aa90c9b852622b922b1ad738 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAl71/sAACgkQRJMUlPKcZ3OlSQ/9GYLotOmsYK0gvSfWLYR9a8WGgT/4EU6RgAkMBLS9TBp0E3V4VUDralnqoId7hNO2cUkRS7boOM2g4/YRShah8gonSJa70lKjUpDeQUPuGwUYWLNKr9qxJtnAcd1rOE4WYxKEUfjPWHBbVsT3QIIdj1Zy31GDKZgELRBQeOyt62RdXYHMaMHHDgg2U/wO9bcRRe5G7mYJf7Vm8sAWyTZXvta2jORxgs4XxWe7xJ9Dj0lMSG5HmfvH5NrGHM1GK3pL0GREKj2+xNSFdkSeHIgSSoHM2qZTVSWtNfx0+fZaRBgvXPPYzDTTghj1mKEaPFoRzg/B8s+NmHupJftT1yyapKFjALo1N6eaPHRRSwVfmnoWSJLu4fwL8TK5wMJr9eGl3QgAnperQPEFT9UHJBIwZ1D+RMuI3pEESdHBJFAYIAyisJI6XyzMhLsysoShlHs6OjFcJ9jTe4pzg9pO+KaPbLYsBJxJUsrtHwV8P9CHxY6CEuKm0AZjYDopYhzLuAUjGJjYDf/C9vJ/xtTOqIm9nywfcFwqgLrmQFhNHHGyOJVr+y/cey1sT9E4/gBv9kor+6qSITALv2g0JTaOpzpkE0zbafUy2r777Wex4WNQEha6bYZFi2aiqxqqX93UHzv+YhmN8n9mlc21xoZMPNtAb2mSxx7rO+PScb5uflKOCYE=
|
||||
5879c5829e8569466386e7c64252b01b99705628 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAl+axlIACgkQRJMUlPKcZ3PZuhAAkzCj+lOt2hHigIHB0zkNUC9nRIE1TItJD4wqQ03nMY4ycBMsb74o1AHsQTtVG6sm2YGSmQuZ0VxG1iuW9nKTsM1hzB40G45i5waIEzxVG8PbZ2i6zLK2Xz2YQ+FBvIg1EKfH7Dyd3r4FqYxauGOQdrUiKwuc3H4r65HpUmT0tIypqahFoRmj1+K/ZSPak0+ZPL27VQ4b/Ts8QS7XwFYTZsMDovYNdFJmaMhBbBe33/zGFWBPk6NCJWrBd3jmJN/LhZp0a5T4fAZ6iA2WjXDWOSiWZaLLk49zM6WYrc4QihEj7ngecj/UUXKR/sWPva8+rHf9YQLZu2lc6IMABCpUkeKLFoJqzvnKGA2rhl1LpRcnNA30/7yJt0YhfFcKhBkjjSxiOH3v0qMPADHMo5poqCKH/x4TVGVyVgzCqcxd+AzsDu77fzfzbxlyQ7wp+VmwXmeHbPfuBc8u9HUBa6Fc4b667aDD26a2S9VKdRYuSp3DkOwCLJUmRqmw+sXKvXlPyxPMUxOi/4R5nbJacD5Js1AH7WH49pAFMJ6bDCQ8QEmOh+Qpqc3RzTBwt1CLl+zt0NLKDmRYSgAY9GZpuju7r+aj2Semjd7nwmq4Y5xtWCh673lea/n7JS0mtBWouVbGgMJErg7QjuqOS3oE77viLcGLpX9niDcGvCL/N3gE13A=
|
||||
63
.hgtags
Normal file
63
.hgtags
Normal file
@@ -0,0 +1,63 @@
|
||||
03f65e461915a940939e4cc689fc89721ffc40de DROPBEAR_0.48.1
|
||||
0f967bfef5cd0056b7ec60e2305d917e51cbf30d DROPBEAR_0.44
|
||||
170329dc8ce5dfcf6298e1ad6699f109bf78e73d DROPBEAR_0.51
|
||||
1dbd2473482f320ea59f76ce961385cb3a0150a9 DROPBEAR_0.46
|
||||
2098857ab826dd42ae05a9a22c3ce2cc835b9844 DROPBEAR_0.45
|
||||
36160290a1b27451178be36752ed038840f59cdd LTC_DB_0.46
|
||||
39d5d58461d6e93337636e69d4cdf184a09c8d24 LTC_1.05
|
||||
55a99934db873be2e63b5968fb6532e5d9bd02e4 DROPBEAR_0.48
|
||||
59400faa4b44708c5d0b595e81193bc621e752d3 libtomcrypt-1.05
|
||||
66087d87c3555c78b47cf01f32bb5a32054c3ceb DROPBEAR_0.44test4
|
||||
677843bfa734238a67636b461a02c110c462ffaf DROPBEAR_0.44test1
|
||||
7faae8f46238e23975430876547b8950b4e75481 t:ltc-0.95-orig
|
||||
8220862baae829ebc762587b99c662480d57bb23 DROPBEAR_0.53
|
||||
86e0b50a9b588239c3fc9cc9cfe255ef586df17b ltm-0.30-orig
|
||||
88e0a1ad951add46b795511dc2698e36b4aee922 DROPBEAR_0.44test3
|
||||
8e94663164c6e106ccc5c9e997dedf6e04d77dd2 LTM_DB_0.44
|
||||
91fbc376f01084037cd5f6a5bf2e2db4903e8e99 libtommath-0.35
|
||||
97db060d0ef5f8cf8e67eb602ef037055a185ca9 libtommath-0.40
|
||||
aa2f51a6b81d33de5e9898a7f27c792a173d9b26 DROPBEAR_0.53.1
|
||||
ab370c629d363f8c9a3eca512bfa86e362034654 DROPBEAR_0.49
|
||||
c2ac796b130eeb6fa840873d8c230544c8ec7e4b DROPBEAR_0.44test2
|
||||
cd1143579f00b0248c79f63ca70efee4a35a57e8 LTC_DB_0.44
|
||||
ce104c8b0be1ff3f2c2590b7cdc3fd6870c865cd DROPBEAR_0.52
|
||||
d5faf4814ddbc5abd9e209409bb9e7a4686c8cd7 libtomcrypt-1.16
|
||||
d7da3b1e15401eb234ec866d5eac992fc4cd5878 t:ltc-0.95-db-merge1
|
||||
d8254fc979e99560c93ca2cece77a6df31927ea5 LTM_0.35
|
||||
e109027b9edfb02f0bdf96ec45bb1cd9ad41e7da LTM_DB_0.46
|
||||
e109027b9edfb02f0bdf96ec45bb1cd9ad41e7da LTM_DB_0.47
|
||||
e37b160c414cab6466622f63b0c4dcbf6ebc47a9 DROPBEAR_0.47
|
||||
e430a26064ee86ab79aef372118d6d03b2441996 DROPBEAR_0.50
|
||||
e5d119ea4c63656bc54ecfd865d04591ac2ed225 LTC_DB_0.47
|
||||
3f12086c2ef2b9ffe36a822fdb3ff647fcec1831 DROPBEAR_2011.54
|
||||
d354464b2aa6f6ba0bf44d43bcae5aa798435393 DROPBEAR_2012.55
|
||||
7faae8f46238e23975430876547b8950b4e75481 t:ltc-0.95-orig
|
||||
0000000000000000000000000000000000000000 t:ltc-0.95-orig
|
||||
d7da3b1e15401eb234ec866d5eac992fc4cd5878 t:ltc-0.95-db-merge1
|
||||
0000000000000000000000000000000000000000 t:ltc-0.95-db-merge1
|
||||
1b8b2b9d6e94bc3cc5e61b620476ea36cc466e1b DROPBEAR_2013.56
|
||||
96b8bcb88017815040949a417caa55686271e8a9 DROPBEAR_2013.57
|
||||
e76614145aea67f66e4a4257685c771efba21aa1 DROPBEAR_2013.58
|
||||
7b68e581985fd4ea50869f8608ab95cda5d17876 DROPBEAR_2013.59
|
||||
a50a1dc743317fad9b3737bc68fbca640659bb6d DROPBEAR_2013.60
|
||||
e894dbc015ba7ff4c3bf897ee20e28ca90c55a16 DROPBEAR_2013.61test
|
||||
3d1d7d151c0ce3a79da62e86463f5632fa2b144a DROPBEAR_2013.62
|
||||
2351b2da8e0d08dcc6e64fcc328b53b9630bda68 DROPBEAR_2014.63
|
||||
0d2d39957c029adb7f4327d37fe6b4900f0736d9 DROPBEAR_2014.64
|
||||
e9579816f20ea85affc6135e87f8477992808948 DROPBEAR_2014.65
|
||||
735511a4c761141416ad0e6728989d2dafa55bc2 DROPBEAR_2014.66
|
||||
cbd674d63cd4f3781464a8d4056a5506c8ae926f DROPBEAR_2015.67
|
||||
809feaa9408f036734129c77f2b3c7e779d4f099 DROPBEAR_2015.68
|
||||
1637dbd262124d113e52967df46afd6c715e4fad DROPBEAR_2015.69
|
||||
79a6ef02307d05cb9dda10465cb5b807baa8f62e DROPBEAR_2015.70
|
||||
9a944a243f08be6b22d32f166a0690eb4872462b DROPBEAR_2015.71
|
||||
78b12b6549be08b0bea3da329b2578060a76ca31 DROPBEAR_2016.72
|
||||
309e1c4a87682b6ca7d80b8555a1db416c3cb7ac DROPBEAR_2016.73
|
||||
0ed3d2bbf956cb8a9bf0f4b5a86b7dd9688205cb DROPBEAR_2016.74
|
||||
c31276613181c5cff7854e7ef586ace03424e55e DROPBEAR_2017.75
|
||||
1c66ca4f3791c82501c88e7637312182c7294978 DROPBEAR_2018.76
|
||||
6d1bbe7d5fa5827c7eae28bca044d691f7efa785 DROPBEAR_2019.77
|
||||
009d52ae26d35f3381c801e02318fa9be34be93c DROPBEAR_2019.78
|
||||
e2e4929d057b09422f2ea4556fb64209aff58161 DROPBEAR_2020.79
|
||||
73646de50f1351735c868d4874f058ff9ad62c96 DROPBEAR_2020.80
|
||||
4b984c42372d01fcc2fd487c58af6a5aa65eb88e DROPBEAR_2020.81
|
||||
75
DEVELOPING.md
Normal file
75
DEVELOPING.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Developer Notes
|
||||
|
||||
## Building
|
||||
|
||||
See [INSTALL](INSTALL) for build instructions.
|
||||
[SMALL](SMALL) has hints for building smaller binaries, also see comments
|
||||
in default_options.h.
|
||||
|
||||
## Debug printing
|
||||
|
||||
Set `#define DEBUG_TRACE 1` in localoptions.h to enable a `-v` option
|
||||
for dropbear and dbclient. That prints various details of the session. For
|
||||
development running `dropbear -F -E` is useful to run in the foreground. You
|
||||
can set `#define DEBUG_NOFORK 1` to make dropbear a one-shot server, easy to
|
||||
run under a debugger.
|
||||
|
||||
## Random sources
|
||||
|
||||
Most cryptography requires a good random entropy source, both to generate secret
|
||||
keys and in the course of a session. Dropbear uses the Linux kernel's
|
||||
`getrandom()` syscall to ensure that the system RNG has been initialised before
|
||||
using it. On some systems there is insufficient entropy gathered during early
|
||||
boot - generating hostkeys then will block for some amount of time.
|
||||
Dropbear has a `-R` option to generate hostkeys upon the first connection
|
||||
as required - that will allow the system more time to gather entropy.
|
||||
|
||||
## Algorithms
|
||||
|
||||
Default algorithm lists are specified in [common-algo.c](common-algo.c).
|
||||
They are in priority order, the client's first matching choice is used
|
||||
(see rfc4253).
|
||||
Dropbear client has `-c` and `-m` arguments to choose which are enabled at
|
||||
runtime (doesn't work for server as of June 2020).
|
||||
|
||||
Enabling/disabling algorithms is done in [localoptions.h](localoptions.h),
|
||||
see [default_options.h](default_options.h).
|
||||
|
||||
## Style
|
||||
|
||||
Source code is indented with tabs, width set to 4 (though width shouldn't
|
||||
matter much). Braces are on the same line as functions/loops/if - try
|
||||
to keep consistency with existing code.
|
||||
|
||||
All `if` statements should have braces, no exceptions.
|
||||
|
||||
Avoid using pointer arithmetic, instead the functions in
|
||||
[buffer.h](buffer.h) should be used.
|
||||
|
||||
Some Dropbear platforms have old compilers.
|
||||
Variable declarations must be at the top of a scope and
|
||||
comments must be `/* */` rather than `//`.
|
||||
|
||||
Pointer variables should be initialised to NULL - it can reduce the
|
||||
severity of bugs.
|
||||
|
||||
## Third party code
|
||||
|
||||
Libtomcrypt and libtommath are periodically synced from upstream, so
|
||||
avoid making changes to that code which will need to be maintained.
|
||||
Improvements can be sent upstream to the libtom project.
|
||||
|
||||
## Non-root user
|
||||
|
||||
Dropbear server will run fine as a non-root user, allowing logins only for
|
||||
that user. Password authentication probably won't work (can't read shadow
|
||||
passwords). You will need to create hostkeys that are readable.
|
||||
|
||||
## Connection setup
|
||||
|
||||
Dropbear implements first_kex_packet_follows to reduce
|
||||
handshake latency (rfc 4253 7.1). Some less common implementations don't
|
||||
handle that, it can be a cause of problems connecting. Note also that
|
||||
Dropbear may send several ssh packets within a single TCP packet - it's just a
|
||||
stream.
|
||||
|
||||
15
Dockerfile
Normal file
15
Dockerfile
Normal file
@@ -0,0 +1,15 @@
|
||||
FROM ubuntu:22.04
|
||||
|
||||
ENV LC_ALL=C.UTF-8
|
||||
|
||||
RUN apt-get update
|
||||
|
||||
RUN apt-get install -y build-essential git autoconf
|
||||
|
||||
RUN mkdir -p /root/dropbear/
|
||||
WORKDIR /root/dropbear/
|
||||
|
||||
# ./configure --disable-zlib --disable-syslog --enable-static --disable-harden
|
||||
# make PROGRAMS="dropbear dropbearconvert"
|
||||
|
||||
ENTRYPOINT ["bash"]
|
||||
77
FUZZER-NOTES.md
Normal file
77
FUZZER-NOTES.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# Fuzzing Dropbear
|
||||
|
||||
Dropbear is process-per-session so it assumes calling `dropbear_exit()`
|
||||
is fine at any point to clean up. This makes fuzzing a bit trickier.
|
||||
A few pieces of wrapping infrastructure are used to work around this.
|
||||
|
||||
The [libfuzzer](http://llvm.org/docs/LibFuzzer.html#fuzz-target) harness
|
||||
expects a long running process to continually run a test function with
|
||||
a string of crafted input. That process should not leak resources or exit.
|
||||
|
||||
## longjmp
|
||||
|
||||
When dropbear runs in fuzz mode it sets up a
|
||||
[`setjmp()`](http://man7.org/linux/man-pages/man3/setjmp.3.html) target prior
|
||||
to launching the code to be fuzzed, and then [`dropbear_exit()`](dbutil.c#L125)
|
||||
calls `longjmp()` back there. This avoids exiting though it doesn't free
|
||||
memory or other resources.
|
||||
|
||||
## malloc Wrapper
|
||||
|
||||
Dropbear normally uses a [`m_malloc()`](dbmalloc.c) function that is the same as `malloc()` but
|
||||
exits if allocation fails. In fuzzing mode this is replaced with a tracking allocator
|
||||
that stores all allocations in a linked list. After the `longjmp()` occurs the fuzzer target
|
||||
calls [`m_malloc_free_epoch(1, 1)`](dbmalloc.c) to clean up any unreleased memory.
|
||||
|
||||
If the fuzz target runs to completion it calls `m_malloc_free_epoch(1, 0)` which will reset
|
||||
the tracked allocations but will not free memory - that allows libfuzzer's leak checking
|
||||
to detect leaks in normal operation.
|
||||
|
||||
## File Descriptor Input
|
||||
|
||||
As a network process Dropbear reads and writes from a socket. The wrappers for
|
||||
`read()`/`write()`/`select()` in [fuzz-wrapfd.c](fuzz-wrapfd.c) will read from the
|
||||
fuzzer input that has been set up with `wrapfd_add()`. `write()` output is
|
||||
currently discarded.
|
||||
These also test error paths such as EINTR and short reads with certain probabilities.
|
||||
|
||||
This allows running the entire dropbear server process with network input provided by the
|
||||
fuzzer, without many modifications to the main code. At the time of writing this
|
||||
only runs the pre-authentication stages, though post-authentication could be run similarly.
|
||||
|
||||
## Encryption and Randomness
|
||||
|
||||
When running in fuzzing mode Dropbear uses a [fixed seed](dbrandom.c#L185)
|
||||
every time so that failures can be reproduced.
|
||||
|
||||
Since the fuzzer cannot generate valid encrypted input the packet decryption and
|
||||
message authentication calls are disabled, see [packet.c](packet.c).
|
||||
MAC failures are set to occur with a low probability to test that error path.
|
||||
|
||||
## Fuzzers
|
||||
|
||||
Current fuzzers are
|
||||
|
||||
- [fuzzer-preauth](fuzzer-preauth.c) - the fuzzer input is treated as a stream of session input. This will
|
||||
test key exchange, packet ordering, authentication attempts etc.
|
||||
|
||||
- [fuzzer-preauth_nomaths](fuzzer-preauth_nomaths.c) - the same as fuzzer-preauth but with asymmetric crypto
|
||||
routines replaced with dummies for faster runtime. corpora are shared
|
||||
between fuzzers by [oss-fuzz](https://github.com/google/oss-fuzz) so this
|
||||
will help fuzzer-preauth too.
|
||||
|
||||
- [fuzzer-verify](fuzzer-verify.c) - read a key and signature from fuzzer input and verify that signature.
|
||||
It would not be expected to pass, though some keys with bad parameters are
|
||||
able to validate with a trivial signature - extra checks are added for that.
|
||||
|
||||
- [fuzzer-pubkey](fuzzer-pubkey.c) - test parsing of an `authorized_keys` line.
|
||||
|
||||
- [fuzzer-kexdh](fuzzer-kexdh.c) - test Diffie-Hellman key exchange where the fuzz input is the
|
||||
ephemeral public key that would be received over the network. This is testing `mp_expt_mod()`
|
||||
and and other libtommath routines.
|
||||
|
||||
- [fuzzer-kexecdh](fuzzer-kexecdh.c) - test Elliptic Curve Diffie-Hellman key exchange like fuzzer-kexdh.
|
||||
This is testing libtommath ECC routines.
|
||||
|
||||
- [fuzzer-kexcurve25519](fuzzer-kexcurve25519.c) - test Curve25519 Elliptic Curve Diffie-Hellman key exchange
|
||||
like fuzzer-kexecdh. This is testing `dropbear_curve25519_scalarmult()` and other libtommath routines.
|
||||
43
INSTALL
43
INSTALL
@@ -1,30 +1,49 @@
|
||||
Basic Dropbear build instructions:
|
||||
|
||||
- Edit options.h to set which features you want.
|
||||
- Edit debug.h if you want any debug options (not usually required).
|
||||
- Edit localoptions.h to set which features you want. Available options
|
||||
are described in default_options.h, these will be overridden by
|
||||
anything set in localoptions.h
|
||||
localoptions.h should be located in the build directory if you are
|
||||
building out of tree.
|
||||
|
||||
(If using a non-tarball copy, "autoconf; autoheader")
|
||||
|
||||
./configure (optionally with --disable-zlib or --disable-syslog,
|
||||
- Configure for your system:
|
||||
./configure (optionally with --disable-zlib or --disable-syslog,
|
||||
or --help for other options)
|
||||
|
||||
Now compile:
|
||||
(you'll need to first run "autoconf; autoheader" if you edit configure.ac)
|
||||
|
||||
make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp"
|
||||
- Compile:
|
||||
|
||||
And install (/usr/local/bin is usual default):
|
||||
make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp"
|
||||
|
||||
make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp" install
|
||||
- Optionally install, or copy the binaries another way
|
||||
|
||||
make install (/usr/local/bin is usual default):
|
||||
|
||||
or
|
||||
|
||||
make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp" install
|
||||
|
||||
(you can leave items out of the PROGRAMS list to avoid compiling them. If you
|
||||
recompile after changing the PROGRAMS list, you *MUST* "make clean" before
|
||||
recompiling - bad things will happen otherwise)
|
||||
|
||||
DEVELOPING.md has some notes on other developer topics, including debugging.
|
||||
|
||||
See MULTI for instructions on making all-in-one binaries.
|
||||
|
||||
If you want to compile statically, add "STATIC=1" to the make command-line.
|
||||
If you want to compile statically use ./configure --enable-static
|
||||
|
||||
Binaries can be strippd with "make strip"
|
||||
By default Dropbear adds various build flags that improve robustness
|
||||
against programming bugs (good for security). If these cause problems
|
||||
they can be disabled with ./configure --disable-harden
|
||||
|
||||
Binaries can be stripped with "make strip"
|
||||
|
||||
============================================================================
|
||||
|
||||
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.
|
||||
|
||||
============================================================================
|
||||
|
||||
@@ -39,7 +58,7 @@ Compiling for uClibc should be the same as normal, just set CC to the magic
|
||||
uClibc toolchain compiler (ie export CC=i386-uclibc-gcc or whatever).
|
||||
You can use "make STATIC=1" to make statically linked binaries, and it is
|
||||
advisable to strip the binaries too. If you're looking to make a small binary,
|
||||
you should remove unneeded ciphers and MD5, by editing options.h
|
||||
you should remove unneeded ciphers and algorithms, by editing localoptions.h
|
||||
|
||||
It is possible to compile zlib in, by copying zlib.h and zconf.h into a
|
||||
subdirectory (ie zlibincludes), and
|
||||
|
||||
29
LICENSE
29
LICENSE
@@ -8,7 +8,7 @@ The majority of code is written by Matt Johnston, under the license below.
|
||||
Portions of the client-mode work are (c) 2004 Mihnea Stoenescu, under the
|
||||
same license:
|
||||
|
||||
Copyright (c) 2002-2004 Matt Johnston
|
||||
Copyright (c) 2002-2020 Matt Johnston
|
||||
Portions copyright (c) 2004 Mihnea Stoenescu
|
||||
All rights reserved.
|
||||
|
||||
@@ -32,7 +32,8 @@ SOFTWARE.
|
||||
|
||||
=====
|
||||
|
||||
LibTomCrypt and LibTomMath are written by Tom St Denis, and are Public Domain.
|
||||
LibTomCrypt and LibTomMath are written by Tom St Denis and others, see
|
||||
libtomcrypt/LICENSE and libtommath/LICENSE.
|
||||
|
||||
=====
|
||||
|
||||
@@ -87,3 +88,27 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
|
||||
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
=====
|
||||
|
||||
curve25519.c:
|
||||
|
||||
Modified TweetNaCl version 20140427, a self-contained public-domain C library.
|
||||
https://tweetnacl.cr.yp.to/
|
||||
|
||||
Contributors (alphabetical order)
|
||||
Daniel J. Bernstein, University of Illinois at Chicago and Technische
|
||||
Universiteit Eindhoven
|
||||
Bernard van Gastel, Radboud Universiteit Nijmegen
|
||||
Wesley Janssen, Radboud Universiteit Nijmegen
|
||||
Tanja Lange, Technische Universiteit Eindhoven
|
||||
Peter Schwabe, Radboud Universiteit Nijmegen
|
||||
Sjaak Smetsers, Radboud Universiteit Nijmegen
|
||||
|
||||
Acknowledgments
|
||||
This work was supported by the U.S. National Science Foundation under grant
|
||||
1018836. "Any opinions, findings, and conclusions or recommendations expressed
|
||||
in this material are those of the author(s) and do not necessarily reflect the
|
||||
views of the National Science Foundation."
|
||||
This work was supported by the Netherlands Organisation for Scientific
|
||||
Research (NWO) under grant 639.073.005 and Veni 2013 project 13114.
|
||||
|
||||
4
MULTI
4
MULTI
@@ -20,7 +20,3 @@ etc
|
||||
then execute as normal:
|
||||
|
||||
./dropbear <options here>
|
||||
|
||||
"make install" doesn't currently work for multi-binary configuration, though
|
||||
in most situations where it is being used, the target and build systems will
|
||||
differ.
|
||||
|
||||
287
Makefile.in
287
Makefile.in
@@ -2,93 +2,133 @@
|
||||
# @configure_input@
|
||||
|
||||
# invocation:
|
||||
# make PROGRAMS="dropbear dbclient scp" MULTI=1 STATIC=1 SCPPROGRESS=1
|
||||
# make PROGRAMS="dropbear dbclient scp" MULTI=1 SCPPROGRESS=1
|
||||
#
|
||||
# to make a multiple-program statically linked binary "staticdropbearmulti".
|
||||
# to make a multiple-program binary "dropbearmulti".
|
||||
# This example will include dropbear, scp, dropbearkey, dropbearconvert, and
|
||||
# dbclient functionality, and includes the progress-bar functionality in scp.
|
||||
# Hopefully that seems intuitive.
|
||||
|
||||
ifndef PROGRAMS
|
||||
PROGRAMS=dropbear dbclient dropbearkey dropbearconvert
|
||||
endif
|
||||
|
||||
LTC=libtomcrypt/libtomcrypt.a
|
||||
LTM=libtommath/libtommath.a
|
||||
STATIC_LTC=libtomcrypt/libtomcrypt.a
|
||||
STATIC_LTM=libtommath/libtommath.a
|
||||
|
||||
COMMONOBJS=dbutil.o buffer.o \
|
||||
LIBTOM_LIBS=@LIBTOM_LIBS@
|
||||
|
||||
ifeq (@BUNDLED_LIBTOM@, 1)
|
||||
LIBTOM_DEPS=$(STATIC_LTC) $(STATIC_LTM)
|
||||
LIBTOM_CLEAN=ltc-clean ltm-clean
|
||||
CPPFLAGS+=-I$(srcdir)/libtomcrypt/src/headers/
|
||||
LIBTOM_LIBS=$(STATIC_LTC) $(STATIC_LTM)
|
||||
endif
|
||||
|
||||
OPTION_HEADERS = default_options_guard.h sysoptions.h
|
||||
ifneq ($(wildcard localoptions.h),)
|
||||
CPPFLAGS+=-DLOCALOPTIONS_H_EXISTS
|
||||
OPTION_HEADERS += localoptions.h
|
||||
endif
|
||||
|
||||
COMMONOBJS=dbutil.o buffer.o dbhelpers.o \
|
||||
dss.o bignum.o \
|
||||
signkey.o rsa.o random.o \
|
||||
signkey.o rsa.o dbrandom.o \
|
||||
queue.o \
|
||||
atomicio.o compat.o fake-rfc2553.o
|
||||
atomicio.o compat.o fake-rfc2553.o \
|
||||
ltc_prng.o ecc.o ecdsa.o sk-ecdsa.o crypto_desc.o \
|
||||
curve25519.o ed25519.o sk-ed25519.o \
|
||||
dbmalloc.o \
|
||||
gensignkey.o gendss.o genrsa.o gened25519.o
|
||||
|
||||
SVROBJS=svr-kex.o svr-algo.o svr-auth.o sshpty.o \
|
||||
svr-authpasswd.o svr-authpubkey.o svr-session.o svr-service.o \
|
||||
SVROBJS=svr-kex.o svr-auth.o sshpty.o \
|
||||
svr-authpasswd.o svr-authpubkey.o svr-authpubkeyoptions.o svr-session.o svr-service.o \
|
||||
svr-chansession.o svr-runopts.o svr-agentfwd.o svr-main.o svr-x11fwd.o\
|
||||
svr-tcpfwd.o svr-authpam.o
|
||||
|
||||
CLIOBJS=cli-algo.o cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \
|
||||
cli-session.o cli-service.o cli-runopts.o cli-chansession.o \
|
||||
cli-authpubkey.o cli-tcpfwd.o cli-channel.o
|
||||
CLIOBJS=cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \
|
||||
cli-session.o cli-runopts.o cli-chansession.o \
|
||||
cli-authpubkey.o cli-tcpfwd.o cli-channel.o cli-authinteract.o \
|
||||
cli-agentfwd.o
|
||||
|
||||
CLISVROBJS=common-session.o packet.o common-algo.o common-kex.o \
|
||||
common-channel.o common-chansession.o termcodes.o loginrec.o \
|
||||
tcp-accept.o listener.o process-packet.o \
|
||||
common-runopts.o circbuffer.o
|
||||
tcp-accept.o listener.o process-packet.o dh_groups.o \
|
||||
common-runopts.o circbuffer.o list.o netio.o chachapoly.o gcm.o
|
||||
|
||||
KEYOBJS=dropbearkey.o gendss.o genrsa.o
|
||||
KEYOBJS=dropbearkey.o
|
||||
|
||||
CONVERTOBJS=dropbearconvert.o keyimport.o
|
||||
CONVERTOBJS=dropbearconvert.o keyimport.o signkey_ossh.o
|
||||
|
||||
SCPOBJS=scp.o progressmeter.o atomicio.o scpmisc.o
|
||||
SCPOBJS=scp.o progressmeter.o atomicio.o scpmisc.o compat.o
|
||||
|
||||
HEADERS=options.h dbutil.h session.h packet.h algo.h ssh.h buffer.h kex.h \
|
||||
dss.h bignum.h signkey.h rsa.h random.h service.h auth.h \
|
||||
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
|
||||
ifeq (@DROPBEAR_FUZZ@, 1)
|
||||
allobjs = $(COMMONOBJS) fuzz/fuzz-common.o fuzz/fuzz-wrapfd.o $(CLISVROBJS) $(CLIOBJS) $(SVROBJS) @CRYPTLIB@
|
||||
allobjs:=$(subst svr-main.o, ,$(allobjs))
|
||||
allobjs:=$(subst cli-main.o, ,$(allobjs))
|
||||
|
||||
dropbearobjs=$(COMMONOBJS) $(CLISVROBJS) $(SVROBJS)
|
||||
dbclientobjs=$(COMMONOBJS) $(CLISVROBJS) $(CLIOBJS)
|
||||
dropbearkeyobjs=$(COMMONOBJS) $(KEYOBJS)
|
||||
dropbearconvertobjs=$(COMMONOBJS) $(CONVERTOBJS)
|
||||
scpobjs=$(SCPOBJS)
|
||||
dropbearobjs=$(allobjs) svr-main.o
|
||||
dbclientobjs=$(allobjs) cli-main.o
|
||||
dropbearkeyobjs=$(allobjs) $(KEYOBJS)
|
||||
dropbearconvertobjs=$(allobjs) $(CONVERTOBJS)
|
||||
# CXX only set when fuzzing
|
||||
CXX=@CXX@
|
||||
FUZZ_CLEAN=fuzz-clean
|
||||
else
|
||||
dropbearobjs=$(COMMONOBJS) $(CLISVROBJS) $(SVROBJS)
|
||||
dbclientobjs=$(COMMONOBJS) $(CLISVROBJS) $(CLIOBJS)
|
||||
dropbearkeyobjs=$(COMMONOBJS) $(KEYOBJS)
|
||||
dropbearconvertobjs=$(COMMONOBJS) $(CONVERTOBJS)
|
||||
scpobjs=$(SCPOBJS)
|
||||
endif
|
||||
|
||||
ifeq (@DROPBEAR_PLUGIN@, 1)
|
||||
# rdynamic makes all the global symbols of dropbear available to all the loaded shared libraries
|
||||
# this allow a plugin to reuse existing crypto/utilities like base64_decode/base64_encode without
|
||||
# the need to rewrite them.
|
||||
PLUGIN_LIBS=-ldl -rdynamic
|
||||
else
|
||||
PLUGIN_LIBS=
|
||||
endif
|
||||
|
||||
VPATH=@srcdir@
|
||||
srcdir=@srcdir@
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=${prefix}
|
||||
bindir=${exec_prefix}/bin
|
||||
sbindir=${exec_prefix}/sbin
|
||||
exec_prefix=@exec_prefix@
|
||||
datarootdir = @datarootdir@
|
||||
bindir=@bindir@
|
||||
sbindir=@sbindir@
|
||||
mandir=@mandir@
|
||||
|
||||
.DELETE_ON_ERROR:
|
||||
|
||||
CC=@CC@
|
||||
LD=@LD@
|
||||
AR=@AR@
|
||||
RANLIB=@RANLIB@
|
||||
STRIP=@STRIP@
|
||||
INSTALL=@INSTALL@
|
||||
CFLAGS=-I. -I$(srcdir)/libtomcrypt @CFLAGS@
|
||||
LIBS=$(LTC) $(LTM) @LIBS@
|
||||
CPPFLAGS+=@CPPFLAGS@ -I. -I$(srcdir)
|
||||
CFLAGS+=@CFLAGS@
|
||||
LIBS+=@LIBS@
|
||||
LDFLAGS=@LDFLAGS@
|
||||
|
||||
EXEEXT=@EXEEXT@
|
||||
|
||||
STATIC=@STATIC@
|
||||
|
||||
# whether we're building client, server, or both for the common objects.
|
||||
# evilness so we detect 'dropbear' by itself as a word
|
||||
space:= $(empty) $(empty)
|
||||
ifneq (,$(strip $(foreach prog, $(PROGRAMS), $(findstring ZdropbearZ, Z$(prog)Z))))
|
||||
CFLAGS+= -DDROPBEAR_SERVER
|
||||
CPPFLAGS+= -DDROPBEAR_SERVER
|
||||
endif
|
||||
ifneq (,$(strip $(foreach prog, $(PROGRAMS), $(findstring ZdbclientZ, Z$(prog)Z))))
|
||||
CFLAGS+= -DDROPBEAR_CLIENT
|
||||
CPPFLAGS+= -DDROPBEAR_CLIENT
|
||||
endif
|
||||
|
||||
|
||||
# these are exported so that libtomcrypt's makefile will use them
|
||||
export CC
|
||||
export CFLAGS
|
||||
export CPPFLAGS
|
||||
export RANLIB AR STRIP
|
||||
|
||||
ifeq ($(STATIC), 1)
|
||||
@@ -96,56 +136,62 @@ ifeq ($(STATIC), 1)
|
||||
endif
|
||||
|
||||
ifeq ($(MULTI), 1)
|
||||
TARGETS=dropbearmulti
|
||||
TARGETS=dropbearmulti$(EXEEXT)
|
||||
else
|
||||
TARGETS=$(PROGRAMS)
|
||||
endif
|
||||
|
||||
# for the scp progress meter. The -D doesn't affect anything else.
|
||||
ifeq ($(SCPPROGRESS), 1)
|
||||
CFLAGS+=-DPROGRESS_METER
|
||||
CPPFLAGS+=-DPROGRESS_METER
|
||||
endif
|
||||
|
||||
#%: $(HEADERS)
|
||||
#%: $(HEADERS) Makefile
|
||||
# TODO
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
# for simplicity assume all source depends on all headers
|
||||
HEADERS=$(wildcard $(srcdir)/*.h *.h) $(OPTION_HEADERS)
|
||||
%.o : %.c $(HEADERS)
|
||||
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
|
||||
|
||||
default_options_guard.h: default_options.h
|
||||
@echo Creating $@
|
||||
@printf "/*\n > > > Do not edit this file (default_options_guard.h) < < <\nGenerated from "$^"\nLocal customisation goes in localoptions.h\n*/\n\n" > $@.tmp
|
||||
@$(srcdir)/ifndef_wrapper.sh < $^ >> $@.tmp
|
||||
@mv $@.tmp $@
|
||||
|
||||
strip: $(TARGETS)
|
||||
$(STRIP) $(addsuffix $(EXEEXT), $(TARGETS))
|
||||
|
||||
install: $(addprefix inst_, $(TARGETS))
|
||||
|
||||
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
|
||||
insmultidropbear: dropbearmulti$(EXEEXT)
|
||||
$(INSTALL) -d $(DESTDIR)$(sbindir)
|
||||
-rm -f $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
|
||||
-ln -s $(DESTDIR)$(bindir)/dropbearmulti$(EXEEXT) $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
|
||||
-ln -s $(bindir)/dropbearmulti$(EXEEXT) $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
|
||||
$(INSTALL) -d $(DESTDIR)$(mandir)/man8
|
||||
$(INSTALL) -m 644 $(srcdir)/dropbear.8 $(DESTDIR)$(mandir)/man8/dropbear.8
|
||||
|
||||
insmulti%: dropbearmulti
|
||||
insmulti%: dropbearmulti$(EXEEXT)
|
||||
$(INSTALL) -d $(DESTDIR)$(bindir)
|
||||
-rm -f $(DESTDIR)$(bindir)/$*$(EXEEXT)
|
||||
-ln -s $(DESTDIR)$(bindir)/dropbearmulti$(EXEEXT) $(DESTDIR)$(bindir)/$*$(EXEEXT)
|
||||
-ln -s $(bindir)/dropbearmulti$(EXEEXT) $(DESTDIR)$(bindir)/$*$(EXEEXT)
|
||||
$(INSTALL) -d $(DESTDIR)$(mandir)/man1
|
||||
if test -e $(srcdir)/$*.1; then $(INSTALL) -m 644 $(srcdir)/$*.1 $(DESTDIR)$(mandir)/man1/$*.1; fi
|
||||
|
||||
# dropbear should go in sbin, so it needs a seperate rule
|
||||
# dropbear should go in sbin, so it needs a separate rule
|
||||
inst_dropbear: dropbear
|
||||
$(INSTALL) -d -m 755 $(DESTDIR)$(sbindir)
|
||||
$(INSTALL) -m 755 dropbear$(EXEEXT) $(DESTDIR)$(sbindir)
|
||||
-chown root $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
|
||||
-chgrp 0 $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
|
||||
$(INSTALL) -d $(DESTDIR)$(sbindir)
|
||||
$(INSTALL) dropbear$(EXEEXT) $(DESTDIR)$(sbindir)
|
||||
$(INSTALL) -d $(DESTDIR)$(mandir)/man8
|
||||
$(INSTALL) -m 644 $(srcdir)/dropbear.8 $(DESTDIR)$(mandir)/man8/dropbear.8
|
||||
|
||||
inst_%: $*
|
||||
$(INSTALL) -d -m 755 $(DESTDIR)$(bindir)
|
||||
$(INSTALL) -m 755 $*$(EXEEXT) $(DESTDIR)$(bindir)
|
||||
-chown root $(DESTDIR)$(bindir)/$*$(EXEEXT)
|
||||
-chgrp 0 $(DESTDIR)$(bindir)/$*$(EXEEXT)
|
||||
inst_%: %
|
||||
$(INSTALL) -d $(DESTDIR)$(bindir)
|
||||
$(INSTALL) $*$(EXEEXT) $(DESTDIR)$(bindir)
|
||||
$(INSTALL) -d $(DESTDIR)$(mandir)/man1
|
||||
if test -e $(srcdir)/$*.1; then $(INSTALL) -m 644 $(srcdir)/$*.1 $(DESTDIR)$(mandir)/man1/$*.1; fi
|
||||
|
||||
inst_dropbearmulti: $(addprefix insmulti, $(PROGRAMS))
|
||||
|
||||
# for some reason the rule further down doesn't like $($@objs) as a prereq.
|
||||
dropbear: $(dropbearobjs)
|
||||
@@ -153,26 +199,31 @@ dbclient: $(dbclientobjs)
|
||||
dropbearkey: $(dropbearkeyobjs)
|
||||
dropbearconvert: $(dropbearconvertobjs)
|
||||
|
||||
dropbear dbclient dropbearkey dropbearconvert: $(HEADERS) $(LTC) $(LTM) \
|
||||
Makefile
|
||||
$(LD) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBS)
|
||||
dropbear: $(HEADERS) $(LIBTOM_DEPS) Makefile
|
||||
$(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBTOM_LIBS) $(LIBS) @CRYPTLIB@ $(PLUGIN_LIBS)
|
||||
|
||||
dbclient: $(HEADERS) $(LIBTOM_DEPS) Makefile
|
||||
$(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBTOM_LIBS) $(LIBS)
|
||||
|
||||
dropbearkey dropbearconvert: $(HEADERS) $(LIBTOM_DEPS) Makefile
|
||||
$(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBTOM_LIBS) $(LIBS)
|
||||
|
||||
# scp doesn't use the libs so is special.
|
||||
scp: $(SCPOBJS) $(HEADERS) Makefile
|
||||
$(LD) $(LDFLAGS) -o $@$(EXEEXT) $(SCPOBJS)
|
||||
$(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
|
||||
CPPFLAGS+=$(addprefix -DDBMULTI_, $(PROGRAMS)) -DDROPBEAR_MULTI
|
||||
endif
|
||||
|
||||
dropbearmulti: multilink
|
||||
dropbearmulti$(EXEEXT): $(HEADERS) $(MULTIOBJS) $(LIBTOM_DEPS) Makefile
|
||||
$(CC) $(LDFLAGS) -o $@ $(MULTIOBJS) $(LIBTOM_LIBS) $(LIBS) @CRYPTLIB@
|
||||
|
||||
multibinary: $(HEADERS) $(MULTIOBJS) $(LTC) $(LTM) Makefile
|
||||
$(LD) $(LDFLAGS) -o dropbearmulti$(EXEEXT) $(MULTIOBJS) $(LIBS)
|
||||
multibinary: dropbearmulti$(EXEEXT)
|
||||
|
||||
multilink: multibinary $(addprefix link, $(PROGRAMS))
|
||||
|
||||
@@ -180,30 +231,98 @@ link%:
|
||||
-rm -f $*$(EXEEXT)
|
||||
-ln -s dropbearmulti$(EXEEXT) $*$(EXEEXT)
|
||||
|
||||
$(LTC): options.h
|
||||
cd libtomcrypt && $(MAKE) clean && $(MAKE)
|
||||
$(STATIC_LTC): $(OPTION_HEADERS)
|
||||
$(MAKE) -C libtomcrypt
|
||||
|
||||
$(LTM): options.h
|
||||
cd libtommath && $(MAKE)
|
||||
$(STATIC_LTM): $(OPTION_HEADERS)
|
||||
$(MAKE) -C libtommath
|
||||
|
||||
.PHONY : clean sizes thisclean distclean tidy ltc-clean ltm-clean lint check
|
||||
|
||||
ltc-clean:
|
||||
cd libtomcrypt && $(MAKE) clean
|
||||
$(MAKE) -C libtomcrypt clean
|
||||
|
||||
ltm-clean:
|
||||
cd libtommath && $(MAKE) clean
|
||||
$(MAKE) -C libtommath clean
|
||||
|
||||
sizes: dropbear
|
||||
objdump -t dropbear|grep ".text"|cut -d "." -f 2|sort -rn
|
||||
|
||||
clean: ltc-clean ltm-clean thisclean
|
||||
clean: $(LIBTOM_CLEAN) $(FUZZ_CLEAN) thisclean
|
||||
|
||||
thisclean:
|
||||
-rm -f dropbear dbclient dropbearkey dropbearconvert scp scp-progress \
|
||||
dropbearmulti *.o *.da *.bb *.bbg *.prof
|
||||
-rm -f dropbear$(EXEEXT) dbclient$(EXEEXT) dropbearkey$(EXEEXT) \
|
||||
dropbearconvert$(EXEEXT) scp$(EXEEXT) scp-progress$(EXEEXT) \
|
||||
dropbearmulti$(EXEEXT) *.o *.da *.bb *.bbg *.prof
|
||||
|
||||
distclean: clean tidy
|
||||
-rm -f config.h
|
||||
-rm -f Makefile
|
||||
-rm -f default_options_guard.h
|
||||
|
||||
tidy:
|
||||
-rm -f *~ *.gcov */*~
|
||||
|
||||
lint:
|
||||
cd $(srcdir); ./dropbear_lint.sh
|
||||
|
||||
check: lint
|
||||
make -C test
|
||||
|
||||
## Fuzzing targets
|
||||
|
||||
# list of fuzz targets
|
||||
FUZZ_TARGETS=fuzzer-preauth fuzzer-pubkey fuzzer-verify fuzzer-preauth_nomaths \
|
||||
fuzzer-kexdh fuzzer-kexecdh fuzzer-kexcurve25519 fuzzer-client fuzzer-client_nomaths \
|
||||
fuzzer-postauth_nomaths
|
||||
|
||||
FUZZER_OPTIONS = $(addsuffix .options, $(FUZZ_TARGETS))
|
||||
FUZZ_OBJS = $(addprefix fuzz/,$(addsuffix .o,$(FUZZ_TARGETS))) \
|
||||
fuzz/fuzz-sshpacketmutator.o
|
||||
|
||||
list-fuzz-targets:
|
||||
@echo $(FUZZ_TARGETS)
|
||||
|
||||
# fuzzers that don't use libfuzzer, just a standalone harness that feeds inputs
|
||||
fuzzstandalone: FUZZLIB=fuzz/fuzz-harness.o
|
||||
fuzzstandalone: fuzz/fuzz-harness.o fuzz-targets
|
||||
|
||||
# Build all the fuzzers. Usually like
|
||||
# make fuzz-targets FUZZLIB=-lFuzzer.a
|
||||
# the library provides main(). Otherwise
|
||||
# make fuzzstandalone
|
||||
# provides a main in fuzz-harness.c
|
||||
fuzz-targets: $(FUZZ_TARGETS) $(FUZZER_OPTIONS)
|
||||
|
||||
$(FUZZ_TARGETS): $(FUZZ_OBJS) $(allobjs) $(LIBTOM_DEPS)
|
||||
$(CXX) $(CXXFLAGS) fuzz/$@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
|
||||
|
||||
# fuzzers that use the custom mutator - these expect a SSH network stream
|
||||
MUTATOR_FUZZERS=fuzzer-client fuzzer-client_nomaths \
|
||||
fuzzer-preauth fuzzer-preauth_nomaths fuzzer-postauth_nomaths
|
||||
|
||||
# Skip custom mutators for -fsanitize-memory since libfuzzer doesn't initialise memory
|
||||
# Pending fix for it https://github.com/google/oss-fuzz/issues/4605
|
||||
ifeq (,$(findstring fsanitize=memory, $(CFLAGS)))
|
||||
$(MUTATOR_FUZZERS): allobjs += fuzz/fuzz-sshpacketmutator.o
|
||||
endif
|
||||
|
||||
fuzzer-%.options: Makefile
|
||||
echo "[libfuzzer]" > $@
|
||||
echo "max_len = 50000" >> $@
|
||||
|
||||
# run this to update hardcoded hostkeys for for fuzzing.
|
||||
# hostkeys.c is checked in to hg.
|
||||
fuzz-hostkeys:
|
||||
dropbearkey -t rsa -f keyr
|
||||
dropbearkey -t dss -f keyd
|
||||
dropbearkey -t ecdsa -size 256 -f keye
|
||||
dropbearkey -t ed25519 -f keyed25519
|
||||
echo > hostkeys.c
|
||||
/usr/bin/xxd -i -a keyr >> hostkeys.c
|
||||
/usr/bin/xxd -i -a keye >> hostkeys.c
|
||||
/usr/bin/xxd -i -a keyd >> hostkeys.c
|
||||
/usr/bin/xxd -i -a keyed25519 >> hostkeys.c
|
||||
|
||||
fuzz-clean:
|
||||
-rm -f fuzz/*.o $(FUZZ_TARGETS) $(FUZZER_OPTIONS)
|
||||
|
||||
23
README
23
README
@@ -1,4 +1,5 @@
|
||||
This is Dropbear, a smallish SSH 2 server and client.
|
||||
This is Dropbear, a smallish SSH server and client.
|
||||
https://matt.ucc.asn.au/dropbear/dropbear.html
|
||||
|
||||
INSTALL has compilation instructions.
|
||||
|
||||
@@ -7,8 +8,10 @@ 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 :)
|
||||
A mirror of the Dropbear website and tarballs is available at https://dropbear.nl/mirror/
|
||||
|
||||
Please contact me if you have any questions/bugs found/features/ideas/comments etc :)
|
||||
There is also a mailing list http://lists.ucc.gu.uwa.edu.au/mailman/listinfo/dropbear
|
||||
|
||||
Matt Johnston
|
||||
matt@ucc.asn.au
|
||||
@@ -25,10 +28,9 @@ 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.
|
||||
user. Beware of editors that split the key into multiple lines.
|
||||
|
||||
NOTE: Dropbear ignores authorized_keys options such as those described in the
|
||||
OpenSSH sshd manpage, and will not allow a login for these keys.
|
||||
Dropbear supports some options for authorized_keys entries, see the manpage.
|
||||
|
||||
============================================================================
|
||||
|
||||
@@ -42,8 +44,7 @@ If you have an OpenSSH-style private key ~/.ssh/id_rsa, you need to do:
|
||||
dropbearconvert openssh dropbear ~/.ssh/id_rsa ~/.ssh/id_rsa.db
|
||||
dbclient -i ~/.ssh/id_rsa.db <hostname>
|
||||
|
||||
Currently encrypted keys aren't supported, neither is agent forwarding. At some
|
||||
stage both hopefully will be.
|
||||
Dropbear does not support encrypted hostkeys though can connect to ssh-agent.
|
||||
|
||||
============================================================================
|
||||
|
||||
@@ -55,10 +56,16 @@ 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
|
||||
./dropbearkey -t ecdsa -f dropbear_ecdsa_host_key
|
||||
./dropbearkey -t ed25519 -f dropbear_ed25519_host_key
|
||||
|
||||
or alternatively convert OpenSSH keys to Dropbear:
|
||||
./dropbearconvert openssh dropbear /etc/ssh/ssh_host_dsa_key dropbear_dss_host_key
|
||||
|
||||
You can also get Dropbear to create keys when the first connection is made -
|
||||
this is preferable to generating keys when the system boots. Make sure
|
||||
/etc/dropbear/ exists and then pass '-R' to the dropbear server.
|
||||
|
||||
============================================================================
|
||||
|
||||
If the server is run as non-root, you most likely won't be able to allocate a
|
||||
|
||||
11
SMALL
11
SMALL
@@ -9,10 +9,7 @@ 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
|
||||
The following are set in localoptions.h:
|
||||
|
||||
- If you're compiling statically, you can turn off host lookups
|
||||
|
||||
@@ -50,4 +47,10 @@ deciding.
|
||||
|
||||
Of course using small C libraries such as uClibc and dietlibc can also help.
|
||||
|
||||
---
|
||||
|
||||
Libtommath has its own default CFLAGS to improve speed. You can use
|
||||
./configure LTM_CFLAGS=-Os
|
||||
to reduce size at the expense of speed.
|
||||
|
||||
If you have any queries, mail me and I'll see if I can help.
|
||||
|
||||
30
TODO
30
TODO
@@ -1,30 +0,0 @@
|
||||
Current:
|
||||
|
||||
Things which might need doing:
|
||||
|
||||
- Make options.h generated from configure perhaps?
|
||||
|
||||
- Improved queueing of unauthed connections
|
||||
|
||||
- fix agent fwd problems
|
||||
|
||||
- handle /etc/environment in AIX
|
||||
|
||||
- check that there aren't timing issues with valid/invalid user authentication
|
||||
feedback.
|
||||
|
||||
- Binding to different interfaces
|
||||
|
||||
- possible RSA blinding? need to check whether this is vuln to timing attacks
|
||||
- check PRNG
|
||||
- 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 ?
|
||||
41
agentfwd.h
41
agentfwd.h
@@ -21,23 +21,46 @@
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
#ifndef _AGENTFWD_H_
|
||||
#define _AGENTFWD_H_
|
||||
#ifndef DISABLE_AGENTFWD
|
||||
#ifndef DROPBEAR_AGENTFWD_H_
|
||||
#define DROPBEAR_AGENTFWD_H_
|
||||
|
||||
#include "includes.h"
|
||||
#include "chansession.h"
|
||||
#include "channel.h"
|
||||
#include "auth.h"
|
||||
#include "list.h"
|
||||
|
||||
int agentreq(struct ChanSess * chansess);
|
||||
void agentsetauth(struct ChanSess *chansess);
|
||||
void agentcleanup(struct ChanSess * chansess);
|
||||
void agentset(struct ChanSess *chansess);
|
||||
#if DROPBEAR_CLI_AGENTFWD
|
||||
|
||||
/* From OpenSSH authfd.h */
|
||||
#define SSH_AGENT_RSA_SHA2_256 0x02
|
||||
|
||||
/* An agent reply can be reasonably large, as it can
|
||||
* contain a list of all public keys held by the agent.
|
||||
* 10000 is arbitrary */
|
||||
#define MAX_AGENT_REPLY 10000
|
||||
|
||||
/* client functions */
|
||||
void cli_load_agent_keys(m_list * ret_list);
|
||||
void agent_buf_sign(buffer *sigblob, sign_key *key,
|
||||
const buffer *data_buf, enum signature_type type);
|
||||
void cli_setup_agent(const struct Channel *channel);
|
||||
|
||||
#ifdef __hpux
|
||||
#define seteuid(a) setresuid(-1, (a), -1)
|
||||
#define setegid(a) setresgid(-1, (a), -1)
|
||||
#endif
|
||||
|
||||
#endif /* DROPBEAR_AGENTFWD */
|
||||
#endif /* _AGENTFWD_H_ */
|
||||
extern const struct ChanType cli_chan_agent;
|
||||
|
||||
#endif /* DROPBEAR_CLI_AGENTFWD */
|
||||
|
||||
#if DROPBEAR_SVR_AGENTFWD
|
||||
|
||||
int svr_agentreq(struct ChanSess * chansess);
|
||||
void svr_agentcleanup(struct ChanSess * chansess);
|
||||
void svr_agentset(const struct ChanSess *chansess);
|
||||
|
||||
#endif /* DROPBEAR_SVR_AGENTFWD */
|
||||
|
||||
#endif /* DROPBEAR_AGENTFWD_H_ */
|
||||
|
||||
117
algo.h
117
algo.h
@@ -22,53 +22,126 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#ifndef _ALGO_H_
|
||||
#ifndef DROPBEAR_ALGO_H_
|
||||
|
||||
#define _ALGO_H_
|
||||
#define DROPBEAR_ALGO_H_
|
||||
|
||||
#include "includes.h"
|
||||
#include "buffer.h"
|
||||
|
||||
#define DROPBEAR_MODE_UNUSED 0
|
||||
#define DROPBEAR_MODE_CBC 1
|
||||
#define DROPBEAR_MODE_CTR 2
|
||||
|
||||
struct Algo_Type {
|
||||
|
||||
unsigned char *name; /* identifying name */
|
||||
const char *name; /* identifying name */
|
||||
char val; /* a value for this cipher, or -1 for invalid */
|
||||
void *data; /* algorithm specific data */
|
||||
unsigned usable : 1; /* whether we can use this algorithm */
|
||||
|
||||
const void *data; /* algorithm specific data */
|
||||
char usable; /* whether we can use this algorithm */
|
||||
const void *mode; /* the mode, currently only used for ciphers,
|
||||
points to a 'struct dropbear_cipher_mode' */
|
||||
};
|
||||
|
||||
typedef struct Algo_Type algo_type;
|
||||
|
||||
/* lists mapping ssh types of algorithms to internal values */
|
||||
extern algo_type sshkex[];
|
||||
extern algo_type sshhostkey[];
|
||||
extern algo_type sigalgs[];
|
||||
extern algo_type sshciphers[];
|
||||
extern algo_type sshhashes[];
|
||||
extern algo_type sshcompress[];
|
||||
extern algo_type ssh_compress[];
|
||||
extern algo_type ssh_delaycompress[];
|
||||
extern algo_type ssh_nocompress[];
|
||||
|
||||
extern const struct dropbear_cipher dropbear_nocipher;
|
||||
extern const struct dropbear_cipher_mode dropbear_mode_none;
|
||||
extern const struct dropbear_hash dropbear_nohash;
|
||||
|
||||
struct dropbear_cipher {
|
||||
const struct _cipher_descriptor *cipherdesc;
|
||||
unsigned long keysize;
|
||||
unsigned char blocksize;
|
||||
const struct ltc_cipher_descriptor *cipherdesc;
|
||||
const unsigned long keysize;
|
||||
const unsigned char blocksize;
|
||||
};
|
||||
|
||||
struct dropbear_cipher_mode {
|
||||
int (*start)(int cipher, const unsigned char *IV,
|
||||
const unsigned char *key,
|
||||
int keylen, int num_rounds, void *cipher_state);
|
||||
int (*encrypt)(const unsigned char *pt, unsigned char *ct,
|
||||
unsigned long len, void *cipher_state);
|
||||
int (*decrypt)(const unsigned char *ct, unsigned char *pt,
|
||||
unsigned long len, void *cipher_state);
|
||||
int (*aead_crypt)(unsigned int seq,
|
||||
const unsigned char *in, unsigned char *out,
|
||||
unsigned long len, unsigned long taglen,
|
||||
void *cipher_state, int direction);
|
||||
int (*aead_getlength)(unsigned int seq,
|
||||
const unsigned char *in, unsigned int *outlen,
|
||||
unsigned long len, void *cipher_state);
|
||||
const struct dropbear_hash *aead_mac;
|
||||
};
|
||||
|
||||
struct dropbear_hash {
|
||||
const struct _hash_descriptor *hashdesc;
|
||||
unsigned long keysize;
|
||||
unsigned char hashsize;
|
||||
const struct ltc_hash_descriptor *hash_desc;
|
||||
const unsigned long keysize;
|
||||
/* hashsize may be truncated from the size returned by hash_desc,
|
||||
eg sha1-96 */
|
||||
const unsigned char hashsize;
|
||||
};
|
||||
|
||||
void crypto_init();
|
||||
int have_algo(char* algo, size_t algolen, algo_type algos[]);
|
||||
void buf_put_algolist(buffer * buf, algo_type localalgos[]);
|
||||
enum dropbear_kex_mode {
|
||||
#if DROPBEAR_NORMAL_DH
|
||||
DROPBEAR_KEX_NORMAL_DH,
|
||||
#endif
|
||||
#if DROPBEAR_ECDH
|
||||
DROPBEAR_KEX_ECDH,
|
||||
#endif
|
||||
#if DROPBEAR_CURVE25519
|
||||
DROPBEAR_KEX_CURVE25519,
|
||||
#endif
|
||||
};
|
||||
|
||||
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);
|
||||
struct dropbear_kex {
|
||||
enum dropbear_kex_mode mode;
|
||||
|
||||
/* "normal" DH KEX */
|
||||
const unsigned char *dh_p_bytes;
|
||||
const int dh_p_len;
|
||||
|
||||
#endif /* _ALGO_H_ */
|
||||
/* elliptic curve DH KEX */
|
||||
#if DROPBEAR_ECDH
|
||||
const struct dropbear_ecc_curve *ecc_curve;
|
||||
#else
|
||||
const void* dummy;
|
||||
#endif
|
||||
|
||||
/* both */
|
||||
const struct ltc_hash_descriptor *hash_desc;
|
||||
};
|
||||
|
||||
/* Includes all algorithms is useall is set */
|
||||
void buf_put_algolist_all(buffer * buf, const algo_type localalgos[], int useall);
|
||||
/* Includes "usable" algorithms */
|
||||
void buf_put_algolist(buffer * buf, const algo_type localalgos[]);
|
||||
|
||||
#define KEXGUESS2_ALGO_NAME "kexguess2@matt.ucc.asn.au"
|
||||
|
||||
int buf_has_algo(buffer *buf, const char *algo);
|
||||
algo_type * first_usable_algo(algo_type algos[]);
|
||||
algo_type * buf_match_algo(buffer* buf, algo_type localalgos[],
|
||||
int kexguess2, int *goodguess);
|
||||
|
||||
#if DROPBEAR_USER_ALGO_LIST
|
||||
int check_user_algos(const char* user_algo_list, algo_type * algos,
|
||||
const char *algo_desc);
|
||||
char * algolist_string(const algo_type algos[]);
|
||||
#endif
|
||||
|
||||
enum {
|
||||
DROPBEAR_COMP_NONE,
|
||||
DROPBEAR_COMP_ZLIB,
|
||||
DROPBEAR_COMP_ZLIB_DELAY,
|
||||
};
|
||||
|
||||
#endif /* DROPBEAR_ALGO_H_ */
|
||||
|
||||
28
atomicio.c
28
atomicio.c
@@ -1,6 +1,8 @@
|
||||
/* $OpenBSD: atomicio.c,v 1.17 2006/04/01 05:51:34 djm Exp $ */
|
||||
/*
|
||||
* Copied from OpenSSH 3.6.1p2.
|
||||
* Copied from OpenSSH/OpenBSD.
|
||||
*
|
||||
* Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
|
||||
* Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -25,38 +27,32 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* RCSID("OpenBSD: atomicio.c,v 1.10 2001/05/08 22:48:07 markus Exp "); */
|
||||
#include "includes.h"
|
||||
|
||||
#include "atomicio.h"
|
||||
|
||||
/*
|
||||
* ensure all of data on socket comes through. f==read || f==write
|
||||
* ensure all of data on socket comes through. f==read || f==vwrite
|
||||
*/
|
||||
ssize_t
|
||||
atomicio(f, fd, _s, n)
|
||||
ssize_t (*f) ();
|
||||
int fd;
|
||||
void *_s;
|
||||
size_t n;
|
||||
size_t
|
||||
atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
|
||||
{
|
||||
char *s = _s;
|
||||
ssize_t res;
|
||||
size_t pos = 0;
|
||||
ssize_t res;
|
||||
|
||||
while (n > pos) {
|
||||
res = (f) (fd, s + pos, n - pos);
|
||||
switch (res) {
|
||||
case -1:
|
||||
#ifdef EWOULDBLOCK
|
||||
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
#else
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
#endif
|
||||
continue;
|
||||
return 0;
|
||||
case 0:
|
||||
return (res);
|
||||
errno = EPIPE;
|
||||
return pos;
|
||||
default:
|
||||
pos += res;
|
||||
pos += (size_t)res;
|
||||
}
|
||||
}
|
||||
return (pos);
|
||||
|
||||
13
atomicio.h
13
atomicio.h
@@ -1,8 +1,7 @@
|
||||
/* $OpenBSD: atomicio.h,v 1.7 2006/03/25 22:22:42 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copied from OpenSSH 3.6.1p2, required for loginrec.c
|
||||
*
|
||||
* $OpenBSD: atomicio.h,v 1.4 2001/06/26 06:32:46 itojun Exp $
|
||||
* Copied from OpenSSH/OpenBSD, required for loginrec.c
|
||||
*
|
||||
* Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
|
||||
* All rights reserved.
|
||||
@@ -28,9 +27,9 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
/*
|
||||
* Ensure all of data on socket comes through. f==read || f==write
|
||||
* Ensure all of data on socket comes through. f==read || f==vwrite
|
||||
*/
|
||||
ssize_t atomicio(ssize_t (*)(), int, void *, size_t);
|
||||
size_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
|
||||
|
||||
#define vwrite (ssize_t (*)(int, void *, size_t))write
|
||||
|
||||
146
auth.h
146
auth.h
@@ -22,78 +22,142 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#ifndef _AUTH_H_
|
||||
#define _AUTH_H_
|
||||
#ifndef DROPBEAR_AUTH_H_
|
||||
#define DROPBEAR_AUTH_H_
|
||||
|
||||
#include "includes.h"
|
||||
#include "signkey.h"
|
||||
#include "chansession.h"
|
||||
#include "list.h"
|
||||
|
||||
void svr_authinitialise();
|
||||
void cli_authinitialise();
|
||||
void svr_authinitialise(void);
|
||||
|
||||
/* Server functions */
|
||||
void recv_msg_userauth_request();
|
||||
void recv_msg_userauth_request(void);
|
||||
void send_msg_userauth_failure(int partial, int incrfail);
|
||||
void send_msg_userauth_success();
|
||||
void svr_auth_password();
|
||||
void svr_auth_pubkey();
|
||||
void svr_auth_pam();
|
||||
void send_msg_userauth_success(void);
|
||||
void send_msg_userauth_banner(const buffer *msg);
|
||||
void svr_auth_password(int valid_user);
|
||||
void svr_auth_pubkey(int valid_user);
|
||||
void svr_auth_pam(int valid_user);
|
||||
|
||||
#if DROPBEAR_SVR_PUBKEY_OPTIONS_BUILT
|
||||
int svr_pubkey_allows_agentfwd(void);
|
||||
int svr_pubkey_allows_tcpfwd(void);
|
||||
int svr_pubkey_allows_x11fwd(void);
|
||||
int svr_pubkey_allows_pty(void);
|
||||
int svr_pubkey_allows_local_tcpfwd(const char *host, unsigned int port);
|
||||
void svr_pubkey_set_forced_command(struct ChanSess *chansess);
|
||||
void svr_pubkey_options_cleanup(void);
|
||||
int svr_add_pubkey_options(buffer *options_buf, int line_num, const char* filename);
|
||||
#else
|
||||
/* no option : success */
|
||||
#define svr_pubkey_allows_agentfwd() 1
|
||||
#define svr_pubkey_allows_tcpfwd() 1
|
||||
#define svr_pubkey_allows_x11fwd() 1
|
||||
#define svr_pubkey_allows_pty() 1
|
||||
static inline int svr_pubkey_allows_local_tcpfwd(const char *host, unsigned int port)
|
||||
{ (void)host; (void)port; return 1; }
|
||||
|
||||
static inline void svr_pubkey_set_forced_command(struct ChanSess *chansess) { }
|
||||
static inline void svr_pubkey_options_cleanup(void) { }
|
||||
#define svr_add_pubkey_options(x,y,z) DROPBEAR_SUCCESS
|
||||
#endif
|
||||
|
||||
/* Client functions */
|
||||
void recv_msg_userauth_failure();
|
||||
void recv_msg_userauth_success();
|
||||
void recv_msg_userauth_pk_ok();
|
||||
void cli_get_user();
|
||||
void cli_auth_getmethods();
|
||||
void cli_auth_try();
|
||||
void recv_msg_userauth_banner();
|
||||
void cli_pubkeyfail();
|
||||
int cli_auth_password();
|
||||
int cli_auth_pubkey();
|
||||
void recv_msg_userauth_failure(void);
|
||||
void recv_msg_userauth_success(void);
|
||||
void recv_msg_userauth_specific_60(void);
|
||||
void recv_msg_userauth_pk_ok(void);
|
||||
void recv_msg_userauth_info_request(void);
|
||||
void cli_get_user(void);
|
||||
void cli_auth_getmethods(void);
|
||||
int cli_auth_try(void);
|
||||
void recv_msg_userauth_banner(void);
|
||||
void cli_pubkeyfail(void);
|
||||
void cli_auth_password(void);
|
||||
int cli_auth_pubkey(void);
|
||||
void cli_auth_interactive(void);
|
||||
char* getpass_or_cancel(const char* prompt);
|
||||
void cli_auth_pubkey_cleanup(void);
|
||||
|
||||
|
||||
#define MAX_USERNAME_LEN 25 /* arbitrary for the moment */
|
||||
#define MAX_USERNAME_LEN 100 /* arbitrary for the moment */
|
||||
|
||||
#define AUTH_TYPE_PUBKEY 1 << 0
|
||||
#define AUTH_TYPE_PASSWORD 1 << 1
|
||||
#define AUTH_TYPE_NONE 1
|
||||
#define AUTH_TYPE_PUBKEY (1 << 1)
|
||||
#define AUTH_TYPE_PASSWORD (1 << 2)
|
||||
#define AUTH_TYPE_INTERACT (1 << 3)
|
||||
|
||||
/* auth types, "none" means we should return list of acceptable types */
|
||||
#define AUTH_METHOD_NONE "none"
|
||||
#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
|
||||
|
||||
#define PUBKEY_OPTIONS_ANY_PORT UINT_MAX
|
||||
|
||||
|
||||
/* 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]
|
||||
unsigned int authdone; /* 0 if we haven't authed, 1 if we have. Applies for
|
||||
client and server (though has differing
|
||||
meanings). */
|
||||
|
||||
unsigned int perm_warn; /* Server only, set if bad permissions on
|
||||
~/.ssh/authorized_keys have already been
|
||||
logged. */
|
||||
unsigned int checkusername_failed; /* Server only, set if checkusername
|
||||
has already failed */
|
||||
struct timespec auth_starttime; /* Server only, time of receiving current
|
||||
SSH_MSG_USERAUTH_REQUEST */
|
||||
|
||||
/* These are only used for the server */
|
||||
char *printableuser; /* stripped of control chars, used for logs etc */
|
||||
struct passwd * pw;
|
||||
|
||||
uid_t pw_uid;
|
||||
gid_t pw_gid;
|
||||
char *pw_dir;
|
||||
char *pw_shell;
|
||||
char *pw_name;
|
||||
char *pw_passwd;
|
||||
#if DROPBEAR_SVR_PUBKEY_OPTIONS_BUILT
|
||||
struct PubKeyOptions* pubkey_options;
|
||||
char *pubkey_info;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct PubkeyList;
|
||||
/* A singly linked list of pubkeys */
|
||||
struct PubkeyList {
|
||||
|
||||
sign_key *key;
|
||||
int type; /* The type of key */
|
||||
struct PubkeyList *next;
|
||||
/* filename? or the buffer? for encrypted keys, so we can later get
|
||||
* the private key portion */
|
||||
|
||||
#if DROPBEAR_SVR_PUBKEY_OPTIONS_BUILT
|
||||
struct PubKeyOptions;
|
||||
struct PubKeyOptions {
|
||||
/* Flags */
|
||||
int no_port_forwarding_flag;
|
||||
int no_agent_forwarding_flag;
|
||||
int no_x11_forwarding_flag;
|
||||
int no_pty_flag;
|
||||
/* "command=" option. */
|
||||
char * forced_command;
|
||||
/* "permitopen=" option */
|
||||
m_list *permit_open_destinations;
|
||||
|
||||
#if DROPBEAR_SK_ECDSA || DROPBEAR_SK_ED25519
|
||||
int no_touch_required_flag;
|
||||
int verify_required_flag;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* _AUTH_H_ */
|
||||
struct PermitTCPFwdEntry {
|
||||
char *host;
|
||||
unsigned int port;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* DROPBEAR_AUTH_H_ */
|
||||
|
||||
71
bignum.c
71
bignum.c
@@ -31,7 +31,7 @@
|
||||
void m_mp_init(mp_int *mp) {
|
||||
|
||||
if (mp_init(mp) != MP_OKAY) {
|
||||
dropbear_exit("mem alloc error");
|
||||
dropbear_exit("Mem alloc error");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,37 +39,66 @@ void m_mp_init(mp_int *mp) {
|
||||
* on error */
|
||||
void m_mp_init_multi(mp_int *mp, ...)
|
||||
{
|
||||
mp_int* cur_arg = mp;
|
||||
va_list args;
|
||||
mp_int* cur_arg = mp;
|
||||
va_list args;
|
||||
|
||||
va_start(args, mp); /* init args to next argument from caller */
|
||||
while (cur_arg != NULL) {
|
||||
if (mp_init(cur_arg) != MP_OKAY) {
|
||||
dropbear_exit("mem alloc error");
|
||||
}
|
||||
cur_arg = va_arg(args, mp_int*);
|
||||
}
|
||||
va_end(args);
|
||||
va_start(args, mp); /* init args to next argument from caller */
|
||||
while (cur_arg != NULL) {
|
||||
if (mp_init(cur_arg) != MP_OKAY) {
|
||||
dropbear_exit("Mem alloc error");
|
||||
}
|
||||
cur_arg = va_arg(args, mp_int*);
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void bytestomp(mp_int *mp, unsigned char* bytes, unsigned int len) {
|
||||
void m_mp_alloc_init_multi(mp_int **mp, ...)
|
||||
{
|
||||
mp_int** cur_arg = mp;
|
||||
va_list args;
|
||||
|
||||
if (mp_read_unsigned_bin(mp, bytes, len) != MP_OKAY) {
|
||||
dropbear_exit("mem alloc error");
|
||||
va_start(args, mp); /* init args to next argument from caller */
|
||||
while (cur_arg != NULL) {
|
||||
*cur_arg = m_malloc(sizeof(mp_int));
|
||||
if (mp_init(*cur_arg) != MP_OKAY) {
|
||||
dropbear_exit("Mem alloc error");
|
||||
}
|
||||
cur_arg = va_arg(args, mp_int**);
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void m_mp_free_multi(mp_int **mp, ...)
|
||||
{
|
||||
mp_int** cur_arg = mp;
|
||||
va_list args;
|
||||
|
||||
va_start(args, mp); /* init args to next argument from caller */
|
||||
while (cur_arg != NULL) {
|
||||
if (*cur_arg) {
|
||||
mp_clear(*cur_arg);
|
||||
}
|
||||
m_free(*cur_arg);
|
||||
cur_arg = va_arg(args, mp_int**);
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void bytes_to_mp(mp_int *mp, const unsigned char* bytes, unsigned int len) {
|
||||
|
||||
if (mp_from_ubin(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;
|
||||
void hash_process_mp(const struct ltc_hash_descriptor *hash_desc,
|
||||
hash_state *hs, const mp_int *mp) {
|
||||
buffer * buf;
|
||||
|
||||
buf = buf_new(512 + 20); /* max buffer is a 4096 bit key,
|
||||
plus header + some leeway*/
|
||||
buf_putmpint(buf, mp);
|
||||
i = buf->pos;
|
||||
buf_setpos(buf, 0);
|
||||
sha1_process(hs, buf_getptr(buf, i), i);
|
||||
buf_free(buf);
|
||||
hash_desc->process(hs, buf->data, buf->len);
|
||||
buf_burn_free(buf);
|
||||
}
|
||||
|
||||
17
bignum.h
17
bignum.h
@@ -22,14 +22,17 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#ifndef _BIGNUM_H_
|
||||
#define _BIGNUM_H_
|
||||
#ifndef DROPBEAR_BIGNUM_H_
|
||||
#define DROPBEAR_BIGNUM_H_
|
||||
|
||||
#include "includes.h"
|
||||
#include "dbhelpers.h"
|
||||
|
||||
void m_mp_init(mp_int *mp);
|
||||
void m_mp_init_multi(mp_int *mp, ...);
|
||||
void bytestomp(mp_int *mp, unsigned char* bytes, unsigned int len);
|
||||
void sha1_process_mp(hash_state *hs, mp_int *mp);
|
||||
void m_mp_init_multi(mp_int *mp, ...) ATTRIB_SENTINEL;
|
||||
void m_mp_alloc_init_multi(mp_int **mp, ...) ATTRIB_SENTINEL;
|
||||
void m_mp_free_multi(mp_int **mp, ...) ATTRIB_SENTINEL;
|
||||
void bytes_to_mp(mp_int *mp, const unsigned char* bytes, unsigned int len);
|
||||
void hash_process_mp(const struct ltc_hash_descriptor *hash_desc,
|
||||
hash_state *hs, const mp_int *mp);
|
||||
|
||||
#endif /* _BIGNUM_H_ */
|
||||
#endif /* DROPBEAR_BIGNUM_H_ */
|
||||
|
||||
168
buffer.c
168
buffer.c
@@ -39,82 +39,71 @@
|
||||
|
||||
/* 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 = (buffer*)m_malloc(sizeof(buffer)+size);
|
||||
buf->data = (unsigned char*)buf + sizeof(buffer);
|
||||
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) {
|
||||
|
||||
/* overwrite the contents of the buffer then free it */
|
||||
void buf_burn_free(buffer* buf) {
|
||||
m_burn(buf->data, buf->size);
|
||||
|
||||
m_free(buf);
|
||||
}
|
||||
|
||||
|
||||
/* resize a buffer, pos and len will be repositioned if required when
|
||||
* downsizing */
|
||||
void buf_resize(buffer *buf, unsigned int newsize) {
|
||||
|
||||
buffer* buf_resize(buffer *buf, unsigned int newsize) {
|
||||
if (newsize > BUF_MAX_SIZE) {
|
||||
dropbear_exit("buf->size too big");
|
||||
}
|
||||
|
||||
buf->data = m_realloc(buf->data, newsize);
|
||||
buf = m_realloc(buf, sizeof(buffer)+newsize);
|
||||
buf->data = (unsigned char*)buf + sizeof(buffer);
|
||||
buf->size = newsize;
|
||||
buf->len = MIN(newsize, buf->len);
|
||||
buf->pos = MIN(newsize, buf->pos);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Create a copy of buf, allocating required memory etc. */
|
||||
/* The new buffer is sized the same as the length of the source buffer. */
|
||||
buffer* buf_newcopy(buffer* buf) {
|
||||
buffer* buf_newcopy(const buffer* buf) {
|
||||
|
||||
buffer* ret;
|
||||
|
||||
ret = buf_new(buf->len);
|
||||
ret->len = buf->len;
|
||||
memcpy(ret->data, buf->data, buf->len);
|
||||
if (buf->len > 0) {
|
||||
memcpy(ret->data, buf->data, buf->len);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set the length of the buffer */
|
||||
void buf_setlen(buffer* buf, unsigned int len) {
|
||||
if (len > buf->size) {
|
||||
dropbear_exit("bad buf_setlen");
|
||||
dropbear_exit("Bad buf_setlen");
|
||||
}
|
||||
buf->len = len;
|
||||
buf->pos = MIN(buf->pos, buf->len);
|
||||
}
|
||||
|
||||
/* Increment the length of the buffer */
|
||||
void buf_incrlen(buffer* buf, unsigned int incr) {
|
||||
if (incr > BUF_MAX_INCR || buf->len + incr > buf->size) {
|
||||
dropbear_exit("bad buf_incrlen");
|
||||
dropbear_exit("Bad buf_incrlen");
|
||||
}
|
||||
buf->len += incr;
|
||||
}
|
||||
@@ -122,15 +111,15 @@ void buf_incrlen(buffer* buf, unsigned int incr) {
|
||||
void buf_setpos(buffer* buf, unsigned int pos) {
|
||||
|
||||
if (pos > buf->len) {
|
||||
dropbear_exit("bad buf_setpos");
|
||||
dropbear_exit("Bad buf_setpos");
|
||||
}
|
||||
buf->pos = pos;
|
||||
}
|
||||
|
||||
/* increment the postion by incr, increasing the buffer length if required */
|
||||
/* increment the position by incr, increasing the buffer length if required */
|
||||
void buf_incrwritepos(buffer* buf, unsigned int incr) {
|
||||
if (incr > BUF_MAX_INCR || buf->pos + incr > buf->size) {
|
||||
dropbear_exit("bad buf_incrwritepos");
|
||||
dropbear_exit("Bad buf_incrwritepos");
|
||||
}
|
||||
buf->pos += incr;
|
||||
if (buf->pos > buf->len) {
|
||||
@@ -138,28 +127,44 @@ void buf_incrwritepos(buffer* buf, unsigned int incr) {
|
||||
}
|
||||
}
|
||||
|
||||
/* increment the position by incr, negative values are allowed, to
|
||||
* decrement the pos*/
|
||||
void buf_incrpos(buffer* buf, int incr) {
|
||||
if (incr > BUF_MAX_INCR ||
|
||||
(unsigned int)((int)buf->pos + incr) > buf->len
|
||||
|| ((int)buf->pos + incr) < 0) {
|
||||
dropbear_exit("bad buf_incrpos");
|
||||
/* increment the position by incr */
|
||||
void buf_incrpos(buffer* buf, unsigned int incr) {
|
||||
if (incr > BUF_MAX_INCR
|
||||
|| (buf->pos + incr) > buf->len) {
|
||||
dropbear_exit("Bad buf_incrpos");
|
||||
}
|
||||
buf->pos += incr;
|
||||
}
|
||||
|
||||
/* decrement the position by decr */
|
||||
void buf_decrpos(buffer* buf, unsigned int decr) {
|
||||
if (decr > buf->pos) {
|
||||
dropbear_exit("Bad buf_decrpos");
|
||||
}
|
||||
buf->pos -= decr;
|
||||
}
|
||||
|
||||
/* 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
|
||||
* assert()able case of pos > len, which should _never_ happen. */
|
||||
* bad case of pos > len, which should _never_ happen. */
|
||||
if (buf->pos >= buf->len) {
|
||||
dropbear_exit("bad buf_getbyte");
|
||||
dropbear_exit("Bad buf_getbyte");
|
||||
}
|
||||
return buf->data[buf->pos++];
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
|
||||
@@ -172,20 +177,20 @@ void buf_putbyte(buffer* buf, unsigned char val) {
|
||||
|
||||
/* returns an in-place pointer to the buffer, checking that
|
||||
* the next len bytes from that position can be used */
|
||||
unsigned char* buf_getptr(buffer* buf, unsigned int len) {
|
||||
unsigned char* buf_getptr(const buffer* buf, unsigned int len) {
|
||||
|
||||
if (buf->pos + len > buf->len) {
|
||||
dropbear_exit("bad buf_getptr");
|
||||
if (len > BUF_MAX_INCR || buf->pos + len > buf->len) {
|
||||
dropbear_exit("Bad buf_getptr");
|
||||
}
|
||||
return &buf->data[buf->pos];
|
||||
}
|
||||
|
||||
/* like buf_getptr, but checks against total size, not used length.
|
||||
* This allows writing past the used length, but not past the size */
|
||||
unsigned char* buf_getwriteptr(buffer* buf, unsigned int len) {
|
||||
unsigned char* buf_getwriteptr(const buffer* buf, unsigned int len) {
|
||||
|
||||
if (buf->pos + len > buf->size) {
|
||||
dropbear_exit("bad buf_getwriteptr");
|
||||
if (len > BUF_MAX_INCR || buf->pos + len > buf->size) {
|
||||
dropbear_exit("Bad buf_getwriteptr");
|
||||
}
|
||||
return &buf->data[buf->pos];
|
||||
}
|
||||
@@ -193,26 +198,60 @@ unsigned char* buf_getwriteptr(buffer* buf, unsigned int len) {
|
||||
/* Return a null-terminated string, it is malloced, so must be free()ed
|
||||
* Note that the string isn't checked for null bytes, hence the retlen
|
||||
* may be longer than what is returned by strlen */
|
||||
unsigned char* buf_getstring(buffer* buf, unsigned int *retlen) {
|
||||
char* buf_getstring(buffer* buf, unsigned int *retlen) {
|
||||
|
||||
unsigned int len;
|
||||
unsigned char* ret;
|
||||
char* ret;
|
||||
void* src = NULL;
|
||||
len = buf_getint(buf);
|
||||
if (len > MAX_STRING_LEN) {
|
||||
dropbear_exit("string too long");
|
||||
dropbear_exit("String too long");
|
||||
}
|
||||
|
||||
if (retlen != NULL) {
|
||||
*retlen = len;
|
||||
}
|
||||
src = buf_getptr(buf, len);
|
||||
ret = m_malloc(len+1);
|
||||
memcpy(ret, buf_getptr(buf, len), len);
|
||||
memcpy(ret, src, len);
|
||||
buf_incrpos(buf, len);
|
||||
ret[len] = '\0';
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return a string as a newly allocated buffer */
|
||||
static buffer * buf_getstringbuf_int(buffer *buf, int incllen) {
|
||||
buffer *ret = NULL;
|
||||
unsigned int len = buf_getint(buf);
|
||||
int extra = 0;
|
||||
if (len > MAX_STRING_LEN) {
|
||||
dropbear_exit("String too long");
|
||||
}
|
||||
if (incllen) {
|
||||
extra = 4;
|
||||
}
|
||||
ret = buf_new(len+extra);
|
||||
if (incllen) {
|
||||
buf_putint(ret, len);
|
||||
}
|
||||
memcpy(buf_getwriteptr(ret, len), buf_getptr(buf, len), len);
|
||||
buf_incrpos(buf, len);
|
||||
buf_incrlen(ret, len);
|
||||
buf_setpos(ret, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return a string as a newly allocated buffer */
|
||||
buffer * buf_getstringbuf(buffer *buf) {
|
||||
return buf_getstringbuf_int(buf, 0);
|
||||
}
|
||||
|
||||
/* Returns a string in a new buffer, including the length */
|
||||
buffer * buf_getbuf(buffer *buf) {
|
||||
return buf_getstringbuf_int(buf, 1);
|
||||
}
|
||||
|
||||
/* Just increment the buffer position the same as if we'd used buf_getstring,
|
||||
* but don't bother copying/malloc()ing for it */
|
||||
void buf_eatstring(buffer *buf) {
|
||||
@@ -238,13 +277,18 @@ void buf_putint(buffer* buf, int unsigned val) {
|
||||
}
|
||||
|
||||
/* put a SSH style string into the buffer, increasing buffer len if required */
|
||||
void buf_putstring(buffer* buf, const unsigned char* str, unsigned int len) {
|
||||
void buf_putstring(buffer* buf, const char* str, unsigned int len) {
|
||||
|
||||
buf_putint(buf, len);
|
||||
buf_putbytes(buf, str, len);
|
||||
buf_putbytes(buf, (const unsigned char*)str, len);
|
||||
|
||||
}
|
||||
|
||||
/* puts an entire buffer as a SSH string. ignore pos of buf_str. */
|
||||
void buf_putbufstring(buffer *buf, const buffer* buf_str) {
|
||||
buf_putstring(buf, (const char*)buf_str->data, buf_str->len);
|
||||
}
|
||||
|
||||
/* put the set of len bytes into the buffer, incrementing the pos, increasing
|
||||
* len if required */
|
||||
void buf_putbytes(buffer *buf, const unsigned char *bytes, unsigned int len) {
|
||||
@@ -255,19 +299,19 @@ void buf_putbytes(buffer *buf, const unsigned char *bytes, unsigned int len) {
|
||||
|
||||
/* for our purposes we only need positive (or 0) numbers, so will
|
||||
* fail if we get negative numbers */
|
||||
void buf_putmpint(buffer* buf, mp_int * mp) {
|
||||
|
||||
void buf_putmpint(buffer* buf, const mp_int * mp) {
|
||||
size_t written;
|
||||
unsigned int len, pad = 0;
|
||||
TRACE(("enter buf_putmpint"))
|
||||
TRACE2(("enter buf_putmpint"))
|
||||
|
||||
assert(mp != NULL);
|
||||
dropbear_assert(mp != NULL);
|
||||
|
||||
if (SIGN(mp) == MP_NEG) {
|
||||
if (mp_isneg(mp)) {
|
||||
dropbear_exit("negative bignum");
|
||||
}
|
||||
|
||||
/* zero check */
|
||||
if (USED(mp) == 1 && DIGIT(mp, 0) == 0) {
|
||||
if (mp_iszero(mp)) {
|
||||
len = 0;
|
||||
} else {
|
||||
/* SSH spec requires padding for mpints with the MSB set, this code
|
||||
@@ -288,13 +332,13 @@ void buf_putmpint(buffer* buf, mp_int * mp) {
|
||||
if (pad) {
|
||||
buf_putbyte(buf, 0x00);
|
||||
}
|
||||
if (mp_to_unsigned_bin(mp, buf_getwriteptr(buf, len-pad)) != MP_OKAY) {
|
||||
if (mp_to_ubin(mp, buf_getwriteptr(buf, len-pad), len-pad, &written) != MP_OKAY) {
|
||||
dropbear_exit("mpint error");
|
||||
}
|
||||
buf_incrwritepos(buf, len-pad);
|
||||
buf_incrwritepos(buf, written);
|
||||
}
|
||||
|
||||
TRACE(("leave buf_putmpint"))
|
||||
TRACE2(("leave buf_putmpint"))
|
||||
}
|
||||
|
||||
/* Retrieve an mp_int from the buffer.
|
||||
@@ -319,7 +363,7 @@ int buf_getmpint(buffer* buf, mp_int* mp) {
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
if (mp_read_unsigned_bin(mp, buf_getptr(buf, len), len) != MP_OKAY) {
|
||||
if (mp_from_ubin(mp, buf_getptr(buf, len), len) != MP_OKAY) {
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
33
buffer.h
33
buffer.h
@@ -22,14 +22,15 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#ifndef _BUFFER_H_
|
||||
#ifndef DROPBEAR_BUFFER_H_
|
||||
|
||||
#define _BUFFER_H_
|
||||
#define DROPBEAR_BUFFER_H_
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
struct buf {
|
||||
|
||||
/* don't manipulate data member outside of buffer.c - it
|
||||
is a pointer into the malloc holding buffer itself */
|
||||
unsigned char * data;
|
||||
unsigned int len; /* the used size */
|
||||
unsigned int pos;
|
||||
@@ -40,26 +41,32 @@ struct buf {
|
||||
typedef struct buf buffer;
|
||||
|
||||
buffer * buf_new(unsigned int size);
|
||||
void buf_resize(buffer *buf, unsigned int newsize);
|
||||
/* Possibly returns a new buffer*, like realloc() */
|
||||
buffer * buf_resize(buffer *buf, unsigned int newsize);
|
||||
void buf_free(buffer* buf);
|
||||
void buf_burn(buffer* buf);
|
||||
buffer* buf_newcopy(buffer* buf);
|
||||
void buf_burn_free(buffer* buf);
|
||||
buffer* buf_newcopy(const buffer* buf);
|
||||
void buf_setlen(buffer* buf, unsigned int len);
|
||||
void buf_incrlen(buffer* buf, unsigned int incr);
|
||||
void buf_setpos(buffer* buf, unsigned int pos);
|
||||
void buf_incrpos(buffer* buf, int incr); /* -ve is ok, to go backwards */
|
||||
void buf_incrpos(buffer* buf, unsigned int incr);
|
||||
void buf_decrpos(buffer* buf, unsigned int decr);
|
||||
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);
|
||||
unsigned char* buf_getptr(const buffer* buf, unsigned int len);
|
||||
unsigned char* buf_getwriteptr(const buffer* buf, unsigned int len);
|
||||
char* buf_getstring(buffer* buf, unsigned int *retlen);
|
||||
buffer * buf_getstringbuf(buffer *buf);
|
||||
buffer * buf_getbuf(buffer *buf);
|
||||
void buf_eatstring(buffer *buf);
|
||||
void buf_putint(buffer* buf, unsigned int val);
|
||||
void buf_putstring(buffer* buf, const unsigned char* str, unsigned int len);
|
||||
void buf_putstring(buffer* buf, const char* str, unsigned int len);
|
||||
void buf_putbufstring(buffer *buf, const buffer* buf_str);
|
||||
void buf_putbytes(buffer *buf, const unsigned char *bytes, unsigned int len);
|
||||
void buf_putmpint(buffer* buf, mp_int * mp);
|
||||
void buf_putmpint(buffer* buf, const mp_int * mp);
|
||||
int buf_getmpint(buffer* buf, mp_int* mp);
|
||||
unsigned int buf_getint(buffer* buf);
|
||||
|
||||
#endif /* _BUFFER_H_ */
|
||||
#endif /* DROPBEAR_BUFFER_H_ */
|
||||
|
||||
7
build.sh
Executable file
7
build.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker build -t dropbearbuild -f Dockerfile .
|
||||
|
||||
docker run --rm -t -v $(pwd):/root/dropbear dropbearbuild -c "./configure --disable-zlib --disable-syslog --enable-static --disable-harden && make PROGRAMS=\"dropbear dropbearconvert\""
|
||||
|
||||
docker image rm dropbearbuild
|
||||
148
chachapoly.c
Normal file
148
chachapoly.c
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Dropbear SSH
|
||||
*
|
||||
* Copyright (c) 2002,2003 Matt Johnston
|
||||
* Copyright (c) 2020 by Vladislav Grishenko
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#include "includes.h"
|
||||
#include "algo.h"
|
||||
#include "dbutil.h"
|
||||
#include "chachapoly.h"
|
||||
|
||||
#if DROPBEAR_CHACHA20POLY1305
|
||||
|
||||
#define CHACHA20_KEY_LEN 32
|
||||
#define CHACHA20_BLOCKSIZE 8
|
||||
#define POLY1305_KEY_LEN 32
|
||||
#define POLY1305_TAG_LEN 16
|
||||
|
||||
static const struct ltc_cipher_descriptor dummy = {.name = NULL};
|
||||
|
||||
static const struct dropbear_hash dropbear_chachapoly_mac =
|
||||
{NULL, POLY1305_KEY_LEN, POLY1305_TAG_LEN};
|
||||
|
||||
const struct dropbear_cipher dropbear_chachapoly =
|
||||
{&dummy, CHACHA20_KEY_LEN*2, CHACHA20_BLOCKSIZE};
|
||||
|
||||
static int dropbear_chachapoly_start(int UNUSED(cipher), const unsigned char* UNUSED(IV),
|
||||
const unsigned char *key, int keylen,
|
||||
int UNUSED(num_rounds), dropbear_chachapoly_state *state) {
|
||||
int err;
|
||||
|
||||
TRACE2(("enter dropbear_chachapoly_start"))
|
||||
|
||||
if (keylen != CHACHA20_KEY_LEN*2) {
|
||||
return CRYPT_ERROR;
|
||||
}
|
||||
|
||||
if ((err = chacha_setup(&state->chacha, key,
|
||||
CHACHA20_KEY_LEN, 20)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if ((err = chacha_setup(&state->header, key + CHACHA20_KEY_LEN,
|
||||
CHACHA20_KEY_LEN, 20) != CRYPT_OK)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
TRACE2(("leave dropbear_chachapoly_start"))
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
static int dropbear_chachapoly_crypt(unsigned int seq,
|
||||
const unsigned char *in, unsigned char *out,
|
||||
unsigned long len, unsigned long taglen,
|
||||
dropbear_chachapoly_state *state, int direction) {
|
||||
poly1305_state poly;
|
||||
unsigned char seqbuf[8], key[POLY1305_KEY_LEN], tag[POLY1305_TAG_LEN];
|
||||
int err;
|
||||
|
||||
TRACE2(("enter dropbear_chachapoly_crypt"))
|
||||
|
||||
if (len < 4 || taglen != POLY1305_TAG_LEN) {
|
||||
return CRYPT_ERROR;
|
||||
}
|
||||
|
||||
STORE64H((uint64_t)seq, seqbuf);
|
||||
chacha_ivctr64(&state->chacha, seqbuf, sizeof(seqbuf), 0);
|
||||
if ((err = chacha_keystream(&state->chacha, key, sizeof(key))) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
poly1305_init(&poly, key, sizeof(key));
|
||||
if (direction == LTC_DECRYPT) {
|
||||
poly1305_process(&poly, in, len);
|
||||
poly1305_done(&poly, tag, &taglen);
|
||||
if (constant_time_memcmp(in + len, tag, taglen) != 0) {
|
||||
return CRYPT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
chacha_ivctr64(&state->header, seqbuf, sizeof(seqbuf), 0);
|
||||
if ((err = chacha_crypt(&state->header, in, 4, out)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
chacha_ivctr64(&state->chacha, seqbuf, sizeof(seqbuf), 1);
|
||||
if ((err = chacha_crypt(&state->chacha, in + 4, len - 4, out + 4)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (direction == LTC_ENCRYPT) {
|
||||
poly1305_process(&poly, out, len);
|
||||
poly1305_done(&poly, out + len, &taglen);
|
||||
}
|
||||
|
||||
TRACE2(("leave dropbear_chachapoly_crypt"))
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
static int dropbear_chachapoly_getlength(unsigned int seq,
|
||||
const unsigned char *in, unsigned int *outlen,
|
||||
unsigned long len, dropbear_chachapoly_state *state) {
|
||||
unsigned char seqbuf[8], buf[4];
|
||||
int err;
|
||||
|
||||
TRACE2(("enter dropbear_chachapoly_getlength"))
|
||||
|
||||
if (len < sizeof(buf)) {
|
||||
return CRYPT_ERROR;
|
||||
}
|
||||
|
||||
STORE64H((uint64_t)seq, seqbuf);
|
||||
chacha_ivctr64(&state->header, seqbuf, sizeof(seqbuf), 0);
|
||||
if ((err = chacha_crypt(&state->header, in, sizeof(buf), buf)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
LOAD32H(*outlen, buf);
|
||||
|
||||
TRACE2(("leave dropbear_chachapoly_getlength"))
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
const struct dropbear_cipher_mode dropbear_mode_chachapoly =
|
||||
{(void *)dropbear_chachapoly_start, NULL, NULL,
|
||||
(void *)dropbear_chachapoly_crypt,
|
||||
(void *)dropbear_chachapoly_getlength, &dropbear_chachapoly_mac};
|
||||
|
||||
#endif /* DROPBEAR_CHACHA20POLY1305 */
|
||||
44
chachapoly.h
Normal file
44
chachapoly.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Dropbear SSH
|
||||
*
|
||||
* Copyright (c) 2002,2003 Matt Johnston
|
||||
* Copyright (c) 2020 by Vladislav Grishenko
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#ifndef DROPBEAR_DROPBEAR_CHACHAPOLY_H_
|
||||
#define DROPBEAR_DROPBEAR_CHACHAPOLY_H_
|
||||
|
||||
#include "includes.h"
|
||||
#include "algo.h"
|
||||
|
||||
#if DROPBEAR_CHACHA20POLY1305
|
||||
|
||||
typedef struct {
|
||||
chacha_state chacha;
|
||||
chacha_state header;
|
||||
} dropbear_chachapoly_state;
|
||||
|
||||
extern const struct dropbear_cipher dropbear_chachapoly;
|
||||
extern const struct dropbear_cipher_mode dropbear_mode_chachapoly;
|
||||
|
||||
#endif /* DROPBEAR_CHACHA20POLY1305 */
|
||||
|
||||
#endif /* DROPBEAR_DROPBEAR_CHACHAPOLY_H_ */
|
||||
121
channel.h
121
channel.h
@@ -22,20 +22,13 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#ifndef _CHANNEL_H_
|
||||
#define _CHANNEL_H_
|
||||
#ifndef DROPBEAR_CHANNEL_H_
|
||||
#define DROPBEAR_CHANNEL_H_
|
||||
|
||||
#include "includes.h"
|
||||
#include "buffer.h"
|
||||
#include "circbuffer.h"
|
||||
|
||||
/* channel->type values */
|
||||
#define CHANNEL_ID_NONE 0
|
||||
#define CHANNEL_ID_SESSION 1
|
||||
#define CHANNEL_ID_X11 2
|
||||
#define CHANNEL_ID_AGENT 3
|
||||
#define CHANNEL_ID_TCPDIRECT 4
|
||||
#define CHANNEL_ID_TCPFORWARDED 5
|
||||
#include "netio.h"
|
||||
|
||||
#define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED 1
|
||||
#define SSH_OPEN_CONNECT_FAILED 2
|
||||
@@ -45,16 +38,8 @@
|
||||
/* Not a real type */
|
||||
#define SSH_OPEN_IN_PROGRESS 99
|
||||
|
||||
#define MAX_CHANNELS 100 /* simple mem restriction, includes each tcp/x11
|
||||
connection, so can't be _too_ small */
|
||||
|
||||
#define CHAN_EXTEND_SIZE 3 /* how many extra slots to add when we need more */
|
||||
|
||||
#define RECV_MAXWINDOW 8000 /* tweak */
|
||||
#define RECV_WINDOWEXTEND 1000 /* We send a "window extend" every
|
||||
RECV_WINDOWEXTEND bytes */
|
||||
#define RECV_MAXPACKET RECV_MAXWINDOW /* tweak */
|
||||
|
||||
struct ChanType;
|
||||
|
||||
struct Channel {
|
||||
@@ -65,67 +50,95 @@ struct Channel {
|
||||
unsigned int recvdonelen;
|
||||
unsigned int recvmaxpacket, transmaxpacket;
|
||||
void* typedata; /* a pointer to type specific data */
|
||||
int infd; /* data to send over the wire */
|
||||
int outfd; /* data for consumption, what was in writebuf */
|
||||
int errfd; /* used like infd or errfd, depending if it's client or server.
|
||||
int writefd; /* read from wire, written to insecure side */
|
||||
int readfd; /* read from insecure side, written to wire */
|
||||
int errfd; /* used like writefd or readfd, depending if it's client or server.
|
||||
Doesn't exactly belong here, but is cleaner here */
|
||||
circbuffer *writebuf; /* data from the wire, for local consumption */
|
||||
int bidir_fd; /* a boolean indicating that writefd/readfd are the same
|
||||
file descriptor (bidirectional), such as a network socket or PTY.
|
||||
That is handled differently when closing FDs */
|
||||
circbuffer *writebuf; /* data from the wire, for local consumption. Can be
|
||||
initially NULL */
|
||||
circbuffer *extrabuf; /* extended-data for the program - used like writebuf
|
||||
but for stderr */
|
||||
|
||||
int sentclosed, recvclosed;
|
||||
|
||||
/* this is set when we receive/send a channel eof packet */
|
||||
int recveof, senteof;
|
||||
/* whether close/eof messages have been exchanged */
|
||||
int sent_close, recv_close;
|
||||
int recv_eof, sent_eof;
|
||||
/* once flushing is set, readfd will close once no more data is available
|
||||
(not waiting for EOF) */
|
||||
int flushing;
|
||||
|
||||
struct dropbear_progress_connection *conn_pending;
|
||||
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). */
|
||||
|
||||
/* Used by client chansession to handle ~ escaping, NULL ignored otherwise */
|
||||
void (*read_mangler)(const struct Channel*, const unsigned char* bytes, int *len);
|
||||
|
||||
const struct ChanType* type;
|
||||
|
||||
enum dropbear_prio prio;
|
||||
};
|
||||
|
||||
struct ChanType {
|
||||
|
||||
int sepfds; /* Whether this channel has seperate pipes for in/out or not */
|
||||
char *name;
|
||||
const char *name;
|
||||
/* Sets up the channel */
|
||||
int (*inithandler)(struct Channel*);
|
||||
int (*checkclose)(struct Channel*);
|
||||
/* Called to check whether a channel should close, separately from the FD being EOF.
|
||||
Used for noticing process exiting */
|
||||
int (*check_close)(struct Channel*);
|
||||
/* Handler for ssh_msg_channel_request */
|
||||
void (*reqhandler)(struct Channel*);
|
||||
void (*closehandler)(struct Channel*);
|
||||
|
||||
/* Called prior to sending ssh_msg_channel_close, used for sending exit status */
|
||||
void (*closehandler)(const struct Channel*);
|
||||
/* Frees resources, called just prior to channel being removed */
|
||||
void (*cleanup)(const struct Channel*);
|
||||
};
|
||||
|
||||
void chaninitialise();
|
||||
void chancleanup();
|
||||
void setchannelfds(fd_set *readfd, fd_set *writefd);
|
||||
void channelio(fd_set *readfd, fd_set *writefd);
|
||||
struct Channel* getchannel(unsigned int chan);
|
||||
struct Channel* newchannel(unsigned int remotechan,
|
||||
const struct ChanType *type,
|
||||
unsigned int transwindow, unsigned int transmaxpacket);
|
||||
/* Callback for connect_remote. errstring may be NULL if result == DROPBEAR_SUCCESS */
|
||||
void channel_connect_done(int result, int sock, void* user_data, const char* errstring);
|
||||
|
||||
void recv_msg_channel_open();
|
||||
void recv_msg_channel_request();
|
||||
void 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 chaninitialise(const struct ChanType *chantypes[]);
|
||||
void chancleanup(void);
|
||||
void setchannelfds(fd_set *readfds, fd_set *writefds, int allow_reads);
|
||||
void channelio(const fd_set *readfd, const fd_set *writefd);
|
||||
struct Channel* getchannel(void);
|
||||
/* Returns an arbitrary channel that is in a ready state - not
|
||||
being initialised and no EOF in either direction. NULL if none. */
|
||||
struct Channel* get_any_ready_channel(void);
|
||||
|
||||
void recv_msg_channel_open(void);
|
||||
void recv_msg_channel_request(void);
|
||||
void send_msg_channel_failure(const struct Channel *channel);
|
||||
void send_msg_channel_success(const struct Channel *channel);
|
||||
void recv_msg_channel_data(void);
|
||||
void recv_msg_channel_extended_data(void);
|
||||
void recv_msg_channel_window_adjust(void);
|
||||
void recv_msg_channel_close(void);
|
||||
void recv_msg_channel_eof(void);
|
||||
|
||||
void common_recv_msg_channel_data(struct Channel *channel, int fd,
|
||||
circbuffer * buf);
|
||||
|
||||
#ifdef DROPBEAR_CLIENT
|
||||
const struct ChanType clichansess;
|
||||
#if DROPBEAR_CLIENT
|
||||
extern const struct ChanType clichansess;
|
||||
#endif
|
||||
|
||||
#if defined(USING_LISTENERS) || defined(DROPBEAR_CLIENT)
|
||||
#if DROPBEAR_LISTENERS || DROPBEAR_CLIENT
|
||||
int send_msg_channel_open_init(int fd, const struct ChanType *type);
|
||||
void recv_msg_channel_open_confirmation();
|
||||
void recv_msg_channel_open_failure();
|
||||
void recv_msg_channel_open_confirmation(void);
|
||||
void recv_msg_channel_open_failure(void);
|
||||
#endif
|
||||
void start_send_channel_request(const struct Channel *channel, const char *type);
|
||||
|
||||
#endif /* _CHANNEL_H_ */
|
||||
void send_msg_request_success(void);
|
||||
void send_msg_request_failure(void);
|
||||
|
||||
|
||||
#endif /* DROPBEAR_CHANNEL_H_ */
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#ifndef _CHANSESSION_H_
|
||||
#define _CHANSESSION_H_
|
||||
#ifndef DROPBEAR_CHANSESSION_H_
|
||||
#define DROPBEAR_CHANSESSION_H_
|
||||
|
||||
#include "loginrec.h"
|
||||
#include "channel.h"
|
||||
@@ -39,19 +39,29 @@ struct exitinfo {
|
||||
|
||||
struct ChanSess {
|
||||
|
||||
unsigned char * cmd; /* command to exec */
|
||||
char * cmd; /* command to exec */
|
||||
pid_t pid; /* child process pid */
|
||||
/* command that was sent by the client, if authorized_keys command= or
|
||||
dropbear -c was used */
|
||||
char *original_command;
|
||||
|
||||
/* pty details */
|
||||
int master; /* the master terminal fd*/
|
||||
int slave;
|
||||
unsigned char * tty;
|
||||
unsigned char * term;
|
||||
char * tty;
|
||||
char * term;
|
||||
|
||||
/* exit details */
|
||||
struct exitinfo exit;
|
||||
|
||||
|
||||
/* These are only set temporarily before forking */
|
||||
/* Used to set $SSH_CONNECTION in the child session. */
|
||||
char *connection_string;
|
||||
/* Used to set $SSH_CLIENT in the child session. */
|
||||
char *client_string;
|
||||
|
||||
#ifndef DISABLE_X11FWD
|
||||
#if DROPBEAR_X11FWD
|
||||
struct Listener * x11listener;
|
||||
int x11port;
|
||||
char * x11authprot;
|
||||
@@ -60,7 +70,7 @@ struct ChanSess {
|
||||
unsigned char x11singleconn;
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_AGENTFWD
|
||||
#if DROPBEAR_SVR_AGENTFWD
|
||||
struct Listener * agentlistener;
|
||||
char * agentfile;
|
||||
char * agentdir;
|
||||
@@ -75,11 +85,15 @@ struct ChildPid {
|
||||
|
||||
void addnewvar(const char* param, const char* var);
|
||||
|
||||
void cli_send_chansess_request();
|
||||
void cli_tty_cleanup();
|
||||
void cli_chansess_winchange();
|
||||
void cli_send_chansess_request(void);
|
||||
void cli_tty_cleanup(void);
|
||||
void cli_chansess_winchange(void);
|
||||
#if DROPBEAR_CLI_NETCAT
|
||||
void cli_send_netcat_request(void);
|
||||
#endif
|
||||
|
||||
void svr_chansessinitialise();
|
||||
void svr_chansessinitialise(void);
|
||||
void svr_chansess_checksignal(void);
|
||||
extern const struct ChanType svrchansess;
|
||||
|
||||
struct SigMap {
|
||||
@@ -89,4 +103,4 @@ struct SigMap {
|
||||
|
||||
extern const struct SigMap signames[];
|
||||
|
||||
#endif /* _CHANSESSION_H_ */
|
||||
#endif /* DROPBEAR_CHANSESSION_H_ */
|
||||
|
||||
73
circbuffer.c
73
circbuffer.c
@@ -33,11 +33,12 @@ circbuffer * cbuf_new(unsigned int size) {
|
||||
circbuffer *cbuf = NULL;
|
||||
|
||||
if (size > MAX_CBUF_SIZE) {
|
||||
dropbear_exit("bad cbuf size");
|
||||
dropbear_exit("Bad cbuf size");
|
||||
}
|
||||
|
||||
cbuf = (circbuffer*)m_malloc(sizeof(circbuffer));
|
||||
cbuf->data = (unsigned char*)m_malloc(size);
|
||||
/* data is malloced on first write */
|
||||
cbuf->data = NULL;
|
||||
cbuf->used = 0;
|
||||
cbuf->readpos = 0;
|
||||
cbuf->writepos = 0;
|
||||
@@ -48,44 +49,30 @@ circbuffer * cbuf_new(unsigned int size) {
|
||||
|
||||
void cbuf_free(circbuffer * cbuf) {
|
||||
|
||||
m_free(cbuf->data);
|
||||
if (cbuf->data) {
|
||||
m_burn(cbuf->data, cbuf->size);
|
||||
m_free(cbuf->data);
|
||||
}
|
||||
m_free(cbuf);
|
||||
}
|
||||
|
||||
unsigned int cbuf_getused(circbuffer * cbuf) {
|
||||
unsigned int cbuf_getused(const circbuffer * cbuf) {
|
||||
|
||||
return cbuf->used;
|
||||
|
||||
}
|
||||
|
||||
unsigned int cbuf_getavail(circbuffer * cbuf) {
|
||||
unsigned int cbuf_getavail(const circbuffer * cbuf) {
|
||||
|
||||
return cbuf->size - cbuf->used;
|
||||
|
||||
}
|
||||
|
||||
unsigned int cbuf_readlen(circbuffer *cbuf) {
|
||||
unsigned int cbuf_writelen(const circbuffer *cbuf) {
|
||||
|
||||
assert(((2*cbuf->size)+cbuf->writepos-cbuf->readpos)%cbuf->size == cbuf->used%cbuf->size);
|
||||
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) {
|
||||
|
||||
assert(cbuf->used <= cbuf->size);
|
||||
assert(((2*cbuf->size)+cbuf->writepos-cbuf->readpos)%cbuf->size == cbuf->used%cbuf->size);
|
||||
assert(((2*cbuf->size)+cbuf->readpos-cbuf->writepos)%cbuf->size == (cbuf->size-cbuf->used)%cbuf->size);
|
||||
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"))
|
||||
@@ -99,18 +86,30 @@ unsigned int cbuf_writelen(circbuffer *cbuf) {
|
||||
return cbuf->size - cbuf->writepos;
|
||||
}
|
||||
|
||||
unsigned char* cbuf_readptr(circbuffer *cbuf, unsigned int len) {
|
||||
if (len > cbuf_readlen(cbuf)) {
|
||||
dropbear_exit("bad cbuf read");
|
||||
}
|
||||
void cbuf_readptrs(const circbuffer *cbuf,
|
||||
unsigned char **p1, unsigned int *len1,
|
||||
unsigned char **p2, unsigned int *len2) {
|
||||
*p1 = &cbuf->data[cbuf->readpos];
|
||||
*len1 = MIN(cbuf->used, cbuf->size - cbuf->readpos);
|
||||
|
||||
return &cbuf->data[cbuf->readpos];
|
||||
if (*len1 < cbuf->used) {
|
||||
*p2 = cbuf->data;
|
||||
*len2 = cbuf->used - *len1;
|
||||
} else {
|
||||
*p2 = NULL;
|
||||
*len2 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char* cbuf_writeptr(circbuffer *cbuf, unsigned int len) {
|
||||
|
||||
if (len > cbuf_writelen(cbuf)) {
|
||||
dropbear_exit("bad cbuf write");
|
||||
dropbear_exit("Bad cbuf write");
|
||||
}
|
||||
|
||||
if (!cbuf->data) {
|
||||
/* lazy allocation */
|
||||
cbuf->data = (unsigned char*)m_malloc(cbuf->size);
|
||||
}
|
||||
|
||||
return &cbuf->data[cbuf->writepos];
|
||||
@@ -118,21 +117,17 @@ unsigned char* cbuf_writeptr(circbuffer *cbuf, unsigned int len) {
|
||||
|
||||
void cbuf_incrwrite(circbuffer *cbuf, unsigned int len) {
|
||||
if (len > cbuf_writelen(cbuf)) {
|
||||
dropbear_exit("bad cbuf write");
|
||||
dropbear_exit("Bad cbuf write");
|
||||
}
|
||||
|
||||
cbuf->used += len;
|
||||
assert(cbuf->used <= cbuf->size);
|
||||
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");
|
||||
}
|
||||
|
||||
assert(cbuf->used >= len);
|
||||
dropbear_assert(cbuf->used >= len);
|
||||
cbuf->used -= len;
|
||||
cbuf->readpos = (cbuf->readpos + len) % cbuf->size;
|
||||
}
|
||||
|
||||
16
circbuffer.h
16
circbuffer.h
@@ -22,8 +22,8 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#ifndef _CIRCBUFFER_H_
|
||||
#define _CIRCBUFFER_H_
|
||||
#ifndef DROPBEAR_CIRCBUFFER_H_
|
||||
#define DROPBEAR_CIRCBUFFER_H_
|
||||
struct circbuf {
|
||||
|
||||
unsigned int size;
|
||||
@@ -38,12 +38,14 @@ 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 int cbuf_getused(const circbuffer * cbuf); /* how much data stored */
|
||||
unsigned int cbuf_getavail(const circbuffer * cbuf); /* how much we can write */
|
||||
unsigned int cbuf_writelen(const circbuffer *cbuf); /* max linear write len */
|
||||
|
||||
unsigned char* cbuf_readptr(circbuffer *cbuf, unsigned int len);
|
||||
/* returns pointers to the two portions of the circular buffer that can be read */
|
||||
void cbuf_readptrs(const circbuffer *cbuf,
|
||||
unsigned char **p1, unsigned int *len1,
|
||||
unsigned char **p2, unsigned int *len2);
|
||||
unsigned char* cbuf_writeptr(circbuffer *cbuf, unsigned int len);
|
||||
void cbuf_incrwrite(circbuffer *cbuf, unsigned int len);
|
||||
void cbuf_incrread(circbuffer *cbuf, unsigned int len);
|
||||
|
||||
316
cli-agentfwd.c
Normal file
316
cli-agentfwd.c
Normal file
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* Dropbear - a SSH2 server
|
||||
*
|
||||
* Copyright (c) 2005 Matt Johnston
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#if DROPBEAR_CLI_AGENTFWD
|
||||
|
||||
#include "agentfwd.h"
|
||||
#include "session.h"
|
||||
#include "ssh.h"
|
||||
#include "dbutil.h"
|
||||
#include "chansession.h"
|
||||
#include "channel.h"
|
||||
#include "packet.h"
|
||||
#include "buffer.h"
|
||||
#include "dbrandom.h"
|
||||
#include "listener.h"
|
||||
#include "runopts.h"
|
||||
#include "atomicio.h"
|
||||
#include "signkey.h"
|
||||
#include "auth.h"
|
||||
|
||||
/* The protocol implemented to talk to OpenSSH's SSH2 agent is documented in
|
||||
PROTOCOL.agent in recent OpenSSH source distributions (5.1p1 has it). */
|
||||
|
||||
static int new_agent_chan(struct Channel * channel);
|
||||
|
||||
const struct ChanType cli_chan_agent = {
|
||||
"auth-agent@openssh.com",
|
||||
new_agent_chan,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
static int connect_agent() {
|
||||
|
||||
int fd = -1;
|
||||
char* agent_sock = NULL;
|
||||
|
||||
agent_sock = getenv("SSH_AUTH_SOCK");
|
||||
if (agent_sock == NULL)
|
||||
return -1;
|
||||
|
||||
fd = connect_unix(agent_sock);
|
||||
|
||||
if (fd < 0) {
|
||||
dropbear_log(LOG_INFO, "Failed to connect to agent");
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* handle a request for a connection to the locally running ssh-agent
|
||||
or forward. */
|
||||
static int new_agent_chan(struct Channel * channel) {
|
||||
|
||||
int fd = -1;
|
||||
|
||||
if (!cli_opts.agent_fwd)
|
||||
return SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
|
||||
|
||||
fd = connect_agent();
|
||||
if (fd < 0) {
|
||||
return SSH_OPEN_CONNECT_FAILED;
|
||||
}
|
||||
|
||||
setnonblocking(fd);
|
||||
|
||||
ses.maxfd = MAX(ses.maxfd, fd);
|
||||
|
||||
channel->readfd = fd;
|
||||
channel->writefd = fd;
|
||||
channel->bidir_fd = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sends a request to the agent, returning a newly allocated buffer
|
||||
* with the response */
|
||||
/* This function will block waiting for a response - it will
|
||||
* only be used by client authentication (not for forwarded requests)
|
||||
* won't cause problems for interactivity. */
|
||||
/* Packet format (from draft-ylonen)
|
||||
4 bytes Length, msb first. Does not include length itself.
|
||||
1 byte Packet type. The value 255 is reserved for future extensions.
|
||||
data Any data, depending on packet type. Encoding as in the ssh packet
|
||||
protocol.
|
||||
*/
|
||||
static buffer * agent_request(unsigned char type, const buffer *data) {
|
||||
|
||||
buffer * payload = NULL;
|
||||
buffer * inbuf = NULL;
|
||||
size_t readlen = 0;
|
||||
ssize_t ret;
|
||||
const int fd = cli_opts.agent_fd;
|
||||
unsigned int data_len = 0;
|
||||
if (data)
|
||||
{
|
||||
data_len = data->len;
|
||||
}
|
||||
|
||||
payload = buf_new(4 + 1 + data_len);
|
||||
|
||||
buf_putint(payload, 1 + data_len);
|
||||
buf_putbyte(payload, type);
|
||||
if (data) {
|
||||
buf_putbytes(payload, data->data, data->len);
|
||||
}
|
||||
buf_setpos(payload, 0);
|
||||
|
||||
ret = atomicio(vwrite, fd, buf_getptr(payload, payload->len), payload->len);
|
||||
if ((size_t)ret != payload->len) {
|
||||
TRACE(("write failed fd %d for agent_request, %s", fd, strerror(errno)))
|
||||
goto out;
|
||||
}
|
||||
|
||||
buf_free(payload);
|
||||
payload = NULL;
|
||||
TRACE(("Wrote out bytes for agent_request"))
|
||||
/* Now we read the response */
|
||||
inbuf = buf_new(4);
|
||||
ret = atomicio(read, fd, buf_getwriteptr(inbuf, 4), 4);
|
||||
if (ret != 4) {
|
||||
TRACE(("read of length failed for agent_request"))
|
||||
goto out;
|
||||
}
|
||||
buf_setpos(inbuf, 0);
|
||||
buf_setlen(inbuf, ret);
|
||||
|
||||
readlen = buf_getint(inbuf);
|
||||
if (readlen > MAX_AGENT_REPLY) {
|
||||
TRACE(("agent reply is too big"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
inbuf = buf_resize(inbuf, readlen);
|
||||
buf_setpos(inbuf, 0);
|
||||
ret = atomicio(read, fd, buf_getwriteptr(inbuf, readlen), readlen);
|
||||
if ((size_t)ret != readlen) {
|
||||
TRACE(("read of data failed for agent_request"))
|
||||
goto out;
|
||||
}
|
||||
buf_incrwritepos(inbuf, readlen);
|
||||
buf_setpos(inbuf, 0);
|
||||
|
||||
out:
|
||||
if (payload)
|
||||
buf_free(payload);
|
||||
|
||||
return inbuf;
|
||||
}
|
||||
|
||||
static void agent_get_key_list(m_list * ret_list)
|
||||
{
|
||||
buffer * inbuf = NULL;
|
||||
unsigned int num = 0;
|
||||
unsigned char packet_type;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
inbuf = agent_request(SSH2_AGENTC_REQUEST_IDENTITIES, NULL);
|
||||
if (!inbuf) {
|
||||
TRACE(("agent_request failed returning identities"))
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* The reply has a format of:
|
||||
byte SSH2_AGENT_IDENTITIES_ANSWER
|
||||
uint32 num_keys
|
||||
Followed by zero or more consecutive keys, encoded as:
|
||||
string key_blob
|
||||
string key_comment
|
||||
*/
|
||||
packet_type = buf_getbyte(inbuf);
|
||||
if (packet_type != SSH2_AGENT_IDENTITIES_ANSWER) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
num = buf_getint(inbuf);
|
||||
for (i = 0; i < num; i++) {
|
||||
sign_key * pubkey = NULL;
|
||||
enum signkey_type key_type = DROPBEAR_SIGNKEY_ANY;
|
||||
buffer * key_buf;
|
||||
|
||||
/* each public key is encoded as a string */
|
||||
key_buf = buf_getstringbuf(inbuf);
|
||||
pubkey = new_sign_key();
|
||||
ret = buf_get_pub_key(key_buf, pubkey, &key_type);
|
||||
buf_free(key_buf);
|
||||
if (ret != DROPBEAR_SUCCESS) {
|
||||
TRACE(("Skipping bad/unknown type pubkey from agent"));
|
||||
sign_key_free(pubkey);
|
||||
} else {
|
||||
pubkey->type = key_type;
|
||||
pubkey->source = SIGNKEY_SOURCE_AGENT;
|
||||
|
||||
list_append(ret_list, pubkey);
|
||||
}
|
||||
|
||||
/* We'll ignore the comment for now. might want it later.*/
|
||||
buf_eatstring(inbuf);
|
||||
}
|
||||
|
||||
out:
|
||||
if (inbuf) {
|
||||
buf_free(inbuf);
|
||||
inbuf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void cli_setup_agent(const struct Channel *channel) {
|
||||
if (!getenv("SSH_AUTH_SOCK")) {
|
||||
return;
|
||||
}
|
||||
|
||||
start_send_channel_request(channel, "auth-agent-req@openssh.com");
|
||||
/* Don't want replies */
|
||||
buf_putbyte(ses.writepayload, 0);
|
||||
encrypt_packet();
|
||||
}
|
||||
|
||||
/* Returned keys are prepended to ret_list, which will
|
||||
be updated. */
|
||||
void cli_load_agent_keys(m_list *ret_list) {
|
||||
/* agent_fd will be closed after successful auth */
|
||||
cli_opts.agent_fd = connect_agent();
|
||||
if (cli_opts.agent_fd < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
agent_get_key_list(ret_list);
|
||||
}
|
||||
|
||||
void agent_buf_sign(buffer *sigblob, sign_key *key,
|
||||
const buffer *data_buf, enum signature_type sigtype) {
|
||||
buffer *request_data = NULL;
|
||||
buffer *response = NULL;
|
||||
unsigned int siglen;
|
||||
int packet_type;
|
||||
int flags = 0;
|
||||
|
||||
/* Request format
|
||||
byte SSH2_AGENTC_SIGN_REQUEST
|
||||
string key_blob
|
||||
string data
|
||||
uint32 flags
|
||||
*/
|
||||
request_data = buf_new(MAX_PUBKEY_SIZE + data_buf->len + 12);
|
||||
buf_put_pub_key(request_data, key, key->type);
|
||||
|
||||
buf_putbufstring(request_data, data_buf);
|
||||
#if DROPBEAR_RSA_SHA256
|
||||
if (sigtype == DROPBEAR_SIGNATURE_RSA_SHA256) {
|
||||
flags |= SSH_AGENT_RSA_SHA2_256;
|
||||
}
|
||||
#endif
|
||||
buf_putint(request_data, flags);
|
||||
|
||||
response = agent_request(SSH2_AGENTC_SIGN_REQUEST, request_data);
|
||||
|
||||
if (!response) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
packet_type = buf_getbyte(response);
|
||||
if (packet_type != SSH2_AGENT_SIGN_RESPONSE) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Response format
|
||||
byte SSH2_AGENT_SIGN_RESPONSE
|
||||
string signature_blob
|
||||
*/
|
||||
siglen = buf_getint(response);
|
||||
buf_putbytes(sigblob, buf_getptr(response, siglen), siglen);
|
||||
goto cleanup;
|
||||
|
||||
fail:
|
||||
/* XXX don't fail badly here. instead propagate a failure code back up to
|
||||
the cli auth pubkey code, and just remove this key from the list of
|
||||
ones to try. */
|
||||
dropbear_exit("Agent failed signing key");
|
||||
|
||||
cleanup:
|
||||
if (request_data) {
|
||||
buf_free(request_data);
|
||||
}
|
||||
if (response) {
|
||||
buf_free(response);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
99
cli-algo.c
99
cli-algo.c
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Dropbear - a SSH2 server
|
||||
* SSH client implementation
|
||||
*
|
||||
* Copyright (c) 2002,2003 Matt Johnston
|
||||
* Copyright (c) 2004 by Mihnea Stoenescu
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#include "algo.h"
|
||||
#include "dbutil.h"
|
||||
|
||||
|
||||
/*
|
||||
* The chosen [encryption | MAC | compression] algorithm to each
|
||||
* direction MUST be the first algorithm on the client's list
|
||||
* that is also on the server's list.
|
||||
*/
|
||||
algo_type * cli_buf_match_algo(buffer* buf, algo_type localalgos[],
|
||||
int *goodguess) {
|
||||
|
||||
unsigned char * algolist = NULL;
|
||||
unsigned char * remotealgos[MAX_PROPOSED_ALGO];
|
||||
unsigned int len;
|
||||
unsigned int count, i, j;
|
||||
algo_type * ret = NULL;
|
||||
|
||||
*goodguess = 0;
|
||||
|
||||
/* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */
|
||||
algolist = buf_getstring(buf, &len);
|
||||
TRACE(("cli_buf_match_algo: %s", algolist))
|
||||
if (len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
|
||||
goto out; /* just a sanity check, no other use */
|
||||
}
|
||||
|
||||
/* remotealgos will contain a list of the strings parsed out */
|
||||
/* We will have at least one string (even if it's just "") */
|
||||
remotealgos[0] = algolist;
|
||||
count = 1;
|
||||
/* Iterate through, replacing ','s with NULs, to split it into
|
||||
* words. */
|
||||
for (i = 0; i < len; i++) {
|
||||
if (algolist[i] == '\0') {
|
||||
/* someone is trying something strange */
|
||||
goto out;
|
||||
}
|
||||
if (algolist[i] == ',') {
|
||||
algolist[i] = '\0';
|
||||
remotealgos[count] = &algolist[i+1];
|
||||
count++;
|
||||
}
|
||||
if (count == MAX_PROPOSED_ALGO) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* iterate and find the first match */
|
||||
|
||||
for (j = 0; localalgos[j].name != NULL; j++) {
|
||||
if (localalgos[j].usable) {
|
||||
len = strlen(localalgos[j].name);
|
||||
for (i = 0; i < count; i++) {
|
||||
if (len == strlen(remotealgos[i])
|
||||
&& strncmp(localalgos[j].name,
|
||||
remotealgos[i], len) == 0) {
|
||||
if (i == 0 && j == 0) {
|
||||
/* was a good guess */
|
||||
*goodguess = 1;
|
||||
}
|
||||
ret = &localalgos[j];
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
m_free(algolist);
|
||||
return ret;
|
||||
}
|
||||
|
||||
257
cli-auth.c
257
cli-auth.c
@@ -32,37 +32,49 @@
|
||||
#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,
|
||||
buf_putstring(ses.writepayload, cli_opts.username,
|
||||
strlen(cli_opts.username));
|
||||
buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
|
||||
buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
|
||||
SSH_SERVICE_CONNECTION_LEN);
|
||||
buf_putstring(ses.writepayload, "none", 4); /* 'none' method */
|
||||
|
||||
encrypt_packet();
|
||||
TRACE(("leave cli_auth_getmethods"))
|
||||
|
||||
#if DROPBEAR_CLI_IMMEDIATE_AUTH
|
||||
/* We can't haven't two auth requests in-flight with delayed zlib mode
|
||||
since if the first one succeeds then the remote side will
|
||||
expect the second one to be compressed.
|
||||
Race described at
|
||||
http://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/zlib-openssh.html
|
||||
*/
|
||||
if (ses.keys->trans.algo_comp != DROPBEAR_COMP_ZLIB_DELAY) {
|
||||
ses.authstate.authtypes = AUTH_TYPE_PUBKEY;
|
||||
#if DROPBEAR_USE_PASSWORD_ENV
|
||||
if (getenv(DROPBEAR_PASSWORD_ENV)) {
|
||||
ses.authstate.authtypes |= AUTH_TYPE_PASSWORD | AUTH_TYPE_INTERACT;
|
||||
}
|
||||
#endif
|
||||
if (cli_auth_try() == DROPBEAR_SUCCESS) {
|
||||
TRACE(("skipped initial none auth query"))
|
||||
/* Note that there will be two auth responses in-flight */
|
||||
cli_ses.ignore_next_auth_response = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
TRACE(("leave cli_auth_getmethods"))
|
||||
}
|
||||
|
||||
void recv_msg_userauth_banner() {
|
||||
|
||||
unsigned char* banner = NULL;
|
||||
char* banner = NULL;
|
||||
unsigned int bannerlen;
|
||||
unsigned int i, linecount;
|
||||
int truncated = 0;
|
||||
|
||||
TRACE(("enter recv_msg_userauth_banner"))
|
||||
if (ses.authstate.authdone) {
|
||||
@@ -70,40 +82,82 @@ void recv_msg_userauth_banner() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cli_opts.quiet) {
|
||||
TRACE(("not showing banner"))
|
||||
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;
|
||||
}
|
||||
truncated = 1;
|
||||
} else {
|
||||
cleantext(banner);
|
||||
|
||||
cleantext(banner);
|
||||
|
||||
/* Limit to 25 lines */
|
||||
linecount = 1;
|
||||
for (i = 0; i < bannerlen; i++) {
|
||||
if (banner[i] == '\n') {
|
||||
if (linecount >= MAX_BANNER_LINES) {
|
||||
banner[i] = '\0';
|
||||
break;
|
||||
/* Limit to 24 lines */
|
||||
linecount = 1;
|
||||
for (i = 0; i < bannerlen; i++) {
|
||||
if (banner[i] == '\n') {
|
||||
if (linecount >= MAX_BANNER_LINES) {
|
||||
banner[i] = '\0';
|
||||
truncated = 1;
|
||||
break;
|
||||
}
|
||||
linecount++;
|
||||
}
|
||||
linecount++;
|
||||
}
|
||||
fprintf(stderr, "%s\n", banner);
|
||||
}
|
||||
|
||||
printf("%s\n", banner);
|
||||
if (truncated) {
|
||||
fprintf(stderr, "[Banner from the server is too long]\n");
|
||||
}
|
||||
|
||||
out:
|
||||
m_free(banner);
|
||||
TRACE(("leave recv_msg_userauth_banner"))
|
||||
}
|
||||
|
||||
/* 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() {
|
||||
|
||||
#if DROPBEAR_CLI_PUBKEY_AUTH
|
||||
if (cli_ses.lastauthtype == AUTH_TYPE_PUBKEY) {
|
||||
recv_msg_userauth_pk_ok();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DROPBEAR_CLI_INTERACT_AUTH
|
||||
if (cli_ses.lastauthtype == AUTH_TYPE_INTERACT) {
|
||||
recv_msg_userauth_info_request();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DROPBEAR_CLI_PASSWORD_AUTH
|
||||
if (cli_ses.lastauthtype == AUTH_TYPE_PASSWORD) {
|
||||
/* Eventually there could be proper password-changing
|
||||
* support. However currently few servers seem to
|
||||
* 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;
|
||||
char * methods = NULL;
|
||||
char * tok = NULL;
|
||||
unsigned int methlen = 0;
|
||||
unsigned int partial = 0;
|
||||
unsigned int i = 0;
|
||||
@@ -111,23 +165,50 @@ void recv_msg_userauth_failure() {
|
||||
TRACE(("<- MSG_USERAUTH_FAILURE"))
|
||||
TRACE(("enter recv_msg_userauth_failure"))
|
||||
|
||||
if (cli_ses.state != USERAUTH_REQ_SENT) {
|
||||
/* Perhaps we should be more fatal? */
|
||||
TRACE(("But we didn't send a userauth request!!!!!!"))
|
||||
if (ses.authstate.authdone) {
|
||||
TRACE(("leave recv_msg_userauth_failure, already authdone."))
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CLI_PUBKEY_AUTH
|
||||
/* If it was a pubkey auth request, we should cross that key
|
||||
* off the list. */
|
||||
if (cli_ses.lastauthtype == AUTH_TYPE_PUBKEY) {
|
||||
cli_pubkeyfail();
|
||||
if (cli_ses.state != USERAUTH_REQ_SENT) {
|
||||
/* Perhaps we should be more fatal? */
|
||||
dropbear_exit("Unexpected userauth failure");
|
||||
}
|
||||
|
||||
/* When DROPBEAR_CLI_IMMEDIATE_AUTH is set there will be an initial response for
|
||||
the "none" auth request, and then a response to the immediate auth request.
|
||||
We need to be careful handling them. */
|
||||
if (cli_ses.ignore_next_auth_response) {
|
||||
cli_ses.state = USERAUTH_REQ_SENT;
|
||||
cli_ses.ignore_next_auth_response = 0;
|
||||
TRACE(("leave recv_msg_userauth_failure, ignored response, state set to USERAUTH_REQ_SENT"));
|
||||
return;
|
||||
} else {
|
||||
#if DROPBEAR_CLI_PUBKEY_AUTH
|
||||
/* If it was a pubkey auth request, we should cross that key
|
||||
* off the list. */
|
||||
if (cli_ses.lastauthtype == AUTH_TYPE_PUBKEY) {
|
||||
cli_pubkeyfail();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DROPBEAR_CLI_INTERACT_AUTH
|
||||
/* If we get a failure message for keyboard interactive without
|
||||
* receiving any request info packet, then we don't bother trying
|
||||
* keyboard interactive again */
|
||||
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.state = USERAUTH_FAIL_RCVD;
|
||||
cli_ses.lastauthtype = AUTH_TYPE_NONE;
|
||||
}
|
||||
|
||||
methods = buf_getstring(ses.payload, &methlen);
|
||||
|
||||
partial = buf_getbyte(ses.payload);
|
||||
partial = buf_getbool(ses.payload);
|
||||
|
||||
if (partial) {
|
||||
dropbear_log(LOG_INFO, "Authentication partially succeeded, more attempts required");
|
||||
@@ -151,13 +232,19 @@ void recv_msg_userauth_failure() {
|
||||
for (i = 0; i <= methlen; i++) {
|
||||
if (methods[i] == '\0') {
|
||||
TRACE(("auth method '%s'", tok))
|
||||
#ifdef ENABLE_CLI_PUBKEY_AUTH
|
||||
#if DROPBEAR_CLI_PUBKEY_AUTH
|
||||
if (strncmp(AUTH_METHOD_PUBKEY, tok,
|
||||
AUTH_METHOD_PUBKEY_LEN) == 0) {
|
||||
ses.authstate.authtypes |= AUTH_TYPE_PUBKEY;
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_CLI_PASSWORD_AUTH
|
||||
#if DROPBEAR_CLI_INTERACT_AUTH
|
||||
if (strncmp(AUTH_METHOD_INTERACT, tok,
|
||||
AUTH_METHOD_INTERACT_LEN) == 0) {
|
||||
ses.authstate.authtypes |= AUTH_TYPE_INTERACT;
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_CLI_PASSWORD_AUTH
|
||||
if (strncmp(AUTH_METHOD_PASSWORD, tok,
|
||||
AUTH_METHOD_PASSWORD_LEN) == 0) {
|
||||
ses.authstate.authtypes |= AUTH_TYPE_PASSWORD;
|
||||
@@ -170,43 +257,103 @@ void recv_msg_userauth_failure() {
|
||||
}
|
||||
|
||||
m_free(methods);
|
||||
|
||||
cli_ses.state = USERAUTH_FAIL_RCVD;
|
||||
|
||||
TRACE(("leave recv_msg_userauth_failure"))
|
||||
}
|
||||
|
||||
void recv_msg_userauth_success() {
|
||||
TRACE(("received msg_userauth_success"))
|
||||
/* This function can validly get called multiple times
|
||||
if DROPBEAR_CLI_IMMEDIATE_AUTH is set */
|
||||
|
||||
DEBUG1(("received msg_userauth_success"))
|
||||
if (cli_opts.disable_trivial_auth && cli_ses.is_trivial_auth) {
|
||||
dropbear_exit("trivial authentication not allowed");
|
||||
}
|
||||
/* 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;
|
||||
|
||||
#if DROPBEAR_CLI_PUBKEY_AUTH
|
||||
cli_auth_pubkey_cleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
void cli_auth_try() {
|
||||
int cli_auth_try() {
|
||||
|
||||
TRACE(("enter cli_auth_try"))
|
||||
int finished = 0;
|
||||
TRACE(("enter cli_auth_try"))
|
||||
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
/* XXX We hardcode that we try a pubkey first */
|
||||
#ifdef ENABLE_CLI_PUBKEY_AUTH
|
||||
/* Order to try is pubkey, interactive, password.
|
||||
* As soon as "finished" is set for one, we don't do any more. */
|
||||
#if DROPBEAR_CLI_PUBKEY_AUTH
|
||||
if (ses.authstate.authtypes & AUTH_TYPE_PUBKEY) {
|
||||
finished = cli_auth_pubkey();
|
||||
cli_ses.lastauthtype = AUTH_TYPE_PUBKEY;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CLI_PASSWORD_AUTH
|
||||
if (!finished && ses.authstate.authtypes & AUTH_TYPE_PASSWORD) {
|
||||
finished = cli_auth_password();
|
||||
cli_ses.lastauthtype = AUTH_TYPE_PASSWORD;
|
||||
#if DROPBEAR_CLI_INTERACT_AUTH
|
||||
if (!finished && (ses.authstate.authtypes & AUTH_TYPE_INTERACT)) {
|
||||
if (ses.keys->trans.algo_crypt->cipherdesc == NULL) {
|
||||
fprintf(stderr, "Sorry, I won't let you use interactive auth unencrypted.\n");
|
||||
} else {
|
||||
if (!cli_ses.auth_interact_failed) {
|
||||
cli_auth_interactive();
|
||||
cli_ses.lastauthtype = AUTH_TYPE_INTERACT;
|
||||
finished = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!finished) {
|
||||
dropbear_exit("No auth methods could be used.");
|
||||
#if DROPBEAR_CLI_PASSWORD_AUTH
|
||||
if (!finished && (ses.authstate.authtypes & AUTH_TYPE_PASSWORD)) {
|
||||
if (ses.keys->trans.algo_crypt->cipherdesc == NULL) {
|
||||
fprintf(stderr, "Sorry, I won't let you use password auth unencrypted.\n");
|
||||
} else {
|
||||
cli_auth_password();
|
||||
finished = 1;
|
||||
cli_ses.lastauthtype = AUTH_TYPE_PASSWORD;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TRACE(("leave cli_auth_try"))
|
||||
TRACE(("cli_auth_try lastauthtype %d", cli_ses.lastauthtype))
|
||||
|
||||
if (finished) {
|
||||
TRACE(("leave cli_auth_try success"))
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
TRACE(("leave cli_auth_try failure"))
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
#if DROPBEAR_CLI_PASSWORD_AUTH || DROPBEAR_CLI_INTERACT_AUTH
|
||||
/* A helper for getpass() that exits if the user cancels. The returned
|
||||
* password is statically allocated by getpass() */
|
||||
char* getpass_or_cancel(const char* prompt)
|
||||
{
|
||||
char* password = NULL;
|
||||
|
||||
#if DROPBEAR_USE_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;
|
||||
}
|
||||
#endif
|
||||
|
||||
176
cli-authinteract.c
Normal file
176
cli-authinteract.c
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
#if DROPBEAR_CLI_INTERACT_AUTH
|
||||
|
||||
static char* get_response(char* prompt)
|
||||
{
|
||||
FILE* tty = NULL;
|
||||
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 = m_strdup("");
|
||||
} else {
|
||||
unsigned int buflen = strlen(buf);
|
||||
/* fgets includes newlines */
|
||||
if (buflen > 0 && buf[buflen-1] == '\n')
|
||||
buf[buflen-1] = '\0';
|
||||
response = m_strdup(buf);
|
||||
}
|
||||
|
||||
m_burn(buf, sizeof(buf));
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
void recv_msg_userauth_info_request() {
|
||||
|
||||
char *name = NULL;
|
||||
char *instruction = NULL;
|
||||
unsigned int num_prompts = 0;
|
||||
unsigned int i;
|
||||
|
||||
char *prompt = NULL;
|
||||
unsigned int echo = 0;
|
||||
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;
|
||||
cli_ses.is_trivial_auth = 0;
|
||||
prompt = buf_getstring(ses.payload, NULL);
|
||||
cleantext(prompt);
|
||||
|
||||
echo = buf_getbool(ses.payload);
|
||||
|
||||
if (!echo) {
|
||||
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(prompt);
|
||||
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 /* DROPBEAR_CLI_INTERACT_AUTH */
|
||||
@@ -29,16 +29,18 @@
|
||||
#include "ssh.h"
|
||||
#include "runopts.h"
|
||||
|
||||
#ifdef ENABLE_CLI_PASSWORD_AUTH
|
||||
#if DROPBEAR_CLI_PASSWORD_AUTH
|
||||
|
||||
#ifdef ENABLE_CLI_ASKPASS_HELPER
|
||||
#if DROPBEAR_CLI_ASKPASS_HELPER
|
||||
/* Returns 1 if we want to use the askpass program, 0 otherwise */
|
||||
static int want_askpass()
|
||||
{
|
||||
char* askpass_prog = NULL;
|
||||
|
||||
askpass_prog = getenv("SSH_ASKPASS");
|
||||
return askpass_prog && !isatty(STDIN_FILENO) && getenv("DISPLAY");
|
||||
return askpass_prog &&
|
||||
((!isatty(STDIN_FILENO) && getenv("DISPLAY") )
|
||||
|| getenv("SSH_ASKPASS_ALWAYS"));
|
||||
}
|
||||
|
||||
/* returns a statically allocated password from a helper app, or NULL
|
||||
@@ -111,34 +113,40 @@ static char *gui_getpass(const char *prompt) {
|
||||
TRACE(("leave gui_getpass"))
|
||||
return(buf);
|
||||
}
|
||||
#endif /* ENABLE_CLI_ASKPASS_HELPER */
|
||||
#endif /* DROPBEAR_CLI_ASKPASS_HELPER */
|
||||
|
||||
int cli_auth_password() {
|
||||
void cli_auth_password() {
|
||||
|
||||
char* password = NULL;
|
||||
char prompt[80];
|
||||
|
||||
TRACE(("enter cli_auth_password"))
|
||||
DEBUG1(("enter cli_auth_password"))
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
#ifdef ENABLE_CLI_ASKPASS_HELPER
|
||||
snprintf(prompt, sizeof(prompt), "%s@%s's password: ",
|
||||
cli_opts.username, cli_opts.remotehost);
|
||||
#if DROPBEAR_CLI_ASKPASS_HELPER
|
||||
if (want_askpass())
|
||||
password = gui_getpass("Password: ");
|
||||
else
|
||||
{
|
||||
password = gui_getpass(prompt);
|
||||
if (!password) {
|
||||
dropbear_exit("No password");
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
password = getpass("Password: ");
|
||||
|
||||
if (password == NULL)
|
||||
return 0;
|
||||
{
|
||||
password = getpass_or_cancel(prompt);
|
||||
}
|
||||
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);
|
||||
|
||||
buf_putstring(ses.writepayload, cli_opts.username,
|
||||
strlen(cli_opts.username));
|
||||
|
||||
buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
|
||||
buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
|
||||
SSH_SERVICE_CONNECTION_LEN);
|
||||
|
||||
buf_putstring(ses.writepayload, AUTH_METHOD_PASSWORD,
|
||||
buf_putstring(ses.writepayload, AUTH_METHOD_PASSWORD,
|
||||
AUTH_METHOD_PASSWORD_LEN);
|
||||
|
||||
buf_putbyte(ses.writepayload, 0); /* FALSE - so says the spec */
|
||||
@@ -147,9 +155,7 @@ int cli_auth_password() {
|
||||
|
||||
encrypt_packet();
|
||||
m_burn(password, strlen(password));
|
||||
|
||||
cli_ses.is_trivial_auth = 0;
|
||||
TRACE(("leave cli_auth_password"))
|
||||
return 1; /* Password auth can always be tried */
|
||||
|
||||
}
|
||||
#endif /* ENABLE_CLI_PASSWORD_AUTH */
|
||||
#endif /* DROPBEAR_CLI_PASSWORD_AUTH */
|
||||
|
||||
202
cli-authpubkey.c
202
cli-authpubkey.c
@@ -30,48 +30,44 @@
|
||||
#include "ssh.h"
|
||||
#include "runopts.h"
|
||||
#include "auth.h"
|
||||
#include "agentfwd.h"
|
||||
|
||||
#ifdef ENABLE_CLI_PUBKEY_AUTH
|
||||
static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign);
|
||||
#if DROPBEAR_CLI_PUBKEY_AUTH
|
||||
static void send_msg_userauth_pubkey(sign_key *key, enum signature_type sigtype, int realsign);
|
||||
|
||||
/* Called when we receive a SSH_MSG_USERAUTH_FAILURE for a pubkey request.
|
||||
* We use it to remove the key we tried from the list */
|
||||
void cli_pubkeyfail() {
|
||||
|
||||
struct PubkeyList *keyitem;
|
||||
struct PubkeyList **previtem;
|
||||
|
||||
TRACE(("enter cli_pubkeyfail"))
|
||||
previtem = &cli_opts.pubkeys;
|
||||
|
||||
/* Find the key we failed with, and remove it */
|
||||
for (keyitem = cli_opts.pubkeys; keyitem != NULL; keyitem = keyitem->next) {
|
||||
if (keyitem == cli_ses.lastpubkey) {
|
||||
*previtem = keyitem->next;
|
||||
m_list_elem *iter;
|
||||
for (iter = cli_opts.privkeys->first; iter; iter = iter->next) {
|
||||
sign_key *iter_key = (sign_key*)iter->item;
|
||||
|
||||
if (iter_key == cli_ses.lastprivkey)
|
||||
{
|
||||
/* found the failing key */
|
||||
list_remove(iter);
|
||||
sign_key_free(iter_key);
|
||||
cli_ses.lastprivkey = NULL;
|
||||
return;
|
||||
}
|
||||
previtem = &keyitem;
|
||||
}
|
||||
|
||||
sign_key_free(cli_ses.lastpubkey->key); /* It won't be used again */
|
||||
m_free(cli_ses.lastpubkey);
|
||||
|
||||
TRACE(("leave cli_pubkeyfail"))
|
||||
}
|
||||
|
||||
void recv_msg_userauth_pk_ok() {
|
||||
|
||||
struct PubkeyList *keyitem;
|
||||
buffer* keybuf;
|
||||
m_list_elem *iter;
|
||||
buffer* keybuf = NULL;
|
||||
char* algotype = NULL;
|
||||
unsigned int algolen;
|
||||
int keytype;
|
||||
enum signkey_type keytype;
|
||||
enum signature_type sigtype;
|
||||
unsigned int remotelen;
|
||||
|
||||
TRACE(("enter recv_msg_userauth_pk_ok"))
|
||||
|
||||
algotype = buf_getstring(ses.payload, &algolen);
|
||||
keytype = signkey_type_from_name(algotype, algolen);
|
||||
TRACE(("recv_msg_userauth_pk_ok: type %d", keytype))
|
||||
sigtype = signature_type_from_name(algotype, algolen);
|
||||
keytype = signkey_type_from_signature(sigtype);
|
||||
TRACE(("recv_msg_userauth_pk_ok: type %d", sigtype))
|
||||
m_free(algotype);
|
||||
|
||||
keybuf = buf_new(MAX_PUBKEY_SIZE);
|
||||
@@ -80,9 +76,9 @@ void recv_msg_userauth_pk_ok() {
|
||||
|
||||
/* Iterate through our keys, find which one it was that matched, and
|
||||
* send a real request with that key */
|
||||
for (keyitem = cli_opts.pubkeys; keyitem != NULL; keyitem = keyitem->next) {
|
||||
|
||||
if (keyitem->type != keytype) {
|
||||
for (iter = cli_opts.privkeys->first; iter; iter = iter->next) {
|
||||
sign_key *key = (sign_key*)iter->item;
|
||||
if (key->type != keytype) {
|
||||
/* Types differed */
|
||||
TRACE(("types differed"))
|
||||
continue;
|
||||
@@ -90,7 +86,7 @@ void recv_msg_userauth_pk_ok() {
|
||||
|
||||
/* Now we compare the contents of the key */
|
||||
keybuf->pos = keybuf->len = 0;
|
||||
buf_put_pub_key(keybuf, keyitem->key, keytype);
|
||||
buf_put_pub_key(keybuf, key, keytype);
|
||||
buf_setpos(keybuf, 0);
|
||||
buf_incrpos(keybuf, 4); /* first int is the length of the remainder (ie
|
||||
remotelen) which has already been taken from
|
||||
@@ -112,27 +108,46 @@ void recv_msg_userauth_pk_ok() {
|
||||
/* Success */
|
||||
break;
|
||||
}
|
||||
buf_free(keybuf);
|
||||
|
||||
if (keyitem != NULL) {
|
||||
if (iter != NULL) {
|
||||
TRACE(("matching key"))
|
||||
/* XXX TODO: if it's an encrypted key, here we ask for their
|
||||
* password */
|
||||
send_msg_userauth_pubkey(keyitem->key, keytype, 1);
|
||||
send_msg_userauth_pubkey((sign_key*)iter->item, sigtype, 1);
|
||||
} else {
|
||||
TRACE(("That was whacky. We got told that a key was valid, but it didn't match our list. Sounds like dodgy code on Dropbear's part"))
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
static void cli_buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype,
|
||||
const buffer *data_buf) {
|
||||
#if DROPBEAR_CLI_AGENTFWD
|
||||
/* TODO: rsa-sha256 agent */
|
||||
if (key->source == SIGNKEY_SOURCE_AGENT) {
|
||||
/* Format the agent signature ourselves, as buf_put_sign would. */
|
||||
buffer *sigblob;
|
||||
sigblob = buf_new(MAX_PUBKEY_SIZE);
|
||||
agent_buf_sign(sigblob, key, data_buf, sigtype);
|
||||
buf_putbufstring(buf, sigblob);
|
||||
buf_free(sigblob);
|
||||
} else
|
||||
#endif /* DROPBEAR_CLI_AGENTFWD */
|
||||
{
|
||||
buf_put_sign(buf, key, sigtype, data_buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void send_msg_userauth_pubkey(sign_key *key, enum signature_type sigtype, int realsign) {
|
||||
|
||||
const char *algoname = NULL;
|
||||
int algolen;
|
||||
unsigned int algolen;
|
||||
buffer* sigbuf = NULL;
|
||||
enum signkey_type keytype = signkey_type_from_signature(sigtype);
|
||||
|
||||
TRACE(("enter send_msg_userauth_pubkey"))
|
||||
DEBUG1(("enter send_msg_userauth_pubkey %s", signature_name_from_type(sigtype, NULL)))
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);
|
||||
@@ -140,48 +155,137 @@ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
|
||||
buf_putstring(ses.writepayload, cli_opts.username,
|
||||
strlen(cli_opts.username));
|
||||
|
||||
buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
|
||||
buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
|
||||
SSH_SERVICE_CONNECTION_LEN);
|
||||
|
||||
buf_putstring(ses.writepayload, AUTH_METHOD_PUBKEY,
|
||||
buf_putstring(ses.writepayload, AUTH_METHOD_PUBKEY,
|
||||
AUTH_METHOD_PUBKEY_LEN);
|
||||
|
||||
buf_putbyte(ses.writepayload, realsign);
|
||||
|
||||
algoname = signkey_name_from_type(type, &algolen);
|
||||
|
||||
algoname = signature_name_from_type(sigtype, &algolen);
|
||||
buf_putstring(ses.writepayload, algoname, algolen);
|
||||
buf_put_pub_key(ses.writepayload, key, type);
|
||||
buf_put_pub_key(ses.writepayload, key, keytype);
|
||||
|
||||
if (realsign) {
|
||||
TRACE(("realsign"))
|
||||
/* We put the signature as well - this contains string(session id), then
|
||||
* the contents of the write payload to this point */
|
||||
sigbuf = buf_new(4 + SHA1_HASH_SIZE + ses.writepayload->len);
|
||||
buf_putstring(sigbuf, ses.session_id, SHA1_HASH_SIZE);
|
||||
sigbuf = buf_new(4 + ses.session_id->len + ses.writepayload->len);
|
||||
buf_putbufstring(sigbuf, ses.session_id);
|
||||
buf_putbytes(sigbuf, ses.writepayload->data, ses.writepayload->len);
|
||||
buf_put_sign(ses.writepayload, key, type, sigbuf->data, sigbuf->len);
|
||||
cli_buf_put_sign(ses.writepayload, key, sigtype, sigbuf);
|
||||
buf_free(sigbuf); /* Nothing confidential in the buffer */
|
||||
cli_ses.is_trivial_auth = 0;
|
||||
}
|
||||
|
||||
encrypt_packet();
|
||||
TRACE(("leave send_msg_userauth_pubkey"))
|
||||
}
|
||||
|
||||
/* Returns 1 if a key was tried */
|
||||
int cli_auth_pubkey() {
|
||||
|
||||
enum signature_type sigtype = DROPBEAR_SIGNATURE_NONE;
|
||||
TRACE(("enter cli_auth_pubkey"))
|
||||
|
||||
if (cli_opts.pubkeys != NULL) {
|
||||
#if DROPBEAR_CLI_AGENTFWD
|
||||
if (!cli_opts.agent_keys_loaded) {
|
||||
/* get the list of available keys from the agent */
|
||||
cli_load_agent_keys(cli_opts.privkeys);
|
||||
cli_opts.agent_keys_loaded = 1;
|
||||
TRACE(("cli_auth_pubkey: agent keys loaded"))
|
||||
}
|
||||
#endif
|
||||
|
||||
/* iterate through privkeys to remove ones not allowed in server-sig-algs */
|
||||
while (cli_opts.privkeys->first) {
|
||||
sign_key * key = (sign_key*)cli_opts.privkeys->first->item;
|
||||
if (cli_ses.server_sig_algs) {
|
||||
#if DROPBEAR_RSA
|
||||
if (key->type == DROPBEAR_SIGNKEY_RSA) {
|
||||
#if DROPBEAR_RSA_SHA256
|
||||
if (buf_has_algo(cli_ses.server_sig_algs, SSH_SIGNATURE_RSA_SHA256)
|
||||
== DROPBEAR_SUCCESS) {
|
||||
sigtype = DROPBEAR_SIGNATURE_RSA_SHA256;
|
||||
TRACE(("server-sig-algs allows rsa sha256"))
|
||||
break;
|
||||
}
|
||||
#endif /* DROPBEAR_RSA_SHA256 */
|
||||
#if DROPBEAR_RSA_SHA1
|
||||
if (buf_has_algo(cli_ses.server_sig_algs, SSH_SIGNKEY_RSA)
|
||||
== DROPBEAR_SUCCESS) {
|
||||
sigtype = DROPBEAR_SIGNATURE_RSA_SHA1;
|
||||
TRACE(("server-sig-algs allows rsa sha1"))
|
||||
break;
|
||||
}
|
||||
#endif /* DROPBEAR_RSA_SHA256 */
|
||||
} else
|
||||
#endif /* DROPBEAR_RSA */
|
||||
{
|
||||
/* Not RSA */
|
||||
const char *name = NULL;
|
||||
sigtype = signature_type_from_signkey(key->type);
|
||||
name = signature_name_from_type(sigtype, NULL);
|
||||
if (buf_has_algo(cli_ses.server_sig_algs, name)
|
||||
== DROPBEAR_SUCCESS) {
|
||||
TRACE(("server-sig-algs allows %s", name))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* No match, skip this key */
|
||||
TRACE(("server-sig-algs no match keytype %d, skipping", key->type))
|
||||
key = list_remove(cli_opts.privkeys->first);
|
||||
sign_key_free(key);
|
||||
continue;
|
||||
} else {
|
||||
/* Server didn't provide a server-sig-algs list, we'll
|
||||
assume all except rsa-sha256 are OK. */
|
||||
#if DROPBEAR_RSA
|
||||
if (key->type == DROPBEAR_SIGNKEY_RSA) {
|
||||
#if DROPBEAR_RSA_SHA1
|
||||
sigtype = DROPBEAR_SIGNATURE_RSA_SHA1;
|
||||
TRACE(("no server-sig-algs, using rsa sha1"))
|
||||
break;
|
||||
#else
|
||||
/* only support rsa-sha256, skip this key */
|
||||
TRACE(("no server-sig-algs, skipping rsa sha256"))
|
||||
key = list_remove(cli_opts.privkeys->first);
|
||||
sign_key_free(key);
|
||||
continue;
|
||||
#endif
|
||||
} /* key->type == DROPBEAR_SIGNKEY_RSA */
|
||||
#endif /* DROPBEAR_RSA */
|
||||
sigtype = signature_type_from_signkey(key->type);
|
||||
TRACE(("no server-sig-algs, using key"))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cli_opts.privkeys->first) {
|
||||
sign_key * key = (sign_key*)cli_opts.privkeys->first->item;
|
||||
/* Send a trial request */
|
||||
send_msg_userauth_pubkey(cli_opts.pubkeys->key,
|
||||
cli_opts.pubkeys->type, 0);
|
||||
cli_ses.lastpubkey = cli_opts.pubkeys;
|
||||
send_msg_userauth_pubkey(key, sigtype, 0);
|
||||
cli_ses.lastprivkey = key;
|
||||
TRACE(("leave cli_auth_pubkey-success"))
|
||||
return 1;
|
||||
} else {
|
||||
/* no more keys left */
|
||||
TRACE(("leave cli_auth_pubkey-failure"))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void cli_auth_pubkey_cleanup() {
|
||||
|
||||
#if DROPBEAR_CLI_AGENTFWD
|
||||
m_close(cli_opts.agent_fd);
|
||||
cli_opts.agent_fd = -1;
|
||||
#endif
|
||||
|
||||
while (cli_opts.privkeys->first) {
|
||||
sign_key * key = list_remove(cli_opts.privkeys->first);
|
||||
sign_key_free(key);
|
||||
}
|
||||
}
|
||||
#endif /* Pubkey auth */
|
||||
|
||||
@@ -33,18 +33,12 @@
|
||||
/* We receive channel data - only used by the client chansession code*/
|
||||
void recv_msg_channel_extended_data() {
|
||||
|
||||
unsigned int chan;
|
||||
struct Channel *channel;
|
||||
unsigned int datatype;
|
||||
|
||||
TRACE(("enter recv_msg_channel_extended_data"))
|
||||
|
||||
chan = buf_getint(ses.payload);
|
||||
channel = getchannel(chan);
|
||||
|
||||
if (channel == NULL) {
|
||||
dropbear_exit("Unknown channel");
|
||||
}
|
||||
channel = getchannel();
|
||||
|
||||
if (channel->type != &clichansess) {
|
||||
TRACE(("leave recv_msg_channel_extended_data: chantype is wrong"))
|
||||
|
||||
@@ -33,73 +33,63 @@
|
||||
#include "runopts.h"
|
||||
#include "termcodes.h"
|
||||
#include "chansession.h"
|
||||
#include "agentfwd.h"
|
||||
|
||||
static void cli_closechansess(struct Channel *channel);
|
||||
static void cli_closechansess(const struct Channel *channel);
|
||||
static int cli_initchansess(struct Channel *channel);
|
||||
static void cli_chansessreq(struct Channel *channel);
|
||||
static void send_chansess_pty_req(const struct Channel *channel);
|
||||
static void send_chansess_shell_req(const struct Channel *channel);
|
||||
static void cli_escape_handler(const struct Channel *channel, const unsigned char* buf, int *len);
|
||||
static int cli_init_netcat(struct Channel *channel);
|
||||
|
||||
static void 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();
|
||||
static void cli_tty_setup(void);
|
||||
|
||||
const struct ChanType clichansess = {
|
||||
0, /* sepfds */
|
||||
"session", /* name */
|
||||
cli_initchansess, /* inithandler */
|
||||
NULL, /* checkclosehandler */
|
||||
cli_chansessreq, /* reqhandler */
|
||||
cli_closechansess, /* closehandler */
|
||||
NULL, /* cleanup */
|
||||
};
|
||||
|
||||
static void cli_chansessreq(struct Channel *channel) {
|
||||
|
||||
unsigned char* type = NULL;
|
||||
char* type = NULL;
|
||||
int wantreply;
|
||||
|
||||
TRACE(("enter cli_chansessreq"))
|
||||
|
||||
type = buf_getstring(ses.payload, NULL);
|
||||
wantreply = buf_getbyte(ses.payload);
|
||||
wantreply = buf_getbool(ses.payload);
|
||||
|
||||
if (strcmp(type, "exit-status") != 0) {
|
||||
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);
|
||||
if (wantreply) {
|
||||
send_msg_channel_failure(channel);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* We'll just trust what they tell us */
|
||||
cli_ses.retval = buf_getint(ses.payload);
|
||||
TRACE(("got exit-status of '%d'", cli_ses.retval))
|
||||
|
||||
out:
|
||||
m_free(type);
|
||||
}
|
||||
|
||||
|
||||
/* If the main session goes, we close it up */
|
||||
static void cli_closechansess(struct Channel *UNUSED(channel)) {
|
||||
static void cli_closechansess(const struct Channel *UNUSED(channel)) {
|
||||
cli_tty_cleanup(); /* Restore tty modes etc */
|
||||
|
||||
/* This channel hasn't gone yet, so we have > 1 */
|
||||
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:
|
||||
@@ -162,8 +152,6 @@ void cli_tty_cleanup() {
|
||||
|
||||
static void put_termcodes() {
|
||||
|
||||
TRACE(("enter put_termcodes"))
|
||||
|
||||
struct termios tio;
|
||||
unsigned int sshcode;
|
||||
const struct TermCode *termcode;
|
||||
@@ -172,6 +160,8 @@ static void put_termcodes() {
|
||||
|
||||
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 */
|
||||
@@ -280,13 +270,13 @@ void cli_chansess_winchange() {
|
||||
cli_ses.winchange = 0;
|
||||
}
|
||||
|
||||
static void send_chansess_pty_req(struct Channel *channel) {
|
||||
static void send_chansess_pty_req(const struct Channel *channel) {
|
||||
|
||||
unsigned char* term = NULL;
|
||||
char* term = NULL;
|
||||
|
||||
TRACE(("enter send_chansess_pty_req"))
|
||||
|
||||
start_channel_request(channel, "pty-req");
|
||||
start_send_channel_request(channel, "pty-req");
|
||||
|
||||
/* Don't want replies */
|
||||
buf_putbyte(ses.writepayload, 0);
|
||||
@@ -308,24 +298,28 @@ static void send_chansess_pty_req(struct Channel *channel) {
|
||||
|
||||
/* Set up a window-change handler */
|
||||
if (signal(SIGWINCH, sigwinch_handler) == SIG_ERR) {
|
||||
dropbear_exit("signal error");
|
||||
dropbear_exit("Signal error");
|
||||
}
|
||||
TRACE(("leave send_chansess_pty_req"))
|
||||
}
|
||||
|
||||
static void send_chansess_shell_req(struct Channel *channel) {
|
||||
static void send_chansess_shell_req(const struct Channel *channel) {
|
||||
|
||||
unsigned char* reqtype = NULL;
|
||||
char* reqtype = NULL;
|
||||
|
||||
TRACE(("enter send_chansess_shell_req"))
|
||||
|
||||
if (cli_opts.cmd) {
|
||||
reqtype = "exec";
|
||||
if (cli_opts.is_subsystem) {
|
||||
reqtype = "subsystem";
|
||||
} else {
|
||||
reqtype = "exec";
|
||||
}
|
||||
} else {
|
||||
reqtype = "shell";
|
||||
}
|
||||
|
||||
start_channel_request(channel, reqtype);
|
||||
start_send_channel_request(channel, reqtype);
|
||||
|
||||
/* XXX TODO */
|
||||
buf_putbyte(ses.writepayload, 0); /* Don't want replies */
|
||||
@@ -337,37 +331,92 @@ static void send_chansess_shell_req(struct Channel *channel) {
|
||||
TRACE(("leave send_chansess_shell_req"))
|
||||
}
|
||||
|
||||
static int cli_initchansess(struct Channel *channel) {
|
||||
|
||||
|
||||
channel->infd = STDOUT_FILENO;
|
||||
/* 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->outfd = STDIN_FILENO;
|
||||
channel->readfd = STDIN_FILENO;
|
||||
setnonblocking(STDIN_FILENO);
|
||||
|
||||
channel->errfd = STDERR_FILENO;
|
||||
setnonblocking(STDERR_FILENO);
|
||||
|
||||
channel->extrabuf = cbuf_new(RECV_MAXWINDOW);
|
||||
channel->extrabuf = cbuf_new(opts.recv_window);
|
||||
channel->bidir_fd = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cli_init_netcat(struct Channel *channel) {
|
||||
return cli_init_stdpipe_sess(channel);
|
||||
}
|
||||
|
||||
static int cli_initchansess(struct Channel *channel) {
|
||||
|
||||
cli_init_stdpipe_sess(channel);
|
||||
|
||||
#if DROPBEAR_CLI_AGENTFWD
|
||||
if (cli_opts.agent_fwd) {
|
||||
cli_setup_agent(channel);
|
||||
}
|
||||
#endif
|
||||
if (cli_opts.wantpty) {
|
||||
send_chansess_pty_req(channel);
|
||||
channel->prio = DROPBEAR_PRIO_LOWDELAY;
|
||||
}
|
||||
|
||||
send_chansess_shell_req(channel);
|
||||
|
||||
if (cli_opts.wantpty) {
|
||||
cli_tty_setup();
|
||||
channel->read_mangler = cli_escape_handler;
|
||||
cli_ses.last_char = '\r';
|
||||
}
|
||||
|
||||
return 0; /* Success */
|
||||
|
||||
}
|
||||
|
||||
#if DROPBEAR_CLI_NETCAT
|
||||
|
||||
static const struct ChanType cli_chan_netcat = {
|
||||
"direct-tcpip",
|
||||
cli_init_netcat, /* inithandler */
|
||||
NULL,
|
||||
NULL,
|
||||
cli_closechansess,
|
||||
NULL,
|
||||
};
|
||||
|
||||
void cli_send_netcat_request() {
|
||||
|
||||
const char* source_host = "127.0.0.1";
|
||||
const int source_port = 22;
|
||||
|
||||
TRACE(("enter cli_send_netcat_request"))
|
||||
cli_opts.wantpty = 0;
|
||||
|
||||
if (send_msg_channel_open_init(STDIN_FILENO, &cli_chan_netcat)
|
||||
== DROPBEAR_FAILURE) {
|
||||
dropbear_exit("Couldn't open initial channel");
|
||||
}
|
||||
|
||||
buf_putstring(ses.writepayload, cli_opts.netcat_host,
|
||||
strlen(cli_opts.netcat_host));
|
||||
buf_putint(ses.writepayload, cli_opts.netcat_port);
|
||||
|
||||
/* originator ip - localhost is accurate enough */
|
||||
buf_putstring(ses.writepayload, source_host, strlen(source_host));
|
||||
buf_putint(ses.writepayload, source_port);
|
||||
|
||||
encrypt_packet();
|
||||
TRACE(("leave cli_send_netcat_request"))
|
||||
}
|
||||
#endif
|
||||
|
||||
void cli_send_chansess_request() {
|
||||
|
||||
TRACE(("enter cli_send_chansess_request"))
|
||||
|
||||
if (send_msg_channel_open_init(STDIN_FILENO, &clichansess)
|
||||
== DROPBEAR_FAILURE) {
|
||||
dropbear_exit("Couldn't open initial channel");
|
||||
@@ -378,3 +427,58 @@ void cli_send_chansess_request() {
|
||||
TRACE(("leave cli_send_chansess_request"))
|
||||
|
||||
}
|
||||
|
||||
/* returns 1 if the character should be consumed, 0 to pass through */
|
||||
static int
|
||||
do_escape(unsigned char c) {
|
||||
switch (c) {
|
||||
case '.':
|
||||
dropbear_exit("Terminated");
|
||||
return 1;
|
||||
case 0x1a:
|
||||
/* ctrl-z */
|
||||
cli_tty_cleanup();
|
||||
kill(getpid(), SIGTSTP);
|
||||
/* after continuation */
|
||||
cli_tty_setup();
|
||||
cli_ses.winchange = 1;
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void cli_escape_handler(const struct Channel* UNUSED(channel), const unsigned char* buf, int *len) {
|
||||
char c;
|
||||
int skip_char = 0;
|
||||
|
||||
/* only handle escape characters if they are read one at a time. simplifies
|
||||
the code and avoids nasty people putting ~. at the start of a line to paste */
|
||||
if (*len != 1) {
|
||||
cli_ses.last_char = 0x0;
|
||||
return;
|
||||
}
|
||||
|
||||
c = buf[0];
|
||||
|
||||
if (cli_ses.last_char == DROPBEAR_ESCAPE_CHAR) {
|
||||
skip_char = do_escape(c);
|
||||
cli_ses.last_char = 0x0;
|
||||
} else {
|
||||
if (c == DROPBEAR_ESCAPE_CHAR) {
|
||||
if (cli_ses.last_char == '\r') {
|
||||
cli_ses.last_char = DROPBEAR_ESCAPE_CHAR;
|
||||
skip_char = 1;
|
||||
} else {
|
||||
cli_ses.last_char = 0x0;
|
||||
}
|
||||
} else {
|
||||
cli_ses.last_char = c;
|
||||
}
|
||||
}
|
||||
|
||||
if (skip_char) {
|
||||
*len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
373
cli-kex.c
373
cli-kex.c
@@ -33,46 +33,90 @@
|
||||
#include "ssh.h"
|
||||
#include "packet.h"
|
||||
#include "bignum.h"
|
||||
#include "random.h"
|
||||
#include "dbrandom.h"
|
||||
#include "runopts.h"
|
||||
#include "signkey.h"
|
||||
#include "ecc.h"
|
||||
|
||||
|
||||
static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen);
|
||||
static void checkhostkey(const unsigned char* keyblob, unsigned int keybloblen);
|
||||
#define MAX_KNOWNHOSTS_LINE 4500
|
||||
|
||||
void send_msg_kexdh_init() {
|
||||
|
||||
cli_ses.dh_e = (mp_int*)m_malloc(sizeof(mp_int));
|
||||
cli_ses.dh_x = (mp_int*)m_malloc(sizeof(mp_int));
|
||||
m_mp_init_multi(cli_ses.dh_e, cli_ses.dh_x, NULL);
|
||||
|
||||
gen_kexdh_vals(cli_ses.dh_e, cli_ses.dh_x);
|
||||
TRACE(("send_msg_kexdh_init()"))
|
||||
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
if (fuzz.fuzzing && fuzz.skip_kexmaths) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT);
|
||||
buf_putmpint(ses.writepayload, cli_ses.dh_e);
|
||||
switch (ses.newkeys->algo_kex->mode) {
|
||||
#if DROPBEAR_NORMAL_DH
|
||||
case DROPBEAR_KEX_NORMAL_DH:
|
||||
if (ses.newkeys->algo_kex != cli_ses.param_kex_algo
|
||||
|| !cli_ses.dh_param) {
|
||||
if (cli_ses.dh_param) {
|
||||
free_kexdh_param(cli_ses.dh_param);
|
||||
}
|
||||
cli_ses.dh_param = gen_kexdh_param();
|
||||
}
|
||||
buf_putmpint(ses.writepayload, &cli_ses.dh_param->pub);
|
||||
break;
|
||||
#endif
|
||||
#if DROPBEAR_ECDH
|
||||
case DROPBEAR_KEX_ECDH:
|
||||
if (ses.newkeys->algo_kex != cli_ses.param_kex_algo
|
||||
|| !cli_ses.ecdh_param) {
|
||||
if (cli_ses.ecdh_param) {
|
||||
free_kexecdh_param(cli_ses.ecdh_param);
|
||||
}
|
||||
cli_ses.ecdh_param = gen_kexecdh_param();
|
||||
}
|
||||
buf_put_ecc_raw_pubkey_string(ses.writepayload, &cli_ses.ecdh_param->key);
|
||||
break;
|
||||
#endif
|
||||
#if DROPBEAR_CURVE25519
|
||||
case DROPBEAR_KEX_CURVE25519:
|
||||
if (ses.newkeys->algo_kex != cli_ses.param_kex_algo
|
||||
|| !cli_ses.curve25519_param) {
|
||||
if (cli_ses.curve25519_param) {
|
||||
free_kexcurve25519_param(cli_ses.curve25519_param);
|
||||
}
|
||||
cli_ses.curve25519_param = gen_kexcurve25519_param();
|
||||
}
|
||||
buf_putstring(ses.writepayload, cli_ses.curve25519_param->pub, CURVE25519_LEN);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
cli_ses.param_kex_algo = ses.newkeys->algo_kex;
|
||||
encrypt_packet();
|
||||
ses.requirenext = SSH_MSG_KEXDH_REPLY;
|
||||
}
|
||||
|
||||
/* Handle a diffie-hellman key exchange reply. */
|
||||
void recv_msg_kexdh_reply() {
|
||||
|
||||
DEF_MP_INT(dh_f);
|
||||
sign_key *hostkey = NULL;
|
||||
unsigned int type, keybloblen;
|
||||
unsigned int keytype, keybloblen;
|
||||
unsigned char* keyblob = NULL;
|
||||
|
||||
|
||||
TRACE(("enter recv_msg_kexdh_reply"))
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
if (fuzz.fuzzing && fuzz.skip_kexmaths) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
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))
|
||||
keytype = ses.newkeys->algo_hostkey;
|
||||
TRACE(("keytype is %d", keytype))
|
||||
|
||||
hostkey = new_sign_key();
|
||||
keybloblen = buf_getint(ses.payload);
|
||||
@@ -83,24 +127,69 @@ void recv_msg_kexdh_reply() {
|
||||
checkhostkey(keyblob, keybloblen);
|
||||
}
|
||||
|
||||
if (buf_get_pub_key(ses.payload, hostkey, &type) != DROPBEAR_SUCCESS) {
|
||||
if (buf_get_pub_key(ses.payload, hostkey, &keytype) != DROPBEAR_SUCCESS) {
|
||||
TRACE(("failed getting pubkey"))
|
||||
dropbear_exit("Bad KEX packet");
|
||||
}
|
||||
|
||||
if (buf_getmpint(ses.payload, &dh_f) != DROPBEAR_SUCCESS) {
|
||||
TRACE(("failed getting mpint"))
|
||||
dropbear_exit("Bad KEX packet");
|
||||
switch (ses.newkeys->algo_kex->mode) {
|
||||
#if DROPBEAR_NORMAL_DH
|
||||
case DROPBEAR_KEX_NORMAL_DH:
|
||||
{
|
||||
DEF_MP_INT(dh_f);
|
||||
m_mp_init(&dh_f);
|
||||
if (buf_getmpint(ses.payload, &dh_f) != DROPBEAR_SUCCESS) {
|
||||
TRACE(("failed getting mpint"))
|
||||
dropbear_exit("Bad KEX packet");
|
||||
}
|
||||
|
||||
kexdh_comb_key(cli_ses.dh_param, &dh_f, hostkey);
|
||||
mp_clear(&dh_f);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if DROPBEAR_ECDH
|
||||
case DROPBEAR_KEX_ECDH:
|
||||
{
|
||||
buffer *ecdh_qs = buf_getstringbuf(ses.payload);
|
||||
kexecdh_comb_key(cli_ses.ecdh_param, ecdh_qs, hostkey);
|
||||
buf_free(ecdh_qs);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if DROPBEAR_CURVE25519
|
||||
case DROPBEAR_KEX_CURVE25519:
|
||||
{
|
||||
buffer *ecdh_qs = buf_getstringbuf(ses.payload);
|
||||
kexcurve25519_comb_key(cli_ses.curve25519_param, ecdh_qs, hostkey);
|
||||
buf_free(ecdh_qs);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
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 DROPBEAR_NORMAL_DH
|
||||
if (cli_ses.dh_param) {
|
||||
free_kexdh_param(cli_ses.dh_param);
|
||||
cli_ses.dh_param = NULL;
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_ECDH
|
||||
if (cli_ses.ecdh_param) {
|
||||
free_kexecdh_param(cli_ses.ecdh_param);
|
||||
cli_ses.ecdh_param = NULL;
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_CURVE25519
|
||||
if (cli_ses.curve25519_param) {
|
||||
free_kexcurve25519_param(cli_ses.curve25519_param);
|
||||
cli_ses.curve25519_param = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (buf_verify(ses.payload, hostkey, ses.hash, SHA1_HASH_SIZE)
|
||||
!= DROPBEAR_SUCCESS) {
|
||||
cli_ses.param_kex_algo = NULL;
|
||||
if (buf_verify(ses.payload, hostkey, ses.newkeys->algo_signature,
|
||||
ses.hash) != DROPBEAR_SUCCESS) {
|
||||
dropbear_exit("Bad hostkey signature");
|
||||
}
|
||||
|
||||
@@ -112,16 +201,27 @@ void recv_msg_kexdh_reply() {
|
||||
TRACE(("leave recv_msg_kexdh_init"))
|
||||
}
|
||||
|
||||
static void ask_to_confirm(unsigned char* keyblob, unsigned int keybloblen) {
|
||||
static void ask_to_confirm(const unsigned char* keyblob, unsigned int keybloblen,
|
||||
const char* algoname) {
|
||||
|
||||
char* fp = NULL;
|
||||
FILE *tty = NULL;
|
||||
char response = 'z';
|
||||
int response = 'z';
|
||||
|
||||
fp = sign_key_fingerprint(keyblob, keybloblen);
|
||||
fprintf(stderr, "\nHost '%s' is not in the trusted hosts file.\n(fingerprint %s)\nDo you want to continue connecting? (y/n)\n",
|
||||
if (cli_opts.always_accept_key) {
|
||||
dropbear_log(LOG_INFO, "\nHost '%s' key accepted unconditionally.\n(%s fingerprint %s)\n",
|
||||
cli_opts.remotehost,
|
||||
algoname,
|
||||
fp);
|
||||
m_free(fp);
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "\nHost '%s' is not in the trusted hosts file.\n(%s fingerprint %s)\nDo you want to continue connecting? (y/n) ",
|
||||
cli_opts.remotehost,
|
||||
algoname,
|
||||
fp);
|
||||
m_free(fp);
|
||||
|
||||
tty = fopen(_PATH_TTY, "r");
|
||||
if (tty) {
|
||||
@@ -129,72 +229,104 @@ static void ask_to_confirm(unsigned char* keyblob, unsigned int keybloblen) {
|
||||
fclose(tty);
|
||||
} else {
|
||||
response = getc(stdin);
|
||||
/* flush stdin buffer */
|
||||
while ((getchar()) != '\n');
|
||||
}
|
||||
|
||||
if (response == 'y') {
|
||||
m_free(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
dropbear_exit("Didn't validate host key");
|
||||
}
|
||||
|
||||
static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
|
||||
|
||||
static FILE* open_known_hosts_file(int * readonly)
|
||||
{
|
||||
FILE * hostsfile = NULL;
|
||||
char * filename = NULL;
|
||||
FILE *hostsfile = NULL;
|
||||
int readonly = 0;
|
||||
struct passwd *pw = NULL;
|
||||
unsigned int hostlen, algolen;
|
||||
unsigned long len;
|
||||
const char *algoname = NULL;
|
||||
buffer * line = NULL;
|
||||
int ret;
|
||||
char * homedir = NULL;
|
||||
|
||||
pw = getpwuid(getuid());
|
||||
homedir = getenv("HOME");
|
||||
|
||||
if (pw == NULL) {
|
||||
dropbear_exit("Failed to get homedir");
|
||||
}
|
||||
|
||||
len = strlen(pw->pw_dir);
|
||||
filename = m_malloc(len + 18); /* "/.ssh/known_hosts" and null-terminator*/
|
||||
|
||||
snprintf(filename, len+18, "%s/.ssh", pw->pw_dir);
|
||||
/* 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 ~/.ssh: %s",
|
||||
strerror(errno));
|
||||
TRACE(("mkdir didn't work: %s", strerror(errno)))
|
||||
ask_to_confirm(keyblob, keybloblen);
|
||||
goto out; /* only get here on success */
|
||||
if (!homedir) {
|
||||
struct passwd * pw = NULL;
|
||||
pw = getpwuid(getuid());
|
||||
if (pw) {
|
||||
homedir = pw->pw_dir;
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(filename, len+18, "%s/.ssh/known_hosts", pw->pw_dir);
|
||||
hostsfile = fopen(filename, "a+");
|
||||
|
||||
if (hostsfile != NULL) {
|
||||
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 (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)))
|
||||
ask_to_confirm(keyblob, keybloblen);
|
||||
goto out; /* We only get here on success */
|
||||
dropbear_log(LOG_WARNING, "Failed to open %s/.ssh/known_hosts",
|
||||
homedir);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
m_free(filename);
|
||||
return hostsfile;
|
||||
}
|
||||
|
||||
static void checkhostkey(const 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;
|
||||
|
||||
if (cli_opts.no_hostkey_check) {
|
||||
dropbear_log(LOG_INFO, "Caution, skipping hostkey check for %s\n", cli_opts.remotehost);
|
||||
return;
|
||||
}
|
||||
|
||||
algoname = signkey_name_from_type(ses.newkeys->algo_hostkey, &algolen);
|
||||
|
||||
hostsfile = open_known_hosts_file(&readonly);
|
||||
if (!hostsfile) {
|
||||
ask_to_confirm(keyblob, keybloblen, algoname);
|
||||
/* ask_to_confirm will exit upon failure */
|
||||
return;
|
||||
}
|
||||
|
||||
line = buf_new(MAX_KNOWNHOSTS_LINE);
|
||||
hostlen = strlen(cli_opts.remotehost);
|
||||
algoname = signkey_name_from_type(ses.newkeys->algo_hostkey, &algolen);
|
||||
|
||||
do {
|
||||
if (buf_getline(line, hostsfile) == DROPBEAR_FAILURE) {
|
||||
@@ -212,9 +344,8 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
|
||||
}
|
||||
|
||||
/* Compare hostnames */
|
||||
if (strncmp(cli_opts.remotehost, buf_getptr(line, hostlen),
|
||||
if (strncmp(cli_opts.remotehost, (const char *) buf_getptr(line, hostlen),
|
||||
hostlen) != 0) {
|
||||
TRACE(("hosts don't match"))
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -225,7 +356,7 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( strncmp(buf_getptr(line, algolen), algoname, algolen) != 0) {
|
||||
if (strncmp((const char *) buf_getptr(line, algolen), algoname, algolen) != 0) {
|
||||
TRACE(("algo doesn't match"))
|
||||
continue;
|
||||
}
|
||||
@@ -237,19 +368,29 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
|
||||
}
|
||||
|
||||
/* Now we're at the interesting hostkey */
|
||||
ret = cmp_base64_key(keyblob, keybloblen, algoname, algolen, line);
|
||||
ret = cmp_base64_key(keyblob, keybloblen, (const unsigned char *) algoname, algolen,
|
||||
line, &fingerprint);
|
||||
|
||||
if (ret == DROPBEAR_SUCCESS) {
|
||||
/* Good matching key */
|
||||
TRACE(("good matching key"))
|
||||
DEBUG1(("server match %s", fingerprint))
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* The keys didn't match. eep. */
|
||||
/* The keys didn't match. eep. Note that we're "leaking"
|
||||
the fingerprint strings here, but we're exiting anyway */
|
||||
dropbear_exit("\n\n%s host key mismatch for %s !\n"
|
||||
"Fingerprint is %s\n"
|
||||
"Expected %s\n"
|
||||
"If you know that the host key is correct you can\nremove the bad entry from ~/.ssh/known_hosts",
|
||||
algoname,
|
||||
cli_opts.remotehost,
|
||||
sign_key_fingerprint(keyblob, keybloblen),
|
||||
fingerprint ? fingerprint : "UNKNOWN");
|
||||
} while (1); /* keep going 'til something happens */
|
||||
|
||||
/* Key doesn't exist yet */
|
||||
ask_to_confirm(keyblob, keybloblen);
|
||||
ask_to_confirm(keyblob, keybloblen, algoname);
|
||||
|
||||
/* If we get here, they said yes */
|
||||
|
||||
@@ -258,31 +399,67 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
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, (const unsigned char *) cli_opts.remotehost, hostlen);
|
||||
buf_putbyte(line, ' ');
|
||||
buf_putbytes(line, (const unsigned char *) algoname, algolen);
|
||||
buf_putbyte(line, ' ');
|
||||
len = line->size - line->pos;
|
||||
/* 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);
|
||||
}
|
||||
m_free(filename);
|
||||
if (line != NULL) {
|
||||
buf_free(line);
|
||||
}
|
||||
m_free(fingerprint);
|
||||
}
|
||||
|
||||
void recv_msg_ext_info(void) {
|
||||
/* This message is not client-specific in the protocol but Dropbear only handles
|
||||
a server-sent message at present. */
|
||||
unsigned int num_ext;
|
||||
unsigned int i;
|
||||
|
||||
TRACE(("enter recv_msg_ext_info"))
|
||||
|
||||
/* Must be after the first SSH_MSG_NEWKEYS */
|
||||
TRACE(("last %d, donefirst %d, donescond %d", ses.lastpacket, ses.kexstate.donefirstkex, ses.kexstate.donesecondkex))
|
||||
if (!(ses.lastpacket == SSH_MSG_NEWKEYS && !ses.kexstate.donesecondkex)) {
|
||||
TRACE(("leave recv_msg_ext_info: ignoring packet received at the wrong time"))
|
||||
return;
|
||||
}
|
||||
|
||||
num_ext = buf_getint(ses.payload);
|
||||
TRACE(("received SSH_MSG_EXT_INFO with %d items", num_ext))
|
||||
|
||||
for (i = 0; i < num_ext; i++) {
|
||||
unsigned int name_len;
|
||||
char *ext_name = buf_getstring(ses.payload, &name_len);
|
||||
TRACE(("extension %d name '%s'", i, ext_name))
|
||||
if (cli_ses.server_sig_algs == NULL
|
||||
&& name_len == strlen(SSH_SERVER_SIG_ALGS)
|
||||
&& strcmp(ext_name, SSH_SERVER_SIG_ALGS) == 0) {
|
||||
cli_ses.server_sig_algs = buf_getbuf(ses.payload);
|
||||
} else {
|
||||
/* valid extension values could be >MAX_STRING_LEN */
|
||||
buf_eatstring(ses.payload);
|
||||
}
|
||||
m_free(ext_name);
|
||||
}
|
||||
TRACE(("leave recv_msg_ext_info"))
|
||||
}
|
||||
|
||||
137
cli-main.c
137
cli-main.c
@@ -28,85 +28,128 @@
|
||||
#include "dbutil.h"
|
||||
#include "runopts.h"
|
||||
#include "session.h"
|
||||
#include "dbrandom.h"
|
||||
#include "crypto_desc.h"
|
||||
#include "netio.h"
|
||||
#include "fuzz.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);
|
||||
#if DROPBEAR_CLI_PROXYCMD
|
||||
static void cli_proxy_cmd(int *sock_in, int *sock_out, pid_t *pid_out);
|
||||
static void kill_proxy_sighandler(int signo);
|
||||
#endif
|
||||
|
||||
#if defined(DBMULTI_dbclient) || !defined(DROPBEAR_MULTI)
|
||||
#if defined(DBMULTI_dbclient) && defined(DROPBEAR_MULTI)
|
||||
#if defined(DBMULTI_dbclient) || !DROPBEAR_MULTI
|
||||
#if defined(DBMULTI_dbclient) && DROPBEAR_MULTI
|
||||
int cli_main(int argc, char ** argv) {
|
||||
#else
|
||||
int main(int argc, char ** argv) {
|
||||
#endif
|
||||
|
||||
int sock;
|
||||
char* error = NULL;
|
||||
char* hostandport;
|
||||
int len;
|
||||
int sock_in, sock_out;
|
||||
struct dropbear_progress_connection *progress = NULL;
|
||||
pid_t proxy_cmd_pid = 0;
|
||||
|
||||
_dropbear_exit = cli_dropbear_exit;
|
||||
_dropbear_log = cli_dropbear_log;
|
||||
|
||||
disallow_core();
|
||||
|
||||
seedrandom();
|
||||
crypto_init();
|
||||
|
||||
cli_getopts(argc, argv);
|
||||
|
||||
TRACE(("user='%s' host='%s' port='%s'", cli_opts.username,
|
||||
cli_opts.remotehost, cli_opts.remoteport))
|
||||
#ifndef DISABLE_SYSLOG
|
||||
if (opts.usingsyslog) {
|
||||
startsyslog("dbclient");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cli_opts.bind_address) {
|
||||
DEBUG1(("connect to: user=%s host=%s/%s bind_address=%s:%s", cli_opts.username,
|
||||
cli_opts.remotehost, cli_opts.remoteport, cli_opts.bind_address, cli_opts.bind_port))
|
||||
} else {
|
||||
DEBUG1(("connect to: user=%s host=%s/%s",cli_opts.username,cli_opts.remotehost,cli_opts.remoteport))
|
||||
}
|
||||
|
||||
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
|
||||
dropbear_exit("signal() error");
|
||||
}
|
||||
|
||||
sock = connect_remote(cli_opts.remotehost, cli_opts.remoteport,
|
||||
0, &error);
|
||||
|
||||
if (sock < 0) {
|
||||
dropbear_exit("%s", error);
|
||||
#if DROPBEAR_CLI_PROXYCMD
|
||||
if (cli_opts.proxycmd) {
|
||||
cli_proxy_cmd(&sock_in, &sock_out, &proxy_cmd_pid);
|
||||
m_free(cli_opts.proxycmd);
|
||||
if (signal(SIGINT, kill_proxy_sighandler) == SIG_ERR ||
|
||||
signal(SIGTERM, kill_proxy_sighandler) == SIG_ERR ||
|
||||
signal(SIGHUP, kill_proxy_sighandler) == SIG_ERR) {
|
||||
dropbear_exit("signal() error");
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
progress = connect_remote(cli_opts.remotehost, cli_opts.remoteport,
|
||||
cli_connected, &ses, cli_opts.bind_address, cli_opts.bind_port,
|
||||
DROPBEAR_PRIO_LOWDELAY);
|
||||
sock_in = sock_out = -1;
|
||||
}
|
||||
|
||||
/* Set up the host:port log */
|
||||
len = strlen(cli_opts.remotehost);
|
||||
len += 10; /* 16 bit port and leeway*/
|
||||
hostandport = (char*)m_malloc(len);
|
||||
snprintf(hostandport, len, "%s:%s",
|
||||
cli_opts.remotehost, cli_opts.remoteport);
|
||||
|
||||
cli_session(sock, hostandport);
|
||||
cli_session(sock_in, sock_out, progress, proxy_cmd_pid);
|
||||
|
||||
/* not reached */
|
||||
return -1;
|
||||
}
|
||||
#endif /* DBMULTI stuff */
|
||||
|
||||
static void cli_dropbear_exit(int exitcode, const char* format, va_list param) {
|
||||
static void exec_proxy_cmd(const void *user_data_cmd) {
|
||||
const char *cmd = user_data_cmd;
|
||||
char *usershell;
|
||||
|
||||
char fmtbuf[300];
|
||||
usershell = m_strdup(get_user_shell());
|
||||
run_shell_command(cmd, ses.maxfd, usershell);
|
||||
dropbear_exit("Failed to run '%s'\n", cmd);
|
||||
}
|
||||
|
||||
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);
|
||||
#if DROPBEAR_CLI_PROXYCMD
|
||||
static void cli_proxy_cmd(int *sock_in, int *sock_out, pid_t *pid_out) {
|
||||
char * ex_cmd = NULL;
|
||||
size_t ex_cmdlen;
|
||||
int ret;
|
||||
|
||||
/* File descriptor "-j &3" */
|
||||
if (*cli_opts.proxycmd == '&') {
|
||||
char *p = cli_opts.proxycmd + 1;
|
||||
int sock = strtoul(p, &p, 10);
|
||||
/* must be a single number, and not stdin/stdout/stderr */
|
||||
if (sock > 2 && sock < 1024 && *p == '\0') {
|
||||
*sock_in = sock;
|
||||
*sock_out = sock;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do the cleanup first, since then the terminal will be reset */
|
||||
cli_session_cleanup();
|
||||
common_session_cleanup();
|
||||
/* Normal proxycommand */
|
||||
|
||||
_dropbear_log(LOG_INFO, fmtbuf, param);
|
||||
/* So that spawn_command knows which shell to run */
|
||||
fill_passwd(cli_opts.own_user);
|
||||
|
||||
exit(exitcode);
|
||||
ex_cmdlen = strlen(cli_opts.proxycmd) + 6; /* "exec " + command + '\0' */
|
||||
ex_cmd = m_malloc(ex_cmdlen);
|
||||
snprintf(ex_cmd, ex_cmdlen, "exec %s", cli_opts.proxycmd);
|
||||
|
||||
ret = spawn_command(exec_proxy_cmd, ex_cmd,
|
||||
sock_out, sock_in, NULL, pid_out);
|
||||
DEBUG1(("cmd: %s pid=%d", ex_cmd,*pid_out))
|
||||
m_free(ex_cmd);
|
||||
if (ret == DROPBEAR_FAILURE) {
|
||||
dropbear_exit("Failed running proxy command");
|
||||
*sock_in = *sock_out = -1;
|
||||
}
|
||||
}
|
||||
|
||||
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 kill_proxy_sighandler(int UNUSED(signo)) {
|
||||
kill_proxy_command();
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
#endif /* DROPBEAR_CLI_PROXYCMD */
|
||||
|
||||
900
cli-runopts.c
900
cli-runopts.c
File diff suppressed because it is too large
Load Diff
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Dropbear SSH
|
||||
*
|
||||
* Copyright (c) 2002,2003 Matt Johnston
|
||||
* Copyright (c) 2004 by Mihnea Stoenescu
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#include "includes.h"
|
||||
#include "service.h"
|
||||
#include "dbutil.h"
|
||||
#include "packet.h"
|
||||
#include "buffer.h"
|
||||
#include "session.h"
|
||||
#include "ssh.h"
|
||||
|
||||
void send_msg_service_request(char* servicename) {
|
||||
|
||||
TRACE(("enter send_msg_service_request: servicename='%s'", servicename))
|
||||
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_SERVICE_REQUEST);
|
||||
buf_putstring(ses.writepayload, servicename, strlen(servicename));
|
||||
|
||||
encrypt_packet();
|
||||
TRACE(("leave send_msg_service_request"))
|
||||
}
|
||||
|
||||
/* This just sets up the state variables right for the main client session loop
|
||||
* to deal with */
|
||||
void recv_msg_service_accept() {
|
||||
|
||||
unsigned char* servicename;
|
||||
unsigned int len;
|
||||
|
||||
TRACE(("enter recv_msg_service_accept"))
|
||||
|
||||
servicename = buf_getstring(ses.payload, &len);
|
||||
|
||||
/* ssh-userauth */
|
||||
if (cli_ses.state == SERVICE_AUTH_REQ_SENT
|
||||
&& len == SSH_SERVICE_USERAUTH_LEN
|
||||
&& strncmp(SSH_SERVICE_USERAUTH, servicename, len) == 0) {
|
||||
|
||||
cli_ses.state = SERVICE_AUTH_ACCEPT_RCVD;
|
||||
m_free(servicename);
|
||||
TRACE(("leave recv_msg_service_accept: done ssh-userauth"))
|
||||
return;
|
||||
}
|
||||
|
||||
/* ssh-connection */
|
||||
if (cli_ses.state == SERVICE_CONN_REQ_SENT
|
||||
&& len == SSH_SERVICE_CONNECTION_LEN
|
||||
&& strncmp(SSH_SERVICE_CONNECTION, servicename, len) == 0) {
|
||||
|
||||
if (ses.authstate.authdone != 1) {
|
||||
dropbear_exit("request for connection before auth");
|
||||
}
|
||||
|
||||
cli_ses.state = SERVICE_CONN_ACCEPT_RCVD;
|
||||
m_free(servicename);
|
||||
TRACE(("leave recv_msg_service_accept: done ssh-connection"))
|
||||
return;
|
||||
}
|
||||
|
||||
dropbear_exit("unrecognised service accept");
|
||||
/* m_free(servicename); not reached */
|
||||
|
||||
}
|
||||
339
cli-session.c
339
cli-session.c
@@ -31,15 +31,21 @@
|
||||
#include "packet.h"
|
||||
#include "tcpfwd.h"
|
||||
#include "channel.h"
|
||||
#include "random.h"
|
||||
#include "dbrandom.h"
|
||||
#include "service.h"
|
||||
#include "runopts.h"
|
||||
#include "chansession.h"
|
||||
#include "agentfwd.h"
|
||||
#include "crypto_desc.h"
|
||||
#include "netio.h"
|
||||
|
||||
static void cli_remoteclosed();
|
||||
static void cli_sessionloop();
|
||||
static void cli_session_init();
|
||||
static void cli_finished();
|
||||
static void cli_remoteclosed(void) ATTRIB_NORETURN;
|
||||
static void cli_sessionloop(void);
|
||||
static void cli_session_init(pid_t proxy_cmd_pid);
|
||||
static void cli_finished(void) ATTRIB_NORETURN;
|
||||
static void recv_msg_service_accept(void);
|
||||
static void cli_session_cleanup(void);
|
||||
static void recv_msg_global_request_cli(void);
|
||||
|
||||
struct clientsession cli_ses; /* GLOBAL */
|
||||
|
||||
@@ -63,49 +69,81 @@ static const packettype cli_packettypes[] = {
|
||||
{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 */
|
||||
#ifdef ENABLE_CLI_PUBKEY_AUTH
|
||||
{SSH_MSG_USERAUTH_PK_OK, recv_msg_userauth_pk_ok}, /* client */
|
||||
{SSH_MSG_USERAUTH_SPECIFIC_60, recv_msg_userauth_specific_60}, /* client */
|
||||
{SSH_MSG_GLOBAL_REQUEST, recv_msg_global_request_cli},
|
||||
{SSH_MSG_CHANNEL_SUCCESS, ignore_recv_response},
|
||||
{SSH_MSG_CHANNEL_FAILURE, ignore_recv_response},
|
||||
#if DROPBEAR_CLI_REMOTETCPFWD
|
||||
{SSH_MSG_REQUEST_SUCCESS, cli_recv_msg_request_success}, /* client */
|
||||
{SSH_MSG_REQUEST_FAILURE, cli_recv_msg_request_failure}, /* client */
|
||||
#else
|
||||
/* For keepalive */
|
||||
{SSH_MSG_REQUEST_SUCCESS, ignore_recv_response},
|
||||
{SSH_MSG_REQUEST_FAILURE, ignore_recv_response},
|
||||
#endif
|
||||
{0, 0} /* End */
|
||||
{SSH_MSG_EXT_INFO, recv_msg_ext_info},
|
||||
{0, NULL} /* End */
|
||||
};
|
||||
|
||||
static const struct ChanType *cli_chantypes[] = {
|
||||
#ifdef ENABLE_CLI_REMOTETCPFWD
|
||||
#if DROPBEAR_CLI_REMOTETCPFWD
|
||||
&cli_chan_tcpremote,
|
||||
#endif
|
||||
#if DROPBEAR_CLI_AGENTFWD
|
||||
&cli_chan_agent,
|
||||
#endif
|
||||
NULL /* Null termination */
|
||||
};
|
||||
|
||||
void cli_session(int sock, char* remotehost) {
|
||||
void cli_connected(int result, int sock, void* userdata, const char *errstring)
|
||||
{
|
||||
struct sshsession *myses = userdata;
|
||||
if (result == DROPBEAR_FAILURE) {
|
||||
dropbear_exit("Connect failed: %s", errstring);
|
||||
}
|
||||
myses->sock_in = myses->sock_out = sock;
|
||||
DEBUG1(("cli_connected"))
|
||||
ses.socket_prio = DROPBEAR_PRIO_NORMAL;
|
||||
/* switches to lowdelay */
|
||||
update_channel_prio();
|
||||
}
|
||||
|
||||
crypto_init();
|
||||
common_session_init(sock, remotehost);
|
||||
void cli_session(int sock_in, int sock_out, struct dropbear_progress_connection *progress, pid_t proxy_cmd_pid) {
|
||||
|
||||
common_session_init(sock_in, sock_out);
|
||||
|
||||
if (progress) {
|
||||
connect_set_writequeue(progress, &ses.writequeue);
|
||||
}
|
||||
|
||||
chaninitialise(cli_chantypes);
|
||||
|
||||
|
||||
/* Set up cli_ses vars */
|
||||
cli_session_init();
|
||||
cli_session_init(proxy_cmd_pid);
|
||||
|
||||
/* Ready to go */
|
||||
sessinitdone = 1;
|
||||
ses.init_done = 1;
|
||||
|
||||
/* Exchange identification */
|
||||
session_identification();
|
||||
send_session_identification();
|
||||
|
||||
seedrandom();
|
||||
kexfirstinitialise(); /* initialise the kex state */
|
||||
|
||||
send_msg_kexinit();
|
||||
|
||||
/* XXX here we do stuff differently */
|
||||
|
||||
session_loop(cli_sessionloop);
|
||||
|
||||
/* Not reached */
|
||||
|
||||
}
|
||||
|
||||
static void cli_session_init() {
|
||||
#if DROPBEAR_KEX_FIRST_FOLLOWS
|
||||
static void cli_send_kex_first_guess() {
|
||||
send_msg_kexdh_init();
|
||||
}
|
||||
#endif
|
||||
|
||||
static void cli_session_init(pid_t proxy_cmd_pid) {
|
||||
|
||||
cli_ses.state = STATE_NOTHING;
|
||||
cli_ses.kex_state = KEX_NOTHING;
|
||||
@@ -113,51 +151,82 @@ static void cli_session_init() {
|
||||
cli_ses.tty_raw_mode = 0;
|
||||
cli_ses.winchange = 0;
|
||||
|
||||
/* We store stdin's flags, so we can set them back on exit (otherwise
|
||||
* busybox's ash isn't happy */
|
||||
/* 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 */
|
||||
cli_ses.proxy_cmd_pid = proxy_cmd_pid;
|
||||
TRACE(("proxy command PID='%d'", proxy_cmd_pid));
|
||||
|
||||
/* Auth */
|
||||
cli_ses.lastpubkey = NULL;
|
||||
cli_ses.lastprivkey = NULL;
|
||||
cli_ses.lastauthtype = 0;
|
||||
cli_ses.is_trivial_auth = 1;
|
||||
|
||||
/* For printing "remote host closed" for the user */
|
||||
ses.remoteclosed = cli_remoteclosed;
|
||||
ses.buf_match_algo = cli_buf_match_algo;
|
||||
|
||||
ses.extra_session_cleanup = cli_session_cleanup;
|
||||
|
||||
/* packet handlers */
|
||||
ses.packettypes = cli_packettypes;
|
||||
|
||||
ses.isserver = 0;
|
||||
|
||||
#if DROPBEAR_KEX_FIRST_FOLLOWS
|
||||
ses.send_kex_first_guess = cli_send_kex_first_guess;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static void send_msg_service_request(const char* servicename) {
|
||||
|
||||
TRACE(("enter send_msg_service_request: servicename='%s'", servicename))
|
||||
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_SERVICE_REQUEST);
|
||||
buf_putstring(ses.writepayload, servicename, strlen(servicename));
|
||||
|
||||
encrypt_packet();
|
||||
TRACE(("leave send_msg_service_request"))
|
||||
}
|
||||
|
||||
static void recv_msg_service_accept(void) {
|
||||
/* do nothing, if it failed then the server MUST have disconnected */
|
||||
}
|
||||
|
||||
/* This function drives the progress of the session - it initiates KEX,
|
||||
* service, userauth and channel requests */
|
||||
static void cli_sessionloop() {
|
||||
|
||||
TRACE(("enter cli_sessionloop"))
|
||||
TRACE2(("enter cli_sessionloop"))
|
||||
|
||||
if (ses.lastpacket == SSH_MSG_KEXINIT && cli_ses.kex_state == KEX_NOTHING) {
|
||||
cli_ses.kex_state = KEXINIT_RCVD;
|
||||
if (ses.lastpacket == 0) {
|
||||
TRACE2(("exit cli_sessionloop: no real packets yet"))
|
||||
return;
|
||||
}
|
||||
|
||||
if (cli_ses.kex_state == KEXINIT_RCVD) {
|
||||
|
||||
if (ses.lastpacket == SSH_MSG_KEXINIT && cli_ses.kex_state == KEX_NOTHING) {
|
||||
/* We initiate the KEXDH. If DH wasn't the correct type, the KEXINIT
|
||||
* negotiation would have failed. */
|
||||
send_msg_kexdh_init();
|
||||
cli_ses.kex_state = KEXDH_INIT_SENT;
|
||||
if (!ses.kexstate.our_first_follows_matches) {
|
||||
send_msg_kexdh_init();
|
||||
}
|
||||
cli_ses.kex_state = KEXDH_INIT_SENT;
|
||||
TRACE(("leave cli_sessionloop: done with KEXINIT_RCVD"))
|
||||
return;
|
||||
}
|
||||
|
||||
/* A KEX has finished, so we should go back to our KEX_NOTHING state */
|
||||
if (cli_ses.kex_state != KEX_NOTHING && ses.kexstate.recvkexinit == 0
|
||||
&& ses.kexstate.sentkexinit == 0) {
|
||||
if (cli_ses.kex_state != KEX_NOTHING && ses.kexstate.sentnewkeys) {
|
||||
cli_ses.kex_state = KEX_NOTHING;
|
||||
}
|
||||
|
||||
@@ -167,10 +236,10 @@ static void cli_sessionloop() {
|
||||
return;
|
||||
}
|
||||
|
||||
/* We should exit if we haven't donefirstkex: we shouldn't reach here
|
||||
* in normal operation */
|
||||
if (ses.kexstate.donefirstkex == 0) {
|
||||
TRACE(("XXX XXX might be bad! leave cli_sessionloop: haven't donefirstkex"))
|
||||
/* We might reach here if we have partial packet reads or have
|
||||
* received SSG_MSG_IGNORE etc. Just skip it */
|
||||
TRACE2(("donefirstkex false\n"))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -180,51 +249,71 @@ static void cli_sessionloop() {
|
||||
/* We've got the transport layer sorted, we now need to request
|
||||
* userauth */
|
||||
send_msg_service_request(SSH_SERVICE_USERAUTH);
|
||||
cli_ses.state = SERVICE_AUTH_REQ_SENT;
|
||||
TRACE(("leave cli_sessionloop: sent userauth service req"))
|
||||
return;
|
||||
|
||||
/* userauth code */
|
||||
case SERVICE_AUTH_ACCEPT_RCVD:
|
||||
/* We aren't using any "implicit server authentication" methods,
|
||||
so don't need to wait for a response for SSH_SERVICE_USERAUTH
|
||||
before sending the auth messages (rfc4253 10) */
|
||||
cli_auth_getmethods();
|
||||
cli_ses.state = USERAUTH_REQ_SENT;
|
||||
TRACE(("leave cli_sessionloop: sent userauth methods req"))
|
||||
return;
|
||||
|
||||
case USERAUTH_REQ_SENT:
|
||||
TRACE(("leave cli_sessionloop: waiting, req_sent"))
|
||||
return;
|
||||
|
||||
case USERAUTH_FAIL_RCVD:
|
||||
cli_auth_try();
|
||||
if (cli_auth_try() == DROPBEAR_FAILURE) {
|
||||
dropbear_exit("No auth methods could be used.");
|
||||
}
|
||||
cli_ses.state = USERAUTH_REQ_SENT;
|
||||
TRACE(("leave cli_sessionloop: cli_auth_try"))
|
||||
return;
|
||||
|
||||
/*
|
||||
case USERAUTH_SUCCESS_RCVD:
|
||||
send_msg_service_request(SSH_SERVICE_CONNECTION);
|
||||
cli_ses.state = SERVICE_CONN_REQ_SENT;
|
||||
TRACE(("leave cli_sessionloop: sent ssh-connection service req"))
|
||||
return;
|
||||
#ifndef DISABLE_SYSLOG
|
||||
if (opts.usingsyslog) {
|
||||
dropbear_log(LOG_INFO, "Authentication succeeded.");
|
||||
}
|
||||
#endif
|
||||
|
||||
case SERVICE_CONN_ACCEPT_RCVD:
|
||||
cli_send_chansess_request();
|
||||
TRACE(("leave cli_sessionloop: cli_send_chansess_request"))
|
||||
cli_ses.state = SESSION_RUNNING;
|
||||
return;
|
||||
*/
|
||||
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(DROPBEAR_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));
|
||||
}
|
||||
}
|
||||
|
||||
#if DROPBEAR_CLI_NETCAT
|
||||
if (cli_opts.netcat_host) {
|
||||
cli_send_netcat_request();
|
||||
} else
|
||||
#endif
|
||||
if (!cli_opts.no_cmd) {
|
||||
cli_send_chansess_request();
|
||||
}
|
||||
|
||||
case USERAUTH_SUCCESS_RCVD:
|
||||
#ifdef ENABLE_CLI_LOCALTCPFWD
|
||||
#if DROPBEAR_CLI_LOCALTCPFWD
|
||||
setup_localtcp();
|
||||
#endif
|
||||
#ifdef ENABLE_CLI_REMOTETCPFWD
|
||||
#if DROPBEAR_CLI_REMOTETCPFWD
|
||||
setup_remotetcp();
|
||||
#endif
|
||||
cli_send_chansess_request();
|
||||
TRACE(("leave cli_sessionloop: cli_send_chansess_request"))
|
||||
|
||||
TRACE(("leave cli_sessionloop: running"))
|
||||
cli_ses.state = SESSION_RUNNING;
|
||||
return;
|
||||
|
||||
case SESSION_RUNNING:
|
||||
if (ses.chancount < 1) {
|
||||
if (ses.chancount < 1 && !cli_opts.no_cmd) {
|
||||
cli_finished();
|
||||
}
|
||||
|
||||
@@ -240,28 +329,51 @@ static void cli_sessionloop() {
|
||||
break;
|
||||
}
|
||||
|
||||
TRACE(("leave cli_sessionloop: fell out"))
|
||||
TRACE2(("leave cli_sessionloop: fell out"))
|
||||
|
||||
}
|
||||
|
||||
void cli_session_cleanup() {
|
||||
void kill_proxy_command(void) {
|
||||
/*
|
||||
* Send SIGHUP to proxy command if used. We don't wait() in
|
||||
* case it hangs and instead rely on init to reap the child
|
||||
*/
|
||||
if (cli_ses.proxy_cmd_pid > 1) {
|
||||
TRACE(("killing proxy command with PID='%d'", cli_ses.proxy_cmd_pid));
|
||||
kill(cli_ses.proxy_cmd_pid, SIGHUP);
|
||||
}
|
||||
}
|
||||
|
||||
if (!sessinitdone) {
|
||||
static void cli_session_cleanup(void) {
|
||||
|
||||
if (!ses.init_done) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set stdin back to non-blocking - busybox ash dies nastily
|
||||
* if we don't revert the flags */
|
||||
fcntl(cli_ses.stdincopy, F_SETFL, cli_ses.stdinflags);
|
||||
kill_proxy_command();
|
||||
|
||||
/* Set std{in,out,err} back to non-blocking - busybox ash dies nastily if
|
||||
* we don't revert the flags */
|
||||
/* Ignore return value since there's nothing we can do */
|
||||
(void)fcntl(cli_ses.stdincopy, F_SETFL, cli_ses.stdinflags);
|
||||
(void)fcntl(cli_ses.stdoutcopy, F_SETFL, cli_ses.stdoutflags);
|
||||
(void)fcntl(cli_ses.stderrcopy, F_SETFL, cli_ses.stderrflags);
|
||||
|
||||
/* Don't leak */
|
||||
m_close(cli_ses.stdincopy);
|
||||
m_close(cli_ses.stdoutcopy);
|
||||
m_close(cli_ses.stderrcopy);
|
||||
|
||||
cli_tty_cleanup();
|
||||
|
||||
if (cli_ses.server_sig_algs) {
|
||||
buf_free(cli_ses.server_sig_algs);
|
||||
}
|
||||
}
|
||||
|
||||
static void cli_finished() {
|
||||
TRACE(("cli_finished()"))
|
||||
|
||||
cli_session_cleanup();
|
||||
common_session_cleanup();
|
||||
session_cleanup();
|
||||
fprintf(stderr, "Connection to %s@%s:%s closed.\n", cli_opts.username,
|
||||
cli_opts.remotehost, cli_opts.remoteport);
|
||||
exit(cli_ses.retval);
|
||||
@@ -273,17 +385,20 @@ static void cli_remoteclosed() {
|
||||
|
||||
/* XXX TODO perhaps print a friendlier message if we get this but have
|
||||
* already sent/received disconnect message(s) ??? */
|
||||
close(ses.sock);
|
||||
ses.sock = -1;
|
||||
dropbear_exit("remote closed the connection");
|
||||
m_close(ses.sock_in);
|
||||
m_close(ses.sock_out);
|
||||
ses.sock_in = -1;
|
||||
ses.sock_out = -1;
|
||||
dropbear_exit("Remote closed the connection");
|
||||
}
|
||||
|
||||
/* Operates in-place turning dirty (untrusted potentially containing control
|
||||
* characters) text into clean text. */
|
||||
void cleantext(unsigned char* dirtytext) {
|
||||
* characters) text into clean text.
|
||||
* Note: this is safe only with ascii - other charsets could have problems. */
|
||||
void cleantext(char* dirtytext) {
|
||||
|
||||
unsigned int i, j;
|
||||
unsigned char c;
|
||||
char c;
|
||||
|
||||
j = 0;
|
||||
for (i = 0; dirtytext[i] != '\0'; i++) {
|
||||
@@ -298,3 +413,77 @@ void cleantext(unsigned char* dirtytext) {
|
||||
/* Null terminate */
|
||||
dirtytext[j] = '\0';
|
||||
}
|
||||
|
||||
static void recv_msg_global_request_cli(void) {
|
||||
unsigned int wantreply = 0;
|
||||
|
||||
buf_eatstring(ses.payload);
|
||||
wantreply = buf_getbool(ses.payload);
|
||||
|
||||
TRACE(("recv_msg_global_request_cli: want_reply: %u", wantreply));
|
||||
|
||||
if (wantreply) {
|
||||
/* Send a proper rejection */
|
||||
send_msg_request_failure();
|
||||
}
|
||||
}
|
||||
|
||||
void cli_dropbear_exit(int exitcode, const char* format, va_list param) {
|
||||
char exitmsg[150];
|
||||
char fullmsg[300];
|
||||
|
||||
/* Note that exit message must be rendered before session cleanup */
|
||||
|
||||
/* Render the formatted exit message */
|
||||
vsnprintf(exitmsg, sizeof(exitmsg), format, param);
|
||||
TRACE(("Exited, cleaning up: %s", exitmsg))
|
||||
|
||||
/* Add the prefix depending on session/auth state */
|
||||
if (!ses.init_done) {
|
||||
snprintf(fullmsg, sizeof(fullmsg), "Exited: %s", exitmsg);
|
||||
} else {
|
||||
snprintf(fullmsg, sizeof(fullmsg),
|
||||
"Connection to %s@%s:%s exited: %s",
|
||||
cli_opts.username, cli_opts.remotehost,
|
||||
cli_opts.remoteport, exitmsg);
|
||||
}
|
||||
|
||||
/* Do the cleanup first, since then the terminal will be reset */
|
||||
session_cleanup();
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
if (fuzz.do_jmp) {
|
||||
longjmp(fuzz.jmp, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Avoid printing onwards from terminal cruft */
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
dropbear_log(LOG_INFO, "%s", fullmsg);
|
||||
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
void cli_dropbear_log(int priority, const char* format, va_list param) {
|
||||
|
||||
char printbuf[1024];
|
||||
const char *name;
|
||||
|
||||
name = cli_opts.progname;
|
||||
if (!name) {
|
||||
name = "dbclient";
|
||||
}
|
||||
|
||||
vsnprintf(printbuf, sizeof(printbuf), format, param);
|
||||
|
||||
#ifndef DISABLE_SYSLOG
|
||||
if (opts.usingsyslog) {
|
||||
syslog(priority, "%s", printbuf);
|
||||
}
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "%s: %s\n", name, printbuf);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
|
||||
234
cli-tcpfwd.c
234
cli-tcpfwd.c
@@ -23,69 +23,88 @@
|
||||
* 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"
|
||||
#include "netio.h"
|
||||
|
||||
#ifdef ENABLE_CLI_REMOTETCPFWD
|
||||
#if DROPBEAR_CLI_REMOTETCPFWD
|
||||
static int newtcpforwarded(struct Channel * channel);
|
||||
|
||||
const struct ChanType cli_chan_tcpremote = {
|
||||
1, /* sepfds */
|
||||
"forwarded-tcpip",
|
||||
newtcpforwarded,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CLI_LOCALTCPFWD
|
||||
static int cli_localtcp(unsigned int listenport, const char* remoteaddr,
|
||||
#if DROPBEAR_CLI_LOCALTCPFWD
|
||||
static int cli_localtcp(const char* listenaddr,
|
||||
unsigned int listenport,
|
||||
const char* remoteaddr,
|
||||
unsigned int remoteport);
|
||||
static const struct ChanType cli_chan_tcplocal = {
|
||||
1, /* sepfds */
|
||||
"direct-tcpip",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CLI_LOCALTCPFWD
|
||||
void setup_localtcp() {
|
||||
#if DROPBEAR_CLI_ANYTCPFWD
|
||||
static void fwd_failed(const char* format, ...) ATTRIB_PRINTF(1,2);
|
||||
static void fwd_failed(const char* format, ...)
|
||||
{
|
||||
va_list param;
|
||||
va_start(param, format);
|
||||
|
||||
if (cli_opts.exit_on_fwd_failure) {
|
||||
_dropbear_exit(EXIT_FAILURE, format, param);
|
||||
} else {
|
||||
_dropbear_log(LOG_WARNING, format, param);
|
||||
}
|
||||
|
||||
va_end(param);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DROPBEAR_CLI_LOCALTCPFWD
|
||||
void setup_localtcp() {
|
||||
m_list_elem *iter;
|
||||
int ret;
|
||||
|
||||
TRACE(("enter setup_localtcp"))
|
||||
|
||||
if (cli_opts.localfwds == NULL) {
|
||||
TRACE(("cli_opts.localfwds == NULL"))
|
||||
}
|
||||
|
||||
while (cli_opts.localfwds != NULL) {
|
||||
ret = cli_localtcp(cli_opts.localfwds->listenport,
|
||||
cli_opts.localfwds->connectaddr,
|
||||
cli_opts.localfwds->connectport);
|
||||
for (iter = cli_opts.localfwds->first; iter; iter = iter->next) {
|
||||
struct TCPFwdEntry * fwd = (struct TCPFwdEntry*)iter->item;
|
||||
ret = cli_localtcp(
|
||||
fwd->listenaddr,
|
||||
fwd->listenport,
|
||||
fwd->connectaddr,
|
||||
fwd->connectport);
|
||||
if (ret == DROPBEAR_FAILURE) {
|
||||
dropbear_log(LOG_WARNING, "Failed local port forward %d:%s:%d",
|
||||
cli_opts.localfwds->listenport,
|
||||
cli_opts.localfwds->connectaddr,
|
||||
cli_opts.localfwds->connectport);
|
||||
}
|
||||
|
||||
cli_opts.localfwds = cli_opts.localfwds->next;
|
||||
fwd_failed("Failed local port forward %s:%d:%s:%d",
|
||||
fwd->listenaddr,
|
||||
fwd->listenport,
|
||||
fwd->connectaddr,
|
||||
fwd->connectport);
|
||||
}
|
||||
}
|
||||
TRACE(("leave setup_localtcp"))
|
||||
|
||||
}
|
||||
|
||||
static int cli_localtcp(unsigned int listenport, const char* remoteaddr,
|
||||
static int cli_localtcp(const char* listenaddr,
|
||||
unsigned int listenport,
|
||||
const char* remoteaddr,
|
||||
unsigned int remoteport) {
|
||||
|
||||
struct TCPListener* tcpinfo = NULL;
|
||||
@@ -94,13 +113,29 @@ static int cli_localtcp(unsigned int listenport, const char* remoteaddr,
|
||||
TRACE(("enter cli_localtcp: %d %s %d", listenport, remoteaddr,
|
||||
remoteport));
|
||||
|
||||
tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener*));
|
||||
tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener));
|
||||
|
||||
tcpinfo->sendaddr = m_strdup(remoteaddr);
|
||||
tcpinfo->sendport = remoteport;
|
||||
tcpinfo->listenport = listenport;
|
||||
tcpinfo->chantype = &cli_chan_tcplocal;
|
||||
|
||||
ret = listen_tcpfwd(tcpinfo);
|
||||
if (listenaddr)
|
||||
{
|
||||
tcpinfo->listenaddr = m_strdup(listenaddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (opts.listen_fwd_all) {
|
||||
tcpinfo->listenaddr = m_strdup("");
|
||||
} else {
|
||||
tcpinfo->listenaddr = m_strdup("localhost");
|
||||
}
|
||||
}
|
||||
tcpinfo->listenport = listenport;
|
||||
|
||||
tcpinfo->chantype = &cli_chan_tcplocal;
|
||||
tcpinfo->tcp_type = direct;
|
||||
|
||||
ret = listen_tcpfwd(tcpinfo, NULL);
|
||||
|
||||
if (ret == DROPBEAR_FAILURE) {
|
||||
m_free(tcpinfo);
|
||||
@@ -108,18 +143,18 @@ static int cli_localtcp(unsigned int listenport, const char* remoteaddr,
|
||||
TRACE(("leave cli_localtcp: %d", ret))
|
||||
return ret;
|
||||
}
|
||||
#endif /* ENABLE_CLI_LOCALTCPFWD */
|
||||
#endif /* DROPBEAR_CLI_LOCALTCPFWD */
|
||||
|
||||
#ifdef ENABLE_CLI_REMOTETCPFWD
|
||||
static void send_msg_global_request_remotetcp(int port) {
|
||||
#if DROPBEAR_CLI_REMOTETCPFWD
|
||||
static void send_msg_global_request_remotetcp(const char *addr, int port) {
|
||||
|
||||
TRACE(("enter send_msg_global_request_remotetcp"))
|
||||
|
||||
CHECKCLEARTOWRITE();
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST);
|
||||
buf_putstring(ses.writepayload, "tcpip-forward", 13);
|
||||
buf_putbyte(ses.writepayload, 0);
|
||||
buf_putstring(ses.writepayload, "0.0.0.0", 7); /* TODO: IPv6? */
|
||||
buf_putbyte(ses.writepayload, 1); /* want_reply */
|
||||
buf_putstring(ses.writepayload, addr, strlen(addr));
|
||||
buf_putint(ses.writepayload, port);
|
||||
|
||||
encrypt_packet();
|
||||
@@ -127,76 +162,125 @@ static void send_msg_global_request_remotetcp(int port) {
|
||||
TRACE(("leave send_msg_global_request_remotetcp"))
|
||||
}
|
||||
|
||||
/* The only global success/failure messages are for remotetcp.
|
||||
* Since there isn't any identifier in these messages, we have to rely on them
|
||||
* being in the same order as we sent the requests. This is the ordering
|
||||
* of the cli_opts.remotefwds list.
|
||||
* If the requested remote port is 0 the listen port will be
|
||||
* dynamically allocated by the server and the port number will be returned
|
||||
* to client and the port number reported to the user. */
|
||||
void cli_recv_msg_request_success() {
|
||||
/* We just mark off that we have received the reply,
|
||||
* so that we can report failure for later ones. */
|
||||
m_list_elem * iter = NULL;
|
||||
for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) {
|
||||
struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item;
|
||||
if (!fwd->have_reply) {
|
||||
fwd->have_reply = 1;
|
||||
if (fwd->listenport == 0) {
|
||||
/* The server should let us know which port was allocated if we requested port 0 */
|
||||
int allocport = buf_getint(ses.payload);
|
||||
if (allocport > 0) {
|
||||
fwd->listenport = allocport;
|
||||
dropbear_log(LOG_INFO, "Allocated port %d for remote forward to %s:%d",
|
||||
allocport, fwd->connectaddr, fwd->connectport);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cli_recv_msg_request_failure() {
|
||||
m_list_elem *iter;
|
||||
for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) {
|
||||
struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item;
|
||||
if (!fwd->have_reply) {
|
||||
fwd->have_reply = 1;
|
||||
fwd_failed("Remote TCP forward request failed (port %d -> %s:%d)",
|
||||
fwd->listenport,
|
||||
fwd->connectaddr,
|
||||
fwd->connectport);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setup_remotetcp() {
|
||||
|
||||
struct TCPFwdList * iter = NULL;
|
||||
|
||||
m_list_elem *iter;
|
||||
TRACE(("enter setup_remotetcp"))
|
||||
|
||||
if (cli_opts.remotefwds == NULL) {
|
||||
TRACE(("cli_opts.remotefwds == NULL"))
|
||||
for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) {
|
||||
struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item;
|
||||
if (!fwd->listenaddr)
|
||||
{
|
||||
/* we store the addresses so that we can compare them
|
||||
when the server sends them back */
|
||||
if (opts.listen_fwd_all) {
|
||||
fwd->listenaddr = m_strdup("");
|
||||
} else {
|
||||
fwd->listenaddr = m_strdup("localhost");
|
||||
}
|
||||
}
|
||||
send_msg_global_request_remotetcp(fwd->listenaddr, fwd->listenport);
|
||||
}
|
||||
|
||||
iter = cli_opts.remotefwds;
|
||||
|
||||
while (iter != NULL) {
|
||||
send_msg_global_request_remotetcp(iter->listenport);
|
||||
iter = iter->next;
|
||||
}
|
||||
TRACE(("leave setup_remotetcp"))
|
||||
}
|
||||
|
||||
static int newtcpforwarded(struct Channel * channel) {
|
||||
|
||||
char *origaddr = NULL;
|
||||
unsigned int origport;
|
||||
struct TCPFwdList * iter = NULL;
|
||||
m_list_elem * iter = NULL;
|
||||
struct TCPFwdEntry *fwd = 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);
|
||||
|
||||
origaddr = buf_getstring(ses.payload, NULL);
|
||||
origport = buf_getint(ses.payload);
|
||||
|
||||
/* Find which port corresponds */
|
||||
iter = cli_opts.remotefwds;
|
||||
|
||||
while (iter != NULL) {
|
||||
if (origport == iter->listenport) {
|
||||
/* Find which port corresponds. First try and match address as well as port,
|
||||
in case they want to forward different ports separately ... */
|
||||
for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) {
|
||||
fwd = (struct TCPFwdEntry*)iter->item;
|
||||
if (origport == fwd->listenport
|
||||
&& strcmp(origaddr, fwd->listenaddr) == 0) {
|
||||
break;
|
||||
}
|
||||
iter = iter->next;
|
||||
}
|
||||
|
||||
if (iter == NULL) {
|
||||
if (!iter)
|
||||
{
|
||||
/* ... otherwise try to generically match the only forwarded port
|
||||
without address (also handles ::1 vs 127.0.0.1 vs localhost case).
|
||||
rfc4254 is vague about the definition of "address that was connected" */
|
||||
for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) {
|
||||
fwd = (struct TCPFwdEntry*)iter->item;
|
||||
if (origport == fwd->listenport) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (iter == NULL || fwd == 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;
|
||||
cleantext(origaddr);
|
||||
dropbear_log(LOG_INFO, "Server sent unrequested forward from \"%s:%d\"",
|
||||
origaddr, origport);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ses.maxfd = MAX(ses.maxfd, sock);
|
||||
snprintf(portstring, sizeof(portstring), "%u", fwd->connectport);
|
||||
channel->conn_pending = connect_remote(fwd->connectaddr, portstring, channel_connect_done,
|
||||
channel, NULL, NULL, DROPBEAR_PRIO_NORMAL);
|
||||
|
||||
/* Note that infd is actually the "outgoing" direction on the
|
||||
* tcp connection, vice versa for outfd.
|
||||
* We don't set outfd, that will get set after the connection's
|
||||
* progress succeeds */
|
||||
channel->infd = sock;
|
||||
channel->initconn = 1;
|
||||
|
||||
err = SSH_OPEN_IN_PROGRESS;
|
||||
|
||||
out:
|
||||
m_free(origaddr);
|
||||
TRACE(("leave newtcpdirect: err %d", err))
|
||||
return err;
|
||||
}
|
||||
#endif /* ENABLE_CLI_REMOTETCPFWD */
|
||||
#endif /* DROPBEAR_CLI_REMOTETCPFWD */
|
||||
|
||||
618
common-algo.c
618
common-algo.c
@@ -23,29 +23,49 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#include "includes.h"
|
||||
#include "algo.h"
|
||||
#include "session.h"
|
||||
#include "dbutil.h"
|
||||
#include "dh_groups.h"
|
||||
#include "ltc_prng.h"
|
||||
#include "ecc.h"
|
||||
#include "gcm.h"
|
||||
#include "chachapoly.h"
|
||||
#include "ssh.h"
|
||||
|
||||
/* This file (algo.c) organises the ciphers which can be used, and is used to
|
||||
* decide which ciphers/hashes/compression/signing to use during key exchange*/
|
||||
|
||||
static int void_cipher(const unsigned char* in, unsigned char* out,
|
||||
unsigned long len, void* UNUSED(cipher_state)) {
|
||||
if (in != out) {
|
||||
memmove(out, in, len);
|
||||
}
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
static int void_start(int UNUSED(cipher), const unsigned char* UNUSED(IV),
|
||||
const unsigned char* UNUSED(key),
|
||||
int UNUSED(keylen), int UNUSED(num_rounds), void* UNUSED(cipher_state)) {
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
/* Mappings for ciphers, parameters are
|
||||
{&cipher_desc, keysize, blocksize} */
|
||||
|
||||
#ifdef DROPBEAR_AES128_CBC
|
||||
const struct dropbear_cipher dropbear_aes128 =
|
||||
/* Remember to add new ciphers/hashes to regciphers/reghashes too */
|
||||
|
||||
#if DROPBEAR_AES256
|
||||
static const struct dropbear_cipher dropbear_aes256 =
|
||||
{&aes_desc, 32, 16};
|
||||
#endif
|
||||
#if DROPBEAR_AES128
|
||||
static const struct dropbear_cipher dropbear_aes128 =
|
||||
{&aes_desc, 16, 16};
|
||||
#endif
|
||||
#ifdef DROPBEAR_BLOWFISH_CBC
|
||||
const struct dropbear_cipher dropbear_blowfish =
|
||||
{&blowfish_desc, 16, 8};
|
||||
#endif
|
||||
#ifdef DROPBEAR_TWOFISH128_CBC
|
||||
const struct dropbear_cipher dropbear_twofish128 =
|
||||
{&twofish_desc, 16, 16};
|
||||
#endif
|
||||
#ifdef DROPBEAR_3DES_CBC
|
||||
const struct dropbear_cipher dropbear_3des =
|
||||
#if DROPBEAR_3DES
|
||||
static const struct dropbear_cipher dropbear_3des =
|
||||
{&des3_desc, 24, 8};
|
||||
#endif
|
||||
|
||||
@@ -53,155 +73,507 @@ const struct dropbear_cipher dropbear_3des =
|
||||
const struct dropbear_cipher dropbear_nocipher =
|
||||
{NULL, 16, 8};
|
||||
|
||||
/* A few void* s are required to silence warnings
|
||||
* about the symmetric_CBC vs symmetric_CTR cipher_state pointer */
|
||||
#if DROPBEAR_ENABLE_CBC_MODE
|
||||
const struct dropbear_cipher_mode dropbear_mode_cbc =
|
||||
{(void*)cbc_start, (void*)cbc_encrypt, (void*)cbc_decrypt, NULL, NULL, NULL};
|
||||
#endif /* DROPBEAR_ENABLE_CBC_MODE */
|
||||
|
||||
const struct dropbear_cipher_mode dropbear_mode_none =
|
||||
{void_start, void_cipher, void_cipher, NULL, NULL, NULL};
|
||||
|
||||
#if DROPBEAR_ENABLE_CTR_MODE
|
||||
/* a wrapper to make ctr_start and cbc_start look the same */
|
||||
static int dropbear_big_endian_ctr_start(int cipher,
|
||||
const unsigned char *IV,
|
||||
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, NULL, NULL, NULL};
|
||||
#endif /* DROPBEAR_ENABLE_CTR_MODE */
|
||||
|
||||
/* Mapping of ssh hashes to libtomcrypt hashes, including keysize etc.
|
||||
{&hash_desc, keysize, hashsize} */
|
||||
|
||||
#ifdef DROPBEAR_SHA1_HMAC
|
||||
const struct dropbear_hash dropbear_sha1 =
|
||||
#if DROPBEAR_SHA1_HMAC
|
||||
static const struct dropbear_hash dropbear_sha1 =
|
||||
{&sha1_desc, 20, 20};
|
||||
#endif
|
||||
#ifdef DROPBEAR_MD5_HMAC
|
||||
const struct dropbear_hash dropbear_md5 =
|
||||
{&md5_desc, 16, 16};
|
||||
#if DROPBEAR_SHA1_96_HMAC
|
||||
static const struct dropbear_hash dropbear_sha1_96 =
|
||||
{&sha1_desc, 20, 12};
|
||||
#endif
|
||||
#if DROPBEAR_SHA2_256_HMAC
|
||||
static const struct dropbear_hash dropbear_sha2_256 =
|
||||
{&sha256_desc, 32, 32};
|
||||
#endif
|
||||
#if DROPBEAR_SHA2_512_HMAC
|
||||
static const struct dropbear_hash dropbear_sha2_512 =
|
||||
{&sha512_desc, 64, 64};
|
||||
#endif
|
||||
|
||||
const struct dropbear_hash dropbear_nohash =
|
||||
{NULL, 16, 0}; /* used initially */
|
||||
|
||||
|
||||
/* The following map ssh names to internal values */
|
||||
/* The following map ssh names to internal values.
|
||||
* The ordering here is important for the client - the first mode
|
||||
* that is also supported by the server will get used. */
|
||||
|
||||
algo_type sshciphers[] = {
|
||||
#ifdef DROPBEAR_AES128_CBC
|
||||
{"aes128-cbc", 0, (void*)&dropbear_aes128, 1},
|
||||
#if DROPBEAR_CHACHA20POLY1305
|
||||
{"chacha20-poly1305@openssh.com", 0, &dropbear_chachapoly, 1, &dropbear_mode_chachapoly},
|
||||
#endif
|
||||
#ifdef DROPBEAR_BLOWFISH_CBC
|
||||
{"blowfish-cbc", 0, (void*)&dropbear_blowfish, 1},
|
||||
|
||||
#if DROPBEAR_ENABLE_GCM_MODE
|
||||
#if DROPBEAR_AES128
|
||||
{"aes128-gcm@openssh.com", 0, &dropbear_aes128, 1, &dropbear_mode_gcm},
|
||||
#endif
|
||||
#ifdef DROPBEAR_TWOFISH128_CBC
|
||||
{"twofish-cbc", 0, (void*)&dropbear_twofish128, 1},
|
||||
#if DROPBEAR_AES256
|
||||
{"aes256-gcm@openssh.com", 0, &dropbear_aes256, 1, &dropbear_mode_gcm},
|
||||
#endif
|
||||
#ifdef DROPBEAR_3DES_CBC
|
||||
{"3des-cbc", 0, (void*)&dropbear_3des, 1},
|
||||
#endif /* DROPBEAR_ENABLE_GCM_MODE */
|
||||
|
||||
#if DROPBEAR_ENABLE_CTR_MODE
|
||||
#if DROPBEAR_AES128
|
||||
{"aes128-ctr", 0, &dropbear_aes128, 1, &dropbear_mode_ctr},
|
||||
#endif
|
||||
{NULL, 0, NULL, 0}
|
||||
#if DROPBEAR_AES256
|
||||
{"aes256-ctr", 0, &dropbear_aes256, 1, &dropbear_mode_ctr},
|
||||
#endif
|
||||
#endif /* DROPBEAR_ENABLE_CTR_MODE */
|
||||
|
||||
#if DROPBEAR_ENABLE_CBC_MODE
|
||||
#if DROPBEAR_AES128
|
||||
{"aes128-cbc", 0, &dropbear_aes128, 1, &dropbear_mode_cbc},
|
||||
#endif
|
||||
#if DROPBEAR_AES256
|
||||
{"aes256-cbc", 0, &dropbear_aes256, 1, &dropbear_mode_cbc},
|
||||
#endif
|
||||
#endif /* DROPBEAR_ENABLE_CBC_MODE */
|
||||
|
||||
#if DROPBEAR_3DES
|
||||
#if DROPBEAR_ENABLE_CTR_MODE
|
||||
{"3des-ctr", 0, &dropbear_3des, 1, &dropbear_mode_ctr},
|
||||
#endif
|
||||
#if DROPBEAR_ENABLE_CBC_MODE
|
||||
{"3des-cbc", 0, &dropbear_3des, 1, &dropbear_mode_cbc},
|
||||
#endif
|
||||
#endif /* DROPBEAR_3DES */
|
||||
|
||||
#if DROPBEAR_ENABLE_CBC_MODE
|
||||
#endif /* DROPBEAR_ENABLE_CBC_MODE */
|
||||
{NULL, 0, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
algo_type sshhashes[] = {
|
||||
#ifdef DROPBEAR_SHA1_HMAC
|
||||
{"hmac-sha1", 0, (void*)&dropbear_sha1, 1},
|
||||
#if DROPBEAR_SHA1_96_HMAC
|
||||
{"hmac-sha1-96", 0, &dropbear_sha1_96, 1, NULL},
|
||||
#endif
|
||||
#ifdef DROPBEAR_MD5_HMAC
|
||||
{"hmac-md5", 0, (void*)&dropbear_md5, 1},
|
||||
#if DROPBEAR_SHA1_HMAC
|
||||
{"hmac-sha1", 0, &dropbear_sha1, 1, NULL},
|
||||
#endif
|
||||
{NULL, 0, NULL, 0}
|
||||
#if DROPBEAR_SHA2_256_HMAC
|
||||
{"hmac-sha2-256", 0, &dropbear_sha2_256, 1, NULL},
|
||||
#endif
|
||||
#if DROPBEAR_SHA2_512_HMAC
|
||||
{"hmac-sha2-512", 0, &dropbear_sha2_512, 1, NULL},
|
||||
#endif
|
||||
{NULL, 0, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
algo_type sshcompress[] = {
|
||||
{"none", DROPBEAR_COMP_NONE, NULL, 1},
|
||||
#ifndef DISABLE_ZLIB
|
||||
{"zlib", DROPBEAR_COMP_ZLIB, NULL, 1},
|
||||
#endif
|
||||
{NULL, 0, NULL, 0}
|
||||
algo_type ssh_compress[] = {
|
||||
{"zlib@openssh.com", DROPBEAR_COMP_ZLIB_DELAY, NULL, 1, NULL},
|
||||
{"zlib", DROPBEAR_COMP_ZLIB, NULL, 1, NULL},
|
||||
{"none", DROPBEAR_COMP_NONE, NULL, 1, NULL},
|
||||
{NULL, 0, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
algo_type sshhostkey[] = {
|
||||
#ifdef DROPBEAR_RSA
|
||||
{"ssh-rsa", DROPBEAR_SIGNKEY_RSA, NULL, 1},
|
||||
algo_type ssh_delaycompress[] = {
|
||||
{"zlib@openssh.com", DROPBEAR_COMP_ZLIB_DELAY, NULL, 1, NULL},
|
||||
{"none", DROPBEAR_COMP_NONE, NULL, 1, NULL},
|
||||
{NULL, 0, NULL, 0, NULL}
|
||||
};
|
||||
#endif
|
||||
#ifdef DROPBEAR_DSS
|
||||
{"ssh-dss", DROPBEAR_SIGNKEY_DSS, NULL, 1},
|
||||
#endif
|
||||
{NULL, 0, NULL, 0}
|
||||
|
||||
algo_type ssh_nocompress[] = {
|
||||
{"none", DROPBEAR_COMP_NONE, NULL, 1, NULL},
|
||||
{NULL, 0, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
algo_type sigalgs[] = {
|
||||
#if DROPBEAR_ED25519
|
||||
{"ssh-ed25519", DROPBEAR_SIGNATURE_ED25519, NULL, 1, NULL},
|
||||
#if DROPBEAR_SK_ED25519
|
||||
{"sk-ssh-ed25519@openssh.com", DROPBEAR_SIGNATURE_SK_ED25519, NULL, 1, NULL},
|
||||
#endif
|
||||
#endif
|
||||
#if DROPBEAR_ECDSA
|
||||
#if DROPBEAR_ECC_256
|
||||
{"ecdsa-sha2-nistp256", DROPBEAR_SIGNATURE_ECDSA_NISTP256, NULL, 1, NULL},
|
||||
#endif
|
||||
#if DROPBEAR_ECC_384
|
||||
{"ecdsa-sha2-nistp384", DROPBEAR_SIGNATURE_ECDSA_NISTP384, NULL, 1, NULL},
|
||||
#endif
|
||||
#if DROPBEAR_ECC_521
|
||||
{"ecdsa-sha2-nistp521", DROPBEAR_SIGNATURE_ECDSA_NISTP521, NULL, 1, NULL},
|
||||
#endif
|
||||
#if DROPBEAR_SK_ECDSA
|
||||
{"sk-ecdsa-sha2-nistp256@openssh.com", DROPBEAR_SIGNATURE_SK_ECDSA_NISTP256, NULL, 1, NULL},
|
||||
#endif
|
||||
#endif
|
||||
#if DROPBEAR_RSA
|
||||
#if DROPBEAR_RSA_SHA256
|
||||
{"rsa-sha2-256", DROPBEAR_SIGNATURE_RSA_SHA256, NULL, 1, NULL},
|
||||
#endif
|
||||
#if DROPBEAR_RSA_SHA1
|
||||
{"ssh-rsa", DROPBEAR_SIGNATURE_RSA_SHA1, NULL, 1, NULL},
|
||||
#endif
|
||||
#endif
|
||||
#if DROPBEAR_DSS
|
||||
{"ssh-dss", DROPBEAR_SIGNATURE_DSS, NULL, 1, NULL},
|
||||
#endif
|
||||
{NULL, 0, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
#if DROPBEAR_DH_GROUP1
|
||||
static const struct dropbear_kex kex_dh_group1 = {DROPBEAR_KEX_NORMAL_DH, dh_p_1, DH_P_1_LEN, NULL, &sha1_desc };
|
||||
#endif
|
||||
#if DROPBEAR_DH_GROUP14_SHA1
|
||||
static const struct dropbear_kex kex_dh_group14_sha1 = {DROPBEAR_KEX_NORMAL_DH, dh_p_14, DH_P_14_LEN, NULL, &sha1_desc };
|
||||
#endif
|
||||
#if DROPBEAR_DH_GROUP14_SHA256
|
||||
static const struct dropbear_kex kex_dh_group14_sha256 = {DROPBEAR_KEX_NORMAL_DH, dh_p_14, DH_P_14_LEN, NULL, &sha256_desc };
|
||||
#endif
|
||||
#if DROPBEAR_DH_GROUP16
|
||||
static const struct dropbear_kex kex_dh_group16_sha512 = {DROPBEAR_KEX_NORMAL_DH, dh_p_16, DH_P_16_LEN, NULL, &sha512_desc };
|
||||
#endif
|
||||
|
||||
#if DROPBEAR_ECDH
|
||||
#if DROPBEAR_ECC_256
|
||||
static const struct dropbear_kex kex_ecdh_nistp256 = {DROPBEAR_KEX_ECDH, NULL, 0, &ecc_curve_nistp256, &sha256_desc };
|
||||
#endif
|
||||
#if DROPBEAR_ECC_384
|
||||
static const struct dropbear_kex kex_ecdh_nistp384 = {DROPBEAR_KEX_ECDH, NULL, 0, &ecc_curve_nistp384, &sha384_desc };
|
||||
#endif
|
||||
#if DROPBEAR_ECC_521
|
||||
static const struct dropbear_kex kex_ecdh_nistp521 = {DROPBEAR_KEX_ECDH, NULL, 0, &ecc_curve_nistp521, &sha512_desc };
|
||||
#endif
|
||||
#endif /* DROPBEAR_ECDH */
|
||||
|
||||
#if DROPBEAR_CURVE25519
|
||||
/* Referred to directly */
|
||||
static const struct dropbear_kex kex_curve25519 = {DROPBEAR_KEX_CURVE25519, NULL, 0, NULL, &sha256_desc };
|
||||
#endif
|
||||
|
||||
/* data == NULL for non-kex algorithm identifiers */
|
||||
algo_type sshkex[] = {
|
||||
{"diffie-hellman-group1-sha1", DROPBEAR_KEX_DH_GROUP1, NULL, 1},
|
||||
{NULL, 0, NULL, 0}
|
||||
#if DROPBEAR_CURVE25519
|
||||
{"curve25519-sha256", 0, &kex_curve25519, 1, NULL},
|
||||
{"curve25519-sha256@libssh.org", 0, &kex_curve25519, 1, NULL},
|
||||
#endif
|
||||
#if DROPBEAR_ECDH
|
||||
#if DROPBEAR_ECC_521
|
||||
{"ecdh-sha2-nistp521", 0, &kex_ecdh_nistp521, 1, NULL},
|
||||
#endif
|
||||
#if DROPBEAR_ECC_384
|
||||
{"ecdh-sha2-nistp384", 0, &kex_ecdh_nistp384, 1, NULL},
|
||||
#endif
|
||||
#if DROPBEAR_ECC_256
|
||||
{"ecdh-sha2-nistp256", 0, &kex_ecdh_nistp256, 1, NULL},
|
||||
#endif
|
||||
#endif
|
||||
#if DROPBEAR_DH_GROUP14_SHA256
|
||||
{"diffie-hellman-group14-sha256", 0, &kex_dh_group14_sha256, 1, NULL},
|
||||
#endif
|
||||
#if DROPBEAR_DH_GROUP14_SHA1
|
||||
{"diffie-hellman-group14-sha1", 0, &kex_dh_group14_sha1, 1, NULL},
|
||||
#endif
|
||||
#if DROPBEAR_DH_GROUP1
|
||||
{"diffie-hellman-group1-sha1", 0, &kex_dh_group1, 1, NULL},
|
||||
#endif
|
||||
#if DROPBEAR_DH_GROUP16
|
||||
{"diffie-hellman-group16-sha512", 0, &kex_dh_group16_sha512, 1, NULL},
|
||||
#endif
|
||||
#if DROPBEAR_KEXGUESS2
|
||||
{KEXGUESS2_ALGO_NAME, 0, NULL, 1, NULL},
|
||||
#endif
|
||||
#if DROPBEAR_EXT_INFO
|
||||
#if DROPBEAR_CLIENT
|
||||
/* Set unusable by svr_algos_initialise() */
|
||||
{SSH_EXT_INFO_C, 0, NULL, 1, NULL},
|
||||
#endif
|
||||
#endif
|
||||
{NULL, 0, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
||||
/* Register the compiled in ciphers.
|
||||
* This should be run before using any of the ciphers/hashes */
|
||||
void crypto_init() {
|
||||
|
||||
const struct _cipher_descriptor *regciphers[] = {
|
||||
#ifdef DROPBEAR_AES128_CBC
|
||||
&aes_desc,
|
||||
#endif
|
||||
#ifdef DROPBEAR_BLOWFISH_CBC
|
||||
&blowfish_desc,
|
||||
#endif
|
||||
#ifdef DROPBEAR_TWOFISH128_CBC
|
||||
&twofish_desc,
|
||||
#endif
|
||||
#ifdef DROPBEAR_3DES_CBC
|
||||
&des3_desc,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct _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[]) {
|
||||
void buf_put_algolist_all(buffer * buf, const algo_type localalgos[], int useall) {
|
||||
unsigned int i, len;
|
||||
unsigned int donefirst = 0;
|
||||
unsigned int startpos;
|
||||
|
||||
unsigned int pos = 0, i, len;
|
||||
char str[50]; /* enough for local algo storage */
|
||||
startpos = buf->pos;
|
||||
/* Placeholder for length */
|
||||
buf_putint(buf, 0);
|
||||
for (i = 0; localalgos[i].name != NULL; i++) {
|
||||
if (localalgos[i].usable || useall) {
|
||||
if (donefirst) {
|
||||
buf_putbyte(buf, ',');
|
||||
}
|
||||
donefirst = 1;
|
||||
len = strlen(localalgos[i].name);
|
||||
buf_putbytes(buf, (const unsigned char *) localalgos[i].name, len);
|
||||
}
|
||||
}
|
||||
/* Fill out the length */
|
||||
len = buf->pos - startpos - 4;
|
||||
buf_setpos(buf, startpos);
|
||||
buf_putint(buf, len);
|
||||
TRACE(("algolist add %d '%.*s'", len, len, buf_getptr(buf, len)))
|
||||
buf_incrwritepos(buf, len);
|
||||
}
|
||||
|
||||
void buf_put_algolist(buffer * buf, const algo_type localalgos[]) {
|
||||
buf_put_algolist_all(buf, localalgos, 0);
|
||||
}
|
||||
|
||||
/* returns a list of pointers into algolist, of null-terminated names.
|
||||
ret_list should be passed in with space for *ret_count elements,
|
||||
on return *ret_count has the number of names filled.
|
||||
algolist is modified. */
|
||||
static void get_algolist(char* algolist, unsigned int algolist_len,
|
||||
const char* *ret_list, unsigned int *ret_count) {
|
||||
unsigned int max_count = *ret_count;
|
||||
unsigned int i;
|
||||
|
||||
if (*ret_count == 0) {
|
||||
return;
|
||||
}
|
||||
if (algolist_len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
|
||||
*ret_count = 0;
|
||||
}
|
||||
|
||||
/* ret_list will contain a list of the strings parsed out.
|
||||
We will have at least one string (even if it's just "") */
|
||||
ret_list[0] = algolist;
|
||||
*ret_count = 1;
|
||||
for (i = 0; i < algolist_len; i++) {
|
||||
if (algolist[i] == '\0') {
|
||||
/* someone is trying something strange */
|
||||
*ret_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (algolist[i] == ',') {
|
||||
if (*ret_count >= max_count) {
|
||||
dropbear_exit("Too many remote algorithms");
|
||||
*ret_count = 0;
|
||||
return;
|
||||
}
|
||||
algolist[i] = '\0';
|
||||
ret_list[*ret_count] = &algolist[i+1];
|
||||
(*ret_count)++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return DROPBEAR_SUCCESS if the namelist contains algo,
|
||||
DROPBEAR_FAILURE otherwise. buf position is not incremented. */
|
||||
int buf_has_algo(buffer *buf, const char *algo) {
|
||||
unsigned char* algolist = NULL;
|
||||
unsigned int orig_pos = buf->pos;
|
||||
unsigned int len, remotecount, i;
|
||||
const char *remotenames[MAX_PROPOSED_ALGO];
|
||||
int ret = DROPBEAR_FAILURE;
|
||||
|
||||
algolist = buf_getstring(buf, &len);
|
||||
remotecount = MAX_PROPOSED_ALGO;
|
||||
get_algolist(algolist, len, remotenames, &remotecount);
|
||||
for (i = 0; i < remotecount; i++)
|
||||
{
|
||||
if (strcmp(remotenames[i], algo) == 0) {
|
||||
ret = DROPBEAR_SUCCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (algolist) {
|
||||
m_free(algolist);
|
||||
}
|
||||
buf_setpos(buf, orig_pos);
|
||||
return ret;
|
||||
}
|
||||
|
||||
algo_type * first_usable_algo(algo_type algos[]) {
|
||||
int i;
|
||||
for (i = 0; algos[i].name != NULL; i++) {
|
||||
if (algos[i].usable) {
|
||||
return &algos[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* match the first algorithm in the comma-separated list in buf which is
|
||||
* also in localalgos[], or return NULL on failure.
|
||||
* (*goodguess) is set to 1 if the preferred client/server algos match,
|
||||
* 0 otherwise. This is used for checking if the kexalgo/hostkeyalgos are
|
||||
* guessed correctly */
|
||||
algo_type * buf_match_algo(buffer* buf, algo_type localalgos[],
|
||||
int kexguess2, int *goodguess) {
|
||||
char * algolist = NULL;
|
||||
const char *remotenames[MAX_PROPOSED_ALGO], *localnames[MAX_PROPOSED_ALGO];
|
||||
unsigned int len;
|
||||
unsigned int remotecount, localcount, clicount, servcount, i, j;
|
||||
algo_type * ret = NULL;
|
||||
const char **clinames, **servnames;
|
||||
|
||||
if (goodguess) {
|
||||
*goodguess = 0;
|
||||
}
|
||||
|
||||
/* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */
|
||||
algolist = buf_getstring(buf, &len);
|
||||
DEBUG3(("buf_match_algo: %s", algolist))
|
||||
remotecount = MAX_PROPOSED_ALGO;
|
||||
get_algolist(algolist, len, remotenames, &remotecount);
|
||||
|
||||
for (i = 0; localalgos[i].name != NULL; i++) {
|
||||
if (localalgos[i].usable) {
|
||||
/* Avoid generating a trailing comma */
|
||||
if (pos)
|
||||
str[pos++] = ',';
|
||||
len = strlen(localalgos[i].name);
|
||||
memcpy(&str[pos], localalgos[i].name, len);
|
||||
pos += len;
|
||||
localnames[i] = localalgos[i].name;
|
||||
} else {
|
||||
localnames[i] = NULL;
|
||||
}
|
||||
}
|
||||
str[pos]=0;
|
||||
/* Debug this */
|
||||
TRACE(("buf_put_algolist: %s", str))
|
||||
buf_putstring(buf, str, pos);
|
||||
localcount = i;
|
||||
|
||||
if (IS_DROPBEAR_SERVER) {
|
||||
clinames = remotenames;
|
||||
clicount = remotecount;
|
||||
servnames = localnames;
|
||||
servcount = localcount;
|
||||
} else {
|
||||
clinames = localnames;
|
||||
clicount = localcount;
|
||||
servnames = remotenames;
|
||||
servcount = remotecount;
|
||||
}
|
||||
|
||||
/* iterate and find the first match */
|
||||
for (i = 0; i < clicount; i++) {
|
||||
for (j = 0; j < servcount; j++) {
|
||||
if (!(servnames[j] && clinames[i])) {
|
||||
/* unusable algos are NULL */
|
||||
continue;
|
||||
}
|
||||
if (strcmp(servnames[j], clinames[i]) == 0) {
|
||||
/* set if it was a good guess */
|
||||
if (goodguess != NULL) {
|
||||
if (kexguess2) {
|
||||
if (i == 0) {
|
||||
*goodguess = 1;
|
||||
}
|
||||
} else {
|
||||
if (i == 0 && j == 0) {
|
||||
*goodguess = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* set the algo to return */
|
||||
if (IS_DROPBEAR_SERVER) {
|
||||
ret = &localalgos[j];
|
||||
} else {
|
||||
ret = &localalgos[i];
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
m_free(algolist);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if DROPBEAR_USER_ALGO_LIST
|
||||
|
||||
char *
|
||||
algolist_string(const algo_type algos[])
|
||||
{
|
||||
char *ret_list;
|
||||
buffer *b = buf_new(200);
|
||||
buf_put_algolist(b, algos);
|
||||
buf_setpos(b, b->len);
|
||||
buf_putbyte(b, '\0');
|
||||
buf_setpos(b, 4);
|
||||
ret_list = m_strdup((const char *) buf_getptr(b, b->len - b->pos));
|
||||
buf_free(b);
|
||||
return ret_list;
|
||||
}
|
||||
|
||||
static algo_type*
|
||||
check_algo(const char* algo_name, algo_type *algos)
|
||||
{
|
||||
algo_type *a;
|
||||
for (a = algos; a->name != NULL; a++)
|
||||
{
|
||||
if (strcmp(a->name, algo_name) == 0)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Checks a user provided comma-separated algorithm list for available
|
||||
* options. Any that are not acceptable are removed in-place. Returns the
|
||||
* number of valid algorithms. */
|
||||
int
|
||||
check_user_algos(const char* user_algo_list, algo_type * algos,
|
||||
const char *algo_desc)
|
||||
{
|
||||
algo_type new_algos[MAX_PROPOSED_ALGO+1];
|
||||
char *work_list = m_strdup(user_algo_list);
|
||||
char *start = work_list;
|
||||
char *c;
|
||||
int n;
|
||||
/* So we can iterate and look for null terminator */
|
||||
memset(new_algos, 0x0, sizeof(new_algos));
|
||||
for (c = work_list, n = 0; ; c++)
|
||||
{
|
||||
char oc = *c;
|
||||
if (n >= MAX_PROPOSED_ALGO) {
|
||||
dropbear_exit("Too many algorithms '%s'", user_algo_list);
|
||||
}
|
||||
if (*c == ',' || *c == '\0') {
|
||||
algo_type *match_algo = NULL;
|
||||
*c = '\0';
|
||||
match_algo = check_algo(start, algos);
|
||||
if (match_algo) {
|
||||
if (check_algo(start, new_algos)) {
|
||||
TRACE(("Skip repeated algorithm '%s'", start))
|
||||
} else {
|
||||
new_algos[n] = *match_algo;
|
||||
n++;
|
||||
}
|
||||
} else {
|
||||
dropbear_log(LOG_WARNING, "This Dropbear program does not support '%s' %s algorithm", start, algo_desc);
|
||||
}
|
||||
c++;
|
||||
start = c;
|
||||
}
|
||||
if (oc == '\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_free(work_list);
|
||||
/* n+1 to include a null terminator */
|
||||
memcpy(algos, new_algos, sizeof(*new_algos) * (n+1));
|
||||
return n;
|
||||
}
|
||||
#endif /* DROPBEAR_USER_ALGO_LIST */
|
||||
|
||||
961
common-channel.c
961
common-channel.c
File diff suppressed because it is too large
Load Diff
852
common-kex.c
852
common-kex.c
File diff suppressed because it is too large
Load Diff
130
common-runopts.c
130
common-runopts.c
@@ -1,19 +1,19 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -28,12 +28,15 @@
|
||||
#include "buffer.h"
|
||||
#include "dbutil.h"
|
||||
#include "auth.h"
|
||||
#include "algo.h"
|
||||
#include "dbrandom.h"
|
||||
|
||||
runopts opts; /* GLOBAL */
|
||||
|
||||
/* returns success or failure, and the keytype in *type. If we want
|
||||
* to restrict the type, type can contain a type to return */
|
||||
int readhostkey(const char * filename, sign_key * hostkey, int *type) {
|
||||
int readhostkey(const char * filename, sign_key * hostkey,
|
||||
enum signkey_type *type) {
|
||||
|
||||
int ret = DROPBEAR_FAILURE;
|
||||
buffer *buf;
|
||||
@@ -44,6 +47,9 @@ int readhostkey(const char * filename, sign_key * hostkey, int *type) {
|
||||
goto out;
|
||||
}
|
||||
buf_setpos(buf, 0);
|
||||
|
||||
addrandom(buf_getptr(buf, buf->len), buf->len);
|
||||
|
||||
if (buf_get_priv_key(buf, hostkey, type) == DROPBEAR_FAILURE) {
|
||||
goto out;
|
||||
}
|
||||
@@ -51,7 +57,117 @@ int readhostkey(const char * filename, sign_key * hostkey, int *type) {
|
||||
ret = DROPBEAR_SUCCESS;
|
||||
out:
|
||||
|
||||
buf_burn(buf);
|
||||
buf_free(buf);
|
||||
buf_burn_free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if DROPBEAR_USER_ALGO_LIST
|
||||
void
|
||||
parse_ciphers_macs() {
|
||||
int printed_help = 0;
|
||||
if (opts.cipher_list) {
|
||||
if (strcmp(opts.cipher_list, "help") == 0) {
|
||||
char *ciphers = algolist_string(sshciphers);
|
||||
dropbear_log(LOG_INFO, "Available ciphers: %s", ciphers);
|
||||
m_free(ciphers);
|
||||
printed_help = 1;
|
||||
} else {
|
||||
if (check_user_algos(opts.cipher_list, sshciphers, "cipher") == 0) {
|
||||
dropbear_exit("No valid ciphers specified for '-c'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.mac_list) {
|
||||
if (strcmp(opts.mac_list, "help") == 0) {
|
||||
char *macs = algolist_string(sshhashes);
|
||||
dropbear_log(LOG_INFO, "Available MACs: %s", macs);
|
||||
m_free(macs);
|
||||
printed_help = 1;
|
||||
} else {
|
||||
if (check_user_algos(opts.mac_list, sshhashes, "MAC") == 0) {
|
||||
dropbear_exit("No valid MACs specified for '-m'");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (printed_help) {
|
||||
dropbear_exit(".");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void print_version() {
|
||||
fprintf(stderr, "Dropbear v%s\n", DROPBEAR_VERSION);
|
||||
}
|
||||
|
||||
void parse_recv_window(const char* recv_window_arg) {
|
||||
int ret;
|
||||
unsigned int rw;
|
||||
|
||||
ret = m_str_to_uint(recv_window_arg, &rw);
|
||||
if (ret == DROPBEAR_FAILURE || rw == 0 || rw > MAX_RECV_WINDOW) {
|
||||
if (rw > MAX_RECV_WINDOW) {
|
||||
opts.recv_window = MAX_RECV_WINDOW;
|
||||
}
|
||||
dropbear_log(LOG_WARNING, "Bad recv window '%s', using %d",
|
||||
recv_window_arg, opts.recv_window);
|
||||
} else {
|
||||
opts.recv_window = rw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Splits addr:port. Handles IPv6 [2001:0011::4]:port style format.
|
||||
Returns first/second parts as malloced strings, second will
|
||||
be NULL if no separator is found.
|
||||
:port -> (NULL, "port")
|
||||
port -> (port, NULL)
|
||||
addr:port (addr, port)
|
||||
addr: -> (addr, "")
|
||||
Returns DROPBEAR_SUCCESS/DROPBEAR_FAILURE */
|
||||
int split_address_port(const char* spec, char **first, char ** second) {
|
||||
char *spec_copy = NULL, *addr = NULL, *colon = NULL;
|
||||
int ret = DROPBEAR_FAILURE;
|
||||
|
||||
*first = NULL;
|
||||
*second = NULL;
|
||||
spec_copy = m_strdup(spec);
|
||||
addr = spec_copy;
|
||||
|
||||
if (*addr == '[') {
|
||||
addr++;
|
||||
colon = strchr(addr, ']');
|
||||
if (!colon) {
|
||||
dropbear_log(LOG_WARNING, "Bad address '%s'", spec);
|
||||
goto out;
|
||||
}
|
||||
*colon = '\0';
|
||||
colon++;
|
||||
if (*colon == '\0') {
|
||||
/* No port part */
|
||||
colon = NULL;
|
||||
} else if (*colon != ':') {
|
||||
dropbear_log(LOG_WARNING, "Bad address '%s'", spec);
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* search for ':', that separates address and port */
|
||||
colon = strrchr(addr, ':');
|
||||
}
|
||||
|
||||
/* colon points to ':' now, or is NULL */
|
||||
if (colon) {
|
||||
/* Split the address/port */
|
||||
*colon = '\0';
|
||||
colon++;
|
||||
*second = m_strdup(colon);
|
||||
}
|
||||
if (strlen(addr)) {
|
||||
*first = m_strdup(addr);
|
||||
}
|
||||
ret = DROPBEAR_SUCCESS;
|
||||
|
||||
out:
|
||||
m_free(spec_copy);
|
||||
return ret;
|
||||
}
|
||||
|
||||
559
common-session.c
559
common-session.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Dropbear - a SSH2 server
|
||||
*
|
||||
* Copyright (c) 2002,2003 Matt Johnston
|
||||
* Copyright (c) Matt Johnston
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
@@ -30,72 +30,110 @@
|
||||
#include "buffer.h"
|
||||
#include "dss.h"
|
||||
#include "ssh.h"
|
||||
#include "random.h"
|
||||
#include "dbrandom.h"
|
||||
#include "kex.h"
|
||||
#include "channel.h"
|
||||
#include "atomicio.h"
|
||||
#include "runopts.h"
|
||||
#include "netio.h"
|
||||
|
||||
static void checktimeouts();
|
||||
static void checktimeouts(void);
|
||||
static long select_timeout(void);
|
||||
static int ident_readln(int fd, char* buf, int count);
|
||||
static void read_session_identification(void);
|
||||
|
||||
struct sshsession ses; /* GLOBAL */
|
||||
|
||||
/* 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, char* remotehost) {
|
||||
void common_session_init(int sock_in, int sock_out) {
|
||||
time_t now;
|
||||
|
||||
#if DEBUG_TRACE
|
||||
debug_start_net();
|
||||
#endif
|
||||
|
||||
TRACE(("enter session_init"))
|
||||
|
||||
ses.remotehost = remotehost;
|
||||
ses.sock_in = sock_in;
|
||||
ses.sock_out = sock_out;
|
||||
ses.maxfd = MAX(sock_in, sock_out);
|
||||
|
||||
ses.sock = sock;
|
||||
ses.maxfd = sock;
|
||||
if (sock_in >= 0) {
|
||||
setnonblocking(sock_in);
|
||||
}
|
||||
if (sock_out >= 0) {
|
||||
setnonblocking(sock_out);
|
||||
}
|
||||
|
||||
ses.connecttimeout = 0;
|
||||
ses.socket_prio = DROPBEAR_PRIO_NORMAL;
|
||||
/* Sets it to lowdelay */
|
||||
update_channel_prio();
|
||||
|
||||
#if !DROPBEAR_SVR_MULTIUSER
|
||||
/* A sanity check to prevent an accidental configuration option
|
||||
leaving multiuser systems exposed */
|
||||
errno = 0;
|
||||
getuid();
|
||||
if (errno != ENOSYS) {
|
||||
dropbear_exit("Non-multiuser Dropbear requires a non-multiuser kernel");
|
||||
}
|
||||
#endif
|
||||
|
||||
now = monotonic_now();
|
||||
ses.connect_time = now;
|
||||
ses.last_packet_time_keepalive_recv = now;
|
||||
ses.last_packet_time_idle = now;
|
||||
ses.last_packet_time_any_sent = 0;
|
||||
ses.last_packet_time_keepalive_sent = 0;
|
||||
|
||||
kexfirstinitialise(); /* initialise the kex state */
|
||||
chaninitialise(); /* initialise the channel state */
|
||||
|
||||
ses.writepayload = buf_new(MAX_TRANS_PAYLOAD_LEN);
|
||||
#if DROPBEAR_FUZZ
|
||||
if (!fuzz.fuzzing)
|
||||
#endif
|
||||
{
|
||||
if (pipe(ses.signal_pipe) < 0) {
|
||||
dropbear_exit("Signal pipe failed");
|
||||
}
|
||||
setnonblocking(ses.signal_pipe[0]);
|
||||
setnonblocking(ses.signal_pipe[1]);
|
||||
ses.maxfd = MAX(ses.maxfd, ses.signal_pipe[0]);
|
||||
ses.maxfd = MAX(ses.maxfd, ses.signal_pipe[1]);
|
||||
}
|
||||
|
||||
ses.writepayload = buf_new(TRANS_MAX_PAYLOAD_LEN);
|
||||
ses.transseq = 0;
|
||||
|
||||
ses.readbuf = NULL;
|
||||
ses.decryptreadbuf = NULL;
|
||||
ses.payload = NULL;
|
||||
ses.recvseq = 0;
|
||||
|
||||
initqueue(&ses.writequeue);
|
||||
|
||||
ses.requirenext = SSH_MSG_KEXINIT;
|
||||
ses.dataallowed = 0; /* don't send data yet, we'll wait until after kex */
|
||||
ses.dataallowed = 1; /* we can send data until we actually
|
||||
send the SSH_MSG_KEXINIT */
|
||||
ses.ignorenext = 0;
|
||||
ses.lastpacket = 0;
|
||||
ses.reply_queue_head = NULL;
|
||||
ses.reply_queue_tail = NULL;
|
||||
|
||||
/* set all the algos to none */
|
||||
ses.keys = (struct key_context*)m_malloc(sizeof(struct key_context));
|
||||
ses.newkeys = NULL;
|
||||
ses.keys->recv_algo_crypt = &dropbear_nocipher;
|
||||
ses.keys->trans_algo_crypt = &dropbear_nocipher;
|
||||
ses.keys->recv.algo_crypt = &dropbear_nocipher;
|
||||
ses.keys->trans.algo_crypt = &dropbear_nocipher;
|
||||
ses.keys->recv.crypt_mode = &dropbear_mode_none;
|
||||
ses.keys->trans.crypt_mode = &dropbear_mode_none;
|
||||
|
||||
ses.keys->recv_algo_mac = &dropbear_nohash;
|
||||
ses.keys->trans_algo_mac = &dropbear_nohash;
|
||||
ses.keys->recv.algo_mac = &dropbear_nohash;
|
||||
ses.keys->trans.algo_mac = &dropbear_nohash;
|
||||
|
||||
ses.keys->algo_kex = -1;
|
||||
ses.keys->algo_kex = NULL;
|
||||
ses.keys->algo_hostkey = -1;
|
||||
ses.keys->recv_algo_comp = DROPBEAR_COMP_NONE;
|
||||
ses.keys->trans_algo_comp = DROPBEAR_COMP_NONE;
|
||||
ses.keys->recv.algo_comp = DROPBEAR_COMP_NONE;
|
||||
ses.keys->trans.algo_comp = DROPBEAR_COMP_NONE;
|
||||
|
||||
#ifndef DISABLE_ZLIB
|
||||
ses.keys->recv_zstream = NULL;
|
||||
ses.keys->trans_zstream = NULL;
|
||||
ses.keys->recv.zstream = NULL;
|
||||
ses.keys->trans.zstream = NULL;
|
||||
#endif
|
||||
|
||||
/* key exchange buffers */
|
||||
@@ -109,11 +147,14 @@ void common_session_init(int sock, char* remotehost) {
|
||||
|
||||
ses.allowprivport = 0;
|
||||
|
||||
#if DROPBEAR_PLUGIN
|
||||
ses.plugin_session = NULL;
|
||||
#endif
|
||||
|
||||
TRACE(("leave session_init"))
|
||||
}
|
||||
|
||||
void session_loop(void(*loophandler)()) {
|
||||
void session_loop(void(*loophandler)(void)) {
|
||||
|
||||
fd_set readfd, writefd;
|
||||
struct timeval timeout;
|
||||
@@ -121,59 +162,90 @@ void session_loop(void(*loophandler)()) {
|
||||
|
||||
/* main loop, select()s for all sockets in use */
|
||||
for(;;) {
|
||||
const int writequeue_has_space = (ses.writequeue_len <= 2*TRANS_MAX_PAYLOAD_LEN);
|
||||
|
||||
timeout.tv_sec = SELECT_TIMEOUT;
|
||||
timeout.tv_sec = select_timeout();
|
||||
timeout.tv_usec = 0;
|
||||
FD_ZERO(&writefd);
|
||||
FD_ZERO(&readfd);
|
||||
assert(ses.payload == NULL);
|
||||
if (ses.sock != -1) {
|
||||
FD_SET(ses.sock, &readfd);
|
||||
if (!isempty(&ses.writequeue)) {
|
||||
FD_SET(ses.sock, &writefd);
|
||||
}
|
||||
DROPBEAR_FD_ZERO(&writefd);
|
||||
DROPBEAR_FD_ZERO(&readfd);
|
||||
|
||||
dropbear_assert(ses.payload == NULL);
|
||||
|
||||
/* We get woken up when signal handlers write to this pipe.
|
||||
SIGCHLD in svr-chansession is the only one currently. */
|
||||
#if DROPBEAR_FUZZ
|
||||
if (!fuzz.fuzzing)
|
||||
#endif
|
||||
{
|
||||
FD_SET(ses.signal_pipe[0], &readfd);
|
||||
}
|
||||
|
||||
/* set up for channels which require reading/writing */
|
||||
if (ses.dataallowed) {
|
||||
setchannelfds(&readfd, &writefd);
|
||||
/* set up for channels which can be read/written */
|
||||
setchannelfds(&readfd, &writefd, writequeue_has_space);
|
||||
|
||||
/* Pending connections to test */
|
||||
set_connect_fds(&writefd);
|
||||
|
||||
/* We delay reading from the input socket during initial setup until
|
||||
after we have written out our initial KEXINIT packet (empty writequeue).
|
||||
This means our initial packet can be in-flight while we're doing a blocking
|
||||
read for the remote ident.
|
||||
We also avoid reading from the socket if the writequeue is full, that avoids
|
||||
replies backing up */
|
||||
if (ses.sock_in != -1
|
||||
&& (ses.remoteident || isempty(&ses.writequeue))
|
||||
&& writequeue_has_space) {
|
||||
FD_SET(ses.sock_in, &readfd);
|
||||
}
|
||||
|
||||
/* Ordering is important, this test must occur after any other function
|
||||
might have queued packets (such as connection handlers) */
|
||||
if (ses.sock_out != -1 && !isempty(&ses.writequeue)) {
|
||||
FD_SET(ses.sock_out, &writefd);
|
||||
}
|
||||
|
||||
val = select(ses.maxfd+1, &readfd, &writefd, NULL, &timeout);
|
||||
|
||||
if (exitflag) {
|
||||
if (ses.exitflag) {
|
||||
dropbear_exit("Terminated by signal");
|
||||
}
|
||||
|
||||
if (val < 0) {
|
||||
if (errno == EINTR) {
|
||||
/* This must happen even if we've been interrupted, so that
|
||||
* changed signal-handler vars can take effect etc */
|
||||
if (loophandler) {
|
||||
loophandler();
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
dropbear_exit("Error in select");
|
||||
}
|
||||
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. */
|
||||
DROPBEAR_FD_ZERO(&writefd);
|
||||
DROPBEAR_FD_ZERO(&readfd);
|
||||
}
|
||||
|
||||
/* We'll just empty out the pipe if required. We don't do
|
||||
any thing with the data, since the pipe's purpose is purely to
|
||||
wake up the select() above. */
|
||||
ses.channel_signal_pending = 0;
|
||||
if (FD_ISSET(ses.signal_pipe[0], &readfd)) {
|
||||
char x;
|
||||
TRACE(("signal pipe set"))
|
||||
while (read(ses.signal_pipe[0], &x, 1) > 0) {}
|
||||
ses.channel_signal_pending = 1;
|
||||
}
|
||||
|
||||
/* check for auth timeout, rekeying required etc */
|
||||
checktimeouts();
|
||||
|
||||
if (val == 0) {
|
||||
/* timeout */
|
||||
TRACE(("select timeout"))
|
||||
continue;
|
||||
}
|
||||
|
||||
/* process session socket's incoming/outgoing data */
|
||||
if (ses.sock != -1) {
|
||||
if (FD_ISSET(ses.sock, &writefd) && !isempty(&ses.writequeue)) {
|
||||
write_packet();
|
||||
}
|
||||
|
||||
if (FD_ISSET(ses.sock, &readfd)) {
|
||||
read_packet();
|
||||
/* process session socket's incoming data */
|
||||
if (ses.sock_in != -1) {
|
||||
if (FD_ISSET(ses.sock_in, &readfd)) {
|
||||
if (!ses.remoteident) {
|
||||
/* blocking read of the version string */
|
||||
read_session_identification();
|
||||
} else {
|
||||
read_packet();
|
||||
}
|
||||
}
|
||||
|
||||
/* Process the decrypted packet. After this, the read buffer
|
||||
@@ -183,14 +255,25 @@ void session_loop(void(*loophandler)()) {
|
||||
}
|
||||
}
|
||||
|
||||
/* if required, flush out any queued reply packets that
|
||||
were being held up during a KEX */
|
||||
maybe_flush_reply_queue();
|
||||
|
||||
handle_connect_fds(&writefd);
|
||||
|
||||
/* loop handler prior to channelio, in case the server loophandler closes
|
||||
channels on process exit */
|
||||
loophandler();
|
||||
|
||||
/* process pipes etc for the channels, ses.dataallowed == 0
|
||||
* during rekeying ) */
|
||||
if (ses.dataallowed) {
|
||||
channelio(&readfd, &writefd);
|
||||
}
|
||||
channelio(&readfd, &writefd);
|
||||
|
||||
if (loophandler) {
|
||||
loophandler();
|
||||
/* process session socket's outgoing data */
|
||||
if (ses.sock_out != -1) {
|
||||
if (!isempty(&ses.writequeue)) {
|
||||
write_packet();
|
||||
}
|
||||
}
|
||||
|
||||
} /* for(;;) */
|
||||
@@ -198,46 +281,100 @@ void session_loop(void(*loophandler)()) {
|
||||
/* Not reached */
|
||||
}
|
||||
|
||||
static void cleanup_buf(buffer **buf) {
|
||||
if (!*buf) {
|
||||
return;
|
||||
}
|
||||
buf_burn_free(*buf);
|
||||
*buf = NULL;
|
||||
}
|
||||
|
||||
/* clean up a session on exit */
|
||||
void common_session_cleanup() {
|
||||
void session_cleanup() {
|
||||
|
||||
TRACE(("enter session_cleanup"))
|
||||
|
||||
/* we can't cleanup if we don't know the session state */
|
||||
if (!sessinitdone) {
|
||||
TRACE(("leave session_cleanup: !sessinitdone"))
|
||||
if (!ses.init_done) {
|
||||
TRACE(("leave session_cleanup: !ses.init_done"))
|
||||
return;
|
||||
}
|
||||
|
||||
m_free(ses.session_id);
|
||||
|
||||
/* BEWARE of changing order of functions here. */
|
||||
|
||||
/* Must be before extra_session_cleanup() */
|
||||
chancleanup();
|
||||
|
||||
if (ses.extra_session_cleanup) {
|
||||
ses.extra_session_cleanup();
|
||||
}
|
||||
|
||||
/* After these are freed most functions will fail */
|
||||
#if DROPBEAR_CLEANUP
|
||||
/* listeners call cleanup functions, this should occur before
|
||||
other session state is freed. */
|
||||
remove_all_listeners();
|
||||
|
||||
remove_connect_pending();
|
||||
|
||||
while (!isempty(&ses.writequeue)) {
|
||||
buf_free(dequeue(&ses.writequeue));
|
||||
}
|
||||
|
||||
m_free(ses.newkeys);
|
||||
#ifndef DISABLE_ZLIB
|
||||
if (ses.keys->recv.zstream != NULL) {
|
||||
if (inflateEnd(ses.keys->recv.zstream) == Z_STREAM_ERROR) {
|
||||
dropbear_exit("Crypto error");
|
||||
}
|
||||
m_free(ses.keys->recv.zstream);
|
||||
}
|
||||
#endif
|
||||
|
||||
m_free(ses.remoteident);
|
||||
m_free(ses.authstate.pw_dir);
|
||||
m_free(ses.authstate.pw_name);
|
||||
m_free(ses.authstate.pw_shell);
|
||||
m_free(ses.authstate.pw_passwd);
|
||||
m_free(ses.authstate.username);
|
||||
#endif
|
||||
|
||||
cleanup_buf(&ses.session_id);
|
||||
cleanup_buf(&ses.hash);
|
||||
cleanup_buf(&ses.payload);
|
||||
cleanup_buf(&ses.readbuf);
|
||||
cleanup_buf(&ses.writepayload);
|
||||
cleanup_buf(&ses.kexhashbuf);
|
||||
cleanup_buf(&ses.transkexinit);
|
||||
if (ses.dh_K) {
|
||||
mp_clear(ses.dh_K);
|
||||
}
|
||||
m_free(ses.dh_K);
|
||||
|
||||
m_burn(ses.keys, sizeof(struct key_context));
|
||||
m_free(ses.keys);
|
||||
|
||||
chancleanup();
|
||||
|
||||
TRACE(("leave session_cleanup"))
|
||||
}
|
||||
|
||||
void send_session_identification() {
|
||||
buffer *writebuf = buf_new(strlen(LOCAL_IDENT "\r\n") + 1);
|
||||
buf_putbytes(writebuf, (const unsigned char *) LOCAL_IDENT "\r\n", strlen(LOCAL_IDENT "\r\n"));
|
||||
writebuf_enqueue(writebuf);
|
||||
}
|
||||
|
||||
void session_identification() {
|
||||
|
||||
static void read_session_identification() {
|
||||
/* max length of 255 chars */
|
||||
char linebuf[256];
|
||||
int len = 0;
|
||||
char done = 0;
|
||||
int i;
|
||||
|
||||
/* write our version string, this blocks */
|
||||
if (atomicio(write, ses.sock, LOCAL_IDENT "\r\n",
|
||||
strlen(LOCAL_IDENT "\r\n")) == DROPBEAR_FAILURE) {
|
||||
dropbear_exit("Error writing ident string");
|
||||
}
|
||||
|
||||
/* We allow up to 9 lines before the actual version string, to
|
||||
* account for wrappers/cruft etc. According to the spec only the client
|
||||
* needs to handle this, but no harm in letting the server handle it too */
|
||||
for (i = 0; i < 10; i++) {
|
||||
len = ident_readln(ses.sock, linebuf, sizeof(linebuf));
|
||||
/* Servers may send other lines of data before sending the
|
||||
* version string, client must be able to process such lines.
|
||||
* If they send more than 50 lines, something is wrong */
|
||||
for (i = IS_DROPBEAR_CLIENT ? 50 : 1; i > 0; i--) {
|
||||
len = ident_readln(ses.sock_in, linebuf, sizeof(linebuf));
|
||||
|
||||
if (len < 0 && errno != EINTR) {
|
||||
/* It failed */
|
||||
@@ -252,15 +389,21 @@ void session_identification() {
|
||||
}
|
||||
|
||||
if (!done) {
|
||||
TRACE(("err: %s for '%s'\n", strerror(errno), linebuf))
|
||||
dropbear_exit("Failed to get remote version");
|
||||
TRACE(("error reading remote ident: %s\n", strerror(errno)))
|
||||
ses.remoteclosed();
|
||||
} else {
|
||||
/* linebuf is already null terminated */
|
||||
ses.remoteident = m_malloc(len);
|
||||
memcpy(ses.remoteident, linebuf, len);
|
||||
}
|
||||
|
||||
TRACE(("remoteident: %s", ses.remoteident))
|
||||
/* Shall assume that 2.x will be backwards compatible. */
|
||||
if (strncmp(ses.remoteident, "SSH-2.", 6) != 0
|
||||
&& strncmp(ses.remoteident, "SSH-1.99-", 9) != 0) {
|
||||
dropbear_exit("Incompatible remote version '%s'", ses.remoteident);
|
||||
}
|
||||
|
||||
DEBUG1(("remoteident: %s", ses.remoteident))
|
||||
|
||||
}
|
||||
|
||||
@@ -280,7 +423,7 @@ static int ident_readln(int fd, char* buf, int count) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
FD_ZERO(&fds);
|
||||
DROPBEAR_FD_ZERO(&fds);
|
||||
|
||||
/* select since it's a non-blocking fd */
|
||||
|
||||
@@ -321,6 +464,11 @@ static int ident_readln(int fd, char* buf, int count) {
|
||||
TRACE(("leave ident_readln: EOF"))
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
fuzz_dump(&in, 1);
|
||||
#endif
|
||||
|
||||
if (in == '\n') {
|
||||
/* end of ident string */
|
||||
break;
|
||||
@@ -338,20 +486,57 @@ static int ident_readln(int fd, char* buf, int count) {
|
||||
return pos+1;
|
||||
}
|
||||
|
||||
void ignore_recv_response() {
|
||||
/* Do nothing */
|
||||
TRACE(("Ignored msg_request_response"))
|
||||
}
|
||||
|
||||
static void send_msg_keepalive() {
|
||||
time_t old_time_idle = ses.last_packet_time_idle;
|
||||
struct Channel *chan = get_any_ready_channel();
|
||||
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
if (chan) {
|
||||
/* Channel requests are preferable, more implementations
|
||||
handle them than SSH_MSG_GLOBAL_REQUEST */
|
||||
TRACE(("keepalive channel request %d", chan->index))
|
||||
start_send_channel_request(chan, DROPBEAR_KEEPALIVE_STRING);
|
||||
} else {
|
||||
TRACE(("keepalive global request"))
|
||||
/* Some peers will reply with SSH_MSG_REQUEST_FAILURE,
|
||||
some will reply with SSH_MSG_UNIMPLEMENTED, some will exit. */
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST);
|
||||
buf_putstring(ses.writepayload, DROPBEAR_KEEPALIVE_STRING,
|
||||
strlen(DROPBEAR_KEEPALIVE_STRING));
|
||||
}
|
||||
buf_putbyte(ses.writepayload, 1); /* want_reply */
|
||||
encrypt_packet();
|
||||
|
||||
ses.last_packet_time_keepalive_sent = monotonic_now();
|
||||
|
||||
/* keepalives shouldn't update idle timeout, reset it back */
|
||||
ses.last_packet_time_idle = old_time_idle;
|
||||
}
|
||||
|
||||
/* Returns the difference in seconds, clamped to LONG_MAX */
|
||||
static long elapsed(time_t now, time_t prev) {
|
||||
time_t del = now - prev;
|
||||
if (del > LONG_MAX) {
|
||||
return LONG_MAX;
|
||||
}
|
||||
return (long)del;
|
||||
}
|
||||
|
||||
/* Check all timeouts which are required. Currently these are the time for
|
||||
* user authentication, and the automatic rekeying. */
|
||||
static void checktimeouts() {
|
||||
|
||||
struct timeval tv;
|
||||
long secs;
|
||||
time_t now;
|
||||
now = monotonic_now();
|
||||
|
||||
if (gettimeofday(&tv, 0) < 0) {
|
||||
dropbear_exit("Error getting time");
|
||||
}
|
||||
|
||||
secs = tv.tv_sec;
|
||||
|
||||
if (ses.connecttimeout != 0 && secs > ses.connecttimeout) {
|
||||
if (IS_DROPBEAR_SERVER && ses.connect_time != 0
|
||||
&& elapsed(now, ses.connect_time) >= AUTH_TIMEOUT) {
|
||||
dropbear_close("Timeout before auth");
|
||||
}
|
||||
|
||||
@@ -361,10 +546,160 @@ static void checktimeouts() {
|
||||
}
|
||||
|
||||
if (!ses.kexstate.sentkexinit
|
||||
&& (secs - ses.kexstate.lastkextime >= KEX_REKEY_TIMEOUT
|
||||
|| ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)){
|
||||
&& (elapsed(now, ses.kexstate.lastkextime) >= KEX_REKEY_TIMEOUT
|
||||
|| ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)) {
|
||||
TRACE(("rekeying after timeout or max data reached"))
|
||||
send_msg_kexinit();
|
||||
}
|
||||
|
||||
if (opts.keepalive_secs > 0 && ses.authstate.authdone) {
|
||||
/* Avoid sending keepalives prior to auth - those are
|
||||
not valid pre-auth packet types */
|
||||
|
||||
/* Send keepalives if we've been idle */
|
||||
if (elapsed(now, ses.last_packet_time_any_sent) >= opts.keepalive_secs) {
|
||||
send_msg_keepalive();
|
||||
}
|
||||
|
||||
/* Also send an explicit keepalive message to trigger a response
|
||||
if the remote end hasn't sent us anything */
|
||||
if (elapsed(now, ses.last_packet_time_keepalive_recv) >= opts.keepalive_secs
|
||||
&& elapsed(now, ses.last_packet_time_keepalive_sent) >= opts.keepalive_secs) {
|
||||
send_msg_keepalive();
|
||||
}
|
||||
|
||||
if (elapsed(now, ses.last_packet_time_keepalive_recv)
|
||||
>= opts.keepalive_secs * DEFAULT_KEEPALIVE_LIMIT) {
|
||||
dropbear_exit("Keepalive timeout");
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.idle_timeout_secs > 0
|
||||
&& elapsed(now, ses.last_packet_time_idle) >= opts.idle_timeout_secs) {
|
||||
dropbear_close("Idle timeout");
|
||||
}
|
||||
}
|
||||
|
||||
static void update_timeout(long limit, time_t now, time_t last_event, long * timeout) {
|
||||
TRACE2(("update_timeout limit %ld, now %llu, last %llu, timeout %ld",
|
||||
limit,
|
||||
(unsigned long long)now,
|
||||
(unsigned long long)last_event, *timeout))
|
||||
if (last_event > 0 && limit > 0) {
|
||||
*timeout = MIN(*timeout, elapsed(now, last_event) + limit);
|
||||
TRACE2(("new timeout %ld", *timeout))
|
||||
}
|
||||
}
|
||||
|
||||
static long select_timeout() {
|
||||
/* determine the minimum timeout that might be required, so
|
||||
as to avoid waking when unneccessary */
|
||||
long timeout = KEX_REKEY_TIMEOUT;
|
||||
time_t now = monotonic_now();
|
||||
|
||||
if (!ses.kexstate.sentkexinit) {
|
||||
update_timeout(KEX_REKEY_TIMEOUT, now, ses.kexstate.lastkextime, &timeout);
|
||||
}
|
||||
|
||||
if (ses.authstate.authdone != 1 && IS_DROPBEAR_SERVER) {
|
||||
/* AUTH_TIMEOUT is only relevant before authdone */
|
||||
update_timeout(AUTH_TIMEOUT, now, ses.connect_time, &timeout);
|
||||
}
|
||||
|
||||
if (ses.authstate.authdone) {
|
||||
update_timeout(opts.keepalive_secs, now,
|
||||
MAX(ses.last_packet_time_keepalive_recv, ses.last_packet_time_keepalive_sent),
|
||||
&timeout);
|
||||
}
|
||||
|
||||
update_timeout(opts.idle_timeout_secs, now, ses.last_packet_time_idle,
|
||||
&timeout);
|
||||
|
||||
/* clamp negative timeouts to zero - event has already triggered */
|
||||
return MAX(timeout, 0);
|
||||
}
|
||||
|
||||
const char* get_user_shell() {
|
||||
/* an empty shell should be interpreted as "/bin/sh" */
|
||||
if (ses.authstate.pw_shell[0] == '\0') {
|
||||
return "/bin/sh";
|
||||
} else {
|
||||
return ses.authstate.pw_shell;
|
||||
}
|
||||
}
|
||||
void fill_passwd(const char* username) {
|
||||
struct passwd *pw = NULL;
|
||||
if (ses.authstate.pw_name)
|
||||
m_free(ses.authstate.pw_name);
|
||||
if (ses.authstate.pw_dir)
|
||||
m_free(ses.authstate.pw_dir);
|
||||
if (ses.authstate.pw_shell)
|
||||
m_free(ses.authstate.pw_shell);
|
||||
if (ses.authstate.pw_passwd)
|
||||
m_free(ses.authstate.pw_passwd);
|
||||
|
||||
pw = getpwnam(username);
|
||||
if (!pw) {
|
||||
return;
|
||||
}
|
||||
ses.authstate.pw_uid = pw->pw_uid;
|
||||
ses.authstate.pw_gid = pw->pw_gid;
|
||||
ses.authstate.pw_name = m_strdup(pw->pw_name);
|
||||
ses.authstate.pw_dir = m_strdup(pw->pw_dir);
|
||||
ses.authstate.pw_shell = m_strdup(pw->pw_shell);
|
||||
{
|
||||
char *passwd_crypt = pw->pw_passwd;
|
||||
#ifdef HAVE_SHADOW_H
|
||||
/* get the shadow password if possible */
|
||||
struct spwd *spasswd = getspnam(ses.authstate.pw_name);
|
||||
if (spasswd && spasswd->sp_pwdp) {
|
||||
passwd_crypt = spasswd->sp_pwdp;
|
||||
}
|
||||
#endif
|
||||
if (!passwd_crypt) {
|
||||
/* android supposedly returns NULL */
|
||||
passwd_crypt = "!!";
|
||||
}
|
||||
ses.authstate.pw_passwd = m_strdup(passwd_crypt);
|
||||
}
|
||||
}
|
||||
|
||||
/* Called when channels are modified */
|
||||
void update_channel_prio() {
|
||||
enum dropbear_prio new_prio;
|
||||
int any = 0;
|
||||
unsigned int i;
|
||||
|
||||
TRACE(("update_channel_prio"))
|
||||
|
||||
if (ses.sock_out < 0) {
|
||||
TRACE(("leave update_channel_prio: no socket"))
|
||||
return;
|
||||
}
|
||||
|
||||
new_prio = DROPBEAR_PRIO_NORMAL;
|
||||
for (i = 0; i < ses.chansize; i++) {
|
||||
struct Channel *channel = ses.channels[i];
|
||||
if (!channel) {
|
||||
continue;
|
||||
}
|
||||
any = 1;
|
||||
if (channel->prio == DROPBEAR_PRIO_LOWDELAY) {
|
||||
new_prio = DROPBEAR_PRIO_LOWDELAY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (any == 0) {
|
||||
/* lowdelay during setup */
|
||||
TRACE(("update_channel_prio: not any"))
|
||||
new_prio = DROPBEAR_PRIO_LOWDELAY;
|
||||
}
|
||||
|
||||
if (new_prio != ses.socket_prio) {
|
||||
TRACE(("Dropbear priority transitioning %d -> %d", ses.socket_prio, new_prio))
|
||||
set_sock_priority(ses.sock_out, new_prio);
|
||||
ses.socket_prio = new_prio;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
26
compat.c
26
compat.c
@@ -114,8 +114,8 @@ size_t strlcpy(char *dst, const char *src, size_t size) {
|
||||
#endif /* HAVE_STRLCPY */
|
||||
|
||||
#ifndef HAVE_STRLCAT
|
||||
/* taken from openbsd-compat for OpenSSH 3.6.1p1 */
|
||||
/* "$OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $"
|
||||
/* taken from openbsd-compat for OpenSSH 7.2p2 */
|
||||
/* "$OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $"
|
||||
*
|
||||
* Appends src to string dst of size siz (unlike strncat, siz is the
|
||||
* full size of dst, not space left). At most siz-1 characters
|
||||
@@ -123,15 +123,12 @@ size_t strlcpy(char *dst, const char *src, size_t size) {
|
||||
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
||||
* If retval >= siz, truncation occurred.
|
||||
*/
|
||||
size_t
|
||||
strlcat(dst, src, siz)
|
||||
char *dst;
|
||||
const char *src;
|
||||
size_t siz;
|
||||
size_t
|
||||
strlcat(char *dst, const char *src, size_t siz)
|
||||
{
|
||||
register char *d = dst;
|
||||
register const char *s = src;
|
||||
register size_t n = siz;
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
size_t n = siz;
|
||||
size_t dlen;
|
||||
|
||||
/* Find the end of dst and adjust bytes left but don't go past end */
|
||||
@@ -177,7 +174,7 @@ int daemon(int nochdir, int noclose) {
|
||||
if (!nochdir)
|
||||
(void)chdir("/");
|
||||
|
||||
if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
|
||||
if (!noclose && (fd = open(DROPBEAR_PATH_DEVNULL, O_RDWR, 0)) != -1) {
|
||||
(void)dup2(fd, STDIN_FILENO);
|
||||
(void)dup2(fd, STDOUT_FILENO);
|
||||
(void)dup2(fd, STDERR_FILENO);
|
||||
@@ -193,6 +190,10 @@ int daemon(int nochdir, int noclose) {
|
||||
char *basename(const char *path) {
|
||||
|
||||
char *foo = strrchr(path, '/');
|
||||
if (!foo)
|
||||
{
|
||||
return path;
|
||||
}
|
||||
return ++foo;
|
||||
}
|
||||
|
||||
@@ -230,8 +231,7 @@ void setusershell() {
|
||||
}
|
||||
|
||||
static char **initshells() {
|
||||
/* don't touch this list. */
|
||||
const char *okshells[] = { "/bin/sh", "/bin/csh", NULL };
|
||||
static const char *okshells[] = { COMPAT_USER_SHELLS, NULL };
|
||||
register char **sp, *cp;
|
||||
register FILE *fp;
|
||||
struct stat statb;
|
||||
|
||||
16
compat.h
16
compat.h
@@ -22,8 +22,8 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#ifndef _COMPAT_H_
|
||||
#define _COMPAT_H_
|
||||
#ifndef DROPBEAR_COMPAT_H_
|
||||
#define DROPBEAR_COMPAT_H_
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
@@ -44,13 +44,13 @@ char *basename(const char* path);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETUSERSHELL
|
||||
char *getusershell();
|
||||
void setusershell();
|
||||
void endusershell();
|
||||
char *getusershell(void);
|
||||
void setusershell(void);
|
||||
void endusershell(void);
|
||||
#endif
|
||||
|
||||
#ifndef _PATH_DEVNULL
|
||||
#define _PATH_DEVNULL "/dev/null"
|
||||
#ifndef DROPBEAR_PATH_DEVNULL
|
||||
#define DROPBEAR_PATH_DEVNULL "/dev/null"
|
||||
#endif
|
||||
|
||||
#endif /* _COMPAT_H_ */
|
||||
#endif /* DROPBEAR_COMPAT_H_ */
|
||||
|
||||
1975
config.guess
vendored
1975
config.guess
vendored
File diff suppressed because it is too large
Load Diff
456
config.h.in
Normal file
456
config.h.in
Normal file
@@ -0,0 +1,456 @@
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Using AIX */
|
||||
#undef AIX
|
||||
|
||||
/* Broken getaddrinfo */
|
||||
#undef BROKEN_GETADDRINFO
|
||||
|
||||
/* Use bundled libtom */
|
||||
#undef BUNDLED_LIBTOM
|
||||
|
||||
/* lastlog file location */
|
||||
#undef CONF_LASTLOG_FILE
|
||||
|
||||
/* utmpx file location */
|
||||
#undef CONF_UTMPX_FILE
|
||||
|
||||
/* utmp file location */
|
||||
#undef CONF_UTMP_FILE
|
||||
|
||||
/* wtmpx file location */
|
||||
#undef CONF_WTMPX_FILE
|
||||
|
||||
/* wtmp file location */
|
||||
#undef CONF_WTMP_FILE
|
||||
|
||||
/* Disable use of lastlog() */
|
||||
#undef DISABLE_LASTLOG
|
||||
|
||||
/* Use PAM */
|
||||
#undef DISABLE_PAM
|
||||
|
||||
/* Disable use of pututline() */
|
||||
#undef DISABLE_PUTUTLINE
|
||||
|
||||
/* Disable use of pututxline() */
|
||||
#undef DISABLE_PUTUTXLINE
|
||||
|
||||
/* Using syslog */
|
||||
#undef DISABLE_SYSLOG
|
||||
|
||||
/* Disable use of utmp */
|
||||
#undef DISABLE_UTMP
|
||||
|
||||
/* Disable use of utmpx */
|
||||
#undef DISABLE_UTMPX
|
||||
|
||||
/* Disable use of wtmp */
|
||||
#undef DISABLE_WTMP
|
||||
|
||||
/* Disable use of wtmpx */
|
||||
#undef DISABLE_WTMPX
|
||||
|
||||
/* Use zlib */
|
||||
#undef DISABLE_ZLIB
|
||||
|
||||
/* Fuzzing */
|
||||
#undef DROPBEAR_FUZZ
|
||||
|
||||
/* External Public Key Authentication */
|
||||
#undef DROPBEAR_PLUGIN
|
||||
|
||||
/* Define to 1 if you have the `basename' function. */
|
||||
#undef HAVE_BASENAME
|
||||
|
||||
/* Define to 1 if you have the `clearenv' function. */
|
||||
#undef HAVE_CLEARENV
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
#undef HAVE_CLOCK_GETTIME
|
||||
|
||||
/* Define if gai_strerror() returns const char * */
|
||||
#undef HAVE_CONST_GAI_STRERROR_PROTO
|
||||
|
||||
/* crypt() function */
|
||||
#undef HAVE_CRYPT
|
||||
|
||||
/* Define to 1 if you have the <crypt.h> header file. */
|
||||
#undef HAVE_CRYPT_H
|
||||
|
||||
/* Define to 1 if you have the `daemon' function. */
|
||||
#undef HAVE_DAEMON
|
||||
|
||||
/* Use /dev/ptc & /dev/pts */
|
||||
#undef HAVE_DEV_PTS_AND_PTC
|
||||
|
||||
/* Define to 1 if you have the `endutent' function. */
|
||||
#undef HAVE_ENDUTENT
|
||||
|
||||
/* Define to 1 if you have the `endutxent' function. */
|
||||
#undef HAVE_ENDUTXENT
|
||||
|
||||
/* Define to 1 if you have the `explicit_bzero' function. */
|
||||
#undef HAVE_EXPLICIT_BZERO
|
||||
|
||||
/* Define to 1 if you have the `fexecve' function. */
|
||||
#undef HAVE_FEXECVE
|
||||
|
||||
/* Define to 1 if you have the `fork' function. */
|
||||
#undef HAVE_FORK
|
||||
|
||||
/* Define to 1 if you have the `freeaddrinfo' function. */
|
||||
#undef HAVE_FREEADDRINFO
|
||||
|
||||
/* Define to 1 if you have the `gai_strerror' function. */
|
||||
#undef HAVE_GAI_STRERROR
|
||||
|
||||
/* Define to 1 if you have the `getaddrinfo' function. */
|
||||
#undef HAVE_GETADDRINFO
|
||||
|
||||
/* Define to 1 if you have the `getgrouplist' function. */
|
||||
#undef HAVE_GETGROUPLIST
|
||||
|
||||
/* Define to 1 if you have the `getnameinfo' function. */
|
||||
#undef HAVE_GETNAMEINFO
|
||||
|
||||
/* Define to 1 if you have the `getpass' function. */
|
||||
#undef HAVE_GETPASS
|
||||
|
||||
/* Define to 1 if you have the `getrandom' function. */
|
||||
#undef HAVE_GETRANDOM
|
||||
|
||||
/* Define to 1 if you have the `getspnam' function. */
|
||||
#undef HAVE_GETSPNAM
|
||||
|
||||
/* Define to 1 if you have the `getusershell' function. */
|
||||
#undef HAVE_GETUSERSHELL
|
||||
|
||||
/* Define to 1 if you have the `getutent' function. */
|
||||
#undef HAVE_GETUTENT
|
||||
|
||||
/* Define to 1 if you have the `getutid' function. */
|
||||
#undef HAVE_GETUTID
|
||||
|
||||
/* Define to 1 if you have the `getutline' function. */
|
||||
#undef HAVE_GETUTLINE
|
||||
|
||||
/* Define to 1 if you have the `getutxent' function. */
|
||||
#undef HAVE_GETUTXENT
|
||||
|
||||
/* Define to 1 if you have the `getutxid' function. */
|
||||
#undef HAVE_GETUTXID
|
||||
|
||||
/* Define to 1 if you have the `getutxline' function. */
|
||||
#undef HAVE_GETUTXLINE
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the <lastlog.h> header file. */
|
||||
#undef HAVE_LASTLOG_H
|
||||
|
||||
/* Define to 1 if you have the <libgen.h> header file. */
|
||||
#undef HAVE_LIBGEN_H
|
||||
|
||||
/* Define to 1 if you have the `pam' library (-lpam). */
|
||||
#undef HAVE_LIBPAM
|
||||
|
||||
/* Define to 1 if you have the <libutil.h> header file. */
|
||||
#undef HAVE_LIBUTIL_H
|
||||
|
||||
/* Define to 1 if you have the `z' library (-lz). */
|
||||
#undef HAVE_LIBZ
|
||||
|
||||
/* Define to 1 if you have the <linux/pkt_sched.h> header file. */
|
||||
#undef HAVE_LINUX_PKT_SCHED_H
|
||||
|
||||
/* Have login() function */
|
||||
#undef HAVE_LOGIN
|
||||
|
||||
/* Define to 1 if you have the `logout' function. */
|
||||
#undef HAVE_LOGOUT
|
||||
|
||||
/* Define to 1 if you have the `logwtmp' function. */
|
||||
#undef HAVE_LOGWTMP
|
||||
|
||||
/* Define to 1 if you have the `mach_absolute_time' function. */
|
||||
#undef HAVE_MACH_ABSOLUTE_TIME
|
||||
|
||||
/* Define to 1 if you have the <mach/mach_time.h> header file. */
|
||||
#undef HAVE_MACH_MACH_TIME_H
|
||||
|
||||
/* Define to 1 if you have the `memset_s' function. */
|
||||
#undef HAVE_MEMSET_S
|
||||
|
||||
/* Define to 1 if you have the <netdb.h> header file. */
|
||||
#undef HAVE_NETDB_H
|
||||
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
#undef HAVE_NETINET_IN_H
|
||||
|
||||
/* Define to 1 if you have the <netinet/in_systm.h> header file. */
|
||||
#undef HAVE_NETINET_IN_SYSTM_H
|
||||
|
||||
/* Define to 1 if you have the <netinet/tcp.h> header file. */
|
||||
#undef HAVE_NETINET_TCP_H
|
||||
|
||||
/* Have openpty() function */
|
||||
#undef HAVE_OPENPTY
|
||||
|
||||
/* Define to 1 if you have the `pam_fail_delay' function. */
|
||||
#undef HAVE_PAM_FAIL_DELAY
|
||||
|
||||
/* Define to 1 if you have the <pam/pam_appl.h> header file. */
|
||||
#undef HAVE_PAM_PAM_APPL_H
|
||||
|
||||
/* Define to 1 if you have the <paths.h> header file. */
|
||||
#undef HAVE_PATHS_H
|
||||
|
||||
/* Define to 1 if you have the <pty.h> header file. */
|
||||
#undef HAVE_PTY_H
|
||||
|
||||
/* Define to 1 if you have the `putenv' function. */
|
||||
#undef HAVE_PUTENV
|
||||
|
||||
/* Define to 1 if you have the `pututline' function. */
|
||||
#undef HAVE_PUTUTLINE
|
||||
|
||||
/* Define to 1 if you have the `pututxline' function. */
|
||||
#undef HAVE_PUTUTXLINE
|
||||
|
||||
/* Define to 1 if you have the <security/pam_appl.h> header file. */
|
||||
#undef HAVE_SECURITY_PAM_APPL_H
|
||||
|
||||
/* Define to 1 if you have the `setutent' function. */
|
||||
#undef HAVE_SETUTENT
|
||||
|
||||
/* Define to 1 if you have the `setutxent' function. */
|
||||
#undef HAVE_SETUTXENT
|
||||
|
||||
/* Define to 1 if you have the <shadow.h> header file. */
|
||||
#undef HAVE_SHADOW_H
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#undef HAVE_STDIO_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the `strlcat' function. */
|
||||
#undef HAVE_STRLCAT
|
||||
|
||||
/* Define to 1 if you have the `strlcpy' function. */
|
||||
#undef HAVE_STRLCPY
|
||||
|
||||
/* Define to 1 if you have the <stropts.h> header file. */
|
||||
#undef HAVE_STROPTS_H
|
||||
|
||||
/* Have struct addrinfo */
|
||||
#undef HAVE_STRUCT_ADDRINFO
|
||||
|
||||
/* Have struct in6_addr */
|
||||
#undef HAVE_STRUCT_IN6_ADDR
|
||||
|
||||
/* Have struct sockaddr_in6 */
|
||||
#undef HAVE_STRUCT_SOCKADDR_IN6
|
||||
|
||||
/* Define to 1 if the system has the type `struct sockaddr_storage'. */
|
||||
#undef HAVE_STRUCT_SOCKADDR_STORAGE
|
||||
|
||||
/* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */
|
||||
#undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY
|
||||
|
||||
/* Define to 1 if `ut_addr' is a member of `struct utmpx'. */
|
||||
#undef HAVE_STRUCT_UTMPX_UT_ADDR
|
||||
|
||||
/* Define to 1 if `ut_addr_v6' is a member of `struct utmpx'. */
|
||||
#undef HAVE_STRUCT_UTMPX_UT_ADDR_V6
|
||||
|
||||
/* Define to 1 if `ut_host' is a member of `struct utmpx'. */
|
||||
#undef HAVE_STRUCT_UTMPX_UT_HOST
|
||||
|
||||
/* Define to 1 if `ut_id' is a member of `struct utmpx'. */
|
||||
#undef HAVE_STRUCT_UTMPX_UT_ID
|
||||
|
||||
/* Define to 1 if `ut_syslen' is a member of `struct utmpx'. */
|
||||
#undef HAVE_STRUCT_UTMPX_UT_SYSLEN
|
||||
|
||||
/* Define to 1 if `ut_time' is a member of `struct utmpx'. */
|
||||
#undef HAVE_STRUCT_UTMPX_UT_TIME
|
||||
|
||||
/* Define to 1 if `ut_tv' is a member of `struct utmpx'. */
|
||||
#undef HAVE_STRUCT_UTMPX_UT_TV
|
||||
|
||||
/* Define to 1 if `ut_type' is a member of `struct utmpx'. */
|
||||
#undef HAVE_STRUCT_UTMPX_UT_TYPE
|
||||
|
||||
/* Define to 1 if `ut_addr' is a member of `struct utmp'. */
|
||||
#undef HAVE_STRUCT_UTMP_UT_ADDR
|
||||
|
||||
/* Define to 1 if `ut_addr_v6' is a member of `struct utmp'. */
|
||||
#undef HAVE_STRUCT_UTMP_UT_ADDR_V6
|
||||
|
||||
/* Define to 1 if `ut_exit' is a member of `struct utmp'. */
|
||||
#undef HAVE_STRUCT_UTMP_UT_EXIT
|
||||
|
||||
/* Define to 1 if `ut_host' is a member of `struct utmp'. */
|
||||
#undef HAVE_STRUCT_UTMP_UT_HOST
|
||||
|
||||
/* Define to 1 if `ut_id' is a member of `struct utmp'. */
|
||||
#undef HAVE_STRUCT_UTMP_UT_ID
|
||||
|
||||
/* Define to 1 if `ut_pid' is a member of `struct utmp'. */
|
||||
#undef HAVE_STRUCT_UTMP_UT_PID
|
||||
|
||||
/* Define to 1 if `ut_time' is a member of `struct utmp'. */
|
||||
#undef HAVE_STRUCT_UTMP_UT_TIME
|
||||
|
||||
/* Define to 1 if `ut_tv' is a member of `struct utmp'. */
|
||||
#undef HAVE_STRUCT_UTMP_UT_TV
|
||||
|
||||
/* Define to 1 if `ut_type' is a member of `struct utmp'. */
|
||||
#undef HAVE_STRUCT_UTMP_UT_TYPE
|
||||
|
||||
/* Define to 1 if you have the <sys/prctl.h> header file. */
|
||||
#undef HAVE_SYS_PRCTL_H
|
||||
|
||||
/* Define to 1 if you have the <sys/random.h> header file. */
|
||||
#undef HAVE_SYS_RANDOM_H
|
||||
|
||||
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||
#undef HAVE_SYS_SELECT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
#undef HAVE_SYS_SOCKET_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <sys/uio.h> header file. */
|
||||
#undef HAVE_SYS_UIO_H
|
||||
|
||||
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
|
||||
#undef HAVE_SYS_WAIT_H
|
||||
|
||||
/* Define to 1 if the system has the type `uint16_t'. */
|
||||
#undef HAVE_UINT16_T
|
||||
|
||||
/* Define to 1 if the system has the type `uint32_t'. */
|
||||
#undef HAVE_UINT32_T
|
||||
|
||||
/* Define to 1 if the system has the type `uint8_t'. */
|
||||
#undef HAVE_UINT8_T
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to 1 if you have the `updwtmp' function. */
|
||||
#undef HAVE_UPDWTMP
|
||||
|
||||
/* Define to 1 if you have the <util.h> header file. */
|
||||
#undef HAVE_UTIL_H
|
||||
|
||||
/* Define to 1 if you have the `utmpname' function. */
|
||||
#undef HAVE_UTMPNAME
|
||||
|
||||
/* Define to 1 if you have the `utmpxname' function. */
|
||||
#undef HAVE_UTMPXNAME
|
||||
|
||||
/* Define to 1 if you have the <utmpx.h> header file. */
|
||||
#undef HAVE_UTMPX_H
|
||||
|
||||
/* Define to 1 if you have the <utmp.h> header file. */
|
||||
#undef HAVE_UTMP_H
|
||||
|
||||
/* Define to 1 if the system has the type `u_int16_t'. */
|
||||
#undef HAVE_U_INT16_T
|
||||
|
||||
/* Define to 1 if the system has the type `u_int32_t'. */
|
||||
#undef HAVE_U_INT32_T
|
||||
|
||||
/* Define to 1 if the system has the type `u_int8_t'. */
|
||||
#undef HAVE_U_INT8_T
|
||||
|
||||
/* Define to 1 if you have the `writev' function. */
|
||||
#undef HAVE_WRITEV
|
||||
|
||||
/* Define to 1 if you have the `_getpty' function. */
|
||||
#undef HAVE__GETPTY
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Define to the type of arg 1 for `select'. */
|
||||
#undef SELECT_TYPE_ARG1
|
||||
|
||||
/* Define to the type of args 2, 3 and 4 for `select'. */
|
||||
#undef SELECT_TYPE_ARG234
|
||||
|
||||
/* Define to the type of arg 5 for `select'. */
|
||||
#undef SELECT_TYPE_ARG5
|
||||
|
||||
/* Define to 1 if all of the C90 standard headers exist (not just the ones
|
||||
required in a freestanding environment). This macro is provided for
|
||||
backward compatibility; new code need not use it. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Use /dev/ptmx */
|
||||
#undef USE_DEV_PTMX
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
#undef _FILE_OFFSET_BITS
|
||||
|
||||
/* Use GNU extensions if glibc */
|
||||
#undef _GNU_SOURCE
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
#undef _LARGE_FILES
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
#undef const
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#undef gid_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#undef mode_t
|
||||
|
||||
/* Define as a signed integer type capable of holding a process identifier. */
|
||||
#undef pid_t
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
#undef size_t
|
||||
|
||||
/* type to use in place of socklen_t if not defined */
|
||||
#undef socklen_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#undef uid_t
|
||||
2769
config.sub
vendored
2769
config.sub
vendored
File diff suppressed because it is too large
Load Diff
915
configure.ac
Normal file
915
configure.ac
Normal file
@@ -0,0 +1,915 @@
|
||||
# -*- 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.59])
|
||||
AC_INIT
|
||||
AC_CONFIG_SRCDIR(buffer.c)
|
||||
|
||||
# Record which revision is being built
|
||||
if test -s "`which hg`" && test -d "$srcdir/.hg"; then
|
||||
hgrev=`hg id -i -R "$srcdir"`
|
||||
AC_MSG_NOTICE([Source directory Mercurial base revision $hgrev])
|
||||
fi
|
||||
|
||||
ORIGCFLAGS="$CFLAGS"
|
||||
LATE_CFLAGS=""
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
|
||||
if test -z "$LD" ; then
|
||||
LD=$CC
|
||||
fi
|
||||
AC_SUBST(LD)
|
||||
|
||||
AC_DEFUN(DB_TRYADDCFLAGS,
|
||||
[{
|
||||
OLDFLAGS="$CFLAGS"
|
||||
TESTFLAGS="$1"
|
||||
CFLAGS="$TESTFLAGS $CFLAGS"
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
|
||||
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
|
||||
[AC_MSG_NOTICE([Not setting $TESTFLAGS]); CFLAGS="$OLDFLAGS" ]
|
||||
)
|
||||
}])
|
||||
|
||||
# set compile flags prior to other tests
|
||||
if test -z "$ORIGCFLAGS" && test "$GCC" = "yes"; then
|
||||
AC_MSG_NOTICE(No \$CFLAGS set... using "-Os -W -Wall" for GCC)
|
||||
CFLAGS="-Os -W -Wall"
|
||||
fi
|
||||
|
||||
# LTM_CFLAGS is given to ./configure by the user,
|
||||
# DROPBEAR_LTM_CFLAGS is substituted in the LTM Makefile.in
|
||||
DROPBEAR_LTM_CFLAGS="$LTM_CFLAGS"
|
||||
if test -z "$DROPBEAR_LTM_CFLAGS"; then
|
||||
DROPBEAR_LTM_CFLAGS="-O3 -funroll-loops -fomit-frame-pointer"
|
||||
fi
|
||||
AC_MSG_NOTICE(Setting LTM_CFLAGS to $DROPBEAR_LTM_CFLAGS)
|
||||
AC_ARG_VAR(LTM_CFLAGS, CFLAGS for bundled libtommath. Default -O3 -funroll-loops -fomit-frame-pointer)
|
||||
AC_SUBST(DROPBEAR_LTM_CFLAGS)
|
||||
|
||||
AC_MSG_NOTICE([Checking if compiler '$CC' supports -Wno-pointer-sign])
|
||||
DB_TRYADDCFLAGS([-Wno-pointer-sign])
|
||||
|
||||
AC_MSG_NOTICE([Checking if compiler '$CC' supports -fno-strict-overflow])
|
||||
DB_TRYADDCFLAGS([-fno-strict-overflow])
|
||||
|
||||
AC_MSG_NOTICE([Checking if compiler '$CC' supports -Wundef])
|
||||
DB_TRYADDCFLAGS([-Wundef])
|
||||
|
||||
# needed for various extensions. define early before autoconf tests
|
||||
AC_DEFINE([_GNU_SOURCE], [], [Use GNU extensions if glibc])
|
||||
|
||||
STATIC=0
|
||||
AC_ARG_ENABLE(static,
|
||||
[ --enable-static Build static binaries],
|
||||
[
|
||||
if test "x$enableval" = "xyes"; then
|
||||
STATIC=1
|
||||
AC_MSG_NOTICE(Static Build)
|
||||
fi
|
||||
], [])
|
||||
AC_SUBST(STATIC)
|
||||
|
||||
hardenbuild=1
|
||||
AC_ARG_ENABLE(harden,
|
||||
[ --disable-harden Don't set hardened build flags],
|
||||
[
|
||||
if test "x$enableval" = "xno"; then
|
||||
hardenbuild=0
|
||||
AC_MSG_NOTICE(Disabling hardened build flags)
|
||||
fi
|
||||
], [])
|
||||
|
||||
if test "$hardenbuild" -eq 1; then
|
||||
AC_MSG_NOTICE(Checking for available hardened build flags:)
|
||||
# relocation flags don't make sense for static builds
|
||||
if test "$STATIC" -ne 1; then
|
||||
# pie
|
||||
DB_TRYADDCFLAGS([-fPIE])
|
||||
|
||||
OLDLDFLAGS="$LDFLAGS"
|
||||
TESTFLAGS="-Wl,-pie"
|
||||
LDFLAGS="$TESTFLAGS $LDFLAGS"
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
|
||||
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
|
||||
[
|
||||
LDFLAGS="$OLDLDFLAGS"
|
||||
TESTFLAGS="-pie"
|
||||
LDFLAGS="$TESTFLAGS $LDFLAGS"
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
|
||||
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
|
||||
[AC_MSG_NOTICE([Not setting $TESTFLAGS]); LDFLAGS="$OLDLDFLAGS" ]
|
||||
)
|
||||
]
|
||||
)
|
||||
# readonly elf relocation sections (relro)
|
||||
OLDLDFLAGS="$LDFLAGS"
|
||||
TESTFLAGS="-Wl,-z,now -Wl,-z,relro"
|
||||
LDFLAGS="$TESTFLAGS $LDFLAGS"
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
|
||||
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
|
||||
[AC_MSG_NOTICE([Not setting $TESTFLAGS]); LDFLAGS="$OLDLDFLAGS" ]
|
||||
)
|
||||
fi # non-static
|
||||
# stack protector. -strong is good but only in gcc 4.9 or later
|
||||
OLDCFLAGS="$CFLAGS"
|
||||
TESTFLAGS="-fstack-protector-strong"
|
||||
CFLAGS="$TESTFLAGS $CFLAGS"
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
|
||||
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
|
||||
[
|
||||
CFLAGS="$OLDCFLAGS"
|
||||
TESTFLAGS="-fstack-protector --param=ssp-buffer-size=4"
|
||||
CFLAGS="$TESTFLAGS $CFLAGS"
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
|
||||
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
|
||||
[AC_MSG_NOTICE([Not setting $TESTFLAGS]); CFLAGS="$OLDCFLAGS" ]
|
||||
)
|
||||
]
|
||||
)
|
||||
# FORTIFY_SOURCE
|
||||
DB_TRYADDCFLAGS([-D_FORTIFY_SOURCE=2])
|
||||
|
||||
# Spectre v2 mitigations
|
||||
DB_TRYADDCFLAGS([-mfunction-return=thunk])
|
||||
DB_TRYADDCFLAGS([-mindirect-branch=thunk])
|
||||
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(werror,
|
||||
[ --enable-werror Set -Werror when building],
|
||||
[
|
||||
if test "x$enableval" = "xyes"; then
|
||||
# -Werror shouldn't be set when configure runs tests.
|
||||
# We add it to the Makefile's CFLAGS
|
||||
LATE_CFLAGS+="$LATE_CFLAGS -Werror"
|
||||
AC_MSG_NOTICE(Enabling -Werror)
|
||||
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,1,Disable utmp)
|
||||
AC_DEFINE(DISABLE_WTMP,1,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,1,Using AIX)
|
||||
# OpenSSH thinks it's broken. If it isn't, let me know.
|
||||
AC_DEFINE(BROKEN_GETADDRINFO,1,Broken getaddrinfo)
|
||||
;;
|
||||
|
||||
*-*-hpux*)
|
||||
LIBS="$LIBS -lsec"
|
||||
# It's probably broken.
|
||||
AC_DEFINE(BROKEN_GETADDRINFO,1,Broken getaddrinfo)
|
||||
;;
|
||||
*-dec-osf*)
|
||||
AC_DEFINE(BROKEN_GETADDRINFO,1,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.])
|
||||
],,)
|
||||
|
||||
dnl We test for crypt() specially. On Linux (and others?) it resides in libcrypt
|
||||
dnl but we don't want link all binaries to -lcrypt, just dropbear server.
|
||||
dnl OS X doesn't need -lcrypt
|
||||
AC_CHECK_FUNC(crypt, found_crypt_func=here)
|
||||
AC_CHECK_LIB(crypt, crypt,
|
||||
[
|
||||
CRYPTLIB="-lcrypt"
|
||||
found_crypt_func=here
|
||||
])
|
||||
AC_SUBST(CRYPTLIB)
|
||||
if test "t$found_crypt_func" = there; then
|
||||
AC_DEFINE(HAVE_CRYPT, 1, [crypt() function])
|
||||
fi
|
||||
|
||||
# Check if zlib is needed
|
||||
AC_ARG_WITH(zlib,
|
||||
[ --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,1,Use zlib)
|
||||
AC_MSG_NOTICE(Disabling zlib)
|
||||
else
|
||||
AC_CHECK_LIB(z, deflate, , AC_MSG_ERROR([*** zlib missing - install first or check config.log ***]))
|
||||
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)
|
||||
AC_CHECK_FUNCS(pam_fail_delay)
|
||||
else
|
||||
AC_DEFINE(DISABLE_PAM,1,Use PAM)
|
||||
AC_MSG_NOTICE(Disabling PAM)
|
||||
fi
|
||||
],
|
||||
[
|
||||
# disable it by default
|
||||
AC_DEFINE(DISABLE_PAM,1,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, [dropbear_cv_func_have_openpty=yes])
|
||||
fi
|
||||
],
|
||||
[
|
||||
AC_MSG_NOTICE(Using openpty if available)
|
||||
AC_SEARCH_LIBS(openpty, util, [dropbear_cv_func_have_openpty=yes])
|
||||
]
|
||||
)
|
||||
|
||||
if test "x$dropbear_cv_func_have_openpty" = "xyes"; then
|
||||
AC_DEFINE(HAVE_OPENPTY,,Have openpty() function)
|
||||
no_ptc_check=yes
|
||||
no_ptmx_check=yes
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(syslog,
|
||||
[ --disable-syslog Don't include syslog support],
|
||||
[
|
||||
if test "x$enableval" = "xno"; then
|
||||
AC_DEFINE(DISABLE_SYSLOG,1,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)
|
||||
]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE(plugin,
|
||||
[ --enable-plugin Enable support for External Public Key Authentication plug-in],
|
||||
[
|
||||
AC_DEFINE(DROPBEAR_PLUGIN, 1, External Public Key Authentication)
|
||||
AC_MSG_NOTICE(Enabling support for External Public Key Authentication)
|
||||
DROPBEAR_PLUGIN=1
|
||||
],
|
||||
[
|
||||
AC_DEFINE(DROPBEAR_PLUGIN, 0, External Public Key Authentication)
|
||||
DROPBEAR_PLUGIN=0
|
||||
]
|
||||
|
||||
)
|
||||
AC_SUBST(DROPBEAR_PLUGIN)
|
||||
|
||||
AC_ARG_ENABLE(fuzz,
|
||||
[ --enable-fuzz Build fuzzing. Not recommended for deployment.],
|
||||
[
|
||||
if test "x$enableval" = "xyes"; then
|
||||
AC_DEFINE(DROPBEAR_FUZZ, 1, Fuzzing)
|
||||
AC_MSG_NOTICE(Enabling fuzzing)
|
||||
DROPBEAR_FUZZ=1
|
||||
# libfuzzer needs linking with c++ libraries
|
||||
AC_PROG_CXX
|
||||
mkdir -pv fuzz
|
||||
else
|
||||
AC_DEFINE(DROPBEAR_FUZZ, 0, Fuzzing)
|
||||
AC_MSG_NOTICE(Disabling fuzzing)
|
||||
DROPBEAR_FUZZ=0
|
||||
fi
|
||||
],
|
||||
[
|
||||
AC_DEFINE(DROPBEAR_FUZZ, 0, Fuzzing)
|
||||
AC_MSG_NOTICE(Disabling fuzzing)
|
||||
DROPBEAR_FUZZ=0
|
||||
]
|
||||
|
||||
)
|
||||
AC_SUBST(DROPBEAR_FUZZ)
|
||||
AC_SUBST(CXX)
|
||||
|
||||
# Checks for header files.
|
||||
AC_HEADER_SYS_WAIT
|
||||
AC_CHECK_HEADERS([netinet/in.h netinet/tcp.h \
|
||||
crypt.h \
|
||||
pty.h libutil.h libgen.h inttypes.h stropts.h utmp.h \
|
||||
utmpx.h lastlog.h paths.h util.h netdb.h security/pam_appl.h \
|
||||
pam/pam_appl.h netinet/in_systm.h sys/uio.h linux/pkt_sched.h \
|
||||
sys/random.h sys/prctl.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_CHECK_TYPES([uint8_t, u_int8_t, uint16_t, u_int16_t, uint32_t, u_int32_t])
|
||||
AC_CHECK_TYPES([struct sockaddr_storage])
|
||||
AC_CHECK_TYPE([socklen_t], ,[
|
||||
AC_MSG_CHECKING([for socklen_t equivalent])
|
||||
AC_CACHE_VAL([curl_cv_socklen_t_equiv],
|
||||
[
|
||||
# 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_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
int getpeername (int, $arg2 *, $t *);
|
||||
]],[[
|
||||
$t len;
|
||||
getpeername(0,0,&len);
|
||||
]])],[
|
||||
curl_cv_socklen_t_equiv="$t"
|
||||
break
|
||||
])
|
||||
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_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
]],
|
||||
[[ if (sizeof(struct sockaddr_storage)) return 0 ]])],
|
||||
[ 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_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
]],
|
||||
[[ if (sizeof(struct sockaddr_in6)) return 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,1,Have struct sockaddr_in6)
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for struct in6_addr], ac_cv_have_struct_in6_addr, [
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
]],
|
||||
[[ if (sizeof(struct in6_addr)) return 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,1,Have struct in6_addr)
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for struct addrinfo], ac_cv_have_struct_addrinfo, [
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
]],
|
||||
[[ if (sizeof(struct addrinfo)) return 0 ]])],
|
||||
[ 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,1,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_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#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)
|
||||
|
||||
# POSIX monotonic time
|
||||
AC_CHECK_FUNCS(clock_gettime)
|
||||
|
||||
# OS X monotonic time
|
||||
AC_CHECK_HEADERS([mach/mach_time.h])
|
||||
AC_CHECK_FUNCS(mach_absolute_time)
|
||||
|
||||
AC_CHECK_FUNCS(explicit_bzero memset_s getrandom)
|
||||
|
||||
AC_ARG_ENABLE(bundled-libtom,
|
||||
[ --enable-bundled-libtom Force using bundled libtomcrypt/libtommath even if a system version exists.
|
||||
--disable-bundled-libtom Force using system libtomcrypt/libtommath, fail if it does not exist.
|
||||
Default is to use system if available, otherwise bundled.
|
||||
Dropbear requires system libtommath >= 1.2.0 and libtomcrypt >= 1.18.0],
|
||||
[
|
||||
if test "x$enableval" = "xyes"; then
|
||||
BUNDLED_LIBTOM=1
|
||||
AC_MSG_NOTICE(Forcing bundled libtom*)
|
||||
else
|
||||
BUNDLED_LIBTOM=0
|
||||
AC_CHECK_LIB(tommath, mp_to_ubin, LIBTOM_LIBS="-ltommath $LIBTOM_LIBS",
|
||||
[AC_MSG_ERROR([Missing/old system libtommath and --disable-bundled-libtom was specified])] )
|
||||
AC_CHECK_LIB(tomcrypt, poly1305_init, LIBTOM_LIBS="-ltomcrypt $LIBTOM_LIBS",
|
||||
[AC_MSG_ERROR([Missing/old system libtomcrypt and --disable-bundled-libtom was specified])] )
|
||||
fi
|
||||
],
|
||||
[
|
||||
BUNDLED_LIBTOM=0
|
||||
AC_CHECK_LIB(tommath, mp_to_ubin, LIBTOM_LIBS="-ltommath $LIBTOM_LIBS", BUNDLED_LIBTOM=1)
|
||||
AC_CHECK_LIB(tomcrypt, poly1305_init, LIBTOM_LIBS="-ltomcrypt $LIBTOM_LIBS", BUNDLED_LIBTOM=1)
|
||||
]
|
||||
)
|
||||
|
||||
if test $BUNDLED_LIBTOM = 1 ; then
|
||||
AC_DEFINE(BUNDLED_LIBTOM,1,Use bundled libtom)
|
||||
fi
|
||||
|
||||
AC_SUBST(LIBTOM_LIBS)
|
||||
AC_SUBST(BUNDLED_LIBTOM)
|
||||
|
||||
dnl Added from OpenSSH 3.6.1p2's configure.ac
|
||||
|
||||
dnl allow user to disable some login recording features
|
||||
AC_ARG_ENABLE(lastlog,
|
||||
[ --disable-lastlog Disable use of lastlog even if detected [no]],
|
||||
[
|
||||
if test "x$enableval" = "xno" ; then
|
||||
AC_DEFINE(DISABLE_LASTLOG,1,Disable use of lastlog())
|
||||
fi
|
||||
]
|
||||
)
|
||||
AC_ARG_ENABLE(utmp,
|
||||
[ --disable-utmp Disable use of utmp even if detected [no]],
|
||||
[
|
||||
if test "x$enableval" = "xno" ; then
|
||||
AC_DEFINE(DISABLE_UTMP,1,Disable use of utmp)
|
||||
fi
|
||||
]
|
||||
)
|
||||
AC_ARG_ENABLE(utmpx,
|
||||
[ --disable-utmpx Disable use of utmpx even if detected [no]],
|
||||
[
|
||||
if test "x$enableval" = "xno" ; then
|
||||
AC_DEFINE(DISABLE_UTMPX,1,Disable use of utmpx)
|
||||
fi
|
||||
]
|
||||
)
|
||||
AC_ARG_ENABLE(wtmp,
|
||||
[ --disable-wtmp Disable use of wtmp even if detected [no]],
|
||||
[
|
||||
if test "x$enableval" = "xno" ; then
|
||||
AC_DEFINE(DISABLE_WTMP,1,Disable use of wtmp)
|
||||
fi
|
||||
]
|
||||
)
|
||||
AC_ARG_ENABLE(wtmpx,
|
||||
[ --disable-wtmpx Disable use of wtmpx even if detected [no]],
|
||||
[
|
||||
if test "x$enableval" = "xno" ; then
|
||||
AC_DEFINE(DISABLE_WTMPX,1,Disable use of wtmpx)
|
||||
fi
|
||||
]
|
||||
)
|
||||
AC_ARG_ENABLE(loginfunc,
|
||||
[ --disable-loginfunc Disable use of login() etc. [no]],
|
||||
[ no_loginfunc_check=1
|
||||
AC_MSG_NOTICE([Not using login() etc]) ]
|
||||
)
|
||||
AC_ARG_ENABLE(pututline,
|
||||
[ --disable-pututline Disable use of pututline() etc. ([uw]tmp) [no]],
|
||||
[
|
||||
if test "x$enableval" = "xno" ; then
|
||||
AC_DEFINE(DISABLE_PUTUTLINE,1,Disable use of pututline())
|
||||
fi
|
||||
]
|
||||
)
|
||||
AC_ARG_ENABLE(pututxline,
|
||||
[ --disable-pututxline Disable use of pututxline() etc. ([uw]tmpx) [no]],
|
||||
[
|
||||
if test "x$enableval" = "xno" ; then
|
||||
AC_DEFINE(DISABLE_PUTUTXLINE,1,Disable use of pututxline())
|
||||
fi
|
||||
]
|
||||
)
|
||||
AC_ARG_WITH(lastlog,
|
||||
[ --with-lastlog=FILE|DIR specify lastlog location [common locations]],
|
||||
[
|
||||
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,1,[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_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#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_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#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_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#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_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_UTMP_H
|
||||
# include <utmp.h>
|
||||
#endif
|
||||
#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_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#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_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <sys/types.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
|
||||
]],
|
||||
[[ 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_CHECK_FUNCS([getpass getspnam getusershell putenv])
|
||||
AC_CHECK_FUNCS([clearenv strlcpy strlcat daemon basename _getpty getaddrinfo ])
|
||||
AC_CHECK_FUNCS([freeaddrinfo getnameinfo fork writev getgrouplist fexecve])
|
||||
|
||||
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
|
||||
if test -e /dev/ptmx ; then
|
||||
AC_DEFINE(USE_DEV_PTMX,1,Use /dev/ptmx)
|
||||
fi
|
||||
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
|
||||
if test -e /dev/ptc ; then
|
||||
AC_DEFINE(HAVE_DEV_PTS_AND_PTC,1,Use /dev/ptc & /dev/pts)
|
||||
fi
|
||||
else
|
||||
AC_MSG_NOTICE([Not checking for /dev/ptc & /dev/pts since we're cross-compiling])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_EXEEXT
|
||||
|
||||
if test $BUNDLED_LIBTOM = 1 ; then
|
||||
(cd $srcdir; find libtomcrypt -type d) | xargs mkdir -pv
|
||||
LIBTOM_FILES="libtomcrypt/Makefile libtommath/Makefile"
|
||||
fi
|
||||
|
||||
# flags that should be set in Makefile but not for configure tests
|
||||
CFLAGS="$CFLAGS $LATE_CFLAGS"
|
||||
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_FILES(Makefile $LIBTOM_FILES test/Makefile)
|
||||
AC_OUTPUT
|
||||
|
||||
AC_MSG_NOTICE()
|
||||
if test $BUNDLED_LIBTOM = 1 ; then
|
||||
AC_MSG_NOTICE([Using bundled libtomcrypt and libtommath])
|
||||
else
|
||||
AC_MSG_NOTICE([Using system libtomcrypt and libtommath])
|
||||
fi
|
||||
|
||||
|
||||
if test "x$ac_cv_func_getpass" != xyes; then
|
||||
AC_MSG_NOTICE()
|
||||
AC_MSG_NOTICE([getpass() not available, dbclient will only have public-key authentication])
|
||||
fi
|
||||
|
||||
if test "t$found_crypt_func" != there; then
|
||||
AC_MSG_NOTICE()
|
||||
AC_MSG_NOTICE([crypt() not available, dropbear server will not have password authentication])
|
||||
fi
|
||||
|
||||
AC_MSG_NOTICE()
|
||||
AC_MSG_NOTICE([Now edit localoptions.h to choose features.])
|
||||
616
configure.in
616
configure.in
@@ -1,616 +0,0 @@
|
||||
# -*- 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_RESULT(No \$CFLAGS set... using "-Os -W -Wall" for GCC)
|
||||
CFLAGS="-Os -W -Wall"
|
||||
fi
|
||||
|
||||
# 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_RESULT(Using uClibc - login() and logout() probably don't work, so we won't use them.)
|
||||
],,,)
|
||||
|
||||
# Checks for libraries.
|
||||
AC_CHECK_LIB(crypt, crypt, LIBS="$LIBS -lcrypt")
|
||||
|
||||
# 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_RESULT(Disabling zlib)
|
||||
else
|
||||
AC_CHECK_LIB(z, deflate, , AC_MSG_ERROR([*** zlib missing - install first or check config.log ***]))
|
||||
AC_MSG_RESULT(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_RESULT(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_RESULT(Enabling PAM)
|
||||
else
|
||||
AC_DEFINE(DISABLE_PAM,, Use PAM)
|
||||
AC_MSG_RESULT(Disabling PAM)
|
||||
fi
|
||||
],
|
||||
[
|
||||
# disable it by default
|
||||
AC_DEFINE(DISABLE_PAM,, Use PAM)
|
||||
AC_MSG_RESULT(Disabling PAM)
|
||||
]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE(openpty,
|
||||
[ --disable-openpty Don't use openpty, use alternative method],
|
||||
[
|
||||
if test "x$enableval" = "xno"; then
|
||||
AC_MSG_RESULT(Not using openpty)
|
||||
else
|
||||
AC_MSG_RESULT(Using openpty if available)
|
||||
AC_SEARCH_LIBS(openpty, util, [AC_DEFINE(HAVE_OPENPTY,,Have openpty() function)])
|
||||
fi
|
||||
],
|
||||
[
|
||||
AC_MSG_RESULT(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_RESULT(Disabling syslog)
|
||||
else
|
||||
AC_MSG_RESULT(Enabling syslog)
|
||||
fi
|
||||
],
|
||||
[
|
||||
AC_MSG_RESULT(Enabling syslog)
|
||||
]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE(shadow,
|
||||
[ --disable-shadow Don't use shadow passwords (if available)],
|
||||
[
|
||||
if test "x$enableval" = "xno"; then
|
||||
AC_MSG_RESULT(Not using shadow passwords)
|
||||
else
|
||||
AC_CHECK_HEADERS([shadow.h])
|
||||
AC_MSG_RESULT(Using shadow passwords if available)
|
||||
fi
|
||||
],
|
||||
[
|
||||
AC_CHECK_HEADERS([shadow.h])
|
||||
AC_MSG_RESULT(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])
|
||||
|
||||
# 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>
|
||||
#if HAVE_UTMPX_H
|
||||
#include <utmpx.h>
|
||||
#endif
|
||||
])
|
||||
|
||||
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_RESULT(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_RESULT(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_RESULT(Not checking for /dev/ptc & /dev/pts\, we're cross-compiling)
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_EXEEXT
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_OUTPUT(Makefile)
|
||||
AC_OUTPUT(libtomcrypt/Makefile)
|
||||
AC_OUTPUT(libtommath/Makefile)
|
||||
AC_MSG_RESULT()
|
||||
AC_MSG_RESULT(Now edit options.h to choose features.)
|
||||
76
crypto_desc.c
Normal file
76
crypto_desc.c
Normal file
@@ -0,0 +1,76 @@
|
||||
#include "includes.h"
|
||||
#include "dbutil.h"
|
||||
#include "crypto_desc.h"
|
||||
#include "ltc_prng.h"
|
||||
#include "ecc.h"
|
||||
#include "dbrandom.h"
|
||||
|
||||
#if DROPBEAR_LTC_PRNG
|
||||
int dropbear_ltc_prng = -1;
|
||||
#endif
|
||||
|
||||
/* Wrapper for libtommath */
|
||||
static mp_err dropbear_rand_source(void* out, size_t size) {
|
||||
genrandom((unsigned char*)out, (unsigned int)size);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
|
||||
/* 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[] = {
|
||||
#if DROPBEAR_AES
|
||||
&aes_desc,
|
||||
#endif
|
||||
#if DROPBEAR_3DES
|
||||
&des3_desc,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct ltc_hash_descriptor *reghashes[] = {
|
||||
#if DROPBEAR_SHA1_HMAC
|
||||
&sha1_desc,
|
||||
#endif
|
||||
#if DROPBEAR_SHA256
|
||||
&sha256_desc,
|
||||
#endif
|
||||
#if DROPBEAR_SHA384
|
||||
&sha384_desc,
|
||||
#endif
|
||||
#if DROPBEAR_SHA512
|
||||
&sha512_desc,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; regciphers[i] != NULL; i++) {
|
||||
if (register_cipher(regciphers[i]) == -1) {
|
||||
dropbear_exit("Error registering crypto");
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; reghashes[i] != NULL; i++) {
|
||||
if (register_hash(reghashes[i]) == -1) {
|
||||
dropbear_exit("Error registering crypto");
|
||||
}
|
||||
}
|
||||
|
||||
#if DROPBEAR_LTC_PRNG
|
||||
dropbear_ltc_prng = register_prng(&dropbear_prng_desc);
|
||||
if (dropbear_ltc_prng == -1) {
|
||||
dropbear_exit("Error registering crypto");
|
||||
}
|
||||
#endif
|
||||
|
||||
mp_rand_source(dropbear_rand_source);
|
||||
|
||||
#if DROPBEAR_ECC
|
||||
ltc_mp = ltm_desc;
|
||||
dropbear_ecc_fill_dp();
|
||||
#endif
|
||||
}
|
||||
|
||||
9
crypto_desc.h
Normal file
9
crypto_desc.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef DROPBEAR_CRYPTO_DESC_H
|
||||
#define DROPBEAR_CRYPTO_DESC_H
|
||||
|
||||
void crypto_init(void);
|
||||
|
||||
extern int dropbear_ltc_prng;
|
||||
|
||||
#endif /* DROPBEAR_CRYPTO_DESC_H */
|
||||
|
||||
497
curve25519.c
Normal file
497
curve25519.c
Normal file
@@ -0,0 +1,497 @@
|
||||
/*
|
||||
* Dropbear - a SSH2 server
|
||||
*
|
||||
* Copyright (c) 2002,2003 Matt Johnston
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#include "includes.h"
|
||||
#include "dbrandom.h"
|
||||
#include "curve25519.h"
|
||||
|
||||
#if DROPBEAR_CURVE25519 || DROPBEAR_ED25519
|
||||
|
||||
/* Modified TweetNaCl version 20140427, a self-contained public-domain C library.
|
||||
* https://tweetnacl.cr.yp.to/ */
|
||||
|
||||
#define FOR(i,n) for (i = 0;i < n;++i)
|
||||
#define sv static void
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned long u32;
|
||||
typedef unsigned long long u64;
|
||||
typedef long long i64;
|
||||
typedef i64 gf[16];
|
||||
|
||||
#if DROPBEAR_CURVE25519
|
||||
static const gf
|
||||
_121665 = {0xDB41,1};
|
||||
#endif /* DROPBEAR_CURVE25519 */
|
||||
#if DROPBEAR_ED25519
|
||||
static const gf
|
||||
gf0,
|
||||
gf1 = {1},
|
||||
D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406},
|
||||
X = {0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169},
|
||||
Y = {0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666};
|
||||
#if DROPBEAR_SIGNKEY_VERIFY
|
||||
static const gf
|
||||
D = {0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203},
|
||||
I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83};
|
||||
#endif /* DROPBEAR_SIGNKEY_VERIFY */
|
||||
#endif /* DROPBEAR_ED25519 */
|
||||
|
||||
#if DROPBEAR_ED25519
|
||||
#if DROPBEAR_SIGNKEY_VERIFY
|
||||
static int vn(const u8 *x,const u8 *y,u32 n)
|
||||
{
|
||||
u32 i,d = 0;
|
||||
FOR(i,n) d |= x[i]^y[i];
|
||||
return (1 & ((d - 1) >> 8)) - 1;
|
||||
}
|
||||
|
||||
static int crypto_verify_32(const u8 *x,const u8 *y)
|
||||
{
|
||||
return vn(x,y,32);
|
||||
}
|
||||
#endif /* DROPBEAR_SIGNKEY_VERIFY */
|
||||
|
||||
sv set25519(gf r, const gf a)
|
||||
{
|
||||
int i;
|
||||
FOR(i,16) r[i]=a[i];
|
||||
}
|
||||
#endif /* DROPBEAR_ED25519 */
|
||||
|
||||
sv car25519(gf o)
|
||||
{
|
||||
int i;
|
||||
i64 c;
|
||||
FOR(i,16) {
|
||||
o[i]+=(1LL<<16);
|
||||
c=o[i]>>16;
|
||||
o[(i+1)*(i<15)]+=c-1+37*(c-1)*(i==15);
|
||||
o[i]-=c<<16;
|
||||
}
|
||||
}
|
||||
|
||||
sv sel25519(gf p,gf q,int b)
|
||||
{
|
||||
i64 t,i,c=~(b-1);
|
||||
FOR(i,16) {
|
||||
t= c&(p[i]^q[i]);
|
||||
p[i]^=t;
|
||||
q[i]^=t;
|
||||
}
|
||||
}
|
||||
|
||||
sv pack25519(u8 *o,const gf n)
|
||||
{
|
||||
int i,j,b;
|
||||
gf m,t;
|
||||
FOR(i,16) t[i]=n[i];
|
||||
car25519(t);
|
||||
car25519(t);
|
||||
car25519(t);
|
||||
FOR(j,2) {
|
||||
m[0]=t[0]-0xffed;
|
||||
for(i=1;i<15;i++) {
|
||||
m[i]=t[i]-0xffff-((m[i-1]>>16)&1);
|
||||
m[i-1]&=0xffff;
|
||||
}
|
||||
m[15]=t[15]-0x7fff-((m[14]>>16)&1);
|
||||
b=(m[15]>>16)&1;
|
||||
m[14]&=0xffff;
|
||||
sel25519(t,m,1-b);
|
||||
}
|
||||
FOR(i,16) {
|
||||
o[2*i]=t[i]&0xff;
|
||||
o[2*i+1]=t[i]>>8;
|
||||
}
|
||||
}
|
||||
|
||||
#if DROPBEAR_ED25519
|
||||
#if DROPBEAR_SIGNKEY_VERIFY
|
||||
static int neq25519(const gf a, const gf b)
|
||||
{
|
||||
u8 c[32],d[32];
|
||||
pack25519(c,a);
|
||||
pack25519(d,b);
|
||||
return crypto_verify_32(c,d);
|
||||
}
|
||||
#endif /* DROPBEAR_SIGNKEY_VERIFY */
|
||||
|
||||
static u8 par25519(const gf a)
|
||||
{
|
||||
u8 d[32];
|
||||
pack25519(d,a);
|
||||
return d[0]&1;
|
||||
}
|
||||
#endif /* DROPBEAR_ED25519 */
|
||||
|
||||
sv unpack25519(gf o, const u8 *n)
|
||||
{
|
||||
int i;
|
||||
FOR(i,16) o[i]=n[2*i]+((i64)n[2*i+1]<<8);
|
||||
o[15]&=0x7fff;
|
||||
}
|
||||
|
||||
sv A(gf o,const gf a,const gf b)
|
||||
{
|
||||
int i;
|
||||
FOR(i,16) o[i]=a[i]+b[i];
|
||||
}
|
||||
|
||||
sv Z(gf o,const gf a,const gf b)
|
||||
{
|
||||
int i;
|
||||
FOR(i,16) o[i]=a[i]-b[i];
|
||||
}
|
||||
|
||||
sv M(gf o,const gf a,const gf b)
|
||||
{
|
||||
i64 i,j,t[31];
|
||||
FOR(i,31) t[i]=0;
|
||||
FOR(i,16) FOR(j,16) t[i+j]+=a[i]*b[j];
|
||||
FOR(i,15) t[i]+=38*t[i+16];
|
||||
FOR(i,16) o[i]=t[i];
|
||||
car25519(o);
|
||||
car25519(o);
|
||||
}
|
||||
|
||||
sv S(gf o,const gf a)
|
||||
{
|
||||
M(o,a,a);
|
||||
}
|
||||
|
||||
sv inv25519(gf o,const gf i)
|
||||
{
|
||||
gf c;
|
||||
int a;
|
||||
FOR(a,16) c[a]=i[a];
|
||||
for(a=253;a>=0;a--) {
|
||||
S(c,c);
|
||||
if(a!=2&&a!=4) M(c,c,i);
|
||||
}
|
||||
FOR(a,16) o[a]=c[a];
|
||||
}
|
||||
|
||||
#if DROPBEAR_ED25519 && DROPBEAR_SIGNKEY_VERIFY
|
||||
sv pow2523(gf o,const gf i)
|
||||
{
|
||||
gf c;
|
||||
int a;
|
||||
FOR(a,16) c[a]=i[a];
|
||||
for(a=250;a>=0;a--) {
|
||||
S(c,c);
|
||||
if(a!=1) M(c,c,i);
|
||||
}
|
||||
FOR(a,16) o[a]=c[a];
|
||||
}
|
||||
#endif /* DROPBEAR_ED25519 && DROPBEAR_SIGNKEY_VERIFY */
|
||||
|
||||
#if DROPBEAR_CURVE25519
|
||||
void dropbear_curve25519_scalarmult(u8 *q,const u8 *n,const u8 *p)
|
||||
{
|
||||
u8 z[32];
|
||||
i64 x[80],r,i;
|
||||
gf a,b,c,d,e,f;
|
||||
FOR(i,31) z[i]=n[i];
|
||||
z[31]=(n[31]&127)|64;
|
||||
z[0]&=248;
|
||||
unpack25519(x,p);
|
||||
FOR(i,16) {
|
||||
b[i]=x[i];
|
||||
d[i]=a[i]=c[i]=0;
|
||||
}
|
||||
a[0]=d[0]=1;
|
||||
for(i=254;i>=0;--i) {
|
||||
r=(z[i>>3]>>(i&7))&1;
|
||||
sel25519(a,b,r);
|
||||
sel25519(c,d,r);
|
||||
A(e,a,c);
|
||||
Z(a,a,c);
|
||||
A(c,b,d);
|
||||
Z(b,b,d);
|
||||
S(d,e);
|
||||
S(f,a);
|
||||
M(a,c,a);
|
||||
M(c,b,e);
|
||||
A(e,a,c);
|
||||
Z(a,a,c);
|
||||
S(b,a);
|
||||
Z(c,d,f);
|
||||
M(a,c,_121665);
|
||||
A(a,a,d);
|
||||
M(c,c,a);
|
||||
M(a,d,f);
|
||||
M(d,b,x);
|
||||
S(b,e);
|
||||
sel25519(a,b,r);
|
||||
sel25519(c,d,r);
|
||||
}
|
||||
FOR(i,16) {
|
||||
x[i+16]=a[i];
|
||||
x[i+32]=c[i];
|
||||
x[i+48]=b[i];
|
||||
x[i+64]=d[i];
|
||||
}
|
||||
inv25519(x+32,x+32);
|
||||
M(x+16,x+16,x+32);
|
||||
pack25519(q,x+16);
|
||||
}
|
||||
#endif /* DROPBEAR_CURVE25519 */
|
||||
|
||||
#if DROPBEAR_ED25519
|
||||
static int crypto_hash(u8 *out,const u8 *m,u64 n)
|
||||
{
|
||||
hash_state hs;
|
||||
|
||||
sha512_init(&hs);
|
||||
sha512_process(&hs, m, n);
|
||||
return sha512_done(&hs, out);
|
||||
}
|
||||
|
||||
sv add(gf p[4],gf q[4])
|
||||
{
|
||||
gf a,b,c,d,t,e,f,g,h;
|
||||
|
||||
Z(a, p[1], p[0]);
|
||||
Z(t, q[1], q[0]);
|
||||
M(a, a, t);
|
||||
A(b, p[0], p[1]);
|
||||
A(t, q[0], q[1]);
|
||||
M(b, b, t);
|
||||
M(c, p[3], q[3]);
|
||||
M(c, c, D2);
|
||||
M(d, p[2], q[2]);
|
||||
A(d, d, d);
|
||||
Z(e, b, a);
|
||||
Z(f, d, c);
|
||||
A(g, d, c);
|
||||
A(h, b, a);
|
||||
|
||||
M(p[0], e, f);
|
||||
M(p[1], h, g);
|
||||
M(p[2], g, f);
|
||||
M(p[3], e, h);
|
||||
}
|
||||
|
||||
sv cswap(gf p[4],gf q[4],u8 b)
|
||||
{
|
||||
int i;
|
||||
FOR(i,4)
|
||||
sel25519(p[i],q[i],b);
|
||||
}
|
||||
|
||||
sv pack(u8 *r,gf p[4])
|
||||
{
|
||||
gf tx, ty, zi;
|
||||
inv25519(zi, p[2]);
|
||||
M(tx, p[0], zi);
|
||||
M(ty, p[1], zi);
|
||||
pack25519(r, ty);
|
||||
r[31] ^= par25519(tx) << 7;
|
||||
}
|
||||
|
||||
sv scalarmult(gf p[4],gf q[4],const u8 *s)
|
||||
{
|
||||
int i;
|
||||
set25519(p[0],gf0);
|
||||
set25519(p[1],gf1);
|
||||
set25519(p[2],gf1);
|
||||
set25519(p[3],gf0);
|
||||
for (i = 255;i >= 0;--i) {
|
||||
u8 b = (s[i/8]>>(i&7))&1;
|
||||
cswap(p,q,b);
|
||||
add(q,p);
|
||||
add(p,p);
|
||||
cswap(p,q,b);
|
||||
}
|
||||
}
|
||||
|
||||
sv scalarbase(gf p[4],const u8 *s)
|
||||
{
|
||||
gf q[4];
|
||||
set25519(q[0],X);
|
||||
set25519(q[1],Y);
|
||||
set25519(q[2],gf1);
|
||||
M(q[3],X,Y);
|
||||
scalarmult(p,q,s);
|
||||
}
|
||||
|
||||
void dropbear_ed25519_make_key(u8 *pk,u8 *sk)
|
||||
{
|
||||
u8 d[64];
|
||||
gf p[4];
|
||||
|
||||
genrandom(sk, 32);
|
||||
|
||||
crypto_hash(d, sk, 32);
|
||||
d[0] &= 248;
|
||||
d[31] &= 127;
|
||||
d[31] |= 64;
|
||||
|
||||
scalarbase(p,d);
|
||||
pack(pk,p);
|
||||
}
|
||||
|
||||
static const u64 L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10};
|
||||
|
||||
sv modL(u8 *r,i64 x[64])
|
||||
{
|
||||
i64 carry,i,j;
|
||||
for (i = 63;i >= 32;--i) {
|
||||
carry = 0;
|
||||
for (j = i - 32;j < i - 12;++j) {
|
||||
x[j] += carry - 16 * x[i] * L[j - (i - 32)];
|
||||
carry = (x[j] + 128) >> 8;
|
||||
x[j] -= carry << 8;
|
||||
}
|
||||
x[j] += carry;
|
||||
x[i] = 0;
|
||||
}
|
||||
carry = 0;
|
||||
FOR(j,32) {
|
||||
x[j] += carry - (x[31] >> 4) * L[j];
|
||||
carry = x[j] >> 8;
|
||||
x[j] &= 255;
|
||||
}
|
||||
FOR(j,32) x[j] -= carry * L[j];
|
||||
FOR(i,32) {
|
||||
x[i+1] += x[i] >> 8;
|
||||
r[i] = x[i] & 255;
|
||||
}
|
||||
}
|
||||
|
||||
sv reduce(u8 *r)
|
||||
{
|
||||
i64 x[64],i;
|
||||
FOR(i,64) x[i] = (u64) r[i];
|
||||
FOR(i,64) r[i] = 0;
|
||||
modL(r,x);
|
||||
}
|
||||
|
||||
void dropbear_ed25519_sign(const u8 *m,u32 mlen,u8 *s,u32 *slen,const u8 *sk, const u8 *pk)
|
||||
{
|
||||
hash_state hs;
|
||||
u8 d[64],h[64],r[64];
|
||||
i64 x[64];
|
||||
gf p[4];
|
||||
u32 i,j;
|
||||
|
||||
crypto_hash(d, sk, 32);
|
||||
d[0] &= 248;
|
||||
d[31] &= 127;
|
||||
d[31] |= 64;
|
||||
|
||||
*slen = 64;
|
||||
|
||||
sha512_init(&hs);
|
||||
sha512_process(&hs,d + 32,32);
|
||||
sha512_process(&hs,m,mlen);
|
||||
sha512_done(&hs,r);
|
||||
reduce(r);
|
||||
scalarbase(p,r);
|
||||
pack(s,p);
|
||||
|
||||
sha512_init(&hs);
|
||||
sha512_process(&hs,s,32);
|
||||
sha512_process(&hs,pk,32);
|
||||
sha512_process(&hs,m,mlen);
|
||||
sha512_done(&hs,h);
|
||||
reduce(h);
|
||||
|
||||
FOR(i,64) x[i] = 0;
|
||||
FOR(i,32) x[i] = (u64) r[i];
|
||||
FOR(i,32) FOR(j,32) x[i+j] += h[i] * (u64) d[j];
|
||||
modL(s + 32,x);
|
||||
}
|
||||
|
||||
#if DROPBEAR_SIGNKEY_VERIFY
|
||||
static int unpackneg(gf r[4],const u8 p[32])
|
||||
{
|
||||
gf t, chk, num, den, den2, den4, den6;
|
||||
set25519(r[2],gf1);
|
||||
unpack25519(r[1],p);
|
||||
S(num,r[1]);
|
||||
M(den,num,D);
|
||||
Z(num,num,r[2]);
|
||||
A(den,r[2],den);
|
||||
|
||||
S(den2,den);
|
||||
S(den4,den2);
|
||||
M(den6,den4,den2);
|
||||
M(t,den6,num);
|
||||
M(t,t,den);
|
||||
|
||||
pow2523(t,t);
|
||||
M(t,t,num);
|
||||
M(t,t,den);
|
||||
M(t,t,den);
|
||||
M(r[0],t,den);
|
||||
|
||||
S(chk,r[0]);
|
||||
M(chk,chk,den);
|
||||
if (neq25519(chk, num)) M(r[0],r[0],I);
|
||||
|
||||
S(chk,r[0]);
|
||||
M(chk,chk,den);
|
||||
if (neq25519(chk, num)) return -1;
|
||||
|
||||
if (par25519(r[0]) == (p[31]>>7)) Z(r[0],gf0,r[0]);
|
||||
|
||||
M(r[3],r[0],r[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dropbear_ed25519_verify(const u8 *m,u32 mlen,const u8 *s,u32 slen,const u8 *pk)
|
||||
{
|
||||
hash_state hs;
|
||||
u8 t[32],h[64];
|
||||
gf p[4],q[4];
|
||||
|
||||
if (slen < 64) return -1;
|
||||
|
||||
if (unpackneg(q,pk)) return -1;
|
||||
|
||||
sha512_init(&hs);
|
||||
sha512_process(&hs,s,32);
|
||||
sha512_process(&hs,pk,32);
|
||||
sha512_process(&hs,m,mlen);
|
||||
sha512_done(&hs,h);
|
||||
|
||||
reduce(h);
|
||||
scalarmult(p,q,h);
|
||||
|
||||
scalarbase(q,s + 32);
|
||||
add(p,q);
|
||||
pack(t,p);
|
||||
|
||||
if (crypto_verify_32(s, t))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* DROPBEAR_SIGNKEY_VERIFY */
|
||||
|
||||
#endif /* DROPBEAR_ED25519 */
|
||||
|
||||
#endif /* DROPBEAR_CURVE25519 || DROPBEAR_ED25519 */
|
||||
37
curve25519.h
Normal file
37
curve25519.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Dropbear - a SSH2 server
|
||||
*
|
||||
* Copyright (c) 2002,2003 Matt Johnston
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#ifndef DROPBEAR_CURVE25519_H
|
||||
#define DROPBEAR_CURVE25519_H
|
||||
|
||||
void dropbear_curve25519_scalarmult(unsigned char *q, const unsigned char *n, const unsigned char *p);
|
||||
void dropbear_ed25519_make_key(unsigned char *pk, unsigned char *sk);
|
||||
void dropbear_ed25519_sign(const unsigned char *m, unsigned long mlen,
|
||||
unsigned char *s, unsigned long *slen,
|
||||
const unsigned char *sk, const unsigned char *pk);
|
||||
int dropbear_ed25519_verify(const unsigned char *m, unsigned long mlen,
|
||||
const unsigned char *s, unsigned long slen,
|
||||
const unsigned char *pk);
|
||||
|
||||
#endif /* DROPBEAR_CURVE25519_H */
|
||||
238
dbclient.1
Normal file
238
dbclient.1
Normal file
@@ -0,0 +1,238 @@
|
||||
.TH dbclient 1
|
||||
.SH NAME
|
||||
dbclient \- lightweight SSH client
|
||||
.SH SYNOPSIS
|
||||
.B dbclient
|
||||
[\fIflag arguments\fR] [\-p
|
||||
.I port\fR] [\-i
|
||||
.I id\fR] [\-L
|
||||
.I l\fR:\fIh\fR:\fIp\fR] [\-R
|
||||
.I l\fR:\fIh\fR:\fIp\fR] [\-l
|
||||
.IR user ]
|
||||
.I host
|
||||
.RI [ \fImore\ flags\fR ]
|
||||
.RI [ command ]
|
||||
|
||||
.B dbclient
|
||||
[\fIargs\fR]
|
||||
[\fIuser1\fR]@\fIhost1\fR[^\fIport1\fR],[\fIuser2\fR]@\fIhost2\fR[^\fIport2\fR],...
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B dbclient
|
||||
is the client part of Dropbear SSH
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.TP
|
||||
.B command
|
||||
A command to run on the remote host. This will normally be run by the remote host
|
||||
using the user's shell. The command begins at the first hyphen argument after the
|
||||
host argument. If no command is specified an interactive terminal will be opened
|
||||
(see -t and -T).
|
||||
.TP
|
||||
.B \-p \fIport
|
||||
Connect to
|
||||
.I port
|
||||
on the remote host. Alternatively a port can be specified as hostname^port.
|
||||
Default is 22.
|
||||
.TP
|
||||
.B \-i \fIidfile
|
||||
Identity file.
|
||||
Read the identity key from file
|
||||
.I idfile
|
||||
(multiple allowed). This file is created with dropbearkey(1) or converted
|
||||
from OpenSSH with dropbearconvert(1). The default path ~/.ssh/id_dropbear is used
|
||||
.TP
|
||||
.B \-L\fR [\fIlistenaddress\fR]:\fIlistenport\fR:\fIhost\fR:\fIport\fR
|
||||
Local port forwarding.
|
||||
Forward
|
||||
.I listenport
|
||||
on the local host through the SSH connection to
|
||||
.I port
|
||||
on
|
||||
.IR host .
|
||||
.TP
|
||||
.B \-R\fR [\fIlistenaddress\fR]:\fIlistenport\fR:\fIhost\fR:\fIport\fR
|
||||
Remote port forwarding.
|
||||
Forward
|
||||
.I listenport
|
||||
on the remote host through the SSH connection to
|
||||
.I port
|
||||
on
|
||||
.IR host .
|
||||
.TP
|
||||
.B \-l \fIuser
|
||||
Username.
|
||||
Login as
|
||||
.I user
|
||||
on the remote host. An alternative is to specify user@host.
|
||||
.TP
|
||||
.B \-t
|
||||
Allocate a PTY. This is the default when no command is given, it gives a full
|
||||
interactive remote session. The main effect is that keystrokes are sent remotely
|
||||
immediately as opposed to local line-based editing.
|
||||
.TP
|
||||
.B \-T
|
||||
Don't allocate a PTY. This is the default when a command is given. See -t.
|
||||
.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. If specified a second time no host key checking
|
||||
is performed at all, this is usually undesirable.
|
||||
.TP
|
||||
.B \-A
|
||||
Forward agent connections to the remote host. dbclient will use any
|
||||
OpenSSH-style agent program if available ($SSH_AUTH_SOCK will be set) for
|
||||
public key authentication. Forwarding is only enabled if \fI-A\fR is specified.
|
||||
|
||||
Beware that a forwarded agent connection will allow the remote server to have
|
||||
the same authentication credentials as you have used locally. A compromised
|
||||
remote server could use that to log in to other servers.
|
||||
|
||||
In many situations Dropbear's multi-hop mode is a better and more secure alternative
|
||||
to agent forwarding, avoiding having to trust the intermediate server.
|
||||
|
||||
If the SSH agent program is set to prompt when a key is used, the
|
||||
\fI-o DisableTrivialAuth\fR option can prevent UI confusion.
|
||||
|
||||
.TP
|
||||
.B \-W \fIwindowsize
|
||||
Specify the per-channel receive window buffer size. Increasing this
|
||||
may improve network performance at the expense of memory use. Use -h to see the
|
||||
default buffer size.
|
||||
.TP
|
||||
.B \-K \fItimeout_seconds
|
||||
Ensure that traffic is transmitted at a certain interval in seconds. This is
|
||||
useful for working around firewalls or routers that drop connections after
|
||||
a certain period of inactivity. The trade-off is that a session may be
|
||||
closed if there is a temporary lapse of network connectivity. A setting
|
||||
if 0 disables keepalives. If no response is received for 3 consecutive keepalives the connection will be closed.
|
||||
.TP
|
||||
.B \-I \fIidle_timeout
|
||||
Disconnect the session if no traffic is transmitted or received for \fIidle_timeout\fR seconds.
|
||||
.TP
|
||||
.B \-z
|
||||
By default Dropbear will send network traffic with the \fBAF21\fR setting for QoS, letting network devices give it higher priority. Some devices may have problems with that, \fI-z\fR can be used to disable it.
|
||||
.TP
|
||||
|
||||
.\" TODO: how to avoid a line break between these two -J arguments?
|
||||
.B \-J \fIproxy_command
|
||||
.TP
|
||||
.B \-J \fI&fd
|
||||
.br
|
||||
Use the standard input/output of the program \fIproxy_command\fR rather than using
|
||||
a normal TCP connection. A hostname should be still be provided, as this is used for
|
||||
comparing saved hostkeys. This command will be executed as "exec proxy_command ..." with the
|
||||
default shell.
|
||||
|
||||
The second form &fd will make dbclient use the numeric file descriptor as a socket. This
|
||||
can be used for more complex tunnelling scenarios. Example usage with socat is
|
||||
|
||||
socat EXEC:'dbclient -J &38 ev',fdin=38,fdout=38 TCP4:host.example.com:22
|
||||
|
||||
.TP
|
||||
.B \-B \fIendhost:endport
|
||||
"Netcat-alike" mode, where Dropbear will connect to the given host, then create a
|
||||
forwarded connection to \fIendhost\fR. This will then be presented as dbclient's
|
||||
standard input/output.
|
||||
.TP
|
||||
.B \-c \fIcipherlist
|
||||
Specify a comma separated list of ciphers to enable. Use \fI-c help\fR to list possibilities.
|
||||
.TP
|
||||
.B \-m \fIMAClist
|
||||
Specify a comma separated list of authentication MACs to enable. Use \fI-m help\fR to list possibilities.
|
||||
.TP
|
||||
.B \-o \fIoption
|
||||
Can be used to give options in the format used by OpenSSH config file. This is
|
||||
useful for specifying options for which there is no separate command-line flag.
|
||||
For full details of the options listed below, and their possible values, see
|
||||
ssh_config(5).
|
||||
The following options have currently been implemented:
|
||||
|
||||
.RS
|
||||
.TP
|
||||
.B ExitOnForwardFailure
|
||||
Specifies whether dbclient should terminate the connection if it cannot set up all requested local and remote port forwardings. The argument must be "yes" or "no". The default is "no".
|
||||
.TP
|
||||
.B UseSyslog
|
||||
Send dbclient log messages to syslog in addition to stderr.
|
||||
.TP
|
||||
.B Port
|
||||
Specify a listening port, like the \fI-p\fR argument.
|
||||
.TP
|
||||
.B DisableTrivialAuth
|
||||
Disallow a server immediately
|
||||
giving successful authentication (without presenting any password/pubkey prompt).
|
||||
This avoids a UI confusion issue where it may appear that the user is accepting
|
||||
a SSH agent prompt from their local machine, but are actually accepting a prompt
|
||||
sent immediately by the remote server.
|
||||
.RE
|
||||
.TP
|
||||
.B \-s
|
||||
The specified command will be requested as a subsystem, used for sftp. Dropbear doesn't implement sftp itself but the OpenSSH sftp client can be used eg \fIsftp -S dbclient user@host\fR
|
||||
.TP
|
||||
.B \-b \fI[address][:port]
|
||||
Bind to a specific local address when connecting to the remote host. This can be used to choose from
|
||||
multiple outgoing interfaces. Either address or port (or both) can be given.
|
||||
.TP
|
||||
.B \-V
|
||||
Print the version
|
||||
|
||||
.SH MULTI-HOP
|
||||
Dropbear will also allow multiple "hops" to be specified, separated by commas. In
|
||||
this case a connection will be made to the first host, then a TCP forwarded
|
||||
connection will be made through that to the second host, and so on. Hosts other than
|
||||
the final destination will not see anything other than the encrypted SSH stream.
|
||||
A port for a host can be specified with a caret (eg matt@martello^44 ).
|
||||
This syntax can also be used with scp or rsync (specifying dbclient as the
|
||||
ssh/rsh command). A file can be "bounced" through multiple SSH hops, eg
|
||||
|
||||
scp -S dbclient matt@martello,root@wrt,canyons:/tmp/dump .
|
||||
|
||||
Note that hostnames are resolved by the prior hop (so "canyons" would be resolved by the host "wrt")
|
||||
in the example above, the same way as other -L TCP forwarded hosts are. Host keys are
|
||||
checked locally based on the given hostname.
|
||||
|
||||
.SH ESCAPE CHARACTERS
|
||||
Typing a newline followed by the key sequence \fI~.\fR (tilde, dot) will terminate a connection.
|
||||
The sequence \fI~^Z\fR (tilde, ctrl-z) will background the connection. This behaviour only
|
||||
applies when a PTY is used.
|
||||
|
||||
.SH ENVIRONMENT
|
||||
.TP
|
||||
.B DROPBEAR_PASSWORD
|
||||
A password to use for remote authentication can be specified in the environment
|
||||
variable DROPBEAR_PASSWORD. Care should be taken that the password is not
|
||||
exposed to other users on a multi-user system, or stored in accessible files.
|
||||
.TP
|
||||
.B SSH_ASKPASS
|
||||
dbclient can use an external program to request a password from a user.
|
||||
SSH_ASKPASS should be set to the path of a program that will return a password
|
||||
on standard output. This program will only be used if either DISPLAY is set and
|
||||
standard input is not a TTY, or the environment variable SSH_ASKPASS_ALWAYS is
|
||||
set.
|
||||
.SH NOTES
|
||||
If compiled with zlib support and if the server supports it, dbclient will
|
||||
always use compression.
|
||||
|
||||
.SH AUTHOR
|
||||
Matt Johnston (matt@ucc.asn.au).
|
||||
.br
|
||||
Mihnea Stoenescu wrote initial Dropbear client support
|
||||
.br
|
||||
Gerrit Pape (pape@smarden.org) wrote this manual page.
|
||||
.SH SEE ALSO
|
||||
dropbear(8), dropbearkey(1)
|
||||
.P
|
||||
https://matt.ucc.asn.au/dropbear/dropbear.html
|
||||
18
dbhelpers.c
Normal file
18
dbhelpers.c
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "dbhelpers.h"
|
||||
#include "includes.h"
|
||||
|
||||
/* Erase data */
|
||||
void m_burn(void *data, unsigned int len) {
|
||||
|
||||
#if defined(HAVE_MEMSET_S)
|
||||
memset_s(data, len, 0x0, len);
|
||||
#elif defined(HAVE_EXPLICIT_BZERO)
|
||||
explicit_bzero(data, len);
|
||||
#else
|
||||
/* This must be volatile to avoid compiler optimisation */
|
||||
volatile void *p = data;
|
||||
memset((void*)p, 0x0, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
21
dbhelpers.h
Normal file
21
dbhelpers.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef DROPBEAR_DBHELPERS_H_
|
||||
#define DROPBEAR_DBHELPERS_H_
|
||||
|
||||
/* This header defines some things that are also used by libtomcrypt/math.
|
||||
We avoid including normal include.h since that can result in conflicting
|
||||
definitions - only include config.h */
|
||||
#include "config.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define ATTRIB_PRINTF(fmt,args) __attribute__((format(printf, fmt, args)))
|
||||
#define ATTRIB_NORETURN __attribute__((noreturn))
|
||||
#define ATTRIB_SENTINEL __attribute__((sentinel))
|
||||
#else
|
||||
#define ATTRIB_PRINTF(fmt,args)
|
||||
#define ATTRIB_NORETURN
|
||||
#define ATTRIB_SENTINEL
|
||||
#endif
|
||||
|
||||
void m_burn(void* data, unsigned int len);
|
||||
|
||||
#endif /* DROPBEAR_DBHELPERS_H_ */
|
||||
192
dbmalloc.c
Normal file
192
dbmalloc.c
Normal file
@@ -0,0 +1,192 @@
|
||||
#include "dbmalloc.h"
|
||||
#include "dbutil.h"
|
||||
|
||||
|
||||
void * m_calloc(size_t nmemb, size_t size) {
|
||||
if (SIZE_T_MAX / nmemb < size) {
|
||||
dropbear_exit("m_calloc failed");
|
||||
}
|
||||
return m_malloc(nmemb*size);
|
||||
}
|
||||
|
||||
void * m_strdup(const char * str) {
|
||||
char* ret;
|
||||
unsigned int len;
|
||||
len = strlen(str);
|
||||
|
||||
ret = m_malloc(len+1);
|
||||
if (ret == NULL) {
|
||||
dropbear_exit("m_strdup failed");
|
||||
}
|
||||
memcpy(ret, str, len+1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if !DROPBEAR_TRACKING_MALLOC
|
||||
|
||||
/* Simple wrappers around malloc etc */
|
||||
void * m_malloc(size_t size) {
|
||||
|
||||
void* ret;
|
||||
|
||||
if (size == 0) {
|
||||
dropbear_exit("m_malloc failed");
|
||||
}
|
||||
ret = calloc(1, size);
|
||||
if (ret == NULL) {
|
||||
dropbear_exit("m_malloc failed");
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
void * m_realloc(void* ptr, size_t size) {
|
||||
|
||||
void *ret;
|
||||
|
||||
if (size == 0) {
|
||||
dropbear_exit("m_realloc failed");
|
||||
}
|
||||
ret = realloc(ptr, size);
|
||||
if (ret == NULL) {
|
||||
dropbear_exit("m_realloc failed");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
/* For fuzzing */
|
||||
|
||||
struct dbmalloc_header {
|
||||
unsigned int epoch;
|
||||
struct dbmalloc_header *prev;
|
||||
struct dbmalloc_header *next;
|
||||
};
|
||||
|
||||
static void put_alloc(struct dbmalloc_header *header);
|
||||
static void remove_alloc(struct dbmalloc_header *header);
|
||||
|
||||
/* end of the linked list */
|
||||
static struct dbmalloc_header* staple;
|
||||
|
||||
unsigned int current_epoch = 0;
|
||||
|
||||
void m_malloc_set_epoch(unsigned int epoch) {
|
||||
current_epoch = epoch;
|
||||
}
|
||||
|
||||
void m_malloc_free_epoch(unsigned int epoch, int dofree) {
|
||||
struct dbmalloc_header* header;
|
||||
struct dbmalloc_header* nextheader = NULL;
|
||||
struct dbmalloc_header* oldstaple = staple;
|
||||
staple = NULL;
|
||||
/* free allocations from this epoch, create a new staple-anchored list from
|
||||
the remainder */
|
||||
for (header = oldstaple; header; header = nextheader)
|
||||
{
|
||||
nextheader = header->next;
|
||||
if (header->epoch == epoch) {
|
||||
if (dofree) {
|
||||
free(header);
|
||||
}
|
||||
} else {
|
||||
header->prev = NULL;
|
||||
header->next = NULL;
|
||||
put_alloc(header);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void put_alloc(struct dbmalloc_header *header) {
|
||||
assert(header->next == NULL);
|
||||
assert(header->prev == NULL);
|
||||
if (staple) {
|
||||
staple->prev = header;
|
||||
}
|
||||
header->next = staple;
|
||||
staple = header;
|
||||
}
|
||||
|
||||
static void remove_alloc(struct dbmalloc_header *header) {
|
||||
if (header->prev) {
|
||||
header->prev->next = header->next;
|
||||
}
|
||||
if (header->next) {
|
||||
header->next->prev = header->prev;
|
||||
}
|
||||
if (staple == header) {
|
||||
staple = header->next;
|
||||
}
|
||||
header->prev = NULL;
|
||||
header->next = NULL;
|
||||
}
|
||||
|
||||
static struct dbmalloc_header* get_header(void* ptr) {
|
||||
char* bptr = ptr;
|
||||
return (struct dbmalloc_header*)&bptr[-sizeof(struct dbmalloc_header)];
|
||||
}
|
||||
|
||||
void * m_malloc(size_t size) {
|
||||
char* mem = NULL;
|
||||
struct dbmalloc_header* header = NULL;
|
||||
|
||||
if (size == 0 || size > 1e9) {
|
||||
dropbear_exit("m_malloc failed");
|
||||
}
|
||||
|
||||
size = size + sizeof(struct dbmalloc_header);
|
||||
|
||||
mem = calloc(1, size);
|
||||
if (mem == NULL) {
|
||||
dropbear_exit("m_malloc failed");
|
||||
}
|
||||
header = (struct dbmalloc_header*)mem;
|
||||
put_alloc(header);
|
||||
header->epoch = current_epoch;
|
||||
return &mem[sizeof(struct dbmalloc_header)];
|
||||
}
|
||||
|
||||
void * m_realloc(void* ptr, size_t size) {
|
||||
char* mem = NULL;
|
||||
struct dbmalloc_header* header = NULL;
|
||||
if (size == 0 || size > 1e9) {
|
||||
dropbear_exit("m_realloc failed");
|
||||
}
|
||||
|
||||
header = get_header(ptr);
|
||||
remove_alloc(header);
|
||||
|
||||
size = size + sizeof(struct dbmalloc_header);
|
||||
mem = realloc(header, size);
|
||||
if (mem == NULL) {
|
||||
dropbear_exit("m_realloc failed");
|
||||
}
|
||||
|
||||
header = (struct dbmalloc_header*)mem;
|
||||
put_alloc(header);
|
||||
return &mem[sizeof(struct dbmalloc_header)];
|
||||
}
|
||||
|
||||
void m_free_direct(void* ptr) {
|
||||
struct dbmalloc_header* header = NULL;
|
||||
if (!ptr) {
|
||||
return;
|
||||
}
|
||||
header = get_header(ptr);
|
||||
remove_alloc(header);
|
||||
free(header);
|
||||
}
|
||||
|
||||
#endif /* DROPBEAR_TRACKING_MALLOC */
|
||||
|
||||
void * m_realloc_ltm(void* ptr, size_t oldsize, size_t newsize) {
|
||||
(void)oldsize;
|
||||
return m_realloc(ptr, newsize);
|
||||
}
|
||||
|
||||
void m_free_ltm(void *mem, size_t size) {
|
||||
(void)size;
|
||||
m_free_direct(mem);
|
||||
}
|
||||
27
dbmalloc.h
Normal file
27
dbmalloc.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef DBMALLOC_H_
|
||||
#define DBMALLOC_H_
|
||||
|
||||
#include "options.h"
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void * m_malloc(size_t size);
|
||||
void * m_calloc(size_t nmemb, size_t size);
|
||||
void * m_strdup(const char * str);
|
||||
void * m_realloc(void* ptr, size_t size);
|
||||
|
||||
#if DROPBEAR_TRACKING_MALLOC
|
||||
void m_free_direct(void* ptr);
|
||||
void m_malloc_set_epoch(unsigned int epoch);
|
||||
void m_malloc_free_epoch(unsigned int epoch, int dofree);
|
||||
|
||||
#else
|
||||
/* plain wrapper */
|
||||
#define m_free_direct free
|
||||
|
||||
#endif
|
||||
|
||||
#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
|
||||
|
||||
|
||||
#endif /* DBMALLOC_H_ */
|
||||
45
dbmulti.c
45
dbmulti.c
@@ -23,24 +23,15 @@
|
||||
* SOFTWARE. */
|
||||
|
||||
#include "includes.h"
|
||||
#include "dbutil.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]);
|
||||
static int runprog(const char *multipath,
|
||||
const char *progname, int argc, char ** argv, int *match) {
|
||||
*match = DROPBEAR_SUCCESS;
|
||||
|
||||
#ifdef DBMULTI_dropbear
|
||||
if (strcmp(progname, "dropbear") == 0) {
|
||||
return dropbear_main(argc, argv);
|
||||
return dropbear_main(argc, argv, multipath);
|
||||
}
|
||||
#endif
|
||||
#ifdef DBMULTI_dbclient
|
||||
@@ -64,10 +55,32 @@ int main(int argc, char ** argv) {
|
||||
return scp_main(argc, argv);
|
||||
}
|
||||
#endif
|
||||
*match = DROPBEAR_FAILURE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
int i;
|
||||
for (i = 0; i < 2; i++) {
|
||||
const char* multipath = NULL;
|
||||
if (i == 1) {
|
||||
multipath = argv[0];
|
||||
}
|
||||
/* Try symlink first, then try as an argument eg "dropbearmulti dbclient host ..." */
|
||||
if (argc > i) {
|
||||
int match, res;
|
||||
/* figure which form we're being called as */
|
||||
const char* progname = basename(argv[i]);
|
||||
res = runprog(multipath, progname, argc-i, &argv[i], &match);
|
||||
if (match == DROPBEAR_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Dropbear multi-purpose version %s\n"
|
||||
"Make a symlink pointing at this binary with one of the following names:\n"
|
||||
fprintf(stderr, "Dropbear SSH multi-purpose v%s\n"
|
||||
"Make a symlink pointing at this binary with one of the\n"
|
||||
"following names or run 'dropbearmulti <command>'.\n"
|
||||
#ifdef DBMULTI_dropbear
|
||||
"'dropbear' - the Dropbear server\n"
|
||||
#endif
|
||||
|
||||
377
dbrandom.c
Normal file
377
dbrandom.c
Normal file
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
* 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 "buffer.h"
|
||||
#include "dbutil.h"
|
||||
#include "bignum.h"
|
||||
#include "dbrandom.h"
|
||||
#include "runopts.h"
|
||||
|
||||
/* this is used to generate unique output from the same hashpool */
|
||||
static uint32_t counter = 0;
|
||||
/* the max value for the counter, so it won't integer overflow */
|
||||
#define MAX_COUNTER (1<<30)
|
||||
|
||||
static unsigned char hashpool[SHA256_HASH_SIZE] = {0};
|
||||
static int donerandinit = 0;
|
||||
|
||||
#define INIT_SEED_SIZE 32 /* 256 bits */
|
||||
|
||||
/* The basic setup is we read some data from /dev/(u)random or prngd and hash it
|
||||
* into hashpool. To read data, we hash together current hashpool contents,
|
||||
* and a counter. We feed more data in by hashing the current pool and new
|
||||
* data into the pool.
|
||||
*
|
||||
* It is important to ensure that counter doesn't wrap around before we
|
||||
* feed in new entropy.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Pass wantlen=0 to hash an entire file */
|
||||
static int
|
||||
process_file(hash_state *hs, const char *filename,
|
||||
unsigned int wantlen, int prngd) {
|
||||
int readfd = -1;
|
||||
unsigned int readcount;
|
||||
int ret = DROPBEAR_FAILURE;
|
||||
|
||||
if (prngd) {
|
||||
#if DROPBEAR_USE_PRNGD
|
||||
readfd = connect_unix(filename);
|
||||
#endif
|
||||
} else {
|
||||
readfd = open(filename, O_RDONLY);
|
||||
}
|
||||
|
||||
if (readfd < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
readcount = 0;
|
||||
while (wantlen == 0 || readcount < wantlen) {
|
||||
int readlen, wantread;
|
||||
unsigned char readbuf[4096];
|
||||
if (wantlen == 0) {
|
||||
wantread = sizeof(readbuf);
|
||||
} else {
|
||||
wantread = MIN(sizeof(readbuf), wantlen-readcount);
|
||||
}
|
||||
|
||||
#if DROPBEAR_USE_PRNGD
|
||||
if (prngd) {
|
||||
char egdcmd[2];
|
||||
egdcmd[0] = 0x02; /* blocking read */
|
||||
egdcmd[1] = (unsigned char)wantread;
|
||||
if (write(readfd, egdcmd, 2) < 0) {
|
||||
dropbear_exit("Can't send command to egd");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
readlen = read(readfd, readbuf, wantread);
|
||||
if (readlen <= 0) {
|
||||
if (readlen < 0 && errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
if (readlen == 0 && wantlen == 0) {
|
||||
/* whole file was read as requested */
|
||||
break;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
sha256_process(hs, readbuf, readlen);
|
||||
readcount += readlen;
|
||||
}
|
||||
ret = DROPBEAR_SUCCESS;
|
||||
out:
|
||||
close(readfd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void addrandom(const unsigned char * buf, unsigned int len)
|
||||
{
|
||||
hash_state hs;
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
if (fuzz.fuzzing) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* hash in the new seed data */
|
||||
sha256_init(&hs);
|
||||
/* existing state (zeroes on startup) */
|
||||
sha256_process(&hs, (void*)hashpool, sizeof(hashpool));
|
||||
|
||||
/* new */
|
||||
sha256_process(&hs, buf, len);
|
||||
sha256_done(&hs, hashpool);
|
||||
}
|
||||
|
||||
static void write_urandom()
|
||||
{
|
||||
#if DROPBEAR_FUZZ
|
||||
if (fuzz.fuzzing) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if !DROPBEAR_USE_PRNGD
|
||||
/* This is opportunistic, don't worry about failure */
|
||||
unsigned char buf[INIT_SEED_SIZE];
|
||||
FILE *f = fopen(DROPBEAR_URANDOM_DEV, "w");
|
||||
if (!f) {
|
||||
return;
|
||||
}
|
||||
genrandom(buf, sizeof(buf));
|
||||
fwrite(buf, sizeof(buf), 1, f);
|
||||
fclose(f);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
void fuzz_seed(const unsigned char* dat, unsigned int len) {
|
||||
hash_state hs;
|
||||
sha256_init(&hs);
|
||||
sha256_process(&hs, "fuzzfuzzfuzz", strlen("fuzzfuzzfuzz"));
|
||||
sha256_process(&hs, dat, len);
|
||||
sha256_done(&hs, hashpool);
|
||||
counter = 0;
|
||||
donerandinit = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_GETRANDOM
|
||||
/* Reads entropy seed with getrandom().
|
||||
* May block if the kernel isn't ready.
|
||||
* Return DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
|
||||
static int process_getrandom(hash_state *hs) {
|
||||
char buf[INIT_SEED_SIZE];
|
||||
ssize_t ret;
|
||||
|
||||
/* First try non-blocking so that we can warn about waiting */
|
||||
ret = getrandom(buf, sizeof(buf), GRND_NONBLOCK);
|
||||
if (ret == -1) {
|
||||
if (errno == ENOSYS) {
|
||||
/* Old kernel */
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
/* Other errors fall through to blocking getrandom() */
|
||||
TRACE(("first getrandom() failed: %d %s", errno, strerror(errno)))
|
||||
if (errno == EAGAIN) {
|
||||
dropbear_log(LOG_WARNING, "Waiting for kernel randomness to be initialised...");
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait blocking if needed. Loop in case we get EINTR */
|
||||
while (ret != sizeof(buf)) {
|
||||
ret = getrandom(buf, sizeof(buf), 0);
|
||||
|
||||
if (ret == sizeof(buf)) {
|
||||
/* Success */
|
||||
break;
|
||||
}
|
||||
if (ret == -1 && errno == EINTR) {
|
||||
/* Try again. */
|
||||
continue;
|
||||
}
|
||||
if (ret >= 0) {
|
||||
TRACE(("Short read %zd from getrandom() shouldn't happen", ret))
|
||||
/* Try again? */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Unexpected problem, fall back to /dev/urandom */
|
||||
TRACE(("2nd getrandom() failed: %d %s", errno, strerror(errno)))
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == sizeof(buf)) {
|
||||
/* Success, stir in the entropy */
|
||||
sha256_process(hs, (void*)buf, sizeof(buf));
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
|
||||
return DROPBEAR_FAILURE;
|
||||
|
||||
}
|
||||
#endif /* HAVE_GETRANDOM */
|
||||
|
||||
/* Initialise the prng from /dev/urandom or prngd. This function can
|
||||
* be called multiple times */
|
||||
void seedrandom() {
|
||||
hash_state hs;
|
||||
|
||||
pid_t pid;
|
||||
struct timeval tv;
|
||||
clock_t clockval;
|
||||
int urandom_seeded = 0;
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
if (fuzz.fuzzing) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* hash in the new seed data */
|
||||
sha256_init(&hs);
|
||||
|
||||
/* existing state */
|
||||
sha256_process(&hs, (void*)hashpool, sizeof(hashpool));
|
||||
|
||||
#ifdef HAVE_GETRANDOM
|
||||
if (process_getrandom(&hs) == DROPBEAR_SUCCESS) {
|
||||
urandom_seeded = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!urandom_seeded) {
|
||||
#if DROPBEAR_USE_PRNGD
|
||||
if (process_file(&hs, DROPBEAR_PRNGD_SOCKET, INIT_SEED_SIZE, 1)
|
||||
!= DROPBEAR_SUCCESS) {
|
||||
dropbear_exit("Failure reading random device %s",
|
||||
DROPBEAR_PRNGD_SOCKET);
|
||||
urandom_seeded = 1;
|
||||
}
|
||||
#else
|
||||
/* non-blocking random source (probably /dev/urandom) */
|
||||
if (process_file(&hs, DROPBEAR_URANDOM_DEV, INIT_SEED_SIZE, 0)
|
||||
!= DROPBEAR_SUCCESS) {
|
||||
dropbear_exit("Failure reading random device %s",
|
||||
DROPBEAR_URANDOM_DEV);
|
||||
urandom_seeded = 1;
|
||||
}
|
||||
#endif
|
||||
} /* urandom_seeded */
|
||||
|
||||
/* A few other sources to fall back on.
|
||||
* Add more here for other platforms */
|
||||
#ifdef __linux__
|
||||
/* Seems to be a reasonable source of entropy from timers. Possibly hard
|
||||
* for even local attackers to reproduce */
|
||||
process_file(&hs, "/proc/timer_list", 0, 0);
|
||||
/* Might help on systems with wireless */
|
||||
process_file(&hs, "/proc/interrupts", 0, 0);
|
||||
|
||||
process_file(&hs, "/proc/loadavg", 0, 0);
|
||||
process_file(&hs, "/proc/sys/kernel/random/entropy_avail", 0, 0);
|
||||
|
||||
/* Mostly network visible but useful in some situations.
|
||||
* Limit size to avoid slowdowns on systems with lots of routes */
|
||||
process_file(&hs, "/proc/net/netstat", 4096, 0);
|
||||
process_file(&hs, "/proc/net/dev", 4096, 0);
|
||||
process_file(&hs, "/proc/net/tcp", 4096, 0);
|
||||
/* Also includes interface lo */
|
||||
process_file(&hs, "/proc/net/rt_cache", 4096, 0);
|
||||
process_file(&hs, "/proc/vmstat", 0, 0);
|
||||
#endif
|
||||
|
||||
pid = getpid();
|
||||
sha256_process(&hs, (void*)&pid, sizeof(pid));
|
||||
|
||||
/* gettimeofday() doesn't completely fill out struct timeval on
|
||||
OS X (10.8.3), avoid valgrind warnings by clearing it first */
|
||||
memset(&tv, 0x0, sizeof(tv));
|
||||
gettimeofday(&tv, NULL);
|
||||
sha256_process(&hs, (void*)&tv, sizeof(tv));
|
||||
|
||||
clockval = clock();
|
||||
sha256_process(&hs, (void*)&clockval, sizeof(clockval));
|
||||
|
||||
/* When a private key is read by the client or server it will
|
||||
* be added to the hashpool - see runopts.c */
|
||||
|
||||
sha256_done(&hs, hashpool);
|
||||
|
||||
counter = 0;
|
||||
donerandinit = 1;
|
||||
|
||||
/* Feed it all back into /dev/urandom - this might help if Dropbear
|
||||
* is running from inetd and gets new state each time */
|
||||
write_urandom();
|
||||
}
|
||||
|
||||
/* return len bytes of pseudo-random data */
|
||||
void genrandom(unsigned char* buf, unsigned int len) {
|
||||
|
||||
hash_state hs;
|
||||
unsigned char hash[SHA256_HASH_SIZE];
|
||||
unsigned int copylen;
|
||||
|
||||
if (!donerandinit) {
|
||||
dropbear_exit("seedrandom not done");
|
||||
}
|
||||
|
||||
while (len > 0) {
|
||||
sha256_init(&hs);
|
||||
sha256_process(&hs, (void*)hashpool, sizeof(hashpool));
|
||||
sha256_process(&hs, (void*)&counter, sizeof(counter));
|
||||
sha256_done(&hs, hash);
|
||||
|
||||
counter++;
|
||||
if (counter > MAX_COUNTER) {
|
||||
seedrandom();
|
||||
}
|
||||
|
||||
copylen = MIN(len, SHA256_HASH_SIZE);
|
||||
memcpy(buf, hash, copylen);
|
||||
len -= copylen;
|
||||
buf += copylen;
|
||||
}
|
||||
m_burn(hash, sizeof(hash));
|
||||
}
|
||||
|
||||
/* Generates a random mp_int.
|
||||
* max is a *mp_int specifying an upper bound.
|
||||
* rand must be an initialised *mp_int for the result.
|
||||
* the result rand satisfies: 0 < rand < max
|
||||
* */
|
||||
void gen_random_mpint(const mp_int *max, mp_int *rand) {
|
||||
|
||||
unsigned char *randbuf = NULL;
|
||||
unsigned int len = 0;
|
||||
const unsigned char masks[] = {0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f};
|
||||
|
||||
const int size_bits = mp_count_bits(max);
|
||||
|
||||
len = size_bits / 8;
|
||||
if ((size_bits % 8) != 0) {
|
||||
len += 1;
|
||||
}
|
||||
|
||||
randbuf = (unsigned char*)m_malloc(len);
|
||||
do {
|
||||
genrandom(randbuf, len);
|
||||
/* Mask out the unrequired bits - mp_read_unsigned_bin expects
|
||||
* MSB first.*/
|
||||
randbuf[0] &= masks[size_bits % 8];
|
||||
|
||||
bytes_to_mp(rand, randbuf, len);
|
||||
|
||||
/* keep regenerating until we get one satisfying
|
||||
* 0 < rand < max */
|
||||
} while (!(mp_cmp(rand, max) == MP_LT && mp_cmp_d(rand, 0) == MP_GT));
|
||||
m_burn(randbuf, len);
|
||||
m_free(randbuf);
|
||||
}
|
||||
35
dbrandom.h
Normal file
35
dbrandom.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 DROPBEAR_RANDOM_H_
|
||||
#define DROPBEAR_RANDOM_H_
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
void seedrandom(void);
|
||||
void genrandom(unsigned char* buf, unsigned int len);
|
||||
void addrandom(const unsigned char * buf, unsigned int len);
|
||||
void gen_random_mpint(const mp_int *max, mp_int *rand);
|
||||
|
||||
#endif /* DROPBEAR_RANDOM_H_ */
|
||||
94
dbutil.h
94
dbutil.h
@@ -22,48 +22,94 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#ifndef _DBUTIL_H_
|
||||
#ifndef DROPBEAR_DBUTIL_H_
|
||||
|
||||
#define _DBUTIL_H_
|
||||
#define DROPBEAR_DBUTIL_H_
|
||||
|
||||
#include "includes.h"
|
||||
#include "buffer.h"
|
||||
#include "queue.h"
|
||||
#include "dbhelpers.h"
|
||||
#include "dbmalloc.h"
|
||||
|
||||
#ifndef DISABLE_SYSLOG
|
||||
void startsyslog();
|
||||
void startsyslog(const char *ident);
|
||||
#endif
|
||||
|
||||
extern void (*_dropbear_exit)(int exitcode, const char* format, va_list param);
|
||||
extern void (*_dropbear_exit)(int exitcode, const char* format, va_list param) ATTRIB_NORETURN;
|
||||
extern void (*_dropbear_log)(int priority, const char* format, va_list param);
|
||||
|
||||
void dropbear_exit(const char* format, ...);
|
||||
void dropbear_close(const char* format, ...);
|
||||
void dropbear_log(int priority, const char* format, ...);
|
||||
#ifdef DEBUG_TRACE
|
||||
void dropbear_trace(const char* format, ...);
|
||||
void printhex(unsigned char* buf, int len);
|
||||
void dropbear_exit(const char* format, ...) ATTRIB_PRINTF(1,2) ATTRIB_NORETURN;
|
||||
|
||||
void dropbear_close(const char* format, ...) ATTRIB_PRINTF(1,2) ;
|
||||
void dropbear_log(int priority, const char* format, ...) ATTRIB_PRINTF(2,3) ;
|
||||
|
||||
void fail_assert(const char* expr, const char* file, int line) ATTRIB_NORETURN;
|
||||
|
||||
#if DEBUG_TRACE
|
||||
void dropbear_trace1(const char* format, ...) ATTRIB_PRINTF(1,2);
|
||||
void dropbear_trace2(const char* format, ...) ATTRIB_PRINTF(1,2);
|
||||
void dropbear_trace3(const char* format, ...) ATTRIB_PRINTF(1,2);
|
||||
void dropbear_trace4(const char* format, ...) ATTRIB_PRINTF(1,2);
|
||||
void dropbear_trace5(const char* format, ...) ATTRIB_PRINTF(1,2);
|
||||
void printhex(const char * label, const unsigned char * buf, int len);
|
||||
void printmpint(const char *label, const mp_int *mp);
|
||||
void debug_start_net(void);
|
||||
extern int debug_trace;
|
||||
#endif
|
||||
|
||||
char * stripcontrol(const char * text);
|
||||
unsigned char * getaddrstring(struct sockaddr_storage* addr, int withport);
|
||||
int dropbear_listen(const char* address, const char* port,
|
||||
int *socks, unsigned int sockcount, char **errstring, int *maxfd);
|
||||
int connect_remote(const char* remotehost, const char* remoteport,
|
||||
int nonblocking, char ** errstring);
|
||||
char* getaddrhostname(struct sockaddr_storage * addr);
|
||||
|
||||
int spawn_command(void(*exec_fn)(const void *user_data), const void *exec_data,
|
||||
int *writefd, int *readfd, int *errfd, pid_t *pid);
|
||||
void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell);
|
||||
#if ENABLE_CONNECT_UNIX
|
||||
int connect_unix(const char* addr);
|
||||
#endif
|
||||
int buf_readfile(buffer* buf, const char* filename);
|
||||
int buf_getline(buffer * line, FILE * authfile);
|
||||
|
||||
int 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 m_close(int fd);
|
||||
void setnonblocking(int fd);
|
||||
void disallow_core(void);
|
||||
int m_str_to_uint(const char* str, unsigned int *val);
|
||||
/* The same as snprintf() but exits rather than returning negative */
|
||||
int m_snprintf(char *str, size_t size, const char *format, ...);
|
||||
|
||||
/* Used to force mp_ints to be initialised */
|
||||
#define DEF_MP_INT(X) mp_int X = {0, 0, 0, NULL}
|
||||
|
||||
#endif /* _DBUTIL_H_ */
|
||||
/* Dropbear assertion */
|
||||
#define dropbear_assert(X) do { if (!(X)) { fail_assert(#X, __FILE__, __LINE__); } } while (0)
|
||||
|
||||
/* Returns 0 if a and b have the same contents */
|
||||
int constant_time_memcmp(const void* a, const void *b, size_t n);
|
||||
|
||||
/* Returns a time in seconds that doesn't go backwards - does not correspond to
|
||||
a real-world clock */
|
||||
time_t monotonic_now(void);
|
||||
/* Higher resolution clock_gettime(CLOCK_MONOTONIC) wrapper */
|
||||
void gettime_wrapper(struct timespec *now);
|
||||
|
||||
char * expand_homedir_path(const char *inpath);
|
||||
|
||||
void fsync_parent_dir(const char* fn);
|
||||
|
||||
int fd_read_pending(int fd);
|
||||
|
||||
#if DROPBEAR_MSAN
|
||||
/* FD_ZERO seems to leave some memory uninitialized. clear it to avoid false positives */
|
||||
#define DROPBEAR_FD_ZERO(fds) do { memset((fds), 0x0, sizeof(fd_set)); FD_ZERO(fds); } while(0)
|
||||
#else
|
||||
#define DROPBEAR_FD_ZERO(fds) FD_ZERO(fds)
|
||||
#endif
|
||||
|
||||
/* dropbearmulti entry points */
|
||||
int dropbear_main(int argc, char ** argv, const char * multipath);
|
||||
int cli_main(int argc, char ** argv);
|
||||
int dropbearkey_main(int argc, char ** argv);
|
||||
int dropbearconvert_main(int argc, char ** argv);
|
||||
int scp_main(int argc, char ** argv);
|
||||
|
||||
|
||||
#endif /* DROPBEAR_DBUTIL_H_ */
|
||||
|
||||
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
|
||||
16
debian/README.runit
vendored
16
debian/README.runit
vendored
@@ -31,16 +31,16 @@ run script
|
||||
|
||||
# vi /etc/dropbear/run
|
||||
|
||||
Finally enable the service by linking dropbear's service directory to
|
||||
/var/service/. The service will be started within five seconds, and
|
||||
automatically at boot time. The sysv init script is disabled; see the
|
||||
runsvctrl(8) program for information on how to control services handled by
|
||||
runit. See the svlogd(8) program on how to configure the log service.
|
||||
Finally enable the service through runit's update-service(8) program, the
|
||||
service will be started within five seconds, and automatically at boot
|
||||
time, and the sysv init script will automatically be disabled; see the
|
||||
sv(8) program for information on how to control services handled by runit.
|
||||
See the svlogd(8) program on how to configure the log service.
|
||||
|
||||
# ln -s /etc/dropbear /var/service/
|
||||
# update-service --add /etc/dropbear
|
||||
|
||||
Optionally check the status of the service a few seconds later
|
||||
|
||||
# runsvstat -l /var/service/dropbear
|
||||
# sv status dropbear
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org>, Sun, 16 May 2004 15:52:34 +0000
|
||||
-- Gerrit Pape <pape@smarden.org>, Fri, 02 Mar 2007 20:41:08 +0000
|
||||
|
||||
375
debian/changelog
vendored
375
debian/changelog
vendored
@@ -1,53 +1,364 @@
|
||||
dropbear (0.45-1) unstable; urgency=high
|
||||
dropbear (2022.83-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Mon, 14 Nov 2022 22:51:57 +0800
|
||||
|
||||
dropbear (2022.82-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Fri, 1 Apr 2022 22:51:57 +0800
|
||||
|
||||
dropbear (2020.81-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Thu, 29 Oct 2020 22:51:57 +0800
|
||||
|
||||
dropbear (2020.80-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Fri, 26 Jun 2020 22:51:57 +0800
|
||||
|
||||
dropbear (2020.79-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Mon, 15 Jun 2020 22:51:57 +0800
|
||||
|
||||
dropbear (2019.78-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Wed, 27 Mar 2019 22:51:57 +0800
|
||||
|
||||
dropbear (2019.77-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Sat, 23 Mar 2019 22:51:57 +0800
|
||||
|
||||
dropbear (2018.76-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Tue, 27 Feb 2018 22:51:57 +0800
|
||||
|
||||
dropbear (2017.75-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Thu, 18 May 2017 22:51:57 +0800
|
||||
|
||||
dropbear (2016.74-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Thu, 21 Jul 2016 22:51:57 +0800
|
||||
|
||||
dropbear (2016.73-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Fri, 18 Mar 2016 22:52:58 +0800
|
||||
|
||||
dropbear (2016.72-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Wed, 10 Mar 2016 22:52:58 +0800
|
||||
|
||||
dropbear (2015.70-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Thu, 26 Nov 2015 22:52:58 +0800
|
||||
|
||||
dropbear (2015.69-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Wed, 25 Nov 2015 22:52:58 +0800
|
||||
|
||||
dropbear (2015.68-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Sat, 8 Aug 2015 22:52:58 +0800
|
||||
|
||||
dropbear (2015.67-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Wed, 28 Jan 2015 22:53:59 +0800
|
||||
|
||||
dropbear (2014.66-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Thu, 23 Oct 2014 22:54:00 +0800
|
||||
|
||||
dropbear (2014.65-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Fri, 8 Aug 2014 22:54:00 +0800
|
||||
|
||||
dropbear (2014.64-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Sun, 27 Jul 2014 22:54:00 +0800
|
||||
|
||||
dropbear (2014.63-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Wed, 19 Feb 2014 22:54:00 +0800
|
||||
|
||||
dropbear (2013.62) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Tue, 7 Dec 2013 22:54:00 +0800
|
||||
|
||||
dropbear (2013.60-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Wed, 16 Oct 2013 22:54:00 +0800
|
||||
|
||||
dropbear (2013.59-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* Build with DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Fri, 4 Oct 2013 22:54:00 +0800
|
||||
|
||||
dropbear (2013.58-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Thu, 18 Apr 2013 22:54:00 +0800
|
||||
|
||||
dropbear (2013.57-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Mon, 15 Apr 2013 22:54:00 +0800
|
||||
|
||||
dropbear (2013.56-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Thu, 21 Mar 2013 22:54:00 +0800
|
||||
|
||||
dropbear (2012.55-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Wed, 22 Feb 2012 22:54:00 +0800
|
||||
|
||||
dropbear (2011.54-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Tues, 8 Nov 2011 22:54:00 +0800
|
||||
|
||||
dropbear (0.53.1-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Wed, 2 Mar 2011 22:54:00 +0900
|
||||
|
||||
dropbear (0.53-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Thu, 24 Feb 2011 22:54:00 +0900
|
||||
|
||||
dropbear (0.52-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Wed, 12 Nov 2008 22:54:00 +0900
|
||||
|
||||
dropbear (0.51-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Thu, 27 Mar 2008 19:14:00 +0900
|
||||
|
||||
dropbear (0.50-4) unstable; urgency=low
|
||||
|
||||
* debian/dropbear.init: apply patch from Petter Reinholdtsen: add LSB
|
||||
formatted dependency info in init.d script (closes: #466257).
|
||||
* debian/rules: no longer include symlinks for ./supervise/ subdirectories.
|
||||
* debian/dropbear.postinst: upgrade from << 0.50-4: if dropbear is managed
|
||||
by runit, remove service, and re-add using update-service(8).
|
||||
* debian/control: Standards-Version: 3.7.3.0.
|
||||
* debian/rules: target clean: don't ignore errors but check for readable
|
||||
./Makefile.
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org> Thu, 06 Mar 2008 19:06:58 +0000
|
||||
|
||||
dropbear (0.50-3) unstable; urgency=low
|
||||
|
||||
* debian/dropbear.init: use the update-service(8) program from the runit
|
||||
package instead of directly checking for the symlink in /var/service/.
|
||||
* debian/README.runit: talk about update-service(8) instead of symlinks
|
||||
in /var/service/.
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org> Fri, 15 Feb 2008 00:32:37 +0000
|
||||
|
||||
dropbear (0.50-2) unstable; urgency=low
|
||||
|
||||
* debian/dropbear.README.Debian: no longer talk about entropy from
|
||||
/dev/random, /dev/urandom is now used by default (thx Joey Hess,
|
||||
closes: #441515).
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org> Mon, 24 Sep 2007 16:49:17 +0000
|
||||
|
||||
dropbear (0.50-1) unstable; urgency=low
|
||||
|
||||
* debian/README.runit: minor.
|
||||
* new upstream version.
|
||||
* debian/diff/0001-options.h-use-dev-urandom-instead-of-dev-random-a.diff:
|
||||
remove; fixed upstream.
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org> Thu, 09 Aug 2007 23:01:01 +0000
|
||||
|
||||
dropbear (0.49-2) unstable; urgency=low
|
||||
|
||||
* debian/rules: apply diffs from debian/diff/ with patch -p1 instead of
|
||||
-p0.
|
||||
* debian/diff/0001-options.h-use-dev-urandom-instead-of-dev-random-a.diff:
|
||||
new; options.h: use /dev/urandom instead of /dev/random as
|
||||
DROPBEAR_RANDOM_DEV (closes: #386976).
|
||||
* debian/rules: target clean: remove libtomcrypt/Makefile,
|
||||
libtommath/Makefile.
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org> Sat, 09 Jun 2007 08:59:59 +0000
|
||||
|
||||
dropbear (0.49-1) unstable; urgency=high
|
||||
|
||||
* new upstream release, fixes
|
||||
* CVE-2007-1099: dropbear dbclient insufficient warning on hostkey
|
||||
mismatch (closes: #412899).
|
||||
* dbclient uses static "Password:" prompt instead of using the server's
|
||||
prompt (closes: #394996).
|
||||
* debian/control: Suggests: openssh-client, not ssh (closes: #405686);
|
||||
Standards-Version: 3.7.2.2.
|
||||
* debian/README.Debian: ssh -> openssh-server, openssh-client; remove
|
||||
'Replacing OpenSSH "sshd" with Dropbear' part, this is simply done by not
|
||||
installing the openssh-server package.
|
||||
* debian/README.runit: runsvstat -> sv status.
|
||||
|
||||
-- Gerrit Pape <pape@smarden.org> Fri, 2 Mar 2007 20:48:18 +0000
|
||||
|
||||
dropbear (0.48.1-1) unstable; urgency=medium
|
||||
|
||||
* 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> Mon, 7 March 2005 00:44:54 +0800
|
||||
-- Matt Johnston <matt@ucc.asn.au> Fri, 8 July 2005 21:32:55 +0800
|
||||
|
||||
dropbear (0.44+final-1) unstable; urgency=high
|
||||
dropbear (0.45-3) unstable; urgency=low
|
||||
|
||||
* New upstream release, various fixes.
|
||||
* 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.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Mon, 3 January 2005 00:44:54 +0800
|
||||
-- Gerrit Pape <pape@smarden.org> Wed, 25 May 2005 22:38:17 +0000
|
||||
|
||||
dropbear (0.44test4-1) unstable; urgency=medium
|
||||
dropbear (0.45-2) unstable; urgency=low
|
||||
|
||||
* New upstream beta, various useful fixes.
|
||||
* Matt Johnston:
|
||||
* New upstream release, various fixes.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Tues, 14 September 2004 21:20:00 +0800
|
||||
-- Gerrit Pape <pape@smarden.org> Sat, 12 Mar 2005 15:17:55 +0000
|
||||
|
||||
dropbear (0.44test3-1) unstable; urgency=medium
|
||||
dropbear (0.44-1) unstable; urgency=low
|
||||
|
||||
* New upstream beta, various useful fixes.
|
||||
* 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.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Fri, 27 August 2004 22:20:00 +0800
|
||||
-- Gerrit Pape <pape@smarden.org> Sat, 8 Jan 2005 22:50:43 +0000
|
||||
|
||||
dropbear (0.44test2-1) unstable; urgency=low
|
||||
dropbear (0.43-2) unstable; urgency=high
|
||||
|
||||
* New upstream beta, various minor fixes.
|
||||
* 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.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Tues, 17 August 2004 19:00:00 +0800
|
||||
|
||||
dropbear (0.44test1-1) unstable; urgency=low
|
||||
|
||||
* Upstream beta 0.44test1
|
||||
* Huge changes to allow client functionality
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Sat, 14 August 2004 23:00:00 +0800
|
||||
|
||||
dropbear (0.43-1) unstable; urgency=high
|
||||
|
||||
* 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)
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Fri, 16 July 2004 17:44:54 +0800
|
||||
-- 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
|
||||
* 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
|
||||
|
||||
|
||||
12
debian/control
vendored
12
debian/control
vendored
@@ -3,16 +3,16 @@ Section: net
|
||||
Priority: optional
|
||||
Maintainer: Gerrit Pape <pape@smarden.org>
|
||||
Build-Depends: libz-dev
|
||||
Standards-Version: 3.6.1.0
|
||||
Standards-Version: 3.7.3.0
|
||||
|
||||
Package: dropbear
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}
|
||||
Suggests: ssh, runit
|
||||
Description: lightweight SSH2 server
|
||||
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.
|
||||
Suggests: openssh-client, runit
|
||||
Description: lightweight SSH2 server and client
|
||||
dropbear is a SSH 2 server and client designed to be small enough to
|
||||
be used in small memory environments, while still being functional and
|
||||
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.
|
||||
|
||||
44
debian/dropbear.README.Debian
vendored
44
debian/dropbear.README.Debian
vendored
@@ -1,41 +1,19 @@
|
||||
Dropbear for Debian
|
||||
-------------------
|
||||
|
||||
This package will attempt to listen on port 22. If the OpenSSH
|
||||
package ("ssh") is installed, the file /etc/default/dropbear
|
||||
will be set up so that the server does not start by default.
|
||||
This package will attempt to setup the Dropbear ssh server to listen on
|
||||
port 22. If the OpenSSH server package ("openssh-server") is installed,
|
||||
the file /etc/default/dropbear will be set up so that the server does not
|
||||
start by default.
|
||||
|
||||
You can run Dropbear concurrently with OpenSSH 'sshd' by
|
||||
modifying /etc/default/dropbear so that "NO_START" is set to
|
||||
"0" and changing the port number that Dropbear runs on. Follow
|
||||
the instructions in the file.
|
||||
You can run Dropbear concurrently with OpenSSH 'sshd' by modifying
|
||||
/etc/default/dropbear so that "NO_START" is set to "0", and changing the
|
||||
port number that Dropbear runs on. Follow the instructions in the file.
|
||||
|
||||
This package suggests you install the "ssh" package. This package
|
||||
provides the "ssh" client program, as well as the "/usr/bin/scp"
|
||||
binary you will need to be able to retrieve files from a server
|
||||
running Dropbear via SCP.
|
||||
|
||||
Replacing OpenSSH "sshd" with Dropbear
|
||||
--------------------------------------
|
||||
|
||||
You will still want to have the "ssh" package installed, as it
|
||||
provides the "ssh" and "scp" binaries. When you install this
|
||||
package, it checks for existing OpenSSH host keys and if found,
|
||||
converts them to the Dropbear format.
|
||||
|
||||
If this appears to have worked, you should be able to change over
|
||||
by following these steps:
|
||||
|
||||
1. Stop the OpenSSH server
|
||||
% /etc/init.d/ssh stop
|
||||
2. Prevent the OpenSSH server from starting in the future
|
||||
% touch /etc/ssh/sshd_not_to_be_run
|
||||
3. Modify the Dropbear defaults file, set NO_START to 0 and
|
||||
ensure DROPBEAR_PORT is set to 22.
|
||||
% editor /etc/default/dropbear
|
||||
4. Restart the Dropbear server.
|
||||
% /etc/init.d/dropbear restart
|
||||
This package suggests you install the "openssh-client" package, which
|
||||
provides the "ssh" client program, as well as the "/usr/bin/scp" binary
|
||||
you will need to be able to retrieve files via SCP from a server running
|
||||
Dropbear.
|
||||
|
||||
See the Dropbear homepage for more information:
|
||||
http://matt.ucc.asn.au/dropbear/dropbear.html
|
||||
|
||||
|
||||
2
debian/dropbear.docs
vendored
2
debian/dropbear.docs
vendored
@@ -1,3 +1,3 @@
|
||||
README
|
||||
TODO
|
||||
debian/README.runit
|
||||
debian/README.Debian.diet
|
||||
|
||||
23
debian/dropbear.init
vendored
23
debian/dropbear.init
vendored
@@ -1,4 +1,12 @@
|
||||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: dropbear
|
||||
# Required-Start: $remote_fs $syslog
|
||||
# Required-Stop: $remote_fs $syslog
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Dropbear SSH server
|
||||
### END INIT INFO
|
||||
#
|
||||
# Do not configure this file. Edit /etc/default/dropbear instead!
|
||||
#
|
||||
@@ -14,10 +22,11 @@ NO_START=0
|
||||
|
||||
set -e
|
||||
|
||||
cancel() { echo "$1" >&2; exit 0; };
|
||||
test ! -r /etc/default/dropbear || . /etc/default/dropbear
|
||||
test "$NO_START" = "0" || exit 0
|
||||
test -x "$DAEMON" || exit 0
|
||||
test ! -h /var/service/dropbear || exit 0
|
||||
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"
|
||||
@@ -25,13 +34,16 @@ 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 'NO_START is not set to zero.'
|
||||
echo -n "Starting $DESC: "
|
||||
start-stop-daemon --start --quiet --pidfile /var/run/"$NAME".pid \
|
||||
--exec "$DAEMON" -- -d "$DROPBEAR_DSSKEY" -r "$DROPBEAR_RSAKEY" \
|
||||
-p "$DROPBEAR_PORT" $DROPBEAR_EXTRA_ARGS
|
||||
-p "$DROPBEAR_PORT" -W "$DROPBEAR_RECEIVE_WINDOW" $DROPBEAR_EXTRA_ARGS
|
||||
echo "$NAME."
|
||||
;;
|
||||
stop)
|
||||
@@ -40,12 +52,13 @@ case "$1" in
|
||||
echo "$NAME."
|
||||
;;
|
||||
restart|force-reload)
|
||||
test "$NO_START" = "0" || cancel 'NO_START is not set to zero.'
|
||||
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" $DROPBEAR_EXTRA_ARGS
|
||||
-p "$DROPBEAR_PORT" -W "$DROPBEAR_RECEIVE_WINDOW" $DROPBEAR_EXTRA_ARGS
|
||||
echo "$NAME."
|
||||
;;
|
||||
*)
|
||||
|
||||
17
debian/dropbear.postinst
vendored
17
debian/dropbear.postinst
vendored
@@ -2,7 +2,6 @@
|
||||
set -e
|
||||
|
||||
test "$1" = 'configure' || exit 0
|
||||
test -n "$2" || chown log /etc/dropbear/log/main || true
|
||||
|
||||
if test ! -e /etc/dropbear/dropbear_rsa_host_key; then
|
||||
if test -f /etc/ssh/ssh_host_rsa_key; then
|
||||
@@ -55,14 +54,26 @@ DROPBEAR_BANNER=""
|
||||
|
||||
# DSS hostkey file (default: /etc/dropbear/dropbear_dss_host_key)
|
||||
#DROPBEAR_DSSKEY="/etc/dropbear/dropbear_dss_host_key"
|
||||
|
||||
# Receive window size - this is a tradeoff between memory and
|
||||
# network performance
|
||||
DROPBEAR_RECEIVE_WINDOW=65536
|
||||
EOT
|
||||
fi
|
||||
|
||||
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 start
|
||||
invoke-rc.d dropbear restart
|
||||
else
|
||||
/etc/init.d/dropbear start
|
||||
/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
|
||||
|
||||
2
debian/dropbear.prerm
vendored
2
debian/dropbear.prerm
vendored
@@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
set -u
|
||||
set -e
|
||||
|
||||
test "$1" = 'remove' || test "$1" = 'deconfigure' || exit 0
|
||||
if test -x /etc/init.d/dropbear; then
|
||||
|
||||
20
debian/implicit
vendored
20
debian/implicit
vendored
@@ -1,4 +1,4 @@
|
||||
# $Id: implicit,v 1.1 2004/06/16 05:08:32 matt Exp $
|
||||
# $Id: implicit,v 1.11 2005/11/29 21:57:55 pape Exp $
|
||||
|
||||
.PHONY: deb-checkdir deb-checkuid
|
||||
|
||||
@@ -12,6 +12,10 @@ deb-checkuid:
|
||||
$*.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'
|
||||
@@ -29,9 +33,19 @@ deb-checkuid:
|
||||
@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 || \
|
||||
@@ -58,13 +72,13 @@ deb-checkuid:
|
||||
@rm -rf debian/$*/DEBIAN
|
||||
: debian/$*/DEBIAN/
|
||||
@install -d -m0755 debian/$*/DEBIAN
|
||||
@for i in conffiles shlibs; do \
|
||||
@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; do \
|
||||
@for i in preinst prerm postinst postrm config; do \
|
||||
test ! -r debian/$*.$$i || \
|
||||
sh -cx "install -m0755 debian/$*.$$i debian/$*/DEBIAN/$$i" \
|
||||
|| exit 1; \
|
||||
|
||||
104
debian/rules
vendored
104
debian/rules
vendored
@@ -1,5 +1,9 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
DPKG_EXPORT_BUILDFLAGS = 1
|
||||
include /usr/share/dpkg/buildflags.mk
|
||||
|
||||
#export DH_OPTIONS
|
||||
DEB_HOST_GNU_TYPE ?=$(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
|
||||
DEB_BUILD_GNU_TYPE ?=$(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
|
||||
@@ -9,86 +13,88 @@ ifneq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||
STRIP =: nostrip
|
||||
endif
|
||||
|
||||
CFLAGS =-Wall -g
|
||||
ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
|
||||
CFLAGS +=-O0
|
||||
else
|
||||
CFLAGS +=-O2
|
||||
endif
|
||||
|
||||
CONFFLAGS =
|
||||
CC =gcc
|
||||
ifneq (,$(findstring diet,$(DEB_BUILD_OPTIONS)))
|
||||
CC =diet -v -Os gcc
|
||||
CONFFLAGS =--disable-zlib
|
||||
CC =diet -v -Os gcc -nostdinc
|
||||
endif
|
||||
|
||||
DIR=`pwd`/debian/dropbear
|
||||
DIR =$(shell pwd)/debian/dropbear
|
||||
|
||||
patch: deb-checkdir patch-stamp
|
||||
patch-stamp:
|
||||
# no patches for now
|
||||
# for i in debian/diff/*.diff; do patch -p0 <$$i || exit 1; done
|
||||
for i in `ls -1 debian/diff/*.diff || :`; do \
|
||||
patch -p1 <$$i || exit 1; \
|
||||
done
|
||||
touch patch-stamp
|
||||
|
||||
config.status: patch-stamp configure
|
||||
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
|
||||
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)
|
||||
|
||||
build: deb-checkdir build-stamp
|
||||
build-stamp: config.status
|
||||
$(MAKE) CC="$(CC)" LD="$(CC)"
|
||||
$(MAKE) CC='$(CC)' LD='$(CC)'
|
||||
touch build-stamp
|
||||
|
||||
clean: deb-checkdir deb-checkuid
|
||||
-$(MAKE) distclean
|
||||
# test ! -e patch-stamp || \
|
||||
# for i in debian/diff/*.diff; do patch -p0 -R <$$i; done
|
||||
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)'
|
||||
rm -f debian/files debian/substvars debian/copyright changelog
|
||||
|
||||
install: deb-checkdir deb-checkuid build-stamp
|
||||
rm -rf "$(DIR)"
|
||||
install -d -m0755 "$(DIR)"/etc/dropbear
|
||||
rm -rf '$(DIR)'
|
||||
install -d -m0755 '$(DIR)'/etc/dropbear
|
||||
# programs
|
||||
install -d -m0755 "$(DIR)"/usr/sbin
|
||||
install -m0755 dropbear "$(DIR)"/usr/sbin/dropbear
|
||||
install -d -m0755 "$(DIR)"/usr/bin
|
||||
install -m0755 dbclient "$(DIR)"/usr/bin/dbclient
|
||||
install -m0755 dropbearkey "$(DIR)"/usr/bin/dropbearkey
|
||||
install -d -m0755 "$(DIR)"/usr/lib/dropbear
|
||||
install -d -m0755 '$(DIR)'/usr/sbin
|
||||
install -m0755 dropbear '$(DIR)'/usr/sbin/dropbear
|
||||
install -d -m0755 '$(DIR)'/usr/bin
|
||||
install -m0755 dbclient '$(DIR)'/usr/bin/dbclient
|
||||
install -m0755 dropbearkey '$(DIR)'/usr/bin/dropbearkey
|
||||
install -d -m0755 '$(DIR)'/usr/lib/dropbear
|
||||
install -m0755 dropbearconvert \
|
||||
"$(DIR)"/usr/lib/dropbear/dropbearconvert
|
||||
$(STRIP) -R .comment -R .note "$(DIR)"/usr/sbin/* \
|
||||
"$(DIR)"/usr/bin/* "$(DIR)"/usr/lib/dropbear/*
|
||||
'$(DIR)'/usr/lib/dropbear/dropbearconvert
|
||||
$(STRIP) -R .comment -R .note '$(DIR)'/usr/sbin/* \
|
||||
'$(DIR)'/usr/bin/* '$(DIR)'/usr/lib/dropbear/*
|
||||
# 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
|
||||
ln -s /var/run/dropbear "$(DIR)"/etc/dropbear/supervise
|
||||
ln -s /var/run/dropbear.log "$(DIR)"/etc/dropbear/log/supervise
|
||||
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
|
||||
# man pages
|
||||
install -d -m0755 "$(DIR)"/usr/share/man/man8
|
||||
for i in dropbear.8 dropbearkey.8; do \
|
||||
install -m644 $$i "$(DIR)"/usr/share/man/man8/ || exit 1; \
|
||||
install -d -m0755 '$(DIR)'/usr/share/man/man8
|
||||
install -d -m0755 '$(DIR)'/usr/share/man/man1
|
||||
install -m644 dropbear.8 '$(DIR)'/usr/share/man/man8/
|
||||
for i in dbclient.1 dropbearkey.1 dropbearconvert.1; do \
|
||||
install -m644 $$i '$(DIR)'/usr/share/man/man1/ || exit 1; \
|
||||
done
|
||||
gzip -9 "$(DIR)"/usr/share/man/man8/*.8
|
||||
gzip -9 '$(DIR)'/usr/share/man/man8/*.8
|
||||
gzip -9 '$(DIR)'/usr/share/man/man1/*.1
|
||||
# copyright, changelog
|
||||
cat debian/copyright.in LICENSE >debian/copyright
|
||||
ln -s CHANGES changelog
|
||||
test -r changelog || ln -s CHANGES changelog
|
||||
|
||||
binary-indep:
|
||||
|
||||
binary-arch: install dropbear.deb
|
||||
test "$(CC)" != 'gcc' || \
|
||||
dpkg-shlibdeps "$(DIR)"/usr/sbin/* "$(DIR)"/usr/bin/* \
|
||||
"$(DIR)"/usr/lib/dropbear/*
|
||||
dpkg-gencontrol -isp -pdropbear -P"$(DIR)"
|
||||
dpkg -b "$(DIR)" ..
|
||||
test '$(CC)' != 'gcc' || \
|
||||
dpkg-shlibdeps '$(DIR)'/usr/sbin/* '$(DIR)'/usr/bin/* \
|
||||
'$(DIR)'/usr/lib/dropbear/*
|
||||
dpkg-gencontrol -isp -pdropbear -P'$(DIR)'
|
||||
dpkg -b '$(DIR)' ..
|
||||
|
||||
binary: binary-arch binary-indep
|
||||
|
||||
|
||||
72
debug.h
72
debug.h
@@ -22,8 +22,8 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#ifndef _DEBUG_H_
|
||||
#define _DEBUG_H_
|
||||
#ifndef DROPBEAR_DEBUG_H_
|
||||
#define DROPBEAR_DEBUG_H_
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
@@ -33,37 +33,65 @@
|
||||
* 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() assert(ses.writepayload->len == 0 && \
|
||||
ses.writepayload->pos == 0)*/
|
||||
|
||||
/* 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*/
|
||||
#ifndef CHECKCLEARTOWRITE
|
||||
#define CHECKCLEARTOWRITE()
|
||||
#endif
|
||||
|
||||
/* 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*/
|
||||
/* The level of TRACE() statements */
|
||||
#define DROPBEAR_VERBOSE_LEVEL 4
|
||||
|
||||
#if DEBUG_TRACE
|
||||
extern int debug_trace;
|
||||
#endif
|
||||
|
||||
/* Enable debug trace levels.
|
||||
We can't use __VA_ARGS_ here because Dropbear supports
|
||||
old ~C89 compilers */
|
||||
/* Default is to discard output ... */
|
||||
#define DEBUG1(X)
|
||||
#define DEBUG2(X)
|
||||
#define DEBUG3(X)
|
||||
#define TRACE(X)
|
||||
#endif /*DEBUG_TRACE*/
|
||||
#define TRACE2(X)
|
||||
/* ... unless DEBUG_TRACE is high enough */
|
||||
#if (DEBUG_TRACE>=1)
|
||||
#undef DEBUG1
|
||||
#define DEBUG1(X) dropbear_trace1 X;
|
||||
#endif
|
||||
#if (DEBUG_TRACE>=2)
|
||||
#undef DEBUG2
|
||||
#define DEBUG2(X) dropbear_trace2 X;
|
||||
#endif
|
||||
#if (DEBUG_TRACE>=3)
|
||||
#undef DEBUG3
|
||||
#define DEBUG3(X) dropbear_trace3 X;
|
||||
#endif
|
||||
#if (DEBUG_TRACE>=4)
|
||||
#undef TRACE
|
||||
#define TRACE(X) dropbear_trace4 X;
|
||||
#endif
|
||||
#if (DEBUG_TRACE>=5)
|
||||
#undef TRACE2
|
||||
#define TRACE2(X) dropbear_trace5 X;
|
||||
#endif
|
||||
|
||||
/* To debug with GDB it is easier to run with no forking of child processes.
|
||||
You will need to pass "-F" as well. */
|
||||
#ifndef DEBUG_NOFORK
|
||||
#define DEBUG_NOFORK 0
|
||||
#endif
|
||||
|
||||
|
||||
/* 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
|
||||
|
||||
357
default_options.h
Normal file
357
default_options.h
Normal file
@@ -0,0 +1,357 @@
|
||||
#ifndef DROPBEAR_DEFAULT_OPTIONS_H_
|
||||
#define DROPBEAR_DEFAULT_OPTIONS_H_
|
||||
/*
|
||||
> > > Read This < < <
|
||||
|
||||
default_options.h documents compile-time options, and provides default values.
|
||||
|
||||
Local customisation should be added to localoptions.h which is
|
||||
used if it exists in the build directory. Options defined there will override
|
||||
any options in this file.
|
||||
|
||||
Options can also be defined with -DDROPBEAR_XXX=[0,1] in Makefile CFLAGS
|
||||
|
||||
IMPORTANT: Some options will require "make clean" after changes */
|
||||
|
||||
#define DROPBEAR_DEFPORT "22"
|
||||
|
||||
/* Listen on all interfaces */
|
||||
#define DROPBEAR_DEFADDRESS ""
|
||||
|
||||
/* Default hostkey paths - these can be specified on the command line.
|
||||
* Homedir is prepended if path begins with ~/
|
||||
*/
|
||||
#define DSS_PRIV_FILENAME "/etc/dropbear/dropbear_dss_host_key"
|
||||
#define RSA_PRIV_FILENAME "/etc/dropbear/dropbear_rsa_host_key"
|
||||
#define ECDSA_PRIV_FILENAME "/etc/dropbear/dropbear_ecdsa_host_key"
|
||||
#define ED25519_PRIV_FILENAME "/etc/dropbear/dropbear_ed25519_host_key"
|
||||
|
||||
/* Set NON_INETD_MODE if you require daemon functionality (ie Dropbear listens
|
||||
* on chosen ports and keeps accepting connections. This is the default.
|
||||
*
|
||||
* Set INETD_MODE if you want to be able to run Dropbear with inetd (or
|
||||
* similar), where it will use stdin/stdout for connections, and each process
|
||||
* lasts for a single connection. Dropbear should be invoked with the -i flag
|
||||
* for inetd, and can only accept IPv4 connections.
|
||||
*
|
||||
* Both of these flags can be defined at once, don't compile without at least
|
||||
* one of them. */
|
||||
#define NON_INETD_MODE 1
|
||||
#define INETD_MODE 1
|
||||
|
||||
/* By default Dropbear will re-execute itself for each incoming connection so
|
||||
that memory layout may be re-randomised (ASLR) - exploiting
|
||||
vulnerabilities becomes harder. Re-exec causes slightly more memory use
|
||||
per connection.
|
||||
This option is ignored on non-Linux platforms at present */
|
||||
#define DROPBEAR_REEXEC 1
|
||||
|
||||
/* Include verbose debug output, enabled with -v at runtime (repeat to increase).
|
||||
* define which level of debug output you compile in
|
||||
* TRACE1 - TRACE3 = approx 4 Kb (connection, remote identity, algos, auth type info)
|
||||
* TRACE4 = approx 17 Kb (detailed before connection)
|
||||
* TRACE5 = approx 8 Kb (detailed after connection) */
|
||||
#define DEBUG_TRACE 0
|
||||
|
||||
/* Set this if you want to use the DROPBEAR_SMALL_CODE option. This can save
|
||||
* several kB in binary size however will make the symmetrical ciphers and hashes
|
||||
* slower, perhaps by 50%. Recommended for small systems that aren't doing
|
||||
* much traffic. */
|
||||
#define DROPBEAR_SMALL_CODE 1
|
||||
|
||||
/* Enable X11 Forwarding - server only */
|
||||
#define DROPBEAR_X11FWD 0
|
||||
|
||||
/* Enable TCP Fowarding */
|
||||
/* 'Local' is "-L" style (client listening port forwarded via server)
|
||||
* 'Remote' is "-R" style (server listening port forwarded via client) */
|
||||
#define DROPBEAR_CLI_LOCALTCPFWD 1
|
||||
#define DROPBEAR_CLI_REMOTETCPFWD 1
|
||||
|
||||
#define DROPBEAR_SVR_LOCALTCPFWD 1
|
||||
#define DROPBEAR_SVR_REMOTETCPFWD 1
|
||||
|
||||
/* Enable Authentication Agent Forwarding */
|
||||
#define DROPBEAR_SVR_AGENTFWD 1
|
||||
#define DROPBEAR_CLI_AGENTFWD 1
|
||||
|
||||
/* Note: Both DROPBEAR_CLI_PROXYCMD and DROPBEAR_CLI_NETCAT must be set to
|
||||
* allow multihop dbclient connections */
|
||||
|
||||
/* Allow using -J <proxycommand> to run the connection through a
|
||||
pipe to a program, rather the normal TCP connection */
|
||||
#define DROPBEAR_CLI_PROXYCMD 1
|
||||
|
||||
/* Enable "Netcat mode" option. This will forward standard input/output
|
||||
* to a remote TCP-forwarded connection */
|
||||
#define DROPBEAR_CLI_NETCAT 1
|
||||
|
||||
/* Whether to support "-c" and "-m" flags to choose ciphers/MACs at runtime */
|
||||
#define DROPBEAR_USER_ALGO_LIST 1
|
||||
|
||||
/* Encryption - at least one required.
|
||||
* AES128 should be enabled, some very old implementations might only
|
||||
* support 3DES.
|
||||
* Including both AES keysize variants (128 and 256) will result in
|
||||
* a minimal size increase */
|
||||
#define DROPBEAR_AES128 1
|
||||
#define DROPBEAR_AES256 1
|
||||
#define DROPBEAR_3DES 0
|
||||
|
||||
/* Enable Chacha20-Poly1305 authenticated encryption mode. This is
|
||||
* generally faster than AES256 on CPU w/o dedicated AES instructions,
|
||||
* having the same key size. Recommended.
|
||||
* Compiling in will add ~5,5kB to binary size on x86-64 */
|
||||
#define DROPBEAR_CHACHA20POLY1305 1
|
||||
|
||||
/* Enable "Counter Mode" for ciphers. Recommended. */
|
||||
#define DROPBEAR_ENABLE_CTR_MODE 1
|
||||
|
||||
/* Enable CBC mode for ciphers. This has security issues though
|
||||
may be required for compatibility with old implementations */
|
||||
#define DROPBEAR_ENABLE_CBC_MODE 0
|
||||
|
||||
/* Enable "Galois/Counter Mode" for ciphers. This authenticated
|
||||
* encryption mode is combination of CTR mode and GHASH. Recommended
|
||||
* for security and forwards compatibility, but slower than CTR on
|
||||
* CPU w/o dedicated AES/GHASH instructions.
|
||||
* Compiling in will add ~6kB to binary size on x86-64 */
|
||||
#define DROPBEAR_ENABLE_GCM_MODE 0
|
||||
|
||||
/* Message integrity. sha2-256 is recommended as a default,
|
||||
sha1 for compatibility */
|
||||
#define DROPBEAR_SHA1_HMAC 1
|
||||
#define DROPBEAR_SHA2_256_HMAC 1
|
||||
#define DROPBEAR_SHA2_512_HMAC 0
|
||||
#define DROPBEAR_SHA1_96_HMAC 0
|
||||
|
||||
/* Hostkey/public key algorithms - at least one required, these are used
|
||||
* for hostkey as well as for verifying signatures with pubkey auth.
|
||||
* RSA is recommended.
|
||||
*
|
||||
* See: RSA_PRIV_FILENAME and DSS_PRIV_FILENAME */
|
||||
#define DROPBEAR_RSA 1
|
||||
/* Newer SSH implementations use SHA256 for RSA signatures. SHA1
|
||||
* support is required to communicate with some older implementations.
|
||||
* It will be removed in future due to SHA1 insecurity, it can be
|
||||
* disabled with DROPBEAR_RSA_SHA1 set to 0 */
|
||||
#define DROPBEAR_RSA_SHA1 1
|
||||
|
||||
/* DSS may be necessary to connect to some systems but is not
|
||||
* recommended for new keys (1024 bits is small, and it uses SHA1).
|
||||
* RSA key generation will be faster with bundled libtommath
|
||||
* if DROPBEAR_DSS is disabled.
|
||||
* https://github.com/mkj/dropbear/issues/174#issuecomment-1267374858 */
|
||||
#define DROPBEAR_DSS 0
|
||||
/* ECDSA is significantly faster than RSA or DSS. Compiling in ECC
|
||||
* code (either ECDSA or ECDH) increases binary size - around 30kB
|
||||
* on x86-64.
|
||||
* See: ECDSA_PRIV_FILENAME */
|
||||
#define DROPBEAR_ECDSA 1
|
||||
|
||||
/* Ed25519 is faster than ECDSA. Compiling in Ed25519 code increases
|
||||
* binary size - around 7,5kB on x86-64.
|
||||
* See: ED25519_PRIV_FILENAME */
|
||||
#define DROPBEAR_ED25519 1
|
||||
|
||||
/* Allow U2F security keys for public key auth, with
|
||||
* sk-ecdsa-sha2-nistp256@openssh.com or sk-ssh-ed25519@openssh.com keys.
|
||||
* The corresponding DROPBEAR_ECDSA or DROPBEAR_ED25519 also needs to be set.
|
||||
* This is currently server-only. */
|
||||
#define DROPBEAR_SK_KEYS 1
|
||||
|
||||
/* RSA must be >=1024 */
|
||||
#define DROPBEAR_DEFAULT_RSA_SIZE 2048
|
||||
/* DSS is always 1024 */
|
||||
/* ECDSA defaults to largest size configured, usually 521 */
|
||||
/* Ed25519 is always 256 */
|
||||
|
||||
/* Add runtime flag "-R" to generate hostkeys as-needed when the first
|
||||
connection using that key type occurs.
|
||||
This avoids the need to otherwise run "dropbearkey" and avoids some problems
|
||||
with badly seeded /dev/urandom when systems first boot. */
|
||||
#define DROPBEAR_DELAY_HOSTKEY 1
|
||||
|
||||
|
||||
/* Key exchange algorithm.
|
||||
|
||||
* group14_sha1 - 2048 bit, sha1
|
||||
* group14_sha256 - 2048 bit, sha2-256
|
||||
* group16 - 4096 bit, sha2-512
|
||||
* group1 - 1024 bit, sha1
|
||||
* curve25519 - elliptic curve DH
|
||||
* ecdh - NIST elliptic curve DH (256, 384, 521)
|
||||
*
|
||||
* group1 is too small for security though is necessary if you need
|
||||
compatibility with some implementations such as Dropbear versions < 0.53
|
||||
* group14 is supported by most implementations.
|
||||
* group16 provides a greater strength level but is slower and increases binary size
|
||||
* curve25519 and ecdh algorithms are faster than non-elliptic curve methods
|
||||
* curve25519 increases binary size by ~2,5kB on x86-64
|
||||
* including either ECDH or ECDSA increases binary size by ~30kB on x86-64
|
||||
|
||||
* Small systems should generally include either curve25519 or ecdh for performance.
|
||||
* curve25519 is less widely supported but is faster
|
||||
*/
|
||||
#define DROPBEAR_DH_GROUP14_SHA1 1
|
||||
#define DROPBEAR_DH_GROUP14_SHA256 1
|
||||
#define DROPBEAR_DH_GROUP16 0
|
||||
#define DROPBEAR_CURVE25519 1
|
||||
#define DROPBEAR_ECDH 1
|
||||
#define DROPBEAR_DH_GROUP1 0
|
||||
|
||||
/* When group1 is enabled it will only be allowed by Dropbear client
|
||||
not as a server, due to concerns over its strength. Set to 0 to allow
|
||||
group1 in Dropbear server too */
|
||||
#define DROPBEAR_DH_GROUP1_CLIENTONLY 1
|
||||
|
||||
/* Control the memory/performance/compression tradeoff for zlib.
|
||||
* Set windowBits=8 for least memory usage, see your system's
|
||||
* zlib.h for full details.
|
||||
* Default settings (windowBits=15) will use 256kB for compression
|
||||
* windowBits=8 will use 129kB for compression.
|
||||
* Both modes will use ~35kB for decompression (using windowBits=15 for
|
||||
* interoperability) */
|
||||
#define DROPBEAR_ZLIB_WINDOW_BITS 15
|
||||
|
||||
/* Whether to do reverse DNS lookups. */
|
||||
#define DO_HOST_LOOKUP 0
|
||||
|
||||
/* Whether to print the message of the day (MOTD). */
|
||||
#define DO_MOTD 1
|
||||
#define MOTD_FILENAME "/etc/motd"
|
||||
|
||||
/* Authentication Types - at least one required.
|
||||
RFC Draft requires pubkey auth, and recommends password */
|
||||
#define DROPBEAR_SVR_PASSWORD_AUTH 1
|
||||
|
||||
/* Note: PAM auth is quite simple and only works for PAM modules which just do
|
||||
* a simple "Login: " "Password: " (you can edit the strings in svr-authpam.c).
|
||||
* It's useful for systems like OS X where standard password crypts don't work
|
||||
* but there's an interface via a PAM module. It won't work for more complex
|
||||
* PAM challenge/response.
|
||||
* You can't enable both PASSWORD and PAM. */
|
||||
#define DROPBEAR_SVR_PAM_AUTH 0
|
||||
|
||||
/* ~/.ssh/authorized_keys authentication.
|
||||
* You must define DROPBEAR_SVR_PUBKEY_AUTH in order to use plugins. */
|
||||
#define DROPBEAR_SVR_PUBKEY_AUTH 1
|
||||
|
||||
/* Whether to take public key options in
|
||||
* authorized_keys file into account */
|
||||
#define DROPBEAR_SVR_PUBKEY_OPTIONS 1
|
||||
|
||||
/* Set this to 0 if your system does not have multiple user support.
|
||||
(Linux kernel CONFIG_MULTIUSER option)
|
||||
The resulting binary will not run on a normal system. */
|
||||
#define DROPBEAR_SVR_MULTIUSER 1
|
||||
|
||||
/* Client authentication options */
|
||||
#define DROPBEAR_CLI_PASSWORD_AUTH 1
|
||||
#define DROPBEAR_CLI_PUBKEY_AUTH 1
|
||||
|
||||
/* A default argument for dbclient -i <privatekey>.
|
||||
* Homedir is prepended if path begins with ~/
|
||||
*/
|
||||
#define DROPBEAR_DEFAULT_CLI_AUTHKEY "~/.ssh/id_dropbear"
|
||||
|
||||
/* Allow specifying the password for dbclient via the DROPBEAR_PASSWORD
|
||||
* environment variable. */
|
||||
#define DROPBEAR_USE_PASSWORD_ENV 1
|
||||
|
||||
/* Define this (as well as DROPBEAR_CLI_PASSWORD_AUTH) to allow the use of
|
||||
* a helper program for the ssh client. The helper program should be
|
||||
* specified in the SSH_ASKPASS environment variable, and dbclient
|
||||
* should be run with DISPLAY set and no tty. The program should
|
||||
* return the password on standard output */
|
||||
#define DROPBEAR_CLI_ASKPASS_HELPER 0
|
||||
|
||||
/* Save a network roundtrip by sendng a real auth request immediately after
|
||||
* sending a query for the available methods. This is not yet enabled by default
|
||||
since it could cause problems with non-compliant servers */
|
||||
#define DROPBEAR_CLI_IMMEDIATE_AUTH 0
|
||||
|
||||
/* Set this to use PRNGD or EGD instead of /dev/urandom */
|
||||
#define DROPBEAR_USE_PRNGD 0
|
||||
#define DROPBEAR_PRNGD_SOCKET "/var/run/dropbear-rng"
|
||||
|
||||
/* Specify the number of clients we will allow to be connected but
|
||||
* not yet authenticated. After this limit, connections are rejected */
|
||||
/* The first setting is per-IP, to avoid denial of service */
|
||||
#define MAX_UNAUTH_PER_IP 5
|
||||
|
||||
/* And then a global limit to avoid chewing memory if connections
|
||||
* come from many IPs */
|
||||
#define MAX_UNAUTH_CLIENTS 30
|
||||
|
||||
/* Default maximum number of failed authentication tries (server option) */
|
||||
/* -T server option overrides */
|
||||
#define MAX_AUTH_TRIES 10
|
||||
|
||||
/* Delay introduced before closing an unauthenticated session (seconds).
|
||||
Disabled by default, can be set to say 30 seconds to reduce the speed
|
||||
of password brute forcing. Note that there is a risk of denial of
|
||||
service by setting this */
|
||||
#define UNAUTH_CLOSE_DELAY 0
|
||||
|
||||
/* The default file to store the daemon's process ID, for shutdown
|
||||
* scripts etc. This can be overridden with the -P flag.
|
||||
* Homedir is prepended if path begins with ~/
|
||||
*/
|
||||
#define DROPBEAR_PIDFILE "/var/run/dropbear.pid"
|
||||
|
||||
/* The command to invoke for xauth when using X11 forwarding.
|
||||
* "-q" for quiet */
|
||||
#define XAUTH_COMMAND "/usr/bin/xauth -q"
|
||||
|
||||
|
||||
/* If you want to enable running an sftp server (such as the one included with
|
||||
* OpenSSH), set the path below and set DROPBEAR_SFTPSERVER.
|
||||
* The sftp-server program is not provided by Dropbear itself.
|
||||
* Homedir is prepended if path begins with ~/
|
||||
*/
|
||||
#define DROPBEAR_SFTPSERVER 1
|
||||
#define SFTPSERVER_PATH "/usr/libexec/sftp-server"
|
||||
|
||||
/* This is used by the scp binary when used as a client binary. If you're
|
||||
* not using the Dropbear client, you'll need to change it */
|
||||
#define DROPBEAR_PATH_SSH_PROGRAM "/usr/bin/dbclient"
|
||||
|
||||
/* Whether to log commands executed by a client. This only logs the
|
||||
* (single) command sent to the server, not what a user did in a
|
||||
* shell/sftp session etc. */
|
||||
#define LOG_COMMANDS 0
|
||||
|
||||
/* Window size limits. These tend to be a trade-off between memory
|
||||
usage and network performance: */
|
||||
/* Size of the network receive window. This amount of memory is allocated
|
||||
as a per-channel receive buffer. Increasing this value can make a
|
||||
significant difference to network performance. 24kB was empirically
|
||||
chosen for a 100mbit ethernet network. The value can be altered at
|
||||
runtime with the -W argument. */
|
||||
#define DEFAULT_RECV_WINDOW 24576
|
||||
/* Maximum size of a received SSH data packet - this _MUST_ be >= 32768
|
||||
in order to interoperate with other implementations */
|
||||
#define RECV_MAX_PAYLOAD_LEN 32768
|
||||
/* Maximum size of a transmitted data packet - this can be any value,
|
||||
though increasing it may not make a significant difference. */
|
||||
#define TRANS_MAX_PAYLOAD_LEN 16384
|
||||
|
||||
/* Ensure that data is transmitted every KEEPALIVE seconds. This can
|
||||
be overridden at runtime with -K. 0 disables keepalives */
|
||||
#define DEFAULT_KEEPALIVE 0
|
||||
|
||||
/* If this many KEEPALIVES are sent with no packets received from the
|
||||
other side, exit. Not run-time configurable - if you have a need
|
||||
for runtime configuration please mail the Dropbear list */
|
||||
#define DEFAULT_KEEPALIVE_LIMIT 3
|
||||
|
||||
/* Ensure that data is received within IDLE_TIMEOUT seconds. This can
|
||||
be overridden at runtime with -I. 0 disables idle timeouts */
|
||||
#define DEFAULT_IDLE_TIMEOUT 0
|
||||
|
||||
/* The default path. This will often get replaced by the shell */
|
||||
#define DEFAULT_PATH "/usr/bin:/bin"
|
||||
#define DEFAULT_ROOT_PATH "/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
|
||||
#endif /* DROPBEAR_DEFAULT_OPTIONS_H_ */
|
||||
97
dh_groups.c
Normal file
97
dh_groups.c
Normal file
@@ -0,0 +1,97 @@
|
||||
#include "options.h"
|
||||
#include "dh_groups.h"
|
||||
|
||||
#if DROPBEAR_NORMAL_DH
|
||||
|
||||
#if DROPBEAR_DH_GROUP1
|
||||
/* diffie-hellman-group1-sha1 value for p */
|
||||
const unsigned char dh_p_1[DH_P_1_LEN] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
|
||||
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
||||
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
|
||||
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
||||
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
|
||||
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
||||
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
|
||||
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
|
||||
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
|
||||
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
#endif /* DROPBEAR_DH_GROUP1 */
|
||||
|
||||
#if DROPBEAR_DH_GROUP14
|
||||
/* diffie-hellman-group14-sha1 value for p */
|
||||
const unsigned char dh_p_14[DH_P_14_LEN] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
|
||||
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
||||
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
|
||||
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
||||
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
|
||||
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
||||
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
|
||||
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
|
||||
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
|
||||
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
|
||||
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
|
||||
0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
|
||||
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
|
||||
0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
|
||||
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
|
||||
0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
|
||||
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
|
||||
0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
|
||||
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
|
||||
0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
|
||||
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF};
|
||||
#endif /* DROPBEAR_DH_GROUP14 */
|
||||
|
||||
#if DROPBEAR_DH_GROUP16
|
||||
/* diffie-hellman-group16-256 value for p */
|
||||
const unsigned char dh_p_16[DH_P_16_LEN] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21,
|
||||
0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02,
|
||||
0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B,
|
||||
0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3,
|
||||
0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F,
|
||||
0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E,
|
||||
0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C,
|
||||
0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
|
||||
0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC,
|
||||
0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA,
|
||||
0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF,
|
||||
0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
|
||||
0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67,
|
||||
0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18,
|
||||
0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77,
|
||||
0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
|
||||
0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95,
|
||||
0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2,
|
||||
0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4,
|
||||
0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB,
|
||||
0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A,
|
||||
0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1,
|
||||
0xE4, 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94,
|
||||
0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
|
||||
0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, 0x3E,
|
||||
0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, 0xBB, 0xE1,
|
||||
0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46,
|
||||
0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC,
|
||||
0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A,
|
||||
0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA,
|
||||
0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68,
|
||||
0x34, 0xB6, 0x15, 0x0B, 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
|
||||
0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F,
|
||||
0xBE, 0xCA, 0xA6, 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2,
|
||||
0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7,
|
||||
0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
|
||||
0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, 0x93,
|
||||
0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6,
|
||||
0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
#endif /* DROPBEAR_DH_GROUP16 */
|
||||
|
||||
/* Same for all groups */
|
||||
const int DH_G_VAL = 2;
|
||||
|
||||
#endif /* DROPBEAR_NORMAL_DH */
|
||||
26
dh_groups.h
Normal file
26
dh_groups.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef DROPBEAR_DH_GROUPS_H
|
||||
#define DROPBEAR_DH_GROUPS_H
|
||||
#include "options.h"
|
||||
|
||||
#if DROPBEAR_NORMAL_DH
|
||||
|
||||
#if DROPBEAR_DH_GROUP1
|
||||
#define DH_P_1_LEN 128
|
||||
extern const unsigned char dh_p_1[DH_P_1_LEN];
|
||||
#endif
|
||||
|
||||
#if DROPBEAR_DH_GROUP14
|
||||
#define DH_P_14_LEN 256
|
||||
extern const unsigned char dh_p_14[DH_P_14_LEN];
|
||||
#endif
|
||||
|
||||
#if DROPBEAR_DH_GROUP16
|
||||
#define DH_P_16_LEN 512
|
||||
extern const unsigned char dh_p_16[DH_P_16_LEN];
|
||||
#endif
|
||||
|
||||
extern const int DH_G_VAL;
|
||||
|
||||
#endif /* DROPBEAR_NORMAL_DH */
|
||||
|
||||
#endif
|
||||
199
dropbear.8
199
dropbear.8
@@ -1,17 +1,15 @@
|
||||
.TH dropbear 8
|
||||
.SH NAME
|
||||
dropbear \- lightweight SSH2 server
|
||||
dropbear \- lightweight SSH server
|
||||
.SH SYNOPSIS
|
||||
.B dropbear
|
||||
[\-FEmwsgjki] [\-b
|
||||
.I banner\fR] [\-d
|
||||
.I dsskey\fR] [\-r
|
||||
.I rsakey\fR] [\-p
|
||||
.IR port ]
|
||||
[\fIflag arguments\fR] [\-b
|
||||
.I banner\fR]
|
||||
[\-r
|
||||
.I hostkeyfile\fR] [\-p [\fIaddress\fR:]\fIport\fR]
|
||||
.SH DESCRIPTION
|
||||
.B dropbear
|
||||
is a SSH 2 server designed to be small enough to be used in small memory
|
||||
environments, while still being functional and secure enough for general use.
|
||||
is a small SSH server
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-b \fIbanner
|
||||
@@ -20,21 +18,16 @@ Display the contents of the file
|
||||
.I banner
|
||||
before user login (default: none).
|
||||
.TP
|
||||
.B \-d \fIdsskey
|
||||
dsskeyfile.
|
||||
.B \-r \fIhostkey
|
||||
Use the contents of the file
|
||||
.I dsskey
|
||||
for the dss host key (default: /etc/dropbear/dropbear_dss_host_key).
|
||||
.I hostkey
|
||||
for the SSH hostkey.
|
||||
This file is generated with
|
||||
.BR dropbearkey (8).
|
||||
.BR dropbearkey (1)
|
||||
or automatically with the '-R' option. See "Host Key Files" below.
|
||||
.TP
|
||||
.B \-r \fIrsakey
|
||||
rsakeyfile.
|
||||
Use the contents of the file
|
||||
.I rsakey
|
||||
for the rsa host key (default: /etc/dropbear/dropbear_rsa_host_key).
|
||||
This file is generated with
|
||||
.BR dropbearkey (8).
|
||||
.B \-R
|
||||
Generate hostkeys automatically. See "Host Key Files" below.
|
||||
.TP
|
||||
.B \-F
|
||||
Don't fork into background.
|
||||
@@ -42,6 +35,12 @@ Don't fork into background.
|
||||
.B \-E
|
||||
Log to standard error rather than syslog.
|
||||
.TP
|
||||
.B \-e
|
||||
Pass on the server environment to all child processes. This is required, for example,
|
||||
if Dropbear is launched on the fly from a SLURM workload manager. The environment is not
|
||||
passed by default. Note that this could expose secrets in environment variables from
|
||||
the calling process - use with caution.
|
||||
.TP
|
||||
.B \-m
|
||||
Don't display the message of the day on login.
|
||||
.TP
|
||||
@@ -54,16 +53,24 @@ Disable password logins.
|
||||
.B \-g
|
||||
Disable password logins for root.
|
||||
.TP
|
||||
.B \-t
|
||||
Enable two-factor authentication. Both password login and public key authentication are
|
||||
required. Should not be used with the '-s' option.
|
||||
.TP
|
||||
.B \-j
|
||||
Disable local port forwarding.
|
||||
.TP
|
||||
.B \-k
|
||||
Disable remote port forwarding.
|
||||
.TP
|
||||
.B \-p \fIport
|
||||
Listen on specified tcp port
|
||||
.IR port ;
|
||||
up to 10 can be specified (default 22 if none specified).
|
||||
.B \-p\fR [\fIaddress\fR:]\fIport
|
||||
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.
|
||||
@@ -71,11 +78,151 @@ 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
|
||||
of 0 disables keepalives. If no response is received for 3 consecutive keepalives the connection will be closed.
|
||||
.TP
|
||||
.B \-I \fIidle_timeout
|
||||
Disconnect the session if no traffic is transmitted or received for \fIidle_timeout\fR seconds.
|
||||
.TP
|
||||
.B \-z
|
||||
By default Dropbear will send network traffic with the \fBAF21\fR setting for QoS, letting network devices give it higher priority. Some devices may have problems with that, \fI-z\fR can be used to disable it.
|
||||
.TP
|
||||
.B \-T \fImax_authentication_attempts
|
||||
Set the number of authentication attempts allowed per connection. If unspecified the default is 10 (MAX_AUTH_TRIES)
|
||||
.TP
|
||||
.B \-c \fIforced_command
|
||||
Disregard the command provided by the user and always run \fIforced_command\fR. This also
|
||||
overrides any authorized_keys command= option. The original command is saved in the
|
||||
SSH_ORIGINAL_COMMAND environment variable (see below).
|
||||
.TP
|
||||
.B \-V
|
||||
Print the version
|
||||
|
||||
.SH FILES
|
||||
|
||||
.TP
|
||||
Authorized Keys
|
||||
|
||||
~/.ssh/authorized_keys can be set up to allow remote login with a RSA,
|
||||
ECDSA, Ed25519 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 restrict
|
||||
Applies all the no- restrictions listed above.
|
||||
|
||||
.TP
|
||||
.B permitopen=\fR"\fIhost:port\fR"
|
||||
Restrict local port forwarding so that connection is allowed only to the
|
||||
specified host and port. Multiple permitopen options separated by commas
|
||||
can be set in authorized_keys. Wildcard character ('*') may be used in
|
||||
port specification for matching any port. Hosts must be literal domain names or
|
||||
IP addresses.
|
||||
|
||||
.TP
|
||||
.B command=\fR"\fIforced_command\fR"
|
||||
Disregard the command provided by the user and always run \fIforced_command\fR.
|
||||
The -c command line option overrides this.
|
||||
|
||||
The authorized_keys file and its containing ~/.ssh directory must only be
|
||||
writable by the user, otherwise Dropbear will not allow a login using public
|
||||
key authentication.
|
||||
|
||||
.TP
|
||||
Host Key Files
|
||||
|
||||
Host key files are read at startup from a standard location, by default
|
||||
/etc/dropbear/dropbear_dss_host_key, /etc/dropbear/dropbear_rsa_host_key,
|
||||
/etc/dropbear/dropbear_ecdsa_host_key and /etc/dropbear/dropbear_ed25519_host_key
|
||||
|
||||
If the -r command line option is specified the default files are not loaded.
|
||||
Host key files are of the form generated by dropbearkey.
|
||||
The -R option can be used to automatically generate keys
|
||||
in the default location - keys will be generated after startup when the first
|
||||
connection is established. This had the benefit that the system /dev/urandom
|
||||
random number source has a better chance of being securely seeded.
|
||||
|
||||
.TP
|
||||
Message Of The Day
|
||||
|
||||
By default the file /etc/motd will be printed for any login shell (unless
|
||||
disabled at compile-time). This can also be disabled per-user
|
||||
by creating a file ~/.hushlogin .
|
||||
|
||||
.SH ENVIRONMENT VARIABLES
|
||||
Dropbear sets the standard variables USER, LOGNAME, HOME, SHELL, PATH, and TERM.
|
||||
|
||||
The variables below are set for sessions as appropriate.
|
||||
|
||||
.TP
|
||||
.B SSH_TTY
|
||||
This is set to the allocated TTY if a PTY was used.
|
||||
|
||||
.TP
|
||||
.B SSH_CONNECTION
|
||||
Contains "<remote_ip> <remote_port> <local_ip> <local_port>".
|
||||
|
||||
.TP
|
||||
.B DISPLAY
|
||||
Set X11 forwarding is used.
|
||||
|
||||
.TP
|
||||
.B SSH_ORIGINAL_COMMAND
|
||||
If a 'command=' authorized_keys option was used, the original command is specified
|
||||
in this variable. If a shell was requested this is set to an empty value.
|
||||
|
||||
.TP
|
||||
.B SSH_AUTH_SOCK
|
||||
Set to a forwarded ssh-agent connection.
|
||||
|
||||
.SH NOTES
|
||||
Dropbear only supports SSH protocol version 2.
|
||||
|
||||
.SH AUTHOR
|
||||
Matt Johnston (matt@ucc.asn.au).
|
||||
.br
|
||||
Gerrit Pape (pape@smarden.org) wrote this manual page.
|
||||
.SH SEE ALSO
|
||||
dropbearkey(8)
|
||||
dropbearkey(1), dbclient(1), dropbearconvert(1)
|
||||
.P
|
||||
http://matt.ucc.asn.au/dropbear/dropbear.html
|
||||
https://matt.ucc.asn.au/dropbear/dropbear.html
|
||||
|
||||
8
dropbear_lint.sh
Executable file
8
dropbear_lint.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
EXITCODE=0
|
||||
|
||||
# #ifdef instead of #if
|
||||
grep '#ifdef DROPBEAR' -I -- *.c *.h && EXITCODE=1
|
||||
|
||||
exit $EXITCODE
|
||||
59
dropbearconvert.1
Normal file
59
dropbearconvert.1
Normal file
@@ -0,0 +1,59 @@
|
||||
.TH dropbearconvert 1
|
||||
.SH NAME
|
||||
dropbearconvert \- convert between Dropbear and OpenSSH private key formats
|
||||
.SH SYNOPSIS
|
||||
.B dropbearconvert
|
||||
.I input_type
|
||||
.I output_type
|
||||
.I input_file
|
||||
.I output_file
|
||||
.SH DESCRIPTION
|
||||
.B Dropbear
|
||||
and
|
||||
.B OpenSSH
|
||||
SSH implementations have different private key formats.
|
||||
.B dropbearconvert
|
||||
can convert between the two.
|
||||
.P
|
||||
Dropbear uses the same SSH public key format as OpenSSH, it can be extracted
|
||||
from a private key by using
|
||||
.B dropbearkey \-y
|
||||
.P
|
||||
Encrypted private keys are not supported, use ssh-keygen(1) to decrypt them
|
||||
first.
|
||||
.SH ARGUMENTS
|
||||
.TP
|
||||
.I input_type
|
||||
Either
|
||||
.I dropbear
|
||||
or
|
||||
.I openssh
|
||||
.TP
|
||||
.I output_type
|
||||
Either
|
||||
.I dropbear
|
||||
or
|
||||
.I openssh
|
||||
.TP
|
||||
.I input_file
|
||||
An existing Dropbear or OpenSSH private key file
|
||||
.TP
|
||||
.I output_file
|
||||
The path to write the converted private key file. For client authentication ~/.ssh/id_dropbear is loaded by default
|
||||
.SH SUPPORTED FORMATS
|
||||
.B dropbearconvert
|
||||
can read OpenSSH format files, and older PEM format files (
|
||||
.B ssh-keygen
|
||||
.I -m PEM
|
||||
).
|
||||
.B dropbearconvert
|
||||
will write OpenSSH format files, usable with OpenSSH 6.5 and later.
|
||||
Reading OpenSSH format DSS files or PKCS8 files is not currently supported.
|
||||
.SH EXAMPLE
|
||||
# dropbearconvert openssh dropbear ~/.ssh/id_rsa ~/.ssh/id_dropbear
|
||||
.SH AUTHOR
|
||||
Matt Johnston (matt@ucc.asn.au).
|
||||
.SH SEE ALSO
|
||||
dropbearkey(1), ssh-keygen(1)
|
||||
.P
|
||||
https://matt.ucc.asn.au/dropbear/dropbear.html
|
||||
@@ -28,6 +28,8 @@
|
||||
#include "buffer.h"
|
||||
#include "dbutil.h"
|
||||
#include "keyimport.h"
|
||||
#include "crypto_desc.h"
|
||||
#include "dbrandom.h"
|
||||
|
||||
|
||||
static int do_convert(int intype, const char* infile, int outtype,
|
||||
@@ -51,8 +53,8 @@ static void printhelp(char * progname) {
|
||||
progname);
|
||||
}
|
||||
|
||||
#if defined(DBMULTI_dropbearconvert) || !defined(DROPBEAR_MULTI)
|
||||
#if defined(DBMULTI_dropbearconvert) && defined(DROPBEAR_MULTI)
|
||||
#if defined(DBMULTI_dropbearconvert) || !DROPBEAR_MULTI
|
||||
#if defined(DBMULTI_dropbearconvert) && DROPBEAR_MULTI
|
||||
int dropbearconvert_main(int argc, char ** argv) {
|
||||
#else
|
||||
int main(int argc, char ** argv) {
|
||||
@@ -62,9 +64,12 @@ int main(int argc, char ** argv) {
|
||||
const char* infile;
|
||||
const char* outfile;
|
||||
|
||||
#ifdef DEBUG_TRACE
|
||||
crypto_init();
|
||||
seedrandom();
|
||||
|
||||
#if DEBUG_TRACE
|
||||
/* It's hard for it to get in the way _too_ much */
|
||||
debug_trace = 1;
|
||||
debug_trace = DROPBEAR_VERBOSE_LEVEL;
|
||||
#endif
|
||||
|
||||
/* get the commandline options */
|
||||
@@ -111,7 +116,7 @@ static int do_convert(int intype, const char* infile, int outtype,
|
||||
const char* outfile) {
|
||||
|
||||
sign_key * key = NULL;
|
||||
char * keytype = NULL;
|
||||
const char * keytype = NULL;
|
||||
int ret = 1;
|
||||
|
||||
key = import_read(infile, NULL, intype);
|
||||
@@ -121,16 +126,7 @@ static int do_convert(int intype, const char* infile, int outtype,
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef DROPBEAR_RSA
|
||||
if (key->rsakey != NULL) {
|
||||
keytype = "RSA";
|
||||
}
|
||||
#endif
|
||||
#ifdef DROPBEAR_DSS
|
||||
if (key->dsskey != NULL) {
|
||||
keytype = "DSS";
|
||||
}
|
||||
#endif
|
||||
keytype = signkey_name_from_type(key->type, NULL);
|
||||
|
||||
fprintf(stderr, "Key is a %s key\n", keytype);
|
||||
|
||||
|
||||
61
dropbearkey.1
Normal file
61
dropbearkey.1
Normal file
@@ -0,0 +1,61 @@
|
||||
.TH dropbearkey 1
|
||||
.SH NAME
|
||||
dropbearkey \- create private keys for the use with dropbear(8) or dbclient(1)
|
||||
.SH SYNOPSIS
|
||||
.B dropbearkey
|
||||
\-t
|
||||
.I type
|
||||
\-f
|
||||
.I file
|
||||
[\-s
|
||||
.IR bits ]
|
||||
[\-y]
|
||||
.SH DESCRIPTION
|
||||
.B dropbearkey
|
||||
generates a
|
||||
\fIRSA\fR, \fIDSS\fR, \fIECDSA\fR, or \fIEd25519\fR
|
||||
format SSH private key, and saves it to a file for the use with the
|
||||
Dropbear client or server.
|
||||
Note that
|
||||
some SSH implementations
|
||||
use the term "DSA" rather than "DSS", they mean the same thing.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-t \fItype
|
||||
Type of key to generate.
|
||||
Must be one of
|
||||
.I rsa
|
||||
.I ecdsa
|
||||
.I ed25519
|
||||
or
|
||||
.IR dss .
|
||||
.TP
|
||||
.B \-f \fIfile
|
||||
Write the secret key to the file
|
||||
\fIfile\fR. For client authentication ~/.ssh/id_dropbear is loaded by default
|
||||
.TP
|
||||
.B \-s \fIbits
|
||||
Set the key size to
|
||||
.I bits
|
||||
bits, should be multiple of 8 (optional).
|
||||
.TP
|
||||
.B \-y
|
||||
Just print the publickey and fingerprint for the private key in \fIfile\fR.
|
||||
.SH NOTES
|
||||
The program dropbearconvert(1) can be used to convert between Dropbear and OpenSSH key formats.
|
||||
.P
|
||||
Dropbear does not support encrypted keys.
|
||||
.SH EXAMPLE
|
||||
generate a host-key:
|
||||
# dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
|
||||
|
||||
extract a public key suitable for authorized_keys from private key:
|
||||
# dropbearkey -y -f id_rsa | grep "^ssh-rsa " >> authorized_keys
|
||||
.SH AUTHOR
|
||||
Matt Johnston (matt@ucc.asn.au).
|
||||
.br
|
||||
Gerrit Pape (pape@smarden.org) wrote this manual page.
|
||||
.SH SEE ALSO
|
||||
dropbear(8), dbclient(1), dropbearconvert(1)
|
||||
.P
|
||||
https://matt.ucc.asn.au/dropbear/dropbear.html
|
||||
@@ -1,47 +0,0 @@
|
||||
.TH dropbearkey 8
|
||||
.SH NAME
|
||||
dropbearkey \- create private keys for the use with dropbear(8)
|
||||
.SH SYNOPSIS
|
||||
.B dropbearkey
|
||||
\-t
|
||||
.I type
|
||||
\-f
|
||||
.I file
|
||||
[\-s
|
||||
.IR bits ]
|
||||
.SH DESCRIPTION
|
||||
.B dropbearkey
|
||||
generates a type
|
||||
.I rsa
|
||||
or
|
||||
.I dss
|
||||
SSH private key, and saves it to a file for the use with the
|
||||
.BR dropbear (8)
|
||||
SSH 2 server.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-t \fItype
|
||||
Type of key to generate.
|
||||
Must be one of
|
||||
.I rsa
|
||||
or
|
||||
.IR dss .
|
||||
.TP
|
||||
.B \-f \fIfile
|
||||
Write the secret key to the file
|
||||
.IR file .
|
||||
.TP
|
||||
.B \-s \fIbits
|
||||
Set the key size to
|
||||
.I bits
|
||||
bits, should be multiple of 8 (optional).
|
||||
.SH EXAMPLE
|
||||
# dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
|
||||
.SH AUTHOR
|
||||
Matt Johnston (matt@ucc.asn.au).
|
||||
.br
|
||||
Gerrit Pape (pape@smarden.org) wrote this manual page.
|
||||
.SH SEE ALSO
|
||||
dropbear(8)
|
||||
.P
|
||||
http://matt.ucc.asn.au/dropbear/dropbear.html
|
||||
276
dropbearkey.c
276
dropbearkey.c
@@ -23,7 +23,7 @@
|
||||
* SOFTWARE. */
|
||||
|
||||
/* The format of the keyfiles is basically a raw dump of the buffer. Data types
|
||||
* are specified in the transport draft - string is a 32-bit len then the
|
||||
* are specified in the transport rfc 4253 - string is a 32-bit len then the
|
||||
* non-null-terminated string, mp_int is a 32-bit len then the bignum data.
|
||||
* The actual functions are buf_put_rsa_priv_key() and buf_put_dss_priv_key()
|
||||
|
||||
@@ -43,6 +43,10 @@
|
||||
* mp_int y
|
||||
* mp_int x
|
||||
*
|
||||
* Ed25519:
|
||||
* string "ssh-ed25519"
|
||||
* string k (32 bytes) + A (32 bytes)
|
||||
*
|
||||
*/
|
||||
#include "includes.h"
|
||||
#include "signkey.h"
|
||||
@@ -51,56 +55,116 @@
|
||||
|
||||
#include "genrsa.h"
|
||||
#include "gendss.h"
|
||||
#include "gened25519.h"
|
||||
#include "ecdsa.h"
|
||||
#include "crypto_desc.h"
|
||||
#include "dbrandom.h"
|
||||
#include "gensignkey.h"
|
||||
|
||||
static void printhelp(char * progname);
|
||||
|
||||
#define RSA_SIZE (1024/8) /* 1024 bit */
|
||||
#define DSS_SIZE (1024/8) /* 1024 bit */
|
||||
|
||||
static void buf_writefile(buffer * buf, const char * filename);
|
||||
static void printpubkey(sign_key * key, int keytype);
|
||||
static void justprintpub(const char* filename);
|
||||
static int printpubfile(const char* filename);
|
||||
|
||||
/* Print a help message */
|
||||
static void printhelp(char * progname) {
|
||||
|
||||
fprintf(stderr, "Usage: %s -t <type> -f <filename> [-s bits]\n"
|
||||
"Options are:\n"
|
||||
"-t type Type of key to generate. One of:\n"
|
||||
#ifdef DROPBEAR_RSA
|
||||
#if DROPBEAR_RSA
|
||||
" rsa\n"
|
||||
#endif
|
||||
#ifdef DROPBEAR_DSS
|
||||
#if DROPBEAR_DSS
|
||||
" dss\n"
|
||||
#endif
|
||||
"-f filename Use filename for the secret key\n"
|
||||
#if DROPBEAR_ECDSA
|
||||
" ecdsa\n"
|
||||
#endif
|
||||
#if DROPBEAR_ED25519
|
||||
" ed25519\n"
|
||||
#endif
|
||||
"-f filename Use filename for the secret key.\n"
|
||||
" ~/.ssh/id_dropbear is recommended for client keys.\n"
|
||||
"-s bits Key size in bits, should be a multiple of 8 (optional)\n"
|
||||
#if DROPBEAR_DSS
|
||||
" DSS has a fixed size of 1024 bits\n"
|
||||
#endif
|
||||
#if DROPBEAR_ECDSA
|
||||
" ECDSA has sizes "
|
||||
#if DROPBEAR_ECC_256
|
||||
"256 "
|
||||
#endif
|
||||
#if DROPBEAR_ECC_384
|
||||
"384 "
|
||||
#endif
|
||||
#if DROPBEAR_ECC_521
|
||||
"521 "
|
||||
#endif
|
||||
"\n"
|
||||
#endif
|
||||
#if DROPBEAR_ED25519
|
||||
" Ed25519 has a fixed size of 256 bits\n"
|
||||
#endif
|
||||
"-y Just print the publickey and fingerprint for the\n private key in <filename>.\n"
|
||||
#ifdef DEBUG_TRACE
|
||||
#if DEBUG_TRACE
|
||||
"-v verbose\n"
|
||||
#endif
|
||||
,progname);
|
||||
}
|
||||
|
||||
#if defined(DBMULTI_dropbearkey) || !defined(DROPBEAR_MULTI)
|
||||
#if defined(DBMULTI_dropbearkey) && defined(DROPBEAR_MULTI)
|
||||
/* fails fatally */
|
||||
static void check_signkey_bits(enum signkey_type type, int bits)
|
||||
{
|
||||
switch (type) {
|
||||
#if DROPBEAR_ED25519
|
||||
case DROPBEAR_SIGNKEY_ED25519:
|
||||
if (bits != 256) {
|
||||
dropbear_exit("Ed25519 keys have a fixed size of 256 bits\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if DROPBEAR_RSA
|
||||
case DROPBEAR_SIGNKEY_RSA:
|
||||
if (bits < 1024 || bits > 4096 || (bits % 8 != 0)) {
|
||||
dropbear_exit("Bits must satisfy 1024 <= bits <= 4096, and be a"
|
||||
" multiple of 8\n");
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if DROPBEAR_DSS
|
||||
case DROPBEAR_SIGNKEY_DSS:
|
||||
if (bits != 1024) {
|
||||
dropbear_exit("DSS keys have a fixed size of 1024 bits\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
(void)0; /* quiet, compiler. ecdsa handles checks itself */
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(DBMULTI_dropbearkey) || !DROPBEAR_MULTI
|
||||
#if defined(DBMULTI_dropbearkey) && DROPBEAR_MULTI
|
||||
int dropbearkey_main(int argc, char ** argv) {
|
||||
#else
|
||||
int main(int argc, char ** argv) {
|
||||
#endif
|
||||
|
||||
int i;
|
||||
char ** next = 0;
|
||||
sign_key *key = NULL;
|
||||
buffer *buf = NULL;
|
||||
char ** next = NULL;
|
||||
char * filename = NULL;
|
||||
int keytype = -1;
|
||||
enum signkey_type keytype = DROPBEAR_SIGNKEY_NONE;
|
||||
char * typetext = NULL;
|
||||
char * sizetext = NULL;
|
||||
unsigned int bits;
|
||||
unsigned int keysize;
|
||||
unsigned int bits = 0, genbits;
|
||||
int printpub = 0;
|
||||
|
||||
crypto_init();
|
||||
seedrandom();
|
||||
|
||||
/* get the commandline options */
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (argv[i] == NULL) {
|
||||
@@ -130,9 +194,9 @@ int main(int argc, char ** argv) {
|
||||
printhelp(argv[0]);
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
#ifdef DEBUG_TRACE
|
||||
#if DEBUG_TRACE
|
||||
case 'v':
|
||||
debug_trace = 1;
|
||||
debug_trace = DROPBEAR_VERBOSE_LEVEL;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
@@ -151,8 +215,8 @@ int main(int argc, char ** argv) {
|
||||
}
|
||||
|
||||
if (printpub) {
|
||||
justprintpub(filename);
|
||||
/* Not reached */
|
||||
int ret = printpubfile(filename);
|
||||
exit(ret);
|
||||
}
|
||||
|
||||
/* check/parse args */
|
||||
@@ -162,21 +226,32 @@ int main(int argc, char ** argv) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (strlen(typetext) == 3) {
|
||||
#ifdef DROPBEAR_RSA
|
||||
if (strncmp(typetext, "rsa", 3) == 0) {
|
||||
keytype = DROPBEAR_SIGNKEY_RSA;
|
||||
TRACE(("type is rsa"))
|
||||
}
|
||||
#endif
|
||||
#ifdef DROPBEAR_DSS
|
||||
if (strncmp(typetext, "dss", 3) == 0) {
|
||||
keytype = DROPBEAR_SIGNKEY_DSS;
|
||||
TRACE(("type is dss"))
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_RSA
|
||||
if (strcmp(typetext, "rsa") == 0)
|
||||
{
|
||||
keytype = DROPBEAR_SIGNKEY_RSA;
|
||||
}
|
||||
if (keytype == -1) {
|
||||
#endif
|
||||
#if DROPBEAR_DSS
|
||||
if (strcmp(typetext, "dss") == 0)
|
||||
{
|
||||
keytype = DROPBEAR_SIGNKEY_DSS;
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_ECDSA
|
||||
if (strcmp(typetext, "ecdsa") == 0)
|
||||
{
|
||||
keytype = DROPBEAR_SIGNKEY_ECDSA_KEYGEN;
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_ED25519
|
||||
if (strcmp(typetext, "ed25519") == 0)
|
||||
{
|
||||
keytype = DROPBEAR_SIGNKEY_ED25519;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (keytype == DROPBEAR_SIGNKEY_NONE) {
|
||||
fprintf(stderr, "Unknown key type '%s'\n", typetext);
|
||||
printhelp(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -187,73 +262,28 @@ int main(int argc, char ** argv) {
|
||||
fprintf(stderr, "Bits must be an integer\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (bits < 512 || bits > 4096 || (bits % 8 != 0)) {
|
||||
fprintf(stderr, "Bits must satisfy 512 <= bits <= 4096, and be a"
|
||||
" multiple of 8\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
keysize = bits / 8;
|
||||
} else {
|
||||
if (keytype == DROPBEAR_SIGNKEY_DSS) {
|
||||
keysize = DSS_SIZE;
|
||||
} else if (keytype == DROPBEAR_SIGNKEY_RSA) {
|
||||
keysize = RSA_SIZE;
|
||||
} else {
|
||||
exit(EXIT_FAILURE); /* not reached */
|
||||
}
|
||||
|
||||
check_signkey_bits(keytype, bits);;
|
||||
}
|
||||
|
||||
|
||||
fprintf(stderr, "Will output %d bit %s secret key to '%s'\n", keysize*8,
|
||||
typetext, filename);
|
||||
|
||||
/* don't want the file readable by others */
|
||||
umask(077);
|
||||
|
||||
/* now we can generate the key */
|
||||
key = new_sign_key();
|
||||
|
||||
fprintf(stderr, "Generating key, this may take a while...\n");
|
||||
switch(keytype) {
|
||||
#ifdef DROPBEAR_RSA
|
||||
case DROPBEAR_SIGNKEY_RSA:
|
||||
key->rsakey = gen_rsa_priv_key(keysize); /* 128 bytes = 1024 bit */
|
||||
break;
|
||||
#endif
|
||||
#ifdef DROPBEAR_DSS
|
||||
case DROPBEAR_SIGNKEY_DSS:
|
||||
key->dsskey = gen_dss_priv_key(keysize); /* 128 bytes = 1024 bit */
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(stderr, "Internal error, bad key type\n");
|
||||
exit(EXIT_FAILURE);
|
||||
genbits = signkey_generate_get_bits(keytype, bits);
|
||||
fprintf(stderr, "Generating %u bit %s key, this may take a while...\n", genbits, typetext);
|
||||
if (signkey_generate(keytype, bits, filename, 0) == DROPBEAR_FAILURE)
|
||||
{
|
||||
dropbear_exit("Failed to generate key.\n");
|
||||
}
|
||||
|
||||
buf = buf_new(MAX_PRIVKEY_SIZE);
|
||||
|
||||
buf_put_priv_key(buf, key, keytype);
|
||||
buf_setpos(buf, 0);
|
||||
buf_writefile(buf, filename);
|
||||
|
||||
buf_burn(buf);
|
||||
buf_free(buf);
|
||||
|
||||
printpubkey(key, keytype);
|
||||
|
||||
sign_key_free(key);
|
||||
printpubfile(filename);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void justprintpub(const char* filename) {
|
||||
static int printpubfile(const char* filename) {
|
||||
|
||||
buffer *buf = NULL;
|
||||
sign_key *key = NULL;
|
||||
int keytype;
|
||||
enum signkey_type keytype;
|
||||
int ret;
|
||||
int err = DROPBEAR_FAILURE;
|
||||
|
||||
@@ -280,12 +310,13 @@ static void justprintpub(const char* filename) {
|
||||
err = DROPBEAR_SUCCESS;
|
||||
|
||||
out:
|
||||
buf_burn(buf);
|
||||
buf_free(buf);
|
||||
buf_burn_free(buf);
|
||||
buf = NULL;
|
||||
sign_key_free(key);
|
||||
key = NULL;
|
||||
exit(err);
|
||||
if (key) {
|
||||
sign_key_free(key);
|
||||
key = NULL;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static void printpubkey(sign_key * key, int keytype) {
|
||||
@@ -297,6 +328,9 @@ static void printpubkey(sign_key * key, int keytype) {
|
||||
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);
|
||||
@@ -308,48 +342,26 @@ static void printpubkey(sign_key * key, int keytype) {
|
||||
err = base64_encode(buf_getptr(buf, len), len, base64key, &base64len);
|
||||
|
||||
if (err != CRYPT_OK) {
|
||||
fprintf(stderr, "base64 failed");
|
||||
dropbear_exit("base64 failed");
|
||||
}
|
||||
|
||||
typestring = signkey_name_from_type(keytype, &err);
|
||||
typestring = signkey_name_from_type(keytype, NULL);
|
||||
|
||||
fp = sign_key_fingerprint(buf_getptr(buf, len), len);
|
||||
|
||||
printf("Public key portion is:\n%s %s\nFingerprint: %s\n",
|
||||
typestring, base64key, fp);
|
||||
/* 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);
|
||||
}
|
||||
|
||||
266
dss.c
266
dss.c
@@ -28,7 +28,7 @@
|
||||
#include "dss.h"
|
||||
#include "buffer.h"
|
||||
#include "ssh.h"
|
||||
#include "random.h"
|
||||
#include "dbrandom.h"
|
||||
|
||||
/* Handle DSS (Digital Signature Standard), aka DSA (D.S. Algorithm),
|
||||
* operations, such as key reading, signing, verification. Key generation
|
||||
@@ -37,21 +37,18 @@
|
||||
* See FIPS186 or the Handbook of Applied Cryptography for details of the
|
||||
* algorithm */
|
||||
|
||||
#ifdef DROPBEAR_DSS
|
||||
#if DROPBEAR_DSS
|
||||
|
||||
/* Load a dss key from a buffer, initialising the values.
|
||||
* The key will have the same format as buf_put_dss_key.
|
||||
* These should be freed with dss_key_free.
|
||||
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
|
||||
int buf_get_dss_pub_key(buffer* buf, dss_key *key) {
|
||||
int buf_get_dss_pub_key(buffer* buf, dropbear_dss_key *key) {
|
||||
int ret = DROPBEAR_FAILURE;
|
||||
|
||||
TRACE(("enter buf_get_dss_pub_key"))
|
||||
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);
|
||||
dropbear_assert(key != NULL);
|
||||
m_mp_alloc_init_multi(&key->p, &key->q, &key->g, &key->y, NULL);
|
||||
key->x = NULL;
|
||||
|
||||
buf_incrpos(buf, 4+SSH_SIGNKEY_DSS_LEN); /* int + "ssh-dss" */
|
||||
@@ -60,71 +57,78 @@ int buf_get_dss_pub_key(buffer* buf, dss_key *key) {
|
||||
|| buf_getmpint(buf, key->g) == DROPBEAR_FAILURE
|
||||
|| buf_getmpint(buf, key->y) == DROPBEAR_FAILURE) {
|
||||
TRACE(("leave buf_get_dss_pub_key: failed reading mpints"))
|
||||
return DROPBEAR_FAILURE;
|
||||
ret = DROPBEAR_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (mp_count_bits(key->p) < MIN_DSS_KEYLEN) {
|
||||
dropbear_log(LOG_WARNING, "DSS key too short");
|
||||
TRACE(("leave buf_get_dss_pub_key: short key"))
|
||||
return DROPBEAR_FAILURE;
|
||||
if (mp_count_bits(key->p) != DSS_P_BITS) {
|
||||
dropbear_log(LOG_WARNING, "Bad DSS p");
|
||||
ret = DROPBEAR_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (mp_count_bits(key->q) != DSS_Q_BITS) {
|
||||
dropbear_log(LOG_WARNING, "Bad DSS q");
|
||||
ret = DROPBEAR_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* test 1 < g < p */
|
||||
if (mp_cmp_d(key->g, 1) != MP_GT) {
|
||||
dropbear_log(LOG_WARNING, "Bad DSS g");
|
||||
ret = DROPBEAR_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
if (mp_cmp(key->g, key->p) != MP_LT) {
|
||||
dropbear_log(LOG_WARNING, "Bad DSS g");
|
||||
ret = DROPBEAR_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = DROPBEAR_SUCCESS;
|
||||
TRACE(("leave buf_get_dss_pub_key: success"))
|
||||
return DROPBEAR_SUCCESS;
|
||||
out:
|
||||
if (ret == DROPBEAR_FAILURE) {
|
||||
m_mp_free_multi(&key->p, &key->q, &key->g, &key->y, NULL);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Same as buf_get_dss_pub_key, but reads a private "x" key at the end.
|
||||
* Loads a private dss key from a buffer
|
||||
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
|
||||
int buf_get_dss_priv_key(buffer* buf, dss_key *key) {
|
||||
int buf_get_dss_priv_key(buffer* buf, dropbear_dss_key *key) {
|
||||
|
||||
int ret = DROPBEAR_FAILURE;
|
||||
|
||||
assert(key != NULL);
|
||||
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);
|
||||
m_mp_alloc_init_multi(&key->x, NULL);
|
||||
ret = buf_getmpint(buf, key->x);
|
||||
if (ret == DROPBEAR_FAILURE) {
|
||||
m_mp_free_multi(&key->x, NULL);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Clear and free the memory used by a public or private key */
|
||||
void dss_key_free(dss_key *key) {
|
||||
void dss_key_free(dropbear_dss_key *key) {
|
||||
|
||||
TRACE(("enter dsa_key_free"))
|
||||
TRACE2(("enter dsa_key_free"))
|
||||
if (key == NULL) {
|
||||
TRACE(("enter dsa_key_free: key == NULL"))
|
||||
TRACE2(("enter dsa_key_free: key == NULL"))
|
||||
return;
|
||||
}
|
||||
if (key->p) {
|
||||
mp_clear(key->p);
|
||||
m_free(key->p);
|
||||
}
|
||||
if (key->q) {
|
||||
mp_clear(key->q);
|
||||
m_free(key->q);
|
||||
}
|
||||
if (key->g) {
|
||||
mp_clear(key->g);
|
||||
m_free(key->g);
|
||||
}
|
||||
if (key->y) {
|
||||
mp_clear(key->y);
|
||||
m_free(key->y);
|
||||
}
|
||||
if (key->x) {
|
||||
mp_clear(key->x);
|
||||
m_free(key->x);
|
||||
}
|
||||
m_mp_free_multi(&key->p, &key->q, &key->g, &key->y, &key->x, NULL);
|
||||
m_free(key);
|
||||
TRACE(("leave dsa_key_free"))
|
||||
TRACE2(("leave dsa_key_free"))
|
||||
}
|
||||
|
||||
/* put the dss public key into the buffer in the required format:
|
||||
@@ -135,9 +139,9 @@ void dss_key_free(dss_key *key) {
|
||||
* mpint g
|
||||
* mpint y
|
||||
*/
|
||||
void buf_put_dss_pub_key(buffer* buf, dss_key *key) {
|
||||
void buf_put_dss_pub_key(buffer* buf, const dropbear_dss_key *key) {
|
||||
|
||||
assert(key != NULL);
|
||||
dropbear_assert(key != NULL);
|
||||
buf_putstring(buf, SSH_SIGNKEY_DSS, SSH_SIGNKEY_DSS_LEN);
|
||||
buf_putmpint(buf, key->p);
|
||||
buf_putmpint(buf, key->q);
|
||||
@@ -147,20 +151,18 @@ void buf_put_dss_pub_key(buffer* buf, dss_key *key) {
|
||||
}
|
||||
|
||||
/* Same as buf_put_dss_pub_key, but with the private "x" key appended */
|
||||
void buf_put_dss_priv_key(buffer* buf, dss_key *key) {
|
||||
void buf_put_dss_priv_key(buffer* buf, const dropbear_dss_key *key) {
|
||||
|
||||
assert(key != NULL);
|
||||
dropbear_assert(key != NULL);
|
||||
buf_put_dss_pub_key(buf, key);
|
||||
buf_putmpint(buf, key->x);
|
||||
|
||||
}
|
||||
|
||||
#ifdef DROPBEAR_SIGNKEY_VERIFY
|
||||
#if DROPBEAR_SIGNKEY_VERIFY
|
||||
/* Verify a DSS signature (in buf) made on data by the key given.
|
||||
* returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
|
||||
int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data,
|
||||
unsigned int len) {
|
||||
|
||||
int buf_dss_verify(buffer* buf, const dropbear_dss_key *key, const buffer *data_buf) {
|
||||
unsigned char msghash[SHA1_HASH_SIZE];
|
||||
hash_state hs;
|
||||
int ret = DROPBEAR_FAILURE;
|
||||
@@ -169,10 +171,10 @@ int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data,
|
||||
DEF_MP_INT(val3);
|
||||
DEF_MP_INT(val4);
|
||||
char * string = NULL;
|
||||
int stringlen;
|
||||
unsigned int stringlen;
|
||||
|
||||
TRACE(("enter buf_dss_verify"))
|
||||
assert(key != NULL);
|
||||
dropbear_assert(key != NULL);
|
||||
|
||||
m_mp_init_multi(&val1, &val2, &val3, &val4, NULL);
|
||||
|
||||
@@ -182,22 +184,34 @@ int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data,
|
||||
goto out;
|
||||
}
|
||||
|
||||
#if DEBUG_DSS_VERIFY
|
||||
printmpint("dss verify p", key->p);
|
||||
printmpint("dss verify q", key->q);
|
||||
printmpint("dss verify g", key->g);
|
||||
printmpint("dss verify y", key->y);
|
||||
#endif
|
||||
|
||||
/* hash the data */
|
||||
sha1_init(&hs);
|
||||
sha1_process(&hs, data, len);
|
||||
sha1_process(&hs, data_buf->data, data_buf->len);
|
||||
sha1_done(&hs, msghash);
|
||||
|
||||
/* create the signature - s' and r' are the received signatures in buf */
|
||||
/* w = (s')-1 mod q */
|
||||
/* let val1 = s' */
|
||||
if (mp_read_unsigned_bin(&val1, &string[SHA1_HASH_SIZE], SHA1_HASH_SIZE)
|
||||
!= MP_OKAY) {
|
||||
goto out;
|
||||
}
|
||||
bytes_to_mp(&val1, (const unsigned char*) &string[SHA1_HASH_SIZE], SHA1_HASH_SIZE);
|
||||
#if DEBUG_DSS_VERIFY
|
||||
printmpint("dss verify s'", &val1);
|
||||
#endif
|
||||
|
||||
if (mp_cmp(&val1, key->q) != MP_LT) {
|
||||
TRACE(("verify failed, s' >= q"))
|
||||
goto out;
|
||||
}
|
||||
if (mp_cmp_d(&val1, 0) != MP_GT) {
|
||||
TRACE(("verify failed, s' <= 0"))
|
||||
goto out;
|
||||
}
|
||||
/* let val2 = w = (s')^-1 mod q*/
|
||||
if (mp_invmod(&val1, key->q, &val2) != MP_OKAY) {
|
||||
goto out;
|
||||
@@ -205,9 +219,11 @@ int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data,
|
||||
|
||||
/* u1 = ((SHA(M')w) mod q */
|
||||
/* let val1 = SHA(M') = msghash */
|
||||
if (mp_read_unsigned_bin(&val1, msghash, SHA1_HASH_SIZE) != MP_OKAY) {
|
||||
goto out;
|
||||
}
|
||||
bytes_to_mp(&val1, msghash, SHA1_HASH_SIZE);
|
||||
#if DEBUG_DSS_VERIFY
|
||||
printmpint("dss verify r'", &val1);
|
||||
#endif
|
||||
|
||||
/* let val3 = u1 = ((SHA(M')w) mod q */
|
||||
if (mp_mulmod(&val1, &val2, key->q, &val3) != MP_OKAY) {
|
||||
goto out;
|
||||
@@ -215,14 +231,15 @@ int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data,
|
||||
|
||||
/* u2 = ((r')w) mod q */
|
||||
/* let val1 = r' */
|
||||
if (mp_read_unsigned_bin(&val1, &string[0], SHA1_HASH_SIZE)
|
||||
!= MP_OKAY) {
|
||||
goto out;
|
||||
}
|
||||
bytes_to_mp(&val1, (const unsigned char*) &string[0], SHA1_HASH_SIZE);
|
||||
if (mp_cmp(&val1, key->q) != MP_LT) {
|
||||
TRACE(("verify failed, r' >= q"))
|
||||
goto out;
|
||||
}
|
||||
if (mp_cmp_d(&val1, 0) != MP_GT) {
|
||||
TRACE(("verify failed, r' <= 0"))
|
||||
goto out;
|
||||
}
|
||||
/* let val4 = u2 = ((r')w) mod q */
|
||||
if (mp_mulmod(&val1, &val2, key->q, &val4) != MP_OKAY) {
|
||||
goto out;
|
||||
@@ -261,52 +278,13 @@ out:
|
||||
}
|
||||
#endif /* DROPBEAR_SIGNKEY_VERIFY */
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* Sign the data presented with key, writing the signature contents
|
||||
* to the buffer
|
||||
*
|
||||
* When DSS_PROTOK is #defined:
|
||||
* The alternate k generation method is based on the method used in PuTTY.
|
||||
* In particular to avoid being vulnerable to attacks using flaws in random
|
||||
* generation of k, we use the following:
|
||||
*
|
||||
* proto_k = SHA512 ( SHA512(x) || SHA160(message) )
|
||||
* k = proto_k mod q
|
||||
*
|
||||
* Now we aren't relying on the random number generation to protect the private
|
||||
* key x, which is a long term secret */
|
||||
void buf_put_dss_sign(buffer* buf, dss_key *key, const unsigned char* data,
|
||||
unsigned int len) {
|
||||
|
||||
* to the buffer */
|
||||
void buf_put_dss_sign(buffer* buf, const dropbear_dss_key *key, const buffer *data_buf) {
|
||||
unsigned char msghash[SHA1_HASH_SIZE];
|
||||
unsigned int writelen;
|
||||
unsigned int i;
|
||||
#ifdef DSS_PROTOK
|
||||
unsigned char privkeyhash[SHA512_HASH_SIZE];
|
||||
unsigned char *privkeytmp;
|
||||
unsigned char proto_k[SHA512_HASH_SIZE];
|
||||
DEF_MP_INT(dss_protok);
|
||||
#else
|
||||
unsigned char kbuf[SHA1_HASH_SIZE];
|
||||
#endif
|
||||
size_t written;
|
||||
DEF_MP_INT(dss_k);
|
||||
DEF_MP_INT(dss_m);
|
||||
DEF_MP_INT(dss_temp1);
|
||||
@@ -316,108 +294,80 @@ void buf_put_dss_sign(buffer* buf, dss_key *key, const unsigned char* data,
|
||||
hash_state hs;
|
||||
|
||||
TRACE(("enter buf_put_dss_sign"))
|
||||
assert(key != NULL);
|
||||
dropbear_assert(key != NULL);
|
||||
|
||||
/* hash the data */
|
||||
sha1_init(&hs);
|
||||
sha1_process(&hs, data, len);
|
||||
sha1_process(&hs, data_buf->data, data_buf->len);
|
||||
sha1_done(&hs, msghash);
|
||||
|
||||
m_mp_init_multi(&dss_k, &dss_temp1, &dss_temp2, &dss_r, &dss_s,
|
||||
&dss_m, NULL);
|
||||
#ifdef DSS_PROTOK
|
||||
/* hash the privkey */
|
||||
privkeytmp = mptobytes(key->x, &i);
|
||||
sha512_init(&hs);
|
||||
sha512_process(&hs, "the quick brown fox jumped over the lazy dog", 44);
|
||||
sha512_process(&hs, privkeytmp, i);
|
||||
sha512_done(&hs, privkeyhash);
|
||||
m_burn(privkeytmp, i);
|
||||
m_free(privkeytmp);
|
||||
|
||||
/* calculate proto_k */
|
||||
sha512_init(&hs);
|
||||
sha512_process(&hs, privkeyhash, SHA512_HASH_SIZE);
|
||||
sha512_process(&hs, msghash, SHA1_HASH_SIZE);
|
||||
sha512_done(&hs, proto_k);
|
||||
|
||||
/* generate k */
|
||||
m_mp_init(&dss_protok);
|
||||
bytestomp(&dss_protok, proto_k, SHA512_HASH_SIZE);
|
||||
mp_mod(&dss_protok, key->q, &dss_k);
|
||||
mp_clear(&dss_protok);
|
||||
m_burn(proto_k, SHA512_HASH_SIZE);
|
||||
#else /* DSS_PROTOK not defined*/
|
||||
do {
|
||||
genrandom(kbuf, SHA1_HASH_SIZE);
|
||||
if (mp_read_unsigned_bin(&dss_k, kbuf, SHA1_HASH_SIZE) != MP_OKAY) {
|
||||
dropbear_exit("dss error");
|
||||
}
|
||||
} while (mp_cmp(&dss_k, key->q) == MP_GT || mp_cmp_d(&dss_k, 0) != MP_GT);
|
||||
m_burn(kbuf, SHA1_HASH_SIZE);
|
||||
#endif
|
||||
/* the random number generator's input has included the private key which
|
||||
* avoids DSS's problem of private key exposure due to low entropy */
|
||||
gen_random_mpint(key->q, &dss_k);
|
||||
|
||||
/* now generate the actual signature */
|
||||
bytestomp(&dss_m, msghash, SHA1_HASH_SIZE);
|
||||
bytes_to_mp(&dss_m, msghash, SHA1_HASH_SIZE);
|
||||
|
||||
/* g^k mod p */
|
||||
if (mp_exptmod(key->g, &dss_k, key->p, &dss_temp1) != MP_OKAY) {
|
||||
dropbear_exit("dss error");
|
||||
dropbear_exit("DSS error");
|
||||
}
|
||||
/* r = (g^k mod p) mod q */
|
||||
if (mp_mod(&dss_temp1, key->q, &dss_r) != MP_OKAY) {
|
||||
dropbear_exit("dss error");
|
||||
dropbear_exit("DSS error");
|
||||
}
|
||||
|
||||
/* x*r mod q */
|
||||
if (mp_mulmod(&dss_r, key->x, key->q, &dss_temp1) != MP_OKAY) {
|
||||
dropbear_exit("dss error");
|
||||
dropbear_exit("DSS error");
|
||||
}
|
||||
/* (SHA1(M) + xr) mod q) */
|
||||
if (mp_addmod(&dss_m, &dss_temp1, key->q, &dss_temp2) != MP_OKAY) {
|
||||
dropbear_exit("dss error");
|
||||
dropbear_exit("DSS error");
|
||||
}
|
||||
|
||||
/* (k^-1) mod q */
|
||||
if (mp_invmod(&dss_k, key->q, &dss_temp1) != MP_OKAY) {
|
||||
dropbear_exit("dss error");
|
||||
dropbear_exit("DSS error");
|
||||
}
|
||||
|
||||
/* s = (k^-1(SHA1(M) + xr)) mod q */
|
||||
if (mp_mulmod(&dss_temp1, &dss_temp2, key->q, &dss_s) != MP_OKAY) {
|
||||
dropbear_exit("dss error");
|
||||
dropbear_exit("DSS error");
|
||||
}
|
||||
|
||||
buf_putstring(buf, SSH_SIGNKEY_DSS, SSH_SIGNKEY_DSS_LEN);
|
||||
buf_putint(buf, 2*SHA1_HASH_SIZE);
|
||||
|
||||
writelen = mp_unsigned_bin_size(&dss_r);
|
||||
assert(writelen <= SHA1_HASH_SIZE);
|
||||
writelen = mp_ubin_size(&dss_r);
|
||||
dropbear_assert(writelen <= SHA1_HASH_SIZE);
|
||||
/* need to pad to 160 bits with leading zeros */
|
||||
for (i = 0; i < SHA1_HASH_SIZE - writelen; i++) {
|
||||
buf_putbyte(buf, 0);
|
||||
}
|
||||
if (mp_to_unsigned_bin(&dss_r, buf_getwriteptr(buf, writelen))
|
||||
if (mp_to_ubin(&dss_r, buf_getwriteptr(buf, writelen), writelen, &written)
|
||||
!= MP_OKAY) {
|
||||
dropbear_exit("dss error");
|
||||
dropbear_exit("DSS error");
|
||||
}
|
||||
mp_clear(&dss_r);
|
||||
buf_incrwritepos(buf, writelen);
|
||||
buf_incrwritepos(buf, written);
|
||||
|
||||
writelen = mp_unsigned_bin_size(&dss_s);
|
||||
assert(writelen <= SHA1_HASH_SIZE);
|
||||
writelen = mp_ubin_size(&dss_s);
|
||||
dropbear_assert(writelen <= SHA1_HASH_SIZE);
|
||||
/* need to pad to 160 bits with leading zeros */
|
||||
for (i = 0; i < SHA1_HASH_SIZE - writelen; i++) {
|
||||
buf_putbyte(buf, 0);
|
||||
}
|
||||
if (mp_to_unsigned_bin(&dss_s, buf_getwriteptr(buf, writelen))
|
||||
if (mp_to_ubin(&dss_s, buf_getwriteptr(buf, writelen), writelen, &written)
|
||||
!= MP_OKAY) {
|
||||
dropbear_exit("dss error");
|
||||
dropbear_exit("DSS error");
|
||||
}
|
||||
mp_clear(&dss_s);
|
||||
buf_incrwritepos(buf, writelen);
|
||||
buf_incrwritepos(buf, written);
|
||||
|
||||
mp_clear_multi(&dss_k, &dss_temp1, &dss_temp1, &dss_r, &dss_s,
|
||||
mp_clear_multi(&dss_k, &dss_temp1, &dss_temp2, &dss_r, &dss_s,
|
||||
&dss_m, NULL);
|
||||
|
||||
/* create the signature to return */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user