mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-05 21:00:33 +09:00
Compare commits
63 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 | ||
|
|
789df0b7d0 | ||
|
|
66a222a73c | ||
|
|
09a7638575 | ||
|
|
203818608a | ||
|
|
f8c452cbef | ||
|
|
adeaa69cc5 | ||
|
|
72bce5ece7 | ||
|
|
7819621fc2 | ||
|
|
fcfba0d8aa | ||
|
|
b166ac4749 | ||
|
|
160a416ef6 | ||
|
|
59071bc4c5 | ||
|
|
2ae63251d3 | ||
|
|
eefae820b5 | ||
|
|
0792fb37b0 | ||
|
|
e23c28a82b | ||
|
|
7291b50420 | ||
|
|
c1d61617fb | ||
|
|
488fb47c32 | ||
|
|
721132696c | ||
|
|
ee034e0484 | ||
|
|
d56c8fdfc6 | ||
|
|
4269b62153 | ||
|
|
c6c63030c5 | ||
|
|
afa5dbb8b1 | ||
|
|
bd7e8295e2 | ||
|
|
933d9c6b07 | ||
|
|
0f0eb05e03 | ||
|
|
171a950a80 | ||
|
|
b1b1da0f97 | ||
|
|
7453038d74 | ||
|
|
29ef92a95e | ||
|
|
6650685758 | ||
|
|
bdca6b7efa | ||
|
|
97b2a61d74 | ||
|
|
781ce47dea | ||
|
|
277ee932d6 |
@@ -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.3 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.0")
|
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
|
||||||
|
|||||||
17
ChangeLog
17
ChangeLog
@@ -1,6 +1,23 @@
|
|||||||
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)
|
||||||
|
* Fixed CVE-2018-10933
|
||||||
|
* Fixed building without globbing support
|
||||||
|
* Fixed possible memory leaks
|
||||||
|
* Avoid SIGPIPE on sockets
|
||||||
|
|
||||||
version 0.8.3 (released 2018-09-21)
|
version 0.8.3 (released 2018-09-21)
|
||||||
* Added support for rsa-sha2
|
* Added support for rsa-sha2
|
||||||
* Added support to parse private keys in openssh container format
|
* Added support to parse private keys in openssh container format
|
||||||
|
|||||||
@@ -273,6 +273,13 @@ int main(void) {
|
|||||||
# For detecting attributes we need to treat warnings as
|
# For detecting attributes we need to treat warnings as
|
||||||
# errors
|
# errors
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
|
# Get warnings for attributs
|
||||||
|
check_c_compiler_flag("-Wattributs" REQUIRED_FLAGS_WERROR)
|
||||||
|
if (REQUIRED_FLAGS_WERROR)
|
||||||
|
set(CMAKE_REQUIRED_FLAGS "-Wattributes")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Turn warnings into errors
|
||||||
check_c_compiler_flag("-Werror" REQUIRED_FLAGS_WERROR)
|
check_c_compiler_flag("-Werror" REQUIRED_FLAGS_WERROR)
|
||||||
if (REQUIRED_FLAGS_WERROR)
|
if (REQUIRED_FLAGS_WERROR)
|
||||||
set(CMAKE_REQUIRED_FLAGS "-Werror")
|
set(CMAKE_REQUIRED_FLAGS "-Werror")
|
||||||
|
|||||||
@@ -16,3 +16,6 @@ set(CMAKE_COLOR_MAKEFILE ON)
|
|||||||
|
|
||||||
# Create the compile command database for clang by default
|
# Create the compile command database for clang by default
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
|
# Always build with -fPIC
|
||||||
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -25,148 +25,230 @@ program.
|
|||||||
static char **sources;
|
static char **sources;
|
||||||
static int nsources;
|
static int nsources;
|
||||||
static char *destination;
|
static char *destination;
|
||||||
static int verbosity=0;
|
static int verbosity = 0;
|
||||||
|
|
||||||
struct location {
|
struct location {
|
||||||
int is_ssh;
|
int is_ssh;
|
||||||
char *user;
|
char *user;
|
||||||
char *host;
|
char *host;
|
||||||
char *path;
|
char *path;
|
||||||
ssh_session session;
|
ssh_session session;
|
||||||
ssh_scp scp;
|
ssh_scp scp;
|
||||||
FILE *file;
|
FILE *file;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
READ,
|
READ,
|
||||||
WRITE
|
WRITE
|
||||||
};
|
};
|
||||||
|
|
||||||
static void usage(const char *argv0){
|
static void usage(const char *argv0) {
|
||||||
fprintf(stderr,"Usage : %s [options] [[user@]host1:]file1 ... \n"
|
fprintf(stderr, "Usage : %s [options] [[user@]host1:]file1 ... \n"
|
||||||
" [[user@]host2:]destination\n"
|
" [[user@]host2:]destination\n"
|
||||||
"sample scp client - libssh-%s\n",
|
"sample scp client - libssh-%s\n",
|
||||||
// "Options :\n",
|
// "Options :\n",
|
||||||
// " -r : use RSA to verify host public key\n",
|
// " -r : use RSA to verify host public key\n",
|
||||||
argv0,
|
argv0,
|
||||||
ssh_version(0));
|
ssh_version(0));
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int opts(int argc, char **argv){
|
static int opts(int argc, char **argv) {
|
||||||
int i;
|
int i;
|
||||||
while((i=getopt(argc,argv,"v"))!=-1){
|
|
||||||
switch(i){
|
while((i = getopt(argc, argv, "v")) != -1) {
|
||||||
case 'v':
|
switch(i) {
|
||||||
verbosity++;
|
case 'v':
|
||||||
break;
|
verbosity++;
|
||||||
default:
|
break;
|
||||||
fprintf(stderr,"unknown option %c\n",optopt);
|
default:
|
||||||
|
fprintf(stderr, "unknown option %c\n", optopt);
|
||||||
|
usage(argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsources = argc - optind - 1;
|
||||||
|
if (nsources < 1) {
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
nsources=argc-optind-1;
|
sources = malloc((nsources + 1) * sizeof(char *));
|
||||||
if(nsources < 1){
|
if (sources == NULL) {
|
||||||
usage(argv[0]);
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
sources=malloc((nsources + 1) * sizeof(char *));
|
for(i = 0; i < nsources; ++i) {
|
||||||
if(sources == NULL)
|
sources[i] = argv[optind];
|
||||||
return -1;
|
optind++;
|
||||||
for(i=0;i<nsources;++i){
|
}
|
||||||
sources[i] = argv[optind];
|
|
||||||
optind++;
|
sources[i] = NULL;
|
||||||
}
|
destination = argv[optind];
|
||||||
sources[i]=NULL;
|
return 0;
|
||||||
destination=argv[optind];
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct location *parse_location(char *loc){
|
static void location_free(struct location *loc)
|
||||||
struct location *location;
|
{
|
||||||
char *ptr;
|
if (loc) {
|
||||||
|
if (loc->path) {
|
||||||
|
free(loc->path);
|
||||||
|
}
|
||||||
|
loc->path = NULL;
|
||||||
|
if (loc->is_ssh) {
|
||||||
|
if (loc->host) {
|
||||||
|
free(loc->host);
|
||||||
|
}
|
||||||
|
loc->host = NULL;
|
||||||
|
if (loc->user) {
|
||||||
|
free(loc->user);
|
||||||
|
}
|
||||||
|
loc->user = NULL;
|
||||||
|
if (loc->host) {
|
||||||
|
free(loc->host);
|
||||||
|
}
|
||||||
|
loc->host = NULL;
|
||||||
|
}
|
||||||
|
free(loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
location = malloc(sizeof(struct location));
|
static struct location *parse_location(char *loc) {
|
||||||
if (location == NULL) {
|
struct location *location;
|
||||||
return NULL;
|
char *ptr;
|
||||||
}
|
|
||||||
memset(location, 0, sizeof(struct location));
|
|
||||||
|
|
||||||
location->host=location->user=NULL;
|
location = malloc(sizeof(struct location));
|
||||||
ptr=strchr(loc,':');
|
if (location == NULL) {
|
||||||
if(ptr != NULL){
|
return NULL;
|
||||||
location->is_ssh=1;
|
}
|
||||||
location->path=strdup(ptr+1);
|
memset(location, 0, sizeof(struct location));
|
||||||
*ptr='\0';
|
|
||||||
ptr=strchr(loc,'@');
|
location->host = location->user = NULL;
|
||||||
if(ptr != NULL){
|
ptr = strchr(loc, ':');
|
||||||
location->host=strdup(ptr+1);
|
|
||||||
*ptr='\0';
|
if (ptr != NULL) {
|
||||||
location->user=strdup(loc);
|
location->is_ssh = 1;
|
||||||
|
location->path = strdup(ptr+1);
|
||||||
|
*ptr = '\0';
|
||||||
|
ptr = strchr(loc, '@');
|
||||||
|
|
||||||
|
if (ptr != NULL) {
|
||||||
|
location->host = strdup(ptr+1);
|
||||||
|
*ptr = '\0';
|
||||||
|
location->user = strdup(loc);
|
||||||
|
} else {
|
||||||
|
location->host = strdup(loc);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
location->host=strdup(loc);
|
location->is_ssh = 0;
|
||||||
|
location->path = strdup(loc);
|
||||||
}
|
}
|
||||||
} else {
|
return location;
|
||||||
location->is_ssh=0;
|
|
||||||
location->path=strdup(loc);
|
|
||||||
}
|
|
||||||
return location;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int open_location(struct location *loc, int flag){
|
static void close_location(struct location *loc) {
|
||||||
if(loc->is_ssh && flag==WRITE){
|
int rc;
|
||||||
loc->session=connect_ssh(loc->host,loc->user,verbosity);
|
|
||||||
if(!loc->session){
|
if (loc) {
|
||||||
fprintf(stderr,"Couldn't connect to %s\n",loc->host);
|
if (loc->is_ssh) {
|
||||||
return -1;
|
if (loc->scp) {
|
||||||
|
rc = ssh_scp_close(loc->scp);
|
||||||
|
if (rc == SSH_ERROR) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Error closing scp: %s\n",
|
||||||
|
ssh_get_error(loc->session));
|
||||||
|
}
|
||||||
|
ssh_scp_free(loc->scp);
|
||||||
|
loc->scp = NULL;
|
||||||
|
}
|
||||||
|
if (loc->session) {
|
||||||
|
ssh_disconnect(loc->session);
|
||||||
|
ssh_free(loc->session);
|
||||||
|
loc->session = NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (loc->file) {
|
||||||
|
fclose(loc->file);
|
||||||
|
loc->file = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
loc->scp=ssh_scp_new(loc->session,SSH_SCP_WRITE,loc->path);
|
}
|
||||||
if(!loc->scp){
|
|
||||||
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
|
static int open_location(struct location *loc, int flag) {
|
||||||
return -1;
|
if (loc->is_ssh && flag == WRITE) {
|
||||||
|
loc->session = connect_ssh(loc->host, loc->user, verbosity);
|
||||||
|
if (!loc->session) {
|
||||||
|
fprintf(stderr, "Couldn't connect to %s\n", loc->host);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
loc->scp = ssh_scp_new(loc->session, SSH_SCP_WRITE, loc->path);
|
||||||
|
if (!loc->scp) {
|
||||||
|
fprintf(stderr, "error : %s\n", ssh_get_error(loc->session));
|
||||||
|
ssh_disconnect(loc->session);
|
||||||
|
ssh_free(loc->session);
|
||||||
|
loc->session = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ssh_scp_init(loc->scp) == SSH_ERROR) {
|
||||||
|
fprintf(stderr, "error : %s\n", ssh_get_error(loc->session));
|
||||||
|
ssh_scp_free(loc->scp);
|
||||||
|
loc->scp = NULL;
|
||||||
|
ssh_disconnect(loc->session);
|
||||||
|
ssh_free(loc->session);
|
||||||
|
loc->session = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} else if (loc->is_ssh && flag == READ) {
|
||||||
|
loc->session = connect_ssh(loc->host, loc->user, verbosity);
|
||||||
|
if (!loc->session) {
|
||||||
|
fprintf(stderr, "Couldn't connect to %s\n", loc->host);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
loc->scp = ssh_scp_new(loc->session, SSH_SCP_READ, loc->path);
|
||||||
|
if (!loc->scp) {
|
||||||
|
fprintf(stderr, "error : %s\n", ssh_get_error(loc->session));
|
||||||
|
ssh_disconnect(loc->session);
|
||||||
|
ssh_free(loc->session);
|
||||||
|
loc->session = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ssh_scp_init(loc->scp) == SSH_ERROR) {
|
||||||
|
fprintf(stderr, "error : %s\n", ssh_get_error(loc->session));
|
||||||
|
ssh_scp_free(loc->scp);
|
||||||
|
loc->scp = NULL;
|
||||||
|
ssh_disconnect(loc->session);
|
||||||
|
ssh_free(loc->session);
|
||||||
|
loc->session = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
loc->file = fopen(loc->path, flag == READ ? "r":"w");
|
||||||
|
if (!loc->file) {
|
||||||
|
if (errno == EISDIR) {
|
||||||
|
if (chdir(loc->path)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Error changing directory to %s: %s\n",
|
||||||
|
loc->path, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
fprintf(stderr,
|
||||||
|
"Error opening %s: %s\n",
|
||||||
|
loc->path, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
if(ssh_scp_init(loc->scp)==SSH_ERROR){
|
return -1;
|
||||||
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
|
|
||||||
ssh_scp_free(loc->scp);
|
|
||||||
loc->scp = NULL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
} else if(loc->is_ssh && flag==READ){
|
|
||||||
loc->session=connect_ssh(loc->host, loc->user,verbosity);
|
|
||||||
if(!loc->session){
|
|
||||||
fprintf(stderr,"Couldn't connect to %s\n",loc->host);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
loc->scp=ssh_scp_new(loc->session,SSH_SCP_READ,loc->path);
|
|
||||||
if(!loc->scp){
|
|
||||||
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(ssh_scp_init(loc->scp)==SSH_ERROR){
|
|
||||||
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
|
|
||||||
ssh_scp_free(loc->scp);
|
|
||||||
loc->scp = NULL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
loc->file=fopen(loc->path,flag==READ ? "r":"w");
|
|
||||||
if(!loc->file){
|
|
||||||
if(errno==EISDIR){
|
|
||||||
if(chdir(loc->path)){
|
|
||||||
fprintf(stderr,"Error changing directory to %s: %s\n",loc->path,strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
fprintf(stderr,"Error opening %s: %s\n",loc->path,strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief copies files from source location to destination
|
/** @brief copies files from source location to destination
|
||||||
@@ -174,155 +256,197 @@ static int open_location(struct location *loc, int flag){
|
|||||||
* @param dest destination location
|
* @param dest destination location
|
||||||
* @param recursive Copy also directories
|
* @param recursive Copy also directories
|
||||||
*/
|
*/
|
||||||
static int do_copy(struct location *src, struct location *dest, int recursive){
|
static int do_copy(struct location *src, struct location *dest, int recursive) {
|
||||||
int size;
|
int size;
|
||||||
socket_t fd;
|
socket_t fd;
|
||||||
struct stat s;
|
struct stat s;
|
||||||
int w,r;
|
int w, r;
|
||||||
char buffer[16384];
|
char buffer[16384];
|
||||||
int total=0;
|
int total = 0;
|
||||||
int mode;
|
int mode;
|
||||||
char *filename = NULL;
|
char *filename = NULL;
|
||||||
/* recursive mode doesn't work yet */
|
/* recursive mode doesn't work yet */
|
||||||
(void)recursive;
|
(void)recursive;
|
||||||
/* Get the file name and size*/
|
/* Get the file name and size*/
|
||||||
if(!src->is_ssh){
|
if (!src->is_ssh) {
|
||||||
fd = fileno(src->file);
|
fd = fileno(src->file);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
fprintf(stderr, "Invalid file pointer, error: %s\n", strerror(errno));
|
fprintf(stderr,
|
||||||
return -1;
|
"Invalid file pointer, error: %s\n",
|
||||||
}
|
strerror(errno));
|
||||||
r = fstat(fd, &s);
|
return -1;
|
||||||
if (r < 0) {
|
}
|
||||||
return -1;
|
r = fstat(fd, &s);
|
||||||
}
|
if (r < 0) {
|
||||||
size=s.st_size;
|
return -1;
|
||||||
mode = s.st_mode & ~S_IFMT;
|
}
|
||||||
filename=ssh_basename(src->path);
|
size = s.st_size;
|
||||||
} else {
|
mode = s.st_mode & ~S_IFMT;
|
||||||
size=0;
|
filename = ssh_basename(src->path);
|
||||||
do {
|
} else {
|
||||||
r=ssh_scp_pull_request(src->scp);
|
size = 0;
|
||||||
if(r==SSH_SCP_REQUEST_NEWDIR){
|
do {
|
||||||
ssh_scp_deny_request(src->scp,"Not in recursive mode");
|
r = ssh_scp_pull_request(src->scp);
|
||||||
continue;
|
if (r == SSH_SCP_REQUEST_NEWDIR) {
|
||||||
}
|
ssh_scp_deny_request(src->scp, "Not in recursive mode");
|
||||||
if(r==SSH_SCP_REQUEST_NEWFILE){
|
continue;
|
||||||
size=ssh_scp_request_get_size(src->scp);
|
}
|
||||||
filename=strdup(ssh_scp_request_get_filename(src->scp));
|
if (r == SSH_SCP_REQUEST_NEWFILE) {
|
||||||
mode=ssh_scp_request_get_permissions(src->scp);
|
size = ssh_scp_request_get_size(src->scp);
|
||||||
//ssh_scp_accept_request(src->scp);
|
filename = strdup(ssh_scp_request_get_filename(src->scp));
|
||||||
break;
|
mode = ssh_scp_request_get_permissions(src->scp);
|
||||||
}
|
//ssh_scp_accept_request(src->scp);
|
||||||
if(r==SSH_ERROR){
|
break;
|
||||||
fprintf(stderr,"Error: %s\n",ssh_get_error(src->session));
|
}
|
||||||
|
if (r == SSH_ERROR) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Error: %s\n",
|
||||||
|
ssh_get_error(src->session));
|
||||||
ssh_string_free_char(filename);
|
ssh_string_free_char(filename);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} while(r != SSH_SCP_REQUEST_NEWFILE);
|
} while(r != SSH_SCP_REQUEST_NEWFILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dest->is_ssh){
|
if (dest->is_ssh) {
|
||||||
r=ssh_scp_push_file(dest->scp,src->path, size, mode);
|
r = ssh_scp_push_file(dest->scp, src->path, size, mode);
|
||||||
// snprintf(buffer,sizeof(buffer),"C0644 %d %s\n",size,src->path);
|
// snprintf(buffer, sizeof(buffer), "C0644 %d %s\n", size, src->path);
|
||||||
if(r==SSH_ERROR){
|
if (r == SSH_ERROR) {
|
||||||
fprintf(stderr,"error: %s\n",ssh_get_error(dest->session));
|
fprintf(stderr,
|
||||||
ssh_string_free_char(filename);
|
"error: %s\n",
|
||||||
ssh_scp_free(dest->scp);
|
ssh_get_error(dest->session));
|
||||||
dest->scp = NULL;
|
ssh_string_free_char(filename);
|
||||||
return -1;
|
ssh_scp_free(dest->scp);
|
||||||
}
|
dest->scp = NULL;
|
||||||
} else {
|
return -1;
|
||||||
if(!dest->file){
|
}
|
||||||
dest->file=fopen(filename,"w");
|
} else {
|
||||||
if(!dest->file){
|
if (!dest->file) {
|
||||||
fprintf(stderr,"Cannot open %s for writing: %s\n",filename,strerror(errno));
|
dest->file = fopen(filename, "w");
|
||||||
if(src->is_ssh)
|
if (!dest->file) {
|
||||||
ssh_scp_deny_request(src->scp,"Cannot open local file");
|
fprintf(stderr,
|
||||||
ssh_string_free_char(filename);
|
"Cannot open %s for writing: %s\n",
|
||||||
return -1;
|
filename, strerror(errno));
|
||||||
}
|
if (src->is_ssh) {
|
||||||
}
|
ssh_scp_deny_request(src->scp, "Cannot open local file");
|
||||||
if(src->is_ssh){
|
}
|
||||||
ssh_scp_accept_request(src->scp);
|
ssh_string_free_char(filename);
|
||||||
}
|
return -1;
|
||||||
}
|
}
|
||||||
do {
|
}
|
||||||
if(src->is_ssh){
|
if (src->is_ssh) {
|
||||||
r=ssh_scp_read(src->scp,buffer,sizeof(buffer));
|
ssh_scp_accept_request(src->scp);
|
||||||
if(r==SSH_ERROR){
|
}
|
||||||
fprintf(stderr,"Error reading scp: %s\n",ssh_get_error(src->session));
|
}
|
||||||
ssh_string_free_char(filename);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(r==0)
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
r=fread(buffer,1,sizeof(buffer),src->file);
|
|
||||||
if(r==0)
|
|
||||||
break;
|
|
||||||
if(r<0){
|
|
||||||
fprintf(stderr,"Error reading file: %s\n",strerror(errno));
|
|
||||||
ssh_string_free_char(filename);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(dest->is_ssh){
|
|
||||||
w=ssh_scp_write(dest->scp,buffer,r);
|
|
||||||
if(w == SSH_ERROR){
|
|
||||||
fprintf(stderr,"Error writing in scp: %s\n",ssh_get_error(dest->session));
|
|
||||||
ssh_scp_free(dest->scp);
|
|
||||||
dest->scp=NULL;
|
|
||||||
ssh_string_free_char(filename);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
w=fwrite(buffer,r,1,dest->file);
|
|
||||||
if(w<=0){
|
|
||||||
fprintf(stderr,"Error writing in local file: %s\n",strerror(errno));
|
|
||||||
ssh_string_free_char(filename);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
total+=r;
|
|
||||||
|
|
||||||
} while(total < size);
|
do {
|
||||||
ssh_string_free_char(filename);
|
if (src->is_ssh) {
|
||||||
printf("wrote %d bytes\n",total);
|
r = ssh_scp_read(src->scp, buffer, sizeof(buffer));
|
||||||
return 0;
|
if (r == SSH_ERROR) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Error reading scp: %s\n",
|
||||||
|
ssh_get_error(src->session));
|
||||||
|
ssh_string_free_char(filename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
r = fread(buffer, 1, sizeof(buffer), src->file);
|
||||||
|
if (r == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r < 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Error reading file: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
ssh_string_free_char(filename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dest->is_ssh) {
|
||||||
|
w = ssh_scp_write(dest->scp, buffer, r);
|
||||||
|
if (w == SSH_ERROR) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Error writing in scp: %s\n",
|
||||||
|
ssh_get_error(dest->session));
|
||||||
|
ssh_scp_free(dest->scp);
|
||||||
|
dest->scp = NULL;
|
||||||
|
ssh_string_free_char(filename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
w = fwrite(buffer, r, 1, dest->file);
|
||||||
|
if (w <= 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Error writing in local file: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
ssh_string_free_char(filename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
total += r;
|
||||||
|
|
||||||
|
} while(total < size);
|
||||||
|
|
||||||
|
ssh_string_free_char(filename);
|
||||||
|
printf("wrote %d bytes\n", total);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv){
|
int main(int argc, char **argv) {
|
||||||
struct location *dest, *src;
|
struct location *dest, *src;
|
||||||
int i;
|
int i;
|
||||||
int r;
|
int r;
|
||||||
if(opts(argc,argv)<0)
|
if (opts(argc, argv) < 0) {
|
||||||
return EXIT_FAILURE;
|
r = EXIT_FAILURE;
|
||||||
dest=parse_location(destination);
|
goto end;
|
||||||
if(open_location(dest,WRITE)<0)
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
for(i=0;i<nsources;++i){
|
|
||||||
src=parse_location(sources[i]);
|
|
||||||
if(open_location(src,READ)<0){
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
}
|
||||||
if(do_copy(src,dest,0) < 0){
|
|
||||||
break;
|
dest = parse_location(destination);
|
||||||
|
if (dest == NULL) {
|
||||||
|
r = EXIT_FAILURE;
|
||||||
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (dest->is_ssh && dest->scp != NULL) {
|
if (open_location(dest, WRITE) < 0) {
|
||||||
r=ssh_scp_close(dest->scp);
|
location_free(dest);
|
||||||
if(r == SSH_ERROR){
|
r = EXIT_FAILURE;
|
||||||
fprintf(stderr,"Error closing scp: %s\n",ssh_get_error(dest->session));
|
goto end;
|
||||||
ssh_scp_free(dest->scp);
|
}
|
||||||
dest->scp=NULL;
|
|
||||||
return -1;
|
for (i = 0; i < nsources; ++i) {
|
||||||
}
|
src = parse_location(sources[i]);
|
||||||
} else {
|
if (src == NULL) {
|
||||||
fclose(dest->file);
|
r = EXIT_FAILURE;
|
||||||
dest->file=NULL;
|
goto close_dest;
|
||||||
}
|
}
|
||||||
ssh_disconnect(dest->session);
|
|
||||||
ssh_finalize();
|
if (open_location(src, READ) < 0) {
|
||||||
return 0;
|
location_free(src);
|
||||||
|
r = EXIT_FAILURE;
|
||||||
|
goto close_dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_copy(src, dest, 0) < 0) {
|
||||||
|
close_location(src);
|
||||||
|
location_free(src);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
close_location(src);
|
||||||
|
location_free(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
r = 0;
|
||||||
|
|
||||||
|
close_dest:
|
||||||
|
close_location(dest);
|
||||||
|
location_free(dest);
|
||||||
|
end:
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -76,6 +76,14 @@ enum ssh_auth_state_e {
|
|||||||
SSH_AUTH_STATE_GSSAPI_TOKEN,
|
SSH_AUTH_STATE_GSSAPI_TOKEN,
|
||||||
/** We have sent the MIC and expecting to be authenticated */
|
/** We have sent the MIC and expecting to be authenticated */
|
||||||
SSH_AUTH_STATE_GSSAPI_MIC_SENT,
|
SSH_AUTH_STATE_GSSAPI_MIC_SENT,
|
||||||
|
/** We have offered a pubkey to check if it is supported */
|
||||||
|
SSH_AUTH_STATE_PUBKEY_OFFER_SENT,
|
||||||
|
/** We have sent pubkey and signature expecting to be authenticated */
|
||||||
|
SSH_AUTH_STATE_PUBKEY_AUTH_SENT,
|
||||||
|
/** We have sent a password expecting to be authenticated */
|
||||||
|
SSH_AUTH_STATE_PASSWORD_AUTH_SENT,
|
||||||
|
/** We have sent a request without auth information (method 'none') */
|
||||||
|
SSH_AUTH_STATE_AUTH_NONE_SENT,
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @internal
|
/** @internal
|
||||||
|
|||||||
@@ -92,7 +92,6 @@ SSH_PACKET_CALLBACK(channel_rcv_close);
|
|||||||
SSH_PACKET_CALLBACK(channel_rcv_request);
|
SSH_PACKET_CALLBACK(channel_rcv_request);
|
||||||
SSH_PACKET_CALLBACK(channel_rcv_data);
|
SSH_PACKET_CALLBACK(channel_rcv_data);
|
||||||
|
|
||||||
ssh_channel ssh_channel_new(ssh_session session);
|
|
||||||
int channel_default_bufferize(ssh_channel channel, void *data, int len,
|
int channel_default_bufferize(ssh_channel channel, void *data, int len,
|
||||||
int is_stderr);
|
int is_stderr);
|
||||||
int ssh_channel_flush(ssh_channel channel);
|
int ssh_channel_flush(ssh_channel channel);
|
||||||
|
|||||||
@@ -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 3
|
#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, \
|
||||||
@@ -630,6 +630,8 @@ typedef int (*ssh_auth_callback) (const char *prompt, char *buf, size_t len,
|
|||||||
int echo, int verify, void *userdata);
|
int echo, int verify, void *userdata);
|
||||||
|
|
||||||
LIBSSH_API ssh_key ssh_key_new(void);
|
LIBSSH_API ssh_key ssh_key_new(void);
|
||||||
|
#define SSH_KEY_FREE(x) \
|
||||||
|
do { if ((x) != NULL) { ssh_key_free(x); x = NULL; } } while(0)
|
||||||
LIBSSH_API void ssh_key_free (ssh_key key);
|
LIBSSH_API void ssh_key_free (ssh_key key);
|
||||||
LIBSSH_API enum ssh_keytypes_e ssh_key_type(const ssh_key key);
|
LIBSSH_API enum ssh_keytypes_e ssh_key_type(const ssh_key key);
|
||||||
LIBSSH_API const char *ssh_key_type_to_char(enum ssh_keytypes_e type);
|
LIBSSH_API const char *ssh_key_type_to_char(enum ssh_keytypes_e type);
|
||||||
|
|||||||
@@ -43,6 +43,12 @@ enum ssh_packet_state_e {
|
|||||||
PACKET_STATE_PROCESSING
|
PACKET_STATE_PROCESSING
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ssh_packet_filter_result_e {
|
||||||
|
SSH_PACKET_UNKNOWN,
|
||||||
|
SSH_PACKET_ALLOWED,
|
||||||
|
SSH_PACKET_DENIED
|
||||||
|
};
|
||||||
|
|
||||||
int ssh_packet_send(ssh_session session);
|
int ssh_packet_send(ssh_session session);
|
||||||
|
|
||||||
SSH_PACKET_CALLBACK(ssh_packet_unimplemented);
|
SSH_PACKET_CALLBACK(ssh_packet_unimplemented);
|
||||||
|
|||||||
@@ -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.0
|
4.7.2
|
||||||
415
src/ABI/libssh-4.7.1.symbols
Normal file
415
src/ABI/libssh-4.7.1.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
|
||||||
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;
|
||||||
|
|
||||||
|
|||||||
56
src/auth.c
56
src/auth.c
@@ -85,6 +85,10 @@ static int ssh_auth_response_termination(void *user) {
|
|||||||
case SSH_AUTH_STATE_GSSAPI_REQUEST_SENT:
|
case SSH_AUTH_STATE_GSSAPI_REQUEST_SENT:
|
||||||
case SSH_AUTH_STATE_GSSAPI_TOKEN:
|
case SSH_AUTH_STATE_GSSAPI_TOKEN:
|
||||||
case SSH_AUTH_STATE_GSSAPI_MIC_SENT:
|
case SSH_AUTH_STATE_GSSAPI_MIC_SENT:
|
||||||
|
case SSH_AUTH_STATE_PUBKEY_AUTH_SENT:
|
||||||
|
case SSH_AUTH_STATE_PUBKEY_OFFER_SENT:
|
||||||
|
case SSH_AUTH_STATE_PASSWORD_AUTH_SENT:
|
||||||
|
case SSH_AUTH_STATE_AUTH_NONE_SENT:
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
return 1;
|
return 1;
|
||||||
@@ -167,6 +171,10 @@ static int ssh_userauth_get_response(ssh_session session) {
|
|||||||
case SSH_AUTH_STATE_GSSAPI_REQUEST_SENT:
|
case SSH_AUTH_STATE_GSSAPI_REQUEST_SENT:
|
||||||
case SSH_AUTH_STATE_GSSAPI_TOKEN:
|
case SSH_AUTH_STATE_GSSAPI_TOKEN:
|
||||||
case SSH_AUTH_STATE_GSSAPI_MIC_SENT:
|
case SSH_AUTH_STATE_GSSAPI_MIC_SENT:
|
||||||
|
case SSH_AUTH_STATE_PUBKEY_OFFER_SENT:
|
||||||
|
case SSH_AUTH_STATE_PUBKEY_AUTH_SENT:
|
||||||
|
case SSH_AUTH_STATE_PASSWORD_AUTH_SENT:
|
||||||
|
case SSH_AUTH_STATE_AUTH_NONE_SENT:
|
||||||
case SSH_AUTH_STATE_NONE:
|
case SSH_AUTH_STATE_NONE:
|
||||||
/* not reached */
|
/* not reached */
|
||||||
rc = SSH_AUTH_ERROR;
|
rc = SSH_AUTH_ERROR;
|
||||||
@@ -312,24 +320,30 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_success) {
|
|||||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_pk_ok) {
|
SSH_PACKET_CALLBACK(ssh_packet_userauth_pk_ok) {
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
SSH_LOG(SSH_LOG_TRACE, "Received SSH_USERAUTH_PK_OK/INFO_REQUEST/GSSAPI_RESPONSE");
|
|
||||||
|
|
||||||
if (session->auth.state == SSH_AUTH_STATE_KBDINT_SENT) {
|
|
||||||
/* Assuming we are in keyboard-interactive context */
|
|
||||||
SSH_LOG(SSH_LOG_TRACE,
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
"keyboard-interactive context, assuming SSH_USERAUTH_INFO_REQUEST");
|
"Received SSH_USERAUTH_PK_OK/INFO_REQUEST/GSSAPI_RESPONSE");
|
||||||
rc = ssh_packet_userauth_info_request(session,type,packet,user);
|
|
||||||
#ifdef WITH_GSSAPI
|
|
||||||
} else if (session->auth.state == SSH_AUTH_STATE_GSSAPI_REQUEST_SENT) {
|
|
||||||
rc = ssh_packet_userauth_gssapi_response(session, type, packet, user);
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
session->auth.state = SSH_AUTH_STATE_PK_OK;
|
|
||||||
SSH_LOG(SSH_LOG_TRACE, "Assuming SSH_USERAUTH_PK_OK");
|
|
||||||
rc = SSH_PACKET_USED;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
if (session->auth.state == SSH_AUTH_STATE_KBDINT_SENT) {
|
||||||
|
/* Assuming we are in keyboard-interactive context */
|
||||||
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
|
"keyboard-interactive context, "
|
||||||
|
"assuming SSH_USERAUTH_INFO_REQUEST");
|
||||||
|
rc = ssh_packet_userauth_info_request(session,type,packet,user);
|
||||||
|
#ifdef WITH_GSSAPI
|
||||||
|
} else if (session->auth.state == SSH_AUTH_STATE_GSSAPI_REQUEST_SENT) {
|
||||||
|
rc = ssh_packet_userauth_gssapi_response(session, type, packet, user);
|
||||||
|
#endif
|
||||||
|
} else if (session->auth.state == SSH_AUTH_STATE_PUBKEY_OFFER_SENT) {
|
||||||
|
session->auth.state = SSH_AUTH_STATE_PK_OK;
|
||||||
|
SSH_LOG(SSH_LOG_TRACE, "Assuming SSH_USERAUTH_PK_OK");
|
||||||
|
rc = SSH_PACKET_USED;
|
||||||
|
} else {
|
||||||
|
session->auth.state = SSH_AUTH_STATE_ERROR;
|
||||||
|
SSH_LOG(SSH_LOG_TRACE, "SSH_USERAUTH_PK_OK received in wrong state");
|
||||||
|
rc = SSH_PACKET_USED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -416,7 +430,7 @@ int ssh_userauth_none(ssh_session session, const char *username) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
session->auth.current_method = SSH_AUTH_METHOD_NONE;
|
session->auth.current_method = SSH_AUTH_METHOD_NONE;
|
||||||
session->auth.state = SSH_AUTH_STATE_NONE;
|
session->auth.state = SSH_AUTH_STATE_AUTH_NONE_SENT;
|
||||||
session->pending_call_state = SSH_PENDING_CALL_AUTH_NONE;
|
session->pending_call_state = SSH_PENDING_CALL_AUTH_NONE;
|
||||||
rc = ssh_packet_send(session);
|
rc = ssh_packet_send(session);
|
||||||
if (rc == SSH_ERROR) {
|
if (rc == SSH_ERROR) {
|
||||||
@@ -553,7 +567,7 @@ int ssh_userauth_try_publickey(ssh_session session,
|
|||||||
ssh_string_free(pubkey_s);
|
ssh_string_free(pubkey_s);
|
||||||
|
|
||||||
session->auth.current_method = SSH_AUTH_METHOD_PUBLICKEY;
|
session->auth.current_method = SSH_AUTH_METHOD_PUBLICKEY;
|
||||||
session->auth.state = SSH_AUTH_STATE_NONE;
|
session->auth.state = SSH_AUTH_STATE_PUBKEY_OFFER_SENT;
|
||||||
session->pending_call_state = SSH_PENDING_CALL_AUTH_OFFER_PUBKEY;
|
session->pending_call_state = SSH_PENDING_CALL_AUTH_OFFER_PUBKEY;
|
||||||
rc = ssh_packet_send(session);
|
rc = ssh_packet_send(session);
|
||||||
if (rc == SSH_ERROR) {
|
if (rc == SSH_ERROR) {
|
||||||
@@ -701,7 +715,7 @@ int ssh_userauth_publickey(ssh_session session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
session->auth.current_method = SSH_AUTH_METHOD_PUBLICKEY;
|
session->auth.current_method = SSH_AUTH_METHOD_PUBLICKEY;
|
||||||
session->auth.state = SSH_AUTH_STATE_NONE;
|
session->auth.state = SSH_AUTH_STATE_PUBKEY_AUTH_SENT;
|
||||||
session->pending_call_state = SSH_PENDING_CALL_AUTH_PUBKEY;
|
session->pending_call_state = SSH_PENDING_CALL_AUTH_PUBKEY;
|
||||||
rc = ssh_packet_send(session);
|
rc = ssh_packet_send(session);
|
||||||
if (rc == SSH_ERROR) {
|
if (rc == SSH_ERROR) {
|
||||||
@@ -797,7 +811,7 @@ static int ssh_userauth_agent_publickey(ssh_session session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
session->auth.current_method = SSH_AUTH_METHOD_PUBLICKEY;
|
session->auth.current_method = SSH_AUTH_METHOD_PUBLICKEY;
|
||||||
session->auth.state = SSH_AUTH_STATE_NONE;
|
session->auth.state = SSH_AUTH_STATE_PUBKEY_AUTH_SENT;
|
||||||
session->pending_call_state = SSH_PENDING_CALL_AUTH_AGENT;
|
session->pending_call_state = SSH_PENDING_CALL_AUTH_AGENT;
|
||||||
rc = ssh_packet_send(session);
|
rc = ssh_packet_send(session);
|
||||||
if (rc == SSH_ERROR) {
|
if (rc == SSH_ERROR) {
|
||||||
@@ -1258,7 +1272,7 @@ int ssh_userauth_password(ssh_session session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
session->auth.current_method = SSH_AUTH_METHOD_PASSWORD;
|
session->auth.current_method = SSH_AUTH_METHOD_PASSWORD;
|
||||||
session->auth.state = SSH_AUTH_STATE_NONE;
|
session->auth.state = SSH_AUTH_STATE_PASSWORD_AUTH_SENT;
|
||||||
session->pending_call_state = SSH_PENDING_CALL_AUTH_PASSWORD;
|
session->pending_call_state = SSH_PENDING_CALL_AUTH_PASSWORD;
|
||||||
rc = ssh_packet_send(session);
|
rc = ssh_packet_send(session);
|
||||||
if (rc == SSH_ERROR) {
|
if (rc == SSH_ERROR) {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -171,6 +171,15 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_open_conf){
|
|||||||
"Received a CHANNEL_OPEN_CONFIRMATION for channel %d:%d",
|
"Received a CHANNEL_OPEN_CONFIRMATION for channel %d:%d",
|
||||||
channel->local_channel,
|
channel->local_channel,
|
||||||
channel->remote_channel);
|
channel->remote_channel);
|
||||||
|
|
||||||
|
if (channel->state != SSH_CHANNEL_STATE_OPENING) {
|
||||||
|
SSH_LOG(SSH_LOG_RARE,
|
||||||
|
"SSH2_MSG_CHANNEL_OPEN_CONFIRMATION received in incorrect "
|
||||||
|
"channel state %d",
|
||||||
|
channel->state);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
SSH_LOG(SSH_LOG_PROTOCOL,
|
SSH_LOG(SSH_LOG_PROTOCOL,
|
||||||
"Remote window : %lu, maxpacket : %lu",
|
"Remote window : %lu, maxpacket : %lu",
|
||||||
(long unsigned int) channel->remote_window,
|
(long unsigned int) channel->remote_window,
|
||||||
@@ -211,6 +220,14 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_open_fail){
|
|||||||
return SSH_PACKET_USED;
|
return SSH_PACKET_USED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (channel->state != SSH_CHANNEL_STATE_OPENING) {
|
||||||
|
SSH_LOG(SSH_LOG_RARE,
|
||||||
|
"SSH2_MSG_CHANNEL_OPEN_FAILURE received in incorrect channel "
|
||||||
|
"state %d",
|
||||||
|
channel->state);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||||
"Channel opening failure: channel %u error (%lu) %s",
|
"Channel opening failure: channel %u error (%lu) %s",
|
||||||
channel->local_channel,
|
channel->local_channel,
|
||||||
@@ -219,6 +236,10 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_open_fail){
|
|||||||
SAFE_FREE(error);
|
SAFE_FREE(error);
|
||||||
channel->state=SSH_CHANNEL_STATE_OPEN_DENIED;
|
channel->state=SSH_CHANNEL_STATE_OPEN_DENIED;
|
||||||
return SSH_PACKET_USED;
|
return SSH_PACKET_USED;
|
||||||
|
|
||||||
|
error:
|
||||||
|
ssh_set_error(session, SSH_FATAL, "Invalid packet");
|
||||||
|
return SSH_PACKET_USED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ssh_channel_open_termination(void *c){
|
static int ssh_channel_open_termination(void *c){
|
||||||
|
|||||||
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) {
|
||||||
|
|||||||
@@ -462,7 +462,7 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
|||||||
|
|
||||||
p = ssh_config_get_str_tok(&s, NULL);
|
p = ssh_config_get_str_tok(&s, NULL);
|
||||||
if (p && *parsing) {
|
if (p && *parsing) {
|
||||||
#ifdef HAVE_GLOB
|
#if defined(HAVE_GLOB) && defined(HAVE_GLOB_GL_FLAGS_MEMBER)
|
||||||
local_parse_glob(session, p, parsing, seen);
|
local_parse_glob(session, p, parsing, seen);
|
||||||
#else
|
#else
|
||||||
local_parse_file(session, p, parsing, seen);
|
local_parse_file(session, p, parsing, seen);
|
||||||
|
|||||||
@@ -220,7 +220,12 @@ static int ssh_connect_ai_timeout(ssh_session session, const char *host,
|
|||||||
static int set_tcp_nodelay(socket_t socket)
|
static int set_tcp_nodelay(socket_t socket)
|
||||||
{
|
{
|
||||||
int opt = 1;
|
int opt = 1;
|
||||||
return setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
|
|
||||||
|
return setsockopt(socket,
|
||||||
|
IPPROTO_TCP,
|
||||||
|
TCP_NODELAY,
|
||||||
|
(void *)&opt,
|
||||||
|
sizeof(opt));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
127
src/connector.c
127
src/connector.c
@@ -26,6 +26,10 @@
|
|||||||
#include "libssh/callbacks.h"
|
#include "libssh/callbacks.h"
|
||||||
#include "libssh/session.h"
|
#include "libssh/session.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#define CHUNKSIZE 4096
|
#define CHUNKSIZE 4096
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -40,6 +44,9 @@
|
|||||||
# undef unlink
|
# undef unlink
|
||||||
# define unlink _unlink
|
# define unlink _unlink
|
||||||
# endif /* HAVE_IO_H */
|
# endif /* HAVE_IO_H */
|
||||||
|
#else
|
||||||
|
# include <sys/types.h>
|
||||||
|
# include <sys/socket.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct ssh_connector_struct {
|
struct ssh_connector_struct {
|
||||||
@@ -51,6 +58,8 @@ struct ssh_connector_struct {
|
|||||||
socket_t in_fd;
|
socket_t in_fd;
|
||||||
socket_t out_fd;
|
socket_t out_fd;
|
||||||
|
|
||||||
|
bool fd_is_socket;
|
||||||
|
|
||||||
ssh_poll_handle in_poll;
|
ssh_poll_handle in_poll;
|
||||||
ssh_poll_handle out_poll;
|
ssh_poll_handle out_poll;
|
||||||
|
|
||||||
@@ -76,6 +85,13 @@ static int ssh_connector_channel_write_wontblock_cb(ssh_session session,
|
|||||||
ssh_channel channel,
|
ssh_channel channel,
|
||||||
size_t bytes,
|
size_t bytes,
|
||||||
void *userdata);
|
void *userdata);
|
||||||
|
static ssize_t ssh_connector_fd_read(ssh_connector connector,
|
||||||
|
void *buffer,
|
||||||
|
uint32_t len);
|
||||||
|
static ssize_t ssh_connector_fd_write(ssh_connector connector,
|
||||||
|
const void *buffer,
|
||||||
|
uint32_t len);
|
||||||
|
static bool ssh_connector_fd_is_socket(socket_t socket);
|
||||||
|
|
||||||
ssh_connector ssh_connector_new(ssh_session session)
|
ssh_connector ssh_connector_new(ssh_session session)
|
||||||
{
|
{
|
||||||
@@ -91,6 +107,8 @@ ssh_connector ssh_connector_new(ssh_session session)
|
|||||||
connector->in_fd = SSH_INVALID_SOCKET;
|
connector->in_fd = SSH_INVALID_SOCKET;
|
||||||
connector->out_fd = SSH_INVALID_SOCKET;
|
connector->out_fd = SSH_INVALID_SOCKET;
|
||||||
|
|
||||||
|
connector->fd_is_socket = false;
|
||||||
|
|
||||||
ssh_callbacks_init(&connector->in_channel_cb);
|
ssh_callbacks_init(&connector->in_channel_cb);
|
||||||
ssh_callbacks_init(&connector->out_channel_cb);
|
ssh_callbacks_init(&connector->out_channel_cb);
|
||||||
|
|
||||||
@@ -167,12 +185,14 @@ int ssh_connector_set_out_channel(ssh_connector connector,
|
|||||||
void ssh_connector_set_in_fd(ssh_connector connector, socket_t fd)
|
void ssh_connector_set_in_fd(ssh_connector connector, socket_t fd)
|
||||||
{
|
{
|
||||||
connector->in_fd = fd;
|
connector->in_fd = fd;
|
||||||
|
connector->fd_is_socket = ssh_connector_fd_is_socket(fd);
|
||||||
connector->in_channel = NULL;
|
connector->in_channel = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ssh_connector_set_out_fd(ssh_connector connector, socket_t fd)
|
void ssh_connector_set_out_fd(ssh_connector connector, socket_t fd)
|
||||||
{
|
{
|
||||||
connector->out_fd = fd;
|
connector->out_fd = fd;
|
||||||
|
connector->fd_is_socket = ssh_connector_fd_is_socket(fd);
|
||||||
connector->out_channel = NULL;
|
connector->out_channel = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,9 +243,9 @@ static void ssh_connector_reset_pollevents(ssh_connector connector)
|
|||||||
static void ssh_connector_fd_in_cb(ssh_connector connector)
|
static void ssh_connector_fd_in_cb(ssh_connector connector)
|
||||||
{
|
{
|
||||||
unsigned char buffer[CHUNKSIZE];
|
unsigned char buffer[CHUNKSIZE];
|
||||||
int r;
|
uint32_t toread = CHUNKSIZE;
|
||||||
int toread = CHUNKSIZE;
|
ssize_t r;
|
||||||
int w;
|
ssize_t w;
|
||||||
int total = 0;
|
int total = 0;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@@ -239,7 +259,7 @@ static void ssh_connector_fd_in_cb(ssh_connector connector)
|
|||||||
toread = MIN(size, CHUNKSIZE);
|
toread = MIN(size, CHUNKSIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = read(connector->in_fd, buffer, toread);
|
r = ssh_connector_fd_read(connector, buffer, toread);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
ssh_connector_except(connector, connector->in_fd);
|
ssh_connector_except(connector, connector->in_fd);
|
||||||
return;
|
return;
|
||||||
@@ -277,7 +297,7 @@ static void ssh_connector_fd_in_cb(ssh_connector connector)
|
|||||||
* bytes
|
* bytes
|
||||||
*/
|
*/
|
||||||
while (total != r) {
|
while (total != r) {
|
||||||
w = write(connector->out_fd, buffer + total, r - total);
|
w = ssh_connector_fd_write(connector, buffer + total, r - total);
|
||||||
if (w < 0){
|
if (w < 0){
|
||||||
ssh_connector_except(connector, connector->out_fd);
|
ssh_connector_except(connector, connector->out_fd);
|
||||||
return;
|
return;
|
||||||
@@ -319,7 +339,7 @@ static void ssh_connector_fd_out_cb(ssh_connector connector){
|
|||||||
} else if(r>0) {
|
} else if(r>0) {
|
||||||
/* loop around write in case the write blocks even for CHUNKSIZE bytes */
|
/* loop around write in case the write blocks even for CHUNKSIZE bytes */
|
||||||
while (total != r){
|
while (total != r){
|
||||||
w = write(connector->out_fd, buffer + total, r - total);
|
w = ssh_connector_fd_write(connector, buffer + total, r - total);
|
||||||
if (w < 0){
|
if (w < 0){
|
||||||
ssh_connector_except(connector, connector->out_fd);
|
ssh_connector_except(connector, connector->out_fd);
|
||||||
return;
|
return;
|
||||||
@@ -451,7 +471,7 @@ static int ssh_connector_channel_data_cb(ssh_session session,
|
|||||||
ssh_connector_except_channel(connector, connector->out_channel);
|
ssh_connector_except_channel(connector, connector->out_channel);
|
||||||
}
|
}
|
||||||
} else if (connector->out_fd != SSH_INVALID_SOCKET) {
|
} else if (connector->out_fd != SSH_INVALID_SOCKET) {
|
||||||
w = write(connector->out_fd, data, len);
|
w = ssh_connector_fd_write(connector, data, len);
|
||||||
if (w < 0)
|
if (w < 0)
|
||||||
ssh_connector_except(connector, connector->out_fd);
|
ssh_connector_except(connector, connector->out_fd);
|
||||||
} else {
|
} else {
|
||||||
@@ -634,3 +654,96 @@ int ssh_connector_remove_event(ssh_connector connector) {
|
|||||||
|
|
||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @brief Check the file descriptor to check if it is a Windows socket handle.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static bool ssh_connector_fd_is_socket(socket_t s)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
struct sockaddr_storage ss;
|
||||||
|
int len = sizeof(struct sockaddr_storage);
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = getsockname(s, (struct sockaddr *)&ss, &len);
|
||||||
|
if (rc == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
|
"Error %i in getsockname() for fd %d",
|
||||||
|
WSAGetLastError(),
|
||||||
|
s);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
struct stat sb;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = fstat(s, &sb);
|
||||||
|
if (rc != 0) {
|
||||||
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
|
"error %i in fstat() for fd %d",
|
||||||
|
errno,
|
||||||
|
s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The descriptor is a socket */
|
||||||
|
if (S_ISSOCK(sb.st_mode)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @brief read len bytes from socket into buffer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static ssize_t ssh_connector_fd_read(ssh_connector connector,
|
||||||
|
void *buffer,
|
||||||
|
uint32_t len)
|
||||||
|
{
|
||||||
|
ssize_t nread = -1;
|
||||||
|
|
||||||
|
if (connector->fd_is_socket) {
|
||||||
|
nread = recv(connector->in_fd,buffer, len, 0);
|
||||||
|
} else {
|
||||||
|
nread = read(connector->in_fd,buffer, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nread;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @brief brief writes len bytes from buffer to socket
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static ssize_t ssh_connector_fd_write(ssh_connector connector,
|
||||||
|
const void *buffer,
|
||||||
|
uint32_t len)
|
||||||
|
{
|
||||||
|
ssize_t bwritten = -1;
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
|
#ifdef MSG_NOSIGNAL
|
||||||
|
flags |= MSG_NOSIGNAL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (connector->fd_is_socket) {
|
||||||
|
bwritten = send(connector->out_fd,buffer, len, flags);
|
||||||
|
} else {
|
||||||
|
bwritten = write(connector->out_fd, buffer, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bwritten;
|
||||||
|
}
|
||||||
|
|||||||
2
src/external/chacha.c
vendored
2
src/external/chacha.c
vendored
@@ -10,8 +10,6 @@ Public domain.
|
|||||||
|
|
||||||
#include "libssh/chacha.h"
|
#include "libssh/chacha.h"
|
||||||
|
|
||||||
typedef unsigned int uint32_t;
|
|
||||||
|
|
||||||
typedef struct chacha_ctx chacha_ctx;
|
typedef struct chacha_ctx chacha_ctx;
|
||||||
|
|
||||||
#define U8C(v) (v##U)
|
#define U8C(v) (v##U)
|
||||||
|
|||||||
@@ -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,
|
||||||
@@ -960,8 +961,8 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_client){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (maj_stat == GSS_S_COMPLETE) {
|
if (maj_stat == GSS_S_COMPLETE) {
|
||||||
session->auth.state = SSH_AUTH_STATE_NONE;
|
|
||||||
ssh_gssapi_send_mic(session);
|
ssh_gssapi_send_mic(session);
|
||||||
|
session->auth.state = SSH_AUTH_STATE_GSSAPI_MIC_SENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SSH_PACKET_USED;
|
return SSH_PACKET_USED;
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ int ssh_finalize(void) {
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#if defined(_MSC_VER) && !defined(LIBSSH_STATIC)
|
||||||
/* Library constructor and destructor */
|
/* Library constructor and destructor */
|
||||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL,
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL,
|
||||||
DWORD fdwReason,
|
DWORD fdwReason,
|
||||||
@@ -249,7 +249,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL,
|
|||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
#endif /* _MSC_VER */
|
#endif /* _MSC_VER && !LIBSSH_STATIC */
|
||||||
|
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -131,17 +131,13 @@ static char **ssh_get_knownhost_line(FILE **file, const char *filename,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!tokens[0] || !tokens[1] || !tokens[2]) {
|
if(tokens[0] == NULL || tokens[1] == NULL || tokens[2] == NULL) {
|
||||||
/* it should have at least 3 tokens */
|
/* it should have at least 3 tokens */
|
||||||
tokens_free(tokens);
|
tokens_free(tokens);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
*found_type = tokens[1];
|
*found_type = tokens[1];
|
||||||
if (tokens[3] || tokens[4]) {
|
|
||||||
tokens_free(tokens);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return tokens;
|
return tokens;
|
||||||
}
|
}
|
||||||
|
|||||||
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
|
||||||
|
|
||||||
|
|||||||
@@ -430,6 +430,13 @@ void ssh_message_queue(ssh_session session, ssh_message message){
|
|||||||
}
|
}
|
||||||
if (session->ssh_message_list != NULL) {
|
if (session->ssh_message_list != NULL) {
|
||||||
ssh_list_append(session->ssh_message_list, message);
|
ssh_list_append(session->ssh_message_list, message);
|
||||||
|
} else {
|
||||||
|
/* If the message list couldn't be allocated, the message can't be
|
||||||
|
* enqueued */
|
||||||
|
ssh_message_reply_default(message);
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
ssh_message_free(message);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -697,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;
|
||||||
@@ -723,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) {
|
||||||
|
|||||||
810
src/packet.c
810
src/packet.c
@@ -128,6 +128,798 @@ static ssh_packet_callback default_packet_handlers[]= {
|
|||||||
ssh_packet_channel_failure, // SSH2_MSG_CHANNEL_FAILURE 100
|
ssh_packet_channel_failure, // SSH2_MSG_CHANNEL_FAILURE 100
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** @internal
|
||||||
|
* @brief check if the received packet is allowed for the current session state
|
||||||
|
* @param session current ssh_session
|
||||||
|
* @returns SSH_PACKET_ALLOWED if the packet is allowed; SSH_PACKET_DENIED
|
||||||
|
* if the packet arrived in wrong state; SSH_PACKET_UNKNOWN if the packet type
|
||||||
|
* is unknown
|
||||||
|
*/
|
||||||
|
static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session session)
|
||||||
|
{
|
||||||
|
enum ssh_packet_filter_result_e rc;
|
||||||
|
|
||||||
|
#ifdef DEBUG_PACKET
|
||||||
|
SSH_LOG(SSH_LOG_PACKET, "Filtering packet type %d",
|
||||||
|
session->in_packet.type);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch(session->in_packet.type) {
|
||||||
|
case SSH2_MSG_DISCONNECT: // 1
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - None
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - session->socket->state = SSH_SOCKET_CLOSED
|
||||||
|
* - session->session_state = SSH_SESSION_STATE_ERROR
|
||||||
|
* */
|
||||||
|
|
||||||
|
/* Always allowed */
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_IGNORE: // 2
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - None
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - None
|
||||||
|
* */
|
||||||
|
|
||||||
|
/* Always allowed */
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_UNIMPLEMENTED: // 3
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - None
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - None
|
||||||
|
* */
|
||||||
|
|
||||||
|
/* Always allowed */
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_DEBUG: // 4
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - None
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - None
|
||||||
|
* */
|
||||||
|
|
||||||
|
/* Always allowed */
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_SERVICE_REQUEST: // 5
|
||||||
|
/* Server only */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session->session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||||
|
* or session->session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||||
|
* - session->dh_handshake_state == DH_STATE_FINISHED
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - None
|
||||||
|
* */
|
||||||
|
|
||||||
|
/* If this is a client, reject the message */
|
||||||
|
if (session->client) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((session->session_state != SSH_SESSION_STATE_AUTHENTICATING) &&
|
||||||
|
(session->session_state != SSH_SESSION_STATE_AUTHENTICATED))
|
||||||
|
{
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session->dh_handshake_state != DH_STATE_FINISHED) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_SERVICE_ACCEPT: // 6
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session->session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||||
|
* or session->session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||||
|
* - session->dh_handshake_state == DH_STATE_FINISHED
|
||||||
|
* - session->auth.service_state == SSH_AUTH_SERVICE_SENT
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - auth.service_state = SSH_AUTH_SERVICE_ACCEPTED
|
||||||
|
* */
|
||||||
|
|
||||||
|
if ((session->session_state != SSH_SESSION_STATE_AUTHENTICATING) &&
|
||||||
|
(session->session_state != SSH_SESSION_STATE_AUTHENTICATED))
|
||||||
|
{
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session->dh_handshake_state != DH_STATE_FINISHED) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO check if only auth service can be requested */
|
||||||
|
if (session->auth.service_state != SSH_AUTH_SERVICE_SENT) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_EXT_INFO: // 7
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||||
|
* - dh_handshake_state == DH_STATE_FINISHED
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - None
|
||||||
|
* */
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session->dh_handshake_state != DH_STATE_FINISHED) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_KEXINIT: // 20
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||||
|
* or session_state == SSH_SESSION_STATE_INITIAL_KEX
|
||||||
|
* - dh_handshake_state == DH_STATE_INIT
|
||||||
|
* or dh_handshake_state == DH_STATE_FINISHED (re-exchange)
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - session->dh_handshake_state = DH_STATE_INIT
|
||||||
|
* - session->session_state = SSH_SESSION_STATE_KEXINIT_RECEIVED
|
||||||
|
*
|
||||||
|
* On server:
|
||||||
|
* - session->session_state = SSH_SESSION_STATE_DH
|
||||||
|
* */
|
||||||
|
|
||||||
|
if ((session->session_state != SSH_SESSION_STATE_AUTHENTICATED) &&
|
||||||
|
(session->session_state != SSH_SESSION_STATE_INITIAL_KEX))
|
||||||
|
{
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((session->dh_handshake_state != DH_STATE_INIT) &&
|
||||||
|
(session->dh_handshake_state != DH_STATE_FINISHED))
|
||||||
|
{
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_NEWKEYS: // 21
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_DH
|
||||||
|
* - dh_handshake_state == DH_STATE_NEWKEYS_SENT
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - session->dh_handshake_state = DH_STATE_FINISHED
|
||||||
|
* - session->session_state = SSH_SESSION_STATE_AUTHENTICATING
|
||||||
|
* if session->flags & SSH_SESSION_FLAG_AUTHENTICATED
|
||||||
|
* - session->session_state = SSH_SESSION_STATE_AUTHENTICATED
|
||||||
|
* */
|
||||||
|
|
||||||
|
/* If DH has not been started, reject message */
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_DH) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only allowed if dh_handshake_state is in NEWKEYS_SENT state */
|
||||||
|
if (session->dh_handshake_state != DH_STATE_NEWKEYS_SENT) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_KEXDH_INIT: // 30
|
||||||
|
// SSH2_MSG_KEX_ECDH_INIT: // 30
|
||||||
|
// SSH2_MSG_ECMQV_INIT: // 30
|
||||||
|
// SSH2_MSG_KEX_DH_GEX_REQUEST_OLD: // 30
|
||||||
|
|
||||||
|
/* Server only */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_DH
|
||||||
|
* - dh_handshake_state == DH_STATE_INIT
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - session->dh_handshake_state = DH_STATE_INIT_SENT
|
||||||
|
* then calls dh_handshake_server which triggers:
|
||||||
|
* - session->dh_handhsake_state = DH_STATE_NEWKEYS_SENT
|
||||||
|
* */
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_DH) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only allowed if dh_handshake_state is in initial state */
|
||||||
|
if (session->dh_handshake_state != DH_STATE_INIT) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_KEXDH_REPLY: // 31
|
||||||
|
// SSH2_MSG_KEX_ECDH_REPLY: // 31
|
||||||
|
// SSH2_MSG_ECMQV_REPLY: // 31
|
||||||
|
// SSH2_MSG_KEX_DH_GEX_GROUP: // 31
|
||||||
|
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_DH
|
||||||
|
* - dh_handshake_state == DH_STATE_INIT_SENT
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - session->dh_handhsake_state = DH_STATE_NEWKEYS_SENT
|
||||||
|
* */
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_DH) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session->dh_handshake_state != DH_STATE_INIT_SENT) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_KEX_DH_GEX_INIT: // 32
|
||||||
|
/* TODO Not filtered */
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_KEX_DH_GEX_REPLY: // 33
|
||||||
|
/* TODO Not filtered */
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_KEX_DH_GEX_REQUEST: // 34
|
||||||
|
/* TODO Not filtered */
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_USERAUTH_REQUEST: // 50
|
||||||
|
/* Server only */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||||
|
* - dh_hanshake_state == DH_STATE_FINISHED
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - if authentication was successful:
|
||||||
|
* - session_state = SSH_SESSION_STATE_AUTHENTICATED
|
||||||
|
* */
|
||||||
|
|
||||||
|
/* If this is a client, reject the message */
|
||||||
|
if (session->client) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session->dh_handshake_state != DH_STATE_FINISHED) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_USERAUTH_FAILURE: // 51
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||||
|
* - dh_hanshake_state == DH_STATE_FINISHED
|
||||||
|
* - session->auth.state == SSH_AUTH_STATE_KBDINT_SENT
|
||||||
|
* or session->auth.state == SSH_AUTH_STATE_PUBKEY_OFFER_SENT
|
||||||
|
* or session->auth.state == SSH_AUTH_STATE_PUBKEY_AUTH_SENT
|
||||||
|
* or session->auth.state == SSH_AUTH_STATE_PASSWORD_AUTH_SENT
|
||||||
|
* or session->auth.state == SSH_AUTH_STATE_GSSAPI_MIC_SENT
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - if unpacking failed:
|
||||||
|
* - session->auth.state = SSH_AUTH_ERROR
|
||||||
|
* - if failure was partial:
|
||||||
|
* - session->auth.state = SSH_AUTH_PARTIAL
|
||||||
|
* - else:
|
||||||
|
* - session->auth.state = SSH_AUTH_STATE_FAILED
|
||||||
|
* */
|
||||||
|
|
||||||
|
/* If this is a server, reject the message */
|
||||||
|
if (session->server) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session->dh_handshake_state != DH_STATE_FINISHED) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_USERAUTH_SUCCESS: // 52
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||||
|
* - dh_hanshake_state == DH_STATE_FINISHED
|
||||||
|
* - session->auth.state == SSH_AUTH_STATE_KBDINT_SENT
|
||||||
|
* or session->auth.state == SSH_AUTH_STATE_PUBKEY_AUTH_SENT
|
||||||
|
* or session->auth.state == SSH_AUTH_STATE_PASSWORD_AUTH_SENT
|
||||||
|
* or session->auth.state == SSH_AUTH_STATE_GSSAPI_MIC_SENT
|
||||||
|
* or session->auth.state == SSH_AUTH_STATE_AUTH_NONE_SENT
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - session->auth.state = SSH_AUTH_STATE_SUCCESS
|
||||||
|
* - session->session_state = SSH_SESSION_STATE_AUTHENTICATED
|
||||||
|
* - session->flags |= SSH_SESSION_FLAG_AUTHENTICATED
|
||||||
|
* - sessions->auth.current_method = SSH_AUTH_METHOD_UNKNOWN
|
||||||
|
* */
|
||||||
|
|
||||||
|
/* If this is a server, reject the message */
|
||||||
|
if (session->server) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session->dh_handshake_state != DH_STATE_FINISHED) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((session->auth.state != SSH_AUTH_STATE_KBDINT_SENT) &&
|
||||||
|
(session->auth.state != SSH_AUTH_STATE_PUBKEY_AUTH_SENT) &&
|
||||||
|
(session->auth.state != SSH_AUTH_STATE_PASSWORD_AUTH_SENT) &&
|
||||||
|
(session->auth.state != SSH_AUTH_STATE_GSSAPI_MIC_SENT) &&
|
||||||
|
(session->auth.state != SSH_AUTH_STATE_AUTH_NONE_SENT))
|
||||||
|
{
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_USERAUTH_BANNER: // 53
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - None
|
||||||
|
* */
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_USERAUTH_PK_OK: // 60
|
||||||
|
// SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ: // 60
|
||||||
|
// SSH2_MSG_USERAUTH_INFO_REQUEST: // 60
|
||||||
|
// SSH2_MSG_USERAUTH_GSSAPI_RESPONSE: // 60
|
||||||
|
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||||
|
* - session->auth.state == SSH_AUTH_STATE_KBDINT_SENT
|
||||||
|
* or
|
||||||
|
* session->auth.state == SSH_AUTH_STATE_GSSAPI_REQUEST_SENT
|
||||||
|
* or
|
||||||
|
* session->auth.state == SSH_AUTH_STATE_PUBKEY_OFFER_SENT
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* Depending on the current state, the message is treated
|
||||||
|
* differently:
|
||||||
|
* - session->auth.state == SSH_AUTH_STATE_KBDINT_SENT
|
||||||
|
* - session->auth.state = SSH_AUTH_STATE_INFO
|
||||||
|
* - session->auth.state == SSH_AUTH_STATE_GSSAPI_REQUEST_SENT
|
||||||
|
* - session->auth.state = SSH_AUTH_STATE_GSSAPI_TOKEN
|
||||||
|
* - session->auth.state == SSH_AUTH_STATE_PUBKEY_OFFER_SENT
|
||||||
|
* - session->auth.state = SSH_AUTH_STATE_PK_OK
|
||||||
|
* */
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((session->auth.state != SSH_AUTH_STATE_KBDINT_SENT) &&
|
||||||
|
(session->auth.state != SSH_AUTH_STATE_PUBKEY_OFFER_SENT) &&
|
||||||
|
(session->auth.state != SSH_AUTH_STATE_GSSAPI_REQUEST_SENT))
|
||||||
|
{
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_USERAUTH_INFO_RESPONSE: // 61
|
||||||
|
// SSH2_MSG_USERAUTH_GSSAPI_TOKEN: // 61
|
||||||
|
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||||
|
* - session_state->auth.state == SSH_SESSION_STATE_GSSAPI_TOKEN
|
||||||
|
* or
|
||||||
|
* session_state->auth.state == SSH_SESSION_STATE_INFO
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - None
|
||||||
|
* */
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((session->auth.state != SSH_AUTH_STATE_INFO) &&
|
||||||
|
(session->auth.state != SSH_AUTH_STATE_GSSAPI_TOKEN))
|
||||||
|
{
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE: // 63
|
||||||
|
/* TODO Not filtered */
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_USERAUTH_GSSAPI_ERROR: // 64
|
||||||
|
/* TODO Not filtered */
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_USERAUTH_GSSAPI_ERRTOK: // 65
|
||||||
|
/* TODO Not filtered */
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_USERAUTH_GSSAPI_MIC: // 66
|
||||||
|
/* Server only */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||||
|
* - session->gssapi->state == SSH_GSSAPI_STATE_RCV_MIC
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* Depending on the result of the verification, the states are
|
||||||
|
* changed:
|
||||||
|
* - SSH_AUTH_SUCCESS:
|
||||||
|
* - session->session_state = SSH_SESSION_STATE_AUTHENTICATED
|
||||||
|
* - session->flags != SSH_SESSION_FLAG_AUTHENTICATED
|
||||||
|
* - SSH_AUTH_PARTIAL:
|
||||||
|
* - None
|
||||||
|
* - any other case:
|
||||||
|
* - None
|
||||||
|
* */
|
||||||
|
|
||||||
|
/* If this is a client, reject the message */
|
||||||
|
if (session->client) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session->dh_handshake_state != DH_STATE_FINISHED) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_GLOBAL_REQUEST: // 80
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - None
|
||||||
|
* */
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_REQUEST_SUCCESS: // 81
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||||
|
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_ACCEPTED
|
||||||
|
* */
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_REQUEST_FAILURE: // 82
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||||
|
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_DENIED
|
||||||
|
* */
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_CHANNEL_OPEN: // 90
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - None
|
||||||
|
* */
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: // 91
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - channel->state = SSH_CHANNEL_STATE_OPEN
|
||||||
|
* - channel->flags &= ~SSH_CHANNEL_FLAG_NOT_BOUND
|
||||||
|
* */
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_CHANNEL_OPEN_FAILURE: // 92
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - channel->state = SSH_CHANNEL_STATE_OPEN_DENIED
|
||||||
|
* */
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_CHANNEL_WINDOW_ADJUST: // 93
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - None
|
||||||
|
* */
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_CHANNEL_DATA: // 94
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - None
|
||||||
|
* */
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_CHANNEL_EXTENDED_DATA: // 95
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - None
|
||||||
|
* */
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_CHANNEL_EOF: // 96
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - None
|
||||||
|
* */
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_CHANNEL_CLOSE: // 97
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - channel->state = SSH_CHANNEL_STATE_CLOSED
|
||||||
|
* - channel->flags |= SSH_CHANNEL_FLAG_CLOSED_REMOTE
|
||||||
|
* */
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_CHANNEL_REQUEST: // 98
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - Depends on the request
|
||||||
|
* */
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_CHANNEL_SUCCESS: // 99
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||||
|
* - channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED
|
||||||
|
* */
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_CHANNEL_FAILURE: // 100
|
||||||
|
/*
|
||||||
|
* States required:
|
||||||
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||||
|
* - channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||||
|
*
|
||||||
|
* Transitions:
|
||||||
|
* - channel->request_state = SSH_CHANNEL_REQ_STATE_DENIED
|
||||||
|
* */
|
||||||
|
|
||||||
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SSH_PACKET_ALLOWED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Unknown message, do not filter */
|
||||||
|
rc = SSH_PACKET_UNKNOWN;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
#ifdef DEBUG_PACKET
|
||||||
|
if (rc == SSH_PACKET_DENIED) {
|
||||||
|
SSH_LOG(SSH_LOG_PACKET, "REJECTED packet type %d: ",
|
||||||
|
session->in_packet.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == SSH_PACKET_UNKNOWN) {
|
||||||
|
SSH_LOG(SSH_LOG_PACKET, "UNKNOWN packet type %d",
|
||||||
|
session->in_packet.type);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/* in nonblocking mode, socket_read will read as much as it can, and return */
|
/* in nonblocking mode, socket_read will read as much as it can, and return */
|
||||||
/* SSH_OK if it has read at least len bytes, otherwise, SSH_AGAIN. */
|
/* SSH_OK if it has read at least len bytes, otherwise, SSH_AGAIN. */
|
||||||
/* in blocking mode, it will read at least len bytes and will block until it's ok. */
|
/* in blocking mode, it will read at least len bytes and will block until it's ok. */
|
||||||
@@ -158,6 +950,7 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
|||||||
uint32_t packet_len, compsize, payloadsize;
|
uint32_t packet_len, compsize, payloadsize;
|
||||||
uint8_t padding;
|
uint8_t padding;
|
||||||
size_t processed = 0; /* number of byte processed from the callback */
|
size_t processed = 0; /* number of byte processed from the callback */
|
||||||
|
enum ssh_packet_filter_result_e filter_result;
|
||||||
|
|
||||||
if(session->current_crypto != NULL) {
|
if(session->current_crypto != NULL) {
|
||||||
current_macsize = hmac_digest_len(session->current_crypto->in_hmac);
|
current_macsize = hmac_digest_len(session->current_crypto->in_hmac);
|
||||||
@@ -345,8 +1138,21 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
|||||||
"packet: read type %hhd [len=%d,padding=%hhd,comp=%d,payload=%d]",
|
"packet: read type %hhd [len=%d,padding=%hhd,comp=%d,payload=%d]",
|
||||||
session->in_packet.type, packet_len, padding, compsize, payloadsize);
|
session->in_packet.type, packet_len, padding, compsize, payloadsize);
|
||||||
|
|
||||||
/* Execute callbacks */
|
/* Check if the packet is expected */
|
||||||
ssh_packet_process(session, session->in_packet.type);
|
filter_result = ssh_packet_incoming_filter(session);
|
||||||
|
|
||||||
|
switch(filter_result) {
|
||||||
|
case SSH_PACKET_ALLOWED:
|
||||||
|
/* Execute callbacks */
|
||||||
|
ssh_packet_process(session, session->in_packet.type);
|
||||||
|
break;
|
||||||
|
case SSH_PACKET_DENIED:
|
||||||
|
goto error;
|
||||||
|
case SSH_PACKET_UNKNOWN:
|
||||||
|
ssh_packet_send_unimplemented(session, session->recv_seq - 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
session->packet_state = PACKET_STATE_INIT;
|
session->packet_state = PACKET_STATE_INIT;
|
||||||
if (processed < receivedlen) {
|
if (processed < receivedlen) {
|
||||||
/* Handle a potential packet left in socket buffer */
|
/* Handle a potential packet left in socket buffer */
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
21
src/sftp.c
21
src/sftp.c
@@ -211,10 +211,31 @@ sftp_session sftp_server_new(ssh_session session, ssh_channel chan){
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sftp->read_packet = calloc(1, sizeof(struct sftp_packet_struct));
|
||||||
|
if (sftp->read_packet == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
sftp->read_packet->payload = ssh_buffer_new();
|
||||||
|
if (sftp->read_packet->payload == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
sftp->session = session;
|
sftp->session = session;
|
||||||
sftp->channel = chan;
|
sftp->channel = chan;
|
||||||
|
|
||||||
return sftp;
|
return sftp;
|
||||||
|
|
||||||
|
error:
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
if (sftp->read_packet != NULL) {
|
||||||
|
if (sftp->read_packet->payload != NULL) {
|
||||||
|
ssh_buffer_free(sftp->read_packet->payload);
|
||||||
|
}
|
||||||
|
SAFE_FREE(sftp->read_packet);
|
||||||
|
}
|
||||||
|
SAFE_FREE(sftp);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sftp_server_init(sftp_session sftp){
|
int sftp_server_init(sftp_session sftp){
|
||||||
|
|||||||
@@ -232,8 +232,6 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
sftp_packet_free(packet);
|
|
||||||
|
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
492
src/socket.c
492
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,15 +86,17 @@ 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;
|
||||||
|
|
||||||
static int ssh_socket_unbuffered_read(ssh_socket s, void *buffer, uint32_t len);
|
static ssize_t ssh_socket_unbuffered_read(ssh_socket s,
|
||||||
static int ssh_socket_unbuffered_write(ssh_socket s, const void *buffer,
|
void *buffer,
|
||||||
uint32_t len);
|
uint32_t len);
|
||||||
|
static ssize_t ssh_socket_unbuffered_write(ssh_socket s,
|
||||||
|
const void *buffer,
|
||||||
|
uint32_t len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \internal
|
* \internal
|
||||||
@@ -146,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;
|
||||||
@@ -167,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;
|
||||||
}
|
}
|
||||||
@@ -178,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);
|
||||||
@@ -187,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,13 +215,18 @@ void ssh_socket_set_callbacks(ssh_socket s, ssh_socket_callbacks callbacks){
|
|||||||
* @return 0 on success, < 0 when the poll object has been removed
|
* @return 0 on success, < 0 when the poll object has been removed
|
||||||
* from its poll context.
|
* from its poll context.
|
||||||
*/
|
*/
|
||||||
int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd,
|
int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p,
|
||||||
int revents, void *v_s) {
|
socket_t fd,
|
||||||
|
int revents,
|
||||||
|
void *v_s)
|
||||||
|
{
|
||||||
ssh_socket s = (ssh_socket)v_s;
|
ssh_socket s = (ssh_socket)v_s;
|
||||||
char buffer[MAX_BUF_SIZE];
|
char buffer[MAX_BUF_SIZE];
|
||||||
int r;
|
ssize_t nread;
|
||||||
|
int rc;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
socklen_t errlen = sizeof(err);
|
socklen_t errlen = sizeof(err);
|
||||||
|
|
||||||
/* Do not do anything if this socket was already closed */
|
/* Do not do anything if this socket was already closed */
|
||||||
if (!ssh_socket_is_open(s)) {
|
if (!ssh_socket_is_open(s)) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -236,16 +240,18 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd,
|
|||||||
/* Check if we are in a connecting state */
|
/* Check if we are in a connecting state */
|
||||||
if (s->state == SSH_SOCKET_CONNECTING) {
|
if (s->state == SSH_SOCKET_CONNECTING) {
|
||||||
s->state = SSH_SOCKET_ERROR;
|
s->state = SSH_SOCKET_ERROR;
|
||||||
r = getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *)&err, &errlen);
|
rc = getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *)&err, &errlen);
|
||||||
if (r < 0) {
|
if (rc < 0) {
|
||||||
err = errno;
|
err = errno;
|
||||||
}
|
}
|
||||||
s->last_errno = err;
|
s->last_errno = err;
|
||||||
ssh_socket_close(s);
|
ssh_socket_close(s);
|
||||||
if (s->callbacks && s->callbacks->connected) {
|
if (s->callbacks != NULL && s->callbacks->connected != NULL) {
|
||||||
s->callbacks->connected(SSH_SOCKET_CONNECTED_ERROR, err,
|
s->callbacks->connected(SSH_SOCKET_CONNECTED_ERROR,
|
||||||
|
err,
|
||||||
s->callbacks->userdata);
|
s->callbacks->userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* Then we are in a more standard kind of error */
|
/* Then we are in a more standard kind of error */
|
||||||
@@ -254,56 +260,62 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd,
|
|||||||
}
|
}
|
||||||
if ((revents & POLLIN) && s->state == SSH_SOCKET_CONNECTED) {
|
if ((revents & POLLIN) && s->state == SSH_SOCKET_CONNECTED) {
|
||||||
s->read_wontblock = 1;
|
s->read_wontblock = 1;
|
||||||
r = ssh_socket_unbuffered_read(s, buffer, sizeof(buffer));
|
nread = ssh_socket_unbuffered_read(s, buffer, sizeof(buffer));
|
||||||
if (r < 0) {
|
if (nread < 0) {
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
ssh_poll_remove_events(p, POLLIN);
|
ssh_poll_remove_events(p, POLLIN);
|
||||||
}
|
}
|
||||||
if (s->callbacks && s->callbacks->exception) {
|
|
||||||
|
if (s->callbacks != NULL && s->callbacks->exception != NULL) {
|
||||||
s->callbacks->exception(SSH_SOCKET_EXCEPTION_ERROR,
|
s->callbacks->exception(SSH_SOCKET_EXCEPTION_ERROR,
|
||||||
s->last_errno, s->callbacks->userdata);
|
s->last_errno,
|
||||||
|
s->callbacks->userdata);
|
||||||
|
|
||||||
/* p may have been freed, so don't use it
|
/* p may have been freed, so don't use it
|
||||||
* anymore in this function */
|
* anymore in this function */
|
||||||
p = NULL;
|
p = NULL;
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (r == 0) {
|
if (nread == 0) {
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
ssh_poll_remove_events(p, POLLIN);
|
ssh_poll_remove_events(p, POLLIN);
|
||||||
}
|
}
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
ssh_poll_remove_events(p, POLLIN);
|
ssh_poll_remove_events(p, POLLIN);
|
||||||
}
|
}
|
||||||
if (s->callbacks && s->callbacks->exception) {
|
if (s->callbacks != NULL && s->callbacks->exception != NULL) {
|
||||||
s->callbacks->exception(SSH_SOCKET_EXCEPTION_EOF,
|
s->callbacks->exception(SSH_SOCKET_EXCEPTION_EOF,
|
||||||
0, s->callbacks->userdata);
|
0,
|
||||||
|
s->callbacks->userdata);
|
||||||
|
|
||||||
/* p may have been freed, so don't use it
|
/* p may have been freed, so don't use it
|
||||||
* anymore in this function */
|
* anymore in this function */
|
||||||
p = NULL;
|
p = NULL;
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (r > 0) {
|
|
||||||
if (s->session->socket_counter != NULL) {
|
if (s->session->socket_counter != NULL) {
|
||||||
s->session->socket_counter->in_bytes += r;
|
s->session->socket_counter->in_bytes += nread;
|
||||||
}
|
}
|
||||||
/* Bufferize the data and then call the callback */
|
|
||||||
r = ssh_buffer_add_data(s->in_buffer, buffer, r);
|
/* Bufferize the data and then call the callback */
|
||||||
if (r < 0) {
|
rc = ssh_buffer_add_data(s->in_buffer, buffer, nread);
|
||||||
return -1;
|
if (rc < 0) {
|
||||||
}
|
return -1;
|
||||||
if (s->callbacks && s->callbacks->data) {
|
}
|
||||||
do {
|
if (s->callbacks != NULL && s->callbacks->data != NULL) {
|
||||||
r = s->callbacks->data(ssh_buffer_get(s->in_buffer),
|
do {
|
||||||
ssh_buffer_get_len(s->in_buffer),
|
nread = s->callbacks->data(ssh_buffer_get(s->in_buffer),
|
||||||
s->callbacks->userdata);
|
ssh_buffer_get_len(s->in_buffer),
|
||||||
ssh_buffer_pass_bytes(s->in_buffer, r);
|
s->callbacks->userdata);
|
||||||
} while ((r > 0) && (s->state == SSH_SOCKET_CONNECTED));
|
ssh_buffer_pass_bytes(s->in_buffer, nread);
|
||||||
/* p may have been freed, so don't use it
|
} while ((nread > 0) && (s->state == SSH_SOCKET_CONNECTED));
|
||||||
* anymore in this function */
|
|
||||||
p = NULL;
|
/* p may have been freed, so don't use it
|
||||||
}
|
* anymore in this function */
|
||||||
|
p = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -311,6 +323,8 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd,
|
|||||||
#else
|
#else
|
||||||
if (revents & POLLOUT) {
|
if (revents & POLLOUT) {
|
||||||
#endif
|
#endif
|
||||||
|
uint32_t len;
|
||||||
|
|
||||||
/* First, POLLOUT is a sign we may be connected */
|
/* First, POLLOUT is a sign we may be connected */
|
||||||
if (s->state == SSH_SOCKET_CONNECTING) {
|
if (s->state == SSH_SOCKET_CONNECTING) {
|
||||||
SSH_LOG(SSH_LOG_PACKET, "Received POLLOUT in connecting state");
|
SSH_LOG(SSH_LOG_PACKET, "Received POLLOUT in connecting state");
|
||||||
@@ -318,26 +332,32 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd,
|
|||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
ssh_poll_set_events(p, POLLOUT | POLLIN);
|
ssh_poll_set_events(p, POLLOUT | POLLIN);
|
||||||
}
|
}
|
||||||
r = ssh_socket_set_blocking(ssh_socket_get_fd_in(s));
|
|
||||||
if (r < 0) {
|
rc = ssh_socket_set_blocking(ssh_socket_get_fd(s));
|
||||||
|
if (rc < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (s->callbacks && s->callbacks->connected) {
|
|
||||||
s->callbacks->connected(SSH_SOCKET_CONNECTED_OK, 0,
|
if (s->callbacks != NULL && s->callbacks->connected != NULL) {
|
||||||
|
s->callbacks->connected(SSH_SOCKET_CONNECTED_OK,
|
||||||
|
0,
|
||||||
s->callbacks->userdata);
|
s->callbacks->userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* So, we can write data */
|
/* So, we can write data */
|
||||||
s->write_wontblock=1;
|
s->write_wontblock = 1;
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
ssh_poll_remove_events(p, POLLOUT);
|
ssh_poll_remove_events(p, POLLOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If buffered data is pending, write it */
|
/* If buffered data is pending, write it */
|
||||||
if (ssh_buffer_get_len(s->out_buffer) > 0) {
|
len = ssh_buffer_get_len(s->out_buffer);
|
||||||
|
if (len > 0) {
|
||||||
ssh_socket_nonblocking_flush(s);
|
ssh_socket_nonblocking_flush(s);
|
||||||
} else if (s->callbacks && s->callbacks->controlflow) {
|
} else if (s->callbacks != NULL && s->callbacks->controlflow != NULL) {
|
||||||
/* Otherwise advertise the upper level that write can be done */
|
/* Otherwise advertise the upper level that write can be done */
|
||||||
SSH_LOG(SSH_LOG_TRACE,"sending control flow event");
|
SSH_LOG(SSH_LOG_TRACE,"sending control flow event");
|
||||||
s->callbacks->controlflow(SSH_SOCKET_FLOW_WRITEWONTBLOCK,
|
s->callbacks->controlflow(SSH_SOCKET_FLOW_WRITEWONTBLOCK,
|
||||||
@@ -345,36 +365,27 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd,
|
|||||||
}
|
}
|
||||||
/* 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 (s->poll_in == NULL || s->poll_out == NULL) ? -1 : 0;
|
/* Return -1 if the poll handler disappeared */
|
||||||
|
if (s->poll_handle == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @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
|
||||||
@@ -431,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;
|
||||||
@@ -466,128 +467,116 @@ 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
|
||||||
* \brief read len bytes from socket into buffer
|
* \brief read len bytes from socket into buffer
|
||||||
*/
|
*/
|
||||||
static int ssh_socket_unbuffered_read(ssh_socket s, void *buffer, uint32_t len) {
|
static ssize_t ssh_socket_unbuffered_read(ssh_socket s,
|
||||||
int rc = -1;
|
void *buffer,
|
||||||
|
uint32_t len)
|
||||||
|
{
|
||||||
|
ssize_t rc = -1;
|
||||||
|
|
||||||
if (s->data_except) {
|
if (s->data_except) {
|
||||||
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();
|
||||||
#else
|
#else
|
||||||
s->last_errno = errno;
|
s->last_errno = errno;
|
||||||
#endif
|
#endif
|
||||||
s->read_wontblock = 0;
|
s->read_wontblock = 0;
|
||||||
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
s->data_except = 1;
|
s->data_except = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \internal
|
/** \internal
|
||||||
* \brief writes len bytes from buffer to socket
|
* \brief writes len bytes from buffer to socket
|
||||||
*/
|
*/
|
||||||
static int ssh_socket_unbuffered_write(ssh_socket s, const void *buffer,
|
static ssize_t ssh_socket_unbuffered_write(ssh_socket s,
|
||||||
uint32_t len) {
|
const void *buffer,
|
||||||
int w = -1;
|
uint32_t len)
|
||||||
|
{
|
||||||
|
ssize_t w = -1;
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
if (s->data_except) {
|
#ifdef MSG_NOSIGNAL
|
||||||
return -1;
|
flags |= MSG_NOSIGNAL;
|
||||||
}
|
|
||||||
if (s->fd_is_socket)
|
|
||||||
w = send(s->fd_out,buffer, len, 0);
|
|
||||||
else
|
|
||||||
w = write(s->fd_out, buffer, len);
|
|
||||||
#ifdef _WIN32
|
|
||||||
s->last_errno = WSAGetLastError();
|
|
||||||
#else
|
|
||||||
s->last_errno = errno;
|
|
||||||
#endif
|
#endif
|
||||||
s->write_wontblock = 0;
|
|
||||||
/* Reactive the POLLOUT detector in the poll multiplexer system */
|
|
||||||
if(s->poll_out){
|
|
||||||
SSH_LOG(SSH_LOG_PACKET, "Enabling POLLOUT for socket");
|
|
||||||
ssh_poll_set_events(s->poll_out,ssh_poll_get_events(s->poll_out) | POLLOUT);
|
|
||||||
}
|
|
||||||
if (w < 0) {
|
|
||||||
s->data_except = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return w;
|
if (s->data_except) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->fd_is_socket) {
|
||||||
|
w = send(s->fd, buffer, len, flags);
|
||||||
|
} else {
|
||||||
|
w = write(s->fd, buffer, len);
|
||||||
|
}
|
||||||
|
#ifdef _WIN32
|
||||||
|
s->last_errno = WSAGetLastError();
|
||||||
|
#else
|
||||||
|
s->last_errno = errno;
|
||||||
|
#endif
|
||||||
|
s->write_wontblock = 0;
|
||||||
|
/* Reactive the POLLOUT detector in the poll multiplexer system */
|
||||||
|
if (s->poll_handle) {
|
||||||
|
SSH_LOG(SSH_LOG_PACKET, "Enabling POLLOUT for socket");
|
||||||
|
ssh_poll_set_events(s->poll_handle,ssh_poll_get_events(s->poll_handle) | POLLOUT);
|
||||||
|
}
|
||||||
|
if (w < 0) {
|
||||||
|
s->data_except = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \internal
|
/** \internal
|
||||||
* \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
|
||||||
@@ -595,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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -636,67 +619,78 @@ int ssh_socket_write(ssh_socket s, const void *buffer, int len) {
|
|||||||
* \brief starts a nonblocking flush of the output buffer
|
* \brief starts a nonblocking flush of the output buffer
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int ssh_socket_nonblocking_flush(ssh_socket s) {
|
int ssh_socket_nonblocking_flush(ssh_socket s)
|
||||||
ssh_session session = s->session;
|
{
|
||||||
uint32_t len;
|
ssh_session session = s->session;
|
||||||
int w;
|
uint32_t len;
|
||||||
|
|
||||||
if (!ssh_socket_is_open(s)) {
|
if (!ssh_socket_is_open(s)) {
|
||||||
session->alive = 0;
|
session->alive = 0;
|
||||||
if(s->callbacks && s->callbacks->exception){
|
if (s->callbacks && s->callbacks->exception) {
|
||||||
s->callbacks->exception(
|
s->callbacks->exception(SSH_SOCKET_EXCEPTION_ERROR,
|
||||||
SSH_SOCKET_EXCEPTION_ERROR,
|
s->last_errno,
|
||||||
s->last_errno,s->callbacks->userdata);
|
s->callbacks->userdata);
|
||||||
}else{
|
} else {
|
||||||
ssh_set_error(session, SSH_FATAL,
|
ssh_set_error(session,
|
||||||
"Writing packet: error on socket (or connection closed): %s",
|
SSH_FATAL,
|
||||||
strerror(s->last_errno));
|
"Writing packet: error on socket (or connection "
|
||||||
|
"closed): %s",
|
||||||
|
strerror(s->last_errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SSH_ERROR;
|
len = ssh_buffer_get_len(s->out_buffer);
|
||||||
}
|
if (!s->write_wontblock && s->poll_handle && len > 0) {
|
||||||
|
/* force the poll system to catch pollout events */
|
||||||
|
ssh_poll_add_events(s->poll_handle, POLLOUT);
|
||||||
|
|
||||||
len = ssh_buffer_get_len(s->out_buffer);
|
return SSH_AGAIN;
|
||||||
if (!s->write_wontblock && s->poll_out && len > 0) {
|
|
||||||
/* force the poll system to catch pollout events */
|
|
||||||
ssh_poll_add_events(s->poll_out, POLLOUT);
|
|
||||||
|
|
||||||
return SSH_AGAIN;
|
|
||||||
}
|
|
||||||
if (s->write_wontblock && len > 0) {
|
|
||||||
w = ssh_socket_unbuffered_write(s, ssh_buffer_get(s->out_buffer), len);
|
|
||||||
if (w < 0) {
|
|
||||||
session->alive = 0;
|
|
||||||
ssh_socket_close(s);
|
|
||||||
|
|
||||||
if(s->callbacks && s->callbacks->exception){
|
|
||||||
s->callbacks->exception(
|
|
||||||
SSH_SOCKET_EXCEPTION_ERROR,
|
|
||||||
s->last_errno,s->callbacks->userdata);
|
|
||||||
}else{
|
|
||||||
ssh_set_error(session, SSH_FATAL,
|
|
||||||
"Writing packet: error on socket (or connection closed): %s",
|
|
||||||
strerror(s->last_errno));
|
|
||||||
}
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
}
|
||||||
ssh_buffer_pass_bytes(s->out_buffer, w);
|
|
||||||
if (s->session->socket_counter != NULL) {
|
if (s->write_wontblock && len > 0) {
|
||||||
s->session->socket_counter->out_bytes += w;
|
ssize_t bwritten;
|
||||||
|
|
||||||
|
bwritten = ssh_socket_unbuffered_write(s,
|
||||||
|
ssh_buffer_get(s->out_buffer),
|
||||||
|
len);
|
||||||
|
if (bwritten < 0) {
|
||||||
|
session->alive = 0;
|
||||||
|
ssh_socket_close(s);
|
||||||
|
|
||||||
|
if (s->callbacks && s->callbacks->exception) {
|
||||||
|
s->callbacks->exception(SSH_SOCKET_EXCEPTION_ERROR,
|
||||||
|
s->last_errno,
|
||||||
|
s->callbacks->userdata);
|
||||||
|
} else {
|
||||||
|
ssh_set_error(session,
|
||||||
|
SSH_FATAL,
|
||||||
|
"Writing packet: error on socket (or connection "
|
||||||
|
"closed): %s",
|
||||||
|
strerror(s->last_errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_buffer_pass_bytes(s->out_buffer, bwritten);
|
||||||
|
if (s->session->socket_counter != NULL) {
|
||||||
|
s->session->socket_counter->out_bytes += bwritten;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* all data written */
|
/* all data written */
|
||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ssh_socket_set_write_wontblock(ssh_socket s) {
|
void ssh_socket_set_write_wontblock(ssh_socket s) {
|
||||||
@@ -751,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;
|
||||||
@@ -844,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;
|
||||||
}
|
}
|
||||||
@@ -864,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)
|
||||||
|
|||||||
@@ -534,8 +534,8 @@ static void torture_auth_cert(void **state) {
|
|||||||
rc = ssh_userauth_publickey(session, NULL, privkey);
|
rc = ssh_userauth_publickey(session, NULL, privkey);
|
||||||
assert_int_equal(rc, SSH_AUTH_SUCCESS);
|
assert_int_equal(rc, SSH_AUTH_SUCCESS);
|
||||||
|
|
||||||
ssh_key_free(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
ssh_key_free(cert);
|
SSH_KEY_FREE(cert);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_auth_agent_cert(void **state) {
|
static void torture_auth_agent_cert(void **state) {
|
||||||
@@ -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
|
||||||
@@ -35,6 +35,9 @@ target_compile_options(torture_knownhosts_parsing PRIVATE ${DEFAULT_C_COMPILE_FL
|
|||||||
add_cmocka_test(torture_hashes torture_hashes.c ${TEST_TARGET_LIBRARIES})
|
add_cmocka_test(torture_hashes torture_hashes.c ${TEST_TARGET_LIBRARIES})
|
||||||
target_compile_options(torture_hashes PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
target_compile_options(torture_hashes PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||||
|
|
||||||
|
add_cmocka_test(torture_packet_filter torture_packet_filter.c ${TORTURE_LIBRARY})
|
||||||
|
target_compile_options(torture_packet_filter PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||||
|
|
||||||
if (CMAKE_USE_PTHREADS_INIT)
|
if (CMAKE_USE_PTHREADS_INIT)
|
||||||
add_cmocka_test(torture_rand torture_rand.c ${TEST_TARGET_LIBRARIES})
|
add_cmocka_test(torture_rand torture_rand.c ${TEST_TARGET_LIBRARIES})
|
||||||
target_compile_options(torture_rand PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
target_compile_options(torture_rand PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ static int setup(void **state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int teardown(void **state) {
|
static int teardown(void **state) {
|
||||||
ssh_buffer_free(*state);
|
SSH_BUFFER_FREE(*state);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -125,9 +125,9 @@ static void torture_ssh_buffer_get_ssh_string(void **state) {
|
|||||||
for(l=0;l<k;++l){
|
for(l=0;l<k;++l){
|
||||||
ssh_string str = ssh_buffer_get_ssh_string(buffer);
|
ssh_string str = ssh_buffer_get_ssh_string(buffer);
|
||||||
assert_null(str);
|
assert_null(str);
|
||||||
ssh_string_free(str);
|
SSH_STRING_FREE(str);
|
||||||
}
|
}
|
||||||
ssh_buffer_free(buffer);
|
SSH_BUFFER_FREE(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -161,7 +161,7 @@ static void torture_ssh_buffer_add_format(void **state) {
|
|||||||
assert_int_equal(len, sizeof(verif) - 1);
|
assert_int_equal(len, sizeof(verif) - 1);
|
||||||
assert_memory_equal(ssh_buffer_get(buffer), verif, sizeof(verif) -1);
|
assert_memory_equal(ssh_buffer_get(buffer), verif, sizeof(verif) -1);
|
||||||
|
|
||||||
ssh_string_free(s);
|
SSH_STRING_FREE(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_ssh_buffer_get_format(void **state) {
|
static void torture_ssh_buffer_get_format(void **state) {
|
||||||
|
|||||||
@@ -170,21 +170,21 @@ static void torture_config_from_file(void **state) {
|
|||||||
assert_non_null(v);
|
assert_non_null(v);
|
||||||
|
|
||||||
assert_string_equal(v, PROXYCMD);
|
assert_string_equal(v, PROXYCMD);
|
||||||
ssh_string_free_char(v);
|
SSH_STRING_FREE_CHAR(v);
|
||||||
|
|
||||||
ret = ssh_options_get(session, SSH_OPTIONS_IDENTITY, &v);
|
ret = ssh_options_get(session, SSH_OPTIONS_IDENTITY, &v);
|
||||||
assert_true(ret == 0);
|
assert_true(ret == 0);
|
||||||
assert_non_null(v);
|
assert_non_null(v);
|
||||||
|
|
||||||
assert_string_equal(v, ID_FILE);
|
assert_string_equal(v, ID_FILE);
|
||||||
ssh_string_free_char(v);
|
SSH_STRING_FREE_CHAR(v);
|
||||||
|
|
||||||
ret = ssh_options_get(session, SSH_OPTIONS_USER, &v);
|
ret = ssh_options_get(session, SSH_OPTIONS_USER, &v);
|
||||||
assert_true(ret == 0);
|
assert_true(ret == 0);
|
||||||
assert_non_null(v);
|
assert_non_null(v);
|
||||||
|
|
||||||
assert_string_equal(v, USERNAME);
|
assert_string_equal(v, USERNAME);
|
||||||
ssh_string_free_char(v);
|
SSH_STRING_FREE_CHAR(v);
|
||||||
|
|
||||||
assert_string_equal(session->opts.wanted_methods[SSH_KEX], KEXALGORITHMS);
|
assert_string_equal(session->opts.wanted_methods[SSH_KEX], KEXALGORITHMS);
|
||||||
|
|
||||||
@@ -223,14 +223,14 @@ static void torture_config_glob(void **state) {
|
|||||||
assert_non_null(v);
|
assert_non_null(v);
|
||||||
|
|
||||||
assert_string_equal(v, PROXYCMD);
|
assert_string_equal(v, PROXYCMD);
|
||||||
ssh_string_free_char(v);
|
SSH_STRING_FREE_CHAR(v);
|
||||||
|
|
||||||
ret = ssh_options_get(session, SSH_OPTIONS_IDENTITY, &v);
|
ret = ssh_options_get(session, SSH_OPTIONS_IDENTITY, &v);
|
||||||
assert_true(ret == 0);
|
assert_true(ret == 0);
|
||||||
assert_non_null(v);
|
assert_non_null(v);
|
||||||
|
|
||||||
assert_string_equal(v, ID_FILE);
|
assert_string_equal(v, ID_FILE);
|
||||||
ssh_string_free_char(v);
|
SSH_STRING_FREE_CHAR(v);
|
||||||
#endif /* HAVE_GLOB */
|
#endif /* HAVE_GLOB */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,88 +41,91 @@ static int setup_rsa_key(void **state)
|
|||||||
|
|
||||||
static int teardown(void **state)
|
static int teardown(void **state)
|
||||||
{
|
{
|
||||||
ssh_key_free(*state);
|
SSH_KEY_FREE(*state);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_md5_hash(void **state)
|
static void torture_md5_hash(void **state)
|
||||||
{
|
{
|
||||||
ssh_key pubkey = *state;
|
ssh_key pubkey = *state;
|
||||||
unsigned char *hash = NULL;
|
char *hash = NULL;
|
||||||
char *hexa = NULL;
|
char *hexa = NULL;
|
||||||
size_t hlen;
|
size_t hlen;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_MD5, &hash, &hlen);
|
rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_MD5,
|
||||||
|
(unsigned char **)&hash, &hlen);
|
||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
|
|
||||||
hexa = ssh_get_hexa(hash, hlen);
|
hexa = ssh_get_hexa((unsigned char *)hash, hlen);
|
||||||
ssh_string_free_char((char *)hash);
|
SSH_STRING_FREE_CHAR(hash);
|
||||||
assert_string_equal(hexa,
|
assert_string_equal(hexa,
|
||||||
"50:15:a0:9b:92:bf:33:1c:01:c5:8c:fe:18:fa:ce:78");
|
"50:15:a0:9b:92:bf:33:1c:01:c5:8c:fe:18:fa:ce:78");
|
||||||
|
|
||||||
ssh_string_free_char(hexa);
|
SSH_STRING_FREE_CHAR(hexa);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_sha1_hash(void **state)
|
static void torture_sha1_hash(void **state)
|
||||||
{
|
{
|
||||||
ssh_key pubkey = *state;
|
ssh_key pubkey = *state;
|
||||||
unsigned char *hash = NULL;
|
char *hash = NULL;
|
||||||
char *sha1 = NULL;
|
char *sha1 = NULL;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
size_t hlen;
|
size_t hlen;
|
||||||
|
|
||||||
rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_SHA1, &hash, &hlen);
|
rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_SHA1,
|
||||||
|
(unsigned char **)&hash, &hlen);
|
||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
|
|
||||||
sha1 = ssh_get_b64_unpadded(hash, hlen);
|
sha1 = ssh_get_b64_unpadded((unsigned char *)hash, hlen);
|
||||||
ssh_string_free_char((char *)hash);
|
SSH_STRING_FREE_CHAR(hash);
|
||||||
assert_string_equal(sha1, "6wP+houujQmxLBiFugTcoeoODCM");
|
assert_string_equal(sha1, "6wP+houujQmxLBiFugTcoeoODCM");
|
||||||
|
|
||||||
ssh_string_free_char(sha1);
|
SSH_STRING_FREE_CHAR(sha1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_sha256_hash(void **state)
|
static void torture_sha256_hash(void **state)
|
||||||
{
|
{
|
||||||
ssh_key pubkey = *state;
|
ssh_key pubkey = *state;
|
||||||
unsigned char *hash = NULL;
|
char *hash = NULL;
|
||||||
char *sha256 = NULL;
|
char *sha256 = NULL;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
size_t hlen;
|
size_t hlen;
|
||||||
|
|
||||||
rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_SHA256, &hash, &hlen);
|
rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_SHA256,
|
||||||
|
(unsigned char **)&hash, &hlen);
|
||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
|
|
||||||
sha256 = ssh_get_b64_unpadded(hash, hlen);
|
sha256 = ssh_get_b64_unpadded((unsigned char *)hash, hlen);
|
||||||
ssh_string_free_char((char *)hash);
|
SSH_STRING_FREE_CHAR(hash);
|
||||||
assert_string_equal(sha256, "jXstVLLe84fSDo1kEYGn6iumnPCSorhaiWxnJz8VTII");
|
assert_string_equal(sha256, "jXstVLLe84fSDo1kEYGn6iumnPCSorhaiWxnJz8VTII");
|
||||||
|
|
||||||
ssh_string_free_char(sha256);
|
SSH_STRING_FREE_CHAR(sha256);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_sha256_fingerprint(void **state)
|
static void torture_sha256_fingerprint(void **state)
|
||||||
{
|
{
|
||||||
ssh_key pubkey = *state;
|
ssh_key pubkey = *state;
|
||||||
unsigned char *hash = NULL;
|
char *hash = NULL;
|
||||||
char *sha256 = NULL;
|
char *sha256 = NULL;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
size_t hlen;
|
size_t hlen;
|
||||||
|
|
||||||
rc = ssh_get_publickey_hash(pubkey,
|
rc = ssh_get_publickey_hash(pubkey,
|
||||||
SSH_PUBLICKEY_HASH_SHA256,
|
SSH_PUBLICKEY_HASH_SHA256,
|
||||||
&hash,
|
(unsigned char **)&hash,
|
||||||
&hlen);
|
&hlen);
|
||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
|
|
||||||
sha256 = ssh_get_fingerprint_hash(SSH_PUBLICKEY_HASH_SHA256,
|
sha256 = ssh_get_fingerprint_hash(SSH_PUBLICKEY_HASH_SHA256,
|
||||||
hash,
|
(unsigned char *)hash,
|
||||||
hlen);
|
hlen);
|
||||||
ssh_string_free_char(discard_const(hash));
|
SSH_STRING_FREE_CHAR(hash);
|
||||||
assert_string_equal(sha256,
|
assert_string_equal(sha256,
|
||||||
"SHA256:jXstVLLe84fSDo1kEYGn6iumnPCSorhaiWxnJz8VTII");
|
"SHA256:jXstVLLe84fSDo1kEYGn6iumnPCSorhaiWxnJz8VTII");
|
||||||
|
|
||||||
ssh_string_free_char(sha256);
|
SSH_STRING_FREE_CHAR(sha256);
|
||||||
}
|
}
|
||||||
|
|
||||||
int torture_run_tests(void) {
|
int torture_run_tests(void) {
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ static void torture_pubkey_from_file(void **state) {
|
|||||||
|
|
||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
|
|
||||||
ssh_string_free(pubkey);
|
SSH_STRING_FREE(pubkey);
|
||||||
|
|
||||||
/* test if it returns 1 if pubkey doesn't exist */
|
/* test if it returns 1 if pubkey doesn't exist */
|
||||||
unlink(LIBSSH_RSA_TESTKEY ".pub");
|
unlink(LIBSSH_RSA_TESTKEY ".pub");
|
||||||
@@ -119,11 +119,17 @@ static void torture_pubkey_from_file(void **state) {
|
|||||||
rc = ssh_try_publickey_from_file(session, LIBSSH_RSA_TESTKEY, &pubkey, &type);
|
rc = ssh_try_publickey_from_file(session, LIBSSH_RSA_TESTKEY, &pubkey, &type);
|
||||||
assert_true(rc == 1);
|
assert_true(rc == 1);
|
||||||
|
|
||||||
|
/* This free is unnecessary, but the static analyser does not know */
|
||||||
|
SSH_STRING_FREE(pubkey);
|
||||||
|
|
||||||
/* test if it returns -1 if privkey doesn't exist */
|
/* test if it returns -1 if privkey doesn't exist */
|
||||||
unlink(LIBSSH_RSA_TESTKEY);
|
unlink(LIBSSH_RSA_TESTKEY);
|
||||||
|
|
||||||
rc = ssh_try_publickey_from_file(session, LIBSSH_RSA_TESTKEY, &pubkey, &type);
|
rc = ssh_try_publickey_from_file(session, LIBSSH_RSA_TESTKEY, &pubkey, &type);
|
||||||
assert_true(rc == -1);
|
assert_true(rc == -1);
|
||||||
|
|
||||||
|
/* This free is unnecessary, but the static analyser does not know */
|
||||||
|
SSH_STRING_FREE(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int torture_read_one_line(const char *filename, char *buffer, size_t len) {
|
static int torture_read_one_line(const char *filename, char *buffer, size_t len) {
|
||||||
@@ -210,8 +216,8 @@ static void torture_pubkey_generate_from_privkey(void **state) {
|
|||||||
|
|
||||||
assert_string_equal(pubkey_line_orig, pubkey_line_new);
|
assert_string_equal(pubkey_line_orig, pubkey_line_new);
|
||||||
|
|
||||||
ssh_string_free(pubkey_orig);
|
SSH_STRING_FREE(pubkey_orig);
|
||||||
ssh_string_free(pubkey_new);
|
SSH_STRING_FREE(pubkey_new);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -560,7 +630,7 @@ static void torture_bind_options_import_key(void **state)
|
|||||||
/* set invalid key */
|
/* set invalid key */
|
||||||
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_IMPORT_KEY, key);
|
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_IMPORT_KEY, key);
|
||||||
assert_int_equal(rc, -1);
|
assert_int_equal(rc, -1);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
|
|
||||||
/* set rsa key */
|
/* set rsa key */
|
||||||
base64_key = torture_get_testkey(SSH_KEYTYPE_RSA, 0, 0);
|
base64_key = torture_get_testkey(SSH_KEYTYPE_RSA, 0, 0);
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
502
tests/unittests/torture_packet_filter.c
Normal file
502
tests/unittests/torture_packet_filter.c
Normal file
@@ -0,0 +1,502 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the SSH Library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018 by Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||||
|
*
|
||||||
|
* The SSH Library is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* The SSH Library is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
* License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with the SSH Library; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||||
|
* MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This test checks if the messages accepted by the packet filter were intented
|
||||||
|
* to be accepted.
|
||||||
|
*
|
||||||
|
* The process consists in 2 steps:
|
||||||
|
* - Try the filter with a message type in an arbitrary state
|
||||||
|
* - If the message is accepted by the filter, check if the message is in the
|
||||||
|
* set of accepted states.
|
||||||
|
*
|
||||||
|
* Only the values selected by the flag (COMPARE_*) are considered.
|
||||||
|
* */
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#define LIBSSH_STATIC
|
||||||
|
|
||||||
|
#include "torture.h"
|
||||||
|
#include "libssh/priv.h"
|
||||||
|
#include "libssh/libssh.h"
|
||||||
|
#include "libssh/session.h"
|
||||||
|
#include "libssh/auth.h"
|
||||||
|
#include "libssh/ssh2.h"
|
||||||
|
#include "libssh/packet.h"
|
||||||
|
|
||||||
|
#include "packet.c"
|
||||||
|
|
||||||
|
#define COMPARE_SESSION_STATE 1
|
||||||
|
#define COMPARE_ROLE (1 << 1)
|
||||||
|
#define COMPARE_DH_STATE (1 << 2)
|
||||||
|
#define COMPARE_AUTH_STATE (1 << 3)
|
||||||
|
#define COMPARE_GLOBAL_REQ_STATE (1 << 4)
|
||||||
|
#define COMPARE_CURRENT_METHOD (1 << 5)
|
||||||
|
|
||||||
|
#define SESSION_STATE_COUNT 11
|
||||||
|
#define DH_STATE_COUNT 4
|
||||||
|
#define AUTH_STATE_COUNT 15
|
||||||
|
#define GLOBAL_REQ_STATE_COUNT 5
|
||||||
|
#define MESSAGE_COUNT 100 // from 1 to 100
|
||||||
|
|
||||||
|
#define ROLE_CLIENT 0
|
||||||
|
#define ROLE_SERVER 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the list of currently unfiltered message types.
|
||||||
|
* Only unrecognized types should be in this list.
|
||||||
|
* */
|
||||||
|
static uint8_t unfiltered[] = {
|
||||||
|
8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
|
||||||
|
22, 23, 24, 25, 26, 27, 28, 29,
|
||||||
|
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
|
||||||
|
54, 55, 56, 57, 58, 59,
|
||||||
|
62,
|
||||||
|
67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
|
||||||
|
83, 84, 85, 86, 87, 88, 89,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct global_state_st {
|
||||||
|
/* If the bit in this flag is zero, the corresponding state is not
|
||||||
|
* considered, working as a wildcard (meaning any value is accepted) */
|
||||||
|
uint32_t flags;
|
||||||
|
uint8_t role;
|
||||||
|
enum ssh_session_state_e session;
|
||||||
|
enum ssh_dh_state_e dh;
|
||||||
|
enum ssh_auth_state_e auth;
|
||||||
|
enum ssh_channel_request_state_e global_req;
|
||||||
|
} global_state;
|
||||||
|
|
||||||
|
static int cmp_state(const void *e1, const void *e2)
|
||||||
|
{
|
||||||
|
global_state *s1 = (global_state *) e1;
|
||||||
|
global_state *s2 = (global_state *) e2;
|
||||||
|
|
||||||
|
/* Compare role (client == 0 or server == 1)*/
|
||||||
|
if (s1->role < s2->role) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (s1->role > s2->role) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compare session state */
|
||||||
|
if (s1->session < s2->session) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (s1->session > s2->session) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compare DH state */
|
||||||
|
if (s1->dh < s2->dh) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (s1->dh > s2->dh) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compare auth */
|
||||||
|
if (s1->auth < s2->auth) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (s1->auth > s2->auth) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compare global_req */
|
||||||
|
if (s1->global_req < s2->global_req) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (s1->global_req > s2->global_req) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If all equal, they are equal */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmp_state_search(const void *key, const void *array_element)
|
||||||
|
{
|
||||||
|
global_state *s1 = (global_state *) key;
|
||||||
|
global_state *s2 = (global_state *) array_element;
|
||||||
|
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
if (s2->flags & COMPARE_ROLE) {
|
||||||
|
/* Compare role (client == 0 or server == 1)*/
|
||||||
|
if (s1->role < s2->role) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (s1->role > s2->role) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s2->flags & COMPARE_SESSION_STATE) {
|
||||||
|
/* Compare session state */
|
||||||
|
if (s1->session < s2->session) {
|
||||||
|
result = -1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
else if (s1->session > s2->session) {
|
||||||
|
result = 1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s2->flags & COMPARE_DH_STATE) {
|
||||||
|
/* Compare DH state */
|
||||||
|
if (s1->dh < s2->dh) {
|
||||||
|
result = -1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
else if (s1->dh > s2->dh) {
|
||||||
|
result = 1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s2->flags & COMPARE_AUTH_STATE) {
|
||||||
|
/* Compare auth */
|
||||||
|
if (s1->auth < s2->auth) {
|
||||||
|
result = -1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
else if (s1->auth > s2->auth) {
|
||||||
|
result = 1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s2->flags & COMPARE_GLOBAL_REQ_STATE) {
|
||||||
|
/* Compare global_req */
|
||||||
|
if (s1->global_req < s2->global_req) {
|
||||||
|
result = -1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
else if (s1->global_req > s2->global_req) {
|
||||||
|
result = 1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int is_state_accepted(global_state *tested, global_state *accepted,
|
||||||
|
int accepted_len)
|
||||||
|
{
|
||||||
|
global_state *found = NULL;
|
||||||
|
|
||||||
|
found = bsearch(tested, accepted, accepted_len, sizeof(global_state),
|
||||||
|
cmp_state_search);
|
||||||
|
|
||||||
|
if (found != NULL) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmp_uint8(const void *i, const void *j)
|
||||||
|
{
|
||||||
|
uint8_t e1 = *((uint8_t *)i);
|
||||||
|
uint8_t e2 = *((uint8_t *)j);
|
||||||
|
|
||||||
|
if (e1 < e2) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (e1 > e2) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_unfiltered(uint8_t msg_type)
|
||||||
|
{
|
||||||
|
uint8_t *found;
|
||||||
|
|
||||||
|
found = bsearch(&msg_type, unfiltered, sizeof(unfiltered)/sizeof(uint8_t),
|
||||||
|
sizeof(uint8_t), cmp_uint8);
|
||||||
|
|
||||||
|
if (found != NULL) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void torture_packet_filter_check_unfiltered(void **state)
|
||||||
|
{
|
||||||
|
ssh_session session;
|
||||||
|
|
||||||
|
int role_c;
|
||||||
|
int auth_c;
|
||||||
|
int session_c;
|
||||||
|
int dh_c;
|
||||||
|
int global_req_c;
|
||||||
|
|
||||||
|
uint8_t msg_type;
|
||||||
|
|
||||||
|
enum ssh_packet_filter_result_e rc;
|
||||||
|
int in_unfiltered;
|
||||||
|
|
||||||
|
session = ssh_new();
|
||||||
|
|
||||||
|
for (msg_type = 1; msg_type <= MESSAGE_COUNT; msg_type++) {
|
||||||
|
session->in_packet.type = msg_type;
|
||||||
|
for (role_c = 0; role_c < 2; role_c++) {
|
||||||
|
session->server = role_c;
|
||||||
|
for (session_c = 0; session_c < SESSION_STATE_COUNT; session_c++) {
|
||||||
|
session->session_state = session_c;
|
||||||
|
for (dh_c = 0; dh_c < DH_STATE_COUNT; dh_c++) {
|
||||||
|
session->dh_handshake_state = dh_c;
|
||||||
|
for (auth_c = 0; auth_c < AUTH_STATE_COUNT; auth_c++) {
|
||||||
|
session->auth.state = auth_c;
|
||||||
|
for (global_req_c = 0;
|
||||||
|
global_req_c < GLOBAL_REQ_STATE_COUNT;
|
||||||
|
global_req_c++)
|
||||||
|
{
|
||||||
|
session->global_req_state = global_req_c;
|
||||||
|
|
||||||
|
rc = ssh_packet_incoming_filter(session);
|
||||||
|
|
||||||
|
if (rc == SSH_PACKET_UNKNOWN) {
|
||||||
|
in_unfiltered = check_unfiltered(msg_type);
|
||||||
|
|
||||||
|
if (!in_unfiltered) {
|
||||||
|
fprintf(stderr, "Message type %d UNFILTERED "
|
||||||
|
"in state: role %d, session %d, dh %d, auth %d\n",
|
||||||
|
msg_type, role_c, session_c, dh_c, auth_c);
|
||||||
|
}
|
||||||
|
assert_int_equal(in_unfiltered, 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
in_unfiltered = check_unfiltered(msg_type);
|
||||||
|
|
||||||
|
if (in_unfiltered) {
|
||||||
|
fprintf(stderr, "Message type %d NOT UNFILTERED "
|
||||||
|
"in state: role %d, session %d, dh %d, auth %d\n",
|
||||||
|
msg_type, role_c, session_c, dh_c, auth_c);
|
||||||
|
}
|
||||||
|
assert_int_equal(in_unfiltered, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ssh_free(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_message_in_all_states(global_state accepted[],
|
||||||
|
int accepted_count, uint8_t msg_type)
|
||||||
|
{
|
||||||
|
ssh_session session;
|
||||||
|
|
||||||
|
int role_c;
|
||||||
|
int auth_c;
|
||||||
|
int session_c;
|
||||||
|
int dh_c;
|
||||||
|
int global_req_c;
|
||||||
|
|
||||||
|
enum ssh_packet_filter_result_e rc;
|
||||||
|
int in_accepted;
|
||||||
|
|
||||||
|
global_state key;
|
||||||
|
|
||||||
|
session = ssh_new();
|
||||||
|
|
||||||
|
/* Sort the accepted array so that the elements can be searched using
|
||||||
|
* bsearch */
|
||||||
|
qsort(accepted, accepted_count, sizeof(global_state), cmp_state);
|
||||||
|
|
||||||
|
session->in_packet.type = msg_type;
|
||||||
|
|
||||||
|
for (role_c = 0; role_c < 2; role_c++) {
|
||||||
|
session->server = role_c;
|
||||||
|
key.role = role_c;
|
||||||
|
for (session_c = 0; session_c < SESSION_STATE_COUNT; session_c++) {
|
||||||
|
session->session_state = session_c;
|
||||||
|
key.session = session_c;
|
||||||
|
for (dh_c = 0; dh_c < DH_STATE_COUNT; dh_c++) {
|
||||||
|
session->dh_handshake_state = dh_c;
|
||||||
|
key.dh = dh_c;
|
||||||
|
for (auth_c = 0; auth_c < AUTH_STATE_COUNT; auth_c++) {
|
||||||
|
session->auth.state = auth_c;
|
||||||
|
key.auth = auth_c;
|
||||||
|
for (global_req_c = 0;
|
||||||
|
global_req_c < GLOBAL_REQ_STATE_COUNT;
|
||||||
|
global_req_c++)
|
||||||
|
{
|
||||||
|
session->global_req_state = global_req_c;
|
||||||
|
key.global_req = global_req_c;
|
||||||
|
|
||||||
|
rc = ssh_packet_incoming_filter(session);
|
||||||
|
|
||||||
|
if (rc == SSH_PACKET_ALLOWED) {
|
||||||
|
in_accepted = is_state_accepted(&key, accepted,
|
||||||
|
accepted_count);
|
||||||
|
|
||||||
|
if (!in_accepted) {
|
||||||
|
fprintf(stderr, "Message type %d ALLOWED "
|
||||||
|
"in state: role %d, session %d, dh %d, auth %d\n",
|
||||||
|
msg_type, role_c, session_c, dh_c, auth_c);
|
||||||
|
}
|
||||||
|
assert_int_equal(in_accepted, 1);
|
||||||
|
}
|
||||||
|
else if (rc == SSH_PACKET_DENIED) {
|
||||||
|
in_accepted = is_state_accepted(&key, accepted, accepted_count);
|
||||||
|
|
||||||
|
if (in_accepted) {
|
||||||
|
fprintf(stderr, "Message type %d DENIED "
|
||||||
|
"in state: role %d, session %d, dh %d, auth %d\n",
|
||||||
|
msg_type, role_c, session_c, dh_c, auth_c);
|
||||||
|
}
|
||||||
|
assert_int_equal(in_accepted, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "Message type %d UNFILTERED "
|
||||||
|
"in state: role %d, session %d, dh %d, auth %d\n",
|
||||||
|
msg_type, role_c, session_c, dh_c, auth_c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_free(session);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void torture_packet_filter_check_auth_success(void **state)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
global_state accepted[] = {
|
||||||
|
{
|
||||||
|
.flags = (COMPARE_SESSION_STATE |
|
||||||
|
COMPARE_ROLE |
|
||||||
|
COMPARE_AUTH_STATE |
|
||||||
|
COMPARE_DH_STATE),
|
||||||
|
.role = ROLE_CLIENT,
|
||||||
|
.session = SSH_SESSION_STATE_AUTHENTICATING,
|
||||||
|
.dh = DH_STATE_FINISHED,
|
||||||
|
.auth = SSH_AUTH_STATE_PUBKEY_AUTH_SENT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.flags = (COMPARE_SESSION_STATE |
|
||||||
|
COMPARE_ROLE |
|
||||||
|
COMPARE_AUTH_STATE |
|
||||||
|
COMPARE_DH_STATE),
|
||||||
|
.role = ROLE_CLIENT,
|
||||||
|
.session = SSH_SESSION_STATE_AUTHENTICATING,
|
||||||
|
.dh = DH_STATE_FINISHED,
|
||||||
|
.auth = SSH_AUTH_STATE_PASSWORD_AUTH_SENT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.flags = (COMPARE_SESSION_STATE |
|
||||||
|
COMPARE_ROLE |
|
||||||
|
COMPARE_AUTH_STATE |
|
||||||
|
COMPARE_DH_STATE),
|
||||||
|
.role = ROLE_CLIENT,
|
||||||
|
.session = SSH_SESSION_STATE_AUTHENTICATING,
|
||||||
|
.dh = DH_STATE_FINISHED,
|
||||||
|
.auth = SSH_AUTH_STATE_GSSAPI_MIC_SENT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.flags = (COMPARE_SESSION_STATE |
|
||||||
|
COMPARE_ROLE |
|
||||||
|
COMPARE_AUTH_STATE |
|
||||||
|
COMPARE_DH_STATE),
|
||||||
|
.role = ROLE_CLIENT,
|
||||||
|
.session = SSH_SESSION_STATE_AUTHENTICATING,
|
||||||
|
.dh = DH_STATE_FINISHED,
|
||||||
|
.auth = SSH_AUTH_STATE_KBDINT_SENT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.flags = (COMPARE_SESSION_STATE |
|
||||||
|
COMPARE_ROLE |
|
||||||
|
COMPARE_AUTH_STATE |
|
||||||
|
COMPARE_DH_STATE |
|
||||||
|
COMPARE_CURRENT_METHOD),
|
||||||
|
.role = ROLE_CLIENT,
|
||||||
|
.session = SSH_SESSION_STATE_AUTHENTICATING,
|
||||||
|
.dh = DH_STATE_FINISHED,
|
||||||
|
.auth = SSH_AUTH_STATE_AUTH_NONE_SENT,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int accepted_count = 5;
|
||||||
|
|
||||||
|
/* Unused */
|
||||||
|
(void) state;
|
||||||
|
|
||||||
|
rc = check_message_in_all_states(accepted, accepted_count,
|
||||||
|
SSH2_MSG_USERAUTH_SUCCESS);
|
||||||
|
|
||||||
|
assert_int_equal(rc, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void torture_packet_filter_check_channel_open(void **state)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* The only condition to accept a CHANNEL_OPEN is to be authenticated */
|
||||||
|
global_state accepted[] = {
|
||||||
|
{
|
||||||
|
.flags = COMPARE_SESSION_STATE,
|
||||||
|
.session = SSH_SESSION_STATE_AUTHENTICATED,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int accepted_count = 1;
|
||||||
|
|
||||||
|
/* Unused */
|
||||||
|
(void) state;
|
||||||
|
|
||||||
|
rc = check_message_in_all_states(accepted, accepted_count,
|
||||||
|
SSH2_MSG_CHANNEL_OPEN);
|
||||||
|
|
||||||
|
assert_int_equal(rc, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int torture_run_tests(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
struct CMUnitTest tests[] = {
|
||||||
|
cmocka_unit_test(torture_packet_filter_check_auth_success),
|
||||||
|
cmocka_unit_test(torture_packet_filter_check_channel_open),
|
||||||
|
cmocka_unit_test(torture_packet_filter_check_unfiltered),
|
||||||
|
};
|
||||||
|
|
||||||
|
ssh_init();
|
||||||
|
torture_filter_tests(tests);
|
||||||
|
rc = cmocka_run_group_tests(tests, NULL, NULL);
|
||||||
|
ssh_finalize();
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
@@ -82,7 +82,7 @@ static void torture_pki_dsa_import_pubkey_file(void **state)
|
|||||||
assert_return_code(rc, errno);
|
assert_return_code(rc, errno);
|
||||||
assert_non_null(pubkey);
|
assert_non_null(pubkey);
|
||||||
|
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_dsa_import_pubkey_from_openssh_privkey(void **state)
|
static void torture_pki_dsa_import_pubkey_from_openssh_privkey(void **state)
|
||||||
@@ -97,7 +97,7 @@ static void torture_pki_dsa_import_pubkey_from_openssh_privkey(void **state)
|
|||||||
assert_return_code(rc, errno);
|
assert_return_code(rc, errno);
|
||||||
assert_non_null(pubkey);
|
assert_non_null(pubkey);
|
||||||
|
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_dsa_import_privkey_base64(void **state)
|
static void torture_pki_dsa_import_privkey_base64(void **state)
|
||||||
@@ -115,7 +115,7 @@ static void torture_pki_dsa_import_privkey_base64(void **state)
|
|||||||
&key);
|
&key);
|
||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
|
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_LIBCRYPTO
|
#ifdef HAVE_LIBCRYPTO
|
||||||
@@ -154,8 +154,8 @@ static void torture_pki_dsa_write_privkey(void **state)
|
|||||||
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
|
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
|
||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
|
|
||||||
ssh_key_free(origkey);
|
SSH_KEY_FREE(origkey);
|
||||||
ssh_key_free(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
|
|
||||||
/* Test with passphrase */
|
/* Test with passphrase */
|
||||||
rc = ssh_pki_import_privkey_file(LIBSSH_DSA_TESTKEY_PASSPHRASE,
|
rc = ssh_pki_import_privkey_file(LIBSSH_DSA_TESTKEY_PASSPHRASE,
|
||||||
@@ -192,8 +192,8 @@ static void torture_pki_dsa_write_privkey(void **state)
|
|||||||
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
|
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
|
||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
|
|
||||||
ssh_key_free(origkey);
|
SSH_KEY_FREE(origkey);
|
||||||
ssh_key_free(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -215,8 +215,7 @@ static void torture_pki_dsa_import_privkey_base64_passphrase(void **state)
|
|||||||
rc = ssh_key_is_private(key);
|
rc = ssh_key_is_private(key);
|
||||||
assert_true(rc == 1);
|
assert_true(rc == 1);
|
||||||
|
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key = NULL;
|
|
||||||
|
|
||||||
/* test if it returns -1 if passphrase is wrong */
|
/* test if it returns -1 if passphrase is wrong */
|
||||||
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_DSS, 0, 1),
|
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_DSS, 0, 1),
|
||||||
@@ -247,8 +246,7 @@ static void torture_pki_dsa_import_privkey_base64_passphrase(void **state)
|
|||||||
rc = ssh_key_is_private(key);
|
rc = ssh_key_is_private(key);
|
||||||
assert_true(rc == 1);
|
assert_true(rc == 1);
|
||||||
|
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key = NULL;
|
|
||||||
|
|
||||||
/* test if it returns -1 if passphrase is wrong */
|
/* test if it returns -1 if passphrase is wrong */
|
||||||
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_DSS, 0, 1),
|
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_DSS, 0, 1),
|
||||||
@@ -259,7 +257,7 @@ static void torture_pki_dsa_import_privkey_base64_passphrase(void **state)
|
|||||||
assert_true(rc == -1);
|
assert_true(rc == -1);
|
||||||
|
|
||||||
/* This free in unnecessary, but the static analyser does not know */
|
/* This free in unnecessary, but the static analyser does not know */
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
|
|
||||||
#ifndef HAVE_LIBCRYPTO
|
#ifndef HAVE_LIBCRYPTO
|
||||||
/* test if it returns -1 if passphrase is NULL */
|
/* test if it returns -1 if passphrase is NULL */
|
||||||
@@ -272,7 +270,7 @@ static void torture_pki_dsa_import_privkey_base64_passphrase(void **state)
|
|||||||
assert_true(rc == -1);
|
assert_true(rc == -1);
|
||||||
|
|
||||||
/* This free in unnecessary, but the static analyser does not know */
|
/* This free in unnecessary, but the static analyser does not know */
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
#endif /* HAVE_LIBCRYPTO */
|
#endif /* HAVE_LIBCRYPTO */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,8 +297,7 @@ torture_pki_dsa_import_openssh_privkey_base64_passphrase(void **state)
|
|||||||
rc = ssh_key_is_private(key);
|
rc = ssh_key_is_private(key);
|
||||||
assert_true(rc == 1);
|
assert_true(rc == 1);
|
||||||
|
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key = NULL;
|
|
||||||
|
|
||||||
/* test if it returns -1 if passphrase is wrong */
|
/* test if it returns -1 if passphrase is wrong */
|
||||||
rc = ssh_pki_import_privkey_base64(keystring,
|
rc = ssh_pki_import_privkey_base64(keystring,
|
||||||
@@ -328,8 +325,7 @@ torture_pki_dsa_import_openssh_privkey_base64_passphrase(void **state)
|
|||||||
rc = ssh_key_is_private(key);
|
rc = ssh_key_is_private(key);
|
||||||
assert_true(rc == 1);
|
assert_true(rc == 1);
|
||||||
|
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key = NULL;
|
|
||||||
|
|
||||||
/* test if it returns -1 if passphrase is wrong */
|
/* test if it returns -1 if passphrase is wrong */
|
||||||
rc = ssh_pki_import_privkey_base64(keystring,
|
rc = ssh_pki_import_privkey_base64(keystring,
|
||||||
@@ -339,6 +335,9 @@ torture_pki_dsa_import_openssh_privkey_base64_passphrase(void **state)
|
|||||||
&key);
|
&key);
|
||||||
assert_true(rc == -1);
|
assert_true(rc == -1);
|
||||||
|
|
||||||
|
/* This free is unnecessary, but the static analyser does not know */
|
||||||
|
SSH_KEY_FREE(key);
|
||||||
|
|
||||||
/* test if it returns -1 if passphrase is NULL */
|
/* test if it returns -1 if passphrase is NULL */
|
||||||
rc = ssh_pki_import_privkey_base64(keystring,
|
rc = ssh_pki_import_privkey_base64(keystring,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -346,6 +345,9 @@ torture_pki_dsa_import_openssh_privkey_base64_passphrase(void **state)
|
|||||||
NULL,
|
NULL,
|
||||||
&key);
|
&key);
|
||||||
assert_true(rc == -1);
|
assert_true(rc == -1);
|
||||||
|
|
||||||
|
/* This free is unnecessary, but the static analyser does not know */
|
||||||
|
SSH_KEY_FREE(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -371,8 +373,8 @@ static void torture_pki_dsa_publickey_from_privatekey(void **state)
|
|||||||
rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey);
|
rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey);
|
||||||
assert_true(rc == SSH_OK);
|
assert_true(rc == SSH_OK);
|
||||||
|
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_dsa_import_cert_file(void **state)
|
static void torture_pki_dsa_import_cert_file(void **state)
|
||||||
@@ -392,7 +394,7 @@ static void torture_pki_dsa_import_cert_file(void **state)
|
|||||||
rc = ssh_key_is_public(cert);
|
rc = ssh_key_is_public(cert);
|
||||||
assert_true(rc == 1);
|
assert_true(rc == 1);
|
||||||
|
|
||||||
ssh_key_free(cert);
|
SSH_KEY_FREE(cert);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_dsa_publickey_base64(void **state)
|
static void torture_pki_dsa_publickey_base64(void **state)
|
||||||
@@ -443,7 +445,7 @@ static void torture_pki_dsa_publickey_base64(void **state)
|
|||||||
|
|
||||||
free(b64_key);
|
free(b64_key);
|
||||||
free(key_buf);
|
free(key_buf);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_dsa_generate_pubkey_from_privkey(void **state)
|
static void torture_pki_dsa_generate_pubkey_from_privkey(void **state)
|
||||||
@@ -482,8 +484,8 @@ static void torture_pki_dsa_generate_pubkey_from_privkey(void **state)
|
|||||||
pubkey_generated,
|
pubkey_generated,
|
||||||
len);
|
len);
|
||||||
|
|
||||||
ssh_key_free(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_dsa_duplicate_key(void **state)
|
static void torture_pki_dsa_duplicate_key(void **state)
|
||||||
@@ -503,7 +505,7 @@ static void torture_pki_dsa_duplicate_key(void **state)
|
|||||||
|
|
||||||
rc = ssh_pki_export_pubkey_base64(pubkey, &b64_key);
|
rc = ssh_pki_export_pubkey_base64(pubkey, &b64_key);
|
||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
|
|
||||||
rc = ssh_pki_import_privkey_file(LIBSSH_DSA_TESTKEY,
|
rc = ssh_pki_import_privkey_file(LIBSSH_DSA_TESTKEY,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -530,11 +532,11 @@ static void torture_pki_dsa_duplicate_key(void **state)
|
|||||||
rc = ssh_key_cmp(privkey, privkey_dup, SSH_KEY_CMP_PRIVATE);
|
rc = ssh_key_cmp(privkey, privkey_dup, SSH_KEY_CMP_PRIVATE);
|
||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
|
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
ssh_key_free(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
ssh_key_free(privkey_dup);
|
SSH_KEY_FREE(privkey_dup);
|
||||||
ssh_string_free_char(b64_key);
|
SSH_STRING_FREE_CHAR(b64_key);
|
||||||
ssh_string_free_char(b64_key_gen);
|
SSH_STRING_FREE_CHAR(b64_key_gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_dsa_generate_key(void **state)
|
static void torture_pki_dsa_generate_key(void **state)
|
||||||
@@ -553,8 +555,7 @@ static void torture_pki_dsa_generate_key(void **state)
|
|||||||
rc = pki_signature_verify(session,sign,key,DSA_HASH,20);
|
rc = pki_signature_verify(session,sign,key,DSA_HASH,20);
|
||||||
assert_true(rc == SSH_OK);
|
assert_true(rc == SSH_OK);
|
||||||
ssh_signature_free(sign);
|
ssh_signature_free(sign);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key=NULL;
|
|
||||||
|
|
||||||
rc = ssh_pki_generate(SSH_KEYTYPE_DSS, 2048, &key);
|
rc = ssh_pki_generate(SSH_KEYTYPE_DSS, 2048, &key);
|
||||||
assert_true(rc == SSH_OK);
|
assert_true(rc == SSH_OK);
|
||||||
@@ -564,8 +565,7 @@ static void torture_pki_dsa_generate_key(void **state)
|
|||||||
rc = pki_signature_verify(session,sign,key,DSA_HASH,20);
|
rc = pki_signature_verify(session,sign,key,DSA_HASH,20);
|
||||||
assert_true(rc == SSH_OK);
|
assert_true(rc == SSH_OK);
|
||||||
ssh_signature_free(sign);
|
ssh_signature_free(sign);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key=NULL;
|
|
||||||
|
|
||||||
rc = ssh_pki_generate(SSH_KEYTYPE_DSS, 3072, &key);
|
rc = ssh_pki_generate(SSH_KEYTYPE_DSS, 3072, &key);
|
||||||
assert_true(rc == SSH_OK);
|
assert_true(rc == SSH_OK);
|
||||||
@@ -575,8 +575,7 @@ static void torture_pki_dsa_generate_key(void **state)
|
|||||||
rc = pki_signature_verify(session,sign,key,DSA_HASH,20);
|
rc = pki_signature_verify(session,sign,key,DSA_HASH,20);
|
||||||
assert_true(rc == SSH_OK);
|
assert_true(rc == SSH_OK);
|
||||||
ssh_signature_free(sign);
|
ssh_signature_free(sign);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key=NULL;
|
|
||||||
|
|
||||||
ssh_free(session);
|
ssh_free(session);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ static void torture_pki_ecdsa_import_pubkey_file(void **state)
|
|||||||
assert_return_code(rc, errno);
|
assert_return_code(rc, errno);
|
||||||
assert_non_null(pubkey);
|
assert_non_null(pubkey);
|
||||||
|
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_ecdsa_import_pubkey_from_openssh_privkey(void **state)
|
static void torture_pki_ecdsa_import_pubkey_from_openssh_privkey(void **state)
|
||||||
@@ -136,7 +136,7 @@ static void torture_pki_ecdsa_import_pubkey_from_openssh_privkey(void **state)
|
|||||||
assert_return_code(rc, errno);
|
assert_return_code(rc, errno);
|
||||||
assert_non_null(pubkey);
|
assert_non_null(pubkey);
|
||||||
|
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_ecdsa_import_privkey_base64(void **state)
|
static void torture_pki_ecdsa_import_privkey_base64(void **state)
|
||||||
@@ -158,7 +158,7 @@ static void torture_pki_ecdsa_import_privkey_base64(void **state)
|
|||||||
assert_true(rc == 1);
|
assert_true(rc == 1);
|
||||||
|
|
||||||
free(key_str);
|
free(key_str);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_ecdsa_publickey_from_privatekey(void **state)
|
static void torture_pki_ecdsa_publickey_from_privatekey(void **state)
|
||||||
@@ -181,8 +181,8 @@ static void torture_pki_ecdsa_publickey_from_privatekey(void **state)
|
|||||||
assert_true(rc == SSH_OK);
|
assert_true(rc == SSH_OK);
|
||||||
|
|
||||||
free(key_str);
|
free(key_str);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_ecdsa_publickey_base64(void **state)
|
static void torture_pki_ecdsa_publickey_base64(void **state)
|
||||||
@@ -219,7 +219,7 @@ static void torture_pki_ecdsa_publickey_base64(void **state)
|
|||||||
|
|
||||||
free(b64_key);
|
free(b64_key);
|
||||||
free(key_buf);
|
free(key_buf);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_ecdsa_generate_pubkey_from_privkey(void **state)
|
static void torture_pki_ecdsa_generate_pubkey_from_privkey(void **state)
|
||||||
@@ -261,8 +261,8 @@ static void torture_pki_ecdsa_generate_pubkey_from_privkey(void **state)
|
|||||||
len = torture_pubkey_len(pubkey_original);
|
len = torture_pubkey_len(pubkey_original);
|
||||||
assert_int_equal(strncmp(pubkey_original, pubkey_generated, len), 0);
|
assert_int_equal(strncmp(pubkey_original, pubkey_generated, len), 0);
|
||||||
|
|
||||||
ssh_key_free(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_ecdsa_duplicate_key(void **state)
|
static void torture_pki_ecdsa_duplicate_key(void **state)
|
||||||
@@ -281,7 +281,7 @@ static void torture_pki_ecdsa_duplicate_key(void **state)
|
|||||||
|
|
||||||
rc = ssh_pki_export_pubkey_base64(pubkey, &b64_key);
|
rc = ssh_pki_export_pubkey_base64(pubkey, &b64_key);
|
||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
|
|
||||||
rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY,
|
rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -307,11 +307,11 @@ static void torture_pki_ecdsa_duplicate_key(void **state)
|
|||||||
rc = ssh_key_cmp(privkey, privkey_dup, SSH_KEY_CMP_PRIVATE);
|
rc = ssh_key_cmp(privkey, privkey_dup, SSH_KEY_CMP_PRIVATE);
|
||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
|
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
ssh_key_free(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
ssh_key_free(privkey_dup);
|
SSH_KEY_FREE(privkey_dup);
|
||||||
ssh_string_free_char(b64_key);
|
SSH_STRING_FREE_CHAR(b64_key);
|
||||||
ssh_string_free_char(b64_key_gen);
|
SSH_STRING_FREE_CHAR(b64_key_gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test case for bug #147: Private ECDSA key duplication did not carry
|
/* Test case for bug #147: Private ECDSA key duplication did not carry
|
||||||
@@ -342,9 +342,9 @@ static void torture_pki_ecdsa_duplicate_then_demote(void **state)
|
|||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
assert_int_equal(pubkey->ecdsa_nid, privkey->ecdsa_nid);
|
assert_int_equal(pubkey->ecdsa_nid, privkey->ecdsa_nid);
|
||||||
|
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
ssh_key_free(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
ssh_key_free(privkey_dup);
|
SSH_KEY_FREE(privkey_dup);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_generate_key_ecdsa(void **state)
|
static void torture_pki_generate_key_ecdsa(void **state)
|
||||||
@@ -373,8 +373,7 @@ static void torture_pki_generate_key_ecdsa(void **state)
|
|||||||
assert_true(strcmp(etype_char, "ecdsa-sha2-nistp256") == 0);
|
assert_true(strcmp(etype_char, "ecdsa-sha2-nistp256") == 0);
|
||||||
|
|
||||||
ssh_signature_free(sign);
|
ssh_signature_free(sign);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key=NULL;
|
|
||||||
|
|
||||||
rc = ssh_pki_generate(SSH_KEYTYPE_ECDSA, 384, &key);
|
rc = ssh_pki_generate(SSH_KEYTYPE_ECDSA, 384, &key);
|
||||||
assert_true(rc == SSH_OK);
|
assert_true(rc == SSH_OK);
|
||||||
@@ -391,8 +390,7 @@ static void torture_pki_generate_key_ecdsa(void **state)
|
|||||||
assert_true(strcmp(etype_char, "ecdsa-sha2-nistp384") == 0);
|
assert_true(strcmp(etype_char, "ecdsa-sha2-nistp384") == 0);
|
||||||
|
|
||||||
ssh_signature_free(sign);
|
ssh_signature_free(sign);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key=NULL;
|
|
||||||
|
|
||||||
rc = ssh_pki_generate(SSH_KEYTYPE_ECDSA, 512, &key);
|
rc = ssh_pki_generate(SSH_KEYTYPE_ECDSA, 512, &key);
|
||||||
assert_true(rc == SSH_OK);
|
assert_true(rc == SSH_OK);
|
||||||
@@ -409,8 +407,7 @@ static void torture_pki_generate_key_ecdsa(void **state)
|
|||||||
assert_true(strcmp(etype_char, "ecdsa-sha2-nistp521") == 0);
|
assert_true(strcmp(etype_char, "ecdsa-sha2-nistp521") == 0);
|
||||||
|
|
||||||
ssh_signature_free(sign);
|
ssh_signature_free(sign);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key=NULL;
|
|
||||||
|
|
||||||
ssh_free(session);
|
ssh_free(session);
|
||||||
}
|
}
|
||||||
@@ -451,8 +448,8 @@ static void torture_pki_ecdsa_write_privkey(void **state)
|
|||||||
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
|
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
|
||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
|
|
||||||
ssh_key_free(origkey);
|
SSH_KEY_FREE(origkey);
|
||||||
ssh_key_free(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
|
|
||||||
/* Test with passphrase */
|
/* Test with passphrase */
|
||||||
rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY_PASSPHRASE,
|
rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY_PASSPHRASE,
|
||||||
@@ -489,8 +486,8 @@ static void torture_pki_ecdsa_write_privkey(void **state)
|
|||||||
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
|
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
|
||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
|
|
||||||
ssh_key_free(origkey);
|
SSH_KEY_FREE(origkey);
|
||||||
ssh_key_free(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
}
|
}
|
||||||
#endif /* HAVE_LIBCRYPTO */
|
#endif /* HAVE_LIBCRYPTO */
|
||||||
|
|
||||||
@@ -508,7 +505,7 @@ static void torture_pki_ecdsa_name(void **state, const char *expected_name)
|
|||||||
etype_char =ssh_pki_key_ecdsa_name(key);
|
etype_char =ssh_pki_key_ecdsa_name(key);
|
||||||
assert_true(strcmp(etype_char, expected_name) == 0);
|
assert_true(strcmp(etype_char, expected_name) == 0);
|
||||||
|
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_ecdsa_name256(void **state)
|
static void torture_pki_ecdsa_name256(void **state)
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ static void torture_pki_ed25519_import_pubkey_file(void **state)
|
|||||||
assert_return_code(rc, errno);
|
assert_return_code(rc, errno);
|
||||||
assert_non_null(pubkey);
|
assert_non_null(pubkey);
|
||||||
|
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_ed25519_import_pubkey_from_openssh_privkey(void **state)
|
static void torture_pki_ed25519_import_pubkey_from_openssh_privkey(void **state)
|
||||||
@@ -77,7 +77,7 @@ static void torture_pki_ed25519_import_pubkey_from_openssh_privkey(void **state)
|
|||||||
assert_return_code(rc, errno);
|
assert_return_code(rc, errno);
|
||||||
assert_non_null(pubkey);
|
assert_non_null(pubkey);
|
||||||
|
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_ed25519_import_privkey_base64(void **state)
|
static void torture_pki_ed25519_import_privkey_base64(void **state)
|
||||||
@@ -106,7 +106,7 @@ static void torture_pki_ed25519_import_privkey_base64(void **state)
|
|||||||
assert_true(rc == 1);
|
assert_true(rc == 1);
|
||||||
|
|
||||||
free(key_str);
|
free(key_str);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ static void torture_pki_ed25519_import_export_privkey_base64(void **state)
|
|||||||
NULL,
|
NULL,
|
||||||
&b64_key);
|
&b64_key);
|
||||||
assert_return_code(rc, errno);
|
assert_return_code(rc, errno);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
|
|
||||||
rc = ssh_pki_import_privkey_base64(b64_key,
|
rc = ssh_pki_import_privkey_base64(b64_key,
|
||||||
passphrase,
|
passphrase,
|
||||||
@@ -157,7 +157,7 @@ static void torture_pki_ed25519_import_export_privkey_base64(void **state)
|
|||||||
assert_true(rc == 1);
|
assert_true(rc == 1);
|
||||||
|
|
||||||
SSH_STRING_FREE_CHAR(b64_key);
|
SSH_STRING_FREE_CHAR(b64_key);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_ed25519_publickey_from_privatekey(void **state)
|
static void torture_pki_ed25519_publickey_from_privatekey(void **state)
|
||||||
@@ -184,8 +184,8 @@ static void torture_pki_ed25519_publickey_from_privatekey(void **state)
|
|||||||
rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey);
|
rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey);
|
||||||
assert_true(rc == SSH_OK);
|
assert_true(rc == SSH_OK);
|
||||||
|
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_ed25519_publickey_base64(void **state)
|
static void torture_pki_ed25519_publickey_base64(void **state)
|
||||||
@@ -222,7 +222,7 @@ static void torture_pki_ed25519_publickey_base64(void **state)
|
|||||||
|
|
||||||
free(b64_key);
|
free(b64_key);
|
||||||
free(key_buf);
|
free(key_buf);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_ed25519_generate_pubkey_from_privkey(void **state)
|
static void torture_pki_ed25519_generate_pubkey_from_privkey(void **state)
|
||||||
@@ -261,8 +261,8 @@ static void torture_pki_ed25519_generate_pubkey_from_privkey(void **state)
|
|||||||
pubkey_generated,
|
pubkey_generated,
|
||||||
len);
|
len);
|
||||||
|
|
||||||
ssh_key_free(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_ed25519_generate_key(void **state)
|
static void torture_pki_ed25519_generate_key(void **state)
|
||||||
@@ -293,8 +293,7 @@ static void torture_pki_ed25519_generate_key(void **state)
|
|||||||
assert_true(rc == SSH_ERROR);
|
assert_true(rc == SSH_ERROR);
|
||||||
|
|
||||||
ssh_signature_free(sign);
|
ssh_signature_free(sign);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key=NULL;
|
|
||||||
|
|
||||||
ssh_free(session);
|
ssh_free(session);
|
||||||
}
|
}
|
||||||
@@ -336,7 +335,7 @@ static void torture_pki_ed25519_write_privkey(void **state)
|
|||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
|
|
||||||
unlink(LIBSSH_ED25519_TESTKEY);
|
unlink(LIBSSH_ED25519_TESTKEY);
|
||||||
ssh_key_free(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
/* do the same with passphrase */
|
/* do the same with passphrase */
|
||||||
rc = ssh_pki_export_privkey_file(origkey,
|
rc = ssh_pki_export_privkey_file(origkey,
|
||||||
torture_get_testkey_passphrase(),
|
torture_get_testkey_passphrase(),
|
||||||
@@ -365,8 +364,8 @@ static void torture_pki_ed25519_write_privkey(void **state)
|
|||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
unlink(LIBSSH_ED25519_TESTKEY);
|
unlink(LIBSSH_ED25519_TESTKEY);
|
||||||
|
|
||||||
ssh_key_free(origkey);
|
SSH_KEY_FREE(origkey);
|
||||||
ssh_key_free(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
|
|
||||||
/* Test with passphrase */
|
/* Test with passphrase */
|
||||||
rc = ssh_pki_import_privkey_file(LIBSSH_ED25519_TESTKEY_PASSPHRASE,
|
rc = ssh_pki_import_privkey_file(LIBSSH_ED25519_TESTKEY_PASSPHRASE,
|
||||||
@@ -404,8 +403,8 @@ static void torture_pki_ed25519_write_privkey(void **state)
|
|||||||
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
|
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
|
||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
|
|
||||||
ssh_key_free(origkey);
|
SSH_KEY_FREE(origkey);
|
||||||
ssh_key_free(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_ed25519_sign(void **state)
|
static void torture_pki_ed25519_sign(void **state)
|
||||||
@@ -441,8 +440,8 @@ static void torture_pki_ed25519_sign(void **state)
|
|||||||
assert_memory_equal(ssh_string_data(blob), ref_signature, sizeof(ref_signature));
|
assert_memory_equal(ssh_string_data(blob), ref_signature, sizeof(ref_signature));
|
||||||
/* ssh_print_hexa("signature", ssh_string_data(blob), ssh_string_len(blob)); */
|
/* ssh_print_hexa("signature", ssh_string_data(blob), ssh_string_len(blob)); */
|
||||||
ssh_signature_free(sig);
|
ssh_signature_free(sig);
|
||||||
ssh_key_free(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
ssh_string_free(blob);
|
SSH_STRING_FREE(blob);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -473,8 +472,8 @@ static void torture_pki_ed25519_verify(void **state){
|
|||||||
ssh_signature_free(sig);
|
ssh_signature_free(sig);
|
||||||
/* alter signature and expect false result */
|
/* alter signature and expect false result */
|
||||||
|
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
ssh_string_free(blob);
|
SSH_STRING_FREE(blob);
|
||||||
free(pkey_ptr);
|
free(pkey_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,8 +508,8 @@ static void torture_pki_ed25519_verify_bad(void **state){
|
|||||||
ssh_signature_free(sig);
|
ssh_signature_free(sig);
|
||||||
|
|
||||||
}
|
}
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
ssh_string_free(blob);
|
SSH_STRING_FREE(blob);
|
||||||
free(pkey_ptr);
|
free(pkey_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -535,8 +534,7 @@ static void torture_pki_ed25519_import_privkey_base64_passphrase(void **state)
|
|||||||
rc = ssh_key_is_private(key);
|
rc = ssh_key_is_private(key);
|
||||||
assert_true(rc == 1);
|
assert_true(rc == 1);
|
||||||
|
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key = NULL;
|
|
||||||
|
|
||||||
/* test if it returns -1 if passphrase is wrong */
|
/* test if it returns -1 if passphrase is wrong */
|
||||||
rc = ssh_pki_import_privkey_base64(testkey,
|
rc = ssh_pki_import_privkey_base64(testkey,
|
||||||
@@ -545,7 +543,7 @@ static void torture_pki_ed25519_import_privkey_base64_passphrase(void **state)
|
|||||||
NULL,
|
NULL,
|
||||||
&key);
|
&key);
|
||||||
assert_true(rc == -1);
|
assert_true(rc == -1);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_ed25519_privkey_dup(void **state)
|
static void torture_pki_ed25519_privkey_dup(void **state)
|
||||||
@@ -572,8 +570,8 @@ static void torture_pki_ed25519_privkey_dup(void **state)
|
|||||||
dup = ssh_key_dup(key);
|
dup = ssh_key_dup(key);
|
||||||
assert_non_null(dup);
|
assert_non_null(dup);
|
||||||
|
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
ssh_key_free(dup);
|
SSH_KEY_FREE(dup);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_ed25519_pubkey_dup(void **state)
|
static void torture_pki_ed25519_pubkey_dup(void **state)
|
||||||
@@ -609,8 +607,8 @@ static void torture_pki_ed25519_pubkey_dup(void **state)
|
|||||||
assert_true(rc == 1);
|
assert_true(rc == 1);
|
||||||
|
|
||||||
SAFE_FREE(pub_str);
|
SAFE_FREE(pub_str);
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
ssh_key_free(dup);
|
SSH_KEY_FREE(dup);
|
||||||
}
|
}
|
||||||
|
|
||||||
int torture_run_tests(void) {
|
int torture_run_tests(void) {
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ static void torture_pki_rsa_import_pubkey_file(void **state)
|
|||||||
assert_return_code(rc, errno);
|
assert_return_code(rc, errno);
|
||||||
assert_non_null(pubkey);
|
assert_non_null(pubkey);
|
||||||
|
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_rsa_import_pubkey_from_openssh_privkey(void **state)
|
static void torture_pki_rsa_import_pubkey_from_openssh_privkey(void **state)
|
||||||
@@ -99,7 +99,7 @@ static void torture_pki_rsa_import_pubkey_from_openssh_privkey(void **state)
|
|||||||
assert_return_code(rc, errno);
|
assert_return_code(rc, errno);
|
||||||
assert_non_null(pubkey);
|
assert_non_null(pubkey);
|
||||||
|
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_rsa_import_privkey_base64_NULL_key(void **state)
|
static void torture_pki_rsa_import_privkey_base64_NULL_key(void **state)
|
||||||
@@ -131,7 +131,7 @@ static void torture_pki_rsa_import_privkey_base64_NULL_str(void **state)
|
|||||||
rc = ssh_pki_import_privkey_base64(NULL, passphrase, NULL, NULL, &key);
|
rc = ssh_pki_import_privkey_base64(NULL, passphrase, NULL, NULL, &key);
|
||||||
assert_true(rc == -1);
|
assert_true(rc == -1);
|
||||||
|
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_rsa_import_privkey_base64(void **state)
|
static void torture_pki_rsa_import_privkey_base64(void **state)
|
||||||
@@ -160,7 +160,7 @@ static void torture_pki_rsa_import_privkey_base64(void **state)
|
|||||||
assert_true(rc == 1);
|
assert_true(rc == 1);
|
||||||
|
|
||||||
free(key_str);
|
free(key_str);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_rsa_publickey_from_privatekey(void **state)
|
static void torture_pki_rsa_publickey_from_privatekey(void **state)
|
||||||
@@ -185,8 +185,8 @@ static void torture_pki_rsa_publickey_from_privatekey(void **state)
|
|||||||
rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey);
|
rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey);
|
||||||
assert_true(rc == SSH_OK);
|
assert_true(rc == SSH_OK);
|
||||||
|
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_rsa_copy_cert_to_privkey(void **state)
|
static void torture_pki_rsa_copy_cert_to_privkey(void **state)
|
||||||
@@ -239,9 +239,9 @@ static void torture_pki_rsa_copy_cert_to_privkey(void **state)
|
|||||||
rc = ssh_pki_copy_cert_to_privkey(cert, privkey);
|
rc = ssh_pki_copy_cert_to_privkey(cert, privkey);
|
||||||
assert_true(rc == SSH_ERROR);
|
assert_true(rc == SSH_ERROR);
|
||||||
|
|
||||||
ssh_key_free(cert);
|
SSH_KEY_FREE(cert);
|
||||||
ssh_key_free(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_rsa_import_cert_file(void **state) {
|
static void torture_pki_rsa_import_cert_file(void **state) {
|
||||||
@@ -260,7 +260,7 @@ static void torture_pki_rsa_import_cert_file(void **state) {
|
|||||||
rc = ssh_key_is_public(cert);
|
rc = ssh_key_is_public(cert);
|
||||||
assert_true(rc == 1);
|
assert_true(rc == 1);
|
||||||
|
|
||||||
ssh_key_free(cert);
|
SSH_KEY_FREE(cert);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_rsa_publickey_base64(void **state)
|
static void torture_pki_rsa_publickey_base64(void **state)
|
||||||
@@ -297,7 +297,7 @@ static void torture_pki_rsa_publickey_base64(void **state)
|
|||||||
|
|
||||||
free(b64_key);
|
free(b64_key);
|
||||||
free(key_buf);
|
free(key_buf);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_rsa_generate_pubkey_from_privkey(void **state) {
|
static void torture_pki_rsa_generate_pubkey_from_privkey(void **state) {
|
||||||
@@ -335,8 +335,8 @@ static void torture_pki_rsa_generate_pubkey_from_privkey(void **state) {
|
|||||||
pubkey_generated,
|
pubkey_generated,
|
||||||
len);
|
len);
|
||||||
|
|
||||||
ssh_key_free(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_rsa_duplicate_key(void **state)
|
static void torture_pki_rsa_duplicate_key(void **state)
|
||||||
@@ -356,7 +356,7 @@ static void torture_pki_rsa_duplicate_key(void **state)
|
|||||||
|
|
||||||
rc = ssh_pki_export_pubkey_base64(pubkey, &b64_key);
|
rc = ssh_pki_export_pubkey_base64(pubkey, &b64_key);
|
||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
|
|
||||||
rc = ssh_pki_import_privkey_file(LIBSSH_RSA_TESTKEY,
|
rc = ssh_pki_import_privkey_file(LIBSSH_RSA_TESTKEY,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -382,11 +382,11 @@ static void torture_pki_rsa_duplicate_key(void **state)
|
|||||||
rc = ssh_key_cmp(privkey, privkey_dup, SSH_KEY_CMP_PRIVATE);
|
rc = ssh_key_cmp(privkey, privkey_dup, SSH_KEY_CMP_PRIVATE);
|
||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
|
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
ssh_key_free(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
ssh_key_free(privkey_dup);
|
SSH_KEY_FREE(privkey_dup);
|
||||||
ssh_string_free_char(b64_key);
|
SSH_STRING_FREE_CHAR(b64_key);
|
||||||
ssh_string_free_char(b64_key_gen);
|
SSH_STRING_FREE_CHAR(b64_key_gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_rsa_generate_key(void **state)
|
static void torture_pki_rsa_generate_key(void **state)
|
||||||
@@ -405,7 +405,7 @@ static void torture_pki_rsa_generate_key(void **state)
|
|||||||
rc = pki_signature_verify(session,sign,key,RSA_HASH,20);
|
rc = pki_signature_verify(session,sign,key,RSA_HASH,20);
|
||||||
assert_true(rc == SSH_OK);
|
assert_true(rc == SSH_OK);
|
||||||
ssh_signature_free(sign);
|
ssh_signature_free(sign);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key=NULL;
|
key=NULL;
|
||||||
|
|
||||||
rc = ssh_pki_generate(SSH_KEYTYPE_RSA, 2048, &key);
|
rc = ssh_pki_generate(SSH_KEYTYPE_RSA, 2048, &key);
|
||||||
@@ -416,7 +416,7 @@ static void torture_pki_rsa_generate_key(void **state)
|
|||||||
rc = pki_signature_verify(session,sign,key,RSA_HASH,20);
|
rc = pki_signature_verify(session,sign,key,RSA_HASH,20);
|
||||||
assert_true(rc == SSH_OK);
|
assert_true(rc == SSH_OK);
|
||||||
ssh_signature_free(sign);
|
ssh_signature_free(sign);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key=NULL;
|
key=NULL;
|
||||||
|
|
||||||
rc = ssh_pki_generate(SSH_KEYTYPE_RSA, 4096, &key);
|
rc = ssh_pki_generate(SSH_KEYTYPE_RSA, 4096, &key);
|
||||||
@@ -427,7 +427,7 @@ static void torture_pki_rsa_generate_key(void **state)
|
|||||||
rc = pki_signature_verify(session,sign,key,RSA_HASH,20);
|
rc = pki_signature_verify(session,sign,key,RSA_HASH,20);
|
||||||
assert_true(rc == SSH_OK);
|
assert_true(rc == SSH_OK);
|
||||||
ssh_signature_free(sign);
|
ssh_signature_free(sign);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key=NULL;
|
key=NULL;
|
||||||
|
|
||||||
ssh_free(session);
|
ssh_free(session);
|
||||||
@@ -477,7 +477,7 @@ static void torture_pki_rsa_sha2(void **state)
|
|||||||
ssh_signature_free(sign);
|
ssh_signature_free(sign);
|
||||||
|
|
||||||
/* Cleanup */
|
/* Cleanup */
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
ssh_free(session);
|
ssh_free(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,8 +518,8 @@ static void torture_pki_rsa_write_privkey(void **state)
|
|||||||
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
|
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
|
||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
|
|
||||||
ssh_key_free(origkey);
|
SSH_KEY_FREE(origkey);
|
||||||
ssh_key_free(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
|
|
||||||
/* Test with passphrase */
|
/* Test with passphrase */
|
||||||
rc = ssh_pki_import_privkey_file(LIBSSH_RSA_TESTKEY_PASSPHRASE,
|
rc = ssh_pki_import_privkey_file(LIBSSH_RSA_TESTKEY_PASSPHRASE,
|
||||||
@@ -557,8 +557,8 @@ static void torture_pki_rsa_write_privkey(void **state)
|
|||||||
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
|
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
|
||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
|
|
||||||
ssh_key_free(origkey);
|
SSH_KEY_FREE(origkey);
|
||||||
ssh_key_free(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
}
|
}
|
||||||
#endif /* HAVE_LIBCRYPTO */
|
#endif /* HAVE_LIBCRYPTO */
|
||||||
|
|
||||||
@@ -581,8 +581,7 @@ static void torture_pki_rsa_import_privkey_base64_passphrase(void **state)
|
|||||||
rc = ssh_key_is_private(key);
|
rc = ssh_key_is_private(key);
|
||||||
assert_true(rc == 1);
|
assert_true(rc == 1);
|
||||||
|
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key = NULL;
|
|
||||||
|
|
||||||
/* test if it returns -1 if passphrase is wrong */
|
/* test if it returns -1 if passphrase is wrong */
|
||||||
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_RSA, 0, 1),
|
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_RSA, 0, 1),
|
||||||
@@ -591,8 +590,7 @@ static void torture_pki_rsa_import_privkey_base64_passphrase(void **state)
|
|||||||
NULL,
|
NULL,
|
||||||
&key);
|
&key);
|
||||||
assert_true(rc == -1);
|
assert_true(rc == -1);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key = NULL;
|
|
||||||
|
|
||||||
#ifndef HAVE_LIBCRYPTO
|
#ifndef HAVE_LIBCRYPTO
|
||||||
/* test if it returns -1 if passphrase is NULL */
|
/* test if it returns -1 if passphrase is NULL */
|
||||||
@@ -603,8 +601,7 @@ static void torture_pki_rsa_import_privkey_base64_passphrase(void **state)
|
|||||||
NULL,
|
NULL,
|
||||||
&key);
|
&key);
|
||||||
assert_true(rc == -1);
|
assert_true(rc == -1);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key = NULL;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -631,8 +628,7 @@ torture_pki_rsa_import_openssh_privkey_base64_passphrase(void **state)
|
|||||||
rc = ssh_key_is_private(key);
|
rc = ssh_key_is_private(key);
|
||||||
assert_true(rc == 1);
|
assert_true(rc == 1);
|
||||||
|
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key = NULL;
|
|
||||||
|
|
||||||
/* test if it returns -1 if passphrase is wrong */
|
/* test if it returns -1 if passphrase is wrong */
|
||||||
rc = ssh_pki_import_privkey_base64(keystring,
|
rc = ssh_pki_import_privkey_base64(keystring,
|
||||||
@@ -641,8 +637,7 @@ torture_pki_rsa_import_openssh_privkey_base64_passphrase(void **state)
|
|||||||
NULL,
|
NULL,
|
||||||
&key);
|
&key);
|
||||||
assert_true(rc == -1);
|
assert_true(rc == -1);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key = NULL;
|
|
||||||
|
|
||||||
/* test if it returns -1 if passphrase is NULL */
|
/* test if it returns -1 if passphrase is NULL */
|
||||||
/* libcrypto asks for a passphrase, so skip this test */
|
/* libcrypto asks for a passphrase, so skip this test */
|
||||||
@@ -652,8 +647,7 @@ torture_pki_rsa_import_openssh_privkey_base64_passphrase(void **state)
|
|||||||
NULL,
|
NULL,
|
||||||
&key);
|
&key);
|
||||||
assert_true(rc == -1);
|
assert_true(rc == -1);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int torture_run_tests(void) {
|
int torture_run_tests(void) {
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ static void *thread_growing_buffer(void *threadid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Teardown */
|
/* Teardown */
|
||||||
ssh_buffer_free(buffer);
|
SSH_BUFFER_FREE(buffer);
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,14 +134,14 @@ static void *thread_growing_buffer_shifting(void *threadid)
|
|||||||
if (ssh_buffer_get_len(buffer) * 4 < buffer->allocated) {
|
if (ssh_buffer_get_len(buffer) * 4 < buffer->allocated) {
|
||||||
assert_true(ssh_buffer_get_len(buffer) * 4 >= buffer->allocated);
|
assert_true(ssh_buffer_get_len(buffer) * 4 >= buffer->allocated);
|
||||||
/* Teardown */
|
/* Teardown */
|
||||||
ssh_buffer_free(buffer);
|
SSH_BUFFER_FREE(buffer);
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Teardown */
|
/* Teardown */
|
||||||
ssh_buffer_free(buffer);
|
SSH_BUFFER_FREE(buffer);
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,7 +198,7 @@ static void *thread_buffer_prepend(void *threadid)
|
|||||||
assert_memory_equal(ssh_buffer_get(buffer), "12345bcdef", 10);
|
assert_memory_equal(ssh_buffer_get(buffer), "12345bcdef", 10);
|
||||||
|
|
||||||
/* Teardown */
|
/* Teardown */
|
||||||
ssh_buffer_free(buffer);
|
SSH_BUFFER_FREE(buffer);
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,9 +247,9 @@ static void *thread_ssh_buffer_get_ssh_string(void *threadid)
|
|||||||
for (l = 0; l < k; ++l) {
|
for (l = 0; l < k; ++l) {
|
||||||
ssh_string str = ssh_buffer_get_ssh_string(buffer);
|
ssh_string str = ssh_buffer_get_ssh_string(buffer);
|
||||||
assert_null(str);
|
assert_null(str);
|
||||||
ssh_string_free(str);
|
SSH_STRING_FREE(str);
|
||||||
}
|
}
|
||||||
ssh_buffer_free(buffer);
|
SSH_BUFFER_FREE(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -316,10 +316,10 @@ static void *thread_ssh_buffer_add_format(void *threadid)
|
|||||||
assert_int_equal(len, sizeof(verif) - 1);
|
assert_int_equal(len, sizeof(verif) - 1);
|
||||||
assert_memory_equal(ssh_buffer_get(buffer), verif, sizeof(verif) -1);
|
assert_memory_equal(ssh_buffer_get(buffer), verif, sizeof(verif) -1);
|
||||||
|
|
||||||
ssh_string_free(s);
|
SSH_STRING_FREE(s);
|
||||||
|
|
||||||
/* Teardown */
|
/* Teardown */
|
||||||
ssh_buffer_free(buffer);
|
SSH_BUFFER_FREE(buffer);
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,7 +397,7 @@ static void *thread_ssh_buffer_get_format(void *threadid) {
|
|||||||
SAFE_FREE(s2);
|
SAFE_FREE(s2);
|
||||||
|
|
||||||
/* Teardown */
|
/* Teardown */
|
||||||
ssh_buffer_free(buffer);
|
SSH_BUFFER_FREE(buffer);
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,7 +458,7 @@ static void *thread_ssh_buffer_get_format_error(void *threadid)
|
|||||||
assert_true(s2 == NULL);
|
assert_true(s2 == NULL);
|
||||||
|
|
||||||
/* Teardown */
|
/* Teardown */
|
||||||
ssh_buffer_free(buffer);
|
SSH_BUFFER_FREE(buffer);
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -514,7 +514,7 @@ static void *thread_buffer_pack_badformat(void *threadid)
|
|||||||
* it could crash the process */
|
* it could crash the process */
|
||||||
|
|
||||||
/* Teardown */
|
/* Teardown */
|
||||||
ssh_buffer_free(buffer);
|
SSH_BUFFER_FREE(buffer);
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ static void *thread_pki_rsa_import_pubkey_file(void *threadid)
|
|||||||
assert_return_code(rc, errno);
|
assert_return_code(rc, errno);
|
||||||
assert_non_null(pubkey);
|
assert_non_null(pubkey);
|
||||||
|
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
|
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
@@ -201,7 +201,7 @@ static void *thread_pki_rsa_import_privkey_base64_NULL_str(void *threadid)
|
|||||||
rc = ssh_pki_import_privkey_base64(NULL, passphrase, NULL, NULL, &key);
|
rc = ssh_pki_import_privkey_base64(NULL, passphrase, NULL, NULL, &key);
|
||||||
assert_true(rc == -1);
|
assert_true(rc == -1);
|
||||||
|
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,7 +242,7 @@ static void *thread_pki_rsa_import_privkey_base64(void *threadid)
|
|||||||
assert_true(ok);
|
assert_true(ok);
|
||||||
|
|
||||||
free(key_str);
|
free(key_str);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
|
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
@@ -283,8 +283,8 @@ static void *thread_pki_rsa_publickey_from_privatekey(void *threadid)
|
|||||||
assert_true(rc == SSH_OK);
|
assert_true(rc == SSH_OK);
|
||||||
assert_non_null(pubkey);
|
assert_non_null(pubkey);
|
||||||
|
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,9 +349,9 @@ static void *thread_pki_rsa_copy_cert_to_privkey(void *threadid)
|
|||||||
rc = ssh_pki_copy_cert_to_privkey(cert, privkey);
|
rc = ssh_pki_copy_cert_to_privkey(cert, privkey);
|
||||||
assert_true(rc == SSH_ERROR);
|
assert_true(rc == SSH_ERROR);
|
||||||
|
|
||||||
ssh_key_free(cert);
|
SSH_KEY_FREE(cert);
|
||||||
ssh_key_free(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,7 +383,7 @@ static void *thread_pki_rsa_import_cert_file(void *threadid)
|
|||||||
rc = ssh_key_is_public(cert);
|
rc = ssh_key_is_public(cert);
|
||||||
assert_true(rc == 1);
|
assert_true(rc == 1);
|
||||||
|
|
||||||
ssh_key_free(cert);
|
SSH_KEY_FREE(cert);
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,7 +432,7 @@ static void *thread_pki_rsa_publickey_base64(void *threadid)
|
|||||||
|
|
||||||
free(b64_key);
|
free(b64_key);
|
||||||
free(key_buf);
|
free(key_buf);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,7 +464,7 @@ static void *thread_pki_rsa_duplicate_key(void *threadid)
|
|||||||
|
|
||||||
rc = ssh_pki_export_pubkey_base64(pubkey, &b64_key);
|
rc = ssh_pki_export_pubkey_base64(pubkey, &b64_key);
|
||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
|
|
||||||
rc = ssh_pki_import_privkey_file(LIBSSH_RSA_TESTKEY,
|
rc = ssh_pki_import_privkey_file(LIBSSH_RSA_TESTKEY,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -489,11 +489,11 @@ static void *thread_pki_rsa_duplicate_key(void *threadid)
|
|||||||
cmp = ssh_key_cmp(privkey, privkey_dup, SSH_KEY_CMP_PRIVATE);
|
cmp = ssh_key_cmp(privkey, privkey_dup, SSH_KEY_CMP_PRIVATE);
|
||||||
assert_true(cmp == 0);
|
assert_true(cmp == 0);
|
||||||
|
|
||||||
ssh_key_free(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
ssh_key_free(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
ssh_key_free(privkey_dup);
|
SSH_KEY_FREE(privkey_dup);
|
||||||
ssh_string_free_char(b64_key);
|
SSH_STRING_FREE_CHAR(b64_key);
|
||||||
ssh_string_free_char(b64_key_gen);
|
SSH_STRING_FREE_CHAR(b64_key_gen);
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,8 +531,7 @@ static void *thread_pki_rsa_generate_key(void *threadid)
|
|||||||
assert_ssh_return_code(session, rc);
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
ssh_signature_free(sign);
|
ssh_signature_free(sign);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key = NULL;
|
|
||||||
|
|
||||||
rc = ssh_pki_generate(SSH_KEYTYPE_RSA, 2048, &key);
|
rc = ssh_pki_generate(SSH_KEYTYPE_RSA, 2048, &key);
|
||||||
assert_ssh_return_code(session, rc);
|
assert_ssh_return_code(session, rc);
|
||||||
@@ -545,8 +544,7 @@ static void *thread_pki_rsa_generate_key(void *threadid)
|
|||||||
assert_ssh_return_code(session, rc);
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
ssh_signature_free(sign);
|
ssh_signature_free(sign);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
rc = ssh_pki_generate(SSH_KEYTYPE_RSA, 4096, &key);
|
rc = ssh_pki_generate(SSH_KEYTYPE_RSA, 4096, &key);
|
||||||
@@ -560,7 +558,7 @@ static void *thread_pki_rsa_generate_key(void *threadid)
|
|||||||
assert_true(rc == SSH_OK);
|
assert_true(rc == SSH_OK);
|
||||||
|
|
||||||
ssh_signature_free(sign);
|
ssh_signature_free(sign);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key = NULL;
|
key = NULL;
|
||||||
|
|
||||||
ssh_free(session);
|
ssh_free(session);
|
||||||
@@ -596,8 +594,7 @@ static void *thread_pki_rsa_import_privkey_base64_passphrase(void *threadid)
|
|||||||
rc = ssh_key_is_private(key);
|
rc = ssh_key_is_private(key);
|
||||||
assert_true(rc == 1);
|
assert_true(rc == 1);
|
||||||
|
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key = NULL;
|
|
||||||
|
|
||||||
/* test if it returns -1 if passphrase is wrong */
|
/* test if it returns -1 if passphrase is wrong */
|
||||||
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_RSA, 0, 1),
|
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_RSA, 0, 1),
|
||||||
@@ -606,8 +603,7 @@ static void *thread_pki_rsa_import_privkey_base64_passphrase(void *threadid)
|
|||||||
NULL,
|
NULL,
|
||||||
&key);
|
&key);
|
||||||
assert_true(rc == -1);
|
assert_true(rc == -1);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key = NULL;
|
|
||||||
|
|
||||||
#ifndef HAVE_LIBCRYPTO
|
#ifndef HAVE_LIBCRYPTO
|
||||||
/* test if it returns -1 if passphrase is NULL */
|
/* test if it returns -1 if passphrase is NULL */
|
||||||
@@ -618,8 +614,7 @@ static void *thread_pki_rsa_import_privkey_base64_passphrase(void *threadid)
|
|||||||
NULL,
|
NULL,
|
||||||
&key);
|
&key);
|
||||||
assert_true(rc == -1);
|
assert_true(rc == -1);
|
||||||
ssh_key_free(key);
|
SSH_KEY_FREE(key);
|
||||||
key = NULL;
|
|
||||||
#endif
|
#endif
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user