mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-05 04:40:31 +09:00
Compare commits
176 Commits
libssh-0.1
...
libssh-0.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f17788adc2 | ||
|
|
23e0053a41 | ||
|
|
b6788f369e | ||
|
|
4cc4236182 | ||
|
|
21a1c51eef | ||
|
|
d796de288e | ||
|
|
7ba381116d | ||
|
|
6f59c0534d | ||
|
|
494fb26b01 | ||
|
|
d0f9320602 | ||
|
|
5826cb6ab2 | ||
|
|
bbdef245a1 | ||
|
|
a0d894dd2a | ||
|
|
05d8421290 | ||
|
|
55b09f4264 | ||
|
|
f128338132 | ||
|
|
ba231d0844 | ||
|
|
6da817aa47 | ||
|
|
05ed61848f | ||
|
|
d63f19c300 | ||
|
|
455da60846 | ||
|
|
46b2eb3c14 | ||
|
|
6236001ff4 | ||
|
|
1471f2c67a | ||
|
|
b485463197 | ||
|
|
64fca8a7ed | ||
|
|
e3d9501b31 | ||
|
|
1699adfa03 | ||
|
|
db81310d71 | ||
|
|
8489521c0d | ||
|
|
2ee6282fdd | ||
|
|
ae218d0d15 | ||
|
|
26579b2231 | ||
|
|
04f1d950b9 | ||
|
|
191c0ae2bb | ||
|
|
5b32f31a31 | ||
|
|
3eac8e1c18 | ||
|
|
dc8f0cddee | ||
|
|
97b263aee9 | ||
|
|
cb53c4f0e1 | ||
|
|
0d029e7038 | ||
|
|
aae725a44c | ||
|
|
0e833d75e6 | ||
|
|
ae83f77511 | ||
|
|
4d8420f328 | ||
|
|
d8f2a793d3 | ||
|
|
558b53a856 | ||
|
|
0764adc82f | ||
|
|
87fd7d617e | ||
|
|
3e83af5f5e | ||
|
|
0dc57fdcf1 | ||
|
|
3799670d01 | ||
|
|
d6390d50bf | ||
|
|
e27b31c9c4 | ||
|
|
684b7f6a57 | ||
|
|
b0b2fd768c | ||
|
|
9180bfffcd | ||
|
|
058bb0f4ea | ||
|
|
64b125700e | ||
|
|
6f650a61ca | ||
|
|
d4e95f4653 | ||
|
|
26be91fb8e | ||
|
|
43a3becf08 | ||
|
|
d127d68b9f | ||
|
|
730da3e3c2 | ||
|
|
661722753b | ||
|
|
ac445a1e18 | ||
|
|
b7a3d41baf | ||
|
|
096475b356 | ||
|
|
d08554dabd | ||
|
|
cbe8f8b760 | ||
|
|
8987bc53e0 | ||
|
|
39802b31fe | ||
|
|
e5a2aef1bf | ||
|
|
edb03bd224 | ||
|
|
1204f43ea9 | ||
|
|
b542bc9e4e | ||
|
|
61a97ccede | ||
|
|
a1ef27c0b8 | ||
|
|
fb8f2cd11b | ||
|
|
1d8a9ddf84 | ||
|
|
bea66b6476 | ||
|
|
a8111934d5 | ||
|
|
f201e983b0 | ||
|
|
81332e1e27 | ||
|
|
ea84f50603 | ||
|
|
ccc94e7ab6 | ||
|
|
4c05be0c1b | ||
|
|
a493a90c59 | ||
|
|
4a18df8574 | ||
|
|
cfa74c1dc6 | ||
|
|
de706de8c3 | ||
|
|
71fa0dc6bb | ||
|
|
914a2d8e41 | ||
|
|
956b64d348 | ||
|
|
91489cd378 | ||
|
|
615bc3b8f7 | ||
|
|
5b645419fd | ||
|
|
c436e07022 | ||
|
|
188fb37801 | ||
|
|
44fed3eb9b | ||
|
|
36abd82a7e | ||
|
|
fd6d0b6897 | ||
|
|
09b0018b93 | ||
|
|
2624e603d4 | ||
|
|
fd61eda16d | ||
|
|
a6dda5fefd | ||
|
|
da8356b477 | ||
|
|
e5fb20c17b | ||
|
|
c472bd7437 | ||
|
|
8796756ae5 | ||
|
|
9c8f285a98 | ||
|
|
8154e24027 | ||
|
|
629cfbccc4 | ||
|
|
c5990791db | ||
|
|
16241938af | ||
|
|
6a8cb38dd3 | ||
|
|
bac2227ee2 | ||
|
|
dcb50cc0c8 | ||
|
|
f503c4a3e1 | ||
|
|
a56c925da9 | ||
|
|
833cc00014 | ||
|
|
09e8cf33d7 | ||
|
|
a03bb2fbf7 | ||
|
|
bb784ec6be | ||
|
|
996c00c81c | ||
|
|
30bdca07e9 | ||
|
|
b4b49cf3f6 | ||
|
|
189796e94f | ||
|
|
2431c7d925 | ||
|
|
fc9c61714f | ||
|
|
e096658df3 | ||
|
|
b1d58c5454 | ||
|
|
ced66eb11f | ||
|
|
1b44daddf6 | ||
|
|
a309c1b38e | ||
|
|
e56aaf5f44 | ||
|
|
632cee4426 | ||
|
|
af25fc35d1 | ||
|
|
db49b84a44 | ||
|
|
c5f4b8c1c7 | ||
|
|
6a0daddd8f | ||
|
|
af997b221d | ||
|
|
9d6855702e | ||
|
|
daf256e15f | ||
|
|
0eddcb4424 | ||
|
|
b7f6794e03 | ||
|
|
cd9fc88151 | ||
|
|
fbe0f37e1b | ||
|
|
c496194614 | ||
|
|
ca639ceb63 | ||
|
|
e85537aac4 | ||
|
|
e839c9cae6 | ||
|
|
100e94c18e | ||
|
|
e7f7b4e499 | ||
|
|
eca8b53868 | ||
|
|
b8767be373 | ||
|
|
9658eade0b | ||
|
|
689536ec92 | ||
|
|
3ff2999228 | ||
|
|
4f65104ecc | ||
|
|
242e1c342c | ||
|
|
935e3b70ae | ||
|
|
8d1bfb5a85 | ||
|
|
2ac664968d | ||
|
|
1199ad8f47 | ||
|
|
c12559f8f6 | ||
|
|
840e1abcdc | ||
|
|
e3594ba0ec | ||
|
|
0d07dc5355 | ||
|
|
4170258595 | ||
|
|
dacfc41d21 | ||
|
|
5158877b72 | ||
|
|
a785ba3c4d | ||
|
|
92dbd4eca2 | ||
|
|
a7144c5b6b |
@@ -8,7 +8,7 @@ set(APPLICATION_NAME ${PROJECT_NAME})
|
|||||||
|
|
||||||
set(APPLICATION_VERSION_MAJOR "0")
|
set(APPLICATION_VERSION_MAJOR "0")
|
||||||
set(APPLICATION_VERSION_MINOR "5")
|
set(APPLICATION_VERSION_MINOR "5")
|
||||||
set(APPLICATION_VERSION_PATCH "0")
|
set(APPLICATION_VERSION_PATCH "5")
|
||||||
|
|
||||||
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
|
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINO
|
|||||||
# Increment AGE. Set REVISION to 0
|
# Increment AGE. Set REVISION to 0
|
||||||
# If the source code was changed, but there were no interface changes:
|
# If the source code was changed, but there were no interface changes:
|
||||||
# Increment REVISION.
|
# Increment REVISION.
|
||||||
set(LIBRARY_VERSION "4.2.0")
|
set(LIBRARY_VERSION "4.2.5")
|
||||||
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
|
||||||
@@ -78,9 +78,11 @@ add_subdirectory(src)
|
|||||||
|
|
||||||
# pkg-config file
|
# pkg-config file
|
||||||
configure_file(libssh.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc)
|
configure_file(libssh.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc)
|
||||||
|
configure_file(libssh_threads.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh_threads.pc)
|
||||||
install(
|
install(
|
||||||
FILES
|
FILES
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/libssh.pc
|
${CMAKE_CURRENT_BINARY_DIR}/libssh.pc
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/libssh_threads.pc
|
||||||
DESTINATION
|
DESTINATION
|
||||||
${LIB_INSTALL_DIR}/pkgconfig
|
${LIB_INSTALL_DIR}/pkgconfig
|
||||||
COMPONENT
|
COMPONENT
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
|
|||||||
|
|
||||||
|
|
||||||
### versions
|
### versions
|
||||||
set(CPACK_PACKAGE_VERSION_MAJOR "0")
|
set(CPACK_PACKAGE_VERSION_MAJOR "${APPLICATION_VERSION_MAJOR}")
|
||||||
set(CPACK_PACKAGE_VERSION_MINOR "4")
|
set(CPACK_PACKAGE_VERSION_MINOR "${APPLICATION_VERSION_MINOR}")
|
||||||
set(CPACK_PACKAGE_VERSION_PATCH "90")
|
set(CPACK_PACKAGE_VERSION_PATCH "${APPLICATION_VERSION_PATCH}")
|
||||||
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
|
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
61
ChangeLog
61
ChangeLog
@@ -1,7 +1,64 @@
|
|||||||
ChangeLog
|
ChangeLog
|
||||||
==========
|
==========
|
||||||
|
|
||||||
version 0.5.0 (released xxxx-xx-xx)
|
version 0.5.5 (released 2013-07-26)
|
||||||
|
* BUG 103: Fix ProxyCommand parsing.
|
||||||
|
* Fix setting -D_FORTIFY_SOURCE=2.
|
||||||
|
* Fix pollset error return if emtpy.
|
||||||
|
* Fix NULL pointer checks in channel functions.
|
||||||
|
* Several bugfixes.
|
||||||
|
|
||||||
|
version 0.5.4 (released 2013-01-22)
|
||||||
|
* CVE-2013-0176 - NULL dereference leads to denial of service
|
||||||
|
* Fixed several NULL pointer dereferences in SSHv1.
|
||||||
|
* Fixed a free crash bug in options parsing.
|
||||||
|
|
||||||
|
version 0.5.3 (released 2012-11-20)
|
||||||
|
* CVE-2012-4559 Fixed multiple double free() flaws.
|
||||||
|
* CVE-2012-4560 Fixed multiple buffer overflow flaws.
|
||||||
|
* CVE-2012-4561 Fixed multiple invalid free() flaws.
|
||||||
|
* BUG #84 - Fix bug in sftp_mkdir not returning on error.
|
||||||
|
* BUG #85 - Fixed a possible channel infinite loop if the connection dropped.
|
||||||
|
* BUG #88 - Added missing channel request_state and set it to accepted.
|
||||||
|
* BUG #89 - Reset error state to no error on successful SSHv1 authentiction.
|
||||||
|
* Fixed a possible use after free in ssh_free().
|
||||||
|
* Fixed multiple possible NULL pointer dereferences.
|
||||||
|
* Fixed multiple memory leaks in error paths.
|
||||||
|
* Fixed timeout handling.
|
||||||
|
* Fixed regression in pre-connected socket setting.
|
||||||
|
* Handle all unknown global messages.
|
||||||
|
|
||||||
|
version 0.5.2 (released 2011-09-17)
|
||||||
|
* Increased window size x10.
|
||||||
|
* Fixed SSHv1.
|
||||||
|
* Fixed bugged lists.
|
||||||
|
* Fixed use-after-free + inconsistent callbacks call in poll.
|
||||||
|
* Fixed scp documentation.
|
||||||
|
* Fixed possible infinite loop in channel_read().
|
||||||
|
* Fixed handling of short reads of sftp_async_read().
|
||||||
|
* Fixed handling request service timeout in blocking mode.
|
||||||
|
* Fixed ssh_auth_list() documentation.
|
||||||
|
* Fixed incorrect return values in ssh_channel_write().
|
||||||
|
* Fixed an infinite loop in the termination callback.
|
||||||
|
* Fixed handling of SSH_AGAIN in channel_open().
|
||||||
|
* Fixed "status -5 inflating zlib packet"
|
||||||
|
|
||||||
|
version 0.5.1 (released 2011-08-09)
|
||||||
|
* Added checks for NULL pointers in string.c.
|
||||||
|
* Set the channel max packet size to 32768.
|
||||||
|
* Don't (de)compress empty buffers.
|
||||||
|
* Fixed ssh_scp_write so it works when doing recursive copy.
|
||||||
|
* Fixed another source of endless wait.
|
||||||
|
* Fixed an endless loop in case of a channel_open error.
|
||||||
|
* Fixed session timeout handling.
|
||||||
|
* Fixed ssh_channel_from_local() loop.
|
||||||
|
* Fixed permissions of scp example when we copy a file.
|
||||||
|
* Workaround ssh_get_user_home_dir on LDAP users.
|
||||||
|
* Added pkg-config support for libssh_threads.
|
||||||
|
* Fixed compilation without server and sftp modes.
|
||||||
|
* Fix static .lib overwriting on Windows.
|
||||||
|
|
||||||
|
version 0.5.0 (released 2011-06-01)
|
||||||
* Added ssh_ prefix to all functions.
|
* Added ssh_ prefix to all functions.
|
||||||
* Added complete Windows support.
|
* Added complete Windows support.
|
||||||
* Added improved server support.
|
* Added improved server support.
|
||||||
@@ -10,6 +67,8 @@ version 0.5.0 (released xxxx-xx-xx)
|
|||||||
* Added a multiplatform ssh_getpass() function.
|
* Added a multiplatform ssh_getpass() function.
|
||||||
* Added a tutorial.
|
* Added a tutorial.
|
||||||
* Added a lot of documentation.
|
* Added a lot of documentation.
|
||||||
|
* Fixed a lot of bugs.
|
||||||
|
* Fixed several memory leaks.
|
||||||
|
|
||||||
version 0.4.8 (released 2011-01-15)
|
version 0.4.8 (released 2011-01-15)
|
||||||
* Fixed memory leaks in session signing.
|
* Fixed memory leaks in session signing.
|
||||||
|
|||||||
@@ -43,7 +43,8 @@ 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_file(wspiapi.h HAVE_WSPIAPI_H)
|
||||||
if (NOT HAVE_WSPIAPI_H)
|
if (NOT HAVE_WSPIAPI_H)
|
||||||
@@ -91,23 +92,34 @@ if (UNIX)
|
|||||||
if (HAVE_LIBSOCKET)
|
if (HAVE_LIBSOCKET)
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} socket)
|
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} socket)
|
||||||
endif (HAVE_LIBSOCKET)
|
endif (HAVE_LIBSOCKET)
|
||||||
|
|
||||||
# libresolv
|
# libresolv
|
||||||
check_library_exists(resolv hstrerror "" HAVE_LIBRESOLV)
|
check_library_exists(resolv hstrerror "" HAVE_LIBRESOLV)
|
||||||
if (HAVE_LIBRESOLV)
|
if (HAVE_LIBRESOLV)
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} resolv)
|
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} resolv)
|
||||||
endif (HAVE_LIBRESOLV)
|
endif (HAVE_LIBRESOLV)
|
||||||
check_library_exists(rt nanosleep "" HAVE_LIBRT)
|
|
||||||
|
# libnsl/inet_pton (Solaris)
|
||||||
|
check_library_exists(nsl inet_pton "" HAVE_LIBNSL)
|
||||||
|
if (HAVE_LIBNSL)
|
||||||
|
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} nsl)
|
||||||
|
endif (HAVE_LIBNSL)
|
||||||
|
|
||||||
# librt
|
# librt
|
||||||
if (HAVE_LIBRT)
|
check_library_exists(rt nanosleep "" HAVE_LIBRT)
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} rt)
|
|
||||||
endif (HAVE_LIBRT)
|
|
||||||
endif (NOT LINUX)
|
endif (NOT LINUX)
|
||||||
|
|
||||||
|
check_library_exists(rt clock_gettime "" HAVE_CLOCK_GETTIME)
|
||||||
|
if (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
|
||||||
|
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} rt)
|
||||||
|
endif (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
|
||||||
|
|
||||||
check_function_exists(getaddrinfo HAVE_GETADDRINFO)
|
check_function_exists(getaddrinfo HAVE_GETADDRINFO)
|
||||||
check_function_exists(poll HAVE_POLL)
|
check_function_exists(poll HAVE_POLL)
|
||||||
check_function_exists(select HAVE_SELECT)
|
check_function_exists(select HAVE_SELECT)
|
||||||
check_function_exists(cfmakeraw HAVE_CFMAKERAW)
|
check_function_exists(cfmakeraw HAVE_CFMAKERAW)
|
||||||
check_function_exists(regcomp HAVE_REGCOMP)
|
check_function_exists(regcomp HAVE_REGCOMP)
|
||||||
|
check_function_exists(ntohll HAVE_NTOHLL)
|
||||||
endif (UNIX)
|
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")
|
||||||
|
|||||||
109
README
109
README
@@ -55,17 +55,102 @@ ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
|
|||||||
5* Copyright policy
|
5* Copyright policy
|
||||||
-_-_-_-_-_-_-_-_-_-_
|
-_-_-_-_-_-_-_-_-_-_
|
||||||
|
|
||||||
The developers of libssh have a policy of asking for contributions to be made
|
libssh is a project with distributed copyright ownership, which means we prefer
|
||||||
under the personal copyright of the contributor, instead of a corporate
|
the copyright on parts of libssh to be held by individuals rather than
|
||||||
copyright.
|
corporations if possible. There are historical legal reasons for this, but one
|
||||||
|
of the best ways to explain it is that it’s much easier to work with
|
||||||
|
individuals who have ownership than corporate legal departments if we ever need
|
||||||
|
to make reasonable compromises with people using and working with libssh.
|
||||||
|
|
||||||
There are some reasons for the establishment of this policy:
|
We track the ownership of every part of libssh via git, our source code control
|
||||||
|
system, so we know the provenance of every piece of code that is committed to
|
||||||
|
libssh.
|
||||||
|
|
||||||
* Individual copyrights make copyright registration in the US a simpler
|
So if possible, if you’re doing libssh changes on behalf of a company who
|
||||||
process.
|
normally owns all the work you do please get them to assign personal copyright
|
||||||
* If libssh is copyrighted by individuals rather than corporations,
|
ownership of your changes to you as an individual, that makes things very easy
|
||||||
decisions regarding enforcement and protection of copyright will, more
|
for us to work with and avoids bringing corporate legal departments into the
|
||||||
likely, be made in the interests of the project, and not in the interests
|
picture.
|
||||||
of any corporation’s shareholders.
|
|
||||||
* If we ever need to relicense a portion of the code contacting individuals
|
If you can’t do this we can still accept patches from you owned by your
|
||||||
for permission to do so is much easier than contacting a company.
|
employer under a standard employment contract with corporate copyright
|
||||||
|
ownership. It just requires a simple set-up process first.
|
||||||
|
|
||||||
|
We use a process very similar to the way things are done in the Linux Kernel
|
||||||
|
community, so it should be very easy to get a sign off from your corporate
|
||||||
|
legal department. The only changes we’ve made are to accommodate the license we
|
||||||
|
use, which is LGPLv2 (or later) whereas the Linux kernel uses GPLv2.
|
||||||
|
|
||||||
|
The process is called signing.
|
||||||
|
|
||||||
|
How to sign your work
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Once you have permission to contribute to libssh from your employer, simply
|
||||||
|
email a copy of the following text from your corporate email address to:
|
||||||
|
|
||||||
|
contributing@libssh.org
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
libssh Developer's Certificate of Origin. Version 1.0
|
||||||
|
|
||||||
|
By making a contribution to this project, I certify that:
|
||||||
|
|
||||||
|
(a) The contribution was created in whole or in part by me and I
|
||||||
|
have the right to submit it under the appropriate
|
||||||
|
version of the GNU General Public License; or
|
||||||
|
|
||||||
|
(b) The contribution is based upon previous work that, to the best of
|
||||||
|
my knowledge, is covered under an appropriate open source license
|
||||||
|
and I have the right under that license to submit that work with
|
||||||
|
modifications, whether created in whole or in part by me, under
|
||||||
|
the GNU General Public License, in the appropriate version; or
|
||||||
|
|
||||||
|
(c) The contribution was provided directly to me by some other
|
||||||
|
person who certified (a) or (b) and I have not modified it.
|
||||||
|
|
||||||
|
(d) I understand and agree that this project and the contribution are
|
||||||
|
public and that a record of the contribution (including all
|
||||||
|
metadata and personal information I submit with it, including my
|
||||||
|
sign-off) is maintained indefinitely and may be redistributed
|
||||||
|
consistent with the libssh Team's policies and the requirements of
|
||||||
|
the GNU GPL where they are relevant.
|
||||||
|
|
||||||
|
(e) I am granting this work to this project under the terms of the
|
||||||
|
GNU Lesser General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2.1 of
|
||||||
|
the License, or (at the option of the project) any later version.
|
||||||
|
|
||||||
|
http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
We will maintain a copy of that email as a record that you have the rights to
|
||||||
|
contribute code to libssh under the required licenses whilst working for the
|
||||||
|
company where the email came from.
|
||||||
|
|
||||||
|
Then when sending in a patch via the normal mechanisms described above, add a
|
||||||
|
line that states:
|
||||||
|
|
||||||
|
|
||||||
|
Signed-off-by: Random J Developer <random@developer.example.org>
|
||||||
|
|
||||||
|
|
||||||
|
using your real name and the email address you sent the original email you used
|
||||||
|
to send the libssh Developer’s Certificate of Origin to us (sorry, no
|
||||||
|
pseudonyms or anonymous contributions.)
|
||||||
|
|
||||||
|
That’s it! Such code can then quite happily contain changes that have copyright
|
||||||
|
messages such as:
|
||||||
|
|
||||||
|
|
||||||
|
(c) Example Corporation.
|
||||||
|
|
||||||
|
|
||||||
|
and can be merged into the libssh codebase in the same way as patches from any
|
||||||
|
other individual. You don’t need to send in a copy of the libssh Developer’s
|
||||||
|
Certificate of Origin for each patch, or inside each patch. Just the sign-off
|
||||||
|
message is all that is required once we’ve received the initial email.
|
||||||
|
|
||||||
|
Have fun and happy libssh hacking!
|
||||||
|
|
||||||
|
The libssh Team
|
||||||
|
|||||||
@@ -25,10 +25,15 @@ if (UNIX AND NOT WIN32)
|
|||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -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)
|
if (CMAKE_BUILD_TYPE)
|
||||||
if (WITH_FORTIFY_SOURCE)
|
string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FORTIFY_SOURCE=2")
|
if (NOT CMAKE_BUILD_TYPE_LOWER MATCHES debug)
|
||||||
endif (WITH_FORTIFY_SOURCE)
|
check_c_compiler_flag("-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE)
|
||||||
|
if (WITH_FORTIFY_SOURCE)
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FORTIFY_SOURCE=2")
|
||||||
|
endif (WITH_FORTIFY_SOURCE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
endif (${CMAKE_C_COMPILER_ID} MATCHES GNU)
|
endif (${CMAKE_C_COMPILER_ID} MATCHES GNU)
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -77,6 +77,12 @@
|
|||||||
/* Define to 1 if you have the `regcomp' function. */
|
/* Define to 1 if you have the `regcomp' function. */
|
||||||
#cmakedefine HAVE_REGCOMP 1
|
#cmakedefine HAVE_REGCOMP 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `clock_gettime' function. */
|
||||||
|
#cmakedefine HAVE_CLOCK_GETTIME 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `ntohll' function. */
|
||||||
|
#cmakedefine HAVE_NTOHLL 1
|
||||||
|
|
||||||
/*************************** LIBRARIES ***************************/
|
/*************************** LIBRARIES ***************************/
|
||||||
|
|
||||||
/* Define to 1 if you have the `crypto' library (-lcrypto). */
|
/* Define to 1 if you have the `crypto' library (-lcrypto). */
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ This tutorial concentrates for its main part on the "client" side of libssh.
|
|||||||
To learn how to accept incoming SSH connexions (how to write a SSH server),
|
To learn how to accept incoming SSH connexions (how to write a SSH server),
|
||||||
you'll have to jump to the end of this document.
|
you'll have to jump to the end of this document.
|
||||||
|
|
||||||
This tutorial describes libssh version 0.5.0. This version is the development
|
This tutorial describes libssh version 0.5.0. This version is a little different
|
||||||
version and is *not* published yet. However, the examples should work with
|
from the 0.4.X series. However, the examples should work with
|
||||||
little changes on versions like 0.4.2 and later.
|
little changes on versions like 0.4.2 and later.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
109
doc/mainpage.dox
109
doc/mainpage.dox
@@ -40,20 +40,105 @@ The libssh library provides:
|
|||||||
|
|
||||||
@section main-copyright Copyright Policy
|
@section main-copyright Copyright Policy
|
||||||
|
|
||||||
The developers of libssh have a policy of asking for contributions to be made
|
libssh is a project with distributed copyright ownership, which means we prefer
|
||||||
under the personal copyright of the contributor, instead of a corporate
|
the copyright on parts of libssh to be held by individuals rather than
|
||||||
copyright.
|
corporations if possible. There are historical legal reasons for this, but one
|
||||||
|
of the best ways to explain it is that it’s much easier to work with
|
||||||
|
individuals who have ownership than corporate legal departments if we ever need
|
||||||
|
to make reasonable compromises with people using and working with libssh.
|
||||||
|
|
||||||
There are some reasons for the establishment of this policy:
|
We track the ownership of every part of libssh via git, our source code control
|
||||||
|
system, so we know the provenance of every piece of code that is committed to
|
||||||
|
libssh.
|
||||||
|
|
||||||
@li Individual copyrights make copyright registration in the US a simpler
|
So if possible, if you’re doing libssh changes on behalf of a company who
|
||||||
process.
|
normally owns all the work you do please get them to assign personal copyright
|
||||||
@li If libssh is copyrighted by individuals rather than corporations,
|
ownership of your changes to you as an individual, that makes things very easy
|
||||||
decisions regarding enforcement and protection of copyright will, more
|
for us to work with and avoids bringing corporate legal departments into the
|
||||||
likely, be made in the interests of the project, and not in the interests
|
picture.
|
||||||
of any corporation’s shareholders.
|
|
||||||
@li If we ever need to relicense a portion of the code contacting individuals
|
If you can’t do this we can still accept patches from you owned by your
|
||||||
for permission to do so is much easier than contacting a company.
|
employer under a standard employment contract with corporate copyright
|
||||||
|
ownership. It just requires a simple set-up process first.
|
||||||
|
|
||||||
|
We use a process very similar to the way things are done in the Linux Kernel
|
||||||
|
community, so it should be very easy to get a sign off from your corporate
|
||||||
|
legal department. The only changes we’ve made are to accommodate the license we
|
||||||
|
use, which is LGPLv2 (or later) whereas the Linux kernel uses GPLv2.
|
||||||
|
|
||||||
|
The process is called signing.
|
||||||
|
|
||||||
|
How to sign your work
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Once you have permission to contribute to libssh from your employer, simply
|
||||||
|
email a copy of the following text from your corporate email address to:
|
||||||
|
|
||||||
|
contributing@libssh.org
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
libssh Developer's Certificate of Origin. Version 1.0
|
||||||
|
|
||||||
|
By making a contribution to this project, I certify that:
|
||||||
|
|
||||||
|
(a) The contribution was created in whole or in part by me and I
|
||||||
|
have the right to submit it under the appropriate
|
||||||
|
version of the GNU General Public License; or
|
||||||
|
|
||||||
|
(b) The contribution is based upon previous work that, to the best of
|
||||||
|
my knowledge, is covered under an appropriate open source license
|
||||||
|
and I have the right under that license to submit that work with
|
||||||
|
modifications, whether created in whole or in part by me, under
|
||||||
|
the GNU General Public License, in the appropriate version; or
|
||||||
|
|
||||||
|
(c) The contribution was provided directly to me by some other
|
||||||
|
person who certified (a) or (b) and I have not modified it.
|
||||||
|
|
||||||
|
(d) I understand and agree that this project and the contribution are
|
||||||
|
public and that a record of the contribution (including all
|
||||||
|
metadata and personal information I submit with it, including my
|
||||||
|
sign-off) is maintained indefinitely and may be redistributed
|
||||||
|
consistent with the libssh Team's policies and the requirements of
|
||||||
|
the GNU GPL where they are relevant.
|
||||||
|
|
||||||
|
(e) I am granting this work to this project under the terms of the
|
||||||
|
GNU Lesser General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2.1 of
|
||||||
|
the License, or (at the option of the project) any later version.
|
||||||
|
|
||||||
|
http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
@endverbatim
|
||||||
|
|
||||||
|
We will maintain a copy of that email as a record that you have the rights to
|
||||||
|
contribute code to libssh under the required licenses whilst working for the
|
||||||
|
company where the email came from.
|
||||||
|
|
||||||
|
Then when sending in a patch via the normal mechanisms described above, add a
|
||||||
|
line that states:
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
Signed-off-by: Random J Developer <random@developer.example.org>
|
||||||
|
@endverbatim
|
||||||
|
|
||||||
|
using your real name and the email address you sent the original email you used
|
||||||
|
to send the libssh Developer’s Certificate of Origin to us (sorry, no
|
||||||
|
pseudonyms or anonymous contributions.)
|
||||||
|
|
||||||
|
That’s it! Such code can then quite happily contain changes that have copyright
|
||||||
|
messages such as:
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
(c) Example Corporation.
|
||||||
|
@endverbatim
|
||||||
|
|
||||||
|
and can be merged into the libssh codebase in the same way as patches from any
|
||||||
|
other individual. You don’t need to send in a copy of the libssh Developer’s
|
||||||
|
Certificate of Origin for each patch, or inside each patch. Just the sign-off
|
||||||
|
message is all that is required once we’ve received the initial email.
|
||||||
|
|
||||||
|
Have fun and happy libssh hacking!
|
||||||
|
|
||||||
|
The libssh Team
|
||||||
|
|
||||||
@section main-rfc Internet standard
|
@section main-rfc Internet standard
|
||||||
|
|
||||||
|
|||||||
@@ -6,16 +6,16 @@ libssh may be used in multithreaded applications, but under several conditions :
|
|||||||
- Threading must be initialized during the initialization of libssh. This
|
- Threading must be initialized during the initialization of libssh. This
|
||||||
initialization must be done outside of any threading context.
|
initialization must be done outside of any threading context.
|
||||||
- If pthreads is being used by your application (or your framework's backend),
|
- If pthreads is being used by your application (or your framework's backend),
|
||||||
you must link with libssh_threads_pthread dynamic library and initialize
|
you must link with libssh_threads dynamic library and initialize
|
||||||
threading with the ssh_threads_pthreads threading object.
|
threading with the ssh_threads_pthreads threading object.
|
||||||
- If an other threading library is being used by your application, you must
|
- If an other threading library is being used by your application, you must
|
||||||
implement all the methods of the ssh_threads_callbacks_struct structure
|
implement all the methods of the ssh_threads_callbacks_struct structure
|
||||||
and initialize libssh with it.
|
and initialize libssh with it.
|
||||||
- At all times, you may use different sessions inside threads, make parallel
|
- At all times, you may use different sessions inside threads, make parallel
|
||||||
connections, read/write on different sessions and so on. You can use a
|
connections, read/write on different sessions and so on. You *cannot* use a
|
||||||
single session in several channels at the same time. This will lead to
|
single session (or channels for a single session) in several threads at the same
|
||||||
internal state corruption. This limitation is being worked out and will
|
time. This will most likely lead to internal state corruption. This limitation is
|
||||||
maybe disappear later.
|
being worked out and will maybe disappear later.
|
||||||
|
|
||||||
@subsection threads_init Initialization of threads
|
@subsection threads_init Initialization of threads
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ use, using ssh_threads_set_callbacks(), then call ssh_init().
|
|||||||
@code
|
@code
|
||||||
#include <libssh/callbacks.h>
|
#include <libssh/callbacks.h>
|
||||||
...
|
...
|
||||||
ssh_threads_set_callbacks(ssh_threads_noop);
|
ssh_threads_set_callbacks(ssh_threads_get_noop());
|
||||||
ssh_init();
|
ssh_init();
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
@@ -40,14 +40,14 @@ threading backend:
|
|||||||
@code
|
@code
|
||||||
#include <libssh/callbacks.h>
|
#include <libssh/callbacks.h>
|
||||||
...
|
...
|
||||||
ssh_threads_set_callbacks(ssh_threads_pthread);
|
ssh_threads_set_callbacks(ssh_threads_get_pthread());
|
||||||
ssh_init();
|
ssh_init();
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
However, you must be sure to link with the library ssh_threads_pthread. If
|
However, you must be sure to link with the library ssh_threads. If
|
||||||
you're using gcc, you must use the commandline
|
you're using gcc, you must use the commandline
|
||||||
@code
|
@code
|
||||||
gcc -o output input.c -lssh -lssh_threads_pthread
|
gcc -o output input.c -lssh -lssh_threads
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ int authenticate_console(ssh_session session){
|
|||||||
banner = ssh_get_issue_banner(session);
|
banner = ssh_get_issue_banner(session);
|
||||||
if (banner) {
|
if (banner) {
|
||||||
printf("%s\n",banner);
|
printf("%s\n",banner);
|
||||||
free(banner);
|
ssh_string_free_char(banner);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|||||||
@@ -32,22 +32,25 @@ ssh_session connect_ssh(const char *host, const char *user,int verbosity){
|
|||||||
|
|
||||||
if(user != NULL){
|
if(user != NULL){
|
||||||
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
|
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
|
||||||
ssh_disconnect(session);
|
ssh_free(session);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) {
|
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) {
|
||||||
|
ssh_free(session);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||||
if(ssh_connect(session)){
|
if(ssh_connect(session)){
|
||||||
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
|
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
|
||||||
ssh_disconnect(session);
|
ssh_disconnect(session);
|
||||||
|
ssh_free(session);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if(verify_knownhost(session)<0){
|
if(verify_knownhost(session)<0){
|
||||||
ssh_disconnect(session);
|
ssh_disconnect(session);
|
||||||
|
ssh_free(session);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
auth=authenticate_console(session);
|
auth=authenticate_console(session);
|
||||||
@@ -59,5 +62,6 @@ ssh_session connect_ssh(const char *host, const char *user,int verbosity){
|
|||||||
fprintf(stderr,"Error while authenticating : %s\n",ssh_get_error(session));
|
fprintf(stderr,"Error while authenticating : %s\n",ssh_get_error(session));
|
||||||
}
|
}
|
||||||
ssh_disconnect(session);
|
ssh_disconnect(session);
|
||||||
|
ssh_free(session);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ int main(void) {
|
|||||||
|
|
||||||
session = connect_ssh("localhost", NULL, 0);
|
session = connect_ssh("localhost", NULL, 0);
|
||||||
if (session == NULL) {
|
if (session == NULL) {
|
||||||
|
ssh_finalize();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,6 +21,7 @@ int main(void) {
|
|||||||
if (channel == NULL) {
|
if (channel == NULL) {
|
||||||
ssh_disconnect(session);
|
ssh_disconnect(session);
|
||||||
ssh_free(session);
|
ssh_free(session);
|
||||||
|
ssh_finalize();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +50,9 @@ int main(void) {
|
|||||||
ssh_channel_send_eof(channel);
|
ssh_channel_send_eof(channel);
|
||||||
ssh_channel_close(channel);
|
ssh_channel_close(channel);
|
||||||
ssh_channel_free(channel);
|
ssh_channel_free(channel);
|
||||||
|
ssh_disconnect(session);
|
||||||
ssh_free(session);
|
ssh_free(session);
|
||||||
|
ssh_finalize();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
failed:
|
failed:
|
||||||
@@ -56,6 +60,7 @@ failed:
|
|||||||
ssh_channel_free(channel);
|
ssh_channel_free(channel);
|
||||||
ssh_disconnect(session);
|
ssh_disconnect(session);
|
||||||
ssh_free(session);
|
ssh_free(session);
|
||||||
|
ssh_finalize();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ int verify_knownhost(ssh_session session){
|
|||||||
case SSH_SERVER_KNOWN_CHANGED:
|
case SSH_SERVER_KNOWN_CHANGED:
|
||||||
fprintf(stderr,"Host key for server changed : server's one is now :\n");
|
fprintf(stderr,"Host key for server changed : server's one is now :\n");
|
||||||
ssh_print_hexa("Public key hash",hash, hlen);
|
ssh_print_hexa("Public key hash",hash, hlen);
|
||||||
free(hash);
|
ssh_clean_pubkey_hash(&hash);
|
||||||
fprintf(stderr,"For security reason, connection will be stopped\n");
|
fprintf(stderr,"For security reason, connection will be stopped\n");
|
||||||
return -1;
|
return -1;
|
||||||
case SSH_SERVER_FOUND_OTHER:
|
case SSH_SERVER_FOUND_OTHER:
|
||||||
@@ -65,20 +65,23 @@ int verify_knownhost(ssh_session session){
|
|||||||
hexa = ssh_get_hexa(hash, hlen);
|
hexa = ssh_get_hexa(hash, hlen);
|
||||||
fprintf(stderr,"The server is unknown. Do you trust the host key ?\n");
|
fprintf(stderr,"The server is unknown. Do you trust the host key ?\n");
|
||||||
fprintf(stderr, "Public key hash: %s\n", hexa);
|
fprintf(stderr, "Public key hash: %s\n", hexa);
|
||||||
free(hexa);
|
ssh_string_free_char(hexa);
|
||||||
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
||||||
|
ssh_clean_pubkey_hash(&hash);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(strncasecmp(buf,"yes",3)!=0){
|
if(strncasecmp(buf,"yes",3)!=0){
|
||||||
|
ssh_clean_pubkey_hash(&hash);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
|
fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
|
||||||
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
||||||
|
ssh_clean_pubkey_hash(&hash);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(strncasecmp(buf,"yes",3)==0){
|
if(strncasecmp(buf,"yes",3)==0){
|
||||||
if (ssh_write_knownhost(session) < 0) {
|
if (ssh_write_knownhost(session) < 0) {
|
||||||
free(hash);
|
ssh_clean_pubkey_hash(&hash);
|
||||||
fprintf(stderr, "error %s\n", strerror(errno));
|
fprintf(stderr, "error %s\n", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -86,10 +89,10 @@ int verify_knownhost(ssh_session session){
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case SSH_SERVER_ERROR:
|
case SSH_SERVER_ERROR:
|
||||||
free(hash);
|
ssh_clean_pubkey_hash(&hash);
|
||||||
fprintf(stderr,"%s",ssh_get_error(session));
|
fprintf(stderr,"%s",ssh_get_error(session));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
free(hash);
|
ssh_clean_pubkey_hash(&hash);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
|
|||||||
fd=fileno(src->file);
|
fd=fileno(src->file);
|
||||||
fstat(fd,&s);
|
fstat(fd,&s);
|
||||||
size=s.st_size;
|
size=s.st_size;
|
||||||
mode = s.st_mode & S_IFMT;
|
mode = s.st_mode & ~S_IFMT;
|
||||||
filename=ssh_basename(src->path);
|
filename=ssh_basename(src->path);
|
||||||
} else {
|
} else {
|
||||||
size=0;
|
size=0;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ program.
|
|||||||
#include <libssh/libsshpp.hpp>
|
#include <libssh/libsshpp.hpp>
|
||||||
|
|
||||||
int main(int argc, const char **argv){
|
int main(int argc, const char **argv){
|
||||||
ssh::Session session,s2;
|
ssh::Session session;
|
||||||
try {
|
try {
|
||||||
if(argc>1)
|
if(argc>1)
|
||||||
session.setOption(SSH_OPTIONS_HOST,argv[1]);
|
session.setOption(SSH_OPTIONS_HOST,argv[1]);
|
||||||
@@ -24,10 +24,10 @@ int main(int argc, const char **argv){
|
|||||||
session.setOption(SSH_OPTIONS_HOST,"localhost");
|
session.setOption(SSH_OPTIONS_HOST,"localhost");
|
||||||
session.connect();
|
session.connect();
|
||||||
session.userauthAutopubkey();
|
session.userauthAutopubkey();
|
||||||
|
session.disconnect();
|
||||||
} catch (ssh::SshException e){
|
} catch (ssh::SshException e){
|
||||||
std::cout << "Error during connection : ";
|
std::cout << "Error during connection : ";
|
||||||
std::cout << e.getError() << std::endl;
|
std::cout << e.getError() << std::endl;
|
||||||
}
|
}
|
||||||
//s2=session;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
|||||||
// we already looked for input from stdin. Now, we are looking for input from the channel
|
// we already looked for input from stdin. Now, we are looking for input from the channel
|
||||||
|
|
||||||
if(channel && ssh_channel_is_closed(channel)){
|
if(channel && ssh_channel_is_closed(channel)){
|
||||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",ssh_channel_get_exit_status(channel));
|
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||||
|
|
||||||
ssh_channel_free(channel);
|
ssh_channel_free(channel);
|
||||||
channel=NULL;
|
channel=NULL;
|
||||||
@@ -261,8 +261,8 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(lus==0){
|
if(lus==0){
|
||||||
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
|
ssh_log(session,SSH_LOG_RARE,"EOF received");
|
||||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",ssh_channel_get_exit_status(channel));
|
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||||
|
|
||||||
ssh_channel_free(channel);
|
ssh_channel_free(channel);
|
||||||
channel=channels[0]=NULL;
|
channel=channels[0]=NULL;
|
||||||
@@ -280,8 +280,8 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(lus==0){
|
if(lus==0){
|
||||||
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
|
ssh_log(session,SSH_LOG_RARE,"EOF received");
|
||||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",ssh_channel_get_exit_status(channel));
|
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||||
ssh_channel_free(channel);
|
ssh_channel_free(channel);
|
||||||
channel=channels[0]=NULL;
|
channel=channels[0]=NULL;
|
||||||
} else
|
} else
|
||||||
@@ -338,7 +338,7 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(channel && ssh_channel_is_closed(channel)){
|
if(channel && ssh_channel_is_closed(channel)){
|
||||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",ssh_channel_get_exit_status(channel));
|
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||||
|
|
||||||
ssh_channel_free(channel);
|
ssh_channel_free(channel);
|
||||||
channel=NULL;
|
channel=NULL;
|
||||||
@@ -353,8 +353,8 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(lus==0){
|
if(lus==0){
|
||||||
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
|
ssh_log(session,SSH_LOG_RARE,"EOF received");
|
||||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",ssh_channel_get_exit_status(channel));
|
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||||
|
|
||||||
ssh_channel_free(channel);
|
ssh_channel_free(channel);
|
||||||
channel=channels[0]=NULL;
|
channel=channels[0]=NULL;
|
||||||
@@ -372,8 +372,8 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(lus==0){
|
if(lus==0){
|
||||||
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
|
ssh_log(session,SSH_LOG_RARE,"EOF received");
|
||||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",ssh_channel_get_exit_status(channel));
|
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||||
ssh_channel_free(channel);
|
ssh_channel_free(channel);
|
||||||
channel=channels[0]=NULL;
|
channel=channels[0]=NULL;
|
||||||
} else
|
} else
|
||||||
@@ -431,8 +431,11 @@ static void batch_shell(ssh_session session){
|
|||||||
ssh_channel channel;
|
ssh_channel channel;
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
int i,s=0;
|
int i,s=0;
|
||||||
for(i=0;i<MAXCMD && cmds[i];++i)
|
for(i=0;i<MAXCMD && cmds[i];++i) {
|
||||||
s+=snprintf(buffer+s,sizeof(buffer)-s,"%s ",cmds[i]);
|
s+=snprintf(buffer+s,sizeof(buffer)-s,"%s ",cmds[i]);
|
||||||
|
free(cmds[i]);
|
||||||
|
cmds[i] = NULL;
|
||||||
|
}
|
||||||
channel=ssh_channel_new(session);
|
channel=ssh_channel_new(session);
|
||||||
ssh_channel_open_session(channel);
|
ssh_channel_open_session(channel);
|
||||||
if(ssh_channel_request_exec(channel,buffer)){
|
if(ssh_channel_request_exec(channel,buffer)){
|
||||||
|
|||||||
@@ -64,16 +64,21 @@ static void create_files(ssh_session session){
|
|||||||
}
|
}
|
||||||
if(ssh_channel_open_session(channel) != SSH_OK){
|
if(ssh_channel_open_session(channel) != SSH_OK){
|
||||||
fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session));
|
fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session));
|
||||||
|
ssh_channel_free(channel);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if(ssh_channel_request_exec(channel,createcommand) != SSH_OK){
|
if(ssh_channel_request_exec(channel,createcommand) != SSH_OK){
|
||||||
fprintf(stderr,"Error executing command: %s\n",ssh_get_error(session));
|
fprintf(stderr,"Error executing command: %s\n",ssh_get_error(session));
|
||||||
|
ssh_channel_close(channel);
|
||||||
|
ssh_channel_free(channel);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
while(!ssh_channel_is_eof(channel)){
|
while(!ssh_channel_is_eof(channel)){
|
||||||
ssh_channel_read(channel,buffer,1,1);
|
ssh_channel_read(channel,buffer,1,1);
|
||||||
if (write(1,buffer,1) < 0) {
|
if (write(1,buffer,1) < 0) {
|
||||||
fprintf(stderr, "Error writing to buffer\n");
|
fprintf(stderr, "Error writing to buffer\n");
|
||||||
|
ssh_channel_close(channel);
|
||||||
|
ssh_channel_free(channel);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,6 +96,7 @@ static int fetch_files(ssh_session session){
|
|||||||
ssh_scp scp=ssh_scp_new(session, SSH_SCP_READ | SSH_SCP_RECURSIVE, "/tmp/libssh_tests/*");
|
ssh_scp scp=ssh_scp_new(session, SSH_SCP_READ | SSH_SCP_RECURSIVE, "/tmp/libssh_tests/*");
|
||||||
if(ssh_scp_init(scp) != SSH_OK){
|
if(ssh_scp_init(scp) != SSH_OK){
|
||||||
fprintf(stderr,"error initializing scp: %s\n",ssh_get_error(session));
|
fprintf(stderr,"error initializing scp: %s\n",ssh_get_error(session));
|
||||||
|
ssh_scp_free(scp);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
printf("Trying to download 3 files (a,b,d) and 1 directory (c)\n");
|
printf("Trying to download 3 files (a,b,d) and 1 directory (c)\n");
|
||||||
@@ -108,12 +114,16 @@ static int fetch_files(ssh_session session){
|
|||||||
r=ssh_scp_read(scp,buffer,sizeof(buffer));
|
r=ssh_scp_read(scp,buffer,sizeof(buffer));
|
||||||
if(r==SSH_ERROR){
|
if(r==SSH_ERROR){
|
||||||
fprintf(stderr,"Error reading scp: %s\n",ssh_get_error(session));
|
fprintf(stderr,"Error reading scp: %s\n",ssh_get_error(session));
|
||||||
|
ssh_scp_close(scp);
|
||||||
|
ssh_scp_free(scp);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
printf("done\n");
|
printf("done\n");
|
||||||
break;
|
break;
|
||||||
case SSH_ERROR:
|
case SSH_ERROR:
|
||||||
fprintf(stderr,"Error: %s\n",ssh_get_error(session));
|
fprintf(stderr,"Error: %s\n",ssh_get_error(session));
|
||||||
|
ssh_scp_close(scp);
|
||||||
|
ssh_scp_free(scp);
|
||||||
return -1;
|
return -1;
|
||||||
case SSH_SCP_REQUEST_WARNING:
|
case SSH_SCP_REQUEST_WARNING:
|
||||||
fprintf(stderr,"Warning: %s\n",ssh_scp_request_get_warning(scp));
|
fprintf(stderr,"Warning: %s\n",ssh_scp_request_get_warning(scp));
|
||||||
@@ -134,6 +144,8 @@ static int fetch_files(ssh_session session){
|
|||||||
}
|
}
|
||||||
} while (1);
|
} while (1);
|
||||||
end:
|
end:
|
||||||
|
ssh_scp_close(scp);
|
||||||
|
ssh_scp_free(scp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,6 +159,7 @@ int main(int argc, char **argv){
|
|||||||
create_files(session);
|
create_files(session);
|
||||||
fetch_files(session);
|
fetch_files(session);
|
||||||
ssh_disconnect(session);
|
ssh_disconnect(session);
|
||||||
|
ssh_free(session);
|
||||||
ssh_finalize();
|
ssh_finalize();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,11 +23,10 @@
|
|||||||
#define BIND_H_
|
#define BIND_H_
|
||||||
|
|
||||||
#include "libssh/priv.h"
|
#include "libssh/priv.h"
|
||||||
|
#include "libssh/session.h"
|
||||||
|
|
||||||
struct ssh_bind_struct {
|
struct ssh_bind_struct {
|
||||||
struct error_struct error;
|
struct ssh_common_struct common; /* stuff common to ssh_bind and ssh_session */
|
||||||
|
|
||||||
ssh_callbacks callbacks; /* Callbacks to user functions */
|
|
||||||
struct ssh_bind_callbacks_struct *bind_callbacks;
|
struct ssh_bind_callbacks_struct *bind_callbacks;
|
||||||
void *bind_callbacks_userdata;
|
void *bind_callbacks_userdata;
|
||||||
|
|
||||||
@@ -40,8 +39,6 @@ struct ssh_bind_struct {
|
|||||||
char *bindaddr;
|
char *bindaddr;
|
||||||
socket_t bindfd;
|
socket_t bindfd;
|
||||||
unsigned int bindport;
|
unsigned int bindport;
|
||||||
unsigned int log_verbosity;
|
|
||||||
|
|
||||||
int blocking;
|
int blocking;
|
||||||
int toaccept;
|
int toaccept;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -48,8 +48,6 @@ enum ssh_channel_state_e {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ssh_channel_struct {
|
struct ssh_channel_struct {
|
||||||
struct ssh_channel_struct *prev;
|
|
||||||
struct ssh_channel_struct *next;
|
|
||||||
ssh_session session; /* SSH_SESSION pointer */
|
ssh_session session; /* SSH_SESSION pointer */
|
||||||
uint32_t local_channel;
|
uint32_t local_channel;
|
||||||
uint32_t local_window;
|
uint32_t local_window;
|
||||||
@@ -95,6 +93,7 @@ int channel_write_common(ssh_channel channel, const void *data,
|
|||||||
#ifdef WITH_SSH1
|
#ifdef WITH_SSH1
|
||||||
SSH_PACKET_CALLBACK(ssh_packet_data1);
|
SSH_PACKET_CALLBACK(ssh_packet_data1);
|
||||||
SSH_PACKET_CALLBACK(ssh_packet_close1);
|
SSH_PACKET_CALLBACK(ssh_packet_close1);
|
||||||
|
SSH_PACKET_CALLBACK(ssh_packet_exist_status1);
|
||||||
|
|
||||||
/* channels1.c */
|
/* channels1.c */
|
||||||
int channel_open_session1(ssh_channel channel);
|
int channel_open_session1(ssh_channel channel);
|
||||||
@@ -104,7 +103,7 @@ int channel_change_pty_size1(ssh_channel channel, int cols, int rows);
|
|||||||
int channel_request_shell1(ssh_channel channel);
|
int channel_request_shell1(ssh_channel channel);
|
||||||
int channel_request_exec1(ssh_channel channel, const char *cmd);
|
int channel_request_exec1(ssh_channel channel, const char *cmd);
|
||||||
int channel_write1(ssh_channel channel, const void *data, int len);
|
int channel_write1(ssh_channel channel, const void *data, int len);
|
||||||
|
ssh_channel ssh_get_channel1(ssh_session session);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* CHANNELS_H_ */
|
#endif /* CHANNELS_H_ */
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ LIBSSH_API ssh_string publickey_from_file(ssh_session session, const char *filen
|
|||||||
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 ssh_message ssh_message_retrieve(ssh_session session, uint32_t packettype);
|
||||||
LIBSSH_API void string_burn(ssh_string str);
|
LIBSSH_API void string_burn(ssh_string str);
|
||||||
LIBSSH_API ssh_string string_copy(ssh_string str);
|
LIBSSH_API ssh_string string_copy(ssh_string str);
|
||||||
LIBSSH_API void *string_data(ssh_string str);
|
LIBSSH_API void *string_data(ssh_string str);
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
/* libssh version */
|
/* libssh version */
|
||||||
#define LIBSSH_VERSION_MAJOR 0
|
#define LIBSSH_VERSION_MAJOR 0
|
||||||
#define LIBSSH_VERSION_MINOR 5
|
#define LIBSSH_VERSION_MINOR 5
|
||||||
#define LIBSSH_VERSION_MICRO 0
|
#define LIBSSH_VERSION_MICRO 5
|
||||||
|
|
||||||
#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, \
|
||||||
@@ -323,6 +323,7 @@ enum ssh_scp_request_types {
|
|||||||
SSH_SCP_REQUEST_WARNING
|
SSH_SCP_REQUEST_WARNING
|
||||||
};
|
};
|
||||||
|
|
||||||
|
LIBSSH_API int ssh_blocking_flush(ssh_session session, int timeout);
|
||||||
LIBSSH_API ssh_channel ssh_channel_accept_x11(ssh_channel channel, int timeout_ms);
|
LIBSSH_API ssh_channel ssh_channel_accept_x11(ssh_channel channel, int timeout_ms);
|
||||||
LIBSSH_API int ssh_channel_change_pty_size(ssh_channel channel,int cols,int rows);
|
LIBSSH_API int ssh_channel_change_pty_size(ssh_channel channel,int cols,int rows);
|
||||||
LIBSSH_API int ssh_channel_close(ssh_channel channel);
|
LIBSSH_API int ssh_channel_close(ssh_channel channel);
|
||||||
@@ -356,6 +357,7 @@ LIBSSH_API int ssh_channel_select(ssh_channel *readchans, ssh_channel *writechan
|
|||||||
timeval * timeout);
|
timeval * timeout);
|
||||||
LIBSSH_API void ssh_channel_set_blocking(ssh_channel channel, int blocking);
|
LIBSSH_API void ssh_channel_set_blocking(ssh_channel channel, int blocking);
|
||||||
LIBSSH_API int ssh_channel_write(ssh_channel channel, const void *data, uint32_t len);
|
LIBSSH_API int ssh_channel_write(ssh_channel channel, const void *data, uint32_t len);
|
||||||
|
LIBSSH_API uint32_t ssh_channel_window_size(ssh_channel channel);
|
||||||
|
|
||||||
LIBSSH_API int ssh_try_publickey_from_file(ssh_session session, const char *keyfile,
|
LIBSSH_API int ssh_try_publickey_from_file(ssh_session session, const char *keyfile,
|
||||||
ssh_string *publickey, int *type);
|
ssh_string *publickey, int *type);
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ int ssh_file_readaccess_ok(const char *file);
|
|||||||
char *ssh_path_expand_tilde(const char *d);
|
char *ssh_path_expand_tilde(const char *d);
|
||||||
char *ssh_path_expand_escape(ssh_session session, const char *s);
|
char *ssh_path_expand_escape(ssh_session session, const char *s);
|
||||||
int ssh_analyze_banner(ssh_session session, int server, int *ssh1, int *ssh2);
|
int ssh_analyze_banner(ssh_session session, int server, int *ssh1, int *ssh2);
|
||||||
|
int ssh_is_ipaddr_v4(const char *str);
|
||||||
|
int ssh_is_ipaddr(const char *str);
|
||||||
|
|
||||||
/* macro for byte ordering */
|
/* macro for byte ordering */
|
||||||
uint64_t ntohll(uint64_t);
|
uint64_t ntohll(uint64_t);
|
||||||
@@ -48,9 +50,15 @@ struct ssh_iterator {
|
|||||||
const void *data;
|
const void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ssh_timestamp {
|
||||||
|
long seconds;
|
||||||
|
long useconds;
|
||||||
|
};
|
||||||
|
|
||||||
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);
|
||||||
|
struct ssh_iterator *ssh_list_find(const struct ssh_list *list, void *value);
|
||||||
int ssh_list_append(struct ssh_list *list, const void *data);
|
int ssh_list_append(struct ssh_list *list, const void *data);
|
||||||
int ssh_list_prepend(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);
|
||||||
@@ -70,4 +78,9 @@ const void *_ssh_list_pop_head(struct ssh_list *list);
|
|||||||
#define ssh_list_pop_head(type, ssh_list)\
|
#define ssh_list_pop_head(type, ssh_list)\
|
||||||
((type)_ssh_list_pop_head(ssh_list))
|
((type)_ssh_list_pop_head(ssh_list))
|
||||||
|
|
||||||
|
int ssh_make_milliseconds(long sec, long usec);
|
||||||
|
void ssh_timestamp_init(struct ssh_timestamp *ts);
|
||||||
|
int ssh_timeout_elapsed(struct ssh_timestamp *ts, int timeout);
|
||||||
|
int ssh_timeout_update(struct ssh_timestamp *ts, int timeout);
|
||||||
|
|
||||||
#endif /* MISC_H_ */
|
#endif /* MISC_H_ */
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ struct ssh_keys_struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ssh_message_struct;
|
struct ssh_message_struct;
|
||||||
|
struct ssh_common_struct;
|
||||||
|
|
||||||
/* server data */
|
/* server data */
|
||||||
|
|
||||||
@@ -172,8 +173,6 @@ void ssh_packet_set_callbacks(ssh_session session, ssh_packet_callbacks callback
|
|||||||
void ssh_packet_set_default_callbacks(ssh_session session);
|
void ssh_packet_set_default_callbacks(ssh_session session);
|
||||||
void ssh_packet_process(ssh_session session, uint8_t type);
|
void ssh_packet_process(ssh_session session, uint8_t type);
|
||||||
/* connect.c */
|
/* connect.c */
|
||||||
int ssh_regex_init(void);
|
|
||||||
void ssh_regex_finalize(void);
|
|
||||||
socket_t ssh_connect_host(ssh_session session, const char *host,const char
|
socket_t ssh_connect_host(ssh_session session, const char *host,const char
|
||||||
*bind_addr, int port, long timeout, long usec);
|
*bind_addr, int port, long timeout, long usec);
|
||||||
socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
||||||
@@ -210,6 +209,9 @@ int match_hostname(const char *host, const char *pattern, unsigned int len);
|
|||||||
int message_handle(ssh_session session, void *user, uint8_t type, ssh_buffer packet);
|
int message_handle(ssh_session session, void *user, uint8_t type, ssh_buffer packet);
|
||||||
/* log.c */
|
/* log.c */
|
||||||
|
|
||||||
|
void ssh_log_common(struct ssh_common_struct *common, int verbosity,
|
||||||
|
const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
|
||||||
|
|
||||||
/* misc.c */
|
/* misc.c */
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
int gettimeofday(struct timeval *__p, void *__t);
|
int gettimeofday(struct timeval *__p, void *__t);
|
||||||
@@ -223,16 +225,16 @@ int gettimeofday(struct timeval *__p, void *__t);
|
|||||||
|
|
||||||
#define _enter_function(sess) \
|
#define _enter_function(sess) \
|
||||||
do {\
|
do {\
|
||||||
if((sess)->log_verbosity >= SSH_LOG_FUNCTIONS){ \
|
if((sess)->common.log_verbosity >= SSH_LOG_FUNCTIONS){ \
|
||||||
ssh_log((sess),SSH_LOG_FUNCTIONS,"entering function %s line %d in " __FILE__ , __FUNCTION__,__LINE__);\
|
ssh_log((sess),SSH_LOG_FUNCTIONS,"entering function %s line %d in " __FILE__ , __FUNCTION__,__LINE__);\
|
||||||
(sess)->log_indent++; \
|
(sess)->common.log_indent++; \
|
||||||
} \
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define _leave_function(sess) \
|
#define _leave_function(sess) \
|
||||||
do { \
|
do { \
|
||||||
if((sess)->log_verbosity >= SSH_LOG_FUNCTIONS){ \
|
if((sess)->common.log_verbosity >= SSH_LOG_FUNCTIONS){ \
|
||||||
(sess)->log_indent--; \
|
(sess)->common.log_indent--; \
|
||||||
ssh_log((sess),SSH_LOG_FUNCTIONS,"leaving function %s line %d in " __FILE__ , __FUNCTION__,__LINE__);\
|
ssh_log((sess),SSH_LOG_FUNCTIONS,"leaving function %s line %d in " __FILE__ , __FUNCTION__,__LINE__);\
|
||||||
}\
|
}\
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|||||||
@@ -87,10 +87,63 @@ LIBSSH_API ssh_bind ssh_bind_new(void);
|
|||||||
*
|
*
|
||||||
* @param sshbind The ssh server bind to configure.
|
* @param sshbind The ssh server bind to configure.
|
||||||
*
|
*
|
||||||
* @param type Option to set up.
|
* @param type The option type to set. This could be one of the
|
||||||
* @param value Value to set.
|
* following:
|
||||||
* @returns SSH_OK No error.
|
*
|
||||||
* @returns SSH_ERROR Invalid option or parameter.
|
* - SSH_BIND_OPTIONS_BINDADDR
|
||||||
|
* The ip address to bind (const char *).
|
||||||
|
*
|
||||||
|
* - SSH_BIND_OPTIONS_BINDPORT
|
||||||
|
* The port to bind (unsigned int).
|
||||||
|
*
|
||||||
|
* - SSH_BIND_OPTIONS_BINDPORT_STR
|
||||||
|
* The port to bind (const char *).
|
||||||
|
*
|
||||||
|
* - SSH_BIND_OPTIONS_HOSTKEY
|
||||||
|
* This specifies the file containing the private host key used
|
||||||
|
* by SSHv1. (const char *).
|
||||||
|
*
|
||||||
|
* - SSH_BIND_OPTIONS_DSAKEY
|
||||||
|
* This specifies the file containing the private host dsa key
|
||||||
|
* used by SSHv2. (const char *).
|
||||||
|
*
|
||||||
|
* - SSH_BIND_OPTIONS_RSAKEY
|
||||||
|
* This specifies the file containing the private host dsa key
|
||||||
|
* used by SSHv2. (const char *).
|
||||||
|
*
|
||||||
|
* - SSH_BIND_OPTIONS_BANNER
|
||||||
|
* That the server banner (version string) for SSH.
|
||||||
|
* (const char *).
|
||||||
|
*
|
||||||
|
* - SSH_BIND_OPTIONS_LOG_VERBOSITY
|
||||||
|
* Set the session logging verbosity (int).\n
|
||||||
|
* \n
|
||||||
|
* The verbosity of the messages. Every log smaller or
|
||||||
|
* equal to verbosity will be shown.
|
||||||
|
* - SSH_LOG_NOLOG: No logging
|
||||||
|
* - SSH_LOG_RARE: Rare conditions or warnings
|
||||||
|
* - SSH_LOG_ENTRY: API-accessible entrypoints
|
||||||
|
* - SSH_LOG_PACKET: Packet id and size
|
||||||
|
* - SSH_LOG_FUNCTIONS: Function entering and leaving
|
||||||
|
*
|
||||||
|
* - SSH_BIND_OPTIONS_LOG_VERBOSITY_STR
|
||||||
|
* Set the session logging verbosity (const char *).\n
|
||||||
|
* \n
|
||||||
|
* The verbosity of the messages. Every log smaller or
|
||||||
|
* equal to verbosity will be shown.
|
||||||
|
* - SSH_LOG_NOLOG: No logging
|
||||||
|
* - SSH_LOG_RARE: Rare conditions or warnings
|
||||||
|
* - SSH_LOG_ENTRY: API-accessible entrypoints
|
||||||
|
* - SSH_LOG_PACKET: Packet id and size
|
||||||
|
* - SSH_LOG_FUNCTIONS: Function entering and leaving
|
||||||
|
* \n
|
||||||
|
* See the corresponding numbers in libssh.h.
|
||||||
|
*
|
||||||
|
* @param value The value to set. This is a generic pointer and the
|
||||||
|
* datatype which is used should be set according to the
|
||||||
|
* type set.
|
||||||
|
*
|
||||||
|
* @returns SSH_OK on success, SSH_ERROR on invalid option or parameter.
|
||||||
*/
|
*/
|
||||||
LIBSSH_API int ssh_bind_options_set(ssh_bind sshbind,
|
LIBSSH_API int ssh_bind_options_set(ssh_bind sshbind,
|
||||||
enum ssh_bind_options_e type, const void *value);
|
enum ssh_bind_options_e type, const void *value);
|
||||||
@@ -104,6 +157,26 @@ LIBSSH_API int ssh_bind_options_set(ssh_bind sshbind,
|
|||||||
*/
|
*/
|
||||||
LIBSSH_API int ssh_bind_listen(ssh_bind ssh_bind_o);
|
LIBSSH_API int ssh_bind_listen(ssh_bind ssh_bind_o);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the callback for this bind.
|
||||||
|
*
|
||||||
|
* @param[in] sshbind The bind to set the callback on.
|
||||||
|
*
|
||||||
|
* @param[in] callbacks An already set up ssh_bind_callbacks instance.
|
||||||
|
*
|
||||||
|
* @param[in] userdata A pointer to private data to pass to the callbacks.
|
||||||
|
*
|
||||||
|
* @return SSH_OK on success, SSH_ERROR if an error occured.
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* struct ssh_callbacks_struct cb = {
|
||||||
|
* .userdata = data,
|
||||||
|
* .auth_function = my_auth_function
|
||||||
|
* };
|
||||||
|
* ssh_callbacks_init(&cb);
|
||||||
|
* ssh_bind_set_callbacks(session, &cb);
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
LIBSSH_API int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks,
|
LIBSSH_API int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks,
|
||||||
void *userdata);
|
void *userdata);
|
||||||
|
|
||||||
@@ -230,6 +303,8 @@ LIBSSH_API int ssh_channel_write_stderr(ssh_channel channel,
|
|||||||
|
|
||||||
/* deprecated functions */
|
/* deprecated functions */
|
||||||
SSH_DEPRECATED LIBSSH_API int ssh_accept(ssh_session session);
|
SSH_DEPRECATED LIBSSH_API int ssh_accept(ssh_session session);
|
||||||
|
SSH_DEPRECATED LIBSSH_API int channel_write_stderr(ssh_channel channel,
|
||||||
|
const void *data, uint32_t len);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,8 +61,16 @@ enum ssh_pending_call_e {
|
|||||||
/* libssh calls may block an undefined amount of time */
|
/* libssh calls may block an undefined amount of time */
|
||||||
#define SSH_SESSION_FLAG_BLOCKING 1
|
#define SSH_SESSION_FLAG_BLOCKING 1
|
||||||
|
|
||||||
struct ssh_session_struct {
|
/* members that are common to ssh_session and ssh_bind */
|
||||||
|
struct ssh_common_struct {
|
||||||
struct error_struct error;
|
struct error_struct error;
|
||||||
|
ssh_callbacks callbacks; /* Callbacks to user functions */
|
||||||
|
int log_verbosity; /* verbosity of the log functions */
|
||||||
|
int log_indent; /* indentation level in enter_function logs */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ssh_session_struct {
|
||||||
|
struct ssh_common_struct common;
|
||||||
struct ssh_socket_struct *socket;
|
struct ssh_socket_struct *socket;
|
||||||
char *serverbanner;
|
char *serverbanner;
|
||||||
char *clientbanner;
|
char *clientbanner;
|
||||||
@@ -110,7 +118,7 @@ struct ssh_session_struct {
|
|||||||
struct ssh_crypto_struct *current_crypto;
|
struct ssh_crypto_struct *current_crypto;
|
||||||
struct ssh_crypto_struct *next_crypto; /* next_crypto is going to be used after a SSH2_MSG_NEWKEYS */
|
struct ssh_crypto_struct *next_crypto; /* next_crypto is going to be used after a SSH2_MSG_NEWKEYS */
|
||||||
|
|
||||||
ssh_channel channels; /* linked list of channels */
|
struct ssh_list *channels; /* linked list of channels */
|
||||||
int maxchannel;
|
int maxchannel;
|
||||||
int exec_channel_opened; /* version 1 only. more
|
int exec_channel_opened; /* version 1 only. more
|
||||||
info in channels1.c */
|
info in channels1.c */
|
||||||
@@ -128,11 +136,8 @@ struct ssh_session_struct {
|
|||||||
struct ssh_list *ssh_message_list; /* list of delayed SSH messages */
|
struct ssh_list *ssh_message_list; /* list of delayed SSH messages */
|
||||||
int (*ssh_message_callback)( struct ssh_session_struct *session, ssh_message msg, void *userdata);
|
int (*ssh_message_callback)( struct ssh_session_struct *session, ssh_message msg, void *userdata);
|
||||||
void *ssh_message_callback_data;
|
void *ssh_message_callback_data;
|
||||||
int log_verbosity; /*cached copy of the option structure */
|
|
||||||
int log_indent; /* indentation level in enter_function logs */
|
|
||||||
|
|
||||||
void (*ssh_connection_callback)( struct ssh_session_struct *session);
|
void (*ssh_connection_callback)( struct ssh_session_struct *session);
|
||||||
ssh_callbacks callbacks; /* Callbacks to user functions */
|
|
||||||
struct ssh_packet_callbacks_struct default_packet_callbacks;
|
struct ssh_packet_callbacks_struct default_packet_callbacks;
|
||||||
struct ssh_list *packet_callbacks;
|
struct ssh_list *packet_callbacks;
|
||||||
struct ssh_socket_callbacks_struct socket_callbacks;
|
struct ssh_socket_callbacks_struct socket_callbacks;
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ void ssh_socket_set_write_wontblock(ssh_socket s);
|
|||||||
void ssh_socket_set_read_wontblock(ssh_socket s);
|
void ssh_socket_set_read_wontblock(ssh_socket s);
|
||||||
void ssh_socket_set_except(ssh_socket s);
|
void ssh_socket_set_except(ssh_socket s);
|
||||||
int ssh_socket_get_status(ssh_socket s);
|
int ssh_socket_get_status(ssh_socket s);
|
||||||
|
int ssh_socket_buffered_write_bytes(ssh_socket s);
|
||||||
int ssh_socket_data_available(ssh_socket s);
|
int ssh_socket_data_available(ssh_socket s);
|
||||||
int ssh_socket_data_writable(ssh_socket s);
|
int ssh_socket_data_writable(ssh_socket s);
|
||||||
|
|
||||||
@@ -61,6 +62,7 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r
|
|||||||
struct ssh_poll_handle_struct * ssh_socket_get_poll_handle_in(ssh_socket s);
|
struct ssh_poll_handle_struct * ssh_socket_get_poll_handle_in(ssh_socket s);
|
||||||
struct ssh_poll_handle_struct * ssh_socket_get_poll_handle_out(ssh_socket s);
|
struct ssh_poll_handle_struct * ssh_socket_get_poll_handle_out(ssh_socket s);
|
||||||
|
|
||||||
|
void ssh_socket_set_connecting(ssh_socket s, socket_t fd);
|
||||||
int ssh_socket_connect(ssh_socket s, const char *host, int port, const char *bind_addr);
|
int ssh_socket_connect(ssh_socket s, const char *host, int port, const char *bind_addr);
|
||||||
|
|
||||||
#endif /* SOCKET_H_ */
|
#endif /* SOCKET_H_ */
|
||||||
|
|||||||
5
libssh_threads.pc.cmake
Normal file
5
libssh_threads.pc.cmake
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
Name: ${APPLICATION_NAME}_threads
|
||||||
|
Description: The SSH Library Thread Extension
|
||||||
|
Version: ${APPLICATION_VERSION}
|
||||||
|
Libs: -L${LIB_INSTALL_DIR} -lssh_threads
|
||||||
|
Cflags: -I${INCLUDE_INSTALL_DIR}
|
||||||
@@ -184,6 +184,11 @@ install(
|
|||||||
if (WITH_STATIC_LIB)
|
if (WITH_STATIC_LIB)
|
||||||
add_library(${LIBSSH_STATIC_LIBRARY} STATIC ${libssh_SRCS})
|
add_library(${LIBSSH_STATIC_LIBRARY} STATIC ${libssh_SRCS})
|
||||||
|
|
||||||
|
if (MSVC)
|
||||||
|
set(OUTPUT_SUFFIX static)
|
||||||
|
else (MSVC)
|
||||||
|
set(OUTPUT_SUFFIX )
|
||||||
|
endif (MSVC)
|
||||||
set_target_properties(
|
set_target_properties(
|
||||||
${LIBSSH_STATIC_LIBRARY}
|
${LIBSSH_STATIC_LIBRARY}
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
@@ -193,6 +198,8 @@ if (WITH_STATIC_LIB)
|
|||||||
${LIBRARY_SOVERSION}
|
${LIBRARY_SOVERSION}
|
||||||
OUTPUT_NAME
|
OUTPUT_NAME
|
||||||
ssh
|
ssh
|
||||||
|
ARCHIVE_OUTPUT_DIRECTORY
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_SUFFIX}
|
||||||
)
|
)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
@@ -208,7 +215,7 @@ if (WITH_STATIC_LIB)
|
|||||||
TARGETS
|
TARGETS
|
||||||
${LIBSSH_STATIC_LIBRARY}
|
${LIBSSH_STATIC_LIBRARY}
|
||||||
DESTINATION
|
DESTINATION
|
||||||
${LIB_INSTALL_DIR}
|
${LIB_INSTALL_DIR}/${OUTPUT_SUFFIX}
|
||||||
COMPONENT
|
COMPONENT
|
||||||
libraries
|
libraries
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -438,6 +439,7 @@ ssh_string agent_sign_data(struct ssh_session_struct *session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ssh_string_free(blob);
|
ssh_string_free(blob);
|
||||||
|
blob = NULL;
|
||||||
|
|
||||||
reply = ssh_buffer_new();
|
reply = ssh_buffer_new();
|
||||||
if (reply == NULL) {
|
if (reply == NULL) {
|
||||||
@@ -450,6 +452,7 @@ ssh_string agent_sign_data(struct ssh_session_struct *session,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ssh_buffer_free(request);
|
ssh_buffer_free(request);
|
||||||
|
request = NULL;
|
||||||
|
|
||||||
/* check if reply is valid */
|
/* check if reply is valid */
|
||||||
if (buffer_get_u8(reply, (uint8_t *) &type) != sizeof(uint8_t)) {
|
if (buffer_get_u8(reply, (uint8_t *) &type) != sizeof(uint8_t)) {
|
||||||
|
|||||||
142
src/auth.c
142
src/auth.c
@@ -27,6 +27,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -62,23 +63,28 @@
|
|||||||
* again is necessary
|
* again is necessary
|
||||||
*/
|
*/
|
||||||
static int ask_userauth(ssh_session session) {
|
static int ask_userauth(ssh_session session) {
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
enter_function();
|
enter_function();
|
||||||
do {
|
do {
|
||||||
rc=ssh_service_request(session,"ssh-userauth");
|
rc = ssh_service_request(session,"ssh-userauth");
|
||||||
if(ssh_is_blocking(session)){
|
if (ssh_is_blocking(session)) {
|
||||||
if(rc==SSH_AGAIN)
|
if (rc == SSH_AGAIN) {
|
||||||
ssh_handle_packets(session,-1);
|
int err = ssh_handle_packets(session, -2);
|
||||||
} else {
|
if (err != SSH_OK) {
|
||||||
/* nonblocking */
|
/* error or timeout */
|
||||||
ssh_handle_packets(session,0);
|
return SSH_ERROR;
|
||||||
rc=ssh_service_request(session,"ssh-userauth");
|
}
|
||||||
break;
|
}
|
||||||
}
|
} else {
|
||||||
} while(rc==SSH_AGAIN);
|
/* nonblocking */
|
||||||
leave_function();
|
ssh_handle_packets(session, 0);
|
||||||
return rc;
|
rc = ssh_service_request(session, "ssh-userauth");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (rc == SSH_AGAIN);
|
||||||
|
leave_function();
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -254,7 +260,7 @@ static int wait_auth_status(ssh_session session) {
|
|||||||
enter_function();
|
enter_function();
|
||||||
|
|
||||||
if(ssh_is_blocking(session)){
|
if(ssh_is_blocking(session)){
|
||||||
if(ssh_handle_packets_termination(session,-1,auth_status_termination,
|
if(ssh_handle_packets_termination(session, -2, auth_status_termination,
|
||||||
session) == SSH_ERROR){
|
session) == SSH_ERROR){
|
||||||
leave_function();
|
leave_function();
|
||||||
return SSH_AUTH_ERROR;
|
return SSH_AUTH_ERROR;
|
||||||
@@ -308,8 +314,8 @@ int ssh_auth_list(ssh_session session) {
|
|||||||
/**
|
/**
|
||||||
* @brief retrieves available authentication methods for this session
|
* @brief retrieves available authentication methods for this session
|
||||||
* @param[in] session the SSH session
|
* @param[in] session the SSH session
|
||||||
* @param[in] username set to NULL
|
* @param[in] username Deprecated, set to NULL.
|
||||||
* @returns A bitfield of values SSH_AUTH_METHOD_NONE, SSH_AUTH_METHOD_PASSWORD,
|
* @returns A bitfield of values SSH_AUTH_METHOD_PASSWORD,
|
||||||
SSH_AUTH_METHOD_PUBLICKEY, SSH_AUTH_METHOD_HOSTBASED,
|
SSH_AUTH_METHOD_PUBLICKEY, SSH_AUTH_METHOD_HOSTBASED,
|
||||||
SSH_AUTH_METHOD_INTERACTIVE.
|
SSH_AUTH_METHOD_INTERACTIVE.
|
||||||
@warning Other reserved flags may appear in future versions.
|
@warning Other reserved flags may appear in future versions.
|
||||||
@@ -345,7 +351,7 @@ int ssh_userauth_list(ssh_session session, const char *username) {
|
|||||||
* SSH_AUTH_DENIED: Authentication failed: use another method\n
|
* SSH_AUTH_DENIED: Authentication failed: use another method\n
|
||||||
* SSH_AUTH_PARTIAL: You've been partially authenticated, you still
|
* SSH_AUTH_PARTIAL: You've been partially authenticated, you still
|
||||||
* have to use another method\n
|
* have to use another method\n
|
||||||
* SSH_AUTH_SUCCESS: Authentication success
|
* SSH_AUTH_SUCCESS: Authentication success\n
|
||||||
* SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again
|
* SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again
|
||||||
* later.
|
* later.
|
||||||
*/
|
*/
|
||||||
@@ -384,6 +390,7 @@ int ssh_userauth_none(ssh_session session, const char *username) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (user == NULL) {
|
if (user == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
leave_function();
|
leave_function();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -415,10 +422,12 @@ int ssh_userauth_none(ssh_session session, const char *username) {
|
|||||||
|
|
||||||
method = ssh_string_from_char("none");
|
method = ssh_string_from_char("none");
|
||||||
if (method == NULL) {
|
if (method == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
service = ssh_string_from_char("ssh-connection");
|
service = ssh_string_from_char("ssh-connection");
|
||||||
if (service == NULL) {
|
if (service == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -519,6 +528,7 @@ int ssh_userauth_offer_pubkey(ssh_session session, const char *username,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (user == NULL) {
|
if (user == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
leave_function();
|
leave_function();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -531,14 +541,17 @@ int ssh_userauth_offer_pubkey(ssh_session session, const char *username,
|
|||||||
|
|
||||||
service = ssh_string_from_char("ssh-connection");
|
service = ssh_string_from_char("ssh-connection");
|
||||||
if (service == NULL) {
|
if (service == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
method = ssh_string_from_char("publickey");
|
method = ssh_string_from_char("publickey");
|
||||||
if (method == NULL) {
|
if (method == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
algo = ssh_string_from_char(ssh_type_to_char(type));
|
algo = ssh_string_from_char(ssh_type_to_char(type));
|
||||||
if (algo == NULL) {
|
if (algo == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -549,6 +562,7 @@ int ssh_userauth_offer_pubkey(ssh_session session, const char *username,
|
|||||||
buffer_add_u8(session->out_buffer, 0) < 0 ||
|
buffer_add_u8(session->out_buffer, 0) < 0 ||
|
||||||
buffer_add_ssh_string(session->out_buffer, algo) < 0 ||
|
buffer_add_ssh_string(session->out_buffer, algo) < 0 ||
|
||||||
buffer_add_ssh_string(session->out_buffer, publickey) < 0) {
|
buffer_add_ssh_string(session->out_buffer, publickey) < 0) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,6 +654,7 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (user == NULL) {
|
if (user == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
leave_function();
|
leave_function();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -652,24 +667,32 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
|
|||||||
|
|
||||||
service = ssh_string_from_char("ssh-connection");
|
service = ssh_string_from_char("ssh-connection");
|
||||||
if (service == NULL) {
|
if (service == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
method = ssh_string_from_char("publickey");
|
method = ssh_string_from_char("publickey");
|
||||||
if (method == NULL) {
|
if (method == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
algo = ssh_string_from_char(ssh_type_to_char(privatekey->type));
|
algo = ssh_string_from_char(ssh_type_to_char(privatekey->type));
|
||||||
if (algo == NULL) {
|
if (algo == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (publickey == NULL) {
|
if (publickey == NULL) {
|
||||||
pk = publickey_from_privatekey(privatekey);
|
pk = publickey_from_privatekey(privatekey);
|
||||||
if (pk == NULL) {
|
if (pk == NULL) {
|
||||||
|
/* most likely oom, and publickey_from_privatekey does not
|
||||||
|
* return any more information */
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
pkstr = publickey_to_string(pk);
|
pkstr = publickey_to_string(pk);
|
||||||
publickey_free(pk);
|
publickey_free(pk);
|
||||||
if (pkstr == NULL) {
|
if (pkstr == NULL) {
|
||||||
|
/* same as above */
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -682,6 +705,7 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
|
|||||||
buffer_add_u8(session->out_buffer, 1) < 0 ||
|
buffer_add_u8(session->out_buffer, 1) < 0 ||
|
||||||
buffer_add_ssh_string(session->out_buffer, algo) < 0 ||
|
buffer_add_ssh_string(session->out_buffer, algo) < 0 ||
|
||||||
buffer_add_ssh_string(session->out_buffer, (publickey == NULL ? pkstr : publickey)) < 0) {
|
buffer_add_ssh_string(session->out_buffer, (publickey == NULL ? pkstr : publickey)) < 0) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -694,6 +718,7 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
|
|||||||
sign = ssh_do_sign(session,session->out_buffer, privatekey);
|
sign = ssh_do_sign(session,session->out_buffer, privatekey);
|
||||||
if (sign) {
|
if (sign) {
|
||||||
if (buffer_add_ssh_string(session->out_buffer,sign) < 0) {
|
if (buffer_add_ssh_string(session->out_buffer,sign) < 0) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
ssh_string_free(sign);
|
ssh_string_free(sign);
|
||||||
@@ -737,7 +762,9 @@ error:
|
|||||||
* SSH_AUTH_DENIED: Authentication failed: use another method.\n
|
* SSH_AUTH_DENIED: Authentication failed: use another method.\n
|
||||||
* SSH_AUTH_PARTIAL: You've been partially authenticated, you still
|
* SSH_AUTH_PARTIAL: You've been partially authenticated, you still
|
||||||
* have to use another method.\n
|
* have to use another method.\n
|
||||||
* SSH_AUTH_SUCCESS: Authentication successful.
|
* SSH_AUTH_SUCCESS: Authentication successful.\n
|
||||||
|
* SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again
|
||||||
|
* later.
|
||||||
*
|
*
|
||||||
* @see publickey_from_file()
|
* @see publickey_from_file()
|
||||||
* @see privatekey_from_file()
|
* @see privatekey_from_file()
|
||||||
@@ -756,6 +783,7 @@ int ssh_userauth_privatekey_file(ssh_session session, const char *username,
|
|||||||
|
|
||||||
pubkeyfile = malloc(strlen(filename) + 1 + 4);
|
pubkeyfile = malloc(strlen(filename) + 1 + 4);
|
||||||
if (pubkeyfile == NULL) {
|
if (pubkeyfile == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
leave_function();
|
leave_function();
|
||||||
return SSH_AUTH_ERROR;
|
return SSH_AUTH_ERROR;
|
||||||
}
|
}
|
||||||
@@ -837,6 +865,7 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (user == NULL) {
|
if (user == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
leave_function();
|
leave_function();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -849,18 +878,22 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
|
|||||||
|
|
||||||
service = ssh_string_from_char("ssh-connection");
|
service = ssh_string_from_char("ssh-connection");
|
||||||
if (service == NULL) {
|
if (service == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
method = ssh_string_from_char("publickey");
|
method = ssh_string_from_char("publickey");
|
||||||
if (method == NULL) {
|
if (method == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
algo = ssh_string_from_char(ssh_type_to_char(publickey->type));
|
algo = ssh_string_from_char(ssh_type_to_char(publickey->type));
|
||||||
if (algo == NULL) {
|
if (algo == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
key = publickey_to_string(publickey);
|
key = publickey_to_string(publickey);
|
||||||
if (key == NULL) {
|
if (key == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -872,6 +905,7 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
|
|||||||
buffer_add_u8(session->out_buffer, 1) < 0 ||
|
buffer_add_u8(session->out_buffer, 1) < 0 ||
|
||||||
buffer_add_ssh_string(session->out_buffer, algo) < 0 ||
|
buffer_add_ssh_string(session->out_buffer, algo) < 0 ||
|
||||||
buffer_add_ssh_string(session->out_buffer, key) < 0) {
|
buffer_add_ssh_string(session->out_buffer, key) < 0) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -879,6 +913,7 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
|
|||||||
|
|
||||||
if (sign) {
|
if (sign) {
|
||||||
if (buffer_add_ssh_string(session->out_buffer, sign) < 0) {
|
if (buffer_add_ssh_string(session->out_buffer, sign) < 0) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
ssh_string_free(sign);
|
ssh_string_free(sign);
|
||||||
@@ -929,7 +964,7 @@ error:
|
|||||||
* SSH_AUTH_DENIED: Authentication failed: use another method.\n
|
* SSH_AUTH_DENIED: Authentication failed: use another method.\n
|
||||||
* SSH_AUTH_PARTIAL: You've been partially authenticated, you still
|
* SSH_AUTH_PARTIAL: You've been partially authenticated, you still
|
||||||
* have to use another method.\n
|
* have to use another method.\n
|
||||||
* SSH_AUTH_SUCCESS: Authentication successful.
|
* SSH_AUTH_SUCCESS: Authentication successful.\n
|
||||||
* SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again
|
* SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again
|
||||||
* later.
|
* later.
|
||||||
*
|
*
|
||||||
@@ -968,6 +1003,7 @@ int ssh_userauth_password(ssh_session session, const char *username,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (user == NULL) {
|
if (user == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
leave_function();
|
leave_function();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -1000,14 +1036,17 @@ int ssh_userauth_password(ssh_session session, const char *username,
|
|||||||
|
|
||||||
service = ssh_string_from_char("ssh-connection");
|
service = ssh_string_from_char("ssh-connection");
|
||||||
if (service == NULL) {
|
if (service == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
method = ssh_string_from_char("password");
|
method = ssh_string_from_char("password");
|
||||||
if (method == NULL) {
|
if (method == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
pwd = ssh_string_from_char(password);
|
pwd = ssh_string_from_char(password);
|
||||||
if (pwd == NULL) {
|
if (pwd == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1017,6 +1056,7 @@ int ssh_userauth_password(ssh_session session, const char *username,
|
|||||||
buffer_add_ssh_string(session->out_buffer, method) < 0 ||
|
buffer_add_ssh_string(session->out_buffer, method) < 0 ||
|
||||||
buffer_add_u8(session->out_buffer, 0) < 0 ||
|
buffer_add_u8(session->out_buffer, 0) < 0 ||
|
||||||
buffer_add_ssh_string(session->out_buffer, pwd) < 0) {
|
buffer_add_ssh_string(session->out_buffer, pwd) < 0) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1374,18 +1414,22 @@ static int kbdauth_init(ssh_session session, const char *user,
|
|||||||
|
|
||||||
usr = ssh_string_from_char(user);
|
usr = ssh_string_from_char(user);
|
||||||
if (usr == NULL) {
|
if (usr == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
sub = (submethods ? ssh_string_from_char(submethods) : ssh_string_from_char(""));
|
sub = (submethods ? ssh_string_from_char(submethods) : ssh_string_from_char(""));
|
||||||
if (sub == NULL) {
|
if (sub == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
service = ssh_string_from_char("ssh-connection");
|
service = ssh_string_from_char("ssh-connection");
|
||||||
if (service == NULL) {
|
if (service == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
method = ssh_string_from_char("keyboard-interactive");
|
method = ssh_string_from_char("keyboard-interactive");
|
||||||
if (method == NULL) {
|
if (method == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1395,6 +1439,7 @@ static int kbdauth_init(ssh_session session, const char *user,
|
|||||||
buffer_add_ssh_string(session->out_buffer, method) < 0 ||
|
buffer_add_ssh_string(session->out_buffer, method) < 0 ||
|
||||||
buffer_add_u32(session->out_buffer, 0) < 0 ||
|
buffer_add_u32(session->out_buffer, 0) < 0 ||
|
||||||
buffer_add_ssh_string(session->out_buffer, sub) < 0) {
|
buffer_add_ssh_string(session->out_buffer, sub) < 0) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1562,23 +1607,30 @@ static int kbdauth_send(ssh_session session) {
|
|||||||
|
|
||||||
enter_function();
|
enter_function();
|
||||||
|
|
||||||
|
if(session==NULL || session->kbdint == NULL) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
if (buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_INFO_RESPONSE) < 0 ||
|
if (buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_INFO_RESPONSE) < 0 ||
|
||||||
buffer_add_u32(session->out_buffer,
|
buffer_add_u32(session->out_buffer,
|
||||||
htonl(session->kbdint->nprompts)) < 0) {
|
htonl(session->kbdint->nprompts)) < 0) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < session->kbdint->nprompts; i++) {
|
for (i = 0; i < session->kbdint->nprompts; i++) {
|
||||||
if (session->kbdint->answers[i]) {
|
if (session->kbdint->answers && session->kbdint->answers[i]) {
|
||||||
answer = ssh_string_from_char(session->kbdint->answers[i]);
|
answer = ssh_string_from_char(session->kbdint->answers[i]);
|
||||||
} else {
|
} else {
|
||||||
answer = ssh_string_from_char("");
|
answer = ssh_string_from_char("");
|
||||||
}
|
}
|
||||||
if (answer == NULL) {
|
if (answer == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer_add_ssh_string(session->out_buffer, answer) < 0) {
|
if (buffer_add_ssh_string(session->out_buffer, answer) < 0) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1622,7 +1674,9 @@ error:
|
|||||||
* have to use another method\n
|
* have to use another method\n
|
||||||
* SSH_AUTH_SUCCESS: Authentication success\n
|
* SSH_AUTH_SUCCESS: Authentication success\n
|
||||||
* SSH_AUTH_INFO: The server asked some questions. Use
|
* SSH_AUTH_INFO: The server asked some questions. Use
|
||||||
* ssh_userauth_kbdint_getnprompts() and such.
|
* ssh_userauth_kbdint_getnprompts() and such.\n
|
||||||
|
* SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again
|
||||||
|
* later.
|
||||||
*
|
*
|
||||||
* @see ssh_userauth_kbdint_getnprompts()
|
* @see ssh_userauth_kbdint_getnprompts()
|
||||||
* @see ssh_userauth_kbdint_getname()
|
* @see ssh_userauth_kbdint_getname()
|
||||||
@@ -1635,7 +1689,7 @@ int ssh_userauth_kbdint(ssh_session session, const char *user,
|
|||||||
int rc = SSH_AUTH_ERROR;
|
int rc = SSH_AUTH_ERROR;
|
||||||
|
|
||||||
if (session->version == 1) {
|
if (session->version == 1) {
|
||||||
/* No keyb-interactive for ssh1 */
|
ssh_set_error(session, SSH_NO_ERROR, "No keyboard-interactive for ssh1");
|
||||||
return SSH_AUTH_DENIED;
|
return SSH_AUTH_DENIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1688,8 +1742,12 @@ int ssh_userauth_kbdint(ssh_session session, const char *user,
|
|||||||
* @returns The number of prompts.
|
* @returns The number of prompts.
|
||||||
*/
|
*/
|
||||||
int ssh_userauth_kbdint_getnprompts(ssh_session session) {
|
int ssh_userauth_kbdint_getnprompts(ssh_session session) {
|
||||||
if(session==NULL || session->kbdint == NULL)
|
if(session==NULL)
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
|
if(session->kbdint == NULL) {
|
||||||
|
ssh_set_error_invalid(session, __FUNCTION__);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
return session->kbdint->nprompts;
|
return session->kbdint->nprompts;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1704,8 +1762,12 @@ int ssh_userauth_kbdint_getnprompts(ssh_session session) {
|
|||||||
* @returns The name of the message block. Do not free it.
|
* @returns The name of the message block. Do not free it.
|
||||||
*/
|
*/
|
||||||
const char *ssh_userauth_kbdint_getname(ssh_session session) {
|
const char *ssh_userauth_kbdint_getname(ssh_session session) {
|
||||||
if(session==NULL || session->kbdint == NULL)
|
if(session==NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
if(session->kbdint == NULL) {
|
||||||
|
ssh_set_error_invalid(session, __FUNCTION__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
return session->kbdint->name;
|
return session->kbdint->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1721,8 +1783,12 @@ const char *ssh_userauth_kbdint_getname(ssh_session session) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const char *ssh_userauth_kbdint_getinstruction(ssh_session session) {
|
const char *ssh_userauth_kbdint_getinstruction(ssh_session session) {
|
||||||
if(session==NULL || session->kbdint == NULL)
|
if(session==NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
if(session->kbdint == NULL) {
|
||||||
|
ssh_set_error_invalid(session, __FUNCTION__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
return session->kbdint->instruction;
|
return session->kbdint->instruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1744,9 +1810,14 @@ const char *ssh_userauth_kbdint_getinstruction(ssh_session session) {
|
|||||||
*/
|
*/
|
||||||
const char *ssh_userauth_kbdint_getprompt(ssh_session session, unsigned int i,
|
const char *ssh_userauth_kbdint_getprompt(ssh_session session, unsigned int i,
|
||||||
char *echo) {
|
char *echo) {
|
||||||
if(session==NULL || session->kbdint == NULL)
|
if(session==NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (i > session->kbdint->nprompts) {
|
if(session->kbdint == NULL) {
|
||||||
|
ssh_set_error_invalid(session, __FUNCTION__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (i > session->kbdint->nprompts) {
|
||||||
|
ssh_set_error_invalid(session, __FUNCTION__);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1773,14 +1844,18 @@ const char *ssh_userauth_kbdint_getprompt(ssh_session session, unsigned int i,
|
|||||||
*/
|
*/
|
||||||
int ssh_userauth_kbdint_setanswer(ssh_session session, unsigned int i,
|
int ssh_userauth_kbdint_setanswer(ssh_session session, unsigned int i,
|
||||||
const char *answer) {
|
const char *answer) {
|
||||||
if (session == NULL || answer == NULL || session->kbdint == NULL ||
|
if (session == NULL)
|
||||||
|
return -1;
|
||||||
|
if (answer == NULL || session->kbdint == NULL ||
|
||||||
i > session->kbdint->nprompts) {
|
i > session->kbdint->nprompts) {
|
||||||
|
ssh_set_error_invalid(session, __FUNCTION__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session->kbdint->answers == NULL) {
|
if (session->kbdint->answers == NULL) {
|
||||||
session->kbdint->answers = malloc(sizeof(char*) * session->kbdint->nprompts);
|
session->kbdint->answers = malloc(sizeof(char*) * session->kbdint->nprompts);
|
||||||
if (session->kbdint->answers == NULL) {
|
if (session->kbdint->answers == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memset(session->kbdint->answers, 0, sizeof(char *) * session->kbdint->nprompts);
|
memset(session->kbdint->answers, 0, sizeof(char *) * session->kbdint->nprompts);
|
||||||
@@ -1793,6 +1868,7 @@ int ssh_userauth_kbdint_setanswer(ssh_session session, unsigned int i,
|
|||||||
|
|
||||||
session->kbdint->answers[i] = strdup(answer);
|
session->kbdint->answers[i] = strdup(answer);
|
||||||
if (session->kbdint->answers[i] == NULL) {
|
if (session->kbdint->answers[i] == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ static int wait_auth1_status(ssh_session session) {
|
|||||||
enter_function();
|
enter_function();
|
||||||
/* wait for a packet */
|
/* wait for a packet */
|
||||||
while(session->auth_state == SSH_AUTH_STATE_NONE)
|
while(session->auth_state == SSH_AUTH_STATE_NONE)
|
||||||
if (ssh_handle_packets(session,-1) != SSH_OK)
|
if (ssh_handle_packets(session, -2) != SSH_OK)
|
||||||
break;
|
break;
|
||||||
ssh_log(session,SSH_LOG_PROTOCOL,"Auth state : %d",session->auth_state);
|
ssh_log(session,SSH_LOG_PROTOCOL,"Auth state : %d",session->auth_state);
|
||||||
leave_function();
|
leave_function();
|
||||||
@@ -108,6 +108,7 @@ static int send_username(ssh_session session, const char *username) {
|
|||||||
if(wait_auth1_status(session) == SSH_AUTH_SUCCESS){
|
if(wait_auth1_status(session) == SSH_AUTH_SUCCESS){
|
||||||
session->auth_service_state=SSH_AUTH_SERVICE_USER_SENT;
|
session->auth_service_state=SSH_AUTH_SERVICE_USER_SENT;
|
||||||
session->auth_state=SSH_AUTH_STATE_SUCCESS;
|
session->auth_state=SSH_AUTH_STATE_SUCCESS;
|
||||||
|
ssh_set_error(session, SSH_NO_ERROR, "Authentication successful");
|
||||||
return SSH_AUTH_SUCCESS;
|
return SSH_AUTH_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
session->auth_service_state=SSH_AUTH_SERVICE_USER_SENT;
|
session->auth_service_state=SSH_AUTH_SERVICE_USER_SENT;
|
||||||
|
|||||||
34
src/bind.c
34
src/bind.c
@@ -150,7 +150,7 @@ ssh_bind ssh_bind_new(void) {
|
|||||||
ZERO_STRUCTP(ptr);
|
ZERO_STRUCTP(ptr);
|
||||||
ptr->bindfd = SSH_INVALID_SOCKET;
|
ptr->bindfd = SSH_INVALID_SOCKET;
|
||||||
ptr->bindport= 22;
|
ptr->bindport= 22;
|
||||||
ptr->log_verbosity = 0;
|
ptr->common.log_verbosity = 0;
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
@@ -160,6 +160,7 @@ int ssh_bind_listen(ssh_bind sshbind) {
|
|||||||
socket_t fd;
|
socket_t fd;
|
||||||
|
|
||||||
if (ssh_init() < 0) {
|
if (ssh_init() < 0) {
|
||||||
|
ssh_set_error(sshbind, SSH_FATAL, "ssh_init() failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,28 +186,13 @@ int ssh_bind_listen(ssh_bind sshbind) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief set the bind callbacks for ssh_bind
|
|
||||||
* @code
|
|
||||||
* struct ssh_callbacks_struct cb = {
|
|
||||||
* .userdata = data,
|
|
||||||
* .auth_function = my_auth_function
|
|
||||||
* };
|
|
||||||
* ssh_callbacks_init(&cb);
|
|
||||||
* ssh_set_callbacks(session, &cb);
|
|
||||||
* @endcode
|
|
||||||
* @param sshbind the ssh_bind structure to set
|
|
||||||
* @param callbacks a ssh_bind_callbacks instance already set up. Do
|
|
||||||
* use ssh_callbacks_init() to initialize it.
|
|
||||||
* @param userdata userdata to be used with each callback called
|
|
||||||
* within callbacks.
|
|
||||||
* @returns SSH_OK on success,
|
|
||||||
* SSH_ERROR on error.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks,
|
int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks,
|
||||||
void *userdata){
|
void *userdata){
|
||||||
if (sshbind == NULL || callbacks == NULL) {
|
if (sshbind == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
if (callbacks == NULL) {
|
||||||
|
ssh_set_error_invalid(sshbind, __FUNCTION__);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
if(callbacks->size <= 0 || callbacks->size > 1024 * sizeof(void *)){
|
if(callbacks->size <= 0 || callbacks->size > 1024 * sizeof(void *)){
|
||||||
@@ -373,11 +359,13 @@ int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
session->log_verbosity = sshbind->log_verbosity;
|
session->common.log_verbosity = sshbind->common.log_verbosity;
|
||||||
|
|
||||||
ssh_socket_free(session->socket);
|
ssh_socket_free(session->socket);
|
||||||
session->socket = ssh_socket_new(session);
|
session->socket = ssh_socket_new(session);
|
||||||
if (session->socket == NULL) {
|
if (session->socket == NULL) {
|
||||||
|
/* perhaps it may be better to copy the error from session to sshbind */
|
||||||
|
ssh_set_error_oom(sshbind);
|
||||||
privatekey_free(dsa);
|
privatekey_free(dsa);
|
||||||
privatekey_free(rsa);
|
privatekey_free(rsa);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
@@ -387,7 +375,7 @@ int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
|
|||||||
session->dsa_key = dsa;
|
session->dsa_key = dsa;
|
||||||
session->rsa_key = rsa;
|
session->rsa_key = rsa;
|
||||||
|
|
||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
34
src/buffer.c
34
src/buffer.c
@@ -21,10 +21,12 @@
|
|||||||
* MA 02111-1307, USA.
|
* MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -109,13 +111,18 @@ void ssh_buffer_free(struct ssh_buffer_struct *buffer) {
|
|||||||
SAFE_FREE(buffer);
|
SAFE_FREE(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int realloc_buffer(struct ssh_buffer_struct *buffer, int needed) {
|
static int realloc_buffer(struct ssh_buffer_struct *buffer, size_t needed) {
|
||||||
int smallest = 1;
|
size_t smallest = 1;
|
||||||
char *new = NULL;
|
char *new;
|
||||||
|
|
||||||
buffer_verify(buffer);
|
buffer_verify(buffer);
|
||||||
|
|
||||||
/* Find the smallest power of two which is greater or equal to needed */
|
/* Find the smallest power of two which is greater or equal to needed */
|
||||||
while(smallest <= needed) {
|
while(smallest <= needed) {
|
||||||
smallest <<= 1;
|
if (smallest == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
smallest <<= 1;
|
||||||
}
|
}
|
||||||
needed = smallest;
|
needed = smallest;
|
||||||
new = realloc(buffer->data, needed);
|
new = realloc(buffer->data, needed);
|
||||||
@@ -180,6 +187,10 @@ int buffer_reinit(struct ssh_buffer_struct *buffer) {
|
|||||||
*/
|
*/
|
||||||
int buffer_add_data(struct ssh_buffer_struct *buffer, const void *data, uint32_t len) {
|
int buffer_add_data(struct ssh_buffer_struct *buffer, const void *data, uint32_t len) {
|
||||||
buffer_verify(buffer);
|
buffer_verify(buffer);
|
||||||
|
|
||||||
|
if (buffer->used + len < len)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (buffer->allocated < (buffer->used + len)) {
|
if (buffer->allocated < (buffer->used + len)) {
|
||||||
if(buffer->pos > 0)
|
if(buffer->pos > 0)
|
||||||
buffer_shift(buffer);
|
buffer_shift(buffer);
|
||||||
@@ -318,6 +329,8 @@ int buffer_prepend_data(struct ssh_buffer_struct *buffer, const void *data,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* pos isn't high enough */
|
/* pos isn't high enough */
|
||||||
|
if (buffer->used - buffer->pos + len < len)
|
||||||
|
return -1;
|
||||||
if (buffer->allocated < (buffer->used - buffer->pos + len)) {
|
if (buffer->allocated < (buffer->used - buffer->pos + len)) {
|
||||||
if (realloc_buffer(buffer, buffer->used - buffer->pos + len) < 0) {
|
if (realloc_buffer(buffer, buffer->used - buffer->pos + len) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -429,7 +442,7 @@ uint32_t buffer_get_rest_len(struct ssh_buffer_struct *buffer){
|
|||||||
*/
|
*/
|
||||||
uint32_t buffer_pass_bytes(struct ssh_buffer_struct *buffer, uint32_t len){
|
uint32_t buffer_pass_bytes(struct ssh_buffer_struct *buffer, uint32_t len){
|
||||||
buffer_verify(buffer);
|
buffer_verify(buffer);
|
||||||
if(buffer->used < buffer->pos+len)
|
if (buffer->pos + len < len || buffer->used < buffer->pos + len)
|
||||||
return 0;
|
return 0;
|
||||||
buffer->pos+=len;
|
buffer->pos+=len;
|
||||||
/* if the buffer is empty after having passed the whole bytes into it, we can clean it */
|
/* if the buffer is empty after having passed the whole bytes into it, we can clean it */
|
||||||
@@ -454,8 +467,11 @@ uint32_t buffer_pass_bytes(struct ssh_buffer_struct *buffer, uint32_t len){
|
|||||||
*/
|
*/
|
||||||
uint32_t buffer_pass_bytes_end(struct ssh_buffer_struct *buffer, uint32_t len){
|
uint32_t buffer_pass_bytes_end(struct ssh_buffer_struct *buffer, uint32_t len){
|
||||||
buffer_verify(buffer);
|
buffer_verify(buffer);
|
||||||
if(buffer->used < buffer->pos + len)
|
|
||||||
return 0;
|
if (buffer->used < len) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
buffer->used-=len;
|
buffer->used-=len;
|
||||||
buffer_verify(buffer);
|
buffer_verify(buffer);
|
||||||
return len;
|
return len;
|
||||||
@@ -548,7 +564,7 @@ struct ssh_string_struct *buffer_get_ssh_string(struct ssh_buffer_struct *buffer
|
|||||||
}
|
}
|
||||||
hostlen = ntohl(stringlen);
|
hostlen = ntohl(stringlen);
|
||||||
/* verify if there is enough space in buffer to get it */
|
/* verify if there is enough space in buffer to get it */
|
||||||
if ((buffer->pos + hostlen) > buffer->used) {
|
if (buffer->pos + hostlen < hostlen || buffer->pos + hostlen > buffer->used) {
|
||||||
return NULL; /* it is indeed */
|
return NULL; /* it is indeed */
|
||||||
}
|
}
|
||||||
str = ssh_string_new(hostlen);
|
str = ssh_string_new(hostlen);
|
||||||
@@ -585,7 +601,7 @@ struct ssh_string_struct *buffer_get_mpint(struct ssh_buffer_struct *buffer) {
|
|||||||
}
|
}
|
||||||
bits = ntohs(bits);
|
bits = ntohs(bits);
|
||||||
len = (bits + 7) / 8;
|
len = (bits + 7) / 8;
|
||||||
if ((buffer->pos + len) > buffer->used) {
|
if (buffer->pos + len < len || buffer->pos + len > buffer->used) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
str = ssh_string_new(len);
|
str = ssh_string_new(len);
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ int ssh_set_callbacks(ssh_session session, ssh_callbacks cb) {
|
|||||||
leave_function();
|
leave_function();
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
session->callbacks = cb;
|
session->common.callbacks = cb;
|
||||||
leave_function();
|
leave_function();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
407
src/channels.c
407
src/channels.c
File diff suppressed because it is too large
Load Diff
@@ -36,6 +36,7 @@
|
|||||||
#include "libssh/packet.h"
|
#include "libssh/packet.h"
|
||||||
#include "libssh/channels.h"
|
#include "libssh/channels.h"
|
||||||
#include "libssh/session.h"
|
#include "libssh/session.h"
|
||||||
|
#include "libssh/misc.h"
|
||||||
|
|
||||||
#ifdef WITH_SSH1
|
#ifdef WITH_SSH1
|
||||||
|
|
||||||
@@ -49,11 +50,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int channel_open_session1(ssh_channel chan) {
|
int channel_open_session1(ssh_channel chan) {
|
||||||
|
ssh_session session;
|
||||||
|
|
||||||
|
if (chan == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
session = chan->session;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We guess we are requesting an *exec* channel. It can only have one exec
|
* We guess we are requesting an *exec* channel. It can only have one exec
|
||||||
* channel. So we abort with an error if we need more than one.
|
* channel. So we abort with an error if we need more than one.
|
||||||
*/
|
*/
|
||||||
ssh_session session = chan->session;
|
|
||||||
if (session->exec_channel_opened) {
|
if (session->exec_channel_opened) {
|
||||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||||
"SSH1 supports only one execution channel. "
|
"SSH1 supports only one execution channel. "
|
||||||
@@ -61,6 +68,7 @@ int channel_open_session1(ssh_channel chan) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
session->exec_channel_opened = 1;
|
session->exec_channel_opened = 1;
|
||||||
|
chan->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED;
|
||||||
chan->state = SSH_CHANNEL_STATE_OPEN;
|
chan->state = SSH_CHANNEL_STATE_OPEN;
|
||||||
chan->local_maxpacket = 32000;
|
chan->local_maxpacket = 32000;
|
||||||
chan->local_window = 64000;
|
chan->local_window = 64000;
|
||||||
@@ -83,8 +91,14 @@ int channel_open_session1(ssh_channel chan) {
|
|||||||
|
|
||||||
int channel_request_pty_size1(ssh_channel channel, const char *terminal, int col,
|
int channel_request_pty_size1(ssh_channel channel, const char *terminal, int col,
|
||||||
int row) {
|
int row) {
|
||||||
ssh_session session = channel->session;
|
ssh_session session;
|
||||||
ssh_string str = NULL;
|
ssh_string str = NULL;
|
||||||
|
|
||||||
|
if (channel == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
session = channel->session;
|
||||||
|
|
||||||
if(channel->request_state != SSH_CHANNEL_REQ_STATE_NONE){
|
if(channel->request_state != SSH_CHANNEL_REQ_STATE_NONE){
|
||||||
ssh_set_error(session,SSH_REQUEST_DENIED,"Wrong request state");
|
ssh_set_error(session,SSH_REQUEST_DENIED,"Wrong request state");
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
@@ -137,7 +151,13 @@ int channel_request_pty_size1(ssh_channel channel, const char *terminal, int col
|
|||||||
}
|
}
|
||||||
|
|
||||||
int channel_change_pty_size1(ssh_channel channel, int cols, int rows) {
|
int channel_change_pty_size1(ssh_channel channel, int cols, int rows) {
|
||||||
ssh_session session = channel->session;
|
ssh_session session;
|
||||||
|
|
||||||
|
if (channel == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
session = channel->session;
|
||||||
|
|
||||||
if(channel->request_state != SSH_CHANNEL_REQ_STATE_NONE){
|
if(channel->request_state != SSH_CHANNEL_REQ_STATE_NONE){
|
||||||
ssh_set_error(session,SSH_REQUEST_DENIED,"Wrong request state");
|
ssh_set_error(session,SSH_REQUEST_DENIED,"Wrong request state");
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
@@ -180,7 +200,12 @@ int channel_change_pty_size1(ssh_channel channel, int cols, int rows) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int channel_request_shell1(ssh_channel channel) {
|
int channel_request_shell1(ssh_channel channel) {
|
||||||
ssh_session session = channel->session;
|
ssh_session session;
|
||||||
|
|
||||||
|
if (channel == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
session = channel->session;
|
||||||
|
|
||||||
if (buffer_add_u8(session->out_buffer,SSH_CMSG_EXEC_SHELL) < 0) {
|
if (buffer_add_u8(session->out_buffer,SSH_CMSG_EXEC_SHELL) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -196,9 +221,14 @@ int channel_request_shell1(ssh_channel channel) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int channel_request_exec1(ssh_channel channel, const char *cmd) {
|
int channel_request_exec1(ssh_channel channel, const char *cmd) {
|
||||||
ssh_session session = channel->session;
|
ssh_session session;
|
||||||
ssh_string command = NULL;
|
ssh_string command = NULL;
|
||||||
|
|
||||||
|
if (channel == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
session = channel->session;
|
||||||
|
|
||||||
command = ssh_string_from_char(cmd);
|
command = ssh_string_from_char(cmd);
|
||||||
if (command == NULL) {
|
if (command == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -221,10 +251,15 @@ int channel_request_exec1(ssh_channel channel, const char *cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SSH_PACKET_CALLBACK(ssh_packet_data1){
|
SSH_PACKET_CALLBACK(ssh_packet_data1){
|
||||||
ssh_channel channel = session->channels;
|
ssh_channel channel = ssh_get_channel1(session);
|
||||||
ssh_string str = NULL;
|
ssh_string str = NULL;
|
||||||
int is_stderr=(type==SSH_SMSG_STDOUT_DATA ? 0 : 1);
|
int is_stderr=(type==SSH_SMSG_STDOUT_DATA ? 0 : 1);
|
||||||
(void)user;
|
(void)user;
|
||||||
|
|
||||||
|
if (channel == NULL) {
|
||||||
|
return SSH_PACKET_NOT_USED;
|
||||||
|
}
|
||||||
|
|
||||||
str = buffer_get_ssh_string(packet);
|
str = buffer_get_ssh_string(packet);
|
||||||
if (str == NULL) {
|
if (str == NULL) {
|
||||||
ssh_log(session, SSH_LOG_FUNCTIONS, "Invalid data packet !\n");
|
ssh_log(session, SSH_LOG_FUNCTIONS, "Invalid data packet !\n");
|
||||||
@@ -232,7 +267,7 @@ SSH_PACKET_CALLBACK(ssh_packet_data1){
|
|||||||
}
|
}
|
||||||
|
|
||||||
ssh_log(session, SSH_LOG_PROTOCOL,
|
ssh_log(session, SSH_LOG_PROTOCOL,
|
||||||
"Adding %zu bytes data in %d",
|
"Adding %" PRIdS " bytes data in %d",
|
||||||
ssh_string_len(str), is_stderr);
|
ssh_string_len(str), is_stderr);
|
||||||
|
|
||||||
if (channel_default_bufferize(channel, ssh_string_data(str), ssh_string_len(str),
|
if (channel_default_bufferize(channel, ssh_string_data(str), ssh_string_len(str),
|
||||||
@@ -246,10 +281,16 @@ SSH_PACKET_CALLBACK(ssh_packet_data1){
|
|||||||
}
|
}
|
||||||
|
|
||||||
SSH_PACKET_CALLBACK(ssh_packet_close1){
|
SSH_PACKET_CALLBACK(ssh_packet_close1){
|
||||||
ssh_channel channel = session->channels;
|
ssh_channel channel = ssh_get_channel1(session);
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
|
|
||||||
(void)type;
|
(void)type;
|
||||||
(void)user;
|
(void)user;
|
||||||
|
|
||||||
|
if (channel == NULL) {
|
||||||
|
return SSH_PACKET_NOT_USED;
|
||||||
|
}
|
||||||
|
|
||||||
buffer_get_u32(packet, &status);
|
buffer_get_u32(packet, &status);
|
||||||
/*
|
/*
|
||||||
* It's much more than a channel closing. spec says it's the last
|
* It's much more than a channel closing. spec says it's the last
|
||||||
@@ -266,12 +307,36 @@ SSH_PACKET_CALLBACK(ssh_packet_close1){
|
|||||||
return SSH_PACKET_USED;
|
return SSH_PACKET_USED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SSH_PACKET_CALLBACK(ssh_packet_exist_status1){
|
||||||
|
ssh_channel channel = ssh_get_channel1(session);
|
||||||
|
uint32_t status;
|
||||||
|
(void)type;
|
||||||
|
(void)user;
|
||||||
|
|
||||||
|
if (channel == NULL) {
|
||||||
|
return SSH_PACKET_NOT_USED;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_get_u32(packet, &status);
|
||||||
|
channel->state = SSH_CHANNEL_STATE_CLOSED;
|
||||||
|
channel->remote_eof = 1;
|
||||||
|
channel->exit_status = ntohl(status);
|
||||||
|
|
||||||
|
return SSH_PACKET_USED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int channel_write1(ssh_channel channel, const void *data, int len) {
|
int channel_write1(ssh_channel channel, const void *data, int len) {
|
||||||
ssh_session session = channel->session;
|
ssh_session session;
|
||||||
int origlen = len;
|
int origlen = len;
|
||||||
int effectivelen;
|
int effectivelen;
|
||||||
const unsigned char *ptr=data;
|
const unsigned char *ptr=data;
|
||||||
|
|
||||||
|
if (channel == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
session = channel->session;
|
||||||
|
|
||||||
while (len > 0) {
|
while (len > 0) {
|
||||||
if (buffer_add_u8(session->out_buffer, SSH_CMSG_STDIN_DATA) < 0) {
|
if (buffer_add_u8(session->out_buffer, SSH_CMSG_STDIN_DATA) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -295,5 +360,20 @@ int channel_write1(ssh_channel channel, const void *data, int len) {
|
|||||||
return origlen;
|
return origlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssh_channel ssh_get_channel1(ssh_session session){
|
||||||
|
struct ssh_iterator *it;
|
||||||
|
|
||||||
|
if (session == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* With SSH1, the channel is always the first one */
|
||||||
|
if(session->channels != NULL){
|
||||||
|
it = ssh_list_get_iterator(session->channels);
|
||||||
|
if(it)
|
||||||
|
return ssh_iterator_value(ssh_channel, it);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
#endif /* WITH_SSH1 */
|
#endif /* WITH_SSH1 */
|
||||||
/* vim: set ts=2 sw=2 et cindent: */
|
/* vim: set ts=2 sw=2 et cindent: */
|
||||||
|
|||||||
38
src/client.c
38
src/client.c
@@ -26,6 +26,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -40,8 +41,8 @@
|
|||||||
#include "libssh/misc.h"
|
#include "libssh/misc.h"
|
||||||
|
|
||||||
#define set_status(session, status) do {\
|
#define set_status(session, status) do {\
|
||||||
if (session->callbacks && session->callbacks->connect_status_function) \
|
if (session->common.callbacks && session->common.callbacks->connect_status_function) \
|
||||||
session->callbacks->connect_status_function(session->callbacks->userdata, status); \
|
session->common.callbacks->connect_status_function(session->common.callbacks->userdata, status); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -664,7 +665,7 @@ int ssh_connect(ssh_session session) {
|
|||||||
session->socket_callbacks.exception=ssh_socket_exception_callback;
|
session->socket_callbacks.exception=ssh_socket_exception_callback;
|
||||||
session->socket_callbacks.userdata=session;
|
session->socket_callbacks.userdata=session;
|
||||||
if (session->fd != SSH_INVALID_SOCKET) {
|
if (session->fd != SSH_INVALID_SOCKET) {
|
||||||
ssh_socket_set_fd(session->socket, session->fd);
|
ssh_socket_set_connecting(session->socket, session->fd);
|
||||||
ret=SSH_OK;
|
ret=SSH_OK;
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
} else if (session->ProxyCommand != NULL){
|
} else if (session->ProxyCommand != NULL){
|
||||||
@@ -673,8 +674,6 @@ int ssh_connect(ssh_session session) {
|
|||||||
} else {
|
} else {
|
||||||
ret=ssh_socket_connect(session->socket, session->host, session->port,
|
ret=ssh_socket_connect(session->socket, session->host, session->port,
|
||||||
session->bindaddr);
|
session->bindaddr);
|
||||||
|
|
||||||
/*, session->timeout * 1000 + session->timeout_usec); */
|
|
||||||
}
|
}
|
||||||
if (ret == SSH_ERROR) {
|
if (ret == SSH_ERROR) {
|
||||||
leave_function();
|
leave_function();
|
||||||
@@ -686,11 +685,21 @@ int ssh_connect(ssh_session session) {
|
|||||||
session->alive = 1;
|
session->alive = 1;
|
||||||
ssh_log(session,SSH_LOG_PROTOCOL,"Socket connecting, now waiting for the callbacks to work");
|
ssh_log(session,SSH_LOG_PROTOCOL,"Socket connecting, now waiting for the callbacks to work");
|
||||||
pending:
|
pending:
|
||||||
session->pending_call_state=SSH_PENDING_CALL_CONNECT;
|
session->pending_call_state=SSH_PENDING_CALL_CONNECT;
|
||||||
if(ssh_is_blocking(session))
|
if(ssh_is_blocking(session)) {
|
||||||
ssh_handle_packets_termination(session,-1,ssh_connect_termination,session);
|
int timeout = (session->timeout * 1000) + (session->timeout_usec / 1000);
|
||||||
|
if (timeout == 0) {
|
||||||
|
timeout = 10 * 1000;
|
||||||
|
}
|
||||||
|
ssh_log(session,SSH_LOG_PACKET,"ssh_connect: Actual timeout : %d", timeout);
|
||||||
|
ssh_handle_packets_termination(session, timeout, ssh_connect_termination, session);
|
||||||
|
if(!ssh_connect_termination(session)){
|
||||||
|
ssh_set_error(session,SSH_FATAL,"Timeout connecting to %s",session->host);
|
||||||
|
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ssh_handle_packets_termination(session,0,ssh_connect_termination, session);
|
ssh_handle_packets_termination(session, 0, ssh_connect_termination, session);
|
||||||
ssh_log(session,SSH_LOG_PACKET,"ssh_connect: Actual state : %d",session->session_state);
|
ssh_log(session,SSH_LOG_PACKET,"ssh_connect: Actual state : %d",session->session_state);
|
||||||
if(!ssh_is_blocking(session) && !ssh_connect_termination(session)){
|
if(!ssh_is_blocking(session) && !ssh_connect_termination(session)){
|
||||||
leave_function();
|
leave_function();
|
||||||
@@ -747,6 +756,7 @@ int ssh_get_openssh_version(ssh_session session) {
|
|||||||
*/
|
*/
|
||||||
void ssh_disconnect(ssh_session session) {
|
void ssh_disconnect(ssh_session session) {
|
||||||
ssh_string str = NULL;
|
ssh_string str = NULL;
|
||||||
|
struct ssh_iterator *it;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (session == NULL) {
|
if (session == NULL) {
|
||||||
@@ -755,7 +765,7 @@ void ssh_disconnect(ssh_session session) {
|
|||||||
|
|
||||||
enter_function();
|
enter_function();
|
||||||
|
|
||||||
if (ssh_socket_is_open(session->socket)) {
|
if (session->socket != NULL && ssh_socket_is_open(session->socket)) {
|
||||||
if (buffer_add_u8(session->out_buffer, SSH2_MSG_DISCONNECT) < 0) {
|
if (buffer_add_u8(session->out_buffer, SSH2_MSG_DISCONNECT) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -780,13 +790,15 @@ void ssh_disconnect(ssh_session session) {
|
|||||||
}
|
}
|
||||||
error:
|
error:
|
||||||
session->alive = 0;
|
session->alive = 0;
|
||||||
if(session->socket){
|
if (session->socket != NULL){
|
||||||
ssh_socket_reset(session->socket);
|
ssh_socket_reset(session->socket);
|
||||||
}
|
}
|
||||||
session->fd = SSH_INVALID_SOCKET;
|
session->fd = SSH_INVALID_SOCKET;
|
||||||
session->session_state=SSH_SESSION_STATE_DISCONNECTED;
|
session->session_state=SSH_SESSION_STATE_DISCONNECTED;
|
||||||
while (session->channels) {
|
|
||||||
ssh_channel_free(session->channels);
|
while ((it=ssh_list_get_iterator(session->channels)) != NULL) {
|
||||||
|
ssh_channel_free(ssh_iterator_value(ssh_channel,it));
|
||||||
|
ssh_list_remove(session->channels, it);
|
||||||
}
|
}
|
||||||
if(session->current_crypto){
|
if(session->current_crypto){
|
||||||
crypto_free(session->current_crypto);
|
crypto_free(session->current_crypto);
|
||||||
|
|||||||
49
src/config.c
49
src/config.c
@@ -78,7 +78,7 @@ static enum ssh_config_opcode_e ssh_config_get_opcode(char *keyword) {
|
|||||||
return SOC_UNSUPPORTED;
|
return SOC_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *ssh_config_get_token(char **str) {
|
static char *ssh_config_get_cmd(char **str) {
|
||||||
register char *c;
|
register char *c;
|
||||||
char *r;
|
char *r;
|
||||||
|
|
||||||
@@ -98,6 +98,25 @@ static char *ssh_config_get_token(char **str) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (r = c; *c; c++) {
|
||||||
|
if (*c == '\n') {
|
||||||
|
*c = '\0';
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
*str = c + 1;
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *ssh_config_get_token(char **str) {
|
||||||
|
register char *c;
|
||||||
|
char *r;
|
||||||
|
|
||||||
|
c = ssh_config_get_cmd(str);
|
||||||
|
|
||||||
for (r = c; *c; c++) {
|
for (r = c; *c; c++) {
|
||||||
if (isblank(*c)) {
|
if (isblank(*c)) {
|
||||||
*c = '\0';
|
*c = '\0';
|
||||||
@@ -127,7 +146,7 @@ static int ssh_config_get_int(char **str, int notfound) {
|
|||||||
return notfound;
|
return notfound;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *ssh_config_get_str(char **str, const char *def) {
|
static const char *ssh_config_get_str_tok(char **str, const char *def) {
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
p = ssh_config_get_token(str);
|
p = ssh_config_get_token(str);
|
||||||
@@ -141,7 +160,7 @@ static const char *ssh_config_get_str(char **str, const char *def) {
|
|||||||
static int ssh_config_get_yesno(char **str, int notfound) {
|
static int ssh_config_get_yesno(char **str, int notfound) {
|
||||||
const char *p;
|
const char *p;
|
||||||
|
|
||||||
p = ssh_config_get_str(str, NULL);
|
p = ssh_config_get_str_tok(str, NULL);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
return notfound;
|
return notfound;
|
||||||
}
|
}
|
||||||
@@ -192,8 +211,8 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
|||||||
case SOC_HOST:
|
case SOC_HOST:
|
||||||
*parsing = 0;
|
*parsing = 0;
|
||||||
lowerhost = (session->host) ? ssh_lowercase(session->host) : NULL;
|
lowerhost = (session->host) ? ssh_lowercase(session->host) : NULL;
|
||||||
for (p = ssh_config_get_str(&s, NULL); p && *p;
|
for (p = ssh_config_get_str_tok(&s, NULL); p && *p;
|
||||||
p = ssh_config_get_str(&s, NULL)) {
|
p = ssh_config_get_str_tok(&s, NULL)) {
|
||||||
if (match_hostname(lowerhost, p, strlen(p))) {
|
if (match_hostname(lowerhost, p, strlen(p))) {
|
||||||
*parsing = 1;
|
*parsing = 1;
|
||||||
}
|
}
|
||||||
@@ -201,14 +220,14 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
|||||||
SAFE_FREE(lowerhost);
|
SAFE_FREE(lowerhost);
|
||||||
break;
|
break;
|
||||||
case SOC_HOSTNAME:
|
case SOC_HOSTNAME:
|
||||||
p = ssh_config_get_str(&s, NULL);
|
p = ssh_config_get_str_tok(&s, NULL);
|
||||||
if (p && *parsing) {
|
if (p && *parsing) {
|
||||||
ssh_options_set(session, SSH_OPTIONS_HOST, p);
|
ssh_options_set(session, SSH_OPTIONS_HOST, p);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SOC_PORT:
|
case SOC_PORT:
|
||||||
if (session->port == 22) {
|
if (session->port == 22) {
|
||||||
p = ssh_config_get_str(&s, NULL);
|
p = ssh_config_get_str_tok(&s, NULL);
|
||||||
if (p && *parsing) {
|
if (p && *parsing) {
|
||||||
ssh_options_set(session, SSH_OPTIONS_PORT_STR, p);
|
ssh_options_set(session, SSH_OPTIONS_PORT_STR, p);
|
||||||
}
|
}
|
||||||
@@ -216,20 +235,20 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
|||||||
break;
|
break;
|
||||||
case SOC_USERNAME:
|
case SOC_USERNAME:
|
||||||
if (session->username == NULL) {
|
if (session->username == NULL) {
|
||||||
p = ssh_config_get_str(&s, NULL);
|
p = ssh_config_get_str_tok(&s, NULL);
|
||||||
if (p && *parsing) {
|
if (p && *parsing) {
|
||||||
ssh_options_set(session, SSH_OPTIONS_USER, p);
|
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_tok(&s, NULL);
|
||||||
if (p && *parsing) {
|
if (p && *parsing) {
|
||||||
ssh_options_set(session, SSH_OPTIONS_ADD_IDENTITY, p);
|
ssh_options_set(session, SSH_OPTIONS_ADD_IDENTITY, p);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SOC_CIPHERS:
|
case SOC_CIPHERS:
|
||||||
p = ssh_config_get_str(&s, NULL);
|
p = ssh_config_get_str_tok(&s, NULL);
|
||||||
if (p && *parsing) {
|
if (p && *parsing) {
|
||||||
ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, p);
|
ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, p);
|
||||||
ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, p);
|
ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, p);
|
||||||
@@ -246,7 +265,7 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SOC_PROTOCOL:
|
case SOC_PROTOCOL:
|
||||||
p = ssh_config_get_str(&s, NULL);
|
p = ssh_config_get_str_tok(&s, NULL);
|
||||||
if (p && *parsing) {
|
if (p && *parsing) {
|
||||||
char *a, *b;
|
char *a, *b;
|
||||||
b = strdup(p);
|
b = strdup(p);
|
||||||
@@ -289,13 +308,13 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SOC_KNOWNHOSTS:
|
case SOC_KNOWNHOSTS:
|
||||||
p = ssh_config_get_str(&s, NULL);
|
p = ssh_config_get_str_tok(&s, NULL);
|
||||||
if (p && *parsing) {
|
if (p && *parsing) {
|
||||||
ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, p);
|
ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, p);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SOC_PROXYCOMMAND:
|
case SOC_PROXYCOMMAND:
|
||||||
p = ssh_config_get_str(&s, NULL);
|
p = ssh_config_get_cmd(&s);
|
||||||
if (p && *parsing) {
|
if (p && *parsing) {
|
||||||
ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, p);
|
ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, p);
|
||||||
}
|
}
|
||||||
@@ -327,9 +346,7 @@ int ssh_config_parse_file(ssh_session session, const char *filename) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session->log_verbosity) {
|
ssh_log(session, SSH_LOG_RARE, "Reading configuration data from %s", filename);
|
||||||
fprintf(stderr, "Reading configuration data from %s\n", filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
parsing = 1;
|
parsing = 1;
|
||||||
while (fgets(line, sizeof(line), f)) {
|
while (fgets(line, sizeof(line), f)) {
|
||||||
|
|||||||
@@ -21,12 +21,17 @@
|
|||||||
* MA 02111-1307, USA.
|
* MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "libssh/libssh.h"
|
||||||
|
#include "libssh/misc.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
/*
|
/*
|
||||||
* Only use Windows API functions available on Windows 2000 SP4 or later.
|
* Only use Windows API functions available on Windows 2000 SP4 or later.
|
||||||
@@ -78,14 +83,6 @@
|
|||||||
#error "Your system must have getaddrinfo()"
|
#error "Your system must have getaddrinfo()"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_REGCOMP
|
|
||||||
/* don't declare gnu extended regexp's */
|
|
||||||
#ifndef _POSIX_C_SOURCE
|
|
||||||
#define _POSIX_C_SOURCE
|
|
||||||
#endif
|
|
||||||
#include <regex.h>
|
|
||||||
#endif /* HAVE_REGCOMP */
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
void ssh_sock_set_nonblocking(socket_t sock) {
|
void ssh_sock_set_nonblocking(socket_t sock) {
|
||||||
u_long nonblocking = 1;
|
u_long nonblocking = 1;
|
||||||
@@ -118,53 +115,6 @@ void ssh_sock_set_blocking(socket_t sock) {
|
|||||||
|
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
#ifdef HAVE_REGCOMP
|
|
||||||
#define IPEXPR "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
|
|
||||||
|
|
||||||
static regex_t *ip_regex = NULL;
|
|
||||||
|
|
||||||
/** @internal
|
|
||||||
* @brief initializes and compile the regexp to be used for IP matching
|
|
||||||
* @returns -1 on error (and error message is set)
|
|
||||||
* @returns 0 on success
|
|
||||||
*/
|
|
||||||
int ssh_regex_init(){
|
|
||||||
if(ip_regex==NULL){
|
|
||||||
int err;
|
|
||||||
regex_t *regex=malloc(sizeof (regex_t));
|
|
||||||
ZERO_STRUCTP(regex);
|
|
||||||
err = regcomp(regex, IPEXPR, REG_EXTENDED | REG_NOSUB);
|
|
||||||
if(err != 0){
|
|
||||||
char buffer[128];
|
|
||||||
regerror(err,regex,buffer,sizeof(buffer));
|
|
||||||
fprintf(stderr,"Error while compiling regular expression : %s\n",buffer);
|
|
||||||
SAFE_FREE(regex);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ip_regex=regex;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @internal
|
|
||||||
* @brief clean up the IP regexp
|
|
||||||
*/
|
|
||||||
void ssh_regex_finalize(){
|
|
||||||
if(ip_regex){
|
|
||||||
regfree(ip_regex);
|
|
||||||
SAFE_FREE(ip_regex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* HAVE_REGCOMP */
|
|
||||||
int ssh_regex_init(){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
void ssh_regex_finalize(){
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static int ssh_connect_socket_close(socket_t s){
|
static int ssh_connect_socket_close(socket_t s){
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return closesocket(s);
|
return closesocket(s);
|
||||||
@@ -194,13 +144,13 @@ static int getai(ssh_session session, const char *host, int port, struct addrinf
|
|||||||
hints.ai_flags=AI_NUMERICSERV;
|
hints.ai_flags=AI_NUMERICSERV;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef HAVE_REGCOMP
|
|
||||||
if(regexec(ip_regex,host,0,NULL,0) == 0){
|
if (ssh_is_ipaddr(host)) {
|
||||||
/* this is an IP address */
|
/* this is an IP address */
|
||||||
ssh_log(session,SSH_LOG_PACKET,"host %s matches an IP address",host);
|
ssh_log(session,SSH_LOG_PACKET,"host %s matches an IP address",host);
|
||||||
hints.ai_flags |= AI_NUMERICHOST;
|
hints.ai_flags |= AI_NUMERICHOST;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return getaddrinfo(host, service, &hints, ai);
|
return getaddrinfo(host, service, &hints, ai);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,7 +159,7 @@ static int ssh_connect_ai_timeout(ssh_session session, const char *host,
|
|||||||
int timeout_ms;
|
int timeout_ms;
|
||||||
ssh_pollfd_t fds;
|
ssh_pollfd_t fds;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
unsigned int len = sizeof(rc);
|
socklen_t len = sizeof(rc);
|
||||||
|
|
||||||
enter_function();
|
enter_function();
|
||||||
|
|
||||||
@@ -472,7 +422,7 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
|||||||
*
|
*
|
||||||
* @param[in] timeout A timeout for the select.
|
* @param[in] timeout A timeout for the select.
|
||||||
*
|
*
|
||||||
* @return -1 if an error occured. E_INTR if it was interrupted, in
|
* @return -1 if an error occured. SSH_EINTR if it was interrupted, in
|
||||||
* that case, just restart it.
|
* that case, just restart it.
|
||||||
*
|
*
|
||||||
* @warning libssh is not threadsafe here. That means that if a signal is caught
|
* @warning libssh is not threadsafe here. That means that if a signal is caught
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
13
src/dh.c
13
src/dh.c
@@ -44,8 +44,10 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -140,6 +142,7 @@ int ssh_crypto_init(void) {
|
|||||||
}
|
}
|
||||||
bignum_bin2bn(p_value, P_LEN, p);
|
bignum_bin2bn(p_value, P_LEN, p);
|
||||||
OpenSSL_add_all_algorithms();
|
OpenSSL_add_all_algorithms();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ssh_crypto_initialized = 1;
|
ssh_crypto_initialized = 1;
|
||||||
@@ -154,8 +157,13 @@ void ssh_crypto_finalize(void) {
|
|||||||
g = NULL;
|
g = NULL;
|
||||||
bignum_free(p);
|
bignum_free(p);
|
||||||
p = NULL;
|
p = NULL;
|
||||||
|
#ifdef HAVE_LIBGCRYPT
|
||||||
|
gcry_control(GCRYCTL_TERM_SECMEM);
|
||||||
|
#elif defined HAVE_LIBCRYPTO
|
||||||
|
EVP_cleanup();
|
||||||
|
CRYPTO_cleanup_all_ex_data();
|
||||||
|
#endif
|
||||||
ssh_crypto_initialized=0;
|
ssh_crypto_initialized=0;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,6 +195,9 @@ char *ssh_get_hexa(const unsigned char *what, size_t len) {
|
|||||||
char *hexa = NULL;
|
char *hexa = NULL;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
|
if (len > (UINT_MAX - 1) / 3)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
hexa = malloc(len * 3 + 1);
|
hexa = malloc(len * 3 + 1);
|
||||||
if (hexa == NULL) {
|
if (hexa == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include "libssh/priv.h"
|
#include "libssh/priv.h"
|
||||||
|
#include "libssh/session.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup libssh_error The SSH error functions.
|
* @defgroup libssh_error The SSH error functions.
|
||||||
@@ -48,13 +49,13 @@
|
|||||||
* @param ... The arguments for the format string.
|
* @param ... The arguments for the format string.
|
||||||
*/
|
*/
|
||||||
void ssh_set_error(void *error, int code, const char *descr, ...) {
|
void ssh_set_error(void *error, int code, const char *descr, ...) {
|
||||||
struct error_struct *err = error;
|
struct ssh_common_struct *err = error;
|
||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, descr);
|
va_start(va, descr);
|
||||||
vsnprintf(err->error_buffer, ERROR_BUFFERLEN, descr, va);
|
vsnprintf(err->error.error_buffer, ERROR_BUFFERLEN, descr, va);
|
||||||
va_end(va);
|
va_end(va);
|
||||||
err->error_code = code;
|
err->error.error_code = code;
|
||||||
ssh_log(error,SSH_LOG_RARE,"Error : %s",err->error_buffer);
|
ssh_log_common(err,SSH_LOG_RARE,"Error : %s",err->error.error_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ static int ssh_gets(const char *prompt, char *buf, size_t len, int verify) {
|
|||||||
}
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
if (fgets(tmp, len, stdin) == NULL) {
|
if (fgets(tmp, len, stdin) == NULL) {
|
||||||
|
free(tmp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ static ssh_buffer gzip_decompress(ssh_session session, ssh_buffer source, size_t
|
|||||||
do {
|
do {
|
||||||
zin->avail_out = BLOCKSIZE;
|
zin->avail_out = BLOCKSIZE;
|
||||||
status = inflate(zin, Z_PARTIAL_FLUSH);
|
status = inflate(zin, Z_PARTIAL_FLUSH);
|
||||||
if (status != Z_OK) {
|
if (status != Z_OK && status != Z_BUF_ERROR) {
|
||||||
ssh_set_error(session, SSH_FATAL,
|
ssh_set_error(session, SSH_FATAL,
|
||||||
"status %d inflating zlib packet", status);
|
"status %d inflating zlib packet", status);
|
||||||
ssh_buffer_free(dest);
|
ssh_buffer_free(dest);
|
||||||
|
|||||||
16
src/init.c
16
src/init.c
@@ -57,8 +57,6 @@ int ssh_init(void) {
|
|||||||
return -1;
|
return -1;
|
||||||
if(ssh_socket_init())
|
if(ssh_socket_init())
|
||||||
return -1;
|
return -1;
|
||||||
if(ssh_regex_init())
|
|
||||||
return -1;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,18 +71,12 @@ int ssh_init(void) {
|
|||||||
@returns 0 otherwise
|
@returns 0 otherwise
|
||||||
*/
|
*/
|
||||||
int ssh_finalize(void) {
|
int ssh_finalize(void) {
|
||||||
ssh_threads_finalize();
|
|
||||||
ssh_regex_finalize();
|
|
||||||
ssh_crypto_finalize();
|
ssh_crypto_finalize();
|
||||||
ssh_socket_cleanup();
|
ssh_socket_cleanup();
|
||||||
#ifdef HAVE_LIBGCRYPT
|
/* It is important to finalize threading after CRYPTO because
|
||||||
gcry_control(GCRYCTL_TERM_SECMEM);
|
* it still depends on it */
|
||||||
#elif defined HAVE_LIBCRYPTO
|
ssh_threads_finalize();
|
||||||
EVP_cleanup();
|
|
||||||
#endif
|
|
||||||
#ifdef _WIN32
|
|
||||||
WSACleanup();
|
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -432,6 +432,7 @@ int ssh_send_kex(ssh_session session, int server_kex) {
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
ssh_string_free(str);
|
ssh_string_free(str);
|
||||||
|
str = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer_add_u8(session->out_buffer, 0) < 0) {
|
if (buffer_add_u8(session->out_buffer, 0) < 0) {
|
||||||
@@ -761,7 +762,7 @@ SSH_PACKET_CALLBACK(ssh_packet_publickey1){
|
|||||||
}
|
}
|
||||||
|
|
||||||
bits = ssh_string_len(enc_session) * 8 - 7;
|
bits = ssh_string_len(enc_session) * 8 - 7;
|
||||||
ssh_log(session, SSH_LOG_PROTOCOL, "%d bits, %zu bytes encrypted session",
|
ssh_log(session, SSH_LOG_PROTOCOL, "%d bits, %" PRIdS " bytes encrypted session",
|
||||||
bits, ssh_string_len(enc_session));
|
bits, ssh_string_len(enc_session));
|
||||||
bits = htons(bits);
|
bits = htons(bits);
|
||||||
/* the encrypted mpint */
|
/* the encrypted mpint */
|
||||||
@@ -814,14 +815,14 @@ int ssh_get_kex1(ssh_session session) {
|
|||||||
ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_PUBLIC_KEY");
|
ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_PUBLIC_KEY");
|
||||||
/* Here the callback is called */
|
/* Here the callback is called */
|
||||||
while(session->session_state==SSH_SESSION_STATE_INITIAL_KEX){
|
while(session->session_state==SSH_SESSION_STATE_INITIAL_KEX){
|
||||||
ssh_handle_packets(session,-1);
|
ssh_handle_packets(session, -2);
|
||||||
}
|
}
|
||||||
if(session->session_state==SSH_SESSION_STATE_ERROR)
|
if(session->session_state==SSH_SESSION_STATE_ERROR)
|
||||||
goto error;
|
goto error;
|
||||||
ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_SUCCESS");
|
ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_SUCCESS");
|
||||||
/* Waiting for SSH_SMSG_SUCCESS */
|
/* Waiting for SSH_SMSG_SUCCESS */
|
||||||
while(session->session_state==SSH_SESSION_STATE_KEXINIT_RECEIVED){
|
while(session->session_state==SSH_SESSION_STATE_KEXINIT_RECEIVED){
|
||||||
ssh_handle_packets(session,-1);
|
ssh_handle_packets(session, -2);
|
||||||
}
|
}
|
||||||
if(session->session_state==SSH_SESSION_STATE_ERROR)
|
if(session->session_state==SSH_SESSION_STATE_ERROR)
|
||||||
goto error;
|
goto error;
|
||||||
|
|||||||
@@ -610,9 +610,9 @@ static int pem_get_password(char *buf, int size, int rwflag, void *userdata) {
|
|||||||
ssh_log(session, SSH_LOG_RARE,
|
ssh_log(session, SSH_LOG_RARE,
|
||||||
"Trying to call external authentication function");
|
"Trying to call external authentication function");
|
||||||
|
|
||||||
if (session && session->callbacks && session->callbacks->auth_function) {
|
if (session && session->common.callbacks && session->common.callbacks->auth_function) {
|
||||||
if (session->callbacks->auth_function("Passphrase for private key:", buf, size, 0, 0,
|
if (session->common.callbacks->auth_function("Passphrase for private key:", buf, size, 0, 0,
|
||||||
session->callbacks->userdata) < 0) {
|
session->common.callbacks->userdata) < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -677,11 +677,15 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
|
|||||||
#elif defined HAVE_LIBCRYPTO
|
#elif defined HAVE_LIBCRYPTO
|
||||||
DSA *dsa = NULL;
|
DSA *dsa = NULL;
|
||||||
RSA *rsa = NULL;
|
RSA *rsa = NULL;
|
||||||
|
BIO *bio = NULL;
|
||||||
#endif
|
#endif
|
||||||
/* TODO Implement to read both DSA and RSA at once. */
|
/* TODO Implement to read both DSA and RSA at once. */
|
||||||
|
|
||||||
/* needed for openssl initialization */
|
/* needed for openssl initialization */
|
||||||
ssh_init();
|
if (ssh_init() < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ssh_log(session, SSH_LOG_RARE, "Trying to open %s", filename);
|
ssh_log(session, SSH_LOG_RARE, "Trying to open %s", filename);
|
||||||
file = fopen(filename,"r");
|
file = fopen(filename,"r");
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
@@ -690,9 +694,18 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBCRYPTO
|
||||||
|
bio = BIO_new_file(filename,"r");
|
||||||
|
if (bio == NULL) {
|
||||||
|
fclose(file);
|
||||||
|
ssh_set_error(session, SSH_FATAL, "Could not create BIO.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
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->common.callbacks && session->common.callbacks->auth_function ? "true" : "false");
|
||||||
|
|
||||||
if (type == 0) {
|
if (type == 0) {
|
||||||
type = privatekey_type_from_file(file);
|
type = privatekey_type_from_file(file);
|
||||||
@@ -706,9 +719,9 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
|
|||||||
case SSH_KEYTYPE_DSS:
|
case SSH_KEYTYPE_DSS:
|
||||||
if (passphrase == NULL) {
|
if (passphrase == NULL) {
|
||||||
#ifdef HAVE_LIBGCRYPT
|
#ifdef HAVE_LIBGCRYPT
|
||||||
if (session->callbacks && session->callbacks->auth_function) {
|
if (session->common.callbacks && session->common.callbacks->auth_function) {
|
||||||
auth_cb = session->callbacks->auth_function;
|
auth_cb = session->common.callbacks->auth_function;
|
||||||
auth_ud = session->callbacks->userdata;
|
auth_ud = session->common.callbacks->userdata;
|
||||||
|
|
||||||
valid = read_dsa_privatekey(file, &dsa, auth_cb, auth_ud,
|
valid = read_dsa_privatekey(file, &dsa, auth_cb, auth_ud,
|
||||||
"Passphrase for private key:");
|
"Passphrase for private key:");
|
||||||
@@ -725,16 +738,17 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
|
|||||||
if (!valid) {
|
if (!valid) {
|
||||||
ssh_set_error(session, SSH_FATAL, "Parsing private key %s", filename);
|
ssh_set_error(session, SSH_FATAL, "Parsing private key %s", filename);
|
||||||
#elif defined HAVE_LIBCRYPTO
|
#elif defined HAVE_LIBCRYPTO
|
||||||
if (session->callbacks && session->callbacks->auth_function) {
|
if (session->common.callbacks && session->common.callbacks->auth_function) {
|
||||||
dsa = PEM_read_DSAPrivateKey(file, NULL, pem_get_password, session);
|
dsa = PEM_read_bio_DSAPrivateKey(bio, NULL, pem_get_password, session);
|
||||||
} else { /* authcb */
|
} else { /* authcb */
|
||||||
/* openssl uses its own callback to get the passphrase here */
|
/* openssl uses its own callback to get the passphrase here */
|
||||||
dsa = PEM_read_DSAPrivateKey(file, NULL, NULL, NULL);
|
dsa = PEM_read_bio_DSAPrivateKey(bio, NULL, NULL, NULL);
|
||||||
} /* authcb */
|
} /* authcb */
|
||||||
} else { /* passphrase */
|
} else { /* passphrase */
|
||||||
dsa = PEM_read_DSAPrivateKey(file, NULL, NULL, (void *) passphrase);
|
dsa = PEM_read_bio_DSAPrivateKey(bio, NULL, NULL, (void *) passphrase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BIO_free(bio);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
if (dsa == NULL) {
|
if (dsa == NULL) {
|
||||||
ssh_set_error(session, SSH_FATAL,
|
ssh_set_error(session, SSH_FATAL,
|
||||||
@@ -747,9 +761,9 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
|
|||||||
case SSH_KEYTYPE_RSA:
|
case SSH_KEYTYPE_RSA:
|
||||||
if (passphrase == NULL) {
|
if (passphrase == NULL) {
|
||||||
#ifdef HAVE_LIBGCRYPT
|
#ifdef HAVE_LIBGCRYPT
|
||||||
if (session->callbacks && session->callbacks->auth_function) {
|
if (session->common.callbacks && session->common.callbacks->auth_function) {
|
||||||
auth_cb = session->callbacks->auth_function;
|
auth_cb = session->common.callbacks->auth_function;
|
||||||
auth_ud = session->callbacks->userdata;
|
auth_ud = session->common.callbacks->userdata;
|
||||||
valid = read_rsa_privatekey(file, &rsa, auth_cb, auth_ud,
|
valid = read_rsa_privatekey(file, &rsa, auth_cb, auth_ud,
|
||||||
"Passphrase for private key:");
|
"Passphrase for private key:");
|
||||||
} else { /* authcb */
|
} else { /* authcb */
|
||||||
@@ -765,16 +779,17 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
|
|||||||
if (!valid) {
|
if (!valid) {
|
||||||
ssh_set_error(session,SSH_FATAL, "Parsing private key %s", filename);
|
ssh_set_error(session,SSH_FATAL, "Parsing private key %s", filename);
|
||||||
#elif defined HAVE_LIBCRYPTO
|
#elif defined HAVE_LIBCRYPTO
|
||||||
if (session->callbacks && session->callbacks->auth_function) {
|
if (session->common.callbacks && session->common.callbacks->auth_function) {
|
||||||
rsa = PEM_read_RSAPrivateKey(file, NULL, pem_get_password, session);
|
rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, pem_get_password, session);
|
||||||
} else { /* authcb */
|
} else { /* authcb */
|
||||||
/* openssl uses its own callback to get the passphrase here */
|
/* openssl uses its own callback to get the passphrase here */
|
||||||
rsa = PEM_read_RSAPrivateKey(file, NULL, NULL, NULL);
|
rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
|
||||||
} /* authcb */
|
} /* authcb */
|
||||||
} else { /* passphrase */
|
} else { /* passphrase */
|
||||||
rsa = PEM_read_RSAPrivateKey(file, NULL, NULL, (void *) passphrase);
|
rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, (void *) passphrase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BIO_free(bio);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
||||||
if (rsa == NULL) {
|
if (rsa == NULL) {
|
||||||
@@ -786,6 +801,9 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
#ifdef HAVE_LIBCRYPTO
|
||||||
|
BIO_free(bio);
|
||||||
|
#endif
|
||||||
fclose(file);
|
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;
|
||||||
@@ -828,22 +846,31 @@ enum ssh_keytypes_e ssh_privatekey_type(ssh_private_key privatekey){
|
|||||||
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) {
|
||||||
ssh_private_key privkey = NULL;
|
ssh_private_key privkey = NULL;
|
||||||
FILE *file = NULL;
|
|
||||||
#ifdef HAVE_LIBGCRYPT
|
#ifdef HAVE_LIBGCRYPT
|
||||||
|
FILE *file = NULL;
|
||||||
gcry_sexp_t dsa = NULL;
|
gcry_sexp_t dsa = NULL;
|
||||||
gcry_sexp_t rsa = NULL;
|
gcry_sexp_t rsa = NULL;
|
||||||
int valid;
|
int valid;
|
||||||
#elif defined HAVE_LIBCRYPTO
|
#elif defined HAVE_LIBCRYPTO
|
||||||
DSA *dsa = NULL;
|
DSA *dsa = NULL;
|
||||||
RSA *rsa = NULL;
|
RSA *rsa = NULL;
|
||||||
|
BIO *bio = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBGCRYPT
|
||||||
file = fopen(filename,"r");
|
file = fopen(filename,"r");
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||||
"Error opening %s: %s", filename, strerror(errno));
|
"Error opening %s: %s", filename, strerror(errno));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#elif defined HAVE_LIBCRYPTO
|
||||||
|
bio = BIO_new_file(filename,"r");
|
||||||
|
if (bio == NULL) {
|
||||||
|
ssh_set_error(session, SSH_FATAL, "Could not create BIO.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SSH_KEYTYPE_DSS:
|
case SSH_KEYTYPE_DSS:
|
||||||
@@ -855,14 +882,16 @@ ssh_private_key _privatekey_from_file(void *session, const char *filename,
|
|||||||
if (!valid) {
|
if (!valid) {
|
||||||
ssh_set_error(session, SSH_FATAL, "Parsing private key %s", filename);
|
ssh_set_error(session, SSH_FATAL, "Parsing private key %s", filename);
|
||||||
#elif defined HAVE_LIBCRYPTO
|
#elif defined HAVE_LIBCRYPTO
|
||||||
dsa = PEM_read_DSAPrivateKey(file, NULL, NULL, NULL);
|
dsa = PEM_read_bio_DSAPrivateKey(bio, NULL, NULL, NULL);
|
||||||
|
|
||||||
fclose(file);
|
BIO_free(bio);
|
||||||
|
|
||||||
if (dsa == NULL) {
|
if (dsa == NULL) {
|
||||||
ssh_set_error(session, SSH_FATAL,
|
ssh_set_error(session, SSH_FATAL,
|
||||||
"Parsing private key %s: %s",
|
"Parsing private key %s: %s",
|
||||||
filename, ERR_error_string(ERR_get_error(), NULL));
|
filename, ERR_error_string(ERR_get_error(), NULL));
|
||||||
|
#else
|
||||||
|
{
|
||||||
#endif
|
#endif
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -876,19 +905,26 @@ ssh_private_key _privatekey_from_file(void *session, const char *filename,
|
|||||||
if (!valid) {
|
if (!valid) {
|
||||||
ssh_set_error(session, SSH_FATAL, "Parsing private key %s", filename);
|
ssh_set_error(session, SSH_FATAL, "Parsing private key %s", filename);
|
||||||
#elif defined HAVE_LIBCRYPTO
|
#elif defined HAVE_LIBCRYPTO
|
||||||
rsa = PEM_read_RSAPrivateKey(file, NULL, NULL, NULL);
|
rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
|
||||||
|
|
||||||
fclose(file);
|
BIO_free(bio);
|
||||||
|
|
||||||
if (rsa == NULL) {
|
if (rsa == NULL) {
|
||||||
ssh_set_error(session, SSH_FATAL,
|
ssh_set_error(session, SSH_FATAL,
|
||||||
"Parsing private key %s: %s",
|
"Parsing private key %s: %s",
|
||||||
filename, ERR_error_string(ERR_get_error(), NULL));
|
filename, ERR_error_string(ERR_get_error(), NULL));
|
||||||
|
#else
|
||||||
|
{
|
||||||
#endif
|
#endif
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
#ifdef HAVE_LIBGCRYPT
|
||||||
|
fclose(file);
|
||||||
|
#elif defined HAVE_LIBCRYPTO
|
||||||
|
BIO_free(bio);
|
||||||
|
#endif
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -1178,7 +1214,7 @@ ssh_string try_publickey_from_file(ssh_session session, struct ssh_keys_struct k
|
|||||||
const char *priv;
|
const char *priv;
|
||||||
const char *pub;
|
const char *pub;
|
||||||
char *new;
|
char *new;
|
||||||
ssh_string pubkey=NULL;
|
ssh_string pubkey;
|
||||||
|
|
||||||
pub = keytab.publickey;
|
pub = keytab.publickey;
|
||||||
if (pub == NULL) {
|
if (pub == NULL) {
|
||||||
@@ -1198,13 +1234,13 @@ ssh_string try_publickey_from_file(ssh_session session, struct ssh_keys_struct k
|
|||||||
ssh_log(session, SSH_LOG_PACKET, "Trying to open publickey %s", pub);
|
ssh_log(session, SSH_LOG_PACKET, "Trying to open publickey %s", pub);
|
||||||
if (!ssh_file_readaccess_ok(pub)) {
|
if (!ssh_file_readaccess_ok(pub)) {
|
||||||
ssh_log(session, SSH_LOG_PACKET, "Failed to open publickey %s", pub);
|
ssh_log(session, SSH_LOG_PACKET, "Failed to open publickey %s", pub);
|
||||||
goto error;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_log(session, SSH_LOG_PACKET, "Trying to open privatekey %s", priv);
|
ssh_log(session, SSH_LOG_PACKET, "Trying to open privatekey %s", priv);
|
||||||
if (!ssh_file_readaccess_ok(priv)) {
|
if (!ssh_file_readaccess_ok(priv)) {
|
||||||
ssh_log(session, SSH_LOG_PACKET, "Failed to open privatekey %s", priv);
|
ssh_log(session, SSH_LOG_PACKET, "Failed to open privatekey %s", priv);
|
||||||
goto error;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_log(session, SSH_LOG_PACKET, "Success opening public and private key");
|
ssh_log(session, SSH_LOG_PACKET, "Success opening public and private key");
|
||||||
@@ -1219,18 +1255,18 @@ ssh_string try_publickey_from_file(ssh_session session, struct ssh_keys_struct k
|
|||||||
"Wasn't able to open public key file %s: %s",
|
"Wasn't able to open public key file %s: %s",
|
||||||
pub,
|
pub,
|
||||||
ssh_get_error(session));
|
ssh_get_error(session));
|
||||||
goto error;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
new = realloc(*privkeyfile, strlen(priv) + 1);
|
new = realloc(*privkeyfile, strlen(priv) + 1);
|
||||||
if (new == NULL) {
|
if (new == NULL) {
|
||||||
ssh_string_free(pubkey);
|
ssh_string_free(pubkey);
|
||||||
goto error;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(new, priv);
|
strcpy(new, priv);
|
||||||
*privkeyfile = new;
|
*privkeyfile = new;
|
||||||
error:
|
|
||||||
return pubkey;
|
return pubkey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ ssh_public_key publickey_make_dss(ssh_session session, ssh_buffer buffer) {
|
|||||||
ssh_buffer_free(buffer);
|
ssh_buffer_free(buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
ZERO_STRUCTP(key);
|
||||||
|
|
||||||
key->type = SSH_KEYTYPE_DSS;
|
key->type = SSH_KEYTYPE_DSS;
|
||||||
key->type_c = ssh_type_to_char(key->type);
|
key->type_c = ssh_type_to_char(key->type);
|
||||||
@@ -173,6 +174,7 @@ ssh_public_key publickey_make_rsa(ssh_session session, ssh_buffer buffer,
|
|||||||
ssh_buffer_free(buffer);
|
ssh_buffer_free(buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
ZERO_STRUCTP(key);
|
||||||
|
|
||||||
key->type = type;
|
key->type = type;
|
||||||
key->type_c = ssh_type_to_char(key->type);
|
key->type_c = ssh_type_to_char(key->type);
|
||||||
@@ -597,7 +599,9 @@ error:
|
|||||||
ssh_string_free(n);
|
ssh_string_free(n);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
#if defined(HAVE_LIBGCRYPT) || defined(HAVE_LIBCRYPTO)
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_LIBGCRYPT
|
#ifdef HAVE_LIBGCRYPT
|
||||||
static int rsa_public_to_string(gcry_sexp_t key, ssh_buffer buffer) {
|
static int rsa_public_to_string(gcry_sexp_t key, ssh_buffer buffer) {
|
||||||
@@ -665,7 +669,9 @@ error:
|
|||||||
ssh_string_free(n);
|
ssh_string_free(n);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
#if defined(HAVE_LIBGCRYPT) || defined(HAVE_LIBCRYPTO)
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convert a public_key object into a a SSH string.
|
* @brief Convert a public_key object into a a SSH string.
|
||||||
@@ -893,6 +899,7 @@ SIGNATURE *signature_from_string(ssh_session session, ssh_string signature,
|
|||||||
ssh_set_error(session, SSH_FATAL, "Not enough space");
|
ssh_set_error(session, SSH_FATAL, "Not enough space");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
ZERO_STRUCTP(sign);
|
||||||
|
|
||||||
tmpbuf = ssh_buffer_new();
|
tmpbuf = ssh_buffer_new();
|
||||||
if (tmpbuf == NULL) {
|
if (tmpbuf == NULL) {
|
||||||
@@ -1276,6 +1283,7 @@ ssh_string ssh_do_sign(ssh_session session, ssh_buffer sigbuf,
|
|||||||
if (sign == NULL) {
|
if (sign == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
ZERO_STRUCTP(sign);
|
||||||
|
|
||||||
switch(privatekey->type) {
|
switch(privatekey->type) {
|
||||||
case SSH_KEYTYPE_DSS:
|
case SSH_KEYTYPE_DSS:
|
||||||
@@ -1432,6 +1440,7 @@ ssh_string ssh_sign_session_id(ssh_session session, ssh_private_key privatekey)
|
|||||||
if (sign == NULL) {
|
if (sign == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
ZERO_STRUCTP(sign);
|
||||||
|
|
||||||
switch(privatekey->type) {
|
switch(privatekey->type) {
|
||||||
case SSH_KEYTYPE_DSS:
|
case SSH_KEYTYPE_DSS:
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
#endif /* HAVE_LIBCRYPTO */
|
#endif /* HAVE_LIBCRYPTO */
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
# include <netinet/in.h>
|
||||||
# include <arpa/inet.h>
|
# include <arpa/inet.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
18
src/legacy.c
18
src/legacy.c
@@ -24,7 +24,9 @@
|
|||||||
* compatibility
|
* compatibility
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libssh/libssh.h>
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <libssh/priv.h>
|
||||||
#include <libssh/server.h>
|
#include <libssh/server.h>
|
||||||
#include <libssh/buffer.h>
|
#include <libssh/buffer.h>
|
||||||
|
|
||||||
@@ -240,4 +242,18 @@ char *string_to_char(ssh_string str){
|
|||||||
int ssh_accept(ssh_session session) {
|
int ssh_accept(ssh_session session) {
|
||||||
return ssh_handle_key_exchange(session);
|
return ssh_handle_key_exchange(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int channel_write_stderr(ssh_channel channel, const void *data, uint32_t len) {
|
||||||
|
return ssh_channel_write(channel, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @deprecated
|
||||||
|
* @brief Interface previously exported by error.
|
||||||
|
*/
|
||||||
|
ssh_message ssh_message_retrieve(ssh_session session, uint32_t packettype){
|
||||||
|
(void) packettype;
|
||||||
|
ssh_set_error(session, SSH_FATAL, "ssh_message_retrieve: obsolete libssh call");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* WITH_SERVER */
|
#endif /* WITH_SERVER */
|
||||||
|
|||||||
64
src/log.c
64
src/log.c
@@ -37,6 +37,33 @@
|
|||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/** @internal
|
||||||
|
* @brief do the actual work of logging an event
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void do_ssh_log(struct ssh_common_struct *common, int verbosity,
|
||||||
|
const char *buffer){
|
||||||
|
char indent[256];
|
||||||
|
int min;
|
||||||
|
if (common->callbacks && common->callbacks->log_function) {
|
||||||
|
common->callbacks->log_function((ssh_session)common, verbosity, buffer,
|
||||||
|
common->callbacks->userdata);
|
||||||
|
} else if (verbosity == SSH_LOG_FUNCTIONS) {
|
||||||
|
if (common->log_indent > 255) {
|
||||||
|
min = 255;
|
||||||
|
} else {
|
||||||
|
min = common->log_indent;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(indent, ' ', min);
|
||||||
|
indent[min] = '\0';
|
||||||
|
|
||||||
|
fprintf(stderr, "[func] %s%s\n", indent, buffer);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "[%d] %s\n", verbosity, buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Log a SSH event.
|
* @brief Log a SSH event.
|
||||||
*
|
*
|
||||||
@@ -48,32 +75,31 @@
|
|||||||
*/
|
*/
|
||||||
void ssh_log(ssh_session session, int verbosity, const char *format, ...) {
|
void ssh_log(ssh_session session, int verbosity, const char *format, ...) {
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
char indent[256];
|
|
||||||
int min;
|
|
||||||
va_list va;
|
va_list va;
|
||||||
|
|
||||||
if (verbosity <= session->log_verbosity) {
|
if (verbosity <= session->common.log_verbosity) {
|
||||||
va_start(va, format);
|
va_start(va, format);
|
||||||
vsnprintf(buffer, sizeof(buffer), format, va);
|
vsnprintf(buffer, sizeof(buffer), format, va);
|
||||||
va_end(va);
|
va_end(va);
|
||||||
|
do_ssh_log(&session->common, verbosity, buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (session->callbacks && session->callbacks->log_function) {
|
/** @internal
|
||||||
session->callbacks->log_function(session, verbosity, buffer,
|
* @brief log a SSH event with a common pointer
|
||||||
session->callbacks->userdata);
|
* @param common The SSH/bind session.
|
||||||
} else if (verbosity == SSH_LOG_FUNCTIONS) {
|
* @param verbosity The verbosity of the event.
|
||||||
if (session->log_indent > 255) {
|
* @param format The format string of the log entry.
|
||||||
min = 255;
|
*/
|
||||||
} else {
|
void ssh_log_common(struct ssh_common_struct *common, int verbosity, const char *format, ...){
|
||||||
min = session->log_indent;
|
char buffer[1024];
|
||||||
}
|
va_list va;
|
||||||
|
|
||||||
memset(indent, ' ', min);
|
if (verbosity <= common->log_verbosity) {
|
||||||
indent[min] = '\0';
|
va_start(va, format);
|
||||||
|
vsnprintf(buffer, sizeof(buffer), format, va);
|
||||||
fprintf(stderr, "[func] %s%s\n", indent, buffer);
|
va_end(va);
|
||||||
} else {
|
do_ssh_log(common, verbosity, buffer);
|
||||||
fprintf(stderr, "[%d] %s\n", verbosity, buffer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,10 +21,13 @@
|
|||||||
* MA 02111-1307, USA.
|
* MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -67,6 +70,51 @@ static ssh_message ssh_message_new(ssh_session session){
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef WITH_SERVER
|
||||||
|
|
||||||
|
/* Reduced version of the reply default that only reply with
|
||||||
|
* SSH_MSG_UNIMPLEMENTED
|
||||||
|
*/
|
||||||
|
static int ssh_message_reply_default(ssh_message msg) {
|
||||||
|
ssh_log(msg->session, SSH_LOG_FUNCTIONS, "Reporting unknown packet");
|
||||||
|
|
||||||
|
if (buffer_add_u8(msg->session->out_buffer, SSH2_MSG_UNIMPLEMENTED) < 0)
|
||||||
|
goto error;
|
||||||
|
if (buffer_add_u32(msg->session->out_buffer,
|
||||||
|
htonl(msg->session->recv_seq-1)) < 0)
|
||||||
|
goto error;
|
||||||
|
return packet_send(msg->session);
|
||||||
|
error:
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int ssh_execute_message_callback(ssh_session session, ssh_message msg) {
|
||||||
|
int ret;
|
||||||
|
if(session->ssh_message_callback != NULL) {
|
||||||
|
ret = session->ssh_message_callback(session, msg,
|
||||||
|
session->ssh_message_callback_data);
|
||||||
|
if(ret == 1) {
|
||||||
|
ret = ssh_message_reply_default(msg);
|
||||||
|
ssh_message_free(msg);
|
||||||
|
if(ret != SSH_OK) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ssh_message_free(msg);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ret = ssh_message_reply_default(msg);
|
||||||
|
ssh_message_free(msg);
|
||||||
|
if(ret != SSH_OK) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*
|
*
|
||||||
@@ -77,12 +125,16 @@ static ssh_message ssh_message_new(ssh_session session){
|
|||||||
* @param[in] message The message to add to the queue.
|
* @param[in] message The message to add to the queue.
|
||||||
*/
|
*/
|
||||||
void ssh_message_queue(ssh_session session, ssh_message message){
|
void ssh_message_queue(ssh_session session, ssh_message message){
|
||||||
if(message){
|
if(message) {
|
||||||
if(session->ssh_message_list == NULL){
|
if(session->ssh_message_list == NULL) {
|
||||||
session->ssh_message_list=ssh_list_new();
|
if(session->ssh_message_callback != NULL) {
|
||||||
|
ssh_execute_message_callback(session, message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
session->ssh_message_list = ssh_list_new();
|
||||||
|
}
|
||||||
|
ssh_list_append(session->ssh_message_list, message);
|
||||||
}
|
}
|
||||||
ssh_list_append(session->ssh_message_list, message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -130,7 +182,7 @@ ssh_message ssh_message_get(ssh_session session) {
|
|||||||
session->ssh_message_list = ssh_list_new();
|
session->ssh_message_list = ssh_list_new();
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
if (ssh_handle_packets(session,-1) == SSH_ERROR) {
|
if (ssh_handle_packets(session, -2) == SSH_ERROR) {
|
||||||
leave_function();
|
leave_function();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -860,6 +912,7 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request){
|
|||||||
char *bind_addr=NULL;
|
char *bind_addr=NULL;
|
||||||
uint32_t bind_port;
|
uint32_t bind_port;
|
||||||
uint8_t want_reply;
|
uint8_t want_reply;
|
||||||
|
int rc = SSH_PACKET_USED;
|
||||||
(void)user;
|
(void)user;
|
||||||
(void)type;
|
(void)type;
|
||||||
(void)packet;
|
(void)packet;
|
||||||
@@ -894,9 +947,9 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request){
|
|||||||
|
|
||||||
ssh_log(session, SSH_LOG_PROTOCOL, "Received SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply, bind_addr, bind_port);
|
ssh_log(session, SSH_LOG_PROTOCOL, "Received SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply, bind_addr, bind_port);
|
||||||
|
|
||||||
if(ssh_callbacks_exists(session->callbacks, global_request_function)) {
|
if(ssh_callbacks_exists(session->common.callbacks, global_request_function)) {
|
||||||
ssh_log(session, SSH_LOG_PROTOCOL, "Calling callback for SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply, bind_addr, bind_port);
|
ssh_log(session, SSH_LOG_PROTOCOL, "Calling callback for SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply, bind_addr, bind_port);
|
||||||
session->callbacks->global_request_function(session, msg, session->callbacks->userdata);
|
session->common.callbacks->global_request_function(session, msg, session->common.callbacks->userdata);
|
||||||
} else {
|
} else {
|
||||||
ssh_message_reply_default(msg);
|
ssh_message_reply_default(msg);
|
||||||
}
|
}
|
||||||
@@ -916,19 +969,21 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request){
|
|||||||
|
|
||||||
ssh_log(session, SSH_LOG_PROTOCOL, "Received SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply, bind_addr, bind_port);
|
ssh_log(session, SSH_LOG_PROTOCOL, "Received SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply, bind_addr, bind_port);
|
||||||
|
|
||||||
if(ssh_callbacks_exists(session->callbacks, global_request_function)) {
|
if(ssh_callbacks_exists(session->common.callbacks, global_request_function)) {
|
||||||
session->callbacks->global_request_function(session, msg, session->callbacks->userdata);
|
session->common.callbacks->global_request_function(session, msg, session->common.callbacks->userdata);
|
||||||
} else {
|
} else {
|
||||||
ssh_message_reply_default(msg);
|
ssh_message_reply_default(msg);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ssh_log(session, SSH_LOG_PROTOCOL, "UNKNOWN SSH_MSG_GLOBAL_REQUEST %s %d", request, want_reply);
|
ssh_log(session, SSH_LOG_PROTOCOL, "UNKNOWN SSH_MSG_GLOBAL_REQUEST %s %d", request, want_reply);
|
||||||
|
rc = SSH_PACKET_NOT_USED;
|
||||||
}
|
}
|
||||||
|
|
||||||
SAFE_FREE(msg);
|
SAFE_FREE(msg);
|
||||||
SAFE_FREE(request);
|
SAFE_FREE(request);
|
||||||
SAFE_FREE(bind_addr);
|
SAFE_FREE(bind_addr);
|
||||||
return SSH_PACKET_USED;
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* WITH_SERVER */
|
#endif /* WITH_SERVER */
|
||||||
|
|||||||
233
src/misc.c
233
src/misc.c
@@ -22,14 +22,22 @@
|
|||||||
* MA 02111-1307, USA.
|
* MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
/* This is needed for a standard getpwuid_r on opensolaris */
|
/* This is needed for a standard getpwuid_r on opensolaris */
|
||||||
#define _POSIX_PTHREAD_SEMANTICS
|
#define _POSIX_PTHREAD_SEMANTICS
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "config.h"
|
#ifndef HAVE_CLOCK_GETTIME
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif /* HAVE_CLOCK_GETTIME */
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -37,6 +45,7 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
@@ -136,7 +145,7 @@ char *ssh_get_local_username(ssh_session session) {
|
|||||||
/* get the size */
|
/* get the size */
|
||||||
GetUserName(NULL, &size);
|
GetUserName(NULL, &size);
|
||||||
|
|
||||||
user = malloc(size);
|
user = (char *) malloc(size);
|
||||||
if (user == NULL) {
|
if (user == NULL) {
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -148,6 +157,49 @@ char *ssh_get_local_username(ssh_session session) {
|
|||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ssh_is_ipaddr_v4(const char *str) {
|
||||||
|
struct sockaddr_storage ss;
|
||||||
|
int sslen = sizeof(ss);
|
||||||
|
int rc = SOCKET_ERROR;
|
||||||
|
|
||||||
|
/* WSAStringToAddressA thinks that 0.0.0 is a valid IP */
|
||||||
|
if (strlen(str) < 7) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = WSAStringToAddressA((LPSTR) str,
|
||||||
|
AF_INET,
|
||||||
|
NULL,
|
||||||
|
(struct sockaddr*)&ss,
|
||||||
|
&sslen);
|
||||||
|
if (rc == 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ssh_is_ipaddr(const char *str) {
|
||||||
|
int rc = SOCKET_ERROR;
|
||||||
|
|
||||||
|
if (strchr(str, ':')) {
|
||||||
|
struct sockaddr_storage ss;
|
||||||
|
int sslen = sizeof(ss);
|
||||||
|
|
||||||
|
/* TODO link-local (IP:v6:addr%ifname). */
|
||||||
|
rc = WSAStringToAddressA((LPSTR) str,
|
||||||
|
AF_INET6,
|
||||||
|
NULL,
|
||||||
|
(struct sockaddr*)&ss,
|
||||||
|
&sslen);
|
||||||
|
if (rc == 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ssh_is_ipaddr_v4(str);
|
||||||
|
}
|
||||||
#else /* _WIN32 */
|
#else /* _WIN32 */
|
||||||
|
|
||||||
#ifndef NSS_BUFLEN_PASSWD
|
#ifndef NSS_BUFLEN_PASSWD
|
||||||
@@ -163,7 +215,8 @@ char *ssh_get_user_home_dir(void) {
|
|||||||
|
|
||||||
rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
|
rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
return NULL;
|
szPath=getenv("HOME");
|
||||||
|
return szPath ? strdup(szPath) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
szPath = strdup(pwd.pw_dir);
|
szPath = strdup(pwd.pw_dir);
|
||||||
@@ -203,20 +256,51 @@ char *ssh_get_local_username(ssh_session session) {
|
|||||||
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ssh_is_ipaddr_v4(const char *str) {
|
||||||
|
int rc = -1;
|
||||||
|
struct in_addr dest;
|
||||||
|
|
||||||
|
rc = inet_pton(AF_INET, str, &dest);
|
||||||
|
if (rc > 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ssh_is_ipaddr(const char *str) {
|
||||||
|
int rc = -1;
|
||||||
|
|
||||||
|
if (strchr(str, ':')) {
|
||||||
|
struct in6_addr dest6;
|
||||||
|
|
||||||
|
/* TODO link-local (IP:v6:addr%ifname). */
|
||||||
|
rc = inet_pton(AF_INET6, str, &dest6);
|
||||||
|
if (rc > 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ssh_is_ipaddr_v4(str);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
#ifndef HAVE_NTOHLL
|
||||||
uint64_t ntohll(uint64_t a) {
|
uint64_t ntohll(uint64_t a) {
|
||||||
#ifdef WORDS_BIGENDIAN
|
#ifdef WORDS_BIGENDIAN
|
||||||
return a;
|
return a;
|
||||||
#else
|
#else /* WORDS_BIGENDIAN */
|
||||||
uint32_t low = (uint32_t)(a & 0xffffffff);
|
uint32_t low = (uint32_t)(a & 0xffffffff);
|
||||||
uint32_t high = (uint32_t)(a >> 32);
|
uint32_t high = (uint32_t)(a >> 32);
|
||||||
low = ntohl(low);
|
low = ntohl(low);
|
||||||
high = ntohl(high);
|
high = ntohl(high);
|
||||||
|
|
||||||
return ((((uint64_t) low) << 32) | ( high));
|
return ((((uint64_t) low) << 32) | ( high));
|
||||||
#endif
|
#endif /* WORDS_BIGENDIAN */
|
||||||
}
|
}
|
||||||
|
#endif /* HAVE_NTOHLL */
|
||||||
|
|
||||||
char *ssh_lowercase(const char* str) {
|
char *ssh_lowercase(const char* str) {
|
||||||
char *new, *p;
|
char *new, *p;
|
||||||
@@ -293,6 +377,8 @@ struct ssh_list *ssh_list_new(){
|
|||||||
|
|
||||||
void ssh_list_free(struct ssh_list *list){
|
void ssh_list_free(struct ssh_list *list){
|
||||||
struct ssh_iterator *ptr,*next;
|
struct ssh_iterator *ptr,*next;
|
||||||
|
if(!list)
|
||||||
|
return;
|
||||||
ptr=list->root;
|
ptr=list->root;
|
||||||
while(ptr){
|
while(ptr){
|
||||||
next=ptr->next;
|
next=ptr->next;
|
||||||
@@ -303,9 +389,19 @@ 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){
|
||||||
|
if(!list)
|
||||||
|
return NULL;
|
||||||
return list->root;
|
return list->root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ssh_iterator *ssh_list_find(const struct ssh_list *list, void *value){
|
||||||
|
struct ssh_iterator *it;
|
||||||
|
for(it = ssh_list_get_iterator(list); it != NULL ;it=it->next)
|
||||||
|
if(it->data==value)
|
||||||
|
return it;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static struct ssh_iterator *ssh_iterator_new(const void *data){
|
static struct ssh_iterator *ssh_iterator_new(const void *data){
|
||||||
struct ssh_iterator *iterator=malloc(sizeof(struct ssh_iterator));
|
struct ssh_iterator *iterator=malloc(sizeof(struct ssh_iterator));
|
||||||
if(!iterator)
|
if(!iterator)
|
||||||
@@ -559,7 +655,7 @@ char *ssh_path_expand_tilde(const char *d) {
|
|||||||
size_t s = p - d;
|
size_t s = p - d;
|
||||||
char u[128];
|
char u[128];
|
||||||
|
|
||||||
if (s > sizeof(u)) {
|
if (s >= sizeof(u)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memcpy(u, d, s);
|
memcpy(u, d, s);
|
||||||
@@ -623,7 +719,8 @@ char *ssh_path_expand_escape(ssh_session session, const char *s) {
|
|||||||
if (*p != '%') {
|
if (*p != '%') {
|
||||||
buf[i] = *p;
|
buf[i] = *p;
|
||||||
i++;
|
i++;
|
||||||
if (i > MAX_BUF_SIZE) {
|
if (i >= MAX_BUF_SIZE) {
|
||||||
|
free(r);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
buf[i] = '\0';
|
buf[i] = '\0';
|
||||||
@@ -664,18 +761,22 @@ char *ssh_path_expand_escape(ssh_session session, const char *s) {
|
|||||||
default:
|
default:
|
||||||
ssh_set_error(session, SSH_FATAL,
|
ssh_set_error(session, SSH_FATAL,
|
||||||
"Wrong escape sequence detected");
|
"Wrong escape sequence detected");
|
||||||
|
free(r);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x == NULL) {
|
if (x == NULL) {
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
|
free(r);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
i += strlen(x);
|
i += strlen(x);
|
||||||
if (i > MAX_BUF_SIZE) {
|
if (i >= MAX_BUF_SIZE) {
|
||||||
ssh_set_error(session, SSH_FATAL,
|
ssh_set_error(session, SSH_FATAL,
|
||||||
"String too long");
|
"String too long");
|
||||||
|
free(x);
|
||||||
|
free(r);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
l = strlen(buf);
|
l = strlen(buf);
|
||||||
@@ -779,6 +880,120 @@ int ssh_analyze_banner(ssh_session session, int server, int *ssh1, int *ssh2) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* try the Monotonic clock if possible for perfs reasons */
|
||||||
|
#ifdef _POSIX_MONOTONIC_CLOCK
|
||||||
|
#define CLOCK CLOCK_MONOTONIC
|
||||||
|
#else
|
||||||
|
#define CLOCK CLOCK_REALTIME
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @brief initializes a timestamp to the current time
|
||||||
|
* @param[out] ts pointer to an allocated ssh_timestamp structure
|
||||||
|
*/
|
||||||
|
void ssh_timestamp_init(struct ssh_timestamp *ts){
|
||||||
|
#ifdef HAVE_CLOCK_GETTIME
|
||||||
|
struct timespec tp;
|
||||||
|
clock_gettime(CLOCK, &tp);
|
||||||
|
ts->useconds = tp.tv_nsec / 1000;
|
||||||
|
#else
|
||||||
|
struct timeval tp;
|
||||||
|
gettimeofday(&tp, NULL);
|
||||||
|
ts->useconds = tp.tv_usec;
|
||||||
|
#endif
|
||||||
|
ts->seconds = tp.tv_sec;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef CLOCK
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @brief gets the time difference between two timestamps in ms
|
||||||
|
* @param[in] old older value
|
||||||
|
* @param[in] new newer value
|
||||||
|
* @returns difference in milliseconds
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int ssh_timestamp_difference(struct ssh_timestamp *old,
|
||||||
|
struct ssh_timestamp *new){
|
||||||
|
long seconds, usecs, msecs;
|
||||||
|
seconds = new->seconds - old->seconds;
|
||||||
|
usecs = new->useconds - old->useconds;
|
||||||
|
if (usecs < 0){
|
||||||
|
seconds--;
|
||||||
|
usecs += 1000000;
|
||||||
|
}
|
||||||
|
msecs = seconds * 1000 + usecs/1000;
|
||||||
|
return msecs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @brief turn seconds and microseconds pair (as provided by user-set options)
|
||||||
|
* into millisecond value
|
||||||
|
* @param[in] sec number of seconds
|
||||||
|
* @param[in] usec number of microseconds
|
||||||
|
* @returns milliseconds, or 10000 if user supplied values are equal to zero
|
||||||
|
*/
|
||||||
|
int ssh_make_milliseconds(long sec, long usec) {
|
||||||
|
int res = usec ? (usec / 1000) : 0;
|
||||||
|
res += (sec * 1000);
|
||||||
|
if (res == 0) {
|
||||||
|
res = 10 * 1000; /* use a reasonable default value in case
|
||||||
|
* SSH_OPTIONS_TIMEOUT is not set in options. */
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @brief Checks if a timeout is elapsed, in function of a previous
|
||||||
|
* timestamp and an assigned timeout
|
||||||
|
* @param[in] ts pointer to an existing timestamp
|
||||||
|
* @param[in] timeout timeout in milliseconds. Negative values mean infinite
|
||||||
|
* timeout
|
||||||
|
* @returns 1 if timeout is elapsed
|
||||||
|
* 0 otherwise
|
||||||
|
*/
|
||||||
|
int ssh_timeout_elapsed(struct ssh_timestamp *ts, int timeout) {
|
||||||
|
struct ssh_timestamp now;
|
||||||
|
switch(timeout) {
|
||||||
|
case -2: // -2 means user-defined timeout as available in session->timeout, session->timeout_usec.
|
||||||
|
fprintf(stderr, "ssh_timeout_elapsed called with -2. this needs to be fixed. "
|
||||||
|
"please set a breakpoint on %s:%d and fix the caller\n", __FILE__, __LINE__);
|
||||||
|
case -1: // -1 means infinite timeout
|
||||||
|
return 0;
|
||||||
|
case 0: // 0 means no timeout
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ssh_timestamp_init(&now);
|
||||||
|
return (ssh_timestamp_difference(ts,&now) >= timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief updates a timeout value so it reflects the remaining time
|
||||||
|
* @param[in] ts pointer to an existing timestamp
|
||||||
|
* @param[in] timeout timeout in milliseconds. Negative values mean infinite
|
||||||
|
* timeout
|
||||||
|
* @returns remaining time in milliseconds, 0 if elapsed, -1 if never,
|
||||||
|
* -2 if option-set-timeout.
|
||||||
|
*/
|
||||||
|
int ssh_timeout_update(struct ssh_timestamp *ts, int timeout){
|
||||||
|
struct ssh_timestamp now;
|
||||||
|
int ms, ret;
|
||||||
|
if (timeout <= 0) {
|
||||||
|
return timeout;
|
||||||
|
}
|
||||||
|
ssh_timestamp_init(&now);
|
||||||
|
ms = ssh_timestamp_difference(ts,&now);
|
||||||
|
if(ms < 0)
|
||||||
|
ms = 0;
|
||||||
|
ret = timeout - ms;
|
||||||
|
return ret >= 0 ? ret: 0;
|
||||||
|
}
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/* vim: set ts=4 sw=4 et cindent: */
|
/* vim: set ts=4 sw=4 et cindent: */
|
||||||
|
|||||||
@@ -139,12 +139,12 @@ int ssh_options_copy(ssh_session src, ssh_session *dest) {
|
|||||||
}
|
}
|
||||||
new->fd = src->fd;
|
new->fd = src->fd;
|
||||||
new->port = src->port;
|
new->port = src->port;
|
||||||
new->callbacks = src->callbacks;
|
new->common.callbacks = src->common.callbacks;
|
||||||
new->timeout = src->timeout;
|
new->timeout = src->timeout;
|
||||||
new->timeout_usec = src->timeout_usec;
|
new->timeout_usec = src->timeout_usec;
|
||||||
new->ssh2 = src->ssh2;
|
new->ssh2 = src->ssh2;
|
||||||
new->ssh1 = src->ssh1;
|
new->ssh1 = src->ssh1;
|
||||||
new->log_verbosity = src->log_verbosity;
|
new->common.log_verbosity = src->common.log_verbosity;
|
||||||
new->compressionlevel = src->compressionlevel;
|
new->compressionlevel = src->compressionlevel;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -544,12 +544,12 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
|||||||
} else {
|
} else {
|
||||||
int *x = (int *) value;
|
int *x = (int *) value;
|
||||||
|
|
||||||
session->log_verbosity = *x & 0xffff;
|
session->common.log_verbosity = *x & 0xffff;
|
||||||
}
|
}
|
||||||
break;
|
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->common.log_verbosity = 0 & 0xffff;
|
||||||
} else {
|
} else {
|
||||||
q = strdup(value);
|
q = strdup(value);
|
||||||
if (q == NULL) {
|
if (q == NULL) {
|
||||||
@@ -562,7 +562,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
|||||||
}
|
}
|
||||||
SAFE_FREE(q);
|
SAFE_FREE(q);
|
||||||
|
|
||||||
session->log_verbosity = i & 0xffff;
|
session->common.log_verbosity = i & 0xffff;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SSH_OPTIONS_CIPHERS_C_S:
|
case SSH_OPTIONS_CIPHERS_C_S:
|
||||||
@@ -655,11 +655,15 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
|||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
SAFE_FREE(session->ProxyCommand);
|
SAFE_FREE(session->ProxyCommand);
|
||||||
q = strdup(value);
|
/* Setting the command to 'none' disables this option. */
|
||||||
if (q == NULL) {
|
rc = strcasecmp(value, "none");
|
||||||
return -1;
|
if (rc != 0) {
|
||||||
|
q = strdup(value);
|
||||||
|
if (q == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
session->ProxyCommand = q;
|
||||||
}
|
}
|
||||||
session->ProxyCommand = q;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -698,7 +702,7 @@ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv) {
|
|||||||
char *cipher = NULL;
|
char *cipher = NULL;
|
||||||
char *identity = NULL;
|
char *identity = NULL;
|
||||||
char *port = NULL;
|
char *port = NULL;
|
||||||
char **save = NULL;
|
char **save = NULL, **tmp;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int argc = *argcptr;
|
int argc = *argcptr;
|
||||||
int debuglevel = 0;
|
int debuglevel = 0;
|
||||||
@@ -720,12 +724,6 @@ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv) {
|
|||||||
int saveoptind = optind; /* need to save 'em */
|
int saveoptind = optind; /* need to save 'em */
|
||||||
int saveopterr = opterr;
|
int saveopterr = opterr;
|
||||||
|
|
||||||
save = malloc(argc * sizeof(char *));
|
|
||||||
if (save == NULL) {
|
|
||||||
ssh_set_error_oom(session);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
opterr = 0; /* shut up getopt */
|
opterr = 0; /* shut up getopt */
|
||||||
while(cont && ((i = getopt(argc, argv, "c:i:Cl:p:vb:rd12")) != -1)) {
|
while(cont && ((i = getopt(argc, argv, "c:i:Cl:p:vb:rd12")) != -1)) {
|
||||||
switch(i) {
|
switch(i) {
|
||||||
@@ -765,6 +763,13 @@ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv) {
|
|||||||
{
|
{
|
||||||
char opt[3]="- ";
|
char opt[3]="- ";
|
||||||
opt[1] = optopt;
|
opt[1] = optopt;
|
||||||
|
tmp = realloc(save, (current + 1) * sizeof(char*));
|
||||||
|
if (tmp == NULL) {
|
||||||
|
SAFE_FREE(save);
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
save = tmp;
|
||||||
save[current] = strdup(opt);
|
save[current] = strdup(opt);
|
||||||
if (save[current] == NULL) {
|
if (save[current] == NULL) {
|
||||||
SAFE_FREE(save);
|
SAFE_FREE(save);
|
||||||
@@ -780,7 +785,16 @@ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv) {
|
|||||||
} /* while */
|
} /* while */
|
||||||
opterr = saveopterr;
|
opterr = saveopterr;
|
||||||
while (optind < argc) {
|
while (optind < argc) {
|
||||||
save[current++] = argv[optind++];
|
tmp = realloc(save, (current + 1) * sizeof(char*));
|
||||||
|
if (tmp == NULL) {
|
||||||
|
SAFE_FREE(save);
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
save = tmp;
|
||||||
|
save[current] = argv[optind];
|
||||||
|
current++;
|
||||||
|
optind++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usersa && usedss) {
|
if (usersa && usedss) {
|
||||||
@@ -1106,12 +1120,12 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
|
|||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
int *x = (int *) value;
|
int *x = (int *) value;
|
||||||
sshbind->log_verbosity = *x & 0xffff;
|
sshbind->common.log_verbosity = *x & 0xffff;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SSH_BIND_OPTIONS_LOG_VERBOSITY_STR:
|
case SSH_BIND_OPTIONS_LOG_VERBOSITY_STR:
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
sshbind->log_verbosity = 0;
|
sshbind->common.log_verbosity = 0;
|
||||||
} else {
|
} else {
|
||||||
q = strdup(value);
|
q = strdup(value);
|
||||||
if (q == NULL) {
|
if (q == NULL) {
|
||||||
@@ -1124,7 +1138,7 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
|
|||||||
}
|
}
|
||||||
SAFE_FREE(q);
|
SAFE_FREE(q);
|
||||||
|
|
||||||
sshbind->log_verbosity = i & 0xffff;
|
sshbind->common.log_verbosity = i & 0xffff;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SSH_BIND_OPTIONS_DSAKEY:
|
case SSH_BIND_OPTIONS_DSAKEY:
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -255,7 +256,9 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
|||||||
"After padding, %d bytes left in buffer",
|
"After padding, %d bytes left in buffer",
|
||||||
buffer_get_rest_len(session->in_buffer));
|
buffer_get_rest_len(session->in_buffer));
|
||||||
#if defined(HAVE_LIBZ) && defined(WITH_LIBZ)
|
#if defined(HAVE_LIBZ) && defined(WITH_LIBZ)
|
||||||
if (session->current_crypto && session->current_crypto->do_compress_in) {
|
if (session->current_crypto
|
||||||
|
&& session->current_crypto->do_compress_in
|
||||||
|
&& buffer_get_rest_len(session->in_buffer)) {
|
||||||
ssh_log(session, SSH_LOG_PACKET, "Decompressing in_buffer ...");
|
ssh_log(session, SSH_LOG_PACKET, "Decompressing in_buffer ...");
|
||||||
if (decompress_buffer(session, session->in_buffer,MAX_PACKET_LEN) < 0) {
|
if (decompress_buffer(session, session->in_buffer,MAX_PACKET_LEN) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
@@ -457,7 +460,9 @@ static int packet_send2(ssh_session session) {
|
|||||||
"Writing on the wire a packet having %u bytes before", currentlen);
|
"Writing on the wire a packet having %u bytes before", currentlen);
|
||||||
|
|
||||||
#if defined(HAVE_LIBZ) && defined(WITH_LIBZ)
|
#if defined(HAVE_LIBZ) && defined(WITH_LIBZ)
|
||||||
if (session->current_crypto && session->current_crypto->do_compress_out) {
|
if (session->current_crypto
|
||||||
|
&& session->current_crypto->do_compress_out
|
||||||
|
&& buffer_get_rest_len(session->out_buffer)) {
|
||||||
ssh_log(session, SSH_LOG_PACKET, "Compressing out_buffer ...");
|
ssh_log(session, SSH_LOG_PACKET, "Compressing out_buffer ...");
|
||||||
if (compress_buffer(session,session->out_buffer) < 0) {
|
if (compress_buffer(session,session->out_buffer) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ ssh_packet_callback default_packet_handlers1[]= {
|
|||||||
ssh_packet_data1, //SSH_SMSG_STDOUT_DATA 17
|
ssh_packet_data1, //SSH_SMSG_STDOUT_DATA 17
|
||||||
ssh_packet_data1, //SSH_SMSG_STDERR_DATA 18
|
ssh_packet_data1, //SSH_SMSG_STDERR_DATA 18
|
||||||
NULL, //SSH_CMSG_EOF 19
|
NULL, //SSH_CMSG_EOF 19
|
||||||
NULL, //SSH_SMSG_EXITSTATUS 20
|
ssh_packet_exist_status1, //SSH_SMSG_EXITSTATUS 20
|
||||||
NULL, //SSH_MSG_CHANNEL_OPEN_CONFIRMATION 21
|
NULL, //SSH_MSG_CHANNEL_OPEN_CONFIRMATION 21
|
||||||
NULL, //SSH_MSG_CHANNEL_OPEN_FAILURE 22
|
NULL, //SSH_MSG_CHANNEL_OPEN_FAILURE 22
|
||||||
NULL, //SSH_MSG_CHANNEL_DATA 23
|
NULL, //SSH_MSG_CHANNEL_DATA 23
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ struct ssh_pcap_file_struct {
|
|||||||
ssh_pcap_file ssh_pcap_file_new(){
|
ssh_pcap_file ssh_pcap_file_new(){
|
||||||
struct ssh_pcap_file_struct *pcap;
|
struct ssh_pcap_file_struct *pcap;
|
||||||
|
|
||||||
pcap = malloc(sizeof(struct ssh_pcap_file_struct));
|
pcap = (struct ssh_pcap_file_struct *) malloc(sizeof(struct ssh_pcap_file_struct));
|
||||||
if (pcap == NULL) {
|
if (pcap == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -228,7 +228,7 @@ void ssh_pcap_file_free(ssh_pcap_file pcap){
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
ssh_pcap_context ssh_pcap_context_new(ssh_session session){
|
ssh_pcap_context ssh_pcap_context_new(ssh_session session){
|
||||||
ssh_pcap_context ctx=malloc(sizeof(struct ssh_pcap_context_struct));
|
ssh_pcap_context ctx = (struct ssh_pcap_context_struct *) malloc(sizeof(struct ssh_pcap_context_struct));
|
||||||
if(ctx==NULL){
|
if(ctx==NULL){
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
78
src/poll.c
78
src/poll.c
@@ -105,29 +105,6 @@ static poll_fn ssh_poll_emu;
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
|
|
||||||
#if (_WIN32_WINNT < 0x0600)
|
|
||||||
typedef struct ssh_pollfd_struct WSAPOLLFD;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef int (WSAAPI* WSAPoll_FunctionType)(WSAPOLLFD fdarray[],
|
|
||||||
ULONG nfds,
|
|
||||||
INT timeout
|
|
||||||
);
|
|
||||||
|
|
||||||
static WSAPoll_FunctionType wsa_poll;
|
|
||||||
|
|
||||||
int win_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
|
|
||||||
if (wsa_poll) {
|
|
||||||
return (wsa_poll)((WSAPOLLFD *) fds, nfds, timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
return SOCKET_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define WS2_LIBRARY "ws2_32.dll"
|
|
||||||
static HINSTANCE hlib;
|
|
||||||
|
|
||||||
#else /* _WIN32 */
|
#else /* _WIN32 */
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
@@ -261,30 +238,10 @@ static int bsd_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
|
|||||||
|
|
||||||
void ssh_poll_init(void) {
|
void ssh_poll_init(void) {
|
||||||
ssh_poll_emu = bsd_poll;
|
ssh_poll_emu = bsd_poll;
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
hlib = LoadLibrary(WS2_LIBRARY);
|
|
||||||
if (hlib != NULL) {
|
|
||||||
wsa_poll = (WSAPoll_FunctionType) (void *) GetProcAddress(hlib, "WSAPoll");
|
|
||||||
}
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
|
|
||||||
if (wsa_poll == NULL) {
|
|
||||||
ssh_poll_emu = bsd_poll;
|
|
||||||
} else {
|
|
||||||
ssh_poll_emu = win_poll;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ssh_poll_cleanup(void) {
|
void ssh_poll_cleanup(void) {
|
||||||
ssh_poll_emu = bsd_poll;
|
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) {
|
int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
|
||||||
@@ -298,8 +255,9 @@ int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
|
|||||||
*
|
*
|
||||||
* @param fd Socket that will be polled.
|
* @param fd Socket that will be polled.
|
||||||
* @param events Poll events that will be monitored for the socket. i.e.
|
* @param events Poll events that will be monitored for the socket. i.e.
|
||||||
* POLLIN, POLLPRI, POLLOUT, POLLERR, POLLHUP, POLLNVAL
|
* POLLIN, POLLPRI, POLLOUT
|
||||||
* @param cb Function to be called if any of the events are set.
|
* @param cb Function to be called if any of the events are set.
|
||||||
|
*
|
||||||
* @param userdata Userdata to be passed to the callback function. NULL if
|
* @param userdata Userdata to be passed to the callback function. NULL if
|
||||||
* not needed.
|
* not needed.
|
||||||
*
|
*
|
||||||
@@ -482,19 +440,9 @@ ssh_poll_ctx ssh_poll_ctx_new(size_t chunk_size) {
|
|||||||
*/
|
*/
|
||||||
void ssh_poll_ctx_free(ssh_poll_ctx ctx) {
|
void ssh_poll_ctx_free(ssh_poll_ctx ctx) {
|
||||||
if (ctx->polls_allocated > 0) {
|
if (ctx->polls_allocated > 0) {
|
||||||
register size_t i, used;
|
while (ctx->polls_used > 0){
|
||||||
|
ssh_poll_handle p = ctx->pollptrs[0];
|
||||||
used = ctx->polls_used;
|
ssh_poll_ctx_remove(ctx, p);
|
||||||
for (i = 0; i < used; ) {
|
|
||||||
ssh_poll_handle p = ctx->pollptrs[i];
|
|
||||||
socket_t fd = ctx->pollfds[i].fd;
|
|
||||||
|
|
||||||
/* force poll object removal */
|
|
||||||
if (p->cb(p, fd, POLLERR, p->cb_data) < 0) {
|
|
||||||
used = ctx->polls_used;
|
|
||||||
} else {
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SAFE_FREE(ctx->pollptrs);
|
SAFE_FREE(ctx->pollptrs);
|
||||||
@@ -622,6 +570,7 @@ void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p) {
|
|||||||
* the poll() function.
|
* the poll() function.
|
||||||
* @returns SSH_OK No error.
|
* @returns SSH_OK No error.
|
||||||
* SSH_ERROR Error happened during the poll.
|
* SSH_ERROR Error happened during the poll.
|
||||||
|
* SSH_AGAIN Timeout occured
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout) {
|
int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout) {
|
||||||
@@ -632,23 +581,28 @@ int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout) {
|
|||||||
int revents;
|
int revents;
|
||||||
|
|
||||||
if (!ctx->polls_used)
|
if (!ctx->polls_used)
|
||||||
return 0;
|
return SSH_ERROR;
|
||||||
|
|
||||||
rc = ssh_poll(ctx->pollfds, ctx->polls_used, timeout);
|
rc = ssh_poll(ctx->pollfds, ctx->polls_used, timeout);
|
||||||
if(rc < 0)
|
if(rc < 0)
|
||||||
rc=SSH_ERROR;
|
return SSH_ERROR;
|
||||||
if(rc <= 0)
|
if (rc == 0)
|
||||||
return rc;
|
return SSH_AGAIN;
|
||||||
used = ctx->polls_used;
|
used = ctx->polls_used;
|
||||||
for (i = 0; i < used && rc > 0; ) {
|
for (i = 0; i < used && rc > 0; ) {
|
||||||
if (!ctx->pollfds[i].revents) {
|
if (!ctx->pollfds[i].revents) {
|
||||||
i++;
|
i++;
|
||||||
} else {
|
} else {
|
||||||
|
int ret;
|
||||||
|
|
||||||
p = ctx->pollptrs[i];
|
p = ctx->pollptrs[i];
|
||||||
fd = ctx->pollfds[i].fd;
|
fd = ctx->pollfds[i].fd;
|
||||||
revents = ctx->pollfds[i].revents;
|
revents = ctx->pollfds[i].revents;
|
||||||
|
|
||||||
if (p->cb(p, fd, revents, p->cb_data) < 0) {
|
if (p->cb && (ret = p->cb(p, fd, revents, p->cb_data)) < 0) {
|
||||||
|
if (ret == -2) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
/* the poll was removed, reload the used counter and start again */
|
/* the poll was removed, reload the used counter and start again */
|
||||||
used = ctx->polls_used;
|
used = ctx->polls_used;
|
||||||
i=0;
|
i=0;
|
||||||
|
|||||||
40
src/scp.c
40
src/scp.c
@@ -148,7 +148,7 @@ int ssh_scp_close(ssh_scp scp){
|
|||||||
*/
|
*/
|
||||||
while(!ssh_channel_is_eof(scp->channel)){
|
while(!ssh_channel_is_eof(scp->channel)){
|
||||||
err=ssh_channel_read(scp->channel,buffer,sizeof(buffer),0);
|
err=ssh_channel_read(scp->channel,buffer,sizeof(buffer),0);
|
||||||
if(err==SSH_ERROR)
|
if(err==SSH_ERROR || err==0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(ssh_channel_close(scp->channel) == SSH_ERROR){
|
if(ssh_channel_close(scp->channel) == SSH_ERROR){
|
||||||
@@ -380,8 +380,8 @@ int ssh_scp_response(ssh_scp scp, char **response){
|
|||||||
*/
|
*/
|
||||||
int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len){
|
int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len){
|
||||||
int w;
|
int w;
|
||||||
//int r;
|
int r;
|
||||||
//uint8_t code;
|
uint8_t code;
|
||||||
if(scp==NULL)
|
if(scp==NULL)
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
if(scp->state != SSH_SCP_WRITE_WRITING){
|
if(scp->state != SSH_SCP_WRITE_WRITING){
|
||||||
@@ -400,19 +400,27 @@ int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len){
|
|||||||
//return=channel_get_exit_status(scp->channel);
|
//return=channel_get_exit_status(scp->channel);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
/* Far end sometimes send a status message, which we need to read
|
||||||
|
* and handle */
|
||||||
|
r = ssh_channel_poll(scp->channel,0);
|
||||||
|
if(r > 0){
|
||||||
|
r = ssh_channel_read(scp->channel, &code, 1, 0);
|
||||||
|
if(r == SSH_ERROR){
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
if(code == 1 || code == 2){
|
||||||
|
ssh_set_error(scp->session,SSH_REQUEST_DENIED, "SCP: Error: status code %i received", code);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
/* Check if we arrived at end of file */
|
/* Check if we arrived at end of file */
|
||||||
if(scp->processed == scp->filelen) {
|
if(scp->processed == scp->filelen) {
|
||||||
/* r=channel_read(scp->channel,&code,1,0);
|
code = 0;
|
||||||
if(r==SSH_ERROR){
|
w = ssh_channel_write(scp->channel, &code, 1);
|
||||||
scp->state=SSH_SCP_ERROR;
|
if(w == SSH_ERROR){
|
||||||
|
scp->state = SSH_SCP_ERROR;
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
if(code != 0){
|
|
||||||
ssh_set_error(scp->session,SSH_FATAL, "scp status code %ud not valid", code);
|
|
||||||
scp->state=SSH_SCP_ERROR;
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
scp->processed=scp->filelen=0;
|
scp->processed=scp->filelen=0;
|
||||||
scp->state=SSH_SCP_WRITE_INITED;
|
scp->state=SSH_SCP_WRITE_INITED;
|
||||||
}
|
}
|
||||||
@@ -461,16 +469,20 @@ int ssh_scp_read_string(ssh_scp scp, char *buffer, size_t len){
|
|||||||
*
|
*
|
||||||
* @returns SSH_SCP_REQUEST_NEWFILE: The other side is sending
|
* @returns SSH_SCP_REQUEST_NEWFILE: The other side is sending
|
||||||
* a file
|
* a file
|
||||||
* SSH_SCP_REQUEST_NEWDIRECTORY: The other side is sending
|
* SSH_SCP_REQUEST_NEWDIR: The other side is sending
|
||||||
* a directory
|
* a directory
|
||||||
* SSH_SCP_REQUEST_END_DIRECTORY: The other side has
|
* SSH_SCP_REQUEST_ENDDIR: The other side has
|
||||||
* finished with the current
|
* finished with the current
|
||||||
* directory
|
* directory
|
||||||
|
* SSH_SCP_REQUEST_WARNING: The other side sent us a warning
|
||||||
|
* SSH_SCP_REQUEST_EOF: The other side finished sending us
|
||||||
|
* files and data.
|
||||||
* SSH_ERROR: Some error happened
|
* SSH_ERROR: Some error happened
|
||||||
*
|
*
|
||||||
* @see ssh_scp_read()
|
* @see ssh_scp_read()
|
||||||
* @see ssh_scp_deny_request()
|
* @see ssh_scp_deny_request()
|
||||||
* @see ssh_scp_accept_request()
|
* @see ssh_scp_accept_request()
|
||||||
|
* @see ssh_scp_request_get_warning()
|
||||||
*/
|
*/
|
||||||
int ssh_scp_pull_request(ssh_scp scp){
|
int ssh_scp_pull_request(ssh_scp scp){
|
||||||
char buffer[4096];
|
char buffer[4096];
|
||||||
|
|||||||
28
src/server.c
28
src/server.c
@@ -59,8 +59,8 @@
|
|||||||
#include "libssh/messages.h"
|
#include "libssh/messages.h"
|
||||||
|
|
||||||
#define set_status(session, status) do {\
|
#define set_status(session, status) do {\
|
||||||
if (session->callbacks && session->callbacks->connect_status_function) \
|
if (session->common.callbacks && session->common.callbacks->connect_status_function) \
|
||||||
session->callbacks->connect_status_function(session->callbacks->userdata, status); \
|
session->common.callbacks->connect_status_function(session->common.callbacks->userdata, status); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static int dh_handshake_server(ssh_session session);
|
static int dh_handshake_server(ssh_session session);
|
||||||
@@ -104,7 +104,7 @@ static int server_set_kex(ssh_session session) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
server->methods = malloc(10 * sizeof(char **));
|
server->methods = (char **) malloc(10 * sizeof(char **));
|
||||||
if (server->methods == NULL) {
|
if (server->methods == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -184,7 +184,11 @@ static int dh_handshake_server(ssh_session session) {
|
|||||||
prv = session->rsa_key;
|
prv = session->rsa_key;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
prv = NULL;
|
ssh_set_error(session,
|
||||||
|
SSH_FATAL,
|
||||||
|
"Could not determine the specified hostkey");
|
||||||
|
ssh_string_free(f);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub = publickey_from_privatekey(prv);
|
pub = publickey_from_privatekey(prv);
|
||||||
@@ -270,6 +274,8 @@ static int dh_handshake_server(ssh_session session) {
|
|||||||
*/
|
*/
|
||||||
static void ssh_server_connection_callback(ssh_session session){
|
static void ssh_server_connection_callback(ssh_session session){
|
||||||
int ssh1,ssh2;
|
int ssh1,ssh2;
|
||||||
|
int rc;
|
||||||
|
|
||||||
enter_function();
|
enter_function();
|
||||||
switch(session->session_state){
|
switch(session->session_state){
|
||||||
case SSH_SESSION_STATE_NONE:
|
case SSH_SESSION_STATE_NONE:
|
||||||
@@ -338,7 +344,10 @@ static void ssh_server_connection_callback(ssh_session session){
|
|||||||
case SSH_SESSION_STATE_KEXINIT_RECEIVED:
|
case SSH_SESSION_STATE_KEXINIT_RECEIVED:
|
||||||
set_status(session,0.6f);
|
set_status(session,0.6f);
|
||||||
ssh_list_kex(session, &session->client_kex); // log client kex
|
ssh_list_kex(session, &session->client_kex); // log client kex
|
||||||
crypt_set_algorithms_server(session);
|
rc = crypt_set_algorithms_server(session);
|
||||||
|
if (rc == SSH_ERROR) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
if (set_kex(session) < 0) {
|
if (set_kex(session) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -479,8 +488,8 @@ int ssh_handle_key_exchange(ssh_session session) {
|
|||||||
* loop until SSH_SESSION_STATE_BANNER_RECEIVED or
|
* loop until SSH_SESSION_STATE_BANNER_RECEIVED or
|
||||||
* SSH_SESSION_STATE_ERROR
|
* SSH_SESSION_STATE_ERROR
|
||||||
*/
|
*/
|
||||||
ssh_handle_packets(session,-1);
|
ssh_handle_packets(session, -2);
|
||||||
ssh_log(session,SSH_LOG_PACKET, "ssh_accept: Actual state : %d",
|
ssh_log(session,SSH_LOG_PACKET, "ssh_handle_key_exchange: Actual state : %d",
|
||||||
session->session_state);
|
session->session_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -616,10 +625,13 @@ static int ssh_message_service_request_reply_default(ssh_message msg) {
|
|||||||
|
|
||||||
int ssh_message_service_reply_success(ssh_message msg) {
|
int ssh_message_service_reply_success(ssh_message msg) {
|
||||||
struct ssh_string_struct *service;
|
struct ssh_string_struct *service;
|
||||||
ssh_session session=msg->session;
|
ssh_session session;
|
||||||
|
|
||||||
if (msg == NULL) {
|
if (msg == NULL) {
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
session = msg->session;
|
||||||
|
|
||||||
ssh_log(session, SSH_LOG_PACKET,
|
ssh_log(session, SSH_LOG_PACKET,
|
||||||
"Sending a SERVICE_ACCEPT for service %s", msg->service_request.service);
|
"Sending a SERVICE_ACCEPT for service %s", msg->service_request.service);
|
||||||
if (buffer_add_u8(session->out_buffer, SSH2_MSG_SERVICE_ACCEPT) < 0) {
|
if (buffer_add_u8(session->out_buffer, SSH2_MSG_SERVICE_ACCEPT) < 0) {
|
||||||
|
|||||||
157
src/session.c
157
src/session.c
@@ -86,7 +86,7 @@ ssh_session ssh_new(void) {
|
|||||||
session->alive = 0;
|
session->alive = 0;
|
||||||
session->auth_methods = 0;
|
session->auth_methods = 0;
|
||||||
ssh_set_blocking(session, 1);
|
ssh_set_blocking(session, 1);
|
||||||
session->log_indent = 0;
|
session->common.log_indent = 0;
|
||||||
session->maxchannel = FIRST_CHANNEL;
|
session->maxchannel = FIRST_CHANNEL;
|
||||||
|
|
||||||
/* options */
|
/* options */
|
||||||
@@ -143,6 +143,7 @@ ssh_session ssh_new(void) {
|
|||||||
return session;
|
return session;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
free(id);
|
||||||
ssh_free(session);
|
ssh_free(session);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -157,16 +158,26 @@ err:
|
|||||||
*/
|
*/
|
||||||
void ssh_free(ssh_session session) {
|
void ssh_free(ssh_session session) {
|
||||||
int i;
|
int i;
|
||||||
enter_function();
|
struct ssh_iterator *it;
|
||||||
|
|
||||||
if (session == NULL) {
|
if (session == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SAFE_FREE(session->serverbanner);
|
/* delete all channels */
|
||||||
SAFE_FREE(session->clientbanner);
|
while ((it=ssh_list_get_iterator(session->channels)) != NULL) {
|
||||||
SAFE_FREE(session->bindaddr);
|
ssh_channel_free(ssh_iterator_value(ssh_channel,it));
|
||||||
SAFE_FREE(session->banner);
|
ssh_list_remove(session->channels, it);
|
||||||
|
}
|
||||||
|
ssh_list_free(session->channels);
|
||||||
|
session->channels=NULL;
|
||||||
|
|
||||||
|
ssh_socket_free(session->socket);
|
||||||
|
|
||||||
|
if (session->default_poll_ctx) {
|
||||||
|
ssh_poll_ctx_free(session->default_poll_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef WITH_PCAP
|
#ifdef WITH_PCAP
|
||||||
if(session->pcap_ctx){
|
if(session->pcap_ctx){
|
||||||
ssh_pcap_context_free(session->pcap_ctx);
|
ssh_pcap_context_free(session->pcap_ctx);
|
||||||
@@ -182,14 +193,6 @@ void ssh_free(ssh_session session) {
|
|||||||
session->in_buffer=session->out_buffer=NULL;
|
session->in_buffer=session->out_buffer=NULL;
|
||||||
crypto_free(session->current_crypto);
|
crypto_free(session->current_crypto);
|
||||||
crypto_free(session->next_crypto);
|
crypto_free(session->next_crypto);
|
||||||
ssh_socket_free(session->socket);
|
|
||||||
if(session->default_poll_ctx){
|
|
||||||
ssh_poll_ctx_free(session->default_poll_ctx);
|
|
||||||
}
|
|
||||||
/* delete all channels */
|
|
||||||
while (session->channels) {
|
|
||||||
ssh_channel_free(session->channels);
|
|
||||||
}
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
agent_free(session->agent);
|
agent_free(session->agent);
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
@@ -232,6 +235,11 @@ void ssh_free(ssh_session session) {
|
|||||||
ssh_list_free(session->identity);
|
ssh_list_free(session->identity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SAFE_FREE(session->serverbanner);
|
||||||
|
SAFE_FREE(session->clientbanner);
|
||||||
|
SAFE_FREE(session->bindaddr);
|
||||||
|
SAFE_FREE(session->banner);
|
||||||
|
|
||||||
/* options */
|
/* options */
|
||||||
SAFE_FREE(session->username);
|
SAFE_FREE(session->username);
|
||||||
SAFE_FREE(session->host);
|
SAFE_FREE(session->host);
|
||||||
@@ -297,6 +305,32 @@ int ssh_is_blocking(ssh_session session){
|
|||||||
return (session->flags&SSH_SESSION_FLAG_BLOCKING) ? 1 : 0;
|
return (session->flags&SSH_SESSION_FLAG_BLOCKING) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Blocking flush of the outgoing buffer
|
||||||
|
* @param[in] session The SSH session
|
||||||
|
* @param[in] timeout Set an upper limit on the time for which this function
|
||||||
|
* will block, in milliseconds. Specifying -1
|
||||||
|
* means an infinite timeout. This parameter is passed to
|
||||||
|
* the poll() function.
|
||||||
|
* @returns SSH_OK on success, SSH_AGAIN if timeout occurred,
|
||||||
|
* SSH_ERROR otherwise.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int ssh_blocking_flush(ssh_session session, int timeout){
|
||||||
|
ssh_socket s;
|
||||||
|
int rc = SSH_OK;
|
||||||
|
if(session==NULL)
|
||||||
|
return SSH_ERROR;
|
||||||
|
|
||||||
|
s=session->socket;
|
||||||
|
while (ssh_socket_buffered_write_bytes(s) > 0 && session->alive) {
|
||||||
|
rc = ssh_handle_packets(session, timeout);
|
||||||
|
if(rc == SSH_AGAIN || rc == SSH_ERROR) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check if we are connected.
|
* @brief Check if we are connected.
|
||||||
*
|
*
|
||||||
@@ -381,33 +415,50 @@ void ssh_set_fd_except(ssh_session session) {
|
|||||||
* @param[in] session The session handle to use.
|
* @param[in] session The session handle to use.
|
||||||
*
|
*
|
||||||
* @param[in] timeout Set an upper limit on the time for which this function
|
* @param[in] timeout Set an upper limit on the time for which this function
|
||||||
* will block, in milliseconds. Specifying a negative value
|
* will block, in milliseconds. Specifying -1
|
||||||
* means an infinite timeout. This parameter is passed to
|
* means an infinite timeout.
|
||||||
* the poll() function.
|
* Specifying -2 means to use the timeout specified in
|
||||||
|
* options. 0 means poll will return immediately. This
|
||||||
|
* parameter is passed to the poll() function.
|
||||||
*
|
*
|
||||||
* @return SSH_OK on success, SSH_ERROR otherwise.
|
* @return SSH_OK on success, SSH_ERROR otherwise.
|
||||||
*/
|
*/
|
||||||
int ssh_handle_packets(ssh_session session, int timeout) {
|
int ssh_handle_packets(ssh_session session, int timeout) {
|
||||||
ssh_poll_handle spoll_in,spoll_out;
|
ssh_poll_handle spoll_in,spoll_out;
|
||||||
ssh_poll_ctx ctx;
|
ssh_poll_ctx ctx;
|
||||||
if(session==NULL || session->socket==NULL)
|
int tm = timeout;
|
||||||
return SSH_ERROR;
|
int rc;
|
||||||
enter_function();
|
|
||||||
spoll_in=ssh_socket_get_poll_handle_in(session->socket);
|
if (session == NULL || session->socket == NULL) {
|
||||||
spoll_out=ssh_socket_get_poll_handle_out(session->socket);
|
return SSH_ERROR;
|
||||||
ctx=ssh_poll_get_ctx(spoll_in);
|
}
|
||||||
if(ctx==NULL){
|
enter_function();
|
||||||
ctx=ssh_poll_get_default_ctx(session);
|
|
||||||
ssh_poll_ctx_add(ctx,spoll_in);
|
spoll_in = ssh_socket_get_poll_handle_in(session->socket);
|
||||||
if(spoll_in != spoll_out)
|
spoll_out = ssh_socket_get_poll_handle_out(session->socket);
|
||||||
ssh_poll_ctx_add(ctx,spoll_out);
|
if (session->server) {
|
||||||
}
|
ssh_poll_add_events(spoll_in, POLLIN);
|
||||||
ssh_poll_ctx_dopoll(ctx,timeout);
|
}
|
||||||
leave_function();
|
ctx = ssh_poll_get_ctx(spoll_in);
|
||||||
if (session->session_state != SSH_SESSION_STATE_ERROR)
|
|
||||||
return SSH_OK;
|
if (!ctx) {
|
||||||
else
|
ctx = ssh_poll_get_default_ctx(session);
|
||||||
return SSH_ERROR;
|
ssh_poll_ctx_add(ctx, spoll_in);
|
||||||
|
if (spoll_in != spoll_out) {
|
||||||
|
ssh_poll_ctx_add(ctx, spoll_out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeout == -2) {
|
||||||
|
tm = ssh_make_milliseconds(session->timeout, session->timeout_usec);
|
||||||
|
}
|
||||||
|
rc = ssh_poll_ctx_dopoll(ctx, tm);
|
||||||
|
if (rc == SSH_ERROR) {
|
||||||
|
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
leave_function();
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -430,21 +481,22 @@ int ssh_handle_packets(ssh_session session, int timeout) {
|
|||||||
* @return SSH_OK on success, SSH_ERROR otherwise.
|
* @return SSH_OK on success, SSH_ERROR otherwise.
|
||||||
*/
|
*/
|
||||||
int ssh_handle_packets_termination(ssh_session session, int timeout,
|
int ssh_handle_packets_termination(ssh_session session, int timeout,
|
||||||
ssh_termination_function fct, void *user){
|
ssh_termination_function fct, void *user){
|
||||||
int ret = SSH_ERROR;
|
int ret = SSH_OK;
|
||||||
while(!fct(user)){
|
struct ssh_timestamp ts;
|
||||||
ret = ssh_handle_packets(session, timeout);
|
ssh_timestamp_init(&ts);
|
||||||
if(ret == SSH_ERROR)
|
while(!fct(user)){
|
||||||
return SSH_ERROR;
|
ret = ssh_handle_packets(session, timeout);
|
||||||
if(timeout == 0){
|
if(ret == SSH_ERROR || ret == SSH_AGAIN)
|
||||||
if(fct(user))
|
return ret;
|
||||||
return SSH_OK;
|
if(fct(user))
|
||||||
else
|
return SSH_OK;
|
||||||
return SSH_AGAIN;
|
else if(ssh_timeout_elapsed(&ts, timeout == -2 ? ssh_make_milliseconds(session->timeout, session->timeout_usec) : timeout))
|
||||||
}
|
/* it is possible that we get unrelated packets but still timeout our request,
|
||||||
/* TODO: verify that total timeout has not expired and then return SSH_AGAIN */
|
* so simply relying on the poll timeout is not enough */
|
||||||
}
|
return SSH_AGAIN;
|
||||||
return ret;
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -552,6 +604,7 @@ SSH_PACKET_CALLBACK(ssh_packet_disconnect_callback){
|
|||||||
|
|
||||||
ssh_socket_close(session->socket);
|
ssh_socket_close(session->socket);
|
||||||
session->alive = 0;
|
session->alive = 0;
|
||||||
|
session->session_state= SSH_SESSION_STATE_ERROR;
|
||||||
/* TODO: handle a graceful disconnect */
|
/* TODO: handle a graceful disconnect */
|
||||||
return SSH_PACKET_USED;
|
return SSH_PACKET_USED;
|
||||||
}
|
}
|
||||||
|
|||||||
55
src/sftp.c
55
src/sftp.c
@@ -35,6 +35,7 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#else
|
#else
|
||||||
#define S_IFSOCK 0140000
|
#define S_IFSOCK 0140000
|
||||||
@@ -668,10 +669,18 @@ int sftp_extension_supported(sftp_session sftp, const char *name,
|
|||||||
const char *data) {
|
const char *data) {
|
||||||
int i, n;
|
int i, n;
|
||||||
|
|
||||||
|
if (sftp == NULL || name == NULL || data == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
n = sftp_extensions_get_count(sftp);
|
n = sftp_extensions_get_count(sftp);
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
if (strcmp(sftp_extensions_get_name(sftp, i), name) == 0 &&
|
const char *ext_name = sftp_extensions_get_name(sftp, i);
|
||||||
strcmp(sftp_extensions_get_data(sftp, i), data) == 0) {
|
const char *ext_data = sftp_extensions_get_data(sftp, i);
|
||||||
|
|
||||||
|
if (ext_name != NULL && ext_data != NULL &&
|
||||||
|
strcmp(ext_name, name) == 0 &&
|
||||||
|
strcmp(ext_data, data) == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -939,6 +948,7 @@ sftp_dir sftp_opendir(sftp_session sftp, const char *path){
|
|||||||
dir = malloc(sizeof(struct sftp_dir_struct));
|
dir = malloc(sizeof(struct sftp_dir_struct));
|
||||||
if (dir == NULL) {
|
if (dir == NULL) {
|
||||||
ssh_set_error_oom(sftp->session);
|
ssh_set_error_oom(sftp->session);
|
||||||
|
free(file);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ZERO_STRUCTP(dir);
|
ZERO_STRUCTP(dir);
|
||||||
@@ -1193,8 +1203,8 @@ static char *sftp_parse_longname(const char *longname,
|
|||||||
so that number of pairs equals extended_count */
|
so that number of pairs equals extended_count */
|
||||||
static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf,
|
static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf,
|
||||||
int expectname) {
|
int expectname) {
|
||||||
ssh_string longname = NULL;
|
ssh_string longname;
|
||||||
ssh_string name = NULL;
|
ssh_string name;
|
||||||
sftp_attributes attr;
|
sftp_attributes attr;
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
@@ -1209,19 +1219,27 @@ static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf,
|
|||||||
/* This isn't really a loop, but it is like a try..catch.. */
|
/* This isn't really a loop, but it is like a try..catch.. */
|
||||||
do {
|
do {
|
||||||
if (expectname) {
|
if (expectname) {
|
||||||
if ((name = buffer_get_ssh_string(buf)) == NULL ||
|
name = buffer_get_ssh_string(buf);
|
||||||
(attr->name = ssh_string_to_char(name)) == NULL) {
|
if (name == NULL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
attr->name = ssh_string_to_char(name);
|
||||||
ssh_string_free(name);
|
ssh_string_free(name);
|
||||||
|
if (attr->name == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ssh_log(sftp->session, SSH_LOG_RARE, "Name: %s", attr->name);
|
ssh_log(sftp->session, SSH_LOG_RARE, "Name: %s", attr->name);
|
||||||
|
|
||||||
if ((longname=buffer_get_ssh_string(buf)) == NULL ||
|
longname = buffer_get_ssh_string(buf);
|
||||||
(attr->longname=ssh_string_to_char(longname)) == NULL) {
|
if (longname == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
attr->longname = ssh_string_to_char(longname);
|
||||||
|
ssh_string_free(longname);
|
||||||
|
if (attr->longname == NULL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ssh_string_free(longname);
|
|
||||||
|
|
||||||
/* Set owner and group if we talk to openssh and have the longname */
|
/* Set owner and group if we talk to openssh and have the longname */
|
||||||
if (ssh_get_openssh_version(sftp->session)) {
|
if (ssh_get_openssh_version(sftp->session)) {
|
||||||
@@ -1326,8 +1344,6 @@ static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf,
|
|||||||
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
/* break issued somewhere */
|
/* break issued somewhere */
|
||||||
ssh_string_free(name);
|
|
||||||
ssh_string_free(longname);
|
|
||||||
ssh_string_free(attr->extended_type);
|
ssh_string_free(attr->extended_type);
|
||||||
ssh_string_free(attr->extended_data);
|
ssh_string_free(attr->extended_data);
|
||||||
SAFE_FREE(attr->name);
|
SAFE_FREE(attr->name);
|
||||||
@@ -1817,7 +1833,7 @@ ssize_t sftp_read(sftp_file handle, void *buf, size_t count) {
|
|||||||
if (ssh_string_len(datastring) > count) {
|
if (ssh_string_len(datastring) > count) {
|
||||||
ssh_set_error(sftp->session, SSH_FATAL,
|
ssh_set_error(sftp->session, SSH_FATAL,
|
||||||
"Received a too big DATA packet from sftp server: "
|
"Received a too big DATA packet from sftp server: "
|
||||||
"%zu and asked for %zu",
|
"%" PRIdS " and asked for %" PRIdS,
|
||||||
ssh_string_len(datastring), count);
|
ssh_string_len(datastring), count);
|
||||||
ssh_string_free(datastring);
|
ssh_string_free(datastring);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1938,16 +1954,15 @@ int sftp_async_read(sftp_file file, void *data, uint32_t size, uint32_t id){
|
|||||||
if (ssh_string_len(datastring) > size) {
|
if (ssh_string_len(datastring) > size) {
|
||||||
ssh_set_error(sftp->session, SSH_FATAL,
|
ssh_set_error(sftp->session, SSH_FATAL,
|
||||||
"Received a too big DATA packet from sftp server: "
|
"Received a too big DATA packet from sftp server: "
|
||||||
"%zu and asked for %u",
|
"%" PRIdS " and asked for %u",
|
||||||
ssh_string_len(datastring), size);
|
ssh_string_len(datastring), size);
|
||||||
ssh_string_free(datastring);
|
ssh_string_free(datastring);
|
||||||
sftp_leave_function();
|
sftp_leave_function();
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
len = ssh_string_len(datastring);
|
len = ssh_string_len(datastring);
|
||||||
//handle->offset+=len;
|
/* Update the offset with the correct value */
|
||||||
/* We already have set the offset previously. All we can do is warn that the expected len
|
file->offset = file->offset - (size - len);
|
||||||
* and effective lengths are different */
|
|
||||||
memcpy(data, ssh_string_data(datastring), len);
|
memcpy(data, ssh_string_data(datastring), len);
|
||||||
ssh_string_free(datastring);
|
ssh_string_free(datastring);
|
||||||
sftp_leave_function();
|
sftp_leave_function();
|
||||||
@@ -2054,6 +2069,7 @@ int sftp_seek(sftp_file file, uint32_t new_offset) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
file->offset = new_offset;
|
file->offset = new_offset;
|
||||||
|
file->eof = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -2064,6 +2080,7 @@ int sftp_seek64(sftp_file file, uint64_t new_offset) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
file->offset = new_offset;
|
file->offset = new_offset;
|
||||||
|
file->eof = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -2080,6 +2097,7 @@ uint64_t sftp_tell64(sftp_file file) {
|
|||||||
/* Rewinds the position of the file pointer to the beginning of the file.*/
|
/* Rewinds the position of the file pointer to the beginning of the file.*/
|
||||||
void sftp_rewind(sftp_file file) {
|
void sftp_rewind(sftp_file file) {
|
||||||
file->offset = 0;
|
file->offset = 0;
|
||||||
|
file->eof = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* code written by Nick */
|
/* code written by Nick */
|
||||||
@@ -2109,10 +2127,12 @@ int sftp_unlink(sftp_session sftp, const char *file) {
|
|||||||
ssh_set_error_oom(sftp->session);
|
ssh_set_error_oom(sftp->session);
|
||||||
ssh_buffer_free(buffer);
|
ssh_buffer_free(buffer);
|
||||||
ssh_string_free(filename);
|
ssh_string_free(filename);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
if (sftp_packet_write(sftp, SSH_FXP_REMOVE, buffer) < 0) {
|
if (sftp_packet_write(sftp, SSH_FXP_REMOVE, buffer) < 0) {
|
||||||
ssh_buffer_free(buffer);
|
ssh_buffer_free(buffer);
|
||||||
ssh_string_free(filename);
|
ssh_string_free(filename);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
ssh_string_free(filename);
|
ssh_string_free(filename);
|
||||||
ssh_buffer_free(buffer);
|
ssh_buffer_free(buffer);
|
||||||
@@ -2265,6 +2285,7 @@ int sftp_mkdir(sftp_session sftp, const char *directory, mode_t mode) {
|
|||||||
sftp_packet_write(sftp, SSH_FXP_MKDIR, buffer) < 0) {
|
sftp_packet_write(sftp, SSH_FXP_MKDIR, buffer) < 0) {
|
||||||
ssh_buffer_free(buffer);
|
ssh_buffer_free(buffer);
|
||||||
ssh_string_free(path);
|
ssh_string_free(path);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
ssh_buffer_free(buffer);
|
ssh_buffer_free(buffer);
|
||||||
ssh_string_free(path);
|
ssh_string_free(path);
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -37,6 +38,7 @@
|
|||||||
#include "libssh/misc.h"
|
#include "libssh/misc.h"
|
||||||
|
|
||||||
sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
||||||
|
ssh_session session = sftp->session;
|
||||||
sftp_packet packet;
|
sftp_packet packet;
|
||||||
sftp_client_message msg;
|
sftp_client_message msg;
|
||||||
ssh_buffer payload;
|
ssh_buffer payload;
|
||||||
@@ -44,12 +46,14 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
|||||||
|
|
||||||
msg = malloc(sizeof (struct sftp_client_message_struct));
|
msg = malloc(sizeof (struct sftp_client_message_struct));
|
||||||
if (msg == NULL) {
|
if (msg == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ZERO_STRUCTP(msg);
|
ZERO_STRUCTP(msg);
|
||||||
|
|
||||||
packet = sftp_packet_read(sftp);
|
packet = sftp_packet_read(sftp);
|
||||||
if (packet == NULL) {
|
if (packet == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
sftp_client_message_free(msg);
|
sftp_client_message_free(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -65,6 +69,7 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
|||||||
case SSH_FXP_READDIR:
|
case SSH_FXP_READDIR:
|
||||||
msg->handle = buffer_get_ssh_string(payload);
|
msg->handle = buffer_get_ssh_string(payload);
|
||||||
if (msg->handle == NULL) {
|
if (msg->handle == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
sftp_client_message_free(msg);
|
sftp_client_message_free(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -72,6 +77,7 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
|||||||
case SSH_FXP_READ:
|
case SSH_FXP_READ:
|
||||||
msg->handle = buffer_get_ssh_string(payload);
|
msg->handle = buffer_get_ssh_string(payload);
|
||||||
if (msg->handle == NULL) {
|
if (msg->handle == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
sftp_client_message_free(msg);
|
sftp_client_message_free(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -81,12 +87,14 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
|||||||
case SSH_FXP_WRITE:
|
case SSH_FXP_WRITE:
|
||||||
msg->handle = buffer_get_ssh_string(payload);
|
msg->handle = buffer_get_ssh_string(payload);
|
||||||
if (msg->handle == NULL) {
|
if (msg->handle == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
sftp_client_message_free(msg);
|
sftp_client_message_free(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
buffer_get_u64(payload, &msg->offset);
|
buffer_get_u64(payload, &msg->offset);
|
||||||
msg->data = buffer_get_ssh_string(payload);
|
msg->data = buffer_get_ssh_string(payload);
|
||||||
if (msg->data == NULL) {
|
if (msg->data == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
sftp_client_message_free(msg);
|
sftp_client_message_free(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -98,12 +106,14 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
|||||||
case SSH_FXP_REALPATH:
|
case SSH_FXP_REALPATH:
|
||||||
tmp = buffer_get_ssh_string(payload);
|
tmp = buffer_get_ssh_string(payload);
|
||||||
if (tmp == NULL) {
|
if (tmp == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
sftp_client_message_free(msg);
|
sftp_client_message_free(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
msg->filename = ssh_string_to_char(tmp);
|
msg->filename = ssh_string_to_char(tmp);
|
||||||
ssh_string_free(tmp);
|
ssh_string_free(tmp);
|
||||||
if (msg->filename == NULL) {
|
if (msg->filename == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
sftp_client_message_free(msg);
|
sftp_client_message_free(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -112,17 +122,20 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
|||||||
case SSH_FXP_SYMLINK:
|
case SSH_FXP_SYMLINK:
|
||||||
tmp = buffer_get_ssh_string(payload);
|
tmp = buffer_get_ssh_string(payload);
|
||||||
if (tmp == NULL) {
|
if (tmp == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
sftp_client_message_free(msg);
|
sftp_client_message_free(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
msg->filename = ssh_string_to_char(tmp);
|
msg->filename = ssh_string_to_char(tmp);
|
||||||
ssh_string_free(tmp);
|
ssh_string_free(tmp);
|
||||||
if (msg->filename == NULL) {
|
if (msg->filename == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
sftp_client_message_free(msg);
|
sftp_client_message_free(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
msg->data = buffer_get_ssh_string(payload);
|
msg->data = buffer_get_ssh_string(payload);
|
||||||
if (msg->data == NULL) {
|
if (msg->data == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
sftp_client_message_free(msg);
|
sftp_client_message_free(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -131,17 +144,20 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
|||||||
case SSH_FXP_SETSTAT:
|
case SSH_FXP_SETSTAT:
|
||||||
tmp = buffer_get_ssh_string(payload);
|
tmp = buffer_get_ssh_string(payload);
|
||||||
if (tmp == NULL) {
|
if (tmp == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
sftp_client_message_free(msg);
|
sftp_client_message_free(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
msg->filename=ssh_string_to_char(tmp);
|
msg->filename=ssh_string_to_char(tmp);
|
||||||
ssh_string_free(tmp);
|
ssh_string_free(tmp);
|
||||||
if (msg->filename == NULL) {
|
if (msg->filename == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
sftp_client_message_free(msg);
|
sftp_client_message_free(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
msg->attr = sftp_parse_attr(sftp, payload, 0);
|
msg->attr = sftp_parse_attr(sftp, payload, 0);
|
||||||
if (msg->attr == NULL) {
|
if (msg->attr == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
sftp_client_message_free(msg);
|
sftp_client_message_free(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -149,11 +165,13 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
|||||||
case SSH_FXP_FSETSTAT:
|
case SSH_FXP_FSETSTAT:
|
||||||
msg->handle = buffer_get_ssh_string(payload);
|
msg->handle = buffer_get_ssh_string(payload);
|
||||||
if (msg->handle == NULL) {
|
if (msg->handle == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
sftp_client_message_free(msg);
|
sftp_client_message_free(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
msg->attr = sftp_parse_attr(sftp, payload, 0);
|
msg->attr = sftp_parse_attr(sftp, payload, 0);
|
||||||
if (msg->attr == NULL) {
|
if (msg->attr == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
sftp_client_message_free(msg);
|
sftp_client_message_free(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -162,12 +180,14 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
|||||||
case SSH_FXP_STAT:
|
case SSH_FXP_STAT:
|
||||||
tmp = buffer_get_ssh_string(payload);
|
tmp = buffer_get_ssh_string(payload);
|
||||||
if (tmp == NULL) {
|
if (tmp == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
sftp_client_message_free(msg);
|
sftp_client_message_free(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
msg->filename = ssh_string_to_char(tmp);
|
msg->filename = ssh_string_to_char(tmp);
|
||||||
ssh_string_free(tmp);
|
ssh_string_free(tmp);
|
||||||
if (msg->filename == NULL) {
|
if (msg->filename == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
sftp_client_message_free(msg);
|
sftp_client_message_free(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -178,31 +198,38 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
|||||||
case SSH_FXP_OPEN:
|
case SSH_FXP_OPEN:
|
||||||
tmp=buffer_get_ssh_string(payload);
|
tmp=buffer_get_ssh_string(payload);
|
||||||
if (tmp == NULL) {
|
if (tmp == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
sftp_client_message_free(msg);
|
sftp_client_message_free(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
msg->filename = ssh_string_to_char(tmp);
|
msg->filename = ssh_string_to_char(tmp);
|
||||||
ssh_string_free(tmp);
|
ssh_string_free(tmp);
|
||||||
if (msg->filename == NULL) {
|
if (msg->filename == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
sftp_client_message_free(msg);
|
sftp_client_message_free(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
buffer_get_u32(payload,&msg->flags);
|
buffer_get_u32(payload,&msg->flags);
|
||||||
msg->attr = sftp_parse_attr(sftp, payload, 0);
|
msg->attr = sftp_parse_attr(sftp, payload, 0);
|
||||||
if (msg->attr == NULL) {
|
if (msg->attr == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
sftp_client_message_free(msg);
|
sftp_client_message_free(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
case SSH_FXP_FSTAT:
|
case SSH_FXP_FSTAT:
|
||||||
msg->handle = buffer_get_ssh_string(payload);
|
msg->handle = buffer_get_ssh_string(payload);
|
||||||
if (msg->handle == NULL) {
|
if (msg->handle == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
sftp_client_message_free(msg);
|
sftp_client_message_free(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
buffer_get_u32(payload, &msg->flags);
|
buffer_get_u32(payload, &msg->flags);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Received unhandled sftp message %d\n", msg->type);
|
ssh_set_error(sftp->session, SSH_FATAL,
|
||||||
|
"Received unhandled sftp message %d\n", msg->type);
|
||||||
|
sftp_client_message_free(msg);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg->flags = ntohl(msg->flags);
|
msg->flags = ntohl(msg->flags);
|
||||||
|
|||||||
113
src/socket.c
113
src/socket.c
@@ -91,6 +91,8 @@ struct ssh_socket_struct {
|
|||||||
ssh_poll_handle poll_out;
|
ssh_poll_handle poll_out;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int sockets_initialized = 0;
|
||||||
|
|
||||||
static int ssh_socket_unbuffered_read(ssh_socket s, void *buffer, uint32_t len);
|
static int ssh_socket_unbuffered_read(ssh_socket s, void *buffer, uint32_t len);
|
||||||
static int ssh_socket_unbuffered_write(ssh_socket s, const void *buffer,
|
static int ssh_socket_unbuffered_write(ssh_socket s, const void *buffer,
|
||||||
uint32_t len);
|
uint32_t len);
|
||||||
@@ -100,16 +102,20 @@ static int ssh_socket_unbuffered_write(ssh_socket s, const void *buffer,
|
|||||||
* \brief inits the socket system (windows specific)
|
* \brief inits the socket system (windows specific)
|
||||||
*/
|
*/
|
||||||
int ssh_socket_init(void) {
|
int ssh_socket_init(void) {
|
||||||
|
if (sockets_initialized == 0) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
struct WSAData wsaData;
|
struct WSAData wsaData;
|
||||||
|
|
||||||
/* Initiates use of the Winsock DLL by a process. */
|
/* Initiates use of the Winsock DLL by a process. */
|
||||||
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
|
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
ssh_poll_init();
|
ssh_poll_init();
|
||||||
|
|
||||||
|
sockets_initialized = 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -118,7 +124,13 @@ int ssh_socket_init(void) {
|
|||||||
* @brief Cleanup the socket system.
|
* @brief Cleanup the socket system.
|
||||||
*/
|
*/
|
||||||
void ssh_socket_cleanup(void) {
|
void ssh_socket_cleanup(void) {
|
||||||
|
if (sockets_initialized == 1) {
|
||||||
ssh_poll_cleanup();
|
ssh_poll_cleanup();
|
||||||
|
#ifdef _WIN32
|
||||||
|
WSACleanup();
|
||||||
|
#endif
|
||||||
|
sockets_initialized = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -131,6 +143,7 @@ ssh_socket ssh_socket_new(ssh_session session) {
|
|||||||
|
|
||||||
s = malloc(sizeof(struct ssh_socket_struct));
|
s = malloc(sizeof(struct ssh_socket_struct));
|
||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
s->fd_in = SSH_INVALID_SOCKET;
|
s->fd_in = SSH_INVALID_SOCKET;
|
||||||
@@ -140,11 +153,13 @@ ssh_socket ssh_socket_new(ssh_session session) {
|
|||||||
s->session = session;
|
s->session = session;
|
||||||
s->in_buffer = ssh_buffer_new();
|
s->in_buffer = ssh_buffer_new();
|
||||||
if (s->in_buffer == NULL) {
|
if (s->in_buffer == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
SAFE_FREE(s);
|
SAFE_FREE(s);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
s->out_buffer=ssh_buffer_new();
|
s->out_buffer=ssh_buffer_new();
|
||||||
if (s->out_buffer == NULL) {
|
if (s->out_buffer == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
ssh_buffer_free(s->in_buffer);
|
ssh_buffer_free(s->in_buffer);
|
||||||
SAFE_FREE(s);
|
SAFE_FREE(s);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -215,7 +230,7 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r
|
|||||||
/* Check if we are in a connecting state */
|
/* Check if we are in a connecting state */
|
||||||
if(s->state==SSH_SOCKET_CONNECTING){
|
if(s->state==SSH_SOCKET_CONNECTING){
|
||||||
s->state=SSH_SOCKET_ERROR;
|
s->state=SSH_SOCKET_ERROR;
|
||||||
getsockopt(fd,SOL_SOCKET,SO_ERROR,(void *)&err,&errlen);
|
getsockopt(fd,SOL_SOCKET,SO_ERROR,(char *)&err,&errlen);
|
||||||
s->last_errno=err;
|
s->last_errno=err;
|
||||||
ssh_socket_close(s);
|
ssh_socket_close(s);
|
||||||
if(s->callbacks && s->callbacks->connected)
|
if(s->callbacks && s->callbacks->connected)
|
||||||
@@ -231,20 +246,34 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r
|
|||||||
s->read_wontblock=1;
|
s->read_wontblock=1;
|
||||||
r=ssh_socket_unbuffered_read(s,buffer,sizeof(buffer));
|
r=ssh_socket_unbuffered_read(s,buffer,sizeof(buffer));
|
||||||
if(r<0){
|
if(r<0){
|
||||||
if(p != NULL)
|
if(p != NULL) {
|
||||||
ssh_poll_set_events(p,ssh_poll_get_events(p) & ~POLLIN);
|
ssh_poll_remove_events(p, POLLIN);
|
||||||
|
}
|
||||||
if(s->callbacks && s->callbacks->exception){
|
if(s->callbacks && s->callbacks->exception){
|
||||||
s->callbacks->exception(
|
s->callbacks->exception(
|
||||||
SSH_SOCKET_EXCEPTION_ERROR,
|
SSH_SOCKET_EXCEPTION_ERROR,
|
||||||
s->last_errno,s->callbacks->userdata);
|
s->last_errno,s->callbacks->userdata);
|
||||||
|
/* p may have been freed, so don't use it
|
||||||
|
* anymore in this function */
|
||||||
|
p = NULL;
|
||||||
|
return -2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(r==0){
|
if(r==0){
|
||||||
ssh_poll_set_events(p,ssh_poll_get_events(p) & ~POLLIN);
|
if(p != NULL) {
|
||||||
|
ssh_poll_remove_events(p, POLLIN);
|
||||||
|
}
|
||||||
|
if(p != NULL) {
|
||||||
|
ssh_poll_remove_events(p, POLLIN);
|
||||||
|
}
|
||||||
if(s->callbacks && s->callbacks->exception){
|
if(s->callbacks && s->callbacks->exception){
|
||||||
s->callbacks->exception(
|
s->callbacks->exception(
|
||||||
SSH_SOCKET_EXCEPTION_EOF,
|
SSH_SOCKET_EXCEPTION_EOF,
|
||||||
0,s->callbacks->userdata);
|
0,s->callbacks->userdata);
|
||||||
|
/* p may have been freed, so don't use it
|
||||||
|
* anymore in this function */
|
||||||
|
p = NULL;
|
||||||
|
return -2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(r>0){
|
if(r>0){
|
||||||
@@ -255,6 +284,9 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r
|
|||||||
buffer_get_rest_len(s->in_buffer),
|
buffer_get_rest_len(s->in_buffer),
|
||||||
s->callbacks->userdata);
|
s->callbacks->userdata);
|
||||||
buffer_pass_bytes(s->in_buffer,r);
|
buffer_pass_bytes(s->in_buffer,r);
|
||||||
|
/* p may have been freed, so don't use it
|
||||||
|
* anymore in this function */
|
||||||
|
p = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -267,7 +299,7 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r
|
|||||||
if(s->state == SSH_SOCKET_CONNECTING){
|
if(s->state == SSH_SOCKET_CONNECTING){
|
||||||
ssh_log(s->session,SSH_LOG_PACKET,"Received POLLOUT in connecting state");
|
ssh_log(s->session,SSH_LOG_PACKET,"Received POLLOUT in connecting state");
|
||||||
s->state = SSH_SOCKET_CONNECTED;
|
s->state = SSH_SOCKET_CONNECTED;
|
||||||
ssh_poll_set_events(p,POLLOUT | POLLIN | POLLERR);
|
ssh_poll_set_events(p,POLLOUT | POLLIN);
|
||||||
ssh_sock_set_blocking(ssh_socket_get_fd_in(s));
|
ssh_sock_set_blocking(ssh_socket_get_fd_in(s));
|
||||||
if(s->callbacks && s->callbacks->connected)
|
if(s->callbacks && s->callbacks->connected)
|
||||||
s->callbacks->connected(SSH_SOCKET_CONNECTED_OK,0,s->callbacks->userdata);
|
s->callbacks->connected(SSH_SOCKET_CONNECTED_OK,0,s->callbacks->userdata);
|
||||||
@@ -275,7 +307,9 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r
|
|||||||
}
|
}
|
||||||
/* So, we can write data */
|
/* So, we can write data */
|
||||||
s->write_wontblock=1;
|
s->write_wontblock=1;
|
||||||
ssh_poll_remove_events(p,POLLOUT);
|
if(p != NULL) {
|
||||||
|
ssh_poll_remove_events(p, POLLOUT);
|
||||||
|
}
|
||||||
|
|
||||||
/* If buffered data is pending, write it */
|
/* If buffered data is pending, write it */
|
||||||
if(buffer_get_rest_len(s->out_buffer) > 0){
|
if(buffer_get_rest_len(s->out_buffer) > 0){
|
||||||
@@ -340,16 +374,24 @@ int ssh_socket_unix(ssh_socket s, const char *path) {
|
|||||||
|
|
||||||
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
if (fd == SSH_INVALID_SOCKET) {
|
if (fd == SSH_INVALID_SOCKET) {
|
||||||
|
ssh_set_error(s->session, SSH_FATAL,
|
||||||
|
"Error from socket(AF_UNIX, SOCK_STREAM, 0): %s",
|
||||||
|
strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fcntl(fd, F_SETFD, 1) == -1) {
|
if (fcntl(fd, F_SETFD, 1) == -1) {
|
||||||
|
ssh_set_error(s->session, SSH_FATAL,
|
||||||
|
"Error from fcntl(fd, F_SETFD, 1): %s",
|
||||||
|
strerror(errno));
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connect(fd, (struct sockaddr *) &sunaddr,
|
if (connect(fd, (struct sockaddr *) &sunaddr,
|
||||||
sizeof(sunaddr)) < 0) {
|
sizeof(sunaddr)) < 0) {
|
||||||
|
ssh_set_error(s->session, SSH_FATAL, "Error from connect(): %s",
|
||||||
|
strerror(errno));
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -544,6 +586,7 @@ int ssh_socket_write(ssh_socket s, const void *buffer, int len) {
|
|||||||
enter_function();
|
enter_function();
|
||||||
if(len > 0) {
|
if(len > 0) {
|
||||||
if (buffer_add_data(s->out_buffer, buffer, len) < 0) {
|
if (buffer_add_data(s->out_buffer, buffer, len) < 0) {
|
||||||
|
ssh_set_error_oom(s->session);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
ssh_socket_nonblocking_flush(s);
|
ssh_socket_nonblocking_flush(s);
|
||||||
@@ -632,6 +675,18 @@ int ssh_socket_data_writable(ssh_socket s) {
|
|||||||
return s->write_wontblock;
|
return s->write_wontblock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @internal
|
||||||
|
* @brief returns the number of outgoing bytes currently buffered
|
||||||
|
* @param s the socket
|
||||||
|
* @returns numbers of bytes buffered, or 0 if the socket isn't connected
|
||||||
|
*/
|
||||||
|
int ssh_socket_buffered_write_bytes(ssh_socket s){
|
||||||
|
if(s==NULL || s->out_buffer == NULL)
|
||||||
|
return 0;
|
||||||
|
return buffer_get_rest_len(s->out_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int ssh_socket_get_status(ssh_socket s) {
|
int ssh_socket_get_status(ssh_socket s) {
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
@@ -646,6 +701,25 @@ int ssh_socket_get_status(ssh_socket s) {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @brief Set a socket into the connecting state
|
||||||
|
* @param s socket handle
|
||||||
|
* @param fd file descriptor
|
||||||
|
*/
|
||||||
|
|
||||||
|
void ssh_socket_set_connecting(ssh_socket s, int fd){
|
||||||
|
ssh_socket_set_fd(s,fd);
|
||||||
|
s->state=SSH_SOCKET_CONNECTING;
|
||||||
|
/* POLLOUT is the event to wait for in a nonblocking connect */
|
||||||
|
ssh_poll_set_events(ssh_socket_get_poll_handle_in(s),POLLOUT);
|
||||||
|
#ifdef _WIN32
|
||||||
|
ssh_poll_add_events(ssh_socket_get_poll_handle_in(s),POLLWRNORM);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
* @brief Launches a socket connection
|
* @brief Launches a socket connection
|
||||||
@@ -665,19 +739,16 @@ int ssh_socket_connect(ssh_socket s, const char *host, int port, const char *bin
|
|||||||
socket_t fd;
|
socket_t fd;
|
||||||
ssh_session session=s->session;
|
ssh_session session=s->session;
|
||||||
enter_function();
|
enter_function();
|
||||||
if(s->state != SSH_SOCKET_NONE)
|
if(s->state != SSH_SOCKET_NONE) {
|
||||||
|
ssh_set_error(s->session, SSH_FATAL,
|
||||||
|
"ssh_socket_connect called on socket not unconnected");
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
fd=ssh_connect_host_nonblocking(s->session,host,bind_addr,port);
|
fd=ssh_connect_host_nonblocking(s->session,host,bind_addr,port);
|
||||||
ssh_log(session,SSH_LOG_PROTOCOL,"Nonblocking connection socket: %d",fd);
|
ssh_log(session,SSH_LOG_PROTOCOL,"Nonblocking connection socket: %d",fd);
|
||||||
if(fd == SSH_INVALID_SOCKET)
|
if(fd == SSH_INVALID_SOCKET)
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
ssh_socket_set_fd(s,fd);
|
ssh_socket_set_connecting(s,fd);
|
||||||
s->state=SSH_SOCKET_CONNECTING;
|
|
||||||
/* POLLOUT is the event to wait for in a nonblocking connect */
|
|
||||||
ssh_poll_set_events(ssh_socket_get_poll_handle_in(s),POLLOUT);
|
|
||||||
#ifdef _WIN32
|
|
||||||
ssh_poll_add_events(ssh_socket_get_poll_handle_in(s),POLLWRNORM);
|
|
||||||
#endif
|
|
||||||
leave_function();
|
leave_function();
|
||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
@@ -744,7 +815,7 @@ int ssh_socket_connect_proxycommand(ssh_socket s, const char *command){
|
|||||||
s->state=SSH_SOCKET_CONNECTED;
|
s->state=SSH_SOCKET_CONNECTED;
|
||||||
s->fd_is_socket=0;
|
s->fd_is_socket=0;
|
||||||
/* POLLOUT is the event to wait for in a nonblocking connect */
|
/* POLLOUT is the event to wait for in a nonblocking connect */
|
||||||
ssh_poll_set_events(ssh_socket_get_poll_handle_in(s),POLLIN | POLLERR);
|
ssh_poll_set_events(ssh_socket_get_poll_handle_in(s),POLLIN);
|
||||||
ssh_poll_set_events(ssh_socket_get_poll_handle_out(s),POLLOUT);
|
ssh_poll_set_events(ssh_socket_get_poll_handle_out(s),POLLOUT);
|
||||||
if(s->callbacks && s->callbacks->connected)
|
if(s->callbacks && s->callbacks->connected)
|
||||||
s->callbacks->connected(SSH_SOCKET_CONNECTED_OK,0,s->callbacks->userdata);
|
s->callbacks->connected(SSH_SOCKET_CONNECTED_OK,0,s->callbacks->userdata);
|
||||||
|
|||||||
45
src/string.c
45
src/string.c
@@ -21,10 +21,13 @@
|
|||||||
* MA 02111-1307, USA.
|
* MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -50,7 +53,11 @@
|
|||||||
struct ssh_string_struct *ssh_string_new(size_t size) {
|
struct ssh_string_struct *ssh_string_new(size_t size) {
|
||||||
struct ssh_string_struct *str = NULL;
|
struct ssh_string_struct *str = NULL;
|
||||||
|
|
||||||
str = malloc(size + 4);
|
if (size > UINT_MAX - sizeof(struct ssh_string_struct)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
str = malloc(sizeof(struct ssh_string_struct) + size);
|
||||||
if (str == NULL) {
|
if (str == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -91,8 +98,15 @@ int ssh_string_fill(struct ssh_string_struct *s, const void *data, size_t len) {
|
|||||||
* @note The nul byte is not copied nor counted in the ouput string.
|
* @note The nul byte is not copied nor counted in the ouput string.
|
||||||
*/
|
*/
|
||||||
struct ssh_string_struct *ssh_string_from_char(const char *what) {
|
struct ssh_string_struct *ssh_string_from_char(const char *what) {
|
||||||
struct ssh_string_struct *ptr = NULL;
|
struct ssh_string_struct *ptr;
|
||||||
size_t len = strlen(what);
|
size_t len;
|
||||||
|
|
||||||
|
if(what == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = strlen(what);
|
||||||
|
|
||||||
ptr = malloc(4 + len);
|
ptr = malloc(4 + len);
|
||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
@@ -133,16 +147,22 @@ size_t ssh_string_len(struct ssh_string_struct *s) {
|
|||||||
char *ssh_string_to_char(struct ssh_string_struct *s) {
|
char *ssh_string_to_char(struct ssh_string_struct *s) {
|
||||||
size_t len;
|
size_t len;
|
||||||
char *new;
|
char *new;
|
||||||
if(s==NULL)
|
if (s == NULL || s->string == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
len = ntohl(s->size) + 1;
|
}
|
||||||
new = malloc(len);
|
|
||||||
|
|
||||||
|
len = ssh_string_len(s);
|
||||||
|
if (len + 1 < len) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
new = malloc(len + 1);
|
||||||
if (new == NULL) {
|
if (new == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memcpy(new, s->string, len - 1);
|
memcpy(new, s->string, len);
|
||||||
new[len - 1] = '\0';
|
new[len] = '\0';
|
||||||
|
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +184,12 @@ void ssh_string_free_char(char *s) {
|
|||||||
* @return Newly allocated copy of the string, NULL on error.
|
* @return Newly allocated copy of the string, NULL on error.
|
||||||
*/
|
*/
|
||||||
struct ssh_string_struct *ssh_string_copy(struct ssh_string_struct *s) {
|
struct ssh_string_struct *ssh_string_copy(struct ssh_string_struct *s) {
|
||||||
struct ssh_string_struct *new = malloc(ntohl(s->size) + 4);
|
struct ssh_string_struct *new;
|
||||||
|
|
||||||
|
if(s == NULL || s->string == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
new = malloc(ntohl(s->size) + 4);
|
||||||
|
|
||||||
if (new == NULL) {
|
if (new == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ static void libcrypto_lock_callback(int mode, int i, const char *file, int line)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int libcrypto_thread_init(){
|
static int libcrypto_thread_init(void){
|
||||||
int n=CRYPTO_num_locks();
|
int n=CRYPTO_num_locks();
|
||||||
int i;
|
int i;
|
||||||
if(user_callbacks == &ssh_threads_noop)
|
if(user_callbacks == &ssh_threads_noop)
|
||||||
@@ -109,7 +109,7 @@ static int libcrypto_thread_init(){
|
|||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void libcrypto_thread_finalize(){
|
static void libcrypto_thread_finalize(void){
|
||||||
int n=CRYPTO_num_locks();
|
int n=CRYPTO_num_locks();
|
||||||
int i;
|
int i;
|
||||||
if (libcrypto_mutexes==NULL)
|
if (libcrypto_mutexes==NULL)
|
||||||
|
|||||||
@@ -86,6 +86,12 @@ install(
|
|||||||
if (WITH_STATIC_LIB)
|
if (WITH_STATIC_LIB)
|
||||||
add_library(${LIBSSH_THREADS_STATIC_LIBRARY} STATIC ${libssh_threads_SRCS})
|
add_library(${LIBSSH_THREADS_STATIC_LIBRARY} STATIC ${libssh_threads_SRCS})
|
||||||
|
|
||||||
|
if (MSVC)
|
||||||
|
set(OUTPUT_SUFFIX static)
|
||||||
|
else (MSVC)
|
||||||
|
set(OUTPUT_SUFFIX )
|
||||||
|
endif (MSVC)
|
||||||
|
|
||||||
set_target_properties(
|
set_target_properties(
|
||||||
${LIBSSH_THREADS_STATIC_LIBRARY}
|
${LIBSSH_THREADS_STATIC_LIBRARY}
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
@@ -93,15 +99,26 @@ if (WITH_STATIC_LIB)
|
|||||||
${LIBRARY_VERSION}
|
${LIBRARY_VERSION}
|
||||||
SOVERSION
|
SOVERSION
|
||||||
${LIBRARY_SOVERSION}
|
${LIBRARY_SOVERSION}
|
||||||
COMPILE_FLAGS
|
OUTPUT_NAME
|
||||||
"-DLIBSSH_STATIC"
|
ssh_threads
|
||||||
|
ARCHIVE_OUTPUT_DIRECTORY
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_SUFFIX}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
set_target_properties(
|
||||||
|
${LIBSSH_THREADS_STATIC_LIBRARY}
|
||||||
|
PROPERTIES
|
||||||
|
COMPILE_FLAGS
|
||||||
|
"-DLIBSSH_STATIC"
|
||||||
|
)
|
||||||
|
endif (WIN32)
|
||||||
|
|
||||||
install(
|
install(
|
||||||
TARGETS
|
TARGETS
|
||||||
${LIBSSH_THREADS_STATIC_LIBRARY}
|
${LIBSSH_THREADS_STATIC_LIBRARY}
|
||||||
DESTINATION
|
DESTINATION
|
||||||
${LIB_INSTALL_DIR}
|
${LIB_INSTALL_DIR}/${OUTPUT_SUFFIX}
|
||||||
COMPONENT
|
COMPONENT
|
||||||
libraries
|
libraries
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -38,6 +38,10 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef WITH_LIBZ
|
||||||
|
#include <zlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "libssh/priv.h"
|
#include "libssh/priv.h"
|
||||||
#include "libssh/session.h"
|
#include "libssh/session.h"
|
||||||
#include "libssh/crypto.h"
|
#include "libssh/crypto.h"
|
||||||
@@ -82,7 +86,7 @@ static void cipher_free(struct crypto_struct *cipher) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct ssh_crypto_struct *crypto_new(void) {
|
struct ssh_crypto_struct *crypto_new(void) {
|
||||||
struct ssh_crypto_struct *crypto;
|
struct ssh_crypto_struct *crypto;
|
||||||
|
|
||||||
crypto = malloc(sizeof(struct ssh_crypto_struct));
|
crypto = malloc(sizeof(struct ssh_crypto_struct));
|
||||||
if (crypto == NULL) {
|
if (crypto == NULL) {
|
||||||
@@ -108,6 +112,18 @@ void crypto_free(struct ssh_crypto_struct *crypto){
|
|||||||
bignum_free(crypto->y);
|
bignum_free(crypto->y);
|
||||||
bignum_free(crypto->k);
|
bignum_free(crypto->k);
|
||||||
/* lot of other things */
|
/* lot of other things */
|
||||||
|
|
||||||
|
#ifdef WITH_LIBZ
|
||||||
|
if (crypto->compress_out_ctx &&
|
||||||
|
(deflateEnd(crypto->compress_out_ctx) != 0)) {
|
||||||
|
inflateEnd(crypto->compress_out_ctx);
|
||||||
|
}
|
||||||
|
if (crypto->compress_in_ctx &&
|
||||||
|
(deflateEnd(crypto->compress_in_ctx) != 0)) {
|
||||||
|
inflateEnd(crypto->compress_in_ctx);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* i'm lost in my own code. good work */
|
/* i'm lost in my own code. good work */
|
||||||
memset(crypto,0,sizeof(*crypto));
|
memset(crypto,0,sizeof(*crypto));
|
||||||
|
|
||||||
@@ -219,11 +235,15 @@ int crypt_set_algorithms_server(ssh_session session){
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
struct crypto_struct *ssh_ciphertab=ssh_get_ciphertab();
|
struct crypto_struct *ssh_ciphertab=ssh_get_ciphertab();
|
||||||
|
|
||||||
|
if (session == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/* we must scan the kex entries to find crypto algorithms and set their appropriate structure */
|
/* we must scan the kex entries to find crypto algorithms and set their appropriate structure */
|
||||||
enter_function();
|
enter_function();
|
||||||
/* out */
|
/* out */
|
||||||
server = session->server_kex.methods[SSH_CRYPT_S_C];
|
server = session->server_kex.methods[SSH_CRYPT_S_C];
|
||||||
if(session && session->client_kex.methods) {
|
if(session->client_kex.methods) {
|
||||||
client = session->client_kex.methods[SSH_CRYPT_S_C];
|
client = session->client_kex.methods[SSH_CRYPT_S_C];
|
||||||
} else {
|
} else {
|
||||||
ssh_log(session,SSH_LOG_PROTOCOL, "Client KEX empty");
|
ssh_log(session,SSH_LOG_PROTOCOL, "Client KEX empty");
|
||||||
|
|||||||
@@ -75,12 +75,12 @@ int benchmarks_ping_latency (const char *host, float *average){
|
|||||||
}
|
}
|
||||||
if(!found)
|
if(!found)
|
||||||
goto parseerror;
|
goto parseerror;
|
||||||
fclose(fd);
|
pclose(fd);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
parseerror:
|
parseerror:
|
||||||
fprintf(stderr,"Parse error : couldn't locate average in %s",line);
|
fprintf(stderr,"Parse error : couldn't locate average in %s",line);
|
||||||
fclose(fd);
|
pclose(fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ static void torture_sftp_mkdir(void **state) {
|
|||||||
snprintf(tmpdir, sizeof(tmpdir), "%s/mkdir_test", t->testdir);
|
snprintf(tmpdir, sizeof(tmpdir), "%s/mkdir_test", t->testdir);
|
||||||
|
|
||||||
rc = sftp_mkdir(t->sftp, tmpdir, 0755);
|
rc = sftp_mkdir(t->sftp, tmpdir, 0755);
|
||||||
|
if(rc != SSH_OK)
|
||||||
|
fprintf(stderr,"error:%s\n",ssh_get_error(t->sftp->session));
|
||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
|
|
||||||
/* check if it really has been created */
|
/* check if it really has been created */
|
||||||
|
|||||||
@@ -21,13 +21,15 @@
|
|||||||
* MA 02111-1307, USA.
|
* MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include "config.h"
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
# include <sys/types.h>
|
||||||
|
# include <sys/stat.h>
|
||||||
|
# include <dirent.h>
|
||||||
|
# include <errno.h>
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -35,6 +37,7 @@
|
|||||||
|
|
||||||
static int verbosity = 0;
|
static int verbosity = 0;
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
static int _torture_auth_kbdint(ssh_session session,
|
static int _torture_auth_kbdint(ssh_session session,
|
||||||
const char *password) {
|
const char *password) {
|
||||||
const char *prompt;
|
const char *prompt;
|
||||||
@@ -129,6 +132,7 @@ int torture_rmdirs(const char *path) {
|
|||||||
rewinddir(d);
|
rewinddir(d);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
closedir(d);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,10 +150,6 @@ int torture_isdir(const char *path) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int torture_libssh_verbosity(void){
|
|
||||||
return verbosity;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssh_session torture_ssh_session(const char *host,
|
ssh_session torture_ssh_session(const char *host,
|
||||||
const char *user,
|
const char *user,
|
||||||
const char *password) {
|
const char *password) {
|
||||||
@@ -216,6 +216,8 @@ failed:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_SFTP
|
||||||
|
|
||||||
struct torture_sftp *torture_sftp_session(ssh_session session) {
|
struct torture_sftp *torture_sftp_session(ssh_session session) {
|
||||||
struct torture_sftp *t;
|
struct torture_sftp *t;
|
||||||
char template[] = "/tmp/ssh_torture_XXXXXX";
|
char template[] = "/tmp/ssh_torture_XXXXXX";
|
||||||
@@ -246,6 +248,8 @@ struct torture_sftp *torture_sftp_session(ssh_session session) {
|
|||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
/* useful if TESTUSER is not the local user */
|
||||||
|
chmod(template,0777);
|
||||||
t->testdir = strdup(p);
|
t->testdir = strdup(p);
|
||||||
if (t->testdir == NULL) {
|
if (t->testdir == NULL) {
|
||||||
goto failed;
|
goto failed;
|
||||||
@@ -258,6 +262,7 @@ failed:
|
|||||||
}
|
}
|
||||||
ssh_disconnect(t->ssh);
|
ssh_disconnect(t->ssh);
|
||||||
ssh_free(t->ssh);
|
ssh_free(t->ssh);
|
||||||
|
free(t);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -281,6 +286,14 @@ void torture_sftp_close(struct torture_sftp *t) {
|
|||||||
free(t->testdir);
|
free(t->testdir);
|
||||||
free(t);
|
free(t);
|
||||||
}
|
}
|
||||||
|
#endif /* WITH_SFTP */
|
||||||
|
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
|
||||||
|
int torture_libssh_verbosity(void){
|
||||||
|
return verbosity;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
struct argument_s arguments;
|
struct argument_s arguments;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ add_cmockery_test(torture_init torture_init.c ${TORTURE_LIBRARY})
|
|||||||
add_cmockery_test(torture_list torture_list.c ${TORTURE_LIBRARY})
|
add_cmockery_test(torture_list torture_list.c ${TORTURE_LIBRARY})
|
||||||
add_cmockery_test(torture_misc torture_misc.c ${TORTURE_LIBRARY})
|
add_cmockery_test(torture_misc torture_misc.c ${TORTURE_LIBRARY})
|
||||||
add_cmockery_test(torture_options torture_options.c ${TORTURE_LIBRARY})
|
add_cmockery_test(torture_options torture_options.c ${TORTURE_LIBRARY})
|
||||||
|
add_cmockery_test(torture_isipaddr torture_isipaddr.c ${TORTURE_LIBRARY})
|
||||||
if (UNIX AND NOT WIN32)
|
if (UNIX AND NOT WIN32)
|
||||||
# requires ssh-keygen
|
# requires ssh-keygen
|
||||||
add_cmockery_test(torture_keyfiles torture_keyfiles.c ${TORTURE_LIBRARY})
|
add_cmockery_test(torture_keyfiles torture_keyfiles.c ${TORTURE_LIBRARY})
|
||||||
|
|||||||
55
tests/unittests/torture_isipaddr.c
Normal file
55
tests/unittests/torture_isipaddr.c
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#define LIBSSH_STATIC
|
||||||
|
|
||||||
|
#include "torture.h"
|
||||||
|
|
||||||
|
#include "misc.c"
|
||||||
|
#include "error.c"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test the behavior of ssh_is_ipaddr()
|
||||||
|
*/
|
||||||
|
static void torture_ssh_is_ipaddr(void **state) {
|
||||||
|
(void)state;
|
||||||
|
|
||||||
|
assert_int_equal(ssh_is_ipaddr("127.0.0.1"),1);
|
||||||
|
assert_int_equal(ssh_is_ipaddr("0.0.0.0"),1);
|
||||||
|
assert_int_equal(ssh_is_ipaddr("1.1.1.1"),1);
|
||||||
|
assert_int_equal(ssh_is_ipaddr("255.255.255.255"),1);
|
||||||
|
assert_int_equal(ssh_is_ipaddr("128.128.128.128"),1);
|
||||||
|
assert_int_equal(ssh_is_ipaddr("1.10.100.1"),1);
|
||||||
|
assert_int_equal(ssh_is_ipaddr("0.1.10.100"),1);
|
||||||
|
|
||||||
|
assert_int_equal(ssh_is_ipaddr("2001:0db8:85a3:0000:0000:8a2e:0370:7334"),1);
|
||||||
|
assert_int_equal(ssh_is_ipaddr("fe80:0000:0000:0000:0202:b3ff:fe1e:8329"),1);
|
||||||
|
assert_int_equal(ssh_is_ipaddr("fe80:0:0:0:202:b3ff:fe1e:8329"),1);
|
||||||
|
assert_int_equal(ssh_is_ipaddr("fe80::202:b3ff:fe1e:8329"),1);
|
||||||
|
assert_int_equal(ssh_is_ipaddr("::1"),1);
|
||||||
|
|
||||||
|
assert_int_equal(ssh_is_ipaddr("::ffff:192.0.2.128"),1);
|
||||||
|
|
||||||
|
assert_int_equal(ssh_is_ipaddr("0.0.0.0.0"),0);
|
||||||
|
assert_int_equal(ssh_is_ipaddr("0.0.0.0.a"),0);
|
||||||
|
assert_int_equal(ssh_is_ipaddr("a.0.0.0"),0);
|
||||||
|
assert_int_equal(ssh_is_ipaddr("0a.0.0.0.0"),0);
|
||||||
|
assert_int_equal(ssh_is_ipaddr(""),0);
|
||||||
|
assert_int_equal(ssh_is_ipaddr("0.0.0."),0);
|
||||||
|
assert_int_equal(ssh_is_ipaddr("0.0"),0);
|
||||||
|
assert_int_equal(ssh_is_ipaddr("0"),0);
|
||||||
|
|
||||||
|
assert_int_equal(ssh_is_ipaddr("2001:0db8:85a3:0000:0000:8a2e:0370:7334:1002"), 0);
|
||||||
|
assert_int_equal(ssh_is_ipaddr("fe80:x:202:b3ff:fe1e:8329"), 0);
|
||||||
|
assert_int_equal(ssh_is_ipaddr("fe80:x:202:b3ff:fe1e:8329"), 0);
|
||||||
|
assert_int_equal(ssh_is_ipaddr(":1"), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int torture_run_tests(void) {
|
||||||
|
int rc;
|
||||||
|
const UnitTest tests[] = {
|
||||||
|
unit_test(torture_ssh_is_ipaddr)
|
||||||
|
};
|
||||||
|
|
||||||
|
ssh_init();
|
||||||
|
rc=run_tests(tests);
|
||||||
|
ssh_finalize();
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
@@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#include "torture.h"
|
#include "torture.h"
|
||||||
#include "misc.c"
|
#include "misc.c"
|
||||||
|
#include "error.c"
|
||||||
|
|
||||||
#define TORTURE_TEST_DIR "/usr/local/bin/truc/much/.."
|
#define TORTURE_TEST_DIR "/usr/local/bin/truc/much/.."
|
||||||
|
|
||||||
|
|
||||||
@@ -159,6 +161,30 @@ static void torture_path_expand_known_hosts(void **state) {
|
|||||||
free(tmp);
|
free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void torture_timeout_elapsed(void **state){
|
||||||
|
struct ssh_timestamp ts;
|
||||||
|
(void) state;
|
||||||
|
ssh_timestamp_init(&ts);
|
||||||
|
usleep(50000);
|
||||||
|
assert_true(ssh_timeout_elapsed(&ts,25));
|
||||||
|
assert_false(ssh_timeout_elapsed(&ts,30000));
|
||||||
|
assert_false(ssh_timeout_elapsed(&ts,75));
|
||||||
|
assert_true(ssh_timeout_elapsed(&ts,0));
|
||||||
|
assert_false(ssh_timeout_elapsed(&ts,-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void torture_timeout_update(void **state){
|
||||||
|
struct ssh_timestamp ts;
|
||||||
|
(void) state;
|
||||||
|
ssh_timestamp_init(&ts);
|
||||||
|
usleep(50000);
|
||||||
|
assert_int_equal(ssh_timeout_update(&ts,25), 0);
|
||||||
|
assert_in_range(ssh_timeout_update(&ts,30000),29000,29960);
|
||||||
|
assert_in_range(ssh_timeout_update(&ts,75),1,40);
|
||||||
|
assert_int_equal(ssh_timeout_update(&ts,0),0);
|
||||||
|
assert_int_equal(ssh_timeout_update(&ts,-1),-1);
|
||||||
|
}
|
||||||
|
|
||||||
int torture_run_tests(void) {
|
int torture_run_tests(void) {
|
||||||
int rc;
|
int rc;
|
||||||
const UnitTest tests[] = {
|
const UnitTest tests[] = {
|
||||||
@@ -173,6 +199,8 @@ int torture_run_tests(void) {
|
|||||||
#endif
|
#endif
|
||||||
unit_test_setup_teardown(torture_path_expand_escape, setup, teardown),
|
unit_test_setup_teardown(torture_path_expand_escape, setup, teardown),
|
||||||
unit_test_setup_teardown(torture_path_expand_known_hosts, setup, teardown),
|
unit_test_setup_teardown(torture_path_expand_known_hosts, setup, teardown),
|
||||||
|
unit_test(torture_timeout_elapsed),
|
||||||
|
unit_test(torture_timeout_update),
|
||||||
};
|
};
|
||||||
|
|
||||||
ssh_init();
|
ssh_init();
|
||||||
|
|||||||
@@ -119,6 +119,23 @@ static void torture_options_set_identity(void **state) {
|
|||||||
assert_string_equal(session->identity->root->next->data, "identity1");
|
assert_string_equal(session->identity->root->next->data, "identity1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void torture_options_proxycommand(void **state) {
|
||||||
|
ssh_session session = *state;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Enable ProxyCommand */
|
||||||
|
rc = ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, "ssh -q -A -X -W %h:%p JUMPHOST");
|
||||||
|
assert_int_equal(rc, 0);
|
||||||
|
|
||||||
|
assert_string_equal(session->ProxyCommand, "ssh -q -A -X -W %h:%p JUMPHOST");
|
||||||
|
|
||||||
|
/* Disable ProxyCommand */
|
||||||
|
rc = ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, "none");
|
||||||
|
assert_int_equal(rc, 0);
|
||||||
|
|
||||||
|
assert_true(session->ProxyCommand == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
int torture_run_tests(void) {
|
int torture_run_tests(void) {
|
||||||
int rc;
|
int rc;
|
||||||
const UnitTest tests[] = {
|
const UnitTest tests[] = {
|
||||||
@@ -127,6 +144,7 @@ int torture_run_tests(void) {
|
|||||||
unit_test_setup_teardown(torture_options_set_fd, setup, teardown),
|
unit_test_setup_teardown(torture_options_set_fd, setup, teardown),
|
||||||
unit_test_setup_teardown(torture_options_set_user, setup, teardown),
|
unit_test_setup_teardown(torture_options_set_user, setup, teardown),
|
||||||
unit_test_setup_teardown(torture_options_set_identity, setup, teardown),
|
unit_test_setup_teardown(torture_options_set_identity, setup, teardown),
|
||||||
|
unit_test_setup_teardown(torture_options_proxycommand, setup, teardown),
|
||||||
};
|
};
|
||||||
|
|
||||||
ssh_init();
|
ssh_init();
|
||||||
|
|||||||
Reference in New Issue
Block a user