Compare commits

...

203 Commits

Author SHA1 Message Date
Aris Adamantiadis
75dc5939ed Workaround ssh_get_user_home_dir on LDAP accounts 2011-07-13 11:59:40 +02:00
Andreas Schneider
4d85f7b1e5 cmake: Fixed a typo.
(cherry picked from commit 7150cabafa)
2011-04-08 11:06:07 +02:00
Andreas Schneider
b7db87c817 doc: Fixed callbacks documentation. 2011-01-28 13:09:02 +01:00
Aris Adamantiadis
eb49bf4bfd SSH1: fix a few bugs that stopped the samplessh to work 2011-01-26 22:37:04 +01:00
Aris Adamantiadis
f6c31db3fc Allow SSH-1 only if compiled in 2011-01-26 22:14:48 +01:00
Aris Adamantiadis
bef014b7a9 Knownhosts: fix missing leave_function() 2011-01-26 22:08:13 +01:00
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
Andreas Schneider
2f0b671a61 Update version to 0.4.0. 2009-12-10 14:15:04 +01:00
Andreas Schneider
1fadec37d6 Don't install crypto.h which is an internal header file. 2009-12-10 13:55:07 +01:00
Andreas Schneider
2aabbd6245 Remove socklen_t definition.
Tthe problem is that winsock2.h defines socklen_t as a typedef, not as a
define, so depending on the order of includes you can get errors in
ws2tcpip.h with msvc.
2009-12-09 13:04:26 +01:00
Aris Adamantiadis
fd6823691b Fix stupid bug which stops log_verbosity working 2009-12-02 14:19:42 +01:00
Andreas Schneider
b174ad8ae4 Fixed indent. 2009-12-02 00:23:27 +01:00
Andreas Schneider
176778bb1c Added gettimeofday for Windows.
Thanks to Patrick Spendrin.
2009-12-02 00:23:20 +01:00
Andreas Schneider
e5bf645010 Fixed uint* to work on Windows.
Thanks to Patrick Spendrin.
2009-12-02 00:23:00 +01:00
61 changed files with 5075 additions and 1670 deletions

View File

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

View File

@@ -12,8 +12,8 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
### versions ### versions
set(CPACK_PACKAGE_VERSION_MAJOR "0") set(CPACK_PACKAGE_VERSION_MAJOR "0")
set(CPACK_PACKAGE_VERSION_MINOR "3") set(CPACK_PACKAGE_VERSION_MINOR "4")
set(CPACK_PACKAGE_VERSION_PATCH "91") set(CPACK_PACKAGE_VERSION_PATCH "8")
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
@@ -22,16 +22,21 @@ set(CPACK_SOURCE_GENERATOR "TGZ")
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/build/;tags;cscope.*") set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/build/;tags;cscope.*")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
if (WIN32)
set(CPACK_GENERATOR "ZIP")
### nsis generator ### nsis generator
set(CPACK_GENERATOR "NSIS") 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_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_PACKAGE_FILE_NAME ${APPLICATION_NAME}-${CPACK_PACKAGE_VERSION})
set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries") set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries")

View File

@@ -1,7 +1,101 @@
ChangeLog ChangeLog
========== ==========
version 0.4 (released xxxx-xx-xx) 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 scp support.
* Added support for sending signals (RFC 4254, section 6.9). * Added support for sending signals (RFC 4254, section 6.9).
* Added MSVC support. * Added MSVC support.

View File

@@ -1,4 +1,5 @@
include(CheckIncludeFile) include(CheckIncludeFile)
include(CheckIncludeFiles)
include(CheckSymbolExists) include(CheckSymbolExists)
include(CheckFunctionExists) include(CheckFunctionExists)
include(CheckLibraryExists) include(CheckLibraryExists)
@@ -16,20 +17,40 @@ set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
set(BINARYDIR ${CMAKE_BINARY_DIR}) set(BINARYDIR ${CMAKE_BINARY_DIR})
set(SOURCEDIR ${CMAKE_SOURCE_DIR}) set(SOURCEDIR ${CMAKE_SOURCE_DIR})
if(CMAKE_COMPILER_IS_GNUC) function(COMPILER_DUMPVERSION _OUTPUT_VERSION)
check_c_compiler_flag("-fvisibility=hidden" WITH_VISIBILITY_HIDDEN) execute_process(
endif(CMAKE_COMPILER_IS_GNUC) 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 # HEADER FILES
check_include_file(argp.h HAVE_ARGP_H) check_include_file(argp.h HAVE_ARGP_H)
check_include_file(pty.h HAVE_PTY_H) check_include_file(pty.h HAVE_PTY_H)
check_include_file(terminos.h HAVE_TERMIOS_H) check_include_file(termios.h HAVE_TERMIOS_H)
if (WIN32) 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) 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) 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) if (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
set(HAVE_GETADDRINFO TRUE) set(HAVE_GETADDRINFO TRUE)
set(HAVE_GETHOSTBYNAME TRUE) set(HAVE_GETHOSTBYNAME TRUE)
@@ -49,6 +70,17 @@ check_include_file(openssl/des.h HAVE_OPENSSL_DES_H)
# FUNCTIONS # 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) if (UNIX)
# libsocket (Solaris) # libsocket (Solaris)
check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET) check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET)
@@ -82,9 +114,9 @@ endif (UNIX)
set(LIBSSH_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CACHE INTERNAL "libssh required system libraries") set(LIBSSH_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CACHE INTERNAL "libssh required system libraries")
# LIBRARIES # LIBRARIES
if (CRYPTO_FOUND) if (OPENSSL_FOUND)
set(HAVE_LIBCRYPTO 1) set(HAVE_LIBCRYPTO 1)
endif (CRYPTO_FOUND) endif (OPENSSL_FOUND)
if (GCRYPT_FOUND) if (GCRYPT_FOUND)
set(HAVE_LIBGCRYPT 1) set(HAVE_LIBGCRYPT 1)
@@ -104,4 +136,6 @@ if (WITH_DEBUG_CALLTRACE)
endif (WITH_DEBUG_CALLTRACE) endif (WITH_DEBUG_CALLTRACE)
# ENDIAN # 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) include(CheckCCompilerFlag)
if (UNIX AND NOT WIN32) if (UNIX AND NOT WIN32)
if (CMAKE_COMPILER_IS_GNUCC) if (${CMAKE_C_COMPILER_ID} MATCHES GNU)
# add -Wconversion ? # 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") 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 # with -fPIC
check_c_compiler_flag("-fPIC" WITH_FPIC) check_c_compiler_flag("-fPIC" WITH_FPIC)
if (WITH_FPIC) if (WITH_FPIC)
add_definitions(-fPIC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
endif (WITH_FPIC) endif (WITH_FPIC)
check_c_compiler_flag("-fstack-protector" WITH_STACK_PROTECTOR) check_c_compiler_flag("-fstack-protector" WITH_STACK_PROTECTOR)
if (WITH_STACK_PROTECTOR) if (WITH_STACK_PROTECTOR)
add_definitions(-fstack-protector) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector")
endif (WITH_STACK_PROTECTOR) endif (WITH_STACK_PROTECTOR)
check_c_compiler_flag("-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE) check_c_compiler_flag("-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE)
if (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 (WITH_FORTIFY_SOURCE)
endif (CMAKE_COMPILER_IS_GNUCC) endif (${CMAKE_C_COMPILER_ID} MATCHES GNU)
if (CMAKE_SIZEOF_VOID_P MATCHES "8") if (CMAKE_SIZEOF_VOID_P MATCHES "8")
# with large file support # with large file support
@@ -48,12 +48,12 @@ if (UNIX AND NOT WIN32)
endif (CMAKE_SIZEOF_VOID_P MATCHES "8") endif (CMAKE_SIZEOF_VOID_P MATCHES "8")
if (_lfs_CFLAGS) if (_lfs_CFLAGS)
string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_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 (_lfs_CFLAGS)
endif (UNIX AND NOT WIN32) endif (UNIX AND NOT WIN32)
# suppress warning about "deprecated" functions # suppress warning about "deprecated" functions
if (MSVC) if (MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS")
endif (MSVC) 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) IF (NOT APPLICATION_NAME)
MESSAGE(STATUS "${PROJECT_NAME} is used as APPLICATION_NAME") MESSAGE(STATUS "${PROJECT_NAME} is used as APPLICATION_NAME")
SET(APPLICATION_NAME ${PROJECT_NAME}) SET(APPLICATION_NAME ${PROJECT_NAME})
@@ -90,18 +101,4 @@ if (UNIX)
"${SHARE_INSTALL_PREFIX}/info" "${SHARE_INSTALL_PREFIX}/info"
CACHE PATH "The ${APPLICATION_NAME} info install dir (default prefix/info)" CACHE PATH "The ${APPLICATION_NAME} info install dir (default prefix/info)"
) )
endif (UNIX) endif ()
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)

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

View File

@@ -18,11 +18,15 @@ if (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
# in cache already # in cache already
set(ZLIB_FOUND TRUE) set(ZLIB_FOUND TRUE)
else (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS) else (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
if (WIN32)
set(_ZLIB_DIR $ENV{PROGRAMFILES}/GnuWin32)
endif (WIN32)
find_path(ZLIB_INCLUDE_DIR find_path(ZLIB_INCLUDE_DIR
NAMES NAMES
zlib.h zlib.h
PATHS PATHS
${_ZLIB_DIR}/include
/usr/include /usr/include
/usr/local/include /usr/local/include
/opt/local/include /opt/local/include
@@ -36,6 +40,7 @@ else (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
zlib zlib
zlib1 zlib1
PATHS PATHS
${_ZLIB_DIR}/lib
/usr/lib /usr/lib
/usr/local/lib /usr/local/lib
/opt/local/lib /opt/local/lib

View File

@@ -1,127 +1,100 @@
# -helper macro to add a "doc" target with CMake build system. # - Run Doxygen
# and configure doxy.config.in to doxy.config
# #
# target "doc" allows building the documentation with doxygen/dot on WIN32 and Linux # Adds a doxygen target that runs doxygen to generate the html
# Creates .chm windows help file if MS HTML help workshop # and optionally the LaTeX API documentation.
# (available from http://msdn.microsoft.com/workshop/author/htmlhelp) # The doxygen target is added to the doc target as dependency.
# is installed with its DLLs in PATH. # 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.: # Variables you may define are:
# doxygen, dot, latex, dvips, makeindex, gswin32, etc. # DOXYFILE_OUTPUT_DIR - Path where the Doxygen output is stored. Defaults to "doc".
# must be in path.
# #
# Note about Visual Studio Projects: # DOXYFILE_LATEX_DIR - Directory where the Doxygen LaTeX output is stored. Defaults to "latex".
# MSVS has its own path environment which may differ from the shell. #
# See "Menu Tools/Options/Projects/VC++ Directories" in VS 7.1 # 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(DOXYGEN_FOUND)
IF (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)") find_file(DOXYFILE_IN
SET(DOXY_WARN_FORMAT "\"$file($line) : $text \"") NAMES
ELSE (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)") doxy.config.in
SET(DOXY_WARN_FORMAT "\"$file:$line: $text \"") PATHS
ENDIF (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)") ${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 if(DOXYGEN_FOUND AND DOXYFILE_IN_FOUND)
FIND_PACKAGE(LATEX) add_custom_target(doxygen ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.config)
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 (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in") usedoxygen_set_default(DOXYFILE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
MESSAGE(STATUS "Generate ${CMAKE_CURRENT_BINARY_DIR}/doxy.config from doxy.config.in") usedoxygen_set_default(DOXYFILE_HTML_DIR "html")
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")
ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config") set_property(DIRECTORY APPEND PROPERTY
ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in") 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 find_package(LATEX)
# HTMLHelp DLL must be in path! if(LATEX_COMPILER AND MAKEINDEX_COMPILER)
# fallback: use hhw.exe interactively set(DOXYFILE_LATEX TRUE)
IF (WIN32) usedoxygen_set_default(DOXYFILE_LATEX_DIR "latex")
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)
ENDIF(HTML_HELP_COMPILER) set_property(DIRECTORY APPEND PROPERTY
# MESSAGE(SEND_ERROR "HTML_HELP_COMPILER=${HTML_HELP_COMPILER}") ADDITIONAL_MAKE_CLEAN_FILES
ENDIF (WIN32) "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
ENDIF(DOXYGEN_FOUND)
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 ***************************/ /*************************** 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. */ /* Define to 1 if you have the `cfmakeraw' function. */
#cmakedefine HAVE_CFMAKERAW 1 #cmakedefine HAVE_CFMAKERAW 1
@@ -94,17 +125,3 @@
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */ significant byte first (like Motorola and SPARC, unlike Intel). */
#cmakedefine WORDS_BIGENDIAN 1 #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 -->

File diff suppressed because it is too large Load Diff

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

View File

@@ -152,10 +152,12 @@ static void do_sftp(ssh_session session){
} }
/* reading the whole directory, file by file */ /* reading the whole directory, file by file */
while((file=sftp_readdir(sftp,dir))){ 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->name,
file->permissions, file->permissions,
file->owner,
file->uid, file->uid,
file->group,
file->gid, file->gid,
(long long unsigned int) file->size); (long long unsigned int) file->size);
sftp_attributes_free(file); 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

@@ -3,7 +3,6 @@ project(libssh-headers C)
set(libssh_HDRS set(libssh_HDRS
callbacks.h callbacks.h
libssh.h libssh.h
crypto.h
ssh2.h ssh2.h
) )

View File

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

View File

@@ -33,6 +33,11 @@
extern "C" { extern "C" {
#endif #endif
/**
* @addtogroup ssh_session
* @{
*/
/** /**
* @brief SSH authentication callback. * @brief SSH authentication callback.
* *
@@ -110,4 +115,6 @@ LIBSSH_API int ssh_set_callbacks(ssh_session session, ssh_callbacks cb);
} }
#endif #endif
/** @} */
#endif /*_SSH_CALLBACK_H */ #endif /*_SSH_CALLBACK_H */

View File

@@ -40,7 +40,7 @@
#endif #endif
#endif #endif
#else #else
#if __GNUC__ >= 4 #if __GNUC__ >= 4 && !defined(__OS2__)
#define LIBSSH_API __attribute__((visibility("default"))) #define LIBSSH_API __attribute__((visibility("default")))
#else #else
#define LIBSSH_API #define LIBSSH_API
@@ -50,6 +50,7 @@
#ifdef _MSC_VER #ifdef _MSC_VER
/* Visual Studio hasn't inttypes.h so it doesn't know uint32_t */ /* Visual Studio hasn't inttypes.h so it doesn't know uint32_t */
typedef int int32_t;
typedef unsigned int uint32_t; typedef unsigned int uint32_t;
typedef unsigned short uint16_t; typedef unsigned short uint16_t;
typedef unsigned char uint8_t; typedef unsigned char uint8_t;
@@ -78,7 +79,7 @@
/* libssh version */ /* libssh version */
#define LIBSSH_VERSION_MAJOR 0 #define LIBSSH_VERSION_MAJOR 0
#define LIBSSH_VERSION_MINOR 4 #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, \ #define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
LIBSSH_VERSION_MINOR, \ LIBSSH_VERSION_MINOR, \
@@ -118,10 +119,16 @@ typedef struct ssh_string_struct* ssh_string;
/* Socket type */ /* Socket type */
#ifdef _WIN32 #ifdef _WIN32
#define socket_t SOCKET #ifndef socket_t
#else typedef SOCKET socket_t;
#endif /* socket_t */
#else /* _WIN32 */
#ifndef socket_t
typedef int socket_t; typedef int socket_t;
#endif #endif
#endif /* _WIN32 */
#define SSH_INVALID_SOCKET ((socket_t) -1)
/* the offsets of methods */ /* the offsets of methods */
enum ssh_kex_types_e { enum ssh_kex_types_e {
@@ -164,7 +171,7 @@ enum ssh_requests_e {
SSH_REQUEST_CHANNEL_OPEN, SSH_REQUEST_CHANNEL_OPEN,
SSH_REQUEST_CHANNEL, SSH_REQUEST_CHANNEL,
SSH_REQUEST_SERVICE, SSH_REQUEST_SERVICE,
SSH_REQUEST_GLOBAL, SSH_REQUEST_GLOBAL
}; };
enum ssh_channel_type_e { enum ssh_channel_type_e {
@@ -182,7 +189,7 @@ enum ssh_channel_requests_e {
SSH_CHANNEL_REQUEST_SHELL, SSH_CHANNEL_REQUEST_SHELL,
SSH_CHANNEL_REQUEST_ENV, SSH_CHANNEL_REQUEST_ENV,
SSH_CHANNEL_REQUEST_SUBSYSTEM, SSH_CHANNEL_REQUEST_SUBSYSTEM,
SSH_CHANNEL_REQUEST_WINDOW_CHANGE, SSH_CHANNEL_REQUEST_WINDOW_CHANGE
}; };
/* status flags */ /* status flags */
@@ -196,7 +203,7 @@ enum ssh_server_known_e {
SSH_SERVER_KNOWN_OK, SSH_SERVER_KNOWN_OK,
SSH_SERVER_KNOWN_CHANGED, SSH_SERVER_KNOWN_CHANGED,
SSH_SERVER_FOUND_OTHER, SSH_SERVER_FOUND_OTHER,
SSH_SERVER_FILE_NOT_FOUND, SSH_SERVER_FILE_NOT_FOUND
}; };
#ifndef MD5_DIGEST_LEN #ifndef MD5_DIGEST_LEN
@@ -230,7 +237,7 @@ enum {
/** Only rare and noteworthy events /** Only rare and noteworthy events
*/ */
SSH_LOG_RARE, SSH_LOG_RARE,
/** High level protocol informations /** High level protocol information
*/ */
SSH_LOG_PROTOCOL, SSH_LOG_PROTOCOL,
/** Lower level protocol infomations, packet level /** Lower level protocol infomations, packet level
@@ -251,6 +258,7 @@ enum ssh_options_e {
SSH_OPTIONS_USER, SSH_OPTIONS_USER,
SSH_OPTIONS_SSH_DIR, SSH_OPTIONS_SSH_DIR,
SSH_OPTIONS_IDENTITY, SSH_OPTIONS_IDENTITY,
SSH_OPTIONS_ADD_IDENTITY,
SSH_OPTIONS_KNOWNHOSTS, SSH_OPTIONS_KNOWNHOSTS,
SSH_OPTIONS_TIMEOUT, SSH_OPTIONS_TIMEOUT,
SSH_OPTIONS_TIMEOUT_USEC, SSH_OPTIONS_TIMEOUT_USEC,
@@ -262,7 +270,9 @@ enum ssh_options_e {
SSH_OPTIONS_CIPHERS_C_S, SSH_OPTIONS_CIPHERS_C_S,
SSH_OPTIONS_CIPHERS_S_C, SSH_OPTIONS_CIPHERS_S_C,
SSH_OPTIONS_COMPRESSION_C_S, SSH_OPTIONS_COMPRESSION_C_S,
SSH_OPTIONS_COMPRESSION_S_C SSH_OPTIONS_COMPRESSION_S_C,
SSH_OPTIONS_PROXYCOMMAND,
SSH_OPTIONS_BINDADDR
}; };
enum { enum {
@@ -334,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, LIBSSH_API ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
int type, const char *passphrase); int type, const char *passphrase);
LIBSSH_API void publickey_free(ssh_public_key key); 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, LIBSSH_API ssh_string publickey_from_file(ssh_session session, const char *filename,
int *type); int *type);
LIBSSH_API ssh_public_key publickey_from_privatekey(ssh_private_key prv); LIBSSH_API ssh_public_key publickey_from_privatekey(ssh_private_key prv);
LIBSSH_API ssh_string publickey_to_string(ssh_public_key key); LIBSSH_API ssh_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 int ssh_auth_list(ssh_session session);
LIBSSH_API char *ssh_basename (const char *path); LIBSSH_API char *ssh_basename (const char *path);
@@ -382,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 void ssh_pcap_file_free(ssh_pcap_file pcap);
LIBSSH_API ssh_pcap_file ssh_pcap_file_new(void); 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_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 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_accept_request(ssh_scp scp);
LIBSSH_API int ssh_scp_close(ssh_scp scp); LIBSSH_API int ssh_scp_close(ssh_scp scp);

View File

@@ -25,8 +25,12 @@
/* in misc.c */ /* in misc.c */
/* gets the user home dir. */ /* gets the user home dir. */
char *ssh_get_user_home_dir(void); char *ssh_get_user_home_dir(void);
char *ssh_get_local_username(ssh_session session);
int ssh_file_readaccess_ok(const char *file); 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 */ /* macro for byte ordering */
uint64_t ntohll(uint64_t); uint64_t ntohll(uint64_t);
#define htonll(x) ntohll(x) #define htonll(x) ntohll(x)
@@ -46,14 +50,12 @@ struct ssh_iterator {
struct ssh_list *ssh_list_new(void); struct ssh_list *ssh_list_new(void);
void ssh_list_free(struct ssh_list *list); void ssh_list_free(struct ssh_list *list);
struct ssh_iterator *ssh_list_get_iterator(const struct ssh_list *list); struct ssh_iterator *ssh_list_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); 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 const void *_ssh_list_pop_head(struct ssh_list *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);
#define ssh_iterator_value(type, iterator)\ #define ssh_iterator_value(type, iterator)\
((type)((iterator)->data)) ((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 /** @brief fetch the head element of a list and remove it from list
* @param type type of the element to return * @param type type of the element to return
* @param list the ssh_list to use * @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)\ #define ssh_list_pop_head(type, ssh_list)\
((type)_ssh_list_get_head(ssh_list)) ((type)_ssh_list_pop_head(ssh_list))
#endif /* MISC_H_ */ #endif /* MISC_H_ */

View File

@@ -7,7 +7,7 @@
#ifdef WITH_PCAP #ifdef WITH_PCAP
typedef struct ssh_pcap_context_struct* ssh_pcap_context; typedef struct ssh_pcap_context_struct* ssh_pcap_context;
int ssh_pcap_file_write_packet(ssh_pcap_file pcap, ssh_buffer packet, u_int32_t original_len); int ssh_pcap_file_write_packet(ssh_pcap_file pcap, ssh_buffer packet, uint32_t original_len);
ssh_pcap_context ssh_pcap_context_new(ssh_session session); ssh_pcap_context ssh_pcap_context_new(ssh_session session);
void ssh_pcap_context_free(ssh_pcap_context ctx); void ssh_pcap_context_free(ssh_pcap_context ctx);
@@ -18,7 +18,7 @@ enum ssh_pcap_direction{
}; };
void ssh_pcap_context_set_file(ssh_pcap_context, ssh_pcap_file); void ssh_pcap_context_set_file(ssh_pcap_context, ssh_pcap_file);
int ssh_pcap_context_write(ssh_pcap_context,enum ssh_pcap_direction direction, void *data, int ssh_pcap_context_write(ssh_pcap_context,enum ssh_pcap_direction direction, void *data,
u_int32_t len, u_int32_t origlen); uint32_t len, uint32_t origlen);
#endif /* WITH_PCAP */ #endif /* WITH_PCAP */

View File

@@ -38,9 +38,48 @@ typedef struct ssh_pollfd_struct {
short revents; /* returned events */ short revents; /* returned events */
} ssh_pollfd_t; } 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 */ /* poll.c */
#ifndef POLLIN #ifndef POLLIN
# define POLLIN 0x001 /* There is data to read. */ #define POLLIN 0x001 /* There is data to read. */
#endif #endif
#ifndef POLLPRI #ifndef POLLPRI
#define POLLPRI 0x002 /* There is urgent data to read. */ #define POLLPRI 0x002 /* There is urgent data to read. */
@@ -59,9 +98,24 @@ typedef struct ssh_pollfd_struct {
#define POLLNVAL 0x020 /* Invalid polling request. */ #define POLLNVAL 0x020 /* Invalid polling request. */
#endif #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 */ #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); 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_ctx_struct *ssh_poll_ctx;
typedef struct ssh_poll_handle_struct *ssh_poll_handle; 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 * @return 0 on success, < 0 if you removed the poll object from
* it's poll context. * 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); void *userdata);

View File

@@ -32,18 +32,72 @@
#include "config.h" #include "config.h"
#ifdef _MSC_VER #ifdef _WIN32
#define snprintf _snprintf
/** Imitate define of inttypes.h */ /* Imitate define of inttypes.h */
#define PRIdS "Id" # ifndef PRIdS
#define strcasecmp _stricmp # define PRIdS "Id"
#define strncasecmp _strnicmp # endif
#define strtoull _strtoui64
#define isblank(ch) ((ch) == ' ' || (ch) == '\t' || (ch) == '\n' || (ch) == '\r') # ifdef _MSC_VER
#else # 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> #include <unistd.h>
#define PRIdS "zd" #define PRIdS "zd"
#endif
#endif /* _WIN32 */
#include "libssh/libssh.h" #include "libssh/libssh.h"
#include "libssh/callbacks.h" #include "libssh/callbacks.h"
@@ -77,7 +131,7 @@ typedef struct kex_struct {
struct error_struct { struct error_struct {
/* error handling */ /* error handling */
int error_code; unsigned int error_code;
char error_buffer[ERROR_BUFFERLEN]; char error_buffer[ERROR_BUFFERLEN];
}; };
@@ -185,6 +239,11 @@ int match_hostname(const char *host, const char *pattern, unsigned int len);
/* log.c */ /* log.c */
/* misc.c */
#ifdef _WIN32
int gettimeofday(struct timeval *__p, void *__t);
#endif /* _WIN32 */
#ifndef __FUNCTION__ #ifndef __FUNCTION__
#if defined(__SUNPRO_C) #if defined(__SUNPRO_C)
#define __FUNCTION__ __func__ #define __FUNCTION__ __func__
@@ -217,8 +276,8 @@ int match_hostname(const char *host, const char *pattern, unsigned int len);
/* options.c */ /* 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_set_algo(ssh_session session, int algo, const char *list);
int ssh_options_apply(ssh_session session);
/** Free memory space */ /** Free memory space */
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0) #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)

View File

@@ -61,9 +61,13 @@ LIBSSH_API ssh_bind ssh_bind_new(void);
/** /**
* @brief Set the opitons for the current SSH server bind. * @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, LIBSSH_API int ssh_bind_options_set(ssh_bind sshbind,
enum ssh_bind_options_e type, const void *value); enum ssh_bind_options_e type, const void *value);

View File

@@ -102,9 +102,9 @@ struct ssh_session_struct {
#endif #endif
char *username; char *username;
char *host; 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 *xbanner; /* TODO: looks like it is not needed */
char *identity; struct ssh_list *identity;
char *sshdir; char *sshdir;
char *knownhosts; char *knownhosts;
char *wanted_methods[10]; char *wanted_methods[10];
@@ -114,8 +114,9 @@ struct ssh_session_struct {
socket_t fd; socket_t fd;
int ssh2; int ssh2;
int ssh1; int ssh1;
char *ProxyCommand;
}; };
int ssh_handle_packets(ssh_session session); int ssh_handle_packets(ssh_session session);
void ssh_global_request_handle(ssh_session session);
#endif /* SESSION_H_ */ #endif /* SESSION_H_ */

View File

@@ -149,17 +149,16 @@ struct sftp_status_message_struct {
char *langmsg; char *langmsg;
}; };
/* don't worry much of these aren't really used */
struct sftp_attributes_struct { struct sftp_attributes_struct {
char *name; char *name;
char *longname; /* some weird stuff */ char *longname; /* ls -l output on openssh, not reliable else */
uint32_t flags; uint32_t flags;
uint8_t type; uint8_t type;
uint64_t size; uint64_t size;
uint32_t uid; uint32_t uid;
uint32_t gid; uint32_t gid;
char *owner; char *owner; /* set if openssh and version 4 */
char *group; char *group; /* set if openssh and version 4 */
uint32_t permissions; uint32_t permissions;
uint64_t atime64; uint64_t atime64;
uint32_t atime; 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_free(struct socket *s);
void ssh_socket_set_fd(struct socket *s, socket_t fd); void ssh_socket_set_fd(struct socket *s, socket_t fd);
socket_t ssh_socket_get_fd(struct socket *s); socket_t ssh_socket_get_fd(struct socket *s);
void ssh_socket_cleanup(void);
#ifndef _WIN32 #ifndef _WIN32
int ssh_socket_unix(struct socket *s, const char *path); int ssh_socket_unix(struct socket *s, const char *path);
#endif #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_write(struct socket *s,const void *buffer, int len);
int ssh_socket_is_open(struct socket *s); int ssh_socket_is_open(struct socket *s);
int ssh_socket_fd_isset(struct socket *s, fd_set *set); 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_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_completewrite(struct socket *s, const void *buffer, uint32_t len);
int ssh_socket_wait_for_data(struct socket *s, ssh_session session, uint32_t len); int ssh_socket_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_available(struct socket *s);
int ssh_socket_data_writable(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_ */ #endif /* SOCKET_H_ */

View File

@@ -70,6 +70,11 @@ typedef HMAC_CTX* HMACCTX;
#define MD5_DIGEST_LEN MD5_DIGEST_LENGTH #define MD5_DIGEST_LEN MD5_DIGEST_LENGTH
#include <openssl/bn.h> #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 BIGNUM* bignum;
typedef BN_CTX* bignum_CTX; typedef BN_CTX* bignum_CTX;

View File

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

View File

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

View File

@@ -35,6 +35,7 @@
#include "libssh/buffer.h" #include "libssh/buffer.h"
#include "libssh/agent.h" #include "libssh/agent.h"
#include "libssh/keyfiles.h" #include "libssh/keyfiles.h"
#include "libssh/misc.h"
#include "libssh/packet.h" #include "libssh/packet.h"
#include "libssh/session.h" #include "libssh/session.h"
#include "libssh/keys.h" #include "libssh/keys.h"
@@ -169,24 +170,33 @@ static int wait_auth_status(ssh_session session, int kbdint) {
return rc; return rc;
} }
/**
* @brief retrieves available authentication methods for this session
* @deprecated
* @see ssh_userauth_list
*/
int ssh_auth_list(ssh_session session) { int ssh_auth_list(ssh_session session) {
if (session == NULL) { return ssh_userauth_list(session, NULL);
return -1;
}
return session->auth_methods;
} }
/**
* @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) { int ssh_userauth_list(ssh_session session, const char *username) {
if (session == NULL || username == NULL) { if (session == NULL) {
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
} }
if (session->auth_methods == 0) { if (session->auth_methods == 0) {
ssh_userauth_none(session, username); ssh_userauth_none(session, username);
} }
return session->auth_methods;
return ssh_auth_list(session);
} }
/* use the "none" authentication question */ /* use the "none" authentication question */
@@ -216,7 +226,7 @@ int ssh_userauth_none(ssh_session session, const char *username) {
#ifdef WITH_SSH1 #ifdef WITH_SSH1
if (session->version == 1) { if (session->version == 1) {
ssh_userauth1_none(session, username); rc = ssh_userauth1_none(session, username);
leave_function(); leave_function();
return rc; return rc;
} }
@@ -224,7 +234,7 @@ int ssh_userauth_none(ssh_session session, const char *username) {
if (username == NULL) { if (username == NULL) {
if (session->username == NULL) { if (session->username == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { if (ssh_options_apply(session) < 0) {
leave_function(); leave_function();
return rc; return rc;
} }
@@ -322,7 +332,7 @@ int ssh_userauth_offer_pubkey(ssh_session session, const char *username,
#ifdef WITH_SSH1 #ifdef WITH_SSH1
if (session->version == 1) { if (session->version == 1) {
ssh_userauth1_offer_pubkey(session, username, type, publickey); rc = ssh_userauth1_offer_pubkey(session, username, type, publickey);
leave_function(); leave_function();
return rc; return rc;
} }
@@ -330,7 +340,7 @@ int ssh_userauth_offer_pubkey(ssh_session session, const char *username,
if (username == NULL) { if (username == NULL) {
if (session->username == NULL) { if (session->username == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { if (ssh_options_apply(session) < 0) {
leave_function(); leave_function();
return rc; return rc;
} }
@@ -442,7 +452,7 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
if (username == NULL) { if (username == NULL) {
if (session->username == NULL) { if (session->username == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { if (ssh_options_apply(session) < 0) {
leave_function(); leave_function();
return rc; return rc;
} }
@@ -560,7 +570,7 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
if (username == NULL) { if (username == NULL) {
if (session->username == NULL) { if (session->username == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { if (ssh_options_apply(session) < 0) {
leave_function(); leave_function();
return rc; return rc;
} }
@@ -687,7 +697,7 @@ int ssh_userauth_password(ssh_session session, const char *username,
if (username == NULL) { if (username == NULL) {
if (session->username == NULL) { if (session->username == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { if (ssh_options_apply(session) < 0) {
leave_function(); leave_function();
return rc; return rc;
} }
@@ -756,42 +766,6 @@ error:
return rc; 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" * @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_kbdint()
* @see ssh_userauth_password() * @see ssh_userauth_password()
* @see ssh_options_set()
*/ */
int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) { int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) {
struct ssh_public_key_struct *publickey; struct ssh_iterator *it;
ssh_string pubkey;
ssh_private_key privkey; ssh_private_key privkey;
char *privkeyfile = NULL; ssh_public_key pubkey;
char *id = NULL; ssh_string pubkey_string;
size_t size;
unsigned int i = 0;
int type = 0; int type = 0;
int rc; int rc;
@@ -837,142 +807,159 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) {
/* Try authentication with ssh-agent first */ /* Try authentication with ssh-agent first */
#ifndef _WIN32 #ifndef _WIN32
if (agent_is_running(session)) { if (agent_is_running(session)) {
char *privkey_file = NULL;
ssh_log(session, SSH_LOG_RARE, ssh_log(session, SSH_LOG_RARE,
"Trying to authenticate with SSH agent keys as user: %s", "Trying to authenticate with SSH agent keys as user: %s",
session->username); session->username);
for (publickey = agent_get_first_ident(session, &privkeyfile); for (pubkey = agent_get_first_ident(session, &privkey_file);
publickey != NULL; pubkey != NULL;
publickey = agent_get_next_ident(session, &privkeyfile)) { 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); pubkey_string = publickey_to_string(pubkey);
if (pubkey) { if (pubkey_string) {
rc = ssh_userauth_offer_pubkey(session, NULL, publickey->type, pubkey); rc = ssh_userauth_offer_pubkey(session, NULL, pubkey->type, pubkey_string);
string_free(pubkey); string_free(pubkey_string);
if (rc == SSH_AUTH_ERROR) { if (rc == SSH_AUTH_ERROR) {
SAFE_FREE(id); SAFE_FREE(privkey_file);
SAFE_FREE(privkeyfile); publickey_free(pubkey);
publickey_free(publickey);
leave_function(); leave_function();
return rc; return rc;
} else if (rc != SSH_AUTH_SUCCESS) { } else if (rc != SSH_AUTH_SUCCESS) {
ssh_log(session, SSH_LOG_PACKET, "Public key refused by server\n"); ssh_log(session, SSH_LOG_PROTOCOL, "Public key refused by server");
SAFE_FREE(id); SAFE_FREE(privkey_file);
SAFE_FREE(privkeyfile); publickey_free(pubkey);
publickey_free(publickey);
continue; continue;
} }
ssh_log(session, SSH_LOG_RARE, "Public key accepted"); ssh_log(session, SSH_LOG_RARE, "Public key accepted");
/* pubkey accepted by server ! */ /* 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) { if (rc == SSH_AUTH_ERROR) {
SAFE_FREE(id); SAFE_FREE(privkey_file);
SAFE_FREE(privkeyfile); publickey_free(pubkey);
publickey_free(publickey);
leave_function(); leave_function();
return rc; return rc;
} else if (rc != SSH_AUTH_SUCCESS) { } else if (rc != SSH_AUTH_SUCCESS) {
ssh_log(session, SSH_LOG_RARE, ssh_log(session, SSH_LOG_RARE,
"Server accepted public key but refused the signature\n" "Server accepted public key but refused the signature ;"
"It might be a bug of libssh\n"); " It might be a bug of libssh");
SAFE_FREE(id); SAFE_FREE(privkey_file);
SAFE_FREE(privkeyfile); publickey_free(pubkey);
publickey_free(publickey);
continue; continue;
} }
/* auth success */ /* auth success */
ssh_log(session, SSH_LOG_RARE, "Authentication using %s success\n", ssh_log(session, SSH_LOG_PROTOCOL, "Authentication using %s success",
privkeyfile); privkey_file);
SAFE_FREE(id); SAFE_FREE(privkey_file);
SAFE_FREE(privkeyfile); publickey_free(pubkey);
publickey_free(publickey);
leave_function(); leave_function();
return SSH_AUTH_SUCCESS; return SSH_AUTH_SUCCESS;
} /* if pubkey */ } /* if pubkey */
SAFE_FREE(id); SAFE_FREE(privkey_file);
SAFE_FREE(privkeyfile); publickey_free(pubkey);
publickey_free(publickey);
} /* for each privkey */ } /* for each privkey */
} /* if agent is running */ } /* if agent is running */
#endif #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); for (it = ssh_list_get_iterator(session->identity);
if (id == NULL) { it != NULL;
leave_function(); it = it->next) {
return SSH_AUTH_ERROR; const char *privkey_file = it->data;
} int privkey_open = 0;
sprintf(id, "%s.pub", session->identity);
keytab[size - 1].privatekey = session->identity; privkey = NULL;
keytab[size - 1].publickey = id;
}
for (i = 0, pubkey = try_publickey_from_file(session, keytab[i], ssh_log(session, SSH_LOG_PROTOCOL, "Trying to read privatekey %s", privkey_file);
&privkeyfile, &type);
i < size; rc = ssh_try_publickey_from_file(session, privkey_file, &pubkey_string, &type);
pubkey = try_publickey_from_file(session, keytab[i++], if (rc == 1) {
&privkeyfile, &type)) { char *publickey_file;
if (pubkey == NULL) { 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; 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 (rc == SSH_AUTH_ERROR){
if (id != NULL) { string_free(pubkey_string);
keytab[size - 1].privatekey = NULL;
keytab[size - 1].publickey = NULL;
SAFE_FREE(id);
}
string_free(pubkey);
SAFE_FREE(privkeyfile);
ssh_log(session, SSH_LOG_RARE, "Publickey authentication error"); ssh_log(session, SSH_LOG_RARE, "Publickey authentication error");
leave_function(); leave_function();
return rc; return rc;
} else { } else {
if (rc != SSH_AUTH_SUCCESS){ if (rc != SSH_AUTH_SUCCESS){
ssh_log(session, SSH_LOG_RARE, "Publickey refused by server"); ssh_log(session, SSH_LOG_PROTOCOL, "Publickey refused by server");
string_free(pubkey); string_free(pubkey_string);
pubkey = NULL;
SAFE_FREE(privkeyfile);
privkeyfile = NULL;
continue; continue;
} }
} }
/* Public key accepted by server! */ /* Public key accepted by server! */
ssh_log(session, SSH_LOG_RARE, "Trying to read privatekey %s", privkeyfile); if (!privkey_open) {
privkey = privatekey_from_file(session, privkeyfile, type, passphrase); ssh_log(session, SSH_LOG_PROTOCOL, "Trying to read privatekey %s",
if (privkey == NULL) { privkey_file);
ssh_log(session, SSH_LOG_FUNCTIONS, privkey = privatekey_from_file(session, privkey_file, type, passphrase);
"Reading private key %s failed (bad passphrase ?)", if (privkey == NULL) {
privkeyfile); ssh_log(session, SSH_LOG_RARE,
string_free(pubkey); "Reading private key %s failed (bad passphrase ?)",
pubkey = NULL; privkey_file);
SAFE_FREE(privkeyfile); string_free(pubkey_string);
privkeyfile = NULL; continue; /* continue the loop with other pubkey */
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 (rc == SSH_AUTH_ERROR) {
if (id != NULL) { string_free(pubkey_string);
keytab[size - 1].privatekey = NULL;
keytab[size - 1].publickey = NULL;
SAFE_FREE(id);
}
string_free(pubkey);
SAFE_FREE(privkeyfile);
privatekey_free(privkey); privatekey_free(privkey);
leave_function(); leave_function();
return rc; return rc;
@@ -980,39 +967,26 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) {
if (rc != SSH_AUTH_SUCCESS){ if (rc != SSH_AUTH_SUCCESS){
ssh_log(session, SSH_LOG_FUNCTIONS, ssh_log(session, SSH_LOG_FUNCTIONS,
"The server accepted the public key but refused the signature"); "The server accepted the public key but refused the signature");
string_free(pubkey); string_free(pubkey_string);
pubkey = NULL;
SAFE_FREE(privkeyfile);
privkeyfile = NULL;
privatekey_free(privkey); privatekey_free(privkey);
continue; continue;
} }
} }
/* auth success */ /* auth success */
ssh_log(session, SSH_LOG_RARE, ssh_log(session, SSH_LOG_PROTOCOL,
"Successfully authenticated using %s", privkeyfile); "Successfully authenticated using %s", privkey_file);
string_free(pubkey); string_free(pubkey_string);
privatekey_free(privkey); privatekey_free(privkey);
SAFE_FREE(privkeyfile);
if (id != NULL) {
keytab[size - 1].privatekey = NULL;
keytab[size - 1].publickey = NULL;
SAFE_FREE(id);
}
leave_function(); leave_function();
return SSH_AUTH_SUCCESS; return SSH_AUTH_SUCCESS;
} }
/* at this point, pubkey is NULL and so is privkeyfile */ /* at this point, pubkey is NULL and so is privkeyfile */
ssh_log(session, SSH_LOG_FUNCTIONS, ssh_log(session, SSH_LOG_FUNCTIONS,
"Tried every public key, none matched"); "Tried every public key, none matched");
ssh_set_error(session,SSH_NO_ERROR,"No public key 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(); leave_function();
return SSH_AUTH_DENIED; 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 */ /* first time we call. we must ask for a challenge */
if (user == NULL) { if (user == NULL) {
if ((user = session->username) == NULL) { if ((user = session->username) == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { if (ssh_options_apply(session) < 0) {
leave_function(); leave_function();
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
} else { } 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. * 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 * the server and then we need to ack the status (new questions or ok
* pass in). * pass in).
*/ */

View File

@@ -35,38 +35,46 @@
#ifdef WITH_SSH1 #ifdef WITH_SSH1
static int wait_auth1_status(ssh_session session) { static int wait_auth1_status(ssh_session session) {
enter_function();
/* wait for a packet */ /* wait for a packet */
if (packet_read(session) != SSH_OK) { if (packet_read(session) != SSH_OK) {
leave_function();
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
} }
if(packet_translate(session) != SSH_OK) { if(packet_translate(session) != SSH_OK) {
leave_function();
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
} }
switch(session->in_packet.type) { switch(session->in_packet.type) {
case SSH_SMSG_SUCCESS: case SSH_SMSG_SUCCESS:
leave_function();
return SSH_AUTH_SUCCESS; return SSH_AUTH_SUCCESS;
case SSH_SMSG_FAILURE: case SSH_SMSG_FAILURE:
leave_function();
return SSH_AUTH_DENIED; return SSH_AUTH_DENIED;
} }
ssh_set_error(session, SSH_FATAL, "Was waiting for a SUCCESS or " ssh_set_error(session, SSH_FATAL, "Was waiting for a SUCCESS or "
"FAILURE, got %d", session->in_packet.type); "FAILURE, got %d", session->in_packet.type);
leave_function();
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
} }
static int send_username(ssh_session session, const char *username) { static int send_username(ssh_session session, const char *username) {
ssh_string user = NULL; ssh_string user = NULL;
/* returns SSH_AUTH_SUCCESS or SSH_AUTH_DENIED */ /* returns SSH_AUTH_SUCCESS or SSH_AUTH_DENIED */
enter_function();
if(session->auth_service_asked) { if(session->auth_service_asked) {
leave_function();
return session->auth_service_asked; return session->auth_service_asked;
} }
if (!username) { if (!username) {
if(!(username = session->username)) { if(!(username = session->username)) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) {
leave_function();
return session->auth_service_asked = SSH_AUTH_ERROR; return session->auth_service_asked = SSH_AUTH_ERROR;
} else { } else {
username = session->username; username = session->username;
@@ -75,24 +83,30 @@ static int send_username(ssh_session session, const char *username) {
} }
user = string_from_char(username); user = string_from_char(username);
if (user == NULL) { if (user == NULL) {
leave_function();
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
} }
if (buffer_add_u8(session->out_buffer, SSH_CMSG_USER) < 0) { if (buffer_add_u8(session->out_buffer, SSH_CMSG_USER) < 0) {
string_free(user); string_free(user);
leave_function();
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
} }
if (buffer_add_ssh_string(session->out_buffer, user) < 0) { if (buffer_add_ssh_string(session->out_buffer, user) < 0) {
string_free(user); string_free(user);
leave_function();
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
} }
string_free(user); string_free(user);
if (packet_send(session) != SSH_OK) { if (packet_send(session) != SSH_OK) {
leave_function();
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
} }
session->auth_service_asked = wait_auth1_status(session); session->auth_service_asked = wait_auth1_status(session);
if(session->auth_service_asked != SSH_AUTH_ERROR)
session->auth_methods=SSH_AUTH_METHOD_PASSWORD;
leave_function();
return session->auth_service_asked; return session->auth_service_asked;
} }

View File

@@ -165,8 +165,10 @@ static int channel_open(ssh_channel channel, const char *type_c, int window,
type_c, channel->local_channel); type_c, channel->local_channel);
if (packet_wait(session, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, 1) != SSH_OK) { if (packet_wait(session, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, 1) != SSH_OK) {
leave_function(); if(session->in_packet.type != SSH2_MSG_CHANNEL_OPEN_FAILURE) {
return -1; leave_function();
return -1;
}
} }
switch(session->in_packet.type) { switch(session->in_packet.type) {
@@ -552,6 +554,15 @@ static void channel_rcv_request(ssh_session session) {
return; 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 */ /* TODO call message_handle since it handles channel requests as messages */
/* *but* reset buffer before !! */ /* *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_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){ void channel_handle(ssh_session session, int type){
enter_function(); enter_function();
@@ -785,7 +796,7 @@ void channel_free(ssh_channel channel) {
* *
* @param channel The channel to send the eof to. * @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 * SSH_ERROR on error\n
* *
* @see channel_close() * @see channel_close()
@@ -828,7 +839,7 @@ error:
* *
* @param channel The channel to close. * @param channel The channel to close.
* *
* @return SSH_SUCCESS on success\n * @return SSH_OK on success\n
* SSH_ERROR on error * SSH_ERROR on error
* *
* @see channel_free() * @see channel_free()
@@ -1107,7 +1118,7 @@ error:
* *
* @param row The number of rows. * @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 channel_request_pty_size(ssh_channel channel, const char *terminal,
int col, int row) { int col, int row) {
@@ -1158,7 +1169,7 @@ error:
* *
* @param channel The channel to send the request. * @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() * @see channel_request_pty_size()
*/ */
@@ -1219,7 +1230,7 @@ error:
* *
* @param channel The channel to send the request. * @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) { int channel_request_shell(ssh_channel channel) {
#ifdef WITH_SSH1 #ifdef WITH_SSH1
@@ -1237,7 +1248,7 @@ int channel_request_shell(ssh_channel channel) {
* *
* @param subsys The subsystem to request (for example "sftp"). * @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(). * @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 #endif
ssh_message msg = NULL; ssh_message msg = NULL;
ssh_channel channel = NULL;
struct ssh_iterator *iterator; struct ssh_iterator *iterator;
int t; 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 && if (ssh_message_type(msg) == SSH_REQUEST_CHANNEL_OPEN &&
ssh_message_subtype(msg) == channeltype) { ssh_message_subtype(msg) == channeltype) {
ssh_list_remove(session->ssh_message_list, iterator); 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; iterator = iterator->next;
} }
} }
if(t>0){
#ifdef _WIN32 #ifdef _WIN32
Sleep(50); /* 50ms */ Sleep(50); /* 50ms */
#else #else
nanosleep(&ts, NULL); nanosleep(&ts, NULL);
#endif #endif
}
} }
return NULL; return NULL;
@@ -1582,7 +1598,7 @@ error:
* *
* @param value The value to set. * @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. * @warning Some environement variables may be refused by security reasons.
* */ * */
@@ -1633,7 +1649,7 @@ error:
* @param cmd The command to execute * @param cmd The command to execute
* (e.g. "ls ~/ -al | grep -i reports"). * (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() * @see channel_request_shell()
*/ */
@@ -1683,7 +1699,7 @@ error:
* @param signal The signal to send (without SIG prefix) * @param signal The signal to send (without SIG prefix)
* (e.g. "TERM" or "KILL"). * (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) { 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) { if (count == 0) {
/* write the ful buffer informations */ /* write the ful buffer information */
if (buffer_add_data(buffer, buffer_get_rest(stdbuf), if (buffer_add_data(buffer, buffer_get_rest(stdbuf),
buffer_get_rest_len(stdbuf)) < 0) { buffer_get_rest_len(stdbuf)) < 0) {
leave_function(); leave_function();
@@ -1995,9 +2011,10 @@ int channel_poll(ssh_channel channel, int is_stderr){
stdbuf = channel->stderr_buffer; stdbuf = channel->stderr_buffer;
} }
while (buffer_get_rest_len(stdbuf) == 0 && channel->remote_eof == 0) { if (buffer_get_rest_len(stdbuf) == 0 && channel->remote_eof == 0) {
if (ssh_handle_packets(channel->session) <= 0) { if (ssh_handle_packets(channel->session) == SSH_ERROR) {
break; leave_function();
return SSH_ERROR;
} }
} }
@@ -2137,7 +2154,7 @@ static int count_ptrs(ssh_channel *ptrs) {
* *
* @param timeout Timeout as defined by select(2). * @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 * SSH_EINTR select(2) syscall was interrupted, relaunch the function
*/ */
int channel_select(ssh_channel *readchans, ssh_channel *writechans, 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 rset;
fd_set wset; fd_set wset;
fd_set eset; fd_set eset;
int fdmax = -1; socket_t max_fd = SSH_INVALID_SOCKET;
int rc; int rc;
int i; int i;
@@ -2215,24 +2232,24 @@ int channel_select(ssh_channel *readchans, ssh_channel *writechans,
for (i = 0; readchans[i] != NULL; i++) { for (i = 0; readchans[i] != NULL; i++) {
if (!ssh_socket_fd_isset(readchans[i]->session->socket, &rset)) { 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++) { for (i = 0; writechans[i] != NULL; i++) {
if (!ssh_socket_fd_isset(writechans[i]->session->socket, &wset)) { 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++) { for (i = 0; exceptchans[i] != NULL; i++) {
if (!ssh_socket_fd_isset(exceptchans[i]->session->socket, &eset)) { 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 */ /* Here we go */
rc = select(fdmax, &rset, &wset, &eset, timeout); rc = select(max_fd, &rset, &wset, &eset, timeout);
/* Leave if select was interrupted */ /* Leave if select was interrupted */
if (rc == EINTR) { if (rc == EINTR) {
SAFE_FREE(rchans); SAFE_FREE(rchans);

View File

@@ -26,6 +26,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#ifndef _WIN32
#include <arpa/inet.h>
#endif
#include "libssh/priv.h" #include "libssh/priv.h"
#include "libssh/ssh1.h" #include "libssh/ssh1.h"
#include "libssh/buffer.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 *banner = session->serverbanner;
const char *openssh; const char *openssh;
ssh_log(session, SSH_LOG_RARE, "Analyzing banner: %s", banner); if (banner == NULL) {
ssh_set_error(session, SSH_FATAL, "Invalid banner");
if (strncmp(banner, "SSH-", 4) != 0) { return -1;
ssh_set_error(session, SSH_FATAL, "Protocol mismatch: %s", banner);
return -1;
} }
/* /*
* Typical banners e.g. are: * Typical banners e.g. are:
* SSH-1.5-blah *
* SSH-1.99-blah * SSH-1.5-openSSH_5.4
* SSH-2.0-blah * 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]) { switch(banner[4]) {
case '1': case '1':
*ssh1 = 1; *ssh1 = 1;
if (banner[6] == '9') { if (strlen(banner) > 6) {
*ssh2 = 1; if (banner[6] == '9') {
} else { *ssh2 = 1;
*ssh2 = 0; } else {
*ssh2 = 0;
}
} }
break; break;
case '2': case '2':
@@ -143,13 +154,21 @@ static int ssh_analyze_banner(ssh_session session, int *ssh1, int *ssh2) {
openssh = strstr(banner, "OpenSSH"); openssh = strstr(banner, "OpenSSH");
if (openssh != NULL) { if (openssh != NULL) {
int major, minor; 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); * The banner is typical:
ssh_log(session, SSH_LOG_RARE, * OpenSSH_5.4
"We are talking to an OpenSSH server version: %d.%d (%x)", * 012345678901234567890
major, minor, session->openssh); */
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; return 0;
@@ -296,6 +315,7 @@ static int dh_handshake(ssh_session session) {
goto error; goto error;
} }
session->dh_server_signature = signature; session->dh_server_signature = signature;
signature=NULL; /* ownership changed */
if (dh_build_k(session) < 0) { if (dh_build_k(session) < 0) {
ssh_set_error(session, SSH_FATAL, "Cannot build k number"); ssh_set_error(session, SSH_FATAL, "Cannot build k number");
rc = SSH_ERROR; rc = SSH_ERROR;
@@ -400,10 +420,6 @@ error:
string_burn(f); string_burn(f);
string_free(f); string_free(f);
} }
if(pubkey != NULL){
string_burn(pubkey);
string_free(pubkey);
}
if(signature != NULL){ if(signature != NULL){
string_burn(signature); string_burn(signature);
string_free(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 ssh_connect(ssh_session session) {
int ssh1 = 0; int ssh1 = 0;
int ssh2 = 0; int ssh2 = 0;
int fd = -1; socket_t fd = SSH_INVALID_SOCKET;
int ret;
if (session == NULL) { if (session == NULL) {
ssh_set_error(session, SSH_FATAL, "Invalid session pointer"); ssh_set_error(session, SSH_FATAL, "Invalid session pointer");
@@ -500,18 +517,31 @@ int ssh_connect(ssh_session session) {
leave_function(); leave_function();
return SSH_ERROR; 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"); ssh_set_error(session, SSH_FATAL, "Hostname required");
leave_function(); leave_function();
return SSH_ERROR; 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; fd = session->fd;
#ifndef _WIN32
} else if (session->ProxyCommand != NULL) {
fd=ssh_socket_connect_proxycommand(session, session->ProxyCommand);
#endif
} else { } else {
fd = ssh_connect_host(session, session->host, session->bindaddr, fd = ssh_connect_host(session, session->host, session->bindaddr,
session->port, session->timeout, session->timeout_usec); session->port, session->timeout, session->timeout_usec);
} }
if (fd < 0) { if (fd == SSH_INVALID_SOCKET) {
leave_function(); leave_function();
return SSH_ERROR; return SSH_ERROR;
} }
@@ -543,8 +573,10 @@ int ssh_connect(ssh_session session) {
/* Here we decide which version of the protocol to use. */ /* Here we decide which version of the protocol to use. */
if (ssh2 && session->ssh2) { if (ssh2 && session->ssh2) {
session->version = 2; session->version = 2;
#ifdef WITH_SSH1
} else if(ssh1 && session->ssh1) { } else if(ssh1 && session->ssh1) {
session->version = 1; session->version = 1;
#endif
} else { } else {
ssh_set_error(session, SSH_FATAL, ssh_set_error(session, SSH_FATAL,
"No version of SSH protocol usable (banner: %s)", "No version of SSH protocol usable (banner: %s)",
@@ -599,6 +631,7 @@ int ssh_connect(ssh_session session) {
session->connected = 1; session->connected = 1;
break; break;
#ifdef WITH_SSH1
case 1: case 1:
if (ssh_get_kex1(session) < 0) { if (ssh_get_kex1(session) < 0) {
ssh_socket_close(session->socket); ssh_socket_close(session->socket);
@@ -610,6 +643,7 @@ int ssh_connect(ssh_session session) {
session->connected = 1; session->connected = 1;
break; break;
#endif
} }
leave_function(); leave_function();
@@ -699,7 +733,7 @@ error:
const char *ssh_copyright(void) { const char *ssh_copyright(void) {
return SSH_STRINGIFY(LIBSSH_VERSION) " (c) 2003-2008 Aris Adamantiadis " return SSH_STRINGIFY(LIBSSH_VERSION) " (c) 2003-2008 Aris Adamantiadis "
"(aris@0xbadc0de.be) Distributed under the LGPL, please refer to COPYING" "(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: */ /* vim: set ts=2 sw=2 et cindent: */

View File

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

View File

@@ -67,10 +67,7 @@
#include "libssh/socket.h" #include "libssh/socket.h"
#include "libssh/channels.h" #include "libssh/channels.h"
#include "libssh/session.h" #include "libssh/session.h"
#include "libssh/poll.h"
#ifndef HAVE_SELECT
#error "Your system must have select()"
#endif
#ifndef HAVE_GETADDRINFO #ifndef HAVE_GETADDRINFO
#error "Your system must 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, static int ssh_connect_ai_timeout(ssh_session session, const char *host,
int port, struct addrinfo *ai, long timeout, long usec, socket_t s) { int port, struct addrinfo *ai, long timeout, long usec, socket_t s) {
struct timeval to; int timeout_ms;
fd_set set; ssh_pollfd_t fds;
int rc = 0; int rc = 0;
unsigned int len = sizeof(rc); unsigned int len = sizeof(rc);
enter_function(); enter_function();
to.tv_sec = timeout; /* I know we're losing some precision. But it's not like poll-like family
to.tv_usec = usec; * type of mechanisms are precise up to the microsecond.
*/
timeout_ms=timeout * 1000 + usec / 1000;
sock_set_nonblocking(s); sock_set_nonblocking(s);
ssh_log(session, SSH_LOG_RARE, "Trying to connect to host: %s:%d with " 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 */ /* The return value is checked later */
connect(s, ai->ai_addr, ai->ai_addrlen); connect(s, ai->ai_addr, ai->ai_addrlen);
freeaddrinfo(ai); freeaddrinfo(ai);
FD_ZERO(&set); fds.fd=s;
FD_SET(s, &set); 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) { if (rc == 0) {
/* timeout */ /* timeout */
ssh_set_error(session, SSH_FATAL, 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) { if (rc < 0) {
ssh_set_error(session, SSH_FATAL, ssh_set_error(session, SSH_FATAL,
"Select error: %s", strerror(errno)); "poll error: %s", strerror(errno));
ssh_connect_socket_close(s); ssh_connect_socket_close(s);
leave_function(); leave_function();
return -1; 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_set_error(session, SSH_FATAL, "Connect failed: %s", strerror(errno));
ssh_connect_socket_close(s); ssh_connect_socket_close(s);
s = -1; s = -1;
leave_function();
continue; continue;
} else { } else {
/* We are connected */ /* 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) { fd_set *readfds, struct timeval *timeout) {
struct timeval zerotime; struct timeval zerotime;
fd_set localset, localset2; fd_set localset, localset2;
socket_t f;
int rep; int rep;
int set; int set;
int i; 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 */ /* Look into the localset for active fd */
set = 0; set = 0;
for (i = 0; (i < maxfd) && !set; i++) { for (f = 0; (f < maxfd) && !set; f++) {
if (FD_ISSET(i, &localset)) { if (FD_ISSET(f, &localset)) {
set = 1; set = 1;
} }
} }
@@ -494,9 +497,9 @@ int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
outchannels[j] = NULL; outchannels[j] = NULL;
FD_ZERO(&localset2); FD_ZERO(&localset2);
for (i = 0; i < maxfd; i++) { for (f = 0; f < maxfd; f++) {
if (FD_ISSET(i, readfds) && FD_ISSET(i, &localset)) { if (FD_ISSET(f, readfds) && FD_ISSET(i, &localset)) {
FD_SET(i, &localset2); 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; return;
} }
printf("%s: %s\n", descr, hexa); printf("%s: %s\n", descr, hexa);
free(hexa);
} }
int dh_generate_x(ssh_session session) { 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) { if (session == NULL || hash == NULL) {
return -1; return -1;
} }
*hash = NULL; *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); h = malloc(sizeof(unsigned char *) * MD5_DIGEST_LEN);
if (h == NULL) { if (h == NULL) {

View File

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

View File

@@ -40,10 +40,11 @@
#include "libssh/wrapper.h" #include "libssh/wrapper.h"
#include "libssh/keys.h" #include "libssh/keys.h"
#include "libssh/dh.h" #include "libssh/dh.h"
#include "libssh/string.h"
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
#define BLOWFISH "blowfish-cbc," #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" #define DES "3des-cbc"
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
#ifdef HAVE_OPENSSL_BLOWFISH_H #ifdef HAVE_OPENSSL_BLOWFISH_H
@@ -52,10 +53,15 @@
#define BLOWFISH "" #define BLOWFISH ""
#endif #endif
#ifdef HAVE_OPENSSL_AES_H #ifdef HAVE_OPENSSL_AES_H
#ifdef BROKEN_AES_CTR
#define AES "aes256-cbc,aes192-cbc,aes128-cbc," #define AES "aes256-cbc,aes192-cbc,aes128-cbc,"
#else #else
#define AES "aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,"
#endif /* BROKEN_AES_CTR */
#else
#define AES "" #define AES ""
#endif #endif
#define DES "3des-cbc" #define DES "3des-cbc"
#endif #endif
@@ -67,7 +73,7 @@
const char *default_methods[] = { const char *default_methods[] = {
"diffie-hellman-group1-sha1", "diffie-hellman-group1-sha1",
"ssh-dss,ssh-rsa", "ssh-rsa,ssh-dss",
AES BLOWFISH DES, AES BLOWFISH DES,
AES BLOWFISH DES, AES BLOWFISH DES,
"hmac-sha1", "hmac-sha1",
@@ -81,7 +87,7 @@ const char *default_methods[] = {
const char *supported_methods[] = { const char *supported_methods[] = {
"diffie-hellman-group1-sha1", "diffie-hellman-group1-sha1",
"ssh-dss,ssh-rsa", "ssh-rsa,ssh-dss",
AES BLOWFISH DES, AES BLOWFISH DES,
AES BLOWFISH DES, AES BLOWFISH DES,
"hmac-sha1", "hmac-sha1",
@@ -194,48 +200,48 @@ char **space_tokenize(const char *chain){
return tokens; return tokens;
} }
/* find_matching gets 2 parameters : a list of available objects (in_d), separated by colons,*/ /* find_matching gets 2 parameters : a list of available objects (available_d), separated by colons,*/
/* and a list of prefered objects (what_d) */ /* 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 */ /* 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 *ssh_find_matching(const char *available_d, const char *preferred_d){
char ** tok_in, **tok_what; char ** tok_available, **tok_preferred;
int i_in, i_what; int i_avail, i_pref;
char *ret; char *ret;
if ((in_d == NULL) || (what_d == NULL)) { if ((available_d == NULL) || (preferred_d == NULL)) {
return NULL; /* don't deal with null args */ return NULL; /* don't deal with null args */
} }
tok_in = tokenize(in_d); tok_available = tokenize(available_d);
if (tok_in == NULL) { if (tok_available == NULL) {
return NULL; return NULL;
} }
tok_what = tokenize(what_d); tok_preferred = tokenize(preferred_d);
if (tok_what == NULL) { if (tok_preferred == NULL) {
SAFE_FREE(tok_in[0]); SAFE_FREE(tok_available[0]);
SAFE_FREE(tok_in); SAFE_FREE(tok_available);
} }
for(i_in=0; tok_in[i_in]; ++i_in){ for(i_pref=0; tok_preferred[i_pref] ; ++i_pref){
for(i_what=0; tok_what[i_what] ; ++i_what){ for(i_avail=0; tok_available[i_avail]; ++i_avail){
if(!strcmp(tok_in[i_in],tok_what[i_what])){ if(!strcmp(tok_available[i_avail],tok_preferred[i_pref])){
/* match */ /* match */
ret=strdup(tok_in[i_in]); ret=strdup(tok_available[i_avail]);
/* free the tokens */ /* free the tokens */
free(tok_in[0]); free(tok_available[0]);
free(tok_what[0]); free(tok_preferred[0]);
free(tok_in); free(tok_available);
free(tok_what); free(tok_preferred);
return ret; return ret;
}
} }
}
} }
free(tok_in[0]); free(tok_available[0]);
free(tok_what[0]); free(tok_preferred[0]);
free(tok_in); free(tok_available);
free(tok_what); free(tok_preferred);
return NULL; return NULL;
} }
@@ -444,6 +450,8 @@ int verify_existing_algo(int algo, const char *name){
return 0; return 0;
} }
#ifdef WITH_SSH1
/* makes a STRING contating 3 strings : ssh-rsa1,e and n */ /* makes a STRING contating 3 strings : ssh-rsa1,e and n */
/* this is a public key in openssh's format */ /* this is a public key in openssh's format */
static ssh_string make_rsa1_string(ssh_string e, ssh_string n){ static ssh_string make_rsa1_string(ssh_string e, ssh_string n){
@@ -487,8 +495,8 @@ static int build_session_id1(ssh_session session, ssh_string servern,
} }
#ifdef DEBUG_CRYPTO #ifdef DEBUG_CRYPTO
ssh_print_hexa("host modulus",hostn->string,string_len(hostn)); ssh_print_hexa("host modulus",string_data(hostn),string_len(hostn));
ssh_print_hexa("server modulus",servern->string,string_len(servern)); ssh_print_hexa("server modulus",string_data(servern),string_len(servern));
#endif #endif
md5_update(md5,string_data(hostn),string_len(hostn)); md5_update(md5,string_data(hostn),string_len(hostn));
md5_update(md5,string_data(servern),string_len(servern)); md5_update(md5,string_data(servern),string_len(servern));
@@ -501,6 +509,7 @@ static int build_session_id1(ssh_session session, ssh_string servern,
return 0; return 0;
} }
/* returns 1 if the modulus of k1 is < than the one of k2 */ /* returns 1 if the modulus of k1 is < than the one of k2 */
static int modulus_smaller(ssh_public_key k1, ssh_public_key k2){ static int modulus_smaller(ssh_public_key k1, ssh_public_key k2){
bignum n1; bignum n1;
@@ -790,4 +799,6 @@ error:
return rc; return rc;
} }
#endif /* WITH_SSH1 */
/* vim: set ts=2 sw=2 et cindent: */ /* vim: set ts=2 sw=2 et cindent: */

View File

@@ -59,15 +59,15 @@
#endif /* HAVE_LIBCRYPTO */ #endif /* HAVE_LIBCRYPTO */
#define MAXLINESIZE 80 #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 #ifdef HAVE_LIBGCRYPT
#define MAX_KEY_SIZE 32 #define MAX_KEY_SIZE 32
#define MAX_PASSPHRASE_SIZE 1024 #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_INTEGER 2
#define ASN1_SEQUENCE 48 #define ASN1_SEQUENCE 48
#define PKCS5_SALT_LEN 8 #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 */ #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 /** \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 /** \brief Reads a SSH private key from a file
* \param session SSH Session * \param session SSH Session
* \param filename Filename containing the private key * \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. * \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. * \returns a PRIVATE_KEY object containing the private key, or NULL if it failed.
* \see privatekey_free() * \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", ssh_log(session, SSH_LOG_RARE, "Trying to read %s, passphase=%s, authcb=%s",
filename, passphrase ? "true" : "false", filename, passphrase ? "true" : "false",
session->callbacks && session->callbacks->auth_function ? "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) { switch (type) {
case TYPE_DSS: case TYPE_DSS:
if (passphrase == NULL) { if (passphrase == NULL) {
if (session->callbacks->auth_function) { if (session->callbacks && session->callbacks->auth_function) {
auth_cb = session->callbacks->auth_function; auth_cb = session->callbacks->auth_function;
auth_ud = session->callbacks->userdata; auth_ud = session->callbacks->userdata;
@@ -731,6 +756,7 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
} }
break; break;
default: default:
fclose(file);
ssh_set_error(session, SSH_FATAL, "Invalid private key type %d", type); ssh_set_error(session, SSH_FATAL, "Invalid private key type %d", type);
return NULL; return NULL;
} /* switch */ } /* switch */
@@ -754,6 +780,20 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
return privkey; 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. */ /* same that privatekey_from_file() but without any passphrase things. */
ssh_private_key _privatekey_from_file(void *session, const char *filename, ssh_private_key _privatekey_from_file(void *session, const char *filename,
int type) { int type) {
@@ -861,6 +901,79 @@ void privatekey_free(ssh_private_key prv) {
SAFE_FREE(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 /** \brief Retrieve a public key from a file
* \param session the SSH session * \param session the SSH session
* \param filename Filename of the key * \param filename Filename of the key
@@ -938,10 +1051,85 @@ ssh_string publickey_from_file(ssh_session session, const char *filename,
return str; 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, ssh_string try_publickey_from_file(ssh_session session, struct ssh_keys_struct keytab,
char **privkeyfile, int *type) { char **privkeyfile, int *type) {
char *public;
char *private;
const char *priv; const char *priv;
const char *pub; const char *pub;
char *new; 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 (session->sshdir == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL) < 0) { if (ssh_options_apply(session) < 0) {
return NULL; return NULL;
} }
} }
/* are them readable ? */ ssh_log(session, SSH_LOG_PACKET, "Trying to open publickey %s", pub);
public=dir_expand_dup(session,pub,1); if (!ssh_file_readaccess_ok(pub)) {
private=dir_expand_dup(session,priv,1); ssh_log(session, SSH_LOG_PACKET, "Failed to open publickey %s", pub);
//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);
goto error; goto error;
} }
ssh_log(session, SSH_LOG_PACKET, "Trying to open privatekey %s", private); ssh_log(session, SSH_LOG_PACKET, "Trying to open privatekey %s", priv);
if (!ssh_file_readaccess_ok(private)) { if (!ssh_file_readaccess_ok(priv)) {
ssh_log(session, SSH_LOG_PACKET, "Failed to open privatekey %s", private); ssh_log(session, SSH_LOG_PACKET, "Failed to open privatekey %s", priv);
goto error; 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 * 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 * 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) { if (pubkey == NULL) {
ssh_log(session, SSH_LOG_PACKET, ssh_log(session, SSH_LOG_PACKET,
"Wasn't able to open public key file %s: %s", "Wasn't able to open public key file %s: %s",
public, pub,
ssh_get_error(session)); ssh_get_error(session));
goto error; goto error;
} }
new = realloc(*privkeyfile, strlen(private) + 1); new = realloc(*privkeyfile, strlen(priv) + 1);
if (new == NULL) { if (new == NULL) {
string_free(pubkey); string_free(pubkey);
goto error; goto error;
} }
strcpy(new, private); strcpy(new, priv);
*privkeyfile = new; *privkeyfile = new;
error: error:
SAFE_FREE(public);
SAFE_FREE(private);
return pubkey; return pubkey;
} }
@@ -1277,6 +1457,7 @@ static int match_hashed_host(ssh_session session, const char *host,
enter_function(); enter_function();
if (strncmp(sourcehash, "|1|", 3) != 0) { if (strncmp(sourcehash, "|1|", 3) != 0) {
leave_function();
return 0; return 0;
} }
@@ -1370,7 +1551,6 @@ static int match_hashed_host(ssh_session session, const char *host,
* if host key is accepted\n * if host key is accepted\n
* SSH_SERVER_ERROR: Some error happened * SSH_SERVER_ERROR: Some error happened
* *
* \see ssh_options_set()
* \see ssh_get_pubkey_hash() * \see ssh_get_pubkey_hash()
* *
* \bug There is no current way to remove or modify an entry into the known * \bug There is no current way to remove or modify an entry into the known
@@ -1380,6 +1560,7 @@ int ssh_is_server_known(ssh_session session) {
FILE *file = NULL; FILE *file = NULL;
char **tokens; char **tokens;
char *host; char *host;
char *hostport;
const char *type; const char *type;
int match; int match;
int ret = SSH_SERVER_NOT_KNOWN; int ret = SSH_SERVER_NOT_KNOWN;
@@ -1387,7 +1568,7 @@ int ssh_is_server_known(ssh_session session) {
enter_function(); enter_function();
if (session->knownhosts == NULL) { 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, ssh_set_error(session, SSH_REQUEST_DENIED,
"Can't find a known_hosts file"); "Can't find a known_hosts file");
leave_function(); leave_function();
@@ -1403,8 +1584,11 @@ int ssh_is_server_known(ssh_session session) {
} }
host = lowercase(session->host); host = lowercase(session->host);
if (host == NULL) { hostport = ssh_hostport(host,session->port);
ssh_set_error(session, SSH_FATAL, "Not enough space!"); if (host == NULL || hostport == NULL) {
ssh_set_error_oom(session);
SAFE_FREE(host);
SAFE_FREE(hostport);
leave_function(); leave_function();
return SSH_SERVER_ERROR; return SSH_SERVER_ERROR;
} }
@@ -1418,10 +1602,15 @@ int ssh_is_server_known(ssh_session session) {
break; break;
} }
match = match_hashed_host(session, host, tokens[0]); match = match_hashed_host(session, host, tokens[0]);
if (match == 0){
match = match_hostname(hostport, tokens[0], strlen(tokens[0]));
}
if (match == 0) { if (match == 0) {
match = match_hostname(host, tokens[0], strlen(tokens[0])); match = match_hostname(host, tokens[0], strlen(tokens[0]));
} }
if (match == 0) {
match = match_hashed_host(session, hostport, tokens[0]);
}
if (match) { if (match) {
/* We got a match. Now check the key type */ /* We got a match. Now check the key type */
if (strcmp(session->current_crypto->server_pubkey_type, type) != 0) { if (strcmp(session->current_crypto->server_pubkey_type, type) != 0) {
@@ -1452,6 +1641,7 @@ int ssh_is_server_known(ssh_session session) {
} while (1); } while (1);
SAFE_FREE(host); SAFE_FREE(host);
SAFE_FREE(hostport);
if (file != NULL) { if (file != NULL) {
fclose(file); fclose(file);
} }
@@ -1461,10 +1651,15 @@ int ssh_is_server_known(ssh_session session) {
return ret; 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. * @brief Write the current server as known in the known hosts file.
* \param session ssh session *
* \return 0 on success, -1 on error * 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) { int ssh_write_knownhost(ssh_session session) {
ssh_string pubkey = session->current_crypto->server_pubkey; ssh_string pubkey = session->current_crypto->server_pubkey;
@@ -1472,17 +1667,30 @@ int ssh_write_knownhost(ssh_session session) {
char buffer[4096] = {0}; char buffer[4096] = {0};
FILE *file; FILE *file;
char *dir; char *dir;
char *host;
char *hostport;
size_t len = 0; 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) { if (session->host == NULL) {
ssh_set_error(session, SSH_FATAL, ssh_set_error(session, SSH_FATAL,
"Cannot write host in known hosts if the hostname is unknown"); "Can't write host in known hosts if the hostname isn't known");
return -1; 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 */ /* Check if ~/.ssh exists and create it if not */
@@ -1506,6 +1714,7 @@ int ssh_write_knownhost(ssh_session session) {
ssh_set_error(session, SSH_FATAL, ssh_set_error(session, SSH_FATAL,
"Couldn't open known_hosts file %s for appending: %s", "Couldn't open known_hosts file %s for appending: %s",
session->knownhosts, strerror(errno)); session->knownhosts, strerror(errno));
SAFE_FREE(host);
return -1; return -1;
} }
@@ -1525,6 +1734,7 @@ int ssh_write_knownhost(ssh_session session) {
key = publickey_from_string(session, pubkey); key = publickey_from_string(session, pubkey);
if (key == NULL) { if (key == NULL) {
fclose(file); fclose(file);
SAFE_FREE(host);
return -1; return -1;
} }
@@ -1533,6 +1743,7 @@ int ssh_write_knownhost(ssh_session session) {
if (sexp == NULL) { if (sexp == NULL) {
publickey_free(key); publickey_free(key);
fclose(file); fclose(file);
SAFE_FREE(host);
return -1; return -1;
} }
e = gcry_sexp_nth_mpi(sexp, 1, GCRYMPI_FMT_USG); e = gcry_sexp_nth_mpi(sexp, 1, GCRYMPI_FMT_USG);
@@ -1540,6 +1751,7 @@ int ssh_write_knownhost(ssh_session session) {
if (e == NULL) { if (e == NULL) {
publickey_free(key); publickey_free(key);
fclose(file); fclose(file);
SAFE_FREE(host);
return -1; return -1;
} }
@@ -1548,6 +1760,7 @@ int ssh_write_knownhost(ssh_session session) {
publickey_free(key); publickey_free(key);
bignum_free(e); bignum_free(e);
fclose(file); fclose(file);
SAFE_FREE(host);
return -1; return -1;
} }
n = gcry_sexp_nth_mpi(sexp, 1, GCRYMPI_FMT_USG); n = gcry_sexp_nth_mpi(sexp, 1, GCRYMPI_FMT_USG);
@@ -1556,6 +1769,7 @@ int ssh_write_knownhost(ssh_session session) {
publickey_free(key); publickey_free(key);
bignum_free(e); bignum_free(e);
fclose(file); fclose(file);
SAFE_FREE(host);
return -1; return -1;
} }
@@ -1580,12 +1794,13 @@ int ssh_write_knownhost(ssh_session session) {
#endif #endif
publickey_free(key); publickey_free(key);
fclose(file); fclose(file);
SAFE_FREE(host);
return -1; return -1;
} }
snprintf(buffer, sizeof(buffer), snprintf(buffer, sizeof(buffer),
"%s %d %s %s\n", "%s %d %s %s\n",
session->host, host,
rsa_size << 3, rsa_size << 3,
e_string, e_string,
n_string); n_string);
@@ -1605,18 +1820,19 @@ int ssh_write_knownhost(ssh_session session) {
pubkey_64 = bin_to_base64(pubkey->string, string_len(pubkey)); pubkey_64 = bin_to_base64(pubkey->string, string_len(pubkey));
if (pubkey_64 == NULL) { if (pubkey_64 == NULL) {
fclose(file); fclose(file);
SAFE_FREE(host);
return -1; return -1;
} }
snprintf(buffer, sizeof(buffer), snprintf(buffer, sizeof(buffer),
"%s %s %s\n", "%s %s %s\n",
session->host, host,
session->current_crypto->server_pubkey_type, session->current_crypto->server_pubkey_type,
pubkey_64); pubkey_64);
SAFE_FREE(pubkey_64); SAFE_FREE(pubkey_64);
} }
SAFE_FREE(host);
len = strlen(buffer); len = strlen(buffer);
if (fwrite(buffer, len, 1, file) != 1 || ferror(file)) { if (fwrite(buffer, len, 1, file) != 1 || ferror(file)) {
fclose(file); fclose(file);

View File

@@ -36,6 +36,7 @@
#include "libssh/keys.h" #include "libssh/keys.h"
#include "libssh/dh.h" #include "libssh/dh.h"
#include "libssh/messages.h" #include "libssh/messages.h"
#include "libssh/string.h"
/** \addtogroup ssh_auth /** \addtogroup ssh_auth
* @{ * @{
@@ -130,9 +131,9 @@ ssh_public_key publickey_make_dss(ssh_session session, ssh_buffer buffer) {
#endif /* HAVE_LIBCRYPTO */ #endif /* HAVE_LIBCRYPTO */
#ifdef DEBUG_CRYPTO #ifdef DEBUG_CRYPTO
ssh_print_hexa("p", p->string, string_len(p)); ssh_print_hexa("p", string_data(p), string_len(p));
ssh_print_hexa("q", q->string, string_len(q)); ssh_print_hexa("q", string_data(q), string_len(q));
ssh_print_hexa("g", g->string, string_len(g)); ssh_print_hexa("g", string_data(g), string_len(g));
#endif #endif
string_burn(p); string_burn(p);
@@ -206,8 +207,8 @@ ssh_public_key publickey_make_rsa(ssh_session session, ssh_buffer buffer,
#endif #endif
#ifdef DEBUG_CRYPTO #ifdef DEBUG_CRYPTO
ssh_print_hexa("e", e->string, string_len(e)); ssh_print_hexa("e", string_data(e), string_len(e));
ssh_print_hexa("n", n->string, string_len(n)); ssh_print_hexa("n", string_data(n), string_len(n));
#endif #endif
string_burn(e); string_burn(e);
@@ -974,8 +975,8 @@ SIGNATURE *signature_from_string(ssh_session session, ssh_string signature,
#endif #endif
#ifdef DEBUG_CRYPTO #ifdef DEBUG_CRYPTO
ssh_print_hexa("r", rs->string, 20); ssh_print_hexa("r", string_data(rs), 20);
ssh_print_hexa("s", rs->string + 20, 20); ssh_print_hexa("s", (const unsigned char *)string_data(rs) + 20, 20);
#endif #endif
string_free(rs); string_free(rs);
@@ -1024,7 +1025,7 @@ SIGNATURE *signature_from_string(ssh_session session, ssh_string signature,
#ifdef DEBUG_CRYPTO #ifdef DEBUG_CRYPTO
ssh_log(session, SSH_LOG_FUNCTIONS, "len e: %d", len); 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 #endif
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
@@ -1307,6 +1308,9 @@ ssh_string ssh_do_sign(ssh_session session, ssh_buffer sigbuf,
#endif #endif
sign->dsa_sign = NULL; sign->dsa_sign = NULL;
break; break;
default:
signature_free(sign);
return NULL;
} }
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
gcry_sexp_release(gcryhash); gcry_sexp_release(gcryhash);
@@ -1462,6 +1466,9 @@ ssh_string ssh_sign_session_id(ssh_session session, ssh_private_key privatekey)
#endif #endif
sign->dsa_sign = NULL; sign->dsa_sign = NULL;
break; break;
default:
signature_free(sign);
return NULL;
} }
#ifdef HAVE_LIBGCRYPT #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, ssh_log(session, SSH_LOG_PACKET,
"Clients wants to open a %s channel", type_c); "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, &sender);
buffer_get_u32(session->in_buffer, &window); 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) { if (strcmp(type_c,"session") == 0) {
msg->channel_request_open.type = SSH_CHANNEL_SESSION; msg->channel_request_open.type = SSH_CHANNEL_SESSION;
string_free(type);
SAFE_FREE(type_c); SAFE_FREE(type_c);
leave_function(); leave_function();
return msg; 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.originator_port = ntohl(originator_port);
msg->channel_request_open.type = SSH_CHANNEL_DIRECT_TCPIP; msg->channel_request_open.type = SSH_CHANNEL_DIRECT_TCPIP;
string_free(type);
SAFE_FREE(type_c); SAFE_FREE(type_c);
leave_function(); leave_function();
return msg; 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.originator_port = ntohl(originator_port);
msg->channel_request_open.type = SSH_CHANNEL_FORWARDED_TCPIP; msg->channel_request_open.type = SSH_CHANNEL_FORWARDED_TCPIP;
string_free(type);
SAFE_FREE(type_c); SAFE_FREE(type_c);
leave_function(); leave_function();
return msg; 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.originator_port = ntohl(originator_port);
msg->channel_request_open.type = SSH_CHANNEL_X11; msg->channel_request_open.type = SSH_CHANNEL_X11;
string_free(type);
SAFE_FREE(type_c); SAFE_FREE(type_c);
leave_function(); leave_function();
return msg; return msg;
} }
msg->channel_request_open.type = SSH_CHANNEL_UNKNOWN; msg->channel_request_open.type = SSH_CHANNEL_UNKNOWN;
string_free(type);
SAFE_FREE(type_c); SAFE_FREE(type_c);
leave_function(); leave_function();
@@ -863,7 +867,7 @@ void message_handle(ssh_session session, uint32_t type){
if(!session->ssh_message_list){ if(!session->ssh_message_list){
session->ssh_message_list=ssh_list_new(); 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 #ifdef _WIN32
#define _WIN32_IE 0x0501 //SHGetSpecialFolderPath #define _WIN32_IE 0x0501 //SHGetSpecialFolderPath
#include <winsock2.h> // Must be the first to include #include <winsock2.h> // Must be the first to include
#include <ws2tcpip.h>
#include <shlobj.h> #include <shlobj.h>
#include <direct.h> #include <direct.h>
#else #else
/* This is needed for a standard getpwuid_r on opensolaris */
#define _POSIX_PTHREAD_SEMANTICS
#include <pwd.h> #include <pwd.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
#include "libssh/priv.h" #include "libssh/priv.h"
#include "libssh/misc.h" #include "libssh/misc.h"
#include "libssh/session.h"
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
#define GCRYPT_STRING "/gnutls" #define GCRYPT_STRING "/gnutls"
@@ -87,25 +91,50 @@ char *ssh_get_user_home_dir(void) {
return NULL; return NULL;
} }
/* we have read access on file */ /* we have read access on file */
int ssh_file_readaccess_ok(const char *file) { int ssh_file_readaccess_ok(const char *file) {
if (_access(file, 4) < 0) { if (_access(file, 4) < 0) {
return 0; return 0;
} }
return 1; return 1;
} }
#define SSH_USEC_IN_SEC 1000000LL
#define SSH_SECONDS_SINCE_1601 11644473600LL
int gettimeofday(struct timeval *__p, void *__t) {
union {
unsigned long long ns100; /* time since 1 Jan 1601 in 100ns units */
FILETIME ft;
} now;
GetSystemTimeAsFileTime (&now.ft);
__p->tv_usec = (long) ((now.ns100 / 10LL) % SSH_USEC_IN_SEC);
__p->tv_sec = (long)(((now.ns100 / 10LL ) / SSH_USEC_IN_SEC) - SSH_SECONDS_SINCE_1601);
return (0);
}
#else /* _WIN32 */ #else /* _WIN32 */
#ifndef NSS_BUFLEN_PASSWD
#define NSS_BUFLEN_PASSWD 4096
#endif
char *ssh_get_user_home_dir(void) { char *ssh_get_user_home_dir(void) {
char *szPath = NULL; char *szPath = NULL;
struct passwd *pwd = NULL; struct passwd pwd;
struct passwd *pwdbuf;
char buf[NSS_BUFLEN_PASSWD];
int rc;
pwd = getpwuid(getuid()); rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
if (pwd == NULL) { if (rc != 0) {
return NULL; szPath = getenv("HOME");
return szPath ? strdup(szPath) : NULL;
} }
szPath = strdup(pwd->pw_dir);
szPath = strdup(pwd.pw_dir);
return szPath; return szPath;
} }
@@ -120,6 +149,20 @@ int ssh_file_readaccess_ok(const char *file) {
} }
#endif #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) { uint64_t ntohll(uint64_t a) {
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
return a; return a;
@@ -133,6 +176,52 @@ uint64_t ntohll(uint64_t a) {
#endif #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 * @brief Check if libssh is the required version or get the version
* string. * string.
@@ -197,7 +286,7 @@ static struct ssh_iterator *ssh_iterator_new(const void *data){
return iterator; 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); struct ssh_iterator *iterator=ssh_iterator_new(data);
if(!iterator) if(!iterator)
return SSH_ERROR; return SSH_ERROR;
@@ -212,6 +301,25 @@ int ssh_list_add(struct ssh_list *list,const void *data){
return SSH_OK; 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){ void ssh_list_remove(struct ssh_list *list, struct ssh_iterator *iterator){
struct ssh_iterator *ptr,*prev; struct ssh_iterator *ptr,*prev;
prev=NULL; prev=NULL;
@@ -236,7 +344,14 @@ void ssh_list_remove(struct ssh_list *list, struct ssh_iterator *iterator){
SAFE_FREE(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; struct ssh_iterator *iterator=list->root;
const void *data; const void *data;
if(!list->root) if(!list->root)
@@ -381,5 +496,157 @@ int ssh_mkdir(const char *pathname, mode_t mode) {
return r; 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" #include "libssh/server.h"
#endif #endif
/**
* @addtogroup ssh_session
* @{
*/
/** /**
* @brief Duplicate the options of a session structure. * @brief Duplicate the options of a session structure.
* *
* If you make several sessions with the same options this is useful. You * If you make several sessions with the same options this is useful. You
* cannot use twice the same option structure in ssh_session_connect. * 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() * @see ssh_session_connect()
*/ */
@@ -76,10 +83,29 @@ int ssh_options_copy(ssh_session src, ssh_session *dest) {
} }
if (src->identity) { if (src->identity) {
new->identity = strdup(src->identity); struct ssh_iterator *it;
new->identity = ssh_list_new();
if (new->identity == NULL) { if (new->identity == NULL) {
return -1; 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) { if (src->sshdir) {
@@ -117,29 +143,6 @@ int ssh_options_copy(ssh_session src, ssh_session *dest) {
return 0; 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, int ssh_options_set_algo(ssh_session session, int algo,
const char *list) { const char *list) {
if (!verify_existing_algo(algo, list)) { if (!verify_existing_algo(algo, list)) {
@@ -159,58 +162,6 @@ int ssh_options_set_algo(ssh_session session, int algo,
return 0; 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. * @brief This function can set all possible ssh options.
* *
@@ -219,143 +170,126 @@ 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 * @param type The option type to set. This could be one of the
* following: * following:
* *
* SSH_OPTIONS_HOST: * - SSH_OPTIONS_HOST:
* The hostname or ip address to connect to (string). * The hostname or ip address to connect to (string).
* *
* SSH_OPTIONS_PORT: * - SSH_OPTIONS_PORT:
* The port to connect to (integer). * The port to connect to (integer).
* *
* SSH_OPTIONS_PORT_STR: * - SSH_OPTIONS_PORT_STR:
* The port to connect to (string). * The port to connect to (string).
* *
* SSH_OPTIONS_FD: * - SSH_OPTIONS_FD:
* The file descriptor to use (socket_t). * The file descriptor to use (socket_t).\n
* * \n
* If you wish to open the socket yourself for a reason * If you wish to open the socket yourself for a reason
* or another, set the file descriptor. Don't forget to * or another, set the file descriptor. Don't forget to
* set the hostname as the hostname is used as a key in * set the hostname as the hostname is used as a key in
* the known_host mechanism. * the known_host mechanism.
* *
* SSH_OPTIONS_USER: * - SSH_OPTIONS_BINDADDR:
* The username for authentication (string). * 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 * If the value is NULL, the username is set to the
* default username. * default username.
* *
* SSH_OPTIONS_SSH_DIR: * - SSH_OPTIONS_SSH_DIR:
* Set the ssh directory (format string). * Set the ssh directory (format string).\n
* * \n
* If the value is NULL, the directory is set to the * 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 * The ssh directory is used for files like known_hosts
* and identity (private and public key). It may include * and identity (private and public key). It may include
* "%s" which will be replaced by the user home * "%s" which will be replaced by the user home
* directory. * directory.
* *
* SSH_OPTIONS_KNOWNHOSTS: * - SSH_OPTIONS_KNOWNHOSTS:
* Set the known hosts file name (format string). * Set the known hosts file name (format string).\n
* * \n
* If the value is NULL, the directory is set to the * 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 * The known hosts file is used to certify remote hosts
* are genuine. It may include "%s" which will be * are genuine. It may include "%s" which will be
* replaced by the user home directory. * replaced by the user home directory.
* *
* SSH_OPTIONS_IDENTITY: * - SSH_OPTIONS_IDENTITY:
* Set the identity file name (format string). * Set the identity file name (format string).\n
* * \n
* By default identity, id_dsa and id_rsa are checked. * By default identity, id_dsa and id_rsa are checked.\n
* * \n
* The identity file used authenticate with public key. * The identity file used authenticate with public key.
* It may include "%s" which will be replaced by the * It may include "%s" which will be replaced by the
* user home directory. * user home directory.
* *
* SSH_OPTIONS_TIMEOUT: * - SSH_OPTIONS_TIMEOUT:
* Set a timeout for the connection in seconds (integer). * 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 * Set a timeout for the connection in micro seconds
* (integer). * (integer).
* *
* SSH_OPTIONS_SSH1: * - SSH_OPTIONS_SSH1:
* Allow or deny the connection to SSH1 servers * Allow or deny the connection to SSH1 servers
* (integer). * (integer).
* *
* SSH_OPTIONS_SSH2: * - SSH_OPTIONS_SSH2:
* Allow or deny the connection to SSH2 servers * Allow or deny the connection to SSH2 servers
* (integer). * (integer).
* *
* SSH_OPTIONS_LOG_VERBOSITY: * - SSH_OPTIONS_LOG_VERBOSITY:
* Set the session logging verbosity (integer). * Set the session logging verbosity (integer).\n
* * \n
* The verbosity of the messages. Every log smaller or * The verbosity of the messages. Every log smaller or
* equal to verbosity will be shown. * equal to verbosity will be shown.
* SSH_LOG_NOLOG: No logging * - SSH_LOG_NOLOG: No logging
* SSH_LOG_RARE: Rare conditions or warnings * - SSH_LOG_RARE: Rare conditions or warnings
* SSH_LOG_ENTRY: API-accessible entrypoints * - SSH_LOG_ENTRY: API-accessible entrypoints
* SSH_LOG_PACKET: Packet id and size * - SSH_LOG_PACKET: Packet id and size
* SSH_LOG_FUNCTIONS: Function entering and leaving * - SSH_LOG_FUNCTIONS: Function entering and leaving
*
* SSH_OPTIONS_LOG_VERBOSITY_STR:
* Set the session logging verbosity (string).
* *
* - SSH_OPTIONS_LOG_VERBOSITY_STR:
* Set the session logging verbosity (string).\n
* \n
* The verbosity of the messages. Every log smaller or * The verbosity of the messages. Every log smaller or
* equal to verbosity will be shown. * equal to verbosity will be shown.
* SSH_LOG_NOLOG: No logging * - SSH_LOG_NOLOG: No logging
* SSH_LOG_RARE: Rare conditions or warnings * - SSH_LOG_RARE: Rare conditions or warnings
* SSH_LOG_ENTRY: API-accessible entrypoints * - SSH_LOG_ENTRY: API-accessible entrypoints
* SSH_LOG_PACKET: Packet id and size * - SSH_LOG_PACKET: Packet id and size
* SSH_LOG_FUNCTIONS: Function entering and leaving * - SSH_LOG_FUNCTIONS: Function entering and leaving
* * \n
* See the corresponding numbers in libssh.h. * See the corresponding numbers in libssh.h.
* *
* SSH_OPTTIONS_AUTH_CALLBACK: * - SSH_OPTTIONS_STATUS_ARG:
* 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_LOG_CALLBACK:
* Set a callback to use your own logging function
* (function pointer).
*
* SSH_OPTTIONS_LOG_USERDATA:
* Set the user data passed to the logging function
* (generic pointer).
*
* SSH_OPTTIONS_STATUS_CALLBACK:
* Set a callback to show connection status in realtime
* (function pointer).
*
* fn(void *arg, float status)
*
* During ssh_connect(), libssh will call the callback
* with status from 0.0 to 1.0.
*
* SSH_OPTTIONS_STATUS_ARG:
* Set the status argument which should be passed to the * Set the status argument which should be passed to the
* status callback (generic pointer). * status callback (generic pointer).
* *
* SSH_OPTIONS_CIPHERS_C_S: * - SSH_OPTIONS_CIPHERS_C_S:
* Set the symmetric cipher client to server (string, * Set the symmetric cipher client to server (string,
* comma-separated list). * comma-separated list).
* *
* SSH_OPTIONS_CIPHERS_S_C: * - SSH_OPTIONS_CIPHERS_S_C:
* Set the symmetric cipher server to client (string, * Set the symmetric cipher server to client (string,
* comma-separated list). * comma-separated list).
* *
* SSH_OPTIONS_COMPRESSION_C_S: * - SSH_OPTIONS_COMPRESSION_C_S:
* Set the compression to use for client to server * Set the compression to use for client to server
* communication (string, "none" or "zlib"). * communication (string, "none" or "zlib").
* *
* SSH_OPTIONS_COMPRESSION_S_C: * - SSH_OPTIONS_COMPRESSION_S_C:
* Set the compression to use for server to client * Set the compression to use for server to client
* communication (string, "none" or "zlib"). * 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 * @param value The value to set. This is a generic pointer and the
* datatype which is used should be set according to the * datatype which is used should be set according to the
* type set. * type set.
@@ -366,6 +300,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
const void *value) { const void *value) {
char *p, *q; char *p, *q;
long int i; long int i;
int rc;
if (session == NULL) { if (session == NULL) {
return -1; return -1;
@@ -429,30 +364,35 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
session->port = i & 0xffff; session->port = i & 0xffff;
} }
break; 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: case SSH_OPTIONS_USER:
SAFE_FREE(session->username); SAFE_FREE(session->username);
if (value == NULL) { /* set default username */ if (value == NULL) { /* set default username */
#ifdef _WIN32 q = ssh_get_local_username(session);
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());
if (q == NULL) { if (q == NULL) {
return -1; return -1;
} }
session->username = q; session->username = q;
#endif /* _WIN32 */
} else { /* username provided */ } else { /* username provided */
session->username = strdup(value); session->username = strdup(value);
if (session->username == NULL) { if (session->username == NULL) {
@@ -464,43 +404,47 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
case SSH_OPTIONS_SSH_DIR: case SSH_OPTIONS_SSH_DIR:
if (value == NULL) { if (value == NULL) {
SAFE_FREE(session->sshdir); 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) { if (session->sshdir == NULL) {
return -1; return -1;
} }
} else { } else {
SAFE_FREE(session->sshdir); SAFE_FREE(session->sshdir);
session->sshdir = dir_expand_dup(session, value, 0); session->sshdir = ssh_path_expand_tilde(value);
if (session->sshdir == NULL) { if (session->sshdir == NULL) {
return -1; return -1;
} }
} }
break; break;
case SSH_OPTIONS_IDENTITY: case SSH_OPTIONS_IDENTITY:
case SSH_OPTIONS_ADD_IDENTITY:
if (value == NULL) { if (value == NULL) {
ssh_set_error_invalid(session, __FUNCTION__); ssh_set_error_invalid(session, __FUNCTION__);
return -1; return -1;
} }
SAFE_FREE(session->identity); q = strdup(value);
session->identity = dir_expand_dup(session, value, 1); if (q == NULL) {
if (session->identity == NULL) { return -1;
}
rc = ssh_list_prepend(session->identity, q);
if (rc < 0) {
return -1; return -1;
} }
break; break;
case SSH_OPTIONS_KNOWNHOSTS: case SSH_OPTIONS_KNOWNHOSTS:
if (value == NULL) { if (value == NULL) {
SAFE_FREE(session->knownhosts); SAFE_FREE(session->knownhosts);
session->knownhosts = dir_expand_dup(session, if (session->sshdir == NULL) {
"SSH_DIR/known_hosts", 1); return -1;
}
session->knownhosts = ssh_path_expand_escape(session, "%d/known_hosts");
if (session->knownhosts == NULL) { if (session->knownhosts == NULL) {
return -1; return -1;
} }
} else { } else {
SAFE_FREE(session->knownhosts); SAFE_FREE(session->knownhosts);
session->knownhosts = dir_expand_dup(session, value, 1); session->knownhosts = strdup(value);
if (session->knownhosts == NULL) { if (session->knownhosts == NULL) {
return -1; return -1;
} }
@@ -553,6 +497,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
session->log_verbosity = *x & 0xffff; session->log_verbosity = *x & 0xffff;
} }
break;
case SSH_OPTIONS_LOG_VERBOSITY_STR: case SSH_OPTIONS_LOG_VERBOSITY_STR:
if (value == NULL) { if (value == NULL) {
session->log_verbosity = 0 & 0xffff; session->log_verbosity = 0 & 0xffff;
@@ -607,16 +552,34 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
return -1; return -1;
} }
break; 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: 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; return -1;
break; break;
} }
return 0; return 0;
} }
/** @} */
#ifdef WITH_SERVER #ifdef WITH_SERVER
/**
* @addtogroup ssh_server
* @{
*/
static int ssh_bind_options_set_algo(ssh_bind sshbind, int algo, static int ssh_bind_options_set_algo(ssh_bind sshbind, int algo,
const char *list) { const char *list) {
if (!verify_existing_algo(algo, list)) { if (!verify_existing_algo(algo, list)) {
@@ -817,7 +780,7 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
} }
break; break;
default: 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; return -1;
break; break;
} }
@@ -1040,19 +1003,91 @@ int ssh_options_parse_config(ssh_session session, const char *filename) {
return -1; 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 */ /* set default filename */
if (filename == NULL) { if (filename == NULL) {
expanded_filename = dir_expand_dup(session, "SSH_DIR/config", 1); expanded_filename = ssh_path_expand_escape(session, "%d/config");
} else { } 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; return -1;
}
r = ssh_config_parse_file(session, expanded_filename); 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); free(expanded_filename);
return r; return r;
} }
/** @} */ int ssh_options_apply(ssh_session session) {
/* vim: set ts=2 sw=2 et cindent: */ 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: case SSH2_MSG_CHANNEL_OPEN:
message_handle(session,type); message_handle(session,type);
return; return;
case SSH2_MSG_GLOBAL_REQUEST:
ssh_global_request_handle(session);
return;
default: default:
ssh_log(session, SSH_LOG_RARE, "Received unhandled packet %d", type); 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"); ssh_log(session, SSH_LOG_PACKET, "received disconnect packet");
leave_function(); leave_function();
return SSH_ERROR; return SSH_ERROR;
case SSH2_MSG_GLOBAL_REQUEST:
case SSH2_MSG_CHANNEL_WINDOW_ADJUST: case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
case SSH2_MSG_CHANNEL_DATA: case SSH2_MSG_CHANNEL_DATA:
case SSH2_MSG_CHANNEL_EXTENDED_DATA: case SSH2_MSG_CHANNEL_EXTENDED_DATA:

View File

@@ -30,8 +30,12 @@
#ifdef WITH_PCAP #ifdef WITH_PCAP
#include <stdio.h> #include <stdio.h>
#ifdef _WIN32
#include <ws2tcpip.h>
#else
#include <sys/time.h> #include <sys/time.h>
#include <sys/socket.h> #include <sys/socket.h>
#endif
#include <errno.h> #include <errno.h>
@@ -46,13 +50,13 @@
* Just for information. * Just for information.
*/ */
struct pcap_hdr_s { struct pcap_hdr_s {
u_int32_t magic_number; /* magic number */ uint32_t magic_number; /* magic number */
u_int16_t version_major; /* major version number */ uint16_t version_major; /* major version number */
u_int16_t version_minor; /* minor version number */ uint16_t version_minor; /* minor version number */
int32_t thiszone; /* GMT to local correction */ int32_t thiszone; /* GMT to local correction */
u_int32_t sigfigs; /* accuracy of timestamps */ uint32_t sigfigs; /* accuracy of timestamps */
u_int32_t snaplen; /* max length of captured packets, in octets */ uint32_t snaplen; /* max length of captured packets, in octets */
u_int32_t network; /* data link type */ uint32_t network; /* data link type */
}; };
#define PCAP_MAGIC 0xa1b2c3d4 #define PCAP_MAGIC 0xa1b2c3d4
@@ -73,10 +77,10 @@ struct pcap_hdr_s {
* Just for information. * Just for information.
*/ */
struct pcaprec_hdr_s { struct pcaprec_hdr_s {
u_int32_t ts_sec; /* timestamp seconds */ uint32_t ts_sec; /* timestamp seconds */
u_int32_t ts_usec; /* timestamp microseconds */ uint32_t ts_usec; /* timestamp microseconds */
u_int32_t incl_len; /* number of octets of packet saved in file */ uint32_t incl_len; /* number of octets of packet saved in file */
u_int32_t orig_len; /* actual length of packet */ uint32_t orig_len; /* actual length of packet */
}; };
/** @private /** @private
@@ -89,15 +93,15 @@ struct ssh_pcap_context_struct {
ssh_session session; ssh_session session;
ssh_pcap_file file; ssh_pcap_file file;
int connected; int connected;
/* All of these informations are useful to generate /* All of these information are useful to generate
* the dummy IP and TCP packets * the dummy IP and TCP packets
*/ */
u_int32_t ipsource; uint32_t ipsource;
u_int32_t ipdest; uint32_t ipdest;
u_int16_t portsource; uint16_t portsource;
u_int16_t portdest; uint16_t portdest;
u_int32_t outsequence; uint32_t outsequence;
u_int32_t insequence; uint32_t insequence;
}; };
/** @private /** @private
@@ -106,7 +110,7 @@ struct ssh_pcap_context_struct {
*/ */
struct ssh_pcap_file_struct { struct ssh_pcap_file_struct {
FILE *output; FILE *output;
u_int16_t ipsequence; uint16_t ipsequence;
}; };
/** /**
@@ -136,7 +140,7 @@ static int ssh_pcap_file_write(ssh_pcap_file pcap, ssh_buffer packet){
* @brief prepends a packet with the pcap header and writes packet * @brief prepends a packet with the pcap header and writes packet
* on file * on file
*/ */
int ssh_pcap_file_write_packet(ssh_pcap_file pcap, ssh_buffer packet, u_int32_t original_len){ int ssh_pcap_file_write_packet(ssh_pcap_file pcap, ssh_buffer packet, uint32_t original_len){
ssh_buffer header=buffer_new(); ssh_buffer header=buffer_new();
struct timeval now; struct timeval now;
int err; int err;
@@ -282,7 +286,7 @@ static int ssh_pcap_context_connect(ssh_pcap_context ctx){
* @returns SSH_ERROR an error happened. * @returns SSH_ERROR an error happened.
*/ */
int ssh_pcap_context_write(ssh_pcap_context ctx,enum ssh_pcap_direction direction int ssh_pcap_context_write(ssh_pcap_context ctx,enum ssh_pcap_direction direction
, void *data, u_int32_t len, u_int32_t origlen){ , void *data, uint32_t len, uint32_t origlen){
ssh_buffer ip; ssh_buffer ip;
int err; int err;
if(ctx==NULL || ctx->file ==NULL) if(ctx==NULL || ctx->file ==NULL)

View File

@@ -3,6 +3,7 @@
* *
* This file is part of the SSH Library * 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) 2003-2009 by Aris Adamantiadis
* Copyright (c) 2009 Aleksandar Kanchev * Copyright (c) 2009 Aleksandar Kanchev
* *
@@ -24,8 +25,6 @@
* vim: ts=2 sw=2 et cindent * vim: ts=2 sw=2 et cindent
*/ */
/* This code is based on glib's gpoll */
#include "config.h" #include "config.h"
#include <errno.h> #include <errno.h>
@@ -60,177 +59,217 @@ struct ssh_poll_ctx_struct {
#ifdef HAVE_POLL #ifdef HAVE_POLL
#include <poll.h> #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) { int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
return poll((struct pollfd *) fds, nfds, timeout); return poll((struct pollfd *) fds, nfds, timeout);
} }
#else /* HAVE_POLL */ #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 #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 #ifndef STRICT
#define STRICT #define STRICT
#endif #endif /* STRICT */
#include <stdio.h> #include <time.h>
#include <windows.h> #include <windows.h>
#include <errno.h> #include <winsock2.h>
static int poll_rest (HANDLE *handles, int nhandles, #if (_WIN32_WINNT < 0x0600)
ssh_pollfd_t *fds, nfds_t nfds, int timeout) { typedef struct ssh_pollfd_struct WSAPOLLFD;
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());
}
#endif #endif
}
if (ready == WAIT_FAILED) { typedef int (WSAAPI* WSAPoll_FunctionType)(WSAPOLLFD fdarray[],
return -1; ULONG nfds,
} else if (ready == WAIT_TIMEOUT || ready == WAIT_IO_COMPLETION) { INT timeout
return 0; );
} else if (ready >= WAIT_OBJECT_0 && ready < WAIT_OBJECT_0 + nhandles) {
for (f = fds; f < &fds[nfds]; f++) { static WSAPoll_FunctionType wsa_poll;
if ((HANDLE) f->fd == handles[ready - WAIT_OBJECT_0]) {
f->revents = f->events; int win_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
} if (wsa_poll) {
return (wsa_poll)(fds, nfds, timeout);
} }
/* return SOCKET_ERROR;
* 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;
} }
int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) { #define WS2_LIBRARY "ws2_32.dll"
HANDLE handles[MAXIMUM_WAIT_OBJECTS]; static HINSTANCE hlib;
ssh_pollfd_t *f;
int nhandles = 0; #else /* _WIN32 */
int rc = -1; #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) { if (fds == NULL) {
errno = EFAULT; errno = EFAULT;
return -1; return -1;
} }
if (nfds >= MAXIMUM_WAIT_OBJECTS) { FD_ZERO (&readfds);
errno = EINVAL; FD_ZERO (&writefds);
return -1; FD_ZERO (&exceptfds);
}
for (f = fds; f < &fds[nfds]; f++) { /* compute fd_sets and find largest descriptor */
if (f->fd > 0) { for (rc = -1, max_fd = 0, i = 0; i < nfds; i++) {
int i; if (fds[i].fd == SSH_INVALID_SOCKET) {
continue;
/*
* 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;
}
} }
#ifndef _WIN32
if (i == nhandles) { if (fds[i].fd >= FD_SETSIZE) {
if (nhandles == MAXIMUM_WAIT_OBJECTS) { rc = -1;
break; 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) { if (max_fd == SSH_INVALID_SOCKET || rc == -1) {
timeout = INFINITE; errno = EINVAL;
return -1;
} }
if (nhandles > 1) { if (timeout < 0) {
/* ptv = NULL;
* 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);
}
} else { } else {
/* ptv = &tv;
* Just polling for one thing, so no need to check first if if (timeout == 0) {
* available immediately tv.tv_sec = 0;
*/ tv.tv_usec = 0;
rc = poll_rest(handles, nhandles, fds, nfds, timeout); } else {
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
}
} }
rc = select (max_fd + 1, &readfds, &writefds, &exceptfds, ptv);
if (rc < 0) { if (rc < 0) {
for (f = fds; f < &fds[nfds]; f++) { return -1;
f->revents = 0;
}
errno = EBADF;
} }
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; 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 */ #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 */ #endif /* HAVE_POLL */
/** /**
@@ -403,7 +442,7 @@ void ssh_poll_ctx_free(ssh_poll_ctx ctx) {
used = ctx->polls_used; used = ctx->polls_used;
for (i = 0; i < used; ) { for (i = 0; i < used; ) {
ssh_poll_handle p = ctx->pollptrs[i]; ssh_poll_handle p = ctx->pollptrs[i];
int fd = ctx->pollfds[i].fd; socket_t fd = ctx->pollfds[i].fd;
/* force poll object removal */ /* force poll object removal */
if (p->cb(p, fd, POLLERR, p->cb_data) < 0) { 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 * @return 0 on success, < 0 on error
*/ */
int ssh_poll_ctx_add(ssh_poll_ctx ctx, ssh_poll_handle p) { int ssh_poll_ctx_add(ssh_poll_ctx ctx, ssh_poll_handle p) {
int fd; socket_t fd;
if (p->ctx != NULL) { if (p->ctx != NULL) {
/* already attached to a context */ /* already attached to a context */
@@ -530,7 +569,7 @@ int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout) {
i++; i++;
} else { } else {
ssh_poll_handle p = ctx->pollptrs[i]; 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; int revents = ctx->pollfds[i].revents;
if (p->cb(p, fd, revents, p->cb_data) < 0) { if (p->cb(p, fd, revents, p->cb_data) < 0) {

View File

@@ -26,11 +26,18 @@
#include "libssh/priv.h" #include "libssh/priv.h"
#include "libssh/scp.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 /** @brief Creates a new scp session
* @param session the SSH session to use * @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. * @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. * 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 NULL if the creation was impossible.
* @returns a ssh_scp handle if it worked. * @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){ int ssh_scp_close(ssh_scp scp){
char buffer[128];
int err;
if(scp->channel != NULL){ if(scp->channel != NULL){
if(channel_send_eof(scp->channel) == SSH_ERROR){ if(channel_send_eof(scp->channel) == SSH_ERROR){
scp->state=SSH_SCP_ERROR; scp->state=SSH_SCP_ERROR;
return SSH_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){ if(channel_close(scp->channel) == SSH_ERROR){
scp->state=SSH_SCP_ERROR; scp->state=SSH_SCP_ERROR;
return SSH_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 /** @brief creates a directory in a scp in sink mode
* @param scp the scp handle.
* @param dirname Name of the directory being created. * @param dirname Name of the directory being created.
* @param mode Unix permissions for the new directory, e.g. 0755. * @param mode Unix permissions for the new directory, e.g. 0755.
* @returns SSH_OK if the directory was created. * @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 /** @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 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 size Exact size in bytes of the file being sent.
* @param mode Unix permissions for the new file, e.g. 0644 * @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 /** @brief Write into a remote scp file
* @param scp the scp handle.
* @param buffer the buffer to write * @param buffer the buffer to write
* @param len the number of bytes to write * @param len the number of bytes to write
* @returns SSH_OK the write was successful * @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' * @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 buffer pointer to a buffer to place the string
* @param len size of the buffer in bytes. If the string is bigger * @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 * 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 * @brief denies the transfer of a file or creation of a directory
* coming from the remote party * coming from the remote party
* @param scp the scp handle.
* @param reason nul-terminated string with a human-readable explanation * @param reason nul-terminated string with a human-readable explanation
* of the deny * of the deny
* @returns SSH_OK the message was sent * @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 * @brief accepts transfer of a file or creation of a directory
* coming from the remote party * coming from the remote party
* @param scp the scp handle.
* @returns SSH_OK the message was sent * @returns SSH_OK the message was sent
* @returns SSH_ERROR Error sending the message, or sending it in a bad state * @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 /** @brief Read from a remote scp file
* @param scp the scp handle.
* @param buffer Destination buffer * @param buffer Destination buffer
* @param size Size of the buffer * @param size Size of the buffer
* @returns Number of bytes read * @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. /** @brief Converts a unix mode into a scp string one.
* @param mode mode to convert, e.g. 420 or 0644 * @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". * e.g. "0644".
*/ */
char *ssh_scp_string_mode(int mode){ 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){ const char *ssh_scp_request_get_warning(ssh_scp scp){
return scp->warning; return scp->warning;
} }
/** @} */

View File

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

View File

@@ -32,7 +32,8 @@
#include "libssh/packet.h" #include "libssh/packet.h"
#include "libssh/session.h" #include "libssh/session.h"
#include "libssh/misc.h" #include "libssh/misc.h"
#include "libssh/ssh2.h"
#include "libssh/buffer.h"
#define FIRST_CHANNEL 42 // why not ? it helps to find bugs. #define FIRST_CHANNEL 42 // why not ? it helps to find bugs.
/** \defgroup ssh_session SSH Session /** \defgroup ssh_session SSH Session
@@ -46,6 +47,8 @@
*/ */
ssh_session ssh_new(void) { ssh_session ssh_new(void) {
ssh_session session; ssh_session session;
char *id;
int rc;
session = malloc(sizeof (struct ssh_session_struct)); session = malloc(sizeof (struct ssh_session_struct));
if (session == NULL) { if (session == NULL) {
@@ -95,6 +98,39 @@ ssh_session ssh_new(void) {
goto err; goto err;
} }
#endif /* _WIN32 */ #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; return session;
err: err:
@@ -117,6 +153,7 @@ void ssh_free(ssh_session session) {
SAFE_FREE(session->serverbanner); SAFE_FREE(session->serverbanner);
SAFE_FREE(session->clientbanner); SAFE_FREE(session->clientbanner);
SAFE_FREE(session->bindaddr);
SAFE_FREE(session->banner); SAFE_FREE(session->banner);
#ifdef WITH_PCAP #ifdef WITH_PCAP
if(session->pcap_ctx){ if(session->pcap_ctx){
@@ -155,19 +192,30 @@ void ssh_free(ssh_session session) {
privatekey_free(session->rsa_key); privatekey_free(session->rsa_key);
if(session->ssh_message_list){ if(session->ssh_message_list){
ssh_message msg; 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){ != NULL){
ssh_message_free(msg); ssh_message_free(msg);
} }
ssh_list_free(session->ssh_message_list); 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 */ /* options */
SAFE_FREE(session->username); SAFE_FREE(session->username);
SAFE_FREE(session->host); SAFE_FREE(session->host);
SAFE_FREE(session->identity);
SAFE_FREE(session->sshdir); SAFE_FREE(session->sshdir);
SAFE_FREE(session->knownhosts); SAFE_FREE(session->knownhosts);
SAFE_FREE(session->ProxyCommand);
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
if (session->wanted_methods[i]) { if (session->wanted_methods[i]) {
@@ -363,5 +411,32 @@ int ssh_get_version(ssh_session session) {
return session->version; 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: */ /* vim: set ts=2 sw=2 et cindent: */

View File

@@ -25,9 +25,11 @@
/* This file contains code written by Nick Zitzmann */ /* This file contains code written by Nick Zitzmann */
#include <errno.h> #include <errno.h>
#include <ctype.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@@ -1111,6 +1113,54 @@ static sftp_attributes sftp_parse_attr_4(sftp_session sftp, ssh_buffer buf,
return attr; 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 */ /* sftp version 0-3 code. It is different from the v4 */
/* maybe a paste of the draft is better than the code */ /* 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; break;
} }
string_free(longname); 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)) { 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); string_free(attr->extended_data);
SAFE_FREE(attr->name); SAFE_FREE(attr->name);
SAFE_FREE(attr->longname); SAFE_FREE(attr->longname);
SAFE_FREE(attr->owner);
SAFE_FREE(attr->group);
SAFE_FREE(attr); SAFE_FREE(attr);
ssh_set_error(sftp->session, SSH_FATAL, "Invalid ATTR structure"); 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 || if (buffer_add_u32(buffer, id) < 0 ||
buffer_add_ssh_string(buffer, oldpath) < 0 || buffer_add_ssh_string(buffer, oldpath) < 0 ||
buffer_add_ssh_string(buffer, newpath) < 0 || buffer_add_ssh_string(buffer, newpath) < 0 ||
/* POSIX rename atomically replaces newpath, we should do the same */ /* POSIX rename atomically replaces newpath, we should do the same
buffer_add_u32(buffer, SSH_FXF_RENAME_OVERWRITE) < 0) { * only available on >=v4 */
sftp->version>=4 ? (buffer_add_u32(buffer, SSH_FXF_RENAME_OVERWRITE) < 0):0) {
ssh_set_error_oom(sftp->session); ssh_set_error_oom(sftp->session);
buffer_free(buffer); buffer_free(buffer);
string_free(oldpath); 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.uid = owner;
attr.gid = group; attr.gid = group;
attr.flags = SSH_FILEXFER_ATTR_OWNERGROUP;
attr.flags = SSH_FILEXFER_ATTR_UIDGID;
return sftp_setstat(sftp, file, &attr); 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) { 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) { } else if (msg->packet_type == SSH_FXP_STATUS) {
status = parse_status_msg(msg); status = parse_status_msg(msg);
sftp_message_free(msg); sftp_message_free(msg);

View File

@@ -27,11 +27,13 @@
#include <stdio.h> #include <stdio.h>
#ifdef _WIN32 #ifdef _WIN32
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h>
#else #else
#include <fcntl.h> #include <fcntl.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
extern char **environ;
#endif #endif
#include "libssh/priv.h" #include "libssh/priv.h"
#include "libssh/socket.h" #include "libssh/socket.h"
@@ -39,6 +41,7 @@
#include "libssh/poll.h" #include "libssh/poll.h"
#include "libssh/session.h" #include "libssh/session.h"
/** \defgroup ssh_socket SSH Sockets /** \defgroup ssh_socket SSH Sockets
* \addtogroup ssh_socket * \addtogroup ssh_socket
* @{ * @{
@@ -68,10 +71,21 @@ int ssh_socket_init(void) {
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) { if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
return -1; return -1;
} }
#endif #endif
ssh_poll_init();
return 0; return 0;
} }
/*
/**
* @brief Cleanup the socket system.
*/
void ssh_socket_cleanup(void) {
ssh_poll_cleanup();
}
/**
* \internal * \internal
* \brief creates a new Socket object * \brief creates a new Socket object
*/ */
@@ -82,7 +96,7 @@ struct socket *ssh_socket_new(ssh_session session) {
if (s == NULL) { if (s == NULL) {
return NULL; return NULL;
} }
s->fd = -1; s->fd = SSH_INVALID_SOCKET;
s->last_errno = -1; s->last_errno = -1;
s->session = session; s->session = session;
s->in_buffer = buffer_new(); 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); snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path), "%s", path);
s->fd = socket(AF_UNIX, SOCK_STREAM, 0); s->fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (s->fd < 0) { if (s->fd == SSH_INVALID_SOCKET) {
return -1; return -1;
} }
if (fcntl(s->fd, F_SETFD, 1) == -1) { if (fcntl(s->fd, F_SETFD, 1) == -1) {
close(s->fd); close(s->fd);
s->fd = -1; s->fd = SSH_INVALID_SOCKET;
return -1; return -1;
} }
if (connect(s->fd, (struct sockaddr *) &sunaddr, if (connect(s->fd, (struct sockaddr *) &sunaddr,
sizeof(sunaddr)) < 0) { sizeof(sunaddr)) < 0) {
close(s->fd); close(s->fd);
s->fd = -1; s->fd = SSH_INVALID_SOCKET;
return -1; return -1;
} }
@@ -157,7 +171,7 @@ void ssh_socket_close(struct socket *s){
close(s->fd); close(s->fd);
s->last_errno = errno; s->last_errno = errno;
#endif #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 * \brief returns nonzero if the socket is open
*/ */
int ssh_socket_is_open(struct socket *s) { int ssh_socket_is_open(struct socket *s) {
return s->fd != -1; return s->fd != SSH_INVALID_SOCKET;
} }
/* \internal /* \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 * \brief returns nonzero if the current socket is in the fd_set
*/ */
int ssh_socket_fd_isset(struct socket *s, fd_set *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 0;
} }
return FD_ISSET(s->fd,set); return FD_ISSET(s->fd,set);
} }
/* \internal /* \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) { void ssh_socket_fd_set(struct socket *s, fd_set *set, socket_t *max_fd) {
if (s->fd == -1) if (s->fd == SSH_INVALID_SOCKET)
return; return;
FD_SET(s->fd,set); 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)) { if (ssh_socket_is_open(session->socket)) {
r = ssh_socket_unbuffered_read(session->socket, buffer, sizeof(buffer)); r = ssh_socket_unbuffered_read(session->socket, buffer, sizeof(buffer));
} else { } else {
r =- 1; r = -1;
} }
if (r <= 0) { if (r <= 0) {
@@ -475,6 +492,7 @@ int ssh_socket_poll(struct socket *s, int *writeable, int *except) {
fd->fd = s->fd; fd->fd = s->fd;
fd->events = 0; fd->events = 0;
fd->revents = 0;
if (!s->data_to_read) { if (!s->data_to_read) {
fd->events |= POLLIN; fd->events |= POLLIN;
@@ -482,13 +500,15 @@ int ssh_socket_poll(struct socket *s, int *writeable, int *except) {
if (!s->data_to_write) { if (!s->data_to_write) {
fd->events |= POLLOUT; fd->events |= POLLOUT;
} }
/* do not do poll if fd->events is empty, we already know the response */
/* Make the call, and listen for errors */ if(fd->events != 0){
rc = ssh_poll(fd, 1, 0); /* Make the call, and listen for errors */
if (rc < 0) { rc = ssh_poll(fd, 1, 0);
ssh_set_error(session, SSH_FATAL, "poll(): %s", strerror(errno)); if (rc < 0) {
leave_function(); ssh_set_error(session, SSH_FATAL, "poll(): %s", strerror(errno));
return -1; leave_function();
return -1;
}
} }
if (!s->data_to_read) { if (!s->data_to_read) {
@@ -542,7 +562,7 @@ int ssh_socket_nonblocking_flush(struct socket *s) {
buffer_get_rest_len(s->out_buffer)); buffer_get_rest_len(s->out_buffer));
} else { } else {
/* write failed */ /* write failed */
w =- 1; w = -1;
} }
if (w < 0) { if (w < 0) {
@@ -658,6 +678,54 @@ int ssh_socket_get_status(struct socket *s) {
return r; 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: */ /* 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) { static int aes_set_key(struct crypto_struct *cipher, void *key, void *IV) {
int mode=GCRY_CIPHER_MODE_CBC;
if (cipher->key == NULL) { if (cipher->key == NULL) {
if (alloc_key(cipher) < 0) { if (alloc_key(cipher) < 0) {
return -1; return -1;
} }
if(strstr(cipher->name,"-ctr"))
mode=GCRY_CIPHER_MODE_CTR;
switch (cipher->keysize) { switch (cipher->keysize) {
case 128: case 128:
if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_AES128, if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_AES128,
GCRY_CIPHER_MODE_CBC, 0)) { mode, 0)) {
SAFE_FREE(cipher->key); SAFE_FREE(cipher->key);
return -1; return -1;
} }
break; break;
case 192: case 192:
if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_AES192, if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_AES192,
GCRY_CIPHER_MODE_CBC, 0)) { mode, 0)) {
SAFE_FREE(cipher->key); SAFE_FREE(cipher->key);
return -1; return -1;
} }
break; break;
case 256: case 256:
if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_AES256, if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_AES256,
GCRY_CIPHER_MODE_CBC, 0)) { mode, 0)) {
SAFE_FREE(cipher->key); SAFE_FREE(cipher->key);
return -1; return -1;
} }
@@ -189,9 +191,17 @@ static int aes_set_key(struct crypto_struct *cipher, void *key, void *IV) {
SAFE_FREE(cipher->key); SAFE_FREE(cipher->key);
return -1; return -1;
} }
if (gcry_cipher_setiv(cipher->key[0], IV, 16)) { if(mode == GCRY_CIPHER_MODE_CBC){
SAFE_FREE(cipher->key); if (gcry_cipher_setiv(cipher->key[0], IV, 16)) {
return -1;
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_encrypt = blowfish_encrypt,
.cbc_decrypt = blowfish_decrypt .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", .name = "aes128-cbc",
.blocksize = 16, .blocksize = 16,
@@ -570,6 +613,30 @@ static void aes_decrypt(struct crypto_struct *cipher, void *in, void *out,
unsigned long len, void *IV) { unsigned long len, void *IV) {
AES_cbc_encrypt(in, out, len, cipher->key, IV, AES_DECRYPT); 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 */ #endif /* HAS_AES */
#ifdef HAS_DES #ifdef HAS_DES
@@ -661,6 +728,41 @@ static struct crypto_struct ssh_ciphertab[] = {
}, },
#endif /* HAS_BLOWFISH */ #endif /* HAS_BLOWFISH */
#ifdef HAS_AES #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", "aes128-cbc",
16, 16,
@@ -907,7 +1009,8 @@ int crypt_set_algorithms_server(ssh_session session){
/* out */ /* out */
server = session->server_kex.methods[SSH_CRYPT_S_C]; server = session->server_kex.methods[SSH_CRYPT_S_C];
client = session->client_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){ if(!match){
ssh_set_error(session,SSH_FATAL,"Crypt_set_algorithms_server : no matching algorithm function found for %s",server); 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 */ /* in */
client=session->client_kex.methods[SSH_CRYPT_C_S]; client=session->client_kex.methods[SSH_CRYPT_C_S];
server=session->server_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){ if(!match){
ssh_set_error(session,SSH_FATAL,"Crypt_set_algorithms_server : no matching algorithm function found for %s",server); ssh_set_error(session,SSH_FATAL,"Crypt_set_algorithms_server : no matching algorithm function found for %s",server);
free(match); free(match);
@@ -964,7 +1067,7 @@ int crypt_set_algorithms_server(ssh_session session){
/* compression */ /* compression */
client=session->client_kex.methods[SSH_CRYPT_C_S]; client=session->client_kex.methods[SSH_CRYPT_C_S];
server=session->server_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")){ if(match && !strcmp(match,"zlib")){
ssh_log(session,SSH_LOG_PACKET,"enabling C->S compression"); ssh_log(session,SSH_LOG_PACKET,"enabling C->S compression");
session->next_crypto->do_compress_in=1; 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]; client=session->client_kex.methods[SSH_CRYPT_S_C];
server=session->server_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")){ if(match && !strcmp(match,"zlib")){
ssh_log(session,SSH_LOG_PACKET,"enabling S->C compression\n"); ssh_log(session,SSH_LOG_PACKET,"enabling S->C compression\n");
session->next_crypto->do_compress_out=1; 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]; server=session->server_kex.methods[SSH_HOSTKEYS];
client=session->client_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")) if(match && !strcmp(match,"ssh-dss"))
session->hostkeys=TYPE_DSS; session->hostkeys=TYPE_DSS;
else if(match && !strcmp(match,"ssh-rsa")) else if(match && !strcmp(match,"ssh-rsa"))