mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-05 04:40:31 +09:00
Compare commits
2088 Commits
release-0-
...
libssh-0.7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
af99a4dc05 | ||
|
|
e800269013 | ||
|
|
ad709edadb | ||
|
|
0774da3c40 | ||
|
|
f1ec4f11e3 | ||
|
|
3eb66cba37 | ||
|
|
514a01f3df | ||
|
|
9156b8c068 | ||
|
|
1067591480 | ||
|
|
7375de0b05 | ||
|
|
51296a0237 | ||
|
|
6efa55d154 | ||
|
|
f9b8395122 | ||
|
|
cdf193d8b5 | ||
|
|
2f674aeec1 | ||
|
|
74bbcf7e29 | ||
|
|
26c118890f | ||
|
|
38420bff76 | ||
|
|
1444d62d96 | ||
|
|
5ba88f01e8 | ||
|
|
6a83f9a044 | ||
|
|
61084b76f6 | ||
|
|
c55ab44caf | ||
|
|
90e5ce3c3e | ||
|
|
448738eb00 | ||
|
|
e1280ce153 | ||
|
|
11c45b0f55 | ||
|
|
e1576ef55a | ||
|
|
df81a05505 | ||
|
|
7d07e1f1bd | ||
|
|
1829e9981b | ||
|
|
5145daba69 | ||
|
|
729a586027 | ||
|
|
8ff6a7a850 | ||
|
|
dbf3cdecda | ||
|
|
35d0c3a860 | ||
|
|
229ef082c1 | ||
|
|
da1eaea51a | ||
|
|
329f4da1e1 | ||
|
|
2c9808daf8 | ||
|
|
5e7b15e2c1 | ||
|
|
20312e23b7 | ||
|
|
2106db3efa | ||
|
|
08c31ccf31 | ||
|
|
f3e09612b3 | ||
|
|
7ed5512145 | ||
|
|
d1bbc35f33 | ||
|
|
f458055e9c | ||
|
|
4103358daa | ||
|
|
1ab4b28b00 | ||
|
|
461988b153 | ||
|
|
c4937cedea | ||
|
|
11c82a26a6 | ||
|
|
351e4107ed | ||
|
|
776ff528df | ||
|
|
22e8858134 | ||
|
|
483ba8100f | ||
|
|
0138c9fd59 | ||
|
|
831ed08a56 | ||
|
|
1467e0782e | ||
|
|
ecec2abfc7 | ||
|
|
8f0b6ccd66 | ||
|
|
b4790fbdd2 | ||
|
|
df373efc56 | ||
|
|
e3b4f27aa9 | ||
|
|
c64ec43eef | ||
|
|
0d3deeec10 | ||
|
|
c28efb8cbc | ||
|
|
ebdd0c6ac1 | ||
|
|
dcd94de076 | ||
|
|
a73557053e | ||
|
|
2c91efcc68 | ||
|
|
73309f19e5 | ||
|
|
6ad80bb4b2 | ||
|
|
365a3bba6e | ||
|
|
e95e3b5736 | ||
|
|
ad92740dc3 | ||
|
|
bf5e5eebd7 | ||
|
|
9d88dcab3e | ||
|
|
dd6a0b51ac | ||
|
|
3b81da21c2 | ||
|
|
ed7e3c936b | ||
|
|
1663917f71 | ||
|
|
9bbbccc0e7 | ||
|
|
c44029e5ce | ||
|
|
c231029be3 | ||
|
|
2ab7f2be75 | ||
|
|
47a4eea827 | ||
|
|
0d1ec1fa48 | ||
|
|
0356b78ede | ||
|
|
b0ab39a6f1 | ||
|
|
31a129ee9e | ||
|
|
7e7910a1ca | ||
|
|
55ddc3932e | ||
|
|
2a0c1e917f | ||
|
|
db20a22e51 | ||
|
|
560b508771 | ||
|
|
f528f71920 | ||
|
|
458e4c07c7 | ||
|
|
7555f3235e | ||
|
|
3e7bd72f76 | ||
|
|
f457080d62 | ||
|
|
37cce98f7e | ||
|
|
7e306a9ec6 | ||
|
|
81e769ec6a | ||
|
|
e809fa881e | ||
|
|
52d9e15c25 | ||
|
|
e933d1e1b1 | ||
|
|
e76442b650 | ||
|
|
9bdb546852 | ||
|
|
86ae29b30d | ||
|
|
65eccf1969 | ||
|
|
d944310412 | ||
|
|
7cb6b15aaa | ||
|
|
212261bb10 | ||
|
|
fadbe80c43 | ||
|
|
7fef6e817e | ||
|
|
1246ad812c | ||
|
|
3b52e38a33 | ||
|
|
6bb5063046 | ||
|
|
950d8e89a9 | ||
|
|
6c26a23cf4 | ||
|
|
b69c26ad72 | ||
|
|
cb0f886a5c | ||
|
|
3d7b24c534 | ||
|
|
4c99f5de4d | ||
|
|
a34ad5825b | ||
|
|
4497cd9b43 | ||
|
|
2b54db7603 | ||
|
|
ff30a8feb0 | ||
|
|
82b4cffe66 | ||
|
|
66b37c856c | ||
|
|
6bc64c368d | ||
|
|
ab2e641b4a | ||
|
|
48b715cce0 | ||
|
|
97e7c95d21 | ||
|
|
e52cc613e4 | ||
|
|
89be6d0309 | ||
|
|
36e4c2e5bc | ||
|
|
aed9d7a84d | ||
|
|
f0a362fdbe | ||
|
|
de4cb811a0 | ||
|
|
abb25861e5 | ||
|
|
b698f6361c | ||
|
|
e6be005236 | ||
|
|
8a4364a99b | ||
|
|
6dae8baefc | ||
|
|
94a8c30feb | ||
|
|
68be73ec0d | ||
|
|
485e3b4014 | ||
|
|
1deb3412bb | ||
|
|
aaae3c4ec1 | ||
|
|
b31efd9ff1 | ||
|
|
5d05aec2ef | ||
|
|
6306bee86c | ||
|
|
59dcebd604 | ||
|
|
7ceaea479e | ||
|
|
2b68728552 | ||
|
|
42c7bc5a21 | ||
|
|
ee47cab548 | ||
|
|
a65029da5d | ||
|
|
f31c33bb31 | ||
|
|
4255a7223c | ||
|
|
9ee45a18d7 | ||
|
|
0ba075e9ce | ||
|
|
d93e38bbfe | ||
|
|
e4bcd063b7 | ||
|
|
d83b3d9ebe | ||
|
|
6f8b5ed679 | ||
|
|
d255d1bf32 | ||
|
|
33e95792ce | ||
|
|
a38c56370c | ||
|
|
01493b8d47 | ||
|
|
1a894e2cf2 | ||
|
|
b8a3e5ffe3 | ||
|
|
09663692dd | ||
|
|
a03d8f49fb | ||
|
|
abd6b8004e | ||
|
|
e3c5096fcf | ||
|
|
51a531f4a7 | ||
|
|
fcf8af20f8 | ||
|
|
2d28ee7d22 | ||
|
|
e41482fec4 | ||
|
|
992f00b145 | ||
|
|
24e94d53e9 | ||
|
|
8455d79bb6 | ||
|
|
222a0d78ca | ||
|
|
e471aa4e0b | ||
|
|
5d6cab4b14 | ||
|
|
afe4c92bbf | ||
|
|
186116f34a | ||
|
|
b2f52799c2 | ||
|
|
915781381e | ||
|
|
21a45e89c5 | ||
|
|
de096910b3 | ||
|
|
ce33633bcb | ||
|
|
fb3f649c76 | ||
|
|
5dfc474fa8 | ||
|
|
6d61c3ce4a | ||
|
|
63c3f0e736 | ||
|
|
e934ab0816 | ||
|
|
9fa53cd932 | ||
|
|
5cd7942801 | ||
|
|
de9bc1fa41 | ||
|
|
b14df297fa | ||
|
|
3896aa43ff | ||
|
|
da8d44ccba | ||
|
|
c6fc69fbdd | ||
|
|
ab8c7de6f8 | ||
|
|
cd4e28e7c8 | ||
|
|
ea0e858de0 | ||
|
|
e403596d98 | ||
|
|
571dc42335 | ||
|
|
68d04c8e47 | ||
|
|
bd3acae4f3 | ||
|
|
894bbf3137 | ||
|
|
f61813eaea | ||
|
|
ad5f306884 | ||
|
|
5ffb8c7cde | ||
|
|
efaebad323 | ||
|
|
cab00c3bfc | ||
|
|
d404ad7152 | ||
|
|
a4ffaff550 | ||
|
|
e164b236c6 | ||
|
|
166ccef8dc | ||
|
|
f2e498c7db | ||
|
|
dde0404dfb | ||
|
|
f86b2bf743 | ||
|
|
13c26f0733 | ||
|
|
f5d8bdf946 | ||
|
|
f4f2237263 | ||
|
|
7e93edc722 | ||
|
|
95ab34696b | ||
|
|
82711acd39 | ||
|
|
e8118c5be4 | ||
|
|
a59a379ce4 | ||
|
|
0bd2bbefa7 | ||
|
|
3d390cf6ff | ||
|
|
e04dc45f20 | ||
|
|
de34a64895 | ||
|
|
46f22576b0 | ||
|
|
2f8ddc6e65 | ||
|
|
b1287cd946 | ||
|
|
a660177a6e | ||
|
|
0a4ea19982 | ||
|
|
0bf2dd81e6 | ||
|
|
ecb6cfd053 | ||
|
|
ba220adb84 | ||
|
|
802e4133cb | ||
|
|
dde3deb9ea | ||
|
|
66045054f4 | ||
|
|
96e0301b58 | ||
|
|
029d165b61 | ||
|
|
4e7736444f | ||
|
|
7254390ac2 | ||
|
|
188c596803 | ||
|
|
0295301928 | ||
|
|
a6e7d1f255 | ||
|
|
f2c183b413 | ||
|
|
5e8e21d106 | ||
|
|
bcc00eec9b | ||
|
|
53008fb5d4 | ||
|
|
9338fb8e5e | ||
|
|
ec5b4d377f | ||
|
|
6352b3d93a | ||
|
|
b8de9e75d0 | ||
|
|
ec56d1d453 | ||
|
|
87036839f9 | ||
|
|
131a0de32e | ||
|
|
3e93836e8b | ||
|
|
21db70888a | ||
|
|
bb2848de5a | ||
|
|
6acce40a28 | ||
|
|
41269874f5 | ||
|
|
9abe591843 | ||
|
|
114cc51a10 | ||
|
|
9fe47da903 | ||
|
|
362be13156 | ||
|
|
e17fcd70f9 | ||
|
|
5f0f334d1c | ||
|
|
996b7cae26 | ||
|
|
b219d1890c | ||
|
|
bfa568e448 | ||
|
|
ff53664f54 | ||
|
|
b811b89f57 | ||
|
|
3db2ac41eb | ||
|
|
ca74d91d50 | ||
|
|
956cf94f70 | ||
|
|
191faea325 | ||
|
|
0493c1fea9 | ||
|
|
ecd2ee95e7 | ||
|
|
c81010e2f7 | ||
|
|
c078e36219 | ||
|
|
c5782b7486 | ||
|
|
1e836a03d2 | ||
|
|
ceb8072b34 | ||
|
|
656fd60110 | ||
|
|
6092596199 | ||
|
|
22f607649d | ||
|
|
b5c4b090da | ||
|
|
fd2064d0b4 | ||
|
|
8567fc8d8c | ||
|
|
61d032fc03 | ||
|
|
dc8103925c | ||
|
|
280ce3fe93 | ||
|
|
332f1a2a51 | ||
|
|
213321d706 | ||
|
|
cddfe602cc | ||
|
|
d0889dd9ea | ||
|
|
3c5235fdc0 | ||
|
|
ed94e7f8a8 | ||
|
|
9460c5906f | ||
|
|
160da5810f | ||
|
|
a18106d3af | ||
|
|
3739bd99c5 | ||
|
|
320951f42f | ||
|
|
a3f83e7274 | ||
|
|
e689375e45 | ||
|
|
977951e96a | ||
|
|
782b2e37c6 | ||
|
|
a92c97b2e1 | ||
|
|
43e3a8e497 | ||
|
|
8ef45e00c7 | ||
|
|
e8cebc2a37 | ||
|
|
8624651de3 | ||
|
|
8b8d9dc83a | ||
|
|
ad24427f03 | ||
|
|
2ed9d2160d | ||
|
|
9bac67a05a | ||
|
|
a3cb5b0707 | ||
|
|
88d6e6253c | ||
|
|
a3cf1e4acc | ||
|
|
62657d5f87 | ||
|
|
1973e833f2 | ||
|
|
387d9e4855 | ||
|
|
2ca0a9cdb2 | ||
|
|
29ad0d19f9 | ||
|
|
c31004442a | ||
|
|
e68b763a67 | ||
|
|
72db38b31d | ||
|
|
300caf9ff3 | ||
|
|
3888a050f8 | ||
|
|
66aaa6f573 | ||
|
|
3582e386b7 | ||
|
|
72001ff8cc | ||
|
|
b7507fc85e | ||
|
|
f558c66e78 | ||
|
|
3bb381fad7 | ||
|
|
88964cb541 | ||
|
|
8fea5c7a28 | ||
|
|
19090c5cd8 | ||
|
|
f0589a2caf | ||
|
|
50e9608dcd | ||
|
|
ee774479de | ||
|
|
840f75f10c | ||
|
|
c0a7a84e92 | ||
|
|
4019dbed85 | ||
|
|
216cb8b1aa | ||
|
|
fb6855a821 | ||
|
|
0770843309 | ||
|
|
f639b8ec1f | ||
|
|
c209c6d5ac | ||
|
|
b136a986a0 | ||
|
|
e93f17cad8 | ||
|
|
47226d9d44 | ||
|
|
a311ec32b1 | ||
|
|
4223c8a116 | ||
|
|
e4d0ac7ba1 | ||
|
|
84dfa13fe8 | ||
|
|
19f7458ed3 | ||
|
|
3e83bc665f | ||
|
|
ddcfe95bbd | ||
|
|
679cd9efd8 | ||
|
|
ae59049347 | ||
|
|
b1434fd09b | ||
|
|
79383cf8ee | ||
|
|
33b0cfc199 | ||
|
|
e9f5c7421e | ||
|
|
9070b04184 | ||
|
|
b309dd8fb7 | ||
|
|
91372e298d | ||
|
|
14bb23ae3b | ||
|
|
0e1992a9cc | ||
|
|
ecbdc589f4 | ||
|
|
fc8a182823 | ||
|
|
f35c284761 | ||
|
|
fa37965ab0 | ||
|
|
3c7571e61b | ||
|
|
d44a79da9b | ||
|
|
ea74a12b70 | ||
|
|
b4823252ca | ||
|
|
244fa0474b | ||
|
|
9e5b3914de | ||
|
|
31727bf33a | ||
|
|
a15399992e | ||
|
|
89733e697f | ||
|
|
2ffbdb0492 | ||
|
|
4305da29a1 | ||
|
|
2f861a858b | ||
|
|
74f5f43409 | ||
|
|
0b7b699ced | ||
|
|
c08bdf5917 | ||
|
|
7d26f7ceab | ||
|
|
90893fd1a3 | ||
|
|
76fad364cd | ||
|
|
ba4f10dc46 | ||
|
|
ce0324770d | ||
|
|
bc2ab9b414 | ||
|
|
ce26b8d777 | ||
|
|
99d2cf02a6 | ||
|
|
17f396ffab | ||
|
|
2c04994443 | ||
|
|
e799c0ce7d | ||
|
|
2cc48db673 | ||
|
|
e797781bb5 | ||
|
|
6bd95b50f5 | ||
|
|
d8d9755b7d | ||
|
|
1fcddebadc | ||
|
|
551a0c855b | ||
|
|
85cc582d4a | ||
|
|
c340192144 | ||
|
|
b6d0b531f8 | ||
|
|
5c19cda280 | ||
|
|
e38f2f933b | ||
|
|
21d68112b8 | ||
|
|
3fa5293aec | ||
|
|
6859e4f4ec | ||
|
|
43fc7553f8 | ||
|
|
717840fc09 | ||
|
|
046aa02f39 | ||
|
|
8a3b02f68d | ||
|
|
dad35304b6 | ||
|
|
744b7720af | ||
|
|
5083742192 | ||
|
|
dc42a1757f | ||
|
|
7202a26b6c | ||
|
|
b785014a15 | ||
|
|
acfc8ea83f | ||
|
|
c2686b8feb | ||
|
|
e7009fe8f3 | ||
|
|
ffb827b539 | ||
|
|
33754c391f | ||
|
|
d7fa15df83 | ||
|
|
519291558d | ||
|
|
abd9856c6a | ||
|
|
4a6a0987a8 | ||
|
|
3622ac83f6 | ||
|
|
f61269a2ef | ||
|
|
d24e353e38 | ||
|
|
09b33b1b6e | ||
|
|
af09313eac | ||
|
|
ac41a083ef | ||
|
|
48980573c1 | ||
|
|
22668bcdae | ||
|
|
07abc3406d | ||
|
|
1b10b175fc | ||
|
|
8f1161f649 | ||
|
|
2cc95e1e08 | ||
|
|
fa7798833a | ||
|
|
b96943e861 | ||
|
|
569312f7bd | ||
|
|
c2883c1f37 | ||
|
|
c19c638d74 | ||
|
|
afa56e0102 | ||
|
|
544747d02c | ||
|
|
68bab2a490 | ||
|
|
c4701a34d3 | ||
|
|
36ec488663 | ||
|
|
714aeca91f | ||
|
|
af225e68cb | ||
|
|
ebfb2a5cdb | ||
|
|
33cf16488b | ||
|
|
0fa88fdcfe | ||
|
|
49ae226b90 | ||
|
|
f3d00e4bc3 | ||
|
|
fa68d91869 | ||
|
|
1f31415760 | ||
|
|
27dea35608 | ||
|
|
ff5bf51af1 | ||
|
|
7b663df185 | ||
|
|
33bd3d6cd9 | ||
|
|
28bfc7645c | ||
|
|
ae89dfd6f2 | ||
|
|
06e0305100 | ||
|
|
3b5bdc5db4 | ||
|
|
95ec57f2fd | ||
|
|
a5d89624d5 | ||
|
|
04faa33259 | ||
|
|
35dce7e8d1 | ||
|
|
c8f48a2478 | ||
|
|
08129002de | ||
|
|
b3d62ecba8 | ||
|
|
bf72440eff | ||
|
|
77e71ae3b5 | ||
|
|
81017b0fc2 | ||
|
|
4a5b72a535 | ||
|
|
c1f8b38b78 | ||
|
|
5581323c2c | ||
|
|
55c758d079 | ||
|
|
09da9418cc | ||
|
|
6d3d5a446e | ||
|
|
11f3b0e684 | ||
|
|
ae1f87e37a | ||
|
|
3105b3c205 | ||
|
|
2e83cc925d | ||
|
|
808c7a9be4 | ||
|
|
6901e25085 | ||
|
|
a0e3facac7 | ||
|
|
6dc7ddde3f | ||
|
|
7e5f1edcb4 | ||
|
|
20f8e73e3e | ||
|
|
ef5701a535 | ||
|
|
7d347aa6f4 | ||
|
|
6d8bb956c5 | ||
|
|
3eece8ac0b | ||
|
|
92c8a71abb | ||
|
|
b5351f2809 | ||
|
|
d1ebc4697a | ||
|
|
7f5206b8ac | ||
|
|
cb2a111fa1 | ||
|
|
555d1a4347 | ||
|
|
17ae216340 | ||
|
|
3a5cc18b32 | ||
|
|
b11567ed9b | ||
|
|
faaf334aa3 | ||
|
|
5d9cd8bf39 | ||
|
|
a2c94abb92 | ||
|
|
510c741229 | ||
|
|
f9dad9ad68 | ||
|
|
7363b29427 | ||
|
|
99e6fde751 | ||
|
|
5c48438dcb | ||
|
|
b5b3db6c90 | ||
|
|
e5a39a3ae9 | ||
|
|
fedfbf9563 | ||
|
|
7093ac986d | ||
|
|
64de14f51e | ||
|
|
fe246db27d | ||
|
|
0cbbe39e4f | ||
|
|
822c68eb8e | ||
|
|
60b92e458e | ||
|
|
e236577503 | ||
|
|
85d12f6774 | ||
|
|
6bf8dfa073 | ||
|
|
66188f1af8 | ||
|
|
d1df255df4 | ||
|
|
a060a235a4 | ||
|
|
7a9f65dd94 | ||
|
|
246d20ef23 | ||
|
|
f803538d21 | ||
|
|
292ed71f09 | ||
|
|
2d9cd48b1d | ||
|
|
10d3d73039 | ||
|
|
f02f889111 | ||
|
|
a9eb0020b8 | ||
|
|
fb4f1412ba | ||
|
|
561441105f | ||
|
|
7c28d0ce6d | ||
|
|
5cf23522de | ||
|
|
be660e801a | ||
|
|
bce2c22e45 | ||
|
|
29ecccb96d | ||
|
|
16b47496c1 | ||
|
|
9379a93c98 | ||
|
|
21875bc71e | ||
|
|
0f41f21227 | ||
|
|
98ada12f66 | ||
|
|
0bd99b3773 | ||
|
|
e5e673bafe | ||
|
|
79ed1bc601 | ||
|
|
228e2edac5 | ||
|
|
1d734f16cf | ||
|
|
5a0735d1e8 | ||
|
|
f1634d33da | ||
|
|
4bdd831d7f | ||
|
|
d4424b2767 | ||
|
|
f2e08e8d7b | ||
|
|
26e624c1b7 | ||
|
|
f8c987d1d4 | ||
|
|
696f574a56 | ||
|
|
ab1a66ca7b | ||
|
|
7457937bab | ||
|
|
b5db04003d | ||
|
|
a51d377afe | ||
|
|
892cb92f57 | ||
|
|
c59939d4a2 | ||
|
|
5c601115c3 | ||
|
|
89253fd22a | ||
|
|
21261270e5 | ||
|
|
1a56892e9f | ||
|
|
c5643c0967 | ||
|
|
c5837a6c63 | ||
|
|
c221db0f36 | ||
|
|
4c1d3b708c | ||
|
|
379d65eaaf | ||
|
|
aa018c1484 | ||
|
|
37df5e17c3 | ||
|
|
609f8fbb7a | ||
|
|
5b706c7ab6 | ||
|
|
a15dab6c00 | ||
|
|
5695f92e22 | ||
|
|
2e577cecb4 | ||
|
|
058bb04396 | ||
|
|
dc9feec005 | ||
|
|
fa4378d47e | ||
|
|
e94b0f8c08 | ||
|
|
149be78ee0 | ||
|
|
8fb8ad0151 | ||
|
|
93c4a8e427 | ||
|
|
9da331e79b | ||
|
|
8edf57fbf2 | ||
|
|
8c8a91a9b7 | ||
|
|
bf2f553fc3 | ||
|
|
82ca6a6c53 | ||
|
|
5cc98ed720 | ||
|
|
bcc0a6d0e0 | ||
|
|
6c03b7a9c9 | ||
|
|
90167f09d3 | ||
|
|
9c376dd913 | ||
|
|
1e019fee43 | ||
|
|
4de4520559 | ||
|
|
245a354187 | ||
|
|
d6829d073c | ||
|
|
79ffd49940 | ||
|
|
a2e08697b1 | ||
|
|
ca9b01af99 | ||
|
|
d0d9e62611 | ||
|
|
a86ac461fd | ||
|
|
859ed8583c | ||
|
|
1b57445f6b | ||
|
|
af82d8dfab | ||
|
|
a98301d2b0 | ||
|
|
9c9199e05f | ||
|
|
fa4f2d8bc1 | ||
|
|
42cea1f2f1 | ||
|
|
c8d06b6b1c | ||
|
|
948400ed92 | ||
|
|
eb65f031af | ||
|
|
c041261921 | ||
|
|
a4b2518761 | ||
|
|
4f19a304d1 | ||
|
|
ab0354dbb6 | ||
|
|
ce41747fae | ||
|
|
8acc3dd3af | ||
|
|
79029854f6 | ||
|
|
743a00dad4 | ||
|
|
bb509ce4f7 | ||
|
|
bac5f62eaf | ||
|
|
e3bd018465 | ||
|
|
5bcf36f098 | ||
|
|
c575de17a8 | ||
|
|
3e56ac650c | ||
|
|
765b42e68a | ||
|
|
2615f8bc94 | ||
|
|
c39181437b | ||
|
|
ddcb88070b | ||
|
|
1a0fbedc2e | ||
|
|
254c30be2e | ||
|
|
25a2108809 | ||
|
|
9b84464748 | ||
|
|
a40f1d8597 | ||
|
|
c940918821 | ||
|
|
f7a7bf071d | ||
|
|
c5028e76ad | ||
|
|
df29df6e35 | ||
|
|
330c713fdb | ||
|
|
42dda7b958 | ||
|
|
614ad97c12 | ||
|
|
04ce7967b8 | ||
|
|
19a3f5a61d | ||
|
|
9dfef44fd8 | ||
|
|
c085892802 | ||
|
|
47ebcac4cd | ||
|
|
977d6fc089 | ||
|
|
3c3673d1b8 | ||
|
|
3f70bce373 | ||
|
|
6c1b508efd | ||
|
|
714fa8960d | ||
|
|
54a2b8a303 | ||
|
|
96e338ba56 | ||
|
|
6ffee22448 | ||
|
|
fe375132c3 | ||
|
|
2780f76247 | ||
|
|
a983512678 | ||
|
|
c77b23b32a | ||
|
|
962bdb1eea | ||
|
|
e06b3dba0d | ||
|
|
190ae27463 | ||
|
|
481522cf63 | ||
|
|
0523adf95c | ||
|
|
74d755873d | ||
|
|
30ec1e0b05 | ||
|
|
f421c05913 | ||
|
|
e92787395a | ||
|
|
a4a1af5bbf | ||
|
|
1c30c2a510 | ||
|
|
8bf8a7ef49 | ||
|
|
37a38d4959 | ||
|
|
13227714f2 | ||
|
|
7949f2cdc6 | ||
|
|
2f87873642 | ||
|
|
6c45d6dc01 | ||
|
|
9c0af42dd8 | ||
|
|
bec483bc18 | ||
|
|
f81444bd57 | ||
|
|
38d00c0e7a | ||
|
|
9bed334da3 | ||
|
|
7c302d376c | ||
|
|
36ee2d3332 | ||
|
|
f55cd7de43 | ||
|
|
9569d053d8 | ||
|
|
028888719a | ||
|
|
d8b41bcac3 | ||
|
|
6ccb3f7a82 | ||
|
|
37b80e9261 | ||
|
|
01c4b713dc | ||
|
|
35686b4822 | ||
|
|
7ccd9c31b3 | ||
|
|
af85337f5f | ||
|
|
563fbe4de8 | ||
|
|
39f962c91e | ||
|
|
c31cac93f3 | ||
|
|
a290fe33c1 | ||
|
|
15ebbad146 | ||
|
|
790b62bca5 | ||
|
|
ca47c9b46e | ||
|
|
0943ce3a4a | ||
|
|
da954c2c5e | ||
|
|
dc9ac022f5 | ||
|
|
54fb43358c | ||
|
|
cc29fef234 | ||
|
|
f684e76ab2 | ||
|
|
c75581fb93 | ||
|
|
27cedaa0b6 | ||
|
|
2be90be740 | ||
|
|
3ba44badb0 | ||
|
|
bcec7eeddc | ||
|
|
ce03d26e03 | ||
|
|
db2d0ebc44 | ||
|
|
583a7f933a | ||
|
|
2653b31af0 | ||
|
|
a3c28f2558 | ||
|
|
c5a998f47a | ||
|
|
3b72bf0880 | ||
|
|
113de13543 | ||
|
|
b54e8cdae5 | ||
|
|
fb0f125351 | ||
|
|
981190f8d3 | ||
|
|
88e2f17b97 | ||
|
|
29fa4b6b35 | ||
|
|
7ff69d9c48 | ||
|
|
640e3830f2 | ||
|
|
3fa801a929 | ||
|
|
d536cc4f39 | ||
|
|
ee83301eb3 | ||
|
|
1880ef54d2 | ||
|
|
94ca5ed3df | ||
|
|
693425afab | ||
|
|
82798035fc | ||
|
|
3c21281bf0 | ||
|
|
3bc46c3bf0 | ||
|
|
ac167c9077 | ||
|
|
c84380bad5 | ||
|
|
17454caf64 | ||
|
|
dcea8db6b2 | ||
|
|
809b3adeba | ||
|
|
34b05fd2dc | ||
|
|
c483418b82 | ||
|
|
ba03388031 | ||
|
|
8b73609e47 | ||
|
|
07fb895fe9 | ||
|
|
65282841e2 | ||
|
|
59f7647cd9 | ||
|
|
4d6b1aa2c7 | ||
|
|
79434649d0 | ||
|
|
a053d819a3 | ||
|
|
837896e72d | ||
|
|
12b61a6266 | ||
|
|
f4f4ce37f0 | ||
|
|
671a982739 | ||
|
|
4e153aed8a | ||
|
|
525324b2f9 | ||
|
|
e3311d03db | ||
|
|
7f0761885c | ||
|
|
9866763789 | ||
|
|
32cd45612b | ||
|
|
d4838d4dc8 | ||
|
|
daf1c3e0a8 | ||
|
|
32ba5204b7 | ||
|
|
b6e712e934 | ||
|
|
7d2064c289 | ||
|
|
eb5fedb685 | ||
|
|
1979c14aac | ||
|
|
8092541603 | ||
|
|
7ba0938846 | ||
|
|
3ae01ff9f5 | ||
|
|
040a543f57 | ||
|
|
a73459171b | ||
|
|
c3849a3cfd | ||
|
|
91c9d86d45 | ||
|
|
6e58342abc | ||
|
|
8b95328b1b | ||
|
|
644145a88c | ||
|
|
ef658b4bef | ||
|
|
a6c53d51de | ||
|
|
e7e4f261a6 | ||
|
|
96d5f13813 | ||
|
|
3a77f2aebe | ||
|
|
5939cfe78a | ||
|
|
3e7d4534ce | ||
|
|
cee8ca339b | ||
|
|
7cc4471168 | ||
|
|
3046a50614 | ||
|
|
23aa58e442 | ||
|
|
f8c7ad9c7a | ||
|
|
72b53aa11e | ||
|
|
c96314971c | ||
|
|
82e3068cb7 | ||
|
|
b308bb9d52 | ||
|
|
c1f65492f7 | ||
|
|
c5db7674ec | ||
|
|
2694853979 | ||
|
|
69d2457762 | ||
|
|
c1d385f6da | ||
|
|
c20afa75a2 | ||
|
|
df3e497dbd | ||
|
|
9a21093ab8 | ||
|
|
5f54eff0be | ||
|
|
43ebdbfe46 | ||
|
|
2be42922c8 | ||
|
|
a0a3ceeaa0 | ||
|
|
42315772b2 | ||
|
|
23b28a573c | ||
|
|
934252d6ca | ||
|
|
94e7d345a7 | ||
|
|
7e4916cefc | ||
|
|
e04d30e083 | ||
|
|
166ee451c5 | ||
|
|
46475dfa2f | ||
|
|
7150cabafa | ||
|
|
29bb718a93 | ||
|
|
1c062b22bf | ||
|
|
4bc9c96e4e | ||
|
|
0ab17a8906 | ||
|
|
1a101a959e | ||
|
|
dff4e4e6d3 | ||
|
|
79b74bdf64 | ||
|
|
633d6532be | ||
|
|
7e921b7afb | ||
|
|
7420b0fb83 | ||
|
|
52e223dfdd | ||
|
|
e2706fe21d | ||
|
|
7daa81f3aa | ||
|
|
6754c34711 | ||
|
|
7e9d384ec8 | ||
|
|
d97458d640 | ||
|
|
dab8f847e6 | ||
|
|
8d3823127c | ||
|
|
8ee8d4f913 | ||
|
|
000d659ea2 | ||
|
|
ddb1c1838f | ||
|
|
e40261c22c | ||
|
|
6582da1d67 | ||
|
|
0c76156f54 | ||
|
|
4b72953c7e | ||
|
|
4ee4450a6b | ||
|
|
a2634ceea8 | ||
|
|
ac8276c70e | ||
|
|
5cc2e69d0d | ||
|
|
23b3c46fd6 | ||
|
|
8a83990c16 | ||
|
|
071b0034db | ||
|
|
7ae59c571a | ||
|
|
b1db0e54ad | ||
|
|
4230509e80 | ||
|
|
11e54e8221 | ||
|
|
eea1df3574 | ||
|
|
9baa491b0b | ||
|
|
cd30a1d4b1 | ||
|
|
ca941d6985 | ||
|
|
cbcd5668f5 | ||
|
|
fdd1cb18d0 | ||
|
|
a0c05c4c4e | ||
|
|
499467d362 | ||
|
|
d1ddec00d9 | ||
|
|
637fc7ea59 | ||
|
|
622d5a43b3 | ||
|
|
483cdc2d2c | ||
|
|
5d4bd5a21d | ||
|
|
e8c3f55751 | ||
|
|
8d9d46ca66 | ||
|
|
4d38b4c848 | ||
|
|
768fbdd92e | ||
|
|
b313fa944a | ||
|
|
7acc2fa607 | ||
|
|
8e0e4d8fb3 | ||
|
|
8b51d29363 | ||
|
|
cc76a192df | ||
|
|
3c0a4781e4 | ||
|
|
32e23a25da | ||
|
|
3eaf25d989 | ||
|
|
6f2bf91e29 | ||
|
|
5a8a2a56af | ||
|
|
d464b57fa5 | ||
|
|
c950ed3b4c | ||
|
|
5144f390ca | ||
|
|
f5e2c94ae3 | ||
|
|
8078d4f674 | ||
|
|
ac785e0aa3 | ||
|
|
541519e563 | ||
|
|
58feb0c983 | ||
|
|
72e08d5dd9 | ||
|
|
f812ace256 | ||
|
|
057704c097 | ||
|
|
92f20ec85a | ||
|
|
a26194ece0 | ||
|
|
22b1e5bc7c | ||
|
|
38d6d38c1f | ||
|
|
215c41710e | ||
|
|
97d261dc79 | ||
|
|
892ebf35f1 | ||
|
|
05cd7296ba | ||
|
|
93a2d79459 | ||
|
|
30e4096c66 | ||
|
|
03b387cf47 | ||
|
|
131e3b968f | ||
|
|
4bf8ee8032 | ||
|
|
63c42f066f | ||
|
|
9e40e60bc4 | ||
|
|
8f850585dd | ||
|
|
4b07157fc6 | ||
|
|
867944b939 | ||
|
|
b0c2be25a6 | ||
|
|
c1ecec7cda | ||
|
|
00d68d63fa | ||
|
|
5d87ca94a8 | ||
|
|
1e827a8e81 | ||
|
|
20e637968a | ||
|
|
5c581f8a4c | ||
|
|
d67cbdc926 | ||
|
|
a63dbc07f3 | ||
|
|
6a3cd6c20f | ||
|
|
8a9ce6239a | ||
|
|
f3685f0f73 | ||
|
|
50a119dd0a | ||
|
|
8abdaa7abf | ||
|
|
80ef7d9304 | ||
|
|
84df46f805 | ||
|
|
460d43f050 | ||
|
|
625692f4c5 | ||
|
|
0e2bbdd25b | ||
|
|
6b52aaff1c | ||
|
|
227764a803 | ||
|
|
624676b1cc | ||
|
|
a236a15c6c | ||
|
|
cb775092bc | ||
|
|
8d7d313498 | ||
|
|
c6e1792696 | ||
|
|
90fc5554e1 | ||
|
|
e579dfb342 | ||
|
|
0c93914948 | ||
|
|
670dd17044 | ||
|
|
b945cbca52 | ||
|
|
f8361d324e | ||
|
|
0b46f68c5f | ||
|
|
2917e71aad | ||
|
|
551b87b65b | ||
|
|
5b6f048197 | ||
|
|
a17472ff2b | ||
|
|
7fbb926c0b | ||
|
|
bb5f5281c0 | ||
|
|
9140242cbe | ||
|
|
bcea8921ba | ||
|
|
076dfb8294 | ||
|
|
d631ce32ed | ||
|
|
4439d5c774 | ||
|
|
ac6278feb7 | ||
|
|
d1e1103198 | ||
|
|
4f83918109 | ||
|
|
6b27966c9c | ||
|
|
a016d356fa | ||
|
|
61852635b5 | ||
|
|
184f1e1706 | ||
|
|
dfa01d0862 | ||
|
|
82547867eb | ||
|
|
7d9f889911 | ||
|
|
13ece2a2f8 | ||
|
|
e57d5a45b9 | ||
|
|
ec12da273e | ||
|
|
fdffa42c02 | ||
|
|
d679d5d7ef | ||
|
|
2464a25de7 | ||
|
|
e12253168c | ||
|
|
1540dad17f | ||
|
|
350838d1b5 | ||
|
|
f23880ddee | ||
|
|
be3e5c35cf | ||
|
|
73c0cd050e | ||
|
|
c54d6b7f8a | ||
|
|
2b6fa19fe5 | ||
|
|
3f538b3ddd | ||
|
|
2faaefade9 | ||
|
|
ef1866db76 | ||
|
|
d4072082d0 | ||
|
|
a7237e8cea | ||
|
|
bc2db562e5 | ||
|
|
93ce8e8ffd | ||
|
|
98bacf032f | ||
|
|
e795dae8f2 | ||
|
|
459fa3734f | ||
|
|
52d6b7b914 | ||
|
|
5331489581 | ||
|
|
2945a42c75 | ||
|
|
1f47730a82 | ||
|
|
1b88542fbe | ||
|
|
530629c5a7 | ||
|
|
98b5f07631 | ||
|
|
f46bf41813 | ||
|
|
8e632b14d1 | ||
|
|
4728ac54fc | ||
|
|
da86340551 | ||
|
|
fc8fdcb16b | ||
|
|
be68cfe923 | ||
|
|
cb48057098 | ||
|
|
ef91ac4ea0 | ||
|
|
1646ce970c | ||
|
|
08906e0f7f | ||
|
|
887d201bd3 | ||
|
|
1267240810 | ||
|
|
296767afc4 | ||
|
|
13f3679b2f | ||
|
|
f3a6c3152c | ||
|
|
80d7ccb522 | ||
|
|
78abf5a88d | ||
|
|
ad231ccd30 | ||
|
|
d4a6c27a83 | ||
|
|
e7a06ad3b4 | ||
|
|
d2bf90c982 | ||
|
|
69ac51dfaa | ||
|
|
3e2f714248 | ||
|
|
530c17e2ef | ||
|
|
31043334f4 | ||
|
|
361e37dc66 | ||
|
|
df55918a41 | ||
|
|
e6329c72d1 | ||
|
|
8bd29736d2 | ||
|
|
0b2cf70622 | ||
|
|
b0446ad55d | ||
|
|
d04ce30b03 | ||
|
|
512b776245 | ||
|
|
d44919dfd4 | ||
|
|
99d45c686c | ||
|
|
2bc03d22a1 | ||
|
|
fa17f33d2b | ||
|
|
400fc350a7 | ||
|
|
6f65e6ae67 | ||
|
|
635a263f64 | ||
|
|
17f592d4dd | ||
|
|
7dc183126a | ||
|
|
4fe1656cf8 | ||
|
|
a883330101 | ||
|
|
f0d811edc6 | ||
|
|
438083542d | ||
|
|
4fa2e4dde1 | ||
|
|
32c0e1c99a | ||
|
|
b4c62ac9ea | ||
|
|
a0e98f585a | ||
|
|
7c728acd12 | ||
|
|
38b87aab08 | ||
|
|
33c41074a7 | ||
|
|
936c65f03e | ||
|
|
825581d0dc | ||
|
|
942b993f57 | ||
|
|
e6bc4b4ff9 | ||
|
|
04e224c3b4 | ||
|
|
19ab9a015f | ||
|
|
94fe52870b | ||
|
|
55470aaaf1 | ||
|
|
6a26335158 | ||
|
|
256e88690d | ||
|
|
3a94c94f20 | ||
|
|
473d3e0b3a | ||
|
|
d5df18a14f | ||
|
|
bffaa86664 | ||
|
|
1922341e2a | ||
|
|
bcfab67daf | ||
|
|
27f170011e | ||
|
|
5cb4c9451f | ||
|
|
80408d5357 | ||
|
|
47d11734e1 | ||
|
|
14d6b8856f | ||
|
|
48e4df4ac0 | ||
|
|
f5d0f232c8 | ||
|
|
d6a5e5cb68 | ||
|
|
751f202f56 | ||
|
|
37eeb854e4 | ||
|
|
57d752a1c3 | ||
|
|
ef1cfbea70 | ||
|
|
038c764055 | ||
|
|
3ea33f9ab6 | ||
|
|
1758c172a2 | ||
|
|
2a6cbed121 | ||
|
|
92fc2d6993 | ||
|
|
2dba4839ad | ||
|
|
0825abd03a | ||
|
|
f58441f474 | ||
|
|
0e82cdeadc | ||
|
|
b6901ec4b9 | ||
|
|
ea4aa26dbb | ||
|
|
98221f4e36 | ||
|
|
8e2699e161 | ||
|
|
01eb20e13f | ||
|
|
b129181809 | ||
|
|
3253ece2a2 | ||
|
|
4b462449cf | ||
|
|
4f8907a524 | ||
|
|
7b1359042c | ||
|
|
da9cd2e64d | ||
|
|
5d1636985b | ||
|
|
088b86d4fe | ||
|
|
9a89fba332 | ||
|
|
0bc032726d | ||
|
|
b2f571e544 | ||
|
|
338a3d9b05 | ||
|
|
5687d6e79a | ||
|
|
a9ec8b055f | ||
|
|
5f69d494ad | ||
|
|
3d8cfa9973 | ||
|
|
0d5cc01f1c | ||
|
|
d7581c4daa | ||
|
|
524302ca7e | ||
|
|
2617024136 | ||
|
|
26d40b5354 | ||
|
|
c4356531f7 | ||
|
|
873e02fc6a | ||
|
|
985db35173 | ||
|
|
c4e67730a3 | ||
|
|
9f7e2c3252 | ||
|
|
5675fbe73e | ||
|
|
5b1c985a0e | ||
|
|
bedc65313f | ||
|
|
9f53906209 | ||
|
|
be837cdbc2 | ||
|
|
38359672a5 | ||
|
|
1b471256d4 | ||
|
|
30e22fed6e | ||
|
|
8b719e51cf | ||
|
|
72b62d3064 | ||
|
|
5f24a84298 | ||
|
|
1eaf55c5f6 | ||
|
|
9d3b84c914 | ||
|
|
b391a7603a | ||
|
|
45b551d4f7 | ||
|
|
15e4ec38f2 | ||
|
|
8c318fcb21 | ||
|
|
a2fe4b2b2c | ||
|
|
e36c9c529b | ||
|
|
41c4e1f5c8 | ||
|
|
75a0281a6b | ||
|
|
a92545517a | ||
|
|
fe31fcaeef | ||
|
|
f7ea9a3f27 | ||
|
|
b0c03280d1 | ||
|
|
5eb7c7b6ec | ||
|
|
b7af2b2959 | ||
|
|
9f02a817ff | ||
|
|
6345afabf8 | ||
|
|
899db7cf22 | ||
|
|
f45dc29eb2 | ||
|
|
d2f38da094 | ||
|
|
697d51cd93 | ||
|
|
f9b0dca7bd | ||
|
|
03087e020c | ||
|
|
4f75fdcd14 | ||
|
|
031c06419b | ||
|
|
254a08f540 | ||
|
|
76ead916ce | ||
|
|
ab2dafc44a | ||
|
|
325cc4e395 | ||
|
|
c1604eff08 | ||
|
|
77b52a5e69 | ||
|
|
d414c4f500 | ||
|
|
398bc769ce | ||
|
|
49f57a8d0d | ||
|
|
fbe102bada | ||
|
|
2cca490076 | ||
|
|
f7842e3a4b | ||
|
|
38421403d2 | ||
|
|
461dde231c | ||
|
|
0785c522f0 | ||
|
|
2656c6b4ac | ||
|
|
ed5ebe7458 | ||
|
|
d71d6afa34 | ||
|
|
2f8f230f61 | ||
|
|
285388409f | ||
|
|
aff5786ed3 | ||
|
|
f97928c740 | ||
|
|
bca73b8340 | ||
|
|
e67d834156 | ||
|
|
a93f2d8bfe | ||
|
|
8c55294ea9 | ||
|
|
50d8d75d89 | ||
|
|
bcc2d8474c | ||
|
|
e34da1b94d | ||
|
|
717eff71dd | ||
|
|
ad95cbc542 | ||
|
|
b30aff6d4d | ||
|
|
bf9a82ad9a | ||
|
|
c1efcd28f5 | ||
|
|
1fa9409554 | ||
|
|
adcd2e38e9 | ||
|
|
c19fb5656b | ||
|
|
74939b8b8d | ||
|
|
29a229724b | ||
|
|
a9fafc32a8 | ||
|
|
2de227a88b | ||
|
|
31ad140d20 | ||
|
|
bcf4e56fe0 | ||
|
|
1834ca3820 | ||
|
|
ad4a4120b7 | ||
|
|
0800f7ba56 | ||
|
|
36576babe8 | ||
|
|
ba9f5b7d95 | ||
|
|
11a5383604 | ||
|
|
d991606493 | ||
|
|
14048354d5 | ||
|
|
94b689e19d | ||
|
|
8066100f53 | ||
|
|
f60c22628a | ||
|
|
53e608cbc4 | ||
|
|
d10e73ffd7 | ||
|
|
1e75841036 | ||
|
|
32bf28e7ef | ||
|
|
fd5aeba117 | ||
|
|
24b524040b | ||
|
|
e533c3f33b | ||
|
|
41ab19e1d0 | ||
|
|
77475bdd55 | ||
|
|
0c70e80d47 | ||
|
|
5aa4592f0c | ||
|
|
855b73de87 | ||
|
|
136f4d3b0d | ||
|
|
714edcb8d9 | ||
|
|
a6b6a61775 | ||
|
|
39c9a6dfed | ||
|
|
561df8d9a2 | ||
|
|
48a20a6137 | ||
|
|
8ef0fbc294 | ||
|
|
51a21823f9 | ||
|
|
7a68331fcd | ||
|
|
d896d6393b | ||
|
|
6d531ed0a6 | ||
|
|
06df7c1b31 | ||
|
|
2b108483ce | ||
|
|
23c745d335 | ||
|
|
eb361626cb | ||
|
|
b0f8ca556b | ||
|
|
e41e28744f | ||
|
|
e862f04527 | ||
|
|
42519db55d | ||
|
|
019cb77b84 | ||
|
|
296f6a9217 | ||
|
|
d688ed2553 | ||
|
|
b4c0b03694 | ||
|
|
e721c122d3 | ||
|
|
8cd0d0040e | ||
|
|
e5542b027b | ||
|
|
5aa9cf2fcf | ||
|
|
a924869096 | ||
|
|
8c08b062d0 | ||
|
|
96b06e8bb4 | ||
|
|
a8efffa969 | ||
|
|
ef0215fcf2 | ||
|
|
82beeea619 | ||
|
|
a18a3813fb | ||
|
|
b8180f4069 | ||
|
|
94b00cc762 | ||
|
|
e4701e7c86 | ||
|
|
fc625b8a8e | ||
|
|
703f125882 | ||
|
|
4581b24b48 | ||
|
|
1d84821d93 | ||
|
|
07f607ec4c | ||
|
|
c3833c6c03 | ||
|
|
65008e2d3c | ||
|
|
d33a97b663 | ||
|
|
6f9fea7fd5 | ||
|
|
c8d978f4e9 | ||
|
|
558f889aae | ||
|
|
937268eb3e | ||
|
|
8be7ece1f5 | ||
|
|
6127da58f2 | ||
|
|
15e4e7e9da | ||
|
|
d484d4e129 | ||
|
|
985019ab64 | ||
|
|
870c9a7a08 | ||
|
|
2a6341c08c | ||
|
|
78e7873e92 | ||
|
|
7ecec3eb94 | ||
|
|
f4facc4e10 | ||
|
|
edffc2a291 | ||
|
|
c30a25e64c | ||
|
|
b9a9f54c45 | ||
|
|
f57d2c3277 | ||
|
|
11a1ae59f4 | ||
|
|
cd1129b9b8 | ||
|
|
216cabc563 | ||
|
|
5dd4f7604f | ||
|
|
94ce1ea451 | ||
|
|
f3697a0d5c | ||
|
|
8f0d40a1dd | ||
|
|
a138a52021 | ||
|
|
518a9b8d8c | ||
|
|
64ae0525cf | ||
|
|
dc88a937f0 | ||
|
|
ac93e2aea7 | ||
|
|
560e938038 | ||
|
|
2a5d71971c | ||
|
|
a59e65336d | ||
|
|
55ef7bc012 | ||
|
|
d3f1d094f7 | ||
|
|
421fb2a829 | ||
|
|
517e58d3dc | ||
|
|
0eaa650e32 | ||
|
|
4fbe572c02 | ||
|
|
7c0ce909ed | ||
|
|
f95157297e | ||
|
|
89993dd757 | ||
|
|
75e7c30594 | ||
|
|
5032a9f13c | ||
|
|
4f34062623 | ||
|
|
255f5bd73f | ||
|
|
0ec847bbe7 | ||
|
|
08bc076a0a | ||
|
|
2c014256f7 | ||
|
|
488e822c8d | ||
|
|
2234c115f2 | ||
|
|
b23b3f1d99 | ||
|
|
46b249f5ce | ||
|
|
b1b42aeb9c | ||
|
|
56c867edfa | ||
|
|
40c1a7e91f | ||
|
|
9739dae794 | ||
|
|
81793de030 | ||
|
|
a5157e69b1 | ||
|
|
101a65378c | ||
|
|
91ef298e7d | ||
|
|
739234afb9 | ||
|
|
4ecefb5017 | ||
|
|
444008aabc | ||
|
|
45857bc606 | ||
|
|
da9b2e25f6 | ||
|
|
fc508f9494 | ||
|
|
3573bd4d87 | ||
|
|
c7ee14e786 | ||
|
|
fac56bae32 | ||
|
|
c5c1698cde | ||
|
|
4df7daec82 | ||
|
|
26d04ff037 | ||
|
|
5713481838 | ||
|
|
74c9c1afa9 | ||
|
|
e159f04df8 | ||
|
|
4a21b6f168 | ||
|
|
fe16cce405 | ||
|
|
8ba02b6f4c | ||
|
|
f5191ec222 | ||
|
|
144126789c | ||
|
|
8dcfc9849e | ||
|
|
b28fb6654c | ||
|
|
9294c3284c | ||
|
|
9278dc0666 | ||
|
|
af519d73ae | ||
|
|
3a326793fd | ||
|
|
f31a14b793 | ||
|
|
7886326aa8 | ||
|
|
31cc03f8e6 | ||
|
|
cf7449c525 | ||
|
|
b0cdbf5b22 | ||
|
|
231e378157 | ||
|
|
431d8fe7c7 | ||
|
|
9ee4d6c697 | ||
|
|
3f14d7a54a | ||
|
|
52acb3fcac | ||
|
|
a8d08a9478 | ||
|
|
c691aa3e32 | ||
|
|
430e570629 | ||
|
|
65dc4f1186 | ||
|
|
6b320a00a0 | ||
|
|
22be109956 | ||
|
|
4bb790fb5d | ||
|
|
7d32ec5d28 | ||
|
|
20e7ec96ae | ||
|
|
2e563e0fa8 | ||
|
|
cbd0a8f4b5 | ||
|
|
ecbe577be3 | ||
|
|
84db436e3b | ||
|
|
904c6ed853 | ||
|
|
186e07b415 | ||
|
|
4ab63d3d8c | ||
|
|
696ef7aecc | ||
|
|
9603f2520b | ||
|
|
a5a806f7ee | ||
|
|
fa294e8603 | ||
|
|
97d2f755c4 | ||
|
|
83536ab7d1 | ||
|
|
6cdbc01208 | ||
|
|
833903e8ec | ||
|
|
c53383a316 | ||
|
|
dfc35699ea | ||
|
|
b7a7c816df | ||
|
|
090f036205 | ||
|
|
8738e93dc0 | ||
|
|
ee2bee88ee | ||
|
|
6ffd38d25e | ||
|
|
250273cf1a | ||
|
|
bc15f7b7aa | ||
|
|
7c3040c624 | ||
|
|
c584b55488 | ||
|
|
5a2abd34ce | ||
|
|
14eb593af3 | ||
|
|
b2b7bc3b77 | ||
|
|
fddbf1f94c | ||
|
|
5d5f6cc60c | ||
|
|
ae64c19f20 | ||
|
|
e5abc065aa | ||
|
|
4ce265b105 | ||
|
|
154e99f2ba | ||
|
|
dab450be32 | ||
|
|
a3db621899 | ||
|
|
e26c6d20fe | ||
|
|
a75a2bf533 | ||
|
|
8dcfc3c94a | ||
|
|
19c4027194 | ||
|
|
0efd50df26 | ||
|
|
a127c8827a | ||
|
|
dcb5a81735 | ||
|
|
4abdf47923 | ||
|
|
d39dce85b4 | ||
|
|
e736725d35 | ||
|
|
d61a699543 | ||
|
|
320b6c0cd8 | ||
|
|
7cf05075a0 | ||
|
|
3e0959fa1b | ||
|
|
d87b29b678 | ||
|
|
2c16a3c0e8 | ||
|
|
dc3d9bb2ab | ||
|
|
fd4ed3909e | ||
|
|
3f29a3d4fa | ||
|
|
1a894b65d4 | ||
|
|
6e82193175 | ||
|
|
32ac1e04ec | ||
|
|
a47a9ecad1 | ||
|
|
d07aef725e | ||
|
|
b5eb08ad09 | ||
|
|
3ce7d7a28c | ||
|
|
9da13d4ff8 | ||
|
|
7d49e49e74 | ||
|
|
0689304cff | ||
|
|
8dd4972fda | ||
|
|
51436cc3a3 | ||
|
|
b168b8f03f | ||
|
|
9e9e7e95ee | ||
|
|
c805f0cdcb | ||
|
|
e4bbba2b15 | ||
|
|
3a5af7fb61 | ||
|
|
34f2d50e29 | ||
|
|
40d0ca7963 | ||
|
|
095f348172 | ||
|
|
67c062e45e | ||
|
|
4516e7bdcb | ||
|
|
90d72c214e | ||
|
|
8fd6c8bc02 | ||
|
|
863cd6fcba | ||
|
|
38fda265e8 | ||
|
|
72058bfbcc | ||
|
|
74e23a7fa2 | ||
|
|
6372f671ed | ||
|
|
8501ca2ea0 | ||
|
|
1264557f0e | ||
|
|
f34cd24f80 | ||
|
|
9cd5e97596 | ||
|
|
9f59be3224 | ||
|
|
dea644bbd6 | ||
|
|
8bcb835aa4 | ||
|
|
eec3532955 | ||
|
|
8424c7a747 | ||
|
|
464176d511 | ||
|
|
e8a1d135e2 | ||
|
|
b707b5e2a4 | ||
|
|
c987fd8c53 | ||
|
|
d083554dff | ||
|
|
ec3af2c5cb | ||
|
|
f857d4aff7 | ||
|
|
39d6ef884a | ||
|
|
492d1f24c8 | ||
|
|
60e5a32d27 | ||
|
|
f8d0055503 | ||
|
|
8baaf64a72 | ||
|
|
6ae69e0df0 | ||
|
|
92ca76721a | ||
|
|
6af2e3fc10 | ||
|
|
9bec3ee48e | ||
|
|
17ca9d9da7 | ||
|
|
c1711243f0 | ||
|
|
fdfd12716e | ||
|
|
dc0d945f28 | ||
|
|
96465a52ee | ||
|
|
512fa6e601 | ||
|
|
12d43e2967 | ||
|
|
e8648416b8 | ||
|
|
b971834d10 | ||
|
|
94ee9effe6 | ||
|
|
81bc13e066 | ||
|
|
1297da380e | ||
|
|
4ee3b28ecb | ||
|
|
757f8a6323 | ||
|
|
a25b06ecfc | ||
|
|
6b703b8d6a | ||
|
|
c97d0d1220 | ||
|
|
7520d9c7b9 | ||
|
|
2577214517 | ||
|
|
8e7bd43016 | ||
|
|
e7b74c57f3 | ||
|
|
cfdd4296a8 | ||
|
|
3407509ed7 | ||
|
|
3ac62dda51 | ||
|
|
3465b592e7 | ||
|
|
ca499a5495 | ||
|
|
8a1d832f80 | ||
|
|
758df26582 | ||
|
|
6ae558b541 | ||
|
|
68f53540df | ||
|
|
48ba9c9bc1 | ||
|
|
245deb2abe | ||
|
|
549ea0d7ba | ||
|
|
94d1112c55 | ||
|
|
0c47227144 | ||
|
|
a2505078da | ||
|
|
35532a63fe | ||
|
|
514ab6eed2 | ||
|
|
c41e3a8e68 | ||
|
|
7d71340241 | ||
|
|
40bcc0bed8 | ||
|
|
74009e2be5 | ||
|
|
40871ab1cc | ||
|
|
2fc4c7e335 | ||
|
|
da8263b3f6 | ||
|
|
12db7c4bc1 | ||
|
|
db3ef37771 | ||
|
|
7f32558e08 | ||
|
|
228ac78397 | ||
|
|
b6656a1525 | ||
|
|
84ec17964e | ||
|
|
ef5dc6cd2b | ||
|
|
84e6aca5c5 | ||
|
|
ebd0987376 | ||
|
|
20baf4f5b6 | ||
|
|
335a0fe768 | ||
|
|
b25ebf4bdb | ||
|
|
804bb44eda | ||
|
|
1b15896e8b | ||
|
|
055fbe1d87 | ||
|
|
648e5d62ba | ||
|
|
49de20aa5c | ||
|
|
13d534e89a | ||
|
|
1944dc8b5f | ||
|
|
f2ca2d50b5 | ||
|
|
b361fb5898 | ||
|
|
8d1faa0dbc | ||
|
|
77baa2df15 | ||
|
|
a229cb4676 | ||
|
|
682ed18123 | ||
|
|
3aae59c224 | ||
|
|
6f3505bf6b | ||
|
|
bfdc48e320 | ||
|
|
fcda8beb1c | ||
|
|
d0647afae5 | ||
|
|
a6383cec51 | ||
|
|
44fd5ff451 | ||
|
|
ea34f37d43 | ||
|
|
23dcc2c7f3 | ||
|
|
91f7d127ea | ||
|
|
43c1245396 | ||
|
|
43288bc4f2 | ||
|
|
2e22d6ef99 | ||
|
|
6509b6e742 | ||
|
|
d2ce0042b3 | ||
|
|
0dcb63ff5e | ||
|
|
bebbac1bd8 | ||
|
|
a1870a62cf | ||
|
|
1ef1a77421 | ||
|
|
98819f92e3 | ||
|
|
ebce70eba1 | ||
|
|
ed257b982a | ||
|
|
1b7877f6ed | ||
|
|
7500b0564c | ||
|
|
0c992ece3b | ||
|
|
e124249a8b | ||
|
|
d950d6af52 | ||
|
|
55abcfeef6 | ||
|
|
49b3712891 | ||
|
|
b9a8b22728 | ||
|
|
65f8e86e41 | ||
|
|
9780f22866 | ||
|
|
46b2b99f63 | ||
|
|
c92f54102e | ||
|
|
964d5f88cc | ||
|
|
ad7e9d88fb | ||
|
|
3ace7817b4 | ||
|
|
0de35ca8f0 | ||
|
|
80b6cf77b0 | ||
|
|
79b4bf4ac2 | ||
|
|
ab6b510408 | ||
|
|
ab52ca01ad | ||
|
|
64b72f8d3a | ||
|
|
ffc9806e6d | ||
|
|
984fb41b98 | ||
|
|
a1e05c62ae | ||
|
|
076e884873 | ||
|
|
2f6fbbd706 | ||
|
|
4924ac8099 | ||
|
|
7962029bdc | ||
|
|
f83f837de7 | ||
|
|
48b719cf68 | ||
|
|
96afa4530c | ||
|
|
270a8a26fa | ||
|
|
92a50f731c | ||
|
|
76d6838223 | ||
|
|
0bfb9d476c | ||
|
|
91bb1b2de6 | ||
|
|
810adadf2e | ||
|
|
8da712ea61 | ||
|
|
56cfb8036f | ||
|
|
f332dd810e |
13
.clang_complete
Normal file
13
.clang_complete
Normal file
@@ -0,0 +1,13 @@
|
||||
-DWITH_SERVER=1
|
||||
-DWITH_GSSAPI=1
|
||||
-DWITH_ZLIB=1
|
||||
-DWITH_SFTP=1
|
||||
-DWITH_SSH1=1
|
||||
-DWITH_PCAP=1
|
||||
-DHAVE_ECDH=1
|
||||
-DHAVE_ECC=1
|
||||
-Iinclude/libssh
|
||||
-Iinclude
|
||||
-Ibuild
|
||||
-Itests
|
||||
-Isrc
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,6 +1,9 @@
|
||||
*.a
|
||||
*.o
|
||||
.*
|
||||
*.swp
|
||||
*~$
|
||||
build
|
||||
obj
|
||||
cscope.*
|
||||
tags
|
||||
build
|
||||
|
||||
2
AUTHORS
2
AUTHORS
@@ -1,7 +1,7 @@
|
||||
Author(s):
|
||||
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)
|
||||
|
||||
|
||||
105
CMakeLists.txt
105
CMakeLists.txt
@@ -1,14 +1,14 @@
|
||||
project(libssh C)
|
||||
|
||||
# Required cmake version
|
||||
cmake_minimum_required(VERSION 2.6.0)
|
||||
cmake_minimum_required(VERSION 2.8.5)
|
||||
|
||||
# global needed variables
|
||||
set(APPLICATION_NAME ${PROJECT_NAME})
|
||||
|
||||
set(APPLICATION_VERSION_MAJOR "0")
|
||||
set(APPLICATION_VERSION_MINOR "4")
|
||||
set(APPLICATION_VERSION_PATCH "6")
|
||||
set(APPLICATION_VERSION_MINOR "7")
|
||||
set(APPLICATION_VERSION_PATCH "0")
|
||||
|
||||
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
|
||||
|
||||
@@ -19,7 +19,7 @@ set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINO
|
||||
# Increment AGE. Set REVISION to 0
|
||||
# If the source code was changed, but there were no interface changes:
|
||||
# Increment REVISION.
|
||||
set(LIBRARY_VERSION "4.1.3")
|
||||
set(LIBRARY_VERSION "4.4.0")
|
||||
set(LIBRARY_SOVERSION "4")
|
||||
|
||||
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
|
||||
@@ -29,6 +29,7 @@ set(CMAKE_MODULE_PATH
|
||||
|
||||
# add definitions
|
||||
include(DefineCMakeDefaults)
|
||||
include(DefinePlatformDefaults)
|
||||
include(DefineCompilerFlags)
|
||||
include(DefineInstallationPaths)
|
||||
include(DefineOptions.cmake)
|
||||
@@ -38,15 +39,13 @@ include(CPackConfig.cmake)
|
||||
include(MacroEnsureOutOfSourceBuild)
|
||||
macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out of source build. Please create a separate build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there.")
|
||||
|
||||
# add macros
|
||||
include(MacroAddPlugin)
|
||||
include(MacroCopyFile)
|
||||
|
||||
# search for libraries
|
||||
find_package(ZLIB REQUIRED)
|
||||
if (WITH_ZLIB)
|
||||
find_package(ZLIB REQUIRED)
|
||||
endif (WITH_ZLIB)
|
||||
|
||||
if (WITH_GCRYPT)
|
||||
find_package(GCrypt REQUIRED)
|
||||
find_package(GCrypt 1.5.0 REQUIRED)
|
||||
if (NOT GCRYPT_FOUND)
|
||||
message(FATAL_ERROR "Could not find GCrypt")
|
||||
endif (NOT GCRYPT_FOUND)
|
||||
@@ -60,6 +59,21 @@ else (WITH_GCRYPT)
|
||||
endif (NOT OPENSSL_FOUND)
|
||||
endif(WITH_GCRYPT)
|
||||
|
||||
# Find out if we have threading available
|
||||
set(CMAKE_THREAD_PREFER_PTHREADS ON)
|
||||
find_package(Threads)
|
||||
|
||||
if (WITH_GSSAPI)
|
||||
find_package(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
|
||||
include(ConfigureChecks.cmake)
|
||||
configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
@@ -67,12 +81,71 @@ configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
# check subdirectories
|
||||
add_subdirectory(doc)
|
||||
add_subdirectory(include)
|
||||
add_subdirectory(libssh)
|
||||
add_subdirectory(src)
|
||||
|
||||
# build samples
|
||||
include_directories(${CMAKE_SOURCE_DIR}/include)
|
||||
# pkg-config file
|
||||
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(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libssh.pc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libssh_threads.pc
|
||||
DESTINATION
|
||||
${LIB_INSTALL_DIR}/pkgconfig
|
||||
COMPONENT
|
||||
pkgconfig
|
||||
)
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
add_subdirectory(examples)
|
||||
endif (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
# cmake config files
|
||||
set(LIBSSH_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}ssh${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||
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(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
|
||||
DESTINATION
|
||||
${CMAKE_INSTALL_DIR}/${PROJECT_NAME}
|
||||
COMPONENT
|
||||
devel
|
||||
)
|
||||
|
||||
|
||||
# in tree build settings
|
||||
configure_file(libssh-build-tree-settings.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libssh-build-tree-settings.cmake @ONLY)
|
||||
|
||||
if (WITH_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif (WITH_EXAMPLES)
|
||||
|
||||
if (WITH_TESTING)
|
||||
find_package(CMocka REQUIRED)
|
||||
include(AddCMockaTest)
|
||||
add_subdirectory(tests)
|
||||
endif (WITH_TESTING)
|
||||
|
||||
|
||||
message(STATUS "********************************************")
|
||||
message(STATUS "********** ${PROJECT_NAME} build options : **********")
|
||||
|
||||
message(STATUS "zlib support: ${WITH_ZLIB}")
|
||||
message(STATUS "libgcrypt support: ${WITH_GCRYPT}")
|
||||
message(STATUS "libnacl support: ${WITH_NACL}")
|
||||
message(STATUS "SSH-1 support: ${WITH_SSH1}")
|
||||
message(STATUS "SFTP support: ${WITH_SFTP}")
|
||||
message(STATUS "Server support : ${WITH_SERVER}")
|
||||
message(STATUS "GSSAPI support : ${WITH_GSSAPI}")
|
||||
message(STATUS "Pcap debugging support : ${WITH_PCAP}")
|
||||
message(STATUS "With static library: ${WITH_STATIC_LIB}")
|
||||
message(STATUS "Unit testing: ${WITH_TESTING}")
|
||||
message(STATUS "Client code Unit testing: ${WITH_CLIENT_TESTING}")
|
||||
if (WITH_INTERNAL_DOC)
|
||||
message(STATUS "Internal documentation generation")
|
||||
else (WITH_INTERNAL_DOC)
|
||||
message(STATUS "Public API documentation generation")
|
||||
endif (WITH_INTERNAL_DOC)
|
||||
message(STATUS "Benchmarks: ${WITH_BENCHMARKS}")
|
||||
message(STATUS "********************************************")
|
||||
|
||||
|
||||
@@ -11,15 +11,15 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
|
||||
|
||||
|
||||
### versions
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "0")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "4")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "6")
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${APPLICATION_VERSION_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${APPLICATION_VERSION_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${APPLICATION_VERSION_PATCH})
|
||||
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
|
||||
|
||||
|
||||
### source generator
|
||||
set(CPACK_SOURCE_GENERATOR "TGZ")
|
||||
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}")
|
||||
|
||||
if (WIN32)
|
||||
@@ -27,12 +27,12 @@ if (WIN32)
|
||||
|
||||
### nsis generator
|
||||
find_package(NSIS)
|
||||
if (HAVE_NSIS)
|
||||
if (NSIS_MAKE)
|
||||
set(CPACK_GENERATOR "${CPACK_GENERATOR};NSIS")
|
||||
set(CPACK_NSIS_DISPLAY_NAME "The SSH Library")
|
||||
set(CPACK_NSIS_COMPRESSOR "/SOLID zlib")
|
||||
set(CPACK_NSIS_MENU_LINKS "http://www.libssh.org/" "libssh homepage")
|
||||
endif (HAVE_NSIS)
|
||||
endif (NSIS_MAKE)
|
||||
endif (WIN32)
|
||||
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "libssh")
|
||||
|
||||
9
CTestConfig.cmake
Normal file
9
CTestConfig.cmake
Normal file
@@ -0,0 +1,9 @@
|
||||
set(UPDATE_TYPE "true")
|
||||
|
||||
set(CTEST_PROJECT_NAME "libssh")
|
||||
set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
|
||||
|
||||
set(CTEST_DROP_METHOD "https")
|
||||
set(CTEST_DROP_SITE "test.libssh.org")
|
||||
set(CTEST_DROP_LOCATION "/submit.php?project=libssh")
|
||||
set(CTEST_DROP_SITE_CDASH TRUE)
|
||||
162
ChangeLog
162
ChangeLog
@@ -1,6 +1,168 @@
|
||||
ChangeLog
|
||||
==========
|
||||
|
||||
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 userauth API.
|
||||
* Added ssh_get_publickey_hash() function.
|
||||
* Added ssh_get_poll_flags() function.
|
||||
* Added gssapi-mic userauth.
|
||||
* Added GSSAPIServerIdentity option.
|
||||
* Added GSSAPIClientIdentity option.
|
||||
* Added GSSAPIDelegateCredentials option.
|
||||
* Added new callback based server API.
|
||||
* Added Elliptic Curve DSA (ECDSA) support (with OpenSSL).
|
||||
* Added Elliptic Curve Diffie Hellman (ECDH) support.
|
||||
* Added Curve25519 for ECDH key exchange.
|
||||
* Added improved logging system.
|
||||
* Added SSH-agent forwarding.
|
||||
* Added key-reexchange.
|
||||
* Added more unit tests.
|
||||
* Improved documentation.
|
||||
* Fixed timeout handling.
|
||||
|
||||
version 0.5.5 (released 2013-07-26)
|
||||
* BUG 103: Fix ProxyCommand parsing.
|
||||
* Fix setting -D_FORTIFY_SOURCE=2.
|
||||
* Fix pollset error return if emtpy.
|
||||
* Fix NULL pointer checks in channel functions.
|
||||
* Several bugfixes.
|
||||
|
||||
version 0.5.4 (released 2013-01-22)
|
||||
* CVE-2013-0176 - NULL dereference leads to denial of service
|
||||
* Fixed several NULL pointer dereferences in SSHv1.
|
||||
* Fixed a free crash bug in options parsing.
|
||||
|
||||
version 0.5.3 (released 2012-11-20)
|
||||
* CVE-2012-4559 Fixed multiple double free() flaws.
|
||||
* CVE-2012-4560 Fixed multiple buffer overflow flaws.
|
||||
* CVE-2012-4561 Fixed multiple invalid free() flaws.
|
||||
* BUG #84 - Fix bug in sftp_mkdir not returning on error.
|
||||
* BUG #85 - Fixed a possible channel infinite loop if the connection dropped.
|
||||
* BUG #88 - Added missing channel request_state and set it to accepted.
|
||||
* BUG #89 - Reset error state to no error on successful SSHv1 authentiction.
|
||||
* Fixed a possible use after free in ssh_free().
|
||||
* Fixed multiple possible NULL pointer dereferences.
|
||||
* Fixed multiple memory leaks in error paths.
|
||||
* Fixed timeout handling.
|
||||
* Fixed regression in pre-connected socket setting.
|
||||
* Handle all unknown global messages.
|
||||
|
||||
version 0.5.2 (released 2011-09-17)
|
||||
* Increased window size x10.
|
||||
* Fixed SSHv1.
|
||||
* Fixed bugged lists.
|
||||
* Fixed use-after-free + inconsistent callbacks call in poll.
|
||||
* Fixed scp documentation.
|
||||
* Fixed possible infinite loop in channel_read().
|
||||
* Fixed handling of short reads of sftp_async_read().
|
||||
* Fixed handling request service timeout in blocking mode.
|
||||
* Fixed ssh_auth_list() documentation.
|
||||
* Fixed incorrect return values in ssh_channel_write().
|
||||
* Fixed an infinite loop in the termination callback.
|
||||
* Fixed handling of SSH_AGAIN in channel_open().
|
||||
* Fixed "status -5 inflating zlib packet"
|
||||
|
||||
version 0.5.1 (released 2011-08-09)
|
||||
* Added checks for NULL pointers in string.c.
|
||||
* Set the channel max packet size to 32768.
|
||||
* Don't (de)compress empty buffers.
|
||||
* Fixed ssh_scp_write so it works when doing recursive copy.
|
||||
* Fixed another source of endless wait.
|
||||
* Fixed an endless loop in case of a channel_open error.
|
||||
* Fixed session timeout handling.
|
||||
* Fixed ssh_channel_from_local() loop.
|
||||
* Fixed permissions of scp example when we copy a file.
|
||||
* Workaround ssh_get_user_home_dir on LDAP users.
|
||||
* Added pkg-config support for libssh_threads.
|
||||
* Fixed compilation without server and sftp modes.
|
||||
* Fix static .lib overwriting on Windows.
|
||||
|
||||
version 0.5.0 (released 2011-06-01)
|
||||
* Added ssh_ prefix to all functions.
|
||||
* Added complete Windows support.
|
||||
* Added improved server support.
|
||||
* Added unit tests for a lot of functions.
|
||||
* Added asynchronous service request.
|
||||
* Added a multiplatform ssh_getpass() function.
|
||||
* Added a tutorial.
|
||||
* Added a lot of documentation.
|
||||
* Fixed a lot of bugs.
|
||||
* Fixed several memory leaks.
|
||||
|
||||
version 0.4.8 (released 2011-01-15)
|
||||
* Fixed memory leaks in session signing.
|
||||
* Fixed memory leak in ssh_print_hexa.
|
||||
* Fixed problem with ssh_connect w/ timeout and fd > 1024.
|
||||
* Fixed some warnings on OS/2.
|
||||
* Fixed installation path for OS/2.
|
||||
|
||||
version 0.4.7 (released 2010-12-28)
|
||||
* Fixed a possible memory leak in ssh_get_user_home().
|
||||
* Fixed a memory leak in sftp_xstat.
|
||||
* Fixed uninitialized fd->revents member.
|
||||
* Fixed timout value in ssh_channel_accept().
|
||||
* Fixed length checks in ssh_analyze_banner().
|
||||
* Fixed a possible data overread and crash bug.
|
||||
* Fixed setting max_fd which breaks ssh_select().
|
||||
* Fixed some pedantic build warnings.
|
||||
* Fixed a memory leak with session->bindaddr.
|
||||
|
||||
version 0.4.6 (released 2010-09-03)
|
||||
* Added a cleanup function to free the ws2_32 library.
|
||||
* Fixed build with gcc 3.4.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
include(CheckIncludeFile)
|
||||
include(CheckIncludeFiles)
|
||||
include(CheckSymbolExists)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckLibraryExists)
|
||||
@@ -18,44 +17,52 @@ set(BINARYDIR ${CMAKE_BINARY_DIR})
|
||||
set(SOURCEDIR ${CMAKE_SOURCE_DIR})
|
||||
|
||||
function(COMPILER_DUMPVERSION _OUTPUT_VERSION)
|
||||
# Remove whitespaces from the argument.
|
||||
# This is needed for CC="ccache gcc" cmake ..
|
||||
string(REPLACE " " "" _C_COMPILER_ARG "${CMAKE_C_COMPILER_ARG1}")
|
||||
|
||||
execute_process(
|
||||
COMMAND
|
||||
${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1} -dumpversion
|
||||
${CMAKE_C_COMPILER} ${_C_COMPILER_ARG} -dumpversion
|
||||
OUTPUT_VARIABLE _COMPILER_VERSION
|
||||
)
|
||||
|
||||
string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2"
|
||||
_COMPILER_VERSION ${_COMPILER_VERSION})
|
||||
_COMPILER_VERSION "${_COMPILER_VERSION}")
|
||||
|
||||
set(${_OUTPUT_VERSION} ${_COMPILER_VERSION} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
|
||||
if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
|
||||
compiler_dumpversion(GNUCC_VERSION)
|
||||
if (NOT GNUCC_VERSION EQUAL 34)
|
||||
check_c_compiler_flag("-fvisibility=hidden" WITH_VISIBILITY_HIDDEN)
|
||||
set(CMAKE_REQUIRED_FLAGS "-fvisibility=hidden")
|
||||
check_c_source_compiles(
|
||||
"void __attribute__((visibility(\"default\"))) test() {}
|
||||
int main(void){ return 0; }
|
||||
" WITH_VISIBILITY_HIDDEN)
|
||||
set(CMAKE_REQUIRED_FLAGS "")
|
||||
endif (NOT GNUCC_VERSION EQUAL 34)
|
||||
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
|
||||
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
|
||||
|
||||
# HEADER FILES
|
||||
check_include_file(argp.h HAVE_ARGP_H)
|
||||
check_include_file(pty.h HAVE_PTY_H)
|
||||
check_include_file(terminos.h HAVE_TERMIOS_H)
|
||||
check_include_file(utmp.h HAVE_UTMP_H)
|
||||
check_include_file(termios.h HAVE_TERMIOS_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)
|
||||
|
||||
if (WIN32)
|
||||
check_include_files("winsock2.h;ws2tcpip.h;wspiapi.h" HAVE_WSPIAPI_H)
|
||||
if (NOT HAVE_WSPIAPI_H)
|
||||
message(STATUS "WARNING: Without wspiapi.h (or dependencies), this build will only work on Windows XP and newer versions")
|
||||
message(STATUS "WARNING: Without wspiapi.h, this build will only work on Windows XP and newer versions")
|
||||
endif (NOT HAVE_WSPIAPI_H)
|
||||
check_include_files("winsock2.h;ws2tcpip.h" HAVE_WS2TCPIP_H)
|
||||
if (NOT HAVE_WS2TCPIP_H)
|
||||
message(ERROR "WARNING: Does not have ws2tcpip.h or winsock2.h")
|
||||
endif (NOT HAVE_WS2TCPIP_H)
|
||||
if (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
|
||||
set(HAVE_GETADDRINFO TRUE)
|
||||
set(HAVE_GETHOSTBYNAME TRUE)
|
||||
endif (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
|
||||
|
||||
set(HAVE_SELECT TRUE)
|
||||
endif (WIN32)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
||||
@@ -67,47 +74,95 @@ check_include_file(openssl/blowfish.h HAVE_OPENSSL_BLOWFISH_H)
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
||||
check_include_file(openssl/des.h HAVE_OPENSSL_DES_H)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
||||
check_include_file(openssl/ecdh.h HAVE_OPENSSL_ECDH_H)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
||||
check_include_file(openssl/ec.h HAVE_OPENSSL_EC_H)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
||||
check_include_file(openssl/ecdsa.h HAVE_OPENSSL_ECDSA_H)
|
||||
|
||||
if (CMAKE_HAVE_PTHREAD_H)
|
||||
set(HAVE_PTHREAD_H 1)
|
||||
endif (CMAKE_HAVE_PTHREAD_H)
|
||||
|
||||
if (NOT WITH_GCRYPT)
|
||||
if (HAVE_OPENSSL_EC_H AND HAVE_OPENSSL_ECDSA_H)
|
||||
set(HAVE_OPENSSL_ECC 1)
|
||||
endif (HAVE_OPENSSL_EC_H AND HAVE_OPENSSL_ECDSA_H)
|
||||
|
||||
if (HAVE_OPENSSL_ECC)
|
||||
set(HAVE_ECC 1)
|
||||
endif (HAVE_OPENSSL_ECC)
|
||||
endif (NOT WITH_GCRYPT)
|
||||
|
||||
# FUNCTIONS
|
||||
|
||||
check_function_exists(isblank HAVE_ISBLANK)
|
||||
check_function_exists(strncpy HAVE_STRNCPY)
|
||||
check_function_exists(vsnprintf HAVE_VSNPRINTF)
|
||||
check_function_exists(snprintf HAVE_SNPRINTF)
|
||||
|
||||
if (WIN32)
|
||||
check_function_exists(_strtoui64 HAVE__STRTOUI64)
|
||||
|
||||
check_function_exists(_vsnprintf_s HAVE__VSNPRINTF_S)
|
||||
check_function_exists(_vsnprintf HAVE__VSNPRINTF)
|
||||
check_function_exists(_snprintf HAVE__SNPRINTF)
|
||||
check_function_exists(_snprintf_s HAVE__SNPRINTF_S)
|
||||
|
||||
if (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
|
||||
check_symbol_exists(ntohll winsock2.h HAVE_NTOHLL)
|
||||
check_symbol_exists(htonll winsock2.h HAVE_HTONLL)
|
||||
|
||||
set(CMAKE_REQUIRED_LIBRARIES ws2_32)
|
||||
check_symbol_exists(select "winsock2.h;ws2tcpip.h" HAVE_SELECT)
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
if (UNIX)
|
||||
# libsocket (Solaris)
|
||||
check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET)
|
||||
if (HAVE_LIBSOCKET)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} socket)
|
||||
endif (HAVE_LIBSOCKET)
|
||||
# libnsl (Solaris)
|
||||
check_library_exists(nsl gethostbyname "" HAVE_LIBNSL)
|
||||
if (HAVE_LIBNSL)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} nsl)
|
||||
endif (HAVE_LIBNSL)
|
||||
# libresolv
|
||||
check_library_exists(resolv hstrerror "" HAVE_LIBRESOLV)
|
||||
if (HAVE_LIBRESOLV)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} resolv)
|
||||
endif (HAVE_LIBRESOLV)
|
||||
check_library_exists(rt nanosleep "" HAVE_LIBRT)
|
||||
# librt
|
||||
if (HAVE_LIBRT)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} rt)
|
||||
endif (HAVE_LIBRT)
|
||||
|
||||
check_function_exists(getaddrinfo HAVE_GETADDRINFO)
|
||||
check_function_exists(gethostbyname HAVE_GETHOSTBYNAME)
|
||||
check_function_exists(poll HAVE_POLL)
|
||||
check_function_exists(select HAVE_SELECT)
|
||||
check_function_exists(cfmakeraw HAVE_CFMAKERAW)
|
||||
check_function_exists(regcomp HAVE_REGCOMP)
|
||||
if (UNIX)
|
||||
if (NOT LINUX)
|
||||
# libsocket (Solaris)
|
||||
check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET)
|
||||
if (HAVE_LIBSOCKET)
|
||||
set(HAVE_GETADDRINFO TRUE)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} socket)
|
||||
endif (HAVE_LIBSOCKET)
|
||||
|
||||
# libnsl/inet_pton (Solaris)
|
||||
check_library_exists(nsl inet_pton "" HAVE_LIBNSL)
|
||||
if (HAVE_LIBNSL)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} nsl)
|
||||
endif (HAVE_LIBNSL)
|
||||
|
||||
# librt
|
||||
check_library_exists(rt nanosleep "" HAVE_LIBRT)
|
||||
endif (NOT LINUX)
|
||||
|
||||
check_library_exists(rt clock_gettime "" HAVE_CLOCK_GETTIME)
|
||||
if (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} rt)
|
||||
endif (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
|
||||
|
||||
check_library_exists(util forkpty "" HAVE_LIBUTIL)
|
||||
check_function_exists(cfmakeraw HAVE_CFMAKERAW)
|
||||
check_function_exists(strtoull HAVE_STRTOULL)
|
||||
check_function_exists(__strtoull HAVE___STRTOULL)
|
||||
endif (UNIX)
|
||||
|
||||
set(LIBSSH_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CACHE INTERNAL "libssh required system libraries")
|
||||
@@ -118,14 +173,71 @@ if (OPENSSL_FOUND)
|
||||
endif (OPENSSL_FOUND)
|
||||
|
||||
if (GCRYPT_FOUND)
|
||||
set(HAVE_LIBGCRYPT 1)
|
||||
set(HAVE_LIBGCRYPT 1)
|
||||
if (GCRYPT_VERSION VERSION_GREATER "1.4.6")
|
||||
#set(HAVE_GCRYPT_ECC 1)
|
||||
#set(HAVE_ECC 1)
|
||||
endif (GCRYPT_VERSION VERSION_GREATER "1.4.6")
|
||||
endif (GCRYPT_FOUND)
|
||||
|
||||
if (Z_LIBRARY)
|
||||
set(HAVE_LIBZ 1)
|
||||
endif (Z_LIBRARY)
|
||||
if (CMAKE_USE_PTHREADS_INIT)
|
||||
set(HAVE_PTHREAD 1)
|
||||
endif (CMAKE_USE_PTHREADS_INIT)
|
||||
|
||||
# OPTIONS
|
||||
check_c_source_compiles("
|
||||
__thread int tls;
|
||||
|
||||
int main(void) {
|
||||
return 0;
|
||||
}" HAVE_GCC_THREAD_LOCAL_STORAGE)
|
||||
|
||||
check_c_source_compiles("
|
||||
__declspec(thread) int tls;
|
||||
|
||||
int main(void) {
|
||||
return 0;
|
||||
}" HAVE_MSC_THREAD_LOCAL_STORAGE)
|
||||
|
||||
check_c_source_compiles("
|
||||
#include <string.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char buf[] = \"This is some content\";
|
||||
|
||||
memset(buf, '\\\\0', sizeof(buf)); __asm__ volatile(\"\" : : \"r\"(&buf) : \"memory\");
|
||||
|
||||
return 0;
|
||||
}" 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)
|
||||
set(DEBUG_CRYPTO 1)
|
||||
endif (WITH_DEBUG_CRYPTO)
|
||||
@@ -134,6 +246,10 @@ if (WITH_DEBUG_CALLTRACE)
|
||||
set(DEBUG_CALLTRACE 1)
|
||||
endif (WITH_DEBUG_CALLTRACE)
|
||||
|
||||
if (WITH_GSSAPI AND NOT GSSAPI_FOUND)
|
||||
set(WITH_GSSAPI 0)
|
||||
endif (WITH_GSSAPI AND NOT GSSAPI_FOUND)
|
||||
|
||||
# ENDIAN
|
||||
if (NOT WIN32)
|
||||
test_big_endian(WORDS_BIGENDIAN)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
option(WITH_LIBZ "Build with ZLIB support" ON)
|
||||
option(WITH_GSSAPI "Build with GSSAPI support" ON)
|
||||
option(WITH_ZLIB "Build with ZLIB support" ON)
|
||||
option(WITH_SSH1 "Build with SSH1 support" OFF)
|
||||
option(WITH_SFTP "Build with SFTP support" ON)
|
||||
option(WITH_SERVER "Build with SSH server support" ON)
|
||||
@@ -6,4 +7,27 @@ option(WITH_STATIC_LIB "Build with a static library" OFF)
|
||||
option(WITH_DEBUG_CRYPTO "Build with cryto debug output" OFF)
|
||||
option(WITH_DEBUG_CALLTRACE "Build with calltrace debug output" ON)
|
||||
option(WITH_GCRYPT "Compile against libgcrypt" OFF)
|
||||
option(WITH_PCAP "Compile with Pcap generation support" OFF)
|
||||
option(WITH_PCAP "Compile with Pcap generation support" ON)
|
||||
option(WITH_INTERNAL_DOC "Compile doxygen internal documentation" OFF)
|
||||
option(WITH_TESTING "Build with unit tests" OFF)
|
||||
option(WITH_CLIENT_TESTING "Build with client tests; requires a running sshd" 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)
|
||||
set(WITH_LIBZ ON)
|
||||
else (WITH_ZLIB)
|
||||
set(WITH_LIBZ OFF)
|
||||
endif (WITH_ZLIB)
|
||||
|
||||
if(WITH_BENCHMARKS)
|
||||
set(WITH_TESTING ON)
|
||||
endif(WITH_BENCHMARKS)
|
||||
|
||||
if (WITH_TESTING)
|
||||
set(WITH_STATIC_LIB ON)
|
||||
endif (WITH_TESTING)
|
||||
|
||||
if (WITH_NACL)
|
||||
set(WITH_NACL ON)
|
||||
endif (WITH_NACL)
|
||||
1272
Doxyfile.internal
1272
Doxyfile.internal
File diff suppressed because it is too large
Load Diff
29
INSTALL
29
INSTALL
@@ -18,16 +18,26 @@ optional:
|
||||
Note that these version numbers are version we know works correctly. If you
|
||||
build and run libssh successfully with an older version, please let us know.
|
||||
|
||||
Windows binaries known to be working:
|
||||
|
||||
- http://www.slproweb.com/products/Win32OpenSSL.html
|
||||
- http://zlib.net/ -> zlib compiled DLL
|
||||
|
||||
We installed them in C:\Program Files
|
||||
|
||||
## Building
|
||||
First, you need to configure the compilation, using CMake. Go inside the
|
||||
`build` dir. Create it if it doesn't exist.
|
||||
|
||||
GNU/Linux and MacOS X:
|
||||
GNU/Linux, MacOS X, MSYS/MinGW:
|
||||
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug ..
|
||||
make
|
||||
|
||||
On Windows you should choose a makefile gernerator with -G or use
|
||||
|
||||
cmake-gui.exe ..
|
||||
|
||||
### CMake standard options
|
||||
Here is a list of the most interesting options provided out of the box by
|
||||
CMake.
|
||||
@@ -47,7 +57,7 @@ Options are defined in the following files:
|
||||
|
||||
They can be changed with the -D option:
|
||||
|
||||
`cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug -DWITH_LIBZ=OFF ..`
|
||||
`cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug -DWITH_ZLIB=OFF ..`
|
||||
|
||||
### Browsing/editing CMake options
|
||||
|
||||
@@ -59,6 +69,17 @@ and MacOS X).
|
||||
- On Windows: run `cmakesetup`
|
||||
- On GNU/Linux and MacOS X: run `ccmake ..`
|
||||
|
||||
### Useful Windows options:
|
||||
|
||||
If you have installed OpenSSL or ZLIB in non standard directories, maybe you
|
||||
want to set:
|
||||
|
||||
OPENSSL_ROOT_DIR
|
||||
|
||||
and
|
||||
|
||||
ZLIB_ROOT_DIR
|
||||
|
||||
## Installing
|
||||
|
||||
If you want to install libssh after compilation run:
|
||||
@@ -67,7 +88,9 @@ If you want to install libssh after compilation run:
|
||||
|
||||
## Running
|
||||
|
||||
The libssh binary can be found in the `build/libssh` directory.
|
||||
The libssh binary can be found in the `build/src` directory.
|
||||
You can use `build/examples/samplessh` which is a sample client to
|
||||
test libssh on UNIX.
|
||||
|
||||
## About this document
|
||||
|
||||
|
||||
119
README
119
README
@@ -1,5 +1,12 @@
|
||||
libssh: the SSH library
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
_ _ _ _
|
||||
(_) (_) (_) (_)
|
||||
(_) _ (_) _ _ _ _ _ (_) _
|
||||
(_) (_) (_)(_) _ (_)(_) (_)(_) (_)(_) _
|
||||
(_) (_) (_) (_) _ (_) _ (_) (_) (_)
|
||||
(_) (_) (_)(_)(_) (_)(_) (_)(_) (_) (_).org
|
||||
|
||||
The SSH library
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
1* Why ?
|
||||
-_-_-_-_-_
|
||||
@@ -29,6 +36,12 @@ http://www.libssh.org
|
||||
4* API Changes !
|
||||
-_-_-_-_-_-_-_-_-_
|
||||
|
||||
Changes between 0.4 and 0.5
|
||||
---------------------------
|
||||
|
||||
We use the ssh_ prefix as namespace for every function now. There is a legacy.h
|
||||
which could be used to get the old function names.
|
||||
|
||||
Changes between 0.3 and 0.4
|
||||
---------------------------
|
||||
|
||||
@@ -46,3 +59,105 @@ header file and it is documented. Example:
|
||||
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
|
||||
|
||||
5* Copyright policy
|
||||
-_-_-_-_-_-_-_-_-_-_
|
||||
|
||||
libssh is a project with distributed copyright ownership, which means we prefer
|
||||
the copyright on parts of libssh to be held by individuals rather than
|
||||
corporations if possible. There are historical legal reasons for this, but one
|
||||
of the best ways to explain it is that it’s much easier to work with
|
||||
individuals who have ownership than corporate legal departments if we ever need
|
||||
to make reasonable compromises with people using and working with libssh.
|
||||
|
||||
We track the ownership of every part of libssh via git, our source code control
|
||||
system, so we know the provenance of every piece of code that is committed to
|
||||
libssh.
|
||||
|
||||
So if possible, if you’re doing libssh changes on behalf of a company who
|
||||
normally owns all the work you do please get them to assign personal copyright
|
||||
ownership of your changes to you as an individual, that makes things very easy
|
||||
for us to work with and avoids bringing corporate legal departments into the
|
||||
picture.
|
||||
|
||||
If you can’t do this we can still accept patches from you owned by your
|
||||
employer under a standard employment contract with corporate copyright
|
||||
ownership. It just requires a simple set-up process first.
|
||||
|
||||
We use a process very similar to the way things are done in the Linux Kernel
|
||||
community, so it should be very easy to get a sign off from your corporate
|
||||
legal department. The only changes we’ve made are to accommodate the license we
|
||||
use, which is LGPLv2 (or later) whereas the Linux kernel uses GPLv2.
|
||||
|
||||
The process is called signing.
|
||||
|
||||
How to sign your work
|
||||
----------------------
|
||||
|
||||
Once you have permission to contribute to libssh from your employer, simply
|
||||
email a copy of the following text from your corporate email address to:
|
||||
|
||||
contributing@libssh.org
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
libssh Developer's Certificate of Origin. Version 1.0
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
(a) The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the appropriate
|
||||
version of the GNU General Public License; or
|
||||
|
||||
(b) The contribution is based upon previous work that, to the best of
|
||||
my knowledge, is covered under an appropriate open source license
|
||||
and I have the right under that license to submit that work with
|
||||
modifications, whether created in whole or in part by me, under
|
||||
the GNU General Public License, in the appropriate version; or
|
||||
|
||||
(c) The contribution was provided directly to me by some other
|
||||
person who certified (a) or (b) and I have not modified it.
|
||||
|
||||
(d) I understand and agree that this project and the contribution are
|
||||
public and that a record of the contribution (including all
|
||||
metadata and personal information I submit with it, including my
|
||||
sign-off) is maintained indefinitely and may be redistributed
|
||||
consistent with the libssh Team's policies and the requirements of
|
||||
the GNU GPL where they are relevant.
|
||||
|
||||
(e) I am granting this work to this project 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 the option of the project) any later version.
|
||||
|
||||
http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
We will maintain a copy of that email as a record that you have the rights to
|
||||
contribute code to libssh under the required licenses whilst working for the
|
||||
company where the email came from.
|
||||
|
||||
Then when sending in a patch via the normal mechanisms described above, add a
|
||||
line that states:
|
||||
|
||||
|
||||
Signed-off-by: Random J Developer <random@developer.example.org>
|
||||
|
||||
|
||||
using your real name and the email address you sent the original email you used
|
||||
to send the libssh Developer’s Certificate of Origin to us (sorry, no
|
||||
pseudonyms or anonymous contributions.)
|
||||
|
||||
That’s it! Such code can then quite happily contain changes that have copyright
|
||||
messages such as:
|
||||
|
||||
|
||||
(c) Example Corporation.
|
||||
|
||||
|
||||
and can be merged into the libssh codebase in the same way as patches from any
|
||||
other individual. You don’t need to send in a copy of the libssh Developer’s
|
||||
Certificate of Origin for each patch, or inside each patch. Just the sign-off
|
||||
message is all that is required once we’ve received the initial email.
|
||||
|
||||
Have fun and happy libssh hacking!
|
||||
|
||||
The libssh Team
|
||||
|
||||
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.
|
||||
118
SubmittingPatches
Normal file
118
SubmittingPatches
Normal file
@@ -0,0 +1,118 @@
|
||||
How to contribute a patch to libssh
|
||||
====================================
|
||||
|
||||
Simple, just make the code change, and email it as either a "diff -u"
|
||||
change, or as a "git format-patch" change against the original source
|
||||
code to libssh@libssh.org, or attach it to a bug report at
|
||||
https://red.libssh.org/
|
||||
|
||||
For larger code changes, breaking the changes up into a set of simple
|
||||
patches, each of which does a single thing, are much easier to review.
|
||||
Patch sets like that will most likely have an easier time being merged
|
||||
into the libssh code than large single patches that make lots of
|
||||
changes in one large diff.
|
||||
|
||||
Ownership of the contributed code
|
||||
==================================
|
||||
|
||||
libssh is a project with distributed copyright ownership, which means
|
||||
we prefer the copyright on parts of libssh to be held by individuals
|
||||
rather than corporations if possible. There are historical legal
|
||||
reasons for this, but one of the best ways to explain it is that it's
|
||||
much easier to work with individuals who have ownership than corporate
|
||||
legal departments if we ever need to make reasonable compromises with
|
||||
people using and working with libssh.
|
||||
|
||||
We track the ownership of every part of libssh via http://git.libssh.org,
|
||||
our source code control system, so we know the provenance of every piece
|
||||
of code that is committed to libssh.
|
||||
|
||||
So if possible, if you're doing libssh changes on behalf of a company
|
||||
who normally owns all the work you do please get them to assign
|
||||
personal copyright ownership of your changes to you as an individual,
|
||||
that makes things very easy for us to work with and avoids bringing
|
||||
corporate legal departments into the picture.
|
||||
|
||||
If you can't do this we can still accept patches from you owned by
|
||||
your employer under a standard employment contract with corporate
|
||||
copyright ownership. It just requires a simple set-up process first.
|
||||
|
||||
We use a process very similar to the way things are done in the Linux
|
||||
Kernel community, so it should be very easy to get a sign off from
|
||||
your corporate legal department. The only changes we've made are to
|
||||
accommodate the license we use, which is LGPLv2 (or later) whereas the
|
||||
Linux kernel uses GPLv2.
|
||||
|
||||
The process is called signing.
|
||||
|
||||
How to sign your work
|
||||
----------------------
|
||||
|
||||
Once you have permission to contribute to libssh from your employer, simply
|
||||
email a copy of the following text from your corporate email address to:
|
||||
|
||||
contributing@libssh.org
|
||||
|
||||
|
||||
|
||||
libssh Developer's Certificate of Origin. Version 1.0
|
||||
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
(a) The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the appropriate
|
||||
version of the GNU General Public License; or
|
||||
|
||||
(b) The contribution is based upon previous work that, to the best of
|
||||
my knowledge, is covered under an appropriate open source license
|
||||
and I have the right under that license to submit that work with
|
||||
modifications, whether created in whole or in part by me, under
|
||||
the GNU General Public License, in the appropriate version; or
|
||||
|
||||
(c) The contribution was provided directly to me by some other
|
||||
person who certified (a) or (b) and I have not modified it.
|
||||
|
||||
(d) I understand and agree that this project and the contribution are
|
||||
public and that a record of the contribution (including all
|
||||
metadata and personal information I submit with it, including my
|
||||
sign-off) is maintained indefinitely and may be redistributed
|
||||
consistent with the libssh Team's policies and the requirements of
|
||||
the GNU GPL where they are relevant.
|
||||
|
||||
(e) I am granting this work to this project 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 the option of the project) any later version.
|
||||
|
||||
http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
|
||||
|
||||
We will maintain a copy of that email as a record that you have the
|
||||
rights to contribute code to libssh under the required licenses whilst
|
||||
working for the company where the email came from.
|
||||
|
||||
Then when sending in a patch via the normal mechanisms described
|
||||
above, add a line that states:
|
||||
|
||||
Signed-off-by: Random J Developer <random@developer.example.org>
|
||||
|
||||
using your real name and the email address you sent the original email
|
||||
you used to send the libssh Developer's Certificate of Origin to us
|
||||
(sorry, no pseudonyms or anonymous contributions.)
|
||||
|
||||
That's it! Such code can then quite happily contain changes that have
|
||||
copyright messages such as:
|
||||
|
||||
(c) Example Corporation.
|
||||
|
||||
and can be merged into the libssh codebase in the same way as patches
|
||||
from any other individual. You don't need to send in a copy of the
|
||||
libssh Developer's Certificate of Origin for each patch, or inside each
|
||||
patch. Just the sign-off message is all that is required once we've
|
||||
received the initial email.
|
||||
|
||||
Have fun and happy libssh hacking !
|
||||
|
||||
The libssh Team
|
||||
|
||||
30
cmake/Modules/AddCMockaTest.cmake
Normal file
30
cmake/Modules/AddCMockaTest.cmake
Normal file
@@ -0,0 +1,30 @@
|
||||
# - ADD_CHECK_TEST(test_name test_source linklib1 ... linklibN)
|
||||
|
||||
# Copyright (c) 2007 Daniel Gollub <dgollub@suse.de>
|
||||
# Copyright (c) 2007-2010 Andreas Schneider <asn@cryptomilk.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
enable_testing()
|
||||
include(CTest)
|
||||
|
||||
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_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_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)
|
||||
|
||||
function (ADD_CMOCKA_TEST _testName _testSource)
|
||||
add_executable(${_testName} ${_testSource})
|
||||
target_link_libraries(${_testName} ${ARGN})
|
||||
add_test(${_testName} ${CMAKE_CURRENT_BINARY_DIR}/${_testName})
|
||||
endfunction (ADD_CMOCKA_TEST)
|
||||
26
cmake/Modules/CheckCCompilerFlagSSP.cmake
Normal file
26
cmake/Modules/CheckCCompilerFlagSSP.cmake
Normal file
@@ -0,0 +1,26 @@
|
||||
# - Check whether the C compiler supports a given flag in the
|
||||
# context of a stack checking compiler option.
|
||||
|
||||
# CHECK_C_COMPILER_FLAG_SSP(FLAG VARIABLE)
|
||||
#
|
||||
# FLAG - the compiler flag
|
||||
# VARIABLE - variable to store the result
|
||||
#
|
||||
# This actually calls check_c_source_compiles.
|
||||
# See help for CheckCSourceCompiles for a listing of variables
|
||||
# that can modify the build.
|
||||
|
||||
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
|
||||
include(CheckCSourceCompiles)
|
||||
|
||||
function(CHECK_C_COMPILER_FLAG_SSP _FLAG _RESULT)
|
||||
set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
|
||||
set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
|
||||
check_c_source_compiles("int main(int argc, char **argv) { char buffer[256]; return buffer[argc]=0;}" ${_RESULT})
|
||||
set(CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
|
||||
endfunction(CHECK_C_COMPILER_FLAG_SSP)
|
||||
@@ -25,3 +25,6 @@ if (NOT CMAKE_BUILD_TYPE)
|
||||
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
|
||||
)
|
||||
endif (NOT CMAKE_BUILD_TYPE)
|
||||
|
||||
# Create the compile command database for clang by default
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
@@ -1,59 +1,84 @@
|
||||
# define system dependent compiler flags
|
||||
|
||||
include(CheckCCompilerFlag)
|
||||
include(CheckCCompilerFlagSSP)
|
||||
|
||||
if (UNIX AND NOT WIN32)
|
||||
if (${CMAKE_C_COMPILER_ID} MATCHES GNU)
|
||||
# add -Wconversion ?
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -pedantic -Wall -Wextra -Wshadow -Wmissing-prototypes -Wdeclaration-after-statement -Wunused -Wfloat-equal -Wpointer-arith -Wwrite-strings -Wformat-security -Wmissing-format-attribute")
|
||||
#
|
||||
# Define GNUCC compiler flags
|
||||
#
|
||||
if (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)")
|
||||
|
||||
# with -fPIC
|
||||
check_c_compiler_flag("-fPIC" WITH_FPIC)
|
||||
if (WITH_FPIC)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
|
||||
endif (WITH_FPIC)
|
||||
# add -Wconversion ?
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -pedantic -pedantic-errors")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wshadow -Wmissing-prototypes -Wdeclaration-after-statement")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wunused -Wfloat-equal -Wpointer-arith -Wwrite-strings -Wformat-security")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-format-attribute")
|
||||
|
||||
check_c_compiler_flag("-fstack-protector" WITH_STACK_PROTECTOR)
|
||||
if (WITH_STACK_PROTECTOR)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector")
|
||||
endif (WITH_STACK_PROTECTOR)
|
||||
# with -fPIC
|
||||
check_c_compiler_flag("-fPIC" WITH_FPIC)
|
||||
if (WITH_FPIC)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
|
||||
endif (WITH_FPIC)
|
||||
|
||||
check_c_compiler_flag("-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE)
|
||||
if (WITH_FORTIFY_SOURCE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FORTIFY_SOURCE=2")
|
||||
endif (WITH_FORTIFY_SOURCE)
|
||||
check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR)
|
||||
if (WITH_STACK_PROTECTOR)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector")
|
||||
endif (WITH_STACK_PROTECTOR)
|
||||
|
||||
endif (${CMAKE_C_COMPILER_ID} MATCHES GNU)
|
||||
if (CMAKE_BUILD_TYPE)
|
||||
string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
|
||||
if (CMAKE_BUILD_TYPE_LOWER MATCHES (release|relwithdebinfo|minsizerel))
|
||||
check_c_compiler_flag("-Wp,-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE)
|
||||
if (WITH_FORTIFY_SOURCE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wp,-D_FORTIFY_SOURCE=2")
|
||||
endif (WITH_FORTIFY_SOURCE)
|
||||
endif()
|
||||
endif()
|
||||
endif (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)")
|
||||
|
||||
if (CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
# with large file support
|
||||
execute_process(
|
||||
COMMAND
|
||||
getconf LFS64_CFLAGS
|
||||
OUTPUT_VARIABLE
|
||||
_lfs_CFLAGS
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
else (CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
# with large file support
|
||||
execute_process(
|
||||
COMMAND
|
||||
getconf LFS_CFLAGS
|
||||
OUTPUT_VARIABLE
|
||||
_lfs_CFLAGS
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
endif (CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
if (_lfs_CFLAGS)
|
||||
string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_lfs_CFLAGS}")
|
||||
endif (_lfs_CFLAGS)
|
||||
#
|
||||
# Check for large filesystem support
|
||||
#
|
||||
if (CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
# with large file support
|
||||
execute_process(
|
||||
COMMAND
|
||||
getconf LFS64_CFLAGS
|
||||
OUTPUT_VARIABLE
|
||||
_lfs_CFLAGS
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
else (CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
# with large file support
|
||||
execute_process(
|
||||
COMMAND
|
||||
getconf LFS_CFLAGS
|
||||
OUTPUT_VARIABLE
|
||||
_lfs_CFLAGS
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
endif (CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
if (_lfs_CFLAGS)
|
||||
string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_lfs_CFLAGS}")
|
||||
endif (_lfs_CFLAGS)
|
||||
|
||||
endif (UNIX AND NOT WIN32)
|
||||
|
||||
# suppress warning about "deprecated" functions
|
||||
if (MSVC)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS")
|
||||
# Use secure functions by defaualt and suppress warnings about
|
||||
#"deprecated" functions
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=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")
|
||||
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)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
if (UNIX)
|
||||
if (UNIX OR OS2)
|
||||
IF (NOT APPLICATION_NAME)
|
||||
MESSAGE(STATUS "${PROJECT_NAME} is used as APPLICATION_NAME")
|
||||
SET(APPLICATION_NAME ${PROJECT_NAME})
|
||||
@@ -47,6 +47,10 @@ if (UNIX)
|
||||
CACHE PATH "The subdirectory to the header prefix (default prefix/include)"
|
||||
)
|
||||
|
||||
set(CMAKE_INSTALL_DIR
|
||||
"${LIB_INSTALL_DIR}/cmake"
|
||||
CACHE PATH "The subdirectory to install cmake config files")
|
||||
|
||||
SET(DATA_INSTALL_DIR
|
||||
"${DATA_INSTALL_PREFIX}"
|
||||
CACHE PATH "The parent directory where applications can install their data (default prefix/share/${APPLICATION_NAME})"
|
||||
@@ -90,18 +94,16 @@ if (UNIX)
|
||||
"${SHARE_INSTALL_PREFIX}/info"
|
||||
CACHE PATH "The ${APPLICATION_NAME} info install dir (default prefix/info)"
|
||||
)
|
||||
endif (UNIX)
|
||||
|
||||
if (WIN32)
|
||||
else()
|
||||
# Same same
|
||||
set(BIN_INSTALL_DIR "bin" CACHE PATH "-")
|
||||
set(SBIN_INSTALL_DIR "." CACHE PATH "-")
|
||||
set(LIB_INSTALL_DIR "lib" CACHE PATH "-")
|
||||
set(SBIN_INSTALL_DIR "sbin" CACHE PATH "-")
|
||||
set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}" CACHE PATH "-")
|
||||
set(INCLUDE_INSTALL_DIR "include" CACHE PATH "-")
|
||||
set(CMAKE_INSTALL_DIR "CMake" CACHE PATH "-")
|
||||
set(PLUGIN_INSTALL_DIR "plugins" CACHE PATH "-")
|
||||
set(HTML_INSTALL_DIR "doc/HTML" CACHE PATH "-")
|
||||
set(ICON_INSTALL_DIR "." CACHE PATH "-")
|
||||
set(SOUND_INSTALL_DIR "." CACHE PATH "-")
|
||||
set(ICON_INSTALL_DIR "icons" CACHE PATH "-")
|
||||
set(SOUND_INSTALL_DIR "soudns" CACHE PATH "-")
|
||||
set(LOCALE_INSTALL_DIR "lang" CACHE PATH "-")
|
||||
endif (WIN32)
|
||||
|
||||
endif ()
|
||||
|
||||
32
cmake/Modules/DefinePlatformDefaults.cmake
Normal file
32
cmake/Modules/DefinePlatformDefaults.cmake
Normal file
@@ -0,0 +1,32 @@
|
||||
# Set system vars
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
set(LINUX TRUE)
|
||||
endif(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
|
||||
set(FREEBSD TRUE)
|
||||
set(BSD TRUE)
|
||||
endif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
|
||||
set(OPENBSD TRUE)
|
||||
set(BSD TRUE)
|
||||
endif (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "NetBSD")
|
||||
set(NETBSD TRUE)
|
||||
set(BSD TRUE)
|
||||
endif (CMAKE_SYSTEM_NAME MATCHES "NetBSD")
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
|
||||
set(SOLARIS TRUE)
|
||||
endif (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "OS2")
|
||||
set(OS2 TRUE)
|
||||
endif (CMAKE_SYSTEM_NAME MATCHES "OS2")
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
set (OSX TRUE)
|
||||
endif (CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
60
cmake/Modules/FindArgp.cmake
Normal file
60
cmake/Modules/FindArgp.cmake
Normal file
@@ -0,0 +1,60 @@
|
||||
# - Try to find Argp
|
||||
# Once done this will define
|
||||
#
|
||||
# ARGP_FOUND - system has Argp
|
||||
# ARGP_INCLUDE_DIRS - the Argp include directory
|
||||
# ARGP_LIBRARIES - Link these to use Argp
|
||||
# ARGP_DEFINITIONS - Compiler switches required for using Argp
|
||||
#
|
||||
# Copyright (c) 2010 Andreas Schneider <asn@cryptomilk.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
|
||||
if (ARGP_LIBRARIES AND ARGP_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(ARGP_FOUND TRUE)
|
||||
else (ARGP_LIBRARIES AND ARGP_INCLUDE_DIRS)
|
||||
|
||||
find_path(ARGP_INCLUDE_DIR
|
||||
NAMES
|
||||
argp.h
|
||||
PATHS
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
)
|
||||
|
||||
find_library(ARGP_LIBRARY
|
||||
NAMES
|
||||
argp
|
||||
PATHS
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
)
|
||||
|
||||
set(ARGP_INCLUDE_DIRS
|
||||
${ARGP_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
if (ARGP_LIBRARY)
|
||||
set(ARGP_LIBRARIES
|
||||
${ARGP_LIBRARIES}
|
||||
${ARGP_LIBRARY}
|
||||
)
|
||||
endif (ARGP_LIBRARY)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Argp DEFAULT_MSG ARGP_LIBRARIES ARGP_INCLUDE_DIRS)
|
||||
|
||||
# show the ARGP_INCLUDE_DIRS and ARGP_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(ARGP_INCLUDE_DIRS ARGP_LIBRARIES)
|
||||
|
||||
endif (ARGP_LIBRARIES AND ARGP_INCLUDE_DIRS)
|
||||
|
||||
66
cmake/Modules/FindCMocka.cmake
Normal file
66
cmake/Modules/FindCMocka.cmake
Normal file
@@ -0,0 +1,66 @@
|
||||
# - Try to find CMocka
|
||||
# Once done this will define
|
||||
#
|
||||
# CMOCKA_ROOT_DIR - Set this variable to the root installation of CMocka
|
||||
#
|
||||
# Read-Only variables:
|
||||
# CMOCKA_FOUND - system has CMocka
|
||||
# CMOCKA_INCLUDE_DIR - the CMocka include directory
|
||||
# CMOCKA_LIBRARIES - Link these to use CMocka
|
||||
# CMOCKA_DEFINITIONS - Compiler switches required for using CMocka
|
||||
#
|
||||
#=============================================================================
|
||||
# Copyright (c) 2011-2012 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.
|
||||
#=============================================================================
|
||||
#
|
||||
|
||||
set(_CMOCKA_ROOT_HINTS
|
||||
)
|
||||
|
||||
set(_CMOCKA_ROOT_PATHS
|
||||
"$ENV{PROGRAMFILES}/cmocka"
|
||||
)
|
||||
|
||||
find_path(CMOCKA_ROOT_DIR
|
||||
NAMES
|
||||
include/cmocka.h
|
||||
HINTS
|
||||
${_CMOCKA_ROOT_HINTS}
|
||||
PATHS
|
||||
${_CMOCKA_ROOT_PATHS}
|
||||
)
|
||||
mark_as_advanced(CMOCKA_ROOT_DIR)
|
||||
|
||||
find_path(CMOCKA_INCLUDE_DIR
|
||||
NAMES
|
||||
cmocka.h
|
||||
PATHS
|
||||
${CMOCKA_ROOT_DIR}/include
|
||||
)
|
||||
|
||||
find_library(CMOCKA_LIBRARY
|
||||
NAMES
|
||||
cmocka
|
||||
PATHS
|
||||
${CMOCKA_ROOT_DIR}/lib
|
||||
)
|
||||
|
||||
if (CMOCKA_LIBRARY)
|
||||
set(CMOCKA_LIBRARIES
|
||||
${CMOCKA_LIBRARIES}
|
||||
${CMOCKA_LIBRARY}
|
||||
)
|
||||
endif (CMOCKA_LIBRARY)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(CMocka DEFAULT_MSG CMOCKA_LIBRARIES CMOCKA_INCLUDE_DIR)
|
||||
|
||||
# show the CMOCKA_INCLUDE_DIR and CMOCKA_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(CMOCKA_INCLUDE_DIR CMOCKA_LIBRARIES)
|
||||
@@ -6,72 +6,70 @@
|
||||
# GCRYPT_LIBRARIES - Link these to use GCrypt
|
||||
# GCRYPT_DEFINITIONS - Compiler switches required for using GCrypt
|
||||
#
|
||||
# Copyright (c) 2009 Andreas Schneider <mail@cynapses.org>
|
||||
#=============================================================================
|
||||
# Copyright (c) 2009-2012 Andreas Schneider <asn@cryptomilk.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
# 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.
|
||||
#=============================================================================
|
||||
#
|
||||
|
||||
set(_GCRYPT_ROOT_HINTS
|
||||
$ENV{GCRYTPT_ROOT_DIR}
|
||||
${GCRYPT_ROOT_DIR})
|
||||
|
||||
if (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(GCRYPT_FOUND TRUE)
|
||||
else (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
|
||||
set(_GCRYPT_ROOT_PATHS
|
||||
"$ENV{PROGRAMFILES}/libgcrypt")
|
||||
|
||||
find_path(GCRYPT_INCLUDE_DIR
|
||||
set(_GCRYPT_ROOT_HINTS_AND_PATHS
|
||||
HINTS ${_GCRYPT_ROOT_HINTS}
|
||||
PATHS ${_GCRYPT_ROOT_PATHS})
|
||||
|
||||
|
||||
find_path(GCRYPT_INCLUDE_DIR
|
||||
NAMES
|
||||
gcrypt.h
|
||||
PATHS
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
)
|
||||
mark_as_advanced(GCRYPT_INCLUDE_DIR)
|
||||
gcrypt.h
|
||||
HINTS
|
||||
${_GCRYPT_ROOT_HINTS_AND_PATHS}
|
||||
)
|
||||
|
||||
find_library(GCRYPT_LIBRARY
|
||||
find_library(GCRYPT_LIBRARY
|
||||
NAMES
|
||||
gcrypt
|
||||
PATHS
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
)
|
||||
mark_as_advanced(GCRYPT_LIBRARY)
|
||||
gcrypt
|
||||
gcrypt11
|
||||
libgcrypt-11
|
||||
HINTS
|
||||
${_GCRYPT_ROOT_HINTS_AND_PATHS}
|
||||
)
|
||||
set(GCRYPT_LIBRARIES ${GCRYPT_LIBRARY})
|
||||
|
||||
if (GCRYPT_LIBRARY)
|
||||
set(GCRYPT_FOUND TRUE CACHE INTERNAL "Wether the gcrypt library has been found" FORCE)
|
||||
endif (GCRYPT_LIBRARY)
|
||||
if (GCRYPT_INCLUDE_DIR)
|
||||
file(STRINGS "${GCRYPT_INCLUDE_DIR}/gcrypt.h" _gcrypt_version_str REGEX "^#define GCRYPT_VERSION \"[0-9]+.[0-9]+.[0-9]+\"")
|
||||
|
||||
set(GCRYPT_INCLUDE_DIRS
|
||||
${GCRYPT_INCLUDE_DIR}
|
||||
)
|
||||
string(REGEX REPLACE "^.*GCRYPT_VERSION.*([0-9]+.[0-9]+.[0-9]+).*" "\\1" GCRYPT_VERSION "${_gcrypt_version_str}")
|
||||
endif (GCRYPT_INCLUDE_DIR)
|
||||
|
||||
if (GCRYPT_FOUND)
|
||||
set(GCRYPT_LIBRARIES
|
||||
${GCRYPT_LIBRARIES}
|
||||
${GCRYPT_LIBRARY}
|
||||
include(FindPackageHandleStandardArgs)
|
||||
if (GCRYPT_VERSION)
|
||||
find_package_handle_standard_args(GCrypt
|
||||
REQUIRED_VARS
|
||||
GCRYPT_INCLUDE_DIR
|
||||
GCRYPT_LIBRARIES
|
||||
VERSION_VAR
|
||||
GCRYPT_VERSION
|
||||
FAIL_MESSAGE
|
||||
"Could NOT find GCrypt, try to set the path to GCrypt root folder in the system variable GCRYPT_ROOT_DIR"
|
||||
)
|
||||
endif (GCRYPT_FOUND)
|
||||
|
||||
if (GCRYPT_INCLUDE_DIRS AND GCRYPT_LIBRARIES)
|
||||
set(GCRYPT_FOUND TRUE)
|
||||
endif (GCRYPT_INCLUDE_DIRS AND GCRYPT_LIBRARIES)
|
||||
|
||||
if (GCRYPT_FOUND)
|
||||
if (NOT GCrypt_FIND_QUIETLY)
|
||||
message(STATUS "Found GCrypt: ${GCRYPT_LIBRARIES}")
|
||||
endif (NOT GCrypt_FIND_QUIETLY)
|
||||
else (GCRYPT_FOUND)
|
||||
if (GCrypt_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find GCrypt")
|
||||
endif (GCrypt_FIND_REQUIRED)
|
||||
endif (GCRYPT_FOUND)
|
||||
|
||||
# show the GCRYPT_INCLUDE_DIRS and GCRYPT_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(GCRYPT_INCLUDE_DIRS GCRYPT_LIBRARIES)
|
||||
|
||||
endif (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
|
||||
else (GCRYPT_VERSION)
|
||||
find_package_handle_standard_args(GCrypt
|
||||
"Could NOT find GCrypt, try to set the path to GCrypt root folder in the system variable GCRYPT_ROOT_DIR"
|
||||
GCRYPT_INCLUDE_DIR
|
||||
GCRYPT_LIBRARIES)
|
||||
endif (GCRYPT_VERSION)
|
||||
|
||||
# show the GCRYPT_INCLUDE_DIRS and GCRYPT_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(GCRYPT_INCLUDE_DIR GCRYPT_LIBRARIES)
|
||||
|
||||
324
cmake/Modules/FindGSSAPI.cmake
Normal file
324
cmake/Modules/FindGSSAPI.cmake
Normal file
@@ -0,0 +1,324 @@
|
||||
# - Try to find GSSAPI
|
||||
# Once done this will define
|
||||
#
|
||||
# KRB5_CONFIG - Path to krb5-config
|
||||
# GSSAPI_ROOT_DIR - Set this variable to the root installation of GSSAPI
|
||||
#
|
||||
# Read-Only variables:
|
||||
# GSSAPI_FLAVOR_MIT - set to TURE if MIT Kerberos has been found
|
||||
# GSSAPI_FLAVOR_HEIMDAL - set to TRUE if Heimdal Keberos has been found
|
||||
# GSSAPI_FOUND - system has GSSAPI
|
||||
# GSSAPI_INCLUDE_DIR - the GSSAPI include directory
|
||||
# GSSAPI_LIBRARIES - Link these to use GSSAPI
|
||||
# GSSAPI_DEFINITIONS - Compiler switches required for using GSSAPI
|
||||
#
|
||||
#=============================================================================
|
||||
# Copyright (c) 2013 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.
|
||||
#=============================================================================
|
||||
#
|
||||
|
||||
find_path(GSSAPI_ROOT_DIR
|
||||
NAMES
|
||||
include/gssapi.h
|
||||
include/gssapi/gssapi.h
|
||||
HINTS
|
||||
${_GSSAPI_ROOT_HINTS}
|
||||
PATHS
|
||||
${_GSSAPI_ROOT_PATHS}
|
||||
)
|
||||
mark_as_advanced(GSSAPI_ROOT_DIR)
|
||||
|
||||
if (UNIX)
|
||||
find_program(KRB5_CONFIG
|
||||
NAMES
|
||||
krb5-config
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/bin
|
||||
/opt/local/bin)
|
||||
mark_as_advanced(KRB5_CONFIG)
|
||||
|
||||
if (KRB5_CONFIG)
|
||||
# Check if we have MIT KRB5
|
||||
execute_process(
|
||||
COMMAND
|
||||
${KRB5_CONFIG} --vendor
|
||||
RESULT_VARIABLE
|
||||
_GSSAPI_VENDOR_RESULT
|
||||
OUTPUT_VARIABLE
|
||||
_GSSAPI_VENDOR_STRING)
|
||||
|
||||
if (_GSSAPI_VENDOR_STRING MATCHES ".*Massachusetts.*")
|
||||
set(GSSAPI_FLAVOR_MIT TRUE)
|
||||
else()
|
||||
execute_process(
|
||||
COMMAND
|
||||
${KRB5_CONFIG} --libs gssapi
|
||||
RESULT_VARIABLE
|
||||
_GSSAPI_LIBS_RESULT
|
||||
OUTPUT_VARIABLE
|
||||
_GSSAPI_LIBS_STRING)
|
||||
|
||||
if (_GSSAPI_LIBS_STRING MATCHES ".*roken.*")
|
||||
set(GSSAPI_FLAVOR_HEIMDAL TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Get the include dir
|
||||
execute_process(
|
||||
COMMAND
|
||||
${KRB5_CONFIG} --cflags gssapi
|
||||
RESULT_VARIABLE
|
||||
_GSSAPI_INCLUDE_RESULT
|
||||
OUTPUT_VARIABLE
|
||||
_GSSAPI_INCLUDE_STRING)
|
||||
string(REGEX REPLACE "(\r?\n)+$" "" _GSSAPI_INCLUDE_STRING "${_GSSAPI_INCLUDE_STRING}")
|
||||
string(REGEX REPLACE " *-I" "" _GSSAPI_INCLUDEDIR "${_GSSAPI_INCLUDE_STRING}")
|
||||
endif()
|
||||
|
||||
if (NOT GSSAPI_FLAVOR_MIT AND NOT GSSAPI_FLAVOR_HEIMDAL)
|
||||
# Check for HEIMDAL
|
||||
find_package(PkgConfig)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(_GSSAPI heimdal-gssapi)
|
||||
endif (PKG_CONFIG_FOUND)
|
||||
|
||||
if (_GSSAPI_FOUND)
|
||||
set(GSSAPI_FLAVOR_HEIMDAL TRUE)
|
||||
else()
|
||||
find_path(_GSSAPI_ROKEN
|
||||
NAMES
|
||||
roken.h
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/include
|
||||
${_GSSAPI_INCLUDEDIR})
|
||||
if (_GSSAPI_ROKEN)
|
||||
set(GSSAPI_FLAVOR_HEIMDAL TRUE)
|
||||
endif()
|
||||
endif ()
|
||||
endif()
|
||||
endif (UNIX)
|
||||
|
||||
find_path(GSSAPI_INCLUDE_DIR
|
||||
NAMES
|
||||
gssapi.h
|
||||
gssapi/gssapi.h
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/include
|
||||
${_GSSAPI_INCLUDEDIR}
|
||||
)
|
||||
|
||||
if (GSSAPI_FLAVOR_MIT)
|
||||
find_library(GSSAPI_LIBRARY
|
||||
NAMES
|
||||
gssapi_krb5
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
find_library(KRB5_LIBRARY
|
||||
NAMES
|
||||
krb5
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
find_library(K5CRYPTO_LIBRARY
|
||||
NAMES
|
||||
k5crypto
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
find_library(COM_ERR_LIBRARY
|
||||
NAMES
|
||||
com_err
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
if (GSSAPI_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${GSSAPI_LIBRARY}
|
||||
)
|
||||
endif (GSSAPI_LIBRARY)
|
||||
|
||||
if (KRB5_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${KRB5_LIBRARY}
|
||||
)
|
||||
endif (KRB5_LIBRARY)
|
||||
|
||||
if (K5CRYPTO_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${K5CRYPTO_LIBRARY}
|
||||
)
|
||||
endif (K5CRYPTO_LIBRARY)
|
||||
|
||||
if (COM_ERR_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${COM_ERR_LIBRARY}
|
||||
)
|
||||
endif (COM_ERR_LIBRARY)
|
||||
endif (GSSAPI_FLAVOR_MIT)
|
||||
|
||||
if (GSSAPI_FLAVOR_HEIMDAL)
|
||||
find_library(GSSAPI_LIBRARY
|
||||
NAMES
|
||||
gssapi
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
find_library(KRB5_LIBRARY
|
||||
NAMES
|
||||
krb5
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
find_library(HCRYPTO_LIBRARY
|
||||
NAMES
|
||||
hcrypto
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
find_library(COM_ERR_LIBRARY
|
||||
NAMES
|
||||
com_err
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
find_library(HEIMNTLM_LIBRARY
|
||||
NAMES
|
||||
heimntlm
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
find_library(HX509_LIBRARY
|
||||
NAMES
|
||||
hx509
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
find_library(ASN1_LIBRARY
|
||||
NAMES
|
||||
asn1
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
find_library(WIND_LIBRARY
|
||||
NAMES
|
||||
wind
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
find_library(ROKEN_LIBRARY
|
||||
NAMES
|
||||
roken
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
if (GSSAPI_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${GSSAPI_LIBRARY}
|
||||
)
|
||||
endif (GSSAPI_LIBRARY)
|
||||
|
||||
if (KRB5_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${KRB5_LIBRARY}
|
||||
)
|
||||
endif (KRB5_LIBRARY)
|
||||
|
||||
if (HCRYPTO_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${HCRYPTO_LIBRARY}
|
||||
)
|
||||
endif (HCRYPTO_LIBRARY)
|
||||
|
||||
if (COM_ERR_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${COM_ERR_LIBRARY}
|
||||
)
|
||||
endif (COM_ERR_LIBRARY)
|
||||
|
||||
if (HEIMNTLM_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${HEIMNTLM_LIBRARY}
|
||||
)
|
||||
endif (HEIMNTLM_LIBRARY)
|
||||
|
||||
if (HX509_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${HX509_LIBRARY}
|
||||
)
|
||||
endif (HX509_LIBRARY)
|
||||
|
||||
if (ASN1_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${ASN1_LIBRARY}
|
||||
)
|
||||
endif (ASN1_LIBRARY)
|
||||
|
||||
if (WIND_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${WIND_LIBRARY}
|
||||
)
|
||||
endif (WIND_LIBRARY)
|
||||
|
||||
if (ROKEN_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${WIND_LIBRARY}
|
||||
)
|
||||
endif (ROKEN_LIBRARY)
|
||||
endif (GSSAPI_FLAVOR_HEIMDAL)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(GSSAPI DEFAULT_MSG GSSAPI_LIBRARIES GSSAPI_INCLUDE_DIR)
|
||||
|
||||
if (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES)
|
||||
set(GSSAPI_FOUND TRUE)
|
||||
endif (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES)
|
||||
|
||||
# show the GSSAPI_INCLUDE_DIRS and GSSAPI_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(GSSAPI_INCLUDE_DIRS GSSAPI_LIBRARIES)
|
||||
@@ -1,31 +1,55 @@
|
||||
# - Try to find NSIS
|
||||
# Once done this will define
|
||||
#
|
||||
# NSIS_ROOT_PATH - Set this variable to the root installation of NSIS
|
||||
#
|
||||
# Read-Only variables:
|
||||
#
|
||||
# NSIS_FOUND - system has NSIS
|
||||
# NSIS_MAKE - NSIS creator executable
|
||||
#
|
||||
# Copyright (c) 2010 Andreas Schneider <mail@cynapses.org>
|
||||
#=============================================================================
|
||||
# Copyright (c) 2010-2013 Andreas Schneider <asn@cryptomilk.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
# 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 (WIN32)
|
||||
set(_NSIS_ROOT_HINTS
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\NSIS;Default]")
|
||||
|
||||
set(_NSIS_ROOT_PATHS
|
||||
$ENV{PROGRAMFILES}/NSIS)
|
||||
|
||||
find_path(NSIS_ROOT_PATH
|
||||
NAMES
|
||||
Include/Library.nsh
|
||||
HINTS
|
||||
${_NSIS_ROOT_HINTS}
|
||||
PATHS
|
||||
${_NSIS_ROOT_PATHS}
|
||||
)
|
||||
mark_as_advanced(NSIS_ROOT_PATH)
|
||||
endif (WIN32)
|
||||
|
||||
find_program(NSIS_MAKE
|
||||
NAMES
|
||||
makensis
|
||||
PATHS
|
||||
${NSIS_ROOT_PATH}
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(NSIS DEFAULT_MSG NSIS_MAKE)
|
||||
|
||||
if (NSIS_MAKE)
|
||||
# in cache already
|
||||
set(NSIS_FOUND TRUE)
|
||||
elseif (NSIS_MAKE)
|
||||
find_program(NSIS_MAKE
|
||||
NAMES
|
||||
makensis
|
||||
PATHS
|
||||
${_NSIS_DIR}
|
||||
${_NSIS_DIR}/Bin
|
||||
$ENV{PROGRAMFILES}/NSIS
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(NSIS DEFAULT_MSG NSIS_MAKE)
|
||||
|
||||
mark_as_advanced(NSIS_MAKE)
|
||||
set(NSIS_FOUND TRUE)
|
||||
endif (NSIS_MAKE)
|
||||
|
||||
mark_as_advanced(NSIS_MAKE)
|
||||
|
||||
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,189 +0,0 @@
|
||||
# - Try to find OpenSSL
|
||||
# Once done this will define
|
||||
#
|
||||
# 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) 2009 Andreas Schneider <mail@cynapses.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
|
||||
if (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(OPENSSL_FOUND TRUE)
|
||||
else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
|
||||
if (WIN32)
|
||||
set(_OPENSSL_DIR $ENV{PROGRAMFILES}/OpenSSL)
|
||||
endif (WIN32)
|
||||
|
||||
# use pkg-config to get the directories and then use these values
|
||||
# in the FIND_PATH() and FIND_LIBRARY() calls
|
||||
if (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
|
||||
include(UsePkgConfig)
|
||||
pkgconfig(openssl _OPENSSL_INCLUDEDIR _OPENSSL_LIBDIR _OPENSSL_LDFLAGS _OPENSSL_CFLAGS)
|
||||
else (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
|
||||
find_package(PkgConfig)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(_OPENSSL openssl)
|
||||
endif (PKG_CONFIG_FOUND)
|
||||
endif (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
|
||||
|
||||
find_path(OPENSSL_INCLUDE_DIR
|
||||
NAMES
|
||||
openssl/ssl.h
|
||||
PATHS
|
||||
${_OPENSSL_DIR}/include
|
||||
${_OPENSSL_INCLUDEDIR}
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/usr/local/ssl/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
/usr/lib/sfw/include
|
||||
)
|
||||
mark_as_advanced(OPENSSL_INCLUDE_DIR)
|
||||
|
||||
find_library(SSL_LIBRARY
|
||||
NAMES
|
||||
ssl
|
||||
libssl
|
||||
PATHS
|
||||
${_OPENSSL_DIR}/lib
|
||||
${_OPENSSL_LIBDIR}
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/usr/local/ssl/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
/usr/sfw/lib/64
|
||||
/usr/sfw/lib
|
||||
)
|
||||
mark_as_advanced(SSL_LIBRARY)
|
||||
|
||||
find_library(SSLEAY32_LIBRARY
|
||||
NAMES
|
||||
ssleay32
|
||||
PATHS
|
||||
${_OPENSSL_DIR}/lib
|
||||
${_OPENSSL_LIBDIR}
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/usr/local/ssl/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
/usr/sfw/lib/64
|
||||
/usr/sfw/lib
|
||||
)
|
||||
mark_as_advanced(SSLEAY32_LIBRARY)
|
||||
|
||||
find_library(SSLEAY32MD_LIBRARY
|
||||
NAMES
|
||||
ssleay32MD
|
||||
PATHS
|
||||
${_OPENSSL_DIR}/lib
|
||||
${_OPENSSL_LIBDIR}
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/usr/local/ssl/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
/usr/sfw/lib/64
|
||||
/usr/sfw/lib
|
||||
)
|
||||
mark_as_advanced(SSLEAY32MD_LIBRARY)
|
||||
|
||||
find_library(CRYPTO_LIBRARY
|
||||
NAMES
|
||||
crypto
|
||||
libcrypto
|
||||
eay
|
||||
eay32
|
||||
libeay
|
||||
libeay32
|
||||
PATHS
|
||||
${_OPENSSL_DIR}/lib
|
||||
${_OPENSSL_LIBDIR}
|
||||
/lib
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/usr/local/ssl/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
/usr/sfw/lib/64
|
||||
/usr/sfw/lib
|
||||
)
|
||||
mark_as_advanced(CRYPTO_LIBRARY)
|
||||
|
||||
if (SSL_LIBRARY)
|
||||
set(SSL_FOUND TRUE CACHE INTERNAL "Wether the ssl library has been found" FORCE)
|
||||
endif (SSL_LIBRARY)
|
||||
|
||||
if (SSLEAY32_LIBRARY)
|
||||
set(SSLEAY32_FOUND TRUE CACHE INTERNAL "Wether the ssleay32 library has been found" FORCE)
|
||||
endif (SSLEAY32_LIBRARY)
|
||||
|
||||
if (SSLEAY32MD_LIBRARY)
|
||||
set(SSLEAY32MD_FOUND TRUE CACHE INTERNAL "Wether the ssleay32MD library has been found" FORCE)
|
||||
endif (SSLEAY32MD_LIBRARY)
|
||||
|
||||
if (CRYPTO_LIBRARY)
|
||||
set(CRYPTO_FOUND TRUE CACHE INTERNAL "Wether the crypto library has been found" FORCE)
|
||||
endif (CRYPTO_LIBRARY)
|
||||
|
||||
set(OPENSSL_INCLUDE_DIRS
|
||||
${OPENSSL_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
if (SSL_FOUND)
|
||||
set(OPENSSL_LIBRARIES
|
||||
${OPENSSL_LIBRARIES}
|
||||
${SSL_LIBRARY}
|
||||
)
|
||||
endif (SSL_FOUND)
|
||||
|
||||
if (SSLEAY32_FOUND)
|
||||
set(OPENSSL_LIBRARIES
|
||||
${OPENSSL_LIBRARIES}
|
||||
${SSLEAY32_LIBRARY}
|
||||
)
|
||||
endif (SSLEAY32_FOUND)
|
||||
|
||||
if (SSLEAY32MD_FOUND)
|
||||
set(OPENSSL_LIBRARIES
|
||||
${OPENSSL_LIBRARIES}
|
||||
${SSLEAY32MD_LIBRARY}
|
||||
)
|
||||
endif (SSLEAY32MD_FOUND)
|
||||
|
||||
if (CRYPTO_FOUND)
|
||||
set(OPENSSL_LIBRARIES
|
||||
${OPENSSL_LIBRARIES}
|
||||
${CRYPTO_LIBRARY}
|
||||
)
|
||||
endif (CRYPTO_FOUND)
|
||||
|
||||
if (OPENSSL_INCLUDE_DIRS AND OPENSSL_LIBRARIES)
|
||||
set(OPENSSL_FOUND TRUE)
|
||||
endif (OPENSSL_INCLUDE_DIRS AND OPENSSL_LIBRARIES)
|
||||
|
||||
if (OPENSSL_FOUND)
|
||||
if (NOT OpenSSL_FIND_QUIETLY)
|
||||
message(STATUS "Found OpenSSL: ${OPENSSL_LIBRARIES}")
|
||||
endif (NOT OpenSSL_FIND_QUIETLY)
|
||||
else (OPENSSL_FOUND)
|
||||
if (OpenSSL_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find OpenSSL")
|
||||
endif (OpenSSL_FIND_REQUIRED)
|
||||
endif (OPENSSL_FOUND)
|
||||
|
||||
# show the OPENSSL_INCLUDE_DIRS and OPENSSL_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(OPENSSL_INCLUDE_DIRS OPENSSL_LIBRARIES)
|
||||
|
||||
endif (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
# - Try to find ZLIB
|
||||
# Once done this will define
|
||||
#
|
||||
# ZLIB_FOUND - system has ZLIB
|
||||
# ZLIB_INCLUDE_DIRS - the ZLIB include directory
|
||||
# ZLIB_LIBRARIES - Link these to use ZLIB
|
||||
# ZLIB_DEFINITIONS - Compiler switches required for using ZLIB
|
||||
#
|
||||
# Copyright (c) 2009 Andreas Schneider <mail@cynapses.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
|
||||
if (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(ZLIB_FOUND TRUE)
|
||||
else (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
|
||||
if (WIN32)
|
||||
set(_ZLIB_DIR $ENV{PROGRAMFILES}/GnuWin32)
|
||||
endif (WIN32)
|
||||
|
||||
find_path(ZLIB_INCLUDE_DIR
|
||||
NAMES
|
||||
zlib.h
|
||||
PATHS
|
||||
${_ZLIB_DIR}/include
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
)
|
||||
mark_as_advanced(ZLIB_INCLUDE_DIR)
|
||||
|
||||
find_library(Z_LIBRARY
|
||||
NAMES
|
||||
z
|
||||
zlib
|
||||
zlib1
|
||||
PATHS
|
||||
${_ZLIB_DIR}/lib
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
)
|
||||
mark_as_advanced(Z_LIBRARY)
|
||||
|
||||
if (Z_LIBRARY)
|
||||
set(Z_FOUND TRUE)
|
||||
endif (Z_LIBRARY)
|
||||
|
||||
set(ZLIB_INCLUDE_DIRS
|
||||
${ZLIB_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
if (Z_FOUND)
|
||||
set(ZLIB_LIBRARIES
|
||||
${ZLIB_LIBRARIES}
|
||||
${Z_LIBRARY}
|
||||
)
|
||||
endif (Z_FOUND)
|
||||
|
||||
if (ZLIB_INCLUDE_DIRS AND ZLIB_LIBRARIES)
|
||||
set(ZLIB_FOUND TRUE)
|
||||
endif (ZLIB_INCLUDE_DIRS AND ZLIB_LIBRARIES)
|
||||
|
||||
if (ZLIB_FOUND)
|
||||
if (NOT ZLIB_FIND_QUIETLY)
|
||||
message(STATUS "Found ZLIB: ${ZLIB_LIBRARIES}")
|
||||
endif (NOT ZLIB_FIND_QUIETLY)
|
||||
else (ZLIB_FOUND)
|
||||
if (ZLIB_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find ZLIB")
|
||||
endif (ZLIB_FIND_REQUIRED)
|
||||
endif (ZLIB_FOUND)
|
||||
|
||||
# show the ZLIB_INCLUDE_DIRS and ZLIB_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(ZLIB_INCLUDE_DIRS ZLIB_LIBRARIES)
|
||||
|
||||
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
|
||||
# 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:
|
||||
# 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
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#
|
||||
# CONFIGURATION
|
||||
#
|
||||
# To configure Doxygen you can edit Doxyfile.in and set some variables in cmake.
|
||||
# Variables you may define are:
|
||||
# DOXYFILE_OUTPUT_DIR - Path where the Doxygen output is stored. Defaults to "doc".
|
||||
#
|
||||
# DOXYFILE_LATEX_DIR - Directory where the Doxygen LaTeX output is stored. Defaults to "latex".
|
||||
#
|
||||
# DOXYFILE_HTML_DIR - Directory where the Doxygen html output is stored. Defaults to "html".
|
||||
# DOXYFILE_SOURCE_DIR - Path where the Doxygen input files are.
|
||||
# Defaults to the current source directory.
|
||||
# DOXYFILE_EXTRA_SOURCES - Additional source diretories/files for Doxygen to scan.
|
||||
# The Paths should be in double quotes and separated by space. e.g.:
|
||||
# "${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) 2010 Andreas Schneider <mail@cynapses.org>
|
||||
# Copyright (c) 2009, 2010, 2011 Tobias Rautenkranz <tobias@rautenkranz.ch>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
macro(usedoxygen_set_default name value)
|
||||
if(NOT DEFINED "${name}")
|
||||
set("${name}" "${value}")
|
||||
endif()
|
||||
macro(usedoxygen_set_default name value type docstring)
|
||||
if(NOT DEFINED "${name}")
|
||||
set("${name}" "${value}" CACHE "${type}" "${docstring}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
find_package(Doxygen)
|
||||
|
||||
if(DOXYGEN_FOUND)
|
||||
find_file(DOXYFILE_IN
|
||||
NAMES
|
||||
doxy.config.in
|
||||
PATHS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_ROOT}/Modules/
|
||||
NO_DEFAULT_PATH)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(DOXYFILE_IN DEFAULT_MSG "DOXYFILE_IN")
|
||||
find_file(DOXYFILE_IN "Doxyfile.in"
|
||||
PATHS "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_ROOT}/Modules/"
|
||||
NO_DEFAULT_PATH
|
||||
DOC "Path to the doxygen configuration template file")
|
||||
set(DOXYFILE "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile")
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(DOXYFILE_IN DEFAULT_MSG "DOXYFILE_IN")
|
||||
endif()
|
||||
|
||||
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_HTML_DIR "html")
|
||||
usedoxygen_set_default(DOXYFILE_LATEX YES BOOL "Generate LaTeX API documentation" OFF)
|
||||
usedoxygen_set_default(DOXYFILE_LATEX_DIR "latex" STRING "LaTex output directory")
|
||||
|
||||
set_property(DIRECTORY APPEND PROPERTY
|
||||
ADDITIONAL_MAKE_CLEAN_FILES "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_HTML_DIR}")
|
||||
mark_as_advanced(DOXYFILE_OUTPUT_DIR DOXYFILE_HTML_DIR DOXYFILE_LATEX_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)
|
||||
if(LATEX_COMPILER AND MAKEINDEX_COMPILER)
|
||||
set(DOXYFILE_LATEX TRUE)
|
||||
usedoxygen_set_default(DOXYFILE_LATEX_DIR "latex")
|
||||
set_property(DIRECTORY
|
||||
APPEND PROPERTY
|
||||
ADDITIONAL_MAKE_CLEAN_FILES
|
||||
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_HTML_DIR}")
|
||||
|
||||
set_property(DIRECTORY APPEND PROPERTY
|
||||
ADDITIONAL_MAKE_CLEAN_FILES
|
||||
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
|
||||
add_custom_target(doxygen
|
||||
COMMAND "${DOXYGEN_EXECUTABLE}"
|
||||
"${DOXYFILE}"
|
||||
COMMENT "Writing documentation to ${DOXYFILE_OUTPUT_DIR}..."
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
if(PDFLATEX_COMPILER)
|
||||
set(DOXYFILE_PDFLATEX TRUE)
|
||||
endif()
|
||||
if(DOXYGEN_DOT_EXECUTABLE)
|
||||
set(DOXYFILE_DOT TRUE)
|
||||
endif()
|
||||
set(DOXYFILE_DOT "NO")
|
||||
if(DOXYGEN_DOT_EXECUTABLE)
|
||||
set(DOXYFILE_DOT "YES")
|
||||
endif()
|
||||
|
||||
add_custom_command(TARGET doxygen
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_MAKE_PROGRAM}
|
||||
WORKING_DIRECTORY "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
|
||||
endif()
|
||||
## LaTeX
|
||||
set(DOXYFILE_PDFLATEX "NO")
|
||||
|
||||
configure_file(${DOXYFILE_IN} ${CMAKE_CURRENT_BINARY_DIR}/doxy.config ESCAPE_QUOTES IMMEDIATE @ONLY)
|
||||
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doxy.trac.in)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doxy.trac.in ${CMAKE_CURRENT_BINARY_DIR}/doxy.trac ESCAPE_QUOTES IMMEDIATE @ONLY)
|
||||
add_custom_target(doxygen-trac ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.trac)
|
||||
endif()
|
||||
set_property(DIRECTORY APPEND PROPERTY
|
||||
ADDITIONAL_MAKE_CLEAN_FILES
|
||||
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
|
||||
|
||||
get_target_property(DOC_TARGET doc TYPE)
|
||||
if(NOT DOC_TARGET)
|
||||
add_custom_target(doc)
|
||||
endif()
|
||||
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_dependencies(doc doxygen)
|
||||
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()
|
||||
|
||||
@@ -17,12 +17,30 @@
|
||||
/* Define to 1 if you have the <argp.h> header file. */
|
||||
#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. */
|
||||
#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. */
|
||||
#cmakedefine HAVE_TERMIOS_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#cmakedefine HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/aes.h> header file. */
|
||||
#cmakedefine HAVE_OPENSSL_AES_H 1
|
||||
|
||||
@@ -35,6 +53,27 @@
|
||||
/* Define to 1 if you have the <openssl/des.h> header file. */
|
||||
#cmakedefine HAVE_OPENSSL_DES_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/ecdh.h> header file. */
|
||||
#cmakedefine HAVE_OPENSSL_ECDH_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/ec.h> header file. */
|
||||
#cmakedefine HAVE_OPENSSL_EC_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/ecdsa.h> header file. */
|
||||
#cmakedefine HAVE_OPENSSL_ECDSA_H 1
|
||||
|
||||
/* Define to 1 if you have the <pthread.h> header file. */
|
||||
#cmakedefine HAVE_PTHREAD_H 1
|
||||
|
||||
/* Define to 1 if you have eliptic curve cryptography in openssl */
|
||||
#cmakedefine HAVE_OPENSSL_ECC 1
|
||||
|
||||
/* Define to 1 if you have eliptic curve cryptography in gcrypt */
|
||||
#cmakedefine HAVE_GCRYPT_ECC 1
|
||||
|
||||
/* Define to 1 if you have eliptic curve cryptography */
|
||||
#cmakedefine HAVE_ECC 1
|
||||
|
||||
/*************************** FUNCTIONS ***************************/
|
||||
|
||||
/* Define to 1 if you have the `snprintf' function. */
|
||||
@@ -55,15 +94,8 @@
|
||||
/* Define to 1 if you have the `_vsnprintf_s' function. */
|
||||
#cmakedefine HAVE__VSNPRINTF_S 1
|
||||
|
||||
/* Define to 1 if you have the `snprintf' function. */
|
||||
#cmakedefine HAVE_SNPRINTF 1
|
||||
|
||||
/* Define to 1 if you have the `_snprintf' function. */
|
||||
#cmakedefine HAVE__SNPRINTF 1
|
||||
|
||||
/* Define to 1 if you have the `_snprintf_s' function. */
|
||||
#cmakedefine HAVE__SNPRINTF_S 1
|
||||
|
||||
/* Define to 1 if you have the `isblank' function. */
|
||||
#cmakedefine HAVE_ISBLANK 1
|
||||
|
||||
/* Define to 1 if you have the `strncpy' function. */
|
||||
#cmakedefine HAVE_STRNCPY 1
|
||||
@@ -74,17 +106,29 @@
|
||||
/* Define to 1 if you have the `getaddrinfo' function. */
|
||||
#cmakedefine HAVE_GETADDRINFO 1
|
||||
|
||||
/* Define to 1 if you have the `gethostbyname' function. */
|
||||
#cmakedefine HAVE_GETHOSTBYNAME 1
|
||||
|
||||
/* Define to 1 if you have the `poll' function. */
|
||||
#cmakedefine HAVE_POLL 1
|
||||
|
||||
/* Define to 1 if you have the `select' function. */
|
||||
#cmakedefine HAVE_SELECT 1
|
||||
|
||||
/* Define to 1 if you have the `regcomp' function. */
|
||||
#cmakedefine HAVE_REGCOMP 1
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
#cmakedefine HAVE_CLOCK_GETTIME 1
|
||||
|
||||
/* Define to 1 if you have the `ntohll' function. */
|
||||
#cmakedefine HAVE_NTOHLL 1
|
||||
|
||||
/* Define to 1 if you have the `htonll' function. */
|
||||
#cmakedefine HAVE_HTONLL 1
|
||||
|
||||
/* Define to 1 if you have the `strtoull' function. */
|
||||
#cmakedefine HAVE_STRTOULL 1
|
||||
|
||||
/* Define to 1 if you have the `__strtoull' function. */
|
||||
#cmakedefine HAVE___STRTOULL 1
|
||||
|
||||
/* Define to 1 if you have the `_strtoui64' function. */
|
||||
#cmakedefine HAVE__STRTOUI64 1
|
||||
|
||||
/*************************** LIBRARIES ***************************/
|
||||
|
||||
@@ -94,13 +138,25 @@
|
||||
/* Define to 1 if you have the `gcrypt' library (-lgcrypt). */
|
||||
#cmakedefine HAVE_LIBGCRYPT 1
|
||||
|
||||
/* Define to 1 if you have the `z' library (-lz). */
|
||||
#cmakedefine HAVE_LIBZ 1
|
||||
/* Define to 1 if you have the `pthread' library (-lpthread). */
|
||||
#cmakedefine HAVE_PTHREAD 1
|
||||
|
||||
/**************************** OPTIONS ****************************/
|
||||
|
||||
#cmakedefine HAVE_GCC_THREAD_LOCAL_STORAGE 1
|
||||
#cmakedefine HAVE_MSC_THREAD_LOCAL_STORAGE 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 */
|
||||
#cmakedefine WITH_GSSAPI 1
|
||||
|
||||
/* Define to 1 if you want to enable ZLIB */
|
||||
#cmakedefine WITH_LIBZ 1
|
||||
#cmakedefine WITH_ZLIB 1
|
||||
|
||||
/* Define to 1 if you want to enable SFTP */
|
||||
#cmakedefine WITH_SFTP 1
|
||||
@@ -120,6 +176,9 @@
|
||||
/* Define to 1 if you want to enable calltrace debug output */
|
||||
#cmakedefine DEBUG_CALLTRACE 1
|
||||
|
||||
/* Define to 1 if you want to enable NaCl support */
|
||||
#cmakedefine WITH_NACL 1
|
||||
|
||||
/*************************** ENDIAN *****************************/
|
||||
|
||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||
|
||||
886
doc/API.html
886
doc/API.html
@@ -1,886 +0,0 @@
|
||||
<!DOCTYPE HTML SYSTEM>
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1">
|
||||
<head>
|
||||
<title>
|
||||
Libssh's Documentation
|
||||
</title>
|
||||
<link href="style.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
|
||||
<div id="titre">
|
||||
<div align="center">
|
||||
LIBSSH API GUIDE <br>
|
||||
Or everything you ever wanted to know about a simple and fast ssh library.
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2> 0 Introduction</h2>
|
||||
|
||||
<div class="tout">
|
||||
Before inserting ssh hooks into your programs, you must know some basics about
|
||||
the ssh protocol, and understand why the ssh library must implement them. <br>
|
||||
Lot of the protocols specifications are hidden by the ssh library API (of
|
||||
course !) but some still needs an attention from the end-user programmer.<br>
|
||||
Note that libssh is still an alpha product, and the API may vary from one
|
||||
version to another. The only guess I can make is that the API won't radically
|
||||
change. <br>
|
||||
The SSH protocol was designed for some goals which I resume here : <br>
|
||||
-Privacy of data<br>
|
||||
-Security<br>
|
||||
-Authentication of the server<br>
|
||||
-Authentication of the client.<br>
|
||||
The client MUST be sure who's speaking to before entering into any
|
||||
authentication way. That's where the end programmer must ensure the given
|
||||
fingerprints *are* from the legitimate server. A ssh connection must follow
|
||||
the following steps:<br>
|
||||
<br>
|
||||
1- Before connecting the socket, you can set up if you wish one or other
|
||||
server public key authentication ie. DSA or RSA.
|
||||
You can choose cryptographic algorithms you trust and compression algorithms
|
||||
if any.<br>
|
||||
2- The connection is made. A secure handshake is made, and resulting from it,
|
||||
a public key from the server is gained.
|
||||
You MUST verify that the public key is legitimate.<br>
|
||||
3- The client must authenticate : the two implemented ways are password, and
|
||||
public keys (from dsa and rsa key-pairs generated by openssh). It is
|
||||
harmless to authenticate to a fake server with these keys because the
|
||||
protocol ensures the data you sign can't be used twice. It just avoids
|
||||
man-in-the-middle attacks.<br>
|
||||
4- Now that the user has been authenticated, you must open one or several
|
||||
channels. channels are different subways for information into a single ssh
|
||||
connection. Each channel has a standard stream (stdout) and an error
|
||||
stream (stderr). You can theoretically open an infinity of channel.<br>
|
||||
5- With the channel you opened, you can do several things :<br>
|
||||
-Open a shell. You may want to request a pseudo virtual terminal before <br>
|
||||
-Execute a command. The virtual terminal is usable, too<br>
|
||||
-Invoke the sftp subsystem. (look at chapter 6)<br>
|
||||
-invoke your own subsystem. This is out the scope of this
|
||||
document but it is easy to do.<br>
|
||||
6- When everything is finished, just close the channels, and then the
|
||||
connection.<br>
|
||||
<br>
|
||||
At every place, a function which returns an error code (typically -1 for int
|
||||
values, NULL for pointers) also sets an error message and an error code.
|
||||
I high-lined the main steps, now that's you to follow them :)
|
||||
<br>
|
||||
</div>
|
||||
<h2> 1- Setting the options </h2>
|
||||
<div class="tout">
|
||||
The options mechanism will change during updates of the library, but the
|
||||
functions which exists now will certainly be kept.
|
||||
<br><br>
|
||||
The ssh system needs to know the preferences of the user, the trust into one
|
||||
or another algorithm and such. More important informations have to be given
|
||||
before connecting : the host name of the server, the port (if non default),
|
||||
the binding address, the default username, ... <br>
|
||||
The options structure is given to a ssh_connect function, then this option
|
||||
structure is used again and again by the ssh implementation. you shall not
|
||||
free it manually, and you shall not share it with multiple sessions.<br>
|
||||
Two ways are given for setting the options : the easy one (of course !) and
|
||||
the long-but-accurate one.<br><br>
|
||||
</div>
|
||||
<h3>a) the easy way</h3><br>
|
||||
<div class="tout">
|
||||
Lot of ssh options in fact come from the command line of the program... <br>
|
||||
you could parse them and then use the long way for every argument, but libssh
|
||||
has a mechanism to do that for you, automatically.<br>
|
||||
<br>
|
||||
<div class="prot">
|
||||
SSH_OPTIONS *ssh_getopt(int *argcptr, char **argv);
|
||||
</div>
|
||||
this function will return you a new options pointer based on the arguments
|
||||
you give in parameters. <br> better, they clean the argv array from used parameters
|
||||
so you can use them after in your own program<br>
|
||||
<div class="ex">
|
||||
int main(int argc, char **argv){<br>
|
||||
SSH_OPTIONS *opt;<br>
|
||||
opt=ssh_getopt(&argc, argv);<br>
|
||||
if(!opt){<br>
|
||||
...<br>
|
||||
}<br>
|
||||
</div>
|
||||
the function will return NULL if some problem is appearing.<br>
|
||||
As a matter of portability for you own programs, the hostname isn't always<br>
|
||||
the first argument from the command line, so the single arguments (not
|
||||
preceded by a -something) won't be parsed.<br>
|
||||
<div class="ex">
|
||||
example: <br>
|
||||
user@host:~$ myssh -u aris localhost <br>
|
||||
-u aris will be caught, localhost will not.<br>
|
||||
</div>
|
||||
|
||||
cfr the options_set_user() function in the next part for more informations
|
||||
about it.<br>
|
||||
</div>
|
||||
<h3>b) the long way</h3>
|
||||
<div class="tout">
|
||||
<div class="prot">
|
||||
SSH_OPTIONS *options_new();
|
||||
</div>
|
||||
This function returns an empty but initialized option structure pointer.<br>
|
||||
The structure is freed by ssh_disconnect described later, so don't use the
|
||||
existing function options_free() (it's an internal function).<br>
|
||||
So : use it only for <b>one</b> ssh_connect(), <b>never</b> free it.<br>
|
||||
<br>
|
||||
<div class="prot">
|
||||
SSH_OPTIONS *options_copy(SSH_OPTIONS *opt);
|
||||
</div>
|
||||
If you need to replicate an option object before using it, use this function.
|
||||
<br><br>
|
||||
|
||||
The following functions are all of the following form : <br>
|
||||
<div class="prot">
|
||||
int options_set_something(SSH_OPTIONS *opt, something);
|
||||
</div>
|
||||
the something parameters are always internaly copied, so you don't have to
|
||||
strdup them.<br>
|
||||
some return eather 0 or -1, in which case an error message appears in the
|
||||
error functions, others never fail (return void)<br>
|
||||
the error codes and descriptions for these functions are recoverable throught <i>ssh_get_error(NULL);</i>
|
||||
<br>
|
||||
<div class="prot">
|
||||
int options_set_wanted_method(SSH_OPTIONS *opt,int method, char *list);
|
||||
</div>
|
||||
Passing an option structure, a ssh macro for the method, and a list of allowed
|
||||
parameters indicates libssh you want to use these.<br>
|
||||
The macros are :<br>
|
||||
KEX_ALGO<br>
|
||||
KEX_HOSTKEY Server public key type expected<br>
|
||||
KEX_CRYPT_C_S 2 Cryptographic algorithm client->server<br>
|
||||
KEX_CRYPT_S_C 3 Cryptographic algorithm server->client<br>
|
||||
KEX_MAC_C_S 4<br>
|
||||
KEX_MAC_S_C 5<br>
|
||||
KEX_COMP_C_S 6 Compression method for the stream ("zlib" or "none"), client to server<br>
|
||||
KEX_COMP_S_C 7 Compression method for the stream ("zlib" or "none"), server to client<br>
|
||||
KEX_LANG_C_S 8<br>
|
||||
KEX_LANG_S_C 9<br>
|
||||
<br>
|
||||
Currently, only KEX_HOSTKEY and ,KEX_CRYPT_C_S,S_C, KEX_COMP_C_S and S_C work
|
||||
as expected. the list is a comma separated string of prefered
|
||||
algorithms/methods, in order of preference.<br>
|
||||
<br>
|
||||
<div class="ex">
|
||||
example : this sets the ssh stream to be compressed in client->server mode only
|
||||
<br>
|
||||
|
||||
ret = option_set_wanted_method(options,KEX_COMP_C_S,"zlib");
|
||||
</div>
|
||||
<div class="ex">
|
||||
example: this will set the cryptographic algorithms wanted from server to
|
||||
client to aes128-cbc and then aes192-cbc if the first one isn't supported by
|
||||
server:<br>
|
||||
ret = option_set_wanted_method(options,KEX_CRYPT_S_C,"aes128-cbc,aes192-cbc");
|
||||
</div>
|
||||
<div class="ex">
|
||||
if you prefer getting the Dss key from a server instead of rsa, but you still
|
||||
accept rsa if dss isn't available :<br>
|
||||
options_set_wanted_method(options,KEX_HOSTKEY,"ssh-dss,ssh-rsa");
|
||||
</div>
|
||||
return value: <br>0 if the option is valid, -1 else.<br> An error is set in that case.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void options_set_port(SSH_OPTIONS *opt, unsigned int port);
|
||||
</div>
|
||||
this function sets the server port.
|
||||
<div class="prot">
|
||||
void options_set_host(SSH_OPTIONS *opt, const char *hostname);
|
||||
</div>
|
||||
this function sets the hostname of the server. It also supports
|
||||
"user@hostname" syntax in which case the user options is set too.
|
||||
<div class="prot">
|
||||
void options_set_fd(SSH_OPTIONS *opt, int fd);
|
||||
</div>
|
||||
permits you to specify an opened file descriptor you've opened yourself.
|
||||
<br>
|
||||
It's a good way of bypassing the internal FD opening in libssh, but there are things you should take care of : <br>
|
||||
-The file descriptor should be returned to libssh without nonblocking settings<br>
|
||||
-If you wish to use <i>is_server_known()</i> You should also set <i>options_set_host</i>... Otherwise libssh won't have any mean of certifying the server is known or not.<br><br>
|
||||
<div class="prot">
|
||||
void options_set_bindaddr(SSH_OPTIONS *opt, char *bindaddr);
|
||||
</div>
|
||||
this function allows you to set the binding address, in case your computer has
|
||||
multiple IP or interfaces. it supports both hostnames and IP's
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void options_set_username(SSH_OPTIONS *opt,char *username);
|
||||
</div>
|
||||
sets username for authenticating in this session.
|
||||
<br><br>
|
||||
|
||||
<div class="prot">
|
||||
void option_set_timeout(SSH_OPTIONS *opt,long seconds, long usec);
|
||||
</div>
|
||||
sets the timeout for connecting to the socket. It does not include a timeout for the name resolving or handshake.
|
||||
<br>
|
||||
<br>
|
||||
<div class="prot">
|
||||
void options_set_ssh_dir(SSH_OPTIONS *opt, char *dir);
|
||||
</div>
|
||||
this function sets the .ssh/ directory used by libssh. You may use a %s
|
||||
which will be replaced by the home directory of the user.
|
||||
NEVER accept parameters others than the user's one, they may contain
|
||||
format strings which are a security hole if a malicious agent gives it.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void options_set_known_hosts_file(SSH_OPTIONS *opt, char *dir);
|
||||
</div>
|
||||
same than <i>options_set_ssh_dir()</i> for known_hosts file.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void options_set_identity(SSH_OPTIONS *opt, char *identity);
|
||||
</div>
|
||||
same than upper for the identity file (they come by pair, the one asked is the file without the .pub suffix)
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void options_set_status_callback(SSH_OPTIONS *opt, void (*callback)(void *arg, float status), void *arg);
|
||||
</div>
|
||||
Because more and more developpers use libssh with GUI, I've added this function to make the ssh_connect function more
|
||||
interactive. This permits to set a callback of the form
|
||||
<div class="prot">void function(void *userarg, float status);</div> with status going from 0 to 1 during ssh_connect. The callback won't ever be called after the connection is made.
|
||||
<br><br>
|
||||
</div>
|
||||
<h2>
|
||||
2- Connecting the ssh server
|
||||
</H2>
|
||||
<div class="tout">
|
||||
The API provides an abstract data type, SSH_SESSION, which describes the
|
||||
connection to one particular server. You can make several connections to
|
||||
different servers under the same process because of this structure.
|
||||
<br>
|
||||
<br>
|
||||
<div class="prot">
|
||||
SSH_SESSION *ssh_connect(SSH_OPTIONS *options);
|
||||
</div>
|
||||
This function returns a handle on the newly connection. This function expects
|
||||
to have a pre-set options structure.
|
||||
<br>
|
||||
It returns NULL in case of error, in which case you can look at error messages
|
||||
for more informations.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void ssh_disconnect(SSH_SESSION *session);
|
||||
</div>
|
||||
This function sends a polite disconnect message, and does clean the session.<br>
|
||||
This is the proper way of finishing a ssh connection.<br>
|
||||
<br>
|
||||
<div class="prot">
|
||||
int ssh_get_pubkey_hash(SSH_SESSION *session, char hash[MD5_DIGEST_LEN]);
|
||||
</div>
|
||||
This function places the MD5 hash of the server public key into the hash array.<br>
|
||||
It's IMPORTANT to verify it matches the previous known value. One server always
|
||||
have the same hash. No other server/attacker can emulate it (or it'd be caught
|
||||
by the public key verification procedure automatically made by libssh).
|
||||
<br>
|
||||
You can skip this step if you correctly handle <i>is_server_known()</i>
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int ssh_is_server_known(SSH_SESSION *session);
|
||||
</div>
|
||||
|
||||
Checks the user's known host file to look for a previous connection to the specified server. Return values:<br>
|
||||
SSH_SERVER_KNOWN_OK : the host is known and the key has not changed<br>
|
||||
SSH_SERVER_KNOWN_CHANGED : The host's key has changed. Either you are under
|
||||
an active attack or the key changed. The API doesn't give any way to modify the key in known hosts yet. I Urge end developers to WARN the user about the possibility of an attack.<br>
|
||||
SSH_SERVER_FOUND_OTHER: The host gave us a public key of one type, which does
|
||||
not exist yet in our known host file, but there is an other type of key which is know.<br>
|
||||
IE server sent a DSA key and we had a RSA key.<br>
|
||||
Be carreful it's a possible attack (coder should use option_set_wanted_method() to specify
|
||||
which key to use).<br>
|
||||
SSH_SERVER_NOT_KNOWN: the server is unknown in known hosts. Possible reasons :
|
||||
case not matching, alias, ... In any case the user MUST confirm the Md5 hash is correct.<br>
|
||||
SSH_SERVER_ERROR : Some error happened while opening known host file.<br>
|
||||
<br>
|
||||
<div class="prot">
|
||||
int ssh_write_knownhost(SSH_SESSION *session);
|
||||
</div>
|
||||
write the current connected host as known in the known host file. returns a negative value if something went wrong. You generaly use it when ssh_is_server_known returned SSH_SERVER_NOT_KNOWN.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int pubkey_get_hash(SSH_SESSION *session,char hash[MD5_DIGEST_LEN]);
|
||||
</div>
|
||||
deprecated but left for binary compatibility (will be removed in newer versions).
|
||||
</div>
|
||||
|
||||
<h2>3- Authenticating to server</h2>
|
||||
<div class="tout">
|
||||
The ssh library supports the two most used authentication methods from SSH.
|
||||
In every function, there is a "username" argument. If null is given instead,
|
||||
the server will use the default username (which is guessed from what you gave
|
||||
to options_set_user or options_set_hostname or even the local user running the code).
|
||||
<br>
|
||||
|
||||
Authentication methods :<br>
|
||||
<h3>A) Public keys</h3><br>
|
||||
The public key is the only method which does not compromise your key if the
|
||||
remote host has been compromised (the server can't do anything more than
|
||||
getting your public key). This is not the case of a password authentication
|
||||
(the server can get your plaintext password).<br>
|
||||
Libssh is obviously fully compatible with the openssh public and private keys.<br>
|
||||
The things go this way : you scan a list of files which contain public keys.<br>
|
||||
For each key, you send it to ssh server until the server acknowledges a key
|
||||
(a key it knows). Then, you get the private key for this key and send a
|
||||
message proving you own that private key.<br>
|
||||
Here again, two ways for the public key authentication... the easy and the
|
||||
complicated one.<br>
|
||||
<br>
|
||||
<h4> easy way:</h4>
|
||||
<div class="prot">
|
||||
int ssh_userauth_autopubkey(SSH_SESSION *session);
|
||||
</div>
|
||||
This function will try the most common places for finding the public and
|
||||
private keys (your home directory) or eventualy the identity files asked by
|
||||
the <i>options_set_identity()</i> function.<br>
|
||||
The return values are :<br>
|
||||
SSH_AUTH_ERROR : some serious error happened during authentication<br>
|
||||
SSH_AUTH_DENIED : no key matched<br>
|
||||
SSH_AUTH_SUCCESS : you are now authenticated<br>
|
||||
SSH_AUTH_PARTIAL : some key matched but you still have to give an other mean
|
||||
of authentication (like password).<br>
|
||||
<br>
|
||||
<h4> peanful way:</h4>
|
||||
there are three steps : you get a public key, you ask the server if the key
|
||||
matches a known one, if true, you get the private key and authenticate with
|
||||
it.<br>
|
||||
<div class="prot">
|
||||
STRING *publickey_from_file(char *filename,int *_type);
|
||||
</div>
|
||||
will return an handle on a public key. if you give a pointer to an int,
|
||||
a symbolic value will be placed there. Do it because you need it in next
|
||||
step.<br><br>
|
||||
<div class="prot">
|
||||
int ssh_userauth_offer_pubkey(SSH_SESSION *session, char *username,
|
||||
int type, STRING *publickey);
|
||||
</div>
|
||||
this function will offer a public key to the server. SSH_AUTH_SUCCESS is
|
||||
returned if the key is accepted (in which case you'll want to get the
|
||||
private key), SSH_AUTH_DENIED otherwise.<br>
|
||||
Still watch for SSH_AUTH_ERROR as connection problems might happen.
|
||||
<br>
|
||||
in case of SSH_AUTH_SUCCESS,
|
||||
<br>
|
||||
<div class="prot">
|
||||
PRIVATE_KEY *privatekey_from_file(SSH_SESSION *session,char *filename,
|
||||
int type,char *passphrase);
|
||||
</div>
|
||||
will get the privatekey from the filename previously set by
|
||||
publickey_from_next_file(). You can call it with a passphrase for
|
||||
unlocking the key. If passphrase==NULL, the default prompt will be used.<br>
|
||||
The function returns NULL if the private key wasn't opened
|
||||
(ie bad passphrase or missing file).<br>
|
||||
<br>
|
||||
<div class="prot">
|
||||
int ssh_userauth_pubkey(SSH_SESSION *session, char *username,
|
||||
STRING *publickey, PRIVATE_KEY *privatekey);
|
||||
</div>
|
||||
Will try to authenticate using the public and private key. It shall return
|
||||
SSH_AUTH_SUCCESS if you are authenticated, SSH_AUTH_ERROR, SSH_AUTH_DENIED or
|
||||
SSH_AUTH_PARTIAL depending of return condition.<br>
|
||||
|
||||
each public key (of type STRING) must be freed with the libc "free" function.<br>
|
||||
The private key must be freed with private_key_free(PRIVATE_KEY *) which
|
||||
will clean the memory before (don't worry about passphrase leaking).<br>
|
||||
<br>
|
||||
|
||||
<h3> B) Password</h3><br>
|
||||
<div class="prot">
|
||||
int ssh_userauth_password(SSH_SESSION *session,char *username,char *password);
|
||||
</div>
|
||||
Will return SSH_AUTH_SUCCESS if the password matched, one of other constants
|
||||
otherwise. It's your work to ask the password and to free it in a secure
|
||||
manner.<br><br>
|
||||
|
||||
<h3> C) Keyboard-interactive</h3><br>
|
||||
<div class="prot">
|
||||
int ssh_userauth_kbdint(SSH_SESSION *session, char *user, char *submethods);
|
||||
</div>
|
||||
This is the main keyboard-interactive function. It will return SSH_AUTH_SUCCESS,SSH_AUTH_DENIED, SSH_AUTH_PARTIAL, SSH_AUTH_ERROR depending on the result of the request.<br>
|
||||
The keyboard-interactive authentication method of SSH2 is a feature which permits the server to ask a certain number of questions in an interactive manner to the client, until it decides to accept or deny the login.<br>
|
||||
To begin, you call this function (you can omit user if it was set previously and omit submethods - instead you know what you do - just put them to NULL) and store the answer.
|
||||
If the answer is SSH_AUTH_INFO, it means the server has sent a few questions to ask your user, which you can retrieve with the following functions. Then, set the answers and call back ssh_userauth_kbdint with same arguments. It may again ask a few other questions etc. until you get an other SSH_AUTH code than SSH_AUTH_INFO.<br>
|
||||
Few remarks :<br>
|
||||
-Even the first call can return SSH_AUTH_DENIED or SSH_AUTH_SUCCESS.<br>
|
||||
-The server can send an empty question set (this is the default behavior on my system) after you have sent the answers to the first questions.
|
||||
you must still parse the answer, it might contain some message from the server saying hello or such things. Just call ssh_userauth_kbdint() once more<br>
|
||||
<br>
|
||||
<div class="prot">
|
||||
int ssh_userauth_kbdint_getnprompts(SSH_SESSION *session);
|
||||
</div>
|
||||
After you called ssh_userauth_kbdint and got SSH_AUTH_INFO, the session contains a few questions (or prompts) from the server. This function returns the number of prompts and answers.<br>
|
||||
It could be zero, in which case you must act as said previously.<br>
|
||||
|
||||
<div class="prot">
|
||||
char *ssh_userauth_kbdint_getname(SSH_SESSION *session);
|
||||
</div>
|
||||
this functions returns the "name" of the message block. The meaning is explained later.<br>
|
||||
This function returns a pointer that stays valid until the next ssh_userauth_kbdint() call and must not be freed.<br>
|
||||
|
||||
<div class="prot">
|
||||
char *ssh_userauth_kbdint_getinstruction(SSH_SESSION *session);
|
||||
</div>
|
||||
this functions returns the "instruction" of the message block. The meaning is explained later.<br>
|
||||
This function returns a pointer that stays valid until the next ssh_userauth_kbdint() call and must not be freed.<br>
|
||||
|
||||
<div class="prot">
|
||||
char *ssh_userauth_kbdint_getprompt(SSH_SESSION *session,int i, char *echo);
|
||||
</div>
|
||||
This functions returns a pointer to the nth prompt. The character pointed by echo, if different from null, will contain a boolean value after the call, which means that the user prompt must be echoed or not.<br>
|
||||
zero means that the echo is Off (like for a password prompt).<br>
|
||||
any other value means the echo is on.<br>
|
||||
This function returns a pointer that stays valid until the next ssh_userauth_kbdint() call and must not be freed.<br>
|
||||
|
||||
<div class="prot">
|
||||
void ssh_userauth_kbdint_setanswer(SSH_SESSION *session, unsigned int i, char *a
|
||||
nswer);
|
||||
</div>
|
||||
This function sets the ith answer. The string you give will be duplicated, and this copy will be discarded once it is no longer necessary.<br>
|
||||
care must be taken so you discard the content of the original string after this function call.<br>
|
||||
|
||||
<h3> A little note about how to use the informations from keyboard-interactive authentication</h3>
|
||||
<br>
|
||||
The words from the original drafts explain everything
|
||||
<div class="prot">
|
||||
3.3 User Interface
|
||||
|
||||
Upon receiving a request message, the client SHOULD prompt the user
|
||||
as follows:<br>
|
||||
A command line interface (CLI) client SHOULD print the name and
|
||||
instruction (if non-empty), adding newlines. Then for each prompt in
|
||||
turn, the client SHOULD display the prompt and read the user input.<br>
|
||||
<br>
|
||||
A graphical user interface (GUI) client has many choices on how to
|
||||
prompt the user. One possibility is to use the name field (possibly
|
||||
prefixed with the application's name) as the title of a dialog window
|
||||
in which the prompt(s) are presented. In that dialog window, the
|
||||
instruction field would be a text message, and the prompts would be
|
||||
labels for text entry fields. All fields SHOULD be presented to the
|
||||
user, for example an implementation SHOULD NOT discard the name field
|
||||
because its windows lack titles; it SHOULD instead find another way
|
||||
to display this information. If prompts are presented in a dialog
|
||||
window, then the client SHOULD NOT present each prompt in a separate
|
||||
window.<br>
|
||||
<br>
|
||||
All clients MUST properly handle an instruction field with embedded
|
||||
newlines. They SHOULD also be able to display at least 30 characters
|
||||
for the name and prompts. If the server presents names or prompts
|
||||
longer than 30 characters, the client MAY truncate these fields to
|
||||
the length it can display. If the client does truncate any fields,
|
||||
there MUST be an obvious indication that such truncation has occured.<br>
|
||||
The instruction field SHOULD NOT be truncated.<br>
|
||||
Clients SHOULD use control character filtering as discussed in
|
||||
[SSH-ARCH] to avoid attacks by including terminal control characters
|
||||
in the fields to be displayed.<br>
|
||||
<br>
|
||||
For each prompt, the corresponding echo field indicates whether or
|
||||
not the user input should be echoed as characters are typed. Clients
|
||||
SHOULD correctly echo/mask user input for each prompt independently
|
||||
of other prompts in the request message. If a client does not honor
|
||||
the echo field for whatever reason, then the client MUST err on the
|
||||
side of masking input. A GUI client might like to have a checkbox
|
||||
toggling echo/mask. Clients SHOULD NOT add any additional characters
|
||||
to the prompt such as ": " (colon-space); the server is responsible
|
||||
for supplying all text to be displayed to the user. Clients MUST
|
||||
also accept empty responses from the user and pass them on as empty
|
||||
strings.<br>
|
||||
|
||||
</div>
|
||||
<br>
|
||||
<h3> D) "none"</h3><br>
|
||||
In fact this mode only serve to get the list of supported authentications.<br>
|
||||
however, it also serves to get the banner message from the server, if any.<br>
|
||||
You should firstly try this method, at least for getting the banner, then to enter if there is no password at all.<br>
|
||||
<div class="prot">
|
||||
int ssh_userauth_none(SSH_SESSION *session, char *username);
|
||||
</div>
|
||||
if the account has no password (and the server is configured to let you
|
||||
pass), the function might answer SSH_AUTH_SUCCESS. That's why
|
||||
ssh_auth_autopubkey already calls it for you.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
char *ssh_get_issue_banner(SSH_SESSION *session);
|
||||
</div>
|
||||
if during authentication, the server has given a banner, you can get it
|
||||
this way. the function returns NULL if no banner exists, and you have to
|
||||
free the returned pointer.<br><br>
|
||||
</div>
|
||||
|
||||
<h2>4- Opening a channel</h2>
|
||||
<div class="tout">
|
||||
Maybe you want to use the sftp subsystem : all this is done for you, you
|
||||
better read at the end of the paper how to use the sftp functions.<br>
|
||||
You probably want to open one or more shells, or call one or more programs.<br>
|
||||
|
||||
So you need a channel.<br>
|
||||
<div class="prot">
|
||||
CHANNEL *channel;
|
||||
</div>
|
||||
This is an handler to a channel object. it describes your channel.
|
||||
<br>
|
||||
<div class="prot">
|
||||
CHANNEL *channel_open_session(SSH_SESSION *session);
|
||||
</div>
|
||||
This will open a channel for use into a session (which can be used for executing
|
||||
a command or a shell. Not for tcp forwarding).<br>
|
||||
The function returns NULL if for a reason or another the channel can't be
|
||||
opened.<br>
|
||||
<i>
|
||||
CHANNEL *open_session_channel(...)</i> is deprecated and should not be used in future
|
||||
applications.<br><br>
|
||||
<div class="prot">
|
||||
CHANNEL *channel_open_forward(SSH_SESSION *session, char *remotehost,
|
||||
int remoteport, char *sourcehost, int localport);
|
||||
</div>
|
||||
Ask the server to tunnel a TCP connection. The server will connect to
|
||||
remotehost:remoteport and libssh will return an handle to the channel if it is allowed.<br>
|
||||
Otherwise, NULL will be returned. sourcehost and localport are generaly
|
||||
used in message debugging purpose and have no effect on the result.<br>
|
||||
<br>
|
||||
When you've finished with your channel, you may send an EOF message and
|
||||
then close it :<br>
|
||||
<div class="prot">
|
||||
void channel_send_eof(CHANNEL *channel);
|
||||
</div>
|
||||
sends an end of file into channel. It doesn't close the channel and you can still read it.<br><br>
|
||||
|
||||
<div class="prot">
|
||||
void channel_free(CHANNEL *channel);
|
||||
</div>
|
||||
closes and destroy the channel.
|
||||
<br>
|
||||
<div class="prot">
|
||||
void channel_close(CHANNEL *channel);
|
||||
</div>
|
||||
sends an EOF and close the channel. (if you don't know what to do, use channel_free). It doesn't free the channel.
|
||||
|
||||
</div>
|
||||
<h2>5- The shell</h2>
|
||||
<div class="tout">
|
||||
<div class="prot">
|
||||
int channel_request_env(CHANNEL *channel, char *name, char *value);
|
||||
</div>
|
||||
Ask the server to set the "name" environment variable to "value". For security
|
||||
reasons, some variables won't be accepted by the server. It returns 0 otherwise.<br><br>
|
||||
<div class="prot">
|
||||
int channel_request_pty(CHANNEL *channel);
|
||||
</div>
|
||||
ask the server to allocate a pseudo terminal for the current channel.<br>
|
||||
the function returns 0 on success.<br><br>
|
||||
|
||||
<div class="prot">
|
||||
int channel_request_pty_size(CHANNEL *channel, char *terminal, int cols, int rows);
|
||||
</div>
|
||||
ask the server to allocate a pty. The terminal parameter is the type of pty
|
||||
(vt100,xterm,...), cols and rows are the size of the new terminal (80x24 by example).<br><br>
|
||||
<div class="prot">
|
||||
int channel_change_pty_size(CHANNEL *channel, int cols,int rows);
|
||||
</div>
|
||||
changes the window size (terminal) of the current session;<br><br>
|
||||
<div class="prot">
|
||||
int channel_request_shell(CHANNEL *channel);
|
||||
</div>
|
||||
This function requests a shell. After its success, a shell is running at the other side of the channel.<br><br>
|
||||
<div class="prot">
|
||||
int channel_request_exec(CHANNEL *channel, char *cmd);
|
||||
</div>
|
||||
run a shell command without an interactive shell, ie $SHELL -c "command".<br>
|
||||
returns 0 on success.<br><br>
|
||||
|
||||
You might ask the server to open a subsystem for you. this is done this way :
|
||||
<div class="prot">
|
||||
int channel_request_subsystem(CHANNEL *channel, char *subsystem);
|
||||
</div>
|
||||
There are some functions used to manipulate the channels :
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int channel_write(CHANNEL *channel,void *data,int len);
|
||||
</div>
|
||||
writes len bytes of data into the channel. It returns the number of bytes written. The current implementation is a blocking write
|
||||
of the complete data buffer, but it may vary.<br><br>
|
||||
<div class="prot">
|
||||
int channel_read(CHANNEL *channel, BUFFER *buffer,int bytes,int is_stderr);
|
||||
</div>
|
||||
It makes a blocking read on the channel, of "bytes" bytes and returns the
|
||||
result into an allocated buffer you passed in. (with <i>buffer_new()</i>).<br>
|
||||
it will read on stderr, if is_stderr is set.<br>
|
||||
The function might read less bytes than "bytes" variable if an End of File
|
||||
happened. Otherwise, the function will always block reading until "bytes"
|
||||
bytes are read.<br>
|
||||
with "bytes"=0, <i>channel_read()</i> will read the current state of the read buffer, but will read at least one byte (and block if nothing is available, except EOF case).<br>
|
||||
|
||||
You don't need to free and allocate a new buffer each time you call this function, just pass the same object each time.<br>
|
||||
look at the <i>buffer_</i> functions further for the correct way of retrieving the data.<br><br>
|
||||
|
||||
<div class="prot">
|
||||
int channel_read_nonblocking (CHANNEL *channel, char *dest, int len, int is_stderr);
|
||||
</div>
|
||||
Non-blocking read on channel, at most len bytes of data are read. Returns 0 if EOF or if no data available.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int channel_is_open(CHANNEL *channel);
|
||||
</div>
|
||||
returns 0 if the channel has been closed by remote host, something else otherwise.<br><br>
|
||||
<div class="prot">
|
||||
int channel_poll(CHANNEL *channel, int is_stderr);
|
||||
</div>
|
||||
This nonblocking function returns the number of bytes immediatly available for
|
||||
reading on the channel and stdin/stderr.<br><br>
|
||||
|
||||
More interesting, if you are going to do channel multiplexing, this function
|
||||
is for you :<br><br>
|
||||
<div class="prot">
|
||||
int ssh_select(CHANNEL **channels,CHANNEL **outchannels, int maxfd,
|
||||
fd_set *readfds, struct timeval *timeout);
|
||||
</div>
|
||||
channels is an array of channel pointers, finished by a NULL pointer.<br>
|
||||
It can be used ever and ever, as it is never written.<br>
|
||||
outchannels is an array of size at least greater or equal to "channels".<br>
|
||||
It hasn't to be initialized.<br>
|
||||
maxfd is the maximum file descriptor from your own filedescriptors.<br>
|
||||
readfds is a pointer to a fd_set structure, like in the original
|
||||
select implementation (man select).<br>
|
||||
the struct timeval *timeout has the same meaning than in
|
||||
select(2) (man select).<br>
|
||||
|
||||
There is no support for writing or special events as in <i>select(2)</i> yet.<br>
|
||||
The function returns -1 if an error occured, or SSH_EINTR if select was interrupted by a syscall. This is not an error, you may restart the function.<br>
|
||||
<b>note about signals:</b> libssh is not threadsafe, and most functions are not
|
||||
reetrant when using the same data structures : it means you *cannot* do anything
|
||||
with a channel from a ssh session passed to <i>ssh_select</i> during a signal.
|
||||
<br>take a look at sample.c on how to bypass that limitation.<br>
|
||||
the function works this way : it returns in the readfds the filedescriptors which have data ready for reading (the given filedescriptors have a greatest priority).<br>
|
||||
Then, if no file descriptor can be read, the function looks for every
|
||||
channel from the array to get a channel with data bufferized. If nothing is
|
||||
available, it waits for activity on any channel/file descriptor and returns
|
||||
immediatly, or waits until timeout.<br>
|
||||
You will find the channels that can be read in the outchannels array (finished by NULL) and the filedescriptors in your fd_set (man FD_ISSET).<br>
|
||||
this is the "heart" of your main loop.<br>
|
||||
<br>
|
||||
<h3>The BUFFER object.</h3>
|
||||
Reading is done through the BUFFER object. here is the public interface :
|
||||
<br>
|
||||
<div class="prot">
|
||||
BUFFER *buffer_new();
|
||||
</div>
|
||||
creates a buffer object.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void *buffer_get(BUFFER *buffer);
|
||||
</div>
|
||||
returns a pointer to the begining of buffer.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int buffer_get_len(BUFFER *buffer);
|
||||
</div>
|
||||
returns buffer's data size.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void buffer_free(BUFFER *buffer);
|
||||
</div>
|
||||
destoys the buffer.
|
||||
<br>
|
||||
<br>
|
||||
How to use the buffer system when you've read something:<br>
|
||||
I've seen people doing such code:<br>
|
||||
<div class="prot">
|
||||
char buffer[256];<br>
|
||||
channel_read(channel,buf,1234,0);<br>
|
||||
strcpy(buffer,buf.data);<br>
|
||||
</div>
|
||||
The correct way of doing this:
|
||||
<div class="prot">
|
||||
char buffer[256];<br>
|
||||
int i;<br>
|
||||
i=channel_read(channel,buf,1234,0);<br>
|
||||
if(i<=0)<br>
|
||||
go_out()...<br>
|
||||
if(i>=256)<br>
|
||||
i=255;<br>
|
||||
memcpy(buffer,buffer_get(buf),i);<br>
|
||||
buffer[i]=0;
|
||||
</div>
|
||||
Do not expect the buffer to be null-terminated. Don't access the internal structure of buffer. Check the sizes before copying.<br>
|
||||
</div>
|
||||
<h2>6- The SFTP subsystem</h2>
|
||||
<div class="tout">
|
||||
SFTP is a secure implementation of a file transfer protocol. The current
|
||||
implemented version is 3. All functions aren't implemented yet but the most
|
||||
important are.<br>
|
||||
<br>
|
||||
<h3>A) Opening the session</h3>
|
||||
<div class="prot">
|
||||
SFTP_SESSION *sftp_new(SSH_SESSION *session);
|
||||
int sftp_init(SFTP_SESSION *sftp);
|
||||
</div>
|
||||
The former returns a SFTP_SESSION handle. It returns NULL if things didn't
|
||||
work as expected.<br>
|
||||
sftp_init makes some initialisation work. It returns 0 if things went right.
|
||||
Both of them must be called.<br>
|
||||
<h3>B) Opening and reading a directory</h3>
|
||||
<div class="prot">
|
||||
SFTP_DIR *sftp_opendir(SFTP_SESSION *session, char *path);
|
||||
</div>
|
||||
opens a directory for file listing. Returns NULL in error case.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
SFTP_ATTRIBUTES *sftp_readdir(SFTP_SESSION *session, SFTP_DIR *dir);
|
||||
</div>
|
||||
This function reads one file attribute from an opened directory. It
|
||||
returns NULL if the directory is EOF, or if something wrong happened.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int sftp_dir_eof(SFTP_DIR *dir);
|
||||
</div>
|
||||
When a <i>sftp_readdir()</i> returned NULL, you can use this function to
|
||||
tell if an EOF occured. the function returns 0 if no EOF occured.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void sftp_attributes_free(SFTP_ATTRIBUTES *file);
|
||||
</div>
|
||||
You have to free any SFTP_ATTRIBUTE structure given by an other function
|
||||
with it.<br><br>
|
||||
<div class="prot">
|
||||
int sftp_dir_close(SFTP_DIR *dir);
|
||||
</div>
|
||||
closes an opened directory. returns 0 when no error occured.
|
||||
<br><br>
|
||||
<h3>C) Opening, reading, writing files</h3>
|
||||
<div class="prot">
|
||||
SFTP_FILE *sftp_open(SFTP_SESSION *session, char *file, int access,
|
||||
SFTP_ATTRIBUTES *attr);
|
||||
</div>
|
||||
Opens a file. The access flags are the same than the stdio flags.<br>
|
||||
see open(2) for more details.<br>
|
||||
attr are the wanted attributes for the new file. If you supply NULL,
|
||||
default values will be used.<br>
|
||||
rem: more work is going on parsing/making the attributes structure
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int sftp_read(SFTP_FILE *file, void *dest, int len);
|
||||
</div>
|
||||
read on a file. Works as the fread() function. It is blocking by default but you can change the default behaviour with <i>sftp_file_set_nonblocking()</i>.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void sftp_file_set_nonblocking(SFTP_FILE *file);
|
||||
</div>
|
||||
sets the file non blocking. reads on this file won't ever block. You can't detect end of files this way.<br>
|
||||
*** TODO more work going there for EOF ****
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void sftp_file_set_blocking(SFTP_FILE *file);
|
||||
</div>
|
||||
restore the default setting of sftp_read.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int sftp_write(SFTP_FILE *file, void *source, int len);
|
||||
</div>
|
||||
works as fwrite() function. It is a blocking write.<br>
|
||||
<br>
|
||||
<div class="prot">
|
||||
void sftp_seek(SFTP_FILE *file, int new_offset);
|
||||
</div>
|
||||
seek into the file for reading/writing at an other place.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
unsigned long sftp_tell(SFTP_FILE *file);
|
||||
</div>
|
||||
returns the current offset (both writing and reading) into the opened file.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void sftp_rewind(SFTP_FILE *file);
|
||||
</div>
|
||||
same as sftp_seek(file,0);
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int sftp_file_close(SFTP_FILE *file);
|
||||
</div>
|
||||
closes a file handle. returns 0 in no error case.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int sftp_rm(SFTP_SESSION *sftp, char *file);
|
||||
</div>
|
||||
deletes a file.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int sftp_rmdir(SFTP_SESSION *sftp, char *directory);
|
||||
</div>
|
||||
<br>
|
||||
deletes a directory.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int sftp_mkdir(SFTP_SESSION *sftp, char *directory, SFTP_ATTRIBUTES *attr);
|
||||
</div>
|
||||
makes a directory, with the given attributes. You can't pass NULL for attr and hope it works.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int sftp_rename(SFTP_SESSION *sftp, char *original, char *newname);
|
||||
</div>
|
||||
changes the name of a file or directory.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int sftp_setstat(SFTP_SESSION *sftp, char *file, SFTP_ATTRIBUTES *attr);
|
||||
</div>
|
||||
changes the attributes of a file or directory.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
char *sftp_canonicalize_path(SFTP_SESSION *sftp, char *path);
|
||||
</div>
|
||||
gives the canonicalized form of some path. You have to
|
||||
free the pointer given in return.<br>
|
||||
(returns NULL if error).
|
||||
<br><br>
|
||||
|
||||
(a function to make proper SFTP_ATTRIBUTES structures is on the way )
|
||||
|
||||
<h3>D) Closing the session</h3>
|
||||
<div class="prot">
|
||||
void sftp_free(SFTP_SESSION *sftp);
|
||||
</div>
|
||||
it closes the sftp channel and subsystem.
|
||||
</div>
|
||||
|
||||
<h2>7- Handling the errors</h2>
|
||||
<div class="tout">
|
||||
When some function returns an error code, it's allways possible to get an
|
||||
english message describing the problem. the function ssh_get_error()
|
||||
returns a pointer to the static error buffer.<br>
|
||||
ssh_error_code() returns the error code number. it's declared as an enum:<br>
|
||||
SSH_NO_ERROR, SSH_REQUEST_DENIED, SSH_INVALID_REQUEST, SSH_CONNECTION_LOST,
|
||||
SSH_FATAL, SSH_INVALID_DATA.<br><br>
|
||||
SSH_REQUEST_DENIED means the ssh server refused your request but the situation is
|
||||
recoverable. the others mean something happened to the connection (some
|
||||
encryption problems, server problems, library bug, ...).<br>
|
||||
SSH_INVALID_REQUEST means the library got some garbage from server. (But might be
|
||||
recoverable).<br>
|
||||
SSH_FATAL means the connection has an important problem and isn't probably
|
||||
recoverable.<br>
|
||||
<br>
|
||||
Most of time, the error returned are SSH_FATAL, but some functions (generaly the
|
||||
<i>ssh_request_*</i> ones) may fail because of server denying request. In these cases, SSH_REQUEST_DENIED is returned.<br><br>
|
||||
|
||||
You'll see in the prototype SSH_SESSION *session. That's because for thread
|
||||
safety, error messages that can be attached to a session aren't static
|
||||
anymore. So, any error that could happen during ssh_getopt(), options_* or
|
||||
ssh_connect() will be retreavable giving NULL as argument.<br>
|
||||
<br>
|
||||
<div class="prot">
|
||||
char *ssh_get_error(SSH_SESSION *session);
|
||||
</div>
|
||||
returns a pointer to a static message error from the given session. No
|
||||
message freeing is needed.<br><br>
|
||||
<div class="prot">
|
||||
enum ssh_error ssh_get_error_code(SSH_SESSION *session);
|
||||
</div>
|
||||
returns the error code that last happened along with the message.
|
||||
<br><br>
|
||||
</div>
|
||||
|
||||
<h2>8- Final word</h2>
|
||||
<div class="tout">
|
||||
I made this library because nothing in the Open source or free software community was existing yet. This project is a very personnal one as it's the first "useful" thing I ever wrote.
|
||||
I hope it fits your needs, but remember the experimental state of libssh : if
|
||||
something doesn't work, please mail me. If something lacks, please ask for it.
|
||||
If something stinks, please write a patch and send it !
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
<!-- Doxygen TracFooter -->
|
||||
@@ -1,4 +0,0 @@
|
||||
<!-- Doxygen TracHeader -->
|
||||
<style>@import url(/chrome/site/doxygen.css);</style>
|
||||
<style>@import url(/chrome/site/tabs.css);</style>
|
||||
<!-- /Doxygen TracHeader -->
|
||||
375
doc/authentication.dox
Normal file
375
doc/authentication.dox
Normal file
@@ -0,0 +1,375 @@
|
||||
/**
|
||||
@page libssh_tutor_authentication Chapter 2: A deeper insight on authentication
|
||||
@section authentication_details A deeper insight on authentication
|
||||
|
||||
In our guided tour, we merely mentioned that the user needed to authenticate.
|
||||
We didn't explain much in detail how that was supposed to happen.
|
||||
This chapter explains better the four authentication methods: with public keys,
|
||||
with a password, with challenges and responses (keyboard-interactive), and with
|
||||
no authentication at all.
|
||||
|
||||
If your software is supposed to connect to an arbitrary server, then you
|
||||
might need to support all authentication methods. If your software will
|
||||
connect only to a given server, then it might be enough for your software
|
||||
to support only the authentication methods used by that server. If you are
|
||||
the administrator of the server, it might be your call to choose those
|
||||
authentication methods.
|
||||
|
||||
It is not the purpose of this document to review in detail the advantages
|
||||
and drawbacks of each authentication method. You are therefore invited
|
||||
to read the abundant documentation on this topic to fully understand the
|
||||
advantages and security risks linked to each method.
|
||||
|
||||
|
||||
@subsection pubkeys Authenticating with public keys
|
||||
|
||||
libssh is fully compatible with the openssh public and private keys. You
|
||||
can either use the automatic public key authentication method provided by
|
||||
libssh, or roll your own using the public key functions.
|
||||
|
||||
The process of authenticating by public key to a server is the following:
|
||||
- you scan a list of files that contain public keys. each key is sent to
|
||||
the SSH server, until the server acknowledges a key (a key it knows can be
|
||||
used to authenticate the user).
|
||||
- then, you retrieve the private key for this key and send a message
|
||||
proving that you know that private key.
|
||||
|
||||
The function ssh_userauth_autopubkey() does this using the available keys in
|
||||
"~/.ssh/". The return values are the following:
|
||||
- SSH_AUTH_ERROR: some serious error happened during authentication
|
||||
- SSH_AUTH_DENIED: no key matched
|
||||
- SSH_AUTH_SUCCESS: you are now authenticated
|
||||
- SSH_AUTH_PARTIAL: some key matched but you still have to provide an other
|
||||
mean of authentication (like a password).
|
||||
|
||||
The ssh_userauth_publickey_auto() function also tries to authenticate using the
|
||||
SSH agent, if you have one running, or the "none" method otherwise.
|
||||
|
||||
If you wish to authenticate with public key by your own, follow these steps:
|
||||
- Retrieve the public key with ssh_import_pubkey_file().
|
||||
- Offer the public key to the SSH server using ssh_userauth_try_publickey().
|
||||
If the return value is SSH_AUTH_SUCCESS, the SSH server accepts to
|
||||
authenticate using the public key and you can go to the next step.
|
||||
- Retrieve the private key, using the ssh_pki_import_privkey_file() function.
|
||||
If a passphrase is needed, either the passphrase specified as argument or
|
||||
a callback will be used.
|
||||
- Authenticate using ssh_userauth_publickey() with your private key.
|
||||
- Do not forget cleaning up memory using ssh_key_free().
|
||||
|
||||
Here is a minimalistic example of public key authentication:
|
||||
|
||||
@code
|
||||
int authenticate_pubkey(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = ssh_userauth_publickey_auto(session, NULL);
|
||||
|
||||
if (rc == SSH_AUTH_ERROR)
|
||||
{
|
||||
fprintf(stderr, "Authentication failed: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@see ssh_userauth_publickey_auto()
|
||||
@see ssh_userauth_try_publickey()
|
||||
@see ssh_userauth_publickey()
|
||||
@see ssh_pki_import_pubkey_file()
|
||||
@see ssh_pki_import_privkey_file()
|
||||
@see ssh_key_free()
|
||||
|
||||
|
||||
@subsection password Authenticating with a password
|
||||
|
||||
The function ssh_userauth_password() serves the purpose of authenticating
|
||||
using a password. It will return SSH_AUTH_SUCCESS if the password worked,
|
||||
or one of other constants otherwise. It's your work to ask the password
|
||||
and to deallocate it in a secure manner.
|
||||
|
||||
If your server complains that the password is wrong, but you can still
|
||||
authenticate using openssh's client (issuing password), it's probably
|
||||
because openssh only accept keyboard-interactive. Switch to
|
||||
keyboard-interactive authentication, or try to configure plain text passwords
|
||||
on the SSH server.
|
||||
|
||||
Here is a small example of password authentication:
|
||||
|
||||
@code
|
||||
int authenticate_password(ssh_session session)
|
||||
{
|
||||
char *password;
|
||||
int rc;
|
||||
|
||||
password = getpass("Enter your password: ");
|
||||
rc = ssh_userauth_password(session, NULL, password);
|
||||
if (rc == SSH_AUTH_ERROR)
|
||||
{
|
||||
fprintf(stderr, "Authentication failed: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@see ssh_userauth_password
|
||||
|
||||
|
||||
@subsection keyb_int The keyboard-interactive authentication method
|
||||
|
||||
The keyboard-interactive method is, as its name tells, interactive. The
|
||||
server will issue one or more challenges that the user has to answer,
|
||||
until the server takes an authentication decision.
|
||||
|
||||
ssh_userauth_kbdint() is the the main keyboard-interactive function.
|
||||
It will return SSH_AUTH_SUCCESS,SSH_AUTH_DENIED, SSH_AUTH_PARTIAL,
|
||||
SSH_AUTH_ERROR, or SSH_AUTH_INFO, depending on the result of the request.
|
||||
|
||||
The keyboard-interactive authentication method of SSH2 is a feature that
|
||||
permits the server to ask a certain number of questions in an interactive
|
||||
manner to the client, until it decides to accept or deny the login.
|
||||
|
||||
To begin, you call ssh_userauth_kbdint() (just set user and submethods to
|
||||
NULL) and store the answer.
|
||||
|
||||
If the answer is SSH_AUTH_INFO, it means that the server has sent a few
|
||||
questions that you should ask the user. You can retrieve these questions
|
||||
with the following functions: ssh_userauth_kbdint_getnprompts(),
|
||||
ssh_userauth_kbdint_getname(), ssh_userauth_kbdint_getinstruction(), and
|
||||
ssh_userauth_kbdint_getprompt().
|
||||
|
||||
Set the answer for each question in the challenge using
|
||||
ssh_userauth_kbdint_setanswer().
|
||||
|
||||
Then, call again ssh_userauth_kbdint() and start the process again until
|
||||
these functions returns something else than SSH_AUTH_INFO.
|
||||
|
||||
Here are a few remarks:
|
||||
- Even the first call can return SSH_AUTH_DENIED or SSH_AUTH_SUCCESS.
|
||||
- The server can send an empty question set (this is the default behavior
|
||||
on my system) after you have sent the answers to the first questions.
|
||||
You must still parse the answer, it might contain some
|
||||
message from the server saying hello or such things. Just call
|
||||
ssh_userauth_kbdint() until needed.
|
||||
- The meaning of "name", "prompt", "instruction" may be a little
|
||||
confusing. An explanation is given in the RFC section that follows.
|
||||
|
||||
Here is a little note about how to use the information from
|
||||
keyboard-interactive authentication, coming from the RFC itself (rfc4256):
|
||||
|
||||
@verbatim
|
||||
|
||||
3.3 User Interface Upon receiving a request message, the client SHOULD
|
||||
prompt the user as follows: A command line interface (CLI) client SHOULD
|
||||
print the name and instruction (if non-empty), adding newlines. Then for
|
||||
each prompt in turn, the client SHOULD display the prompt and read the
|
||||
user input.
|
||||
|
||||
A graphical user interface (GUI) client has many choices on how to prompt
|
||||
the user. One possibility is to use the name field (possibly prefixed
|
||||
with the application's name) as the title of a dialog window in which
|
||||
the prompt(s) are presented. In that dialog window, the instruction field
|
||||
would be a text message, and the prompts would be labels for text entry
|
||||
fields. All fields SHOULD be presented to the user, for example an
|
||||
implementation SHOULD NOT discard the name field because its windows lack
|
||||
titles; it SHOULD instead find another way to display this information. If
|
||||
prompts are presented in a dialog window, then the client SHOULD NOT
|
||||
present each prompt in a separate window.
|
||||
|
||||
All clients MUST properly handle an instruction field with embedded
|
||||
newlines. They SHOULD also be able to display at least 30 characters for
|
||||
the name and prompts. If the server presents names or prompts longer than 30
|
||||
characters, the client MAY truncate these fields to the length it can
|
||||
display. If the client does truncate any fields, there MUST be an obvious
|
||||
indication that such truncation has occured.
|
||||
|
||||
The instruction field SHOULD NOT be truncated. Clients SHOULD use control
|
||||
character filtering as discussed in [SSH-ARCH] to avoid attacks by
|
||||
including terminal control characters in the fields to be displayed.
|
||||
|
||||
For each prompt, the corresponding echo field indicates whether or not
|
||||
the user input should be echoed as characters are typed. Clients SHOULD
|
||||
correctly echo/mask user input for each prompt independently of other
|
||||
prompts in the request message. If a client does not honor the echo field
|
||||
for whatever reason, then the client MUST err on the side of
|
||||
masking input. A GUI client might like to have a checkbox toggling
|
||||
echo/mask. Clients SHOULD NOT add any additional characters to the prompt
|
||||
such as ": " (colon-space); the server is responsible for supplying all
|
||||
text to be displayed to the user. Clients MUST also accept empty responses
|
||||
from the user and pass them on as empty strings.
|
||||
@endverbatim
|
||||
|
||||
The following example shows how to perform keyboard-interactive authentication:
|
||||
|
||||
@code
|
||||
int authenticate_kbdint(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = ssh_userauth_kbdint(session, NULL, NULL);
|
||||
while (rc == SSH_AUTH_INFO)
|
||||
{
|
||||
const char *name, *instruction;
|
||||
int nprompts, iprompt;
|
||||
|
||||
name = ssh_userauth_kbdint_getname(session);
|
||||
instruction = ssh_userauth_kbdint_getinstruction(session);
|
||||
nprompts = ssh_userauth_kbdint_getnprompts(session);
|
||||
|
||||
if (strlen(name) > 0)
|
||||
printf("%s\n", name);
|
||||
if (strlen(instruction) > 0)
|
||||
printf("%s\n", instruction);
|
||||
for (iprompt = 0; iprompt < nprompts; iprompt++)
|
||||
{
|
||||
const char *prompt;
|
||||
char echo;
|
||||
|
||||
prompt = ssh_userauth_kbdint_getprompt(session, iprompt, &echo);
|
||||
if (echo)
|
||||
{
|
||||
char buffer[128], *ptr;
|
||||
|
||||
printf("%s", prompt);
|
||||
if (fgets(buffer, sizeof(buffer), stdin) == NULL)
|
||||
return SSH_AUTH_ERROR;
|
||||
buffer[sizeof(buffer) - 1] = '\0';
|
||||
if ((ptr = strchr(buffer, '\n')) != NULL)
|
||||
*ptr = '\0';
|
||||
if (ssh_userauth_kbdint_setanswer(session, iprompt, buffer) < 0)
|
||||
return SSH_AUTH_ERROR;
|
||||
memset(buffer, 0, strlen(buffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
ptr = getpass(prompt);
|
||||
if (ssh_userauth_kbdint_setanswer(session, iprompt, ptr) < 0)
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
}
|
||||
rc = ssh_userauth_kbdint(session, NULL, NULL);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@see ssh_userauth_kbdint()
|
||||
@see ssh_userauth_kbdint_getnprompts()
|
||||
@see ssh_userauth_kbdint_getname()
|
||||
@see ssh_userauth_kbdint_getinstruction()
|
||||
@see ssh_userauth_kbdint_getprompt()
|
||||
@see ssh_userauth_kbdint_setanswer()
|
||||
|
||||
|
||||
@subsection none Authenticating with "none" method
|
||||
|
||||
The primary purpose of the "none" method is to get authenticated **without**
|
||||
any credential. Don't do that, use one of the other authentication methods,
|
||||
unless you really want to grant anonymous access.
|
||||
|
||||
If the account has no password, and if the server is configured to let you
|
||||
pass, ssh_userauth_none() might answer SSH_AUTH_SUCCESS.
|
||||
|
||||
The following example shows how to perform "none" authentication:
|
||||
|
||||
@code
|
||||
int authenticate_kbdint(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@subsection auth_list Getting the list of supported authentications
|
||||
|
||||
You are not meant to choose a given authentication method, you can
|
||||
let the server tell you which methods are available. Once you know them,
|
||||
you try them one after the other.
|
||||
|
||||
The following example shows how to get the list of available authentication
|
||||
methods with ssh_userauth_list() and how to use the result:
|
||||
|
||||
@code
|
||||
int test_several_auth_methods(ssh_session session)
|
||||
{
|
||||
int method, rc;
|
||||
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
if (rc != SSH_AUTH_SUCCESS) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
method = ssh_userauth_list(session, NULL);
|
||||
|
||||
if (method & SSH_AUTH_METHOD_NONE)
|
||||
{ // For the source code of function authenticate_none(),
|
||||
// refer to the corresponding example
|
||||
rc = authenticate_none(session);
|
||||
if (rc == SSH_AUTH_SUCCESS) return rc;
|
||||
}
|
||||
if (method & SSH_AUTH_METHOD_PUBLICKEY)
|
||||
{ // For the source code of function authenticate_pubkey(),
|
||||
// refer to the corresponding example
|
||||
rc = authenticate_pubkey(session);
|
||||
if (rc == SSH_AUTH_SUCCESS) return rc;
|
||||
}
|
||||
if (method & SSH_AUTH_METHOD_INTERACTIVE)
|
||||
{ // For the source code of function authenticate_kbdint(),
|
||||
// refer to the corresponding example
|
||||
rc = authenticate_kbdint(session);
|
||||
if (rc == SSH_AUTH_SUCCESS) return rc;
|
||||
}
|
||||
if (method & SSH_AUTH_METHOD_PASSWORD)
|
||||
{ // For the source code of function authenticate_password(),
|
||||
// refer to the corresponding example
|
||||
rc = authenticate_password(session);
|
||||
if (rc == SSH_AUTH_SUCCESS) return rc;
|
||||
}
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection banner Getting the banner
|
||||
|
||||
The SSH server might send a banner, which you can retrieve with
|
||||
ssh_get_issue_banner(), then display to the user.
|
||||
|
||||
The following example shows how to retrieve and dispose the issue banner:
|
||||
|
||||
@code
|
||||
int display_banner(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
char *banner;
|
||||
|
||||
/*
|
||||
*** Does not work without calling ssh_userauth_none() first ***
|
||||
*** That will be fixed ***
|
||||
*/
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
if (rc == SSH_AUTH_ERROR)
|
||||
return rc;
|
||||
|
||||
banner = ssh_get_issue_banner(session);
|
||||
if (banner)
|
||||
{
|
||||
printf("%s\n", banner);
|
||||
free(banner);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
*/
|
||||
94
doc/command.dox
Normal file
94
doc/command.dox
Normal file
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
@page libssh_tutor_command Chapter 4: Passing a remote command
|
||||
@section remote_command Passing a remote command
|
||||
|
||||
Previous chapter has shown how to open a full shell session, with an attached
|
||||
terminal or not. If you only need to execute a command on the remote end,
|
||||
you don't need all that complexity.
|
||||
|
||||
The method described here is suited for executing only one remote command.
|
||||
If you need to issue several commands in a row, you should consider using
|
||||
a non-interactive remote shell, as explained in previous chapter.
|
||||
|
||||
@see shell
|
||||
|
||||
|
||||
@subsection exec_remote Executing a remote command
|
||||
|
||||
The first steps for executing a remote command are identical to those
|
||||
for opening remote shells. You first need a SSH channel, and then
|
||||
a SSH session that uses this channel:
|
||||
|
||||
@code
|
||||
int show_remote_files(ssh_session session)
|
||||
{
|
||||
ssh_channel channel;
|
||||
int rc;
|
||||
|
||||
channel = ssh_channel_new(session);
|
||||
if (channel == NULL) return SSH_ERROR;
|
||||
|
||||
rc = ssh_channel_open_session(channel);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
ssh_channel_free(channel);
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
Once a session is open, you can start the remote command with
|
||||
ssh_channel_request_exec():
|
||||
|
||||
@code
|
||||
rc = ssh_channel_request_exec(channel, "ls -l");
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
If the remote command displays data, you get them with ssh_channel_read().
|
||||
This function returns the number of bytes read. If there is no more
|
||||
data to read on the channel, this function returns 0, and you can go to next step.
|
||||
If an error has been encountered, it returns a negative value:
|
||||
|
||||
@code
|
||||
char buffer[256];
|
||||
unsigned int nbytes;
|
||||
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
while (nbytes > 0)
|
||||
{
|
||||
if (fwrite(buffer, 1, nbytes, stdout) != nbytes)
|
||||
{
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
}
|
||||
|
||||
if (nbytes < 0)
|
||||
{
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
@endcode
|
||||
|
||||
Once you read the result of the remote command, you send an
|
||||
end-of-file to the channel, close it, and free the memory
|
||||
that it used:
|
||||
|
||||
@code
|
||||
ssh_channel_send_eof(channel);
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
*/
|
||||
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
|
||||
1445
doc/doxy.config.in
1445
doc/doxy.config.in
File diff suppressed because it is too large
Load Diff
230
doc/forwarding.dox
Normal file
230
doc/forwarding.dox
Normal file
@@ -0,0 +1,230 @@
|
||||
/**
|
||||
@page libssh_tutor_forwarding Chapter 7: Forwarding connections (tunnel)
|
||||
@section forwarding_connections Forwarding connections
|
||||
|
||||
Port forwarding comes in SSH protocol in two different flavours:
|
||||
direct or reverse port forwarding. Direct port forwarding is also
|
||||
named local port forwardind, and reverse port forwarding is also called
|
||||
remote port forwarding. SSH also allows X11 tunnels.
|
||||
|
||||
|
||||
|
||||
@subsection forwarding_direct Direct port forwarding
|
||||
|
||||
Direct port forwarding is from client to server. The client opens a tunnel,
|
||||
and forwards whatever data to the server. Then, the server connects to an
|
||||
end point. The end point can reside on another machine or on the SSH
|
||||
server itself.
|
||||
|
||||
Example of use of direct port forwarding:
|
||||
@verbatim
|
||||
Mail client application Google Mail
|
||||
| ^
|
||||
5555 (arbitrary) |
|
||||
| 143 (IMAP2)
|
||||
V |
|
||||
SSH client =====> SSH server
|
||||
|
||||
Legend:
|
||||
--P-->: port connexion through port P
|
||||
=====>: SSH tunnel
|
||||
@endverbatim
|
||||
A mail client connects to port 5555 of a client. An encrypted tunnel is
|
||||
established to the server. The server connects to port 143 of Google Mail (the
|
||||
end point). Now the local mail client can retreive mail.
|
||||
|
||||
|
||||
@subsection forwarding_reverse Reverse port forwarding
|
||||
|
||||
The reverse forwarding is slightly different. It goes from server to client,
|
||||
even though the client has the initiative of establishing the tunnel.
|
||||
Once the tunnel is established, the server will listen on a port. Whenever
|
||||
a connection to this port is made, the server forwards the data to the client.
|
||||
|
||||
Example of use of reverse port forwarding:
|
||||
@verbatim
|
||||
Local mail server Mail client application
|
||||
^ |
|
||||
| 5555 (arbitrary)
|
||||
143 (IMAP2) |
|
||||
| V
|
||||
SSH client <===== SSH server
|
||||
|
||||
Legend:
|
||||
--P-->: port connexion through port P
|
||||
=====>: SSH tunnel
|
||||
@endverbatim
|
||||
In this example, the SSH client establishes the tunnel,
|
||||
but it is used to forward the connections established at
|
||||
the server to the client.
|
||||
|
||||
|
||||
@subsection forwarding_x11 X11 tunnels
|
||||
|
||||
X11 tunnels allow a remote application to display locally.
|
||||
|
||||
Example of use of X11 tunnels:
|
||||
@verbatim
|
||||
Local display Graphical application
|
||||
(X11 server) (X11 client)
|
||||
^ |
|
||||
| V
|
||||
SSH client <===== SSH server
|
||||
|
||||
Legend:
|
||||
----->: X11 connection through X11 display number
|
||||
=====>: SSH tunnel
|
||||
@endverbatim
|
||||
The SSH tunnel is established by the client.
|
||||
|
||||
How to establish X11 tunnels with libssh has already been described in
|
||||
this tutorial.
|
||||
|
||||
@see x11
|
||||
|
||||
|
||||
@subsection libssh_direct Doing direct port forwarding with libssh
|
||||
|
||||
To do direct port forwarding, call function ssh_channel_open_forward():
|
||||
- you need a separate channel for the tunnel as first parameter;
|
||||
- second and third parameters are the remote endpoint;
|
||||
- fourth and fifth parameters are sent to the remote server
|
||||
so that they can be logged on that server.
|
||||
|
||||
If you don't plan to forward the data you will receive to any local port,
|
||||
just put fake values like "localhost" and 5555 as your local host and port.
|
||||
|
||||
The example below shows how to open a direct channel that would be
|
||||
used to retrieve google's home page from the remote SSH server.
|
||||
|
||||
@code
|
||||
int direct_forwarding(ssh_session session)
|
||||
{
|
||||
ssh_channel forwarding_channel;
|
||||
int rc;
|
||||
char *http_get = "GET / HTTP/1.1\nHost: www.google.com\n\n";
|
||||
int nbytes, nwritten;
|
||||
|
||||
forwarding_channel = ssh_channel_new(session);
|
||||
if (forwarding_channel == NULL) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = ssh_channel_open_forward(forwarding_channel,
|
||||
"www.google.com", 80,
|
||||
"localhost", 5555);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
ssh_channel_free(forwarding_channel);
|
||||
return rc;
|
||||
}
|
||||
|
||||
nbytes = strlen(http_get);
|
||||
nwritten = ssh_channel_write(forwarding_channel,
|
||||
http_get,
|
||||
nbytes);
|
||||
if (nbytes != nwritten)
|
||||
{
|
||||
ssh_channel_free(forwarding_channel);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
ssh_channel_free(forwarding_channel);
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
The data sent by Google can be retrieved for example with ssh_select()
|
||||
and ssh_channel_read(). Goggle's home page can then be displayed on the
|
||||
local SSH client, saved into a local file, made available on a local port,
|
||||
or whatever use you have for it.
|
||||
|
||||
|
||||
@subsection libssh_reverse Doing reverse port forwarding with libssh
|
||||
|
||||
To do reverse port forwarding, call ssh_channel_listen_forward(),
|
||||
then ssh_channel_accept_forward().
|
||||
|
||||
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
|
||||
your own priviledged or non-priviledged port. Beware that you should have
|
||||
administrative priviledges on the remote server to open a priviledged port
|
||||
(port number < 1024).
|
||||
|
||||
Below is an example of a very rough web server waiting for connections on port
|
||||
8080 of remote SSH server. The incoming connections are passed to the
|
||||
local libssh application, which handles them:
|
||||
|
||||
@code
|
||||
int web_server(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
ssh_channel channel;
|
||||
char buffer[256];
|
||||
int nbytes, nwritten;
|
||||
int port = 0;
|
||||
char *helloworld = ""
|
||||
"HTTP/1.1 200 OK\n"
|
||||
"Content-Type: text/html\n"
|
||||
"Content-Length: 113\n"
|
||||
"\n"
|
||||
"<html>\n"
|
||||
" <head>\n"
|
||||
" <title>Hello, World!</title>\n"
|
||||
" </head>\n"
|
||||
" <body>\n"
|
||||
" <h1>Hello, World!</h1>\n"
|
||||
" </body>\n"
|
||||
"</html>\n";
|
||||
|
||||
rc = ssh_channel_listen_forward(session, NULL, 8080, NULL);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Error opening remote port: %s\n",
|
||||
ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
|
||||
channel = ssh_channel_accept_forward(session, 60000, &port);
|
||||
if (channel == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error waiting for incoming connection: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
if (nbytes < 0)
|
||||
{
|
||||
fprintf(stderr, "Error reading incoming data: %s\n",
|
||||
ssh_get_error(session));
|
||||
ssh_channel_send_eof(channel);
|
||||
ssh_channel_free(channel);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (strncmp(buffer, "GET /", 5)) continue;
|
||||
|
||||
nbytes = strlen(helloworld);
|
||||
nwritten = ssh_channel_write(channel, helloworld, nbytes);
|
||||
if (nwritten != nbytes)
|
||||
{
|
||||
fprintf(stderr, "Error sending answer: %s\n",
|
||||
ssh_get_error(session));
|
||||
ssh_channel_send_eof(channel);
|
||||
ssh_channel_free(channel);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
printf("Sent answer\n");
|
||||
}
|
||||
|
||||
ssh_channel_send_eof(channel);
|
||||
ssh_channel_free(channel);
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
*/
|
||||
454
doc/guided_tour.dox
Normal file
454
doc/guided_tour.dox
Normal file
@@ -0,0 +1,454 @@
|
||||
/**
|
||||
@page libssh_tutor_guided_tour Chapter 1: A typical SSH session
|
||||
@section ssh_session A typical SSH session
|
||||
|
||||
A SSH session goes through the following steps:
|
||||
|
||||
- Before connecting to the server, you can set up if you wish one or other
|
||||
server public key authentication, i.e. DSA or RSA. You can choose
|
||||
cryptographic algorithms you trust and compression algorithms if any. You
|
||||
must of course set up the hostname.
|
||||
|
||||
- The connection is established. A secure handshake is made, and resulting from
|
||||
it, a public key from the server is gained. You MUST verify that the public
|
||||
key is legitimate, using for instance the MD5 fingerprint or the known hosts
|
||||
file.
|
||||
|
||||
- The client must authenticate: the classical ways are password, or
|
||||
public keys (from dsa and rsa key-pairs generated by openssh).
|
||||
If a SSH agent is running, it is possible to use it.
|
||||
|
||||
- Now that the user has been authenticated, you must open one or several
|
||||
channels. Channels are different subways for information into a single ssh
|
||||
connection. Each channel has a standard stream (stdout) and an error stream
|
||||
(stderr). You can theoretically open an infinity of channels.
|
||||
|
||||
- With the channel you opened, you can do several things:
|
||||
- Execute a single command.
|
||||
- Open a shell. You may want to request a pseudo-terminal before.
|
||||
- Invoke the sftp subsystem to transfer files.
|
||||
- Invoke the scp subsystem to transfer files.
|
||||
- Invoke your own subsystem. This is outside the scope of this document,
|
||||
but can be done.
|
||||
|
||||
- When everything is finished, just close the channels, and then the connection.
|
||||
|
||||
The sftp and scp subsystems use channels, but libssh hides them to
|
||||
the programmer. If you want to use those subsystems, instead of a channel,
|
||||
you'll usually open a "sftp session" or a "scp session".
|
||||
|
||||
|
||||
@subsection setup Creating the session and setting options
|
||||
|
||||
The most important object in a SSH connection is the SSH session. In order
|
||||
to allocate a new SSH session, you use ssh_new(). Don't forget to
|
||||
always verify that the allocation successed.
|
||||
@code
|
||||
#include <libssh/libssh.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
ssh_session my_ssh_session = ssh_new();
|
||||
if (my_ssh_session == NULL)
|
||||
exit(-1);
|
||||
...
|
||||
ssh_free(my_ssh_session);
|
||||
}
|
||||
@endcode
|
||||
|
||||
libssh follows the allocate-it-deallocate-it pattern. Each object that you allocate
|
||||
using xxxxx_new() must be deallocated using xxxxx_free(). In this case, ssh_new()
|
||||
does the allocation and ssh_free() does the contrary.
|
||||
|
||||
The ssh_options_set() function sets the options of the session. The most important options are:
|
||||
- SSH_OPTIONS_HOST: the name of the host you want to connect to
|
||||
- SSH_OPTIONS_PORT: the used port (default is port 22)
|
||||
- SSH_OPTIONS_USER: the system user under which you want to connect
|
||||
- SSH_OPTIONS_LOG_VERBOSITY: the quantity of messages that are printed
|
||||
|
||||
The complete list of options can be found in the documentation of ssh_options_set().
|
||||
The only mandatory option is SSH_OPTIONS_HOST. If you don't use SSH_OPTIONS_USER,
|
||||
the local username of your account will be used.
|
||||
|
||||
Here is a small example of how to use it:
|
||||
|
||||
@code
|
||||
#include <libssh/libssh.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
ssh_session my_ssh_session;
|
||||
int verbosity = SSH_LOG_PROTOCOL;
|
||||
int port = 22;
|
||||
|
||||
my_ssh_session = ssh_new();
|
||||
if (my_ssh_session == NULL)
|
||||
exit(-1);
|
||||
|
||||
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
|
||||
ssh_options_set(my_ssh_session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||
ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, &port);
|
||||
|
||||
...
|
||||
|
||||
ssh_free(my_ssh_session);
|
||||
}
|
||||
@endcode
|
||||
|
||||
Please notice that all parameters are passed to ssh_options_set() as pointers,
|
||||
even if you need to set an integer value.
|
||||
|
||||
@see ssh_new
|
||||
@see ssh_free
|
||||
@see ssh_options_set
|
||||
@see ssh_options_parse_config
|
||||
@see ssh_options_copy
|
||||
@see ssh_options_getopt
|
||||
|
||||
|
||||
@subsection connect Connecting to the server
|
||||
|
||||
Once all settings have been made, you can connect using ssh_connect(). That
|
||||
function will return SSH_OK if the connection worked, SSH_ERROR otherwise.
|
||||
|
||||
You can get the English error string with ssh_get_error() in order to show the
|
||||
user what went wrong. Then, use ssh_disconnect() when you want to stop
|
||||
the session.
|
||||
|
||||
Here's an example:
|
||||
|
||||
@code
|
||||
#include <libssh/libssh.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
ssh_session my_ssh_session;
|
||||
int rc;
|
||||
|
||||
my_ssh_session = ssh_new();
|
||||
if (my_ssh_session == NULL)
|
||||
exit(-1);
|
||||
|
||||
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
|
||||
|
||||
rc = ssh_connect(my_ssh_session);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Error connecting to localhost: %s\n",
|
||||
ssh_get_error(my_ssh_session));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
ssh_disconnect(my_ssh_session);
|
||||
ssh_free(my_ssh_session);
|
||||
}
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection serverauth Authenticating the server
|
||||
|
||||
Once you're connected, the following step is mandatory: you must check that the server
|
||||
you just connected to is known and safe to use (remember, SSH is about security and
|
||||
authentication).
|
||||
|
||||
There are two ways of doing this:
|
||||
- The first way (recommended) is to use the ssh_is_server_known()
|
||||
function. This function will look into the known host file
|
||||
(~/.ssh/known_hosts on UNIX), look for the server hostname's pattern,
|
||||
and determine whether this host is present or not in the list.
|
||||
- The second way is to use ssh_get_pubkey_hash() to get a binary version
|
||||
of the public key hash value. You can then use your own database to check
|
||||
if this public key is known and secure.
|
||||
|
||||
You can also use the ssh_get_pubkey_hash() to show the public key hash
|
||||
value to the user, in case he knows what the public key hash value is
|
||||
(some paranoid people write their public key hash values on paper before
|
||||
going abroad, just in case ...).
|
||||
|
||||
If the remote host is being used to for the first time, you can ask the user whether
|
||||
he/she trusts it. Once he/she concluded that the host is valid and worth being
|
||||
added in the known hosts file, you use ssh_write_knownhost() to register it in
|
||||
the known hosts file, or any other way if you use your own database.
|
||||
|
||||
The following example is part of the examples suite available in the
|
||||
examples/ directory:
|
||||
|
||||
@code
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
int verify_knownhost(ssh_session session)
|
||||
{
|
||||
int state, hlen;
|
||||
unsigned char *hash = NULL;
|
||||
char *hexa;
|
||||
char buf[10];
|
||||
|
||||
state = ssh_is_server_known(session);
|
||||
|
||||
hlen = ssh_get_pubkey_hash(session, &hash);
|
||||
if (hlen < 0)
|
||||
return -1;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case SSH_SERVER_KNOWN_OK:
|
||||
break; /* ok */
|
||||
|
||||
case SSH_SERVER_KNOWN_CHANGED:
|
||||
fprintf(stderr, "Host key for server changed: it is now:\n");
|
||||
ssh_print_hexa("Public key hash", hash, hlen);
|
||||
fprintf(stderr, "For security reasons, connection will be stopped\n");
|
||||
free(hash);
|
||||
return -1;
|
||||
|
||||
case SSH_SERVER_FOUND_OTHER:
|
||||
fprintf(stderr, "The host key for this server was not found but an other"
|
||||
"type of key exists.\n");
|
||||
fprintf(stderr, "An attacker might change the default server key to"
|
||||
"confuse your client into thinking the key does not exist\n");
|
||||
free(hash);
|
||||
return -1;
|
||||
|
||||
case SSH_SERVER_FILE_NOT_FOUND:
|
||||
fprintf(stderr, "Could not find known host file.\n");
|
||||
fprintf(stderr, "If you accept the host key here, the file will be"
|
||||
"automatically created.\n");
|
||||
/* fallback to SSH_SERVER_NOT_KNOWN behavior */
|
||||
|
||||
case SSH_SERVER_NOT_KNOWN:
|
||||
hexa = ssh_get_hexa(hash, hlen);
|
||||
fprintf(stderr,"The server is unknown. Do you trust the host key?\n");
|
||||
fprintf(stderr, "Public key hash: %s\n", hexa);
|
||||
free(hexa);
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL)
|
||||
{
|
||||
free(hash);
|
||||
return -1;
|
||||
}
|
||||
if (strncasecmp(buf, "yes", 3) != 0)
|
||||
{
|
||||
free(hash);
|
||||
return -1;
|
||||
}
|
||||
if (ssh_write_knownhost(session) < 0)
|
||||
{
|
||||
fprintf(stderr, "Error %s\n", strerror(errno));
|
||||
free(hash);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case SSH_SERVER_ERROR:
|
||||
fprintf(stderr, "Error %s", ssh_get_error(session));
|
||||
free(hash);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(hash);
|
||||
return 0;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@see ssh_connect
|
||||
@see ssh_disconnect
|
||||
@see ssh_get_error
|
||||
@see ssh_get_error_code
|
||||
@see ssh_get_pubkey_hash
|
||||
@see ssh_is_server_known
|
||||
@see ssh_write_knownhost
|
||||
|
||||
|
||||
@subsection auth Authenticating the user
|
||||
|
||||
The authentication process is the way a service provider can identify a
|
||||
user and verify his/her identity. The authorization process is about enabling
|
||||
the authenticated user the access to ressources. In SSH, the two concepts
|
||||
are linked. After authentication, the server can grant the user access to
|
||||
several ressources such as port forwarding, shell, sftp subsystem, and so on.
|
||||
|
||||
libssh supports several methods of authentication:
|
||||
- "none" method. This method allows to get the available authentications
|
||||
methods. It also gives the server a chance to authenticate the user with
|
||||
just his/her login. Some very old hardware uses this feature to fallback
|
||||
the user on a "telnet over SSH" style of login.
|
||||
- password method. A password is sent to the server, which accepts it or not.
|
||||
- keyboard-interactive method. The server sends several challenges to the
|
||||
user, who must answer correctly. This makes possible the authentication
|
||||
via a codebook for instance ("give code at 23:R on page 3").
|
||||
- public key method. The host knows the public key of the user, and the
|
||||
user must prove he knows the associated private key. This can be done
|
||||
manually, or delegated to the SSH agent as we'll see later.
|
||||
|
||||
All these methods can be combined. You can for instance force the user to
|
||||
authenticate with at least two of the authentication methods. In that case,
|
||||
one speaks of "Partial authentication". A partial authentication is a
|
||||
response from authentication functions stating that your credential was
|
||||
accepted, but yet another one is required to get in.
|
||||
|
||||
The example below shows an authentication with password:
|
||||
|
||||
@code
|
||||
#include <libssh/libssh.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
ssh_session my_ssh_session;
|
||||
int rc;
|
||||
char *password;
|
||||
|
||||
// Open session and set options
|
||||
my_ssh_session = ssh_new();
|
||||
if (my_ssh_session == NULL)
|
||||
exit(-1);
|
||||
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
|
||||
|
||||
// Connect to server
|
||||
rc = ssh_connect(my_ssh_session);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Error connecting to localhost: %s\n",
|
||||
ssh_get_error(my_ssh_session));
|
||||
ssh_free(my_ssh_session);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Verify the server's identity
|
||||
// For the source code of verify_knowhost(), check previous example
|
||||
if (verify_knownhost(my_ssh_session) < 0)
|
||||
{
|
||||
ssh_disconnect(my_ssh_session);
|
||||
ssh_free(my_ssh_session);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Authenticate ourselves
|
||||
password = getpass("Password: ");
|
||||
rc = ssh_userauth_password(my_ssh_session, NULL, password);
|
||||
if (rc != SSH_AUTH_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Error authenticating with password: %s\n",
|
||||
ssh_get_error(my_ssh_session));
|
||||
ssh_disconnect(my_ssh_session);
|
||||
ssh_free(my_ssh_session);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
ssh_disconnect(my_ssh_session);
|
||||
ssh_free(my_ssh_session);
|
||||
}
|
||||
@endcode
|
||||
|
||||
@see @ref authentication_details
|
||||
|
||||
|
||||
@subsection using_ssh Doing something
|
||||
|
||||
At this point, the authenticity of both server and client is established.
|
||||
Time has come to take advantage of the many possibilities offered by the SSH
|
||||
protocol: execute a remote command, open remote shells, transfer files,
|
||||
forward ports, etc.
|
||||
|
||||
The example below shows how to execute a remote command:
|
||||
|
||||
@code
|
||||
int show_remote_processes(ssh_session session)
|
||||
{
|
||||
ssh_channel channel;
|
||||
int rc;
|
||||
char buffer[256];
|
||||
unsigned int nbytes;
|
||||
|
||||
channel = ssh_channel_new(session);
|
||||
if (channel == NULL)
|
||||
return SSH_ERROR;
|
||||
|
||||
rc = ssh_channel_open_session(channel);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
ssh_channel_free(channel);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = ssh_channel_request_exec(channel, "ps aux");
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return rc;
|
||||
}
|
||||
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
while (nbytes > 0)
|
||||
{
|
||||
if (write(1, buffer, nbytes) != nbytes)
|
||||
{
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
}
|
||||
|
||||
if (nbytes < 0)
|
||||
{
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
ssh_channel_send_eof(channel);
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@see @ref opening_shell
|
||||
@see @ref remote_command
|
||||
@see @ref sftp_subsystem
|
||||
@see @ref scp_subsystem
|
||||
|
||||
|
||||
@subsection errors Handling the errors
|
||||
|
||||
All the libssh functions which return an error value also set an English error message
|
||||
describing the problem.
|
||||
|
||||
Error values are typically SSH_ERROR for integer values, or NULL for pointers.
|
||||
|
||||
The function ssh_get_error() returns a pointer to the static error message.
|
||||
|
||||
ssh_error_code() returns the error code number : SSH_NO_ERROR,
|
||||
SSH_REQUEST_DENIED, SSH_INVALID_REQUEST, SSH_CONNECTION_LOST, SSH_FATAL,
|
||||
or SSH_INVALID_DATA. SSH_REQUEST_DENIED means the ssh server refused your
|
||||
request, but the situation is recoverable. The others mean something happened
|
||||
to the connection (some encryption problems, server problems, ...).
|
||||
SSH_INVALID_REQUEST means the library got some garbage from server, but
|
||||
might be recoverable. SSH_FATAL means the connection has an important
|
||||
problem and isn't probably recoverable.
|
||||
|
||||
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.
|
||||
In these cases, SSH_REQUEST_DENIED is returned.
|
||||
|
||||
For thread safety, errors are bound to ssh_session objects.
|
||||
As long as your ssh_session object is not NULL, you can retrieve the last error
|
||||
message and error code from the ssh_session using ssh_get_error() and
|
||||
ssh_get_error_code() respectively.
|
||||
|
||||
The SFTP subsystem has its own error codes, in addition to libssh ones.
|
||||
|
||||
|
||||
*/
|
||||
49
doc/introduction.dox
Normal file
49
doc/introduction.dox
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
@page libssh_tutorial The Tutorial
|
||||
@section introduction Introduction
|
||||
|
||||
libssh is a C library that enables you to write a program that uses the
|
||||
SSH protocol. With it, you can remotely execute programs, transfer
|
||||
files, or use a secure and transparent tunnel for your remote programs.
|
||||
The SSH protocol is encrypted, ensures data integrity, and provides strong
|
||||
means of authenticating both the server of the client. The library hides
|
||||
a lot of technical details from the SSH protocol, but this does not
|
||||
mean that you should not try to know about and understand these details.
|
||||
|
||||
libssh is a Free Software / Open Source project. The libssh library
|
||||
is distributed under LGPL license. The libssh project has nothing to do with
|
||||
"libssh2", which is a completly different and independant project.
|
||||
|
||||
libssh can run on top of either libgcrypt or libcrypto,
|
||||
two general-purpose cryptographic libraries.
|
||||
|
||||
This tutorial concentrates for its main part on the "client" side of libssh.
|
||||
To learn how to accept incoming SSH connexions (how to write a SSH server),
|
||||
you'll have to jump to the end of this document.
|
||||
|
||||
This tutorial describes libssh version 0.5.0. This version is a little different
|
||||
from the 0.4.X series. However, the examples should work with
|
||||
little changes on versions like 0.4.2 and later.
|
||||
|
||||
|
||||
Table of contents:
|
||||
|
||||
@subpage libssh_tutor_guided_tour
|
||||
|
||||
@subpage libssh_tutor_authentication
|
||||
|
||||
@subpage libssh_tutor_shell
|
||||
|
||||
@subpage libssh_tutor_command
|
||||
|
||||
@subpage libssh_tutor_sftp
|
||||
|
||||
@subpage libssh_tutor_scp
|
||||
|
||||
@subpage libssh_tutor_forwarding
|
||||
|
||||
@subpage libssh_tutor_threads
|
||||
|
||||
@subpage libssh_tutor_todo
|
||||
|
||||
*/
|
||||
@@ -1,385 +0,0 @@
|
||||
The new libssh 0.2 API
|
||||
----------------------
|
||||
|
||||
Version 1
|
||||
|
||||
A. Introduction
|
||||
---------------
|
||||
|
||||
With the time from the first release of libssh, I have received lots of
|
||||
comments about the current API. Myself, I found it quite limiting when doing
|
||||
my first libssh-server drafts. Thus, I am moving to a stronger API.
|
||||
This API must still be simple. I am not introducing complex changes. An API
|
||||
well designed must hide the implementation details. Implementation can change
|
||||
easily within bugfixes - but API cannot change each release.
|
||||
|
||||
To the people already using libssh 0.11 : sorry. Once I have the complete API
|
||||
redesigned, I will write a migration paper. It won't be too hard normally.
|
||||
|
||||
Here are the things that were lacking in the previous API and *must* change:
|
||||
|
||||
* A non-blocking mode connection type
|
||||
* Functions to relegate File descriptor listening to Calling functions and to
|
||||
the programmer. (I'll explain later).
|
||||
* Along with that, good buffering system (well, it's not an API but).
|
||||
* Leave the "functions returns a pointer when it works and NULL when it does
|
||||
not work". It gives serious problems to implement bindings (A C++
|
||||
constructor should not fail and should not depend on a network thing
|
||||
* Make the Session structure an abstract structure that can work with both
|
||||
client and *servers*. That mean we should have a Server object which listen
|
||||
to clients on a bound port, does the different handshakes and return a
|
||||
session.
|
||||
Since C is not per se an Object language, I won't use inheritance between
|
||||
objects.
|
||||
* This same server thing must provide the reverse capabilities than the
|
||||
client. That is, accept the handshake, in a nonblocking way. Accept channel
|
||||
requests, or send them to the controller program.
|
||||
* Support for program forking : Imagine you have a Ssh server object. You
|
||||
accept a connection and receive a session, then you receive a channel. You
|
||||
may want to keep the good old days fork() tricks. Libssh will give a way to
|
||||
destroy handlers from sessions which belong to an other process without
|
||||
disturbing the session.
|
||||
* So often I received the comment back saying that it was not clear why a
|
||||
session or a channel was terminated. This is over.
|
||||
* And of course I received lot of mails about the fact I'm doing namespace
|
||||
polution. this will be resolved this time.
|
||||
So, please read this draft not as a formal documentation but like a roadmap of
|
||||
things that each kind of object must do.
|
||||
|
||||
B. Description of objects and functions
|
||||
|
||||
Initialization and finalization
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Initialization is for now called automatically, so you don't have to take care
|
||||
of that.
|
||||
As for finalization, we need to finalize the underlying cryptographic library
|
||||
(either OpenSSL or libgcrypt). Be sure that you call ssh_finalize when this
|
||||
library won't be used anymore, even by other libraries (i.e. if you use libssh
|
||||
and another library that uses OpenSSL, call ssh_finalize when any function of
|
||||
both these libraries won't be called).
|
||||
If you trust your operating system to clean up the mess after a process
|
||||
terminates, you can skip this call.
|
||||
|
||||
Options structure
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
struct ssh_options *ssh_options_new()
|
||||
|
||||
ssh_options_getopt(options, *argc, argv)
|
||||
|
||||
ssh_options_copy(options)
|
||||
|
||||
char ** ssh_options_get_supported_algos(options,type)
|
||||
returns a list of the algos supported by libssh, type being one of
|
||||
SSH_HOSTKEYS, SSH_KEX, SSH_CRYPT, SSH_MAC, SSH_COMP, SSH_LANG
|
||||
|
||||
ssh_options_set_wanted_algos(options,type, char *list)
|
||||
list being comma-separated list of algos, and type being the upper constants
|
||||
but with _C_S or _S_V added to them.
|
||||
|
||||
ssh_options_set_port(options, port)
|
||||
|
||||
ssh_options_set_host(options, host)
|
||||
|
||||
ssh_options_set_fd(options, fd)
|
||||
|
||||
ssh_options_set_bind(options, bindaddr, port)
|
||||
this options sets the address to bind for a client *or* a server. a port of
|
||||
zero means whatever port is free (what most clients want).
|
||||
|
||||
ssh_options_set_username(options, username)
|
||||
|
||||
ssh_options_set_connect_timeout(options, seconds, usec)
|
||||
|
||||
ssh_options_set_ssh_dir(options, dir)
|
||||
ssh_options_set_known_hosts_file(options, file)
|
||||
ssh_options_set_identity(options, file)
|
||||
|
||||
ssh_options_set_banner(options, banner)
|
||||
ssh_options_allow_ssh1(options, bool allow)
|
||||
ssh_options_allow_ssh2(options, bool allow)
|
||||
|
||||
options_set_status_callback has moved into ssh_* functions.
|
||||
|
||||
ssh_session Structure
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This session structure represents a ssh socket to a server *or* a client.
|
||||
|
||||
ssh_session *ssh_new()
|
||||
|
||||
ssh_set_options(ssh_session,ssh_options)
|
||||
|
||||
ssh_connect(session);
|
||||
it will return some status describing at which point of the connection it is,
|
||||
or an error code. If the connection method is non-blocking, the function
|
||||
will be called more than once, though the return value SSH_AGAIN.
|
||||
|
||||
ssh_set_blocking(session, bool blocking)
|
||||
set blocking mode or non blocking mode.
|
||||
|
||||
ssh_get_fd(session)
|
||||
get the currently used connection file descriptor or equivalent (windows)
|
||||
|
||||
ssh_set_fd_toread(session)
|
||||
ssh_set_fd_towrite(session)
|
||||
ssh_set_fd_except(session)
|
||||
Serve to notify the library that data is actualy available to be read on the
|
||||
file descriptor socket. why ? because on most platforms select can't be done
|
||||
twice on the same socket when the first reported data to read or to write
|
||||
|
||||
ssh_get_status(session)
|
||||
Returns the current status bitmask : connection Open or closed, data
|
||||
pending to read or not (even if connection closed), connection closed on
|
||||
error or on an exit message
|
||||
|
||||
ssh_get_disconnect_message(session)
|
||||
Returns the connection disconnect error/exit message
|
||||
|
||||
ssh_get_pubkey_hash(session, hash)
|
||||
get the public key hash from the server.
|
||||
|
||||
ssh_is_server_known(session)
|
||||
ssh_write_knownhost(session)
|
||||
these 2 functions will be kept
|
||||
|
||||
ssh_disconnect(session)
|
||||
standard disconnect
|
||||
|
||||
ssh_disconnect_error(session,error code, message)
|
||||
disconnect with a message
|
||||
|
||||
ssh_set_username(session)
|
||||
set the user name to log in
|
||||
|
||||
ssh_userauth_* functions will be kept as they are now, excepted the fact that
|
||||
the username field will disapear.
|
||||
the public key mechanism may get some more functions, like retrieving a public
|
||||
key from a private key and authenticating without a public key.
|
||||
|
||||
ssh_get_issue_banner(session)
|
||||
get the issue banner from the server, that is the welcome message.
|
||||
|
||||
ssh_silent_free(session)
|
||||
This function silently free all data structures used by the session and
|
||||
closes the socket. It may be used for instance when the process forked and
|
||||
doesn't want to keep track of this session. This is obviously not possible to
|
||||
do with separate channels.
|
||||
|
||||
The channel_struct structure
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The channels will change a bit. the constructor thing will change, and the way
|
||||
to multiplex different connections will change too. channel functions will be
|
||||
prefixed with "ssh_"
|
||||
|
||||
struct channel_struct *ssh_channel_new()
|
||||
|
||||
ssh_channel_open_session(channel)
|
||||
will return if the channel allocation failed or not.
|
||||
|
||||
ssh_channel_open_forward(channel, ...) won't change. it will report an error if
|
||||
the channel allocation failed.
|
||||
|
||||
ssh_channel_send_eof(channel)
|
||||
send EOF
|
||||
ssh_channel_close(channel)
|
||||
closes a channel but doesn't destroy it. you may read unread data still in
|
||||
the buffer. Once you closed the buffer, the other party can't send you data,
|
||||
while it could still do it if you only sent an EOF.
|
||||
ssh_channel_is_closed(channel)
|
||||
returns true if the channel was closed at one of both sides. a closed chan
|
||||
may still have data to read, if you closed yourself the connection. otherwise
|
||||
(you didn't close it) the closed notification only comes when you read the
|
||||
last buffer byte, or when trying to write into the channel (the SIGPIPE-like
|
||||
behaviour).
|
||||
|
||||
ssh_channel_is_eof(channel)
|
||||
reports if the other side has sent an EOF. This functions returns FALSE if
|
||||
there is still data to read. A closed channel is always EOF.
|
||||
ssh_channel_free(channel)
|
||||
completely free the channel. closes it before if it was not done.
|
||||
|
||||
ssh_channel_request_env(channel, name, value)
|
||||
set an environment variable.
|
||||
|
||||
ssh_channel_request_pty(channel)
|
||||
ssh_channel_request_pty_size()
|
||||
ssh_channel_change_pty_size()
|
||||
ssh_channel_request_shell()
|
||||
ssh_channel_request_exec()
|
||||
ssh_channel_request_subsystem()
|
||||
These functions won't change.
|
||||
|
||||
int ssh_channel_write(channel,data, len,stderr)
|
||||
Depending on the blocking/non blocking mode of the channel, the behaviour may
|
||||
change.
|
||||
stderr is the extended buffer. It's generaly only a server->client stream.
|
||||
|
||||
ssh_channel_set_blocking(bool blocking)
|
||||
|
||||
int ssh_channel_read(channel, buffer, maxlen, is_stderr)
|
||||
the behaviour will be this one:
|
||||
-if the chan is in non blocking mode, it will poll what's available to read
|
||||
and return this. otherwise (nothing to read) it will return 0.
|
||||
-if the chan is blocking, it will block until at least one byte is
|
||||
available.
|
||||
ssh_channel_nonblocking disapears for the later reason.
|
||||
|
||||
int channel_poll(channel, is_stderr)
|
||||
polls the network and reports the number of bytes ready to be read in the
|
||||
chan.
|
||||
|
||||
ssh_session ssh_channel_get_session(channel)
|
||||
returns the session pointer associated to the channel, for simplicity
|
||||
reasons.
|
||||
|
||||
int ssh_channel_select(CHANNELS *readchans, CHANNELS *writechans, CHANNELS
|
||||
*exceptchans, struct timeval *timeout)
|
||||
This function won't work the same way ssh_select did.
|
||||
I removed the custom file descriptor thing for 2 reasons:
|
||||
1- it's not windows compliant. D'ouh !
|
||||
2- most programmers won't want to depend on libssh for socket multiplexing.
|
||||
that's why i let the programmer poll the fds himself and then use
|
||||
ssh_set_fd_toread, towrite or except. Then, he may use ssh_channel_select
|
||||
with a NULL timeout to poll which channels have something to read, write or
|
||||
error report.
|
||||
Here is how it's going to work. The coder sets 3 different arrays with the
|
||||
channels he wants to select(), the last entry being a NULL pointer. The
|
||||
function will first poll them and return the chans that must be
|
||||
read/write/excepted. If nothing has this state, the function will select()
|
||||
using the timeout.
|
||||
The function will return 0 if everything is ok, SSH_TIMEOUT or SSH_EINTR if
|
||||
the select was interrupted by a signal. It is dangerous to execute any
|
||||
channel-related functions into signal handlers. they should set a flag that
|
||||
you read into your loop. this "trap" (SSH_EINTR) will permit you to catch
|
||||
them faster and make your program responsive and look fast.
|
||||
the function will return -1 if a serious problem happens.
|
||||
|
||||
|
||||
Error handling
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
when an error happens, the programmer can get the error code and description
|
||||
with ssh_get_error(session). the creation of a failess constructor for
|
||||
ssh_session was needed for this reason.
|
||||
|
||||
ssh_get_error_code(session) will return an error code into this subset:
|
||||
SSH_NO_ERROR : no error :)
|
||||
SSH_REQUEST_DENIED : you request for a functionality or a service that is not
|
||||
allowed. The session can continue.
|
||||
SSH_FATAL : Unrecoverable error. The session can't continue and you should
|
||||
disconnect the session. It includes the connection being cut without a
|
||||
disconnect() message.
|
||||
If a disconnect() message or the channel was closed, a read on such a channel
|
||||
won't produce an error. otherwise it will return -1 with a SSH_FATAL error
|
||||
code.
|
||||
|
||||
Server socket binding
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
It is not possible to bind a socket for ssh with a SSH_SESSION type, because a
|
||||
single bound port may lead to multiple ssh connections. That's why the
|
||||
SSH_BIND structure must be created. It uses options from the SSH_OPTIONS
|
||||
structure.
|
||||
|
||||
SSH_BIND *ssh_bind_new()
|
||||
creates a structure
|
||||
ssh_bind_set_options(bind, options)
|
||||
set the option structure
|
||||
int ssh_bind_listen(bind)
|
||||
bind and listen to the port. This call is not blocking. if some error
|
||||
happens, it returns -1 and the error code can be found with perror().
|
||||
|
||||
ssh_bind_set_blocking(bind, bool blocking)
|
||||
should ssh_bind_accept() block or not.
|
||||
|
||||
int ssh_bind_get_fd(bind)
|
||||
return the bound file descriptor, that is the listener socket. you may put it
|
||||
into a select() in your code to detect a connection attempt.
|
||||
|
||||
ssh_bind_set_fd_toaccept(bind)
|
||||
say that the listener socket has a connection to accept (to avoid
|
||||
ssh_bind_accept() to do a select on it).
|
||||
|
||||
SSH_SESSION *ssh_bind_accept(bind)
|
||||
return a server handle to a ssh session. if the mode is blocking, the
|
||||
function will always return a pointer to a session. if the mode is not
|
||||
blocking, the function can return NULL if there is no connection to accept.
|
||||
|
||||
This SSH_SESSION handle must then pass through the functions explained above.
|
||||
|
||||
|
||||
*server functions *
|
||||
|
||||
int ssh_accept(session)
|
||||
when a new connection is accepted, the handshake must be done. this function
|
||||
will do the banner handshake and the key exchange.
|
||||
it will return SSH_AGAIN if the session mode is non blocking, and the
|
||||
function must be called again until an error occurs or the kex is done.
|
||||
|
||||
Here, I had a few choises about *how* to implement the message parsing as a
|
||||
server. There are multiple ways to do it, one being callbacks and one being
|
||||
"Message" reading, parsing and then choice going to the user to use it and
|
||||
answer. I've choosen the latter because i believe it's the stronger method.
|
||||
A ssh server can receive 30 different kind of messages having to be dealt by
|
||||
the high level routines, like channel request_shell or authentication. Having
|
||||
a callback for all of them would produce a huge kludge of callbacks, with
|
||||
no relations on when there were called etc.
|
||||
A message based parsing allows the user to filtrate the messages he's
|
||||
interested into and to use a default answer for the others. Then, the callback
|
||||
thing is still possible to handle through a simple message code/callback
|
||||
function array.
|
||||
|
||||
I did not define yet what it would look like, but i'm sure there will be a
|
||||
SSH_MESSAGE (they won't have a 1/1 correspondance with ssh packets) which will
|
||||
be read through
|
||||
SSH_MESSAGE *ssh_server_read_message(session).
|
||||
with all of the non-blocking stuff in head like returning NULL if the message
|
||||
is not full.
|
||||
Then, the message can be parsed, ie
|
||||
int ssh_message_get_code(message)
|
||||
which will return SSH_MESSAGE_AUTH
|
||||
then
|
||||
int ssh_message_get_subcode(message)
|
||||
which then will returh SSH_MESSAGE_AUTH_PASSWORD or _NONE or _PUBKEY etc.
|
||||
|
||||
Then, once the message was parsed, the message will have to be answered, ie
|
||||
with the generic functions like
|
||||
ssh_message_accept(message) which says 'Ok your request is accepted' or
|
||||
ssh_message_deny(message) which says 'Your request is refused'.
|
||||
|
||||
There would be specific message answer functions for some kind of messages
|
||||
like the authentication one. you may want to reply that the authentication is
|
||||
Partial rather than denied, and that you still accept some kind of auths, like
|
||||
ssh_message_auth_reply(message,SSH_AUTH_PARTIAL,SSH_AUTH_PASSWORD |
|
||||
SSH_AUTH_PUBKEY | SSH_AUTH_KEYBINT);
|
||||
|
||||
I won't let the user have to deal with the channels himself. When a channel is
|
||||
going to be created by the remote size, a message will come asking to open a
|
||||
channel. the programmer can either deny or accept, in which case a CHANNEL
|
||||
object will be created and returned to the programmer. then, all standard
|
||||
channel functions will run.
|
||||
|
||||
C. Change log of this document
|
||||
|
||||
3. Add paragraph about initalization and finalization.
|
||||
|
||||
2. ssh_options_set_username finaly is kept into the options, because it can be
|
||||
set by ssh_options_getopt()
|
||||
|
||||
1. first release
|
||||
|
||||
D. End notes
|
||||
|
||||
I think libssh must have a very simple to use, powerful and exhaustive API. It
|
||||
must have no design flaw either.
|
||||
While I got some good experience at the SSH protocol, I've never writen
|
||||
more-than-100 lines programs than use libssh and I don't really know the
|
||||
problems of the library. I'd like people who don't understand some detail into
|
||||
the API I describe here, who have comments or opinions about it to write me
|
||||
the soonest possible to limit the damages if I made something the completely
|
||||
wrong way.
|
||||
Thanks for your patience.
|
||||
|
||||
30
doc/linking.dox
Normal file
30
doc/linking.dox
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
|
||||
@page libssh_linking The Linking HowTo
|
||||
|
||||
@section dynamic Dynamic Linking
|
||||
|
||||
On UNIX and Windows systems its the same, you need at least the libssh.h
|
||||
header file and the libssh shared library.
|
||||
|
||||
@section static Static Linking
|
||||
|
||||
@warning <b>The libssh library is licensed under the LGPL! Make sure you
|
||||
understand what this means to your codebase if you want to distribute
|
||||
binaries and link statically against LGPL code!</b>
|
||||
|
||||
On UNIX systems linking against the static version of the library is the
|
||||
same as linking against the shared library. Both have the same name. Some
|
||||
build system require to use the full path to the static library.
|
||||
|
||||
To be able to compile the application you're developing you need to either pass
|
||||
LIBSSH_STATIC as a define in the compiler command line or define it before you
|
||||
include libssh.h. This is required cause the dynamic library needs to specify
|
||||
the dllimport attribute.
|
||||
|
||||
@code
|
||||
#define LIBSSH_STATIC 1
|
||||
#include <libssh/libssh.h>
|
||||
@endcode
|
||||
|
||||
*/
|
||||
232
doc/mainpage.dox
232
doc/mainpage.dox
@@ -1,12 +1,224 @@
|
||||
/**
|
||||
* @mainpage
|
||||
* This manual documents the libssh C API.
|
||||
*
|
||||
* There are several other places to look for libssh information, such as the
|
||||
* <a href="http://dev.libssh.org/wiki/Tutorial" target="_blank">tutorial</a>
|
||||
* and the specification; those can be found at the <a
|
||||
* href="http://www.libssh.org/" target="_blank">libssh website</a>.
|
||||
*
|
||||
* To be continued...
|
||||
*/
|
||||
|
||||
@mainpage
|
||||
|
||||
This is the online reference for developing with the libssh library. It
|
||||
documents the libssh C API and the C++ wrapper.
|
||||
|
||||
@section main-linking Linking
|
||||
|
||||
We created a small howto how to link libssh against your application, read
|
||||
@subpage libssh_linking.
|
||||
|
||||
@section main-tutorial Tutorial
|
||||
|
||||
You should start by reading @subpage libssh_tutorial, then reading the documentation of
|
||||
the interesting functions as you go.
|
||||
|
||||
@section main-features Features
|
||||
|
||||
The libssh library provides:
|
||||
|
||||
- <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>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>MAC hashes</strong>: hmac-sha1, none
|
||||
- <strong>Authentication</strong>: none, password, public-key, hostbased, keyboard-interactive, <i>gssapi-with-mic</i>
|
||||
- <strong>Channels</strong>: shell, exec (incl. SCP wrapper), direct-tcpip, subsystem, <i>auth-agent-req@openssh.com</i>
|
||||
- <strong>Global Requests</strong>: tcpip-forward, forwarded-tcpip
|
||||
- <strong>Channel Requests</strong>: x11, pty, <i>exit-status, signal, exit-signal, keepalive@openssh.com, auth-agent-req@openssh.com</i>
|
||||
- <strong>Subsystems</strong>: sftp(version 3), publickey(version 2), <i>OpenSSH Extensions</i>
|
||||
- <strong>SFTP</strong>: <i>statvfs@openssh.com, fstatvfs@openssh.com</i>
|
||||
- <strong>Thread-safe</strong>: Just don't share sessions
|
||||
- <strong>Non-blocking</strong>: it can be used both blocking and non-blocking
|
||||
- <strong>Your sockets</strong>: the app hands over the socket, or uses libssh sockets
|
||||
- <b>OpenSSL</b> or <b>gcrypt</b>: builds with either
|
||||
|
||||
@section main-additional-features Additional Features
|
||||
|
||||
- Client <b>and</b> server support
|
||||
- SSHv2 and SSHv1 protocol support
|
||||
- Supports <a href="http://test.libssh.org/" target="_blank">Linux, UNIX, BSD, Solaris, OS/2 and Windows</a>
|
||||
- Automated test cases with nightly <a href="http://test.libssh.org/" target="_blank">tests</a>
|
||||
- Event model based on poll(2), or a poll(2)-emulation.
|
||||
|
||||
@section main-copyright Copyright Policy
|
||||
|
||||
libssh is a project with distributed copyright ownership, which means we prefer
|
||||
the copyright on parts of libssh to be held by individuals rather than
|
||||
corporations if possible. There are historical legal reasons for this, but one
|
||||
of the best ways to explain it is that it’s much easier to work with
|
||||
individuals who have ownership than corporate legal departments if we ever need
|
||||
to make reasonable compromises with people using and working with libssh.
|
||||
|
||||
We track the ownership of every part of libssh via git, our source code control
|
||||
system, so we know the provenance of every piece of code that is committed to
|
||||
libssh.
|
||||
|
||||
So if possible, if you’re doing libssh changes on behalf of a company who
|
||||
normally owns all the work you do please get them to assign personal copyright
|
||||
ownership of your changes to you as an individual, that makes things very easy
|
||||
for us to work with and avoids bringing corporate legal departments into the
|
||||
picture.
|
||||
|
||||
If you can’t do this we can still accept patches from you owned by your
|
||||
employer under a standard employment contract with corporate copyright
|
||||
ownership. It just requires a simple set-up process first.
|
||||
|
||||
We use a process very similar to the way things are done in the Linux Kernel
|
||||
community, so it should be very easy to get a sign off from your corporate
|
||||
legal department. The only changes we’ve made are to accommodate the license we
|
||||
use, which is LGPLv2 (or later) whereas the Linux kernel uses GPLv2.
|
||||
|
||||
The process is called signing.
|
||||
|
||||
How to sign your work
|
||||
----------------------
|
||||
|
||||
Once you have permission to contribute to libssh from your employer, simply
|
||||
email a copy of the following text from your corporate email address to:
|
||||
|
||||
contributing@libssh.org
|
||||
|
||||
@verbatim
|
||||
libssh Developer's Certificate of Origin. Version 1.0
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
(a) The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the appropriate
|
||||
version of the GNU General Public License; or
|
||||
|
||||
(b) The contribution is based upon previous work that, to the best of
|
||||
my knowledge, is covered under an appropriate open source license
|
||||
and I have the right under that license to submit that work with
|
||||
modifications, whether created in whole or in part by me, under
|
||||
the GNU General Public License, in the appropriate version; or
|
||||
|
||||
(c) The contribution was provided directly to me by some other
|
||||
person who certified (a) or (b) and I have not modified it.
|
||||
|
||||
(d) I understand and agree that this project and the contribution are
|
||||
public and that a record of the contribution (including all
|
||||
metadata and personal information I submit with it, including my
|
||||
sign-off) is maintained indefinitely and may be redistributed
|
||||
consistent with the libssh Team's policies and the requirements of
|
||||
the GNU GPL where they are relevant.
|
||||
|
||||
(e) I am granting this work to this project 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 the option of the project) any later version.
|
||||
|
||||
http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
@endverbatim
|
||||
|
||||
We will maintain a copy of that email as a record that you have the rights to
|
||||
contribute code to libssh under the required licenses whilst working for the
|
||||
company where the email came from.
|
||||
|
||||
Then when sending in a patch via the normal mechanisms described above, add a
|
||||
line that states:
|
||||
|
||||
@verbatim
|
||||
Signed-off-by: Random J Developer <random@developer.example.org>
|
||||
@endverbatim
|
||||
|
||||
using your real name and the email address you sent the original email you used
|
||||
to send the libssh Developer’s Certificate of Origin to us (sorry, no
|
||||
pseudonyms or anonymous contributions.)
|
||||
|
||||
That’s it! Such code can then quite happily contain changes that have copyright
|
||||
messages such as:
|
||||
|
||||
@verbatim
|
||||
(c) Example Corporation.
|
||||
@endverbatim
|
||||
|
||||
and can be merged into the libssh codebase in the same way as patches from any
|
||||
other individual. You don’t need to send in a copy of the libssh Developer’s
|
||||
Certificate of Origin for each patch, or inside each patch. Just the sign-off
|
||||
message is all that is required once we’ve received the initial email.
|
||||
|
||||
Have fun and happy libssh hacking!
|
||||
|
||||
The libssh Team
|
||||
|
||||
@section main-rfc Internet standard
|
||||
|
||||
@subsection main-rfc-secsh Secure Shell (SSH)
|
||||
|
||||
The following RFC documents described SSH-2 protcol as an Internet standard.
|
||||
|
||||
- <a href="http://tools.ietf.org/html/rfc4250" target="_blank">RFC 4250</a>,
|
||||
The Secure Shell (SSH) Protocol Assigned Numbers
|
||||
- <a href="http://tools.ietf.org/html/rfc4251" target="_blank">RFC 4251</a>,
|
||||
The Secure Shell (SSH) Protocol Architecture
|
||||
- <a href="http://tools.ietf.org/html/rfc4252" target="_blank">RFC 4252</a>,
|
||||
The Secure Shell (SSH) Authentication Protocol
|
||||
- <a href="http://tools.ietf.org/html/rfc4253" target="_blank">RFC 4253</a>,
|
||||
The Secure Shell (SSH) Transport Layer Protocol
|
||||
- <a href="http://tools.ietf.org/html/rfc4254" target="_blank">RFC 4254</a>,
|
||||
The Secure Shell (SSH) Connection Protocol
|
||||
- <a href="http://tools.ietf.org/html/rfc4255" target="_blank">RFC 4255</a>,
|
||||
Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints
|
||||
- <a href="http://tools.ietf.org/html/rfc4256" target="_blank">RFC 4256</a>,
|
||||
Generic Message Exchange Authentication for the Secure Shell Protocol (SSH)
|
||||
- <a href="http://tools.ietf.org/html/rfc4335" target="_blank">RFC 4335</a>,
|
||||
The Secure Shell (SSH) Session Channel Break Extension
|
||||
- <a href="http://tools.ietf.org/html/rfc4344" target="_blank">RFC 4344</a>,
|
||||
The Secure Shell (SSH) Transport Layer Encryption Modes
|
||||
- <a href="http://tools.ietf.org/html/rfc4345" target="_blank">RFC 4345</a>,
|
||||
Improved Arcfour Modes for the Secure Shell (SSH) Transport Layer Protocol
|
||||
|
||||
It was later modified and expanded by the following RFCs.
|
||||
|
||||
- <a href="http://tools.ietf.org/html/rfc4419" target="_blank">RFC 4419</a>,
|
||||
Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer
|
||||
Protocol
|
||||
- <a href="http://tools.ietf.org/html/rfc4432" target="_blank">RFC 4432</a>,
|
||||
RSA Key Exchange for the Secure Shell (SSH) Transport Layer Protocol
|
||||
- <a href="http://tools.ietf.org/html/rfc4462" target="_blank">RFC 4462</a>,
|
||||
Generic Security Service Application Program Interface (GSS-API)
|
||||
Authentication and Key Exchange for the Secure Shell (SSH) Protocol
|
||||
- <a href="http://tools.ietf.org/html/rfc4716" target="_blank">RFC 4716</a>,
|
||||
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>,
|
||||
Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer
|
||||
|
||||
Interesting cryptography documents:
|
||||
|
||||
- <a href="http://www.cryptsoft.com/pkcs11doc/" target="_blank">PKCS #11</a>, PKCS #11 reference documents, describing interface with smartcards.
|
||||
|
||||
@subsection main-rfc-sftp Secure Shell File Transfer Protocol (SFTP)
|
||||
|
||||
The protocol is not an Internet standard but it is still widely implemented.
|
||||
OpenSSH and most other implementation implement Version 3 of the protocol. We
|
||||
do the same in libssh.
|
||||
|
||||
- <a href="http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02" target="_blank">
|
||||
draft-ietf-secsh-filexfer-02.txt</a>,
|
||||
SSH File Transfer Protocol
|
||||
|
||||
@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
|
||||
them like the statvfs calls in SFTP or the ssh-agent.
|
||||
|
||||
- <a href="http://api.libssh.org/rfc/PROTOCOL" target="_blank">
|
||||
OpenSSH's deviations and extensions</a>
|
||||
- <a href="http://api.libssh.org/rfc/PROTOCOL.agent" target="_blank">
|
||||
OpenSSH's ssh-agent</a>
|
||||
- <a href="http://api.libssh.org/rfc/PROTOCOL.certkeys" target="_blank">
|
||||
OpenSSH's pubkey certificate authentication</a>
|
||||
|
||||
*/
|
||||
|
||||
268
doc/scp.dox
Normal file
268
doc/scp.dox
Normal file
@@ -0,0 +1,268 @@
|
||||
/**
|
||||
@page libssh_tutor_scp Chapter 6: The SCP subsystem
|
||||
@section scp_subsystem The SCP subsystem
|
||||
|
||||
The SCP subsystem has far less functionnality than the SFTP subsystem.
|
||||
However, if you only need to copy files from and to the remote system,
|
||||
it does its job.
|
||||
|
||||
|
||||
@subsection scp_session Opening and closing a SCP session
|
||||
|
||||
Like in the SFTP subsystem, you don't handle the SSH channels directly.
|
||||
Instead, you open a "SCP session".
|
||||
|
||||
When you open your SCP session, you have to choose between read or write mode.
|
||||
You can't do both in the same session. So you specify either SSH_SCP_READ or
|
||||
SSH_SCP_WRITE as the second parameter of function ssh_scp_new().
|
||||
|
||||
Another important mode flag for opening your SCP session is SSH_SCP_RECURSIVE.
|
||||
When you use SSH_SCP_RECURSIVE, you declare that you are willing to emulate
|
||||
the behaviour of "scp -r" command in your program, no matter it is for
|
||||
reading or for writing.
|
||||
|
||||
Once your session is created, you initialize it with ssh_scp_init(). When
|
||||
you have finished transferring files, you terminate the SCP connection with
|
||||
ssh_scp_close(). Finally, you can dispose the SCP connection with
|
||||
ssh_scp_free().
|
||||
|
||||
The example below does the maintenance work to open a SCP connection for writing in
|
||||
recursive mode:
|
||||
|
||||
@code
|
||||
int scp_write(ssh_session session)
|
||||
{
|
||||
ssh_scp scp;
|
||||
int rc;
|
||||
|
||||
scp = ssh_scp_new
|
||||
(session, SSH_SCP_WRITE | SSH_SCP_RECURSIVE, ".");
|
||||
if (scp == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error allocating scp session: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = ssh_scp_init(scp);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Error initializing scp session: %s\n",
|
||||
ssh_get_error(session));
|
||||
ssh_scp_free(scp);
|
||||
return rc;
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
ssh_scp_close(scp);
|
||||
ssh_scp_free(scp);
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
The example below shows how to open a connection to read a single file:
|
||||
|
||||
@code
|
||||
int scp_read(ssh_session session)
|
||||
{
|
||||
ssh_scp scp;
|
||||
int rc;
|
||||
|
||||
scp = ssh_scp_new
|
||||
(session, SSH_SCP_READ, "helloworld/helloworld.txt");
|
||||
if (scp == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error allocating scp session: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = ssh_scp_init(scp);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Error initializing scp session: %s\n",
|
||||
ssh_get_error(session));
|
||||
ssh_scp_free(scp);
|
||||
return rc;
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
ssh_scp_close(scp);
|
||||
ssh_scp_free(scp);
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection scp_write Creating files and directories
|
||||
|
||||
You create directories with ssh_scp_push_directory(). In recursive mode,
|
||||
you are placed in this directory once it is created. If the directory
|
||||
already exists and if you are in recursive mode, you simply enter that
|
||||
directory.
|
||||
|
||||
Creating files is done in two steps. First, you prepare the writing with
|
||||
ssh_scp_push_file(). Then, you write the data with ssh_scp_write().
|
||||
The length of the data to write must be identical between both function calls.
|
||||
There's no need to "open" nor "close" the file, this is done automatically
|
||||
on the remote end. If the file already exists, it is overwritten and truncated.
|
||||
|
||||
The following example creates a new directory named "helloworld/", then creates
|
||||
a file named "helloworld.txt" in that directory:
|
||||
|
||||
@code
|
||||
int scp_helloworld(ssh_session session, ssh_scp scp)
|
||||
{
|
||||
int rc;
|
||||
const char *helloworld = "Hello, world!\n";
|
||||
int length = strlen(helloworld);
|
||||
|
||||
rc = ssh_scp_push_directory(scp, "helloworld", S_IRWXU);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Can't create remote directory: %s\n",
|
||||
ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = ssh_scp_push_file
|
||||
(scp, "helloworld.txt", length, S_IRUSR | S_IWUSR);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Can't open remote file: %s\n",
|
||||
ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = ssh_scp_write(scp, helloworld, length);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Can't write to remote file: %s\n",
|
||||
ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection scp_recursive_write Copying full directory trees to the remote server
|
||||
|
||||
Let's say you want to copy the following tree of files to the remote site:
|
||||
|
||||
@verbatim
|
||||
+-- file1
|
||||
+-- B --+
|
||||
| +-- file2
|
||||
-- A --+
|
||||
| +-- file3
|
||||
+-- C --+
|
||||
+-- file4
|
||||
@endverbatim
|
||||
|
||||
You would do it that way:
|
||||
- open the session in recursive mode
|
||||
- enter directory A
|
||||
- enter its subdirectory B
|
||||
- create file1 in B
|
||||
- create file2 in B
|
||||
- leave directory B
|
||||
- enter subdirectory C
|
||||
- create file3 in C
|
||||
- create file4 in C
|
||||
- leave directory C
|
||||
- leave directory A
|
||||
|
||||
To leave a directory, call ssh_scp_leave_directory().
|
||||
|
||||
|
||||
@subsection scp_read Reading files and directories
|
||||
|
||||
|
||||
To receive files, you pull requests from the other side with ssh_scp_pull_request().
|
||||
If this function returns SSH_SCP_REQUEST_NEWFILE, then you must get ready for
|
||||
the reception. You can get the size of the data to receive with ssh_scp_request_get_size()
|
||||
and allocate a buffer accordingly. When you are ready, you accept the request with
|
||||
ssh_scp_accept_request(), then read the data with ssh_scp_read().
|
||||
|
||||
The following example receives a single file. The name of the file to
|
||||
receive has been given earlier, when the scp session was opened:
|
||||
|
||||
@code
|
||||
int scp_receive(ssh_session session, ssh_scp scp)
|
||||
{
|
||||
int rc;
|
||||
int size, mode;
|
||||
char *filename, *buffer;
|
||||
|
||||
rc = ssh_scp_pull_request(scp);
|
||||
if (rc != SSH_SCP_REQUEST_NEWFILE)
|
||||
{
|
||||
fprintf(stderr, "Error receiving information about file: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
size = ssh_scp_request_get_size(scp);
|
||||
filename = strdup(ssh_scp_request_get_filename(scp));
|
||||
mode = ssh_scp_request_get_permissions(scp);
|
||||
printf("Receiving file %s, size %d, permisssions 0%o\n",
|
||||
filename, size, mode);
|
||||
free(filename);
|
||||
|
||||
buffer = malloc(size);
|
||||
if (buffer == NULL)
|
||||
{
|
||||
fprintf(stderr, "Memory allocation error\n");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
ssh_scp_accept_request(scp);
|
||||
rc = ssh_scp_read(scp, buffer, size);
|
||||
if (rc == SSH_ERROR)
|
||||
{
|
||||
fprintf(stderr, "Error receiving file data: %s\n",
|
||||
ssh_get_error(session));
|
||||
free(buffer);
|
||||
return rc;
|
||||
}
|
||||
printf("Done\n");
|
||||
|
||||
write(1, buffer, size);
|
||||
free(buffer);
|
||||
|
||||
rc = ssh_scp_pull_request(scp);
|
||||
if (rc != SSH_SCP_REQUEST_EOF)
|
||||
{
|
||||
fprintf(stderr, "Unexpected request: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
In this example, since we just requested a single file, we expect ssh_scp_request()
|
||||
to return SSH_SCP_REQUEST_NEWFILE first, then SSH_SCP_REQUEST_EOF. That's quite a
|
||||
naive approach; for example, the remote server might send a warning as well
|
||||
(return code SSH_SCP_REQUEST_WARNING) and the example would fail. A more comprehensive
|
||||
reception program would receive the requests in a loop and analyze them carefully
|
||||
until SSH_SCP_REQUEST_EOF has been received.
|
||||
|
||||
|
||||
@subsection scp_recursive_read Receiving full directory trees from the remote server
|
||||
|
||||
If you opened the SCP session in recursive mode, the remote end will be
|
||||
telling you when to change directory.
|
||||
|
||||
In that case, when ssh_scp_pull_request() answers
|
||||
SSH_SCP_REQUEST_NEWDIRECTORY, you should make that local directory (if
|
||||
it does not exist yet) and enter it. When ssh_scp_pull_request() answers
|
||||
SSH_SCP_REQUEST_ENDDIRECTORY, you should leave the current directory.
|
||||
|
||||
*/
|
||||
431
doc/sftp.dox
Normal file
431
doc/sftp.dox
Normal file
@@ -0,0 +1,431 @@
|
||||
/**
|
||||
@page libssh_tutor_sftp Chapter 5: The SFTP subsystem
|
||||
@section sftp_subsystem The SFTP subsystem
|
||||
|
||||
SFTP stands for "Secure File Transfer Protocol". It enables you to safely
|
||||
transfer files between the local and the remote computer. It reminds a lot
|
||||
of the old FTP protocol.
|
||||
|
||||
SFTP is a rich protocol. It lets you do over the network almost everything
|
||||
that you can do with local files:
|
||||
- send files
|
||||
- modify only a portion of a file
|
||||
- receive files
|
||||
- receive only a portion of a file
|
||||
- get file owner and group
|
||||
- get file permissions
|
||||
- set file owner and group
|
||||
- set file permissions
|
||||
- remove files
|
||||
- rename files
|
||||
- create a directory
|
||||
- remove a directory
|
||||
- retrieve the list of files in a directory
|
||||
- get the target of a symbolic link
|
||||
- create symbolic links
|
||||
- get information about mounted filesystems.
|
||||
|
||||
The current implemented version of the SFTP protocol is version 3. All functions
|
||||
aren't implemented yet, but the most important are.
|
||||
|
||||
|
||||
@subsection sftp_session Opening and closing a SFTP session
|
||||
|
||||
Unlike with remote shells and remote commands, when you use the SFTP subsystem,
|
||||
you don't handle directly the SSH channels. Instead, you open a "SFTP session".
|
||||
|
||||
The function sftp_new() creates a new SFTP session. The function sftp_init()
|
||||
initializes it. The function sftp_free() deletes it.
|
||||
|
||||
As you see, all the SFTP-related functions start with the "sftp_" prefix
|
||||
instead of the usual "ssh_" prefix.
|
||||
|
||||
The example below shows how to use these functions:
|
||||
|
||||
@code
|
||||
#include <libssh/sftp.h>
|
||||
|
||||
int sftp_helloworld(ssh_session session)
|
||||
{
|
||||
sftp_session sftp;
|
||||
int rc;
|
||||
|
||||
sftp = sftp_new(session);
|
||||
if (sftp == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error allocating SFTP session: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = sftp_init(sftp);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Error initializing SFTP session: %s.\n",
|
||||
sftp_get_error(sftp));
|
||||
sftp_free(sftp);
|
||||
return rc;
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
sftp_free(sftp);
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection sftp_errors Analyzing SFTP errors
|
||||
|
||||
In case of a problem, the function sftp_get_error() returns a SFTP-specific
|
||||
error number, in addition to the regular SSH error number returned by
|
||||
ssh_get_error_number().
|
||||
|
||||
Possible errors are:
|
||||
- SSH_FX_OK: no error
|
||||
- SSH_FX_EOF: end-of-file encountered
|
||||
- SSH_FX_NO_SUCH_FILE: file does not exist
|
||||
- SSH_FX_PERMISSION_DENIED: permission denied
|
||||
- SSH_FX_FAILURE: generic failure
|
||||
- SSH_FX_BAD_MESSAGE: garbage received from server
|
||||
- SSH_FX_NO_CONNECTION: no connection has been set up
|
||||
- SSH_FX_CONNECTION_LOST: there was a connection, but we lost it
|
||||
- SSH_FX_OP_UNSUPPORTED: operation not supported by libssh yet
|
||||
- SSH_FX_INVALID_HANDLE: invalid file handle
|
||||
- SSH_FX_NO_SUCH_PATH: no such file or directory path exists
|
||||
- SSH_FX_FILE_ALREADY_EXISTS: an attempt to create an already existing file or directory has been made
|
||||
- SSH_FX_WRITE_PROTECT: write-protected filesystem
|
||||
- SSH_FX_NO_MEDIA: no media was in remote drive
|
||||
|
||||
|
||||
@subsection sftp_mkdir Creating a directory
|
||||
|
||||
The function sftp_mkdir() tahes the "SFTP session" we juste created as
|
||||
its first argument. It also needs the name of the file to create, and the
|
||||
desired permissions. The permissions are the same as for the usual mkdir()
|
||||
function. To get a comprehensive list of the available permissions, use the
|
||||
"man 2 stat" command. The desired permissions are combined with the remote
|
||||
user's mask to determine the effective permissions.
|
||||
|
||||
The code below creates a directory named "helloworld" in the current directory that
|
||||
can be read and written only by its owner:
|
||||
|
||||
@code
|
||||
#include <libssh/sftp.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
int sftp_helloworld(ssh_session session, sftp_session sftp)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = sftp_mkdir(sftp, "helloworld", S_IRWXU);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
if (sftp_get_error(sftp) != SSH_FX_FILE_ALREADY_EXISTS)
|
||||
{
|
||||
fprintf(stderr, "Can't create directory: %s\n",
|
||||
ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
Unlike its equivalent in the SCP subsystem, this function does NOT change the
|
||||
current directory to the newly created subdirectory.
|
||||
|
||||
|
||||
@subsection sftp_write Copying a file to the remote computer
|
||||
|
||||
You handle the contents of a remote file just like you would do with a
|
||||
local file: you open the file in a given mode, move the file pointer in it,
|
||||
read or write data, and close the file.
|
||||
|
||||
The sftp_open() function is very similar to the regular open() function,
|
||||
excepted that it returns a file handle of type sftp_file. This file handle
|
||||
is then used by the other file manipulation functions and remains valid
|
||||
until you close the remote file with sftp_close().
|
||||
|
||||
The example below creates a new file named "helloworld.txt" in the
|
||||
newly created "helloworld" directory. If the file already exists, it will
|
||||
be truncated. It then writes the famous "Hello, World!" sentence to the
|
||||
file, followed by a new line character. Finally, the file is closed:
|
||||
|
||||
@code
|
||||
#include <libssh/sftp.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
int sftp_helloworld(ssh_session session, sftp_session sftp)
|
||||
{
|
||||
int access_type = O_WRONLY | O_CREAT | O_TRUNC;
|
||||
sftp_file file;
|
||||
const char *helloworld = "Hello, World!\n";
|
||||
int length = strlen(helloworld);
|
||||
int rc, nwritten;
|
||||
|
||||
...
|
||||
|
||||
file = sftp_open(sftp, "helloworld/helloworld.txt",
|
||||
access_type, S_IRWXU);
|
||||
if (file == NULL)
|
||||
{
|
||||
fprintf(stderr, "Can't open file for writing: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
nwritten = sftp_write(file, helloworld, length);
|
||||
if (nwritten != length)
|
||||
{
|
||||
fprintf(stderr, "Can't write data to file: %s\n",
|
||||
ssh_get_error(session));
|
||||
sftp_close(file);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = sftp_close(file);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Can't close the written file: %s\n",
|
||||
ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection sftp_read Reading a file from the remote computer
|
||||
|
||||
The nice thing with reading a file over the network through SFTP is that it
|
||||
can be done both in a synchronous way or an asynchronous way. If you read the file
|
||||
asynchronously, your program can do something else while it waits for the
|
||||
results to come.
|
||||
|
||||
Synchronous read is done with sftp_read().
|
||||
|
||||
Files are normally transferred in chunks. A good chunk size is 16 KB. The following
|
||||
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
|
||||
// Good chunk size
|
||||
#define MAX_XFER_BUF_SIZE 16384
|
||||
|
||||
int sftp_read_sync(ssh_session session, sftp_session sftp)
|
||||
{
|
||||
int access_type;
|
||||
sftp_file file;
|
||||
char buffer[MAX_XFER_BUF_SIZE];
|
||||
int nbytes, nwritten, rc;
|
||||
int fd;
|
||||
|
||||
access_type = O_RDONLY;
|
||||
file = sftp_open(sftp, "/etc/profile",
|
||||
access_type, 0);
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "Can't open file for reading: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
fd = open("/path/to/profile", O_CREAT);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Can't open file for writing: %s\n",
|
||||
strerror(errno));
|
||||
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, buf, nbytes);
|
||||
if (nwritten != nbytes) {
|
||||
fprintf(stderr, "Error writing: %s\n",
|
||||
strerror(errno));
|
||||
sftp_close(file);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
rc = sftp_close(file);
|
||||
if (rc != SSH_OK) {
|
||||
fprintf(stderr, "Can't close the read file: %s\n",
|
||||
ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
Asynchronous read is done in two steps, first sftp_async_read_begin(), which
|
||||
returns a "request handle", and then sftp_async_read(), which uses that request handle.
|
||||
If the file has been opened in nonblocking mode, then sftp_async_read()
|
||||
might return SSH_AGAIN, which means that the request hasn't completed yet
|
||||
and that the function should be called again later on. Otherwise,
|
||||
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.
|
||||
|
||||
The example below reads a very big file in asynchronous, nonblocking, mode. Each
|
||||
time the data are not ready yet, a counter is incrementer.
|
||||
|
||||
@code
|
||||
// Good chunk size
|
||||
#define MAX_XFER_BUF_SIZE 16384
|
||||
|
||||
int sftp_read_async(ssh_session session, sftp_session sftp)
|
||||
{
|
||||
int access_type;
|
||||
sftp_file file;
|
||||
char buffer[MAX_XFER_BUF_SIZE];
|
||||
int async_request;
|
||||
int nbytes;
|
||||
long counter;
|
||||
int rc;
|
||||
|
||||
access_type = O_RDONLY;
|
||||
file = sftp_open(sftp, "some_very_big_file",
|
||||
access_type, 0);
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "Can't open file for reading: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
sftp_file_set_nonblocking(file);
|
||||
|
||||
async_request = sftp_async_read_begin(file, sizeof(buffer));
|
||||
counter = 0L;
|
||||
usleep(10000);
|
||||
if (async_request >= 0) {
|
||||
nbytes = sftp_async_read(file, buffer, sizeof(buffer),
|
||||
async_request);
|
||||
} else {
|
||||
nbytes = -1;
|
||||
}
|
||||
|
||||
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",
|
||||
ssh_get_error(session));
|
||||
sftp_close(file);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
printf("The counter has reached value: %ld\n", counter);
|
||||
|
||||
rc = sftp_close(file);
|
||||
if (rc != SSH_OK) {
|
||||
fprintf(stderr, "Can't close the read file: %s\n",
|
||||
ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@subsection sftp_ls Listing the contents of a directory
|
||||
|
||||
The functions sftp_opendir(), sftp_readdir(), sftp_dir_eof(),
|
||||
and sftp_closedir() enable to list the contents of a directory.
|
||||
They use a new handle_type, "sftp_dir", which gives access to the
|
||||
directory being read.
|
||||
|
||||
In addition, sftp_readdir() returns a "sftp_attributes" which is a pointer
|
||||
to a structure with informations about a directory entry:
|
||||
- name: the name of the file or directory
|
||||
- size: its size in bytes
|
||||
- etc.
|
||||
|
||||
sftp_readdir() might return NULL under two conditions:
|
||||
- when the end of the directory has been met
|
||||
- when an error occured
|
||||
|
||||
To tell the difference, call sftp_dir_eof().
|
||||
|
||||
The attributes must be freed with sftp_attributes_free() when no longer
|
||||
needed.
|
||||
|
||||
The following example reads the contents of some remote directory:
|
||||
|
||||
@code
|
||||
int sftp_list_dir(ssh_session session, sftp_session sftp)
|
||||
{
|
||||
sftp_dir dir;
|
||||
sftp_attributes attributes;
|
||||
int rc;
|
||||
|
||||
dir = sftp_opendir(sftp, "/var/log");
|
||||
if (!dir)
|
||||
{
|
||||
fprintf(stderr, "Directory not opened: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
printf("Name Size Perms Owner\tGroup\n");
|
||||
|
||||
while ((attributes = sftp_readdir(sftp, dir)) != NULL)
|
||||
{
|
||||
printf("%-20s %10llu %.8o %s(%d)\t%s(%d)\n",
|
||||
attributes->name,
|
||||
(long long unsigned int) attributes->size,
|
||||
attributes->permissions,
|
||||
attributes->owner,
|
||||
attributes->uid,
|
||||
attributes->group,
|
||||
attributes->gid);
|
||||
|
||||
sftp_attributes_free(attributes);
|
||||
}
|
||||
|
||||
if (!sftp_dir_eof(dir))
|
||||
{
|
||||
fprintf(stderr, "Can't list directory: %s\n",
|
||||
ssh_get_error(session));
|
||||
sftp_closedir(dir);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = sftp_closedir(dir);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Can't close directory: %s\n",
|
||||
ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
@endcode
|
||||
|
||||
*/
|
||||
361
doc/shell.dox
Normal file
361
doc/shell.dox
Normal file
@@ -0,0 +1,361 @@
|
||||
/**
|
||||
@page libssh_tutor_shell Chapter 3: Opening a remote shell
|
||||
@section opening_shell Opening a remote shell
|
||||
|
||||
We already mentioned that a single SSH connection can be shared
|
||||
between several "channels". Channels can be used for different purposes.
|
||||
|
||||
This chapter shows how to open one of these channels, and how to use it to
|
||||
start a command interpreter on a remote computer.
|
||||
|
||||
|
||||
@subsection open_channel Opening and closing a channel
|
||||
|
||||
The ssh_channel_new() function creates a channel. It returns the channel as
|
||||
a variable of type ssh_channel.
|
||||
|
||||
Once you have this channel, you open a SSH session that uses it with
|
||||
ssh_channel_open_session().
|
||||
|
||||
Once you don't need the channel anymore, you can send an end-of-file
|
||||
to it with ssh_channel_close(). At this point, you can destroy the channel
|
||||
with ssh_channel_free().
|
||||
|
||||
The code sample below achieves these tasks:
|
||||
|
||||
@code
|
||||
int shell_session(ssh_session session)
|
||||
{
|
||||
ssh_channel channel;
|
||||
int rc;
|
||||
|
||||
channel = ssh_channel_new(session);
|
||||
if (channel == NULL)
|
||||
return SSH_ERROR;
|
||||
|
||||
rc = ssh_channel_open_session(channel);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
ssh_channel_free(channel);
|
||||
return rc;
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_send_eof(channel);
|
||||
ssh_channel_free(channel);
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection interactive Interactive and non-interactive sessions
|
||||
|
||||
A "shell" is a command interpreter. It is said to be "interactive"
|
||||
if there is a human user typing the commands, one after the
|
||||
other. The contrary, a non-interactive shell, is similar to
|
||||
the execution of commands in the background: there is no attached
|
||||
terminal.
|
||||
|
||||
If you plan using an interactive shell, you need to create a
|
||||
pseud-terminal on the remote side. A remote terminal is usually referred
|
||||
to as a "pty", for "pseudo-teletype". The remote processes won't see the
|
||||
difference with a real text-oriented terminal.
|
||||
|
||||
If needed, you request the pty with the function ssh_channel_request_pty().
|
||||
Then you define its dimensions (number of rows and columns)
|
||||
with ssh_channel_change_pty_size().
|
||||
|
||||
Be your session interactive or not, the next step is to request a
|
||||
shell with ssh_channel_request_shell().
|
||||
|
||||
@code
|
||||
int interactive_shell_session(ssh_channel channel)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = ssh_channel_request_pty(channel);
|
||||
if (rc != SSH_OK) return rc;
|
||||
|
||||
rc = ssh_channel_change_pty_size(channel, 80, 24);
|
||||
if (rc != SSH_OK) return rc;
|
||||
|
||||
rc = ssh_channel_request_shell(channel);
|
||||
if (rc != SSH_OK) return rc;
|
||||
|
||||
...
|
||||
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection read_data Displaying the data sent by the remote computer
|
||||
|
||||
In your program, you will usually need to receive all the data "displayed"
|
||||
into the remote pty. You will usually analyse, log, or display this data.
|
||||
|
||||
ssh_channel_read() and ssh_channel_read_nonblocking() are the simplest
|
||||
way to read data from a channel. If you only need to read from a single
|
||||
channel, they should be enough.
|
||||
|
||||
The example below shows how to wait for remote data using ssh_channel_read():
|
||||
|
||||
@code
|
||||
int interactive_shell_session(ssh_channel channel)
|
||||
{
|
||||
int rc;
|
||||
char buffer[256];
|
||||
int nbytes;
|
||||
|
||||
rc = ssh_channel_request_pty(channel);
|
||||
if (rc != SSH_OK) return rc;
|
||||
|
||||
rc = ssh_channel_change_pty_size(channel, 80, 24);
|
||||
if (rc != SSH_OK) return rc;
|
||||
|
||||
rc = ssh_channel_request_shell(channel);
|
||||
if (rc != SSH_OK) return rc;
|
||||
|
||||
while (ssh_channel_is_open(channel) &&
|
||||
!ssh_channel_is_eof(channel))
|
||||
{
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
if (nbytes < 0)
|
||||
return SSH_ERROR;
|
||||
|
||||
if (nbytes > 0)
|
||||
write(1, buffer, nbytes);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
Unlike ssh_channel_read(), ssh_channel_read_nonblocking() never waits for
|
||||
remote data to be ready. It returns immediately.
|
||||
|
||||
If you plan to use ssh_channel_read_nonblocking() repeatedly in a loop,
|
||||
you should use a "passive wait" function like usleep(3) in the same
|
||||
loop. Otherwise, your program will consume all the CPU time, and your
|
||||
computer might become unresponsive.
|
||||
|
||||
|
||||
@subsection write_data Sending user input to the remote computer
|
||||
|
||||
User's input is sent to the remote site with ssh_channel_write().
|
||||
|
||||
The following example shows how to combine a nonblocking read from a SSH
|
||||
channel with a nonblocking read from the keyboard. The local input is then
|
||||
sent to the remote computer:
|
||||
|
||||
@code
|
||||
/* Under Linux, this function determines whether a key has been pressed.
|
||||
Under Windows, it is a standard function, so you need not redefine it.
|
||||
*/
|
||||
int kbhit()
|
||||
{
|
||||
struct timeval tv = { 0L, 0L };
|
||||
fd_set fds;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(0, &fds);
|
||||
|
||||
return select(1, &fds, NULL, NULL, &tv);
|
||||
}
|
||||
|
||||
/* A very simple terminal emulator:
|
||||
- print data received from the remote computer
|
||||
- send keyboard input to the remote computer
|
||||
*/
|
||||
int interactive_shell_session(ssh_channel channel)
|
||||
{
|
||||
/* Session and terminal initialization skipped */
|
||||
...
|
||||
|
||||
char buffer[256];
|
||||
int nbytes, nwritten;
|
||||
|
||||
while (ssh_channel_is_open(channel) &&
|
||||
!ssh_channel_is_eof(channel))
|
||||
{
|
||||
nbytes = ssh_channel_read_nonblocking(channel, buffer, sizeof(buffer), 0);
|
||||
if (nbytes < 0) return SSH_ERROR;
|
||||
if (nbytes > 0)
|
||||
{
|
||||
nwritten = write(1, buffer, nbytes);
|
||||
if (nwritten != nbytes) return SSH_ERROR;
|
||||
|
||||
if (!kbhit())
|
||||
{
|
||||
usleep(50000L); // 0.05 second
|
||||
continue;
|
||||
}
|
||||
|
||||
nbytes = read(0, buffer, sizeof(buffer));
|
||||
if (nbytes < 0) return SSH_ERROR;
|
||||
if (nbytes > 0)
|
||||
{
|
||||
nwritten = ssh_channel_write(channel, buffer, nbytes);
|
||||
if (nwritten != nbytes) return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
Of course, this is a poor terminal emulator, since the echo from the keys
|
||||
pressed should not be done locally, but should be done by the remote side.
|
||||
Also, user's input should not be sent once "Enter" key is pressed, but
|
||||
immediately after each key is pressed. This can be accomplished
|
||||
by setting the local terminal to "raw" mode with the cfmakeraw(3) function.
|
||||
cfmakeraw() is a standard function under Linux, on other systems you can
|
||||
recode it with:
|
||||
|
||||
@code
|
||||
static void cfmakeraw(struct termios *termios_p)
|
||||
{
|
||||
termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
|
||||
termios_p->c_oflag &= ~OPOST;
|
||||
termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
|
||||
termios_p->c_cflag &= ~(CSIZE|PARENB);
|
||||
termios_p->c_cflag |= CS8;
|
||||
}
|
||||
@endcode
|
||||
|
||||
If you are not using a local terminal, but some kind of graphical
|
||||
environment, the solution to this kind of "echo" problems will be different.
|
||||
|
||||
|
||||
@subsection select_loop A more elaborate way to get the remote data
|
||||
|
||||
*** Warning: ssh_select() and ssh_channel_select() are not relevant anymore,
|
||||
since libssh is about to provide an easier system for asynchronous
|
||||
communications. This subsection should be removed then. ***
|
||||
|
||||
ssh_channel_read() and ssh_channel_read_nonblocking() functions are simple,
|
||||
but they are not adapted when you expect data from more than one SSH channel,
|
||||
or from other file descriptors. Last example showed how getting data from
|
||||
the standard input (the keyboard) at the same time as data from the SSH
|
||||
channel was complicated. The functions ssh_select() and ssh_channel_select()
|
||||
provide a more elegant way to wait for data coming from many sources.
|
||||
|
||||
The functions ssh_select() and ssh_channel_select() remind of the standard
|
||||
UNIX select(2) function. The idea is to wait for "something" to happen:
|
||||
incoming data to be read, outcoming data to block, or an exception to
|
||||
occur. Both these functions do a "passive wait", i.e. you can safely use
|
||||
them repeatedly in a loop, it will not consume exaggerate processor time
|
||||
and make your computer unresponsive. It is quite common to use these
|
||||
functions in your application's main loop.
|
||||
|
||||
The difference between ssh_select() and ssh_channel_select() is that
|
||||
ssh_channel_select() is simpler, but allows you only to watch SSH channels.
|
||||
ssh_select() is more complete and enables watching regular file descriptors
|
||||
as well, in the same function call.
|
||||
|
||||
Below is an example of a function that waits both for remote SSH data to come,
|
||||
as well as standard input from the keyboard:
|
||||
|
||||
@code
|
||||
int interactive_shell_session(ssh_session session, ssh_channel channel)
|
||||
{
|
||||
/* Session and terminal initialization skipped */
|
||||
...
|
||||
|
||||
char buffer[256];
|
||||
int nbytes, nwritten;
|
||||
|
||||
while (ssh_channel_is_open(channel) &&
|
||||
!ssh_channel_is_eof(channel))
|
||||
{
|
||||
struct timeval timeout;
|
||||
ssh_channel in_channels[2], out_channels[2];
|
||||
fd_set fds;
|
||||
int maxfd;
|
||||
|
||||
timeout.tv_sec = 30;
|
||||
timeout.tv_usec = 0;
|
||||
in_channels[0] = channel;
|
||||
in_channels[1] = NULL;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(0, &fds);
|
||||
FD_SET(ssh_get_fd(session), &fds);
|
||||
maxfd = ssh_get_fd(session) + 1;
|
||||
|
||||
ssh_select(in_channels, out_channels, maxfd, &fds, &timeout);
|
||||
|
||||
if (out_channels[0] != NULL)
|
||||
{
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
if (nbytes < 0) return SSH_ERROR;
|
||||
if (nbytes > 0)
|
||||
{
|
||||
nwritten = write(1, buffer, nbytes);
|
||||
if (nwritten != nbytes) return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (FD_ISSET(0, &fds))
|
||||
{
|
||||
nbytes = read(0, buffer, sizeof(buffer));
|
||||
if (nbytes < 0) return SSH_ERROR;
|
||||
if (nbytes > 0)
|
||||
{
|
||||
nwritten = ssh_channel_write(channel, buffer, nbytes);
|
||||
if (nbytes != nwritten) return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection x11 Using graphical applications on the remote side
|
||||
|
||||
If your remote application is graphical, you can forward the X11 protocol to
|
||||
your local computer.
|
||||
|
||||
To do that, you first declare that you accept X11 connections with
|
||||
ssh_channel_accept_x11(). Then you create the forwarding tunnel for
|
||||
the X11 protocol with ssh_channel_request_x11().
|
||||
|
||||
The following code performs channel initialization and shell session
|
||||
opening, and handles a parallel X11 connection:
|
||||
|
||||
@code
|
||||
int interactive_shell_session(ssh_channel channel)
|
||||
{
|
||||
int rc;
|
||||
ssh_channel x11channel;
|
||||
|
||||
rc = ssh_channel_request_pty(channel);
|
||||
if (rc != SSH_OK) return rc;
|
||||
|
||||
rc = ssh_channel_change_pty_size(channel, 80, 24);
|
||||
if (rc != SSH_OK) return rc;
|
||||
|
||||
rc = ssh_channel_request_x11(channel, 0, NULL, NULL, 0);
|
||||
if (rc != SSH_OK) return rc;
|
||||
|
||||
rc = ssh_channel_request_shell(channel);
|
||||
if (rc != SSH_OK) return rc;
|
||||
|
||||
/* Read the data sent by the remote computer here */
|
||||
...
|
||||
}
|
||||
@endcode
|
||||
|
||||
Don't forget to set the $DISPLAY environment variable on the remote
|
||||
side, or the remote applications won't try using the X11 tunnel:
|
||||
|
||||
@code
|
||||
$ export DISPLAY=:0
|
||||
$ xclock &
|
||||
@endcode
|
||||
|
||||
*/
|
||||
184
doc/style.css
184
doc/style.css
@@ -1,184 +0,0 @@
|
||||
|
||||
body {
|
||||
background-color:#ddf;
|
||||
/*background-image:url(../back6.jpg);*/
|
||||
margin:10px 10px 10px 10px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family:verdana, sans-serif;
|
||||
font-size:80%;
|
||||
color:black;
|
||||
background-color:transparent;
|
||||
text-align:left;
|
||||
}
|
||||
h2 {
|
||||
font-family:verdana, sans-serif;
|
||||
font-size:100%;
|
||||
color:black;
|
||||
background-color:transparent;
|
||||
text-align:left;
|
||||
}
|
||||
h3 {
|
||||
font-family:verdana, sans-serif;
|
||||
font-size:80%;
|
||||
color:black;
|
||||
background-color:transparent;
|
||||
text-align:left;
|
||||
}
|
||||
p {
|
||||
font-family:verdana, sans-serif;
|
||||
font-size:80%;
|
||||
color:black;
|
||||
background-color:transparent;
|
||||
text-align:left;
|
||||
margin-left:0px;
|
||||
margin-right:0px;
|
||||
}
|
||||
li {
|
||||
font-family:verdana, sans-serif;
|
||||
font-size:80%;
|
||||
color:black;
|
||||
background-color:transparent;
|
||||
text-align:left;
|
||||
margin-left:0px;
|
||||
margin-right:0px;
|
||||
}
|
||||
a:link {
|
||||
font-family:verdana, sans-serif;
|
||||
font-size:100%;
|
||||
color:black;
|
||||
background-color:transparent;
|
||||
text-decoration:underline;
|
||||
}
|
||||
a:visited {
|
||||
font-family:verdana, sans-serif;
|
||||
font-size:100%;
|
||||
color:black;
|
||||
background-color:transparent;
|
||||
text-decoration:underline;
|
||||
}
|
||||
a:hover {
|
||||
font-family:verdana, sans-serif;
|
||||
font-size:100%;
|
||||
color:black;
|
||||
background-color:transparent;
|
||||
text-decoration:underline;
|
||||
}
|
||||
|
||||
table {
|
||||
border-color:transparent;
|
||||
border-style:solid;
|
||||
border-width:1px;
|
||||
}
|
||||
|
||||
td {
|
||||
font-family:verdana, sans-serif;
|
||||
font-size:80%;
|
||||
color:black;
|
||||
text-align:left;
|
||||
background-color:transparent;
|
||||
border-color:transparent;
|
||||
border-style:solid;
|
||||
border-width:1px;
|
||||
}
|
||||
|
||||
.tout {
|
||||
margin: 5px;
|
||||
padding: 0px;
|
||||
border: 2px solid #aac;
|
||||
background: #eef;
|
||||
}
|
||||
|
||||
.prot {
|
||||
border-style:solid;
|
||||
border-width:2px;
|
||||
border-color:#88F;
|
||||
padding: 4px;
|
||||
background-color:#cce;
|
||||
margin: 5px 5px 5px 5px;
|
||||
}
|
||||
|
||||
.ex {
|
||||
border-style:solid;
|
||||
border-width:2px;
|
||||
border-color:#aaF;
|
||||
padding: 4px;
|
||||
background-color:#dde;
|
||||
margin: 5px 5px 5px 5px;
|
||||
}
|
||||
.desc {
|
||||
border-style:solid;
|
||||
border-width:3px;
|
||||
border-color:#66F;
|
||||
padding: 4px;
|
||||
background-color:#aac;
|
||||
margin: 15px 5px 20px 5px;
|
||||
}
|
||||
|
||||
#titre {
|
||||
margin: 5px;
|
||||
padding: 0px;
|
||||
border: 5px solid #aac;
|
||||
background: #eef;
|
||||
}
|
||||
|
||||
#gauche {
|
||||
float:left;
|
||||
margin: 5px;
|
||||
padding: 4px;
|
||||
border: 5px solid #aac;
|
||||
background: #bbf;
|
||||
width: 130px;
|
||||
}
|
||||
|
||||
#droite {
|
||||
position: relative;
|
||||
top:5px;
|
||||
left:165px;
|
||||
margin: 5px 170px 5px 5px;
|
||||
padding: 10px;
|
||||
border: 5px solid #aac;
|
||||
background: #bbf;
|
||||
}
|
||||
|
||||
/* boutons */
|
||||
|
||||
a.bouton:link{
|
||||
width:128px;
|
||||
height:34px;
|
||||
text-decoration:none;
|
||||
color:#aaa;
|
||||
text-align:center;
|
||||
font-weight:bold;
|
||||
/*background-color:#444;*/
|
||||
background-image:url(noclicked.png);
|
||||
}
|
||||
|
||||
a.bouton:visited{
|
||||
width:128px;
|
||||
height:34px;
|
||||
text-decoration:none;
|
||||
color:#aaa;
|
||||
text-align:center;
|
||||
font-weight:bold;
|
||||
/*background-color:#444;*/
|
||||
background-image:url(noclicked.png);
|
||||
}
|
||||
|
||||
a.bouton:hover{
|
||||
width:128px;
|
||||
height:34px;
|
||||
text-decoration:none;
|
||||
color:white;
|
||||
text-align:center;
|
||||
font-weight:bold;
|
||||
/*background-color:#888;*/
|
||||
background-image:url(clicked.png);
|
||||
}
|
||||
|
||||
.bouton{
|
||||
text-align:center;
|
||||
display:block;
|
||||
}
|
||||
|
||||
14
doc/tbd.dox
Normal file
14
doc/tbd.dox
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
@page libssh_tutor_todo To be done
|
||||
|
||||
*** To be written ***
|
||||
|
||||
@section sshd Writing a libssh-based server
|
||||
|
||||
*** To be written ***
|
||||
|
||||
@section cpp The libssh C++ wrapper
|
||||
|
||||
*** To be written ***
|
||||
|
||||
*/
|
||||
66
doc/threading.dox
Normal file
66
doc/threading.dox
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
@page libssh_tutor_threads Chapter 8: Threads with libssh
|
||||
@section threads_with_libssh How to use libssh with threads
|
||||
|
||||
libssh may be used in multithreaded applications, but under several conditions :
|
||||
- Threading must be initialized during the initialization of libssh. This
|
||||
initialization must be done outside of any threading context.
|
||||
- If pthreads is being used by your application (or your framework's backend),
|
||||
you must link with libssh_threads dynamic library and initialize
|
||||
threading with the ssh_threads_pthreads threading object.
|
||||
- If an other threading library is being used by your application, you must
|
||||
implement all the methods of the ssh_threads_callbacks_struct structure
|
||||
and initialize libssh with it.
|
||||
- At all times, you may use different sessions inside threads, make parallel
|
||||
connections, read/write on different sessions and so on. You *cannot* use a
|
||||
single session (or channels for a single session) in several threads at the same
|
||||
time. This will most likely lead to internal state corruption. This limitation is
|
||||
being worked out and will maybe disappear later.
|
||||
|
||||
@subsection threads_init Initialization of threads
|
||||
|
||||
To initialize threading, you must first select the threading model you want to
|
||||
use, using ssh_threads_set_callbacks(), then call ssh_init().
|
||||
|
||||
@code
|
||||
#include <libssh/callbacks.h>
|
||||
...
|
||||
ssh_threads_set_callbacks(ssh_threads_get_noop());
|
||||
ssh_init();
|
||||
@endcode
|
||||
|
||||
ssh_threads_noop is the threading structure that does nothing. It's the
|
||||
threading callbacks being used by default when you're not using threading.
|
||||
|
||||
@subsection threads_pthread Using libpthread with libssh
|
||||
|
||||
If your application is using libpthread, you may simply use the libpthread
|
||||
threading backend:
|
||||
|
||||
@code
|
||||
#include <libssh/callbacks.h>
|
||||
...
|
||||
ssh_threads_set_callbacks(ssh_threads_get_pthread());
|
||||
ssh_init();
|
||||
@endcode
|
||||
|
||||
However, you must be sure to link with the library ssh_threads. If
|
||||
you're using gcc, you must use the commandline
|
||||
@code
|
||||
gcc -o output input.c -lssh -lssh_threads
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection threads_other Using another threading library
|
||||
|
||||
You must find your way in the ssh_threads_callbacks_struct structure. You must
|
||||
implement the following methods :
|
||||
- mutex_lock
|
||||
- mutex_unlock
|
||||
- mutex_init
|
||||
- mutex_destroy
|
||||
- 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 !
|
||||
*/
|
||||
@@ -1,4 +1,4 @@
|
||||
project(libssh-examples C)
|
||||
project(libssh-examples C CXX)
|
||||
|
||||
set(examples_SRCS
|
||||
authentication.c
|
||||
@@ -6,36 +6,61 @@ set(examples_SRCS
|
||||
connect_ssh.c
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${LIBSSH_PUBLIC_INCLUDE_DIRS}
|
||||
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
add_executable(libssh_scp libssh_scp.c ${examples_SRCS})
|
||||
add_executable(scp_download scp_download.c ${examples_SRCS})
|
||||
add_executable(samplessh sample.c ${examples_SRCS})
|
||||
add_executable(exec exec.c ${examples_SRCS})
|
||||
add_executable(sshnetcat sshnetcat.c ${examples_SRCS})
|
||||
|
||||
target_link_libraries(libssh_scp ${LIBSSH_SHARED_LIBRARY})
|
||||
target_link_libraries(scp_download ${LIBSSH_SHARED_LIBRARY})
|
||||
target_link_libraries(samplessh ${LIBSSH_SHARED_LIBRARY})
|
||||
target_link_libraries(exec ${LIBSSH_SHARED_LIBRARY})
|
||||
target_link_libraries(sshnetcat ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
|
||||
include_directories(
|
||||
${LIBSSH_PUBLIC_INCLUDE_DIRS}
|
||||
${CMAKE_BINARY_DIR}
|
||||
)
|
||||
|
||||
if (WITH_SFTP)
|
||||
add_executable(samplesftp samplesftp.c ${examples_SRCS})
|
||||
target_link_libraries(samplesftp ${LIBSSH_SHARED_LIBRARY})
|
||||
endif (WITH_SFTP)
|
||||
if (BSD OR SOLARIS OR OSX)
|
||||
find_package(Argp)
|
||||
endif (BSD OR SOLARIS OR OSX)
|
||||
|
||||
if (WITH_SERVER)
|
||||
add_executable(samplesshd samplesshd.c)
|
||||
target_link_libraries(samplesshd ${LIBSSH_SHARED_LIBRARY})
|
||||
endif (WITH_SERVER)
|
||||
if (UNIX AND NOT WIN32)
|
||||
add_executable(libssh_scp libssh_scp.c ${examples_SRCS})
|
||||
target_link_libraries(libssh_scp ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
add_executable(scp_download scp_download.c ${examples_SRCS})
|
||||
target_link_libraries(scp_download ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
add_executable(sshnetcat sshnetcat.c ${examples_SRCS})
|
||||
target_link_libraries(sshnetcat ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
if (WITH_SFTP)
|
||||
add_executable(samplesftp samplesftp.c ${examples_SRCS})
|
||||
target_link_libraries(samplesftp ${LIBSSH_SHARED_LIBRARY})
|
||||
endif (WITH_SFTP)
|
||||
|
||||
add_executable(samplessh sample.c ${examples_SRCS})
|
||||
target_link_libraries(samplessh ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
if (WITH_SERVER)
|
||||
if (HAVE_LIBUTIL)
|
||||
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)
|
||||
add_executable(samplesshd-cb samplesshd-cb.c)
|
||||
target_link_libraries(samplesshd-cb ${LIBSSH_SHARED_LIBRARY} ${ARGP_LIBRARIES})
|
||||
|
||||
add_executable(proxy proxy.c)
|
||||
target_link_libraries(proxy ${LIBSSH_SHARED_LIBRARY} ${ARGP_LIBRARIES})
|
||||
endif (WITH_GSSAPI AND GSSAPI_FOUND)
|
||||
|
||||
add_executable(samplesshd-kbdint samplesshd-kbdint.c)
|
||||
target_link_libraries(samplesshd-kbdint ${LIBSSH_SHARED_LIBRARY} ${ARGP_LIBRARIES})
|
||||
|
||||
endif (WITH_SERVER)
|
||||
endif (UNIX AND NOT WIN32)
|
||||
|
||||
add_executable(exec exec.c ${examples_SRCS})
|
||||
target_link_libraries(exec ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
add_executable(senddata senddata.c ${examples_SRCS})
|
||||
target_link_libraries(senddata ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
add_executable(libsshpp libsshpp.cpp)
|
||||
target_link_libraries(libsshpp ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
add_executable(libsshpp_noexcept libsshpp_noexcept.cpp)
|
||||
target_link_libraries(libsshpp_noexcept ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
@@ -18,74 +18,121 @@ clients must be made or how a client should react.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include "examples_common.h"
|
||||
|
||||
int authenticate_kbdint(ssh_session session){
|
||||
int err=ssh_userauth_kbdint(session,NULL,NULL);
|
||||
const char *name, *instruction, *prompt;
|
||||
char *ptr;
|
||||
char buffer[128];
|
||||
int i,n;
|
||||
char echo;
|
||||
while (err==SSH_AUTH_INFO){
|
||||
name=ssh_userauth_kbdint_getname(session);
|
||||
instruction=ssh_userauth_kbdint_getinstruction(session);
|
||||
n=ssh_userauth_kbdint_getnprompts(session);
|
||||
if(strlen(name)>0)
|
||||
printf("%s\n",name);
|
||||
if(strlen(instruction)>0)
|
||||
printf("%s\n",instruction);
|
||||
for(i=0;i<n;++i){
|
||||
prompt=ssh_userauth_kbdint_getprompt(session,i,&echo);
|
||||
if(echo){
|
||||
printf("%s",prompt);
|
||||
fgets(buffer,sizeof(buffer),stdin);
|
||||
buffer[sizeof(buffer)-1]=0;
|
||||
if((ptr=strchr(buffer,'\n')))
|
||||
*ptr=0;
|
||||
if (ssh_userauth_kbdint_setanswer(session,i,buffer) < 0) {
|
||||
return SSH_AUTH_ERROR;
|
||||
int authenticate_kbdint(ssh_session session, const char *password) {
|
||||
int err;
|
||||
|
||||
err = ssh_userauth_kbdint(session, NULL, NULL);
|
||||
while (err == SSH_AUTH_INFO) {
|
||||
const char *instruction;
|
||||
const char *name;
|
||||
char buffer[128];
|
||||
int i, n;
|
||||
|
||||
name = ssh_userauth_kbdint_getname(session);
|
||||
instruction = ssh_userauth_kbdint_getinstruction(session);
|
||||
n = ssh_userauth_kbdint_getnprompts(session);
|
||||
|
||||
if (name && strlen(name) > 0) {
|
||||
printf("%s\n", name);
|
||||
}
|
||||
memset(buffer,0,strlen(buffer));
|
||||
} else {
|
||||
ptr=getpass(prompt);
|
||||
if (ssh_userauth_kbdint_setanswer(session,i,ptr) < 0) {
|
||||
return SSH_AUTH_ERROR;
|
||||
|
||||
if (instruction && strlen(instruction) > 0) {
|
||||
printf("%s\n", instruction);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
const char *answer;
|
||||
const char *prompt;
|
||||
char echo;
|
||||
|
||||
prompt = ssh_userauth_kbdint_getprompt(session, i, &echo);
|
||||
if (prompt == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (echo) {
|
||||
char *p;
|
||||
|
||||
printf("%s", prompt);
|
||||
|
||||
if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
buffer[sizeof(buffer) - 1] = '\0';
|
||||
if ((p = strchr(buffer, '\n'))) {
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
if (ssh_userauth_kbdint_setanswer(session, i, buffer) < 0) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
memset(buffer, 0, strlen(buffer));
|
||||
} else {
|
||||
if (password && strstr(prompt, "Password:")) {
|
||||
answer = password;
|
||||
} else {
|
||||
buffer[0] = '\0';
|
||||
|
||||
if (ssh_getpass(prompt, buffer, sizeof(buffer), 0, 0) < 0) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
answer = buffer;
|
||||
}
|
||||
err = ssh_userauth_kbdint_setanswer(session, i, answer);
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
if (err < 0) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
err=ssh_userauth_kbdint(session,NULL,NULL);
|
||||
}
|
||||
err=ssh_userauth_kbdint(session,NULL,NULL);
|
||||
}
|
||||
return err;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void error(ssh_session session){
|
||||
fprintf(stderr,"Authentication failed: %s\n",ssh_get_error(session));
|
||||
}
|
||||
|
||||
int authenticate_console(ssh_session session){
|
||||
int rc;
|
||||
int method;
|
||||
char *password;
|
||||
char password[128] = {0};
|
||||
char *banner;
|
||||
|
||||
// Try to authenticate
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
perror("Authentication failed.");
|
||||
error(session);
|
||||
return rc;
|
||||
}
|
||||
|
||||
method = ssh_auth_list(session);
|
||||
method = ssh_userauth_list(session, NULL);
|
||||
while (rc != SSH_AUTH_SUCCESS) {
|
||||
|
||||
if (method & SSH_AUTH_METHOD_GSSAPI_MIC){
|
||||
rc = ssh_userauth_gssapi(session);
|
||||
if(rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Try to authenticate with public key first
|
||||
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) {
|
||||
perror("Authentication failed.");
|
||||
return rc;
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
@@ -93,32 +140,36 @@ int authenticate_console(ssh_session session){
|
||||
|
||||
// Try to authenticate with keyboard interactive";
|
||||
if (method & SSH_AUTH_METHOD_INTERACTIVE) {
|
||||
rc = authenticate_kbdint(session);
|
||||
rc = authenticate_kbdint(session, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
perror("Authentication failed.");
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
password=getpass("Password: ");
|
||||
if (ssh_getpass("Password: ", password, sizeof(password), 0, 0) < 0) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
// Try to authenticate with password
|
||||
if (method & SSH_AUTH_METHOD_PASSWORD) {
|
||||
rc = ssh_userauth_password(session, NULL, password);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
perror("Authentication failed.");
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
memset(password, 0, sizeof(password));
|
||||
}
|
||||
|
||||
banner = ssh_get_issue_banner(session);
|
||||
if (banner) {
|
||||
printf("%s\n",banner);
|
||||
free(banner);
|
||||
ssh_string_free_char(banner);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
@@ -32,22 +32,25 @@ ssh_session connect_ssh(const char *host, const char *user,int verbosity){
|
||||
|
||||
if(user != NULL){
|
||||
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) {
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||
if(ssh_connect(session)){
|
||||
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
if(verify_knownhost(session)<0){
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
auth=authenticate_console(session);
|
||||
@@ -59,5 +62,6 @@ ssh_session connect_ssh(const char *host, const char *user,int verbosity){
|
||||
fprintf(stderr,"Error while authenticating : %s\n",ssh_get_error(session));
|
||||
}
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ clients must be made or how a client should react.
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
int authenticate_console(ssh_session session);
|
||||
int authenticate_kbdint(ssh_session session);
|
||||
int authenticate_kbdint(ssh_session session, const char *password);
|
||||
int verify_knownhost(ssh_session session);
|
||||
ssh_session connect_ssh(const char *hostname, const char *user, int verbosity);
|
||||
|
||||
|
||||
@@ -5,53 +5,62 @@
|
||||
#include "examples_common.h"
|
||||
|
||||
int main(void) {
|
||||
ssh_session session;
|
||||
ssh_channel channel;
|
||||
char buf[4096];
|
||||
int rc;
|
||||
ssh_session session;
|
||||
ssh_channel channel;
|
||||
char buffer[256];
|
||||
int nbytes;
|
||||
int rc;
|
||||
|
||||
session = connect_ssh("localhost", NULL, 0);
|
||||
if (session == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
channel = channel_new(session);;
|
||||
if (channel == NULL) {
|
||||
ssh_disconnect(session);
|
||||
ssh_finalize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
rc = channel_open_session(channel);
|
||||
if (rc < 0) {
|
||||
channel_close(channel);
|
||||
ssh_disconnect(session);
|
||||
ssh_finalize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
rc = channel_request_exec(channel, "ps aux");
|
||||
if (rc < 0) {
|
||||
channel_close(channel);
|
||||
ssh_disconnect(session);
|
||||
ssh_finalize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
do {
|
||||
if (channel_is_open(channel)) {
|
||||
rc = channel_read(channel, buf, sizeof(buf), 0);
|
||||
if(rc > 0){
|
||||
fwrite(buf,1,rc,stdout);
|
||||
}
|
||||
session = connect_ssh("localhost", NULL, 0);
|
||||
if (session == NULL) {
|
||||
ssh_finalize();
|
||||
return 1;
|
||||
}
|
||||
} while(rc > 0);
|
||||
|
||||
channel_send_eof(channel);
|
||||
channel_close(channel);
|
||||
channel = ssh_channel_new(session);;
|
||||
if (channel == NULL) {
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
ssh_finalize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
ssh_disconnect(session);
|
||||
ssh_finalize();
|
||||
rc = ssh_channel_open_session(channel);
|
||||
if (rc < 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
return 0;
|
||||
rc = ssh_channel_request_exec(channel, "lsof");
|
||||
if (rc < 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
while (nbytes > 0) {
|
||||
if (fwrite(buffer, 1, nbytes, stdout) != (unsigned int) nbytes) {
|
||||
goto failed;
|
||||
}
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
}
|
||||
|
||||
if (nbytes < 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
ssh_channel_send_eof(channel);
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
ssh_finalize();
|
||||
|
||||
return 0;
|
||||
failed:
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
ssh_finalize();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -20,32 +20,47 @@ clients must be made or how a client should react.
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include "examples_common.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define strncasecmp _strnicmp
|
||||
#endif
|
||||
|
||||
int verify_knownhost(ssh_session session){
|
||||
char *hexa;
|
||||
int state;
|
||||
char buf[10];
|
||||
unsigned char *hash = NULL;
|
||||
int hlen;
|
||||
size_t hlen;
|
||||
ssh_key srv_pubkey;
|
||||
int rc;
|
||||
|
||||
state=ssh_is_server_known(session);
|
||||
|
||||
hlen = ssh_get_pubkey_hash(session, &hash);
|
||||
if (hlen < 0) {
|
||||
return -1;
|
||||
rc = ssh_get_publickey(session, &srv_pubkey);
|
||||
if (rc < 0) {
|
||||
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){
|
||||
case SSH_SERVER_KNOWN_OK:
|
||||
break; /* ok */
|
||||
case SSH_SERVER_KNOWN_CHANGED:
|
||||
fprintf(stderr,"Host key for server changed : server's one is now :\n");
|
||||
ssh_print_hexa("Public key hash",hash, hlen);
|
||||
free(hash);
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
fprintf(stderr,"For security reason, connection will be stopped\n");
|
||||
return -1;
|
||||
case SSH_SERVER_FOUND_OTHER:
|
||||
@@ -62,16 +77,23 @@ int verify_knownhost(ssh_session session){
|
||||
hexa = ssh_get_hexa(hash, hlen);
|
||||
fprintf(stderr,"The server is unknown. Do you trust the host key ?\n");
|
||||
fprintf(stderr, "Public key hash: %s\n", hexa);
|
||||
free(hexa);
|
||||
fgets(buf,sizeof(buf),stdin);
|
||||
ssh_string_free_char(hexa);
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
}
|
||||
if(strncasecmp(buf,"yes",3)!=0){
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
|
||||
fgets(buf,sizeof(buf),stdin);
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
}
|
||||
if(strncasecmp(buf,"yes",3)==0){
|
||||
if (ssh_write_knownhost(session) < 0) {
|
||||
free(hash);
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
fprintf(stderr, "error %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
@@ -79,10 +101,10 @@ int verify_knownhost(ssh_session session){
|
||||
|
||||
break;
|
||||
case SSH_SERVER_ERROR:
|
||||
free(hash);
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
fprintf(stderr,"%s",ssh_get_error(session));
|
||||
return -1;
|
||||
}
|
||||
free(hash);
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -22,10 +22,10 @@ program.
|
||||
#include <libssh/libssh.h>
|
||||
#include "examples_common.h"
|
||||
|
||||
char **sources;
|
||||
int nsources;
|
||||
char *destination;
|
||||
int verbosity=0;
|
||||
static char **sources;
|
||||
static int nsources;
|
||||
static char *destination;
|
||||
static int verbosity=0;
|
||||
|
||||
struct location {
|
||||
int is_ssh;
|
||||
@@ -84,9 +84,15 @@ static int opts(int argc, char **argv){
|
||||
}
|
||||
|
||||
static struct location *parse_location(char *loc){
|
||||
struct location *location=malloc(sizeof(struct location));
|
||||
struct location *location;
|
||||
char *ptr;
|
||||
|
||||
location = malloc(sizeof(struct location));
|
||||
if (location == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memset(location, 0, sizeof(struct location));
|
||||
|
||||
location->host=location->user=NULL;
|
||||
ptr=strchr(loc,':');
|
||||
if(ptr != NULL){
|
||||
@@ -123,6 +129,7 @@ static int open_location(struct location *loc, int flag){
|
||||
if(ssh_scp_init(loc->scp)==SSH_ERROR){
|
||||
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
|
||||
ssh_scp_free(loc->scp);
|
||||
loc->scp = NULL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -140,6 +147,7 @@ static int open_location(struct location *loc, int flag){
|
||||
if(ssh_scp_init(loc->scp)==SSH_ERROR){
|
||||
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
|
||||
ssh_scp_free(loc->scp);
|
||||
loc->scp = NULL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -174,15 +182,22 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||
char buffer[16384];
|
||||
int total=0;
|
||||
int mode;
|
||||
char *filename;
|
||||
char *filename = NULL;
|
||||
/* recursive mode doesn't work yet */
|
||||
(void)recursive;
|
||||
/* Get the file name and size*/
|
||||
if(!src->is_ssh){
|
||||
fd=fileno(src->file);
|
||||
fstat(fd,&s);
|
||||
fd = fileno(src->file);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Invalid file pointer, error: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
r = fstat(fd, &s);
|
||||
if (r < 0) {
|
||||
return -1;
|
||||
}
|
||||
size=s.st_size;
|
||||
mode=s.st_mode;
|
||||
mode = s.st_mode & ~S_IFMT;
|
||||
filename=ssh_basename(src->path);
|
||||
} else {
|
||||
size=0;
|
||||
@@ -201,17 +216,20 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||
}
|
||||
if(r==SSH_ERROR){
|
||||
fprintf(stderr,"Error: %s\n",ssh_get_error(src->session));
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
} while(r != SSH_SCP_REQUEST_NEWFILE);
|
||||
}
|
||||
|
||||
if(dest->is_ssh){
|
||||
r=ssh_scp_push_file(dest->scp,src->path,size,0644);
|
||||
r=ssh_scp_push_file(dest->scp,src->path, size, mode);
|
||||
// snprintf(buffer,sizeof(buffer),"C0644 %d %s\n",size,src->path);
|
||||
if(r==SSH_ERROR){
|
||||
fprintf(stderr,"error: %s\n",ssh_get_error(dest->session));
|
||||
ssh_string_free_char(filename);
|
||||
ssh_scp_free(dest->scp);
|
||||
dest->scp = NULL;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
@@ -221,6 +239,7 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||
fprintf(stderr,"Cannot open %s for writing: %s\n",filename,strerror(errno));
|
||||
if(src->is_ssh)
|
||||
ssh_scp_deny_request(src->scp,"Cannot open local file");
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -233,6 +252,7 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||
r=ssh_scp_read(src->scp,buffer,sizeof(buffer));
|
||||
if(r==SSH_ERROR){
|
||||
fprintf(stderr,"Error reading scp: %s\n",ssh_get_error(src->session));
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
if(r==0)
|
||||
@@ -243,6 +263,7 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||
break;
|
||||
if(r<0){
|
||||
fprintf(stderr,"Error reading file: %s\n",strerror(errno));
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -252,18 +273,21 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||
fprintf(stderr,"Error writing in scp: %s\n",ssh_get_error(dest->session));
|
||||
ssh_scp_free(dest->scp);
|
||||
dest->scp=NULL;
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
w=fwrite(buffer,r,1,dest->file);
|
||||
if(w<=0){
|
||||
fprintf(stderr,"Error writing in local file: %s\n",strerror(errno));
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
total+=r;
|
||||
|
||||
} while(total < size);
|
||||
ssh_string_free_char(filename);
|
||||
printf("wrote %d bytes\n",total);
|
||||
return 0;
|
||||
}
|
||||
@@ -286,7 +310,7 @@ int main(int argc, char **argv){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(dest->is_ssh){
|
||||
if (dest->is_ssh && dest->scp != NULL) {
|
||||
r=ssh_scp_close(dest->scp);
|
||||
if(r == SSH_ERROR){
|
||||
fprintf(stderr,"Error closing scp: %s\n",ssh_get_error(dest->session));
|
||||
|
||||
33
examples/libsshpp.cpp
Normal file
33
examples/libsshpp.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright 2010 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.
|
||||
*/
|
||||
|
||||
/* This file demonstrates the use of the C++ wrapper to libssh */
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <libssh/libsshpp.hpp>
|
||||
|
||||
int main(int argc, const char **argv){
|
||||
ssh::Session session;
|
||||
try {
|
||||
if(argc>1)
|
||||
session.setOption(SSH_OPTIONS_HOST,argv[1]);
|
||||
else
|
||||
session.setOption(SSH_OPTIONS_HOST,"localhost");
|
||||
session.connect();
|
||||
session.userauthPublickeyAuto();
|
||||
session.disconnect();
|
||||
} catch (ssh::SshException e){
|
||||
std::cout << "Error during connection : ";
|
||||
std::cout << e.getError() << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
41
examples/libsshpp_noexcept.cpp
Normal file
41
examples/libsshpp_noexcept.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Copyright 2010 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.
|
||||
*/
|
||||
|
||||
/* This file demonstrates the use of the C++ wrapper to libssh
|
||||
* specifically, without C++ exceptions
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#define SSH_NO_CPP_EXCEPTIONS
|
||||
#include <libssh/libsshpp.hpp>
|
||||
|
||||
int main(int argc, const char **argv){
|
||||
ssh::Session session,s2;
|
||||
int err;
|
||||
if(argc>1)
|
||||
err=session.setOption(SSH_OPTIONS_HOST,argv[1]);
|
||||
else
|
||||
err=session.setOption(SSH_OPTIONS_HOST,"localhost");
|
||||
if(err==SSH_ERROR)
|
||||
goto error;
|
||||
err=session.connect();
|
||||
if(err==SSH_ERROR)
|
||||
goto error;
|
||||
err=session.userauthPublickeyAuto();
|
||||
if(err==SSH_ERROR)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
error:
|
||||
std::cout << "Error during connection : ";
|
||||
std::cout << session.getError() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
347
examples/proxy.c
Normal file
347
examples/proxy.c
Normal file
@@ -0,0 +1,347 @@
|
||||
/* This is a sample implementation of a libssh based SSH proxy */
|
||||
/*
|
||||
Copyright 2003-2013 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>
|
||||
|
||||
#define USER "myuser"
|
||||
#define PASSWORD "mypassword"
|
||||
|
||||
static int authenticated=0;
|
||||
static int tries = 0;
|
||||
static int error = 0;
|
||||
static ssh_channel chan=NULL;
|
||||
static char *username;
|
||||
static ssh_gssapi_creds client_creds = NULL;
|
||||
|
||||
static int auth_password(ssh_session session, const char *user,
|
||||
const char *password, void *userdata){
|
||||
|
||||
(void)userdata;
|
||||
|
||||
printf("Authenticating user %s pwd %s\n",user, password);
|
||||
if(strcmp(user,USER) == 0 && strcmp(password, PASSWORD) == 0){
|
||||
authenticated = 1;
|
||||
printf("Authenticated\n");
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
if (tries >= 3){
|
||||
printf("Too many authentication tries\n");
|
||||
ssh_disconnect(session);
|
||||
error = 1;
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
tries++;
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
static int auth_gssapi_mic(ssh_session session, const char *user, const char *principal, void *userdata){
|
||||
(void)userdata;
|
||||
client_creds = ssh_gssapi_get_creds(session);
|
||||
printf("Authenticating user %s with gssapi principal %s\n",user, principal);
|
||||
if (client_creds != NULL)
|
||||
printf("Received some gssapi credentials\n");
|
||||
else
|
||||
printf("Not received any forwardable creds\n");
|
||||
printf("authenticated\n");
|
||||
authenticated = 1;
|
||||
username = strdup(principal);
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
|
||||
static int pty_request(ssh_session session, ssh_channel channel, const char *term,
|
||||
int x,int y, int px, int py, void *userdata){
|
||||
(void) session;
|
||||
(void) channel;
|
||||
(void) term;
|
||||
(void) x;
|
||||
(void) y;
|
||||
(void) px;
|
||||
(void) py;
|
||||
(void) userdata;
|
||||
printf("Allocated terminal\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int shell_request(ssh_session session, ssh_channel channel, void *userdata){
|
||||
(void)session;
|
||||
(void)channel;
|
||||
(void)userdata;
|
||||
printf("Allocated shell\n");
|
||||
return 0;
|
||||
}
|
||||
struct ssh_channel_callbacks_struct channel_cb = {
|
||||
.channel_pty_request_function = pty_request,
|
||||
.channel_shell_request_function = shell_request
|
||||
};
|
||||
|
||||
static ssh_channel new_session_channel(ssh_session session, void *userdata){
|
||||
(void) session;
|
||||
(void) userdata;
|
||||
if(chan != NULL)
|
||||
return NULL;
|
||||
printf("Allocated session channel\n");
|
||||
chan = ssh_channel_new(session);
|
||||
ssh_callbacks_init(&channel_cb);
|
||||
ssh_set_channel_callbacks(chan, &channel_cb);
|
||||
return chan;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
const char *argp_program_version = "libssh proxy 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_event mainloop;
|
||||
ssh_session client_session;
|
||||
|
||||
struct ssh_server_callbacks_struct cb = {
|
||||
.userdata = NULL,
|
||||
.auth_password_function = auth_password,
|
||||
.auth_gssapi_mic_function = auth_gssapi_mic,
|
||||
.channel_open_request_session_function = new_session_channel
|
||||
};
|
||||
|
||||
char buf[2048];
|
||||
char host[128]="";
|
||||
char *ptr;
|
||||
int i,r, rc;
|
||||
|
||||
sshbind=ssh_bind_new();
|
||||
session=ssh_new();
|
||||
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, "sshd_rsa");
|
||||
|
||||
#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
|
||||
|
||||
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;
|
||||
}
|
||||
ssh_callbacks_init(&cb);
|
||||
ssh_set_server_callbacks(session, &cb);
|
||||
|
||||
if (ssh_handle_key_exchange(session)) {
|
||||
printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session));
|
||||
return 1;
|
||||
}
|
||||
ssh_set_auth_methods(session,SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_GSSAPI_MIC);
|
||||
mainloop = ssh_event_new();
|
||||
ssh_event_add_session(mainloop, session);
|
||||
|
||||
while (!(authenticated && chan != NULL)){
|
||||
if(error)
|
||||
break;
|
||||
r = ssh_event_dopoll(mainloop, -1);
|
||||
if (r == SSH_ERROR){
|
||||
printf("Error : %s\n",ssh_get_error(session));
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if(error){
|
||||
printf("Error, exiting loop\n");
|
||||
return 1;
|
||||
} else
|
||||
printf("Authenticated and got a channel\n");
|
||||
if (!client_creds){
|
||||
snprintf(buf,sizeof(buf), "Sorry, but you do not have forwardable tickets. Try again with -K\r\n");
|
||||
ssh_channel_write(chan,buf,strlen(buf));
|
||||
printf("%s",buf);
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
snprintf(buf,sizeof(buf), "Hello %s, welcome to the Sample SSH proxy.\r\nPlease select your destination: ", username);
|
||||
ssh_channel_write(chan, buf, strlen(buf));
|
||||
do{
|
||||
i=ssh_channel_read(chan,buf, 2048, 0);
|
||||
if(i>0) {
|
||||
ssh_channel_write(chan, buf, i);
|
||||
if(strlen(host) + i < sizeof(host)){
|
||||
strncat(host, buf, i);
|
||||
}
|
||||
if (strchr(host, '\x0d')) {
|
||||
*strchr(host, '\x0d')='\0';
|
||||
ssh_channel_write(chan, "\n", 1);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
printf ("Error: %s\n", ssh_get_error(session) );
|
||||
return 1;
|
||||
}
|
||||
} while (i>0);
|
||||
snprintf(buf,sizeof(buf),"Trying to connect to \"%s\"\r\n", host);
|
||||
ssh_channel_write(chan, buf, strlen(buf));
|
||||
printf("%s",buf);
|
||||
|
||||
client_session = ssh_new();
|
||||
|
||||
/* ssh servers expect username without realm */
|
||||
ptr = strchr(username,'@');
|
||||
if(ptr)
|
||||
*ptr= '\0';
|
||||
ssh_options_set(client_session, SSH_OPTIONS_HOST, host);
|
||||
ssh_options_set(client_session, SSH_OPTIONS_USER, username);
|
||||
ssh_gssapi_set_creds(client_session, client_creds);
|
||||
rc = ssh_connect(client_session);
|
||||
if (rc != SSH_OK){
|
||||
printf("Error connecting to %s: %s", host, ssh_get_error(client_session));
|
||||
return 1;
|
||||
}
|
||||
rc = ssh_userauth_none(client_session, NULL);
|
||||
if(rc == SSH_AUTH_SUCCESS){
|
||||
printf("Authenticated using method none\n");
|
||||
} else {
|
||||
rc = ssh_userauth_gssapi(client_session);
|
||||
if(rc != SSH_AUTH_SUCCESS){
|
||||
printf("GSSAPI Authentication failed: %s\n",ssh_get_error(client_session));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
snprintf(buf,sizeof(buf), "Authentication success\r\n");
|
||||
printf("%s",buf);
|
||||
ssh_channel_write(chan,buf,strlen(buf));
|
||||
ssh_disconnect(client_session);
|
||||
ssh_disconnect(session);
|
||||
ssh_bind_free(sshbind);
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -14,64 +14,50 @@ clients must be made or how a client should react.
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifdef HAVE_TERMIOS_H
|
||||
#include <termios.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_PTY_H
|
||||
#include <pty.h>
|
||||
#endif
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <libssh/callbacks.h>
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/sftp.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "examples_common.h"
|
||||
#define MAXCMD 10
|
||||
char *host;
|
||||
char *user;
|
||||
char *cmds[MAXCMD];
|
||||
struct termios terminal;
|
||||
|
||||
#ifdef WITH_PCAP
|
||||
/* this header file won't be necessary in the future */
|
||||
#include <libssh/pcap.h>
|
||||
char *pcap_file=NULL;
|
||||
#endif
|
||||
static char *host;
|
||||
static char *user;
|
||||
static char *cmds[MAXCMD];
|
||||
static struct termios terminal;
|
||||
|
||||
char *proxycommand;
|
||||
static char *pcap_file=NULL;
|
||||
|
||||
static char *proxycommand;
|
||||
|
||||
static int auth_callback(const char *prompt, char *buf, size_t len,
|
||||
int echo, int verify, void *userdata) {
|
||||
char *answer = NULL;
|
||||
char *ptr;
|
||||
(void) verify;
|
||||
(void) userdata;
|
||||
|
||||
(void) verify;
|
||||
(void) userdata;
|
||||
|
||||
if (echo) {
|
||||
while ((answer = fgets(buf, len, stdin)) == NULL);
|
||||
if ((ptr = strchr(buf, '\n'))) {
|
||||
ptr = '\0';
|
||||
}
|
||||
} else {
|
||||
answer = getpass(prompt);
|
||||
}
|
||||
|
||||
if (answer == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(buf, answer, len);
|
||||
|
||||
return 0;
|
||||
return ssh_getpass(prompt, buf, len, echo, verify);
|
||||
}
|
||||
|
||||
struct ssh_callbacks_struct cb = {
|
||||
@@ -81,9 +67,12 @@ struct ssh_callbacks_struct cb = {
|
||||
|
||||
static void add_cmd(char *cmd){
|
||||
int n;
|
||||
for(n=0;cmds[n] && (n<MAXCMD);n++);
|
||||
if(n==MAXCMD)
|
||||
|
||||
for (n = 0; (n < MAXCMD) && cmds[n] != NULL; n++);
|
||||
|
||||
if (n == MAXCMD) {
|
||||
return;
|
||||
}
|
||||
cmds[n]=strdup(cmd);
|
||||
}
|
||||
|
||||
@@ -113,17 +102,15 @@ static int opts(int argc, char **argv){
|
||||
/* insert your own arguments here */
|
||||
while((i=getopt(argc,argv,"T:P:"))!=-1){
|
||||
switch(i){
|
||||
#ifdef WITH_PCAP
|
||||
case 'P':
|
||||
pcap_file=optarg;
|
||||
break;
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
case 'T':
|
||||
proxycommand=optarg;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
default:
|
||||
fprintf(stderr,"unknown option %c\n",optopt);
|
||||
usage();
|
||||
}
|
||||
@@ -179,7 +166,7 @@ static void setsignal(void){
|
||||
static void sizechanged(void){
|
||||
struct winsize win = { 0, 0, 0, 0 };
|
||||
ioctl(1, TIOCGWINSZ, &win);
|
||||
channel_change_pty_size(chan,win.ws_col, win.ws_row);
|
||||
ssh_channel_change_pty_size(chan,win.ws_col, win.ws_row);
|
||||
// printf("Changed pty size\n");
|
||||
setsignal();
|
||||
}
|
||||
@@ -202,7 +189,7 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
fd_set fds;
|
||||
struct timeval timeout;
|
||||
char buffer[4096];
|
||||
ssh_buffer readbuf=buffer_new();
|
||||
ssh_buffer readbuf=ssh_buffer_new();
|
||||
ssh_channel channels[2];
|
||||
int lus;
|
||||
int eof=0;
|
||||
@@ -230,10 +217,10 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
if(FD_ISSET(0,&fds)){
|
||||
lus=read(0,buffer,sizeof(buffer));
|
||||
if(lus)
|
||||
channel_write(channel,buffer,lus);
|
||||
ssh_channel_write(channel,buffer,lus);
|
||||
else {
|
||||
eof=1;
|
||||
channel_send_eof(channel);
|
||||
ssh_channel_send_eof(channel);
|
||||
}
|
||||
}
|
||||
if(FD_ISSET(ssh_get_fd(session),&fds)){
|
||||
@@ -241,22 +228,20 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
}
|
||||
channels[0]=channel; // set the first channel we want to read from
|
||||
channels[1]=NULL;
|
||||
ret=channel_select(channels,NULL,NULL,NULL); // no specific timeout - just poll
|
||||
ret=ssh_channel_select(channels,NULL,NULL,NULL); // no specific timeout - just poll
|
||||
if(signal_delayed)
|
||||
sizechanged();
|
||||
} while (ret==EINTR || ret==SSH_EINTR);
|
||||
|
||||
// we already looked for input from stdin. Now, we are looking for input from the channel
|
||||
|
||||
if(channel && channel_is_closed(channel)){
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
|
||||
|
||||
channel_free(channel);
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_channel_free(channel);
|
||||
channel=NULL;
|
||||
channels[0]=NULL;
|
||||
}
|
||||
if(channels[0]){
|
||||
while(channel && channel_is_open(channel) && channel_poll(channel,0)){
|
||||
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,0)>0){
|
||||
lus=channel_read_buffer(channel,readbuf,0,0);
|
||||
if(lus==-1){
|
||||
fprintf(stderr, "Error reading channel: %s\n",
|
||||
@@ -264,15 +249,15 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
|
||||
|
||||
channel_free(channel);
|
||||
ssh_channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else
|
||||
write(1,buffer_get(readbuf),lus);
|
||||
if (write(1,ssh_buffer_get_begin(readbuf),lus) < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
while(channel && channel_is_open(channel) && channel_poll(channel,1)){ /* stderr */
|
||||
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,1)>0){ /* stderr */
|
||||
lus=channel_read_buffer(channel,readbuf,0,1);
|
||||
if(lus==-1){
|
||||
fprintf(stderr, "Error reading channel: %s\n",
|
||||
@@ -280,20 +265,21 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
|
||||
channel_free(channel);
|
||||
ssh_channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else
|
||||
write(2,buffer_get(readbuf),lus);
|
||||
if (write(2,ssh_buffer_get_begin(readbuf),lus) < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(channel && channel_is_closed(channel)){
|
||||
channel_free(channel);
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_channel_free(channel);
|
||||
channel=NULL;
|
||||
}
|
||||
}
|
||||
buffer_free(readbuf);
|
||||
ssh_buffer_free(readbuf);
|
||||
}
|
||||
#else /* CHANNEL_SELECT */
|
||||
|
||||
@@ -308,16 +294,26 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
int lus;
|
||||
int eof=0;
|
||||
int maxfd;
|
||||
unsigned int r;
|
||||
int ret;
|
||||
while(channel){
|
||||
do{
|
||||
int fd;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
if(!eof)
|
||||
FD_SET(0,&fds);
|
||||
timeout.tv_sec=30;
|
||||
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[1]=NULL;
|
||||
ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout);
|
||||
@@ -328,54 +324,53 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
if(FD_ISSET(0,&fds)){
|
||||
lus=read(0,buffer,sizeof(buffer));
|
||||
if(lus)
|
||||
channel_write(channel,buffer,lus);
|
||||
ssh_channel_write(channel,buffer,lus);
|
||||
else {
|
||||
eof=1;
|
||||
channel_send_eof(channel);
|
||||
ssh_channel_send_eof(channel);
|
||||
}
|
||||
}
|
||||
if(channel && channel_is_closed(channel)){
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
|
||||
|
||||
channel_free(channel);
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_channel_free(channel);
|
||||
channel=NULL;
|
||||
channels[0]=NULL;
|
||||
}
|
||||
if(outchannels[0]){
|
||||
while(channel && channel_is_open(channel) && channel_poll(channel,0)){
|
||||
lus=channel_read(channel,buffer,sizeof(buffer),0);
|
||||
while(channel && ssh_channel_is_open(channel) && (r = ssh_channel_poll(channel,0))!=0){
|
||||
lus=ssh_channel_read(channel,buffer,sizeof(buffer) > r ? r : sizeof(buffer),0);
|
||||
if(lus==-1){
|
||||
fprintf(stderr, "Error reading channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
|
||||
|
||||
channel_free(channel);
|
||||
ssh_channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else
|
||||
write(1,buffer,lus);
|
||||
if (write(1,buffer,lus) < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
while(channel && channel_is_open(channel) && channel_poll(channel,1)){ /* stderr */
|
||||
lus=channel_read(channel,buffer,sizeof(buffer),1);
|
||||
while(channel && ssh_channel_is_open(channel) && (r = ssh_channel_poll(channel,1))!=0){ /* stderr */
|
||||
lus=ssh_channel_read(channel,buffer,sizeof(buffer) > r ? r : sizeof(buffer),1);
|
||||
if(lus==-1){
|
||||
fprintf(stderr, "Error reading channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
|
||||
channel_free(channel);
|
||||
ssh_channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else
|
||||
write(2,buffer,lus);
|
||||
if (write(2,buffer,lus) < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(channel && channel_is_closed(channel)){
|
||||
channel_free(channel);
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_channel_free(channel);
|
||||
channel=NULL;
|
||||
}
|
||||
} while (ret==EINTR || ret==SSH_EINTR);
|
||||
@@ -389,21 +384,21 @@ static void shell(ssh_session session){
|
||||
ssh_channel channel;
|
||||
struct termios terminal_local;
|
||||
int interactive=isatty(0);
|
||||
channel = channel_new(session);
|
||||
channel = ssh_channel_new(session);
|
||||
if(interactive){
|
||||
tcgetattr(0,&terminal_local);
|
||||
memcpy(&terminal,&terminal_local,sizeof(struct termios));
|
||||
}
|
||||
if(channel_open_session(channel)){
|
||||
if(ssh_channel_open_session(channel)){
|
||||
printf("error opening channel : %s\n",ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
chan=channel;
|
||||
if(interactive){
|
||||
channel_request_pty(channel);
|
||||
ssh_channel_request_pty(channel);
|
||||
sizechanged();
|
||||
}
|
||||
if(channel_request_shell(channel)){
|
||||
if(ssh_channel_request_shell(channel)){
|
||||
printf("Requesting shell : %s\n",ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
@@ -422,11 +417,14 @@ static void batch_shell(ssh_session session){
|
||||
ssh_channel channel;
|
||||
char buffer[1024];
|
||||
int i,s=0;
|
||||
for(i=0;i<MAXCMD && cmds[i];++i)
|
||||
for(i=0;i<MAXCMD && cmds[i];++i) {
|
||||
s+=snprintf(buffer+s,sizeof(buffer)-s,"%s ",cmds[i]);
|
||||
channel=channel_new(session);
|
||||
channel_open_session(channel);
|
||||
if(channel_request_exec(channel,buffer)){
|
||||
free(cmds[i]);
|
||||
cmds[i] = NULL;
|
||||
}
|
||||
channel=ssh_channel_new(session);
|
||||
ssh_channel_open_session(channel);
|
||||
if(ssh_channel_request_exec(channel,buffer)){
|
||||
printf("error executing \"%s\" : %s\n",buffer,ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
@@ -465,7 +463,6 @@ static int client(ssh_session session){
|
||||
if(auth != SSH_AUTH_SUCCESS){
|
||||
return -1;
|
||||
}
|
||||
ssh_log(session, SSH_LOG_FUNCTIONS, "Authentication success");
|
||||
if(!cmds[0])
|
||||
shell(session);
|
||||
else
|
||||
@@ -473,13 +470,14 @@ static int client(ssh_session session){
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WITH_PCAP
|
||||
ssh_pcap_file pcap;
|
||||
void set_pcap(ssh_session session);
|
||||
void set_pcap(ssh_session session){
|
||||
if(!pcap_file)
|
||||
return;
|
||||
pcap=ssh_pcap_file_new();
|
||||
if(!pcap)
|
||||
return;
|
||||
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
|
||||
printf("Error opening pcap file\n");
|
||||
ssh_pcap_file_free(pcap);
|
||||
@@ -491,10 +489,10 @@ void set_pcap(ssh_session session){
|
||||
|
||||
void cleanup_pcap(void);
|
||||
void cleanup_pcap(){
|
||||
ssh_pcap_file_free(pcap);
|
||||
if(pcap)
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap=NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
@@ -511,16 +509,13 @@ int main(int argc, char **argv){
|
||||
}
|
||||
opts(argc,argv);
|
||||
signal(SIGTERM, do_exit);
|
||||
#ifdef WITH_PCAP
|
||||
|
||||
set_pcap(session);
|
||||
#endif
|
||||
client(session);
|
||||
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
#ifdef WITH_PCAP
|
||||
cleanup_pcap();
|
||||
#endif
|
||||
|
||||
ssh_finalize();
|
||||
|
||||
|
||||
@@ -15,11 +15,13 @@ clients must be made or how a client should react.
|
||||
|
||||
#include <sys/statvfs.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/sftp.h>
|
||||
@@ -27,9 +29,10 @@ clients must be made or how a client should react.
|
||||
#include "examples_common.h"
|
||||
#ifdef WITH_SFTP
|
||||
|
||||
int verbosity;
|
||||
char *destination;
|
||||
static int verbosity;
|
||||
static char *destination;
|
||||
|
||||
#define DATALEN 65536
|
||||
static void do_sftp(ssh_session session){
|
||||
sftp_session sftp=sftp_new(session);
|
||||
sftp_dir dir;
|
||||
@@ -40,7 +43,7 @@ static void do_sftp(ssh_session session){
|
||||
sftp_file to;
|
||||
int len=1;
|
||||
unsigned int i;
|
||||
char data[8000]={0};
|
||||
char data[DATALEN]={0};
|
||||
char *lnk;
|
||||
|
||||
unsigned int count;
|
||||
@@ -202,9 +205,9 @@ static void do_sftp(ssh_session session){
|
||||
printf("fichiers ferm\n");
|
||||
to=sftp_open(sftp,"/tmp/grosfichier",O_WRONLY|O_CREAT, 0644);
|
||||
for(i=0;i<1000;++i){
|
||||
len=sftp_write(to,data,8000);
|
||||
len=sftp_write(to,data,DATALEN);
|
||||
printf("wrote %d bytes\n",len);
|
||||
if(len != 8000){
|
||||
if(len != DATALEN){
|
||||
printf("chunk %d : %d (%s)\n",i,len,ssh_get_error(session));
|
||||
}
|
||||
}
|
||||
|
||||
306
examples/samplesshd-cb.c
Normal file
306
examples/samplesshd-cb.c
Normal file
@@ -0,0 +1,306 @@
|
||||
/* 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>
|
||||
#include <libssh/callbacks.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
|
||||
|
||||
#define USER "myuser"
|
||||
#define PASSWORD "mypassword"
|
||||
|
||||
static int authenticated=0;
|
||||
static int tries = 0;
|
||||
static int error = 0;
|
||||
static ssh_channel chan=NULL;
|
||||
|
||||
static int auth_password(ssh_session session, const char *user,
|
||||
const char *password, void *userdata){
|
||||
(void)userdata;
|
||||
printf("Authenticating user %s pwd %s\n",user, password);
|
||||
if(strcmp(user,USER) == 0 && strcmp(password, PASSWORD) == 0){
|
||||
authenticated = 1;
|
||||
printf("Authenticated\n");
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
if (tries >= 3){
|
||||
printf("Too many authentication tries\n");
|
||||
ssh_disconnect(session);
|
||||
error = 1;
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
tries++;
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
static int auth_gssapi_mic(ssh_session session, const char *user, const char *principal, void *userdata){
|
||||
ssh_gssapi_creds creds = ssh_gssapi_get_creds(session);
|
||||
(void)userdata;
|
||||
printf("Authenticating user %s with gssapi principal %s\n",user, principal);
|
||||
if (creds != NULL)
|
||||
printf("Received some gssapi credentials\n");
|
||||
else
|
||||
printf("Not received any forwardable creds\n");
|
||||
printf("authenticated\n");
|
||||
authenticated = 1;
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
|
||||
static int pty_request(ssh_session session, ssh_channel channel, const char *term,
|
||||
int x,int y, int px, int py, void *userdata){
|
||||
(void) session;
|
||||
(void) channel;
|
||||
(void) term;
|
||||
(void) x;
|
||||
(void) y;
|
||||
(void) px;
|
||||
(void) py;
|
||||
(void) userdata;
|
||||
printf("Allocated terminal\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int shell_request(ssh_session session, ssh_channel channel, void *userdata){
|
||||
(void)session;
|
||||
(void)channel;
|
||||
(void)userdata;
|
||||
printf("Allocated shell\n");
|
||||
return 0;
|
||||
}
|
||||
struct ssh_channel_callbacks_struct channel_cb = {
|
||||
.channel_pty_request_function = pty_request,
|
||||
.channel_shell_request_function = shell_request
|
||||
};
|
||||
|
||||
static ssh_channel new_session_channel(ssh_session session, void *userdata){
|
||||
(void) session;
|
||||
(void) userdata;
|
||||
if(chan != NULL)
|
||||
return NULL;
|
||||
printf("Allocated session channel\n");
|
||||
chan = ssh_channel_new(session);
|
||||
ssh_callbacks_init(&channel_cb);
|
||||
ssh_set_channel_callbacks(chan, &channel_cb);
|
||||
return chan;
|
||||
}
|
||||
|
||||
|
||||
#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_event mainloop;
|
||||
struct ssh_server_callbacks_struct cb = {
|
||||
.userdata = NULL,
|
||||
.auth_password_function = auth_password,
|
||||
.auth_gssapi_mic_function = auth_gssapi_mic,
|
||||
.channel_open_request_session_function = new_session_channel
|
||||
};
|
||||
|
||||
char buf[2048];
|
||||
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
|
||||
|
||||
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;
|
||||
}
|
||||
ssh_callbacks_init(&cb);
|
||||
ssh_set_server_callbacks(session, &cb);
|
||||
|
||||
if (ssh_handle_key_exchange(session)) {
|
||||
printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session));
|
||||
return 1;
|
||||
}
|
||||
ssh_set_auth_methods(session,SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_GSSAPI_MIC);
|
||||
mainloop = ssh_event_new();
|
||||
ssh_event_add_session(mainloop, session);
|
||||
|
||||
while (!(authenticated && chan != NULL)){
|
||||
if(error)
|
||||
break;
|
||||
r = ssh_event_dopoll(mainloop, -1);
|
||||
if (r == SSH_ERROR){
|
||||
printf("Error : %s\n",ssh_get_error(session));
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if(error){
|
||||
printf("Error, exiting loop\n");
|
||||
} else
|
||||
printf("Authenticated and got a channel\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);
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
413
examples/samplesshd-kbdint.c
Normal file
413
examples/samplesshd-kbdint.c
Normal file
@@ -0,0 +1,413 @@
|
||||
/* 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>
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
#include <argp.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.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
|
||||
|
||||
static int port = 22;
|
||||
|
||||
#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, 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";
|
||||
|
||||
/* 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 const char *name;
|
||||
static const char *instruction;
|
||||
static const char *prompts[2];
|
||||
static char echo[] = { 1, 0 };
|
||||
|
||||
static int kbdint_check_response(ssh_session session) {
|
||||
int count;
|
||||
|
||||
count = ssh_userauth_kbdint_getnanswers(session);
|
||||
if(count != 2) {
|
||||
instruction = "Something weird happened :(";
|
||||
return 0;
|
||||
}
|
||||
if(strcasecmp("Arthur Dent",
|
||||
ssh_userauth_kbdint_getanswer(session, 0)) != 0) {
|
||||
instruction = "OK, this is not YOUR name, "
|
||||
"but it's a reference to the HGTG...";
|
||||
prompts[0] = "The main character's full name: ";
|
||||
return 0;
|
||||
}
|
||||
if(strcmp("42", ssh_userauth_kbdint_getanswer(session, 1)) != 0) {
|
||||
instruction = "Make an effort !!! What is the Answer to the Ultimate "
|
||||
"Question of Life, the Universe, and Everything ?";
|
||||
prompts[1] = "Answer to the Ultimate Question of Life, the Universe, "
|
||||
"and Everything: ";
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int authenticate(ssh_session session) {
|
||||
ssh_message message;
|
||||
|
||||
name = "\n\nKeyboard-Interactive Fancy Authentication\n";
|
||||
instruction = "Please enter your real name and your password";
|
||||
prompts[0] = "Real name: ";
|
||||
prompts[1] = "Password: ";
|
||||
|
||||
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_INTERACTIVE:
|
||||
if(!ssh_message_auth_kbdint_is_response(message)) {
|
||||
printf("User %s wants to auth with kbdint\n",
|
||||
ssh_message_auth_user(message));
|
||||
ssh_message_auth_interactive_request(message, name,
|
||||
instruction, 2, prompts, echo);
|
||||
} else {
|
||||
if(kbdint_check_response(session)) {
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
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 shell=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;
|
||||
}
|
||||
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 &&
|
||||
ssh_message_subtype(message) == SSH_CHANNEL_REQUEST_SHELL) {
|
||||
shell = 1;
|
||||
ssh_message_channel_request_reply_success(message);
|
||||
ssh_message_free(message);
|
||||
break;
|
||||
}
|
||||
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");
|
||||
do{
|
||||
i=ssh_channel_read(chan,buf, 2048, 0);
|
||||
if(i>0) {
|
||||
if(*buf == '' || *buf == '')
|
||||
break;
|
||||
if(i == 1 && *buf == '\r')
|
||||
ssh_channel_write(chan, "\r\n", 2);
|
||||
else
|
||||
ssh_channel_write(chan, buf, i);
|
||||
if (write(1,buf,i) < 0) {
|
||||
printf("error writing to buffer\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} while (i>0);
|
||||
ssh_channel_close(chan);
|
||||
ssh_disconnect(session);
|
||||
ssh_bind_free(sshbind);
|
||||
#ifdef WITH_PCAP
|
||||
cleanup_pcap();
|
||||
#endif
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,269 +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>
|
||||
#include <unistd.h>
|
||||
#ifndef KEYS_FOLDER
|
||||
#ifdef _WIN32
|
||||
#define KEYS_FOLDER
|
||||
#else
|
||||
#define KEYS_FOLDER "/etc/ssh/"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int auth_password(char *user, 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, 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);
|
||||
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;
|
||||
ssh_buffer buf;
|
||||
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);
|
||||
#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_accept(session)){
|
||||
printf("ssh_accept: %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){
|
||||
// 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");
|
||||
buf=buffer_new();
|
||||
do{
|
||||
i=channel_read_buffer(chan,buf,0,0);
|
||||
if(i>0)
|
||||
write(1,buffer_get(buf),buffer_get_len(buf));
|
||||
} while (i>0);
|
||||
buffer_free(buf);
|
||||
ssh_disconnect(session);
|
||||
ssh_bind_free(sshbind);
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -56,26 +56,44 @@ static int opts(int argc, char **argv){
|
||||
}
|
||||
|
||||
static void create_files(ssh_session session){
|
||||
ssh_channel channel=channel_new(session);
|
||||
ssh_channel channel=ssh_channel_new(session);
|
||||
char buffer[1];
|
||||
int rc;
|
||||
|
||||
if(channel == NULL){
|
||||
fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if(channel_open_session(channel) != SSH_OK){
|
||||
if(ssh_channel_open_session(channel) != SSH_OK){
|
||||
fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session));
|
||||
ssh_channel_free(channel);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if(channel_request_exec(channel,createcommand) != SSH_OK){
|
||||
if(ssh_channel_request_exec(channel,createcommand) != SSH_OK){
|
||||
fprintf(stderr,"Error executing command: %s\n",ssh_get_error(session));
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
while(!channel_is_eof(channel)){
|
||||
channel_read(channel,buffer,1,1);
|
||||
write(1,buffer,1);
|
||||
while(!ssh_channel_is_eof(channel)){
|
||||
rc = ssh_channel_read(channel,buffer,1,1);
|
||||
if (rc != 1) {
|
||||
fprintf(stderr, "Error reading from channel\n");
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = write(1, buffer, 1);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return;
|
||||
}
|
||||
}
|
||||
channel_close(channel);
|
||||
channel_free(channel);
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
}
|
||||
|
||||
|
||||
@@ -88,6 +106,7 @@ static int fetch_files(ssh_session session){
|
||||
ssh_scp scp=ssh_scp_new(session, SSH_SCP_READ | SSH_SCP_RECURSIVE, "/tmp/libssh_tests/*");
|
||||
if(ssh_scp_init(scp) != SSH_OK){
|
||||
fprintf(stderr,"error initializing scp: %s\n",ssh_get_error(session));
|
||||
ssh_scp_free(scp);
|
||||
return -1;
|
||||
}
|
||||
printf("Trying to download 3 files (a,b,d) and 1 directory (c)\n");
|
||||
@@ -105,12 +124,16 @@ static int fetch_files(ssh_session session){
|
||||
r=ssh_scp_read(scp,buffer,sizeof(buffer));
|
||||
if(r==SSH_ERROR){
|
||||
fprintf(stderr,"Error reading scp: %s\n",ssh_get_error(session));
|
||||
ssh_scp_close(scp);
|
||||
ssh_scp_free(scp);
|
||||
return -1;
|
||||
}
|
||||
printf("done\n");
|
||||
break;
|
||||
case SSH_ERROR:
|
||||
fprintf(stderr,"Error: %s\n",ssh_get_error(session));
|
||||
ssh_scp_close(scp);
|
||||
ssh_scp_free(scp);
|
||||
return -1;
|
||||
case SSH_SCP_REQUEST_WARNING:
|
||||
fprintf(stderr,"Warning: %s\n",ssh_scp_request_get_warning(scp));
|
||||
@@ -131,6 +154,8 @@ static int fetch_files(ssh_session session){
|
||||
}
|
||||
} while (1);
|
||||
end:
|
||||
ssh_scp_close(scp);
|
||||
ssh_scp_free(scp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -144,6 +169,7 @@ int main(int argc, char **argv){
|
||||
create_files(session);
|
||||
fetch_files(session);
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
64
examples/senddata.c
Normal file
64
examples/senddata.c
Normal file
@@ -0,0 +1,64 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include "examples_common.h"
|
||||
|
||||
#define LIMIT 0x100000000
|
||||
|
||||
int main(void) {
|
||||
ssh_session session;
|
||||
ssh_channel channel;
|
||||
char buffer[1024*1024];
|
||||
int rc;
|
||||
uint64_t total=0;
|
||||
uint64_t lastshown=4096;
|
||||
session = connect_ssh("localhost", NULL, 0);
|
||||
if (session == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
channel = ssh_channel_new(session);;
|
||||
if (channel == NULL) {
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
|
||||
rc = ssh_channel_open_session(channel);
|
||||
if (rc < 0) {
|
||||
ssh_channel_close(channel);
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
|
||||
rc = ssh_channel_request_exec(channel, "cat > /dev/null");
|
||||
if (rc < 0) {
|
||||
ssh_channel_close(channel);
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
while ((rc = ssh_channel_write(channel, buffer, sizeof(buffer))) > 0) {
|
||||
total += rc;
|
||||
if(total/2 >= lastshown){
|
||||
printf("written %llx\n", (long long unsigned int) total);
|
||||
lastshown=total;
|
||||
}
|
||||
if(total > LIMIT)
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
printf("error : %s\n",ssh_get_error(session));
|
||||
ssh_channel_close(channel);
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ssh_channel_send_eof(channel);
|
||||
ssh_channel_close(channel);
|
||||
|
||||
ssh_disconnect(session);
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -13,10 +13,14 @@ clients must be made or how a client should react.
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_TERMIOS_H
|
||||
#include <termios.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <sys/time.h>
|
||||
@@ -83,13 +87,23 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
int ret;
|
||||
while(channel){
|
||||
do{
|
||||
int fd;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
if(!eof)
|
||||
FD_SET(0,&fds);
|
||||
timeout.tv_sec=30;
|
||||
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[1]=NULL;
|
||||
ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout);
|
||||
@@ -98,54 +112,59 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
if(FD_ISSET(0,&fds)){
|
||||
lus=read(0,buffer,sizeof(buffer));
|
||||
if(lus)
|
||||
channel_write(channel,buffer,lus);
|
||||
ssh_channel_write(channel,buffer,lus);
|
||||
else {
|
||||
eof=1;
|
||||
channel_send_eof(channel);
|
||||
ssh_channel_send_eof(channel);
|
||||
}
|
||||
}
|
||||
if(channel && channel_is_closed(channel)){
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
|
||||
|
||||
channel_free(channel);
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_channel_free(channel);
|
||||
channel=NULL;
|
||||
channels[0]=NULL;
|
||||
}
|
||||
if(outchannels[0]){
|
||||
while(channel && channel_is_open(channel) && channel_poll(channel,0)){
|
||||
lus=channel_read(channel,buffer,sizeof(buffer),0);
|
||||
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,0)){
|
||||
lus = ssh_channel_read(channel,buffer,sizeof(buffer),0);
|
||||
if(lus==-1){
|
||||
fprintf(stderr, "Error reading channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
|
||||
|
||||
channel_free(channel);
|
||||
ssh_channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else
|
||||
write(1,buffer,lus);
|
||||
} else {
|
||||
ret = write(1, buffer, lus);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error writing to stdin: %s",
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
while(channel && channel_is_open(channel) && channel_poll(channel,1)){ /* stderr */
|
||||
lus=channel_read(channel,buffer,sizeof(buffer),1);
|
||||
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,1)){ /* stderr */
|
||||
lus = ssh_channel_read(channel, buffer, sizeof(buffer), 1);
|
||||
if(lus==-1){
|
||||
fprintf(stderr, "Error reading channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
|
||||
channel_free(channel);
|
||||
ssh_channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else
|
||||
write(2,buffer,lus);
|
||||
} else {
|
||||
ret = write(2, buffer, lus);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error writing to stderr: %s",
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(channel && channel_is_closed(channel)){
|
||||
channel_free(channel);
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_channel_free(channel);
|
||||
channel=NULL;
|
||||
}
|
||||
} while (ret==EINTR || ret==SSH_EINTR);
|
||||
@@ -156,8 +175,8 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
static void forwarding(ssh_session session){
|
||||
ssh_channel channel;
|
||||
int r;
|
||||
channel=channel_new(session);
|
||||
r=channel_open_forward(channel,desthost,atoi(port),"localhost",22);
|
||||
channel = ssh_channel_new(session);
|
||||
r = ssh_channel_open_forward(channel, desthost, atoi(port), "localhost", 22);
|
||||
if(r<0) {
|
||||
printf("error forwarding port : %s\n",ssh_get_error(session));
|
||||
return;
|
||||
@@ -191,7 +210,6 @@ static int client(ssh_session session){
|
||||
if(auth != SSH_AUTH_SUCCESS){
|
||||
return -1;
|
||||
}
|
||||
ssh_log(session, SSH_LOG_FUNCTIONS, "Authentication success");
|
||||
forwarding(session);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ set(libssh_HDRS
|
||||
callbacks.h
|
||||
libssh.h
|
||||
ssh2.h
|
||||
legacy.h
|
||||
libsshpp.hpp
|
||||
)
|
||||
|
||||
if (WITH_SFTP)
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2008-2009 Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __AGENT_H
|
||||
#define __AGENT_H
|
||||
|
||||
@@ -48,9 +68,10 @@
|
||||
#define SSH_AGENT_OLD_SIGNATURE 0x01
|
||||
|
||||
struct ssh_agent_struct {
|
||||
struct socket *sock;
|
||||
struct ssh_socket_struct *sock;
|
||||
ssh_buffer ident;
|
||||
unsigned int count;
|
||||
ssh_channel channel;
|
||||
};
|
||||
|
||||
#ifndef _WIN32
|
||||
@@ -80,17 +101,17 @@ void agent_free(struct ssh_agent_struct *agent);
|
||||
*/
|
||||
int agent_is_running(struct ssh_session_struct *session);
|
||||
|
||||
int agent_get_ident_count(struct ssh_session_struct *session);
|
||||
int ssh_agent_get_ident_count(struct ssh_session_struct *session);
|
||||
|
||||
struct ssh_public_key_struct *agent_get_next_ident(struct ssh_session_struct *session,
|
||||
char **comment);
|
||||
ssh_key ssh_agent_get_next_ident(struct ssh_session_struct *session,
|
||||
char **comment);
|
||||
|
||||
struct ssh_public_key_struct *agent_get_first_ident(struct ssh_session_struct *session,
|
||||
char **comment);
|
||||
ssh_key ssh_agent_get_first_ident(struct ssh_session_struct *session,
|
||||
char **comment);
|
||||
|
||||
ssh_string agent_sign_data(struct ssh_session_struct *session,
|
||||
struct ssh_buffer_struct *data,
|
||||
struct ssh_public_key_struct *pubkey);
|
||||
ssh_string ssh_agent_sign_data(ssh_session session,
|
||||
const ssh_key pubkey,
|
||||
struct ssh_buffer_struct *data);
|
||||
#endif
|
||||
|
||||
#endif /* __AGENT_H */
|
||||
|
||||
111
include/libssh/auth.h
Normal file
111
include/libssh/auth.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2009 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 AUTH_H_
|
||||
#define AUTH_H_
|
||||
#include "config.h"
|
||||
#include "libssh/callbacks.h"
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_banner);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_failure);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_success);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_pk_ok);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_info_request);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_info_response);
|
||||
|
||||
/** @internal
|
||||
* kdbint structure must be shared with message.c
|
||||
* and server.c
|
||||
*/
|
||||
struct ssh_kbdint_struct {
|
||||
uint32_t nprompts;
|
||||
uint32_t nanswers;
|
||||
char *name;
|
||||
char *instruction;
|
||||
char **prompts;
|
||||
unsigned char *echo; /* bool array */
|
||||
char **answers;
|
||||
};
|
||||
typedef struct ssh_kbdint_struct* ssh_kbdint;
|
||||
|
||||
ssh_kbdint ssh_kbdint_new(void);
|
||||
void ssh_kbdint_clean(ssh_kbdint kbd);
|
||||
void ssh_kbdint_free(ssh_kbdint kbd);
|
||||
|
||||
|
||||
#ifdef WITH_SSH1
|
||||
void ssh_auth1_handler(ssh_session session, uint8_t type);
|
||||
|
||||
/* auth1.c */
|
||||
int ssh_userauth1_none(ssh_session session, const char *username);
|
||||
int ssh_userauth1_offer_pubkey(ssh_session session, const char *username,
|
||||
int type, ssh_string pubkey);
|
||||
int ssh_userauth1_password(ssh_session session, const char *username,
|
||||
const char *password);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/** @internal
|
||||
* States of authentication in the client-side. They describe
|
||||
* what was the last response from the server
|
||||
*/
|
||||
enum ssh_auth_state_e {
|
||||
/** No authentication asked */
|
||||
SSH_AUTH_STATE_NONE=0,
|
||||
/** Last authentication response was a partial success */
|
||||
SSH_AUTH_STATE_PARTIAL,
|
||||
/** Last authentication response was a success */
|
||||
SSH_AUTH_STATE_SUCCESS,
|
||||
/** Last authentication response was failed */
|
||||
SSH_AUTH_STATE_FAILED,
|
||||
/** Last authentication was erroneous */
|
||||
SSH_AUTH_STATE_ERROR,
|
||||
/** Last state was a keyboard-interactive ask for info */
|
||||
SSH_AUTH_STATE_INFO,
|
||||
/** Last state was a public key accepted for authentication */
|
||||
SSH_AUTH_STATE_PK_OK,
|
||||
/** We asked for a keyboard-interactive authentication */
|
||||
SSH_AUTH_STATE_KBDINT_SENT,
|
||||
/** We have sent an userauth request with gssapi-with-mic */
|
||||
SSH_AUTH_STATE_GSSAPI_REQUEST_SENT,
|
||||
/** We are exchanging tokens until authentication */
|
||||
SSH_AUTH_STATE_GSSAPI_TOKEN,
|
||||
/** We have sent the MIC and expecting to be authenticated */
|
||||
SSH_AUTH_STATE_GSSAPI_MIC_SENT,
|
||||
};
|
||||
|
||||
/** @internal
|
||||
* @brief states of the authentication service request
|
||||
*/
|
||||
enum ssh_auth_service_state_e {
|
||||
/** initial state */
|
||||
SSH_AUTH_SERVICE_NONE=0,
|
||||
/** Authentication service request packet sent */
|
||||
SSH_AUTH_SERVICE_SENT,
|
||||
/** Service accepted */
|
||||
SSH_AUTH_SERVICE_ACCEPTED,
|
||||
/** Access to service denied (fatal) */
|
||||
SSH_AUTH_SERVICE_DENIED,
|
||||
/** Specific to SSH1 */
|
||||
SSH_AUTH_SERVICE_USER_SENT
|
||||
};
|
||||
|
||||
#endif /* AUTH_H_ */
|
||||
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_ */
|
||||
55
include/libssh/bind.h
Normal file
55
include/libssh/bind.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2010 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 BIND_H_
|
||||
#define BIND_H_
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
|
||||
struct ssh_bind_struct {
|
||||
struct ssh_common_struct common; /* stuff common to ssh_bind and ssh_session */
|
||||
struct ssh_bind_callbacks_struct *bind_callbacks;
|
||||
void *bind_callbacks_userdata;
|
||||
|
||||
struct ssh_poll_handle_struct *poll;
|
||||
/* options */
|
||||
char *wanted_methods[10];
|
||||
char *banner;
|
||||
char *ecdsakey;
|
||||
char *dsakey;
|
||||
char *rsakey;
|
||||
char *ed25519key;
|
||||
ssh_key ecdsa;
|
||||
ssh_key dsa;
|
||||
ssh_key rsa;
|
||||
ssh_key ed25519;
|
||||
char *bindaddr;
|
||||
socket_t bindfd;
|
||||
unsigned int bindport;
|
||||
int blocking;
|
||||
int toaccept;
|
||||
};
|
||||
|
||||
struct ssh_poll_handle_struct *ssh_bind_get_poll(struct ssh_bind_struct
|
||||
*sshbind);
|
||||
|
||||
|
||||
#endif /* BIND_H_ */
|
||||
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 */
|
||||
@@ -3,42 +3,80 @@
|
||||
*
|
||||
* Copyright (c) 2009 by Aris Adamantiadis
|
||||
*
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
* 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 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.
|
||||
* 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 BUFFER_H_
|
||||
#define BUFFER_H_
|
||||
|
||||
/* Describes a buffer state */
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "libssh/libssh.h"
|
||||
/*
|
||||
* Describes a buffer state
|
||||
* [XXXXXXXXXXXXDATA PAYLOAD XXXXXXXXXXXXXXXXXXXXXXXX]
|
||||
* ^ ^ ^ ^]
|
||||
* \_data points\_pos points here \_used points here | /
|
||||
* here Allocated
|
||||
*/
|
||||
struct ssh_buffer_struct {
|
||||
char *data;
|
||||
uint32_t used;
|
||||
uint32_t allocated;
|
||||
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_get_begin(ssh_buffer buffer);
|
||||
LIBSSH_API uint32_t ssh_buffer_get_len(ssh_buffer buffer);
|
||||
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_u8(ssh_buffer buffer, uint8_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_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_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 */
|
||||
void *buffer_get_rest(ssh_buffer buffer);
|
||||
|
||||
@@ -3,20 +3,19 @@
|
||||
*
|
||||
* Copyright (c) 2009 Aris Adamantiadis <aris@0xbadc0de.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.
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
* 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 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.
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* callback.h
|
||||
@@ -34,45 +33,370 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SSH authentication callback.
|
||||
* @defgroup libssh_callbacks The libssh callbacks
|
||||
* @ingroup libssh
|
||||
*
|
||||
* @param prompt Prompt to be displayed.
|
||||
* @param buf Buffer to save the password. You should null-terminate it.
|
||||
* @param len Length of the buffer.
|
||||
* @param echo Enable or disable the echo of what you type.
|
||||
* @param verify Should the password be verified?
|
||||
* @param userdata Userdata to be passed to the callback function. Useful
|
||||
* for GUI applications.
|
||||
* Callback which can be replaced in libssh.
|
||||
*
|
||||
* @return 0 on success, < 0 on error.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @internal
|
||||
* @brief callback to process simple codes
|
||||
* @param code value to transmit
|
||||
* @param user Userdata to pass in callback
|
||||
*/
|
||||
typedef void (*ssh_callback_int) (int code, void *user);
|
||||
|
||||
/** @internal
|
||||
* @brief callback for data received messages.
|
||||
* @param data data retrieved from the socket or stream
|
||||
* @param len number of bytes available from this stream
|
||||
* @param user user-supplied pointer sent along with all callback messages
|
||||
* @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_callback_data) (const void *data, size_t len, void *user);
|
||||
|
||||
typedef void (*ssh_callback_int_int) (int code, int errno_code, void *user);
|
||||
|
||||
typedef int (*ssh_message_callback) (ssh_session, ssh_message message, void *user);
|
||||
typedef int (*ssh_channel_callback_int) (ssh_channel channel, int code, void *user);
|
||||
typedef int (*ssh_channel_callback_data) (ssh_channel channel, int code, void *data, size_t len, void *user);
|
||||
|
||||
/**
|
||||
* @brief SSH log callback. All logging messages will go through this callback
|
||||
* @param session Current session handler
|
||||
* @param priority Priority of the log, the smaller being the more important
|
||||
* @param message the actual message
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef int (*ssh_auth_callback) (const char *prompt, char *buf, size_t len,
|
||||
int echo, int verify, void *userdata);
|
||||
typedef void (*ssh_log_callback) (ssh_session session, int priority,
|
||||
const char *message, void *userdata);
|
||||
/** this callback will be called with status going from 0.0 to 1.0 during
|
||||
* connection */
|
||||
|
||||
/**
|
||||
* @brief SSH log callback.
|
||||
*
|
||||
* All logging messages will go through this callback.
|
||||
*
|
||||
* @param priority Priority of the log, the smaller being the more important.
|
||||
*
|
||||
* @param function The function name calling the the logging fucntions.
|
||||
*
|
||||
* @param message The actual message
|
||||
*
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef void (*ssh_logging_callback) (int priority,
|
||||
const char *function,
|
||||
const char *buffer,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH Connection status callback.
|
||||
* @param session Current session handler
|
||||
* @param status Percentage of connection status, going from 0.0 to 1.0
|
||||
* once connection is done.
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef void (*ssh_status_callback) (ssh_session session, float status,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH global request callback. All global request will go through this
|
||||
* callback.
|
||||
* @param session Current session handler
|
||||
* @param message the actual message
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef void (*ssh_global_request_callback) (ssh_session session,
|
||||
ssh_message message, void *userdata);
|
||||
|
||||
/**
|
||||
* @brief Handles an SSH new channel open X11 request. This happens when the server
|
||||
* sends back an X11 connection attempt. This is a client-side API
|
||||
* @param session current session handler
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns a valid ssh_channel handle if the request is to be allowed
|
||||
* @returns NULL if the request should not be allowed
|
||||
* @warning The channel pointer returned by this callback must be closed by the application.
|
||||
*/
|
||||
typedef ssh_channel (*ssh_channel_open_request_x11_callback) (ssh_session session,
|
||||
const char * originator_address, int originator_port, void *userdata);
|
||||
|
||||
/**
|
||||
* The structure to replace libssh functions with appropriate callbacks.
|
||||
*/
|
||||
struct ssh_callbacks_struct {
|
||||
/** size of this structure. internal, shoud be set with ssh_callbacks_init()*/
|
||||
size_t size;
|
||||
/** User-provided data. User is free to set anything he wants here */
|
||||
void *userdata;
|
||||
/** this functions will be called if e.g. a keyphrase is needed. */
|
||||
ssh_auth_callback auth_function;
|
||||
/** this function will be called each time a loggable event happens. */
|
||||
ssh_log_callback log_function;
|
||||
/** this function gets called during connection time to indicate the percentage
|
||||
* of connection steps completed.
|
||||
*/
|
||||
/** DON'T SET THIS use ssh_callbacks_init() instead. */
|
||||
size_t size;
|
||||
/**
|
||||
* User-provided data. User is free to set anything he wants here
|
||||
*/
|
||||
void *userdata;
|
||||
/**
|
||||
* This functions will be called if e.g. a keyphrase is needed.
|
||||
*/
|
||||
ssh_auth_callback auth_function;
|
||||
/**
|
||||
* This function will be called each time a loggable event happens.
|
||||
*/
|
||||
ssh_log_callback log_function;
|
||||
/**
|
||||
* This function gets called during connection time to indicate the
|
||||
* percentage of connection steps completed.
|
||||
*/
|
||||
void (*connect_status_function)(void *userdata, float status);
|
||||
/**
|
||||
* This function will be called each time a global request is received.
|
||||
*/
|
||||
ssh_global_request_callback global_request_function;
|
||||
/** This function will be called when an incoming X11 request is received.
|
||||
*/
|
||||
ssh_channel_open_request_x11_callback channel_open_request_x11_function;
|
||||
};
|
||||
typedef struct ssh_callbacks_struct *ssh_callbacks;
|
||||
|
||||
typedef struct ssh_callbacks_struct * ssh_callbacks;
|
||||
/** These are callbacks used specifically in SSH servers.
|
||||
*/
|
||||
|
||||
/** Initializes an ssh_callbacks_struct
|
||||
/**
|
||||
* @brief SSH authentication callback.
|
||||
* @param session Current session handler
|
||||
* @param user User that wants to authenticate
|
||||
* @param password Password used for authentication
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns SSH_AUTH_SUCCESS Authentication is accepted.
|
||||
* @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed.
|
||||
* @returns SSH_AUTH_DENIED Authentication failed.
|
||||
*/
|
||||
typedef int (*ssh_auth_password_callback) (ssh_session session, const char *user, const char *password,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH authentication callback. Tries to authenticates user with the "none" method
|
||||
* which is anonymous or passwordless.
|
||||
* @param session Current session handler
|
||||
* @param user User that wants to authenticate
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns SSH_AUTH_SUCCESS Authentication is accepted.
|
||||
* @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed.
|
||||
* @returns SSH_AUTH_DENIED Authentication failed.
|
||||
*/
|
||||
typedef int (*ssh_auth_none_callback) (ssh_session session, const char *user, void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH authentication callback. Tries to authenticates user with the "gssapi-with-mic" method
|
||||
* @param session Current session handler
|
||||
* @param user Username of the user (can be spoofed)
|
||||
* @param principal Authenticated principal of the user, including realm.
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns SSH_AUTH_SUCCESS Authentication is accepted.
|
||||
* @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed.
|
||||
* @returns SSH_AUTH_DENIED Authentication failed.
|
||||
* @warning Implementations should verify that parameter user matches in some way the principal.
|
||||
* user and principal can be different. Only the latter is guaranteed to be safe.
|
||||
*/
|
||||
typedef int (*ssh_auth_gssapi_mic_callback) (ssh_session session, const char *user, const char *principal,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH authentication callback.
|
||||
* @param session Current session handler
|
||||
* @param user User that wants to authenticate
|
||||
* @param pubkey public key used for authentication
|
||||
* @param signature_state SSH_PUBLICKEY_STATE_NONE if the key is not signed (simple public key probe),
|
||||
* SSH_PUBLICKEY_STATE_VALID if the signature is valid. Others values should be
|
||||
* replied with a SSH_AUTH_DENIED.
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns SSH_AUTH_SUCCESS Authentication is accepted.
|
||||
* @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed.
|
||||
* @returns SSH_AUTH_DENIED Authentication failed.
|
||||
*/
|
||||
typedef int (*ssh_auth_pubkey_callback) (ssh_session session, const char *user, struct ssh_key_struct *pubkey,
|
||||
char signature_state, void *userdata);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handles an SSH service request
|
||||
* @param session current session handler
|
||||
* @param service name of the service (e.g. "ssh-userauth") requested
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns 0 if the request is to be allowed
|
||||
* @returns -1 if the request should not be allowed
|
||||
*/
|
||||
|
||||
typedef int (*ssh_service_request_callback) (ssh_session session, const char *service, void *userdata);
|
||||
|
||||
/**
|
||||
* @brief Handles an SSH new channel open session request
|
||||
* @param session current session handler
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns a valid ssh_channel handle if the request is to be allowed
|
||||
* @returns NULL if the request should not be allowed
|
||||
* @warning The channel pointer returned by this callback must be closed by the application.
|
||||
*/
|
||||
typedef ssh_channel (*ssh_channel_open_request_session_callback) (ssh_session session, void *userdata);
|
||||
|
||||
/*
|
||||
* @brief handle the beginning of a GSSAPI authentication, server side.
|
||||
* @param session current session handler
|
||||
* @param user the username of the client
|
||||
* @param n_oid number of available oids
|
||||
* @param oids OIDs provided by the client
|
||||
* @returns an ssh_string containing the chosen OID, that's supported by both
|
||||
* client and server.
|
||||
* @warning It is not necessary to fill this callback in if libssh is linked
|
||||
* with libgssapi.
|
||||
*/
|
||||
typedef ssh_string (*ssh_gssapi_select_oid_callback) (ssh_session session, const char *user,
|
||||
int n_oid, ssh_string *oids, void *userdata);
|
||||
|
||||
/*
|
||||
* @brief handle the negociation of a security context, server side.
|
||||
* @param session current session handler
|
||||
* @param[in] input_token input token provided by client
|
||||
* @param[out] output_token output of the gssapi accept_sec_context method,
|
||||
* NULL after completion.
|
||||
* @returns SSH_OK if the token was generated correctly or accept_sec_context
|
||||
* returned GSS_S_COMPLETE
|
||||
* @returns SSH_ERROR in case of error
|
||||
* @warning It is not necessary to fill this callback in if libssh is linked
|
||||
* with libgssapi.
|
||||
*/
|
||||
typedef int (*ssh_gssapi_accept_sec_ctx_callback) (ssh_session session,
|
||||
ssh_string input_token, ssh_string *output_token, void *userdata);
|
||||
|
||||
/*
|
||||
* @brief Verify and authenticates a MIC, server side.
|
||||
* @param session current session handler
|
||||
* @param[in] mic input mic to be verified provided by client
|
||||
* @param[in] mic_buffer buffer of data to be signed.
|
||||
* @param[in] mic_buffer_size size of mic_buffer
|
||||
* @returns SSH_OK if the MIC was authenticated correctly
|
||||
* @returns SSH_ERROR in case of error
|
||||
* @warning It is not necessary to fill this callback in if libssh is linked
|
||||
* with libgssapi.
|
||||
*/
|
||||
typedef int (*ssh_gssapi_verify_mic_callback) (ssh_session session,
|
||||
ssh_string mic, void *mic_buffer, size_t mic_buffer_size, void *userdata);
|
||||
|
||||
|
||||
/**
|
||||
* This structure can be used to implement a libssh server, with appropriate callbacks.
|
||||
*/
|
||||
|
||||
struct ssh_server_callbacks_struct {
|
||||
/** DON'T SET THIS use ssh_callbacks_init() instead. */
|
||||
size_t size;
|
||||
/**
|
||||
* User-provided data. User is free to set anything he wants here
|
||||
*/
|
||||
void *userdata;
|
||||
/** This function gets called when a client tries to authenticate through
|
||||
* password method.
|
||||
*/
|
||||
ssh_auth_password_callback auth_password_function;
|
||||
|
||||
/** This function gets called when a client tries to authenticate through
|
||||
* none method.
|
||||
*/
|
||||
ssh_auth_none_callback auth_none_function;
|
||||
|
||||
/** This function gets called when a client tries to authenticate through
|
||||
* gssapi-mic method.
|
||||
*/
|
||||
ssh_auth_gssapi_mic_callback auth_gssapi_mic_function;
|
||||
|
||||
/** this function gets called when a client tries to authenticate or offer
|
||||
* a public key.
|
||||
*/
|
||||
ssh_auth_pubkey_callback auth_pubkey_function;
|
||||
|
||||
/** This functions gets called when a service request is issued by the
|
||||
* client
|
||||
*/
|
||||
ssh_service_request_callback service_request_function;
|
||||
/** This functions gets called when a new channel request is issued by
|
||||
* the client
|
||||
*/
|
||||
ssh_channel_open_request_session_callback channel_open_request_session_function;
|
||||
/** This function will be called when a new gssapi authentication is attempted.
|
||||
*/
|
||||
ssh_gssapi_select_oid_callback gssapi_select_oid_function;
|
||||
/** This function will be called when a gssapi token comes in.
|
||||
*/
|
||||
ssh_gssapi_accept_sec_ctx_callback gssapi_accept_sec_ctx_function;
|
||||
/* This function will be called when a MIC needs to be verified.
|
||||
*/
|
||||
ssh_gssapi_verify_mic_callback gssapi_verify_mic_function;
|
||||
};
|
||||
typedef struct ssh_server_callbacks_struct *ssh_server_callbacks;
|
||||
|
||||
/**
|
||||
* @brief Set the session server callback functions.
|
||||
*
|
||||
* This functions sets the callback structure to use your own callback
|
||||
* functions for user authentication, new channels and requests.
|
||||
*
|
||||
* @code
|
||||
* struct ssh_server_callbacks_struct cb = {
|
||||
* .userdata = data,
|
||||
* .auth_password_function = my_auth_function
|
||||
* };
|
||||
* ssh_callbacks_init(&cb);
|
||||
* ssh_set_server_callbacks(session, &cb);
|
||||
* @endcode
|
||||
*
|
||||
* @param session The session to set the callback structure.
|
||||
*
|
||||
* @param cb The callback structure itself.
|
||||
*
|
||||
* @return SSH_OK on success, SSH_ERROR on error.
|
||||
*/
|
||||
LIBSSH_API int ssh_set_server_callbacks(ssh_session session, ssh_server_callbacks cb);
|
||||
|
||||
/**
|
||||
* These are the callbacks exported by the socket structure
|
||||
* They are called by the socket module when a socket event appears
|
||||
*/
|
||||
struct ssh_socket_callbacks_struct {
|
||||
/**
|
||||
* User-provided data. User is free to set anything he wants here
|
||||
*/
|
||||
void *userdata;
|
||||
/**
|
||||
* This function will be called each time data appears on socket. The data
|
||||
* not consumed will appear on the next data event.
|
||||
*/
|
||||
ssh_callback_data data;
|
||||
/** This function will be called each time a controlflow state changes, i.e.
|
||||
* the socket is available for reading or writing.
|
||||
*/
|
||||
ssh_callback_int controlflow;
|
||||
/** This function will be called each time an exception appears on socket. An
|
||||
* exception can be a socket problem (timeout, ...) or an end-of-file.
|
||||
*/
|
||||
ssh_callback_int_int exception;
|
||||
/** This function is called when the ssh_socket_connect was used on the socket
|
||||
* on nonblocking state, and the connection successed.
|
||||
*/
|
||||
ssh_callback_int_int connected;
|
||||
};
|
||||
typedef struct ssh_socket_callbacks_struct *ssh_socket_callbacks;
|
||||
|
||||
#define SSH_SOCKET_FLOW_WRITEWILLBLOCK 1
|
||||
#define SSH_SOCKET_FLOW_WRITEWONTBLOCK 2
|
||||
|
||||
#define SSH_SOCKET_EXCEPTION_EOF 1
|
||||
#define SSH_SOCKET_EXCEPTION_ERROR 2
|
||||
|
||||
#define SSH_SOCKET_CONNECTED_OK 1
|
||||
#define SSH_SOCKET_CONNECTED_ERROR 2
|
||||
#define SSH_SOCKET_CONNECTED_TIMEOUT 3
|
||||
|
||||
/**
|
||||
* @brief Initializes an ssh_callbacks_struct
|
||||
* A call to this macro is mandatory when you have set a new
|
||||
* ssh_callback_struct structure. Its goal is to maintain the binary
|
||||
* compatibility with future versions of libssh as the structure
|
||||
@@ -83,31 +407,449 @@ typedef struct ssh_callbacks_struct * ssh_callbacks;
|
||||
} while(0);
|
||||
|
||||
/**
|
||||
* @brief Set the callback functions.
|
||||
* @internal
|
||||
* @brief tests if a callback can be called without crash
|
||||
* verifies that the struct size if big enough
|
||||
* verifies that the callback pointer exists
|
||||
* @param p callback pointer
|
||||
* @param c callback name
|
||||
* @returns nonzero if callback can be called
|
||||
*/
|
||||
#define ssh_callbacks_exists(p,c) (\
|
||||
(p != NULL) && ( (char *)&((p)-> c) < (char *)(p) + (p)->size ) && \
|
||||
((p)-> c != NULL) \
|
||||
)
|
||||
|
||||
/** @brief Prototype for a packet callback, to be called when a new packet arrives
|
||||
* @param session The current session of the packet
|
||||
* @param type packet type (see ssh2.h)
|
||||
* @param packet buffer containing the packet, excluding size, type and padding fields
|
||||
* @param user user argument to the callback
|
||||
* and are called each time a packet shows up
|
||||
* @returns SSH_PACKET_USED Packet was parsed and used
|
||||
* @returns SSH_PACKET_NOT_USED Packet was not used or understood, processing must continue
|
||||
*/
|
||||
typedef int (*ssh_packet_callback) (ssh_session session, uint8_t type, ssh_buffer packet, void *user);
|
||||
|
||||
/** return values for a ssh_packet_callback */
|
||||
/** Packet was used and should not be parsed by another callback */
|
||||
#define SSH_PACKET_USED 1
|
||||
/** Packet was not used and should be passed to any other callback
|
||||
* available */
|
||||
#define SSH_PACKET_NOT_USED 2
|
||||
|
||||
|
||||
/** @brief This macro declares a packet callback handler
|
||||
* @code
|
||||
* SSH_PACKET_CALLBACK(mycallback){
|
||||
* ...
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
#define SSH_PACKET_CALLBACK(name) \
|
||||
int name (ssh_session session, uint8_t type, ssh_buffer packet, void *user)
|
||||
|
||||
struct ssh_packet_callbacks_struct {
|
||||
/** Index of the first packet type being handled */
|
||||
uint8_t start;
|
||||
/** Number of packets being handled by this callback struct */
|
||||
uint8_t n_callbacks;
|
||||
/** A pointer to n_callbacks packet callbacks */
|
||||
ssh_packet_callback *callbacks;
|
||||
/**
|
||||
* User-provided data. User is free to set anything he wants here
|
||||
*/
|
||||
void *user;
|
||||
};
|
||||
|
||||
typedef struct ssh_packet_callbacks_struct *ssh_packet_callbacks;
|
||||
|
||||
/**
|
||||
* @brief Set the session callback functions.
|
||||
*
|
||||
* This functions sets the callback structure to use your own callback
|
||||
* functions for auth, logging and status.
|
||||
*
|
||||
* @code
|
||||
* struct ssh_callbacks_struct cb;
|
||||
* memset(&cb, 0, sizeof(struct ssh_callbacks_struct));
|
||||
* cb.userdata = data;
|
||||
* cb.auth_function = my_auth_function;
|
||||
*
|
||||
* struct ssh_callbacks_struct cb = {
|
||||
* .userdata = data,
|
||||
* .auth_function = my_auth_function
|
||||
* };
|
||||
* ssh_callbacks_init(&cb);
|
||||
* ssh_set_callbacks(session, &cb);
|
||||
* @endcode
|
||||
*
|
||||
* @param session The session to set the callback structure.
|
||||
*
|
||||
* @param cb The callback itself.
|
||||
* @param cb The callback structure itself.
|
||||
*
|
||||
* @return 0 on success, < 0 on error.
|
||||
* @return SSH_OK on success, SSH_ERROR on error.
|
||||
*/
|
||||
LIBSSH_API int ssh_set_callbacks(ssh_session session, ssh_callbacks cb);
|
||||
|
||||
/**
|
||||
* @brief SSH channel data callback. Called when data is available on a channel
|
||||
* @param session Current session handler
|
||||
* @param channel the actual channel
|
||||
* @param data the data that has been read on the channel
|
||||
* @param len the length of the data
|
||||
* @param is_stderr is 0 for stdout or 1 for stderr
|
||||
* @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,
|
||||
ssh_channel channel,
|
||||
void *data,
|
||||
uint32_t len,
|
||||
int is_stderr,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH channel eof callback. Called when a channel receives EOF
|
||||
* @param session Current session handler
|
||||
* @param channel the actual channel
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef void (*ssh_channel_eof_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH channel close callback. Called when a channel is closed by remote peer
|
||||
* @param session Current session handler
|
||||
* @param channel the actual channel
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef void (*ssh_channel_close_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH channel signal callback. Called when a channel has received a signal
|
||||
* @param session Current session handler
|
||||
* @param channel the actual channel
|
||||
* @param signal the signal name (without the SIG prefix)
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef void (*ssh_channel_signal_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
const char *signal,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH channel exit status callback. Called when a channel has received an exit status
|
||||
* @param session Current session handler
|
||||
* @param channel the actual channel
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef void (*ssh_channel_exit_status_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
int exit_status,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH channel exit signal callback. Called when a channel has received an exit signal
|
||||
* @param session Current session handler
|
||||
* @param channel the actual channel
|
||||
* @param signal the signal name (without the SIG prefix)
|
||||
* @param core a boolean telling wether a core has been dumped or not
|
||||
* @param errmsg the description of the exception
|
||||
* @param lang the language of the description (format: RFC 3066)
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef void (*ssh_channel_exit_signal_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
const char *signal,
|
||||
int core,
|
||||
const char *errmsg,
|
||||
const char *lang,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH channel PTY request from a client.
|
||||
* @param channel the channel
|
||||
* @param term The type of terminal emulation
|
||||
* @param width width of the terminal, in characters
|
||||
* @param height height of the terminal, in characters
|
||||
* @param pxwidth width of the terminal, in pixels
|
||||
* @param pxheight height of the terminal, in pixels
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns 0 if the pty request is accepted
|
||||
* @returns -1 if the request is denied
|
||||
*/
|
||||
typedef int (*ssh_channel_pty_request_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
const char *term,
|
||||
int width, int height,
|
||||
int pxwidth, int pwheight,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH channel Shell request from a client.
|
||||
* @param channel the channel
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns 0 if the shell request is accepted
|
||||
* @returns 1 if the request is denied
|
||||
*/
|
||||
typedef int (*ssh_channel_shell_request_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
void *userdata);
|
||||
/**
|
||||
* @brief SSH auth-agent-request from the client. This request is
|
||||
* sent by a client when agent forwarding is available.
|
||||
* Server is free to ignore this callback, no answer is expected.
|
||||
* @param channel the channel
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef void (*ssh_channel_auth_agent_req_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH X11 request from the client. This request is
|
||||
* sent by a client when X11 forwarding is requested(and available).
|
||||
* Server is free to ignore this callback, no answer is expected.
|
||||
* @param channel the channel
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef void (*ssh_channel_x11_req_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
int single_connection,
|
||||
const char *auth_protocol,
|
||||
const char *auth_cookie,
|
||||
uint32_t screen_number,
|
||||
void *userdata);
|
||||
/**
|
||||
* @brief SSH channel PTY windows change (terminal size) from a client.
|
||||
* @param channel the channel
|
||||
* @param width width of the terminal, in characters
|
||||
* @param height height of the terminal, in characters
|
||||
* @param pxwidth width of the terminal, in pixels
|
||||
* @param pxheight height of the terminal, in pixels
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns 0 if the pty request is accepted
|
||||
* @returns -1 if the request is denied
|
||||
*/
|
||||
typedef int (*ssh_channel_pty_window_change_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
int width, int height,
|
||||
int pxwidth, int pwheight,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH channel Exec request from a client.
|
||||
* @param channel the channel
|
||||
* @param command the shell command to be executed
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns 0 if the exec request is accepted
|
||||
* @returns 1 if the request is denied
|
||||
*/
|
||||
typedef int (*ssh_channel_exec_request_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
const char *command,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH channel environment request from a client.
|
||||
* @param channel the channel
|
||||
* @param env_name name of the environment value to be set
|
||||
* @param env_value value of the environment value to be set
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns 0 if the env request is accepted
|
||||
* @returns 1 if the request is denied
|
||||
* @warning some environment variables can be dangerous if changed (e.g.
|
||||
* LD_PRELOAD) and should not be fulfilled.
|
||||
*/
|
||||
typedef int (*ssh_channel_env_request_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
const char *env_name,
|
||||
const char *env_value,
|
||||
void *userdata);
|
||||
/**
|
||||
* @brief SSH channel subsystem request from a client.
|
||||
* @param channel the channel
|
||||
* @param subsystem the subsystem required
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns 0 if the subsystem request is accepted
|
||||
* @returns 1 if the request is denied
|
||||
*/
|
||||
typedef int (*ssh_channel_subsystem_request_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
const char *subsystem,
|
||||
void *userdata);
|
||||
|
||||
|
||||
struct ssh_channel_callbacks_struct {
|
||||
/** DON'T SET THIS use ssh_callbacks_init() instead. */
|
||||
size_t size;
|
||||
/**
|
||||
* User-provided data. User is free to set anything he wants here
|
||||
*/
|
||||
void *userdata;
|
||||
/**
|
||||
* This functions will be called when there is data available.
|
||||
*/
|
||||
ssh_channel_data_callback channel_data_function;
|
||||
/**
|
||||
* This functions will be called when the channel has received an EOF.
|
||||
*/
|
||||
ssh_channel_eof_callback channel_eof_function;
|
||||
/**
|
||||
* This functions will be called when the channel has been closed by remote
|
||||
*/
|
||||
ssh_channel_close_callback channel_close_function;
|
||||
/**
|
||||
* This functions will be called when a signal has been received
|
||||
*/
|
||||
ssh_channel_signal_callback channel_signal_function;
|
||||
/**
|
||||
* This functions will be called when an exit status has been received
|
||||
*/
|
||||
ssh_channel_exit_status_callback channel_exit_status_function;
|
||||
/**
|
||||
* This functions will be called when an exit signal has been received
|
||||
*/
|
||||
ssh_channel_exit_signal_callback channel_exit_signal_function;
|
||||
/**
|
||||
* This function will be called when a client requests a PTY
|
||||
*/
|
||||
ssh_channel_pty_request_callback channel_pty_request_function;
|
||||
/**
|
||||
* This function will be called when a client requests a shell
|
||||
*/
|
||||
ssh_channel_shell_request_callback channel_shell_request_function;
|
||||
/** This function will be called when a client requests agent
|
||||
* authentication forwarding.
|
||||
*/
|
||||
ssh_channel_auth_agent_req_callback channel_auth_agent_req_function;
|
||||
/** This function will be called when a client requests X11
|
||||
* forwarding.
|
||||
*/
|
||||
ssh_channel_x11_req_callback channel_x11_req_function;
|
||||
/** This function will be called when a client requests a
|
||||
* window change.
|
||||
*/
|
||||
ssh_channel_pty_window_change_callback channel_pty_window_change_function;
|
||||
/** This function will be called when a client requests a
|
||||
* command execution.
|
||||
*/
|
||||
ssh_channel_exec_request_callback channel_exec_request_function;
|
||||
/** This function will be called when a client requests an environment
|
||||
* variable to be set.
|
||||
*/
|
||||
ssh_channel_env_request_callback channel_env_request_function;
|
||||
/** This function will be called when a client requests a subsystem
|
||||
* (like sftp).
|
||||
*/
|
||||
ssh_channel_subsystem_request_callback channel_subsystem_request_function;
|
||||
};
|
||||
|
||||
typedef struct ssh_channel_callbacks_struct *ssh_channel_callbacks;
|
||||
|
||||
/**
|
||||
* @brief Set the channel callback functions.
|
||||
*
|
||||
* This functions sets the callback structure to use your own callback
|
||||
* functions for channel data and exceptions
|
||||
*
|
||||
* @code
|
||||
* struct ssh_channel_callbacks_struct cb = {
|
||||
* .userdata = data,
|
||||
* .channel_data = my_channel_data_function
|
||||
* };
|
||||
* ssh_callbacks_init(&cb);
|
||||
* ssh_set_channel_callbacks(channel, &cb);
|
||||
* @endcode
|
||||
*
|
||||
* @param channel The channel to set the callback structure.
|
||||
*
|
||||
* @param cb The callback structure itself.
|
||||
*
|
||||
* @return SSH_OK on success, SSH_ERROR on error.
|
||||
*/
|
||||
LIBSSH_API int ssh_set_channel_callbacks(ssh_channel channel,
|
||||
ssh_channel_callbacks cb);
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @group libssh_threads
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef int (*ssh_thread_callback) (void **lock);
|
||||
|
||||
typedef unsigned long (*ssh_thread_id_callback) (void);
|
||||
struct ssh_threads_callbacks_struct {
|
||||
const char *type;
|
||||
ssh_thread_callback mutex_init;
|
||||
ssh_thread_callback mutex_destroy;
|
||||
ssh_thread_callback mutex_lock;
|
||||
ssh_thread_callback mutex_unlock;
|
||||
ssh_thread_id_callback thread_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Set the thread callbacks structure.
|
||||
*
|
||||
* This is necessary if your program is using libssh in a multithreaded fashion.
|
||||
* This function must be called first, outside of any threading context (in your
|
||||
* main() function for instance), before you call ssh_init().
|
||||
*
|
||||
* @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_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
|
||||
*cb);
|
||||
|
||||
/**
|
||||
* @brief returns a pointer on the pthread threads callbacks, to be used with
|
||||
* ssh_threads_set_callbacks.
|
||||
* @warning you have to link with the library ssh_threads.
|
||||
* @see ssh_threads_set_callbacks
|
||||
*/
|
||||
LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_pthread(void);
|
||||
|
||||
/**
|
||||
* @brief Get the noop threads callbacks structure
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_noop(void);
|
||||
|
||||
/**
|
||||
* @brief Set the logging callback function.
|
||||
*
|
||||
* @param[in] cb The callback to set.
|
||||
*
|
||||
* @return 0 on success, < 0 on errror.
|
||||
*/
|
||||
LIBSSH_API int ssh_set_log_callback(ssh_logging_callback cb);
|
||||
|
||||
/**
|
||||
* @brief Get the pointer to the logging callback function.
|
||||
*
|
||||
* @return The pointer the the callback or NULL if none set.
|
||||
*/
|
||||
LIBSSH_API ssh_logging_callback ssh_get_log_callback(void);
|
||||
|
||||
/** @} */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_SSH_CALLBACK_H */
|
||||
|
||||
/* @} */
|
||||
|
||||
@@ -3,29 +3,58 @@
|
||||
*
|
||||
* Copyright (c) 2009 by Aris Adamantiadis
|
||||
*
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
* 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 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.
|
||||
* 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 CHANNELS_H_
|
||||
#define CHANNELS_H_
|
||||
#include "libssh/priv.h"
|
||||
|
||||
/** @internal
|
||||
* Describes the different possible states in a
|
||||
* outgoing (client) channel request
|
||||
*/
|
||||
enum ssh_channel_request_state_e {
|
||||
/** No request has been made */
|
||||
SSH_CHANNEL_REQ_STATE_NONE = 0,
|
||||
/** A request has been made and answer is pending */
|
||||
SSH_CHANNEL_REQ_STATE_PENDING,
|
||||
/** A request has been replied and accepted */
|
||||
SSH_CHANNEL_REQ_STATE_ACCEPTED,
|
||||
/** A request has been replied and refused */
|
||||
SSH_CHANNEL_REQ_STATE_DENIED,
|
||||
/** A request has been replied and an error happend */
|
||||
SSH_CHANNEL_REQ_STATE_ERROR
|
||||
};
|
||||
|
||||
enum ssh_channel_state_e {
|
||||
SSH_CHANNEL_STATE_NOT_OPEN = 0,
|
||||
SSH_CHANNEL_STATE_OPENING,
|
||||
SSH_CHANNEL_STATE_OPEN_DENIED,
|
||||
SSH_CHANNEL_STATE_OPEN,
|
||||
SSH_CHANNEL_STATE_CLOSED
|
||||
};
|
||||
|
||||
/* The channel has been closed by the remote side */
|
||||
#define SSH_CHANNEL_FLAG_CLOSED_REMOTE 0x1
|
||||
/* The channel has been freed by the calling program */
|
||||
#define SSH_CHANNEL_FLAG_FREED_LOCAL 0x2
|
||||
/* the channel has not yet been bound to a remote one */
|
||||
#define SSH_CHANNEL_FLAG_NOT_BOUND 0x4
|
||||
|
||||
struct ssh_channel_struct {
|
||||
struct ssh_channel_struct *prev;
|
||||
struct ssh_channel_struct *next;
|
||||
ssh_session session; /* SSH_SESSION pointer */
|
||||
uint32_t local_channel;
|
||||
uint32_t local_window;
|
||||
@@ -36,23 +65,54 @@ struct ssh_channel_struct {
|
||||
uint32_t remote_window;
|
||||
int remote_eof; /* end of file received */
|
||||
uint32_t remote_maxpacket;
|
||||
int open; /* shows if the channel is still opened */
|
||||
enum ssh_channel_state_e state;
|
||||
int delayed_close;
|
||||
int flags;
|
||||
ssh_buffer stdout_buffer;
|
||||
ssh_buffer stderr_buffer;
|
||||
void *userarg;
|
||||
int version;
|
||||
int blocking;
|
||||
int exit_status;
|
||||
enum ssh_channel_request_state_e request_state;
|
||||
ssh_channel_callbacks callbacks;
|
||||
/* counters */
|
||||
ssh_counter counter;
|
||||
};
|
||||
|
||||
void channel_handle(ssh_session session, int type);
|
||||
ssh_channel channel_new(ssh_session session);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_channel_open_conf);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_channel_open_fail);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_channel_success);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_channel_failure);
|
||||
SSH_PACKET_CALLBACK(ssh_request_success);
|
||||
SSH_PACKET_CALLBACK(ssh_request_denied);
|
||||
|
||||
SSH_PACKET_CALLBACK(channel_rcv_change_window);
|
||||
SSH_PACKET_CALLBACK(channel_rcv_eof);
|
||||
SSH_PACKET_CALLBACK(channel_rcv_close);
|
||||
SSH_PACKET_CALLBACK(channel_rcv_request);
|
||||
SSH_PACKET_CALLBACK(channel_rcv_data);
|
||||
|
||||
ssh_channel ssh_channel_new(ssh_session session);
|
||||
int channel_default_bufferize(ssh_channel channel, void *data, int len,
|
||||
int is_stderr);
|
||||
int ssh_channel_flush(ssh_channel channel);
|
||||
uint32_t ssh_channel_new_id(ssh_session session);
|
||||
ssh_channel ssh_channel_from_local(ssh_session session, uint32_t id);
|
||||
int channel_write_common(ssh_channel channel, const void *data,
|
||||
uint32_t len, int is_stderr);
|
||||
void ssh_channel_do_free(ssh_channel channel);
|
||||
#ifdef WITH_SSH1
|
||||
SSH_PACKET_CALLBACK(ssh_packet_data1);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_close1);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_exist_status1);
|
||||
|
||||
/* channels1.c */
|
||||
int channel_open_session1(ssh_channel channel);
|
||||
int channel_request_pty_size1(ssh_channel channel, const char *terminal,
|
||||
int cols, int rows);
|
||||
int channel_change_pty_size1(ssh_channel channel, int cols, int rows);
|
||||
int channel_request_shell1(ssh_channel channel);
|
||||
int channel_request_exec1(ssh_channel channel, const char *cmd);
|
||||
int channel_write1(ssh_channel channel, const void *data, int len);
|
||||
ssh_channel ssh_get_channel1(ssh_session session);
|
||||
#endif
|
||||
|
||||
#endif /* CHANNELS_H_ */
|
||||
|
||||
28
include/libssh/crc32.h
Normal file
28
include/libssh/crc32.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* crc32.c - simple CRC32 code
|
||||
*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2005 by Aris Adamantiadis
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _CRC32_H
|
||||
#define _CRC32_H
|
||||
|
||||
uint32_t ssh_crc32(const char *buf, uint32_t len);
|
||||
|
||||
#endif /* _CRC32_H */
|
||||
@@ -1,22 +1,21 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2003,2009 by Aris Adamantiadis
|
||||
* Copyright (c) 2003-2009 by Aris Adamantiadis
|
||||
*
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
* 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 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.
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -40,29 +39,69 @@
|
||||
#undef cbc_decrypt
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENSSL_ECDH_H
|
||||
#include <openssl/ecdh.h>
|
||||
#endif
|
||||
#include "libssh/ecdh.h"
|
||||
#include "libssh/kex.h"
|
||||
#include "libssh/curve25519.h"
|
||||
|
||||
#define DIGEST_MAX_LEN 64
|
||||
|
||||
enum ssh_key_exchange_e {
|
||||
/* diffie-hellman-group1-sha1 */
|
||||
SSH_KEX_DH_GROUP1_SHA1=1,
|
||||
/* diffie-hellman-group14-sha1 */
|
||||
SSH_KEX_DH_GROUP14_SHA1,
|
||||
/* ecdh-sha2-nistp256 */
|
||||
SSH_KEX_ECDH_SHA2_NISTP256,
|
||||
/* curve25519-sha256@libssh.org */
|
||||
SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG
|
||||
};
|
||||
|
||||
struct ssh_crypto_struct {
|
||||
bignum e,f,x,k,y;
|
||||
unsigned char session_id[SHA_DIGEST_LEN];
|
||||
#ifdef HAVE_ECDH
|
||||
EC_KEY *ecdh_privkey;
|
||||
ssh_string ecdh_client_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
|
||||
ssh_string dh_server_signature; /* information used by dh_handshake. */
|
||||
size_t digest_len; /* len of all the fields below */
|
||||
unsigned char *session_id;
|
||||
unsigned char *secret_hash; /* Secret hash is same as session id until re-kex */
|
||||
unsigned char *encryptIV;
|
||||
unsigned char *decryptIV;
|
||||
unsigned char *decryptkey;
|
||||
unsigned char *encryptkey;
|
||||
unsigned char *encryptMAC;
|
||||
unsigned char *decryptMAC;
|
||||
unsigned char hmacbuf[DIGEST_MAX_LEN];
|
||||
struct ssh_cipher_struct *in_cipher, *out_cipher; /* the cipher structures/objects */
|
||||
enum ssh_hmac_e in_hmac, out_hmac; /* the MAC algorithms used */
|
||||
|
||||
unsigned char encryptIV[SHA_DIGEST_LEN*2];
|
||||
unsigned char decryptIV[SHA_DIGEST_LEN*2];
|
||||
|
||||
unsigned char decryptkey[SHA_DIGEST_LEN*2];
|
||||
unsigned char encryptkey[SHA_DIGEST_LEN*2];
|
||||
|
||||
unsigned char encryptMAC[SHA_DIGEST_LEN];
|
||||
unsigned char decryptMAC[SHA_DIGEST_LEN];
|
||||
unsigned char hmacbuf[EVP_MAX_MD_SIZE];
|
||||
struct crypto_struct *in_cipher, *out_cipher; /* the cipher structures/objects */
|
||||
ssh_string server_pubkey;
|
||||
const char *server_pubkey_type;
|
||||
int do_compress_out; /* idem */
|
||||
int do_compress_in; /* don't set them, set the option instead */
|
||||
int delayed_compress_in; /* Use of zlib@openssh.org */
|
||||
int delayed_compress_out;
|
||||
void *compress_out_ctx; /* don't touch it */
|
||||
void *compress_in_ctx; /* really, don't */
|
||||
/* kex sent by server, client, and mutually elected methods */
|
||||
struct ssh_kex_struct server_kex;
|
||||
struct ssh_kex_struct client_kex;
|
||||
char *kex_methods[SSH_KEX_METHODS];
|
||||
enum ssh_key_exchange_e kex_type;
|
||||
enum ssh_mac_e mac_type; /* Mac operations to use for key gen */
|
||||
};
|
||||
|
||||
struct crypto_struct {
|
||||
struct ssh_cipher_struct {
|
||||
const char *name; /* ssh name of the algorithm */
|
||||
unsigned int blocksize; /* blocksize of the algo */
|
||||
unsigned int keylen; /* length of the key structure */
|
||||
@@ -70,25 +109,16 @@ struct crypto_struct {
|
||||
gcry_cipher_hd_t *key;
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
void *key; /* a key buffer allocated for the algo */
|
||||
void *IV;
|
||||
#endif
|
||||
unsigned int keysize; /* bytes of key used. != keylen */
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
/* sets the new key for immediate use */
|
||||
int (*set_encrypt_key)(struct crypto_struct *cipher, void *key, void *IV);
|
||||
int (*set_decrypt_key)(struct crypto_struct *cipher, void *key, void *IV);
|
||||
void (*cbc_encrypt)(struct crypto_struct *cipher, void *in, void *out,
|
||||
int (*set_encrypt_key)(struct ssh_cipher_struct *cipher, void *key, void *IV);
|
||||
int (*set_decrypt_key)(struct ssh_cipher_struct *cipher, void *key, void *IV);
|
||||
void (*encrypt)(struct ssh_cipher_struct *cipher, void *in, void *out,
|
||||
unsigned long len);
|
||||
void (*cbc_decrypt)(struct crypto_struct *cipher, void *in, void *out,
|
||||
void (*decrypt)(struct ssh_cipher_struct *cipher, void *in, void *out,
|
||||
unsigned long len);
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
/* sets the new key for immediate use */
|
||||
int (*set_encrypt_key)(struct crypto_struct *cipher, void *key);
|
||||
int (*set_decrypt_key)(struct crypto_struct *cipher, void *key);
|
||||
void (*cbc_encrypt)(struct crypto_struct *cipher, void *in, void *out,
|
||||
unsigned long len, void *IV);
|
||||
void (*cbc_decrypt)(struct crypto_struct *cipher, void *in, void *out,
|
||||
unsigned long len, void *IV);
|
||||
#endif
|
||||
};
|
||||
|
||||
/* vim: set ts=2 sw=2 et cindent: */
|
||||
|
||||
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_ */
|
||||
@@ -3,30 +3,28 @@
|
||||
*
|
||||
* Copyright (c) 2009 by Aris Adamantiadis
|
||||
*
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
* 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 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.
|
||||
* 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 DH_H_
|
||||
#define DH_H_
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/* DH key generation */
|
||||
#include "libssh/keys.h"
|
||||
#include "libssh/crypto.h"
|
||||
|
||||
void ssh_print_bignum(const char *which,bignum num);
|
||||
int dh_generate_e(ssh_session session);
|
||||
int dh_generate_f(ssh_session session);
|
||||
int dh_generate_x(ssh_session session);
|
||||
@@ -41,17 +39,13 @@ int dh_import_f(ssh_session session,ssh_string f_string);
|
||||
int dh_import_e(ssh_session session, ssh_string e_string);
|
||||
void dh_import_pubkey(ssh_session session,ssh_string pubkey_string);
|
||||
int dh_build_k(ssh_session session);
|
||||
int ssh_client_dh_init(ssh_session session);
|
||||
int ssh_client_dh_reply(ssh_session session, ssh_buffer packet);
|
||||
|
||||
int make_sessionid(ssh_session session);
|
||||
/* add data for the final cookie */
|
||||
int hashbufin_add_cookie(ssh_session session, unsigned char *cookie);
|
||||
int hashbufout_add_cookie(ssh_session session);
|
||||
int generate_session_keys(ssh_session session);
|
||||
int sig_verify(ssh_session session, ssh_public_key pubkey,
|
||||
SIGNATURE *signature, unsigned char *digest, int size);
|
||||
/* returns 1 if server signature ok, 0 otherwise. The NEXT crypto is checked, not the current one */
|
||||
int signature_verify(ssh_session session,ssh_string signature);
|
||||
bignum make_string_bn(ssh_string string);
|
||||
ssh_string make_bignum_string(bignum num);
|
||||
|
||||
|
||||
#endif /* DH_H_ */
|
||||
|
||||
43
include/libssh/ecdh.h
Normal file
43
include/libssh/ecdh.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2011 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 ECDH_H_
|
||||
#define ECDH_H_
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
#ifdef HAVE_OPENSSL_ECDH_H
|
||||
|
||||
#ifdef HAVE_ECC
|
||||
#define HAVE_ECDH 1
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_OPENSSL_ECDH_H */
|
||||
#endif /* HAVE_LIBCRYPTO */
|
||||
|
||||
int ssh_client_ecdh_init(ssh_session session);
|
||||
int ssh_client_ecdh_reply(ssh_session session, ssh_buffer packet);
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet);
|
||||
#endif /* WITH_SERVER */
|
||||
|
||||
#endif /* ECDH_H_ */
|
||||
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
|
||||
45
include/libssh/gssapi.h
Normal file
45
include/libssh/gssapi.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2013 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 GSSAPI_H_
|
||||
#define GSSAPI_H_
|
||||
|
||||
#include "config.h"
|
||||
#include "session.h"
|
||||
|
||||
/* all OID begin with the tag identifier + length */
|
||||
#define SSH_OID_TAG 06
|
||||
|
||||
typedef struct ssh_gssapi_struct *ssh_gssapi;
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n_oid, ssh_string *oids);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_mic);
|
||||
#endif /* WITH_SERVER */
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_client);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_response);
|
||||
|
||||
|
||||
int ssh_gssapi_auth_mic(ssh_session session);
|
||||
|
||||
#endif /* GSSAPI_H */
|
||||
50
include/libssh/kex.h
Normal file
50
include/libssh/kex.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2009 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 KEX_H_
|
||||
#define KEX_H_
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/callbacks.h"
|
||||
|
||||
#define SSH_KEX_METHODS 10
|
||||
|
||||
struct ssh_kex_struct {
|
||||
unsigned char cookie[16];
|
||||
char *methods[SSH_KEX_METHODS];
|
||||
};
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_kexinit);
|
||||
#ifdef WITH_SSH1
|
||||
SSH_PACKET_CALLBACK(ssh_packet_publickey1);
|
||||
#endif
|
||||
|
||||
int ssh_send_kex(ssh_session session, int server_kex);
|
||||
void ssh_list_kex(struct ssh_kex_struct *kex);
|
||||
int set_client_kex(ssh_session session);
|
||||
int ssh_kex_select_methods(ssh_session session);
|
||||
int verify_existing_algo(int algo, const char *name);
|
||||
char **space_tokenize(const char *chain);
|
||||
int ssh_get_kex1(ssh_session session);
|
||||
char *ssh_find_matching(const char *in_d, const char *what_d);
|
||||
const char *ssh_kex_get_supported_method(uint32_t algo);
|
||||
const char *ssh_kex_get_description(uint32_t algo);
|
||||
|
||||
#endif /* KEX_H_ */
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2009 by Aris Adamantiadis
|
||||
*
|
||||
* The SSH Library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* The SSH Library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with the SSH Library; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef KEYFILES_H_
|
||||
#define KEYFILES_H_
|
||||
|
||||
/* in keyfiles.c */
|
||||
|
||||
ssh_private_key _privatekey_from_file(void *session, const char *filename,
|
||||
int type);
|
||||
ssh_string try_publickey_from_file(ssh_session session,
|
||||
struct ssh_keys_struct keytab,
|
||||
char **privkeyfile, int *type);
|
||||
|
||||
#endif /* KEYFILES_H_ */
|
||||
@@ -3,20 +3,19 @@
|
||||
*
|
||||
* Copyright (c) 2009 by Aris Adamantiadis
|
||||
*
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
* 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 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.
|
||||
* 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 KEYS_H_
|
||||
@@ -49,36 +48,9 @@ struct ssh_private_key_struct {
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct signature_struct {
|
||||
int type;
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
gcry_sexp_t dsa_sign;
|
||||
gcry_sexp_t rsa_sign;
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
DSA_SIG *dsa_sign;
|
||||
ssh_string rsa_sign;
|
||||
#endif
|
||||
} SIGNATURE;
|
||||
|
||||
const char *ssh_type_to_char(int type);
|
||||
int ssh_type_from_name(const char *name);
|
||||
ssh_buffer ssh_userauth_build_digest(ssh_session session, ssh_message msg, char *service);
|
||||
|
||||
ssh_private_key privatekey_make_dss(ssh_session session, ssh_buffer buffer);
|
||||
ssh_private_key privatekey_make_rsa(ssh_session session, ssh_buffer buffer,
|
||||
const char *type);
|
||||
ssh_private_key privatekey_from_string(ssh_session session, ssh_string privkey_s);
|
||||
|
||||
ssh_public_key publickey_make_dss(ssh_session session, ssh_buffer buffer);
|
||||
ssh_public_key publickey_make_rsa(ssh_session session, ssh_buffer buffer, int type);
|
||||
ssh_public_key publickey_from_string(ssh_session session, ssh_string pubkey_s);
|
||||
SIGNATURE *signature_from_string(ssh_session session, ssh_string signature,ssh_public_key pubkey,int needed_type);
|
||||
void signature_free(SIGNATURE *sign);
|
||||
ssh_string ssh_do_sign_with_agent(struct ssh_session_struct *session,
|
||||
struct ssh_buffer_struct *buf, struct ssh_public_key_struct *publickey);
|
||||
ssh_string ssh_do_sign(ssh_session session,ssh_buffer sigbuf,
|
||||
ssh_private_key privatekey);
|
||||
ssh_string ssh_sign_session_id(ssh_session session, ssh_private_key privatekey);
|
||||
ssh_string ssh_encrypt_rsa1(ssh_session session, ssh_string data, ssh_public_key key);
|
||||
|
||||
#endif /* KEYS_H_ */
|
||||
|
||||
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_ */
|
||||
120
include/libssh/legacy.h
Normal file
120
include/libssh/legacy.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2010 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
|
||||
*/
|
||||
|
||||
/* Since libssh.h includes legacy.h, it's important that libssh.h is included
|
||||
* first. we don't define LEGACY_H now because we want it to be defined when
|
||||
* included from libssh.h
|
||||
* All function calls declared in this header are deprecated and meant to be
|
||||
* removed in future.
|
||||
*/
|
||||
|
||||
#ifndef LEGACY_H_
|
||||
#define LEGACY_H_
|
||||
|
||||
typedef struct ssh_private_key_struct* ssh_private_key;
|
||||
typedef struct ssh_public_key_struct* ssh_public_key;
|
||||
|
||||
LIBSSH_API int ssh_auth_list(ssh_session session);
|
||||
LIBSSH_API int ssh_userauth_offer_pubkey(ssh_session session, const char *username, int type, ssh_string publickey);
|
||||
LIBSSH_API int ssh_userauth_pubkey(ssh_session session, const char *username, ssh_string publickey, ssh_private_key privatekey);
|
||||
#ifndef _WIN32
|
||||
LIBSSH_API int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
|
||||
ssh_public_key publickey);
|
||||
#endif
|
||||
LIBSSH_API int ssh_userauth_autopubkey(ssh_session session, const char *passphrase);
|
||||
LIBSSH_API int ssh_userauth_privatekey_file(ssh_session session, const char *username,
|
||||
const char *filename, const char *passphrase);
|
||||
|
||||
SSH_DEPRECATED LIBSSH_API void buffer_free(ssh_buffer buffer);
|
||||
SSH_DEPRECATED LIBSSH_API void *buffer_get(ssh_buffer buffer);
|
||||
SSH_DEPRECATED LIBSSH_API uint32_t buffer_get_len(ssh_buffer buffer);
|
||||
SSH_DEPRECATED LIBSSH_API ssh_buffer buffer_new(void);
|
||||
|
||||
SSH_DEPRECATED LIBSSH_API ssh_channel channel_accept_x11(ssh_channel channel, int timeout_ms);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_change_pty_size(ssh_channel channel,int cols,int rows);
|
||||
SSH_DEPRECATED LIBSSH_API ssh_channel channel_forward_accept(ssh_session session, int timeout_ms);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_close(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_forward_cancel(ssh_session session, const char *address, int port);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_forward_listen(ssh_session session, const char *address, int port, int *bound_port);
|
||||
SSH_DEPRECATED LIBSSH_API void channel_free(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_get_exit_status(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API ssh_session channel_get_session(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_is_closed(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_is_eof(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_is_open(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API ssh_channel channel_new(ssh_session session);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_open_forward(ssh_channel channel, const char *remotehost,
|
||||
int remoteport, const char *sourcehost, int localport);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_open_session(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_poll(ssh_channel channel, int is_stderr);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_read(ssh_channel channel, void *dest, uint32_t count, int is_stderr);
|
||||
|
||||
SSH_DEPRECATED LIBSSH_API int channel_read_buffer(ssh_channel channel, ssh_buffer buffer, uint32_t count,
|
||||
int is_stderr);
|
||||
|
||||
SSH_DEPRECATED LIBSSH_API int channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count,
|
||||
int is_stderr);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_request_env(ssh_channel channel, const char *name, const char *value);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_request_exec(ssh_channel channel, const char *cmd);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_request_pty(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_request_pty_size(ssh_channel channel, const char *term,
|
||||
int cols, int rows);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_request_shell(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_request_send_signal(ssh_channel channel, const char *signum);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_request_sftp(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_request_subsystem(ssh_channel channel, const char *subsystem);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_request_x11(ssh_channel channel, int single_connection, const char *protocol,
|
||||
const char *cookie, int screen_number);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_send_eof(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_select(ssh_channel *readchans, ssh_channel *writechans, ssh_channel *exceptchans, struct
|
||||
timeval * timeout);
|
||||
SSH_DEPRECATED LIBSSH_API void channel_set_blocking(ssh_channel channel, int blocking);
|
||||
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 ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
|
||||
int type, const char *passphrase);
|
||||
LIBSSH_API void publickey_free(ssh_public_key key);
|
||||
LIBSSH_API int ssh_publickey_to_file(ssh_session session, const char *file,
|
||||
ssh_string pubkey, int type);
|
||||
LIBSSH_API ssh_string publickey_from_file(ssh_session session, const char *filename,
|
||||
int *type);
|
||||
LIBSSH_API ssh_public_key publickey_from_privatekey(ssh_private_key prv);
|
||||
LIBSSH_API ssh_string publickey_to_string(ssh_public_key key);
|
||||
LIBSSH_API int ssh_try_publickey_from_file(ssh_session session, const char *keyfile,
|
||||
ssh_string *publickey, int *type);
|
||||
LIBSSH_API enum ssh_keytypes_e ssh_privatekey_type(ssh_private_key privatekey);
|
||||
|
||||
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_public_key ssh_message_auth_publickey(ssh_message msg);
|
||||
|
||||
SSH_DEPRECATED LIBSSH_API void string_burn(ssh_string str);
|
||||
SSH_DEPRECATED LIBSSH_API ssh_string string_copy(ssh_string str);
|
||||
SSH_DEPRECATED LIBSSH_API void *string_data(ssh_string str);
|
||||
SSH_DEPRECATED LIBSSH_API int string_fill(ssh_string str, const void *data, size_t len);
|
||||
SSH_DEPRECATED LIBSSH_API void string_free(ssh_string str);
|
||||
SSH_DEPRECATED LIBSSH_API ssh_string string_from_char(const char *what);
|
||||
SSH_DEPRECATED LIBSSH_API size_t string_len(ssh_string str);
|
||||
SSH_DEPRECATED LIBSSH_API ssh_string string_new(size_t size);
|
||||
SSH_DEPRECATED LIBSSH_API char *string_to_char(ssh_string str);
|
||||
|
||||
#endif /* LEGACY_H_ */
|
||||
104
include/libssh/libcrypto.h
Normal file
104
include/libssh/libcrypto.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2009 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 LIBCRYPTO_H_
|
||||
#define LIBCRYPTO_H_
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/hmac.h>
|
||||
#ifdef HAVE_OPENSSL_ECC
|
||||
#include <openssl/evp.h>
|
||||
#endif
|
||||
|
||||
typedef SHA_CTX* SHACTX;
|
||||
typedef SHA256_CTX* SHA256CTX;
|
||||
typedef SHA512_CTX* SHA384CTX;
|
||||
typedef SHA512_CTX* SHA512CTX;
|
||||
typedef MD5_CTX* MD5CTX;
|
||||
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 SHA256_DIGEST_LEN SHA256_DIGEST_LENGTH
|
||||
#define SHA384_DIGEST_LEN SHA384_DIGEST_LENGTH
|
||||
#define SHA512_DIGEST_LEN SHA512_DIGEST_LENGTH
|
||||
#ifdef MD5_DIGEST_LEN
|
||||
#undef MD5_DIGEST_LEN
|
||||
#endif
|
||||
#define MD5_DIGEST_LEN MD5_DIGEST_LENGTH
|
||||
|
||||
#ifdef HAVE_OPENSSL_ECC
|
||||
#define EVP_DIGEST_LEN EVP_MAX_MD_SIZE
|
||||
#endif
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/opensslv.h>
|
||||
#define OPENSSL_0_9_7b 0x0090702fL
|
||||
#if (OPENSSL_VERSION_NUMBER <= OPENSSL_0_9_7b)
|
||||
#define BROKEN_AES_CTR
|
||||
#endif
|
||||
typedef BIGNUM* bignum;
|
||||
typedef BN_CTX* bignum_CTX;
|
||||
|
||||
#define bignum_new() BN_new()
|
||||
#define bignum_free(num) BN_clear_free(num)
|
||||
#define bignum_set_word(bn,n) BN_set_word(bn,n)
|
||||
#define bignum_bin2bn(bn,datalen,data) BN_bin2bn(bn,datalen,data)
|
||||
#define bignum_bn2dec(num) BN_bn2dec(num)
|
||||
#define bignum_dec2bn(bn,data) BN_dec2bn(data,bn)
|
||||
#define bignum_bn2hex(num) BN_bn2hex(num)
|
||||
#define bignum_rand(rnd, bits, top, bottom) BN_rand(rnd,bits,top,bottom)
|
||||
#define bignum_ctx_new() BN_CTX_new()
|
||||
#define bignum_ctx_free(num) BN_CTX_free(num)
|
||||
#define bignum_mod_exp(dest,generator,exp,modulo,ctx) BN_mod_exp(dest,generator,exp,modulo,ctx)
|
||||
#define bignum_num_bytes(num) BN_num_bytes(num)
|
||||
#define bignum_num_bits(num) BN_num_bits(num)
|
||||
#define bignum_is_bit_set(num,bit) BN_is_bit_set(num,bit)
|
||||
#define bignum_bn2bin(num,ptr) BN_bn2bin(num,ptr)
|
||||
#define bignum_cmp(num1,num2) BN_cmp(num1,num2)
|
||||
|
||||
SHA256CTX sha256_init(void);
|
||||
void sha256_update(SHA256CTX c, const void *data, unsigned long len);
|
||||
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);
|
||||
|
||||
#endif /* HAVE_LIBCRYPTO */
|
||||
|
||||
#endif /* LIBCRYPTO_H_ */
|
||||
78
include/libssh/libgcrypt.h
Normal file
78
include/libssh/libgcrypt.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2009 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 LIBGCRYPT_H_
|
||||
#define LIBGCRYPT_H_
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
|
||||
#include <gcrypt.h>
|
||||
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 HMACCTX;
|
||||
typedef void *EVPCTX;
|
||||
#define SHA_DIGEST_LENGTH 20
|
||||
#define SHA_DIGEST_LEN SHA_DIGEST_LENGTH
|
||||
#define MD5_DIGEST_LEN 16
|
||||
#define SHA256_DIGEST_LENGTH 32
|
||||
#define SHA256_DIGEST_LEN SHA256_DIGEST_LENGTH
|
||||
#define SHA384_DIGEST_LENGTH 48
|
||||
#define SHA384_DIGEST_LEN SHA384_DIGEST_LENGTH
|
||||
#define SHA512_DIGEST_LENGTH 64
|
||||
#define SHA512_DIGEST_LEN SHA512_DIGEST_LENGTH
|
||||
|
||||
#ifndef EVP_MAX_MD_SIZE
|
||||
#define EVP_MAX_MD_SIZE 64
|
||||
#endif
|
||||
|
||||
#define EVP_DIGEST_LEN EVP_MAX_MD_SIZE
|
||||
|
||||
typedef gcry_mpi_t bignum;
|
||||
|
||||
/* missing gcrypt functions */
|
||||
int my_gcry_dec2bn(bignum *bn, const char *data);
|
||||
char *my_gcry_bn2dec(bignum bn);
|
||||
|
||||
#define bignum_new() gcry_mpi_new(0)
|
||||
#define bignum_free(num) gcry_mpi_release(num)
|
||||
#define bignum_set_word(bn,n) gcry_mpi_set_ui(bn,n)
|
||||
#define bignum_bin2bn(bn,datalen,data) gcry_mpi_scan(data,GCRYMPI_FMT_USG,bn,datalen,NULL)
|
||||
#define bignum_bn2dec(num) my_gcry_bn2dec(num)
|
||||
#define bignum_dec2bn(num, data) my_gcry_dec2bn(data, num)
|
||||
#define bignum_bn2hex(num,data) gcry_mpi_aprint(GCRYMPI_FMT_HEX,data,NULL,num)
|
||||
#define bignum_hex2bn(num,datalen,data) gcry_mpi_scan(num,GCRYMPI_FMT_HEX,data,datalen,NULL)
|
||||
#define bignum_rand(num,bits) gcry_mpi_randomize(num,bits,GCRY_STRONG_RANDOM),gcry_mpi_set_bit(num,bits-1),gcry_mpi_set_bit(num,0)
|
||||
#define bignum_mod_exp(dest,generator,exp,modulo) gcry_mpi_powm(dest,generator,exp,modulo)
|
||||
#define bignum_num_bits(num) gcry_mpi_get_nbits(num)
|
||||
#define bignum_num_bytes(num) ((gcry_mpi_get_nbits(num)+7)/8)
|
||||
#define bignum_is_bit_set(num,bit) gcry_mpi_test_bit(num,bit)
|
||||
#define bignum_bn2bin(num,datalen,data) gcry_mpi_print(GCRYMPI_FMT_USG,data,datalen,NULL,num)
|
||||
#define bignum_cmp(num1,num2) gcry_mpi_cmp(num1,num2)
|
||||
|
||||
#endif /* HAVE_LIBGCRYPT */
|
||||
|
||||
struct ssh_cipher_struct *ssh_get_ciphertab(void);
|
||||
|
||||
#endif /* LIBGCRYPT_H_ */
|
||||
@@ -3,29 +3,28 @@
|
||||
*
|
||||
* Copyright (c) 2003-2009 by Aris Adamantiadis
|
||||
*
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
* 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 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.
|
||||
* 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 _LIBSSH_H
|
||||
#define _LIBSSH_H
|
||||
|
||||
#ifdef LIBSSH_STATIC
|
||||
#define LIBSSH_API
|
||||
#else
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
#ifdef LIBSSH_STATIC
|
||||
#define LIBSSH_API
|
||||
#else
|
||||
#ifdef LIBSSH_EXPORTS
|
||||
#ifdef __GNUC__
|
||||
#define LIBSSH_API __attribute__((dllexport))
|
||||
@@ -39,12 +38,12 @@
|
||||
#define LIBSSH_API __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#if __GNUC__ >= 4 && !defined(__OS2__)
|
||||
#define LIBSSH_API __attribute__((visibility("default")))
|
||||
#else
|
||||
#if __GNUC__ >= 4
|
||||
#define LIBSSH_API __attribute__((visibility("default")))
|
||||
#else
|
||||
#define LIBSSH_API
|
||||
#endif
|
||||
#define LIBSSH_API
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -78,8 +77,8 @@
|
||||
|
||||
/* libssh version */
|
||||
#define LIBSSH_VERSION_MAJOR 0
|
||||
#define LIBSSH_VERSION_MINOR 4
|
||||
#define LIBSSH_VERSION_MICRO 6
|
||||
#define LIBSSH_VERSION_MINOR 7
|
||||
#define LIBSSH_VERSION_MICRO 0
|
||||
|
||||
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
|
||||
LIBSSH_VERSION_MINOR, \
|
||||
@@ -105,17 +104,25 @@
|
||||
extern "C" {
|
||||
#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_buffer_struct* ssh_buffer;
|
||||
typedef struct ssh_channel_struct* ssh_channel;
|
||||
typedef struct ssh_message_struct* ssh_message;
|
||||
typedef struct ssh_pcap_file_struct* ssh_pcap_file;
|
||||
typedef struct ssh_private_key_struct* ssh_private_key;
|
||||
typedef struct ssh_public_key_struct* ssh_public_key;
|
||||
typedef struct ssh_key_struct* ssh_key;
|
||||
typedef struct ssh_scp_struct* ssh_scp;
|
||||
typedef struct ssh_session_struct* ssh_session;
|
||||
typedef struct ssh_string_struct* ssh_string;
|
||||
typedef struct ssh_event_struct* ssh_event;
|
||||
typedef void* ssh_gssapi_creds;
|
||||
|
||||
/* Socket type */
|
||||
#ifdef _WIN32
|
||||
@@ -154,6 +161,7 @@ enum ssh_auth_e {
|
||||
SSH_AUTH_DENIED,
|
||||
SSH_AUTH_PARTIAL,
|
||||
SSH_AUTH_INFO,
|
||||
SSH_AUTH_AGAIN,
|
||||
SSH_AUTH_ERROR=-1
|
||||
};
|
||||
|
||||
@@ -164,6 +172,7 @@ enum ssh_auth_e {
|
||||
#define SSH_AUTH_METHOD_PUBLICKEY 0x0004
|
||||
#define SSH_AUTH_METHOD_HOSTBASED 0x0008
|
||||
#define SSH_AUTH_METHOD_INTERACTIVE 0x0010
|
||||
#define SSH_AUTH_METHOD_GSSAPI_MIC 0x0020
|
||||
|
||||
/* messages */
|
||||
enum ssh_requests_e {
|
||||
@@ -171,7 +180,7 @@ enum ssh_requests_e {
|
||||
SSH_REQUEST_CHANNEL_OPEN,
|
||||
SSH_REQUEST_CHANNEL,
|
||||
SSH_REQUEST_SERVICE,
|
||||
SSH_REQUEST_GLOBAL,
|
||||
SSH_REQUEST_GLOBAL
|
||||
};
|
||||
|
||||
enum ssh_channel_type_e {
|
||||
@@ -190,12 +199,31 @@ enum ssh_channel_requests_e {
|
||||
SSH_CHANNEL_REQUEST_ENV,
|
||||
SSH_CHANNEL_REQUEST_SUBSYSTEM,
|
||||
SSH_CHANNEL_REQUEST_WINDOW_CHANGE,
|
||||
SSH_CHANNEL_REQUEST_X11
|
||||
};
|
||||
|
||||
/* status flags */
|
||||
enum ssh_global_requests_e {
|
||||
SSH_GLOBAL_REQUEST_UNKNOWN=0,
|
||||
SSH_GLOBAL_REQUEST_TCPIP_FORWARD,
|
||||
SSH_GLOBAL_REQUEST_CANCEL_TCPIP_FORWARD,
|
||||
};
|
||||
|
||||
enum ssh_publickey_state_e {
|
||||
SSH_PUBLICKEY_STATE_ERROR=-1,
|
||||
SSH_PUBLICKEY_STATE_NONE=0,
|
||||
SSH_PUBLICKEY_STATE_VALID=1,
|
||||
SSH_PUBLICKEY_STATE_WRONG=2
|
||||
};
|
||||
|
||||
/* Status flags */
|
||||
/** Socket is closed */
|
||||
#define SSH_CLOSED 0x01
|
||||
/** Reading to socket won't block */
|
||||
#define SSH_READ_PENDING 0x02
|
||||
/** Session was closed due to an error */
|
||||
#define SSH_CLOSED_ERROR 0x04
|
||||
/** Output buffer not empty */
|
||||
#define SSH_WRITE_PENDING 0x08
|
||||
|
||||
enum ssh_server_known_e {
|
||||
SSH_SERVER_ERROR=-1,
|
||||
@@ -203,7 +231,7 @@ enum ssh_server_known_e {
|
||||
SSH_SERVER_KNOWN_OK,
|
||||
SSH_SERVER_KNOWN_CHANGED,
|
||||
SSH_SERVER_FOUND_OTHER,
|
||||
SSH_SERVER_FILE_NOT_FOUND,
|
||||
SSH_SERVER_FILE_NOT_FOUND
|
||||
};
|
||||
|
||||
#ifndef MD5_DIGEST_LEN
|
||||
@@ -218,25 +246,40 @@ enum ssh_error_types_e {
|
||||
SSH_EINTR
|
||||
};
|
||||
|
||||
/* some types for keys */
|
||||
enum ssh_keytypes_e{
|
||||
SSH_KEYTYPE_UNKNOWN=0,
|
||||
SSH_KEYTYPE_DSS=1,
|
||||
SSH_KEYTYPE_RSA,
|
||||
SSH_KEYTYPE_RSA1,
|
||||
SSH_KEYTYPE_ECDSA,
|
||||
SSH_KEYTYPE_ED25519
|
||||
};
|
||||
|
||||
enum ssh_keycmp_e {
|
||||
SSH_KEY_CMP_PUBLIC = 0,
|
||||
SSH_KEY_CMP_PRIVATE
|
||||
};
|
||||
|
||||
/* Error return codes */
|
||||
#define SSH_OK 0 /* No error */
|
||||
#define SSH_ERROR -1 /* Error of some kind */
|
||||
#define SSH_AGAIN -2 /* The nonblocking call must be repeated */
|
||||
#define SSH_EOF -127 /* We have already a eof */
|
||||
|
||||
/** \addtogroup ssh_log
|
||||
/**
|
||||
* @addtogroup libssh_log
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
/** \brief Verbosity level for logging and help to debugging
|
||||
*/
|
||||
|
||||
enum {
|
||||
/** No logging at all
|
||||
*/
|
||||
SSH_LOG_NOLOG=0,
|
||||
/** Only rare and noteworthy events
|
||||
/** Only warnings
|
||||
*/
|
||||
SSH_LOG_RARE,
|
||||
SSH_LOG_WARNING,
|
||||
/** High level protocol information
|
||||
*/
|
||||
SSH_LOG_PROTOCOL,
|
||||
@@ -247,9 +290,29 @@ enum {
|
||||
*/
|
||||
SSH_LOG_FUNCTIONS
|
||||
};
|
||||
/** @}
|
||||
/** @} */
|
||||
#define SSH_LOG_RARE SSH_LOG_WARNING
|
||||
|
||||
/**
|
||||
* @name Logging levels
|
||||
*
|
||||
* @brief Debug levels for logging.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** No logging at all */
|
||||
#define SSH_LOG_NONE 0
|
||||
/** Show only warnings */
|
||||
#define SSH_LOG_WARN 1
|
||||
/** Get some information what's going on */
|
||||
#define SSH_LOG_INFO 2
|
||||
/** Get detailed debuging information **/
|
||||
#define SSH_LOG_DEBUG 3
|
||||
/** Get trace output, packet information, ... */
|
||||
#define SSH_LOG_TRACE 4
|
||||
|
||||
/** @} */
|
||||
|
||||
enum ssh_options_e {
|
||||
SSH_OPTIONS_HOST,
|
||||
SSH_OPTIONS_PORT,
|
||||
@@ -266,13 +329,22 @@ enum ssh_options_e {
|
||||
SSH_OPTIONS_SSH2,
|
||||
SSH_OPTIONS_LOG_VERBOSITY,
|
||||
SSH_OPTIONS_LOG_VERBOSITY_STR,
|
||||
|
||||
SSH_OPTIONS_CIPHERS_C_S,
|
||||
SSH_OPTIONS_CIPHERS_S_C,
|
||||
SSH_OPTIONS_COMPRESSION_C_S,
|
||||
SSH_OPTIONS_COMPRESSION_S_C,
|
||||
SSH_OPTIONS_PROXYCOMMAND,
|
||||
SSH_OPTIONS_BINDADDR
|
||||
SSH_OPTIONS_BINDADDR,
|
||||
SSH_OPTIONS_STRICTHOSTKEYCHECK,
|
||||
SSH_OPTIONS_COMPRESSION,
|
||||
SSH_OPTIONS_COMPRESSION_LEVEL,
|
||||
SSH_OPTIONS_KEY_EXCHANGE,
|
||||
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 {
|
||||
@@ -296,64 +368,48 @@ enum ssh_scp_request_types {
|
||||
SSH_SCP_REQUEST_WARNING
|
||||
};
|
||||
|
||||
LIBSSH_API void buffer_free(ssh_buffer buffer);
|
||||
LIBSSH_API void *buffer_get(ssh_buffer buffer);
|
||||
LIBSSH_API uint32_t buffer_get_len(ssh_buffer buffer);
|
||||
LIBSSH_API ssh_buffer buffer_new(void);
|
||||
|
||||
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);
|
||||
LIBSSH_API ssh_channel channel_forward_accept(ssh_session session, int timeout_ms);
|
||||
LIBSSH_API int channel_close(ssh_channel channel);
|
||||
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);
|
||||
LIBSSH_API void channel_free(ssh_channel channel);
|
||||
LIBSSH_API int channel_get_exit_status(ssh_channel channel);
|
||||
LIBSSH_API ssh_session channel_get_session(ssh_channel channel);
|
||||
LIBSSH_API int channel_is_closed(ssh_channel channel);
|
||||
LIBSSH_API int channel_is_eof(ssh_channel channel);
|
||||
LIBSSH_API int channel_is_open(ssh_channel channel);
|
||||
LIBSSH_API ssh_channel channel_new(ssh_session session);
|
||||
LIBSSH_API int channel_open_forward(ssh_channel channel, const char *remotehost,
|
||||
LIBSSH_API int ssh_blocking_flush(ssh_session session, int timeout);
|
||||
LIBSSH_API ssh_channel ssh_channel_accept_x11(ssh_channel channel, int timeout_ms);
|
||||
LIBSSH_API int ssh_channel_change_pty_size(ssh_channel channel,int cols,int rows);
|
||||
LIBSSH_API int ssh_channel_close(ssh_channel channel);
|
||||
LIBSSH_API void ssh_channel_free(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_get_exit_status(ssh_channel channel);
|
||||
LIBSSH_API ssh_session ssh_channel_get_session(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_is_closed(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_is_eof(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_is_open(ssh_channel channel);
|
||||
LIBSSH_API ssh_channel ssh_channel_new(ssh_session session);
|
||||
LIBSSH_API int ssh_channel_open_auth_agent(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_open_forward(ssh_channel channel, const char *remotehost,
|
||||
int remoteport, const char *sourcehost, int localport);
|
||||
LIBSSH_API int channel_open_session(ssh_channel channel);
|
||||
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);
|
||||
LIBSSH_API int channel_read_buffer(ssh_channel channel, ssh_buffer buffer, uint32_t count,
|
||||
LIBSSH_API int ssh_channel_open_session(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_open_x11(ssh_channel channel, const char *orig_addr, int orig_port);
|
||||
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_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,
|
||||
int is_stderr);
|
||||
LIBSSH_API int channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count,
|
||||
int is_stderr);
|
||||
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);
|
||||
LIBSSH_API int channel_request_pty(ssh_channel channel);
|
||||
LIBSSH_API int channel_request_pty_size(ssh_channel channel, const char *term,
|
||||
LIBSSH_API int ssh_channel_request_env(ssh_channel channel, const char *name, const char *value);
|
||||
LIBSSH_API int ssh_channel_request_exec(ssh_channel channel, const char *cmd);
|
||||
LIBSSH_API int ssh_channel_request_pty(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_request_pty_size(ssh_channel channel, const char *term,
|
||||
int cols, int rows);
|
||||
LIBSSH_API int channel_request_shell(ssh_channel channel);
|
||||
LIBSSH_API int channel_request_send_signal(ssh_channel channel, const char *signum);
|
||||
LIBSSH_API int channel_request_sftp(ssh_channel channel);
|
||||
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,
|
||||
LIBSSH_API int ssh_channel_request_shell(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_request_send_signal(ssh_channel channel, const char *signum);
|
||||
LIBSSH_API int ssh_channel_request_sftp(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_request_subsystem(ssh_channel channel, const char *subsystem);
|
||||
LIBSSH_API int ssh_channel_request_x11(ssh_channel channel, int single_connection, const char *protocol,
|
||||
const char *cookie, int screen_number);
|
||||
LIBSSH_API int channel_send_eof(ssh_channel channel);
|
||||
LIBSSH_API int channel_select(ssh_channel *readchans, ssh_channel *writechans, ssh_channel *exceptchans, struct
|
||||
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
|
||||
timeval * timeout);
|
||||
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);
|
||||
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 uint32_t ssh_channel_window_size(ssh_channel channel);
|
||||
|
||||
LIBSSH_API void privatekey_free(ssh_private_key prv);
|
||||
LIBSSH_API ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
|
||||
int type, const char *passphrase);
|
||||
LIBSSH_API void publickey_free(ssh_public_key key);
|
||||
LIBSSH_API int ssh_publickey_to_file(ssh_session session, const char *file,
|
||||
ssh_string pubkey, int type);
|
||||
LIBSSH_API ssh_string publickey_from_file(ssh_session session, const char *filename,
|
||||
int *type);
|
||||
LIBSSH_API ssh_public_key publickey_from_privatekey(ssh_private_key prv);
|
||||
LIBSSH_API ssh_string publickey_to_string(ssh_public_key key);
|
||||
LIBSSH_API int ssh_try_publickey_from_file(ssh_session session, const char *keyfile,
|
||||
ssh_string *publickey, int *type);
|
||||
|
||||
LIBSSH_API int ssh_auth_list(ssh_session session);
|
||||
LIBSSH_API char *ssh_basename (const char *path);
|
||||
LIBSSH_API void ssh_clean_pubkey_hash(unsigned char **hash);
|
||||
LIBSSH_API int ssh_connect(ssh_session session);
|
||||
@@ -361,6 +417,19 @@ LIBSSH_API const char *ssh_copyright(void);
|
||||
LIBSSH_API void ssh_disconnect(ssh_session session);
|
||||
LIBSSH_API char *ssh_dirname (const char *path);
|
||||
LIBSSH_API int ssh_finalize(void);
|
||||
|
||||
/* REVERSE PORT FORWARDING */
|
||||
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 const char *ssh_get_disconnect_message(ssh_session session);
|
||||
LIBSSH_API const char *ssh_get_error(void *error);
|
||||
@@ -369,19 +438,52 @@ 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_issue_banner(ssh_session session);
|
||||
LIBSSH_API int ssh_get_openssh_version(ssh_session session);
|
||||
LIBSSH_API ssh_string ssh_get_pubkey(ssh_session session);
|
||||
LIBSSH_API int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash);
|
||||
|
||||
LIBSSH_API int ssh_get_publickey(ssh_session session, ssh_key *key);
|
||||
|
||||
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_version(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_is_blocking(ssh_session session);
|
||||
LIBSSH_API int ssh_is_connected(ssh_session session);
|
||||
LIBSSH_API int ssh_is_server_known(ssh_session session);
|
||||
LIBSSH_API void ssh_log(ssh_session session, int prioriry, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
|
||||
|
||||
/* LOGGING */
|
||||
LIBSSH_API int ssh_set_log_level(int level);
|
||||
LIBSSH_API int ssh_get_log_level(void);
|
||||
LIBSSH_API void *ssh_get_log_userdata(void);
|
||||
LIBSSH_API int ssh_set_log_userdata(void *data);
|
||||
LIBSSH_API void _ssh_log(int verbosity,
|
||||
const char *function,
|
||||
const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
|
||||
|
||||
/* legacy */
|
||||
SSH_DEPRECATED LIBSSH_API void ssh_log(ssh_session session,
|
||||
int prioriry,
|
||||
const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
|
||||
|
||||
LIBSSH_API ssh_channel ssh_message_channel_request_open_reply_accept(ssh_message msg);
|
||||
LIBSSH_API int ssh_message_channel_request_reply_success(ssh_message msg);
|
||||
LIBSSH_API void ssh_message_free(ssh_message msg);
|
||||
LIBSSH_API ssh_message ssh_message_get(ssh_session session);
|
||||
LIBSSH_API ssh_message ssh_message_retrieve(ssh_session session, uint32_t packettype);
|
||||
LIBSSH_API int ssh_message_subtype(ssh_message msg);
|
||||
LIBSSH_API int ssh_message_type(ssh_message msg);
|
||||
LIBSSH_API int ssh_mkdir (const char *pathname, mode_t mode);
|
||||
@@ -392,14 +494,78 @@ LIBSSH_API int ssh_options_getopt(ssh_session session, int *argcptr, char **argv
|
||||
LIBSSH_API int ssh_options_parse_config(ssh_session session, const char *filename);
|
||||
LIBSSH_API int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
||||
const void *value);
|
||||
LIBSSH_API int ssh_options_get(ssh_session session, enum ssh_options_e type,
|
||||
char **value);
|
||||
LIBSSH_API int ssh_options_get_port(ssh_session session, unsigned int * port_target);
|
||||
LIBSSH_API int ssh_pcap_file_close(ssh_pcap_file pcap);
|
||||
LIBSSH_API void ssh_pcap_file_free(ssh_pcap_file pcap);
|
||||
LIBSSH_API ssh_pcap_file ssh_pcap_file_new(void);
|
||||
LIBSSH_API int ssh_pcap_file_open(ssh_pcap_file pcap, const char *filename);
|
||||
|
||||
LIBSSH_API int ssh_privatekey_type(ssh_private_key privatekey);
|
||||
/**
|
||||
* @brief SSH authentication callback.
|
||||
*
|
||||
* @param prompt Prompt to be displayed.
|
||||
* @param buf Buffer to save the password. You should null-terminate it.
|
||||
* @param len Length of the buffer.
|
||||
* @param echo Enable or disable the echo of what you type.
|
||||
* @param verify Should the password be verified?
|
||||
* @param userdata Userdata to be passed to the callback function. Useful
|
||||
* for GUI applications.
|
||||
*
|
||||
* @return 0 on success, < 0 on error.
|
||||
*/
|
||||
typedef int (*ssh_auth_callback) (const char *prompt, char *buf, size_t len,
|
||||
int echo, int verify, void *userdata);
|
||||
|
||||
LIBSSH_API ssh_key ssh_key_new(void);
|
||||
LIBSSH_API void ssh_key_free (ssh_key key);
|
||||
LIBSSH_API enum ssh_keytypes_e ssh_key_type(const ssh_key key);
|
||||
LIBSSH_API const char *ssh_key_type_to_char(enum ssh_keytypes_e type);
|
||||
LIBSSH_API enum ssh_keytypes_e ssh_key_type_from_name(const char *name);
|
||||
LIBSSH_API int ssh_key_is_public(const ssh_key k);
|
||||
LIBSSH_API int ssh_key_is_private(const ssh_key k);
|
||||
LIBSSH_API int ssh_key_cmp(const ssh_key k1,
|
||||
const ssh_key k2,
|
||||
enum ssh_keycmp_e what);
|
||||
|
||||
LIBSSH_API int ssh_pki_generate(enum ssh_keytypes_e type, int parameter,
|
||||
ssh_key *pkey);
|
||||
LIBSSH_API int ssh_pki_import_privkey_base64(const char *b64_key,
|
||||
const char *passphrase,
|
||||
ssh_auth_callback auth_fn,
|
||||
void *auth_data,
|
||||
ssh_key *pkey);
|
||||
LIBSSH_API int ssh_pki_import_privkey_file(const char *filename,
|
||||
const char *passphrase,
|
||||
ssh_auth_callback auth_fn,
|
||||
void *auth_data,
|
||||
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,
|
||||
enum ssh_keytypes_e type,
|
||||
ssh_key *pkey);
|
||||
LIBSSH_API int ssh_pki_import_pubkey_file(const char *filename,
|
||||
ssh_key *pkey);
|
||||
|
||||
LIBSSH_API int ssh_pki_export_privkey_to_pubkey(const ssh_key privkey,
|
||||
ssh_key *pkey);
|
||||
LIBSSH_API int ssh_pki_export_pubkey_base64(const ssh_key key,
|
||||
char **b64_key);
|
||||
LIBSSH_API int ssh_pki_export_pubkey_file(const ssh_key key,
|
||||
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 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 void ssh_gssapi_set_creds(ssh_session session, const ssh_gssapi_creds creds);
|
||||
LIBSSH_API int ssh_scp_accept_request(ssh_scp scp);
|
||||
LIBSSH_API int ssh_scp_close(ssh_scp scp);
|
||||
LIBSSH_API int ssh_scp_deny_request(ssh_scp scp, const char *reason);
|
||||
@@ -410,51 +576,97 @@ LIBSSH_API ssh_scp ssh_scp_new(ssh_session session, int mode, const char *locati
|
||||
LIBSSH_API int ssh_scp_pull_request(ssh_scp scp);
|
||||
LIBSSH_API int ssh_scp_push_directory(ssh_scp scp, const char *dirname, int mode);
|
||||
LIBSSH_API int ssh_scp_push_file(ssh_scp scp, const char *filename, size_t size, int perms);
|
||||
LIBSSH_API int ssh_scp_push_file64(ssh_scp scp, const char *filename, uint64_t size, int perms);
|
||||
LIBSSH_API int ssh_scp_read(ssh_scp scp, void *buffer, size_t size);
|
||||
LIBSSH_API const char *ssh_scp_request_get_filename(ssh_scp scp);
|
||||
LIBSSH_API int ssh_scp_request_get_permissions(ssh_scp scp);
|
||||
LIBSSH_API size_t ssh_scp_request_get_size(ssh_scp scp);
|
||||
LIBSSH_API uint64_t ssh_scp_request_get_size64(ssh_scp scp);
|
||||
LIBSSH_API const char *ssh_scp_request_get_warning(ssh_scp scp);
|
||||
LIBSSH_API int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len);
|
||||
LIBSSH_API int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
|
||||
fd_set *readfds, struct timeval *timeout);
|
||||
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 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_toread(ssh_session session);
|
||||
LIBSSH_API void ssh_set_fd_towrite(ssh_session session);
|
||||
LIBSSH_API void ssh_silent_disconnect(ssh_session session);
|
||||
LIBSSH_API int ssh_set_pcap_file(ssh_session session, ssh_pcap_file pcapfile);
|
||||
|
||||
/* USERAUTH */
|
||||
LIBSSH_API int ssh_userauth_none(ssh_session session, const char *username);
|
||||
LIBSSH_API int ssh_userauth_list(ssh_session session, const char *username);
|
||||
LIBSSH_API int ssh_userauth_try_publickey(ssh_session session,
|
||||
const char *username,
|
||||
const ssh_key pubkey);
|
||||
LIBSSH_API int ssh_userauth_publickey(ssh_session session,
|
||||
const char *username,
|
||||
const ssh_key privkey);
|
||||
#ifndef _WIN32
|
||||
LIBSSH_API int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
|
||||
ssh_public_key publickey);
|
||||
LIBSSH_API int ssh_userauth_agent(ssh_session session,
|
||||
const char *username);
|
||||
#endif
|
||||
LIBSSH_API int ssh_userauth_autopubkey(ssh_session session, const char *passphrase);
|
||||
LIBSSH_API int ssh_userauth_publickey_auto(ssh_session session,
|
||||
const char *username,
|
||||
const char *passphrase);
|
||||
LIBSSH_API int ssh_userauth_password(ssh_session session,
|
||||
const char *username,
|
||||
const char *password);
|
||||
|
||||
LIBSSH_API int ssh_userauth_kbdint(ssh_session session, const char *user, const char *submethods);
|
||||
LIBSSH_API const char *ssh_userauth_kbdint_getinstruction(ssh_session session);
|
||||
LIBSSH_API const char *ssh_userauth_kbdint_getname(ssh_session session);
|
||||
LIBSSH_API int ssh_userauth_kbdint_getnprompts(ssh_session session);
|
||||
LIBSSH_API const char *ssh_userauth_kbdint_getprompt(ssh_session session, unsigned int i, char *echo);
|
||||
LIBSSH_API int ssh_userauth_kbdint_getnanswers(ssh_session session);
|
||||
LIBSSH_API const char *ssh_userauth_kbdint_getanswer(ssh_session session, unsigned int i);
|
||||
LIBSSH_API int ssh_userauth_kbdint_setanswer(ssh_session session, unsigned int i,
|
||||
const char *answer);
|
||||
LIBSSH_API int ssh_userauth_list(ssh_session session, const char *username);
|
||||
LIBSSH_API int ssh_userauth_none(ssh_session session, const char *username);
|
||||
LIBSSH_API int ssh_userauth_offer_pubkey(ssh_session session, const char *username, int type, ssh_string publickey);
|
||||
LIBSSH_API int ssh_userauth_password(ssh_session session, const char *username, const char *password);
|
||||
LIBSSH_API int ssh_userauth_pubkey(ssh_session session, const char *username, ssh_string publickey, ssh_private_key privatekey);
|
||||
LIBSSH_API int ssh_userauth_gssapi(ssh_session session);
|
||||
LIBSSH_API const char *ssh_version(int req_version);
|
||||
LIBSSH_API int ssh_write_knownhost(ssh_session session);
|
||||
|
||||
LIBSSH_API void string_burn(ssh_string str);
|
||||
LIBSSH_API ssh_string string_copy(ssh_string str);
|
||||
LIBSSH_API void *string_data(ssh_string str);
|
||||
LIBSSH_API int string_fill(ssh_string str, const void *data, size_t len);
|
||||
LIBSSH_API void string_free(ssh_string str);
|
||||
LIBSSH_API ssh_string string_from_char(const char *what);
|
||||
LIBSSH_API size_t string_len(ssh_string str);
|
||||
LIBSSH_API ssh_string string_new(size_t size);
|
||||
LIBSSH_API char *string_to_char(ssh_string str);
|
||||
LIBSSH_API void ssh_string_burn(ssh_string str);
|
||||
LIBSSH_API ssh_string ssh_string_copy(ssh_string str);
|
||||
LIBSSH_API void *ssh_string_data(ssh_string str);
|
||||
LIBSSH_API int ssh_string_fill(ssh_string str, const void *data, size_t len);
|
||||
LIBSSH_API void ssh_string_free(ssh_string str);
|
||||
LIBSSH_API ssh_string ssh_string_from_char(const char *what);
|
||||
LIBSSH_API size_t ssh_string_len(ssh_string str);
|
||||
LIBSSH_API ssh_string ssh_string_new(size_t size);
|
||||
LIBSSH_API const char *ssh_string_get_char(ssh_string str);
|
||||
LIBSSH_API char *ssh_string_to_char(ssh_string str);
|
||||
LIBSSH_API void ssh_string_free_char(char *s);
|
||||
|
||||
LIBSSH_API int ssh_getpass(const char *prompt, char *buf, size_t len, int echo,
|
||||
int verify);
|
||||
|
||||
|
||||
typedef int (*ssh_event_callback)(socket_t fd, int revents, void *userdata);
|
||||
|
||||
LIBSSH_API ssh_event ssh_event_new(void);
|
||||
LIBSSH_API int ssh_event_add_fd(ssh_event event, socket_t fd, short events,
|
||||
ssh_event_callback cb, void *userdata);
|
||||
LIBSSH_API int ssh_event_add_session(ssh_event event, ssh_session session);
|
||||
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_session(ssh_event event, ssh_session session);
|
||||
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_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
|
||||
#include "libssh/legacy.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user