mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-05 12:50:30 +09:00
Compare commits
26 Commits
libssh-0.8
...
libssh-0.8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
273fb4cfc6 | ||
|
|
56f7c27852 | ||
|
|
1285b37b60 | ||
|
|
b7de358cdc | ||
|
|
bea6393de0 | ||
|
|
9158cc524c | ||
|
|
8ba10ef42b | ||
|
|
2ff8a09ee6 | ||
|
|
d52fa9a02c | ||
|
|
ec3fdb434c | ||
|
|
d877969db3 | ||
|
|
b1a7bd21ad | ||
|
|
0831b85002 | ||
|
|
34d1f5e097 | ||
|
|
fcf2cd0d9e | ||
|
|
4a4ca44b19 | ||
|
|
17a6c3f88f | ||
|
|
e24bb932ed | ||
|
|
5c2d444fa8 | ||
|
|
9763563c02 | ||
|
|
5f9d9f4a53 | ||
|
|
e8f3207a0d | ||
|
|
e5cee205c1 | ||
|
|
63056d1bb1 | ||
|
|
09e4f3d331 | ||
|
|
4b886ac656 |
@@ -10,7 +10,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
|
|||||||
include(DefineCMakeDefaults)
|
include(DefineCMakeDefaults)
|
||||||
include(DefineCompilerFlags)
|
include(DefineCompilerFlags)
|
||||||
|
|
||||||
project(libssh VERSION 0.8.4 LANGUAGES C)
|
project(libssh VERSION 0.8.5 LANGUAGES C)
|
||||||
|
|
||||||
# global needed variable
|
# global needed variable
|
||||||
set(APPLICATION_NAME ${PROJECT_NAME})
|
set(APPLICATION_NAME ${PROJECT_NAME})
|
||||||
@@ -22,7 +22,7 @@ set(APPLICATION_NAME ${PROJECT_NAME})
|
|||||||
# 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.7.1")
|
set(LIBRARY_VERSION "4.7.2")
|
||||||
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
|
||||||
|
|||||||
11
ChangeLog
11
ChangeLog
@@ -1,6 +1,17 @@
|
|||||||
ChangeLog
|
ChangeLog
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|
version 0.8.5 (released 2018-10-29)
|
||||||
|
* Added support to get known_hosts locations with ssh_options_get()
|
||||||
|
* Fixed preferred algorithm for known hosts negotiations
|
||||||
|
* Fixed KEX with some server implementations (e.g. Cisco)
|
||||||
|
* Fixed issues with MSVC
|
||||||
|
* Fixed keyboard-interactive auth in server mode
|
||||||
|
(regression from CVE-2018-10933)
|
||||||
|
* Fixed gssapi auth in server mode (regression from CVE-2018-10933)
|
||||||
|
* Fixed socket fd handling with proxy command
|
||||||
|
* Fixed a memory leak with OpenSSL
|
||||||
|
|
||||||
version 0.8.4 (released 2018-10-16)
|
version 0.8.4 (released 2018-10-16)
|
||||||
* Fixed CVE-2018-10933
|
* Fixed CVE-2018-10933
|
||||||
* Fixed building without globbing support
|
* Fixed building without globbing support
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ The keyboard-interactive method is, as its name tells, interactive. The
|
|||||||
server will issue one or more challenges that the user has to answer,
|
server will issue one or more challenges that the user has to answer,
|
||||||
until the server takes an authentication decision.
|
until the server takes an authentication decision.
|
||||||
|
|
||||||
ssh_userauth_kbdint() is the the main keyboard-interactive function.
|
ssh_userauth_kbdint() is the the main keyboard-interactive function.
|
||||||
It will return SSH_AUTH_SUCCESS,SSH_AUTH_DENIED, SSH_AUTH_PARTIAL,
|
It will return SSH_AUTH_SUCCESS,SSH_AUTH_DENIED, SSH_AUTH_PARTIAL,
|
||||||
SSH_AUTH_ERROR, or SSH_AUTH_INFO, depending on the result of the request.
|
SSH_AUTH_ERROR, or SSH_AUTH_INFO, depending on the result of the request.
|
||||||
|
|
||||||
@@ -154,9 +154,9 @@ Here are a few remarks:
|
|||||||
- Even the first call can return SSH_AUTH_DENIED or SSH_AUTH_SUCCESS.
|
- Even the first call can return SSH_AUTH_DENIED or SSH_AUTH_SUCCESS.
|
||||||
- The server can send an empty question set (this is the default behavior
|
- The server can send an empty question set (this is the default behavior
|
||||||
on my system) after you have sent the answers to the first questions.
|
on my system) after you have sent the answers to the first questions.
|
||||||
You must still parse the answer, it might contain some
|
You must still parse the answer, it might contain some
|
||||||
message from the server saying hello or such things. Just call
|
message from the server saying hello or such things. Just call
|
||||||
ssh_userauth_kbdint() until needed.
|
ssh_userauth_kbdint() until needed.
|
||||||
- The meaning of "name", "prompt", "instruction" may be a little
|
- The meaning of "name", "prompt", "instruction" may be a little
|
||||||
confusing. An explanation is given in the RFC section that follows.
|
confusing. An explanation is given in the RFC section that follows.
|
||||||
|
|
||||||
@@ -187,7 +187,7 @@ keyboard-interactive authentication, coming from the RFC itself (rfc4256):
|
|||||||
the name and prompts. If the server presents names or prompts longer than 30
|
the name and prompts. If the server presents names or prompts longer than 30
|
||||||
characters, the client MAY truncate these fields to the length it can
|
characters, the client MAY truncate these fields to the length it can
|
||||||
display. If the client does truncate any fields, there MUST be an obvious
|
display. If the client does truncate any fields, there MUST be an obvious
|
||||||
indication that such truncation has occured.
|
indication that such truncation has occurred.
|
||||||
|
|
||||||
The instruction field SHOULD NOT be truncated. Clients SHOULD use control
|
The instruction field SHOULD NOT be truncated. Clients SHOULD use control
|
||||||
character filtering as discussed in [SSH-ARCH] to avoid attacks by
|
character filtering as discussed in [SSH-ARCH] to avoid attacks by
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
Port forwarding comes in SSH protocol in two different flavours:
|
Port forwarding comes in SSH protocol in two different flavours:
|
||||||
direct or reverse port forwarding. Direct port forwarding is also
|
direct or reverse port forwarding. Direct port forwarding is also
|
||||||
named local port forwardind, and reverse port forwarding is also called
|
named local port forwarding, and reverse port forwarding is also called
|
||||||
remote port forwarding. SSH also allows X11 tunnels.
|
remote port forwarding. SSH also allows X11 tunnels.
|
||||||
|
|
||||||
|
|
||||||
@@ -23,15 +23,15 @@ Mail client application Google Mail
|
|||||||
5555 (arbitrary) |
|
5555 (arbitrary) |
|
||||||
| 143 (IMAP2)
|
| 143 (IMAP2)
|
||||||
V |
|
V |
|
||||||
SSH client =====> SSH server
|
SSH client =====> SSH server
|
||||||
|
|
||||||
Legend:
|
Legend:
|
||||||
--P-->: port connexion through port P
|
--P-->: port connections through port P
|
||||||
=====>: SSH tunnel
|
=====>: SSH tunnel
|
||||||
@endverbatim
|
@endverbatim
|
||||||
A mail client connects to port 5555 of a client. An encrypted tunnel is
|
A mail client connects to port 5555 of a client. An encrypted tunnel is
|
||||||
established to the server. The server connects to port 143 of Google Mail (the
|
established to the server. The server connects to port 143 of Google Mail (the
|
||||||
end point). Now the local mail client can retreive mail.
|
end point). Now the local mail client can retrieve mail.
|
||||||
|
|
||||||
|
|
||||||
@subsection forwarding_reverse Reverse port forwarding
|
@subsection forwarding_reverse Reverse port forwarding
|
||||||
@@ -51,7 +51,7 @@ Example of use of reverse port forwarding:
|
|||||||
SSH client <===== SSH server
|
SSH client <===== SSH server
|
||||||
|
|
||||||
Legend:
|
Legend:
|
||||||
--P-->: port connexion through port P
|
--P-->: port connections through port P
|
||||||
=====>: SSH tunnel
|
=====>: SSH tunnel
|
||||||
@endverbatim
|
@endverbatim
|
||||||
In this example, the SSH client establishes the tunnel,
|
In this example, the SSH client establishes the tunnel,
|
||||||
@@ -148,9 +148,9 @@ To do reverse port forwarding, call ssh_channel_listen_forward(),
|
|||||||
then ssh_channel_accept_forward().
|
then ssh_channel_accept_forward().
|
||||||
|
|
||||||
When you call ssh_channel_listen_forward(), you can let the remote server
|
When you call ssh_channel_listen_forward(), you can let the remote server
|
||||||
chose the non-priviledged port it should listen to. Otherwise, you can chose
|
chose the non-privileged port it should listen to. Otherwise, you can chose
|
||||||
your own priviledged or non-priviledged port. Beware that you should have
|
your own privileged or non-privileged port. Beware that you should have
|
||||||
administrative priviledges on the remote server to open a priviledged port
|
administrative privileges on the remote server to open a privileged port
|
||||||
(port number < 1024).
|
(port number < 1024).
|
||||||
|
|
||||||
Below is an example of a very rough web server waiting for connections on port
|
Below is an example of a very rough web server waiting for connections on port
|
||||||
|
|||||||
@@ -31,20 +31,20 @@ A SSH session goes through the following steps:
|
|||||||
- Invoke your own subsystem. This is outside the scope of this document,
|
- Invoke your own subsystem. This is outside the scope of this document,
|
||||||
but can be done.
|
but can be done.
|
||||||
|
|
||||||
- When everything is finished, just close the channels, and then the connection.
|
- When everything is finished, just close the channels, and then the connection.
|
||||||
|
|
||||||
The sftp and scp subsystems use channels, but libssh hides them to
|
The sftp and scp subsystems use channels, but libssh hides them to
|
||||||
the programmer. If you want to use those subsystems, instead of a channel,
|
the programmer. If you want to use those subsystems, instead of a channel,
|
||||||
you'll usually open a "sftp session" or a "scp session".
|
you'll usually open a "sftp session" or a "scp session".
|
||||||
|
|
||||||
|
|
||||||
@subsection setup Creating the session and setting options
|
@subsection setup Creating the session and setting options
|
||||||
|
|
||||||
The most important object in a SSH connection is the SSH session. In order
|
The most important object in a SSH connection is the SSH session. In order
|
||||||
to allocate a new SSH session, you use ssh_new(). Don't forget to
|
to allocate a new SSH session, you use ssh_new(). Don't forget to
|
||||||
always verify that the allocation successed.
|
always verify that the allocation succeeded.
|
||||||
@code
|
@code
|
||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
@@ -69,12 +69,12 @@ The ssh_options_set() function sets the options of the session. The most importa
|
|||||||
|
|
||||||
The complete list of options can be found in the documentation of ssh_options_set().
|
The complete list of options can be found in the documentation of ssh_options_set().
|
||||||
The only mandatory option is SSH_OPTIONS_HOST. If you don't use SSH_OPTIONS_USER,
|
The only mandatory option is SSH_OPTIONS_HOST. If you don't use SSH_OPTIONS_USER,
|
||||||
the local username of your account will be used.
|
the local username of your account will be used.
|
||||||
|
|
||||||
Here is a small example of how to use it:
|
Here is a small example of how to use it:
|
||||||
|
|
||||||
@code
|
@code
|
||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
@@ -122,7 +122,7 @@ Here's an example:
|
|||||||
@code
|
@code
|
||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
@@ -285,9 +285,9 @@ int verify_knownhost(ssh_session session)
|
|||||||
|
|
||||||
The authentication process is the way a service provider can identify a
|
The authentication process is the way a service provider can identify a
|
||||||
user and verify his/her identity. The authorization process is about enabling
|
user and verify his/her identity. The authorization process is about enabling
|
||||||
the authenticated user the access to ressources. In SSH, the two concepts
|
the authenticated user the access to resources. In SSH, the two concepts
|
||||||
are linked. After authentication, the server can grant the user access to
|
are linked. After authentication, the server can grant the user access to
|
||||||
several ressources such as port forwarding, shell, sftp subsystem, and so on.
|
several resources such as port forwarding, shell, sftp subsystem, and so on.
|
||||||
|
|
||||||
libssh supports several methods of authentication:
|
libssh supports several methods of authentication:
|
||||||
- "none" method. This method allows to get the available authentications
|
- "none" method. This method allows to get the available authentications
|
||||||
@@ -313,7 +313,7 @@ The example below shows an authentication with password:
|
|||||||
@code
|
@code
|
||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
@@ -338,7 +338,7 @@ int main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify the server's identity
|
// Verify the server's identity
|
||||||
// For the source code of verify_knowhost(), check previous example
|
// For the source code of verify_knownhost(), check previous example
|
||||||
if (verify_knownhost(my_ssh_session) < 0)
|
if (verify_knownhost(my_ssh_session) < 0)
|
||||||
{
|
{
|
||||||
ssh_disconnect(my_ssh_session);
|
ssh_disconnect(my_ssh_session);
|
||||||
@@ -415,7 +415,7 @@ int show_remote_processes(ssh_session session)
|
|||||||
}
|
}
|
||||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbytes < 0)
|
if (nbytes < 0)
|
||||||
{
|
{
|
||||||
ssh_channel_close(channel);
|
ssh_channel_close(channel);
|
||||||
@@ -456,7 +456,7 @@ might be recoverable. SSH_FATAL means the connection has an important
|
|||||||
problem and isn't probably recoverable.
|
problem and isn't probably recoverable.
|
||||||
|
|
||||||
Most of time, the error returned are SSH_FATAL, but some functions
|
Most of time, the error returned are SSH_FATAL, but some functions
|
||||||
(generaly the ssh_request_xxx ones) may fail because of server denying request.
|
(generally the ssh_request_xxx ones) may fail because of server denying request.
|
||||||
In these cases, SSH_REQUEST_DENIED is returned.
|
In these cases, SSH_REQUEST_DENIED is returned.
|
||||||
|
|
||||||
For thread safety, errors are bound to ssh_session objects.
|
For thread safety, errors are bound to ssh_session objects.
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ mean that you should not try to know about and understand these details.
|
|||||||
|
|
||||||
libssh is a Free Software / Open Source project. The libssh library
|
libssh is a Free Software / Open Source project. The libssh library
|
||||||
is distributed under LGPL license. The libssh project has nothing to do with
|
is distributed under LGPL license. The libssh project has nothing to do with
|
||||||
"libssh2", which is a completly different and independant project.
|
"libssh2", which is a completely different and independent project.
|
||||||
|
|
||||||
libssh can run on top of either libgcrypt or libcrypto,
|
libssh can run on top of either libgcrypt or libcrypto,
|
||||||
two general-purpose cryptographic libraries.
|
two general-purpose cryptographic libraries.
|
||||||
|
|
||||||
This tutorial concentrates for its main part on the "client" side of libssh.
|
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 connections (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 a little different
|
This tutorial describes libssh version 0.5.0. This version is a little different
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
@page libssh_tutor_scp Chapter 6: The SCP subsystem
|
@page libssh_tutor_scp Chapter 6: The SCP subsystem
|
||||||
@section scp_subsystem The SCP subsystem
|
@section scp_subsystem The SCP subsystem
|
||||||
|
|
||||||
The SCP subsystem has far less functionnality than the SFTP subsystem.
|
The SCP subsystem has far less functionality than the SFTP subsystem.
|
||||||
However, if you only need to copy files from and to the remote system,
|
However, if you only need to copy files from and to the remote system,
|
||||||
it does its job.
|
it does its job.
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ Let's say you want to copy the following tree of files to the remote site:
|
|||||||
+-- file1
|
+-- file1
|
||||||
+-- B --+
|
+-- B --+
|
||||||
| +-- file2
|
| +-- file2
|
||||||
-- A --+
|
-- A --+
|
||||||
| +-- file3
|
| +-- file3
|
||||||
+-- C --+
|
+-- C --+
|
||||||
+-- file4
|
+-- file4
|
||||||
@@ -210,7 +210,7 @@ int scp_receive(ssh_session session, ssh_scp scp)
|
|||||||
size = ssh_scp_request_get_size(scp);
|
size = ssh_scp_request_get_size(scp);
|
||||||
filename = strdup(ssh_scp_request_get_filename(scp));
|
filename = strdup(ssh_scp_request_get_filename(scp));
|
||||||
mode = ssh_scp_request_get_permissions(scp);
|
mode = ssh_scp_request_get_permissions(scp);
|
||||||
printf("Receiving file %s, size %d, permisssions 0%o\n",
|
printf("Receiving file %s, size %d, permissions 0%o\n",
|
||||||
filename, size, mode);
|
filename, size, mode);
|
||||||
free(filename);
|
free(filename);
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ Possible errors are:
|
|||||||
|
|
||||||
@subsection sftp_mkdir Creating a directory
|
@subsection sftp_mkdir Creating a directory
|
||||||
|
|
||||||
The function sftp_mkdir() tahes the "SFTP session" we juste created as
|
The function sftp_mkdir() takes the "SFTP session" we just created as
|
||||||
its first argument. It also needs the name of the file to create, and the
|
its first argument. It also needs the name of the file to create, and the
|
||||||
desired permissions. The permissions are the same as for the usual mkdir()
|
desired permissions. The permissions are the same as for the usual mkdir()
|
||||||
function. To get a comprehensive list of the available permissions, use the
|
function. To get a comprehensive list of the available permissions, use the
|
||||||
@@ -358,19 +358,19 @@ int sftp_read_async(ssh_session session, sftp_session sftp)
|
|||||||
@subsection sftp_ls Listing the contents of a directory
|
@subsection sftp_ls Listing the contents of a directory
|
||||||
|
|
||||||
The functions sftp_opendir(), sftp_readdir(), sftp_dir_eof(),
|
The functions sftp_opendir(), sftp_readdir(), sftp_dir_eof(),
|
||||||
and sftp_closedir() enable to list the contents of a directory.
|
and sftp_closedir() enable to list the contents of a directory.
|
||||||
They use a new handle_type, "sftp_dir", which gives access to the
|
They use a new handle_type, "sftp_dir", which gives access to the
|
||||||
directory being read.
|
directory being read.
|
||||||
|
|
||||||
In addition, sftp_readdir() returns a "sftp_attributes" which is a pointer
|
In addition, sftp_readdir() returns a "sftp_attributes" which is a pointer
|
||||||
to a structure with informations about a directory entry:
|
to a structure with information about a directory entry:
|
||||||
- name: the name of the file or directory
|
- name: the name of the file or directory
|
||||||
- size: its size in bytes
|
- size: its size in bytes
|
||||||
- etc.
|
- etc.
|
||||||
|
|
||||||
sftp_readdir() might return NULL under two conditions:
|
sftp_readdir() might return NULL under two conditions:
|
||||||
- when the end of the directory has been met
|
- when the end of the directory has been met
|
||||||
- when an error occured
|
- when an error occurred
|
||||||
|
|
||||||
To tell the difference, call sftp_dir_eof().
|
To tell the difference, call sftp_dir_eof().
|
||||||
|
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ int interactive_shell_session(ssh_channel channel)
|
|||||||
|
|
||||||
Of course, this is a poor terminal emulator, since the echo from the keys
|
Of course, this is a poor terminal emulator, since the echo from the keys
|
||||||
pressed should not be done locally, but should be done by the remote side.
|
pressed should not be done locally, but should be done by the remote side.
|
||||||
Also, user's input should not be sent once "Enter" key is pressed, but
|
Also, user's input should not be sent once "Enter" key is pressed, but
|
||||||
immediately after each key is pressed. This can be accomplished
|
immediately after each key is pressed. This can be accomplished
|
||||||
by setting the local terminal to "raw" mode with the cfmakeraw(3) function.
|
by setting the local terminal to "raw" mode with the cfmakeraw(3) function.
|
||||||
cfmakeraw() is a standard function under Linux, on other systems you can
|
cfmakeraw() is a standard function under Linux, on other systems you can
|
||||||
@@ -245,13 +245,13 @@ provide a more elegant way to wait for data coming from many sources.
|
|||||||
|
|
||||||
The functions ssh_select() and ssh_channel_select() remind of the standard
|
The functions ssh_select() and ssh_channel_select() remind of the standard
|
||||||
UNIX select(2) function. The idea is to wait for "something" to happen:
|
UNIX select(2) function. The idea is to wait for "something" to happen:
|
||||||
incoming data to be read, outcoming data to block, or an exception to
|
incoming data to be read, outgoing data to block, or an exception to
|
||||||
occur. Both these functions do a "passive wait", i.e. you can safely use
|
occur. Both these functions do a "passive wait", i.e. you can safely use
|
||||||
them repeatedly in a loop, it will not consume exaggerate processor time
|
them repeatedly in a loop, it will not consume exaggerate processor time
|
||||||
and make your computer unresponsive. It is quite common to use these
|
and make your computer unresponsive. It is quite common to use these
|
||||||
functions in your application's main loop.
|
functions in your application's main loop.
|
||||||
|
|
||||||
The difference between ssh_select() and ssh_channel_select() is that
|
The difference between ssh_select() and ssh_channel_select() is that
|
||||||
ssh_channel_select() is simpler, but allows you only to watch SSH channels.
|
ssh_channel_select() is simpler, but allows you only to watch SSH channels.
|
||||||
ssh_select() is more complete and enables watching regular file descriptors
|
ssh_select() is more complete and enables watching regular file descriptors
|
||||||
as well, in the same function call.
|
as well, in the same function call.
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ libssh may be used in multithreaded applications, but under several conditions :
|
|||||||
- If libssh is statically linked, threading must be initialized by calling
|
- If libssh is statically linked, threading must be initialized by calling
|
||||||
ssh_init() before using any of libssh provided functions. This initialization
|
ssh_init() before using any of libssh provided functions. This initialization
|
||||||
must be done outside of any threading context. Don't forget to call
|
must be done outside of any threading context. Don't forget to call
|
||||||
ssh_finalize() to avoid memory leak
|
ssh_finalize() to avoid memory leak
|
||||||
- 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 *cannot* use a
|
connections, read/write on different sessions and so on. You *cannot* use a
|
||||||
single session (or channels for a single session) in several threads at the same
|
single session (or channels for a single session) in several threads at the same
|
||||||
time. This will most likely lead to internal state corruption. This limitation is
|
time. This will most likely lead to internal state corruption. This limitation is
|
||||||
being worked out and will maybe disappear later.
|
being worked out and will maybe disappear later.
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ clients must be made or how a client should react.
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#define SSHD_USER "libssh"
|
#define SSHD_USER "libssh"
|
||||||
#define SSHD_PASSWORD "libssh"
|
#define SSHD_PASSWORD "libssh"
|
||||||
@@ -36,6 +37,7 @@ clients must be made or how a client should react.
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int port = 22;
|
static int port = 22;
|
||||||
|
static bool authenticated = false;
|
||||||
|
|
||||||
#ifdef WITH_PCAP
|
#ifdef WITH_PCAP
|
||||||
static const char *pcap_file = "debug.server.pcap";
|
static const char *pcap_file = "debug.server.pcap";
|
||||||
@@ -61,11 +63,20 @@ static void cleanup_pcap(void) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static int auth_password(const char *user, const char *password){
|
static int auth_password(const char *user, const char *password)
|
||||||
if(strcmp(user, SSHD_USER))
|
{
|
||||||
|
int cmp;
|
||||||
|
|
||||||
|
cmp = strcmp(user, SSHD_USER);
|
||||||
|
if (cmp != 0) {
|
||||||
return 0;
|
return 0;
|
||||||
if(strcmp(password, SSHD_PASSWORD))
|
}
|
||||||
|
cmp = strcmp(password, SSHD_PASSWORD);
|
||||||
|
if (cmp != 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticated = true;
|
||||||
return 1; // authenticated
|
return 1; // authenticated
|
||||||
}
|
}
|
||||||
#ifdef HAVE_ARGP_H
|
#ifdef HAVE_ARGP_H
|
||||||
@@ -200,6 +211,7 @@ static int kbdint_check_response(ssh_session session) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
authenticated = true;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,7 +340,7 @@ int main(int argc, char **argv){
|
|||||||
|
|
||||||
/* proceed to authentication */
|
/* proceed to authentication */
|
||||||
auth = authenticate(session);
|
auth = authenticate(session);
|
||||||
if(!auth){
|
if (!auth || !authenticated) {
|
||||||
printf("Authentication error: %s\n", ssh_get_error(session));
|
printf("Authentication error: %s\n", ssh_get_error(session));
|
||||||
ssh_disconnect(session);
|
ssh_disconnect(session);
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -45,5 +45,6 @@ char *ssh_find_matching(const char *in_d, const char *what_d);
|
|||||||
const char *ssh_kex_get_supported_method(uint32_t algo);
|
const char *ssh_kex_get_supported_method(uint32_t algo);
|
||||||
const char *ssh_kex_get_default_methods(uint32_t algo);
|
const char *ssh_kex_get_default_methods(uint32_t algo);
|
||||||
const char *ssh_kex_get_description(uint32_t algo);
|
const char *ssh_kex_get_description(uint32_t algo);
|
||||||
|
char *ssh_client_select_hostkeys(ssh_session session);
|
||||||
|
|
||||||
#endif /* KEX_H_ */
|
#endif /* KEX_H_ */
|
||||||
|
|||||||
@@ -23,5 +23,9 @@
|
|||||||
#define SSH_KNOWNHOSTS_H_
|
#define SSH_KNOWNHOSTS_H_
|
||||||
|
|
||||||
struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session);
|
struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session);
|
||||||
|
enum ssh_known_hosts_e
|
||||||
|
ssh_session_get_known_hosts_entry_file(ssh_session session,
|
||||||
|
const char *filename,
|
||||||
|
struct ssh_knownhosts_entry **pentry);
|
||||||
|
|
||||||
#endif /* SSH_KNOWNHOSTS_H_ */
|
#endif /* SSH_KNOWNHOSTS_H_ */
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
/* libssh version */
|
/* libssh version */
|
||||||
#define LIBSSH_VERSION_MAJOR 0
|
#define LIBSSH_VERSION_MAJOR 0
|
||||||
#define LIBSSH_VERSION_MINOR 8
|
#define LIBSSH_VERSION_MINOR 8
|
||||||
#define LIBSSH_VERSION_MICRO 4
|
#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, \
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#ifndef _LIBSSH_PRIV_H
|
#ifndef _LIBSSH_PRIV_H
|
||||||
#define _LIBSSH_PRIV_H
|
#define _LIBSSH_PRIV_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -128,6 +129,13 @@ char *strndup(const char *s, size_t n);
|
|||||||
# endif /* HAVE__VSNPRINTF */
|
# endif /* HAVE__VSNPRINTF */
|
||||||
# endif /* HAVE__VSNPRINTF_S */
|
# endif /* HAVE__VSNPRINTF_S */
|
||||||
|
|
||||||
|
# ifndef _SSIZE_T_DEFINED
|
||||||
|
# undef ssize_t
|
||||||
|
# include <BaseTsd.h>
|
||||||
|
typedef _W64 SSIZE_T ssize_t;
|
||||||
|
# define _SSIZE_T_DEFINED
|
||||||
|
# endif /* _SSIZE_T_DEFINED */
|
||||||
|
|
||||||
# endif /* _MSC_VER */
|
# endif /* _MSC_VER */
|
||||||
|
|
||||||
struct timeval;
|
struct timeval;
|
||||||
|
|||||||
@@ -53,9 +53,14 @@ extern "C" {
|
|||||||
typedef uint32_t gid_t;
|
typedef uint32_t gid_t;
|
||||||
#endif /* gid_t */
|
#endif /* gid_t */
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#ifndef ssize_t
|
|
||||||
typedef _W64 SSIZE_T ssize_t;
|
# ifndef _SSIZE_T_DEFINED
|
||||||
#endif /* ssize_t */
|
# undef ssize_t
|
||||||
|
# include <BaseTsd.h>
|
||||||
|
typedef _W64 SSIZE_T ssize_t;
|
||||||
|
# define _SSIZE_T_DEFINED
|
||||||
|
# endif /* _SSIZE_T_DEFINED */
|
||||||
|
|
||||||
#endif /* _MSC_VER */
|
#endif /* _MSC_VER */
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ ssh_socket ssh_socket_new(ssh_session session);
|
|||||||
void ssh_socket_reset(ssh_socket s);
|
void ssh_socket_reset(ssh_socket s);
|
||||||
void ssh_socket_free(ssh_socket s);
|
void ssh_socket_free(ssh_socket s);
|
||||||
void ssh_socket_set_fd(ssh_socket s, socket_t fd);
|
void ssh_socket_set_fd(ssh_socket s, socket_t fd);
|
||||||
socket_t ssh_socket_get_fd_in(ssh_socket s);
|
socket_t ssh_socket_get_fd(ssh_socket s);
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
int ssh_socket_unix(ssh_socket s, const char *path);
|
int ssh_socket_unix(ssh_socket s, const char *path);
|
||||||
void ssh_execute_command(const char *command, socket_t in, socket_t out);
|
void ssh_execute_command(const char *command, socket_t in, socket_t out);
|
||||||
@@ -61,8 +61,7 @@ int ssh_socket_set_blocking(socket_t fd);
|
|||||||
|
|
||||||
void ssh_socket_set_callbacks(ssh_socket s, ssh_socket_callbacks callbacks);
|
void ssh_socket_set_callbacks(ssh_socket s, ssh_socket_callbacks callbacks);
|
||||||
int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int revents, void *v_s);
|
int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int revents, void *v_s);
|
||||||
struct ssh_poll_handle_struct * ssh_socket_get_poll_handle_in(ssh_socket s);
|
struct ssh_poll_handle_struct * ssh_socket_get_poll_handle(ssh_socket s);
|
||||||
struct ssh_poll_handle_struct * ssh_socket_get_poll_handle_out(ssh_socket s);
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
4.7.1
|
4.7.2
|
||||||
415
src/ABI/libssh-4.7.2.symbols
Normal file
415
src/ABI/libssh-4.7.2.symbols
Normal file
@@ -0,0 +1,415 @@
|
|||||||
|
_ssh_log
|
||||||
|
buffer_free
|
||||||
|
buffer_get
|
||||||
|
buffer_get_len
|
||||||
|
buffer_new
|
||||||
|
channel_accept_x11
|
||||||
|
channel_change_pty_size
|
||||||
|
channel_close
|
||||||
|
channel_forward_accept
|
||||||
|
channel_forward_cancel
|
||||||
|
channel_forward_listen
|
||||||
|
channel_free
|
||||||
|
channel_get_exit_status
|
||||||
|
channel_get_session
|
||||||
|
channel_is_closed
|
||||||
|
channel_is_eof
|
||||||
|
channel_is_open
|
||||||
|
channel_new
|
||||||
|
channel_open_forward
|
||||||
|
channel_open_session
|
||||||
|
channel_poll
|
||||||
|
channel_read
|
||||||
|
channel_read_buffer
|
||||||
|
channel_read_nonblocking
|
||||||
|
channel_request_env
|
||||||
|
channel_request_exec
|
||||||
|
channel_request_pty
|
||||||
|
channel_request_pty_size
|
||||||
|
channel_request_send_signal
|
||||||
|
channel_request_sftp
|
||||||
|
channel_request_shell
|
||||||
|
channel_request_subsystem
|
||||||
|
channel_request_x11
|
||||||
|
channel_select
|
||||||
|
channel_send_eof
|
||||||
|
channel_set_blocking
|
||||||
|
channel_write
|
||||||
|
channel_write_stderr
|
||||||
|
privatekey_free
|
||||||
|
privatekey_from_file
|
||||||
|
publickey_free
|
||||||
|
publickey_from_file
|
||||||
|
publickey_from_privatekey
|
||||||
|
publickey_to_string
|
||||||
|
sftp_async_read
|
||||||
|
sftp_async_read_begin
|
||||||
|
sftp_attributes_free
|
||||||
|
sftp_canonicalize_path
|
||||||
|
sftp_chmod
|
||||||
|
sftp_chown
|
||||||
|
sftp_client_message_free
|
||||||
|
sftp_client_message_get_data
|
||||||
|
sftp_client_message_get_filename
|
||||||
|
sftp_client_message_get_flags
|
||||||
|
sftp_client_message_get_submessage
|
||||||
|
sftp_client_message_get_type
|
||||||
|
sftp_client_message_set_filename
|
||||||
|
sftp_close
|
||||||
|
sftp_closedir
|
||||||
|
sftp_dir_eof
|
||||||
|
sftp_extension_supported
|
||||||
|
sftp_extensions_get_count
|
||||||
|
sftp_extensions_get_data
|
||||||
|
sftp_extensions_get_name
|
||||||
|
sftp_file_set_blocking
|
||||||
|
sftp_file_set_nonblocking
|
||||||
|
sftp_free
|
||||||
|
sftp_fstat
|
||||||
|
sftp_fstatvfs
|
||||||
|
sftp_fsync
|
||||||
|
sftp_get_client_message
|
||||||
|
sftp_get_error
|
||||||
|
sftp_handle
|
||||||
|
sftp_handle_alloc
|
||||||
|
sftp_handle_remove
|
||||||
|
sftp_init
|
||||||
|
sftp_lstat
|
||||||
|
sftp_mkdir
|
||||||
|
sftp_new
|
||||||
|
sftp_new_channel
|
||||||
|
sftp_open
|
||||||
|
sftp_opendir
|
||||||
|
sftp_read
|
||||||
|
sftp_readdir
|
||||||
|
sftp_readlink
|
||||||
|
sftp_rename
|
||||||
|
sftp_reply_attr
|
||||||
|
sftp_reply_data
|
||||||
|
sftp_reply_handle
|
||||||
|
sftp_reply_name
|
||||||
|
sftp_reply_names
|
||||||
|
sftp_reply_names_add
|
||||||
|
sftp_reply_status
|
||||||
|
sftp_rewind
|
||||||
|
sftp_rmdir
|
||||||
|
sftp_seek
|
||||||
|
sftp_seek64
|
||||||
|
sftp_send_client_message
|
||||||
|
sftp_server_init
|
||||||
|
sftp_server_new
|
||||||
|
sftp_server_version
|
||||||
|
sftp_setstat
|
||||||
|
sftp_stat
|
||||||
|
sftp_statvfs
|
||||||
|
sftp_statvfs_free
|
||||||
|
sftp_symlink
|
||||||
|
sftp_tell
|
||||||
|
sftp_tell64
|
||||||
|
sftp_unlink
|
||||||
|
sftp_utimes
|
||||||
|
sftp_write
|
||||||
|
ssh_accept
|
||||||
|
ssh_add_channel_callbacks
|
||||||
|
ssh_auth_list
|
||||||
|
ssh_basename
|
||||||
|
ssh_bind_accept
|
||||||
|
ssh_bind_accept_fd
|
||||||
|
ssh_bind_fd_toaccept
|
||||||
|
ssh_bind_free
|
||||||
|
ssh_bind_get_fd
|
||||||
|
ssh_bind_listen
|
||||||
|
ssh_bind_new
|
||||||
|
ssh_bind_options_set
|
||||||
|
ssh_bind_set_blocking
|
||||||
|
ssh_bind_set_callbacks
|
||||||
|
ssh_bind_set_fd
|
||||||
|
ssh_blocking_flush
|
||||||
|
ssh_buffer_add_data
|
||||||
|
ssh_buffer_free
|
||||||
|
ssh_buffer_get
|
||||||
|
ssh_buffer_get_data
|
||||||
|
ssh_buffer_get_len
|
||||||
|
ssh_buffer_new
|
||||||
|
ssh_buffer_reinit
|
||||||
|
ssh_channel_accept_forward
|
||||||
|
ssh_channel_accept_x11
|
||||||
|
ssh_channel_cancel_forward
|
||||||
|
ssh_channel_change_pty_size
|
||||||
|
ssh_channel_close
|
||||||
|
ssh_channel_free
|
||||||
|
ssh_channel_get_exit_status
|
||||||
|
ssh_channel_get_session
|
||||||
|
ssh_channel_is_closed
|
||||||
|
ssh_channel_is_eof
|
||||||
|
ssh_channel_is_open
|
||||||
|
ssh_channel_listen_forward
|
||||||
|
ssh_channel_new
|
||||||
|
ssh_channel_open_auth_agent
|
||||||
|
ssh_channel_open_forward
|
||||||
|
ssh_channel_open_reverse_forward
|
||||||
|
ssh_channel_open_session
|
||||||
|
ssh_channel_open_x11
|
||||||
|
ssh_channel_poll
|
||||||
|
ssh_channel_poll_timeout
|
||||||
|
ssh_channel_read
|
||||||
|
ssh_channel_read_nonblocking
|
||||||
|
ssh_channel_read_timeout
|
||||||
|
ssh_channel_request_auth_agent
|
||||||
|
ssh_channel_request_env
|
||||||
|
ssh_channel_request_exec
|
||||||
|
ssh_channel_request_pty
|
||||||
|
ssh_channel_request_pty_size
|
||||||
|
ssh_channel_request_send_break
|
||||||
|
ssh_channel_request_send_exit_signal
|
||||||
|
ssh_channel_request_send_exit_status
|
||||||
|
ssh_channel_request_send_signal
|
||||||
|
ssh_channel_request_sftp
|
||||||
|
ssh_channel_request_shell
|
||||||
|
ssh_channel_request_subsystem
|
||||||
|
ssh_channel_request_x11
|
||||||
|
ssh_channel_select
|
||||||
|
ssh_channel_send_eof
|
||||||
|
ssh_channel_set_blocking
|
||||||
|
ssh_channel_set_counter
|
||||||
|
ssh_channel_window_size
|
||||||
|
ssh_channel_write
|
||||||
|
ssh_channel_write_stderr
|
||||||
|
ssh_clean_pubkey_hash
|
||||||
|
ssh_connect
|
||||||
|
ssh_connector_free
|
||||||
|
ssh_connector_new
|
||||||
|
ssh_connector_set_in_channel
|
||||||
|
ssh_connector_set_in_fd
|
||||||
|
ssh_connector_set_out_channel
|
||||||
|
ssh_connector_set_out_fd
|
||||||
|
ssh_copyright
|
||||||
|
ssh_dirname
|
||||||
|
ssh_disconnect
|
||||||
|
ssh_dump_knownhost
|
||||||
|
ssh_event_add_connector
|
||||||
|
ssh_event_add_fd
|
||||||
|
ssh_event_add_session
|
||||||
|
ssh_event_dopoll
|
||||||
|
ssh_event_free
|
||||||
|
ssh_event_new
|
||||||
|
ssh_event_remove_connector
|
||||||
|
ssh_event_remove_fd
|
||||||
|
ssh_event_remove_session
|
||||||
|
ssh_execute_message_callbacks
|
||||||
|
ssh_finalize
|
||||||
|
ssh_forward_accept
|
||||||
|
ssh_forward_cancel
|
||||||
|
ssh_forward_listen
|
||||||
|
ssh_free
|
||||||
|
ssh_get_cipher_in
|
||||||
|
ssh_get_cipher_out
|
||||||
|
ssh_get_clientbanner
|
||||||
|
ssh_get_disconnect_message
|
||||||
|
ssh_get_error
|
||||||
|
ssh_get_error_code
|
||||||
|
ssh_get_fd
|
||||||
|
ssh_get_fingerprint_hash
|
||||||
|
ssh_get_hexa
|
||||||
|
ssh_get_hmac_in
|
||||||
|
ssh_get_hmac_out
|
||||||
|
ssh_get_issue_banner
|
||||||
|
ssh_get_kex_algo
|
||||||
|
ssh_get_log_callback
|
||||||
|
ssh_get_log_level
|
||||||
|
ssh_get_log_userdata
|
||||||
|
ssh_get_openssh_version
|
||||||
|
ssh_get_poll_flags
|
||||||
|
ssh_get_pubkey
|
||||||
|
ssh_get_pubkey_hash
|
||||||
|
ssh_get_publickey
|
||||||
|
ssh_get_publickey_hash
|
||||||
|
ssh_get_random
|
||||||
|
ssh_get_server_publickey
|
||||||
|
ssh_get_serverbanner
|
||||||
|
ssh_get_status
|
||||||
|
ssh_get_version
|
||||||
|
ssh_getpass
|
||||||
|
ssh_gssapi_get_creds
|
||||||
|
ssh_gssapi_set_creds
|
||||||
|
ssh_handle_key_exchange
|
||||||
|
ssh_init
|
||||||
|
ssh_is_blocking
|
||||||
|
ssh_is_connected
|
||||||
|
ssh_is_server_known
|
||||||
|
ssh_key_cmp
|
||||||
|
ssh_key_free
|
||||||
|
ssh_key_is_private
|
||||||
|
ssh_key_is_public
|
||||||
|
ssh_key_new
|
||||||
|
ssh_key_type
|
||||||
|
ssh_key_type_from_name
|
||||||
|
ssh_key_type_to_char
|
||||||
|
ssh_known_hosts_parse_line
|
||||||
|
ssh_knownhosts_entry_free
|
||||||
|
ssh_log
|
||||||
|
ssh_message_auth_interactive_request
|
||||||
|
ssh_message_auth_kbdint_is_response
|
||||||
|
ssh_message_auth_password
|
||||||
|
ssh_message_auth_pubkey
|
||||||
|
ssh_message_auth_publickey
|
||||||
|
ssh_message_auth_publickey_state
|
||||||
|
ssh_message_auth_reply_pk_ok
|
||||||
|
ssh_message_auth_reply_pk_ok_simple
|
||||||
|
ssh_message_auth_reply_success
|
||||||
|
ssh_message_auth_set_methods
|
||||||
|
ssh_message_auth_user
|
||||||
|
ssh_message_channel_request_channel
|
||||||
|
ssh_message_channel_request_command
|
||||||
|
ssh_message_channel_request_env_name
|
||||||
|
ssh_message_channel_request_env_value
|
||||||
|
ssh_message_channel_request_open_destination
|
||||||
|
ssh_message_channel_request_open_destination_port
|
||||||
|
ssh_message_channel_request_open_originator
|
||||||
|
ssh_message_channel_request_open_originator_port
|
||||||
|
ssh_message_channel_request_open_reply_accept
|
||||||
|
ssh_message_channel_request_pty_height
|
||||||
|
ssh_message_channel_request_pty_pxheight
|
||||||
|
ssh_message_channel_request_pty_pxwidth
|
||||||
|
ssh_message_channel_request_pty_term
|
||||||
|
ssh_message_channel_request_pty_width
|
||||||
|
ssh_message_channel_request_reply_success
|
||||||
|
ssh_message_channel_request_subsystem
|
||||||
|
ssh_message_channel_request_x11_auth_cookie
|
||||||
|
ssh_message_channel_request_x11_auth_protocol
|
||||||
|
ssh_message_channel_request_x11_screen_number
|
||||||
|
ssh_message_channel_request_x11_single_connection
|
||||||
|
ssh_message_free
|
||||||
|
ssh_message_get
|
||||||
|
ssh_message_global_request_address
|
||||||
|
ssh_message_global_request_port
|
||||||
|
ssh_message_global_request_reply_success
|
||||||
|
ssh_message_reply_default
|
||||||
|
ssh_message_retrieve
|
||||||
|
ssh_message_service_reply_success
|
||||||
|
ssh_message_service_service
|
||||||
|
ssh_message_subtype
|
||||||
|
ssh_message_type
|
||||||
|
ssh_mkdir
|
||||||
|
ssh_new
|
||||||
|
ssh_options_copy
|
||||||
|
ssh_options_get
|
||||||
|
ssh_options_get_port
|
||||||
|
ssh_options_getopt
|
||||||
|
ssh_options_parse_config
|
||||||
|
ssh_options_set
|
||||||
|
ssh_pcap_file_close
|
||||||
|
ssh_pcap_file_free
|
||||||
|
ssh_pcap_file_new
|
||||||
|
ssh_pcap_file_open
|
||||||
|
ssh_pki_copy_cert_to_privkey
|
||||||
|
ssh_pki_export_privkey_base64
|
||||||
|
ssh_pki_export_privkey_file
|
||||||
|
ssh_pki_export_privkey_to_pubkey
|
||||||
|
ssh_pki_export_pubkey_base64
|
||||||
|
ssh_pki_export_pubkey_file
|
||||||
|
ssh_pki_generate
|
||||||
|
ssh_pki_import_cert_base64
|
||||||
|
ssh_pki_import_cert_file
|
||||||
|
ssh_pki_import_privkey_base64
|
||||||
|
ssh_pki_import_privkey_file
|
||||||
|
ssh_pki_import_pubkey_base64
|
||||||
|
ssh_pki_import_pubkey_file
|
||||||
|
ssh_pki_key_ecdsa_name
|
||||||
|
ssh_print_hash
|
||||||
|
ssh_print_hexa
|
||||||
|
ssh_privatekey_type
|
||||||
|
ssh_publickey_to_file
|
||||||
|
ssh_remove_channel_callbacks
|
||||||
|
ssh_scp_accept_request
|
||||||
|
ssh_scp_close
|
||||||
|
ssh_scp_deny_request
|
||||||
|
ssh_scp_free
|
||||||
|
ssh_scp_init
|
||||||
|
ssh_scp_leave_directory
|
||||||
|
ssh_scp_new
|
||||||
|
ssh_scp_pull_request
|
||||||
|
ssh_scp_push_directory
|
||||||
|
ssh_scp_push_file
|
||||||
|
ssh_scp_push_file64
|
||||||
|
ssh_scp_read
|
||||||
|
ssh_scp_request_get_filename
|
||||||
|
ssh_scp_request_get_permissions
|
||||||
|
ssh_scp_request_get_size
|
||||||
|
ssh_scp_request_get_size64
|
||||||
|
ssh_scp_request_get_warning
|
||||||
|
ssh_scp_write
|
||||||
|
ssh_select
|
||||||
|
ssh_send_debug
|
||||||
|
ssh_send_ignore
|
||||||
|
ssh_send_keepalive
|
||||||
|
ssh_server_init_kex
|
||||||
|
ssh_service_request
|
||||||
|
ssh_session_export_known_hosts_entry
|
||||||
|
ssh_session_has_known_hosts_entry
|
||||||
|
ssh_session_is_known_server
|
||||||
|
ssh_session_update_known_hosts
|
||||||
|
ssh_set_agent_channel
|
||||||
|
ssh_set_agent_socket
|
||||||
|
ssh_set_auth_methods
|
||||||
|
ssh_set_blocking
|
||||||
|
ssh_set_callbacks
|
||||||
|
ssh_set_channel_callbacks
|
||||||
|
ssh_set_counters
|
||||||
|
ssh_set_fd_except
|
||||||
|
ssh_set_fd_toread
|
||||||
|
ssh_set_fd_towrite
|
||||||
|
ssh_set_log_callback
|
||||||
|
ssh_set_log_level
|
||||||
|
ssh_set_log_userdata
|
||||||
|
ssh_set_message_callback
|
||||||
|
ssh_set_pcap_file
|
||||||
|
ssh_set_server_callbacks
|
||||||
|
ssh_silent_disconnect
|
||||||
|
ssh_string_burn
|
||||||
|
ssh_string_copy
|
||||||
|
ssh_string_data
|
||||||
|
ssh_string_fill
|
||||||
|
ssh_string_free
|
||||||
|
ssh_string_free_char
|
||||||
|
ssh_string_from_char
|
||||||
|
ssh_string_get_char
|
||||||
|
ssh_string_len
|
||||||
|
ssh_string_new
|
||||||
|
ssh_string_to_char
|
||||||
|
ssh_threads_get_noop
|
||||||
|
ssh_threads_get_pthread
|
||||||
|
ssh_threads_set_callbacks
|
||||||
|
ssh_try_publickey_from_file
|
||||||
|
ssh_userauth_agent
|
||||||
|
ssh_userauth_agent_pubkey
|
||||||
|
ssh_userauth_autopubkey
|
||||||
|
ssh_userauth_gssapi
|
||||||
|
ssh_userauth_kbdint
|
||||||
|
ssh_userauth_kbdint_getanswer
|
||||||
|
ssh_userauth_kbdint_getinstruction
|
||||||
|
ssh_userauth_kbdint_getname
|
||||||
|
ssh_userauth_kbdint_getnanswers
|
||||||
|
ssh_userauth_kbdint_getnprompts
|
||||||
|
ssh_userauth_kbdint_getprompt
|
||||||
|
ssh_userauth_kbdint_setanswer
|
||||||
|
ssh_userauth_list
|
||||||
|
ssh_userauth_none
|
||||||
|
ssh_userauth_offer_pubkey
|
||||||
|
ssh_userauth_password
|
||||||
|
ssh_userauth_privatekey_file
|
||||||
|
ssh_userauth_pubkey
|
||||||
|
ssh_userauth_publickey
|
||||||
|
ssh_userauth_publickey_auto
|
||||||
|
ssh_userauth_try_publickey
|
||||||
|
ssh_version
|
||||||
|
ssh_write_knownhost
|
||||||
|
string_burn
|
||||||
|
string_copy
|
||||||
|
string_data
|
||||||
|
string_fill
|
||||||
|
string_free
|
||||||
|
string_from_char
|
||||||
|
string_len
|
||||||
|
string_new
|
||||||
|
string_to_char
|
||||||
@@ -93,7 +93,7 @@ static size_t atomicio(struct ssh_agent_struct *agent, void *buf, size_t n, int
|
|||||||
|
|
||||||
/* Using a socket ? */
|
/* Using a socket ? */
|
||||||
if (channel == NULL) {
|
if (channel == NULL) {
|
||||||
fd = ssh_socket_get_fd_in(agent->sock);
|
fd = ssh_socket_get_fd(agent->sock);
|
||||||
pfd.fd = fd;
|
pfd.fd = fd;
|
||||||
pfd.events = do_read ? POLLIN : POLLOUT;
|
pfd.events = do_read ? POLLIN : POLLOUT;
|
||||||
|
|
||||||
|
|||||||
@@ -447,7 +447,7 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
ssh_socket_set_fd(session->socket, fd);
|
ssh_socket_set_fd(session->socket, fd);
|
||||||
ssh_socket_get_poll_handle_out(session->socket);
|
ssh_socket_get_poll_handle(session->socket);
|
||||||
|
|
||||||
/* We must try to import any keys that could be imported in case
|
/* We must try to import any keys that could be imported in case
|
||||||
* we are not using ssh_bind_listen (which is the other place
|
* we are not using ssh_bind_listen (which is the other place
|
||||||
|
|||||||
23
src/client.c
23
src/client.c
@@ -411,6 +411,14 @@ static void ssh_client_connection_callback(ssh_session session)
|
|||||||
|
|
||||||
ssh_packet_set_default_callbacks(session);
|
ssh_packet_set_default_callbacks(session);
|
||||||
session->session_state = SSH_SESSION_STATE_INITIAL_KEX;
|
session->session_state = SSH_SESSION_STATE_INITIAL_KEX;
|
||||||
|
rc = ssh_set_client_kex(session);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
rc = ssh_send_kex(session, 0);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
set_status(session, 0.5f);
|
set_status(session, 0.5f);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -420,14 +428,19 @@ static void ssh_client_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->next_crypto->server_kex);
|
ssh_list_kex(&session->next_crypto->server_kex);
|
||||||
if (ssh_set_client_kex(session) < 0) {
|
if (session->next_crypto->client_kex.methods[0] == NULL) {
|
||||||
goto error;
|
/* in rekeying state if next_crypto client_kex is empty */
|
||||||
|
rc = ssh_set_client_kex(session);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
rc = ssh_send_kex(session, 0);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ssh_kex_select_methods(session) == SSH_ERROR)
|
if (ssh_kex_select_methods(session) == SSH_ERROR)
|
||||||
goto error;
|
goto error;
|
||||||
if (ssh_send_kex(session, 0) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
set_status(session,0.8f);
|
set_status(session,0.8f);
|
||||||
session->session_state=SSH_SESSION_STATE_DH;
|
session->session_state=SSH_SESSION_STATE_DH;
|
||||||
if (dh_handshake(session) == SSH_ERROR) {
|
if (dh_handshake(session) == SSH_ERROR) {
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ static int ssh_gssapi_send_response(ssh_session session, ssh_string oid){
|
|||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
session->auth.state = SSH_AUTH_STATE_GSSAPI_TOKEN;
|
||||||
|
|
||||||
ssh_packet_send(session);
|
ssh_packet_send(session);
|
||||||
SSH_LOG(SSH_LOG_PACKET,
|
SSH_LOG(SSH_LOG_PACKET,
|
||||||
|
|||||||
39
src/kex.c
39
src/kex.c
@@ -26,6 +26,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "libssh/priv.h"
|
#include "libssh/priv.h"
|
||||||
#include "libssh/buffer.h"
|
#include "libssh/buffer.h"
|
||||||
@@ -592,9 +593,11 @@ void ssh_list_kex(struct ssh_kex_struct *kex) {
|
|||||||
* @returns a cstring containing a comma-separated list of hostkey methods.
|
* @returns a cstring containing a comma-separated list of hostkey methods.
|
||||||
* NULL if no method matches
|
* NULL if no method matches
|
||||||
*/
|
*/
|
||||||
static char *ssh_client_select_hostkeys(ssh_session session)
|
char *ssh_client_select_hostkeys(ssh_session session)
|
||||||
{
|
{
|
||||||
char methods_buffer[128]={0};
|
char methods_buffer[128]={0};
|
||||||
|
char tail_buffer[128]={0};
|
||||||
|
char *new_hostkeys = NULL;
|
||||||
static const char *preferred_hostkeys[] = {
|
static const char *preferred_hostkeys[] = {
|
||||||
"ssh-ed25519",
|
"ssh-ed25519",
|
||||||
"ecdsa-sha2-nistp521",
|
"ecdsa-sha2-nistp521",
|
||||||
@@ -610,7 +613,7 @@ static char *ssh_client_select_hostkeys(ssh_session session)
|
|||||||
struct ssh_iterator *it = NULL;
|
struct ssh_iterator *it = NULL;
|
||||||
size_t algo_count;
|
size_t algo_count;
|
||||||
int needcomma = 0;
|
int needcomma = 0;
|
||||||
int i;
|
size_t i, len;
|
||||||
|
|
||||||
algo_list = ssh_known_hosts_get_algorithms(session);
|
algo_list = ssh_known_hosts_get_algorithms(session);
|
||||||
if (algo_list == NULL) {
|
if (algo_list == NULL) {
|
||||||
@@ -624,9 +627,11 @@ static char *ssh_client_select_hostkeys(ssh_session session)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; preferred_hostkeys[i] != NULL; ++i) {
|
for (i = 0; preferred_hostkeys[i] != NULL; ++i) {
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
for (it = ssh_list_get_iterator(algo_list);
|
for (it = ssh_list_get_iterator(algo_list);
|
||||||
it != NULL;
|
it != NULL;
|
||||||
it = ssh_list_get_iterator(algo_list)) {
|
it = it->next) {
|
||||||
const char *algo = ssh_iterator_value(const char *, it);
|
const char *algo = ssh_iterator_value(const char *, it);
|
||||||
int cmp;
|
int cmp;
|
||||||
int ok;
|
int ok;
|
||||||
@@ -644,10 +649,18 @@ static char *ssh_client_select_hostkeys(ssh_session session)
|
|||||||
algo,
|
algo,
|
||||||
sizeof(methods_buffer) - strlen(methods_buffer) - 1);
|
sizeof(methods_buffer) - strlen(methods_buffer) - 1);
|
||||||
needcomma = 1;
|
needcomma = 1;
|
||||||
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ssh_list_remove(algo_list, it);
|
/* Collect the rest of the algorithms in other buffer, that will
|
||||||
|
* follow the preferred buffer. This will signalize all the algorithms
|
||||||
|
* we are willing to accept.
|
||||||
|
*/
|
||||||
|
if (!found) {
|
||||||
|
snprintf(tail_buffer + strlen(tail_buffer),
|
||||||
|
sizeof(tail_buffer) - strlen(tail_buffer),
|
||||||
|
",%s", preferred_hostkeys[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ssh_list_free(algo_list);
|
ssh_list_free(algo_list);
|
||||||
@@ -658,11 +671,23 @@ static char *ssh_client_select_hostkeys(ssh_session session)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Append the supported list to the preferred.
|
||||||
|
* The length is maximum 128 + 128 + 1, which will not overflow
|
||||||
|
*/
|
||||||
|
len = strlen(methods_buffer) + strlen(tail_buffer) + 1;
|
||||||
|
new_hostkeys = malloc(len);
|
||||||
|
if (new_hostkeys == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
snprintf(new_hostkeys, len,
|
||||||
|
"%s%s", methods_buffer, tail_buffer);
|
||||||
|
|
||||||
SSH_LOG(SSH_LOG_DEBUG,
|
SSH_LOG(SSH_LOG_DEBUG,
|
||||||
"Changing host key method to \"%s\"",
|
"Changing host key method to \"%s\"",
|
||||||
methods_buffer);
|
new_hostkeys);
|
||||||
|
|
||||||
return strdup(methods_buffer);
|
return new_hostkeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
128
src/knownhosts.c
128
src/knownhosts.c
@@ -182,11 +182,16 @@ static int known_hosts_read_line(FILE *fp,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This method reads the known_hosts file referenced by the path
|
||||||
|
* in filename argument, and entries matching the match argument
|
||||||
|
* will be added to the list in entries argument.
|
||||||
|
* If the entries list is NULL, it will allocate a new list. Caller
|
||||||
|
* is responsible to free it even if an error occurs.
|
||||||
|
*/
|
||||||
static int ssh_known_hosts_read_entries(const char *match,
|
static int ssh_known_hosts_read_entries(const char *match,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
struct ssh_list **entries)
|
struct ssh_list **entries)
|
||||||
{
|
{
|
||||||
struct ssh_list *entry_list;
|
|
||||||
char line[8192];
|
char line[8192];
|
||||||
size_t lineno = 0;
|
size_t lineno = 0;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
@@ -195,13 +200,18 @@ static int ssh_known_hosts_read_entries(const char *match,
|
|||||||
|
|
||||||
fp = fopen(filename, "r");
|
fp = fopen(filename, "r");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
return SSH_ERROR;
|
SSH_LOG(SSH_LOG_WARN, "Failed to open the known_hosts file '%s': %s",
|
||||||
|
filename, strerror(errno));
|
||||||
|
/* The missing file is not an error here */
|
||||||
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
entry_list = ssh_list_new();
|
if (*entries == NULL) {
|
||||||
if (entry_list == NULL) {
|
*entries = ssh_list_new();
|
||||||
fclose(fp);
|
if (*entries == NULL) {
|
||||||
return SSH_ERROR;
|
fclose(fp);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (rc = known_hosts_read_line(fp, line, sizeof(line), &len, &lineno);
|
for (rc = known_hosts_read_line(fp, line, sizeof(line), &len, &lineno);
|
||||||
@@ -231,15 +241,12 @@ static int ssh_known_hosts_read_entries(const char *match,
|
|||||||
} else if (rc != SSH_OK) {
|
} else if (rc != SSH_OK) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
ssh_list_append(entry_list, entry);
|
ssh_list_append(*entries, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
*entries = entry_list;
|
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
error:
|
error:
|
||||||
ssh_list_free(entry_list);
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
@@ -323,8 +330,23 @@ struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session)
|
|||||||
rc = ssh_known_hosts_read_entries(host_port,
|
rc = ssh_known_hosts_read_entries(host_port,
|
||||||
session->opts.knownhosts,
|
session->opts.knownhosts,
|
||||||
&entry_list);
|
&entry_list);
|
||||||
|
if (rc != 0) {
|
||||||
|
ssh_list_free(entry_list);
|
||||||
|
ssh_list_free(list);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_known_hosts_read_entries(host_port,
|
||||||
|
session->opts.global_knownhosts,
|
||||||
|
&entry_list);
|
||||||
SAFE_FREE(host_port);
|
SAFE_FREE(host_port);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
|
ssh_list_free(entry_list);
|
||||||
|
ssh_list_free(list);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_list == NULL) {
|
||||||
ssh_list_free(list);
|
ssh_list_free(list);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -340,12 +362,10 @@ struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session)
|
|||||||
it != NULL;
|
it != NULL;
|
||||||
it = ssh_list_get_iterator(entry_list)) {
|
it = ssh_list_get_iterator(entry_list)) {
|
||||||
struct ssh_knownhosts_entry *entry = NULL;
|
struct ssh_knownhosts_entry *entry = NULL;
|
||||||
enum ssh_keytypes_e key_type;
|
|
||||||
const char *algo = NULL;
|
const char *algo = NULL;
|
||||||
|
|
||||||
entry = ssh_iterator_value(struct ssh_knownhosts_entry *, it);
|
entry = ssh_iterator_value(struct ssh_knownhosts_entry *, it);
|
||||||
key_type = ssh_key_type(entry->publickey);
|
algo = entry->publickey->type_c;
|
||||||
algo = ssh_key_type_to_char(key_type);
|
|
||||||
|
|
||||||
rc = ssh_list_append(list, algo);
|
rc = ssh_list_append(list, algo);
|
||||||
if (rc != SSH_OK) {
|
if (rc != SSH_OK) {
|
||||||
@@ -556,8 +576,17 @@ enum ssh_known_hosts_e ssh_session_has_known_hosts_entry(ssh_session session)
|
|||||||
rc = ssh_known_hosts_read_entries(host_port,
|
rc = ssh_known_hosts_read_entries(host_port,
|
||||||
session->opts.knownhosts,
|
session->opts.knownhosts,
|
||||||
&entry_list);
|
&entry_list);
|
||||||
|
if (rc != 0) {
|
||||||
|
ssh_list_free(entry_list);
|
||||||
|
return SSH_KNOWN_HOSTS_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_known_hosts_read_entries(host_port,
|
||||||
|
session->opts.global_knownhosts,
|
||||||
|
&entry_list);
|
||||||
SAFE_FREE(host_port);
|
SAFE_FREE(host_port);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
|
ssh_list_free(entry_list);
|
||||||
return SSH_KNOWN_HOSTS_UNKNOWN;
|
return SSH_KNOWN_HOSTS_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -621,7 +650,7 @@ int ssh_session_export_known_hosts_entry(ssh_session session,
|
|||||||
|
|
||||||
if (session->current_crypto == NULL) {
|
if (session->current_crypto == NULL) {
|
||||||
ssh_set_error(session, SSH_FATAL,
|
ssh_set_error(session, SSH_FATAL,
|
||||||
"No current crypto context, please connnect first");
|
"No current crypto context, please connect first");
|
||||||
SAFE_FREE(host);
|
SAFE_FREE(host);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
@@ -657,10 +686,11 @@ int ssh_session_export_known_hosts_entry(ssh_session session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Add the current connected server to the known_hosts file.
|
* @brief Add the current connected server to the user known_hosts file.
|
||||||
*
|
*
|
||||||
* This adds the currently connected server to the known_hosts file by
|
* This adds the currently connected server to the known_hosts file by
|
||||||
* appending a new line at the end.
|
* appending a new line at the end. The global known_hosts file is considered
|
||||||
|
* read-only so it is not touched by this function.
|
||||||
*
|
*
|
||||||
* @param[in] session The session to use to write the entry.
|
* @param[in] session The session to use to write the entry.
|
||||||
*
|
*
|
||||||
@@ -747,6 +777,7 @@ ssh_known_hosts_check_server_key(const char *hosts_entry,
|
|||||||
filename,
|
filename,
|
||||||
&entry_list);
|
&entry_list);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
|
ssh_list_free(entry_list);
|
||||||
return SSH_KNOWN_HOSTS_UNKNOWN;
|
return SSH_KNOWN_HOSTS_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -824,9 +855,7 @@ enum ssh_known_hosts_e
|
|||||||
ssh_session_get_known_hosts_entry(ssh_session session,
|
ssh_session_get_known_hosts_entry(ssh_session session,
|
||||||
struct ssh_knownhosts_entry **pentry)
|
struct ssh_knownhosts_entry **pentry)
|
||||||
{
|
{
|
||||||
ssh_key server_pubkey = NULL;
|
enum ssh_known_hosts_e old_rv, rv = SSH_KNOWN_HOSTS_UNKNOWN;
|
||||||
char *host_port = NULL;
|
|
||||||
enum ssh_known_hosts_e found = SSH_KNOWN_HOSTS_UNKNOWN;
|
|
||||||
|
|
||||||
if (session->opts.knownhosts == NULL) {
|
if (session->opts.knownhosts == NULL) {
|
||||||
if (ssh_options_apply(session) < 0) {
|
if (ssh_options_apply(session) < 0) {
|
||||||
@@ -838,6 +867,65 @@ ssh_session_get_known_hosts_entry(ssh_session session,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rv = ssh_session_get_known_hosts_entry_file(session,
|
||||||
|
session->opts.knownhosts,
|
||||||
|
pentry);
|
||||||
|
if (rv == SSH_KNOWN_HOSTS_OK) {
|
||||||
|
/* We already found a match in the first file: return */
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
old_rv = rv;
|
||||||
|
rv = ssh_session_get_known_hosts_entry_file(session,
|
||||||
|
session->opts.global_knownhosts,
|
||||||
|
pentry);
|
||||||
|
|
||||||
|
/* If we did not find any match at all: we report the previous result */
|
||||||
|
if (rv == SSH_KNOWN_HOSTS_UNKNOWN) {
|
||||||
|
return old_rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We found some match: return it */
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the known_hosts entry for the current connected session
|
||||||
|
* from the given known_hosts file.
|
||||||
|
*
|
||||||
|
* @param[in] session The session to validate.
|
||||||
|
*
|
||||||
|
* @param[in] filename The filename to parse.
|
||||||
|
*
|
||||||
|
* @param[in] pentry A pointer to store the allocated known hosts entry.
|
||||||
|
*
|
||||||
|
* @returns SSH_KNOWN_HOSTS_OK: The server is known and has not changed.\n
|
||||||
|
* SSH_KNOWN_HOSTS_CHANGED: The server key has changed. Either you
|
||||||
|
* are under attack or the administrator
|
||||||
|
* changed the key. You HAVE to warn the
|
||||||
|
* user about a possible attack.\n
|
||||||
|
* SSH_KNOWN_HOSTS_OTHER: The server gave use a key of a type while
|
||||||
|
* we had an other type recorded. It is a
|
||||||
|
* possible attack.\n
|
||||||
|
* SSH_KNOWN_HOSTS_UNKNOWN: The server is unknown. User should
|
||||||
|
* confirm the public key hash is correct.\n
|
||||||
|
* SSH_KNOWN_HOSTS_NOT_FOUND: The known host file does not exist. The
|
||||||
|
* host is thus unknown. File will be
|
||||||
|
* created if host key is accepted.\n
|
||||||
|
* SSH_KNOWN_HOSTS_ERROR: There had been an eror checking the host.
|
||||||
|
*
|
||||||
|
* @see ssh_knownhosts_entry_free()
|
||||||
|
*/
|
||||||
|
enum ssh_known_hosts_e
|
||||||
|
ssh_session_get_known_hosts_entry_file(ssh_session session,
|
||||||
|
const char *filename,
|
||||||
|
struct ssh_knownhosts_entry **pentry)
|
||||||
|
{
|
||||||
|
ssh_key server_pubkey = NULL;
|
||||||
|
char *host_port = NULL;
|
||||||
|
enum ssh_known_hosts_e found = SSH_KNOWN_HOSTS_UNKNOWN;
|
||||||
|
|
||||||
server_pubkey = ssh_dh_get_current_server_publickey(session);
|
server_pubkey = ssh_dh_get_current_server_publickey(session);
|
||||||
if (server_pubkey == NULL) {
|
if (server_pubkey == NULL) {
|
||||||
ssh_set_error(session,
|
ssh_set_error(session,
|
||||||
@@ -854,7 +942,7 @@ ssh_session_get_known_hosts_entry(ssh_session session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
found = ssh_known_hosts_check_server_key(host_port,
|
found = ssh_known_hosts_check_server_key(host_port,
|
||||||
session->opts.knownhosts,
|
filename,
|
||||||
server_pubkey,
|
server_pubkey,
|
||||||
pentry);
|
pentry);
|
||||||
SAFE_FREE(host_port);
|
SAFE_FREE(host_port);
|
||||||
|
|||||||
@@ -196,6 +196,7 @@ void evp_update(EVPCTX ctx, const void *data, unsigned long len)
|
|||||||
void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen)
|
void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen)
|
||||||
{
|
{
|
||||||
EVP_DigestFinal(ctx, md, mdlen);
|
EVP_DigestFinal(ctx, md, mdlen);
|
||||||
|
EVP_MD_CTX_free(ctx);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -704,6 +704,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
|
|||||||
ssh_message msg = NULL;
|
ssh_message msg = NULL;
|
||||||
char *service = NULL;
|
char *service = NULL;
|
||||||
char *method = NULL;
|
char *method = NULL;
|
||||||
|
int cmp;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
(void)user;
|
(void)user;
|
||||||
@@ -730,6 +731,13 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
|
|||||||
service, method,
|
service, method,
|
||||||
msg->auth_request.username);
|
msg->auth_request.username);
|
||||||
|
|
||||||
|
cmp = strcmp(service, "ssh-connection");
|
||||||
|
if (cmp != 0) {
|
||||||
|
SSH_LOG(SSH_LOG_WARNING,
|
||||||
|
"Invalid service request: %s",
|
||||||
|
service);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
if (strcmp(method, "none") == 0) {
|
if (strcmp(method, "none") == 0) {
|
||||||
msg->auth_request.method = SSH_AUTH_METHOD_NONE;
|
msg->auth_request.method = SSH_AUTH_METHOD_NONE;
|
||||||
|
|||||||
@@ -1022,6 +1022,12 @@ int ssh_options_get_port(ssh_session session, unsigned int* port_target) {
|
|||||||
* remote host. When not explicitly set, it will be read
|
* remote host. When not explicitly set, it will be read
|
||||||
* from the ~/.ssh/config file.
|
* from the ~/.ssh/config file.
|
||||||
*
|
*
|
||||||
|
* - SSH_OPTIONS_GLOBAL_KNOWNHOSTS:
|
||||||
|
* Get the path to the global known_hosts file being used.
|
||||||
|
*
|
||||||
|
* - SSH_OPTIONS_KNOWNHOSTS:
|
||||||
|
* Get the path to the known_hosts file being used.
|
||||||
|
*
|
||||||
* @param value The value to get into. As a char**, space will be
|
* @param value The value to get into. As a char**, space will be
|
||||||
* allocated by the function for the value, it is
|
* allocated by the function for the value, it is
|
||||||
* your responsibility to free the memory using
|
* your responsibility to free the memory using
|
||||||
@@ -1064,6 +1070,14 @@ int ssh_options_get(ssh_session session, enum ssh_options_e type, char** value)
|
|||||||
src = session->opts.ProxyCommand;
|
src = session->opts.ProxyCommand;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SSH_OPTIONS_KNOWNHOSTS: {
|
||||||
|
src = session->opts.knownhosts;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SSH_OPTIONS_GLOBAL_KNOWNHOSTS: {
|
||||||
|
src = session->opts.global_knownhosts;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
ssh_set_error(session, SSH_REQUEST_DENIED, "Unknown ssh option %d", type);
|
ssh_set_error(session, SSH_REQUEST_DENIED, "Unknown ssh option %d", type);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
@@ -1356,6 +1370,17 @@ int ssh_options_apply(ssh_session session) {
|
|||||||
free(session->opts.knownhosts);
|
free(session->opts.knownhosts);
|
||||||
session->opts.knownhosts = tmp;
|
session->opts.knownhosts = tmp;
|
||||||
|
|
||||||
|
if (session->opts.global_knownhosts == NULL) {
|
||||||
|
tmp = strdup("/etc/ssh/ssh_known_hosts");
|
||||||
|
} else {
|
||||||
|
tmp = ssh_path_expand_escape(session, session->opts.global_knownhosts);
|
||||||
|
}
|
||||||
|
if (tmp == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
free(session->opts.global_knownhosts);
|
||||||
|
session->opts.global_knownhosts = tmp;
|
||||||
|
|
||||||
if (session->opts.ProxyCommand != NULL) {
|
if (session->opts.ProxyCommand != NULL) {
|
||||||
tmp = ssh_path_expand_escape(session, session->opts.ProxyCommand);
|
tmp = ssh_path_expand_escape(session, session->opts.ProxyCommand);
|
||||||
if (tmp == NULL) {
|
if (tmp == NULL) {
|
||||||
|
|||||||
@@ -308,6 +308,7 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
|
|||||||
(session->dh_handshake_state != DH_STATE_FINISHED))
|
(session->dh_handshake_state != DH_STATE_FINISHED))
|
||||||
{
|
{
|
||||||
rc = SSH_PACKET_DENIED;
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = SSH_PACKET_ALLOWED;
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
|||||||
@@ -312,7 +312,7 @@ static int ssh_pcap_context_connect(ssh_pcap_context ctx){
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
if(session->socket==NULL)
|
if(session->socket==NULL)
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
fd=ssh_socket_get_fd_in(session->socket);
|
fd = ssh_socket_get_fd(session->socket);
|
||||||
/* TODO: adapt for windows */
|
/* TODO: adapt for windows */
|
||||||
if(fd<0)
|
if(fd<0)
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
|
|||||||
@@ -790,7 +790,7 @@ ssh_string pki_private_key_to_pem(const ssh_key key,
|
|||||||
case SSH_KEYTYPE_UNKNOWN:
|
case SSH_KEYTYPE_UNKNOWN:
|
||||||
default:
|
default:
|
||||||
BIO_free(mem);
|
BIO_free(mem);
|
||||||
SSH_LOG(SSH_LOG_WARN, "Unkown or invalid private key type %d", key->type);
|
SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d", key->type);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -916,7 +916,7 @@ ssh_key pki_private_key_from_base64(const char *b64_key,
|
|||||||
case SSH_KEYTYPE_RSA_CERT01:
|
case SSH_KEYTYPE_RSA_CERT01:
|
||||||
case SSH_KEYTYPE_UNKNOWN:
|
case SSH_KEYTYPE_UNKNOWN:
|
||||||
BIO_free(mem);
|
BIO_free(mem);
|
||||||
SSH_LOG(SSH_LOG_WARN, "Unkown or invalid private key type %d", type);
|
SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d", type);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -998,7 +998,7 @@ ssh_key pki_private_key_from_base64(const char *b64_key,
|
|||||||
case SSH_KEYTYPE_RSA1:
|
case SSH_KEYTYPE_RSA1:
|
||||||
case SSH_KEYTYPE_UNKNOWN:
|
case SSH_KEYTYPE_UNKNOWN:
|
||||||
default:
|
default:
|
||||||
SSH_LOG(SSH_LOG_WARN, "Unkown or invalid private key type %d", type);
|
SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d", type);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
22
src/poll.c
22
src/poll.c
@@ -533,19 +533,17 @@ int ssh_poll_ctx_add(ssh_poll_ctx ctx, ssh_poll_handle p) {
|
|||||||
*
|
*
|
||||||
* @return 0 on success, < 0 on error
|
* @return 0 on success, < 0 on error
|
||||||
*/
|
*/
|
||||||
int ssh_poll_ctx_add_socket (ssh_poll_ctx ctx, ssh_socket s) {
|
int ssh_poll_ctx_add_socket (ssh_poll_ctx ctx, ssh_socket s)
|
||||||
ssh_poll_handle p_in, p_out;
|
{
|
||||||
int ret;
|
ssh_poll_handle p;
|
||||||
p_in=ssh_socket_get_poll_handle_in(s);
|
int ret;
|
||||||
if(p_in==NULL)
|
|
||||||
return -1;
|
p = ssh_socket_get_poll_handle(s);
|
||||||
ret = ssh_poll_ctx_add(ctx,p_in);
|
if (p == NULL) {
|
||||||
if(ret != 0)
|
return -1;
|
||||||
|
}
|
||||||
|
ret = ssh_poll_ctx_add(ctx,p);
|
||||||
return ret;
|
return ret;
|
||||||
p_out=ssh_socket_get_poll_handle_out(s);
|
|
||||||
if(p_in != p_out)
|
|
||||||
ret = ssh_poll_ctx_add(ctx,p_out);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1039,6 +1039,7 @@ int ssh_message_auth_interactive_request(ssh_message msg, const char *name,
|
|||||||
msg->session->kbdint->prompts = NULL;
|
msg->session->kbdint->prompts = NULL;
|
||||||
msg->session->kbdint->echo = NULL;
|
msg->session->kbdint->echo = NULL;
|
||||||
}
|
}
|
||||||
|
msg->session->auth.state = SSH_AUTH_STATE_INFO;
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -536,7 +536,7 @@ socket_t ssh_get_fd(ssh_session session) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ssh_socket_get_fd_in(session->socket);
|
return ssh_socket_get_fd(session->socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -599,7 +599,7 @@ void ssh_set_fd_except(ssh_session session) {
|
|||||||
* @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;
|
||||||
ssh_poll_ctx ctx;
|
ssh_poll_ctx ctx;
|
||||||
int tm = timeout;
|
int tm = timeout;
|
||||||
int rc;
|
int rc;
|
||||||
@@ -608,17 +608,13 @@ int ssh_handle_packets(ssh_session session, int timeout) {
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
spoll_in = ssh_socket_get_poll_handle_in(session->socket);
|
spoll = ssh_socket_get_poll_handle(session->socket);
|
||||||
spoll_out = ssh_socket_get_poll_handle_out(session->socket);
|
ssh_poll_add_events(spoll, POLLIN);
|
||||||
ssh_poll_add_events(spoll_in, POLLIN);
|
ctx = ssh_poll_get_ctx(spoll);
|
||||||
ctx = ssh_poll_get_ctx(spoll_in);
|
|
||||||
|
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
ctx = ssh_poll_get_default_ctx(session);
|
ctx = ssh_poll_get_default_ctx(session);
|
||||||
ssh_poll_ctx_add(ctx, spoll_in);
|
ssh_poll_ctx_add(ctx, spoll);
|
||||||
if (spoll_in != spoll_out) {
|
|
||||||
ssh_poll_ctx_add(ctx, spoll_out);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timeout == SSH_TIMEOUT_USER) {
|
if (timeout == SSH_TIMEOUT_USER) {
|
||||||
|
|||||||
189
src/socket.c
189
src/socket.c
@@ -74,8 +74,7 @@ enum ssh_socket_states_e {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ssh_socket_struct {
|
struct ssh_socket_struct {
|
||||||
socket_t fd_in;
|
socket_t fd;
|
||||||
socket_t fd_out;
|
|
||||||
int fd_is_socket;
|
int fd_is_socket;
|
||||||
int last_errno;
|
int last_errno;
|
||||||
int read_wontblock; /* reading now on socket will
|
int read_wontblock; /* reading now on socket will
|
||||||
@@ -87,8 +86,7 @@ struct ssh_socket_struct {
|
|||||||
ssh_buffer in_buffer;
|
ssh_buffer in_buffer;
|
||||||
ssh_session session;
|
ssh_session session;
|
||||||
ssh_socket_callbacks callbacks;
|
ssh_socket_callbacks callbacks;
|
||||||
ssh_poll_handle poll_in;
|
ssh_poll_handle poll_handle;
|
||||||
ssh_poll_handle poll_out;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int sockets_initialized = 0;
|
static int sockets_initialized = 0;
|
||||||
@@ -149,8 +147,7 @@ ssh_socket ssh_socket_new(ssh_session session) {
|
|||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
s->fd_in = SSH_INVALID_SOCKET;
|
s->fd = SSH_INVALID_SOCKET;
|
||||||
s->fd_out= SSH_INVALID_SOCKET;
|
|
||||||
s->last_errno = -1;
|
s->last_errno = -1;
|
||||||
s->fd_is_socket = 1;
|
s->fd_is_socket = 1;
|
||||||
s->session = session;
|
s->session = session;
|
||||||
@@ -170,7 +167,7 @@ ssh_socket ssh_socket_new(ssh_session session) {
|
|||||||
s->read_wontblock = 0;
|
s->read_wontblock = 0;
|
||||||
s->write_wontblock = 0;
|
s->write_wontblock = 0;
|
||||||
s->data_except = 0;
|
s->data_except = 0;
|
||||||
s->poll_in=s->poll_out=NULL;
|
s->poll_handle = NULL;
|
||||||
s->state=SSH_SOCKET_NONE;
|
s->state=SSH_SOCKET_NONE;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@@ -181,8 +178,7 @@ ssh_socket ssh_socket_new(ssh_session session) {
|
|||||||
* @param[in] s socket to rest
|
* @param[in] s socket to rest
|
||||||
*/
|
*/
|
||||||
void ssh_socket_reset(ssh_socket s){
|
void ssh_socket_reset(ssh_socket s){
|
||||||
s->fd_in = SSH_INVALID_SOCKET;
|
s->fd = SSH_INVALID_SOCKET;
|
||||||
s->fd_out= SSH_INVALID_SOCKET;
|
|
||||||
s->last_errno = -1;
|
s->last_errno = -1;
|
||||||
s->fd_is_socket = 1;
|
s->fd_is_socket = 1;
|
||||||
ssh_buffer_reinit(s->in_buffer);
|
ssh_buffer_reinit(s->in_buffer);
|
||||||
@@ -190,7 +186,7 @@ void ssh_socket_reset(ssh_socket s){
|
|||||||
s->read_wontblock = 0;
|
s->read_wontblock = 0;
|
||||||
s->write_wontblock = 0;
|
s->write_wontblock = 0;
|
||||||
s->data_except = 0;
|
s->data_except = 0;
|
||||||
s->poll_in=s->poll_out=NULL;
|
s->poll_handle = NULL;
|
||||||
s->state=SSH_SOCKET_NONE;
|
s->state=SSH_SOCKET_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,7 +333,7 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p,
|
|||||||
ssh_poll_set_events(p, POLLOUT | POLLIN);
|
ssh_poll_set_events(p, POLLOUT | POLLIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ssh_socket_set_blocking(ssh_socket_get_fd_in(s));
|
rc = ssh_socket_set_blocking(ssh_socket_get_fd(s));
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -370,8 +366,8 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p,
|
|||||||
/* TODO: Find a way to put back POLLOUT when buffering occurs */
|
/* TODO: Find a way to put back POLLOUT when buffering occurs */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return -1 if one of the poll handlers disappeared */
|
/* Return -1 if the poll handler disappeared */
|
||||||
if (s->poll_in == NULL || s->poll_out == NULL) {
|
if (s->poll_handle == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,31 +375,17 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @internal
|
/** @internal
|
||||||
* @brief returns the input poll handle corresponding to the socket,
|
* @brief returns the poll handle corresponding to the socket,
|
||||||
* creates it if it does not exist.
|
* creates it if it does not exist.
|
||||||
* @returns allocated and initialized ssh_poll_handle object
|
* @returns allocated and initialized ssh_poll_handle object
|
||||||
*/
|
*/
|
||||||
ssh_poll_handle ssh_socket_get_poll_handle_in(ssh_socket s){
|
ssh_poll_handle ssh_socket_get_poll_handle(ssh_socket s)
|
||||||
if(s->poll_in)
|
{
|
||||||
return s->poll_in;
|
if (s->poll_handle) {
|
||||||
s->poll_in=ssh_poll_new(s->fd_in,0,ssh_socket_pollcallback,s);
|
return s->poll_handle;
|
||||||
if(s->fd_in == s->fd_out && s->poll_out == NULL)
|
}
|
||||||
s->poll_out=s->poll_in;
|
s->poll_handle = ssh_poll_new(s->fd,0,ssh_socket_pollcallback,s);
|
||||||
return s->poll_in;
|
return s->poll_handle;
|
||||||
}
|
|
||||||
|
|
||||||
/** @internal
|
|
||||||
* @brief returns the output poll handle corresponding to the socket,
|
|
||||||
* creates it if it does not exist.
|
|
||||||
* @returns allocated and initialized ssh_poll_handle object
|
|
||||||
*/
|
|
||||||
ssh_poll_handle ssh_socket_get_poll_handle_out(ssh_socket s){
|
|
||||||
if(s->poll_out)
|
|
||||||
return s->poll_out;
|
|
||||||
s->poll_out=ssh_poll_new(s->fd_out,0,ssh_socket_pollcallback,s);
|
|
||||||
if(s->fd_in == s->fd_out && s->poll_in == NULL)
|
|
||||||
s->poll_in=s->poll_out;
|
|
||||||
return s->poll_out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \internal
|
/** \internal
|
||||||
@@ -460,27 +442,17 @@ int ssh_socket_unix(ssh_socket s, const char *path) {
|
|||||||
void ssh_socket_close(ssh_socket s){
|
void ssh_socket_close(ssh_socket s){
|
||||||
if (ssh_socket_is_open(s)) {
|
if (ssh_socket_is_open(s)) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
CLOSE_SOCKET(s->fd_in);
|
CLOSE_SOCKET(s->fd);
|
||||||
/* fd_in = fd_out under win32 */
|
|
||||||
s->last_errno = WSAGetLastError();
|
s->last_errno = WSAGetLastError();
|
||||||
#else
|
#else
|
||||||
if (s->fd_out != s->fd_in && s->fd_out != -1) {
|
CLOSE_SOCKET(s->fd);
|
||||||
CLOSE_SOCKET(s->fd_out);
|
|
||||||
}
|
|
||||||
CLOSE_SOCKET(s->fd_in);
|
|
||||||
s->last_errno = errno;
|
s->last_errno = errno;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if(s->poll_in != NULL){
|
if(s->poll_handle != NULL){
|
||||||
if(s->poll_out == s->poll_in)
|
ssh_poll_free(s->poll_handle);
|
||||||
s->poll_out = NULL;
|
s->poll_handle=NULL;
|
||||||
ssh_poll_free(s->poll_in);
|
|
||||||
s->poll_in=NULL;
|
|
||||||
}
|
|
||||||
if(s->poll_out != NULL){
|
|
||||||
ssh_poll_free(s->poll_out);
|
|
||||||
s->poll_out=NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s->state = SSH_SOCKET_CLOSED;
|
s->state = SSH_SOCKET_CLOSED;
|
||||||
@@ -495,59 +467,34 @@ void ssh_socket_close(ssh_socket s){
|
|||||||
* file descriptors
|
* file descriptors
|
||||||
*/
|
*/
|
||||||
void ssh_socket_set_fd(ssh_socket s, socket_t fd) {
|
void ssh_socket_set_fd(ssh_socket s, socket_t fd) {
|
||||||
s->fd_in = s->fd_out = fd;
|
s->fd = fd;
|
||||||
|
|
||||||
if (s->poll_in) {
|
if (s->poll_handle) {
|
||||||
ssh_poll_set_fd(s->poll_in,fd);
|
ssh_poll_set_fd(s->poll_handle,fd);
|
||||||
} else {
|
} else {
|
||||||
s->state = SSH_SOCKET_CONNECTING;
|
s->state = SSH_SOCKET_CONNECTING;
|
||||||
|
|
||||||
/* 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), POLLOUT);
|
ssh_poll_set_events(ssh_socket_get_poll_handle(s), POLLOUT);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
ssh_poll_add_events(ssh_socket_get_poll_handle_in(s), POLLWRNORM);
|
ssh_poll_add_events(ssh_socket_get_poll_handle(s), POLLWRNORM);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
* @brief sets the input file descriptor of the socket.
|
|
||||||
* @param[out] s ssh_socket to update
|
|
||||||
* @param[in] fd file descriptor to set
|
|
||||||
*/
|
|
||||||
void ssh_socket_set_fd_in(ssh_socket s, socket_t fd) {
|
|
||||||
s->fd_in = fd;
|
|
||||||
if(s->poll_in)
|
|
||||||
ssh_poll_set_fd(s->poll_in,fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
* @brief sets the output file descriptor of the socket.
|
|
||||||
* @param[out] s ssh_socket to update
|
|
||||||
* @param[in] fd file descriptor to set
|
|
||||||
*/
|
|
||||||
void ssh_socket_set_fd_out(ssh_socket s, socket_t fd) {
|
|
||||||
s->fd_out = fd;
|
|
||||||
if(s->poll_out)
|
|
||||||
ssh_poll_set_fd(s->poll_out,fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** \internal
|
/** \internal
|
||||||
* \brief returns the input file descriptor of the socket
|
* \brief returns the input file descriptor of the socket
|
||||||
*/
|
*/
|
||||||
socket_t ssh_socket_get_fd_in(ssh_socket s) {
|
socket_t ssh_socket_get_fd(ssh_socket s)
|
||||||
return s->fd_in;
|
{
|
||||||
|
return s->fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \internal
|
/** \internal
|
||||||
* \brief returns nonzero if the socket is open
|
* \brief returns nonzero if the socket is open
|
||||||
*/
|
*/
|
||||||
int ssh_socket_is_open(ssh_socket s) {
|
int ssh_socket_is_open(ssh_socket s) {
|
||||||
return s->fd_in != SSH_INVALID_SOCKET;
|
return s->fd != SSH_INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \internal
|
/** \internal
|
||||||
@@ -563,9 +510,9 @@ static ssize_t ssh_socket_unbuffered_read(ssh_socket s,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (s->fd_is_socket) {
|
if (s->fd_is_socket) {
|
||||||
rc = recv(s->fd_in,buffer, len, 0);
|
rc = recv(s->fd,buffer, len, 0);
|
||||||
} else {
|
} else {
|
||||||
rc = read(s->fd_in,buffer, len);
|
rc = read(s->fd,buffer, len);
|
||||||
}
|
}
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
s->last_errno = WSAGetLastError();
|
s->last_errno = WSAGetLastError();
|
||||||
@@ -600,9 +547,9 @@ static ssize_t ssh_socket_unbuffered_write(ssh_socket s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (s->fd_is_socket) {
|
if (s->fd_is_socket) {
|
||||||
w = send(s->fd_out, buffer, len, flags);
|
w = send(s->fd, buffer, len, flags);
|
||||||
} else {
|
} else {
|
||||||
w = write(s->fd_out, buffer, len);
|
w = write(s->fd, buffer, len);
|
||||||
}
|
}
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
s->last_errno = WSAGetLastError();
|
s->last_errno = WSAGetLastError();
|
||||||
@@ -611,9 +558,9 @@ static ssize_t ssh_socket_unbuffered_write(ssh_socket s,
|
|||||||
#endif
|
#endif
|
||||||
s->write_wontblock = 0;
|
s->write_wontblock = 0;
|
||||||
/* Reactive the POLLOUT detector in the poll multiplexer system */
|
/* Reactive the POLLOUT detector in the poll multiplexer system */
|
||||||
if (s->poll_out) {
|
if (s->poll_handle) {
|
||||||
SSH_LOG(SSH_LOG_PACKET, "Enabling POLLOUT for socket");
|
SSH_LOG(SSH_LOG_PACKET, "Enabling POLLOUT for socket");
|
||||||
ssh_poll_set_events(s->poll_out,ssh_poll_get_events(s->poll_out) | POLLOUT);
|
ssh_poll_set_events(s->poll_handle,ssh_poll_get_events(s->poll_handle) | POLLOUT);
|
||||||
}
|
}
|
||||||
if (w < 0) {
|
if (w < 0) {
|
||||||
s->data_except = 1;
|
s->data_except = 1;
|
||||||
@@ -626,10 +573,10 @@ static ssize_t ssh_socket_unbuffered_write(ssh_socket s,
|
|||||||
* \brief returns nonzero if the current socket is in the fd_set
|
* \brief returns nonzero if the current socket is in the fd_set
|
||||||
*/
|
*/
|
||||||
int ssh_socket_fd_isset(ssh_socket s, fd_set *set) {
|
int ssh_socket_fd_isset(ssh_socket s, fd_set *set) {
|
||||||
if(s->fd_in == SSH_INVALID_SOCKET) {
|
if(s->fd == SSH_INVALID_SOCKET) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return FD_ISSET(s->fd_in,set) || FD_ISSET(s->fd_out,set);
|
return FD_ISSET(s->fd,set);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \internal
|
/** \internal
|
||||||
@@ -637,22 +584,16 @@ int ssh_socket_fd_isset(ssh_socket s, fd_set *set) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void ssh_socket_fd_set(ssh_socket s, fd_set *set, socket_t *max_fd) {
|
void ssh_socket_fd_set(ssh_socket s, fd_set *set, socket_t *max_fd) {
|
||||||
if (s->fd_in == SSH_INVALID_SOCKET) {
|
if (s->fd == SSH_INVALID_SOCKET) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FD_SET(s->fd_in,set);
|
FD_SET(s->fd,set);
|
||||||
FD_SET(s->fd_out,set);
|
|
||||||
|
|
||||||
if (s->fd_in >= 0 &&
|
if (s->fd >= 0 &&
|
||||||
s->fd_in >= *max_fd &&
|
s->fd >= *max_fd &&
|
||||||
s->fd_in != SSH_INVALID_SOCKET) {
|
s->fd != SSH_INVALID_SOCKET) {
|
||||||
*max_fd = s->fd_in + 1;
|
*max_fd = s->fd + 1;
|
||||||
}
|
|
||||||
if (s->fd_out >= 0 &&
|
|
||||||
s->fd_out >= *max_fd &&
|
|
||||||
s->fd_out != SSH_INVALID_SOCKET) {
|
|
||||||
*max_fd = s->fd_out + 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -701,9 +642,9 @@ int ssh_socket_nonblocking_flush(ssh_socket s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
len = ssh_buffer_get_len(s->out_buffer);
|
len = ssh_buffer_get_len(s->out_buffer);
|
||||||
if (!s->write_wontblock && s->poll_out && len > 0) {
|
if (!s->write_wontblock && s->poll_handle && len > 0) {
|
||||||
/* force the poll system to catch pollout events */
|
/* force the poll system to catch pollout events */
|
||||||
ssh_poll_add_events(s->poll_out, POLLOUT);
|
ssh_poll_add_events(s->poll_handle, POLLOUT);
|
||||||
|
|
||||||
return SSH_AGAIN;
|
return SSH_AGAIN;
|
||||||
}
|
}
|
||||||
@@ -741,9 +682,9 @@ int ssh_socket_nonblocking_flush(ssh_socket s)
|
|||||||
|
|
||||||
/* Is there some data pending? */
|
/* Is there some data pending? */
|
||||||
len = ssh_buffer_get_len(s->out_buffer);
|
len = ssh_buffer_get_len(s->out_buffer);
|
||||||
if (s->poll_out && len > 0) {
|
if (s->poll_handle && len > 0) {
|
||||||
/* force the poll system to catch pollout events */
|
/* force the poll system to catch pollout events */
|
||||||
ssh_poll_add_events(s->poll_out, POLLOUT);
|
ssh_poll_add_events(s->poll_handle, POLLOUT);
|
||||||
|
|
||||||
return SSH_AGAIN;
|
return SSH_AGAIN;
|
||||||
}
|
}
|
||||||
@@ -804,10 +745,10 @@ int ssh_socket_get_status(ssh_socket s) {
|
|||||||
|
|
||||||
int ssh_socket_get_poll_flags(ssh_socket s) {
|
int ssh_socket_get_poll_flags(ssh_socket s) {
|
||||||
int r = 0;
|
int r = 0;
|
||||||
if (s->poll_in != NULL && (ssh_poll_get_events (s->poll_in) & POLLIN) > 0) {
|
if (s->poll_handle != NULL && (ssh_poll_get_events (s->poll_handle) & POLLIN) > 0) {
|
||||||
r |= SSH_READ_PENDING;
|
r |= SSH_READ_PENDING;
|
||||||
}
|
}
|
||||||
if (s->poll_out != NULL && (ssh_poll_get_events (s->poll_out) & POLLOUT) > 0) {
|
if (s->poll_handle != NULL && (ssh_poll_get_events (s->poll_handle) & POLLOUT) > 0) {
|
||||||
r |= SSH_WRITE_PENDING;
|
r |= SSH_WRITE_PENDING;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
@@ -897,19 +838,15 @@ void ssh_execute_command(const char *command, socket_t in, socket_t out){
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int ssh_socket_connect_proxycommand(ssh_socket s, const char *command){
|
int ssh_socket_connect_proxycommand(ssh_socket s, const char *command){
|
||||||
socket_t in_pipe[2];
|
socket_t pair[2];
|
||||||
socket_t out_pipe[2];
|
|
||||||
int pid;
|
int pid;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if(s->state != SSH_SOCKET_NONE)
|
if (s->state != SSH_SOCKET_NONE) {
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
|
|
||||||
rc = pipe(in_pipe);
|
|
||||||
if (rc < 0) {
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
}
|
||||||
rc = pipe(out_pipe);
|
|
||||||
|
rc = socketpair(PF_LOCAL, SOCK_STREAM, 0, pair);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
@@ -917,20 +854,18 @@ int ssh_socket_connect_proxycommand(ssh_socket s, const char *command){
|
|||||||
SSH_LOG(SSH_LOG_PROTOCOL,"Executing proxycommand '%s'",command);
|
SSH_LOG(SSH_LOG_PROTOCOL,"Executing proxycommand '%s'",command);
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if(pid == 0){
|
if(pid == 0){
|
||||||
ssh_execute_command(command,out_pipe[0],in_pipe[1]);
|
ssh_execute_command(command,pair[0],pair[0]);
|
||||||
}
|
}
|
||||||
close(in_pipe[1]);
|
close(pair[0]);
|
||||||
close(out_pipe[0]);
|
SSH_LOG(SSH_LOG_PROTOCOL,"ProxyCommand connection pipe: [%d,%d]",pair[0],pair[1]);
|
||||||
SSH_LOG(SSH_LOG_PROTOCOL,"ProxyCommand connection pipe: [%d,%d]",in_pipe[0],out_pipe[1]);
|
ssh_socket_set_fd(s, pair[1]);
|
||||||
ssh_socket_set_fd_in(s,in_pipe[0]);
|
|
||||||
ssh_socket_set_fd_out(s,out_pipe[1]);
|
|
||||||
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);
|
ssh_poll_set_events(ssh_socket_get_poll_handle(s), POLLIN | 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);
|
||||||
|
}
|
||||||
|
|
||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,6 +121,8 @@ if (CLIENT_TESTING)
|
|||||||
file(COPY keys/id_rsa.pub DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
file(COPY keys/id_rsa.pub DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
||||||
file(COPY keys/id_ecdsa DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
file(COPY keys/id_ecdsa DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
||||||
file(COPY keys/id_ecdsa.pub DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
file(COPY keys/id_ecdsa.pub DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
||||||
|
file(COPY keys/id_ed25519 DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
||||||
|
file(COPY keys/id_ed25519.pub DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
||||||
|
|
||||||
# Allow to auth with bob his public keys on alice account
|
# Allow to auth with bob his public keys on alice account
|
||||||
configure_file(keys/id_rsa.pub ${CMAKE_CURRENT_BINARY_DIR}/home/alice/.ssh/authorized_keys @ONLY)
|
configure_file(keys/id_rsa.pub ${CMAKE_CURRENT_BINARY_DIR}/home/alice/.ssh/authorized_keys @ONLY)
|
||||||
@@ -128,6 +130,10 @@ if (CLIENT_TESTING)
|
|||||||
file(READ keys/id_ecdsa.pub CONTENTS)
|
file(READ keys/id_ecdsa.pub CONTENTS)
|
||||||
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/home/alice/.ssh/authorized_keys "${CONTENTS}")
|
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/home/alice/.ssh/authorized_keys "${CONTENTS}")
|
||||||
|
|
||||||
|
# append ed25519 public key
|
||||||
|
file(READ keys/id_ed25519.pub CONTENTS)
|
||||||
|
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/home/alice/.ssh/authorized_keys "${CONTENTS}")
|
||||||
|
|
||||||
# Copy the signed key to an alternative directory in bob's homedir.
|
# Copy the signed key to an alternative directory in bob's homedir.
|
||||||
file(COPY keys/certauth/id_rsa DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh_cert/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
file(COPY keys/certauth/id_rsa DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh_cert/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
||||||
file(COPY keys/certauth/id_rsa.pub DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh_cert/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
file(COPY keys/certauth/id_rsa.pub DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh_cert/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
||||||
|
|||||||
@@ -559,7 +559,7 @@ static void torture_auth_pubkey_types(void **state)
|
|||||||
rc = ssh_connect(session);
|
rc = ssh_connect(session);
|
||||||
assert_ssh_return_code(session, rc);
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
rc = ssh_userauth_none(session,NULL);
|
rc = ssh_userauth_none(session, NULL);
|
||||||
/* This request should return a SSH_REQUEST_DENIED error */
|
/* This request should return a SSH_REQUEST_DENIED error */
|
||||||
if (rc == SSH_ERROR) {
|
if (rc == SSH_ERROR) {
|
||||||
assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
|
assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
|
||||||
@@ -596,7 +596,7 @@ static void torture_auth_pubkey_types_ecdsa(void **state)
|
|||||||
rc = ssh_connect(session);
|
rc = ssh_connect(session);
|
||||||
assert_ssh_return_code(session, rc);
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
rc = ssh_userauth_none(session,NULL);
|
rc = ssh_userauth_none(session, NULL);
|
||||||
/* This request should return a SSH_REQUEST_DENIED error */
|
/* This request should return a SSH_REQUEST_DENIED error */
|
||||||
if (rc == SSH_ERROR) {
|
if (rc == SSH_ERROR) {
|
||||||
assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
|
assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
|
||||||
@@ -622,6 +622,44 @@ static void torture_auth_pubkey_types_ecdsa(void **state)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void torture_auth_pubkey_types_ed25519(void **state)
|
||||||
|
{
|
||||||
|
struct torture_state *s = *state;
|
||||||
|
ssh_session session = s->ssh.session;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
rc = ssh_connect(session);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
rc = ssh_userauth_none(session, NULL);
|
||||||
|
/* This request should return a SSH_REQUEST_DENIED error */
|
||||||
|
if (rc == SSH_ERROR) {
|
||||||
|
assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
|
||||||
|
}
|
||||||
|
rc = ssh_userauth_list(session, NULL);
|
||||||
|
assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);
|
||||||
|
|
||||||
|
/* Enable only DSA keys -- authentication should fail */
|
||||||
|
rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
||||||
|
"ssh-dss");
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
|
||||||
|
assert_int_equal(rc, SSH_AUTH_DENIED);
|
||||||
|
|
||||||
|
/* Verify we can use also ed25519 keys */
|
||||||
|
rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
||||||
|
"ssh-ed25519");
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
|
||||||
|
assert_int_equal(rc, SSH_AUTH_SUCCESS);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static void torture_auth_pubkey_types_nonblocking(void **state)
|
static void torture_auth_pubkey_types_nonblocking(void **state)
|
||||||
{
|
{
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
@@ -634,7 +672,7 @@ static void torture_auth_pubkey_types_nonblocking(void **state)
|
|||||||
rc = ssh_connect(session);
|
rc = ssh_connect(session);
|
||||||
assert_ssh_return_code(session, rc);
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
ssh_set_blocking(session,0);
|
ssh_set_blocking(session, 0);
|
||||||
do {
|
do {
|
||||||
rc = ssh_userauth_none(session, NULL);
|
rc = ssh_userauth_none(session, NULL);
|
||||||
} while (rc == SSH_AUTH_AGAIN);
|
} while (rc == SSH_AUTH_AGAIN);
|
||||||
@@ -681,7 +719,7 @@ static void torture_auth_pubkey_types_ecdsa_nonblocking(void **state)
|
|||||||
rc = ssh_connect(session);
|
rc = ssh_connect(session);
|
||||||
assert_ssh_return_code(session, rc);
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
ssh_set_blocking(session,0);
|
ssh_set_blocking(session, 0);
|
||||||
do {
|
do {
|
||||||
rc = ssh_userauth_none(session, NULL);
|
rc = ssh_userauth_none(session, NULL);
|
||||||
} while (rc == SSH_AUTH_AGAIN);
|
} while (rc == SSH_AUTH_AGAIN);
|
||||||
@@ -704,7 +742,7 @@ static void torture_auth_pubkey_types_ecdsa_nonblocking(void **state)
|
|||||||
} while (rc == SSH_AUTH_AGAIN);
|
} while (rc == SSH_AUTH_AGAIN);
|
||||||
assert_int_equal(rc, SSH_AUTH_DENIED);
|
assert_int_equal(rc, SSH_AUTH_DENIED);
|
||||||
|
|
||||||
/* Verify we can use also ECDSA keys with their various names */
|
/* Verify we can use also ECDSA key to authenticate */
|
||||||
rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
||||||
"ecdsa-sha2-nistp256");
|
"ecdsa-sha2-nistp256");
|
||||||
assert_ssh_return_code(session, rc);
|
assert_ssh_return_code(session, rc);
|
||||||
@@ -716,6 +754,52 @@ static void torture_auth_pubkey_types_ecdsa_nonblocking(void **state)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void torture_auth_pubkey_types_ed25519_nonblocking(void **state)
|
||||||
|
{
|
||||||
|
struct torture_state *s = *state;
|
||||||
|
ssh_session session = s->ssh.session;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
rc = ssh_connect(session);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
ssh_set_blocking(session, 0);
|
||||||
|
do {
|
||||||
|
rc = ssh_userauth_none(session, NULL);
|
||||||
|
} while (rc == SSH_AUTH_AGAIN);
|
||||||
|
|
||||||
|
/* This request should return a SSH_REQUEST_DENIED error */
|
||||||
|
if (rc == SSH_ERROR) {
|
||||||
|
assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_userauth_list(session, NULL);
|
||||||
|
assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);
|
||||||
|
|
||||||
|
/* Enable only DSA keys -- authentication should fail */
|
||||||
|
rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
||||||
|
"ssh-dss");
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
do {
|
||||||
|
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
|
||||||
|
} while (rc == SSH_AUTH_AGAIN);
|
||||||
|
assert_int_equal(rc, SSH_AUTH_DENIED);
|
||||||
|
|
||||||
|
/* Verify we can use also ED25519 key to authenticate */
|
||||||
|
rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
||||||
|
"ssh-ed25519");
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
do {
|
||||||
|
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
|
||||||
|
} while (rc == SSH_AUTH_AGAIN);
|
||||||
|
assert_int_equal(rc, SSH_AUTH_SUCCESS);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int torture_run_tests(void) {
|
int torture_run_tests(void) {
|
||||||
int rc;
|
int rc;
|
||||||
@@ -771,6 +855,12 @@ int torture_run_tests(void) {
|
|||||||
cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ecdsa_nonblocking,
|
cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ecdsa_nonblocking,
|
||||||
pubkey_setup,
|
pubkey_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ed25519,
|
||||||
|
pubkey_setup,
|
||||||
|
session_teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ed25519_nonblocking,
|
||||||
|
pubkey_setup,
|
||||||
|
session_teardown),
|
||||||
};
|
};
|
||||||
|
|
||||||
ssh_init();
|
ssh_init();
|
||||||
|
|||||||
@@ -167,6 +167,10 @@ static void torture_knownhosts_precheck(void **state)
|
|||||||
"127.0.0.10 %s\n",
|
"127.0.0.10 %s\n",
|
||||||
torture_get_testkey_pub(SSH_KEYTYPE_ED25519, 0));
|
torture_get_testkey_pub(SSH_KEYTYPE_ED25519, 0));
|
||||||
|
|
||||||
|
fprintf(file,
|
||||||
|
"127.0.0.10 %s\n",
|
||||||
|
torture_get_testkey_pub(SSH_KEYTYPE_ECDSA, 521));
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
||||||
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file);
|
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file);
|
||||||
@@ -176,7 +180,7 @@ static void torture_knownhosts_precheck(void **state)
|
|||||||
assert_non_null(algo_list);
|
assert_non_null(algo_list);
|
||||||
|
|
||||||
algo_count = ssh_list_count(algo_list);
|
algo_count = ssh_list_count(algo_list);
|
||||||
assert_int_equal(algo_count, 2);
|
assert_int_equal(algo_count, 3);
|
||||||
|
|
||||||
it = ssh_list_get_iterator(algo_list);
|
it = ssh_list_get_iterator(algo_list);
|
||||||
assert_non_null(it);
|
assert_non_null(it);
|
||||||
@@ -190,6 +194,13 @@ static void torture_knownhosts_precheck(void **state)
|
|||||||
algo = ssh_iterator_value(const char *, it);
|
algo = ssh_iterator_value(const char *, it);
|
||||||
assert_string_equal(algo, "ssh-ed25519");
|
assert_string_equal(algo, "ssh-ed25519");
|
||||||
|
|
||||||
|
ssh_list_remove(algo_list, it);
|
||||||
|
|
||||||
|
it = ssh_list_get_iterator(algo_list);
|
||||||
|
assert_non_null(it);
|
||||||
|
algo = ssh_iterator_value(const char *, it);
|
||||||
|
assert_string_equal(algo, "ecdsa-sha2-nistp521");
|
||||||
|
|
||||||
ssh_list_free(algo_list);
|
ssh_list_free(algo_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ set(CTEST_SOURCE_DIRECTORY "${CTEST_DIRECTORY}/${CTEST_BUILD_NAME}/source")
|
|||||||
set(CTEST_BINARY_DIRECTORY "${CTEST_DIRECTORY}/${CTEST_BUILD_NAME}/build")
|
set(CTEST_BINARY_DIRECTORY "${CTEST_DIRECTORY}/${CTEST_BUILD_NAME}/build")
|
||||||
|
|
||||||
set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE ${CMAKE_SOURCE_DIR}/tests/valgrind.supp)
|
set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE ${CMAKE_SOURCE_DIR}/tests/valgrind.supp)
|
||||||
set(CTEST_MEMORYCHECK_COMMAND_OPTIONS " --trace-children-skip=sshd")
|
set(CTEST_MEMORYCHECK_COMMAND_OPTIONS " --trace-children-skip=${SSHD_EXECUTABLE}")
|
||||||
|
|
||||||
find_program(CTEST_GIT_COMMAND NAMES git)
|
find_program(CTEST_GIT_COMMAND NAMES git)
|
||||||
find_program(CTEST_COVERAGE_COMMAND NAMES gcov)
|
find_program(CTEST_COVERAGE_COMMAND NAMES gcov)
|
||||||
|
|||||||
8
tests/keys/id_ed25519
Normal file
8
tests/keys/id_ed25519
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||||
|
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||||
|
QyNTUxOQAAACCLo6vx1lX6ZZoe05lWTkuwrJUZN0T8hEer5UF9KPhOVgAAAKg+IRNSPiET
|
||||||
|
UgAAAAtzc2gtZWQyNTUxOQAAACCLo6vx1lX6ZZoe05lWTkuwrJUZN0T8hEer5UF9KPhOVg
|
||||||
|
AAAED2zFg52qYItoZaSUnir4VKubTxJveL9D2oWK7Prg/O24ujq/HWVfplmh7TmVZOS7Cs
|
||||||
|
lRk3RPyER6vlQX0o+E5WAAAAHmpqZWxlbkB0NDcwcy5qamVsZW4ucmVkaGF0LmNvbQECAw
|
||||||
|
QFBgc=
|
||||||
|
-----END OPENSSH PRIVATE KEY-----
|
||||||
1
tests/keys/id_ed25519.pub
Normal file
1
tests/keys/id_ed25519.pub
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIujq/HWVfplmh7TmVZOS7CslRk3RPyER6vlQX0o+E5W jjelen@t470s.jjelen.redhat.com
|
||||||
@@ -42,18 +42,24 @@ static int setup_knownhosts_file(void **state)
|
|||||||
|
|
||||||
nwritten = fwrite(LOCALHOST_PATTERN_ED25519,
|
nwritten = fwrite(LOCALHOST_PATTERN_ED25519,
|
||||||
sizeof(char),
|
sizeof(char),
|
||||||
sizeof(LOCALHOST_PATTERN_ED25519),
|
strlen(LOCALHOST_PATTERN_ED25519),
|
||||||
fp);
|
fp);
|
||||||
if (nwritten != sizeof(LOCALHOST_PATTERN_ED25519)) {
|
if (nwritten != strlen(LOCALHOST_PATTERN_ED25519)) {
|
||||||
|
fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nwritten = fwrite("\n", sizeof(char), 1, fp);
|
||||||
|
if (nwritten != 1) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
nwritten = fwrite(LOCALHOST_RSA_LINE,
|
nwritten = fwrite(LOCALHOST_RSA_LINE,
|
||||||
sizeof(char),
|
sizeof(char),
|
||||||
sizeof(LOCALHOST_RSA_LINE),
|
strlen(LOCALHOST_RSA_LINE),
|
||||||
fp);
|
fp);
|
||||||
if (nwritten != sizeof(LOCALHOST_RSA_LINE)) {
|
if (nwritten != strlen(LOCALHOST_RSA_LINE)) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -210,6 +216,8 @@ static void torture_knownhosts_read_file(void **state)
|
|||||||
const char *knownhosts_file = *state;
|
const char *knownhosts_file = *state;
|
||||||
struct ssh_list *entry_list = NULL;
|
struct ssh_list *entry_list = NULL;
|
||||||
struct ssh_iterator *it = NULL;
|
struct ssh_iterator *it = NULL;
|
||||||
|
struct ssh_knownhosts_entry *entry = NULL;
|
||||||
|
enum ssh_keytypes_e type;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = ssh_known_hosts_read_entries("localhost",
|
rc = ssh_known_hosts_read_entries("localhost",
|
||||||
@@ -219,22 +227,27 @@ static void torture_knownhosts_read_file(void **state)
|
|||||||
assert_non_null(entry_list);
|
assert_non_null(entry_list);
|
||||||
it = ssh_list_get_iterator(entry_list);
|
it = ssh_list_get_iterator(entry_list);
|
||||||
assert_non_null(it);
|
assert_non_null(it);
|
||||||
for (;it != NULL; it = it->next) {
|
|
||||||
struct ssh_knownhosts_entry *entry = NULL;
|
|
||||||
enum ssh_keytypes_e type;
|
|
||||||
|
|
||||||
entry = ssh_iterator_value(struct ssh_knownhosts_entry *, it);
|
/* First key in known hosts file is ED25519 */
|
||||||
assert_non_null(entry);
|
entry = ssh_iterator_value(struct ssh_knownhosts_entry *, it);
|
||||||
|
assert_non_null(entry);
|
||||||
|
|
||||||
assert_string_equal(entry->hostname, "localhost");
|
assert_string_equal(entry->hostname, "localhost");
|
||||||
type = ssh_key_type(entry->publickey);
|
type = ssh_key_type(entry->publickey);
|
||||||
assert_int_equal(type, SSH_KEYTYPE_ED25519);
|
assert_int_equal(type, SSH_KEYTYPE_ED25519);
|
||||||
}
|
|
||||||
|
it = it->next;
|
||||||
|
|
||||||
|
/* Second key in known hosts file is RSA */
|
||||||
|
entry = ssh_iterator_value(struct ssh_knownhosts_entry *, it);
|
||||||
|
assert_non_null(entry);
|
||||||
|
|
||||||
|
assert_string_equal(entry->hostname, "localhost");
|
||||||
|
type = ssh_key_type(entry->publickey);
|
||||||
|
assert_int_equal(type, SSH_KEYTYPE_RSA);
|
||||||
|
|
||||||
it = ssh_list_get_iterator(entry_list);
|
it = ssh_list_get_iterator(entry_list);
|
||||||
for (;it != NULL; it = it->next) {
|
for (;it != NULL; it = it->next) {
|
||||||
struct ssh_knownhosts_entry *entry = NULL;
|
|
||||||
|
|
||||||
entry = ssh_iterator_value(struct ssh_knownhosts_entry *, it);
|
entry = ssh_iterator_value(struct ssh_knownhosts_entry *, it);
|
||||||
SSH_KNOWNHOSTS_ENTRY_FREE(entry);
|
SSH_KNOWNHOSTS_ENTRY_FREE(entry);
|
||||||
}
|
}
|
||||||
@@ -252,6 +265,8 @@ static void torture_knownhosts_host_exists(void **state)
|
|||||||
|
|
||||||
ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
|
ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
|
||||||
ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, knownhosts_file);
|
ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, knownhosts_file);
|
||||||
|
/* This makes sure the system's known_hosts are not used */
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_GLOBAL_KNOWNHOSTS, "/dev/null");
|
||||||
|
|
||||||
found = ssh_session_has_known_hosts_entry(session);
|
found = ssh_session_has_known_hosts_entry(session);
|
||||||
assert_int_equal(found, SSH_KNOWN_HOSTS_OK);
|
assert_int_equal(found, SSH_KNOWN_HOSTS_OK);
|
||||||
@@ -264,6 +279,89 @@ static void torture_knownhosts_host_exists(void **state)
|
|||||||
ssh_free(session);
|
ssh_free(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void torture_knownhosts_host_exists_global(void **state)
|
||||||
|
{
|
||||||
|
const char *knownhosts_file = *state;
|
||||||
|
enum ssh_known_hosts_e found;
|
||||||
|
ssh_session session;
|
||||||
|
|
||||||
|
session = ssh_new();
|
||||||
|
assert_non_null(session);
|
||||||
|
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
|
||||||
|
/* This makes sure the user's known_hosts are not used */
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, "/dev/null");
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_GLOBAL_KNOWNHOSTS, knownhosts_file);
|
||||||
|
|
||||||
|
found = ssh_session_has_known_hosts_entry(session);
|
||||||
|
assert_int_equal(found, SSH_KNOWN_HOSTS_OK);
|
||||||
|
assert_true(found == SSH_KNOWN_HOSTS_OK);
|
||||||
|
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_HOST, "wurstbrot");
|
||||||
|
found = ssh_session_has_known_hosts_entry(session);
|
||||||
|
assert_true(found == SSH_KNOWN_HOSTS_UNKNOWN);
|
||||||
|
|
||||||
|
ssh_free(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
torture_knownhosts_algorithms(void **state)
|
||||||
|
{
|
||||||
|
const char *knownhosts_file = *state;
|
||||||
|
char *algo_list = NULL;
|
||||||
|
ssh_session session;
|
||||||
|
const char *expect = "ssh-ed25519,ssh-rsa,ecdsa-sha2-nistp521,"
|
||||||
|
"ecdsa-sha2-nistp384,ecdsa-sha2-nistp256"
|
||||||
|
#ifdef HAVE_DSA
|
||||||
|
",ssh-dss"
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
|
session = ssh_new();
|
||||||
|
assert_non_null(session);
|
||||||
|
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, knownhosts_file);
|
||||||
|
/* This makes sure the system's known_hosts are not used */
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_GLOBAL_KNOWNHOSTS, "/dev/null");
|
||||||
|
|
||||||
|
algo_list = ssh_client_select_hostkeys(session);
|
||||||
|
assert_non_null(algo_list);
|
||||||
|
assert_string_equal(algo_list, expect);
|
||||||
|
free(algo_list);
|
||||||
|
|
||||||
|
ssh_free(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
torture_knownhosts_algorithms_global(void **state)
|
||||||
|
{
|
||||||
|
const char *knownhosts_file = *state;
|
||||||
|
char *algo_list = NULL;
|
||||||
|
ssh_session session;
|
||||||
|
const char *expect = "ssh-ed25519,ssh-rsa,ecdsa-sha2-nistp521,"
|
||||||
|
"ecdsa-sha2-nistp384,ecdsa-sha2-nistp256"
|
||||||
|
#ifdef HAVE_DSA
|
||||||
|
",ssh-dss"
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
|
session = ssh_new();
|
||||||
|
assert_non_null(session);
|
||||||
|
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
|
||||||
|
/* This makes sure the current-user's known hosts are not used */
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, "/dev/null");
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_GLOBAL_KNOWNHOSTS, knownhosts_file);
|
||||||
|
|
||||||
|
algo_list = ssh_client_select_hostkeys(session);
|
||||||
|
assert_non_null(algo_list);
|
||||||
|
assert_string_equal(algo_list, expect);
|
||||||
|
free(algo_list);
|
||||||
|
|
||||||
|
ssh_free(session);
|
||||||
|
}
|
||||||
|
|
||||||
int torture_run_tests(void) {
|
int torture_run_tests(void) {
|
||||||
int rc;
|
int rc;
|
||||||
struct CMUnitTest tests[] = {
|
struct CMUnitTest tests[] = {
|
||||||
@@ -279,6 +377,15 @@ int torture_run_tests(void) {
|
|||||||
cmocka_unit_test_setup_teardown(torture_knownhosts_host_exists,
|
cmocka_unit_test_setup_teardown(torture_knownhosts_host_exists,
|
||||||
setup_knownhosts_file,
|
setup_knownhosts_file,
|
||||||
teardown_knownhosts_file),
|
teardown_knownhosts_file),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_knownhosts_host_exists_global,
|
||||||
|
setup_knownhosts_file,
|
||||||
|
teardown_knownhosts_file),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_knownhosts_algorithms,
|
||||||
|
setup_knownhosts_file,
|
||||||
|
teardown_knownhosts_file),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_knownhosts_algorithms_global,
|
||||||
|
setup_knownhosts_file,
|
||||||
|
teardown_knownhosts_file),
|
||||||
};
|
};
|
||||||
|
|
||||||
ssh_init();
|
ssh_init();
|
||||||
|
|||||||
@@ -346,6 +346,76 @@ static void torture_options_get_identity(void **state) {
|
|||||||
free(identity);
|
free(identity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void torture_options_set_global_knownhosts(void **state)
|
||||||
|
{
|
||||||
|
ssh_session session = *state;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = ssh_options_set(session,
|
||||||
|
SSH_OPTIONS_GLOBAL_KNOWNHOSTS,
|
||||||
|
"/etc/libssh/known_hosts");
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
assert_string_equal(session->opts.global_knownhosts,
|
||||||
|
"/etc/libssh/known_hosts");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void torture_options_get_global_knownhosts(void **state)
|
||||||
|
{
|
||||||
|
ssh_session session = *state;
|
||||||
|
char *str = NULL;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = ssh_options_set(session,
|
||||||
|
SSH_OPTIONS_GLOBAL_KNOWNHOSTS,
|
||||||
|
"/etc/libssh/known_hosts");
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
assert_string_equal(session->opts.global_knownhosts,
|
||||||
|
"/etc/libssh/known_hosts");
|
||||||
|
|
||||||
|
|
||||||
|
rc = ssh_options_get(session, SSH_OPTIONS_GLOBAL_KNOWNHOSTS, &str);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
assert_string_equal(session->opts.global_knownhosts,
|
||||||
|
"/etc/libssh/known_hosts");
|
||||||
|
|
||||||
|
SSH_STRING_FREE_CHAR(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void torture_options_set_knownhosts(void **state)
|
||||||
|
{
|
||||||
|
ssh_session session = *state;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = ssh_options_set(session,
|
||||||
|
SSH_OPTIONS_KNOWNHOSTS,
|
||||||
|
"/home/libssh/.ssh/known_hosts");
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
assert_string_equal(session->opts.knownhosts,
|
||||||
|
"/home/libssh/.ssh/known_hosts");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void torture_options_get_knownhosts(void **state)
|
||||||
|
{
|
||||||
|
ssh_session session = *state;
|
||||||
|
char *str = NULL;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = ssh_options_set(session,
|
||||||
|
SSH_OPTIONS_KNOWNHOSTS,
|
||||||
|
"/home/libssh/.ssh/known_hosts");
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
assert_string_equal(session->opts.knownhosts,
|
||||||
|
"/home/libssh/.ssh/known_hosts");
|
||||||
|
|
||||||
|
|
||||||
|
rc = ssh_options_get(session, SSH_OPTIONS_KNOWNHOSTS, &str);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
assert_string_equal(session->opts.knownhosts,
|
||||||
|
"/home/libssh/.ssh/known_hosts");
|
||||||
|
|
||||||
|
SSH_STRING_FREE_CHAR(str);
|
||||||
|
}
|
||||||
|
|
||||||
static void torture_options_proxycommand(void **state) {
|
static void torture_options_proxycommand(void **state) {
|
||||||
ssh_session session = *state;
|
ssh_session session = *state;
|
||||||
int rc;
|
int rc;
|
||||||
@@ -604,6 +674,10 @@ int torture_run_tests(void) {
|
|||||||
cmocka_unit_test_setup_teardown(torture_options_get_user, setup, teardown),
|
cmocka_unit_test_setup_teardown(torture_options_get_user, setup, teardown),
|
||||||
cmocka_unit_test_setup_teardown(torture_options_set_identity, setup, teardown),
|
cmocka_unit_test_setup_teardown(torture_options_set_identity, setup, teardown),
|
||||||
cmocka_unit_test_setup_teardown(torture_options_get_identity, setup, teardown),
|
cmocka_unit_test_setup_teardown(torture_options_get_identity, setup, teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_options_set_global_knownhosts, setup, teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_options_get_global_knownhosts, setup, teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_options_set_knownhosts, setup, teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_options_get_knownhosts, setup, teardown),
|
||||||
cmocka_unit_test_setup_teardown(torture_options_proxycommand, setup, teardown),
|
cmocka_unit_test_setup_teardown(torture_options_proxycommand, setup, teardown),
|
||||||
cmocka_unit_test_setup_teardown(torture_options_set_ciphers, setup, teardown),
|
cmocka_unit_test_setup_teardown(torture_options_set_ciphers, setup, teardown),
|
||||||
cmocka_unit_test_setup_teardown(torture_options_set_key_exchange, setup, teardown),
|
cmocka_unit_test_setup_teardown(torture_options_set_key_exchange, setup, teardown),
|
||||||
|
|||||||
@@ -104,8 +104,7 @@ static void torture_packet(const char *cipher,
|
|||||||
|
|
||||||
assert_non_null(session->out_buffer);
|
assert_non_null(session->out_buffer);
|
||||||
ssh_buffer_add_data(session->out_buffer, test_data, payload_len);
|
ssh_buffer_add_data(session->out_buffer, test_data, payload_len);
|
||||||
session->socket->fd_out = sockets[0];
|
session->socket->fd = sockets[0];
|
||||||
session->socket->fd_in = -2;
|
|
||||||
session->socket->write_wontblock = 1;
|
session->socket->write_wontblock = 1;
|
||||||
rc = ssh_packet_send(session);
|
rc = ssh_packet_send(session);
|
||||||
assert_int_equal(rc, SSH_OK);
|
assert_int_equal(rc, SSH_OK);
|
||||||
@@ -126,8 +125,7 @@ static void torture_packet(const char *cipher,
|
|||||||
}
|
}
|
||||||
close(sockets[0]);
|
close(sockets[0]);
|
||||||
close(sockets[1]);
|
close(sockets[1]);
|
||||||
session->socket->fd_in = SSH_INVALID_SOCKET;
|
session->socket->fd = SSH_INVALID_SOCKET;
|
||||||
session->socket->fd_out = SSH_INVALID_SOCKET;
|
|
||||||
ssh_free(session);
|
ssh_free(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user