Compare commits

...

190 Commits

Author SHA1 Message Date
Andreas Schneider
e6d17ccc15 build: Updated the ChangeLog. 2011-01-15 09:57:00 +01:00
Andreas Schneider
0b0a2d85d0 build: Updated version number to 0.4.8 2011-01-10 14:52:25 +01:00
Andreas Schneider
8d7245f54b keys: Fixed memory leaks in session signing.
Found by cppcheck - http://test.libssh.org/cppcheck-analyzer/
2011-01-07 15:48:39 +01:00
Andreas Schneider
0b1f8a2b0c dh: Fixed a memory leak in ssh_print_hexa.
Found by cppcheck - http://test.libssh.org/cppcheck-analyzer/
(cherry picked from commit a016d356fa)
2011-01-07 15:47:18 +01:00
Aris Adamantiadis
8d676c77b1 Fix release number 2011-01-07 12:07:09 +01:00
Aris Adamantiadis
b1a65dd25f Fix problem with ssh_connect w/ timeout &fd > 1024
Convert that code to ssh_poll
2011-01-03 22:51:23 +01:00
Andreas Schneider
e78cc89b52 cmake: Added ssl libraries for OS/2. 2010-12-31 14:56:29 +01:00
Andreas Schneider
f6586576fb cmake: Fixed a warning on OS/2 if the compiler version is empty.
(cherry picked from commit 98b5f07631)
2010-12-31 14:42:34 +01:00
Andreas Schneider
3797ca0ec6 libssh: Don't use the visibility flag on OS/2. 2010-12-31 14:36:27 +01:00
Andreas Schneider
bfe59d0cdd cmake: Fixed installation path for OS/2. 2010-12-31 14:10:59 +01:00
Andreas Schneider
4362d76416 build: Prepare libssh 0.4.7 release. 2010-12-27 20:08:58 +01:00
Andreas Schneider
da3b2d68a3 misc: Fixed a possible memory leak.
(cherry picked from commit a0e98f585a)
2010-12-27 18:10:09 +01:00
Andreas Schneider
4638b353d5 sftp: Fixed a memory leak in sftp_xstat.
Thanks to dsc for the bug report.
(cherry picked from commit 7c728acd12)
2010-12-27 17:53:23 +01:00
Vic Lee
a9f3a2f103 socket: Fixed uninitialized fd->revents member.
Signed-off-by: Vic Lee <llyzs@163.com>
2010-12-08 11:40:40 +01:00
Aris Adamantiadis
59f0293576 Fix from Oleksandr Shneyder
http://www.libssh.org/archive/libssh/2010-11/0000005.html
2010-12-07 16:10:34 +01:00
Andreas Schneider
7a314d9149 client: Fixed a typo. 2010-09-29 14:19:45 +02:00
Andreas Schneider
a13c9d4182 misc: Make sure ssh_analyze_banner has proper length checks.
(backported from commit 38359672a5)
2010-09-29 12:15:11 +02:00
Andreas Schneider
93f79c62ef misc: Fixed a possible data overread and crash bug.
(backported from commit 30e22fed6e)
2010-09-29 11:35:53 +02:00
Vic Lee
31fdb4ecf6 socket.c: Fixed setting max_fd which breaks ssh_select().
Signed-off-by: Andreas Schneider <asn@cynapses.org>
2010-09-20 19:24:36 +02:00
Andreas Schneider
0b564c358f include: Fixed some pedantic build warnings. 2010-09-10 21:47:47 +02:00
Andreas Schneider
fb24e68edd session: Fixed a memory leak with session->bindaddr.
(cherry picked from commit 325cc4e395)
2010-09-07 17:37:00 +02:00
Andreas Schneider
b5f095d0b4 misc: Fixed a memory leak.
(cherry picked from commit c1604eff08)
2010-09-07 17:33:29 +02:00
Andreas Schneider
62f7eaf156 misc: Updated the changelog. 2010-09-05 17:57:48 +02:00
Andreas Schneider
2462b0fbc7 build: Increase version number. 2010-09-05 17:54:03 +02:00
Andreas Schneider
c05666245c build: Fixed a wrong if statement.
(cherry picked from commit 461dde231c)
2010-09-05 13:13:01 +02:00
Andreas Schneider
6db13f776f 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 13:00:51 +02:00
Andreas Schneider
0980117c52 build: Fixed checking for printf function on Windows. 2010-09-02 11:50:59 +02:00
Andreas Schneider
3d66164545 poll: Fixed the Windows build on Vista and newer. 2010-09-01 23:31:06 +02:00
Aris Adamantiadis
c087e8704d Fixes bug #99
returns error when no cryptographic context is available
2010-08-28 23:38:53 +02:00
Andreas Schneider
e5801287da poll: Fixed the ssh_poll_(init/cleanup) functions. 2010-08-25 23:12:27 +02:00
Andreas Schneider
5b9d92c36f poll: Fixed the usage of WSAPoll() on Windows.
This should fix ticket #101.
2010-08-25 23:12:27 +02:00
Andreas Schneider
edc6b2cef2 poll: Added a cleanup function to free the ws2_32 library. 2010-08-25 23:12:26 +02:00
Aris Adamantiadis
9590a643ab Fixed "@deprecated" in doxygen 2010-08-20 12:59:42 +02:00
Aris Adamantiadis
bec9bc1222 Changed SSH_SUCCESS to SSH_OK 2010-08-20 12:58:48 +02:00
Aris Adamantiadis
b3067e362c Obsoletes ssh_auth_list, comment ssh_userauth_list
Conflicts:

	libssh/auth.c
2010-08-19 19:53:16 +02:00
Andreas Schneider
5f99fed07c build: Fixed some mingw warnings. 2010-07-24 21:36:00 +02:00
Andreas Schneider
9973de535e priv: Fixed a mingw build bug. 2010-07-24 10:10:33 +02:00
Aris Adamantiadis
a7d9f4addd Correctly handle failed opened channels 2010-07-19 22:50:15 +02:00
Aris Adamantiadis
a4f4fa3058 Fixed keepalive problem on older openssh servers 2010-07-16 23:04:54 +02:00
Aris Adamantiadis
a9c4877d84 New example for port forwarding 2010-07-16 22:45:12 +02:00
Andreas Schneider
284466632e build: InstallRequiredSystemLibraries isn't needed. 2010-07-16 08:58:32 +02:00
Andreas Schneider
aa8381999a build: Fixed the NSIS build. 2010-07-13 17:49:01 +02:00
Andreas Schneider
ac54a26c5d build: Fixed the Windows build.
We have to include stdio.h for the printf function before we can do
anything.
2010-07-13 17:27:52 +02:00
Andreas Schneider
fd53ebc7b6 build: Define values for printf functions. 2010-07-13 17:25:48 +02:00
Andreas Schneider
df2436b4a6 build: Don't test for big endian on Windows.
Visual Studio 2010 has problems running the test.
2010-07-13 16:08:43 +02:00
Andreas Schneider
7029d2f4b8 build: Fixed the Windows preprocessor macros and defines. 2010-07-13 15:10:19 +02:00
Andreas Schneider
3c9c358385 build: Set a default zlib search path for windows. 2010-07-13 14:03:54 +02:00
Andreas Schneider
82d1627cad build: Set a default openssl search path for windows. 2010-07-13 14:03:25 +02:00
Andreas Schneider
641e89b14a build: Fixed typo. 2010-07-13 13:25:20 +02:00
Andreas Schneider
3a61d55f27 build: Added a check for NSIS. 2010-07-13 13:19:06 +02:00
Andreas Schneider
c4d1d8b684 build: Increase version numbers. 2010-07-13 10:15:22 +02:00
Andreas Schneider
10e27f26be build: Updated ChangeLog. 2010-07-12 09:48:22 +02:00
Andreas Schneider
9791bc3eeb poll: Added poll constants for Windows.
WSAPoll uses different constanst values as the POSIX implementation,
what else ...
2010-07-09 09:46:57 +02:00
Andreas Schneider
4ad7828797 options: Added option to bind a client to an ip address.
Thanks to Donatello Boccaforno <donatello.boccaforno@gmail.com>.
2010-07-07 12:40:49 +02:00
Aris Adamantiadis
af8315b9ce Fixed ssh_socket_poll behaviour 2010-07-07 10:00:09 +02:00
Andreas Schneider
94fdcf7a2a socket: Fixed ssh_socket_poll().
If we don't have date to read or write, leave ssh_socket_poll().
2010-07-06 23:18:16 +02:00
Andreas Schneider
59a95fc3a7 poll: FD_SETSIZE is only for the count value of FD_SET on Windows. 2010-07-06 00:40:19 +02:00
Andreas Schneider
c1729c36d9 socket: Fixed a prototype. 2010-06-25 16:20:38 +02:00
Andreas Schneider
23efab0f8f socket: Fixed conflicting types. 2010-06-24 20:05:10 +02:00
Andreas Schneider
e50752a925 poll: Another attempt to get bsd_poll() working correctly. 2010-06-24 09:17:39 +02:00
Andreas Schneider
fd45c1b36b poll: Fixed building with poll-emulation on UNIX. 2010-06-24 09:16:58 +02:00
Andreas Schneider
5080671581 agent: Use the our poll typedef. 2010-06-24 09:14:07 +02:00
Andreas Schneider
e67fafd60f poll: Added a comment to the bsd_poll() implementation. 2010-06-22 14:45:08 +02:00
Andreas Schneider
a2a98fb5bc poll: Handle FD_SETSIZE in bsd_poll(). 2010-06-22 14:44:54 +02:00
Andreas Schneider
e2480fbaba poll: Fixed a comparsion. 2010-06-22 14:43:09 +02:00
Andreas Schneider
23e6b36209 poll: Fixed a typo. 2010-06-21 15:41:58 +02:00
Andreas Schneider
541b38b772 poll: Check if maxfd has been set. 2010-06-20 21:16:29 +02:00
Andreas Schneider
a85a4cc192 connect: Fixed some socket build warnings on windows. 2010-06-18 12:43:12 +02:00
Andreas Schneider
54ef77123a server: Fixed types and checks of fd's. 2010-06-17 13:36:14 +02:00
Andreas Schneider
4c679fd8a6 poll: Fixed type of the fd variables and use SSH_INVALID_SOCKET. 2010-06-17 13:35:40 +02:00
Andreas Schneider
21d918c68a client: Fixed fd type and checks. 2010-06-17 13:33:52 +02:00
Andreas Schneider
544fc28e6b channel: Fixed the type of the max fd variable in ssh_channel_select(). 2010-06-17 13:32:14 +02:00
Andreas Schneider
601081ebb6 agent: Use ssh_poll in agent code. 2010-06-17 13:31:35 +02:00
Andreas Schneider
22d975a24b socket: Fixed checks for max fd. 2010-06-17 13:18:23 +02:00
Andreas Schneider
aeb9f3e389 poll: Fixed brackets. 2010-06-17 12:02:06 +02:00
Andreas Schneider
d3a4e01137 poll: Fixed another wrong invalid fd check in bsd_poll. 2010-06-17 11:49:28 +02:00
Andreas Schneider
a1b9ae5048 poll: Some code cleanup for easier debugging. 2010-06-17 11:23:58 +02:00
Andreas Schneider
a375ebe29b poll: Fixed a malfunction with wrong max fd value check. 2010-06-17 11:23:50 +02:00
Andreas Schneider
b2f49a6a93 config: Use ssh log and error functions for problems. 2010-06-03 16:46:17 +02:00
Andreas Schneider
99fb5987ce socket: Fixed signed values which could be seen as an unary operator. 2010-06-02 10:14:53 +02:00
Andreas Schneider
be389dd644 socket: According to execle(2) environ shouldn't be const. 2010-06-01 21:47:15 +02:00
Andreas Schneider
a6a7922dbd Update Changelog. 2010-05-31 19:36:32 +02:00
Aris Adamantiadis
608e81bc00 Fix warning for snprintf 2010-05-31 11:52:36 +03:00
Aris Adamantiadis
7e17838c0b Fix unclean null termination in ~ expending 2010-05-31 11:50:52 +03:00
Andreas Schneider
84f6945a9c Increased version numbers. 2010-05-30 11:26:11 +02:00
Andreas Schneider
3ae187dbe7 misc: Make sure the expanded string is null-terminated. 2010-05-30 11:00:38 +02:00
Andreas Schneider
26989ab001 session: Fixed setting up default identity files. 2010-05-28 10:47:37 +02:00
Andreas Schneider
5b2e39cd79 options: Make sure that we have always have default options set. 2010-05-21 10:21:03 +02:00
Andreas Schneider
13af149ef9 options: Set the local username if still not set. 2010-05-21 10:19:06 +02:00
Andreas Schneider
3453cafd95 keyfiles: Fixed possible problem with known_hosts path. 2010-05-21 10:03:13 +02:00
Andreas Schneider
fa65fd3dd1 cmake: Fixed doxygen. 2010-05-18 00:32:43 +02:00
Andreas Schneider
ec5fa5cc06 doxygen: Fixed latex pdf generation. 2010-05-18 00:08:01 +02:00
Andreas Schneider
8577688174 Updated changelog file. 2010-05-17 23:41:15 +02:00
Andreas Schneider
31462a4d72 sftp: Fixed sftp_chown. 2010-05-17 23:38:21 +02:00
Aris Adamantiadis
fd2ff2d29c Fix sftp_rename on sftp3 2010-05-17 20:05:22 +02:00
Aris Adamantiadis
0b09bd900f Typos in last patch 2010-05-14 12:49:24 +02:00
Aris Adamantiadis
abc61fa1cc Fix build on VC7 2010-05-14 12:46:17 +02:00
Aris Adamantiadis
e94bff02ba Respond to keepalives/global requests 2010-05-12 21:58:09 +02:00
Andreas Schneider
3671c61023 build: Fixed build.
I've added a non-existent kex header, sorry.
2010-05-12 19:36:40 +02:00
Andreas Schneider
2702f3ea3f Fixed building libssh with DEBUG_CRYPTO. 2010-05-12 19:25:34 +02:00
Andreas Schneider
4abd0522b4 Increment version and soversion numbers. 2010-05-12 19:00:07 +02:00
Andreas Schneider
62b6eb4436 Updated ChangeLog entries for 0.4.3. 2010-05-12 18:59:29 +02:00
Andreas Schneider
4b7eba1eda Added runtime detection of WSAPoll().
Signed-off-by: Andreas Schneider <mail@cynapses.org>
2010-05-12 18:44:09 +02:00
Andreas Schneider
9970b1fd7d Added the possibility to define _OPENSSL_DIR and _ZLIB_DIR. 2010-05-12 13:57:54 +02:00
Andreas Schneider
d703f51861 Fixed windows include files in pcap support. 2010-05-12 13:39:00 +02:00
Andreas Schneider
a009702cd6 Fixed Windows build warnings. 2010-05-12 13:11:33 +02:00
Andreas Schneider
ed268e5948 Fixed Windows build. 2010-05-12 13:11:33 +02:00
Andreas Schneider
10b4654ad5 Added a select(2) based poll-emulation if poll(2) is not available. 2010-05-12 13:11:33 +02:00
Andreas Schneider
9d7fc9d50b Use the new expand functions.
This implements escape chars for IdentityFile in ssh_config and reads
the system ssh_config.
2010-05-11 09:52:06 +02:00
Andreas Schneider
b8bc3a6582 Added a function to expand an escaped string. 2010-05-11 09:44:29 +02:00
Andreas Schneider
07e8d8f1f2 Added a function to expand the tilde from a path. 2010-05-11 09:44:13 +02:00
Aris Adamantiadis
34a927716a Added code to test proxycommand 2010-05-10 22:40:28 +02:00
Aris Adamantiadis
bae4090715 Backport of the proxycommand feature 2010-05-10 22:32:52 +02:00
Andreas Schneider
403ded1e97 Use configure checks to define vsnprintf and strncpy. 2010-05-10 15:53:57 +02:00
Andreas Schneider
6fd8de3376 Added configure checks for _vsnprintf_s and strncpy. 2010-05-10 15:53:46 +02:00
Andreas Schneider
5fe99f8b09 Fixed building libssh with VC9. 2010-05-10 14:41:20 +02:00
Patrick Spendrin
af155db080 Move ssh_hostport to a location which is global accessible.
Signed-off-by: Andreas Schneider <mail@cynapses.org>
2010-05-10 10:48:13 +02:00
Patrick Spendrin
df5a94d445 The lower function doesn't have the prefix.
Signed-off-by: Andreas Schneider <mail@cynapses.org>
2010-05-10 10:48:03 +02:00
Andreas Schneider
4bfe7f024c Added more defines to use secure VC functions. 2010-05-10 10:45:51 +02:00
Aris Adamantiadis
99ea177eea oops, this file was not intended to be commited 2010-05-07 13:03:35 +02:00
Aris Adamantiadis
476630841f Match hashed [host]:port format knownhosts 2010-05-07 13:02:28 +02:00
Aris Adamantiadis
7f59662cad knownhosts writing cherry-pick
Conflicts:

	libssh/keyfiles.c
	tests/unittests/CMakeLists.txt
2010-05-07 12:58:56 +02:00
Aris Adamantiadis
e9d6b15926 First implementation of known_hosts with port read
Conflicts:

	include/libssh/misc.h
	libssh/keyfiles.c
	libssh/misc.c
2010-05-07 12:55:33 +02:00
Aris Adamantiadis
6885d32c05 Added ssh_privatekey_type public function 2010-04-28 11:51:02 +02:00
Aris Adamantiadis
e5c2af6316 Fix doublefree happening after a negociation error 2010-04-14 20:56:22 +02:00
Aris Adamantiadis
08a1bebb58 Do not compile aes*-ctr with <=OpenSSL 0.9.7b 2010-04-14 20:43:06 +02:00
Aris Adamantiadis
6195b133bf Fix missing string_data() in crypto debug code 2010-04-14 18:24:23 +02:00
Aris Adamantiadis
6e65abbe63 Fix vsnprintf symbol on older VS2003 compiler 2010-04-06 22:58:43 +02:00
Aris Adamantiadis
bda836d744 Fix building on win32/vs7 2010-04-06 22:23:43 +02:00
Andreas Schneider
c8c2647555 Fixed a typo. 2010-04-04 15:55:49 +02:00
Andreas Schneider
4ad74765f6 Removed the unneeded dependency to doxygen. 2010-04-04 15:00:59 +02:00
Andreas Schneider
b1f93f600e Fixed documentation of ssh_bind_options_set. 2010-04-04 14:07:54 +02:00
Andreas Schneider
28edbe1ef5 Added an improved version of UseDoxygen.cmake which handles trac doc. 2010-04-04 14:07:43 +02:00
Andreas Schneider
75cf66a3ee Added a doxygen configuration for trac. 2010-04-04 14:04:38 +02:00
Andreas Schneider
5021ed3074 Fixed config parsing wich has overwritten user specified values. 2010-04-04 14:02:09 +02:00
Andreas Schneider
3773366a25 Fixed blocking bug in channel_poll.
This is a backport from 514ab6eed2.
2010-04-03 23:29:01 +02:00
Aris Adamantiadis
c6fab4bf84 Fix openssl detection in cmake 2010-03-29 23:06:20 +02:00
Aris Adamantiadis
7d1dcb0dff Fix file inclusion with VS2003 2010-03-29 22:23:47 +02:00
Aris Adamantiadis
d7c1384df0 Fix exec example which has broken read usage 2010-03-28 21:49:17 +02:00
Aris Adamantiadis
d2bb97c1c6 Fixes the broken algorithm choice for server 2010-03-28 21:43:13 +02:00
Aris Adamantiadis
3b6098597d Fix crash when no callback is defined 2010-03-28 21:19:12 +02:00
Andreas Schneider
964d8fdc11 Fixed build warnings on Windows. 2010-03-25 16:47:45 +01:00
Andreas Schneider
5d339aa9e2 Fixed a build warning in ssh_userauth_autopubkey. 2010-03-25 15:32:28 +01:00
Andreas Schneider
af7f69c515 Fixed spelling. 2010-03-25 13:55:50 +01:00
Andreas Schneider
ea92d5b230 Added comments to the so version to increment it correctly in future. 2010-03-25 13:24:59 +01:00
Andreas Schneider
f096e031ed Fixed a typo that we don't export all symbols. 2010-03-25 09:52:05 +01:00
Andreas Schneider
a8be476ea9 Build examples only on the Linux plattform. 2010-03-17 10:09:38 +01:00
Andreas Schneider
b9f65b5740 Added changelog entries for version 0.4.2. 2010-03-15 19:33:49 +01:00
Andreas Schneider
99a58eb325 Increase version number to 0.4.2. 2010-03-15 19:33:11 +01:00
Andreas Schneider
ed1cba705c Fixed a memory leak in ssh_try_publickey_from_file. 2010-03-13 15:00:19 +01:00
Andreas Schneider
0b13a6d265 Added missing SSH_OPTIONS_FD option. 2010-03-13 14:21:57 +01:00
Andreas Schneider
74c0201219 Remove support for SSHv1 Cipher variable. 2010-03-13 13:09:23 +01:00
Andreas Schneider
83c51d1c13 Fixed and added support for several identity files. 2010-03-06 12:33:27 +01:00
Andreas Schneider
c712d30311 Rename ssh_list_add to ssh_list_append. 2010-03-06 12:29:03 +01:00
Andreas Schneider
2144049c7d Added a prepend function for ssh_list. 2010-03-06 12:29:03 +01:00
Aris Adamantiadis
9dd86859e8 renamed ssh_list_get_head to ssh_list_pop_head 2010-03-06 12:28:56 +01:00
Andreas Schneider
810fbfb620 Fixed sftp_parse_longname() on Windows.
There is no strndup function on Windows.
2010-03-02 14:16:21 +01:00
Aris Adamantiadis
370d072eba Fix a race condition bug in ssh_scp_close() 2010-03-01 20:00:29 +01:00
Aris Adamantiadis
56dfa69fc9 Send back replies to openssh's keepalives 2010-03-01 18:41:59 +01:00
Aris Adamantiadis
672f8412f0 Fixed documentation in scp code 2010-02-26 18:49:15 +01:00
Andreas Schneider
83ff1ffcc3 Added printout of owner and group in the sftp example. 2010-02-24 00:26:20 +01:00
Andreas Schneider
fb35153b49 Fixed longname parsing, this only workings with readdir. 2010-02-24 00:25:38 +01:00
Andreas Schneider
7539200773 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:52:56 +01:00
Andreas Schneider
254a166c02 Don't add the tests directory to the build. 2010-02-13 13:13:20 +01:00
Andreas Schneider
3e938cb901 Added ChangeLog entries for 0.4.1. 2010-02-13 13:00:10 +01:00
Andreas Schneider
452b16ede2 Set CFLAGS correctly. 2010-02-13 13:00:10 +01:00
Aris Adamantiadis
bd47ff75ba Fix compilation of opensolaris 2010-02-12 10:08:22 +01:00
Andreas Schneider
0016ded7f9 Try zlib compression and fallback to none if not available. 2010-02-11 23:28:37 +01:00
Aris Adamantiadis
d725b31752 Use closesocket in server.c for win32
Resolves #56
2010-02-11 19:54:57 +01:00
Aris Adamantiadis
c2e86c876c aes128-ctr aes192-ctr aes256-ctr for libgcrypt 2010-02-09 22:43:37 +01:00
Aris Adamantiadis
028516ba6a aes192-ctr and aes256-ctr working on libcrypto 2010-02-09 22:43:27 +01:00
Aris Adamantiadis
344b27ac6c Added aes128-ctr support for libcrypto (openssl) 2010-02-09 22:43:13 +01:00
Aris Adamantiadis
a700259b01 KEX bug: client preference should be prioritary 2010-02-09 22:42:53 +01:00
Andreas Schneider
14da14db05 Respect known_hosts file set by the user.
Thanks to contact@leblanc-simon.eu for the patch.
2010-02-07 22:39:35 +01:00
Vic Lee
474d63f24e 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:24:50 +01:00
Andreas Schneider
b3589fbf6c Increased version number. 2010-01-29 18:59:55 +01:00
Aris Adamantiadis
dd68bae776 Fix underflow when leave_function() are unbalanced 2010-01-29 18:54:48 +01:00
Vic Lee
4768cf3e85 In handle_channel_request_open(), variable type is freed too early and cause memory corruptions.
Signed-off-by: Vic Lee <llyzs@163.com>
Signed-off-by: Andreas Schneider <mail@cynapses.org>
2010-01-29 18:51:50 +01:00
Vic Lee
5a95681f01 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:59 +01:00
Andreas Schneider
13a3619102 Added an example for exec. 2009-12-22 18:33:16 +01:00
Vic Lee
c7636edf84 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 08:58:05 +01:00
Andreas Schneider
27e332b623 Fixed ssh_get_user_home_dir() to be thread safe. 2009-12-21 12:33:44 +01:00
Andreas Schneider
ebc8544c56 Improved doxygen output of ssh_options_set(). 2009-12-19 00:11:37 +01:00
Andreas Schneider
0f8e9b839c Disabled caller graphs as they are only of internal interest. 2009-12-18 23:55:17 +01:00
Andreas Schneider
0c02d6effe Updated the doxygen file. 2009-12-18 23:49:56 +01:00
Andreas Schneider
7199b196b0 Fixed documentation of buffer struct. 2009-12-18 23:45:34 +01:00
Andreas Schneider
ca83b66066 Fixed documentation of ssh_options_copy(). 2009-12-18 23:45:24 +01:00
Andreas Schneider
d978f9b58a Moved the doxygen mainpage to doc/mainpage.dox 2009-12-18 23:45:09 +01:00
Andreas Schneider
e539eaf9e0 Added a mainpage to doxygen. 2009-12-18 23:11:25 +01:00
Andreas Schneider
b728f44ce9 Fixed the doxygen documentation. 2009-12-18 23:05:03 +01:00
57 changed files with 4202 additions and 1090 deletions

View File

@@ -6,13 +6,20 @@ cmake_minimum_required(VERSION 2.6.0)
# global needed variables
set(APPLICATION_NAME ${PROJECT_NAME})
set(APPLICATION_VERSION "0.4.0")
set(APPLICATION_VERSION_MAJOR "0")
set(APPLICATION_VERSION_MINOR "4")
set(APPLICATION_VERSION_PATCH "0")
set(APPLICATION_VERSION_PATCH "8")
set(LIBRARY_VERSION "4.0.0")
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
# SOVERSION scheme: CURRENT.AGE.REVISION
# If there was an incompatible interface change:
# Increment CURRENT. Set AGE and REVISION to 0
# If there was a compatible interface change:
# 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_SOVERSION "4")
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
@@ -23,6 +30,7 @@ set(CMAKE_MODULE_PATH
# add definitions
include(DefineCMakeDefaults)
include(DefineCompilerFlags)
include(DefinePlatformDefaults)
include(DefineInstallationPaths)
include(DefineOptions.cmake)
include(CPackConfig.cmake)
@@ -45,12 +53,12 @@ if (WITH_GCRYPT)
endif (NOT GCRYPT_FOUND)
else (WITH_GCRYPT)
find_package(OpenSSL)
if (NOT CRYPTO_FOUND)
if (NOT OPENSSL_FOUND)
find_package(GCrypt)
if (NOT GCRYPT_FOUND)
message(FATAL_ERROR "Could not find OpenSSL or GCrypt")
endif (NOT GCRYPT_FOUND)
endif (NOT CRYPTO_FOUND)
endif (NOT OPENSSL_FOUND)
endif(WITH_GCRYPT)
# config.h checks
@@ -61,12 +69,11 @@ configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
add_subdirectory(doc)
add_subdirectory(include)
add_subdirectory(libssh)
add_subdirectory(tests)
# build samples
include_directories(${CMAKE_SOURCE_DIR}/include)
if (UNIX AND NOT WIN32)
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
add_subdirectory(examples)
endif (CMAKE_SYSTEM_NAME STREQUAL "Linux")
endif (UNIX AND NOT WIN32)

View File

@@ -13,7 +13,7 @@ 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 "0")
set(CPACK_PACKAGE_VERSION_PATCH "8")
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
@@ -22,16 +22,21 @@ set(CPACK_SOURCE_GENERATOR "TGZ")
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/build/;tags;cscope.*")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
if (WIN32)
set(CPACK_GENERATOR "ZIP")
### nsis generator
set(CPACK_GENERATOR "NSIS")
### nsis generator
find_package(NSIS)
if (HAVE_NSIS)
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 (WIN32)
set(CPACK_PACKAGE_INSTALL_DIRECTORY "libssh")
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")
set(CPACK_PACKAGE_FILE_NAME ${APPLICATION_NAME}-${CPACK_PACKAGE_VERSION})
set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries")

View File

@@ -1,6 +1,100 @@
ChangeLog
==========
version 0.4.8 (released 2011-01-15)
* Fixed memory leaks in session signing.
* Fixed memory leak in ssh_print_hexa.
* Fixed problem with ssh_connect w/ timeout and fd > 1024.
* Fixed some warnings on OS/2.
* Fixed installation path for OS/2.
version 0.4.7 (released 2010-12-28)
* Fixed a possible memory leak in ssh_get_user_home().
* Fixed a memory leak in sftp_xstat.
* Fixed uninitialized fd->revents member.
* Fixed timout value in ssh_channel_accept().
* Fixed length checks in ssh_analyze_banner().
* Fixed a possible data overread and crash bug.
* Fixed setting max_fd which breaks ssh_select().
* Fixed some pedantic build warnings.
* Fixed a memory leak with session->bindaddr.
version 0.4.6 (released 2010-09-03)
* Added a cleanup function to free the ws2_32 library.
* Fixed build with gcc 3.4.
* Fixed the Windows build on Vista and newer.
* Fixed the usage of WSAPoll() on Windows.
* Fixed "@deprecated" in doxygen
* Fixed some mingw warnings.
* Fixed handling of opened channels.
* Fixed keepalive problem on older openssh servers.
* Fixed testing for big endian on Windows.
* Fixed the Windows preprocessor macros and defines.
version 0.4.5 (released 2010-07-13)
* Added option to bind a client to an ip address.
* Fixed the ssh socket polling function.
* Fixed Windows related bugs in bsd_poll().
* Fixed serveral build warnings.
version 0.4.4 (released 2010-06-01)
* Fixed a bug in the expand function for escape sequences.
* Fixed a bug in the tilde expand function.
* Fixed a bug in setting the options.
version 0.4.3 (released 2010-05-18)
* Added global/keepalive responses.
* Added runtime detection of WSAPoll().
* Added a select(2) based poll-emulation if poll(2) is not available.
* Added a function to expand an escaped string.
* Added a function to expand the tilde from a path.
* Added a proxycommand support.
* Added ssh_privatekey_type public function
* Added the possibility to define _OPENSSL_DIR and _ZLIB_DIR.
* Fixed sftp_chown.
* Fixed sftp_rename on protocol version 3.
* Fixed a blocking bug in channel_poll.
* Fixed config parsing wich has overwritten user specified values.
* Fixed hashed [host]:port format in knownhosts
* Fixed Windows build.
* Fixed doublefree happening after a negociation error.
* Fixed aes*-ctr with <= OpenSSL 0.9.7b.
* Fixed some documentation.
* Fixed exec example which has broken read usage.
* Fixed broken algorithm choice for server.
* Fixed a typo that we don't export all symbols.
* Removed the unneeded dependency to doxygen.
* Build examples only on the Linux plattform.
version 0.4.2 (released 2010-03-15)
* Added owner and group information in sftp attributes.
* Added missing SSH_OPTIONS_FD option.
* Added printout of owner and group in the sftp example.
* Added a prepend function for ssh_list.
* Added send back replies to openssh's keepalives.
* Fixed documentation in scp code
* Fixed longname parsing, this only workings with readdir.
* Fixed and added support for several identity files.
* Fixed sftp_parse_longname() on Windows.
* Fixed a race condition bug in ssh_scp_close()
* Remove config support for SSHv1 Cipher variable.
* Rename ssh_list_add to ssh_list_append.
* Rename ssh_list_get_head to ssh_list_pop_head
version 0.4.1 (released 2010-02-13)
* Added support for aes128-ctr, aes192-ctr and aes256-ctr encryption.
* Added an example for exec.
* Added private key type detection feature in privatekey_from_file().
* Fixed zlib compression fallback.
* Fixed kex bug that client preference should be prioritary
* Fixed known_hosts file set by the user.
* Fixed a memleak in channel_accept().
* Fixed underflow when leave_function() are unbalanced
* Fixed memory corruption in handle_channel_request_open().
* Fixed closing of a file handle case of errors in privatekey_from_file().
* Fixed ssh_get_user_home_dir() to be thread safe.
* Fixed the doxygen documentation.
version 0.4.0 (released 2009-12-10)
* Added scp support.
* Added support for sending signals (RFC 4254, section 6.9).

View File

@@ -1,4 +1,5 @@
include(CheckIncludeFile)
include(CheckIncludeFiles)
include(CheckSymbolExists)
include(CheckFunctionExists)
include(CheckLibraryExists)
@@ -16,20 +17,39 @@ set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
set(BINARYDIR ${CMAKE_BINARY_DIR})
set(SOURCEDIR ${CMAKE_SOURCE_DIR})
if(CMAKE_COMPILER_IS_GNUC)
check_c_compiler_flag("-fvisibility=hidden" WITH_VISIBILITY_HIDDEN)
endif(CMAKE_COMPILER_IS_GNUC)
function(COMPILER_DUMPVERSION _OUTPUT_VERSION)
execute_process(
COMMAND
${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1} -dumpversion
OUTPUT_VARIABLE _COMPILER_VERSION
)
string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2"
_COMPILER_VERSION "${_COMPILER_VERSION}")
set(${_OUTPUT_VERSION} ${_COMPILER_VERSION} PARENT_SCOPE)
endfunction()
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 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)
if (WIN32)
check_include_file(wspiapi.h HAVE_WSPIAPI_H)
check_include_files("winsock2.h;ws2tcpip.h;wspiapi.h" HAVE_WSPIAPI_H)
if (NOT HAVE_WSPIAPI_H)
message(STATUS "WARNING: Without wspiapi.h, this build will only work on Windows XP and newer versions")
message(STATUS "WARNING: Without wspiapi.h (or dependencies), this build will only work on Windows XP and newer versions")
endif (NOT HAVE_WSPIAPI_H)
check_include_file(ws2tcpip.h HAVE_WS2TCPIP_H)
check_include_files("winsock2.h;ws2tcpip.h" HAVE_WS2TCPIP_H)
if (NOT HAVE_WS2TCPIP_H)
message(ERROR "WARNING: Does not have ws2tcpip.h or winsock2.h")
endif (NOT HAVE_WS2TCPIP_H)
if (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
set(HAVE_GETADDRINFO TRUE)
set(HAVE_GETHOSTBYNAME TRUE)
@@ -49,6 +69,17 @@ check_include_file(openssl/des.h HAVE_OPENSSL_DES_H)
# FUNCTIONS
check_function_exists(strncpy HAVE_STRNCPY)
check_function_exists(vsnprintf HAVE_VSNPRINTF)
check_function_exists(snprintf HAVE_SNPRINTF)
if (WIN32)
check_function_exists(_vsnprintf_s HAVE__VSNPRINTF_S)
check_function_exists(_vsnprintf HAVE__VSNPRINTF)
check_function_exists(_snprintf HAVE__SNPRINTF)
check_function_exists(_snprintf_s HAVE__SNPRINTF_S)
endif (WIN32)
if (UNIX)
# libsocket (Solaris)
check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET)
@@ -82,9 +113,9 @@ endif (UNIX)
set(LIBSSH_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CACHE INTERNAL "libssh required system libraries")
# LIBRARIES
if (CRYPTO_FOUND)
if (OPENSSL_FOUND)
set(HAVE_LIBCRYPTO 1)
endif (CRYPTO_FOUND)
endif (OPENSSL_FOUND)
if (GCRYPT_FOUND)
set(HAVE_LIBGCRYPT 1)
@@ -104,4 +135,6 @@ if (WITH_DEBUG_CALLTRACE)
endif (WITH_DEBUG_CALLTRACE)
# ENDIAN
test_big_endian(WORDS_BIGENDIAN)
if (NOT WIN32)
test_big_endian(WORDS_BIGENDIAN)
endif (NOT WIN32)

View File

@@ -3,27 +3,27 @@
include(CheckCCompilerFlag)
if (UNIX AND NOT WIN32)
if (CMAKE_COMPILER_IS_GNUCC)
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")
# with -fPIC
check_c_compiler_flag("-fPIC" WITH_FPIC)
if (WITH_FPIC)
add_definitions(-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)
add_definitions(-fstack-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)
add_definitions(-D_FORTIFY_SOURCE=2)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FORTIFY_SOURCE=2")
endif (WITH_FORTIFY_SOURCE)
endif (CMAKE_COMPILER_IS_GNUCC)
endif (${CMAKE_C_COMPILER_ID} MATCHES GNU)
if (CMAKE_SIZEOF_VOID_P MATCHES "8")
# with large file support
@@ -48,12 +48,12 @@ if (UNIX AND NOT WIN32)
endif (CMAKE_SIZEOF_VOID_P MATCHES "8")
if (_lfs_CFLAGS)
string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}")
add_definitions(${_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)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS")
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,25 @@
# 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)
endif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
if (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
set(OPENBSD TRUE)
endif (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
if (CMAKE_SYSTEM_NAME MATCHES "NetBSD")
set(NETBSD 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,31 @@
# - Try to find NSIS
# Once done this will define
#
# NSIS_FOUND - system has NSIS
# NSIS_MAKE - NSIS creator executable
#
# Copyright (c) 2010 Andreas Schneider <mail@cynapses.org>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
if (NSIS_MAKE)
# in cache already
set(NSIS_FOUND TRUE)
elseif (NSIS_MAKE)
find_program(NSIS_MAKE
NAMES
makensis
PATHS
${_NSIS_DIR}
${_NSIS_DIR}/Bin
$ENV{PROGRAMFILES}/NSIS
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NSIS DEFAULT_MSG NSIS_MAKE)
mark_as_advanced(NSIS_MAKE)
endif (NSIS_MAKE)

View File

@@ -18,6 +18,10 @@ if (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
# in cache already
set(OPENSSL_FOUND TRUE)
else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
if (WIN32)
set(_OPENSSL_DIR $ENV{PROGRAMFILES}/OpenSSL)
endif (WIN32)
# use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
if (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
@@ -34,6 +38,7 @@ else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
NAMES
openssl/ssl.h
PATHS
${_OPENSSL_DIR}/include
${_OPENSSL_INCLUDEDIR}
/usr/include
/usr/local/include
@@ -47,8 +52,10 @@ else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
find_library(SSL_LIBRARY
NAMES
ssl
ssl_dl
libssl
PATHS
${_OPENSSL_DIR}/lib
${_OPENSSL_LIBDIR}
/usr/lib
/usr/local/lib
@@ -64,6 +71,7 @@ else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
NAMES
ssleay32
PATHS
${_OPENSSL_DIR}/lib
${_OPENSSL_LIBDIR}
/usr/lib
/usr/local/lib
@@ -79,6 +87,7 @@ else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
NAMES
ssleay32MD
PATHS
${_OPENSSL_DIR}/lib
${_OPENSSL_LIBDIR}
/usr/lib
/usr/local/lib
@@ -93,12 +102,14 @@ else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
find_library(CRYPTO_LIBRARY
NAMES
crypto
crypto_dl
libcrypto
eay
eay32
libeay
libeay32
PATHS
${_OPENSSL_DIR}/lib
${_OPENSSL_LIBDIR}
/lib
/usr/lib

View File

@@ -18,11 +18,15 @@ 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
@@ -36,6 +40,7 @@ else (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
zlib
zlib1
PATHS
${_ZLIB_DIR}/lib
/usr/lib
/usr/local/lib
/opt/local/lib

View File

@@ -1,127 +1,100 @@
# -helper macro to add a "doc" target with CMake build system.
# and configure doxy.config.in to doxy.config
# - Run Doxygen
#
# target "doc" allows building the documentation with doxygen/dot on WIN32 and Linux
# Creates .chm windows help file if MS HTML help workshop
# (available from http://msdn.microsoft.com/workshop/author/htmlhelp)
# is installed with its DLLs in PATH.
# Adds a doxygen target that runs doxygen to generate the html
# and optionally the LaTeX API documentation.
# The doxygen target is added to the doc target as dependency.
# i.e.: the API documentation is built with:
# make doc
#
# USAGE: INCLUDE IN PROJECT
#
# set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
# include(UseDoxygen)
# Add the Doxyfile.in and UseDoxygen.cmake files to the projects source directory.
#
#
# Please note, that the tools, e.g.:
# doxygen, dot, latex, dvips, makeindex, gswin32, etc.
# must be in path.
# Variables you may define are:
# DOXYFILE_OUTPUT_DIR - Path where the Doxygen output is stored. Defaults to "doc".
#
# Note about Visual Studio Projects:
# MSVS has its own path environment which may differ from the shell.
# See "Menu Tools/Options/Projects/VC++ Directories" in VS 7.1
# DOXYFILE_LATEX_DIR - Directory where the Doxygen LaTeX output is stored. Defaults to "latex".
#
# DOXYFILE_HTML_DIR - Directory where the Doxygen html output is stored. Defaults to "html".
#
# author Jan Woetzel 2004-2006
# www.mip.informatik.uni-kiel.de/~jw
#
# Copyright (c) 2009-2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
# Copyright (c) 2010 Andreas Schneider <mail@cynapses.org>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
FIND_PACKAGE(Doxygen)
macro(usedoxygen_set_default name value)
if(NOT DEFINED "${name}")
set("${name}" "${value}")
endif()
endmacro()
IF (DOXYGEN_FOUND)
find_package(Doxygen)
# click+jump in Emacs and Visual Studio (for doxy.config) (jw)
IF (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)")
SET(DOXY_WARN_FORMAT "\"$file($line) : $text \"")
ELSE (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)")
SET(DOXY_WARN_FORMAT "\"$file:$line: $text \"")
ENDIF (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)")
if(DOXYGEN_FOUND)
find_file(DOXYFILE_IN
NAMES
doxy.config.in
PATHS
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_ROOT}/Modules/
NO_DEFAULT_PATH)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(DOXYFILE_IN DEFAULT_MSG "DOXYFILE_IN")
endif()
# we need latex for doxygen because of the formulas
FIND_PACKAGE(LATEX)
IF (NOT LATEX_COMPILER)
MESSAGE(STATUS "latex command LATEX_COMPILER not found but usually required. You will probably get warnings and user inetraction on doxy run.")
ENDIF (NOT LATEX_COMPILER)
IF (NOT MAKEINDEX_COMPILER)
MESSAGE(STATUS "makeindex command MAKEINDEX_COMPILER not found but usually required.")
ENDIF (NOT MAKEINDEX_COMPILER)
IF (NOT DVIPS_CONVERTER)
MESSAGE(STATUS "dvips command DVIPS_CONVERTER not found but usually required.")
ENDIF (NOT DVIPS_CONVERTER)
FIND_PROGRAM(DOXYGEN_DOT_EXECUTABLE_PATH NAMES dot)
IF (DOXYGEN_DOT_EXECUTABLE_PATH)
SET(DOXYGEN_DOT_FOUND "YES")
ENDIF (DOXYGEN_DOT_EXECUTABLE_PATH)
if(DOXYGEN_FOUND AND DOXYFILE_IN_FOUND)
add_custom_target(doxygen ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.config)
IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in")
MESSAGE(STATUS "Generate ${CMAKE_CURRENT_BINARY_DIR}/doxy.config from doxy.config.in")
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in
${CMAKE_CURRENT_BINARY_DIR}/doxy.config
@ONLY )
# use (configured) doxy.config from (out of place) BUILD tree:
SET(DOXY_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/doxy.config")
ELSE (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in")
# use static hand-edited doxy.config from SOURCE tree:
SET(DOXY_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
MESSAGE(STATUS "WARNING: using existing ${CMAKE_CURRENT_SOURCE_DIR}/doxy.config instead of configuring from doxy.config.in file.")
ELSE (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
IF (EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in")
# using template doxy.config.in
MESSAGE(STATUS "Generate ${CMAKE_CURRENT_BINARY_DIR}/doxy.config from doxy.config.in")
CONFIGURE_FILE(${CMAKE_MODULE_PATH}/doxy.config.in
${CMAKE_CURRENT_BINARY_DIR}/doxy.config
@ONLY )
SET(DOXY_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/doxy.config")
ELSE (EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in")
# failed completely...
MESSAGE(SEND_ERROR "Please create ${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in (or doxy.config as fallback)")
ENDIF(EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in")
usedoxygen_set_default(DOXYFILE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
usedoxygen_set_default(DOXYFILE_HTML_DIR "html")
ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in")
set_property(DIRECTORY APPEND PROPERTY
ADDITIONAL_MAKE_CLEAN_FILES "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_HTML_DIR}")
ADD_CUSTOM_TARGET(doc ${DOXYGEN_EXECUTABLE} ${DOXY_CONFIG} DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/doxy.config)
set(DOXYFILE_LATEX FALSE)
set(DOXYFILE_PDFLATEX FALSE)
set(DOXYFILE_DOT FALSE)
# create a windows help .chm file using hhc.exe
# HTMLHelp DLL must be in path!
# fallback: use hhw.exe interactively
IF (WIN32)
FIND_PACKAGE(HTMLHelp)
IF (HTML_HELP_COMPILER)
SET (TMP "${CMAKE_CURRENT_BINARY_DIR}\\doc\\html\\index.hhp")
STRING(REGEX REPLACE "[/]" "\\\\" HHP_FILE ${TMP} )
# MESSAGE(SEND_ERROR "DBG HHP_FILE=${HHP_FILE}")
ADD_CUSTOM_TARGET(winhelp ${HTML_HELP_COMPILER} ${HHP_FILE})
ADD_DEPENDENCIES (winhelp doc)
IF (NOT TARGET_DOC_SKIP_INSTALL)
# install windows help?
# determine useful name for output file
# should be project and version unique to allow installing
# multiple projects into one global directory
IF (EXISTS "${PROJECT_BINARY_DIR}/doc/html/index.chm")
IF (PROJECT_NAME)
SET(OUT "${PROJECT_NAME}")
ELSE (PROJECT_NAME)
SET(OUT "Documentation") # default
ENDIF(PROJECT_NAME)
IF (${PROJECT_NAME}_VERSION_MAJOR)
SET(OUT "${OUT}-${${PROJECT_NAME}_VERSION_MAJOR}")
IF (${PROJECT_NAME}_VERSION_MINOR)
SET(OUT "${OUT}.${${PROJECT_NAME}_VERSION_MINOR}")
IF (${PROJECT_NAME}_VERSION_PATCH)
SET(OUT "${OUT}.${${PROJECT_NAME}_VERSION_PATCH}")
ENDIF(${PROJECT_NAME}_VERSION_PATCH)
ENDIF(${PROJECT_NAME}_VERSION_MINOR)
ENDIF(${PROJECT_NAME}_VERSION_MAJOR)
# keep suffix
SET(OUT "${OUT}.chm")
#MESSAGE("DBG ${PROJECT_BINARY_DIR}/doc/html/index.chm \n${OUT}")
# create target used by install and package commands
INSTALL(FILES "${PROJECT_BINARY_DIR}/doc/html/index.chm"
DESTINATION "doc"
RENAME "${OUT}"
)
ENDIF(EXISTS "${PROJECT_BINARY_DIR}/doc/html/index.chm")
ENDIF(NOT TARGET_DOC_SKIP_INSTALL)
find_package(LATEX)
if(LATEX_COMPILER AND MAKEINDEX_COMPILER)
set(DOXYFILE_LATEX TRUE)
usedoxygen_set_default(DOXYFILE_LATEX_DIR "latex")
ENDIF(HTML_HELP_COMPILER)
# MESSAGE(SEND_ERROR "HTML_HELP_COMPILER=${HTML_HELP_COMPILER}")
ENDIF (WIN32)
ENDIF(DOXYGEN_FOUND)
set_property(DIRECTORY APPEND PROPERTY
ADDITIONAL_MAKE_CLEAN_FILES
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
if(PDFLATEX_COMPILER)
set(DOXYFILE_PDFLATEX TRUE)
endif()
if(DOXYGEN_DOT_EXECUTABLE)
set(DOXYFILE_DOT TRUE)
endif()
add_custom_command(TARGET doxygen
POST_BUILD
COMMAND ${CMAKE_MAKE_PROGRAM}
WORKING_DIRECTORY "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
endif()
configure_file(${DOXYFILE_IN} ${CMAKE_CURRENT_BINARY_DIR}/doxy.config ESCAPE_QUOTES IMMEDIATE @ONLY)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doxy.trac.in)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doxy.trac.in ${CMAKE_CURRENT_BINARY_DIR}/doxy.trac ESCAPE_QUOTES IMMEDIATE @ONLY)
add_custom_target(doxygen-trac ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.trac)
endif()
get_target_property(DOC_TARGET doc TYPE)
if(NOT DOC_TARGET)
add_custom_target(doc)
endif()
add_dependencies(doc doxygen)
endif()

View File

@@ -37,6 +37,37 @@
/*************************** FUNCTIONS ***************************/
/* 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 `vsnprintf' function. */
#cmakedefine HAVE_VSNPRINTF 1
/* Define to 1 if you have the `_vsnprintf' function. */
#cmakedefine HAVE__VSNPRINTF 1
/* 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
/* Define to 1 if you have the `cfmakeraw' function. */
#cmakedefine HAVE_CFMAKERAW 1
@@ -94,17 +125,3 @@
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#cmakedefine WORDS_BIGENDIAN 1
/************************* MS Windows ***************************/
#ifdef _WIN32
# ifdef _MSC_VER
/* On Microsoft compilers define inline to __inline on all others use inline */
# undef inline
# define inline __inline
# undef strdup
# define strdup _strdup
# endif // _MSC_VER
#endif /* _WIN32 */

1
doc/TracFooter.html Normal file
View File

@@ -0,0 +1 @@
<!-- Doxygen TracFooter -->

4
doc/TracHeader.html Normal file
View File

@@ -0,0 +1,4 @@
<!-- Doxygen TracHeader -->
<style>@import url(/chrome/site/doxygen.css);</style>
<style>@import url(/chrome/site/tabs.css);</style>
<!-- /Doxygen TracHeader -->

View File

@@ -1,4 +1,4 @@
# Doxyfile 1.5.8
# Doxyfile 1.5.6
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project
@@ -57,8 +57,8 @@ CREATE_SUBDIRS = NO
# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
# Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene,
# Spanish, Swedish, and Ukrainian.
# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish,
# and Ukrainian.
OUTPUT_LANGUAGE = English
@@ -165,6 +165,13 @@ QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
# If the DETAILS_AT_TOP tag is set to YES then Doxygen
# will output the detailed description near the top, like JavaDoc.
# If set to NO, the detailed description appears after the member
# documentation.
DETAILS_AT_TOP = YES
# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
# member inherits the documentation from any documented member that it
# re-implements.
@@ -217,17 +224,6 @@ OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
# Doxygen selects the parser to use depending on the extension of the files it parses.
# With this tag you can assign which parser to use for a given extension.
# Doxygen has a built-in mapping, but you can override or extend it using this tag.
# The format is ext=language, where ext is a file extension, and language is one of
# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP,
# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat
# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran),
# use: inc=Fortran f=C
EXTENSION_MAPPING =
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
# to include (a tag file for) the STL sources as input, then you should
# set this tag to YES in order to let doxygen match functions declarations and
@@ -237,7 +233,7 @@ EXTENSION_MAPPING =
BUILTIN_STL_SUPPORT = NO
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
CPP_CLI_SUPPORT = NO
@@ -280,23 +276,7 @@ SUBGROUPING = YES
# be useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.
TYPEDEF_HIDES_STRUCT = NO
# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
# determine which symbols to keep in memory and which to flush to disk.
# When the cache is full, less often used symbols will be written to disk.
# For small to medium size projects (<1000 input files) the default value is
# probably good enough. For larger projects a too small cache size can cause
# doxygen to be busy swapping symbols to and from disk most of the time
# causing a significant performance penality.
# If the system has enough physical memory increasing the cache will improve the
# performance by keeping more symbols in memory. Note that the value works on
# a logarithmic scale so increasing the size by one will rougly double the
# memory usage. The cache size is given by this formula:
# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
# corresponding to a cache size of 2^16 = 65536 symbols
SYMBOL_CACHE_SIZE = 0
TYPEDEF_HIDES_STRUCT = YES
#---------------------------------------------------------------------------
# Build related configuration options
@@ -425,7 +405,7 @@ SORT_GROUP_NAMES = NO
# sorted by fully-qualified names, including namespaces. If set to
# NO (the default), the class list will be sorted only by class name,
# not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
# Note: This option applies only to the class list, not to the
# alphabetical list.
@@ -482,15 +462,14 @@ SHOW_USED_FILES = YES
SHOW_DIRECTORIES = NO
# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
# This will remove the Files entry from the Quick Index and from the
# Folder Tree View (if specified). The default is YES.
SHOW_FILES = YES
# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
# Namespaces page.
# This will remove the Namespaces entry from the Quick Index
# Namespaces page. This will remove the Namespaces entry from the Quick Index
# and from the Folder Tree View (if specified). The default is YES.
SHOW_NAMESPACES = YES
@@ -505,15 +484,6 @@ SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by
# doxygen. The layout file controls the global structure of the generated output files
# in an output format independent way. The create the layout file that represents
# doxygen's defaults, run doxygen with the -l option. You can optionally specify a
# file name after the option, if omitted DoxygenLayout.xml will be used as the name
# of the layout file.
LAYOUT_FILE =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
@@ -575,7 +545,8 @@ WARN_LOGFILE = @CMAKE_CURRENT_BINARY_DIR@/doxy.log
# with spaces.
INPUT = @CMAKE_SOURCE_DIR@/include \
@CMAKE_SOURCE_DIR@/libssh
@CMAKE_SOURCE_DIR@/libssh \
@CMAKE_SOURCE_DIR@/doc
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
@@ -642,18 +613,15 @@ EXCLUDE_SYMBOLS =
# directories that contain example code fragments that are included (see
# the \include command).
EXAMPLE_PATH = @CMAKE_SOURCE_DIR@/tests \
@CMAKE_SOURCE_DIR@
EXAMPLE_PATH = @CMAKE_SOURCE_DIR@/examples
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank all files are included.
EXAMPLE_PATTERNS = *.cpp \
*.cc \
EXAMPLE_PATTERNS = *.c \
*.h \
*.hh \
INSTALL \
DEPENDENCIES \
CHANGELOG \
@@ -678,17 +646,14 @@ IMAGE_PATH =
# by executing (via popen()) the command <filter> <input-file>, where <filter>
# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
# input file. Doxygen will then use the output that the filter program writes
# to standard output.
# If FILTER_PATTERNS is specified, this tag will be
# to standard output. If FILTER_PATTERNS is specified, this tag will be
# ignored.
INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis.
# Doxygen will compare the file name with each pattern and apply the
# filter if there is a match.
# The filters are a list of the form:
# basis. Doxygen will compare the file name with each pattern and apply the
# filter if there is a match. The filters are a list of the form:
# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
# is applied to all files.
@@ -735,11 +700,10 @@ REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
# link to the source code.
# Otherwise they will link to the documentation.
# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
# link to the source code. Otherwise they will link to the documentstion.
REFERENCES_LINK_SOURCE = YES
@@ -828,13 +792,12 @@ HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded. For this to work a browser that supports
# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the
# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
# of the generated HTML documentation.
HTML_DYNAMIC_SECTIONS = NO
GENERATE_HTMLHELP = NO
# If the GENERATE_DOCSET tag is set to YES, additional index files
# will be generated that can be used as input for Apple's Xcode 3
@@ -843,8 +806,7 @@ HTML_DYNAMIC_SECTIONS = NO
# HTML output directory. Running make will produce the docset in that
# directory and running "make install" will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
# it at startup.
# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
# it at startup.
GENERATE_DOCSET = NO
@@ -862,12 +824,13 @@ DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the
# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
# of the generated HTML documentation.
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded. For this to work a browser that supports
# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
GENERATE_HTMLHELP = NO
HTML_DYNAMIC_SECTIONS = NO
# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
# be used to specify the file name of the resulting .chm file. You
@@ -889,8 +852,8 @@ HHC_LOCATION =
GENERATE_CHI = NO
# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
# is used to encode HtmlHelp index (hhk), content (hhc) and project file
# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
# is used to encode HtmlHelp index (hhk), content (hhc) and project file
# content.
CHM_INDEX_ENCODING =
@@ -906,55 +869,6 @@ BINARY_TOC = NO
TOC_EXPAND = NO
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER
# are set, an additional index file will be generated that can be used as input for
# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated
# HTML documentation.
GENERATE_QHP = NO
# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
# be used to specify the file name of the resulting .qch file.
# The path specified is relative to the HTML output folder.
QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating
# Qt Help Project output. For more information please see
# http://doc.trolltech.com/qthelpproject.html#namespace
QHP_NAMESPACE =
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
# Qt Help Project output. For more information please see
# http://doc.trolltech.com/qthelpproject.html#virtual-folders
QHP_VIRTUAL_FOLDER = doc
# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add.
# For more information please see
# http://doc.trolltech.com/qthelpproject.html#custom-filters
QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see
# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's
# filter section matches.
# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
QHP_SECT_FILTER_ATTRS =
# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
# be used to specify the location of Qt's qhelpgenerator.
# If non-empty doxygen will try to run qhelpgenerator on the generated
# .qhp file.
QHG_LOCATION =
# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
# top of each HTML page. The value NO (the default) enables the index and
# the value YES disables it.
@@ -966,19 +880,19 @@ DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information.
# If the tag value is set to FRAME, a side panel will be generated
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information.
# If the tag value is set to FRAME, a side panel will be generated
# containing a tree-like index structure (just like the one that
# is generated for HTML Help). For this to work a browser that supports
# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
# probably better off using the HTML help feature. Other possible values
# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
# and Class Hierarchy pages using a tree view instead of an ordered list;
# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
# disables this behavior completely. For backwards compatibility with previous
# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
# and Class Hiererachy pages using a tree view instead of an ordered list;
# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
# disables this behavior completely. For backwards compatibility with previous
# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
# respectively.
GENERATE_TREEVIEW = NO
@@ -1004,7 +918,7 @@ FORMULA_FONTSIZE = 10
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.
GENERATE_LATEX = NO
GENERATE_LATEX = @DOXYFILE_LATEX@
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
@@ -1209,10 +1123,8 @@ GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
# nicely formatted so it can be parsed by a human reader.
# This is useful
# if you want to understand what is going on.
# On the other hand, if this
# nicely formatted so it can be parsed by a human reader. This is useful
# if you want to understand what is going on. On the other hand, if this
# tag is set to NO the size of the Perl module output will be much smaller
# and Perl will parse it just the same.
@@ -1299,16 +1211,14 @@ SKIP_FUNCTION_MACROS = YES
# Optionally an initial location of the external documentation
# can be added for each tagfile. The format of a tag file without
# this location is as follows:
#
# TAGFILES = file1 file2 ...
# TAGFILES = file1 file2 ...
# Adding location for the tag files is done as follows:
#
# TAGFILES = file1=loc1 "file2 = loc2" ...
# TAGFILES = file1=loc1 "file2 = loc2" ...
# where "loc1" and "loc2" can be relative or absolute paths or
# URLs. If a location is present for each tag, the installdox tool
# does not have to be run to correct the links.
# Note that each tag file must have a unique name
# (where the name does NOT include the path)
# does not have to be run to correct the links.
# Note that each tag file must have a unique name
# (where the name does NOT include the path)
# If a tag file is not located in the directory in which doxygen
# is run, you must also specify the path to the tagfile here.
@@ -1382,11 +1292,6 @@ HAVE_DOT = @DOXYGEN_DOT_FOUND@
DOT_FONTNAME = FreeSans
# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
# The default size is 10pt.
DOT_FONTSIZE = 10
# By default doxygen will tell dot to use the output directory to look for the
# FreeSans.ttf font (which doxygen will put there itself). If you specify a
# different font using DOT_FONTNAME you can set the path where dot
@@ -1429,7 +1334,7 @@ TEMPLATE_RELATIONS = YES
# file showing the direct and indirect include dependencies of the file with
# other documented files.
INCLUDE_GRAPH = YES
INCLUDE_GRAPH = NO
# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
@@ -1444,7 +1349,7 @@ INCLUDED_BY_GRAPH = YES
# the time of a run. So in most cases it will be better to enable call graphs
# for selected functions only using the \callgraph command.
CALL_GRAPH = YES
CALL_GRAPH = NO
# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
# doxygen will generate a caller dependency graph for every global function
@@ -1452,7 +1357,7 @@ CALL_GRAPH = YES
# the time of a run. So in most cases it will be better to enable caller
# graphs for selected functions only using the \callergraph command.
CALLER_GRAPH = YES
CALLER_GRAPH = NO
# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
# will graphical hierarchy of all classes instead of a textual one.
@@ -1461,13 +1366,13 @@ GRAPHICAL_HIERARCHY = YES
# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
# then doxygen will show the dependencies a directory has on other directories
# in a graphical way. The dependency relations are determined by the #include
# in a graphical way. The dependency relations are determined by the #include
# relations between the files in the directories.
DIRECTORY_GRAPH = YES
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. Possible values are png, jpg, or gif
# generated by dot. Possible values are png, jpg, or gif
# If left blank png will be used.
DOT_IMAGE_FORMAT = png
@@ -1504,10 +1409,10 @@ DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
# background. This is disabled by default, because dot on Windows does not
# seem to support this out of the box. Warning: Depending on the platform used,
# enabling this option may lead to badly anti-aliased labels on the edges of
# a graph (i.e. they become hard to read).
# background. This is enabled by default, which results in a transparent
# background. Warning: Depending on the platform used, enabling this option
# may lead to badly anti-aliased labels on the edges of a graph (i.e. they
# become hard to read).
DOT_TRANSPARENT = NO
@@ -1531,7 +1436,7 @@ GENERATE_LEGEND = YES
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Options related to the search engine
# Configuration::additions related to the search engine
#---------------------------------------------------------------------------
# The SEARCHENGINE tag specifies whether or not a search engine should be

1546
doc/doxy.trac.in Normal file

File diff suppressed because it is too large Load Diff

12
doc/mainpage.dox Normal file
View File

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

View File

@@ -14,10 +14,15 @@ include_directories(
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}

57
examples/exec.c Normal file
View File

@@ -0,0 +1,57 @@
/* simple exec example */
#include <stdio.h>
#include <libssh/libssh.h>
#include "examples_common.h"
int main(void) {
ssh_session session;
ssh_channel channel;
char buf[4096];
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);
}
}
} while(rc > 0);
channel_send_eof(channel);
channel_close(channel);
ssh_disconnect(session);
ssh_finalize();
return 0;
}

View File

@@ -46,6 +46,8 @@ struct termios terminal;
char *pcap_file=NULL;
#endif
char *proxycommand;
static int auth_callback(const char *prompt, char *buf, size_t len,
int echo, int verify, void *userdata) {
char *answer = NULL;
@@ -95,6 +97,9 @@ static void usage(){
" -r : use RSA to verify host public key\n"
#ifdef WITH_PCAP
" -P file : create a pcap debugging file\n"
#endif
#ifndef _WIN32
" -T proxycommand : command to execute as a socket proxy\n"
#endif
,
ssh_version(0));
@@ -106,12 +111,17 @@ static int opts(int argc, char **argv){
// for(i=0;i<argc;i++)
// printf("%d : %s\n",i,argv[i]);
/* insert your own arguments here */
while((i=getopt(argc,argv,"P:"))!=-1){
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:
fprintf(stderr,"unknown option %c\n",optopt);
@@ -432,7 +442,10 @@ static int client(ssh_session session){
return -1;
if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0)
return -1;
if (proxycommand != NULL){
if(ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, proxycommand))
return -1;
}
ssh_options_parse_config(session, NULL);
if(ssh_connect(session)){

View File

@@ -152,10 +152,12 @@ static void do_sftp(ssh_session session){
}
/* reading the whole directory, file by file */
while((file=sftp_readdir(sftp,dir))){
fprintf(stderr, "%30s(%.8o) : %.5d.%.5d : %.10llu bytes\n",
fprintf(stderr, "%30s(%.8o) : %s(%.5d) %s(%.5d) : %.10llu bytes\n",
file->name,
file->permissions,
file->owner,
file->uid,
file->group,
file->gid,
(long long unsigned int) file->size);
sftp_attributes_free(file);

247
examples/sshnetcat.c Normal file
View File

@@ -0,0 +1,247 @@
/*
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.
The goal is to show the API in action. It's not a reference on how terminal
clients must be made or how a client should react.
*/
#include "config.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <libssh/callbacks.h>
#include <libssh/libssh.h>
#include <libssh/sftp.h>
#include <fcntl.h>
#include "examples_common.h"
char *host;
const char *desthost="localhost";
const char *port="22";
#ifdef WITH_PCAP
#include <libssh/pcap.h>
char *pcap_file=NULL;
#endif
static void usage(){
fprintf(stderr,"Usage : sshnetcat [user@]host forwarded_host forwarded_port\n");
exit(1);
}
static int opts(int argc, char **argv){
int i;
while((i=getopt(argc,argv,"P:"))!=-1){
switch(i){
#ifdef WITH_PCAP
case 'P':
pcap_file=optarg;
break;
#endif
default:
fprintf(stderr,"unknown option %c\n",optopt);
usage();
}
}
if(optind < argc)
host=argv[optind++];
if(optind < argc)
desthost=argv[optind++];
if(optind < argc)
port=argv[optind++];
if(host==NULL)
usage();
return 0;
}
static void select_loop(ssh_session session,ssh_channel channel){
fd_set fds;
struct timeval timeout;
char buffer[4096];
/* channels will be set to the channels to poll.
* outchannels will contain the result of the poll
*/
ssh_channel channels[2], outchannels[2];
int lus;
int eof=0;
int maxfd;
int ret;
while(channel){
do{
FD_ZERO(&fds);
if(!eof)
FD_SET(0,&fds);
timeout.tv_sec=30;
timeout.tv_usec=0;
FD_SET(ssh_get_fd(session),&fds);
maxfd=ssh_get_fd(session)+1;
channels[0]=channel; // set the first channel we want to read from
channels[1]=NULL;
ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout);
if(ret==EINTR)
continue;
if(FD_ISSET(0,&fds)){
lus=read(0,buffer,sizeof(buffer));
if(lus)
channel_write(channel,buffer,lus);
else {
eof=1;
channel_send_eof(channel);
}
}
if(channel && channel_is_closed(channel)){
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
channel_free(channel);
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);
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);
channel=channels[0]=NULL;
} else
write(1,buffer,lus);
}
while(channel && channel_is_open(channel) && channel_poll(channel,1)){ /* stderr */
lus=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);
channel=channels[0]=NULL;
} else
write(2,buffer,lus);
}
}
if(channel && channel_is_closed(channel)){
channel_free(channel);
channel=NULL;
}
} while (ret==EINTR || ret==SSH_EINTR);
}
}
static void forwarding(ssh_session session){
ssh_channel channel;
int r;
channel=channel_new(session);
r=channel_open_forward(channel,desthost,atoi(port),"localhost",22);
if(r<0) {
printf("error forwarding port : %s\n",ssh_get_error(session));
return;
}
select_loop(session,channel);
}
static int client(ssh_session session){
int auth=0;
char *banner;
int state;
if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0)
return -1;
ssh_options_parse_config(session, NULL);
if(ssh_connect(session)){
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
return -1;
}
state=verify_knownhost(session);
if (state != 0)
return -1;
ssh_userauth_none(session, NULL);
banner=ssh_get_issue_banner(session);
if(banner){
printf("%s\n",banner);
free(banner);
}
auth=authenticate_console(session);
if(auth != SSH_AUTH_SUCCESS){
return -1;
}
ssh_log(session, SSH_LOG_FUNCTIONS, "Authentication success");
forwarding(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(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
int main(int argc, char **argv){
ssh_session session;
session = ssh_new();
if(ssh_options_getopt(session, &argc, argv)) {
fprintf(stderr, "error parsing command line :%s\n",
ssh_get_error(session));
usage();
}
opts(argc,argv);
#ifdef WITH_PCAP
set_pcap(session);
#endif
client(session);
ssh_disconnect(session);
ssh_free(session);
#ifdef WITH_PCAP
cleanup_pcap();
#endif
ssh_finalize();
return 0;
}

View File

@@ -22,8 +22,7 @@
#ifndef BUFFER_H_
#define BUFFER_H_
/** Describes a buffer state at a moment
*/
/* Describes a buffer state */
struct ssh_buffer_struct {
char *data;
uint32_t used;

View File

@@ -40,7 +40,7 @@
#endif
#endif
#else
#if __GNUC__ >= 4
#if __GNUC__ >= 4 && !defined(__OS2__)
#define LIBSSH_API __attribute__((visibility("default")))
#else
#define LIBSSH_API
@@ -79,7 +79,7 @@
/* libssh version */
#define LIBSSH_VERSION_MAJOR 0
#define LIBSSH_VERSION_MINOR 4
#define LIBSSH_VERSION_MICRO 0
#define LIBSSH_VERSION_MICRO 8
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
LIBSSH_VERSION_MINOR, \
@@ -119,10 +119,16 @@ typedef struct ssh_string_struct* ssh_string;
/* Socket type */
#ifdef _WIN32
#define socket_t SOCKET
#else
#ifndef socket_t
typedef SOCKET socket_t;
#endif /* socket_t */
#else /* _WIN32 */
#ifndef socket_t
typedef int socket_t;
#endif
#endif /* _WIN32 */
#define SSH_INVALID_SOCKET ((socket_t) -1)
/* the offsets of methods */
enum ssh_kex_types_e {
@@ -165,7 +171,7 @@ enum ssh_requests_e {
SSH_REQUEST_CHANNEL_OPEN,
SSH_REQUEST_CHANNEL,
SSH_REQUEST_SERVICE,
SSH_REQUEST_GLOBAL,
SSH_REQUEST_GLOBAL
};
enum ssh_channel_type_e {
@@ -183,7 +189,7 @@ enum ssh_channel_requests_e {
SSH_CHANNEL_REQUEST_SHELL,
SSH_CHANNEL_REQUEST_ENV,
SSH_CHANNEL_REQUEST_SUBSYSTEM,
SSH_CHANNEL_REQUEST_WINDOW_CHANGE,
SSH_CHANNEL_REQUEST_WINDOW_CHANGE
};
/* status flags */
@@ -197,7 +203,7 @@ enum ssh_server_known_e {
SSH_SERVER_KNOWN_OK,
SSH_SERVER_KNOWN_CHANGED,
SSH_SERVER_FOUND_OTHER,
SSH_SERVER_FILE_NOT_FOUND,
SSH_SERVER_FILE_NOT_FOUND
};
#ifndef MD5_DIGEST_LEN
@@ -231,7 +237,7 @@ enum {
/** Only rare and noteworthy events
*/
SSH_LOG_RARE,
/** High level protocol informations
/** High level protocol information
*/
SSH_LOG_PROTOCOL,
/** Lower level protocol infomations, packet level
@@ -252,6 +258,7 @@ enum ssh_options_e {
SSH_OPTIONS_USER,
SSH_OPTIONS_SSH_DIR,
SSH_OPTIONS_IDENTITY,
SSH_OPTIONS_ADD_IDENTITY,
SSH_OPTIONS_KNOWNHOSTS,
SSH_OPTIONS_TIMEOUT,
SSH_OPTIONS_TIMEOUT_USEC,
@@ -263,7 +270,9 @@ enum ssh_options_e {
SSH_OPTIONS_CIPHERS_C_S,
SSH_OPTIONS_CIPHERS_S_C,
SSH_OPTIONS_COMPRESSION_C_S,
SSH_OPTIONS_COMPRESSION_S_C
SSH_OPTIONS_COMPRESSION_S_C,
SSH_OPTIONS_PROXYCOMMAND,
SSH_OPTIONS_BINDADDR
};
enum {
@@ -335,10 +344,14 @@ LIBSSH_API void privatekey_free(ssh_private_key prv);
LIBSSH_API ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
int type, const char *passphrase);
LIBSSH_API void publickey_free(ssh_public_key key);
LIBSSH_API int ssh_publickey_to_file(ssh_session session, const char *file,
ssh_string pubkey, int type);
LIBSSH_API ssh_string publickey_from_file(ssh_session session, const char *filename,
int *type);
LIBSSH_API ssh_public_key publickey_from_privatekey(ssh_private_key prv);
LIBSSH_API ssh_string publickey_to_string(ssh_public_key key);
LIBSSH_API int ssh_try_publickey_from_file(ssh_session session, const char *keyfile,
ssh_string *publickey, int *type);
LIBSSH_API int ssh_auth_list(ssh_session session);
LIBSSH_API char *ssh_basename (const char *path);
@@ -383,6 +396,9 @@ LIBSSH_API int ssh_pcap_file_close(ssh_pcap_file pcap);
LIBSSH_API void ssh_pcap_file_free(ssh_pcap_file pcap);
LIBSSH_API ssh_pcap_file ssh_pcap_file_new(void);
LIBSSH_API int ssh_pcap_file_open(ssh_pcap_file pcap, const char *filename);
LIBSSH_API int ssh_privatekey_type(ssh_private_key privatekey);
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);
LIBSSH_API int ssh_scp_close(ssh_scp scp);

View File

@@ -25,8 +25,12 @@
/* in misc.c */
/* gets the user home dir. */
char *ssh_get_user_home_dir(void);
char *ssh_get_local_username(ssh_session session);
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);
/* macro for byte ordering */
uint64_t ntohll(uint64_t);
#define htonll(x) ntohll(x)
@@ -46,14 +50,12 @@ struct ssh_iterator {
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);
int ssh_list_add(struct ssh_list *list, const void *data);
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_hostport(const char *host, int port);
/** @brief fetch the head element of a list and remove it from list
* @param list the ssh_list to use
* @return the first element of the list
*/
const void *_ssh_list_get_head(struct ssh_list *list);
const void *_ssh_list_pop_head(struct ssh_list *list);
#define ssh_iterator_value(type, iterator)\
((type)((iterator)->data))
@@ -61,9 +63,9 @@ const void *_ssh_list_get_head(struct ssh_list *list);
/** @brief fetch the head element of a list and remove it from list
* @param type type of the element to return
* @param list the ssh_list to use
* @return the first element of the list
* @return the first element of the list, or NULL if the list is empty
*/
#define ssh_list_get_head(type, ssh_list)\
((type)_ssh_list_get_head(ssh_list))
#define ssh_list_pop_head(type, ssh_list)\
((type)_ssh_list_pop_head(ssh_list))
#endif /* MISC_H_ */

View File

@@ -38,9 +38,48 @@ typedef struct ssh_pollfd_struct {
short revents; /* returned events */
} ssh_pollfd_t;
typedef unsigned long int nfds_t;
#ifdef _WIN32
#ifndef POLLRDNORM
#define POLLRDNORM 0x0100
#endif
#ifndef POLLRDBAND
#define POLLRDBAND 0x0200
#endif
#ifndef POLLIN
#define POLLIN (POLLRDNORM | POLLRDBAND)
#endif
#ifndef POLLPRI
#define POLLPRI 0x0400
#endif
#ifndef POLLWRNORM
#define POLLWRNORM 0x0010
#endif
#ifndef POLLOUT
#define POLLOUT (POLLWRNORM)
#endif
#ifndef POLLWRBAND
#define POLLWRBAND 0x0020
#endif
#ifndef POLLERR
#define POLLERR 0x0001
#endif
#ifndef POLLHUP
#define POLLHUP 0x0002
#endif
#ifndef POLLNVAL
#define POLLNVAL 0x0004
#endif
#else /* _WIN32 */
/* poll.c */
#ifndef POLLIN
# define POLLIN 0x001 /* There is data to read. */
#define POLLIN 0x001 /* There is data to read. */
#endif
#ifndef POLLPRI
#define POLLPRI 0x002 /* There is urgent data to read. */
@@ -59,9 +98,24 @@ typedef struct ssh_pollfd_struct {
#define POLLNVAL 0x020 /* Invalid polling request. */
#endif
typedef unsigned long int nfds_t;
#ifndef POLLRDNORM
#define POLLRDNORM 0x040 /* mapped to read fds_set */
#endif
#ifndef POLLRDBAND
#define POLLRDBAND 0x080 /* mapped to exception fds_set */
#endif
#ifndef POLLWRNORM
#define POLLWRNORM 0x100 /* mapped to write fds_set */
#endif
#ifndef POLLWRBAND
#define POLLWRBAND 0x200 /* mapped to write fds_set */
#endif
#endif /* WIN32 */
#endif /* HAVE_POLL */
void ssh_poll_init(void);
void ssh_poll_cleanup(void);
int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout);
typedef struct ssh_poll_ctx_struct *ssh_poll_ctx;
typedef struct ssh_poll_handle_struct *ssh_poll_handle;
@@ -77,7 +131,7 @@ typedef struct ssh_poll_handle_struct *ssh_poll_handle;
* @return 0 on success, < 0 if you removed the poll object from
* it's poll context.
*/
typedef int (*ssh_poll_callback)(ssh_poll_handle p, int fd, int revents,
typedef int (*ssh_poll_callback)(ssh_poll_handle p, socket_t fd, int revents,
void *userdata);

View File

@@ -32,18 +32,72 @@
#include "config.h"
#ifdef _MSC_VER
#define snprintf _snprintf
/** Imitate define of inttypes.h */
#define PRIdS "Id"
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#define strtoull _strtoui64
#define isblank(ch) ((ch) == ' ' || (ch) == '\t' || (ch) == '\n' || (ch) == '\r')
#else
#ifdef _WIN32
/* Imitate define of inttypes.h */
# ifndef PRIdS
# define PRIdS "Id"
# endif
# ifdef _MSC_VER
# include <stdio.h>
/* On Microsoft compilers define inline to __inline on all others use inline */
# undef inline
# define inline __inline
# undef strdup
# define strdup _strdup
# define strcasecmp _stricmp
# define strncasecmp _strnicmp
# define strtoull _strtoui64
# define isblank(ch) ((ch) == ' ' || (ch) == '\t' || (ch) == '\n' || (ch) == '\r')
# define usleep(X) Sleep(((X)+1000)/1000)
# undef strtok_r
# define strtok_r strtok_s
# if defined(HAVE__SNPRINTF_S)
# undef snprintf
# define snprintf(d, n, ...) _snprintf_s((d), (n), _TRUNCATE, __VA_ARGS__)
# else /* HAVE__SNPRINTF_S */
# if defined(HAVE__SNPRINTF)
# undef snprintf
# define snprintf _snprintf
# else /* HAVE__SNPRINTF */
# if !defined(HAVE_SNPRINTF)
# error "no snprintf compatible function found"
# endif /* HAVE_SNPRINTF */
# endif /* HAVE__SNPRINTF */
# endif /* HAVE__SNPRINTF_S */
# if defined(HAVE__VSNPRINTF_S)
# undef vsnprintf
# define vsnprintf(s, n, f, v) _vsnprintf_s((s), (n), _TRUNCATE, (f), (v))
# else /* HAVE__VSNPRINTF_S */
# if defined(HAVE__VSNPRINTF)
# undef vsnprintf
# define vsnprintf _vsnprintf
# else
# if !defined(HAVE_VSNPRINTF)
# error "No vsnprintf compatible function found"
# endif /* HAVE_VSNPRINTF */
# 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 */
#include <unistd.h>
#define PRIdS "zd"
#endif
#endif /* _WIN32 */
#include "libssh/libssh.h"
#include "libssh/callbacks.h"
@@ -77,7 +131,7 @@ typedef struct kex_struct {
struct error_struct {
/* error handling */
int error_code;
unsigned int error_code;
char error_buffer[ERROR_BUFFERLEN];
};
@@ -222,8 +276,8 @@ int gettimeofday(struct timeval *__p, void *__t);
/* options.c */
char *dir_expand_dup(ssh_session session, const char *value, int allowsshdir);
int ssh_options_set_algo(ssh_session session, int algo, const char *list);
int ssh_options_apply(ssh_session session);
/** Free memory space */
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)

View File

@@ -61,9 +61,13 @@ LIBSSH_API ssh_bind ssh_bind_new(void);
/**
* @brief Set the opitons for the current SSH server bind.
*
* @param ssh_bind The ssh server bind to use.
* @param sshbind The ssh server bind to use.
*
* @param options The option structure to set.
* @param type The option type to set.
*
* @param value The option value to set.
*
* @return 0 on success, < 0 on error.
*/
LIBSSH_API int ssh_bind_options_set(ssh_bind sshbind,
enum ssh_bind_options_e type, const void *value);

View File

@@ -102,9 +102,9 @@ struct ssh_session_struct {
#endif
char *username;
char *host;
char *bindaddr; /* TODO: check if needed */
char *bindaddr; /* bind the client to an ip addr */
char *xbanner; /* TODO: looks like it is not needed */
char *identity;
struct ssh_list *identity;
char *sshdir;
char *knownhosts;
char *wanted_methods[10];
@@ -114,8 +114,9 @@ struct ssh_session_struct {
socket_t fd;
int ssh2;
int ssh1;
char *ProxyCommand;
};
int ssh_handle_packets(ssh_session session);
void ssh_global_request_handle(ssh_session session);
#endif /* SESSION_H_ */

View File

@@ -149,17 +149,16 @@ struct sftp_status_message_struct {
char *langmsg;
};
/* don't worry much of these aren't really used */
struct sftp_attributes_struct {
char *name;
char *longname; /* some weird stuff */
char *longname; /* ls -l output on openssh, not reliable else */
uint32_t flags;
uint8_t type;
uint64_t size;
uint32_t uid;
uint32_t gid;
char *owner;
char *group;
char *owner; /* set if openssh and version 4 */
char *group; /* set if openssh and version 4 */
uint32_t permissions;
uint64_t atime64;
uint32_t atime;

View File

@@ -30,6 +30,7 @@ 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
@@ -38,7 +39,7 @@ 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, int *fd_max);
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);
@@ -52,4 +53,10 @@ int ssh_socket_get_status(struct socket *s);
int ssh_socket_data_available(struct socket *s);
int ssh_socket_data_writable(struct socket *s);
#ifndef _WIN32
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);
#endif
#endif /* SOCKET_H_ */

View File

@@ -70,6 +70,11 @@ typedef HMAC_CTX* HMACCTX;
#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;

View File

@@ -43,7 +43,7 @@ if (HAVE_LIBSOCKET)
)
endif (HAVE_LIBSOCKET)
if (CRYPTO_LIBRARY)
if (OPENSSL_LIBRARIES)
set(LIBSSH_PRIVATE_INCLUDE_DIRS
${LIBSSH_PRIVATE_INCLUDE_DIRS}
${OPENSSL_INCLUDE_DIRS}
@@ -51,9 +51,9 @@ if (CRYPTO_LIBRARY)
set(LIBSSH_LINK_LIBRARIES
${LIBSSH_LINK_LIBRARIES}
${CRYPTO_LIBRARY}
${OPENSSL_LIBRARIES}
)
endif (CRYPTO_LIBRARY)
endif (OPENSSL_LIBRARIES)
if (GCRYPT_LIBRARY)
set(LIBSSH_PRIVATE_INCLUDE_DIRS

View File

@@ -41,7 +41,6 @@
#include <string.h>
#include <stdio.h>
#include <poll.h>
#include <unistd.h>
#ifndef _WIN32
@@ -54,6 +53,7 @@
#include "libssh/buffer.h"
#include "libssh/session.h"
#include "libssh/keys.h"
#include "libssh/poll.h"
/* macro to check for "agent failure" message */
#define agent_failed(x) \
@@ -85,8 +85,8 @@ static size_t atomicio(struct socket *s, void *buf, size_t n, int do_read) {
char *b = buf;
size_t pos = 0;
ssize_t res;
struct pollfd pfd;
int fd = ssh_socket_get_fd(s);
ssh_pollfd_t pfd;
socket_t fd = ssh_socket_get_fd(s);
pfd.fd = fd;
pfd.events = do_read ? POLLIN : POLLOUT;
@@ -107,7 +107,7 @@ static size_t atomicio(struct socket *s, void *buf, size_t n, int do_read) {
#else
if (errno == EAGAIN) {
#endif
(void) poll(&pfd, 1, -1);
(void) ssh_poll(&pfd, 1, -1);
continue;
}
return 0;

View File

@@ -35,6 +35,7 @@
#include "libssh/buffer.h"
#include "libssh/agent.h"
#include "libssh/keyfiles.h"
#include "libssh/misc.h"
#include "libssh/packet.h"
#include "libssh/session.h"
#include "libssh/keys.h"
@@ -169,24 +170,33 @@ static int wait_auth_status(ssh_session session, int kbdint) {
return rc;
}
/**
* @brief retrieves available authentication methods for this session
* @deprecated
* @see ssh_userauth_list
*/
int ssh_auth_list(ssh_session session) {
if (session == NULL) {
return -1;
}
return session->auth_methods;
return ssh_userauth_list(session, NULL);
}
/**
* @brief retrieves available authentication methods for this session
* @param[in] session the SSH session
* @param[in] username set to NULL
* @returns A bitfield of values SSH_AUTH_METHOD_NONE, SSH_AUTH_METHOD_PASSWORD,
SSH_AUTH_METHOD_PUBLICKEY, SSH_AUTH_METHOD_HOSTBASED,
SSH_AUTH_METHOD_INTERACTIVE.
@warning Other reserved flags may appear in future versions.
*/
int ssh_userauth_list(ssh_session session, const char *username) {
if (session == NULL || username == NULL) {
if (session == NULL) {
return SSH_AUTH_ERROR;
}
if (session->auth_methods == 0) {
ssh_userauth_none(session, username);
}
return ssh_auth_list(session);
return session->auth_methods;
}
/* use the "none" authentication question */
@@ -224,7 +234,7 @@ int ssh_userauth_none(ssh_session session, const char *username) {
if (username == NULL) {
if (session->username == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) {
if (ssh_options_apply(session) < 0) {
leave_function();
return rc;
}
@@ -330,7 +340,7 @@ int ssh_userauth_offer_pubkey(ssh_session session, const char *username,
if (username == NULL) {
if (session->username == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) {
if (ssh_options_apply(session) < 0) {
leave_function();
return rc;
}
@@ -442,7 +452,7 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
if (username == NULL) {
if (session->username == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) {
if (ssh_options_apply(session) < 0) {
leave_function();
return rc;
}
@@ -560,7 +570,7 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
if (username == NULL) {
if (session->username == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) {
if (ssh_options_apply(session) < 0) {
leave_function();
return rc;
}
@@ -687,7 +697,7 @@ int ssh_userauth_password(ssh_session session, const char *username,
if (username == NULL) {
if (session->username == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) {
if (ssh_options_apply(session) < 0) {
leave_function();
return rc;
}
@@ -756,42 +766,6 @@ error:
return rc;
}
#ifdef _MSC_VER
static const char privKey_1[] = "SSH_DIR/identity";
static const char pubKey_1[] = "SSH_DIR/identity.pub";
static const char privKey_2[] = "SSH_DIR/id_dsa";
static const char pubKey_2[] = "SSH_DIR/id_dsa.pub";
static const char privKey_3[] = "SSH_DIR/id_rsa";
static const char pubKey_3[] = "SSH_DIR/id_rsa.pub";
/** Used different var to allow const char[] declaration */
static struct ssh_keys_struct keytab[] = {
{ privKey_1, pubKey_1},
{ privKey_2, pubKey_2},
{ privKey_3, pubKey_3},
{0}
};
#else
/* This requires GCC extensions */
static struct ssh_keys_struct keytab[] = {
{
.privatekey = "SSH_DIR/identity",
.publickey = "SSH_DIR/identity.pub"
},
{
.privatekey = "SSH_DIR/id_dsa",
.publickey = "SSH_DIR/id_dsa.pub",
},
{
.privatekey = "SSH_DIR/id_rsa",
.publickey = "SSH_DIR/id_rsa.pub",
},
{
.privatekey = NULL,
.publickey = NULL
}
};
#endif
/**
* @brief Tries to automaticaly authenticate with public key and "none"
*
@@ -812,16 +786,12 @@ static struct ssh_keys_struct keytab[] = {
*
* @see ssh_userauth_kbdint()
* @see ssh_userauth_password()
* @see ssh_options_set()
*/
int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) {
struct ssh_public_key_struct *publickey;
ssh_string pubkey;
struct ssh_iterator *it;
ssh_private_key privkey;
char *privkeyfile = NULL;
char *id = NULL;
size_t size;
unsigned int i = 0;
ssh_public_key pubkey;
ssh_string pubkey_string;
int type = 0;
int rc;
@@ -837,142 +807,159 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) {
/* Try authentication with ssh-agent first */
#ifndef _WIN32
if (agent_is_running(session)) {
char *privkey_file = NULL;
ssh_log(session, SSH_LOG_RARE,
"Trying to authenticate with SSH agent keys as user: %s",
session->username);
for (publickey = agent_get_first_ident(session, &privkeyfile);
publickey != NULL;
publickey = agent_get_next_ident(session, &privkeyfile)) {
for (pubkey = agent_get_first_ident(session, &privkey_file);
pubkey != NULL;
pubkey = agent_get_next_ident(session, &privkey_file)) {
ssh_log(session, SSH_LOG_RARE, "Trying identity %s", privkeyfile);
ssh_log(session, SSH_LOG_RARE, "Trying identity %s", privkey_file);
pubkey = publickey_to_string(publickey);
if (pubkey) {
rc = ssh_userauth_offer_pubkey(session, NULL, publickey->type, pubkey);
string_free(pubkey);
pubkey_string = publickey_to_string(pubkey);
if (pubkey_string) {
rc = ssh_userauth_offer_pubkey(session, NULL, pubkey->type, pubkey_string);
string_free(pubkey_string);
if (rc == SSH_AUTH_ERROR) {
SAFE_FREE(id);
SAFE_FREE(privkeyfile);
publickey_free(publickey);
SAFE_FREE(privkey_file);
publickey_free(pubkey);
leave_function();
return rc;
} else if (rc != SSH_AUTH_SUCCESS) {
ssh_log(session, SSH_LOG_PACKET, "Public key refused by server\n");
SAFE_FREE(id);
SAFE_FREE(privkeyfile);
publickey_free(publickey);
ssh_log(session, SSH_LOG_PROTOCOL, "Public key refused by server");
SAFE_FREE(privkey_file);
publickey_free(pubkey);
continue;
}
ssh_log(session, SSH_LOG_RARE, "Public key accepted");
/* pubkey accepted by server ! */
rc = ssh_userauth_agent_pubkey(session, NULL, publickey);
rc = ssh_userauth_agent_pubkey(session, NULL, pubkey);
if (rc == SSH_AUTH_ERROR) {
SAFE_FREE(id);
SAFE_FREE(privkeyfile);
publickey_free(publickey);
SAFE_FREE(privkey_file);
publickey_free(pubkey);
leave_function();
return rc;
} else if (rc != SSH_AUTH_SUCCESS) {
ssh_log(session, SSH_LOG_RARE,
"Server accepted public key but refused the signature\n"
"It might be a bug of libssh\n");
SAFE_FREE(id);
SAFE_FREE(privkeyfile);
publickey_free(publickey);
"Server accepted public key but refused the signature ;"
" It might be a bug of libssh");
SAFE_FREE(privkey_file);
publickey_free(pubkey);
continue;
}
/* auth success */
ssh_log(session, SSH_LOG_RARE, "Authentication using %s success\n",
privkeyfile);
SAFE_FREE(id);
SAFE_FREE(privkeyfile);
publickey_free(publickey);
ssh_log(session, SSH_LOG_PROTOCOL, "Authentication using %s success",
privkey_file);
SAFE_FREE(privkey_file);
publickey_free(pubkey);
leave_function();
return SSH_AUTH_SUCCESS;
} /* if pubkey */
SAFE_FREE(id);
SAFE_FREE(privkeyfile);
publickey_free(publickey);
SAFE_FREE(privkey_file);
publickey_free(pubkey);
} /* for each privkey */
} /* if agent is running */
#endif
size = ARRAY_SIZE(keytab);
if (session->identity) {
ssh_log(session, SSH_LOG_RARE,
"Trying identity file %s\n", session->identity);
id = malloc(strlen(session->identity) + 1 + 4);
if (id == NULL) {
leave_function();
return SSH_AUTH_ERROR;
}
sprintf(id, "%s.pub", session->identity);
for (it = ssh_list_get_iterator(session->identity);
it != NULL;
it = it->next) {
const char *privkey_file = it->data;
int privkey_open = 0;
keytab[size - 1].privatekey = session->identity;
keytab[size - 1].publickey = id;
}
privkey = NULL;
for (i = 0, pubkey = try_publickey_from_file(session, keytab[i],
&privkeyfile, &type);
i < size;
pubkey = try_publickey_from_file(session, keytab[i++],
&privkeyfile, &type)) {
if (pubkey == NULL) {
ssh_log(session, SSH_LOG_PROTOCOL, "Trying to read privatekey %s", privkey_file);
rc = ssh_try_publickey_from_file(session, privkey_file, &pubkey_string, &type);
if (rc == 1) {
char *publickey_file;
size_t len;
privkey = privatekey_from_file(session, privkey_file, type, passphrase);
if (privkey == NULL) {
ssh_log(session, SSH_LOG_RARE,
"Reading private key %s failed (bad passphrase ?)",
privkey_file);
leave_function();
return SSH_AUTH_ERROR;
}
privkey_open = 1;
pubkey = publickey_from_privatekey(privkey);
if (pubkey == NULL) {
privatekey_free(privkey);
ssh_set_error_oom(session);
leave_function();
return SSH_AUTH_ERROR;
}
pubkey_string = publickey_to_string(pubkey);
type = pubkey->type;
publickey_free(pubkey);
if (pubkey_string == NULL) {
ssh_set_error_oom(session);
leave_function();
return SSH_AUTH_ERROR;
}
len = strlen(privkey_file) + 5;
publickey_file = malloc(len);
if (publickey_file == NULL) {
ssh_set_error_oom(session);
leave_function();
return SSH_AUTH_ERROR;
}
snprintf(publickey_file, len, "%s.pub", privkey_file);
rc = ssh_publickey_to_file(session, publickey_file, pubkey_string, type);
if (rc < 0) {
ssh_log(session, SSH_LOG_PACKET,
"Could not write public key to file: %s", publickey_file);
}
SAFE_FREE(publickey_file);
} else if (rc < 0) {
continue;
}
rc = ssh_userauth_offer_pubkey(session, NULL, type, pubkey);
rc = ssh_userauth_offer_pubkey(session, NULL, type, pubkey_string);
if (rc == SSH_AUTH_ERROR){
if (id != NULL) {
keytab[size - 1].privatekey = NULL;
keytab[size - 1].publickey = NULL;
SAFE_FREE(id);
}
string_free(pubkey);
SAFE_FREE(privkeyfile);
string_free(pubkey_string);
ssh_log(session, SSH_LOG_RARE, "Publickey authentication error");
leave_function();
return rc;
} else {
if (rc != SSH_AUTH_SUCCESS){
ssh_log(session, SSH_LOG_RARE, "Publickey refused by server");
string_free(pubkey);
pubkey = NULL;
SAFE_FREE(privkeyfile);
privkeyfile = NULL;
ssh_log(session, SSH_LOG_PROTOCOL, "Publickey refused by server");
string_free(pubkey_string);
continue;
}
}
/* Public key accepted by server! */
ssh_log(session, SSH_LOG_RARE, "Trying to read privatekey %s", privkeyfile);
privkey = privatekey_from_file(session, privkeyfile, type, passphrase);
if (privkey == NULL) {
ssh_log(session, SSH_LOG_FUNCTIONS,
"Reading private key %s failed (bad passphrase ?)",
privkeyfile);
string_free(pubkey);
pubkey = NULL;
SAFE_FREE(privkeyfile);
privkeyfile = NULL;
continue; /* continue the loop with other pubkey */
if (!privkey_open) {
ssh_log(session, SSH_LOG_PROTOCOL, "Trying to read privatekey %s",
privkey_file);
privkey = privatekey_from_file(session, privkey_file, type, passphrase);
if (privkey == NULL) {
ssh_log(session, SSH_LOG_RARE,
"Reading private key %s failed (bad passphrase ?)",
privkey_file);
string_free(pubkey_string);
continue; /* continue the loop with other pubkey */
}
}
rc = ssh_userauth_pubkey(session, NULL, pubkey, privkey);
rc = ssh_userauth_pubkey(session, NULL, pubkey_string, privkey);
if (rc == SSH_AUTH_ERROR) {
if (id != NULL) {
keytab[size - 1].privatekey = NULL;
keytab[size - 1].publickey = NULL;
SAFE_FREE(id);
}
string_free(pubkey);
SAFE_FREE(privkeyfile);
string_free(pubkey_string);
privatekey_free(privkey);
leave_function();
return rc;
@@ -980,39 +967,26 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) {
if (rc != SSH_AUTH_SUCCESS){
ssh_log(session, SSH_LOG_FUNCTIONS,
"The server accepted the public key but refused the signature");
string_free(pubkey);
pubkey = NULL;
SAFE_FREE(privkeyfile);
privkeyfile = NULL;
string_free(pubkey_string);
privatekey_free(privkey);
continue;
}
}
/* auth success */
ssh_log(session, SSH_LOG_RARE,
"Successfully authenticated using %s", privkeyfile);
string_free(pubkey);
ssh_log(session, SSH_LOG_PROTOCOL,
"Successfully authenticated using %s", privkey_file);
string_free(pubkey_string);
privatekey_free(privkey);
SAFE_FREE(privkeyfile);
if (id != NULL) {
keytab[size - 1].privatekey = NULL;
keytab[size - 1].publickey = NULL;
SAFE_FREE(id);
}
leave_function();
return SSH_AUTH_SUCCESS;
}
/* at this point, pubkey is NULL and so is privkeyfile */
ssh_log(session, SSH_LOG_FUNCTIONS,
"Tried every public key, none matched");
ssh_set_error(session,SSH_NO_ERROR,"No public key matched");
if (id) {
keytab[size - 1].privatekey = NULL;
keytab[size - 1].publickey = NULL;
SAFE_FREE(id);
}
leave_function();
return SSH_AUTH_DENIED;
@@ -1370,7 +1344,7 @@ int ssh_userauth_kbdint(ssh_session session, const char *user,
/* first time we call. we must ask for a challenge */
if (user == NULL) {
if ((user = session->username) == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) {
if (ssh_options_apply(session) < 0) {
leave_function();
return SSH_AUTH_ERROR;
} else {
@@ -1402,7 +1376,7 @@ int ssh_userauth_kbdint(ssh_session session, const char *user,
/*
* If we are at this point, it ss because session->kbdint exists.
* It means the user has set some informations there we need to send
* It means the user has set some information there we need to send
* the server and then we need to ack the status (new questions or ok
* pass in).
*/

View File

@@ -165,8 +165,10 @@ static int channel_open(ssh_channel channel, const char *type_c, int window,
type_c, channel->local_channel);
if (packet_wait(session, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, 1) != SSH_OK) {
leave_function();
return -1;
if(session->in_packet.type != SSH2_MSG_CHANNEL_OPEN_FAILURE) {
leave_function();
return -1;
}
}
switch(session->in_packet.type) {
@@ -552,6 +554,15 @@ static void channel_rcv_request(ssh_session session) {
return;
}
if(strcmp(request,"keepalive@openssh.com")==0){
SAFE_FREE(request);
ssh_log(session, SSH_LOG_PROTOCOL,"Responding to Openssh's keepalive");
buffer_add_u8(session->out_buffer, SSH2_MSG_CHANNEL_FAILURE);
buffer_add_u32(session->out_buffer, htonl(channel->remote_channel));
packet_send(session);
leave_function();
return;
}
/* TODO call message_handle since it handles channel requests as messages */
/* *but* reset buffer before !! */
@@ -566,7 +577,7 @@ static void channel_rcv_request(ssh_session session) {
/*
* channel_handle() is called by packet_wait(), for example when there is
* channel informations to handle.
* channel information to handle.
*/
void channel_handle(ssh_session session, int type){
enter_function();
@@ -785,7 +796,7 @@ void channel_free(ssh_channel channel) {
*
* @param channel The channel to send the eof to.
*
* @return SSH_SUCCESS on success\n
* @return SSH_OK on success\n
* SSH_ERROR on error\n
*
* @see channel_close()
@@ -828,7 +839,7 @@ error:
*
* @param channel The channel to close.
*
* @return SSH_SUCCESS on success\n
* @return SSH_OK on success\n
* SSH_ERROR on error
*
* @see channel_free()
@@ -1107,7 +1118,7 @@ error:
*
* @param row The number of rows.
*
* @return SSH_SUCCESS on success, SSH_ERROR on error.
* @return SSH_OK on success, SSH_ERROR on error.
*/
int channel_request_pty_size(ssh_channel channel, const char *terminal,
int col, int row) {
@@ -1158,7 +1169,7 @@ error:
*
* @param channel The channel to send the request.
*
* @return SSH_SUCCESS on success, SSH_ERROR on error.
* @return SSH_OK on success, SSH_ERROR on error.
*
* @see channel_request_pty_size()
*/
@@ -1219,7 +1230,7 @@ error:
*
* @param channel The channel to send the request.
*
* @returns SSH_SUCCESS on success, SSH_ERROR on error.
* @returns SSH_OK on success, SSH_ERROR on error.
*/
int channel_request_shell(ssh_channel channel) {
#ifdef WITH_SSH1
@@ -1237,7 +1248,7 @@ int channel_request_shell(ssh_channel channel) {
*
* @param subsys The subsystem to request (for example "sftp").
*
* @return SSH_SUCCESS on success, SSH_ERROR on error.
* @return SSH_OK on success, SSH_ERROR on error.
*
* @warning You normally don't have to call it for sftp, see sftp_new().
*/
@@ -1359,6 +1370,7 @@ static ssh_channel channel_accept(ssh_session session, int channeltype,
};
#endif
ssh_message msg = NULL;
ssh_channel channel = NULL;
struct ssh_iterator *iterator;
int t;
@@ -1373,16 +1385,20 @@ static ssh_channel channel_accept(ssh_session session, int channeltype,
if (ssh_message_type(msg) == SSH_REQUEST_CHANNEL_OPEN &&
ssh_message_subtype(msg) == channeltype) {
ssh_list_remove(session->ssh_message_list, iterator);
return ssh_message_channel_request_open_reply_accept(msg);
channel = ssh_message_channel_request_open_reply_accept(msg);
ssh_message_free(msg);
return channel;
}
iterator = iterator->next;
}
}
if(t>0){
#ifdef _WIN32
Sleep(50); /* 50ms */
Sleep(50); /* 50ms */
#else
nanosleep(&ts, NULL);
nanosleep(&ts, NULL);
#endif
}
}
return NULL;
@@ -1582,7 +1598,7 @@ error:
*
* @param value The value to set.
*
* @return SSH_SUCCESS on success, SSH_ERROR on error.
* @return SSH_OK on success, SSH_ERROR on error.
*
* @warning Some environement variables may be refused by security reasons.
* */
@@ -1633,7 +1649,7 @@ error:
* @param cmd The command to execute
* (e.g. "ls ~/ -al | grep -i reports").
*
* @return SSH_SUCCESS on success, SSH_ERROR on error.
* @return SSH_OK on success, SSH_ERROR on error.
*
* @see channel_request_shell()
*/
@@ -1683,7 +1699,7 @@ error:
* @param signal The signal to send (without SIG prefix)
* (e.g. "TERM" or "KILL").
*
* @return SSH_SUCCESS on success, SSH_ERROR on error (including attempt to send signal via SSH-v1 session).
* @return SSH_OK on success, SSH_ERROR on error (including attempt to send signal via SSH-v1 session).
*
*/
int channel_request_send_signal(ssh_channel channel, const char *signal) {
@@ -1806,7 +1822,7 @@ int channel_read_buffer(ssh_channel channel, ssh_buffer buffer, uint32_t count,
}
if (count == 0) {
/* write the ful buffer informations */
/* write the ful buffer information */
if (buffer_add_data(buffer, buffer_get_rest(stdbuf),
buffer_get_rest_len(stdbuf)) < 0) {
leave_function();
@@ -1995,9 +2011,10 @@ int channel_poll(ssh_channel channel, int is_stderr){
stdbuf = channel->stderr_buffer;
}
while (buffer_get_rest_len(stdbuf) == 0 && channel->remote_eof == 0) {
if (ssh_handle_packets(channel->session) <= 0) {
break;
if (buffer_get_rest_len(stdbuf) == 0 && channel->remote_eof == 0) {
if (ssh_handle_packets(channel->session) == SSH_ERROR) {
leave_function();
return SSH_ERROR;
}
}
@@ -2137,7 +2154,7 @@ static int count_ptrs(ssh_channel *ptrs) {
*
* @param timeout Timeout as defined by select(2).
*
* @return SSH_SUCCESS operation successful\n
* @return SSH_OK operation successful\n
* SSH_EINTR select(2) syscall was interrupted, relaunch the function
*/
int channel_select(ssh_channel *readchans, ssh_channel *writechans,
@@ -2147,7 +2164,7 @@ int channel_select(ssh_channel *readchans, ssh_channel *writechans,
fd_set rset;
fd_set wset;
fd_set eset;
int fdmax = -1;
socket_t max_fd = SSH_INVALID_SOCKET;
int rc;
int i;
@@ -2215,24 +2232,24 @@ int channel_select(ssh_channel *readchans, ssh_channel *writechans,
for (i = 0; readchans[i] != NULL; i++) {
if (!ssh_socket_fd_isset(readchans[i]->session->socket, &rset)) {
ssh_socket_fd_set(readchans[i]->session->socket, &rset, &fdmax);
ssh_socket_fd_set(readchans[i]->session->socket, &rset, &max_fd);
}
}
for (i = 0; writechans[i] != NULL; i++) {
if (!ssh_socket_fd_isset(writechans[i]->session->socket, &wset)) {
ssh_socket_fd_set(writechans[i]->session->socket, &wset, &fdmax);
ssh_socket_fd_set(writechans[i]->session->socket, &wset, &max_fd);
}
}
for (i = 0; exceptchans[i] != NULL; i++) {
if (!ssh_socket_fd_isset(exceptchans[i]->session->socket, &eset)) {
ssh_socket_fd_set(exceptchans[i]->session->socket, &eset, &fdmax);
ssh_socket_fd_set(exceptchans[i]->session->socket, &eset, &max_fd);
}
}
/* Here we go */
rc = select(fdmax, &rset, &wset, &eset, timeout);
rc = select(max_fd, &rset, &wset, &eset, timeout);
/* Leave if select was interrupted */
if (rc == EINTR) {
SAFE_FREE(rchans);

View File

@@ -26,6 +26,9 @@
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#ifndef _WIN32
#include <arpa/inet.h>
#endif
#include "libssh/priv.h"
#include "libssh/ssh1.h"
#include "libssh/buffer.h"

View File

@@ -110,26 +110,37 @@ static int ssh_analyze_banner(ssh_session session, int *ssh1, int *ssh2) {
const char *banner = session->serverbanner;
const char *openssh;
ssh_log(session, SSH_LOG_RARE, "Analyzing banner: %s", banner);
if (strncmp(banner, "SSH-", 4) != 0) {
ssh_set_error(session, SSH_FATAL, "Protocol mismatch: %s", banner);
return -1;
if (banner == NULL) {
ssh_set_error(session, SSH_FATAL, "Invalid banner");
return -1;
}
/*
* Typical banners e.g. are:
* SSH-1.5-blah
* SSH-1.99-blah
* SSH-2.0-blah
*
* 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 (banner[6] == '9') {
*ssh2 = 1;
} else {
*ssh2 = 0;
if (strlen(banner) > 6) {
if (banner[6] == '9') {
*ssh2 = 1;
} else {
*ssh2 = 0;
}
}
break;
case '2':
@@ -143,13 +154,21 @@ static int ssh_analyze_banner(ssh_session session, int *ssh1, int *ssh2) {
openssh = strstr(banner, "OpenSSH");
if (openssh != NULL) {
int major, minor;
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 server version: %d.%d (%x)",
major, minor, session->openssh);
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;
@@ -296,6 +315,7 @@ static int dh_handshake(ssh_session session) {
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;
@@ -400,10 +420,6 @@ error:
string_burn(f);
string_free(f);
}
if(pubkey != NULL){
string_burn(pubkey);
string_free(pubkey);
}
if(signature != NULL){
string_burn(signature);
string_free(signature);
@@ -484,7 +500,8 @@ int ssh_service_request(ssh_session session, const char *service) {
int ssh_connect(ssh_session session) {
int ssh1 = 0;
int ssh2 = 0;
int fd = -1;
socket_t fd = SSH_INVALID_SOCKET;
int ret;
if (session == NULL) {
ssh_set_error(session, SSH_FATAL, "Invalid session pointer");
@@ -500,18 +517,31 @@ int ssh_connect(ssh_session session) {
leave_function();
return SSH_ERROR;
}
if (session->fd == -1 && session->host == NULL) {
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;
}
if (session->fd != -1) {
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 < 0) {
if (fd == SSH_INVALID_SOCKET) {
leave_function();
return SSH_ERROR;
}
@@ -699,7 +729,7 @@ error:
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 informations about your rights";
"file for information about your rights";
}
/** @} */
/* vim: set ts=2 sw=2 et cindent: */

View File

@@ -35,11 +35,11 @@ enum ssh_config_opcode_e {
SOC_PORT,
SOC_USERNAME,
SOC_IDENTITY,
SOC_CIPHER,
SOC_CIPHERS,
SOC_COMPRESSION,
SOC_TIMEOUT,
SOC_PROTOCOL
SOC_PROTOCOL,
SOC_PROXYCOMMAND
};
struct ssh_config_keyword_table_s {
@@ -53,11 +53,11 @@ static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
{ "port", SOC_PORT },
{ "user", SOC_USERNAME },
{ "identityfile", SOC_IDENTITY },
{ "cipher", SOC_CIPHER },
{ "ciphers", SOC_CIPHERS },
{ "compression", SOC_COMPRESSION },
{ "connecttimeout", SOC_TIMEOUT },
{ "protocol", SOC_PROTOCOL },
{ "proxycommand", SOC_PROXYCOMMAND },
{ NULL, SOC_UNSUPPORTED }
};
@@ -199,21 +199,25 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
}
break;
case SOC_PORT:
p = ssh_config_get_str(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_PORT_STR, p);
if (session->port == 22) {
p = ssh_config_get_str(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_PORT_STR, p);
}
}
break;
case SOC_USERNAME:
p = ssh_config_get_str(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_USER, p);
if (session->username == NULL) {
p = ssh_config_get_str(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_USER, p);
}
}
break;
case SOC_IDENTITY:
p = ssh_config_get_str(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_IDENTITY, p);
ssh_options_set(session, SSH_OPTIONS_ADD_IDENTITY, p);
}
break;
case SOC_CIPHERS:
@@ -227,8 +231,8 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
i = ssh_config_get_yesno(&s, -1);
if (i >= 0 && *parsing) {
if (i) {
ssh_options_set(session, SSH_OPTIONS_COMPRESSION_C_S, "zlib");
ssh_options_set(session, SSH_OPTIONS_COMPRESSION_S_C, "zlib");
ssh_options_set(session, SSH_OPTIONS_COMPRESSION_C_S, "zlib,none");
ssh_options_set(session, SSH_OPTIONS_COMPRESSION_S_C, "zlib,none");
} else {
ssh_options_set(session, SSH_OPTIONS_COMPRESSION_C_S, "none");
ssh_options_set(session, SSH_OPTIONS_COMPRESSION_S_C, "none");
@@ -272,11 +276,19 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
ssh_options_set(session, SSH_OPTIONS_TIMEOUT, &i);
}
break;
case SOC_PROXYCOMMAND:
p = ssh_config_get_str(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, p);
}
break;
case SOC_UNSUPPORTED:
fprintf(stderr, "Unsupported option: %s, line: %d\n", keyword, count);
ssh_log(session, SSH_LOG_RARE, "Unsupported option: %s, line: %d\n",
keyword, count);
break;
default:
fprintf(stderr, "ERROR - unimplemented opcode: %d\n", opcode);
ssh_set_error(session, SSH_FATAL, "ERROR - unimplemented opcode: %d\n",
opcode);
SAFE_FREE(x);
return -1;
break;

View File

@@ -67,10 +67,7 @@
#include "libssh/socket.h"
#include "libssh/channels.h"
#include "libssh/session.h"
#ifndef HAVE_SELECT
#error "Your system must have select()"
#endif
#include "libssh/poll.h"
#ifndef HAVE_GETADDRINFO
#error "Your system must have getaddrinfo()"
@@ -202,29 +199,35 @@ static int getai(ssh_session session, const char *host, int port, struct addrinf
static int ssh_connect_ai_timeout(ssh_session session, const char *host,
int port, struct addrinfo *ai, long timeout, long usec, socket_t s) {
struct timeval to;
fd_set set;
int timeout_ms;
ssh_pollfd_t fds;
int rc = 0;
unsigned int len = sizeof(rc);
enter_function();
to.tv_sec = timeout;
to.tv_usec = usec;
/* I know we're losing some precision. But it's not like poll-like family
* type of mechanisms are precise up to the microsecond.
*/
timeout_ms=timeout * 1000 + usec / 1000;
sock_set_nonblocking(s);
ssh_log(session, SSH_LOG_RARE, "Trying to connect to host: %s:%d with "
"timeout %ld.%ld", host, port, timeout, usec);
"timeout %d ms", host, port, timeout_ms);
/* The return value is checked later */
connect(s, ai->ai_addr, ai->ai_addrlen);
freeaddrinfo(ai);
FD_ZERO(&set);
FD_SET(s, &set);
fds.fd=s;
fds.revents=0;
fds.events=POLLOUT;
#ifdef _WIN32
fds.events |= POLLWRNORM;
#endif
rc = ssh_poll(&fds,1,timeout_ms);
rc = select(s + 1, NULL, &set, NULL, &to);
if (rc == 0) {
/* timeout */
ssh_set_error(session, SSH_FATAL,
@@ -236,7 +239,7 @@ static int ssh_connect_ai_timeout(ssh_session session, const char *host,
if (rc < 0) {
ssh_set_error(session, SSH_FATAL,
"Select error: %s", strerror(errno));
"poll error: %s", strerror(errno));
ssh_connect_socket_close(s);
leave_function();
return -1;
@@ -341,7 +344,6 @@ socket_t ssh_connect_host(ssh_session session, const char *host,
ssh_set_error(session, SSH_FATAL, "Connect failed: %s", strerror(errno));
ssh_connect_socket_close(s);
s = -1;
leave_function();
continue;
} else {
/* We are connected */
@@ -391,6 +393,7 @@ int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
fd_set *readfds, struct timeval *timeout) {
struct timeval zerotime;
fd_set localset, localset2;
socket_t f;
int rep;
int set;
int i;
@@ -431,8 +434,8 @@ int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
/* Look into the localset for active fd */
set = 0;
for (i = 0; (i < maxfd) && !set; i++) {
if (FD_ISSET(i, &localset)) {
for (f = 0; (f < maxfd) && !set; f++) {
if (FD_ISSET(f, &localset)) {
set = 1;
}
}
@@ -494,9 +497,9 @@ int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
outchannels[j] = NULL;
FD_ZERO(&localset2);
for (i = 0; i < maxfd; i++) {
if (FD_ISSET(i, readfds) && FD_ISSET(i, &localset)) {
FD_SET(i, &localset2);
for (f = 0; f < maxfd; f++) {
if (FD_ISSET(f, readfds) && FD_ISSET(i, &localset)) {
FD_SET(f, &localset2);
}
}

View File

@@ -222,6 +222,8 @@ void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len) {
return;
}
printf("%s: %s\n", descr, hexa);
free(hexa);
}
int dh_generate_x(ssh_session session) {
@@ -831,8 +833,11 @@ int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash) {
if (session == NULL || hash == NULL) {
return -1;
}
*hash = NULL;
if (session->current_crypto == NULL ||
session->current_crypto->server_pubkey == NULL){
ssh_set_error(session,SSH_FATAL,"No current cryptographic context");
}
h = malloc(sizeof(unsigned char *) * MD5_DIGEST_LEN);
if (h == NULL) {

View File

@@ -65,6 +65,7 @@ int ssh_init(void) {
int ssh_finalize(void) {
ssh_regex_finalize();
ssh_crypto_finalize();
ssh_socket_cleanup();
#ifdef HAVE_LIBGCRYPT
gcry_control(GCRYCTL_TERM_SECMEM);
#elif defined HAVE_LIBCRYPTO

View File

@@ -40,10 +40,11 @@
#include "libssh/wrapper.h"
#include "libssh/keys.h"
#include "libssh/dh.h"
#include "libssh/string.h"
#ifdef HAVE_LIBGCRYPT
#define BLOWFISH "blowfish-cbc,"
#define AES "aes256-cbc,aes192-cbc,aes128-cbc,"
#define AES "aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,"
#define DES "3des-cbc"
#elif defined HAVE_LIBCRYPTO
#ifdef HAVE_OPENSSL_BLOWFISH_H
@@ -52,10 +53,15 @@
#define BLOWFISH ""
#endif
#ifdef HAVE_OPENSSL_AES_H
#ifdef BROKEN_AES_CTR
#define AES "aes256-cbc,aes192-cbc,aes128-cbc,"
#else
#define AES "aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,"
#endif /* BROKEN_AES_CTR */
#else
#define AES ""
#endif
#define DES "3des-cbc"
#endif
@@ -67,7 +73,7 @@
const char *default_methods[] = {
"diffie-hellman-group1-sha1",
"ssh-dss,ssh-rsa",
"ssh-rsa,ssh-dss",
AES BLOWFISH DES,
AES BLOWFISH DES,
"hmac-sha1",
@@ -81,7 +87,7 @@ const char *default_methods[] = {
const char *supported_methods[] = {
"diffie-hellman-group1-sha1",
"ssh-dss,ssh-rsa",
"ssh-rsa,ssh-dss",
AES BLOWFISH DES,
AES BLOWFISH DES,
"hmac-sha1",
@@ -194,48 +200,48 @@ char **space_tokenize(const char *chain){
return tokens;
}
/* find_matching gets 2 parameters : a list of available objects (in_d), separated by colons,*/
/* and a list of prefered objects (what_d) */
/* find_matching gets 2 parameters : a list of available objects (available_d), separated by colons,*/
/* and a list of preferred objects (preferred_d) */
/* it will return a strduped pointer on the first prefered object found in the available objects list */
char *ssh_find_matching(const char *in_d, const char *what_d){
char ** tok_in, **tok_what;
int i_in, i_what;
char *ssh_find_matching(const char *available_d, const char *preferred_d){
char ** tok_available, **tok_preferred;
int i_avail, i_pref;
char *ret;
if ((in_d == NULL) || (what_d == NULL)) {
if ((available_d == NULL) || (preferred_d == NULL)) {
return NULL; /* don't deal with null args */
}
tok_in = tokenize(in_d);
if (tok_in == NULL) {
tok_available = tokenize(available_d);
if (tok_available == NULL) {
return NULL;
}
tok_what = tokenize(what_d);
if (tok_what == NULL) {
SAFE_FREE(tok_in[0]);
SAFE_FREE(tok_in);
tok_preferred = tokenize(preferred_d);
if (tok_preferred == NULL) {
SAFE_FREE(tok_available[0]);
SAFE_FREE(tok_available);
}
for(i_in=0; tok_in[i_in]; ++i_in){
for(i_what=0; tok_what[i_what] ; ++i_what){
if(!strcmp(tok_in[i_in],tok_what[i_what])){
/* match */
ret=strdup(tok_in[i_in]);
/* free the tokens */
free(tok_in[0]);
free(tok_what[0]);
free(tok_in);
free(tok_what);
return ret;
}
for(i_pref=0; tok_preferred[i_pref] ; ++i_pref){
for(i_avail=0; tok_available[i_avail]; ++i_avail){
if(!strcmp(tok_available[i_avail],tok_preferred[i_pref])){
/* match */
ret=strdup(tok_available[i_avail]);
/* free the tokens */
free(tok_available[0]);
free(tok_preferred[0]);
free(tok_available);
free(tok_preferred);
return ret;
}
}
}
free(tok_in[0]);
free(tok_what[0]);
free(tok_in);
free(tok_what);
free(tok_available[0]);
free(tok_preferred[0]);
free(tok_available);
free(tok_preferred);
return NULL;
}
@@ -487,8 +493,8 @@ static int build_session_id1(ssh_session session, ssh_string servern,
}
#ifdef DEBUG_CRYPTO
ssh_print_hexa("host modulus",hostn->string,string_len(hostn));
ssh_print_hexa("server modulus",servern->string,string_len(servern));
ssh_print_hexa("host modulus",string_data(hostn),string_len(hostn));
ssh_print_hexa("server modulus",string_data(servern),string_len(servern));
#endif
md5_update(md5,string_data(hostn),string_len(hostn));
md5_update(md5,string_data(servern),string_len(servern));

View File

@@ -59,15 +59,15 @@
#endif /* HAVE_LIBCRYPTO */
#define MAXLINESIZE 80
#define RSA_HEADER_BEGIN "-----BEGIN RSA PRIVATE KEY-----"
#define RSA_HEADER_END "-----END RSA PRIVATE KEY-----"
#define DSA_HEADER_BEGIN "-----BEGIN DSA PRIVATE KEY-----"
#define DSA_HEADER_END "-----END DSA PRIVATE KEY-----"
#ifdef HAVE_LIBGCRYPT
#define MAX_KEY_SIZE 32
#define MAX_PASSPHRASE_SIZE 1024
#define RSA_HEADER_BEGIN "-----BEGIN RSA PRIVATE KEY-----"
#define RSA_HEADER_END "-----END RSA PRIVATE KEY-----"
#define DSA_HEADER_BEGIN "-----BEGIN DSA PRIVATE KEY-----"
#define DSA_HEADER_END "-----END DSA PRIVATE KEY-----"
#define ASN1_INTEGER 2
#define ASN1_SEQUENCE 48
#define PKCS5_SALT_LEN 8
@@ -611,6 +611,22 @@ static int pem_get_password(char *buf, int size, int rwflag, void *userdata) {
}
#endif /* HAVE_LIBCRYPTO */
static int privatekey_type_from_file(FILE *fp) {
char buffer[MAXLINESIZE] = {0};
if (!fgets(buffer, MAXLINESIZE, fp)) {
return 0;
}
fseek(fp, 0, SEEK_SET);
if (strncmp(buffer, DSA_HEADER_BEGIN, strlen(DSA_HEADER_BEGIN)) == 0) {
return TYPE_DSS;
}
if (strncmp(buffer, RSA_HEADER_BEGIN, strlen(RSA_HEADER_BEGIN)) == 0) {
return TYPE_RSA;
}
return 0;
}
/** \addtogroup ssh_auth
* @{
*/
@@ -618,7 +634,7 @@ static int pem_get_password(char *buf, int size, int rwflag, void *userdata) {
/** \brief Reads a SSH private key from a file
* \param session SSH Session
* \param filename Filename containing the private key
* \param type Type of the private key. One of TYPE_DSS or TYPE_RSA.
* \param type Type of the private key. One of TYPE_DSS or TYPE_RSA. Pass 0 to automatically detect the type.
* \param passphrase Passphrase to decrypt the private key. Set to null if none is needed or it is unknown.
* \returns a PRIVATE_KEY object containing the private key, or NULL if it failed.
* \see privatekey_free()
@@ -649,10 +665,19 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
ssh_log(session, SSH_LOG_RARE, "Trying to read %s, passphase=%s, authcb=%s",
filename, passphrase ? "true" : "false",
session->callbacks && session->callbacks->auth_function ? "true" : "false");
if (type == 0) {
type = privatekey_type_from_file(file);
if (type == 0) {
fclose(file);
ssh_set_error(session, SSH_FATAL, "Invalid private key file.");
return NULL;
}
}
switch (type) {
case TYPE_DSS:
if (passphrase == NULL) {
if (session->callbacks->auth_function) {
if (session->callbacks && session->callbacks->auth_function) {
auth_cb = session->callbacks->auth_function;
auth_ud = session->callbacks->userdata;
@@ -731,6 +756,7 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
}
break;
default:
fclose(file);
ssh_set_error(session, SSH_FATAL, "Invalid private key type %d", type);
return NULL;
} /* switch */
@@ -754,6 +780,20 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
return privkey;
}
/**
* @brief returns the type of a private key
* @param privatekey[in] the private key handle
* @returns one of TYPE_RSA,TYPE_DSS,TYPE_RSA1
* @returns 0 if the type is unknown
* @see privatekey_from_file
* @see ssh_userauth_offer_pubkey
*/
int ssh_privatekey_type(ssh_private_key privatekey){
if (privatekey==NULL)
return 0;
return privatekey->type;
}
/* same that privatekey_from_file() but without any passphrase things. */
ssh_private_key _privatekey_from_file(void *session, const char *filename,
int type) {
@@ -861,6 +901,79 @@ void privatekey_free(ssh_private_key prv) {
SAFE_FREE(prv);
}
/**
* @brief Write a public key to a file.
*
* @param[in] session The ssh session to use.
*
* @param[in] file The filename to write the key into.
*
* @param[in] pubkey The public key to write.
*
* @param[in] type The type of the public key.
*
* @return 0 on success, -1 on error.
*/
int ssh_publickey_to_file(ssh_session session, const char *file,
ssh_string pubkey, int type) {
FILE *fp;
char *user;
char buffer[1024];
char host[256];
unsigned char *pubkey_64;
size_t len;
int rc;
pubkey_64 = bin_to_base64(pubkey->string, string_len(pubkey));
if (pubkey_64 == NULL) {
return -1;
}
user = ssh_get_local_username(session);
if (user == NULL) {
SAFE_FREE(pubkey_64);
return -1;
}
rc = gethostname(host, sizeof(host));
if (rc < 0) {
SAFE_FREE(user);
SAFE_FREE(pubkey_64);
return -1;
}
snprintf(buffer, sizeof(buffer), "%s %s %s@%s\n",
ssh_type_to_char(type),
pubkey_64,
user,
host);
SAFE_FREE(pubkey_64);
SAFE_FREE(user);
ssh_log(session, SSH_LOG_RARE, "Trying to write public key file: %s", file);
ssh_log(session, SSH_LOG_PACKET, "public key file content: %s", buffer);
fp = fopen(file, "w+");
if (fp == NULL) {
ssh_set_error(session, SSH_REQUEST_DENIED,
"Error opening %s: %s", file, strerror(errno));
return -1;
}
len = strlen(buffer);
if (fwrite(buffer, len, 1, fp) != 1 || ferror(fp)) {
ssh_set_error(session, SSH_REQUEST_DENIED,
"Unable to write to %s", file);
fclose(fp);
unlink(file);
return -1;
}
fclose(fp);
return 0;
}
/** \brief Retrieve a public key from a file
* \param session the SSH session
* \param filename Filename of the key
@@ -938,10 +1051,85 @@ ssh_string publickey_from_file(ssh_session session, const char *filename,
return str;
}
/**
* @brief Try to read the public key from a given file.
*
* @param[in] session The ssh session to use.
*
* @param[in] keyfile The name of the private keyfile.
*
* @param[out] publickey A ssh_string to store the public key.
*
* @param[out] type A pointer to an integer to store the type.
*
* @return 0 on success, -1 on error or the private key doesn't
* exist, 1 if the public key doesn't exist.
*/
int ssh_try_publickey_from_file(ssh_session session, const char *keyfile,
ssh_string *publickey, int *type) {
char *pubkey_file;
size_t len;
ssh_string pubkey_string;
int pubkey_type;
if (session == NULL || keyfile == NULL || publickey == NULL || type == NULL) {
return -1;
}
if (session->sshdir == NULL) {
if (ssh_options_apply(session) < 0) {
return -1;
}
}
ssh_log(session, SSH_LOG_PACKET, "Trying to open privatekey %s", keyfile);
if (!ssh_file_readaccess_ok(keyfile)) {
ssh_log(session, SSH_LOG_PACKET, "Failed to open privatekey %s", keyfile);
return -1;
}
len = strlen(keyfile) + 5;
pubkey_file = malloc(len);
if (pubkey_file == NULL) {
return -1;
}
snprintf(pubkey_file, len, "%s.pub", keyfile);
ssh_log(session, SSH_LOG_PACKET, "Trying to open publickey %s",
pubkey_file);
if (!ssh_file_readaccess_ok(pubkey_file)) {
ssh_log(session, SSH_LOG_PACKET, "Failed to open publickey %s",
pubkey_file);
SAFE_FREE(pubkey_file);
return 1;
}
ssh_log(session, SSH_LOG_PACKET, "Success opening public and private key");
/*
* We are sure both the private and public key file is readable. We return
* the public as a string, and the private filename as an argument
*/
pubkey_string = publickey_from_file(session, pubkey_file, &pubkey_type);
if (pubkey_string == NULL) {
ssh_log(session, SSH_LOG_PACKET,
"Wasn't able to open public key file %s: %s",
pubkey_file,
ssh_get_error(session));
SAFE_FREE(pubkey_file);
return -1;
}
SAFE_FREE(pubkey_file);
*publickey = pubkey_string;
*type = pubkey_type;
return 0;
}
ssh_string try_publickey_from_file(ssh_session session, struct ssh_keys_struct keytab,
char **privkeyfile, int *type) {
char *public;
char *private;
const char *priv;
const char *pub;
char *new;
@@ -957,26 +1145,20 @@ ssh_string try_publickey_from_file(ssh_session session, struct ssh_keys_struct k
}
if (session->sshdir == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL) < 0) {
if (ssh_options_apply(session) < 0) {
return NULL;
}
}
/* are them readable ? */
public=dir_expand_dup(session,pub,1);
private=dir_expand_dup(session,priv,1);
//snprintf(public, sizeof(public), "%s/%s", session->sshdir, pub);
//snprintf(private, sizeof(private), "%s/%s", session->sshdir, priv);
ssh_log(session, SSH_LOG_PACKET, "Trying to open publickey %s", public);
if (!ssh_file_readaccess_ok(public)) {
ssh_log(session, SSH_LOG_PACKET, "Failed to open publickey %s", public);
ssh_log(session, SSH_LOG_PACKET, "Trying to open publickey %s", pub);
if (!ssh_file_readaccess_ok(pub)) {
ssh_log(session, SSH_LOG_PACKET, "Failed to open publickey %s", pub);
goto error;
}
ssh_log(session, SSH_LOG_PACKET, "Trying to open privatekey %s", private);
if (!ssh_file_readaccess_ok(private)) {
ssh_log(session, SSH_LOG_PACKET, "Failed to open privatekey %s", private);
ssh_log(session, SSH_LOG_PACKET, "Trying to open privatekey %s", priv);
if (!ssh_file_readaccess_ok(priv)) {
ssh_log(session, SSH_LOG_PACKET, "Failed to open privatekey %s", priv);
goto error;
}
@@ -986,26 +1168,24 @@ ssh_string try_publickey_from_file(ssh_session session, struct ssh_keys_struct k
* We are sure both the private and public key file is readable. We return
* the public as a string, and the private filename as an argument
*/
pubkey = publickey_from_file(session, public, type);
pubkey = publickey_from_file(session, pub, type);
if (pubkey == NULL) {
ssh_log(session, SSH_LOG_PACKET,
"Wasn't able to open public key file %s: %s",
public,
pub,
ssh_get_error(session));
goto error;
}
new = realloc(*privkeyfile, strlen(private) + 1);
new = realloc(*privkeyfile, strlen(priv) + 1);
if (new == NULL) {
string_free(pubkey);
goto error;
}
strcpy(new, private);
strcpy(new, priv);
*privkeyfile = new;
error:
SAFE_FREE(public);
SAFE_FREE(private);
return pubkey;
}
@@ -1370,7 +1550,6 @@ static int match_hashed_host(ssh_session session, const char *host,
* if host key is accepted\n
* SSH_SERVER_ERROR: Some error happened
*
* \see ssh_options_set()
* \see ssh_get_pubkey_hash()
*
* \bug There is no current way to remove or modify an entry into the known
@@ -1380,6 +1559,7 @@ int ssh_is_server_known(ssh_session session) {
FILE *file = NULL;
char **tokens;
char *host;
char *hostport;
const char *type;
int match;
int ret = SSH_SERVER_NOT_KNOWN;
@@ -1387,7 +1567,7 @@ int ssh_is_server_known(ssh_session session) {
enter_function();
if (session->knownhosts == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, NULL) < 0) {
if (ssh_options_apply(session) < 0) {
ssh_set_error(session, SSH_REQUEST_DENIED,
"Can't find a known_hosts file");
leave_function();
@@ -1403,8 +1583,11 @@ int ssh_is_server_known(ssh_session session) {
}
host = lowercase(session->host);
if (host == NULL) {
ssh_set_error(session, SSH_FATAL, "Not enough space!");
hostport = ssh_hostport(host,session->port);
if (host == NULL || hostport == NULL) {
ssh_set_error_oom(session);
SAFE_FREE(host);
SAFE_FREE(hostport);
leave_function();
return SSH_SERVER_ERROR;
}
@@ -1418,10 +1601,15 @@ int ssh_is_server_known(ssh_session session) {
break;
}
match = match_hashed_host(session, host, tokens[0]);
if (match == 0){
match = match_hostname(hostport, tokens[0], strlen(tokens[0]));
}
if (match == 0) {
match = match_hostname(host, tokens[0], strlen(tokens[0]));
}
if (match == 0) {
match = match_hashed_host(session, hostport, tokens[0]);
}
if (match) {
/* We got a match. Now check the key type */
if (strcmp(session->current_crypto->server_pubkey_type, type) != 0) {
@@ -1452,6 +1640,7 @@ int ssh_is_server_known(ssh_session session) {
} while (1);
SAFE_FREE(host);
SAFE_FREE(hostport);
if (file != NULL) {
fclose(file);
}
@@ -1461,10 +1650,15 @@ int ssh_is_server_known(ssh_session session) {
return ret;
}
/** You generaly use it when ssh_is_server_known() answered SSH_SERVER_NOT_KNOWN
* \brief write the current server as known in the known hosts file. This will create the known hosts file if it does not exist.
* \param session ssh session
* \return 0 on success, -1 on error
/**
* @brief Write the current server as known in the known hosts file.
*
* This will create the known hosts file if it does not exist. You generaly use
* it when ssh_is_server_known() answered SSH_SERVER_NOT_KNOWN.
*
* @param[in] session The ssh session to use.
*
* @return SSH_OK on success, SSH_ERROR on error.
*/
int ssh_write_knownhost(ssh_session session) {
ssh_string pubkey = session->current_crypto->server_pubkey;
@@ -1472,17 +1666,30 @@ int ssh_write_knownhost(ssh_session session) {
char buffer[4096] = {0};
FILE *file;
char *dir;
char *host;
char *hostport;
size_t len = 0;
if (ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, NULL) < 0) {
ssh_set_error(session, SSH_FATAL, "Cannot find known_hosts file.");
return -1;
}
if (session->host == NULL) {
ssh_set_error(session, SSH_FATAL,
"Cannot write host in known hosts if the hostname is unknown");
return -1;
"Can't write host in known hosts if the hostname isn't known");
return SSH_ERROR;
}
host = lowercase(session->host);
/* If using a nonstandard port, save the host in the [host]:port format */
if(session->port != 22){
hostport = ssh_hostport(host,session->port);
SAFE_FREE(host);
host=hostport;
hostport=NULL;
}
if (session->knownhosts == NULL) {
if (ssh_options_apply(session) < 0) {
ssh_set_error(session, SSH_FATAL, "Can't find a known_hosts file");
return -1;
}
}
/* Check if ~/.ssh exists and create it if not */
@@ -1506,6 +1713,7 @@ int ssh_write_knownhost(ssh_session session) {
ssh_set_error(session, SSH_FATAL,
"Couldn't open known_hosts file %s for appending: %s",
session->knownhosts, strerror(errno));
SAFE_FREE(host);
return -1;
}
@@ -1525,6 +1733,7 @@ int ssh_write_knownhost(ssh_session session) {
key = publickey_from_string(session, pubkey);
if (key == NULL) {
fclose(file);
SAFE_FREE(host);
return -1;
}
@@ -1533,6 +1742,7 @@ int ssh_write_knownhost(ssh_session session) {
if (sexp == NULL) {
publickey_free(key);
fclose(file);
SAFE_FREE(host);
return -1;
}
e = gcry_sexp_nth_mpi(sexp, 1, GCRYMPI_FMT_USG);
@@ -1540,6 +1750,7 @@ int ssh_write_knownhost(ssh_session session) {
if (e == NULL) {
publickey_free(key);
fclose(file);
SAFE_FREE(host);
return -1;
}
@@ -1548,6 +1759,7 @@ int ssh_write_knownhost(ssh_session session) {
publickey_free(key);
bignum_free(e);
fclose(file);
SAFE_FREE(host);
return -1;
}
n = gcry_sexp_nth_mpi(sexp, 1, GCRYMPI_FMT_USG);
@@ -1556,6 +1768,7 @@ int ssh_write_knownhost(ssh_session session) {
publickey_free(key);
bignum_free(e);
fclose(file);
SAFE_FREE(host);
return -1;
}
@@ -1580,12 +1793,13 @@ int ssh_write_knownhost(ssh_session session) {
#endif
publickey_free(key);
fclose(file);
SAFE_FREE(host);
return -1;
}
snprintf(buffer, sizeof(buffer),
"%s %d %s %s\n",
session->host,
host,
rsa_size << 3,
e_string,
n_string);
@@ -1605,18 +1819,19 @@ int ssh_write_knownhost(ssh_session session) {
pubkey_64 = bin_to_base64(pubkey->string, string_len(pubkey));
if (pubkey_64 == NULL) {
fclose(file);
SAFE_FREE(host);
return -1;
}
snprintf(buffer, sizeof(buffer),
"%s %s %s\n",
session->host,
host,
session->current_crypto->server_pubkey_type,
pubkey_64);
SAFE_FREE(pubkey_64);
}
SAFE_FREE(host);
len = strlen(buffer);
if (fwrite(buffer, len, 1, file) != 1 || ferror(file)) {
fclose(file);

View File

@@ -36,6 +36,7 @@
#include "libssh/keys.h"
#include "libssh/dh.h"
#include "libssh/messages.h"
#include "libssh/string.h"
/** \addtogroup ssh_auth
* @{
@@ -130,9 +131,9 @@ ssh_public_key publickey_make_dss(ssh_session session, ssh_buffer buffer) {
#endif /* HAVE_LIBCRYPTO */
#ifdef DEBUG_CRYPTO
ssh_print_hexa("p", p->string, string_len(p));
ssh_print_hexa("q", q->string, string_len(q));
ssh_print_hexa("g", g->string, string_len(g));
ssh_print_hexa("p", string_data(p), string_len(p));
ssh_print_hexa("q", string_data(q), string_len(q));
ssh_print_hexa("g", string_data(g), string_len(g));
#endif
string_burn(p);
@@ -206,8 +207,8 @@ ssh_public_key publickey_make_rsa(ssh_session session, ssh_buffer buffer,
#endif
#ifdef DEBUG_CRYPTO
ssh_print_hexa("e", e->string, string_len(e));
ssh_print_hexa("n", n->string, string_len(n));
ssh_print_hexa("e", string_data(e), string_len(e));
ssh_print_hexa("n", string_data(n), string_len(n));
#endif
string_burn(e);
@@ -974,8 +975,8 @@ SIGNATURE *signature_from_string(ssh_session session, ssh_string signature,
#endif
#ifdef DEBUG_CRYPTO
ssh_print_hexa("r", rs->string, 20);
ssh_print_hexa("s", rs->string + 20, 20);
ssh_print_hexa("r", string_data(rs), 20);
ssh_print_hexa("s", (const unsigned char *)string_data(rs) + 20, 20);
#endif
string_free(rs);
@@ -1024,7 +1025,7 @@ SIGNATURE *signature_from_string(ssh_session session, ssh_string signature,
#ifdef DEBUG_CRYPTO
ssh_log(session, SSH_LOG_FUNCTIONS, "len e: %d", len);
ssh_print_hexa("RSA signature", e->string, len);
ssh_print_hexa("RSA signature", string_data(e), len);
#endif
#ifdef HAVE_LIBGCRYPT
@@ -1307,6 +1308,9 @@ ssh_string ssh_do_sign(ssh_session session, ssh_buffer sigbuf,
#endif
sign->dsa_sign = NULL;
break;
default:
signature_free(sign);
return NULL;
}
#ifdef HAVE_LIBGCRYPT
gcry_sexp_release(gcryhash);
@@ -1462,6 +1466,9 @@ ssh_string ssh_sign_session_id(ssh_session session, ssh_private_key privatekey)
#endif
sign->dsa_sign = NULL;
break;
default:
signature_free(sign);
return NULL;
}
#ifdef HAVE_LIBGCRYPT

View File

@@ -319,7 +319,6 @@ static ssh_message handle_channel_request_open(ssh_session session) {
ssh_log(session, SSH_LOG_PACKET,
"Clients wants to open a %s channel", type_c);
string_free(type);
buffer_get_u32(session->in_buffer, &sender);
buffer_get_u32(session->in_buffer, &window);
@@ -331,6 +330,7 @@ static ssh_message handle_channel_request_open(ssh_session session) {
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;
@@ -370,6 +370,7 @@ static ssh_message handle_channel_request_open(ssh_session session) {
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;
@@ -409,6 +410,7 @@ static ssh_message handle_channel_request_open(ssh_session session) {
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;
@@ -432,12 +434,14 @@ static ssh_message handle_channel_request_open(ssh_session session) {
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();
@@ -863,7 +867,7 @@ void message_handle(ssh_session session, uint32_t type){
if(!session->ssh_message_list){
session->ssh_message_list=ssh_list_new();
}
ssh_list_add(session->ssh_message_list,msg);
ssh_list_append(session->ssh_message_list,msg);
}
}

View File

@@ -35,15 +35,19 @@
#ifdef _WIN32
#define _WIN32_IE 0x0501 //SHGetSpecialFolderPath
#include <winsock2.h> // Must be the first to include
#include <ws2tcpip.h>
#include <shlobj.h>
#include <direct.h>
#else
/* This is needed for a standard getpwuid_r on opensolaris */
#define _POSIX_PTHREAD_SEMANTICS
#include <pwd.h>
#include <arpa/inet.h>
#endif
#include "libssh/priv.h"
#include "libssh/misc.h"
#include "libssh/session.h"
#ifdef HAVE_LIBGCRYPT
#define GCRYPT_STRING "/gnutls"
@@ -112,16 +116,23 @@ int gettimeofday(struct timeval *__p, void *__t) {
return (0);
}
#else /* _WIN32 */
#ifndef NSS_BUFLEN_PASSWD
#define NSS_BUFLEN_PASSWD 4096
#endif
char *ssh_get_user_home_dir(void) {
char *szPath = NULL;
struct passwd *pwd = NULL;
struct passwd pwd;
struct passwd *pwdbuf;
char buf[NSS_BUFLEN_PASSWD];
int rc;
pwd = getpwuid(getuid());
if (pwd == NULL) {
rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
if (rc != 0) {
return NULL;
}
szPath = strdup(pwd->pw_dir);
szPath = strdup(pwd.pw_dir);
return szPath;
}
@@ -136,6 +147,20 @@ int ssh_file_readaccess_ok(const char *file) {
}
#endif
char *ssh_hostport(const char *host, int port){
char *dest;
size_t len;
if(host==NULL)
return NULL;
/* 3 for []:, 5 for 65536 and 1 for nul */
len=strlen(host) + 3 + 5 + 1;
dest=malloc(len);
if(dest==NULL)
return NULL;
snprintf(dest,len,"[%s]:%d",host,port);
return dest;
}
uint64_t ntohll(uint64_t a) {
#ifdef WORDS_BIGENDIAN
return a;
@@ -149,6 +174,52 @@ uint64_t ntohll(uint64_t a) {
#endif
}
#ifdef _WIN32
char *ssh_get_local_username(ssh_session session) {
DWORD size = 0;
char *user;
/* get the size */
GetUserName(NULL, &size);
user = malloc(size);
if (user == NULL) {
ssh_set_error_oom(session);
return NULL;
}
if (GetUserName(user, &size)) {
return user;
}
return NULL;
}
#else
char *ssh_get_local_username(ssh_session session) {
struct passwd pwd;
struct passwd *pwdbuf;
char buf[NSS_BUFLEN_PASSWD];
char *name;
int rc;
rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
if (rc != 0) {
ssh_set_error(session, SSH_FATAL,
"Couldn't retrieve information for current user!");
return NULL;
}
name = strdup(pwd.pw_name);
if (name == NULL) {
ssh_set_error_oom(session);
return NULL;
}
return name;
}
#endif
/**
* @brief Check if libssh is the required version or get the version
* string.
@@ -213,7 +284,7 @@ static struct ssh_iterator *ssh_iterator_new(const void *data){
return iterator;
}
int ssh_list_add(struct ssh_list *list,const void *data){
int ssh_list_append(struct ssh_list *list,const void *data){
struct ssh_iterator *iterator=ssh_iterator_new(data);
if(!iterator)
return SSH_ERROR;
@@ -228,6 +299,25 @@ int ssh_list_add(struct ssh_list *list,const void *data){
return SSH_OK;
}
int ssh_list_prepend(struct ssh_list *list, const void *data){
struct ssh_iterator *it = ssh_iterator_new(data);
if (it == NULL) {
return SSH_ERROR;
}
if (list->end == NULL) {
/* list is empty */
list->root = list->end = it;
} else {
/* set as new root */
it->next = list->root;
list->root = it;
}
return SSH_OK;
}
void ssh_list_remove(struct ssh_list *list, struct ssh_iterator *iterator){
struct ssh_iterator *ptr,*prev;
prev=NULL;
@@ -252,7 +342,14 @@ void ssh_list_remove(struct ssh_list *list, struct ssh_iterator *iterator){
SAFE_FREE(iterator);
}
const void *_ssh_list_get_head(struct ssh_list *list){
/** @internal
* @brief Removes the top element of the list and returns the data value attached
* to it
* @param list the ssh_list
* @returns pointer to the element being stored in head, or
* NULL if the list is empty.
*/
const void *_ssh_list_pop_head(struct ssh_list *list){
struct ssh_iterator *iterator=list->root;
const void *data;
if(!list->root)
@@ -397,5 +494,157 @@ int ssh_mkdir(const char *pathname, mode_t mode) {
return r;
}
/** @} */
/* vim: set ts=2 sw=2 et cindent: */
/**
* @brief Expand a directory starting with a tilde '~'
*
* @param[in] session The ssh session to use.
*
* @param[in] d The directory to expand.
*
* @return The expanded directory, NULL on error.
*/
char *ssh_path_expand_tilde(const char *d) {
char *h = NULL, *r;
const char *p;
size_t ld;
size_t lh = 0;
if (d[0] != '~') {
return strdup(d);
}
d++;
/* handle ~user/path */
p = strchr(d, '/');
if (p != NULL && p > d) {
#ifdef _WIN32
return strdup(d);
#else
struct passwd *pw;
size_t s = p - d;
char u[128];
if (s > sizeof(u)) {
return NULL;
}
memcpy(u, d, s);
u[s] = '\0';
pw = getpwnam(u);
if (pw == NULL) {
return NULL;
}
ld = strlen(p);
h = strdup(pw->pw_dir);
#endif
} else {
ld = strlen(d);
p = (char *) d;
h = ssh_get_user_home_dir();
}
if (h == NULL) {
return NULL;
}
lh = strlen(h);
r = malloc(ld + lh + 1);
if (r == NULL) {
SAFE_FREE(h);
return NULL;
}
if (lh > 0) {
memcpy(r, h, lh);
}
SAFE_FREE(h);
memcpy(r + lh, p, ld + 1);
return r;
}
char *ssh_path_expand_escape(ssh_session session, const char *s) {
#define MAX_BUF_SIZE 4096
char host[NI_MAXHOST];
char buf[MAX_BUF_SIZE];
char *r, *x = NULL;
const char *p;
size_t i, l;
if (strlen(s) > MAX_BUF_SIZE) {
ssh_set_error(session, SSH_FATAL, "string to expand too long");
return NULL;
}
r = ssh_path_expand_tilde(s);
if (r == NULL) {
ssh_set_error_oom(session);
return NULL;
}
p = r;
buf[0] = '\0';
for (i = 0; *p != '\0'; p++) {
if (*p != '%') {
buf[i] = *p;
i++;
if (i > MAX_BUF_SIZE) {
return NULL;
}
buf[i] = '\0';
continue;
}
p++;
if (*p == '\0') {
break;
}
switch (*p) {
case 'd':
x = strdup(session->sshdir);
break;
case 'u':
x = ssh_get_local_username(session);
break;
case 'l':
if (gethostname(host, sizeof(host) == 0)) {
x = strdup(host);
}
break;
case 'h':
x = strdup(session->host);
break;
case 'r':
x = strdup(session->username);
break;
default:
ssh_set_error(session, SSH_FATAL,
"Wrong escape sequence detected");
return NULL;
}
if (x == NULL) {
ssh_set_error_oom(session);
return NULL;
}
i += strlen(x);
if (i > MAX_BUF_SIZE) {
ssh_set_error(session, SSH_FATAL,
"String too long");
return NULL;
}
l = strlen(buf);
strcat(buf + l, x);
buf[i] = '\0';
SAFE_FREE(x);
}
free(r);
return strdup(buf);
#undef MAX_BUF_SIZE
}
/* @} */
/* vim: set ts=4 sw=4 et cindent: */

View File

@@ -39,15 +39,22 @@
#include "libssh/server.h"
#endif
/**
* @addtogroup ssh_session
* @{
*/
/**
* @brief Duplicate the options of a session structure.
*
* If you make several sessions with the same options this is useful. You
* cannot use twice the same option structure in ssh_session_connect.
*
* @param opt Option structure to copy.
* @param src The session to use to copy the options.
*
* @returns New copied option structure, NULL on error.
* @param dest The session to copy the options to.
*
* @returns 0 on sucess, -1 on error with errno set.
*
* @see ssh_session_connect()
*/
@@ -76,10 +83,29 @@ int ssh_options_copy(ssh_session src, ssh_session *dest) {
}
if (src->identity) {
new->identity = strdup(src->identity);
struct ssh_iterator *it;
new->identity = ssh_list_new();
if (new->identity == NULL) {
return -1;
}
it = ssh_list_get_iterator(src->identity);
while (it) {
char *id;
int rc;
id = strdup((char *) it->data);
if (id == NULL) {
return -1;
}
rc = ssh_list_append(new->identity, id);
if (rc < 0) {
return -1;
}
it = it->next;
}
}
if (src->sshdir) {
@@ -117,29 +143,6 @@ int ssh_options_copy(ssh_session src, ssh_session *dest) {
return 0;
}
#ifndef _WIN32
static char *get_username_from_uid(ssh_session session, uid_t uid){
struct passwd *pwd = NULL;
char *name;
pwd = getpwuid(uid);
if (pwd == NULL) {
ssh_set_error(session, SSH_FATAL, "uid %d doesn't exist !", uid);
return NULL;
}
name = strdup(pwd->pw_name);
if (name == NULL) {
ssh_set_error_oom(session);
return NULL;
}
return name;
}
#endif
int ssh_options_set_algo(ssh_session session, int algo,
const char *list) {
if (!verify_existing_algo(algo, list)) {
@@ -159,58 +162,6 @@ int ssh_options_set_algo(ssh_session session, int algo,
return 0;
}
char *dir_expand_dup(ssh_session session, const char *value, int allowsshdir) {
char *new;
if (value[0] == '~' && value[1] == '/') {
char *homedir = ssh_get_user_home_dir();
size_t lv, lh;
if (homedir == NULL) {
return NULL;
}
lv = strlen(value + 1);
lh = strlen(homedir);
new = malloc(lv + lh + 1);
if (new == NULL) {
ssh_set_error_oom(session);
SAFE_FREE(homedir);
return NULL;
}
memcpy(new, homedir, lh);
SAFE_FREE(homedir);
memcpy(new + lh, value + 1, lv + 1);
return new;
}
if (allowsshdir && strncmp(value, "SSH_DIR/", 8) == 0) {
size_t lv, ls;
if (session->sshdir == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL) < 0)
return NULL;
}
value += 7;
lv = strlen(value);
ls = strlen(session->sshdir);
new = malloc(lv + ls + 1);
if (new == NULL) {
ssh_set_error_oom(session);
return NULL;
}
memcpy(new, session->sshdir, ls);
memcpy(new + ls, value, lv + 1);
return new;
}
new = strdup(value);
if (new == NULL) {
ssh_set_error_oom(session);
return NULL;
}
return new;
}
/**
* @brief This function can set all possible ssh options.
*
@@ -219,143 +170,153 @@ char *dir_expand_dup(ssh_session session, const char *value, int allowsshdir) {
* @param type The option type to set. This could be one of the
* following:
*
* SSH_OPTIONS_HOST:
* - SSH_OPTIONS_HOST:
* The hostname or ip address to connect to (string).
*
* SSH_OPTIONS_PORT:
* - SSH_OPTIONS_PORT:
* The port to connect to (integer).
*
* SSH_OPTIONS_PORT_STR:
* - SSH_OPTIONS_PORT_STR:
* The port to connect to (string).
*
* SSH_OPTIONS_FD:
* The file descriptor to use (socket_t).
*
* - SSH_OPTIONS_FD:
* The file descriptor to use (socket_t).\n
* \n
* If you wish to open the socket yourself for a reason
* or another, set the file descriptor. Don't forget to
* set the hostname as the hostname is used as a key in
* the known_host mechanism.
*
* SSH_OPTIONS_USER:
* The username for authentication (string).
* - SSH_OPTIONS_BINDADDR:
* The address to bind the client to (string).
*
* - SSH_OPTIONS_USER:
* The username for authentication (string).\n
* \n
* If the value is NULL, the username is set to the
* default username.
*
* SSH_OPTIONS_SSH_DIR:
* Set the ssh directory (format string).
*
* - SSH_OPTIONS_SSH_DIR:
* Set the ssh directory (format string).\n
* \n
* If the value is NULL, the directory is set to the
* default ssh directory.
*
* default ssh directory.\n
* \n
* The ssh directory is used for files like known_hosts
* and identity (private and public key). It may include
* "%s" which will be replaced by the user home
* directory.
*
* SSH_OPTIONS_KNOWNHOSTS:
* Set the known hosts file name (format string).
*
* - SSH_OPTIONS_KNOWNHOSTS:
* Set the known hosts file name (format string).\n
* \n
* If the value is NULL, the directory is set to the
* default known hosts file, normally ~/.ssh/known_hosts.
*
* default known hosts file, normally
* ~/.ssh/known_hosts.\n
* \n
* The known hosts file is used to certify remote hosts
* are genuine. It may include "%s" which will be
* replaced by the user home directory.
*
* SSH_OPTIONS_IDENTITY:
* Set the identity file name (format string).
*
* By default identity, id_dsa and id_rsa are checked.
*
* - SSH_OPTIONS_IDENTITY:
* Set the identity file name (format string).\n
* \n
* By default identity, id_dsa and id_rsa are checked.\n
* \n
* The identity file used authenticate with public key.
* It may include "%s" which will be replaced by the
* user home directory.
*
* SSH_OPTIONS_TIMEOUT:
* - SSH_OPTIONS_TIMEOUT:
* Set a timeout for the connection in seconds (integer).
*
* SSH_OPTIONS_TIMEOUT_USEC:
* - SSH_OPTIONS_TIMEOUT_USEC:
* Set a timeout for the connection in micro seconds
* (integer).
*
* SSH_OPTIONS_SSH1:
* - SSH_OPTIONS_SSH1:
* Allow or deny the connection to SSH1 servers
* (integer).
*
* SSH_OPTIONS_SSH2:
* - SSH_OPTIONS_SSH2:
* Allow or deny the connection to SSH2 servers
* (integer).
*
* SSH_OPTIONS_LOG_VERBOSITY:
* Set the session logging verbosity (integer).
*
* - SSH_OPTIONS_LOG_VERBOSITY:
* Set the session logging verbosity (integer).\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_OPTIONS_LOG_VERBOSITY_STR:
* Set the session logging verbosity (string).
* - 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_OPTIONS_LOG_VERBOSITY_STR:
* Set the session logging verbosity (string).\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_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.
*
* SSH_OPTTIONS_AUTH_CALLBACK:
* - SSH_OPTTIONS_AUTH_CALLBACK:
* Set a callback to use your own authentication function
* (function pointer).
*
* SSH_OPTTIONS_AUTH_USERDATA:
* Set the user data passed to the authentication function
* (generic pointer).
* - SSH_OPTTIONS_AUTH_USERDATA:
* Set the user data passed to the authentication
* function (generic pointer).
*
* SSH_OPTTIONS_LOG_CALLBACK:
* - SSH_OPTTIONS_LOG_CALLBACK:
* Set a callback to use your own logging function
* (function pointer).
*
* SSH_OPTTIONS_LOG_USERDATA:
* - SSH_OPTTIONS_LOG_USERDATA:
* Set the user data passed to the logging function
* (generic pointer).
*
* SSH_OPTTIONS_STATUS_CALLBACK:
* - SSH_OPTTIONS_STATUS_CALLBACK:
* Set a callback to show connection status in realtime
* (function pointer).
*
* (function pointer).\n
* \n
* @code
* fn(void *arg, float status)
*
* @endcode
* \n
* During ssh_connect(), libssh will call the callback
* with status from 0.0 to 1.0.
*
* SSH_OPTTIONS_STATUS_ARG:
* - SSH_OPTTIONS_STATUS_ARG:
* Set the status argument which should be passed to the
* status callback (generic pointer).
*
* SSH_OPTIONS_CIPHERS_C_S:
* - SSH_OPTIONS_CIPHERS_C_S:
* Set the symmetric cipher client to server (string,
* comma-separated list).
*
* SSH_OPTIONS_CIPHERS_S_C:
* - SSH_OPTIONS_CIPHERS_S_C:
* Set the symmetric cipher server to client (string,
* comma-separated list).
*
* SSH_OPTIONS_COMPRESSION_C_S:
* - SSH_OPTIONS_COMPRESSION_C_S:
* Set the compression to use for client to server
* communication (string, "none" or "zlib").
*
* SSH_OPTIONS_COMPRESSION_S_C:
* - SSH_OPTIONS_COMPRESSION_S_C:
* Set the compression to use for server to client
* communication (string, "none" or "zlib").
*
* - SSH_OPTIONS_PROXYCOMMAND:
* Set the command to be executed in order to connect to
* server.
*
* @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.
@@ -366,6 +327,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
const void *value) {
char *p, *q;
long int i;
int rc;
if (session == NULL) {
return -1;
@@ -429,30 +391,35 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
session->port = i & 0xffff;
}
break;
case SSH_OPTIONS_FD:
if (value == NULL) {
session->fd = -1;
} else {
socket_t *x = (socket_t *) value;
session->fd = *x & 0xffff;
}
break;
case SSH_OPTIONS_BINDADDR:
if (value == NULL) {
ssh_set_error_invalid(session, __FUNCTION__);
return -1;
}
q = strdup(value);
if (q == NULL) {
return -1;
}
SAFE_FREE(session->bindaddr);
session->bindaddr = q;
break;
case SSH_OPTIONS_USER:
SAFE_FREE(session->username);
if (value == NULL) { /* set default username */
#ifdef _WIN32
DWORD size = 0;
GetUserName(NULL, &size); //Get Size
q = malloc(size);
if (q == NULL) {
ssh_set_error_oom(session);
return -1;
}
if (GetUserName(q, &size)) {
session->username = q;
} else {
SAFE_FREE(q);
return -1;
}
#else /* _WIN32 */
q = get_username_from_uid(session, getuid());
q = ssh_get_local_username(session);
if (q == NULL) {
return -1;
}
session->username = q;
#endif /* _WIN32 */
} else { /* username provided */
session->username = strdup(value);
if (session->username == NULL) {
@@ -464,43 +431,47 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
case SSH_OPTIONS_SSH_DIR:
if (value == NULL) {
SAFE_FREE(session->sshdir);
/* TODO: why ~/.ssh/ instead of ~/.ssh ? */
session->sshdir = dir_expand_dup(session, "~/.ssh/", 0);
session->sshdir = ssh_path_expand_tilde("~/.ssh/");
if (session->sshdir == NULL) {
return -1;
}
} else {
SAFE_FREE(session->sshdir);
session->sshdir = dir_expand_dup(session, value, 0);
session->sshdir = ssh_path_expand_tilde(value);
if (session->sshdir == NULL) {
return -1;
}
}
break;
case SSH_OPTIONS_IDENTITY:
case SSH_OPTIONS_ADD_IDENTITY:
if (value == NULL) {
ssh_set_error_invalid(session, __FUNCTION__);
return -1;
}
SAFE_FREE(session->identity);
session->identity = dir_expand_dup(session, value, 1);
if (session->identity == NULL) {
q = strdup(value);
if (q == NULL) {
return -1;
}
rc = ssh_list_prepend(session->identity, q);
if (rc < 0) {
return -1;
}
break;
case SSH_OPTIONS_KNOWNHOSTS:
if (value == NULL) {
SAFE_FREE(session->knownhosts);
session->knownhosts = dir_expand_dup(session,
"SSH_DIR/known_hosts", 1);
if (session->sshdir == NULL) {
return -1;
}
session->knownhosts = ssh_path_expand_escape(session, "%d/known_hosts");
if (session->knownhosts == NULL) {
return -1;
}
} else {
SAFE_FREE(session->knownhosts);
session->knownhosts = dir_expand_dup(session, value, 1);
session->knownhosts = strdup(value);
if (session->knownhosts == NULL) {
return -1;
}
@@ -608,16 +579,34 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
return -1;
}
break;
case SSH_OPTIONS_PROXYCOMMAND:
if (value == NULL) {
ssh_set_error_invalid(session, __FUNCTION__);
return -1;
} else {
SAFE_FREE(session->ProxyCommand);
q = strdup(value);
if (q == NULL) {
return -1;
}
session->ProxyCommand = q;
}
break;
default:
ssh_set_error(session, SSH_REQUEST_DENIED, "Unkown ssh option %d", type);
ssh_set_error(session, SSH_REQUEST_DENIED, "Unknown ssh option %d", type);
return -1;
break;
}
return 0;
}
/** @} */
#ifdef WITH_SERVER
/**
* @addtogroup ssh_server
* @{
*/
static int ssh_bind_options_set_algo(ssh_bind sshbind, int algo,
const char *list) {
if (!verify_existing_algo(algo, list)) {
@@ -818,7 +807,7 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
}
break;
default:
ssh_set_error(sshbind, SSH_REQUEST_DENIED, "Unkown ssh option %d", type);
ssh_set_error(sshbind, SSH_REQUEST_DENIED, "Unknown ssh option %d", type);
return -1;
break;
}
@@ -1041,19 +1030,91 @@ int ssh_options_parse_config(ssh_session session, const char *filename) {
return -1;
}
if (session->sshdir == NULL) {
r = ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL);
if (r < 0) {
ssh_set_error_oom(session);
return -1;
}
}
/* set default filename */
if (filename == NULL) {
expanded_filename = dir_expand_dup(session, "SSH_DIR/config", 1);
expanded_filename = ssh_path_expand_escape(session, "%d/config");
} else {
expanded_filename = dir_expand_dup(session, filename, 1);
expanded_filename = ssh_path_expand_escape(session, filename);
}
if (expanded_filename == NULL)
if (expanded_filename == NULL) {
return -1;
}
r = ssh_config_parse_file(session, expanded_filename);
if (r < 0) {
goto out;
}
if (filename == NULL) {
r = ssh_config_parse_file(session, "/etc/ssh/ssh_config");
}
out:
free(expanded_filename);
return r;
}
/** @} */
/* vim: set ts=2 sw=2 et cindent: */
int ssh_options_apply(ssh_session session) {
struct ssh_iterator *it;
char *tmp;
int rc;
if (session->sshdir == NULL) {
rc = ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL);
if (rc < 0) {
return -1;
}
}
if (session->username == NULL) {
rc = ssh_options_set(session, SSH_OPTIONS_USER, NULL);
if (rc < 0) {
return -1;
}
}
if (session->knownhosts == NULL) {
tmp = ssh_path_expand_escape(session, "%d/known_hosts");
} else {
tmp = ssh_path_expand_escape(session, session->knownhosts);
}
if (tmp == NULL) {
return -1;
}
free(session->knownhosts);
session->knownhosts = tmp;
if (session->ProxyCommand != NULL) {
tmp = ssh_path_expand_escape(session, session->ProxyCommand);
if (tmp == NULL) {
return -1;
}
free(session->ProxyCommand);
session->ProxyCommand = tmp;
}
for (it = ssh_list_get_iterator(session->identity);
it != NULL;
it = it->next) {
char *id = (char *) it->data;
tmp = ssh_path_expand_escape(session, id);
if (tmp == NULL) {
return -1;
}
free(id);
it->data = tmp;
}
return 0;
}
/* @} */
/* vim: set ts=4 sw=4 et cindent: */

View File

@@ -693,6 +693,9 @@ void packet_parse(ssh_session session) {
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);
}
@@ -779,6 +782,7 @@ static int packet_wait2(ssh_session session, int type, int blocking) {
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:

View File

@@ -30,7 +30,9 @@
#ifdef WITH_PCAP
#include <stdio.h>
#ifndef _WIN32
#ifdef _WIN32
#include <ws2tcpip.h>
#else
#include <sys/time.h>
#include <sys/socket.h>
#endif
@@ -91,7 +93,7 @@ struct ssh_pcap_context_struct {
ssh_session session;
ssh_pcap_file file;
int connected;
/* All of these informations are useful to generate
/* All of these information are useful to generate
* the dummy IP and TCP packets
*/
uint32_t ipsource;

View File

@@ -3,6 +3,7 @@
*
* This file is part of the SSH Library
*
* Copyright (c) 2009-2010 by Andreas Schneider <mail@cynapses.org>
* Copyright (c) 2003-2009 by Aris Adamantiadis
* Copyright (c) 2009 Aleksandar Kanchev
*
@@ -24,8 +25,6 @@
* vim: ts=2 sw=2 et cindent
*/
/* This code is based on glib's gpoll */
#include "config.h"
#include <errno.h>
@@ -60,177 +59,217 @@ struct ssh_poll_ctx_struct {
#ifdef HAVE_POLL
#include <poll.h>
void ssh_poll_init(void) {
return;
}
void ssh_poll_cleanup(void) {
return;
}
int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
return poll((struct pollfd *) fds, nfds, timeout);
}
#else /* HAVE_POLL */
typedef int (*poll_fn)(ssh_pollfd_t *, nfds_t, int);
static poll_fn ssh_poll_emu;
#include <sys/types.h>
#ifdef _WIN32
#if 0
/* defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) */
#include <winsock2.h>
int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
return WSAPoll(fds, nfds, timeout);
}
#else /* _WIN32_WINNT */
#ifndef STRICT
#define STRICT
#endif
#endif /* STRICT */
#include <stdio.h>
#include <time.h>
#include <windows.h>
#include <errno.h>
#include <winsock2.h>
static int poll_rest (HANDLE *handles, int nhandles,
ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
DWORD ready;
ssh_pollfd_t *f;
int recursed_result;
if (nhandles == 0) {
/* No handles to wait for, just the timeout */
if (timeout == INFINITE) {
ready = WAIT_FAILED;
} else {
SleepEx(timeout, 1);
ready = WAIT_TIMEOUT;
}
} else {
/* Wait for just handles */
ready = WaitForMultipleObjectsEx(nhandles, handles, FALSE, timeout, TRUE);
#if 0
if (ready == WAIT_FAILED) {
fprintf(stderr, "WaitForMultipleObjectsEx failed: %d\n", GetLastError());
}
#if (_WIN32_WINNT < 0x0600)
typedef struct ssh_pollfd_struct WSAPOLLFD;
#endif
}
if (ready == WAIT_FAILED) {
return -1;
} else if (ready == WAIT_TIMEOUT || ready == WAIT_IO_COMPLETION) {
return 0;
} else if (ready >= WAIT_OBJECT_0 && ready < WAIT_OBJECT_0 + nhandles) {
for (f = fds; f < &fds[nfds]; f++) {
if ((HANDLE) f->fd == handles[ready - WAIT_OBJECT_0]) {
f->revents = f->events;
}
typedef int (WSAAPI* WSAPoll_FunctionType)(WSAPOLLFD fdarray[],
ULONG nfds,
INT timeout
);
static WSAPoll_FunctionType wsa_poll;
int win_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
if (wsa_poll) {
return (wsa_poll)(fds, nfds, timeout);
}
/*
* If no timeout and polling several handles, recurse to poll
* the rest of them.
*/
if (timeout == 0 && nhandles > 1) {
/* Remove the handle that fired */
int i;
if (ready < nhandles - 1) {
for (i = ready - WAIT_OBJECT_0 + 1; i < nhandles; i++) {
handles[i-1] = handles[i];
}
}
nhandles--;
recursed_result = poll_rest(handles, nhandles, fds, nfds, 0);
if (recursed_result < 0) {
return -1;
}
return recursed_result + 1;
}
return 1;
}
return 0;
return SOCKET_ERROR;
}
int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
ssh_pollfd_t *f;
int nhandles = 0;
int rc = -1;
#define WS2_LIBRARY "ws2_32.dll"
static HINSTANCE hlib;
#else /* _WIN32 */
#include <sys/select.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/time.h>
#endif /* _WIN32 */
/*
* This is a poll(2)-emulation using select for systems not providing a native
* poll implementation.
*
* Keep in mind that select is terribly inefficient. The interface is simply not
* meant to be used with maximum descriptor value greater, say, 32 or so. With
* a value as high as 1024 on Linux you'll pay dearly in every single call.
* poll() will be orders of magnitude faster.
*/
static int bsd_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
fd_set readfds, writefds, exceptfds;
struct timeval tv, *ptv;
socket_t max_fd;
int rc;
nfds_t i;
if (fds == NULL) {
errno = EFAULT;
return -1;
errno = EFAULT;
return -1;
}
if (nfds >= MAXIMUM_WAIT_OBJECTS) {
errno = EINVAL;
return -1;
}
FD_ZERO (&readfds);
FD_ZERO (&writefds);
FD_ZERO (&exceptfds);
for (f = fds; f < &fds[nfds]; f++) {
if (f->fd > 0) {
int i;
/*
* Don't add the same handle several times into the array, as
* docs say that is not allowed, even if it actually does seem
* to work.
*/
for (i = 0; i < nhandles; i++) {
if (handles[i] == (HANDLE) f->fd) {
break;
}
/* compute fd_sets and find largest descriptor */
for (rc = -1, max_fd = 0, i = 0; i < nfds; i++) {
if (fds[i].fd == SSH_INVALID_SOCKET) {
continue;
}
if (i == nhandles) {
if (nhandles == MAXIMUM_WAIT_OBJECTS) {
#ifndef _WIN32
if (fds[i].fd >= FD_SETSIZE) {
rc = -1;
break;
} else {
handles[nhandles++] = (HANDLE) f->fd;
}
}
}
#endif
if (fds[i].events & (POLLIN | POLLRDNORM)) {
FD_SET (fds[i].fd, &readfds);
}
if (fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
FD_SET (fds[i].fd, &writefds);
}
if (fds[i].events & (POLLPRI | POLLRDBAND)) {
FD_SET (fds[i].fd, &exceptfds);
}
if (fds[i].fd > max_fd &&
(fds[i].events & (POLLIN | POLLOUT | POLLPRI |
POLLRDNORM | POLLRDBAND |
POLLWRNORM | POLLWRBAND))) {
max_fd = fds[i].fd;
rc = 0;
}
}
if (timeout == -1) {
timeout = INFINITE;
if (max_fd == SSH_INVALID_SOCKET || rc == -1) {
errno = EINVAL;
return -1;
}
if (nhandles > 1) {
/*
* First check if one or several of them are immediately
* available.
*/
rc = poll_rest(handles, nhandles, fds, nfds, 0);
/*
* If not, and we have a significant timeout, poll again with
* timeout then. Note that this will return indication for only
* one event, or only for messages. We ignore timeouts less than
* ten milliseconds as they are mostly pointless on Windows, the
* MsgWaitForMultipleObjectsEx() call will timeout right away
* anyway.
*/
if (rc == 0 && (timeout == INFINITE || timeout >= 10)) {
rc = poll_rest(handles, nhandles, fds, nfds, timeout);
}
if (timeout < 0) {
ptv = NULL;
} else {
/*
* Just polling for one thing, so no need to check first if
* available immediately
*/
rc = poll_rest(handles, nhandles, fds, nfds, timeout);
ptv = &tv;
if (timeout == 0) {
tv.tv_sec = 0;
tv.tv_usec = 0;
} else {
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
}
}
rc = select (max_fd + 1, &readfds, &writefds, &exceptfds, ptv);
if (rc < 0) {
for (f = fds; f < &fds[nfds]; f++) {
f->revents = 0;
}
errno = EBADF;
return -1;
}
for (rc = 0, i = 0; i < nfds; i++)
if (fds[i].fd >= 0) {
fds[i].revents = 0;
if (FD_ISSET(fds[i].fd, &readfds)) {
int save_errno = errno;
char data[64] = {0};
int ret;
/* support for POLLHUP */
ret = recv(fds[i].fd, data, 64, MSG_PEEK);
#ifdef _WIN32
if ((ret == -1) &&
(errno == WSAESHUTDOWN || errno == WSAECONNRESET ||
errno == WSAECONNABORTED || errno == WSAENETRESET)) {
#else
if ((ret == -1) &&
(errno == ESHUTDOWN || errno == ECONNRESET ||
errno == ECONNABORTED || errno == ENETRESET)) {
#endif
fds[i].revents |= POLLHUP;
} else {
fds[i].revents |= fds[i].events & (POLLIN | POLLRDNORM);
}
errno = save_errno;
}
if (FD_ISSET(fds[i].fd, &writefds)) {
fds[i].revents |= fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND);
}
if (FD_ISSET(fds[i].fd, &exceptfds)) {
fds[i].revents |= fds[i].events & (POLLPRI | POLLRDBAND);
}
if (fds[i].revents & ~POLLHUP) {
rc++;
}
} else {
fds[i].revents = POLLNVAL;
}
return rc;
}
#endif /* _WIN32_WINNT */
void ssh_poll_init(void) {
ssh_poll_emu = bsd_poll;
#ifdef _WIN32
hlib = LoadLibrary(WS2_LIBRARY);
if (hlib != NULL) {
wsa_poll = (WSAPoll_FunctionType) (void *) GetProcAddress(hlib, "WSAPoll");
}
#endif /* _WIN32 */
if (wsa_poll != NULL) {
ssh_poll_emu = bsd_poll;
}
}
void ssh_poll_cleanup(void) {
ssh_poll_emu = bsd_poll;
#ifdef _WIN32
wsa_poll = NULL;
FreeLibrary(hlib);
hlib = NULL;
#endif /* _WIN32 */
}
int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
return (ssh_poll_emu)(fds, nfds, timeout);
}
#endif /* HAVE_POLL */
/**
@@ -403,7 +442,7 @@ void ssh_poll_ctx_free(ssh_poll_ctx ctx) {
used = ctx->polls_used;
for (i = 0; i < used; ) {
ssh_poll_handle p = ctx->pollptrs[i];
int fd = ctx->pollfds[i].fd;
socket_t fd = ctx->pollfds[i].fd;
/* force poll object removal */
if (p->cb(p, fd, POLLERR, p->cb_data) < 0) {
@@ -451,7 +490,7 @@ static int ssh_poll_ctx_resize(ssh_poll_ctx ctx, size_t new_size) {
* @return 0 on success, < 0 on error
*/
int ssh_poll_ctx_add(ssh_poll_ctx ctx, ssh_poll_handle p) {
int fd;
socket_t fd;
if (p->ctx != NULL) {
/* already attached to a context */
@@ -530,7 +569,7 @@ int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout) {
i++;
} else {
ssh_poll_handle p = ctx->pollptrs[i];
int fd = ctx->pollfds[i].fd;
socket_t fd = ctx->pollfds[i].fd;
int revents = ctx->pollfds[i].revents;
if (p->cb(p, fd, revents, p->cb_data) < 0) {

View File

@@ -26,11 +26,18 @@
#include "libssh/priv.h"
#include "libssh/scp.h"
/** @defgroup ssh_scp SSH-scp
* @brief SCP protocol over SSH functions
* @addtogroup ssh_scp
* @{
*/
/** @brief Creates a new scp session
* @param session the SSH session to use
* @param mode one of SSH_SCP_WRITE or SSH_SCP_READ, depending if you need to drop files remotely or read them.
* It is not possible to combine read and write.
* @param location The directory in which write or read will be done. Any push or pull will be relative
* to this place
* @returns NULL if the creation was impossible.
* @returns a ssh_scp handle if it worked.
*/
@@ -110,11 +117,22 @@ int ssh_scp_init(ssh_scp scp){
}
int ssh_scp_close(ssh_scp scp){
char buffer[128];
int err;
if(scp->channel != NULL){
if(channel_send_eof(scp->channel) == SSH_ERROR){
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
/* avoid situations where data are buffered and
* not yet stored on disk. This can happen if the close is sent
* before we got the EOF back
*/
while(!channel_is_eof(scp->channel)){
err=channel_read(scp->channel,buffer,sizeof(buffer),0);
if(err==SSH_ERROR)
break;
}
if(channel_close(scp->channel) == SSH_ERROR){
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
@@ -138,6 +156,7 @@ void ssh_scp_free(ssh_scp scp){
}
/** @brief creates a directory in a scp in sink mode
* @param scp the scp handle.
* @param dirname Name of the directory being created.
* @param mode Unix permissions for the new directory, e.g. 0755.
* @returns SSH_OK if the directory was created.
@@ -203,6 +222,7 @@ int ssh_scp_push_directory(ssh_scp scp, const char *dirname, int mode){
/** @brief initializes the sending of a file to a scp in sink mode
* @param scp the scp handle.
* @param filename Name of the file being sent. It should not contain any path indicator
* @param size Exact size in bytes of the file being sent.
* @param mode Unix permissions for the new file, e.g. 0644
@@ -285,6 +305,7 @@ int ssh_scp_response(ssh_scp scp, char **response){
}
/** @brief Write into a remote scp file
* @param scp the scp handle.
* @param buffer the buffer to write
* @param len the number of bytes to write
* @returns SSH_OK the write was successful
@@ -331,6 +352,7 @@ int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len){
/**
* @brief reads a string on a channel, terminated by '\n'
* @param scp the scp handle.
* @param buffer pointer to a buffer to place the string
* @param len size of the buffer in bytes. If the string is bigger
* than len-1, only len-1 bytes are read and the string
@@ -455,6 +477,7 @@ int ssh_scp_pull_request(ssh_scp scp){
/**
* @brief denies the transfer of a file or creation of a directory
* coming from the remote party
* @param scp the scp handle.
* @param reason nul-terminated string with a human-readable explanation
* of the deny
* @returns SSH_OK the message was sent
@@ -481,6 +504,7 @@ int ssh_scp_deny_request(ssh_scp scp, const char *reason){
/**
* @brief accepts transfer of a file or creation of a directory
* coming from the remote party
* @param scp the scp handle.
* @returns SSH_OK the message was sent
* @returns SSH_ERROR Error sending the message, or sending it in a bad state
*/
@@ -503,6 +527,7 @@ int ssh_scp_accept_request(ssh_scp scp){
}
/** @brief Read from a remote scp file
* @param scp the scp handle.
* @param buffer Destination buffer
* @param size Size of the buffer
* @returns Number of bytes read
@@ -585,7 +610,7 @@ int ssh_scp_integer_mode(const char *mode){
/** @brief Converts a unix mode into a scp string one.
* @param mode mode to convert, e.g. 420 or 0644
* @retuns pointer to a malloc'ed string containing the scp mode,
* @returns pointer to a malloc'ed string containing the scp mode,
* e.g. "0644".
*/
char *ssh_scp_string_mode(int mode){
@@ -601,3 +626,6 @@ char *ssh_scp_string_mode(int mode){
const char *ssh_scp_request_get_warning(ssh_scp scp){
return scp->warning;
}
/** @} */

View File

@@ -129,7 +129,7 @@ ssh_bind ssh_bind_new(void) {
return NULL;
}
ZERO_STRUCTP(ptr);
ptr->bindfd = -1;
ptr->bindfd = SSH_INVALID_SOCKET;
ptr->bindport= 22;
ptr->log_verbosity = 0;
@@ -138,7 +138,7 @@ ssh_bind ssh_bind_new(void) {
int ssh_bind_listen(ssh_bind sshbind) {
const char *host;
int fd;
socket_t fd;
if (ssh_init() < 0) {
return -1;
@@ -185,10 +185,10 @@ void ssh_bind_fd_toaccept(ssh_bind sshbind) {
int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
ssh_private_key dsa = NULL;
ssh_private_key rsa = NULL;
int fd = -1;
socket_t fd = SSH_INVALID_SOCKET;
int i;
if (sshbind->bindfd < 0) {
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;
@@ -219,7 +219,7 @@ int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
}
fd = accept(sshbind->bindfd, NULL, NULL);
if (fd < 0) {
if (fd == SSH_INVALID_SOCKET) {
ssh_set_error(sshbind, SSH_FATAL,
"Accepting a new connection: %s",
strerror(errno));
@@ -246,6 +246,7 @@ int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
if (sshbind->bindaddr == NULL)
session->bindaddr = NULL;
else {
SAFE_FREE(session->bindaddr);
session->bindaddr = strdup(sshbind->bindaddr);
if (session->bindaddr == NULL) {
privatekey_free(dsa);
@@ -278,9 +279,13 @@ void ssh_bind_free(ssh_bind sshbind){
}
if (sshbind->bindfd >= 0) {
#ifdef _WIN32
closesocket(sshbind->bindfd);
#else
close(sshbind->bindfd);
#endif
}
sshbind->bindfd = -1;
sshbind->bindfd = SSH_INVALID_SOCKET;
/* options */
SAFE_FREE(sshbind->banner);
@@ -867,7 +872,7 @@ int ssh_execute_message_callbacks(ssh_session session){
if(!session->ssh_message_list)
return SSH_OK;
if(session->ssh_message_callback){
while((msg=ssh_list_get_head(ssh_message , session->ssh_message_list)) != NULL){
while((msg=ssh_list_pop_head(ssh_message , session->ssh_message_list)) != NULL){
ret=session->ssh_message_callback(session,msg);
if(ret==1){
ret = ssh_message_reply_default(msg);
@@ -876,7 +881,7 @@ int ssh_execute_message_callbacks(ssh_session session){
}
}
} else {
while((msg=ssh_list_get_head(ssh_message , session->ssh_message_list)) != NULL){
while((msg=ssh_list_pop_head(ssh_message , session->ssh_message_list)) != NULL){
ret = ssh_message_reply_default(msg);
if(ret != SSH_OK)
return ret;

View File

@@ -32,7 +32,8 @@
#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
@@ -46,6 +47,8 @@
*/
ssh_session ssh_new(void) {
ssh_session session;
char *id;
int rc;
session = malloc(sizeof (struct ssh_session_struct));
if (session == NULL) {
@@ -95,6 +98,39 @@ ssh_session ssh_new(void) {
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:
@@ -117,6 +153,7 @@ void ssh_free(ssh_session session) {
SAFE_FREE(session->serverbanner);
SAFE_FREE(session->clientbanner);
SAFE_FREE(session->bindaddr);
SAFE_FREE(session->banner);
#ifdef WITH_PCAP
if(session->pcap_ctx){
@@ -155,19 +192,30 @@ void ssh_free(ssh_session session) {
privatekey_free(session->rsa_key);
if(session->ssh_message_list){
ssh_message msg;
while((msg=ssh_list_get_head(ssh_message ,session->ssh_message_list))
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->identity);
SAFE_FREE(session->sshdir);
SAFE_FREE(session->knownhosts);
SAFE_FREE(session->ProxyCommand);
for (i = 0; i < 10; i++) {
if (session->wanted_methods[i]) {
@@ -363,5 +411,32 @@ int ssh_get_version(ssh_session session) {
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

@@ -25,9 +25,11 @@
/* This file contains code written by Nick Zitzmann */
#include <errno.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -1111,6 +1113,54 @@ static sftp_attributes sftp_parse_attr_4(sftp_session sftp, ssh_buffer buf,
return attr;
}
enum sftp_longname_field_e {
SFTP_LONGNAME_PERM = 0,
SFTP_LONGNAME_FIXME,
SFTP_LONGNAME_OWNER,
SFTP_LONGNAME_GROUP,
SFTP_LONGNAME_SIZE,
SFTP_LONGNAME_DATE,
SFTP_LONGNAME_TIME,
SFTP_LONGNAME_NAME,
};
static char *sftp_parse_longname(const char *longname,
enum sftp_longname_field_e longname_field) {
const char *p, *q;
size_t len, field = 0;
char *x;
p = longname;
/* Find the beginning of the field which is specified by sftp_longanme_field_e. */
while(field != longname_field) {
if(isspace(*p)) {
field++;
p++;
while(*p && isspace(*p)) {
p++;
}
} else {
p++;
}
}
q = p;
while (! isspace(*q)) {
q++;
}
/* There is no strndup on windows */
len = q - p + 1;
x = malloc(len);
if (x == NULL) {
return NULL;
}
snprintf(x, len, "%s", p);
return x;
}
/* sftp version 0-3 code. It is different from the v4 */
/* maybe a paste of the draft is better than the code */
/*
@@ -1157,6 +1207,19 @@ static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf,
break;
}
string_free(longname);
/* Set owner and group if we talk to openssh and have the longname */
if (ssh_get_openssh_version(sftp->session)) {
attr->owner = sftp_parse_longname(attr->longname, SFTP_LONGNAME_OWNER);
if (attr->owner == NULL) {
break;
}
attr->group = sftp_parse_longname(attr->longname, SFTP_LONGNAME_GROUP);
if (attr->group == NULL) {
break;
}
}
}
if (buffer_get_u32(buf, &flags) != sizeof(uint32_t)) {
@@ -1254,6 +1317,8 @@ static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf,
string_free(attr->extended_data);
SAFE_FREE(attr->name);
SAFE_FREE(attr->longname);
SAFE_FREE(attr->owner);
SAFE_FREE(attr->group);
SAFE_FREE(attr);
ssh_set_error(sftp->session, SSH_FATAL, "Invalid ATTR structure");
@@ -2276,8 +2341,9 @@ int sftp_rename(sftp_session sftp, const char *original, const char *newname) {
if (buffer_add_u32(buffer, id) < 0 ||
buffer_add_ssh_string(buffer, oldpath) < 0 ||
buffer_add_ssh_string(buffer, newpath) < 0 ||
/* POSIX rename atomically replaces newpath, we should do the same */
buffer_add_u32(buffer, SSH_FXF_RENAME_OVERWRITE) < 0) {
/* POSIX rename atomically replaces newpath, we should do the same
* only available on >=v4 */
sftp->version>=4 ? (buffer_add_u32(buffer, SSH_FXF_RENAME_OVERWRITE) < 0):0) {
ssh_set_error_oom(sftp->session);
buffer_free(buffer);
string_free(oldpath);
@@ -2419,7 +2485,8 @@ int sftp_chown(sftp_session sftp, const char *file, uid_t owner, gid_t group) {
attr.uid = owner;
attr.gid = group;
attr.flags = SSH_FILEXFER_ATTR_OWNERGROUP;
attr.flags = SSH_FILEXFER_ATTR_UIDGID;
return sftp_setstat(sftp, file, &attr);
}
@@ -3056,7 +3123,10 @@ static sftp_attributes sftp_xstat(sftp_session sftp, const char *path,
}
if (msg->packet_type == SSH_FXP_ATTRS) {
return sftp_parse_attr(sftp, msg->payload, 0);
sftp_attributes attr = sftp_parse_attr(sftp, msg->payload, 0);
sftp_message_free(msg);
return attr;
} else if (msg->packet_type == SSH_FXP_STATUS) {
status = parse_status_msg(msg);
sftp_message_free(msg);

View File

@@ -27,11 +27,13 @@
#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"
@@ -39,6 +41,7 @@
#include "libssh/poll.h"
#include "libssh/session.h"
/** \defgroup ssh_socket SSH Sockets
* \addtogroup ssh_socket
* @{
@@ -68,10 +71,21 @@ int ssh_socket_init(void) {
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
*/
@@ -82,7 +96,7 @@ struct socket *ssh_socket_new(ssh_session session) {
if (s == NULL) {
return NULL;
}
s->fd = -1;
s->fd = SSH_INVALID_SOCKET;
s->last_errno = -1;
s->session = session;
s->in_buffer = buffer_new();
@@ -124,20 +138,20 @@ int ssh_socket_unix(struct socket *s, const char *path) {
snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path), "%s", path);
s->fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (s->fd < 0) {
if (s->fd == SSH_INVALID_SOCKET) {
return -1;
}
if (fcntl(s->fd, F_SETFD, 1) == -1) {
close(s->fd);
s->fd = -1;
s->fd = SSH_INVALID_SOCKET;
return -1;
}
if (connect(s->fd, (struct sockaddr *) &sunaddr,
sizeof(sunaddr)) < 0) {
close(s->fd);
s->fd = -1;
s->fd = SSH_INVALID_SOCKET;
return -1;
}
@@ -157,7 +171,7 @@ void ssh_socket_close(struct socket *s){
close(s->fd);
s->last_errno = errno;
#endif
s->fd=-1;
s->fd = SSH_INVALID_SOCKET;
}
}
@@ -179,7 +193,7 @@ socket_t ssh_socket_get_fd(struct socket *s) {
* \brief returns nonzero if the socket is open
*/
int ssh_socket_is_open(struct socket *s) {
return s->fd != -1;
return s->fd != SSH_INVALID_SOCKET;
}
/* \internal
@@ -237,22 +251,25 @@ static int ssh_socket_unbuffered_write(struct socket *s, const void *buffer,
* \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 == -1) {
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 fd_max
* \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, int *fd_max) {
if (s->fd == -1)
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 >= *fd_max) {
*fd_max = s->fd + 1;
if (s->fd >= 0 &&
s->fd >= *max_fd &&
s->fd != SSH_INVALID_SOCKET) {
*max_fd = s->fd + 1;
}
}
@@ -435,7 +452,7 @@ int ssh_socket_wait_for_data(struct socket *s, ssh_session session, uint32_t len
if (ssh_socket_is_open(session->socket)) {
r = ssh_socket_unbuffered_read(session->socket, buffer, sizeof(buffer));
} else {
r =- 1;
r = -1;
}
if (r <= 0) {
@@ -475,6 +492,7 @@ int ssh_socket_poll(struct socket *s, int *writeable, int *except) {
fd->fd = s->fd;
fd->events = 0;
fd->revents = 0;
if (!s->data_to_read) {
fd->events |= POLLIN;
@@ -482,13 +500,15 @@ int ssh_socket_poll(struct socket *s, int *writeable, int *except) {
if (!s->data_to_write) {
fd->events |= POLLOUT;
}
/* 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;
/* 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) {
@@ -542,7 +562,7 @@ int ssh_socket_nonblocking_flush(struct socket *s) {
buffer_get_rest_len(s->out_buffer));
} else {
/* write failed */
w =- 1;
w = -1;
}
if (w < 0) {
@@ -658,6 +678,54 @@ int ssh_socket_get_status(struct socket *s) {
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

@@ -157,29 +157,31 @@ static void blowfish_decrypt(struct crypto_struct *cipher, void *in,
}
static int aes_set_key(struct crypto_struct *cipher, void *key, void *IV) {
int mode=GCRY_CIPHER_MODE_CBC;
if (cipher->key == NULL) {
if (alloc_key(cipher) < 0) {
return -1;
}
if(strstr(cipher->name,"-ctr"))
mode=GCRY_CIPHER_MODE_CTR;
switch (cipher->keysize) {
case 128:
if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_AES128,
GCRY_CIPHER_MODE_CBC, 0)) {
mode, 0)) {
SAFE_FREE(cipher->key);
return -1;
}
break;
case 192:
if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_AES192,
GCRY_CIPHER_MODE_CBC, 0)) {
mode, 0)) {
SAFE_FREE(cipher->key);
return -1;
}
break;
case 256:
if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_AES256,
GCRY_CIPHER_MODE_CBC, 0)) {
mode, 0)) {
SAFE_FREE(cipher->key);
return -1;
}
@@ -189,9 +191,17 @@ static int aes_set_key(struct crypto_struct *cipher, void *key, void *IV) {
SAFE_FREE(cipher->key);
return -1;
}
if (gcry_cipher_setiv(cipher->key[0], IV, 16)) {
SAFE_FREE(cipher->key);
return -1;
if(mode == GCRY_CIPHER_MODE_CBC){
if (gcry_cipher_setiv(cipher->key[0], IV, 16)) {
SAFE_FREE(cipher->key);
return -1;
}
} else {
if(gcry_cipher_setctr(cipher->key[0],IV,16)){
SAFE_FREE(cipher->key);
return -1;
}
}
}
@@ -319,6 +329,39 @@ static struct crypto_struct ssh_ciphertab[] = {
.cbc_encrypt = blowfish_encrypt,
.cbc_decrypt = blowfish_decrypt
},
{
.name = "aes128-ctr",
.blocksize = 16,
.keylen = sizeof(gcry_cipher_hd_t),
.key = NULL,
.keysize = 128,
.set_encrypt_key = aes_set_key,
.set_decrypt_key = aes_set_key,
.cbc_encrypt = aes_encrypt,
.cbc_decrypt = aes_encrypt
},
{
.name = "aes192-ctr",
.blocksize = 16,
.keylen = sizeof(gcry_cipher_hd_t),
.key = NULL,
.keysize = 192,
.set_encrypt_key = aes_set_key,
.set_decrypt_key = aes_set_key,
.cbc_encrypt = aes_encrypt,
.cbc_decrypt = aes_encrypt
},
{
.name = "aes256-ctr",
.blocksize = 16,
.keylen = sizeof(gcry_cipher_hd_t),
.key = NULL,
.keysize = 256,
.set_encrypt_key = aes_set_key,
.set_decrypt_key = aes_set_key,
.cbc_encrypt = aes_encrypt,
.cbc_decrypt = aes_encrypt
},
{
.name = "aes128-cbc",
.blocksize = 16,
@@ -570,6 +613,30 @@ static void aes_decrypt(struct crypto_struct *cipher, void *in, void *out,
unsigned long len, void *IV) {
AES_cbc_encrypt(in, out, len, cipher->key, IV, AES_DECRYPT);
}
#ifndef BROKEN_AES_CTR
/* OpenSSL until 0.9.7c has a broken AES_ctr128_encrypt implementation which
* increments the counter from 2^64 instead of 1. It's better not to use it
*/
/** @internal
* @brief encrypts/decrypts data with stream cipher AES_ctr128. 128 bits is actually
* the size of the CTR counter and incidentally the blocksize, but not the keysize.
* @param len[in] must be a multiple of AES128 block size.
*/
static void aes_ctr128_encrypt(struct crypto_struct *cipher, void *in, void *out,
unsigned long len, void *IV) {
unsigned char tmp_buffer[128/8];
unsigned int num=0;
/* Some things are special with ctr128 :
* In this case, tmp_buffer is not being used, because it is used to store temporary data
* when an encryption is made on lengths that are not multiple of blocksize.
* Same for num, which is being used to store the current offset in blocksize in CTR
* function.
*/
AES_ctr128_encrypt(in, out, len, cipher->key, IV, tmp_buffer, &num);
}
#endif /* BROKEN_AES_CTR */
#endif /* HAS_AES */
#ifdef HAS_DES
@@ -661,6 +728,41 @@ static struct crypto_struct ssh_ciphertab[] = {
},
#endif /* HAS_BLOWFISH */
#ifdef HAS_AES
#ifndef BROKEN_AES_CTR
{
"aes128-ctr",
16,
sizeof(AES_KEY),
NULL,
128,
aes_set_encrypt_key,
aes_set_encrypt_key,
aes_ctr128_encrypt,
aes_ctr128_encrypt
},
{
"aes192-ctr",
16,
sizeof(AES_KEY),
NULL,
192,
aes_set_encrypt_key,
aes_set_encrypt_key,
aes_ctr128_encrypt,
aes_ctr128_encrypt
},
{
"aes256-ctr",
16,
sizeof(AES_KEY),
NULL,
256,
aes_set_encrypt_key,
aes_set_encrypt_key,
aes_ctr128_encrypt,
aes_ctr128_encrypt
},
#endif /* BROKEN_AES_CTR */
{
"aes128-cbc",
16,
@@ -907,7 +1009,8 @@ int crypt_set_algorithms_server(ssh_session session){
/* out */
server = session->server_kex.methods[SSH_CRYPT_S_C];
client = session->client_kex.methods[SSH_CRYPT_S_C];
match = ssh_find_matching(client, server);
/* That's the client algorithms that are more important */
match = ssh_find_matching(server,client);
if(!match){
ssh_set_error(session,SSH_FATAL,"Crypt_set_algorithms_server : no matching algorithm function found for %s",server);
@@ -936,7 +1039,7 @@ int crypt_set_algorithms_server(ssh_session session){
/* in */
client=session->client_kex.methods[SSH_CRYPT_C_S];
server=session->server_kex.methods[SSH_CRYPT_S_C];
match=ssh_find_matching(client,server);
match=ssh_find_matching(server,client);
if(!match){
ssh_set_error(session,SSH_FATAL,"Crypt_set_algorithms_server : no matching algorithm function found for %s",server);
free(match);
@@ -964,7 +1067,7 @@ int crypt_set_algorithms_server(ssh_session session){
/* compression */
client=session->client_kex.methods[SSH_CRYPT_C_S];
server=session->server_kex.methods[SSH_CRYPT_C_S];
match=ssh_find_matching(client,server);
match=ssh_find_matching(server,client);
if(match && !strcmp(match,"zlib")){
ssh_log(session,SSH_LOG_PACKET,"enabling C->S compression");
session->next_crypto->do_compress_in=1;
@@ -973,7 +1076,7 @@ int crypt_set_algorithms_server(ssh_session session){
client=session->client_kex.methods[SSH_CRYPT_S_C];
server=session->server_kex.methods[SSH_CRYPT_S_C];
match=ssh_find_matching(client,server);
match=ssh_find_matching(server,client);
if(match && !strcmp(match,"zlib")){
ssh_log(session,SSH_LOG_PACKET,"enabling S->C compression\n");
session->next_crypto->do_compress_out=1;
@@ -982,7 +1085,7 @@ int crypt_set_algorithms_server(ssh_session session){
server=session->server_kex.methods[SSH_HOSTKEYS];
client=session->client_kex.methods[SSH_HOSTKEYS];
match=ssh_find_matching(client,server);
match=ssh_find_matching(server,client);
if(match && !strcmp(match,"ssh-dss"))
session->hostkeys=TYPE_DSS;
else if(match && !strcmp(match,"ssh-rsa"))