mirror of
https://github.com/tmate-io/tmate.git
synced 2024-11-27 10:33:09 +01:00
Update libssh
This commit is contained in:
parent
8a87170c8a
commit
bb5634ce20
@ -109,7 +109,9 @@ install(
|
|||||||
# in tree build settings
|
# in tree build settings
|
||||||
configure_file(libssh-build-tree-settings.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libssh-build-tree-settings.cmake @ONLY)
|
configure_file(libssh-build-tree-settings.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libssh-build-tree-settings.cmake @ONLY)
|
||||||
|
|
||||||
|
if (WITH_EXAMPLES)
|
||||||
add_subdirectory(examples)
|
add_subdirectory(examples)
|
||||||
|
endif (WITH_EXAMPLES)
|
||||||
|
|
||||||
if (WITH_TESTING)
|
if (WITH_TESTING)
|
||||||
find_package(CMocka REQUIRED)
|
find_package(CMocka REQUIRED)
|
||||||
|
@ -12,6 +12,7 @@ option(WITH_INTERNAL_DOC "Compile doxygen internal documentation" OFF)
|
|||||||
option(WITH_TESTING "Build with unit tests" OFF)
|
option(WITH_TESTING "Build with unit tests" OFF)
|
||||||
option(WITH_CLIENT_TESTING "Build with client tests; requires a running sshd" OFF)
|
option(WITH_CLIENT_TESTING "Build with client tests; requires a running sshd" OFF)
|
||||||
option(WITH_BENCHMARKS "Build benchmarks tools" OFF)
|
option(WITH_BENCHMARKS "Build benchmarks tools" OFF)
|
||||||
|
option(WITH_EXAMPLES "Build examples" ON)
|
||||||
|
|
||||||
if (WITH_ZLIB)
|
if (WITH_ZLIB)
|
||||||
set(WITH_LIBZ ON)
|
set(WITH_LIBZ ON)
|
||||||
|
119
libssh/doc/curve25519-sha256@libssh.org.txt
Normal file
119
libssh/doc/curve25519-sha256@libssh.org.txt
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
curve25519-sha256@libssh.org.txt Aris Adamantiadis <aris@badcode.be>
|
||||||
|
21/9/2013
|
||||||
|
|
||||||
|
1. Introduction
|
||||||
|
|
||||||
|
This document describes the key exchange methode curve25519-sha256@libssh.org
|
||||||
|
for SSH version 2 protocol. It is provided as an alternative to the existing
|
||||||
|
key exchange mechanisms based on either Diffie-Hellman or Elliptic Curve Diffie-
|
||||||
|
Hellman [RFC5656].
|
||||||
|
The reason is the following : During summer of 2013, revelations from ex-
|
||||||
|
consultant at NSA Edward Snowden gave proof that NSA willingly inserts backdoors
|
||||||
|
into softwares, hardware components and published standards. While it is still
|
||||||
|
believed that the mathematics behind ECC cryptography are still sound and solid,
|
||||||
|
some people (including Bruce Schneier [SCHNEIER]), showed their lack of confidence
|
||||||
|
in NIST-published curves such as nistp256, nistp384, nistp521, for which constant
|
||||||
|
parameters (including the generator point) are defined without explanation. It
|
||||||
|
is also believed that NSA had a word to say in their definition. These curves
|
||||||
|
are not the most secure or fastest possible for their key sizes [DJB], and
|
||||||
|
researchers think it is possible that NSA have ways of cracking NIST curves.
|
||||||
|
It is also interesting to note that SSH belongs to the list of protocols the NSA
|
||||||
|
claims to be able to eavesdrop. Having a secure replacement would make passive
|
||||||
|
attacks much harder if such a backdoor exists.
|
||||||
|
|
||||||
|
However an alternative exists in the form of Curve25519. This algorithm has been
|
||||||
|
proposed in 2006 by DJB [Curve25519]. Its main stengths are its speed, its
|
||||||
|
constant-time run time (and resistance against side-channel attacks), and its
|
||||||
|
lack of nebulous hard-coded constants.
|
||||||
|
|
||||||
|
The reference version being used in this document is the one described in
|
||||||
|
[Curve25519] as implemented in the library NaCl [NaCl].
|
||||||
|
This document does not attempts to provide alternatives to the ecdsa-sha1-*
|
||||||
|
authentication keys.
|
||||||
|
|
||||||
|
2. Key exchange
|
||||||
|
|
||||||
|
The key exchange procedure is very similar to the one described chapter 4 of
|
||||||
|
[RFC5656]. Public ephemeral keys are transmitted over SSH encapsulated into
|
||||||
|
standard SSH strings.
|
||||||
|
|
||||||
|
The following is an overview of the key exchange process:
|
||||||
|
|
||||||
|
Client Server
|
||||||
|
------ ------
|
||||||
|
Generate ephemeral key pair.
|
||||||
|
SSH_MSG_KEX_ECDH_INIT -------->
|
||||||
|
Verify that client public key
|
||||||
|
length is 32 bytes.
|
||||||
|
Generate ephemeral key pair.
|
||||||
|
Compute shared secret.
|
||||||
|
Generate and sign exchange hash.
|
||||||
|
<-------- SSH_MSG_KEX_ECDH_REPLY
|
||||||
|
Verify that server public key length is 32 bytes.
|
||||||
|
* Verify host keys belong to server.
|
||||||
|
Compute shared secret.
|
||||||
|
Generate exchange hash.
|
||||||
|
Verify server's signature.
|
||||||
|
|
||||||
|
* Optional but strongly recommanded as this protects against MITM attacks.
|
||||||
|
|
||||||
|
This is implemented using the same messages as described in RFC5656 chapter 4
|
||||||
|
|
||||||
|
3. Method Name
|
||||||
|
|
||||||
|
The name of this key exchange method is "curve25519-sha256@libssh.org".
|
||||||
|
|
||||||
|
4. Implementation considerations
|
||||||
|
|
||||||
|
The whole method is based on the curve25519 scalar multiplication. In this
|
||||||
|
method, a private key is a scalar of 256 bits, and a public key is a point
|
||||||
|
of 256 bits.
|
||||||
|
|
||||||
|
4.1. Private key generation
|
||||||
|
|
||||||
|
A 32 bytes private key should be generated for each new connection,
|
||||||
|
using a secure PRNG. The following actions must be done on the private key:
|
||||||
|
mysecret[0] &= 248;
|
||||||
|
mysecret[31] &= 127;
|
||||||
|
mysecret[31] |= 64;
|
||||||
|
In order to keep the key valid. However, many cryptographic libraries will do
|
||||||
|
this automatically.
|
||||||
|
It should be noted that, in opposition to NIST curves, no special validation
|
||||||
|
should be done to ensure the result is a valid and secure private key.
|
||||||
|
|
||||||
|
4.2 Public key generation
|
||||||
|
|
||||||
|
The 32 bytes public key of either a client or a server must be generated using
|
||||||
|
the 32 bytes private key and a common generator base. This base is defined as 9
|
||||||
|
followed by all zeroes:
|
||||||
|
const unsigned char basepoint[32] = {9};
|
||||||
|
|
||||||
|
The public key is calculated using the cryptographic scalar multiplication:
|
||||||
|
const unsigned char privkey[32];
|
||||||
|
unsigned char pubkey[32];
|
||||||
|
crypto_scalarmult (pubkey, privkey, basepoint);
|
||||||
|
However some cryptographic libraries may provide a combined function:
|
||||||
|
crypto_scalarmult_base (pubkey, privkey);
|
||||||
|
|
||||||
|
It should be noted that, in opposition to NIST curves, no special validation
|
||||||
|
should be done to ensure the received public keys are valid curves point. The
|
||||||
|
Curve25519 algorithm ensure that every possible public key maps to a valid
|
||||||
|
ECC Point.
|
||||||
|
|
||||||
|
4.3 Shared secret generation
|
||||||
|
|
||||||
|
The shared secret, k, is defined in SSH specifications to be a big integer.
|
||||||
|
This number is calculated using the following procedure:
|
||||||
|
|
||||||
|
X is the 32 bytes point obtained by the scalar multiplication of the other
|
||||||
|
side's public key and the local private key scalar.
|
||||||
|
|
||||||
|
The whole 32 bytes of the number X are then converted into a big integer k.
|
||||||
|
This conversion follows the network byte order. This step differs from
|
||||||
|
RFC5656.
|
||||||
|
|
||||||
|
[RFC5656] http://tools.ietf.org/html/rfc5656
|
||||||
|
[SCHNEIER] https://www.schneier.com/blog/archives/2013/09/the_nsa_is_brea.html#c1675929
|
||||||
|
[DJB] http://cr.yp.to/talks/2013.05.31/slides-dan+tanja-20130531-4x3.pdf
|
||||||
|
[Curve25519] "Curve25519: new Diffie-Hellman speed records."
|
||||||
|
http://cr.yp.to/ecdh/curve25519-20060209.pdf
|
@ -788,12 +788,17 @@ struct ssh_threads_callbacks_struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief sets the thread callbacks necessary if your program is using
|
* @brief Set the thread callbacks structure.
|
||||||
* libssh in a multithreaded fashion. This function must be called first,
|
*
|
||||||
* outside of any threading context (in your main() for instance), before
|
* This is necessary if your program is using libssh in a multithreaded fashion.
|
||||||
* ssh_init().
|
* This function must be called first, outside of any threading context (in your
|
||||||
* @param cb pointer to a ssh_threads_callbacks_struct structure, which contains
|
* main() function for instance), before you call ssh_init().
|
||||||
* the different callbacks to be set.
|
*
|
||||||
|
* @param[in] cb A pointer to a ssh_threads_callbacks_struct structure, which
|
||||||
|
* contains the different callbacks to be set.
|
||||||
|
*
|
||||||
|
* @returns Always returns SSH_OK.
|
||||||
|
*
|
||||||
* @see ssh_threads_callbacks_struct
|
* @see ssh_threads_callbacks_struct
|
||||||
* @see SSH_THREADS_PTHREAD
|
* @see SSH_THREADS_PTHREAD
|
||||||
*/
|
*/
|
||||||
@ -809,9 +814,13 @@ LIBSSH_API int ssh_threads_set_callbacks(struct ssh_threads_callbacks_struct
|
|||||||
LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_pthread(void);
|
LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_pthread(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief returns a pointer on the noop threads callbacks, to be used with
|
* @brief Get the noop threads callbacks structure
|
||||||
* ssh_threads_set_callbacks. These callbacks do nothing and are being used by
|
*
|
||||||
* default.
|
* This can be used with ssh_threads_set_callbacks. These callbacks do nothing
|
||||||
|
* and are being used by default.
|
||||||
|
*
|
||||||
|
* @return Always returns a valid pointer to the noop callbacks structure.
|
||||||
|
*
|
||||||
* @see ssh_threads_set_callbacks
|
* @see ssh_threads_set_callbacks
|
||||||
*/
|
*/
|
||||||
LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_noop(void);
|
LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_noop(void);
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "libssh/ecdh.h"
|
#include "libssh/ecdh.h"
|
||||||
#include "libssh/kex.h"
|
#include "libssh/kex.h"
|
||||||
|
#include "libssh/curve25519.h"
|
||||||
|
|
||||||
enum ssh_key_exchange_e {
|
enum ssh_key_exchange_e {
|
||||||
/* diffie-hellman-group1-sha1 */
|
/* diffie-hellman-group1-sha1 */
|
||||||
@ -51,7 +52,9 @@ enum ssh_key_exchange_e {
|
|||||||
/* diffie-hellman-group14-sha1 */
|
/* diffie-hellman-group14-sha1 */
|
||||||
SSH_KEX_DH_GROUP14_SHA1,
|
SSH_KEX_DH_GROUP14_SHA1,
|
||||||
/* ecdh-sha2-nistp256 */
|
/* ecdh-sha2-nistp256 */
|
||||||
SSH_KEX_ECDH_SHA2_NISTP256
|
SSH_KEX_ECDH_SHA2_NISTP256,
|
||||||
|
/* curve25519-sha256@libssh.org */
|
||||||
|
SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ssh_crypto_struct {
|
struct ssh_crypto_struct {
|
||||||
@ -60,6 +63,11 @@ struct ssh_crypto_struct {
|
|||||||
EC_KEY *ecdh_privkey;
|
EC_KEY *ecdh_privkey;
|
||||||
ssh_string ecdh_client_pubkey;
|
ssh_string ecdh_client_pubkey;
|
||||||
ssh_string ecdh_server_pubkey;
|
ssh_string ecdh_server_pubkey;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CURVE25519
|
||||||
|
ssh_curve25519_privkey curve25519_privkey;
|
||||||
|
ssh_curve25519_pubkey curve25519_client_pubkey;
|
||||||
|
ssh_curve25519_pubkey curve25519_server_pubkey;
|
||||||
#endif
|
#endif
|
||||||
ssh_string dh_server_signature; /* information used by dh_handshake. */
|
ssh_string dh_server_signature; /* information used by dh_handshake. */
|
||||||
size_t digest_len; /* len of all the fields below */
|
size_t digest_len; /* len of all the fields below */
|
||||||
|
46
libssh/include/libssh/curve25519.h
Normal file
46
libssh/include/libssh/curve25519.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the SSH Library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 by Aris Adamantiadis <aris@badcode.be>
|
||||||
|
*
|
||||||
|
* This 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,
|
||||||
|
* version 2.1 of the License.
|
||||||
|
*
|
||||||
|
* This 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 this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CURVE25519_H_
|
||||||
|
#define CURVE25519_H_
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "libssh.h"
|
||||||
|
|
||||||
|
#ifdef WITH_NACL
|
||||||
|
|
||||||
|
#define HAVE_CURVE25519
|
||||||
|
#include <nacl/crypto_scalarmult_curve25519.h>
|
||||||
|
#define CURVE25519_PUBKEY_SIZE crypto_scalarmult_curve25519_BYTES
|
||||||
|
#define CURVE25519_PRIVKEY_SIZE crypto_scalarmult_curve25519_SCALARBYTES
|
||||||
|
|
||||||
|
typedef unsigned char ssh_curve25519_pubkey[CURVE25519_PUBKEY_SIZE];
|
||||||
|
typedef unsigned char ssh_curve25519_privkey[CURVE25519_PRIVKEY_SIZE];
|
||||||
|
|
||||||
|
#endif /* WITH_NACL */
|
||||||
|
|
||||||
|
int ssh_client_curve25519_init(ssh_session session);
|
||||||
|
int ssh_client_curve25519_reply(ssh_session session, ssh_buffer packet);
|
||||||
|
|
||||||
|
#ifdef WITH_SERVER
|
||||||
|
int ssh_server_curve25519_init(ssh_session session, ssh_buffer packet);
|
||||||
|
#endif /* WITH_SERVER */
|
||||||
|
|
||||||
|
#endif /* CURVE25519_H_ */
|
@ -97,9 +97,6 @@ struct ssh_session_struct {
|
|||||||
int openssh;
|
int openssh;
|
||||||
uint32_t send_seq;
|
uint32_t send_seq;
|
||||||
uint32_t recv_seq;
|
uint32_t recv_seq;
|
||||||
/* status flags */
|
|
||||||
int closed;
|
|
||||||
int closed_by_except;
|
|
||||||
|
|
||||||
int connected;
|
int connected;
|
||||||
/* !=0 when the user got a session handle */
|
/* !=0 when the user got a session handle */
|
||||||
|
@ -76,6 +76,18 @@ if (WITH_GSSAPI AND GSSAPI_FOUND)
|
|||||||
)
|
)
|
||||||
endif (WITH_GSSAPI AND GSSAPI_FOUND)
|
endif (WITH_GSSAPI AND GSSAPI_FOUND)
|
||||||
|
|
||||||
|
if (WITH_NACL AND NACL_FOUND)
|
||||||
|
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||||
|
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
||||||
|
${NACL_INCLUDE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
set(LIBSSH_LINK_LIBRARIES
|
||||||
|
${LIBSSH_LINK_LIBRARIES}
|
||||||
|
${NACL_LIBRARY}
|
||||||
|
)
|
||||||
|
endif (WITH_NACL AND NACL_FOUND)
|
||||||
|
|
||||||
set(LIBSSH_LINK_LIBRARIES
|
set(LIBSSH_LINK_LIBRARIES
|
||||||
${LIBSSH_LINK_LIBRARIES}
|
${LIBSSH_LINK_LIBRARIES}
|
||||||
CACHE INTERNAL "libssh link libraries"
|
CACHE INTERNAL "libssh link libraries"
|
||||||
@ -192,6 +204,13 @@ if (WITH_GSSAPI AND GSSAPI_FOUND)
|
|||||||
)
|
)
|
||||||
endif (WITH_GSSAPI AND GSSAPI_FOUND)
|
endif (WITH_GSSAPI AND GSSAPI_FOUND)
|
||||||
|
|
||||||
|
if (WITH_NACL)
|
||||||
|
set(libssh_SRCS
|
||||||
|
${libssh_SRCS}
|
||||||
|
curve25519.c
|
||||||
|
)
|
||||||
|
endif (WITH_NACL)
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${LIBSSH_PUBLIC_INCLUDE_DIRS}
|
${LIBSSH_PUBLIC_INCLUDE_DIRS}
|
||||||
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
||||||
|
@ -312,7 +312,11 @@ static int channel_open(ssh_channel channel, const char *type_c, int window,
|
|||||||
type_c, channel->local_channel);
|
type_c, channel->local_channel);
|
||||||
pending:
|
pending:
|
||||||
/* wait until channel is opened by server */
|
/* wait until channel is opened by server */
|
||||||
err = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER, ssh_channel_open_termination, channel);
|
err = ssh_handle_packets_termination(session,
|
||||||
|
SSH_TIMEOUT_DEFAULT,
|
||||||
|
ssh_channel_open_termination,
|
||||||
|
channel);
|
||||||
|
|
||||||
if (session->session_state == SSH_SESSION_STATE_ERROR)
|
if (session->session_state == SSH_SESSION_STATE_ERROR)
|
||||||
err = SSH_ERROR;
|
err = SSH_ERROR;
|
||||||
end:
|
end:
|
||||||
@ -1607,7 +1611,11 @@ static int channel_request(ssh_channel channel, const char *request,
|
|||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
pending:
|
pending:
|
||||||
rc = ssh_handle_packets_termination(session,SSH_TIMEOUT_USER, ssh_channel_request_termination, channel);
|
rc = ssh_handle_packets_termination(session,
|
||||||
|
SSH_TIMEOUT_DEFAULT,
|
||||||
|
ssh_channel_request_termination,
|
||||||
|
channel);
|
||||||
|
|
||||||
if(session->session_state == SSH_SESSION_STATE_ERROR || rc == SSH_ERROR) {
|
if(session->session_state == SSH_SESSION_STATE_ERROR || rc == SSH_ERROR) {
|
||||||
channel->request_state = SSH_CHANNEL_REQ_STATE_ERROR;
|
channel->request_state = SSH_CHANNEL_REQ_STATE_ERROR;
|
||||||
}
|
}
|
||||||
@ -1983,8 +1991,11 @@ static ssh_channel ssh_channel_accept(ssh_session session, int channeltype,
|
|||||||
struct ssh_iterator *iterator;
|
struct ssh_iterator *iterator;
|
||||||
int t;
|
int t;
|
||||||
|
|
||||||
for (t = timeout_ms; t >= 0; t -= 50)
|
/*
|
||||||
{
|
* We sleep for 50 ms in ssh_handle_packets() and later sleep for
|
||||||
|
* 50 ms. So we need to decrement by 100 ms.
|
||||||
|
*/
|
||||||
|
for (t = timeout_ms; t >= 0; t -= 100) {
|
||||||
ssh_handle_packets(session, 50);
|
ssh_handle_packets(session, 50);
|
||||||
|
|
||||||
if (session->ssh_message_list) {
|
if (session->ssh_message_list) {
|
||||||
@ -2145,8 +2156,11 @@ static int global_request(ssh_session session, const char *request,
|
|||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
pending:
|
pending:
|
||||||
rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER,
|
rc = ssh_handle_packets_termination(session,
|
||||||
ssh_global_request_termination, session);
|
SSH_TIMEOUT_DEFAULT,
|
||||||
|
ssh_global_request_termination,
|
||||||
|
session);
|
||||||
|
|
||||||
if(rc==SSH_ERROR || session->session_state == SSH_SESSION_STATE_ERROR){
|
if(rc==SSH_ERROR || session->session_state == SSH_SESSION_STATE_ERROR){
|
||||||
session->global_req_state = SSH_CHANNEL_REQ_STATE_ERROR;
|
session->global_req_state = SSH_CHANNEL_REQ_STATE_ERROR;
|
||||||
}
|
}
|
||||||
@ -2640,8 +2654,8 @@ static int ssh_channel_read_termination(void *s){
|
|||||||
* @param[in] is_stderr A boolean value to mark reading from the stderr flow.
|
* @param[in] is_stderr A boolean value to mark reading from the stderr flow.
|
||||||
*
|
*
|
||||||
* @return The number of bytes read, 0 on end of file or SSH_ERROR
|
* @return The number of bytes read, 0 on end of file or SSH_ERROR
|
||||||
* on error. Can return 0 if nothing is available in nonblocking
|
* on error. In nonblocking mode it Can return 0 if no data
|
||||||
* mode.
|
* is available or SSH_AGAIN.
|
||||||
*
|
*
|
||||||
* @warning This function may return less than count bytes of data, and won't
|
* @warning This function may return less than count bytes of data, and won't
|
||||||
* block until count bytes have been read.
|
* block until count bytes have been read.
|
||||||
@ -2924,8 +2938,10 @@ int ssh_channel_get_exit_status(ssh_channel channel) {
|
|||||||
if(channel == NULL) {
|
if(channel == NULL) {
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
rc = ssh_handle_packets_termination(channel->session, SSH_TIMEOUT_USER,
|
rc = ssh_handle_packets_termination(channel->session,
|
||||||
ssh_channel_exit_status_termination, channel);
|
SSH_TIMEOUT_DEFAULT,
|
||||||
|
ssh_channel_exit_status_termination,
|
||||||
|
channel);
|
||||||
if (rc == SSH_ERROR || channel->session->session_state ==
|
if (rc == SSH_ERROR || channel->session->session_state ==
|
||||||
SSH_SESSION_STATE_ERROR)
|
SSH_SESSION_STATE_ERROR)
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
|
@ -196,6 +196,11 @@ static int dh_handshake(ssh_session session) {
|
|||||||
case SSH_KEX_ECDH_SHA2_NISTP256:
|
case SSH_KEX_ECDH_SHA2_NISTP256:
|
||||||
rc = ssh_client_ecdh_init(session);
|
rc = ssh_client_ecdh_init(session);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CURVE25519
|
||||||
|
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
|
||||||
|
rc = ssh_client_curve25519_init(session);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
rc = SSH_ERROR;
|
rc = SSH_ERROR;
|
||||||
@ -579,6 +584,14 @@ char *ssh_get_issue_banner(ssh_session session) {
|
|||||||
* @param[in] session The SSH session to use.
|
* @param[in] session The SSH session to use.
|
||||||
*
|
*
|
||||||
* @return The version number if available, 0 otherwise.
|
* @return The version number if available, 0 otherwise.
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* int openssh = ssh_get_openssh_version();
|
||||||
|
*
|
||||||
|
* if (openssh == SSH_INT_VERSION(6, 1, 0)) {
|
||||||
|
* printf("Version match!\m");
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
*/
|
*/
|
||||||
int ssh_get_openssh_version(ssh_session session) {
|
int ssh_get_openssh_version(ssh_session session) {
|
||||||
if (session == NULL) {
|
if (session == NULL) {
|
||||||
|
285
libssh/src/curve25519.c
Normal file
285
libssh/src/curve25519.c
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
/*
|
||||||
|
* curve25519.c - Curve25519 ECDH functions for key exchange
|
||||||
|
* curve25519-sha256@libssh.org
|
||||||
|
*
|
||||||
|
* This file is part of the SSH Library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 by Aris Adamantiadis <aris@badcode.be>
|
||||||
|
*
|
||||||
|
* 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, version 2.1 of the License.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "libssh/curve25519.h"
|
||||||
|
#ifdef HAVE_CURVE25519
|
||||||
|
|
||||||
|
#include "nacl/crypto_scalarmult_curve25519.h"
|
||||||
|
#include "libssh/ssh2.h"
|
||||||
|
#include "libssh/buffer.h"
|
||||||
|
#include "libssh/priv.h"
|
||||||
|
#include "libssh/session.h"
|
||||||
|
#include "libssh/crypto.h"
|
||||||
|
#include "libssh/dh.h"
|
||||||
|
#include "libssh/pki.h"
|
||||||
|
|
||||||
|
/** @internal
|
||||||
|
* @brief Starts curve25519-sha256@libssh.org key exchange
|
||||||
|
*/
|
||||||
|
int ssh_client_curve25519_init(ssh_session session){
|
||||||
|
ssh_string client_pubkey;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_INIT);
|
||||||
|
if (rc < 0) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_get_random(session->next_crypto->curve25519_privkey, CURVE25519_PRIVKEY_SIZE, 1);
|
||||||
|
if (rc == 0){
|
||||||
|
ssh_set_error(session, SSH_FATAL, "PRNG error");
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
crypto_scalarmult_curve25519_base(session->next_crypto->curve25519_client_pubkey,
|
||||||
|
session->next_crypto->curve25519_privkey);
|
||||||
|
client_pubkey = ssh_string_new(CURVE25519_PUBKEY_SIZE);
|
||||||
|
if (client_pubkey == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
ssh_string_fill(client_pubkey, session->next_crypto->curve25519_client_pubkey,
|
||||||
|
CURVE25519_PUBKEY_SIZE);
|
||||||
|
rc = buffer_add_ssh_string(session->out_buffer,client_pubkey);
|
||||||
|
if (rc < 0) {
|
||||||
|
ssh_string_free(client_pubkey);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = packet_send(session);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ssh_curve25519_build_k(ssh_session session) {
|
||||||
|
ssh_curve25519_pubkey k;
|
||||||
|
session->next_crypto->k = bignum_new();
|
||||||
|
|
||||||
|
if (session->next_crypto->k == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session->server)
|
||||||
|
crypto_scalarmult_curve25519(k, session->next_crypto->curve25519_privkey,
|
||||||
|
session->next_crypto->curve25519_client_pubkey);
|
||||||
|
else
|
||||||
|
crypto_scalarmult_curve25519(k, session->next_crypto->curve25519_privkey,
|
||||||
|
session->next_crypto->curve25519_server_pubkey);
|
||||||
|
|
||||||
|
BN_bin2bn(k, CURVE25519_PUBKEY_SIZE, session->next_crypto->k);
|
||||||
|
|
||||||
|
#ifdef DEBUG_CRYPTO
|
||||||
|
ssh_print_hexa("Session server cookie",
|
||||||
|
session->next_crypto->server_kex.cookie, 16);
|
||||||
|
ssh_print_hexa("Session client cookie",
|
||||||
|
session->next_crypto->client_kex.cookie, 16);
|
||||||
|
ssh_print_bignum("Shared secret key", session->next_crypto->k);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @internal
|
||||||
|
* @brief parses a SSH_MSG_KEX_ECDH_REPLY packet and sends back
|
||||||
|
* a SSH_MSG_NEWKEYS
|
||||||
|
*/
|
||||||
|
int ssh_client_curve25519_reply(ssh_session session, ssh_buffer packet){
|
||||||
|
ssh_string q_s_string = NULL;
|
||||||
|
ssh_string pubkey = NULL;
|
||||||
|
ssh_string signature = NULL;
|
||||||
|
int rc;
|
||||||
|
pubkey = buffer_get_ssh_string(packet);
|
||||||
|
if (pubkey == NULL){
|
||||||
|
ssh_set_error(session,SSH_FATAL, "No public key in packet");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
/* this is the server host key */
|
||||||
|
session->next_crypto->server_pubkey = pubkey;
|
||||||
|
pubkey = NULL;
|
||||||
|
|
||||||
|
q_s_string = buffer_get_ssh_string(packet);
|
||||||
|
if (q_s_string == NULL) {
|
||||||
|
ssh_set_error(session,SSH_FATAL, "No Q_S ECC point in packet");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (ssh_string_len(q_s_string) != CURVE25519_PUBKEY_SIZE){
|
||||||
|
ssh_set_error(session, SSH_FATAL, "Incorrect size for server Curve25519 public key: %d",
|
||||||
|
ssh_string_len(q_s_string));
|
||||||
|
ssh_string_free(q_s_string);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
memcpy(session->next_crypto->curve25519_server_pubkey, ssh_string_data(q_s_string), CURVE25519_PUBKEY_SIZE);
|
||||||
|
|
||||||
|
signature = buffer_get_ssh_string(packet);
|
||||||
|
if (signature == NULL) {
|
||||||
|
ssh_set_error(session, SSH_FATAL, "No signature in packet");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
session->next_crypto->dh_server_signature = signature;
|
||||||
|
signature=NULL; /* ownership changed */
|
||||||
|
/* TODO: verify signature now instead of waiting for NEWKEYS */
|
||||||
|
if (ssh_curve25519_build_k(session) < 0) {
|
||||||
|
ssh_set_error(session, SSH_FATAL, "Cannot build k number");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send the MSG_NEWKEYS */
|
||||||
|
if (buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc=packet_send(session);
|
||||||
|
SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");
|
||||||
|
return rc;
|
||||||
|
error:
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_SERVER
|
||||||
|
|
||||||
|
/** @brief Parse a SSH_MSG_KEXDH_INIT packet (server) and send a
|
||||||
|
* SSH_MSG_KEXDH_REPLY
|
||||||
|
*/
|
||||||
|
int ssh_server_curve25519_init(ssh_session session, ssh_buffer packet){
|
||||||
|
/* ECDH keys */
|
||||||
|
ssh_string q_c_string;
|
||||||
|
ssh_string q_s_string;
|
||||||
|
|
||||||
|
/* SSH host keys (rsa,dsa,ecdsa) */
|
||||||
|
ssh_key privkey;
|
||||||
|
ssh_string sig_blob = NULL;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Extract the client pubkey from the init packet */
|
||||||
|
q_c_string = buffer_get_ssh_string(packet);
|
||||||
|
if (q_c_string == NULL) {
|
||||||
|
ssh_set_error(session,SSH_FATAL, "No Q_C ECC point in packet");
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
if (ssh_string_len(q_c_string) != CURVE25519_PUBKEY_SIZE){
|
||||||
|
ssh_set_error(session, SSH_FATAL, "Incorrect size for server Curve25519 public key: %d",
|
||||||
|
ssh_string_len(q_c_string));
|
||||||
|
ssh_string_free(q_c_string);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(session->next_crypto->curve25519_client_pubkey,
|
||||||
|
ssh_string_data(q_c_string), CURVE25519_PUBKEY_SIZE);
|
||||||
|
ssh_string_free(q_c_string);
|
||||||
|
/* Build server's keypair */
|
||||||
|
|
||||||
|
rc = ssh_get_random(session->next_crypto->curve25519_privkey, CURVE25519_PRIVKEY_SIZE, 1);
|
||||||
|
if (rc == 0){
|
||||||
|
ssh_set_error(session, SSH_FATAL, "PRNG error");
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
crypto_scalarmult_curve25519_base(session->next_crypto->curve25519_server_pubkey,
|
||||||
|
session->next_crypto->curve25519_privkey);
|
||||||
|
|
||||||
|
q_s_string = ssh_string_new(CURVE25519_PUBKEY_SIZE);
|
||||||
|
if (q_s_string == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_string_fill(q_s_string, session->next_crypto->curve25519_server_pubkey,
|
||||||
|
CURVE25519_PUBKEY_SIZE);
|
||||||
|
|
||||||
|
rc = buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_REPLY);
|
||||||
|
if (rc < 0) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* build k and session_id */
|
||||||
|
rc = ssh_curve25519_build_k(session);
|
||||||
|
if (rc < 0) {
|
||||||
|
ssh_set_error(session, SSH_FATAL, "Cannot build k number");
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* privkey is not allocated */
|
||||||
|
rc = ssh_get_key_params(session, &privkey);
|
||||||
|
if (rc == SSH_ERROR) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = make_sessionid(session);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
ssh_set_error(session, SSH_FATAL, "Could not create a session id");
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add host's public key */
|
||||||
|
rc = buffer_add_ssh_string(session->out_buffer,
|
||||||
|
session->next_crypto->server_pubkey);
|
||||||
|
if (rc < 0) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add ecdh public key */
|
||||||
|
rc = buffer_add_ssh_string(session->out_buffer, q_s_string);
|
||||||
|
ssh_string_free(q_s_string);
|
||||||
|
|
||||||
|
if (rc < 0) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
/* add signature blob */
|
||||||
|
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
|
||||||
|
if (sig_blob == NULL) {
|
||||||
|
ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = buffer_add_ssh_string(session->out_buffer, sig_blob);
|
||||||
|
ssh_string_free(sig_blob);
|
||||||
|
if (rc < 0) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEX_ECDH_REPLY sent");
|
||||||
|
rc = packet_send(session);
|
||||||
|
if (rc == SSH_ERROR) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send the MSG_NEWKEYS */
|
||||||
|
rc = buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS);
|
||||||
|
if (rc < 0) {
|
||||||
|
return SSH_ERROR;;
|
||||||
|
}
|
||||||
|
|
||||||
|
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
||||||
|
rc = packet_send(session);
|
||||||
|
SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WITH_SERVER */
|
||||||
|
|
||||||
|
#endif /* HAVE_CURVE25519 */
|
@ -770,6 +770,18 @@ int make_sessionid(ssh_session session) {
|
|||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CURVE25519
|
||||||
|
} else if(session->next_crypto->kex_type == SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG){
|
||||||
|
rc = buffer_add_u32(buf, htonl(CURVE25519_PUBKEY_SIZE));
|
||||||
|
rc += buffer_add_data(buf, session->next_crypto->curve25519_client_pubkey,
|
||||||
|
CURVE25519_PUBKEY_SIZE);
|
||||||
|
rc += buffer_add_u32(buf, htonl(CURVE25519_PUBKEY_SIZE));
|
||||||
|
rc += buffer_add_data(buf, session->next_crypto->curve25519_server_pubkey,
|
||||||
|
CURVE25519_PUBKEY_SIZE);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
num = make_bignum_string(session->next_crypto->k);
|
num = make_bignum_string(session->next_crypto->k);
|
||||||
@ -800,6 +812,7 @@ int make_sessionid(ssh_session session) {
|
|||||||
session->next_crypto->secret_hash);
|
session->next_crypto->secret_hash);
|
||||||
break;
|
break;
|
||||||
case SSH_KEX_ECDH_SHA2_NISTP256:
|
case SSH_KEX_ECDH_SHA2_NISTP256:
|
||||||
|
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
|
||||||
session->next_crypto->digest_len = SHA256_DIGEST_LENGTH;
|
session->next_crypto->digest_len = SHA256_DIGEST_LENGTH;
|
||||||
session->next_crypto->mac_type = SSH_MAC_SHA256;
|
session->next_crypto->mac_type = SSH_MAC_SHA256;
|
||||||
session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
|
session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "libssh/session.h"
|
#include "libssh/session.h"
|
||||||
#include "libssh/ssh2.h"
|
#include "libssh/ssh2.h"
|
||||||
#include "libssh/string.h"
|
#include "libssh/string.h"
|
||||||
|
#include "libssh/curve25519.h"
|
||||||
|
|
||||||
#ifdef HAVE_LIBGCRYPT
|
#ifdef HAVE_LIBGCRYPT
|
||||||
# define BLOWFISH "blowfish-cbc,"
|
# define BLOWFISH "blowfish-cbc,"
|
||||||
@ -63,14 +64,21 @@
|
|||||||
#define ZLIB "none"
|
#define ZLIB "none"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_ECDH
|
#ifdef HAVE_CURVE25519
|
||||||
#define KEY_EXCHANGE "ecdh-sha2-nistp256,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"
|
#define CURVE25519 "curve25519-sha256@libssh.org,"
|
||||||
#define HOSTKEYS "ecdsa-sha2-nistp256,ssh-rsa,ssh-dss"
|
|
||||||
#else
|
#else
|
||||||
#define KEY_EXCHANGE "diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"
|
#define CURVE25519 ""
|
||||||
#define HOSTKEYS "ssh-rsa,ssh-dss"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_ECDH
|
||||||
|
#define ECDH "ecdh-sha2-nistp256,"
|
||||||
|
#define HOSTKEYS "ecdsa-sha2-nistp256,ssh-rsa,ssh-dss"
|
||||||
|
#else
|
||||||
|
#define HOSTKEYS "ssh-rsa,ssh-dss"
|
||||||
|
#define ECDH ""
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define KEY_EXCHANGE CURVE25519 ECDH "diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"
|
||||||
#define KEX_METHODS_SIZE 10
|
#define KEX_METHODS_SIZE 10
|
||||||
|
|
||||||
/* NOTE: This is a fixed API and the index is defined by ssh_kex_types_e */
|
/* NOTE: This is a fixed API and the index is defined by ssh_kex_types_e */
|
||||||
@ -412,6 +420,8 @@ int ssh_kex_select_methods (ssh_session session){
|
|||||||
session->next_crypto->kex_type=SSH_KEX_DH_GROUP14_SHA1;
|
session->next_crypto->kex_type=SSH_KEX_DH_GROUP14_SHA1;
|
||||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp256") == 0){
|
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp256") == 0){
|
||||||
session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP256;
|
session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP256;
|
||||||
|
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "curve25519-sha256@libssh.org") == 0){
|
||||||
|
session->next_crypto->kex_type=SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
|
@ -126,6 +126,17 @@ static int ssh_execute_server_request(ssh_session session, ssh_message msg)
|
|||||||
ssh_message_reply_default(msg);
|
ssh_message_reply_default(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return SSH_OK;
|
||||||
|
} else if (msg->auth_request.method == SSH_AUTH_METHOD_NONE &&
|
||||||
|
ssh_callbacks_exists(session->server_callbacks, auth_none_function)) {
|
||||||
|
rc = session->server_callbacks->auth_none_function(session,
|
||||||
|
msg->auth_request.username, session->server_callbacks->userdata);
|
||||||
|
if (rc == SSH_AUTH_SUCCESS || rc == SSH_AUTH_PARTIAL){
|
||||||
|
ssh_message_auth_reply_success(msg, rc == SSH_AUTH_PARTIAL);
|
||||||
|
} else {
|
||||||
|
ssh_message_reply_default(msg);
|
||||||
|
}
|
||||||
|
|
||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include "libssh/session.h"
|
#include "libssh/session.h"
|
||||||
#include "libssh/socket.h"
|
#include "libssh/socket.h"
|
||||||
#include "libssh/ssh2.h"
|
#include "libssh/ssh2.h"
|
||||||
|
#include "libssh/curve25519.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
@ -102,6 +103,11 @@ SSH_PACKET_CALLBACK(ssh_packet_dh_reply){
|
|||||||
case SSH_KEX_ECDH_SHA2_NISTP256:
|
case SSH_KEX_ECDH_SHA2_NISTP256:
|
||||||
rc = ssh_client_ecdh_reply(session, packet);
|
rc = ssh_client_ecdh_reply(session, packet);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CURVE25519
|
||||||
|
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
|
||||||
|
rc = ssh_client_curve25519_reply(session, packet);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
ssh_set_error(session,SSH_FATAL,"Wrong kex type in ssh_packet_dh_reply");
|
ssh_set_error(session,SSH_FATAL,"Wrong kex type in ssh_packet_dh_reply");
|
||||||
|
@ -349,8 +349,8 @@ void ssh_signature_free(ssh_signature sig)
|
|||||||
*
|
*
|
||||||
* @param[in] auth_data Private data passed to the auth function.
|
* @param[in] auth_data Private data passed to the auth function.
|
||||||
*
|
*
|
||||||
* @param[out] pkey A pointer where the key can be stored. You need
|
* @param[out] pkey A pointer where the allocated key can be stored. You
|
||||||
* to free the memory.
|
* need to free the memory.
|
||||||
*
|
*
|
||||||
* @return SSH_ERROR in case of error, SSH_OK otherwise.
|
* @return SSH_ERROR in case of error, SSH_OK otherwise.
|
||||||
*
|
*
|
||||||
@ -397,8 +397,8 @@ int ssh_pki_import_privkey_base64(const char *b64_key,
|
|||||||
*
|
*
|
||||||
* @param[in] auth_data Private data passed to the auth function.
|
* @param[in] auth_data Private data passed to the auth function.
|
||||||
*
|
*
|
||||||
* @param[out] pkey A pointer to store the ssh_key. You need to free the
|
* @param[out] pkey A pointer to store the allocated ssh_key. You need to
|
||||||
* key.
|
* free the key.
|
||||||
*
|
*
|
||||||
* @returns SSH_OK on success, SSH_EOF if the file doesn't exist or permission
|
* @returns SSH_OK on success, SSH_EOF if the file doesn't exist or permission
|
||||||
* denied, SSH_ERROR otherwise.
|
* denied, SSH_ERROR otherwise.
|
||||||
@ -684,8 +684,8 @@ fail:
|
|||||||
*
|
*
|
||||||
* @param[in] type The type of the key to format.
|
* @param[in] type The type of the key to format.
|
||||||
*
|
*
|
||||||
* @param[out] pkey A pointer where the key can be stored. You need
|
* @param[out] pkey A pointer where the allocated key can be stored. You
|
||||||
* to free the memory.
|
* need to free the memory.
|
||||||
*
|
*
|
||||||
* @return SSH_OK on success, SSH_ERROR on error.
|
* @return SSH_OK on success, SSH_ERROR on error.
|
||||||
*
|
*
|
||||||
@ -728,8 +728,8 @@ int ssh_pki_import_pubkey_base64(const char *b64_key,
|
|||||||
* @param[in] key_blob The key blob to import as specified in RFC 4253 section
|
* @param[in] key_blob The key blob to import as specified in RFC 4253 section
|
||||||
* 6.6 "Public Key Algorithms".
|
* 6.6 "Public Key Algorithms".
|
||||||
*
|
*
|
||||||
* @param[out] pkey A pointer where the key can be stored. You need
|
* @param[out] pkey A pointer where the allocated key can be stored. You
|
||||||
* to free the memory.
|
* need to free the memory.
|
||||||
*
|
*
|
||||||
* @return SSH_OK on success, SSH_ERROR on error.
|
* @return SSH_OK on success, SSH_ERROR on error.
|
||||||
*
|
*
|
||||||
@ -789,8 +789,8 @@ fail:
|
|||||||
*
|
*
|
||||||
* @param[in] filename The path to the public key.
|
* @param[in] filename The path to the public key.
|
||||||
*
|
*
|
||||||
* @param[out] pkey A pointer to store the public key. You need to free the
|
* @param[out] pkey A pointer to store the allocated public key. You need to
|
||||||
* memory.
|
* free the memory.
|
||||||
*
|
*
|
||||||
* @returns SSH_OK on success, SSH_EOF if the file doesn't exist or permission
|
* @returns SSH_OK on success, SSH_EOF if the file doesn't exist or permission
|
||||||
* denied, SSH_ERROR otherwise.
|
* denied, SSH_ERROR otherwise.
|
||||||
@ -875,17 +875,20 @@ int ssh_pki_import_pubkey_file(const char *filename, ssh_key *pkey)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Generates a keypair.
|
* @brief Generates a keypair.
|
||||||
|
*
|
||||||
* @param[in] type Type of key to create
|
* @param[in] type Type of key to create
|
||||||
|
*
|
||||||
* @param[in] parameter Parameter to the creation of key:
|
* @param[in] parameter Parameter to the creation of key:
|
||||||
* rsa : length of the key in bits (e.g. 1024, 2048, 4096)
|
* rsa : length of the key in bits (e.g. 1024, 2048, 4096)
|
||||||
* dsa : length of the key in bits (e.g. 1024, 2048, 3072)
|
* dsa : length of the key in bits (e.g. 1024, 2048, 3072)
|
||||||
* ecdsa : bits of the key (e.g. 256, 384, 512)
|
* ecdsa : bits of the key (e.g. 256, 384, 512)
|
||||||
* @param[out] pkey A pointer to store the private key. You need to free the
|
* @param[out] pkey A pointer to store the allocated private key. You need
|
||||||
* memory.
|
* to free the memory.
|
||||||
|
*
|
||||||
* @return SSH_OK on success, SSH_ERROR on error.
|
* @return SSH_OK on success, SSH_ERROR on error.
|
||||||
|
*
|
||||||
* @warning Generating a key pair may take some time.
|
* @warning Generating a key pair may take some time.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ssh_pki_generate(enum ssh_keytypes_e type, int parameter,
|
int ssh_pki_generate(enum ssh_keytypes_e type, int parameter,
|
||||||
ssh_key *pkey){
|
ssh_key *pkey){
|
||||||
int rc;
|
int rc;
|
||||||
@ -1000,7 +1003,8 @@ int ssh_pki_export_pubkey_blob(const ssh_key key,
|
|||||||
*
|
*
|
||||||
* @param[in] key The key to hash
|
* @param[in] key The key to hash
|
||||||
*
|
*
|
||||||
* @param[out] b64_key A pointer to store the base64 hased key.
|
* @param[out] b64_key A pointer to store the allocated base64 hashed key. You
|
||||||
|
* need to free the buffer.
|
||||||
*
|
*
|
||||||
* @return SSH_OK on success, SSH_ERROR on error.
|
* @return SSH_OK on success, SSH_ERROR on error.
|
||||||
*
|
*
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
#include "libssh/dh.h"
|
#include "libssh/dh.h"
|
||||||
#include "libssh/messages.h"
|
#include "libssh/messages.h"
|
||||||
#include "libssh/options.h"
|
#include "libssh/options.h"
|
||||||
|
#include "libssh/curve25519.h"
|
||||||
|
|
||||||
#define set_status(session, status) do {\
|
#define set_status(session, status) do {\
|
||||||
if (session->common.callbacks && session->common.callbacks->connect_status_function) \
|
if (session->common.callbacks && session->common.callbacks->connect_status_function) \
|
||||||
@ -182,6 +183,11 @@ SSH_PACKET_CALLBACK(ssh_packet_kexdh_init){
|
|||||||
case SSH_KEX_ECDH_SHA2_NISTP256:
|
case SSH_KEX_ECDH_SHA2_NISTP256:
|
||||||
rc = ssh_server_ecdh_init(session, packet);
|
rc = ssh_server_ecdh_init(session, packet);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CURVE25519
|
||||||
|
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
|
||||||
|
rc = ssh_server_curve25519_init(session, packet);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
ssh_set_error(session,SSH_FATAL,"Wrong kex type in ssh_packet_kexdh_init");
|
ssh_set_error(session,SSH_FATAL,"Wrong kex type in ssh_packet_kexdh_init");
|
||||||
|
@ -115,6 +115,17 @@ ssh_session ssh_new(void) {
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_ECC
|
||||||
|
id = strdup("%d/id_ecdsa");
|
||||||
|
if (id == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
rc = ssh_list_append(session->opts.identity, id);
|
||||||
|
if (rc == SSH_ERROR) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
id = strdup("%d/id_rsa");
|
id = strdup("%d/id_rsa");
|
||||||
if (id == NULL) {
|
if (id == NULL) {
|
||||||
goto err;
|
goto err;
|
||||||
@ -268,7 +279,10 @@ void ssh_free(ssh_session session) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief get the server banner
|
* @brief get the server banner
|
||||||
|
*
|
||||||
* @param[in] session The SSH session
|
* @param[in] session The SSH session
|
||||||
|
*
|
||||||
|
* @return Returns the server banner string or NULL.
|
||||||
*/
|
*/
|
||||||
const char* ssh_get_serverbanner(ssh_session session) {
|
const char* ssh_get_serverbanner(ssh_session session) {
|
||||||
if(!session) {
|
if(!session) {
|
||||||
@ -300,8 +314,6 @@ void ssh_silent_disconnect(ssh_session session) {
|
|||||||
* @param[in] session The ssh session to change.
|
* @param[in] session The ssh session to change.
|
||||||
*
|
*
|
||||||
* @param[in] blocking Zero for nonblocking mode.
|
* @param[in] blocking Zero for nonblocking mode.
|
||||||
*
|
|
||||||
* \bug nonblocking code is in development and won't work as expected
|
|
||||||
*/
|
*/
|
||||||
void ssh_set_blocking(ssh_session session, int blocking) {
|
void ssh_set_blocking(ssh_session session, int blocking) {
|
||||||
if (session == NULL) {
|
if (session == NULL) {
|
||||||
@ -577,7 +589,7 @@ int ssh_get_status(ssh_session session) {
|
|||||||
|
|
||||||
socketstate = ssh_socket_get_status(session->socket);
|
socketstate = ssh_socket_get_status(session->socket);
|
||||||
|
|
||||||
if (session->closed) {
|
if (session->session_state == SSH_SESSION_STATE_DISCONNECTED) {
|
||||||
r |= SSH_CLOSED;
|
r |= SSH_CLOSED;
|
||||||
}
|
}
|
||||||
if (socketstate & SSH_READ_PENDING) {
|
if (socketstate & SSH_READ_PENDING) {
|
||||||
@ -586,7 +598,8 @@ int ssh_get_status(ssh_session session) {
|
|||||||
if (socketstate & SSH_WRITE_PENDING) {
|
if (socketstate & SSH_WRITE_PENDING) {
|
||||||
r |= SSH_WRITE_PENDING;
|
r |= SSH_WRITE_PENDING;
|
||||||
}
|
}
|
||||||
if ((session->closed && (socketstate & SSH_CLOSED_ERROR)) ||
|
if ((session->session_state == SSH_SESSION_STATE_DISCONNECTED &&
|
||||||
|
(socketstate & SSH_CLOSED_ERROR)) ||
|
||||||
session->session_state == SSH_SESSION_STATE_ERROR) {
|
session->session_state == SSH_SESSION_STATE_ERROR) {
|
||||||
r |= SSH_CLOSED_ERROR;
|
r |= SSH_CLOSED_ERROR;
|
||||||
}
|
}
|
||||||
@ -610,12 +623,9 @@ const char *ssh_get_disconnect_message(ssh_session session) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!session->closed) {
|
if (session->session_state != SSH_SESSION_STATE_DISCONNECTED) {
|
||||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||||
"Connection not closed yet");
|
"Connection not closed yet");
|
||||||
} else if(session->closed_by_except) {
|
|
||||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
|
||||||
"Connection closed by socket error");
|
|
||||||
} else if(!session->discon_msg) {
|
} else if(!session->discon_msg) {
|
||||||
ssh_set_error(session, SSH_FATAL,
|
ssh_set_error(session, SSH_FATAL,
|
||||||
"Connection correctly closed but no disconnect message");
|
"Connection correctly closed but no disconnect message");
|
||||||
|
Loading…
Reference in New Issue
Block a user