Compare commits

..

891 Commits

Author SHA1 Message Date
Andreas Schneider
6da817aa47 Update ChangeLog. 2012-11-14 17:56:48 +01:00
Andreas Schneider
05ed61848f cmake: Bump version number. 2012-11-14 17:11:03 +01:00
Andreas Schneider
d63f19c300 CVE-2012-4561: Fix possible free's on invalid pointers. 2012-11-14 17:11:03 +01:00
Andreas Schneider
455da60846 CVE-2012-4561: Fix error handling of try_publickey_from_file(). 2012-11-14 17:11:03 +01:00
Andreas Schneider
46b2eb3c14 CVE-2012-4559: Make sure we don't free name and longname twice on error. 2012-11-14 17:11:03 +01:00
Andreas Schneider
6236001ff4 CVE-2012-4559: Ensure that we don't free req twice. 2012-11-14 17:11:03 +01:00
Andreas Schneider
1471f2c67a CVE-2012-4559: Ensure we don't free blob or request twice. 2012-11-14 17:11:03 +01:00
Andreas Schneider
b485463197 CVE-2012-4560: Fix a write one past the end of 'buf'. 2012-11-14 17:11:03 +01:00
Andreas Schneider
64fca8a7ed CVE-2012-4560: Fix a write one past the end of the 'u' buffer. 2012-11-14 17:11:03 +01:00
Xi Wang
e3d9501b31 CVE-2012-4562: Fix possible string related integer overflows. 2012-11-14 17:11:00 +01:00
Andreas Schneider
1699adfa03 CVE-2012-4562: Fix a possible infinite loop in buffer_reinit().
If needed is bigger than the highest power of two or a which fits in an
integer we will loop forever.
2012-11-14 17:10:57 +01:00
Xi Wang
db81310d71 CVE-2012-4562: Fix multiple integer overflows in buffer-related functions. 2012-11-14 17:10:53 +01:00
Xi Wang
8489521c0d CVE-2012-4562: Fix possible integer overflow in ssh_get_hexa().
No exploit known, but it is better to check the string length.
2012-11-14 17:10:47 +01:00
Andreas Schneider
2ee6282fdd channels: Fix a possible infinite loop if the connection dropped.
This fixes bug #85.
2012-10-22 18:13:53 +02:00
Andreas Schneider
ae218d0d15 channels1: Add missing request_state and set it to accepted.
This fixes bug #88.
2012-10-22 18:06:12 +02:00
Andreas Schneider
26579b2231 auth1: Reset error state to no error.
This fixes bug #89.
2012-10-22 18:06:09 +02:00
Andreas Schneider
04f1d950b9 session: Fix a possible use after free in ssh_free().
We need to cleanup the channels first cause we call ssh_channel_close()
on the channels which still require a working socket and poll context.

Thanks to sh4rm4!
2012-10-22 17:37:50 +02:00
Andreas Schneider
191c0ae2bb doc: Update copyright policy. 2012-10-14 19:58:26 +02:00
Andreas Schneider
5b32f31a31 channel: Fix a possible null pointer dereference.
(cherry picked from commit ceb8072b34)
2012-10-05 11:48:34 +02:00
Andreas Schneider
3eac8e1c18 channels: Fix a possible null pointer dereference.
(cherry picked from commit 656fd60110)
2012-10-05 11:47:35 +02:00
Andreas Schneider
dc8f0cddee getpass: Fix a memory leak in ssh_gets() on error.
(cherry picked from commit 6092596199)
2012-10-05 11:45:47 +02:00
Andreas Schneider
97b263aee9 sftp: Harden sftp_extension_supported() against null pointers.
(cherry picked from commit 22f607649d)
2012-10-05 11:45:28 +02:00
Andreas Schneider
cb53c4f0e1 sftp: Fix a memory on error in sftp_opendir().
(cherry picked from commit b5c4b090da)
2012-10-05 11:45:12 +02:00
Andreas Schneider
0d029e7038 misc: Don't leak memory on ssh_path_expand_escape() on error.
(cherry picked from commit 61d032fc03)
2012-10-05 11:44:50 +02:00
Andreas Schneider
aae725a44c session: Fix a memory leak in ssh_new() on error.
(cherry picked from commit 280ce3fe93)
2012-10-05 11:44:12 +02:00
Werner Koch
0e833d75e6 Fix regression in pre-connected socket setting.
* src/socket.c (ssh_socket_pollcallback): Factor some code out to ...
(ssh_socket_set_connecting): New.
* include/libssh/socket.h (ssh_socket_set_connecting): Add prototype.
* src/client.c (ssh_connect): Use new function for a socket set by
SSH_OPTIONS_FD.

Signed-off-by: Werner Koch <wk@gnupg.org>
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
2012-09-21 09:41:47 +02:00
Andreas Schneider
ae83f77511 build: Fix missing struct in_addr warning.
(cherry picked from commit 782b2e37c6)
2012-07-17 18:17:05 +02:00
Andreas Schneider
4d8420f328 sftp: Fix bug in sftp_mkdir not returning on error.
resolves: #84
(cherry picked from commit a92c97b2e1)
2012-07-17 18:13:03 +02:00
Andreas Schneider
d8f2a793d3 connect: Fix a build warning.
(cherry picked from commit 8b8d9dc83a)
2012-07-17 17:34:50 +02:00
rofl0r
558b53a856 session: Cleanup timeout functions and fix packets termination.
It is possible that we get unrelated packets while waiting for
termination, thus waiting indefinitely. As a workaround we have to
check the user-supplied timeout.
Also cleaned up ssh_blocking_flush, which was using the timeout in a
bogus manner (resetting the timeout after each check).
2012-01-02 12:42:47 +01:00
Andreas Schneider
0764adc82f message: Fix compiler warning.
(cherry picked from commit 2f861a858b)
2012-01-02 09:31:59 +01:00
rofl0r
87fd7d617e message: Handle all unknown global messages.
Reply to unknown global messages as required by the RFC. Therefore
keepalive@openssh.com style messages should get treated in a sane way.
2012-01-01 20:54:09 +01:00
Andreas Schneider
3e83af5f5e keyfiles: Fix build errors with callbacks.
Introduced with the last commit.
2011-09-17 22:59:13 +02:00
Aris Adamantiadis
0dc57fdcf1 Fixes the ssh_log issue on ssh_bind handles.
(cherry picked from commit da954c2c5e)

Conflicts:

	src/keyfiles.c
2011-09-17 22:01:43 +02:00
Andreas Schneider
3799670d01 doc: Fix threading documentation.
(cherry picked from commit 2cc95e1e08)
2011-09-17 21:32:43 +02:00
Aris Adamantiadis
d6390d50bf Fix documentation bug about threading
(cherry picked from commit c84380bad5)
2011-09-17 21:22:20 +02:00
Andreas Schneider
e27b31c9c4 build: Increase version number. 2011-09-16 21:56:19 +02:00
Andreas Schneider
684b7f6a57 build: Updated changelog. 2011-09-16 21:54:39 +02:00
Aris Adamantiadis
b0b2fd768c SSH1: handle exit-status message (channels would not close) 2011-09-15 11:25:11 +02:00
Aris Adamantiadis
9180bfffcd channels: don't send SSH2 packets on SSH1 ! 2011-09-15 11:25:00 +02:00
Aris Adamantiadis
058bb0f4ea SSH1: fix build
(cherry picked from commit 3eece8ac0b)

Conflicts:

	src/channels.c
	src/channels1.c
2011-09-02 23:02:27 +02:00
Aris Adamantiadis
64b125700e channels: replaced bugged lists with ssh_list
(cherry picked from commit 6d8bb956c5)

Conflicts:

	src/channels.c
	src/session.c
2011-09-02 22:59:44 +02:00
Aris Adamantiadis
6f650a61ca poll: resolve use-after-free + inconsistent callbacks call
This code was weird in the first place. I suspect my change will break something else
(probably the appcode that needed it). ssh_poll_ctx_free is not a good
place to send exception callbacks imho.
(cherry picked from commit b5351f2809)
2011-09-02 22:49:22 +02:00
Aris Adamantiadis
d4e95f4653 Channels: increase window size x10
Provides me a 3x performance boost for async sftp, 5x for sync sftp
(on localhost)
(cherry picked from commit 17ae216340)
2011-09-02 22:45:54 +02:00
Andreas Schneider
26be91fb8e channels: Fix bug #52.
(cherry picked from commit a2c94abb92)

Conflicts:
    src/channels.c
2011-09-02 22:45:50 +02:00
Aris Adamantiadis
43a3becf08 unittests:make sftp_dir pass on my laptop
(cherry picked from commit 7363b29427)
2011-09-02 22:25:26 +02:00
Aris Adamantiadis
d127d68b9f scp: Fixed documentation bug #9
(cherry picked from commit 99e6fde751)
2011-09-02 22:24:47 +02:00
rofl0r
730da3e3c2 channels: Fix possible infinite loop in channel_read().
(cherry picked from commit 66188f1af8)
2011-08-29 21:48:09 +02:00
Jonas Jonsson
661722753b sftp: Handle short reads of sftp_async_read().
sftp_async_read() and sftp_async_read_begin() assume that the whole read
will be successful but when this is not the case, the offset will be
wrong.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit d1df255df4)
2011-08-29 10:07:22 +02:00
Andreas Schneider
ac445a1e18 auth: Handle request service timeout in blocking mode.
(cherry picked from commit e5e673bafe)
2011-08-27 00:00:28 +02:00
Andreas Schneider
b7a3d41baf auth: Fix ssh_auth_list() documentation.
The server will not return SSH_AUTH_METHOD_NONE.
(cherry picked from commit 9c376dd913)
2011-08-22 15:04:09 +02:00
Andreas Schneider
096475b356 channels: Fix incorrect return values in ssh_channel_write().
(cherry picked from commit 13227714f2)
2011-08-10 18:37:58 +02:00
rofl0r
d08554dabd session: Fix an infinite loop in the termination callback.
This happened due to the use of the buggy and obsolete timeout
funtions.
(cherry picked from commit 7949f2cdc6)
2011-08-10 18:37:14 +02:00
Andreas Schneider
cbe8f8b760 channels: Handle SSH_AGAIN in channel_open().
(cherry picked from commit 2f87873642)
2011-08-09 23:08:39 +02:00
Mark Riordan
8987bc53e0 Fix "status -5 inflating zlib packet"
Signed-off-by: Mark Riordan <mriordan@ipswitch.com>
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 6c45d6dc01)
2011-08-09 20:13:41 +02:00
Andreas Schneider
39802b31fe build: Set libssh version to 0.5.1. 2011-08-09 14:47:33 +02:00
Andreas Schneider
e5a2aef1bf build: Updated ChangeLog. 2011-08-09 14:46:26 +02:00
Einar Floystad Dorum
edb03bd224 Fixed ssh_scp_write so it works when doing recursive copy
There where two issues with ssh_scp_write:
1) It did not write a status message after the last write and OpenSSH
   would then give up after the write finished.
2) OpenSSH would sometimes write a status message, after near ends write.
   If scp_write didn't handle it, and subsequent status message. The remote
   window would shrink to zero and ssh_channel_write would start returning 0.

Signed-off-by: Einar Floystad Dorum <einarfd@mailthief.com>
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 01c4b713dc)
2011-08-08 15:28:08 +02:00
rofl0r
1204f43ea9 client: Fix another source of endless wait.
(cherry picked from commit 35686b4822)
2011-08-07 12:47:23 +02:00
rofl0r
b542bc9e4e channels: Fix an endless loop in case of a channel_open error.
(cherry picked from commit 7ccd9c31b3)
2011-08-07 12:47:17 +02:00
rofl0r
61a97ccede session: Fix timeout handling.
-2 now means to use the timeout specified in options. It wasn't used
earlier and poll only knows -1 and 0 anyway for special meanings.
(cherry picked from commit af85337f5f)
2011-08-07 12:47:09 +02:00
rofl0r
a1ef27c0b8 channels: Fix checking for fatal errors.
We need this that we don't end up in and infinite poll loop.
(cherry picked from commit 563fbe4de8)

Conflicts:

	src/poll.c
2011-08-07 12:46:47 +02:00
rofl0r
fb8f2cd11b channels: Fix ssh_channel_from_local()
It only worked if the first channel in the list was equivalent to we
were looking for.
(cherry picked from commit 39f962c91e)
2011-08-07 12:46:06 +02:00
rofl0r
1d8a9ddf84 misc: Fix ssh_timeout_update().
(cherry picked from commit c31cac93f3)
2011-08-07 12:45:54 +02:00
Andreas Schneider
bea66b6476 examples: Fix permissions of the file we copy.
Thanks to Baptiste Marchand.
(cherry picked from commit 15ebbad146)
2011-08-03 22:23:51 +02:00
Andreas Schneider
a8111934d5 channels: Set the max packet size to 32768.
(cherry picked from commit 790b62bca5)
2011-08-03 22:20:52 +02:00
Aris Adamantiadis
f201e983b0 Workaround ssh_get_user_home_dir on LDAP users 2011-07-13 12:04:04 +02:00
Andreas Schneider
81332e1e27 build: Fix libssh_threads pkg-config.
(cherry picked from commit 269c9fed354f3a8adbc54fccba6287d5b1f166e3)
2011-06-15 18:26:33 +02:00
Andreas Schneider
ea84f50603 cmake: Added pkg-config support for libssh_treads.
(cherry picked from commit 583a7f933a)
2011-06-14 13:47:51 +02:00
Andreas Schneider
ccc94e7ab6 packet: Don't (de)compress empty buffers.
This fixes bug #50.
(cherry picked from commit fb0f125351)
2011-06-11 13:16:21 +02:00
Aris Adamantiadis
4c05be0c1b Fix compilation without server and sftp modes
(cherry picked from commit 809b3adeba)
2011-06-09 12:16:07 +02:00
Andreas Schneider
a493a90c59 build: Check for ntohll().
This function is available on AIX.
(cherry picked from commit 640e3830f2)
2011-06-06 18:57:50 +02:00
Andreas Schneider
4a18df8574 string: Added missing include.
(cherry picked from commit 3fa801a929)
2011-06-06 18:57:11 +02:00
Andreas Schneider
cfa74c1dc6 string: Added missing errno.
(cherry picked from commit d536cc4f39)
2011-06-06 18:51:12 +02:00
milo
de706de8c3 Check for NULL pointers in string.c
(cherry picked from commit 4230509e80)
2011-06-06 18:50:11 +02:00
Andreas Schneider
71fa0dc6bb cmake: Fix static .lib overwriting on Windows.
(cherry picked from commit 1880ef54d2)
2011-06-01 14:53:29 +02:00
Andreas Schneider
914a2d8e41 cmake: Prepare for release. 2011-05-30 12:36:54 +02:00
Andreas Schneider
956b64d348 session: Fix return code of ssh_blocking_flush().
(cherry picked from commit 3c21281bf0)
2011-05-28 18:35:21 +02:00
Aris Adamantiadis
91489cd378 remove "0.5.0 is dev" in the doc
(cherry picked from commit 3bc46c3bf0)
2011-05-27 14:20:02 +02:00
Aris Adamantiadis
615bc3b8f7 Forgot a cast to remove warnings
(cherry picked from commit ac167c9077)
2011-05-27 14:19:54 +02:00
Aris Adamantiadis
5b645419fd Fix bug #5, channel_read_nonblocking that blocks 2011-05-27 14:19:42 +02:00
Mark Riordan
c436e07022 Fix memory leak when compression is used
Signed-off-by: Mark Riordan <mriordan@ipswitch.com>
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit dcea8db6b2)
2011-05-27 11:47:26 +02:00
Andreas Schneider
188fb37801 sftp: Reset eof on seek operations.
This fixes bug #48.
(cherry picked from commit c483418b82)
2011-05-26 11:27:35 +02:00
Andreas Schneider
44fed3eb9b misc: Fix compilation on Windows.
(cherry picked from commit ba03388031)
2011-05-26 11:20:25 +02:00
Andreas Schneider
36abd82a7e cmake: Fix detection of clock_gettime. 2011-05-25 22:13:28 +02:00
Aris Adamantiadis
fd6d0b6897 Replace clock_gettime with gettimeofday when missing
(cherry picked from commit 65282841e2)
2011-05-25 22:00:00 +02:00
Aris Adamantiadis
09b0018b93 Introduced ssh_timeout_elapsed functions
Functions to mesure elapsed time before and after a serie of
calls. Introduces a dependancy to clock_gettime() and librt,
hope this doesn't break anything. Porting to gettimeofday() should
not be too hard.
(cherry picked from commit 59f7647cd9)
2011-05-25 21:59:51 +02:00
Andreas Schneider
2624e603d4 Revert "Use BIO* in _privatekey_from_file [Oliver Stöneberg]"
This reverts commit da8356b477.
2011-05-19 19:47:29 +02:00
Oliver Stöneberg
fd61eda16d keyfiles: Move FILE* into HAVE_LIBGCRYPT code.
(cherry picked from commit c7c563eb8ad01ab5750b5ea4e72031ebd298651c)
2011-05-17 21:00:02 +02:00
Oliver Stöneberg
a6dda5fefd keyfiles: Use BIO* in _privatekey_from_file().
(cherry picked from commit 82df5dc2083a6f7234d1545bd671ee1b5b4680b6)
2011-05-17 20:59:55 +02:00
Oliver Stöneberg
da8356b477 Use BIO* in _privatekey_from_file [Oliver Stöneberg]
_privatekey_from_file: moved FILE* into HAVE_LIBGCRYPT code / added missing #ifdef's to default case of switch [Oliver Stöneberg]
2011-05-17 20:57:58 +02:00
Oliver Stöneberg
e5fb20c17b socket: Fixed use-after-free.
When s->callbacks->exception() was called in ssh_socket_pollcallback()
we had a use after free bug.
(cherry picked from commit 9866763789)
2011-05-17 20:57:38 +02:00
Oliver Stöneberg
c472bd7437 keyfiles: Fixed compilation without defines.
This fixes cppcheck issues.
(cherry picked from commit 7f0761885c)
2011-05-17 20:57:38 +02:00
Oliver Stöneberg
8796756ae5 tests: Fixed some cppcheck warnings.
(cherry picked from commit e3311d03db)
2011-05-17 20:57:38 +02:00
Oliver Stöneberg
9c8f285a98 examples: Use the right cleanup functions.
(cherry picked from commit 525324b2f9)
2011-05-17 20:57:38 +02:00
Oliver Stöneberg
8154e24027 channel: Fixed potential use-after-free in ssh_channel_get_exit_status().
If ssh_channel_get_exit_status() is called more than once and the
connection closed.
(cherry picked from commit 4e153aed8a)
2011-05-17 20:57:38 +02:00
Oliver Stöneberg
629cfbccc4 connect: Set timeout on connect
This also fixes error handling in ssh_poll_ctx_dopoll() and
ssh_handle_packets(), so it won't loop forever on an actual timeout.
(cherry picked from commit 671a982739)
2011-05-17 20:57:38 +02:00
Oliver Stöneberg
c5990791db poll: Removed WSAPoll() support.
It was causing too many issues and the poll emulation is quite stable.
(cherry picked from commit f4f4ce37f0)
2011-05-17 20:57:38 +02:00
Oliver Stöneberg
16241938af doc: Small update to auth.c documentation.
(cherry picked from commit 12b61a6266)
2011-05-17 20:57:38 +02:00
Andreas Schneider
6a8cb38dd3 channel: Improve the request signal documentation.
(cherry picked from commit 32cd45612b)
2011-05-15 13:44:11 +02:00
Oliver Stöneberg
bac2227ee2 Updated privatekey_from_file() to use BIO* as well [Oliver Stöneberg] 2011-05-02 19:46:54 +02:00
Oliver Stöneberg
dcb50cc0c8 Use BIO* in _privatekey_from_file [Oliver Stöneberg]
_privatekey_from_file: moved FILE* into HAVE_LIBGCRYPT code / added missing #ifdef's to default case of switch [Oliver Stöneberg]
2011-05-02 19:17:38 +02:00
milo
f503c4a3e1 Delay the check for kbdint->answers in kbdint_send()
(cherry picked from commit 32ba5204b7)
2011-05-02 18:04:56 +02:00
milo
a56c925da9 Fix segfault when ssh_userauth_kbdint_setanswer() has not been called
(cherry picked from commit b6e712e934)
2011-05-02 17:47:00 +02:00
milo
833cc00014 [socket] fix a segfault at disconnect
(cherry picked from commit 7d2064c289)
2011-05-02 17:41:51 +02:00
milo
09e8cf33d7 [messages] don't queue messages if callback present
(cherry picked from commit 1979c14aac)
2011-05-02 17:40:05 +02:00
milo
a03bb2fbf7 [poll] avoid infinite loop in ssh_poll_ctx_free()
(cherry picked from commit 8092541603)
2011-05-02 17:39:28 +02:00
milo
bb784ec6be [channels] Added ssh_channel_window_size() and avoided reentrancy in channel_write_common()
(cherry picked from commit 7ba0938846)
2011-05-02 17:35:34 +02:00
Andreas Schneider
996c00c81c keyfiles: Fixed the build. 2011-05-01 21:04:55 +02:00
Oliver Stöneberg
30bdca07e9 init: Some initialization fixes.
- Check result of ssh_init() in privatekey_from_base64()
- Moved code from ssh_finalize() to appropriate subroutines
- Only initialize sockets once (caused mismatch of WSAStartup() and
  WSACleanup() calls and potential usage of bsd_poll when win_poll
  should be used)
2011-05-01 19:43:57 +02:00
Oliver Stöneberg
b4b49cf3f6 socket: Fixed poll input event.
(cherry picked from commit 040a543f57)
2011-05-01 19:43:01 +02:00
Oliver Stöneberg
189796e94f examples: Removed unnecessary \n from ssh_log() calls in samplessh.
(cherry picked from commit a73459171b)
2011-05-01 19:42:13 +02:00
Oliver Stöneberg
2431c7d925 examples: Fixed memory leak in samplessh when using commands.
(cherry picked from commit c3849a3cfd)
2011-05-01 19:42:01 +02:00
Andreas Schneider
fc9c61714f poll: Fix poll input events.
bug#38
2011-04-15 19:17:40 +02:00
Andreas Schneider
e096658df3 examples: Fix some memory leaks.
(cherry picked from commit 644145a88c)
2011-04-15 19:06:24 +02:00
Andreas Schneider
b1d58c5454 Fix assertion with Visual Studio because of %zu.
(cherry picked from commit ef658b4bef)
2011-04-15 19:03:02 +02:00
Mark Riordan
ced66eb11f scp: Fix potential infinite loop in ssh_scp_close
Signed-off-by: Mark Riordan <mriordan@ipswitch.com>
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 5939cfe78a)
2011-04-14 14:19:15 +02:00
Andreas Schneider
1b44daddf6 examples: Call correct functions on exit.
(cherry picked from commit 3e7d4534ce)
2011-04-14 14:19:08 +02:00
Aris Adamantiadis
a309c1b38e Fixed missing CRYPTO_cleanup_all_ex_data() in ssh_finalize
(cherry picked from commit 934252d6ca)
2011-04-14 13:40:42 +02:00
Andreas Schneider
e56aaf5f44 wrapper: Fixed a possible NULL pointer dereference.
(cherry picked from commit 94e7d345a7)
2011-04-14 10:18:37 +02:00
Andreas Schneider
632cee4426 server: Fixed a possible NULL pointer dereference.
(cherry picked from commit 7e4916cefc)
2011-04-14 10:18:34 +02:00
Oliver Stöneberg
af25fc35d1 build: Fixed some VS2010 problems.
(cherry picked from commit 166ee451c5)
2011-04-11 11:19:26 +02:00
Oliver Stöneberg
db49b84a44 keys: Fixed issues reported by cppcheck.
(cherry picked from commit 46475dfa2f)
2011-04-11 11:19:18 +02:00
Andreas Schneider
c5f4b8c1c7 cmake: Fixed a typo.
(cherry picked from commit 7150cabafa)
2011-04-08 11:06:16 +02:00
Mark Riordan
6a0daddd8f sftp: Fixed double-free in sftp_unlink().
(cherry picked from commit 29bb718a93)
2011-04-08 11:00:04 +02:00
Aris Adamantiadis
af997b221d Fixed doc of ssh_userauth_list()
(cherry picked from commit 1c062b22bf)
2011-03-28 13:36:51 +02:00
Aris Adamantiadis
9d6855702e Change session state after receiving a Disconnect
(cherry picked from commit 4bc9c96e4e)
2011-03-28 13:36:44 +02:00
Andreas Schneider
daf256e15f cpack: Raise version number. 2011-03-23 08:51:06 +01:00
Aris Adamantiadis
0eddcb4424 Fix the ssh_message_retrieve problem by anihilation 2011-03-23 08:49:34 +01:00
Aris Adamantiadis
b7f6794e03 Implement ssh_blocking_flush()
Based on code from Jan Willamowius
(cherry picked from commit dff4e4e6d3)
2011-03-23 08:49:26 +01:00
Andreas Schneider
cd9fc88151 doc: Improve the doc of ssh_bind_set_callbacks.
(cherry picked from commit 7daa81f3aa)
2011-03-09 18:33:49 +01:00
Andreas Schneider
fbe0f37e1b doc: Improved documentation for server options.
(cherry picked from commit 6754c34711)
2011-03-09 18:33:42 +01:00
Andreas Schneider
c496194614 messages: Added missing config.h include. 2011-03-01 14:08:01 +01:00
Andreas Schneider
ca639ceb63 legacy: Added missing channel_write_stderr. 2011-02-23 12:39:25 +01:00
Andreas Schneider
e85537aac4 legacy: Fixed the symbol export. 2011-02-23 12:32:02 +01:00
milo
e839c9cae6 Reverse commit 076dfb82 for the server side
(cherry picked from commit 32e23a25da)
2011-02-19 10:38:15 +01:00
Andreas Schneider
100e94c18e channel: Fixed uninitialized use of session. 2011-02-19 10:24:57 +01:00
Andreas Schneider
e7f7b4e499 server: Fixed logging function name.
(cherry picked from commit ac8276c70e)
2011-02-18 20:57:37 +01:00
Bernhard R. Link
eca8b53868 channel: Improve ssh_channel_open_reverse_forward documentation.
(cherry picked from commit 23b3c46fd6)
2011-02-18 18:01:45 +01:00
Andreas Schneider
b8767be373 channels: set error for new NULL pointer checks
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8a83990c16)
2011-02-18 18:01:45 +01:00
Bernhard R. Link
9658eade0b socket: Set errors on return.
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 071b0034db)
2011-02-18 17:54:43 +01:00
Bernhard R. Link
689536ec92 channels: Set errors on return.
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 7ae59c571a)
2011-02-18 17:54:34 +01:00
Bernhard R. Link
3ff2999228 bind: Set errors on return.
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit b1db0e54ad)
2011-02-18 17:54:28 +01:00
Andreas Schneider
4f65104ecc misc: Fixed ssh_is_ipaddr_v4() on Windows.
(cherry picked from commit eea1df3574)
2011-02-13 17:39:18 +01:00
Andreas Schneider
242e1c342c build: Try to fix the build on Solaris.
(cherry picked from commit 9baa491b0b)
2011-02-13 17:39:11 +01:00
Andreas Schneider
935e3b70ae misc: Added working ssh_is_ipaddr for Windows.
(cherry picked from commit cd30a1d4b1)
2011-02-13 12:30:52 +01:00
Andreas Schneider
8d1bfb5a85 tests: Fixed misc and isipaddr test on Windows.
(cherry picked from commit ca941d6985)
2011-02-13 12:30:46 +01:00
Andreas Schneider
2ac664968d torture: Fixed torture on Windows.
(cherry picked from commit cbcd5668f5)
2011-02-13 12:30:33 +01:00
Andreas Schneider
1199ad8f47 misc: Fixed ssh_is_ipaddr on FreeBSD.
(cherry picked from commit d1ddec00d9)
2011-02-13 12:30:17 +01:00
Bernhard R. Link
c12559f8f6 always set error when returning error in auth.c
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 637fc7ea59)
2011-02-12 20:15:07 +01:00
Andreas Schneider
840e1abcdc tests: Added ipv6 tests.
(cherry picked from commit 5d4bd5a21d)
2011-02-12 19:22:02 +01:00
Andreas Schneider
e3594ba0ec tests: Fixed torture_isipaddr.
(cherry picked from commit e8c3f55751)
2011-02-12 19:22:02 +01:00
Andreas Schneider
0d07dc5355 srv_sftp: Set error messages in sftp_get_client_message().
(cherry picked from commit 4d38b4c848)
2011-02-12 19:22:01 +01:00
Andreas Schneider
4170258595 connect: Use ssh_is_ipaddr instead of regex.
(cherry picked from commit 768fbdd92e)
2011-02-12 19:22:01 +01:00
Andreas Schneider
dacfc41d21 misc: Added ssh_is_ipaddr() function.
(cherry picked from commit b313fa944a)
2011-02-12 19:22:01 +01:00
Aris Adamantiadis
5158877b72 Connect: Test the new isipaddr() function
(cherry picked from commit 7acc2fa607)
2011-02-12 19:21:42 +01:00
Bernhard R. Link
a785ba3c4d use ssh_log instead of fprintf in ssh_config_parse_file
ssh_config_parse_file calls "fprintf(stderr," directly thus ignoring
a set log callback. Replacing the print with a call to ssh_log should
fix this.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8d9d46ca66)
2011-02-12 19:21:17 +01:00
Bernhard R. Link
92dbd4eca2 ssh_connect_host_nonblocking returns SSH_EINTR, not E_INTR, so update documentation
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8e0e4d8fb3)
2011-02-12 19:21:16 +01:00
Bernhard R. Link
a7144c5b6b proper prototypes
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8b51d29363)
2011-02-12 19:21:16 +01:00
Andreas Schneider
5a8a2a56af poll: Use WSAPoll() on Windows. 2011-02-09 00:36:16 +01:00
Andreas Schneider
d464b57fa5 Revert "poll: Remove obsolete win_poll functions."
This reverts commit c950ed3b4c.
2011-02-09 00:34:36 +01:00
Andreas Schneider
c950ed3b4c poll: Remove obsolete win_poll functions.
Thanks for the hint Milo ;)
2011-02-09 00:13:47 +01:00
Andreas Schneider
5144f390ca examples: Fixed build warning. 2011-02-08 19:36:44 +01:00
Andreas Schneider
f5e2c94ae3 torture: Fixed memory leak. 2011-02-08 19:08:27 +01:00
Andreas Schneider
8078d4f674 doc: Use fwrite for the command example. 2011-02-08 10:59:50 +01:00
Andreas Schneider
ac785e0aa3 examples: The exec example should be like tutorial one. 2011-02-08 10:54:25 +01:00
Andreas Schneider
541519e563 build: Updated the ChangeLog. 2011-02-07 18:22:34 +01:00
Andreas Schneider
58feb0c983 vim: Added .clang_complete file. 2011-02-07 17:39:06 +01:00
Andreas Schneider
72e08d5dd9 build: Added a --clang option. 2011-02-07 13:34:37 +01:00
Andreas Schneider
f812ace256 tests: Some fixes for sftp_dir. 2011-02-07 13:33:28 +01:00
Andreas Schneider
057704c097 torture: Added more test for correct auth. 2011-02-07 13:31:31 +01:00
Andreas Schneider
92f20ec85a torture: Fixed the kbdint auth. 2011-02-07 13:31:08 +01:00
Andreas Schneider
a26194ece0 torture: Rename the static auth kbdint function. 2011-02-07 13:30:23 +01:00
Andreas Schneider
22b1e5bc7c tests: Added test for sftp directory functions. 2011-02-06 16:35:54 +01:00
Andreas Schneider
38d6d38c1f torture: Added a function to setup a sftp session. 2011-02-06 16:27:43 +01:00
Andreas Schneider
215c41710e torture: Added torture_isdir(). 2011-02-06 15:35:18 +01:00
Andreas Schneider
97d261dc79 torture: Added torture_rmdirs(). 2011-02-06 15:35:18 +01:00
Andreas Schneider
892ebf35f1 torture: Added GPL header. 2011-02-06 15:34:32 +01:00
Andreas Schneider
05cd7296ba tests: Added a torture_ssh_session(). 2011-02-06 11:15:05 +01:00
Andreas Schneider
93a2d79459 session: Added ssh_is_connected(). 2011-02-06 10:50:14 +01:00
Andreas Schneider
30e4096c66 tests: Fixed missing ; 2011-02-06 08:45:37 +01:00
Andreas Schneider
03b387cf47 Revert "sftp: Added missing break's to server."
This reverts commit 131e3b968f.
2011-02-05 18:40:00 +01:00
Andreas Schneider
131e3b968f sftp: Added missing break's to server. 2011-02-05 18:24:23 +01:00
Andreas Schneider
4bf8ee8032 tests: Check fgets output. 2011-02-05 15:23:19 +01:00
Andreas Schneider
63c42f066f tests: Fixed checking return values of system(). 2011-02-05 15:23:19 +01:00
Andreas Schneider
9e40e60bc4 examples: Check return values of write. 2011-02-05 15:23:19 +01:00
Andreas Schneider
8f850585dd session: Fixed possible uninitialized return of ret. 2011-02-05 15:23:19 +01:00
Andreas Schneider
4b07157fc6 getpass: Fixed a compiler warning. 2011-02-05 15:23:19 +01:00
milo
867944b939 Respect RFC when sending stderr data
http://tools.ietf.org/html/rfc4254#section-5.2

      byte      SSH_MSG_CHANNEL_EXTENDED_DATA
      uint32    recipient channel
     *uint32    data_type_code*
      string    data
2011-02-04 12:46:51 +01:00
Andreas Schneider
b0c2be25a6 doc: Fixed the include dir. 2011-01-28 13:13:08 +01:00
Aris Adamantiadis
c1ecec7cda SSH1: Update a few fix from 0.4.8-git 2011-01-26 22:50:05 +01:00
Aris Adamantiadis
00d68d63fa Getpass: fixed loop + indentation 2011-01-26 21:49:58 +01:00
Aris Adamantiadis
5d87ca94a8 Getpass: Fix password clearing 2011-01-26 13:22:29 +01:00
Andreas Schneider
1e827a8e81 getpass: Fixed possible segfault if len is too small. 2011-01-24 17:13:35 +01:00
Andreas Schneider
20e637968a cmake: Define BSD. 2011-01-24 15:44:11 +01:00
Andreas Schneider
5c581f8a4c libsshpp: Removed unused variable. 2011-01-24 15:25:50 +01:00
Andreas Schneider
d67cbdc926 examples: Fixed compilation on Windows. 2011-01-24 15:25:50 +01:00
Andreas Schneider
a63dbc07f3 examples: Fixed knownhosts on Windows. 2011-01-24 13:55:05 +01:00
Andreas Schneider
6a3cd6c20f examples: enable exec and senddata on all plattforms. 2011-01-24 13:55:05 +01:00
Andreas Schneider
8a9ce6239a examples: Remove unused header file. 2011-01-24 13:55:05 +01:00
Andreas Schneider
f3685f0f73 examples: Use ssh_getpass(). 2011-01-24 13:55:05 +01:00
Andreas Schneider
50a119dd0a misc: Added multiplatform ssh_getpass() fuction. 2011-01-24 13:55:05 +01:00
Andreas Schneider
8abdaa7abf examples: Start to build examples on more plattforms. 2011-01-23 18:57:35 +01:00
Aris Adamantiadis
80ef7d9304 Fix problem with ssh_connect w/ timeout &fd > 1024
Convert that code to ssh_poll
(cherry picked from commit b1a65dd25f)
2011-01-22 16:55:36 +01:00
Aris Adamantiadis
84df46f805 Fix use-after-free when socket is closed in a callback handler 2011-01-19 16:01:21 +01:00
Andreas Schneider
460d43f050 cmake: Fixed ZLIB configure check. 2011-01-18 18:56:24 +01:00
Andreas Schneider
625692f4c5 cmake: Don't use cmake 2.8.3 features. 2011-01-17 09:24:57 +01:00
Aris Adamantiadis
0e2bbdd25b Fix doxygen warning 2011-01-16 23:42:19 +01:00
Aris Adamantiadis
6b52aaff1c ssh_auth_password made nonblocking 2011-01-16 23:42:19 +01:00
Aris Adamantiadis
227764a803 Made ssh_userauth_none nonblocking 2011-01-16 23:42:19 +01:00
Aris Adamantiadis
624676b1cc Made ask_userauth nonblocking 2011-01-16 23:42:19 +01:00
Andreas Schneider
a236a15c6c modules: Improved the GCrypt module. 2011-01-16 12:47:06 +01:00
Andreas Schneider
cb775092bc cmake: Fixed NSIS module. 2011-01-16 12:21:58 +01:00
Andreas Schneider
8d7d313498 cmake: Fixed ZLIB path checks. 2011-01-16 12:16:53 +01:00
Andreas Schneider
c6e1792696 cmake: Improved the NSIS module. 2011-01-16 12:12:35 +01:00
Andreas Schneider
90fc5554e1 cmake: Improved the ZLIB find module based on CMake one. 2011-01-16 11:53:37 +01:00
Andreas Schneider
e579dfb342 cmake: Fixed license header of the OpenSSL module. 2011-01-16 11:51:02 +01:00
Andreas Schneider
0c93914948 cmake: Improved FindOpenSSL based on CMake ones. 2011-01-16 11:30:24 +01:00
Aris Adamantiadis
670dd17044 Test double ssh_disconnect 2011-01-15 22:50:34 +01:00
Aris Adamantiadis
b945cbca52 Fix double-connect testcase 2011-01-15 22:43:58 +01:00
Aris Adamantiadis
f8361d324e Fix torture_connect_double so it tests the right thing 2011-01-14 14:35:44 +01:00
Aris Adamantiadis
0b46f68c5f Fixed compilation without argp.h available 2011-01-13 21:21:19 +01:00
Aris Adamantiadis
2917e71aad Replaced argp support for platforms that support it
Argp is really useful, but it's not mandatory.
2011-01-13 18:34:04 +01:00
Aris Adamantiadis
551b87b65b New testcases for nonblocking ssh_connect and double ssh_connect 2011-01-13 18:09:04 +01:00
Aris Adamantiadis
5b6f048197 Use termination functions for event polling 2011-01-12 23:04:43 +01:00
Aris Adamantiadis
a17472ff2b Fix unit tests for opensolaris 2011-01-11 17:55:12 +01:00
Aris Adamantiadis
7fbb926c0b Fix getpwuid_r on opensolaris 2011-01-11 17:55:12 +01:00
Andreas Schneider
bb5f5281c0 build: Fixed build on Windows. 2011-01-11 11:07:17 +01:00
Aris Adamantiadis
9140242cbe Non-blocking mode for ssh_connect
This looks ugly. I'll see if we need to revert or change that patch later.
2011-01-10 18:01:35 +01:00
Aris Adamantiadis
bcea8921ba Change blocking parameter to a flag 2011-01-10 17:39:47 +01:00
Aris Adamantiadis
076dfb8294 Fix connection callbacks called at wrong time 2011-01-10 12:14:26 +01:00
Aris Adamantiadis
d631ce32ed All error path consistent with ssh_packet_kexinit 2011-01-10 11:24:15 +01:00
Aris Adamantiadis
4439d5c774 Log errors with ssh_log 2011-01-10 11:23:49 +01:00
Aris Adamantiadis
ac6278feb7 Fix leak when key exchange fails. 2011-01-09 22:27:55 +01:00
Andreas Schneider
d1e1103198 examples: Improve the authenticate_kbdint function.
The function excepts a predefined password now. It will try to use it if
the prompt is a Password prompt. This works in 80% of the cases.
2011-01-08 10:18:55 +01:00
Aris Adamantiadis
4f83918109 Added interesting link 2011-01-07 13:41:10 +01:00
Andreas Schneider
6b27966c9c keys: Fixed memory leaks in session signing.
Found by cppcheck - http://test.libssh.org/cppcheck-analyzer/
2011-01-06 14:32:39 +01:00
Andreas Schneider
a016d356fa dh: Fixed a memory leak in ssh_print_hexa.
Found by cppcheck - http://test.libssh.org/cppcheck-analyzer/
2011-01-06 14:25:35 +01:00
Andreas Schneider
61852635b5 tests: Moved assert to the write place in torture_keyfiles.
Found by clang-analyzer http://test.libssh.org/clang-analyzer/
2011-01-06 11:44:02 +01:00
Andreas Schneider
184f1e1706 tests: Assert if ssh_get_random failed in torture_rand_thread.
Found by clang-analyzer http://test.libssh.org/clang-analyzer/
2011-01-06 10:15:01 +01:00
Andreas Schneider
dfa01d0862 examples: Use the src mode in scp do_copy function.
Found by clang-analyzer http://test.libssh.org/clang-analyzer/
2011-01-06 10:15:01 +01:00
Andreas Schneider
82547867eb options: Remove unsused getopt option.
Found by clang-analyzer http://test.libssh.org/clang-analyzer/
2011-01-06 10:15:01 +01:00
Andreas Schneider
7d9f889911 tests: Added missing asserts in torture_keyfiles.
Found by clang-analyzer http://test.libssh.org/clang-analyzer/
2011-01-06 10:15:01 +01:00
Andreas Schneider
13ece2a2f8 messages: Added missing NULL pointer checks.
Found by clang-analyzer http://test.libssh.org/clang-analyzer/
2011-01-06 10:04:12 +01:00
Aris Adamantiadis
e57d5a45b9 Fix the missing returns in C++ wrapper 2011-01-05 21:14:27 +01:00
Andreas Schneider
ec12da273e tests: Fixed the segfault in torture_knownhosts. 2011-01-04 23:10:01 +01:00
Aris Adamantiadis
fdffa42c02 Fix "SSH_KEXINIT received in wrong state" race
Setting the flag before doing any IO
2011-01-04 16:59:54 +01:00
Andreas Schneider
d679d5d7ef poll: Ensure that the poll handle and ctx is zeroed. 2011-01-03 09:07:02 +01:00
Andreas Schneider
2464a25de7 tests: Fixed a build warning introduced before. 2011-01-03 09:02:34 +01:00
Andreas Schneider
e12253168c tests: Call init and finalize in client torture tests. 2011-01-03 08:46:14 +01:00
Andreas Schneider
1540dad17f tests: Added more openssl valgrind suppressions. 2011-01-03 07:51:46 +01:00
Andreas Schneider
350838d1b5 messages: Fixed cast warnings on Windows. 2011-01-02 19:35:54 +01:00
Andreas Schneider
f23880ddee base64: Added casts to GET macros to fix build warnings. 2011-01-02 19:35:54 +01:00
Andreas Schneider
be3e5c35cf scp: Fixed a build warning on Windows. 2011-01-02 19:35:54 +01:00
Andreas Schneider
73c0cd050e poll: Fixed a build warning on Windows. 2011-01-02 19:35:53 +01:00
Andreas Schneider
c54d6b7f8a bind: Added include file for close function on Windows. 2011-01-02 19:35:53 +01:00
Andreas Schneider
2b6fa19fe5 cmake: Fixed msvc posix warnings and unsecure functions. 2011-01-02 19:35:53 +01:00
Aris Adamantiadis
3f538b3ddd Call ssh_init()/ssh_finalize bf/af each testcase 2011-01-02 17:25:51 +01:00
Aris Adamantiadis
2faaefade9 Revert "tests: Call ssh_init() and ssh_finalize() before we run the tests."
Reason: breaks test_rand, because threading has to be initialized
before ssh_init()

This reverts commit ef1866db76.
2011-01-02 17:15:03 +01:00
Andreas Schneider
ef1866db76 tests: Call ssh_init() and ssh_finalize() before we run the tests. 2011-01-02 09:19:53 +01:00
Andreas Schneider
d4072082d0 tests: More openssl valgrind suppressions. 2011-01-02 09:10:42 +01:00
Andreas Schneider
a7237e8cea tests: Updated the valgrind suppressions file. 2011-01-01 22:13:03 +01:00
Andreas Schneider
bc2db562e5 cmake: Added missing OpenSSL directories on Windows. 2011-01-01 20:53:55 +01:00
Andreas Schneider
93ce8e8ffd cmake: Added looking for zdll on Windows. 2011-01-01 20:53:55 +01:00
Andreas Schneider
98bacf032f tests: Added torture_auth_autopubkey client test. 2011-01-01 20:53:55 +01:00
Andreas Schneider
e795dae8f2 tests: Added a windows test for torture_path_expand_tilde. 2011-01-01 20:53:55 +01:00
Andreas Schneider
459fa3734f tests: Fixed includes for torture_list on Windows. 2011-01-01 20:53:54 +01:00
Andreas Schneider
52d6b7b914 tests: Fixed includes of torture_options for windows. 2011-01-01 20:53:54 +01:00
Andreas Schneider
5331489581 tests: Fixed the torture_callbacks test.
We should zero the structure else ssh_callback_exists() can't be
working.
2011-01-01 19:14:54 +01:00
Andreas Schneider
2945a42c75 tests: Don't run torture_keyfiles on Windows.
This test needs ssh-keygen to be working.
2011-01-01 19:14:54 +01:00
Andreas Schneider
1f47730a82 tests: Fixed Windows build of torture_options. 2011-01-01 19:14:49 +01:00
Andreas Schneider
1b88542fbe misc: Avoid redefine of _WIN32_IE. 2011-01-01 18:43:37 +01:00
Andreas Schneider
530629c5a7 cmake: Added ssl libraries for OS/2. 2010-12-31 14:55:36 +01:00
Andreas Schneider
98b5f07631 cmake: Fixed a warning on OS/2 if the compiler version is empty. 2010-12-31 14:41:50 +01:00
Andreas Schneider
f46bf41813 libssh: Don't use the visibility flag on OS/2. 2010-12-31 14:35:06 +01:00
Andreas Schneider
8e632b14d1 cmake: Fixed installation path for OS/2. 2010-12-31 14:08:20 +01:00
Andreas Schneider
4728ac54fc build: Fixed some build warnings. 2010-12-30 12:12:34 +01:00
Andreas Schneider
da86340551 cmake: Improved the ctest file. 2010-12-30 12:12:06 +01:00
Andreas Schneider
fc8fdcb16b cmake: Only use Profiling on Unix systems. 2010-12-30 11:55:13 +01:00
Andreas Schneider
be68cfe923 cmake: Fixed NSIS detection on Windows. 2010-12-30 11:17:48 +01:00
Andreas Schneider
cb48057098 threads: Fixed ssh_pthread_thread_id with mingw. 2010-12-30 00:39:07 +01:00
Andreas Schneider
ef91ac4ea0 socket: Fixed ssh_socket_fd_set prototype. 2010-12-30 00:30:44 +01:00
Andreas Schneider
1646ce970c cmake: Fixed find modules on Windows. 2010-12-30 00:26:37 +01:00
Andreas Schneider
08906e0f7f tests: It is enough to include libssh.h for torture_init. 2010-12-29 21:02:51 +01:00
Andreas Schneider
887d201bd3 server: Added missing include files for getaddrinfo on Windows. 2010-12-29 20:53:28 +01:00
Andreas Schneider
1267240810 connect: Added and improved regex for ip detection.
Thanks to Norbert Kiesel, rlo#14.
2010-12-29 20:44:07 +01:00
Andreas Schneider
296767afc4 server: Added include files for getaddrinfo. 2010-12-29 20:36:14 +01:00
Andreas Schneider
13f3679b2f tests: Fixed torture_get_user_home_dir on Windows. 2010-12-29 20:35:55 +01:00
Andreas Schneider
f3a6c3152c cmake: Don't build torture_rand on Windows. 2010-12-29 20:33:32 +01:00
Andreas Schneider
80d7ccb522 cmake: Added missing include dirs for libssh. 2010-12-29 20:18:18 +01:00
Andreas Schneider
78abf5a88d cmake: Added include and library deps to torture. 2010-12-29 20:17:36 +01:00
Andreas Schneider
ad231ccd30 cmake: Fixed test includes and libraries. 2010-12-29 20:11:00 +01:00
Andreas Schneider
d4a6c27a83 cmake: Only set profile GCC flags on UNIX systems. 2010-12-29 20:02:03 +01:00
Andreas Schneider
e7a06ad3b4 cmake: Find cmockery on Windows. 2010-12-29 19:51:46 +01:00
Andreas Schneider
d2bf90c982 build: Fixed include directories for torture lib. 2010-12-29 19:49:07 +01:00
Andreas Schneider
69ac51dfaa connect: Added missing $ in IPREGEX.
Fixes rlo#14.
2010-12-29 19:48:15 +01:00
Andreas Schneider
3e2f714248 tests: Fixed a assert bug in torture_auth. 2010-12-29 09:13:17 +01:00
Aris Adamantiadis
530c17e2ef First real benchmark : raw SSH speed 2010-12-29 00:19:05 +01:00
Aris Adamantiadis
31043334f4 Export and document timestamp functions 2010-12-29 00:19:05 +01:00
Andreas Schneider
361e37dc66 tests: Added a torture_sftp_static test. 2010-12-28 22:14:47 +01:00
Andreas Schneider
df55918a41 tests: Migrated torture_proxycommand to cmockery. 2010-12-28 22:14:47 +01:00
Andreas Schneider
e6329c72d1 tests: Migrated torture_knownhosts to cmockery. 2010-12-28 22:14:47 +01:00
Andreas Schneider
8bd29736d2 tests: Migrated torture_auth to cmockery. 2010-12-28 22:14:47 +01:00
Andreas Schneider
0b2cf70622 tests: Migrated torture_algorithms to cmockery. 2010-12-28 22:14:47 +01:00
Andreas Schneider
b0446ad55d tests: Migrated torture_rand to cmockery. 2010-12-28 22:14:47 +01:00
Andreas Schneider
d04ce30b03 tests: Migrated torture_options to cmockery. 2010-12-28 22:14:47 +01:00
Andreas Schneider
512b776245 tests: Migrated torture_misc to cmockery. 2010-12-28 22:14:47 +01:00
Andreas Schneider
d44919dfd4 tests: Migrated torture_list to cmockery. 2010-12-28 22:14:47 +01:00
Andreas Schneider
99d45c686c tests: Moved torture_knownhosts to client tests. 2010-12-28 22:14:47 +01:00
Andreas Schneider
2bc03d22a1 tests: Migrated torture_keyfiles to cmockery. 2010-12-28 22:14:47 +01:00
Andreas Schneider
fa17f33d2b tests: Migrated torture_init to cmockery. 2010-12-28 22:14:47 +01:00
Andreas Schneider
400fc350a7 tests: Migrated torture_callbacks to cmockery. 2010-12-28 22:14:47 +01:00
Andreas Schneider
6f65e6ae67 tests: Migrate torture_buffer to cmockery. 2010-12-28 22:14:47 +01:00
Andreas Schneider
635a263f64 tests: Migrate the torture library to cmockery. 2010-12-28 22:14:47 +01:00
Andreas Schneider
17f592d4dd tests: Start to migrate tests to cmockery.
https://code.google.com/p/cmockery/wiki/Cmockery_Unit_Testing_Framework
2010-12-28 22:14:47 +01:00
Aris Adamantiadis
7dc183126a Set variables in the good order 2010-12-28 13:50:34 +01:00
Aris Adamantiadis
4fe1656cf8 Moved benchmarks to the tests/ directory 2010-12-28 13:17:27 +01:00
Aris Adamantiadis
a883330101 New benchmark framework
with pluggable style benchmarks and an original SSH RTT calculator !
2010-12-28 02:19:15 +01:00
Andreas Schneider
f0d811edc6 ctest: Added more valgrind suppressions. 2010-12-28 00:38:11 +01:00
Andreas Schneider
438083542d connect: Use a better IP regex. 2010-12-28 00:24:47 +01:00
Aris Adamantiadis
4fa2e4dde1 Added compression options and allow "yes/no" setting
SSH_OPTION_COMPRESSION and SSH_OPTION_COMPRESSION_LEVEL options have been added. Now, end-level apps may simply choose to enable compression without knowing the relevant algorithms behind it.
2010-12-27 23:28:39 +01:00
Andreas Schneider
32c0e1c99a test: Added openssh checks to the compression tests. 2010-12-27 22:47:37 +01:00
Andreas Schneider
b4c62ac9ea server: Replace gethostbyname() with getaddrinfo().
Fixes rlo#13.
2010-12-27 21:51:55 +01:00
Andreas Schneider
a0e98f585a misc: Fixed a possible memory leak. 2010-12-27 18:08:30 +01:00
Andreas Schneider
7c728acd12 sftp: Fixed a memory leak in sftp_xstat.
Thanks to dsc for the bug report.
2010-12-27 17:52:24 +01:00
Andreas Schneider
38b87aab08 channels: Fixed a build warning. 2010-12-23 10:18:09 +01:00
Andreas Schneider
33c41074a7 libsshpp: Fixed return of non-void function. 2010-12-23 08:54:39 +01:00
Andreas Schneider
936c65f03e options: Remove unused variable. 2010-12-21 21:29:22 +01:00
Andreas Schneider
825581d0dc packet1: Fixed dead assignments.
Found by http://test.libssh.org/scan-build/
2010-12-21 16:29:08 +01:00
Aris Adamantiadis
942b993f57 Add log verbosity to some testcases 2010-12-21 16:21:49 +01:00
Andreas Schneider
e6bc4b4ff9 doc: Added samplessh hint to INSTALL. 2010-12-21 16:21:02 +01:00
Andreas Schneider
04e224c3b4 doc: Updated Changelog. 2010-12-21 15:51:07 +01:00
Andreas Schneider
19ab9a015f doc: Added copyright policy section. 2010-12-21 15:40:36 +01:00
Andreas Schneider
94fe52870b doc: Update README. 2010-12-21 15:24:38 +01:00
Andreas Schneider
55470aaaf1 doc: Remove the note. 2010-12-21 15:13:18 +01:00
Andreas Schneider
6a26335158 doc: Some fixes for linking howto. 2010-12-21 15:07:42 +01:00
Andreas Schneider
256e88690d doc: Make the warning bold. 2010-12-21 15:03:13 +01:00
Andreas Schneider
3a94c94f20 doc: More linking details. 2010-12-21 14:55:39 +01:00
Andreas Schneider
473d3e0b3a ctest: Set the suppression file correctly. 2010-12-21 14:43:14 +01:00
Andreas Schneider
d5df18a14f build: Fixed build warning on FreeBSD. 2010-12-20 15:49:29 +01:00
Andreas Schneider
bffaa86664 build: Fixed some build warnings on FreeBSD. 2010-12-20 15:45:49 +01:00
Aris Adamantiadis
1922341e2a New benchmarks directory 2010-12-19 18:56:16 +01:00
Andreas Schneider
bcfab67daf ctest: Set the memcheck suppression file correctly. 2010-12-19 16:30:23 +01:00
Andreas Schneider
27f170011e ctest: Set suppression file only in CTestConfig. 2010-12-19 12:54:52 +01:00
Andreas Schneider
5cb4c9451f ctest: Make sure we have a clean source tree for each build. 2010-12-19 12:54:52 +01:00
Aris Adamantiadis
80408d5357 Fixed memory leak reported by valgrind 2010-12-19 12:37:21 +01:00
Aris Adamantiadis
47d11734e1 Fix free() on uninitialized data on some cases. 2010-12-19 12:33:31 +01:00
Andreas Schneider
14d6b8856f example: Fixed gcc warning. 2010-12-18 14:05:06 +01:00
Andreas Schneider
48e4df4ac0 TODO server: Fixed server support. 2010-12-18 14:02:53 +01:00
Andreas Schneider
f5d0f232c8 ctest: Fixed git URL. 2010-12-18 12:15:14 +01:00
Andreas Schneider
d6a5e5cb68 test: Fixed the default ctest file. 2010-12-15 19:15:02 +01:00
Andreas Schneider
751f202f56 doc: Follow the current naming convention. 2010-12-10 20:28:59 +01:00
Andreas Schneider
37eeb854e4 doc: Started to write a linking howto. 2010-12-10 20:17:57 +01:00
Andreas Schneider
57d752a1c3 include: Only require LIBSSH_STATIC on Windows. 2010-12-10 20:02:15 +01:00
Andreas Schneider
ef1cfbea70 build: Use the same name for static and shared library. 2010-12-10 20:00:23 +01:00
Andreas Schneider
038c764055 server: Remove channel_write_stderr. 2010-12-08 10:52:15 +01:00
Andreas Schneider
3ea33f9ab6 doc: Some small fixes in server.h. 2010-12-07 21:43:26 +01:00
Andreas Schneider
1758c172a2 doc: Fixed pki doc group. 2010-12-07 21:28:50 +01:00
Andreas Schneider
2a6cbed121 doc: Define a doc group for the callbacks. 2010-12-07 21:25:53 +01:00
Andreas Schneider
92fc2d6993 doc: Added buzzword. 2010-12-07 20:59:08 +01:00
Aris Adamantiadis
2dba4839ad Fix from Oleksandr Shneyder
http://www.libssh.org/archive/libssh/2010-11/0000005.html
2010-12-07 16:13:40 +01:00
Andreas Schneider
0825abd03a doc: Fixed doc namespace to be able to install manpages. 2010-12-05 10:53:39 +01:00
Aris Adamantiadis
f58441f474 Moved declarations from auth.h to various headers 2010-10-30 22:38:09 +02:00
Aris Adamantiadis
0e82cdeadc Moved includes from priv.h to bind.h 2010-10-27 23:06:38 +02:00
Aris Adamantiadis
b6901ec4b9 Fix senddata.c for 32bits machines 2010-10-27 22:53:20 +02:00
Aris Adamantiadis
ea4aa26dbb Split ssh_bind functions in a new .c file 2010-10-20 16:54:22 +02:00
Aris Adamantiadis
98221f4e36 Fixed a bunch of smallish bugs
http://linuxtesting.org/upstream-tracker/test_results/libssh/current/test_results.html
for a whole list
2010-10-20 14:47:11 +02:00
Aris Adamantiadis
8e2699e161 start of work to have callbackbased ssh_bind 2010-10-19 23:51:32 +02:00
Andreas Schneider
01eb20e13f cmake: Fixed a problem with ccache. 2010-10-19 11:50:29 +02:00
Aris Adamantiadis
b129181809 Adapt comments in options to give parameters types 2010-10-15 16:53:18 +02:00
Aris Adamantiadis
3253ece2a2 Oops, libssh.h did not compile anymore 2010-10-15 16:43:38 +02:00
Aris Adamantiadis
4b462449cf Fix OPTIONS_BINDADDR, PROXYCOMMAND constant change 2010-10-14 11:53:30 +02:00
Aris Adamantiadis
4f8907a524 Removed the global poll ctx in fav. of /session ctx 2010-10-12 17:57:15 +02:00
Aris Adamantiadis
7b1359042c Add zlib@openssh.com on the list of compression 2010-10-04 16:23:43 +02:00
Aris Adamantiadis
da9cd2e64d Implemented zlib@openssh.com compression 2010-10-04 16:19:20 +02:00
Aris Adamantiadis
5d1636985b Resolved the server blocked bug 2010-10-03 21:36:03 +02:00
Aris Adamantiadis
088b86d4fe Fix doxygen warnings 2010-10-03 16:16:30 +02:00
Aris Adamantiadis
9a89fba332 resolve memory consumption bug 2010-10-03 13:31:02 +02:00
Aris Adamantiadis
0bc032726d Fix prepend bug 2010-10-03 13:01:21 +02:00
Aris Adamantiadis
b2f571e544 test the buffer_prepend_data function 2010-10-03 12:25:33 +02:00
Aris Adamantiadis
338a3d9b05 Removed references to ssh_buffer_get_begin 2010-10-03 12:07:00 +02:00
Aris Adamantiadis
5687d6e79a Added buffer test case 2010-10-03 12:06:47 +02:00
Aris Adamantiadis
a9ec8b055f Fix warnings on testcases 2010-10-02 23:27:26 +02:00
Aris Adamantiadis
5f69d494ad Fix documentation of ssh_set_message_callback 2010-10-02 23:24:19 +02:00
milo
3d8cfa9973 Don't grow window if there is no space in the buffer 2010-10-02 22:55:53 +02:00
Aris Adamantiadis
0d5cc01f1c Fix the window not growing problem
Fix conflict with patch from milo
Conflicts:

	src/channels.c
2010-10-02 22:54:59 +02:00
milo
d7581c4daa Change path to ../src instead of the old ../libssh 2010-10-02 22:52:24 +02:00
milo
524302ca7e Added ssh_channel_write_stderr() for the server 2010-10-02 22:52:06 +02:00
milo
2617024136 Added channel features on the server
- ssh_channel_request_send_exit_status()
- ssh_channel_request_send_exit_signal()

- enhanced these features client-side
2010-10-02 22:51:49 +02:00
milo
26d40b5354 Handle global requests and reverse forwarding 2010-10-02 22:51:35 +02:00
milo
c4356531f7 Add new callbacks in session and channels 2010-10-02 22:51:14 +02:00
Aris Adamantiadis
873e02fc6a First step getting rid of ssh_buffer_get_begin 2010-10-01 23:41:04 +02:00
Aris Adamantiadis
985db35173 Rewrote channel_read_buffer to use ssh_channel_read 2010-10-01 23:03:08 +02:00
Aris Adamantiadis
c4e67730a3 Convert sftp.c to ssh_channel_read 2010-10-01 21:41:56 +02:00
Aris Adamantiadis
9f7e2c3252 Update the window *after* effective read 2010-10-01 18:56:57 +02:00
Aris Adamantiadis
5675fbe73e Fix the behaviour of channel window handling 2010-10-01 18:38:08 +02:00
Aris Adamantiadis
5b1c985a0e Changed the threads cbks from struct to publ func 2010-09-30 11:10:08 +02:00
Aris Adamantiadis
bedc65313f Removed the extern char *environ 2010-09-30 10:42:55 +02:00
Aris Adamantiadis
9f53906209 Remove extern environ from the requirements 2010-09-29 17:06:54 +02:00
Andreas Schneider
be837cdbc2 misc: Fixed a typo. 2010-09-29 14:19:07 +02:00
Andreas Schneider
38359672a5 misc: Make sure ssh_analyze_banner has proper length checks. 2010-09-29 12:12:14 +02:00
Andreas Schneider
1b471256d4 misc: Differentiate between client and server in ssh_analyze_banner. 2010-09-29 12:11:43 +02:00
Andreas Schneider
30e22fed6e misc: Fixed a possible data overread and crash bug. 2010-09-29 11:29:37 +02:00
Andreas Schneider
8b719e51cf misc: Move ssh_analyze_banner to a common location.
Don't duplicate functions!
2010-09-29 11:26:35 +02:00
Andreas Schneider
72b62d3064 build: Fixed the unit test build. 2010-09-29 11:26:16 +02:00
Andreas Schneider
5f24a84298 known_hosts: Added missing include.
Thanks miloj ;)
2010-09-29 11:17:46 +02:00
Andreas Schneider
1eaf55c5f6 keyfiles: Fixed unlink warning. 2010-09-28 19:16:42 +02:00
Andreas Schneider
9d3b84c914 threads: Fixed windows build.
MSVC isn't C99.
2010-09-28 19:12:01 +02:00
Andreas Schneider
b391a7603a pki: Create a file for known_hosts functions. 2010-09-28 19:09:29 +02:00
Andreas Schneider
45b551d4f7 build: Remove unneeded include directories. 2010-09-28 19:08:11 +02:00
Andreas Schneider
15e4ec38f2 pki: Added GPL to header file. 2010-09-28 19:07:16 +02:00
Andreas Schneider
8c318fcb21 keyfiles: Fixed the windows defines. 2010-09-28 19:06:49 +02:00
Andreas Schneider
a2fe4b2b2c options: Rename HOSTKEYCHECK to STRICTHOSTKEYCHECK.
Looks like people are confused by the name and think this is normal host
key checking.
2010-09-28 14:13:18 +02:00
Andreas Schneider
e36c9c529b options: Fixed documentation of SSH_OPTIONS_HOSTKEYCHECK. 2010-09-28 14:10:15 +02:00
Aris Adamantiadis
41c4e1f5c8 Completed senddata example to exit someday 2010-09-26 23:11:07 +02:00
Aris Adamantiadis
75a0281a6b Fixed outgoing flow control + writes behaviours 2010-09-26 22:33:58 +02:00
Vic Lee
a92545517a socket.c: Fixed setting max_fd which breaks ssh_select().
Signed-off-by: Andreas Schneider <asn@cynapses.org>
2010-09-20 19:22:19 +02:00
Andreas Schneider
fe31fcaeef pki: Fixed a possible crash. 2010-09-18 20:59:29 +02:00
Aris Adamantiadis
f7ea9a3f27 Added documentation for threading 2010-09-12 22:34:38 +02:00
Aris Adamantiadis
b0c03280d1 ssh_threads_init is private 2010-09-12 22:01:21 +02:00
Aris Adamantiadis
5eb7c7b6ec Added initialisation logs for threading 2010-09-12 21:53:42 +02:00
Aris Adamantiadis
b7af2b2959 Changed callbacks type 2010-09-12 21:45:53 +02:00
Andreas Schneider
9f02a817ff build: Added -pedantic-errors. 2010-09-10 21:46:36 +02:00
Andreas Schneider
6345afabf8 build: Remove unneeded debug message. 2010-09-09 20:09:44 +02:00
Aris Adamantiadis
899db7cf22 Fix #ifdef'ed erroneous debug code in buffer.c 2010-09-09 10:01:29 +02:00
Andreas Schneider
f45dc29eb2 build: Improve pthread detection. 2010-09-08 16:51:55 +02:00
Andreas Schneider
d2f38da094 build: Make sure LIBSSH_THREADS_LINK_LIBRARIES is in the cache. 2010-09-08 16:43:55 +02:00
Andreas Schneider
697d51cd93 build: Make sure to link against all required thread libraries. 2010-09-08 16:32:54 +02:00
Andreas Schneider
f9b0dca7bd build: Fixed options parsing. 2010-09-08 16:29:50 +02:00
Andreas Schneider
03087e020c build: Improve the check for argp. 2010-09-08 11:41:14 +02:00
Andreas Schneider
4f75fdcd14 build: There is no need to check for system libraries on Linux. 2010-09-08 11:20:10 +02:00
Andreas Schneider
031c06419b build: Added DefinePlatformDefaults cmake file. 2010-09-08 11:20:10 +02:00
Andreas Schneider
254a08f540 build: Cleanup DefineCompilerFlags. 2010-09-08 11:20:10 +02:00
Andreas Schneider
76ead916ce build: Fixed linking against libssh in thread library. 2010-09-08 10:50:06 +02:00
Andreas Schneider
ab2dafc44a socket: Make code easier to read and debug. 2010-09-07 18:50:38 +02:00
Andreas Schneider
325cc4e395 session: Fixed a memory leak with session->bindaddr. 2010-09-07 17:30:10 +02:00
Andreas Schneider
c1604eff08 misc: Fixed a memory leak. 2010-09-07 17:26:07 +02:00
Andreas Schneider
77b52a5e69 doc: Added links to the RFCs. 2010-09-07 10:27:46 +02:00
Andreas Schneider
d414c4f500 doc: Fixed doxygen config. 2010-09-07 09:55:15 +02:00
Éric Bischoff
398bc769ce doc: More work on the tutorial. 2010-09-07 09:54:42 +02:00
Aris Adamantiadis
49f57a8d0d Implemented the noop and native pointers 2010-09-06 16:52:14 +02:00
Andreas Schneider
fbe102bada threads: Build a libssh threading library. 2010-09-06 15:17:03 +02:00
Aris Adamantiadis
2cca490076 Moved pthread specific code in src/threads/pthread.c
pthread example doesn't compile du to the lack of
libssh_threads_native.so library
2010-09-06 14:51:01 +02:00
Andreas Schneider
f7842e3a4b misc: Rename libssh/ to src/ 2010-09-06 14:28:38 +02:00
Éric Bischoff
38421403d2 doc: Some corrections for shell execution. 2010-09-06 11:03:00 +02:00
Andreas Schneider
461dde231c build: Fixed a wrong if statement. 2010-09-05 13:11:19 +02:00
Andreas Schneider
0785c522f0 build: Fixed build with gcc 3.4.
The -fvisibility=hidden flag is broken in gcc 3.4. This fixes the build
on CentOS, bug #74.
2010-09-05 12:56:01 +02:00
Andreas Schneider
2656c6b4ac server: Fixed a shadowed variable. 2010-09-05 12:34:12 +02:00
Andreas Schneider
ed5ebe7458 tests: Fixed cmdline parsing. 2010-09-05 12:34:12 +02:00
Andreas Schneider
d71d6afa34 tests: Disable options parsing if argp isn't available. 2010-09-03 15:44:41 +02:00
Andreas Schneider
2f8f230f61 build: Added support to find argp on BSD. 2010-09-03 15:38:12 +02:00
Aris Adamantiadis
285388409f Made pthread threading a user macro 2010-09-03 12:03:04 +02:00
Andreas Schneider
aff5786ed3 thread: Fixed detection of thread libraries on Windows. 2010-09-02 12:31:59 +02:00
Andreas Schneider
f97928c740 build: Fixed checking for printf function on Windows. 2010-09-02 11:50:21 +02:00
Andreas Schneider
bca73b8340 poll: Fixed the Windows build on Vista and newer. 2010-09-01 23:31:24 +02:00
Aris Adamantiadis
e67d834156 Fix initialization of threading 2010-09-01 16:05:06 +02:00
Andreas Schneider
a93f2d8bfe build: Fixed pthread detection. 2010-09-01 15:15:17 +02:00
Aris Adamantiadis
8c55294ea9 Openssl implementation of threading + default imp 2010-09-01 14:07:45 +02:00
Aris Adamantiadis
50d8d75d89 some more work on threading but not complete yet 2010-08-31 16:49:55 +02:00
Aris Adamantiadis
bcc2d8474c Begin of a solution for threading 2010-08-30 23:44:03 +02:00
Aris Adamantiadis
e34da1b94d Added "fix" for libgcrypt threading, ...
... but it doesn't seem to work. This is however the recommanded
way of initializing threading :
http://lists.gnupg.org/pipermail/gcrypt-devel/2009-February/001452.html
2010-08-30 14:39:35 +02:00
Aris Adamantiadis
717eff71dd Added test for the openssl threading 2010-08-30 14:08:07 +02:00
Éric Bischoff
ad95cbc542 doc: Added documentation for tunnels. 2010-08-29 16:25:31 +02:00
Aris Adamantiadis
b30aff6d4d Mark channel_read_buffer as deprecated in doxygen 2010-08-29 00:12:01 +02:00
Aris Adamantiadis
bf9a82ad9a Limit the size of packets in ssh_channel_write* 2010-08-28 23:59:18 +02:00
Aris Adamantiadis
c1efcd28f5 Fixes bug #99
returns error when no cryptographic context is available
2010-08-28 23:35:59 +02:00
Aris Adamantiadis
1fa9409554 ssh_channel_forward_* -> ssh_forward_*
Fixes bug #108
2010-08-28 23:31:07 +02:00
Aris Adamantiadis
adcd2e38e9 libsshpp: do not use deprecated functions 2010-08-28 22:53:18 +02:00
Aris Adamantiadis
c19fb5656b Fixed missing libsshpp methods 2010-08-28 22:51:23 +02:00
Aris Adamantiadis
74939b8b8d Added missing /** in doxygen @}'s 2010-08-28 21:32:08 +02:00
Aris Adamantiadis
29a229724b Fix a few documentation issues 2010-08-28 21:05:24 +02:00
Aris Adamantiadis
a9fafc32a8 Near to end of implementation of the C++ wrapper 2010-08-28 13:59:24 +02:00
Andreas Schneider
2de227a88b doc: Fixed section names. 2010-08-27 16:22:38 +02:00
Éric Bischoff
31ad140d20 doc: More work on the tutorial. 2010-08-27 16:20:17 +02:00
Aris Adamantiadis
bcf4e56fe0 Fix C++ documentation about the exceptions 2010-08-27 12:01:42 +02:00
Aris Adamantiadis
1834ca3820 Added a SSH_NO_CPP_EXCEPTIONS mode to libsshpp.h 2010-08-27 11:53:38 +02:00
Andreas Schneider
ad4a4120b7 doc: Add more details to the mainpage. 2010-08-27 11:45:13 +02:00
Andreas Schneider
0800f7ba56 doc: Added a newline on the mainpage. 2010-08-27 11:33:43 +02:00
Andreas Schneider
36576babe8 doc: Document the server responses. 2010-08-27 11:27:42 +02:00
Éric Bischoff
ba9f5b7d95 doc: Improved the tutorial. 2010-08-27 11:11:08 +02:00
Andreas Schneider
11a5383604 poll: Fixed the ssh_poll_(init/cleanup) functions. 2010-08-25 23:11:54 +02:00
Andreas Schneider
d991606493 poll: Fixed the usage of WSAPoll() on Windows.
This should fix ticket #101.
2010-08-25 23:11:54 +02:00
Aris Adamantiadis
14048354d5 Fix conflicts/ missing /** */ in doxygen 2010-08-23 21:21:57 +02:00
Eric Bischoff
94b689e19d New update of doxygen documentation 2010-08-23 21:00:35 +02:00
Aris Adamantiadis
8066100f53 Doxygen fixes 2010-08-23 20:48:30 +02:00
Aris Adamantiadis
f60c22628a lot of C++ wrapper work 2010-08-23 20:34:17 +02:00
Aris Adamantiadis
53e608cbc4 Changed SSH_SUCCESS to SSH_OK 2010-08-20 13:01:12 +02:00
Aris Adamantiadis
d10e73ffd7 Fixed "@deprecated" in doxygen 2010-08-20 13:00:10 +02:00
Aris Adamantiadis
1e75841036 Obsoletes ssh_auth_list, comment ssh_userauth_list 2010-08-19 19:51:18 +02:00
Eric Bischoff
32bf28e7ef doc: Improve the tutorial. 2010-08-19 15:06:38 +02:00
Aris Adamantiadis
fd5aeba117 Change SOversion to 4.2.0 instead of 5.0.0 2010-08-18 23:18:57 +02:00
Milo Jhoran
24b524040b server: Added an API entry for the message callback.
Signed-off-by: Andreas Schneider <asn@cynapses.org>
2010-08-13 11:17:18 +02:00
milo
e533c3f33b server: Fix missing socket close notification.
Signed-off-by: Andreas Schneider <asn@cynapses.org>
2010-08-13 11:17:09 +02:00
Aris Adamantiadis
41ab19e1d0 Log Proxycommand command executed 2010-08-10 14:32:03 +02:00
Andreas Schneider
77475bdd55 misc: Added %p for port to ssh_path_expand_escape(). 2010-08-10 11:10:26 +02:00
Milo Jhoran
0c70e80d47 Fix typos in port forwarding (server side) 2010-08-10 00:49:24 +02:00
Andreas Schneider
5aa4592f0c example: Fixed build of samplesshd. 2010-08-10 00:32:51 +02:00
milo
855b73de87 server: Split ssh_bind_accept and create ssh_handle_key_exchange.
Signed-off-by: Andreas Schneider <asn@cynapses.org>
2010-08-10 00:30:25 +02:00
Aris Adamantiadis
136f4d3b0d Removed unnecessary headers in samplesshd 2010-08-09 22:08:43 +02:00
Aris Adamantiadis
714edcb8d9 Moved content from deprecated.c to legacy.c 2010-08-09 22:05:33 +02:00
Andreas Schneider
a6b6a61775 server: Make ssh_accept a depreacted function to not break the API. 2010-08-09 21:39:32 +02:00
Andreas Schneider
39c9a6dfed server: Merge ssh_bind_accept. 2010-08-09 21:28:47 +02:00
Andreas Schneider
561df8d9a2 server: Rename ssh_accept to ssh_bind_accept. 2010-08-09 20:54:43 +02:00
milo
48a20a6137 example: Fixed the sample ssh server implementation.
Signed-off-by: Andreas Schneider <asn@cynapses.org>
2010-08-09 20:54:40 +02:00
milo
8ef0fbc294 server: Fixed the server implementation.
Signed-off-by: Andreas Schneider <asn@cynapses.org>
2010-08-09 20:54:32 +02:00
milo
51a21823f9 server: Added a define to set the server status.
Signed-off-by: Andreas Schneider <asn@cynapses.org>
2010-08-09 20:54:28 +02:00
milo
7a68331fcd messages: Make sure we pop the message at the beginning.
Signed-off-by: Andreas Schneider <asn@cynapses.org>
2010-08-09 20:54:23 +02:00
milo
d896d6393b wrapper: Added a log message if client kex is empty.
Signed-off-by: Andreas Schneider <asn@cynapses.org>
2010-08-09 20:54:17 +02:00
milo
6d531ed0a6 session: Set needed poll events for handling packets.
Signed-off-by: Andreas Schneider <asn@cynapses.org>
2010-08-09 20:54:13 +02:00
milo
06df7c1b31 socket: Make sure we only transmit data if we have some.
Signed-off-by: Andreas Schneider <asn@cynapses.org>
2010-08-09 20:54:06 +02:00
milo
2b108483ce pcap: Zero the pcap structure.
Signed-off-by: Andreas Schneider <asn@cynapses.org>
2010-08-09 20:54:01 +02:00
milo
23c745d335 kex: Fixed initialization of server kex.
Signed-off-by: Andreas Schneider <asn@cynapses.org>
2010-08-09 20:53:56 +02:00
milo
eb361626cb session: Added callback for the connection per session.
Signed-off-by: Andreas Schneider <asn@cynapses.org>
2010-08-09 20:53:49 +02:00
milo
b0f8ca556b session: Fixed the type of the session dh_handshake_state.
Signed-off-by: Andreas Schneider <asn@cynapses.org>
2010-08-09 20:53:03 +02:00
Andreas Schneider
e41e28744f build: Added a check for NSIS. 2010-08-03 18:13:59 +02:00
Andreas Schneider
e862f04527 build: Set a default zlib search path for windows. 2010-08-03 18:13:59 +02:00
Andreas Schneider
42519db55d build: Set a default openssl search path for windows. 2010-08-03 18:13:59 +02:00
Andreas Schneider
019cb77b84 build: Don't test for big endian on Windows.
Visual Studio 2010 has problems running the test.
2010-08-03 18:13:59 +02:00
Andreas Schneider
296f6a9217 build: Fixed the Windows preprocessor macros and defines. 2010-08-03 18:13:59 +02:00
Aris Adamantiadis
d688ed2553 Begining of zlib@openssh.org implementation 2010-07-23 16:49:28 +02:00
Aris Adamantiadis
b4c0b03694 Added the client unit testing information 2010-07-23 11:04:09 +02:00
Aris Adamantiadis
e721c122d3 Continue removing old flushing code 2010-07-23 11:01:06 +02:00
Aris Adamantiadis
8cd0d0040e Removed obsolete socket functions 2010-07-23 08:27:05 +02:00
Aris Adamantiadis
e5542b027b State error in server.c 2010-07-23 08:18:37 +02:00
Aris Adamantiadis
5aa9cf2fcf Add consistency check to ssh_set_callbacks 2010-07-23 08:09:57 +02:00
Aris Adamantiadis
a924869096 Receive and send SSH_MSG_UNIMPLEMENTED 2010-07-18 00:39:51 +02:00
Aris Adamantiadis
8c08b062d0 Fixed channel opening failures (infinite loop) 2010-07-17 23:51:15 +02:00
Aris Adamantiadis
96b06e8bb4 Fixed keepalive problem on older openssh servers
Conflicts:

	libssh/channels.c
2010-07-16 23:16:04 +02:00
Aris Adamantiadis
a8efffa969 New example for port forwarding
Conflicts:

	examples/CMakeLists.txt
2010-07-16 23:14:47 +02:00
Andreas Schneider
ef0215fcf2 poll: Added poll constants for Windows.
WSAPoll uses different constanst values as the POSIX implementation,
what else ...
2010-07-09 09:49:21 +02:00
Andreas Schneider
82beeea619 options: Added option to bind a client to an ip address.
Thanks to Donatello Boccaforno <donatello.boccaforno@gmail.com>.
2010-07-07 12:43:50 +02:00
Aris Adamantiadis
a18a3813fb Removed dead code in socket.c 2010-07-07 10:19:47 +02:00
Andreas Schneider
b8180f4069 poll: FD_SETSIZE is only for the count value of FD_SET on Windows. 2010-07-06 00:41:00 +02:00
Aris Adamantiadis
94b00cc762 Add ssh_callbacks_exists internal macro + unittest
(first commit with eclipse helios, crossing fingers ...)
2010-06-25 16:19:19 +02:00
Andreas Schneider
e4701e7c86 poll: Another attempt to get bsd_poll() working correctly. 2010-06-24 09:19:34 +02:00
Andreas Schneider
fc625b8a8e poll: Fixed building with poll-emulation on UNIX. 2010-06-24 09:19:26 +02:00
Andreas Schneider
703f125882 agent: Use the our poll typedef. 2010-06-24 09:19:10 +02:00
Andreas Schneider
4581b24b48 poll: Added a comment to the bsd_poll() implementation. 2010-06-22 14:44:35 +02:00
Andreas Schneider
1d84821d93 poll: Handle FD_SETSIZE in bsd_poll(). 2010-06-22 14:44:24 +02:00
Andreas Schneider
07f607ec4c poll: Fixed a comparsion. 2010-06-22 14:43:48 +02:00
Aris Adamantiadis
c3833c6c03 Fix threadsafety issue in zlib code 2010-06-22 12:42:13 +02:00
Aris Adamantiadis
65008e2d3c Fixes leak reports in valgrind 2010-06-21 15:47:34 +02:00
Andreas Schneider
d33a97b663 poll: Fixed a typo. 2010-06-21 15:41:18 +02:00
Andreas Schneider
6f9fea7fd5 poll: Check if maxfd has been set. 2010-06-20 21:18:46 +02:00
Andreas Schneider
c8d978f4e9 ctest: Update config file for new cdash board. 2010-06-20 10:29:25 +02:00
Andreas Schneider
558f889aae Fixed more fd checks. 2010-06-17 13:47:29 +02:00
Andreas Schneider
937268eb3e torture: Fixed fd check. 2010-06-17 13:38:13 +02:00
Andreas Schneider
8be7ece1f5 client: Fixed fd checks. 2010-06-17 13:37:42 +02:00
Andreas Schneider
6127da58f2 server: Fixed types and checks of fd's. 2010-06-17 13:29:14 +02:00
Andreas Schneider
15e4e7e9da poll: Fixed type of the fd variables and use SSH_INVALID_SOCKET. 2010-06-17 13:25:45 +02:00
Andreas Schneider
d484d4e129 channel: Fixed the type of the max fd variable in ssh_channel_select(). 2010-06-17 13:23:03 +02:00
Andreas Schneider
985019ab64 agent: Use ssh_poll in agent code. 2010-06-17 13:21:22 +02:00
Andreas Schneider
870c9a7a08 socket: Rename INVALID_SOCKET_T to SSH_INVALID_SOCKET. 2010-06-17 13:19:24 +02:00
Andreas Schneider
2a6341c08c socket: Fixed checks for max fd. 2010-06-17 13:13:35 +02:00
Andreas Schneider
78e7873e92 socket: Fixed prototype of ssh_socket_pollcallback(). 2010-06-17 13:09:58 +02:00
Andreas Schneider
7ecec3eb94 poll: Fixed brackets. 2010-06-17 12:01:27 +02:00
Andreas Schneider
f4facc4e10 poll: Fixed another wrong invalid fd check in bsd_poll. 2010-06-17 11:47:39 +02:00
Andreas Schneider
edffc2a291 poll: Some code cleanup for easier debugging. 2010-06-17 11:19:05 +02:00
Andreas Schneider
c30a25e64c poll: Fixed a malfunction with wrong max fd value check. 2010-06-17 11:16:24 +02:00
Andreas Schneider
b9a9f54c45 string: Added a function to delete a char basesd stirng object. 2010-06-11 11:05:37 +02:00
Andreas Schneider
f57d2c3277 build: Fixed building without zlib. 2010-06-11 10:43:02 +02:00
Andreas Schneider
11a1ae59f4 tests: Moved proxycommand test to client tests. 2010-06-03 16:55:45 +02:00
Andreas Schneider
cd1129b9b8 config: Use ssh log and error functions for problems. 2010-06-03 16:45:23 +02:00
Andreas Schneider
216cabc563 tests: Move getpwuid_r to a setup function. 2010-06-03 16:44:47 +02:00
Andreas Schneider
5dd4f7604f tests: Move client tests to a seperate directory.
Tests which require a running sshd should go to tests/client.
2010-06-03 12:36:00 +02:00
Andreas Schneider
94ce1ea451 tests: Fixed the misc torture test. 2010-06-03 12:29:32 +02:00
Andreas Schneider
f3697a0d5c keyfiles: Move the auth callback inside the HAVE_LIBGCRYPT ifdef. 2010-06-03 12:29:31 +02:00
Andreas Schneider
8f0d40a1dd cpp: Fixed return value of userauthAutopubkey. 2010-06-02 10:01:46 +02:00
Andreas Schneider
a138a52021 doc: Fixed ssh_path_expand_tilde documentation. 2010-06-01 23:11:00 +02:00
Andreas Schneider
518a9b8d8c doc: Group the poll functions and add a description. 2010-06-01 23:10:01 +02:00
Andreas Schneider
64ae0525cf socket: According to execle(2) environ shouldn't be const. 2010-06-01 21:50:03 +02:00
Aris Adamantiadis
dc88a937f0 Fix warning for snprintf 2010-05-31 11:19:27 +02:00
Aris Adamantiadis
ac93e2aea7 Fix unclean null termination in ~ expending 2010-05-31 11:19:10 +02:00
Andreas Schneider
560e938038 misc: Move size check down in ssh_path_expand_escape(). 2010-05-31 09:17:54 +02:00
Andreas Schneider
2a5d71971c misc: Make sure the expanded string is null-terminated. 2010-05-30 10:59:47 +02:00
Andreas Schneider
a59e65336d session: Fixed setting up default identity files. 2010-05-28 10:46:50 +02:00
Andreas Schneider
55ef7bc012 options: Make sure that we have always have default options set. 2010-05-21 10:23:19 +02:00
Andreas Schneider
d3f1d094f7 options: Set the local username if still not set. 2010-05-21 10:22:27 +02:00
Andreas Schneider
421fb2a829 keyfiles: Fixed possible problem with known_hosts path. 2010-05-21 10:08:26 +02:00
Aris Adamantiadis
517e58d3dc Fixed keyboard-interactive and unit test 2010-05-19 14:07:40 +02:00
Aris Adamantiadis
0eaa650e32 Fix authentication test 2010-05-19 11:13:47 +02:00
Aris Adamantiadis
4fbe572c02 Added verbosity flag for unit tests 2010-05-18 23:02:41 +02:00
Aris Adamantiadis
7c0ce909ed Added unit test for kbdint and password auth.
The kbdint test still doesn't pass
2010-05-18 22:49:22 +02:00
Aris Adamantiadis
f95157297e Factorize all the main functions in unit tests 2010-05-18 22:25:06 +02:00
Aris Adamantiadis
89993dd757 Fixed unittest name 2010-05-18 22:11:41 +02:00
Andreas Schneider
75e7c30594 cmake: Fixed doxygen. 2010-05-18 00:33:58 +02:00
Andreas Schneider
5032a9f13c doxygen: Fixed latex pdf generation. 2010-05-18 00:33:44 +02:00
Andreas Schneider
4f34062623 sftp: Fixed sftp_chown. 2010-05-17 23:37:11 +02:00
Andreas Schneider
255f5bd73f Install missing legacy header file. 2010-05-17 23:36:39 +02:00
Aris Adamantiadis
0ec847bbe7 Added some other junk test file 2010-05-17 20:08:11 +02:00
Aris Adamantiadis
08bc076a0a New sample that writes a lot of data on channel 2010-05-17 20:08:10 +02:00
Aris Adamantiadis
2c014256f7 Fix sftp_rename on sftp3 2010-05-17 20:08:10 +02:00
Andreas Schneider
488e822c8d poll: Added a cleanup function to free the ws2_32 library. 2010-05-17 11:19:31 +02:00
Aris Adamantiadis
2234c115f2 Separation work between openssl and libgcrypt 2010-05-14 01:22:22 +02:00
Aris Adamantiadis
b23b3f1d99 Sanitize libssh namespace + legacy wrappers 2010-05-14 00:51:08 +02:00
Andreas Schneider
46b249f5ce connect: Fixed signedness warnings from MSVC. 2010-05-12 21:01:18 +02:00
Andreas Schneider
b1b42aeb9c win: Added missing includes with newer MSCV. 2010-05-12 21:01:18 +02:00
Andreas Schneider
56c867edfa connect: Don't shadow errno. 2010-05-12 20:30:52 +02:00
Andreas Schneider
40c1a7e91f connect: Make sure that we use float values for the status. 2010-05-12 20:27:15 +02:00
Andreas Schneider
9739dae794 proxycommand: check the return values of pipe(). 2010-05-12 19:29:13 +02:00
Andreas Schneider
81793de030 Fixed building libssh with DEBUG_CRYPTO. 2010-05-12 19:24:22 +02:00
Andreas Schneider
a5157e69b1 Increment the soversion number. 2010-05-12 19:01:25 +02:00
Andreas Schneider
101a65378c Merge branch 'look' 2010-05-12 18:42:20 +02:00
Andreas Schneider
91ef298e7d Added runtime detection of WSAPoll().
Signed-off-by: Andreas Schneider <mail@cynapses.org>
2010-05-12 18:22:09 +02:00
Andreas Schneider
739234afb9 Added the possibility to define _OPENSSL_DIR and _ZLIB_DIR. 2010-05-12 13:55:32 +02:00
Andreas Schneider
4ecefb5017 Fixed linking errors on Windows. 2010-05-12 13:53:25 +02:00
Andreas Schneider
444008aabc Fixed build of ssh_lowercase and ssh_hostport on Windows. 2010-05-12 13:47:28 +02:00
Andreas Schneider
45857bc606 Fixed windows include files in pcap support. 2010-05-12 13:39:44 +02:00
Andreas Schneider
da9b2e25f6 Fixed Windows build warnings. 2010-05-12 13:08:45 +02:00
Andreas Schneider
fc508f9494 Fixed Windows build. 2010-05-12 12:46:50 +02:00
Andreas Schneider
3573bd4d87 Use the new expand functions. 2010-05-11 09:40:33 +02:00
Andreas Schneider
c7ee14e786 Added a torture test for ssh_path_expand_escape(). 2010-05-11 02:10:55 +02:00
Andreas Schneider
fac56bae32 Added a function to expand an escaped string. 2010-05-11 02:10:55 +02:00
Andreas Schneider
c5c1698cde Added a torture test for ssh_path_expand_tilde(). 2010-05-11 02:10:55 +02:00
Andreas Schneider
4df7daec82 Added a function to expand the tilde from a path. 2010-05-11 02:10:55 +02:00
Aris Adamantiadis
26d04ff037 Fix style in ssh_poll_ctx_dopoll
Also do a rescan of polled events when a poll object has been deleted.
2010-05-10 23:19:39 +02:00
Aris Adamantiadis
5713481838 Fix options copy 2010-05-10 22:46:20 +02:00
Aris Adamantiadis
74c9c1afa9 Added code to test proxycommand
Conflicts:

	examples/sample.c
2010-05-10 22:44:06 +02:00
Aris Adamantiadis
e159f04df8 make compression not mandatory in options_getopt 2010-05-10 22:17:29 +02:00
Aris Adamantiadis
4a21b6f168 Some grammarnazi things + fix int->socket_t 2010-05-10 22:01:09 +02:00
Aris Adamantiadis
fe16cce405 Fix crash in testcase proxycommand 2010-05-10 21:50:03 +02:00
Andreas Schneider
8ba02b6f4c Use configure checks to define vsnprintf and strncpy. 2010-05-10 15:32:17 +02:00
Andreas Schneider
f5191ec222 Added configure checks for _vsnprintf_s and strncpy. 2010-05-10 15:27:40 +02:00
Andreas Schneider
144126789c Added configure checks for vsnprintf and _vsnprintf. 2010-05-10 15:24:52 +02:00
Andreas Schneider
8dcfc9849e Fixed building libssh with VC9. 2010-05-10 14:40:00 +02:00
Andreas Schneider
b28fb6654c Fixed a MSVC build error. 2010-05-10 13:18:16 +02:00
Aris Adamantiadis
9294c3284c Changed test name + test with invalid proxycommand 2010-05-10 11:08:32 +02:00
Andreas Schneider
9278dc0666 Added more defines to use secure VC functions. 2010-05-10 10:41:47 +02:00
Aris Adamantiadis
af519d73ae Fix doc and actually make the test run :) 2010-05-09 01:05:12 +02:00
Aris Adamantiadis
3a326793fd Test case for proxycommand 2010-05-09 00:54:37 +02:00
Aris Adamantiadis
f31a14b793 ssh_socket support for 2 fd + Proxyhost command 2010-05-09 00:48:10 +02:00
Aris Adamantiadis
7886326aa8 Fix u_int_x_t -> uint_x_t 2010-05-08 22:23:05 +02:00
Aris Adamantiadis
31cc03f8e6 added test for ntohll 2010-05-08 22:22:06 +02:00
Aris Adamantiadis
cf7449c525 Added tests for ssh_dirname and ssh_basename 2010-05-08 22:13:35 +02:00
Aris Adamantiadis
b0cdbf5b22 Added test for zlib compression method
Unfortunately the test doesn't pass. (my host doesn't support zlib, only zlib@openssh.com)
2010-05-07 13:51:10 +02:00
Aris Adamantiadis
231e378157 Added torture_algorithms test case
tests for all supported cipher types
2010-05-07 13:39:38 +02:00
Aris Adamantiadis
431d8fe7c7 The actual init test 2010-05-07 13:39:08 +02:00
Aris Adamantiadis
9ee4d6c697 Added torture_ssh_init unit test 2010-05-07 13:16:42 +02:00
Aris Adamantiadis
3f14d7a54a More detailed tests 2010-05-05 14:57:47 +02:00
Aris Adamantiadis
52acb3fcac Make unit test spit libssh error messages 2010-05-05 14:26:30 +02:00
Aris Adamantiadis
a8d08a9478 Fixed a typo in tutorial 2010-05-03 21:15:24 +02:00
Aris Adamantiadis
c691aa3e32 Forgot the pki files 2010-05-02 00:03:06 +02:00
Aris Adamantiadis
430e570629 Added pki.[ch] files as a new standard API for PKs
Right now it's just a wrapper to the existing calls
but soon it's gona be the effective implementation and
other calls will be wrappers.
2010-05-01 20:32:27 +02:00
Aris Adamantiadis
65dc4f1186 Match hashed [host]:port format knownhosts 2010-05-01 16:52:46 +02:00
Aris Adamantiadis
6b320a00a0 knownhosts writing and unit test 2010-05-01 12:47:44 +02:00
Aris Adamantiadis
22be109956 First implementation of known_hosts with port read 2010-05-01 00:40:10 +02:00
Aris Adamantiadis
4bb790fb5d Fix uninitialized variable used 2010-04-28 20:22:05 +02:00
Aris Adamantiadis
7d32ec5d28 Fix warnings found with clang analyzer 2010-04-28 19:36:39 +02:00
Aris Adamantiadis
20e7ec96ae Fix bugs found by clang analyzer 2010-04-28 18:43:41 +02:00
Aris Adamantiadis
2e563e0fa8 Fix documentation of MacroCheckCCompilerFlagSSP 2010-04-28 18:31:07 +02:00
Aris Adamantiadis
cbd0a8f4b5 Change the test file for stackprotector for clang
Now compiles with clang !
2010-04-28 18:01:15 +02:00
Aris Adamantiadis
ecbe577be3 Fixed warnings with clang 2010-04-28 17:23:47 +02:00
Aris Adamantiadis
84db436e3b Fix doc and libgcrypt build 2010-04-28 12:48:47 +02:00
Aris Adamantiadis
904c6ed853 Renamed private type TYPE_RSA to SSH_KEYTYPE_*
Also made this enum public
2010-04-28 12:14:03 +02:00
Aris Adamantiadis
186e07b415 Added ssh_privatekey_type public function 2010-04-28 11:51:42 +02:00
Aris Adamantiadis
4ab63d3d8c Added first unittest-based bug found :) 2010-04-27 23:48:54 +02:00
Aris Adamantiadis
696ef7aecc Added privatekey_from_file with passphrase test 2010-04-27 23:48:18 +02:00
Aris Adamantiadis
9603f2520b make torture_keyfiles silent 2010-04-27 23:28:18 +02:00
Aris Adamantiadis
a5a806f7ee Added test for privatekey_from_file 2010-04-27 23:25:21 +02:00
Aris Adamantiadis
fa294e8603 Fix select loop in sample 2010-04-24 23:22:00 +02:00
Aris Adamantiadis
97d2f755c4 Do not send twice ssh_userauth_none requests
Thanks to Xi Wang for the bug report
2010-04-24 23:01:18 +02:00
Aris Adamantiadis
83536ab7d1 Fixes \r in SSH1 banner
Thanks to Xi Wang for the patch
WARNING: this may cause backward compatibility
issues with SSH1, revert if there are problems
2010-04-24 22:47:34 +02:00
Aris Adamantiadis
6cdbc01208 Fixes infinite loops
Thanks to Xi Wang for the patches
2010-04-24 22:46:19 +02:00
Andreas Schneider
833903e8ec torture: Fix compiling options test if NSS_BUFLEN_PASSWD isn't defined.
Thanks to Xi Wang for the patch.
2010-04-20 13:30:07 +02:00
Andreas Schneider
c53383a316 session: Fixed a memory leak.
Thanks to Xi Wang for the patch.
2010-04-20 13:29:50 +02:00
Andreas Schneider
dfc35699ea packet: Fixed linking if we build without server support.
Thanks to Xi Wang for the patch.
2010-04-20 13:28:54 +02:00
Andreas Schneider
b7a7c816df kex: Fixed a memory leak.
Thanks to Xi Wang for the patch.
2010-04-20 13:28:12 +02:00
Andreas Schneider
090f036205 channels: Don't use signal as a name.
Thanks to Xi Wang for the patch.
2010-04-20 13:27:12 +02:00
Andreas Schneider
8738e93dc0 cmake: Fixed openssl detection.
Thanks to Xi Wang for the patch.
2010-04-20 13:25:46 +02:00
Aris Adamantiadis
ee2bee88ee Fix warnings 2010-04-14 21:20:42 +02:00
Aris Adamantiadis
6ffd38d25e Fix doublefree happening after a negociation error
Fix the cherry-pick merge
Conflicts:

	libssh/client.c
2010-04-14 21:14:32 +02:00
Aris Adamantiadis
250273cf1a Do not compile aes*-ctr with <=OpenSSL 0.9.7b 2010-04-14 21:11:29 +02:00
Aris Adamantiadis
bc15f7b7aa Fix missing string_data() in crypto debug code 2010-04-14 21:11:19 +02:00
Aris Adamantiadis
7c3040c624 First experiment at trying to make libssh c89 2010-04-07 13:20:30 +02:00
Andreas Schneider
c584b55488 Added the copyright policy to the README. 2010-04-07 11:29:47 +02:00
Ruben Garcia Azuara
5a2abd34ce Added support for StrictHostKeyChecking and UserKnownHostsFile parameters.
Added OpenSSH parameters to libssh:
  - StrictHostKeyChecking
  - UserKnownHostsFile

This parameters are useful to avoid checking the fingerprint. Eg:

~/.ssh/config:
    Host 192.10.20.30
    StrictHostKeyChecking no
    UserKnownHostsFile /dev/null

Signed-off-by: Ruben Garcia Azuara <rubenga@tid.es>
Signed-off-by: Andreas Schneider <mail@cynapses.org>
2010-04-07 11:29:47 +02:00
Ruben Garcia Azuara
14eb593af3 Fixed solaris compilation warning and ignore case at host parameter.
- Suppress compilation warning in solaris caused by a comma at the end of
    the last value.
  - Ignore case at host parameter in config file

Signed-off-by: Ruben Garcia Azuara <rubenga@tid.es>
Signed-off-by: Andreas Schneider <mail@cynapses.org>
2010-04-07 11:29:47 +02:00
Aris Adamantiadis
b2b7bc3b77 Fix building on win32/vs7 2010-04-06 23:24:25 +02:00
Andreas Schneider
fddbf1f94c Added a select(2) based poll-emulation if poll(2) is not available. 2010-04-04 17:38:50 +02:00
Andreas Schneider
5d5f6cc60c Fixed the group of the pcap functions. 2010-04-04 17:38:50 +02:00
Andreas Schneider
ae64c19f20 Fixed the group of the server functions. 2010-04-04 17:38:50 +02:00
Andreas Schneider
e5abc065aa Fixed the documentation of the scp functions. 2010-04-04 17:37:05 +02:00
Andreas Schneider
4ce265b105 Fixed the documentation of the SSH messages. 2010-04-04 17:37:05 +02:00
Andreas Schneider
154e99f2ba Fixed the documentation of channels.c. 2010-04-04 17:37:05 +02:00
Andreas Schneider
dab450be32 Fixed the doxygen group of the libssh c++ wrapper. 2010-04-04 17:37:05 +02:00
Andreas Schneider
a3db621899 Fixed documentation of socket functions. 2010-04-04 15:51:54 +02:00
Andreas Schneider
e26c6d20fe Fixed documenation of ssh_select(). 2010-04-04 15:51:54 +02:00
Andreas Schneider
a75a2bf533 Fixed documentation of dh functions. 2010-04-04 15:51:54 +02:00
Andreas Schneider
8dcfc3c94a Fixed the documentation of the client code. 2010-04-04 15:51:54 +02:00
Andreas Schneider
19c4027194 Fixed the group of the options. 2010-04-04 15:51:54 +02:00
Andreas Schneider
0efd50df26 Fixed the documentation of key functions. 2010-04-04 15:51:54 +02:00
Andreas Schneider
a127c8827a Fixed the documentation of log.c 2010-04-04 15:51:54 +02:00
Andreas Schneider
dcb5a81735 Fixed the documentation of misc.c 2010-04-04 15:51:54 +02:00
Andreas Schneider
4abdf47923 Fixed the documentation of error.c 2010-04-04 15:51:54 +02:00
Andreas Schneider
d39dce85b4 Fixed the documentation of buffer.c 2010-04-04 15:51:54 +02:00
Andreas Schneider
e736725d35 Fixed the documentation of auth.c 2010-04-04 15:51:54 +02:00
Andreas Schneider
d61a699543 Removed the unneeded dependency to doxygen. 2010-04-04 15:51:54 +02:00
Andreas Schneider
320b6c0cd8 Added an improved version of UseDoxygen.cmake which handles trac doc. 2010-04-04 14:10:10 +02:00
Andreas Schneider
7cf05075a0 Added a doxygen configuration for trac. 2010-04-04 14:10:00 +02:00
Andreas Schneider
3e0959fa1b Fixed config parsing wich has overwritten user specified values. 2010-04-04 14:03:44 +02:00
Andreas Schneider
d87b29b678 Fixed Check cmake module. 2010-03-29 23:20:59 +02:00
Andreas Schneider
2c16a3c0e8 Fixed ZLIB cmake module. 2010-03-29 23:20:43 +02:00
Andreas Schneider
dc3d9bb2ab Fixed GCrypt find module. 2010-03-29 23:20:22 +02:00
Andreas Schneider
fd4ed3909e Fixed OpenSSL find module. 2010-03-29 23:14:04 +02:00
Andreas Schneider
3f29a3d4fa Fixed a build warning in sftp. 2010-03-29 23:13:39 +02:00
Andreas Schneider
1a894b65d4 Fixed build warning in the sshd example. 2010-03-29 22:47:22 +02:00
Andreas Schneider
6e82193175 Fixed build warnings of the scp example. 2010-03-29 22:46:03 +02:00
Andreas Schneider
32ac1e04ec Fixed build warnings of the ssh client example. 2010-03-29 22:44:20 +02:00
Andreas Schneider
a47a9ecad1 Fixed build warnings in the knownhosts example. 2010-03-29 22:38:38 +02:00
Andreas Schneider
d07aef725e Fixed build warnings in the exec example. 2010-03-29 22:38:21 +02:00
Andreas Schneider
b5eb08ad09 Fixed the torture_keyfiles test. 2010-03-28 23:46:56 +02:00
Aris Adamantiadis
3ce7d7a28c Workaround for check linkage on ubuntu amd64 2010-03-28 23:17:13 +02:00
Aris Adamantiadis
9da13d4ff8 Fixes the broken algorithm choice for server 2010-03-28 21:59:11 +02:00
Aris Adamantiadis
7d49e49e74 Fix crash when no callback is defined 2010-03-28 21:58:59 +02:00
Andreas Schneider
0689304cff Fixed build warnings on Windows. 2010-03-25 16:48:30 +01:00
Andreas Schneider
8dd4972fda Fixed a build warning. 2010-03-25 15:30:56 +01:00
Andreas Schneider
51436cc3a3 Fixed a build warning in ssh_userauth_autopubkey. 2010-03-25 15:30:23 +01:00
Andreas Schneider
b168b8f03f Fixed a typo that we don't export all symbols. 2010-03-25 14:04:13 +01:00
Andreas Schneider
9e9e7e95ee Fixed spelling. 2010-03-25 13:46:09 +01:00
Andreas Schneider
c805f0cdcb Fix revision. 2010-03-25 13:42:30 +01:00
Andreas Schneider
e4bbba2b15 Added comments to the so version to increment it correctly in future. 2010-03-25 13:26:37 +01:00
Andreas Schneider
3a5af7fb61 Build examples only on the Linux plattform. 2010-03-17 10:12:03 +01:00
Andreas Schneider
34f2d50e29 Require check if testing is enabled. 2010-03-15 16:09:16 +01:00
Andreas Schneider
40d0ca7963 Added options for memcheck and coverage.
Disable it by default as only one machine should do this.
2010-03-15 16:09:05 +01:00
Andreas Schneider
095f348172 Added a ctest script for nightly builds. 2010-03-13 21:17:59 +01:00
Andreas Schneider
67c062e45e Added a valgrind suppression file to ignore check errors. 2010-03-13 17:10:53 +01:00
Andreas Schneider
4516e7bdcb Fixed a memory leak in the torture_get_user_home_dir test. 2010-03-13 16:59:26 +01:00
Andreas Schneider
90d72c214e Fixed the torture_pubkey_generate_from_privkey test. 2010-03-13 16:51:52 +01:00
Andreas Schneider
8fd6c8bc02 Fixed a memory leak in keyfile torture test. 2010-03-13 16:38:43 +01:00
Andreas Schneider
863cd6fcba Added a CTestConfig file to be able to submit to the dashboard. 2010-03-13 14:59:29 +01:00
Andreas Schneider
38fda265e8 Fixed a memory leak in ssh_try_publickey_from_file. 2010-03-13 14:59:02 +01:00
Andreas Schneider
72058bfbcc Added tests for ssh options. 2010-03-13 14:21:23 +01:00
Andreas Schneider
74e23a7fa2 Added missing SSH_OPTIONS_FD option. 2010-03-13 14:21:01 +01:00
Andreas Schneider
6372f671ed Remove support for SSHv1 Cipher variable. 2010-03-12 19:01:50 +01:00
Andreas Schneider
8501ca2ea0 Added some tests for ssh_list. 2010-03-06 12:55:56 +01:00
Andreas Schneider
1264557f0e Added a test for keyfiles.c. 2010-03-04 20:41:21 +01:00
Andreas Schneider
f34cd24f80 Fixed and added support for several identity files. 2010-03-04 20:41:17 +01:00
Andreas Schneider
9cd5e97596 Fixed linking of the tests. 2010-03-04 20:08:04 +01:00
Andreas Schneider
9f59be3224 Rename ssh_list_add to ssh_list_append. 2010-03-04 20:08:04 +01:00
Andreas Schneider
dea644bbd6 Added a prepend function for ssh_list. 2010-03-04 20:08:04 +01:00
Andreas Schneider
8bcb835aa4 Fixed unit testing. 2010-03-02 23:49:21 +01:00
Andreas Schneider
eec3532955 Simplify the build option output. 2010-03-02 23:37:49 +01:00
Andreas Schneider
8424c7a747 Fixed sftp_parse_longname() on Windows.
There is no strndup function on Windows.
2010-03-02 14:15:20 +01:00
Andreas Schneider
464176d511 Added unit testing support using check. 2010-03-02 13:54:14 +01:00
Aris Adamantiadis
e8a1d135e2 Fix a race condition bug in ssh_scp_close()
Conflicts:

	libssh/scp.c
2010-03-01 20:00:02 +01:00
Aris Adamantiadis
b707b5e2a4 Answer to openssh's keepalives 2010-03-01 18:54:52 +01:00
Aris Adamantiadis
c987fd8c53 renamed ssh_list_get_head to ssh_list_pop_head 2010-03-01 18:11:40 +01:00
Aris Adamantiadis
d083554dff Fixed documentation in scp code 2010-02-26 18:48:38 +01:00
Andreas Schneider
ec3af2c5cb Added printout of owner and group in the sftp example. 2010-02-24 00:27:02 +01:00
Andreas Schneider
f857d4aff7 Fixed longname parsing, this only workings with readdir. 2010-02-24 00:26:51 +01:00
Andreas Schneider
39d6ef884a Added owner and group information in sftp attributes.
Parse the longname which is the output of 'ls -l' and set the owner and
group if we are talking to an openssh server.
2010-02-23 22:50:43 +01:00
Andreas Schneider
492d1f24c8 Set CFLAGS correctly. 2010-02-13 12:47:28 +01:00
Aris Adamantiadis
60e5a32d27 Small doc fix 2010-02-12 23:29:24 +01:00
Aris Adamantiadis
f8d0055503 More C++ work 2010-02-12 22:17:50 +01:00
Aris Adamantiadis
8baaf64a72 Fix compilation of opensolaris 2010-02-12 10:08:54 +01:00
Andreas Schneider
6ae69e0df0 Try zlib compression and fallback to none if not available. 2010-02-11 23:27:25 +01:00
Aris Adamantiadis
92ca76721a More C++ wrapper work.
Wrote stubs of functions needed in the wrapper
Created an Exception class which greatly simplifies
the use of libssh in C++
2010-02-11 23:08:07 +01:00
Aris Adamantiadis
6af2e3fc10 Fix closesocket() portbug for win32 2010-02-11 22:42:28 +01:00
Aris Adamantiadis
9bec3ee48e Use closesocket in server.c for win32
Resolves #56
2010-02-11 19:56:23 +01:00
Aris Adamantiadis
17ca9d9da7 Make better error messages for SSH1 errors 2010-02-10 18:20:21 +01:00
Aris Adamantiadis
c1711243f0 aes192-ctr and aes256-ctr working on libcrypto 2010-02-09 22:29:43 +01:00
Aris Adamantiadis
fdfd12716e aes128-ctr aes192-ctr aes256-ctr for libgcrypt 2010-02-09 22:24:04 +01:00
Aris Adamantiadis
dc0d945f28 Added aes128-ctr support for libcrypto (openssl) 2010-02-09 21:21:11 +01:00
Aris Adamantiadis
96465a52ee KEX bug: client preference should be prioritary 2010-02-09 21:20:17 +01:00
Aris Adamantiadis
512fa6e601 Added summary of build options in Cmake 2010-02-08 16:55:03 +01:00
Andreas Schneider
12d43e2967 Rename the libssh sftp documentation group. 2010-02-07 22:36:03 +01:00
Andreas Schneider
e8648416b8 Describe the main group a bit. 2010-02-07 22:36:03 +01:00
Andreas Schneider
b971834d10 Respect known_hosts file set by the user.
Thanks to contact@leblanc-simon.eu for the patch.
2010-02-07 22:35:38 +01:00
Andreas Schneider
94ee9effe6 Improve the SSH string documentation. 2010-02-07 21:50:38 +01:00
Aris Adamantiadis
81bc13e066 Expend macros in doxygen generation 2010-02-06 23:49:41 +01:00
Andreas Schneider
1297da380e Improve the session documentation. 2010-02-05 18:34:39 +01:00
Andreas Schneider
4ee3b28ecb Update the doxygen config. 2010-02-05 18:34:13 +01:00
Andreas Schneider
757f8a6323 Set the soversion to 4.1 as we didn't break something.
yet?
2010-02-05 12:34:20 +01:00
Andreas Schneider
a25b06ecfc Increase version number. 2010-02-05 12:07:50 +01:00
Aris Adamantiadis
6b703b8d6a Update c++ prototypes 2010-02-02 18:30:26 +01:00
Aris Adamantiadis
c97d0d1220 add missing leave_function() 2010-02-02 18:20:23 +01:00
Aris Adamantiadis
7520d9c7b9 Handle timeout correctly 2010-02-02 18:16:46 +01:00
Vic Lee
2577214517 The ssh_message object needs to be freed after processing in channel_accept().
Signed-off-by: Vic Lee <llyzs@163.com>
Signed-off-by: Andreas Schneider <mail@cynapses.org>
2010-02-01 17:26:50 +01:00
Aris Adamantiadis
8e7bd43016 Fix compilation without WITH_SSH1 2010-01-30 20:36:00 +01:00
Aris Adamantiadis
e7b74c57f3 Hacked SSH1 to get past authentication
Also resolved some bugs that may impact 0.4. need to check
2010-01-25 23:23:01 +01:00
Aris Adamantiadis
cfdd4296a8 Fix poll not waking up on connect on win32
Under windows, poll does not detect connected socket using
POLLOUT but POLLWRNORM.
"Pending connect requests are indicated in the returned revents member of WSAPOLLFD structure by POLLWRNORM."
http://msdn.microsoft.com/en-us/library/ms741669%28VS.85%29.aspx
However, I did not test that fix. (no windows at hands). I also don't know
if the poll emulation layer works with that too.
2010-01-25 19:48:38 +01:00
Aris Adamantiadis
3407509ed7 Correctly handle channel failures and chan states 2010-01-24 23:03:56 +01:00
Aris Adamantiadis
3ac62dda51 Made packet handlers independant of session buffer 2010-01-24 22:43:52 +01:00
Aris Adamantiadis
3465b592e7 Few function name changes 2010-01-24 22:30:43 +01:00
Aris Adamantiadis
ca499a5495 Made ssh_packet_read asynchronous
Normally that's all that was needed into making SSH1 compliant
with the new API.
Beware, I have only implemented it, not actually tested it.
2010-01-24 22:27:44 +01:00
Aris Adamantiadis
8a1d832f80 Removed last calls to packet_read 2010-01-24 22:08:20 +01:00
Aris Adamantiadis
758df26582 Made parts of SSH asynchronous (inc kex1) 2010-01-24 21:03:03 +01:00
Aris Adamantiadis
6ae558b541 Beginning of async solution for SSH1 2010-01-24 01:07:08 +01:00
Aris Adamantiadis
68f53540df Move SSH-1 specific packet functions in packet1.c 2010-01-23 22:59:10 +01:00
Aris Adamantiadis
48ba9c9bc1 stub of C++ wrapper for libssh 2010-01-21 21:54:20 +01:00
Aris Adamantiadis
245deb2abe Fixed error message when connection failed 2010-01-16 18:47:32 +01:00
Aris Adamantiadis
549ea0d7ba Fix SSH1 related warning 2010-01-16 18:38:49 +01:00
Aris Adamantiadis
94d1112c55 SSH-1 cleanup and compile
Not tested, probably not working correctly yet
2010-01-10 21:05:46 +01:00
Aris Adamantiadis
0c47227144 Fix typo in build_make script 2010-01-10 20:07:37 +01:00
Aris Adamantiadis
a2505078da Set socket blocking after connexion 2010-01-08 23:28:55 +01:00
Aris Adamantiadis
35532a63fe Enforce NULL ptr verification in scp.c 2010-01-08 23:14:10 +01:00
Aris Adamantiadis
514ab6eed2 Fixed blocking bug in channel_poll 2010-01-08 23:05:10 +01:00
Aris Adamantiadis
c41e3a8e68 Cosmetics for packet numbering 2010-01-08 22:49:16 +01:00
Aris Adamantiadis
7d71340241 Oops, forgot the callback for server DH 2010-01-08 22:37:18 +01:00
Aris Adamantiadis
40bcc0bed8 No more packet_read2() ! 2010-01-08 22:33:58 +01:00
Aris Adamantiadis
74009e2be5 Prefix message_new with ssh_ 2010-01-08 22:28:40 +01:00
Aris Adamantiadis
40871ab1cc Prefix message_handle_channel_request with ssh_ 2010-01-08 22:27:16 +01:00
Aris Adamantiadis
2fc4c7e335 Dequeue the processed messages 2010-01-08 22:25:26 +01:00
Aris Adamantiadis
da8263b3f6 Renamed message_queue to ssh_message_queue 2010-01-08 22:16:00 +01:00
Aris Adamantiadis
12db7c4bc1 Merged the channel_request hdlrs and clean hdlrs 2010-01-08 22:14:31 +01:00
Aris Adamantiadis
db3ef37771 ssh_packet_userauth_request with new system 2010-01-08 21:09:40 +01:00
Aris Adamantiadis
7f32558e08 Converted message handlers to new system 2010-01-07 22:41:38 +01:00
Aris Adamantiadis
228ac78397 Changes to messages for async message handling 2010-01-07 22:02:21 +01:00
Aris Adamantiadis
b6656a1525 Removed packet_wait for SSH2 2010-01-06 22:53:10 +01:00
Aris Adamantiadis
84ec17964e Made the server DH asynchronous.
It still needs testing and cleanup, it was done with less
care than the client-side.
The socket listening and connexion is still synchronous
2010-01-06 22:49:40 +01:00
Aris Adamantiadis
ef5dc6cd2b Add support for async global requests
Normally the infamous packet_wait() synchronous call
is gone in all SSH2 client code.
2010-01-06 21:48:44 +01:00
Aris Adamantiadis
84e6aca5c5 Fixed typos from a* to error.c 2010-01-06 21:12:00 +01:00
Aris Adamantiadis
ebd0987376 Fix build when WITH_SSH1 undefined 2010-01-06 13:34:56 +01:00
Aris Adamantiadis
20baf4f5b6 Part of kex.c is SSH-1 specific 2010-01-03 23:38:37 +01:00
Aris Adamantiadis
335a0fe768 Remove some references to packet_wait() 2010-01-03 23:36:06 +01:00
Aris Adamantiadis
b25ebf4bdb Removed channel_handle now unused function 2010-01-03 23:23:56 +01:00
Aris Adamantiadis
804bb44eda Channel requests are asynchronous
Exec example also runs perfectly now.
2010-01-03 23:16:14 +01:00
Aris Adamantiadis
1b15896e8b Fix infinite loop in exec example 2010-01-03 23:15:55 +01:00
Aris Adamantiadis
055fbe1d87 Explicitely use the packet buffer arg in channels 2010-01-03 22:34:48 +01:00
Aris Adamantiadis
648e5d62ba Some work for async channel requests 2010-01-03 22:14:21 +01:00
Andreas Schneider
49de20aa5c Fixed cmake warning.
There is no CMakeLists.txt in tests and we don't build something
in the root CMakeLists.txt.
2009-12-30 19:08:03 +01:00
Vic Lee
13d534e89a Add pkg-config file libssh.pc
Signed-off-by: Vic Lee <llyzs@163.com>
Signed-off-by: Andreas Schneider <mail@cynapses.org>
2009-12-30 19:05:48 +01:00
Vic Lee
1944dc8b5f Add new API function ssh_userauth_privatekey_file().
Signed-off-by: Vic Lee <llyzs@163.com>
Signed-off-by: Andreas Schneider <mail@cynapses.org>
2009-12-30 19:05:37 +01:00
Vic Lee
f2ca2d50b5 In ssh_userauth_pubkey, if publickey argument is NULL, generate it from privatekey.
Signed-off-by: Vic Lee <llyzs@163.com>
Signed-off-by: Andreas Schneider <mail@cynapses.org>
2009-12-30 19:05:29 +01:00
Aris Adamantiadis
b361fb5898 Fix use-without-initialization 2009-12-28 22:29:50 +01:00
Aris Adamantiadis
8d1faa0dbc Made channel_open_session partially asynchronous 2009-12-27 00:06:34 +01:00
Aris Adamantiadis
77baa2df15 Fix a few log strings and levels in auth.c 2009-12-26 22:12:08 +01:00
Aris Adamantiadis
a229cb4676 Asynchronous authentication works ! 2009-12-26 21:59:37 +01:00
Aris Adamantiadis
682ed18123 New packet handler for SSH_USERAUTH_BANNER 2009-12-26 20:24:07 +01:00
Aris Adamantiadis
3aae59c224 Fix tricky bug within packet decoding 2009-12-26 17:03:27 +01:00
Aris Adamantiadis
6f3505bf6b Asynchronous service request 2009-12-26 16:51:33 +01:00
Aris Adamantiadis
bfdc48e320 Simplification of the "exec" sample 2009-12-24 10:46:46 +01:00
Vic Lee
fcda8beb1c File handle need to be closed in case of errors in privatekey_from_file
Signed-off-by: Vic Lee <llyzs@163.com>
Signed-off-by: Andreas Schneider <mail@cynapses.org>
2009-12-23 09:37:35 +01:00
Andreas Schneider
d0647afae5 Added an example for exec. 2009-12-22 18:34:23 +01:00
Aris Adamantiadis
a6383cec51 Fix typos in doc 2009-12-22 10:20:19 +01:00
Vic Lee
44fd5ff451 Added private key type detection feature in privatekey_from_file
Signed-off-by: Vic Lee <llyzs@163.com>
Signed-off-by: Andreas Schneider <mail@cynapses.org>
2009-12-22 09:02:10 +01:00
Andreas Schneider
ea34f37d43 Generate the APPLICATION_VERSION. 2009-12-21 15:56:21 +01:00
Andreas Schneider
23dcc2c7f3 Fixed ssh_get_user_home_dir() to be thread safe. 2009-12-21 12:32:58 +01:00
Aris Adamantiadis
91f7d127ea Tutorial doxyginized and updated up to auth sect. 2009-12-20 23:21:59 +01:00
Aris Adamantiadis
43c1245396 Some options functions did not show up in doxygen 2009-12-20 20:23:58 +01:00
Aris Adamantiadis
43288bc4f2 added ssh_message_auth_reply_pk_ok_simple 2009-12-20 18:51:37 +01:00
Aris Adamantiadis
2e22d6ef99 Add key validation in server side authentication 2009-12-20 18:05:02 +01:00
Andreas Schneider
6509b6e742 Started to add the tutorial to doxygen. 2009-12-19 00:31:47 +01:00
Aris Adamantiadis
d2ce0042b3 Deleted obsolete doxygen files 2009-12-19 00:10:54 +01:00
Aris Adamantiadis
0dcb63ff5e Merge branch 'master' of git://git.libssh.org/projects/libssh/libssh 2009-12-19 00:10:13 +01:00
Andreas Schneider
bebbac1bd8 Improved doxygen output of ssh_options_set(). 2009-12-19 00:08:54 +01:00
Aris Adamantiadis
a1870a62cf Documentation callbacks.h + standardization 2009-12-18 23:56:59 +01:00
Andreas Schneider
1ef1a77421 Disabled caller graphs as they are only of internal interest. 2009-12-18 23:54:31 +01:00
Andreas Schneider
98819f92e3 Updated the doxygen file. 2009-12-18 23:41:25 +01:00
Andreas Schneider
ebce70eba1 Fixed documentation of buffer struct. 2009-12-18 23:41:01 +01:00
Andreas Schneider
ed257b982a Fixed documentation of ssh_options_copy(). 2009-12-18 23:38:27 +01:00
Andreas Schneider
1b7877f6ed Moved the doxygen mainpage to doc/mainpage.dox 2009-12-18 23:35:41 +01:00
Andreas Schneider
7500b0564c Document the callback structure correctly. 2009-12-18 23:19:37 +01:00
Andreas Schneider
0c992ece3b Added a mainpage to doxygen. 2009-12-18 23:12:47 +01:00
Andreas Schneider
e124249a8b Fixed the doxygen documentation. 2009-12-18 23:12:37 +01:00
Aris Adamantiadis
d950d6af52 Optional compilation of developper's doc 2009-12-16 23:19:18 +01:00
Aris Adamantiadis
55abcfeef6 These docs are outdated too 2009-12-15 23:53:28 +01:00
Aris Adamantiadis
49b3712891 Stub for doxygen main documentation 2009-12-15 23:50:16 +01:00
Aris Adamantiadis
b9a8b22728 Doxygen now outputs on stderr, inputs from doc/ 2009-12-15 23:48:51 +01:00
Aris Adamantiadis
65f8e86e41 Deleted obsolete documentation draft 2009-12-15 23:37:53 +01:00
Aris Adamantiadis
9780f22866 Made packet_wait issue warnings 2009-12-13 20:49:47 +01:00
Aris Adamantiadis
46b2b99f63 Fix strange error message in sample authentication 2009-12-13 19:53:32 +01:00
Aris Adamantiadis
c92f54102e Key exchange currently done asynchronously
Fixed an important bug in packet buffering (two packets received in the same recv would'nt be processed correctly)
2009-12-13 18:20:05 +01:00
Aris Adamantiadis
964d5f88cc ssh_poll_handle detaches from context before free 2009-12-13 17:04:23 +01:00
Aris Adamantiadis
ad7e9d88fb packet SSH_KEXINIT received and parsed
Resolved some bugs in the callback mechanism as well
2009-12-12 00:23:53 +01:00
Aris Adamantiadis
3ace7817b4 Async connection + banner fetch is working 2009-12-11 23:26:25 +01:00
Aris Adamantiadis
0de35ca8f0 Fix logging problem in match_known_host 2009-12-11 21:23:52 +01:00
Aris Adamantiadis
80b6cf77b0 Added a global poll context 2009-12-11 21:11:23 +01:00
Andreas Schneider
79b4bf4ac2 Don't install crypto.h which is an internal header file. 2009-12-10 13:55:42 +01:00
Aris Adamantiadis
ab6b510408 More doxygen stuff 2009-12-09 20:27:10 +01:00
Aris Adamantiadis
ab52ca01ad Resolving doxygen errors in internal mode 2009-12-09 19:53:58 +01:00
Aris Adamantiadis
64b72f8d3a Fix some doxygen errors 2009-12-09 19:43:16 +01:00
Andreas Schneider
ffc9806e6d Remove socklen_t definition.
Tthe problem is that winsock2.h defines socklen_t as a typedef, not as a
define, so depending on the order of includes you can get errors in
ws2tcpip.h with msvc.
2009-12-09 13:02:48 +01:00
Aris Adamantiadis
984fb41b98 Moved #defines into an enum 2009-12-06 23:47:58 +01:00
Aris Adamantiadis
a1e05c62ae struct socket -> struct ssh_socket_struct +typedef 2009-12-06 22:48:56 +01:00
Aris Adamantiadis
076e884873 More callback stuff in connection
I have coded it, not actually tested it :) It still needs
work to get past the banner exchange.
2009-12-05 15:05:02 +01:00
Aris Adamantiadis
2f6fbbd706 Trying to adapt client.c to use callbacks 2009-12-03 23:55:46 +01:00
Aris Adamantiadis
4924ac8099 Asynchronous sockets work !
Still need a bit of tuning but it's stable enough
for our current needs
2009-12-01 23:34:55 +01:00
Andreas Schneider
7962029bdc Fixed indent. 2009-12-01 16:59:41 +01:00
Andreas Schneider
f83f837de7 Added gettimeofday for Windows.
Thanks to Patrick Spendrin.
2009-12-01 16:57:49 +01:00
Andreas Schneider
48b719cf68 Fixed uint* to work on Windows.
Thanks to Patrick Spendrin.
2009-12-01 16:15:54 +01:00
Aris Adamantiadis
96afa4530c More logging 2009-11-30 23:56:21 +01:00
Aris Adamantiadis
270a8a26fa Fix stupid bug which stops log_verbosity working 2009-11-30 23:55:02 +01:00
Aris Adamantiadis
92a50f731c Socket connect callback working...
Still need to make sure the connect syscall is correctly
called
2009-11-30 23:44:40 +01:00
Aris Adamantiadis
76d6838223 Some brain surgery to add event-based sockets
chapter 1- SSH Socket Connections.
I would like to be able to
-Have a ssh_poll_ctx object
-Add a ssh socket over it
-launch the socket connection (using socket functions)
-ssh_poll_ctx_dopoll()
-Wait for the timeout or have the "connected" callback called
2009-11-30 22:35:43 +01:00
Aris Adamantiadis
0bfb9d476c Standardize callbacks style and add documentation 2009-11-29 22:51:14 +01:00
Aris Adamantiadis
91bb1b2de6 Squashed commit of the following:
commit 43fad8dfd977637c31fade76ace2905f6528c3bc
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date:   Fri Nov 27 18:39:06 2009 +0100

    adaptation to the new ssh_poll_handle object name

commit 1e5e6ac4605adf10d437d04f0fd4b7e66024853c
Merge: 3fd92a0... 810adad...
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date:   Fri Nov 27 18:33:06 2009 +0100

    Merge branch 'master' into badcode/libssh_async

commit 3fd92a08eb74b1447a9ff4ca4e1d137475c62cc6
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date:   Mon Nov 2 14:25:46 2009 +0100

    Compiles again

commit 8910d7b9692418c9ccea0234f6d49674d238dc16
Merge: e83f1b5... cce34a6...
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date:   Mon Nov 2 12:47:34 2009 +0100

    Merge branch 'master' into libssh_async

    Very big merge !

    Conflicts:
    	include/libssh/callbacks.h
    	include/libssh/priv.h
    	libssh/channels.c
    	libssh/messages.c
    	libssh/packet.c
    	libssh/server.c
    	libssh/session.c
    	libssh/socket.c

commit e83f1b593219e183082b015315f09bfe95a29cfc
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date:   Mon Nov 2 12:07:01 2009 +0100

    rename callback.h

commit dffa7b730e8f39e2198de18ab69a8e57bef95e58
Merge: 5a8b748... de8808c...
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date:   Tue Sep 15 10:50:07 2009 +0200

    Merge branch 'master' of git://git.libssh.org/projects/libssh/libssh into libssh_async

commit 5a8b7484f36599d28f2c0c14a23b76bfc7257638
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date:   Sun Sep 13 12:55:18 2009 +0200

    More updates to callback system

commit 18620c20d5e4e62107093f7fd330e553493253fa
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date:   Sat Sep 12 22:26:52 2009 +0200

    Same thing with channel_rcv_data

commit fc4a56f6726e409a5866272923f1cbebfc821af3
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date:   Sat Sep 12 22:17:45 2009 +0200

    added a few packet handlers for channels

commit 4b6bb4fd00b10cf1321a764126f277ab204bffe3
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date:   Fri Sep 11 23:15:25 2009 +0300

    sample packet handlers + bugfixes

commit 2784d09d6dec0a8f868912d14f90d860233b3f82
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date:   Fri Sep 11 20:30:50 2009 +0300

    Packet callbacks nearly finished

    Need tests and implementation of some packet callbacks

commit cd3ea43f20c9ae2f54576ca98a0ea75c5d4299d3
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date:   Thu Sep 10 12:46:02 2009 +0300

    First step of async packet handling

    The socket to packet handler is nearly done (needs testing)
    I still need to define the interface for callbacks.

commit 487f4d2a900a5fe3b90ceda4460ab7d38d7ad722
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date:   Tue Sep 8 23:24:09 2009 +0300

    Almost complete socket callback system

    Finished the callback function so it bufferizes data when
    callee does not use it.
    Flushes the buffer automaticaly after a ssh_socket_nonblocking_flush

commit 23571f22fac9e40c855dfa99569bba181a39648b
Author: Aris Adamantiadis <aris@0xbadc0de.be>
Date:   Tue Sep 8 22:22:32 2009 +0300

    First draft of a callback system
2009-11-27 20:42:43 +01:00
Aris Adamantiadis
810adadf2e Compile with pcap support by default
This will permit to get pcap debugging out of the box
2009-11-27 18:18:12 +01:00
Aris Adamantiadis
8da712ea61 Compile in stub for pcap funcs when pcap disabled
Avoid that way linking problems
2009-11-27 18:16:10 +01:00
Aris Adamantiadis
56cfb8036f Build the pcap code into example in all cases 2009-11-27 18:08:53 +01:00
Andreas Schneider
f332dd810e Added changelog entries for 0.4 rc2. 2009-11-20 16:11:17 +01:00
179 changed files with 25677 additions and 16757 deletions

1
.clang_complete Normal file
View File

@@ -0,0 +1 @@
-Iinclude -Ibuild

View File

@@ -7,8 +7,8 @@ cmake_minimum_required(VERSION 2.6.0)
set(APPLICATION_NAME ${PROJECT_NAME})
set(APPLICATION_VERSION_MAJOR "0")
set(APPLICATION_VERSION_MINOR "4")
set(APPLICATION_VERSION_PATCH "7")
set(APPLICATION_VERSION_MINOR "5")
set(APPLICATION_VERSION_PATCH "3")
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.4")
set(LIBRARY_VERSION "4.2.3")
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)
@@ -43,7 +44,9 @@ include(MacroAddPlugin)
include(MacroCopyFile)
# search for libraries
find_package(ZLIB REQUIRED)
if (WITH_LIBZ)
find_package(ZLIB REQUIRED)
endif (WITH_LIBZ)
if (WITH_GCRYPT)
find_package(GCrypt REQUIRED)
@@ -60,6 +63,10 @@ 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)
# config.h checks
include(ConfigureChecks.cmake)
configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
@@ -67,12 +74,46 @@ 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")
add_subdirectory(examples)
if (WITH_TESTING)
find_package(CMockery REQUIRED)
include(AddCMockeryTest)
add_subdirectory(tests)
endif (WITH_TESTING)
message(STATUS "********************************************")
message(STATUS "********** ${PROJECT_NAME} build options : **********")
message(STATUS "zlib support: ${WITH_LIBZ}")
message(STATUS "libgcrypt support: ${WITH_GCRYPT}")
message(STATUS "SSH-1 support: ${WITH_SSH1}")
message(STATUS "SFTP support: ${WITH_SFTP}")
message(STATUS "Server support : ${WITH_SERVER}")
message(STATUS "Pcap debugging support : ${WITH_PCAP}")
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 "********************************************")

View File

@@ -12,8 +12,8 @@ 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 "7")
set(CPACK_PACKAGE_VERSION_MINOR "5")
set(CPACK_PACKAGE_VERSION_PATCH "3")
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
@@ -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
View File

@@ -0,0 +1,9 @@
set(UPDATE_TYPE "true")
set(CTEST_PROJECT_NAME "libssh")
set(CTEST_NIGHTLY_START_TIME "01:00:00 CET")
set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "test.libssh.org")
set(CTEST_DROP_LOCATION "/submit.php?project=libssh")
set(CTEST_DROP_SITE_CDASH TRUE)

View File

@@ -1,6 +1,70 @@
ChangeLog
==========
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.

View File

@@ -1,5 +1,4 @@
include(CheckIncludeFile)
include(CheckIncludeFiles)
include(CheckSymbolExists)
include(CheckFunctionExists)
include(CheckLibraryExists)
@@ -18,38 +17,40 @@ 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)
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(termios.h HAVE_TERMIOS_H)
if (WIN32)
check_include_files("winsock2.h;ws2tcpip.h;wspiapi.h" HAVE_WSPIAPI_H)
check_include_file(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)
check_include_file(ws2tcpip.h HAVE_WS2TCPIP_H)
if (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
set(HAVE_GETADDRINFO TRUE)
set(HAVE_GETHOSTBYNAME TRUE)
@@ -67,6 +68,10 @@ 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)
if (CMAKE_HAVE_PTHREAD_H)
set(HAVE_PTHREAD_H 1)
endif (CMAKE_HAVE_PTHREAD_H)
# FUNCTIONS
check_function_exists(strncpy HAVE_STRNCPY)
@@ -81,33 +86,40 @@ if (WIN32)
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)
if (NOT LINUX)
# libsocket (Solaris)
check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET)
if (HAVE_LIBSOCKET)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} socket)
endif (HAVE_LIBSOCKET)
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)
# libresolv
check_library_exists(resolv hstrerror "" HAVE_LIBRESOLV)
if (HAVE_LIBRESOLV)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} resolv)
endif (HAVE_LIBRESOLV)
# 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_function_exists(getaddrinfo HAVE_GETADDRINFO)
check_function_exists(poll HAVE_POLL)
check_function_exists(select HAVE_SELECT)
check_function_exists(cfmakeraw HAVE_CFMAKERAW)
check_function_exists(regcomp HAVE_REGCOMP)
check_function_exists(ntohll HAVE_NTOHLL)
endif (UNIX)
set(LIBSSH_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CACHE INTERNAL "libssh required system libraries")
@@ -121,9 +133,15 @@ if (GCRYPT_FOUND)
set(HAVE_LIBGCRYPT 1)
endif (GCRYPT_FOUND)
if (Z_LIBRARY)
if (ZLIB_LIBRARY)
set(HAVE_LIBZ 1)
endif (Z_LIBRARY)
endif (ZLIB_LIBRARY)
if (CMAKE_HAVE_THREADS_LIBRARY)
if (CMAKE_USE_PTHREADS_INIT)
set(HAVE_PTHREAD 1)
endif (CMAKE_USE_PTHREADS_INIT)
endif (CMAKE_HAVE_THREADS_LIBRARY)
# OPTIONS
if (WITH_DEBUG_CRYPTO)

View File

@@ -6,4 +6,16 @@ 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)
if(WITH_BENCHMARKS)
set(WITH_TESTING ON)
endif(WITH_BENCHMARKS)
if (WITH_TESTING)
set(WITH_STATIC_LIB ON)
endif (WITH_TESTING)

1272
Doxyfile

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -68,6 +68,8 @@ If you want to install libssh after compilation run:
## Running
The libssh binary can be found in the `build/libssh` directory.
You can use `build/examples/samplessh` which is a sample client to
test libssh on UNIX.
## About this document

108
README
View File

@@ -29,6 +29,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 +52,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 its 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 youre 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 cant 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 weve 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 Developers Certificate of Origin to us (sorry, no
pseudonyms or anonymous contributions.)
Thats 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 dont need to send in a copy of the libssh Developers
Certificate of Origin for each patch, or inside each patch. Just the sign-off
message is all that is required once weve received the initial email.
Have fun and happy libssh hacking!
The libssh Team

View File

@@ -62,8 +62,8 @@ function clean_build_dir() {
}
function usage () {
echo "Usage: `basename $0` [--prefix /install_prefix|--build [debug|final]|--clean|--verbose|--libsuffix (32|64)|--help|--cmakedir /directory|--make
(gmake|make)|--ccompiler (gcc|cc)|--withstaticlib|--unittesting|--withss1|--withserver]"
echo "Usage: `basename $0` [--prefix /install_prefix|--build [debug|final]|--clean|--verbose|--libsuffix (32|64)|--help|--clang|--cmakedir /directory|--make
(gmake|make)|--ccompiler (gcc|cc)|--withstaticlib|--unittesting|--clientunittesting|--withssh1|--withserver]"
cleanup_and_exit
}
@@ -100,6 +100,9 @@ while test -n "$1"; do
clean_build_dir
cleanup_and_exit
;;
*-clang)
OPTIONS="${OPTIONS} -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++"
;;
*-verbose)
DOVERBOSE="1"
;;
@@ -132,19 +135,18 @@ while test -n "$1"; do
;;
*-withstaticlib)
OPTIONS="${OPTIONS} -DWITH_STATIC_LIB=ON"
shift
;;
*-unittesting)
OPTIONS="${OPTIONS} -DUNIT_TESTING=ON"
shift
OPTIONS="${OPTIONS} -DWITH_TESTING=ON"
;;
*-clientunittesting)
OPTIONS="${OPTIONS} -DWITH_CLIENT_TESTING=ON"
;;
*-withssh1)
OPTIONS="${OPTIONS} -DWITH_SSH1=ON"
shift
;;
*-withserver)
OPTIONS="${OPTIONS} -DWITH_SERVER=ON"
shift
;;
----noarg)
echo "$ARG does not take an argument"

View File

@@ -0,0 +1,23 @@
# - ADD_CHECK_TEST(test_name test_source linklib1 ... linklibN)
# Copyright (c) 2007 Daniel Gollub <dgollub@suse.de>
# Copyright (c) 2007-2010 Andreas Schneider <asn@cynapses.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)
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")
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
function (ADD_CMOCKERY_TEST _testName _testSource)
add_executable(${_testName} ${_testSource})
target_link_libraries(${_testName} ${ARGN})
add_test(${_testName} ${CMAKE_CURRENT_BINARY_DIR}/${_testName})
endfunction (ADD_CMOCKERY_TEST)

View File

@@ -1,59 +1,71 @@
# define system dependent compiler flags
include(CheckCCompilerFlag)
include(MacroCheckCCompilerFlagSSP)
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)
# 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")
# with -fPIC
check_c_compiler_flag("-fPIC" WITH_FPIC)
if (WITH_FPIC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
endif (WITH_FPIC)
# 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("-fstack-protector" WITH_STACK_PROTECTOR)
if (WITH_STACK_PROTECTOR)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector")
endif (WITH_STACK_PROTECTOR)
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)
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("-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)
endif (${CMAKE_C_COMPILER_ID} MATCHES GNU)
endif (${CMAKE_C_COMPILER_ID} MATCHES GNU)
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)

View File

@@ -1,4 +1,15 @@
if (UNIX)
if (WIN32)
# Same same
set(BIN_INSTALL_DIR "bin" CACHE PATH "-")
set(SBIN_INSTALL_DIR "." CACHE PATH "-")
set(LIB_INSTALL_DIR "lib" CACHE PATH "-")
set(INCLUDE_INSTALL_DIR "include" 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(LOCALE_INSTALL_DIR "lang" CACHE PATH "-")
elseif (UNIX OR OS2)
IF (NOT APPLICATION_NAME)
MESSAGE(STATUS "${PROJECT_NAME} is used as APPLICATION_NAME")
SET(APPLICATION_NAME ${PROJECT_NAME})
@@ -90,18 +101,4 @@ if (UNIX)
"${SHARE_INSTALL_PREFIX}/info"
CACHE PATH "The ${APPLICATION_NAME} info install dir (default prefix/info)"
)
endif (UNIX)
if (WIN32)
# Same same
set(BIN_INSTALL_DIR "bin" CACHE PATH "-")
set(SBIN_INSTALL_DIR "." CACHE PATH "-")
set(LIB_INSTALL_DIR "lib" CACHE PATH "-")
set(INCLUDE_INSTALL_DIR "include" 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(LOCALE_INSTALL_DIR "lang" CACHE PATH "-")
endif (WIN32)
endif ()

View File

@@ -0,0 +1,28 @@
# 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")

View 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@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 (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)

View File

@@ -0,0 +1,63 @@
# - Try to find CMockery
# Once done this will define
#
# CMOCKERY_FOUND - system has CMockery
# CMOCKERY_INCLUDE_DIRS - the CMockery include directory
# CMOCKERY_LIBRARIES - Link these to use CMockery
# CMOCKERY_DEFINITIONS - Compiler switches required for using CMockery
#
# 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 (CMOCKERY_LIBRARIES AND CMOCKERY_INCLUDE_DIRS)
# in cache already
set(CMOCKERY_FOUND TRUE)
else (CMOCKERY_LIBRARIES AND CMOCKERY_INCLUDE_DIRS)
find_path(CMOCKERY_INCLUDE_DIR
NAMES
google/cmockery.h
PATHS
${_CMOCKERY_DIR}/include
/usr/include
/usr/local/include
/opt/local/include
/sw/include
$ENV{PROGRAMFILES}/cmockery/include
)
find_library(CMOCKERY_LIBRARY
NAMES
cmockery
PATHS
${_CMOCKERY_DIR}/lib
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
$ENV{PROGRAMFILES}/cmockery/lib
)
set(CMOCKERY_INCLUDE_DIRS
${CMOCKERY_INCLUDE_DIR}
)
if (CMOCKERY_LIBRARY)
set(CMOCKERY_LIBRARIES
${CMOCKERY_LIBRARIES}
${CMOCKERY_LIBRARY}
)
endif (CMOCKERY_LIBRARY)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(CMockery DEFAULT_MSG CMOCKERY_LIBRARIES CMOCKERY_INCLUDE_DIRS)
# show the CMOCKERY_INCLUDE_DIRS and CMOCKERY_LIBRARIES variables only in the advanced view
mark_as_advanced(CMOCKERY_INCLUDE_DIRS CMOCKERY_LIBRARIES)
endif (CMOCKERY_LIBRARIES AND CMOCKERY_INCLUDE_DIRS)

View File

@@ -6,72 +6,65 @@
# 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-2011 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 (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
# in cache already
set(GCRYPT_FOUND TRUE)
# in cache already
# set(GCRYPT_FOUND TRUE)
else (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
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)
find_library(GCRYPT_LIBRARY
NAMES
gcrypt
PATHS
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
)
mark_as_advanced(GCRYPT_LIBRARY)
if (GCRYPT_LIBRARY)
set(GCRYPT_FOUND TRUE CACHE INTERNAL "Wether the gcrypt library has been found" FORCE)
endif (GCRYPT_LIBRARY)
set(GCRYPT_INCLUDE_DIRS
${GCRYPT_INCLUDE_DIR}
)
if (GCRYPT_FOUND)
set(GCRYPT_LIBRARIES
${GCRYPT_LIBRARIES}
${GCRYPT_LIBRARY}
set(_GCRYPT_ROOT_PATHS
"$ENV{PROGRAMFILES}/libgcrypt"
)
endif (GCRYPT_FOUND)
if (GCRYPT_INCLUDE_DIRS AND GCRYPT_LIBRARIES)
set(GCRYPT_FOUND TRUE)
endif (GCRYPT_INCLUDE_DIRS AND GCRYPT_LIBRARIES)
find_path(GCRYPT_ROOT_DIR
NAMES
include/gcrypt.h
PATHS
${_GCRYPT_ROOT_PATHS}
)
mark_as_advanced(ZLIB_ROOT_DIR)
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)
find_path(GCRYPT_INCLUDE_DIR
NAMES
gcrypt.h
PATHS
/usr/local/include
/opt/local/include
/sw/include
/usr/lib/sfw/include
${GCRYPT_ROOT_DIR}/include
)
set(GCRYPT_INCLUDE_DIRS ${GCRYPT_INCLUDE_DIR})
# show the GCRYPT_INCLUDE_DIRS and GCRYPT_LIBRARIES variables only in the advanced view
mark_as_advanced(GCRYPT_INCLUDE_DIRS GCRYPT_LIBRARIES)
find_library(GCRYPT_LIBRARY
NAMES
gcrypt
gcrypt11
libgcrypt-11
PATHS
/opt/local/lib
/sw/lib
/usr/sfw/lib/64
/usr/sfw/lib
${GCRYPT_ROOT_DIR}/lib
)
set(GCRYPT_LIBRARIES ${GCRYPT_LIBRARY})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(GCrypt DEFAULT_MSG GCRYPT_LIBRARIES GCRYPT_INCLUDE_DIRS)
# 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)

View File

@@ -1,31 +1,39 @@
# - Try to find NSIS
# Once done this will define
#
# NSIS_ROOT_DIR - Set this variable to the root installation of ZLIB
#
# Read-Only variables:
# NSIS_FOUND - system has NSIS
# NSIS_MAKE - NSIS creator executable
#
# Copyright (c) 2010 Andreas Schneider <mail@cynapses.org>
#=============================================================================
# Copyright (c) 2010-2011 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 (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
)
set(_NSIS_ROOT_PATHS
C:/NSIS/Bin
"$ENV{PROGRAMFILES}/NSIS"
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NSIS DEFAULT_MSG NSIS_MAKE)
find_program(NSIS_MAKE
NAMES
makensis
PATHS
${NSIS_ROOT_PATH}
${NSIS_ROOT_PATH}/Bin
${_NSIS_ROOT_PATHS}
)
mark_as_advanced(NSIS_MAKE)
endif (NSIS_MAKE)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NSIS DEFAULT_MSG NSIS_MAKE)
mark_as_advanced(NSIS_MAKE)

View File

@@ -1,189 +1,208 @@
# - Try to find OpenSSL
# Once done this will define
#
# OPENSSL_ROOT_DIR - Set this variable to the root installation of OpenSSL
#
# Read-Only variables:
# OPENSSL_FOUND - system has OpenSSL
# OPENSSL_INCLUDE_DIRS - the OpenSSL include directory
# OPENSSL_LIBRARIES - Link these to use OpenSSL
# OPENSSL_DEFINITIONS - Compiler switches required for using OpenSSL
#
# Copyright (c) 2009 Andreas Schneider <mail@cynapses.org>
#=============================================================================
# Copyright (c) 2006-2009 Kitware, Inc.
# Copyright (c) 2006 Alexander Neundorf <neundorf@kde.org>
# Copyright (c) 2009-2010 Mathieu Malaterre <mathieu.malaterre@gmail.com>
# Copyright (c) 2011 Andreas Schneider <asn@cryptomilk.org>
#
# 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 (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
# in cache already
set(OPENSSL_FOUND TRUE)
# 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)
if (UNIX)
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
pkg_check_modules(_OPENSSL openssl)
endif (PKG_CONFIG_FOUND)
endif (UNIX)
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}
# http://www.slproweb.com/products/Win32OpenSSL.html
set(_OPENSSL_ROOT_HINTS
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
)
endif (SSL_FOUND)
if (SSLEAY32_FOUND)
set(OPENSSL_LIBRARIES
${OPENSSL_LIBRARIES}
${SSLEAY32_LIBRARY}
set(_OPENSSL_ROOT_PATHS
"C:/OpenSSL/"
"C:/OpenSSL-Win32/"
"C:/OpenSSL-Win64/"
"$ENV{PROGRAMFILES}/OpenSSL"
"$ENV{PROGRAMFILES}/OpenSSL-Win32"
"$ENV{PROGRAMFILES}/OpenSSL-Win64"
)
endif (SSLEAY32_FOUND)
if (SSLEAY32MD_FOUND)
set(OPENSSL_LIBRARIES
${OPENSSL_LIBRARIES}
${SSLEAY32MD_LIBRARY}
find_path(OPENSSL_ROOT_DIR
NAMES
include/openssl/ssl.h
HINTS
${_OPENSSL_ROOT_HINTS}
PATHS
${_OPENSSL_ROOT_PATHS}
)
endif (SSLEAY32MD_FOUND)
mark_as_advanced(OPENSSL_ROOT_DIR)
if (CRYPTO_FOUND)
set(OPENSSL_LIBRARIES
${OPENSSL_LIBRARIES}
${CRYPTO_LIBRARY}
find_path(OPENSSL_INCLUDE_DIR
NAMES
openssl/ssl.h
PATHS
/usr/local/include
/opt/local/include
/sw/include
/usr/lib/sfw/include
${OPENSSL_ROOT_DIR}/include
)
endif (CRYPTO_FOUND)
if (OPENSSL_INCLUDE_DIRS AND OPENSSL_LIBRARIES)
set(OPENSSL_FOUND TRUE)
endif (OPENSSL_INCLUDE_DIRS AND OPENSSL_LIBRARIES)
set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR})
mark_as_advanced(OPENSSL_INCLUDE_DIRS)
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)
if (WIN32 AND NOT CYGWIN)
# MINGW should go here too
if (MSVC)
# /MD and /MDd are the standard values - if someone wants to use
# others, the libnames have to change here too
# use also ssl and ssleay32 in debug as fallback for openssl < 0.9.8b
# TODO: handle /MT and static lib
# In Visual C++ naming convention each of these four kinds of Windows libraries has it's standard suffix:
# * MD for dynamic-release
# * MDd for dynamic-debug
# * MT for static-release
# * MTd for static-debug
# show the OPENSSL_INCLUDE_DIRS and OPENSSL_LIBRARIES variables only in the advanced view
mark_as_advanced(OPENSSL_INCLUDE_DIRS OPENSSL_LIBRARIES)
# Implementation details:
# We are using the libraries located in the VC subdir instead of the parent directory eventhough :
# libeay32MD.lib is identical to ../libeay32.lib, and
# ssleay32MD.lib is identical to ../ssleay32.lib
find_library(LIB_EAY_DEBUG
NAMES
libeay32MDd
libeay32
PATHS
${OPENSSL_ROOT_DIR}/lib/VC
)
find_library(LIB_EAY_RELEASE
NAMES
libeay32MD
libeay32
PATHS
${OPENSSL_ROOT_DIR}/lib/VC
)
find_library(SSL_EAY_DEBUG
NAMES
ssleay32MDd
ssleay32
ssl
PATHS ${OPENSSL_ROOT_DIR}/lib/VC
)
find_library(SSL_EAY_RELEASE
NAMES
ssleay32MD
ssleay32
ssl
PATHS
${OPENSSL_ROOT_DIR}/lib/VC
)
if (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)
set(OPENSSL_LIBRARIES
optimized ${SSL_EAY_RELEASE} debug ${SSL_EAY_DEBUG}
optimized ${LIB_EAY_RELEASE} debug ${LIB_EAY_DEBUG}
)
else (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)
set( OPENSSL_LIBRARIES ${SSL_EAY_RELEASE} ${LIB_EAY_RELEASE} )
endif (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)
mark_as_advanced(SSL_EAY_DEBUG SSL_EAY_RELEASE)
mark_as_advanced(LIB_EAY_DEBUG LIB_EAY_RELEASE)
elseif (MINGW)
# same player, for MingW
find_library(LIB_EAY
NAMES
libeay32
PATHS
${OPENSSL_ROOT_DIR}/lib/MinGW
)
find_library(SSL_EAY
NAMES
ssleay32
PATHS
${OPENSSL_ROOT_DIR}/lib/MinGW
)
mark_as_advanced(SSL_EAY LIB_EAY)
set(OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY})
else(MSVC)
# Not sure what to pick for -say- intel, let's use the toplevel ones and hope someone report issues:
find_library(LIB_EAY
NAMES
libeay32
PATHS
${OPENSSL_ROOT_DIR}/lib
)
find_library(SSL_EAY
NAMES
ssleay32
PATHS
${OPENSSL_ROOT_DIR}/lib
)
mark_as_advanced(SSL_EAY LIB_EAY)
set(OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY})
endif(MSVC)
else (WIN32 AND NOT CYGWIN)
find_library(OPENSSL_SSL_LIBRARIES
NAMES
ssl
ssleay32
ssleay32MD
PATHS
${_OPENSSL_LIBDIR}
/opt/local/lib
/sw/lib
/usr/sfw/lib/64
/usr/sfw/lib
)
find_library(OPENSSL_CRYPTO_LIBRARIES
NAMES
crypto
PATHS
${_OPENSSL_LIBDIR}
/opt/local/lib
/sw/lib
/usr/sfw/lib/64
/usr/sfw/lib
)
mark_as_advanced(OPENSSL_CRYPTO_LIBRARIES OPENSSL_SSL_LIBRARIES)
set(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARIES})
endif (WIN32 AND NOT CYGWIN)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OpenSSL DEFAULT_MSG OPENSSL_LIBRARIES OPENSSL_INCLUDE_DIRS)
endif (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)

View File

@@ -1,84 +1,119 @@
# - Try to find ZLIB
# Once done this will define
#
# ZLIB_ROOT_DIR - Set this variable to the root installation of ZLIB
#
# Read-Only variables:
# ZLIB_FOUND - system has ZLIB
# ZLIB_INCLUDE_DIRS - the ZLIB include directory
# ZLIB_LIBRARIES - Link these to use ZLIB
# ZLIB_DEFINITIONS - Compiler switches required for using ZLIB
#
# Copyright (c) 2009 Andreas Schneider <mail@cynapses.org>
# ZLIB_VERSION_STRING - The version of zlib found (x.y.z)
# ZLIB_VERSION_MAJOR - The major version of zlib
# ZLIB_VERSION_MINOR - The minor version of zlib
# ZLIB_VERSION_PATCH - The patch version of zlib
# ZLIB_VERSION_TWEAK - The tweak version of zlib
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
# The following variable are provided for backward compatibility
#
# ZLIB_MAJOR_VERSION - The major version of zlib
# ZLIB_MINOR_VERSION - The minor version of zlib
# ZLIB_PATCH_VERSION - The patch version of zlib
#
#=============================================================================
# Copyright (c) 2001-2009 Kitware, Inc.
# Copyright (c) 2011 Andreas Schneider <asn@cryptomilk.org>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
#
if (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
# in cache already
set(ZLIB_FOUND TRUE)
else (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
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}
set(_ZLIB_ROOT_HINTS
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\Zlib;InstallPath]/include"
)
endif (Z_FOUND)
if (ZLIB_INCLUDE_DIRS AND ZLIB_LIBRARIES)
set(ZLIB_FOUND TRUE)
endif (ZLIB_INCLUDE_DIRS AND ZLIB_LIBRARIES)
set(_ZLIB_ROOT_PATHS
"$ENV{PROGRAMFILES}/zlib"
)
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)
find_path(ZLIB_ROOT_DIR
NAMES
include/zlib.h
HINTS
${_ZLIB_ROOT_HINTS}
PATHS
${_ZLIB_ROOT_PATHS}
)
mark_as_advanced(ZLIB_ROOT_DIR)
# show the ZLIB_INCLUDE_DIRS and ZLIB_LIBRARIES variables only in the advanced view
mark_as_advanced(ZLIB_INCLUDE_DIRS ZLIB_LIBRARIES)
# check for header file
find_path(ZLIB_INCLUDE_DIR
NAMES
zlib.h
PATHS
/usr/local/include
/opt/local/include
/sw/include
/usr/lib/sfw/include
${ZLIB_ROOT_DIR}/include
)
mark_as_advanced(ZLIB_INCLUDE_DIR)
# check version number
if (ZLIB_INCLUDE_DIR AND EXISTS "${ZLIB_INCLUDE_DIR}/zlib.h")
file(STRINGS "${ZLIB_INCLUDE_DIR}/zlib.h" ZLIB_H REGEX "^#define ZLIB_VERSION \"[^\"]*\"$")
string(REGEX REPLACE "^.*ZLIB_VERSION \"([0-9]+).*$" "\\1" ZLIB_VERSION_MAJOR "${ZLIB_H}")
string(REGEX REPLACE "^.*ZLIB_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" ZLIB_VERSION_MINOR "${ZLIB_H}")
string(REGEX REPLACE "^.*ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" ZLIB_VERSION_PATCH "${ZLIB_H}")
set(ZLIB_VERSION_STRING "${ZLIB_VERSION_MAJOR}.${ZLIB_VERSION_MINOR}.${ZLIB_VERSION_PATCH}")
# only append a TWEAK version if it exists:
set(ZLIB_VERSION_TWEAK "")
if ("${ZLIB_H}" MATCHES "^.*ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]+\\.([0-9]+).*$")
set(ZLIB_VERSION_TWEAK "${CMAKE_MATCH_1}")
set(ZLIB_VERSION_STRING "${ZLIB_VERSION_STRING}.${ZLIB_VERSION_TWEAK}")
endif ("${ZLIB_H}" MATCHES "^.*ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]+\\.([0-9]+).*$")
set(ZLIB_MAJOR_VERSION "${ZLIB_VERSION_MAJOR}")
set(ZLIB_MINOR_VERSION "${ZLIB_VERSION_MINOR}")
set(ZLIB_PATCH_VERSION "${ZLIB_VERSION_PATCH}")
endif (ZLIB_INCLUDE_DIR AND EXISTS "${ZLIB_INCLUDE_DIR}/zlib.h")
find_library(ZLIB_LIBRARY
NAMES
z
zdll
zlib
zlib1
PATHS
/usr/local/lib
/opt/local/lib
/sw/lib
/usr/sfw/lib/64
/usr/sfw/lib
${ZLIB_ROOT_DIR}/lib
)
mark_as_advanced(ZLIB_LIBRARY)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(ZLIB DEFAULT_MSG ZLIB_INCLUDE_DIR ZLIB_LIBRARY)
#find_package_handle_standard_args(ZLIB REQUIRED_VARS ZLIB_INCLUDE_DIR ZLIB_LIBRARY
# VERSION_VAR ZLIB_VERSION_STRING)
if (ZLIB_FOUND)
set(ZLIB_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR})
set(ZLIB_LIBRARIES ${ZLIB_LIBRARY})
endif (ZLIB_FOUND)
endif (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)

View 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 the check_c_source_compiles macro.
# 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)
MACRO (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}")
ENDMACRO (CHECK_C_COMPILER_FLAG_SSP)

View File

@@ -35,6 +35,10 @@
/* 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 <pthread.h> header file. */
#cmakedefine HAVE_PTHREAD_H 1
/*************************** FUNCTIONS ***************************/
/* Define to 1 if you have the `snprintf' function. */
@@ -55,16 +59,6 @@
/* 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 `strncpy' function. */
#cmakedefine HAVE_STRNCPY 1
@@ -74,9 +68,6 @@
/* 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
@@ -86,6 +77,12 @@
/* 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
/*************************** LIBRARIES ***************************/
/* Define to 1 if you have the `crypto' library (-lcrypto). */
@@ -97,6 +94,10 @@
/* 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 ****************************/
/* Define to 1 if you want to enable ZLIB */

View File

@@ -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>
&nbsp;&nbsp;&nbsp;&nbsp;go_out()...<br>
if(i>=256)<br>
&nbsp;&nbsp;&nbsp;&nbsp;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>

373
doc/authentication.dox Normal file
View File

@@ -0,0 +1,373 @@
/**
@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_autopubkey() 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 in a ssh_string using publickey_from_file().
- Offer the public key to the SSH server using ssh_userauth_offer_pubkey().
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 privatekey_from_file() function. If
a passphrase is needed, either the passphrase specified as argument or
a callback (see callbacks section) will be used.
- Authenticate using ssh_userauth_pubkey() with your public key string
and private key.
- Do not forget cleaning up memory using string_free() and privatekey_free().
Here is a minimalistic example of public key authentication:
@code
int authenticate_pubkey(ssh_session session)
{
int rc;
rc = ssh_userauth_autopubkey(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_autopubkey
@see ssh_userauth_offer_pubkey
@see ssh_userauth_pubkey
@see publickey_from_file
@see publickey_from_privatekey
@see string_free
@see privatekey_from_file
@see privatekey_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, 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;
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
View 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
*/

File diff suppressed because it is too large Load Diff

221
doc/forwarding.dox Normal file
View File

@@ -0,0 +1,221 @@
/**
@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 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 (rc != SSH_OK) return rc;
rc = 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 = 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_forward_listen(),
then ssh_channel_forward_accept().
When you call ssh_channel_forward_listen(), 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;
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_forward_listen(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_forward_accept(session, 60000);
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
*/

455
doc/guided_tour.dox Normal file
View File

@@ -0,0 +1,455 @@
/**
@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.
ssh_get_error() and ssh_get_error_code() take a ssh_session as a parameter.
That's for thread safety, error messages that can be attached to a session
aren't static anymore. Any error that happens during ssh_options_xxx()
or ssh_connect() (i.e., outside of any session) can be retrieved by
giving NULL as argument.
The SFTP subsystem has its own error codes, in addition to libssh ones.
*/

50
doc/introduction.dox Normal file
View File

@@ -0,0 +1,50 @@
/**
@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 (http://directory.fsf.org/project/libgcrypt/)
or libcrypto (http://www.openssl.org/docs/crypto/crypto.html), 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
*/

View File

@@ -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.

24
doc/linking.dox Normal file
View File

@@ -0,0 +1,24 @@
/**
@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.
On Windows you need to define LIBSSH_STATIC in the compiler command
line. This is required cause the dynamic library needs to specify the
dllimport attribute.
*/

View File

@@ -1,12 +1,209 @@
/**
* @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:
- Full C library functions for manipulating a client-side SSH connection
- SSH2 and SSH1 protocol compliant
- Fully configurable sessions
- Server support
- SSH agent authentication support
- Support for AES-128, AES-192, AES-256, Blowfish, 3DES in CBC mode, and AES in CTR mode
- Supports OpenSSL and GCrypt
- Use multiple SSH connections in a same process, at same time
- Use multiple channels in the same connection
- Thread safety when using different sessions at same time
- POSIX-like SFTP (Secure File Transfer) implementation with openssh extension support
- SCP implementation
- Large file system support (files bigger than 4GB)
- RSA and DSS server public key supported
- Compression support (with zlib)
- Public key (RSA and DSS), password and keyboard-interactive authentication
- Full poll()/WSAPoll() support and a poll-emulation for Win32.
- Runs and tested under x86_64, x86, ARM, Sparc32, PPC under Linux, BSD, MacOSX, Solaris and Windows
@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 its 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 youre 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 cant 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 weve 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 Developers Certificate of Origin to us (sorry, no
pseudonyms or anonymous contributions.)
Thats 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 dont need to send in a copy of the libssh Developers
Certificate of Origin for each patch, or inside each patch. Just the sign-off
message is all that is required once weve 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/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 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>
*/

257
doc/scp.dox Normal file
View File

@@ -0,0 +1,257 @@
/**
@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.
*/

395
doc/sftp.dox Normal file
View File

@@ -0,0 +1,395 @@
/**
@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().
The following example prints the contents of remote file "/etc/profile". For
each 1024 bytes of information read, it waits until the end of the read operation:
@code
int sftp_read_sync(ssh_session session, sftp_session sftp)
{
int access_type;
sftp_file file;
char buffer[1024];
int nbytes, rc;
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;
}
nbytes = sftp_read(file, buffer, sizeof(buffer));
while (nbytes > 0)
{
if (write(1, buffer, nbytes) != nbytes)
{
sftp_close(file);
return SSH_ERROR;
}
nbytes = sftp_read(file, buffer, sizeof(buffer));
}
if (nbytes < 0)
{
fprintf(stderr, "Error while reading 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 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
int sftp_read_async(ssh_session session, sftp_session sftp)
{
int access_type;
sftp_file file;
char buffer[1024];
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("%-22s %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
View 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
*/

View File

@@ -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
View 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 ***
*/

65
doc/threading.dox Normal file
View File

@@ -0,0 +1,65 @@
/**
@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
Good luck !
*/

View File

@@ -1,4 +1,4 @@
project(libssh-examples C)
project(libssh-examples C CXX)
set(examples_SRCS
authentication.c
@@ -6,36 +6,43 @@ 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 (LINUX)
add_executable(libssh_scp libssh_scp.c ${examples_SRCS})
target_link_libraries(libssh_scp ${LIBSSH_SHARED_LIBRARY})
if (WITH_SERVER)
add_executable(samplesshd samplesshd.c)
target_link_libraries(samplesshd ${LIBSSH_SHARED_LIBRARY})
endif (WITH_SERVER)
add_executable(scp_download scp_download.c ${examples_SRCS})
target_link_libraries(scp_download ${LIBSSH_SHARED_LIBRARY})
add_executable(samplessh sample.c ${examples_SRCS})
target_link_libraries(samplessh ${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)
if (WITH_SERVER)
add_executable(samplesshd samplesshd.c)
target_link_libraries(samplesshd ${LIBSSH_SHARED_LIBRARY})
endif (WITH_SERVER)
endif (LINUX)
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})

View File

@@ -18,73 +18,109 @@ 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;
}
if (ssh_userauth_kbdint_setanswer(session, i, answer) < 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);
while (rc != SSH_AUTH_SUCCESS) {
// Try to authenticate with public key first
if (method & SSH_AUTH_METHOD_PUBLICKEY) {
rc = ssh_userauth_autopubkey(session, NULL);
if (rc == SSH_AUTH_ERROR) {
perror("Authentication failed.");
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
@@ -93,21 +129,24 @@ 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;
@@ -118,7 +157,7 @@ int authenticate_console(ssh_session session){
banner = ssh_get_issue_banner(session);
if (banner) {
printf("%s\n",banner);
free(banner);
ssh_string_free_char(banner);
}
return rc;

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -20,12 +20,15 @@ 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;
@@ -45,7 +48,7 @@ int verify_knownhost(ssh_session session){
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 +65,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 +89,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;
}

View File

@@ -182,7 +182,7 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
fd=fileno(src->file);
fstat(fd,&s);
size=s.st_size;
mode=s.st_mode;
mode = s.st_mode & ~S_IFMT;
filename=ssh_basename(src->path);
} else {
size=0;
@@ -207,7 +207,7 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
}
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));

33
examples/libsshpp.cpp Normal file
View 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.userauthAutopubkey();
session.disconnect();
} catch (ssh::SshException e){
std::cout << "Error during connection : ";
std::cout << e.getError() << std::endl;
}
return 0;
}

View 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.userauthAutopubkey();
if(err==SSH_ERROR)
goto error;
return 0;
error:
std::cout << "Error during connection : ";
std::cout << session.getError() << std::endl;
return 1;
}

View File

@@ -40,11 +40,7 @@ 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
char *proxycommand;
@@ -59,10 +55,13 @@ static int auth_callback(const char *prompt, char *buf, size_t len,
if (echo) {
while ((answer = fgets(buf, len, stdin)) == NULL);
if ((ptr = strchr(buf, '\n'))) {
ptr = '\0';
*ptr = '\0';
}
} else {
answer = getpass(prompt);
if (ssh_getpass(prompt, buf, len, 0, 0) < 0) {
return -1;
}
return 0;
}
if (answer == NULL) {
@@ -113,17 +112,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 +176,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 +199,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 +227,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 +238,22 @@ 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));
if(channel && ssh_channel_is_closed(channel)){
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
channel_free(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 +261,18 @@ 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));
ssh_log(session,SSH_LOG_RARE,"EOF received");
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_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 +280,23 @@ 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_log(session,SSH_LOG_RARE,"EOF received");
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(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 */
@@ -328,54 +331,60 @@ 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));
if(channel && ssh_channel_is_closed(channel)){
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
channel_free(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)!=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));
ssh_log(session,SSH_LOG_RARE,"EOF received");
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_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) && ssh_channel_poll(channel,1)!=0){ /* 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_log(session,SSH_LOG_RARE,"EOF received");
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(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 +398,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 +431,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;
}
@@ -473,13 +485,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 +504,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 +524,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();

View File

@@ -29,7 +29,7 @@ clients must be made or how a client should react.
int verbosity;
char *destination;
#define DATALEN 65536
static void do_sftp(ssh_session session){
sftp_session sftp=sftp_new(session);
sftp_dir dir;
@@ -40,7 +40,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 +202,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));
}
}

View File

@@ -23,7 +23,7 @@ clients must be made or how a client should react.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#ifndef KEYS_FOLDER
#ifdef _WIN32
#define KEYS_FOLDER
@@ -32,6 +32,32 @@ clients must be made or how a client should react.
#endif
#endif
#ifdef WITH_PCAP
const char *pcap_file="debug.server.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(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);
}
void cleanup_pcap(void);
void cleanup_pcap(){
ssh_pcap_file_free(pcap);
pcap=NULL;
}
#endif
static int auth_password(char *user, char *password){
if(strcmp(user,"aris"))
return 0;
@@ -147,7 +173,7 @@ int main(int argc, char **argv){
ssh_bind sshbind;
ssh_message message;
ssh_channel chan=0;
ssh_buffer buf;
char buf[2048];
int auth=0;
int sftp=0;
int i;
@@ -165,7 +191,14 @@ int main(int argc, char **argv){
* 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;
@@ -175,8 +208,8 @@ int main(int argc, char **argv){
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));
if (ssh_handle_key_exchange(session)) {
printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session));
return 1;
}
do {
@@ -254,15 +287,21 @@ int main(int argc, char **argv){
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));
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;
}
}
} while (i>0);
buffer_free(buf);
ssh_disconnect(session);
ssh_bind_free(sshbind);
#ifdef WITH_PCAP
cleanup_pcap();
#endif
ssh_finalize();
return 0;
}

View File

@@ -56,26 +56,34 @@ 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];
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)){
ssh_channel_read(channel,buffer,1,1);
if (write(1,buffer,1) < 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 +96,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 +114,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 +144,8 @@ static int fetch_files(ssh_session session){
}
} while (1);
end:
ssh_scp_close(scp);
ssh_scp_free(scp);
return 0;
}
@@ -144,6 +159,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
View 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;
}

View File

@@ -125,8 +125,14 @@ static void select_loop(ssh_session session,ssh_channel channel){
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);
@@ -141,7 +147,12 @@ static void select_loop(ssh_session session,ssh_channel channel){
channel_free(channel);
channel=channels[0]=NULL;
} else
write(2,buffer,lus);
ret = write(2, buffer, lus);
if (ret < 0) {
fprintf(stderr, "Error writing to stderr: %s",
strerror(errno));
return;
}
}
}
if(channel && channel_is_closed(channel)){

View File

@@ -4,6 +4,7 @@ set(libssh_HDRS
callbacks.h
libssh.h
ssh2.h
legacy.h
)
if (WITH_SFTP)

View File

@@ -48,7 +48,7 @@
#define SSH_AGENT_OLD_SIGNATURE 0x01
struct ssh_agent_struct {
struct socket *sock;
struct ssh_socket_struct *sock;
ssh_buffer ident;
unsigned int count;
};

86
include/libssh/auth.h Normal file
View File

@@ -0,0 +1,86 @@
/*
* 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 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);
#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
};
/** @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_ */

50
include/libssh/bind.h Normal file
View File

@@ -0,0 +1,50 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2010 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 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 *dsakey;
char *rsakey;
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_ */

View File

@@ -22,7 +22,14 @@
#ifndef BUFFER_H_
#define BUFFER_H_
/* Describes a buffer state */
#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;
@@ -30,6 +37,10 @@ struct ssh_buffer_struct {
uint32_t pos;
};
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);
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);

View File

@@ -33,6 +33,37 @@
extern "C" {
#endif
/**
* @defgroup libssh_callbacks The libssh callbacks
* @ingroup libssh
*
* Callback which can be replaced in libssh.
*
* @{
*/
/** @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 authentication callback.
*
@@ -46,33 +77,110 @@ extern "C" {
*
* @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);
/**
* @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 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 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);
/**
* 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;
};
typedef struct ssh_callbacks_struct *ssh_callbacks;
typedef struct ssh_callbacks_struct * ssh_callbacks;
/**
* 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;
/** Initializes an ssh_callbacks_struct
#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 +191,273 @@ 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.
*/
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);
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;
};
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 sets the thread callbacks 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() for instance), before
* ssh_init().
* @param cb pointer to a ssh_threads_callbacks_struct structure, which contains
* the different callbacks to be set.
* @see ssh_threads_callbacks_struct
* @see SSH_THREADS_PTHREAD
*/
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 returns a pointer on the noop threads callbacks, to be used with
* ssh_threads_set_callbacks. These callbacks do nothing and are being used by
* default.
* @see ssh_threads_set_callbacks
*/
LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_noop(void);
/** @} */
#ifdef __cplusplus
}
#endif
#endif /*_SSH_CALLBACK_H */
/* @} */

View File

@@ -23,9 +23,31 @@
#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_OPEN_DENIED,
SSH_CHANNEL_STATE_OPEN,
SSH_CHANNEL_STATE_CLOSED
};
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,7 +58,7 @@ 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;
ssh_buffer stdout_buffer;
ssh_buffer stderr_buffer;
@@ -44,15 +66,44 @@ struct ssh_channel_struct {
int version;
int blocking;
int exit_status;
enum ssh_channel_request_state_e request_state;
ssh_channel_callbacks callbacks;
};
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);
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);
#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_ */

View File

@@ -58,6 +58,8 @@ struct ssh_crypto_struct {
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 */
};

View File

@@ -1,9 +1,7 @@
/*
* callbacks.c - callback functions
*
* This file is part of the SSH Library
*
* Copyright (c) 2009 by Andreas Schneider <mail@cynapses.org>
* 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
@@ -21,17 +19,15 @@
* MA 02111-1307, USA.
*/
#include "config.h"
#ifndef KEX_H_
#define KEX_H_
#include "libssh/priv.h"
#include "libssh/callbacks.h"
#include "libssh/session.h"
int ssh_set_callbacks(ssh_session session, ssh_callbacks cb) {
if (session == NULL || cb == NULL) {
return -1;
}
SSH_PACKET_CALLBACK(ssh_packet_kexinit);
#ifdef WITH_SSH1
SSH_PACKET_CALLBACK(ssh_packet_publickey1);
#endif
session->callbacks = cb;
return 0;
}
#endif /* KEX_H_ */

100
include/libssh/legacy.h Normal file
View File

@@ -0,0 +1,100 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2010 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.
*/
/* 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.
*/
#include "libssh/libssh.h"
#ifndef LEGACY_H_
#define LEGACY_H_
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,
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,
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,
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,
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
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 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 ssh_message ssh_message_retrieve(ssh_session session, uint32_t packettype);
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);
#endif /* LEGACY_H_ */

View File

@@ -0,0 +1,74 @@
/*
* 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 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>
typedef SHA_CTX* SHACTX;
typedef MD5_CTX* MD5CTX;
typedef HMAC_CTX* HMACCTX;
#define SHA_DIGEST_LEN SHA_DIGEST_LENGTH
#ifdef MD5_DIGEST_LEN
#undef MD5_DIGEST_LEN
#endif
#define MD5_DIGEST_LEN MD5_DIGEST_LENGTH
#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)
struct crypto_struct *ssh_get_ciphertab(void);
#endif /* HAVE_LIBCRYPTO */
#endif /* LIBCRYPTO_H_ */

View File

@@ -0,0 +1,60 @@
/*
* 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 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 MD5CTX;
typedef gcry_md_hd_t HMACCTX;
#define SHA_DIGEST_LEN 20
#define MD5_DIGEST_LEN 16
#define EVP_MAX_MD_SIZE 36
typedef gcry_mpi_t bignum;
#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 crypto_struct *ssh_get_ciphertab(void);
#endif /* LIBGCRYPT_H_ */

View File

@@ -22,10 +22,10 @@
#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 +39,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 +78,8 @@
/* libssh version */
#define LIBSSH_VERSION_MAJOR 0
#define LIBSSH_VERSION_MINOR 4
#define LIBSSH_VERSION_MICRO 6
#define LIBSSH_VERSION_MINOR 5
#define LIBSSH_VERSION_MICRO 2
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
LIBSSH_VERSION_MINOR, \
@@ -113,6 +113,7 @@ 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;
@@ -154,6 +155,7 @@ enum ssh_auth_e {
SSH_AUTH_DENIED,
SSH_AUTH_PARTIAL,
SSH_AUTH_INFO,
SSH_AUTH_AGAIN,
SSH_AUTH_ERROR=-1
};
@@ -192,6 +194,19 @@ enum ssh_channel_requests_e {
SSH_CHANNEL_REQUEST_WINDOW_CHANGE
};
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 */
#define SSH_CLOSED 0x01
#define SSH_READ_PENDING 0x02
@@ -218,18 +233,29 @@ 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
};
/* 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
*/
/**
* @brief Verbosity level for logging and help to debugging
*/
enum {
/** No logging at all
*/
@@ -247,8 +273,7 @@ enum {
*/
SSH_LOG_FUNCTIONS
};
/** @}
*/
/** @} */
enum ssh_options_e {
SSH_OPTIONS_HOST,
@@ -266,13 +291,15 @@ 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
};
enum {
@@ -296,60 +323,42 @@ 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_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_poll(ssh_channel channel, 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_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 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);
@@ -361,6 +370,9 @@ 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);
LIBSSH_API ssh_channel ssh_forward_accept(ssh_session session, int timeout_ms);
LIBSSH_API int ssh_forward_cancel(ssh_session session, const char *address, int port);
LIBSSH_API int ssh_forward_listen(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);
@@ -375,13 +387,14 @@ 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_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);
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);
@@ -397,7 +410,7 @@ 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);
LIBSSH_API enum ssh_keytypes_e ssh_privatekey_type(ssh_private_key privatekey);
LIBSSH_API void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len);
LIBSSH_API int ssh_scp_accept_request(ssh_scp scp);
@@ -442,19 +455,28 @@ 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_privatekey_file(ssh_session session, const char *username,
const char *filename, const char *passphrase);
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 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);
#ifndef LIBSSH_LEGACY_0_4
#include "libssh/legacy.h"
#endif
#ifdef __cplusplus
}

604
include/libssh/libsshpp.hpp Normal file
View File

@@ -0,0 +1,604 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2010 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 LIBSSHPP_HPP_
#define LIBSSHPP_HPP_
/**
* @defgroup ssh_cpp The libssh C++ wrapper
*
* The C++ bindings for libssh are completely embedded in a single .hpp file, and
* this for two reasons:
* - C++ is hard to keep binary compatible, C is easy. We try to keep libssh C version
* as much as possible binary compatible between releases, while this would be hard for
* C++. If you compile your program with these headers, you will only link to the C version
* of libssh which will be kept ABI compatible. No need to recompile your C++ program
* each time a new binary-compatible version of libssh is out
* - Most of the functions in this file are really short and are probably worth the "inline"
* linking mode, which the compiler can decide to do in some case. There would be nearly no
* performance penalty of using the wrapper rather than native calls.
*
* Please visit the documentation of ssh::Session and ssh::Channel
* @see ssh::Session
* @see ssh::Channel
*
* If you wish not to use C++ exceptions, please define SSH_NO_CPP_EXCEPTIONS:
* @code
* #define SSH_NO_CPP_EXCEPTIONS
* #include <libssh/libsshpp.hpp>
* @endcode
* All functions will then return SSH_ERROR in case of error.
* @{
*/
/* do not use deprecated functions */
#define LIBSSH_LEGACY_0_4
#include <libssh/libssh.h>
#include <libssh/server.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
namespace ssh {
class Channel;
/** Some people do not like C++ exceptions. With this define, we give
* the choice to use or not exceptions.
* @brief if defined, disable C++ exceptions for libssh c++ wrapper
*/
#ifndef SSH_NO_CPP_EXCEPTIONS
/** @brief This class describes a SSH Exception object. This object can be thrown
* by several SSH functions that interact with the network, and may fail because of
* socket, protocol or memory errors.
*/
class SshException{
public:
SshException(ssh_session csession){
code=ssh_get_error_code(csession);
description=std::string(ssh_get_error(csession));
}
SshException(const SshException &e){
code=e.code;
description=e.description;
}
/** @brief returns the Error code
* @returns SSH_FATAL Fatal error happened (not recoverable)
* @returns SSH_REQUEST_DENIED Request was denied by remote host
* @see ssh_get_error_code
*/
int getCode(){
return code;
}
/** @brief returns the error message of the last exception
* @returns pointer to a c string containing the description of error
* @see ssh_get_error
*/
std::string getError(){
return description;
}
private:
int code;
std::string description;
};
/** @internal
* @brief Macro to throw exception if there was an error
*/
#define ssh_throw(x) if((x)==SSH_ERROR) throw SshException(getCSession())
#define ssh_throw_null(CSession,x) if((x)==NULL) throw SshException(CSession)
#define void_throwable void
#define return_throwable return
#else
/* No exception at all. All functions will return an error code instead
* of an exception
*/
#define ssh_throw(x) if((x)==SSH_ERROR) return SSH_ERROR
#define ssh_throw_null(CSession,x) if((x)==NULL) return NULL
#define void_throwable int
#define return_throwable return SSH_OK
#endif
/**
* The ssh::Session class contains the state of a SSH connection.
*/
class Session {
friend class Channel;
public:
Session(){
c_session=ssh_new();
}
~Session(){
ssh_free(c_session);
c_session=NULL;
}
/** @brief sets an SSH session options
* @param type Type of option
* @param option cstring containing the value of option
* @throws SshException on error
* @see ssh_options_set
*/
void_throwable setOption(enum ssh_options_e type, const char *option){
ssh_throw(ssh_options_set(c_session,type,option));
return_throwable;
}
/** @brief sets an SSH session options
* @param type Type of option
* @param option long integer containing the value of option
* @throws SshException on error
* @see ssh_options_set
*/
void_throwable setOption(enum ssh_options_e type, long int option){
ssh_throw(ssh_options_set(c_session,type,&option));
return_throwable;
}
/** @brief sets an SSH session options
* @param type Type of option
* @param option void pointer containing the value of option
* @throws SshException on error
* @see ssh_options_set
*/
void_throwable setOption(enum ssh_options_e type, void *option){
ssh_throw(ssh_options_set(c_session,type,option));
return_throwable;
}
/** @brief connects to the remote host
* @throws SshException on error
* @see ssh_connect
*/
void_throwable connect(){
int ret=ssh_connect(c_session);
ssh_throw(ret);
return_throwable;
}
/** @brief Authenticates automatically using public key
* @throws SshException on error
* @returns SSH_AUTH_SUCCESS, SSH_AUTH_PARTIAL, SSH_AUTH_DENIED
* @see ssh_userauth_autopubkey
*/
int userauthAutopubkey(void){
int ret=ssh_userauth_autopubkey(c_session,NULL);
ssh_throw(ret);
return ret;
}
/** @brief Authenticates using the "none" method. Prefer using autopubkey if
* possible.
* @throws SshException on error
* @returns SSH_AUTH_SUCCESS, SSH_AUTH_PARTIAL, SSH_AUTH_DENIED
* @see ssh_userauth_none
* @see Session::userauthAutoPubkey
*/
int userauthNone(){
int ret=ssh_userauth_none(c_session,NULL);
ssh_throw(ret);
return ret;
}
/** @brief Authenticates using the password method.
* @param[in] password password to use for authentication
* @throws SshException on error
* @returns SSH_AUTH_SUCCESS, SSH_AUTH_PARTIAL, SSH_AUTH_DENIED
* @see ssh_userauth_password
*/
int userauthPassword(const char *password){
int ret=ssh_userauth_password(c_session,NULL,password);
ssh_throw(ret);
return ret;
}
/** @brief Try to authenticate using the publickey method.
* @param[in] type public key type
* @param[in] pubkey public key to use for authentication
* @throws SshException on error
* @returns SSH_AUTH_SUCCESS if the pubkey is accepted,
* @returns SSH_AUTH_DENIED if the pubkey is denied
* @see ssh_userauth_offer_pubkey
*/
int userauthOfferPubkey(int type, ssh_string pubkey){
int ret=ssh_userauth_offer_pubkey(c_session,NULL,type,pubkey);
ssh_throw(ret);
return ret;
}
/** @brief Authenticates using the publickey method.
* @param[in] pubkey public key to use for authentication
* @param[in] privkey private key to use for authentication
* @throws SshException on error
* @returns SSH_AUTH_SUCCESS, SSH_AUTH_PARTIAL, SSH_AUTH_DENIED
* @see ssh_userauth_pubkey
*/
int userauthPubkey(ssh_string pubkey, ssh_private_key privkey){
int ret=ssh_userauth_pubkey(c_session,NULL,pubkey,privkey);
ssh_throw(ret);
return ret;
}
int userauthPubkey(ssh_private_key privkey){
int ret=ssh_userauth_pubkey(c_session,NULL,NULL,privkey);
ssh_throw(ret);
return ret;
}
int userauthPrivatekeyFile(const char *filename,
const char *passphrase);
/** @brief Returns the available authentication methods from the server
* @throws SshException on error
* @returns Bitfield of available methods.
* @see ssh_userauth_list
*/
int getAuthList(){
int ret=ssh_userauth_list(c_session, NULL);
ssh_throw(ret);
return ret;
}
/** @brief Disconnects from the SSH server and closes connection
* @see ssh_disconnect
*/
void disconnect(){
ssh_disconnect(c_session);
}
/** @brief Returns the disconnect message from the server, if any
* @returns pointer to the message, or NULL. Do not attempt to free
* the pointer.
*/
const char *getDisconnectMessage(){
const char *msg=ssh_get_disconnect_message(c_session);
return msg;
}
/** @internal
* @brief gets error message
*/
const char *getError(){
return ssh_get_error(c_session);
}
/** @internal
* @brief returns error code
*/
int getErrorCode(){
return ssh_get_error_code(c_session);
}
/** @brief returns the file descriptor used for the communication
* @returns the file descriptor
* @warning if a proxycommand is used, this function will only return
* one of the two file descriptors being used
* @see ssh_get_fd
*/
socket_t getSocket(){
return ssh_get_fd(c_session);
}
/** @brief gets the Issue banner from the ssh server
* @returns the issue banner. This is generally a MOTD from server
* @see ssh_get_issue_banner
*/
std::string getIssueBanner(){
char *banner=ssh_get_issue_banner(c_session);
std::string ret= std::string(banner);
::free(banner);
return ret;
}
/** @brief returns the OpenSSH version (server) if possible
* @returns openssh version code
* @see ssh_get_openssh_version
*/
int getOpensshVersion(){
return ssh_get_openssh_version(c_session);
}
/** @brief returns the version of the SSH protocol being used
* @returns the SSH protocol version
* @see ssh_get_version
*/
int getVersion(){
return ssh_get_version(c_session);
}
/** @brief verifies that the server is known
* @throws SshException on error
* @returns Integer value depending on the knowledge of the
* server key
* @see ssh_is_server_known
*/
int isServerKnown(){
int ret=ssh_is_server_known(c_session);
ssh_throw(ret);
return ret;
}
void log(int priority, const char *format, ...){
char buffer[1024];
va_list va;
va_start(va, format);
vsnprintf(buffer, sizeof(buffer), format, va);
va_end(va);
ssh_log(c_session,priority, "%s", buffer);
}
/** @brief copies options from a session to another
* @throws SshException on error
* @see ssh_options_copy
*/
void_throwable optionsCopy(const Session &source){
ssh_throw(ssh_options_copy(source.c_session,&c_session));
return_throwable;
}
/** @brief parses a configuration file for options
* @throws SshException on error
* @param[in] file configuration file name
* @see ssh_options_parse_config
*/
void_throwable optionsParseConfig(const char *file){
ssh_throw(ssh_options_parse_config(c_session,file));
return_throwable;
}
/** @brief silently disconnect from remote host
* @see ssh_silent_disconnect
*/
void silentDisconnect(){
ssh_silent_disconnect(c_session);
}
/** @brief Writes the known host file with current
* host key
* @throws SshException on error
* @see ssh_write_knownhost
*/
int writeKnownhost(){
int ret = ssh_write_knownhost(c_session);
ssh_throw(ret);
return ret;
}
/** @brief accept an incoming forward connection
* @param[in] timeout_ms timeout for waiting, in ms
* @returns new Channel pointer on the forward connection
* @returns NULL in case of error
* @warning you have to delete this pointer after use
* @see ssh_channel_forward_accept
* @see Session::listenForward
*/
Channel *acceptForward(int timeout_ms);
/* acceptForward is implemented later in this file */
void_throwable cancelForward(const char *address, int port){
int err=ssh_forward_cancel(c_session, address, port);
ssh_throw(err);
return_throwable;
}
void_throwable listenForward(const char *address, int port,
int &boundport){
int err=ssh_forward_listen(c_session, address, port, &boundport);
ssh_throw(err);
return_throwable;
}
private:
ssh_session c_session;
ssh_session getCSession(){
return c_session;
}
/* No copy constructor, no = operator */
Session(const Session &);
Session& operator=(const Session &);
};
/** @brief the ssh::Channel class describes the state of an SSH
* channel.
* @see ssh_channel
*/
class Channel {
friend class Session;
public:
Channel(Session &session){
channel=ssh_channel_new(session.getCSession());
this->session=&session;
}
~Channel(){
ssh_channel_free(channel);
channel=NULL;
}
/** @brief accept an incoming X11 connection
* @param[in] timeout_ms timeout for waiting, in ms
* @returns new Channel pointer on the X11 connection
* @returns NULL in case of error
* @warning you have to delete this pointer after use
* @see ssh_channel_accept_x11
* @see Channel::requestX11
*/
Channel *acceptX11(int timeout_ms){
ssh_channel x11chan = ssh_channel_accept_x11(channel,timeout_ms);
ssh_throw_null(getCSession(),x11chan);
Channel *newchan = new Channel(getSession(),x11chan);
return newchan;
}
/** @brief change the size of a pseudoterminal
* @param[in] cols number of columns
* @param[in] rows number of rows
* @throws SshException on error
* @see ssh_channel_change_pty_size
*/
void_throwable changePtySize(int cols, int rows){
int err=ssh_channel_change_pty_size(channel,cols,rows);
ssh_throw(err);
return_throwable;
}
/** @brief closes a channel
* @throws SshException on error
* @see ssh_channel_close
*/
void_throwable close(){
ssh_throw(ssh_channel_close(channel));
return_throwable;
}
int getExitStatus(){
return ssh_channel_get_exit_status(channel);
}
Session &getSession(){
return *session;
}
/** @brief returns true if channel is in closed state
* @see ssh_channel_is_closed
*/
bool isClosed(){
return ssh_channel_is_closed(channel) != 0;
}
/** @brief returns true if channel is in EOF state
* @see ssh_channel_is_eof
*/
bool isEof(){
return ssh_channel_is_eof(channel) != 0;
}
/** @brief returns true if channel is in open state
* @see ssh_channel_is_open
*/
bool isOpen(){
return ssh_channel_is_open(channel) != 0;
}
int openForward(const char *remotehost, int remoteport,
const char *sourcehost=NULL, int localport=0){
int err=ssh_channel_open_forward(channel,remotehost,remoteport,
sourcehost, localport);
ssh_throw(err);
return err;
}
/* TODO: completely remove this ? */
void_throwable openSession(){
int err=ssh_channel_open_session(channel);
ssh_throw(err);
return_throwable;
}
int poll(bool is_stderr=false){
int err=ssh_channel_poll(channel,is_stderr);
ssh_throw(err);
return err;
}
int read(void *dest, size_t count, bool is_stderr=false){
int err;
/* handle int overflow */
if(count > 0x7fffffff)
count = 0x7fffffff;
err=ssh_channel_read(channel,dest,count,is_stderr);
ssh_throw(err);
return err;
}
int readNonblocking(void *dest, size_t count, bool is_stderr=false){
int err;
/* handle int overflow */
if(count > 0x7fffffff)
count = 0x7fffffff;
err=ssh_channel_read_nonblocking(channel,dest,count,is_stderr);
ssh_throw(err);
return err;
}
void_throwable requestEnv(const char *name, const char *value){
int err=ssh_channel_request_env(channel,name,value);
ssh_throw(err);
return_throwable;
}
void_throwable requestExec(const char *cmd){
int err=ssh_channel_request_exec(channel,cmd);
ssh_throw(err);
return_throwable;
}
void_throwable requestPty(const char *term=NULL, int cols=0, int rows=0){
int err;
if(term != NULL && cols != 0 && rows != 0)
err=ssh_channel_request_pty_size(channel,term,cols,rows);
else
err=ssh_channel_request_pty(channel);
ssh_throw(err);
return_throwable;
}
void_throwable requestShell(){
int err=ssh_channel_request_shell(channel);
ssh_throw(err);
return_throwable;
}
void_throwable requestSendSignal(const char *signum){
int err=ssh_channel_request_send_signal(channel, signum);
ssh_throw(err);
return_throwable;
}
void_throwable requestSubsystem(const char *subsystem){
int err=ssh_channel_request_subsystem(channel,subsystem);
ssh_throw(err);
return_throwable;
}
int requestX11(bool single_connection,
const char *protocol, const char *cookie, int screen_number){
int err=ssh_channel_request_x11(channel,single_connection,
protocol, cookie, screen_number);
ssh_throw(err);
return err;
}
void_throwable sendEof(){
int err=ssh_channel_send_eof(channel);
ssh_throw(err);
return_throwable;
}
/** @brief Writes on a channel
* @param data data to write.
* @param len number of bytes to write.
* @param is_stderr write should be done on the stderr channel (server only)
* @returns number of bytes written
* @throws SshException in case of error
* @see channel_write
* @see channel_write_stderr
*/
int write(const void *data, size_t len, bool is_stderr=false){
int ret;
if(is_stderr){
ret=ssh_channel_write_stderr(channel,data,len);
} else {
ret=ssh_channel_write(channel,data,len);
}
ssh_throw(ret);
return ret;
}
private:
ssh_session getCSession(){
return session->getCSession();
}
Channel (Session &session, ssh_channel c_channel){
this->channel=c_channel;
this->session=&session;
}
Session *session;
ssh_channel channel;
/* No copy and no = operator */
Channel(const Channel &);
Channel &operator=(const Channel &);
};
/* This code cannot be put inline due to references to Channel */
Channel *Session::acceptForward(int timeout_ms){
ssh_channel forward = ssh_forward_accept(c_session,
timeout_ms);
ssh_throw_null(c_session,forward);
Channel *newchan = new Channel(*this,forward);
return newchan;
}
} // namespace ssh
/** @} */
#endif /* LIBSSHPP_HPP_ */

View File

@@ -47,6 +47,13 @@ struct ssh_service_request {
char *service;
};
struct ssh_global_request {
int type;
uint8_t want_reply;
char *bind_address;
uint16_t bind_port;
};
struct ssh_channel_request {
int type;
ssh_channel channel;
@@ -75,10 +82,17 @@ struct ssh_message_struct {
struct ssh_channel_request_open channel_request_open;
struct ssh_channel_request channel_request;
struct ssh_service_request service_request;
struct ssh_global_request global_request;
};
SSH_PACKET_CALLBACK(ssh_packet_channel_open);
SSH_PACKET_CALLBACK(ssh_packet_service_request);
SSH_PACKET_CALLBACK(ssh_packet_userauth_request);
SSH_PACKET_CALLBACK(ssh_packet_global_request);
void message_handle(ssh_session session, uint32_t type);
int ssh_execute_message_callbacks(ssh_session session);
int ssh_message_handle_channel_request(ssh_session session, ssh_channel channel, ssh_buffer packet,
const char *request, uint8_t want_reply);
void ssh_message_queue(ssh_session session, ssh_message message);
ssh_message ssh_message_pop_head(ssh_session session);
#endif /* MESSAGES_H_ */

View File

@@ -30,6 +30,9 @@ int ssh_file_readaccess_ok(const char *file);
char *ssh_path_expand_tilde(const char *d);
char *ssh_path_expand_escape(ssh_session session, const char *s);
int ssh_analyze_banner(ssh_session session, int server, int *ssh1, int *ssh2);
int ssh_is_ipaddr_v4(const char *str);
int ssh_is_ipaddr(const char *str);
/* macro for byte ordering */
uint64_t ntohll(uint64_t);
@@ -47,12 +50,19 @@ struct ssh_iterator {
const void *data;
};
struct ssh_timestamp {
long seconds;
long useconds;
};
struct ssh_list *ssh_list_new(void);
void ssh_list_free(struct ssh_list *list);
struct ssh_iterator *ssh_list_get_iterator(const struct ssh_list *list);
struct ssh_iterator *ssh_list_find(const struct ssh_list *list, void *value);
int ssh_list_append(struct ssh_list *list, const void *data);
int ssh_list_prepend(struct ssh_list *list, const void *data);
void ssh_list_remove(struct ssh_list *list, struct ssh_iterator *iterator);
char *ssh_lowercase(const char* str);
char *ssh_hostport(const char *host, int port);
const void *_ssh_list_pop_head(struct ssh_list *list);
@@ -68,4 +78,9 @@ const void *_ssh_list_pop_head(struct ssh_list *list);
#define ssh_list_pop_head(type, ssh_list)\
((type)_ssh_list_pop_head(ssh_list))
int ssh_make_milliseconds(long sec, long usec);
void ssh_timestamp_init(struct ssh_timestamp *ts);
int ssh_timeout_elapsed(struct ssh_timestamp *ts, int timeout);
int ssh_timeout_update(struct ssh_timestamp *ts, int timeout);
#endif /* MISC_H_ */

View File

@@ -29,13 +29,34 @@ typedef struct packet_struct {
uint8_t type;
} PACKET;
void packet_parse(ssh_session session);
/** different state of packet reading. */
enum ssh_packet_state_e {
/** Packet not initialized, must read the size of packet */
PACKET_STATE_INIT,
/** Size was read, waiting for the rest of data */
PACKET_STATE_SIZEREAD,
/** Full packet was read and callbacks are being called. Future packets
* should wait for the end of the callback. */
PACKET_STATE_PROCESSING
};
int packet_send(ssh_session session);
int packet_read(ssh_session session);
int packet_translate(ssh_session session);
int packet_wait(ssh_session session,int type,int blocking);
int packet_flush(ssh_session session, int enforce_blocking);
#ifdef WITH_SSH1
int packet_send1(ssh_session session) ;
void ssh_packet_set_default_callbacks1(ssh_session session);
SSH_PACKET_CALLBACK(ssh_packet_disconnect1);
SSH_PACKET_CALLBACK(ssh_packet_smsg_success1);
SSH_PACKET_CALLBACK(ssh_packet_smsg_failure1);
int ssh_packet_socket_callback1(const void *data, size_t receivedlen, void *user);
#endif
SSH_PACKET_CALLBACK(ssh_packet_unimplemented);
int ssh_packet_send_unimplemented(ssh_session session, uint32_t seqnum);
int ssh_packet_parse_type(ssh_session session);
//int packet_flush(ssh_session session, int enforce_blocking);
#endif /* PACKET_H_ */

49
include/libssh/pki.h Normal file
View File

@@ -0,0 +1,49 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2010 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 PKI_H_
#define PKI_H_
#define SSH_KEY_FLAG_EMPTY 0
#define SSH_KEY_FLAG_PUBLIC 1
#define SSH_KEY_FLAG_PRIVATE 2
struct ssh_key_struct {
enum ssh_keytypes_e type;
int flags;
const char *type_c; /* Don't free it ! it is static */
#ifdef HAVE_LIBGCRYPT
gcry_sexp_t dsa;
gcry_sexp_t rsa;
#elif HAVE_LIBCRYPTO
DSA *dsa;
RSA *rsa;
#endif
};
ssh_key ssh_key_new (void);
void ssh_key_clean (ssh_key key);
enum ssh_keytypes_e ssh_key_type(ssh_key key);
int ssh_key_import_private(ssh_key key, ssh_session session,
const char *filename, const char *passphrase);
void ssh_key_free (ssh_key key);
#endif /* PKI_H_ */

View File

@@ -121,7 +121,8 @@ typedef struct ssh_poll_ctx_struct *ssh_poll_ctx;
typedef struct ssh_poll_handle_struct *ssh_poll_handle;
/**
* @brief SSH poll callback.
* @brief SSH poll callback. This callback will be used when an event
* caught on the socket.
*
* @param p Poll object this callback belongs to.
* @param fd The raw socket.
@@ -129,7 +130,7 @@ typedef struct ssh_poll_handle_struct *ssh_poll_handle;
* @param userdata Userdata to be passed to the callback function.
*
* @return 0 on success, < 0 if you removed the poll object from
* it's poll context.
* its poll context.
*/
typedef int (*ssh_poll_callback)(ssh_poll_handle p, socket_t fd, int revents,
void *userdata);
@@ -144,13 +145,14 @@ void ssh_poll_set_events(ssh_poll_handle p, short events);
void ssh_poll_add_events(ssh_poll_handle p, short events);
void ssh_poll_remove_events(ssh_poll_handle p, short events);
socket_t ssh_poll_get_fd(ssh_poll_handle p);
void ssh_poll_set_fd(ssh_poll_handle p, socket_t fd);
void ssh_poll_set_callback(ssh_poll_handle p, ssh_poll_callback cb, void *userdata);
ssh_poll_ctx ssh_poll_ctx_new(size_t chunk_size);
void ssh_poll_ctx_free(ssh_poll_ctx ctx);
int ssh_poll_ctx_add(ssh_poll_ctx ctx, ssh_poll_handle p);
int ssh_poll_ctx_add_socket (ssh_poll_ctx ctx, struct ssh_socket_struct *s);
void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p);
int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout);
ssh_poll_ctx ssh_poll_get_default_ctx(ssh_session session);
#endif /* POLL_H_ */

View File

@@ -46,9 +46,6 @@
# undef inline
# define inline __inline
# undef strdup
# define strdup _strdup
# define strcasecmp _stricmp
# define strncasecmp _strnicmp
# define strtoull _strtoui64
@@ -87,9 +84,6 @@
# endif /* HAVE__VSNPRINTF */
# endif /* HAVE__VSNPRINTF_S */
# ifndef HAVE_STRNCPY
# define strncpy(d, s, n) strncpy_s((d), (n), (s), _TRUNCATE)
# endif
# endif /* _MSC_VER */
#else /* _WIN32 */
@@ -102,18 +96,13 @@
#include "libssh/libssh.h"
#include "libssh/callbacks.h"
#include "libssh/crypto.h"
/* some constants */
#define MAX_PACKET_LEN 262144
#define ERROR_BUFFERLEN 1024
#define CLIENTBANNER1 "SSH-1.5-libssh-" SSH_STRINGIFY(LIBSSH_VERSION)
#define CLIENTBANNER2 "SSH-2.0-libssh-" SSH_STRINGIFY(LIBSSH_VERSION)
#define KBDINT_MAX_PROMPT 256 /* more than openssh's :) */
/* some types for public keys */
enum public_key_types_e{
TYPE_DSS=1,
TYPE_RSA,
TYPE_RSA1
};
#ifdef __cplusplus
extern "C" {
@@ -131,7 +120,7 @@ typedef struct kex_struct {
struct error_struct {
/* error handling */
unsigned int error_code;
int error_code;
char error_buffer[ERROR_BUFFERLEN];
};
@@ -144,34 +133,20 @@ struct ssh_keys_struct {
};
struct ssh_message_struct;
struct ssh_common_struct;
/* server data */
struct ssh_bind_struct {
struct error_struct error;
ssh_callbacks callbacks; /* Callbacks to user functions */
/* options */
char *wanted_methods[10];
char *banner;
char *dsakey;
char *rsakey;
char *bindaddr;
socket_t bindfd;
unsigned int bindport;
unsigned int log_verbosity;
int blocking;
int toaccept;
};
SSH_PACKET_CALLBACK(ssh_packet_disconnect_callback);
SSH_PACKET_CALLBACK(ssh_packet_ignore_callback);
/* client.c */
int ssh_send_banner(ssh_session session, int is_server);
char *ssh_get_banner(ssh_session session);
SSH_PACKET_CALLBACK(ssh_packet_dh_reply);
SSH_PACKET_CALLBACK(ssh_packet_newkeys);
SSH_PACKET_CALLBACK(ssh_packet_service_accept);
/* config.c */
int ssh_config_parse_file(ssh_session session, const char *filename);
@@ -186,26 +161,36 @@ uint32_t packet_decrypt_len(ssh_session session,char *crypted);
int packet_decrypt(ssh_session session, void *packet,unsigned int len);
unsigned char *packet_encrypt(ssh_session session,void *packet,unsigned int len);
/* it returns the hmac buffer if exists*/
struct ssh_poll_handle_struct;
int packet_hmac_verify(ssh_session session,ssh_buffer buffer,unsigned char *mac);
struct ssh_socket_struct;
int ssh_packet_socket_callback(const void *data, size_t len, void *user);
void ssh_packet_register_socket_callback(ssh_session session, struct ssh_socket_struct *s);
void ssh_packet_set_callbacks(ssh_session session, ssh_packet_callbacks callbacks);
void ssh_packet_set_default_callbacks(ssh_session session);
void ssh_packet_process(ssh_session session, uint8_t type);
/* connect.c */
int ssh_regex_init(void);
void ssh_regex_finalize(void);
ssh_session ssh_session_new(void);
socket_t ssh_connect_host(ssh_session session, const char *host,const char
*bind_addr, int port, long timeout, long usec);
socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
const char *bind_addr, int port);
void ssh_sock_set_nonblocking(socket_t sock);
void ssh_sock_set_blocking(socket_t sock);
/* in kex.c */
extern const char *ssh_kex_nums[];
int ssh_send_kex(ssh_session session, int server_kex);
void ssh_list_kex(ssh_session session, KEX *kex);
int set_kex(ssh_session session);
int ssh_get_kex(ssh_session session, int server_kex);
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);
/* in base64.c */
ssh_buffer base64_to_bin(const char *source);
unsigned char *bin_to_base64(const unsigned char *source, int len);
@@ -217,28 +202,16 @@ int decompress_buffer(ssh_session session,ssh_buffer buf, size_t maxlen);
/* crc32.c */
uint32_t ssh_crc32(const char *buf, uint32_t len);
/* 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);
/* 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_handle1(ssh_session session, int type);
int channel_write1(ssh_channel channel, const void *data, int len);
/* match.c */
int match_hostname(const char *host, const char *pattern, unsigned int len);
int message_handle(ssh_session session, void *user, uint8_t type, ssh_buffer packet);
/* log.c */
void ssh_log_common(struct ssh_common_struct *common, int verbosity,
const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
/* misc.c */
#ifdef _WIN32
int gettimeofday(struct timeval *__p, void *__t);
@@ -252,16 +225,16 @@ int gettimeofday(struct timeval *__p, void *__t);
#define _enter_function(sess) \
do {\
if((sess)->log_verbosity >= SSH_LOG_FUNCTIONS){ \
if((sess)->common.log_verbosity >= SSH_LOG_FUNCTIONS){ \
ssh_log((sess),SSH_LOG_FUNCTIONS,"entering function %s line %d in " __FILE__ , __FUNCTION__,__LINE__);\
(sess)->log_indent++; \
(sess)->common.log_indent++; \
} \
} while(0)
#define _leave_function(sess) \
do { \
if((sess)->log_verbosity >= SSH_LOG_FUNCTIONS){ \
(sess)->log_indent--; \
if((sess)->common.log_verbosity >= SSH_LOG_FUNCTIONS){ \
(sess)->common.log_indent--; \
ssh_log((sess),SSH_LOG_FUNCTIONS,"leaving function %s line %d in " __FILE__ , __FUNCTION__,__LINE__);\
}\
} while(0)
@@ -279,6 +252,9 @@ int gettimeofday(struct timeval *__p, void *__t);
int ssh_options_set_algo(ssh_session session, int algo, const char *list);
int ssh_options_apply(ssh_session session);
/* server.c */
SSH_PACKET_CALLBACK(ssh_packet_kexdh_init);
/** Free memory space */
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)

View File

@@ -21,8 +21,8 @@
*/
/**
* @defgroup ssh_server SSH Server
* @addtogroup ssh_server
* @defgroup libssh_server The libssh server API
*
* @{
*/
@@ -48,9 +48,33 @@ enum ssh_bind_options_e {
SSH_BIND_OPTIONS_LOG_VERBOSITY_STR
};
//typedef struct ssh_bind_struct SSH_BIND;
typedef struct ssh_bind_struct* ssh_bind;
/* Callback functions */
/**
* @brief Incoming connection callback. This callback is called when a ssh_bind
* has a new incoming connection.
* @param sshbind Current sshbind session handler
* @param message the actual message
* @param userdata Userdata to be passed to the callback function.
*/
typedef void (*ssh_bind_incoming_connection_callback) (ssh_bind sshbind,
void *userdata);
/**
* @brief These are the callbacks exported by the ssh_bind structure.
*
* They are called by the server module when events appear on the network.
*/
struct ssh_bind_callbacks_struct {
/** DON'T SET THIS use ssh_callbacks_init() instead. */
size_t size;
/** A new connection is available. */
ssh_bind_incoming_connection_callback incoming_connection;
};
typedef struct ssh_bind_callbacks_struct *ssh_bind_callbacks;
/**
* @brief Creates a new SSH server bind.
*
@@ -59,15 +83,67 @@ typedef struct ssh_bind_struct* ssh_bind;
LIBSSH_API ssh_bind ssh_bind_new(void);
/**
* @brief Set the opitons for the current SSH server bind.
* @brief Set the options for the current SSH server bind.
*
* @param sshbind The ssh server bind to use.
* @param sshbind The ssh server bind to configure.
*
* @param type The option type to set.
* @param type The option type to set. This could be one of the
* following:
*
* @param value The option value to set.
* - SSH_BIND_OPTIONS_BINDADDR
* The ip address to bind (const char *).
*
* @return 0 on success, < 0 on error.
* - SSH_BIND_OPTIONS_BINDPORT
* The port to bind (unsigned int).
*
* - SSH_BIND_OPTIONS_BINDPORT_STR
* The port to bind (const char *).
*
* - SSH_BIND_OPTIONS_HOSTKEY
* This specifies the file containing the private host key used
* by SSHv1. (const char *).
*
* - SSH_BIND_OPTIONS_DSAKEY
* This specifies the file containing the private host dsa key
* used by SSHv2. (const char *).
*
* - SSH_BIND_OPTIONS_RSAKEY
* This specifies the file containing the private host dsa key
* used by SSHv2. (const char *).
*
* - SSH_BIND_OPTIONS_BANNER
* That the server banner (version string) for SSH.
* (const char *).
*
* - SSH_BIND_OPTIONS_LOG_VERBOSITY
* Set the session logging verbosity (int).\n
* \n
* The verbosity of the messages. Every log smaller or
* equal to verbosity will be shown.
* - SSH_LOG_NOLOG: No logging
* - SSH_LOG_RARE: Rare conditions or warnings
* - SSH_LOG_ENTRY: API-accessible entrypoints
* - SSH_LOG_PACKET: Packet id and size
* - SSH_LOG_FUNCTIONS: Function entering and leaving
*
* - SSH_BIND_OPTIONS_LOG_VERBOSITY_STR
* Set the session logging verbosity (const char *).\n
* \n
* The verbosity of the messages. Every log smaller or
* equal to verbosity will be shown.
* - SSH_LOG_NOLOG: No logging
* - SSH_LOG_RARE: Rare conditions or warnings
* - SSH_LOG_ENTRY: API-accessible entrypoints
* - SSH_LOG_PACKET: Packet id and size
* - SSH_LOG_FUNCTIONS: Function entering and leaving
* \n
* See the corresponding numbers in libssh.h.
*
* @param value The value to set. This is a generic pointer and the
* datatype which is used should be set according to the
* type set.
*
* @returns SSH_OK on success, SSH_ERROR on invalid option or parameter.
*/
LIBSSH_API int ssh_bind_options_set(ssh_bind sshbind,
enum ssh_bind_options_e type, const void *value);
@@ -81,6 +157,29 @@ LIBSSH_API int ssh_bind_options_set(ssh_bind sshbind,
*/
LIBSSH_API int ssh_bind_listen(ssh_bind ssh_bind_o);
/**
* @brief Set the callback for this bind.
*
* @param[in] sshbind The bind to set the callback on.
*
* @param[in] callbacks An already set up ssh_bind_callbacks instance.
*
* @param[in] userdata A pointer to private data to pass to the callbacks.
*
* @return SSH_OK on success, SSH_ERROR if an error occured.
*
* @code
* struct ssh_callbacks_struct cb = {
* .userdata = data,
* .auth_function = my_auth_function
* };
* ssh_callbacks_init(&cb);
* ssh_bind_set_callbacks(session, &cb);
* @endcode
*/
LIBSSH_API int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks,
void *userdata);
/**
* @brief Set the session to blocking/nonblocking mode.
*
@@ -121,10 +220,19 @@ LIBSSH_API void ssh_bind_fd_toaccept(ssh_bind ssh_bind_o);
* @param ssh_bind_o The ssh server bind to accept a connection.
* @param session A preallocated ssh session
* @see ssh_new
* @return A newly allocated ssh session, NULL on error.
* @return SSH_OK when a connection is established
*/
LIBSSH_API int ssh_bind_accept(ssh_bind ssh_bind_o, ssh_session session);
/**
* @brief Handles the key exchange and set up encryption
*
* @param session A connected ssh session
* @see ssh_bind_accept
* @return SSH_OK if the key exchange was successful
*/
LIBSSH_API int ssh_handle_key_exchange(ssh_session session);
/**
* @brief Free a ssh servers bind.
*
@@ -132,32 +240,29 @@ LIBSSH_API int ssh_bind_accept(ssh_bind ssh_bind_o, ssh_session session);
*/
LIBSSH_API void ssh_bind_free(ssh_bind ssh_bind_o);
/**
* @brief Exchange the banner and cryptographic keys.
*
* @param session The ssh session to accept a connection.
*
* @return 0 on success, < 0 on error.
*/
LIBSSH_API int ssh_accept(ssh_session session);
LIBSSH_API int channel_write_stderr(ssh_channel channel, const void *data, uint32_t len);
/* messages.c */
LIBSSH_API int ssh_message_reply_default(ssh_message msg);
LIBSSH_API char *ssh_message_auth_user(ssh_message msg);
LIBSSH_API char *ssh_message_auth_password(ssh_message msg);
LIBSSH_API ssh_public_key ssh_message_auth_publickey(ssh_message msg);
LIBSSH_API enum ssh_publickey_state_e ssh_message_auth_publickey_state(ssh_message msg);
LIBSSH_API int ssh_message_auth_reply_success(ssh_message msg,int partial);
LIBSSH_API int ssh_message_auth_reply_pk_ok(ssh_message msg, ssh_string algo, ssh_string pubkey);
LIBSSH_API int ssh_message_auth_reply_pk_ok_simple(ssh_message msg);
LIBSSH_API int ssh_message_auth_set_methods(ssh_message msg, int methods);
LIBSSH_API int ssh_message_service_reply_success(ssh_message msg);
LIBSSH_API char *ssh_message_service_service(ssh_message msg);
LIBSSH_API int ssh_message_global_request_reply_success(ssh_message msg,
uint16_t bound_port);
LIBSSH_API void ssh_set_message_callback(ssh_session session,
int(*ssh_message_callback)(ssh_session session, ssh_message msg));
int(*ssh_bind_message_callback)(ssh_session session, ssh_message msg, void *data),
void *data);
LIBSSH_API int ssh_execute_message_callbacks(ssh_session session);
LIBSSH_API char *ssh_message_channel_request_open_originator(ssh_message msg);
LIBSSH_API int ssh_message_channel_request_open_originator_port(ssh_message msg);
@@ -179,13 +284,32 @@ LIBSSH_API char *ssh_message_channel_request_command(ssh_message msg);
LIBSSH_API char *ssh_message_channel_request_subsystem(ssh_message msg);
LIBSSH_API char *ssh_message_global_request_address(ssh_message msg);
LIBSSH_API int ssh_message_global_request_port(ssh_message msg);
LIBSSH_API int ssh_channel_open_reverse_forward(ssh_channel channel, const char *remotehost,
int remoteport, const char *sourcehost, int localport);
LIBSSH_API int ssh_channel_request_send_exit_status(ssh_channel channel,
int exit_status);
LIBSSH_API int ssh_channel_request_send_exit_signal(ssh_channel channel,
const char *signum,
int core,
const char *errmsg,
const char *lang);
LIBSSH_API int ssh_channel_write_stderr(ssh_channel channel,
const void *data,
uint32_t len);
/* deprecated functions */
SSH_DEPRECATED LIBSSH_API int ssh_accept(ssh_session session);
SSH_DEPRECATED LIBSSH_API int channel_write_stderr(ssh_channel channel,
const void *data, uint32_t len);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* SERVER_H */
/**
* @}
*/
/* vim: set ts=2 sw=2 et cindent: */
/** @} */

View File

@@ -24,12 +24,54 @@
#include "libssh/priv.h"
#include "libssh/packet.h"
#include "libssh/pcap.h"
#include "libssh/auth.h"
#include "libssh/channels.h"
#include "libssh/poll.h"
typedef struct ssh_kbdint_struct* ssh_kbdint;
struct ssh_session_struct {
/* These are the different states a SSH session can be into its life */
enum ssh_session_state_e {
SSH_SESSION_STATE_NONE=0,
SSH_SESSION_STATE_CONNECTING,
SSH_SESSION_STATE_SOCKET_CONNECTED,
SSH_SESSION_STATE_BANNER_RECEIVED,
SSH_SESSION_STATE_INITIAL_KEX,
SSH_SESSION_STATE_KEXINIT_RECEIVED,
SSH_SESSION_STATE_DH,
SSH_SESSION_STATE_AUTHENTICATING,
SSH_SESSION_STATE_AUTHENTICATED,
SSH_SESSION_STATE_ERROR,
SSH_SESSION_STATE_DISCONNECTED
};
enum ssh_dh_state_e {
DH_STATE_INIT=0,
DH_STATE_INIT_SENT,
DH_STATE_NEWKEYS_SENT,
DH_STATE_FINISHED
};
enum ssh_pending_call_e {
SSH_PENDING_CALL_NONE = 0,
SSH_PENDING_CALL_CONNECT,
SSH_PENDING_CALL_AUTH_NONE,
SSH_PENDING_CALL_AUTH_PASSWORD
};
/* libssh calls may block an undefined amount of time */
#define SSH_SESSION_FLAG_BLOCKING 1
/* members that are common to ssh_session and ssh_bind */
struct ssh_common_struct {
struct error_struct error;
struct socket *socket;
ssh_callbacks callbacks; /* Callbacks to user functions */
int log_verbosity; /* verbosity of the log functions */
int log_indent; /* indentation level in enter_function logs */
};
struct ssh_session_struct {
struct ssh_common_struct common;
struct ssh_socket_struct *socket;
char *serverbanner;
char *clientbanner;
int protoversion;
@@ -46,15 +88,13 @@ struct ssh_session_struct {
/* !=0 when the user got a session handle */
int alive;
/* two previous are deprecated */
int auth_service_asked;
/* int auth_service_asked; */
/* socket status */
int blocking; // functions should block
/* session flags (SSH_SESSION_FLAG_*) */
int flags;
ssh_string banner; /* that's the issue banner from
the server */
char *remotebanner; /* that's the SSH- banner from
remote host. */
char *discon_msg; /* disconnect message from
the remote host */
ssh_buffer in_buffer;
@@ -63,10 +103,14 @@ struct ssh_session_struct {
/* the states are used by the nonblocking stuff to remember */
/* where it was before being interrupted */
enum ssh_pending_call_e pending_call_state;
enum ssh_session_state_e session_state;
int packet_state;
int dh_handshake_state;
ssh_string dh_server_signature; //information used by dh_handshake.
enum ssh_dh_state_e dh_handshake_state;
enum ssh_auth_service_state_e auth_service_state;
enum ssh_auth_state_e auth_state;
enum ssh_channel_request_state_e global_req_state;
ssh_string dh_server_signature; /* information used by dh_handshake. */
KEX server_kex;
KEX client_kex;
ssh_buffer in_hashbuf;
@@ -74,7 +118,7 @@ struct ssh_session_struct {
struct ssh_crypto_struct *current_crypto;
struct ssh_crypto_struct *next_crypto; /* next_crypto is going to be used after a SSH2_MSG_NEWKEYS */
ssh_channel channels; /* linked list of channels */
struct ssh_list *channels; /* linked list of channels */
int maxchannel;
int exec_channel_opened; /* version 1 only. more
info in channels1.c */
@@ -90,12 +134,14 @@ struct ssh_session_struct {
int auth_methods;
int hostkeys; /* contains type of host key wanted by client, in server impl */
struct ssh_list *ssh_message_list; /* list of delayed SSH messages */
int (*ssh_message_callback)( struct ssh_session_struct *session, ssh_message msg);
int log_verbosity; /*cached copy of the option structure */
int log_indent; /* indentation level in enter_function logs */
ssh_callbacks callbacks; /* Callbacks to user functions */
int (*ssh_message_callback)( struct ssh_session_struct *session, ssh_message msg, void *userdata);
void *ssh_message_callback_data;
void (*ssh_connection_callback)( struct ssh_session_struct *session);
struct ssh_packet_callbacks_struct default_packet_callbacks;
struct ssh_list *packet_callbacks;
struct ssh_socket_callbacks_struct socket_callbacks;
ssh_poll_ctx default_poll_ctx;
/* options */
#ifdef WITH_PCAP
ssh_pcap_context pcap_ctx; /* pcap debugging context */
@@ -108,15 +154,26 @@ struct ssh_session_struct {
char *sshdir;
char *knownhosts;
char *wanted_methods[10];
char compressionlevel;
unsigned long timeout; /* seconds */
unsigned long timeout_usec;
unsigned int port;
socket_t fd;
int ssh2;
int ssh1;
int StrictHostKeyChecking;
char *ProxyCommand;
};
int ssh_handle_packets(ssh_session session);
void ssh_global_request_handle(ssh_session session);
/** @internal
* @brief a termination function evaluates the status of an object
* @param user[in] object to evaluate
* @returns 1 if the polling routine should terminate, 0 instead
*/
typedef int (*ssh_termination_function)(void *user);
int ssh_handle_packets(ssh_session session, int timeout);
int ssh_handle_packets_termination(ssh_session session, int timeout,
ssh_termination_function fct, void *user);
void ssh_socket_exception_callback(int code, int errno_code, void *user);
#endif /* SESSION_H_ */

View File

@@ -32,7 +32,7 @@
* it can fetch it, while continuing to read for other messages (it is
* unspecified in which order messages may be sent back to the client
*
* @defgroup ssh_sftp SFTP Functions
* @defgroup libssh_sftp The libssh SFTP API
* @{
*/
@@ -843,22 +843,44 @@ void sftp_handle_remove(sftp_session sftp, void *handle);
#define SSH_FILEXFER_TYPE_SPECIAL 4
#define SSH_FILEXFER_TYPE_UNKNOWN 5
/* server responses */
/**
* @name Server responses
*
* @brief Responses returned by the sftp server.
* @{
*/
/** No error */
#define SSH_FX_OK 0
/** End-of-file encountered */
#define SSH_FX_EOF 1
/** File doesn't exist */
#define SSH_FX_NO_SUCH_FILE 2
/** Permission denied */
#define SSH_FX_PERMISSION_DENIED 3
/** Generic failure */
#define SSH_FX_FAILURE 4
/** Garbage received from server */
#define SSH_FX_BAD_MESSAGE 5
/** No connection has been set up */
#define SSH_FX_NO_CONNECTION 6
/** There was a connection, but we lost it */
#define SSH_FX_CONNECTION_LOST 7
/** Operation not supported by the server */
#define SSH_FX_OP_UNSUPPORTED 8
/** Invalid file handle */
#define SSH_FX_INVALID_HANDLE 9
/** No such file or directory path exists */
#define SSH_FX_NO_SUCH_PATH 10
/** An attempt to create an already existing file or directory has been made */
#define SSH_FX_FILE_ALREADY_EXISTS 11
/** We are trying to write on a write-protected filesystem */
#define SSH_FX_WRITE_PROTECT 12
/** No media in remote drive */
#define SSH_FX_NO_MEDIA 13
/** @} */
/* file flags */
#define SSH_FXF_READ 0x01
#define SSH_FXF_WRITE 0x02

View File

@@ -22,41 +22,47 @@
#ifndef SOCKET_H_
#define SOCKET_H_
#include "libssh/callbacks.h"
struct ssh_poll_handle_struct;
/* socket.c */
struct socket;
int ssh_socket_init(void);
struct socket *ssh_socket_new(ssh_session session);
void ssh_socket_free(struct socket *s);
void ssh_socket_set_fd(struct socket *s, socket_t fd);
socket_t ssh_socket_get_fd(struct socket *s);
void ssh_socket_cleanup(void);
#ifndef _WIN32
int ssh_socket_unix(struct socket *s, const char *path);
#endif
void ssh_socket_close(struct socket *s);
int ssh_socket_read(struct socket *s, void *buffer, int len);
int ssh_socket_write(struct socket *s,const void *buffer, int len);
int ssh_socket_is_open(struct socket *s);
int ssh_socket_fd_isset(struct socket *s, fd_set *set);
void ssh_socket_fd_set(struct socket *s, fd_set *set, socket_t *max_fd);
int ssh_socket_completeread(struct socket *s, void *buffer, uint32_t len);
int ssh_socket_completewrite(struct socket *s, const void *buffer, uint32_t len);
int ssh_socket_wait_for_data(struct socket *s, ssh_session session, uint32_t len);
int ssh_socket_nonblocking_flush(struct socket *s);
int ssh_socket_blocking_flush(struct socket *s);
int ssh_socket_poll(struct socket *s, int *writeable, int *except);
void ssh_socket_set_towrite(struct socket *s);
void ssh_socket_set_toread(struct socket *s);
void ssh_socket_set_except(struct socket *s);
int ssh_socket_get_status(struct socket *s);
int ssh_socket_data_available(struct socket *s);
int ssh_socket_data_writable(struct socket *s);
struct ssh_socket_struct;
typedef struct ssh_socket_struct* ssh_socket;
int ssh_socket_init(void);
void ssh_socket_cleanup(void);
ssh_socket ssh_socket_new(ssh_session session);
void ssh_socket_reset(ssh_socket s);
void ssh_socket_free(ssh_socket s);
void ssh_socket_set_fd(ssh_socket s, socket_t fd);
socket_t ssh_socket_get_fd_in(ssh_socket s);
#ifndef _WIN32
int ssh_socket_unix(ssh_socket s, const char *path);
void ssh_execute_command(const char *command, socket_t in, socket_t out);
socket_t ssh_socket_connect_proxycommand(ssh_session session,
const char *command);
int ssh_socket_connect_proxycommand(ssh_socket s, const char *command);
#endif
void ssh_socket_close(ssh_socket s);
int ssh_socket_write(ssh_socket s,const void *buffer, int len);
int ssh_socket_is_open(ssh_socket s);
int ssh_socket_fd_isset(ssh_socket s, fd_set *set);
void ssh_socket_fd_set(ssh_socket s, fd_set *set, socket_t *max_fd);
void ssh_socket_set_fd_in(ssh_socket s, socket_t fd);
void ssh_socket_set_fd_out(ssh_socket s, socket_t fd);
int ssh_socket_nonblocking_flush(ssh_socket s);
void ssh_socket_set_write_wontblock(ssh_socket s);
void ssh_socket_set_read_wontblock(ssh_socket s);
void ssh_socket_set_except(ssh_socket s);
int ssh_socket_get_status(ssh_socket s);
int ssh_socket_buffered_write_bytes(ssh_socket s);
int ssh_socket_data_available(ssh_socket s);
int ssh_socket_data_writable(ssh_socket s);
void ssh_socket_set_callbacks(ssh_socket s, ssh_socket_callbacks callbacks);
int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int revents, void *v_s);
struct ssh_poll_handle_struct * ssh_socket_get_poll_handle_in(ssh_socket s);
struct ssh_poll_handle_struct * ssh_socket_get_poll_handle_out(ssh_socket s);
void ssh_socket_set_connecting(ssh_socket s, socket_t fd);
int ssh_socket_connect(ssh_socket s, const char *host, int port, const char *bind_addr);
#endif /* SOCKET_H_ */

32
include/libssh/threads.h Normal file
View File

@@ -0,0 +1,32 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2010 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 THREADS_H_
#define THREADS_H_
#include <libssh/libssh.h>
#include <libssh/callbacks.h>
int ssh_threads_init(void);
void ssh_threads_finalize(void);
const char *ssh_threads_get_type(void);
#endif /* THREADS_H_ */

View File

@@ -23,79 +23,8 @@
#define WRAPPER_H_
#include "config.h"
#ifdef MD5_DIGEST_LEN
#undef MD5_DIGEST_LEN
#endif
/* wrapper things */
#ifdef HAVE_LIBGCRYPT
#include <gcrypt.h>
typedef gcry_md_hd_t SHACTX;
typedef gcry_md_hd_t MD5CTX;
typedef gcry_md_hd_t HMACCTX;
#define SHA_DIGEST_LEN 20
#define MD5_DIGEST_LEN 16
#define EVP_MAX_MD_SIZE 36
typedef gcry_mpi_t bignum;
#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)
#elif defined HAVE_LIBCRYPTO
#include <openssl/dsa.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include <openssl/md5.h>
#include <openssl/hmac.h>
typedef SHA_CTX* SHACTX;
typedef MD5_CTX* MD5CTX;
typedef HMAC_CTX* HMACCTX;
#define SHA_DIGEST_LEN SHA_DIGEST_LENGTH
#define MD5_DIGEST_LEN MD5_DIGEST_LENGTH
#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)
#endif /* OPENSSL_CRYPTO */
#include "libssh/libcrypto.h"
#include "libssh/libgcrypt.h"
MD5CTX md5_init(void);
void md5_update(MD5CTX c, const void *data, unsigned long len);

6
libssh.pc.cmake Normal file
View File

@@ -0,0 +1,6 @@
Name: ${APPLICATION_NAME}
Description: The SSH Library
Version: ${APPLICATION_VERSION}
Libs: -L${LIB_INSTALL_DIR} -lssh
Cflags: -I${INCLUDE_INSTALL_DIR}

View File

@@ -1,462 +0,0 @@
/*
* buffer.c - buffer functions
*
* This file is part of the SSH Library
*
* 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.
*
* The SSH Library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the SSH Library; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <string.h>
#ifndef _WIN32
#include <arpa/inet.h>
#endif
#include "libssh/priv.h"
#include "libssh/buffer.h"
/** \defgroup ssh_buffer SSH Buffers
* \brief buffer handling
*/
/** \addtogroup ssh_buffer
* @{
*/
/** \brief checks that preconditions and postconditions are valid
* \internal
*/
#ifdef DEBUG_BUFFER
static void buffer_verify(struct buffer_struct *buf){
int doabort=0;
if(buf->data == NULL)
return;
if(buf->used > buf->allocated){
fprintf(stderr,"Buffer error : allocated %u, used %u\n",buf->allocated, buf->used);
doabort=1;
}
if(buf->pos > buf->used){
fprintf(stderr,"Buffer error : position %u, used %u\n",buf->pos, buf->used);
doabort=1;
}
if(buf->pos > buf->allocated){
fprintf(stderr,"Buffer error : position %u, allocated %u\n",buf->pos, buf->allocated);
doabort=1;
}
if(doabort)
abort();
}
#else
#define buffer_verify(x)
#endif
/** \brief creates a new buffer
* \return a new initialized buffer, NULL on error.
*/
struct ssh_buffer_struct *buffer_new(void) {
struct ssh_buffer_struct *buf = malloc(sizeof(struct ssh_buffer_struct));
if (buf == NULL) {
return NULL;
}
memset(buf, 0, sizeof(struct ssh_buffer_struct));
buffer_verify(buf);
return buf;
}
/** \brief deallocate a buffer
* \param buffer buffer to free
*/
void buffer_free(struct ssh_buffer_struct *buffer) {
if (buffer == NULL) {
return;
}
buffer_verify(buffer);
if (buffer->data) {
/* burn the data */
memset(buffer->data, 0, buffer->allocated);
SAFE_FREE(buffer->data);
}
memset(buffer, 'X', sizeof(*buffer));
SAFE_FREE(buffer);
}
static int realloc_buffer(struct ssh_buffer_struct *buffer, int needed) {
int smallest = 1;
char *new = NULL;
buffer_verify(buffer);
/* Find the smallest power of two which is greater or equal to needed */
while(smallest < needed) {
smallest <<= 1;
}
needed = smallest;
new = realloc(buffer->data, needed);
if (new == NULL) {
return -1;
}
buffer->data = new;
buffer->allocated = needed;
buffer_verify(buffer);
return 0;
}
/* \internal
* \brief reinitialize a buffer
* \param buffer buffer
* \return 0 on sucess, < 0 on error
*/
int buffer_reinit(struct ssh_buffer_struct *buffer) {
buffer_verify(buffer);
memset(buffer->data, 0, buffer->used);
buffer->used = 0;
buffer->pos = 0;
if(buffer->allocated > 127) {
if (realloc_buffer(buffer, 127) < 0) {
return -1;
}
}
buffer_verify(buffer);
return 0;
}
/** \internal
* \brief add data at tail of the buffer
* \param buffer buffer
* \param data data pointer
* \param len length of data
*/
int buffer_add_data(struct ssh_buffer_struct *buffer, const void *data, uint32_t len) {
buffer_verify(buffer);
if (buffer->allocated < (buffer->used + len)) {
if (realloc_buffer(buffer, buffer->used + len) < 0) {
return -1;
}
}
memcpy(buffer->data+buffer->used, data, len);
buffer->used+=len;
buffer_verify(buffer);
return 0;
}
/** \internal
* \brief add a SSH string to the tail of buffer
* \param buffer buffer
* \param string SSH String to add
* \return 0 on success, -1 on error.
*/
int buffer_add_ssh_string(struct ssh_buffer_struct *buffer,
struct ssh_string_struct *string) {
uint32_t len = 0;
len = string_len(string);
if (buffer_add_data(buffer, string, len + sizeof(uint32_t)) < 0) {
return -1;
}
return 0;
}
/** \internal
* \brief add a 32 bits unsigned integer to the tail of buffer
* \param buffer buffer
* \param data 32 bits integer
* \return 0 on success, -1 on error.
*/
int buffer_add_u32(struct ssh_buffer_struct *buffer,uint32_t data){
if (buffer_add_data(buffer, &data, sizeof(data)) < 0) {
return -1;
}
return 0;
}
/** \internal
* \brief add a 16 bits unsigned integer to the tail of buffer
* \param buffer buffer
* \param data 16 bits integer
* \return 0 on success, -1 on error.
*/
int buffer_add_u16(struct ssh_buffer_struct *buffer,uint16_t data){
if (buffer_add_data(buffer, &data, sizeof(data)) < 0) {
return -1;
}
return 0;
}
/** \internal
* \brief add a 64 bits unsigned integer to the tail of buffer
* \param buffer buffer
* \param data 64 bits integer
* \return 0 on success, -1 on error.
*/
int buffer_add_u64(struct ssh_buffer_struct *buffer, uint64_t data){
if (buffer_add_data(buffer, &data, sizeof(data)) < 0) {
return -1;
}
return 0;
}
/** \internal
* \brief add a 8 bits unsigned integer to the tail of buffer
* \param buffer buffer
* \param data 8 bits integer
* \return 0 on success, -1 on error.
*/
int buffer_add_u8(struct ssh_buffer_struct *buffer,uint8_t data){
if (buffer_add_data(buffer, &data, sizeof(uint8_t)) < 0) {
return -1;
}
return 0;
}
/** \internal
* \brief add data at head of a buffer
* \param buffer buffer
* \param data data to add
* \param len length of data
* \return 0 on success, -1 on error.
*/
int buffer_prepend_data(struct ssh_buffer_struct *buffer, const void *data,
uint32_t len) {
buffer_verify(buffer);
if (buffer->allocated < (buffer->used + len)) {
if (realloc_buffer(buffer, buffer->used + len) < 0) {
return -1;
}
}
memmove(buffer->data + len, buffer->data, buffer->used);
memcpy(buffer->data, data, len);
buffer->used += len;
buffer_verify(buffer);
return 0;
}
/** \internal
* \brief append data from a buffer to tail of another
* \param buffer destination buffer
* \param source source buffer. Doesn't take position in buffer into account
* \return 0 on success, -1 on error.
*/
int buffer_add_buffer(struct ssh_buffer_struct *buffer,
struct ssh_buffer_struct *source) {
if (buffer_add_data(buffer, buffer_get(source), buffer_get_len(source)) < 0) {
return -1;
}
return 0;
}
/** \brief get a pointer on the head of the buffer
* \param buffer buffer
* \return data pointer on the head. Doesn't take position into account.
* \warning don't expect data to be nul-terminated
* \see buffer_get_rest()
* \see buffer_get_len()
*/
void *buffer_get(struct ssh_buffer_struct *buffer){
return buffer->data;
}
/** \internal
* \brief get a pointer to head of the buffer at current position
* \param buffer buffer
* \return pointer to the data from current position
* \see buffer_get_rest_len()
* \see buffer_get()
*/
void *buffer_get_rest(struct ssh_buffer_struct *buffer){
return buffer->data + buffer->pos;
}
/** \brief get length of the buffer, not counting position
* \param buffer
* \return length of the buffer
* \see buffer_get()
*/
uint32_t buffer_get_len(struct ssh_buffer_struct *buffer){
return buffer->used;
}
/** \internal
* \brief get length of the buffer from the current position
* \param buffer
* \return length of the buffer
* \see buffer_get_rest()
*/
uint32_t buffer_get_rest_len(struct ssh_buffer_struct *buffer){
buffer_verify(buffer);
return buffer->used - buffer->pos;
}
/** \internal
* has effect to "eat" bytes at head of the buffer
* \brief advance the position in the buffer
* \param buffer buffer
* \param len number of bytes to eat
* \return new size of the buffer
*/
uint32_t buffer_pass_bytes(struct ssh_buffer_struct *buffer, uint32_t len){
buffer_verify(buffer);
if(buffer->used < buffer->pos+len)
return 0;
buffer->pos+=len;
/* if the buffer is empty after having passed the whole bytes into it, we can clean it */
if(buffer->pos==buffer->used){
buffer->pos=0;
buffer->used=0;
}
buffer_verify(buffer);
return len;
}
/** \internal
* \brief cut the end of the buffer
* \param buffer buffer
* \param len number of bytes to remove from tail
* \return new size of the buffer
*/
uint32_t buffer_pass_bytes_end(struct ssh_buffer_struct *buffer, uint32_t len){
buffer_verify(buffer);
if(buffer->used < buffer->pos + len)
return 0;
buffer->used-=len;
buffer_verify(buffer);
return len;
}
/** \internal
* \brief gets remaining data out of the buffer. Adjust the read pointer.
* \param buffer Buffer to read
* \param data data buffer where to store the data
* \param len length to read from the buffer
* \returns 0 if there is not enough data in buffer
* \returns len otherwise.
*/
uint32_t buffer_get_data(struct ssh_buffer_struct *buffer, void *data, uint32_t len){
/*
* Check for a integer overflow first, then check if not enough data is in
* the buffer.
*/
if (buffer->pos + len < len || buffer->pos + len > buffer->used) {
return 0;
}
memcpy(data,buffer->data+buffer->pos,len);
buffer->pos+=len;
return len; /* no yet support for partial reads (is it really needed ?? ) */
}
/** \internal
* \brief gets a 8 bits unsigned int out of the buffer. Adjusts the read pointer.
* \param buffer Buffer to read
* \param data pointer to a uint8_t where to store the data
* \returns 0 if there is not enough data in buffer
* \returns 1 otherwise.
*/
int buffer_get_u8(struct ssh_buffer_struct *buffer, uint8_t *data){
return buffer_get_data(buffer,data,sizeof(uint8_t));
}
/** \internal
* \brief gets a 32 bits unsigned int out of the buffer. Adjusts the read pointer.
* \param buffer Buffer to read
* \param data pointer to a uint32_t where to store the data
* \returns 0 if there is not enough data in buffer
* \returns 4 otherwise.
*/
int buffer_get_u32(struct ssh_buffer_struct *buffer, uint32_t *data){
return buffer_get_data(buffer,data,sizeof(uint32_t));
}
/** \internal
* \brief gets a 64 bits unsigned int out of the buffer. Adjusts the read pointer.
* \param buffer Buffer to read
* \param data pointer to a uint64_t where to store the data
* \returns 0 if there is not enough data in buffer
* \returns 8 otherwise.
*/
int buffer_get_u64(struct ssh_buffer_struct *buffer, uint64_t *data){
return buffer_get_data(buffer,data,sizeof(uint64_t));
}
/** \internal
* \brief gets a SSH String out of the buffer. Adjusts the read pointer.
* \param buffer Buffer to read
* \returns The SSH String read
* \returns NULL otherwise.
*/
struct ssh_string_struct *buffer_get_ssh_string(struct ssh_buffer_struct *buffer) {
uint32_t stringlen;
uint32_t hostlen;
struct ssh_string_struct *str = NULL;
if (buffer_get_u32(buffer, &stringlen) == 0) {
return NULL;
}
hostlen = ntohl(stringlen);
/* verify if there is enough space in buffer to get it */
if ((buffer->pos + hostlen) > buffer->used) {
return NULL; /* it is indeed */
}
str = string_new(hostlen);
if (str == NULL) {
return NULL;
}
if (buffer_get_data(buffer, string_data(str), hostlen) != hostlen) {
/* should never happen */
SAFE_FREE(str);
return NULL;
}
return str;
}
/** \internal
* \brief gets a mpint out of the buffer. Adjusts the read pointer.
* SSH-1 only
* \param buffer Buffer to read
* \returns the SSH String containing the mpint
* \returns NULL otherwise
*/
struct ssh_string_struct *buffer_get_mpint(struct ssh_buffer_struct *buffer) {
uint16_t bits;
uint32_t len;
struct ssh_string_struct *str = NULL;
if (buffer_get_data(buffer, &bits, sizeof(uint16_t)) != sizeof(uint16_t)) {
return NULL;
}
bits = ntohs(bits);
len = (bits + 7) / 8;
if ((buffer->pos + len) > buffer->used) {
return NULL;
}
str = string_new(len);
if (str == NULL) {
return NULL;
}
if (buffer_get_data(buffer, string_data(str), len) != len) {
SAFE_FREE(str);
return NULL;
}
return str;
}
/** @} */
/* vim: set ts=2 sw=2 et cindent: */

File diff suppressed because it is too large Load Diff

View File

@@ -1,735 +0,0 @@
/*
* client.c - SSH client functions
*
* This file is part of the SSH Library
*
* Copyright (c) 2003-2008 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef _WIN32
#include <arpa/inet.h>
#endif
#include "libssh/priv.h"
#include "libssh/ssh2.h"
#include "libssh/buffer.h"
#include "libssh/packet.h"
#include "libssh/socket.h"
#include "libssh/session.h"
#include "libssh/dh.h"
#define set_status(session, status) do {\
if (session->callbacks && session->callbacks->connect_status_function) \
session->callbacks->connect_status_function(session->callbacks->userdata, status); \
} while (0)
/**
* @internal
*
* @brief Get a banner from a socket.
*
* The caller has to free memroy.
*
* @param session The session to get the banner from.
*
* @return A newly allocated string with the banner or NULL on error.
*/
char *ssh_get_banner(ssh_session session) {
char buffer[128] = {0};
char *str = NULL;
int i;
enter_function();
for (i = 0; i < 127; i++) {
if (ssh_socket_read(session->socket, &buffer[i], 1) != SSH_OK) {
ssh_set_error(session, SSH_FATAL, "Remote host closed connection");
leave_function();
return NULL;
}
#ifdef WITH_PCAP
if(session->pcap_ctx && buffer[i] == '\n'){
ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_IN,buffer,i+1,i+1);
}
#endif
if (buffer[i] == '\r') {
buffer[i] = '\0';
}
if (buffer[i] == '\n') {
buffer[i] = '\0';
str = strdup(buffer);
if (str == NULL) {
leave_function();
return NULL;
}
leave_function();
return str;
}
}
ssh_set_error(session, SSH_FATAL, "Too large banner");
leave_function();
return NULL;
}
/**
* @internal
*
* @brief Analyze the SSH banner to find out if we have a SSHv1 or SSHv2
* server.
*
* @param session The session to analyze the banner from.
* @param ssh1 The variable which is set if it is a SSHv1 server.
* @param ssh2 The variable which is set if it is a SSHv2 server.
*
* @return 0 on success, < 0 on error.
*
* @see ssh_get_banner()
*/
static int ssh_analyze_banner(ssh_session session, int *ssh1, int *ssh2) {
const char *banner = session->serverbanner;
const char *openssh;
if (banner == NULL) {
ssh_set_error(session, SSH_FATAL, "Invalid banner");
return -1;
}
/*
* Typical banners e.g. are:
*
* SSH-1.5-openSSH_5.4
* SSH-1.99-openSSH_3.0
*
* SSH-2.0-something
* 012345678901234567890
*/
if (strlen(banner) < 6 ||
strncmp(banner, "SSH-", 4) != 0) {
ssh_set_error(session, SSH_FATAL, "Protocol mismatch: %s", banner);
return -1;
}
ssh_log(session, SSH_LOG_RARE, "Analyzing banner: %s", banner);
switch(banner[4]) {
case '1':
*ssh1 = 1;
if (strlen(banner) > 6) {
if (banner[6] == '9') {
*ssh2 = 1;
} else {
*ssh2 = 0;
}
}
break;
case '2':
*ssh1 = 0;
*ssh2 = 1;
break;
default:
ssh_set_error(session, SSH_FATAL, "Protocol mismatch: %s", banner);
return -1;
}
openssh = strstr(banner, "OpenSSH");
if (openssh != NULL) {
int major, minor;
/*
* The banner is typical:
* OpenSSH_5.4
* 012345678901234567890
*/
if (strlen(openssh) > 9) {
major = strtol(openssh + 8, (char **) NULL, 10);
minor = strtol(openssh + 10, (char **) NULL, 10);
session->openssh = SSH_VERSION_INT(major, minor, 0);
ssh_log(session, SSH_LOG_RARE,
"We are talking to an OpenSSH client version: %d.%d (%x)",
major, minor, session->openssh);
}
}
return 0;
}
/** @internal
* @brief Sends a SSH banner to the server.
*
* @param session The SSH session to use.
*
* @param server Send client or server banner.
*
* @return 0 on success, < 0 on error.
*/
int ssh_send_banner(ssh_session session, int server) {
const char *banner = NULL;
char buffer[128] = {0};
enter_function();
banner = session->version == 1 ? CLIENTBANNER1 : CLIENTBANNER2;
if (session->xbanner) {
banner = session->xbanner;
}
if (server) {
session->serverbanner = strdup(banner);
if (session->serverbanner == NULL) {
leave_function();
return -1;
}
} else {
session->clientbanner = strdup(banner);
if (session->clientbanner == NULL) {
leave_function();
return -1;
}
}
snprintf(buffer, 128, "%s\r\n", banner);
if (ssh_socket_write(session->socket, buffer, strlen(buffer)) == SSH_ERROR) {
leave_function();
return -1;
}
if (ssh_socket_blocking_flush(session->socket) != SSH_OK) {
leave_function();
return -1;
}
#ifdef WITH_PCAP
if(session->pcap_ctx)
ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_OUT,buffer,strlen(buffer),strlen(buffer));
#endif
leave_function();
return 0;
}
#define DH_STATE_INIT 0
#define DH_STATE_INIT_TO_SEND 1
#define DH_STATE_INIT_SENT 2
#define DH_STATE_NEWKEYS_TO_SEND 3
#define DH_STATE_NEWKEYS_SENT 4
#define DH_STATE_FINISHED 5
static int dh_handshake(ssh_session session) {
ssh_string e = NULL;
ssh_string f = NULL;
ssh_string pubkey = NULL;
ssh_string signature = NULL;
int rc = SSH_ERROR;
enter_function();
switch (session->dh_handshake_state) {
case DH_STATE_INIT:
if (buffer_add_u8(session->out_buffer, SSH2_MSG_KEXDH_INIT) < 0) {
goto error;
}
if (dh_generate_x(session) < 0) {
goto error;
}
if (dh_generate_e(session) < 0) {
goto error;
}
e = dh_get_e(session);
if (e == NULL) {
goto error;
}
if (buffer_add_ssh_string(session->out_buffer, e) < 0) {
goto error;
}
string_burn(e);
string_free(e);
e=NULL;
rc = packet_send(session);
if (rc == SSH_ERROR) {
goto error;
}
session->dh_handshake_state = DH_STATE_INIT_TO_SEND;
case DH_STATE_INIT_TO_SEND:
rc = packet_flush(session, 0);
if (rc != SSH_OK) {
goto error;
}
session->dh_handshake_state = DH_STATE_INIT_SENT;
case DH_STATE_INIT_SENT:
rc = packet_wait(session, SSH2_MSG_KEXDH_REPLY, 1);
if (rc != SSH_OK) {
goto error;
}
pubkey = buffer_get_ssh_string(session->in_buffer);
if (pubkey == NULL){
ssh_set_error(session,SSH_FATAL, "No public key in packet");
rc = SSH_ERROR;
goto error;
}
dh_import_pubkey(session, pubkey);
f = buffer_get_ssh_string(session->in_buffer);
if (f == NULL) {
ssh_set_error(session,SSH_FATAL, "No F number in packet");
rc = SSH_ERROR;
goto error;
}
if (dh_import_f(session, f) < 0) {
ssh_set_error(session, SSH_FATAL, "Cannot import f number");
rc = SSH_ERROR;
goto error;
}
string_burn(f);
string_free(f);
f=NULL;
signature = buffer_get_ssh_string(session->in_buffer);
if (signature == NULL) {
ssh_set_error(session, SSH_FATAL, "No signature in packet");
rc = SSH_ERROR;
goto error;
}
session->dh_server_signature = signature;
signature=NULL; /* ownership changed */
if (dh_build_k(session) < 0) {
ssh_set_error(session, SSH_FATAL, "Cannot build k number");
rc = SSH_ERROR;
goto error;
}
/* Send the MSG_NEWKEYS */
if (buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
rc = SSH_ERROR;
goto error;
}
rc = packet_send(session);
if (rc == SSH_ERROR) {
goto error;
}
session->dh_handshake_state = DH_STATE_NEWKEYS_TO_SEND;
case DH_STATE_NEWKEYS_TO_SEND:
rc = packet_flush(session, 0);
if (rc != SSH_OK) {
goto error;
}
ssh_log(session, SSH_LOG_RARE, "SSH_MSG_NEWKEYS sent\n");
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
case DH_STATE_NEWKEYS_SENT:
rc = packet_wait(session, SSH2_MSG_NEWKEYS, 1);
if (rc != SSH_OK) {
goto error;
}
ssh_log(session, SSH_LOG_RARE, "Got SSH_MSG_NEWKEYS\n");
rc = make_sessionid(session);
if (rc != SSH_OK) {
goto error;
}
/*
* Set the cryptographic functions for the next crypto
* (it is needed for generate_session_keys for key lenghts)
*/
if (crypt_set_algorithms(session)) {
rc = SSH_ERROR;
goto error;
}
if (generate_session_keys(session) < 0) {
rc = SSH_ERROR;
goto error;
}
/* Verify the host's signature. FIXME do it sooner */
signature = session->dh_server_signature;
session->dh_server_signature = NULL;
if (signature_verify(session, signature)) {
rc = SSH_ERROR;
goto error;
}
/* forget it for now ... */
string_burn(signature);
string_free(signature);
signature=NULL;
/*
* Once we got SSH2_MSG_NEWKEYS we can switch next_crypto and
* current_crypto
*/
if (session->current_crypto) {
crypto_free(session->current_crypto);
session->current_crypto=NULL;
}
/* FIXME later, include a function to change keys */
session->current_crypto = session->next_crypto;
session->next_crypto = crypto_new();
if (session->next_crypto == NULL) {
rc = SSH_ERROR;
goto error;
}
session->dh_handshake_state = DH_STATE_FINISHED;
leave_function();
return SSH_OK;
default:
ssh_set_error(session, SSH_FATAL, "Invalid state in dh_handshake(): %d",
session->dh_handshake_state);
leave_function();
return SSH_ERROR;
}
/* not reached */
error:
if(e != NULL){
string_burn(e);
string_free(e);
}
if(f != NULL){
string_burn(f);
string_free(f);
}
if(signature != NULL){
string_burn(signature);
string_free(signature);
}
leave_function();
return rc;
}
/**
* @internal
*
* @brief Request a service from the SSH server.
*
* Service requests are for example: ssh-userauth, ssh-connection, etc.
*
* @param session The session to use to ask for a service request.
* @param service The service request.
*
* @return 0 on success, < 0 on error.
*/
int ssh_service_request(ssh_session session, const char *service) {
ssh_string service_s = NULL;
enter_function();
if (buffer_add_u8(session->out_buffer, SSH2_MSG_SERVICE_REQUEST) < 0) {
leave_function();
return -1;
}
service_s = string_from_char(service);
if (service_s == NULL) {
leave_function();
return -1;
}
if (buffer_add_ssh_string(session->out_buffer,service_s) < 0) {
string_free(service_s);
leave_function();
return -1;
}
string_free(service_s);
if (packet_send(session) != SSH_OK) {
ssh_set_error(session, SSH_FATAL,
"Sending SSH2_MSG_SERVICE_REQUEST failed.");
leave_function();
return -1;
}
ssh_log(session, SSH_LOG_PACKET,
"Sent SSH_MSG_SERVICE_REQUEST (service %s)", service);
if (packet_wait(session,SSH2_MSG_SERVICE_ACCEPT,1) != SSH_OK) {
ssh_set_error(session, SSH_FATAL, "Did not receive SERVICE_ACCEPT");
leave_function();
return -1;
}
ssh_log(session, SSH_LOG_PACKET,
"Received SSH_MSG_SERVICE_ACCEPT (service %s)", service);
leave_function();
return 0;
}
/** \addtogroup ssh_session
* @{
*/
/** \brief connect to the ssh server
* \param session ssh session
* \return SSH_OK on success, SSH_ERROR on error
* \see ssh_new()
* \see ssh_disconnect()
*/
int ssh_connect(ssh_session session) {
int ssh1 = 0;
int ssh2 = 0;
socket_t fd = SSH_INVALID_SOCKET;
int ret;
if (session == NULL) {
ssh_set_error(session, SSH_FATAL, "Invalid session pointer");
return SSH_ERROR;
}
enter_function();
session->alive = 0;
session->client = 1;
if (ssh_init() < 0) {
leave_function();
return SSH_ERROR;
}
if (session->fd == SSH_INVALID_SOCKET && session->host == NULL &&
session->ProxyCommand == NULL) {
ssh_set_error(session, SSH_FATAL, "Hostname required");
leave_function();
return SSH_ERROR;
}
ret = ssh_options_apply(session);
if (ret < 0) {
ssh_set_error(session, SSH_FATAL, "Couldn't apply options");
leave_function();
return SSH_ERROR;
}
if (session->fd != SSH_INVALID_SOCKET) {
fd = session->fd;
#ifndef _WIN32
} else if (session->ProxyCommand != NULL) {
fd=ssh_socket_connect_proxycommand(session, session->ProxyCommand);
#endif
} else {
fd = ssh_connect_host(session, session->host, session->bindaddr,
session->port, session->timeout, session->timeout_usec);
}
if (fd == SSH_INVALID_SOCKET) {
leave_function();
return SSH_ERROR;
}
set_status(session, 0.2);
ssh_socket_set_fd(session->socket, fd);
session->alive = 1;
session->serverbanner = ssh_get_banner(session);
if (session->serverbanner == NULL) {
ssh_socket_close(session->socket);
session->alive = 0;
leave_function();
return SSH_ERROR;
}
set_status(session, 0.4);
ssh_log(session, SSH_LOG_RARE,
"SSH server banner: %s", session->serverbanner);
/* Here we analyse the different protocols the server allows. */
if (ssh_analyze_banner(session, &ssh1, &ssh2) < 0) {
ssh_socket_close(session->socket);
session->alive = 0;
leave_function();
return SSH_ERROR;
}
/* Here we decide which version of the protocol to use. */
if (ssh2 && session->ssh2) {
session->version = 2;
} else if(ssh1 && session->ssh1) {
session->version = 1;
} else {
ssh_set_error(session, SSH_FATAL,
"No version of SSH protocol usable (banner: %s)",
session->serverbanner);
ssh_socket_close(session->socket);
session->alive = 0;
leave_function();
return SSH_ERROR;
}
if (ssh_send_banner(session, 0) < 0) {
ssh_set_error(session, SSH_FATAL, "Sending the banner failed");
ssh_socket_close(session->socket);
session->alive = 0;
leave_function();
return SSH_ERROR;
}
set_status(session, 0.5);
switch (session->version) {
case 2:
if (ssh_get_kex(session,0) < 0) {
ssh_socket_close(session->socket);
session->alive = 0;
leave_function();
return SSH_ERROR;
}
set_status(session,0.6);
ssh_list_kex(session, &session->server_kex);
if (set_kex(session) < 0) {
ssh_socket_close(session->socket);
session->alive = 0;
leave_function();
return SSH_ERROR;
}
if (ssh_send_kex(session, 0) < 0) {
ssh_socket_close(session->socket);
session->alive = 0;
leave_function();
return SSH_ERROR;
}
set_status(session,0.8);
if (dh_handshake(session) < 0) {
ssh_socket_close(session->socket);
session->alive = 0;
leave_function();
return SSH_ERROR;
}
set_status(session,1.0);
session->connected = 1;
break;
case 1:
if (ssh_get_kex1(session) < 0) {
ssh_socket_close(session->socket);
session->alive = 0;
leave_function();
return SSH_ERROR;
}
set_status(session,0.6);
session->connected = 1;
break;
}
leave_function();
return 0;
}
/**
* @brief Get the issue banner from the server.
*
* This is the banner showing a disclaimer to users who log in,
* typically their right or the fact that they will be monitored.
*
* @param session The SSH session to use.
*
* @return A newly allocated string with the banner, NULL on error.
*/
char *ssh_get_issue_banner(ssh_session session) {
if (session == NULL || session->banner == NULL) {
return NULL;
}
return string_to_char(session->banner);
}
/**
* @brief Get the version of the OpenSSH server, if it is not an OpenSSH server
* then 0 will be returned.
*
* You can use the SSH_VERSION_INT macro to compare version numbers.
*
* @param session The SSH session to use.
*
* @return The version number if available, 0 otherwise.
*/
int ssh_get_openssh_version(ssh_session session) {
if (session == NULL) {
return 0;
}
return session->openssh;
}
/**
* @brief Disconnect from a session (client or server).
* The session can then be reused to open a new session.
*
* @param session The SSH session to disconnect.
*/
void ssh_disconnect(ssh_session session) {
ssh_string str = NULL;
if (session == NULL) {
return;
}
enter_function();
if (ssh_socket_is_open(session->socket)) {
if (buffer_add_u8(session->out_buffer, SSH2_MSG_DISCONNECT) < 0) {
goto error;
}
if (buffer_add_u32(session->out_buffer,
htonl(SSH2_DISCONNECT_BY_APPLICATION)) < 0) {
goto error;
}
str = string_from_char("Bye Bye");
if (str == NULL) {
goto error;
}
if (buffer_add_ssh_string(session->out_buffer,str) < 0) {
string_free(str);
goto error;
}
string_free(str);
packet_send(session);
ssh_socket_close(session->socket);
}
session->alive = 0;
error:
leave_function();
}
const char *ssh_copyright(void) {
return SSH_STRINGIFY(LIBSSH_VERSION) " (c) 2003-2008 Aris Adamantiadis "
"(aris@0xbadc0de.be) Distributed under the LGPL, please refer to COPYING"
"file for information about your rights";
}
/** @} */
/* vim: set ts=2 sw=2 et cindent: */

View File

@@ -1,877 +0,0 @@
/*
* messages.c - message parsion for the server
*
* This file is part of the SSH Library
*
* 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.
*
* 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.
*/
/** \defgroup ssh_messages SSH Messages
* this file contains the Message parsing utilities for server programs using
* libssh. The main loop of the program will call ssh_message_get(session) to
* get messages as they come. they are not 1-1 with the protocol messages.
* then, the user will know what kind of a message it is and use the appropriate
* functions to handle it (or use the default handlers if she doesn't know what to
* do
* \addtogroup ssh_messages
* @{
*/
#include <string.h>
#include <stdlib.h>
#ifndef _WIN32
#include <arpa/inet.h>
#endif
#include "libssh/libssh.h"
#include "libssh/priv.h"
#include "libssh/ssh2.h"
#include "libssh/buffer.h"
#include "libssh/packet.h"
#include "libssh/channels.h"
#include "libssh/session.h"
#include "libssh/misc.h"
#include "libssh/keys.h"
#include "libssh/dh.h"
#include "libssh/messages.h"
static ssh_message message_new(ssh_session session){
ssh_message msg = malloc(sizeof(struct ssh_message_struct));
if (msg == NULL) {
return NULL;
}
ZERO_STRUCTP(msg);
msg->session = session;
return msg;
}
static ssh_message handle_service_request(ssh_session session) {
ssh_string service = NULL;
char *service_c = NULL;
ssh_message msg=NULL;
enter_function();
service = buffer_get_ssh_string(session->in_buffer);
if (service == NULL) {
ssh_set_error(session, SSH_FATAL, "Invalid SSH_MSG_SERVICE_REQUEST packet");
goto error;
}
service_c = string_to_char(service);
if (service_c == NULL) {
goto error;
}
ssh_log(session, SSH_LOG_PACKET,
"Received a SERVICE_REQUEST for service %s", service_c);
msg=message_new(session);
if(!msg){
SAFE_FREE(service_c);
goto error;
}
msg->type=SSH_REQUEST_SERVICE;
msg->service_request.service=service_c;
error:
string_free(service);
leave_function();
return msg;
}
static int handle_unimplemented(ssh_session session) {
if (buffer_add_u32(session->out_buffer, htonl(session->recv_seq - 1)) < 0) {
return -1;
}
if (packet_send(session) != SSH_OK) {
return -1;
}
return 0;
}
static ssh_message handle_userauth_request(ssh_session session){
ssh_string user = NULL;
ssh_string service = NULL;
ssh_string method = NULL;
ssh_message msg = NULL;
char *service_c = NULL;
char *method_c = NULL;
uint32_t method_size = 0;
enter_function();
msg = message_new(session);
if (msg == NULL) {
return NULL;
}
user = buffer_get_ssh_string(session->in_buffer);
if (user == NULL) {
goto error;
}
service = buffer_get_ssh_string(session->in_buffer);
if (service == NULL) {
goto error;
}
method = buffer_get_ssh_string(session->in_buffer);
if (method == NULL) {
goto error;
}
msg->type = SSH_REQUEST_AUTH;
msg->auth_request.username = string_to_char(user);
if (msg->auth_request.username == NULL) {
goto error;
}
string_free(user);
user = NULL;
service_c = string_to_char(service);
if (service_c == NULL) {
goto error;
}
method_c = string_to_char(method);
if (method_c == NULL) {
goto error;
}
method_size = string_len(method);
string_free(service);
service = NULL;
string_free(method);
method = NULL;
ssh_log(session, SSH_LOG_PACKET,
"Auth request for service %s, method %s for user '%s'",
service_c, method_c,
msg->auth_request.username);
if (strncmp(method_c, "none", method_size) == 0) {
msg->auth_request.method = SSH_AUTH_METHOD_NONE;
SAFE_FREE(service_c);
SAFE_FREE(method_c);
leave_function();
return msg;
}
if (strncmp(method_c, "password", method_size) == 0) {
ssh_string pass = NULL;
uint8_t tmp;
msg->auth_request.method = SSH_AUTH_METHOD_PASSWORD;
SAFE_FREE(service_c);
SAFE_FREE(method_c);
buffer_get_u8(session->in_buffer, &tmp);
pass = buffer_get_ssh_string(session->in_buffer);
if (pass == NULL) {
goto error;
}
msg->auth_request.password = string_to_char(pass);
string_burn(pass);
string_free(pass);
pass = NULL;
if (msg->auth_request.password == NULL) {
goto error;
}
leave_function();
return msg;
}
if (strncmp(method_c, "publickey", method_size) == 0) {
ssh_string algo = NULL;
ssh_string publickey = NULL;
uint8_t has_sign;
msg->auth_request.method = SSH_AUTH_METHOD_PUBLICKEY;
SAFE_FREE(method_c);
buffer_get_u8(session->in_buffer, &has_sign);
algo = buffer_get_ssh_string(session->in_buffer);
if (algo == NULL) {
goto error;
}
publickey = buffer_get_ssh_string(session->in_buffer);
if (publickey == NULL) {
string_free(algo);
algo = NULL;
goto error;
}
msg->auth_request.public_key = publickey_from_string(session, publickey);
string_free(algo);
algo = NULL;
string_free(publickey);
publickey = NULL;
if (msg->auth_request.public_key == NULL) {
goto error;
}
msg->auth_request.signature_state = 0;
// has a valid signature ?
if(has_sign) {
SIGNATURE *signature = NULL;
ssh_public_key public_key = msg->auth_request.public_key;
ssh_string sign = NULL;
ssh_buffer digest = NULL;
sign = buffer_get_ssh_string(session->in_buffer);
if(sign == NULL) {
ssh_log(session, SSH_LOG_PACKET, "Invalid signature packet from peer");
msg->auth_request.signature_state = -2;
goto error;
}
signature = signature_from_string(session, sign, public_key,
public_key->type);
digest = ssh_userauth_build_digest(session, msg, service_c);
if ((digest == NULL || signature == NULL) ||
(digest != NULL && signature != NULL &&
sig_verify(session, public_key, signature,
buffer_get(digest), buffer_get_len(digest)) < 0)) {
ssh_log(session, SSH_LOG_PACKET, "Invalid signature from peer");
string_free(sign);
sign = NULL;
buffer_free(digest);
digest = NULL;
signature_free(signature);
signature = NULL;
msg->auth_request.signature_state = -1;
goto error;
}
else
ssh_log(session, SSH_LOG_PACKET, "Valid signature received");
buffer_free(digest);
digest = NULL;
string_free(sign);
sign = NULL;
signature_free(signature);
signature = NULL;
msg->auth_request.signature_state = 1;
}
SAFE_FREE(service_c);
leave_function();
return msg;
}
msg->auth_request.method = SSH_AUTH_METHOD_UNKNOWN;
SAFE_FREE(method_c);
leave_function();
return msg;
error:
string_free(user);
string_free(service);
string_free(method);
SAFE_FREE(method_c);
SAFE_FREE(service_c);
ssh_message_free(msg);
leave_function();
return NULL;
}
static ssh_message handle_channel_request_open(ssh_session session) {
ssh_message msg = NULL;
ssh_string type = NULL, originator = NULL, destination = NULL;
char *type_c = NULL;
uint32_t sender, window, packet, originator_port, destination_port;
enter_function();
msg = message_new(session);
if (msg == NULL) {
ssh_set_error_oom(session);
leave_function();
return NULL;
}
msg->type = SSH_REQUEST_CHANNEL_OPEN;
type = buffer_get_ssh_string(session->in_buffer);
if (type == NULL) {
ssh_set_error_oom(session);
goto error;
}
type_c = string_to_char(type);
if (type_c == NULL) {
ssh_set_error_oom(session);
goto error;
}
ssh_log(session, SSH_LOG_PACKET,
"Clients wants to open a %s channel", type_c);
buffer_get_u32(session->in_buffer, &sender);
buffer_get_u32(session->in_buffer, &window);
buffer_get_u32(session->in_buffer, &packet);
msg->channel_request_open.sender = ntohl(sender);
msg->channel_request_open.window = ntohl(window);
msg->channel_request_open.packet_size = ntohl(packet);
if (strcmp(type_c,"session") == 0) {
msg->channel_request_open.type = SSH_CHANNEL_SESSION;
string_free(type);
SAFE_FREE(type_c);
leave_function();
return msg;
}
if (strcmp(type_c,"direct-tcpip") == 0) {
destination = buffer_get_ssh_string(session->in_buffer);
if (destination == NULL) {
ssh_set_error_oom(session);
goto error;
}
msg->channel_request_open.destination = string_to_char(type);
if (msg->channel_request_open.destination == NULL) {
ssh_set_error_oom(session);
string_free(destination);
goto error;
}
string_free(destination);
buffer_get_u32(session->in_buffer, &destination_port);
msg->channel_request_open.destination_port = ntohl(destination_port);
originator = buffer_get_ssh_string(session->in_buffer);
if (originator == NULL) {
ssh_set_error_oom(session);
goto error;
}
msg->channel_request_open.originator = string_to_char(type);
if (msg->channel_request_open.originator == NULL) {
ssh_set_error_oom(session);
string_free(originator);
goto error;
}
string_free(originator);
buffer_get_u32(session->in_buffer, &originator_port);
msg->channel_request_open.originator_port = ntohl(originator_port);
msg->channel_request_open.type = SSH_CHANNEL_DIRECT_TCPIP;
string_free(type);
SAFE_FREE(type_c);
leave_function();
return msg;
}
if (strcmp(type_c,"forwarded-tcpip") == 0) {
destination = buffer_get_ssh_string(session->in_buffer);
if (destination == NULL) {
ssh_set_error_oom(session);
goto error;
}
msg->channel_request_open.destination = string_to_char(type);
if (msg->channel_request_open.destination == NULL) {
ssh_set_error_oom(session);
string_free(destination);
goto error;
}
string_free(destination);
buffer_get_u32(session->in_buffer, &destination_port);
msg->channel_request_open.destination_port = ntohl(destination_port);
originator = buffer_get_ssh_string(session->in_buffer);
if (originator == NULL) {
ssh_set_error_oom(session);
goto error;
}
msg->channel_request_open.originator = string_to_char(type);
if (msg->channel_request_open.originator == NULL) {
ssh_set_error_oom(session);
string_free(originator);
goto error;
}
string_free(originator);
buffer_get_u32(session->in_buffer, &originator_port);
msg->channel_request_open.originator_port = ntohl(originator_port);
msg->channel_request_open.type = SSH_CHANNEL_FORWARDED_TCPIP;
string_free(type);
SAFE_FREE(type_c);
leave_function();
return msg;
}
if (strcmp(type_c,"x11") == 0) {
originator = buffer_get_ssh_string(session->in_buffer);
if (originator == NULL) {
ssh_set_error_oom(session);
goto error;
}
msg->channel_request_open.originator = string_to_char(type);
if (msg->channel_request_open.originator == NULL) {
ssh_set_error_oom(session);
string_free(originator);
goto error;
}
string_free(originator);
buffer_get_u32(session->in_buffer, &originator_port);
msg->channel_request_open.originator_port = ntohl(originator_port);
msg->channel_request_open.type = SSH_CHANNEL_X11;
string_free(type);
SAFE_FREE(type_c);
leave_function();
return msg;
}
msg->channel_request_open.type = SSH_CHANNEL_UNKNOWN;
string_free(type);
SAFE_FREE(type_c);
leave_function();
return msg;
error:
string_free(type);
SAFE_FREE(type_c);
ssh_message_free(msg);
leave_function();
return NULL;
}
ssh_channel ssh_message_channel_request_open_reply_accept(ssh_message msg) {
ssh_session session = msg->session;
ssh_channel chan = NULL;
enter_function();
if (msg == NULL) {
leave_function();
return NULL;
}
chan = channel_new(session);
if (chan == NULL) {
leave_function();
return NULL;
}
chan->local_channel = ssh_channel_new_id(session);
chan->local_maxpacket = 35000;
chan->local_window = 32000;
chan->remote_channel = msg->channel_request_open.sender;
chan->remote_maxpacket = msg->channel_request_open.packet_size;
chan->remote_window = msg->channel_request_open.window;
chan->open = 1;
if (buffer_add_u8(session->out_buffer, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) < 0) {
goto error;
}
if (buffer_add_u32(session->out_buffer, htonl(chan->remote_channel)) < 0) {
goto error;
}
if (buffer_add_u32(session->out_buffer, htonl(chan->local_channel)) < 0) {
goto error;
}
if (buffer_add_u32(session->out_buffer, htonl(chan->local_window)) < 0) {
goto error;
}
if (buffer_add_u32(session->out_buffer, htonl(chan->local_maxpacket)) < 0) {
goto error;
}
ssh_log(session, SSH_LOG_PACKET,
"Accepting a channel request_open for chan %d", chan->remote_channel);
if (packet_send(session) != SSH_OK) {
goto error;
}
leave_function();
return chan;
error:
channel_free(chan);
leave_function();
return NULL;
}
static ssh_message handle_channel_request(ssh_session session) {
ssh_message msg = NULL;
ssh_string type = NULL;
char *type_c = NULL;
uint32_t channel;
uint8_t want_reply;
enter_function();
msg = message_new(session);
if (msg == NULL) {
ssh_set_error_oom(session);
return NULL;
}
buffer_get_u32(session->in_buffer, &channel);
channel = ntohl(channel);
type = buffer_get_ssh_string(session->in_buffer);
if (type == NULL) {
ssh_set_error_oom(session);
goto error;
}
type_c = string_to_char(type);
if (type_c == NULL) {
ssh_set_error_oom(session);
goto error;
}
string_free(type);
buffer_get_u8(session->in_buffer,&want_reply);
ssh_log(session, SSH_LOG_PACKET,
"Received a %s channel_request for channel %d (want_reply=%hhd)",
type_c, channel, want_reply);
msg->type = SSH_REQUEST_CHANNEL;
msg->channel_request.channel = ssh_channel_from_local(session, channel);
if (msg->channel_request.channel == NULL) {
ssh_set_error(session, SSH_FATAL, "There are no channels with the id %u.",
channel);
goto error;
}
msg->channel_request.want_reply = want_reply;
if (strcmp(type_c, "pty-req") == 0) {
ssh_string term = NULL;
char *term_c = NULL;
SAFE_FREE(type_c);
term = buffer_get_ssh_string(session->in_buffer);
if (term == NULL) {
ssh_set_error_oom(session);
goto error;
}
term_c = string_to_char(term);
if (term_c == NULL) {
ssh_set_error_oom(session);
string_free(term);
goto error;
}
string_free(term);
msg->channel_request.type = SSH_CHANNEL_REQUEST_PTY;
msg->channel_request.TERM = term_c;
buffer_get_u32(session->in_buffer, &msg->channel_request.width);
buffer_get_u32(session->in_buffer, &msg->channel_request.height);
buffer_get_u32(session->in_buffer, &msg->channel_request.pxwidth);
buffer_get_u32(session->in_buffer, &msg->channel_request.pxheight);
msg->channel_request.width = ntohl(msg->channel_request.width);
msg->channel_request.height = ntohl(msg->channel_request.height);
msg->channel_request.pxwidth = ntohl(msg->channel_request.pxwidth);
msg->channel_request.pxheight = ntohl(msg->channel_request.pxheight);
msg->channel_request.modes = buffer_get_ssh_string(session->in_buffer);
if (msg->channel_request.modes == NULL) {
SAFE_FREE(term_c);
goto error;
}
leave_function();
return msg;
}
if (strcmp(type_c, "window-change") == 0) {
SAFE_FREE(type_c);
msg->channel_request.type = SSH_CHANNEL_REQUEST_WINDOW_CHANGE;
buffer_get_u32(session->in_buffer, &msg->channel_request.width);
buffer_get_u32(session->in_buffer, &msg->channel_request.height);
buffer_get_u32(session->in_buffer, &msg->channel_request.pxwidth);
buffer_get_u32(session->in_buffer, &msg->channel_request.pxheight);
msg->channel_request.width = ntohl(msg->channel_request.width);
msg->channel_request.height = ntohl(msg->channel_request.height);
msg->channel_request.pxwidth = ntohl(msg->channel_request.pxwidth);
msg->channel_request.pxheight = ntohl(msg->channel_request.pxheight);
leave_function();
return msg;
}
if (strcmp(type_c, "subsystem") == 0) {
ssh_string subsys = NULL;
char *subsys_c = NULL;
SAFE_FREE(type_c);
subsys = buffer_get_ssh_string(session->in_buffer);
if (subsys == NULL) {
ssh_set_error_oom(session);
goto error;
}
subsys_c = string_to_char(subsys);
if (subsys_c == NULL) {
ssh_set_error_oom(session);
string_free(subsys);
goto error;
}
string_free(subsys);
msg->channel_request.type = SSH_CHANNEL_REQUEST_SUBSYSTEM;
msg->channel_request.subsystem = subsys_c;
leave_function();
return msg;
}
if (strcmp(type_c, "shell") == 0) {
SAFE_FREE(type_c);
msg->channel_request.type = SSH_CHANNEL_REQUEST_SHELL;
leave_function();
return msg;
}
if (strcmp(type_c, "exec") == 0) {
ssh_string cmd = NULL;
SAFE_FREE(type_c);
cmd = buffer_get_ssh_string(session->in_buffer);
if (cmd == NULL) {
ssh_set_error_oom(session);
goto error;
}
msg->channel_request.type = SSH_CHANNEL_REQUEST_EXEC;
msg->channel_request.command = string_to_char(cmd);
if (msg->channel_request.command == NULL) {
string_free(cmd);
goto error;
}
string_free(cmd);
leave_function();
return msg;
}
if (strcmp(type_c, "env") == 0) {
ssh_string name = NULL;
ssh_string value = NULL;
SAFE_FREE(type_c);
name = buffer_get_ssh_string(session->in_buffer);
if (name == NULL) {
ssh_set_error_oom(session);
goto error;
}
value = buffer_get_ssh_string(session->in_buffer);
if (value == NULL) {
ssh_set_error_oom(session);
string_free(name);
goto error;
}
msg->channel_request.type = SSH_CHANNEL_REQUEST_ENV;
msg->channel_request.var_name = string_to_char(name);
msg->channel_request.var_value = string_to_char(value);
if (msg->channel_request.var_name == NULL ||
msg->channel_request.var_value == NULL) {
string_free(name);
string_free(value);
goto error;
}
string_free(name);
string_free(value);
leave_function();
return msg;
}
msg->channel_request.type = SSH_CHANNEL_UNKNOWN;
SAFE_FREE(type_c);
leave_function();
return msg;
error:
string_free(type);
SAFE_FREE(type_c);
ssh_message_free(msg);
leave_function();
return NULL;
}
int ssh_message_channel_request_reply_success(ssh_message msg) {
uint32_t channel;
if (msg == NULL) {
return SSH_ERROR;
}
if (msg->channel_request.want_reply) {
channel = msg->channel_request.channel->remote_channel;
ssh_log(msg->session, SSH_LOG_PACKET,
"Sending a channel_request success to channel %d", channel);
if (buffer_add_u8(msg->session->out_buffer, SSH2_MSG_CHANNEL_SUCCESS) < 0) {
return SSH_ERROR;
}
if (buffer_add_u32(msg->session->out_buffer, htonl(channel)) < 0) {
return SSH_ERROR;
}
return packet_send(msg->session);
}
ssh_log(msg->session, SSH_LOG_PACKET,
"The client doesn't want to know the request succeeded");
return SSH_OK;
}
ssh_message ssh_message_retrieve(ssh_session session, uint32_t packettype){
ssh_message msg=NULL;
enter_function();
switch(packettype) {
case SSH2_MSG_SERVICE_REQUEST:
msg=handle_service_request(session);
break;
case SSH2_MSG_USERAUTH_REQUEST:
msg = handle_userauth_request(session);
break;
case SSH2_MSG_CHANNEL_OPEN:
msg = handle_channel_request_open(session);
break;
case SSH2_MSG_CHANNEL_REQUEST:
msg = handle_channel_request(session);
break;
default:
if (handle_unimplemented(session) == 0) {
ssh_set_error(session, SSH_FATAL,
"Unhandled message %d\n", session->in_packet.type);
}
}
leave_function();
return msg;
}
/* \brief blocking message retrieval
* \bug does anything that is not a message, like a channel read/write
*/
ssh_message ssh_message_get(ssh_session session) {
ssh_message msg = NULL;
enter_function();
do {
if ((packet_read(session) != SSH_OK) ||
(packet_translate(session) != SSH_OK)) {
leave_function();
return NULL;
}
} while(session->in_packet.type==SSH2_MSG_IGNORE || session->in_packet.type==SSH2_MSG_DEBUG);
msg=ssh_message_retrieve(session,session->in_packet.type);
leave_function();
return msg;
}
int ssh_message_type(ssh_message msg) {
if (msg == NULL) {
return -1;
}
return msg->type;
}
int ssh_message_subtype(ssh_message msg) {
if (msg == NULL) {
return -1;
}
switch(msg->type) {
case SSH_REQUEST_AUTH:
return msg->auth_request.method;
case SSH_REQUEST_CHANNEL_OPEN:
return msg->channel_request_open.type;
case SSH_REQUEST_CHANNEL:
return msg->channel_request.type;
}
return -1;
}
void ssh_message_free(ssh_message msg){
if (msg == NULL) {
return;
}
switch(msg->type) {
case SSH_REQUEST_AUTH:
SAFE_FREE(msg->auth_request.username);
if (msg->auth_request.password) {
memset(msg->auth_request.password, 0,
strlen(msg->auth_request.password));
SAFE_FREE(msg->auth_request.password);
}
publickey_free(msg->auth_request.public_key);
break;
case SSH_REQUEST_CHANNEL_OPEN:
SAFE_FREE(msg->channel_request_open.originator);
SAFE_FREE(msg->channel_request_open.destination);
break;
case SSH_REQUEST_CHANNEL:
SAFE_FREE(msg->channel_request.TERM);
SAFE_FREE(msg->channel_request.modes);
SAFE_FREE(msg->channel_request.var_name);
SAFE_FREE(msg->channel_request.var_value);
SAFE_FREE(msg->channel_request.command);
SAFE_FREE(msg->channel_request.subsystem);
break;
case SSH_REQUEST_SERVICE:
SAFE_FREE(msg->service_request.service);
break;
}
ZERO_STRUCTP(msg);
SAFE_FREE(msg);
}
/** \internal
* \brief handle various SSH request messages and stack them for callback
* \param session SSH session
* \param type packet type
* \returns nothing
*/
void message_handle(ssh_session session, uint32_t type){
ssh_message msg=ssh_message_retrieve(session,type);
ssh_log(session,SSH_LOG_PROTOCOL,"Stacking message from packet type %d",type);
if(msg){
if(!session->ssh_message_list){
session->ssh_message_list=ssh_list_new();
}
ssh_list_append(session->ssh_message_list,msg);
}
}
/**
* @}
*/
/* vim: set ts=2 sw=2 et cindent: */

View File

@@ -1,830 +0,0 @@
/*
* packet.c - packet building functions
*
* This file is part of the SSH Library
*
* Copyright (c) 2003-2008 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.
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#ifndef _WIN32
#include <arpa/inet.h>
#endif
#include "libssh/priv.h"
#include "libssh/ssh2.h"
#include "libssh/ssh1.h"
#include "libssh/crypto.h"
#include "libssh/buffer.h"
#include "libssh/packet.h"
#include "libssh/socket.h"
#include "libssh/channels.h"
#include "libssh/session.h"
#include "libssh/messages.h"
#include "libssh/pcap.h"
/* XXX include selected mac size */
static int macsize=SHA_DIGEST_LEN;
/* in nonblocking mode, socket_read will read as much as it can, and return */
/* SSH_OK if it has read at least len bytes, otherwise, SSH_AGAIN. */
/* in blocking mode, it will read at least len bytes and will block until it's ok. */
#define PACKET_STATE_INIT 0
#define PACKET_STATE_SIZEREAD 1
static int packet_read2(ssh_session session) {
unsigned int blocksize = (session->current_crypto ?
session->current_crypto->in_cipher->blocksize : 8);
int current_macsize = session->current_crypto ? macsize : 0;
unsigned char mac[30] = {0};
char buffer[16] = {0};
void *packet=NULL;
int to_be_read;
int rc = SSH_ERROR;
uint32_t len;
uint8_t padding;
enter_function();
if (session->alive == 0) {
/* The error message was already set into this session */
leave_function();
return SSH_ERROR;
}
switch(session->packet_state) {
case PACKET_STATE_INIT:
memset(&session->in_packet, 0, sizeof(PACKET));
if (session->in_buffer) {
if (buffer_reinit(session->in_buffer) < 0) {
goto error;
}
} else {
session->in_buffer = buffer_new();
if (session->in_buffer == NULL) {
goto error;
}
}
rc = ssh_socket_wait_for_data(session->socket, session, blocksize);
if (rc != SSH_OK) {
goto error;
}
rc = SSH_ERROR;
/* can't fail since we're sure there is enough data in socket buffer */
ssh_socket_read(session->socket, buffer, blocksize);
len = packet_decrypt_len(session, buffer);
if (buffer_add_data(session->in_buffer, buffer, blocksize) < 0) {
goto error;
}
if(len > MAX_PACKET_LEN) {
ssh_set_error(session, SSH_FATAL,
"read_packet(): Packet len too high(%u %.4x)", len, len);
goto error;
}
to_be_read = len - blocksize + sizeof(uint32_t);
if (to_be_read < 0) {
/* remote sshd sends invalid sizes? */
ssh_set_error(session, SSH_FATAL,
"given numbers of bytes left to be read < 0 (%d)!", to_be_read);
goto error;
}
/* saves the status of the current operations */
session->in_packet.len = len;
session->packet_state = PACKET_STATE_SIZEREAD;
case PACKET_STATE_SIZEREAD:
len = session->in_packet.len;
to_be_read = len - blocksize + sizeof(uint32_t) + current_macsize;
/* if to_be_read is zero, the whole packet was blocksize bytes. */
if (to_be_read != 0) {
rc = ssh_socket_wait_for_data(session->socket,session,to_be_read);
if (rc != SSH_OK) {
goto error;
}
rc = SSH_ERROR;
packet = malloc(to_be_read);
if (packet == NULL) {
ssh_set_error(session, SSH_FATAL, "No space left");
goto error;
}
ssh_socket_read(session->socket,packet,to_be_read-current_macsize);
ssh_log(session,SSH_LOG_PACKET,"Read a %d bytes packet",len);
if (buffer_add_data(session->in_buffer, packet,
to_be_read - current_macsize) < 0) {
SAFE_FREE(packet);
goto error;
}
SAFE_FREE(packet);
}
if (session->current_crypto) {
/*
* decrypt the rest of the packet (blocksize bytes already
* have been decrypted)
*/
if (packet_decrypt(session,
((uint8_t*)buffer_get(session->in_buffer) + blocksize),
buffer_get_len(session->in_buffer) - blocksize) < 0) {
ssh_set_error(session, SSH_FATAL, "Decrypt error");
goto error;
}
#ifdef WITH_PCAP
if(session->pcap_ctx){
ssh_pcap_context_write(session->pcap_ctx,
SSH_PCAP_DIR_IN, buffer_get(session->in_buffer),
buffer_get_len(session->in_buffer),
buffer_get_len(session->in_buffer));
}
#endif
ssh_socket_read(session->socket, mac, macsize);
if (packet_hmac_verify(session, session->in_buffer, mac) < 0) {
ssh_set_error(session, SSH_FATAL, "HMAC error");
goto error;
}
}
#ifdef WITH_PCAP
else {
/* No crypto */
if(session->pcap_ctx){
ssh_pcap_context_write(session->pcap_ctx,
SSH_PCAP_DIR_IN, buffer_get(session->in_buffer),
buffer_get_len(session->in_buffer),
buffer_get_len(session->in_buffer));
}
}
#endif
buffer_pass_bytes(session->in_buffer, sizeof(uint32_t));
/* pass the size which has been processed before */
if (buffer_get_u8(session->in_buffer, &padding) == 0) {
ssh_set_error(session, SSH_FATAL, "Packet too short to read padding");
goto error;
}
ssh_log(session, SSH_LOG_PACKET,
"%hhd bytes padding, %d bytes left in buffer",
padding, buffer_get_rest_len(session->in_buffer));
if (padding > buffer_get_rest_len(session->in_buffer)) {
ssh_set_error(session, SSH_FATAL,
"Invalid padding: %d (%d resting)",
padding,
buffer_get_rest_len(session->in_buffer));
#ifdef DEBUG_CRYPTO
ssh_print_hexa("incrimined packet",
buffer_get(session->in_buffer),
buffer_get_len(session->in_buffer));
#endif
goto error;
}
buffer_pass_bytes_end(session->in_buffer, padding);
ssh_log(session, SSH_LOG_PACKET,
"After padding, %d bytes left in buffer",
buffer_get_rest_len(session->in_buffer));
#if defined(HAVE_LIBZ) && defined(WITH_LIBZ)
if (session->current_crypto && session->current_crypto->do_compress_in) {
ssh_log(session, SSH_LOG_PACKET, "Decompressing in_buffer ...");
if (decompress_buffer(session, session->in_buffer, MAX_PACKET_LEN) < 0) {
goto error;
}
}
#endif
session->recv_seq++;
session->packet_state = PACKET_STATE_INIT;
leave_function();
return SSH_OK;
}
ssh_set_error(session, SSH_FATAL,
"Invalid state into packet_read2(): %d",
session->packet_state);
error:
leave_function();
return rc;
}
#ifdef WITH_SSH1
/* a slighty modified packet_read2() for SSH-1 protocol */
static int packet_read1(ssh_session session) {
void *packet = NULL;
int rc = SSH_ERROR;
int to_be_read;
uint32_t padding;
uint32_t crc;
uint32_t len;
enter_function();
if(!session->alive) {
goto error;
}
switch (session->packet_state){
case PACKET_STATE_INIT:
memset(&session->in_packet, 0, sizeof(PACKET));
if (session->in_buffer) {
if (buffer_reinit(session->in_buffer) < 0) {
goto error;
}
} else {
session->in_buffer = buffer_new();
if (session->in_buffer == NULL) {
goto error;
}
}
rc = ssh_socket_read(session->socket, &len, sizeof(uint32_t));
if (rc != SSH_OK) {
goto error;
}
rc = SSH_ERROR;
/* len is not encrypted */
len = ntohl(len);
if (len > MAX_PACKET_LEN) {
ssh_set_error(session, SSH_FATAL,
"read_packet(): Packet len too high (%u %.8x)", len, len);
goto error;
}
ssh_log(session, SSH_LOG_PACKET, "Reading a %d bytes packet", len);
session->in_packet.len = len;
session->packet_state = PACKET_STATE_SIZEREAD;
case PACKET_STATE_SIZEREAD:
len = session->in_packet.len;
/* SSH-1 has a fixed padding lenght */
padding = 8 - (len % 8);
to_be_read = len + padding;
/* it is _not_ possible that to_be_read be < 8. */
packet = malloc(to_be_read);
if (packet == NULL) {
ssh_set_error(session, SSH_FATAL, "Not enough space");
goto error;
}
rc = ssh_socket_read(session->socket, packet, to_be_read);
if(rc != SSH_OK) {
SAFE_FREE(packet);
goto error;
}
rc = SSH_ERROR;
if (buffer_add_data(session->in_buffer,packet,to_be_read) < 0) {
SAFE_FREE(packet);
goto error;
}
SAFE_FREE(packet);
#ifdef DEBUG_CRYPTO
ssh_print_hexa("read packet:", buffer_get(session->in_buffer),
buffer_get_len(session->in_buffer));
#endif
if (session->current_crypto) {
/*
* We decrypt everything, missing the lenght part (which was
* previously read, unencrypted, and is not part of the buffer
*/
if (packet_decrypt(session,
buffer_get(session->in_buffer),
buffer_get_len(session->in_buffer)) < 0) {
ssh_set_error(session, SSH_FATAL, "Packet decrypt error");
goto error;
}
}
#ifdef DEBUG_CRYPTO
ssh_print_hexa("read packet decrypted:", buffer_get(session->in_buffer),
buffer_get_len(session->in_buffer));
#endif
ssh_log(session, SSH_LOG_PACKET, "%d bytes padding", padding);
if(((len + padding) != buffer_get_rest_len(session->in_buffer)) ||
((len + padding) < sizeof(uint32_t))) {
ssh_log(session, SSH_LOG_RARE, "no crc32 in packet");
ssh_set_error(session, SSH_FATAL, "no crc32 in packet");
goto error;
}
memcpy(&crc,
(unsigned char *)buffer_get_rest(session->in_buffer) + (len+padding) - sizeof(uint32_t),
sizeof(uint32_t));
buffer_pass_bytes_end(session->in_buffer, sizeof(uint32_t));
crc = ntohl(crc);
if (ssh_crc32(buffer_get_rest(session->in_buffer),
(len + padding) - sizeof(uint32_t)) != crc) {
#ifdef DEBUG_CRYPTO
ssh_print_hexa("crc32 on",buffer_get_rest(session->in_buffer),
len + padding - sizeof(uint32_t));
#endif
ssh_log(session, SSH_LOG_RARE, "Invalid crc32");
ssh_set_error(session, SSH_FATAL,
"Invalid crc32: expected %.8x, got %.8x",
crc,
ssh_crc32(buffer_get_rest(session->in_buffer),
len + padding - sizeof(uint32_t)));
goto error;
}
/* pass the padding */
buffer_pass_bytes(session->in_buffer, padding);
ssh_log(session, SSH_LOG_PACKET, "The packet is valid");
/* TODO FIXME
#if defined(HAVE_LIBZ) && defined(WITH_LIBZ)
if(session->current_crypto && session->current_crypto->do_compress_in){
decompress_buffer(session,session->in_buffer);
}
#endif
*/
session->recv_seq++;
session->packet_state=PACKET_STATE_INIT;
leave_function();
return SSH_OK;
} /* switch */
ssh_set_error(session, SSH_FATAL,
"Invalid state into packet_read1(): %d",
session->packet_state);
error:
leave_function();
return rc;
}
#endif /* WITH_SSH1 */
/* that's where i'd like C to be object ... */
int packet_read(ssh_session session) {
#ifdef WITH_SSH1
if (session->version == 1) {
return packet_read1(session);
}
#endif
return packet_read2(session);
}
int packet_translate(ssh_session session) {
enter_function();
memset(&session->in_packet, 0, sizeof(PACKET));
if(session->in_buffer == NULL) {
leave_function();
return SSH_ERROR;
}
ssh_log(session, SSH_LOG_PACKET, "Final size %d",
buffer_get_rest_len(session->in_buffer));
if(buffer_get_u8(session->in_buffer, &session->in_packet.type) == 0) {
ssh_set_error(session, SSH_FATAL, "Packet too short to read type");
leave_function();
return SSH_ERROR;
}
ssh_log(session, SSH_LOG_PACKET, "Type %hhd", session->in_packet.type);
session->in_packet.valid = 1;
leave_function();
return SSH_OK;
}
/*
* Write the the bufferized output. If the session is blocking, or
* enforce_blocking is set, the call may block. Otherwise, it won't block.
* Return SSH_OK if everything has been sent, SSH_AGAIN if there are still
* things to send on buffer, SSH_ERROR if there is an error.
*/
int packet_flush(ssh_session session, int enforce_blocking) {
if (enforce_blocking || session->blocking) {
return ssh_socket_blocking_flush(session->socket);
}
return ssh_socket_nonblocking_flush(session->socket);
}
/*
* This function places the outgoing packet buffer into an outgoing
* socket buffer
*/
static int packet_write(ssh_session session) {
int rc = SSH_ERROR;
enter_function();
ssh_socket_write(session->socket,
buffer_get(session->out_buffer),
buffer_get_len(session->out_buffer));
rc = packet_flush(session, 0);
leave_function();
return rc;
}
static int packet_send2(ssh_session session) {
unsigned int blocksize = (session->current_crypto ?
session->current_crypto->out_cipher->blocksize : 8);
uint32_t currentlen = buffer_get_len(session->out_buffer);
unsigned char *hmac = NULL;
char padstring[32] = {0};
int rc = SSH_ERROR;
uint32_t finallen;
uint8_t padding;
enter_function();
ssh_log(session, SSH_LOG_PACKET,
"Writing on the wire a packet having %u bytes before", currentlen);
#if defined(HAVE_LIBZ) && defined(WITH_LIBZ)
if (session->current_crypto && session->current_crypto->do_compress_out) {
ssh_log(session, SSH_LOG_PACKET, "Compressing in_buffer ...");
if (compress_buffer(session,session->out_buffer) < 0) {
goto error;
}
currentlen = buffer_get_len(session->out_buffer);
}
#endif
padding = (blocksize - ((currentlen +5) % blocksize));
if(padding < 4) {
padding += blocksize;
}
if (session->current_crypto) {
ssh_get_random(padstring, padding, 0);
} else {
memset(padstring,0,padding);
}
finallen = htonl(currentlen + padding + 1);
ssh_log(session, SSH_LOG_PACKET,
"%d bytes after comp + %d padding bytes = %lu bytes packet",
currentlen, padding, (long unsigned int) ntohl(finallen));
if (buffer_prepend_data(session->out_buffer, &padding, sizeof(uint8_t)) < 0) {
goto error;
}
if (buffer_prepend_data(session->out_buffer, &finallen, sizeof(uint32_t)) < 0) {
goto error;
}
if (buffer_add_data(session->out_buffer, padstring, padding) < 0) {
goto error;
}
#ifdef WITH_PCAP
if(session->pcap_ctx){
ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_OUT,
buffer_get(session->out_buffer),buffer_get_len(session->out_buffer)
,buffer_get_len(session->out_buffer));
}
#endif
hmac = packet_encrypt(session, buffer_get(session->out_buffer),
buffer_get_len(session->out_buffer));
if (hmac) {
if (buffer_add_data(session->out_buffer, hmac, 20) < 0) {
goto error;
}
}
rc = packet_write(session);
session->send_seq++;
if (buffer_reinit(session->out_buffer) < 0) {
rc = SSH_ERROR;
}
error:
leave_function();
return rc; /* SSH_OK, AGAIN or ERROR */
}
#ifdef WITH_SSH1
static int packet_send1(ssh_session session) {
unsigned int blocksize = (session->current_crypto ?
session->current_crypto->out_cipher->blocksize : 8);
uint32_t currentlen = buffer_get_len(session->out_buffer) + sizeof(uint32_t);
char padstring[32] = {0};
int rc = SSH_ERROR;
uint32_t finallen;
uint32_t crc;
uint8_t padding;
enter_function();
ssh_log(session,SSH_LOG_PACKET,"Sending a %d bytes long packet",currentlen);
/* TODO FIXME
#if defined(HAVE_LIBZ) && defined(WITH_LIBZ)
if (session->current_crypto && session->current_crypto->do_compress_out) {
if (compress_buffer(session, session->out_buffer) < 0) {
goto error;
}
currentlen = buffer_get_len(session->out_buffer);
}
#endif
*/
padding = blocksize - (currentlen % blocksize);
if (session->current_crypto) {
ssh_get_random(padstring, padding, 0);
} else {
memset(padstring, 0, padding);
}
finallen = htonl(currentlen);
ssh_log(session, SSH_LOG_PACKET,
"%d bytes after comp + %d padding bytes = %d bytes packet",
currentlen, padding, ntohl(finallen));
if (buffer_prepend_data(session->out_buffer, &padstring, padding) < 0) {
goto error;
}
if (buffer_prepend_data(session->out_buffer, &finallen, sizeof(uint32_t)) < 0) {
goto error;
}
crc = ssh_crc32((char *)buffer_get(session->out_buffer) + sizeof(uint32_t),
buffer_get_len(session->out_buffer) - sizeof(uint32_t));
if (buffer_add_u32(session->out_buffer, ntohl(crc)) < 0) {
goto error;
}
#ifdef DEBUG_CRYPTO
ssh_print_hexa("Clear packet", buffer_get(session->out_buffer),
buffer_get_len(session->out_buffer));
#endif
packet_encrypt(session, (unsigned char *)buffer_get(session->out_buffer) + sizeof(uint32_t),
buffer_get_len(session->out_buffer) - sizeof(uint32_t));
#ifdef DEBUG_CRYPTO
ssh_print_hexa("encrypted packet",buffer_get(session->out_buffer),
buffer_get_len(session->out_buffer));
#endif
if (ssh_socket_write(session->socket, buffer_get(session->out_buffer),
buffer_get_len(session->out_buffer)) == SSH_ERROR) {
goto error;
}
rc = packet_flush(session, 0);
session->send_seq++;
if (buffer_reinit(session->out_buffer) < 0) {
rc = SSH_ERROR;
}
error:
leave_function();
return rc; /* SSH_OK, AGAIN or ERROR */
}
#endif /* WITH_SSH1 */
int packet_send(ssh_session session) {
#ifdef WITH_SSH1
if (session->version == 1) {
return packet_send1(session);
}
#endif
return packet_send2(session);
}
void packet_parse(ssh_session session) {
ssh_string error_s = NULL;
char *error = NULL;
uint32_t type = session->in_packet.type;
uint32_t tmp;
#ifdef WITH_SSH1
if (session->version == 1) {
/* SSH-1 */
switch(type) {
case SSH_MSG_DISCONNECT:
ssh_log(session, SSH_LOG_PACKET, "Received SSH_MSG_DISCONNECT");
ssh_set_error(session, SSH_FATAL, "Received SSH_MSG_DISCONNECT");
ssh_socket_close(session->socket);
session->alive = 0;
return;
case SSH_SMSG_STDOUT_DATA:
case SSH_SMSG_STDERR_DATA:
case SSH_SMSG_EXITSTATUS:
channel_handle1(session,type);
return;
case SSH_MSG_DEBUG:
case SSH_MSG_IGNORE:
break;
default:
ssh_log(session, SSH_LOG_PACKET,
"Unexpected message code %d", type);
}
return;
} else {
#endif /* WITH_SSH1 */
switch(type) {
case SSH2_MSG_DISCONNECT:
buffer_get_u32(session->in_buffer, &tmp);
error_s = buffer_get_ssh_string(session->in_buffer);
if (error_s == NULL) {
return;
}
error = string_to_char(error_s);
string_free(error_s);
if (error == NULL) {
return;
}
ssh_log(session, SSH_LOG_PACKET, "Received SSH_MSG_DISCONNECT\n");
ssh_set_error(session, SSH_FATAL,
"Received SSH_MSG_DISCONNECT: %s",error);
SAFE_FREE(error);
ssh_socket_close(session->socket);
session->alive = 0;
return;
case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
case SSH2_MSG_CHANNEL_DATA:
case SSH2_MSG_CHANNEL_EXTENDED_DATA:
case SSH2_MSG_CHANNEL_REQUEST:
case SSH2_MSG_CHANNEL_EOF:
case SSH2_MSG_CHANNEL_CLOSE:
channel_handle(session,type);
return;
case SSH2_MSG_IGNORE:
case SSH2_MSG_DEBUG:
return;
case SSH2_MSG_SERVICE_REQUEST:
case SSH2_MSG_USERAUTH_REQUEST:
case SSH2_MSG_CHANNEL_OPEN:
message_handle(session,type);
return;
case SSH2_MSG_GLOBAL_REQUEST:
ssh_global_request_handle(session);
return;
default:
ssh_log(session, SSH_LOG_RARE, "Received unhandled packet %d", type);
}
#ifdef WITH_SSH1
}
#endif
}
#ifdef WITH_SSH1
static int packet_wait1(ssh_session session, int type, int blocking) {
enter_function();
ssh_log(session, SSH_LOG_PROTOCOL, "packet_wait1 waiting for %d", type);
do {
if ((packet_read1(session) != SSH_OK) ||
(packet_translate(session) != SSH_OK)) {
leave_function();
return SSH_ERROR;
}
ssh_log(session, SSH_LOG_PACKET, "packet_wait1() received a type %d packet",
session->in_packet.type);
switch (session->in_packet.type) {
case SSH_MSG_DISCONNECT:
packet_parse(session);
leave_function();
return SSH_ERROR;
case SSH_SMSG_STDOUT_DATA:
case SSH_SMSG_STDERR_DATA:
case SSH_SMSG_EXITSTATUS:
if (channel_handle1(session,type) < 0) {
leave_function();
return SSH_ERROR;
}
break;
case SSH_MSG_DEBUG:
case SSH_MSG_IGNORE:
break;
/* case SSH2_MSG_CHANNEL_CLOSE:
packet_parse(session);
break;;
*/
default:
if (type && (type != session->in_packet.type)) {
ssh_set_error(session, SSH_FATAL,
"packet_wait1(): Received a %d type packet, but expected %d\n",
session->in_packet.type, type);
leave_function();
return SSH_ERROR;
}
leave_function();
return SSH_OK;
}
if (blocking == 0) {
leave_function();
return SSH_OK;
}
} while(1);
leave_function();
return SSH_OK;
}
#endif /* WITH_SSH1 */
static int packet_wait2(ssh_session session, int type, int blocking) {
int rc = SSH_ERROR;
enter_function();
do {
rc = packet_read2(session);
if (rc != SSH_OK) {
leave_function();
return rc;
}
if (packet_translate(session) != SSH_OK) {
leave_function();
return SSH_ERROR;
}
switch (session->in_packet.type) {
case SSH2_MSG_DISCONNECT:
packet_parse(session);
ssh_log(session, SSH_LOG_PACKET, "received disconnect packet");
leave_function();
return SSH_ERROR;
case SSH2_MSG_GLOBAL_REQUEST:
case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
case SSH2_MSG_CHANNEL_DATA:
case SSH2_MSG_CHANNEL_EXTENDED_DATA:
case SSH2_MSG_CHANNEL_REQUEST:
case SSH2_MSG_CHANNEL_EOF:
case SSH2_MSG_CHANNEL_CLOSE:
case SSH2_MSG_SERVICE_REQUEST:
case SSH2_MSG_USERAUTH_REQUEST:
case SSH2_MSG_CHANNEL_OPEN:
packet_parse(session);
break;
case SSH2_MSG_IGNORE:
case SSH2_MSG_DEBUG:
break;
default:
if (type && (type != session->in_packet.type)) {
ssh_set_error(session, SSH_FATAL,
"packet_wait2(): Received a %d type packet, but expected a %d\n",
session->in_packet.type, type);
leave_function();
return SSH_ERROR;
}
leave_function();
return SSH_OK;
}
if (blocking == 0) {
leave_function();
return SSH_OK; //shouldn't it return SSH_AGAIN here ?
}
} while(1);
leave_function();
return SSH_OK;
}
int packet_wait(ssh_session session, int type, int block) {
#ifdef WITH_SSH1
if (session->version == 1) {
return packet_wait1(session, type, block);
}
#endif
return packet_wait2(session, type, block);
}
/* vim: set ts=2 sw=2 et cindent: */

View File

@@ -1,442 +0,0 @@
/*
* session.c - non-networking functions
*
* This file is part of the SSH Library
*
* Copyright (c) 2005-2008 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.
*/
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include "libssh/libssh.h"
#include "libssh/priv.h"
#include "libssh/server.h"
#include "libssh/socket.h"
#include "libssh/agent.h"
#include "libssh/packet.h"
#include "libssh/session.h"
#include "libssh/misc.h"
#include "libssh/ssh2.h"
#include "libssh/buffer.h"
#define FIRST_CHANNEL 42 // why not ? it helps to find bugs.
/** \defgroup ssh_session SSH Session
* \brief functions that manage a session
*/
/** \addtogroup ssh_session
* @{ */
/** \brief creates a new ssh session
* \returns new ssh_session pointer
*/
ssh_session ssh_new(void) {
ssh_session session;
char *id;
int rc;
session = malloc(sizeof (struct ssh_session_struct));
if (session == NULL) {
return NULL;
}
ZERO_STRUCTP(session);
session->next_crypto = crypto_new();
if (session->next_crypto == NULL) {
goto err;
}
session->socket = ssh_socket_new(session);
if (session->socket == NULL) {
goto err;
}
session->out_buffer = buffer_new();
if (session->out_buffer == NULL) {
goto err;
}
session->in_buffer=buffer_new();
if (session->in_buffer == NULL) {
goto err;
}
session->alive = 0;
session->auth_methods = 0;
session->blocking = 1;
session->log_indent = 0;
session->maxchannel = FIRST_CHANNEL;
/* options */
session->port = 22;
session->fd = -1;
session->ssh2 = 1;
#ifdef WITH_SSH1
session->ssh1 = 1;
#else
session->ssh1 = 0;
#endif
#ifndef _WIN32
session->agent = agent_new(session);
if (session->agent == NULL) {
goto err;
}
#endif /* _WIN32 */
session->identity = ssh_list_new();
if (session->identity == NULL) {
goto err;
}
id = strdup("%d/id_rsa");
if (id == NULL) {
goto err;
}
rc = ssh_list_append(session->identity, id);
if (rc == SSH_ERROR) {
goto err;
}
id = strdup("%d/id_dsa");
if (id == NULL) {
goto err;
}
rc = ssh_list_append(session->identity, id);
if (rc == SSH_ERROR) {
goto err;
}
id = strdup("%d/identity");
if (id == NULL) {
goto err;
}
rc = ssh_list_append(session->identity, id);
if (rc == SSH_ERROR) {
goto err;
}
return session;
err:
ssh_free(session);
return NULL;
}
/**
* @brief deallocate a session handle
* @see ssh_disconnect()
* @see ssh_new()
*/
void ssh_free(ssh_session session) {
int i;
enter_function();
if (session == NULL) {
return;
}
SAFE_FREE(session->serverbanner);
SAFE_FREE(session->clientbanner);
SAFE_FREE(session->bindaddr);
SAFE_FREE(session->banner);
#ifdef WITH_PCAP
if(session->pcap_ctx){
ssh_pcap_context_free(session->pcap_ctx);
session->pcap_ctx=NULL;
}
#endif
buffer_free(session->in_buffer);
buffer_free(session->out_buffer);
session->in_buffer=session->out_buffer=NULL;
crypto_free(session->current_crypto);
crypto_free(session->next_crypto);
ssh_socket_free(session->socket);
/* delete all channels */
while (session->channels) {
channel_free(session->channels);
}
#ifndef _WIN32
agent_free(session->agent);
#endif /* _WIN32 */
if (session->client_kex.methods) {
for (i = 0; i < 10; i++) {
SAFE_FREE(session->client_kex.methods[i]);
}
}
if (session->server_kex.methods) {
for (i = 0; i < 10; i++) {
SAFE_FREE(session->server_kex.methods[i]);
}
}
SAFE_FREE(session->client_kex.methods);
SAFE_FREE(session->server_kex.methods);
privatekey_free(session->dsa_key);
privatekey_free(session->rsa_key);
if(session->ssh_message_list){
ssh_message msg;
while((msg=ssh_list_pop_head(ssh_message ,session->ssh_message_list))
!= NULL){
ssh_message_free(msg);
}
ssh_list_free(session->ssh_message_list);
}
if (session->identity) {
char *id;
for (id = ssh_list_pop_head(char *, session->identity);
id != NULL;
id = ssh_list_pop_head(char *, session->identity)) {
SAFE_FREE(id);
}
ssh_list_free(session->identity);
}
/* options */
SAFE_FREE(session->username);
SAFE_FREE(session->host);
SAFE_FREE(session->sshdir);
SAFE_FREE(session->knownhosts);
SAFE_FREE(session->ProxyCommand);
for (i = 0; i < 10; i++) {
if (session->wanted_methods[i]) {
SAFE_FREE(session->wanted_methods[i]);
}
}
/* burn connection, it could hang sensitive datas */
ZERO_STRUCTP(session);
SAFE_FREE(session);
}
/** \brief disconnect impolitely from remote host by closing the socket.
* Suitable if you forked and want to destroy this session.
* \param session current ssh session
*/
void ssh_silent_disconnect(ssh_session session) {
enter_function();
if (session == NULL) {
return;
}
ssh_socket_close(session->socket);
session->alive = 0;
ssh_disconnect(session);
leave_function();
}
/** \brief set the session in blocking/nonblocking mode
* \param session ssh session
* \param blocking zero for nonblocking mode
* \bug nonblocking code is in development and won't work as expected
*/
void ssh_set_blocking(ssh_session session, int blocking) {
if (session == NULL) {
return;
}
session->blocking = blocking ? 1 : 0;
}
/** In case you'd need the file descriptor of the connection
* to the server/client
* \brief recover the fd of connection
* \param session ssh session
* \return file descriptor of the connection, or -1 if it is
* not connected
*/
socket_t ssh_get_fd(ssh_session session) {
if (session == NULL) {
return -1;
}
return ssh_socket_get_fd(session->socket);
}
/** \brief say to the session it has data to read on the file descriptor without blocking
* \param session ssh session
*/
void ssh_set_fd_toread(ssh_session session) {
if (session == NULL) {
return;
}
ssh_socket_set_toread(session->socket);
}
/** \brief say the session it may write to the file descriptor without blocking
* \param session ssh session
*/
void ssh_set_fd_towrite(ssh_session session) {
if (session == NULL) {
return;
}
ssh_socket_set_towrite(session->socket);
}
/** \brief say the session it has an exception to catch on the file descriptor
* \param session ssh session
*/
void ssh_set_fd_except(ssh_session session) {
if (session == NULL) {
return;
}
ssh_socket_set_except(session->socket);
}
/** \warning I don't remember if this should be internal or not
*/
/* looks if there is data to read on the socket and parse it. */
int ssh_handle_packets(ssh_session session) {
int w = 0;
int e = 0;
int rc = -1;
enter_function();
do {
rc = ssh_socket_poll(session->socket, &w, &e);
if (rc <= 0) {
/* error or no data available */
leave_function();
return rc;
}
/* if an exception happened, it will be trapped by packet_read() */
if ((packet_read(session) != SSH_OK) ||
(packet_translate(session) != SSH_OK)) {
leave_function();
return -1;
}
packet_parse(session);
} while(rc > 0);
leave_function();
return rc;
}
/**
* @brief Get session status
*
* @param session The ssh session to use.
*
* @returns A bitmask including SSH_CLOSED, SSH_READ_PENDING or SSH_CLOSED_ERROR
* which respectively means the session is closed, has data to read on
* the connection socket and session was closed due to an error.
*/
int ssh_get_status(ssh_session session) {
int socketstate;
int r = 0;
if (session == NULL) {
return 0;
}
socketstate = ssh_socket_get_status(session->socket);
if (session->closed) {
r |= SSH_CLOSED;
}
if (socketstate & SSH_READ_PENDING) {
r |= SSH_READ_PENDING;
}
if (session->closed && (socketstate & SSH_CLOSED_ERROR)) {
r |= SSH_CLOSED_ERROR;
}
return r;
}
/** \brief get the disconnect message from the server
* \param session ssh session
* \return message sent by the server along with the disconnect, or NULL in which case the reason of the disconnect may be found with ssh_get_error.
* \see ssh_get_error()
*/
const char *ssh_get_disconnect_message(ssh_session session) {
if (session == NULL) {
return NULL;
}
if (!session->closed) {
ssh_set_error(session, SSH_REQUEST_DENIED,
"Connection not closed yet");
} else if(session->closed_by_except) {
ssh_set_error(session, SSH_REQUEST_DENIED,
"Connection closed by socket error");
} else if(!session->discon_msg) {
ssh_set_error(session, SSH_FATAL,
"Connection correctly closed but no disconnect message");
} else {
return session->discon_msg;
}
return NULL;
}
/**
* @brief Get the protocol version of the session.
*
* @param session The ssh session to use.
*
* @return 1 or 2, for ssh1 or ssh2, < 0 on error.
*/
int ssh_get_version(ssh_session session) {
if (session == NULL) {
return -1;
}
return session->version;
}
/**
* @internal
* @handle a SSH_MSG_GLOBAL_REQUEST packet
* @param session the SSH session
*/
void ssh_global_request_handle(ssh_session session){
ssh_string type;
char *type_c;
uint32_t needreply;
type=buffer_get_ssh_string(session->in_buffer);
buffer_get_u32(session->in_buffer,&needreply);
if(type==NULL)
return;
type_c=string_to_char(type);
if(!type_c)
return;
ssh_log(session, SSH_LOG_PROTOCOL,
"Received SSH_GLOBAL_REQUEST %s (wantreply=%d)",type_c,needreply);
SAFE_FREE(type_c);
string_free(type);
if(needreply != 0){
buffer_add_u8(session->out_buffer,SSH2_MSG_REQUEST_FAILURE);
packet_send(session);
}
}
/** @} */
/* vim: set ts=2 sw=2 et cindent: */

View File

@@ -1,731 +0,0 @@
/*
* socket.c - socket functions for the library
*
* This file is part of the SSH Library
*
* Copyright (c) 2008 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.
*/
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
extern char **environ;
#endif
#include "libssh/priv.h"
#include "libssh/socket.h"
#include "libssh/buffer.h"
#include "libssh/poll.h"
#include "libssh/session.h"
/** \defgroup ssh_socket SSH Sockets
* \addtogroup ssh_socket
* @{
*/
struct socket {
socket_t fd;
int last_errno;
int data_to_read; /* reading now on socket will
not block */
int data_to_write;
int data_except;
ssh_buffer out_buffer;
ssh_buffer in_buffer;
ssh_session session;
};
/*
* \internal
* \brief inits the socket system (windows specific)
*/
int ssh_socket_init(void) {
#ifdef _WIN32
struct WSAData wsaData;
/* Initiates use of the Winsock DLL by a process. */
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
return -1;
}
#endif
ssh_poll_init();
return 0;
}
/**
* @brief Cleanup the socket system.
*/
void ssh_socket_cleanup(void) {
ssh_poll_cleanup();
}
/**
* \internal
* \brief creates a new Socket object
*/
struct socket *ssh_socket_new(ssh_session session) {
struct socket *s;
s = malloc(sizeof(struct socket));
if (s == NULL) {
return NULL;
}
s->fd = SSH_INVALID_SOCKET;
s->last_errno = -1;
s->session = session;
s->in_buffer = buffer_new();
if (s->in_buffer == NULL) {
SAFE_FREE(s);
return NULL;
}
s->out_buffer=buffer_new();
if (s->out_buffer == NULL) {
buffer_free(s->in_buffer);
SAFE_FREE(s);
return NULL;
}
s->data_to_read = 0;
s->data_to_write = 0;
s->data_except = 0;
return s;
}
/* \internal
* \brief Deletes a socket object
*/
void ssh_socket_free(struct socket *s){
if (s == NULL) {
return;
}
ssh_socket_close(s);
buffer_free(s->in_buffer);
buffer_free(s->out_buffer);
SAFE_FREE(s);
}
#ifndef _WIN32
int ssh_socket_unix(struct socket *s, const char *path) {
struct sockaddr_un sunaddr;
sunaddr.sun_family = AF_UNIX;
snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path), "%s", path);
s->fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (s->fd == SSH_INVALID_SOCKET) {
return -1;
}
if (fcntl(s->fd, F_SETFD, 1) == -1) {
close(s->fd);
s->fd = SSH_INVALID_SOCKET;
return -1;
}
if (connect(s->fd, (struct sockaddr *) &sunaddr,
sizeof(sunaddr)) < 0) {
close(s->fd);
s->fd = SSH_INVALID_SOCKET;
return -1;
}
return 0;
}
#endif
/* \internal
* \brief closes a socket
*/
void ssh_socket_close(struct socket *s){
if (ssh_socket_is_open(s)) {
#ifdef _WIN32
closesocket(s->fd);
s->last_errno = WSAGetLastError();
#else
close(s->fd);
s->last_errno = errno;
#endif
s->fd = SSH_INVALID_SOCKET;
}
}
/* \internal
* \brief sets the file descriptor of the socket
*/
void ssh_socket_set_fd(struct socket *s, socket_t fd) {
s->fd = fd;
}
/* \internal
* \brief returns the file descriptor of the socket
*/
socket_t ssh_socket_get_fd(struct socket *s) {
return s->fd;
}
/* \internal
* \brief returns nonzero if the socket is open
*/
int ssh_socket_is_open(struct socket *s) {
return s->fd != SSH_INVALID_SOCKET;
}
/* \internal
* \brief read len bytes from socket into buffer
*/
static int ssh_socket_unbuffered_read(struct socket *s, void *buffer, uint32_t len) {
int rc = -1;
if (s->data_except) {
return -1;
}
rc = recv(s->fd,buffer, len, 0);
#ifdef _WIN32
s->last_errno = WSAGetLastError();
#else
s->last_errno = errno;
#endif
s->data_to_read = 0;
if (rc < 0) {
s->data_except = 1;
}
return rc;
}
/* \internal
* \brief writes len bytes from buffer to socket
*/
static int ssh_socket_unbuffered_write(struct socket *s, const void *buffer,
uint32_t len) {
int w = -1;
if (s->data_except) {
return -1;
}
w = send(s->fd,buffer, len, 0);
#ifdef _WIN32
s->last_errno = WSAGetLastError();
#else
s->last_errno = errno;
#endif
s->data_to_write = 0;
if (w < 0) {
s->data_except = 1;
}
return w;
}
/* \internal
* \brief returns nonzero if the current socket is in the fd_set
*/
int ssh_socket_fd_isset(struct socket *s, fd_set *set) {
if(s->fd == SSH_INVALID_SOCKET) {
return 0;
}
return FD_ISSET(s->fd,set);
}
/* \internal
* \brief sets the current fd in a fd_set and updates the max_fd
*/
void ssh_socket_fd_set(struct socket *s, fd_set *set, socket_t *max_fd) {
if (s->fd == SSH_INVALID_SOCKET)
return;
FD_SET(s->fd,set);
if (s->fd >= 0 &&
s->fd >= *max_fd &&
s->fd != SSH_INVALID_SOCKET) {
*max_fd = s->fd + 1;
}
}
/** \internal
* \brief reads blocking until len bytes have been read
*/
int ssh_socket_completeread(struct socket *s, void *buffer, uint32_t len) {
int r = -1;
uint32_t total = 0;
uint32_t toread = len;
if(! ssh_socket_is_open(s)) {
return SSH_ERROR;
}
while((r = ssh_socket_unbuffered_read(s, ((uint8_t*)buffer + total), toread))) {
if (r < 0) {
return SSH_ERROR;
}
total += r;
toread -= r;
if (total == len) {
return len;
}
if (r == 0) {
return 0;
}
}
/* connection closed */
return total;
}
/** \internal
* \brief Blocking write of len bytes
*/
int ssh_socket_completewrite(struct socket *s, const void *buffer, uint32_t len) {
ssh_session session = s->session;
int written = -1;
enter_function();
if(! ssh_socket_is_open(s)) {
leave_function();
return SSH_ERROR;
}
while (len >0) {
written = ssh_socket_unbuffered_write(s, buffer, len);
if (written == 0 || written == -1) {
leave_function();
return SSH_ERROR;
}
len -= written;
buffer = ((uint8_t*)buffer + written);
}
leave_function();
return SSH_OK;
}
/** \internal
* \brief buffered read of data (complete)
* \returns SSH_OK or SSH_ERROR.
* \returns SSH_AGAIN in nonblocking mode
*/
int ssh_socket_read(struct socket *s, void *buffer, int len){
ssh_session session = s->session;
int rc = SSH_ERROR;
enter_function();
rc = ssh_socket_wait_for_data(s, s->session, len);
if (rc != SSH_OK) {
leave_function();
return rc;
}
memcpy(buffer, buffer_get_rest(s->in_buffer), len);
buffer_pass_bytes(s->in_buffer, len);
leave_function();
return SSH_OK;
}
#define WRITE_BUFFERING_THRESHOLD 65536
/** \internal
* \brief buffered write of data
* \returns SSH_OK, or SSH_ERROR
* \warning has no effect on socket before a flush
*/
int ssh_socket_write(struct socket *s, const void *buffer, int len) {
ssh_session session = s->session;
int rc = SSH_ERROR;
enter_function();
if (buffer_add_data(s->out_buffer, buffer, len) < 0) {
return SSH_ERROR;
}
if (buffer_get_rest_len(s->out_buffer) > WRITE_BUFFERING_THRESHOLD) {
rc = ssh_socket_nonblocking_flush(s);
} else {
rc = len;
}
leave_function();
return rc;
}
/** \internal
* \brief wait for data on socket
* \param s socket
* \param session the ssh session
* \param len number of bytes to be read
* \returns SSH_OK bytes are available on socket
* \returns SSH_AGAIN need to call later for data
* \returns SSH_ERROR error happened
*/
int ssh_socket_wait_for_data(struct socket *s, ssh_session session, uint32_t len) {
char buffer[4096] = {0};
char *buf = NULL;
int except;
int can_write;
int to_read;
int r;
enter_function();
to_read = len - buffer_get_rest_len(s->in_buffer);
if (to_read <= 0) {
leave_function();
return SSH_OK;
}
if (session->blocking) {
buf = malloc(to_read);
if (buf == NULL) {
leave_function();
return SSH_ERROR;
}
r = ssh_socket_completeread(session->socket,buf,to_read);
if (r == SSH_ERROR || r == 0) {
ssh_set_error(session, SSH_FATAL,
(r == 0) ? "Connection closed by remote host" :
"Error reading socket");
ssh_socket_close(session->socket);
session->alive = 0;
SAFE_FREE(buf);
leave_function();
return SSH_ERROR;
}
if (buffer_add_data(s->in_buffer,buf,to_read) < 0) {
SAFE_FREE(buf);
leave_function();
return SSH_ERROR;
}
SAFE_FREE(buf);
leave_function();
return SSH_OK;
}
/* nonblocking read */
do {
/* internally sets data_to_read */
r = ssh_socket_poll(s, &can_write, &except);
if (r < 0 || !s->data_to_read) {
leave_function();
return SSH_AGAIN;
}
/* read as much as we can */
if (ssh_socket_is_open(session->socket)) {
r = ssh_socket_unbuffered_read(session->socket, buffer, sizeof(buffer));
} else {
r = -1;
}
if (r <= 0) {
ssh_set_error(session, SSH_FATAL,
(r == 0) ? "Connection closed by remote host" :
"Error reading socket");
ssh_socket_close(session->socket);
session->alive = 0;
leave_function();
return SSH_ERROR;
}
if (buffer_add_data(s->in_buffer,buffer, (uint32_t) r) < 0) {
leave_function();
return SSH_ERROR;
}
} while(buffer_get_rest_len(s->in_buffer) < len);
leave_function();
return SSH_OK;
}
/* ssh_socket_poll */
int ssh_socket_poll(struct socket *s, int *writeable, int *except) {
ssh_session session = s->session;
ssh_pollfd_t fd[1];
int rc = -1;
enter_function();
if (!ssh_socket_is_open(s)) {
*except = 1;
*writeable = 0;
return 0;
}
fd->fd = s->fd;
fd->events = 0;
fd->revents = 0;
if (!s->data_to_read) {
fd->events |= POLLIN;
}
if (!s->data_to_write) {
fd->events |= POLLOUT;
}
/* do not do poll if fd->events is empty, we already know the response */
if(fd->events != 0){
/* Make the call, and listen for errors */
rc = ssh_poll(fd, 1, 0);
if (rc < 0) {
ssh_set_error(session, SSH_FATAL, "poll(): %s", strerror(errno));
leave_function();
return -1;
}
}
if (!s->data_to_read) {
s->data_to_read = fd->revents & POLLIN;
}
if (!s->data_to_write) {
s->data_to_write = fd->revents & POLLOUT;
}
if (!s->data_except) {
s->data_except = fd->revents & POLLERR;
}
*except = s->data_except;
*writeable = s->data_to_write;
leave_function();
return (s->data_to_read || (buffer_get_rest_len(s->in_buffer) > 0));
}
/** \internal
* \brief nonblocking flush of the output buffer
*/
int ssh_socket_nonblocking_flush(struct socket *s) {
ssh_session session = s->session;
int except;
int can_write;
int w;
enter_function();
/* internally sets data_to_write */
if (ssh_socket_poll(s, &can_write, &except) < 0) {
leave_function();
return SSH_ERROR;
}
if (!ssh_socket_is_open(s)) {
session->alive = 0;
/* FIXME use ssh_socket_get_errno */
ssh_set_error(session, SSH_FATAL,
"Writing packet: error on socket (or connection closed): %s",
strerror(errno));
leave_function();
return SSH_ERROR;
}
while(s->data_to_write && buffer_get_rest_len(s->out_buffer) > 0) {
if (ssh_socket_is_open(s)) {
w = ssh_socket_unbuffered_write(s, buffer_get_rest(s->out_buffer),
buffer_get_rest_len(s->out_buffer));
} else {
/* write failed */
w = -1;
}
if (w < 0) {
session->alive = 0;
ssh_socket_close(s);
/* FIXME use ssh_socket_get_errno() */
ssh_set_error(session, SSH_FATAL,
"Writing packet: error on socket (or connection closed): %s",
strerror(errno));
leave_function();
return SSH_ERROR;
}
buffer_pass_bytes(s->out_buffer, w);
/* refresh the socket status */
if (ssh_socket_poll(session->socket, &can_write, &except) < 0) {
leave_function();
return SSH_ERROR;
}
}
/* Is there some data pending? */
if (buffer_get_rest_len(s->out_buffer) > 0) {
leave_function();
return SSH_AGAIN;
}
/* all data written */
leave_function();
return SSH_OK;
}
/** \internal
* \brief locking flush of the output packet buffer
*/
int ssh_socket_blocking_flush(struct socket *s) {
ssh_session session = s->session;
enter_function();
if (!ssh_socket_is_open(s)) {
session->alive = 0;
leave_function();
return SSH_ERROR;
}
if (s->data_except) {
leave_function();
return SSH_ERROR;
}
if (buffer_get_rest_len(s->out_buffer) == 0) {
leave_function();
return SSH_OK;
}
if (ssh_socket_completewrite(s, buffer_get_rest(s->out_buffer),
buffer_get_rest_len(s->out_buffer)) != SSH_OK) {
session->alive = 0;
ssh_socket_close(s);
/* FIXME use the proper errno */
ssh_set_error(session, SSH_FATAL,
"Writing packet: error on socket (or connection closed): %s",
strerror(errno));
leave_function();
return SSH_ERROR;
}
if (buffer_reinit(s->out_buffer) < 0) {
leave_function();
return SSH_ERROR;
}
leave_function();
return SSH_OK; // no data pending
}
void ssh_socket_set_towrite(struct socket *s) {
s->data_to_write = 1;
}
void ssh_socket_set_toread(struct socket *s) {
s->data_to_read = 1;
}
void ssh_socket_set_except(struct socket *s) {
s->data_except = 1;
}
int ssh_socket_data_available(struct socket *s) {
return s->data_to_read;
}
int ssh_socket_data_writable(struct socket *s) {
return s->data_to_write;
}
int ssh_socket_get_status(struct socket *s) {
int r = 0;
if (s->data_to_read) {
r |= SSH_READ_PENDING;
}
if (s->data_except) {
r |= SSH_CLOSED_ERROR;
}
return r;
}
#ifndef _WIN32
/**
* @internal
* @brief executes a command and redirect input and outputs
* @param command command to execute
* @param in input file descriptor
* @param out output file descriptor
*/
void ssh_execute_command(const char *command, socket_t in, socket_t out){
const char *args[]={"/bin/sh","-c",command,NULL};
/* redirect in and out to stdin, stdout and stderr */
dup2(in, 0);
dup2(out,1);
dup2(out,2);
close(in);
close(out);
execve(args[0],(char * const *)args,(char * const *)environ);
exit(1);
}
/**
* @internal
* @brief Open a socket on a ProxyCommand
* This call will always be nonblocking.
* @param s socket to connect.
* @param command Command to execute.
* @returns SSH_OK socket is being connected.
* @returns SSH_ERROR error while executing the command.
*/
socket_t ssh_socket_connect_proxycommand(ssh_session session,
const char *command){
socket_t fd[2];
int pid;
enter_function();
socketpair(AF_UNIX,SOCK_STREAM,0,fd);
pid = fork();
if(pid == 0){
ssh_execute_command(command,fd[1],fd[1]);
}
close(fd[1]);
ssh_log(session,SSH_LOG_PROTOCOL,"ProxyCommand connection pipe: [%d,%d]",fd[0],fd[1]);
return fd[0];
}
#endif /* _WIN32 */
/** @}
*/
/* vim: set ts=2 sw=2 et cindent: */

View File

@@ -1,183 +0,0 @@
/*
* string.c - ssh string functions
*
* This file is part of the SSH Library
*
* Copyright (c) 2003-2008 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.
*/
#include <stdlib.h>
#include <string.h>
#ifndef _WIN32
#include <arpa/inet.h>
#endif
#include "libssh/priv.h"
#include "libssh/string.h"
/** \defgroup ssh_string SSH Strings
* \brief string manipulations
*/
/** \addtogroup ssh_string
* @{ */
/**
* \brief Creates a new SSH String object
* \param size size of the string
* \return the newly allocated string
*/
struct ssh_string_struct *string_new(size_t size) {
struct ssh_string_struct *str = NULL;
str = malloc(size + 4);
if (str == NULL) {
return NULL;
}
str->size = htonl(size);
return str;
}
/**
* @brief Fill a string with given data. The string should be big enough.
*
* @param s An allocated string to fill with data.
*
* @param data The data to fill the string with.
*
* @param len Size of data.
*
* @return 0 on success, < 0 on error.
*/
int string_fill(struct ssh_string_struct *s, const void *data, size_t len) {
if ((s == NULL) || (data == NULL) ||
(len == 0) || (len > s->size)) {
return -1;
}
memcpy(s->string, data, len);
return 0;
}
/**
* \brief Creates a ssh stream using a C string
* \param what source 0-terminated C string
* \return the newly allocated string.
* \warning The nul byte is not copied nor counted in the ouput string.
*/
struct ssh_string_struct *string_from_char(const char *what) {
struct ssh_string_struct *ptr = NULL;
size_t len = strlen(what);
ptr = malloc(4 + len);
if (ptr == NULL) {
return NULL;
}
ptr->size = htonl(len);
memcpy(ptr->string, what, len);
return ptr;
}
/**
* \brief returns the size of a SSH string
* \param s the input SSH string
* \return size of the content of str, 0 on error
*/
size_t string_len(struct ssh_string_struct *s) {
if (s == NULL) {
return ntohl(0);
}
return ntohl(s->size);
}
/**
* \brief convert a SSH string to a C nul-terminated string
* \param s the input SSH string
* \return a malloc'ed string pointer.
* \warning If the input SSH string contains zeroes, some parts of
* the output string may not be readable with regular libc functions.
*/
char *string_to_char(struct ssh_string_struct *s) {
size_t len = ntohl(s->size) + 1;
char *new = malloc(len);
if (new == NULL) {
return NULL;
}
memcpy(new, s->string, len - 1);
new[len - 1] = '\0';
return new;
}
/**
* @brief Copy a string, return a newly allocated string. The caller has to
* free the string.
*
* @param s String to copy.
*
* @return Newly allocated copy of the string, NULL on error.
*/
struct ssh_string_struct *string_copy(struct ssh_string_struct *s) {
struct ssh_string_struct *new = malloc(ntohl(s->size) + 4);
if (new == NULL) {
return NULL;
}
new->size = s->size;
memcpy(new->string, s->string, ntohl(s->size));
return new;
}
/** \brief destroy data in a string so it couldn't appear in a core dump
* \param s string to burn
*/
void string_burn(struct ssh_string_struct *s) {
if (s == NULL) {
return;
}
memset(s->string, 'X', string_len(s));
}
/**
* @brief Get the payload of the string.
*
* @param s The string to get the data from.
*
* @return Return the data of the string or NULL on error.
*/
void *string_data(struct ssh_string_struct *s) {
if (s == NULL) {
return NULL;
}
return s->string;
}
/**
* \brief deallocate a STRING object
* \param s String to delete
*/
void string_free(struct ssh_string_struct *s) {
SAFE_FREE(s);
}
/** @} */
/* vim: set ts=2 sw=2 et cindent: */

File diff suppressed because it is too large Load Diff

5
libssh_threads.pc.cmake Normal file
View File

@@ -0,0 +1,5 @@
Name: ${APPLICATION_NAME}_threads
Description: The SSH Library Thread Extension
Version: ${APPLICATION_VERSION}
Libs: -L${LIB_INSTALL_DIR} -lssh_threads
Cflags: -I${INCLUDE_INSTALL_DIR}

View File

@@ -2,13 +2,13 @@ project(libssh-library C)
set(LIBSSH_PUBLIC_INCLUDE_DIRS
${CMAKE_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_SOURCE_DIR}
CACHE INTERNAL "libssh public include directories"
)
set(LIBSSH_PRIVATE_INCLUDE_DIRS
${CMAKE_BINARY_DIR}
${OPENSSL_INCLUDE_DIRS}
${GCRYPT_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIRS}
)
@@ -67,6 +67,11 @@ if (GCRYPT_LIBRARY)
)
endif (GCRYPT_LIBRARY)
set(LIBSSH_LINK_LIBRARIES
${LIBSSH_LINK_LIBRARIES}
CACHE INTERNAL "libssh link libraries"
)
set(libssh_SRCS
agent.c
auth.c
@@ -81,34 +86,34 @@ set(libssh_SRCS
crypt.c
dh.c
error.c
getpass.c
gcrypt_missing.c
gzip.c
init.c
kex.c
keyfiles.c
keys.c
known_hosts.c
legacy.c
libcrypto.c
libgcrypt.c
log.c
match.c
messages.c
misc.c
options.c
packet.c
pcap.c
pki.c
poll.c
session.c
scp.c
socket.c
string.c
threads.c
wrapper.c
)
if (WITH_PCAP)
set(libssh_SRCS
${libssh_SRCS}
pcap.c
)
endif (WITH_PCAP)
if (WITH_SFTP)
set(libssh_SRCS
${libssh_SRCS}
@@ -128,6 +133,7 @@ if (WITH_SSH1)
${libssh_SRCS}
auth1.c
channels1.c
packet1.c
)
endif (WITH_SSH1)
@@ -135,6 +141,7 @@ if (WITH_SERVER)
set(libssh_SRCS
${libssh_SRCS}
server.c
bind.c
)
endif (WITH_SERVER)
@@ -177,6 +184,11 @@ install(
if (WITH_STATIC_LIB)
add_library(${LIBSSH_STATIC_LIBRARY} STATIC ${libssh_SRCS})
if (MSVC)
set(OUTPUT_SUFFIX static)
else (MSVC)
set(OUTPUT_SUFFIX )
endif (MSVC)
set_target_properties(
${LIBSSH_STATIC_LIBRARY}
PROPERTIES
@@ -184,17 +196,31 @@ if (WITH_STATIC_LIB)
${LIBRARY_VERSION}
SOVERSION
${LIBRARY_SOVERSION}
COMPILE_FLAGS
"-DLIBSSH_STATIC"
OUTPUT_NAME
ssh
ARCHIVE_OUTPUT_DIRECTORY
${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_SUFFIX}
)
if (WIN32)
set_target_properties(
${LIBSSH_STATIC_LIBRARY}
PROPERTIES
COMPILE_FLAGS
"-DLIBSSH_STATIC"
)
endif (WIN32)
install(
TARGETS
${LIBSSH_STATIC_LIBRARY}
DESTINATION
${LIB_INSTALL_DIR}
${LIB_INSTALL_DIR}/${OUTPUT_SUFFIX}
COMPONENT
libraries
)
endif (WITH_STATIC_LIB)
if (CMAKE_HAVE_THREADS_LIBRARY)
add_subdirectory(threads)
endif (CMAKE_HAVE_THREADS_LIBRARY)

View File

@@ -27,7 +27,7 @@
* How does the ssh-agent work?
*
* a) client sends a request to get a list of all keys
* the agent returns the cound and all public keys
* the agent returns the count and all public keys
* b) iterate over them to check if the server likes one
* c) the client sends a sign request to the agent
* type, pubkey as blob, data to sign, flags
@@ -44,6 +44,7 @@
#include <unistd.h>
#ifndef _WIN32
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
@@ -81,12 +82,12 @@ static void agent_put_u32(void *vp, uint32_t v) {
p[3] = (uint8_t)v & 0xff;
}
static size_t atomicio(struct socket *s, void *buf, size_t n, int do_read) {
static size_t atomicio(ssh_socket s, void *buf, size_t n, int do_read) {
char *b = buf;
size_t pos = 0;
ssize_t res;
ssh_pollfd_t pfd;
socket_t fd = ssh_socket_get_fd(s);
socket_t fd = ssh_socket_get_fd_in(s);
pfd.fd = fd;
pfd.events = do_read ? POLLIN : POLLOUT;
@@ -154,7 +155,7 @@ void agent_close(struct ssh_agent_struct *agent) {
void agent_free(ssh_agent agent) {
if (agent) {
if (agent->ident) {
buffer_free(agent->ident);
ssh_buffer_free(agent->ident);
}
if (agent->sock) {
agent_close(agent);
@@ -208,7 +209,7 @@ static int agent_talk(struct ssh_session_struct *session,
uint32_t len = 0;
uint8_t payload[1024] = {0};
len = buffer_get_len(request);
len = buffer_get_rest_len(request);
ssh_log(session, SSH_LOG_PACKET, "agent_talk - len of request: %u", len);
agent_put_u32(payload, len);
@@ -284,23 +285,23 @@ int agent_get_ident_count(struct ssh_session_struct *session) {
}
/* send message to the agent requesting the list of identities */
request = buffer_new();
request = ssh_buffer_new();
if (buffer_add_u8(request, c1) < 0) {
ssh_set_error(session, SSH_FATAL, "Not enough space");
return -1;
}
reply = buffer_new();
reply = ssh_buffer_new();
if (reply == NULL) {
ssh_set_error(session, SSH_FATAL, "Not enough space");
return -1;
}
if (agent_talk(session, request, reply) < 0) {
buffer_free(request);
ssh_buffer_free(request);
return 0;
}
buffer_free(request);
ssh_buffer_free(request);
/* get message type and verify the answer */
buffer_get_u8(reply, (uint8_t *) &type);
@@ -323,7 +324,7 @@ int agent_get_ident_count(struct ssh_session_struct *session) {
ssh_set_error(session, SSH_FATAL,
"Too many identities in authentication reply: %d",
session->agent->count);
buffer_free(reply);
ssh_buffer_free(reply);
return -1;
}
@@ -369,24 +370,24 @@ struct ssh_public_key_struct *agent_get_next_ident(struct ssh_session_struct *se
/* get the comment */
tmp = buffer_get_ssh_string(session->agent->ident);
if (tmp == NULL) {
string_free(blob);
ssh_string_free(blob);
return NULL;
}
if (comment) {
*comment = string_to_char(tmp);
*comment = ssh_string_to_char(tmp);
} else {
string_free(blob);
string_free(tmp);
ssh_string_free(blob);
ssh_string_free(tmp);
return NULL;
}
string_free(tmp);
ssh_string_free(tmp);
/* get key from blob */
pubkey = publickey_from_string(session, blob);
string_free(blob);
ssh_string_free(blob);
break;
default:
return NULL;
@@ -409,7 +410,7 @@ ssh_string agent_sign_data(struct ssh_session_struct *session,
/* create blob from the pubkey */
blob = publickey_to_string(pubkey);
request = buffer_new();
request = ssh_buffer_new();
if (request == NULL) {
goto error;
}
@@ -425,11 +426,11 @@ ssh_string agent_sign_data(struct ssh_session_struct *session,
}
/* Add data */
dlen = buffer_get_len(data);
dlen = buffer_get_rest_len(data);
if (buffer_add_u32(request, htonl(dlen)) < 0) {
goto error;
}
if (buffer_add_data(request, buffer_get(data), dlen) < 0) {
if (buffer_add_data(request, buffer_get_rest(data), dlen) < 0) {
goto error;
}
@@ -437,19 +438,21 @@ ssh_string agent_sign_data(struct ssh_session_struct *session,
goto error;
}
string_free(blob);
ssh_string_free(blob);
blob = NULL;
reply = buffer_new();
reply = ssh_buffer_new();
if (reply == NULL) {
goto error;
}
/* send the request */
if (agent_talk(session, request, reply) < 0) {
buffer_free(request);
ssh_buffer_free(request);
return NULL;
}
buffer_free(request);
ssh_buffer_free(request);
request = NULL;
/* check if reply is valid */
if (buffer_get_u8(reply, (uint8_t *) &type) != sizeof(uint8_t)) {
@@ -457,24 +460,24 @@ ssh_string agent_sign_data(struct ssh_session_struct *session,
}
if (agent_failed(type)) {
ssh_log(session, SSH_LOG_RARE, "Agent reports failure in signing the key");
buffer_free(reply);
ssh_buffer_free(reply);
return NULL;
} else if (type != SSH2_AGENT_SIGN_RESPONSE) {
ssh_set_error(session, SSH_FATAL, "Bad authentication response: %d", type);
buffer_free(reply);
ssh_buffer_free(reply);
return NULL;
}
sig = buffer_get_ssh_string(reply);
buffer_free(reply);
ssh_buffer_free(reply);
return sig;
error:
ssh_set_error(session, SSH_FATAL, "Not enough memory");
string_free(blob);
buffer_free(request);
buffer_free(reply);
ssh_string_free(blob);
ssh_buffer_free(request);
ssh_buffer_free(reply);
return NULL;
}

File diff suppressed because it is too large Load Diff

View File

@@ -35,65 +35,87 @@
#ifdef WITH_SSH1
static int wait_auth1_status(ssh_session session) {
enter_function();
/* wait for a packet */
if (packet_read(session) != SSH_OK) {
return SSH_AUTH_ERROR;
}
if(packet_translate(session) != SSH_OK) {
return SSH_AUTH_ERROR;
}
switch(session->in_packet.type) {
case SSH_SMSG_SUCCESS:
while(session->auth_state == SSH_AUTH_STATE_NONE)
if (ssh_handle_packets(session, -2) != SSH_OK)
break;
ssh_log(session,SSH_LOG_PROTOCOL,"Auth state : %d",session->auth_state);
leave_function();
switch(session->auth_state) {
case SSH_AUTH_STATE_SUCCESS:
return SSH_AUTH_SUCCESS;
case SSH_SMSG_FAILURE:
case SSH_AUTH_STATE_FAILED:
return SSH_AUTH_DENIED;
default:
return SSH_AUTH_ERROR;
}
ssh_set_error(session, SSH_FATAL, "Was waiting for a SUCCESS or "
"FAILURE, got %d", session->in_packet.type);
return SSH_AUTH_ERROR;
}
void ssh_auth1_handler(ssh_session session, uint8_t type){
if(session->session_state != SSH_SESSION_STATE_AUTHENTICATING){
ssh_set_error(session,SSH_FATAL,"SSH_SMSG_SUCCESS or FAILED received in wrong state");
return;
}
if(type==SSH_SMSG_SUCCESS){
session->auth_state=SSH_AUTH_STATE_SUCCESS;
session->session_state=SSH_SESSION_STATE_AUTHENTICATED;
} else if(type==SSH_SMSG_FAILURE)
session->auth_state=SSH_AUTH_STATE_FAILED;
}
static int send_username(ssh_session session, const char *username) {
ssh_string user = NULL;
/* returns SSH_AUTH_SUCCESS or SSH_AUTH_DENIED */
if(session->auth_service_asked) {
return session->auth_service_asked;
if(session->auth_service_state == SSH_AUTH_SERVICE_USER_SENT) {
if(session->auth_state == SSH_AUTH_STATE_FAILED)
return SSH_AUTH_DENIED;
if(session->auth_state == SSH_AUTH_STATE_SUCCESS)
return SSH_AUTH_SUCCESS;
return SSH_AUTH_ERROR;
}
if (!username) {
if(!(username = session->username)) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) {
return session->auth_service_asked = SSH_AUTH_ERROR;
session->auth_service_state = SSH_AUTH_SERVICE_DENIED;
return SSH_ERROR;
} else {
username = session->username;
}
}
}
user = string_from_char(username);
user = ssh_string_from_char(username);
if (user == NULL) {
return SSH_AUTH_ERROR;
}
if (buffer_add_u8(session->out_buffer, SSH_CMSG_USER) < 0) {
string_free(user);
ssh_string_free(user);
return SSH_AUTH_ERROR;
}
if (buffer_add_ssh_string(session->out_buffer, user) < 0) {
string_free(user);
ssh_string_free(user);
return SSH_AUTH_ERROR;
}
string_free(user);
if (packet_send(session) != SSH_OK) {
ssh_string_free(user);
session->auth_state=SSH_AUTH_STATE_NONE;
if (packet_send(session) == SSH_ERROR) {
return SSH_AUTH_ERROR;
}
session->auth_service_asked = wait_auth1_status(session);
if(wait_auth1_status(session) == SSH_AUTH_SUCCESS){
session->auth_service_state=SSH_AUTH_SERVICE_USER_SENT;
session->auth_state=SSH_AUTH_STATE_SUCCESS;
ssh_set_error(session, SSH_NO_ERROR, "Authentication successful");
return SSH_AUTH_SUCCESS;
} else {
session->auth_service_state=SSH_AUTH_SERVICE_USER_SENT;
ssh_set_error(session,SSH_REQUEST_DENIED,"Password authentication necessary for user %s",username);
return SSH_AUTH_DENIED;
}
return session->auth_service_asked;
}
/* use the "none" authentication question */
@@ -101,44 +123,6 @@ int ssh_userauth1_none(ssh_session session, const char *username){
return send_username(session, username);
}
/*
int ssh_userauth_offer_pubkey(ssh_session session, char *username,int type, ssh_string publickey){
ssh_string user;
ssh_string service;
ssh_string method;
ssh_string algo;
int err=SSH_AUTH_ERROR;
if(!username)
if(!(username=session->options->username)){
if(options_default_username(session->options))
return SSH_AUTH_ERROR;
else
username=session->options->username;
}
if(ask_userauth(session))
return SSH_AUTH_ERROR;
user=string_from_char(username);
service=string_from_char("ssh-connection");
method=string_from_char("publickey");
algo=string_from_char(ssh_type_to_char(type));
packet_clear_out(session);
buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_REQUEST);
buffer_add_ssh_string(session->out_buffer,user);
buffer_add_ssh_string(session->out_buffer,service);
buffer_add_ssh_string(session->out_buffer,method);
buffer_add_u8(session->out_buffer,0);
buffer_add_ssh_string(session->out_buffer,algo);
buffer_add_ssh_string(session->out_buffer,publickey);
packet_send(session);
err=wait_auth_status(session,0);
free(user);
free(method);
free(service);
free(algo);
return err;
}
*/
/** \internal
* \todo implement ssh1 public key
*/
@@ -148,63 +132,19 @@ int ssh_userauth1_offer_pubkey(ssh_session session, const char *username,
(void) username;
(void) type;
(void) pubkey;
enter_function();
leave_function();
return SSH_AUTH_DENIED;
}
/*
int ssh_userauth_pubkey(ssh_session session, char *username, ssh_string publickey, ssh_private_key privatekey){
ssh_string user;
ssh_string service;
ssh_string method;
ssh_string algo;
ssh_string sign;
int err=SSH_AUTH_ERROR;
if(!username)
if(!(username=session->options->username)){
if(options_default_username(session->options))
return err;
else
username=session->options->username;
}
if(ask_userauth(session))
return err;
user=string_from_char(username);
service=string_from_char("ssh-connection");
method=string_from_char("publickey");
algo=string_from_char(ssh_type_to_char(privatekey->type));
*/ /* we said previously the public key was accepted */
/* packet_clear_out(session);
buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_REQUEST);
buffer_add_ssh_string(session->out_buffer,user);
buffer_add_ssh_string(session->out_buffer,service);
buffer_add_ssh_string(session->out_buffer,method);
buffer_add_u8(session->out_buffer,1);
buffer_add_ssh_string(session->out_buffer,algo);
buffer_add_ssh_string(session->out_buffer,publickey);
sign=ssh_do_sign(session,session->out_buffer,privatekey);
if(sign){
buffer_add_ssh_string(session->out_buffer,sign);
free(sign);
packet_send(session);
err=wait_auth_status(session,0);
}
free(user);
free(service);
free(method);
free(algo);
return err;
}
*/
int ssh_userauth1_password(ssh_session session, const char *username,
const char *password) {
ssh_string pwd = NULL;
int rc;
enter_function();
rc = send_username(session, username);
if (rc != SSH_AUTH_DENIED) {
leave_function();
return rc;
}
@@ -217,8 +157,9 @@ int ssh_userauth1_password(ssh_session session, const char *username,
/* cisco IOS doesn't like when a password is followed by zeroes and random pad. */
if(1 || strlen(password) >= 128) {
/* not risky to disclose the size of such a big password .. */
pwd = string_from_char(password);
pwd = ssh_string_from_char(password);
if (pwd == NULL) {
leave_function();
return SSH_AUTH_ERROR;
}
} else {
@@ -228,8 +169,9 @@ int ssh_userauth1_password(ssh_session session, const char *username,
* why garbage ? because nul bytes will be compressed by
* gzip and disclose password len.
*/
pwd = string_new(128);
pwd = ssh_string_new(128);
if (pwd == NULL) {
leave_function();
return SSH_AUTH_ERROR;
}
ssh_get_random( pwd->string, 128, 0);
@@ -237,24 +179,28 @@ int ssh_userauth1_password(ssh_session session, const char *username,
}
if (buffer_add_u8(session->out_buffer, SSH_CMSG_AUTH_PASSWORD) < 0) {
string_burn(pwd);
string_free(pwd);
ssh_string_burn(pwd);
ssh_string_free(pwd);
leave_function();
return SSH_AUTH_ERROR;
}
if (buffer_add_ssh_string(session->out_buffer, pwd) < 0) {
string_burn(pwd);
string_free(pwd);
ssh_string_burn(pwd);
ssh_string_free(pwd);
leave_function();
return SSH_AUTH_ERROR;
}
string_burn(pwd);
string_free(pwd);
if (packet_send(session) != SSH_OK) {
ssh_string_burn(pwd);
ssh_string_free(pwd);
session->auth_state=SSH_AUTH_STATE_NONE;
if (packet_send(session) == SSH_ERROR) {
leave_function();
return SSH_AUTH_ERROR;
}
return wait_auth1_status(session);
rc = wait_auth1_status(session);
leave_function();
return rc;
}
#endif /* WITH_SSH1 */

View File

@@ -39,9 +39,9 @@ static char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define SET_C(n, i) do { (n) |= ((i) & 63) << 6; } while (0)
#define SET_D(n, i) do { (n) |= ((i) & 63); } while (0)
#define GET_A(n) (((n) & 0xff0000) >> 16)
#define GET_B(n) (((n) & 0xff00) >> 8)
#define GET_C(n) ((n) & 0xff)
#define GET_A(n) (unsigned char) (((n) & 0xff0000) >> 16)
#define GET_B(n) (unsigned char) (((n) & 0xff00) >> 8)
#define GET_C(n) (unsigned char) ((n) & 0xff)
static int _base64_to_bin(unsigned char dest[3], const char *source, int num);
static int get_equals(char *string);
@@ -77,7 +77,7 @@ ssh_buffer base64_to_bin(const char *source) {
return NULL;
}
buffer = buffer_new();
buffer = ssh_buffer_new();
if (buffer == NULL) {
SAFE_FREE(base64);
return NULL;
@@ -162,7 +162,7 @@ ssh_buffer base64_to_bin(const char *source) {
error:
SAFE_FREE(base64);
buffer_free(buffer);
ssh_buffer_free(buffer);
return NULL;
}

384
src/bind.c Normal file
View File

@@ -0,0 +1,384 @@
/*
* bind.c : all ssh_bind functions
*
* This file is part of the SSH Library
*
* Copyright (c) 2004-2005 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.
*/
#include "config.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "libssh/priv.h"
#include "libssh/bind.h"
#include "libssh/libssh.h"
#include "libssh/server.h"
#include "libssh/keyfiles.h"
#include "libssh/buffer.h"
#include "libssh/socket.h"
#include "libssh/session.h"
/**
* @addtogroup libssh_server
*
* @{
*/
#ifdef _WIN32
#include <io.h>
#include <winsock2.h>
#include <ws2tcpip.h>
/*
* <wspiapi.h> is necessary for getaddrinfo before Windows XP, but it isn't
* available on some platforms like MinGW.
*/
#ifdef HAVE_WSPIAPI_H
# include <wspiapi.h>
#endif
#define SOCKOPT_TYPE_ARG4 char
/*
* We need to provide hstrerror. Not we can't call the parameter h_errno
* because it's #defined
*/
static char *hstrerror(int h_errno_val) {
static char text[50] = {0};
snprintf(text, sizeof(text), "getaddrino error %d\n", h_errno_val);
return text;
}
#else /* _WIN32 */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SOCKOPT_TYPE_ARG4 int
#endif /* _WIN32 */
static socket_t bind_socket(ssh_bind sshbind, const char *hostname,
int port) {
char port_c[6];
struct addrinfo *ai;
struct addrinfo hints;
int opt = 1;
socket_t s;
int rc;
ZERO_STRUCT(hints);
hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM;
snprintf(port_c, 6, "%d", port);
rc = getaddrinfo(hostname, port_c, &hints, &ai);
if (rc != 0) {
ssh_set_error(sshbind,
SSH_FATAL,
"Resolving %s: %s", hostname, gai_strerror(rc));
return -1;
}
s = socket (ai->ai_family,
ai->ai_socktype,
ai->ai_protocol);
if (s == SSH_INVALID_SOCKET) {
ssh_set_error(sshbind, SSH_FATAL, "%s", strerror(errno));
freeaddrinfo (ai);
return -1;
}
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
(char *)&opt, sizeof(opt)) < 0) {
ssh_set_error(sshbind,
SSH_FATAL,
"Setting socket options failed: %s",
hstrerror(h_errno));
freeaddrinfo (ai);
close(s);
return -1;
}
if (bind(s, ai->ai_addr, ai->ai_addrlen) != 0) {
ssh_set_error(sshbind,
SSH_FATAL,
"Binding to %s:%d: %s",
hostname,
port,
strerror(errno));
freeaddrinfo (ai);
close(s);
return -1;
}
freeaddrinfo (ai);
return s;
}
ssh_bind ssh_bind_new(void) {
ssh_bind ptr;
ptr = malloc(sizeof(struct ssh_bind_struct));
if (ptr == NULL) {
return NULL;
}
ZERO_STRUCTP(ptr);
ptr->bindfd = SSH_INVALID_SOCKET;
ptr->bindport= 22;
ptr->common.log_verbosity = 0;
return ptr;
}
int ssh_bind_listen(ssh_bind sshbind) {
const char *host;
socket_t fd;
if (ssh_init() < 0) {
ssh_set_error(sshbind, SSH_FATAL, "ssh_init() failed");
return -1;
}
host = sshbind->bindaddr;
if (host == NULL) {
host = "0.0.0.0";
}
fd = bind_socket(sshbind, host, sshbind->bindport);
if (fd == SSH_INVALID_SOCKET) {
return -1;
}
sshbind->bindfd = fd;
if (listen(fd, 10) < 0) {
ssh_set_error(sshbind, SSH_FATAL,
"Listening to socket %d: %s",
fd, strerror(errno));
close(fd);
return -1;
}
return 0;
}
int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks,
void *userdata){
if (sshbind == NULL) {
return SSH_ERROR;
}
if (callbacks == NULL) {
ssh_set_error_invalid(sshbind, __FUNCTION__);
return SSH_ERROR;
}
if(callbacks->size <= 0 || callbacks->size > 1024 * sizeof(void *)){
ssh_set_error(sshbind,SSH_FATAL,
"Invalid callback passed in (badly initialized)");
return SSH_ERROR;
}
sshbind->bind_callbacks = callbacks;
sshbind->bind_callbacks_userdata=userdata;
return 0;
}
/** @internal
* @brief callback being called by poll when an event happens
*
*/
static int ssh_bind_poll_callback(ssh_poll_handle sshpoll,
socket_t fd, int revents, void *user){
ssh_bind sshbind=(ssh_bind)user;
(void)sshpoll;
(void)fd;
if(revents & POLLIN){
/* new incoming connection */
if(ssh_callbacks_exists(sshbind->bind_callbacks,incoming_connection)){
sshbind->bind_callbacks->incoming_connection(sshbind,
sshbind->bind_callbacks_userdata);
}
}
return 0;
}
/** @internal
* @brief returns the current poll handle, or create it
* @param sshbind the ssh_bind object
* @returns a ssh_poll handle suitable for operation
*/
ssh_poll_handle ssh_bind_get_poll(ssh_bind sshbind){
if(sshbind->poll)
return sshbind->poll;
sshbind->poll=ssh_poll_new(sshbind->bindfd,POLLIN,
ssh_bind_poll_callback,sshbind);
return sshbind->poll;
}
void ssh_bind_set_blocking(ssh_bind sshbind, int blocking) {
sshbind->blocking = blocking ? 1 : 0;
}
socket_t ssh_bind_get_fd(ssh_bind sshbind) {
return sshbind->bindfd;
}
void ssh_bind_set_fd(ssh_bind sshbind, socket_t fd) {
sshbind->bindfd = fd;
}
void ssh_bind_fd_toaccept(ssh_bind sshbind) {
sshbind->toaccept = 1;
}
void ssh_bind_free(ssh_bind sshbind){
int i;
if (sshbind == NULL) {
return;
}
if (sshbind->bindfd >= 0) {
#ifdef _WIN32
closesocket(sshbind->bindfd);
#else
close(sshbind->bindfd);
#endif
}
sshbind->bindfd = SSH_INVALID_SOCKET;
/* options */
SAFE_FREE(sshbind->banner);
SAFE_FREE(sshbind->dsakey);
SAFE_FREE(sshbind->rsakey);
SAFE_FREE(sshbind->bindaddr);
for (i = 0; i < 10; i++) {
if (sshbind->wanted_methods[i]) {
SAFE_FREE(sshbind->wanted_methods[i]);
}
}
SAFE_FREE(sshbind);
}
int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
ssh_private_key dsa = NULL;
ssh_private_key rsa = NULL;
socket_t fd = SSH_INVALID_SOCKET;
int i;
if (sshbind->bindfd == SSH_INVALID_SOCKET) {
ssh_set_error(sshbind, SSH_FATAL,
"Can't accept new clients on a not bound socket.");
return SSH_ERROR;
}
if(session == NULL){
ssh_set_error(sshbind, SSH_FATAL,"session is null");
return SSH_ERROR;
}
if (sshbind->dsakey == NULL && sshbind->rsakey == NULL) {
ssh_set_error(sshbind, SSH_FATAL,
"DSA or RSA host key file must be set before accept()");
return SSH_ERROR;
}
if (sshbind->dsakey) {
dsa = _privatekey_from_file(sshbind, sshbind->dsakey, SSH_KEYTYPE_DSS);
if (dsa == NULL) {
return SSH_ERROR;
}
}
if (sshbind->rsakey) {
rsa = _privatekey_from_file(sshbind, sshbind->rsakey, SSH_KEYTYPE_RSA);
if (rsa == NULL) {
privatekey_free(dsa);
return SSH_ERROR;
}
}
fd = accept(sshbind->bindfd, NULL, NULL);
if (fd == SSH_INVALID_SOCKET) {
ssh_set_error(sshbind, SSH_FATAL,
"Accepting a new connection: %s",
strerror(errno));
privatekey_free(dsa);
privatekey_free(rsa);
return SSH_ERROR;
}
session->server = 1;
session->version = 2;
/* copy options */
for (i = 0; i < 10; ++i) {
if (sshbind->wanted_methods[i]) {
session->wanted_methods[i] = strdup(sshbind->wanted_methods[i]);
if (session->wanted_methods[i] == NULL) {
privatekey_free(dsa);
privatekey_free(rsa);
return SSH_ERROR;
}
}
}
if (sshbind->bindaddr == NULL)
session->bindaddr = NULL;
else {
SAFE_FREE(session->bindaddr);
session->bindaddr = strdup(sshbind->bindaddr);
if (session->bindaddr == NULL) {
privatekey_free(dsa);
privatekey_free(rsa);
return SSH_ERROR;
}
}
session->common.log_verbosity = sshbind->common.log_verbosity;
ssh_socket_free(session->socket);
session->socket = ssh_socket_new(session);
if (session->socket == NULL) {
/* perhaps it may be better to copy the error from session to sshbind */
ssh_set_error_oom(sshbind);
privatekey_free(dsa);
privatekey_free(rsa);
return SSH_ERROR;
}
ssh_socket_set_fd(session->socket, fd);
ssh_socket_get_poll_handle_out(session->socket);
session->dsa_key = dsa;
session->rsa_key = rsa;
return SSH_OK;
}
/**
* @}
*/

620
src/buffer.c Normal file
View File

@@ -0,0 +1,620 @@
/*
* buffer.c - buffer functions
*
* This file is part of the SSH Library
*
* 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.
*
* The SSH Library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the SSH Library; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#ifndef _WIN32
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#include "libssh/priv.h"
#include "libssh/buffer.h"
/**
* @defgroup libssh_buffer The SSH buffer functions.
* @ingroup libssh
*
* Functions to handle SSH buffers.
*
* @{
*/
#ifdef DEBUG_BUFFER
/**
* @internal
*
* @brief Check that preconditions and postconditions are valid.
*
* @param[in] buf The buffer to check.
*/
static void buffer_verify(ssh_buffer buf){
int doabort=0;
if(buf->data == NULL)
return;
if(buf->used > buf->allocated){
fprintf(stderr,"Buffer error : allocated %u, used %u\n",buf->allocated, buf->used);
doabort=1;
}
if(buf->pos > buf->used){
fprintf(stderr,"Buffer error : position %u, used %u\n",buf->pos, buf->used);
doabort=1;
}
if(buf->pos > buf->allocated){
fprintf(stderr,"Buffer error : position %u, allocated %u\n",buf->pos, buf->allocated);
doabort=1;
}
if(doabort)
abort();
}
#else
#define buffer_verify(x)
#endif
/**
* @brief Create a new SSH buffer.
*
* @return A newly initialized SSH buffer, NULL on error.
*/
struct ssh_buffer_struct *ssh_buffer_new(void) {
struct ssh_buffer_struct *buf = malloc(sizeof(struct ssh_buffer_struct));
if (buf == NULL) {
return NULL;
}
memset(buf, 0, sizeof(struct ssh_buffer_struct));
buffer_verify(buf);
return buf;
}
/**
* @brief Deallocate a SSH buffer.
*
* \param[in] buffer The buffer to free.
*/
void ssh_buffer_free(struct ssh_buffer_struct *buffer) {
if (buffer == NULL) {
return;
}
buffer_verify(buffer);
if (buffer->data) {
/* burn the data */
memset(buffer->data, 0, buffer->allocated);
SAFE_FREE(buffer->data);
}
memset(buffer, 'X', sizeof(*buffer));
SAFE_FREE(buffer);
}
static int realloc_buffer(struct ssh_buffer_struct *buffer, size_t needed) {
size_t smallest = 1;
char *new;
buffer_verify(buffer);
/* Find the smallest power of two which is greater or equal to needed */
while(smallest <= needed) {
if (smallest == 0) {
return -1;
}
smallest <<= 1;
}
needed = smallest;
new = realloc(buffer->data, needed);
if (new == NULL) {
return -1;
}
buffer->data = new;
buffer->allocated = needed;
buffer_verify(buffer);
return 0;
}
/** @internal
* @brief shifts a buffer to remove unused data in the beginning
* @param buffer SSH buffer
*/
static void buffer_shift(ssh_buffer buffer){
buffer_verify(buffer);
if(buffer->pos==0)
return;
memmove(buffer->data, buffer->data + buffer->pos, buffer->used - buffer->pos);
buffer->used -= buffer->pos;
buffer->pos=0;
buffer_verify(buffer);
}
/**
* @internal
*
* @brief Reinitialize a SSH buffer.
*
* @param[in] buffer The buffer to reinitialize.
*
* @return 0 on success, < 0 on error.
*/
int buffer_reinit(struct ssh_buffer_struct *buffer) {
buffer_verify(buffer);
memset(buffer->data, 0, buffer->used);
buffer->used = 0;
buffer->pos = 0;
if(buffer->allocated > 127) {
if (realloc_buffer(buffer, 127) < 0) {
return -1;
}
}
buffer_verify(buffer);
return 0;
}
/**
* @internal
*
* @brief Add data at the tail of a buffer.
*
* @param[in] buffer The buffer to add the data.
*
* @param[in] data A pointer to the data to add.
*
* @param[in] len The length of the data to add.
*
* @return 0 on success, < 0 on error.
*/
int buffer_add_data(struct ssh_buffer_struct *buffer, const void *data, uint32_t len) {
buffer_verify(buffer);
if (buffer->used + len < len)
return -1;
if (buffer->allocated < (buffer->used + len)) {
if(buffer->pos > 0)
buffer_shift(buffer);
if (realloc_buffer(buffer, buffer->used + len) < 0) {
return -1;
}
}
memcpy(buffer->data+buffer->used, data, len);
buffer->used+=len;
buffer_verify(buffer);
return 0;
}
/**
* @internal
*
* @brief Add a SSH string to the tail of a buffer.
*
* @param[in] buffer The buffer to add the string.
*
* @param[in] string The SSH String to add.
*
* @return 0 on success, < 0 on error.
*/
int buffer_add_ssh_string(struct ssh_buffer_struct *buffer,
struct ssh_string_struct *string) {
uint32_t len = 0;
len = ssh_string_len(string);
if (buffer_add_data(buffer, string, len + sizeof(uint32_t)) < 0) {
return -1;
}
return 0;
}
/**
* @internal
*
* @brief Add a 32 bits unsigned integer to the tail of a buffer.
*
* @param[in] buffer The buffer to add the integer.
*
* @param[in] data The 32 bits integer to add.
*
* @return 0 on success, -1 on error.
*/
int buffer_add_u32(struct ssh_buffer_struct *buffer,uint32_t data){
if (buffer_add_data(buffer, &data, sizeof(data)) < 0) {
return -1;
}
return 0;
}
/**
* @internal
*
* @brief Add a 16 bits unsigned integer to the tail of a buffer.
*
* @param[in] buffer The buffer to add the integer.
*
* @param[in] data The 16 bits integer to add.
*
* @return 0 on success, -1 on error.
*/
int buffer_add_u16(struct ssh_buffer_struct *buffer,uint16_t data){
if (buffer_add_data(buffer, &data, sizeof(data)) < 0) {
return -1;
}
return 0;
}
/**
* @internal
*
* @brief Add a 64 bits unsigned integer to the tail of a buffer.
*
* @param[in] buffer The buffer to add the integer.
*
* @param[in] data The 64 bits integer to add.
*
* @return 0 on success, -1 on error.
*/
int buffer_add_u64(struct ssh_buffer_struct *buffer, uint64_t data){
if (buffer_add_data(buffer, &data, sizeof(data)) < 0) {
return -1;
}
return 0;
}
/**
* @internal
*
* @brief Add a 8 bits unsigned integer to the tail of a buffer.
*
* @param[in] buffer The buffer to add the integer.
*
* @param[in] data The 8 bits integer to add.
*
* @return 0 on success, -1 on error.
*/
int buffer_add_u8(struct ssh_buffer_struct *buffer,uint8_t data){
if (buffer_add_data(buffer, &data, sizeof(uint8_t)) < 0) {
return -1;
}
return 0;
}
/**
* @internal
*
* @brief Add data at the head of a buffer.
*
* @param[in] buffer The buffer to add the data.
*
* @param[in] data The data to prepend.
*
* @param[in] len The length of data to prepend.
*
* @return 0 on success, -1 on error.
*/
int buffer_prepend_data(struct ssh_buffer_struct *buffer, const void *data,
uint32_t len) {
buffer_verify(buffer);
if(len <= buffer->pos){
/* It's possible to insert data between begin and pos */
memcpy(buffer->data + (buffer->pos - len), data, len);
buffer->pos -= len;
buffer_verify(buffer);
return 0;
}
/* pos isn't high enough */
if (buffer->used - buffer->pos + len < len)
return -1;
if (buffer->allocated < (buffer->used - buffer->pos + len)) {
if (realloc_buffer(buffer, buffer->used - buffer->pos + len) < 0) {
return -1;
}
}
memmove(buffer->data + len, buffer->data + buffer->pos, buffer->used - buffer->pos);
memcpy(buffer->data, data, len);
buffer->used += len - buffer->pos;
buffer->pos = 0;
buffer_verify(buffer);
return 0;
}
/**
* @internal
*
* @brief Append data from a buffer to the tail of another buffer.
*
* @param[in] buffer The destination buffer.
*
* @param[in] source The source buffer to append. It doesn't take the
* position of the buffer into account.
*
* @return 0 on success, -1 on error.
*/
int buffer_add_buffer(struct ssh_buffer_struct *buffer,
struct ssh_buffer_struct *source) {
if (buffer_add_data(buffer, buffer_get_rest(source), buffer_get_rest_len(source)) < 0) {
return -1;
}
return 0;
}
/**
* @brief Get a pointer on the head of a buffer.
*
* @param[in] buffer The buffer to get the head pointer.
*
* @return A data pointer on the head. It doesn't take the position
* into account.
*
* @warning Don't expect data to be nul-terminated.
*
* @see buffer_get_rest()
* @see buffer_get_len()
*/
void *ssh_buffer_get_begin(struct ssh_buffer_struct *buffer){
return buffer->data;
}
/**
* @internal
*
* @brief Get a pointer to the head of a buffer at the current position.
*
* @param[in] buffer The buffer to get the head pointer.
*
* @return A pointer to the data from current position.
*
* @see buffer_get_rest_len()
* @see buffer_get()
*/
void *buffer_get_rest(struct ssh_buffer_struct *buffer){
return buffer->data + buffer->pos;
}
/**
* @brief Get the length of the buffer, not counting position.
*
* @param[in] buffer The buffer to get the length from.
*
* @return The length of the buffer.
*
* @see buffer_get()
*/
uint32_t ssh_buffer_get_len(struct ssh_buffer_struct *buffer){
return buffer->used;
}
/**
* @internal
*
* @brief Get the length of the buffer from the current position.
*
* @param[in] buffer The buffer to get the length from.
*
* @return The length of the buffer.
*
* @see buffer_get_rest()
*/
uint32_t buffer_get_rest_len(struct ssh_buffer_struct *buffer){
buffer_verify(buffer);
return buffer->used - buffer->pos;
}
/**
* @internal
*
* @brief Advance the position in the buffer.
*
* This has effect to "eat" bytes at head of the buffer.
*
* @param[in] buffer The buffer to advance the position.
*
* @param[in] len The number of bytes to eat.
*
* @return The new size of the buffer.
*/
uint32_t buffer_pass_bytes(struct ssh_buffer_struct *buffer, uint32_t len){
buffer_verify(buffer);
if (buffer->pos + len < len || buffer->used < buffer->pos + len)
return 0;
buffer->pos+=len;
/* if the buffer is empty after having passed the whole bytes into it, we can clean it */
if(buffer->pos==buffer->used){
buffer->pos=0;
buffer->used=0;
}
buffer_verify(buffer);
return len;
}
/**
* @internal
*
* @brief Cut the end of the buffer.
*
* @param[in] buffer The buffer to cut.
*
* @param[in] len The number of bytes to remove from the tail.
*
* @return The new size of the buffer.
*/
uint32_t buffer_pass_bytes_end(struct ssh_buffer_struct *buffer, uint32_t len){
buffer_verify(buffer);
if (buffer->used < len) {
return 0;
}
buffer->used-=len;
buffer_verify(buffer);
return len;
}
/**
* @internal
*
* @brief Get the remaining data out of the buffer and adjust the read pointer.
*
* @param[in] buffer The buffer to read.
*
* @param[in] data The data buffer where to store the data.
*
* @param[in] len The length to read from the buffer.
*
* @returns 0 if there is not enough data in buffer, len otherwise.
*/
uint32_t buffer_get_data(struct ssh_buffer_struct *buffer, void *data, uint32_t len){
/*
* Check for a integer overflow first, then check if not enough data is in
* the buffer.
*/
if (buffer->pos + len < len || buffer->pos + len > buffer->used) {
return 0;
}
memcpy(data,buffer->data+buffer->pos,len);
buffer->pos+=len;
return len; /* no yet support for partial reads (is it really needed ?? ) */
}
/**
* @internal
*
* @brief Get a 8 bits unsigned int out of the buffer and adjusts the read
* pointer.
*
* @param[in] buffer The buffer to read.
*
* @param[in] data A pointer to a uint8_t where to store the data.
*
* @returns 0 if there is not enough data in buffer, 1 otherwise.
*/
int buffer_get_u8(struct ssh_buffer_struct *buffer, uint8_t *data){
return buffer_get_data(buffer,data,sizeof(uint8_t));
}
/** \internal
* \brief gets a 32 bits unsigned int out of the buffer. Adjusts the read pointer.
* \param buffer Buffer to read
* \param data pointer to a uint32_t where to store the data
* \returns 0 if there is not enough data in buffer
* \returns 4 otherwise.
*/
int buffer_get_u32(struct ssh_buffer_struct *buffer, uint32_t *data){
return buffer_get_data(buffer,data,sizeof(uint32_t));
}
/**
* @internal
*
* @brief Get a 64 bits unsigned int out of the buffer and adjusts the read
* pointer.
*
* @param[in] buffer The buffer to read.
*
* @param[in] data A pointer to a uint64_t where to store the data.
*
* @returns 0 if there is not enough data in buffer, 8 otherwise.
*/
int buffer_get_u64(struct ssh_buffer_struct *buffer, uint64_t *data){
return buffer_get_data(buffer,data,sizeof(uint64_t));
}
/**
* @internal
*
* @brief Get a SSH String out of the buffer and adjusts the read pointer.
*
* @param[in] buffer The buffer to read.
*
* @returns The SSH String, NULL on error.
*/
struct ssh_string_struct *buffer_get_ssh_string(struct ssh_buffer_struct *buffer) {
uint32_t stringlen;
uint32_t hostlen;
struct ssh_string_struct *str = NULL;
if (buffer_get_u32(buffer, &stringlen) == 0) {
return NULL;
}
hostlen = ntohl(stringlen);
/* verify if there is enough space in buffer to get it */
if (buffer->pos + hostlen < hostlen || buffer->pos + hostlen > buffer->used) {
return NULL; /* it is indeed */
}
str = ssh_string_new(hostlen);
if (str == NULL) {
return NULL;
}
if (buffer_get_data(buffer, ssh_string_data(str), hostlen) != hostlen) {
/* should never happen */
SAFE_FREE(str);
return NULL;
}
return str;
}
/**
* @internal
*
* @brief Get a mpint out of the buffer and adjusts the read pointer.
*
* @note This function is SSH-1 only.
*
* @param[in] buffer The buffer to read.
*
* @returns The SSH String containing the mpint, NULL on error.
*/
struct ssh_string_struct *buffer_get_mpint(struct ssh_buffer_struct *buffer) {
uint16_t bits;
uint32_t len;
struct ssh_string_struct *str = NULL;
if (buffer_get_data(buffer, &bits, sizeof(uint16_t)) != sizeof(uint16_t)) {
return NULL;
}
bits = ntohs(bits);
len = (bits + 7) / 8;
if (buffer->pos + len < len || buffer->pos + len > buffer->used) {
return NULL;
}
str = ssh_string_new(len);
if (str == NULL) {
return NULL;
}
if (buffer_get_data(buffer, ssh_string_data(str), len) != len) {
SAFE_FREE(str);
return NULL;
}
return str;
}
/** @} */
/* vim: set ts=4 sw=4 et cindent: */

61
src/callbacks.c Normal file
View File

@@ -0,0 +1,61 @@
/*
* callbacks.c - callback functions
*
* This file is part of the SSH Library
*
* Copyright (c) 2009 by Andreas Schneider <mail@cynapses.org>
*
* The SSH Library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* The SSH Library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the SSH Library; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#include "config.h"
#include "libssh/callbacks.h"
#include "libssh/session.h"
int ssh_set_callbacks(ssh_session session, ssh_callbacks cb) {
if (session == NULL || cb == NULL) {
return SSH_ERROR;
}
enter_function();
if(cb->size <= 0 || cb->size > 1024 * sizeof(void *)){
ssh_set_error(session,SSH_FATAL,
"Invalid callback passed in (badly initialized)");
leave_function();
return SSH_ERROR;
}
session->common.callbacks = cb;
leave_function();
return 0;
}
int ssh_set_channel_callbacks(ssh_channel channel, ssh_channel_callbacks cb) {
ssh_session session = NULL;
if (channel == NULL || cb == NULL) {
return SSH_ERROR;
}
session = channel->session;
enter_function();
if(cb->size <= 0 || cb->size > 1024 * sizeof(void *)){
ssh_set_error(session,SSH_FATAL,
"Invalid channel callback passed in (badly initialized)");
leave_function();
return SSH_ERROR;
}
channel->callbacks = cb;
leave_function();
return 0;
}

Some files were not shown because too many files have changed in this diff Show More