mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-04 20:30:38 +09:00
Compare commits
499 Commits
libssh-0.6
...
libssh-0.7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cdf7690e03 | ||
|
|
7b19719022 | ||
|
|
f8d0026c65 | ||
|
|
6b608e70ee | ||
|
|
a69a1af568 | ||
|
|
32b72555ee | ||
|
|
32af6a2390 | ||
|
|
b470dd943f | ||
|
|
69ca977aed | ||
|
|
728a6349b7 | ||
|
|
ec32174abc | ||
|
|
2172cd234a | ||
|
|
0425ac9ad0 | ||
|
|
367558bb21 | ||
|
|
186e7b5ca4 | ||
|
|
2197704693 | ||
|
|
229eb8715d | ||
|
|
1b18a06f8c | ||
|
|
91b513798e | ||
|
|
25234e510a | ||
|
|
d16eac5704 | ||
|
|
46bff47975 | ||
|
|
f718b50b3f | ||
|
|
58b7d0f5d2 | ||
|
|
30d4581be5 | ||
|
|
83387f957f | ||
|
|
f3620bbbad | ||
|
|
b45933d30d | ||
|
|
1613ed556d | ||
|
|
8f5b7b65eb | ||
|
|
053f72c671 | ||
|
|
63a8f333b8 | ||
|
|
57fd8e3187 | ||
|
|
03972b16c9 | ||
|
|
ac7ed82585 | ||
|
|
196c2e9c1f | ||
|
|
1accbcb98b | ||
|
|
342ae10f08 | ||
|
|
eb98a780ed | ||
|
|
64233fa3bb | ||
|
|
cbf5cf4ac3 | ||
|
|
a3f3f9cb76 | ||
|
|
5aeae08be0 | ||
|
|
64a658acaa | ||
|
|
361940a5d7 | ||
|
|
2721cbc8ee | ||
|
|
5eb7a6ca38 | ||
|
|
3f4b5436e5 | ||
|
|
82cf5ea24c | ||
|
|
90e4786523 | ||
|
|
f65f41acc2 | ||
|
|
8979150745 | ||
|
|
f81d296e54 | ||
|
|
57afe78167 | ||
|
|
ee460dc04b | ||
|
|
f134cb3d57 | ||
|
|
3eaad77de2 | ||
|
|
9244750a63 | ||
|
|
e8720a30e2 | ||
|
|
ad09009201 | ||
|
|
e4e3b3052f | ||
|
|
96882cc58c | ||
|
|
7c79959e94 | ||
|
|
ca501df8c8 | ||
|
|
a4cecf59d5 | ||
|
|
244881b87d | ||
|
|
cf05e653de | ||
|
|
4b9916136d | ||
|
|
33ecff11dd | ||
|
|
83d3ee7fdb | ||
|
|
b1a3f4ee33 | ||
|
|
05498e0e33 | ||
|
|
4948fe21cd | ||
|
|
fe8fcb805c | ||
|
|
c4af6fbce3 | ||
|
|
3091025472 | ||
|
|
bf0c7ae0ae | ||
|
|
b5dc8197f7 | ||
|
|
19e23e6128 | ||
|
|
195f25cfbd | ||
|
|
1cb940c44a | ||
|
|
3f04367fb8 | ||
|
|
6c7e552509 | ||
|
|
b1cb8de385 | ||
|
|
69c9cd029f | ||
|
|
c699b9ca94 | ||
|
|
53586ed4ba | ||
|
|
5236358a48 | ||
|
|
d6fe9dc220 | ||
|
|
e0a73d3dbe | ||
|
|
dbe7df7571 | ||
|
|
a3357b8920 | ||
|
|
7ec798d3e7 | ||
|
|
f32e5f2191 | ||
|
|
cd078c7085 | ||
|
|
2e445d5871 | ||
|
|
5c46fbc680 | ||
|
|
2a780afc57 | ||
|
|
940cb233ce | ||
|
|
a653e27a2e | ||
|
|
d3f30da158 | ||
|
|
760d93e87b | ||
|
|
d42a1a35b0 | ||
|
|
8af829a42a | ||
|
|
ad8fa427dd | ||
|
|
de10a7754b | ||
|
|
6789170799 | ||
|
|
afc9988c93 | ||
|
|
2490404d45 | ||
|
|
fbdb940c46 | ||
|
|
c8d0b724b3 | ||
|
|
9e4700cdc0 | ||
|
|
b76d37b341 | ||
|
|
423fa6818b | ||
|
|
61e2c8f0f7 | ||
|
|
c02b260e7e | ||
|
|
01a6004171 | ||
|
|
4f5660e081 | ||
|
|
46bc11f977 | ||
|
|
119840b0a9 | ||
|
|
4343ac5b08 | ||
|
|
6b9183a20b | ||
|
|
3ec3a926e5 | ||
|
|
2f7886837f | ||
|
|
7febad5821 | ||
|
|
b235c380f2 | ||
|
|
f6a50aff4c | ||
|
|
6b7f275c32 | ||
|
|
4bde48bb2e | ||
|
|
f4154c503b | ||
|
|
8db4520d89 | ||
|
|
9a7d450098 | ||
|
|
7070117dc3 | ||
|
|
433f8fd550 | ||
|
|
c6590bd189 | ||
|
|
929868c691 | ||
|
|
06a0d8ff1c | ||
|
|
af0dd3fb02 | ||
|
|
ce02f6576a | ||
|
|
68e720a3da | ||
|
|
c224508bf8 | ||
|
|
15d71a8c51 | ||
|
|
8536cd9808 | ||
|
|
353751e3e3 | ||
|
|
159ef828dd | ||
|
|
3dd069c0c8 | ||
|
|
a198193723 | ||
|
|
e051135a05 | ||
|
|
bb18442fe8 | ||
|
|
c2aed4ca78 | ||
|
|
b7b535816d | ||
|
|
d8e691b58a | ||
|
|
52968b1a11 | ||
|
|
b35f1f488c | ||
|
|
10f71c6769 | ||
|
|
014fde0542 | ||
|
|
ca2acec34a | ||
|
|
bb197de75d | ||
|
|
03095f1516 | ||
|
|
6895d0b727 | ||
|
|
4745d652b5 | ||
|
|
a48711ae7e | ||
|
|
a25790d343 | ||
|
|
cd2dc3770a | ||
|
|
250f506487 | ||
|
|
9dc932c02b | ||
|
|
aaae6cd97d | ||
|
|
509676e3a4 | ||
|
|
a6d412f0d7 | ||
|
|
59da8dab50 | ||
|
|
7edbedf0dd | ||
|
|
af25c5e668 | ||
|
|
092fe0b727 | ||
|
|
1ddb99c46f | ||
|
|
93c7b81b4e | ||
|
|
93e82fa0c0 | ||
|
|
e9b2d164e0 | ||
|
|
86ae6b2251 | ||
|
|
2cb2587b55 | ||
|
|
86294ad3ea | ||
|
|
173994786b | ||
|
|
81123d6a91 | ||
|
|
25eb9c4914 | ||
|
|
c6210f5aef | ||
|
|
c673543e54 | ||
|
|
edca9d6e96 | ||
|
|
83aed7610c | ||
|
|
5fa4721c6e | ||
|
|
8b7627efd5 | ||
|
|
662217f409 | ||
|
|
19433dca00 | ||
|
|
6961dd79ad | ||
|
|
1b6375ce89 | ||
|
|
64f6abead7 | ||
|
|
f20a6d0a82 | ||
|
|
97c6b76863 | ||
|
|
6019cf1bed | ||
|
|
228dc08038 | ||
|
|
33cd594f1f | ||
|
|
0cd0f685c9 | ||
|
|
664b94d1c5 | ||
|
|
3b4b0f01ec | ||
|
|
7bd62dd652 | ||
|
|
c341da03d3 | ||
|
|
c238136010 | ||
|
|
5a08ddcff2 | ||
|
|
a182926024 | ||
|
|
9457685320 | ||
|
|
e9fd14c7f0 | ||
|
|
cfd2e4894e | ||
|
|
3703389feb | ||
|
|
673990f568 | ||
|
|
97638a1465 | ||
|
|
506e11fa8b | ||
|
|
1dd95675df | ||
|
|
cb10ad0c84 | ||
|
|
1f2c61d6ad | ||
|
|
1d97f75b0a | ||
|
|
835e34d1eb | ||
|
|
13c42bff3f | ||
|
|
59a1799501 | ||
|
|
d9c47a8cfa | ||
|
|
987991a3f2 | ||
|
|
a738507ad2 | ||
|
|
142b2e4ede | ||
|
|
517a01b7ad | ||
|
|
83633d539e | ||
|
|
c2ee63431b | ||
|
|
9e4bc10525 | ||
|
|
f37c844bf7 | ||
|
|
2c7dfb02a8 | ||
|
|
2884bbf5b1 | ||
|
|
f48a99b97c | ||
|
|
11cfb2903e | ||
|
|
c520d97dd9 | ||
|
|
6c74d6f891 | ||
|
|
262c82ac06 | ||
|
|
164b8e99cc | ||
|
|
4a08902664 | ||
|
|
d6e6a453fc | ||
|
|
eb86fd8cdf | ||
|
|
099e2e8438 | ||
|
|
291312c5e4 | ||
|
|
e2805abbf7 | ||
|
|
79d51099ac | ||
|
|
adf23533e0 | ||
|
|
927cd90dc1 | ||
|
|
b5efbe75cd | ||
|
|
01311dd419 | ||
|
|
5865b9436f | ||
|
|
ad1313c2e5 | ||
|
|
0cb9f792b8 | ||
|
|
efe785e711 | ||
|
|
48aca98cd5 | ||
|
|
89e154f78c | ||
|
|
491b407d17 | ||
|
|
2f4589b765 | ||
|
|
acb7161c81 | ||
|
|
437a39c798 | ||
|
|
b3e6d5df53 | ||
|
|
53644a14ac | ||
|
|
aa05248ca8 | ||
|
|
04543c9dbc | ||
|
|
d5aeebe323 | ||
|
|
47bd0b6d1f | ||
|
|
8e2590b535 | ||
|
|
c51f42a566 | ||
|
|
00d4fbe753 | ||
|
|
dee8e5688b | ||
|
|
40d81bb7ca | ||
|
|
10bc5ac203 | ||
|
|
8ba9402282 | ||
|
|
a2fe341da5 | ||
|
|
dbb2de272b | ||
|
|
9423a3a065 | ||
|
|
0c5d4954a7 | ||
|
|
0b8d24f800 | ||
|
|
48354f56ec | ||
|
|
5c0c95bd34 | ||
|
|
c82dd2eb81 | ||
|
|
f6276fe739 | ||
|
|
2a1089d607 | ||
|
|
fbf73ede1e | ||
|
|
577840d7f7 | ||
|
|
3d9b1693eb | ||
|
|
15f3988bc8 | ||
|
|
9c2127b798 | ||
|
|
0bb779904d | ||
|
|
5eeac3566e | ||
|
|
e99246246b | ||
|
|
c96e862c08 | ||
|
|
7021a46617 | ||
|
|
c7cb2d0657 | ||
|
|
fd50a4dd9f | ||
|
|
afe97d6cab | ||
|
|
00949383f4 | ||
|
|
2a1cb323f7 | ||
|
|
4463d89a4a | ||
|
|
9e0fb9f29b | ||
|
|
a277dd9277 | ||
|
|
370d4b014d | ||
|
|
7bd5e4101c | ||
|
|
352c7381a8 | ||
|
|
3e57b54688 | ||
|
|
2a183440c7 | ||
|
|
bb0023b7c7 | ||
|
|
398e8d50b5 | ||
|
|
fa34d11749 | ||
|
|
93370d61ba | ||
|
|
22d6c36800 | ||
|
|
c28ad814d0 | ||
|
|
fdc660f313 | ||
|
|
57418dd2cc | ||
|
|
4e04ec8bf5 | ||
|
|
79a80cdc77 | ||
|
|
95782ada1f | ||
|
|
f7b61bf557 | ||
|
|
adf4d4f147 | ||
|
|
dc93edc932 | ||
|
|
6bbdaceaca | ||
|
|
eedecd0269 | ||
|
|
d904784489 | ||
|
|
31fb4e1e69 | ||
|
|
3bdc2b1d4f | ||
|
|
1e37430dbe | ||
|
|
671f1979a6 | ||
|
|
fdaa42da1a | ||
|
|
8d450ef81a | ||
|
|
c433ac02bd | ||
|
|
1c24a0508f | ||
|
|
f0d6ce8958 | ||
|
|
75be42df75 | ||
|
|
3224506fe0 | ||
|
|
d4d30d0375 | ||
|
|
7ff6b3537f | ||
|
|
368509f5d1 | ||
|
|
7eff889384 | ||
|
|
465816f4a0 | ||
|
|
9fff70fa41 | ||
|
|
d3e081ba44 | ||
|
|
086847f997 | ||
|
|
cb9786b3ae | ||
|
|
9c4144689d | ||
|
|
e745236ae5 | ||
|
|
13eef19000 | ||
|
|
2fe59071b2 | ||
|
|
a7157b7907 | ||
|
|
6007c3c43f | ||
|
|
9d1ddd0547 | ||
|
|
5229253f86 | ||
|
|
a1c4fc07d4 | ||
|
|
6d09104ad3 | ||
|
|
57ef959aa3 | ||
|
|
b617d7fa29 | ||
|
|
4b3363ecf2 | ||
|
|
6fe51b13fb | ||
|
|
8bcbfb1642 | ||
|
|
aecd952d18 | ||
|
|
fedb1b3def | ||
|
|
8fdfa13227 | ||
|
|
9d90d15e91 | ||
|
|
09a715b147 | ||
|
|
42ad55377f | ||
|
|
d771dafe04 | ||
|
|
09af855b6f | ||
|
|
0571360f37 | ||
|
|
f3e3700063 | ||
|
|
41fe03e0d6 | ||
|
|
b514957af7 | ||
|
|
d9c5d0767c | ||
|
|
8f162e3b13 | ||
|
|
32ba84dac7 | ||
|
|
7f806b7c68 | ||
|
|
a6107f7432 | ||
|
|
9829aa2236 | ||
|
|
f8debe9a19 | ||
|
|
8b407f1ca2 | ||
|
|
20b5734649 | ||
|
|
0557f57c63 | ||
|
|
4f4e917187 | ||
|
|
a1f0b2acfc | ||
|
|
d65777b570 | ||
|
|
2df00fd84c | ||
|
|
d1d3beac33 | ||
|
|
ad0abff8b3 | ||
|
|
cdd7a6cb8d | ||
|
|
004240af48 | ||
|
|
4e3d16e291 | ||
|
|
7933aef747 | ||
|
|
136efd6ed5 | ||
|
|
94969cf263 | ||
|
|
68c3c26029 | ||
|
|
fd185acbea | ||
|
|
7a4e8e58f0 | ||
|
|
cbeb2a9de7 | ||
|
|
d61fcbf7b2 | ||
|
|
75e61f498b | ||
|
|
09edee123a | ||
|
|
060171028c | ||
|
|
7ecdc3e0d5 | ||
|
|
67a080874b | ||
|
|
7b63fe2f22 | ||
|
|
3d934f3ddc | ||
|
|
06cc94eecf | ||
|
|
f6443b725a | ||
|
|
d8ead516de | ||
|
|
ccdc0f1805 | ||
|
|
66e7e7023b | ||
|
|
b4fc5d9524 | ||
|
|
811c645f2a | ||
|
|
c2312f9dda | ||
|
|
440d2ec0ea | ||
|
|
47e53deebd | ||
|
|
095a01b70c | ||
|
|
503c729bb0 | ||
|
|
41d99d32e8 | ||
|
|
c481f9dafd | ||
|
|
f240ecf328 | ||
|
|
1972a27fe0 | ||
|
|
097760db17 | ||
|
|
b3a08ba8d3 | ||
|
|
fef7e1dffe | ||
|
|
6d7bbe63fe | ||
|
|
387e26c837 | ||
|
|
e8e99ec6de | ||
|
|
13c4499449 | ||
|
|
4cc7f4ad03 | ||
|
|
a8dc67ded8 | ||
|
|
aa33d18930 | ||
|
|
8c5777554a | ||
|
|
06cd9bc4dc | ||
|
|
0c8984ba9f | ||
|
|
6f0f1ef292 | ||
|
|
b12f3f38c7 | ||
|
|
cb165df64e | ||
|
|
e4c4f57f05 | ||
|
|
c5ef5ed18f | ||
|
|
ebf4a03908 | ||
|
|
4f3ee2fc7e | ||
|
|
f565aeebfa | ||
|
|
04cb94a2dd | ||
|
|
754152aa22 | ||
|
|
1ef00045dd | ||
|
|
a466a624e2 | ||
|
|
643a3b7cc3 | ||
|
|
d2dea8dc2e | ||
|
|
6edb6bcca1 | ||
|
|
d4f5a0e6ab | ||
|
|
ce1d73e0f0 | ||
|
|
20caa68b84 | ||
|
|
b00a6e3885 | ||
|
|
ffc33ca28c | ||
|
|
ee95c05c08 | ||
|
|
cfea381307 | ||
|
|
099b914fd9 | ||
|
|
afd35fa98c | ||
|
|
f02bc4768e | ||
|
|
bcb162816e | ||
|
|
5baa6aed6b | ||
|
|
6a6e85752e | ||
|
|
4421540b7b | ||
|
|
d3c186b04c | ||
|
|
e30acdb58a | ||
|
|
b0cbe88b0b | ||
|
|
3afba83134 | ||
|
|
b8d47a438c | ||
|
|
5201c5850e | ||
|
|
bd8ab422d0 | ||
|
|
33890daf41 | ||
|
|
ac4c5699b1 | ||
|
|
15e31eb464 | ||
|
|
2e81dd61dd | ||
|
|
f2c2687ca6 | ||
|
|
4c300313c3 | ||
|
|
bec13a6ac0 | ||
|
|
423d8c9b6a | ||
|
|
685fe1d0b6 | ||
|
|
e588e2325d | ||
|
|
04fd756c49 | ||
|
|
4cb6afcbd4 | ||
|
|
4eae4d592c | ||
|
|
566d842405 | ||
|
|
5e2fbbc202 | ||
|
|
8e703b9974 | ||
|
|
89853607c5 | ||
|
|
20658abc78 | ||
|
|
8823dee51a | ||
|
|
3e07359a35 | ||
|
|
e9242a7a31 | ||
|
|
b9ada25296 | ||
|
|
33cb1bc08b | ||
|
|
6da54688eb | ||
|
|
ef6d19fbb1 | ||
|
|
acbca6a562 | ||
|
|
fc8081cd06 | ||
|
|
7a64dd1b9a | ||
|
|
5045133dc2 | ||
|
|
7f2049b0d5 | ||
|
|
aa3eeb38f9 |
@@ -4,6 +4,8 @@
|
|||||||
-DWITH_SFTP=1
|
-DWITH_SFTP=1
|
||||||
-DWITH_SSH1=1
|
-DWITH_SSH1=1
|
||||||
-DWITH_PCAP=1
|
-DWITH_PCAP=1
|
||||||
|
-DHAVE_ECDH=1
|
||||||
|
-DHAVE_ECC=1
|
||||||
-Iinclude/libssh
|
-Iinclude/libssh
|
||||||
-Iinclude
|
-Iinclude
|
||||||
-Ibuild
|
-Ibuild
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,6 +3,7 @@
|
|||||||
.*
|
.*
|
||||||
*.swp
|
*.swp
|
||||||
*~$
|
*~$
|
||||||
build
|
|
||||||
cscope.*
|
cscope.*
|
||||||
tags
|
tags
|
||||||
|
/build
|
||||||
|
/obj*
|
||||||
|
|||||||
2
AUTHORS
2
AUTHORS
@@ -1,7 +1,7 @@
|
|||||||
Author(s):
|
Author(s):
|
||||||
Aris Adamantiadis <aris@0xbadc0de.be> (project initiator)
|
Aris Adamantiadis <aris@0xbadc0de.be> (project initiator)
|
||||||
|
|
||||||
Andreas Schneider <mail@cynapses.org> (developer)
|
Andreas Schneider <asn@cryptomilk.org> (developer)
|
||||||
|
|
||||||
Nick Zitzmann <seiryu (at) comcast (dot) net> (mostly client SFTP stuff)
|
Nick Zitzmann <seiryu (at) comcast (dot) net> (mostly client SFTP stuff)
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
project(libssh C)
|
project(libssh C)
|
||||||
|
|
||||||
# Required cmake version
|
# Required cmake version
|
||||||
cmake_minimum_required(VERSION 2.6.0)
|
cmake_minimum_required(VERSION 2.8.5)
|
||||||
|
|
||||||
# global needed variables
|
# global needed variables
|
||||||
set(APPLICATION_NAME ${PROJECT_NAME})
|
set(APPLICATION_NAME ${PROJECT_NAME})
|
||||||
|
|
||||||
set(APPLICATION_VERSION_MAJOR "0")
|
set(APPLICATION_VERSION_MAJOR "0")
|
||||||
set(APPLICATION_VERSION_MINOR "5")
|
set(APPLICATION_VERSION_MINOR "7")
|
||||||
set(APPLICATION_VERSION_PATCH "90")
|
set(APPLICATION_VERSION_PATCH "3")
|
||||||
|
|
||||||
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
|
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
|
||||||
|
|
||||||
@@ -19,12 +19,12 @@ set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINO
|
|||||||
# Increment AGE. Set REVISION to 0
|
# Increment AGE. Set REVISION to 0
|
||||||
# If the source code was changed, but there were no interface changes:
|
# If the source code was changed, but there were no interface changes:
|
||||||
# Increment REVISION.
|
# Increment REVISION.
|
||||||
set(LIBRARY_VERSION "4.3.0")
|
set(LIBRARY_VERSION "4.4.1")
|
||||||
set(LIBRARY_SOVERSION "4")
|
set(LIBRARY_SOVERSION "4")
|
||||||
|
|
||||||
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
|
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
|
||||||
set(CMAKE_MODULE_PATH
|
set(CMAKE_MODULE_PATH
|
||||||
${CMAKE_SOURCE_DIR}/cmake/Modules
|
${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules
|
||||||
)
|
)
|
||||||
|
|
||||||
# add definitions
|
# add definitions
|
||||||
@@ -39,10 +39,6 @@ include(CPackConfig.cmake)
|
|||||||
include(MacroEnsureOutOfSourceBuild)
|
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.")
|
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.")
|
||||||
|
|
||||||
# add macros
|
|
||||||
include(MacroAddPlugin)
|
|
||||||
include(MacroCopyFile)
|
|
||||||
|
|
||||||
# search for libraries
|
# search for libraries
|
||||||
if (WITH_ZLIB)
|
if (WITH_ZLIB)
|
||||||
find_package(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
@@ -71,6 +67,13 @@ if (WITH_GSSAPI)
|
|||||||
find_package(GSSAPI)
|
find_package(GSSAPI)
|
||||||
endif (WITH_GSSAPI)
|
endif (WITH_GSSAPI)
|
||||||
|
|
||||||
|
if (WITH_NACL)
|
||||||
|
find_package(NaCl)
|
||||||
|
if (NOT NACL_FOUND)
|
||||||
|
set(WITH_NACL OFF)
|
||||||
|
endif (NOT NACL_FOUND)
|
||||||
|
endif (WITH_NACL)
|
||||||
|
|
||||||
# config.h checks
|
# config.h checks
|
||||||
include(ConfigureChecks.cmake)
|
include(ConfigureChecks.cmake)
|
||||||
configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||||
@@ -81,8 +84,8 @@ add_subdirectory(include)
|
|||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
|
|
||||||
# pkg-config file
|
# pkg-config file
|
||||||
|
if (UNIX)
|
||||||
configure_file(libssh.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc)
|
configure_file(libssh.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc)
|
||||||
configure_file(libssh_threads.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh_threads.pc)
|
|
||||||
install(
|
install(
|
||||||
FILES
|
FILES
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/libssh.pc
|
${CMAKE_CURRENT_BINARY_DIR}/libssh.pc
|
||||||
@@ -93,23 +96,43 @@ install(
|
|||||||
pkgconfig
|
pkgconfig
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (LIBSSH_THREADS)
|
||||||
|
configure_file(libssh_threads.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh_threads.pc)
|
||||||
|
install(
|
||||||
|
FILES
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/libssh.pc
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/libssh_threads.pc
|
||||||
|
DESTINATION
|
||||||
|
${LIB_INSTALL_DIR}/pkgconfig
|
||||||
|
COMPONENT
|
||||||
|
pkgconfig
|
||||||
|
)
|
||||||
|
endif (LIBSSH_THREADS)
|
||||||
|
endif (UNIX)
|
||||||
|
|
||||||
# cmake config files
|
# cmake config files
|
||||||
configure_file(libssh-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libssh-config.cmake @ONLY)
|
set(LIBSSH_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}ssh${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||||
configure_file(libssh-config-version.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libssh-config-version.cmake @ONLY)
|
set(LIBSSH_THREADS_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)
|
||||||
install(
|
install(
|
||||||
FILES
|
FILES
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/libssh-config.cmake
|
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/libssh-config-version.cmake
|
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
|
||||||
DESTINATION
|
DESTINATION
|
||||||
${CMAKE_INSTALL_DIR}
|
${CMAKE_INSTALL_DIR}/${PROJECT_NAME}
|
||||||
COMPONENT
|
COMPONENT
|
||||||
devel
|
devel
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# in tree build settings
|
# in tree build settings
|
||||||
configure_file(libssh-build-tree-settings.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libssh-build-tree-settings.cmake @ONLY)
|
configure_file(libssh-build-tree-settings.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libssh-build-tree-settings.cmake @ONLY)
|
||||||
|
|
||||||
add_subdirectory(examples)
|
if (WITH_EXAMPLES)
|
||||||
|
add_subdirectory(examples)
|
||||||
|
endif (WITH_EXAMPLES)
|
||||||
|
|
||||||
if (WITH_TESTING)
|
if (WITH_TESTING)
|
||||||
find_package(CMocka REQUIRED)
|
find_package(CMocka REQUIRED)
|
||||||
@@ -123,6 +146,7 @@ message(STATUS "********** ${PROJECT_NAME} build options : **********")
|
|||||||
|
|
||||||
message(STATUS "zlib support: ${WITH_ZLIB}")
|
message(STATUS "zlib support: ${WITH_ZLIB}")
|
||||||
message(STATUS "libgcrypt support: ${WITH_GCRYPT}")
|
message(STATUS "libgcrypt support: ${WITH_GCRYPT}")
|
||||||
|
message(STATUS "libnacl support: ${WITH_NACL}")
|
||||||
message(STATUS "SSH-1 support: ${WITH_SSH1}")
|
message(STATUS "SSH-1 support: ${WITH_SSH1}")
|
||||||
message(STATUS "SFTP support: ${WITH_SFTP}")
|
message(STATUS "SFTP support: ${WITH_SFTP}")
|
||||||
message(STATUS "Server support : ${WITH_SERVER}")
|
message(STATUS "Server support : ${WITH_SERVER}")
|
||||||
|
|||||||
@@ -4,22 +4,22 @@
|
|||||||
### general settings
|
### general settings
|
||||||
set(CPACK_PACKAGE_NAME ${APPLICATION_NAME})
|
set(CPACK_PACKAGE_NAME ${APPLICATION_NAME})
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The SSH library")
|
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The SSH library")
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README")
|
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README")
|
||||||
set(CPACK_PACKAGE_VENDOR "The SSH Library Development Team")
|
set(CPACK_PACKAGE_VENDOR "The SSH Library Development Team")
|
||||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
|
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
|
||||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
|
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING")
|
||||||
|
|
||||||
|
|
||||||
### versions
|
### versions
|
||||||
set(CPACK_PACKAGE_VERSION_MAJOR "0")
|
set(CPACK_PACKAGE_VERSION_MAJOR ${APPLICATION_VERSION_MAJOR})
|
||||||
set(CPACK_PACKAGE_VERSION_MINOR "5")
|
set(CPACK_PACKAGE_VERSION_MINOR ${APPLICATION_VERSION_MINOR})
|
||||||
set(CPACK_PACKAGE_VERSION_PATCH "90")
|
set(CPACK_PACKAGE_VERSION_PATCH ${APPLICATION_VERSION_PATCH})
|
||||||
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
|
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
|
||||||
|
|
||||||
|
|
||||||
### source generator
|
### source generator
|
||||||
set(CPACK_SOURCE_GENERATOR "TGZ")
|
set(CPACK_SOURCE_GENERATOR "TXZ")
|
||||||
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/build/;tags;cscope.*")
|
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/build/;/obj*/;tags;cscope.*")
|
||||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
|
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ set(UPDATE_TYPE "true")
|
|||||||
set(CTEST_PROJECT_NAME "libssh")
|
set(CTEST_PROJECT_NAME "libssh")
|
||||||
set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
|
set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
|
||||||
|
|
||||||
set(CTEST_DROP_METHOD "http")
|
set(CTEST_DROP_METHOD "https")
|
||||||
set(CTEST_DROP_SITE "test.libssh.org")
|
set(CTEST_DROP_SITE "test.libssh.org")
|
||||||
set(CTEST_DROP_LOCATION "/submit.php?project=libssh")
|
set(CTEST_DROP_LOCATION "/submit.php?project=libssh")
|
||||||
set(CTEST_DROP_SITE_CDASH TRUE)
|
set(CTEST_DROP_SITE_CDASH TRUE)
|
||||||
|
|||||||
84
ChangeLog
84
ChangeLog
@@ -1,16 +1,98 @@
|
|||||||
ChangeLog
|
ChangeLog
|
||||||
==========
|
==========
|
||||||
|
|
||||||
version 0.6.0 (released 2013-XX-XX)
|
version 0.7.3 (released 2016-01-23)
|
||||||
|
* Fixed CVE-2016-0739
|
||||||
|
* Fixed ssh-agent on big endian
|
||||||
|
* Fixed some documentation issues
|
||||||
|
|
||||||
|
version 0.7.2 (released 2015-09-15)
|
||||||
|
* Fixed OpenSSL detection on Windows
|
||||||
|
* Fixed return status for ssh_userauth_agent()
|
||||||
|
* Fixed KEX to prefer hmac-sha2-256
|
||||||
|
* Fixed sftp packet handling
|
||||||
|
* Fixed return values of ssh_key_is_(public|private)
|
||||||
|
* Fixed bug in global success reply
|
||||||
|
|
||||||
|
version 0.7.1 (released 2015-06-30)
|
||||||
|
* Fixed SSH_AUTH_PARTIAL auth with auto public key
|
||||||
|
* Fixed memory leak in session options
|
||||||
|
* Fixed allocation of ed25519 public keys
|
||||||
|
* Fixed channel exit-status and exit-signal
|
||||||
|
* Reintroduce ssh_forward_listen()
|
||||||
|
|
||||||
|
version 0.7.0 (released 2015-05-11)
|
||||||
|
* Added support for ed25519 keys
|
||||||
|
* Added SHA2 algorithms for HMAC
|
||||||
|
* Added improved and more secure buffer handling code
|
||||||
|
* Added callback for auth_none_function
|
||||||
|
* Added support for ECDSA private key signing
|
||||||
|
* Added more tests
|
||||||
|
* Fixed a lot of bugs
|
||||||
|
* Improved API documentation
|
||||||
|
|
||||||
|
version 0.6.5 (released 2015-04-29)
|
||||||
|
* Fixed CVE-2015-3146
|
||||||
|
* Fixed port handling in config file
|
||||||
|
* Fixed the build with libgcrypt
|
||||||
|
* Fixed SFTP endian issues (rlo #179)
|
||||||
|
* Fixed uninitilized sig variable (rlo #167)
|
||||||
|
* Fixed polling issues which could result in a hang
|
||||||
|
* Fixed handling of EINTR in ssh_poll() (rlo #186)
|
||||||
|
* Fixed C99 issues with __func__
|
||||||
|
* Fixed some memory leaks
|
||||||
|
* Improved macro detection on Windows
|
||||||
|
|
||||||
|
version 0.6.4 (released 2014-12-19)
|
||||||
|
* Fixed CVE-2014-8132.
|
||||||
|
* Added SHA-2 for session ID signing with ECDSA keys.
|
||||||
|
* Added support for ECDSA host keys.
|
||||||
|
* Added support for more ECDSA hostkey algorithms.
|
||||||
|
* Added ssh_pki_key_ecdsa_name() API.
|
||||||
|
* Fixed setting the bindfd only after successful listen.
|
||||||
|
* Fixed issues with user created sockets.
|
||||||
|
* Fixed several issues in libssh C++ wrapper.
|
||||||
|
* Fixed several documentation issues.
|
||||||
|
* Fixed channel exit-signal request.
|
||||||
|
* Fixed X11 request screen number in messages.
|
||||||
|
* Fixed several memory leaks.
|
||||||
|
|
||||||
|
version 0.6.3 (released 2014-03-04)
|
||||||
|
* Fixed CVE-2014-0017.
|
||||||
|
* Fixed memory leak with ecdsa signatures.
|
||||||
|
|
||||||
|
version 0.6.2 (released 2014-03-04)
|
||||||
|
* security: fix for vulnerability CVE-2014-0017
|
||||||
|
|
||||||
|
version 0.6.1 (released 2014-02-08)
|
||||||
|
* Added support for libgcrypt 1.6.
|
||||||
|
* Added ssh_channel_accept_forward().
|
||||||
|
* Added known_hosts heuristic during connection (#138).
|
||||||
|
* Added getters for session cipher names.
|
||||||
|
* Fixed decrypt of zero length buffer.
|
||||||
|
* Fixed padding in RSA signature blobs.
|
||||||
|
* Fixed DSA signature extraction.
|
||||||
|
* Fixed some memory leaks.
|
||||||
|
* Fixed read of non-connected socket.
|
||||||
|
* Fixed thread dectection.
|
||||||
|
|
||||||
|
version 0.6.0 (released 2014-01-08)
|
||||||
* Added new publicy key API.
|
* Added new publicy key API.
|
||||||
* Added new userauth API.
|
* Added new userauth API.
|
||||||
|
* Added ssh_get_publickey_hash() function.
|
||||||
|
* Added ssh_get_poll_flags() function.
|
||||||
* Added gssapi-mic userauth.
|
* Added gssapi-mic userauth.
|
||||||
|
* Added GSSAPIServerIdentity option.
|
||||||
|
* Added GSSAPIClientIdentity option.
|
||||||
|
* Added GSSAPIDelegateCredentials option.
|
||||||
* Added new callback based server API.
|
* Added new callback based server API.
|
||||||
* Added Elliptic Curve DSA (ECDSA) support (with OpenSSL).
|
* Added Elliptic Curve DSA (ECDSA) support (with OpenSSL).
|
||||||
* Added Elliptic Curve Diffie Hellman (ECDH) support.
|
* Added Elliptic Curve Diffie Hellman (ECDH) support.
|
||||||
|
* Added Curve25519 for ECDH key exchange.
|
||||||
* Added improved logging system.
|
* Added improved logging system.
|
||||||
* Added SSH-agent forwarding.
|
* Added SSH-agent forwarding.
|
||||||
* Added key-reexchange.
|
* Added key-reexchange.
|
||||||
|
* Added more unit tests.
|
||||||
* Improved documentation.
|
* Improved documentation.
|
||||||
* Fixed timeout handling.
|
* Fixed timeout handling.
|
||||||
|
|
||||||
|
|||||||
59
CodingStyle
59
CodingStyle
@@ -1,59 +0,0 @@
|
|||||||
Coding Style Conventions
|
|
||||||
========================
|
|
||||||
|
|
||||||
Coding style guidelines are about reducing the number of unnecessary
|
|
||||||
reformatting patches and making things easier for developers to work together.
|
|
||||||
|
|
||||||
You don't have to like them or even agree with them, but once put in place we
|
|
||||||
all have to abide by them (or vote to change them). However, coding style
|
|
||||||
should never outweigh coding itself and so the guidelines described here are
|
|
||||||
hopefully easy enough to follow as they are very common and supported by tools
|
|
||||||
and editors.
|
|
||||||
|
|
||||||
The basic style for C code is the Linux kernel coding style [1] with one
|
|
||||||
excecption, we use 4 spaces instead of tabs. This closely matches what most
|
|
||||||
libssh developers use already anyways, with a few exceptions as mentioned
|
|
||||||
below.
|
|
||||||
|
|
||||||
To shorthen this here are the highlights:
|
|
||||||
|
|
||||||
* Maximum line width is 80 characters
|
|
||||||
|
|
||||||
The reason is not about people with low-res screens but rather sticking
|
|
||||||
to 80 columns prevents you from easily nesting more than one level of
|
|
||||||
if statements or other code blocks.
|
|
||||||
|
|
||||||
* Use 4 spaces to indent
|
|
||||||
|
|
||||||
* No trailing whitespaces
|
|
||||||
|
|
||||||
* Follow the K&R guidelines. We won't go through all of them here. Do you
|
|
||||||
have a copy of "The C Programming Language" anyways right?
|
|
||||||
|
|
||||||
Editors
|
|
||||||
========
|
|
||||||
|
|
||||||
VIM
|
|
||||||
----
|
|
||||||
|
|
||||||
set ts=4 sw=4 et cindent
|
|
||||||
|
|
||||||
For Vim, the following settings in $HOME/.vimrc will also deal with
|
|
||||||
displaying trailing whitespace:
|
|
||||||
|
|
||||||
if has("syntax") && (&t_Co > 2 || has("gui_running"))
|
|
||||||
syntax on
|
|
||||||
function! ActivateInvisibleCharIndicator()
|
|
||||||
syntax match TrailingSpace "[ \t]\+$" display containedin=ALL
|
|
||||||
highlight TrailingSpace ctermbg=Red
|
|
||||||
endf
|
|
||||||
autocmd BufNewFile,BufRead * call ActivateInvisibleCharIndicator()
|
|
||||||
endif
|
|
||||||
" Show tabs, trailing whitespace, and continued lines visually
|
|
||||||
set list listchars=tab:»·,trail:·,extends:…
|
|
||||||
|
|
||||||
" highlight overly long lines same as TODOs.
|
|
||||||
set textwidth=80
|
|
||||||
autocmd BufNewFile,BufRead *.c,*.h exec 'match Todo /\%>' . &textwidth . 'v.\+/'
|
|
||||||
|
|
||||||
[1] https://www.kernel.org/doc/Documentation/CodingStyle
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
include(CheckIncludeFile)
|
include(CheckIncludeFile)
|
||||||
|
include(CheckIncludeFiles)
|
||||||
include(CheckSymbolExists)
|
include(CheckSymbolExists)
|
||||||
include(CheckFunctionExists)
|
include(CheckFunctionExists)
|
||||||
include(CheckLibraryExists)
|
include(CheckLibraryExists)
|
||||||
@@ -48,8 +49,15 @@ endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
|
|||||||
# HEADER FILES
|
# HEADER FILES
|
||||||
check_include_file(argp.h HAVE_ARGP_H)
|
check_include_file(argp.h HAVE_ARGP_H)
|
||||||
check_include_file(pty.h HAVE_PTY_H)
|
check_include_file(pty.h HAVE_PTY_H)
|
||||||
|
check_include_file(utmp.h HAVE_UTMP_H)
|
||||||
check_include_file(termios.h HAVE_TERMIOS_H)
|
check_include_file(termios.h HAVE_TERMIOS_H)
|
||||||
check_include_file(unistd.h HAVE_UNISTD_H)
|
check_include_file(unistd.h HAVE_UNISTD_H)
|
||||||
|
check_include_file(util.h HAVE_UTIL_H)
|
||||||
|
check_include_file(libutil.h HAVE_LIBUTIL_H)
|
||||||
|
check_include_file(sys/time.h HAVE_SYS_TIME_H)
|
||||||
|
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)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
check_include_files("winsock2.h;ws2tcpip.h;wspiapi.h" HAVE_WSPIAPI_H)
|
check_include_files("winsock2.h;ws2tcpip.h;wspiapi.h" HAVE_WSPIAPI_H)
|
||||||
@@ -59,23 +67,31 @@ if (WIN32)
|
|||||||
check_include_files("winsock2.h;ws2tcpip.h" HAVE_WS2TCPIP_H)
|
check_include_files("winsock2.h;ws2tcpip.h" HAVE_WS2TCPIP_H)
|
||||||
endif (WIN32)
|
endif (WIN32)
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
if (OPENSSL_FOUND)
|
||||||
check_include_file(openssl/aes.h HAVE_OPENSSL_AES_H)
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||||
|
check_include_file(openssl/des.h HAVE_OPENSSL_DES_H)
|
||||||
|
if (NOT HAVE_OPENSSL_DES_H)
|
||||||
|
message(FATAL_ERROR "Could not detect openssl/des.h")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||||
check_include_file(openssl/blowfish.h HAVE_OPENSSL_BLOWFISH_H)
|
check_include_file(openssl/aes.h HAVE_OPENSSL_AES_H)
|
||||||
|
if (NOT HAVE_OPENSSL_AES_H)
|
||||||
|
message(FATAL_ERROR "Could not detect openssl/aes.h")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||||
check_include_file(openssl/des.h HAVE_OPENSSL_DES_H)
|
check_include_file(openssl/blowfish.h HAVE_OPENSSL_BLOWFISH_H)
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||||
check_include_file(openssl/ecdh.h HAVE_OPENSSL_ECDH_H)
|
check_include_file(openssl/ecdh.h HAVE_OPENSSL_ECDH_H)
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||||
check_include_file(openssl/ec.h HAVE_OPENSSL_EC_H)
|
check_include_file(openssl/ec.h HAVE_OPENSSL_EC_H)
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||||
check_include_file(openssl/ecdsa.h HAVE_OPENSSL_ECDSA_H)
|
check_include_file(openssl/ecdsa.h HAVE_OPENSSL_ECDSA_H)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (CMAKE_HAVE_PTHREAD_H)
|
if (CMAKE_HAVE_PTHREAD_H)
|
||||||
set(HAVE_PTHREAD_H 1)
|
set(HAVE_PTHREAD_H 1)
|
||||||
@@ -93,14 +109,11 @@ endif (NOT WITH_GCRYPT)
|
|||||||
|
|
||||||
# FUNCTIONS
|
# FUNCTIONS
|
||||||
|
|
||||||
|
check_function_exists(isblank HAVE_ISBLANK)
|
||||||
check_function_exists(strncpy HAVE_STRNCPY)
|
check_function_exists(strncpy HAVE_STRNCPY)
|
||||||
check_function_exists(vsnprintf HAVE_VSNPRINTF)
|
|
||||||
check_function_exists(snprintf HAVE_SNPRINTF)
|
check_symbol_exists(vsnprintf "stdio.h" HAVE_VSNPRINTF)
|
||||||
check_function_exists(poll HAVE_POLL)
|
check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF)
|
||||||
check_function_exists(select HAVE_SELECT)
|
|
||||||
check_function_exists(getaddrinfo HAVE_GETADDRINFO)
|
|
||||||
check_function_exists(ntohll HAVE_NTOHLL)
|
|
||||||
check_function_exists(htonll HAVE_HTONLL)
|
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
check_function_exists(_strtoui64 HAVE__STRTOUI64)
|
check_function_exists(_strtoui64 HAVE__STRTOUI64)
|
||||||
@@ -111,17 +124,28 @@ if (WIN32)
|
|||||||
check_function_exists(_snprintf_s HAVE__SNPRINTF_S)
|
check_function_exists(_snprintf_s HAVE__SNPRINTF_S)
|
||||||
|
|
||||||
if (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
|
if (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
|
||||||
set(HAVE_GETADDRINFO TRUE)
|
check_symbol_exists(ntohll winsock2.h HAVE_NTOHLL)
|
||||||
set(HAVE_GETHOSTBYNAME TRUE)
|
check_symbol_exists(htonll winsock2.h HAVE_HTONLL)
|
||||||
if (MSVC)
|
|
||||||
set(HAVE_NTOHLL TRUE)
|
set(CMAKE_REQUIRED_LIBRARIES ws2_32)
|
||||||
set(HAVE_HTONLL TRUE)
|
check_symbol_exists(select "winsock2.h;ws2tcpip.h" HAVE_SELECT)
|
||||||
endif (MSVC)
|
check_symbol_exists(poll "winsock2.h;ws2tcpip.h" HAVE_SELECT)
|
||||||
|
# The getaddrinfo function is defined to the WspiapiGetAddrInfo inline function
|
||||||
|
check_symbol_exists(getaddrinfo "winsock2.h;ws2tcpip.h" HAVE_GETADDRINFO)
|
||||||
|
set(CMAKE_REQUIRED_LIBRARIES)
|
||||||
endif (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
|
endif (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
|
||||||
|
|
||||||
set(HAVE_SELECT TRUE)
|
set(HAVE_SELECT TRUE)
|
||||||
|
else (WIN32)
|
||||||
|
check_function_exists(poll HAVE_POLL)
|
||||||
|
check_function_exists(select HAVE_SELECT)
|
||||||
|
check_function_exists(getaddrinfo HAVE_GETADDRINFO)
|
||||||
|
|
||||||
|
check_symbol_exists(ntohll arpa/inet.h HAVE_NTOHLL)
|
||||||
|
check_symbol_exists(htonll arpa/inet.h HAVE_HTONLL)
|
||||||
endif (WIN32)
|
endif (WIN32)
|
||||||
|
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
if (NOT LINUX)
|
if (NOT LINUX)
|
||||||
# libsocket (Solaris)
|
# libsocket (Solaris)
|
||||||
@@ -167,11 +191,9 @@ if (GCRYPT_FOUND)
|
|||||||
endif (GCRYPT_VERSION VERSION_GREATER "1.4.6")
|
endif (GCRYPT_VERSION VERSION_GREATER "1.4.6")
|
||||||
endif (GCRYPT_FOUND)
|
endif (GCRYPT_FOUND)
|
||||||
|
|
||||||
if (CMAKE_HAVE_THREADS_LIBRARY)
|
if (CMAKE_USE_PTHREADS_INIT)
|
||||||
if (CMAKE_USE_PTHREADS_INIT)
|
set(HAVE_PTHREAD 1)
|
||||||
set(HAVE_PTHREAD 1)
|
endif (CMAKE_USE_PTHREADS_INIT)
|
||||||
endif (CMAKE_USE_PTHREADS_INIT)
|
|
||||||
endif (CMAKE_HAVE_THREADS_LIBRARY)
|
|
||||||
|
|
||||||
# OPTIONS
|
# OPTIONS
|
||||||
check_c_source_compiles("
|
check_c_source_compiles("
|
||||||
@@ -200,6 +222,33 @@ int main(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}" HAVE_GCC_VOLATILE_MEMORY_PROTECTION)
|
}" HAVE_GCC_VOLATILE_MEMORY_PROTECTION)
|
||||||
|
|
||||||
|
check_c_source_compiles("
|
||||||
|
#include <stdio.h>
|
||||||
|
#define __VA_NARG__(...) (__VA_NARG_(_0, ## __VA_ARGS__, __RSEQ_N()) - 1)
|
||||||
|
#define __VA_NARG_(...) __VA_ARG_N(__VA_ARGS__)
|
||||||
|
#define __VA_ARG_N( _1, _2, _3, _4, _5, _6, _7, _8, _9,_10,N,...) N
|
||||||
|
#define __RSEQ_N() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
|
||||||
|
#define myprintf(format, ...) printf((format), __VA_NARG__(__VA_ARGS__), __VA_ARGS__)
|
||||||
|
int main(void) {
|
||||||
|
myprintf(\"%d %d %d %d\",1,2,3);
|
||||||
|
return 0;
|
||||||
|
}" HAVE_GCC_NARG_MACRO)
|
||||||
|
|
||||||
|
check_c_source_compiles("
|
||||||
|
#include <stdio.h>
|
||||||
|
int main(void) {
|
||||||
|
printf(\"%s\", __func__);
|
||||||
|
return 0;
|
||||||
|
}" HAVE_COMPILER__FUNC__)
|
||||||
|
|
||||||
|
check_c_source_compiles("
|
||||||
|
#include <stdio.h>
|
||||||
|
int main(void) {
|
||||||
|
printf(\"%s\", __FUNCTION__);
|
||||||
|
return 0;
|
||||||
|
}" HAVE_COMPILER__FUNCTION__)
|
||||||
|
|
||||||
|
|
||||||
if (WITH_DEBUG_CRYPTO)
|
if (WITH_DEBUG_CRYPTO)
|
||||||
set(DEBUG_CRYPTO 1)
|
set(DEBUG_CRYPTO 1)
|
||||||
endif (WITH_DEBUG_CRYPTO)
|
endif (WITH_DEBUG_CRYPTO)
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ option(WITH_INTERNAL_DOC "Compile doxygen internal documentation" OFF)
|
|||||||
option(WITH_TESTING "Build with unit tests" OFF)
|
option(WITH_TESTING "Build with unit tests" OFF)
|
||||||
option(WITH_CLIENT_TESTING "Build with client tests; requires a running sshd" OFF)
|
option(WITH_CLIENT_TESTING "Build with client tests; requires a running sshd" OFF)
|
||||||
option(WITH_BENCHMARKS "Build benchmarks tools" OFF)
|
option(WITH_BENCHMARKS "Build benchmarks tools" OFF)
|
||||||
|
option(WITH_EXAMPLES "Build examples" ON)
|
||||||
|
option(WITH_NACL "Build with libnacl (curve25519" ON)
|
||||||
if (WITH_ZLIB)
|
if (WITH_ZLIB)
|
||||||
set(WITH_LIBZ ON)
|
set(WITH_LIBZ ON)
|
||||||
else (WITH_ZLIB)
|
else (WITH_ZLIB)
|
||||||
@@ -26,3 +27,7 @@ endif(WITH_BENCHMARKS)
|
|||||||
if (WITH_TESTING)
|
if (WITH_TESTING)
|
||||||
set(WITH_STATIC_LIB ON)
|
set(WITH_STATIC_LIB ON)
|
||||||
endif (WITH_TESTING)
|
endif (WITH_TESTING)
|
||||||
|
|
||||||
|
if (WITH_NACL)
|
||||||
|
set(WITH_NACL ON)
|
||||||
|
endif (WITH_NACL)
|
||||||
354
README.CodingStyle
Normal file
354
README.CodingStyle
Normal file
@@ -0,0 +1,354 @@
|
|||||||
|
Coding conventions in the libssh tree
|
||||||
|
======================================
|
||||||
|
|
||||||
|
===========
|
||||||
|
Quick Start
|
||||||
|
===========
|
||||||
|
|
||||||
|
Coding style guidelines are about reducing the number of unnecessary
|
||||||
|
reformatting patches and making things easier for developers to work together.
|
||||||
|
|
||||||
|
You don't have to like them or even agree with them, but once put in place we
|
||||||
|
all have to abide by them (or vote to change them). However, coding style
|
||||||
|
should never outweigh coding itself and so the guidelines described here are
|
||||||
|
hopefully easy enough to follow as they are very common and supported by tools
|
||||||
|
and editors.
|
||||||
|
|
||||||
|
The basic style for C code, is the Linux kernel coding style (See
|
||||||
|
Documentation/CodingStyle in the kernel source tree). This closely matches what
|
||||||
|
libssh developers use already anyways, with a few exceptions as mentioned
|
||||||
|
below.
|
||||||
|
|
||||||
|
But to save you the trouble of reading the Linux kernel style guide, here
|
||||||
|
are the highlights.
|
||||||
|
|
||||||
|
* Maximum Line Width is 80 Characters
|
||||||
|
The reason is not about people with low-res screens but rather sticking
|
||||||
|
to 80 columns prevents you from easily nesting more than one level of
|
||||||
|
if statements or other code blocks.
|
||||||
|
|
||||||
|
* Use 4 Spaces to Indent
|
||||||
|
|
||||||
|
* No Trailing Whitespace
|
||||||
|
Clean up your files before committing.
|
||||||
|
|
||||||
|
* Follow the K&R guidelines. We won't go through all of them here. Do you
|
||||||
|
have a copy of "The C Programming Language" anyways right?
|
||||||
|
|
||||||
|
|
||||||
|
=============
|
||||||
|
Editor Hints
|
||||||
|
=============
|
||||||
|
|
||||||
|
Emacs
|
||||||
|
------
|
||||||
|
Add the follow to your $HOME/.emacs file:
|
||||||
|
|
||||||
|
(add-hook 'c-mode-hook
|
||||||
|
(lambda ()
|
||||||
|
(c-set-style "linux")
|
||||||
|
(c-toggle-auto-state)))
|
||||||
|
|
||||||
|
|
||||||
|
Vim
|
||||||
|
----
|
||||||
|
|
||||||
|
For the basic vi editor included with all variants of \*nix, add the
|
||||||
|
following to $HOME/.vimrc:
|
||||||
|
|
||||||
|
set ts=4 sw=4 et cindent
|
||||||
|
|
||||||
|
You can use the Vim gitmodline plugin to store this in the git config:
|
||||||
|
|
||||||
|
http://git.cryptomilk.org/projects/vim-gitmodeline.git/
|
||||||
|
|
||||||
|
For Vim, the following settings in $HOME/.vimrc will also deal with
|
||||||
|
displaying trailing whitespace:
|
||||||
|
|
||||||
|
if has("syntax") && (&t_Co > 2 || has("gui_running"))
|
||||||
|
syntax on
|
||||||
|
function! ActivateInvisibleCharIndicator()
|
||||||
|
syntax match TrailingSpace "[ \t]\+$" display containedin=ALL
|
||||||
|
highlight TrailingSpace ctermbg=Red
|
||||||
|
endf
|
||||||
|
autocmd BufNewFile,BufRead * call ActivateInvisibleCharIndicator()
|
||||||
|
endif
|
||||||
|
" Show tabs, trailing whitespace, and continued lines visually
|
||||||
|
set list listchars=tab:»·,trail:·,extends:…
|
||||||
|
|
||||||
|
" highlight overly long lines same as TODOs.
|
||||||
|
set textwidth=80
|
||||||
|
autocmd BufNewFile,BufRead *.c,*.h exec 'match Todo /\%>' . &textwidth . 'v.\+/'
|
||||||
|
|
||||||
|
|
||||||
|
==========================
|
||||||
|
FAQ & Statement Reference
|
||||||
|
==========================
|
||||||
|
|
||||||
|
Comments
|
||||||
|
---------
|
||||||
|
|
||||||
|
Comments should always use the standard C syntax. C++ style comments are not
|
||||||
|
currently allowed.
|
||||||
|
|
||||||
|
The lines before a comment should be empty. If the comment directly belongs to
|
||||||
|
the following code, there should be no empty line after the comment, except if
|
||||||
|
the comment contains a summary of multiple following code blocks.
|
||||||
|
|
||||||
|
This is good:
|
||||||
|
|
||||||
|
...
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a multi line comment,
|
||||||
|
* which explains the logical steps we have to do:
|
||||||
|
*
|
||||||
|
* 1. We need to set i=5, because...
|
||||||
|
* 2. We need to call complex_fn1
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This is a one line comment about i = 5. */
|
||||||
|
i = 5;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a multi line comment,
|
||||||
|
* explaining the call to complex_fn1()
|
||||||
|
*/
|
||||||
|
ret = complex_fn1();
|
||||||
|
if (ret != 0) {
|
||||||
|
...
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This is a doxygen comment.
|
||||||
|
*
|
||||||
|
* This is a more detailed explanation of
|
||||||
|
* this simple function.
|
||||||
|
*
|
||||||
|
* @param[in] param1 The parameter value of the function.
|
||||||
|
*
|
||||||
|
* @param[out] result1 The result value of the function.
|
||||||
|
*
|
||||||
|
* @return 0 on success and -1 on error.
|
||||||
|
*/
|
||||||
|
int example(int param1, int *result1);
|
||||||
|
|
||||||
|
This is bad:
|
||||||
|
|
||||||
|
...
|
||||||
|
int i;
|
||||||
|
/*
|
||||||
|
* This is a multi line comment,
|
||||||
|
* which explains the logical steps we have to do:
|
||||||
|
*
|
||||||
|
* 1. We need to set i=5, because...
|
||||||
|
* 2. We need to call complex_fn1
|
||||||
|
*/
|
||||||
|
/* This is a one line comment about i = 5. */
|
||||||
|
i = 5;
|
||||||
|
/*
|
||||||
|
* This is a multi line comment,
|
||||||
|
* explaining the call to complex_fn1()
|
||||||
|
*/
|
||||||
|
ret = complex_fn1();
|
||||||
|
if (ret != 0) {
|
||||||
|
...
|
||||||
|
|
||||||
|
/*This is a one line comment.*/
|
||||||
|
|
||||||
|
/* This is a multi line comment,
|
||||||
|
with some more words...*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a multi line comment,
|
||||||
|
* with some more words...*/
|
||||||
|
|
||||||
|
Indention & Whitespace & 80 columns
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
To avoid confusion, indentations have to be 4 spaces. Do not use tabs!. When
|
||||||
|
wrapping parameters for function calls, align the parameter list with the first
|
||||||
|
parameter on the previous line. For example,
|
||||||
|
|
||||||
|
var1 = foo(arg1,
|
||||||
|
arg2,
|
||||||
|
arg3);
|
||||||
|
|
||||||
|
The previous example is intended to illustrate alignment of function
|
||||||
|
parameters across lines and not as encourage for gratuitous line
|
||||||
|
splitting. Never split a line before columns 70 - 79 unless you
|
||||||
|
have a really good reason. Be smart about formatting.
|
||||||
|
|
||||||
|
|
||||||
|
If, switch, & Code blocks
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
Always follow an 'if' keyword with a space but don't include additional
|
||||||
|
spaces following or preceding the parentheses in the conditional.
|
||||||
|
This is good:
|
||||||
|
|
||||||
|
if (x == 1)
|
||||||
|
|
||||||
|
This is bad:
|
||||||
|
|
||||||
|
if ( x == 1 )
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
if (x==1)
|
||||||
|
|
||||||
|
Yes we have a lot of code that uses the second and third form and we are trying
|
||||||
|
to clean it up without being overly intrusive.
|
||||||
|
|
||||||
|
Note that this is a rule about parentheses following keywords and not
|
||||||
|
functions. Don't insert a space between the name and left parentheses when
|
||||||
|
invoking functions.
|
||||||
|
|
||||||
|
Braces for code blocks used by for, if, switch, while, do..while, etc. should
|
||||||
|
begin on the same line as the statement keyword and end on a line of their own.
|
||||||
|
You should always include braces, even if the block only contains one
|
||||||
|
statement. NOTE: Functions are different and the beginning left brace should
|
||||||
|
be located in the first column on the next line.
|
||||||
|
|
||||||
|
If the beginning statement has to be broken across lines due to length, the
|
||||||
|
beginning brace should be on a line of its own.
|
||||||
|
|
||||||
|
The exception to the ending rule is when the closing brace is followed by
|
||||||
|
another language keyword such as else or the closing while in a do..while loop.
|
||||||
|
|
||||||
|
Good examples:
|
||||||
|
|
||||||
|
if (x == 1) {
|
||||||
|
printf("good\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (x = 1; x < 10; x++) {
|
||||||
|
print("%d\n", x);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (really_really_really_really_long_var_name = 0;
|
||||||
|
really_really_really_really_long_var_name < 10;
|
||||||
|
really_really_really_really_long_var_name++)
|
||||||
|
{
|
||||||
|
print("%d\n", really_really_really_really_long_var_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
printf("also good\n");
|
||||||
|
} while (1);
|
||||||
|
|
||||||
|
Bad examples:
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
print("I'm in a loop!\n"); }
|
||||||
|
|
||||||
|
for (x=1;
|
||||||
|
x<10;
|
||||||
|
x++)
|
||||||
|
{
|
||||||
|
print("no good\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < 10)
|
||||||
|
print("I should be in braces.\n");
|
||||||
|
|
||||||
|
|
||||||
|
Goto
|
||||||
|
-----
|
||||||
|
|
||||||
|
While many people have been academically taught that "goto"s are fundamentally
|
||||||
|
evil, they can greatly enhance readability and reduce memory leaks when used as
|
||||||
|
the single exit point from a function. But in no libssh world what so ever is a
|
||||||
|
goto outside of a function or block of code a good idea.
|
||||||
|
|
||||||
|
Good Examples:
|
||||||
|
|
||||||
|
int function foo(int y)
|
||||||
|
{
|
||||||
|
int *z = NULL;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (y < 10) {
|
||||||
|
z = malloc(sizeof(int)*y);
|
||||||
|
if (z == NULL) {
|
||||||
|
rc = 1;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Allocated %d elements.\n", y);
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (z != NULL) {
|
||||||
|
free(z);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Typedefs
|
||||||
|
---------
|
||||||
|
|
||||||
|
libssh tries to avoid "typedef struct { .. } x_t;" so we do always try to use
|
||||||
|
"struct x { .. };". We know there are still such typedefs in the code, but for
|
||||||
|
new code, please don't do that anymore.
|
||||||
|
|
||||||
|
Make use of helper variables
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
Please try to avoid passing function calls as function parameters in new code.
|
||||||
|
This makes the code much easier to read and it's also easier to use the "step"
|
||||||
|
command within gdb.
|
||||||
|
|
||||||
|
Good Example:
|
||||||
|
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
name = get_some_name();
|
||||||
|
if (name == NULL) {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = some_function_my_name(name);
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
Bad Example:
|
||||||
|
|
||||||
|
rc = some_function_my_name(get_some_name());
|
||||||
|
...
|
||||||
|
|
||||||
|
Please try to avoid passing function return values to if- or while-conditions.
|
||||||
|
The reason for this is better handling of code under a debugger.
|
||||||
|
|
||||||
|
Good example:
|
||||||
|
|
||||||
|
x = malloc(sizeof(short) * 10);
|
||||||
|
if (x == NULL) {
|
||||||
|
fprintf(stderr, "Unable to alloc memory!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
Bad example:
|
||||||
|
|
||||||
|
if ((x = malloc(sizeof(short)*10)) == NULL ) {
|
||||||
|
fprintf(stderr, "Unable to alloc memory!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
There are exceptions to this rule. One example is walking a data structure in
|
||||||
|
an iterator style:
|
||||||
|
|
||||||
|
while ((opt = poptGetNextOpt(pc)) != -1) {
|
||||||
|
... do something with opt ...
|
||||||
|
}
|
||||||
|
|
||||||
|
But in general, please try to avoid this pattern.
|
||||||
|
|
||||||
|
|
||||||
|
Control-Flow changing macros
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
Macros like STATUS_NOT_OK_RETURN that change control flow (return/goto/etc)
|
||||||
|
from within the macro are considered bad, because they look like function calls
|
||||||
|
that never change control flow. Please do not introduce them.
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
# - ADD_CHECK_TEST(test_name test_source linklib1 ... linklibN)
|
# - ADD_CHECK_TEST(test_name test_source linklib1 ... linklibN)
|
||||||
|
|
||||||
# Copyright (c) 2007 Daniel Gollub <dgollub@suse.de>
|
# Copyright (c) 2007 Daniel Gollub <dgollub@suse.de>
|
||||||
# Copyright (c) 2007-2010 Andreas Schneider <asn@cynapses.org>
|
# Copyright (c) 2007-2010 Andreas Schneider <asn@cryptomilk.org>
|
||||||
#
|
#
|
||||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||||
@@ -10,10 +10,17 @@ enable_testing()
|
|||||||
include(CTest)
|
include(CTest)
|
||||||
|
|
||||||
if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
|
if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
|
||||||
|
# Profiling
|
||||||
set(CMAKE_C_FLAGS_PROFILING "-g -O0 -Wall -W -Wshadow -Wunused-variable -Wunused-parameter -Wunused-function -Wunused -Wno-system-headers -Wwrite-strings -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Compiler Flags")
|
set(CMAKE_C_FLAGS_PROFILING "-g -O0 -Wall -W -Wshadow -Wunused-variable -Wunused-parameter -Wunused-function -Wunused -Wno-system-headers -Wwrite-strings -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Compiler Flags")
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
|
set(CMAKE_SHARED_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
|
||||||
set(CMAKE_MODULE_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
|
set(CMAKE_MODULE_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
|
||||||
set(CMAKE_EXEC_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
|
set(CMAKE_EXEC_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
|
||||||
|
|
||||||
|
# Address Sanitizer
|
||||||
|
set(CMAKE_C_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer" CACHE STRING "Address sanitizer compiler flags")
|
||||||
|
set(CMAKE_SHARED_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address" CACHE STRING "Address sanitizer shared linker flags")
|
||||||
|
set(CMAKE_MODULE_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address" CACHE STRING "Address sanitizer module linker flags")
|
||||||
|
set(CMAKE_EXEC_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address" CACHE STRING "Address sanitizer executable linker flags")
|
||||||
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
|
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
|
||||||
|
|
||||||
function (ADD_CMOCKA_TEST _testName _testSource)
|
function (ADD_CMOCKA_TEST _testName _testSource)
|
||||||
|
|||||||
@@ -25,3 +25,6 @@ if (NOT CMAKE_BUILD_TYPE)
|
|||||||
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
|
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
|
||||||
)
|
)
|
||||||
endif (NOT CMAKE_BUILD_TYPE)
|
endif (NOT CMAKE_BUILD_TYPE)
|
||||||
|
|
||||||
|
# Create the compile command database for clang by default
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|||||||
@@ -75,3 +75,10 @@ if (MSVC)
|
|||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1")
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1")
|
||||||
endif (MSVC)
|
endif (MSVC)
|
||||||
|
|
||||||
|
# This removes this annoying warning
|
||||||
|
# "warning: 'BN_CTX_free' is deprecated: first deprecated in OS X 10.7 [-Wdeprecated-declarations]"
|
||||||
|
if (OSX)
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations")
|
||||||
|
endif (OSX)
|
||||||
|
|
||||||
|
|||||||
@@ -26,3 +26,7 @@ endif (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
|
|||||||
if (CMAKE_SYSTEM_NAME MATCHES "OS2")
|
if (CMAKE_SYSTEM_NAME MATCHES "OS2")
|
||||||
set(OS2 TRUE)
|
set(OS2 TRUE)
|
||||||
endif (CMAKE_SYSTEM_NAME MATCHES "OS2")
|
endif (CMAKE_SYSTEM_NAME MATCHES "OS2")
|
||||||
|
|
||||||
|
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||||
|
set (OSX TRUE)
|
||||||
|
endif (CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
# ARGP_LIBRARIES - Link these to use Argp
|
# ARGP_LIBRARIES - Link these to use Argp
|
||||||
# ARGP_DEFINITIONS - Compiler switches required for using Argp
|
# ARGP_DEFINITIONS - Compiler switches required for using Argp
|
||||||
#
|
#
|
||||||
# Copyright (c) 2010 Andreas Schneider <asn@cynapses.org>
|
# Copyright (c) 2010 Andreas Schneider <asn@cryptomilk.org>
|
||||||
#
|
#
|
||||||
# Redistribution and use is allowed according to the terms of the New
|
# Redistribution and use is allowed according to the terms of the New
|
||||||
# BSD license.
|
# BSD license.
|
||||||
|
|||||||
61
cmake/Modules/FindNaCl.cmake
Normal file
61
cmake/Modules/FindNaCl.cmake
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
# - Try to find NaCl
|
||||||
|
# Once done this will define
|
||||||
|
#
|
||||||
|
# NACL_FOUND - system has NaCl
|
||||||
|
# NACL_INCLUDE_DIRS - the NaCl include directory
|
||||||
|
# NACL_LIBRARIES - Link these to use NaCl
|
||||||
|
# NACL_DEFINITIONS - Compiler switches required for using NaCl
|
||||||
|
#
|
||||||
|
# Copyright (c) 2010 Andreas Schneider <asn@cryptomilk.org>
|
||||||
|
# Copyright (c) 2013 Aris Adamantiadis <aris@badcode.be>
|
||||||
|
#
|
||||||
|
# Redistribution and use is allowed according to the terms of the New
|
||||||
|
# BSD license.
|
||||||
|
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
if (NACL_LIBRARIES AND NACL_INCLUDE_DIRS)
|
||||||
|
# in cache already
|
||||||
|
set(NACL_FOUND TRUE)
|
||||||
|
else (NACL_LIBRARIES AND NACL_INCLUDE_DIRS)
|
||||||
|
|
||||||
|
find_path(NACL_INCLUDE_DIR
|
||||||
|
NAMES
|
||||||
|
nacl/crypto_box_curve25519xsalsa20poly1305.h
|
||||||
|
PATHS
|
||||||
|
/usr/include
|
||||||
|
/usr/local/include
|
||||||
|
/opt/local/include
|
||||||
|
/sw/include
|
||||||
|
)
|
||||||
|
|
||||||
|
find_library(NACL_LIBRARY
|
||||||
|
NAMES
|
||||||
|
nacl
|
||||||
|
PATHS
|
||||||
|
/usr/lib
|
||||||
|
/usr/local/lib
|
||||||
|
/opt/local/lib
|
||||||
|
/sw/lib
|
||||||
|
)
|
||||||
|
|
||||||
|
set(NACL_INCLUDE_DIRS
|
||||||
|
${NACL_INCLUDE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (NACL_LIBRARY)
|
||||||
|
set(NACL_LIBRARIES
|
||||||
|
${NACL_LIBRARIES}
|
||||||
|
${NACL_LIBRARY}
|
||||||
|
)
|
||||||
|
endif (NACL_LIBRARY)
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(NaCl DEFAULT_MSG NACL_LIBRARIES NACL_INCLUDE_DIRS)
|
||||||
|
|
||||||
|
# show the NACL_INCLUDE_DIRS and NACL_LIBRARIES variables only in the advanced view
|
||||||
|
mark_as_advanced(NACL_INCLUDE_DIRS NACL_LIBRARIES)
|
||||||
|
|
||||||
|
endif (NACL_LIBRARIES AND NACL_INCLUDE_DIRS)
|
||||||
|
|
||||||
@@ -1,208 +0,0 @@
|
|||||||
# - Try to find OpenSSL
|
|
||||||
# Once done this will define
|
|
||||||
#
|
|
||||||
# OPENSSL_ROOT_DIR - Set this variable to the root installation of OpenSSL
|
|
||||||
#
|
|
||||||
# Read-Only variables:
|
|
||||||
# OPENSSL_FOUND - system has OpenSSL
|
|
||||||
# OPENSSL_INCLUDE_DIRS - the OpenSSL include directory
|
|
||||||
# OPENSSL_LIBRARIES - Link these to use OpenSSL
|
|
||||||
# OPENSSL_DEFINITIONS - Compiler switches required for using OpenSSL
|
|
||||||
#
|
|
||||||
#=============================================================================
|
|
||||||
# Copyright (c) 2006-2009 Kitware, Inc.
|
|
||||||
# Copyright (c) 2006 Alexander Neundorf <neundorf@kde.org>
|
|
||||||
# Copyright (c) 2009-2010 Mathieu Malaterre <mathieu.malaterre@gmail.com>
|
|
||||||
# Copyright (c) 2011 Andreas Schneider <asn@cryptomilk.org>
|
|
||||||
#
|
|
||||||
# Distributed under the OSI-approved BSD License (the "License");
|
|
||||||
# see accompanying file Copyright.txt for details.
|
|
||||||
#
|
|
||||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
||||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
# See the License for more information.
|
|
||||||
#=============================================================================
|
|
||||||
#
|
|
||||||
|
|
||||||
if (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
|
|
||||||
# in cache already
|
|
||||||
set(OPENSSL_FOUND TRUE)
|
|
||||||
else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
|
|
||||||
|
|
||||||
if (UNIX)
|
|
||||||
find_package(PkgConfig)
|
|
||||||
if (PKG_CONFIG_FOUND)
|
|
||||||
pkg_check_modules(_OPENSSL openssl)
|
|
||||||
endif (PKG_CONFIG_FOUND)
|
|
||||||
endif (UNIX)
|
|
||||||
|
|
||||||
# http://www.slproweb.com/products/Win32OpenSSL.html
|
|
||||||
set(_OPENSSL_ROOT_HINTS
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
|
|
||||||
)
|
|
||||||
|
|
||||||
set(_OPENSSL_ROOT_PATHS
|
|
||||||
"C:/OpenSSL/"
|
|
||||||
"C:/OpenSSL-Win32/"
|
|
||||||
"C:/OpenSSL-Win64/"
|
|
||||||
"$ENV{PROGRAMFILES}/OpenSSL"
|
|
||||||
"$ENV{PROGRAMFILES}/OpenSSL-Win32"
|
|
||||||
"$ENV{PROGRAMFILES}/OpenSSL-Win64"
|
|
||||||
)
|
|
||||||
|
|
||||||
find_path(OPENSSL_ROOT_DIR
|
|
||||||
NAMES
|
|
||||||
include/openssl/ssl.h
|
|
||||||
HINTS
|
|
||||||
${_OPENSSL_ROOT_HINTS}
|
|
||||||
PATHS
|
|
||||||
${_OPENSSL_ROOT_PATHS}
|
|
||||||
)
|
|
||||||
mark_as_advanced(OPENSSL_ROOT_DIR)
|
|
||||||
|
|
||||||
find_path(OPENSSL_INCLUDE_DIR
|
|
||||||
NAMES
|
|
||||||
openssl/ssl.h
|
|
||||||
PATHS
|
|
||||||
/usr/local/include
|
|
||||||
/opt/local/include
|
|
||||||
/sw/include
|
|
||||||
/usr/lib/sfw/include
|
|
||||||
${OPENSSL_ROOT_DIR}/include
|
|
||||||
)
|
|
||||||
|
|
||||||
set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR})
|
|
||||||
mark_as_advanced(OPENSSL_INCLUDE_DIRS)
|
|
||||||
|
|
||||||
if (WIN32 AND NOT CYGWIN)
|
|
||||||
# MINGW should go here too
|
|
||||||
if (MSVC)
|
|
||||||
# /MD and /MDd are the standard values - if someone wants to use
|
|
||||||
# others, the libnames have to change here too
|
|
||||||
# use also ssl and ssleay32 in debug as fallback for openssl < 0.9.8b
|
|
||||||
# TODO: handle /MT and static lib
|
|
||||||
# In Visual C++ naming convention each of these four kinds of Windows libraries has it's standard suffix:
|
|
||||||
# * MD for dynamic-release
|
|
||||||
# * MDd for dynamic-debug
|
|
||||||
# * MT for static-release
|
|
||||||
# * MTd for static-debug
|
|
||||||
|
|
||||||
# Implementation details:
|
|
||||||
# We are using the libraries located in the VC subdir instead of the parent directory eventhough :
|
|
||||||
# libeay32MD.lib is identical to ../libeay32.lib, and
|
|
||||||
# ssleay32MD.lib is identical to ../ssleay32.lib
|
|
||||||
find_library(LIB_EAY_DEBUG
|
|
||||||
NAMES
|
|
||||||
libeay32MDd
|
|
||||||
libeay32
|
|
||||||
PATHS
|
|
||||||
${OPENSSL_ROOT_DIR}/lib/VC
|
|
||||||
)
|
|
||||||
|
|
||||||
find_library(LIB_EAY_RELEASE
|
|
||||||
NAMES
|
|
||||||
libeay32MD
|
|
||||||
libeay32
|
|
||||||
PATHS
|
|
||||||
${OPENSSL_ROOT_DIR}/lib/VC
|
|
||||||
)
|
|
||||||
|
|
||||||
find_library(SSL_EAY_DEBUG
|
|
||||||
NAMES
|
|
||||||
ssleay32MDd
|
|
||||||
ssleay32
|
|
||||||
ssl
|
|
||||||
PATHS ${OPENSSL_ROOT_DIR}/lib/VC
|
|
||||||
)
|
|
||||||
|
|
||||||
find_library(SSL_EAY_RELEASE
|
|
||||||
NAMES
|
|
||||||
ssleay32MD
|
|
||||||
ssleay32
|
|
||||||
ssl
|
|
||||||
PATHS
|
|
||||||
${OPENSSL_ROOT_DIR}/lib/VC
|
|
||||||
)
|
|
||||||
|
|
||||||
if (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)
|
|
||||||
set(OPENSSL_LIBRARIES
|
|
||||||
optimized ${SSL_EAY_RELEASE} debug ${SSL_EAY_DEBUG}
|
|
||||||
optimized ${LIB_EAY_RELEASE} debug ${LIB_EAY_DEBUG}
|
|
||||||
)
|
|
||||||
else (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)
|
|
||||||
set( OPENSSL_LIBRARIES ${SSL_EAY_RELEASE} ${LIB_EAY_RELEASE} )
|
|
||||||
endif (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)
|
|
||||||
|
|
||||||
mark_as_advanced(SSL_EAY_DEBUG SSL_EAY_RELEASE)
|
|
||||||
mark_as_advanced(LIB_EAY_DEBUG LIB_EAY_RELEASE)
|
|
||||||
elseif (MINGW)
|
|
||||||
# same player, for MingW
|
|
||||||
find_library(LIB_EAY
|
|
||||||
NAMES
|
|
||||||
libeay32
|
|
||||||
PATHS
|
|
||||||
${OPENSSL_ROOT_DIR}/lib/MinGW
|
|
||||||
)
|
|
||||||
|
|
||||||
find_library(SSL_EAY
|
|
||||||
NAMES
|
|
||||||
ssleay32
|
|
||||||
PATHS
|
|
||||||
${OPENSSL_ROOT_DIR}/lib/MinGW
|
|
||||||
)
|
|
||||||
|
|
||||||
mark_as_advanced(SSL_EAY LIB_EAY)
|
|
||||||
set(OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY})
|
|
||||||
else(MSVC)
|
|
||||||
# Not sure what to pick for -say- intel, let's use the toplevel ones and hope someone report issues:
|
|
||||||
find_library(LIB_EAY
|
|
||||||
NAMES
|
|
||||||
libeay32
|
|
||||||
PATHS
|
|
||||||
${OPENSSL_ROOT_DIR}/lib
|
|
||||||
)
|
|
||||||
|
|
||||||
find_library(SSL_EAY
|
|
||||||
NAMES
|
|
||||||
ssleay32
|
|
||||||
PATHS
|
|
||||||
${OPENSSL_ROOT_DIR}/lib
|
|
||||||
)
|
|
||||||
|
|
||||||
mark_as_advanced(SSL_EAY LIB_EAY)
|
|
||||||
set(OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY})
|
|
||||||
endif(MSVC)
|
|
||||||
else (WIN32 AND NOT CYGWIN)
|
|
||||||
find_library(OPENSSL_SSL_LIBRARIES
|
|
||||||
NAMES
|
|
||||||
ssl
|
|
||||||
ssleay32
|
|
||||||
ssleay32MD
|
|
||||||
PATHS
|
|
||||||
${_OPENSSL_LIBDIR}
|
|
||||||
/opt/local/lib
|
|
||||||
/sw/lib
|
|
||||||
/usr/sfw/lib/64
|
|
||||||
/usr/sfw/lib
|
|
||||||
)
|
|
||||||
|
|
||||||
find_library(OPENSSL_CRYPTO_LIBRARIES
|
|
||||||
NAMES
|
|
||||||
crypto
|
|
||||||
PATHS
|
|
||||||
${_OPENSSL_LIBDIR}
|
|
||||||
/opt/local/lib
|
|
||||||
/sw/lib
|
|
||||||
/usr/sfw/lib/64
|
|
||||||
/usr/sfw/lib
|
|
||||||
)
|
|
||||||
|
|
||||||
mark_as_advanced(OPENSSL_CRYPTO_LIBRARIES OPENSSL_SSL_LIBRARIES)
|
|
||||||
set(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARIES})
|
|
||||||
endif (WIN32 AND NOT CYGWIN)
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
find_package_handle_standard_args(OpenSSL DEFAULT_MSG OPENSSL_LIBRARIES OPENSSL_INCLUDE_DIRS)
|
|
||||||
|
|
||||||
endif (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
# - Try to find ZLIB
|
|
||||||
# Once done this will define
|
|
||||||
#
|
|
||||||
# ZLIB_ROOT_DIR - Set this variable to the root installation of ZLIB
|
|
||||||
#
|
|
||||||
# Read-Only variables:
|
|
||||||
# ZLIB_FOUND - system has ZLIB
|
|
||||||
# ZLIB_INCLUDE_DIRS - the ZLIB include directory
|
|
||||||
# ZLIB_LIBRARIES - Link these to use ZLIB
|
|
||||||
#
|
|
||||||
# ZLIB_VERSION_STRING - The version of zlib found (x.y.z)
|
|
||||||
# ZLIB_VERSION_MAJOR - The major version of zlib
|
|
||||||
# ZLIB_VERSION_MINOR - The minor version of zlib
|
|
||||||
# ZLIB_VERSION_PATCH - The patch version of zlib
|
|
||||||
# ZLIB_VERSION_TWEAK - The tweak version of zlib
|
|
||||||
#
|
|
||||||
# The following variable are provided for backward compatibility
|
|
||||||
#
|
|
||||||
# ZLIB_MAJOR_VERSION - The major version of zlib
|
|
||||||
# ZLIB_MINOR_VERSION - The minor version of zlib
|
|
||||||
# ZLIB_PATCH_VERSION - The patch version of zlib
|
|
||||||
#
|
|
||||||
#=============================================================================
|
|
||||||
# Copyright (c) 2001-2009 Kitware, Inc.
|
|
||||||
# Copyright (c) 2011 Andreas Schneider <asn@cryptomilk.org>
|
|
||||||
#
|
|
||||||
# Distributed under the OSI-approved BSD License (the "License");
|
|
||||||
# see accompanying file Copyright.txt for details.
|
|
||||||
#
|
|
||||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
||||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
# See the License for more information.
|
|
||||||
#=============================================================================
|
|
||||||
#
|
|
||||||
|
|
||||||
if (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
|
|
||||||
# in cache already
|
|
||||||
set(ZLIB_FOUND TRUE)
|
|
||||||
else (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
|
|
||||||
|
|
||||||
set(_ZLIB_ROOT_HINTS
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\Zlib;InstallPath]/include"
|
|
||||||
)
|
|
||||||
|
|
||||||
set(_ZLIB_ROOT_PATHS
|
|
||||||
"$ENV{PROGRAMFILES}/zlib"
|
|
||||||
)
|
|
||||||
|
|
||||||
find_path(ZLIB_ROOT_DIR
|
|
||||||
NAMES
|
|
||||||
include/zlib.h
|
|
||||||
HINTS
|
|
||||||
${_ZLIB_ROOT_HINTS}
|
|
||||||
PATHS
|
|
||||||
${_ZLIB_ROOT_PATHS}
|
|
||||||
)
|
|
||||||
mark_as_advanced(ZLIB_ROOT_DIR)
|
|
||||||
|
|
||||||
# check for header file
|
|
||||||
find_path(ZLIB_INCLUDE_DIR
|
|
||||||
NAMES
|
|
||||||
zlib.h
|
|
||||||
PATHS
|
|
||||||
/usr/local/include
|
|
||||||
/opt/local/include
|
|
||||||
/sw/include
|
|
||||||
/usr/lib/sfw/include
|
|
||||||
${ZLIB_ROOT_DIR}/include
|
|
||||||
)
|
|
||||||
mark_as_advanced(ZLIB_INCLUDE_DIR)
|
|
||||||
|
|
||||||
# check version number
|
|
||||||
if (ZLIB_INCLUDE_DIR AND EXISTS "${ZLIB_INCLUDE_DIR}/zlib.h")
|
|
||||||
file(STRINGS "${ZLIB_INCLUDE_DIR}/zlib.h" ZLIB_H REGEX "^#define ZLIB_VERSION \"[^\"]*\"$")
|
|
||||||
|
|
||||||
string(REGEX REPLACE "^.*ZLIB_VERSION \"([0-9]+).*$" "\\1" ZLIB_VERSION_MAJOR "${ZLIB_H}")
|
|
||||||
string(REGEX REPLACE "^.*ZLIB_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" ZLIB_VERSION_MINOR "${ZLIB_H}")
|
|
||||||
string(REGEX REPLACE "^.*ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" ZLIB_VERSION_PATCH "${ZLIB_H}")
|
|
||||||
|
|
||||||
set(ZLIB_VERSION_STRING "${ZLIB_VERSION_MAJOR}.${ZLIB_VERSION_MINOR}.${ZLIB_VERSION_PATCH}")
|
|
||||||
|
|
||||||
# only append a TWEAK version if it exists:
|
|
||||||
set(ZLIB_VERSION_TWEAK "")
|
|
||||||
if ("${ZLIB_H}" MATCHES "^.*ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]+\\.([0-9]+).*$")
|
|
||||||
set(ZLIB_VERSION_TWEAK "${CMAKE_MATCH_1}")
|
|
||||||
set(ZLIB_VERSION_STRING "${ZLIB_VERSION_STRING}.${ZLIB_VERSION_TWEAK}")
|
|
||||||
endif ("${ZLIB_H}" MATCHES "^.*ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]+\\.([0-9]+).*$")
|
|
||||||
|
|
||||||
set(ZLIB_MAJOR_VERSION "${ZLIB_VERSION_MAJOR}")
|
|
||||||
set(ZLIB_MINOR_VERSION "${ZLIB_VERSION_MINOR}")
|
|
||||||
set(ZLIB_PATCH_VERSION "${ZLIB_VERSION_PATCH}")
|
|
||||||
endif (ZLIB_INCLUDE_DIR AND EXISTS "${ZLIB_INCLUDE_DIR}/zlib.h")
|
|
||||||
|
|
||||||
find_library(ZLIB_LIBRARY
|
|
||||||
NAMES
|
|
||||||
z
|
|
||||||
zdll
|
|
||||||
zlib
|
|
||||||
zlib1
|
|
||||||
zlibd
|
|
||||||
PATHS
|
|
||||||
/usr/local/lib
|
|
||||||
/opt/local/lib
|
|
||||||
/sw/lib
|
|
||||||
/usr/sfw/lib/64
|
|
||||||
/usr/sfw/lib
|
|
||||||
${ZLIB_ROOT_DIR}/lib
|
|
||||||
)
|
|
||||||
mark_as_advanced(ZLIB_LIBRARY)
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
find_package_handle_standard_args(ZLIB DEFAULT_MSG ZLIB_INCLUDE_DIR ZLIB_LIBRARY)
|
|
||||||
#find_package_handle_standard_args(ZLIB REQUIRED_VARS ZLIB_INCLUDE_DIR ZLIB_LIBRARY
|
|
||||||
# VERSION_VAR ZLIB_VERSION_STRING)
|
|
||||||
|
|
||||||
if (ZLIB_FOUND)
|
|
||||||
set(ZLIB_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR})
|
|
||||||
set(ZLIB_LIBRARIES ${ZLIB_LIBRARY})
|
|
||||||
endif (ZLIB_FOUND)
|
|
||||||
endif (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
# - MACRO_ADD_COMPILE_FLAGS(target_name flag1 ... flagN)
|
|
||||||
|
|
||||||
# Copyright (c) 2006, Oswald Buddenhagen, <ossi@kde.org>
|
|
||||||
# Copyright (c) 2006, Andreas Schneider, <mail@cynapses.org>
|
|
||||||
#
|
|
||||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
|
||||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
|
||||||
|
|
||||||
|
|
||||||
macro (MACRO_ADD_COMPILE_FLAGS _target)
|
|
||||||
|
|
||||||
get_target_property(_flags ${_target} COMPILE_FLAGS)
|
|
||||||
if (_flags)
|
|
||||||
set(_flags ${_flags} ${ARGN})
|
|
||||||
else (_flags)
|
|
||||||
set(_flags ${ARGN})
|
|
||||||
endif (_flags)
|
|
||||||
|
|
||||||
set_target_properties(${_target} PROPERTIES COMPILE_FLAGS ${_flags})
|
|
||||||
|
|
||||||
endmacro (MACRO_ADD_COMPILE_FLAGS)
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
# - MACRO_ADD_LINK_FLAGS(target_name flag1 ... flagN)
|
|
||||||
|
|
||||||
# Copyright (c) 2006, Oswald Buddenhagen, <ossi@kde.org>
|
|
||||||
# Copyright (c) 2006, Andreas Schneider, <mail@cynapses.org>
|
|
||||||
#
|
|
||||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
|
||||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
|
||||||
|
|
||||||
macro (MACRO_ADD_LINK_FLAGS _target)
|
|
||||||
|
|
||||||
get_target_property(_flags ${_target} LINK_FLAGS)
|
|
||||||
if (_flags)
|
|
||||||
set(_flags "${_flags} ${ARGN}")
|
|
||||||
else (_flags)
|
|
||||||
set(_flags "${ARGN}")
|
|
||||||
endif (_flags)
|
|
||||||
|
|
||||||
set_target_properties(${_target} PROPERTIES LINK_FLAGS "${_flags}")
|
|
||||||
|
|
||||||
endmacro (MACRO_ADD_LINK_FLAGS)
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# - MACRO_ADD_PLUGIN(name [WITH_PREFIX] file1 .. fileN)
|
|
||||||
#
|
|
||||||
# Create a plugin from the given source files.
|
|
||||||
# If WITH_PREFIX is given, the resulting plugin will have the
|
|
||||||
# prefix "lib", otherwise it won't.
|
|
||||||
#
|
|
||||||
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
|
|
||||||
# Copyright (c) 2006, Laurent Montel, <montel@kde.org>
|
|
||||||
# Copyright (c) 2006, Andreas Schneider, <mail@cynapses.org>
|
|
||||||
#
|
|
||||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
|
||||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
|
||||||
|
|
||||||
|
|
||||||
macro (MACRO_ADD_PLUGIN _target_NAME _with_PREFIX)
|
|
||||||
|
|
||||||
if (${_with_PREFIX} STREQUAL "WITH_PREFIX")
|
|
||||||
set(_first_SRC)
|
|
||||||
else (${_with_PREFIX} STREQUAL "WITH_PREFIX")
|
|
||||||
set(_first_SRC ${_with_PREFIX})
|
|
||||||
endif (${_with_PREFIX} STREQUAL "WITH_PREFIX")
|
|
||||||
|
|
||||||
add_library(${_target_NAME} MODULE ${_first_SRC} ${ARGN})
|
|
||||||
|
|
||||||
if (_first_SRC)
|
|
||||||
set_target_properties(${_target_NAME} PROPERTIES PREFIX "")
|
|
||||||
endif (_first_SRC)
|
|
||||||
|
|
||||||
endmacro (MACRO_ADD_PLUGIN _name _sources)
|
|
||||||
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
# - macro_copy_file(_src _dst)
|
|
||||||
# Copies a file to ${_dst} only if ${_src} is different (newer) than ${_dst}
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
# macro_copy_file(${CMAKE_CURRENT_SOURCE_DIR}/icon.png ${CMAKE_CURRENT_BINARY_DIR}/.)
|
|
||||||
# Copies file icon.png to ${CMAKE_CURRENT_BINARY_DIR} directory
|
|
||||||
#
|
|
||||||
# Copyright (c) 2006-2007 Wengo
|
|
||||||
# Copyright (c) 2006-2008 Andreas Schneider <mail@cynapses.org>
|
|
||||||
#
|
|
||||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
|
||||||
# For details see the accompanying COPYING file.
|
|
||||||
|
|
||||||
|
|
||||||
macro (macro_copy_file _src _dst)
|
|
||||||
# Removes all path containing .svn or CVS or CMakeLists.txt during the copy
|
|
||||||
if (NOT ${_src} MATCHES ".*\\.svn|CVS|CMakeLists\\.txt.*")
|
|
||||||
|
|
||||||
if (CMAKE_VERBOSE_MAKEFILE)
|
|
||||||
message(STATUS "Copy file from ${_src} to ${_dst}")
|
|
||||||
endif (CMAKE_VERBOSE_MAKEFILE)
|
|
||||||
|
|
||||||
# Creates directory if necessary
|
|
||||||
get_filename_component(_path ${_dst} PATH)
|
|
||||||
file(MAKE_DIRECTORY ${_path})
|
|
||||||
|
|
||||||
execute_process(
|
|
||||||
COMMAND
|
|
||||||
${CMAKE_COMMAND} -E copy_if_different ${_src} ${_dst}
|
|
||||||
OUTPUT_QUIET
|
|
||||||
)
|
|
||||||
endif (NOT ${_src} MATCHES ".*\\.svn|CVS|CMakeLists\\.txt.*")
|
|
||||||
endmacro (macro_copy_file)
|
|
||||||
@@ -2,10 +2,18 @@
|
|||||||
#
|
#
|
||||||
# Adds a doxygen target that runs doxygen to generate the html
|
# Adds a doxygen target that runs doxygen to generate the html
|
||||||
# and optionally the LaTeX API documentation.
|
# and optionally the LaTeX API documentation.
|
||||||
# The doxygen target is added to the doc target as dependency.
|
# The doxygen target is added to the doc target as a dependency.
|
||||||
# i.e.: the API documentation is built with:
|
# i.e.: the API documentation is built with:
|
||||||
# make doc
|
# make doc
|
||||||
#
|
#
|
||||||
|
# USAGE: GLOBAL INSTALL
|
||||||
|
#
|
||||||
|
# Install it with:
|
||||||
|
# cmake ./ && sudo make install
|
||||||
|
# Add the following to the CMakeLists.txt of your project:
|
||||||
|
# include(UseDoxygen OPTIONAL)
|
||||||
|
# Optionally copy Doxyfile.in in the directory of CMakeLists.txt and edit it.
|
||||||
|
#
|
||||||
# USAGE: INCLUDE IN PROJECT
|
# USAGE: INCLUDE IN PROJECT
|
||||||
#
|
#
|
||||||
# set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
|
# set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
@@ -13,88 +21,120 @@
|
|||||||
# Add the Doxyfile.in and UseDoxygen.cmake files to the projects source directory.
|
# Add the Doxyfile.in and UseDoxygen.cmake files to the projects source directory.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
# CONFIGURATION
|
||||||
|
#
|
||||||
|
# To configure Doxygen you can edit Doxyfile.in and set some variables in cmake.
|
||||||
# Variables you may define are:
|
# Variables you may define are:
|
||||||
# DOXYFILE_OUTPUT_DIR - Path where the Doxygen output is stored. Defaults to "doc".
|
# DOXYFILE_SOURCE_DIR - Path where the Doxygen input files are.
|
||||||
#
|
# Defaults to the current source directory.
|
||||||
# DOXYFILE_LATEX_DIR - Directory where the Doxygen LaTeX output is stored. Defaults to "latex".
|
# DOXYFILE_EXTRA_SOURCES - Additional source diretories/files for Doxygen to scan.
|
||||||
#
|
# The Paths should be in double quotes and separated by space. e.g.:
|
||||||
# DOXYFILE_HTML_DIR - Directory where the Doxygen html output is stored. Defaults to "html".
|
# "${CMAKE_CURRENT_BINARY_DIR}/foo.c" "${CMAKE_CURRENT_BINARY_DIR}/bar/"
|
||||||
|
#
|
||||||
|
# DOXYFILE_OUTPUT_DIR - Path where the Doxygen output is stored.
|
||||||
|
# Defaults to "${CMAKE_CURRENT_BINARY_DIR}/doc".
|
||||||
|
#
|
||||||
|
# DOXYFILE_LATEX - ON/OFF; Set to "ON" if you want the LaTeX documentation
|
||||||
|
# to be built.
|
||||||
|
# DOXYFILE_LATEX_DIR - Directory relative to DOXYFILE_OUTPUT_DIR where
|
||||||
|
# the Doxygen LaTeX output is stored. Defaults to "latex".
|
||||||
|
#
|
||||||
|
# DOXYFILE_HTML_DIR - Directory relative to DOXYFILE_OUTPUT_DIR where
|
||||||
|
# the Doxygen html output is stored. Defaults to "html".
|
||||||
#
|
#
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2009-2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
|
# Copyright (c) 2009, 2010, 2011 Tobias Rautenkranz <tobias@rautenkranz.ch>
|
||||||
# Copyright (c) 2010 Andreas Schneider <mail@cynapses.org>
|
|
||||||
#
|
#
|
||||||
# Redistribution and use is allowed according to the terms of the New
|
# Redistribution and use is allowed according to the terms of the New
|
||||||
# BSD license.
|
# BSD license.
|
||||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||||
#
|
#
|
||||||
|
|
||||||
macro(usedoxygen_set_default name value)
|
macro(usedoxygen_set_default name value type docstring)
|
||||||
if(NOT DEFINED "${name}")
|
if(NOT DEFINED "${name}")
|
||||||
set("${name}" "${value}")
|
set("${name}" "${value}" CACHE "${type}" "${docstring}")
|
||||||
endif()
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
find_package(Doxygen)
|
find_package(Doxygen)
|
||||||
|
|
||||||
if(DOXYGEN_FOUND)
|
if(DOXYGEN_FOUND)
|
||||||
find_file(DOXYFILE_IN
|
find_file(DOXYFILE_IN "Doxyfile.in"
|
||||||
NAMES
|
PATHS "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_ROOT}/Modules/"
|
||||||
doxy.config.in
|
NO_DEFAULT_PATH
|
||||||
PATHS
|
DOC "Path to the doxygen configuration template file")
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
set(DOXYFILE "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile")
|
||||||
${CMAKE_ROOT}/Modules/
|
include(FindPackageHandleStandardArgs)
|
||||||
NO_DEFAULT_PATH)
|
find_package_handle_standard_args(DOXYFILE_IN DEFAULT_MSG "DOXYFILE_IN")
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
find_package_handle_standard_args(DOXYFILE_IN DEFAULT_MSG "DOXYFILE_IN")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(DOXYGEN_FOUND AND DOXYFILE_IN_FOUND)
|
if(DOXYGEN_FOUND AND DOXYFILE_IN_FOUND)
|
||||||
add_custom_target(doxygen ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.config)
|
usedoxygen_set_default(DOXYFILE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/doc"
|
||||||
|
PATH "Doxygen output directory")
|
||||||
|
usedoxygen_set_default(DOXYFILE_HTML_DIR "html"
|
||||||
|
STRING "Doxygen HTML output directory")
|
||||||
|
usedoxygen_set_default(DOXYFILE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
PATH "Input files source directory")
|
||||||
|
usedoxygen_set_default(DOXYFILE_EXTRA_SOURCE_DIRS ""
|
||||||
|
STRING "Additional source files/directories separated by space")
|
||||||
|
set(DOXYFILE_SOURCE_DIRS "\"${DOXYFILE_SOURCE_DIR}\" ${DOXYFILE_EXTRA_SOURCES}")
|
||||||
|
|
||||||
usedoxygen_set_default(DOXYFILE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
usedoxygen_set_default(DOXYFILE_LATEX YES BOOL "Generate LaTeX API documentation" OFF)
|
||||||
usedoxygen_set_default(DOXYFILE_HTML_DIR "html")
|
usedoxygen_set_default(DOXYFILE_LATEX_DIR "latex" STRING "LaTex output directory")
|
||||||
|
|
||||||
set_property(DIRECTORY APPEND PROPERTY
|
mark_as_advanced(DOXYFILE_OUTPUT_DIR DOXYFILE_HTML_DIR DOXYFILE_LATEX_DIR
|
||||||
ADDITIONAL_MAKE_CLEAN_FILES "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_HTML_DIR}")
|
DOXYFILE_SOURCE_DIR DOXYFILE_EXTRA_SOURCE_DIRS DOXYFILE_IN)
|
||||||
|
|
||||||
set(DOXYFILE_LATEX FALSE)
|
|
||||||
set(DOXYFILE_PDFLATEX FALSE)
|
|
||||||
set(DOXYFILE_DOT FALSE)
|
|
||||||
|
|
||||||
#find_package(LATEX)
|
set_property(DIRECTORY
|
||||||
#if(LATEX_COMPILER AND MAKEINDEX_COMPILER)
|
APPEND PROPERTY
|
||||||
# set(DOXYFILE_LATEX TRUE)
|
ADDITIONAL_MAKE_CLEAN_FILES
|
||||||
# usedoxygen_set_default(DOXYFILE_LATEX_DIR "latex")
|
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_HTML_DIR}")
|
||||||
#
|
|
||||||
# set_property(DIRECTORY APPEND PROPERTY
|
|
||||||
# ADDITIONAL_MAKE_CLEAN_FILES
|
|
||||||
# "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
|
|
||||||
#
|
|
||||||
# if(PDFLATEX_COMPILER)
|
|
||||||
# set(DOXYFILE_PDFLATEX TRUE)
|
|
||||||
# endif()
|
|
||||||
# if(DOXYGEN_DOT_EXECUTABLE)
|
|
||||||
# set(DOXYFILE_DOT TRUE)
|
|
||||||
# endif()
|
|
||||||
#
|
|
||||||
# add_custom_command(TARGET doxygen
|
|
||||||
# POST_BUILD
|
|
||||||
# COMMAND ${CMAKE_MAKE_PROGRAM}
|
|
||||||
# WORKING_DIRECTORY "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
|
|
||||||
#endif()
|
|
||||||
|
|
||||||
configure_file(${DOXYFILE_IN} ${CMAKE_CURRENT_BINARY_DIR}/doxy.config ESCAPE_QUOTES IMMEDIATE @ONLY)
|
add_custom_target(doxygen
|
||||||
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doxy.trac.in)
|
COMMAND "${DOXYGEN_EXECUTABLE}"
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doxy.trac.in ${CMAKE_CURRENT_BINARY_DIR}/doxy.trac ESCAPE_QUOTES IMMEDIATE @ONLY)
|
"${DOXYFILE}"
|
||||||
add_custom_target(doxygen-trac ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.trac)
|
COMMENT "Writing documentation to ${DOXYFILE_OUTPUT_DIR}..."
|
||||||
endif()
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
|
||||||
get_target_property(DOC_TARGET doc TYPE)
|
set(DOXYFILE_DOT "NO")
|
||||||
if(NOT DOC_TARGET)
|
if(DOXYGEN_DOT_EXECUTABLE)
|
||||||
add_custom_target(doc)
|
set(DOXYFILE_DOT "YES")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_dependencies(doc doxygen)
|
## LaTeX
|
||||||
|
set(DOXYFILE_PDFLATEX "NO")
|
||||||
|
|
||||||
|
set_property(DIRECTORY APPEND PROPERTY
|
||||||
|
ADDITIONAL_MAKE_CLEAN_FILES
|
||||||
|
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
|
||||||
|
|
||||||
|
if(DOXYFILE_LATEX STREQUAL "ON")
|
||||||
|
set(DOXYFILE_GENERATE_LATEX "YES")
|
||||||
|
find_package(LATEX)
|
||||||
|
find_program(DOXYFILE_MAKE make)
|
||||||
|
mark_as_advanced(DOXYFILE_MAKE)
|
||||||
|
if(LATEX_COMPILER AND MAKEINDEX_COMPILER AND DOXYFILE_MAKE)
|
||||||
|
if(PDFLATEX_COMPILER)
|
||||||
|
set(DOXYFILE_PDFLATEX "YES")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_custom_command(TARGET doxygen
|
||||||
|
POST_BUILD
|
||||||
|
COMMAND "${DOXYFILE_MAKE}"
|
||||||
|
COMMENT "Running LaTeX for Doxygen documentation in ${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}..."
|
||||||
|
WORKING_DIRECTORY "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
|
||||||
|
else()
|
||||||
|
set(DOXYGEN_LATEX "NO")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set(DOXYFILE_GENERATE_LATEX "NO")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
configure_file("${DOXYFILE_IN}" "${DOXYFILE}" @ONLY)
|
||||||
|
|
||||||
|
add_custom_target(doc)
|
||||||
|
add_dependencies(doc doxygen)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -17,9 +17,24 @@
|
|||||||
/* Define to 1 if you have the <argp.h> header file. */
|
/* Define to 1 if you have the <argp.h> header file. */
|
||||||
#cmakedefine HAVE_ARGP_H 1
|
#cmakedefine HAVE_ARGP_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <aprpa/inet.h> header file. */
|
||||||
|
#cmakedefine HAVE_ARPA_INET_H 1
|
||||||
|
|
||||||
/* Define to 1 if you have the <pty.h> header file. */
|
/* Define to 1 if you have the <pty.h> header file. */
|
||||||
#cmakedefine HAVE_PTY_H 1
|
#cmakedefine HAVE_PTY_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <utmp.h> header file. */
|
||||||
|
#cmakedefine HAVE_UTMP_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <util.h> header file. */
|
||||||
|
#cmakedefine HAVE_UTIL_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <libutil.h> header file. */
|
||||||
|
#cmakedefine HAVE_LIBUTIL_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||||
|
#cmakedefine HAVE_SYS_TIME_H 1
|
||||||
|
|
||||||
/* Define to 1 if you have the <termios.h> header file. */
|
/* Define to 1 if you have the <termios.h> header file. */
|
||||||
#cmakedefine HAVE_TERMIOS_H 1
|
#cmakedefine HAVE_TERMIOS_H 1
|
||||||
|
|
||||||
@@ -79,6 +94,9 @@
|
|||||||
/* Define to 1 if you have the `_vsnprintf_s' function. */
|
/* Define to 1 if you have the `_vsnprintf_s' function. */
|
||||||
#cmakedefine HAVE__VSNPRINTF_S 1
|
#cmakedefine HAVE__VSNPRINTF_S 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `isblank' function. */
|
||||||
|
#cmakedefine HAVE_ISBLANK 1
|
||||||
|
|
||||||
/* Define to 1 if you have the `strncpy' function. */
|
/* Define to 1 if you have the `strncpy' function. */
|
||||||
#cmakedefine HAVE_STRNCPY 1
|
#cmakedefine HAVE_STRNCPY 1
|
||||||
|
|
||||||
@@ -123,13 +141,16 @@
|
|||||||
/* Define to 1 if you have the `pthread' library (-lpthread). */
|
/* Define to 1 if you have the `pthread' library (-lpthread). */
|
||||||
#cmakedefine HAVE_PTHREAD 1
|
#cmakedefine HAVE_PTHREAD 1
|
||||||
|
|
||||||
|
|
||||||
/**************************** OPTIONS ****************************/
|
/**************************** OPTIONS ****************************/
|
||||||
|
|
||||||
#cmakedefine HAVE_GCC_THREAD_LOCAL_STORAGE 1
|
#cmakedefine HAVE_GCC_THREAD_LOCAL_STORAGE 1
|
||||||
#cmakedefine HAVE_MSC_THREAD_LOCAL_STORAGE 1
|
#cmakedefine HAVE_MSC_THREAD_LOCAL_STORAGE 1
|
||||||
|
|
||||||
#cmakedefine HAVE_GCC_VOLATILE_MEMORY_PROTECTION 1
|
#cmakedefine HAVE_GCC_VOLATILE_MEMORY_PROTECTION 1
|
||||||
|
#cmakedefine HAVE_GCC_NARG_MACRO 1
|
||||||
|
|
||||||
|
#cmakedefine HAVE_COMPILER__FUNC__ 1
|
||||||
|
#cmakedefine HAVE_COMPILER__FUNCTION__ 1
|
||||||
|
|
||||||
/* Define to 1 if you want to enable GSSAPI */
|
/* Define to 1 if you want to enable GSSAPI */
|
||||||
#cmakedefine WITH_GSSAPI 1
|
#cmakedefine WITH_GSSAPI 1
|
||||||
@@ -155,6 +176,9 @@
|
|||||||
/* Define to 1 if you want to enable calltrace debug output */
|
/* Define to 1 if you want to enable calltrace debug output */
|
||||||
#cmakedefine DEBUG_CALLTRACE 1
|
#cmakedefine DEBUG_CALLTRACE 1
|
||||||
|
|
||||||
|
/* Define to 1 if you want to enable NaCl support */
|
||||||
|
#cmakedefine WITH_NACL 1
|
||||||
|
|
||||||
/*************************** ENDIAN *****************************/
|
/*************************** ENDIAN *****************************/
|
||||||
|
|
||||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||||
|
|||||||
@@ -721,7 +721,7 @@ EXCLUDE_SYMLINKS = NO
|
|||||||
EXCLUDE_PATTERNS = */.git/* \
|
EXCLUDE_PATTERNS = */.git/* \
|
||||||
*/.svn/* \
|
*/.svn/* \
|
||||||
*/cmake/* \
|
*/cmake/* \
|
||||||
*/build/*
|
*/obj/*
|
||||||
|
|
||||||
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
|
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
|
||||||
# (namespaces, classes, functions, etc.) that should be excluded from the
|
# (namespaces, classes, functions, etc.) that should be excluded from the
|
||||||
@@ -1628,7 +1628,7 @@ INCLUDE_FILE_PATTERNS =
|
|||||||
# undefined via #undef or recursively expanded use the := operator
|
# undefined via #undef or recursively expanded use the := operator
|
||||||
# instead of the = operator.
|
# instead of the = operator.
|
||||||
|
|
||||||
PREDEFINED =
|
PREDEFINED = WITH_SERVER WITH_SFTP WITH_PCAP
|
||||||
|
|
||||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
|
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
|
||||||
# this tag can be used to specify a list of macro names that should be expanded.
|
# this tag can be used to specify a list of macro names that should be expanded.
|
||||||
@@ -285,7 +285,7 @@ int authenticate_kbdint(ssh_session session)
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = ssh_userauth_none(session, NULL, NULL);
|
rc = ssh_userauth_none(session, NULL);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@endcode
|
@endcode
|
||||||
@@ -304,7 +304,7 @@ int test_several_auth_methods(ssh_session session)
|
|||||||
{
|
{
|
||||||
int method, rc;
|
int method, rc;
|
||||||
|
|
||||||
rc = ssh_userauth_none(session, NULL, NULL);
|
rc = ssh_userauth_none(session, NULL);
|
||||||
if (rc != SSH_AUTH_SUCCESS) {
|
if (rc != SSH_AUTH_SUCCESS) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ If an error has been encountered, it returns a negative value:
|
|||||||
|
|
||||||
@code
|
@code
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
unsigned int nbytes;
|
int nbytes;
|
||||||
|
|
||||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||||
while (nbytes > 0)
|
while (nbytes > 0)
|
||||||
|
|||||||
119
doc/curve25519-sha256@libssh.org.txt
Normal file
119
doc/curve25519-sha256@libssh.org.txt
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
curve25519-sha256@libssh.org.txt Aris Adamantiadis <aris@badcode.be>
|
||||||
|
21/9/2013
|
||||||
|
|
||||||
|
1. Introduction
|
||||||
|
|
||||||
|
This document describes the key exchange methode curve25519-sha256@libssh.org
|
||||||
|
for SSH version 2 protocol. It is provided as an alternative to the existing
|
||||||
|
key exchange mechanisms based on either Diffie-Hellman or Elliptic Curve Diffie-
|
||||||
|
Hellman [RFC5656].
|
||||||
|
The reason is the following : During summer of 2013, revelations from ex-
|
||||||
|
consultant at NSA Edward Snowden gave proof that NSA willingly inserts backdoors
|
||||||
|
into softwares, hardware components and published standards. While it is still
|
||||||
|
believed that the mathematics behind ECC cryptography are still sound and solid,
|
||||||
|
some people (including Bruce Schneier [SCHNEIER]), showed their lack of confidence
|
||||||
|
in NIST-published curves such as nistp256, nistp384, nistp521, for which constant
|
||||||
|
parameters (including the generator point) are defined without explanation. It
|
||||||
|
is also believed that NSA had a word to say in their definition. These curves
|
||||||
|
are not the most secure or fastest possible for their key sizes [DJB], and
|
||||||
|
researchers think it is possible that NSA have ways of cracking NIST curves.
|
||||||
|
It is also interesting to note that SSH belongs to the list of protocols the NSA
|
||||||
|
claims to be able to eavesdrop. Having a secure replacement would make passive
|
||||||
|
attacks much harder if such a backdoor exists.
|
||||||
|
|
||||||
|
However an alternative exists in the form of Curve25519. This algorithm has been
|
||||||
|
proposed in 2006 by DJB [Curve25519]. Its main strengths are its speed, its
|
||||||
|
constant-time run time (and resistance against side-channel attacks), and its
|
||||||
|
lack of nebulous hard-coded constants.
|
||||||
|
|
||||||
|
The reference version being used in this document is the one described in
|
||||||
|
[Curve25519] as implemented in the library NaCl [NaCl].
|
||||||
|
This document does not attempt to provide alternatives to the ecdsa-sha1-*
|
||||||
|
authentication keys.
|
||||||
|
|
||||||
|
2. Key exchange
|
||||||
|
|
||||||
|
The key exchange procedure is very similar to the one described chapter 4 of
|
||||||
|
[RFC5656]. Public ephemeral keys are transmitted over SSH encapsulated into
|
||||||
|
standard SSH strings.
|
||||||
|
|
||||||
|
The following is an overview of the key exchange process:
|
||||||
|
|
||||||
|
Client Server
|
||||||
|
------ ------
|
||||||
|
Generate ephemeral key pair.
|
||||||
|
SSH_MSG_KEX_ECDH_INIT -------->
|
||||||
|
Verify that client public key
|
||||||
|
length is 32 bytes.
|
||||||
|
Generate ephemeral key pair.
|
||||||
|
Compute shared secret.
|
||||||
|
Generate and sign exchange hash.
|
||||||
|
<-------- SSH_MSG_KEX_ECDH_REPLY
|
||||||
|
Verify that server public key length is 32 bytes.
|
||||||
|
* Verify host keys belong to server.
|
||||||
|
Compute shared secret.
|
||||||
|
Generate exchange hash.
|
||||||
|
Verify server's signature.
|
||||||
|
|
||||||
|
* Optional but strongly recommanded as this protects against MITM attacks.
|
||||||
|
|
||||||
|
This is implemented using the same messages as described in RFC5656 chapter 4
|
||||||
|
|
||||||
|
3. Method Name
|
||||||
|
|
||||||
|
The name of this key exchange method is "curve25519-sha256@libssh.org".
|
||||||
|
|
||||||
|
4. Implementation considerations
|
||||||
|
|
||||||
|
The whole method is based on the curve25519 scalar multiplication. In this
|
||||||
|
method, a private key is a scalar of 256 bits, and a public key is a point
|
||||||
|
of 256 bits.
|
||||||
|
|
||||||
|
4.1. Private key generation
|
||||||
|
|
||||||
|
A 32 bytes private key should be generated for each new connection,
|
||||||
|
using a secure PRNG. The following actions must be done on the private key:
|
||||||
|
mysecret[0] &= 248;
|
||||||
|
mysecret[31] &= 127;
|
||||||
|
mysecret[31] |= 64;
|
||||||
|
In order to keep the key valid. However, many cryptographic libraries will do
|
||||||
|
this automatically.
|
||||||
|
It should be noted that, in opposition to NIST curves, no special validation
|
||||||
|
should be done to ensure the result is a valid and secure private key.
|
||||||
|
|
||||||
|
4.2 Public key generation
|
||||||
|
|
||||||
|
The 32 bytes public key of either a client or a server must be generated using
|
||||||
|
the 32 bytes private key and a common generator base. This base is defined as 9
|
||||||
|
followed by all zeroes:
|
||||||
|
const unsigned char basepoint[32] = {9};
|
||||||
|
|
||||||
|
The public key is calculated using the cryptographic scalar multiplication:
|
||||||
|
const unsigned char privkey[32];
|
||||||
|
unsigned char pubkey[32];
|
||||||
|
crypto_scalarmult (pubkey, privkey, basepoint);
|
||||||
|
However some cryptographic libraries may provide a combined function:
|
||||||
|
crypto_scalarmult_base (pubkey, privkey);
|
||||||
|
|
||||||
|
It should be noted that, in opposition to NIST curves, no special validation
|
||||||
|
should be done to ensure the received public keys are valid curves point. The
|
||||||
|
Curve25519 algorithm ensure that every possible public key maps to a valid
|
||||||
|
ECC Point.
|
||||||
|
|
||||||
|
4.3 Shared secret generation
|
||||||
|
|
||||||
|
The shared secret, k, is defined in SSH specifications to be a big integer.
|
||||||
|
This number is calculated using the following procedure:
|
||||||
|
|
||||||
|
X is the 32 bytes point obtained by the scalar multiplication of the other
|
||||||
|
side's public key and the local private key scalar.
|
||||||
|
|
||||||
|
The whole 32 bytes of the number X are then converted into a big integer k.
|
||||||
|
This conversion follows the network byte order. This step differs from
|
||||||
|
RFC5656.
|
||||||
|
|
||||||
|
[RFC5656] http://tools.ietf.org/html/rfc5656
|
||||||
|
[SCHNEIER] https://www.schneier.com/blog/archives/2013/09/the_nsa_is_brea.html#c1675929
|
||||||
|
[DJB] http://cr.yp.to/talks/2013.05.31/slides-dan+tanja-20130531-4x3.pdf
|
||||||
|
[Curve25519] "Curve25519: new Diffie-Hellman speed records."
|
||||||
|
http://cr.yp.to/ecdh/curve25519-20060209.pdf
|
||||||
1546
doc/doxy.trac.in
1546
doc/doxy.trac.in
File diff suppressed because it is too large
Load Diff
@@ -144,10 +144,10 @@ or whatever use you have for it.
|
|||||||
|
|
||||||
@subsection libssh_reverse Doing reverse port forwarding with libssh
|
@subsection libssh_reverse Doing reverse port forwarding with libssh
|
||||||
|
|
||||||
To do reverse port forwarding, call ssh_forward_listen(),
|
To do reverse port forwarding, call ssh_channel_listen_forward(),
|
||||||
then ssh_forward_accept().
|
then ssh_channel_accept_forward().
|
||||||
|
|
||||||
When you call ssh_forward_listen(), you can let the remote server
|
When you call ssh_channel_listen_forward(), you can let the remote server
|
||||||
chose the non-priviledged port it should listen to. Otherwise, you can chose
|
chose the non-priviledged port it should listen to. Otherwise, you can chose
|
||||||
your own priviledged or non-priviledged port. Beware that you should have
|
your own priviledged or non-priviledged port. Beware that you should have
|
||||||
administrative priviledges on the remote server to open a priviledged port
|
administrative priviledges on the remote server to open a priviledged port
|
||||||
@@ -164,6 +164,7 @@ int web_server(ssh_session session)
|
|||||||
ssh_channel channel;
|
ssh_channel channel;
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
int nbytes, nwritten;
|
int nbytes, nwritten;
|
||||||
|
int port = 0;
|
||||||
char *helloworld = ""
|
char *helloworld = ""
|
||||||
"HTTP/1.1 200 OK\n"
|
"HTTP/1.1 200 OK\n"
|
||||||
"Content-Type: text/html\n"
|
"Content-Type: text/html\n"
|
||||||
@@ -178,7 +179,7 @@ int web_server(ssh_session session)
|
|||||||
" </body>\n"
|
" </body>\n"
|
||||||
"</html>\n";
|
"</html>\n";
|
||||||
|
|
||||||
rc = ssh_forward_listen(session, NULL, 8080, NULL);
|
rc = ssh_channel_listen_forward(session, NULL, 8080, NULL);
|
||||||
if (rc != SSH_OK)
|
if (rc != SSH_OK)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error opening remote port: %s\n",
|
fprintf(stderr, "Error opening remote port: %s\n",
|
||||||
@@ -186,7 +187,7 @@ int web_server(ssh_session session)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
channel = ssh_forward_accept(session, 60000);
|
channel = ssh_channel_accept_forward(session, 60000, &port);
|
||||||
if (channel == NULL)
|
if (channel == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error waiting for incoming connection: %s\n",
|
fprintf(stderr, "Error waiting for incoming connection: %s\n",
|
||||||
|
|||||||
@@ -367,7 +367,7 @@ int show_remote_processes(ssh_session session)
|
|||||||
ssh_channel channel;
|
ssh_channel channel;
|
||||||
int rc;
|
int rc;
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
unsigned int nbytes;
|
int nbytes;
|
||||||
|
|
||||||
channel = ssh_channel_new(session);
|
channel = ssh_channel_new(session);
|
||||||
if (channel == NULL)
|
if (channel == NULL)
|
||||||
@@ -391,7 +391,7 @@ int show_remote_processes(ssh_session session)
|
|||||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||||
while (nbytes > 0)
|
while (nbytes > 0)
|
||||||
{
|
{
|
||||||
if (write(1, buffer, nbytes) != nbytes)
|
if (write(1, buffer, nbytes) != (unsigned int) nbytes)
|
||||||
{
|
{
|
||||||
ssh_channel_close(channel);
|
ssh_channel_close(channel);
|
||||||
ssh_channel_free(channel);
|
ssh_channel_free(channel);
|
||||||
@@ -443,11 +443,10 @@ Most of time, the error returned are SSH_FATAL, but some functions
|
|||||||
(generaly the ssh_request_xxx ones) may fail because of server denying request.
|
(generaly the ssh_request_xxx ones) may fail because of server denying request.
|
||||||
In these cases, SSH_REQUEST_DENIED is returned.
|
In these cases, SSH_REQUEST_DENIED is returned.
|
||||||
|
|
||||||
ssh_get_error() and ssh_get_error_code() take a ssh_session as a parameter.
|
For thread safety, errors are bound to ssh_session objects.
|
||||||
That's for thread safety, error messages that can be attached to a session
|
As long as your ssh_session object is not NULL, you can retrieve the last error
|
||||||
aren't static anymore. Any error that happens during ssh_options_xxx()
|
message and error code from the ssh_session using ssh_get_error() and
|
||||||
or ssh_connect() (i.e., outside of any session) can be retrieved by
|
ssh_get_error_code() respectively.
|
||||||
giving NULL as argument.
|
|
||||||
|
|
||||||
The SFTP subsystem has its own error codes, in addition to libssh ones.
|
The SFTP subsystem has its own error codes, in addition to libssh ones.
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ the interesting functions as you go.
|
|||||||
|
|
||||||
The libssh library provides:
|
The libssh library provides:
|
||||||
|
|
||||||
- <strong>Key Exchange Methods</strong>: <i>ecdh-sha2-nistp256</i>, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1
|
- <strong>Key Exchange Methods</strong>: <i>curve25519-sha256@libssh.org, ecdh-sha2-nistp256</i>, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1
|
||||||
- <strong>Hostkey Types</strong>: <i>ecdsa-sha2-nistp256</i>, ssh-dss, ssh-rsa
|
- <strong>Hostkey Types</strong>: <i>ecdsa-sha2-nistp256</i>, ssh-dss, ssh-rsa
|
||||||
- <strong>Ciphers</strong>: <i>aes256-ctr, aes192-ctr, aes128-ctr</i>, aes256-cbc (rijndael-cbc@lysator.liu.se), aes192-cbc, aes128-cbc, 3des-cbc, des-cbc-ssh1, blowfish-cbc, none
|
- <strong>Ciphers</strong>: <i>aes256-ctr, aes192-ctr, aes128-ctr</i>, aes256-cbc (rijndael-cbc@lysator.liu.se), aes192-cbc, aes128-cbc, 3des-cbc, des-cbc-ssh1, blowfish-cbc, none
|
||||||
- <strong>Compression Schemes</strong>: zlib, <i>zlib@openssh.com</i>, none
|
- <strong>Compression Schemes</strong>: zlib, <i>zlib@openssh.com</i>, none
|
||||||
@@ -184,6 +184,8 @@ It was later modified and expanded by the following RFCs.
|
|||||||
Authentication and Key Exchange for the Secure Shell (SSH) Protocol
|
Authentication and Key Exchange for the Secure Shell (SSH) Protocol
|
||||||
- <a href="http://tools.ietf.org/html/rfc4716" target="_blank">RFC 4716</a>,
|
- <a href="http://tools.ietf.org/html/rfc4716" target="_blank">RFC 4716</a>,
|
||||||
The Secure Shell (SSH) Public Key File Format
|
The Secure Shell (SSH) Public Key File Format
|
||||||
|
- <a href="http://tools.ietf.org/html/rfc5647" target="_blank">RFC 5647</a>,
|
||||||
|
AES Galois Counter Mode for the Secure Shell Transport Layer Protocol
|
||||||
- <a href="http://tools.ietf.org/html/rfc5656" target="_blank">RFC 5656</a>,
|
- <a href="http://tools.ietf.org/html/rfc5656" target="_blank">RFC 5656</a>,
|
||||||
Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer
|
Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer
|
||||||
|
|
||||||
@@ -203,6 +205,12 @@ do the same in libssh.
|
|||||||
|
|
||||||
@subsection main-rfc-extensions Secure Shell Extensions
|
@subsection main-rfc-extensions Secure Shell Extensions
|
||||||
|
|
||||||
|
The libssh project has an extension to support Curve25519 which is also supported by
|
||||||
|
the OpenSSH project.
|
||||||
|
|
||||||
|
- <a href="http://git.libssh.org/projects/libssh.git/tree/doc/curve25519-sha256@libssh.org.txt" target="_blank">curve25519-sha256@libssh.org</a>,
|
||||||
|
Curve25519-SHA256 for ECDH KEX
|
||||||
|
|
||||||
The OpenSSH project has defined some extensions to the protocol. We support some of
|
The OpenSSH project has defined some extensions to the protocol. We support some of
|
||||||
them like the statvfs calls in SFTP or the ssh-agent.
|
them like the statvfs calls in SFTP or the ssh-agent.
|
||||||
|
|
||||||
|
|||||||
122
doc/sftp.dox
122
doc/sftp.dox
@@ -210,52 +210,63 @@ results to come.
|
|||||||
|
|
||||||
Synchronous read is done with sftp_read().
|
Synchronous read is done with sftp_read().
|
||||||
|
|
||||||
The following example prints the contents of remote file "/etc/profile". For
|
Files are normally transferred in chunks. A good chunk size is 16 KB. The following
|
||||||
each 1024 bytes of information read, it waits until the end of the read operation:
|
example transfers the remote file "/etc/profile" in 16 KB chunks. For each chunk we
|
||||||
|
request, sftp_read blocks till the data has been received:
|
||||||
|
|
||||||
@code
|
@code
|
||||||
|
// Good chunk size
|
||||||
|
#define MAX_XFER_BUF_SIZE 16384
|
||||||
|
|
||||||
int sftp_read_sync(ssh_session session, sftp_session sftp)
|
int sftp_read_sync(ssh_session session, sftp_session sftp)
|
||||||
{
|
{
|
||||||
int access_type;
|
int access_type;
|
||||||
sftp_file file;
|
sftp_file file;
|
||||||
char buffer[1024];
|
char buffer[MAX_XFER_BUF_SIZE];
|
||||||
int nbytes, rc;
|
int nbytes, nwritten, rc;
|
||||||
|
int fd;
|
||||||
|
|
||||||
access_type = O_RDONLY;
|
access_type = O_RDONLY;
|
||||||
file = sftp_open(sftp, "/etc/profile",
|
file = sftp_open(sftp, "/etc/profile",
|
||||||
access_type, 0);
|
access_type, 0);
|
||||||
if (file == NULL)
|
if (file == NULL) {
|
||||||
{
|
fprintf(stderr, "Can't open file for reading: %s\n",
|
||||||
fprintf(stderr, "Can't open file for reading: %s\n",
|
ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
nbytes = sftp_read(file, buffer, sizeof(buffer));
|
|
||||||
while (nbytes > 0)
|
|
||||||
{
|
|
||||||
if (write(1, buffer, nbytes) != nbytes)
|
|
||||||
{
|
|
||||||
sftp_close(file);
|
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
|
||||||
nbytes = sftp_read(file, buffer, sizeof(buffer));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbytes < 0)
|
fd = open("/path/to/profile", O_CREAT);
|
||||||
{
|
if (fd < 0) {
|
||||||
fprintf(stderr, "Error while reading file: %s\n",
|
fprintf(stderr, "Can't open file for writing: %s\n",
|
||||||
ssh_get_error(session));
|
strerror(errno));
|
||||||
sftp_close(file);
|
return SSH_ERROR;
|
||||||
return SSH_ERROR;
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
nbytes = sftp_read(file, buffer, sizeof(buffer));
|
||||||
|
if (nbytes == 0) {
|
||||||
|
break; // EOF
|
||||||
|
} else if (nbytes < 0) {
|
||||||
|
fprintf(stderr, "Error while reading file: %s\n",
|
||||||
|
ssh_get_error(session));
|
||||||
|
sftp_close(file);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
nwritten = write(fd, buffer, nbytes);
|
||||||
|
if (nwritten != nbytes) {
|
||||||
|
fprintf(stderr, "Error writing: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
sftp_close(file);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = sftp_close(file);
|
rc = sftp_close(file);
|
||||||
if (rc != SSH_OK)
|
if (rc != SSH_OK) {
|
||||||
{
|
fprintf(stderr, "Can't close the read file: %s\n",
|
||||||
fprintf(stderr, "Can't close the read file: %s\n",
|
ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
return rc;
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
@@ -271,14 +282,17 @@ sftp_async_read() waits for the data to come. To open a file in nonblocking mode
|
|||||||
call sftp_file_set_nonblocking() right after you opened it. Default is blocking mode.
|
call sftp_file_set_nonblocking() right after you opened it. Default is blocking mode.
|
||||||
|
|
||||||
The example below reads a very big file in asynchronous, nonblocking, mode. Each
|
The example below reads a very big file in asynchronous, nonblocking, mode. Each
|
||||||
time the data are not ready yet, a counter is incrementer.
|
time the data is not ready yet, a counter is incremented.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
|
// Good chunk size
|
||||||
|
#define MAX_XFER_BUF_SIZE 16384
|
||||||
|
|
||||||
int sftp_read_async(ssh_session session, sftp_session sftp)
|
int sftp_read_async(ssh_session session, sftp_session sftp)
|
||||||
{
|
{
|
||||||
int access_type;
|
int access_type;
|
||||||
sftp_file file;
|
sftp_file file;
|
||||||
char buffer[1024];
|
char buffer[MAX_XFER_BUF_SIZE];
|
||||||
int async_request;
|
int async_request;
|
||||||
int nbytes;
|
int nbytes;
|
||||||
long counter;
|
long counter;
|
||||||
@@ -287,8 +301,7 @@ int sftp_read_async(ssh_session session, sftp_session sftp)
|
|||||||
access_type = O_RDONLY;
|
access_type = O_RDONLY;
|
||||||
file = sftp_open(sftp, "some_very_big_file",
|
file = sftp_open(sftp, "some_very_big_file",
|
||||||
access_type, 0);
|
access_type, 0);
|
||||||
if (file == NULL)
|
if (file == NULL) {
|
||||||
{
|
|
||||||
fprintf(stderr, "Can't open file for reading: %s\n",
|
fprintf(stderr, "Can't open file for reading: %s\n",
|
||||||
ssh_get_error(session));
|
ssh_get_error(session));
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
@@ -298,27 +311,31 @@ int sftp_read_async(ssh_session session, sftp_session sftp)
|
|||||||
async_request = sftp_async_read_begin(file, sizeof(buffer));
|
async_request = sftp_async_read_begin(file, sizeof(buffer));
|
||||||
counter = 0L;
|
counter = 0L;
|
||||||
usleep(10000);
|
usleep(10000);
|
||||||
if (async_request >= 0)
|
if (async_request >= 0) {
|
||||||
nbytes = sftp_async_read(file, buffer, sizeof(buffer),
|
nbytes = sftp_async_read(file, buffer, sizeof(buffer),
|
||||||
async_request);
|
async_request);
|
||||||
else nbytes = -1;
|
} else {
|
||||||
while (nbytes > 0 || nbytes == SSH_AGAIN)
|
nbytes = -1;
|
||||||
{
|
|
||||||
if (nbytes > 0)
|
|
||||||
{
|
|
||||||
write(1, buffer, nbytes);
|
|
||||||
async_request = sftp_async_read_begin(file, sizeof(buffer));
|
|
||||||
}
|
|
||||||
else counter++;
|
|
||||||
usleep(10000);
|
|
||||||
if (async_request >= 0)
|
|
||||||
nbytes = sftp_async_read(file, buffer, sizeof(buffer),
|
|
||||||
async_request);
|
|
||||||
else nbytes = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbytes < 0)
|
while (nbytes > 0 || nbytes == SSH_AGAIN) {
|
||||||
{
|
if (nbytes > 0) {
|
||||||
|
write(1, buffer, nbytes);
|
||||||
|
async_request = sftp_async_read_begin(file, sizeof(buffer));
|
||||||
|
} else {
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
usleep(10000);
|
||||||
|
|
||||||
|
if (async_request >= 0) {
|
||||||
|
nbytes = sftp_async_read(file, buffer, sizeof(buffer),
|
||||||
|
async_request);
|
||||||
|
} else {
|
||||||
|
nbytes = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nbytes < 0) {
|
||||||
fprintf(stderr, "Error while reading file: %s\n",
|
fprintf(stderr, "Error while reading file: %s\n",
|
||||||
ssh_get_error(session));
|
ssh_get_error(session));
|
||||||
sftp_close(file);
|
sftp_close(file);
|
||||||
@@ -328,8 +345,7 @@ int sftp_read_async(ssh_session session, sftp_session sftp)
|
|||||||
printf("The counter has reached value: %ld\n", counter);
|
printf("The counter has reached value: %ld\n", counter);
|
||||||
|
|
||||||
rc = sftp_close(file);
|
rc = sftp_close(file);
|
||||||
if (rc != SSH_OK)
|
if (rc != SSH_OK) {
|
||||||
{
|
|
||||||
fprintf(stderr, "Can't close the read file: %s\n",
|
fprintf(stderr, "Can't close the read file: %s\n",
|
||||||
ssh_get_error(session));
|
ssh_get_error(session));
|
||||||
return rc;
|
return rc;
|
||||||
|
|||||||
@@ -61,5 +61,6 @@ implement the following methods :
|
|||||||
- mutex_destroy
|
- mutex_destroy
|
||||||
- thread_id
|
- thread_id
|
||||||
|
|
||||||
|
libgcrypt 1.6 and bigger backend does not support custom callback. Using anything else than pthreads (ssh_threads_get_pthread()) here will fail.
|
||||||
Good luck !
|
Good luck !
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ include_directories(
|
|||||||
${CMAKE_BINARY_DIR}
|
${CMAKE_BINARY_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
if (BSD OR SOLARIS)
|
if (BSD OR SOLARIS OR OSX)
|
||||||
find_package(Argp)
|
find_package(Argp)
|
||||||
endif (BSD OR SOLARIS)
|
endif (BSD OR SOLARIS OR OSX)
|
||||||
|
|
||||||
if (UNIX AND NOT WIN32)
|
if (UNIX AND NOT WIN32)
|
||||||
add_executable(libssh_scp libssh_scp.c ${examples_SRCS})
|
add_executable(libssh_scp libssh_scp.c ${examples_SRCS})
|
||||||
@@ -25,13 +25,6 @@ if (UNIX AND NOT WIN32)
|
|||||||
add_executable(sshnetcat sshnetcat.c ${examples_SRCS})
|
add_executable(sshnetcat sshnetcat.c ${examples_SRCS})
|
||||||
target_link_libraries(sshnetcat ${LIBSSH_SHARED_LIBRARY})
|
target_link_libraries(sshnetcat ${LIBSSH_SHARED_LIBRARY})
|
||||||
|
|
||||||
if (WITH_SERVER)
|
|
||||||
if (HAVE_LIBUTIL)
|
|
||||||
add_executable(samplesshd-tty samplesshd-tty.c)
|
|
||||||
target_link_libraries(samplesshd-tty ${LIBSSH_SHARED_LIBRARY} util)
|
|
||||||
endif (HAVE_LIBUTIL)
|
|
||||||
endif (WITH_SERVER)
|
|
||||||
|
|
||||||
if (WITH_SFTP)
|
if (WITH_SFTP)
|
||||||
add_executable(samplesftp samplesftp.c ${examples_SRCS})
|
add_executable(samplesftp samplesftp.c ${examples_SRCS})
|
||||||
target_link_libraries(samplesftp ${LIBSSH_SHARED_LIBRARY})
|
target_link_libraries(samplesftp ${LIBSSH_SHARED_LIBRARY})
|
||||||
@@ -41,8 +34,10 @@ if (UNIX AND NOT WIN32)
|
|||||||
target_link_libraries(samplessh ${LIBSSH_SHARED_LIBRARY})
|
target_link_libraries(samplessh ${LIBSSH_SHARED_LIBRARY})
|
||||||
|
|
||||||
if (WITH_SERVER)
|
if (WITH_SERVER)
|
||||||
add_executable(samplesshd samplesshd.c)
|
if (HAVE_LIBUTIL)
|
||||||
target_link_libraries(samplesshd ${LIBSSH_SHARED_LIBRARY} ${ARGP_LIBRARIES})
|
add_executable(ssh_server_fork ssh_server_fork.c)
|
||||||
|
target_link_libraries(ssh_server_fork ${LIBSSH_SHARED_LIBRARY} ${ARGP_LIBRARIES} util)
|
||||||
|
endif (HAVE_LIBUTIL)
|
||||||
|
|
||||||
if (WITH_GSSAPI AND GSSAPI_FOUND)
|
if (WITH_GSSAPI AND GSSAPI_FOUND)
|
||||||
add_executable(samplesshd-cb samplesshd-cb.c)
|
add_executable(samplesshd-cb samplesshd-cb.c)
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ int authenticate_console(ssh_session session){
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
method = ssh_auth_list(session);
|
method = ssh_userauth_list(session, NULL);
|
||||||
while (rc != SSH_AUTH_SUCCESS) {
|
while (rc != SSH_AUTH_SUCCESS) {
|
||||||
if (method & SSH_AUTH_METHOD_GSSAPI_MIC){
|
if (method & SSH_AUTH_METHOD_GSSAPI_MIC){
|
||||||
rc = ssh_userauth_gssapi(session);
|
rc = ssh_userauth_gssapi(session);
|
||||||
@@ -129,10 +129,10 @@ int authenticate_console(ssh_session session){
|
|||||||
}
|
}
|
||||||
// Try to authenticate with public key first
|
// Try to authenticate with public key first
|
||||||
if (method & SSH_AUTH_METHOD_PUBLICKEY) {
|
if (method & SSH_AUTH_METHOD_PUBLICKEY) {
|
||||||
rc = ssh_userauth_autopubkey(session, NULL);
|
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
|
||||||
if (rc == SSH_AUTH_ERROR) {
|
if (rc == SSH_AUTH_ERROR) {
|
||||||
error(session);
|
error(session);
|
||||||
return rc;
|
return rc;
|
||||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,14 +34,26 @@ int verify_knownhost(ssh_session session){
|
|||||||
int state;
|
int state;
|
||||||
char buf[10];
|
char buf[10];
|
||||||
unsigned char *hash = NULL;
|
unsigned char *hash = NULL;
|
||||||
int hlen;
|
size_t hlen;
|
||||||
|
ssh_key srv_pubkey;
|
||||||
|
int rc;
|
||||||
|
|
||||||
state=ssh_is_server_known(session);
|
state=ssh_is_server_known(session);
|
||||||
|
|
||||||
hlen = ssh_get_pubkey_hash(session, &hash);
|
rc = ssh_get_publickey(session, &srv_pubkey);
|
||||||
if (hlen < 0) {
|
if (rc < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = ssh_get_publickey_hash(srv_pubkey,
|
||||||
|
SSH_PUBLICKEY_HASH_SHA1,
|
||||||
|
&hash,
|
||||||
|
&hlen);
|
||||||
|
ssh_key_free(srv_pubkey);
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
switch(state){
|
switch(state){
|
||||||
case SSH_SERVER_KNOWN_OK:
|
case SSH_SERVER_KNOWN_OK:
|
||||||
break; /* ok */
|
break; /* ok */
|
||||||
|
|||||||
@@ -229,6 +229,7 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
|
|||||||
fprintf(stderr,"error: %s\n",ssh_get_error(dest->session));
|
fprintf(stderr,"error: %s\n",ssh_get_error(dest->session));
|
||||||
ssh_string_free_char(filename);
|
ssh_string_free_char(filename);
|
||||||
ssh_scp_free(dest->scp);
|
ssh_scp_free(dest->scp);
|
||||||
|
dest->scp = NULL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -298,13 +298,22 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
|||||||
int ret;
|
int ret;
|
||||||
while(channel){
|
while(channel){
|
||||||
do{
|
do{
|
||||||
|
int fd;
|
||||||
|
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
if(!eof)
|
if(!eof)
|
||||||
FD_SET(0,&fds);
|
FD_SET(0,&fds);
|
||||||
timeout.tv_sec=30;
|
timeout.tv_sec=30;
|
||||||
timeout.tv_usec=0;
|
timeout.tv_usec=0;
|
||||||
FD_SET(ssh_get_fd(session),&fds);
|
|
||||||
maxfd=ssh_get_fd(session)+1;
|
fd = ssh_get_fd(session);
|
||||||
|
if (fd < 0) {
|
||||||
|
fprintf(stderr, "Error getting fd\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FD_SET(fd, &fds);
|
||||||
|
maxfd = fd + 1;
|
||||||
|
|
||||||
channels[0]=channel; // set the first channel we want to read from
|
channels[0]=channel; // set the first channel we want to read from
|
||||||
channels[1]=NULL;
|
channels[1]=NULL;
|
||||||
ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout);
|
ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout);
|
||||||
|
|||||||
@@ -1,462 +0,0 @@
|
|||||||
/* This is a sample implementation of a libssh based SSH server */
|
|
||||||
/*
|
|
||||||
Copyright 2003-2011 Aris Adamantiadis
|
|
||||||
|
|
||||||
This file is part of the SSH Library
|
|
||||||
|
|
||||||
You are free to copy this file, modify it in any way, consider it being public
|
|
||||||
domain. This does not apply to the rest of the library though, but it is
|
|
||||||
allowed to cut-and-paste working code from this file to any license of
|
|
||||||
program.
|
|
||||||
The goal is to show the API in action. It's not a reference on how terminal
|
|
||||||
clients must be made or how a client should react.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <libssh/libssh.h>
|
|
||||||
#include <libssh/server.h>
|
|
||||||
#include <libssh/callbacks.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_ARGP_H
|
|
||||||
#include <argp.h>
|
|
||||||
#endif
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <poll.h>
|
|
||||||
#include <pty.h>
|
|
||||||
|
|
||||||
#define SSHD_USER "libssh"
|
|
||||||
#define SSHD_PASSWORD "libssh"
|
|
||||||
|
|
||||||
#ifndef KEYS_FOLDER
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define KEYS_FOLDER
|
|
||||||
#else
|
|
||||||
#define KEYS_FOLDER "/etc/ssh/"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WITH_PCAP
|
|
||||||
const char *pcap_file="debug.server.pcap";
|
|
||||||
ssh_pcap_file pcap;
|
|
||||||
|
|
||||||
static void set_pcap(ssh_session session){
|
|
||||||
if(!pcap_file)
|
|
||||||
return;
|
|
||||||
pcap=ssh_pcap_file_new();
|
|
||||||
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
|
|
||||||
printf("Error opening pcap file\n");
|
|
||||||
ssh_pcap_file_free(pcap);
|
|
||||||
pcap=NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ssh_set_pcap_file(session,pcap);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cleanup_pcap(){
|
|
||||||
ssh_pcap_file_free(pcap);
|
|
||||||
pcap=NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static int auth_password(const char *user, const char *password){
|
|
||||||
if(strcmp(user, SSHD_USER))
|
|
||||||
return 0;
|
|
||||||
if(strcmp(password, SSHD_PASSWORD))
|
|
||||||
return 0;
|
|
||||||
return 1; // authenticated
|
|
||||||
}
|
|
||||||
#ifdef HAVE_ARGP_H
|
|
||||||
const char *argp_program_version = "libssh server example "
|
|
||||||
SSH_STRINGIFY(LIBSSH_VERSION);
|
|
||||||
const char *argp_program_bug_address = "<libssh@libssh.org>";
|
|
||||||
|
|
||||||
/* Program documentation. */
|
|
||||||
static char doc[] = "libssh -- a Secure Shell protocol implementation";
|
|
||||||
|
|
||||||
/* A description of the arguments we accept. */
|
|
||||||
static char args_doc[] = "BINDADDR";
|
|
||||||
|
|
||||||
static int port = 22;
|
|
||||||
|
|
||||||
/* The options we understand. */
|
|
||||||
static struct argp_option options[] = {
|
|
||||||
{
|
|
||||||
.name = "port",
|
|
||||||
.key = 'p',
|
|
||||||
.arg = "PORT",
|
|
||||||
.flags = 0,
|
|
||||||
.doc = "Set the port to bind.",
|
|
||||||
.group = 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "hostkey",
|
|
||||||
.key = 'k',
|
|
||||||
.arg = "FILE",
|
|
||||||
.flags = 0,
|
|
||||||
.doc = "Set the host key.",
|
|
||||||
.group = 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "dsakey",
|
|
||||||
.key = 'd',
|
|
||||||
.arg = "FILE",
|
|
||||||
.flags = 0,
|
|
||||||
.doc = "Set the dsa key.",
|
|
||||||
.group = 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "rsakey",
|
|
||||||
.key = 'r',
|
|
||||||
.arg = "FILE",
|
|
||||||
.flags = 0,
|
|
||||||
.doc = "Set the rsa key.",
|
|
||||||
.group = 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "verbose",
|
|
||||||
.key = 'v',
|
|
||||||
.arg = NULL,
|
|
||||||
.flags = 0,
|
|
||||||
.doc = "Get verbose output.",
|
|
||||||
.group = 0
|
|
||||||
},
|
|
||||||
{NULL, 0, 0, 0, NULL, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Parse a single option. */
|
|
||||||
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
|
||||||
/* Get the input argument from argp_parse, which we
|
|
||||||
* know is a pointer to our arguments structure.
|
|
||||||
*/
|
|
||||||
ssh_bind sshbind = state->input;
|
|
||||||
|
|
||||||
switch (key) {
|
|
||||||
case 'p':
|
|
||||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
|
|
||||||
port = atoi(arg);
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
|
|
||||||
break;
|
|
||||||
case 'k':
|
|
||||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
|
|
||||||
break;
|
|
||||||
case ARGP_KEY_ARG:
|
|
||||||
if (state->arg_num >= 1) {
|
|
||||||
/* Too many arguments. */
|
|
||||||
argp_usage (state);
|
|
||||||
}
|
|
||||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
|
|
||||||
break;
|
|
||||||
case ARGP_KEY_END:
|
|
||||||
if (state->arg_num < 1) {
|
|
||||||
/* Not enough arguments. */
|
|
||||||
argp_usage (state);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return ARGP_ERR_UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Our argp parser. */
|
|
||||||
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
|
||||||
#endif /* HAVE_ARGP_H */
|
|
||||||
|
|
||||||
static int authenticate(ssh_session session) {
|
|
||||||
ssh_message message;
|
|
||||||
|
|
||||||
do {
|
|
||||||
message=ssh_message_get(session);
|
|
||||||
if(!message)
|
|
||||||
break;
|
|
||||||
switch(ssh_message_type(message)){
|
|
||||||
case SSH_REQUEST_AUTH:
|
|
||||||
switch(ssh_message_subtype(message)){
|
|
||||||
case SSH_AUTH_METHOD_PASSWORD:
|
|
||||||
printf("User %s wants to auth with pass %s\n",
|
|
||||||
ssh_message_auth_user(message),
|
|
||||||
ssh_message_auth_password(message));
|
|
||||||
if(auth_password(ssh_message_auth_user(message),
|
|
||||||
ssh_message_auth_password(message))){
|
|
||||||
ssh_message_auth_reply_success(message,0);
|
|
||||||
ssh_message_free(message);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
ssh_message_auth_set_methods(message,
|
|
||||||
SSH_AUTH_METHOD_PASSWORD |
|
|
||||||
SSH_AUTH_METHOD_INTERACTIVE);
|
|
||||||
// not authenticated, send default message
|
|
||||||
ssh_message_reply_default(message);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSH_AUTH_METHOD_NONE:
|
|
||||||
default:
|
|
||||||
printf("User %s wants to auth with unknown auth %d\n",
|
|
||||||
ssh_message_auth_user(message),
|
|
||||||
ssh_message_subtype(message));
|
|
||||||
ssh_message_auth_set_methods(message,
|
|
||||||
SSH_AUTH_METHOD_PASSWORD |
|
|
||||||
SSH_AUTH_METHOD_INTERACTIVE);
|
|
||||||
ssh_message_reply_default(message);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ssh_message_auth_set_methods(message,
|
|
||||||
SSH_AUTH_METHOD_PASSWORD |
|
|
||||||
SSH_AUTH_METHOD_INTERACTIVE);
|
|
||||||
ssh_message_reply_default(message);
|
|
||||||
}
|
|
||||||
ssh_message_free(message);
|
|
||||||
} while (1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int copy_fd_to_chan(socket_t fd, int revents, void *userdata) {
|
|
||||||
ssh_channel chan = (ssh_channel)userdata;
|
|
||||||
char buf[2048];
|
|
||||||
int sz = 0;
|
|
||||||
|
|
||||||
if(!chan) {
|
|
||||||
close(fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(revents & POLLIN) {
|
|
||||||
sz = read(fd, buf, 2048);
|
|
||||||
if(sz > 0) {
|
|
||||||
ssh_channel_write(chan, buf, sz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(revents & POLLHUP) {
|
|
||||||
ssh_channel_close(chan);
|
|
||||||
sz = -1;
|
|
||||||
}
|
|
||||||
return sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int copy_chan_to_fd(ssh_session session,
|
|
||||||
ssh_channel channel,
|
|
||||||
void *data,
|
|
||||||
uint32_t len,
|
|
||||||
int is_stderr,
|
|
||||||
void *userdata) {
|
|
||||||
int fd = *(int*)userdata;
|
|
||||||
int sz;
|
|
||||||
(void)session;
|
|
||||||
(void)channel;
|
|
||||||
(void)is_stderr;
|
|
||||||
|
|
||||||
sz = write(fd, data, len);
|
|
||||||
return sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void chan_close(ssh_session session, ssh_channel channel, void *userdata) {
|
|
||||||
int fd = *(int*)userdata;
|
|
||||||
(void)session;
|
|
||||||
(void)channel;
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ssh_channel_callbacks_struct cb = {
|
|
||||||
.channel_data_function = copy_chan_to_fd,
|
|
||||||
.channel_eof_function = chan_close,
|
|
||||||
.channel_close_function = chan_close,
|
|
||||||
.userdata = NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static int main_loop(ssh_channel chan) {
|
|
||||||
ssh_session session = ssh_channel_get_session(chan);
|
|
||||||
socket_t fd;
|
|
||||||
struct termios *term = NULL;
|
|
||||||
struct winsize *win = NULL;
|
|
||||||
pid_t childpid;
|
|
||||||
ssh_event event;
|
|
||||||
short events;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
childpid = forkpty(&fd, NULL, term, win);
|
|
||||||
if(childpid == 0) {
|
|
||||||
execl("/bin/bash", "/bin/bash", (char *)NULL);
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
cb.userdata = &fd;
|
|
||||||
ssh_callbacks_init(&cb);
|
|
||||||
ssh_set_channel_callbacks(chan, &cb);
|
|
||||||
|
|
||||||
events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
|
|
||||||
|
|
||||||
event = ssh_event_new();
|
|
||||||
if(event == NULL) {
|
|
||||||
printf("Couldn't get a event\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(ssh_event_add_fd(event, fd, events, copy_fd_to_chan, chan) != SSH_OK) {
|
|
||||||
printf("Couldn't add an fd to the event\n");
|
|
||||||
ssh_event_free(event);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(ssh_event_add_session(event, session) != SSH_OK) {
|
|
||||||
printf("Couldn't add the session to the event\n");
|
|
||||||
ssh_event_remove_fd(event, fd);
|
|
||||||
ssh_event_free(event);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
rc = ssh_event_dopoll(event, 1000);
|
|
||||||
if (rc == SSH_ERROR){
|
|
||||||
fprintf(stderr, "Error : %s\n", ssh_get_error(session));
|
|
||||||
ssh_event_free(event);
|
|
||||||
ssh_disconnect(session);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} while(!ssh_channel_is_closed(chan));
|
|
||||||
|
|
||||||
ssh_event_remove_fd(event, fd);
|
|
||||||
|
|
||||||
ssh_event_remove_session(event, session);
|
|
||||||
|
|
||||||
ssh_event_free(event);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv){
|
|
||||||
ssh_session session;
|
|
||||||
ssh_bind sshbind;
|
|
||||||
ssh_message message;
|
|
||||||
ssh_channel chan=0;
|
|
||||||
int auth=0;
|
|
||||||
int shell=0;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
sshbind=ssh_bind_new();
|
|
||||||
session=ssh_new();
|
|
||||||
|
|
||||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY,
|
|
||||||
KEYS_FOLDER "ssh_host_dsa_key");
|
|
||||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY,
|
|
||||||
KEYS_FOLDER "ssh_host_rsa_key");
|
|
||||||
|
|
||||||
#ifdef HAVE_ARGP_H
|
|
||||||
/*
|
|
||||||
* Parse our arguments; every option seen by parse_opt will
|
|
||||||
* be reflected in arguments.
|
|
||||||
*/
|
|
||||||
argp_parse (&argp, argc, argv, 0, 0, sshbind);
|
|
||||||
#else
|
|
||||||
(void) argc;
|
|
||||||
(void) argv;
|
|
||||||
#endif
|
|
||||||
#ifdef WITH_PCAP
|
|
||||||
set_pcap(session);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(ssh_bind_listen(sshbind)<0){
|
|
||||||
printf("Error listening to socket: %s\n", ssh_get_error(sshbind));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
printf("Started sample libssh sshd on port %d\n", port);
|
|
||||||
printf("You can login as the user %s with the password %s\n", SSHD_USER,
|
|
||||||
SSHD_PASSWORD);
|
|
||||||
r = ssh_bind_accept(sshbind, session);
|
|
||||||
if(r==SSH_ERROR){
|
|
||||||
printf("Error accepting a connection: %s\n", ssh_get_error(sshbind));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (ssh_handle_key_exchange(session)) {
|
|
||||||
printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* proceed to authentication */
|
|
||||||
auth = authenticate(session);
|
|
||||||
if(!auth){
|
|
||||||
printf("Authentication error: %s\n", ssh_get_error(session));
|
|
||||||
ssh_disconnect(session);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* wait for a channel session */
|
|
||||||
do {
|
|
||||||
message = ssh_message_get(session);
|
|
||||||
if(message){
|
|
||||||
if(ssh_message_type(message) == SSH_REQUEST_CHANNEL_OPEN &&
|
|
||||||
ssh_message_subtype(message) == SSH_CHANNEL_SESSION) {
|
|
||||||
chan = ssh_message_channel_request_open_reply_accept(message);
|
|
||||||
ssh_message_free(message);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
ssh_message_reply_default(message);
|
|
||||||
ssh_message_free(message);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while(!chan);
|
|
||||||
|
|
||||||
if(!chan) {
|
|
||||||
printf("Error: cleint did not ask for a channel session (%s)\n",
|
|
||||||
ssh_get_error(session));
|
|
||||||
ssh_finalize();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* wait for a shell */
|
|
||||||
do {
|
|
||||||
message = ssh_message_get(session);
|
|
||||||
if(message != NULL) {
|
|
||||||
if(ssh_message_type(message) == SSH_REQUEST_CHANNEL) {
|
|
||||||
if(ssh_message_subtype(message) == SSH_CHANNEL_REQUEST_SHELL) {
|
|
||||||
shell = 1;
|
|
||||||
ssh_message_channel_request_reply_success(message);
|
|
||||||
ssh_message_free(message);
|
|
||||||
break;
|
|
||||||
} else if(ssh_message_subtype(message) == SSH_CHANNEL_REQUEST_PTY) {
|
|
||||||
ssh_message_channel_request_reply_success(message);
|
|
||||||
ssh_message_free(message);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ssh_message_reply_default(message);
|
|
||||||
ssh_message_free(message);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while(!shell);
|
|
||||||
|
|
||||||
if(!shell) {
|
|
||||||
printf("Error: No shell requested (%s)\n", ssh_get_error(session));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("it works !\n");
|
|
||||||
|
|
||||||
main_loop(chan);
|
|
||||||
|
|
||||||
ssh_disconnect(session);
|
|
||||||
ssh_bind_free(sshbind);
|
|
||||||
#ifdef WITH_PCAP
|
|
||||||
cleanup_pcap();
|
|
||||||
#endif
|
|
||||||
ssh_finalize();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,314 +0,0 @@
|
|||||||
/* This is a sample implementation of a libssh based SSH server */
|
|
||||||
/*
|
|
||||||
Copyright 2003-2009 Aris Adamantiadis
|
|
||||||
|
|
||||||
This file is part of the SSH Library
|
|
||||||
|
|
||||||
You are free to copy this file, modify it in any way, consider it being public
|
|
||||||
domain. This does not apply to the rest of the library though, but it is
|
|
||||||
allowed to cut-and-paste working code from this file to any license of
|
|
||||||
program.
|
|
||||||
The goal is to show the API in action. It's not a reference on how terminal
|
|
||||||
clients must be made or how a client should react.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <libssh/libssh.h>
|
|
||||||
#include <libssh/server.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_ARGP_H
|
|
||||||
#include <argp.h>
|
|
||||||
#endif
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#ifndef KEYS_FOLDER
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define KEYS_FOLDER
|
|
||||||
#else
|
|
||||||
#define KEYS_FOLDER "/etc/ssh/"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WITH_PCAP
|
|
||||||
static const char *pcap_file="debug.server.pcap";
|
|
||||||
static ssh_pcap_file pcap;
|
|
||||||
|
|
||||||
static void set_pcap(ssh_session session) {
|
|
||||||
if(!pcap_file)
|
|
||||||
return;
|
|
||||||
pcap=ssh_pcap_file_new();
|
|
||||||
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
|
|
||||||
printf("Error opening pcap file\n");
|
|
||||||
ssh_pcap_file_free(pcap);
|
|
||||||
pcap=NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ssh_set_pcap_file(session,pcap);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cleanup_pcap(void) {
|
|
||||||
ssh_pcap_file_free(pcap);
|
|
||||||
pcap=NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static int auth_password(const char *user, const char *password){
|
|
||||||
if(strcmp(user,"aris"))
|
|
||||||
return 0;
|
|
||||||
if(strcmp(password,"lala"))
|
|
||||||
return 0;
|
|
||||||
return 1; // authenticated
|
|
||||||
}
|
|
||||||
#ifdef HAVE_ARGP_H
|
|
||||||
const char *argp_program_version = "libssh server example "
|
|
||||||
SSH_STRINGIFY(LIBSSH_VERSION);
|
|
||||||
const char *argp_program_bug_address = "<libssh@libssh.org>";
|
|
||||||
|
|
||||||
/* Program documentation. */
|
|
||||||
static char doc[] = "libssh -- a Secure Shell protocol implementation";
|
|
||||||
|
|
||||||
/* A description of the arguments we accept. */
|
|
||||||
static char args_doc[] = "BINDADDR";
|
|
||||||
|
|
||||||
/* The options we understand. */
|
|
||||||
static struct argp_option options[] = {
|
|
||||||
{
|
|
||||||
.name = "port",
|
|
||||||
.key = 'p',
|
|
||||||
.arg = "PORT",
|
|
||||||
.flags = 0,
|
|
||||||
.doc = "Set the port to bind.",
|
|
||||||
.group = 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "hostkey",
|
|
||||||
.key = 'k',
|
|
||||||
.arg = "FILE",
|
|
||||||
.flags = 0,
|
|
||||||
.doc = "Set the host key.",
|
|
||||||
.group = 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "dsakey",
|
|
||||||
.key = 'd',
|
|
||||||
.arg = "FILE",
|
|
||||||
.flags = 0,
|
|
||||||
.doc = "Set the dsa key.",
|
|
||||||
.group = 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "rsakey",
|
|
||||||
.key = 'r',
|
|
||||||
.arg = "FILE",
|
|
||||||
.flags = 0,
|
|
||||||
.doc = "Set the rsa key.",
|
|
||||||
.group = 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "verbose",
|
|
||||||
.key = 'v',
|
|
||||||
.arg = NULL,
|
|
||||||
.flags = 0,
|
|
||||||
.doc = "Get verbose output.",
|
|
||||||
.group = 0
|
|
||||||
},
|
|
||||||
{NULL, 0, NULL, 0, NULL, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Parse a single option. */
|
|
||||||
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
|
||||||
/* Get the input argument from argp_parse, which we
|
|
||||||
* know is a pointer to our arguments structure.
|
|
||||||
*/
|
|
||||||
ssh_bind sshbind = state->input;
|
|
||||||
|
|
||||||
switch (key) {
|
|
||||||
case 'p':
|
|
||||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
|
|
||||||
break;
|
|
||||||
case 'k':
|
|
||||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
|
|
||||||
break;
|
|
||||||
case ARGP_KEY_ARG:
|
|
||||||
if (state->arg_num >= 1) {
|
|
||||||
/* Too many arguments. */
|
|
||||||
argp_usage (state);
|
|
||||||
}
|
|
||||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
|
|
||||||
break;
|
|
||||||
case ARGP_KEY_END:
|
|
||||||
if (state->arg_num < 1) {
|
|
||||||
/* Not enough arguments. */
|
|
||||||
argp_usage (state);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return ARGP_ERR_UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Our argp parser. */
|
|
||||||
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
|
||||||
#endif /* HAVE_ARGP_H */
|
|
||||||
|
|
||||||
int main(int argc, char **argv){
|
|
||||||
ssh_session session;
|
|
||||||
ssh_bind sshbind;
|
|
||||||
ssh_message message;
|
|
||||||
ssh_channel chan=0;
|
|
||||||
char buf[2048];
|
|
||||||
int auth=0;
|
|
||||||
int sftp=0;
|
|
||||||
int i;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
sshbind=ssh_bind_new();
|
|
||||||
session=ssh_new();
|
|
||||||
|
|
||||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key");
|
|
||||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key");
|
|
||||||
|
|
||||||
#ifdef HAVE_ARGP_H
|
|
||||||
/*
|
|
||||||
* Parse our arguments; every option seen by parse_opt will
|
|
||||||
* be reflected in arguments.
|
|
||||||
*/
|
|
||||||
argp_parse (&argp, argc, argv, 0, 0, sshbind);
|
|
||||||
#else
|
|
||||||
(void) argc;
|
|
||||||
(void) argv;
|
|
||||||
#endif
|
|
||||||
#ifdef WITH_PCAP
|
|
||||||
set_pcap(session);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(ssh_bind_listen(sshbind)<0){
|
|
||||||
printf("Error listening to socket: %s\n",ssh_get_error(sshbind));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
r=ssh_bind_accept(sshbind,session);
|
|
||||||
if(r==SSH_ERROR){
|
|
||||||
printf("error accepting a connection : %s\n",ssh_get_error(sshbind));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (ssh_handle_key_exchange(session)) {
|
|
||||||
printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
message=ssh_message_get(session);
|
|
||||||
if(!message)
|
|
||||||
break;
|
|
||||||
switch(ssh_message_type(message)){
|
|
||||||
case SSH_REQUEST_AUTH:
|
|
||||||
switch(ssh_message_subtype(message)){
|
|
||||||
case SSH_AUTH_METHOD_PASSWORD:
|
|
||||||
printf("User %s wants to auth with pass %s\n",
|
|
||||||
ssh_message_auth_user(message),
|
|
||||||
ssh_message_auth_password(message));
|
|
||||||
if(auth_password(ssh_message_auth_user(message),
|
|
||||||
ssh_message_auth_password(message))){
|
|
||||||
auth=1;
|
|
||||||
ssh_message_auth_reply_success(message,0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// not authenticated, send default message
|
|
||||||
case SSH_AUTH_METHOD_NONE:
|
|
||||||
default:
|
|
||||||
ssh_message_auth_set_methods(message,SSH_AUTH_METHOD_PASSWORD);
|
|
||||||
ssh_message_reply_default(message);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ssh_message_reply_default(message);
|
|
||||||
}
|
|
||||||
ssh_message_free(message);
|
|
||||||
} while (!auth);
|
|
||||||
if(!auth){
|
|
||||||
printf("auth error: %s\n",ssh_get_error(session));
|
|
||||||
ssh_disconnect(session);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
message=ssh_message_get(session);
|
|
||||||
if(message){
|
|
||||||
switch(ssh_message_type(message)){
|
|
||||||
case SSH_REQUEST_CHANNEL_OPEN:
|
|
||||||
if(ssh_message_subtype(message)==SSH_CHANNEL_SESSION){
|
|
||||||
chan=ssh_message_channel_request_open_reply_accept(message);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
ssh_message_reply_default(message);
|
|
||||||
}
|
|
||||||
ssh_message_free(message);
|
|
||||||
}
|
|
||||||
} while(message && !chan);
|
|
||||||
if(!chan){
|
|
||||||
printf("error : %s\n",ssh_get_error(session));
|
|
||||||
ssh_finalize();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
message=ssh_message_get(session);
|
|
||||||
if(message && ssh_message_type(message)==SSH_REQUEST_CHANNEL &&
|
|
||||||
(ssh_message_subtype(message)==SSH_CHANNEL_REQUEST_SHELL ||
|
|
||||||
ssh_message_subtype(message)==SSH_CHANNEL_REQUEST_PTY)) {
|
|
||||||
// if(!strcmp(ssh_message_channel_request_subsystem(message),"sftp")){
|
|
||||||
sftp=1;
|
|
||||||
ssh_message_channel_request_reply_success(message);
|
|
||||||
break;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
if(!sftp){
|
|
||||||
ssh_message_reply_default(message);
|
|
||||||
}
|
|
||||||
ssh_message_free(message);
|
|
||||||
} while (message && !sftp);
|
|
||||||
if(!sftp){
|
|
||||||
printf("error : %s\n",ssh_get_error(session));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
printf("it works !\n");
|
|
||||||
do{
|
|
||||||
i=ssh_channel_read(chan,buf, 2048, 0);
|
|
||||||
if(i>0) {
|
|
||||||
ssh_channel_write(chan, buf, i);
|
|
||||||
if (write(1,buf,i) < 0) {
|
|
||||||
printf("error writing to buffer\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (buf[0] == '\x0d') {
|
|
||||||
if (write(1, "\n", 1) < 0) {
|
|
||||||
printf("error writing to buffer\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
ssh_channel_write(chan, "\n", 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (i>0);
|
|
||||||
ssh_disconnect(session);
|
|
||||||
ssh_bind_free(sshbind);
|
|
||||||
#ifdef WITH_PCAP
|
|
||||||
cleanup_pcap();
|
|
||||||
#endif
|
|
||||||
ssh_finalize();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
697
examples/ssh_server_fork.c
Normal file
697
examples/ssh_server_fork.c
Normal file
@@ -0,0 +1,697 @@
|
|||||||
|
/* This is a sample implementation of a libssh based SSH server */
|
||||||
|
/*
|
||||||
|
Copyright 2014 Audrius Butkevicius
|
||||||
|
|
||||||
|
This file is part of the SSH Library
|
||||||
|
|
||||||
|
You are free to copy this file, modify it in any way, consider it being public
|
||||||
|
domain. This does not apply to the rest of the library though, but it is
|
||||||
|
allowed to cut-and-paste working code from this file to any license of
|
||||||
|
program.
|
||||||
|
The goal is to show the API in action.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <libssh/callbacks.h>
|
||||||
|
#include <libssh/poll.h>
|
||||||
|
#include <libssh/server.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_ARGP_H
|
||||||
|
#include <argp.h>
|
||||||
|
#endif
|
||||||
|
#include <fcntl.h>
|
||||||
|
#ifdef HAVE_LIBUTIL_H
|
||||||
|
#include <libutil.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_PTY_H
|
||||||
|
#include <pty.h>
|
||||||
|
#endif
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifdef HAVE_UTMP_H
|
||||||
|
#include <utmp.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UTIL_H
|
||||||
|
#include <util.h>
|
||||||
|
#endif
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifndef KEYS_FOLDER
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define KEYS_FOLDER
|
||||||
|
#else
|
||||||
|
#define KEYS_FOLDER "/etc/ssh/"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define USER "myuser"
|
||||||
|
#define PASS "mypassword"
|
||||||
|
#define BUF_SIZE 1048576
|
||||||
|
#define SESSION_END (SSH_CLOSED | SSH_CLOSED_ERROR)
|
||||||
|
#define SFTP_SERVER_PATH "/usr/lib/sftp-server"
|
||||||
|
|
||||||
|
static void set_default_keys(ssh_bind sshbind,
|
||||||
|
int rsa_already_set,
|
||||||
|
int dsa_already_set,
|
||||||
|
int ecdsa_already_set) {
|
||||||
|
if (!rsa_already_set) {
|
||||||
|
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY,
|
||||||
|
KEYS_FOLDER "ssh_host_rsa_key");
|
||||||
|
}
|
||||||
|
if (!dsa_already_set) {
|
||||||
|
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY,
|
||||||
|
KEYS_FOLDER "ssh_host_dsa_key");
|
||||||
|
}
|
||||||
|
if (!ecdsa_already_set) {
|
||||||
|
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_ECDSAKEY,
|
||||||
|
KEYS_FOLDER "ssh_host_ecdsa_key");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_ARGP_H
|
||||||
|
const char *argp_program_version = "libssh server example "
|
||||||
|
SSH_STRINGIFY(LIBSSH_VERSION);
|
||||||
|
const char *argp_program_bug_address = "<libssh@libssh.org>";
|
||||||
|
|
||||||
|
/* Program documentation. */
|
||||||
|
static char doc[] = "libssh -- a Secure Shell protocol implementation";
|
||||||
|
|
||||||
|
/* A description of the arguments we accept. */
|
||||||
|
static char args_doc[] = "BINDADDR";
|
||||||
|
|
||||||
|
/* The options we understand. */
|
||||||
|
static struct argp_option options[] = {
|
||||||
|
{
|
||||||
|
.name = "port",
|
||||||
|
.key = 'p',
|
||||||
|
.arg = "PORT",
|
||||||
|
.flags = 0,
|
||||||
|
.doc = "Set the port to bind.",
|
||||||
|
.group = 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "hostkey",
|
||||||
|
.key = 'k',
|
||||||
|
.arg = "FILE",
|
||||||
|
.flags = 0,
|
||||||
|
.doc = "Set a host key. Can be used multiple times. "
|
||||||
|
"Implies no default keys.",
|
||||||
|
.group = 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "dsakey",
|
||||||
|
.key = 'd',
|
||||||
|
.arg = "FILE",
|
||||||
|
.flags = 0,
|
||||||
|
.doc = "Set the dsa key.",
|
||||||
|
.group = 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "rsakey",
|
||||||
|
.key = 'r',
|
||||||
|
.arg = "FILE",
|
||||||
|
.flags = 0,
|
||||||
|
.doc = "Set the rsa key.",
|
||||||
|
.group = 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "ecdsakey",
|
||||||
|
.key = 'e',
|
||||||
|
.arg = "FILE",
|
||||||
|
.flags = 0,
|
||||||
|
.doc = "Set the ecdsa key.",
|
||||||
|
.group = 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "no-default-keys",
|
||||||
|
.key = 'n',
|
||||||
|
.arg = NULL,
|
||||||
|
.flags = 0,
|
||||||
|
.doc = "Do not set default key locations.",
|
||||||
|
.group = 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "verbose",
|
||||||
|
.key = 'v',
|
||||||
|
.arg = NULL,
|
||||||
|
.flags = 0,
|
||||||
|
.doc = "Get verbose output.",
|
||||||
|
.group = 0
|
||||||
|
},
|
||||||
|
{NULL, 0, NULL, 0, NULL, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Parse a single option. */
|
||||||
|
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
||||||
|
/* Get the input argument from argp_parse, which we
|
||||||
|
* know is a pointer to our arguments structure. */
|
||||||
|
ssh_bind sshbind = state->input;
|
||||||
|
static int no_default_keys = 0;
|
||||||
|
static int rsa_already_set = 0, dsa_already_set = 0, ecdsa_already_set = 0;
|
||||||
|
|
||||||
|
switch (key) {
|
||||||
|
case 'n':
|
||||||
|
no_default_keys = 1;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
|
||||||
|
dsa_already_set = 1;
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
||||||
|
/* We can't track the types of keys being added with this
|
||||||
|
option, so let's ensure we keep the keys we're adding
|
||||||
|
by just not setting the default keys */
|
||||||
|
no_default_keys = 1;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
|
||||||
|
rsa_already_set = 1;
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_ECDSAKEY, arg);
|
||||||
|
ecdsa_already_set = 1;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR,
|
||||||
|
"3");
|
||||||
|
break;
|
||||||
|
case ARGP_KEY_ARG:
|
||||||
|
if (state->arg_num >= 1) {
|
||||||
|
/* Too many arguments. */
|
||||||
|
argp_usage (state);
|
||||||
|
}
|
||||||
|
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
|
||||||
|
break;
|
||||||
|
case ARGP_KEY_END:
|
||||||
|
if (state->arg_num < 1) {
|
||||||
|
/* Not enough arguments. */
|
||||||
|
argp_usage (state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!no_default_keys) {
|
||||||
|
set_default_keys(sshbind,
|
||||||
|
rsa_already_set,
|
||||||
|
dsa_already_set,
|
||||||
|
ecdsa_already_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ARGP_ERR_UNKNOWN;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Our argp parser. */
|
||||||
|
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
||||||
|
#endif /* HAVE_ARGP_H */
|
||||||
|
|
||||||
|
/* A userdata struct for channel. */
|
||||||
|
struct channel_data_struct {
|
||||||
|
/* pid of the child process the channel will spawn. */
|
||||||
|
pid_t pid;
|
||||||
|
/* For PTY allocation */
|
||||||
|
socket_t pty_master;
|
||||||
|
socket_t pty_slave;
|
||||||
|
/* For communication with the child process. */
|
||||||
|
socket_t child_stdin;
|
||||||
|
socket_t child_stdout;
|
||||||
|
/* Only used for subsystem and exec requests. */
|
||||||
|
socket_t child_stderr;
|
||||||
|
/* Event which is used to poll the above descriptors. */
|
||||||
|
ssh_event event;
|
||||||
|
/* Terminal size struct. */
|
||||||
|
struct winsize *winsize;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* A userdata struct for session. */
|
||||||
|
struct session_data_struct {
|
||||||
|
/* Pointer to the channel the session will allocate. */
|
||||||
|
ssh_channel channel;
|
||||||
|
int auth_attempts;
|
||||||
|
int authenticated;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int data_function(ssh_session session, ssh_channel channel, void *data,
|
||||||
|
uint32_t len, int is_stderr, void *userdata) {
|
||||||
|
struct channel_data_struct *cdata = (struct channel_data_struct *) userdata;
|
||||||
|
|
||||||
|
(void) session;
|
||||||
|
(void) channel;
|
||||||
|
(void) is_stderr;
|
||||||
|
|
||||||
|
if (len == 0 || cdata->pid < 1 || kill(cdata->pid, 0) < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return write(cdata->child_stdin, (char *) data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pty_request(ssh_session session, ssh_channel channel,
|
||||||
|
const char *term, int cols, int rows, int py, int px,
|
||||||
|
void *userdata) {
|
||||||
|
struct channel_data_struct *cdata = (struct channel_data_struct *)userdata;
|
||||||
|
|
||||||
|
(void) session;
|
||||||
|
(void) channel;
|
||||||
|
(void) term;
|
||||||
|
|
||||||
|
cdata->winsize->ws_row = rows;
|
||||||
|
cdata->winsize->ws_col = cols;
|
||||||
|
cdata->winsize->ws_xpixel = px;
|
||||||
|
cdata->winsize->ws_ypixel = py;
|
||||||
|
|
||||||
|
if (openpty(&cdata->pty_master, &cdata->pty_slave, NULL, NULL,
|
||||||
|
cdata->winsize) != 0) {
|
||||||
|
fprintf(stderr, "Failed to open pty\n");
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pty_resize(ssh_session session, ssh_channel channel, int cols,
|
||||||
|
int rows, int py, int px, void *userdata) {
|
||||||
|
struct channel_data_struct *cdata = (struct channel_data_struct *)userdata;
|
||||||
|
|
||||||
|
(void) session;
|
||||||
|
(void) channel;
|
||||||
|
|
||||||
|
cdata->winsize->ws_row = rows;
|
||||||
|
cdata->winsize->ws_col = cols;
|
||||||
|
cdata->winsize->ws_xpixel = px;
|
||||||
|
cdata->winsize->ws_ypixel = py;
|
||||||
|
|
||||||
|
if (cdata->pty_master != -1) {
|
||||||
|
return ioctl(cdata->pty_master, TIOCSWINSZ, cdata->winsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int exec_pty(const char *mode, const char *command,
|
||||||
|
struct channel_data_struct *cdata) {
|
||||||
|
switch(cdata->pid = fork()) {
|
||||||
|
case -1:
|
||||||
|
close(cdata->pty_master);
|
||||||
|
close(cdata->pty_slave);
|
||||||
|
fprintf(stderr, "Failed to fork\n");
|
||||||
|
return SSH_ERROR;
|
||||||
|
case 0:
|
||||||
|
close(cdata->pty_master);
|
||||||
|
if (login_tty(cdata->pty_slave) != 0) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
execl("/bin/sh", "sh", mode, command, NULL);
|
||||||
|
exit(0);
|
||||||
|
default:
|
||||||
|
close(cdata->pty_slave);
|
||||||
|
/* pty fd is bi-directional */
|
||||||
|
cdata->child_stdout = cdata->child_stdin = cdata->pty_master;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int exec_nopty(const char *command, struct channel_data_struct *cdata) {
|
||||||
|
int in[2], out[2], err[2];
|
||||||
|
|
||||||
|
/* Do the plumbing to be able to talk with the child process. */
|
||||||
|
if (pipe(in) != 0) {
|
||||||
|
goto stdin_failed;
|
||||||
|
}
|
||||||
|
if (pipe(out) != 0) {
|
||||||
|
goto stdout_failed;
|
||||||
|
}
|
||||||
|
if (pipe(err) != 0) {
|
||||||
|
goto stderr_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(cdata->pid = fork()) {
|
||||||
|
case -1:
|
||||||
|
goto fork_failed;
|
||||||
|
case 0:
|
||||||
|
/* Finish the plumbing in the child process. */
|
||||||
|
close(in[1]);
|
||||||
|
close(out[0]);
|
||||||
|
close(err[0]);
|
||||||
|
dup2(in[0], STDIN_FILENO);
|
||||||
|
dup2(out[1], STDOUT_FILENO);
|
||||||
|
dup2(err[1], STDERR_FILENO);
|
||||||
|
close(in[0]);
|
||||||
|
close(out[1]);
|
||||||
|
close(err[1]);
|
||||||
|
/* exec the requested command. */
|
||||||
|
execl("/bin/sh", "sh", "-c", command, NULL);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(in[0]);
|
||||||
|
close(out[1]);
|
||||||
|
close(err[1]);
|
||||||
|
|
||||||
|
cdata->child_stdin = in[1];
|
||||||
|
cdata->child_stdout = out[0];
|
||||||
|
cdata->child_stderr = err[0];
|
||||||
|
|
||||||
|
return SSH_OK;
|
||||||
|
|
||||||
|
fork_failed:
|
||||||
|
close(err[0]);
|
||||||
|
close(err[1]);
|
||||||
|
stderr_failed:
|
||||||
|
close(out[0]);
|
||||||
|
close(out[1]);
|
||||||
|
stdout_failed:
|
||||||
|
close(in[0]);
|
||||||
|
close(in[1]);
|
||||||
|
stdin_failed:
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int exec_request(ssh_session session, ssh_channel channel,
|
||||||
|
const char *command, void *userdata) {
|
||||||
|
struct channel_data_struct *cdata = (struct channel_data_struct *) userdata;
|
||||||
|
|
||||||
|
|
||||||
|
(void) session;
|
||||||
|
(void) channel;
|
||||||
|
|
||||||
|
if(cdata->pid > 0) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cdata->pty_master != -1 && cdata->pty_slave != -1) {
|
||||||
|
return exec_pty("-c", command, cdata);
|
||||||
|
}
|
||||||
|
return exec_nopty(command, cdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int shell_request(ssh_session session, ssh_channel channel,
|
||||||
|
void *userdata) {
|
||||||
|
struct channel_data_struct *cdata = (struct channel_data_struct *) userdata;
|
||||||
|
|
||||||
|
(void) session;
|
||||||
|
(void) channel;
|
||||||
|
|
||||||
|
if(cdata->pid > 0) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cdata->pty_master != -1 && cdata->pty_slave != -1) {
|
||||||
|
return exec_pty("-l", NULL, cdata);
|
||||||
|
}
|
||||||
|
/* Client requested a shell without a pty, let's pretend we allow that */
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int subsystem_request(ssh_session session, ssh_channel channel,
|
||||||
|
const char *subsystem, void *userdata) {
|
||||||
|
/* subsystem requests behave simillarly to exec requests. */
|
||||||
|
if (strcmp(subsystem, "sftp") == 0) {
|
||||||
|
return exec_request(session, channel, SFTP_SERVER_PATH, userdata);
|
||||||
|
}
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int auth_password(ssh_session session, const char *user,
|
||||||
|
const char *pass, void *userdata) {
|
||||||
|
struct session_data_struct *sdata = (struct session_data_struct *) userdata;
|
||||||
|
|
||||||
|
(void) session;
|
||||||
|
|
||||||
|
if (strcmp(user, USER) == 0 && strcmp(pass, PASS) == 0) {
|
||||||
|
sdata->authenticated = 1;
|
||||||
|
return SSH_AUTH_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
sdata->auth_attempts++;
|
||||||
|
return SSH_AUTH_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssh_channel channel_open(ssh_session session, void *userdata) {
|
||||||
|
struct session_data_struct *sdata = (struct session_data_struct *) userdata;
|
||||||
|
|
||||||
|
sdata->channel = ssh_channel_new(session);
|
||||||
|
return sdata->channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int process_stdout(socket_t fd, int revents, void *userdata) {
|
||||||
|
char buf[BUF_SIZE];
|
||||||
|
int n = -1;
|
||||||
|
ssh_channel channel = (ssh_channel) userdata;
|
||||||
|
|
||||||
|
if (channel != NULL && (revents & POLLIN) != 0) {
|
||||||
|
n = read(fd, buf, BUF_SIZE);
|
||||||
|
if (n > 0) {
|
||||||
|
ssh_channel_write(channel, buf, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int process_stderr(socket_t fd, int revents, void *userdata) {
|
||||||
|
char buf[BUF_SIZE];
|
||||||
|
int n = -1;
|
||||||
|
ssh_channel channel = (ssh_channel) userdata;
|
||||||
|
|
||||||
|
if (channel != NULL && (revents & POLLIN) != 0) {
|
||||||
|
n = read(fd, buf, BUF_SIZE);
|
||||||
|
if (n > 0) {
|
||||||
|
ssh_channel_write_stderr(channel, buf, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_session(ssh_event event, ssh_session session) {
|
||||||
|
int n, rc;
|
||||||
|
|
||||||
|
/* Structure for storing the pty size. */
|
||||||
|
struct winsize wsize = {
|
||||||
|
.ws_row = 0,
|
||||||
|
.ws_col = 0,
|
||||||
|
.ws_xpixel = 0,
|
||||||
|
.ws_ypixel = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Our struct holding information about the channel. */
|
||||||
|
struct channel_data_struct cdata = {
|
||||||
|
.pid = 0,
|
||||||
|
.pty_master = -1,
|
||||||
|
.pty_slave = -1,
|
||||||
|
.child_stdin = -1,
|
||||||
|
.child_stdout = -1,
|
||||||
|
.child_stderr = -1,
|
||||||
|
.event = NULL,
|
||||||
|
.winsize = &wsize
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Our struct holding information about the session. */
|
||||||
|
struct session_data_struct sdata = {
|
||||||
|
.channel = NULL,
|
||||||
|
.auth_attempts = 0,
|
||||||
|
.authenticated = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ssh_channel_callbacks_struct channel_cb = {
|
||||||
|
.userdata = &cdata,
|
||||||
|
.channel_pty_request_function = pty_request,
|
||||||
|
.channel_pty_window_change_function = pty_resize,
|
||||||
|
.channel_shell_request_function = shell_request,
|
||||||
|
.channel_exec_request_function = exec_request,
|
||||||
|
.channel_data_function = data_function,
|
||||||
|
.channel_subsystem_request_function = subsystem_request
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ssh_server_callbacks_struct server_cb = {
|
||||||
|
.userdata = &sdata,
|
||||||
|
.auth_password_function = auth_password,
|
||||||
|
.channel_open_request_session_function = channel_open,
|
||||||
|
};
|
||||||
|
|
||||||
|
ssh_callbacks_init(&server_cb);
|
||||||
|
ssh_callbacks_init(&channel_cb);
|
||||||
|
|
||||||
|
ssh_set_server_callbacks(session, &server_cb);
|
||||||
|
|
||||||
|
if (ssh_handle_key_exchange(session) != SSH_OK) {
|
||||||
|
fprintf(stderr, "%s\n", ssh_get_error(session));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_set_auth_methods(session, SSH_AUTH_METHOD_PASSWORD);
|
||||||
|
ssh_event_add_session(event, session);
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
while (sdata.authenticated == 0 || sdata.channel == NULL) {
|
||||||
|
/* If the user has used up all attempts, or if he hasn't been able to
|
||||||
|
* authenticate in 10 seconds (n * 100ms), disconnect. */
|
||||||
|
if (sdata.auth_attempts >= 3 || n >= 100) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ssh_event_dopoll(event, 100) == SSH_ERROR) {
|
||||||
|
fprintf(stderr, "%s\n", ssh_get_error(session));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_set_channel_callbacks(sdata.channel, &channel_cb);
|
||||||
|
|
||||||
|
do {
|
||||||
|
/* Poll the main event which takes care of the session, the channel and
|
||||||
|
* even our child process's stdout/stderr (once it's started). */
|
||||||
|
if (ssh_event_dopoll(event, -1) == SSH_ERROR) {
|
||||||
|
ssh_channel_close(sdata.channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If child process's stdout/stderr has been registered with the event,
|
||||||
|
* or the child process hasn't started yet, continue. */
|
||||||
|
if (cdata.event != NULL || cdata.pid == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Executed only once, once the child process starts. */
|
||||||
|
cdata.event = event;
|
||||||
|
/* If stdout valid, add stdout to be monitored by the poll event. */
|
||||||
|
if (cdata.child_stdout != -1) {
|
||||||
|
if (ssh_event_add_fd(event, cdata.child_stdout, POLLIN, process_stdout,
|
||||||
|
sdata.channel) != SSH_OK) {
|
||||||
|
fprintf(stderr, "Failed to register stdout to poll context\n");
|
||||||
|
ssh_channel_close(sdata.channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If stderr valid, add stderr to be monitored by the poll event. */
|
||||||
|
if (cdata.child_stderr != -1){
|
||||||
|
if (ssh_event_add_fd(event, cdata.child_stderr, POLLIN, process_stderr,
|
||||||
|
sdata.channel) != SSH_OK) {
|
||||||
|
fprintf(stderr, "Failed to register stderr to poll context\n");
|
||||||
|
ssh_channel_close(sdata.channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while(ssh_channel_is_open(sdata.channel) &&
|
||||||
|
(cdata.pid == 0 || waitpid(cdata.pid, &rc, WNOHANG) == 0));
|
||||||
|
|
||||||
|
close(cdata.pty_master);
|
||||||
|
close(cdata.child_stdin);
|
||||||
|
close(cdata.child_stdout);
|
||||||
|
close(cdata.child_stderr);
|
||||||
|
|
||||||
|
/* Remove the descriptors from the polling context, since they are now
|
||||||
|
* closed, they will always trigger during the poll calls. */
|
||||||
|
ssh_event_remove_fd(event, cdata.child_stdout);
|
||||||
|
ssh_event_remove_fd(event, cdata.child_stderr);
|
||||||
|
|
||||||
|
/* If the child process exited. */
|
||||||
|
if (kill(cdata.pid, 0) < 0 && WIFEXITED(rc)) {
|
||||||
|
rc = WEXITSTATUS(rc);
|
||||||
|
ssh_channel_request_send_exit_status(sdata.channel, rc);
|
||||||
|
/* If client terminated the channel or the process did not exit nicely,
|
||||||
|
* but only if something has been forked. */
|
||||||
|
} else if (cdata.pid > 0) {
|
||||||
|
kill(cdata.pid, SIGKILL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_channel_send_eof(sdata.channel);
|
||||||
|
ssh_channel_close(sdata.channel);
|
||||||
|
|
||||||
|
/* Wait up to 5 seconds for the client to terminate the session. */
|
||||||
|
for (n = 0; n < 50 && (ssh_get_status(session) & SESSION_END) == 0; n++) {
|
||||||
|
ssh_event_dopoll(event, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SIGCHLD handler for cleaning up dead children. */
|
||||||
|
static void sigchld_handler(int signo) {
|
||||||
|
(void) signo;
|
||||||
|
while (waitpid(-1, NULL, WNOHANG) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
ssh_bind sshbind;
|
||||||
|
ssh_session session;
|
||||||
|
ssh_event event;
|
||||||
|
struct sigaction sa;
|
||||||
|
|
||||||
|
/* Set up SIGCHLD handler. */
|
||||||
|
sa.sa_handler = sigchld_handler;
|
||||||
|
sigemptyset(&sa.sa_mask);
|
||||||
|
sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
|
||||||
|
if (sigaction(SIGCHLD, &sa, NULL) != 0) {
|
||||||
|
fprintf(stderr, "Failed to register SIGCHLD handler\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_init();
|
||||||
|
sshbind = ssh_bind_new();
|
||||||
|
|
||||||
|
#ifdef HAVE_ARGP_H
|
||||||
|
argp_parse(&argp, argc, argv, 0, 0, sshbind);
|
||||||
|
#else
|
||||||
|
(void) argc;
|
||||||
|
(void) argv;
|
||||||
|
|
||||||
|
set_default_keys(sshbind, 0, 0, 0);
|
||||||
|
#endif /* HAVE_ARGP_H */
|
||||||
|
|
||||||
|
if(ssh_bind_listen(sshbind) < 0) {
|
||||||
|
fprintf(stderr, "%s\n", ssh_get_error(sshbind));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
session = ssh_new();
|
||||||
|
if (session == NULL) {
|
||||||
|
fprintf(stderr, "Failed to allocate session\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Blocks until there is a new incoming connection. */
|
||||||
|
if(ssh_bind_accept(sshbind, session) != SSH_ERROR) {
|
||||||
|
switch(fork()) {
|
||||||
|
case 0:
|
||||||
|
/* Remove the SIGCHLD handler inherited from parent. */
|
||||||
|
sa.sa_handler = SIG_DFL;
|
||||||
|
sigaction(SIGCHLD, &sa, NULL);
|
||||||
|
/* Remove socket binding, which allows us to restart the
|
||||||
|
* parent process, without terminating existing sessions. */
|
||||||
|
ssh_bind_free(sshbind);
|
||||||
|
|
||||||
|
event = ssh_event_new();
|
||||||
|
if (event != NULL) {
|
||||||
|
/* Blocks until the SSH session ends by either
|
||||||
|
* child process exiting, or client disconnecting. */
|
||||||
|
handle_session(event, session);
|
||||||
|
ssh_event_free(event);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Could not create polling context\n");
|
||||||
|
}
|
||||||
|
ssh_disconnect(session);
|
||||||
|
ssh_free(session);
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
case -1:
|
||||||
|
fprintf(stderr, "Failed to fork\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "%s\n", ssh_get_error(sshbind));
|
||||||
|
}
|
||||||
|
/* Since the session has been passed to a child fork, do some cleaning
|
||||||
|
* up at the parent process. */
|
||||||
|
ssh_disconnect(session);
|
||||||
|
ssh_free(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_bind_free(sshbind);
|
||||||
|
ssh_finalize();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -87,13 +87,23 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
|||||||
int ret;
|
int ret;
|
||||||
while(channel){
|
while(channel){
|
||||||
do{
|
do{
|
||||||
|
int fd;
|
||||||
|
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
if(!eof)
|
if(!eof)
|
||||||
FD_SET(0,&fds);
|
FD_SET(0,&fds);
|
||||||
timeout.tv_sec=30;
|
timeout.tv_sec=30;
|
||||||
timeout.tv_usec=0;
|
timeout.tv_usec=0;
|
||||||
FD_SET(ssh_get_fd(session),&fds);
|
|
||||||
maxfd=ssh_get_fd(session)+1;
|
fd = ssh_get_fd(session);
|
||||||
|
if (fd == -1) {
|
||||||
|
fprintf(stderr, "Error getting the session file descriptor: %s\n",
|
||||||
|
ssh_get_error(session));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FD_SET(fd, &fds);
|
||||||
|
maxfd = fd + 1;
|
||||||
|
|
||||||
channels[0]=channel; // set the first channel we want to read from
|
channels[0]=channel; // set the first channel we want to read from
|
||||||
channels[1]=NULL;
|
channels[1]=NULL;
|
||||||
ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout);
|
ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout);
|
||||||
@@ -102,27 +112,27 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
|||||||
if(FD_ISSET(0,&fds)){
|
if(FD_ISSET(0,&fds)){
|
||||||
lus=read(0,buffer,sizeof(buffer));
|
lus=read(0,buffer,sizeof(buffer));
|
||||||
if(lus)
|
if(lus)
|
||||||
channel_write(channel,buffer,lus);
|
ssh_channel_write(channel,buffer,lus);
|
||||||
else {
|
else {
|
||||||
eof=1;
|
eof=1;
|
||||||
channel_send_eof(channel);
|
ssh_channel_send_eof(channel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(channel && channel_is_closed(channel)){
|
if(channel && ssh_channel_is_closed(channel)){
|
||||||
channel_free(channel);
|
ssh_channel_free(channel);
|
||||||
channel=NULL;
|
channel=NULL;
|
||||||
channels[0]=NULL;
|
channels[0]=NULL;
|
||||||
}
|
}
|
||||||
if(outchannels[0]){
|
if(outchannels[0]){
|
||||||
while(channel && channel_is_open(channel) && channel_poll(channel,0)){
|
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,0)){
|
||||||
lus=channel_read(channel,buffer,sizeof(buffer),0);
|
lus = ssh_channel_read(channel,buffer,sizeof(buffer),0);
|
||||||
if(lus==-1){
|
if(lus==-1){
|
||||||
fprintf(stderr, "Error reading channel: %s\n",
|
fprintf(stderr, "Error reading channel: %s\n",
|
||||||
ssh_get_error(session));
|
ssh_get_error(session));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(lus==0){
|
if(lus==0){
|
||||||
channel_free(channel);
|
ssh_channel_free(channel);
|
||||||
channel=channels[0]=NULL;
|
channel=channels[0]=NULL;
|
||||||
} else {
|
} else {
|
||||||
ret = write(1, buffer, lus);
|
ret = write(1, buffer, lus);
|
||||||
@@ -133,27 +143,28 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while(channel && channel_is_open(channel) && channel_poll(channel,1)){ /* stderr */
|
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,1)){ /* stderr */
|
||||||
lus=channel_read(channel,buffer,sizeof(buffer),1);
|
lus = ssh_channel_read(channel, buffer, sizeof(buffer), 1);
|
||||||
if(lus==-1){
|
if(lus==-1){
|
||||||
fprintf(stderr, "Error reading channel: %s\n",
|
fprintf(stderr, "Error reading channel: %s\n",
|
||||||
ssh_get_error(session));
|
ssh_get_error(session));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(lus==0){
|
if(lus==0){
|
||||||
channel_free(channel);
|
ssh_channel_free(channel);
|
||||||
channel=channels[0]=NULL;
|
channel=channels[0]=NULL;
|
||||||
} else
|
} else {
|
||||||
ret = write(2, buffer, lus);
|
ret = write(2, buffer, lus);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Error writing to stderr: %s",
|
fprintf(stderr, "Error writing to stderr: %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(channel && channel_is_closed(channel)){
|
if(channel && ssh_channel_is_closed(channel)){
|
||||||
channel_free(channel);
|
ssh_channel_free(channel);
|
||||||
channel=NULL;
|
channel=NULL;
|
||||||
}
|
}
|
||||||
} while (ret==EINTR || ret==SSH_EINTR);
|
} while (ret==EINTR || ret==SSH_EINTR);
|
||||||
@@ -164,8 +175,8 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
|||||||
static void forwarding(ssh_session session){
|
static void forwarding(ssh_session session){
|
||||||
ssh_channel channel;
|
ssh_channel channel;
|
||||||
int r;
|
int r;
|
||||||
channel=channel_new(session);
|
channel = ssh_channel_new(session);
|
||||||
r=channel_open_forward(channel,desthost,atoi(port),"localhost",22);
|
r = ssh_channel_open_forward(channel, desthost, atoi(port), "localhost", 22);
|
||||||
if(r<0) {
|
if(r<0) {
|
||||||
printf("error forwarding port : %s\n",ssh_get_error(session));
|
printf("error forwarding port : %s\n",ssh_get_error(session));
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
project(headers C)
|
project(libssh-headers-x C)
|
||||||
|
|
||||||
add_subdirectory(libssh)
|
add_subdirectory(libssh)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ set(libssh_HDRS
|
|||||||
libssh.h
|
libssh.h
|
||||||
ssh2.h
|
ssh2.h
|
||||||
legacy.h
|
legacy.h
|
||||||
|
libsshpp.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if (WITH_SFTP)
|
if (WITH_SFTP)
|
||||||
|
|||||||
33
include/libssh/bignum.h
Normal file
33
include/libssh/bignum.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the SSH Library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 by Aris Adamantiadis <aris@badcode.be>
|
||||||
|
*
|
||||||
|
* 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 BIGNUM_H_
|
||||||
|
#define BIGNUM_H_
|
||||||
|
|
||||||
|
#include "libssh/libcrypto.h"
|
||||||
|
#include "libssh/libgcrypt.h"
|
||||||
|
|
||||||
|
bignum make_string_bn(ssh_string string);
|
||||||
|
void make_string_bn_inplace(ssh_string string, bignum bnout);
|
||||||
|
ssh_string make_bignum_string(bignum num);
|
||||||
|
void ssh_print_bignum(const char *which,bignum num);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* BIGNUM_H_ */
|
||||||
@@ -36,9 +36,11 @@ struct ssh_bind_struct {
|
|||||||
char *ecdsakey;
|
char *ecdsakey;
|
||||||
char *dsakey;
|
char *dsakey;
|
||||||
char *rsakey;
|
char *rsakey;
|
||||||
|
char *ed25519key;
|
||||||
ssh_key ecdsa;
|
ssh_key ecdsa;
|
||||||
ssh_key dsa;
|
ssh_key dsa;
|
||||||
ssh_key rsa;
|
ssh_key rsa;
|
||||||
|
ssh_key ed25519;
|
||||||
char *bindaddr;
|
char *bindaddr;
|
||||||
socket_t bindfd;
|
socket_t bindfd;
|
||||||
unsigned int bindport;
|
unsigned int bindport;
|
||||||
|
|||||||
87
include/libssh/blf.h
Normal file
87
include/libssh/blf.h
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/* $OpenBSD: blf.h,v 1.7 2007/03/14 17:59:41 grunk Exp $ */
|
||||||
|
/*
|
||||||
|
* Blowfish - a fast block cipher designed by Bruce Schneier
|
||||||
|
*
|
||||||
|
* Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by Niels Provos.
|
||||||
|
* 4. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BLF_H_
|
||||||
|
#define _BLF_H_
|
||||||
|
|
||||||
|
//#include "includes.h"
|
||||||
|
|
||||||
|
#if !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H)
|
||||||
|
|
||||||
|
/* Schneier specifies a maximum key length of 56 bytes.
|
||||||
|
* This ensures that every key bit affects every cipher
|
||||||
|
* bit. However, the subkeys can hold up to 72 bytes.
|
||||||
|
* Warning: For normal blowfish encryption only 56 bytes
|
||||||
|
* of the key affect all cipherbits.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define BLF_N 16 /* Number of Subkeys */
|
||||||
|
#define BLF_MAXKEYLEN ((BLF_N-2)*4) /* 448 bits */
|
||||||
|
#define BLF_MAXUTILIZED ((BLF_N+2)*4) /* 576 bits */
|
||||||
|
|
||||||
|
/* Blowfish context */
|
||||||
|
typedef struct BlowfishContext {
|
||||||
|
uint32_t S[4][256]; /* S-Boxes */
|
||||||
|
uint32_t P[BLF_N + 2]; /* Subkeys */
|
||||||
|
} blf_ctx;
|
||||||
|
|
||||||
|
/* Raw access to customized Blowfish
|
||||||
|
* blf_key is just:
|
||||||
|
* Blowfish_initstate( state )
|
||||||
|
* Blowfish_expand0state( state, key, keylen )
|
||||||
|
*/
|
||||||
|
|
||||||
|
void Blowfish_encipher(blf_ctx *, uint32_t *, uint32_t *);
|
||||||
|
void Blowfish_decipher(blf_ctx *, uint32_t *, uint32_t *);
|
||||||
|
void Blowfish_initstate(blf_ctx *);
|
||||||
|
void Blowfish_expand0state(blf_ctx *, const uint8_t *, uint16_t);
|
||||||
|
void Blowfish_expandstate
|
||||||
|
(blf_ctx *, const uint8_t *, uint16_t, const uint8_t *, uint16_t);
|
||||||
|
|
||||||
|
/* Standard Blowfish */
|
||||||
|
|
||||||
|
void blf_key(blf_ctx *, const uint8_t *, uint16_t);
|
||||||
|
void blf_enc(blf_ctx *, uint32_t *, uint16_t);
|
||||||
|
void blf_dec(blf_ctx *, uint32_t *, uint16_t);
|
||||||
|
|
||||||
|
void blf_ecb_encrypt(blf_ctx *, uint8_t *, uint32_t);
|
||||||
|
void blf_ecb_decrypt(blf_ctx *, uint8_t *, uint32_t);
|
||||||
|
|
||||||
|
void blf_cbc_encrypt(blf_ctx *, uint8_t *, uint8_t *, uint32_t);
|
||||||
|
void blf_cbc_decrypt(blf_ctx *, uint8_t *, uint8_t *, uint32_t);
|
||||||
|
|
||||||
|
/* Converts uint8_t to uint32_t */
|
||||||
|
uint32_t Blowfish_stream2word(const uint8_t *, uint16_t , uint16_t *);
|
||||||
|
|
||||||
|
#endif /* !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H) */
|
||||||
|
#endif /* _BLF_H */
|
||||||
@@ -21,6 +21,8 @@
|
|||||||
#ifndef BUFFER_H_
|
#ifndef BUFFER_H_
|
||||||
#define BUFFER_H_
|
#define BUFFER_H_
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include "libssh/libssh.h"
|
#include "libssh/libssh.h"
|
||||||
/*
|
/*
|
||||||
* Describes a buffer state
|
* Describes a buffer state
|
||||||
@@ -34,21 +36,47 @@ struct ssh_buffer_struct {
|
|||||||
uint32_t used;
|
uint32_t used;
|
||||||
uint32_t allocated;
|
uint32_t allocated;
|
||||||
uint32_t pos;
|
uint32_t pos;
|
||||||
|
int secure;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define SSH_BUFFER_PACK_END ((uint32_t) 0x4f65feb3)
|
||||||
|
|
||||||
LIBSSH_API void ssh_buffer_free(ssh_buffer buffer);
|
LIBSSH_API void ssh_buffer_free(ssh_buffer buffer);
|
||||||
LIBSSH_API void *ssh_buffer_get_begin(ssh_buffer buffer);
|
LIBSSH_API void *ssh_buffer_get_begin(ssh_buffer buffer);
|
||||||
LIBSSH_API uint32_t ssh_buffer_get_len(ssh_buffer buffer);
|
LIBSSH_API uint32_t ssh_buffer_get_len(ssh_buffer buffer);
|
||||||
LIBSSH_API ssh_buffer ssh_buffer_new(void);
|
LIBSSH_API ssh_buffer ssh_buffer_new(void);
|
||||||
|
void ssh_buffer_set_secure(ssh_buffer buffer);
|
||||||
int buffer_add_ssh_string(ssh_buffer buffer, ssh_string string);
|
int buffer_add_ssh_string(ssh_buffer buffer, ssh_string string);
|
||||||
int buffer_add_u8(ssh_buffer buffer, uint8_t data);
|
int buffer_add_u8(ssh_buffer buffer, uint8_t data);
|
||||||
int buffer_add_u16(ssh_buffer buffer, uint16_t data);
|
int buffer_add_u16(ssh_buffer buffer, uint16_t data);
|
||||||
int buffer_add_u32(ssh_buffer buffer, uint32_t data);
|
int buffer_add_u32(ssh_buffer buffer, uint32_t data);
|
||||||
int buffer_add_u64(ssh_buffer buffer, uint64_t data);
|
int buffer_add_u64(ssh_buffer buffer, uint64_t data);
|
||||||
int buffer_add_data(ssh_buffer buffer, const void *data, uint32_t len);
|
int ssh_buffer_add_data(ssh_buffer buffer, const void *data, uint32_t len);
|
||||||
|
|
||||||
|
int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
|
||||||
|
const char *format,
|
||||||
|
int argc,
|
||||||
|
va_list ap);
|
||||||
|
int _ssh_buffer_pack(struct ssh_buffer_struct *buffer,
|
||||||
|
const char *format,
|
||||||
|
int argc,
|
||||||
|
...);
|
||||||
|
#define ssh_buffer_pack(buffer, format, ...) \
|
||||||
|
_ssh_buffer_pack((buffer), (format), __VA_NARG__(__VA_ARGS__), __VA_ARGS__, SSH_BUFFER_PACK_END)
|
||||||
|
|
||||||
|
int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||||
|
const char *format, int argc,
|
||||||
|
va_list ap);
|
||||||
|
int _ssh_buffer_unpack(struct ssh_buffer_struct *buffer,
|
||||||
|
const char *format,
|
||||||
|
int argc,
|
||||||
|
...);
|
||||||
|
#define ssh_buffer_unpack(buffer, format, ...) \
|
||||||
|
_ssh_buffer_unpack((buffer), (format), __VA_NARG__(__VA_ARGS__), __VA_ARGS__, SSH_BUFFER_PACK_END)
|
||||||
|
|
||||||
int buffer_prepend_data(ssh_buffer buffer, const void *data, uint32_t len);
|
int buffer_prepend_data(ssh_buffer buffer, const void *data, uint32_t len);
|
||||||
int buffer_add_buffer(ssh_buffer buffer, ssh_buffer source);
|
int buffer_add_buffer(ssh_buffer buffer, ssh_buffer source);
|
||||||
int buffer_reinit(ssh_buffer buffer);
|
int ssh_buffer_reinit(ssh_buffer buffer);
|
||||||
|
|
||||||
/* buffer_get_rest returns a pointer to the current position into the buffer */
|
/* buffer_get_rest returns a pointer to the current position into the buffer */
|
||||||
void *buffer_get_rest(ssh_buffer buffer);
|
void *buffer_get_rest(ssh_buffer buffer);
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ typedef struct ssh_callbacks_struct *ssh_callbacks;
|
|||||||
* @param user User that wants to authenticate
|
* @param user User that wants to authenticate
|
||||||
* @param password Password used for authentication
|
* @param password Password used for authentication
|
||||||
* @param userdata Userdata to be passed to the callback function.
|
* @param userdata Userdata to be passed to the callback function.
|
||||||
* @returns SSH_AUTH_OK Authentication is accepted.
|
* @returns SSH_AUTH_SUCCESS Authentication is accepted.
|
||||||
* @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed.
|
* @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed.
|
||||||
* @returns SSH_AUTH_DENIED Authentication failed.
|
* @returns SSH_AUTH_DENIED Authentication failed.
|
||||||
*/
|
*/
|
||||||
@@ -179,7 +179,7 @@ typedef int (*ssh_auth_password_callback) (ssh_session session, const char *user
|
|||||||
* @param session Current session handler
|
* @param session Current session handler
|
||||||
* @param user User that wants to authenticate
|
* @param user User that wants to authenticate
|
||||||
* @param userdata Userdata to be passed to the callback function.
|
* @param userdata Userdata to be passed to the callback function.
|
||||||
* @returns SSH_AUTH_OK Authentication is accepted.
|
* @returns SSH_AUTH_SUCCESS Authentication is accepted.
|
||||||
* @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed.
|
* @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed.
|
||||||
* @returns SSH_AUTH_DENIED Authentication failed.
|
* @returns SSH_AUTH_DENIED Authentication failed.
|
||||||
*/
|
*/
|
||||||
@@ -191,7 +191,7 @@ typedef int (*ssh_auth_none_callback) (ssh_session session, const char *user, vo
|
|||||||
* @param user Username of the user (can be spoofed)
|
* @param user Username of the user (can be spoofed)
|
||||||
* @param principal Authenticated principal of the user, including realm.
|
* @param principal Authenticated principal of the user, including realm.
|
||||||
* @param userdata Userdata to be passed to the callback function.
|
* @param userdata Userdata to be passed to the callback function.
|
||||||
* @returns SSH_AUTH_OK Authentication is accepted.
|
* @returns SSH_AUTH_SUCCESS Authentication is accepted.
|
||||||
* @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed.
|
* @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed.
|
||||||
* @returns SSH_AUTH_DENIED Authentication failed.
|
* @returns SSH_AUTH_DENIED Authentication failed.
|
||||||
* @warning Implementations should verify that parameter user matches in some way the principal.
|
* @warning Implementations should verify that parameter user matches in some way the principal.
|
||||||
@@ -209,7 +209,7 @@ typedef int (*ssh_auth_gssapi_mic_callback) (ssh_session session, const char *us
|
|||||||
* SSH_PUBLICKEY_STATE_VALID if the signature is valid. Others values should be
|
* SSH_PUBLICKEY_STATE_VALID if the signature is valid. Others values should be
|
||||||
* replied with a SSH_AUTH_DENIED.
|
* replied with a SSH_AUTH_DENIED.
|
||||||
* @param userdata Userdata to be passed to the callback function.
|
* @param userdata Userdata to be passed to the callback function.
|
||||||
* @returns SSH_AUTH_OK Authentication is accepted.
|
* @returns SSH_AUTH_SUCCESS Authentication is accepted.
|
||||||
* @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed.
|
* @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed.
|
||||||
* @returns SSH_AUTH_DENIED Authentication failed.
|
* @returns SSH_AUTH_DENIED Authentication failed.
|
||||||
*/
|
*/
|
||||||
@@ -495,6 +495,8 @@ LIBSSH_API int ssh_set_callbacks(ssh_session session, ssh_callbacks cb);
|
|||||||
* @param len the length of the data
|
* @param len the length of the data
|
||||||
* @param is_stderr is 0 for stdout or 1 for stderr
|
* @param is_stderr is 0 for stdout or 1 for stderr
|
||||||
* @param userdata Userdata to be passed to the callback function.
|
* @param userdata Userdata to be passed to the callback function.
|
||||||
|
* @returns number of bytes processed by the callee. The remaining bytes will
|
||||||
|
* be sent in the next callback message, when more data is available.
|
||||||
*/
|
*/
|
||||||
typedef int (*ssh_channel_data_callback) (ssh_session session,
|
typedef int (*ssh_channel_data_callback) (ssh_session session,
|
||||||
ssh_channel channel,
|
ssh_channel channel,
|
||||||
@@ -788,14 +790,21 @@ struct ssh_threads_callbacks_struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief sets the thread callbacks necessary if your program is using
|
* @brief Set the thread callbacks structure.
|
||||||
* libssh in a multithreaded fashion. This function must be called first,
|
*
|
||||||
* outside of any threading context (in your main() for instance), before
|
* This is necessary if your program is using libssh in a multithreaded fashion.
|
||||||
* ssh_init().
|
* This function must be called first, outside of any threading context (in your
|
||||||
* @param cb pointer to a ssh_threads_callbacks_struct structure, which contains
|
* main() function for instance), before you call ssh_init().
|
||||||
* the different callbacks to be set.
|
*
|
||||||
|
* @param[in] cb A pointer to a ssh_threads_callbacks_struct structure, which
|
||||||
|
* contains the different callbacks to be set.
|
||||||
|
*
|
||||||
|
* @returns Always returns SSH_OK.
|
||||||
|
*
|
||||||
* @see ssh_threads_callbacks_struct
|
* @see ssh_threads_callbacks_struct
|
||||||
* @see SSH_THREADS_PTHREAD
|
* @see SSH_THREADS_PTHREAD
|
||||||
|
* @bug libgcrypt 1.6 and bigger backend does not support custom callback.
|
||||||
|
* Using anything else than pthreads here will fail.
|
||||||
*/
|
*/
|
||||||
LIBSSH_API int ssh_threads_set_callbacks(struct ssh_threads_callbacks_struct
|
LIBSSH_API int ssh_threads_set_callbacks(struct ssh_threads_callbacks_struct
|
||||||
*cb);
|
*cb);
|
||||||
@@ -809,9 +818,13 @@ LIBSSH_API int ssh_threads_set_callbacks(struct ssh_threads_callbacks_struct
|
|||||||
LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_pthread(void);
|
LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_pthread(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief returns a pointer on the noop threads callbacks, to be used with
|
* @brief Get the noop threads callbacks structure
|
||||||
* ssh_threads_set_callbacks. These callbacks do nothing and are being used by
|
*
|
||||||
* default.
|
* This can be used with ssh_threads_set_callbacks. These callbacks do nothing
|
||||||
|
* and are being used by default.
|
||||||
|
*
|
||||||
|
* @return Always returns a valid pointer to the noop callbacks structure.
|
||||||
|
*
|
||||||
* @see ssh_threads_set_callbacks
|
* @see ssh_threads_set_callbacks
|
||||||
*/
|
*/
|
||||||
LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_noop(void);
|
LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_noop(void);
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ struct ssh_channel_struct {
|
|||||||
int exit_status;
|
int exit_status;
|
||||||
enum ssh_channel_request_state_e request_state;
|
enum ssh_channel_request_state_e request_state;
|
||||||
ssh_channel_callbacks callbacks;
|
ssh_channel_callbacks callbacks;
|
||||||
|
/* counters */
|
||||||
|
ssh_counter counter;
|
||||||
};
|
};
|
||||||
|
|
||||||
SSH_PACKET_CALLBACK(ssh_packet_channel_open_conf);
|
SSH_PACKET_CALLBACK(ssh_packet_channel_open_conf);
|
||||||
@@ -96,8 +98,6 @@ int channel_default_bufferize(ssh_channel channel, void *data, int len,
|
|||||||
int ssh_channel_flush(ssh_channel channel);
|
int ssh_channel_flush(ssh_channel channel);
|
||||||
uint32_t ssh_channel_new_id(ssh_session session);
|
uint32_t ssh_channel_new_id(ssh_session session);
|
||||||
ssh_channel ssh_channel_from_local(ssh_session session, uint32_t id);
|
ssh_channel ssh_channel_from_local(ssh_session session, uint32_t id);
|
||||||
int channel_write_common(ssh_channel channel, const void *data,
|
|
||||||
uint32_t len, int is_stderr);
|
|
||||||
void ssh_channel_do_free(ssh_channel channel);
|
void ssh_channel_do_free(ssh_channel channel);
|
||||||
#ifdef WITH_SSH1
|
#ifdef WITH_SSH1
|
||||||
SSH_PACKET_CALLBACK(ssh_packet_data1);
|
SSH_PACKET_CALLBACK(ssh_packet_data1);
|
||||||
|
|||||||
@@ -44,6 +44,9 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "libssh/ecdh.h"
|
#include "libssh/ecdh.h"
|
||||||
#include "libssh/kex.h"
|
#include "libssh/kex.h"
|
||||||
|
#include "libssh/curve25519.h"
|
||||||
|
|
||||||
|
#define DIGEST_MAX_LEN 64
|
||||||
|
|
||||||
enum ssh_key_exchange_e {
|
enum ssh_key_exchange_e {
|
||||||
/* diffie-hellman-group1-sha1 */
|
/* diffie-hellman-group1-sha1 */
|
||||||
@@ -51,7 +54,9 @@ enum ssh_key_exchange_e {
|
|||||||
/* diffie-hellman-group14-sha1 */
|
/* diffie-hellman-group14-sha1 */
|
||||||
SSH_KEX_DH_GROUP14_SHA1,
|
SSH_KEX_DH_GROUP14_SHA1,
|
||||||
/* ecdh-sha2-nistp256 */
|
/* ecdh-sha2-nistp256 */
|
||||||
SSH_KEX_ECDH_SHA2_NISTP256
|
SSH_KEX_ECDH_SHA2_NISTP256,
|
||||||
|
/* curve25519-sha256@libssh.org */
|
||||||
|
SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ssh_crypto_struct {
|
struct ssh_crypto_struct {
|
||||||
@@ -60,6 +65,11 @@ struct ssh_crypto_struct {
|
|||||||
EC_KEY *ecdh_privkey;
|
EC_KEY *ecdh_privkey;
|
||||||
ssh_string ecdh_client_pubkey;
|
ssh_string ecdh_client_pubkey;
|
||||||
ssh_string ecdh_server_pubkey;
|
ssh_string ecdh_server_pubkey;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CURVE25519
|
||||||
|
ssh_curve25519_privkey curve25519_privkey;
|
||||||
|
ssh_curve25519_pubkey curve25519_client_pubkey;
|
||||||
|
ssh_curve25519_pubkey curve25519_server_pubkey;
|
||||||
#endif
|
#endif
|
||||||
ssh_string dh_server_signature; /* information used by dh_handshake. */
|
ssh_string dh_server_signature; /* information used by dh_handshake. */
|
||||||
size_t digest_len; /* len of all the fields below */
|
size_t digest_len; /* len of all the fields below */
|
||||||
@@ -71,8 +81,10 @@ struct ssh_crypto_struct {
|
|||||||
unsigned char *encryptkey;
|
unsigned char *encryptkey;
|
||||||
unsigned char *encryptMAC;
|
unsigned char *encryptMAC;
|
||||||
unsigned char *decryptMAC;
|
unsigned char *decryptMAC;
|
||||||
unsigned char hmacbuf[EVP_MAX_MD_SIZE];
|
unsigned char hmacbuf[DIGEST_MAX_LEN];
|
||||||
struct ssh_cipher_struct *in_cipher, *out_cipher; /* the cipher structures/objects */
|
struct ssh_cipher_struct *in_cipher, *out_cipher; /* the cipher structures/objects */
|
||||||
|
enum ssh_hmac_e in_hmac, out_hmac; /* the MAC algorithms used */
|
||||||
|
|
||||||
ssh_string server_pubkey;
|
ssh_string server_pubkey;
|
||||||
const char *server_pubkey_type;
|
const char *server_pubkey_type;
|
||||||
int do_compress_out; /* idem */
|
int do_compress_out; /* idem */
|
||||||
@@ -103,9 +115,9 @@ struct ssh_cipher_struct {
|
|||||||
/* sets the new key for immediate use */
|
/* sets the new key for immediate use */
|
||||||
int (*set_encrypt_key)(struct ssh_cipher_struct *cipher, void *key, void *IV);
|
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);
|
int (*set_decrypt_key)(struct ssh_cipher_struct *cipher, void *key, void *IV);
|
||||||
void (*cbc_encrypt)(struct ssh_cipher_struct *cipher, void *in, void *out,
|
void (*encrypt)(struct ssh_cipher_struct *cipher, void *in, void *out,
|
||||||
unsigned long len);
|
unsigned long len);
|
||||||
void (*cbc_decrypt)(struct ssh_cipher_struct *cipher, void *in, void *out,
|
void (*decrypt)(struct ssh_cipher_struct *cipher, void *in, void *out,
|
||||||
unsigned long len);
|
unsigned long len);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
57
include/libssh/curve25519.h
Normal file
57
include/libssh/curve25519.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the SSH Library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 by Aris Adamantiadis <aris@badcode.be>
|
||||||
|
*
|
||||||
|
* 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,
|
||||||
|
* version 2.1 of the License.
|
||||||
|
*
|
||||||
|
* 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 CURVE25519_H_
|
||||||
|
#define CURVE25519_H_
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "libssh.h"
|
||||||
|
|
||||||
|
#ifdef WITH_NACL
|
||||||
|
|
||||||
|
#include <nacl/crypto_scalarmult_curve25519.h>
|
||||||
|
#define CURVE25519_PUBKEY_SIZE crypto_scalarmult_curve25519_BYTES
|
||||||
|
#define CURVE25519_PRIVKEY_SIZE crypto_scalarmult_curve25519_SCALARBYTES
|
||||||
|
#define crypto_scalarmult_base crypto_scalarmult_curve25519_base
|
||||||
|
#define crypto_scalarmult crypto_scalarmult_curve25519
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define CURVE25519_PUBKEY_SIZE 32
|
||||||
|
#define CURVE25519_PRIVKEY_SIZE 32
|
||||||
|
int crypto_scalarmult_base(unsigned char *q, const unsigned char *n);
|
||||||
|
int crypto_scalarmult(unsigned char *q, const unsigned char *n, const unsigned char *p);
|
||||||
|
#endif /* WITH_NACL */
|
||||||
|
|
||||||
|
#ifdef HAVE_ECC
|
||||||
|
#define HAVE_CURVE25519 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef unsigned char ssh_curve25519_pubkey[CURVE25519_PUBKEY_SIZE];
|
||||||
|
typedef unsigned char ssh_curve25519_privkey[CURVE25519_PRIVKEY_SIZE];
|
||||||
|
|
||||||
|
|
||||||
|
int ssh_client_curve25519_init(ssh_session session);
|
||||||
|
int ssh_client_curve25519_reply(ssh_session session, ssh_buffer packet);
|
||||||
|
|
||||||
|
#ifdef WITH_SERVER
|
||||||
|
int ssh_server_curve25519_init(ssh_session session, ssh_buffer packet);
|
||||||
|
#endif /* WITH_SERVER */
|
||||||
|
|
||||||
|
#endif /* CURVE25519_H_ */
|
||||||
@@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
#include "libssh/crypto.h"
|
#include "libssh/crypto.h"
|
||||||
|
|
||||||
void ssh_print_bignum(const char *which,bignum num);
|
|
||||||
int dh_generate_e(ssh_session session);
|
int dh_generate_e(ssh_session session);
|
||||||
int dh_generate_f(ssh_session session);
|
int dh_generate_f(ssh_session session);
|
||||||
int dh_generate_x(ssh_session session);
|
int dh_generate_x(ssh_session session);
|
||||||
@@ -48,8 +47,5 @@ int make_sessionid(ssh_session session);
|
|||||||
int hashbufin_add_cookie(ssh_session session, unsigned char *cookie);
|
int hashbufin_add_cookie(ssh_session session, unsigned char *cookie);
|
||||||
int hashbufout_add_cookie(ssh_session session);
|
int hashbufout_add_cookie(ssh_session session);
|
||||||
int generate_session_keys(ssh_session session);
|
int generate_session_keys(ssh_session session);
|
||||||
bignum make_string_bn(ssh_string string);
|
|
||||||
ssh_string make_bignum_string(bignum num);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* DH_H_ */
|
#endif /* DH_H_ */
|
||||||
|
|||||||
@@ -26,7 +26,9 @@
|
|||||||
#ifdef HAVE_LIBCRYPTO
|
#ifdef HAVE_LIBCRYPTO
|
||||||
#ifdef HAVE_OPENSSL_ECDH_H
|
#ifdef HAVE_OPENSSL_ECDH_H
|
||||||
|
|
||||||
#define HAVE_ECDH
|
#ifdef HAVE_ECC
|
||||||
|
#define HAVE_ECDH 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* HAVE_OPENSSL_ECDH_H */
|
#endif /* HAVE_OPENSSL_ECDH_H */
|
||||||
#endif /* HAVE_LIBCRYPTO */
|
#endif /* HAVE_LIBCRYPTO */
|
||||||
|
|||||||
79
include/libssh/ed25519.h
Normal file
79
include/libssh/ed25519.h
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the SSH Library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 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 ED25519_H_
|
||||||
|
#define ED25519_H_
|
||||||
|
#include "libssh/priv.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup ed25519 ed25519 API
|
||||||
|
* @internal
|
||||||
|
* @brief API for DJB's ed25519
|
||||||
|
*
|
||||||
|
* @{ */
|
||||||
|
|
||||||
|
#define ED25519_PK_LEN 32
|
||||||
|
#define ED25519_SK_LEN 64
|
||||||
|
#define ED25519_SIG_LEN 64
|
||||||
|
|
||||||
|
typedef uint8_t ed25519_pubkey[ED25519_PK_LEN];
|
||||||
|
typedef uint8_t ed25519_privkey[ED25519_SK_LEN];
|
||||||
|
typedef uint8_t ed25519_signature[ED25519_SIG_LEN];
|
||||||
|
|
||||||
|
/** @internal
|
||||||
|
* @brief generate an ed25519 key pair
|
||||||
|
* @param[out] pk generated public key
|
||||||
|
* @param[out] sk generated secret key
|
||||||
|
* @return 0 on success, -1 on error.
|
||||||
|
* */
|
||||||
|
int crypto_sign_ed25519_keypair(ed25519_pubkey pk, ed25519_privkey sk);
|
||||||
|
|
||||||
|
/** @internal
|
||||||
|
* @brief sign a message with ed25519
|
||||||
|
* @param[out] sm location to store the signed message.
|
||||||
|
* Its length should be mlen + 64.
|
||||||
|
* @param[out] smlen pointer to the size of the signed message
|
||||||
|
* @param[in] m message to be signed
|
||||||
|
* @param[in] mlen length of the message to be signed
|
||||||
|
* @param[in] sk secret key to sign the message with
|
||||||
|
* @return 0 on success.
|
||||||
|
*/
|
||||||
|
int crypto_sign_ed25519(
|
||||||
|
unsigned char *sm,unsigned long long *smlen,
|
||||||
|
const unsigned char *m,unsigned long long mlen,
|
||||||
|
const ed25519_privkey sk);
|
||||||
|
|
||||||
|
/** @internal
|
||||||
|
* @brief "open" and verify the signature of a signed message
|
||||||
|
* @param[out] m location to store the verified message.
|
||||||
|
* Its length should be equal to smlen.
|
||||||
|
* @param[out] mlen pointer to the size of the verified message
|
||||||
|
* @param[in] sm signed message to verify
|
||||||
|
* @param[in] smlen length of the signed message to verify
|
||||||
|
* @param[in] pk public key used to sign the message
|
||||||
|
* @returns 0 on success (supposedly).
|
||||||
|
*/
|
||||||
|
int crypto_sign_ed25519_open(
|
||||||
|
unsigned char *m,unsigned long long *mlen,
|
||||||
|
const unsigned char *sm,unsigned long long smlen,
|
||||||
|
const ed25519_pubkey pk);
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
#endif /* ED25519_H_ */
|
||||||
68
include/libssh/fe25519.h
Normal file
68
include/libssh/fe25519.h
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
/* $OpenBSD: fe25519.h,v 1.3 2013/12/09 11:03:45 markus Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange,
|
||||||
|
* Peter Schwabe, Bo-Yin Yang.
|
||||||
|
* Copied from supercop-20130419/crypto_sign/ed25519/ref/fe25519.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FE25519_H
|
||||||
|
#define FE25519_H
|
||||||
|
|
||||||
|
#include "libssh/priv.h"
|
||||||
|
|
||||||
|
#define fe25519 crypto_sign_ed25519_ref_fe25519
|
||||||
|
#define fe25519_freeze crypto_sign_ed25519_ref_fe25519_freeze
|
||||||
|
#define fe25519_unpack crypto_sign_ed25519_ref_fe25519_unpack
|
||||||
|
#define fe25519_pack crypto_sign_ed25519_ref_fe25519_pack
|
||||||
|
#define fe25519_iszero crypto_sign_ed25519_ref_fe25519_iszero
|
||||||
|
#define fe25519_iseq_vartime crypto_sign_ed25519_ref_fe25519_iseq_vartime
|
||||||
|
#define fe25519_cmov crypto_sign_ed25519_ref_fe25519_cmov
|
||||||
|
#define fe25519_setone crypto_sign_ed25519_ref_fe25519_setone
|
||||||
|
#define fe25519_setzero crypto_sign_ed25519_ref_fe25519_setzero
|
||||||
|
#define fe25519_neg crypto_sign_ed25519_ref_fe25519_neg
|
||||||
|
#define fe25519_getparity crypto_sign_ed25519_ref_fe25519_getparity
|
||||||
|
#define fe25519_add crypto_sign_ed25519_ref_fe25519_add
|
||||||
|
#define fe25519_sub crypto_sign_ed25519_ref_fe25519_sub
|
||||||
|
#define fe25519_mul crypto_sign_ed25519_ref_fe25519_mul
|
||||||
|
#define fe25519_square crypto_sign_ed25519_ref_fe25519_square
|
||||||
|
#define fe25519_invert crypto_sign_ed25519_ref_fe25519_invert
|
||||||
|
#define fe25519_pow2523 crypto_sign_ed25519_ref_fe25519_pow2523
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t v[32];
|
||||||
|
} fe25519;
|
||||||
|
|
||||||
|
void fe25519_freeze(fe25519 *r);
|
||||||
|
|
||||||
|
void fe25519_unpack(fe25519 *r, const unsigned char x[32]);
|
||||||
|
|
||||||
|
void fe25519_pack(unsigned char r[32], const fe25519 *x);
|
||||||
|
|
||||||
|
int fe25519_iszero(const fe25519 *x);
|
||||||
|
|
||||||
|
int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y);
|
||||||
|
|
||||||
|
void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b);
|
||||||
|
|
||||||
|
void fe25519_setone(fe25519 *r);
|
||||||
|
|
||||||
|
void fe25519_setzero(fe25519 *r);
|
||||||
|
|
||||||
|
void fe25519_neg(fe25519 *r, const fe25519 *x);
|
||||||
|
|
||||||
|
unsigned char fe25519_getparity(const fe25519 *x);
|
||||||
|
|
||||||
|
void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y);
|
||||||
|
|
||||||
|
void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y);
|
||||||
|
|
||||||
|
void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y);
|
||||||
|
|
||||||
|
void fe25519_square(fe25519 *r, const fe25519 *x);
|
||||||
|
|
||||||
|
void fe25519_invert(fe25519 *r, const fe25519 *x);
|
||||||
|
|
||||||
|
void fe25519_pow2523(fe25519 *r, const fe25519 *x);
|
||||||
|
|
||||||
|
#endif
|
||||||
43
include/libssh/ge25519.h
Normal file
43
include/libssh/ge25519.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/* $OpenBSD: ge25519.h,v 1.3 2013/12/09 11:03:45 markus Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange,
|
||||||
|
* Peter Schwabe, Bo-Yin Yang.
|
||||||
|
* Copied from supercop-20130419/crypto_sign/ed25519/ref/ge25519.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GE25519_H
|
||||||
|
#define GE25519_H
|
||||||
|
|
||||||
|
#include "fe25519.h"
|
||||||
|
#include "sc25519.h"
|
||||||
|
|
||||||
|
#define ge25519 crypto_sign_ed25519_ref_ge25519
|
||||||
|
#define ge25519_base crypto_sign_ed25519_ref_ge25519_base
|
||||||
|
#define ge25519_unpackneg_vartime crypto_sign_ed25519_ref_unpackneg_vartime
|
||||||
|
#define ge25519_pack crypto_sign_ed25519_ref_pack
|
||||||
|
#define ge25519_isneutral_vartime crypto_sign_ed25519_ref_isneutral_vartime
|
||||||
|
#define ge25519_double_scalarmult_vartime crypto_sign_ed25519_ref_double_scalarmult_vartime
|
||||||
|
#define ge25519_scalarmult_base crypto_sign_ed25519_ref_scalarmult_base
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
fe25519 x;
|
||||||
|
fe25519 y;
|
||||||
|
fe25519 z;
|
||||||
|
fe25519 t;
|
||||||
|
} ge25519;
|
||||||
|
|
||||||
|
const ge25519 ge25519_base;
|
||||||
|
|
||||||
|
int ge25519_unpackneg_vartime(ge25519 *r, const unsigned char p[32]);
|
||||||
|
|
||||||
|
void ge25519_pack(unsigned char r[32], const ge25519 *p);
|
||||||
|
|
||||||
|
int ge25519_isneutral_vartime(const ge25519 *p);
|
||||||
|
|
||||||
|
void ge25519_double_scalarmult_vartime(ge25519 *r, const ge25519 *p1, const sc25519 *s1, const ge25519 *p2, const sc25519 *s2);
|
||||||
|
|
||||||
|
void ge25519_scalarmult_base(ge25519 *r, const sc25519 *s);
|
||||||
|
|
||||||
|
#endif
|
||||||
27
include/libssh/knownhosts.h
Normal file
27
include/libssh/knownhosts.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the SSH Library
|
||||||
|
*
|
||||||
|
* Copyright (c) 20014 by Aris Adamantiadis <aris@badcode.be>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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 KNOWNHOSTS_H_
|
||||||
|
#define KNOWNHOSTS_H_
|
||||||
|
|
||||||
|
char **ssh_knownhosts_algorithms(ssh_session session);
|
||||||
|
|
||||||
|
#endif /* KNOWNHOSTS_H_ */
|
||||||
@@ -42,51 +42,51 @@ LIBSSH_API int ssh_userauth_autopubkey(ssh_session session, const char *passphra
|
|||||||
LIBSSH_API int ssh_userauth_privatekey_file(ssh_session session, const char *username,
|
LIBSSH_API int ssh_userauth_privatekey_file(ssh_session session, const char *username,
|
||||||
const char *filename, const char *passphrase);
|
const char *filename, const char *passphrase);
|
||||||
|
|
||||||
LIBSSH_API void buffer_free(ssh_buffer buffer);
|
SSH_DEPRECATED LIBSSH_API void buffer_free(ssh_buffer buffer);
|
||||||
LIBSSH_API void *buffer_get(ssh_buffer buffer);
|
SSH_DEPRECATED LIBSSH_API void *buffer_get(ssh_buffer buffer);
|
||||||
LIBSSH_API uint32_t buffer_get_len(ssh_buffer buffer);
|
SSH_DEPRECATED LIBSSH_API uint32_t buffer_get_len(ssh_buffer buffer);
|
||||||
LIBSSH_API ssh_buffer buffer_new(void);
|
SSH_DEPRECATED LIBSSH_API ssh_buffer buffer_new(void);
|
||||||
|
|
||||||
LIBSSH_API ssh_channel channel_accept_x11(ssh_channel channel, int timeout_ms);
|
SSH_DEPRECATED LIBSSH_API ssh_channel channel_accept_x11(ssh_channel channel, int timeout_ms);
|
||||||
LIBSSH_API int channel_change_pty_size(ssh_channel channel,int cols,int rows);
|
SSH_DEPRECATED LIBSSH_API int channel_change_pty_size(ssh_channel channel,int cols,int rows);
|
||||||
LIBSSH_API ssh_channel channel_forward_accept(ssh_session session, int timeout_ms);
|
SSH_DEPRECATED LIBSSH_API ssh_channel channel_forward_accept(ssh_session session, int timeout_ms);
|
||||||
LIBSSH_API int channel_close(ssh_channel channel);
|
SSH_DEPRECATED LIBSSH_API int channel_close(ssh_channel channel);
|
||||||
LIBSSH_API int channel_forward_cancel(ssh_session session, const char *address, int port);
|
SSH_DEPRECATED LIBSSH_API int channel_forward_cancel(ssh_session session, const char *address, int port);
|
||||||
LIBSSH_API int channel_forward_listen(ssh_session session, const char *address, int port, int *bound_port);
|
SSH_DEPRECATED LIBSSH_API int channel_forward_listen(ssh_session session, const char *address, int port, int *bound_port);
|
||||||
LIBSSH_API void channel_free(ssh_channel channel);
|
SSH_DEPRECATED LIBSSH_API void channel_free(ssh_channel channel);
|
||||||
LIBSSH_API int channel_get_exit_status(ssh_channel channel);
|
SSH_DEPRECATED LIBSSH_API int channel_get_exit_status(ssh_channel channel);
|
||||||
LIBSSH_API ssh_session channel_get_session(ssh_channel channel);
|
SSH_DEPRECATED LIBSSH_API ssh_session channel_get_session(ssh_channel channel);
|
||||||
LIBSSH_API int channel_is_closed(ssh_channel channel);
|
SSH_DEPRECATED LIBSSH_API int channel_is_closed(ssh_channel channel);
|
||||||
LIBSSH_API int channel_is_eof(ssh_channel channel);
|
SSH_DEPRECATED LIBSSH_API int channel_is_eof(ssh_channel channel);
|
||||||
LIBSSH_API int channel_is_open(ssh_channel channel);
|
SSH_DEPRECATED LIBSSH_API int channel_is_open(ssh_channel channel);
|
||||||
LIBSSH_API ssh_channel channel_new(ssh_session session);
|
SSH_DEPRECATED LIBSSH_API ssh_channel channel_new(ssh_session session);
|
||||||
LIBSSH_API int channel_open_forward(ssh_channel channel, const char *remotehost,
|
SSH_DEPRECATED LIBSSH_API int channel_open_forward(ssh_channel channel, const char *remotehost,
|
||||||
int remoteport, const char *sourcehost, int localport);
|
int remoteport, const char *sourcehost, int localport);
|
||||||
LIBSSH_API int channel_open_session(ssh_channel channel);
|
SSH_DEPRECATED LIBSSH_API int channel_open_session(ssh_channel channel);
|
||||||
LIBSSH_API int channel_poll(ssh_channel channel, int is_stderr);
|
SSH_DEPRECATED LIBSSH_API int channel_poll(ssh_channel channel, int is_stderr);
|
||||||
LIBSSH_API int channel_read(ssh_channel channel, void *dest, uint32_t count, int is_stderr);
|
SSH_DEPRECATED LIBSSH_API int channel_read(ssh_channel channel, void *dest, uint32_t count, int is_stderr);
|
||||||
|
|
||||||
LIBSSH_API int channel_read_buffer(ssh_channel channel, ssh_buffer buffer, uint32_t count,
|
SSH_DEPRECATED LIBSSH_API int channel_read_buffer(ssh_channel channel, ssh_buffer buffer, uint32_t count,
|
||||||
int is_stderr);
|
int is_stderr);
|
||||||
|
|
||||||
LIBSSH_API int channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count,
|
SSH_DEPRECATED LIBSSH_API int channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count,
|
||||||
int is_stderr);
|
int is_stderr);
|
||||||
LIBSSH_API int channel_request_env(ssh_channel channel, const char *name, const char *value);
|
SSH_DEPRECATED LIBSSH_API int channel_request_env(ssh_channel channel, const char *name, const char *value);
|
||||||
LIBSSH_API int channel_request_exec(ssh_channel channel, const char *cmd);
|
SSH_DEPRECATED LIBSSH_API int channel_request_exec(ssh_channel channel, const char *cmd);
|
||||||
LIBSSH_API int channel_request_pty(ssh_channel channel);
|
SSH_DEPRECATED LIBSSH_API int channel_request_pty(ssh_channel channel);
|
||||||
LIBSSH_API int channel_request_pty_size(ssh_channel channel, const char *term,
|
SSH_DEPRECATED LIBSSH_API int channel_request_pty_size(ssh_channel channel, const char *term,
|
||||||
int cols, int rows);
|
int cols, int rows);
|
||||||
LIBSSH_API int channel_request_shell(ssh_channel channel);
|
SSH_DEPRECATED LIBSSH_API int channel_request_shell(ssh_channel channel);
|
||||||
LIBSSH_API int channel_request_send_signal(ssh_channel channel, const char *signum);
|
SSH_DEPRECATED LIBSSH_API int channel_request_send_signal(ssh_channel channel, const char *signum);
|
||||||
LIBSSH_API int channel_request_sftp(ssh_channel channel);
|
SSH_DEPRECATED LIBSSH_API int channel_request_sftp(ssh_channel channel);
|
||||||
LIBSSH_API int channel_request_subsystem(ssh_channel channel, const char *subsystem);
|
SSH_DEPRECATED LIBSSH_API int channel_request_subsystem(ssh_channel channel, const char *subsystem);
|
||||||
LIBSSH_API int channel_request_x11(ssh_channel channel, int single_connection, const char *protocol,
|
SSH_DEPRECATED LIBSSH_API int channel_request_x11(ssh_channel channel, int single_connection, const char *protocol,
|
||||||
const char *cookie, int screen_number);
|
const char *cookie, int screen_number);
|
||||||
LIBSSH_API int channel_send_eof(ssh_channel channel);
|
SSH_DEPRECATED LIBSSH_API int channel_send_eof(ssh_channel channel);
|
||||||
LIBSSH_API int channel_select(ssh_channel *readchans, ssh_channel *writechans, ssh_channel *exceptchans, struct
|
SSH_DEPRECATED LIBSSH_API int channel_select(ssh_channel *readchans, ssh_channel *writechans, ssh_channel *exceptchans, struct
|
||||||
timeval * timeout);
|
timeval * timeout);
|
||||||
LIBSSH_API void channel_set_blocking(ssh_channel channel, int blocking);
|
SSH_DEPRECATED LIBSSH_API void channel_set_blocking(ssh_channel channel, int blocking);
|
||||||
LIBSSH_API int channel_write(ssh_channel channel, const void *data, uint32_t len);
|
SSH_DEPRECATED LIBSSH_API int channel_write(ssh_channel channel, const void *data, uint32_t len);
|
||||||
|
|
||||||
LIBSSH_API void privatekey_free(ssh_private_key prv);
|
LIBSSH_API void privatekey_free(ssh_private_key prv);
|
||||||
LIBSSH_API ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
|
LIBSSH_API ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
|
||||||
@@ -107,14 +107,14 @@ LIBSSH_API ssh_string ssh_get_pubkey(ssh_session session);
|
|||||||
LIBSSH_API ssh_message ssh_message_retrieve(ssh_session session, uint32_t packettype);
|
LIBSSH_API ssh_message ssh_message_retrieve(ssh_session session, uint32_t packettype);
|
||||||
LIBSSH_API ssh_public_key ssh_message_auth_publickey(ssh_message msg);
|
LIBSSH_API ssh_public_key ssh_message_auth_publickey(ssh_message msg);
|
||||||
|
|
||||||
LIBSSH_API void string_burn(ssh_string str);
|
SSH_DEPRECATED LIBSSH_API void string_burn(ssh_string str);
|
||||||
LIBSSH_API ssh_string string_copy(ssh_string str);
|
SSH_DEPRECATED LIBSSH_API ssh_string string_copy(ssh_string str);
|
||||||
LIBSSH_API void *string_data(ssh_string str);
|
SSH_DEPRECATED LIBSSH_API void *string_data(ssh_string str);
|
||||||
LIBSSH_API int string_fill(ssh_string str, const void *data, size_t len);
|
SSH_DEPRECATED LIBSSH_API int string_fill(ssh_string str, const void *data, size_t len);
|
||||||
LIBSSH_API void string_free(ssh_string str);
|
SSH_DEPRECATED LIBSSH_API void string_free(ssh_string str);
|
||||||
LIBSSH_API ssh_string string_from_char(const char *what);
|
SSH_DEPRECATED LIBSSH_API ssh_string string_from_char(const char *what);
|
||||||
LIBSSH_API size_t string_len(ssh_string str);
|
SSH_DEPRECATED LIBSSH_API size_t string_len(ssh_string str);
|
||||||
LIBSSH_API ssh_string string_new(size_t size);
|
SSH_DEPRECATED LIBSSH_API ssh_string string_new(size_t size);
|
||||||
LIBSSH_API char *string_to_char(ssh_string str);
|
SSH_DEPRECATED LIBSSH_API char *string_to_char(ssh_string str);
|
||||||
|
|
||||||
#endif /* LEGACY_H_ */
|
#endif /* LEGACY_H_ */
|
||||||
|
|||||||
@@ -36,10 +36,20 @@
|
|||||||
|
|
||||||
typedef SHA_CTX* SHACTX;
|
typedef SHA_CTX* SHACTX;
|
||||||
typedef SHA256_CTX* SHA256CTX;
|
typedef SHA256_CTX* SHA256CTX;
|
||||||
|
typedef SHA512_CTX* SHA384CTX;
|
||||||
|
typedef SHA512_CTX* SHA512CTX;
|
||||||
typedef MD5_CTX* MD5CTX;
|
typedef MD5_CTX* MD5CTX;
|
||||||
typedef HMAC_CTX* HMACCTX;
|
typedef HMAC_CTX* HMACCTX;
|
||||||
|
#ifdef HAVE_ECC
|
||||||
|
typedef EVP_MD_CTX *EVPCTX;
|
||||||
|
#else
|
||||||
|
typedef void *EVPCTX;
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SHA_DIGEST_LEN SHA_DIGEST_LENGTH
|
#define SHA_DIGEST_LEN SHA_DIGEST_LENGTH
|
||||||
|
#define SHA256_DIGEST_LEN SHA256_DIGEST_LENGTH
|
||||||
|
#define SHA384_DIGEST_LEN SHA384_DIGEST_LENGTH
|
||||||
|
#define SHA512_DIGEST_LEN SHA512_DIGEST_LENGTH
|
||||||
#ifdef MD5_DIGEST_LEN
|
#ifdef MD5_DIGEST_LEN
|
||||||
#undef MD5_DIGEST_LEN
|
#undef MD5_DIGEST_LEN
|
||||||
#endif
|
#endif
|
||||||
@@ -79,6 +89,14 @@ SHA256CTX sha256_init(void);
|
|||||||
void sha256_update(SHA256CTX c, const void *data, unsigned long len);
|
void sha256_update(SHA256CTX c, const void *data, unsigned long len);
|
||||||
void sha256_final(unsigned char *md, SHA256CTX c);
|
void sha256_final(unsigned char *md, SHA256CTX c);
|
||||||
|
|
||||||
|
SHA384CTX sha384_init(void);
|
||||||
|
void sha384_update(SHA384CTX c, const void *data, unsigned long len);
|
||||||
|
void sha384_final(unsigned char *md, SHA384CTX c);
|
||||||
|
|
||||||
|
SHA512CTX sha512_init(void);
|
||||||
|
void sha512_update(SHA512CTX c, const void *data, unsigned long len);
|
||||||
|
void sha512_final(unsigned char *md, SHA512CTX c);
|
||||||
|
|
||||||
struct ssh_cipher_struct *ssh_get_ciphertab(void);
|
struct ssh_cipher_struct *ssh_get_ciphertab(void);
|
||||||
|
|
||||||
#endif /* HAVE_LIBCRYPTO */
|
#endif /* HAVE_LIBCRYPTO */
|
||||||
|
|||||||
@@ -27,17 +27,24 @@
|
|||||||
|
|
||||||
#include <gcrypt.h>
|
#include <gcrypt.h>
|
||||||
typedef gcry_md_hd_t SHACTX;
|
typedef gcry_md_hd_t SHACTX;
|
||||||
|
typedef gcry_md_hd_t SHA256CTX;
|
||||||
|
typedef gcry_md_hd_t SHA384CTX;
|
||||||
|
typedef gcry_md_hd_t SHA512CTX;
|
||||||
typedef gcry_md_hd_t MD5CTX;
|
typedef gcry_md_hd_t MD5CTX;
|
||||||
typedef gcry_md_hd_t HMACCTX;
|
typedef gcry_md_hd_t HMACCTX;
|
||||||
|
typedef void *EVPCTX;
|
||||||
#define SHA_DIGEST_LENGTH 20
|
#define SHA_DIGEST_LENGTH 20
|
||||||
#define SHA_DIGEST_LEN SHA_DIGEST_LENGTH
|
#define SHA_DIGEST_LEN SHA_DIGEST_LENGTH
|
||||||
#define MD5_DIGEST_LEN 16
|
#define MD5_DIGEST_LEN 16
|
||||||
#define SHA256_DIGEST_LENGTH 32
|
#define SHA256_DIGEST_LENGTH 32
|
||||||
|
#define SHA256_DIGEST_LEN SHA256_DIGEST_LENGTH
|
||||||
#define SHA384_DIGEST_LENGTH 48
|
#define SHA384_DIGEST_LENGTH 48
|
||||||
|
#define SHA384_DIGEST_LEN SHA384_DIGEST_LENGTH
|
||||||
#define SHA512_DIGEST_LENGTH 64
|
#define SHA512_DIGEST_LENGTH 64
|
||||||
|
#define SHA512_DIGEST_LEN SHA512_DIGEST_LENGTH
|
||||||
|
|
||||||
#ifndef EVP_MAX_MD_SIZE
|
#ifndef EVP_MAX_MD_SIZE
|
||||||
#define EVP_MAX_MD_SIZE 36
|
#define EVP_MAX_MD_SIZE 64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define EVP_DIGEST_LEN EVP_MAX_MD_SIZE
|
#define EVP_DIGEST_LEN EVP_MAX_MD_SIZE
|
||||||
|
|||||||
@@ -58,6 +58,7 @@
|
|||||||
#else /* _MSC_VER */
|
#else /* _MSC_VER */
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#endif /* _MSC_VER */
|
#endif /* _MSC_VER */
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -77,8 +78,8 @@
|
|||||||
|
|
||||||
/* libssh version */
|
/* libssh version */
|
||||||
#define LIBSSH_VERSION_MAJOR 0
|
#define LIBSSH_VERSION_MAJOR 0
|
||||||
#define LIBSSH_VERSION_MINOR 6
|
#define LIBSSH_VERSION_MINOR 7
|
||||||
#define LIBSSH_VERSION_MICRO 0
|
#define LIBSSH_VERSION_MICRO 3
|
||||||
|
|
||||||
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
|
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
|
||||||
LIBSSH_VERSION_MINOR, \
|
LIBSSH_VERSION_MINOR, \
|
||||||
@@ -104,6 +105,13 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct ssh_counter_struct {
|
||||||
|
uint64_t in_bytes;
|
||||||
|
uint64_t out_bytes;
|
||||||
|
uint64_t in_packets;
|
||||||
|
uint64_t out_packets;
|
||||||
|
};
|
||||||
|
typedef struct ssh_counter_struct *ssh_counter;
|
||||||
|
|
||||||
typedef struct ssh_agent_struct* ssh_agent;
|
typedef struct ssh_agent_struct* ssh_agent;
|
||||||
typedef struct ssh_buffer_struct* ssh_buffer;
|
typedef struct ssh_buffer_struct* ssh_buffer;
|
||||||
@@ -208,10 +216,14 @@ enum ssh_publickey_state_e {
|
|||||||
SSH_PUBLICKEY_STATE_WRONG=2
|
SSH_PUBLICKEY_STATE_WRONG=2
|
||||||
};
|
};
|
||||||
|
|
||||||
/* status flags */
|
/* Status flags */
|
||||||
|
/** Socket is closed */
|
||||||
#define SSH_CLOSED 0x01
|
#define SSH_CLOSED 0x01
|
||||||
|
/** Reading to socket won't block */
|
||||||
#define SSH_READ_PENDING 0x02
|
#define SSH_READ_PENDING 0x02
|
||||||
|
/** Session was closed due to an error */
|
||||||
#define SSH_CLOSED_ERROR 0x04
|
#define SSH_CLOSED_ERROR 0x04
|
||||||
|
/** Output buffer not empty */
|
||||||
#define SSH_WRITE_PENDING 0x08
|
#define SSH_WRITE_PENDING 0x08
|
||||||
|
|
||||||
enum ssh_server_known_e {
|
enum ssh_server_known_e {
|
||||||
@@ -241,7 +253,8 @@ enum ssh_keytypes_e{
|
|||||||
SSH_KEYTYPE_DSS=1,
|
SSH_KEYTYPE_DSS=1,
|
||||||
SSH_KEYTYPE_RSA,
|
SSH_KEYTYPE_RSA,
|
||||||
SSH_KEYTYPE_RSA1,
|
SSH_KEYTYPE_RSA1,
|
||||||
SSH_KEYTYPE_ECDSA
|
SSH_KEYTYPE_ECDSA,
|
||||||
|
SSH_KEYTYPE_ED25519
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ssh_keycmp_e {
|
enum ssh_keycmp_e {
|
||||||
@@ -327,7 +340,12 @@ enum ssh_options_e {
|
|||||||
SSH_OPTIONS_COMPRESSION,
|
SSH_OPTIONS_COMPRESSION,
|
||||||
SSH_OPTIONS_COMPRESSION_LEVEL,
|
SSH_OPTIONS_COMPRESSION_LEVEL,
|
||||||
SSH_OPTIONS_KEY_EXCHANGE,
|
SSH_OPTIONS_KEY_EXCHANGE,
|
||||||
SSH_OPTIONS_HOSTKEYS
|
SSH_OPTIONS_HOSTKEYS,
|
||||||
|
SSH_OPTIONS_GSSAPI_SERVER_IDENTITY,
|
||||||
|
SSH_OPTIONS_GSSAPI_CLIENT_IDENTITY,
|
||||||
|
SSH_OPTIONS_GSSAPI_DELEGATE_CREDENTIALS,
|
||||||
|
SSH_OPTIONS_HMAC_C_S,
|
||||||
|
SSH_OPTIONS_HMAC_S_C,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -370,6 +388,7 @@ LIBSSH_API int ssh_channel_open_x11(ssh_channel channel, const char *orig_addr,
|
|||||||
LIBSSH_API int ssh_channel_poll(ssh_channel channel, int is_stderr);
|
LIBSSH_API int ssh_channel_poll(ssh_channel channel, int is_stderr);
|
||||||
LIBSSH_API int ssh_channel_poll_timeout(ssh_channel channel, int timeout, int is_stderr);
|
LIBSSH_API int ssh_channel_poll_timeout(ssh_channel channel, int timeout, int is_stderr);
|
||||||
LIBSSH_API int ssh_channel_read(ssh_channel channel, void *dest, uint32_t count, int is_stderr);
|
LIBSSH_API int ssh_channel_read(ssh_channel channel, void *dest, uint32_t count, int is_stderr);
|
||||||
|
LIBSSH_API int ssh_channel_read_timeout(ssh_channel channel, void *dest, uint32_t count, int is_stderr, int timeout_ms);
|
||||||
LIBSSH_API int ssh_channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count,
|
LIBSSH_API int ssh_channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count,
|
||||||
int is_stderr);
|
int is_stderr);
|
||||||
LIBSSH_API int ssh_channel_request_env(ssh_channel channel, const char *name, const char *value);
|
LIBSSH_API int ssh_channel_request_env(ssh_channel channel, const char *name, const char *value);
|
||||||
@@ -387,6 +406,8 @@ LIBSSH_API int ssh_channel_send_eof(ssh_channel channel);
|
|||||||
LIBSSH_API int ssh_channel_select(ssh_channel *readchans, ssh_channel *writechans, ssh_channel *exceptchans, struct
|
LIBSSH_API int ssh_channel_select(ssh_channel *readchans, ssh_channel *writechans, ssh_channel *exceptchans, struct
|
||||||
timeval * timeout);
|
timeval * timeout);
|
||||||
LIBSSH_API void ssh_channel_set_blocking(ssh_channel channel, int blocking);
|
LIBSSH_API void ssh_channel_set_blocking(ssh_channel channel, int blocking);
|
||||||
|
LIBSSH_API void ssh_channel_set_counter(ssh_channel channel,
|
||||||
|
ssh_counter counter);
|
||||||
LIBSSH_API int ssh_channel_write(ssh_channel channel, const void *data, uint32_t len);
|
LIBSSH_API int ssh_channel_write(ssh_channel channel, const void *data, uint32_t len);
|
||||||
LIBSSH_API uint32_t ssh_channel_window_size(ssh_channel channel);
|
LIBSSH_API uint32_t ssh_channel_window_size(ssh_channel channel);
|
||||||
|
|
||||||
@@ -397,9 +418,19 @@ LIBSSH_API const char *ssh_copyright(void);
|
|||||||
LIBSSH_API void ssh_disconnect(ssh_session session);
|
LIBSSH_API void ssh_disconnect(ssh_session session);
|
||||||
LIBSSH_API char *ssh_dirname (const char *path);
|
LIBSSH_API char *ssh_dirname (const char *path);
|
||||||
LIBSSH_API int ssh_finalize(void);
|
LIBSSH_API int ssh_finalize(void);
|
||||||
LIBSSH_API ssh_channel ssh_forward_accept(ssh_session session, int timeout_ms);
|
|
||||||
LIBSSH_API int ssh_forward_cancel(ssh_session session, const char *address, int port);
|
/* REVERSE PORT FORWARDING */
|
||||||
LIBSSH_API int ssh_forward_listen(ssh_session session, const char *address, int port, int *bound_port);
|
LIBSSH_API ssh_channel ssh_channel_accept_forward(ssh_session session,
|
||||||
|
int timeout_ms,
|
||||||
|
int *destination_port);
|
||||||
|
LIBSSH_API int ssh_channel_cancel_forward(ssh_session session,
|
||||||
|
const char *address,
|
||||||
|
int port);
|
||||||
|
LIBSSH_API int ssh_channel_listen_forward(ssh_session session,
|
||||||
|
const char *address,
|
||||||
|
int port,
|
||||||
|
int *bound_port);
|
||||||
|
|
||||||
LIBSSH_API void ssh_free(ssh_session session);
|
LIBSSH_API void ssh_free(ssh_session session);
|
||||||
LIBSSH_API const char *ssh_get_disconnect_message(ssh_session session);
|
LIBSSH_API const char *ssh_get_disconnect_message(ssh_session session);
|
||||||
LIBSSH_API const char *ssh_get_error(void *error);
|
LIBSSH_API const char *ssh_get_error(void *error);
|
||||||
@@ -408,11 +439,29 @@ LIBSSH_API socket_t ssh_get_fd(ssh_session session);
|
|||||||
LIBSSH_API char *ssh_get_hexa(const unsigned char *what, size_t len);
|
LIBSSH_API char *ssh_get_hexa(const unsigned char *what, size_t len);
|
||||||
LIBSSH_API char *ssh_get_issue_banner(ssh_session session);
|
LIBSSH_API char *ssh_get_issue_banner(ssh_session session);
|
||||||
LIBSSH_API int ssh_get_openssh_version(ssh_session session);
|
LIBSSH_API int ssh_get_openssh_version(ssh_session session);
|
||||||
|
|
||||||
LIBSSH_API int ssh_get_publickey(ssh_session session, ssh_key *key);
|
LIBSSH_API int ssh_get_publickey(ssh_session session, ssh_key *key);
|
||||||
LIBSSH_API int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash);
|
|
||||||
|
enum ssh_publickey_hash_type {
|
||||||
|
SSH_PUBLICKEY_HASH_SHA1,
|
||||||
|
SSH_PUBLICKEY_HASH_MD5
|
||||||
|
};
|
||||||
|
LIBSSH_API int ssh_get_publickey_hash(const ssh_key key,
|
||||||
|
enum ssh_publickey_hash_type type,
|
||||||
|
unsigned char **hash,
|
||||||
|
size_t *hlen);
|
||||||
|
|
||||||
|
/* DEPRECATED FUNCTIONS */
|
||||||
|
SSH_DEPRECATED LIBSSH_API int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash);
|
||||||
|
SSH_DEPRECATED LIBSSH_API ssh_channel ssh_forward_accept(ssh_session session, int timeout_ms);
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
||||||
LIBSSH_API int ssh_get_random(void *where,int len,int strong);
|
LIBSSH_API int ssh_get_random(void *where,int len,int strong);
|
||||||
LIBSSH_API int ssh_get_version(ssh_session session);
|
LIBSSH_API int ssh_get_version(ssh_session session);
|
||||||
LIBSSH_API int ssh_get_status(ssh_session session);
|
LIBSSH_API int ssh_get_status(ssh_session session);
|
||||||
|
LIBSSH_API int ssh_get_poll_flags(ssh_session session);
|
||||||
LIBSSH_API int ssh_init(void);
|
LIBSSH_API int ssh_init(void);
|
||||||
LIBSSH_API int ssh_is_blocking(ssh_session session);
|
LIBSSH_API int ssh_is_blocking(ssh_session session);
|
||||||
LIBSSH_API int ssh_is_connected(ssh_session session);
|
LIBSSH_API int ssh_is_connected(ssh_session session);
|
||||||
@@ -493,6 +542,11 @@ LIBSSH_API int ssh_pki_import_privkey_file(const char *filename,
|
|||||||
ssh_auth_callback auth_fn,
|
ssh_auth_callback auth_fn,
|
||||||
void *auth_data,
|
void *auth_data,
|
||||||
ssh_key *pkey);
|
ssh_key *pkey);
|
||||||
|
LIBSSH_API int ssh_pki_export_privkey_file(const ssh_key privkey,
|
||||||
|
const char *passphrase,
|
||||||
|
ssh_auth_callback auth_fn,
|
||||||
|
void *auth_data,
|
||||||
|
const char *filename);
|
||||||
|
|
||||||
LIBSSH_API int ssh_pki_import_pubkey_base64(const char *b64_key,
|
LIBSSH_API int ssh_pki_import_pubkey_base64(const char *b64_key,
|
||||||
enum ssh_keytypes_e type,
|
enum ssh_keytypes_e type,
|
||||||
@@ -507,6 +561,8 @@ LIBSSH_API int ssh_pki_export_pubkey_base64(const ssh_key key,
|
|||||||
LIBSSH_API int ssh_pki_export_pubkey_file(const ssh_key key,
|
LIBSSH_API int ssh_pki_export_pubkey_file(const ssh_key key,
|
||||||
const char *filename);
|
const char *filename);
|
||||||
|
|
||||||
|
LIBSSH_API const char *ssh_pki_key_ecdsa_name(const ssh_key key);
|
||||||
|
|
||||||
LIBSSH_API void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len);
|
LIBSSH_API void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len);
|
||||||
LIBSSH_API int ssh_send_ignore (ssh_session session, const char *data);
|
LIBSSH_API int ssh_send_ignore (ssh_session session, const char *data);
|
||||||
LIBSSH_API int ssh_send_debug (ssh_session session, const char *message, int always_display);
|
LIBSSH_API int ssh_send_debug (ssh_session session, const char *message, int always_display);
|
||||||
@@ -533,7 +589,10 @@ LIBSSH_API int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socke
|
|||||||
fd_set *readfds, struct timeval *timeout);
|
fd_set *readfds, struct timeval *timeout);
|
||||||
LIBSSH_API int ssh_service_request(ssh_session session, const char *service);
|
LIBSSH_API int ssh_service_request(ssh_session session, const char *service);
|
||||||
LIBSSH_API int ssh_set_agent_channel(ssh_session session, ssh_channel channel);
|
LIBSSH_API int ssh_set_agent_channel(ssh_session session, ssh_channel channel);
|
||||||
|
LIBSSH_API int ssh_set_agent_socket(ssh_session session, socket_t fd);
|
||||||
LIBSSH_API void ssh_set_blocking(ssh_session session, int blocking);
|
LIBSSH_API void ssh_set_blocking(ssh_session session, int blocking);
|
||||||
|
LIBSSH_API void ssh_set_counters(ssh_session session, ssh_counter scounter,
|
||||||
|
ssh_counter rcounter);
|
||||||
LIBSSH_API void ssh_set_fd_except(ssh_session session);
|
LIBSSH_API void ssh_set_fd_except(ssh_session session);
|
||||||
LIBSSH_API void ssh_set_fd_toread(ssh_session session);
|
LIBSSH_API void ssh_set_fd_toread(ssh_session session);
|
||||||
LIBSSH_API void ssh_set_fd_towrite(ssh_session session);
|
LIBSSH_API void ssh_set_fd_towrite(ssh_session session);
|
||||||
@@ -599,7 +658,13 @@ LIBSSH_API int ssh_event_dopoll(ssh_event event, int timeout);
|
|||||||
LIBSSH_API int ssh_event_remove_fd(ssh_event event, socket_t fd);
|
LIBSSH_API int ssh_event_remove_fd(ssh_event event, socket_t fd);
|
||||||
LIBSSH_API int ssh_event_remove_session(ssh_event event, ssh_session session);
|
LIBSSH_API int ssh_event_remove_session(ssh_event event, ssh_session session);
|
||||||
LIBSSH_API void ssh_event_free(ssh_event event);
|
LIBSSH_API void ssh_event_free(ssh_event event);
|
||||||
|
LIBSSH_API const char* ssh_get_clientbanner(ssh_session session);
|
||||||
LIBSSH_API const char* ssh_get_serverbanner(ssh_session session);
|
LIBSSH_API const char* ssh_get_serverbanner(ssh_session session);
|
||||||
|
LIBSSH_API const char* ssh_get_kex_algo(ssh_session session);
|
||||||
|
LIBSSH_API const char* ssh_get_cipher_in(ssh_session session);
|
||||||
|
LIBSSH_API const char* ssh_get_cipher_out(ssh_session session);
|
||||||
|
LIBSSH_API const char* ssh_get_hmac_in(ssh_session session);
|
||||||
|
LIBSSH_API const char* ssh_get_hmac_out(ssh_session session);
|
||||||
|
|
||||||
#ifndef LIBSSH_LEGACY_0_4
|
#ifndef LIBSSH_LEGACY_0_4
|
||||||
#include "libssh/legacy.h"
|
#include "libssh/legacy.h"
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace ssh {
|
namespace ssh {
|
||||||
|
|
||||||
@@ -361,18 +362,18 @@ public:
|
|||||||
* @see ssh_channel_forward_accept
|
* @see ssh_channel_forward_accept
|
||||||
* @see Session::listenForward
|
* @see Session::listenForward
|
||||||
*/
|
*/
|
||||||
Channel *acceptForward(int timeout_ms);
|
inline Channel *acceptForward(int timeout_ms);
|
||||||
/* acceptForward is implemented later in this file */
|
/* implemented outside the class due Channel references */
|
||||||
|
|
||||||
void_throwable cancelForward(const char *address, int port){
|
void_throwable cancelForward(const char *address, int port){
|
||||||
int err=ssh_forward_cancel(c_session, address, port);
|
int err=ssh_channel_cancel_forward(c_session, address, port);
|
||||||
ssh_throw(err);
|
ssh_throw(err);
|
||||||
return_throwable;
|
return_throwable;
|
||||||
}
|
}
|
||||||
|
|
||||||
void_throwable listenForward(const char *address, int port,
|
void_throwable listenForward(const char *address, int port,
|
||||||
int &boundport){
|
int &boundport){
|
||||||
int err=ssh_forward_listen(c_session, address, port, &boundport);
|
int err=ssh_channel_listen_forward(c_session, address, port, &boundport);
|
||||||
ssh_throw(err);
|
ssh_throw(err);
|
||||||
return_throwable;
|
return_throwable;
|
||||||
}
|
}
|
||||||
@@ -480,12 +481,30 @@ public:
|
|||||||
ssh_throw(err);
|
ssh_throw(err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
int read(void *dest, size_t count, bool is_stderr=false){
|
int read(void *dest, size_t count, bool is_stderr){
|
||||||
int err;
|
int err;
|
||||||
/* handle int overflow */
|
/* handle int overflow */
|
||||||
if(count > 0x7fffffff)
|
if(count > 0x7fffffff)
|
||||||
count = 0x7fffffff;
|
count = 0x7fffffff;
|
||||||
err=ssh_channel_read(channel,dest,count,is_stderr);
|
err=ssh_channel_read_timeout(channel,dest,count,is_stderr,-1);
|
||||||
|
ssh_throw(err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
int read(void *dest, size_t count, int timeout){
|
||||||
|
int err;
|
||||||
|
/* handle int overflow */
|
||||||
|
if(count > 0x7fffffff)
|
||||||
|
count = 0x7fffffff;
|
||||||
|
err=ssh_channel_read_timeout(channel,dest,count,false,timeout);
|
||||||
|
ssh_throw(err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
int read(void *dest, size_t count, bool is_stderr=false, int timeout=-1){
|
||||||
|
int err;
|
||||||
|
/* handle int overflow */
|
||||||
|
if(count > 0x7fffffff)
|
||||||
|
count = 0x7fffffff;
|
||||||
|
err=ssh_channel_read_timeout(channel,dest,count,is_stderr,timeout);
|
||||||
ssh_throw(err);
|
ssh_throw(err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -581,10 +600,9 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* This code cannot be put inline due to references to Channel */
|
inline Channel *Session::acceptForward(int timeout_ms){
|
||||||
Channel *Session::acceptForward(int timeout_ms){
|
ssh_channel forward =
|
||||||
ssh_channel forward = ssh_forward_accept(c_session,
|
ssh_channel_accept_forward(c_session, timeout_ms, NULL);
|
||||||
timeout_ms);
|
|
||||||
ssh_throw_null(c_session,forward);
|
ssh_throw_null(c_session,forward);
|
||||||
Channel *newchan = new Channel(*this,forward);
|
Channel *newchan = new Channel(*this,forward);
|
||||||
return newchan;
|
return newchan;
|
||||||
|
|||||||
@@ -76,8 +76,8 @@ struct ssh_channel_request {
|
|||||||
|
|
||||||
/* X11 */
|
/* X11 */
|
||||||
uint8_t x11_single_connection;
|
uint8_t x11_single_connection;
|
||||||
const char *x11_auth_protocol;
|
char *x11_auth_protocol;
|
||||||
const char *x11_auth_cookie;
|
char *x11_auth_cookie;
|
||||||
uint32_t x11_screen_number;
|
uint32_t x11_screen_number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
#ifndef PACKET_H_
|
#ifndef PACKET_H_
|
||||||
#define PACKET_H_
|
#define PACKET_H_
|
||||||
|
|
||||||
|
#include "libssh/wrapper.h"
|
||||||
|
|
||||||
struct ssh_socket_struct;
|
struct ssh_socket_struct;
|
||||||
|
|
||||||
/* this structure should go someday */
|
/* this structure should go someday */
|
||||||
@@ -82,6 +84,6 @@ unsigned char *packet_encrypt(ssh_session session,
|
|||||||
void *packet,
|
void *packet,
|
||||||
unsigned int len);
|
unsigned int len);
|
||||||
int packet_hmac_verify(ssh_session session,ssh_buffer buffer,
|
int packet_hmac_verify(ssh_session session,ssh_buffer buffer,
|
||||||
unsigned char *mac);
|
unsigned char *mac, enum ssh_hmac_e type);
|
||||||
|
|
||||||
#endif /* PACKET_H_ */
|
#endif /* PACKET_H_ */
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#ifndef PKI_H_
|
#ifndef PKI_H_
|
||||||
#define PKI_H_
|
#define PKI_H_
|
||||||
|
|
||||||
|
#include "libssh/priv.h"
|
||||||
#ifdef HAVE_OPENSSL_EC_H
|
#ifdef HAVE_OPENSSL_EC_H
|
||||||
#include <openssl/ec.h>
|
#include <openssl/ec.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -29,6 +30,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "libssh/crypto.h"
|
#include "libssh/crypto.h"
|
||||||
|
#include "libssh/ed25519.h"
|
||||||
|
|
||||||
#define MAX_PUBKEY_SIZE 0x100000 /* 1M */
|
#define MAX_PUBKEY_SIZE 0x100000 /* 1M */
|
||||||
#define MAX_PRIVKEY_SIZE 0x400000 /* 4M */
|
#define MAX_PRIVKEY_SIZE 0x400000 /* 4M */
|
||||||
@@ -55,11 +57,14 @@ struct ssh_key_struct {
|
|||||||
void *ecdsa;
|
void *ecdsa;
|
||||||
#endif /* HAVE_OPENSSL_EC_H */
|
#endif /* HAVE_OPENSSL_EC_H */
|
||||||
#endif
|
#endif
|
||||||
|
ed25519_pubkey *ed25519_pubkey;
|
||||||
|
ed25519_privkey *ed25519_privkey;
|
||||||
void *cert;
|
void *cert;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ssh_signature_struct {
|
struct ssh_signature_struct {
|
||||||
enum ssh_keytypes_e type;
|
enum ssh_keytypes_e type;
|
||||||
|
const char *type_c;
|
||||||
#ifdef HAVE_LIBGCRYPT
|
#ifdef HAVE_LIBGCRYPT
|
||||||
gcry_sexp_t dsa_sig;
|
gcry_sexp_t dsa_sig;
|
||||||
gcry_sexp_t rsa_sig;
|
gcry_sexp_t rsa_sig;
|
||||||
@@ -73,6 +78,7 @@ struct ssh_signature_struct {
|
|||||||
void *ecdsa_sig;
|
void *ecdsa_sig;
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
ed25519_signature *ed25519_sig;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct ssh_signature_struct *ssh_signature;
|
typedef struct ssh_signature_struct *ssh_signature;
|
||||||
|
|||||||
@@ -21,25 +21,43 @@
|
|||||||
#ifndef PKI_PRIV_H_
|
#ifndef PKI_PRIV_H_
|
||||||
#define PKI_PRIV_H_
|
#define PKI_PRIV_H_
|
||||||
|
|
||||||
|
#include "libssh/pki.h"
|
||||||
|
|
||||||
|
/* defined in bcrypt_pbkdf.c */
|
||||||
|
int bcrypt_pbkdf(const char *pass,
|
||||||
|
size_t passlen,
|
||||||
|
const uint8_t *salt,
|
||||||
|
size_t saltlen,
|
||||||
|
uint8_t *key,
|
||||||
|
size_t keylen,
|
||||||
|
unsigned int rounds);
|
||||||
|
|
||||||
#define RSA_HEADER_BEGIN "-----BEGIN RSA PRIVATE KEY-----"
|
#define RSA_HEADER_BEGIN "-----BEGIN RSA PRIVATE KEY-----"
|
||||||
#define RSA_HEADER_END "-----END RSA PRIVATE KEY-----"
|
#define RSA_HEADER_END "-----END RSA PRIVATE KEY-----"
|
||||||
#define DSA_HEADER_BEGIN "-----BEGIN DSA PRIVATE KEY-----"
|
#define DSA_HEADER_BEGIN "-----BEGIN DSA PRIVATE KEY-----"
|
||||||
#define DSA_HEADER_END "-----END DSA PRIVATE KEY-----"
|
#define DSA_HEADER_END "-----END DSA PRIVATE KEY-----"
|
||||||
#define ECDSA_HEADER_BEGIN "-----BEGIN EC PRIVATE KEY-----"
|
#define ECDSA_HEADER_BEGIN "-----BEGIN EC PRIVATE KEY-----"
|
||||||
#define ECDSA_HEADER_END "-----END EC PRIVATE KEY-----"
|
#define ECDSA_HEADER_END "-----END EC PRIVATE KEY-----"
|
||||||
|
#define OPENSSH_HEADER_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----"
|
||||||
|
#define OPENSSH_HEADER_END "-----END OPENSSH PRIVATE KEY-----"
|
||||||
|
/* Magic defined in OpenSSH/PROTOCOL.key */
|
||||||
|
#define OPENSSH_AUTH_MAGIC "openssh-key-v1"
|
||||||
|
|
||||||
#define ssh_pki_log(...) \
|
#define ssh_pki_log(...) \
|
||||||
_ssh_pki_log(__FUNCTION__, __VA_ARGS__)
|
_ssh_log(SSH_LOG_FUNCTIONS, __func__, __VA_ARGS__)
|
||||||
void _ssh_pki_log(const char *function,
|
void _ssh_pki_log(const char *function,
|
||||||
const char *format, ...) PRINTF_ATTRIBUTE(2, 3);
|
const char *format, ...) PRINTF_ATTRIBUTE(2, 3);
|
||||||
|
|
||||||
int pki_key_ecdsa_nid_from_name(const char *name);
|
int pki_key_ecdsa_nid_from_name(const char *name);
|
||||||
|
const char *pki_key_ecdsa_nid_to_name(int nid);
|
||||||
|
|
||||||
/* SSH Key Functions */
|
/* SSH Key Functions */
|
||||||
ssh_key pki_key_dup(const ssh_key key, int demote);
|
ssh_key pki_key_dup(const ssh_key key, int demote);
|
||||||
int pki_key_generate_rsa(ssh_key key, int parameter);
|
int pki_key_generate_rsa(ssh_key key, int parameter);
|
||||||
int pki_key_generate_dss(ssh_key key, int parameter);
|
int pki_key_generate_dss(ssh_key key, int parameter);
|
||||||
int pki_key_generate_ecdsa(ssh_key key, int parameter);
|
int pki_key_generate_ecdsa(ssh_key key, int parameter);
|
||||||
|
int pki_key_generate_ed25519(ssh_key key);
|
||||||
|
|
||||||
int pki_key_compare(const ssh_key k1,
|
int pki_key_compare(const ssh_key k1,
|
||||||
const ssh_key k2,
|
const ssh_key k2,
|
||||||
enum ssh_keycmp_e what);
|
enum ssh_keycmp_e what);
|
||||||
@@ -51,6 +69,11 @@ ssh_key pki_private_key_from_base64(const char *b64_key,
|
|||||||
ssh_auth_callback auth_fn,
|
ssh_auth_callback auth_fn,
|
||||||
void *auth_data);
|
void *auth_data);
|
||||||
|
|
||||||
|
ssh_string pki_private_key_to_pem(const ssh_key key,
|
||||||
|
const char *passphrase,
|
||||||
|
ssh_auth_callback auth_fn,
|
||||||
|
void *auth_data);
|
||||||
|
|
||||||
/* SSH Public Key Functions */
|
/* SSH Public Key Functions */
|
||||||
int pki_pubkey_build_dss(ssh_key key,
|
int pki_pubkey_build_dss(ssh_key key,
|
||||||
ssh_string p,
|
ssh_string p,
|
||||||
@@ -85,4 +108,22 @@ ssh_signature pki_do_sign(const ssh_key privkey,
|
|||||||
ssh_signature pki_do_sign_sessionid(const ssh_key key,
|
ssh_signature pki_do_sign_sessionid(const ssh_key key,
|
||||||
const unsigned char *hash,
|
const unsigned char *hash,
|
||||||
size_t hlen);
|
size_t hlen);
|
||||||
|
int pki_ed25519_sign(const ssh_key privkey, ssh_signature sig,
|
||||||
|
const unsigned char *hash, size_t hlen);
|
||||||
|
int pki_ed25519_verify(const ssh_key pubkey, ssh_signature sig,
|
||||||
|
const unsigned char *hash, size_t hlen);
|
||||||
|
int pki_ed25519_key_cmp(const ssh_key k1,
|
||||||
|
const ssh_key k2,
|
||||||
|
enum ssh_keycmp_e what);
|
||||||
|
int pki_ed25519_key_dup(ssh_key new, const ssh_key key);
|
||||||
|
int pki_ed25519_public_key_to_blob(ssh_buffer buffer, ssh_key key);
|
||||||
|
ssh_string pki_ed25519_sig_to_blob(ssh_signature sig);
|
||||||
|
int pki_ed25519_sig_from_blob(ssh_signature sig, ssh_string sig_blob);
|
||||||
|
|
||||||
|
/* PKI Container OpenSSH */
|
||||||
|
ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
|
||||||
|
const char *passphrase, ssh_auth_callback auth_fn, void *auth_data);
|
||||||
|
ssh_string ssh_pki_openssh_privkey_export(const ssh_key privkey,
|
||||||
|
const char *passphrase, ssh_auth_callback auth_fn, void *auth_data);
|
||||||
|
|
||||||
#endif /* PKI_PRIV_H_ */
|
#endif /* PKI_PRIV_H_ */
|
||||||
|
|||||||
@@ -43,6 +43,16 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif /* !defined(HAVE_STRTOULL) */
|
#endif /* !defined(HAVE_STRTOULL) */
|
||||||
|
|
||||||
|
#ifdef HAVE_BYTESWAP_H
|
||||||
|
#include <byteswap.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef bswap_32
|
||||||
|
#define bswap_32(x) \
|
||||||
|
((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
|
||||||
|
(((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
/* Imitate define of inttypes.h */
|
/* Imitate define of inttypes.h */
|
||||||
@@ -60,14 +70,21 @@
|
|||||||
|
|
||||||
# ifdef _MSC_VER
|
# ifdef _MSC_VER
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
|
# include <stdarg.h> /* va_copy define check */
|
||||||
|
|
||||||
/* On Microsoft compilers define inline to __inline on all others use inline */
|
/* On Microsoft compilers define inline to __inline on all others use inline */
|
||||||
# undef inline
|
# undef inline
|
||||||
# define inline __inline
|
# define inline __inline
|
||||||
|
|
||||||
|
# ifndef va_copy
|
||||||
|
# define va_copy(dest, src) (dest = src)
|
||||||
|
# endif
|
||||||
|
|
||||||
# define strcasecmp _stricmp
|
# define strcasecmp _stricmp
|
||||||
# define strncasecmp _strnicmp
|
# define strncasecmp _strnicmp
|
||||||
# define isblank(ch) ((ch) == ' ' || (ch) == '\t' || (ch) == '\n' || (ch) == '\r')
|
# if ! defined(HAVE_ISBLANK)
|
||||||
|
# define isblank(ch) ((ch) == ' ' || (ch) == '\t' || (ch) == '\n' || (ch) == '\r')
|
||||||
|
# endif
|
||||||
|
|
||||||
# define usleep(X) Sleep(((X)+1000)/1000)
|
# define usleep(X) Sleep(((X)+1000)/1000)
|
||||||
|
|
||||||
@@ -107,27 +124,46 @@
|
|||||||
struct timeval;
|
struct timeval;
|
||||||
int gettimeofday(struct timeval *__p, void *__t);
|
int gettimeofday(struct timeval *__p, void *__t);
|
||||||
|
|
||||||
|
#define _XCLOSESOCKET closesocket
|
||||||
|
|
||||||
#else /* _WIN32 */
|
#else /* _WIN32 */
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#define PRIdS "zd"
|
#define PRIdS "zd"
|
||||||
|
|
||||||
|
#define _XCLOSESOCKET close
|
||||||
|
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
#include "libssh/libssh.h"
|
#include "libssh/libssh.h"
|
||||||
#include "libssh/callbacks.h"
|
#include "libssh/callbacks.h"
|
||||||
|
|
||||||
/* some constants */
|
/* some constants */
|
||||||
|
#ifndef MAX_PACKAT_LEN
|
||||||
#define MAX_PACKET_LEN 262144
|
#define MAX_PACKET_LEN 262144
|
||||||
#define ERROR_BUFFERLEN 1024
|
|
||||||
#define CLIENTBANNER1 "SSH-1.5-libssh-" SSH_STRINGIFY(LIBSSH_VERSION)
|
|
||||||
#define CLIENTBANNER2 "SSH-2.0-libssh-" SSH_STRINGIFY(LIBSSH_VERSION)
|
|
||||||
#define KBDINT_MAX_PROMPT 256 /* more than openssh's :) */
|
|
||||||
|
|
||||||
#ifndef __FUNCTION__
|
|
||||||
#if defined(__SUNPRO_C)
|
|
||||||
#define __FUNCTION__ __func__
|
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef ERROR_BUFFERLEN
|
||||||
|
#define ERROR_BUFFERLEN 1024
|
||||||
|
#endif
|
||||||
|
#ifndef CLIENTBANNER1
|
||||||
|
#define CLIENTBANNER1 "SSH-1.5-libssh-" SSH_STRINGIFY(LIBSSH_VERSION)
|
||||||
|
#endif
|
||||||
|
#ifndef CLIENTBANNER2
|
||||||
|
#define CLIENTBANNER2 "SSH-2.0-libssh-" SSH_STRINGIFY(LIBSSH_VERSION)
|
||||||
|
#endif
|
||||||
|
#ifndef KBDINT_MAX_PROMPT
|
||||||
|
#define KBDINT_MAX_PROMPT 256 /* more than openssh's :) */
|
||||||
|
#endif
|
||||||
|
#ifndef MAX_BUF_SIZE
|
||||||
|
#define MAX_BUF_SIZE 4096
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_COMPILER__FUNC__
|
||||||
|
# ifdef HAVE_COMPILER__FUNCTION__
|
||||||
|
# define __func__ __FUNCTION__
|
||||||
|
# else
|
||||||
|
# error "Your system must provide a __func__ macro"
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_GCC_THREAD_LOCAL_STORAGE)
|
#if defined(HAVE_GCC_THREAD_LOCAL_STORAGE)
|
||||||
@@ -164,7 +200,7 @@ void ssh_log_function(int verbosity,
|
|||||||
const char *function,
|
const char *function,
|
||||||
const char *buffer);
|
const char *buffer);
|
||||||
#define SSH_LOG(priority, ...) \
|
#define SSH_LOG(priority, ...) \
|
||||||
_ssh_log(priority, __FUNCTION__, __VA_ARGS__)
|
_ssh_log(priority, __func__, __VA_ARGS__)
|
||||||
|
|
||||||
/* LEGACY */
|
/* LEGACY */
|
||||||
void ssh_log_common(struct ssh_common_struct *common,
|
void ssh_log_common(struct ssh_common_struct *common,
|
||||||
@@ -182,18 +218,18 @@ struct error_struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define ssh_set_error(error, code, ...) \
|
#define ssh_set_error(error, code, ...) \
|
||||||
_ssh_set_error(error, code, __FUNCTION__, __VA_ARGS__)
|
_ssh_set_error(error, code, __func__, __VA_ARGS__)
|
||||||
void _ssh_set_error(void *error,
|
void _ssh_set_error(void *error,
|
||||||
int code,
|
int code,
|
||||||
const char *function,
|
const char *function,
|
||||||
const char *descr, ...) PRINTF_ATTRIBUTE(4, 5);
|
const char *descr, ...) PRINTF_ATTRIBUTE(4, 5);
|
||||||
|
|
||||||
#define ssh_set_error_oom(error) \
|
#define ssh_set_error_oom(error) \
|
||||||
_ssh_set_error_oom(error, __FUNCTION__)
|
_ssh_set_error_oom(error, __func__)
|
||||||
void _ssh_set_error_oom(void *error, const char *function);
|
void _ssh_set_error_oom(void *error, const char *function);
|
||||||
|
|
||||||
#define ssh_set_error_invalid(error) \
|
#define ssh_set_error_invalid(error) \
|
||||||
_ssh_set_error_invalid(error, __FUNCTION__)
|
_ssh_set_error_invalid(error, __func__)
|
||||||
void _ssh_set_error_invalid(void *error, const char *function);
|
void _ssh_set_error_invalid(void *error, const char *function);
|
||||||
|
|
||||||
|
|
||||||
@@ -223,8 +259,9 @@ int decompress_buffer(ssh_session session,ssh_buffer buf, size_t maxlen);
|
|||||||
/* match.c */
|
/* match.c */
|
||||||
int match_hostname(const char *host, const char *pattern, unsigned int len);
|
int match_hostname(const char *host, const char *pattern, unsigned int len);
|
||||||
|
|
||||||
|
#ifndef MIN
|
||||||
|
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
/** Free memory space */
|
/** Free memory space */
|
||||||
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
|
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
|
||||||
@@ -251,7 +288,7 @@ int match_hostname(const char *host, const char *pattern, unsigned int len);
|
|||||||
/** Overwrite the buffer with '\0' */
|
/** Overwrite the buffer with '\0' */
|
||||||
# define BURN_BUFFER(x, size) do { \
|
# define BURN_BUFFER(x, size) do { \
|
||||||
if ((x) != NULL) \
|
if ((x) != NULL) \
|
||||||
memset((x), '\0', (size))); __asm__ volatile("" : : "r"(&(x)) : "memory"); \
|
memset((x), '\0', (size)); __asm__ volatile("" : : "r"(&(x)) : "memory"); \
|
||||||
} while(0)
|
} while(0)
|
||||||
#else /* HAVE_GCC_VOLATILE_MEMORY_PROTECTION */
|
#else /* HAVE_GCC_VOLATILE_MEMORY_PROTECTION */
|
||||||
/** Overwrite a string with '\0' */
|
/** Overwrite a string with '\0' */
|
||||||
@@ -262,7 +299,7 @@ int match_hostname(const char *host, const char *pattern, unsigned int len);
|
|||||||
/** Overwrite the buffer with '\0' */
|
/** Overwrite the buffer with '\0' */
|
||||||
# define BURN_BUFFER(x, size) do { \
|
# define BURN_BUFFER(x, size) do { \
|
||||||
if ((x) != NULL) \
|
if ((x) != NULL) \
|
||||||
memset((x), '\0', (size))); __asm__ volatile("" : : "r"(&(x)) : "memory"); \
|
memset((x), '\0', (size)); \
|
||||||
} while(0)
|
} while(0)
|
||||||
#endif /* HAVE_GCC_VOLATILE_MEMORY_PROTECTION */
|
#endif /* HAVE_GCC_VOLATILE_MEMORY_PROTECTION */
|
||||||
|
|
||||||
@@ -285,5 +322,44 @@ int match_hostname(const char *host, const char *pattern, unsigned int len);
|
|||||||
*/
|
*/
|
||||||
#define discard_const_p(type, ptr) ((type *)discard_const(ptr))
|
#define discard_const_p(type, ptr) ((type *)discard_const(ptr))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the argument cound of variadic arguments
|
||||||
|
*/
|
||||||
|
#ifdef HAVE_GCC_NARG_MACRO
|
||||||
|
/*
|
||||||
|
* Since MSVC 2010 there is a bug in passing __VA_ARGS__ to subsequent
|
||||||
|
* macros as a single token, which results in:
|
||||||
|
* warning C4003: not enough actual parameters for macro '_VA_ARG_N'
|
||||||
|
* and incorrect behavior. This fixes issue.
|
||||||
|
*/
|
||||||
|
#define VA_APPLY_VARIADIC_MACRO(macro, tuple) macro tuple
|
||||||
|
|
||||||
|
#define __VA_NARG__(...) \
|
||||||
|
(__VA_NARG_(_0, ## __VA_ARGS__, __RSEQ_N()) - 1)
|
||||||
|
#define __VA_NARG_(...) \
|
||||||
|
VA_APPLY_VARIADIC_MACRO(__VA_ARG_N, (__VA_ARGS__))
|
||||||
|
#define __VA_ARG_N( \
|
||||||
|
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
|
||||||
|
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
|
||||||
|
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
|
||||||
|
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
|
||||||
|
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
|
||||||
|
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
|
||||||
|
_61,_62,_63,N,...) N
|
||||||
|
#define __RSEQ_N() \
|
||||||
|
63, 62, 61, 60, \
|
||||||
|
59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \
|
||||||
|
49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \
|
||||||
|
39, 38, 37, 36, 35, 34, 33, 32, 31, 30, \
|
||||||
|
29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
|
||||||
|
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
|
||||||
|
9, 8, 7, 6, 5, 4, 3, 2, 1, 0
|
||||||
|
#else
|
||||||
|
/* clang does not support the above construction */
|
||||||
|
#define __VA_NARG__(...) (-1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CLOSE_SOCKET(s) do { if ((s) != SSH_INVALID_SOCKET) { _XCLOSESOCKET(s); (s) = SSH_INVALID_SOCKET;} } while(0)
|
||||||
|
|
||||||
#endif /* _LIBSSH_PRIV_H */
|
#endif /* _LIBSSH_PRIV_H */
|
||||||
/* vim: set ts=4 sw=4 et cindent: */
|
/* vim: set ts=4 sw=4 et cindent: */
|
||||||
|
|||||||
74
include/libssh/sc25519.h
Normal file
74
include/libssh/sc25519.h
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/* $OpenBSD: sc25519.h,v 1.3 2013/12/09 11:03:45 markus Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange,
|
||||||
|
* Peter Schwabe, Bo-Yin Yang.
|
||||||
|
* Copied from supercop-20130419/crypto_sign/ed25519/ref/sc25519.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SC25519_H
|
||||||
|
#define SC25519_H
|
||||||
|
|
||||||
|
#define sc25519 crypto_sign_ed25519_ref_sc25519
|
||||||
|
#define shortsc25519 crypto_sign_ed25519_ref_shortsc25519
|
||||||
|
#define sc25519_from32bytes crypto_sign_ed25519_ref_sc25519_from32bytes
|
||||||
|
#define shortsc25519_from16bytes crypto_sign_ed25519_ref_shortsc25519_from16bytes
|
||||||
|
#define sc25519_from64bytes crypto_sign_ed25519_ref_sc25519_from64bytes
|
||||||
|
#define sc25519_from_shortsc crypto_sign_ed25519_ref_sc25519_from_shortsc
|
||||||
|
#define sc25519_to32bytes crypto_sign_ed25519_ref_sc25519_to32bytes
|
||||||
|
#define sc25519_iszero_vartime crypto_sign_ed25519_ref_sc25519_iszero_vartime
|
||||||
|
#define sc25519_isshort_vartime crypto_sign_ed25519_ref_sc25519_isshort_vartime
|
||||||
|
#define sc25519_lt_vartime crypto_sign_ed25519_ref_sc25519_lt_vartime
|
||||||
|
#define sc25519_add crypto_sign_ed25519_ref_sc25519_add
|
||||||
|
#define sc25519_sub_nored crypto_sign_ed25519_ref_sc25519_sub_nored
|
||||||
|
#define sc25519_mul crypto_sign_ed25519_ref_sc25519_mul
|
||||||
|
#define sc25519_mul_shortsc crypto_sign_ed25519_ref_sc25519_mul_shortsc
|
||||||
|
#define sc25519_window3 crypto_sign_ed25519_ref_sc25519_window3
|
||||||
|
#define sc25519_window5 crypto_sign_ed25519_ref_sc25519_window5
|
||||||
|
#define sc25519_2interleave2 crypto_sign_ed25519_ref_sc25519_2interleave2
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t v[32];
|
||||||
|
} sc25519;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t v[16];
|
||||||
|
} shortsc25519;
|
||||||
|
|
||||||
|
void sc25519_from32bytes(sc25519 *r, const unsigned char x[32]);
|
||||||
|
|
||||||
|
void shortsc25519_from16bytes(shortsc25519 *r, const unsigned char x[16]);
|
||||||
|
|
||||||
|
void sc25519_from64bytes(sc25519 *r, const unsigned char x[64]);
|
||||||
|
|
||||||
|
void sc25519_from_shortsc(sc25519 *r, const shortsc25519 *x);
|
||||||
|
|
||||||
|
void sc25519_to32bytes(unsigned char r[32], const sc25519 *x);
|
||||||
|
|
||||||
|
int sc25519_iszero_vartime(const sc25519 *x);
|
||||||
|
|
||||||
|
int sc25519_isshort_vartime(const sc25519 *x);
|
||||||
|
|
||||||
|
int sc25519_lt_vartime(const sc25519 *x, const sc25519 *y);
|
||||||
|
|
||||||
|
void sc25519_add(sc25519 *r, const sc25519 *x, const sc25519 *y);
|
||||||
|
|
||||||
|
void sc25519_sub_nored(sc25519 *r, const sc25519 *x, const sc25519 *y);
|
||||||
|
|
||||||
|
void sc25519_mul(sc25519 *r, const sc25519 *x, const sc25519 *y);
|
||||||
|
|
||||||
|
void sc25519_mul_shortsc(sc25519 *r, const sc25519 *x, const shortsc25519 *y);
|
||||||
|
|
||||||
|
/* Convert s into a representation of the form \sum_{i=0}^{84}r[i]2^3
|
||||||
|
* with r[i] in {-4,...,3}
|
||||||
|
*/
|
||||||
|
void sc25519_window3(signed char r[85], const sc25519 *s);
|
||||||
|
|
||||||
|
/* Convert s into a representation of the form \sum_{i=0}^{50}r[i]2^5
|
||||||
|
* with r[i] in {-16,...,15}
|
||||||
|
*/
|
||||||
|
void sc25519_window5(signed char r[51], const sc25519 *s);
|
||||||
|
|
||||||
|
void sc25519_2interleave2(unsigned char r[127], const sc25519 *s1, const sc25519 *s2);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -44,7 +44,8 @@ enum ssh_bind_options_e {
|
|||||||
SSH_BIND_OPTIONS_RSAKEY,
|
SSH_BIND_OPTIONS_RSAKEY,
|
||||||
SSH_BIND_OPTIONS_BANNER,
|
SSH_BIND_OPTIONS_BANNER,
|
||||||
SSH_BIND_OPTIONS_LOG_VERBOSITY,
|
SSH_BIND_OPTIONS_LOG_VERBOSITY,
|
||||||
SSH_BIND_OPTIONS_LOG_VERBOSITY_STR
|
SSH_BIND_OPTIONS_LOG_VERBOSITY_STR,
|
||||||
|
SSH_BIND_OPTIONS_ECDSAKEY
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct ssh_bind_struct* ssh_bind;
|
typedef struct ssh_bind_struct* ssh_bind;
|
||||||
@@ -80,69 +81,6 @@ typedef struct ssh_bind_callbacks_struct *ssh_bind_callbacks;
|
|||||||
*/
|
*/
|
||||||
LIBSSH_API ssh_bind ssh_bind_new(void);
|
LIBSSH_API ssh_bind ssh_bind_new(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the options for the current SSH server bind.
|
|
||||||
*
|
|
||||||
* @param sshbind The ssh server bind to configure.
|
|
||||||
*
|
|
||||||
* @param type The option type to set. This could be one of the
|
|
||||||
* following:
|
|
||||||
*
|
|
||||||
* - SSH_BIND_OPTIONS_BINDADDR
|
|
||||||
* The ip address to bind (const char *).
|
|
||||||
*
|
|
||||||
* - SSH_BIND_OPTIONS_BINDPORT
|
|
||||||
* The port to bind (unsigned int).
|
|
||||||
*
|
|
||||||
* - SSH_BIND_OPTIONS_BINDPORT_STR
|
|
||||||
* The port to bind (const char *).
|
|
||||||
*
|
|
||||||
* - SSH_BIND_OPTIONS_HOSTKEY
|
|
||||||
* This specifies the file containing the private host key used
|
|
||||||
* by SSHv1. (const char *).
|
|
||||||
*
|
|
||||||
* - SSH_BIND_OPTIONS_DSAKEY
|
|
||||||
* This specifies the file containing the private host dsa key
|
|
||||||
* used by SSHv2. (const char *).
|
|
||||||
*
|
|
||||||
* - SSH_BIND_OPTIONS_RSAKEY
|
|
||||||
* This specifies the file containing the private host dsa key
|
|
||||||
* used by SSHv2. (const char *).
|
|
||||||
*
|
|
||||||
* - SSH_BIND_OPTIONS_BANNER
|
|
||||||
* That the server banner (version string) for SSH.
|
|
||||||
* (const char *).
|
|
||||||
*
|
|
||||||
* - SSH_BIND_OPTIONS_LOG_VERBOSITY
|
|
||||||
* Set the session logging verbosity (int).\n
|
|
||||||
* \n
|
|
||||||
* The verbosity of the messages. Every log smaller or
|
|
||||||
* equal to verbosity will be shown.
|
|
||||||
* - SSH_LOG_NOLOG: No logging
|
|
||||||
* - SSH_LOG_RARE: Rare conditions or warnings
|
|
||||||
* - SSH_LOG_ENTRY: API-accessible entrypoints
|
|
||||||
* - SSH_LOG_PACKET: Packet id and size
|
|
||||||
* - SSH_LOG_FUNCTIONS: Function entering and leaving
|
|
||||||
*
|
|
||||||
* - SSH_BIND_OPTIONS_LOG_VERBOSITY_STR
|
|
||||||
* Set the session logging verbosity (const char *).\n
|
|
||||||
* \n
|
|
||||||
* The verbosity of the messages. Every log smaller or
|
|
||||||
* equal to verbosity will be shown.
|
|
||||||
* - SSH_LOG_NOLOG: No logging
|
|
||||||
* - SSH_LOG_RARE: Rare conditions or warnings
|
|
||||||
* - SSH_LOG_ENTRY: API-accessible entrypoints
|
|
||||||
* - SSH_LOG_PACKET: Packet id and size
|
|
||||||
* - SSH_LOG_FUNCTIONS: Function entering and leaving
|
|
||||||
* \n
|
|
||||||
* See the corresponding numbers in libssh.h.
|
|
||||||
*
|
|
||||||
* @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.
|
|
||||||
*
|
|
||||||
* @returns SSH_OK on success, SSH_ERROR on invalid option or parameter.
|
|
||||||
*/
|
|
||||||
LIBSSH_API int ssh_bind_options_set(ssh_bind sshbind,
|
LIBSSH_API int ssh_bind_options_set(ssh_bind sshbind,
|
||||||
enum ssh_bind_options_e type, const void *value);
|
enum ssh_bind_options_e type, const void *value);
|
||||||
|
|
||||||
@@ -382,6 +320,8 @@ LIBSSH_API int ssh_channel_write_stderr(ssh_channel channel,
|
|||||||
const void *data,
|
const void *data,
|
||||||
uint32_t len);
|
uint32_t len);
|
||||||
|
|
||||||
|
LIBSSH_API int ssh_send_keepalive(ssh_session session);
|
||||||
|
|
||||||
/* deprecated functions */
|
/* deprecated functions */
|
||||||
SSH_DEPRECATED LIBSSH_API int ssh_accept(ssh_session session);
|
SSH_DEPRECATED LIBSSH_API int ssh_accept(ssh_session session);
|
||||||
SSH_DEPRECATED LIBSSH_API int channel_write_stderr(ssh_channel channel,
|
SSH_DEPRECATED LIBSSH_API int channel_write_stderr(ssh_channel channel,
|
||||||
|
|||||||
@@ -97,9 +97,6 @@ struct ssh_session_struct {
|
|||||||
int openssh;
|
int openssh;
|
||||||
uint32_t send_seq;
|
uint32_t send_seq;
|
||||||
uint32_t recv_seq;
|
uint32_t recv_seq;
|
||||||
/* status flags */
|
|
||||||
int closed;
|
|
||||||
int closed_by_except;
|
|
||||||
|
|
||||||
int connected;
|
int connected;
|
||||||
/* !=0 when the user got a session handle */
|
/* !=0 when the user got a session handle */
|
||||||
@@ -130,6 +127,15 @@ struct ssh_session_struct {
|
|||||||
struct ssh_agent_state_struct *agent_state;
|
struct ssh_agent_state_struct *agent_state;
|
||||||
struct ssh_auth_auto_state_struct *auth_auto_state;
|
struct ssh_auth_auto_state_struct *auth_auto_state;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RFC 4253, 7.1: if the first_kex_packet_follows flag was set in
|
||||||
|
* the received SSH_MSG_KEXINIT, but the guess was wrong, this
|
||||||
|
* field will be set such that the following guessed packet will
|
||||||
|
* be ignored. Once that packet has been received and ignored,
|
||||||
|
* this field is cleared.
|
||||||
|
*/
|
||||||
|
int first_kex_follows_guess_wrong;
|
||||||
|
|
||||||
ssh_buffer in_hashbuf;
|
ssh_buffer in_hashbuf;
|
||||||
ssh_buffer out_hashbuf;
|
ssh_buffer out_hashbuf;
|
||||||
struct ssh_crypto_struct *current_crypto;
|
struct ssh_crypto_struct *current_crypto;
|
||||||
@@ -150,7 +156,7 @@ struct ssh_session_struct {
|
|||||||
ssh_key rsa_key;
|
ssh_key rsa_key;
|
||||||
ssh_key dsa_key;
|
ssh_key dsa_key;
|
||||||
ssh_key ecdsa_key;
|
ssh_key ecdsa_key;
|
||||||
|
ssh_key ed25519_key;
|
||||||
/* The type of host key wanted by client */
|
/* The type of host key wanted by client */
|
||||||
enum ssh_keytypes_e hostkey;
|
enum ssh_keytypes_e hostkey;
|
||||||
} srv;
|
} srv;
|
||||||
@@ -178,6 +184,7 @@ struct ssh_session_struct {
|
|||||||
char *knownhosts;
|
char *knownhosts;
|
||||||
char *wanted_methods[10];
|
char *wanted_methods[10];
|
||||||
char *ProxyCommand;
|
char *ProxyCommand;
|
||||||
|
char *custombanner;
|
||||||
unsigned long timeout; /* seconds */
|
unsigned long timeout; /* seconds */
|
||||||
unsigned long timeout_usec;
|
unsigned long timeout_usec;
|
||||||
unsigned int port;
|
unsigned int port;
|
||||||
@@ -186,7 +193,13 @@ struct ssh_session_struct {
|
|||||||
int ssh2;
|
int ssh2;
|
||||||
int ssh1;
|
int ssh1;
|
||||||
char compressionlevel;
|
char compressionlevel;
|
||||||
|
char *gss_server_identity;
|
||||||
|
char *gss_client_identity;
|
||||||
|
int gss_delegate_creds;
|
||||||
} opts;
|
} opts;
|
||||||
|
/* counters */
|
||||||
|
ssh_counter socket_counter;
|
||||||
|
ssh_counter raw_counter;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @internal
|
/** @internal
|
||||||
|
|||||||
@@ -143,10 +143,10 @@ struct sftp_request_queue_struct {
|
|||||||
|
|
||||||
/* SSH_FXP_MESSAGE described into .7 page 26 */
|
/* SSH_FXP_MESSAGE described into .7 page 26 */
|
||||||
struct sftp_status_message_struct {
|
struct sftp_status_message_struct {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
ssh_string error;
|
ssh_string error_unused; /* not used anymore */
|
||||||
ssh_string lang;
|
ssh_string lang_unused; /* not used anymore */
|
||||||
char *errormsg;
|
char *errormsg;
|
||||||
char *langmsg;
|
char *langmsg;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ void ssh_socket_set_write_wontblock(ssh_socket s);
|
|||||||
void ssh_socket_set_read_wontblock(ssh_socket s);
|
void ssh_socket_set_read_wontblock(ssh_socket s);
|
||||||
void ssh_socket_set_except(ssh_socket s);
|
void ssh_socket_set_except(ssh_socket s);
|
||||||
int ssh_socket_get_status(ssh_socket s);
|
int ssh_socket_get_status(ssh_socket s);
|
||||||
|
int ssh_socket_get_poll_flags(ssh_socket s);
|
||||||
int ssh_socket_buffered_write_bytes(ssh_socket s);
|
int ssh_socket_buffered_write_bytes(ssh_socket s);
|
||||||
int ssh_socket_data_available(ssh_socket s);
|
int ssh_socket_data_available(ssh_socket s);
|
||||||
int ssh_socket_data_writable(ssh_socket s);
|
int ssh_socket_data_writable(ssh_socket s);
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#define WRAPPER_H_
|
#define WRAPPER_H_
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "libssh/libssh.h"
|
||||||
#include "libssh/libcrypto.h"
|
#include "libssh/libcrypto.h"
|
||||||
#include "libssh/libgcrypt.h"
|
#include "libssh/libgcrypt.h"
|
||||||
|
|
||||||
@@ -34,6 +35,9 @@ enum ssh_mac_e {
|
|||||||
|
|
||||||
enum ssh_hmac_e {
|
enum ssh_hmac_e {
|
||||||
SSH_HMAC_SHA1 = 1,
|
SSH_HMAC_SHA1 = 1,
|
||||||
|
SSH_HMAC_SHA256,
|
||||||
|
SSH_HMAC_SHA384,
|
||||||
|
SSH_HMAC_SHA512,
|
||||||
SSH_HMAC_MD5
|
SSH_HMAC_MD5
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -42,17 +46,40 @@ enum ssh_des_e {
|
|||||||
SSH_DES
|
SSH_DES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ssh_hmac_struct {
|
||||||
|
const char* name;
|
||||||
|
enum ssh_hmac_e hmac_type;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct ssh_mac_ctx_struct *ssh_mac_ctx;
|
typedef struct ssh_mac_ctx_struct *ssh_mac_ctx;
|
||||||
MD5CTX md5_init(void);
|
MD5CTX md5_init(void);
|
||||||
void md5_update(MD5CTX c, const void *data, unsigned long len);
|
void md5_update(MD5CTX c, const void *data, unsigned long len);
|
||||||
void md5_final(unsigned char *md,MD5CTX c);
|
void md5_final(unsigned char *md,MD5CTX c);
|
||||||
|
|
||||||
SHACTX sha1_init(void);
|
SHACTX sha1_init(void);
|
||||||
void sha1_update(SHACTX c, const void *data, unsigned long len);
|
void sha1_update(SHACTX c, const void *data, unsigned long len);
|
||||||
void sha1_final(unsigned char *md,SHACTX c);
|
void sha1_final(unsigned char *md,SHACTX c);
|
||||||
void sha1(unsigned char *digest,int len,unsigned char *hash);
|
void sha1(unsigned char *digest,int len,unsigned char *hash);
|
||||||
|
|
||||||
|
SHA256CTX sha256_init(void);
|
||||||
|
void sha256_update(SHA256CTX c, const void *data, unsigned long len);
|
||||||
|
void sha256_final(unsigned char *md,SHA256CTX c);
|
||||||
void sha256(unsigned char *digest, int len, unsigned char *hash);
|
void sha256(unsigned char *digest, int len, unsigned char *hash);
|
||||||
|
|
||||||
|
SHA384CTX sha384_init(void);
|
||||||
|
void sha384_update(SHA384CTX c, const void *data, unsigned long len);
|
||||||
|
void sha384_final(unsigned char *md,SHA384CTX c);
|
||||||
|
void sha384(unsigned char *digest, int len, unsigned char *hash);
|
||||||
|
|
||||||
|
SHA512CTX sha512_init(void);
|
||||||
|
void sha512_update(SHA512CTX c, const void *data, unsigned long len);
|
||||||
|
void sha512_final(unsigned char *md,SHA512CTX c);
|
||||||
|
void sha512(unsigned char *digest, int len, unsigned char *hash);
|
||||||
|
|
||||||
void evp(int nid, unsigned char *digest, int len, unsigned char *hash, unsigned int *hlen);
|
void evp(int nid, unsigned char *digest, int len, unsigned char *hash, unsigned int *hlen);
|
||||||
|
EVPCTX evp_init(int nid);
|
||||||
|
void evp_update(EVPCTX ctx, const void *data, unsigned long len);
|
||||||
|
void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen);
|
||||||
|
|
||||||
ssh_mac_ctx ssh_mac_ctx_init(enum ssh_mac_e type);
|
ssh_mac_ctx ssh_mac_ctx_init(enum ssh_mac_e type);
|
||||||
void ssh_mac_update(ssh_mac_ctx ctx, const void *data, unsigned long len);
|
void ssh_mac_update(ssh_mac_ctx ctx, const void *data, unsigned long len);
|
||||||
@@ -61,11 +88,17 @@ void ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx);
|
|||||||
HMACCTX hmac_init(const void *key,int len, enum ssh_hmac_e type);
|
HMACCTX hmac_init(const void *key,int len, enum ssh_hmac_e type);
|
||||||
void hmac_update(HMACCTX c, const void *data, unsigned long len);
|
void hmac_update(HMACCTX c, const void *data, unsigned long len);
|
||||||
void hmac_final(HMACCTX ctx,unsigned char *hashmacbuf,unsigned int *len);
|
void hmac_final(HMACCTX ctx,unsigned char *hashmacbuf,unsigned int *len);
|
||||||
|
size_t hmac_digest_len(enum ssh_hmac_e type);
|
||||||
|
|
||||||
int crypt_set_algorithms(ssh_session session, enum ssh_des_e des_type);
|
int crypt_set_algorithms(ssh_session session, enum ssh_des_e des_type);
|
||||||
int crypt_set_algorithms_server(ssh_session session);
|
int crypt_set_algorithms_server(ssh_session session);
|
||||||
struct ssh_crypto_struct *crypto_new(void);
|
struct ssh_crypto_struct *crypto_new(void);
|
||||||
void crypto_free(struct ssh_crypto_struct *crypto);
|
void crypto_free(struct ssh_crypto_struct *crypto);
|
||||||
|
|
||||||
|
void ssh_reseed(void);
|
||||||
|
|
||||||
|
void ssh_cipher_clear(struct ssh_cipher_struct *cipher);
|
||||||
|
struct ssh_hmac_struct *ssh_get_hmactab(void);
|
||||||
|
const char *ssh_hmac_type_to_string(enum ssh_hmac_e hmac_type);
|
||||||
|
|
||||||
#endif /* WRAPPER_H_ */
|
#endif /* WRAPPER_H_ */
|
||||||
|
|||||||
@@ -7,5 +7,7 @@ else()
|
|||||||
set(LIBSSH_INCLUDE_DIR @INCLUDE_INSTALL_DIR@)
|
set(LIBSSH_INCLUDE_DIR @INCLUDE_INSTALL_DIR@)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(LIBSSH_LIRBARY @LIB_INSTALL_DIR@/libssh.so)
|
set(LIBSSH_LIBRARY @LIB_INSTALL_DIR@/@LIBSSH_LIBRARY_NAME@)
|
||||||
set(LIBSSH_LIRBARIES @LIB_INSTALL_DIR@/libssh.so)
|
set(LIBSSH_LIBRARIES @LIB_INSTALL_DIR@/@LIBSSH_LIBRARY_NAME@)
|
||||||
|
|
||||||
|
set(LIBSSH_THREADS_LIBRARY @LIB_INSTALL_DIR@/@LIBSSH_THREADS_LIBRARY_NAME@)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#
|
#
|
||||||
# Script to build libssh on UNIX.
|
# Script to build libssh on UNIX.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2006-2007 Andreas Schneider <mail@cynapses.org>
|
# Copyright (c) 2006-2007 Andreas Schneider <asn@cryptomilk.org>
|
||||||
#
|
#
|
||||||
|
|
||||||
SOURCE_DIR=".."
|
SOURCE_DIR=".."
|
||||||
@@ -1,13 +1,12 @@
|
|||||||
project(libssh-library C)
|
project(libssh-library C)
|
||||||
|
|
||||||
set(LIBSSH_PUBLIC_INCLUDE_DIRS
|
set(LIBSSH_PUBLIC_INCLUDE_DIRS
|
||||||
${CMAKE_SOURCE_DIR}/include
|
${libssh_SOURCE_DIR}/include
|
||||||
CACHE INTERNAL "libssh public include directories"
|
CACHE INTERNAL "libssh public include directories"
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||||
${CMAKE_BINARY_DIR}
|
${libssh_BINARY_DIR}
|
||||||
${OPENSSL_INCLUDE_DIRS}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIBSSH_LINK_LIBRARIES
|
set(LIBSSH_LINK_LIBRARIES
|
||||||
@@ -28,17 +27,17 @@ if (HAVE_LIBSOCKET)
|
|||||||
)
|
)
|
||||||
endif (HAVE_LIBSOCKET)
|
endif (HAVE_LIBSOCKET)
|
||||||
|
|
||||||
if (OPENSSL_LIBRARIES)
|
if (OPENSSL_CRYPTO_LIBRARY)
|
||||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||||
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
||||||
${OPENSSL_INCLUDE_DIRS}
|
${OPENSSL_INCLUDE_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIBSSH_LINK_LIBRARIES
|
set(LIBSSH_LINK_LIBRARIES
|
||||||
${LIBSSH_LINK_LIBRARIES}
|
${LIBSSH_LINK_LIBRARIES}
|
||||||
${OPENSSL_LIBRARIES}
|
${OPENSSL_CRYPTO_LIBRARY}
|
||||||
)
|
)
|
||||||
endif (OPENSSL_LIBRARIES)
|
endif (OPENSSL_CRYPTO_LIBRARY)
|
||||||
|
|
||||||
if (GCRYPT_LIBRARY)
|
if (GCRYPT_LIBRARY)
|
||||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||||
@@ -55,7 +54,7 @@ endif (GCRYPT_LIBRARY)
|
|||||||
if (WITH_ZLIB)
|
if (WITH_ZLIB)
|
||||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||||
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
||||||
${ZLIB_INCLUDE_DIRS}
|
${ZLIB_INCLUDE_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIBSSH_LINK_LIBRARIES
|
set(LIBSSH_LINK_LIBRARIES
|
||||||
@@ -76,6 +75,18 @@ if (WITH_GSSAPI AND GSSAPI_FOUND)
|
|||||||
)
|
)
|
||||||
endif (WITH_GSSAPI AND GSSAPI_FOUND)
|
endif (WITH_GSSAPI AND GSSAPI_FOUND)
|
||||||
|
|
||||||
|
if (WITH_NACL AND NACL_FOUND)
|
||||||
|
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||||
|
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
||||||
|
${NACL_INCLUDE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
set(LIBSSH_LINK_LIBRARIES
|
||||||
|
${LIBSSH_LINK_LIBRARIES}
|
||||||
|
${NACL_LIBRARY}
|
||||||
|
)
|
||||||
|
endif (WITH_NACL AND NACL_FOUND)
|
||||||
|
|
||||||
set(LIBSSH_LINK_LIBRARIES
|
set(LIBSSH_LINK_LIBRARIES
|
||||||
${LIBSSH_LINK_LIBRARIES}
|
${LIBSSH_LINK_LIBRARIES}
|
||||||
CACHE INTERNAL "libssh link libraries"
|
CACHE INTERNAL "libssh link libraries"
|
||||||
@@ -97,12 +108,14 @@ set(libssh_SRCS
|
|||||||
agent.c
|
agent.c
|
||||||
auth.c
|
auth.c
|
||||||
base64.c
|
base64.c
|
||||||
|
bignum.c
|
||||||
buffer.c
|
buffer.c
|
||||||
callbacks.c
|
callbacks.c
|
||||||
channels.c
|
channels.c
|
||||||
client.c
|
client.c
|
||||||
config.c
|
config.c
|
||||||
connect.c
|
connect.c
|
||||||
|
curve25519.c
|
||||||
dh.c
|
dh.c
|
||||||
ecdh.c
|
ecdh.c
|
||||||
error.c
|
error.c
|
||||||
@@ -122,6 +135,8 @@ set(libssh_SRCS
|
|||||||
packet_crypt.c
|
packet_crypt.c
|
||||||
pcap.c
|
pcap.c
|
||||||
pki.c
|
pki.c
|
||||||
|
pki_container_openssh.c
|
||||||
|
pki_ed25519.c
|
||||||
poll.c
|
poll.c
|
||||||
session.c
|
session.c
|
||||||
scp.c
|
scp.c
|
||||||
@@ -129,6 +144,12 @@ set(libssh_SRCS
|
|||||||
string.c
|
string.c
|
||||||
threads.c
|
threads.c
|
||||||
wrapper.c
|
wrapper.c
|
||||||
|
external/bcrypt_pbkdf.c
|
||||||
|
external/blowfish.c
|
||||||
|
external/ed25519.c
|
||||||
|
external/fe25519.c
|
||||||
|
external/ge25519.c
|
||||||
|
external/sc25519.c
|
||||||
)
|
)
|
||||||
|
|
||||||
if (WITH_GCRYPT)
|
if (WITH_GCRYPT)
|
||||||
@@ -192,6 +213,13 @@ if (WITH_GSSAPI AND GSSAPI_FOUND)
|
|||||||
)
|
)
|
||||||
endif (WITH_GSSAPI AND GSSAPI_FOUND)
|
endif (WITH_GSSAPI AND GSSAPI_FOUND)
|
||||||
|
|
||||||
|
if (NOT WITH_NACL)
|
||||||
|
set(libssh_SRCS
|
||||||
|
${libssh_SRCS}
|
||||||
|
external/curve25519_ref.c
|
||||||
|
)
|
||||||
|
endif (NOT WITH_NACL)
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${LIBSSH_PUBLIC_INCLUDE_DIRS}
|
${LIBSSH_PUBLIC_INCLUDE_DIRS}
|
||||||
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
||||||
@@ -218,6 +246,10 @@ if (WITH_VISIBILITY_HIDDEN)
|
|||||||
set_target_properties(${LIBSSH_SHARED_LIBRARY} PROPERTIES COMPILE_FLAGS "-fvisibility=hidden")
|
set_target_properties(${LIBSSH_SHARED_LIBRARY} PROPERTIES COMPILE_FLAGS "-fvisibility=hidden")
|
||||||
endif (WITH_VISIBILITY_HIDDEN)
|
endif (WITH_VISIBILITY_HIDDEN)
|
||||||
|
|
||||||
|
if (MINGW)
|
||||||
|
set_target_properties(${LIBSSH_SHARED_LIBRARY} PROPERTIES LINK_FLAGS "-Wl,--enable-stdcall-fixup")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
install(
|
install(
|
||||||
TARGETS
|
TARGETS
|
||||||
@@ -268,6 +300,7 @@ if (WITH_STATIC_LIB)
|
|||||||
)
|
)
|
||||||
endif (WITH_STATIC_LIB)
|
endif (WITH_STATIC_LIB)
|
||||||
|
|
||||||
if (CMAKE_HAVE_THREADS_LIBRARY)
|
message(STATUS "Threads_FOUND=${Threads_FOUND}")
|
||||||
|
if (Threads_FOUND)
|
||||||
add_subdirectory(threads)
|
add_subdirectory(threads)
|
||||||
endif (CMAKE_HAVE_THREADS_LIBRARY)
|
endif (Threads_FOUND)
|
||||||
|
|||||||
48
src/agent.c
48
src/agent.c
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the SSH Library
|
* This file is part of the SSH Library
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008-2009 by Andreas Schneider <asn@cryptomilk.org>
|
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@@ -185,15 +185,32 @@ int ssh_set_agent_channel(ssh_session session, ssh_channel channel){
|
|||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief sets the SSH agent socket.
|
||||||
|
* The SSH agent will be used to authenticate this client using
|
||||||
|
* the given socket to communicate with the ssh-agent. The caller
|
||||||
|
* is responsible for connecting to the socket prior to calling
|
||||||
|
* this function.
|
||||||
|
* @returns SSH_OK in case of success
|
||||||
|
* SSH_ERROR in case of an error
|
||||||
|
*/
|
||||||
|
int ssh_set_agent_socket(ssh_session session, socket_t fd){
|
||||||
|
if (!session)
|
||||||
|
return SSH_ERROR;
|
||||||
|
if (!session->agent){
|
||||||
|
ssh_set_error(session, SSH_REQUEST_DENIED, "Session has no active agent");
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_socket_set_fd(session->agent->sock, fd);
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
void agent_close(struct ssh_agent_struct *agent) {
|
void agent_close(struct ssh_agent_struct *agent) {
|
||||||
if (agent == NULL) {
|
if (agent == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getenv("SSH_AUTH_SOCK")) {
|
ssh_socket_close(agent->sock);
|
||||||
ssh_socket_close(agent->sock);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void agent_free(ssh_agent agent) {
|
void agent_free(ssh_agent agent) {
|
||||||
@@ -300,7 +317,7 @@ static int agent_talk(struct ssh_session_struct *session,
|
|||||||
"Error reading response from authentication socket.");
|
"Error reading response from authentication socket.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (buffer_add_data(reply, payload, n) < 0) {
|
if (ssh_buffer_add_data(reply, payload, n) < 0) {
|
||||||
SSH_LOG(SSH_LOG_WARN, "Not enough space");
|
SSH_LOG(SSH_LOG_WARN, "Not enough space");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -365,6 +382,9 @@ int ssh_agent_get_ident_count(struct ssh_session_struct *session) {
|
|||||||
ssh_buffer_free(reply);
|
ssh_buffer_free(reply);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
type = bswap_32(type);
|
||||||
|
#endif
|
||||||
|
|
||||||
SSH_LOG(SSH_LOG_WARN,
|
SSH_LOG(SSH_LOG_WARN,
|
||||||
"Answer type: %d, expected answer: %d",
|
"Answer type: %d, expected answer: %d",
|
||||||
@@ -375,7 +395,7 @@ int ssh_agent_get_ident_count(struct ssh_session_struct *session) {
|
|||||||
return 0;
|
return 0;
|
||||||
} else if (type != c2) {
|
} else if (type != c2) {
|
||||||
ssh_set_error(session, SSH_FATAL,
|
ssh_set_error(session, SSH_FATAL,
|
||||||
"Bad authentication reply message type: %d", type);
|
"Bad authentication reply message type: %u", type);
|
||||||
ssh_buffer_free(reply);
|
ssh_buffer_free(reply);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -393,7 +413,7 @@ int ssh_agent_get_ident_count(struct ssh_session_struct *session) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (session->agent->ident) {
|
if (session->agent->ident) {
|
||||||
buffer_reinit(session->agent->ident);
|
ssh_buffer_reinit(session->agent->ident);
|
||||||
}
|
}
|
||||||
session->agent->ident = reply;
|
session->agent->ident = reply;
|
||||||
|
|
||||||
@@ -490,8 +510,8 @@ ssh_string ssh_agent_sign_data(ssh_session session,
|
|||||||
ssh_buffer reply;
|
ssh_buffer reply;
|
||||||
ssh_string key_blob;
|
ssh_string key_blob;
|
||||||
ssh_string sig_blob;
|
ssh_string sig_blob;
|
||||||
int type = SSH2_AGENT_FAILURE;
|
unsigned int type = 0;
|
||||||
int flags = 0;
|
unsigned int flags = 0;
|
||||||
uint32_t dlen;
|
uint32_t dlen;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@@ -526,7 +546,7 @@ ssh_string ssh_agent_sign_data(ssh_session session,
|
|||||||
ssh_buffer_free(request);
|
ssh_buffer_free(request);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (buffer_add_data(request, buffer_get_rest(data), dlen) < 0) {
|
if (ssh_buffer_add_data(request, buffer_get_rest(data), dlen) < 0) {
|
||||||
ssh_buffer_free(request);
|
ssh_buffer_free(request);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -555,13 +575,19 @@ ssh_string ssh_agent_sign_data(ssh_session session,
|
|||||||
ssh_buffer_free(reply);
|
ssh_buffer_free(reply);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
type = bswap_32(type);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (agent_failed(type)) {
|
if (agent_failed(type)) {
|
||||||
SSH_LOG(SSH_LOG_WARN, "Agent reports failure in signing the key");
|
SSH_LOG(SSH_LOG_WARN, "Agent reports failure in signing the key");
|
||||||
ssh_buffer_free(reply);
|
ssh_buffer_free(reply);
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if (type != SSH2_AGENT_SIGN_RESPONSE) {
|
} else if (type != SSH2_AGENT_SIGN_RESPONSE) {
|
||||||
ssh_set_error(session, SSH_FATAL, "Bad authentication response: %d", type);
|
ssh_set_error(session,
|
||||||
|
SSH_FATAL,
|
||||||
|
"Bad authentication response: %u",
|
||||||
|
type);
|
||||||
ssh_buffer_free(reply);
|
ssh_buffer_free(reply);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
601
src/auth.c
Normal file → Executable file
601
src/auth.c
Normal file → Executable file
@@ -3,8 +3,8 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the SSH Library
|
* This file is part of the SSH Library
|
||||||
*
|
*
|
||||||
* Copyright (c) 2003-2011 by Aris Adamantiadis <aris@0xbadc0de.be>
|
* Copyright (c) 2003-2013 by Aris Adamantiadis <aris@0xbadc0de.be>
|
||||||
* Copyright (c) 2008-2011 Andreas Schneider <asn@cryptomilk.org>
|
* Copyright (c) 2008-2013 Andreas Schneider <asn@cryptomilk.org>
|
||||||
*
|
*
|
||||||
* The SSH Library is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
@@ -182,25 +182,19 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_banner){
|
|||||||
*/
|
*/
|
||||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_failure){
|
SSH_PACKET_CALLBACK(ssh_packet_userauth_failure){
|
||||||
char *auth_methods = NULL;
|
char *auth_methods = NULL;
|
||||||
ssh_string auth;
|
|
||||||
uint8_t partial = 0;
|
uint8_t partial = 0;
|
||||||
|
int rc;
|
||||||
(void) type;
|
(void) type;
|
||||||
(void) user;
|
(void) user;
|
||||||
|
|
||||||
auth = buffer_get_ssh_string(packet);
|
rc = ssh_buffer_unpack(packet, "sb", &auth_methods, &partial);
|
||||||
if (auth == NULL || buffer_get_u8(packet, &partial) != 1) {
|
if (rc != SSH_OK) {
|
||||||
ssh_set_error(session, SSH_FATAL,
|
ssh_set_error(session, SSH_FATAL,
|
||||||
"Invalid SSH_MSG_USERAUTH_FAILURE message");
|
"Invalid SSH_MSG_USERAUTH_FAILURE message");
|
||||||
session->auth_state=SSH_AUTH_STATE_ERROR;
|
session->auth_state=SSH_AUTH_STATE_ERROR;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
auth_methods = ssh_string_to_char(auth);
|
|
||||||
if (auth_methods == NULL) {
|
|
||||||
ssh_set_error_oom(session);
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (partial) {
|
if (partial) {
|
||||||
session->auth_state=SSH_AUTH_STATE_PARTIAL;
|
session->auth_state=SSH_AUTH_STATE_PARTIAL;
|
||||||
SSH_LOG(SSH_LOG_INFO,
|
SSH_LOG(SSH_LOG_INFO,
|
||||||
@@ -215,8 +209,8 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_failure){
|
|||||||
"Access denied. Authentication that can continue: %s",
|
"Access denied. Authentication that can continue: %s",
|
||||||
auth_methods);
|
auth_methods);
|
||||||
|
|
||||||
session->auth_methods = 0;
|
|
||||||
}
|
}
|
||||||
|
session->auth_methods = 0;
|
||||||
if (strstr(auth_methods, "password") != NULL) {
|
if (strstr(auth_methods, "password") != NULL) {
|
||||||
session->auth_methods |= SSH_AUTH_METHOD_PASSWORD;
|
session->auth_methods |= SSH_AUTH_METHOD_PASSWORD;
|
||||||
}
|
}
|
||||||
@@ -234,7 +228,6 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_failure){
|
|||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
ssh_string_free(auth);
|
|
||||||
SAFE_FREE(auth_methods);
|
SAFE_FREE(auth_methods);
|
||||||
|
|
||||||
return SSH_PACKET_USED;
|
return SSH_PACKET_USED;
|
||||||
@@ -355,11 +348,10 @@ int ssh_userauth_list(ssh_session session, const char *username)
|
|||||||
* later.
|
* later.
|
||||||
*
|
*
|
||||||
* @note Most server implementations do not permit changing the username during
|
* @note Most server implementations do not permit changing the username during
|
||||||
* authentication. The username should only be set with ssh_optoins_set() only
|
* authentication. The username should only be set with ssh_options_set() only
|
||||||
* before you connect to the server.
|
* before you connect to the server.
|
||||||
*/
|
*/
|
||||||
int ssh_userauth_none(ssh_session session, const char *username) {
|
int ssh_userauth_none(ssh_session session, const char *username) {
|
||||||
ssh_string str;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
#ifdef WITH_SSH1
|
#ifdef WITH_SSH1
|
||||||
@@ -387,47 +379,12 @@ int ssh_userauth_none(ssh_session session, const char *username) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* request */
|
/* request */
|
||||||
rc = buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_REQUEST);
|
rc = ssh_buffer_pack(session->out_buffer, "bsss",
|
||||||
if (rc < 0) {
|
SSH2_MSG_USERAUTH_REQUEST,
|
||||||
goto fail;
|
username ? username : session->opts.username,
|
||||||
}
|
"ssh-connection",
|
||||||
|
"none"
|
||||||
/* username */
|
);
|
||||||
if (username) {
|
|
||||||
str = ssh_string_from_char(username);
|
|
||||||
} else {
|
|
||||||
str = ssh_string_from_char(session->opts.username);
|
|
||||||
}
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* service */
|
|
||||||
str = ssh_string_from_char("ssh-connection");
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* method */
|
|
||||||
str = ssh_string_from_char("none");
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -448,7 +405,7 @@ pending:
|
|||||||
return rc;
|
return rc;
|
||||||
fail:
|
fail:
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
buffer_reinit(session->out_buffer);
|
ssh_buffer_reinit(session->out_buffer);
|
||||||
|
|
||||||
return SSH_AUTH_ERROR;
|
return SSH_AUTH_ERROR;
|
||||||
}
|
}
|
||||||
@@ -478,14 +435,14 @@ fail:
|
|||||||
* later.
|
* later.
|
||||||
*
|
*
|
||||||
* @note Most server implementations do not permit changing the username during
|
* @note Most server implementations do not permit changing the username during
|
||||||
* authentication. The username should only be set with ssh_optoins_set() only
|
* authentication. The username should only be set with ssh_options_set() only
|
||||||
* before you connect to the server.
|
* before you connect to the server.
|
||||||
*/
|
*/
|
||||||
int ssh_userauth_try_publickey(ssh_session session,
|
int ssh_userauth_try_publickey(ssh_session session,
|
||||||
const char *username,
|
const char *username,
|
||||||
const ssh_key pubkey)
|
const ssh_key pubkey)
|
||||||
{
|
{
|
||||||
ssh_string str;
|
ssh_string pubkey_s = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (session == NULL) {
|
if (session == NULL) {
|
||||||
@@ -522,82 +479,28 @@ int ssh_userauth_try_publickey(ssh_session session,
|
|||||||
return SSH_AUTH_ERROR;
|
return SSH_AUTH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* request */
|
|
||||||
rc = buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_REQUEST);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* username */
|
|
||||||
if (username) {
|
|
||||||
str = ssh_string_from_char(username);
|
|
||||||
} else {
|
|
||||||
str = ssh_string_from_char(session->opts.username);
|
|
||||||
}
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* service */
|
|
||||||
str = ssh_string_from_char("ssh-connection");
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* method */
|
|
||||||
str = ssh_string_from_char("publickey");
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* private key? */
|
|
||||||
rc = buffer_add_u8(session->out_buffer, 0);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* algo */
|
|
||||||
str = ssh_string_from_char(pubkey->type_c);
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* public key */
|
/* public key */
|
||||||
rc = ssh_pki_export_pubkey_blob(pubkey, &str);
|
rc = ssh_pki_export_pubkey_blob(pubkey, &pubkey_s);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
/* request */
|
||||||
ssh_string_free(str);
|
rc = ssh_buffer_pack(session->out_buffer, "bsssbsS",
|
||||||
|
SSH2_MSG_USERAUTH_REQUEST,
|
||||||
|
username ? username : session->opts.username,
|
||||||
|
"ssh-connection",
|
||||||
|
"publickey",
|
||||||
|
0, /* private key ? */
|
||||||
|
pubkey->type_c, /* algo */
|
||||||
|
pubkey_s /* public key */
|
||||||
|
);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssh_string_free(pubkey_s);
|
||||||
|
|
||||||
session->auth_state = SSH_AUTH_STATE_NONE;
|
session->auth_state = SSH_AUTH_STATE_NONE;
|
||||||
session->pending_call_state = SSH_PENDING_CALL_AUTH_OFFER_PUBKEY;
|
session->pending_call_state = SSH_PENDING_CALL_AUTH_OFFER_PUBKEY;
|
||||||
rc = packet_send(session);
|
rc = packet_send(session);
|
||||||
@@ -613,8 +516,9 @@ pending:
|
|||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
fail:
|
fail:
|
||||||
|
ssh_string_free(pubkey_s);
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
buffer_reinit(session->out_buffer);
|
ssh_buffer_reinit(session->out_buffer);
|
||||||
|
|
||||||
return SSH_AUTH_ERROR;
|
return SSH_AUTH_ERROR;
|
||||||
}
|
}
|
||||||
@@ -640,14 +544,14 @@ fail:
|
|||||||
* later.
|
* later.
|
||||||
*
|
*
|
||||||
* @note Most server implementations do not permit changing the username during
|
* @note Most server implementations do not permit changing the username during
|
||||||
* authentication. The username should only be set with ssh_optoins_set() only
|
* authentication. The username should only be set with ssh_options_set() only
|
||||||
* before you connect to the server.
|
* before you connect to the server.
|
||||||
*/
|
*/
|
||||||
int ssh_userauth_publickey(ssh_session session,
|
int ssh_userauth_publickey(ssh_session session,
|
||||||
const char *username,
|
const char *username,
|
||||||
const ssh_key privkey)
|
const ssh_key privkey)
|
||||||
{
|
{
|
||||||
ssh_string str;
|
ssh_string str = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (session == NULL) {
|
if (session == NULL) {
|
||||||
@@ -684,81 +588,26 @@ int ssh_userauth_publickey(ssh_session session,
|
|||||||
return SSH_AUTH_ERROR;
|
return SSH_AUTH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* request */
|
|
||||||
rc = buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_REQUEST);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* username */
|
|
||||||
if (username) {
|
|
||||||
str = ssh_string_from_char(username);
|
|
||||||
} else {
|
|
||||||
str = ssh_string_from_char(session->opts.username);
|
|
||||||
}
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* service */
|
|
||||||
str = ssh_string_from_char("ssh-connection");
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* method */
|
|
||||||
str = ssh_string_from_char("publickey");
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* private key? */
|
|
||||||
rc = buffer_add_u8(session->out_buffer, 1);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* algo */
|
|
||||||
str = ssh_string_from_char(privkey->type_c);
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* public key */
|
/* public key */
|
||||||
rc = ssh_pki_export_pubkey_blob(privkey, &str);
|
rc = ssh_pki_export_pubkey_blob(privkey, &str);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
/* request */
|
||||||
ssh_string_free(str);
|
rc = ssh_buffer_pack(session->out_buffer, "bsssbsS",
|
||||||
|
SSH2_MSG_USERAUTH_REQUEST,
|
||||||
|
username ? username : session->opts.username,
|
||||||
|
"ssh-connection",
|
||||||
|
"publickey",
|
||||||
|
1, /* private key */
|
||||||
|
privkey->type_c, /* algo */
|
||||||
|
str /* public key */
|
||||||
|
);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
ssh_string_free(str);
|
||||||
|
|
||||||
/* sign the buffer with the private key */
|
/* sign the buffer with the private key */
|
||||||
str = ssh_pki_do_sign(session, session->out_buffer, privkey);
|
str = ssh_pki_do_sign(session, session->out_buffer, privkey);
|
||||||
@@ -768,6 +617,7 @@ int ssh_userauth_publickey(ssh_session session,
|
|||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
rc = buffer_add_ssh_string(session->out_buffer, str);
|
||||||
ssh_string_free(str);
|
ssh_string_free(str);
|
||||||
|
str = NULL;
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -787,8 +637,9 @@ pending:
|
|||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
fail:
|
fail:
|
||||||
|
ssh_string_free(str);
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
buffer_reinit(session->out_buffer);
|
ssh_buffer_reinit(session->out_buffer);
|
||||||
|
|
||||||
return SSH_AUTH_ERROR;
|
return SSH_AUTH_ERROR;
|
||||||
}
|
}
|
||||||
@@ -798,7 +649,7 @@ static int ssh_userauth_agent_publickey(ssh_session session,
|
|||||||
const char *username,
|
const char *username,
|
||||||
ssh_key pubkey)
|
ssh_key pubkey)
|
||||||
{
|
{
|
||||||
ssh_string str;
|
ssh_string str = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
switch(session->pending_call_state) {
|
switch(session->pending_call_state) {
|
||||||
@@ -820,69 +671,6 @@ static int ssh_userauth_agent_publickey(ssh_session session,
|
|||||||
return SSH_AUTH_ERROR;
|
return SSH_AUTH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* request */
|
|
||||||
rc = buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_REQUEST);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* username */
|
|
||||||
if (username) {
|
|
||||||
str = ssh_string_from_char(username);
|
|
||||||
} else {
|
|
||||||
str = ssh_string_from_char(session->opts.username);
|
|
||||||
}
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* service */
|
|
||||||
str = ssh_string_from_char("ssh-connection");
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* method */
|
|
||||||
str = ssh_string_from_char("publickey");
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* private key? */
|
|
||||||
rc = buffer_add_u8(session->out_buffer, 1);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* algo */
|
|
||||||
str = ssh_string_from_char(pubkey->type_c);
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* public key */
|
/* public key */
|
||||||
rc = ssh_pki_export_pubkey_blob(pubkey, &str);
|
rc = ssh_pki_export_pubkey_blob(pubkey, &str);
|
||||||
@@ -890,12 +678,22 @@ static int ssh_userauth_agent_publickey(ssh_session session,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
/* request */
|
||||||
ssh_string_free(str);
|
rc = ssh_buffer_pack(session->out_buffer, "bsssbsS",
|
||||||
|
SSH2_MSG_USERAUTH_REQUEST,
|
||||||
|
username ? username : session->opts.username,
|
||||||
|
"ssh-connection",
|
||||||
|
"publickey",
|
||||||
|
1, /* private key */
|
||||||
|
pubkey->type_c, /* algo */
|
||||||
|
str /* public key */
|
||||||
|
);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssh_string_free(str);
|
||||||
|
|
||||||
/* sign the buffer with the private key */
|
/* sign the buffer with the private key */
|
||||||
str = ssh_pki_do_sign_agent(session, session->out_buffer, pubkey);
|
str = ssh_pki_do_sign_agent(session, session->out_buffer, pubkey);
|
||||||
if (str == NULL) {
|
if (str == NULL) {
|
||||||
@@ -924,7 +722,8 @@ pending:
|
|||||||
return rc;
|
return rc;
|
||||||
fail:
|
fail:
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
buffer_reinit(session->out_buffer);
|
ssh_buffer_reinit(session->out_buffer);
|
||||||
|
ssh_string_free(str);
|
||||||
|
|
||||||
return SSH_AUTH_ERROR;
|
return SSH_AUTH_ERROR;
|
||||||
}
|
}
|
||||||
@@ -961,7 +760,7 @@ struct ssh_agent_state_struct {
|
|||||||
* later.
|
* later.
|
||||||
*
|
*
|
||||||
* @note Most server implementations do not permit changing the username during
|
* @note Most server implementations do not permit changing the username during
|
||||||
* authentication. The username should only be set with ssh_optoins_set() only
|
* authentication. The username should only be set with ssh_options_set() only
|
||||||
* before you connect to the server.
|
* before you connect to the server.
|
||||||
*/
|
*/
|
||||||
int ssh_userauth_agent(ssh_session session,
|
int ssh_userauth_agent(ssh_session session,
|
||||||
@@ -987,6 +786,11 @@ int ssh_userauth_agent(ssh_session session,
|
|||||||
state = session->agent_state;
|
state = session->agent_state;
|
||||||
if (state->pubkey == NULL)
|
if (state->pubkey == NULL)
|
||||||
state->pubkey = ssh_agent_get_first_ident(session, &state->comment);
|
state->pubkey = ssh_agent_get_first_ident(session, &state->comment);
|
||||||
|
|
||||||
|
if (state->pubkey == NULL) {
|
||||||
|
return SSH_AUTH_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
while (state->pubkey != NULL) {
|
while (state->pubkey != NULL) {
|
||||||
if(state->state == SSH_AGENT_STATE_NONE){
|
if(state->state == SSH_AGENT_STATE_NONE){
|
||||||
SSH_LOG(SSH_LOG_DEBUG,
|
SSH_LOG(SSH_LOG_DEBUG,
|
||||||
@@ -1083,7 +887,7 @@ struct ssh_auth_auto_state_struct {
|
|||||||
* later.
|
* later.
|
||||||
*
|
*
|
||||||
* @note Most server implementations do not permit changing the username during
|
* @note Most server implementations do not permit changing the username during
|
||||||
* authentication. The username should only be set with ssh_optoins_set() only
|
* authentication. The username should only be set with ssh_options_set() only
|
||||||
* before you connect to the server.
|
* before you connect to the server.
|
||||||
*/
|
*/
|
||||||
int ssh_userauth_publickey_auto(ssh_session session,
|
int ssh_userauth_publickey_auto(ssh_session session,
|
||||||
@@ -1246,15 +1050,14 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
|||||||
ssh_key_free(state->privkey);
|
ssh_key_free(state->privkey);
|
||||||
ssh_key_free(state->pubkey);
|
ssh_key_free(state->pubkey);
|
||||||
SAFE_FREE(session->auth_auto_state);
|
SAFE_FREE(session->auth_auto_state);
|
||||||
|
if (rc == SSH_AUTH_SUCCESS) {
|
||||||
|
SSH_LOG(SSH_LOG_INFO,
|
||||||
|
"Successfully authenticated using %s",
|
||||||
|
privkey_file);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
if (rc == SSH_AUTH_ERROR) {
|
if (rc == SSH_AUTH_AGAIN){
|
||||||
return rc;
|
|
||||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
|
||||||
SSH_LOG(SSH_LOG_INFO,
|
|
||||||
"Successfully authenticated using %s",
|
|
||||||
privkey_file);
|
|
||||||
return rc;
|
|
||||||
} else if (rc == SSH_AUTH_AGAIN){
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1297,7 +1100,7 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
|||||||
* later.
|
* later.
|
||||||
*
|
*
|
||||||
* @note Most server implementations do not permit changing the username during
|
* @note Most server implementations do not permit changing the username during
|
||||||
* authentication. The username should only be set with ssh_optoins_set() only
|
* authentication. The username should only be set with ssh_options_set() only
|
||||||
* before you connect to the server.
|
* before you connect to the server.
|
||||||
*
|
*
|
||||||
* @see ssh_userauth_none()
|
* @see ssh_userauth_none()
|
||||||
@@ -1306,7 +1109,6 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
|||||||
int ssh_userauth_password(ssh_session session,
|
int ssh_userauth_password(ssh_session session,
|
||||||
const char *username,
|
const char *username,
|
||||||
const char *password) {
|
const char *password) {
|
||||||
ssh_string str;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
#ifdef WITH_SSH1
|
#ifdef WITH_SSH1
|
||||||
@@ -1336,65 +1138,14 @@ int ssh_userauth_password(ssh_session session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* request */
|
/* request */
|
||||||
rc = buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_REQUEST);
|
rc = ssh_buffer_pack(session->out_buffer, "bsssbs",
|
||||||
if (rc < 0) {
|
SSH2_MSG_USERAUTH_REQUEST,
|
||||||
goto fail;
|
username ? username : session->opts.username,
|
||||||
}
|
"ssh-connection",
|
||||||
|
"password",
|
||||||
/* username */
|
0, /* false */
|
||||||
if (username) {
|
password
|
||||||
str = ssh_string_from_char(username);
|
);
|
||||||
} else {
|
|
||||||
str = ssh_string_from_char(session->opts.username);
|
|
||||||
}
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* service */
|
|
||||||
str = ssh_string_from_char("ssh-connection");
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* method */
|
|
||||||
str = ssh_string_from_char("password");
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FALSE */
|
|
||||||
rc = buffer_add_u8(session->out_buffer, 0);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* password */
|
|
||||||
str = ssh_string_from_char(password);
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -1415,7 +1166,7 @@ pending:
|
|||||||
return rc;
|
return rc;
|
||||||
fail:
|
fail:
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
buffer_reinit(session->out_buffer);
|
ssh_buffer_reinit(session->out_buffer);
|
||||||
|
|
||||||
return SSH_AUTH_ERROR;
|
return SSH_AUTH_ERROR;
|
||||||
}
|
}
|
||||||
@@ -1536,7 +1287,6 @@ static int ssh_userauth_kbdint_init(ssh_session session,
|
|||||||
const char *username,
|
const char *username,
|
||||||
const char *submethods)
|
const char *submethods)
|
||||||
{
|
{
|
||||||
ssh_string str;
|
|
||||||
int rc;
|
int rc;
|
||||||
if (session->pending_call_state == SSH_PENDING_CALL_AUTH_KBDINT_INIT)
|
if (session->pending_call_state == SSH_PENDING_CALL_AUTH_KBDINT_INIT)
|
||||||
goto pending;
|
goto pending;
|
||||||
@@ -1552,78 +1302,18 @@ static int ssh_userauth_kbdint_init(ssh_session session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* request */
|
/* request */
|
||||||
rc = buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_REQUEST);
|
rc = ssh_buffer_pack(session->out_buffer, "bsssss",
|
||||||
|
SSH2_MSG_USERAUTH_REQUEST,
|
||||||
|
username ? username : session->opts.username,
|
||||||
|
"ssh-connection",
|
||||||
|
"keyboard-interactive",
|
||||||
|
"", /* lang (ignore it) */
|
||||||
|
submethods ? submethods : ""
|
||||||
|
);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* username */
|
|
||||||
if (username) {
|
|
||||||
str = ssh_string_from_char(username);
|
|
||||||
} else {
|
|
||||||
str = ssh_string_from_char(session->opts.username);
|
|
||||||
}
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* service */
|
|
||||||
str = ssh_string_from_char("ssh-connection");
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* method */
|
|
||||||
str = ssh_string_from_char("keyboard-interactive");
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* lang string (ignore it) */
|
|
||||||
str = ssh_string_from_char("");
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* submethods */
|
|
||||||
if (submethods == NULL) {
|
|
||||||
submethods = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
str = ssh_string_from_char(submethods);
|
|
||||||
if (str == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, str);
|
|
||||||
ssh_string_free(str);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
session->auth_state = SSH_AUTH_STATE_KBDINT_SENT;
|
session->auth_state = SSH_AUTH_STATE_KBDINT_SENT;
|
||||||
session->pending_call_state = SSH_PENDING_CALL_AUTH_KBDINT_INIT;
|
session->pending_call_state = SSH_PENDING_CALL_AUTH_KBDINT_INIT;
|
||||||
@@ -1642,7 +1332,7 @@ pending:
|
|||||||
return rc;
|
return rc;
|
||||||
fail:
|
fail:
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
buffer_reinit(session->out_buffer);
|
ssh_buffer_reinit(session->out_buffer);
|
||||||
|
|
||||||
return SSH_AUTH_ERROR;
|
return SSH_AUTH_ERROR;
|
||||||
}
|
}
|
||||||
@@ -1660,7 +1350,6 @@ fail:
|
|||||||
*/
|
*/
|
||||||
static int ssh_userauth_kbdint_send(ssh_session session)
|
static int ssh_userauth_kbdint_send(ssh_session session)
|
||||||
{
|
{
|
||||||
ssh_string answer;
|
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
int rc;
|
int rc;
|
||||||
if (session->pending_call_state == SSH_PENDING_CALL_AUTH_KBDINT_SEND)
|
if (session->pending_call_state == SSH_PENDING_CALL_AUTH_KBDINT_SEND)
|
||||||
@@ -1669,29 +1358,17 @@ static int ssh_userauth_kbdint_send(ssh_session session)
|
|||||||
ssh_set_error_invalid(session);
|
ssh_set_error_invalid(session);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
rc = buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_INFO_RESPONSE);
|
rc = ssh_buffer_pack(session->out_buffer, "bd",
|
||||||
if (rc < 0) {
|
SSH2_MSG_USERAUTH_INFO_RESPONSE,
|
||||||
goto fail;
|
session->kbdint->nprompts);
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_u32(session->out_buffer, htonl(session->kbdint->nprompts));
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < session->kbdint->nprompts; i++) {
|
for (i = 0; i < session->kbdint->nprompts; i++) {
|
||||||
if (session->kbdint->answers && session->kbdint->answers[i]) {
|
rc = ssh_buffer_pack(session->out_buffer, "s",
|
||||||
answer = ssh_string_from_char(session->kbdint->answers[i]);
|
session->kbdint->answers && session->kbdint->answers[i] ?
|
||||||
} else {
|
session->kbdint->answers[i]:"");
|
||||||
answer = ssh_string_from_char("");
|
|
||||||
}
|
|
||||||
if (answer == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, answer);
|
|
||||||
string_burn(answer);
|
|
||||||
string_free(answer);
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -1716,7 +1393,7 @@ pending:
|
|||||||
return rc;
|
return rc;
|
||||||
fail:
|
fail:
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
buffer_reinit(session->out_buffer);
|
ssh_buffer_reinit(session->out_buffer);
|
||||||
|
|
||||||
return SSH_AUTH_ERROR;
|
return SSH_AUTH_ERROR;
|
||||||
}
|
}
|
||||||
@@ -1728,64 +1405,41 @@ fail:
|
|||||||
* authentication state.
|
* authentication state.
|
||||||
*/
|
*/
|
||||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_info_request) {
|
SSH_PACKET_CALLBACK(ssh_packet_userauth_info_request) {
|
||||||
ssh_string name; /* name of the "asking" window showed to client */
|
ssh_string tmp = NULL;
|
||||||
ssh_string instruction;
|
|
||||||
ssh_string tmp;
|
|
||||||
uint32_t nprompts;
|
uint32_t nprompts;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
int rc;
|
||||||
(void)user;
|
(void)user;
|
||||||
(void)type;
|
(void)type;
|
||||||
|
|
||||||
name = buffer_get_ssh_string(packet);
|
|
||||||
instruction = buffer_get_ssh_string(packet);
|
|
||||||
tmp = buffer_get_ssh_string(packet);
|
|
||||||
buffer_get_u32(packet, &nprompts);
|
|
||||||
|
|
||||||
/* We don't care about tmp */
|
|
||||||
ssh_string_free(tmp);
|
|
||||||
|
|
||||||
if (name == NULL || instruction == NULL) {
|
|
||||||
ssh_string_free(name);
|
|
||||||
ssh_string_free(instruction);
|
|
||||||
ssh_set_error(session, SSH_FATAL, "Invalid USERAUTH_INFO_REQUEST msg");
|
|
||||||
|
|
||||||
return SSH_PACKET_USED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (session->kbdint == NULL) {
|
if (session->kbdint == NULL) {
|
||||||
session->kbdint = ssh_kbdint_new();
|
session->kbdint = ssh_kbdint_new();
|
||||||
if (session->kbdint == NULL) {
|
if (session->kbdint == NULL) {
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
ssh_string_free(name);
|
|
||||||
ssh_string_free(instruction);
|
|
||||||
|
|
||||||
return SSH_PACKET_USED;
|
return SSH_PACKET_USED;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ssh_kbdint_clean(session->kbdint);
|
ssh_kbdint_clean(session->kbdint);
|
||||||
}
|
}
|
||||||
|
|
||||||
session->kbdint->name = ssh_string_to_char(name);
|
rc = ssh_buffer_unpack(packet, "ssSd",
|
||||||
ssh_string_free(name);
|
&session->kbdint->name, /* name of the "asking" window shown to client */
|
||||||
if (session->kbdint->name == NULL) {
|
&session->kbdint->instruction,
|
||||||
ssh_set_error_oom(session);
|
&tmp, /* to ignore */
|
||||||
ssh_kbdint_free(session->kbdint);
|
&nprompts
|
||||||
ssh_string_free(instruction);
|
);
|
||||||
|
|
||||||
return SSH_PACKET_USED;
|
/* We don't care about tmp */
|
||||||
|
ssh_string_free(tmp);
|
||||||
|
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
ssh_set_error(session, SSH_FATAL, "Invalid USERAUTH_INFO_REQUEST msg");
|
||||||
|
ssh_kbdint_free(session->kbdint);
|
||||||
|
session->kbdint = NULL;
|
||||||
|
return SSH_PACKET_USED;
|
||||||
}
|
}
|
||||||
|
|
||||||
session->kbdint->instruction = ssh_string_to_char(instruction);
|
|
||||||
ssh_string_free(instruction);
|
|
||||||
if (session->kbdint->instruction == NULL) {
|
|
||||||
ssh_set_error_oom(session);
|
|
||||||
ssh_kbdint_free(session->kbdint);
|
|
||||||
session->kbdint = NULL;
|
|
||||||
|
|
||||||
return SSH_PACKET_USED;
|
|
||||||
}
|
|
||||||
|
|
||||||
nprompts = ntohl(nprompts);
|
|
||||||
SSH_LOG(SSH_LOG_DEBUG,
|
SSH_LOG(SSH_LOG_DEBUG,
|
||||||
"%d keyboard-interactive prompts", nprompts);
|
"%d keyboard-interactive prompts", nprompts);
|
||||||
if (nprompts > KBDINT_MAX_PROMPT) {
|
if (nprompts > KBDINT_MAX_PROMPT) {
|
||||||
@@ -1823,23 +1477,14 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_info_request) {
|
|||||||
memset(session->kbdint->echo, 0, nprompts);
|
memset(session->kbdint->echo, 0, nprompts);
|
||||||
|
|
||||||
for (i = 0; i < nprompts; i++) {
|
for (i = 0; i < nprompts; i++) {
|
||||||
tmp = buffer_get_ssh_string(packet);
|
rc = ssh_buffer_unpack(packet, "sb",
|
||||||
buffer_get_u8(packet, &session->kbdint->echo[i]);
|
&session->kbdint->prompts[i],
|
||||||
if (tmp == NULL) {
|
&session->kbdint->echo[i]);
|
||||||
|
if (rc == SSH_ERROR) {
|
||||||
ssh_set_error(session, SSH_FATAL, "Short INFO_REQUEST packet");
|
ssh_set_error(session, SSH_FATAL, "Short INFO_REQUEST packet");
|
||||||
ssh_kbdint_free(session->kbdint);
|
ssh_kbdint_free(session->kbdint);
|
||||||
session->kbdint = NULL;
|
session->kbdint = NULL;
|
||||||
|
|
||||||
return SSH_PACKET_USED;
|
|
||||||
}
|
|
||||||
session->kbdint->prompts[i] = ssh_string_to_char(tmp);
|
|
||||||
ssh_string_free(tmp);
|
|
||||||
if (session->kbdint->prompts[i] == NULL) {
|
|
||||||
ssh_set_error_oom(session);
|
|
||||||
session->kbdint->nprompts = i;
|
|
||||||
ssh_kbdint_free(session->kbdint);
|
|
||||||
session->kbdint = NULL;
|
|
||||||
|
|
||||||
return SSH_PACKET_USED;
|
return SSH_PACKET_USED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1907,7 +1552,7 @@ int ssh_userauth_kbdint(ssh_session session, const char *user,
|
|||||||
* This should not happen
|
* This should not happen
|
||||||
*/
|
*/
|
||||||
rc = SSH_AUTH_ERROR;
|
rc = SSH_AUTH_ERROR;
|
||||||
ssh_set_error(session,SSH_FATAL,"Invalid state in %s", __FUNCTION__);
|
ssh_set_error(session, SSH_FATAL, "Invalid state in %s", __func__);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/base64.c
13
src/base64.c
@@ -82,13 +82,18 @@ ssh_buffer base64_to_bin(const char *source) {
|
|||||||
SAFE_FREE(base64);
|
SAFE_FREE(base64);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* The base64 buffer often contains sensitive data. Make sure we don't leak
|
||||||
|
* sensitive data
|
||||||
|
*/
|
||||||
|
ssh_buffer_set_secure(buffer);
|
||||||
|
|
||||||
len = strlen(ptr);
|
len = strlen(ptr);
|
||||||
while (len > 4) {
|
while (len > 4) {
|
||||||
if (_base64_to_bin(block, ptr, 3) < 0) {
|
if (_base64_to_bin(block, ptr, 3) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (buffer_add_data(buffer, block, 3) < 0) {
|
if (ssh_buffer_add_data(buffer, block, 3) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
len -= 4;
|
len -= 4;
|
||||||
@@ -112,7 +117,7 @@ ssh_buffer base64_to_bin(const char *source) {
|
|||||||
if (_base64_to_bin(block, ptr, 3) < 0) {
|
if (_base64_to_bin(block, ptr, 3) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (buffer_add_data(buffer, block, 3) < 0) {
|
if (ssh_buffer_add_data(buffer, block, 3) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
SAFE_FREE(base64);
|
SAFE_FREE(base64);
|
||||||
@@ -131,7 +136,7 @@ ssh_buffer base64_to_bin(const char *source) {
|
|||||||
if (_base64_to_bin(block, ptr, 1) < 0) {
|
if (_base64_to_bin(block, ptr, 1) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (buffer_add_data(buffer, block, 1) < 0) {
|
if (ssh_buffer_add_data(buffer, block, 1) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
SAFE_FREE(base64);
|
SAFE_FREE(base64);
|
||||||
@@ -149,7 +154,7 @@ ssh_buffer base64_to_bin(const char *source) {
|
|||||||
if (_base64_to_bin(block, ptr, 2) < 0) {
|
if (_base64_to_bin(block, ptr, 2) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (buffer_add_data(buffer,block,2) < 0) {
|
if (ssh_buffer_add_data(buffer,block,2) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
SAFE_FREE(base64);
|
SAFE_FREE(base64);
|
||||||
|
|||||||
111
src/bignum.c
Normal file
111
src/bignum.c
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the SSH Library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 by Aris Adamantiadis <aris@badcode.be>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "libssh/priv.h"
|
||||||
|
#include "libssh/bignum.h"
|
||||||
|
#include "libssh/string.h"
|
||||||
|
|
||||||
|
ssh_string make_bignum_string(bignum num) {
|
||||||
|
ssh_string ptr = NULL;
|
||||||
|
int pad = 0;
|
||||||
|
unsigned int len = bignum_num_bytes(num);
|
||||||
|
unsigned int bits = bignum_num_bits(num);
|
||||||
|
|
||||||
|
if (len == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the first bit is set we have a negative number */
|
||||||
|
if (!(bits % 8) && bignum_is_bit_set(num, bits - 1)) {
|
||||||
|
pad++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_CRYPTO
|
||||||
|
fprintf(stderr, "%d bits, %d bytes, %d padding\n", bits, len, pad);
|
||||||
|
#endif /* DEBUG_CRYPTO */
|
||||||
|
|
||||||
|
ptr = ssh_string_new(len + pad);
|
||||||
|
if (ptr == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We have a negative number so we need a leading zero */
|
||||||
|
if (pad) {
|
||||||
|
ptr->data[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBGCRYPT
|
||||||
|
bignum_bn2bin(num, len, ptr->data + pad);
|
||||||
|
#elif HAVE_LIBCRYPTO
|
||||||
|
bignum_bn2bin(num, ptr->data + pad);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bignum make_string_bn(ssh_string string){
|
||||||
|
bignum bn = NULL;
|
||||||
|
unsigned int len = ssh_string_len(string);
|
||||||
|
|
||||||
|
#ifdef DEBUG_CRYPTO
|
||||||
|
fprintf(stderr, "Importing a %d bits, %d bytes object ...\n",
|
||||||
|
len * 8, len);
|
||||||
|
#endif /* DEBUG_CRYPTO */
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBGCRYPT
|
||||||
|
bignum_bin2bn(string->data, len, &bn);
|
||||||
|
#elif defined HAVE_LIBCRYPTO
|
||||||
|
bn = bignum_bin2bn(string->data, len, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return bn;
|
||||||
|
}
|
||||||
|
|
||||||
|
void make_string_bn_inplace(ssh_string string, bignum bnout) {
|
||||||
|
unsigned int 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);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* prints the bignum on stderr */
|
||||||
|
void ssh_print_bignum(const char *which, bignum num) {
|
||||||
|
#ifdef HAVE_LIBGCRYPT
|
||||||
|
unsigned char *hex = NULL;
|
||||||
|
bignum_bn2hex(num, &hex);
|
||||||
|
#elif defined HAVE_LIBCRYPTO
|
||||||
|
char *hex = NULL;
|
||||||
|
hex = bignum_bn2hex(num);
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, "%s value: ", which);
|
||||||
|
fprintf(stderr, "%s\n", (hex == NULL) ? "(null)" : (char *) hex);
|
||||||
|
#ifdef HAVE_LIBGCRYPT
|
||||||
|
SAFE_FREE(hex);
|
||||||
|
#elif defined HAVE_LIBCRYPTO
|
||||||
|
OPENSSL_free(hex);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
109
src/bind.c
109
src/bind.c
@@ -109,7 +109,7 @@ static socket_t bind_socket(ssh_bind sshbind, const char *hostname,
|
|||||||
"Setting socket options failed: %s",
|
"Setting socket options failed: %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
freeaddrinfo (ai);
|
freeaddrinfo (ai);
|
||||||
close(s);
|
CLOSE_SOCKET(s);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +121,7 @@ static socket_t bind_socket(ssh_bind sshbind, const char *hostname,
|
|||||||
port,
|
port,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
freeaddrinfo (ai);
|
freeaddrinfo (ai);
|
||||||
close(s);
|
CLOSE_SOCKET(s);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,26 +144,19 @@ ssh_bind ssh_bind_new(void) {
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ssh_bind_listen(ssh_bind sshbind) {
|
static int ssh_bind_import_keys(ssh_bind sshbind) {
|
||||||
const char *host;
|
|
||||||
socket_t fd;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (ssh_init() < 0) {
|
|
||||||
ssh_set_error(sshbind, SSH_FATAL, "ssh_init() failed");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sshbind->ecdsakey == NULL &&
|
if (sshbind->ecdsakey == NULL &&
|
||||||
sshbind->dsakey == NULL &&
|
sshbind->dsakey == NULL &&
|
||||||
sshbind->rsakey == NULL) {
|
sshbind->rsakey == NULL) {
|
||||||
ssh_set_error(sshbind, SSH_FATAL,
|
ssh_set_error(sshbind, SSH_FATAL,
|
||||||
"DSA or RSA host key file must be set before listen()");
|
"ECDSA, DSA, or RSA host key file must be set");
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_ECC
|
#ifdef HAVE_ECC
|
||||||
if (sshbind->ecdsakey) {
|
if (sshbind->ecdsa == NULL && sshbind->ecdsakey != NULL) {
|
||||||
rc = ssh_pki_import_privkey_file(sshbind->ecdsakey,
|
rc = ssh_pki_import_privkey_file(sshbind->ecdsakey,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -179,12 +172,13 @@ int ssh_bind_listen(ssh_bind sshbind) {
|
|||||||
ssh_set_error(sshbind, SSH_FATAL,
|
ssh_set_error(sshbind, SSH_FATAL,
|
||||||
"The ECDSA host key has the wrong type");
|
"The ECDSA host key has the wrong type");
|
||||||
ssh_key_free(sshbind->ecdsa);
|
ssh_key_free(sshbind->ecdsa);
|
||||||
|
sshbind->ecdsa = NULL;
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (sshbind->dsakey) {
|
if (sshbind->dsa == NULL && sshbind->dsakey != NULL) {
|
||||||
rc = ssh_pki_import_privkey_file(sshbind->dsakey,
|
rc = ssh_pki_import_privkey_file(sshbind->dsakey,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -201,11 +195,12 @@ int ssh_bind_listen(ssh_bind sshbind) {
|
|||||||
"The DSA host key has the wrong type: %d",
|
"The DSA host key has the wrong type: %d",
|
||||||
ssh_key_type(sshbind->dsa));
|
ssh_key_type(sshbind->dsa));
|
||||||
ssh_key_free(sshbind->dsa);
|
ssh_key_free(sshbind->dsa);
|
||||||
|
sshbind->dsa = NULL;
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sshbind->rsakey) {
|
if (sshbind->rsa == NULL && sshbind->rsakey != NULL) {
|
||||||
rc = ssh_pki_import_privkey_file(sshbind->rsakey,
|
rc = ssh_pki_import_privkey_file(sshbind->rsakey,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -222,10 +217,29 @@ int ssh_bind_listen(ssh_bind sshbind) {
|
|||||||
ssh_set_error(sshbind, SSH_FATAL,
|
ssh_set_error(sshbind, SSH_FATAL,
|
||||||
"The RSA host key has the wrong type");
|
"The RSA host key has the wrong type");
|
||||||
ssh_key_free(sshbind->rsa);
|
ssh_key_free(sshbind->rsa);
|
||||||
|
sshbind->rsa = NULL;
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ssh_bind_listen(ssh_bind sshbind) {
|
||||||
|
const char *host;
|
||||||
|
socket_t fd;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (ssh_init() < 0) {
|
||||||
|
ssh_set_error(sshbind, SSH_FATAL, "ssh_init() failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_bind_import_keys(sshbind);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (sshbind->bindfd == SSH_INVALID_SOCKET) {
|
if (sshbind->bindfd == SSH_INVALID_SOCKET) {
|
||||||
host = sshbind->bindaddr;
|
host = sshbind->bindaddr;
|
||||||
if (host == NULL) {
|
if (host == NULL) {
|
||||||
@@ -235,20 +249,25 @@ int ssh_bind_listen(ssh_bind sshbind) {
|
|||||||
fd = bind_socket(sshbind, host, sshbind->bindport);
|
fd = bind_socket(sshbind, host, sshbind->bindport);
|
||||||
if (fd == SSH_INVALID_SOCKET) {
|
if (fd == SSH_INVALID_SOCKET) {
|
||||||
ssh_key_free(sshbind->dsa);
|
ssh_key_free(sshbind->dsa);
|
||||||
|
sshbind->dsa = NULL;
|
||||||
ssh_key_free(sshbind->rsa);
|
ssh_key_free(sshbind->rsa);
|
||||||
|
sshbind->rsa = NULL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
sshbind->bindfd = fd;
|
|
||||||
|
|
||||||
if (listen(fd, 10) < 0) {
|
if (listen(fd, 10) < 0) {
|
||||||
ssh_set_error(sshbind, SSH_FATAL,
|
ssh_set_error(sshbind, SSH_FATAL,
|
||||||
"Listening to socket %d: %s",
|
"Listening to socket %d: %s",
|
||||||
fd, strerror(errno));
|
fd, strerror(errno));
|
||||||
close(fd);
|
CLOSE_SOCKET(fd);
|
||||||
ssh_key_free(sshbind->dsa);
|
ssh_key_free(sshbind->dsa);
|
||||||
|
sshbind->dsa = NULL;
|
||||||
ssh_key_free(sshbind->rsa);
|
ssh_key_free(sshbind->rsa);
|
||||||
|
sshbind->rsa = NULL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sshbind->bindfd = fd;
|
||||||
} else {
|
} else {
|
||||||
SSH_LOG(SSH_LOG_INFO, "Using app-provided bind socket");
|
SSH_LOG(SSH_LOG_INFO, "Using app-provided bind socket");
|
||||||
}
|
}
|
||||||
@@ -331,21 +350,27 @@ void ssh_bind_free(ssh_bind sshbind){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sshbind->bindfd >= 0) {
|
if (sshbind->bindfd >= 0) {
|
||||||
#ifdef _WIN32
|
CLOSE_SOCKET(sshbind->bindfd);
|
||||||
closesocket(sshbind->bindfd);
|
|
||||||
#else
|
|
||||||
close(sshbind->bindfd);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
sshbind->bindfd = SSH_INVALID_SOCKET;
|
sshbind->bindfd = SSH_INVALID_SOCKET;
|
||||||
|
|
||||||
/* options */
|
/* options */
|
||||||
SAFE_FREE(sshbind->banner);
|
SAFE_FREE(sshbind->banner);
|
||||||
|
SAFE_FREE(sshbind->bindaddr);
|
||||||
|
|
||||||
SAFE_FREE(sshbind->dsakey);
|
SAFE_FREE(sshbind->dsakey);
|
||||||
SAFE_FREE(sshbind->rsakey);
|
SAFE_FREE(sshbind->rsakey);
|
||||||
SAFE_FREE(sshbind->dsa);
|
SAFE_FREE(sshbind->ecdsakey);
|
||||||
SAFE_FREE(sshbind->rsa);
|
SAFE_FREE(sshbind->ed25519key);
|
||||||
SAFE_FREE(sshbind->bindaddr);
|
|
||||||
|
ssh_key_free(sshbind->dsa);
|
||||||
|
sshbind->dsa = NULL;
|
||||||
|
ssh_key_free(sshbind->rsa);
|
||||||
|
sshbind->rsa = NULL;
|
||||||
|
ssh_key_free(sshbind->ecdsa);
|
||||||
|
sshbind->ecdsa = NULL;
|
||||||
|
ssh_key_free(sshbind->ed25519);
|
||||||
|
sshbind->ed25519 = NULL;
|
||||||
|
|
||||||
for (i = 0; i < 10; i++) {
|
for (i = 0; i < 10; i++) {
|
||||||
if (sshbind->wanted_methods[i]) {
|
if (sshbind->wanted_methods[i]) {
|
||||||
@@ -357,7 +382,7 @@ void ssh_bind_free(ssh_bind sshbind){
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
|
int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
|
||||||
int i;
|
int i, rc;
|
||||||
|
|
||||||
if (session == NULL){
|
if (session == NULL){
|
||||||
ssh_set_error(sshbind, SSH_FATAL,"session is null");
|
ssh_set_error(sshbind, SSH_FATAL,"session is null");
|
||||||
@@ -368,7 +393,7 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
|
|||||||
session->version = 2;
|
session->version = 2;
|
||||||
|
|
||||||
/* copy options */
|
/* copy options */
|
||||||
for (i = 0; i < 10; ++i) {
|
for (i = 0; i < 10; i++) {
|
||||||
if (sshbind->wanted_methods[i]) {
|
if (sshbind->wanted_methods[i]) {
|
||||||
session->opts.wanted_methods[i] = strdup(sshbind->wanted_methods[i]);
|
session->opts.wanted_methods[i] = strdup(sshbind->wanted_methods[i]);
|
||||||
if (session->opts.wanted_methods[i] == NULL) {
|
if (session->opts.wanted_methods[i] == NULL) {
|
||||||
@@ -388,7 +413,8 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
|
|||||||
}
|
}
|
||||||
|
|
||||||
session->common.log_verbosity = sshbind->common.log_verbosity;
|
session->common.log_verbosity = sshbind->common.log_verbosity;
|
||||||
|
if(sshbind->banner != NULL)
|
||||||
|
session->opts.custombanner = strdup(sshbind->banner);
|
||||||
ssh_socket_free(session->socket);
|
ssh_socket_free(session->socket);
|
||||||
session->socket = ssh_socket_new(session);
|
session->socket = ssh_socket_new(session);
|
||||||
if (session->socket == NULL) {
|
if (session->socket == NULL) {
|
||||||
@@ -399,6 +425,16 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
|
|||||||
ssh_socket_set_fd(session->socket, fd);
|
ssh_socket_set_fd(session->socket, fd);
|
||||||
ssh_socket_get_poll_handle_out(session->socket);
|
ssh_socket_get_poll_handle_out(session->socket);
|
||||||
|
|
||||||
|
/* We must try to import any keys that could be imported in case
|
||||||
|
* we are not using ssh_bind_listen (which is the other place
|
||||||
|
* where keys can be imported) on this ssh_bind and are instead
|
||||||
|
* only using ssh_bind_accept_fd to manage sockets ourselves.
|
||||||
|
*/
|
||||||
|
rc = ssh_bind_import_keys(sshbind);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_ECC
|
#ifdef HAVE_ECC
|
||||||
if (sshbind->ecdsa) {
|
if (sshbind->ecdsa) {
|
||||||
session->srv.ecdsa_key = ssh_key_dup(sshbind->ecdsa);
|
session->srv.ecdsa_key = ssh_key_dup(sshbind->ecdsa);
|
||||||
@@ -422,6 +458,16 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (sshbind->ed25519 != NULL) {
|
||||||
|
session->srv.ed25519_key = ssh_key_dup(sshbind->ed25519);
|
||||||
|
if (session->srv.ed25519_key == NULL){
|
||||||
|
ssh_set_error_oom(sshbind);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* force PRNG to change state in case we fork after ssh_bind_accept */
|
||||||
|
ssh_reseed();
|
||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,13 +495,8 @@ int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
|
|||||||
rc = ssh_bind_accept_fd(sshbind, session, fd);
|
rc = ssh_bind_accept_fd(sshbind, session, fd);
|
||||||
|
|
||||||
if(rc == SSH_ERROR){
|
if(rc == SSH_ERROR){
|
||||||
#ifdef _WIN32
|
CLOSE_SOCKET(fd);
|
||||||
closesocket(fd);
|
ssh_socket_free(session->socket);
|
||||||
#else
|
|
||||||
close(fd);
|
|
||||||
#endif
|
|
||||||
if (session->socket)
|
|
||||||
ssh_socket_close(session->socket);
|
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|||||||
499
src/buffer.c
499
src/buffer.c
@@ -24,6 +24,7 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
@@ -32,6 +33,8 @@
|
|||||||
|
|
||||||
#include "libssh/priv.h"
|
#include "libssh/priv.h"
|
||||||
#include "libssh/buffer.h"
|
#include "libssh/buffer.h"
|
||||||
|
#include "libssh/misc.h"
|
||||||
|
#include "libssh/bignum.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup libssh_buffer The SSH buffer functions.
|
* @defgroup libssh_buffer The SSH buffer functions.
|
||||||
@@ -104,13 +107,25 @@ void ssh_buffer_free(struct ssh_buffer_struct *buffer) {
|
|||||||
|
|
||||||
if (buffer->data) {
|
if (buffer->data) {
|
||||||
/* burn the data */
|
/* burn the data */
|
||||||
memset(buffer->data, 0, buffer->allocated);
|
BURN_BUFFER(buffer->data, buffer->allocated);
|
||||||
SAFE_FREE(buffer->data);
|
SAFE_FREE(buffer->data);
|
||||||
}
|
}
|
||||||
memset(buffer, 'X', sizeof(*buffer));
|
BURN_BUFFER(buffer, sizeof(struct ssh_buffer_struct));
|
||||||
SAFE_FREE(buffer);
|
SAFE_FREE(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the buffer as secure.
|
||||||
|
*
|
||||||
|
* A secure buffer will never leave cleartext data in the heap
|
||||||
|
* after being reallocated or freed.
|
||||||
|
*
|
||||||
|
* @param[in] buffer buffer to set secure.
|
||||||
|
*/
|
||||||
|
void ssh_buffer_set_secure(ssh_buffer buffer){
|
||||||
|
buffer->secure = 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int realloc_buffer(struct ssh_buffer_struct *buffer, size_t needed) {
|
static int realloc_buffer(struct ssh_buffer_struct *buffer, size_t needed) {
|
||||||
size_t smallest = 1;
|
size_t smallest = 1;
|
||||||
char *new;
|
char *new;
|
||||||
@@ -125,9 +140,20 @@ static int realloc_buffer(struct ssh_buffer_struct *buffer, size_t needed) {
|
|||||||
smallest <<= 1;
|
smallest <<= 1;
|
||||||
}
|
}
|
||||||
needed = smallest;
|
needed = smallest;
|
||||||
new = realloc(buffer->data, needed);
|
if (buffer->secure){
|
||||||
if (new == NULL) {
|
new = malloc(needed);
|
||||||
return -1;
|
if (new == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(new, buffer->data,buffer->used);
|
||||||
|
BURN_BUFFER(buffer->data, buffer->used);
|
||||||
|
SAFE_FREE(buffer->data);
|
||||||
|
} else {
|
||||||
|
new = realloc(buffer->data, needed);
|
||||||
|
if (new == NULL) {
|
||||||
|
buffer->data = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
buffer->data = new;
|
buffer->data = new;
|
||||||
buffer->allocated = needed;
|
buffer->allocated = needed;
|
||||||
@@ -140,12 +166,20 @@ static int realloc_buffer(struct ssh_buffer_struct *buffer, size_t needed) {
|
|||||||
* @param buffer SSH buffer
|
* @param buffer SSH buffer
|
||||||
*/
|
*/
|
||||||
static void buffer_shift(ssh_buffer buffer){
|
static void buffer_shift(ssh_buffer buffer){
|
||||||
|
uint32_t burn_pos = buffer->pos;
|
||||||
|
|
||||||
buffer_verify(buffer);
|
buffer_verify(buffer);
|
||||||
if(buffer->pos==0)
|
if(buffer->pos==0)
|
||||||
return;
|
return;
|
||||||
memmove(buffer->data, buffer->data + buffer->pos, buffer->used - buffer->pos);
|
memmove(buffer->data, buffer->data + buffer->pos, buffer->used - buffer->pos);
|
||||||
buffer->used -= buffer->pos;
|
buffer->used -= buffer->pos;
|
||||||
buffer->pos=0;
|
buffer->pos=0;
|
||||||
|
|
||||||
|
if (buffer->secure){
|
||||||
|
void *ptr = buffer->data + buffer->used;
|
||||||
|
BURN_BUFFER(ptr, burn_pos);
|
||||||
|
}
|
||||||
|
|
||||||
buffer_verify(buffer);
|
buffer_verify(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,9 +192,10 @@ static void buffer_shift(ssh_buffer buffer){
|
|||||||
*
|
*
|
||||||
* @return 0 on success, < 0 on error.
|
* @return 0 on success, < 0 on error.
|
||||||
*/
|
*/
|
||||||
int buffer_reinit(struct ssh_buffer_struct *buffer) {
|
int ssh_buffer_reinit(struct ssh_buffer_struct *buffer)
|
||||||
|
{
|
||||||
buffer_verify(buffer);
|
buffer_verify(buffer);
|
||||||
memset(buffer->data, 0, buffer->used);
|
BURN_BUFFER(buffer->data, buffer->used);
|
||||||
buffer->used = 0;
|
buffer->used = 0;
|
||||||
buffer->pos = 0;
|
buffer->pos = 0;
|
||||||
if(buffer->allocated > 127) {
|
if(buffer->allocated > 127) {
|
||||||
@@ -185,9 +220,14 @@ int buffer_reinit(struct ssh_buffer_struct *buffer) {
|
|||||||
*
|
*
|
||||||
* @return 0 on success, < 0 on error.
|
* @return 0 on success, < 0 on error.
|
||||||
*/
|
*/
|
||||||
int buffer_add_data(struct ssh_buffer_struct *buffer, const void *data, uint32_t len) {
|
int ssh_buffer_add_data(struct ssh_buffer_struct *buffer, const void *data, uint32_t len)
|
||||||
|
{
|
||||||
buffer_verify(buffer);
|
buffer_verify(buffer);
|
||||||
|
|
||||||
|
if (data == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (buffer->used + len < len) {
|
if (buffer->used + len < len) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -221,8 +261,12 @@ int buffer_add_ssh_string(struct ssh_buffer_struct *buffer,
|
|||||||
struct ssh_string_struct *string) {
|
struct ssh_string_struct *string) {
|
||||||
uint32_t len = 0;
|
uint32_t len = 0;
|
||||||
|
|
||||||
|
if (string == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
len = ssh_string_len(string);
|
len = ssh_string_len(string);
|
||||||
if (buffer_add_data(buffer, string, len + sizeof(uint32_t)) < 0) {
|
if (ssh_buffer_add_data(buffer, string, len + sizeof(uint32_t)) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,12 +284,16 @@ int buffer_add_ssh_string(struct ssh_buffer_struct *buffer,
|
|||||||
*
|
*
|
||||||
* @return 0 on success, -1 on error.
|
* @return 0 on success, -1 on error.
|
||||||
*/
|
*/
|
||||||
int buffer_add_u32(struct ssh_buffer_struct *buffer,uint32_t data){
|
int buffer_add_u32(struct ssh_buffer_struct *buffer,uint32_t data)
|
||||||
if (buffer_add_data(buffer, &data, sizeof(data)) < 0) {
|
{
|
||||||
return -1;
|
int rc;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
rc = ssh_buffer_add_data(buffer, &data, sizeof(data));
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -259,12 +307,16 @@ int buffer_add_u32(struct ssh_buffer_struct *buffer,uint32_t data){
|
|||||||
*
|
*
|
||||||
* @return 0 on success, -1 on error.
|
* @return 0 on success, -1 on error.
|
||||||
*/
|
*/
|
||||||
int buffer_add_u16(struct ssh_buffer_struct *buffer,uint16_t data){
|
int buffer_add_u16(struct ssh_buffer_struct *buffer,uint16_t data)
|
||||||
if (buffer_add_data(buffer, &data, sizeof(data)) < 0) {
|
{
|
||||||
return -1;
|
int rc;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
rc = ssh_buffer_add_data(buffer, &data, sizeof(data));
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -278,12 +330,16 @@ int buffer_add_u16(struct ssh_buffer_struct *buffer,uint16_t data){
|
|||||||
*
|
*
|
||||||
* @return 0 on success, -1 on error.
|
* @return 0 on success, -1 on error.
|
||||||
*/
|
*/
|
||||||
int buffer_add_u64(struct ssh_buffer_struct *buffer, uint64_t data){
|
int buffer_add_u64(struct ssh_buffer_struct *buffer, uint64_t data)
|
||||||
if (buffer_add_data(buffer, &data, sizeof(data)) < 0) {
|
{
|
||||||
return -1;
|
int rc;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
rc = ssh_buffer_add_data(buffer, &data, sizeof(data));
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -297,12 +353,16 @@ int buffer_add_u64(struct ssh_buffer_struct *buffer, uint64_t data){
|
|||||||
*
|
*
|
||||||
* @return 0 on success, -1 on error.
|
* @return 0 on success, -1 on error.
|
||||||
*/
|
*/
|
||||||
int buffer_add_u8(struct ssh_buffer_struct *buffer,uint8_t data){
|
int buffer_add_u8(struct ssh_buffer_struct *buffer,uint8_t data)
|
||||||
if (buffer_add_data(buffer, &data, sizeof(uint8_t)) < 0) {
|
{
|
||||||
return -1;
|
int rc;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
rc = ssh_buffer_add_data(buffer, &data, sizeof(uint8_t));
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -360,12 +420,18 @@ int buffer_prepend_data(struct ssh_buffer_struct *buffer, const void *data,
|
|||||||
* @return 0 on success, -1 on error.
|
* @return 0 on success, -1 on error.
|
||||||
*/
|
*/
|
||||||
int buffer_add_buffer(struct ssh_buffer_struct *buffer,
|
int buffer_add_buffer(struct ssh_buffer_struct *buffer,
|
||||||
struct ssh_buffer_struct *source) {
|
struct ssh_buffer_struct *source)
|
||||||
if (buffer_add_data(buffer, buffer_get_rest(source), buffer_get_rest_len(source)) < 0) {
|
{
|
||||||
return -1;
|
int rc;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
rc = ssh_buffer_add_data(buffer,
|
||||||
|
buffer_get_rest(source),
|
||||||
|
buffer_get_rest_len(source));
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -621,6 +687,371 @@ struct ssh_string_struct *buffer_get_mpint(struct ssh_buffer_struct *buffer) {
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @internal
|
||||||
|
* @brief Add multiple values in a buffer on a single function call
|
||||||
|
* @param[in] buffer The buffer to add to
|
||||||
|
* @param[in] format A format string of arguments.
|
||||||
|
* @param[in] ap A va_list of arguments.
|
||||||
|
* @returns SSH_OK on success
|
||||||
|
* SSH_ERROR on error
|
||||||
|
* @see ssh_buffer_add_format() for format list values.
|
||||||
|
*/
|
||||||
|
int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
|
||||||
|
const char *format,
|
||||||
|
int argc,
|
||||||
|
va_list ap)
|
||||||
|
{
|
||||||
|
int rc = SSH_ERROR;
|
||||||
|
const char *p;
|
||||||
|
union {
|
||||||
|
uint8_t byte;
|
||||||
|
uint16_t word;
|
||||||
|
uint32_t dword;
|
||||||
|
uint64_t qword;
|
||||||
|
ssh_string string;
|
||||||
|
void *data;
|
||||||
|
} o;
|
||||||
|
char *cstring;
|
||||||
|
bignum b;
|
||||||
|
size_t len;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
for (p = format, count = 0; *p != '\0'; p++, count++) {
|
||||||
|
/* Invalid number of arguments passed */
|
||||||
|
if (argc != -1 && count > argc) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(*p) {
|
||||||
|
case 'b':
|
||||||
|
o.byte = (uint8_t)va_arg(ap, unsigned int);
|
||||||
|
rc = buffer_add_u8(buffer, o.byte);
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
o.word = (uint16_t)va_arg(ap, unsigned int);
|
||||||
|
o.word = htons(o.word);
|
||||||
|
rc = buffer_add_u16(buffer, o.word);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
o.dword = va_arg(ap, uint32_t);
|
||||||
|
o.dword = htonl(o.dword);
|
||||||
|
rc = buffer_add_u32(buffer, o.dword);
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
o.qword = va_arg(ap, uint64_t);
|
||||||
|
o.qword = htonll(o.qword);
|
||||||
|
rc = buffer_add_u64(buffer, o.qword);
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
o.string = va_arg(ap, ssh_string);
|
||||||
|
rc = buffer_add_ssh_string(buffer, o.string);
|
||||||
|
o.string = NULL;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
cstring = va_arg(ap, char *);
|
||||||
|
len = strlen(cstring);
|
||||||
|
rc = buffer_add_u32(buffer, htonl(len));
|
||||||
|
if (rc == SSH_OK){
|
||||||
|
rc = ssh_buffer_add_data(buffer, cstring, len);
|
||||||
|
}
|
||||||
|
cstring = NULL;
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
len = va_arg(ap, size_t);
|
||||||
|
|
||||||
|
o.data = va_arg(ap, void *);
|
||||||
|
count++; /* increase argument count */
|
||||||
|
|
||||||
|
rc = ssh_buffer_add_data(buffer, o.data, len);
|
||||||
|
o.data = NULL;
|
||||||
|
break;
|
||||||
|
case 'B':
|
||||||
|
b = va_arg(ap, bignum);
|
||||||
|
o.string = make_bignum_string(b);
|
||||||
|
if(o.string == NULL){
|
||||||
|
rc = SSH_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rc = buffer_add_ssh_string(buffer, o.string);
|
||||||
|
SAFE_FREE(o.string);
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
cstring = va_arg(ap, char *);
|
||||||
|
len = strlen(cstring);
|
||||||
|
rc = ssh_buffer_add_data(buffer, cstring, len);
|
||||||
|
cstring = NULL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SSH_LOG(SSH_LOG_WARN, "Invalid buffer format %c", *p);
|
||||||
|
rc = SSH_ERROR;
|
||||||
|
}
|
||||||
|
if (rc != SSH_OK){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc != -1 && argc != count) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc != SSH_ERROR){
|
||||||
|
/* 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @internal
|
||||||
|
* @brief Add multiple values in a buffer on a single function call
|
||||||
|
* @param[in] buffer The buffer to add to
|
||||||
|
* @param[in] format A format string of arguments. This string contains single
|
||||||
|
* letters describing the order and type of arguments:
|
||||||
|
* 'b': uint8_t (pushed in network byte order)
|
||||||
|
* 'w': uint16_t (pushed in network byte order)
|
||||||
|
* 'd': uint32_t (pushed in network byte order)
|
||||||
|
* 'q': uint64_t (pushed in network byte order)
|
||||||
|
* 'S': ssh_string
|
||||||
|
* 's': char * (C string, pushed as SSH string)
|
||||||
|
* 't': char * (C string, pushed as free text)
|
||||||
|
* 'P': size_t, void * (len of data, pointer to data)
|
||||||
|
* only pushes data.
|
||||||
|
* 'B': bignum (pushed as SSH string)
|
||||||
|
* @returns SSH_OK on success
|
||||||
|
* SSH_ERROR on error
|
||||||
|
* @warning when using 'P' with a constant size (e.g. 8), do not
|
||||||
|
* forget to cast to (size_t).
|
||||||
|
*/
|
||||||
|
int _ssh_buffer_pack(struct ssh_buffer_struct *buffer,
|
||||||
|
const char *format,
|
||||||
|
int argc,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
va_start(ap, argc);
|
||||||
|
rc = ssh_buffer_pack_va(buffer, format, argc, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @internal
|
||||||
|
* @brief Get multiple values from a buffer on a single function call
|
||||||
|
* @param[in] buffer The buffer to get from
|
||||||
|
* @param[in] format A format string of arguments.
|
||||||
|
* @param[in] ap A va_list of arguments.
|
||||||
|
* @returns SSH_OK on success
|
||||||
|
* SSH_ERROR on error
|
||||||
|
* @see ssh_buffer_get_format() for format list values.
|
||||||
|
*/
|
||||||
|
int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||||
|
const char *format,
|
||||||
|
int argc,
|
||||||
|
va_list ap)
|
||||||
|
{
|
||||||
|
int rc = SSH_ERROR;
|
||||||
|
const char *p, *last;
|
||||||
|
union {
|
||||||
|
uint8_t *byte;
|
||||||
|
uint16_t *word;
|
||||||
|
uint32_t *dword;
|
||||||
|
uint64_t *qword;
|
||||||
|
ssh_string *string;
|
||||||
|
char **cstring;
|
||||||
|
void **data;
|
||||||
|
} o;
|
||||||
|
size_t len, rlen;
|
||||||
|
uint32_t u32len;
|
||||||
|
va_list ap_copy;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
/* copy the argument list in case a rollback is needed */
|
||||||
|
va_copy(ap_copy, ap);
|
||||||
|
|
||||||
|
for (p = format, count = 0; *p != '\0'; p++, count++) {
|
||||||
|
/* Invalid number of arguments passed */
|
||||||
|
if (argc != -1 && count > argc) {
|
||||||
|
va_end(ap_copy);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (*p) {
|
||||||
|
case 'b':
|
||||||
|
o.byte = va_arg(ap, uint8_t *);
|
||||||
|
rlen = buffer_get_u8(buffer, o.byte);
|
||||||
|
rc = rlen==1 ? SSH_OK : SSH_ERROR;
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
o.word = va_arg(ap, uint16_t *);
|
||||||
|
rlen = buffer_get_data(buffer, o.word, sizeof(uint16_t));
|
||||||
|
*o.word = ntohs(*o.word);
|
||||||
|
rc = rlen==2 ? SSH_OK : SSH_ERROR;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
o.dword = va_arg(ap, uint32_t *);
|
||||||
|
rlen = buffer_get_u32(buffer, o.dword);
|
||||||
|
*o.dword = ntohl(*o.dword);
|
||||||
|
rc = rlen==4 ? SSH_OK : SSH_ERROR;
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
o.qword = va_arg(ap, uint64_t*);
|
||||||
|
rlen = buffer_get_u64(buffer, o.qword);
|
||||||
|
*o.qword = ntohll(*o.qword);
|
||||||
|
rc = rlen==8 ? SSH_OK : SSH_ERROR;
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
o.string = va_arg(ap, ssh_string *);
|
||||||
|
*o.string = buffer_get_ssh_string(buffer);
|
||||||
|
rc = *o.string != NULL ? SSH_OK : SSH_ERROR;
|
||||||
|
o.string = NULL;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
o.cstring = va_arg(ap, char **);
|
||||||
|
*o.cstring = NULL;
|
||||||
|
rc = buffer_get_u32(buffer, &u32len);
|
||||||
|
if (rc != 4){
|
||||||
|
rc = SSH_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
len = ntohl(u32len);
|
||||||
|
if (len > UINT_MAX - 1){
|
||||||
|
rc = SSH_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*o.cstring = malloc(len + 1);
|
||||||
|
if (*o.cstring == NULL){
|
||||||
|
rc = SSH_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rlen = buffer_get_data(buffer, *o.cstring, len);
|
||||||
|
if (rlen != len){
|
||||||
|
SAFE_FREE(*o.cstring);
|
||||||
|
rc = SSH_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(*o.cstring)[len] = '\0';
|
||||||
|
o.cstring = NULL;
|
||||||
|
rc = SSH_OK;
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
len = va_arg(ap, size_t);
|
||||||
|
|
||||||
|
o.data = va_arg(ap, void **);
|
||||||
|
count++;
|
||||||
|
|
||||||
|
*o.data = malloc(len);
|
||||||
|
if(*o.data == NULL){
|
||||||
|
rc = SSH_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rlen = buffer_get_data(buffer, *o.data, len);
|
||||||
|
if (rlen != len){
|
||||||
|
SAFE_FREE(*o.data);
|
||||||
|
rc = SSH_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
o.data = NULL;
|
||||||
|
rc = SSH_OK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SSH_LOG(SSH_LOG_WARN, "Invalid buffer format %c", *p);
|
||||||
|
rc = SSH_ERROR;
|
||||||
|
}
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc != -1 && argc != count) {
|
||||||
|
rc = SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc != SSH_ERROR){
|
||||||
|
/* 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){
|
||||||
|
rc = SSH_ERROR;
|
||||||
|
} else {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc != SSH_OK){
|
||||||
|
/* Reset the format string and erase everything that was allocated */
|
||||||
|
last = p;
|
||||||
|
for(p=format;p<last;++p){
|
||||||
|
switch(*p){
|
||||||
|
case 'b':
|
||||||
|
case 'w':
|
||||||
|
case 'd':
|
||||||
|
case 'q':
|
||||||
|
(void)va_arg(ap_copy, void *);
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
o.string=va_arg(ap_copy, ssh_string *);
|
||||||
|
SAFE_FREE(*o.string);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
o.cstring=va_arg(ap_copy, char **);
|
||||||
|
SAFE_FREE(*o.cstring);
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
(void)va_arg(ap_copy, size_t);
|
||||||
|
o.data = va_arg(ap_copy, void **);
|
||||||
|
SAFE_FREE(*o.data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
(void)va_arg(ap_copy, void *);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
va_end(ap_copy);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @internal
|
||||||
|
* @brief Get multiple values from a buffer on a single function call
|
||||||
|
* @param[in] buffer The buffer to get from
|
||||||
|
* @param[in] format A format string of arguments. This string contains single
|
||||||
|
* letters describing the order and type of arguments:
|
||||||
|
* 'b': uint8_t * (pulled in network byte order)
|
||||||
|
* 'w': uint16_t * (pulled in network byte order)
|
||||||
|
* 'd': uint32_t * (pulled in network byte order)
|
||||||
|
* 'q': uint64_t * (pulled in network byte order)
|
||||||
|
* 'S': ssh_string *
|
||||||
|
* 's': char ** (C string, pulled as SSH string)
|
||||||
|
* 'P': size_t, void ** (len of data, pointer to data)
|
||||||
|
* only pulls data.
|
||||||
|
* @returns SSH_OK on success
|
||||||
|
* SSH_ERROR on error
|
||||||
|
* @warning when using 'P' with a constant size (e.g. 8), do not
|
||||||
|
* forget to cast to (size_t).
|
||||||
|
*/
|
||||||
|
int _ssh_buffer_unpack(struct ssh_buffer_struct *buffer,
|
||||||
|
const char *format,
|
||||||
|
int argc,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
va_start(ap, argc);
|
||||||
|
rc = ssh_buffer_unpack_va(buffer, format, argc, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/* vim: set ts=4 sw=4 et cindent: */
|
/* vim: set ts=4 sw=4 et cindent: */
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the SSH Library
|
* This file is part of the SSH Library
|
||||||
*
|
*
|
||||||
* Copyright (c) 2009 by Andreas Schneider <mail@cynapses.org>
|
* Copyright (c) 2009-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||||
*
|
*
|
||||||
* The SSH Library is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
|||||||
997
src/channels.c
997
src/channels.c
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
|||||||
* This file is part of the SSH Library
|
* This file is part of the SSH Library
|
||||||
*
|
*
|
||||||
* Copyright (c) 2003-2008 by Aris Adamantiadis
|
* Copyright (c) 2003-2008 by Aris Adamantiadis
|
||||||
* Copyright (c) 2009 by Andreas Schneider <mail@cynapses.org>
|
* Copyright (c) 2009 by Andreas Schneider <asn@cryptomilk.org>
|
||||||
*
|
*
|
||||||
* The SSH Library is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
@@ -101,7 +101,8 @@ int channel_request_pty_size1(ssh_channel channel, const char *terminal, int col
|
|||||||
}
|
}
|
||||||
session = channel->session;
|
session = channel->session;
|
||||||
|
|
||||||
if(channel->request_state != SSH_CHANNEL_REQ_STATE_NONE){
|
if(channel->request_state != SSH_CHANNEL_REQ_STATE_NONE &&
|
||||||
|
channel->request_state != SSH_CHANNEL_REQ_STATE_ACCEPTED){
|
||||||
ssh_set_error(session,SSH_REQUEST_DENIED,"Wrong request state");
|
ssh_set_error(session,SSH_REQUEST_DENIED,"Wrong request state");
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
@@ -356,7 +357,7 @@ int channel_write1(ssh_channel channel, const void *data, int len) {
|
|||||||
effectivelen = len > 32000 ? 32000 : len;
|
effectivelen = len > 32000 ? 32000 : len;
|
||||||
|
|
||||||
if (buffer_add_u32(session->out_buffer, htonl(effectivelen)) < 0 ||
|
if (buffer_add_u32(session->out_buffer, htonl(effectivelen)) < 0 ||
|
||||||
buffer_add_data(session->out_buffer, ptr, effectivelen) < 0) {
|
ssh_buffer_add_data(session->out_buffer, ptr, effectivelen) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,6 +368,9 @@ int channel_write1(ssh_channel channel, const void *data, int len) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ssh_handle_packets(session, SSH_TIMEOUT_NONBLOCKING);
|
ssh_handle_packets(session, SSH_TIMEOUT_NONBLOCKING);
|
||||||
|
if (channel->counter != NULL) {
|
||||||
|
channel->counter->out_bytes += effectivelen;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ssh_blocking_flush(session,SSH_TIMEOUT_USER) == SSH_ERROR)
|
if (ssh_blocking_flush(session,SSH_TIMEOUT_USER) == SSH_ERROR)
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
139
src/client.c
139
src/client.c
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the SSH Library
|
* This file is part of the SSH Library
|
||||||
*
|
*
|
||||||
* Copyright (c) 2003-2008 by Aris Adamantiadis
|
* Copyright (c) 2003-2013 by Aris Adamantiadis
|
||||||
*
|
*
|
||||||
* The SSH Library is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
@@ -60,12 +60,15 @@
|
|||||||
static void socket_callback_connected(int code, int errno_code, void *user){
|
static void socket_callback_connected(int code, int errno_code, void *user){
|
||||||
ssh_session session=(ssh_session)user;
|
ssh_session session=(ssh_session)user;
|
||||||
|
|
||||||
if(session->session_state != SSH_SESSION_STATE_CONNECTING){
|
if (session->session_state != SSH_SESSION_STATE_CONNECTING &&
|
||||||
|
session->session_state != SSH_SESSION_STATE_SOCKET_CONNECTED)
|
||||||
|
{
|
||||||
ssh_set_error(session,SSH_FATAL, "Wrong state in socket_callback_connected : %d",
|
ssh_set_error(session,SSH_FATAL, "Wrong state in socket_callback_connected : %d",
|
||||||
session->session_state);
|
session->session_state);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SSH_LOG(SSH_LOG_RARE,"Socket connection callback: %d (%d)",code, errno_code);
|
SSH_LOG(SSH_LOG_RARE,"Socket connection callback: %d (%d)",code, errno_code);
|
||||||
if(code == SSH_SOCKET_CONNECTED_OK)
|
if(code == SSH_SOCKET_CONNECTED_OK)
|
||||||
session->session_state=SSH_SESSION_STATE_SOCKET_CONNECTED;
|
session->session_state=SSH_SESSION_STATE_SOCKET_CONNECTED;
|
||||||
@@ -105,14 +108,18 @@ static int callback_receive_banner(const void *data, size_t len, void *user) {
|
|||||||
ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_IN,buffer,i+1,i+1);
|
ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_IN,buffer,i+1,i+1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if(buffer[i]=='\r')
|
if(buffer[i]=='\r') {
|
||||||
buffer[i]='\0';
|
buffer[i]='\0';
|
||||||
if(buffer[i]=='\n'){
|
}
|
||||||
buffer[i]='\0';
|
if (buffer[i]=='\n') {
|
||||||
str=strdup(buffer);
|
buffer[i] = '\0';
|
||||||
/* number of bytes read */
|
str = strdup(buffer);
|
||||||
ret=i+1;
|
if (str == NULL) {
|
||||||
session->serverbanner=str;
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
/* number of bytes read */
|
||||||
|
ret = i + 1;
|
||||||
|
session->serverbanner = str;
|
||||||
session->session_state=SSH_SESSION_STATE_BANNER_RECEIVED;
|
session->session_state=SSH_SESSION_STATE_BANNER_RECEIVED;
|
||||||
SSH_LOG(SSH_LOG_PACKET,"Received banner: %s",str);
|
SSH_LOG(SSH_LOG_PACKET,"Received banner: %s",str);
|
||||||
session->ssh_connection_callback(session);
|
session->ssh_connection_callback(session);
|
||||||
@@ -148,19 +155,27 @@ int ssh_send_banner(ssh_session session, int server) {
|
|||||||
banner = session->version == 1 ? CLIENTBANNER1 : CLIENTBANNER2;
|
banner = session->version == 1 ? CLIENTBANNER1 : CLIENTBANNER2;
|
||||||
|
|
||||||
if (server) {
|
if (server) {
|
||||||
session->serverbanner = strdup(banner);
|
if(session->opts.custombanner == NULL){
|
||||||
|
session->serverbanner = strdup(banner);
|
||||||
|
} else {
|
||||||
|
session->serverbanner = malloc(strlen(session->opts.custombanner) + 9);
|
||||||
|
if(!session->serverbanner)
|
||||||
|
goto end;
|
||||||
|
strcpy(session->serverbanner, "SSH-2.0-");
|
||||||
|
strcat(session->serverbanner, session->opts.custombanner);
|
||||||
|
}
|
||||||
if (session->serverbanner == NULL) {
|
if (session->serverbanner == NULL) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
snprintf(buffer, 128, "%s\n", session->serverbanner);
|
||||||
} else {
|
} else {
|
||||||
session->clientbanner = strdup(banner);
|
session->clientbanner = strdup(banner);
|
||||||
if (session->clientbanner == NULL) {
|
if (session->clientbanner == NULL) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
snprintf(buffer, 128, "%s\n", session->clientbanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(buffer, 128, "%s\n", banner);
|
|
||||||
|
|
||||||
if (ssh_socket_write(session->socket, buffer, strlen(buffer)) == SSH_ERROR) {
|
if (ssh_socket_write(session->socket, buffer, strlen(buffer)) == SSH_ERROR) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
@@ -196,6 +211,11 @@ static int dh_handshake(ssh_session session) {
|
|||||||
case SSH_KEX_ECDH_SHA2_NISTP256:
|
case SSH_KEX_ECDH_SHA2_NISTP256:
|
||||||
rc = ssh_client_ecdh_init(session);
|
rc = ssh_client_ecdh_init(session);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CURVE25519
|
||||||
|
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
|
||||||
|
rc = ssh_client_curve25519_init(session);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
rc = SSH_ERROR;
|
rc = SSH_ERROR;
|
||||||
@@ -249,24 +269,19 @@ static int ssh_service_request_termination(void *s){
|
|||||||
* @bug actually only works with ssh-userauth
|
* @bug actually only works with ssh-userauth
|
||||||
*/
|
*/
|
||||||
int ssh_service_request(ssh_session session, const char *service) {
|
int ssh_service_request(ssh_session session, const char *service) {
|
||||||
ssh_string service_s = NULL;
|
|
||||||
int rc=SSH_ERROR;
|
int rc=SSH_ERROR;
|
||||||
|
|
||||||
if(session->auth_service_state != SSH_AUTH_SERVICE_NONE)
|
if(session->auth_service_state != SSH_AUTH_SERVICE_NONE)
|
||||||
goto pending;
|
goto pending;
|
||||||
if (buffer_add_u8(session->out_buffer, SSH2_MSG_SERVICE_REQUEST) < 0) {
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
service_s = ssh_string_from_char(service);
|
|
||||||
if (service_s == NULL) {
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer_add_ssh_string(session->out_buffer,service_s) < 0) {
|
rc = ssh_buffer_pack(session->out_buffer,
|
||||||
ssh_string_free(service_s);
|
"bs",
|
||||||
|
SSH2_MSG_SERVICE_REQUEST,
|
||||||
|
service);
|
||||||
|
if (rc != SSH_OK){
|
||||||
|
ssh_set_error_oom(session);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
ssh_string_free(service_s);
|
|
||||||
session->auth_service_state=SSH_AUTH_SERVICE_SENT;
|
session->auth_service_state=SSH_AUTH_SERVICE_SENT;
|
||||||
if (packet_send(session) == SSH_ERROR) {
|
if (packet_send(session) == SSH_ERROR) {
|
||||||
ssh_set_error(session, SSH_FATAL,
|
ssh_set_error(session, SSH_FATAL,
|
||||||
@@ -486,7 +501,12 @@ int ssh_connect(ssh_session session) {
|
|||||||
ssh_set_error(session, SSH_FATAL, "Couldn't apply options");
|
ssh_set_error(session, SSH_FATAL, "Couldn't apply options");
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
SSH_LOG(SSH_LOG_RARE,"libssh %s, using threading %s", ssh_copyright(), ssh_threads_get_type());
|
|
||||||
|
SSH_LOG(SSH_LOG_PROTOCOL,
|
||||||
|
"libssh %s, using threading %s",
|
||||||
|
ssh_copyright(),
|
||||||
|
ssh_threads_get_type());
|
||||||
|
|
||||||
session->ssh_connection_callback = ssh_client_connection_callback;
|
session->ssh_connection_callback = ssh_client_connection_callback;
|
||||||
session->session_state=SSH_SESSION_STATE_CONNECTING;
|
session->session_state=SSH_SESSION_STATE_CONNECTING;
|
||||||
ssh_socket_set_callbacks(session->socket,&session->socket_callbacks);
|
ssh_socket_set_callbacks(session->socket,&session->socket_callbacks);
|
||||||
@@ -495,6 +515,7 @@ int ssh_connect(ssh_session session) {
|
|||||||
session->socket_callbacks.exception=ssh_socket_exception_callback;
|
session->socket_callbacks.exception=ssh_socket_exception_callback;
|
||||||
session->socket_callbacks.userdata=session;
|
session->socket_callbacks.userdata=session;
|
||||||
if (session->opts.fd != SSH_INVALID_SOCKET) {
|
if (session->opts.fd != SSH_INVALID_SOCKET) {
|
||||||
|
session->session_state=SSH_SESSION_STATE_SOCKET_CONNECTED;
|
||||||
ssh_socket_set_fd(session->socket, session->opts.fd);
|
ssh_socket_set_fd(session->socket, session->opts.fd);
|
||||||
ret=SSH_OK;
|
ret=SSH_OK;
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
@@ -505,7 +526,7 @@ int ssh_connect(ssh_session session) {
|
|||||||
} else {
|
} else {
|
||||||
ret=ssh_socket_connect(session->socket,
|
ret=ssh_socket_connect(session->socket,
|
||||||
session->opts.host,
|
session->opts.host,
|
||||||
session->opts.port,
|
session->opts.port > 0 ? session->opts.port : 22,
|
||||||
session->opts.bindaddr);
|
session->opts.bindaddr);
|
||||||
}
|
}
|
||||||
if (ret == SSH_ERROR) {
|
if (ret == SSH_ERROR) {
|
||||||
@@ -524,9 +545,10 @@ pending:
|
|||||||
if (timeout == 0) {
|
if (timeout == 0) {
|
||||||
timeout = 10 * 1000;
|
timeout = 10 * 1000;
|
||||||
}
|
}
|
||||||
SSH_LOG(SSH_LOG_PACKET,"ssh_connect: Actual timeout : %d", timeout);
|
SSH_LOG(SSH_LOG_PACKET,"Actual timeout : %d", timeout);
|
||||||
ret = ssh_handle_packets_termination(session, timeout, ssh_connect_termination, session);
|
ret = ssh_handle_packets_termination(session, timeout, ssh_connect_termination, session);
|
||||||
if (ret == SSH_ERROR || !ssh_connect_termination(session)) {
|
if (session->session_state != SSH_SESSION_STATE_ERROR &&
|
||||||
|
(ret == SSH_ERROR || !ssh_connect_termination(session))) {
|
||||||
ssh_set_error(session, SSH_FATAL,
|
ssh_set_error(session, SSH_FATAL,
|
||||||
"Timeout connecting to %s", session->opts.host);
|
"Timeout connecting to %s", session->opts.host);
|
||||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||||
@@ -541,7 +563,7 @@ pending:
|
|||||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SSH_LOG(SSH_LOG_PACKET,"ssh_connect: Actual state : %d",session->session_state);
|
SSH_LOG(SSH_LOG_PACKET,"current state : %d",session->session_state);
|
||||||
if(!ssh_is_blocking(session) && !ssh_connect_termination(session)){
|
if(!ssh_is_blocking(session) && !ssh_connect_termination(session)){
|
||||||
return SSH_AGAIN;
|
return SSH_AGAIN;
|
||||||
}
|
}
|
||||||
@@ -579,6 +601,14 @@ char *ssh_get_issue_banner(ssh_session session) {
|
|||||||
* @param[in] session The SSH session to use.
|
* @param[in] session The SSH session to use.
|
||||||
*
|
*
|
||||||
* @return The version number if available, 0 otherwise.
|
* @return The version number if available, 0 otherwise.
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* int openssh = ssh_get_openssh_version();
|
||||||
|
*
|
||||||
|
* if (openssh == SSH_INT_VERSION(6, 1, 0)) {
|
||||||
|
* printf("Version match!\m");
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
*/
|
*/
|
||||||
int ssh_get_openssh_version(ssh_session session) {
|
int ssh_get_openssh_version(ssh_session session) {
|
||||||
if (session == NULL) {
|
if (session == NULL) {
|
||||||
@@ -595,32 +625,23 @@ int ssh_get_openssh_version(ssh_session session) {
|
|||||||
* @param[in] session The SSH session to use.
|
* @param[in] session The SSH session to use.
|
||||||
*/
|
*/
|
||||||
void ssh_disconnect(ssh_session session) {
|
void ssh_disconnect(ssh_session session) {
|
||||||
ssh_string str = NULL;
|
|
||||||
struct ssh_iterator *it;
|
struct ssh_iterator *it;
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (session == NULL) {
|
if (session == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session->socket != NULL && ssh_socket_is_open(session->socket)) {
|
if (session->socket != NULL && ssh_socket_is_open(session->socket)) {
|
||||||
if (buffer_add_u8(session->out_buffer, SSH2_MSG_DISCONNECT) < 0) {
|
rc = ssh_buffer_pack(session->out_buffer,
|
||||||
|
"bds",
|
||||||
|
SSH2_MSG_DISCONNECT,
|
||||||
|
SSH2_DISCONNECT_BY_APPLICATION,
|
||||||
|
"Bye Bye");
|
||||||
|
if (rc != SSH_OK){
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (buffer_add_u32(session->out_buffer,
|
|
||||||
htonl(SSH2_DISCONNECT_BY_APPLICATION)) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
str = ssh_string_from_char("Bye Bye");
|
|
||||||
if (str == NULL) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer_add_ssh_string(session->out_buffer,str) < 0) {
|
|
||||||
ssh_string_free(str);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
ssh_string_free(str);
|
|
||||||
|
|
||||||
packet_send(session);
|
packet_send(session);
|
||||||
ssh_socket_close(session->socket);
|
ssh_socket_close(session->socket);
|
||||||
@@ -634,21 +655,25 @@ error:
|
|||||||
session->session_state=SSH_SESSION_STATE_DISCONNECTED;
|
session->session_state=SSH_SESSION_STATE_DISCONNECTED;
|
||||||
|
|
||||||
while ((it=ssh_list_get_iterator(session->channels)) != NULL) {
|
while ((it=ssh_list_get_iterator(session->channels)) != NULL) {
|
||||||
ssh_channel_free(ssh_iterator_value(ssh_channel,it));
|
ssh_channel_do_free(ssh_iterator_value(ssh_channel,it));
|
||||||
ssh_list_remove(session->channels, it);
|
ssh_list_remove(session->channels, it);
|
||||||
}
|
}
|
||||||
if(session->current_crypto){
|
if(session->current_crypto){
|
||||||
crypto_free(session->current_crypto);
|
crypto_free(session->current_crypto);
|
||||||
session->current_crypto=NULL;
|
session->current_crypto=NULL;
|
||||||
}
|
}
|
||||||
if(session->in_buffer)
|
if (session->in_buffer) {
|
||||||
buffer_reinit(session->in_buffer);
|
ssh_buffer_reinit(session->in_buffer);
|
||||||
if(session->out_buffer)
|
}
|
||||||
buffer_reinit(session->out_buffer);
|
if (session->out_buffer) {
|
||||||
if(session->in_hashbuf)
|
ssh_buffer_reinit(session->out_buffer);
|
||||||
buffer_reinit(session->in_hashbuf);
|
}
|
||||||
if(session->out_hashbuf)
|
if (session->in_hashbuf) {
|
||||||
buffer_reinit(session->out_hashbuf);
|
ssh_buffer_reinit(session->in_hashbuf);
|
||||||
|
}
|
||||||
|
if (session->out_hashbuf) {
|
||||||
|
ssh_buffer_reinit(session->out_hashbuf);
|
||||||
|
}
|
||||||
session->auth_methods = 0;
|
session->auth_methods = 0;
|
||||||
SAFE_FREE(session->serverbanner);
|
SAFE_FREE(session->serverbanner);
|
||||||
SAFE_FREE(session->clientbanner);
|
SAFE_FREE(session->clientbanner);
|
||||||
@@ -670,8 +695,8 @@ error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *ssh_copyright(void) {
|
const char *ssh_copyright(void) {
|
||||||
return SSH_STRINGIFY(LIBSSH_VERSION) " (c) 2003-2010 Aris Adamantiadis "
|
return SSH_STRINGIFY(LIBSSH_VERSION) " (c) 2003-2014 Aris Adamantiadis, Andreas Schneider, "
|
||||||
"(aris@0xbadc0de.be) Distributed under the LGPL, please refer to COPYING "
|
"and libssh contributors. Distributed under the LGPL, please refer to COPYING "
|
||||||
"file for information about your rights";
|
"file for information about your rights";
|
||||||
}
|
}
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|||||||
61
src/config.c
61
src/config.c
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the SSH Library
|
* This file is part of the SSH Library
|
||||||
*
|
*
|
||||||
* Copyright (c) 2009 by Andreas Schneider <mail@cynapses.org>
|
* Copyright (c) 2009-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||||
*
|
*
|
||||||
* The SSH Library is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
@@ -46,7 +46,10 @@ enum ssh_config_opcode_e {
|
|||||||
SOC_PROTOCOL,
|
SOC_PROTOCOL,
|
||||||
SOC_STRICTHOSTKEYCHECK,
|
SOC_STRICTHOSTKEYCHECK,
|
||||||
SOC_KNOWNHOSTS,
|
SOC_KNOWNHOSTS,
|
||||||
SOC_PROXYCOMMAND
|
SOC_PROXYCOMMAND,
|
||||||
|
SOC_GSSAPISERVERIDENTITY,
|
||||||
|
SOC_GSSAPICLIENTIDENTITY,
|
||||||
|
SOC_GSSAPIDELEGATECREDENTIALS,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ssh_config_keyword_table_s {
|
struct ssh_config_keyword_table_s {
|
||||||
@@ -67,6 +70,9 @@ static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
|
|||||||
{ "stricthostkeychecking", SOC_STRICTHOSTKEYCHECK },
|
{ "stricthostkeychecking", SOC_STRICTHOSTKEYCHECK },
|
||||||
{ "userknownhostsfile", SOC_KNOWNHOSTS },
|
{ "userknownhostsfile", SOC_KNOWNHOSTS },
|
||||||
{ "proxycommand", SOC_PROXYCOMMAND },
|
{ "proxycommand", SOC_PROXYCOMMAND },
|
||||||
|
{ "gssapiserveridentity", SOC_GSSAPISERVERIDENTITY },
|
||||||
|
{ "gssapiserveridentity", SOC_GSSAPICLIENTIDENTITY },
|
||||||
|
{ "gssapidelegatecredentials", SOC_GSSAPIDELEGATECREDENTIALS },
|
||||||
{ NULL, SOC_UNSUPPORTED }
|
{ NULL, SOC_UNSUPPORTED }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -122,7 +128,7 @@ static char *ssh_config_get_token(char **str) {
|
|||||||
c = ssh_config_get_cmd(str);
|
c = ssh_config_get_cmd(str);
|
||||||
|
|
||||||
for (r = c; *c; c++) {
|
for (r = c; *c; c++) {
|
||||||
if (isblank(*c)) {
|
if (isblank(*c) || *c == '=') {
|
||||||
*c = '\0';
|
*c = '\0';
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -213,16 +219,25 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
|||||||
|
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case SOC_HOST:
|
case SOC_HOST:
|
||||||
*parsing = 0;
|
*parsing = 0;
|
||||||
lowerhost = (session->opts.host) ? ssh_lowercase(session->opts.host) : NULL;
|
lowerhost = (session->opts.host) ? ssh_lowercase(session->opts.host) : NULL;
|
||||||
for (p = ssh_config_get_str_tok(&s, NULL); p && *p;
|
for (p = ssh_config_get_str_tok(&s, NULL);
|
||||||
p = ssh_config_get_str_tok(&s, NULL)) {
|
p != NULL && p[0] != '\0';
|
||||||
if (match_hostname(lowerhost, p, strlen(p))) {
|
p = ssh_config_get_str_tok(&s, NULL)) {
|
||||||
*parsing = 1;
|
char *z = ssh_path_expand_escape(session, p);
|
||||||
|
int ok;
|
||||||
|
|
||||||
|
if (z == NULL) {
|
||||||
|
z = strdup(p);
|
||||||
|
}
|
||||||
|
ok = match_hostname(lowerhost, z, strlen(z));
|
||||||
|
if (ok) {
|
||||||
|
*parsing = 1;
|
||||||
|
}
|
||||||
|
free(z);
|
||||||
}
|
}
|
||||||
}
|
SAFE_FREE(lowerhost);
|
||||||
SAFE_FREE(lowerhost);
|
break;
|
||||||
break;
|
|
||||||
case SOC_HOSTNAME:
|
case SOC_HOSTNAME:
|
||||||
p = ssh_config_get_str_tok(&s, NULL);
|
p = ssh_config_get_str_tok(&s, NULL);
|
||||||
if (p && *parsing) {
|
if (p && *parsing) {
|
||||||
@@ -230,7 +245,7 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SOC_PORT:
|
case SOC_PORT:
|
||||||
if (session->opts.port == 22) {
|
if (session->opts.port == 0) {
|
||||||
p = ssh_config_get_str_tok(&s, NULL);
|
p = ssh_config_get_str_tok(&s, NULL);
|
||||||
if (p && *parsing) {
|
if (p && *parsing) {
|
||||||
ssh_options_set(session, SSH_OPTIONS_PORT_STR, p);
|
ssh_options_set(session, SSH_OPTIONS_PORT_STR, p);
|
||||||
@@ -323,6 +338,24 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
|||||||
ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, p);
|
ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, p);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SOC_GSSAPISERVERIDENTITY:
|
||||||
|
p = ssh_config_get_str_tok(&s, NULL);
|
||||||
|
if (p && *parsing) {
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_GSSAPI_SERVER_IDENTITY, p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SOC_GSSAPICLIENTIDENTITY:
|
||||||
|
p = ssh_config_get_str_tok(&s, NULL);
|
||||||
|
if (p && *parsing) {
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_GSSAPI_CLIENT_IDENTITY, p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SOC_GSSAPIDELEGATECREDENTIALS:
|
||||||
|
i = ssh_config_get_yesno(&s, -1);
|
||||||
|
if (i >=0 && *parsing) {
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_GSSAPI_DELEGATE_CREDENTIALS, &i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case SOC_UNSUPPORTED:
|
case SOC_UNSUPPORTED:
|
||||||
SSH_LOG(SSH_LOG_RARE, "Unsupported option: %s, line: %d\n",
|
SSH_LOG(SSH_LOG_RARE, "Unsupported option: %s, line: %d\n",
|
||||||
keyword, count);
|
keyword, count);
|
||||||
@@ -350,7 +383,7 @@ int ssh_config_parse_file(ssh_session session, const char *filename) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SSH_LOG(SSH_LOG_RARE, "Reading configuration data from %s", filename);
|
SSH_LOG(SSH_LOG_PACKET, "Reading configuration data from %s", filename);
|
||||||
|
|
||||||
parsing = 1;
|
parsing = 1;
|
||||||
while (fgets(line, sizeof(line), f)) {
|
while (fgets(line, sizeof(line), f)) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the SSH Library
|
* This file is part of the SSH Library
|
||||||
*
|
*
|
||||||
* Copyright (c) 2003-2009 by Aris Adamantiadis
|
* Copyright (c) 2003-2013 by Aris Adamantiadis
|
||||||
*
|
*
|
||||||
* The SSH Library is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
@@ -64,6 +64,10 @@
|
|||||||
#include <wspiapi.h>
|
#include <wspiapi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef EINPROGRESS
|
||||||
|
#define EINPROGRESS WSAEINPROGRESS
|
||||||
|
#endif
|
||||||
|
|
||||||
#else /* _WIN32 */
|
#else /* _WIN32 */
|
||||||
|
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
@@ -285,6 +289,7 @@ socket_t ssh_connect_host(ssh_session session, const char *host,
|
|||||||
socket_t ret = ssh_connect_ai_timeout(session, host, port, itr,
|
socket_t ret = ssh_connect_ai_timeout(session, host, port, itr,
|
||||||
timeout, usec, s);
|
timeout, usec, s);
|
||||||
|
|
||||||
|
freeaddrinfo(ai);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,7 +387,16 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(s, itr->ai_addr, itr->ai_addrlen);
|
errno = 0;
|
||||||
|
rc = connect(s, itr->ai_addr, itr->ai_addrlen);
|
||||||
|
if (rc == -1 && (errno != 0) && (errno != EINPROGRESS)) {
|
||||||
|
ssh_set_error(session, SSH_FATAL,
|
||||||
|
"Failed to connect: %s", strerror(errno));
|
||||||
|
ssh_connect_socket_close(s);
|
||||||
|
s = -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,7 +435,7 @@ static int ssh_select_cb (socket_t fd, int revents, void *userdata){
|
|||||||
* @param[in] readfds A fd_set of file descriptors to be select'ed for
|
* @param[in] readfds A fd_set of file descriptors to be select'ed for
|
||||||
* reading.
|
* reading.
|
||||||
*
|
*
|
||||||
* @param[in] timeout A timeout for the select.
|
* @param[in] timeout The timeout in milliseconds.
|
||||||
*
|
*
|
||||||
* @return SSH_OK on success,
|
* @return SSH_OK on success,
|
||||||
* SSH_ERROR on error,
|
* SSH_ERROR on error,
|
||||||
@@ -436,6 +450,7 @@ static int ssh_select_cb (socket_t fd, int revents, void *userdata){
|
|||||||
*/
|
*/
|
||||||
int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
|
int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
|
||||||
fd_set *readfds, struct timeval *timeout) {
|
fd_set *readfds, struct timeval *timeout) {
|
||||||
|
fd_set origfds;
|
||||||
socket_t fd;
|
socket_t fd;
|
||||||
int i,j;
|
int i,j;
|
||||||
int rc;
|
int rc;
|
||||||
@@ -449,9 +464,11 @@ int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
|
|||||||
ssh_event_add_session(event, channels[i]->session);
|
ssh_event_add_session(event, channels[i]->session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FD_ZERO(&origfds);
|
||||||
for (fd = 0; fd < maxfd ; fd++) {
|
for (fd = 0; fd < maxfd ; fd++) {
|
||||||
if (FD_ISSET(fd, readfds)) {
|
if (FD_ISSET(fd, readfds)) {
|
||||||
ssh_event_add_fd(event, fd, POLLIN, ssh_select_cb, readfds);
|
ssh_event_add_fd(event, fd, POLLIN, ssh_select_cb, readfds);
|
||||||
|
FD_SET(fd, &origfds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
outchannels[0] = NULL;
|
outchannels[0] = NULL;
|
||||||
@@ -485,13 +502,17 @@ int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
|
|||||||
/* since there's nothing, let's fire the polling */
|
/* since there's nothing, let's fire the polling */
|
||||||
rc = ssh_event_dopoll(event,tm);
|
rc = ssh_event_dopoll(event,tm);
|
||||||
if (rc == SSH_ERROR){
|
if (rc == SSH_ERROR){
|
||||||
ssh_event_free(event);
|
goto out;
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
}
|
||||||
tm = ssh_timeout_update(&ts, base_tm);
|
tm = ssh_timeout_update(&ts, base_tm);
|
||||||
firstround=0;
|
firstround=0;
|
||||||
} while (1);
|
} while (1);
|
||||||
out:
|
out:
|
||||||
|
for (fd = 0; fd < maxfd; fd++) {
|
||||||
|
if (FD_ISSET(fd, &origfds)) {
|
||||||
|
ssh_event_remove_fd(event, fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
ssh_event_free(event);
|
ssh_event_free(event);
|
||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
286
src/curve25519.c
Normal file
286
src/curve25519.c
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
/*
|
||||||
|
* curve25519.c - Curve25519 ECDH functions for key exchange
|
||||||
|
* curve25519-sha256@libssh.org
|
||||||
|
*
|
||||||
|
* This file is part of the SSH Library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 by Aris Adamantiadis <aris@badcode.be>
|
||||||
|
*
|
||||||
|
* 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, version 2.1 of the License.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "libssh/curve25519.h"
|
||||||
|
#ifdef HAVE_CURVE25519
|
||||||
|
|
||||||
|
#ifdef WITH_NACL
|
||||||
|
#include "nacl/crypto_scalarmult_curve25519.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "libssh/ssh2.h"
|
||||||
|
#include "libssh/buffer.h"
|
||||||
|
#include "libssh/priv.h"
|
||||||
|
#include "libssh/session.h"
|
||||||
|
#include "libssh/crypto.h"
|
||||||
|
#include "libssh/dh.h"
|
||||||
|
#include "libssh/pki.h"
|
||||||
|
#include "libssh/bignum.h"
|
||||||
|
|
||||||
|
/** @internal
|
||||||
|
* @brief Starts curve25519-sha256@libssh.org key exchange
|
||||||
|
*/
|
||||||
|
int ssh_client_curve25519_init(ssh_session session){
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = ssh_get_random(session->next_crypto->curve25519_privkey, CURVE25519_PRIVKEY_SIZE, 1);
|
||||||
|
if (rc == 0){
|
||||||
|
ssh_set_error(session, SSH_FATAL, "PRNG error");
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
crypto_scalarmult_base(session->next_crypto->curve25519_client_pubkey,
|
||||||
|
session->next_crypto->curve25519_privkey);
|
||||||
|
|
||||||
|
rc = ssh_buffer_pack(session->out_buffer,
|
||||||
|
"bdP",
|
||||||
|
SSH2_MSG_KEX_ECDH_INIT,
|
||||||
|
CURVE25519_PUBKEY_SIZE,
|
||||||
|
(size_t)CURVE25519_PUBKEY_SIZE, session->next_crypto->curve25519_client_pubkey);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = packet_send(session);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ssh_curve25519_build_k(ssh_session session) {
|
||||||
|
ssh_curve25519_pubkey k;
|
||||||
|
session->next_crypto->k = bignum_new();
|
||||||
|
|
||||||
|
if (session->next_crypto->k == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session->server)
|
||||||
|
crypto_scalarmult(k, session->next_crypto->curve25519_privkey,
|
||||||
|
session->next_crypto->curve25519_client_pubkey);
|
||||||
|
else
|
||||||
|
crypto_scalarmult(k, session->next_crypto->curve25519_privkey,
|
||||||
|
session->next_crypto->curve25519_server_pubkey);
|
||||||
|
|
||||||
|
bignum_bin2bn(k, CURVE25519_PUBKEY_SIZE, session->next_crypto->k);
|
||||||
|
|
||||||
|
#ifdef DEBUG_CRYPTO
|
||||||
|
ssh_print_hexa("Session server cookie",
|
||||||
|
session->next_crypto->server_kex.cookie, 16);
|
||||||
|
ssh_print_hexa("Session client cookie",
|
||||||
|
session->next_crypto->client_kex.cookie, 16);
|
||||||
|
ssh_print_bignum("Shared secret key", session->next_crypto->k);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @internal
|
||||||
|
* @brief parses a SSH_MSG_KEX_ECDH_REPLY packet and sends back
|
||||||
|
* a SSH_MSG_NEWKEYS
|
||||||
|
*/
|
||||||
|
int ssh_client_curve25519_reply(ssh_session session, ssh_buffer packet){
|
||||||
|
ssh_string q_s_string = NULL;
|
||||||
|
ssh_string pubkey = NULL;
|
||||||
|
ssh_string signature = NULL;
|
||||||
|
int rc;
|
||||||
|
pubkey = buffer_get_ssh_string(packet);
|
||||||
|
if (pubkey == NULL){
|
||||||
|
ssh_set_error(session,SSH_FATAL, "No public key in packet");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
/* this is the server host key */
|
||||||
|
session->next_crypto->server_pubkey = pubkey;
|
||||||
|
pubkey = NULL;
|
||||||
|
|
||||||
|
q_s_string = buffer_get_ssh_string(packet);
|
||||||
|
if (q_s_string == NULL) {
|
||||||
|
ssh_set_error(session,SSH_FATAL, "No Q_S ECC point in packet");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (ssh_string_len(q_s_string) != CURVE25519_PUBKEY_SIZE){
|
||||||
|
ssh_set_error(session, SSH_FATAL, "Incorrect size for server Curve25519 public key: %d",
|
||||||
|
(int)ssh_string_len(q_s_string));
|
||||||
|
ssh_string_free(q_s_string);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
memcpy(session->next_crypto->curve25519_server_pubkey, ssh_string_data(q_s_string), CURVE25519_PUBKEY_SIZE);
|
||||||
|
ssh_string_free(q_s_string);
|
||||||
|
|
||||||
|
signature = buffer_get_ssh_string(packet);
|
||||||
|
if (signature == NULL) {
|
||||||
|
ssh_set_error(session, SSH_FATAL, "No signature in packet");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
session->next_crypto->dh_server_signature = signature;
|
||||||
|
signature=NULL; /* ownership changed */
|
||||||
|
/* TODO: verify signature now instead of waiting for NEWKEYS */
|
||||||
|
if (ssh_curve25519_build_k(session) < 0) {
|
||||||
|
ssh_set_error(session, SSH_FATAL, "Cannot build k number");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send the MSG_NEWKEYS */
|
||||||
|
if (buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc=packet_send(session);
|
||||||
|
SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");
|
||||||
|
return rc;
|
||||||
|
error:
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_SERVER
|
||||||
|
|
||||||
|
/** @brief Parse a SSH_MSG_KEXDH_INIT packet (server) and send a
|
||||||
|
* SSH_MSG_KEXDH_REPLY
|
||||||
|
*/
|
||||||
|
int ssh_server_curve25519_init(ssh_session session, ssh_buffer packet){
|
||||||
|
/* ECDH keys */
|
||||||
|
ssh_string q_c_string;
|
||||||
|
ssh_string q_s_string;
|
||||||
|
|
||||||
|
/* SSH host keys (rsa,dsa,ecdsa) */
|
||||||
|
ssh_key privkey;
|
||||||
|
ssh_string sig_blob = NULL;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Extract the client pubkey from the init packet */
|
||||||
|
q_c_string = buffer_get_ssh_string(packet);
|
||||||
|
if (q_c_string == NULL) {
|
||||||
|
ssh_set_error(session,SSH_FATAL, "No Q_C ECC point in packet");
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
if (ssh_string_len(q_c_string) != CURVE25519_PUBKEY_SIZE){
|
||||||
|
ssh_set_error(session, SSH_FATAL, "Incorrect size for server Curve25519 public key: %d",
|
||||||
|
(int)ssh_string_len(q_c_string));
|
||||||
|
ssh_string_free(q_c_string);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(session->next_crypto->curve25519_client_pubkey,
|
||||||
|
ssh_string_data(q_c_string), CURVE25519_PUBKEY_SIZE);
|
||||||
|
ssh_string_free(q_c_string);
|
||||||
|
/* Build server's keypair */
|
||||||
|
|
||||||
|
rc = ssh_get_random(session->next_crypto->curve25519_privkey, CURVE25519_PRIVKEY_SIZE, 1);
|
||||||
|
if (rc == 0){
|
||||||
|
ssh_set_error(session, SSH_FATAL, "PRNG error");
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
crypto_scalarmult_base(session->next_crypto->curve25519_server_pubkey,
|
||||||
|
session->next_crypto->curve25519_privkey);
|
||||||
|
|
||||||
|
rc = buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_REPLY);
|
||||||
|
if (rc < 0) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* build k and session_id */
|
||||||
|
rc = ssh_curve25519_build_k(session);
|
||||||
|
if (rc < 0) {
|
||||||
|
ssh_set_error(session, SSH_FATAL, "Cannot build k number");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* privkey is not allocated */
|
||||||
|
rc = ssh_get_key_params(session, &privkey);
|
||||||
|
if (rc == SSH_ERROR) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = make_sessionid(session);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
ssh_set_error(session, SSH_FATAL, "Could not create a session id");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add host's public key */
|
||||||
|
rc = buffer_add_ssh_string(session->out_buffer,
|
||||||
|
session->next_crypto->server_pubkey);
|
||||||
|
if (rc < 0) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add ecdh public key */
|
||||||
|
q_s_string = ssh_string_new(CURVE25519_PUBKEY_SIZE);
|
||||||
|
if (q_s_string == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_string_fill(q_s_string,
|
||||||
|
session->next_crypto->curve25519_server_pubkey,
|
||||||
|
CURVE25519_PUBKEY_SIZE);
|
||||||
|
|
||||||
|
rc = buffer_add_ssh_string(session->out_buffer, q_s_string);
|
||||||
|
ssh_string_free(q_s_string);
|
||||||
|
if (rc < 0) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
/* add signature blob */
|
||||||
|
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
|
||||||
|
if (sig_blob == NULL) {
|
||||||
|
ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = buffer_add_ssh_string(session->out_buffer, sig_blob);
|
||||||
|
ssh_string_free(sig_blob);
|
||||||
|
if (rc < 0) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEX_ECDH_REPLY sent");
|
||||||
|
rc = packet_send(session);
|
||||||
|
if (rc == SSH_ERROR) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send the MSG_NEWKEYS */
|
||||||
|
rc = buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
||||||
|
rc = packet_send(session);
|
||||||
|
SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
error:
|
||||||
|
ssh_buffer_reinit(session->out_buffer);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WITH_SERVER */
|
||||||
|
|
||||||
|
#endif /* HAVE_CURVE25519 */
|
||||||
780
src/dh.c
780
src/dh.c
@@ -3,8 +3,8 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the SSH Library
|
* This file is part of the SSH Library
|
||||||
*
|
*
|
||||||
* Copyright (c) 2003-2008 by Aris Adamantiadis
|
* Copyright (c) 2003-2013 by Aris Adamantiadis
|
||||||
* Copyright (c) 2009 by Andreas Schneider <mail@cynapses.org>
|
* Copyright (c) 2009-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||||
* Copyright (c) 2012 by Dmitriy Kuznetsov <dk@yandex.ru>
|
* Copyright (c) 2012 by Dmitriy Kuznetsov <dk@yandex.ru>
|
||||||
*
|
*
|
||||||
* The SSH Library is free software; you can redistribute it and/or modify
|
* The SSH Library is free software; you can redistribute it and/or modify
|
||||||
@@ -60,6 +60,7 @@
|
|||||||
#include "libssh/dh.h"
|
#include "libssh/dh.h"
|
||||||
#include "libssh/ssh2.h"
|
#include "libssh/ssh2.h"
|
||||||
#include "libssh/pki.h"
|
#include "libssh/pki.h"
|
||||||
|
#include "libssh/bignum.h"
|
||||||
|
|
||||||
/* todo: remove it */
|
/* todo: remove it */
|
||||||
#include "libssh/string.h"
|
#include "libssh/string.h"
|
||||||
@@ -170,7 +171,7 @@ int ssh_crypto_init(void) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
bignum_bin2bn(p_group14_value, P_GROUP14_LEN, &p_group14);
|
bignum_bin2bn(p_group14_value, P_GROUP14_LEN, &p_group14);
|
||||||
if (p_group1 == NULL) {
|
if (p_group14 == NULL) {
|
||||||
bignum_free(g);
|
bignum_free(g);
|
||||||
bignum_free(p_group1);
|
bignum_free(p_group1);
|
||||||
g = NULL;
|
g = NULL;
|
||||||
@@ -225,87 +226,22 @@ void ssh_crypto_finalize(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* prints the bignum on stderr */
|
|
||||||
void ssh_print_bignum(const char *which, bignum num) {
|
|
||||||
#ifdef HAVE_LIBGCRYPT
|
|
||||||
unsigned char *hex = NULL;
|
|
||||||
bignum_bn2hex(num, &hex);
|
|
||||||
#elif defined HAVE_LIBCRYPTO
|
|
||||||
char *hex = NULL;
|
|
||||||
hex = bignum_bn2hex(num);
|
|
||||||
#endif
|
|
||||||
fprintf(stderr, "%s value: ", which);
|
|
||||||
fprintf(stderr, "%s\n", (hex == NULL) ? "(null)" : (char *) hex);
|
|
||||||
SAFE_FREE(hex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Convert a buffer into a colon separated hex string.
|
|
||||||
* The caller has to free the memory.
|
|
||||||
*
|
|
||||||
* @param what What should be converted to a hex string.
|
|
||||||
*
|
|
||||||
* @param len Length of the buffer to convert.
|
|
||||||
*
|
|
||||||
* @return The hex string or NULL on error.
|
|
||||||
*
|
|
||||||
* @see ssh_string_free_char()
|
|
||||||
*/
|
|
||||||
char *ssh_get_hexa(const unsigned char *what, size_t len) {
|
|
||||||
const char h[] = "0123456789abcdef";
|
|
||||||
char *hexa;
|
|
||||||
size_t i;
|
|
||||||
size_t hlen = len * 3;
|
|
||||||
|
|
||||||
if (len > (UINT_MAX - 1) / 3) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
hexa = malloc(hlen + 1);
|
|
||||||
if (hexa == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
hexa[i * 3] = h[(what[i] >> 4) & 0xF];
|
|
||||||
hexa[i * 3 + 1] = h[what[i] & 0xF];
|
|
||||||
hexa[i * 3 + 2] = ':';
|
|
||||||
}
|
|
||||||
hexa[hlen - 1] = '\0';
|
|
||||||
|
|
||||||
return hexa;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Print a buffer as colon separated hex string.
|
|
||||||
*
|
|
||||||
* @param descr Description printed in front of the hex string.
|
|
||||||
*
|
|
||||||
* @param what What should be converted to a hex string.
|
|
||||||
*
|
|
||||||
* @param len Length of the buffer to convert.
|
|
||||||
*/
|
|
||||||
void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len) {
|
|
||||||
char *hexa = ssh_get_hexa(what, len);
|
|
||||||
|
|
||||||
if (hexa == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
printf("%s: %s\n", descr, hexa);
|
|
||||||
|
|
||||||
free(hexa);
|
|
||||||
}
|
|
||||||
|
|
||||||
int dh_generate_x(ssh_session session) {
|
int dh_generate_x(ssh_session session) {
|
||||||
|
int keysize;
|
||||||
|
if (session->next_crypto->kex_type == SSH_KEX_DH_GROUP1_SHA1) {
|
||||||
|
keysize = 1023;
|
||||||
|
} else {
|
||||||
|
keysize = 2047;
|
||||||
|
}
|
||||||
session->next_crypto->x = bignum_new();
|
session->next_crypto->x = bignum_new();
|
||||||
if (session->next_crypto->x == NULL) {
|
if (session->next_crypto->x == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_LIBGCRYPT
|
#ifdef HAVE_LIBGCRYPT
|
||||||
bignum_rand(session->next_crypto->x, 128);
|
bignum_rand(session->next_crypto->x, keysize);
|
||||||
#elif defined HAVE_LIBCRYPTO
|
#elif defined HAVE_LIBCRYPTO
|
||||||
bignum_rand(session->next_crypto->x, 128, 0, -1);
|
bignum_rand(session->next_crypto->x, keysize, -1, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* not harder than this */
|
/* not harder than this */
|
||||||
@@ -318,15 +254,21 @@ int dh_generate_x(ssh_session session) {
|
|||||||
|
|
||||||
/* used by server */
|
/* used by server */
|
||||||
int dh_generate_y(ssh_session session) {
|
int dh_generate_y(ssh_session session) {
|
||||||
session->next_crypto->y = bignum_new();
|
int keysize;
|
||||||
|
if (session->next_crypto->kex_type == SSH_KEX_DH_GROUP1_SHA1) {
|
||||||
|
keysize = 1023;
|
||||||
|
} else {
|
||||||
|
keysize = 2047;
|
||||||
|
}
|
||||||
|
session->next_crypto->y = bignum_new();
|
||||||
if (session->next_crypto->y == NULL) {
|
if (session->next_crypto->y == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_LIBGCRYPT
|
#ifdef HAVE_LIBGCRYPT
|
||||||
bignum_rand(session->next_crypto->y, 128);
|
bignum_rand(session->next_crypto->y, keysize);
|
||||||
#elif defined HAVE_LIBCRYPTO
|
#elif defined HAVE_LIBCRYPTO
|
||||||
bignum_rand(session->next_crypto->y, 128, 0, -1);
|
bignum_rand(session->next_crypto->y, keysize, -1, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* not harder than this */
|
/* not harder than this */
|
||||||
@@ -408,62 +350,6 @@ int dh_generate_f(ssh_session session) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_string make_bignum_string(bignum num) {
|
|
||||||
ssh_string ptr = NULL;
|
|
||||||
int pad = 0;
|
|
||||||
unsigned int len = bignum_num_bytes(num);
|
|
||||||
unsigned int bits = bignum_num_bits(num);
|
|
||||||
|
|
||||||
if (len == 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the first bit is set we have a negative number */
|
|
||||||
if (!(bits % 8) && bignum_is_bit_set(num, bits - 1)) {
|
|
||||||
pad++;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG_CRYPTO
|
|
||||||
fprintf(stderr, "%d bits, %d bytes, %d padding\n", bits, len, pad);
|
|
||||||
#endif /* DEBUG_CRYPTO */
|
|
||||||
|
|
||||||
ptr = ssh_string_new(len + pad);
|
|
||||||
if (ptr == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We have a negative number so we need a leading zero */
|
|
||||||
if (pad) {
|
|
||||||
ptr->data[0] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_LIBGCRYPT
|
|
||||||
bignum_bn2bin(num, len, ptr->data + pad);
|
|
||||||
#elif HAVE_LIBCRYPTO
|
|
||||||
bignum_bn2bin(num, ptr->data + pad);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bignum make_string_bn(ssh_string string){
|
|
||||||
bignum bn = NULL;
|
|
||||||
unsigned int len = ssh_string_len(string);
|
|
||||||
|
|
||||||
#ifdef DEBUG_CRYPTO
|
|
||||||
fprintf(stderr, "Importing a %d bits, %d bytes object ...\n",
|
|
||||||
len * 8, len);
|
|
||||||
#endif /* DEBUG_CRYPTO */
|
|
||||||
|
|
||||||
#ifdef HAVE_LIBGCRYPT
|
|
||||||
bignum_bin2bn(string->data, len, &bn);
|
|
||||||
#elif defined HAVE_LIBCRYPTO
|
|
||||||
bn = bignum_bin2bn(string->data, len, NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return bn;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssh_string dh_get_e(ssh_session session) {
|
ssh_string dh_get_e(ssh_session session) {
|
||||||
return make_bignum_string(session->next_crypto->e);
|
return make_bignum_string(session->next_crypto->e);
|
||||||
}
|
}
|
||||||
@@ -561,10 +447,6 @@ int ssh_client_dh_init(ssh_session session){
|
|||||||
ssh_string e = NULL;
|
ssh_string e = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (buffer_add_u8(session->out_buffer, SSH2_MSG_KEXDH_INIT) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dh_generate_x(session) < 0) {
|
if (dh_generate_x(session) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -577,9 +459,11 @@ int ssh_client_dh_init(ssh_session session){
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer_add_ssh_string(session->out_buffer, e) < 0) {
|
rc = ssh_buffer_pack(session->out_buffer, "bS", SSH2_MSG_KEXDH_INIT, e);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_string_burn(e);
|
ssh_string_burn(e);
|
||||||
ssh_string_free(e);
|
ssh_string_free(e);
|
||||||
e=NULL;
|
e=NULL;
|
||||||
@@ -644,205 +528,180 @@ error:
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
static void sha_add(ssh_string str,SHACTX ctx){
|
|
||||||
sha1_update(ctx,str,string_len(str)+4);
|
|
||||||
#ifdef DEBUG_CRYPTO
|
|
||||||
ssh_print_hexa("partial hashed sessionid",str,string_len(str)+4);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
int make_sessionid(ssh_session session) {
|
int make_sessionid(ssh_session session) {
|
||||||
ssh_string num = NULL;
|
ssh_string num = NULL;
|
||||||
ssh_string str = NULL;
|
ssh_buffer server_hash = NULL;
|
||||||
ssh_buffer server_hash = NULL;
|
ssh_buffer client_hash = NULL;
|
||||||
ssh_buffer client_hash = NULL;
|
ssh_buffer buf = NULL;
|
||||||
ssh_buffer buf = NULL;
|
int rc = SSH_ERROR;
|
||||||
uint32_t len;
|
|
||||||
int rc = SSH_ERROR;
|
|
||||||
|
|
||||||
buf = ssh_buffer_new();
|
buf = ssh_buffer_new();
|
||||||
if (buf == NULL) {
|
if (buf == NULL) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
|
||||||
|
|
||||||
str = ssh_string_from_char(session->clientbanner);
|
|
||||||
if (str == NULL) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer_add_ssh_string(buf, str) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
ssh_string_free(str);
|
|
||||||
|
|
||||||
str = ssh_string_from_char(session->serverbanner);
|
|
||||||
if (str == NULL) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer_add_ssh_string(buf, str) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (session->client) {
|
|
||||||
server_hash = session->in_hashbuf;
|
|
||||||
client_hash = session->out_hashbuf;
|
|
||||||
} else {
|
|
||||||
server_hash = session->out_hashbuf;
|
|
||||||
client_hash = session->in_hashbuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer_add_u32(server_hash, 0) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (buffer_add_u8(server_hash, 0) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (buffer_add_u32(client_hash, 0) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (buffer_add_u8(client_hash, 0) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = ntohl(buffer_get_rest_len(client_hash));
|
|
||||||
if (buffer_add_u32(buf,len) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (buffer_add_data(buf, buffer_get_rest(client_hash),
|
|
||||||
buffer_get_rest_len(client_hash)) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = ntohl(buffer_get_rest_len(server_hash));
|
|
||||||
if (buffer_add_u32(buf, len) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (buffer_add_data(buf, buffer_get_rest(server_hash),
|
|
||||||
buffer_get_rest_len(server_hash)) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = ssh_string_len(session->next_crypto->server_pubkey) + 4;
|
|
||||||
if (buffer_add_data(buf, session->next_crypto->server_pubkey, len) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if(session->next_crypto->kex_type == SSH_KEX_DH_GROUP1_SHA1 ||
|
|
||||||
session->next_crypto->kex_type == SSH_KEX_DH_GROUP14_SHA1) {
|
|
||||||
|
|
||||||
num = make_bignum_string(session->next_crypto->e);
|
|
||||||
if (num == NULL) {
|
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
len = ssh_string_len(num) + 4;
|
rc = ssh_buffer_pack(buf,
|
||||||
if (buffer_add_data(buf, num, len) < 0) {
|
"ss",
|
||||||
goto error;
|
session->clientbanner,
|
||||||
|
session->serverbanner);
|
||||||
|
if (rc == SSH_ERROR) {
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_string_free(num);
|
if (session->client) {
|
||||||
num = make_bignum_string(session->next_crypto->f);
|
server_hash = session->in_hashbuf;
|
||||||
if (num == NULL) {
|
client_hash = session->out_hashbuf;
|
||||||
goto error;
|
} else {
|
||||||
|
server_hash = session->out_hashbuf;
|
||||||
|
client_hash = session->in_hashbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = ssh_string_len(num) + 4;
|
/*
|
||||||
if (buffer_add_data(buf, num, len) < 0) {
|
* Handle the two final fields for the KEXINIT message (RFC 4253 7.1):
|
||||||
goto error;
|
*
|
||||||
|
* boolean first_kex_packet_follows
|
||||||
|
* uint32 0 (reserved for future extension)
|
||||||
|
*/
|
||||||
|
rc = buffer_add_u8(server_hash, 0);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
rc = buffer_add_u32(server_hash, 0);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_string_free(num);
|
/* These fields are handled for the server case in ssh_packet_kexinit. */
|
||||||
|
if (session->client) {
|
||||||
|
rc = buffer_add_u8(client_hash, 0);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
rc = buffer_add_u32(client_hash, 0);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_buffer_pack(buf,
|
||||||
|
"dPdPS",
|
||||||
|
buffer_get_rest_len(client_hash),
|
||||||
|
buffer_get_rest_len(client_hash),
|
||||||
|
buffer_get_rest(client_hash),
|
||||||
|
buffer_get_rest_len(server_hash),
|
||||||
|
buffer_get_rest_len(server_hash),
|
||||||
|
buffer_get_rest(server_hash),
|
||||||
|
session->next_crypto->server_pubkey);
|
||||||
|
|
||||||
|
if(rc != SSH_OK){
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session->next_crypto->kex_type == SSH_KEX_DH_GROUP1_SHA1 ||
|
||||||
|
session->next_crypto->kex_type == SSH_KEX_DH_GROUP14_SHA1) {
|
||||||
|
rc = ssh_buffer_pack(buf,
|
||||||
|
"BB",
|
||||||
|
session->next_crypto->e,
|
||||||
|
session->next_crypto->f);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_ECDH
|
#ifdef HAVE_ECDH
|
||||||
} else if (session->next_crypto->kex_type == SSH_KEX_ECDH_SHA2_NISTP256){
|
} else if (session->next_crypto->kex_type == SSH_KEX_ECDH_SHA2_NISTP256) {
|
||||||
if(session->next_crypto->ecdh_client_pubkey == NULL ||
|
if (session->next_crypto->ecdh_client_pubkey == NULL ||
|
||||||
session->next_crypto->ecdh_server_pubkey == NULL){
|
session->next_crypto->ecdh_server_pubkey == NULL) {
|
||||||
SSH_LOG(SSH_LOG_WARNING, "ECDH parameted missing");
|
SSH_LOG(SSH_LOG_WARNING, "ECDH parameted missing");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
rc = buffer_add_ssh_string(buf,session->next_crypto->ecdh_client_pubkey);
|
rc = ssh_buffer_pack(buf,
|
||||||
if (rc < 0) {
|
"SS",
|
||||||
goto error;
|
session->next_crypto->ecdh_client_pubkey,
|
||||||
}
|
session->next_crypto->ecdh_server_pubkey);
|
||||||
rc = buffer_add_ssh_string(buf,session->next_crypto->ecdh_server_pubkey);
|
if (rc != SSH_OK) {
|
||||||
if (rc < 0) {
|
goto error;
|
||||||
goto error;
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
#ifdef HAVE_CURVE25519
|
||||||
num = make_bignum_string(session->next_crypto->k);
|
} else if (session->next_crypto->kex_type == SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG) {
|
||||||
if (num == NULL) {
|
rc = ssh_buffer_pack(buf,
|
||||||
goto error;
|
"dPdP",
|
||||||
}
|
CURVE25519_PUBKEY_SIZE,
|
||||||
|
(size_t)CURVE25519_PUBKEY_SIZE, session->next_crypto->curve25519_client_pubkey,
|
||||||
|
CURVE25519_PUBKEY_SIZE,
|
||||||
|
(size_t)CURVE25519_PUBKEY_SIZE, session->next_crypto->curve25519_server_pubkey);
|
||||||
|
|
||||||
len = ssh_string_len(num) + 4;
|
if (rc != SSH_OK) {
|
||||||
if (buffer_add_data(buf, num, len) < 0) {
|
goto error;
|
||||||
goto error;
|
}
|
||||||
}
|
#endif
|
||||||
|
}
|
||||||
|
rc = ssh_buffer_pack(buf, "B", session->next_crypto->k);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_CRYPTO
|
#ifdef DEBUG_CRYPTO
|
||||||
ssh_print_hexa("hash buffer", ssh_buffer_get_begin(buf), ssh_buffer_get_len(buf));
|
ssh_print_hexa("hash buffer", ssh_buffer_get_begin(buf), ssh_buffer_get_len(buf));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch(session->next_crypto->kex_type){
|
switch (session->next_crypto->kex_type) {
|
||||||
case SSH_KEX_DH_GROUP1_SHA1:
|
case SSH_KEX_DH_GROUP1_SHA1:
|
||||||
case SSH_KEX_DH_GROUP14_SHA1:
|
case SSH_KEX_DH_GROUP14_SHA1:
|
||||||
session->next_crypto->digest_len = SHA_DIGEST_LENGTH;
|
session->next_crypto->digest_len = SHA_DIGEST_LENGTH;
|
||||||
session->next_crypto->mac_type = SSH_MAC_SHA1;
|
session->next_crypto->mac_type = SSH_MAC_SHA1;
|
||||||
session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
|
session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
|
||||||
if(session->next_crypto->secret_hash == NULL){
|
if (session->next_crypto->secret_hash == NULL) {
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
sha1(buffer_get_rest(buf), buffer_get_rest_len(buf),
|
sha1(buffer_get_rest(buf), buffer_get_rest_len(buf),
|
||||||
session->next_crypto->secret_hash);
|
session->next_crypto->secret_hash);
|
||||||
break;
|
break;
|
||||||
case SSH_KEX_ECDH_SHA2_NISTP256:
|
case SSH_KEX_ECDH_SHA2_NISTP256:
|
||||||
session->next_crypto->digest_len = SHA256_DIGEST_LENGTH;
|
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
|
||||||
session->next_crypto->mac_type = SSH_MAC_SHA256;
|
session->next_crypto->digest_len = SHA256_DIGEST_LENGTH;
|
||||||
session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
|
session->next_crypto->mac_type = SSH_MAC_SHA256;
|
||||||
if(session->next_crypto->secret_hash == NULL){
|
session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
|
||||||
ssh_set_error_oom(session);
|
if (session->next_crypto->secret_hash == NULL) {
|
||||||
goto error;
|
ssh_set_error_oom(session);
|
||||||
}
|
goto error;
|
||||||
sha256(buffer_get_rest(buf), buffer_get_rest_len(buf),
|
}
|
||||||
session->next_crypto->secret_hash);
|
sha256(buffer_get_rest(buf), buffer_get_rest_len(buf),
|
||||||
break;
|
session->next_crypto->secret_hash);
|
||||||
}
|
break;
|
||||||
/* During the first kex, secret hash and session ID are equal. However, after
|
}
|
||||||
* a key re-exchange, a new secret hash is calculated. This hash will not replace
|
/* During the first kex, secret hash and session ID are equal. However, after
|
||||||
* but complement existing session id.
|
* a key re-exchange, a new secret hash is calculated. This hash will not replace
|
||||||
*/
|
* but complement existing session id.
|
||||||
if (!session->next_crypto->session_id){
|
*/
|
||||||
session->next_crypto->session_id = malloc(session->next_crypto->digest_len);
|
if (!session->next_crypto->session_id) {
|
||||||
if (session->next_crypto->session_id == NULL){
|
session->next_crypto->session_id = malloc(session->next_crypto->digest_len);
|
||||||
ssh_set_error_oom(session);
|
if (session->next_crypto->session_id == NULL) {
|
||||||
goto error;
|
ssh_set_error_oom(session);
|
||||||
}
|
goto error;
|
||||||
memcpy(session->next_crypto->session_id, session->next_crypto->secret_hash,
|
}
|
||||||
session->next_crypto->digest_len);
|
memcpy(session->next_crypto->session_id, session->next_crypto->secret_hash,
|
||||||
}
|
session->next_crypto->digest_len);
|
||||||
|
}
|
||||||
#ifdef DEBUG_CRYPTO
|
#ifdef DEBUG_CRYPTO
|
||||||
printf("Session hash: \n");
|
printf("Session hash: \n");
|
||||||
ssh_print_hexa("secret hash", session->next_crypto->secret_hash, session->next_crypto->digest_len);
|
ssh_print_hexa("secret hash", session->next_crypto->secret_hash, session->next_crypto->digest_len);
|
||||||
ssh_print_hexa("session id", session->next_crypto->session_id, session->next_crypto->digest_len);
|
ssh_print_hexa("session id", session->next_crypto->session_id, session->next_crypto->digest_len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rc = SSH_OK;
|
rc = SSH_OK;
|
||||||
error:
|
error:
|
||||||
ssh_buffer_free(buf);
|
ssh_buffer_free(buf);
|
||||||
ssh_buffer_free(client_hash);
|
ssh_buffer_free(client_hash);
|
||||||
ssh_buffer_free(server_hash);
|
ssh_buffer_free(server_hash);
|
||||||
|
|
||||||
session->in_hashbuf = NULL;
|
session->in_hashbuf = NULL;
|
||||||
session->out_hashbuf = NULL;
|
session->out_hashbuf = NULL;
|
||||||
|
|
||||||
ssh_string_free(str);
|
ssh_string_free(num);
|
||||||
ssh_string_free(num);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hashbufout_add_cookie(ssh_session session) {
|
int hashbufout_add_cookie(ssh_session session) {
|
||||||
@@ -852,20 +711,20 @@ int hashbufout_add_cookie(ssh_session session) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (buffer_add_u8(session->out_hashbuf, 20) < 0) {
|
if (buffer_add_u8(session->out_hashbuf, 20) < 0) {
|
||||||
buffer_reinit(session->out_hashbuf);
|
ssh_buffer_reinit(session->out_hashbuf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session->server) {
|
if (session->server) {
|
||||||
if (buffer_add_data(session->out_hashbuf,
|
if (ssh_buffer_add_data(session->out_hashbuf,
|
||||||
session->next_crypto->server_kex.cookie, 16) < 0) {
|
session->next_crypto->server_kex.cookie, 16) < 0) {
|
||||||
buffer_reinit(session->out_hashbuf);
|
ssh_buffer_reinit(session->out_hashbuf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (buffer_add_data(session->out_hashbuf,
|
if (ssh_buffer_add_data(session->out_hashbuf,
|
||||||
session->next_crypto->client_kex.cookie, 16) < 0) {
|
session->next_crypto->client_kex.cookie, 16) < 0) {
|
||||||
buffer_reinit(session->out_hashbuf);
|
ssh_buffer_reinit(session->out_hashbuf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -880,11 +739,11 @@ int hashbufin_add_cookie(ssh_session session, unsigned char *cookie) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (buffer_add_u8(session->in_hashbuf, 20) < 0) {
|
if (buffer_add_u8(session->in_hashbuf, 20) < 0) {
|
||||||
buffer_reinit(session->in_hashbuf);
|
ssh_buffer_reinit(session->in_hashbuf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (buffer_add_data(session->in_hashbuf,cookie, 16) < 0) {
|
if (ssh_buffer_add_data(session->in_hashbuf,cookie, 16) < 0) {
|
||||||
buffer_reinit(session->in_hashbuf);
|
ssh_buffer_reinit(session->in_hashbuf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -892,8 +751,10 @@ int hashbufin_add_cookie(ssh_session session, unsigned char *cookie) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int generate_one_key(ssh_string k,
|
static int generate_one_key(ssh_string k,
|
||||||
struct ssh_crypto_struct *crypto, unsigned char *output, char letter) {
|
struct ssh_crypto_struct *crypto, unsigned char **output, char letter, size_t requested_size) {
|
||||||
ssh_mac_ctx ctx;
|
ssh_mac_ctx ctx;
|
||||||
|
unsigned char *tmp;
|
||||||
|
size_t size = crypto->digest_len;
|
||||||
ctx=ssh_mac_ctx_init(crypto->mac_type);
|
ctx=ssh_mac_ctx_init(crypto->mac_type);
|
||||||
|
|
||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
@@ -904,14 +765,32 @@ static int generate_one_key(ssh_string k,
|
|||||||
ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len);
|
ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len);
|
||||||
ssh_mac_update(ctx, &letter, 1);
|
ssh_mac_update(ctx, &letter, 1);
|
||||||
ssh_mac_update(ctx, crypto->session_id, crypto->digest_len);
|
ssh_mac_update(ctx, crypto->session_id, crypto->digest_len);
|
||||||
ssh_mac_final(output, ctx);
|
ssh_mac_final(*output, ctx);
|
||||||
|
|
||||||
|
while(requested_size > size) {
|
||||||
|
tmp = realloc(*output, size + crypto->digest_len);
|
||||||
|
if (tmp == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*output = tmp;
|
||||||
|
|
||||||
|
ctx = ssh_mac_ctx_init(crypto->mac_type);
|
||||||
|
if (ctx == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ssh_mac_update(ctx, k, ssh_string_len(k) + 4);
|
||||||
|
ssh_mac_update(ctx, crypto->secret_hash,
|
||||||
|
crypto->digest_len);
|
||||||
|
ssh_mac_update(ctx, tmp, size);
|
||||||
|
ssh_mac_final(tmp + size, ctx);
|
||||||
|
size += crypto->digest_len;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int generate_session_keys(ssh_session session) {
|
int generate_session_keys(ssh_session session) {
|
||||||
ssh_string k_string = NULL;
|
ssh_string k_string = NULL;
|
||||||
ssh_mac_ctx ctx = NULL;
|
|
||||||
struct ssh_crypto_struct *crypto = session->next_crypto;
|
struct ssh_crypto_struct *crypto = session->next_crypto;
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
|
|
||||||
@@ -936,88 +815,71 @@ int generate_session_keys(ssh_session session) {
|
|||||||
|
|
||||||
/* IV */
|
/* IV */
|
||||||
if (session->client) {
|
if (session->client) {
|
||||||
if (generate_one_key(k_string, crypto, crypto->encryptIV, 'A') < 0) {
|
rc = generate_one_key(k_string, crypto, &crypto->encryptIV, 'A', crypto->digest_len);
|
||||||
|
if (rc < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (generate_one_key(k_string, crypto, crypto->decryptIV, 'B') < 0) {
|
rc = generate_one_key(k_string, crypto, &crypto->decryptIV, 'B', crypto->digest_len);
|
||||||
|
if (rc < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (generate_one_key(k_string, crypto, crypto->decryptIV, 'A') < 0) {
|
rc = generate_one_key(k_string, crypto, &crypto->decryptIV, 'A', crypto->digest_len);
|
||||||
|
if (rc < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (generate_one_key(k_string, crypto, crypto->encryptIV, 'B') < 0) {
|
rc = generate_one_key(k_string, crypto, &crypto->encryptIV, 'B', crypto->digest_len);
|
||||||
|
if (rc < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (session->client) {
|
if (session->client) {
|
||||||
if (generate_one_key(k_string, crypto, crypto->encryptkey, 'C') < 0) {
|
rc = generate_one_key(k_string, crypto, &crypto->encryptkey, 'C', crypto->out_cipher->keysize / 8);
|
||||||
|
if (rc < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (generate_one_key(k_string, crypto, crypto->decryptkey, 'D') < 0) {
|
rc = generate_one_key(k_string, crypto, &crypto->decryptkey, 'D', crypto->in_cipher->keysize / 8);
|
||||||
|
if (rc < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (generate_one_key(k_string, crypto, crypto->decryptkey, 'C') < 0) {
|
rc = generate_one_key(k_string, crypto, &crypto->decryptkey, 'C', crypto->in_cipher->keysize / 8);
|
||||||
|
if (rc < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (generate_one_key(k_string, crypto, crypto->encryptkey, 'D') < 0) {
|
rc = generate_one_key(k_string, crypto, &crypto->encryptkey, 'D', crypto->out_cipher->keysize / 8);
|
||||||
|
if (rc < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* some ciphers need more than DIGEST_LEN bytes of input key */
|
|
||||||
if (crypto->out_cipher->keysize > crypto->digest_len * 8) {
|
|
||||||
crypto->encryptkey = realloc(crypto->encryptkey, crypto->digest_len * 2);
|
|
||||||
if(crypto->encryptkey == NULL)
|
|
||||||
goto error;
|
|
||||||
ctx = ssh_mac_ctx_init(crypto->mac_type);
|
|
||||||
if (ctx == NULL) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
ssh_mac_update(ctx, k_string, ssh_string_len(k_string) + 4);
|
|
||||||
ssh_mac_update(ctx, crypto->secret_hash,
|
|
||||||
crypto->digest_len);
|
|
||||||
ssh_mac_update(ctx, crypto->encryptkey, crypto->digest_len);
|
|
||||||
ssh_mac_final(crypto->encryptkey + crypto->digest_len, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (crypto->in_cipher->keysize > crypto->digest_len * 8) {
|
|
||||||
crypto->decryptkey = realloc(crypto->decryptkey, crypto->digest_len *2);
|
|
||||||
if(crypto->decryptkey == NULL)
|
|
||||||
goto error;
|
|
||||||
ctx = ssh_mac_ctx_init(crypto->mac_type);
|
|
||||||
ssh_mac_update(ctx, k_string, ssh_string_len(k_string) + 4);
|
|
||||||
ssh_mac_update(ctx, crypto->secret_hash,
|
|
||||||
crypto->digest_len);
|
|
||||||
ssh_mac_update(ctx, crypto->decryptkey, crypto->digest_len);
|
|
||||||
ssh_mac_final(crypto->decryptkey + crypto->digest_len, ctx);
|
|
||||||
}
|
|
||||||
if(session->client) {
|
if(session->client) {
|
||||||
if (generate_one_key(k_string, crypto, crypto->encryptMAC, 'E') < 0) {
|
rc = generate_one_key(k_string, crypto, &crypto->encryptMAC, 'E', hmac_digest_len(crypto->out_hmac));
|
||||||
|
if (rc < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (generate_one_key(k_string, crypto, crypto->decryptMAC, 'F') < 0) {
|
rc = generate_one_key(k_string, crypto, &crypto->decryptMAC, 'F', hmac_digest_len(crypto->in_hmac));
|
||||||
|
if (rc < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (generate_one_key(k_string, crypto, crypto->decryptMAC, 'E') < 0) {
|
rc = generate_one_key(k_string, crypto, &crypto->decryptMAC, 'E', hmac_digest_len(crypto->in_hmac));
|
||||||
|
if (rc < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (generate_one_key(k_string, crypto, crypto->encryptMAC, 'F') < 0) {
|
rc = generate_one_key(k_string, crypto, &crypto->encryptMAC, 'F', hmac_digest_len(crypto->out_hmac));
|
||||||
|
if (rc < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_CRYPTO
|
#ifdef DEBUG_CRYPTO
|
||||||
ssh_print_hexa("Encrypt IV", crypto->encryptIV, SHA_DIGEST_LEN);
|
ssh_print_hexa("Encrypt IV", crypto->encryptIV, crypto->digest_len);
|
||||||
ssh_print_hexa("Decrypt IV", crypto->decryptIV, SHA_DIGEST_LEN);
|
ssh_print_hexa("Decrypt IV", crypto->decryptIV, crypto->digest_len);
|
||||||
ssh_print_hexa("Encryption key", crypto->encryptkey,
|
ssh_print_hexa("Encryption key", crypto->encryptkey, crypto->out_cipher->keysize / 8);
|
||||||
crypto->out_cipher->keysize);
|
ssh_print_hexa("Decryption key", crypto->decryptkey, crypto->in_cipher->keysize / 8);
|
||||||
ssh_print_hexa("Decryption key", crypto->decryptkey,
|
ssh_print_hexa("Encryption MAC", crypto->encryptMAC, hmac_digest_len(crypto->out_hmac));
|
||||||
crypto->in_cipher->keysize);
|
ssh_print_hexa("Decryption MAC", crypto->decryptMAC, hmac_digest_len(crypto->in_hmac));
|
||||||
ssh_print_hexa("Encryption MAC", crypto->encryptMAC, SHA_DIGEST_LEN);
|
|
||||||
ssh_print_hexa("Decryption MAC", crypto->decryptMAC, 20);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rc = 0;
|
rc = 0;
|
||||||
@@ -1034,25 +896,7 @@ error:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Allocates a buffer with the MD5 hash of the server public key.
|
* @deprecated Use ssh_get_publickey_hash()
|
||||||
*
|
|
||||||
* This function allows you to get a MD5 hash of the public key. You can then
|
|
||||||
* print this hash in a human-readable form to the user so that he is able to
|
|
||||||
* verify it. Use ssh_get_hexa() or ssh_print_hexa() to display it.
|
|
||||||
*
|
|
||||||
* @param[in] session The SSH session to use.
|
|
||||||
*
|
|
||||||
* @param[in] hash The buffer to allocate.
|
|
||||||
*
|
|
||||||
* @return The bytes allocated or < 0 on error.
|
|
||||||
*
|
|
||||||
* @warning It is very important that you verify at some moment that the hash
|
|
||||||
* matches a known server. If you don't do it, cryptography wont help
|
|
||||||
* you at making things secure
|
|
||||||
*
|
|
||||||
* @see ssh_is_server_known()
|
|
||||||
* @see ssh_get_hexa()
|
|
||||||
* @see ssh_print_hexa()
|
|
||||||
*/
|
*/
|
||||||
int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash) {
|
int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash) {
|
||||||
ssh_string pubkey;
|
ssh_string pubkey;
|
||||||
@@ -1129,6 +973,164 @@ int ssh_get_publickey(ssh_session session, ssh_key *key)
|
|||||||
key);
|
key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocates a buffer with the hash of the public key.
|
||||||
|
*
|
||||||
|
* This function allows you to get a hash of the public key. You can then
|
||||||
|
* print this hash in a human-readable form to the user so that he is able to
|
||||||
|
* verify it. Use ssh_get_hexa() or ssh_print_hexa() to display it.
|
||||||
|
*
|
||||||
|
* @param[in] key The public key to create the hash for.
|
||||||
|
*
|
||||||
|
* @param[in] type The type of the hash you want.
|
||||||
|
*
|
||||||
|
* @param[in] hash A pointer to store the allocated buffer. It can be
|
||||||
|
* freed using ssh_clean_pubkey_hash().
|
||||||
|
*
|
||||||
|
* @param[in] hlen The length of the hash.
|
||||||
|
*
|
||||||
|
* @return 0 on success, -1 if an error occured.
|
||||||
|
*
|
||||||
|
* @warning It is very important that you verify at some moment that the hash
|
||||||
|
* matches a known server. If you don't do it, cryptography wont help
|
||||||
|
* you at making things secure.
|
||||||
|
* OpenSSH uses SHA1 to print public key digests.
|
||||||
|
*
|
||||||
|
* @see ssh_is_server_known()
|
||||||
|
* @see ssh_get_hexa()
|
||||||
|
* @see ssh_print_hexa()
|
||||||
|
* @see ssh_clean_pubkey_hash()
|
||||||
|
*/
|
||||||
|
int ssh_get_publickey_hash(const ssh_key key,
|
||||||
|
enum ssh_publickey_hash_type type,
|
||||||
|
unsigned char **hash,
|
||||||
|
size_t *hlen)
|
||||||
|
{
|
||||||
|
ssh_string blob;
|
||||||
|
unsigned char *h;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = ssh_pki_export_pubkey_blob(key, &blob);
|
||||||
|
if (rc < 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case SSH_PUBLICKEY_HASH_SHA1:
|
||||||
|
{
|
||||||
|
SHACTX ctx;
|
||||||
|
|
||||||
|
h = malloc(SHA_DIGEST_LEN);
|
||||||
|
if (h == NULL) {
|
||||||
|
rc = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = sha1_init();
|
||||||
|
if (ctx == NULL) {
|
||||||
|
free(h);
|
||||||
|
rc = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
sha1_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
|
||||||
|
sha1_final(h, ctx);
|
||||||
|
|
||||||
|
*hlen = SHA_DIGEST_LEN;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SSH_PUBLICKEY_HASH_MD5:
|
||||||
|
{
|
||||||
|
MD5CTX ctx;
|
||||||
|
|
||||||
|
h = malloc(MD5_DIGEST_LEN);
|
||||||
|
if (h == NULL) {
|
||||||
|
rc = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = md5_init();
|
||||||
|
if (ctx == NULL) {
|
||||||
|
free(h);
|
||||||
|
rc = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
md5_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
|
||||||
|
md5_final(h, ctx);
|
||||||
|
|
||||||
|
*hlen = MD5_DIGEST_LEN;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rc = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
*hash = h;
|
||||||
|
rc = 0;
|
||||||
|
out:
|
||||||
|
ssh_string_free(blob);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert a buffer into a colon separated hex string.
|
||||||
|
* The caller has to free the memory.
|
||||||
|
*
|
||||||
|
* @param what What should be converted to a hex string.
|
||||||
|
*
|
||||||
|
* @param len Length of the buffer to convert.
|
||||||
|
*
|
||||||
|
* @return The hex string or NULL on error.
|
||||||
|
*
|
||||||
|
* @see ssh_string_free_char()
|
||||||
|
*/
|
||||||
|
char *ssh_get_hexa(const unsigned char *what, size_t len) {
|
||||||
|
const char h[] = "0123456789abcdef";
|
||||||
|
char *hexa;
|
||||||
|
size_t i;
|
||||||
|
size_t hlen = len * 3;
|
||||||
|
|
||||||
|
if (len > (UINT_MAX - 1) / 3) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
hexa = malloc(hlen + 1);
|
||||||
|
if (hexa == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
hexa[i * 3] = h[(what[i] >> 4) & 0xF];
|
||||||
|
hexa[i * 3 + 1] = h[what[i] & 0xF];
|
||||||
|
hexa[i * 3 + 2] = ':';
|
||||||
|
}
|
||||||
|
hexa[hlen - 1] = '\0';
|
||||||
|
|
||||||
|
return hexa;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Print a buffer as colon separated hex string.
|
||||||
|
*
|
||||||
|
* @param descr Description printed in front of the hex string.
|
||||||
|
*
|
||||||
|
* @param what What should be converted to a hex string.
|
||||||
|
*
|
||||||
|
* @param len Length of the buffer to convert.
|
||||||
|
*/
|
||||||
|
void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len) {
|
||||||
|
char *hexa = ssh_get_hexa(what, len);
|
||||||
|
|
||||||
|
if (hexa == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf("%s: %s\n", descr, hexa);
|
||||||
|
|
||||||
|
free(hexa);
|
||||||
|
}
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/* vim: set ts=4 sw=4 et cindent: */
|
/* vim: set ts=4 sw=4 et cindent: */
|
||||||
|
|||||||
89
src/ecdh.c
89
src/ecdh.c
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the SSH Library
|
* This file is part of the SSH Library
|
||||||
*
|
*
|
||||||
* Copyright (c) 2011 by Aris Adamantiadis
|
* Copyright (c) 2011-2013 by Aris Adamantiadis
|
||||||
*
|
*
|
||||||
* The SSH Library is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
@@ -26,6 +26,7 @@
|
|||||||
#include "libssh/buffer.h"
|
#include "libssh/buffer.h"
|
||||||
#include "libssh/ssh2.h"
|
#include "libssh/ssh2.h"
|
||||||
#include "libssh/pki.h"
|
#include "libssh/pki.h"
|
||||||
|
#include "libssh/bignum.h"
|
||||||
|
|
||||||
#ifdef HAVE_ECDH
|
#ifdef HAVE_ECDH
|
||||||
#include <openssl/ecdh.h>
|
#include <openssl/ecdh.h>
|
||||||
@@ -99,6 +100,7 @@ static int ecdh_build_k(ssh_session session) {
|
|||||||
const EC_GROUP *group = EC_KEY_get0_group(session->next_crypto->ecdh_privkey);
|
const EC_GROUP *group = EC_KEY_get0_group(session->next_crypto->ecdh_privkey);
|
||||||
EC_POINT *pubkey;
|
EC_POINT *pubkey;
|
||||||
void *buffer;
|
void *buffer;
|
||||||
|
int rc;
|
||||||
int len = (EC_GROUP_get_degree(group) + 7) / 8;
|
int len = (EC_GROUP_get_degree(group) + 7) / 8;
|
||||||
bignum_CTX ctx = bignum_ctx_new();
|
bignum_CTX ctx = bignum_ctx_new();
|
||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
@@ -117,19 +119,48 @@ static int ecdh_build_k(ssh_session session) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session->server)
|
if (session->server) {
|
||||||
EC_POINT_oct2point(group,pubkey,ssh_string_data(session->next_crypto->ecdh_client_pubkey),
|
rc = EC_POINT_oct2point(group,
|
||||||
ssh_string_len(session->next_crypto->ecdh_client_pubkey),ctx);
|
pubkey,
|
||||||
else
|
ssh_string_data(session->next_crypto->ecdh_client_pubkey),
|
||||||
EC_POINT_oct2point(group,pubkey,ssh_string_data(session->next_crypto->ecdh_server_pubkey),
|
ssh_string_len(session->next_crypto->ecdh_client_pubkey),
|
||||||
ssh_string_len(session->next_crypto->ecdh_server_pubkey),ctx);
|
ctx);
|
||||||
|
} else {
|
||||||
|
rc = EC_POINT_oct2point(group,
|
||||||
|
pubkey,
|
||||||
|
ssh_string_data(session->next_crypto->ecdh_server_pubkey),
|
||||||
|
ssh_string_len(session->next_crypto->ecdh_server_pubkey),
|
||||||
|
ctx);
|
||||||
|
}
|
||||||
|
bignum_ctx_free(ctx);
|
||||||
|
if (rc <= 0) {
|
||||||
|
EC_POINT_clear_free(pubkey);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
buffer = malloc(len);
|
buffer = malloc(len);
|
||||||
ECDH_compute_key(buffer,len,pubkey,session->next_crypto->ecdh_privkey,NULL);
|
if (buffer == NULL) {
|
||||||
EC_POINT_free(pubkey);
|
EC_POINT_clear_free(pubkey);
|
||||||
BN_bin2bn(buffer,len,session->next_crypto->k);
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ECDH_compute_key(buffer,
|
||||||
|
len,
|
||||||
|
pubkey,
|
||||||
|
session->next_crypto->ecdh_privkey,
|
||||||
|
NULL);
|
||||||
|
EC_POINT_clear_free(pubkey);
|
||||||
|
if (rc <= 0) {
|
||||||
|
free(buffer);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bignum_bin2bn(buffer, len, session->next_crypto->k);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
||||||
EC_KEY_free(session->next_crypto->ecdh_privkey);
|
EC_KEY_free(session->next_crypto->ecdh_privkey);
|
||||||
session->next_crypto->ecdh_privkey=NULL;
|
session->next_crypto->ecdh_privkey = NULL;
|
||||||
|
|
||||||
#ifdef DEBUG_CRYPTO
|
#ifdef DEBUG_CRYPTO
|
||||||
ssh_print_hexa("Session server cookie",
|
ssh_print_hexa("Session server cookie",
|
||||||
session->next_crypto->server_kex.cookie, 16);
|
session->next_crypto->server_kex.cookie, 16);
|
||||||
@@ -138,10 +169,6 @@ static int ecdh_build_k(ssh_session session) {
|
|||||||
ssh_print_bignum("Shared secret key", session->next_crypto->k);
|
ssh_print_bignum("Shared secret key", session->next_crypto->k);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_LIBCRYPTO
|
|
||||||
bignum_ctx_free(ctx);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,12 +286,6 @@ int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet){
|
|||||||
session->next_crypto->ecdh_privkey = ecdh_key;
|
session->next_crypto->ecdh_privkey = ecdh_key;
|
||||||
session->next_crypto->ecdh_server_pubkey = q_s_string;
|
session->next_crypto->ecdh_server_pubkey = q_s_string;
|
||||||
|
|
||||||
rc = buffer_add_u8(session->out_buffer, SSH2_MSG_KEXDH_REPLY);
|
|
||||||
if (rc < 0) {
|
|
||||||
ssh_set_error_oom(session);
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* build k and session_id */
|
/* build k and session_id */
|
||||||
rc = ecdh_build_k(session);
|
rc = ecdh_build_k(session);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
@@ -284,30 +305,22 @@ int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet){
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add host's public key */
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer,
|
|
||||||
session->next_crypto->server_pubkey);
|
|
||||||
if (rc < 0) {
|
|
||||||
ssh_set_error_oom(session);
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add ecdh public key */
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, q_s_string);
|
|
||||||
if (rc < 0) {
|
|
||||||
ssh_set_error_oom(session);
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
/* add signature blob */
|
|
||||||
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
|
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
|
||||||
if (sig_blob == NULL) {
|
if (sig_blob == NULL) {
|
||||||
ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
|
ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = buffer_add_ssh_string(session->out_buffer, sig_blob);
|
rc = ssh_buffer_pack(session->out_buffer,
|
||||||
|
"bSSS",
|
||||||
|
SSH2_MSG_KEXDH_REPLY,
|
||||||
|
session->next_crypto->server_pubkey, /* host's pubkey */
|
||||||
|
q_s_string, /* ecdh public key */
|
||||||
|
sig_blob); /* signature blob */
|
||||||
|
|
||||||
ssh_string_free(sig_blob);
|
ssh_string_free(sig_blob);
|
||||||
if (rc < 0) {
|
|
||||||
|
if (rc != SSH_OK) {
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ void _ssh_set_error_invalid(void *error, const char *function)
|
|||||||
/**
|
/**
|
||||||
* @brief Retrieve the error text message from the last error.
|
* @brief Retrieve the error text message from the last error.
|
||||||
*
|
*
|
||||||
* @param error The SSH session pointer.
|
* @param error An ssh_session or ssh_bind.
|
||||||
*
|
*
|
||||||
* @return A static string describing the error.
|
* @return A static string describing the error.
|
||||||
*/
|
*/
|
||||||
@@ -117,7 +117,7 @@ const char *ssh_get_error(void *error) {
|
|||||||
/**
|
/**
|
||||||
* @brief Retrieve the error code from the last error.
|
* @brief Retrieve the error code from the last error.
|
||||||
*
|
*
|
||||||
* @param error The SSH session pointer.
|
* @param error An ssh_session or ssh_bind.
|
||||||
*
|
*
|
||||||
* \return SSH_NO_ERROR No error occurred\n
|
* \return SSH_NO_ERROR No error occurred\n
|
||||||
* SSH_REQUEST_DENIED The last request was denied but situation is
|
* SSH_REQUEST_DENIED The last request was denied but situation is
|
||||||
|
|||||||
181
src/external/bcrypt_pbkdf.c
vendored
Normal file
181
src/external/bcrypt_pbkdf.c
vendored
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
/* $OpenBSD: bcrypt_pbkdf.c,v 1.4 2013/07/29 00:55:53 tedu Exp $ */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013 Ted Unangst <tedu@openbsd.org>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//#include "includes.h"
|
||||||
|
|
||||||
|
#ifndef HAVE_BCRYPT_PBKDF
|
||||||
|
|
||||||
|
#include "libssh/priv.h"
|
||||||
|
#include "libssh/wrapper.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#ifdef HAVE_SYS_PARAM_H
|
||||||
|
#include <sys/param.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "libssh/blf.h"
|
||||||
|
#include "libssh/pki_priv.h"
|
||||||
|
#ifndef SHA512_DIGEST_LENGTH
|
||||||
|
#define SHA512_DIGEST_LENGTH SHA512_DIGEST_LEN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pkcs #5 pbkdf2 implementation using the "bcrypt" hash
|
||||||
|
*
|
||||||
|
* The bcrypt hash function is derived from the bcrypt password hashing
|
||||||
|
* function with the following modifications:
|
||||||
|
* 1. The input password and salt are preprocessed with SHA512.
|
||||||
|
* 2. The output length is expanded to 256 bits.
|
||||||
|
* 3. Subsequently the magic string to be encrypted is lengthened and modifed
|
||||||
|
* to "OxychromaticBlowfishSwatDynamite"
|
||||||
|
* 4. The hash function is defined to perform 64 rounds of initial state
|
||||||
|
* expansion. (More rounds are performed by iterating the hash.)
|
||||||
|
*
|
||||||
|
* Note that this implementation pulls the SHA512 operations into the caller
|
||||||
|
* as a performance optimization.
|
||||||
|
*
|
||||||
|
* One modification from official pbkdf2. Instead of outputting key material
|
||||||
|
* linearly, we mix it. pbkdf2 has a known weakness where if one uses it to
|
||||||
|
* generate (i.e.) 512 bits of key material for use as two 256 bit keys, an
|
||||||
|
* attacker can merely run once through the outer loop below, but the user
|
||||||
|
* always runs it twice. Shuffling output bytes requires computing the
|
||||||
|
* entirety of the key material to assemble any subkey. This is something a
|
||||||
|
* wise caller could do; we just do it for you.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define BCRYPT_BLOCKS 8
|
||||||
|
#define BCRYPT_HASHSIZE (BCRYPT_BLOCKS * 4)
|
||||||
|
|
||||||
|
static void
|
||||||
|
bcrypt_hash(uint8_t *sha2pass, uint8_t *sha2salt, uint8_t *out)
|
||||||
|
{
|
||||||
|
blf_ctx state;
|
||||||
|
uint8_t ciphertext[BCRYPT_HASHSIZE] =
|
||||||
|
"OxychromaticBlowfishSwatDynamite";
|
||||||
|
uint32_t cdata[BCRYPT_BLOCKS];
|
||||||
|
int i;
|
||||||
|
uint16_t j;
|
||||||
|
size_t shalen = SHA512_DIGEST_LENGTH;
|
||||||
|
|
||||||
|
/* key expansion */
|
||||||
|
Blowfish_initstate(&state);
|
||||||
|
Blowfish_expandstate(&state, sha2salt, shalen, sha2pass, shalen);
|
||||||
|
for (i = 0; i < 64; i++) {
|
||||||
|
Blowfish_expand0state(&state, sha2salt, shalen);
|
||||||
|
Blowfish_expand0state(&state, sha2pass, shalen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* encryption */
|
||||||
|
j = 0;
|
||||||
|
for (i = 0; i < BCRYPT_BLOCKS; i++)
|
||||||
|
cdata[i] = Blowfish_stream2word(ciphertext, sizeof(ciphertext),
|
||||||
|
&j);
|
||||||
|
for (i = 0; i < 64; i++)
|
||||||
|
blf_enc(&state, cdata, sizeof(cdata) / sizeof(uint64_t));
|
||||||
|
|
||||||
|
/* copy out */
|
||||||
|
for (i = 0; i < BCRYPT_BLOCKS; i++) {
|
||||||
|
out[4 * i + 3] = (cdata[i] >> 24) & 0xff;
|
||||||
|
out[4 * i + 2] = (cdata[i] >> 16) & 0xff;
|
||||||
|
out[4 * i + 1] = (cdata[i] >> 8) & 0xff;
|
||||||
|
out[4 * i + 0] = cdata[i] & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* zap */
|
||||||
|
BURN_BUFFER(ciphertext, sizeof(ciphertext));
|
||||||
|
BURN_BUFFER(cdata, sizeof(cdata));
|
||||||
|
ZERO_STRUCT(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt, size_t saltlen,
|
||||||
|
uint8_t *key, size_t keylen, unsigned int rounds)
|
||||||
|
{
|
||||||
|
uint8_t sha2pass[SHA512_DIGEST_LENGTH];
|
||||||
|
uint8_t sha2salt[SHA512_DIGEST_LENGTH];
|
||||||
|
uint8_t out[BCRYPT_HASHSIZE];
|
||||||
|
uint8_t tmpout[BCRYPT_HASHSIZE];
|
||||||
|
uint8_t *countsalt;
|
||||||
|
size_t i, j, amt, stride;
|
||||||
|
uint32_t count;
|
||||||
|
size_t origkeylen = keylen;
|
||||||
|
SHA512CTX ctx;
|
||||||
|
|
||||||
|
/* nothing crazy */
|
||||||
|
if (rounds < 1)
|
||||||
|
return -1;
|
||||||
|
if (passlen == 0 || saltlen == 0 || keylen == 0 ||
|
||||||
|
keylen > sizeof(out) * sizeof(out) || saltlen > 1<<20)
|
||||||
|
return -1;
|
||||||
|
if ((countsalt = calloc(1, saltlen + 4)) == NULL)
|
||||||
|
return -1;
|
||||||
|
stride = (keylen + sizeof(out) - 1) / sizeof(out);
|
||||||
|
amt = (keylen + stride - 1) / stride;
|
||||||
|
|
||||||
|
memcpy(countsalt, salt, saltlen);
|
||||||
|
|
||||||
|
/* collapse password */
|
||||||
|
ctx = sha512_init();
|
||||||
|
sha512_update(ctx, pass, passlen);
|
||||||
|
sha512_final(sha2pass, ctx);
|
||||||
|
|
||||||
|
/* generate key, sizeof(out) at a time */
|
||||||
|
for (count = 1; keylen > 0; count++) {
|
||||||
|
countsalt[saltlen + 0] = (count >> 24) & 0xff;
|
||||||
|
countsalt[saltlen + 1] = (count >> 16) & 0xff;
|
||||||
|
countsalt[saltlen + 2] = (count >> 8) & 0xff;
|
||||||
|
countsalt[saltlen + 3] = count & 0xff;
|
||||||
|
|
||||||
|
/* first round, salt is salt */
|
||||||
|
ctx = sha512_init();
|
||||||
|
sha512_update(ctx, countsalt, saltlen + 4);
|
||||||
|
sha512_final(sha2salt, ctx);
|
||||||
|
|
||||||
|
bcrypt_hash(sha2pass, sha2salt, tmpout);
|
||||||
|
memcpy(out, tmpout, sizeof(out));
|
||||||
|
|
||||||
|
for (i = 1; i < rounds; i++) {
|
||||||
|
/* subsequent rounds, salt is previous output */
|
||||||
|
ctx = sha512_init();
|
||||||
|
sha512_update(ctx, tmpout, sizeof(tmpout));
|
||||||
|
sha512_final(sha2salt, ctx);
|
||||||
|
bcrypt_hash(sha2pass, sha2salt, tmpout);
|
||||||
|
for (j = 0; j < sizeof(out); j++)
|
||||||
|
out[j] ^= tmpout[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pbkdf2 deviation: ouput the key material non-linearly.
|
||||||
|
*/
|
||||||
|
amt = MIN(amt, keylen);
|
||||||
|
for (i = 0; i < amt; i++) {
|
||||||
|
size_t dest = i * stride + (count - 1);
|
||||||
|
if (dest >= origkeylen) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
key[dest] = out[i];
|
||||||
|
}
|
||||||
|
keylen -= i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* zap */
|
||||||
|
BURN_BUFFER(out, sizeof(out));
|
||||||
|
free(countsalt);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_BCRYPT_PBKDF */
|
||||||
694
src/external/blowfish.c
vendored
Normal file
694
src/external/blowfish.c
vendored
Normal file
@@ -0,0 +1,694 @@
|
|||||||
|
/* $OpenBSD: blowfish.c,v 1.18 2004/11/02 17:23:26 hshoexer Exp $ */
|
||||||
|
/*
|
||||||
|
* Blowfish block cipher for OpenBSD
|
||||||
|
* Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Implementation advice by David Mazieres <dm@lcs.mit.edu>.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by Niels Provos.
|
||||||
|
* 4. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This code is derived from section 14.3 and the given source
|
||||||
|
* in section V of Applied Cryptography, second edition.
|
||||||
|
* Blowfish is an unpatented fast block cipher designed by
|
||||||
|
* Bruce Schneier.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(HAVE_BCRYPT_PBKDF) && (!defined(HAVE_BLOWFISH_INITSTATE) || \
|
||||||
|
!defined(HAVE_BLOWFISH_EXPAND0STATE) || !defined(HAVE_BLF_ENC))
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#include <stdio.h> /* used for debugging */
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "libssh/blf.h"
|
||||||
|
|
||||||
|
#undef inline
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define inline __inline
|
||||||
|
#else /* !__GNUC__ */
|
||||||
|
#define inline
|
||||||
|
#endif /* !__GNUC__ */
|
||||||
|
|
||||||
|
/* Function for Feistel Networks */
|
||||||
|
|
||||||
|
#define F(s, x) ((((s)[ (((x)>>24)&0xFF)] \
|
||||||
|
+ (s)[0x100 + (((x)>>16)&0xFF)]) \
|
||||||
|
^ (s)[0x200 + (((x)>> 8)&0xFF)]) \
|
||||||
|
+ (s)[0x300 + ( (x) &0xFF)])
|
||||||
|
|
||||||
|
#define BLFRND(s,p,i,j,n) (i ^= F(s,j) ^ (p)[n])
|
||||||
|
|
||||||
|
void
|
||||||
|
Blowfish_encipher(blf_ctx *c, uint32_t *xl, uint32_t *xr)
|
||||||
|
{
|
||||||
|
uint32_t Xl;
|
||||||
|
uint32_t Xr;
|
||||||
|
uint32_t *s = c->S[0];
|
||||||
|
uint32_t *p = c->P;
|
||||||
|
|
||||||
|
Xl = *xl;
|
||||||
|
Xr = *xr;
|
||||||
|
|
||||||
|
Xl ^= p[0];
|
||||||
|
BLFRND(s, p, Xr, Xl, 1); BLFRND(s, p, Xl, Xr, 2);
|
||||||
|
BLFRND(s, p, Xr, Xl, 3); BLFRND(s, p, Xl, Xr, 4);
|
||||||
|
BLFRND(s, p, Xr, Xl, 5); BLFRND(s, p, Xl, Xr, 6);
|
||||||
|
BLFRND(s, p, Xr, Xl, 7); BLFRND(s, p, Xl, Xr, 8);
|
||||||
|
BLFRND(s, p, Xr, Xl, 9); BLFRND(s, p, Xl, Xr, 10);
|
||||||
|
BLFRND(s, p, Xr, Xl, 11); BLFRND(s, p, Xl, Xr, 12);
|
||||||
|
BLFRND(s, p, Xr, Xl, 13); BLFRND(s, p, Xl, Xr, 14);
|
||||||
|
BLFRND(s, p, Xr, Xl, 15); BLFRND(s, p, Xl, Xr, 16);
|
||||||
|
|
||||||
|
*xl = Xr ^ p[17];
|
||||||
|
*xr = Xl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Blowfish_decipher(blf_ctx *c, uint32_t *xl, uint32_t *xr)
|
||||||
|
{
|
||||||
|
uint32_t Xl;
|
||||||
|
uint32_t Xr;
|
||||||
|
uint32_t *s = c->S[0];
|
||||||
|
uint32_t *p = c->P;
|
||||||
|
|
||||||
|
Xl = *xl;
|
||||||
|
Xr = *xr;
|
||||||
|
|
||||||
|
Xl ^= p[17];
|
||||||
|
BLFRND(s, p, Xr, Xl, 16); BLFRND(s, p, Xl, Xr, 15);
|
||||||
|
BLFRND(s, p, Xr, Xl, 14); BLFRND(s, p, Xl, Xr, 13);
|
||||||
|
BLFRND(s, p, Xr, Xl, 12); BLFRND(s, p, Xl, Xr, 11);
|
||||||
|
BLFRND(s, p, Xr, Xl, 10); BLFRND(s, p, Xl, Xr, 9);
|
||||||
|
BLFRND(s, p, Xr, Xl, 8); BLFRND(s, p, Xl, Xr, 7);
|
||||||
|
BLFRND(s, p, Xr, Xl, 6); BLFRND(s, p, Xl, Xr, 5);
|
||||||
|
BLFRND(s, p, Xr, Xl, 4); BLFRND(s, p, Xl, Xr, 3);
|
||||||
|
BLFRND(s, p, Xr, Xl, 2); BLFRND(s, p, Xl, Xr, 1);
|
||||||
|
|
||||||
|
*xl = Xr ^ p[0];
|
||||||
|
*xr = Xl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Blowfish_initstate(blf_ctx *c)
|
||||||
|
{
|
||||||
|
/* P-box and S-box tables initialized with digits of Pi */
|
||||||
|
|
||||||
|
static const blf_ctx initstate =
|
||||||
|
{ {
|
||||||
|
{
|
||||||
|
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
|
||||||
|
0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
|
||||||
|
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
|
||||||
|
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
|
||||||
|
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
|
||||||
|
0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
|
||||||
|
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
|
||||||
|
0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
|
||||||
|
0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
|
||||||
|
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
|
||||||
|
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
|
||||||
|
0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
|
||||||
|
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
|
||||||
|
0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
|
||||||
|
0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
|
||||||
|
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
|
||||||
|
0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
|
||||||
|
0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
|
||||||
|
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
|
||||||
|
0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
|
||||||
|
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
|
||||||
|
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
|
||||||
|
0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
|
||||||
|
0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
|
||||||
|
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
|
||||||
|
0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
|
||||||
|
0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
|
||||||
|
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
|
||||||
|
0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
|
||||||
|
0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
|
||||||
|
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
|
||||||
|
0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
|
||||||
|
0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
|
||||||
|
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
|
||||||
|
0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
|
||||||
|
0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
|
||||||
|
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
|
||||||
|
0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
|
||||||
|
0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
|
||||||
|
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
|
||||||
|
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
|
||||||
|
0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
|
||||||
|
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
|
||||||
|
0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
|
||||||
|
0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
|
||||||
|
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
|
||||||
|
0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
|
||||||
|
0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
|
||||||
|
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
|
||||||
|
0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
|
||||||
|
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
|
||||||
|
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
|
||||||
|
0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
|
||||||
|
0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
|
||||||
|
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
|
||||||
|
0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
|
||||||
|
0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
|
||||||
|
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
|
||||||
|
0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
|
||||||
|
0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
|
||||||
|
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
|
||||||
|
0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
|
||||||
|
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
|
||||||
|
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a},
|
||||||
|
{
|
||||||
|
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
|
||||||
|
0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
|
||||||
|
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
|
||||||
|
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
|
||||||
|
0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
|
||||||
|
0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
|
||||||
|
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
|
||||||
|
0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
|
||||||
|
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
|
||||||
|
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
|
||||||
|
0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
|
||||||
|
0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
|
||||||
|
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
|
||||||
|
0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
|
||||||
|
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
|
||||||
|
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
|
||||||
|
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
|
||||||
|
0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
|
||||||
|
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
|
||||||
|
0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
|
||||||
|
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
|
||||||
|
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
|
||||||
|
0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
|
||||||
|
0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
|
||||||
|
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
|
||||||
|
0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
|
||||||
|
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
|
||||||
|
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
|
||||||
|
0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
|
||||||
|
0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
|
||||||
|
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
|
||||||
|
0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
|
||||||
|
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
|
||||||
|
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
|
||||||
|
0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
|
||||||
|
0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
|
||||||
|
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
|
||||||
|
0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
|
||||||
|
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
|
||||||
|
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
|
||||||
|
0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
|
||||||
|
0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
|
||||||
|
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
|
||||||
|
0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
|
||||||
|
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
|
||||||
|
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
|
||||||
|
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
|
||||||
|
0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
|
||||||
|
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
|
||||||
|
0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
|
||||||
|
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
|
||||||
|
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
|
||||||
|
0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
|
||||||
|
0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
|
||||||
|
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
|
||||||
|
0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
|
||||||
|
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
|
||||||
|
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
|
||||||
|
0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
|
||||||
|
0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
|
||||||
|
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
|
||||||
|
0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
|
||||||
|
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
|
||||||
|
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7},
|
||||||
|
{
|
||||||
|
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
|
||||||
|
0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
|
||||||
|
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
|
||||||
|
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
|
||||||
|
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
|
||||||
|
0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
|
||||||
|
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
|
||||||
|
0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
|
||||||
|
0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
|
||||||
|
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
|
||||||
|
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
|
||||||
|
0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
|
||||||
|
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
|
||||||
|
0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
|
||||||
|
0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
|
||||||
|
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
|
||||||
|
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
|
||||||
|
0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
|
||||||
|
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
|
||||||
|
0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
|
||||||
|
0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
|
||||||
|
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
|
||||||
|
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
|
||||||
|
0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
|
||||||
|
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
|
||||||
|
0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
|
||||||
|
0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
|
||||||
|
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
|
||||||
|
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
|
||||||
|
0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
|
||||||
|
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
|
||||||
|
0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
|
||||||
|
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
|
||||||
|
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
|
||||||
|
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
|
||||||
|
0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
|
||||||
|
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
|
||||||
|
0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
|
||||||
|
0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
|
||||||
|
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
|
||||||
|
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
|
||||||
|
0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
|
||||||
|
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
|
||||||
|
0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
|
||||||
|
0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
|
||||||
|
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
|
||||||
|
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
|
||||||
|
0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
|
||||||
|
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
|
||||||
|
0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
|
||||||
|
0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
|
||||||
|
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
|
||||||
|
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
|
||||||
|
0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
|
||||||
|
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
|
||||||
|
0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
|
||||||
|
0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
|
||||||
|
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
|
||||||
|
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
|
||||||
|
0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
|
||||||
|
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
|
||||||
|
0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
|
||||||
|
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
|
||||||
|
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0},
|
||||||
|
{
|
||||||
|
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
|
||||||
|
0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
|
||||||
|
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
|
||||||
|
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
|
||||||
|
0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
|
||||||
|
0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
|
||||||
|
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
|
||||||
|
0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
|
||||||
|
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
|
||||||
|
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
|
||||||
|
0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
|
||||||
|
0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
|
||||||
|
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
|
||||||
|
0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
|
||||||
|
0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
|
||||||
|
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
|
||||||
|
0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
|
||||||
|
0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
|
||||||
|
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
|
||||||
|
0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
|
||||||
|
0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
|
||||||
|
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
|
||||||
|
0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
|
||||||
|
0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
|
||||||
|
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
|
||||||
|
0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
|
||||||
|
0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
|
||||||
|
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
|
||||||
|
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
|
||||||
|
0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
|
||||||
|
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
|
||||||
|
0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
|
||||||
|
0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
|
||||||
|
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
|
||||||
|
0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
|
||||||
|
0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
|
||||||
|
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
|
||||||
|
0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
|
||||||
|
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
|
||||||
|
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
|
||||||
|
0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
|
||||||
|
0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
|
||||||
|
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
|
||||||
|
0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
|
||||||
|
0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
|
||||||
|
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
|
||||||
|
0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
|
||||||
|
0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
|
||||||
|
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
|
||||||
|
0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
|
||||||
|
0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
|
||||||
|
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
|
||||||
|
0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
|
||||||
|
0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
|
||||||
|
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
|
||||||
|
0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
|
||||||
|
0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
|
||||||
|
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
|
||||||
|
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
|
||||||
|
0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
|
||||||
|
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
|
||||||
|
0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
|
||||||
|
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
|
||||||
|
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
|
||||||
|
0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
|
||||||
|
0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
|
||||||
|
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
|
||||||
|
0x9216d5d9, 0x8979fb1b
|
||||||
|
} };
|
||||||
|
|
||||||
|
*c = initstate;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
Blowfish_stream2word(const uint8_t *data, uint16_t databytes,
|
||||||
|
uint16_t *current)
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
uint16_t j;
|
||||||
|
uint32_t temp;
|
||||||
|
|
||||||
|
temp = 0x00000000;
|
||||||
|
j = *current;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++, j++) {
|
||||||
|
if (j >= databytes)
|
||||||
|
j = 0;
|
||||||
|
temp = (temp << 8) | data[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
*current = j;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Blowfish_expand0state(blf_ctx *c, const uint8_t *key, uint16_t keybytes)
|
||||||
|
{
|
||||||
|
uint16_t i;
|
||||||
|
uint16_t j;
|
||||||
|
uint16_t k;
|
||||||
|
uint32_t temp;
|
||||||
|
uint32_t datal;
|
||||||
|
uint32_t datar;
|
||||||
|
|
||||||
|
j = 0;
|
||||||
|
for (i = 0; i < BLF_N + 2; i++) {
|
||||||
|
/* Extract 4 int8 to 1 int32 from keystream */
|
||||||
|
temp = Blowfish_stream2word(key, keybytes, &j);
|
||||||
|
c->P[i] = c->P[i] ^ temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
j = 0;
|
||||||
|
datal = 0x00000000;
|
||||||
|
datar = 0x00000000;
|
||||||
|
for (i = 0; i < BLF_N + 2; i += 2) {
|
||||||
|
Blowfish_encipher(c, &datal, &datar);
|
||||||
|
|
||||||
|
c->P[i] = datal;
|
||||||
|
c->P[i + 1] = datar;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
for (k = 0; k < 256; k += 2) {
|
||||||
|
Blowfish_encipher(c, &datal, &datar);
|
||||||
|
|
||||||
|
c->S[i][k] = datal;
|
||||||
|
c->S[i][k + 1] = datar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Blowfish_expandstate(blf_ctx *c, const uint8_t *data, uint16_t databytes,
|
||||||
|
const uint8_t *key, uint16_t keybytes)
|
||||||
|
{
|
||||||
|
uint16_t i;
|
||||||
|
uint16_t j;
|
||||||
|
uint16_t k;
|
||||||
|
uint32_t temp;
|
||||||
|
uint32_t datal;
|
||||||
|
uint32_t datar;
|
||||||
|
|
||||||
|
j = 0;
|
||||||
|
for (i = 0; i < BLF_N + 2; i++) {
|
||||||
|
/* Extract 4 int8 to 1 int32 from keystream */
|
||||||
|
temp = Blowfish_stream2word(key, keybytes, &j);
|
||||||
|
c->P[i] = c->P[i] ^ temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
j = 0;
|
||||||
|
datal = 0x00000000;
|
||||||
|
datar = 0x00000000;
|
||||||
|
for (i = 0; i < BLF_N + 2; i += 2) {
|
||||||
|
datal ^= Blowfish_stream2word(data, databytes, &j);
|
||||||
|
datar ^= Blowfish_stream2word(data, databytes, &j);
|
||||||
|
Blowfish_encipher(c, &datal, &datar);
|
||||||
|
|
||||||
|
c->P[i] = datal;
|
||||||
|
c->P[i + 1] = datar;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
for (k = 0; k < 256; k += 2) {
|
||||||
|
datal ^= Blowfish_stream2word(data, databytes, &j);
|
||||||
|
datar ^= Blowfish_stream2word(data, databytes, &j);
|
||||||
|
Blowfish_encipher(c, &datal, &datar);
|
||||||
|
|
||||||
|
c->S[i][k] = datal;
|
||||||
|
c->S[i][k + 1] = datar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
blf_key(blf_ctx *c, const uint8_t *k, uint16_t len)
|
||||||
|
{
|
||||||
|
/* Initialize S-boxes and subkeys with Pi */
|
||||||
|
Blowfish_initstate(c);
|
||||||
|
|
||||||
|
/* Transform S-boxes and subkeys with key */
|
||||||
|
Blowfish_expand0state(c, k, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
blf_enc(blf_ctx *c, uint32_t *data, uint16_t blocks)
|
||||||
|
{
|
||||||
|
uint32_t *d;
|
||||||
|
uint16_t i;
|
||||||
|
|
||||||
|
d = data;
|
||||||
|
for (i = 0; i < blocks; i++) {
|
||||||
|
Blowfish_encipher(c, d, d + 1);
|
||||||
|
d += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
blf_dec(blf_ctx *c, uint32_t *data, uint16_t blocks)
|
||||||
|
{
|
||||||
|
uint32_t *d;
|
||||||
|
uint16_t i;
|
||||||
|
|
||||||
|
d = data;
|
||||||
|
for (i = 0; i < blocks; i++) {
|
||||||
|
Blowfish_decipher(c, d, d + 1);
|
||||||
|
d += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
blf_ecb_encrypt(blf_ctx *c, uint8_t *data, uint32_t len)
|
||||||
|
{
|
||||||
|
uint32_t l, r;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i += 8) {
|
||||||
|
l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
|
||||||
|
r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
|
||||||
|
Blowfish_encipher(c, &l, &r);
|
||||||
|
data[0] = l >> 24 & 0xff;
|
||||||
|
data[1] = l >> 16 & 0xff;
|
||||||
|
data[2] = l >> 8 & 0xff;
|
||||||
|
data[3] = l & 0xff;
|
||||||
|
data[4] = r >> 24 & 0xff;
|
||||||
|
data[5] = r >> 16 & 0xff;
|
||||||
|
data[6] = r >> 8 & 0xff;
|
||||||
|
data[7] = r & 0xff;
|
||||||
|
data += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
blf_ecb_decrypt(blf_ctx *c, uint8_t *data, uint32_t len)
|
||||||
|
{
|
||||||
|
uint32_t l, r;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i += 8) {
|
||||||
|
l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
|
||||||
|
r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
|
||||||
|
Blowfish_decipher(c, &l, &r);
|
||||||
|
data[0] = l >> 24 & 0xff;
|
||||||
|
data[1] = l >> 16 & 0xff;
|
||||||
|
data[2] = l >> 8 & 0xff;
|
||||||
|
data[3] = l & 0xff;
|
||||||
|
data[4] = r >> 24 & 0xff;
|
||||||
|
data[5] = r >> 16 & 0xff;
|
||||||
|
data[6] = r >> 8 & 0xff;
|
||||||
|
data[7] = r & 0xff;
|
||||||
|
data += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
blf_cbc_encrypt(blf_ctx *c, uint8_t *iv, uint8_t *data, uint32_t len)
|
||||||
|
{
|
||||||
|
uint32_t l, r;
|
||||||
|
uint32_t i, j;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i += 8) {
|
||||||
|
for (j = 0; j < 8; j++)
|
||||||
|
data[j] ^= iv[j];
|
||||||
|
l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
|
||||||
|
r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
|
||||||
|
Blowfish_encipher(c, &l, &r);
|
||||||
|
data[0] = l >> 24 & 0xff;
|
||||||
|
data[1] = l >> 16 & 0xff;
|
||||||
|
data[2] = l >> 8 & 0xff;
|
||||||
|
data[3] = l & 0xff;
|
||||||
|
data[4] = r >> 24 & 0xff;
|
||||||
|
data[5] = r >> 16 & 0xff;
|
||||||
|
data[6] = r >> 8 & 0xff;
|
||||||
|
data[7] = r & 0xff;
|
||||||
|
iv = data;
|
||||||
|
data += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
blf_cbc_decrypt(blf_ctx *c, uint8_t *iva, uint8_t *data, uint32_t len)
|
||||||
|
{
|
||||||
|
uint32_t l, r;
|
||||||
|
uint8_t *iv;
|
||||||
|
uint32_t i, j;
|
||||||
|
|
||||||
|
iv = data + len - 16;
|
||||||
|
data = data + len - 8;
|
||||||
|
for (i = len - 8; i >= 8; i -= 8) {
|
||||||
|
l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
|
||||||
|
r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
|
||||||
|
Blowfish_decipher(c, &l, &r);
|
||||||
|
data[0] = l >> 24 & 0xff;
|
||||||
|
data[1] = l >> 16 & 0xff;
|
||||||
|
data[2] = l >> 8 & 0xff;
|
||||||
|
data[3] = l & 0xff;
|
||||||
|
data[4] = r >> 24 & 0xff;
|
||||||
|
data[5] = r >> 16 & 0xff;
|
||||||
|
data[6] = r >> 8 & 0xff;
|
||||||
|
data[7] = r & 0xff;
|
||||||
|
for (j = 0; j < 8; j++)
|
||||||
|
data[j] ^= iv[j];
|
||||||
|
iv -= 8;
|
||||||
|
data -= 8;
|
||||||
|
}
|
||||||
|
l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
|
||||||
|
r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
|
||||||
|
Blowfish_decipher(c, &l, &r);
|
||||||
|
data[0] = l >> 24 & 0xff;
|
||||||
|
data[1] = l >> 16 & 0xff;
|
||||||
|
data[2] = l >> 8 & 0xff;
|
||||||
|
data[3] = l & 0xff;
|
||||||
|
data[4] = r >> 24 & 0xff;
|
||||||
|
data[5] = r >> 16 & 0xff;
|
||||||
|
data[6] = r >> 8 & 0xff;
|
||||||
|
data[7] = r & 0xff;
|
||||||
|
for (j = 0; j < 8; j++)
|
||||||
|
data[j] ^= iva[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
void
|
||||||
|
report(uint32_t data[], uint16_t len)
|
||||||
|
{
|
||||||
|
uint16_t i;
|
||||||
|
for (i = 0; i < len; i += 2)
|
||||||
|
printf("Block %0hd: %08lx %08lx.\n",
|
||||||
|
i / 2, data[i], data[i + 1]);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
blf_ctx c;
|
||||||
|
char key[] = "AAAAA";
|
||||||
|
char key2[] = "abcdefghijklmnopqrstuvwxyz";
|
||||||
|
|
||||||
|
uint32_t data[10];
|
||||||
|
uint32_t data2[] =
|
||||||
|
{0x424c4f57l, 0x46495348l};
|
||||||
|
|
||||||
|
uint16_t i;
|
||||||
|
|
||||||
|
/* First test */
|
||||||
|
for (i = 0; i < 10; i++)
|
||||||
|
data[i] = i;
|
||||||
|
|
||||||
|
blf_key(&c, (uint8_t *) key, 5);
|
||||||
|
blf_enc(&c, data, 5);
|
||||||
|
blf_dec(&c, data, 1);
|
||||||
|
blf_dec(&c, data + 2, 4);
|
||||||
|
printf("Should read as 0 - 9.\n");
|
||||||
|
report(data, 10);
|
||||||
|
|
||||||
|
/* Second test */
|
||||||
|
blf_key(&c, (uint8_t *) key2, strlen(key2));
|
||||||
|
blf_enc(&c, data2, 1);
|
||||||
|
printf("\nShould read as: 0x324ed0fe 0xf413a203.\n");
|
||||||
|
report(data2, 2);
|
||||||
|
blf_dec(&c, data2, 1);
|
||||||
|
report(data2, 2);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* !defined(HAVE_BCRYPT_PBKDF) && (!defined(HAVE_BLOWFISH_INITSTATE) || \
|
||||||
|
!defined(HAVE_BLOWFISH_EXPAND0STATE) || !defined(HAVE_BLF_ENC)) */
|
||||||
271
src/external/curve25519_ref.c
vendored
Normal file
271
src/external/curve25519_ref.c
vendored
Normal file
@@ -0,0 +1,271 @@
|
|||||||
|
/*
|
||||||
|
version 20081011
|
||||||
|
Matthew Dempsky
|
||||||
|
Public domain.
|
||||||
|
Derived from public domain code by D. J. Bernstein.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libssh/curve25519.h"
|
||||||
|
static const unsigned char base[32] = {9};
|
||||||
|
|
||||||
|
int crypto_scalarmult_base(unsigned char *q,
|
||||||
|
const unsigned char *n)
|
||||||
|
{
|
||||||
|
return crypto_scalarmult(q,n,base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add(unsigned int out[32],const unsigned int a[32],const unsigned int b[32])
|
||||||
|
{
|
||||||
|
unsigned int j;
|
||||||
|
unsigned int u;
|
||||||
|
u = 0;
|
||||||
|
for (j = 0;j < 31;++j) { u += a[j] + b[j]; out[j] = u & 255; u >>= 8; }
|
||||||
|
u += a[31] + b[31]; out[31] = u;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sub(unsigned int out[32],const unsigned int a[32],const unsigned int b[32])
|
||||||
|
{
|
||||||
|
unsigned int j;
|
||||||
|
unsigned int u;
|
||||||
|
u = 218;
|
||||||
|
for (j = 0;j < 31;++j) {
|
||||||
|
u += a[j] + 65280 - b[j];
|
||||||
|
out[j] = u & 255;
|
||||||
|
u >>= 8;
|
||||||
|
}
|
||||||
|
u += a[31] - b[31];
|
||||||
|
out[31] = u;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void squeeze(unsigned int a[32])
|
||||||
|
{
|
||||||
|
unsigned int j;
|
||||||
|
unsigned int u;
|
||||||
|
u = 0;
|
||||||
|
for (j = 0;j < 31;++j) { u += a[j]; a[j] = u & 255; u >>= 8; }
|
||||||
|
u += a[31]; a[31] = u & 127;
|
||||||
|
u = 19 * (u >> 7);
|
||||||
|
for (j = 0;j < 31;++j) { u += a[j]; a[j] = u & 255; u >>= 8; }
|
||||||
|
u += a[31]; a[31] = u;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const unsigned int minusp[32] = {
|
||||||
|
19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128
|
||||||
|
} ;
|
||||||
|
|
||||||
|
static void freeze(unsigned int a[32])
|
||||||
|
{
|
||||||
|
unsigned int aorig[32];
|
||||||
|
unsigned int j;
|
||||||
|
unsigned int negative;
|
||||||
|
|
||||||
|
for (j = 0;j < 32;++j) aorig[j] = a[j];
|
||||||
|
add(a,a,minusp);
|
||||||
|
negative = -((a[31] >> 7) & 1);
|
||||||
|
for (j = 0;j < 32;++j) a[j] ^= negative & (aorig[j] ^ a[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mult(unsigned int out[32],const unsigned int a[32],const unsigned int b[32])
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
unsigned int j;
|
||||||
|
unsigned int u;
|
||||||
|
|
||||||
|
for (i = 0;i < 32;++i) {
|
||||||
|
u = 0;
|
||||||
|
for (j = 0;j <= i;++j) u += a[j] * b[i - j];
|
||||||
|
for (j = i + 1;j < 32;++j) u += 38 * a[j] * b[i + 32 - j];
|
||||||
|
out[i] = u;
|
||||||
|
}
|
||||||
|
squeeze(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mult121665(unsigned int out[32],const unsigned int a[32])
|
||||||
|
{
|
||||||
|
unsigned int j;
|
||||||
|
unsigned int u;
|
||||||
|
|
||||||
|
u = 0;
|
||||||
|
for (j = 0;j < 31;++j) { u += 121665 * a[j]; out[j] = u & 255; u >>= 8; }
|
||||||
|
u += 121665 * a[31]; out[31] = u & 127;
|
||||||
|
u = 19 * (u >> 7);
|
||||||
|
for (j = 0;j < 31;++j) { u += out[j]; out[j] = u & 255; u >>= 8; }
|
||||||
|
u += out[j]; out[j] = u;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void square(unsigned int out[32],const unsigned int a[32])
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
unsigned int j;
|
||||||
|
unsigned int u;
|
||||||
|
|
||||||
|
for (i = 0;i < 32;++i) {
|
||||||
|
u = 0;
|
||||||
|
for (j = 0;j < i - j;++j) u += a[j] * a[i - j];
|
||||||
|
for (j = i + 1;j < i + 32 - j;++j) u += 38 * a[j] * a[i + 32 - j];
|
||||||
|
u *= 2;
|
||||||
|
if ((i & 1) == 0) {
|
||||||
|
u += a[i / 2] * a[i / 2];
|
||||||
|
u += 38 * a[i / 2 + 16] * a[i / 2 + 16];
|
||||||
|
}
|
||||||
|
out[i] = u;
|
||||||
|
}
|
||||||
|
squeeze(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void c_select(unsigned int p[64],unsigned int q[64],const unsigned int r[64],const unsigned int s[64],unsigned int b)
|
||||||
|
{
|
||||||
|
unsigned int j;
|
||||||
|
unsigned int t;
|
||||||
|
unsigned int bminus1;
|
||||||
|
|
||||||
|
bminus1 = b - 1;
|
||||||
|
for (j = 0;j < 64;++j) {
|
||||||
|
t = bminus1 & (r[j] ^ s[j]);
|
||||||
|
p[j] = s[j] ^ t;
|
||||||
|
q[j] = r[j] ^ t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mainloop(unsigned int work[64],const unsigned char e[32])
|
||||||
|
{
|
||||||
|
unsigned int xzm1[64];
|
||||||
|
unsigned int xzm[64];
|
||||||
|
unsigned int xzmb[64];
|
||||||
|
unsigned int xzm1b[64];
|
||||||
|
unsigned int xznb[64];
|
||||||
|
unsigned int xzn1b[64];
|
||||||
|
unsigned int a0[64];
|
||||||
|
unsigned int a1[64];
|
||||||
|
unsigned int b0[64];
|
||||||
|
unsigned int b1[64];
|
||||||
|
unsigned int c1[64];
|
||||||
|
unsigned int r[32];
|
||||||
|
unsigned int s[32];
|
||||||
|
unsigned int t[32];
|
||||||
|
unsigned int u[32];
|
||||||
|
unsigned int j;
|
||||||
|
unsigned int b;
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
for (j = 0;j < 32;++j) xzm1[j] = work[j];
|
||||||
|
xzm1[32] = 1;
|
||||||
|
for (j = 33;j < 64;++j) xzm1[j] = 0;
|
||||||
|
|
||||||
|
xzm[0] = 1;
|
||||||
|
for (j = 1;j < 64;++j) xzm[j] = 0;
|
||||||
|
|
||||||
|
for (pos = 254;pos >= 0;--pos) {
|
||||||
|
b = e[pos / 8] >> (pos & 7);
|
||||||
|
b &= 1;
|
||||||
|
c_select(xzmb,xzm1b,xzm,xzm1,b);
|
||||||
|
add(a0,xzmb,xzmb + 32);
|
||||||
|
sub(a0 + 32,xzmb,xzmb + 32);
|
||||||
|
add(a1,xzm1b,xzm1b + 32);
|
||||||
|
sub(a1 + 32,xzm1b,xzm1b + 32);
|
||||||
|
square(b0,a0);
|
||||||
|
square(b0 + 32,a0 + 32);
|
||||||
|
mult(b1,a1,a0 + 32);
|
||||||
|
mult(b1 + 32,a1 + 32,a0);
|
||||||
|
add(c1,b1,b1 + 32);
|
||||||
|
sub(c1 + 32,b1,b1 + 32);
|
||||||
|
square(r,c1 + 32);
|
||||||
|
sub(s,b0,b0 + 32);
|
||||||
|
mult121665(t,s);
|
||||||
|
add(u,t,b0);
|
||||||
|
mult(xznb,b0,b0 + 32);
|
||||||
|
mult(xznb + 32,s,u);
|
||||||
|
square(xzn1b,c1);
|
||||||
|
mult(xzn1b + 32,r,work);
|
||||||
|
c_select(xzm,xzm1,xznb,xzn1b,b);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0;j < 64;++j) work[j] = xzm[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void recip(unsigned int out[32],const unsigned int z[32])
|
||||||
|
{
|
||||||
|
unsigned int z2[32];
|
||||||
|
unsigned int z9[32];
|
||||||
|
unsigned int z11[32];
|
||||||
|
unsigned int z2_5_0[32];
|
||||||
|
unsigned int z2_10_0[32];
|
||||||
|
unsigned int z2_20_0[32];
|
||||||
|
unsigned int z2_50_0[32];
|
||||||
|
unsigned int z2_100_0[32];
|
||||||
|
unsigned int t0[32];
|
||||||
|
unsigned int t1[32];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* 2 */ square(z2,z);
|
||||||
|
/* 4 */ square(t1,z2);
|
||||||
|
/* 8 */ square(t0,t1);
|
||||||
|
/* 9 */ mult(z9,t0,z);
|
||||||
|
/* 11 */ mult(z11,z9,z2);
|
||||||
|
/* 22 */ square(t0,z11);
|
||||||
|
/* 2^5 - 2^0 = 31 */ mult(z2_5_0,t0,z9);
|
||||||
|
|
||||||
|
/* 2^6 - 2^1 */ square(t0,z2_5_0);
|
||||||
|
/* 2^7 - 2^2 */ square(t1,t0);
|
||||||
|
/* 2^8 - 2^3 */ square(t0,t1);
|
||||||
|
/* 2^9 - 2^4 */ square(t1,t0);
|
||||||
|
/* 2^10 - 2^5 */ square(t0,t1);
|
||||||
|
/* 2^10 - 2^0 */ mult(z2_10_0,t0,z2_5_0);
|
||||||
|
|
||||||
|
/* 2^11 - 2^1 */ square(t0,z2_10_0);
|
||||||
|
/* 2^12 - 2^2 */ square(t1,t0);
|
||||||
|
/* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { square(t0,t1); square(t1,t0); }
|
||||||
|
/* 2^20 - 2^0 */ mult(z2_20_0,t1,z2_10_0);
|
||||||
|
|
||||||
|
/* 2^21 - 2^1 */ square(t0,z2_20_0);
|
||||||
|
/* 2^22 - 2^2 */ square(t1,t0);
|
||||||
|
/* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { square(t0,t1); square(t1,t0); }
|
||||||
|
/* 2^40 - 2^0 */ mult(t0,t1,z2_20_0);
|
||||||
|
|
||||||
|
/* 2^41 - 2^1 */ square(t1,t0);
|
||||||
|
/* 2^42 - 2^2 */ square(t0,t1);
|
||||||
|
/* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { square(t1,t0); square(t0,t1); }
|
||||||
|
/* 2^50 - 2^0 */ mult(z2_50_0,t0,z2_10_0);
|
||||||
|
|
||||||
|
/* 2^51 - 2^1 */ square(t0,z2_50_0);
|
||||||
|
/* 2^52 - 2^2 */ square(t1,t0);
|
||||||
|
/* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { square(t0,t1); square(t1,t0); }
|
||||||
|
/* 2^100 - 2^0 */ mult(z2_100_0,t1,z2_50_0);
|
||||||
|
|
||||||
|
/* 2^101 - 2^1 */ square(t1,z2_100_0);
|
||||||
|
/* 2^102 - 2^2 */ square(t0,t1);
|
||||||
|
/* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { square(t1,t0); square(t0,t1); }
|
||||||
|
/* 2^200 - 2^0 */ mult(t1,t0,z2_100_0);
|
||||||
|
|
||||||
|
/* 2^201 - 2^1 */ square(t0,t1);
|
||||||
|
/* 2^202 - 2^2 */ square(t1,t0);
|
||||||
|
/* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { square(t0,t1); square(t1,t0); }
|
||||||
|
/* 2^250 - 2^0 */ mult(t0,t1,z2_50_0);
|
||||||
|
|
||||||
|
/* 2^251 - 2^1 */ square(t1,t0);
|
||||||
|
/* 2^252 - 2^2 */ square(t0,t1);
|
||||||
|
/* 2^253 - 2^3 */ square(t1,t0);
|
||||||
|
/* 2^254 - 2^4 */ square(t0,t1);
|
||||||
|
/* 2^255 - 2^5 */ square(t1,t0);
|
||||||
|
/* 2^255 - 21 */ mult(out,t1,z11);
|
||||||
|
}
|
||||||
|
|
||||||
|
int crypto_scalarmult(unsigned char *q,
|
||||||
|
const unsigned char *n,
|
||||||
|
const unsigned char *p)
|
||||||
|
{
|
||||||
|
unsigned int work[96];
|
||||||
|
unsigned char e[32];
|
||||||
|
unsigned int i;
|
||||||
|
for (i = 0;i < 32;++i) e[i] = n[i];
|
||||||
|
e[0] &= 248;
|
||||||
|
e[31] &= 127;
|
||||||
|
e[31] |= 64;
|
||||||
|
for (i = 0;i < 32;++i) work[i] = p[i];
|
||||||
|
mainloop(work,e);
|
||||||
|
recip(work + 32,work + 32);
|
||||||
|
mult(work + 64,work,work + 32);
|
||||||
|
freeze(work + 64);
|
||||||
|
for (i = 0;i < 32;++i) q[i] = work[64 + i];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
222
src/external/ed25519.c
vendored
Normal file
222
src/external/ed25519.c
vendored
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
/* $OpenBSD: ed25519.c,v 1.3 2013/12/09 11:03:45 markus Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange,
|
||||||
|
* Peter Schwabe, Bo-Yin Yang.
|
||||||
|
* Copied from supercop-20130419/crypto_sign/ed25519/ref/ed25519.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "libssh/libcrypto.h"
|
||||||
|
#include "libssh/wrapper.h"
|
||||||
|
#include "libssh/ge25519.h"
|
||||||
|
#include "libssh/sc25519.h"
|
||||||
|
#include "libssh/ed25519.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Public Domain, Author: Daniel J. Bernstein
|
||||||
|
* Copied from nacl-20110221/crypto_verify/32/ref/verify.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int crypto_verify_32(const unsigned char *x,const unsigned char *y)
|
||||||
|
{
|
||||||
|
unsigned int differentbits = 0;
|
||||||
|
#define F(i) differentbits |= x[i] ^ y[i];
|
||||||
|
F(0)
|
||||||
|
F(1)
|
||||||
|
F(2)
|
||||||
|
F(3)
|
||||||
|
F(4)
|
||||||
|
F(5)
|
||||||
|
F(6)
|
||||||
|
F(7)
|
||||||
|
F(8)
|
||||||
|
F(9)
|
||||||
|
F(10)
|
||||||
|
F(11)
|
||||||
|
F(12)
|
||||||
|
F(13)
|
||||||
|
F(14)
|
||||||
|
F(15)
|
||||||
|
F(16)
|
||||||
|
F(17)
|
||||||
|
F(18)
|
||||||
|
F(19)
|
||||||
|
F(20)
|
||||||
|
F(21)
|
||||||
|
F(22)
|
||||||
|
F(23)
|
||||||
|
F(24)
|
||||||
|
F(25)
|
||||||
|
F(26)
|
||||||
|
F(27)
|
||||||
|
F(28)
|
||||||
|
F(29)
|
||||||
|
F(30)
|
||||||
|
F(31)
|
||||||
|
|
||||||
|
return (1 & ((differentbits - 1) >> 8)) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_hram(unsigned char *hram,
|
||||||
|
const unsigned char *sm,
|
||||||
|
const unsigned char *pk,
|
||||||
|
unsigned char *playground,
|
||||||
|
unsigned long long smlen)
|
||||||
|
{
|
||||||
|
unsigned long long i;
|
||||||
|
SHA512CTX ctx;
|
||||||
|
for (i = 0;i < 32;++i) playground[i] = sm[i];
|
||||||
|
for (i = 32;i < 64;++i) playground[i] = pk[i-32];
|
||||||
|
for (i = 64;i < smlen;++i) playground[i] = sm[i];
|
||||||
|
|
||||||
|
ctx = sha512_init();
|
||||||
|
sha512_update(ctx, playground, smlen);
|
||||||
|
sha512_final(hram, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int crypto_sign_ed25519_keypair(unsigned char *pk,
|
||||||
|
unsigned char *sk)
|
||||||
|
{
|
||||||
|
sc25519 scsk;
|
||||||
|
ge25519 gepk;
|
||||||
|
SHA512CTX ctx;
|
||||||
|
unsigned char extsk[64];
|
||||||
|
int i;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = ssh_get_random(sk, 32, 0);
|
||||||
|
if (rc < 0){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = sha512_init();
|
||||||
|
sha512_update(ctx, sk, 32);
|
||||||
|
sha512_final(extsk, ctx);
|
||||||
|
extsk[0] &= 248;
|
||||||
|
extsk[31] &= 127;
|
||||||
|
extsk[31] |= 64;
|
||||||
|
|
||||||
|
sc25519_from32bytes(&scsk,extsk);
|
||||||
|
|
||||||
|
ge25519_scalarmult_base(&gepk, &scsk);
|
||||||
|
ge25519_pack(pk, &gepk);
|
||||||
|
for(i=0;i<32;i++) {
|
||||||
|
sk[32 + i] = pk[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int crypto_sign_ed25519(unsigned char *sm,
|
||||||
|
unsigned long long *smlen,
|
||||||
|
const unsigned char *m,
|
||||||
|
unsigned long long mlen,
|
||||||
|
const unsigned char *sk)
|
||||||
|
{
|
||||||
|
sc25519 sck, scs, scsk;
|
||||||
|
ge25519 ger;
|
||||||
|
SHA512CTX ctx;
|
||||||
|
unsigned char r[32];
|
||||||
|
unsigned char s[32];
|
||||||
|
unsigned char extsk[64];
|
||||||
|
unsigned long long i;
|
||||||
|
unsigned char hmg[SHA512_DIGEST_LEN];
|
||||||
|
unsigned char hram[SHA512_DIGEST_LEN];
|
||||||
|
|
||||||
|
ctx = sha512_init();
|
||||||
|
sha512_update(ctx, sk, 32);
|
||||||
|
sha512_final(extsk, ctx);
|
||||||
|
|
||||||
|
extsk[0] &= 248;
|
||||||
|
extsk[31] &= 127;
|
||||||
|
extsk[31] |= 64;
|
||||||
|
|
||||||
|
*smlen = mlen + 64;
|
||||||
|
for (i = 0;i < mlen; i++) {
|
||||||
|
sm[64 + i] = m[i];
|
||||||
|
}
|
||||||
|
for (i = 0;i < 32; i++) {
|
||||||
|
sm[32 + i] = extsk[32+i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate k as h(extsk[32],...,extsk[63],m) */
|
||||||
|
ctx = sha512_init();
|
||||||
|
sha512_update(ctx, sm + 32, mlen + 32);
|
||||||
|
sha512_final(hmg, ctx);
|
||||||
|
|
||||||
|
/* Computation of R */
|
||||||
|
sc25519_from64bytes(&sck, hmg);
|
||||||
|
ge25519_scalarmult_base(&ger, &sck);
|
||||||
|
ge25519_pack(r, &ger);
|
||||||
|
|
||||||
|
/* Computation of s */
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
sm[i] = r[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
get_hram(hram, sm, sk+32, sm, mlen+64);
|
||||||
|
|
||||||
|
sc25519_from64bytes(&scs, hram);
|
||||||
|
sc25519_from32bytes(&scsk, extsk);
|
||||||
|
sc25519_mul(&scs, &scs, &scsk);
|
||||||
|
|
||||||
|
sc25519_add(&scs, &scs, &sck);
|
||||||
|
|
||||||
|
sc25519_to32bytes(s,&scs); /* cat s */
|
||||||
|
for (i = 0;i < 32; i++) {
|
||||||
|
sm[32 + i] = s[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int crypto_sign_ed25519_open(unsigned char *m,
|
||||||
|
unsigned long long *mlen,
|
||||||
|
const unsigned char *sm,
|
||||||
|
unsigned long long smlen,
|
||||||
|
const unsigned char *pk)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
int ret;
|
||||||
|
unsigned char t2[32];
|
||||||
|
ge25519 get1, get2;
|
||||||
|
sc25519 schram, scs;
|
||||||
|
unsigned char hram[SHA512_DIGEST_LEN];
|
||||||
|
|
||||||
|
*mlen = (unsigned long long) -1;
|
||||||
|
if (smlen < 64) return -1;
|
||||||
|
|
||||||
|
if (ge25519_unpackneg_vartime(&get1, pk)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
get_hram(hram,sm,pk,m,smlen);
|
||||||
|
|
||||||
|
sc25519_from64bytes(&schram, hram);
|
||||||
|
|
||||||
|
sc25519_from32bytes(&scs, sm+32);
|
||||||
|
|
||||||
|
ge25519_double_scalarmult_vartime(&get2,
|
||||||
|
&get1,
|
||||||
|
&schram,
|
||||||
|
&ge25519_base,
|
||||||
|
&scs);
|
||||||
|
ge25519_pack(t2, &get2);
|
||||||
|
|
||||||
|
ret = crypto_verify_32(sm, t2);
|
||||||
|
if (ret != 0) {
|
||||||
|
for (i = 0; i < smlen - 64; i++) {
|
||||||
|
m[i] = sm[i + 64];
|
||||||
|
}
|
||||||
|
*mlen = smlen-64;
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < smlen - 64; i++) {
|
||||||
|
m[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
416
src/external/fe25519.c
vendored
Normal file
416
src/external/fe25519.c
vendored
Normal file
@@ -0,0 +1,416 @@
|
|||||||
|
/*
|
||||||
|
* Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange,
|
||||||
|
* Peter Schwabe, Bo-Yin Yang.
|
||||||
|
* Copied from supercop-20130419/crypto_sign/ed25519/ref/fe25519.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WINDOWSIZE 1 /* Should be 1,2, or 4 */
|
||||||
|
#define WINDOWMASK ((1<<WINDOWSIZE)-1)
|
||||||
|
|
||||||
|
#include "libssh/fe25519.h"
|
||||||
|
|
||||||
|
static uint32_t equal(uint32_t a,uint32_t b) /* 16-bit inputs */
|
||||||
|
{
|
||||||
|
uint32_t x = a ^ b; /* 0: yes; 1..65535: no */
|
||||||
|
x -= 1; /* 4294967295: yes; 0..65534: no */
|
||||||
|
x >>= 31; /* 1: yes; 0: no */
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t ge(uint32_t a,uint32_t b) /* 16-bit inputs */
|
||||||
|
{
|
||||||
|
unsigned int x = a;
|
||||||
|
|
||||||
|
x -= (unsigned int) b; /* 0..65535: yes; 4294901761..4294967295: no */
|
||||||
|
x >>= 31; /* 0: yes; 1: no */
|
||||||
|
x ^= 1; /* 1: yes; 0: no */
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t times19(uint32_t a)
|
||||||
|
{
|
||||||
|
return (a << 4) + (a << 1) + a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t times38(uint32_t a)
|
||||||
|
{
|
||||||
|
return (a << 5) + (a << 2) + (a << 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reduce_add_sub(fe25519 *r)
|
||||||
|
{
|
||||||
|
uint32_t t;
|
||||||
|
int i,rep;
|
||||||
|
|
||||||
|
for(rep = 0; rep < 4; rep++) {
|
||||||
|
t = r->v[31] >> 7;
|
||||||
|
r->v[31] &= 127;
|
||||||
|
t = times19(t);
|
||||||
|
r->v[0] += t;
|
||||||
|
for(i = 0; i < 31; i++) {
|
||||||
|
t = r->v[i] >> 8;
|
||||||
|
r->v[i+1] += t;
|
||||||
|
r->v[i] &= 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reduce_mul(fe25519 *r)
|
||||||
|
{
|
||||||
|
uint32_t t;
|
||||||
|
int i,rep;
|
||||||
|
|
||||||
|
for(rep = 0; rep < 2; rep++) {
|
||||||
|
t = r->v[31] >> 7;
|
||||||
|
r->v[31] &= 127;
|
||||||
|
t = times19(t);
|
||||||
|
r->v[0] += t;
|
||||||
|
for(i = 0; i < 31; i++) {
|
||||||
|
t = r->v[i] >> 8;
|
||||||
|
r->v[i+1] += t;
|
||||||
|
r->v[i] &= 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reduction modulo 2^255-19 */
|
||||||
|
void fe25519_freeze(fe25519 *r)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint32_t m = equal(r->v[31],127);
|
||||||
|
|
||||||
|
for (i = 30; i > 0; i--) {
|
||||||
|
m &= equal(r->v[i],255);
|
||||||
|
}
|
||||||
|
m &= ge(r->v[0],237);
|
||||||
|
|
||||||
|
m = -m;
|
||||||
|
|
||||||
|
r->v[31] -= m&127;
|
||||||
|
for (i = 30; i > 0; i--) {
|
||||||
|
r->v[i] -= m&255;
|
||||||
|
}
|
||||||
|
r->v[0] -= m&237;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fe25519_unpack(fe25519 *r, const unsigned char x[32])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0;i < 32; i++) {
|
||||||
|
r->v[i] = x[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
r->v[31] &= 127;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assumes input x being reduced below 2^255 */
|
||||||
|
void fe25519_pack(unsigned char r[32], const fe25519 *x)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
fe25519 y = *x;
|
||||||
|
fe25519_freeze(&y);
|
||||||
|
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
r[i] = y.v[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int fe25519_iszero(const fe25519 *x)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
fe25519 t = *x;
|
||||||
|
fe25519_freeze(&t);
|
||||||
|
|
||||||
|
r = equal(t.v[0],0);
|
||||||
|
for (i = 1; i < 32; i++) {
|
||||||
|
r &= equal(t.v[i],0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
fe25519 t1 = *x;
|
||||||
|
fe25519 t2 = *y;
|
||||||
|
fe25519_freeze(&t1);
|
||||||
|
fe25519_freeze(&t2);
|
||||||
|
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
if(t1.v[i] != t2.v[i]) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint32_t mask = b;
|
||||||
|
|
||||||
|
mask = -mask;
|
||||||
|
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
r->v[i] ^= mask & (x->v[i] ^ r->v[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char fe25519_getparity(const fe25519 *x)
|
||||||
|
{
|
||||||
|
fe25519 t = *x;
|
||||||
|
fe25519_freeze(&t);
|
||||||
|
|
||||||
|
return t.v[0] & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fe25519_setone(fe25519 *r)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
r->v[0] = 1;
|
||||||
|
for (i = 1; i < 32; i++) {
|
||||||
|
r->v[i]=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fe25519_setzero(fe25519 *r)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
r->v[i]=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fe25519_neg(fe25519 *r, const fe25519 *x)
|
||||||
|
{
|
||||||
|
fe25519 t;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
t.v[i]=x->v[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
fe25519_setzero(r);
|
||||||
|
fe25519_sub(r, r, &t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
r->v[i] = x->v[i] + y->v[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
reduce_add_sub(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint32_t t[32];
|
||||||
|
|
||||||
|
t[0] = x->v[0] + 0x1da;
|
||||||
|
t[31] = x->v[31] + 0xfe;
|
||||||
|
|
||||||
|
for (i = 1; i < 31; i++) {
|
||||||
|
t[i] = x->v[i] + 0x1fe;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
r->v[i] = t[i] - y->v[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
reduce_add_sub(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y)
|
||||||
|
{
|
||||||
|
int i,j;
|
||||||
|
uint32_t t[63];
|
||||||
|
|
||||||
|
for (i = 0; i < 63; i++) {
|
||||||
|
t[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
for (j = 0; j < 32; j++) {
|
||||||
|
t[i+j] += x->v[i] * y->v[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 32; i < 63; i++) {
|
||||||
|
r->v[i-32] = t[i-32] + times38(t[i]);
|
||||||
|
}
|
||||||
|
r->v[31] = t[31]; /* result now in r[0]...r[31] */
|
||||||
|
|
||||||
|
reduce_mul(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fe25519_square(fe25519 *r, const fe25519 *x)
|
||||||
|
{
|
||||||
|
fe25519_mul(r, x, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fe25519_invert(fe25519 *r, const fe25519 *x)
|
||||||
|
{
|
||||||
|
fe25519 z2;
|
||||||
|
fe25519 z9;
|
||||||
|
fe25519 z11;
|
||||||
|
fe25519 z2_5_0;
|
||||||
|
fe25519 z2_10_0;
|
||||||
|
fe25519 z2_20_0;
|
||||||
|
fe25519 z2_50_0;
|
||||||
|
fe25519 z2_100_0;
|
||||||
|
fe25519 t0;
|
||||||
|
fe25519 t1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* 2 */ fe25519_square(&z2, x);
|
||||||
|
/* 4 */ fe25519_square(&t1, &z2);
|
||||||
|
/* 8 */ fe25519_square(&t0, &t1);
|
||||||
|
/* 9 */ fe25519_mul(&z9, &t0, x);
|
||||||
|
/* 11 */ fe25519_mul(&z11, &z9, &z2);
|
||||||
|
/* 22 */ fe25519_square(&t0, &z11);
|
||||||
|
/* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0, &t0, &z9);
|
||||||
|
|
||||||
|
/* 2^6 - 2^1 */ fe25519_square(&t0, &z2_5_0);
|
||||||
|
/* 2^7 - 2^2 */ fe25519_square(&t1, &t0);
|
||||||
|
/* 2^8 - 2^3 */ fe25519_square(&t0, &t1);
|
||||||
|
/* 2^9 - 2^4 */ fe25519_square(&t1, &t0);
|
||||||
|
/* 2^10 - 2^5 */ fe25519_square(&t0, &t1);
|
||||||
|
/* 2^10 - 2^0 */ fe25519_mul(&z2_10_0, &t0, &z2_5_0);
|
||||||
|
|
||||||
|
/* 2^11 - 2^1 */ fe25519_square(&t0, &z2_10_0);
|
||||||
|
/* 2^12 - 2^2 */ fe25519_square(&t1, &t0);
|
||||||
|
/* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) {
|
||||||
|
fe25519_square(&t0, &t1);
|
||||||
|
fe25519_square(&t1, &t0);
|
||||||
|
}
|
||||||
|
/* 2^20 - 2^0 */ fe25519_mul(&z2_20_0, &t1, &z2_10_0);
|
||||||
|
|
||||||
|
/* 2^21 - 2^1 */ fe25519_square(&t0, &z2_20_0);
|
||||||
|
/* 2^22 - 2^2 */ fe25519_square(&t1, &t0);
|
||||||
|
/* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) {
|
||||||
|
fe25519_square(&t0, &t1);
|
||||||
|
fe25519_square(&t1,&t0);
|
||||||
|
}
|
||||||
|
/* 2^40 - 2^0 */ fe25519_mul(&t0, &t1, &z2_20_0);
|
||||||
|
|
||||||
|
/* 2^41 - 2^1 */ fe25519_square(&t1, &t0);
|
||||||
|
/* 2^42 - 2^2 */ fe25519_square(&t0, &t1);
|
||||||
|
/* 2^50 - 2^10 */ for (i = 2; i < 10;i += 2) {
|
||||||
|
fe25519_square(&t1, &t0);
|
||||||
|
fe25519_square(&t0, &t1);
|
||||||
|
}
|
||||||
|
/* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t0,&z2_10_0);
|
||||||
|
|
||||||
|
/* 2^51 - 2^1 */ fe25519_square(&t0, &z2_50_0);
|
||||||
|
/* 2^52 - 2^2 */ fe25519_square(&t1, &t0);
|
||||||
|
/* 2^100 - 2^50 */ for (i = 2; i < 50; i += 2) {
|
||||||
|
fe25519_square(&t0, &t1);
|
||||||
|
fe25519_square(&t1,&t0);
|
||||||
|
}
|
||||||
|
/* 2^100 - 2^0 */ fe25519_mul(&z2_100_0, &t1, &z2_50_0);
|
||||||
|
|
||||||
|
/* 2^101 - 2^1 */ fe25519_square(&t1, &z2_100_0);
|
||||||
|
/* 2^102 - 2^2 */ fe25519_square(&t0, &t1);
|
||||||
|
/* 2^200 - 2^100 */ for (i = 2; i < 100; i += 2) {
|
||||||
|
fe25519_square(&t1, &t0);
|
||||||
|
fe25519_square(&t0,&t1);
|
||||||
|
}
|
||||||
|
/* 2^200 - 2^0 */ fe25519_mul(&t1, &t0, &z2_100_0);
|
||||||
|
|
||||||
|
/* 2^201 - 2^1 */ fe25519_square(&t0, &t1);
|
||||||
|
/* 2^202 - 2^2 */ fe25519_square(&t1, &t0);
|
||||||
|
/* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) {
|
||||||
|
fe25519_square(&t0, &t1);
|
||||||
|
fe25519_square(&t1,&t0);
|
||||||
|
}
|
||||||
|
/* 2^250 - 2^0 */ fe25519_mul(&t0, &t1, &z2_50_0);
|
||||||
|
|
||||||
|
/* 2^251 - 2^1 */ fe25519_square(&t1, &t0);
|
||||||
|
/* 2^252 - 2^2 */ fe25519_square(&t0, &t1);
|
||||||
|
/* 2^253 - 2^3 */ fe25519_square(&t1, &t0);
|
||||||
|
/* 2^254 - 2^4 */ fe25519_square(&t0, &t1);
|
||||||
|
/* 2^255 - 2^5 */ fe25519_square(&t1, &t0);
|
||||||
|
/* 2^255 - 21 */ fe25519_mul(r, &t1, &z11);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fe25519_pow2523(fe25519 *r, const fe25519 *x)
|
||||||
|
{
|
||||||
|
fe25519 z2;
|
||||||
|
fe25519 z9;
|
||||||
|
fe25519 z11;
|
||||||
|
fe25519 z2_5_0;
|
||||||
|
fe25519 z2_10_0;
|
||||||
|
fe25519 z2_20_0;
|
||||||
|
fe25519 z2_50_0;
|
||||||
|
fe25519 z2_100_0;
|
||||||
|
fe25519 t;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* 2 */ fe25519_square(&z2, x);
|
||||||
|
/* 4 */ fe25519_square(&t, &z2);
|
||||||
|
/* 8 */ fe25519_square(&t, &t);
|
||||||
|
/* 9 */ fe25519_mul(&z9, &t, x);
|
||||||
|
/* 11 */ fe25519_mul(&z11, &z9, &z2);
|
||||||
|
/* 22 */ fe25519_square(&t, &z11);
|
||||||
|
/* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0, &t, &z9);
|
||||||
|
|
||||||
|
/* 2^6 - 2^1 */ fe25519_square(&t, &z2_5_0);
|
||||||
|
/* 2^10 - 2^5 */ for (i = 1; i < 5; i++) {
|
||||||
|
fe25519_square(&t,&t);
|
||||||
|
}
|
||||||
|
/* 2^10 - 2^0 */ fe25519_mul(&z2_10_0, &t, &z2_5_0);
|
||||||
|
|
||||||
|
/* 2^11 - 2^1 */ fe25519_square(&t, &z2_10_0);
|
||||||
|
/* 2^20 - 2^10 */ for (i = 1; i < 10; i++) {
|
||||||
|
fe25519_square(&t, &t);
|
||||||
|
}
|
||||||
|
/* 2^20 - 2^0 */ fe25519_mul(&z2_20_0, &t, &z2_10_0);
|
||||||
|
|
||||||
|
/* 2^21 - 2^1 */ fe25519_square(&t, &z2_20_0);
|
||||||
|
/* 2^40 - 2^20 */ for (i = 1; i < 20; i++) {
|
||||||
|
fe25519_square(&t,&t);
|
||||||
|
}
|
||||||
|
/* 2^40 - 2^0 */ fe25519_mul(&t, &t, &z2_20_0);
|
||||||
|
|
||||||
|
/* 2^41 - 2^1 */ fe25519_square(&t, &t);
|
||||||
|
/* 2^50 - 2^10 */ for (i = 1; i < 10; i++) {
|
||||||
|
fe25519_square(&t,&t);
|
||||||
|
}
|
||||||
|
/* 2^50 - 2^0 */ fe25519_mul(&z2_50_0, &t, &z2_10_0);
|
||||||
|
|
||||||
|
/* 2^51 - 2^1 */ fe25519_square(&t, &z2_50_0);
|
||||||
|
/* 2^100 - 2^50 */ for (i = 1; i < 50; i++) {
|
||||||
|
fe25519_square(&t, &t);
|
||||||
|
}
|
||||||
|
/* 2^100 - 2^0 */ fe25519_mul(&z2_100_0, &t, &z2_50_0);
|
||||||
|
|
||||||
|
/* 2^101 - 2^1 */ fe25519_square(&t, &z2_100_0);
|
||||||
|
/* 2^200 - 2^100 */ for (i = 1; i < 100; i++) {
|
||||||
|
fe25519_square(&t, &t);
|
||||||
|
}
|
||||||
|
/* 2^200 - 2^0 */ fe25519_mul(&t, &t, &z2_100_0);
|
||||||
|
|
||||||
|
/* 2^201 - 2^1 */ fe25519_square(&t, &t);
|
||||||
|
/* 2^250 - 2^50 */ for (i = 1; i < 50; i++) {
|
||||||
|
fe25519_square(&t, &t);
|
||||||
|
}
|
||||||
|
/* 2^250 - 2^0 */ fe25519_mul(&t, &t, &z2_50_0);
|
||||||
|
|
||||||
|
/* 2^251 - 2^1 */ fe25519_square(&t, &t);
|
||||||
|
/* 2^252 - 2^2 */ fe25519_square(&t, &t);
|
||||||
|
/* 2^252 - 3 */ fe25519_mul(r, &t, x);
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user