mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-03-24 20:40:09 +09:00
Compare commits
526 Commits
libssh-0.8
...
master-fix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8daf03c564 | ||
|
|
8ece2abfab | ||
|
|
f05717d23e | ||
|
|
eaa97d2062 | ||
|
|
bda2cc69af | ||
|
|
83d827d7dd | ||
|
|
0f95295966 | ||
|
|
8e69d435ef | ||
|
|
d78a29eb79 | ||
|
|
58113d489e | ||
|
|
c306a693f3 | ||
|
|
21e2522360 | ||
|
|
8f887e82c7 | ||
|
|
993e24a361 | ||
|
|
cf6f1e7a64 | ||
|
|
31bc83f366 | ||
|
|
42ce989488 | ||
|
|
4282f3c664 | ||
|
|
3784226fd8 | ||
|
|
cf24048f02 | ||
|
|
f427a975b8 | ||
|
|
c413834764 | ||
|
|
41b0d263d6 | ||
|
|
a08a97f9c7 | ||
|
|
c0ae59e102 | ||
|
|
109a203453 | ||
|
|
ac8b954019 | ||
|
|
c6ca62d7e1 | ||
|
|
6d3672911b | ||
|
|
95f83c2391 | ||
|
|
130256c348 | ||
|
|
b72c9eead6 | ||
|
|
c7628fbfea | ||
|
|
783e5fd206 | ||
|
|
c79c33e224 | ||
|
|
968fdf4e18 | ||
|
|
bc91fa98ea | ||
|
|
d2434c69c0 | ||
|
|
7f83a1efae | ||
|
|
7b725e6bc7 | ||
|
|
46d8840f7e | ||
|
|
c1fdb56d23 | ||
|
|
57bdc9cb20 | ||
|
|
312084731e | ||
|
|
500bf54a34 | ||
|
|
a56fa14fda | ||
|
|
ac1377148f | ||
|
|
f38c6fcc6e | ||
|
|
0dd2b375c7 | ||
|
|
77be4ce905 | ||
|
|
78b1f0ead3 | ||
|
|
31527d4105 | ||
|
|
65e16b8d9e | ||
|
|
1f6b929735 | ||
|
|
74285d3aca | ||
|
|
7960fbaabb | ||
|
|
a2baf6e97b | ||
|
|
f9ff53b494 | ||
|
|
98487f464b | ||
|
|
b214f84538 | ||
|
|
05417665b9 | ||
|
|
e639c9d0d8 | ||
|
|
bf2c7128ab | ||
|
|
83f2ac4abb | ||
|
|
0b4c2a8e62 | ||
|
|
8418a1131e | ||
|
|
c18ed4eafa | ||
|
|
daabb084fe | ||
|
|
6709f2edf9 | ||
|
|
5bdb7a5079 | ||
|
|
824c56067b | ||
|
|
db5721d041 | ||
|
|
3da5fcbb56 | ||
|
|
9d8c943c68 | ||
|
|
21881cde34 | ||
|
|
55252e4d70 | ||
|
|
8e002b9415 | ||
|
|
f4339df577 | ||
|
|
0197e5e1e5 | ||
|
|
9546b20dec | ||
|
|
b227c12ad2 | ||
|
|
f369d02932 | ||
|
|
0b9e07fbdc | ||
|
|
c47cdc0f97 | ||
|
|
4b6eb05023 | ||
|
|
59ada799d7 | ||
|
|
bb5d46c190 | ||
|
|
aa56b8ca53 | ||
|
|
67f418218b | ||
|
|
03c30e9c8a | ||
|
|
61cac32288 | ||
|
|
aa899f8ec0 | ||
|
|
c88fb4c55b | ||
|
|
a8ed5e31dc | ||
|
|
86dabfe7e4 | ||
|
|
1650d8178e | ||
|
|
6eb43fcbf3 | ||
|
|
9aa47fef99 | ||
|
|
de7405f1c7 | ||
|
|
4a95a35bc6 | ||
|
|
f6b390084e | ||
|
|
b7fefb0500 | ||
|
|
89a8a6fcf0 | ||
|
|
7e44ce1556 | ||
|
|
5fc4d5b22a | ||
|
|
5159cd96e8 | ||
|
|
35c417312c | ||
|
|
e1a8b359c1 | ||
|
|
c8519c435e | ||
|
|
d85bc347d3 | ||
|
|
9c4baa7fd5 | ||
|
|
a4342b97d6 | ||
|
|
963c3077a4 | ||
|
|
a280747462 | ||
|
|
bce8d56705 | ||
|
|
ced05eb6db | ||
|
|
b796924fea | ||
|
|
2af4e3970e | ||
|
|
cf3c2ee5b3 | ||
|
|
57eb6a400a | ||
|
|
8c77a49729 | ||
|
|
8c8026b892 | ||
|
|
80be1d0ee9 | ||
|
|
9c3ba94960 | ||
|
|
194c34ebe3 | ||
|
|
00cd5b1c83 | ||
|
|
9fbbdcc154 | ||
|
|
b9ac61d5a3 | ||
|
|
ca425ebe67 | ||
|
|
7e6b540277 | ||
|
|
12ec1fed2f | ||
|
|
fb70d0fb41 | ||
|
|
f8b70d6a73 | ||
|
|
74888a6fa4 | ||
|
|
729384f346 | ||
|
|
7e5291668c | ||
|
|
bb081f6681 | ||
|
|
8a3ea3bdd5 | ||
|
|
a190ff9302 | ||
|
|
2e7e0ad6c9 | ||
|
|
39b08af2e8 | ||
|
|
60a3796041 | ||
|
|
cc4f220fd3 | ||
|
|
bc72ec5821 | ||
|
|
54ec81db2d | ||
|
|
1ec2ca4202 | ||
|
|
2fad391456 | ||
|
|
cde13b0f00 | ||
|
|
8f31623947 | ||
|
|
253bda4bac | ||
|
|
480915c07d | ||
|
|
e27c6b21b5 | ||
|
|
f65c00f39d | ||
|
|
1d33a4424d | ||
|
|
0386e088eb | ||
|
|
e91bb29e9d | ||
|
|
f622c4309b | ||
|
|
ae6b0e0f49 | ||
|
|
bdb3bb9ccd | ||
|
|
32e502a79d | ||
|
|
6ec5a08639 | ||
|
|
35a6455489 | ||
|
|
c1a8c41c5d | ||
|
|
893b69d82b | ||
|
|
9285e8516b | ||
|
|
91f35eca4d | ||
|
|
49e287006f | ||
|
|
85fc0d5b83 | ||
|
|
0ff566b6dd | ||
|
|
9c200d3ef4 | ||
|
|
4ea46eecce | ||
|
|
009ca5c9dd | ||
|
|
fe618a35dc | ||
|
|
795389ae1b | ||
|
|
60037f3275 | ||
|
|
e1548a71bd | ||
|
|
75be012b4a | ||
|
|
68b0c7a934 | ||
|
|
459868c4a5 | ||
|
|
5d7414467d | ||
|
|
20981bf229 | ||
|
|
825f4ba964 | ||
|
|
2bddafeb70 | ||
|
|
16b876d07f | ||
|
|
a80caec19b | ||
|
|
d6b6fff7f7 | ||
|
|
259d7de153 | ||
|
|
d13517e922 | ||
|
|
45058285fc | ||
|
|
42bd7cdf6c | ||
|
|
72bd2fe197 | ||
|
|
a2120e168b | ||
|
|
5790036a23 | ||
|
|
032f486f27 | ||
|
|
46090facba | ||
|
|
777786d76c | ||
|
|
101df98e54 | ||
|
|
f747e46f33 | ||
|
|
275f73125d | ||
|
|
422376efd4 | ||
|
|
3245b50795 | ||
|
|
508dfc5251 | ||
|
|
43a40999da | ||
|
|
e701913fc8 | ||
|
|
aec9fa4442 | ||
|
|
85a274ff3c | ||
|
|
e210b61148 | ||
|
|
f09ca85ebf | ||
|
|
096d966e43 | ||
|
|
cc513c4c9a | ||
|
|
31202822a7 | ||
|
|
6118628424 | ||
|
|
00e5ef1b3c | ||
|
|
6eef4b4a3c | ||
|
|
79e907402e | ||
|
|
ca7da823c3 | ||
|
|
2eaa23a20e | ||
|
|
143b5e2e50 | ||
|
|
11d480134c | ||
|
|
3786db4cdf | ||
|
|
9cf341bad3 | ||
|
|
e57f0273a6 | ||
|
|
3d74c3802e | ||
|
|
667fb5f9a9 | ||
|
|
14f5624ff5 | ||
|
|
9adc2d36eb | ||
|
|
1e5e09563a | ||
|
|
35bf5334b8 | ||
|
|
a7604c7d6e | ||
|
|
c5cadaa982 | ||
|
|
caf50270c6 | ||
|
|
b7a29c7ffd | ||
|
|
491a42d046 | ||
|
|
642a1b1aa4 | ||
|
|
f709c3ac58 | ||
|
|
ae2b9a3bde | ||
|
|
1d7520b68a | ||
|
|
9c37c8c5a5 | ||
|
|
6c56c1e0d7 | ||
|
|
e4711c469f | ||
|
|
8410f43d8b | ||
|
|
d0ce2d1ecd | ||
|
|
5a198732a5 | ||
|
|
92aa2cf496 | ||
|
|
bbed139eca | ||
|
|
0eab270754 | ||
|
|
71594f9d6c | ||
|
|
2ae2baf9ca | ||
|
|
4c47719d98 | ||
|
|
a30d542207 | ||
|
|
d9d3b65df2 | ||
|
|
97cb302c0e | ||
|
|
90373d8394 | ||
|
|
07f7fa7806 | ||
|
|
5123f7955b | ||
|
|
c15ad753a7 | ||
|
|
63aa274f4b | ||
|
|
8170e30073 | ||
|
|
77f58a225f | ||
|
|
48459c37f6 | ||
|
|
31f24ed23e | ||
|
|
82c3faa44d | ||
|
|
7c75e76d10 | ||
|
|
f246e31ca0 | ||
|
|
7390db6bbb | ||
|
|
cc83b463ce | ||
|
|
39975fdd6d | ||
|
|
1226de875b | ||
|
|
2307be32cf | ||
|
|
eaaa4131de | ||
|
|
39102224b2 | ||
|
|
e365aed6d2 | ||
|
|
d23bda8181 | ||
|
|
86d521cbe7 | ||
|
|
856dc698a9 | ||
|
|
4d09c6dc31 | ||
|
|
03a66b8599 | ||
|
|
c04eac40f3 | ||
|
|
8cc0672c0c | ||
|
|
8f7214a584 | ||
|
|
9d2de880ec | ||
|
|
039c066da5 | ||
|
|
6efbf7a30e | ||
|
|
e5170107c9 | ||
|
|
30df04a8a5 | ||
|
|
aaca395bd3 | ||
|
|
0762057eb9 | ||
|
|
57153f6481 | ||
|
|
4c32befd93 | ||
|
|
be8302e2f3 | ||
|
|
97d2e1f4cb | ||
|
|
12fc0ea1bf | ||
|
|
573eab0d51 | ||
|
|
0e317e612f | ||
|
|
01135703a3 | ||
|
|
c070414309 | ||
|
|
d2cc4eccc7 | ||
|
|
38781f69b0 | ||
|
|
dc4faf9952 | ||
|
|
cbbc6ddcb6 | ||
|
|
a7456bf4d5 | ||
|
|
afc14fe003 | ||
|
|
79a3fcac72 | ||
|
|
945afaa6b4 | ||
|
|
d840a05be3 | ||
|
|
662c30eb72 | ||
|
|
29b5477849 | ||
|
|
2e8f2f03e7 | ||
|
|
983d1189d0 | ||
|
|
7b2e1c7fb7 | ||
|
|
ceecd3fd6f | ||
|
|
bfd33ecf29 | ||
|
|
56317caafc | ||
|
|
ca4fb9c6f8 | ||
|
|
91800eb243 | ||
|
|
2923ad59f9 | ||
|
|
556ad59a5a | ||
|
|
fcb203cb2d | ||
|
|
6dbcc21921 | ||
|
|
2eccd04ff6 | ||
|
|
e9b44d26b1 | ||
|
|
9f5f10552b | ||
|
|
458bda8877 | ||
|
|
3d35250c07 | ||
|
|
ef06ef2c1b | ||
|
|
ba1ff992ce | ||
|
|
e558827c4e | ||
|
|
1e195a232a | ||
|
|
d1cd914012 | ||
|
|
c3980d433a | ||
|
|
78498ee289 | ||
|
|
76f5a60a82 | ||
|
|
07986731c6 | ||
|
|
f1608778be | ||
|
|
72e91d5131 | ||
|
|
4af4b59e21 | ||
|
|
ca464ca2ba | ||
|
|
9ac6ac6c26 | ||
|
|
b6b5a61c97 | ||
|
|
1acb82e38a | ||
|
|
a6d59811bb | ||
|
|
d4a443d56c | ||
|
|
62bff4aff1 | ||
|
|
f8e68b92b8 | ||
|
|
9c5d2d4543 | ||
|
|
7867126aa6 | ||
|
|
4774d2b9f7 | ||
|
|
f48dcb26e3 | ||
|
|
d1f23cd6d8 | ||
|
|
e601dbd8e3 | ||
|
|
f3ffd8aa41 | ||
|
|
4d98b1cd7e | ||
|
|
b00a0578f9 | ||
|
|
336c097ae7 | ||
|
|
1dd8466f66 | ||
|
|
8b19ef05f3 | ||
|
|
7e11e41a9f | ||
|
|
5914ea7c75 | ||
|
|
f1e84d5e67 | ||
|
|
8e3dd09e11 | ||
|
|
ae0afec98d | ||
|
|
0be43c333e | ||
|
|
83a5d3b258 | ||
|
|
bb4bdec184 | ||
|
|
e0449ba21f | ||
|
|
8a56b90c3e | ||
|
|
218c67a51d | ||
|
|
89c525bbf1 | ||
|
|
2c0baef7d4 | ||
|
|
bfb6718b50 | ||
|
|
d99c066a0b | ||
|
|
2844942c1b | ||
|
|
3a729829fd | ||
|
|
576fdbe1e8 | ||
|
|
87df9cfc5d | ||
|
|
ea375d1605 | ||
|
|
c15bd2831f | ||
|
|
efef877356 | ||
|
|
254a0f7132 | ||
|
|
d2131b286f | ||
|
|
c1c32bda14 | ||
|
|
a1b57d3b94 | ||
|
|
be703974e9 | ||
|
|
29f36791c9 | ||
|
|
492e3d5c77 | ||
|
|
9a3f43f4ee | ||
|
|
baa434ebed | ||
|
|
f99e6766d6 | ||
|
|
3efc64112a | ||
|
|
bc19f892eb | ||
|
|
f8fc0b9dfb | ||
|
|
1b12a2415d | ||
|
|
1c0ac0b12e | ||
|
|
ea2b403ab2 | ||
|
|
8323cd791f | ||
|
|
461ebd1e2f | ||
|
|
be147e897d | ||
|
|
1d329236b3 | ||
|
|
0c6544adcb | ||
|
|
09a1d95b69 | ||
|
|
6b10bbea2f | ||
|
|
b4c8bd9fe4 | ||
|
|
5d13006650 | ||
|
|
6fa5e8adb0 | ||
|
|
60ad7ee15d | ||
|
|
5fe81e89fb | ||
|
|
09cf301eee | ||
|
|
594c62d718 | ||
|
|
4169be45eb | ||
|
|
5d53f519bc | ||
|
|
37864b6575 | ||
|
|
4521ab73b6 | ||
|
|
9ca6127b91 | ||
|
|
ebb01549d0 | ||
|
|
945469c9e0 | ||
|
|
82da0c3361 | ||
|
|
1f08aabe43 | ||
|
|
3ca7e1eea9 | ||
|
|
fa60827840 | ||
|
|
761225712a | ||
|
|
df13d8c61f | ||
|
|
cbccae795d | ||
|
|
100c9c98ce | ||
|
|
d7a64b9519 | ||
|
|
fc212d73ed | ||
|
|
2b05e46b62 | ||
|
|
8d8b64cc3f | ||
|
|
11d87238b8 | ||
|
|
8243030c55 | ||
|
|
111d06eac5 | ||
|
|
20ca6e09dd | ||
|
|
66a0f14a0c | ||
|
|
aba6e34b63 | ||
|
|
4fcc0bd407 | ||
|
|
7960b8ed1b | ||
|
|
2aeee5194c | ||
|
|
ca925588b0 | ||
|
|
5b07c1aa2c | ||
|
|
9510a538c2 | ||
|
|
f32cb70675 | ||
|
|
1499b38aef | ||
|
|
509331ec81 | ||
|
|
247983e982 | ||
|
|
f0e99961b6 | ||
|
|
2291c75ab0 | ||
|
|
77b4801e11 | ||
|
|
a3c8dac6b6 | ||
|
|
5334cb9d55 | ||
|
|
9a73fa885a | ||
|
|
23f60a56f3 | ||
|
|
648f5cf400 | ||
|
|
f49bb1b6a3 | ||
|
|
f0a4c1e888 | ||
|
|
a0fec81221 | ||
|
|
0aad4de5f4 | ||
|
|
280519af29 | ||
|
|
0ae376f133 | ||
|
|
73c9d60e5a | ||
|
|
ae3825dfb2 | ||
|
|
8f1e995cec | ||
|
|
4de8ed684b | ||
|
|
d0f3cdfa10 | ||
|
|
a97e227a9d | ||
|
|
119a457357 | ||
|
|
4ae7e35d9c | ||
|
|
47bf099c36 | ||
|
|
9a43298b3a | ||
|
|
3f17154367 | ||
|
|
f8435e261c | ||
|
|
6162b63d5e | ||
|
|
19e081aedb | ||
|
|
a154bd9f22 | ||
|
|
e618298bda | ||
|
|
7e1b67754c | ||
|
|
868623f9a8 | ||
|
|
49f92cf5cd | ||
|
|
c2fc9ac956 | ||
|
|
15473426c8 | ||
|
|
9820a35a9e | ||
|
|
5e9435924c | ||
|
|
64a354159f | ||
|
|
0a46690eca | ||
|
|
26263aabd4 | ||
|
|
6867a35004 | ||
|
|
7946104566 | ||
|
|
140ddf5109 | ||
|
|
887908107a | ||
|
|
8855a140cf | ||
|
|
a9a99fb31f | ||
|
|
26a4097742 | ||
|
|
99a9cf0fcb | ||
|
|
fd157befae | ||
|
|
6f6840a88a | ||
|
|
562e579675 | ||
|
|
1e89896d05 | ||
|
|
3b896750b8 | ||
|
|
f433949dcd | ||
|
|
8e418ea020 | ||
|
|
6766b0a860 | ||
|
|
ce45de9ea2 | ||
|
|
85d2c0371a | ||
|
|
1d9f548204 | ||
|
|
dad456a1ee | ||
|
|
a0214dfc9a | ||
|
|
c004b43fde | ||
|
|
6848c23d84 | ||
|
|
4104d2fb91 | ||
|
|
86d00f438c | ||
|
|
f65882cca6 | ||
|
|
a3475c2e4b | ||
|
|
4d87256ca7 | ||
|
|
6aa9392699 | ||
|
|
0656f8a43d | ||
|
|
66a3bc0332 | ||
|
|
dbce0e5228 | ||
|
|
8ef35a005c | ||
|
|
8425dce7b2 | ||
|
|
0be1ae0e3b | ||
|
|
83898f3f6c | ||
|
|
a33e71ae88 | ||
|
|
f2b6899298 | ||
|
|
4c058aefd9 | ||
|
|
8c2ad7bdd3 | ||
|
|
e04a8b3abd | ||
|
|
15ab612592 | ||
|
|
4f0f1a9160 |
366
.gitlab-ci.yml
366
.gitlab-ci.yml
@@ -7,29 +7,14 @@ variables:
|
||||
DEBIAN_CROSS_BUILD: buildenv-debian-cross
|
||||
|
||||
# torture_auth fails on centos7 docker images, so we don't use -DCLIENT_TESTING=ON
|
||||
centos7/openssl_1.0.x/x86-64:
|
||||
centos7/openssl_1.0.x/x86_64:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS7_BUILD
|
||||
script:
|
||||
- mkdir -p obj && cd obj && cmake3 -DUNIT_TESTING=ON -DCMAKE_BUILD_TYPE=Debug
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON
|
||||
-DWITH_PCAP=ON .. && make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
except:
|
||||
- tags
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
fedora/openssl_1.1.x/x86-64:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
script:
|
||||
- mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=Debug
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
- mkdir -p obj && cd obj && cmake3
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
@@ -41,12 +26,13 @@ fedora/openssl_1.1.x/x86-64:
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
fedora/openssl_1.1.x/x86-64/release:
|
||||
fedora/openssl_1.1.x/x86_64:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
script:
|
||||
- mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=Release
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
- mkdir -p obj && cd obj && cmake
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
@@ -67,7 +53,8 @@ fedora/address-sanitizer:
|
||||
script:
|
||||
- mkdir -p obj && cd obj && cmake
|
||||
-DCMAKE_BUILD_TYPE=AddressSanitizer
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
@@ -85,7 +72,7 @@ fedora/undefined-sanitizer:
|
||||
script:
|
||||
- mkdir -p obj && cd obj && cmake
|
||||
-DCMAKE_C_FLAGS="-fsanitize=undefined -fsanitize=null -fsanitize=alignment -fno-sanitize-recover"
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON ..
|
||||
&& make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
@@ -98,16 +85,27 @@ fedora/undefined-sanitizer:
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
fedora/static-analysis:
|
||||
fedora/csbuild:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
script:
|
||||
- export CCC_CC=clang
|
||||
- export CCC_CXX=clang++
|
||||
- mkdir -p obj && cd obj && scan-build cmake -DCMAKE_BUILD_TYPE=Debug
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON
|
||||
-DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang .. &&
|
||||
scan-build --status-bugs -o scan make -j$(nproc)
|
||||
- |
|
||||
if [[ -z "$CI_COMMIT_BEFORE_SHA" ]]; then
|
||||
export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20")
|
||||
fi
|
||||
|
||||
# Check if the commit exists in this branch
|
||||
# This is not the case for a force push
|
||||
git branch --contains $CI_COMMIT_BEFORE_SHA 2>/dev/null || export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20")
|
||||
|
||||
export CI_COMMIT_RANGE="$CI_COMMIT_BEFORE_SHA..$CI_COMMIT_SHA"
|
||||
|
||||
- csbuild
|
||||
--build-dir=obj-csbuild
|
||||
--prep-cmd="cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON @SRCDIR@"
|
||||
--build-cmd "make clean && make -j$(nproc)"
|
||||
--git-commit-range $CI_COMMIT_RANGE
|
||||
--color
|
||||
--print-current --print-fixed
|
||||
tags:
|
||||
- shared
|
||||
except:
|
||||
@@ -116,16 +114,17 @@ fedora/static-analysis:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/scan
|
||||
- obj-csbuild/
|
||||
|
||||
# That is a specific runner that we cannot enable universally.
|
||||
# We restrict it to builds under the $BUILD_IMAGES_PROJECT project.
|
||||
freebsd/x86-64:
|
||||
freebsd/x86_64:
|
||||
image:
|
||||
script:
|
||||
- mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=Debug
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
- mkdir -p obj && cd obj && cmake
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make && ctest --output-on-failure
|
||||
tags:
|
||||
@@ -141,11 +140,13 @@ freebsd/x86-64:
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
fedora/libgcrypt/x86-64:
|
||||
fedora/libgcrypt/x86_64:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
script:
|
||||
- mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=Debug
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
- mkdir -p obj && cd obj && cmake
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON
|
||||
-DWITH_GCRYPT=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
@@ -159,13 +160,14 @@ fedora/libgcrypt/x86-64:
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
fedora/mbedtls/x86-64:
|
||||
fedora/mbedtls/x86_64:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
script:
|
||||
- mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=Debug
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON
|
||||
- mkdir -p obj && cd obj && cmake
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON
|
||||
-DWITH_MBEDTLS=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
@@ -178,13 +180,89 @@ fedora/mbedtls/x86-64:
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
tumbleweed/openssl_1.1.x/x86-64:
|
||||
# Unit testing only, no client and pkd testing, because cwrap is not available
|
||||
# for MinGW
|
||||
fedora/mingw64:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$MINGW_BUILD
|
||||
script:
|
||||
- export WINEPATH=/usr/x86_64-w64-mingw32/sys-root/mingw/bin
|
||||
- export WINEDEBUG=-all
|
||||
- mkdir -p obj && cd obj && mingw64-cmake
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
except:
|
||||
- tags
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
# Unit testing only, no client and pkd testing, because cwrap is not available
|
||||
# for MinGW
|
||||
fedora/mingw32:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$MINGW_BUILD
|
||||
script:
|
||||
- export WINEPATH=/usr/i686-w64-mingw32/sys-root/mingw/bin
|
||||
- export WINEDEBUG=-all
|
||||
- mkdir -p obj && cd obj && mingw32-cmake
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
except:
|
||||
- tags
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
.Debian.cross.template: &Debian_cross_template
|
||||
stage: test
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$DEBIAN_CROSS_BUILD
|
||||
script:
|
||||
- build=$(dpkg-architecture -qDEB_HOST_GNU_TYPE)
|
||||
- host="${CI_JOB_NAME#*.cross.}"
|
||||
- mkdir -p obj && cd obj && cmake
|
||||
-DCMAKE_C_COMPILER="$(which $host-gcc)"
|
||||
-DCMAKE_CXX_COMPILER="$(which $host-g++)"
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DUNIT_TESTING=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON
|
||||
-DWITH_PCAP=ON .. &&
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
except:
|
||||
- tags
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
Debian.cross.mips-linux-gnu:
|
||||
<<: *Debian_cross_template
|
||||
|
||||
tumbleweed/openssl_1.1.x/x86_64/gcc:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
|
||||
script:
|
||||
- mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=Debug
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
-DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config
|
||||
- mkdir -p obj && cd obj && cmake
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
@@ -197,13 +275,77 @@ tumbleweed/openssl_1.1.x/x86-64:
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
tumbleweed/openssl_1.1.x/x86-64/release:
|
||||
tumbleweed/openssl_1.1.x/x86/gcc:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
|
||||
script:
|
||||
- mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=Release
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
-DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config
|
||||
- mkdir -p obj && cd obj && cmake
|
||||
-DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
except:
|
||||
- tags
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
tumbleweed/openssl_1.1.x/x86_64/gcc7:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
|
||||
script:
|
||||
- mkdir -p obj && cd obj && cmake
|
||||
-DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
except:
|
||||
- tags
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
tumbleweed/openssl_1.1.x/x86/gcc7:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
|
||||
script:
|
||||
- mkdir -p obj && cd obj && cmake
|
||||
-DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake
|
||||
-DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
except:
|
||||
- tags
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
tumbleweed/openssl_1.1.x/x86_64/clang:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
|
||||
script:
|
||||
- mkdir -p obj && cd obj && cmake
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
@@ -230,32 +372,15 @@ tumbleweed/docs:
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
tumbleweed/openssl_1.1.x/x86:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
|
||||
script:
|
||||
- mkdir -p obj && cd obj && cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
except:
|
||||
- tags
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
tumbleweed/undefined-sanitizer:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
|
||||
script:
|
||||
- mkdir -p obj && cd obj && cmake
|
||||
-DCMAKE_C_FLAGS="-fsanitize=undefined -fsanitize=null -fsanitize=alignment -fno-sanitize-recover"
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON ..
|
||||
&& make -j$(nproc) && ctest --output-on-failure
|
||||
-DCMAKE_BUILD_TYPE=UndefinedSanitizer
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
except:
|
||||
@@ -271,10 +396,12 @@ tumbleweed/static-analysis:
|
||||
script:
|
||||
- export CCC_CC=clang
|
||||
- export CCC_CXX=clang++
|
||||
- mkdir -p obj && cd obj && scan-build cmake -DCMAKE_BUILD_TYPE=Debug
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON
|
||||
-DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang .. &&
|
||||
- mkdir -p obj && cd obj && scan-build cmake
|
||||
-DCMAKE_BUILD_TYPE=Debug
|
||||
-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
scan-build --status-bugs -o scan make -j$(nproc)
|
||||
tags:
|
||||
- shared
|
||||
@@ -286,76 +413,55 @@ tumbleweed/static-analysis:
|
||||
paths:
|
||||
- obj/scan
|
||||
|
||||
# Unit testing only, no client and pkd testing, because cwrap is not available
|
||||
# for MinGW
|
||||
mingw64:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$MINGW_BUILD
|
||||
visualstudio/x86_64:
|
||||
script:
|
||||
- Xvfb :1 -screen 0 1024x768x16 -ac +extension GLX +render -noreset -nolisten tcp &
|
||||
- export DISPLAY=:1
|
||||
- mkdir -p obj && cd obj && mingw64-cmake -DCMAKE_BUILD_TYPE=Debug
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc)
|
||||
- export WINEPATH=/usr/x86_64-w64-mingw32/sys-root/mingw/bin
|
||||
- $env:VCPKG_DEFAULT_TRIPLET="x64-windows"
|
||||
- cd obj
|
||||
- cmake
|
||||
-A x64
|
||||
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_TOOLCHAIN_FILE"
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON ..
|
||||
- cmake --build .
|
||||
- ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
- vs2017
|
||||
- windows
|
||||
except:
|
||||
- tags
|
||||
only:
|
||||
- branches@libssh/libssh-mirror
|
||||
- branches@ansasaki/libssh-mirror
|
||||
- branches@cryptomilk/libssh-mirror
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
# Unit testing only, no client and pkd testing, because cwrap is not available
|
||||
# for MinGW
|
||||
mingw32:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$MINGW_BUILD
|
||||
visualstudio/x86:
|
||||
script:
|
||||
- Xvfb :1 -screen 0 1024x768x16 -ac +extension GLX +render -noreset -nolisten tcp &
|
||||
- export DISPLAY=:1
|
||||
- mkdir -p obj && cd obj && mingw32-cmake -DCMAKE_BUILD_TYPE=Debug
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc)
|
||||
- export WINEPATH=/usr/i686-w64-mingw32/sys-root/mingw/bin
|
||||
- $env:VCPKG_DEFAULT_TRIPLET="x86-windows"
|
||||
- cd obj
|
||||
- cmake
|
||||
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_TOOLCHAIN_FILE"
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON ..
|
||||
- cmake --build .
|
||||
- ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
- vs2017
|
||||
- windows
|
||||
except:
|
||||
- tags
|
||||
only:
|
||||
- branches@libssh/libssh-mirror
|
||||
- branches@ansasaki/libssh-mirror
|
||||
- branches@cryptomilk/libssh-mirror
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
.Debian.cross.template: &Debian_cross_template
|
||||
stage: test
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$DEBIAN_CROSS_BUILD
|
||||
script:
|
||||
- build=$(dpkg-architecture -qDEB_HOST_GNU_TYPE)
|
||||
- host="${CI_JOB_NAME#*.cross.}"
|
||||
- mkdir -p obj && cd obj && cmake
|
||||
-DCMAKE_C_COMPILER="$(which $host-gcc)"
|
||||
-DCMAKE_CXX_COMPILER="$(which $host-g++)"
|
||||
-DCMAKE_BUILD_TYPE=Debug
|
||||
-DUNIT_TESTING=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON
|
||||
-DWITH_PCAP=ON .. && make -j$(nproc)
|
||||
- ctest --output-on-failure -j$(nproc)
|
||||
tags:
|
||||
- shared
|
||||
except:
|
||||
- tags
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
Debian.cross.mips-linux-gnu:
|
||||
<<: *Debian_cross_template
|
||||
|
||||
@@ -10,7 +10,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
|
||||
include(DefineCMakeDefaults)
|
||||
include(DefineCompilerFlags)
|
||||
|
||||
project(libssh VERSION 0.8.5 LANGUAGES C)
|
||||
project(libssh VERSION 0.8.90 LANGUAGES C)
|
||||
|
||||
# global needed variable
|
||||
set(APPLICATION_NAME ${PROJECT_NAME})
|
||||
@@ -39,6 +39,9 @@ include(CompilerChecks.cmake)
|
||||
include(MacroEnsureOutOfSourceBuild)
|
||||
macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out of source build. Please create a separate build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there.")
|
||||
|
||||
# Copy library files to a lib sub-directory
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
|
||||
|
||||
# search for libraries
|
||||
if (WITH_ZLIB)
|
||||
find_package(ZLIB REQUIRED)
|
||||
@@ -67,6 +70,10 @@ else (WITH_GCRYPT)
|
||||
endif (NOT OPENSSL_FOUND)
|
||||
endif(WITH_GCRYPT)
|
||||
|
||||
if (UNIT_TESTING)
|
||||
find_package(CMocka REQUIRED)
|
||||
endif ()
|
||||
|
||||
# Find out if we have threading available
|
||||
set(CMAKE_THREAD_PREFER_PTHREADS ON)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
@@ -116,11 +123,22 @@ install(
|
||||
)
|
||||
endif (UNIX)
|
||||
|
||||
# cmake config files
|
||||
# CMake config files
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
set(LIBSSH_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}ssh${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||
|
||||
configure_file(${PROJECT_NAME}-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake @ONLY)
|
||||
configure_file(${PROJECT_NAME}-config-version.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake @ONLY)
|
||||
# libssh-config-version.cmake
|
||||
write_basic_package_version_file(libssh-config-version.cmake
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY SameMajorVersion)
|
||||
|
||||
# libssh-config.cmake
|
||||
configure_package_config_file(${PROJECT_NAME}-config.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_DIR}/${PROJECT_NAME}
|
||||
PATH_VARS INCLUDE_INSTALL_DIR LIB_INSTALL_DIR)
|
||||
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
|
||||
@@ -131,18 +149,13 @@ install(
|
||||
devel
|
||||
)
|
||||
|
||||
|
||||
# in tree build settings
|
||||
configure_file(libssh-build-tree-settings.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libssh-build-tree-settings.cmake @ONLY)
|
||||
|
||||
if (WITH_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif (WITH_EXAMPLES)
|
||||
|
||||
if (UNIT_TESTING)
|
||||
find_package(CMocka REQUIRED)
|
||||
include(AddCMockaTest)
|
||||
add_subdirectory(tests)
|
||||
include(AddCMockaTest)
|
||||
add_subdirectory(tests)
|
||||
endif (UNIT_TESTING)
|
||||
|
||||
### SOURCE PACKAGE
|
||||
|
||||
13
COPYING
13
COPYING
@@ -455,6 +455,15 @@ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
Linking with OpenSSL
|
||||
17. In addition, as a special exception, we give permission to link the code of its release of libssh with the OpenSSL project's "OpenSSL" library (or with modified versions of it that use the same license as the "OpenSSL" library), and distribute the linked executables. You must obey the GNU Lesser General Public License in all respects for all of the code used other than "OpenSSL". If you modify this file, you may extend this exception to your version of the file, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version.
|
||||
Linking with OpenSSL
|
||||
|
||||
17. In addition, as a special exception, we give permission to link the code
|
||||
of its release of libssh with the OpenSSL project's "OpenSSL" library (or with
|
||||
modified versions of it that use the same license as the "OpenSSL" library),
|
||||
and distribute the linked executables. You must obey the GNU Lesser General
|
||||
Public License in all respects for all of the code used other than "OpenSSL".
|
||||
If you modify this file, you may extend this exception to your version of the
|
||||
file, but you are not obligated to do so. If you do not wish to do so, delete
|
||||
this exception statement from your version.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
48
ChangeLog
48
ChangeLog
@@ -1,54 +1,6 @@
|
||||
ChangeLog
|
||||
==========
|
||||
|
||||
version 0.8.5 (released 2018-10-29)
|
||||
* Added support to get known_hosts locations with ssh_options_get()
|
||||
* Fixed preferred algorithm for known hosts negotiations
|
||||
* Fixed KEX with some server implementations (e.g. Cisco)
|
||||
* Fixed issues with MSVC
|
||||
* Fixed keyboard-interactive auth in server mode
|
||||
(regression from CVE-2018-10933)
|
||||
* Fixed gssapi auth in server mode (regression from CVE-2018-10933)
|
||||
* Fixed socket fd handling with proxy command
|
||||
* Fixed a memory leak with OpenSSL
|
||||
|
||||
version 0.8.4 (released 2018-10-16)
|
||||
* Fixed CVE-2018-10933
|
||||
* Fixed building without globbing support
|
||||
* Fixed possible memory leaks
|
||||
* Avoid SIGPIPE on sockets
|
||||
|
||||
version 0.8.3 (released 2018-09-21)
|
||||
* Added support for rsa-sha2
|
||||
* Added support to parse private keys in openssh container format
|
||||
(other than ed25519)
|
||||
* Added support for diffie-hellman-group18-sha512 and
|
||||
diffie-hellman-group16-sha512
|
||||
* Added ssh_get_fingerprint_hash()
|
||||
* Added ssh_pki_export_privkey_base64()
|
||||
* Added support for Match keyword in config file
|
||||
* Improved performance and reduced memory footprint for sftp
|
||||
* Fixed ecdsa publickey auth
|
||||
* Fixed reading a closed channel
|
||||
* Added support to announce posix-rename@openssh.com and
|
||||
hardlink@openssh.com in the sftp server
|
||||
|
||||
version 0.8.2 (released 2018-08-30)
|
||||
* Added sha256 fingerprints for pubkeys
|
||||
* Improved compiler flag detection
|
||||
* Fixed race condition in reading sftp messages
|
||||
* Fixed doxygen generation and added modern style
|
||||
* Fixed library initialization on Windows
|
||||
* Fixed __bounded__ attribute detection
|
||||
* Fixed a bug in the options parser
|
||||
* Fixed documentation for new knwon_hosts API
|
||||
|
||||
version 0.8.1 (released 2018-08-13)
|
||||
* Fixed version number in the header
|
||||
* Fixed version number in pkg-config and cmake config
|
||||
* Fixed library initialization
|
||||
* Fixed attribute detection
|
||||
|
||||
version 0.8.0 (released 2018-08-10)
|
||||
* Removed support for deprecated SSHv1 protocol
|
||||
* Added new connector API for clients
|
||||
|
||||
@@ -51,7 +51,10 @@ if (UNIX)
|
||||
add_c_compiler_flag("-Werror=format-security" SUPPORTED_COMPILER_FLAGS)
|
||||
|
||||
# Allow zero for a variadic macro argument
|
||||
add_c_compiler_flag("-Wno-gnu-zero-variadic-macro-arguments" SUPPORTED_COMPILER_FLAGS)
|
||||
string(TOLOWER "${CMAKE_C_COMPILER_ID}" _C_COMPILER_ID)
|
||||
if ("${_C_COMPILER_ID}" STREQUAL "clang")
|
||||
add_c_compiler_flag("-Wno-gnu-zero-variadic-macro-arguments" SUPPORTED_COMPILER_FLAGS)
|
||||
endif()
|
||||
|
||||
add_c_compiler_flag("-fno-common" SUPPORTED_COMPILER_FLAGS)
|
||||
|
||||
@@ -65,10 +68,18 @@ if (UNIX)
|
||||
check_c_compiler_flag_ssp("-fstack-protector-strong" WITH_STACK_PROTECTOR_STRONG)
|
||||
if (WITH_STACK_PROTECTOR_STRONG)
|
||||
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector-strong")
|
||||
# This is needed as Solaris has a seperate libssp
|
||||
if (SOLARIS)
|
||||
list(APPEND SUPPORTED_LINKER_FLAGS "-fstack-protector-strong")
|
||||
endif()
|
||||
else (WITH_STACK_PROTECTOR_STRONG)
|
||||
check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR)
|
||||
if (WITH_STACK_PROTECTOR)
|
||||
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector")
|
||||
# This is needed as Solaris has a seperate libssp
|
||||
if (SOLARIS)
|
||||
list(APPEND SUPPORTED_LINKER_FLAGS "-fstack-protector")
|
||||
endif()
|
||||
endif()
|
||||
endif (WITH_STACK_PROTECTOR_STRONG)
|
||||
|
||||
@@ -82,6 +93,8 @@ if (UNIX)
|
||||
add_c_compiler_flag("-Wno-error=tautological-compare" SUPPORTED_COMPILER_FLAGS)
|
||||
endif()
|
||||
|
||||
add_c_compiler_flag("-Wno-deprecated-declarations" DEPRECATION_COMPILER_FLAGS)
|
||||
|
||||
# Unset CMAKE_REQUIRED_FLAGS
|
||||
unset(CMAKE_REQUIRED_FLAGS)
|
||||
endif()
|
||||
@@ -100,3 +113,8 @@ if (OSX)
|
||||
endif()
|
||||
|
||||
set(DEFAULT_C_COMPILE_FLAGS ${SUPPORTED_COMPILER_FLAGS} CACHE INTERNAL "Default C Compiler Flags" FORCE)
|
||||
set(DEFAULT_LINK_FLAGS ${SUPPORTED_LINKER_FLAGS} CACHE INTERNAL "Default C Linker Flags" FORCE)
|
||||
|
||||
if (DEPRECATION_COMPILER_FLAGS)
|
||||
set(DEFAULT_C_NO_DEPRECATION_FLAGS ${DEPRECATION_COMPILER_FLAGS} CACHE INTERNAL "Default no deprecation flags" FORCE)
|
||||
endif()
|
||||
|
||||
@@ -64,6 +64,7 @@ check_include_file(sys/param.h HAVE_SYS_PARAM_H)
|
||||
check_include_file(arpa/inet.h HAVE_ARPA_INET_H)
|
||||
check_include_file(byteswap.h HAVE_BYTESWAP_H)
|
||||
check_include_file(glob.h HAVE_GLOB_H)
|
||||
check_include_file(valgrind/valgrind.h HAVE_VALGRIND_VALGRIND_H)
|
||||
|
||||
if (WIN32)
|
||||
check_include_file(io.h HAVE_IO_H)
|
||||
@@ -108,6 +109,10 @@ if (OPENSSL_FOUND)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
check_function_exists(EVP_aes_128_cbc HAVE_OPENSSL_EVP_AES_CBC)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
check_function_exists(EVP_aes_128_gcm HAVE_OPENSSL_EVP_AES_GCM)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
check_function_exists(CRYPTO_THREADID_set_callback HAVE_OPENSSL_CRYPTO_THREADID_SET_CALLBACK)
|
||||
@@ -124,6 +129,8 @@ if (OPENSSL_FOUND)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
check_function_exists(RAND_priv_bytes HAVE_OPENSSL_RAND_PRIV_BYTES)
|
||||
|
||||
check_function_exists(OPENSSL_ia32cap_loc HAVE_OPENSSL_IA32CAP_LOC)
|
||||
|
||||
unset(CMAKE_REQUIRED_INCLUDES)
|
||||
unset(CMAKE_REQUIRED_LIBRARIES)
|
||||
endif()
|
||||
@@ -254,6 +261,14 @@ if (CMAKE_USE_PTHREADS_INIT)
|
||||
set(HAVE_PTHREAD 1)
|
||||
endif (CMAKE_USE_PTHREADS_INIT)
|
||||
|
||||
if (UNIT_TESTING)
|
||||
if (CMOCKA_FOUND)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMOCKA_LIBRARIES})
|
||||
check_function_exists(cmocka_set_test_filter HAVE_CMOCKA_SET_TEST_FILTER)
|
||||
unset(CMAKE_REQUIRED_LIBRARIES)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# OPTIONS
|
||||
check_c_source_compiles("
|
||||
__thread int tls;
|
||||
@@ -272,19 +287,19 @@ int main(void) {
|
||||
###########################################################
|
||||
# For detecting attributes we need to treat warnings as
|
||||
# errors
|
||||
if (UNIX)
|
||||
if (UNIX OR MINGW)
|
||||
# Get warnings for attributs
|
||||
check_c_compiler_flag("-Wattributs" REQUIRED_FLAGS_WERROR)
|
||||
check_c_compiler_flag("-Wattributes" REQUIRED_FLAGS_WERROR)
|
||||
if (REQUIRED_FLAGS_WERROR)
|
||||
set(CMAKE_REQUIRED_FLAGS "-Wattributes")
|
||||
string(APPEND CMAKE_REQUIRED_FLAGS "-Wattributes ")
|
||||
endif()
|
||||
|
||||
# Turn warnings into errors
|
||||
check_c_compiler_flag("-Werror" REQUIRED_FLAGS_WERROR)
|
||||
if (REQUIRED_FLAGS_WERROR)
|
||||
set(CMAKE_REQUIRED_FLAGS "-Werror")
|
||||
string(APPEND CMAKE_REQUIRED_FLAGS "-Werror ")
|
||||
endif()
|
||||
endif (UNIX)
|
||||
endif ()
|
||||
|
||||
check_c_source_compiles("
|
||||
void test_constructor_attribute(void) __attribute__ ((constructor));
|
||||
@@ -328,6 +343,28 @@ int main(void) {
|
||||
return 0;
|
||||
}" HAVE_FALLTHROUGH_ATTRIBUTE)
|
||||
|
||||
if (NOT WIN32)
|
||||
check_c_source_compiles("
|
||||
#define __unused __attribute__((unused))
|
||||
|
||||
static int do_nothing(int i __unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = do_nothing(5);
|
||||
if (i > 5) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}" HAVE_UNUSED_ATTRIBUTE)
|
||||
endif()
|
||||
|
||||
check_c_source_compiles("
|
||||
#include <string.h>
|
||||
|
||||
@@ -366,6 +403,8 @@ int main(void) {
|
||||
return 0;
|
||||
}" HAVE_COMPILER__FUNCTION__)
|
||||
|
||||
# This is only available with OpenBSD's gcc implementation */
|
||||
if (OPENBSD)
|
||||
check_c_source_compiles("
|
||||
#define ARRAY_LEN 16
|
||||
void test_attr(const unsigned char *k)
|
||||
@@ -374,6 +413,7 @@ void test_attr(const unsigned char *k)
|
||||
int main(void) {
|
||||
return 0;
|
||||
}" HAVE_GCC_BOUNDED_ATTRIBUTE)
|
||||
endif(OPENBSD)
|
||||
|
||||
# Stop treating warnings as errors
|
||||
unset(CMAKE_REQUIRED_FLAGS)
|
||||
|
||||
8
INSTALL
8
INSTALL
@@ -22,12 +22,12 @@ optional:
|
||||
Note that these version numbers are version we know works correctly. If you
|
||||
build and run libssh successfully with an older version, please let us know.
|
||||
|
||||
Windows binaries known to be working:
|
||||
For Windows use vcpkg:
|
||||
|
||||
- http://www.slproweb.com/products/Win32OpenSSL.html
|
||||
- http://zlib.net/ -> zlib compiled DLL
|
||||
https://github.com/Microsoft/vcpkg
|
||||
|
||||
We installed them in C:\Program Files
|
||||
which you can use to install openssl and zilib. libssh itself is also part of
|
||||
vcpkg!
|
||||
|
||||
## Building
|
||||
First, you need to configure the compilation, using CMake. Go inside the
|
||||
|
||||
@@ -1,11 +1,63 @@
|
||||
# - add_cmocka_test(test_name test_source linklib1 ... linklibN)
|
||||
|
||||
#
|
||||
# Copyright (c) 2007 Daniel Gollub <dgollub@suse.de>
|
||||
# Copyright (c) 2007-2018 Andreas Schneider <asn@cryptomilk.org>
|
||||
# Copyright (c) 2018 Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
#.rst:
|
||||
# AddCMockaTest
|
||||
# -------------
|
||||
#
|
||||
# This file provides a function to add a test
|
||||
#
|
||||
# Functions provided
|
||||
# ------------------
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# add_cmocka_test(target_name
|
||||
# SOURCES src1 src2 ... srcN
|
||||
# [COMPILE_OPTIONS opt1 opt2 ... optN]
|
||||
# [LINK_LIBRARIES lib1 lib2 ... libN]
|
||||
# [LINK_OPTIONS lopt1 lop2 .. loptN]
|
||||
# )
|
||||
#
|
||||
# ``target_name``:
|
||||
# Required, expects the name of the test which will be used to define a target
|
||||
#
|
||||
# ``SOURCES``:
|
||||
# Required, expects one or more source files names
|
||||
#
|
||||
# ``COMPILE_OPTIONS``:
|
||||
# Optional, expects one or more options to be passed to the compiler
|
||||
#
|
||||
# ``LINK_LIBRARIES``:
|
||||
# Optional, expects one or more libraries to be linked with the test
|
||||
# executable.
|
||||
#
|
||||
# ``LINK_OPTIONS``:
|
||||
# Optional, expects one or more options to be passed to the linker
|
||||
#
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# .. code-block:: cmake
|
||||
#
|
||||
# add_cmocka_test(my_test
|
||||
# SOURCES my_test.c other_source.c
|
||||
# COMPILE_OPTIONS -g -Wall
|
||||
# LINK_LIBRARIES mylib
|
||||
# LINK_OPTIONS -Wl,--enable-syscall-fixup
|
||||
# )
|
||||
#
|
||||
# Where ``my_test`` is the name of the test, ``my_test.c`` and
|
||||
# ``other_source.c`` are sources for the binary, ``-g -Wall`` are compiler
|
||||
# options to be used, ``mylib`` is a target of a library to be linked, and
|
||||
# ``-Wl,--enable-syscall-fixup`` is an option passed to the linker.
|
||||
#
|
||||
|
||||
enable_testing()
|
||||
include(CTest)
|
||||
|
||||
@@ -17,10 +69,52 @@ if (CMAKE_CROSSCOMPILING)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
function(ADD_CMOCKA_TEST _testName _testSource)
|
||||
add_executable(${_testName} ${_testSource})
|
||||
function(ADD_CMOCKA_TEST _TARGET_NAME)
|
||||
|
||||
target_link_libraries(${_testName} ${ARGN})
|
||||
set(one_value_arguments
|
||||
)
|
||||
|
||||
set(multi_value_arguments
|
||||
SOURCES
|
||||
COMPILE_OPTIONS
|
||||
LINK_LIBRARIES
|
||||
LINK_OPTIONS
|
||||
)
|
||||
|
||||
cmake_parse_arguments(_add_cmocka_test
|
||||
""
|
||||
"${one_value_arguments}"
|
||||
"${multi_value_arguments}"
|
||||
${ARGN}
|
||||
)
|
||||
|
||||
if (NOT DEFINED _add_cmocka_test_SOURCES)
|
||||
message(FATAL_ERROR "No sources provided for target ${_TARGET_NAME}")
|
||||
endif()
|
||||
|
||||
add_executable(${_TARGET_NAME} ${_add_cmocka_test_SOURCES})
|
||||
|
||||
if (DEFINED _add_cmocka_test_COMPILE_OPTIONS)
|
||||
target_compile_options(${_TARGET_NAME}
|
||||
PRIVATE ${_add_cmocka_test_COMPILE_OPTIONS}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (DEFINED _add_cmocka_test_LINK_LIBRARIES)
|
||||
target_link_libraries(${_TARGET_NAME}
|
||||
PRIVATE ${_add_cmocka_test_LINK_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (DEFINED _add_cmocka_test_LINK_OPTIONS)
|
||||
set_target_properties(${_TARGET_NAME}
|
||||
PROPERTIES LINK_FLAGS
|
||||
${_add_cmocka_test_LINK_OPTIONS}
|
||||
)
|
||||
endif()
|
||||
|
||||
add_test(${_TARGET_NAME}
|
||||
${TARGET_SYSTEM_EMULATOR} ${_TARGET_NAME}
|
||||
)
|
||||
|
||||
add_test(${_testName} ${TARGET_SYSTEM_EMULATOR} ${CMAKE_CURRENT_BINARY_DIR}/${_testName}${CMAKE_EXECUTABLE_SUFFIX})
|
||||
endfunction (ADD_CMOCKA_TEST)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
if (UNIX AND NOT WIN32)
|
||||
# Activate with: -DCMAKE_BUILD_TYPE=Profiling
|
||||
set(CMAKE_C_FLAGS_PROFILING "-g -O0 -fprofile-arcs -ftest-coverage"
|
||||
set(CMAKE_C_FLAGS_PROFILING "-O0 -g -fprofile-arcs -ftest-coverage"
|
||||
CACHE STRING "Flags used by the C compiler during PROFILING builds.")
|
||||
set(CMAKE_CXX_FLAGS_PROFILING "-g -O0 -fprofile-arcs -ftest-coverage"
|
||||
set(CMAKE_CXX_FLAGS_PROFILING "-O0 -g -fprofile-arcs -ftest-coverage"
|
||||
CACHE STRING "Flags used by the CXX compiler during PROFILING builds.")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage"
|
||||
CACHE STRING "Flags used by the linker during the creation of shared libraries during PROFILING builds.")
|
||||
@@ -22,4 +22,16 @@ if (UNIX AND NOT WIN32)
|
||||
CACHE STRING "Flags used by the linker during the creation of shared libraries during ADDRESSSANITIZER builds.")
|
||||
set(CMAKE_EXEC_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address"
|
||||
CACHE STRING "Flags used by the linker during ADDRESSSANITIZER builds.")
|
||||
|
||||
# Activate with: -DCMAKE_BUILD_TYPE=UndefinedSanitizer
|
||||
set(CMAKE_C_FLAGS_UNDEFINEDSANITIZER "-g -O1 -fsanitize=undefined -fsanitize=null -fsanitize=alignment -fno-sanitize-recover"
|
||||
CACHE STRING "Flags used by the C compiler during UNDEFINEDSANITIZER builds.")
|
||||
set(CMAKE_CXX_FLAGS_UNDEFINEDSANITIZER "-g -O1 -fsanitize=undefined -fsanitize=null -fsanitize=alignment -fno-sanitize-recover"
|
||||
CACHE STRING "Flags used by the CXX compiler during UNDEFINEDSANITIZER builds.")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_UNDEFINEDSANITIZER "-fsanitize=undefined"
|
||||
CACHE STRING "Flags used by the linker during the creation of shared libraries during UNDEFINEDSANITIZER builds.")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_UNDEFINEDSANITIZER "-fsanitize=undefined"
|
||||
CACHE STRING "Flags used by the linker during the creation of shared libraries during UNDEFINEDSANITIZER builds.")
|
||||
set(CMAKE_EXEC_LINKER_FLAGS_UNDEFINEDSANITIZER "-fsanitize=undefined"
|
||||
CACHE STRING "Flags used by the linker during UNDEFINEDSANITIZER builds.")
|
||||
endif()
|
||||
|
||||
@@ -49,7 +49,15 @@ find_library(GCRYPT_LIBRARY
|
||||
PATH_SUFFIXES
|
||||
lib
|
||||
)
|
||||
set(GCRYPT_LIBRARIES ${GCRYPT_LIBRARY})
|
||||
find_library(GCRYPT_ERROR_LIBRARY
|
||||
NAMES
|
||||
gpg-error
|
||||
libgpg-error-0
|
||||
libgpg-error6-0
|
||||
HINTS
|
||||
${_GCRYPT_ROOT_HINTS_AND_PATHS}
|
||||
)
|
||||
set(GCRYPT_LIBRARIES ${GCRYPT_LIBRARY} ${GCRYPT_ERROR_LIBRARY})
|
||||
|
||||
if (GCRYPT_INCLUDE_DIR)
|
||||
file(STRINGS "${GCRYPT_INCLUDE_DIR}/gcrypt.h" _gcrypt_version_str REGEX "^#define GCRYPT_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]")
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
/* Define to 1 if you have the <glob.h> header file. */
|
||||
#cmakedefine HAVE_GLOB_H 1
|
||||
|
||||
/* Define to 1 if you have the <valgrind/valgrind.h> header file. */
|
||||
#cmakedefine HAVE_VALGRIND_VALGRIND_H 1
|
||||
|
||||
/* Define to 1 if you have the <pty.h> header file. */
|
||||
#cmakedefine HAVE_PTY_H 1
|
||||
|
||||
@@ -100,6 +103,9 @@
|
||||
/* Define to 1 if you have the `EVP_aes128_cbc' function. */
|
||||
#cmakedefine HAVE_OPENSSL_EVP_AES_CBC 1
|
||||
|
||||
/* Define to 1 if you have the `EVP_aes128_gcm' function. */
|
||||
#cmakedefine HAVE_OPENSSL_EVP_AES_GCM 1
|
||||
|
||||
/* Define to 1 if you have the `CRYPTO_THREADID_set_callback' function. */
|
||||
#cmakedefine HAVE_OPENSSL_CRYPTO_THREADID_SET_CALLBACK 1
|
||||
|
||||
@@ -109,6 +115,9 @@
|
||||
/* Define to 1 if you have the `EVP_CIPHER_CTX_new' function. */
|
||||
#cmakedefine HAVE_OPENSSL_EVP_CIPHER_CTX_NEW 1
|
||||
|
||||
/* Define to 1 if you have the `OPENSSL_ia32cap_loc' function. */
|
||||
#cmakedefine HAVE_OPENSSL_IA32CAP_LOC 1
|
||||
|
||||
/* Define to 1 if you have the `snprintf' function. */
|
||||
#cmakedefine HAVE_SNPRINTF 1
|
||||
|
||||
@@ -178,6 +187,9 @@
|
||||
/* Define to 1 if you have the `SecureZeroMemory' function. */
|
||||
#cmakedefine HAVE_SECURE_ZERO_MEMORY 1
|
||||
|
||||
/* Define to 1 if you have the `cmocka_set_test_filter' function. */
|
||||
#cmakedefine HAVE_CMOCKA_SET_TEST_FILTER 1
|
||||
|
||||
/*************************** LIBRARIES ***************************/
|
||||
|
||||
/* Define to 1 if you have the `crypto' library (-lcrypto). */
|
||||
@@ -192,12 +204,16 @@
|
||||
/* Define to 1 if you have the `pthread' library (-lpthread). */
|
||||
#cmakedefine HAVE_PTHREAD 1
|
||||
|
||||
/* Define to 1 if you have the `cmocka' library (-lcmocka). */
|
||||
#cmakedefine HAVE_CMOCKA 1
|
||||
|
||||
/**************************** OPTIONS ****************************/
|
||||
|
||||
#cmakedefine HAVE_GCC_THREAD_LOCAL_STORAGE 1
|
||||
#cmakedefine HAVE_MSC_THREAD_LOCAL_STORAGE 1
|
||||
|
||||
#cmakedefine HAVE_FALLTHROUGH_ATTRIBUTE 1
|
||||
#cmakedefine HAVE_UNUSED_ATTRIBUTE 1
|
||||
|
||||
#cmakedefine HAVE_CONSTRUCTOR_ATTRIBUTE 1
|
||||
#cmakedefine HAVE_DESTRUCTOR_ATTRIBUTE 1
|
||||
|
||||
@@ -14,6 +14,10 @@ clients must be made or how a client should react.
|
||||
#define EXAMPLES_COMMON_H_
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
|
||||
/** Zero a structure */
|
||||
#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
|
||||
|
||||
int authenticate_console(ssh_session session);
|
||||
int authenticate_kbdint(ssh_session session, const char *password);
|
||||
int verify_knownhost(ssh_session session);
|
||||
|
||||
@@ -32,82 +32,86 @@ clients must be made or how a client should react.
|
||||
#define strncasecmp _strnicmp
|
||||
#endif
|
||||
|
||||
int verify_knownhost(ssh_session session){
|
||||
enum ssh_known_hosts_e state;
|
||||
char buf[10];
|
||||
unsigned char *hash = NULL;
|
||||
size_t hlen;
|
||||
ssh_key srv_pubkey;
|
||||
int rc;
|
||||
int verify_knownhost(ssh_session session)
|
||||
{
|
||||
enum ssh_known_hosts_e state;
|
||||
char buf[10];
|
||||
unsigned char *hash = NULL;
|
||||
size_t hlen;
|
||||
ssh_key srv_pubkey;
|
||||
int rc;
|
||||
|
||||
rc = ssh_get_server_publickey(session, &srv_pubkey);
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
}
|
||||
rc = ssh_get_server_publickey(session, &srv_pubkey);
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = ssh_get_publickey_hash(srv_pubkey,
|
||||
SSH_PUBLICKEY_HASH_SHA256,
|
||||
&hash,
|
||||
&hlen);
|
||||
ssh_key_free(srv_pubkey);
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
}
|
||||
rc = ssh_get_publickey_hash(srv_pubkey,
|
||||
SSH_PUBLICKEY_HASH_SHA256,
|
||||
&hash,
|
||||
&hlen);
|
||||
ssh_key_free(srv_pubkey);
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
state = ssh_session_is_known_server(session);
|
||||
state = ssh_session_is_known_server(session);
|
||||
|
||||
switch(state){
|
||||
case SSH_KNOWN_HOSTS_OK:
|
||||
break; /* ok */
|
||||
switch(state) {
|
||||
case SSH_KNOWN_HOSTS_CHANGED:
|
||||
fprintf(stderr,"Host key for server changed : server's one is now :\n");
|
||||
ssh_print_hash(SSH_PUBLICKEY_HASH_SHA256, hash, hlen);
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
fprintf(stderr,"For security reason, connection will be stopped\n");
|
||||
return -1;
|
||||
fprintf(stderr,"Host key for server changed : server's one is now :\n");
|
||||
ssh_print_hash(SSH_PUBLICKEY_HASH_SHA256, hash, hlen);
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
fprintf(stderr,"For security reason, connection will be stopped\n");
|
||||
return -1;
|
||||
case SSH_KNOWN_HOSTS_OTHER:
|
||||
fprintf(stderr,"The host key for this server was not found but an other type of key exists.\n");
|
||||
fprintf(stderr,"An attacker might change the default server key to confuse your client"
|
||||
"into thinking the key does not exist\n"
|
||||
"We advise you to rerun the client with -d or -r for more safety.\n");
|
||||
return -1;
|
||||
fprintf(stderr,"The host key for this server was not found but an other type of key exists.\n");
|
||||
fprintf(stderr,"An attacker might change the default server key to confuse your client"
|
||||
"into thinking the key does not exist\n"
|
||||
"We advise you to rerun the client with -d or -r for more safety.\n");
|
||||
return -1;
|
||||
case SSH_KNOWN_HOSTS_NOT_FOUND:
|
||||
fprintf(stderr,"Could not find known host file. If you accept the host key here,\n");
|
||||
fprintf(stderr,"the file will be automatically created.\n");
|
||||
/* fallback to SSH_SERVER_NOT_KNOWN behavior */
|
||||
FALL_THROUGH;
|
||||
fprintf(stderr,"Could not find known host file. If you accept the host key here,\n");
|
||||
fprintf(stderr,"the file will be automatically created.\n");
|
||||
/* fallback to SSH_SERVER_NOT_KNOWN behavior */
|
||||
FALL_THROUGH;
|
||||
case SSH_SERVER_NOT_KNOWN:
|
||||
fprintf(stderr,
|
||||
"The server is unknown. Do you trust the host key (yes/no)?\n");
|
||||
ssh_print_hash(SSH_PUBLICKEY_HASH_SHA256, hash, hlen);
|
||||
fprintf(stderr,
|
||||
"The server is unknown. Do you trust the host key (yes/no)?\n");
|
||||
ssh_print_hash(SSH_PUBLICKEY_HASH_SHA256, hash, hlen);
|
||||
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
}
|
||||
if(strncasecmp(buf,"yes",3)!=0){
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
}
|
||||
if(strncasecmp(buf,"yes",3)==0){
|
||||
if (ssh_write_knownhost(session) < 0) {
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
fprintf(stderr, "error %s\n", strerror(errno));
|
||||
return -1;
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
}
|
||||
if(strncasecmp(buf,"yes",3)!=0){
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
}
|
||||
if(strncasecmp(buf,"yes",3)==0){
|
||||
rc = ssh_session_update_known_hosts(session);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
fprintf(stderr, "error %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
case SSH_KNOWN_HOSTS_ERROR:
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
fprintf(stderr,"%s",ssh_get_error(session));
|
||||
return -1;
|
||||
}
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return 0;
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
fprintf(stderr,"%s",ssh_get_error(session));
|
||||
return -1;
|
||||
case SSH_KNOWN_HOSTS_OK:
|
||||
break; /* ok */
|
||||
}
|
||||
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -472,7 +472,8 @@ static int process_stderr(socket_t fd, int revents, void *userdata) {
|
||||
}
|
||||
|
||||
static void handle_session(ssh_event event, ssh_session session) {
|
||||
int n, rc;
|
||||
int n;
|
||||
int rc = 0;
|
||||
|
||||
/* Structure for storing the pty size. */
|
||||
struct winsize wsize = {
|
||||
|
||||
@@ -90,6 +90,7 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
do{
|
||||
int fd;
|
||||
|
||||
ZERO_STRUCT(fds);
|
||||
FD_ZERO(&fds);
|
||||
if(!eof)
|
||||
FD_SET(0,&fds);
|
||||
|
||||
@@ -40,11 +40,11 @@ void *ssh_buffer_allocate(struct ssh_buffer_struct *buffer, uint32_t len);
|
||||
int ssh_buffer_allocate_size(struct ssh_buffer_struct *buffer, uint32_t len);
|
||||
int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
|
||||
const char *format,
|
||||
int argc,
|
||||
size_t argc,
|
||||
va_list ap);
|
||||
int _ssh_buffer_pack(struct ssh_buffer_struct *buffer,
|
||||
const char *format,
|
||||
int argc,
|
||||
size_t argc,
|
||||
...);
|
||||
#define ssh_buffer_pack(buffer, format, ...) \
|
||||
_ssh_buffer_pack((buffer), (format), __VA_NARG__(__VA_ARGS__), __VA_ARGS__, SSH_BUFFER_PACK_END)
|
||||
|
||||
90
include/libssh/bytearray.h
Normal file
90
include/libssh/bytearray.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2018 Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef _BYTEARRAY_H
|
||||
#define _BYTEARRAY_H
|
||||
|
||||
#define _DATA_BYTE_CONST(data, pos) \
|
||||
((uint8_t)(((const uint8_t *)(data))[(pos)]))
|
||||
|
||||
#define _DATA_BYTE(data, pos) \
|
||||
(((uint8_t *)(data))[(pos)])
|
||||
|
||||
/*
|
||||
* These macros pull or push integer values from byte arrays stored in
|
||||
* little-endian byte order.
|
||||
*/
|
||||
#define PULL_LE_U8(data, pos) \
|
||||
(_DATA_BYTE_CONST(data, pos))
|
||||
|
||||
#define PULL_LE_U16(data, pos) \
|
||||
((uint16_t)PULL_LE_U8(data, pos) | ((uint16_t)(PULL_LE_U8(data, (pos) + 1))) << 8)
|
||||
|
||||
#define PULL_LE_U32(data, pos) \
|
||||
((uint32_t)(PULL_LE_U16(data, pos) | ((uint32_t)PULL_LE_U16(data, (pos) + 2)) << 16))
|
||||
|
||||
#define PULL_LE_U64(data, pos) \
|
||||
((uint64_t)(PULL_LE_U32(data, pos) | ((uint64_t)PULL_LE_U32(data, (pos) + 4)) << 32))
|
||||
|
||||
|
||||
#define PUSH_LE_U8(data, pos, val) \
|
||||
(_DATA_BYTE(data, pos) = ((uint8_t)(val)))
|
||||
|
||||
#define PUSH_LE_U16(data, pos, val) \
|
||||
(PUSH_LE_U8((data), (pos), (uint8_t)((uint16_t)(val) & 0xff)), PUSH_LE_U8((data), (pos) + 1, (uint8_t)((uint16_t)(val) >> 8)))
|
||||
|
||||
#define PUSH_LE_U32(data, pos, val) \
|
||||
(PUSH_LE_U16((data), (pos), (uint16_t)((uint32_t)(val) & 0xffff)), PUSH_LE_U16((data), (pos) + 2, (uint16_t)((uint32_t)(val) >> 16)))
|
||||
|
||||
#define PUSH_LE_U64(data, pos, val) \
|
||||
(PUSH_LE_U32((data), (pos), (uint32_t)((uint64_t)(val) & 0xffffffff)), PUSH_LE_U32((data), (pos) + 4, (uint32_t)((uint64_t)(val) >> 32)))
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* These macros pull or push integer values from byte arrays stored in
|
||||
* big-endian byte order (network byte order).
|
||||
*/
|
||||
#define PULL_BE_U8(data, pos) \
|
||||
(_DATA_BYTE_CONST(data, pos))
|
||||
|
||||
#define PULL_BE_U16(data, pos) \
|
||||
((((uint16_t)(PULL_BE_U8(data, pos))) << 8) | (uint16_t)PULL_BE_U8(data, (pos) + 1))
|
||||
|
||||
#define PULL_BE_U32(data, pos) \
|
||||
((((uint32_t)PULL_BE_U16(data, pos)) << 16) | (uint32_t)(PULL_BE_U16(data, (pos) + 2)))
|
||||
|
||||
#define PULL_BE_U64(data, pos) \
|
||||
((((uint64_t)PULL_BE_U32(data, pos)) << 32) | (uint64_t)(PULL_BE_U32(data, (pos) + 4)))
|
||||
|
||||
|
||||
|
||||
#define PUSH_BE_U8(data, pos, val) \
|
||||
(_DATA_BYTE(data, pos) = ((uint8_t)(val)))
|
||||
|
||||
#define PUSH_BE_U16(data, pos, val) \
|
||||
(PUSH_BE_U8((data), (pos), (uint8_t)(((uint16_t)(val)) >> 8)), PUSH_BE_U8((data), (pos) + 1, (uint8_t)((val) & 0xff)))
|
||||
|
||||
#define PUSH_BE_U32(data, pos, val) \
|
||||
(PUSH_BE_U16((data), (pos), (uint16_t)(((uint32_t)(val)) >> 16)), PUSH_BE_U16((data), (pos) + 2, (uint16_t)((val) & 0xffff)))
|
||||
|
||||
#define PUSH_BE_U64(data, pos, val) \
|
||||
(PUSH_BE_U32((data), (pos), (uint32_t)(((uint64_t)(val)) >> 32)), PUSH_BE_U32((data), (pos) + 4, (uint32_t)((val) & 0xffffffff)))
|
||||
|
||||
#endif /* _BYTEARRAY_H */
|
||||
@@ -98,5 +98,9 @@ int ssh_channel_flush(ssh_channel channel);
|
||||
uint32_t ssh_channel_new_id(ssh_session session);
|
||||
ssh_channel ssh_channel_from_local(ssh_session session, uint32_t id);
|
||||
void ssh_channel_do_free(ssh_channel channel);
|
||||
int ssh_global_request(ssh_session session,
|
||||
const char *request,
|
||||
ssh_buffer buffer,
|
||||
int reply);
|
||||
|
||||
#endif /* CHANNELS_H_ */
|
||||
|
||||
66
include/libssh/config.h
Normal file
66
include/libssh/config.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* config.h - parse the ssh config file
|
||||
*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2009-2018 by Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* The SSH Library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* The SSH Library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with the SSH Library; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef LIBSSH_CONFIG_H_
|
||||
#define LIBSSH_CONFIG_H_
|
||||
|
||||
|
||||
enum ssh_config_opcode_e {
|
||||
/* Unknown opcode */
|
||||
SOC_UNKNOWN = -3,
|
||||
/* Known and not applicable to libssh */
|
||||
SOC_NA = -2,
|
||||
/* Known but not supported by current libssh version */
|
||||
SOC_UNSUPPORTED = -1,
|
||||
SOC_HOST,
|
||||
SOC_MATCH,
|
||||
SOC_HOSTNAME,
|
||||
SOC_PORT,
|
||||
SOC_USERNAME,
|
||||
SOC_IDENTITY,
|
||||
SOC_CIPHERS,
|
||||
SOC_MACS,
|
||||
SOC_COMPRESSION,
|
||||
SOC_TIMEOUT,
|
||||
SOC_PROTOCOL,
|
||||
SOC_STRICTHOSTKEYCHECK,
|
||||
SOC_KNOWNHOSTS,
|
||||
SOC_PROXYCOMMAND,
|
||||
SOC_GSSAPISERVERIDENTITY,
|
||||
SOC_GSSAPICLIENTIDENTITY,
|
||||
SOC_GSSAPIDELEGATECREDENTIALS,
|
||||
SOC_INCLUDE,
|
||||
SOC_BINDADDRESS,
|
||||
SOC_GLOBALKNOWNHOSTSFILE,
|
||||
SOC_LOGLEVEL,
|
||||
SOC_HOSTKEYALGORITHMS,
|
||||
SOC_KEXALGORITHMS,
|
||||
SOC_GSSAPIAUTHENTICATION,
|
||||
SOC_KBDINTERACTIVEAUTHENTICATION,
|
||||
SOC_PASSWORDAUTHENTICATION,
|
||||
SOC_PUBKEYAUTHENTICATION,
|
||||
SOC_PUBKEYACCEPTEDTYPES,
|
||||
|
||||
SOC_MAX /* Keep this one last in the list */
|
||||
};
|
||||
#endif /* LIBSSH_CONFIG_H_ */
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* crc32.c - simple CRC32 code
|
||||
*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2005 by Aris Adamantiadis
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _CRC32_H
|
||||
#define _CRC32_H
|
||||
|
||||
uint32_t ssh_crc32(const char *buf, uint32_t len);
|
||||
|
||||
#endif /* _CRC32_H */
|
||||
@@ -29,6 +29,8 @@
|
||||
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
#include <gcrypt.h>
|
||||
#elif defined(HAVE_LIBMBEDCRYPTO)
|
||||
#include <mbedtls/gcm.h>
|
||||
#endif
|
||||
#include "libssh/wrapper.h"
|
||||
|
||||
@@ -48,6 +50,9 @@
|
||||
|
||||
#define DIGEST_MAX_LEN 64
|
||||
|
||||
#define AES_GCM_TAGLEN 16
|
||||
#define AES_GCM_IVLEN 12
|
||||
|
||||
enum ssh_key_exchange_e {
|
||||
/* diffie-hellman-group1-sha1 */
|
||||
SSH_KEX_DH_GROUP1_SHA1=1,
|
||||
@@ -78,7 +83,10 @@ enum ssh_cipher_e {
|
||||
SSH_AES256_CBC,
|
||||
SSH_AES128_CTR,
|
||||
SSH_AES192_CTR,
|
||||
SSH_AES256_CTR
|
||||
SSH_AES256_CTR,
|
||||
SSH_AEAD_AES128_GCM,
|
||||
SSH_AEAD_AES256_GCM,
|
||||
SSH_AEAD_CHACHA20_POLY1305
|
||||
};
|
||||
|
||||
struct ssh_crypto_struct {
|
||||
@@ -136,6 +144,7 @@ struct ssh_cipher_struct {
|
||||
size_t keylen; /* length of the key structure */
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
gcry_cipher_hd_t *key;
|
||||
unsigned char last_iv[AES_GCM_IVLEN];
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
struct ssh_3des_key_schedule *des3_key;
|
||||
struct ssh_aes_key_schedule *aes_key;
|
||||
@@ -145,6 +154,10 @@ struct ssh_cipher_struct {
|
||||
mbedtls_cipher_context_t encrypt_ctx;
|
||||
mbedtls_cipher_context_t decrypt_ctx;
|
||||
mbedtls_cipher_type_t type;
|
||||
#ifdef MBEDTLS_GCM_C
|
||||
mbedtls_gcm_context gcm_ctx;
|
||||
unsigned char last_iv[AES_GCM_IVLEN];
|
||||
#endif /* MBEDTLS_GCM_C */
|
||||
#endif
|
||||
struct chacha20_poly1305_keysched *chacha20_schedule;
|
||||
unsigned int keysize; /* bytes of key used. != keylen */
|
||||
@@ -152,10 +165,14 @@ struct ssh_cipher_struct {
|
||||
/* sets the new key for immediate use */
|
||||
int (*set_encrypt_key)(struct ssh_cipher_struct *cipher, void *key, void *IV);
|
||||
int (*set_decrypt_key)(struct ssh_cipher_struct *cipher, void *key, void *IV);
|
||||
void (*encrypt)(struct ssh_cipher_struct *cipher, void *in, void *out,
|
||||
unsigned long len);
|
||||
void (*decrypt)(struct ssh_cipher_struct *cipher, void *in, void *out,
|
||||
unsigned long len);
|
||||
void (*encrypt)(struct ssh_cipher_struct *cipher,
|
||||
void *in,
|
||||
void *out,
|
||||
size_t len);
|
||||
void (*decrypt)(struct ssh_cipher_struct *cipher,
|
||||
void *in,
|
||||
void *out,
|
||||
size_t len);
|
||||
void (*aead_encrypt)(struct ssh_cipher_struct *cipher, void *in, void *out,
|
||||
size_t len, uint8_t *mac, uint64_t seq);
|
||||
int (*aead_decrypt_length)(struct ssh_cipher_struct *cipher, void *in,
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
/* libssh version */
|
||||
#define LIBSSH_VERSION_MAJOR 0
|
||||
#define LIBSSH_VERSION_MINOR 8
|
||||
#define LIBSSH_VERSION_MICRO 5
|
||||
#define LIBSSH_VERSION_MICRO 90
|
||||
|
||||
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
|
||||
LIBSSH_VERSION_MINOR, \
|
||||
@@ -405,6 +405,7 @@ enum ssh_options_e {
|
||||
SSH_OPTIONS_GLOBAL_KNOWNHOSTS,
|
||||
SSH_OPTIONS_NODELAY,
|
||||
SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
||||
SSH_OPTIONS_PROCESS_CONFIG,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -543,6 +544,10 @@ SSH_DEPRECATED LIBSSH_API ssh_channel ssh_forward_accept(ssh_session session, in
|
||||
SSH_DEPRECATED LIBSSH_API int ssh_forward_cancel(ssh_session session, const char *address, int port);
|
||||
SSH_DEPRECATED LIBSSH_API int ssh_forward_listen(ssh_session session, const char *address, int port, int *bound_port);
|
||||
SSH_DEPRECATED LIBSSH_API int ssh_get_publickey(ssh_session session, ssh_key *key);
|
||||
SSH_DEPRECATED LIBSSH_API int ssh_write_knownhost(ssh_session session);
|
||||
SSH_DEPRECATED LIBSSH_API char *ssh_dump_knownhost(ssh_session session);
|
||||
SSH_DEPRECATED LIBSSH_API int ssh_is_server_known(ssh_session session);
|
||||
|
||||
|
||||
|
||||
LIBSSH_API int ssh_get_random(void *where,int len,int strong);
|
||||
@@ -552,7 +557,6 @@ LIBSSH_API int ssh_get_poll_flags(ssh_session session);
|
||||
LIBSSH_API int ssh_init(void);
|
||||
LIBSSH_API int ssh_is_blocking(ssh_session session);
|
||||
LIBSSH_API int ssh_is_connected(ssh_session session);
|
||||
LIBSSH_API int ssh_is_server_known(ssh_session session);
|
||||
|
||||
/* KNOWN HOSTS */
|
||||
LIBSSH_API void ssh_knownhosts_entry_free(struct ssh_knownhosts_entry *entry);
|
||||
@@ -593,6 +597,8 @@ SSH_DEPRECATED LIBSSH_API void ssh_log(ssh_session session,
|
||||
|
||||
LIBSSH_API ssh_channel ssh_message_channel_request_open_reply_accept(ssh_message msg);
|
||||
LIBSSH_API int ssh_message_channel_request_reply_success(ssh_message msg);
|
||||
#define SSH_MESSAGE_FREE(x) \
|
||||
do { if ((x) != NULL) { ssh_message_free(x); (x) = NULL; } } while(0)
|
||||
LIBSSH_API void ssh_message_free(ssh_message msg);
|
||||
LIBSSH_API ssh_message ssh_message_get(ssh_session session);
|
||||
LIBSSH_API int ssh_message_subtype(ssh_message msg);
|
||||
@@ -760,8 +766,6 @@ LIBSSH_API int ssh_userauth_kbdint_setanswer(ssh_session session, unsigned int i
|
||||
const char *answer);
|
||||
LIBSSH_API int ssh_userauth_gssapi(ssh_session session);
|
||||
LIBSSH_API const char *ssh_version(int req_version);
|
||||
LIBSSH_API int ssh_write_knownhost(ssh_session session);
|
||||
LIBSSH_API char *ssh_dump_knownhost(ssh_session session);
|
||||
|
||||
LIBSSH_API void ssh_string_burn(ssh_string str);
|
||||
LIBSSH_API ssh_string ssh_string_copy(ssh_string str);
|
||||
|
||||
@@ -212,7 +212,7 @@ public:
|
||||
* @see ssh_userauth_kbdint
|
||||
*/
|
||||
int userauthKbdint(const char* username, const char* submethods){
|
||||
int ret=ssh_userauth_kbdint(c_session,NULL,NULL);
|
||||
int ret = ssh_userauth_kbdint(c_session, username, submethods);
|
||||
ssh_throw(ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -407,7 +407,7 @@ public:
|
||||
* @see ssh_write_knownhost
|
||||
*/
|
||||
int writeKnownhost(){
|
||||
int ret = ssh_write_knownhost(c_session);
|
||||
int ret = ssh_session_update_known_hosts(c_session);
|
||||
ssh_throw(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -101,7 +101,6 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request);
|
||||
|
||||
int ssh_message_handle_channel_request(ssh_session session, ssh_channel channel, ssh_buffer packet,
|
||||
const char *request, uint8_t want_reply);
|
||||
void ssh_message_queue(ssh_session session, ssh_message message);
|
||||
ssh_message ssh_message_pop_head(ssh_session session);
|
||||
int ssh_message_channel_request_open_reply_accept_channel(ssh_message msg, ssh_channel chan);
|
||||
|
||||
|
||||
@@ -81,4 +81,6 @@ int ssh_timeout_update(struct ssh_timestamp *ts, int timeout);
|
||||
|
||||
int ssh_match_group(const char *group, const char *object);
|
||||
|
||||
void uint64_inc(unsigned char *counter);
|
||||
|
||||
#endif /* MISC_H_ */
|
||||
|
||||
@@ -70,6 +70,7 @@ int ssh_packet_parse_type(ssh_session session);
|
||||
int ssh_packet_socket_callback(const void *data, size_t len, void *user);
|
||||
void ssh_packet_register_socket_callback(ssh_session session, struct ssh_socket_struct *s);
|
||||
void ssh_packet_set_callbacks(ssh_session session, ssh_packet_callbacks callbacks);
|
||||
void ssh_packet_remove_callbacks(ssh_session session, ssh_packet_callbacks callbacks);
|
||||
void ssh_packet_set_default_callbacks(ssh_session session);
|
||||
void ssh_packet_process(ssh_session session, uint8_t type);
|
||||
|
||||
|
||||
@@ -44,23 +44,23 @@ struct ssh_key_struct {
|
||||
int flags;
|
||||
const char *type_c; /* Don't free it ! it is static */
|
||||
int ecdsa_nid;
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
#if defined(HAVE_LIBGCRYPT)
|
||||
gcry_sexp_t dsa;
|
||||
gcry_sexp_t rsa;
|
||||
gcry_sexp_t ecdsa;
|
||||
#elif HAVE_LIBMBEDCRYPTO
|
||||
#elif defined(HAVE_LIBMBEDCRYPTO)
|
||||
mbedtls_pk_context *rsa;
|
||||
mbedtls_ecdsa_context *ecdsa;
|
||||
void *dsa;
|
||||
#elif HAVE_LIBCRYPTO
|
||||
#elif defined(HAVE_LIBCRYPTO)
|
||||
DSA *dsa;
|
||||
RSA *rsa;
|
||||
#ifdef HAVE_OPENSSL_ECC
|
||||
# if defined(HAVE_OPENSSL_ECC)
|
||||
EC_KEY *ecdsa;
|
||||
#else
|
||||
# else
|
||||
void *ecdsa;
|
||||
#endif /* HAVE_OPENSSL_EC_H */
|
||||
#endif
|
||||
# endif /* HAVE_OPENSSL_EC_H */
|
||||
#endif /* HAVE_LIBGCRYPT */
|
||||
ed25519_pubkey *ed25519_pubkey;
|
||||
ed25519_privkey *ed25519_privkey;
|
||||
void *cert;
|
||||
@@ -71,11 +71,11 @@ struct ssh_signature_struct {
|
||||
enum ssh_keytypes_e type;
|
||||
enum ssh_digest_e hash_type;
|
||||
const char *type_c;
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
#if defined(HAVE_LIBGCRYPT)
|
||||
gcry_sexp_t dsa_sig;
|
||||
gcry_sexp_t rsa_sig;
|
||||
gcry_sexp_t ecdsa_sig;
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
#elif defined(HAVE_LIBCRYPTO)
|
||||
DSA_SIG *dsa_sig;
|
||||
ssh_string rsa_sig;
|
||||
# ifdef HAVE_OPENSSL_ECC
|
||||
@@ -83,10 +83,10 @@ struct ssh_signature_struct {
|
||||
# else
|
||||
void *ecdsa_sig;
|
||||
# endif
|
||||
#elif defined HAVE_LIBMBEDCRYPTO
|
||||
#elif defined(HAVE_LIBMBEDCRYPTO)
|
||||
ssh_string rsa_sig;
|
||||
struct mbedtls_ecdsa_sig ecdsa_sig;
|
||||
#endif
|
||||
#endif /* HAVE_LIBGCRYPT */
|
||||
ed25519_signature *ed25519_sig;
|
||||
};
|
||||
|
||||
@@ -110,11 +110,11 @@ int ssh_pki_export_signature_blob(const ssh_signature sign,
|
||||
int ssh_pki_import_signature_blob(const ssh_string sig_blob,
|
||||
const ssh_key pubkey,
|
||||
ssh_signature *psig);
|
||||
int ssh_pki_signature_verify_blob(ssh_session session,
|
||||
ssh_string sig_blob,
|
||||
const ssh_key key,
|
||||
unsigned char *digest,
|
||||
size_t dlen);
|
||||
int ssh_pki_signature_verify(ssh_session session,
|
||||
ssh_signature sig,
|
||||
const ssh_key key,
|
||||
unsigned char *digest,
|
||||
size_t dlen);
|
||||
|
||||
/* SSH Public Key Functions */
|
||||
int ssh_pki_export_pubkey_blob(const ssh_key key,
|
||||
|
||||
@@ -386,6 +386,22 @@ void explicit_bzero(void *s, size_t n);
|
||||
# endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
|
||||
#endif /* FALL_THROUGH */
|
||||
|
||||
#ifndef __unused__
|
||||
# ifdef HAVE_UNUSED_ATTRIBUTE
|
||||
# define __unused__ __attribute__((unused))
|
||||
# else /* HAVE_UNUSED_ATTRIBUTE */
|
||||
# define __unused__
|
||||
# endif /* HAVE_UNUSED_ATTRIBUTE */
|
||||
#endif /* __unused__ */
|
||||
|
||||
#ifndef UNUSED_PARAM
|
||||
#define UNUSED_PARAM(param) param __unused__
|
||||
#endif /* UNUSED_PARAM */
|
||||
|
||||
#ifndef UNUSED_VAR
|
||||
#define UNUSED_VAR(var) __unused__ var
|
||||
#endif /* UNUSED_VAR */
|
||||
|
||||
void ssh_agent_state_free(void *data);
|
||||
|
||||
#endif /* _LIBSSH_PRIV_H */
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
#ifndef SESSION_H_
|
||||
#define SESSION_H_
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/kex.h"
|
||||
#include "libssh/packet.h"
|
||||
@@ -27,6 +29,7 @@
|
||||
#include "libssh/auth.h"
|
||||
#include "libssh/channels.h"
|
||||
#include "libssh/poll.h"
|
||||
#include "libssh/config.h"
|
||||
|
||||
/* These are the different states a SSH session can be into its life */
|
||||
enum ssh_session_state_e {
|
||||
@@ -164,8 +167,6 @@ struct ssh_session_struct {
|
||||
|
||||
struct ssh_list *channels; /* linked list of channels */
|
||||
int maxchannel;
|
||||
int exec_channel_opened; /* version 1 only. more
|
||||
info in channels1.c */
|
||||
ssh_agent agent; /* ssh agent */
|
||||
|
||||
/* keyb interactive data */
|
||||
@@ -219,6 +220,8 @@ struct ssh_session_struct {
|
||||
int gss_delegate_creds;
|
||||
int flags;
|
||||
int nodelay;
|
||||
bool config_processed;
|
||||
uint8_t options_seen[SOC_MAX];
|
||||
} opts;
|
||||
/* counters */
|
||||
ssh_counter socket_counter;
|
||||
@@ -232,8 +235,10 @@ struct ssh_session_struct {
|
||||
*/
|
||||
typedef int (*ssh_termination_function)(void *user);
|
||||
int ssh_handle_packets(ssh_session session, int timeout);
|
||||
int ssh_handle_packets_termination(ssh_session session, int timeout,
|
||||
ssh_termination_function fct, void *user);
|
||||
int ssh_handle_packets_termination(ssh_session session,
|
||||
long timeout,
|
||||
ssh_termination_function fct,
|
||||
void *user);
|
||||
void ssh_socket_exception_callback(int code, int errno_code, void *user);
|
||||
|
||||
#endif /* SESSION_H_ */
|
||||
|
||||
@@ -47,7 +47,8 @@ enum ssh_hmac_e {
|
||||
SSH_HMAC_SHA384,
|
||||
SSH_HMAC_SHA512,
|
||||
SSH_HMAC_MD5,
|
||||
SSH_HMAC_AEAD_POLY1305
|
||||
SSH_HMAC_AEAD_POLY1305,
|
||||
SSH_HMAC_AEAD_GCM
|
||||
};
|
||||
|
||||
enum ssh_des_e {
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
set(LIBSSH_INLUDE_DIR @PROJECT_SOURCE_DIR@/include)
|
||||
@@ -1,11 +0,0 @@
|
||||
set(PACKAGE_VERSION @PROJECT_VERSION@)
|
||||
|
||||
# Check whether the requested PACKAGE_FIND_VERSION is compatible
|
||||
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
|
||||
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||
else()
|
||||
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
||||
if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
|
||||
set(PACKAGE_VERSION_EXACT TRUE)
|
||||
endif()
|
||||
endif()
|
||||
@@ -1,15 +1,15 @@
|
||||
get_filename_component(LIBSSH_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||
@PACKAGE_INIT@
|
||||
|
||||
if (EXISTS "${LIBSSH_CMAKE_DIR}/CMakeCache.txt")
|
||||
# In build tree
|
||||
include(${LIBSSH_CMAKE_DIR}/libssh-build-tree-settings.cmake)
|
||||
if (EXISTS "${CMAKE_CURRENT_LIST_DIR}/CMakeCache.txt")
|
||||
# In tree build
|
||||
set_and_check(LIBSSH_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/include")
|
||||
set_and_check(LIBSSH_LIBRARIES "${CMAKE_CURRENT_LIST_DIR}/lib/@LIBSSH_LIBRARY_NAME@")
|
||||
else()
|
||||
set(LIBSSH_INCLUDE_DIR @INCLUDE_INSTALL_DIR@)
|
||||
set_and_check(LIBSSH_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@")
|
||||
set_and_check(LIBSSH_LIBRARIES "@PACKAGE_LIB_INSTALL_DIR@/@LIBSSH_LIBRARY_NAME@")
|
||||
endif()
|
||||
|
||||
set(LIBSSH_LIBRARY @LIB_INSTALL_DIR@/@LIBSSH_LIBRARY_NAME@)
|
||||
set(LIBSSH_LIBRARIES @LIB_INSTALL_DIR@/@LIBSSH_LIBRARY_NAME@)
|
||||
# For backward compatibility
|
||||
set(LIBSSH_LIBRARY ${LIBSSH_LIBRARIES})
|
||||
|
||||
set(LIBSSH_THREADS_LIBRARY @LIB_INSTALL_DIR@/@LIBSSH_THREADS_LIBRARY_NAME@)
|
||||
|
||||
mark_as_advanced(LIBSSH_LIBRARIES LIBSSH_INCLUDE_DIR)
|
||||
mark_as_advanced(LIBSSH_LIBRARIES LIBSSH_LIBRARY LIBSSH_INCLUDE_DIR)
|
||||
|
||||
@@ -48,7 +48,7 @@ if (MBEDTLS_CRYPTO_LIBRARY)
|
||||
)
|
||||
endif (MBEDTLS_CRYPTO_LIBRARY)
|
||||
|
||||
if (GCRYPT_LIBRARY)
|
||||
if (GCRYPT_LIBRARIES)
|
||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
||||
${GCRYPT_INCLUDE_DIR}
|
||||
@@ -56,9 +56,8 @@ if (GCRYPT_LIBRARY)
|
||||
|
||||
set(LIBSSH_LINK_LIBRARIES
|
||||
${LIBSSH_LINK_LIBRARIES}
|
||||
${GCRYPT_LIBRARY}
|
||||
)
|
||||
endif (GCRYPT_LIBRARY)
|
||||
${GCRYPT_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if (WITH_ZLIB)
|
||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||
@@ -165,6 +164,12 @@ set(libssh_SRCS
|
||||
chachapoly.c
|
||||
)
|
||||
|
||||
if (DEFAULT_C_NO_DEPRECATION_FLAGS)
|
||||
set_source_files_properties(known_hosts.c
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS ${DEFAULT_C_NO_DEPRECATION_FLAGS})
|
||||
endif()
|
||||
|
||||
if (CMAKE_USE_PTHREADS_INIT)
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
|
||||
39
src/agent.c
39
src/agent.c
@@ -56,33 +56,13 @@
|
||||
#include "libssh/session.h"
|
||||
#include "libssh/poll.h"
|
||||
#include "libssh/pki.h"
|
||||
#include "libssh/bytearray.h"
|
||||
|
||||
/* macro to check for "agent failure" message */
|
||||
#define agent_failed(x) \
|
||||
(((x) == SSH_AGENT_FAILURE) || ((x) == SSH_COM_AGENT2_FAILURE) || \
|
||||
((x) == SSH2_AGENT_FAILURE))
|
||||
|
||||
static uint32_t agent_get_u32(const void *vp) {
|
||||
const uint8_t *p = (const uint8_t *)vp;
|
||||
uint32_t v;
|
||||
|
||||
v = (uint32_t)p[0] << 24;
|
||||
v |= (uint32_t)p[1] << 16;
|
||||
v |= (uint32_t)p[2] << 8;
|
||||
v |= (uint32_t)p[3];
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static void agent_put_u32(void *vp, uint32_t v) {
|
||||
uint8_t *p = (uint8_t *)vp;
|
||||
|
||||
p[0] = (uint8_t)(v >> 24) & 0xff;
|
||||
p[1] = (uint8_t)(v >> 16) & 0xff;
|
||||
p[2] = (uint8_t)(v >> 8) & 0xff;
|
||||
p[3] = (uint8_t)v & 0xff;
|
||||
}
|
||||
|
||||
static size_t atomicio(struct ssh_agent_struct *agent, void *buf, size_t n, int do_read) {
|
||||
char *b = buf;
|
||||
size_t pos = 0;
|
||||
@@ -275,7 +255,7 @@ static int agent_talk(struct ssh_session_struct *session,
|
||||
|
||||
len = ssh_buffer_get_len(request);
|
||||
SSH_LOG(SSH_LOG_TRACE, "Request length: %u", len);
|
||||
agent_put_u32(payload, len);
|
||||
PUSH_BE_U32(payload, 0, len);
|
||||
|
||||
/* send length and then the request packet */
|
||||
if (atomicio(session->agent, payload, 4, 0) == 4) {
|
||||
@@ -299,7 +279,7 @@ static int agent_talk(struct ssh_session_struct *session,
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = agent_get_u32(payload);
|
||||
len = PULL_BE_U32(payload, 0);
|
||||
if (len > 256 * 1024) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Authentication response too long: %u", len);
|
||||
@@ -331,7 +311,7 @@ int ssh_agent_get_ident_count(struct ssh_session_struct *session) {
|
||||
ssh_buffer request = NULL;
|
||||
ssh_buffer reply = NULL;
|
||||
unsigned int type = 0;
|
||||
uint32_t buf[1] = {0};
|
||||
uint32_t count = 0;
|
||||
int rc;
|
||||
|
||||
/* send message to the agent requesting the list of identities */
|
||||
@@ -386,8 +366,15 @@ int ssh_agent_get_ident_count(struct ssh_session_struct *session) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssh_buffer_get_u32(reply, (uint32_t *) buf);
|
||||
session->agent->count = agent_get_u32(buf);
|
||||
rc = ssh_buffer_get_u32(reply, &count);
|
||||
if (rc != 4) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Failed to read count");
|
||||
ssh_buffer_free(reply);
|
||||
return -1;
|
||||
}
|
||||
session->agent->count = ntohl(count);
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Agent count: %d",
|
||||
session->agent->count);
|
||||
if (session->agent->count > 1024) {
|
||||
|
||||
10
src/bignum.c
10
src/bignum.c
@@ -69,7 +69,7 @@ ssh_string ssh_make_bignum_string(bignum num) {
|
||||
|
||||
bignum ssh_make_string_bn(ssh_string string){
|
||||
bignum bn = NULL;
|
||||
unsigned int len = ssh_string_len(string);
|
||||
size_t len = ssh_string_len(string);
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
fprintf(stderr, "Importing a %d bits, %d bytes object ...\n",
|
||||
@@ -88,12 +88,12 @@ bignum ssh_make_string_bn(ssh_string string){
|
||||
return bn;
|
||||
}
|
||||
|
||||
void ssh_make_string_bn_inplace(ssh_string string, bignum bnout) {
|
||||
unsigned int len = ssh_string_len(string);
|
||||
void ssh_make_string_bn_inplace(ssh_string string,
|
||||
UNUSED_PARAM(bignum bnout))
|
||||
{
|
||||
UNUSED_VAR(size_t len) = ssh_string_len(string);
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
/* XXX: FIXME as needed for LIBGCRYPT ECDSA codepaths. */
|
||||
(void) len;
|
||||
(void) bnout;
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
bignum_bin2bn(string->data, len, bnout);
|
||||
#elif defined HAVE_LIBMBEDCRYPTO
|
||||
|
||||
40
src/buffer.c
40
src/buffer.c
@@ -809,20 +809,20 @@ ssh_buffer_get_ssh_string(struct ssh_buffer_struct *buffer)
|
||||
*/
|
||||
static int ssh_buffer_pack_allocate_va(struct ssh_buffer_struct *buffer,
|
||||
const char *format,
|
||||
int argc,
|
||||
size_t argc,
|
||||
va_list ap)
|
||||
{
|
||||
const char *p = NULL;
|
||||
ssh_string string = NULL;
|
||||
char *cstring = NULL;
|
||||
size_t needed_size = 0;
|
||||
size_t count;
|
||||
size_t len;
|
||||
size_t count;
|
||||
int rc = SSH_OK;
|
||||
|
||||
for (p = format, count = 0; *p != '\0'; p++, count++) {
|
||||
/* Invalid number of arguments passed */
|
||||
if (argc != -1 && count > argc) {
|
||||
if (count > argc) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
@@ -881,7 +881,7 @@ static int ssh_buffer_pack_allocate_va(struct ssh_buffer_struct *buffer,
|
||||
}
|
||||
}
|
||||
|
||||
if (argc != -1 && argc != count) {
|
||||
if (argc != count) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
@@ -891,11 +891,7 @@ static int ssh_buffer_pack_allocate_va(struct ssh_buffer_struct *buffer,
|
||||
*/
|
||||
uint32_t canary = va_arg(ap, uint32_t);
|
||||
if (canary != SSH_BUFFER_PACK_END) {
|
||||
if (argc == -1){
|
||||
return SSH_ERROR;
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -918,7 +914,7 @@ static int ssh_buffer_pack_allocate_va(struct ssh_buffer_struct *buffer,
|
||||
*/
|
||||
int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
|
||||
const char *format,
|
||||
int argc,
|
||||
size_t argc,
|
||||
va_list ap)
|
||||
{
|
||||
int rc = SSH_ERROR;
|
||||
@@ -934,11 +930,15 @@ int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
|
||||
char *cstring;
|
||||
bignum b;
|
||||
size_t len;
|
||||
int count;
|
||||
size_t count;
|
||||
|
||||
if (argc > 256) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
for (p = format, count = 0; *p != '\0'; p++, count++) {
|
||||
/* Invalid number of arguments passed */
|
||||
if (argc != -1 && count > argc) {
|
||||
if (count > argc) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
@@ -1010,7 +1010,7 @@ int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
|
||||
}
|
||||
}
|
||||
|
||||
if (argc != -1 && argc != count) {
|
||||
if (argc != count) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
@@ -1018,11 +1018,7 @@ int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
|
||||
/* Check if our canary is intact, if not somthing really bad happened */
|
||||
uint32_t canary = va_arg(ap, uint32_t);
|
||||
if (canary != SSH_BUFFER_PACK_END) {
|
||||
if (argc == -1){
|
||||
return SSH_ERROR;
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
abort();
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
@@ -1050,12 +1046,16 @@ int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
|
||||
*/
|
||||
int _ssh_buffer_pack(struct ssh_buffer_struct *buffer,
|
||||
const char *format,
|
||||
int argc,
|
||||
size_t argc,
|
||||
...)
|
||||
{
|
||||
va_list ap;
|
||||
int rc;
|
||||
|
||||
if (argc > 256) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
va_start(ap, argc);
|
||||
rc = ssh_buffer_pack_allocate_va(buffer, format, argc, ap);
|
||||
va_end(ap);
|
||||
@@ -1098,7 +1098,7 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||
} o;
|
||||
size_t len, rlen, max_len;
|
||||
va_list ap_copy;
|
||||
int count;
|
||||
int count; /* int for size comparison with argc */
|
||||
|
||||
max_len = ssh_buffer_get_len(buffer);
|
||||
|
||||
|
||||
@@ -192,6 +192,7 @@ static void chacha20_cleanup(struct ssh_cipher_struct *cipher) {
|
||||
}
|
||||
|
||||
const struct ssh_cipher_struct chacha20poly1305_cipher = {
|
||||
.ciphertype = SSH_AEAD_CHACHA20_POLY1305,
|
||||
.name = "chacha20-poly1305@openssh.com",
|
||||
.blocksize = 8,
|
||||
.lenfield_blocksize = 4,
|
||||
|
||||
@@ -683,6 +683,10 @@ SSH_PACKET_CALLBACK(channel_rcv_request) {
|
||||
if (strcmp(request,"exit-status") == 0) {
|
||||
SAFE_FREE(request);
|
||||
rc = ssh_buffer_unpack(packet, "d", &channel->exit_status);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_PACKET, "Invalid exit-status packet");
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_PACKET, "received exit-status %d", channel->exit_status);
|
||||
|
||||
ssh_callbacks_execute_list(channel->callbacks,
|
||||
@@ -1076,43 +1080,47 @@ void ssh_channel_do_free(ssh_channel channel)
|
||||
* @see ssh_channel_free()
|
||||
* @see ssh_channel_is_eof()
|
||||
*/
|
||||
int ssh_channel_send_eof(ssh_channel channel){
|
||||
ssh_session session;
|
||||
int rc = SSH_ERROR;
|
||||
int err;
|
||||
int ssh_channel_send_eof(ssh_channel channel)
|
||||
{
|
||||
ssh_session session;
|
||||
int rc = SSH_ERROR;
|
||||
int err;
|
||||
|
||||
if(channel == NULL) {
|
||||
return rc;
|
||||
}
|
||||
if(channel == NULL) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
session = channel->session;
|
||||
session = channel->session;
|
||||
|
||||
err = ssh_buffer_pack(session->out_buffer,
|
||||
"bd",
|
||||
SSH2_MSG_CHANNEL_EOF,
|
||||
channel->remote_channel);
|
||||
if (err != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
err = ssh_buffer_pack(session->out_buffer,
|
||||
"bd",
|
||||
SSH2_MSG_CHANNEL_EOF,
|
||||
channel->remote_channel);
|
||||
if (err != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_packet_send(session);
|
||||
SSH_LOG(SSH_LOG_PACKET,
|
||||
"Sent a EOF on client channel (%d:%d)",
|
||||
channel->local_channel,
|
||||
channel->remote_channel);
|
||||
rc = ssh_packet_send(session);
|
||||
SSH_LOG(SSH_LOG_PACKET,
|
||||
"Sent a EOF on client channel (%d:%d)",
|
||||
channel->local_channel,
|
||||
channel->remote_channel);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_channel_flush(channel);
|
||||
if(rc == SSH_ERROR)
|
||||
goto error;
|
||||
rc = ssh_channel_flush(channel);
|
||||
if (rc == SSH_ERROR) {
|
||||
goto error;
|
||||
}
|
||||
channel->local_eof = 1;
|
||||
|
||||
channel->local_eof = 1;
|
||||
|
||||
return rc;
|
||||
return rc;
|
||||
error:
|
||||
ssh_buffer_reinit(session->out_buffer);
|
||||
ssh_buffer_reinit(session->out_buffer);
|
||||
|
||||
return rc;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2082,8 +2090,11 @@ static int ssh_global_request_termination(void *s){
|
||||
* SSH_AGAIN if in nonblocking mode and call has
|
||||
* to be done again.
|
||||
*/
|
||||
static int global_request(ssh_session session, const char *request,
|
||||
ssh_buffer buffer, int reply) {
|
||||
int ssh_global_request(ssh_session session,
|
||||
const char *request,
|
||||
ssh_buffer buffer,
|
||||
int reply)
|
||||
{
|
||||
int rc;
|
||||
|
||||
switch (session->global_req_state) {
|
||||
@@ -2214,7 +2225,7 @@ int ssh_channel_listen_forward(ssh_session session,
|
||||
goto error;
|
||||
}
|
||||
pending:
|
||||
rc = global_request(session, "tcpip-forward", buffer, 1);
|
||||
rc = ssh_global_request(session, "tcpip-forward", buffer, 1);
|
||||
|
||||
/* TODO: FIXME no guarantee the last packet we received contains
|
||||
* that info */
|
||||
@@ -2294,7 +2305,7 @@ int ssh_channel_cancel_forward(ssh_session session,
|
||||
goto error;
|
||||
}
|
||||
pending:
|
||||
rc = global_request(session, "cancel-tcpip-forward", buffer, 1);
|
||||
rc = ssh_global_request(session, "cancel-tcpip-forward", buffer, 1);
|
||||
|
||||
error:
|
||||
ssh_buffer_free(buffer);
|
||||
@@ -2740,7 +2751,7 @@ int ssh_channel_read_timeout(ssh_channel channel,
|
||||
ctx.buffer = stdbuf;
|
||||
ctx.count = 1;
|
||||
|
||||
if (timeout_ms < 0) {
|
||||
if (timeout_ms < SSH_TIMEOUT_DEFAULT) {
|
||||
timeout_ms = SSH_TIMEOUT_INFINITE;
|
||||
}
|
||||
|
||||
@@ -2755,8 +2766,13 @@ int ssh_channel_read_timeout(ssh_channel channel,
|
||||
/*
|
||||
* If the channel is closed or in an error state, reading from it is an error
|
||||
*/
|
||||
if (session->session_state == SSH_SESSION_STATE_ERROR ||
|
||||
channel->state == SSH_CHANNEL_STATE_CLOSED) {
|
||||
if (session->session_state == SSH_SESSION_STATE_ERROR) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (channel->state == SSH_CHANNEL_STATE_CLOSED) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Remote channel is closed.");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (channel->remote_eof && ssh_buffer_get_len(stdbuf) == 0) {
|
||||
|
||||
15
src/client.c
15
src/client.c
@@ -180,7 +180,6 @@ int ssh_send_banner(ssh_session session, int server)
|
||||
|
||||
if (server == 1) {
|
||||
if (session->opts.custombanner == NULL){
|
||||
len = strlen(banner);
|
||||
session->serverbanner = strdup(banner);
|
||||
if (session->serverbanner == NULL) {
|
||||
goto end;
|
||||
@@ -494,8 +493,8 @@ static int ssh_connect_termination(void *user){
|
||||
* @param[in] session The ssh session to connect.
|
||||
*
|
||||
* @returns SSH_OK on success, SSH_ERROR on error.
|
||||
* @returns SSH_AGAIN, if the session is in nonblocking mode,
|
||||
* and call must be done again.
|
||||
* @returns SSH_AGAIN, if the session is in nonblocking mode,
|
||||
* and call must be done again.
|
||||
*
|
||||
* @see ssh_new()
|
||||
* @see ssh_disconnect()
|
||||
@@ -527,6 +526,16 @@ int ssh_connect(ssh_session session) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* If the system configuration files were not yet processed, do it now */
|
||||
if (!session->opts.config_processed) {
|
||||
ret = ssh_options_parse_config(session, NULL);
|
||||
if (ret != 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to process system configuration files");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ssh_options_apply(session);
|
||||
if (ret < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Couldn't apply options");
|
||||
|
||||
164
src/config.c
164
src/config.c
@@ -32,6 +32,7 @@
|
||||
#endif
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "libssh/config.h"
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
#include "libssh/misc.h"
|
||||
@@ -39,45 +40,6 @@
|
||||
|
||||
#define MAX_LINE_SIZE 1024
|
||||
|
||||
enum ssh_config_opcode_e {
|
||||
/* Unknown opcode */
|
||||
SOC_UNKNOWN = -3,
|
||||
/* Known and not applicable to libssh */
|
||||
SOC_NA = -2,
|
||||
/* Known but not supported by current libssh version */
|
||||
SOC_UNSUPPORTED = -1,
|
||||
SOC_HOST,
|
||||
SOC_MATCH,
|
||||
SOC_HOSTNAME,
|
||||
SOC_PORT,
|
||||
SOC_USERNAME,
|
||||
SOC_IDENTITY,
|
||||
SOC_CIPHERS,
|
||||
SOC_MACS,
|
||||
SOC_COMPRESSION,
|
||||
SOC_TIMEOUT,
|
||||
SOC_PROTOCOL,
|
||||
SOC_STRICTHOSTKEYCHECK,
|
||||
SOC_KNOWNHOSTS,
|
||||
SOC_PROXYCOMMAND,
|
||||
SOC_GSSAPISERVERIDENTITY,
|
||||
SOC_GSSAPICLIENTIDENTITY,
|
||||
SOC_GSSAPIDELEGATECREDENTIALS,
|
||||
SOC_INCLUDE,
|
||||
SOC_BINDADDRESS,
|
||||
SOC_GLOBALKNOWNHOSTSFILE,
|
||||
SOC_LOGLEVEL,
|
||||
SOC_HOSTKEYALGORITHMS,
|
||||
SOC_KEXALGORITHMS,
|
||||
SOC_GSSAPIAUTHENTICATION,
|
||||
SOC_KBDINTERACTIVEAUTHENTICATION,
|
||||
SOC_PASSWORDAUTHENTICATION,
|
||||
SOC_PUBKEYAUTHENTICATION,
|
||||
SOC_PUBKEYACCEPTEDTYPES,
|
||||
|
||||
SOC_END /* Keep this one last in the list */
|
||||
};
|
||||
|
||||
struct ssh_config_keyword_table_s {
|
||||
const char *name;
|
||||
enum ssh_config_opcode_e opcode;
|
||||
@@ -213,7 +175,7 @@ static struct ssh_config_match_keyword_table_s ssh_config_match_keyword_table[]
|
||||
};
|
||||
|
||||
static int ssh_config_parse_line(ssh_session session, const char *line,
|
||||
unsigned int count, int *parsing, int seen[]);
|
||||
unsigned int count, int *parsing);
|
||||
|
||||
static enum ssh_config_opcode_e ssh_config_get_opcode(char *keyword) {
|
||||
int i;
|
||||
@@ -323,35 +285,41 @@ static int ssh_config_get_yesno(char **str, int notfound) {
|
||||
return notfound;
|
||||
}
|
||||
|
||||
static void local_parse_file(ssh_session session, const char *filename, int *parsing, int seen[]) {
|
||||
FILE *f;
|
||||
char line[MAX_LINE_SIZE] = {0};
|
||||
unsigned int count = 0;
|
||||
static void
|
||||
local_parse_file(ssh_session session,
|
||||
const char *filename,
|
||||
int *parsing)
|
||||
{
|
||||
FILE *f;
|
||||
char line[MAX_LINE_SIZE] = {0};
|
||||
unsigned int count = 0;
|
||||
int rv;
|
||||
|
||||
if ((f = fopen(filename, "r")) == NULL) {
|
||||
SSH_LOG(SSH_LOG_RARE, "Cannot find file %s to load",
|
||||
filename);
|
||||
return;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET, "Reading additional configuration data from %s", filename);
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
count++;
|
||||
if (ssh_config_parse_line(session, line, count, parsing, seen) < 0) {
|
||||
fclose(f);
|
||||
return;
|
||||
f = fopen(filename, "r");
|
||||
if (f == NULL) {
|
||||
SSH_LOG(SSH_LOG_RARE, "Cannot find file %s to load",
|
||||
filename);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return;
|
||||
SSH_LOG(SSH_LOG_PACKET, "Reading additional configuration data from %s", filename);
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
count++;
|
||||
rv = ssh_config_parse_line(session, line, count, parsing);
|
||||
if (rv < 0) {
|
||||
fclose(f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(HAVE_GLOB) && defined(HAVE_GLOB_GL_FLAGS_MEMBER)
|
||||
static void local_parse_glob(ssh_session session,
|
||||
const char *fileglob,
|
||||
int *parsing,
|
||||
int seen[])
|
||||
int *parsing)
|
||||
{
|
||||
glob_t globbuf = {
|
||||
.gl_flags = 0,
|
||||
@@ -371,7 +339,7 @@ static void local_parse_glob(ssh_session session,
|
||||
}
|
||||
|
||||
for (i = 0; i < globbuf.gl_pathc; i++) {
|
||||
local_parse_file(session, globbuf.gl_pathv[i], parsing, seen);
|
||||
local_parse_file(session, globbuf.gl_pathv[i], parsing);
|
||||
}
|
||||
|
||||
globfree(&globbuf);
|
||||
@@ -412,8 +380,12 @@ ssh_config_match(char *value, const char *pattern, bool negate)
|
||||
return result;
|
||||
}
|
||||
|
||||
static int ssh_config_parse_line(ssh_session session, const char *line,
|
||||
unsigned int count, int *parsing, int seen[]) {
|
||||
static int
|
||||
ssh_config_parse_line(ssh_session session,
|
||||
const char *line,
|
||||
unsigned int count,
|
||||
int *parsing)
|
||||
{
|
||||
enum ssh_config_opcode_e opcode;
|
||||
const char *p;
|
||||
char *s, *x;
|
||||
@@ -421,6 +393,7 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
||||
char *lowerhost;
|
||||
size_t len;
|
||||
int i;
|
||||
uint8_t *seen = session->opts.options_seen;
|
||||
long l;
|
||||
|
||||
x = s = strdup(line);
|
||||
@@ -450,6 +423,7 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
||||
opcode != SOC_MATCH &&
|
||||
opcode != SOC_INCLUDE &&
|
||||
opcode > SOC_UNSUPPORTED) { /* Ignore all unknown types here */
|
||||
/* Skip all the options that were already applied */
|
||||
if (seen[opcode] != 0) {
|
||||
SAFE_FREE(x);
|
||||
return 0;
|
||||
@@ -463,9 +437,9 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
#if defined(HAVE_GLOB) && defined(HAVE_GLOB_GL_FLAGS_MEMBER)
|
||||
local_parse_glob(session, p, parsing, seen);
|
||||
local_parse_glob(session, p, parsing);
|
||||
#else
|
||||
local_parse_file(session, p, parsing, seen);
|
||||
local_parse_file(session, p, parsing);
|
||||
#endif /* HAVE_GLOB */
|
||||
}
|
||||
break;
|
||||
@@ -506,7 +480,7 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
||||
}
|
||||
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"line %d: ERROR - Match all can not be combined with "
|
||||
"line %d: ERROR - Match all cannot be combined with "
|
||||
"other Match attributes", count);
|
||||
SAFE_FREE(x);
|
||||
return -1;
|
||||
@@ -798,7 +772,7 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
||||
}
|
||||
break;
|
||||
case SOC_NA:
|
||||
SSH_LOG(SSH_LOG_INFO, "Unapplicable option: %s, line: %d\n",
|
||||
SSH_LOG(SSH_LOG_INFO, "Unapplicable option: %s, line: %d",
|
||||
keyword, count);
|
||||
break;
|
||||
case SOC_UNSUPPORTED:
|
||||
@@ -806,7 +780,7 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
||||
keyword, count);
|
||||
break;
|
||||
case SOC_UNKNOWN:
|
||||
SSH_LOG(SSH_LOG_WARN, "Unknown option: %s, line: %d\n",
|
||||
SSH_LOG(SSH_LOG_WARN, "Unknown option: %s, line: %d",
|
||||
keyword, count);
|
||||
break;
|
||||
default:
|
||||
@@ -821,29 +795,37 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ssh_config_parse_file */
|
||||
int ssh_config_parse_file(ssh_session session, const char *filename) {
|
||||
char line[MAX_LINE_SIZE] = {0};
|
||||
unsigned int count = 0;
|
||||
FILE *f;
|
||||
int parsing;
|
||||
int seen[SOC_END - SOC_UNSUPPORTED] = {0};
|
||||
/* @brief Parse configuration file and set the options to the given session
|
||||
*
|
||||
* @params[in] session The ssh session
|
||||
* @params[in] filename The path to the ssh configuration file
|
||||
*
|
||||
* @returns 0 on successful parsing the configuration file, -1 on error
|
||||
*/
|
||||
int ssh_config_parse_file(ssh_session session, const char *filename)
|
||||
{
|
||||
char line[MAX_LINE_SIZE] = {0};
|
||||
unsigned int count = 0;
|
||||
FILE *f;
|
||||
int parsing, rv;
|
||||
|
||||
if ((f = fopen(filename, "r")) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET, "Reading configuration data from %s", filename);
|
||||
|
||||
parsing = 1;
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
count++;
|
||||
if (ssh_config_parse_line(session, line, count, &parsing, seen) < 0) {
|
||||
fclose(f);
|
||||
return -1;
|
||||
f = fopen(filename, "r");
|
||||
if (f == NULL) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return 0;
|
||||
SSH_LOG(SSH_LOG_PACKET, "Reading configuration data from %s", filename);
|
||||
|
||||
parsing = 1;
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
count++;
|
||||
rv = ssh_config_parse_line(session, line, count, &parsing);
|
||||
if (rv < 0) {
|
||||
fclose(f);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -476,7 +476,7 @@ int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
|
||||
fd_set *readfds, struct timeval *timeout) {
|
||||
fd_set origfds;
|
||||
socket_t fd;
|
||||
int i,j;
|
||||
size_t i, j;
|
||||
int rc;
|
||||
int base_tm, tm;
|
||||
struct ssh_timestamp ts;
|
||||
@@ -488,6 +488,7 @@ int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
|
||||
ssh_event_add_session(event, channels[i]->session);
|
||||
}
|
||||
|
||||
ZERO_STRUCT(origfds);
|
||||
FD_ZERO(&origfds);
|
||||
for (fd = 0; fd < maxfd ; fd++) {
|
||||
if (FD_ISSET(fd, readfds)) {
|
||||
|
||||
@@ -286,7 +286,7 @@ int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet) {
|
||||
session->next_crypto->ecdh_client_pubkey = q_c_string;
|
||||
|
||||
/* Build server's keypair */
|
||||
err = gcry_sexp_build(¶m, NULL, "(genkey(ecdh(curve %s)))",
|
||||
err = gcry_sexp_build(¶m, NULL, "(genkey(ecdh(curve %s) (flags transient-key)))",
|
||||
curve);
|
||||
if (err) {
|
||||
goto out;
|
||||
|
||||
13
src/gssapi.c
13
src/gssapi.c
@@ -172,10 +172,10 @@ static void ssh_gssapi_log_error(int verb,
|
||||
|
||||
out:
|
||||
if (msg_maj.value) {
|
||||
dummy_maj = gss_release_buffer(&dummy_min, &msg_maj);
|
||||
gss_release_buffer(&dummy_min, &msg_maj);
|
||||
}
|
||||
if (msg_min.value) {
|
||||
dummy_maj = gss_release_buffer(&dummy_min, &msg_min);
|
||||
gss_release_buffer(&dummy_min, &msg_min);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,6 +217,15 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n
|
||||
gss_create_empty_oid_set(&min_stat, &both_supported);
|
||||
|
||||
maj_stat = gss_indicate_mechs(&min_stat, &supported);
|
||||
if (maj_stat != GSS_S_COMPLETE) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "indicate mecks %d, %d", maj_stat, min_stat);
|
||||
ssh_gssapi_log_error(SSH_LOG_WARNING,
|
||||
"indicate mechs",
|
||||
maj_stat,
|
||||
min_stat);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
for (i=0; i < supported->count; ++i){
|
||||
ptr = ssh_get_hexa(supported->elements[i].elements, supported->elements[i].length);
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Supported mech %zu: %s", i, ptr);
|
||||
|
||||
@@ -143,7 +143,7 @@ void libssh_constructor(void)
|
||||
* If the library is already initialized, increments the _ssh_initialized
|
||||
* counter and return the error code cached in _ssh_init_ret.
|
||||
*
|
||||
* @returns 0 on success, -1 if an error occured.
|
||||
* @returns SSH_OK on success, SSH_ERROR if an error occurred.
|
||||
*/
|
||||
int ssh_init(void) {
|
||||
return _ssh_init(0);
|
||||
@@ -188,7 +188,7 @@ _ret:
|
||||
*
|
||||
* This function is automatically called when the library is unloaded.
|
||||
*
|
||||
* @returns 0 on succes, -1 if an error occured.
|
||||
* @returns SSH_OK on success, SSH_ERROR if an error occurred.
|
||||
*
|
||||
*/
|
||||
void libssh_destructor(void)
|
||||
|
||||
35
src/kex.c
35
src/kex.c
@@ -41,13 +41,21 @@
|
||||
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
# define BLOWFISH "blowfish-cbc,"
|
||||
# define AES "aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,"
|
||||
# define AES "aes256-gcm@openssh.com,aes128-gcm@openssh.com," \
|
||||
"aes256-ctr,aes192-ctr,aes128-ctr," \
|
||||
"aes256-cbc,aes192-cbc,aes128-cbc,"
|
||||
# define DES "3des-cbc"
|
||||
# define DES_SUPPORTED "3des-cbc"
|
||||
|
||||
#elif defined HAVE_LIBMBEDCRYPTO
|
||||
# define BLOWFISH "blowfish-cbc,"
|
||||
# define AES "aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,"
|
||||
# ifdef MBEDTLS_GCM_C
|
||||
# define GCM "aes256-gcm@openssh.com,aes128-gcm@openssh.com,"
|
||||
# else
|
||||
# define GCM ""
|
||||
# endif /* MBEDTLS_GCM_C */
|
||||
# define AES GCM "aes256-ctr,aes192-ctr,aes128-ctr," \
|
||||
"aes256-cbc,aes192-cbc,aes128-cbc,"
|
||||
# define DES "3des-cbc"
|
||||
# define DES_SUPPORTED "3des-cbc"
|
||||
|
||||
@@ -60,10 +68,15 @@
|
||||
# endif /* HAVE_OPENSSL_BLOWFISH_H */
|
||||
|
||||
# ifdef HAVE_OPENSSL_AES_H
|
||||
# ifdef HAVE_OPENSSL_EVP_AES_GCM
|
||||
# define GCM "aes256-gcm@openssh.com,aes128-gcm@openssh.com,"
|
||||
# else
|
||||
# define GCM ""
|
||||
# endif /* HAVE_OPENSSL_EVP_AES_GCM */
|
||||
# ifdef BROKEN_AES_CTR
|
||||
# define AES "aes256-cbc,aes192-cbc,aes128-cbc,"
|
||||
# define AES GCM "aes256-cbc,aes192-cbc,aes128-cbc,"
|
||||
# else /* BROKEN_AES_CTR */
|
||||
# define AES "aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,"
|
||||
# define AES GCM "aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,"
|
||||
# endif /* BROKEN_AES_CTR */
|
||||
# else /* HAVE_OPENSSL_AES_H */
|
||||
# define AES ""
|
||||
@@ -415,9 +428,10 @@ out:
|
||||
return is_wrong;
|
||||
}
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_kexinit){
|
||||
SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
{
|
||||
int i, ok;
|
||||
int server_kex=session->server;
|
||||
int server_kex = session->server;
|
||||
ssh_string str = NULL;
|
||||
char *strings[KEX_METHODS_SIZE] = {0};
|
||||
int rc = SSH_ERROR;
|
||||
@@ -428,9 +442,9 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit){
|
||||
(void)type;
|
||||
(void)user;
|
||||
|
||||
if (session->session_state == SSH_SESSION_STATE_AUTHENTICATED){
|
||||
if (session->session_state == SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "Other side initiating key re-exchange");
|
||||
} else if(session->session_state != SSH_SESSION_STATE_INITIAL_KEX){
|
||||
} else if (session->session_state != SSH_SESSION_STATE_INITIAL_KEX) {
|
||||
ssh_set_error(session,SSH_FATAL,"SSH_KEXINIT received in wrong state");
|
||||
goto error;
|
||||
}
|
||||
@@ -729,6 +743,11 @@ int ssh_set_client_kex(ssh_session session)
|
||||
}
|
||||
}
|
||||
|
||||
/* For rekeying, skip the extension negotiation */
|
||||
if (session->session_state == SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/* Here we append ext-info-c to the list of kex algorithms */
|
||||
kex = client->methods[SSH_KEX];
|
||||
len = strlen(kex);
|
||||
|
||||
@@ -306,7 +306,8 @@ struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session)
|
||||
int list_error = 0;
|
||||
int rc;
|
||||
|
||||
if (session->opts.knownhosts == NULL) {
|
||||
if (session->opts.knownhosts == NULL ||
|
||||
session->opts.global_knownhosts == NULL) {
|
||||
if (ssh_options_apply(session) < 0) {
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
@@ -882,6 +883,9 @@ ssh_session_get_known_hosts_entry(ssh_session session,
|
||||
|
||||
/* If we did not find any match at all: we report the previous result */
|
||||
if (rv == SSH_KNOWN_HOSTS_UNKNOWN) {
|
||||
if (session->opts.StrictHostKeyChecking == 0) {
|
||||
return SSH_KNOWN_HOSTS_OK;
|
||||
}
|
||||
return old_rv;
|
||||
}
|
||||
|
||||
|
||||
@@ -545,6 +545,10 @@ ssh_string publickey_to_string(ssh_public_key pubkey) {
|
||||
ssh_string key_blob;
|
||||
int rc;
|
||||
|
||||
if (pubkey == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
key = ssh_key_new();
|
||||
if (key == NULL) {
|
||||
return NULL;
|
||||
|
||||
@@ -10,9 +10,12 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/engine.h>
|
||||
#include "libcrypto-compat.h"
|
||||
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
#include <openssl/engine.h>
|
||||
#endif
|
||||
|
||||
static void *OPENSSL_zalloc(size_t num)
|
||||
{
|
||||
void *ret = OPENSSL_malloc(num);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
|
||||
int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q);
|
||||
|
||||
321
src/libcrypto.c
321
src/libcrypto.c
@@ -58,6 +58,11 @@
|
||||
#define OLD_CRYPTO
|
||||
#endif
|
||||
|
||||
#if (defined(HAVE_VALGRIND_VALGRIND_H) && defined(HAVE_OPENSSL_IA32CAP_LOC))
|
||||
#include <valgrind/valgrind.h>
|
||||
#define CAN_DISABLE_AESNI
|
||||
#endif
|
||||
|
||||
#include "libssh/crypto.h"
|
||||
|
||||
struct ssh_mac_ctx_struct {
|
||||
@@ -438,7 +443,6 @@ HMACCTX hmac_init(const void *key, int len, enum ssh_hmac_e type) {
|
||||
break;
|
||||
default:
|
||||
HMAC_CTX_free(ctx);
|
||||
SAFE_FREE(ctx);
|
||||
ctx = NULL;
|
||||
}
|
||||
|
||||
@@ -494,6 +498,19 @@ static void evp_cipher_init(struct ssh_cipher_struct *cipher) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "This cipher is not available in evp_cipher_init");
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL_EVP_AES_GCM
|
||||
case SSH_AEAD_AES128_GCM:
|
||||
cipher->cipher = EVP_aes_128_gcm();
|
||||
break;
|
||||
case SSH_AEAD_AES256_GCM:
|
||||
cipher->cipher = EVP_aes_256_gcm();
|
||||
break;
|
||||
#else
|
||||
case SSH_AEAD_AES128_GCM:
|
||||
case SSH_AEAD_AES256_GCM:
|
||||
SSH_LOG(SSH_LOG_WARNING, "This cipher is not available in evp_cipher_init");
|
||||
break;
|
||||
#endif /* HAVE_OPENSSL_EVP_AES_GCM */
|
||||
case SSH_3DES_CBC:
|
||||
cipher->cipher = EVP_des_ede3_cbc();
|
||||
break;
|
||||
@@ -501,6 +518,9 @@ static void evp_cipher_init(struct ssh_cipher_struct *cipher) {
|
||||
cipher->cipher = EVP_bf_cbc();
|
||||
break;
|
||||
/* ciphers not using EVP */
|
||||
case SSH_AEAD_CHACHA20_POLY1305:
|
||||
SSH_LOG(SSH_LOG_WARNING, "The ChaCha cipher cannot be handled here");
|
||||
break;
|
||||
case SSH_NO_CIPHER:
|
||||
SSH_LOG(SSH_LOG_WARNING, "No valid ciphertype found");
|
||||
break;
|
||||
@@ -520,6 +540,22 @@ static int evp_cipher_set_encrypt_key(struct ssh_cipher_struct *cipher,
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_EncryptInit_ex failed");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENSSL_EVP_AES_GCM
|
||||
/* For AES-GCM we need to set IV in specific way */
|
||||
if (cipher->ciphertype == SSH_AEAD_AES128_GCM ||
|
||||
cipher->ciphertype == SSH_AEAD_AES256_GCM) {
|
||||
rc = EVP_CIPHER_CTX_ctrl(cipher->ctx,
|
||||
EVP_CTRL_GCM_SET_IV_FIXED,
|
||||
-1,
|
||||
(u_char *)IV);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_SET_IV_FIXED failed");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_OPENSSL_EVP_AES_GCM */
|
||||
|
||||
EVP_CIPHER_CTX_set_padding(cipher->ctx, 0);
|
||||
|
||||
return SSH_OK;
|
||||
@@ -537,6 +573,22 @@ static int evp_cipher_set_decrypt_key(struct ssh_cipher_struct *cipher,
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_DecryptInit_ex failed");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENSSL_EVP_AES_GCM
|
||||
/* For AES-GCM we need to set IV in specific way */
|
||||
if (cipher->ciphertype == SSH_AEAD_AES128_GCM ||
|
||||
cipher->ciphertype == SSH_AEAD_AES256_GCM) {
|
||||
rc = EVP_CIPHER_CTX_ctrl(cipher->ctx,
|
||||
EVP_CTRL_GCM_SET_IV_FIXED,
|
||||
-1,
|
||||
(u_char *)IV);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_SET_IV_FIXED failed");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_OPENSSL_EVP_AES_GCM */
|
||||
|
||||
EVP_CIPHER_CTX_set_padding(cipher->ctx, 0);
|
||||
|
||||
return SSH_OK;
|
||||
@@ -544,20 +596,25 @@ static int evp_cipher_set_decrypt_key(struct ssh_cipher_struct *cipher,
|
||||
|
||||
/* EVP wrapper function for encrypt/decrypt */
|
||||
static void evp_cipher_encrypt(struct ssh_cipher_struct *cipher,
|
||||
void *in,
|
||||
void *out,
|
||||
unsigned long len) {
|
||||
void *in,
|
||||
void *out,
|
||||
size_t len)
|
||||
{
|
||||
int outlen = 0;
|
||||
int rc = 0;
|
||||
|
||||
rc = EVP_EncryptUpdate(cipher->ctx, (unsigned char *)out, &outlen, (unsigned char *)in, len);
|
||||
rc = EVP_EncryptUpdate(cipher->ctx,
|
||||
(unsigned char *)out,
|
||||
&outlen,
|
||||
(unsigned char *)in,
|
||||
(int)len);
|
||||
if (rc != 1){
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_EncryptUpdate failed");
|
||||
return;
|
||||
}
|
||||
if (outlen != (int)len){
|
||||
SSH_LOG(SSH_LOG_WARNING,
|
||||
"EVP_EncryptUpdate: output size %d for %lu in",
|
||||
"EVP_EncryptUpdate: output size %d for %zu in",
|
||||
outlen,
|
||||
len);
|
||||
return;
|
||||
@@ -565,20 +622,25 @@ static void evp_cipher_encrypt(struct ssh_cipher_struct *cipher,
|
||||
}
|
||||
|
||||
static void evp_cipher_decrypt(struct ssh_cipher_struct *cipher,
|
||||
void *in,
|
||||
void *out,
|
||||
unsigned long len) {
|
||||
void *in,
|
||||
void *out,
|
||||
size_t len)
|
||||
{
|
||||
int outlen = 0;
|
||||
int rc = 0;
|
||||
|
||||
rc = EVP_DecryptUpdate(cipher->ctx, (unsigned char *)out, &outlen, (unsigned char *)in, len);
|
||||
rc = EVP_DecryptUpdate(cipher->ctx,
|
||||
(unsigned char *)out,
|
||||
&outlen,
|
||||
(unsigned char *)in,
|
||||
(int)len);
|
||||
if (rc != 1){
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_DecryptUpdate failed");
|
||||
return;
|
||||
}
|
||||
if (outlen != (int)len){
|
||||
SSH_LOG(SSH_LOG_WARNING,
|
||||
"EVP_DecryptUpdate: output size %d for %lu in",
|
||||
"EVP_DecryptUpdate: output size %d for %zu in",
|
||||
outlen,
|
||||
len);
|
||||
return;
|
||||
@@ -645,6 +707,176 @@ static void aes_ctr_cleanup(struct ssh_cipher_struct *cipher){
|
||||
|
||||
#endif /* HAVE_OPENSSL_EVP_AES_CTR */
|
||||
|
||||
#ifdef HAVE_OPENSSL_EVP_AES_GCM
|
||||
static int
|
||||
evp_cipher_aead_get_length(struct ssh_cipher_struct *cipher,
|
||||
void *in,
|
||||
uint8_t *out,
|
||||
size_t len,
|
||||
uint64_t seq)
|
||||
{
|
||||
(void)cipher;
|
||||
(void)seq;
|
||||
|
||||
/* The length is not encrypted: Copy it to the result buffer */
|
||||
memcpy(out, in, len);
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
evp_cipher_aead_encrypt(struct ssh_cipher_struct *cipher,
|
||||
void *in,
|
||||
void *out,
|
||||
size_t len,
|
||||
uint8_t *tag,
|
||||
uint64_t seq)
|
||||
{
|
||||
size_t authlen, aadlen;
|
||||
u_char lastiv[1];
|
||||
int outlen = 0;
|
||||
int rc;
|
||||
|
||||
(void) seq;
|
||||
|
||||
aadlen = cipher->lenfield_blocksize;
|
||||
authlen = cipher->tag_size;
|
||||
|
||||
/* increment IV */
|
||||
rc = EVP_CIPHER_CTX_ctrl(cipher->ctx,
|
||||
EVP_CTRL_GCM_IV_GEN,
|
||||
1,
|
||||
lastiv);
|
||||
if (rc == 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_IV_GEN failed");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Pass over the authenticated data (not encrypted) */
|
||||
rc = EVP_EncryptUpdate(cipher->ctx,
|
||||
NULL,
|
||||
&outlen,
|
||||
(unsigned char *)in,
|
||||
(int)aadlen);
|
||||
if (rc == 0 || outlen != (int)aadlen) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "Failed to pass authenticated data");
|
||||
return;
|
||||
}
|
||||
memcpy(out, in, aadlen);
|
||||
|
||||
/* Encrypt the rest of the data */
|
||||
rc = EVP_EncryptUpdate(cipher->ctx,
|
||||
(unsigned char *)out + aadlen,
|
||||
&outlen,
|
||||
(unsigned char *)in + aadlen,
|
||||
(int)len - aadlen);
|
||||
if (rc != 1 || outlen != (int)len - aadlen) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_EncryptUpdate failed");
|
||||
return;
|
||||
}
|
||||
|
||||
/* compute tag */
|
||||
rc = EVP_EncryptFinal(cipher->ctx,
|
||||
NULL,
|
||||
&outlen);
|
||||
if (rc < 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_EncryptFinal failed: Failed to create a tag");
|
||||
return;
|
||||
}
|
||||
|
||||
rc = EVP_CIPHER_CTX_ctrl(cipher->ctx,
|
||||
EVP_CTRL_GCM_GET_TAG,
|
||||
authlen,
|
||||
(unsigned char *)tag);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_GET_TAG failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
evp_cipher_aead_decrypt(struct ssh_cipher_struct *cipher,
|
||||
void *complete_packet,
|
||||
uint8_t *out,
|
||||
size_t encrypted_size,
|
||||
uint64_t seq)
|
||||
{
|
||||
size_t authlen, aadlen;
|
||||
u_char lastiv[1];
|
||||
int outlen = 0;
|
||||
int rc = 0;
|
||||
|
||||
(void)seq;
|
||||
|
||||
aadlen = cipher->lenfield_blocksize;
|
||||
authlen = cipher->tag_size;
|
||||
|
||||
/* increment IV */
|
||||
rc = EVP_CIPHER_CTX_ctrl(cipher->ctx,
|
||||
EVP_CTRL_GCM_IV_GEN,
|
||||
1,
|
||||
lastiv);
|
||||
if (rc == 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_IV_GEN failed");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* set tag for authentication */
|
||||
rc = EVP_CIPHER_CTX_ctrl(cipher->ctx,
|
||||
EVP_CTRL_GCM_SET_TAG,
|
||||
authlen,
|
||||
(unsigned char *)complete_packet + aadlen + encrypted_size);
|
||||
if (rc == 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_SET_TAG failed");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* Pass over the authenticated data (not encrypted) */
|
||||
rc = EVP_DecryptUpdate(cipher->ctx,
|
||||
NULL,
|
||||
&outlen,
|
||||
(unsigned char *)complete_packet,
|
||||
(int)aadlen);
|
||||
if (rc == 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "Failed to pass authenticated data");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
/* Do not copy the length to the target buffer, because it is already processed */
|
||||
//memcpy(out, complete_packet, aadlen);
|
||||
|
||||
/* Decrypt the rest of the data */
|
||||
rc = EVP_DecryptUpdate(cipher->ctx,
|
||||
(unsigned char *)out,
|
||||
&outlen,
|
||||
(unsigned char *)complete_packet + aadlen,
|
||||
encrypted_size /* already substracted aadlen*/);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_DecryptUpdate failed");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (outlen != (int)encrypted_size) {
|
||||
SSH_LOG(SSH_LOG_WARNING,
|
||||
"EVP_DecryptUpdate: output size %d for %zd in",
|
||||
outlen,
|
||||
encrypted_size);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* verify tag */
|
||||
rc = EVP_DecryptFinal(cipher->ctx,
|
||||
NULL,
|
||||
&outlen);
|
||||
if (rc < 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_DecryptFinal failed: Failed authentication");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
#endif /* HAVE_OPENSSL_EVP_AES_GCM */
|
||||
|
||||
/*
|
||||
* The table of supported ciphers
|
||||
*/
|
||||
@@ -668,7 +900,7 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
|
||||
#ifdef HAVE_OPENSSL_EVP_AES_CTR
|
||||
{
|
||||
.name = "aes128-ctr",
|
||||
.blocksize = 16,
|
||||
.blocksize = AES_BLOCK_SIZE,
|
||||
.ciphertype = SSH_AES128_CTR,
|
||||
.keysize = 128,
|
||||
.set_encrypt_key = evp_cipher_set_encrypt_key,
|
||||
@@ -679,7 +911,7 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
|
||||
},
|
||||
{
|
||||
.name = "aes192-ctr",
|
||||
.blocksize = 16,
|
||||
.blocksize = AES_BLOCK_SIZE,
|
||||
.ciphertype = SSH_AES192_CTR,
|
||||
.keysize = 192,
|
||||
.set_encrypt_key = evp_cipher_set_encrypt_key,
|
||||
@@ -690,7 +922,7 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
|
||||
},
|
||||
{
|
||||
.name = "aes256-ctr",
|
||||
.blocksize = 16,
|
||||
.blocksize = AES_BLOCK_SIZE,
|
||||
.ciphertype = SSH_AES256_CTR,
|
||||
.keysize = 256,
|
||||
.set_encrypt_key = evp_cipher_set_encrypt_key,
|
||||
@@ -702,7 +934,7 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
|
||||
#else /* HAVE_OPENSSL_EVP_AES_CTR */
|
||||
{
|
||||
.name = "aes128-ctr",
|
||||
.blocksize = 16,
|
||||
.blocksize = AES_BLOCK_SIZE,
|
||||
.ciphertype = SSH_AES128_CTR,
|
||||
.keysize = 128,
|
||||
.set_encrypt_key = aes_ctr_set_key,
|
||||
@@ -713,7 +945,7 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
|
||||
},
|
||||
{
|
||||
.name = "aes192-ctr",
|
||||
.blocksize = 16,
|
||||
.blocksize = AES_BLOCK_SIZE,
|
||||
.ciphertype = SSH_AES192_CTR,
|
||||
.keysize = 192,
|
||||
.set_encrypt_key = aes_ctr_set_key,
|
||||
@@ -724,7 +956,7 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
|
||||
},
|
||||
{
|
||||
.name = "aes256-ctr",
|
||||
.blocksize = 16,
|
||||
.blocksize = AES_BLOCK_SIZE,
|
||||
.ciphertype = SSH_AES256_CTR,
|
||||
.keysize = 256,
|
||||
.set_encrypt_key = aes_ctr_set_key,
|
||||
@@ -737,7 +969,7 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
|
||||
#endif /* BROKEN_AES_CTR */
|
||||
{
|
||||
.name = "aes128-cbc",
|
||||
.blocksize = 16,
|
||||
.blocksize = AES_BLOCK_SIZE,
|
||||
.ciphertype = SSH_AES128_CBC,
|
||||
.keysize = 128,
|
||||
.set_encrypt_key = evp_cipher_set_encrypt_key,
|
||||
@@ -748,7 +980,7 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
|
||||
},
|
||||
{
|
||||
.name = "aes192-cbc",
|
||||
.blocksize = 16,
|
||||
.blocksize = AES_BLOCK_SIZE,
|
||||
.ciphertype = SSH_AES192_CBC,
|
||||
.keysize = 192,
|
||||
.set_encrypt_key = evp_cipher_set_encrypt_key,
|
||||
@@ -759,7 +991,7 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
|
||||
},
|
||||
{
|
||||
.name = "aes256-cbc",
|
||||
.blocksize = 16,
|
||||
.blocksize = AES_BLOCK_SIZE,
|
||||
.ciphertype = SSH_AES256_CBC,
|
||||
.keysize = 256,
|
||||
.set_encrypt_key = evp_cipher_set_encrypt_key,
|
||||
@@ -768,6 +1000,36 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
|
||||
.decrypt = evp_cipher_decrypt,
|
||||
.cleanup = evp_cipher_cleanup
|
||||
},
|
||||
#ifdef HAVE_OPENSSL_EVP_AES_GCM
|
||||
{
|
||||
.name = "aes128-gcm@openssh.com",
|
||||
.blocksize = AES_BLOCK_SIZE,
|
||||
.lenfield_blocksize = 4, /* not encrypted, but authenticated */
|
||||
.ciphertype = SSH_AEAD_AES128_GCM,
|
||||
.keysize = 128,
|
||||
.tag_size = AES_GCM_TAGLEN,
|
||||
.set_encrypt_key = evp_cipher_set_encrypt_key,
|
||||
.set_decrypt_key = evp_cipher_set_decrypt_key,
|
||||
.aead_encrypt = evp_cipher_aead_encrypt,
|
||||
.aead_decrypt_length = evp_cipher_aead_get_length,
|
||||
.aead_decrypt = evp_cipher_aead_decrypt,
|
||||
.cleanup = evp_cipher_cleanup
|
||||
},
|
||||
{
|
||||
.name = "aes256-gcm@openssh.com",
|
||||
.blocksize = AES_BLOCK_SIZE,
|
||||
.lenfield_blocksize = 4, /* not encrypted, but authenticated */
|
||||
.ciphertype = SSH_AEAD_AES256_GCM,
|
||||
.keysize = 256,
|
||||
.tag_size = AES_GCM_TAGLEN,
|
||||
.set_encrypt_key = evp_cipher_set_encrypt_key,
|
||||
.set_decrypt_key = evp_cipher_set_decrypt_key,
|
||||
.aead_encrypt = evp_cipher_aead_encrypt,
|
||||
.aead_decrypt_length = evp_cipher_aead_get_length,
|
||||
.aead_decrypt = evp_cipher_aead_decrypt,
|
||||
.cleanup = evp_cipher_cleanup
|
||||
},
|
||||
#endif /* HAVE_OPENSSL_EVP_AES_GCM */
|
||||
#endif /* HAS_AES */
|
||||
#ifdef HAS_DES
|
||||
{
|
||||
@@ -806,7 +1068,24 @@ int ssh_crypto_init(void)
|
||||
if (libcrypto_initialized) {
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
if (SSLeay() != OPENSSL_VERSION_NUMBER){
|
||||
SSH_LOG(SSH_LOG_WARNING, "libssh compiled with %s "
|
||||
"headers, currently running with %s.",
|
||||
OPENSSL_VERSION_TEXT,
|
||||
SSLeay_version(SSLeay())
|
||||
);
|
||||
}
|
||||
#ifdef CAN_DISABLE_AESNI
|
||||
/*
|
||||
* disable AES-NI when running within Valgrind, because they generate
|
||||
* too many "uninitialized memory access" false positives
|
||||
*/
|
||||
if (RUNNING_ON_VALGRIND){
|
||||
SSH_LOG(SSH_LOG_INFO, "Running within Valgrind, disabling AES-NI");
|
||||
/* Bit #57 denotes AES-NI instruction set extension */
|
||||
OPENSSL_ia32cap &= ~(1LL << 57);
|
||||
}
|
||||
#endif
|
||||
OpenSSL_add_all_algorithms();
|
||||
|
||||
for (i = 0; ssh_ciphertab[i].name != NULL; i++) {
|
||||
|
||||
208
src/libgcrypt.c
208
src/libgcrypt.c
@@ -31,6 +31,7 @@
|
||||
#include "libssh/crypto.h"
|
||||
#include "libssh/wrapper.h"
|
||||
#include "libssh/string.h"
|
||||
#include "libssh/misc.h"
|
||||
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
#include <gcrypt.h>
|
||||
@@ -353,6 +354,8 @@ static int aes_set_key(struct ssh_cipher_struct *cipher, void *key, void *IV) {
|
||||
}
|
||||
if(strstr(cipher->name,"-ctr"))
|
||||
mode=GCRY_CIPHER_MODE_CTR;
|
||||
if (strstr(cipher->name, "-gcm"))
|
||||
mode = GCRY_CIPHER_MODE_GCM;
|
||||
switch (cipher->keysize) {
|
||||
case 128:
|
||||
if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_AES128,
|
||||
@@ -386,6 +389,11 @@ static int aes_set_key(struct ssh_cipher_struct *cipher, void *key, void *IV) {
|
||||
SAFE_FREE(cipher->key);
|
||||
return -1;
|
||||
}
|
||||
} else if (mode == GCRY_CIPHER_MODE_GCM) {
|
||||
/* Store the IV so we can handle the packet counter increments later
|
||||
* The IV is passed to the cipher context later.
|
||||
*/
|
||||
memcpy(cipher->last_iv, IV, AES_GCM_IVLEN);
|
||||
} else {
|
||||
if(gcry_cipher_setctr(cipher->key[0],IV,16)){
|
||||
SAFE_FREE(cipher->key);
|
||||
@@ -397,14 +405,174 @@ static int aes_set_key(struct ssh_cipher_struct *cipher, void *key, void *IV) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void aes_encrypt(struct ssh_cipher_struct *cipher, void *in, void *out,
|
||||
unsigned long len) {
|
||||
gcry_cipher_encrypt(cipher->key[0], out, len, in, len);
|
||||
static void aes_encrypt(struct ssh_cipher_struct *cipher,
|
||||
void *in,
|
||||
void *out,
|
||||
size_t len)
|
||||
{
|
||||
gcry_cipher_encrypt(cipher->key[0], out, len, in, len);
|
||||
}
|
||||
|
||||
static void aes_decrypt(struct ssh_cipher_struct *cipher, void *in, void *out,
|
||||
unsigned long len) {
|
||||
gcry_cipher_decrypt(cipher->key[0], out, len, in, len);
|
||||
static void aes_decrypt(struct ssh_cipher_struct *cipher,
|
||||
void *in,
|
||||
void *out,
|
||||
size_t len)
|
||||
{
|
||||
gcry_cipher_decrypt(cipher->key[0], out, len, in, len);
|
||||
}
|
||||
|
||||
static int
|
||||
aes_aead_get_length(struct ssh_cipher_struct *cipher,
|
||||
void *in,
|
||||
uint8_t *out,
|
||||
size_t len,
|
||||
uint64_t seq)
|
||||
{
|
||||
(void)cipher;
|
||||
(void)seq;
|
||||
|
||||
/* The length is not encrypted: Copy it to the result buffer */
|
||||
memcpy(out, in, len);
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
aes_gcm_encrypt(struct ssh_cipher_struct *cipher,
|
||||
void *in,
|
||||
void *out,
|
||||
size_t len,
|
||||
uint8_t *tag,
|
||||
uint64_t seq)
|
||||
{
|
||||
gpg_error_t err;
|
||||
size_t aadlen, authlen;
|
||||
|
||||
(void)seq;
|
||||
|
||||
aadlen = cipher->lenfield_blocksize;
|
||||
authlen = cipher->tag_size;
|
||||
|
||||
/* increment IV */
|
||||
err = gcry_cipher_setiv(cipher->key[0],
|
||||
cipher->last_iv,
|
||||
AES_GCM_IVLEN);
|
||||
/* This actualy does not increment the packet counter for the
|
||||
* current encryption operation, but for the next one. The first
|
||||
* operation needs to be completed with the derived IV.
|
||||
*
|
||||
* The IV buffer has the following structure:
|
||||
* [ 4B static IV ][ 8B packet counter ][ 4B block counter ]
|
||||
*/
|
||||
uint64_inc(cipher->last_iv + 4);
|
||||
if (err) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "gcry_cipher_setiv failed: %s",
|
||||
gpg_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Pass the authenticated data (packet_length) */
|
||||
err = gcry_cipher_authenticate(cipher->key[0], in, aadlen);
|
||||
if (err) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "gcry_cipher_authenticate failed: %s",
|
||||
gpg_strerror(err));
|
||||
return;
|
||||
}
|
||||
memcpy(out, in, aadlen);
|
||||
|
||||
/* Encrypt the rest of the data */
|
||||
err = gcry_cipher_encrypt(cipher->key[0],
|
||||
(unsigned char *)out + aadlen,
|
||||
len - aadlen,
|
||||
(unsigned char *)in + aadlen,
|
||||
len - aadlen);
|
||||
if (err) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "gcry_cipher_encrypt failed: %s",
|
||||
gpg_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Calculate the tag */
|
||||
err = gcry_cipher_gettag(cipher->key[0],
|
||||
(void *)tag,
|
||||
authlen);
|
||||
if (err) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "gcry_cipher_gettag failed: %s",
|
||||
gpg_strerror(err));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
aes_gcm_decrypt(struct ssh_cipher_struct *cipher,
|
||||
void *complete_packet,
|
||||
uint8_t *out,
|
||||
size_t encrypted_size,
|
||||
uint64_t seq)
|
||||
{
|
||||
gpg_error_t err;
|
||||
size_t aadlen, authlen;
|
||||
|
||||
(void)seq;
|
||||
|
||||
aadlen = cipher->lenfield_blocksize;
|
||||
authlen = cipher->tag_size;
|
||||
|
||||
/* increment IV */
|
||||
err = gcry_cipher_setiv(cipher->key[0],
|
||||
cipher->last_iv,
|
||||
AES_GCM_IVLEN);
|
||||
/* This actualy does not increment the packet counter for the
|
||||
* current encryption operation, but for the next one. The first
|
||||
* operation needs to be completed with the derived IV.
|
||||
*
|
||||
* The IV buffer has the following structure:
|
||||
* [ 4B static IV ][ 8B packet counter ][ 4B block counter ]
|
||||
*/
|
||||
uint64_inc(cipher->last_iv + 4);
|
||||
if (err) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "gcry_cipher_setiv failed: %s",
|
||||
gpg_strerror(err));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* Pass the authenticated data (packet_length) */
|
||||
err = gcry_cipher_authenticate(cipher->key[0],
|
||||
complete_packet,
|
||||
aadlen);
|
||||
if (err) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "gcry_cipher_authenticate failed: %s",
|
||||
gpg_strerror(err));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
/* Do not copy the length to the target buffer, because it is already processed */
|
||||
//memcpy(out, complete_packet, aadlen);
|
||||
|
||||
/* Encrypt the rest of the data */
|
||||
err = gcry_cipher_decrypt(cipher->key[0],
|
||||
out,
|
||||
encrypted_size,
|
||||
(unsigned char *)complete_packet + aadlen,
|
||||
encrypted_size);
|
||||
if (err) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "gcry_cipher_decrypt failed: %s",
|
||||
gpg_strerror(err));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* Check the tag */
|
||||
err = gcry_cipher_checktag(cipher->key[0],
|
||||
(unsigned char *)complete_packet + aadlen + encrypted_size,
|
||||
authlen);
|
||||
if (gpg_err_code(err) == GPG_ERR_CHECKSUM) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "The authentication tag does not match");
|
||||
return SSH_ERROR;
|
||||
} else if (err != GPG_ERR_NO_ERROR) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "General error while decryption: %s",
|
||||
gpg_strerror(err));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static int des3_set_key(struct ssh_cipher_struct *cipher, void *key, void *IV) {
|
||||
@@ -519,6 +687,34 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
|
||||
.encrypt = aes_encrypt,
|
||||
.decrypt = aes_decrypt
|
||||
},
|
||||
{
|
||||
.name = "aes128-gcm@openssh.com",
|
||||
.blocksize = 16,
|
||||
.lenfield_blocksize = 4, /* not encrypted, but authenticated */
|
||||
.keylen = sizeof(gcry_cipher_hd_t),
|
||||
.key = NULL,
|
||||
.keysize = 128,
|
||||
.tag_size = AES_GCM_TAGLEN,
|
||||
.set_encrypt_key = aes_set_key,
|
||||
.set_decrypt_key = aes_set_key,
|
||||
.aead_encrypt = aes_gcm_encrypt,
|
||||
.aead_decrypt_length = aes_aead_get_length,
|
||||
.aead_decrypt = aes_gcm_decrypt,
|
||||
},
|
||||
{
|
||||
.name = "aes256-gcm@openssh.com",
|
||||
.blocksize = 16,
|
||||
.lenfield_blocksize = 4, /* not encrypted, but authenticated */
|
||||
.keylen = sizeof(gcry_cipher_hd_t),
|
||||
.key = NULL,
|
||||
.keysize = 256,
|
||||
.tag_size = AES_GCM_TAGLEN,
|
||||
.set_encrypt_key = aes_set_key,
|
||||
.set_decrypt_key = aes_set_key,
|
||||
.aead_encrypt = aes_gcm_encrypt,
|
||||
.aead_decrypt_length = aes_aead_get_length,
|
||||
.aead_decrypt = aes_gcm_decrypt,
|
||||
},
|
||||
{
|
||||
.name = "3des-cbc",
|
||||
.blocksize = 8,
|
||||
|
||||
@@ -26,9 +26,13 @@
|
||||
#include "libssh/wrapper.h"
|
||||
#include "libssh/crypto.h"
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/misc.h"
|
||||
|
||||
#ifdef HAVE_LIBMBEDCRYPTO
|
||||
#include <mbedtls/md.h>
|
||||
#ifdef MBEDTLS_GCM_C
|
||||
#include <mbedtls/gcm.h>
|
||||
#endif /* MBEDTLS_GCM_C */
|
||||
|
||||
static mbedtls_entropy_context ssh_mbedtls_entropy;
|
||||
static mbedtls_ctr_drbg_context ssh_mbedtls_ctr_drbg;
|
||||
@@ -509,39 +513,68 @@ void hmac_final(HMACCTX c, unsigned char *hashmacbuf, unsigned int *len)
|
||||
SAFE_FREE(c);
|
||||
}
|
||||
|
||||
static int cipher_set_encrypt_key(struct ssh_cipher_struct *cipher, void *key,
|
||||
void *IV)
|
||||
static int
|
||||
cipher_init(struct ssh_cipher_struct *cipher,
|
||||
mbedtls_operation_t operation,
|
||||
void *key,
|
||||
void *IV)
|
||||
{
|
||||
|
||||
const mbedtls_cipher_info_t *cipher_info = NULL;
|
||||
mbedtls_cipher_context_t *ctx;
|
||||
int rc;
|
||||
|
||||
mbedtls_cipher_init(&cipher->encrypt_ctx);
|
||||
if (operation == MBEDTLS_ENCRYPT) {
|
||||
ctx = &cipher->encrypt_ctx;
|
||||
} else if (operation == MBEDTLS_DECRYPT) {
|
||||
ctx = &cipher->decrypt_ctx;
|
||||
} else {
|
||||
SSH_LOG(SSH_LOG_WARNING, "unknown operation");
|
||||
return 1;
|
||||
}
|
||||
|
||||
mbedtls_cipher_init(ctx);
|
||||
cipher_info = mbedtls_cipher_info_from_type(cipher->type);
|
||||
|
||||
rc = mbedtls_cipher_setup(&cipher->encrypt_ctx, cipher_info);
|
||||
rc = mbedtls_cipher_setup(ctx, cipher_info);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setup failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = mbedtls_cipher_setkey(&cipher->encrypt_ctx, key,
|
||||
rc = mbedtls_cipher_setkey(ctx, key,
|
||||
cipher_info->key_bitlen,
|
||||
MBEDTLS_ENCRYPT);
|
||||
operation);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = mbedtls_cipher_set_iv(&cipher->encrypt_ctx, IV, cipher_info->iv_size);
|
||||
|
||||
rc = mbedtls_cipher_set_iv(ctx, IV, cipher_info->iv_size);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_iv failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = mbedtls_cipher_reset(&cipher->encrypt_ctx);
|
||||
return 0;
|
||||
error:
|
||||
mbedtls_cipher_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
cipher_set_encrypt_key(struct ssh_cipher_struct *cipher,
|
||||
void *key,
|
||||
void *IV)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = cipher_init(cipher, MBEDTLS_ENCRYPT, key, IV);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "cipher_init failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = mbedtls_cipher_reset(&cipher->encrypt_ctx);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed");
|
||||
goto error;
|
||||
@@ -549,38 +582,19 @@ static int cipher_set_encrypt_key(struct ssh_cipher_struct *cipher, void *key,
|
||||
|
||||
return SSH_OK;
|
||||
error:
|
||||
mbedtls_cipher_free(&cipher->encrypt_ctx);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
static int cipher_set_encrypt_key_cbc(struct ssh_cipher_struct *cipher, void *key,
|
||||
void *IV)
|
||||
static int
|
||||
cipher_set_encrypt_key_cbc(struct ssh_cipher_struct *cipher,
|
||||
void *key,
|
||||
void *IV)
|
||||
{
|
||||
|
||||
const mbedtls_cipher_info_t *cipher_info = NULL;
|
||||
int rc;
|
||||
|
||||
mbedtls_cipher_init(&cipher->encrypt_ctx);
|
||||
cipher_info = mbedtls_cipher_info_from_type(cipher->type);
|
||||
|
||||
rc = mbedtls_cipher_setup(&cipher->encrypt_ctx, cipher_info);
|
||||
rc = cipher_init(cipher, MBEDTLS_ENCRYPT, key, IV);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setup failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = mbedtls_cipher_setkey(&cipher->encrypt_ctx, key,
|
||||
cipher_info->key_bitlen,
|
||||
MBEDTLS_ENCRYPT);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = mbedtls_cipher_set_iv(&cipher->encrypt_ctx, IV, cipher_info->iv_size);
|
||||
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_iv failed");
|
||||
SSH_LOG(SSH_LOG_WARNING, "cipher_init failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -595,7 +609,6 @@ static int cipher_set_encrypt_key_cbc(struct ssh_cipher_struct *cipher, void *ke
|
||||
}
|
||||
|
||||
rc = mbedtls_cipher_reset(&cipher->encrypt_ctx);
|
||||
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed");
|
||||
goto error;
|
||||
@@ -607,37 +620,51 @@ error:
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
static int cipher_set_decrypt_key(struct ssh_cipher_struct *cipher, void *key,
|
||||
void *IV)
|
||||
#ifdef MBEDTLS_GCM_C
|
||||
static int
|
||||
cipher_set_key_gcm(struct ssh_cipher_struct *cipher,
|
||||
void *key,
|
||||
void *IV)
|
||||
{
|
||||
const mbedtls_cipher_info_t *cipher_info = NULL;
|
||||
int rc;
|
||||
|
||||
mbedtls_cipher_init(&cipher->decrypt_ctx);
|
||||
mbedtls_gcm_init(&cipher->gcm_ctx);
|
||||
cipher_info = mbedtls_cipher_info_from_type(cipher->type);
|
||||
|
||||
rc = mbedtls_cipher_setup(&cipher->decrypt_ctx, cipher_info);
|
||||
rc = mbedtls_gcm_setkey(&cipher->gcm_ctx,
|
||||
MBEDTLS_CIPHER_ID_AES,
|
||||
key,
|
||||
cipher_info->key_bitlen);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed");
|
||||
SSH_LOG(SSH_LOG_WARNING, "mbedtls_gcm_setkey failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = mbedtls_cipher_setkey(&cipher->decrypt_ctx, key,
|
||||
cipher_info->key_bitlen,
|
||||
MBEDTLS_DECRYPT);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed");
|
||||
goto error;
|
||||
}
|
||||
/* Store the IV so we can increment the packet counter later */
|
||||
memcpy(cipher->last_iv, IV, AES_GCM_IVLEN);
|
||||
|
||||
rc = mbedtls_cipher_set_iv(&cipher->decrypt_ctx, IV, cipher_info->iv_size);
|
||||
return 0;
|
||||
error:
|
||||
mbedtls_gcm_free(&cipher->gcm_ctx);
|
||||
return 1;
|
||||
}
|
||||
#endif /* MBEDTLS_GCM_C */
|
||||
|
||||
static int
|
||||
cipher_set_decrypt_key(struct ssh_cipher_struct *cipher,
|
||||
void *key,
|
||||
void *IV)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = cipher_init(cipher, MBEDTLS_DECRYPT, key, IV);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_iv failed");
|
||||
SSH_LOG(SSH_LOG_WARNING, "cipher_init failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
mbedtls_cipher_reset(&cipher->decrypt_ctx);
|
||||
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed");
|
||||
goto error;
|
||||
@@ -649,45 +676,27 @@ error:
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
static int cipher_set_decrypt_key_cbc(struct ssh_cipher_struct *cipher, void *key,
|
||||
void *IV)
|
||||
static int
|
||||
cipher_set_decrypt_key_cbc(struct ssh_cipher_struct *cipher,
|
||||
void *key,
|
||||
void *IV)
|
||||
{
|
||||
const mbedtls_cipher_info_t *cipher_info;
|
||||
int rc;
|
||||
|
||||
mbedtls_cipher_init(&cipher->decrypt_ctx);
|
||||
cipher_info = mbedtls_cipher_info_from_type(cipher->type);
|
||||
|
||||
rc = mbedtls_cipher_setup(&cipher->decrypt_ctx, cipher_info);
|
||||
rc = cipher_init(cipher, MBEDTLS_DECRYPT, key, IV);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = mbedtls_cipher_setkey(&cipher->decrypt_ctx, key,
|
||||
cipher_info->key_bitlen,
|
||||
MBEDTLS_DECRYPT);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = mbedtls_cipher_set_iv(&cipher->decrypt_ctx, IV, cipher_info->iv_size);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_iv failed");
|
||||
SSH_LOG(SSH_LOG_WARNING, "cipher_init failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = mbedtls_cipher_set_padding_mode(&cipher->decrypt_ctx,
|
||||
MBEDTLS_PADDING_NONE);
|
||||
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_padding_mode failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
mbedtls_cipher_reset(&cipher->decrypt_ctx);
|
||||
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed");
|
||||
goto error;
|
||||
@@ -699,8 +708,10 @@ error:
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
static void cipher_encrypt(struct ssh_cipher_struct *cipher, void *in, void *out,
|
||||
unsigned long len)
|
||||
static void cipher_encrypt(struct ssh_cipher_struct *cipher,
|
||||
void *in,
|
||||
void *out,
|
||||
size_t len)
|
||||
{
|
||||
size_t outlen = 0;
|
||||
size_t total_len = 0;
|
||||
@@ -754,8 +765,10 @@ static void cipher_encrypt_cbc(struct ssh_cipher_struct *cipher, void *in, void
|
||||
|
||||
}
|
||||
|
||||
static void cipher_decrypt(struct ssh_cipher_struct *cipher, void *in, void *out,
|
||||
unsigned long len)
|
||||
static void cipher_decrypt(struct ssh_cipher_struct *cipher,
|
||||
void *in,
|
||||
void *out,
|
||||
size_t len)
|
||||
{
|
||||
size_t outlen = 0;
|
||||
int rc = 0;
|
||||
@@ -836,10 +849,105 @@ static void cipher_decrypt_cbc(struct ssh_cipher_struct *cipher, void *in, void
|
||||
|
||||
}
|
||||
|
||||
#ifdef MBEDTLS_GCM_C
|
||||
static int
|
||||
cipher_gcm_get_length(struct ssh_cipher_struct *cipher,
|
||||
void *in,
|
||||
uint8_t *out,
|
||||
size_t len,
|
||||
uint64_t seq)
|
||||
{
|
||||
(void)cipher;
|
||||
(void)seq;
|
||||
|
||||
/* The length is not encrypted: Copy it to the result buffer */
|
||||
memcpy(out, in, len);
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
cipher_encrypt_gcm(struct ssh_cipher_struct *cipher,
|
||||
void *in,
|
||||
void *out,
|
||||
size_t len,
|
||||
uint8_t *tag,
|
||||
uint64_t seq)
|
||||
{
|
||||
size_t authlen, aadlen;
|
||||
int rc;
|
||||
|
||||
(void) seq;
|
||||
|
||||
aadlen = cipher->lenfield_blocksize;
|
||||
authlen = cipher->tag_size;
|
||||
|
||||
/* The length is not encrypted */
|
||||
memcpy(out, in, aadlen);
|
||||
rc = mbedtls_gcm_crypt_and_tag(&cipher->gcm_ctx,
|
||||
MBEDTLS_GCM_ENCRYPT,
|
||||
len - aadlen, /* encrypted data len */
|
||||
cipher->last_iv, /* IV */
|
||||
AES_GCM_IVLEN,
|
||||
in, /* aad */
|
||||
aadlen,
|
||||
(const unsigned char *)in + aadlen, /* input */
|
||||
(unsigned char *)out + aadlen, /* output */
|
||||
authlen,
|
||||
tag); /* tag */
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "mbedtls_gcm_crypt_and_tag failed");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Increment the IV for the next invocation */
|
||||
uint64_inc(cipher->last_iv + 4);
|
||||
}
|
||||
|
||||
static int
|
||||
cipher_decrypt_gcm(struct ssh_cipher_struct *cipher,
|
||||
void *complete_packet,
|
||||
uint8_t *out,
|
||||
size_t encrypted_size,
|
||||
uint64_t seq)
|
||||
{
|
||||
size_t authlen, aadlen;
|
||||
int rc;
|
||||
|
||||
(void) seq;
|
||||
|
||||
aadlen = cipher->lenfield_blocksize;
|
||||
authlen = cipher->tag_size;
|
||||
|
||||
rc = mbedtls_gcm_auth_decrypt(&cipher->gcm_ctx,
|
||||
encrypted_size, /* encrypted data len */
|
||||
cipher->last_iv, /* IV */
|
||||
AES_GCM_IVLEN,
|
||||
complete_packet, /* aad */
|
||||
aadlen,
|
||||
(const u_char *)complete_packet + aadlen + encrypted_size, /* tag */
|
||||
authlen,
|
||||
(const u_char *)complete_packet + aadlen, /* input */
|
||||
(unsigned char *)out); /* output */
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "mbedtls_gcm_auth_decrypt failed");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* Increment the IV for the next invocation */
|
||||
uint64_inc(cipher->last_iv + 4);
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
#endif /* MBEDTLS_GCM_C */
|
||||
|
||||
static void cipher_cleanup(struct ssh_cipher_struct *cipher)
|
||||
{
|
||||
mbedtls_cipher_free(&cipher->encrypt_ctx);
|
||||
mbedtls_cipher_free(&cipher->decrypt_ctx);
|
||||
#ifdef MBEDTLS_GCM_C
|
||||
mbedtls_gcm_free(&cipher->gcm_ctx);
|
||||
#endif /* MBEDTLS_GCM_C */
|
||||
}
|
||||
|
||||
static struct ssh_cipher_struct ssh_ciphertab[] = {
|
||||
@@ -920,6 +1028,36 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
|
||||
.decrypt = cipher_decrypt_cbc,
|
||||
.cleanup = cipher_cleanup
|
||||
},
|
||||
#ifdef MBEDTLS_GCM_C
|
||||
{
|
||||
.name = "aes128-gcm@openssh.com",
|
||||
.blocksize = 16,
|
||||
.lenfield_blocksize = 4, /* not encrypted, but authenticated */
|
||||
.keysize = 128,
|
||||
.tag_size = AES_GCM_TAGLEN,
|
||||
.type = MBEDTLS_CIPHER_AES_128_GCM,
|
||||
.set_encrypt_key = cipher_set_key_gcm,
|
||||
.set_decrypt_key = cipher_set_key_gcm,
|
||||
.aead_encrypt = cipher_encrypt_gcm,
|
||||
.aead_decrypt_length = cipher_gcm_get_length,
|
||||
.aead_decrypt = cipher_decrypt_gcm,
|
||||
.cleanup = cipher_cleanup
|
||||
},
|
||||
{
|
||||
.name = "aes256-gcm@openssh.com",
|
||||
.blocksize = 16,
|
||||
.lenfield_blocksize = 4, /* not encrypted, but authenticated */
|
||||
.keysize = 256,
|
||||
.tag_size = AES_GCM_TAGLEN,
|
||||
.type = MBEDTLS_CIPHER_AES_256_GCM,
|
||||
.set_encrypt_key = cipher_set_key_gcm,
|
||||
.set_decrypt_key = cipher_set_key_gcm,
|
||||
.aead_encrypt = cipher_encrypt_gcm,
|
||||
.aead_decrypt_length = cipher_gcm_get_length,
|
||||
.aead_decrypt = cipher_decrypt_gcm,
|
||||
.cleanup = cipher_cleanup
|
||||
},
|
||||
#endif /* MBEDTLS_GCM_C */
|
||||
{
|
||||
.name = "3des-cbc",
|
||||
.blocksize = 8,
|
||||
|
||||
198
src/messages.c
198
src/messages.c
@@ -63,14 +63,15 @@
|
||||
* @{
|
||||
*/
|
||||
|
||||
static ssh_message ssh_message_new(ssh_session session){
|
||||
ssh_message msg = malloc(sizeof(struct ssh_message_struct));
|
||||
if (msg == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ZERO_STRUCTP(msg);
|
||||
msg->session = session;
|
||||
return msg;
|
||||
static ssh_message ssh_message_new(ssh_session session)
|
||||
{
|
||||
ssh_message msg = calloc(1, sizeof(struct ssh_message_struct));
|
||||
if (msg == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
msg->session = session;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
#ifndef WITH_SERVER
|
||||
@@ -155,6 +156,11 @@ static int ssh_execute_server_request(ssh_session session, ssh_message msg)
|
||||
session->server_callbacks->userdata);
|
||||
if (channel != NULL) {
|
||||
rc = ssh_message_channel_request_open_reply_accept_channel(msg, channel);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_WARNING,
|
||||
"Failed to send reply for accepting a channel "
|
||||
"open");
|
||||
}
|
||||
return SSH_OK;
|
||||
} else {
|
||||
ssh_message_reply_default(msg);
|
||||
@@ -227,6 +233,10 @@ static int ssh_execute_server_request(ssh_session session, ssh_message msg)
|
||||
msg->channel_request.height,
|
||||
msg->channel_request.pxwidth,
|
||||
msg->channel_request.pxheight);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_WARNING,
|
||||
"Failed to iterate callbacks for window change");
|
||||
}
|
||||
return SSH_OK;
|
||||
}
|
||||
ssh_callbacks_iterate_end();
|
||||
@@ -372,16 +382,16 @@ static int ssh_execute_message_callback(ssh_session session, ssh_message msg) {
|
||||
session->ssh_message_callback_data);
|
||||
if(ret == 1) {
|
||||
ret = ssh_message_reply_default(msg);
|
||||
ssh_message_free(msg);
|
||||
SSH_MESSAGE_FREE(msg);
|
||||
if(ret != SSH_OK) {
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
ssh_message_free(msg);
|
||||
SSH_MESSAGE_FREE(msg);
|
||||
}
|
||||
} else {
|
||||
ret = ssh_message_reply_default(msg);
|
||||
ssh_message_free(msg);
|
||||
SSH_MESSAGE_FREE(msg);
|
||||
if(ret != SSH_OK) {
|
||||
return ret;
|
||||
}
|
||||
@@ -399,46 +409,60 @@ static int ssh_execute_message_callback(ssh_session session, ssh_message msg) {
|
||||
*
|
||||
* @param[in] message The message to add to the queue.
|
||||
*/
|
||||
void ssh_message_queue(ssh_session session, ssh_message message){
|
||||
if (message != NULL) {
|
||||
static void ssh_message_queue(ssh_session session, ssh_message message)
|
||||
{
|
||||
#ifdef WITH_SERVER
|
||||
int ret;
|
||||
/* probably not the best place to execute server callbacks, but still better
|
||||
* than nothing.
|
||||
*/
|
||||
ret = ssh_execute_server_callbacks(session, message);
|
||||
if (ret == SSH_OK){
|
||||
ssh_message_free(message);
|
||||
return;
|
||||
}
|
||||
int ret;
|
||||
#endif
|
||||
|
||||
if (message == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
/* probably not the best place to execute server callbacks, but still better
|
||||
* than nothing.
|
||||
*/
|
||||
ret = ssh_execute_server_callbacks(session, message);
|
||||
if (ret == SSH_OK) {
|
||||
SSH_MESSAGE_FREE(message);
|
||||
return;
|
||||
}
|
||||
#endif /* WITH_SERVER */
|
||||
if(session->ssh_message_callback != NULL) {
|
||||
ssh_execute_message_callback(session, message);
|
||||
return;
|
||||
}
|
||||
if (session->server_callbacks != NULL){
|
||||
/* if we have server callbacks, but nothing was executed, it means we are
|
||||
* in non-synchronous mode, and we just don't care about the message we
|
||||
* received. Just send a default response. Do not queue it.
|
||||
|
||||
if (session->ssh_message_callback != NULL) {
|
||||
/* This will transfer the message, do not free. */
|
||||
ssh_execute_message_callback(session, message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (session->server_callbacks != NULL) {
|
||||
/* if we have server callbacks, but nothing was executed, it means we are
|
||||
* in non-synchronous mode, and we just don't care about the message we
|
||||
* received. Just send a default response. Do not queue it.
|
||||
*/
|
||||
ssh_message_reply_default(message);
|
||||
SSH_MESSAGE_FREE(message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (session->ssh_message_list == NULL) {
|
||||
session->ssh_message_list = ssh_list_new();
|
||||
if (session->ssh_message_list != NULL) {
|
||||
/*
|
||||
* If the message list couldn't be allocated, the message can't be
|
||||
* enqueued
|
||||
*/
|
||||
ssh_message_reply_default(message);
|
||||
ssh_message_free(message);
|
||||
return;
|
||||
}
|
||||
if(session->ssh_message_list == NULL) {
|
||||
session->ssh_message_list = ssh_list_new();
|
||||
}
|
||||
if (session->ssh_message_list != NULL) {
|
||||
ssh_list_append(session->ssh_message_list, message);
|
||||
} else {
|
||||
/* If the message list couldn't be allocated, the message can't be
|
||||
* enqueued */
|
||||
ssh_message_reply_default(message);
|
||||
ssh_set_error_oom(session);
|
||||
ssh_message_free(message);
|
||||
SSH_MESSAGE_FREE(message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* This will transfer the message, do not free. */
|
||||
ssh_list_append(session->ssh_message_list, message);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -611,38 +635,42 @@ void ssh_message_free(ssh_message msg){
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_service_request){
|
||||
ssh_string service = NULL;
|
||||
char *service_c = NULL;
|
||||
ssh_message msg=NULL;
|
||||
SSH_PACKET_CALLBACK(ssh_packet_service_request)
|
||||
{
|
||||
char *service_c = NULL;
|
||||
ssh_message msg = NULL;
|
||||
int rc;
|
||||
|
||||
(void)type;
|
||||
(void)user;
|
||||
service = ssh_buffer_get_ssh_string(packet);
|
||||
if (service == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "Invalid SSH_MSG_SERVICE_REQUEST packet");
|
||||
goto error;
|
||||
}
|
||||
(void)type;
|
||||
(void)user;
|
||||
|
||||
service_c = ssh_string_to_char(service);
|
||||
if (service_c == NULL) {
|
||||
goto error;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_PACKET,
|
||||
"Received a SERVICE_REQUEST for service %s", service_c);
|
||||
msg=ssh_message_new(session);
|
||||
if(!msg){
|
||||
SAFE_FREE(service_c);
|
||||
goto error;
|
||||
}
|
||||
msg->type=SSH_REQUEST_SERVICE;
|
||||
msg->service_request.service=service_c;
|
||||
rc = ssh_buffer_unpack(packet,
|
||||
"s",
|
||||
&service_c);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Invalid SSH_MSG_SERVICE_REQUEST packet");
|
||||
goto error;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET,
|
||||
"Received a SERVICE_REQUEST for service %s",
|
||||
service_c);
|
||||
|
||||
msg = ssh_message_new(session);
|
||||
if (msg == NULL) {
|
||||
SAFE_FREE(service_c);
|
||||
goto error;
|
||||
}
|
||||
|
||||
msg->type = SSH_REQUEST_SERVICE;
|
||||
msg->service_request.service = service_c;
|
||||
|
||||
ssh_message_queue(session, msg);
|
||||
error:
|
||||
ssh_string_free(service);
|
||||
if(msg != NULL)
|
||||
ssh_message_queue(session,msg);
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
|
||||
@@ -702,6 +730,7 @@ static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
|
||||
*/
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
|
||||
ssh_message msg = NULL;
|
||||
ssh_signature sig = NULL;
|
||||
char *service = NULL;
|
||||
char *method = NULL;
|
||||
int cmp;
|
||||
@@ -835,17 +864,23 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_pki_signature_verify_blob(session,
|
||||
sig_blob,
|
||||
rc = ssh_pki_import_signature_blob(sig_blob,
|
||||
msg->auth_request.pubkey,
|
||||
ssh_buffer_get(digest),
|
||||
ssh_buffer_get_len(digest));
|
||||
&sig);
|
||||
if (rc == SSH_OK) {
|
||||
rc = ssh_pki_signature_verify(session,
|
||||
sig,
|
||||
msg->auth_request.pubkey,
|
||||
ssh_buffer_get(digest),
|
||||
ssh_buffer_get_len(digest));
|
||||
}
|
||||
ssh_string_free(sig_blob);
|
||||
ssh_buffer_free(digest);
|
||||
ssh_signature_free(sig);
|
||||
if (rc < 0) {
|
||||
SSH_LOG(
|
||||
SSH_LOG_PACKET,
|
||||
"Received an invalid signature from peer");
|
||||
"Received an invalid signature from peer");
|
||||
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_WRONG;
|
||||
goto error;
|
||||
}
|
||||
@@ -902,7 +937,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
|
||||
/* bypass the message queue thing */
|
||||
SAFE_FREE(service);
|
||||
SAFE_FREE(method);
|
||||
ssh_message_free(msg);
|
||||
SSH_MESSAGE_FREE(msg);
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
@@ -915,7 +950,7 @@ error:
|
||||
SAFE_FREE(service);
|
||||
SAFE_FREE(method);
|
||||
|
||||
ssh_message_free(msg);
|
||||
SSH_MESSAGE_FREE(msg);
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
end:
|
||||
@@ -1058,7 +1093,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_info_response){
|
||||
return SSH_PACKET_USED;
|
||||
|
||||
error:
|
||||
ssh_message_free(msg);
|
||||
SSH_MESSAGE_FREE(msg);
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
@@ -1157,8 +1192,7 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_open){
|
||||
goto end;
|
||||
|
||||
error:
|
||||
ssh_message_free(msg);
|
||||
msg=NULL;
|
||||
SSH_MESSAGE_FREE(msg);
|
||||
end:
|
||||
SAFE_FREE(type_c);
|
||||
if(msg != NULL)
|
||||
@@ -1355,7 +1389,7 @@ end:
|
||||
|
||||
return SSH_OK;
|
||||
error:
|
||||
ssh_message_free(msg);
|
||||
SSH_MESSAGE_FREE(msg);
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
66
src/misc.c
66
src/misc.c
@@ -213,47 +213,50 @@ int ssh_is_ipaddr(const char *str) {
|
||||
#define NSS_BUFLEN_PASSWD 4096
|
||||
#endif /* NSS_BUFLEN_PASSWD */
|
||||
|
||||
char *ssh_get_user_home_dir(void) {
|
||||
char *szPath = NULL;
|
||||
struct passwd pwd;
|
||||
struct passwd *pwdbuf;
|
||||
char buf[NSS_BUFLEN_PASSWD] = {0};
|
||||
int rc;
|
||||
char *ssh_get_user_home_dir(void)
|
||||
{
|
||||
char *szPath = NULL;
|
||||
struct passwd pwd;
|
||||
struct passwd *pwdbuf = NULL;
|
||||
char buf[NSS_BUFLEN_PASSWD] = {0};
|
||||
int rc;
|
||||
|
||||
rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
|
||||
if (rc != 0) {
|
||||
szPath = getenv("HOME");
|
||||
if (szPath == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%s", szPath);
|
||||
rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
|
||||
if (rc != 0 || pwdbuf == NULL ) {
|
||||
szPath = getenv("HOME");
|
||||
if (szPath == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%s", szPath);
|
||||
|
||||
return strdup(buf);
|
||||
}
|
||||
return strdup(buf);
|
||||
}
|
||||
|
||||
szPath = strdup(pwd.pw_dir);
|
||||
szPath = strdup(pwd.pw_dir);
|
||||
|
||||
return szPath;
|
||||
return szPath;
|
||||
}
|
||||
|
||||
/* we have read access on file */
|
||||
int ssh_file_readaccess_ok(const char *file) {
|
||||
if (access(file, R_OK) < 0) {
|
||||
return 0;
|
||||
}
|
||||
int ssh_file_readaccess_ok(const char *file)
|
||||
{
|
||||
if (access(file, R_OK) < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *ssh_get_local_username(void) {
|
||||
char *ssh_get_local_username(void)
|
||||
{
|
||||
struct passwd pwd;
|
||||
struct passwd *pwdbuf;
|
||||
struct passwd *pwdbuf = NULL;
|
||||
char buf[NSS_BUFLEN_PASSWD];
|
||||
char *name;
|
||||
int rc;
|
||||
|
||||
rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
|
||||
if (rc != 0) {
|
||||
if (rc != 0 || pwdbuf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1105,4 +1108,17 @@ char *strndup(const char *s, size_t n)
|
||||
}
|
||||
#endif /* ! HAVE_STRNDUP */
|
||||
|
||||
/* Increment 64b integer in network byte order */
|
||||
void
|
||||
uint64_inc(unsigned char *counter)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 7; i >= 0; i--) {
|
||||
counter[i]++;
|
||||
if (counter[i])
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -421,6 +421,12 @@ int ssh_options_set_algo(ssh_session session,
|
||||
* Set it to disable Nagle's Algorithm (TCP_NODELAY) on the
|
||||
* session socket. (int, 0=false)
|
||||
*
|
||||
* - SSH_OPTIONS_PROCESS_CONFIG
|
||||
* Set it to false to disable automatic processing of per-user
|
||||
* and system-wide OpenSSH configuration files. LibSSH
|
||||
* automatically uses these configuration files unless
|
||||
* you provide it with this option or with different file (bool).
|
||||
*
|
||||
* @param value The value to set. This is a generic pointer and the
|
||||
* datatype which is used should be set according to the
|
||||
* type set.
|
||||
@@ -605,12 +611,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
||||
v = value;
|
||||
SAFE_FREE(session->opts.knownhosts);
|
||||
if (v == NULL) {
|
||||
session->opts.knownhosts = ssh_path_expand_escape(session,
|
||||
"%d/known_hosts");
|
||||
if (session->opts.knownhosts == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return -1;
|
||||
}
|
||||
/* The default value will be set by the ssh_options_apply() */
|
||||
} else if (v[0] == '\0') {
|
||||
ssh_set_error_invalid(session);
|
||||
return -1;
|
||||
@@ -954,6 +955,15 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
||||
session->opts.nodelay = (*x & 0xff) > 0 ? 1 : 0;
|
||||
}
|
||||
break;
|
||||
case SSH_OPTIONS_PROCESS_CONFIG:
|
||||
if (value == NULL) {
|
||||
ssh_set_error_invalid(session);
|
||||
return -1;
|
||||
} else {
|
||||
bool *x = (bool *)value;
|
||||
session->opts.config_processed = !(*x);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED, "Unknown ssh option %d", type);
|
||||
return -1;
|
||||
@@ -1335,6 +1345,8 @@ int ssh_options_parse_config(ssh_session session, const char *filename) {
|
||||
r = ssh_config_parse_file(session, "/etc/ssh/ssh_config");
|
||||
}
|
||||
|
||||
/* Do not process the default configuration as part of connection again */
|
||||
session->opts.config_processed = true;
|
||||
out:
|
||||
free(expanded_filename);
|
||||
return r;
|
||||
|
||||
263
src/packet.c
263
src/packet.c
@@ -47,6 +47,7 @@
|
||||
#include "libssh/kex.h"
|
||||
#include "libssh/auth.h"
|
||||
#include "libssh/gssapi.h"
|
||||
#include "libssh/bytearray.h"
|
||||
|
||||
static ssh_packet_callback default_packet_handlers[]= {
|
||||
ssh_packet_disconnect_callback, // SSH2_MSG_DISCONNECT 1
|
||||
@@ -952,8 +953,8 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
||||
size_t processed = 0; /* number of byte processed from the callback */
|
||||
enum ssh_packet_filter_result_e filter_result;
|
||||
|
||||
if(session->current_crypto != NULL) {
|
||||
current_macsize = hmac_digest_len(session->current_crypto->in_hmac);
|
||||
if (session->current_crypto != NULL) {
|
||||
current_macsize = hmac_digest_len(session->current_crypto->in_hmac);
|
||||
}
|
||||
if (lenfield_blocksize == 0) {
|
||||
lenfield_blocksize = blocksize;
|
||||
@@ -1061,32 +1062,45 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
||||
packet_len - (lenfield_blocksize - sizeof(uint32_t));
|
||||
cleartext_packet = ssh_buffer_allocate(session->in_buffer,
|
||||
packet_remaining);
|
||||
if (session->current_crypto) {
|
||||
/*
|
||||
* Decrypt the rest of the packet (lenfield_blocksize bytes already
|
||||
* have been decrypted)
|
||||
*/
|
||||
if (packet_remaining > 0) {
|
||||
rc = ssh_packet_decrypt(session,
|
||||
cleartext_packet,
|
||||
(uint8_t *)data,
|
||||
lenfield_blocksize,
|
||||
processed - lenfield_blocksize);
|
||||
if (cleartext_packet == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (packet_second_block != NULL) {
|
||||
if (session->current_crypto != NULL) {
|
||||
/*
|
||||
* Decrypt the rest of the packet (lenfield_blocksize bytes
|
||||
* already have been decrypted)
|
||||
*/
|
||||
if (packet_remaining > 0) {
|
||||
rc = ssh_packet_decrypt(session,
|
||||
cleartext_packet,
|
||||
(uint8_t *)data,
|
||||
lenfield_blocksize,
|
||||
processed - lenfield_blocksize);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Decryption error");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
mac = packet_second_block + packet_remaining;
|
||||
|
||||
rc = ssh_packet_hmac_verify(session,
|
||||
session->in_buffer,
|
||||
mac,
|
||||
session->current_crypto->in_hmac);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Decryption error");
|
||||
ssh_set_error(session, SSH_FATAL, "HMAC error");
|
||||
goto error;
|
||||
}
|
||||
processed += current_macsize;
|
||||
} else {
|
||||
memcpy(cleartext_packet,
|
||||
packet_second_block,
|
||||
packet_remaining);
|
||||
}
|
||||
mac = packet_second_block + packet_remaining;
|
||||
|
||||
rc = ssh_packet_hmac_verify(session, session->in_buffer, mac, session->current_crypto->in_hmac);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "HMAC error");
|
||||
goto error;
|
||||
}
|
||||
processed += current_macsize;
|
||||
} else {
|
||||
memcpy(cleartext_packet, packet_second_block, packet_remaining);
|
||||
}
|
||||
|
||||
/* skip the size field which has been processed before */
|
||||
@@ -1227,6 +1241,17 @@ void ssh_packet_set_callbacks(ssh_session session, ssh_packet_callbacks callback
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal
|
||||
* @brief remove the callbacks from the packet layer
|
||||
*/
|
||||
void ssh_packet_remove_callbacks(ssh_session session, ssh_packet_callbacks callbacks){
|
||||
struct ssh_iterator *it = NULL;
|
||||
it = ssh_list_find(session->packet_callbacks, callbacks);
|
||||
if (it != NULL) {
|
||||
ssh_list_remove(session->packet_callbacks, it);
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal
|
||||
* @brief sets the default packet handlers
|
||||
*/
|
||||
@@ -1357,106 +1382,112 @@ static int ssh_packet_write(ssh_session session) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int packet_send2(ssh_session session) {
|
||||
unsigned int blocksize = (session->current_crypto ?
|
||||
session->current_crypto->out_cipher->blocksize : 8);
|
||||
unsigned int lenfield_blocksize = (session->current_crypto ?
|
||||
session->current_crypto->out_cipher->lenfield_blocksize : 0);
|
||||
enum ssh_hmac_e hmac_type = (session->current_crypto ?
|
||||
session->current_crypto->out_hmac : session->next_crypto->out_hmac);
|
||||
uint32_t currentlen = ssh_buffer_get_len(session->out_buffer);
|
||||
unsigned char *hmac = NULL;
|
||||
char padstring[32] = { 0 };
|
||||
int rc = SSH_ERROR;
|
||||
uint32_t finallen,payloadsize,compsize;
|
||||
uint8_t padding;
|
||||
ssh_buffer header_buffer = ssh_buffer_new();
|
||||
static int packet_send2(ssh_session session)
|
||||
{
|
||||
unsigned int blocksize =
|
||||
(session->current_crypto ?
|
||||
session->current_crypto->out_cipher->blocksize : 8);
|
||||
unsigned int lenfield_blocksize =
|
||||
(session->current_crypto ?
|
||||
session->current_crypto->out_cipher->lenfield_blocksize : 0);
|
||||
enum ssh_hmac_e hmac_type =
|
||||
(session->current_crypto ?
|
||||
session->current_crypto->out_hmac : session->next_crypto->out_hmac);
|
||||
uint32_t currentlen = ssh_buffer_get_len(session->out_buffer);
|
||||
unsigned char *hmac = NULL;
|
||||
uint8_t padding_data[32] = { 0 };
|
||||
uint8_t padding_size;
|
||||
uint32_t finallen, payloadsize, compsize;
|
||||
uint8_t header[5] = {0};
|
||||
int rc = SSH_ERROR;
|
||||
|
||||
payloadsize = currentlen;
|
||||
payloadsize = currentlen;
|
||||
#ifdef WITH_ZLIB
|
||||
if (session->current_crypto
|
||||
&& session->current_crypto->do_compress_out
|
||||
&& ssh_buffer_get_len(session->out_buffer)) {
|
||||
if (compress_buffer(session,session->out_buffer) < 0) {
|
||||
goto error;
|
||||
if (session->current_crypto != NULL &&
|
||||
session->current_crypto->do_compress_out &&
|
||||
ssh_buffer_get_len(session->out_buffer) > 0) {
|
||||
rc = compress_buffer(session,session->out_buffer);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
currentlen = ssh_buffer_get_len(session->out_buffer);
|
||||
}
|
||||
currentlen = ssh_buffer_get_len(session->out_buffer);
|
||||
}
|
||||
#endif /* WITH_ZLIB */
|
||||
compsize = currentlen;
|
||||
/* compressed payload + packet len (4) + padding len (1) */
|
||||
/* totallen - lenfield_blocksize must be equal to 0 (mod blocksize) */
|
||||
padding = (blocksize - ((blocksize - lenfield_blocksize + currentlen + 5) % blocksize));
|
||||
if(padding < 4) {
|
||||
padding += blocksize;
|
||||
}
|
||||
|
||||
if (session->current_crypto != NULL) {
|
||||
int ok;
|
||||
|
||||
ok = ssh_get_random(padstring, padding, 0);
|
||||
if (!ok) {
|
||||
ssh_set_error(session, SSH_FATAL, "PRNG error");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (header_buffer == NULL){
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
finallen = currentlen + padding + 1;
|
||||
rc = ssh_buffer_pack(header_buffer, "db", finallen, padding);
|
||||
if (rc == SSH_ERROR){
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_prepend_data(session->out_buffer,
|
||||
ssh_buffer_get(header_buffer),
|
||||
ssh_buffer_get_len(header_buffer));
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
rc = ssh_buffer_add_data(session->out_buffer, padstring, padding);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
#ifdef WITH_PCAP
|
||||
if (session->pcap_ctx) {
|
||||
ssh_pcap_context_write(session->pcap_ctx,
|
||||
SSH_PCAP_DIR_OUT,
|
||||
ssh_buffer_get(session->out_buffer),
|
||||
ssh_buffer_get_len(session->out_buffer),
|
||||
ssh_buffer_get_len(session->out_buffer));
|
||||
}
|
||||
#endif
|
||||
hmac = ssh_packet_encrypt(session, ssh_buffer_get(session->out_buffer),
|
||||
ssh_buffer_get_len(session->out_buffer));
|
||||
if (hmac) {
|
||||
rc = ssh_buffer_add_data(session->out_buffer, hmac, hmac_digest_len(hmac_type));
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
compsize = currentlen;
|
||||
/* compressed payload + packet len (4) + padding_size len (1) */
|
||||
/* totallen - lenfield_blocksize must be equal to 0 (mod blocksize) */
|
||||
padding_size = (blocksize - ((blocksize - lenfield_blocksize + currentlen + 5) % blocksize));
|
||||
if (padding_size < 4) {
|
||||
padding_size += blocksize;
|
||||
}
|
||||
}
|
||||
|
||||
rc = ssh_packet_write(session);
|
||||
session->send_seq++;
|
||||
if (session->raw_counter != NULL) {
|
||||
session->raw_counter->out_bytes += payloadsize;
|
||||
session->raw_counter->out_packets++;
|
||||
}
|
||||
if (session->current_crypto != NULL) {
|
||||
int ok;
|
||||
|
||||
ok = ssh_get_random(padding_data, padding_size, 0);
|
||||
if (!ok) {
|
||||
ssh_set_error(session, SSH_FATAL, "PRNG error");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
finallen = currentlen + padding_size + 1;
|
||||
|
||||
PUSH_BE_U32(header, 0, finallen);
|
||||
PUSH_BE_U8(header, 4, padding_size);
|
||||
|
||||
rc = ssh_buffer_prepend_data(session->out_buffer,
|
||||
header,
|
||||
sizeof(header));
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_data(session->out_buffer, padding_data, padding_size);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
#ifdef WITH_PCAP
|
||||
if (session->pcap_ctx != NULL) {
|
||||
ssh_pcap_context_write(session->pcap_ctx,
|
||||
SSH_PCAP_DIR_OUT,
|
||||
ssh_buffer_get(session->out_buffer),
|
||||
ssh_buffer_get_len(session->out_buffer),
|
||||
ssh_buffer_get_len(session->out_buffer));
|
||||
}
|
||||
#endif
|
||||
|
||||
hmac = ssh_packet_encrypt(session,
|
||||
ssh_buffer_get(session->out_buffer),
|
||||
ssh_buffer_get_len(session->out_buffer));
|
||||
if (hmac != NULL) {
|
||||
rc = ssh_buffer_add_data(session->out_buffer,
|
||||
hmac,
|
||||
hmac_digest_len(hmac_type));
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
rc = ssh_packet_write(session);
|
||||
session->send_seq++;
|
||||
if (session->raw_counter != NULL) {
|
||||
session->raw_counter->out_bytes += payloadsize;
|
||||
session->raw_counter->out_packets++;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET,
|
||||
"packet: wrote [len=%d,padding_size=%hhd,comp=%d,payload=%d]",
|
||||
finallen, padding_size, compsize, payloadsize);
|
||||
|
||||
rc = ssh_buffer_reinit(session->out_buffer);
|
||||
if (rc < 0) {
|
||||
rc = SSH_ERROR;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET,
|
||||
"packet: wrote [len=%d,padding=%hhd,comp=%d,payload=%d]",
|
||||
finallen, padding, compsize, payloadsize);
|
||||
if (ssh_buffer_reinit(session->out_buffer) < 0) {
|
||||
rc = SSH_ERROR;
|
||||
}
|
||||
error:
|
||||
if (header_buffer != NULL) {
|
||||
ssh_buffer_free(header_buffer);
|
||||
}
|
||||
return rc; /* SSH_OK, AGAIN or ERROR */
|
||||
return rc; /* SSH_OK, AGAIN or ERROR */
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -138,6 +138,7 @@ error:
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_newkeys){
|
||||
ssh_string sig_blob = NULL;
|
||||
ssh_signature sig = NULL;
|
||||
int rc;
|
||||
(void)packet;
|
||||
(void)user;
|
||||
@@ -185,30 +186,36 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){
|
||||
/* get the server public key */
|
||||
server_key = ssh_dh_get_next_server_publickey(session);
|
||||
if (server_key == NULL) {
|
||||
return SSH_ERROR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* check if public key from server matches user preferences */
|
||||
rc = ssh_pki_import_signature_blob(sig_blob, server_key, &sig);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Check if signature from server matches user preferences */
|
||||
if (session->opts.wanted_methods[SSH_HOSTKEYS]) {
|
||||
if(!ssh_match_group(session->opts.wanted_methods[SSH_HOSTKEYS],
|
||||
server_key->type_c)) {
|
||||
if (!ssh_match_group(session->opts.wanted_methods[SSH_HOSTKEYS],
|
||||
sig->type_c)) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Public key from server (%s) doesn't match user "
|
||||
"preference (%s)",
|
||||
server_key->type_c,
|
||||
sig->type_c,
|
||||
session->opts.wanted_methods[SSH_HOSTKEYS]);
|
||||
return -1;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
rc = ssh_pki_signature_verify_blob(session,
|
||||
sig_blob,
|
||||
server_key,
|
||||
session->next_crypto->secret_hash,
|
||||
session->next_crypto->digest_len);
|
||||
rc = ssh_pki_signature_verify(session,
|
||||
sig,
|
||||
server_key,
|
||||
session->next_crypto->secret_hash,
|
||||
session->next_crypto->digest_len);
|
||||
ssh_string_burn(sig_blob);
|
||||
ssh_string_free(sig_blob);
|
||||
ssh_signature_free(sig);
|
||||
sig_blob = NULL;
|
||||
if (rc == SSH_ERROR) {
|
||||
goto error;
|
||||
@@ -250,10 +257,10 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){
|
||||
}
|
||||
session->dh_handshake_state = DH_STATE_FINISHED;
|
||||
session->ssh_connection_callback(session);
|
||||
return SSH_PACKET_USED;
|
||||
return SSH_PACKET_USED;
|
||||
error:
|
||||
session->session_state=SSH_SESSION_STATE_ERROR;
|
||||
return SSH_PACKET_USED;
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -198,8 +198,9 @@ int ssh_packet_hmac_verify(ssh_session session,
|
||||
unsigned int len;
|
||||
uint32_t seq;
|
||||
|
||||
/* AEAD type have no mac checking */
|
||||
if (type == SSH_HMAC_AEAD_POLY1305) {
|
||||
/* AEAD types have no mac checking */
|
||||
if (type == SSH_HMAC_AEAD_POLY1305 ||
|
||||
type == SSH_HMAC_AEAD_GCM) {
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
|
||||
60
src/pki.c
60
src/pki.c
@@ -91,10 +91,13 @@ enum ssh_keytypes_e pki_privatekey_type_from_string(const char *privkey) {
|
||||
*/
|
||||
const char *ssh_pki_key_ecdsa_name(const ssh_key key)
|
||||
{
|
||||
if (key == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ECC /* FIXME Better ECC check needed */
|
||||
return pki_key_ecdsa_nid_to_name(key->ecdsa_nid);
|
||||
#else
|
||||
(void) key; /* unused */
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
@@ -214,6 +217,7 @@ ssh_key_signature_to_char(enum ssh_keytypes_e type,
|
||||
case SSH_DIGEST_SHA512:
|
||||
return "rsa-sha2-512";
|
||||
case SSH_DIGEST_SHA1:
|
||||
case SSH_DIGEST_AUTO:
|
||||
return "ssh-rsa";
|
||||
default:
|
||||
return NULL;
|
||||
@@ -271,13 +275,14 @@ static enum ssh_digest_e ssh_key_hash_from_name(const char *name)
|
||||
/* we do not care for others now */
|
||||
return SSH_DIGEST_AUTO;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks the given key against the configured allowed
|
||||
* public key algorithm types
|
||||
*
|
||||
* @param[in] session The SSH session
|
||||
* @parma[in] type The key algorithm to check
|
||||
* @returns 1 if the key algorithm is allowed 0 otherwise
|
||||
* @param[in] type The key algorithm to check
|
||||
* @returns 1 if the key algorithm is allowed, 0 otherwise
|
||||
*/
|
||||
int ssh_key_algorithm_allowed(ssh_session session, const char *type)
|
||||
{
|
||||
@@ -1534,7 +1539,7 @@ int ssh_pki_import_cert_file(const char *filename, ssh_key *pkey)
|
||||
* @param[in] parameter Parameter to the creation of key:
|
||||
* rsa : length of the key in bits (e.g. 1024, 2048, 4096)
|
||||
* dsa : length of the key in bits (e.g. 1024, 2048, 3072)
|
||||
* ecdsa : bits of the key (e.g. 256, 384, 512)
|
||||
* ecdsa : bits of the key (e.g. 256, 384, 521)
|
||||
* @param[out] pkey A pointer to store the allocated private key. You need
|
||||
* to free the memory.
|
||||
*
|
||||
@@ -1863,10 +1868,10 @@ int ssh_pki_import_signature_blob(const ssh_string sig_blob,
|
||||
const ssh_key pubkey,
|
||||
ssh_signature *psig)
|
||||
{
|
||||
ssh_signature sig;
|
||||
ssh_signature sig = NULL;
|
||||
enum ssh_keytypes_e type;
|
||||
enum ssh_digest_e hash_type;
|
||||
ssh_string str;
|
||||
ssh_string algorithm = NULL, blob = NULL;
|
||||
ssh_buffer buf;
|
||||
const char *alg = NULL;
|
||||
int rc;
|
||||
@@ -1888,25 +1893,25 @@ int ssh_pki_import_signature_blob(const ssh_string sig_blob,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
str = ssh_buffer_get_ssh_string(buf);
|
||||
if (str == NULL) {
|
||||
algorithm = ssh_buffer_get_ssh_string(buf);
|
||||
if (algorithm == NULL) {
|
||||
ssh_buffer_free(buf);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
alg = ssh_string_get_char(str);
|
||||
alg = ssh_string_get_char(algorithm);
|
||||
type = ssh_key_type_from_signature_name(alg);
|
||||
hash_type = ssh_key_hash_from_name(alg);
|
||||
ssh_string_free(str);
|
||||
ssh_string_free(algorithm);
|
||||
|
||||
str = ssh_buffer_get_ssh_string(buf);
|
||||
blob = ssh_buffer_get_ssh_string(buf);
|
||||
ssh_buffer_free(buf);
|
||||
if (str == NULL) {
|
||||
if (blob == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
sig = pki_signature_from_blob(pubkey, str, type, hash_type);
|
||||
ssh_string_free(str);
|
||||
sig = pki_signature_from_blob(pubkey, blob, type, hash_type);
|
||||
ssh_string_free(blob);
|
||||
if (sig == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
@@ -1915,24 +1920,24 @@ int ssh_pki_import_signature_blob(const ssh_string sig_blob,
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
int ssh_pki_signature_verify_blob(ssh_session session,
|
||||
ssh_string sig_blob,
|
||||
const ssh_key key,
|
||||
unsigned char *digest,
|
||||
size_t dlen)
|
||||
int ssh_pki_signature_verify(ssh_session session,
|
||||
ssh_signature sig,
|
||||
const ssh_key key,
|
||||
unsigned char *digest,
|
||||
size_t dlen)
|
||||
{
|
||||
ssh_signature sig;
|
||||
int rc;
|
||||
|
||||
rc = ssh_pki_import_signature_blob(sig_blob, key, &sig);
|
||||
if (rc < 0) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_FUNCTIONS,
|
||||
"Going to verify a %s type signature",
|
||||
sig->type_c);
|
||||
|
||||
if (key->type != sig->type) {
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Can not verify %s signature with %s key",
|
||||
sig->type_c, key->type_c);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (key->type == SSH_KEYTYPE_ECDSA) {
|
||||
#if HAVE_ECC
|
||||
@@ -1996,8 +2001,6 @@ int ssh_pki_signature_verify_blob(ssh_session session,
|
||||
hlen);
|
||||
}
|
||||
|
||||
ssh_signature_free(sig);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2202,8 +2205,9 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
|
||||
if (session == NULL || privkey == NULL || !ssh_key_is_private(privkey)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
crypto = session->next_crypto ? session->next_crypto :
|
||||
session->current_crypto;
|
||||
session->current_crypto;
|
||||
|
||||
if (crypto->secret_hash == NULL){
|
||||
ssh_set_error(session,SSH_FATAL,"Missing secret_hash");
|
||||
|
||||
@@ -313,6 +313,9 @@ ssh_pki_openssh_import(const char *text_key,
|
||||
*/
|
||||
if (!private) {
|
||||
rc = ssh_pki_import_pubkey_blob(pubkey0, &key);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to import public key blob");
|
||||
}
|
||||
/* in either case we clean up here */
|
||||
goto out;
|
||||
}
|
||||
@@ -330,7 +333,6 @@ ssh_pki_openssh_import(const char *text_key,
|
||||
|
||||
privkey_buffer = ssh_buffer_new();
|
||||
if (privkey_buffer == NULL) {
|
||||
rc = SSH_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
@@ -516,7 +516,7 @@ int pki_key_generate_rsa(ssh_key key, int parameter){
|
||||
|
||||
int pki_key_generate_dss(ssh_key key, int parameter){
|
||||
int rc;
|
||||
#if OPENSSL_VERSION_NUMBER > 0x10100000L
|
||||
#if OPENSSL_VERSION_NUMBER > 0x00908000L
|
||||
key->dsa = DSA_new();
|
||||
if (key->dsa == NULL) {
|
||||
return SSH_ERROR;
|
||||
@@ -558,7 +558,7 @@ int pki_key_generate_ecdsa(ssh_key key, int parameter) {
|
||||
case 384:
|
||||
nid = NID_secp384r1;
|
||||
break;
|
||||
case 512:
|
||||
case 521:
|
||||
nid = NID_secp521r1;
|
||||
break;
|
||||
case 256:
|
||||
@@ -1038,7 +1038,7 @@ int pki_privkey_build_rsa(ssh_key key,
|
||||
ssh_string n,
|
||||
ssh_string e,
|
||||
ssh_string d,
|
||||
ssh_string iqmp,
|
||||
UNUSED_PARAM(ssh_string iqmp),
|
||||
ssh_string p,
|
||||
ssh_string q)
|
||||
{
|
||||
@@ -1600,6 +1600,14 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
int rc;
|
||||
BIGNUM *pr = NULL, *ps = NULL;
|
||||
|
||||
if (type != pubkey->type) {
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Incompatible public key provided (%d) expecting (%d)",
|
||||
type,
|
||||
pubkey->type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig = ssh_signature_new();
|
||||
if (sig == NULL) {
|
||||
return NULL;
|
||||
@@ -1607,7 +1615,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
|
||||
sig->type = type;
|
||||
sig->hash_type = hash_type;
|
||||
sig->type_c = ssh_key_signature_to_char(type, hash_type);
|
||||
sig->type_c = pubkey->type_c; /* for all types but RSA */
|
||||
|
||||
len = ssh_string_len(sig_blob);
|
||||
|
||||
@@ -1673,6 +1681,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
case SSH_KEYTYPE_RSA:
|
||||
case SSH_KEYTYPE_RSA1:
|
||||
sig = pki_signature_from_rsa_blob(pubkey, sig_blob, sig);
|
||||
sig->type_c = ssh_key_signature_to_char(type, hash_type);
|
||||
break;
|
||||
case SSH_KEYTYPE_ECDSA:
|
||||
#ifdef HAVE_OPENSSL_ECC
|
||||
@@ -1787,7 +1796,15 @@ int pki_signature_verify(ssh_session session,
|
||||
int rc;
|
||||
int nid;
|
||||
|
||||
switch(key->type) {
|
||||
if (key->type != sig->type) {
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Can not verify %s signature with %s key",
|
||||
sig->type_c,
|
||||
key->type_c);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
switch (key->type) {
|
||||
case SSH_KEYTYPE_DSS:
|
||||
rc = DSA_do_verify(hash,
|
||||
hlen,
|
||||
|
||||
@@ -1348,7 +1348,7 @@ int pki_key_generate_ecdsa(ssh_key key, int parameter) {
|
||||
case 384:
|
||||
nid = NID_gcrypt_nistp384;
|
||||
break;
|
||||
case 512:
|
||||
case 521:
|
||||
nid = NID_gcrypt_nistp521;
|
||||
break;
|
||||
case 256:
|
||||
@@ -1848,6 +1848,14 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
size_t rsalen;
|
||||
int rc;
|
||||
|
||||
if (type != pubkey->type) {
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Incompatible public key provided (%d) expecting (%d)",
|
||||
type,
|
||||
pubkey->type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig = ssh_signature_new();
|
||||
if (sig == NULL) {
|
||||
return NULL;
|
||||
@@ -1855,7 +1863,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
|
||||
sig->type = type;
|
||||
sig->hash_type = hash_type;
|
||||
sig->type_c = ssh_key_signature_to_char(type, hash_type);
|
||||
sig->type_c = pubkey->type_c; /* for all types but RSA */
|
||||
|
||||
len = ssh_string_len(sig_blob);
|
||||
|
||||
@@ -1921,6 +1929,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
}
|
||||
sig->type_c = ssh_key_signature_to_char(type, hash_type);
|
||||
break;
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
rc = pki_ed25519_sig_from_blob(sig, sig_blob);
|
||||
@@ -2025,6 +2034,14 @@ int pki_signature_verify(ssh_session session,
|
||||
gcry_sexp_t sexp;
|
||||
gcry_error_t err;
|
||||
|
||||
if (key->type != sig->type) {
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Can not verify %s signature with %s key",
|
||||
sig->type_c,
|
||||
key->type_c);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
switch(key->type) {
|
||||
case SSH_KEYTYPE_DSS:
|
||||
/* That is to mark the number as positive */
|
||||
@@ -2124,7 +2141,6 @@ int pki_signature_verify(ssh_session session,
|
||||
gcry_sexp_release(sexp);
|
||||
if (err) {
|
||||
ssh_set_error(session, SSH_FATAL, "Invalid ECDSA signature");
|
||||
abort();
|
||||
if (gcry_err_code(err) != GPG_ERR_BAD_SIGNATURE) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
|
||||
@@ -897,6 +897,14 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
ssh_signature sig = NULL;
|
||||
int rc;
|
||||
|
||||
if (type != pubkey->type) {
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Incompatible public key provided (%d) expecting (%d)",
|
||||
type,
|
||||
pubkey->type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig = ssh_signature_new();
|
||||
if (sig == NULL) {
|
||||
return NULL;
|
||||
@@ -904,11 +912,12 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
|
||||
sig->type = type;
|
||||
sig->hash_type = hash_type;
|
||||
sig->type_c = ssh_key_signature_to_char(type, hash_type);
|
||||
sig->type_c = pubkey->type_c; /* for all types but RSA */
|
||||
|
||||
switch(type) {
|
||||
case SSH_KEYTYPE_RSA:
|
||||
sig = pki_signature_from_rsa_blob(pubkey, sig_blob, sig);
|
||||
sig->type_c = ssh_key_signature_to_char(type, hash_type);
|
||||
break;
|
||||
case SSH_KEYTYPE_ECDSA: {
|
||||
ssh_buffer b;
|
||||
@@ -999,6 +1008,14 @@ int pki_signature_verify(ssh_session session, const ssh_signature sig, const
|
||||
int rc;
|
||||
mbedtls_md_type_t md = 0;
|
||||
|
||||
if (key->type != sig->type) {
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Can not verify %s signature with %s key",
|
||||
sig->type_c,
|
||||
key->type_c);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
switch (key->type) {
|
||||
case SSH_KEYTYPE_RSA:
|
||||
switch (sig->hash_type) {
|
||||
@@ -1439,7 +1456,7 @@ int pki_key_generate_ecdsa(ssh_key key, int parameter)
|
||||
case 384:
|
||||
nid = NID_mbedtls_nistp384;
|
||||
break;
|
||||
case 512:
|
||||
case 521:
|
||||
nid = NID_mbedtls_nistp521;
|
||||
break;
|
||||
case 256:
|
||||
|
||||
44
src/server.c
44
src/server.c
@@ -518,20 +518,22 @@ static void ssh_server_connection_callback(ssh_session session){
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the client supports extension negotiation, we will send
|
||||
* our supported extensions now. This is the first message after
|
||||
* sending NEWKEYS message and after turning on crypto.
|
||||
*/
|
||||
if (session->extensions &&
|
||||
session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
ssh_server_send_extensions(session);
|
||||
}
|
||||
|
||||
set_status(session,1.0f);
|
||||
session->connected = 1;
|
||||
session->session_state=SSH_SESSION_STATE_AUTHENTICATING;
|
||||
if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED)
|
||||
session->session_state = SSH_SESSION_STATE_AUTHENTICATED;
|
||||
|
||||
/*
|
||||
* If the client supports extension negotiation, we will send
|
||||
* our supported extensions now. This is the first message after
|
||||
* sending NEWKEYS message and after turning on crypto.
|
||||
*/
|
||||
if (session->extensions) {
|
||||
ssh_server_send_extensions(session);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SSH_SESSION_STATE_AUTHENTICATING:
|
||||
@@ -1253,30 +1255,10 @@ int ssh_execute_message_callbacks(ssh_session session){
|
||||
|
||||
int ssh_send_keepalive(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
/* Client denies the request, so the error code is not meaningful */
|
||||
(void)ssh_global_request(session, "keepalive@openssh.com", NULL, 1);
|
||||
|
||||
rc = ssh_buffer_pack(session->out_buffer,
|
||||
"bsb",
|
||||
SSH2_MSG_GLOBAL_REQUEST,
|
||||
"keepalive@openssh.com",
|
||||
1);
|
||||
if (rc != SSH_OK) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ssh_packet_send(session) == SSH_ERROR) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
ssh_handle_packets(session, SSH_TIMEOUT_NONBLOCKING);
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET, "Sent a keepalive");
|
||||
return SSH_OK;
|
||||
|
||||
err:
|
||||
ssh_set_error_oom(session);
|
||||
ssh_buffer_reinit(session->out_buffer);
|
||||
return SSH_ERROR;
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -449,12 +449,13 @@ void ssh_silent_disconnect(ssh_session session) {
|
||||
*
|
||||
* @param[in] blocking Zero for nonblocking mode.
|
||||
*/
|
||||
void ssh_set_blocking(ssh_session session, int blocking) {
|
||||
if (session == NULL) {
|
||||
return;
|
||||
}
|
||||
session->flags &= ~SSH_SESSION_FLAG_BLOCKING;
|
||||
session->flags |= blocking ? SSH_SESSION_FLAG_BLOCKING : 0;
|
||||
void ssh_set_blocking(ssh_session session, int blocking)
|
||||
{
|
||||
if (session == NULL) {
|
||||
return;
|
||||
}
|
||||
session->flags &= ~SSH_SESSION_FLAG_BLOCKING;
|
||||
session->flags |= blocking ? SSH_SESSION_FLAG_BLOCKING : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -463,8 +464,9 @@ void ssh_set_blocking(ssh_session session, int blocking) {
|
||||
* @returns 0 if the session is nonblocking,
|
||||
* @returns 1 if the functions may block.
|
||||
*/
|
||||
int ssh_is_blocking(ssh_session session){
|
||||
return (session->flags&SSH_SESSION_FLAG_BLOCKING) ? 1 : 0;
|
||||
int ssh_is_blocking(ssh_session session)
|
||||
{
|
||||
return (session->flags & SSH_SESSION_FLAG_BLOCKING) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* Waits until the output socket is empty */
|
||||
@@ -643,11 +645,13 @@ int ssh_handle_packets(ssh_session session, int timeout) {
|
||||
* @param[in] session The session handle to use.
|
||||
*
|
||||
* @param[in] timeout Set an upper limit on the time for which this function
|
||||
* will block, in milliseconds. Specifying SSH_TIMEOUT_INFINITE
|
||||
* (-1) means an infinite timeout.
|
||||
* will block, in milliseconds. Specifying
|
||||
* SSH_TIMEOUT_INFINITE (-1) means an infinite timeout.
|
||||
* Specifying SSH_TIMEOUT_USER means to use the timeout
|
||||
* specified in options. 0 means poll will return immediately.
|
||||
* SSH_TIMEOUT_DEFAULT uses blocking parameters of the session.
|
||||
* specified in options. 0 means poll will return
|
||||
* immediately.
|
||||
* SSH_TIMEOUT_DEFAULT uses the session timeout if set or
|
||||
* uses blocking parameters of the session.
|
||||
* This parameter is passed to the poll() function.
|
||||
*
|
||||
* @param[in] fct Termination function to be used to determine if it is
|
||||
@@ -656,46 +660,50 @@ int ssh_handle_packets(ssh_session session, int timeout) {
|
||||
* @return SSH_OK on success, SSH_ERROR otherwise.
|
||||
*/
|
||||
int ssh_handle_packets_termination(ssh_session session,
|
||||
int timeout,
|
||||
long timeout,
|
||||
ssh_termination_function fct,
|
||||
void *user)
|
||||
{
|
||||
struct ssh_timestamp ts;
|
||||
long timeout_ms = SSH_TIMEOUT_INFINITE; /* default timeout */
|
||||
long tm;
|
||||
int ret = SSH_OK;
|
||||
int tm;
|
||||
|
||||
if (timeout == SSH_TIMEOUT_USER) {
|
||||
/* If a timeout has been provided, use it */
|
||||
if (timeout > 0) {
|
||||
timeout_ms = timeout;
|
||||
} else {
|
||||
if (ssh_is_blocking(session)) {
|
||||
timeout = ssh_make_milliseconds(session->opts.timeout,
|
||||
session->opts.timeout_usec);
|
||||
if (timeout == SSH_TIMEOUT_USER || timeout == SSH_TIMEOUT_DEFAULT) {
|
||||
if (session->opts.timeout > 0 ||
|
||||
session->opts.timeout_usec > 0) {
|
||||
timeout_ms =
|
||||
ssh_make_milliseconds(session->opts.timeout,
|
||||
session->opts.timeout_usec);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
timeout = SSH_TIMEOUT_NONBLOCKING;
|
||||
}
|
||||
} else if (timeout == SSH_TIMEOUT_DEFAULT) {
|
||||
if (ssh_is_blocking(session)) {
|
||||
timeout = SSH_TIMEOUT_INFINITE;
|
||||
} else {
|
||||
timeout = SSH_TIMEOUT_NONBLOCKING;
|
||||
timeout_ms = SSH_TIMEOUT_NONBLOCKING;
|
||||
}
|
||||
}
|
||||
|
||||
/* avoid unnecessary syscall for the SSH_TIMEOUT_NONBLOCKING case */
|
||||
if (timeout != SSH_TIMEOUT_NONBLOCKING) {
|
||||
if (timeout_ms != SSH_TIMEOUT_NONBLOCKING) {
|
||||
ssh_timestamp_init(&ts);
|
||||
}
|
||||
|
||||
tm = timeout;
|
||||
tm = timeout_ms;
|
||||
while(!fct(user)) {
|
||||
ret = ssh_handle_packets(session, tm);
|
||||
if (ret == SSH_ERROR) {
|
||||
break;
|
||||
}
|
||||
if (ssh_timeout_elapsed(&ts,timeout)) {
|
||||
if (ssh_timeout_elapsed(&ts, timeout_ms)) {
|
||||
ret = fct(user) ? SSH_OK : SSH_AGAIN;
|
||||
break;
|
||||
}
|
||||
|
||||
tm = ssh_timeout_update(&ts, timeout);
|
||||
tm = ssh_timeout_update(&ts, timeout_ms);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
199
src/sftp.c
199
src/sftp.c
@@ -48,6 +48,7 @@
|
||||
#include "libssh/channels.h"
|
||||
#include "libssh/session.h"
|
||||
#include "libssh/misc.h"
|
||||
#include "libssh/bytearray.h"
|
||||
|
||||
#ifdef WITH_SFTP
|
||||
|
||||
@@ -67,19 +68,6 @@ static void sftp_message_free(sftp_message msg);
|
||||
static void sftp_set_error(sftp_session sftp, int errnum);
|
||||
static void status_msg_free(sftp_status_message status);
|
||||
|
||||
static uint32_t sftp_get_u32(const void *vp)
|
||||
{
|
||||
const uint8_t *p = (const uint8_t *)vp;
|
||||
uint32_t v;
|
||||
|
||||
v = (uint32_t)p[0] << 24;
|
||||
v |= (uint32_t)p[1] << 16;
|
||||
v |= (uint32_t)p[2] << 8;
|
||||
v |= (uint32_t)p[3];
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static sftp_ext sftp_ext_new(void) {
|
||||
sftp_ext ext;
|
||||
|
||||
@@ -127,22 +115,26 @@ sftp_session sftp_new(ssh_session session)
|
||||
|
||||
sftp->ext = sftp_ext_new();
|
||||
if (sftp->ext == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
sftp->read_packet = calloc(1, sizeof(struct sftp_packet_struct));
|
||||
if (sftp->read_packet == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
sftp->read_packet->payload = ssh_buffer_new();
|
||||
if (sftp->read_packet->payload == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
sftp->session = session;
|
||||
sftp->channel = ssh_channel_new(session);
|
||||
if (sftp->channel == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -156,7 +148,6 @@ sftp_session sftp_new(ssh_session session)
|
||||
|
||||
return sftp;
|
||||
error:
|
||||
ssh_set_error_oom(session);
|
||||
if (sftp->ext != NULL) {
|
||||
sftp_ext_free(sftp->ext);
|
||||
}
|
||||
@@ -330,32 +321,41 @@ void sftp_free(sftp_session sftp)
|
||||
SAFE_FREE(sftp);
|
||||
}
|
||||
|
||||
int sftp_packet_write(sftp_session sftp, uint8_t type, ssh_buffer payload){
|
||||
int size;
|
||||
int sftp_packet_write(sftp_session sftp, uint8_t type, ssh_buffer payload)
|
||||
{
|
||||
uint8_t header[5] = {0};
|
||||
uint32_t payload_size;
|
||||
int size;
|
||||
int rc;
|
||||
|
||||
if (ssh_buffer_prepend_data(payload, &type, sizeof(uint8_t)) < 0) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
return -1;
|
||||
}
|
||||
/* Add size of type */
|
||||
payload_size = ssh_buffer_get_len(payload) + sizeof(uint8_t);
|
||||
PUSH_BE_U32(header, 0, payload_size);
|
||||
PUSH_BE_U8(header, 4, type);
|
||||
|
||||
size = htonl(ssh_buffer_get_len(payload));
|
||||
if (ssh_buffer_prepend_data(payload, &size, sizeof(uint32_t)) < 0) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
return -1;
|
||||
}
|
||||
rc = ssh_buffer_prepend_data(payload, header, sizeof(header));
|
||||
if (rc < 0) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
size = ssh_channel_write(sftp->channel, ssh_buffer_get(payload),
|
||||
ssh_buffer_get_len(payload));
|
||||
if (size < 0) {
|
||||
return -1;
|
||||
} else if((uint32_t) size != ssh_buffer_get_len(payload)) {
|
||||
SSH_LOG(SSH_LOG_PACKET,
|
||||
"Had to write %d bytes, wrote only %d",
|
||||
ssh_buffer_get_len(payload),
|
||||
size);
|
||||
}
|
||||
size = ssh_channel_write(sftp->channel,
|
||||
ssh_buffer_get(payload),
|
||||
ssh_buffer_get_len(payload));
|
||||
if (size < 0) {
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return size;
|
||||
if ((uint32_t)size != ssh_buffer_get_len(payload)) {
|
||||
SSH_LOG(SSH_LOG_PACKET,
|
||||
"Had to write %d bytes, wrote only %d",
|
||||
ssh_buffer_get_len(payload),
|
||||
size);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
sftp_packet sftp_packet_read(sftp_session sftp)
|
||||
@@ -377,12 +377,14 @@ sftp_packet sftp_packet_read(sftp_session sftp)
|
||||
rc = ssh_buffer_reinit(packet->payload);
|
||||
if (rc != 0) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
packet->payload = ssh_buffer_new();
|
||||
if (packet->payload == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -398,6 +400,10 @@ sftp_packet sftp_packet_read(sftp_session sftp)
|
||||
} else if (s == 0) {
|
||||
is_eof = ssh_channel_is_eof(sftp->channel);
|
||||
if (is_eof) {
|
||||
ssh_set_error(sftp->session,
|
||||
SSH_FATAL,
|
||||
"Received EOF while reading sftp packet size");
|
||||
sftp_set_error(sftp, SSH_FX_EOF);
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
@@ -405,9 +411,10 @@ sftp_packet sftp_packet_read(sftp_session sftp)
|
||||
}
|
||||
} while (nread < 4);
|
||||
|
||||
size = sftp_get_u32(buffer);
|
||||
size = PULL_BE_U32(buffer, 0);
|
||||
if (size == 0 || size > SFTP_PACKET_SIZE_MAX) {
|
||||
ssh_set_error(sftp->session, SSH_FATAL, "Invalid sftp packet size!");
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -418,6 +425,10 @@ sftp_packet sftp_packet_read(sftp_session sftp)
|
||||
} else if (nread == 0) {
|
||||
is_eof = ssh_channel_is_eof(sftp->channel);
|
||||
if (is_eof) {
|
||||
ssh_set_error(sftp->session,
|
||||
SSH_FATAL,
|
||||
"Received EOF while reading sftp packet type");
|
||||
sftp_set_error(sftp, SSH_FX_EOF);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@@ -431,6 +442,7 @@ sftp_packet sftp_packet_read(sftp_session sftp)
|
||||
nread = ssh_buffer_allocate_size(packet->payload, size);
|
||||
if (nread < 0) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
goto error;
|
||||
}
|
||||
while (size > 0 && size < SFTP_PACKET_SIZE_MAX) {
|
||||
@@ -447,12 +459,17 @@ sftp_packet sftp_packet_read(sftp_session sftp)
|
||||
rc = ssh_buffer_add_data(packet->payload, buffer, nread);
|
||||
if (rc != 0) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
goto error;
|
||||
}
|
||||
} else { /* nread == 0 */
|
||||
/* Retry the reading unless the remote was closed */
|
||||
is_eof = ssh_channel_is_eof(sftp->channel);
|
||||
if (is_eof) {
|
||||
ssh_set_error(sftp->session,
|
||||
SSH_REQUEST_DENIED,
|
||||
"Received EOF while reading sftp packet");
|
||||
sftp_set_error(sftp, SSH_FX_EOF);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@@ -510,12 +527,14 @@ static sftp_message sftp_get_message(sftp_packet packet)
|
||||
SSH_FATAL,
|
||||
"Unknown packet type %d",
|
||||
packet->type);
|
||||
sftp_set_error(packet->sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
msg = calloc(1, sizeof(struct sftp_message_struct));
|
||||
if (msg == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(packet->sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -531,6 +550,7 @@ static sftp_message sftp_get_message(sftp_packet packet)
|
||||
ssh_set_error(packet->sftp->session, SSH_FATAL,
|
||||
"Invalid packet %d: no ID", packet->type);
|
||||
sftp_message_free(msg);
|
||||
sftp_set_error(packet->sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -587,6 +607,7 @@ int sftp_init(sftp_session sftp) {
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -594,6 +615,7 @@ int sftp_init(sftp_session sftp) {
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
ssh_buffer_free(buffer);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
if (sftp_packet_write(sftp, SSH_FXP_INIT, buffer) < 0) {
|
||||
@@ -616,6 +638,7 @@ int sftp_init(sftp_session sftp) {
|
||||
/* TODO: are we sure there are 4 bytes ready? */
|
||||
rc = ssh_buffer_unpack(packet->payload, "d", &version);
|
||||
if (rc != SSH_OK){
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_RARE,
|
||||
@@ -641,6 +664,7 @@ int sftp_init(sftp_session sftp) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
SAFE_FREE(ext_name);
|
||||
SAFE_FREE(ext_data);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
tmp[count - 1] = ext_name;
|
||||
@@ -651,6 +675,7 @@ int sftp_init(sftp_session sftp) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
SAFE_FREE(ext_name);
|
||||
SAFE_FREE(ext_data);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
tmp[count - 1] = ext_data;
|
||||
@@ -736,6 +761,7 @@ static sftp_request_queue request_queue_new(sftp_message msg) {
|
||||
queue = calloc(1, sizeof(struct sftp_request_queue_struct));
|
||||
if (queue == NULL) {
|
||||
ssh_set_error_oom(msg->sftp->session);
|
||||
sftp_set_error(msg->sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -832,12 +858,14 @@ static sftp_status_message parse_status_msg(sftp_message msg){
|
||||
if (msg->packet_type != SSH_FXP_STATUS) {
|
||||
ssh_set_error(msg->sftp->session, SSH_FATAL,
|
||||
"Not a ssh_fxp_status message passed in!");
|
||||
sftp_set_error(msg->sftp, SSH_FX_BAD_MESSAGE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = calloc(1, sizeof(struct sftp_status_message_struct));
|
||||
if (status == NULL) {
|
||||
ssh_set_error_oom(msg->sftp->session);
|
||||
sftp_set_error(msg->sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -848,6 +876,7 @@ static sftp_status_message parse_status_msg(sftp_message msg){
|
||||
SAFE_FREE(status);
|
||||
ssh_set_error(msg->sftp->session, SSH_FATAL,
|
||||
"Invalid SSH_FXP_STATUS message");
|
||||
sftp_set_error(msg->sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
rc = ssh_buffer_unpack(msg->payload, "ss",
|
||||
@@ -859,6 +888,7 @@ static sftp_status_message parse_status_msg(sftp_message msg){
|
||||
SAFE_FREE(status);
|
||||
ssh_set_error(msg->sftp->session, SSH_FATAL,
|
||||
"Invalid SSH_FXP_STATUS message");
|
||||
sftp_set_error(msg->sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
if (status->errormsg == NULL)
|
||||
@@ -867,6 +897,7 @@ static sftp_status_message parse_status_msg(sftp_message msg){
|
||||
status->langmsg = strdup("");
|
||||
if (status->errormsg == NULL || status->langmsg == NULL) {
|
||||
ssh_set_error_oom(msg->sftp->session);
|
||||
sftp_set_error(msg->sftp, SSH_FX_FAILURE);
|
||||
status_msg_free(status);
|
||||
return NULL;
|
||||
}
|
||||
@@ -896,6 +927,7 @@ static sftp_file parse_handle_msg(sftp_message msg){
|
||||
file = calloc(1, sizeof(struct sftp_file_struct));
|
||||
if (file == NULL) {
|
||||
ssh_set_error_oom(msg->sftp->session);
|
||||
sftp_set_error(msg->sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -904,6 +936,7 @@ static sftp_file parse_handle_msg(sftp_message msg){
|
||||
ssh_set_error(msg->sftp->session, SSH_FATAL,
|
||||
"Invalid SSH_FXP_HANDLE message");
|
||||
SAFE_FREE(file);
|
||||
sftp_set_error(msg->sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -925,9 +958,14 @@ sftp_dir sftp_opendir(sftp_session sftp, const char *path)
|
||||
uint32_t id;
|
||||
int rc;
|
||||
|
||||
if (sftp == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
payload = ssh_buffer_new();
|
||||
if (payload == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -940,6 +978,7 @@ sftp_dir sftp_opendir(sftp_session sftp, const char *path)
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
ssh_buffer_free(payload);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1019,6 +1058,7 @@ static sftp_attributes sftp_parse_attr_4(sftp_session sftp, ssh_buffer buf,
|
||||
attr = calloc(1, sizeof(struct sftp_attributes_struct));
|
||||
if (attr == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1236,6 +1276,7 @@ static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf,
|
||||
attr = calloc(1, sizeof(struct sftp_attributes_struct));
|
||||
if (attr == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1365,6 +1406,7 @@ static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf,
|
||||
SAFE_FREE(attr->group);
|
||||
SAFE_FREE(attr);
|
||||
ssh_set_error(sftp->session, SSH_FATAL, "Invalid ATTR structure");
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1453,6 +1495,7 @@ sftp_attributes sftp_readdir(sftp_session sftp, sftp_dir dir)
|
||||
payload = ssh_buffer_new();
|
||||
if (payload == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1464,6 +1507,7 @@ sftp_attributes sftp_readdir(sftp_session sftp, sftp_dir dir)
|
||||
dir->handle);
|
||||
if (rc != 0) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
ssh_buffer_free(payload);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1518,6 +1562,7 @@ sftp_attributes sftp_readdir(sftp_session sftp, sftp_dir dir)
|
||||
ssh_set_error(sftp->session, SSH_FATAL,
|
||||
"Unsupported message back %d", msg->packet_type);
|
||||
sftp_message_free(msg);
|
||||
sftp_set_error(sftp, SSH_FX_BAD_MESSAGE);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1583,6 +1628,7 @@ static int sftp_handle_close(sftp_session sftp, ssh_string handle)
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1595,6 +1641,7 @@ static int sftp_handle_close(sftp_session sftp, ssh_string handle)
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
ssh_buffer_free(buffer);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1636,6 +1683,7 @@ static int sftp_handle_close(sftp_session sftp, ssh_string handle)
|
||||
ssh_set_error(sftp->session, SSH_FATAL,
|
||||
"Received message %d during sftp_handle_close!", msg->packet_type);
|
||||
sftp_message_free(msg);
|
||||
sftp_set_error(sftp, SSH_FX_BAD_MESSAGE);
|
||||
}
|
||||
|
||||
return -1;
|
||||
@@ -1725,6 +1773,7 @@ sftp_file sftp_open(sftp_session sftp,
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
ssh_buffer_free(buffer);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1732,6 +1781,7 @@ sftp_file sftp_open(sftp_session sftp,
|
||||
if (rc < 0) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
ssh_buffer_free(buffer);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1776,6 +1826,7 @@ sftp_file sftp_open(sftp_session sftp,
|
||||
SSH_FATAL,
|
||||
"Cannot open in append mode. Unknown file size.");
|
||||
sftp_close(handle);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1786,6 +1837,7 @@ sftp_file sftp_open(sftp_session sftp,
|
||||
ssh_set_error(sftp->session, SSH_FATAL,
|
||||
"Received message %d during open!", msg->packet_type);
|
||||
sftp_message_free(msg);
|
||||
sftp_set_error(sftp, SSH_FX_BAD_MESSAGE);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -1830,6 +1882,7 @@ ssize_t sftp_read(sftp_file handle, void *buf, size_t count) {
|
||||
if (rc != SSH_OK){
|
||||
ssh_set_error_oom(sftp->session);
|
||||
ssh_buffer_free(buffer);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
if (sftp_packet_write(handle->sftp, SSH_FXP_READ, buffer) < 0) {
|
||||
@@ -1898,6 +1951,7 @@ ssize_t sftp_read(sftp_file handle, void *buf, size_t count) {
|
||||
ssh_set_error(sftp->session, SSH_FATAL,
|
||||
"Received message %d during read!", msg->packet_type);
|
||||
sftp_message_free(msg);
|
||||
sftp_set_error(sftp, SSH_FX_BAD_MESSAGE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1914,6 +1968,7 @@ int sftp_async_read_begin(sftp_file file, uint32_t len){
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1928,6 +1983,7 @@ int sftp_async_read_begin(sftp_file file, uint32_t len){
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
ssh_buffer_free(buffer);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
if (sftp_packet_write(sftp, SSH_FXP_READ, buffer) < 0) {
|
||||
@@ -2018,6 +2074,7 @@ int sftp_async_read(sftp_file file, void *data, uint32_t size, uint32_t id){
|
||||
default:
|
||||
ssh_set_error(sftp->session,SSH_FATAL,"Received message %d during read!",msg->packet_type);
|
||||
sftp_message_free(msg);
|
||||
sftp_set_error(sftp, SSH_FX_BAD_MESSAGE);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
@@ -2037,6 +2094,7 @@ ssize_t sftp_write(sftp_file file, const void *buf, size_t count) {
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2052,6 +2110,7 @@ ssize_t sftp_write(sftp_file file, const void *buf, size_t count) {
|
||||
if (rc != SSH_OK){
|
||||
ssh_set_error_oom(sftp->session);
|
||||
ssh_buffer_free(buffer);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
packetlen=ssh_buffer_get_len(buffer);
|
||||
@@ -2097,6 +2156,7 @@ ssize_t sftp_write(sftp_file file, const void *buf, size_t count) {
|
||||
ssh_set_error(sftp->session, SSH_FATAL,
|
||||
"Received message %d during write!", msg->packet_type);
|
||||
sftp_message_free(msg);
|
||||
sftp_set_error(sftp, SSH_FX_BAD_MESSAGE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2152,6 +2212,7 @@ int sftp_unlink(sftp_session sftp, const char *file) {
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2164,6 +2225,7 @@ int sftp_unlink(sftp_session sftp, const char *file) {
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
ssh_buffer_free(buffer);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2208,6 +2270,7 @@ int sftp_unlink(sftp_session sftp, const char *file) {
|
||||
ssh_set_error(sftp->session,SSH_FATAL,
|
||||
"Received message %d when attempting to remove file", msg->packet_type);
|
||||
sftp_message_free(msg);
|
||||
sftp_set_error(sftp, SSH_FX_BAD_MESSAGE);
|
||||
}
|
||||
|
||||
return -1;
|
||||
@@ -2224,6 +2287,7 @@ int sftp_rmdir(sftp_session sftp, const char *directory) {
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2236,6 +2300,7 @@ int sftp_rmdir(sftp_session sftp, const char *directory) {
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
ssh_buffer_free(buffer);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
if (sftp_packet_write(sftp, SSH_FXP_RMDIR, buffer) < 0) {
|
||||
@@ -2276,6 +2341,7 @@ int sftp_rmdir(sftp_session sftp, const char *directory) {
|
||||
"Received message %d when attempting to remove directory",
|
||||
msg->packet_type);
|
||||
sftp_message_free(msg);
|
||||
sftp_set_error(sftp, SSH_FX_BAD_MESSAGE);
|
||||
}
|
||||
|
||||
return -1;
|
||||
@@ -2295,6 +2361,7 @@ int sftp_mkdir(sftp_session sftp, const char *directory, mode_t mode)
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2311,6 +2378,7 @@ int sftp_mkdir(sftp_session sftp, const char *directory, mode_t mode)
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
ssh_buffer_free(buffer);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2318,6 +2386,7 @@ int sftp_mkdir(sftp_session sftp, const char *directory, mode_t mode)
|
||||
if (rc < 0) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
ssh_buffer_free(buffer);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2375,6 +2444,7 @@ int sftp_mkdir(sftp_session sftp, const char *directory, mode_t mode)
|
||||
"Received message %d when attempting to make directory",
|
||||
msg->packet_type);
|
||||
sftp_message_free(msg);
|
||||
sftp_set_error(sftp, SSH_FX_BAD_MESSAGE);
|
||||
}
|
||||
|
||||
return -1;
|
||||
@@ -2391,6 +2461,7 @@ int sftp_rename(sftp_session sftp, const char *original, const char *newname) {
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2404,6 +2475,7 @@ int sftp_rename(sftp_session sftp, const char *original, const char *newname) {
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
ssh_buffer_free(buffer);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2454,6 +2526,7 @@ int sftp_rename(sftp_session sftp, const char *original, const char *newname) {
|
||||
"Received message %d when attempting to rename",
|
||||
msg->packet_type);
|
||||
sftp_message_free(msg);
|
||||
sftp_set_error(sftp, SSH_FX_BAD_MESSAGE);
|
||||
}
|
||||
|
||||
return -1;
|
||||
@@ -2472,6 +2545,7 @@ int sftp_setstat(sftp_session sftp, const char *file, sftp_attributes attr)
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2484,6 +2558,7 @@ int sftp_setstat(sftp_session sftp, const char *file, sftp_attributes attr)
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
ssh_buffer_free(buffer);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2491,6 +2566,7 @@ int sftp_setstat(sftp_session sftp, const char *file, sftp_attributes attr)
|
||||
if (rc != 0) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
ssh_buffer_free(buffer);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2534,6 +2610,7 @@ int sftp_setstat(sftp_session sftp, const char *file, sftp_attributes attr)
|
||||
ssh_set_error(sftp->session, SSH_FATAL,
|
||||
"Received message %d when attempting to set stats", msg->packet_type);
|
||||
sftp_message_free(msg);
|
||||
sftp_set_error(sftp, SSH_FX_BAD_MESSAGE);
|
||||
}
|
||||
|
||||
return -1;
|
||||
@@ -2591,12 +2668,14 @@ int sftp_symlink(sftp_session sftp, const char *target, const char *dest) {
|
||||
return -1;
|
||||
if (target == NULL || dest == NULL) {
|
||||
ssh_set_error_invalid(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2619,6 +2698,7 @@ int sftp_symlink(sftp_session sftp, const char *target, const char *dest) {
|
||||
if (rc != SSH_OK){
|
||||
ssh_set_error_oom(sftp->session);
|
||||
ssh_buffer_free(buffer);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2662,6 +2742,7 @@ int sftp_symlink(sftp_session sftp, const char *target, const char *dest) {
|
||||
ssh_set_error(sftp->session, SSH_FATAL,
|
||||
"Received message %d when attempting to set stats", msg->packet_type);
|
||||
sftp_message_free(msg);
|
||||
sftp_set_error(sftp, SSH_FX_BAD_MESSAGE);
|
||||
}
|
||||
|
||||
return -1;
|
||||
@@ -2681,15 +2762,18 @@ char *sftp_readlink(sftp_session sftp, const char *path)
|
||||
|
||||
if (path == NULL) {
|
||||
ssh_set_error_invalid(sftp);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
if (sftp->version < 3){
|
||||
ssh_set_error(sftp,SSH_REQUEST_DENIED,"sftp version %d does not support sftp_readlink",sftp->version);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -2702,6 +2786,7 @@ char *sftp_readlink(sftp_session sftp, const char *path)
|
||||
if (rc < 0) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
ssh_buffer_free(buffer);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -2731,6 +2816,7 @@ char *sftp_readlink(sftp_session sftp, const char *path)
|
||||
ssh_set_error(sftp->session,
|
||||
SSH_ERROR,
|
||||
"Failed to retrieve link");
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -2741,6 +2827,7 @@ char *sftp_readlink(sftp_session sftp, const char *path)
|
||||
if (status == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
sftp_set_error(sftp, status->status);
|
||||
ssh_set_error(sftp->session, SSH_REQUEST_DENIED,
|
||||
"SFTP server: %s", status->errormsg);
|
||||
status_msg_free(status);
|
||||
@@ -2748,6 +2835,7 @@ char *sftp_readlink(sftp_session sftp, const char *path)
|
||||
ssh_set_error(sftp->session, SSH_FATAL,
|
||||
"Received message %d when attempting to set stats", msg->packet_type);
|
||||
sftp_message_free(msg);
|
||||
sftp_set_error(sftp, SSH_FX_BAD_MESSAGE);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -2760,6 +2848,7 @@ static sftp_statvfs_t sftp_parse_statvfs(sftp_session sftp, ssh_buffer buf) {
|
||||
statvfs = calloc(1, sizeof(struct sftp_statvfs_struct));
|
||||
if (statvfs == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -2779,6 +2868,7 @@ static sftp_statvfs_t sftp_parse_statvfs(sftp_session sftp, ssh_buffer buf) {
|
||||
if (rc != SSH_OK) {
|
||||
SAFE_FREE(statvfs);
|
||||
ssh_set_error(sftp->session, SSH_FATAL, "Invalid statvfs structure");
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -2797,16 +2887,19 @@ sftp_statvfs_t sftp_statvfs(sftp_session sftp, const char *path)
|
||||
return NULL;
|
||||
if (path == NULL) {
|
||||
ssh_set_error_invalid(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
if (sftp->version < 3){
|
||||
ssh_set_error(sftp,SSH_REQUEST_DENIED,"sftp version %d does not support sftp_statvfs",sftp->version);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -2820,6 +2913,7 @@ sftp_statvfs_t sftp_statvfs(sftp_session sftp, const char *path)
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
ssh_buffer_free(buffer);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -2850,6 +2944,7 @@ sftp_statvfs_t sftp_statvfs(sftp_session sftp, const char *path)
|
||||
if (status == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
sftp_set_error(sftp, status->status);
|
||||
ssh_set_error(sftp->session, SSH_REQUEST_DENIED,
|
||||
"SFTP server: %s", status->errormsg);
|
||||
status_msg_free(status);
|
||||
@@ -2857,6 +2952,7 @@ sftp_statvfs_t sftp_statvfs(sftp_session sftp, const char *path)
|
||||
ssh_set_error(sftp->session, SSH_FATAL,
|
||||
"Received message %d when attempting to get statvfs", msg->packet_type);
|
||||
sftp_message_free(msg);
|
||||
sftp_set_error(sftp, SSH_FX_BAD_MESSAGE);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -2878,6 +2974,7 @@ int sftp_fsync(sftp_file file)
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2890,6 +2987,7 @@ int sftp_fsync(sftp_file file)
|
||||
file->handle);
|
||||
if (rc < 0) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -2949,6 +3047,7 @@ int sftp_fsync(sftp_file file)
|
||||
"Received message %d when attempting to set stats",
|
||||
msg->packet_type);
|
||||
sftp_message_free(msg);
|
||||
sftp_set_error(sftp, SSH_FX_BAD_MESSAGE);
|
||||
}
|
||||
|
||||
rc = -1;
|
||||
@@ -2975,6 +3074,7 @@ sftp_statvfs_t sftp_fstatvfs(sftp_file file)
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -2988,6 +3088,7 @@ sftp_statvfs_t sftp_fstatvfs(sftp_file file)
|
||||
if (rc < 0) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
ssh_buffer_free(buffer);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -3018,6 +3119,7 @@ sftp_statvfs_t sftp_fstatvfs(sftp_file file)
|
||||
if (status == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
sftp_set_error(sftp, status->status);
|
||||
ssh_set_error(sftp->session, SSH_REQUEST_DENIED,
|
||||
"SFTP server: %s", status->errormsg);
|
||||
status_msg_free(status);
|
||||
@@ -3025,6 +3127,7 @@ sftp_statvfs_t sftp_fstatvfs(sftp_file file)
|
||||
ssh_set_error(sftp->session, SSH_FATAL,
|
||||
"Received message %d when attempting to set stats", msg->packet_type);
|
||||
sftp_message_free(msg);
|
||||
sftp_set_error(sftp, SSH_FX_BAD_MESSAGE);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -3051,12 +3154,14 @@ char *sftp_canonicalize_path(sftp_session sftp, const char *path)
|
||||
return NULL;
|
||||
if (path == NULL) {
|
||||
ssh_set_error_invalid(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -3069,6 +3174,7 @@ char *sftp_canonicalize_path(sftp_session sftp, const char *path)
|
||||
if (rc < 0) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
ssh_buffer_free(buffer);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -3098,6 +3204,7 @@ char *sftp_canonicalize_path(sftp_session sftp, const char *path)
|
||||
ssh_set_error(sftp->session,
|
||||
SSH_ERROR,
|
||||
"Failed to parse canonicalized path");
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -3108,6 +3215,7 @@ char *sftp_canonicalize_path(sftp_session sftp, const char *path)
|
||||
if (status == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
sftp_set_error(sftp, status->status);
|
||||
ssh_set_error(sftp->session, SSH_REQUEST_DENIED,
|
||||
"SFTP server: %s", status->errormsg);
|
||||
status_msg_free(status);
|
||||
@@ -3115,6 +3223,7 @@ char *sftp_canonicalize_path(sftp_session sftp, const char *path)
|
||||
ssh_set_error(sftp->session, SSH_FATAL,
|
||||
"Received message %d when attempting to set stats", msg->packet_type);
|
||||
sftp_message_free(msg);
|
||||
sftp_set_error(sftp, SSH_FX_BAD_MESSAGE);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -3130,14 +3239,20 @@ static sftp_attributes sftp_xstat(sftp_session sftp,
|
||||
uint32_t id;
|
||||
int rc;
|
||||
|
||||
if (sftp == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (path == NULL) {
|
||||
ssh_set_error_invalid(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -3150,6 +3265,7 @@ static sftp_attributes sftp_xstat(sftp_session sftp,
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
ssh_buffer_free(buffer);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -3186,6 +3302,7 @@ static sftp_attributes sftp_xstat(sftp_session sftp,
|
||||
ssh_set_error(sftp->session, SSH_FATAL,
|
||||
"Received mesg %d during stat()", msg->packet_type);
|
||||
sftp_message_free(msg);
|
||||
sftp_set_error(sftp, SSH_FX_BAD_MESSAGE);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -3206,9 +3323,14 @@ sftp_attributes sftp_fstat(sftp_file file)
|
||||
uint32_t id;
|
||||
int rc;
|
||||
|
||||
if (file == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(file->sftp->session);
|
||||
sftp_set_error(file->sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -3221,6 +3343,7 @@ sftp_attributes sftp_fstat(sftp_file file)
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(file->sftp->session);
|
||||
ssh_buffer_free(buffer);
|
||||
sftp_set_error(file->sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -3248,6 +3371,7 @@ sftp_attributes sftp_fstat(sftp_file file)
|
||||
if (status == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
sftp_set_error(file->sftp, status->status);
|
||||
ssh_set_error(file->sftp->session, SSH_REQUEST_DENIED,
|
||||
"SFTP server: %s", status->errormsg);
|
||||
status_msg_free(status);
|
||||
@@ -3257,6 +3381,7 @@ sftp_attributes sftp_fstat(sftp_file file)
|
||||
ssh_set_error(file->sftp->session, SSH_FATAL,
|
||||
"Received msg %d during fstat()", msg->packet_type);
|
||||
sftp_message_free(msg);
|
||||
sftp_set_error(file->sftp, SSH_FX_BAD_MESSAGE);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
17
src/socket.c
17
src/socket.c
@@ -236,7 +236,7 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p,
|
||||
(revents & POLLOUT) ? "POLLOUT ":"",
|
||||
(revents & POLLERR) ? "POLLERR":"",
|
||||
ssh_buffer_get_len(s->out_buffer));
|
||||
if (revents & POLLERR || revents & POLLHUP) {
|
||||
if ((revents & POLLERR) || (revents & POLLHUP)) {
|
||||
/* Check if we are in a connecting state */
|
||||
if (s->state == SSH_SOCKET_CONNECTING) {
|
||||
s->state = SSH_SOCKET_ERROR;
|
||||
@@ -270,17 +270,10 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p,
|
||||
s->callbacks->exception(SSH_SOCKET_EXCEPTION_ERROR,
|
||||
s->last_errno,
|
||||
s->callbacks->userdata);
|
||||
|
||||
/* p may have been freed, so don't use it
|
||||
* anymore in this function */
|
||||
p = NULL;
|
||||
return -2;
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
if (nread == 0) {
|
||||
if (p != NULL) {
|
||||
ssh_poll_remove_events(p, POLLIN);
|
||||
}
|
||||
if (p != NULL) {
|
||||
ssh_poll_remove_events(p, POLLIN);
|
||||
}
|
||||
@@ -288,12 +281,8 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p,
|
||||
s->callbacks->exception(SSH_SOCKET_EXCEPTION_EOF,
|
||||
0,
|
||||
s->callbacks->userdata);
|
||||
|
||||
/* p may have been freed, so don't use it
|
||||
* anymore in this function */
|
||||
p = NULL;
|
||||
return -2;
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (s->session->socket_counter != NULL) {
|
||||
|
||||
@@ -116,6 +116,14 @@ void crypto_thread_finalize(void)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENSSL_CRYPTO_THREADID_SET_CALLBACK
|
||||
CRYPTO_THREADID_set_callback(NULL);
|
||||
#else
|
||||
CRYPTO_set_id_callback(NULL);
|
||||
#endif
|
||||
|
||||
CRYPTO_set_locking_callback(NULL);
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
user_callbacks->mutex_destroy(&libcrypto_mutexes[i]);
|
||||
}
|
||||
|
||||
285
src/wrapper.c
285
src/wrapper.c
@@ -56,6 +56,7 @@ static struct ssh_hmac_struct ssh_hmac_tab[] = {
|
||||
{ "hmac-sha2-512", SSH_HMAC_SHA512 },
|
||||
{ "hmac-md5", SSH_HMAC_MD5 },
|
||||
{ "aead-poly1305", SSH_HMAC_AEAD_POLY1305 },
|
||||
{ "aead-gcm", SSH_HMAC_AEAD_GCM },
|
||||
{ NULL, 0}
|
||||
};
|
||||
|
||||
@@ -77,6 +78,8 @@ size_t hmac_digest_len(enum ssh_hmac_e type) {
|
||||
return MD5_DIGEST_LEN;
|
||||
case SSH_HMAC_AEAD_POLY1305:
|
||||
return POLY1305_TAGLEN;
|
||||
case SSH_HMAC_AEAD_GCM:
|
||||
return AES_GCM_TAGLEN;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -221,134 +224,148 @@ void crypto_free(struct ssh_crypto_struct *crypto)
|
||||
SAFE_FREE(crypto);
|
||||
}
|
||||
|
||||
static int crypt_set_algorithms2(ssh_session session){
|
||||
const char *wanted;
|
||||
int i = 0;
|
||||
struct ssh_cipher_struct *ssh_ciphertab=ssh_get_ciphertab();
|
||||
struct ssh_hmac_struct *ssh_hmactab=ssh_get_hmactab();
|
||||
int cmp;
|
||||
static int crypt_set_algorithms2(ssh_session session)
|
||||
{
|
||||
const char *wanted = NULL;
|
||||
struct ssh_cipher_struct *ssh_ciphertab=ssh_get_ciphertab();
|
||||
struct ssh_hmac_struct *ssh_hmactab=ssh_get_hmactab();
|
||||
size_t i = 0;
|
||||
int cmp;
|
||||
|
||||
/*
|
||||
* We must scan the kex entries to find crypto algorithms and set their
|
||||
* appropriate structure.
|
||||
*/
|
||||
/*
|
||||
* We must scan the kex entries to find crypto algorithms and set their
|
||||
* appropriate structure.
|
||||
*/
|
||||
|
||||
/* out */
|
||||
wanted = session->next_crypto->kex_methods[SSH_CRYPT_C_S];
|
||||
while (ssh_ciphertab[i].name && strcmp(wanted, ssh_ciphertab[i].name)) {
|
||||
i++;
|
||||
}
|
||||
/* out */
|
||||
wanted = session->next_crypto->kex_methods[SSH_CRYPT_C_S];
|
||||
for (i = 0; i < 64 && ssh_ciphertab[i].name != NULL; ++i) {
|
||||
cmp = strcmp(wanted, ssh_ciphertab[i].name);
|
||||
if (cmp == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssh_ciphertab[i].name == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"crypt_set_algorithms2: no crypto algorithm function found for %s",
|
||||
wanted);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_PACKET, "Set output algorithm to %s", wanted);
|
||||
if (ssh_ciphertab[i].name == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"crypt_set_algorithms2: no crypto algorithm function found for %s",
|
||||
wanted);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_PACKET, "Set output algorithm to %s", wanted);
|
||||
|
||||
session->next_crypto->out_cipher = cipher_new(i);
|
||||
if (session->next_crypto->out_cipher == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
i = 0;
|
||||
session->next_crypto->out_cipher = cipher_new(i);
|
||||
if (session->next_crypto->out_cipher == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (session->next_crypto->out_cipher->aead_encrypt != NULL){
|
||||
/* this cipher has integrated MAC */
|
||||
wanted = "aead-poly1305";
|
||||
} else {
|
||||
/*
|
||||
* We must scan the kex entries to find hmac algorithms and set their
|
||||
* appropriate structure.
|
||||
*/
|
||||
if (session->next_crypto->out_cipher->aead_encrypt != NULL) {
|
||||
/* this cipher has integrated MAC */
|
||||
if (session->next_crypto->out_cipher->ciphertype == SSH_AEAD_CHACHA20_POLY1305) {
|
||||
wanted = "aead-poly1305";
|
||||
} else {
|
||||
wanted = "aead-gcm";
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* We must scan the kex entries to find hmac algorithms and set their
|
||||
* appropriate structure.
|
||||
*/
|
||||
|
||||
/* out */
|
||||
wanted = session->next_crypto->kex_methods[SSH_MAC_C_S];
|
||||
}
|
||||
/* out */
|
||||
wanted = session->next_crypto->kex_methods[SSH_MAC_C_S];
|
||||
}
|
||||
|
||||
for (i = 0; ssh_hmactab[i].name != NULL; i++) {
|
||||
cmp = strcmp(wanted, ssh_hmactab[i].name);
|
||||
if (cmp == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0; ssh_hmactab[i].name != NULL; i++) {
|
||||
cmp = strcmp(wanted, ssh_hmactab[i].name);
|
||||
if (cmp == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssh_hmactab[i].name == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"crypt_set_algorithms2: no hmac algorithm function found for %s",
|
||||
wanted);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_PACKET, "Set HMAC output algorithm to %s", wanted);
|
||||
if (ssh_hmactab[i].name == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"crypt_set_algorithms2: no hmac algorithm function found for %s",
|
||||
wanted);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_PACKET, "Set HMAC output algorithm to %s", wanted);
|
||||
|
||||
session->next_crypto->out_hmac = ssh_hmactab[i].hmac_type;
|
||||
session->next_crypto->out_hmac = ssh_hmactab[i].hmac_type;
|
||||
|
||||
/* in */
|
||||
wanted = session->next_crypto->kex_methods[SSH_CRYPT_S_C];
|
||||
/* in */
|
||||
wanted = session->next_crypto->kex_methods[SSH_CRYPT_S_C];
|
||||
|
||||
for (i = 0; ssh_ciphertab[i].name != NULL; i++) {
|
||||
cmp = strcmp(wanted, ssh_ciphertab[i].name);
|
||||
if (cmp == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0; ssh_ciphertab[i].name != NULL; i++) {
|
||||
cmp = strcmp(wanted, ssh_ciphertab[i].name);
|
||||
if (cmp == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssh_ciphertab[i].name == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Crypt_set_algorithms: no crypto algorithm function found for %s",
|
||||
wanted);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_PACKET, "Set input algorithm to %s", wanted);
|
||||
if (ssh_ciphertab[i].name == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Crypt_set_algorithms: no crypto algorithm function found for %s",
|
||||
wanted);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_PACKET, "Set input algorithm to %s", wanted);
|
||||
|
||||
session->next_crypto->in_cipher = cipher_new(i);
|
||||
if (session->next_crypto->in_cipher == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
session->next_crypto->in_cipher = cipher_new(i);
|
||||
if (session->next_crypto->in_cipher == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (session->next_crypto->in_cipher->aead_encrypt != NULL){
|
||||
/* this cipher has integrated MAC */
|
||||
wanted = "aead-poly1305";
|
||||
} else {
|
||||
/* we must scan the kex entries to find hmac algorithms and set their appropriate structure */
|
||||
wanted = session->next_crypto->kex_methods[SSH_MAC_S_C];
|
||||
}
|
||||
if (session->next_crypto->in_cipher->aead_encrypt != NULL){
|
||||
/* this cipher has integrated MAC */
|
||||
if (session->next_crypto->in_cipher->ciphertype == SSH_AEAD_CHACHA20_POLY1305) {
|
||||
wanted = "aead-poly1305";
|
||||
} else {
|
||||
wanted = "aead-gcm";
|
||||
}
|
||||
} else {
|
||||
/* we must scan the kex entries to find hmac algorithms and set their appropriate structure */
|
||||
wanted = session->next_crypto->kex_methods[SSH_MAC_S_C];
|
||||
}
|
||||
|
||||
for (i = 0; ssh_hmactab[i].name != NULL; i++) {
|
||||
cmp = strcmp(wanted, ssh_hmactab[i].name);
|
||||
if (cmp == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0; ssh_hmactab[i].name != NULL; i++) {
|
||||
cmp = strcmp(wanted, ssh_hmactab[i].name);
|
||||
if (cmp == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssh_hmactab[i].name == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"crypt_set_algorithms2: no hmac algorithm function found for %s",
|
||||
wanted);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_PACKET, "Set HMAC input algorithm to %s", wanted);
|
||||
if (ssh_hmactab[i].name == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"crypt_set_algorithms2: no hmac algorithm function found for %s",
|
||||
wanted);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_PACKET, "Set HMAC input algorithm to %s", wanted);
|
||||
|
||||
session->next_crypto->in_hmac = ssh_hmactab[i].hmac_type;
|
||||
i = 0;
|
||||
session->next_crypto->in_hmac = ssh_hmactab[i].hmac_type;
|
||||
|
||||
/* compression */
|
||||
if (strcmp(session->next_crypto->kex_methods[SSH_COMP_C_S], "zlib") == 0) {
|
||||
session->next_crypto->do_compress_out = 1;
|
||||
}
|
||||
if (strcmp(session->next_crypto->kex_methods[SSH_COMP_S_C], "zlib") == 0) {
|
||||
session->next_crypto->do_compress_in = 1;
|
||||
}
|
||||
if (strcmp(session->next_crypto->kex_methods[SSH_COMP_C_S], "zlib@openssh.com") == 0) {
|
||||
session->next_crypto->delayed_compress_out = 1;
|
||||
}
|
||||
if (strcmp(session->next_crypto->kex_methods[SSH_COMP_S_C], "zlib@openssh.com") == 0) {
|
||||
session->next_crypto->delayed_compress_in = 1;
|
||||
}
|
||||
/* compression */
|
||||
cmp = strcmp(session->next_crypto->kex_methods[SSH_COMP_C_S], "zlib");
|
||||
if (cmp == 0) {
|
||||
session->next_crypto->do_compress_out = 1;
|
||||
}
|
||||
cmp = strcmp(session->next_crypto->kex_methods[SSH_COMP_S_C], "zlib");
|
||||
if (cmp == 0) {
|
||||
session->next_crypto->do_compress_in = 1;
|
||||
}
|
||||
cmp = strcmp(session->next_crypto->kex_methods[SSH_COMP_C_S], "zlib@openssh.com");
|
||||
if (cmp == 0) {
|
||||
session->next_crypto->delayed_compress_out = 1;
|
||||
}
|
||||
cmp = strcmp(session->next_crypto->kex_methods[SSH_COMP_S_C], "zlib@openssh.com");
|
||||
if (cmp == 0) {
|
||||
session->next_crypto->delayed_compress_in = 1;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
int crypt_set_algorithms_client(ssh_session session)
|
||||
@@ -359,9 +376,11 @@ int crypt_set_algorithms_client(ssh_session session)
|
||||
#ifdef WITH_SERVER
|
||||
int crypt_set_algorithms_server(ssh_session session){
|
||||
const char *method = NULL;
|
||||
int i = 0;
|
||||
size_t i = 0;
|
||||
struct ssh_cipher_struct *ssh_ciphertab=ssh_get_ciphertab();
|
||||
struct ssh_hmac_struct *ssh_hmactab=ssh_get_hmactab();
|
||||
int cmp;
|
||||
|
||||
|
||||
if (session == NULL) {
|
||||
return SSH_ERROR;
|
||||
@@ -375,8 +394,6 @@ int crypt_set_algorithms_server(ssh_session session){
|
||||
method = session->next_crypto->kex_methods[SSH_CRYPT_S_C];
|
||||
|
||||
for (i = 0; ssh_ciphertab[i].name != NULL; i++) {
|
||||
int cmp;
|
||||
|
||||
cmp = strcmp(method, ssh_ciphertab[i].name);
|
||||
if (cmp == 0) {
|
||||
break;
|
||||
@@ -395,10 +412,14 @@ int crypt_set_algorithms_server(ssh_session session){
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
i=0;
|
||||
|
||||
if (session->next_crypto->out_cipher->aead_encrypt != NULL){
|
||||
/* this cipher has integrated MAC */
|
||||
method = "aead-poly1305";
|
||||
if (session->next_crypto->out_cipher->ciphertype == SSH_AEAD_CHACHA20_POLY1305) {
|
||||
method = "aead-poly1305";
|
||||
} else {
|
||||
method = "aead-gcm";
|
||||
}
|
||||
} else {
|
||||
/* we must scan the kex entries to find hmac algorithms and set their appropriate structure */
|
||||
/* out */
|
||||
@@ -406,8 +427,11 @@ int crypt_set_algorithms_server(ssh_session session){
|
||||
}
|
||||
/* HMAC algorithm selection */
|
||||
|
||||
while (ssh_hmactab[i].name && strcmp(method, ssh_hmactab[i].name)) {
|
||||
i++;
|
||||
for (i = 0; ssh_hmactab[i].name != NULL; i++) {
|
||||
cmp = strcmp(method, ssh_hmactab[i].name);
|
||||
if (cmp == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssh_hmactab[i].name == NULL) {
|
||||
@@ -421,16 +445,13 @@ int crypt_set_algorithms_server(ssh_session session){
|
||||
session->next_crypto->out_hmac = ssh_hmactab[i].hmac_type;
|
||||
|
||||
/* in */
|
||||
i=0;
|
||||
method = session->next_crypto->kex_methods[SSH_CRYPT_C_S];
|
||||
|
||||
for (i = 0; ssh_ciphertab[i].name; i++) {
|
||||
int cmp;
|
||||
|
||||
cmp = strcmp(method, ssh_ciphertab[i].name);
|
||||
if (cmp == 0) {
|
||||
break;
|
||||
}
|
||||
cmp = strcmp(method, ssh_ciphertab[i].name);
|
||||
if (cmp == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssh_ciphertab[i].name == NULL) {
|
||||
@@ -445,23 +466,24 @@ int crypt_set_algorithms_server(ssh_session session){
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
i=0;
|
||||
|
||||
if (session->next_crypto->in_cipher->aead_encrypt != NULL){
|
||||
/* this cipher has integrated MAC */
|
||||
method = "aead-poly1305";
|
||||
if (session->next_crypto->in_cipher->ciphertype == SSH_AEAD_CHACHA20_POLY1305) {
|
||||
method = "aead-poly1305";
|
||||
} else {
|
||||
method = "aead-gcm";
|
||||
}
|
||||
} else {
|
||||
/* we must scan the kex entries to find hmac algorithms and set their appropriate structure */
|
||||
method = session->next_crypto->kex_methods[SSH_MAC_C_S];
|
||||
}
|
||||
|
||||
for (i = 0; ssh_hmactab[i].name != NULL; i++) {
|
||||
int cmp;
|
||||
|
||||
cmp = strcmp(method, ssh_hmactab[i].name);
|
||||
if (cmp == 0) {
|
||||
break;
|
||||
}
|
||||
cmp = strcmp(method, ssh_hmactab[i].name);
|
||||
if (cmp == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssh_hmactab[i].name == NULL) {
|
||||
@@ -473,7 +495,6 @@ int crypt_set_algorithms_server(ssh_session session){
|
||||
SSH_LOG(SSH_LOG_PACKET, "Set HMAC input algorithm to %s", method);
|
||||
|
||||
session->next_crypto->in_hmac = ssh_hmactab[i].hmac_type;
|
||||
i=0;
|
||||
|
||||
/* compression */
|
||||
method = session->next_crypto->kex_methods[SSH_COMP_C_S];
|
||||
|
||||
@@ -9,8 +9,6 @@ set(TORTURE_LIBRARY torture)
|
||||
include_directories(
|
||||
${LIBSSH_PUBLIC_INCLUDE_DIRS}
|
||||
${CMOCKA_INCLUDE_DIR}
|
||||
${OPENSSL_INCLUDE_DIR}
|
||||
${GCRYPT_INCLUDE_DIR}
|
||||
${ZLIB_INCLUDE_DIR}
|
||||
${CMAKE_BINARY_DIR}
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
@@ -84,7 +82,7 @@ if (CLIENT_TESTING)
|
||||
|
||||
# chroot_wrapper
|
||||
add_library(chroot_wrapper SHARED chroot_wrapper.c)
|
||||
set(CHROOT_WRAPPER_LIBRARY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}chroot_wrapper${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||
set(CHROOT_WRAPPER_LIBRARY ${libssh_BINARY_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}chroot_wrapper${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||
set(TEST_TARGET_LIBRARIES
|
||||
${TEST_TARGET_LIBRARIES}
|
||||
chroot_wrapper
|
||||
|
||||
@@ -4,6 +4,7 @@ find_package(socket_wrapper)
|
||||
|
||||
set(LIBSSH_CLIENT_TESTS
|
||||
torture_algorithms
|
||||
torture_client_config
|
||||
torture_connect
|
||||
torture_hostkey
|
||||
torture_auth
|
||||
@@ -14,6 +15,11 @@ set(LIBSSH_CLIENT_TESTS
|
||||
torture_session
|
||||
torture_request_env)
|
||||
|
||||
if (DEFAULT_C_NO_DEPRECATION_FLAGS)
|
||||
set_source_files_properties(torture_knownhosts.c
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS ${DEFAULT_C_NO_DEPRECATION_FLAGS})
|
||||
endif()
|
||||
if (WITH_SFTP)
|
||||
if (WITH_BENCHMARKS)
|
||||
set(SFTP_BENCHMARK_TESTS
|
||||
@@ -30,8 +36,11 @@ if (WITH_SFTP)
|
||||
endif (WITH_SFTP)
|
||||
|
||||
foreach(_CLI_TEST ${LIBSSH_CLIENT_TESTS})
|
||||
add_cmocka_test(${_CLI_TEST} ${_CLI_TEST}.c ${TORTURE_LIBRARY})
|
||||
target_compile_options(${_CLI_TEST} PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
add_cmocka_test(${_CLI_TEST}
|
||||
SOURCES ${_CLI_TEST}.c
|
||||
COMPILE_OPTIONS ${DEFAULT_C_COMPILE_FLAGS}
|
||||
LINK_LIBRARIES ${TORTURE_LIBRARY}
|
||||
)
|
||||
|
||||
if (OSX)
|
||||
set_property(
|
||||
|
||||
@@ -90,9 +90,6 @@ static void test_algorithm(ssh_session session,
|
||||
};
|
||||
unsigned int i;
|
||||
|
||||
int verbosity = torture_libssh_verbosity();
|
||||
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||
|
||||
if (kex != NULL) {
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_KEY_EXCHANGE, kex);
|
||||
assert_ssh_return_code(session, rc);
|
||||
@@ -240,6 +237,20 @@ static void torture_algorithms_aes256_ctr_hmac_sha2_512(void **state) {
|
||||
test_algorithm(s->ssh.session, NULL/*kex*/, "aes256-ctr", "hmac-sha2-512");
|
||||
}
|
||||
|
||||
static void torture_algorithms_aes128_gcm(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
|
||||
test_algorithm(s->ssh.session, NULL/*kex*/, "aes128-gcm@openssh.com", NULL);
|
||||
}
|
||||
|
||||
static void torture_algorithms_aes256_gcm(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
|
||||
test_algorithm(s->ssh.session, NULL/*kex*/, "aes256-gcm@openssh.com", NULL);
|
||||
}
|
||||
|
||||
static void torture_algorithms_3des_cbc_hmac_sha1(void **state) {
|
||||
struct torture_state *s = *state;
|
||||
|
||||
@@ -407,6 +418,24 @@ static void torture_algorithms_dh_group1(void **state) {
|
||||
test_algorithm(s->ssh.session, "diffie-hellman-group1-sha1", NULL/*cipher*/, NULL/*hmac*/);
|
||||
}
|
||||
|
||||
static void torture_algorithms_dh_group14(void **state) {
|
||||
struct torture_state *s = *state;
|
||||
|
||||
test_algorithm(s->ssh.session, "diffie-hellman-group14-sha1", NULL/*cipher*/, NULL/*hmac*/);
|
||||
}
|
||||
|
||||
static void torture_algorithms_dh_group16(void **state) {
|
||||
struct torture_state *s = *state;
|
||||
|
||||
test_algorithm(s->ssh.session, "diffie-hellman-group16-sha512", NULL/*cipher*/, NULL/*hmac*/);
|
||||
}
|
||||
|
||||
static void torture_algorithms_dh_group18(void **state) {
|
||||
struct torture_state *s = *state;
|
||||
|
||||
test_algorithm(s->ssh.session, "diffie-hellman-group18-sha512", NULL/*cipher*/, NULL/*hmac*/);
|
||||
}
|
||||
|
||||
int torture_run_tests(void) {
|
||||
int rc;
|
||||
struct CMUnitTest tests[] = {
|
||||
@@ -464,6 +493,12 @@ int torture_run_tests(void) {
|
||||
cmocka_unit_test_setup_teardown(torture_algorithms_aes256_ctr_hmac_sha2_512,
|
||||
session_setup,
|
||||
session_teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_algorithms_aes128_gcm,
|
||||
session_setup,
|
||||
session_teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_algorithms_aes256_gcm,
|
||||
session_setup,
|
||||
session_teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_algorithms_3des_cbc_hmac_sha1,
|
||||
session_setup,
|
||||
session_teardown),
|
||||
@@ -496,6 +531,15 @@ int torture_run_tests(void) {
|
||||
cmocka_unit_test_setup_teardown(torture_algorithms_dh_group1,
|
||||
session_setup,
|
||||
session_teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_algorithms_dh_group14,
|
||||
session_setup,
|
||||
session_teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_algorithms_dh_group16,
|
||||
session_setup,
|
||||
session_teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_algorithms_dh_group18,
|
||||
session_setup,
|
||||
session_teardown),
|
||||
#if ((OPENSSH_VERSION_MAJOR == 7 && OPENSSH_VERSION_MINOR >= 3) || OPENSSH_VERSION_MAJOR > 7)
|
||||
cmocka_unit_test_setup_teardown(torture_algorithms_ecdh_curve25519_sha256,
|
||||
session_setup,
|
||||
|
||||
@@ -52,12 +52,24 @@ static int session_setup(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
int verbosity = torture_libssh_verbosity();
|
||||
struct passwd *pwd;
|
||||
bool b = false;
|
||||
int rc;
|
||||
|
||||
pwd = getpwnam("bob");
|
||||
assert_non_null(pwd);
|
||||
|
||||
rc = setuid(pwd->pw_uid);
|
||||
assert_return_code(rc, errno);
|
||||
|
||||
s->ssh.session = ssh_new();
|
||||
assert_non_null(s->ssh.session);
|
||||
|
||||
ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||
ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
|
||||
/* Make sure no other configuration options from system will get used */
|
||||
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_PROCESS_CONFIG, &b);
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -75,19 +87,12 @@ static int session_teardown(void **state)
|
||||
static int pubkey_setup(void **state)
|
||||
{
|
||||
int rc;
|
||||
struct passwd *pwd;
|
||||
|
||||
rc = session_setup(state);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
pwd = getpwnam("bob");
|
||||
assert_non_null(pwd);
|
||||
|
||||
rc = setuid(pwd->pw_uid);
|
||||
assert_return_code(rc, errno);
|
||||
|
||||
/* Make sure we do not interfere with another ssh-agent */
|
||||
unsetenv("SSH_AUTH_SOCK");
|
||||
unsetenv("SSH_AGENT_PID");
|
||||
@@ -232,7 +237,7 @@ static void torture_auth_none_nonblocking(void **state) {
|
||||
|
||||
/* This request should return a SSH_REQUEST_DENIED error */
|
||||
if (rc == SSH_ERROR) {
|
||||
assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
|
||||
assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);
|
||||
}
|
||||
|
||||
ssh_set_blocking(session,0);
|
||||
@@ -241,7 +246,7 @@ static void torture_auth_none_nonblocking(void **state) {
|
||||
rc = ssh_userauth_none(session,NULL);
|
||||
} while (rc == SSH_AUTH_AGAIN);
|
||||
assert_int_equal(rc, SSH_AUTH_DENIED);
|
||||
assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
|
||||
assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);
|
||||
|
||||
}
|
||||
|
||||
@@ -260,7 +265,7 @@ static void torture_auth_autopubkey(void **state) {
|
||||
rc = ssh_userauth_none(session,NULL);
|
||||
/* This request should return a SSH_REQUEST_DENIED error */
|
||||
if (rc == SSH_ERROR) {
|
||||
assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
|
||||
assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);
|
||||
}
|
||||
rc = ssh_userauth_list(session, NULL);
|
||||
assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);
|
||||
@@ -313,7 +318,7 @@ static void torture_auth_kbdint(void **state) {
|
||||
rc = ssh_userauth_none(session,NULL);
|
||||
/* This request should return a SSH_REQUEST_DENIED error */
|
||||
if (rc == SSH_ERROR) {
|
||||
assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
|
||||
assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);
|
||||
}
|
||||
rc = ssh_userauth_list(session, NULL);
|
||||
assert_true(rc & SSH_AUTH_METHOD_INTERACTIVE);
|
||||
@@ -352,7 +357,7 @@ static void torture_auth_kbdint_nonblocking(void **state) {
|
||||
|
||||
/* This request should return a SSH_REQUEST_DENIED error */
|
||||
if (rc == SSH_ERROR) {
|
||||
assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
|
||||
assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);
|
||||
}
|
||||
rc = ssh_userauth_list(session, NULL);
|
||||
assert_true(rc & SSH_AUTH_METHOD_INTERACTIVE);
|
||||
@@ -392,7 +397,7 @@ static void torture_auth_password(void **state) {
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
/* This request should return a SSH_REQUEST_DENIED error */
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
|
||||
assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);
|
||||
}
|
||||
rc = ssh_userauth_list(session, NULL);
|
||||
assert_true(rc & SSH_AUTH_METHOD_PASSWORD);
|
||||
@@ -419,7 +424,7 @@ static void torture_auth_password_nonblocking(void **state) {
|
||||
|
||||
/* This request should return a SSH_REQUEST_DENIED error */
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
|
||||
assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);
|
||||
}
|
||||
|
||||
rc = ssh_userauth_list(session, NULL);
|
||||
@@ -450,7 +455,7 @@ static void torture_auth_agent(void **state) {
|
||||
rc = ssh_userauth_none(session,NULL);
|
||||
/* This request should return a SSH_REQUEST_DENIED error */
|
||||
if (rc == SSH_ERROR) {
|
||||
assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
|
||||
assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);
|
||||
}
|
||||
rc = ssh_userauth_list(session, NULL);
|
||||
assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);
|
||||
@@ -477,7 +482,7 @@ static void torture_auth_agent_nonblocking(void **state) {
|
||||
rc = ssh_userauth_none(session,NULL);
|
||||
/* This request should return a SSH_REQUEST_DENIED error */
|
||||
if (rc == SSH_ERROR) {
|
||||
assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
|
||||
assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);
|
||||
}
|
||||
rc = ssh_userauth_list(session, NULL);
|
||||
assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);
|
||||
@@ -562,7 +567,7 @@ static void torture_auth_pubkey_types(void **state)
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
/* This request should return a SSH_REQUEST_DENIED error */
|
||||
if (rc == SSH_ERROR) {
|
||||
assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
|
||||
assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);
|
||||
}
|
||||
rc = ssh_userauth_list(session, NULL);
|
||||
assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);
|
||||
@@ -599,7 +604,7 @@ static void torture_auth_pubkey_types_ecdsa(void **state)
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
/* This request should return a SSH_REQUEST_DENIED error */
|
||||
if (rc == SSH_ERROR) {
|
||||
assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
|
||||
assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);
|
||||
}
|
||||
rc = ssh_userauth_list(session, NULL);
|
||||
assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);
|
||||
@@ -637,7 +642,7 @@ static void torture_auth_pubkey_types_ed25519(void **state)
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
/* This request should return a SSH_REQUEST_DENIED error */
|
||||
if (rc == SSH_ERROR) {
|
||||
assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
|
||||
assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);
|
||||
}
|
||||
rc = ssh_userauth_list(session, NULL);
|
||||
assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);
|
||||
|
||||
200
tests/client/torture_client_config.c
Normal file
200
tests/client/torture_client_config.c
Normal file
@@ -0,0 +1,200 @@
|
||||
#include "config.h"
|
||||
|
||||
#define LIBSSH_STATIC
|
||||
|
||||
#include <pwd.h>
|
||||
#include <errno.h>
|
||||
#include "torture.h"
|
||||
#include "libssh/session.h"
|
||||
#include "libssh/misc.h"
|
||||
|
||||
#define LIBSSH_SSH_CONFIG "libssh_config"
|
||||
|
||||
#define TORTURE_CONFIG_USER "test-user"
|
||||
|
||||
#define CIPHERS "aes256-gcm@openssh.com,chacha20-poly1305@openssh.com"
|
||||
#define CIPHERS2 "aes256-cbc,aes128-ctr"
|
||||
|
||||
static int sshd_setup(void **state)
|
||||
{
|
||||
torture_setup_sshd_server(state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sshd_teardown(void **state) {
|
||||
torture_teardown_sshd_server(state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_config_files(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
int verbosity;
|
||||
struct passwd *pwd;
|
||||
char *filename = NULL;
|
||||
int rc;
|
||||
|
||||
/* Work under the bob's UID to be able to load his configuration file */
|
||||
pwd = getpwnam("bob");
|
||||
assert_non_null(pwd);
|
||||
|
||||
rc = setuid(pwd->pw_uid);
|
||||
assert_return_code(rc, errno);
|
||||
|
||||
s->ssh.session = ssh_new();
|
||||
assert_non_null(s->ssh.session);
|
||||
|
||||
filename = ssh_path_expand_tilde("~/.ssh/config");
|
||||
torture_write_file(filename, "Ciphers "CIPHERS"\nTestBogus1\nUser "TORTURE_CONFIG_USER);
|
||||
free(filename);
|
||||
|
||||
torture_write_file(LIBSSH_SSH_CONFIG, "Ciphers "CIPHERS2"\nTestBogus2\n");
|
||||
|
||||
verbosity = torture_libssh_verbosity();
|
||||
ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||
ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int teardown(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
char *filename;
|
||||
|
||||
filename = ssh_path_expand_tilde("~/.ssh/config");
|
||||
if (filename != NULL) {
|
||||
if (strlen(filename) > 0) {
|
||||
unlink(filename);
|
||||
}
|
||||
SAFE_FREE(filename);
|
||||
}
|
||||
|
||||
unlink(LIBSSH_SSH_CONFIG);
|
||||
|
||||
ssh_disconnect(s->ssh.session);
|
||||
ssh_free(s->ssh.session);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This tests makes sure that parsing both system-wide and per-user
|
||||
* configuration files retains OpenSSH semantics (the per-user overrides
|
||||
* the system-wide values).
|
||||
* This function ssh_options_parse_config() has hardcoded path to the
|
||||
* system-wide configuration file so this might not test anything at all
|
||||
* if this system-wide file does not overwrite this option.
|
||||
*/
|
||||
static void torture_client_config_system(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
int ret = 0;
|
||||
|
||||
/* The first tests assumes there is system-wide configuration file
|
||||
* setting Ciphers to some non-default value. We do not have any control
|
||||
* of that in this test case.
|
||||
*/
|
||||
ret = ssh_options_parse_config(s->ssh.session, NULL);
|
||||
assert_ssh_return_code(s->ssh.session, ret);
|
||||
|
||||
assert_string_equal(s->ssh.session->opts.wanted_methods[SSH_CRYPT_C_S], CIPHERS);
|
||||
assert_string_equal(s->ssh.session->opts.wanted_methods[SSH_CRYPT_S_C], CIPHERS);
|
||||
|
||||
/* Make sure the configuration was processed and user modified */
|
||||
assert_string_equal(s->ssh.session->opts.username, TORTURE_CONFIG_USER);
|
||||
}
|
||||
|
||||
/* This tests makes sure that parsing both system-wide and per-user
|
||||
* configuration files retains OpenSSH semantics (the per-user overrides
|
||||
* the system-wide values).
|
||||
* The function ssh_options_parse_config() has hardcoded path to the
|
||||
* system-wide configuraion file so we try to emmulate the behavior by parsing
|
||||
* the files separately in the same order.
|
||||
*/
|
||||
static void torture_client_config_emulate(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
char *filename = NULL;
|
||||
int ret = 0;
|
||||
|
||||
/* The first tests assumes there is system-wide configuration file
|
||||
* setting Ciphers to some non-default value. We do not have any control
|
||||
* of that in this test case
|
||||
*/
|
||||
filename = ssh_path_expand_tilde("~/.ssh/config");
|
||||
ret = ssh_options_parse_config(s->ssh.session, filename);
|
||||
free(filename);
|
||||
assert_ssh_return_code(s->ssh.session, ret);
|
||||
|
||||
ret = ssh_options_parse_config(s->ssh.session, LIBSSH_SSH_CONFIG);
|
||||
assert_ssh_return_code(s->ssh.session, ret);
|
||||
|
||||
assert_non_null(s->ssh.session->opts.wanted_methods[SSH_CRYPT_C_S]);
|
||||
assert_string_equal(s->ssh.session->opts.wanted_methods[SSH_CRYPT_C_S], CIPHERS);
|
||||
assert_non_null(s->ssh.session->opts.wanted_methods[SSH_CRYPT_S_C]);
|
||||
assert_string_equal(s->ssh.session->opts.wanted_methods[SSH_CRYPT_S_C], CIPHERS);
|
||||
|
||||
/* Make sure the configuration was processed and user modified */
|
||||
assert_string_equal(s->ssh.session->opts.username, TORTURE_CONFIG_USER);
|
||||
}
|
||||
|
||||
/* This verifies that configuration files are parsed by default.
|
||||
*/
|
||||
static void torture_client_config_autoparse(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
int ret = 0;
|
||||
|
||||
ret = ssh_connect(s->ssh.session);
|
||||
assert_ssh_return_code(s->ssh.session, ret);
|
||||
|
||||
/* Make sure the configuration was processed and user modified */
|
||||
assert_string_equal(s->ssh.session->opts.username, TORTURE_CONFIG_USER);
|
||||
}
|
||||
|
||||
/* This verifies that we are able to suppress parsing of the configuration files
|
||||
* on connect using an option.
|
||||
*/
|
||||
static void torture_client_config_suppress(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
bool b = false;
|
||||
int ret = 0;
|
||||
|
||||
ret = ssh_options_set(s->ssh.session, SSH_OPTIONS_PROCESS_CONFIG, &b);
|
||||
assert_ssh_return_code(s->ssh.session, ret);
|
||||
|
||||
ret = ssh_connect(s->ssh.session);
|
||||
assert_ssh_return_code(s->ssh.session, ret);
|
||||
|
||||
/* Make sure the configuration was not processed and user modified */
|
||||
assert_string_equal(s->ssh.session->opts.username, "bob");
|
||||
}
|
||||
|
||||
|
||||
int torture_run_tests(void) {
|
||||
int rc;
|
||||
struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(torture_client_config_system,
|
||||
setup_config_files,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_client_config_emulate,
|
||||
setup_config_files,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_client_config_autoparse,
|
||||
setup_config_files,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_client_config_suppress,
|
||||
setup_config_files,
|
||||
teardown),
|
||||
};
|
||||
|
||||
|
||||
ssh_init();
|
||||
torture_filter_tests(tests);
|
||||
rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown);
|
||||
ssh_finalize();
|
||||
return rc;
|
||||
}
|
||||
@@ -68,6 +68,7 @@ static int session_setup(void **state)
|
||||
assert_non_null(s->ssh.session);
|
||||
|
||||
ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||
ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, BLACKHOLE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -82,6 +82,9 @@ static void torture_ssh_forward(void **state)
|
||||
int dport;
|
||||
int bound_port;
|
||||
int rc;
|
||||
int verbosity = SSH_LOG_TRACE;
|
||||
|
||||
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||
|
||||
rc = ssh_channel_listen_forward(session, "127.0.0.21", 8080, &bound_port);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
@@ -163,7 +163,7 @@ static void torture_hostkey_ecdsa(void **state) {
|
||||
static void torture_hostkey_rsa_sha256(void **state) {
|
||||
struct torture_state *s = *state;
|
||||
ssh_session session = s->ssh.session;
|
||||
char rsa[] = "rsa-sha2-256,ssh-rsa";
|
||||
char rsa[] = "rsa-sha2-256";
|
||||
|
||||
int rc;
|
||||
|
||||
@@ -182,7 +182,7 @@ static void torture_hostkey_rsa_sha256(void **state) {
|
||||
static void torture_hostkey_rsa_sha512(void **state) {
|
||||
struct torture_state *s = *state;
|
||||
ssh_session session = s->ssh.session;
|
||||
char rsa[] = "rsa-sha2-512,ssh-rsa";
|
||||
char rsa[] = "rsa-sha2-512";
|
||||
|
||||
int rc;
|
||||
|
||||
|
||||
@@ -328,6 +328,41 @@ static void torture_knownhosts_conflict(void **state) {
|
||||
/* session will be freed by session_teardown() */
|
||||
}
|
||||
|
||||
static void torture_knownhosts_no_hostkeychecking(void **state)
|
||||
{
|
||||
|
||||
struct torture_state *s = *state;
|
||||
ssh_session session = s->ssh.session;
|
||||
char known_hosts_file[1024] = {0};
|
||||
enum ssh_known_hosts_e found;
|
||||
int strict_host_key_checking = 0;
|
||||
int rc;
|
||||
|
||||
snprintf(known_hosts_file,
|
||||
sizeof(known_hosts_file),
|
||||
"%s/%s",
|
||||
s->socket_dir,
|
||||
TORTURE_KNOWN_HOSTS_FILE);
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "ssh-ed25519");
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
found = ssh_session_is_known_server(session);
|
||||
assert_int_equal(found, SSH_KNOWN_HOSTS_UNKNOWN);
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_STRICTHOSTKEYCHECK, &strict_host_key_checking);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
found = ssh_session_is_known_server(session);
|
||||
assert_int_equal(found, SSH_KNOWN_HOSTS_OK);
|
||||
}
|
||||
|
||||
int torture_run_tests(void) {
|
||||
int rc;
|
||||
struct CMUnitTest tests[] = {
|
||||
@@ -346,6 +381,9 @@ int torture_run_tests(void) {
|
||||
cmocka_unit_test_setup_teardown(torture_knownhosts_conflict,
|
||||
session_setup,
|
||||
session_teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_knownhosts_no_hostkeychecking,
|
||||
session_setup,
|
||||
session_teardown),
|
||||
};
|
||||
|
||||
ssh_init();
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
static int sshd_setup(void **state)
|
||||
{
|
||||
@@ -61,11 +62,16 @@ static void torture_options_set_proxycommand(void **state) {
|
||||
struct torture_state *s = *state;
|
||||
ssh_session session = s->ssh.session;
|
||||
int rc;
|
||||
socket_t fd;
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, "nc 127.0.0.10 22");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = ssh_connect(session);
|
||||
assert_ssh_return_code(session, rc);
|
||||
fd = ssh_get_fd(session);
|
||||
assert_true(fd != SSH_INVALID_SOCKET);
|
||||
rc = fcntl(fd, F_GETFL);
|
||||
assert_int_equal(rc & O_RDWR, O_RDWR);
|
||||
}
|
||||
|
||||
static void torture_options_set_proxycommand_notexist(void **state) {
|
||||
|
||||
@@ -5,8 +5,6 @@ if (WITH_SERVER AND UNIX AND NOT WIN32)
|
||||
include_directories(
|
||||
${LIBSSH_PUBLIC_INCLUDE_DIRS}
|
||||
${CMOCKA_INCLUDE_DIR}
|
||||
${OPENSSL_INCLUDE_DIR}
|
||||
${GCRYPT_INCLUDE_DIR}
|
||||
${ZLIB_INCLUDE_DIR}
|
||||
${CMAKE_BINARY_DIR}
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
|
||||
@@ -35,7 +35,7 @@ struct pkd_daemon_args {
|
||||
unsigned int iterations;
|
||||
|
||||
struct {
|
||||
const char *mkdtemp_str;
|
||||
char *mkdtemp_str;
|
||||
} socket_wrapper;
|
||||
} opts;
|
||||
};
|
||||
|
||||
@@ -383,6 +383,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
||||
#endif
|
||||
|
||||
#define CHACHA20 "chacha20-poly1305@openssh.com"
|
||||
#define AES128_GCM "aes128-gcm@openssh.com"
|
||||
#define AES256_GCM "aes256-gcm@openssh.com"
|
||||
|
||||
#ifdef HAVE_DSA
|
||||
#define PKDTESTS_CIPHER_OPENSSHONLY(f, client, ciphercmd) \
|
||||
@@ -390,9 +392,13 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
||||
f(client, rsa_aes192_cbc, ciphercmd("aes192-cbc"), setup_rsa, teardown) \
|
||||
f(client, rsa_aes192_ctr, ciphercmd("aes192-ctr"), setup_rsa, teardown) \
|
||||
f(client, rsa_chacha20, ciphercmd(CHACHA20), setup_rsa, teardown) \
|
||||
f(client, rsa_aes128_gcm, ciphercmd(AES128_GCM), setup_rsa, teardown) \
|
||||
f(client, rsa_aes256_gcm, ciphercmd(AES256_GCM), setup_rsa, teardown) \
|
||||
f(client, dsa_aes192_cbc, ciphercmd("aes192-cbc"), setup_dsa, teardown) \
|
||||
f(client, dsa_aes192_ctr, ciphercmd("aes192-ctr"), setup_dsa, teardown) \
|
||||
f(client, dsa_chacha20, ciphercmd(CHACHA20), setup_dsa, teardown) \
|
||||
f(client, dsa_aes128_gcm, ciphercmd(AES128_GCM), setup_dsa, teardown) \
|
||||
f(client, dsa_aes256_gcm, ciphercmd(AES256_GCM), setup_dsa, teardown) \
|
||||
f(client, ed25519_3des_cbc, ciphercmd("3des-cbc"), setup_ed25519, teardown) \
|
||||
f(client, ed25519_aes128_cbc, ciphercmd("aes128-cbc"), setup_ed25519, teardown) \
|
||||
f(client, ed25519_aes128_ctr, ciphercmd("aes128-ctr"), setup_ed25519, teardown) \
|
||||
@@ -401,21 +407,31 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
||||
f(client, ed25519_aes192_cbc, ciphercmd("aes192-cbc"), setup_ed25519, teardown) \
|
||||
f(client, ed25519_aes192_ctr, ciphercmd("aes192-ctr"), setup_ed25519, teardown) \
|
||||
f(client, ed25519_chacha20, ciphercmd(CHACHA20), setup_ed25519, teardown) \
|
||||
f(client, ed25519_aes128_gcm, ciphercmd(AES128_GCM), setup_ed25519, teardown) \
|
||||
f(client, ed25519_aes256_gcm, ciphercmd(AES256_GCM), setup_ed25519, teardown) \
|
||||
f(client, ecdsa_256_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_chacha20, ciphercmd(CHACHA20), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_aes128_gcm, ciphercmd(AES128_GCM), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_aes256_gcm, ciphercmd(AES256_GCM), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_384_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_chacha20, ciphercmd(CHACHA20), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_aes128_gcm, ciphercmd(AES128_GCM), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_aes256_gcm, ciphercmd(AES256_GCM), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_521_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_chacha20, ciphercmd(CHACHA20), setup_ecdsa_521, teardown)
|
||||
f(client, ecdsa_521_chacha20, ciphercmd(CHACHA20), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_aes128_gcm, ciphercmd(AES128_GCM), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_aes256_gcm, ciphercmd(AES256_GCM), setup_ecdsa_521, teardown)
|
||||
#else
|
||||
#define PKDTESTS_CIPHER_OPENSSHONLY(f, client, ciphercmd) \
|
||||
/* Ciphers. */ \
|
||||
f(client, rsa_aes192_cbc, ciphercmd("aes192-cbc"), setup_rsa, teardown) \
|
||||
f(client, rsa_aes192_ctr, ciphercmd("aes192-ctr"), setup_rsa, teardown) \
|
||||
f(client, rsa_chacha20, ciphercmd(CHACHA20), setup_rsa, teardown) \
|
||||
f(client, rsa_aes128_gcm, ciphercmd(AES128_GCM), setup_rsa, teardown) \
|
||||
f(client, rsa_aes256_gcm, ciphercmd(AES256_GCM), setup_rsa, teardown) \
|
||||
f(client, ed25519_3des_cbc, ciphercmd("3des-cbc"), setup_ed25519, teardown) \
|
||||
f(client, ed25519_aes128_cbc, ciphercmd("aes128-cbc"), setup_ed25519, teardown) \
|
||||
f(client, ed25519_aes128_ctr, ciphercmd("aes128-ctr"), setup_ed25519, teardown) \
|
||||
@@ -424,17 +440,26 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
||||
f(client, ed25519_aes192_cbc, ciphercmd("aes192-cbc"), setup_ed25519, teardown) \
|
||||
f(client, ed25519_aes192_ctr, ciphercmd("aes192-ctr"), setup_ed25519, teardown) \
|
||||
f(client, ed25519_chacha20, ciphercmd(CHACHA20), setup_ed25519, teardown) \
|
||||
f(client, ed25519_aes128_gcm, ciphercmd(AES128_GCM), setup_ed25519, teardown) \
|
||||
f(client, ed25519_aes256_gcm, ciphercmd(AES256_GCM), setup_ed25519, teardown) \
|
||||
f(client, ecdsa_256_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_chacha20, ciphercmd(CHACHA20), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_aes128_gcm, ciphercmd(AES128_GCM), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_aes256_gcm, ciphercmd(AES256_GCM), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_384_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_chacha20, ciphercmd(CHACHA20), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_aes128_gcm, ciphercmd(AES128_GCM), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_aes256_gcm, ciphercmd(AES256_GCM), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_521_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_chacha20, ciphercmd(CHACHA20), setup_ecdsa_521, teardown)
|
||||
f(client, ecdsa_521_chacha20, ciphercmd(CHACHA20), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_aes128_gcm, ciphercmd(AES128_GCM), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_aes256_gcm, ciphercmd(AES256_GCM), setup_ecdsa_521, teardown)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_DSA
|
||||
#define PKDTESTS_MAC(f, client, maccmd) \
|
||||
/* MACs. */ \
|
||||
@@ -849,6 +874,8 @@ static int pkd_cleanup_socket_wrapper(void) {
|
||||
goto errrmdir;
|
||||
}
|
||||
|
||||
free(pkd_dargs.opts.socket_wrapper.mkdtemp_str);
|
||||
|
||||
goto out;
|
||||
errrmdir:
|
||||
errrmfiles:
|
||||
|
||||
422
tests/torture.c
422
tests/torture.c
@@ -38,15 +38,20 @@
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#elif (defined _WIN32) || (defined _WIN64)
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#define read _read
|
||||
#define open _open
|
||||
#define write _write
|
||||
#define close _close
|
||||
#define chdir _chdir
|
||||
#endif
|
||||
|
||||
#include "torture.h"
|
||||
#include "torture_key.h"
|
||||
#include "libssh/misc.h"
|
||||
|
||||
/* for pattern matching */
|
||||
#include "match.c"
|
||||
|
||||
#define TORTURE_SSHD_SRV_IPV4 "127.0.0.10"
|
||||
/* socket wrapper IPv6 prefix fd00::5357:5fxx */
|
||||
#define TORTURE_SSHD_SRV_IPV6 "fd00::5357:5f0a"
|
||||
@@ -425,7 +430,7 @@ failed:
|
||||
}
|
||||
ssh_disconnect(t->ssh);
|
||||
ssh_free(t->ssh);
|
||||
free(t);
|
||||
free(t);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -497,11 +502,10 @@ void torture_setup_socket_dir(void **state)
|
||||
s = malloc(sizeof(struct torture_state));
|
||||
assert_non_null(s);
|
||||
|
||||
s->socket_dir = strdup(TORTURE_SOCKET_DIR);
|
||||
s->socket_dir = torture_make_temp_dir(TORTURE_SOCKET_DIR);
|
||||
assert_non_null(s->socket_dir);
|
||||
|
||||
p = mkdtemp(s->socket_dir);
|
||||
assert_non_null(p);
|
||||
p = s->socket_dir;
|
||||
|
||||
/* pcap file */
|
||||
len = strlen(p) + 1 + strlen(TORTURE_PCAP_FILE) + 1;
|
||||
@@ -785,37 +789,361 @@ void torture_teardown_sshd_server(void **state)
|
||||
torture_teardown_socket_dir(state);
|
||||
}
|
||||
|
||||
char *torture_make_temp_dir(const char *template)
|
||||
{
|
||||
char *new_dir = NULL;
|
||||
char *template_copy = NULL;
|
||||
|
||||
if (template == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
template_copy = strdup(template);
|
||||
if (template_copy == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
new_dir = mkdtemp(template_copy);
|
||||
if (new_dir == NULL) {
|
||||
SAFE_FREE(template_copy);
|
||||
}
|
||||
|
||||
end:
|
||||
return template_copy;
|
||||
}
|
||||
|
||||
char *torture_create_temp_file(const char *template)
|
||||
{
|
||||
char *new_file = NULL;
|
||||
FILE *fp = NULL;
|
||||
mode_t mask;
|
||||
int fd;
|
||||
|
||||
new_file = strdup(template);
|
||||
if (new_file == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
mask = umask(S_IRWXO | S_IRWXG);
|
||||
fd = mkstemp(new_file);
|
||||
umask(mask);
|
||||
if (fd == -1) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
fp = fdopen(fd, "w");
|
||||
if (fp == NULL) {
|
||||
SAFE_FREE(new_file);
|
||||
close(fd);
|
||||
goto end;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
end:
|
||||
return new_file;
|
||||
}
|
||||
|
||||
char *torture_get_current_working_dir(void)
|
||||
{
|
||||
|
||||
char *cwd = NULL;
|
||||
char *result = NULL;
|
||||
|
||||
cwd = (char *)malloc(PATH_MAX + 1);
|
||||
if (cwd == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
result = getcwd(cwd, PATH_MAX);
|
||||
|
||||
if (result == NULL) {
|
||||
SAFE_FREE(cwd);
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
return cwd;
|
||||
}
|
||||
|
||||
#else /* _WIN32 */
|
||||
|
||||
char *torture_make_temp_dir(const char *template)
|
||||
{
|
||||
DWORD rc = 0;
|
||||
char tmp_dir_path[MAX_PATH];
|
||||
char tmp_file_name[MAX_PATH];
|
||||
char *prefix = NULL;
|
||||
char *path = NULL;
|
||||
char *prefix_end = NULL;
|
||||
char *slash = NULL;
|
||||
|
||||
BOOL created;
|
||||
|
||||
if (template == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
prefix = strdup(template);
|
||||
if (prefix == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Replace slashes with backslashes */
|
||||
slash = strchr(prefix, '/');
|
||||
for (; slash != NULL; slash = strchr(prefix, '/')) {
|
||||
*slash = '\\';
|
||||
}
|
||||
|
||||
prefix_end = strstr(prefix, "XXXXXX");
|
||||
if (prefix_end != NULL) {
|
||||
*prefix_end = '\0';
|
||||
}
|
||||
|
||||
rc = GetTempPathA(MAX_PATH, tmp_dir_path);
|
||||
if ((rc > MAX_PATH) || (rc == 0)) {
|
||||
goto free_prefix;
|
||||
}
|
||||
|
||||
rc = GetTempFileNameA(tmp_dir_path, TEXT(prefix), 0, tmp_file_name);
|
||||
if (rc == 0) {
|
||||
goto free_prefix;
|
||||
}
|
||||
|
||||
path = strdup(tmp_file_name);
|
||||
if (path == NULL) {
|
||||
goto free_prefix;
|
||||
}
|
||||
|
||||
/* GetTempFileNameA() creates a temporary file; we need to remove it */
|
||||
rc = DeleteFileA(path);
|
||||
if (rc == 0) {
|
||||
rc = -1;
|
||||
SAFE_FREE(path);
|
||||
goto free_prefix;
|
||||
}
|
||||
|
||||
created = CreateDirectoryA(path, NULL);
|
||||
if (!created) {
|
||||
SAFE_FREE(path);
|
||||
}
|
||||
|
||||
free_prefix:
|
||||
SAFE_FREE(prefix);
|
||||
end:
|
||||
return path;
|
||||
}
|
||||
|
||||
static int recursive_rm_dir_content(const char *path)
|
||||
{
|
||||
WIN32_FIND_DATA file_data;
|
||||
HANDLE file_handle;
|
||||
DWORD attributes;
|
||||
|
||||
DWORD last_error = 0;
|
||||
|
||||
char file_path[MAX_PATH];
|
||||
|
||||
int rc = 0;
|
||||
BOOL removed;
|
||||
|
||||
strcpy(file_path, path);
|
||||
strcat(file_path, "\\*");
|
||||
|
||||
file_handle = FindFirstFile(file_path, &file_data);
|
||||
|
||||
if (file_handle == INVALID_HANDLE_VALUE) {
|
||||
last_error = GetLastError();
|
||||
|
||||
/* Empty directory */
|
||||
if (last_error == ERROR_FILE_NOT_FOUND) {
|
||||
rc = 0;
|
||||
}
|
||||
else {
|
||||
/*TODO print error message?*/
|
||||
rc = last_error;
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
else {
|
||||
do {
|
||||
rc = strcmp(file_data.cFileName, ".");
|
||||
if (rc == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
rc = strcmp(file_data.cFileName, "..");
|
||||
if (rc == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Create full file path */
|
||||
strcpy(file_path, path);
|
||||
strcat(file_path, "\\");
|
||||
strcat(file_path, file_data.cFileName);
|
||||
|
||||
attributes = GetFileAttributes(file_path);
|
||||
if (attributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
rc = recursive_rm_dir_content((const char *)file_path);
|
||||
if (rc != 0) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
removed = RemoveDirectoryA(file_path);
|
||||
|
||||
if (!removed) {
|
||||
last_error = GetLastError();
|
||||
|
||||
/*TODO print error message?*/
|
||||
|
||||
rc = last_error;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else {
|
||||
rc = remove(file_path);
|
||||
if (rc) {
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
} while(FindNextFile(file_handle, &file_data));
|
||||
|
||||
FindClose(file_handle);
|
||||
}
|
||||
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int torture_rmdirs(const char *path)
|
||||
{
|
||||
int rc = 0;
|
||||
BOOL removed;
|
||||
|
||||
rc = recursive_rm_dir_content(path);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
removed = RemoveDirectoryA(path);
|
||||
if (!removed) {
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int torture_isdir(const char *path)
|
||||
{
|
||||
|
||||
DWORD attributes = 0;
|
||||
|
||||
attributes = GetFileAttributes(path);
|
||||
if (attributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *torture_create_temp_file(const char *template)
|
||||
{
|
||||
DWORD rc = 0;
|
||||
char tmp_dir_path[MAX_PATH];
|
||||
char tmp_file_name[MAX_PATH];
|
||||
char *prefix = NULL;
|
||||
char *path = NULL;
|
||||
char *prefix_end = NULL;
|
||||
char *slash = NULL;
|
||||
|
||||
if (template == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
prefix = strdup(template);
|
||||
if (prefix == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Replace slashes with backslashes */
|
||||
slash = strchr(prefix, '/');
|
||||
for (; slash != NULL; slash = strchr(prefix, '/')) {
|
||||
*slash = '\\';
|
||||
}
|
||||
|
||||
prefix_end = strstr(prefix, "XXXXXX");
|
||||
if (prefix_end != NULL) {
|
||||
*prefix_end = '\0';
|
||||
}
|
||||
|
||||
rc = GetTempPathA(MAX_PATH, tmp_dir_path);
|
||||
if ((rc > MAX_PATH) || (rc == 0)) {
|
||||
goto free_prefix;
|
||||
}
|
||||
|
||||
/* Remark: this function creates the file */
|
||||
rc = GetTempFileNameA(tmp_dir_path, TEXT(prefix), 0, tmp_file_name);
|
||||
if (rc == 0) {
|
||||
goto free_prefix;
|
||||
}
|
||||
|
||||
path = strdup(tmp_file_name);
|
||||
|
||||
free_prefix:
|
||||
SAFE_FREE(prefix);
|
||||
end:
|
||||
return path;
|
||||
}
|
||||
|
||||
char *torture_get_current_working_dir(void)
|
||||
{
|
||||
char *cwd = NULL;
|
||||
char *result = NULL;
|
||||
|
||||
cwd = (char *)malloc(_MAX_PATH + 1);
|
||||
if (cwd == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
result = _getcwd(cwd, _MAX_PATH);
|
||||
|
||||
if (result == NULL) {
|
||||
SAFE_FREE(cwd);
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
return cwd;
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
int torture_change_dir(char *path)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (path == NULL) {
|
||||
rc = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
rc = chdir(path);
|
||||
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int torture_libssh_verbosity(void){
|
||||
return verbosity;
|
||||
}
|
||||
|
||||
void _torture_filter_tests(struct CMUnitTest *tests, size_t ntests)
|
||||
{
|
||||
size_t i,j;
|
||||
const char *name;
|
||||
if (pattern == NULL){
|
||||
return;
|
||||
}
|
||||
for (i=0; i < ntests; ++i){
|
||||
name = tests[i].name;
|
||||
/*printf("match(%s,%s)\n",name,pattern);*/
|
||||
if (!match_pattern(name, pattern)){
|
||||
for (j = i; j < ntests-1;++j){
|
||||
tests[j]=tests[j+1];
|
||||
}
|
||||
tests[ntests-1].name = NULL;
|
||||
tests[ntests-1].test_func = NULL;
|
||||
ntests--;
|
||||
--i;
|
||||
}
|
||||
}
|
||||
if (ntests != 0){
|
||||
printf("%d tests left\n",(int)ntests);
|
||||
} else {
|
||||
printf("No matching test left\n");
|
||||
}
|
||||
(void) tests;
|
||||
(void) ntests;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void torture_write_file(const char *filename, const char *data){
|
||||
@@ -835,22 +1163,30 @@ void torture_write_file(const char *filename, const char *data){
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void torture_reset_config(ssh_session session)
|
||||
{
|
||||
memset(session->opts.options_seen, 0, sizeof(session->opts.options_seen));
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
struct argument_s arguments;
|
||||
char *env = getenv("LIBSSH_VERBOSITY");
|
||||
struct argument_s arguments;
|
||||
char *env = getenv("LIBSSH_VERBOSITY");
|
||||
|
||||
arguments.verbose=0;
|
||||
arguments.pattern=NULL;
|
||||
torture_cmdline_parse(argc, argv, &arguments);
|
||||
verbosity=arguments.verbose;
|
||||
pattern=arguments.pattern;
|
||||
arguments.verbose=0;
|
||||
arguments.pattern=NULL;
|
||||
torture_cmdline_parse(argc, argv, &arguments);
|
||||
verbosity=arguments.verbose;
|
||||
pattern=arguments.pattern;
|
||||
|
||||
if (verbosity == 0 && env != NULL && env[0] != '\0') {
|
||||
if (env[0] > '0' && env[0] < '9') {
|
||||
verbosity = atoi(env);
|
||||
}
|
||||
}
|
||||
if (verbosity == 0 && env != NULL && env[0] != '\0') {
|
||||
if (env[0] > '0' && env[0] < '9') {
|
||||
verbosity = atoi(env);
|
||||
}
|
||||
}
|
||||
|
||||
return torture_run_tests();
|
||||
#if defined HAVE_CMOCKA_SET_TEST_FILTER
|
||||
cmocka_set_test_filter(pattern);
|
||||
#endif
|
||||
|
||||
return torture_run_tests();
|
||||
}
|
||||
|
||||
@@ -120,9 +120,17 @@ void torture_setup_sshd_server(void **state);
|
||||
void torture_teardown_socket_dir(void **state);
|
||||
void torture_teardown_sshd_server(void **state);
|
||||
|
||||
void torture_reset_config(ssh_session session);
|
||||
|
||||
/*
|
||||
* This function must be defined in every unit test file.
|
||||
*/
|
||||
int torture_run_tests(void);
|
||||
|
||||
char *torture_make_temp_dir(const char *template);
|
||||
char *torture_create_temp_file(const char *template);
|
||||
|
||||
char *torture_get_current_working_dir(void);
|
||||
int torture_change_dir(char *path);
|
||||
|
||||
#endif /* _TORTURE_H */
|
||||
|
||||
@@ -1,10 +1,21 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#elif (defined _WIN32) || (defined _WIN64)
|
||||
#include <io.h>
|
||||
#define read _read
|
||||
#define open _open
|
||||
#define write _write
|
||||
#define close _close
|
||||
#endif
|
||||
|
||||
#include "torture_pki.h"
|
||||
|
||||
|
||||
@@ -2,98 +2,86 @@ project(unittests C)
|
||||
|
||||
include_directories(${OPENSSL_INCLUDE_DIR})
|
||||
|
||||
add_cmocka_test(torture_buffer torture_buffer.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_buffer PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
set(LIBSSH_UNIT_TESTS
|
||||
torture_buffer
|
||||
torture_bytearray
|
||||
torture_callbacks
|
||||
torture_crypto
|
||||
torture_init
|
||||
torture_list
|
||||
torture_misc
|
||||
torture_config
|
||||
torture_options
|
||||
torture_isipaddr
|
||||
torture_knownhosts_parsing
|
||||
torture_hashes
|
||||
torture_packet_filter
|
||||
torture_temp_dir
|
||||
torture_temp_file
|
||||
torture_push_pop_dir
|
||||
)
|
||||
|
||||
add_cmocka_test(torture_callbacks torture_callbacks.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_callbacks PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_crypto torture_crypto.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_crypto PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_init torture_init.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_init PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_list torture_list.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_list PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_misc torture_misc.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_misc PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_config torture_config.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_config PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_options torture_options.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_options PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_isipaddr torture_isipaddr.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_isipaddr PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_knownhosts_parsing torture_knownhosts_parsing.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_knownhosts_parsing PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_hashes torture_hashes.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_hashes PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_packet_filter torture_packet_filter.c ${TORTURE_LIBRARY})
|
||||
target_compile_options(torture_packet_filter PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
if (CMAKE_USE_PTHREADS_INIT)
|
||||
add_cmocka_test(torture_rand torture_rand.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_rand PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(torture_rand Threads::Threads)
|
||||
|
||||
add_cmocka_test(torture_threads_init torture_threads_init.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_threads_init PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(torture_threads_init Threads::Threads)
|
||||
|
||||
add_cmocka_test(torture_threads_buffer torture_threads_buffer.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_threads_buffer PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(torture_threads_buffer Threads::Threads)
|
||||
|
||||
add_cmocka_test(torture_threads_crypto torture_threads_crypto.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_threads_crypto PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(torture_threads_crypto Threads::Threads)
|
||||
endif ()
|
||||
set(LIBSSH_THREAD_UNIT_TESTS
|
||||
torture_rand
|
||||
torture_threads_init
|
||||
torture_threads_buffer
|
||||
torture_threads_crypto
|
||||
)
|
||||
|
||||
if (UNIX AND NOT WIN32)
|
||||
# this uses a socketpair
|
||||
add_cmocka_test(torture_packet torture_packet.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_packet PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
# requires ssh-keygen
|
||||
add_cmocka_test(torture_keyfiles torture_keyfiles.c ${TEST_TARGET_LIBRARIES})
|
||||
|
||||
add_cmocka_test(torture_pki torture_pki.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_pki PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_pki_rsa torture_pki_rsa.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_pki_rsa PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_pki_ed25519 torture_pki_ed25519.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_pki_ed25519 PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
set(LIBSSH_UNIT_TESTS
|
||||
${LIBSSH_UNIT_TESTS}
|
||||
# this uses a socketpair
|
||||
torture_packet
|
||||
# requires ssh-keygen
|
||||
torture_keyfiles
|
||||
torture_pki
|
||||
torture_pki_rsa
|
||||
torture_pki_ed25519
|
||||
# requires /dev/null
|
||||
torture_channel
|
||||
)
|
||||
|
||||
if (HAVE_DSA)
|
||||
add_cmocka_test(torture_pki_dsa torture_pki_dsa.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_pki_dsa PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
set(LIBSSH_UNIT_TESTS
|
||||
${LIBSSH_UNIT_TESTS}
|
||||
torture_pki_dsa
|
||||
)
|
||||
endif()
|
||||
|
||||
if (HAVE_ECC)
|
||||
add_cmocka_test(torture_pki_ecdsa torture_pki_ecdsa.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_pki_ecdsa PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
set(LIBSSH_UNIT_TESTS
|
||||
${LIBSSH_UNIT_TESTS}
|
||||
torture_pki_ecdsa
|
||||
)
|
||||
endif()
|
||||
|
||||
# requires /dev/null
|
||||
add_cmocka_test(torture_channel torture_channel.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_channel PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
# requires pthread
|
||||
if (CMAKE_USE_PTHREADS_INIT)
|
||||
add_cmocka_test(torture_threads_pki_rsa torture_threads_pki_rsa.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_threads_pki_rsa PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(torture_threads_pki_rsa Threads::Threads)
|
||||
|
||||
# Not working correctly
|
||||
#if (WITH_SERVER)
|
||||
# add_cmocka_test(torture_server_x11 torture_server_x11.c ${TEST_TARGET_LIBRARIES})
|
||||
#endif (WITH_SERVER)
|
||||
endif ()
|
||||
set(LIBSSH_THREAD_UNIT_TESTS
|
||||
${LIBSSH_THREAD_UNIT_TESTS}
|
||||
# requires pthread
|
||||
torture_threads_pki_rsa
|
||||
)
|
||||
# Not working correctly
|
||||
#if (WITH_SERVER)
|
||||
# add_cmocka_test(torture_server_x11 torture_server_x11.c ${TEST_TARGET_LIBRARIES})
|
||||
#endif (WITH_SERVER)
|
||||
endif (UNIX AND NOT WIN32)
|
||||
|
||||
foreach(_UNIT_TEST ${LIBSSH_UNIT_TESTS})
|
||||
add_cmocka_test(${_UNIT_TEST}
|
||||
SOURCES ${_UNIT_TEST}.c
|
||||
COMPILE_OPTIONS ${DEFAULT_C_COMPILE_FLAGS}
|
||||
LINK_LIBRARIES ${TEST_TARGET_LIBRARIES}
|
||||
)
|
||||
endforeach()
|
||||
|
||||
if (CMAKE_USE_PTHREADS_INIT)
|
||||
foreach(_UNIT_TEST ${LIBSSH_THREAD_UNIT_TESTS})
|
||||
add_cmocka_test(${_UNIT_TEST}
|
||||
SOURCES ${_UNIT_TEST}.c
|
||||
COMPILE_OPTIONS ${DEFAULT_C_COMPILE_FLAGS}
|
||||
LINK_LIBRARIES ${TEST_TARGET_LIBRARIES} Threads::Threads
|
||||
)
|
||||
endforeach()
|
||||
endif ()
|
||||
|
||||
|
||||
410
tests/unittests/torture_bytearray.c
Normal file
410
tests/unittests/torture_bytearray.c
Normal file
@@ -0,0 +1,410 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "torture.h"
|
||||
#include "libssh/bytearray.h"
|
||||
|
||||
static void torture_pull_le_u8(void **state)
|
||||
{
|
||||
uint8_t data[2] = {0};
|
||||
uint8_t result;
|
||||
|
||||
(void)state;
|
||||
|
||||
result = PULL_LE_U8(data, 0);
|
||||
assert_int_equal(result, 0);
|
||||
|
||||
data[0] = 0x2a;
|
||||
result = PULL_LE_U8(data, 0);
|
||||
assert_int_equal(result, 42);
|
||||
|
||||
|
||||
data[0] = 0xf;
|
||||
result = PULL_LE_U8(data, 0);
|
||||
assert_int_equal(result, 0xf);
|
||||
|
||||
data[0] = 0xff;
|
||||
result = PULL_LE_U8(data, 0);
|
||||
assert_int_equal(result, 0xff);
|
||||
|
||||
data[1] = 0x2a;
|
||||
result = PULL_LE_U8(data, 1);
|
||||
assert_int_equal(result, 42);
|
||||
}
|
||||
|
||||
static void torture_pull_le_u16(void **state)
|
||||
{
|
||||
uint8_t data[2] = {0, 0};
|
||||
uint16_t result;
|
||||
|
||||
(void)state;
|
||||
|
||||
result = PULL_LE_U16(data, 0);
|
||||
assert_int_equal(result, 0);
|
||||
|
||||
data[0] = 0x2a;
|
||||
data[1] = 0x00;
|
||||
result = PULL_LE_U16(data, 0);
|
||||
assert_int_equal(result, 42);
|
||||
|
||||
data[0] = 0xff;
|
||||
data[1] = 0x00;
|
||||
result = PULL_LE_U16(data, 0);
|
||||
assert_int_equal(result, 0x00ff);
|
||||
|
||||
data[0] = 0x00;
|
||||
data[1] = 0xff;
|
||||
result = PULL_LE_U16(data, 0);
|
||||
assert_int_equal(result, 0xff00);
|
||||
|
||||
data[0] = 0xff;
|
||||
data[1] = 0xff;
|
||||
result = PULL_LE_U16(data, 0);
|
||||
assert_int_equal(result, 0xffff);
|
||||
}
|
||||
|
||||
static void torture_pull_le_u32(void **state)
|
||||
{
|
||||
uint8_t data[4] = {0, 0, 0, 0};
|
||||
uint32_t result;
|
||||
|
||||
(void)state;
|
||||
|
||||
result = PULL_LE_U32(data, 0);
|
||||
assert_int_equal(result, 0);
|
||||
|
||||
data[0] = 0x2a;
|
||||
data[1] = 0x00;
|
||||
data[2] = 0x00;
|
||||
data[3] = 0x00;
|
||||
result = PULL_LE_U32(data, 0);
|
||||
assert_int_equal(result, 42);
|
||||
|
||||
data[0] = 0xff;
|
||||
data[1] = 0x00;
|
||||
data[2] = 0x00;
|
||||
data[3] = 0x00;
|
||||
result = PULL_LE_U32(data, 0);
|
||||
assert_int_equal(result, 0x00ff);
|
||||
|
||||
data[0] = 0x00;
|
||||
data[1] = 0xff;
|
||||
data[2] = 0x00;
|
||||
data[3] = 0x00;
|
||||
result = PULL_LE_U32(data, 0);
|
||||
assert_int_equal(result, 0xff00);
|
||||
|
||||
data[0] = 0x00;
|
||||
data[1] = 0x00;
|
||||
data[2] = 0xff;
|
||||
data[3] = 0x00;
|
||||
result = PULL_LE_U32(data, 0);
|
||||
assert_int_equal(result, 0xff0000);
|
||||
|
||||
data[0] = 0x00;
|
||||
data[1] = 0x00;
|
||||
data[2] = 0x00;
|
||||
data[3] = 0xff;
|
||||
result = PULL_LE_U32(data, 0);
|
||||
assert_int_equal(result, 0xff000000);
|
||||
|
||||
data[0] = 0xff;
|
||||
data[1] = 0xff;
|
||||
data[2] = 0xff;
|
||||
data[3] = 0xff;
|
||||
result = PULL_LE_U32(data, 0);
|
||||
assert_int_equal(result, 0xffffffff);
|
||||
}
|
||||
|
||||
static void torture_push_le_u8(void **state)
|
||||
{
|
||||
uint8_t data[4] = {0, 0, 0, 0};
|
||||
uint8_t data2[4] = {42, 42, 42, 42};
|
||||
|
||||
(void)state;
|
||||
|
||||
PUSH_LE_U8(data, 0, 42);
|
||||
PUSH_LE_U8(data, 1, 42);
|
||||
PUSH_LE_U8(data, 2, 42);
|
||||
PUSH_LE_U8(data, 3, 42);
|
||||
assert_memory_equal(data, data2, sizeof(data));
|
||||
}
|
||||
|
||||
static void torture_push_le_u16(void **state)
|
||||
{
|
||||
uint8_t data[4] = {0, 0, 0, 0};
|
||||
uint8_t data2[4] = {0xa6, 0x7f, 0x2a, 0x00};
|
||||
uint16_t result;
|
||||
|
||||
(void)state;
|
||||
|
||||
PUSH_LE_U16(data, 0, 32678);
|
||||
PUSH_LE_U16(data, 2, 42);
|
||||
assert_memory_equal(data, data2, sizeof(data));
|
||||
|
||||
result = PULL_LE_U16(data, 2);
|
||||
assert_int_equal(result, 42);
|
||||
|
||||
result = PULL_LE_U16(data, 0);
|
||||
assert_int_equal(result, 32678);
|
||||
}
|
||||
|
||||
static void torture_push_le_u32(void **state)
|
||||
{
|
||||
uint8_t data[8] = {0};
|
||||
uint8_t data2[8] = {0xa6, 0x7f, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00};
|
||||
uint32_t result;
|
||||
|
||||
(void)state;
|
||||
|
||||
PUSH_LE_U32(data, 0, 32678);
|
||||
PUSH_LE_U32(data, 4, 42);
|
||||
assert_memory_equal(data, data2, sizeof(data));
|
||||
|
||||
result = PULL_LE_U32(data, 4);
|
||||
assert_int_equal(result, 42);
|
||||
|
||||
result = PULL_LE_U32(data, 0);
|
||||
assert_int_equal(result, 32678);
|
||||
|
||||
PUSH_LE_U32(data, 0, 0xfffefffe);
|
||||
result = PULL_LE_U32(data, 0);
|
||||
assert_int_equal(result, 0xfffefffe);
|
||||
}
|
||||
|
||||
static void torture_push_le_u64(void **state)
|
||||
{
|
||||
uint8_t data[16] = {0};
|
||||
uint64_t result;
|
||||
|
||||
(void)state;
|
||||
|
||||
PUSH_LE_U64(data, 0, 32678);
|
||||
|
||||
result = PULL_LE_U64(data, 0);
|
||||
assert_int_equal(result, 32678);
|
||||
|
||||
PUSH_LE_U64(data, 0, 0xfffefffefffefffeUL);
|
||||
|
||||
result = PULL_LE_U64(data, 0);
|
||||
assert_int_equal(result, 0xfffefffefffefffeUL);
|
||||
}
|
||||
|
||||
/****************** BIG ENDIAN ********************/
|
||||
|
||||
static void torture_pull_be_u8(void **state)
|
||||
{
|
||||
uint8_t data[2] = {0};
|
||||
uint8_t result;
|
||||
|
||||
(void)state;
|
||||
|
||||
result = PULL_BE_U8(data, 0);
|
||||
assert_int_equal(result, 0);
|
||||
|
||||
data[0] = 0x2a;
|
||||
result = PULL_BE_U8(data, 0);
|
||||
assert_int_equal(result, 42);
|
||||
|
||||
|
||||
data[0] = 0xf;
|
||||
result = PULL_BE_U8(data, 0);
|
||||
assert_int_equal(result, 0xf);
|
||||
|
||||
data[0] = 0xff;
|
||||
result = PULL_BE_U8(data, 0);
|
||||
assert_int_equal(result, 0xff);
|
||||
|
||||
data[1] = 0x2a;
|
||||
result = PULL_BE_U8(data, 1);
|
||||
assert_int_equal(result, 42);
|
||||
}
|
||||
|
||||
static void torture_pull_be_u16(void **state)
|
||||
{
|
||||
uint8_t data[2] = {0, 0};
|
||||
uint16_t result;
|
||||
|
||||
(void)state;
|
||||
|
||||
result = PULL_BE_U16(data, 0);
|
||||
assert_int_equal(result, 0);
|
||||
|
||||
data[0] = 0x00;
|
||||
data[1] = 0x2a;
|
||||
result = PULL_BE_U16(data, 0);
|
||||
assert_int_equal(result, 42);
|
||||
|
||||
data[0] = 0x00;
|
||||
data[1] = 0xff;
|
||||
result = PULL_BE_U16(data, 0);
|
||||
assert_int_equal(result, 0x00ff);
|
||||
|
||||
data[0] = 0xff;
|
||||
data[1] = 0x00;
|
||||
result = PULL_BE_U16(data, 0);
|
||||
assert_int_equal(result, 0xff00);
|
||||
|
||||
data[0] = 0xff;
|
||||
data[1] = 0xff;
|
||||
result = PULL_BE_U16(data, 0);
|
||||
assert_int_equal(result, 0xffff);
|
||||
}
|
||||
|
||||
static void torture_pull_be_u32(void **state)
|
||||
{
|
||||
uint8_t data[4] = {0, 0, 0, 0};
|
||||
uint32_t result;
|
||||
|
||||
(void)state;
|
||||
|
||||
result = PULL_BE_U32(data, 0);
|
||||
assert_int_equal(result, 0);
|
||||
|
||||
data[0] = 0x00;
|
||||
data[1] = 0x00;
|
||||
data[2] = 0x00;
|
||||
data[3] = 0x2a;
|
||||
result = PULL_BE_U32(data, 0);
|
||||
assert_int_equal(result, 42);
|
||||
|
||||
data[0] = 0x00;
|
||||
data[1] = 0x00;
|
||||
data[2] = 0x00;
|
||||
data[3] = 0xff;
|
||||
result = PULL_BE_U32(data, 0);
|
||||
assert_int_equal(result, 0x00ff);
|
||||
|
||||
data[0] = 0x00;
|
||||
data[1] = 0x00;
|
||||
data[2] = 0xff;
|
||||
data[3] = 0x00;
|
||||
result = PULL_BE_U32(data, 0);
|
||||
assert_int_equal(result, 0xff00);
|
||||
|
||||
data[0] = 0x00;
|
||||
data[1] = 0xff;
|
||||
data[2] = 0x00;
|
||||
data[3] = 0x00;
|
||||
result = PULL_BE_U32(data, 0);
|
||||
assert_int_equal(result, 0xff0000);
|
||||
|
||||
data[0] = 0xff;
|
||||
data[1] = 0x00;
|
||||
data[2] = 0x00;
|
||||
data[3] = 0x00;
|
||||
result = PULL_BE_U32(data, 0);
|
||||
assert_int_equal(result, 0xff000000);
|
||||
|
||||
data[0] = 0xff;
|
||||
data[1] = 0xff;
|
||||
data[2] = 0xff;
|
||||
data[3] = 0xff;
|
||||
result = PULL_BE_U32(data, 0);
|
||||
assert_int_equal(result, 0xffffffff);
|
||||
}
|
||||
|
||||
static void torture_push_be_u8(void **state)
|
||||
{
|
||||
uint8_t data[4] = {0, 0, 0, 0};
|
||||
uint8_t data2[4] = {42, 42, 42, 42};
|
||||
|
||||
(void)state;
|
||||
|
||||
PUSH_BE_U8(data, 0, 42);
|
||||
PUSH_BE_U8(data, 1, 42);
|
||||
PUSH_BE_U8(data, 2, 42);
|
||||
PUSH_BE_U8(data, 3, 42);
|
||||
assert_memory_equal(data, data2, sizeof(data));
|
||||
}
|
||||
|
||||
static void torture_push_be_u16(void **state)
|
||||
{
|
||||
uint8_t data[4] = {0, 0, 0, 0};
|
||||
uint8_t data2[4] = {0x7f, 0xa6, 0x00, 0x2a};
|
||||
uint16_t result;
|
||||
|
||||
(void)state;
|
||||
|
||||
PUSH_BE_U16(data, 0, 32678);
|
||||
PUSH_BE_U16(data, 2, 42);
|
||||
assert_memory_equal(data, data2, sizeof(data));
|
||||
|
||||
result = PULL_BE_U16(data, 2);
|
||||
assert_int_equal(result, 42);
|
||||
|
||||
result = PULL_BE_U16(data, 0);
|
||||
assert_int_equal(result, 32678);
|
||||
}
|
||||
|
||||
static void torture_push_be_u32(void **state)
|
||||
{
|
||||
uint8_t data[8] = {0};
|
||||
uint8_t data2[8] = {0x00, 0x00, 0x7f, 0xa6, 0x00, 0x00, 0x00, 0x2a};
|
||||
uint32_t result;
|
||||
|
||||
(void)state;
|
||||
|
||||
PUSH_BE_U32(data, 0, 32678);
|
||||
PUSH_BE_U32(data, 4, 42);
|
||||
assert_memory_equal(data, data2, sizeof(data));
|
||||
|
||||
result = PULL_BE_U32(data, 4);
|
||||
assert_int_equal(result, 42);
|
||||
|
||||
result = PULL_BE_U32(data, 0);
|
||||
assert_int_equal(result, 32678);
|
||||
|
||||
PUSH_BE_U32(data, 0, 0xfffefffe);
|
||||
result = PULL_BE_U32(data, 0);
|
||||
assert_int_equal(result, 0xfffefffe);
|
||||
}
|
||||
|
||||
static void torture_push_be_u64(void **state)
|
||||
{
|
||||
uint8_t data[16] = {0};
|
||||
uint64_t result;
|
||||
|
||||
(void)state;
|
||||
|
||||
PUSH_BE_U64(data, 0, 32678);
|
||||
|
||||
result = PULL_BE_U64(data, 0);
|
||||
assert_int_equal(result, 32678);
|
||||
|
||||
PUSH_LE_U64(data, 8, 0xfffefffe);
|
||||
|
||||
result = PULL_LE_U64(data, 8);
|
||||
assert_int_equal(result, 0xfffefffe);
|
||||
}
|
||||
|
||||
int torture_run_tests(void) {
|
||||
int rc;
|
||||
struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(torture_pull_le_u8),
|
||||
cmocka_unit_test(torture_pull_le_u16),
|
||||
cmocka_unit_test(torture_pull_le_u32),
|
||||
|
||||
cmocka_unit_test(torture_push_le_u8),
|
||||
cmocka_unit_test(torture_push_le_u16),
|
||||
cmocka_unit_test(torture_push_le_u32),
|
||||
cmocka_unit_test(torture_push_le_u64),
|
||||
|
||||
/* BIG ENDIAN */
|
||||
cmocka_unit_test(torture_pull_be_u8),
|
||||
cmocka_unit_test(torture_pull_be_u16),
|
||||
cmocka_unit_test(torture_pull_be_u32),
|
||||
|
||||
cmocka_unit_test(torture_push_be_u8),
|
||||
cmocka_unit_test(torture_push_be_u16),
|
||||
cmocka_unit_test(torture_push_be_u32),
|
||||
cmocka_unit_test(torture_push_be_u64),
|
||||
};
|
||||
|
||||
torture_filter_tests(tests);
|
||||
|
||||
rc = cmocka_run_group_tests(tests, NULL, NULL);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -75,6 +75,11 @@ static int setup_config_files(void **state)
|
||||
"\tConnectTimeout 30\n"
|
||||
"\tLogLevel DEBUG3\n"
|
||||
"\tGlobalKnownHostsFile "GLOBAL_KNOWN_HOSTS"\n"
|
||||
"\tCompression yes\n"
|
||||
"\tStrictHostkeyChecking no\n"
|
||||
"\tGSSAPIDelegateCredentials yes\n"
|
||||
"\tGSSAPIServerIdentity example.com\n"
|
||||
"\tGSSAPIClientIdentity home.sweet\n"
|
||||
"\tUserKnownHostsFile "USER_KNOWN_HOSTS"\n");
|
||||
|
||||
/* authentication methods */
|
||||
@@ -151,7 +156,6 @@ static int teardown(void **state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief tests ssh_config_parse_file with Include directives
|
||||
*/
|
||||
@@ -249,6 +253,14 @@ static void torture_config_new(void **state)
|
||||
assert_string_equal(session->opts.global_knownhosts, GLOBAL_KNOWN_HOSTS);
|
||||
assert_int_equal(session->opts.timeout, 30);
|
||||
assert_string_equal(session->opts.bindaddr, BIND_ADDRESS);
|
||||
assert_string_equal(session->opts.wanted_methods[SSH_COMP_C_S],
|
||||
"zlib@openssh.com,zlib");
|
||||
assert_string_equal(session->opts.wanted_methods[SSH_COMP_S_C],
|
||||
"zlib@openssh.com,zlib");
|
||||
assert_int_equal(session->opts.StrictHostKeyChecking, 0);
|
||||
assert_int_equal(session->opts.gss_delegate_creds, 1);
|
||||
assert_string_equal(session->opts.gss_server_identity, "example.com");
|
||||
assert_string_equal(session->opts.gss_client_identity, "home.sweet");
|
||||
|
||||
assert_int_equal(ssh_get_log_level(), SSH_LOG_TRACE);
|
||||
assert_int_equal(session->common.log_verbosity, SSH_LOG_TRACE);
|
||||
@@ -284,9 +296,10 @@ static void torture_config_auth_methods(void **state) {
|
||||
assert_false(session->opts.flags & SSH_OPT_FLAG_PUBKEY_AUTH);
|
||||
|
||||
/* no method should be left enabled */
|
||||
assert_int_equal(session->opts.port, 0);
|
||||
assert_int_equal(session->opts.flags, 0);
|
||||
|
||||
/* gradually enable them again */
|
||||
torture_reset_config(session);
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "gss");
|
||||
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG8);
|
||||
assert_true(ret == 0);
|
||||
@@ -341,29 +354,34 @@ static void torture_config_match(void **state)
|
||||
assert_string_equal(session->opts.host, "all-matched.com");
|
||||
|
||||
/* Hostname example does simple hostname matching */
|
||||
torture_reset_config(session);
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "example");
|
||||
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10);
|
||||
assert_true(ret == 0);
|
||||
assert_string_equal(session->opts.host, "example.com");
|
||||
|
||||
/* We can match also both hosts from a comma separated list */
|
||||
torture_reset_config(session);
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "example1");
|
||||
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10);
|
||||
assert_true(ret == 0);
|
||||
assert_string_equal(session->opts.host, "exampleN");
|
||||
|
||||
torture_reset_config(session);
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "example2");
|
||||
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10);
|
||||
assert_true(ret == 0);
|
||||
assert_string_equal(session->opts.host, "exampleN");
|
||||
|
||||
/* We can match by user */
|
||||
torture_reset_config(session);
|
||||
ssh_options_set(session, SSH_OPTIONS_USER, "guest");
|
||||
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10);
|
||||
assert_true(ret == 0);
|
||||
assert_string_equal(session->opts.host, "guest.com");
|
||||
|
||||
/* We can combine two options on a single line to match both of them */
|
||||
torture_reset_config(session);
|
||||
ssh_options_set(session, SSH_OPTIONS_USER, "tester");
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "testhost");
|
||||
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10);
|
||||
@@ -371,6 +389,7 @@ static void torture_config_match(void **state)
|
||||
assert_string_equal(session->opts.host, "testhost.com");
|
||||
|
||||
/* We can also negate conditions */
|
||||
torture_reset_config(session);
|
||||
ssh_options_set(session, SSH_OPTIONS_USER, "not-tester");
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "testhost");
|
||||
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10);
|
||||
@@ -382,33 +401,19 @@ static void torture_config_match(void **state)
|
||||
int torture_run_tests(void) {
|
||||
int rc;
|
||||
struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(torture_config_from_file,
|
||||
setup_config_files,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_config_double_ports,
|
||||
setup_config_files,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_config_glob,
|
||||
setup_config_files,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_config_new,
|
||||
setup_config_files,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_config_auth_methods,
|
||||
setup_config_files,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_config_unknown,
|
||||
setup_config_files,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_config_match,
|
||||
setup_config_files,
|
||||
teardown),
|
||||
cmocka_unit_test(torture_config_from_file),
|
||||
cmocka_unit_test(torture_config_double_ports),
|
||||
cmocka_unit_test(torture_config_glob),
|
||||
cmocka_unit_test(torture_config_new),
|
||||
cmocka_unit_test(torture_config_auth_methods),
|
||||
cmocka_unit_test(torture_config_unknown),
|
||||
cmocka_unit_test(torture_config_match),
|
||||
};
|
||||
|
||||
|
||||
ssh_init();
|
||||
torture_filter_tests(tests);
|
||||
rc = cmocka_run_group_tests(tests, NULL, NULL);
|
||||
rc = cmocka_run_group_tests(tests, setup_config_files, teardown);
|
||||
ssh_finalize();
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -20,15 +20,19 @@ static int setup_rsa_key(void **state)
|
||||
assert_true(b64_key != NULL);
|
||||
|
||||
q = p = b64_key;
|
||||
while (*p != ' ') p++;
|
||||
*p = '\0';
|
||||
while (p != NULL && *p != '\0' && *p != ' ') p++;
|
||||
if (p != NULL) {
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
type = ssh_key_type_from_name(q);
|
||||
assert_true(type == SSH_KEYTYPE_RSA);
|
||||
|
||||
q = ++p;
|
||||
while (*p != ' ') p++;
|
||||
*p = '\0';
|
||||
while (p != NULL && *p != '\0' && *p != ' ') p++;
|
||||
if (p != NULL) {
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
rc = ssh_pki_import_pubkey_base64(q, type, &key);
|
||||
assert_true(rc == 0);
|
||||
|
||||
@@ -16,10 +16,27 @@ static void torture_ssh_init(void **state) {
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
}
|
||||
|
||||
static void torture_ssh_init_after_finalize(void **state) {
|
||||
|
||||
int rc;
|
||||
|
||||
(void) state;
|
||||
|
||||
rc = ssh_init();
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
rc = ssh_finalize();
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
rc = ssh_init();
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
rc = ssh_finalize();
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
}
|
||||
|
||||
int torture_run_tests(void) {
|
||||
int rc;
|
||||
struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(torture_ssh_init),
|
||||
cmocka_unit_test(torture_ssh_init_after_finalize),
|
||||
};
|
||||
|
||||
torture_filter_tests(tests);
|
||||
|
||||
@@ -104,7 +104,7 @@ static int teardown(void **state)
|
||||
|
||||
static void torture_pubkey_from_file(void **state) {
|
||||
ssh_session session = *state;
|
||||
ssh_string pubkey;
|
||||
ssh_string pubkey = NULL;
|
||||
int type, rc;
|
||||
|
||||
rc = ssh_try_publickey_from_file(session, LIBSSH_RSA_TESTKEY, &pubkey, &type);
|
||||
|
||||
@@ -8,6 +8,15 @@
|
||||
|
||||
#include "knownhosts.c"
|
||||
|
||||
#if (defined _WIN32) || (defined _WIN64)
|
||||
#ifndef S_IRWXO
|
||||
#define S_IRWXO 0
|
||||
#endif
|
||||
#ifndef S_IRWXG
|
||||
#define S_IRWXG 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define LOCALHOST_RSA_LINE "localhost,127.0.0.1 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDD7g+vV5cvxxGN0Ldmda4WZCPgRaxV1tV+1KRZoGUNUI61h0X4bmmGaAPRQBCz4G1d9bawqDqEqnpFWazrxBU5cQtISSjzuDJKovLGliky/ShTszee1Thszg3qVNk9gGOWj7jn/HDaOxRlp003Bp47MOdnMnK/oftllFDfY2fF5IRpE6sSIGtg2ZDtF95TV5/9W2oMOIAy8u/83tuibYlNPa1X/von5LgdaPLn6Bk16bQKIhAhlMtFZH8MBYEWe4ZtOGaSWKOsK9MM/RTMlwPi6PkfoHNl4MCMupjx+CdLXwbQEt9Ww+bBIaCui2VWBEiruVbIgJh0W2Tal0e2BzYZ What a Wurst!"
|
||||
#define LOCALHOST_ECDSA_SHA1_NISTP256_LINE "localhost ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFWmI0n0Tn5+zR7pPGcKYszRbJ/T0T3QfzRBSMMiyebGKRY8tjkU5h2l/UMugzOrOyWqMGQDgQn+a0aMunhKMg0="
|
||||
#define LOCALHOST_DEFAULT_ED25519 "localhost ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA7M22fXD7OiS7kGMXP+OoIjCa+J+5sq8SgAZfIOmDgM"
|
||||
@@ -22,37 +31,29 @@ static int setup_knownhosts_file(void **state)
|
||||
char *tmp_file = NULL;
|
||||
size_t nwritten;
|
||||
FILE *fp = NULL;
|
||||
mode_t mask;
|
||||
int fd;
|
||||
int rc = 0;
|
||||
|
||||
tmp_file = strdup(TMP_FILE_NAME);
|
||||
tmp_file = torture_create_temp_file(TMP_FILE_NAME);
|
||||
assert_non_null(tmp_file);
|
||||
|
||||
*state = tmp_file;
|
||||
|
||||
mask = umask(S_IRWXO | S_IRWXG);
|
||||
fd = mkstemp(tmp_file);
|
||||
umask(mask);
|
||||
assert_return_code(fd, errno);
|
||||
|
||||
fp = fdopen(fd, "w");
|
||||
if (fp == NULL) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
fp = fopen(tmp_file, "w");
|
||||
assert_non_null(fp);
|
||||
|
||||
nwritten = fwrite(LOCALHOST_PATTERN_ED25519,
|
||||
sizeof(char),
|
||||
strlen(LOCALHOST_PATTERN_ED25519),
|
||||
fp);
|
||||
if (nwritten != strlen(LOCALHOST_PATTERN_ED25519)) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
rc = -1;
|
||||
goto close_fp;
|
||||
}
|
||||
|
||||
nwritten = fwrite("\n", sizeof(char), 1, fp);
|
||||
if (nwritten != 1) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
rc = -1;
|
||||
goto close_fp;
|
||||
}
|
||||
|
||||
nwritten = fwrite(LOCALHOST_RSA_LINE,
|
||||
@@ -60,13 +61,14 @@ static int setup_knownhosts_file(void **state)
|
||||
strlen(LOCALHOST_RSA_LINE),
|
||||
fp);
|
||||
if (nwritten != strlen(LOCALHOST_RSA_LINE)) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
rc = -1;
|
||||
goto close_fp;
|
||||
}
|
||||
|
||||
close_fp:
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int teardown_knownhosts_file(void **state)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <libssh/session.h>
|
||||
#include <libssh/misc.h>
|
||||
#include <libssh/pki_priv.h>
|
||||
#include <libssh/options.h>
|
||||
|
||||
static int setup(void **state)
|
||||
{
|
||||
@@ -392,6 +393,16 @@ static void torture_options_set_knownhosts(void **state)
|
||||
assert_ssh_return_code(session, rc);
|
||||
assert_string_equal(session->opts.knownhosts,
|
||||
"/home/libssh/.ssh/known_hosts");
|
||||
|
||||
/* The NULL value should not crash the libssh */
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, NULL);
|
||||
assert_ssh_return_code(session, rc);
|
||||
assert_null(session->opts.knownhosts);
|
||||
|
||||
/* ssh_options_apply() should set the path to correct value */
|
||||
rc = ssh_options_apply(session);
|
||||
assert_ssh_return_code(session, rc);
|
||||
assert_true(session->opts.knownhosts != NULL);
|
||||
}
|
||||
|
||||
static void torture_options_get_knownhosts(void **state)
|
||||
@@ -451,22 +462,26 @@ static void torture_options_config_host(void **state) {
|
||||
|
||||
assert_int_equal(session->opts.port, 42);
|
||||
|
||||
torture_reset_config(session);
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "testhost2");
|
||||
ssh_options_parse_config(session, "test_config");
|
||||
assert_int_equal(session->opts.port, 43);
|
||||
|
||||
session->opts.port = 0;
|
||||
|
||||
torture_reset_config(session);
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "testhost3");
|
||||
ssh_options_parse_config(session, "test_config");
|
||||
assert_int_equal(session->opts.port, 43);
|
||||
|
||||
torture_reset_config(session);
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "testhost4");
|
||||
ssh_options_parse_config(session, "test_config");
|
||||
assert_int_equal(session->opts.port, 44);
|
||||
|
||||
session->opts.port = 0;
|
||||
|
||||
torture_reset_config(session);
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "testhost5");
|
||||
ssh_options_parse_config(session, "test_config");
|
||||
assert_int_equal(session->opts.port, 44);
|
||||
@@ -494,6 +509,7 @@ static void torture_options_config_match(void **state)
|
||||
assert_ssh_return_code_equal(session, rv, SSH_ERROR);
|
||||
|
||||
/* The Match all keyword needs to be the only one (start) */
|
||||
torture_reset_config(session);
|
||||
config = fopen("test_config", "w");
|
||||
assert_non_null(config);
|
||||
fputs("Match all host local\n",
|
||||
@@ -504,6 +520,7 @@ static void torture_options_config_match(void **state)
|
||||
assert_ssh_return_code_equal(session, rv, SSH_ERROR);
|
||||
|
||||
/* The Match all keyword needs to be the only one (end) */
|
||||
torture_reset_config(session);
|
||||
config = fopen("test_config", "w");
|
||||
assert_non_null(config);
|
||||
fputs("Match host local all\n",
|
||||
@@ -514,6 +531,7 @@ static void torture_options_config_match(void **state)
|
||||
assert_ssh_return_code_equal(session, rv, SSH_ERROR);
|
||||
|
||||
/* The Match host keyword requires an argument */
|
||||
torture_reset_config(session);
|
||||
config = fopen("test_config", "w");
|
||||
assert_non_null(config);
|
||||
fputs("Match host\n",
|
||||
@@ -524,6 +542,7 @@ static void torture_options_config_match(void **state)
|
||||
assert_ssh_return_code_equal(session, rv, SSH_ERROR);
|
||||
|
||||
/* The Match user keyword requires an argument */
|
||||
torture_reset_config(session);
|
||||
config = fopen("test_config", "w");
|
||||
assert_non_null(config);
|
||||
fputs("Match user\n",
|
||||
@@ -534,6 +553,7 @@ static void torture_options_config_match(void **state)
|
||||
assert_ssh_return_code_equal(session, rv, SSH_ERROR);
|
||||
|
||||
/* The Match canonical keyword is ignored */
|
||||
torture_reset_config(session);
|
||||
config = fopen("test_config", "w");
|
||||
assert_non_null(config);
|
||||
fputs("Match canonical\n"
|
||||
@@ -550,6 +570,7 @@ static void torture_options_config_match(void **state)
|
||||
session->opts.port = 0;
|
||||
|
||||
/* The Match originalhost keyword is ignored */
|
||||
torture_reset_config(session);
|
||||
config = fopen("test_config", "w");
|
||||
assert_non_null(config);
|
||||
fputs("Match originalhost origin\n"
|
||||
@@ -566,6 +587,7 @@ static void torture_options_config_match(void **state)
|
||||
session->opts.port = 0;
|
||||
|
||||
/* The Match localuser keyword is ignored */
|
||||
torture_reset_config(session);
|
||||
config = fopen("test_config", "w");
|
||||
assert_non_null(config);
|
||||
fputs("Match originalhost origin\n"
|
||||
@@ -582,6 +604,7 @@ static void torture_options_config_match(void **state)
|
||||
session->opts.port = 0;
|
||||
|
||||
/* The Match exec keyword is ignored */
|
||||
torture_reset_config(session);
|
||||
config = fopen("test_config", "w");
|
||||
assert_non_null(config);
|
||||
fputs("Match exec /bin/true\n"
|
||||
@@ -651,7 +674,7 @@ static void torture_bind_options_import_key(void **state)
|
||||
assert_int_equal(rc, 0);
|
||||
#endif
|
||||
/* set ecdsa key */
|
||||
base64_key = torture_get_testkey(SSH_KEYTYPE_ECDSA, 512, 0);
|
||||
base64_key = torture_get_testkey(SSH_KEYTYPE_ECDSA, 521, 0);
|
||||
rc = ssh_pki_import_privkey_base64(base64_key, NULL, NULL, NULL, &key);
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
assert_non_null(key);
|
||||
|
||||
@@ -41,9 +41,10 @@ static SSH_PACKET_CALLBACK(copy_packet_data){
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void torture_packet(const char *cipher,
|
||||
const char *mac_type, size_t payload_len) {
|
||||
|
||||
static void
|
||||
torture_packet(const char *cipher, const char *mac_type,
|
||||
const char *comp_type, size_t payload_len)
|
||||
{
|
||||
ssh_session session = ssh_new();
|
||||
int verbosity = torture_libssh_verbosity();
|
||||
struct ssh_crypto_struct *crypto;
|
||||
@@ -61,6 +62,7 @@ static void torture_packet(const char *cipher,
|
||||
.callbacks=callbacks,
|
||||
.user=response
|
||||
};
|
||||
int cmp;
|
||||
|
||||
assert_non_null(session);
|
||||
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||
@@ -75,8 +77,8 @@ static void torture_packet(const char *cipher,
|
||||
crypto->kex_methods[SSH_CRYPT_S_C] = strdup(cipher);
|
||||
crypto->kex_methods[SSH_MAC_C_S] = strdup(mac_type);
|
||||
crypto->kex_methods[SSH_MAC_S_C] = strdup(mac_type);
|
||||
crypto->kex_methods[SSH_COMP_C_S] = strdup("none");
|
||||
crypto->kex_methods[SSH_COMP_S_C] = strdup("none");
|
||||
crypto->kex_methods[SSH_COMP_C_S] = strdup(comp_type);
|
||||
crypto->kex_methods[SSH_COMP_S_C] = strdup(comp_type);
|
||||
crypto->kex_methods[SSH_LANG_C_S] = strdup("none");
|
||||
crypto->kex_methods[SSH_LANG_S_C] = strdup("none");
|
||||
rc = crypt_set_algorithms_client(session);
|
||||
@@ -112,7 +114,12 @@ static void torture_packet(const char *cipher,
|
||||
rc = recv(sockets[1], buffer, sizeof(buffer), 0);
|
||||
assert_true(rc > 0);
|
||||
encrypted_packet_len = rc;
|
||||
assert_in_range(encrypted_packet_len, payload_len + 4, payload_len + (32 * 3));
|
||||
cmp = strcmp(comp_type, "none");
|
||||
if (cmp == 0) {
|
||||
assert_in_range(encrypted_packet_len,
|
||||
payload_len + 4,
|
||||
payload_len + (32 * 3));
|
||||
}
|
||||
rc = send(sockets[0], buffer, encrypted_packet_len, 0);
|
||||
assert_int_equal(rc, encrypted_packet_len);
|
||||
|
||||
@@ -134,7 +141,7 @@ static void torture_packet_aes128_ctr(void **state)
|
||||
int i;
|
||||
(void)state; /* unused */
|
||||
for (i=1;i<256;++i){
|
||||
torture_packet("aes128-ctr","hmac-sha1",i);
|
||||
torture_packet("aes128-ctr", "hmac-sha1", "none", i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +150,7 @@ static void torture_packet_aes192_ctr(void **state)
|
||||
int i;
|
||||
(void)state; /* unused */
|
||||
for (i=1;i<256;++i){
|
||||
torture_packet("aes192-ctr","hmac-sha1",i);
|
||||
torture_packet("aes192-ctr", "hmac-sha1", "none", i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +159,7 @@ static void torture_packet_aes256_ctr(void **state)
|
||||
int i;
|
||||
(void)state; /* unused */
|
||||
for (i=1;i<256;++i){
|
||||
torture_packet("aes256-ctr","hmac-sha1",i);
|
||||
torture_packet("aes256-ctr", "hmac-sha1", "none", i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +168,7 @@ static void torture_packet_aes128_cbc(void **state)
|
||||
int i;
|
||||
(void)state; /* unused */
|
||||
for (i=1;i<256;++i){
|
||||
torture_packet("aes128-cbc","hmac-sha1",i);
|
||||
torture_packet("aes128-cbc", "hmac-sha1", "none", i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +177,7 @@ static void torture_packet_aes192_cbc(void **state)
|
||||
int i;
|
||||
(void)state; /* unused */
|
||||
for (i=1;i<256;++i){
|
||||
torture_packet("aes192-cbc","hmac-sha1",i);
|
||||
torture_packet("aes192-cbc", "hmac-sha1", "none", i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,7 +186,7 @@ static void torture_packet_aes256_cbc(void **state)
|
||||
int i;
|
||||
(void)state; /* unused */
|
||||
for (i=1;i<256;++i){
|
||||
torture_packet("aes256-cbc","hmac-sha1",i);
|
||||
torture_packet("aes256-cbc", "hmac-sha1", "none", i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,7 +195,7 @@ static void torture_packet_3des_cbc(void **state)
|
||||
int i;
|
||||
(void)state; /* unused */
|
||||
for (i=1;i<256;++i){
|
||||
torture_packet("3des-cbc","hmac-sha1",i);
|
||||
torture_packet("3des-cbc", "hmac-sha1", "none", i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,7 +204,43 @@ static void torture_packet_chacha20(void **state)
|
||||
int i;
|
||||
(void)state; /* unused */
|
||||
for (i=1;i<256;++i){
|
||||
torture_packet("chacha20-poly1305@openssh.com","none",i);
|
||||
torture_packet("chacha20-poly1305@openssh.com", "none", "none", i);
|
||||
}
|
||||
}
|
||||
|
||||
static void torture_packet_aes128_gcm(void **state)
|
||||
{
|
||||
int i;
|
||||
(void)state; /* unused */
|
||||
for (i=1;i<256;++i){
|
||||
torture_packet("aes128-gcm@openssh.com", "none", "none", i);
|
||||
}
|
||||
}
|
||||
|
||||
static void torture_packet_aes256_gcm(void **state)
|
||||
{
|
||||
int i;
|
||||
(void)state; /* unused */
|
||||
for (i=1;i<256;++i){
|
||||
torture_packet("aes256-gcm@openssh.com", "none", "none", i);
|
||||
}
|
||||
}
|
||||
|
||||
static void torture_packet_compress_zlib(void **state)
|
||||
{
|
||||
int i;
|
||||
(void)state; /* unused */
|
||||
for (i=1;i<256;++i){
|
||||
torture_packet("aes256-ctr", "hmac-sha1", "zlib", i);
|
||||
}
|
||||
}
|
||||
|
||||
static void torture_packet_compress_zlib_openssh(void **state)
|
||||
{
|
||||
int i;
|
||||
(void)state; /* unused */
|
||||
for (i=1;i<256;++i){
|
||||
torture_packet("aes256-ctr", "hmac-sha1", "zlib@openssh.com", i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,7 +254,11 @@ int torture_run_tests(void) {
|
||||
cmocka_unit_test(torture_packet_aes192_cbc),
|
||||
cmocka_unit_test(torture_packet_aes256_cbc),
|
||||
cmocka_unit_test(torture_packet_3des_cbc),
|
||||
cmocka_unit_test(torture_packet_chacha20)
|
||||
cmocka_unit_test(torture_packet_chacha20),
|
||||
cmocka_unit_test(torture_packet_aes128_gcm),
|
||||
cmocka_unit_test(torture_packet_aes256_gcm),
|
||||
cmocka_unit_test(torture_packet_compress_zlib),
|
||||
cmocka_unit_test(torture_packet_compress_zlib_openssh),
|
||||
};
|
||||
|
||||
ssh_init();
|
||||
|
||||
@@ -263,6 +263,8 @@ static void torture_packet_filter_check_unfiltered(void **state)
|
||||
enum ssh_packet_filter_result_e rc;
|
||||
int in_unfiltered;
|
||||
|
||||
(void)state;
|
||||
|
||||
session = ssh_new();
|
||||
|
||||
for (msg_type = 1; msg_type <= MESSAGE_COUNT; msg_type++) {
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
#include "torture_pki.h"
|
||||
#include "pki.c"
|
||||
|
||||
|
||||
const unsigned char HASH[] = "1234567890123456789012345678901234567890"
|
||||
"123456789012345678901234";
|
||||
|
||||
static void torture_pki_keytype(void **state) {
|
||||
enum ssh_keytypes_e type;
|
||||
const char *type_c;
|
||||
@@ -43,11 +47,227 @@ static void torture_pki_signature(void **state)
|
||||
ssh_signature_free(sig);
|
||||
}
|
||||
|
||||
/* Maps to enum ssh_keytypes_e */
|
||||
const char *key_types[] = {
|
||||
"", /* UNKNOWN */
|
||||
"ssh-dss",
|
||||
"ssh-rsa",
|
||||
"",/* RSA1 */
|
||||
"ecdsa-sha2-nistp521",
|
||||
"ssh-ed25519",
|
||||
};
|
||||
|
||||
/* Maps to enum ssh_keytypes_e */
|
||||
const int key_sizes[] = {
|
||||
0, /* UNKNOWN */
|
||||
1024,
|
||||
2048,
|
||||
0, /* RSA1 */
|
||||
521,
|
||||
0,
|
||||
};
|
||||
|
||||
/* Maps to enum ssh_keytypes_e */
|
||||
const int sig_lengths[] = {
|
||||
0, /* UNKNOWN */
|
||||
20,
|
||||
20,
|
||||
0, /* RSA1 */
|
||||
64,
|
||||
33,
|
||||
};
|
||||
|
||||
/* Maps to enum ssh_keytypes_e */
|
||||
const char *signature_types[] = {
|
||||
"", /* UNKNOWN */
|
||||
"ssh-dss",
|
||||
"ssh-rsa",
|
||||
"",/* RSA1 */
|
||||
"ecdsa-sha2-nistp521",
|
||||
"ssh-ed25519",
|
||||
};
|
||||
|
||||
/* Maps to enum ssh_digest_e */
|
||||
const char *hash_signatures[] = {
|
||||
"", /* Not used here */
|
||||
"ssh-rsa",
|
||||
"rsa-sha2-256",
|
||||
"rsa-sha2-512",
|
||||
};
|
||||
|
||||
/* Maps to enum ssh_digest_e */
|
||||
int hash_lengths[] = {
|
||||
0, /* Not used here */
|
||||
20,
|
||||
32,
|
||||
64,
|
||||
};
|
||||
|
||||
/* This tests all the base types and their signatures against each other */
|
||||
static void torture_pki_verify_mismatch(void **state)
|
||||
{
|
||||
int rc;
|
||||
int verbosity = torture_libssh_verbosity();
|
||||
ssh_key key = NULL, verify_key = NULL;
|
||||
ssh_signature sign = NULL, import_sig = NULL, new_sig = NULL;
|
||||
ssh_string blob;
|
||||
ssh_session session = ssh_new();
|
||||
enum ssh_keytypes_e key_type, sig_type, first_key;
|
||||
enum ssh_digest_e hash;
|
||||
int hash_length;
|
||||
|
||||
(void) state;
|
||||
|
||||
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||
|
||||
#ifdef HAVE_DSA
|
||||
first_key = SSH_KEYTYPE_DSS;
|
||||
#else
|
||||
first_key = SSH_KEYTYPE_RSA;
|
||||
#endif /* HAVE_DSA */
|
||||
|
||||
for (sig_type = first_key;
|
||||
sig_type <= SSH_KEYTYPE_ED25519;
|
||||
sig_type++) {
|
||||
if (sig_type == SSH_KEYTYPE_RSA1) {
|
||||
continue;
|
||||
}
|
||||
rc = ssh_pki_generate(sig_type, key_sizes[sig_type], &key);
|
||||
assert_true(rc == SSH_OK);
|
||||
assert_true(key != NULL);
|
||||
assert_int_equal(key->type, sig_type);
|
||||
assert_string_equal(key->type_c, key_types[sig_type]);
|
||||
|
||||
for (hash = SSH_DIGEST_AUTO;
|
||||
hash <= SSH_DIGEST_SHA512;
|
||||
hash++) {
|
||||
hash_length = ((hash == SSH_DIGEST_AUTO) ?
|
||||
sig_lengths[sig_type] : hash_lengths[hash]);
|
||||
|
||||
SSH_LOG(SSH_LOG_TRACE, "Creating signature %d with hash %d",
|
||||
sig_type, hash);
|
||||
|
||||
/* Create a valid signature using this key */
|
||||
sign = pki_do_sign_hash(key, HASH, hash_length, hash);
|
||||
assert_true(sign != NULL);
|
||||
assert_int_equal(sign->type, key->type);
|
||||
if (hash == SSH_DIGEST_AUTO) {
|
||||
assert_string_equal(sign->type_c, key->type_c);
|
||||
assert_string_equal(sign->type_c, signature_types[sig_type]);
|
||||
} else {
|
||||
assert_string_equal(sign->type_c, hash_signatures[hash]);
|
||||
}
|
||||
|
||||
/* Create a signature blob that can be imported and verified */
|
||||
blob = pki_signature_to_blob(sign);
|
||||
assert_non_null(blob);
|
||||
|
||||
/* Import and verify with current key
|
||||
* (this is not tested anywhere else yet) */
|
||||
import_sig = pki_signature_from_blob(key,
|
||||
blob,
|
||||
sig_type,
|
||||
hash);
|
||||
assert_non_null(import_sig);
|
||||
assert_int_equal(import_sig->type, key->type);
|
||||
if (hash == SSH_DIGEST_AUTO) {
|
||||
assert_string_equal(import_sig->type_c, key->type_c);
|
||||
assert_string_equal(import_sig->type_c, signature_types[sig_type]);
|
||||
} else {
|
||||
assert_string_equal(import_sig->type_c, hash_signatures[hash]);
|
||||
}
|
||||
|
||||
/* Internal API: Should work */
|
||||
rc = pki_signature_verify(session,
|
||||
import_sig,
|
||||
key,
|
||||
HASH,
|
||||
hash_length);
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
/* XXX Test all the hash versions only with RSA.
|
||||
* This also skips the cleanup for the last hash so we can use the
|
||||
* created signatures later on
|
||||
*/
|
||||
if (sig_type != SSH_KEYTYPE_RSA || hash == SSH_DIGEST_SHA512) {
|
||||
break;
|
||||
}
|
||||
ssh_string_free(blob);
|
||||
ssh_signature_free(sign);
|
||||
ssh_signature_free(import_sig);
|
||||
}
|
||||
|
||||
for (key_type = first_key;
|
||||
key_type <= SSH_KEYTYPE_ED25519;
|
||||
key_type++) {
|
||||
if (key_type == SSH_KEYTYPE_RSA1) {
|
||||
continue;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_TRACE, "Trying key %d with signature %d",
|
||||
key_type, sig_type);
|
||||
|
||||
rc = ssh_pki_generate(key_type, key_sizes[key_type], &verify_key);
|
||||
assert_true(rc == SSH_OK);
|
||||
assert_true(verify_key != NULL);
|
||||
|
||||
/* Should gracefully fail, but not crash */
|
||||
rc = pki_signature_verify(session,
|
||||
sign,
|
||||
verify_key,
|
||||
HASH,
|
||||
hash_length);
|
||||
assert_true(rc != SSH_OK);
|
||||
|
||||
/* Try the same with the imported signature */
|
||||
rc = pki_signature_verify(session,
|
||||
import_sig,
|
||||
verify_key,
|
||||
HASH,
|
||||
hash_length);
|
||||
assert_true(rc != SSH_OK);
|
||||
|
||||
/* Try to import the signature blob with different key */
|
||||
new_sig = pki_signature_from_blob(verify_key,
|
||||
blob,
|
||||
sig_type,
|
||||
SSH_DIGEST_SHA1);
|
||||
if (sig_type != key_type) {
|
||||
assert_true(new_sig == NULL);
|
||||
} else {
|
||||
/* Importing with the same key type should work */
|
||||
assert_true(new_sig != NULL);
|
||||
assert_int_equal(new_sig->type, key->type);
|
||||
assert_string_equal(new_sig->type_c, key->type_c);
|
||||
assert_string_equal(new_sig->type_c, signature_types[sig_type]);
|
||||
|
||||
/* The verification should not work */
|
||||
rc = pki_signature_verify(session,
|
||||
new_sig,
|
||||
verify_key,
|
||||
HASH,
|
||||
hash_length);
|
||||
assert_true(rc != SSH_OK);
|
||||
|
||||
ssh_signature_free(new_sig);
|
||||
}
|
||||
SSH_KEY_FREE(verify_key);
|
||||
}
|
||||
ssh_string_free(blob);
|
||||
ssh_signature_free(sign);
|
||||
ssh_signature_free(import_sig);
|
||||
SSH_KEY_FREE(key);
|
||||
key = NULL;
|
||||
}
|
||||
|
||||
ssh_free(session);
|
||||
}
|
||||
|
||||
int torture_run_tests(void) {
|
||||
int rc;
|
||||
struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(torture_pki_keytype),
|
||||
cmocka_unit_test(torture_pki_signature),
|
||||
cmocka_unit_test(torture_pki_verify_mismatch),
|
||||
};
|
||||
|
||||
ssh_init();
|
||||
|
||||
@@ -14,16 +14,39 @@
|
||||
#define LIBSSH_DSA_TESTKEY "libssh_testkey.id_dsa"
|
||||
#define LIBSSH_DSA_TESTKEY_PASSPHRASE "libssh_testkey_passphrase.id_dsa"
|
||||
|
||||
const char template[] = "temp_dir_XXXXXX";
|
||||
const unsigned char DSA_HASH[] = "12345678901234567890";
|
||||
|
||||
struct pki_st {
|
||||
char *cwd;
|
||||
char *temp_dir;
|
||||
};
|
||||
|
||||
static int setup_dsa_key(void **state)
|
||||
{
|
||||
(void) state; /* unused */
|
||||
struct pki_st *test_state = NULL;
|
||||
char *cwd = NULL;
|
||||
char *tmp_dir = NULL;
|
||||
int rc = 0;
|
||||
|
||||
unlink(LIBSSH_DSA_TESTKEY);
|
||||
unlink(LIBSSH_DSA_TESTKEY_PASSPHRASE);
|
||||
unlink(LIBSSH_DSA_TESTKEY ".pub");
|
||||
unlink(LIBSSH_DSA_TESTKEY "-cert.pub");
|
||||
test_state = (struct pki_st *)malloc(sizeof(struct pki_st));
|
||||
assert_non_null(test_state);
|
||||
|
||||
cwd = torture_get_current_working_dir();
|
||||
assert_non_null(cwd);
|
||||
|
||||
tmp_dir = torture_make_temp_dir(template);
|
||||
assert_non_null(tmp_dir);
|
||||
|
||||
test_state->cwd = cwd;
|
||||
test_state->temp_dir = tmp_dir;
|
||||
|
||||
*state = test_state;
|
||||
|
||||
rc = torture_change_dir(tmp_dir);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
printf("Changed directory to: %s\n", tmp_dir);
|
||||
|
||||
torture_write_file(LIBSSH_DSA_TESTKEY,
|
||||
torture_get_testkey(SSH_KEYTYPE_DSS, 0, 0));
|
||||
@@ -39,12 +62,27 @@ static int setup_dsa_key(void **state)
|
||||
|
||||
static int setup_openssh_dsa_key(void **state)
|
||||
{
|
||||
(void) state; /* unused */
|
||||
struct pki_st *test_state = NULL;
|
||||
char *cwd = NULL;
|
||||
char *tmp_dir = NULL;
|
||||
int rc = 0;
|
||||
|
||||
unlink(LIBSSH_DSA_TESTKEY);
|
||||
unlink(LIBSSH_DSA_TESTKEY_PASSPHRASE);
|
||||
unlink(LIBSSH_DSA_TESTKEY ".pub");
|
||||
unlink(LIBSSH_DSA_TESTKEY "-cert.pub");
|
||||
test_state = (struct pki_st *)malloc(sizeof(struct pki_st));
|
||||
assert_non_null(test_state);
|
||||
|
||||
cwd = torture_get_current_working_dir();
|
||||
assert_non_null(cwd);
|
||||
|
||||
tmp_dir = torture_make_temp_dir(template);
|
||||
assert_non_null(tmp_dir);
|
||||
|
||||
test_state->cwd = cwd;
|
||||
test_state->temp_dir = tmp_dir;
|
||||
|
||||
*state = test_state;
|
||||
|
||||
rc = torture_change_dir(tmp_dir);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
torture_write_file(LIBSSH_DSA_TESTKEY,
|
||||
torture_get_openssh_testkey(SSH_KEYTYPE_DSS, 0, 0));
|
||||
@@ -58,14 +96,26 @@ static int setup_openssh_dsa_key(void **state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int teardown_dsa_key(void **state)
|
||||
{
|
||||
(void)state;
|
||||
static int teardown(void **state) {
|
||||
|
||||
unlink(LIBSSH_DSA_TESTKEY);
|
||||
unlink(LIBSSH_DSA_TESTKEY_PASSPHRASE);
|
||||
unlink(LIBSSH_DSA_TESTKEY ".pub");
|
||||
unlink(LIBSSH_DSA_TESTKEY "-cert.pub");
|
||||
struct pki_st *test_state = NULL;
|
||||
int rc = 0;
|
||||
|
||||
test_state = *((struct pki_st **)state);
|
||||
|
||||
assert_non_null(test_state);
|
||||
assert_non_null(test_state->cwd);
|
||||
assert_non_null(test_state->temp_dir);
|
||||
|
||||
rc = torture_change_dir(test_state->cwd);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = torture_rmdirs(test_state->temp_dir);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
SAFE_FREE(test_state->temp_dir);
|
||||
SAFE_FREE(test_state->cwd);
|
||||
SAFE_FREE(test_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -586,26 +636,26 @@ int torture_run_tests(void)
|
||||
struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(torture_pki_dsa_import_pubkey_file,
|
||||
setup_dsa_key,
|
||||
teardown_dsa_key),
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_dsa_import_pubkey_from_openssh_privkey,
|
||||
setup_openssh_dsa_key,
|
||||
teardown_dsa_key),
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_dsa_import_privkey_base64,
|
||||
setup_dsa_key,
|
||||
teardown_dsa_key),
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_dsa_import_privkey_base64,
|
||||
setup_openssh_dsa_key,
|
||||
teardown_dsa_key),
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_dsa_publickey_from_privatekey,
|
||||
setup_dsa_key,
|
||||
teardown_dsa_key),
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_dsa_import_cert_file,
|
||||
setup_dsa_key,
|
||||
teardown_dsa_key),
|
||||
teardown),
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
cmocka_unit_test_setup_teardown(torture_pki_dsa_write_privkey,
|
||||
setup_dsa_key,
|
||||
teardown_dsa_key),
|
||||
teardown),
|
||||
#endif
|
||||
cmocka_unit_test(torture_pki_dsa_import_privkey_base64_passphrase),
|
||||
cmocka_unit_test(torture_pki_dsa_import_openssh_privkey_base64_passphrase),
|
||||
@@ -613,16 +663,16 @@ int torture_run_tests(void)
|
||||
/* public key */
|
||||
cmocka_unit_test_setup_teardown(torture_pki_dsa_publickey_base64,
|
||||
setup_dsa_key,
|
||||
teardown_dsa_key),
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_dsa_generate_pubkey_from_privkey,
|
||||
setup_dsa_key,
|
||||
teardown_dsa_key),
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_dsa_duplicate_key,
|
||||
setup_dsa_key,
|
||||
teardown_dsa_key),
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_dsa_duplicate_key,
|
||||
setup_dsa_key,
|
||||
teardown_dsa_key),
|
||||
teardown),
|
||||
cmocka_unit_test(torture_pki_dsa_generate_key),
|
||||
};
|
||||
|
||||
|
||||
@@ -13,15 +13,39 @@
|
||||
#define LIBSSH_ECDSA_TESTKEY "libssh_testkey.id_ecdsa"
|
||||
#define LIBSSH_ECDSA_TESTKEY_PASSPHRASE "libssh_testkey_passphrase.id_ecdsa"
|
||||
|
||||
const char template[] = "temp_dir_XXXXXX";
|
||||
const unsigned char ECDSA_HASH[] = "12345678901234567890";
|
||||
|
||||
struct pki_st {
|
||||
char *cwd;
|
||||
char *temp_dir;
|
||||
};
|
||||
|
||||
static int setup_ecdsa_key(void **state, int ecdsa_bits)
|
||||
{
|
||||
(void) state; /* unused */
|
||||
struct pki_st *test_state = NULL;
|
||||
char *cwd = NULL;
|
||||
char *tmp_dir = NULL;
|
||||
int rc = 0;
|
||||
|
||||
unlink(LIBSSH_ECDSA_TESTKEY);
|
||||
unlink(LIBSSH_ECDSA_TESTKEY_PASSPHRASE);
|
||||
unlink(LIBSSH_ECDSA_TESTKEY ".pub");
|
||||
test_state = (struct pki_st *)malloc(sizeof(struct pki_st));
|
||||
assert_non_null(test_state);
|
||||
|
||||
cwd = torture_get_current_working_dir();
|
||||
assert_non_null(cwd);
|
||||
|
||||
tmp_dir = torture_make_temp_dir(template);
|
||||
assert_non_null(tmp_dir);
|
||||
|
||||
test_state->cwd = cwd;
|
||||
test_state->temp_dir = tmp_dir;
|
||||
|
||||
*state = test_state;
|
||||
|
||||
rc = torture_change_dir(tmp_dir);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
printf("Changed directory to: %s\n", tmp_dir);
|
||||
|
||||
torture_write_file(LIBSSH_ECDSA_TESTKEY,
|
||||
torture_get_testkey(SSH_KEYTYPE_ECDSA, ecdsa_bits, 0));
|
||||
@@ -35,13 +59,30 @@ static int setup_ecdsa_key(void **state, int ecdsa_bits)
|
||||
|
||||
static int setup_openssh_ecdsa_key(void **state, int ecdsa_bits)
|
||||
{
|
||||
struct pki_st *test_state = NULL;
|
||||
char *cwd = NULL;
|
||||
char *tmp_dir = NULL;
|
||||
const char *keystring = NULL;
|
||||
int rc = 0;
|
||||
|
||||
(void) state; /* unused */
|
||||
test_state = (struct pki_st *)malloc(sizeof(struct pki_st));
|
||||
assert_non_null(test_state);
|
||||
|
||||
unlink(LIBSSH_ECDSA_TESTKEY);
|
||||
unlink(LIBSSH_ECDSA_TESTKEY_PASSPHRASE);
|
||||
unlink(LIBSSH_ECDSA_TESTKEY ".pub");
|
||||
cwd = torture_get_current_working_dir();
|
||||
assert_non_null(cwd);
|
||||
|
||||
tmp_dir = torture_make_temp_dir(template);
|
||||
assert_non_null(tmp_dir);
|
||||
|
||||
test_state->cwd = cwd;
|
||||
test_state->temp_dir = tmp_dir;
|
||||
|
||||
*state = test_state;
|
||||
|
||||
rc = torture_change_dir(tmp_dir);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
printf("Changed directory to: %s\n", tmp_dir);
|
||||
|
||||
keystring = torture_get_openssh_testkey(SSH_KEYTYPE_ECDSA, ecdsa_bits, 0);
|
||||
torture_write_file(LIBSSH_ECDSA_TESTKEY,
|
||||
@@ -98,13 +139,26 @@ static int setup_openssh_ecdsa_key_256(void **state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int teardown(void **state)
|
||||
{
|
||||
(void) state; /* unused */
|
||||
static int teardown(void **state) {
|
||||
|
||||
unlink(LIBSSH_ECDSA_TESTKEY);
|
||||
unlink(LIBSSH_ECDSA_TESTKEY_PASSPHRASE);
|
||||
unlink(LIBSSH_ECDSA_TESTKEY ".pub");
|
||||
struct pki_st *test_state = NULL;
|
||||
int rc = 0;
|
||||
|
||||
test_state = *((struct pki_st **)state);
|
||||
|
||||
assert_non_null(test_state);
|
||||
assert_non_null(test_state->cwd);
|
||||
assert_non_null(test_state->temp_dir);
|
||||
|
||||
rc = torture_change_dir(test_state->cwd);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = torture_rmdirs(test_state->temp_dir);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
SAFE_FREE(test_state->temp_dir);
|
||||
SAFE_FREE(test_state->cwd);
|
||||
SAFE_FREE(test_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -199,15 +253,19 @@ static void torture_pki_ecdsa_publickey_base64(void **state)
|
||||
assert_true(key_buf != NULL);
|
||||
|
||||
q = p = key_buf;
|
||||
while (*p != ' ') p++;
|
||||
*p = '\0';
|
||||
while (p != NULL && *p != '\0' && *p != ' ') p++;
|
||||
if (p != NULL) {
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
type = ssh_key_type_from_name(q);
|
||||
assert_true(type == SSH_KEYTYPE_ECDSA);
|
||||
|
||||
q = ++p;
|
||||
while (*p != ' ') p++;
|
||||
*p = '\0';
|
||||
while (p != NULL && *p != '\0' && *p != ' ') p++;
|
||||
if (p != NULL) {
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
rc = ssh_pki_import_pubkey_base64(q, type, &key);
|
||||
assert_true(rc == 0);
|
||||
@@ -332,14 +390,15 @@ static void torture_pki_ecdsa_duplicate_then_demote(void **state)
|
||||
NULL,
|
||||
NULL,
|
||||
&privkey);
|
||||
assert_true(rc == 0);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
privkey_dup = ssh_key_dup(privkey);
|
||||
assert_true(privkey_dup != NULL);
|
||||
assert_non_null(privkey_dup);
|
||||
assert_int_equal(privkey->ecdsa_nid, privkey_dup->ecdsa_nid);
|
||||
|
||||
rc = ssh_pki_export_privkey_to_pubkey(privkey_dup, &pubkey);
|
||||
assert_true(rc == 0);
|
||||
assert_int_equal(rc, 0);
|
||||
assert_non_null(pubkey);
|
||||
assert_int_equal(pubkey->ecdsa_nid, privkey->ecdsa_nid);
|
||||
|
||||
SSH_KEY_FREE(pubkey);
|
||||
@@ -392,7 +451,7 @@ static void torture_pki_generate_key_ecdsa(void **state)
|
||||
ssh_signature_free(sign);
|
||||
SSH_KEY_FREE(key);
|
||||
|
||||
rc = ssh_pki_generate(SSH_KEYTYPE_ECDSA, 512, &key);
|
||||
rc = ssh_pki_generate(SSH_KEYTYPE_ECDSA, 521, &key);
|
||||
assert_true(rc == SSH_OK);
|
||||
assert_true(key != NULL);
|
||||
sign = pki_do_sign(key, ECDSA_HASH, 20);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#define LIBSSH_ED25519_TESTKEY "libssh_testkey.id_ed25519"
|
||||
#define LIBSSH_ED25519_TESTKEY_PASSPHRASE "libssh_testkey_passphrase.id_ed25519"
|
||||
|
||||
const char template[] = "temp_dir_XXXXXX";
|
||||
const unsigned char HASH[] = "12345678901234567890";
|
||||
const uint8_t ref_signature[ED25519_SIG_LEN]=
|
||||
"\xbb\x8d\x55\x9f\x06\x14\x39\x24\xb4\xe1\x5a\x57\x3d\x9d\xbe\x22"
|
||||
@@ -19,15 +20,37 @@ const uint8_t ref_signature[ED25519_SIG_LEN]=
|
||||
"\x10\xa3\x18\x93\xdf\xa4\x96\x81\x11\x8e\x1e\x26\x14\x8a\x08\x1b"
|
||||
"\x01\x6a\x60\x59\x9c\x4a\x55\xa3\x16\x56\xf6\xc4\x50\x42\x7f\x03";
|
||||
|
||||
struct pki_st {
|
||||
char *cwd;
|
||||
char *temp_dir;
|
||||
};
|
||||
|
||||
static int setup_ed25519_key(void **state)
|
||||
{
|
||||
const char *keystring = NULL;
|
||||
struct pki_st *test_state = NULL;
|
||||
char *cwd = NULL;
|
||||
char *tmp_dir = NULL;
|
||||
int rc = 0;
|
||||
|
||||
(void) state; /* unused */
|
||||
test_state = (struct pki_st *)malloc(sizeof(struct pki_st));
|
||||
assert_non_null(test_state);
|
||||
|
||||
unlink(LIBSSH_ED25519_TESTKEY);
|
||||
unlink(LIBSSH_ED25519_TESTKEY_PASSPHRASE);
|
||||
unlink(LIBSSH_ED25519_TESTKEY ".pub");
|
||||
cwd = torture_get_current_working_dir();
|
||||
assert_non_null(cwd);
|
||||
|
||||
tmp_dir = torture_make_temp_dir(template);
|
||||
assert_non_null(tmp_dir);
|
||||
|
||||
test_state->cwd = cwd;
|
||||
test_state->temp_dir = tmp_dir;
|
||||
|
||||
*state = test_state;
|
||||
|
||||
rc = torture_change_dir(tmp_dir);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
printf("Changed directory to: %s\n", tmp_dir);
|
||||
|
||||
keystring = torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0, 0);
|
||||
torture_write_file(LIBSSH_ED25519_TESTKEY, keystring);
|
||||
@@ -41,11 +64,24 @@ static int setup_ed25519_key(void **state)
|
||||
}
|
||||
|
||||
static int teardown(void **state) {
|
||||
(void) state; /* unused */
|
||||
struct pki_st *test_state = NULL;
|
||||
int rc = 0;
|
||||
|
||||
unlink(LIBSSH_ED25519_TESTKEY);
|
||||
unlink(LIBSSH_ED25519_TESTKEY_PASSPHRASE);
|
||||
unlink(LIBSSH_ED25519_TESTKEY ".pub");
|
||||
test_state = *((struct pki_st **)state);
|
||||
|
||||
assert_non_null(test_state);
|
||||
assert_non_null(test_state->cwd);
|
||||
assert_non_null(test_state->temp_dir);
|
||||
|
||||
rc = torture_change_dir(test_state->cwd);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = torture_rmdirs(test_state->temp_dir);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
SAFE_FREE(test_state->temp_dir);
|
||||
SAFE_FREE(test_state->cwd);
|
||||
SAFE_FREE(test_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -202,15 +238,19 @@ static void torture_pki_ed25519_publickey_base64(void **state)
|
||||
assert_true(key_buf != NULL);
|
||||
|
||||
q = p = key_buf;
|
||||
while (*p != ' ') p++;
|
||||
*p = '\0';
|
||||
while (p != NULL && *p != '\0' && *p != ' ') p++;
|
||||
if (p != NULL) {
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
type = ssh_key_type_from_name(q);
|
||||
assert_true(type == SSH_KEYTYPE_ED25519);
|
||||
|
||||
q = ++p;
|
||||
while (*p != ' ') p++;
|
||||
*p = '\0';
|
||||
while (p != NULL && *p != '\0' && *p != ' ') p++;
|
||||
if (p != NULL) {
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
rc = ssh_pki_import_pubkey_base64(q, type, &key);
|
||||
assert_true(rc == 0);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user