mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-06 18:29:50 +09:00
Compare commits
36 Commits
libssh-0.5
...
libssh-0.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
@@ -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 "2")
|
set(APPLICATION_VERSION_PATCH "3")
|
||||||
|
|
||||||
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.2")
|
set(LIBRARY_VERSION "4.2.3")
|
||||||
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
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
|
|||||||
### versions
|
### versions
|
||||||
set(CPACK_PACKAGE_VERSION_MAJOR "0")
|
set(CPACK_PACKAGE_VERSION_MAJOR "0")
|
||||||
set(CPACK_PACKAGE_VERSION_MINOR "5")
|
set(CPACK_PACKAGE_VERSION_MINOR "5")
|
||||||
set(CPACK_PACKAGE_VERSION_PATCH "2")
|
set(CPACK_PACKAGE_VERSION_PATCH "3")
|
||||||
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}")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
15
ChangeLog
15
ChangeLog
@@ -1,6 +1,21 @@
|
|||||||
ChangeLog
|
ChangeLog
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|
version 0.5.3 (released 2012-11-20)
|
||||||
|
* CVE-2012-4559 Fixed multiple double free() flaws.
|
||||||
|
* CVE-2012-4560 Fixed multiple buffer overflow flaws.
|
||||||
|
* CVE-2012-4561 Fixed multiple invalid free() flaws.
|
||||||
|
* BUG #84 - Fix bug in sftp_mkdir not returning on error.
|
||||||
|
* BUG #85 - Fixed a possible channel infinite loop if the connection dropped.
|
||||||
|
* BUG #88 - Added missing channel request_state and set it to accepted.
|
||||||
|
* BUG #89 - Reset error state to no error on successful SSHv1 authentiction.
|
||||||
|
* Fixed a possible use after free in ssh_free().
|
||||||
|
* Fixed multiple possible NULL pointer dereferences.
|
||||||
|
* Fixed multiple memory leaks in error paths.
|
||||||
|
* Fixed timeout handling.
|
||||||
|
* Fixed regression in pre-connected socket setting.
|
||||||
|
* Handle all unknown global messages.
|
||||||
|
|
||||||
version 0.5.2 (released 2011-09-17)
|
version 0.5.2 (released 2011-09-17)
|
||||||
* Increased window size x10.
|
* Increased window size x10.
|
||||||
* Fixed SSHv1.
|
* Fixed SSHv1.
|
||||||
|
|||||||
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
|
||||||
|
|||||||
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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ 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);
|
void ssh_timestamp_init(struct ssh_timestamp *ts);
|
||||||
int ssh_timeout_elapsed(struct ssh_timestamp *ts, int timeout);
|
int ssh_timeout_elapsed(struct ssh_timestamp *ts, int timeout);
|
||||||
int ssh_timeout_update(struct ssh_timestamp *ts, int timeout);
|
int ssh_timeout_update(struct ssh_timestamp *ts, int timeout);
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ struct ssh_keys_struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ssh_message_struct;
|
struct ssh_message_struct;
|
||||||
|
struct ssh_common_struct;
|
||||||
|
|
||||||
/* server data */
|
/* server data */
|
||||||
|
|
||||||
@@ -208,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);
|
||||||
@@ -221,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)
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -62,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_ */
|
||||||
|
|||||||
@@ -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)) {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -359,7 +359,7 @@ 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);
|
||||||
@@ -375,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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1232,7 +1233,9 @@ int channel_write_common(ssh_channel channel, const void *data,
|
|||||||
/* it's a good idea to flush the socket now */
|
/* it's a good idea to flush the socket now */
|
||||||
do {
|
do {
|
||||||
rc = ssh_handle_packets(session, timeout);
|
rc = ssh_handle_packets(session, timeout);
|
||||||
} while(ssh_socket_buffered_write_bytes(session->socket) > 0 && timeout != 0);
|
} while(rc == SSH_OK &&
|
||||||
|
timeout != 0 &&
|
||||||
|
ssh_socket_buffered_write_bytes(session->socket) > 0);
|
||||||
out:
|
out:
|
||||||
leave_function();
|
leave_function();
|
||||||
return (int)(origlen - len);
|
return (int)(origlen - len);
|
||||||
@@ -1414,6 +1417,7 @@ static int channel_request(ssh_channel channel, const char *request,
|
|||||||
buffer_add_ssh_string(session->out_buffer, req) < 0 ||
|
buffer_add_ssh_string(session->out_buffer, req) < 0 ||
|
||||||
buffer_add_u8(session->out_buffer, reply == 0 ? 0 : 1) < 0) {
|
buffer_add_u8(session->out_buffer, reply == 0 ? 0 : 1) < 0) {
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
|
ssh_string_free(req);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
ssh_string_free(req);
|
ssh_string_free(req);
|
||||||
@@ -1473,7 +1477,6 @@ static int channel_request(ssh_channel channel, const char *request,
|
|||||||
return rc;
|
return rc;
|
||||||
error:
|
error:
|
||||||
buffer_reinit(session->out_buffer);
|
buffer_reinit(session->out_buffer);
|
||||||
ssh_string_free(req);
|
|
||||||
|
|
||||||
leave_function();
|
leave_function();
|
||||||
return rc;
|
return rc;
|
||||||
@@ -1494,11 +1497,16 @@ error:
|
|||||||
*/
|
*/
|
||||||
int ssh_channel_request_pty_size(ssh_channel channel, const char *terminal,
|
int ssh_channel_request_pty_size(ssh_channel channel, const char *terminal,
|
||||||
int col, int row) {
|
int col, int row) {
|
||||||
ssh_session session = channel->session;
|
ssh_session session;
|
||||||
ssh_string term = NULL;
|
ssh_string term = NULL;
|
||||||
ssh_buffer buffer = NULL;
|
ssh_buffer buffer = NULL;
|
||||||
int rc = SSH_ERROR;
|
int rc = SSH_ERROR;
|
||||||
|
|
||||||
|
if (channel == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
session = channel->session;
|
||||||
|
|
||||||
enter_function();
|
enter_function();
|
||||||
#ifdef WITH_SSH1
|
#ifdef WITH_SSH1
|
||||||
if (channel->version==1) {
|
if (channel->version==1) {
|
||||||
@@ -2271,11 +2279,16 @@ error:
|
|||||||
*/
|
*/
|
||||||
int channel_read_buffer(ssh_channel channel, ssh_buffer buffer, uint32_t count,
|
int channel_read_buffer(ssh_channel channel, ssh_buffer buffer, uint32_t count,
|
||||||
int is_stderr) {
|
int is_stderr) {
|
||||||
ssh_session session=channel->session;
|
ssh_session session;
|
||||||
char buffer_tmp[8192];
|
char buffer_tmp[8192];
|
||||||
int r;
|
int r;
|
||||||
uint32_t total=0;
|
uint32_t total=0;
|
||||||
|
|
||||||
|
if (channel == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
session = channel->session;
|
||||||
|
|
||||||
enter_function();
|
enter_function();
|
||||||
buffer_reinit(buffer);
|
buffer_reinit(buffer);
|
||||||
if(count==0){
|
if(count==0){
|
||||||
|
|||||||
@@ -62,6 +62,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;
|
||||||
|
|||||||
@@ -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){
|
||||||
|
|||||||
@@ -159,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();
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
5
src/dh.c
5
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
|
||||||
|
|
||||||
@@ -193,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -705,7 +705,7 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
|
|||||||
|
|
||||||
ssh_log(session, SSH_LOG_RARE, "Trying to read %s, passphase=%s, authcb=%s",
|
ssh_log(session, SSH_LOG_RARE, "Trying to read %s, passphase=%s, authcb=%s",
|
||||||
filename, passphrase ? "true" : "false",
|
filename, passphrase ? "true" : "false",
|
||||||
session->callbacks && session->callbacks->auth_function ? "true" : "false");
|
session->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);
|
||||||
@@ -719,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:");
|
||||||
@@ -738,7 +738,7 @@ 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_bio_DSAPrivateKey(bio, 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 */
|
||||||
@@ -761,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 */
|
||||||
@@ -779,7 +779,7 @@ 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_bio_RSAPrivateKey(bio, 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 */
|
||||||
@@ -1214,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) {
|
||||||
@@ -1234,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");
|
||||||
@@ -1255,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);
|
||||||
@@ -897,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) {
|
||||||
@@ -1280,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:
|
||||||
@@ -1436,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
|
||||||
|
|
||||||
|
|||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -911,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;
|
||||||
@@ -945,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);
|
||||||
}
|
}
|
||||||
@@ -967,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 */
|
||||||
|
|||||||
54
src/misc.c
54
src/misc.c
@@ -655,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);
|
||||||
@@ -719,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';
|
||||||
@@ -760,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);
|
||||||
@@ -923,6 +928,24 @@ static int ssh_timestamp_difference(struct ssh_timestamp *old,
|
|||||||
return msecs;
|
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
|
* @internal
|
||||||
* @brief Checks if a timeout is elapsed, in function of a previous
|
* @brief Checks if a timeout is elapsed, in function of a previous
|
||||||
@@ -934,17 +957,20 @@ static int ssh_timestamp_difference(struct ssh_timestamp *old,
|
|||||||
* 0 otherwise
|
* 0 otherwise
|
||||||
*/
|
*/
|
||||||
int ssh_timeout_elapsed(struct ssh_timestamp *ts, int timeout) {
|
int ssh_timeout_elapsed(struct ssh_timestamp *ts, int timeout) {
|
||||||
struct ssh_timestamp now;
|
struct ssh_timestamp now;
|
||||||
if(timeout < 0)
|
switch(timeout) {
|
||||||
return 0; // -1 means infinite timeout
|
case -2: // -2 means user-defined timeout as available in session->timeout, session->timeout_usec.
|
||||||
if(timeout == 0)
|
fprintf(stderr, "ssh_timeout_elapsed called with -2. this needs to be fixed. "
|
||||||
return 1; // 0 means no timeout
|
"please set a breakpoint on %s:%d and fix the caller\n", __FILE__, __LINE__);
|
||||||
ssh_timestamp_init(&now);
|
case -1: // -1 means infinite timeout
|
||||||
|
return 0;
|
||||||
if(ssh_timestamp_difference(ts,&now) >= timeout)
|
case 0: // 0 means no timeout
|
||||||
return 1;
|
return 1;
|
||||||
else
|
default:
|
||||||
return 0;
|
break;
|
||||||
|
}
|
||||||
|
ssh_timestamp_init(&now);
|
||||||
|
return (ssh_timestamp_difference(ts,&now) >= timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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:
|
||||||
@@ -1106,12 +1106,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 +1124,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
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -163,10 +164,20 @@ void ssh_free(ssh_session session) {
|
|||||||
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,17 +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 ((it=ssh_list_get_iterator(session->channels)) != NULL) {
|
|
||||||
ssh_channel_free(ssh_iterator_value(ssh_channel,it));
|
|
||||||
ssh_list_remove(session->channels, it);
|
|
||||||
}
|
|
||||||
ssh_list_free(session->channels);
|
|
||||||
session->channels=NULL;
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
agent_free(session->agent);
|
agent_free(session->agent);
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
@@ -235,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);
|
||||||
@@ -304,7 +309,7 @@ int ssh_is_blocking(ssh_session session){
|
|||||||
* @brief Blocking flush of the outgoing buffer
|
* @brief Blocking flush of the outgoing buffer
|
||||||
* @param[in] session The SSH session
|
* @param[in] session The SSH session
|
||||||
* @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. This parameter is passed to
|
||||||
* the poll() function.
|
* the poll() function.
|
||||||
* @returns SSH_OK on success, SSH_AGAIN if timeout occurred,
|
* @returns SSH_OK on success, SSH_AGAIN if timeout occurred,
|
||||||
@@ -313,24 +318,16 @@ int ssh_is_blocking(ssh_session session){
|
|||||||
|
|
||||||
int ssh_blocking_flush(ssh_session session, int timeout){
|
int ssh_blocking_flush(ssh_session session, int timeout){
|
||||||
ssh_socket s;
|
ssh_socket s;
|
||||||
struct ssh_timestamp ts;
|
|
||||||
int rc = SSH_OK;
|
int rc = SSH_OK;
|
||||||
if(session==NULL)
|
if(session==NULL)
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
|
|
||||||
enter_function();
|
|
||||||
s=session->socket;
|
s=session->socket;
|
||||||
ssh_timestamp_init(&ts);
|
|
||||||
while (ssh_socket_buffered_write_bytes(s) > 0 && session->alive) {
|
while (ssh_socket_buffered_write_bytes(s) > 0 && session->alive) {
|
||||||
rc=ssh_handle_packets(session, timeout);
|
rc = ssh_handle_packets(session, timeout);
|
||||||
if(ssh_timeout_elapsed(&ts,timeout)){
|
if(rc == SSH_AGAIN || rc == SSH_ERROR) break;
|
||||||
rc=SSH_AGAIN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
timeout = ssh_timeout_update(&ts, timeout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
leave_function();
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,17 +404,6 @@ void ssh_set_fd_except(ssh_session session) {
|
|||||||
ssh_socket_set_except(session->socket);
|
ssh_socket_set_except(session->socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
static 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
|
* @internal
|
||||||
*
|
*
|
||||||
@@ -497,13 +483,18 @@ int ssh_handle_packets(ssh_session session, int timeout) {
|
|||||||
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_OK;
|
int ret = SSH_OK;
|
||||||
|
struct ssh_timestamp ts;
|
||||||
|
ssh_timestamp_init(&ts);
|
||||||
while(!fct(user)){
|
while(!fct(user)){
|
||||||
ret = ssh_handle_packets(session, timeout);
|
ret = ssh_handle_packets(session, timeout);
|
||||||
if(ret == SSH_ERROR || ret == SSH_AGAIN)
|
if(ret == SSH_ERROR || ret == SSH_AGAIN)
|
||||||
return ret;
|
return ret;
|
||||||
if(fct(user))
|
if(fct(user))
|
||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
|
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,
|
||||||
|
* so simply relying on the poll timeout is not enough */
|
||||||
|
return SSH_AGAIN;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
41
src/sftp.c
41
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);
|
||||||
@@ -2269,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
|
||||||
|
|
||||||
|
|||||||
27
src/socket.c
27
src/socket.c
@@ -701,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
|
||||||
@@ -729,13 +748,7 @@ int ssh_socket_connect(ssh_socket s, const char *host, int port, const char *bin
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|||||||
26
src/string.c
26
src/string.c
@@ -22,10 +22,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <errno.h>
|
#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
|
||||||
|
|
||||||
@@ -51,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;
|
||||||
}
|
}
|
||||||
@@ -141,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 || s->string == 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user