Compare commits

..

90 Commits

Author SHA1 Message Date
Andreas Schneider
dff6c0821e Bump version to 0.11.2
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
2025-06-24 10:35:39 +02:00
Jakub Jelen
82175044dc dh-gex: Reformat the dhgex_server_callbacks structure
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2025-06-24 10:15:43 +02:00
Jakub Jelen
8559f59404 dh-gex.c: Fix typo in the constant name
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2025-06-24 10:15:43 +02:00
Jakub Jelen
160fc7df10 packet: Implement missing packet filter for DH GEX
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2025-06-24 10:15:43 +02:00
Jakub Jelen
a9d8a3d448 CVE-2025-5372 libgcrypto: Simplify error checking and handling of return codes in ssh_kdf()
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2025-06-24 09:32:00 +02:00
Jakub Jelen
f13b91c2d8 libgcrypto: Reformat ssh_kdf()
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2025-06-24 09:31:58 +02:00
Jakub Jelen
90b4845e0c CVE-2025-5987 libcrypto: Correctly detect failures of chacha initialization
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2025-06-24 09:31:53 +02:00
Jakub Jelen
6ddb730a27 CVE-2025-5351 pki_crypto: Avoid double-free on low-memory conditions
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2025-06-24 09:31:36 +02:00
Jakub Jelen
b35ee876ad CVE-2025-4878 legacy: Properly check return value to avoid NULL pointer dereference
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2025-06-24 09:28:09 +02:00
Jakub Jelen
697650caa9 CVE-2025-4878 Initialize pointers where possible
This is mostly mechanical change initializing all the pointers I was able to
find with some grep and manual review of sources and examples.

Used the following greps (which yield some false positives though):

    git grep "    \w* *\* *\w*;$"
    git grep " ssh_session \w*;"
    git grep " ssh_channel \w*;"
    git grep " struct ssh_iterator \*\w*;"
    git grep " ssh_bind \w*;"
    git grep " ssh_key \w*;"
    git grep " ssh_string \w*;"
    git grep " ssh_buffer \w*;"
    git grep " HMACCTX \w*;"
    git grep " SHACTX \w*;"
    grep -rinP '^(?!.*=)\s*(?:\w+\s+)*\w+\s*\*\s*\w+\s*;'

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2025-06-24 09:27:52 +02:00
Jakub Jelen
5504ff4051 CVE-2025-5449 sftpserver: Use constant for return values
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2025-06-24 09:27:52 +02:00
Jakub Jelen
f79ec51b7f CVE-2025-5449 sftpserver: Fix possible read behind buffer on 32bit arch
On 32b architecture when processing the SFTP packets, the value
0x7ffffffc in the payload_len will overflow to negative integer values,
causing these checks to pass and possibly reading behind the buffer
bounds later.

This affects only SFTP server implementations running on 32b
architecture.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2025-06-24 09:27:52 +02:00
Jakub Jelen
78485f446a CVE-2025-5449 sftpserver: Avoid NULL dereference for invalid handles
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2025-06-24 09:08:24 +02:00
Jakub Jelen
3443aec901 CVE-2025-5449 tests: Reproducer for sftp handles exhaustion
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2025-06-24 09:08:24 +02:00
Jakub Jelen
261612179f CVE-2025-5449 sftpserver: Avoid memory leak when we run out of handles during sftp_open
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2025-06-24 09:08:24 +02:00
Jakub Jelen
5f4ffda887 CVE-2025-5318: sftpserver: Fix possible buffer overrun
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2025-06-24 09:08:24 +02:00
Jakub Jelen
6fd9cc8ce3 CVE-2025-4877 base64: Prevent integer overflow and potential OOB
Set maximum input to 256MB to have safe margin to the 1GB trigger point
for 32b arch.

The OOB should not be reachable by any internal code paths as most of
the buffers and strings we use as input for this operation already have
similar limit and none really allows this much of data.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 00f09acbec)
2025-06-24 09:08:24 +02:00
Norbert Pocs
b595cc7ada gitlab-ci.yml: Run fedora without pkcs11
Signed-off-by: Norbert Pocs <norbertpocs0@gmail.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 2971e122d0)
2025-06-23 14:42:35 +02:00
Jakub Jelen
d044b79de0 tests: Remove p11-kit remoting from pkcs11 tests
The p11-kit remoting was initially introduced because softhsm
was crashing during cleanup with OpenSSL 3.0. This was resolved
since then and this code introduces a lot of complexity and
possible bugs, such as when using the mechanisms from PKCS#11 3.0
that are unknown to the p11-kit remoting tool. It decides to remove
them from the list as demonstrated here:

https://github.com/p11-glue/p11-kit/issues/668

This resulted in pkcs11-provider not registering EDDSA siganture
methods to the OpenSSL and failing when asked to provide a singature
by the Ed25519 key from the PKCS#11 token.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Sahana Prasad <sahana@redhat.com>
(cherry picked from commit 99fcd56135)
2025-06-23 14:37:36 +02:00
Jakub Jelen
827c24055f sftp: Do not fail if the status message does not contain error message
Some SFTP servers (Cisco) do not implement the v3 protocol correctly and do not
send the mandatory part of the status message. This falls back to the v2
behavior when the error message and language tag are not provided.

Fixes: #272

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Sahana Prasad <sahana@redhat.com>
(cherry picked from commit 0306581f1c)
2025-06-23 13:26:47 +02:00
Lucas Mulling
1eff5d68f4 tests: Cleanup torture_channel_exit_signal
Signed-off-by: Lucas Mulling <lucas.mulling@suse.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 74eb01f26d)
2025-06-23 13:25:45 +02:00
Jakub Jelen
e4ede51d87 pki: Set ECDSA signature buffers secure
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Eshan Kelkar <eshankelkar@galorithm.com>
(cherry picked from commit b8e587e498)
2025-06-23 13:25:35 +02:00
Jakub Jelen
991b4422bd tests: Auth without none method
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Norbert Pocs <norbertpocs0@gmail.com>
(cherry picked from commit 2a2c714dfa)
2025-06-23 13:25:02 +02:00
Jakub Jelen
1a2c46781c auth: Process outstanding packets before selecting signature algorithm
Originally reported by Till on mailing list here:

https://archive.libssh.org/libssh/2025-05/0000000.html

After some debugging, it turns out the client code does not guarantee
the extensions are processed before making decisions on the signature algorithm
that is being used for authentication, causing false-positive failures.

This does not happen in the tests, where we initially call ssh_userauth_none,
which enumerates authentications methods and as a side effect processes
outstanding packets such as SSH_EXT_INFO message with the server-sig-algs
extension.

When the first function called after `ssh_connect()` is
`ssh_userauth_publickey()`, the `ssh_userauth_request_service()` was wrongly
called only after the signature algorithm compatibility was checked.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Norbert Pocs <norbertpocs0@gmail.com>
(cherry picked from commit 12baa5200a)
2025-06-23 13:24:59 +02:00
Jakub Jelen
65699380cf buffer: Use sizeof instead of magic number
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Norbert Pocs <norbertpocs0@gmail.com>
(cherry picked from commit f2b64abcbd)
2025-06-23 13:24:57 +02:00
Praneeth Sarode
52e648c7f1 tests: remove unsupported SHA1 HMAC tests for compatibility with latest dropbear version
Signed-off-by: Praneeth Sarode <praneethsarode@gmail.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit ca4c874a9e)
2025-06-23 13:24:25 +02:00
Lucas Mulling
66314eeb71 misc: Fix OpenSSH banner parsing
Signed-off-by: Lucas Mulling <lucas.mulling@suse.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Norbert Pocs <norbertpocs0@gmail.com>
(cherry picked from commit d758990d39)
2025-06-23 13:24:05 +02:00
Jakub Jelen
573e0e48dc sftpserver: Free memory on error condition
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Norbert Pocs <norbertpocs0@gmail.com>
(cherry picked from commit 69c169e4cb)
2025-06-23 13:23:31 +02:00
Jakub Jelen
a2bb9b5d0c test: Fix potential leak of fds on error
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Norbert Pocs <norbertpocs0@gmail.com>
(cherry picked from commit f0b9db586b)
2025-06-23 13:23:28 +02:00
Jakub Jelen
0de97c48d0 test: Fix unused variables and potential memory leaks
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Norbert Pocs <norbertpocs0@gmail.com>
(cherry picked from commit c735b44f83)
2025-06-23 13:23:18 +02:00
Jakub Jelen
eeb498c0e3 Make sure we pass right parameters to buffer_pack
Fixes: #299

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Sahana Prasad <sahana@redhat.com>
Reviewed-by: Norbert Pocs <norbertpocs0@gmail.com>
(cherry picked from commit d00f7b1bf9)
2025-06-23 13:22:47 +02:00
Jakub Jelen
715855d888 tests: Do not build zlib test when built without
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Sahana Prasad <sahana@redhat.com>
Reviewed-by: Norbert Pocs <norbertpocs0@gmail.com>
(cherry picked from commit b14018ecab)
2025-06-23 13:21:37 +02:00
Norbert Pocs
38004ecf94 CmakeLists: Fix multiple digit major version for OpenSSH
Signed-off-by: Norbert Pocs <norbertpocs0@gmail.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit af10857aa3)
2025-06-23 13:20:31 +02:00
Jakub Jelen
edb1b8ba2c tests: Fix variable names to avoid codespell issues
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit a25f9d211d)
2025-06-23 13:17:28 +02:00
Jakub Jelen
1e9e37580f tests: Reproducer for graceful failure on ignored Match arguments
https://gitlab.com/libssh/libssh-mirror/-/issues/291#note_2376323499
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 3a52bf1679)
2025-06-23 13:17:17 +02:00
Jakub Jelen
8b5b785e0c config: Be less strict when parsing unknown Match keywords
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit f7bdd779d6)
2025-06-23 13:17:12 +02:00
Jakub Jelen
d245706678 config: Fix copy&paste error in error message
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8ef249a4a4)
2025-06-23 13:17:06 +02:00
Jakub Jelen
5911d058f1 tests: Unit test nested quotes
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 7f045e2d91)
2025-06-23 13:15:02 +02:00
Jakub Jelen
3daa06dba7 Reproducer for #291
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit a10553ae57)
2025-06-23 13:14:56 +02:00
Jakub Jelen
45888d65ba config: Allow escaping quotes inside of quoted tokens
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit d1ce336ae3)
2025-06-23 13:14:55 +02:00
Jakub Jelen
33a73594e6 examples: Fix format string unearthed during macos build
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit d5456931cc)
2025-06-23 13:14:19 +02:00
Jakub Jelen
9cdcd16e82 cmake: Do not attempt to use -fstack-clash-protection on MacOS M1 chips
This is supported in clang, but only on x86_64 so we need to back down to the
architecture checks. Otherwise the checks pass with warning, but the build
itself fails with errors (-Werror).

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit dc18b41357)
2025-06-23 13:14:09 +02:00
Jakub Jelen
12077f7294 clang-format: Update config for clang 19
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Sahana Prasad <sahana@redhat.com>
(cherry picked from commit 9b9a2ea97d)
2025-06-23 13:13:31 +02:00
Andreas Schneider
f067d9e0d3 torture_config: Use getpwuid() instead of env variables
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Sahana Prasad <sahana@redhat.com>
(cherry picked from commit e9b76ff1bd)
2025-06-23 13:13:27 +02:00
Andreas Schneider
ec753057a5 torture_misc: Do not rely on environment variables
The safest way is to use getpwuid().

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Sahana Prasad <sahana@redhat.com>
(cherry picked from commit e9046fc069)
2025-06-23 13:13:23 +02:00
Jakub Jelen
39aefd479f zlib: Move conditional compilation inside of the gzip.c
This implements stub for the compression functions and includes the
gzip.c in the compilation target uncoditionally, keeping the WITH_ZLIB
conditional compilation only in the gzip.c

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 0cd749a533)
2025-06-23 13:13:18 +02:00
Jakub Jelen
2e5b6beec7 gzip: Move cleanup to separate function
to avoid exposing gzip function into wrapper.c

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 00fce9cb6c)
2025-06-23 13:12:14 +02:00
Jakub Jelen
11c16531f0 gzip: Avoid potential memory leak
Thanks coverity CID 1589436

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit a547b7f115)
2025-06-23 13:11:19 +02:00
Jakub Jelen
69ee0062d7 options: Clarify format of HOST option
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 91e228b08b)
2025-06-23 13:10:23 +02:00
Jakub Jelen
13c69821dd Happy new year 2025!
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit cbcd6d6f46)
2025-06-23 13:10:16 +02:00
Jakub Jelen
543c730691 packet: Implement logging of SSH2_MSG_DEBUG message
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 49b0c859f9)
2025-06-23 13:10:09 +02:00
Jakub Jelen
97bda86d41 channels: Remove callbacks from freed channels
When the user frees the channel, they no longer expect any callbacks
to be triggered on it. When we delay the close before we receive
the remaining messages, we should not trigger the user callbacks
as it might be already freed.

I believe this is the random torture_session test failures and
errors we are getting from valgrind from time to time.

We keep the callbacks cleanup in the do_cleanup() in case the
calling application sets the callback after free for some reason.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 79ba546cde)
2025-06-23 13:10:05 +02:00
Jakub Jelen
77c9498dbe tests: Close channel before freeying
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c043122655)
2025-06-23 13:09:38 +02:00
Jakub Jelen
404452728d tests: Fix random failure on too fast systems
On mingw we are frequently getting a failure like this:

[  ERROR   ] --- 451 is not within the range 1-450

This means the 50ms sleep did not manage to elapse the 50ms in the timeout
structure. Extending the range to 460 will give use more wiggle room if the
clock is not as it should be.

Related: #273
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 874b75429f)
2025-06-23 13:08:56 +02:00
Jakub Jelen
e111a63acb ci: Skip torture_rand in mingw as it keeps hanging
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit f8a6b1e2b3)
2025-06-23 13:08:51 +02:00
Andreas Schneider
054682e72d tests:valgrind: Add suppression memleak in krb5_mcc_generate_new
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 4bc40a47a3)
2025-06-23 13:08:02 +02:00
Jakub Jelen
5bff8b5dc6 sftpserver: Do not override the ssh error code
Fixes: https://gitlab.com/libssh/libssh-mirror/-/issues/275#note_2162076660

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Sahana Prasad <sahana@redhat.com>
(cherry picked from commit d0ecb5388c)
2025-06-23 13:07:33 +02:00
Axel Lin
758fbdd31b Add #ifndef __VA_NARG__ guard to avoid "__VA_NARG__" redefined warnings
Some SDK already defined __VA_NARG__, so without #ifndef __VA_NARG__ guard
we got a lot of "__VA_NARG__" redefined warnings.
Fix it by adding #ifndef __VA_NARG__ guard in include/libssh/priv.h.

Fixes: #279
Signed-off-by: Axel Lin <axel.lin@ingics.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 861590192f)
2025-06-23 13:06:59 +02:00
JamesWrigley
5c0add44e7 Add missing #include's to sftpserver.h
Presumably this header is always imported with all the other necessary ones so
it doesn't usually make a difference, but generating Julia bindings from the
header by itself requires all the types to be defined (e.g. ssh_session,
ssh_channel, etc).

Signed-off-by: James Wrigley <james@puiterwijk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 9ad2f6b3b1)
2025-06-23 13:06:40 +02:00
JamesWrigley
9f4e7eb06b Make codespell ignore PENDIN in CI
This is the correct name of a terminal opcode.

Signed-off-by: James Wrigley <james@puiterwijk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit ef8e90863b)
2025-06-23 13:06:34 +02:00
Simon Josefsson
1d157c57a3 tests: Permit slow systems to take 1-450 instead of 1-40ms.
Thanks to Jakub Jelen for debugging and suggested fix.  Fixes #273.

Signed-off-by: Simon Josefsson <simon@josefsson.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit d29ed23010)
2025-06-23 13:06:28 +02:00
Jakub Jelen
7d35d25297 tests: Do not use global openssl.cnf
The global openssl configuration file automatically loads a pkcs11
provider, but it does it before we set up the token, which makes
the pkcs11 tests failing.

The workaround is to not load the global configuration, which is
delaying the loading of the pkcs11 provider to the time of first
use.

Consequently, this will require separate integration end-to-end
test that will verify the libssh works correctly with the pkcs11
provider loaded early.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Sahana Prasad <sahana@redhat.com>
(cherry picked from commit 46d7417620)
2025-06-23 13:06:20 +02:00
Jakub Jelen
4119ad0fd8 ci: Add Centos 10 development container
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Sahana Prasad <sahana@redhat.com>
(cherry picked from commit c73a8a824e)
2025-06-23 13:06:15 +02:00
Davidwed
771dc30f79 cmake: Fixed compatibility issues with "CPM.cmake" in combination with the libraries MBedTLS and libgcrypt.
Signed-off-by: Davidwed <davidwe@posteo.de>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 7712c7d0f9)
2025-06-23 13:06:11 +02:00
Simon Josefsson
747dd17e64 tests: Permit slow systems to take 300ms instead of 75ms.
Thanks to Jakub Jelen for debugging.  Fixes #273.

Reproduce problem by changing the value to 1ms.

Signed-off-by: Simon Josefsson <simon@josefsson.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit d7a0cbcfbb)
2025-06-23 13:05:24 +02:00
Thomas Perale
093431f929 cmake: Only enable CXX when running the coverage
Commit 25a678190c introduced code coverage
collection. That also introduced a dependency to CXX language.

When cross-compiling libssh in an environment that doesn't have a C++ compiler
the following error is raised: "No CMAKE_CXX_COMPILER could be found.".

Since the C++ part is only needed for the coverage part, this commit only enable
that language dependency when actually needing it.

Signed-off-by: Thomas Perale <thomas.perale@mind.be>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit cb0237e85b)
2025-06-23 13:05:02 +02:00
Jakub Jelen
854795c654 libssh 0.11.1
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Sahana Prasad <sahana@redhat.com>
2024-08-29 15:36:46 +02:00
Jakub Jelen
da064c9a18 ttyopts: Adjust the default TTY modes to be sane
The "sane" default is now based on the man stty "sane" alias with addition of
utf8.

Fixes: #270

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 48d474f78c)
2024-08-29 15:07:00 +02:00
Carlo Bramini
c85dc05436 CYGWIN: fix build.
Signed-off-by: Carlo Bramini <carlo_bramini@users.sourceforge.net>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit e298600303)
2024-08-19 15:17:03 +02:00
Jakub Jelen
8d0d3d4d7b Add explicit -Werror=unused-variable
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Eshan Kelkar <eshankelkar@galorithm.com>
(cherry picked from commit 8295945011)
2024-08-19 15:17:01 +02:00
Jakub Jelen
0b2e13bc9b cmake: Do not build server examples and tests when built without server
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Eshan Kelkar <eshankelkar@galorithm.com>
(cherry picked from commit 8363929104)
2024-08-19 15:17:00 +02:00
Jakub Jelen
51f4a5743d kex: Avoid unused variable when built without server
Fixes: #267

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Eshan Kelkar <eshankelkar@galorithm.com>
(cherry picked from commit 71e1baeb5f)
2024-08-19 15:16:58 +02:00
Jakub Jelen
e816256333 config: Do not parse unsupported ControlPath/ControlMaster
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 82b363f294)
2024-08-19 15:16:54 +02:00
Jakub Jelen
960a6d1cdd tests: Do not crash on cleanup when sshd does not come up
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8fb2c5d2fd)
2024-08-19 15:16:51 +02:00
Jakub Jelen
1fa9ea7f43 tests: Do not override verbosity set by environment
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 9ce53b6972)
2024-08-19 15:16:48 +02:00
Jakub Jelen
afa77c11ca test: Workaround the new OpenSSH failure rate limiting
The new OpenSSH rate limits the failed authentication attempts per source
address and drops connection when the amount is reached, which is happening
in our testsuite.

By whitelisting the IP address of the client on the socket wrapper,
this allows the tests to pass.

https://man.openbsd.org/sshd_config.5#PerSourcePenaltyExemptList

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 7b89ff760a)
2024-08-19 15:16:35 +02:00
Andreas Schneider
825de355d4 cpack: Make sure to not package .git file
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 362ab3a684)
2024-08-19 15:16:33 +02:00
Jakub Jelen
a910526e10 tests: Avoid unused variables
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit ea97d41bbb)
2024-08-19 15:16:31 +02:00
Jakub Jelen
dfc3cb7112 wrapper: Use calloc instead of zerostructp
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c85268c38b)
2024-08-19 15:16:30 +02:00
Jakub Jelen
3264d3e83c wrapper: Avoid asymmetric termination of gzip context
For some reason, both compress and decompress contexts were terminated
with both compress and decompress end functions (if the deflateEnd worked),
which was causing for some another unexplained reasons issues on i686
architecture when running the torture_packet unit test.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c9cfeb9b83)
2024-08-19 15:16:28 +02:00
Jakub Jelen
6030d2fcd5 tests: Describe reason for using internal-sftp
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit deedc0e108)
2024-08-19 15:16:26 +02:00
Jakub Jelen
406a014d58 tests: Remove needless printf
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 57073d588a)
2024-08-19 15:16:24 +02:00
Jakub Jelen
af0153f30f tests: Rewrite fs_wrapper for readability
includes also additional syscalls for 32b archs.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit d416ef533f)
2024-08-19 15:16:21 +02:00
Jakub Jelen
84dde6d302 tests: Assemble the output into single buffer
... before checking the content.

This test was failing randomly when the read returned only partial buffer.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 2743b510ac)
2024-08-19 15:16:19 +02:00
Jakub Jelen
dd38f523e1 tests: Be explicit about types.
Casting int to bool might not always work as expected

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 41d370864e)
2024-08-19 15:16:14 +02:00
JamesWrigley
5318ddaabc Use CMake's C_STANDARD property
This is more portable than specifying a compiler flag explicitly.

Signed-off-by: James Wrigley <james@puiterwijk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 7e4ea0d111)
2024-08-19 15:16:11 +02:00
Francesco Rollo
2f50ef2fe6 tests: add support for IPv4/IPv6 loopback network ID fallback in torture_config_match_localnetwork.c
Signed-off-by: Francesco <eferollo@gmail.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit b0b2e8fefd)
2024-08-02 11:21:02 +02:00
Jakub Jelen
eae3a60ef8 Fix proxy_disconnect on systems without pthread
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit b804aa9286)
2024-08-02 11:20:56 +02:00
Jakub Jelen
318f675ef8 match: Workaround matching on systems without IPv6
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit ab10f5c2f7)
2024-08-02 11:20:54 +02:00
Jakub Jelen
7beb580aab Conditional compilation of localnetwork matching
Some architectures (esp32) might not have this API.

Fixes: #263

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 9634668258)
2024-08-02 11:20:52 +02:00
203 changed files with 7696 additions and 19446 deletions

View File

@@ -26,4 +26,3 @@ BreakAfterReturnType: ExceptShortType
AlwaysBreakAfterReturnType: AllDefinitions
AlignEscapedNewlines: Left
ForEachMacros: ['ssh_callbacks_iterate']
AlignConsecutiveMacros: 'Consecutive'

1
.gitignore vendored
View File

@@ -10,4 +10,3 @@ tags
/build
/obj*
doc/tags.xml
.DS_Store

View File

@@ -27,17 +27,13 @@ workflow:
when: never
- if: '$CI_COMMIT_BRANCH'
.build_options:
.build:
stage: build
variables:
CMAKE_DEFAULT_OPTIONS: "-DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON"
CMAKE_DEFAULT_DEBUG_OPTIONS: "-DCMAKE_C_FLAGS='-O0 -g -ggdb' -DPICKY_DEVELOPER=ON"
CMAKE_BUILD_OPTIONS: "-DWITH_BLOWFISH_CIPHER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_DEBUG_PACKET=ON -DWITH_DEBUG_CALLTRACE=ON"
CMAKE_TEST_OPTIONS: "-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DGSSAPI_TESTING=ON -DWITH_BENCHMARKS=ON -DFUZZ_TESTING=ON"
CMAKE_OPTIONS: $CMAKE_DEFAULT_OPTIONS $CMAKE_BUILD_OPTIONS $CMAKE_TEST_OPTIONS
.build:
extends: .build_options
stage: build
before_script: &build
- uname -a
- cat /etc/os-release
@@ -125,7 +121,7 @@ review:
###############################################################################
# CentOS builds #
###############################################################################
centos10s/openssl_3.5.x/x86_64:
centos10s/openssl_3.2.x/x86_64:
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS10_BUILD
extends: .tests
variables:
@@ -136,7 +132,7 @@ centos10s/openssl_3.5.x/x86_64:
make -j$(nproc) &&
ctest --output-on-failure
centos10s/openssl_3.5.x/x86_64/fips:
centos10s/openssl_3.2.x/x86_64/fips:
extends: .fips
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS10_BUILD
variables:
@@ -147,7 +143,7 @@ centos10s/openssl_3.5.x/x86_64/fips:
make -j$(nproc) &&
OPENSSL_FORCE_FIPS_MODE=1 ctest --output-on-failure
centos9s/openssl_3.5.x/x86_64:
centos9s/openssl_3.0.x/x86_64:
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS9_BUILD
extends: .tests
variables:
@@ -164,7 +160,7 @@ centos9s/mbedtls_2.x/x86_64:
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_BLOWFISH_CIPHER=OFF"
centos9s/openssl_3.5.x/x86_64/fips:
centos9s/openssl_3.0.x/x86_64/fips:
extends: .fips
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS9_BUILD
script:
@@ -229,15 +225,15 @@ fedora/coverage:
coverage_format: cobertura
path: obj/coverage_xml.xml
fedora/openssl_3.x/x86_64:
fedora/openssl_3.0.x/x86_64:
extends: .fedora
fedora/openssl_3.x/x86_64/pkcs11-provider:
fedora/openssl_3.0.x/x86_64/pkcs11-provider:
variables:
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON -DWITH_PKCS11_PROVIDER=ON
extends: .fedora
fedora/openssl_3.x/x86_64/minimal:
fedora/openssl_3.0.x/x86_64/minimal:
extends: .fedora
variables:
script:
@@ -409,7 +405,7 @@ fedora/mingw32:
paths:
- obj-csbuild/
fedora/csbuild/openssl_3.x:
fedora/csbuild/openssl_3.0.x:
extends: .csbuild
script:
- csbuild
@@ -439,62 +435,6 @@ fedora/csbuild/mbedtls:
--color
--print-current --print-fixed
###############################################################################
# Fedora abidiff #
###############################################################################
fedora/abidiff:
stage: analysis
variables:
GIT_DEPTH: "100"
CMAKE_OPTIONS: $CMAKE_DEFAULT_DEBUG_OPTIONS $CMAKE_BUILD_OPTIONS
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
before_script:
- uname -a
- cat /etc/os-release
- mount
- df -h
- cat /proc/swaps
- free -h
- |
# for merge requests
if [[ -n "$CI_MERGE_REQUEST_DIFF_BASE_SHA" ]]; then
export CI_COMMIT_BEFORE_SHA="$CI_MERGE_REQUEST_DIFF_BASE_SHA"
fi
# for branches run
if [[ -z "$CI_COMMIT_BEFORE_SHA" ]]; then
export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20")
fi
# Check if the commit exists in this branch
# This is not the case for a force push
git branch --contains $CI_COMMIT_BEFORE_SHA 2>/dev/null || export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20")
- mkdir -p obj-${CI_COMMIT_BEFORE_SHA}
- mkdir -p obj-${CI_COMMIT_SHA}
- export INSTALL_DIR1=$(pwd)/install/${CI_COMMIT_BEFORE_SHA}
- export INSTALL_DIR2=$(pwd)/install/${CI_COMMIT_SHA}
script:
- git checkout ${CI_COMMIT_BEFORE_SHA}
- pushd obj-${CI_COMMIT_BEFORE_SHA}
- cmake ${CMAKE_OPTIONS} -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR1} .. &&
make -j$(nproc) && make -j$(nproc) install
- popd
- ls -l ${INSTALL_DIR1}/lib*/
- git checkout ${CI_COMMIT_SHA}
- pushd obj-${CI_COMMIT_SHA}
- cmake ${CMAKE_OPTIONS} -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR2} .. &&
make -j$(nproc) && make -j$(nproc) install
- popd
- ls -l ${INSTALL_DIR2}/lib*/
- ./.gitlab-ci/checkabi.sh ${INSTALL_DIR1} ${INSTALL_DIR2}
tags:
- saas-linux-small-amd64
except:
- tags
only:
- merge_requests
###############################################################################
# Ubuntu builds #
@@ -507,7 +447,7 @@ ubuntu/openssl_3.0.x/x86_64:
###############################################################################
# Alpine builds #
###############################################################################
alpine/openssl_3.x/musl:
alpine/openssl_3.0.x/musl:
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$ALPINE_BUILD
extends: .tests
script:
@@ -524,10 +464,10 @@ alpine/openssl_3.x/musl:
###############################################################################
# Tumbleweed builds #
###############################################################################
tumbleweed/openssl_3.x/x86_64/gcc:
tumbleweed/openssl_3.0.x/x86_64/gcc:
extends: .tumbleweed
tumbleweed/openssl_3.x/x86/gcc:
tumbleweed/openssl_3.0.x/x86/gcc:
extends: .tumbleweed
script:
- cmake
@@ -540,12 +480,12 @@ tumbleweed/openssl_3.x/x86/gcc:
-DUNIT_TESTING=ON .. &&
make -j$(nproc)
tumbleweed/openssl_3.x/x86_64/gcc7:
tumbleweed/openssl_3.0.x/x86_64/gcc7:
extends: .tumbleweed
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7"
tumbleweed/openssl_3.x/x86/gcc7:
tumbleweed/openssl_3.0.x/x86/gcc7:
extends: .tumbleweed
script:
- cmake
@@ -557,7 +497,7 @@ tumbleweed/openssl_3.x/x86/gcc7:
make -j$(nproc) &&
ctest --output-on-failure
tumbleweed/openssl_3.x/x86_64/clang:
tumbleweed/openssl_3.0.x/x86_64/clang:
extends: .tumbleweed
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++"
@@ -567,11 +507,6 @@ tumbleweed/mbedtls-3.6.x/x86_64/gcc:
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config -DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_BLOWFISH_CIPHER=OFF "
tumbleweed/mbedtls-3.6.x/x86_64/clang:
extends: .tumbleweed
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config -DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_BLOWFISH_CIPHER=OFF "
tumbleweed/static-analysis:
extends: .tests
stage: analysis
@@ -633,7 +568,9 @@ freebsd/openssl_1.1.1/x86_64:
# 2024-05-13: These jobs run out of the stages as they take extremely long and
# usually timeout with the update to Gitlab 17.0
.vs:
stage: test
stage: analysis
needs: []
allow_failure: true
cache:
key: vcpkg.${CI_JOB_NAME}
paths:
@@ -725,41 +662,3 @@ coverity:
when: on_failure
paths:
- obj/cov-int/*.txt
###############################################################################
# MacOS #
###############################################################################
.macos:
tags:
- saas-macos-medium-m1
image: macos-14-xcode-15
before_script:
- echo "MacOS runner started"
- brew update
- brew install cmake openssl cmocka doxygen
- mkdir obj && cd obj
only:
- branches@libssh/libssh-mirror
- branches@cryptomilk/libssh-mirror
- branches@jjelen/libssh-mirror
- branches@marco.fortina/libssh-mirror
# TODO add -DFUZZ_TESTING=ON clang cant find _LLVMFuzzerInitialize on arm64
macos-m1:
extends: .macos
variables:
HOMEBREW_NO_AUTO_UPDATE: 1
CMAKE_DEFAULT_OPTIONS: "-DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON"
CMAKE_BUILD_OPTIONS: "-DWITH_BLOWFISH_CIPHER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_DEBUG_PACKET=ON -DWITH_DEBUG_CALLTRACE=ON"
CMAKE_TEST_OPTIONS: "-DUNIT_TESTING=ON"
CMAKE_OPTIONS: $CMAKE_DEFAULT_OPTIONS $CMAKE_BUILD_OPTIONS $CMAKE_TEST_OPTIONS
stage: test
script:
- cmake $CMAKE_OPTIONS .. &&
make -j$(sysctl -n hw.logicalcpu) &&
ctest --output-on-failure
artifacts:
expire_in: 1 week
when: on_failure
paths:
- obj/

View File

@@ -1,42 +0,0 @@
#!/bin/bash
INSTALL_DIR1=${1}
INSTALL_DIR2=${2}
abidiff \
--headers-dir1 "${INSTALL_DIR1}/include/libssh/" \
--headers-dir2 "${INSTALL_DIR2}/include/libssh/" \
"${INSTALL_DIR1}/lib64/libssh.so" \
"${INSTALL_DIR2}/lib64/libssh.so" \
--fail-no-debug-info
abiret=$?
ABIDIFF_ERROR=$(((abiret & 0x01) != 0))
ABIDIFF_USAGE_ERROR=$(((abiret & 0x02) != 0))
ABIDIFF_ABI_CHANGE=$(((abiret & 0x04) != 0))
ABIDIFF_ABI_INCOMPATIBLE_CHANGE=$(((abiret & 0x08) != 0))
ABIDIFF_UNKNOWN_BIT_SET=$(((abiret & 0xf0) != 0))
if [ $ABIDIFF_ERROR -ne 0 ]; then
echo "abidiff reported ABIDIFF_ERROR."
exit 1
fi
if [ $ABIDIFF_USAGE_ERROR -ne 0 ]; then
echo "abidiff reported ABIDIFF_USAGE_ERROR."
exit 1
fi
if [ $ABIDIFF_UNKNOWN_BIT_SET -ne 0 ]; then
echo "abidiff reported ABIDIFF_UNKNOWN_BIT_SET."
exit 1
fi
if [ $ABIDIFF_ABI_INCOMPATIBLE_CHANGE -ne 0 ]; then
echo "abidiff result ABIDIFF_ABI_INCOMPATIBLE_CHANGE, this breaks the API!"
exit 1
fi
if [ $ABIDIFF_ABI_CHANGE -ne 0 ]; then
echo "Ignoring abidiff result ABI_CHANGE"
fi
exit 0

View File

@@ -1,16 +0,0 @@
Add a description of the new feature/bug fix. Reference any relevant bugs.
## Checklist
* [ ] Commits have `Signed-off-by:` with name/author being identical to the commit author
* [ ] Code modified for feature
* [ ] Test suite updated with functionality tests
* [ ] Test suite updated with negative tests
* [ ] Documentation updated
* [ ] The project pipelines timeout is [extended](https://docs.gitlab.com/ee/ci/pipelines/settings.html#set-a-limit-for-how-long-jobs-can-run) at least to 2 hours.
## Reviewer's checklist:
* [ ] Any issues marked for closing are addressed
* [ ] There is a test suite reasonably covering new functionality or modifications
* [ ] Function naming, parameters, return values, types, etc., are consistent and according to [CONTRIBUTING.md](https://gitlab.com/libssh/libssh-mirror/-/blob/master/CONTRIBUTING.md)
* [ ] This feature/change has adequate documentation added
* [ ] No obvious mistakes in the code

View File

@@ -1,6 +1,35 @@
CHANGELOG
=========
version 0.11.2 (released 2025-06-24)
* Security:
* CVE-2025-4877 - Write beyond bounds in binary to base64 conversion
* CVE-2025-4878 - Use of uninitialized variable in privatekey_from_file()
* CVE-2025-5318 - Likely read beyond bounds in sftp server handle management
* CVE-2025-5351 - Double free in functions exporting keys
* CVE-2025-5372 - ssh_kdf() returns a success code on certain failures
* CVE-2025-5449 - Likely read beyond bounds in sftp server message decoding
* CVE-2025-5987 - Invalid return code for chacha20 poly1305 with OpenSSL
* Compatibility
* Fixed compatibility with CPM.cmake
* Compatibility with OpenSSH 10.0
* Tests compatibility with new Dropbear releases
* Removed p11-kit remoting from the pkcs11 testsuite
* Bugfixes
* Implement missing packet filter for DH GEX
* Properly process the SSH2_MSG_DEBUG message
* Allow escaping quotes in quoted arguments to ssh configuration
* Do not fail with unknown match keywords in ssh configuration
* Process packets before selecting signature algorithm during authentication
* Do not fail hard when the SFTP status message is not sent by noncompliant
servers
version 0.11.1 (released 2024-08-30)
* Fixed default TTY modes that are set when stdin is not connected to tty (#270)
* Fixed zlib cleanup procedure, which could crash on i386
* Various test fixes improving their stability
* Fixed cygwin build
version 0.11.0 (released 2024-07-31)
* Deprecations and Removals:
* Dropped support for DSA

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.14.0)
cmake_minimum_required(VERSION 3.12.0)
# Specify search path for CMake modules to be loaded by include()
# and find_package()
@@ -9,7 +9,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
include(DefineCMakeDefaults)
include(DefineCompilerFlags)
project(libssh VERSION 0.11.00 LANGUAGES C)
project(libssh VERSION 0.11.2 LANGUAGES C)
# global needed variable
set(APPLICATION_NAME ${PROJECT_NAME})
@@ -21,7 +21,7 @@ set(APPLICATION_NAME ${PROJECT_NAME})
# Increment AGE. Set REVISION to 0
# If the source code was changed, but there were no interface changes:
# Increment REVISION.
set(LIBRARY_VERSION "4.10.0")
set(LIBRARY_VERSION "4.10.2")
set(LIBRARY_SOVERSION "4")
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
@@ -41,8 +41,6 @@ macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out of source buil
# Copy library files to a lib sub-directory
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
set(LIBSSSH_PC_REQUIRES_PRIVATE "")
# search for libraries
if (WITH_ZLIB)
find_package(ZLIB REQUIRED)
@@ -68,7 +66,6 @@ find_package(Threads)
if (WITH_GSSAPI)
find_package(GSSAPI)
list(APPEND LIBSSH_PC_REQUIRES_PRIVATE ${GSSAPI_PC_REQUIRES})
endif (WITH_GSSAPI)
if (WITH_NACL)
@@ -199,7 +196,7 @@ if (WITH_COVERAGE)
NAME "coverage"
EXECUTABLE make test
DEPENDENCIES ssh tests)
set(GCOVR_ADDITIONAL_ARGS --xml-pretty --exclude-unreachable-branches --print-summary --gcov-ignore-parse-errors)
set(GCOVR_ADDITIONAL_ARGS --xml-pretty --exclude-unreachable-branches --print-summary)
setup_target_for_coverage_gcovr_xml(
NAME "coverage_xml"
EXECUTABLE make test
@@ -252,15 +249,9 @@ message(STATUS "Benchmarks: ${WITH_BENCHMARKS}")
message(STATUS "Symbol versioning: ${WITH_SYMBOL_VERSIONING}")
message(STATUS "Allow ABI break: ${WITH_ABI_BREAK}")
message(STATUS "Release is final: ${WITH_FINAL}")
if (WITH_HERMETIC_USR)
message(STATUS "User global client config: ${USR_GLOBAL_CLIENT_CONFIG}")
endif ()
message(STATUS "Global client config: ${GLOBAL_CLIENT_CONFIG}")
if (WITH_SERVER)
if (WITH_HERMETIC_USR)
message(STATUS "User global bind config: ${USR_GLOBAL_BIND_CONFIG}")
endif ()
message(STATUS "Global bind config: ${GLOBAL_BIND_CONFIG}")
message(STATUS "Global bind config: ${GLOBAL_BIND_CONFIG}")
endif()
message(STATUS "********************************************")

View File

@@ -117,25 +117,6 @@ libssh Developer's Certificate of Origin for each patch, or inside each
patch. Just the sign-off message is all that is required once we've
received the initial email.
## Continuous Integration
Contributing patches through Merge Request workflow on Gitlab allows us to run
various checks on various configuration as part of Gitlab CI. Unfortunately,
some pipelines are slower (as they involve building dependencies) so the default
timeout of 1 hour needs to be extended at least to 2 hours. This can be done in
project settings of your libssh fork:
https://docs.gitlab.com/ee/ci/pipelines/settings.html#set-a-limit-for-how-long-jobs-can-run
Otherwise you will encounter errors like these, usually on visualstudio builds:
```
ERROR: Job failed: execution took longer than 1h0m0s seconds
The script exceeded the maximum execution time set for the job
```
Note, that the built dependencies are cached so after successful build in your
namespace, the rebuilds should be much faster.
# Coding conventions in the libssh tree
@@ -536,37 +517,6 @@ Bad example:
break;
}
## ABI Versioning and Symbol Management
To maintain [ABI](https://en.wikipedia.org/wiki/Application_binary_interface) stability
and ensure backward compatibility, libssh uses **symbol versioning** to track and manage
exported functions and variables. This allows libssh to introduce new symbols or modify
existing functions in an ABI-compatible way.
When introducing a new symbol:
1. Use the `LIBSSH_API` macro to mark the symbol as part of the public API.
2. If you have [abimap](https://github.com/ansasaki/abimap) installed, the new symbols are
automatically generated in the `src/libssh_dev.map` file in the **build** directory and used automatically for building the updated library. But, depending on the version of `abimap` under use, you may face linker errors like: `unable to find version dependency LIBSSH_4_9_0`. In this case, you need to manually replace the existing `src/libssh.map` file with the generated `libssh_dev.map` file to update the symbol versioning.
3. If you do not have abimap installed, the modified/added symbols must manually be added to the
`src/libssh.map` file. The symbols must be added in the following format (assuming that 4_10_0 is the latest released version):
```
LIBSSH_AFTER_4_10_0
{
global:
new_function;
new_variable;
} LIBSSH_4_10_0;
```
4. After following either of the above steps, the library can be successfully built and
tested without any linker errors.
5. When submitting the patch, make sure that any new symbols have been added to `libssh.map` as described in step 3, so that the new additions may not be excluded from the next release due to human error.
Also, to maintain ABI compatibility, existing symbols must not be removed. Instead, they can
be marked as deprecated using the `LIBSSH_DEPRECATED` macro. This allows the symbol to be
removed in a future release without breaking the ABI.
Have fun and happy libssh hacking!

View File

@@ -104,11 +104,6 @@ if (OPENSSL_FOUND)
check_function_exists(RAND_priv_bytes HAVE_OPENSSL_RAND_PRIV_BYTES)
check_function_exists(EVP_chacha20 HAVE_OPENSSL_EVP_CHACHA20)
# Check for ML-KEM768 availability (OpenSSL 3.5+)
if (OPENSSL_VERSION VERSION_GREATER_EQUAL "3.5.0")
set(HAVE_MLKEM 1)
endif ()
unset(CMAKE_REQUIRED_INCLUDES)
unset(CMAKE_REQUIRED_LIBRARIES)
endif()
@@ -231,7 +226,6 @@ if (GCRYPT_FOUND)
endif (GCRYPT_VERSION VERSION_GREATER "1.4.6")
if (NOT GCRYPT_VERSION VERSION_LESS "1.7.0")
set(HAVE_GCRYPT_CHACHA_POLY 1)
set(HAVE_GCRYPT_CURVE25519 1)
endif (NOT GCRYPT_VERSION VERSION_LESS "1.7.0")
endif (GCRYPT_FOUND)
@@ -242,13 +236,6 @@ if (MBEDTLS_FOUND)
set(CMAKE_REQUIRED_INCLUDES "${MBEDTLS_INCLUDE_DIR}/mbedtls")
check_include_file(chacha20.h HAVE_MBEDTLS_CHACHA20_H)
check_include_file(poly1305.h HAVE_MBEDTLS_POLY1305_H)
if (MBEDTLS_VERSION VERSION_LESS "3.0.0")
check_symbol_exists(MBEDTLS_ECP_DP_CURVE25519_ENABLED "config.h" HAVE_MBEDTLS_CURVE25519)
else()
check_symbol_exists(MBEDTLS_ECP_DP_CURVE25519_ENABLED "mbedtls_config.h" HAVE_MBEDTLS_CURVE25519)
endif()
if (WITH_BLOWFISH_CIPHER)
check_include_file(blowfish.h HAVE_BLOWFISH)
endif()

View File

@@ -27,7 +27,6 @@ option(WITH_INSECURE_NONE "Enable insecure none cipher and MAC algorithms (not s
option(WITH_EXEC "Enable libssh to execute arbitrary commands from configuration files or options (match exec, proxy commands and OpenSSH-based proxy-jumps)." ON)
option(FUZZ_TESTING "Build with fuzzer for the server and client (automatically enables none cipher!)" OFF)
option(PICKY_DEVELOPER "Build with picky developer flags" OFF)
option(WITH_HERMETIC_USR "Build with support for hermetic /usr/" OFF)
if (WITH_ZLIB)
set(WITH_LIBZ ON)
@@ -60,11 +59,6 @@ if (NOT GLOBAL_CLIENT_CONFIG)
set(GLOBAL_CLIENT_CONFIG "/etc/ssh/ssh_config")
endif (NOT GLOBAL_CLIENT_CONFIG)
if (WITH_HERMETIC_USR)
set(USR_GLOBAL_BIND_CONFIG "/usr${GLOBAL_BIND_CONFIG}")
set(USR_GLOBAL_CLIENT_CONFIG "/usr${GLOBAL_CLIENT_CONFIG}")
endif (WITH_HERMETIC_USR)
if (FUZZ_TESTING)
set(WITH_INSECURE_NONE ON)
endif (FUZZ_TESTING)

View File

@@ -38,16 +38,14 @@ First, you need to configure the compilation, using CMake. Go inside the
`build` dir. Create it if it doesn't exist.
GNU/Linux, MacOS X, MSYS/MinGW:
cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug ..
cmake -DUNIT_TESTING=ON -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug ..
make
On Windows you should choose a makefile generator with -G or use
cmake-gui.exe ..
To enable building tests use -DUNIT_TESTING=ON. For this, the
[cmocka](https://cmocka.org) dependency is required.
To enable additional client tests against a local OpenSSH server, add the
compile option -DCLIENT_TESTING=ON. These tests require an OpenSSH
server package and some wrapper libraries (see optional requirements) to

View File

@@ -11,8 +11,6 @@
# GSSAPI_INCLUDE_DIR - the GSSAPI include directory
# GSSAPI_LIBRARIES - Link these to use GSSAPI
# GSSAPI_DEFINITIONS - Compiler switches required for using GSSAPI
# GSSAPI_PC_REQUIRES - pkg-config module name if found, needed for
# Requires.private for static linking
#
#=============================================================================
# Copyright (c) 2013 Andreas Schneider <asn@cryptomilk.org>
@@ -26,23 +24,12 @@
#=============================================================================
#
set(_mit_modname "mit-krb5-gssapi")
set(_heimdal_modname "heimdal-gssapi")
if(NOT _GSSAPI_ROOT_HINTS AND NOT _GSSAPI_ROOT_PATHS)
find_package(PkgConfig QUIET)
if (PKG_CONFIG_FOUND)
pkg_search_module(_GSSAPI ${_mit_modname} ${_heimdal_modname})
endif()
endif()
find_path(GSSAPI_ROOT_DIR
NAMES
include/gssapi.h
include/gssapi/gssapi.h
HINTS
${_GSSAPI_ROOT_HINTS}
"${_GSSAPI_INCLUDEDIR}"
PATHS
${_GSSAPI_ROOT_PATHS}
)
@@ -330,15 +317,9 @@ endif (GSSAPI_FLAVOR_HEIMDAL)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(GSSAPI DEFAULT_MSG GSSAPI_LIBRARIES GSSAPI_INCLUDE_DIR)
if(GSSAPI_FOUND)
if(_GSSAPI_FOUND) # via pkg-config
if (GSSAPI_FLAVOR_MIT)
set(GSSAPI_PC_REQUIRES ${_mit_modname})
elseif (GSSAPI_FLAVOR_HEIMDAL)
set(GSSAPI_PC_REQUIRES ${_heimdal_modname})
endif()
endif()
endif()
if (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES)
set(GSSAPI_FOUND TRUE)
endif (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES)
# show the GSSAPI_INCLUDE_DIR and GSSAPI_LIBRARIES variables only in the advanced view
mark_as_advanced(GSSAPI_INCLUDE_DIR GSSAPI_LIBRARIES)
# show the GSSAPI_INCLUDE_DIRS and GSSAPI_LIBRARIES variables only in the advanced view
mark_as_advanced(GSSAPI_INCLUDE_DIRS GSSAPI_LIBRARIES)

View File

@@ -72,23 +72,21 @@ find_library(MBEDTLS_X509_LIBRARY
set(MBEDTLS_LIBRARIES ${MBEDTLS_SSL_LIBRARY} ${MBEDTLS_CRYPTO_LIBRARY}
${MBEDTLS_X509_LIBRARY})
# mbedtls 2.8
if (MBEDTLS_INCLUDE_DIR AND EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h")
# mbedtls 2.8
file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h" _mbedtls_version_str REGEX
"^#[\t ]*define[\t ]+MBEDTLS_VERSION_STRING[\t ]+\"[0-9]+.[0-9]+.[0-9]+\"")
string(REGEX REPLACE "^.*MBEDTLS_VERSION_STRING.*([0-9]+\\.[0-9]+\\.[0-9]+).*$"
string(REGEX REPLACE "^.*MBEDTLS_VERSION_STRING.*([0-9]+.[0-9]+.[0-9]+).*"
"\\1" MBEDTLS_VERSION "${_mbedtls_version_str}")
endif()
# mbedtls 3.6
if (NOT MBEDTLS_VERSION AND MBEDTLS_INCLUDE_DIR AND EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h")
file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h" _mbedtls_version_str REGEX
elseif (MBEDTLS_INCLUDE_DIR AND EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h")
# mbedtls 3.6
file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h" _mbedtls_version_str REGEX
"^#[\t ]*define[\t ]+MBEDTLS_VERSION_STRING[\t ]+\"[0-9]+.[0-9]+.[0-9]+\"")
string(REGEX REPLACE "^.*MBEDTLS_VERSION_STRING.*([0-9]+\\.[0-9]+\\.[0-9]+).*$"
string(REGEX REPLACE "^.*MBEDTLS_VERSION_STRING.*([0-9]+.[0-9]+.[0-9]+).*"
"\\1" MBEDTLS_VERSION "${_mbedtls_version_str}")
endif()
endif ()
include(FindPackageHandleStandardArgs)
if (MBEDTLS_VERSION)

View File

@@ -9,11 +9,9 @@
#cmakedefine SOURCEDIR "${SOURCEDIR}"
/* Global bind configuration file path */
#cmakedefine USR_GLOBAL_BIND_CONFIG "${USR_GLOBAL_BIND_CONFIG}"
#cmakedefine GLOBAL_BIND_CONFIG "${GLOBAL_BIND_CONFIG}"
/* Global client configuration file path */
#cmakedefine USR_GLOBAL_CLIENT_CONFIG "${USR_GLOBAL_CLIENT_CONFIG}"
#cmakedefine GLOBAL_CLIENT_CONFIG "${GLOBAL_CLIENT_CONFIG}"
/************************** HEADER FILES *************************/
@@ -87,9 +85,6 @@
/* Define to 1 if you have elliptic curve cryptography in openssl */
#cmakedefine HAVE_OPENSSL_ECC 1
/* Define to 1 if mbedTLS supports curve25519 */
#cmakedefine HAVE_MBEDTLS_CURVE25519 1
/* Define to 1 if you have elliptic curve cryptography in gcrypt */
#cmakedefine HAVE_GCRYPT_ECC 1
@@ -102,9 +97,6 @@
/* Define to 1 if you have gcrypt with ChaCha20/Poly1305 support */
#cmakedefine HAVE_GCRYPT_CHACHA_POLY 1
/* Define to 1 if you have gcrypt with curve25519 support */
#cmakedefine HAVE_GCRYPT_CURVE25519
/*************************** FUNCTIONS ***************************/
/* Define to 1 if you have the `EVP_chacha20' function. */
@@ -191,9 +183,6 @@
/* Define to 1 if we have support for blowfish */
#cmakedefine HAVE_BLOWFISH 1
/* Define to 1 if we have support for ML-KEM */
#cmakedefine HAVE_MLKEM 1
/*************************** LIBRARIES ***************************/
/* Define to 1 if you have the `crypto' library (-lcrypto). */

View File

@@ -91,10 +91,4 @@ that it used:
}
@endcode
Warning: In a single channel, only ONE command can be executed!
If you want to executed multiple commands, allocate separate channels for
them or consider opening interactive shell.
Attempting to run multiple consecutive commands in one channel will fail.
*/

View File

@@ -19,7 +19,7 @@ the interesting functions as you go.
The libssh library provides:
- <strong>Key Exchange Methods</strong>: <i>sntrup761x25519-sha512, sntrup761x25519-sha512@openssh.com, mlkem768x25519-sha256, curve25519-sha256, curve25519-sha256@libssh.org, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521</i>, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1
- <strong>Key Exchange Methods</strong>: <i>curve25519-sha256, curve25519-sha256@libssh.org, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521</i>, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1
- <strong>Public Key Algorithms</strong>: ssh-ed25519, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, ssh-rsa, rsa-sha2-512, rsa-sha2-256
- <strong>Ciphers</strong>: <i>aes256-ctr, aes192-ctr, aes128-ctr</i>, aes256-cbc (rijndael-cbc@lysator.liu.se), aes192-cbc, aes128-cbc, 3des-cbc, blowfish-cbc
- <strong>Compression Schemes</strong>: zlib, <i>zlib@openssh.com</i>, none

View File

@@ -303,6 +303,7 @@ span.lineno {
padding-right: 4px;
text-align: right;
color: black;
height: 100px;
white-space: pre;
border-right: 3px solid #1d7567;
background-color: #323232; }

View File

@@ -66,6 +66,7 @@ int authenticate_kbdint(ssh_session session, const char *password)
return SSH_AUTH_ERROR;
}
buffer[sizeof(buffer) - 1] = '\0';
if ((p = strchr(buffer, '\n'))) {
*p = '\0';
}
@@ -74,7 +75,7 @@ int authenticate_kbdint(ssh_session session, const char *password)
return SSH_AUTH_ERROR;
}
memset(buffer, 0, sizeof(buffer));
memset(buffer, 0, strlen(buffer));
} else {
if (password && strstr(prompt, "Password:")) {
answer = password;
@@ -146,7 +147,7 @@ int authenticate_console(ssh_session session)
// Try to authenticate
rc = ssh_userauth_none(session, NULL);
if (rc == SSH_AUTH_ERROR || !ssh_is_connected(session)) {
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
}
@@ -155,7 +156,7 @@ int authenticate_console(ssh_session session)
while (rc != SSH_AUTH_SUCCESS) {
if (method & SSH_AUTH_METHOD_GSSAPI_MIC){
rc = ssh_userauth_gssapi(session);
if (rc == SSH_AUTH_ERROR || !ssh_is_connected(session)) {
if(rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
@@ -165,7 +166,7 @@ int authenticate_console(ssh_session session)
// Try to authenticate with public key first
if (method & SSH_AUTH_METHOD_PUBLICKEY) {
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
if (rc == SSH_AUTH_ERROR || !ssh_is_connected(session)) {
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
@@ -205,7 +206,7 @@ int authenticate_console(ssh_session session)
// Try to authenticate with keyboard interactive";
if (method & SSH_AUTH_METHOD_INTERACTIVE) {
rc = authenticate_kbdint(session, NULL);
if (rc == SSH_AUTH_ERROR || !ssh_is_connected(session)) {
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
@@ -220,7 +221,7 @@ int authenticate_console(ssh_session session)
// Try to authenticate with password
if (method & SSH_AUTH_METHOD_PASSWORD) {
rc = ssh_userauth_password(session, NULL, password);
if (rc == SSH_AUTH_ERROR || !ssh_is_connected(session)) {
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {

View File

@@ -21,57 +21,47 @@ clients must be made or how a client should react.
#include "examples_common.h"
#include <stdio.h>
ssh_session connect_ssh(const char *host, const char *port, const char *user, int verbosity)
{
ssh_session session = NULL;
int auth = 0;
ssh_session connect_ssh(const char *host, const char *user,int verbosity){
ssh_session session = NULL;
int auth=0;
session = ssh_new();
if (session == NULL) {
return NULL;
}
session=ssh_new();
if (session == NULL) {
return NULL;
}
if (user != NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
ssh_free(session);
return NULL;
}
if(user != NULL){
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
ssh_free(session);
return NULL;
}
}
if (port != NULL) {
if (ssh_options_set(session, SSH_OPTIONS_PORT_STR, port) < 0) {
ssh_free(session);
return NULL;
}
}
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) {
ssh_free(session);
return NULL;
}
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
if (ssh_connect(session)) {
fprintf(stderr, "Connection failed : %s\n", ssh_get_error(session));
ssh_disconnect(session);
ssh_free(session);
return NULL;
}
if (verify_knownhost(session) < 0) {
ssh_disconnect(session);
ssh_free(session);
return NULL;
}
auth = authenticate_console(session);
if (auth == SSH_AUTH_SUCCESS) {
return session;
} else if (auth == SSH_AUTH_DENIED) {
fprintf(stderr, "Authentication failed\n");
} else {
fprintf(stderr,
"Error while authenticating : %s\n",
ssh_get_error(session));
}
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) {
ssh_free(session);
return NULL;
}
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
if(ssh_connect(session)){
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
ssh_disconnect(session);
ssh_free(session);
return NULL;
}
if(verify_knownhost(session)<0){
ssh_disconnect(session);
ssh_free(session);
return NULL;
}
auth=authenticate_console(session);
if(auth==SSH_AUTH_SUCCESS){
return session;
} else if(auth==SSH_AUTH_DENIED){
fprintf(stderr,"Authentication failed\n");
} else {
fprintf(stderr,"Error while authenticating : %s\n",ssh_get_error(session));
}
ssh_disconnect(session);
ssh_free(session);
return NULL;
}

View File

@@ -16,11 +16,11 @@ clients must be made or how a client should react.
#include <libssh/libssh.h>
/** Zero a structure */
#define ZERO_STRUCT(x) memset(&(x), 0, sizeof(x))
#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
int authenticate_console(ssh_session session);
int authenticate_kbdint(ssh_session session, const char *password);
int verify_knownhost(ssh_session session);
ssh_session connect_ssh(const char *hostname, const char *port, const char *user, int verbosity);
ssh_session connect_ssh(const char *hostname, const char *user, int verbosity);
#endif /* EXAMPLES_COMMON_H_ */

View File

@@ -11,7 +11,7 @@ int main(void) {
int rbytes, wbytes, total = 0;
int rc;
session = connect_ssh("localhost", NULL, NULL, 0);
session = connect_ssh("localhost", NULL, 0);
if (session == NULL) {
ssh_finalize();
return 1;

View File

@@ -350,12 +350,7 @@ int main(int argc, char *argv[])
goto end;
}
if (arguments.file == NULL) {
fprintf(stderr, "Error: Missing argument file\n");
goto end;
}
if (arguments.action_list) {
if (arguments.action_list && arguments.file) {
list_fingerprint(arguments.file);
goto end;
}

View File

@@ -30,7 +30,6 @@ static char **sources = NULL;
static int nsources;
static char *destination = NULL;
static int verbosity = 0;
static char *port = NULL;
struct location {
int is_ssh;
@@ -50,10 +49,9 @@ enum {
static void usage(const char *argv0) {
fprintf(stderr, "Usage : %s [options] [[user@]host1:]file1 ... \n"
" [[user@]host2:]destination\n"
"sample scp client - libssh-%s\n"
"Options :\n"
" -P : use port to connect to remote host\n"
" -v : increase verbosity of libssh. Can be used multiple times\n",
"sample scp client - libssh-%s\n",
// "Options :\n",
// " -r : use RSA to verify host public key\n",
argv0,
ssh_version(0));
exit(0);
@@ -62,14 +60,11 @@ static void usage(const char *argv0) {
static int opts(int argc, char **argv) {
int i;
while((i = getopt(argc, argv, "P:v")) != -1) {
while((i = getopt(argc, argv, "v")) != -1) {
switch(i) {
case 'v':
verbosity++;
break;
case 'P':
port = optarg;
break;
default:
fprintf(stderr, "unknown option %c\n", optopt);
usage(argv[0]);
@@ -124,10 +119,6 @@ static struct location *parse_location(char *loc)
struct location *location = NULL;
char *ptr = NULL;
if (loc == NULL) {
return NULL;
}
location = malloc(sizeof(struct location));
if (location == NULL) {
return NULL;
@@ -188,7 +179,7 @@ static void close_location(struct location *loc) {
static int open_location(struct location *loc, int flag) {
if (loc->is_ssh && flag == WRITE) {
loc->session = connect_ssh(loc->host, port, loc->user, verbosity);
loc->session = connect_ssh(loc->host, loc->user, verbosity);
if (!loc->session) {
fprintf(stderr, "Couldn't connect to %s\n", loc->host);
return -1;
@@ -214,7 +205,7 @@ static int open_location(struct location *loc, int flag) {
}
return 0;
} else if (loc->is_ssh && flag == READ) {
loc->session = connect_ssh(loc->host, port, loc->user, verbosity);
loc->session = connect_ssh(loc->host, loc->user, verbosity);
if (!loc->session) {
fprintf(stderr, "Couldn't connect to %s\n", loc->host);
return -1;

View File

@@ -148,7 +148,6 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
ssh_bind sshbind = state->input;
static int no_default_keys = 0;
static int rsa_already_set = 0, ecdsa_already_set = 0;
static int verbosity = 0;
switch (key)
{
@@ -177,10 +176,8 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
strncpy(authorizedkeys, arg, DEF_STR_SIZE - 1);
break;
case 'v':
verbosity++;
ssh_bind_options_set(sshbind,
SSH_BIND_OPTIONS_LOG_VERBOSITY,
&verbosity);
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR,
"3");
break;
case ARGP_KEY_ARG:
if (state->arg_num >= 1)
@@ -216,7 +213,10 @@ static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
#endif /* HAVE_ARGP_H */
/* A userdata struct for channel. */
struct channel_data_struct {
struct channel_data_struct
{
/* Event which is used to poll the above descriptors. */
ssh_event event;
sftp_session sftp;
};
@@ -378,11 +378,18 @@ static void handle_session(ssh_event event, ssh_session session)
do {
/* Poll the main event which takes care of the session, the channel and
* even our child process's stdout/stderr (once it's started). */
if (ssh_event_dopoll(event, 100) == SSH_ERROR) {
if (ssh_event_dopoll(event, -1) == SSH_ERROR) {
ssh_channel_close(sdata.channel);
}
} while (ssh_channel_is_open(sdata.channel) &&
!ssh_channel_is_eof(sdata.channel));
/* If child process's stdout/stderr has been registered with the event,
* or the child process hasn't started yet, continue. */
if (cdata.event != NULL) {
continue;
}
/* FIXME The server keeps hanging in the poll above when the client
* closes the channel */
} while (ssh_channel_is_open(sdata.channel));
ssh_channel_send_eof(sdata.channel);
ssh_channel_close(sdata.channel);

View File

@@ -32,163 +32,151 @@ static const char *createcommand =
"cd /tmp/libssh_tests && date > a && date > b && mkdir c && date > d";
static char *host = NULL;
static void usage(const char *argv0)
{
fprintf(stderr,
"Usage : %s [options] host\n"
"sample tiny scp downloader client - libssh-%s\n"
"This program will create files in /tmp and try to fetch them\n",
argv0,
ssh_version(0));
exit(0);
static void usage(const char *argv0){
fprintf(stderr,"Usage : %s [options] host\n"
"sample tiny scp downloader client - libssh-%s\n"
"This program will create files in /tmp and try to fetch them\n",
// "Options :\n",
// " -r : use RSA to verify host public key\n",
argv0,
ssh_version(0));
exit(0);
}
static int opts(int argc, char **argv)
{
int i;
while ((i = getopt(argc, argv, "v")) != -1) {
switch (i) {
case 'v':
verbosity++;
break;
default:
fprintf(stderr, "unknown option %c\n", optopt);
usage(argv[0]);
return -1;
}
}
host = argv[optind];
if (host == NULL)
static int opts(int argc, char **argv){
int i;
while((i=getopt(argc,argv,"v"))!=-1){
switch(i){
case 'v':
verbosity++;
break;
default:
fprintf(stderr,"unknown option %c\n",optopt);
usage(argv[0]);
return 0;
}
static void create_files(ssh_session session)
{
ssh_channel channel = ssh_channel_new(session);
char buffer[1];
int rc;
if (channel == NULL) {
fprintf(stderr, "Error creating channel: %s\n", ssh_get_error(session));
exit(EXIT_FAILURE);
}
if (ssh_channel_open_session(channel) != SSH_OK) {
fprintf(stderr, "Error creating channel: %s\n", ssh_get_error(session));
ssh_channel_free(channel);
exit(EXIT_FAILURE);
}
if (ssh_channel_request_exec(channel, createcommand) != SSH_OK) {
fprintf(stderr,
"Error executing command: %s\n",
ssh_get_error(session));
ssh_channel_close(channel);
ssh_channel_free(channel);
exit(EXIT_FAILURE);
}
while (!ssh_channel_is_eof(channel)) {
rc = ssh_channel_read(channel, buffer, 1, 1);
if (rc != 1) {
fprintf(stderr, "Error reading from channel\n");
ssh_channel_close(channel);
ssh_channel_free(channel);
return;
}
rc = write(1, buffer, 1);
if (rc < 0) {
fprintf(stderr, "Error writing to buffer\n");
ssh_channel_close(channel);
ssh_channel_free(channel);
return;
}
}
ssh_channel_close(channel);
ssh_channel_free(channel);
}
static int fetch_files(ssh_session session)
{
int size;
char buffer[BUF_SIZE];
int mode;
char *filename = NULL;
int r;
ssh_scp scp = ssh_scp_new(session,
SSH_SCP_READ | SSH_SCP_RECURSIVE,
"/tmp/libssh_tests/*");
if (ssh_scp_init(scp) != SSH_OK) {
fprintf(stderr, "error initializing scp: %s\n", ssh_get_error(session));
ssh_scp_free(scp);
return -1;
}
printf("Trying to download 3 files (a,b,d) and 1 directory (c)\n");
do {
r = ssh_scp_pull_request(scp);
switch (r) {
case SSH_SCP_REQUEST_NEWFILE:
size = ssh_scp_request_get_size(scp);
filename = strdup(ssh_scp_request_get_filename(scp));
mode = ssh_scp_request_get_permissions(scp);
printf("downloading file %s, size %d, perms 0%o\n",
filename,
size,
mode);
free(filename);
ssh_scp_accept_request(scp);
r = ssh_scp_read(scp, buffer, sizeof(buffer));
if (r == SSH_ERROR) {
fprintf(stderr,
"Error reading scp: %s\n",
ssh_get_error(session));
ssh_scp_close(scp);
ssh_scp_free(scp);
return -1;
}
printf("done\n");
break;
case SSH_ERROR:
fprintf(stderr, "Error: %s\n", ssh_get_error(session));
ssh_scp_close(scp);
ssh_scp_free(scp);
return -1;
case SSH_SCP_REQUEST_WARNING:
fprintf(stderr, "Warning: %s\n", ssh_scp_request_get_warning(scp));
break;
case SSH_SCP_REQUEST_NEWDIR:
filename = strdup(ssh_scp_request_get_filename(scp));
mode = ssh_scp_request_get_permissions(scp);
printf("downloading directory %s, perms 0%o\n", filename, mode);
free(filename);
ssh_scp_accept_request(scp);
break;
case SSH_SCP_REQUEST_ENDDIR:
printf("End of directory\n");
break;
case SSH_SCP_REQUEST_EOF:
printf("End of requests\n");
goto end;
}
} while (1);
end:
ssh_scp_close(scp);
ssh_scp_free(scp);
return 0;
}
host = argv[optind];
if(host == NULL)
usage(argv[0]);
return 0;
}
int main(int argc, char **argv)
{
ssh_session session = NULL;
if (opts(argc, argv) < 0)
return EXIT_FAILURE;
session = connect_ssh(host, NULL, NULL, verbosity);
if (session == NULL)
return EXIT_FAILURE;
create_files(session);
fetch_files(session);
ssh_disconnect(session);
ssh_free(session);
ssh_finalize();
return 0;
static void create_files(ssh_session session){
ssh_channel channel=ssh_channel_new(session);
char buffer[1];
int rc;
if(channel == NULL){
fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session));
exit(EXIT_FAILURE);
}
if(ssh_channel_open_session(channel) != SSH_OK){
fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session));
ssh_channel_free(channel);
exit(EXIT_FAILURE);
}
if(ssh_channel_request_exec(channel,createcommand) != SSH_OK){
fprintf(stderr,"Error executing command: %s\n",ssh_get_error(session));
ssh_channel_close(channel);
ssh_channel_free(channel);
exit(EXIT_FAILURE);
}
while(!ssh_channel_is_eof(channel)){
rc = ssh_channel_read(channel,buffer,1,1);
if (rc != 1) {
fprintf(stderr, "Error reading from channel\n");
ssh_channel_close(channel);
ssh_channel_free(channel);
return;
}
rc = write(1, buffer, 1);
if (rc < 0) {
fprintf(stderr, "Error writing to buffer\n");
ssh_channel_close(channel);
ssh_channel_free(channel);
return;
}
}
ssh_channel_close(channel);
ssh_channel_free(channel);
}
static int fetch_files(ssh_session session){
int size;
char buffer[BUF_SIZE];
int mode;
char *filename = NULL;
int r;
ssh_scp scp=ssh_scp_new(session, SSH_SCP_READ | SSH_SCP_RECURSIVE, "/tmp/libssh_tests/*");
if(ssh_scp_init(scp) != SSH_OK){
fprintf(stderr,"error initializing scp: %s\n",ssh_get_error(session));
ssh_scp_free(scp);
return -1;
}
printf("Trying to download 3 files (a,b,d) and 1 directory (c)\n");
do {
r=ssh_scp_pull_request(scp);
switch(r){
case SSH_SCP_REQUEST_NEWFILE:
size=ssh_scp_request_get_size(scp);
filename=strdup(ssh_scp_request_get_filename(scp));
mode=ssh_scp_request_get_permissions(scp);
printf("downloading file %s, size %d, perms 0%o\n",filename,size,mode);
free(filename);
ssh_scp_accept_request(scp);
r=ssh_scp_read(scp,buffer,sizeof(buffer));
if(r==SSH_ERROR){
fprintf(stderr,"Error reading scp: %s\n",ssh_get_error(session));
ssh_scp_close(scp);
ssh_scp_free(scp);
return -1;
}
printf("done\n");
break;
case SSH_ERROR:
fprintf(stderr,"Error: %s\n",ssh_get_error(session));
ssh_scp_close(scp);
ssh_scp_free(scp);
return -1;
case SSH_SCP_REQUEST_WARNING:
fprintf(stderr,"Warning: %s\n",ssh_scp_request_get_warning(scp));
break;
case SSH_SCP_REQUEST_NEWDIR:
filename=strdup(ssh_scp_request_get_filename(scp));
mode=ssh_scp_request_get_permissions(scp);
printf("downloading directory %s, perms 0%o\n",filename,mode);
free(filename);
ssh_scp_accept_request(scp);
break;
case SSH_SCP_REQUEST_ENDDIR:
printf("End of directory\n");
break;
case SSH_SCP_REQUEST_EOF:
printf("End of requests\n");
goto end;
}
} while (1);
end:
ssh_scp_close(scp);
ssh_scp_free(scp);
return 0;
}
int main(int argc, char **argv){
ssh_session session = NULL;
if(opts(argc,argv)<0)
return EXIT_FAILURE;
session=connect_ssh(host,NULL,verbosity);
if(session == NULL)
return EXIT_FAILURE;
create_files(session);
fetch_files(session);
ssh_disconnect(session);
ssh_free(session);
ssh_finalize();
return 0;
}

View File

@@ -5,60 +5,60 @@
#define LIMIT 0x100000000UL
int main(void)
{
ssh_session session = NULL;
ssh_channel channel = NULL;
char buffer[1024 * 1024] = {0};
int rc;
uint64_t total = 0;
uint64_t lastshown = 4096;
session = connect_ssh("localhost", NULL, NULL, 0);
if (session == NULL) {
return 1;
}
channel = ssh_channel_new(session);
if (channel == NULL) {
ssh_disconnect(session);
return 1;
}
rc = ssh_channel_open_session(channel);
if (rc < 0) {
ssh_channel_close(channel);
ssh_disconnect(session);
return 1;
}
rc = ssh_channel_request_exec(channel, "cat > /dev/null");
if (rc < 0) {
ssh_channel_close(channel);
ssh_disconnect(session);
return 1;
}
while ((rc = ssh_channel_write(channel, buffer, sizeof(buffer))) > 0) {
total += rc;
if (total / 2 >= lastshown) {
printf("written %llx\n", (long long unsigned int)total);
lastshown = total;
}
if (total > LIMIT)
break;
}
if (rc < 0) {
printf("error : %s\n", ssh_get_error(session));
ssh_channel_close(channel);
ssh_disconnect(session);
return 1;
}
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
int main(void) {
ssh_session session = NULL;
ssh_channel channel;
char buffer[1024*1024];
int rc;
uint64_t total=0;
uint64_t lastshown=4096;
session = connect_ssh("localhost", NULL, 0);
if (session == NULL) {
return 1;
}
channel = ssh_channel_new(session);
if (channel == NULL) {
ssh_disconnect(session);
return 1;
}
return 0;
rc = ssh_channel_open_session(channel);
if (rc < 0) {
ssh_channel_close(channel);
ssh_disconnect(session);
return 1;
}
rc = ssh_channel_request_exec(channel, "cat > /dev/null");
if (rc < 0) {
ssh_channel_close(channel);
ssh_disconnect(session);
return 1;
}
while ((rc = ssh_channel_write(channel, buffer, sizeof(buffer))) > 0) {
total += rc;
if(total/2 >= lastshown){
printf("written %llx\n", (long long unsigned int) total);
lastshown=total;
}
if(total > LIMIT)
break;
}
if (rc < 0) {
printf("error : %s\n",ssh_get_error(session));
ssh_channel_close(channel);
ssh_disconnect(session);
return 1;
}
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_disconnect(session);
return 0;
}

View File

@@ -39,6 +39,8 @@
#include <libssh/callbacks.h>
#include <libssh/libssh.h>
#include <libssh/sftp.h>
#include "examples_common.h"
#define MAXCMD 10
@@ -110,8 +112,8 @@ static int opts(int argc, char **argv)
{
int i;
while ((i = getopt(argc, argv, "T:P:F:")) != -1) {
switch (i) {
while((i = getopt(argc,argv,"T:P:F:")) != -1) {
switch(i){
case 'P':
pcap_file = optarg;
break;
@@ -157,14 +159,16 @@ static void cfmakeraw(struct termios *termios_p)
static void do_cleanup(int i)
{
(void)i;
/* unused variable */
(void) i;
tcsetattr(0, TCSANOW, &terminal);
tcsetattr(0, TCSANOW, &terminal);
}
static void do_exit(int i)
{
(void)i;
/* unused variable */
(void) i;
do_cleanup(0);
exit(0);
@@ -175,7 +179,7 @@ static int signal_delayed = 0;
#ifdef SIGWINCH
static void sigwindowchanged(int i)
{
(void)i;
(void) i;
signal_delayed = 1;
}
#endif
@@ -209,18 +213,18 @@ static void select_loop(ssh_session session,ssh_channel channel)
/* stdin */
connector_in = ssh_connector_new(session);
ssh_connector_set_out_channel(connector_in, channel, SSH_CONNECTOR_STDINOUT);
ssh_connector_set_in_fd(connector_in, STDIN_FILENO);
ssh_connector_set_in_fd(connector_in, 0);
ssh_event_add_connector(event, connector_in);
/* stdout */
connector_out = ssh_connector_new(session);
ssh_connector_set_out_fd(connector_out, STDOUT_FILENO);
ssh_connector_set_out_fd(connector_out, 1);
ssh_connector_set_in_channel(connector_out, channel, SSH_CONNECTOR_STDINOUT);
ssh_event_add_connector(event, connector_out);
/* stderr */
connector_err = ssh_connector_new(session);
ssh_connector_set_out_fd(connector_err, STDERR_FILENO);
ssh_connector_set_out_fd(connector_err, 2);
ssh_connector_set_in_channel(connector_err, channel, SSH_CONNECTOR_STDERR);
ssh_event_add_connector(event, connector_err);
@@ -249,7 +253,7 @@ static void shell(ssh_session session)
{
ssh_channel channel = NULL;
struct termios terminal_local;
int interactive = isatty(0);
int interactive=isatty(0);
channel = ssh_channel_new(session);
if (channel == NULL) {

View File

@@ -192,6 +192,9 @@ static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
static int
parse_opt(int argc, char **argv, ssh_bind sshbind)
{
int no_default_keys = 0;
int rsa_already_set = 0;
int ecdsa_already_set = 0;
int key;
while((key = getopt(argc, argv, "a:e:k:p:P:r:u:v")) != -1) {
@@ -199,10 +202,16 @@ parse_opt(int argc, char **argv, ssh_bind sshbind)
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, optarg);
} else if (key == 'k') {
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, optarg);
/* We can't track the types of keys being added with this
option, so let's ensure we keep the keys we're adding
by just not setting the default keys */
no_default_keys = 1;
} else if (key == 'r') {
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, optarg);
rsa_already_set = 1;
} else if (key == 'e') {
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, optarg);
ecdsa_already_set = 1;
} else if (key == 'a') {
strncpy(authorizedkeys, optarg, DEF_STR_SIZE-1);
} else if (key == 'u') {
@@ -247,6 +256,12 @@ parse_opt(int argc, char **argv, ssh_bind sshbind)
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, argv[optind]);
if (!no_default_keys) {
set_default_keys(sshbind,
rsa_already_set,
ecdsa_already_set);
}
return 0;
}
#endif /* HAVE_ARGP_H */

View File

@@ -40,236 +40,222 @@ clients must be made or how a client should react.
#endif
char *host = NULL;
const char *desthost = "localhost";
const char *port = "22";
const char *desthost="localhost";
const char *port="22";
#ifdef WITH_PCAP
#include <libssh/pcap.h>
char *pcap_file = NULL;
char *pcap_file=NULL;
#endif
static void usage(void)
{
fprintf(stderr,
"Usage : sshnetcat [user@]host forwarded_host forwarded_port\n");
exit(1);
fprintf(stderr,"Usage : sshnetcat [user@]host forwarded_host forwarded_port\n");
exit(1);
}
static int opts(int argc, char **argv)
{
static int opts(int argc, char **argv){
int i;
while ((i = getopt(argc, argv, "P:")) != -1) {
switch (i) {
while((i=getopt(argc,argv,"P:"))!=-1){
switch(i){
#ifdef WITH_PCAP
case 'P':
pcap_file = optarg;
break;
case 'P':
pcap_file=optarg;
break;
#endif
default:
fprintf(stderr, "unknown option %c\n", optopt);
usage();
default:
fprintf(stderr,"unknown option %c\n",optopt);
usage();
}
}
if (optind < argc)
host = argv[optind++];
if (optind < argc)
desthost = argv[optind++];
if (optind < argc)
port = argv[optind++];
if (host == NULL)
if(optind < argc)
host=argv[optind++];
if(optind < argc)
desthost=argv[optind++];
if(optind < argc)
port=argv[optind++];
if(host==NULL)
usage();
return 0;
}
static void select_loop(ssh_session session, ssh_channel channel)
{
fd_set fds;
struct timeval timeout;
char buffer[BUF_SIZE];
/* channels will be set to the channels to poll.
* outchannels will contain the result of the poll
*/
ssh_channel channels[2], outchannels[2];
int lus;
int eof = 0;
int maxfd;
int ret;
while (channel) {
do {
static void select_loop(ssh_session session,ssh_channel channel){
fd_set fds;
struct timeval timeout;
char buffer[BUF_SIZE];
/* channels will be set to the channels to poll.
* outchannels will contain the result of the poll
*/
ssh_channel channels[2], outchannels[2];
int lus;
int eof=0;
int maxfd;
int ret;
while(channel){
do{
int fd;
ZERO_STRUCT(fds);
FD_ZERO(&fds);
if (!eof)
FD_SET(0, &fds);
timeout.tv_sec = 30;
timeout.tv_usec = 0;
FD_ZERO(&fds);
if(!eof)
FD_SET(0,&fds);
timeout.tv_sec=30;
timeout.tv_usec=0;
fd = ssh_get_fd(session);
if (fd == -1) {
fprintf(stderr,
"Error getting the session file descriptor: %s\n",
ssh_get_error(session));
fprintf(stderr, "Error getting the session file descriptor: %s\n",
ssh_get_error(session));
return;
}
FD_SET(fd, &fds);
maxfd = fd + 1;
channels[0] = channel; // set the first channel we want to read from
channels[1] = NULL;
ret = ssh_select(channels, outchannels, maxfd, &fds, &timeout);
if (ret == EINTR)
continue;
if (FD_ISSET(0, &fds)) {
lus = read(0, buffer, sizeof(buffer));
if (lus)
ssh_channel_write(channel, buffer, lus);
else {
eof = 1;
ssh_channel_send_eof(channel);
}
}
if (channel && ssh_channel_is_closed(channel)) {
ssh_channel_free(channel);
channel = NULL;
channels[0] = NULL;
}
if (outchannels[0]) {
while (channel && ssh_channel_is_open(channel) &&
ssh_channel_poll(channel, 0)) {
lus = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
if (lus == -1) {
fprintf(stderr,
"Error reading channel: %s\n",
ssh_get_error(session));
return;
channels[0]=channel; // set the first channel we want to read from
channels[1]=NULL;
ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout);
if(ret==EINTR)
continue;
if(FD_ISSET(0,&fds)){
lus=read(0,buffer,sizeof(buffer));
if(lus)
ssh_channel_write(channel,buffer,lus);
else {
eof=1;
ssh_channel_send_eof(channel);
}
}
if(channel && ssh_channel_is_closed(channel)){
ssh_channel_free(channel);
channel=NULL;
channels[0]=NULL;
}
if(outchannels[0]){
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,0)){
lus = ssh_channel_read(channel,buffer,sizeof(buffer),0);
if(lus==-1){
fprintf(stderr, "Error reading channel: %s\n",
ssh_get_error(session));
return;
}
if(lus==0){
ssh_channel_free(channel);
channel=channels[0]=NULL;
} else {
ret = write(1, buffer, lus);
if (ret < 0) {
fprintf(stderr, "Error writing to stdin: %s",
strerror(errno));
return;
}
}
}
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,1)){ /* stderr */
lus = ssh_channel_read(channel, buffer, sizeof(buffer), 1);
if(lus==-1){
fprintf(stderr, "Error reading channel: %s\n",
ssh_get_error(session));
return;
}
if(lus==0){
ssh_channel_free(channel);
channel=channels[0]=NULL;
} else {
ret = write(2, buffer, lus);
if (ret < 0) {
fprintf(stderr, "Error writing to stderr: %s",
strerror(errno));
return;
}
}
if (lus == 0) {
ssh_channel_free(channel);
channel = channels[0] = NULL;
} else {
ret = write(1, buffer, lus);
if (ret < 0) {
fprintf(stderr,
"Error writing to stdin: %s",
strerror(errno));
return;
}
}
}
while (channel && ssh_channel_is_open(channel) &&
ssh_channel_poll(channel, 1)) { /* stderr */
lus = ssh_channel_read(channel, buffer, sizeof(buffer), 1);
if (lus == -1) {
fprintf(stderr,
"Error reading channel: %s\n",
ssh_get_error(session));
return;
}
if (lus == 0) {
ssh_channel_free(channel);
channel = channels[0] = NULL;
} else {
ret = write(2, buffer, lus);
if (ret < 0) {
fprintf(stderr,
"Error writing to stderr: %s",
strerror(errno));
return;
}
}
}
}
if (channel && ssh_channel_is_closed(channel)) {
ssh_channel_free(channel);
channel = NULL;
}
} while (ret == EINTR || ret == SSH_EINTR);
}
}
}
if(channel && ssh_channel_is_closed(channel)){
ssh_channel_free(channel);
channel=NULL;
}
} while (ret==EINTR || ret==SSH_EINTR);
}
}
static void forwarding(ssh_session session)
{
static void forwarding(ssh_session session){
ssh_channel channel;
int r;
channel = ssh_channel_new(session);
r = ssh_channel_open_forward(channel, desthost, atoi(port), "localhost", 22);
if (r < 0) {
printf("error forwarding port : %s\n", ssh_get_error(session));
if(r<0) {
printf("error forwarding port : %s\n",ssh_get_error(session));
return;
}
select_loop(session, channel);
select_loop(session,channel);
}
static int client(ssh_session session)
{
int auth = 0;
char *banner = NULL;
int state;
static int client(ssh_session session){
int auth=0;
char *banner = NULL;
int state;
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0)
return -1;
ssh_options_parse_config(session, NULL);
if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0)
return -1;
ssh_options_parse_config(session, NULL);
if (ssh_connect(session)) {
fprintf(stderr, "Connection failed : %s\n", ssh_get_error(session));
return -1;
}
state = verify_knownhost(session);
if (state != 0)
return -1;
ssh_userauth_none(session, NULL);
banner = ssh_get_issue_banner(session);
if (banner) {
printf("%s\n", banner);
free(banner);
}
auth = authenticate_console(session);
if (auth != SSH_AUTH_SUCCESS) {
return -1;
}
forwarding(session);
return 0;
if(ssh_connect(session)){
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
return -1;
}
state=verify_knownhost(session);
if (state != 0)
return -1;
ssh_userauth_none(session, NULL);
banner=ssh_get_issue_banner(session);
if(banner){
printf("%s\n",banner);
free(banner);
}
auth=authenticate_console(session);
if(auth != SSH_AUTH_SUCCESS){
return -1;
}
forwarding(session);
return 0;
}
#ifdef WITH_PCAP
ssh_pcap_file pcap;
void set_pcap(ssh_session session);
void set_pcap(ssh_session session)
{
if (!pcap_file)
return;
pcap = ssh_pcap_file_new();
if (ssh_pcap_file_open(pcap, pcap_file) == SSH_ERROR) {
printf("Error opening pcap file\n");
ssh_pcap_file_free(pcap);
pcap = NULL;
return;
}
ssh_set_pcap_file(session, pcap);
void set_pcap(ssh_session session){
if(!pcap_file)
return;
pcap=ssh_pcap_file_new();
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
printf("Error opening pcap file\n");
ssh_pcap_file_free(pcap);
pcap=NULL;
return;
}
ssh_set_pcap_file(session,pcap);
}
void cleanup_pcap(void);
void cleanup_pcap(void)
{
ssh_pcap_file_free(pcap);
pcap = NULL;
ssh_pcap_file_free(pcap);
pcap = NULL;
}
#endif
int main(int argc, char **argv)
{
int main(int argc, char **argv){
ssh_session session = NULL;
session = ssh_new();
if (ssh_options_getopt(session, &argc, argv)) {
fprintf(stderr,
"error parsing command line :%s\n",
ssh_get_error(session));
usage();
if(ssh_options_getopt(session, &argc, argv)) {
fprintf(stderr, "error parsing command line :%s\n",
ssh_get_error(session));
usage();
}
opts(argc, argv);
opts(argc,argv);
#ifdef WITH_PCAP
set_pcap(session);
#endif

View File

@@ -31,7 +31,6 @@ extern "C" {
bignum ssh_make_string_bn(ssh_string string);
ssh_string ssh_make_bignum_string(bignum num);
ssh_string ssh_make_padded_bignum_string(bignum num, size_t pad_len);
void ssh_print_bignum(const char *which, const_bignum num);
#ifdef __cplusplus

View File

@@ -52,7 +52,6 @@ enum ssh_bind_config_opcode_e {
BIND_CFG_MATCH,
BIND_CFG_PUBKEY_ACCEPTED_KEY_TYPES,
BIND_CFG_HOSTKEY_ALGORITHMS,
BIND_CFG_REQUIRED_RSA_SIZE,
BIND_CFG_MAX /* Keep this one last in the list */
};

View File

@@ -74,8 +74,6 @@ ssh_string ssh_buffer_get_ssh_string(ssh_buffer buffer);
uint32_t ssh_buffer_pass_bytes_end(ssh_buffer buffer, uint32_t len);
uint32_t ssh_buffer_pass_bytes(ssh_buffer buffer, uint32_t len);
ssh_buffer ssh_buffer_dup(const ssh_buffer buffer);
#ifdef __cplusplus
}
#endif

View File

@@ -113,17 +113,6 @@ typedef void (*ssh_status_callback) (ssh_session session, float status,
typedef void (*ssh_global_request_callback) (ssh_session session,
ssh_message message, void *userdata);
/**
* @brief SSH connect status callback. These are functions that report the
* status of the connection i,e. a function indicating the completed percentage
* of the connection
* steps.
* @param userdata Userdata to be passed to the callback function.
* @param status Percentage of connection status, going from 0.0 to 1.0
* once connection is done.
*/
typedef void (*ssh_connect_status_callback)(void *userdata, float status);
/**
* @brief Handles an SSH new channel open X11 request. This happens when the server
* sends back an X11 connection attempt. This is a client-side API
@@ -192,7 +181,7 @@ struct ssh_callbacks_struct {
* This function gets called during connection time to indicate the
* percentage of connection steps completed.
*/
ssh_connect_status_callback connect_status_function;
void (*connect_status_function)(void *userdata, float status);
/**
* This function will be called each time a global request is received.
*/
@@ -336,28 +325,6 @@ typedef int (*ssh_gssapi_accept_sec_ctx_callback) (ssh_session session,
typedef int (*ssh_gssapi_verify_mic_callback) (ssh_session session,
ssh_string mic, void *mic_buffer, size_t mic_buffer_size, void *userdata);
/**
* @brief Handles an SSH new channel open "direct-tcpip" request. This
* happens when the client forwards an incoming TCP connection on a port it
* wants to forward to the destination. This is a server-side API
* @param session current session handler
* @param destination_address the address that the TCP connection connected to
* @param destination_port the port that the TCP connection connected to
* @param originator_address the originator IP address
* @param originator_port the originator port
* @param userdata Userdata to be passed to the callback function.
* @returns a valid ssh_channel handle if the request is to be allowed
* @returns NULL if the request should not be allowed
* @warning The channel pointer returned by this callback must be closed by the
* application.
*/
typedef ssh_channel (*ssh_channel_open_request_direct_tcpip_callback)(
ssh_session session,
const char *destination_address,
int destination_port,
const char *originator_address,
int originator_port,
void *userdata);
/**
* This structure can be used to implement a libssh server, with appropriate callbacks.
@@ -408,12 +375,6 @@ struct ssh_server_callbacks_struct {
/* This function will be called when a MIC needs to be verified.
*/
ssh_gssapi_verify_mic_callback gssapi_verify_mic_function;
/**
* This function will be called when an incoming "direct-tcpip"
* request is received.
*/
ssh_channel_open_request_direct_tcpip_callback
channel_open_request_direct_tcpip_function;
};
typedef struct ssh_server_callbacks_struct *ssh_server_callbacks;

View File

@@ -66,7 +66,6 @@ enum ssh_config_opcode_e {
SOC_CONTROLMASTER,
SOC_CONTROLPATH,
SOC_CERTIFICATE,
SOC_REQUIRED_RSA_SIZE,
SOC_MAX /* Keep this one last in the list */
};

View File

@@ -45,14 +45,10 @@
#ifdef HAVE_OPENSSL_ECDH_H
#include <openssl/ecdh.h>
#endif
#include "libssh/curve25519.h"
#include "libssh/dh.h"
#include "libssh/ecdh.h"
#include "libssh/kex.h"
#include "libssh/sntrup761.h"
#ifdef HAVE_MLKEM
#include "libssh/mlkem768.h"
#endif
#include "libssh/curve25519.h"
#define DIGEST_MAX_LEN 64
@@ -60,40 +56,32 @@
#define AES_GCM_IVLEN 12
enum ssh_key_exchange_e {
/* diffie-hellman-group1-sha1 */
SSH_KEX_DH_GROUP1_SHA1 = 1,
/* diffie-hellman-group14-sha1 */
SSH_KEX_DH_GROUP14_SHA1,
/* diffie-hellman-group1-sha1 */
SSH_KEX_DH_GROUP1_SHA1=1,
/* diffie-hellman-group14-sha1 */
SSH_KEX_DH_GROUP14_SHA1,
#ifdef WITH_GEX
/* diffie-hellman-group-exchange-sha1 */
SSH_KEX_DH_GEX_SHA1,
/* diffie-hellman-group-exchange-sha256 */
SSH_KEX_DH_GEX_SHA256,
/* diffie-hellman-group-exchange-sha1 */
SSH_KEX_DH_GEX_SHA1,
/* diffie-hellman-group-exchange-sha256 */
SSH_KEX_DH_GEX_SHA256,
#endif /* WITH_GEX */
/* ecdh-sha2-nistp256 */
SSH_KEX_ECDH_SHA2_NISTP256,
/* ecdh-sha2-nistp384 */
SSH_KEX_ECDH_SHA2_NISTP384,
/* ecdh-sha2-nistp521 */
SSH_KEX_ECDH_SHA2_NISTP521,
/* curve25519-sha256@libssh.org */
SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG,
/* curve25519-sha256 */
SSH_KEX_CURVE25519_SHA256,
/* diffie-hellman-group16-sha512 */
SSH_KEX_DH_GROUP16_SHA512,
/* diffie-hellman-group18-sha512 */
SSH_KEX_DH_GROUP18_SHA512,
/* diffie-hellman-group14-sha256 */
SSH_KEX_DH_GROUP14_SHA256,
/* sntrup761x25519-sha512@openssh.com */
SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM,
/* sntrup761x25519-sha512 */
SSH_KEX_SNTRUP761X25519_SHA512,
#ifdef HAVE_MLKEM
/* mlkem768x25519-sha256 */
SSH_KEX_MLKEM768X25519_SHA256,
#endif /* HAVE_MLKEM */
/* ecdh-sha2-nistp256 */
SSH_KEX_ECDH_SHA2_NISTP256,
/* ecdh-sha2-nistp384 */
SSH_KEX_ECDH_SHA2_NISTP384,
/* ecdh-sha2-nistp521 */
SSH_KEX_ECDH_SHA2_NISTP521,
/* curve25519-sha256@libssh.org */
SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG,
/* curve25519-sha256 */
SSH_KEX_CURVE25519_SHA256,
/* diffie-hellman-group16-sha512 */
SSH_KEX_DH_GROUP16_SHA512,
/* diffie-hellman-group18-sha512 */
SSH_KEX_DH_GROUP18_SHA512,
/* diffie-hellman-group14-sha256 */
SSH_KEX_DH_GROUP14_SHA256,
};
enum ssh_cipher_e {
@@ -137,25 +125,9 @@ struct ssh_crypto_struct {
ssh_string ecdh_server_pubkey;
#endif
#ifdef HAVE_CURVE25519
#ifdef HAVE_LIBCRYPTO
EVP_PKEY *curve25519_privkey;
#elif defined(HAVE_GCRYPT_CURVE25519)
gcry_sexp_t curve25519_privkey;
#else
ssh_curve25519_privkey curve25519_privkey;
#endif
ssh_curve25519_pubkey curve25519_client_pubkey;
ssh_curve25519_pubkey curve25519_server_pubkey;
#endif
#ifdef HAVE_MLKEM
ssh_mlkem768_privkey mlkem768_client_privkey;
ssh_mlkem768_pubkey mlkem768_client_pubkey;
ssh_mlkem768_ciphertext mlkem768_ciphertext;
#endif
#ifdef HAVE_SNTRUP761
ssh_sntrup761_privkey sntrup761_privkey;
ssh_sntrup761_pubkey sntrup761_client_pubkey;
ssh_sntrup761_ciphertext sntrup761_ciphertext;
#endif
ssh_string dh_server_signature; /* information used by dh_handshake. */
size_t session_id_len;
@@ -251,6 +223,9 @@ int sshkdf_derive_key(struct ssh_crypto_struct *crypto,
size_t requested_len);
int secure_memcmp(const void *s1, const void *s2, size_t n);
#if defined(HAVE_LIBCRYPTO) && !defined(WITH_PKCS11_PROVIDER)
ENGINE *pki_get_engine(void);
#endif /* HAVE_LIBCRYPTO */
void compress_cleanup(struct ssh_crypto_struct *crypto);

View File

@@ -50,9 +50,6 @@ int crypto_scalarmult(unsigned char *q, const unsigned char *n, const unsigned c
typedef unsigned char ssh_curve25519_pubkey[CURVE25519_PUBKEY_SIZE];
typedef unsigned char ssh_curve25519_privkey[CURVE25519_PRIVKEY_SIZE];
int ssh_curve25519_init(ssh_session session);
int curve25519_do_create_k(ssh_session session, ssh_curve25519_pubkey k);
int ssh_curve25519_create_k(ssh_session session, ssh_curve25519_pubkey k);
int ssh_client_curve25519_init(ssh_session session);
void ssh_client_curve25519_remove_callbacks(ssh_session session);

View File

@@ -52,10 +52,10 @@ char *ssh_prefix_default_algos(enum ssh_kex_types_e algo, const char *list);
char **ssh_space_tokenize(const char *chain);
int ssh_get_kex1(ssh_session session);
char *ssh_find_matching(const char *in_d, const char *what_d);
const char *ssh_kex_get_supported_method(enum ssh_kex_types_e type);
const char *ssh_kex_get_default_methods(enum ssh_kex_types_e type);
const char *ssh_kex_get_fips_methods(enum ssh_kex_types_e type);
const char *ssh_kex_get_description(enum ssh_kex_types_e type);
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_fips_methods(uint32_t algo);
const char *ssh_kex_get_description(uint32_t algo);
char *ssh_client_select_hostkeys(ssh_session session);
int ssh_send_rekex(ssh_session session);
int server_set_kex(ssh_session session);

View File

@@ -121,15 +121,6 @@ typedef BN_CTX* bignum_CTX;
ssh_string pki_key_make_ecpoint_string(const EC_GROUP *g, const EC_POINT *p);
int pki_key_ecgroup_name_to_nid(const char *group);
#if defined(WITH_PKCS11_URI)
#if defined(WITH_PKCS11_PROVIDER)
int pki_load_pkcs11_provider(void);
#else
ENGINE *pki_get_engine(void);
#endif
#endif /* WITH_PKCS11_PROVIDER */
#endif /* HAVE_LIBCRYPTO */
#endif /* LIBCRYPTO_H_ */

View File

@@ -49,10 +49,9 @@
#endif
#endif
#include <inttypes.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <inttypes.h>
#ifdef _MSC_VER
typedef int mode_t;
@@ -844,7 +843,6 @@ LIBSSH_API int ssh_string_fill(ssh_string str, const void *data, size_t len);
do { if ((x) != NULL) { ssh_string_free(x); x = NULL; } } while(0)
LIBSSH_API void ssh_string_free(ssh_string str);
LIBSSH_API ssh_string ssh_string_from_char(const char *what);
LIBSSH_API ssh_string ssh_string_from_data(const void *data, size_t len);
LIBSSH_API size_t ssh_string_len(ssh_string str);
LIBSSH_API ssh_string ssh_string_new(size_t size);
LIBSSH_API const char *ssh_string_get_char(ssh_string str);
@@ -852,7 +850,6 @@ LIBSSH_API char *ssh_string_to_char(ssh_string str);
#define SSH_STRING_FREE_CHAR(x) \
do { if ((x) != NULL) { ssh_string_free_char(x); x = NULL; } } while(0)
LIBSSH_API void ssh_string_free_char(char *s);
LIBSSH_API int ssh_string_cmp(ssh_string s1, ssh_string s2);
LIBSSH_API int ssh_getpass(const char *prompt, char *buf, size_t len, int echo,
int verify);
@@ -877,7 +874,6 @@ LIBSSH_API const char* ssh_get_cipher_in(ssh_session session);
LIBSSH_API const char* ssh_get_cipher_out(ssh_session session);
LIBSSH_API const char* ssh_get_hmac_in(ssh_session session);
LIBSSH_API const char* ssh_get_hmac_out(ssh_session session);
LIBSSH_API const char *ssh_get_supported_methods(enum ssh_kex_types_e type);
LIBSSH_API ssh_buffer ssh_buffer_new(void);
LIBSSH_API void ssh_buffer_free(ssh_buffer buffer);
@@ -890,27 +886,6 @@ LIBSSH_API void *ssh_buffer_get(ssh_buffer buffer);
LIBSSH_API uint32_t ssh_buffer_get_len(ssh_buffer buffer);
LIBSSH_API int ssh_session_set_disconnect_message(ssh_session session, const char *message);
/* SSHSIG hashes data independently from the key used, so we use a new enum
to avoid confusion. See
https://gitlab.com/jas/ietf-sshsig-format/-/blob/cc70a225cbd695d5a6f20aaebdb4b92b0818e43a/ietf-sshsig-format.md#L137
*/
enum sshsig_digest_e {
SSHSIG_DIGEST_SHA2_256 = 0,
SSHSIG_DIGEST_SHA2_512 = 1,
};
LIBSSH_API int sshsig_sign(const void *data,
size_t data_length,
ssh_key privkey,
const char *sig_namespace,
enum sshsig_digest_e hash_alg,
char **signature);
LIBSSH_API int sshsig_verify(const void *data,
size_t data_length,
const char *signature,
const char *sig_namespace,
ssh_key *sign_key);
#ifndef LIBSSH_LEGACY_0_4
#include "libssh/legacy.h"
#endif

View File

@@ -28,7 +28,6 @@ struct ssh_auth_request {
int method;
char *password;
struct ssh_key_struct *pubkey;
struct ssh_key_struct *server_pubkey;
char *sigtype;
enum ssh_publickey_state_e signature_state;
char kbdint_response;

View File

@@ -1,63 +0,0 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2025 by Red Hat, Inc.
*
* Author: Sahana Prasad <sahana@redhat.com>
* Author: Claude (Anthropic)
*
* 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; either
* version 2.1 of the License, or (at your option) any later version.
*
* 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 MLKEM768_H_
#define MLKEM768_H_
#include "config.h"
/* ML-KEM768 key and ciphertext sizes as defined in FIPS 203 */
#define MLKEM768_PUBLICKEY_SIZE 1184
#define MLKEM768_SECRETKEY_SIZE 2400
#define MLKEM768_CIPHERTEXT_SIZE 1088
#define MLKEM768_SHARED_SECRET_SIZE 32
/* Hybrid ML-KEM768x25519 combined sizes */
#define MLKEM768X25519_CLIENT_PUBKEY_SIZE \
(MLKEM768_PUBLICKEY_SIZE + CURVE25519_PUBKEY_SIZE)
#define MLKEM768X25519_SERVER_RESPONSE_SIZE \
(MLKEM768_CIPHERTEXT_SIZE + CURVE25519_PUBKEY_SIZE)
#define MLKEM768X25519_SHARED_SECRET_SIZE \
(MLKEM768_SHARED_SECRET_SIZE + CURVE25519_PUBKEY_SIZE)
typedef unsigned char ssh_mlkem768_pubkey[MLKEM768_PUBLICKEY_SIZE];
typedef unsigned char ssh_mlkem768_privkey[MLKEM768_SECRETKEY_SIZE];
typedef unsigned char ssh_mlkem768_ciphertext[MLKEM768_CIPHERTEXT_SIZE];
#ifdef __cplusplus
extern "C" {
#endif
/* ML-KEM768x25519 key exchange functions */
int ssh_client_mlkem768x25519_init(ssh_session session);
void ssh_client_mlkem768x25519_remove_callbacks(ssh_session session);
#ifdef WITH_SERVER
void ssh_server_mlkem768x25519_init(ssh_session session);
#endif /* WITH_SERVER */
#ifdef __cplusplus
}
#endif
#endif /* MLKEM768_H_ */

View File

@@ -25,7 +25,6 @@
extern "C" {
#endif
int ssh_config_parse(ssh_session session, FILE *fp, bool global);
int ssh_config_parse_file(ssh_session session, const char *filename);
int ssh_config_parse_string(ssh_session session, const char *input);
int ssh_options_set_algo(ssh_session session,

View File

@@ -46,24 +46,11 @@
#define MAX_PUBKEY_SIZE 0x100000 /* 1M */
#define MAX_PRIVKEY_SIZE 0x400000 /* 4M */
#define RSA_MIN_KEY_SIZE 1024
#define RSA_MIN_FIPS_KEY_SIZE 2048
#define RSA_DEFAULT_KEY_SIZE 3072
#define SSH_KEY_FLAG_EMPTY 0x0
#define SSH_KEY_FLAG_PUBLIC 0x0001
#define SSH_KEY_FLAG_PRIVATE 0x0002
#define SSH_KEY_FLAG_PKCS11_URI 0x0004
/* Constants matching the Lightweight Secure Shell Signature Format */
/* https://datatracker.ietf.org/doc/draft-josefsson-sshsig-format */
#define SSHSIG_VERSION 0x01
#define SSHSIG_MAGIC_PREAMBLE "SSHSIG"
#define SSHSIG_MAGIC_PREAMBLE_LEN (sizeof(SSHSIG_MAGIC_PREAMBLE) - 1)
#define SSHSIG_BEGIN_SIGNATURE "-----BEGIN SSH SIGNATURE-----"
#define SSHSIG_END_SIGNATURE "-----END SSH SIGNATURE-----"
#define SSHSIG_LINE_LENGTH 76
struct ssh_key_struct {
enum ssh_keytypes_e type;
int flags;
@@ -76,12 +63,11 @@ struct ssh_key_struct {
mbedtls_pk_context *pk;
mbedtls_ecdsa_context *ecdsa;
#elif defined(HAVE_LIBCRYPTO)
/* This holds either ENGINE/PROVIDER key for PKCS#11 support
* or just key in high-level format */
/* This holds either ENGINE key for PKCS#11 support or just key in
* high-level format */
EVP_PKEY *key;
/* keep this around for FIPS mode so we can parse the public keys. We won't
* be able to use them nor use the private keys though */
uint8_t *ed25519_pubkey;
uint8_t *ed25519_privkey;
#endif /* HAVE_LIBGCRYPT */
#ifndef HAVE_LIBCRYPTO
ed25519_pubkey *ed25519_pubkey;
@@ -90,11 +76,6 @@ struct ssh_key_struct {
ssh_string sk_application;
ssh_buffer cert;
enum ssh_keytypes_e cert_type;
/* Security Key specific private data */
uint8_t sk_flags;
ssh_string sk_key_handle;
ssh_string sk_reserved;
};
struct ssh_signature_struct {
@@ -146,11 +127,6 @@ enum ssh_digest_e ssh_key_hash_from_name(const char *name);
((kt) >= SSH_KEYTYPE_ECDSA_P256_CERT01 &&\
(kt) <= SSH_KEYTYPE_ED25519_CERT01))
#define is_sk_key_type(kt) \
((kt) == SSH_KEYTYPE_SK_ECDSA || (kt) == SSH_KEYTYPE_SK_ED25519 || \
(kt) == SSH_KEYTYPE_SK_ECDSA_CERT01 || \
(kt) == SSH_KEYTYPE_SK_ED25519_CERT01)
/* SSH Signature Functions */
ssh_signature ssh_signature_new(void);
void ssh_signature_free(ssh_signature sign);

View File

@@ -61,7 +61,6 @@ enum ssh_digest_e ssh_key_type_to_hash(ssh_session session,
enum ssh_keytypes_e type);
/* SSH Key Functions */
ssh_key pki_key_dup_common_init(const ssh_key key, int demote);
ssh_key pki_key_dup(const ssh_key key, int demote);
int pki_key_generate_rsa(ssh_key key, int parameter);
int pki_key_generate_ecdsa(ssh_key key, int parameter);
@@ -149,7 +148,6 @@ int pki_signature_from_ed25519_blob(ssh_signature sig, ssh_string sig_blob);
int pki_privkey_build_ed25519(ssh_key key,
ssh_string pubkey,
ssh_string privkey);
int pki_pubkey_build_ed25519(ssh_key key, ssh_string pubkey);
/* PKI Container OpenSSH */
ssh_key ssh_pki_openssh_pubkey_import(const char *text_key);
@@ -164,16 +162,6 @@ int pki_uri_import(const char *uri_name, ssh_key *key, enum ssh_key_e key_type);
#endif /* WITH_PKCS11_URI */
bool ssh_key_size_allowed_rsa(int min_size, ssh_key key);
/* Security Key Helper Functions */
int pki_buffer_pack_sk_priv_data(ssh_buffer buffer, const ssh_key key);
int pki_buffer_unpack_sk_priv_data(ssh_buffer buffer, ssh_key key);
int pki_sk_signature_buffer_prepare(const ssh_key key,
const ssh_signature sig,
const unsigned char *input,
size_t input_len,
ssh_buffer *sk_buffer_out);
#ifdef __cplusplus
}
#endif

View File

@@ -157,7 +157,6 @@ void ssh_poll_ctx_free(ssh_poll_ctx ctx);
int ssh_poll_ctx_add(ssh_poll_ctx ctx, ssh_poll_handle p);
int ssh_poll_ctx_add_socket (ssh_poll_ctx ctx, struct ssh_socket_struct *s);
void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p);
bool ssh_poll_is_locked(ssh_poll_handle p);
int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout);
ssh_poll_ctx ssh_poll_get_default_ctx(ssh_session session);
int ssh_event_add_poll(ssh_event event, ssh_poll_handle p);

View File

@@ -30,11 +30,10 @@
#define _LIBSSH_PRIV_H
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdbool.h>
#if !defined(HAVE_STRTOULL)
# if defined(HAVE___STRTOULL)
@@ -165,9 +164,6 @@ int ssh_gettimeofday(struct timeval *__p, void *__t);
#define gettimeofday ssh_gettimeofday
struct tm *ssh_localtime(const time_t *timer, struct tm *result);
# define localtime_r ssh_localtime
#define _XCLOSESOCKET closesocket
# ifdef HAVE_IO_H
@@ -333,7 +329,7 @@ int decompress_buffer(ssh_session session,ssh_buffer buf, size_t maxlen);
/* match.c */
int match_pattern_list(const char *string, const char *pattern,
size_t len, int dolower);
int match_hostname(const char *host, const char *pattern, size_t len);
int match_hostname(const char *host, const char *pattern, unsigned int len);
#ifndef _WIN32
int match_cidr_address_list(const char *address,
const char *addrlist,
@@ -357,10 +353,10 @@ int ssh_connector_remove_event(ssh_connector connector);
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
/** Zero a structure */
#define ZERO_STRUCT(x) memset(&(x), 0, sizeof(x))
#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
/** Zero a structure given a pointer to the structure */
#define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((x), 0, sizeof(*(x))); } while(0)
#define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0)
/** Get the size of an array */
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
@@ -369,17 +365,6 @@ int ssh_connector_remove_event(ssh_connector connector);
void explicit_bzero(void *s, size_t n);
#endif /* !HAVE_EXPLICIT_BZERO */
void burn_free(void *ptr, size_t len);
/** Free memory space after zeroing it */
#define BURN_FREE(x, len) \
do { \
if ((x) != NULL) { \
burn_free((x), (len)); \
(x) = NULL; \
} \
} while (0)
/**
* This is a hack to fix warnings. The idea is to use this everywhere that we
* get the "discarding const" warning by the compiler. That doesn't actually

View File

@@ -89,9 +89,6 @@ enum ssh_pending_call_e {
#define SSH_SESSION_FLAG_KEX_STRICT 0x0010
/* Unexpected packets have been sent while the session was still unencrypted */
#define SSH_SESSION_FLAG_KEX_TAINTED 0x0020
/* The scp on server can not handle quoted paths. Skip the mitigation for
* CVE-2019-14889 when using scp */
#define SSH_SESSION_FLAG_SCP_QUOTING_BROKEN 0x0040
/* codes to use with ssh_handle_packets*() */
/* Infinite timeout */
@@ -123,8 +120,6 @@ enum ssh_pending_call_e {
/* server-sig-algs extension */
#define SSH_EXT_SIG_RSA_SHA256 0x02
#define SSH_EXT_SIG_RSA_SHA512 0x04
/* Host-bound public key authentication extension */
#define SSH_EXT_PUBLICKEY_HOSTBOUND 0x08
/* members that are common to ssh_session and ssh_bind */
struct ssh_common_struct {

View File

@@ -79,7 +79,6 @@ typedef struct sftp_status_message_struct* sftp_status_message;
typedef struct sftp_statvfs_struct* sftp_statvfs_t;
typedef struct sftp_limits_struct* sftp_limits_t;
typedef struct sftp_aio_struct* sftp_aio;
typedef struct sftp_name_id_map_struct *sftp_name_id_map;
struct sftp_session_struct {
ssh_session session;
@@ -214,22 +213,6 @@ struct sftp_limits_struct {
uint64_t max_open_handles; /** maximum number of active handles allowed by server */
};
/**
* @brief SFTP names map structure to store the mapping between ids and names.
*
* This is mainly for the use of sftp_get_users_groups_by_id() function.
*/
struct sftp_name_id_map_struct {
/** @brief Count of name-id pairs in the map */
uint32_t count;
/** @brief Array of ids, ids[i] mapped to names[i] */
uint32_t *ids;
/** @brief Array of names, names[i] mapped to ids[i] */
char **names;
};
/**
* @brief Creates a new sftp session.
*
@@ -237,30 +220,24 @@ struct sftp_name_id_map_struct {
* with the server inside of the provided ssh session. This function call is
* usually followed by the sftp_init(), which initializes SFTP protocol itself.
*
* @param session The ssh session to use. The session *must* be in
* blocking mode since most `sftp_*` functions do not
* support the non-blocking API.
* @param session The ssh session to use.
*
* @return A new sftp session or NULL on error.
*
* @see sftp_free()
* @see sftp_init()
* @see ssh_set_blocking()
*/
LIBSSH_API sftp_session sftp_new(ssh_session session);
/**
* @brief Start a new sftp session with an existing channel.
*
* @param session The ssh session to use. The session *must* be in
* blocking mode since most `sftp_*` functions do not
* support the non-blocking API.
* @param session The ssh session to use.
* @param channel An open session channel with subsystem already allocated
*
* @return A new sftp session or NULL on error.
*
* @see sftp_free()
* @see ssh_set_blocking()
*/
LIBSSH_API sftp_session sftp_new_channel(ssh_session session, ssh_channel channel);
@@ -1211,58 +1188,6 @@ LIBSSH_API char *sftp_expand_path(sftp_session sftp, const char *path);
*/
LIBSSH_API char *sftp_home_directory(sftp_session sftp, const char *username);
/**
* @brief Create a new sftp_name_id_map struct.
*
* @param count The number of ids/names to store in the map.
*
* @return A pointer to the newly allocated sftp_name_id_map
* struct.
*/
LIBSSH_API sftp_name_id_map sftp_name_id_map_new(uint32_t count);
/**
* @brief Free the memory of an allocated `sftp_name_id_map` struct.
*
* @param map A pointer to the `sftp_name_id_map` struct to free.
*/
LIBSSH_API void sftp_name_id_map_free(sftp_name_id_map map);
/**
* @brief Retrieves usernames and group names based on provided user and group
* IDs.
*
* The retrieved names are stored in the `names` field of the
* `sftp_name_id_map` structure. In case a uid or gid is not found, an empty
* string is stored.
*
* This calls the "users-groups-by-id@openssh.com" extension.
* You should check if the extension is supported using:
*
* @code
* int supported = sftp_extension_supported(sftp,
* "users-groups-by-id@openssh.com", "1");
* @endcode
*
* @param sftp The SFTP session handle.
*
* @param users_map A pointer to a `sftp_name_id_map` struct with the user
* IDs. Can be NULL if only group names are needed.
*
* @param groups_map A pointer to a `sftp_name_id_map` struct with the group
* IDs. Can be NULL if only user names are needed.
*
* @return 0 on success, < 0 on error with ssh and sftp error set.
*
* @note The caller needs to free the memory used for
* the maps later using `sftp_name_id_map_free()`.
*
* @see sftp_get_error()
*/
LIBSSH_API int sftp_get_users_groups_by_id(sftp_session sftp,
sftp_name_id_map users_map,
sftp_name_id_map groups_map);
#ifdef WITH_SERVER
/**
* @brief Create a new sftp server session.

View File

@@ -21,8 +21,6 @@
#ifndef SFTP_PRIV_H
#define SFTP_PRIV_H
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
@@ -64,39 +62,6 @@ int sftp_read_and_dispatch(sftp_session sftp);
sftp_message sftp_dequeue(sftp_session sftp, uint32_t id);
/**
* @brief Receive the response of an sftp request
*
* In blocking mode, if the response hasn't arrived at the time of call, this
* function waits for the response to arrive.
*
* @param sftp The sftp session via which the request was sent.
*
* @param id The request identifier of the request whose
* corresponding response is required.
*
* @param blocking Flag to indicate the operating mode. true indicates
* blocking mode and false indicates non-blocking mode
*
* @param msg_ptr Pointer to the location to store the response message.
* In case of success, the message is allocated
* dynamically and must be freed (using
* sftp_message_free()) by the caller after usage. In case
* of failure, this is left untouched.
*
* @returns SSH_OK on success
* @returns SSH_ERROR on failure with the sftp and ssh errors set
* @returns SSH_AGAIN in case of non-blocking mode if the response hasn't
* arrived yet.
*
* @warning In blocking mode, this may block indefinitely for an invalid request
* identifier.
*/
int sftp_recv_response_msg(sftp_session sftp,
uint32_t id,
bool blocking,
sftp_message *msg_ptr);
/*
* Assigns a new SFTP ID for new requests and assures there is no collision
* between them.

View File

@@ -1,86 +0,0 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2013 by Aris Adamantiadis <aris@badcode.be>
* Copyright (c) 2023 Simon Josefsson <simon@josefsson.org>
* Copyright (c) 2025 Jakub Jelen <jjelen@redhat.com>
*
* 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 SNTRUP761_H_
#define SNTRUP761_H_
#include "config.h"
#include "curve25519.h"
#include "libssh.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef HAVE_CURVE25519
#define HAVE_SNTRUP761 1
#endif
extern void crypto_hash_sha512(unsigned char *out,
const unsigned char *in,
unsigned long long inlen);
/*
* Derived from public domain source, written by (in alphabetical order):
* - Daniel J. Bernstein
* - Chitchanok Chuengsatiansup
* - Tanja Lange
* - Christine van Vredendaal
*/
#include <stdint.h>
#include <string.h>
#define SNTRUP761_SECRETKEY_SIZE 1763
#define SNTRUP761_PUBLICKEY_SIZE 1158
#define SNTRUP761_CIPHERTEXT_SIZE 1039
#define SNTRUP761_SIZE 32
typedef void sntrup761_random_func(void *ctx, size_t length, uint8_t *dst);
void sntrup761_keypair(uint8_t *pk,
uint8_t *sk,
void *random_ctx,
sntrup761_random_func *random);
void sntrup761_enc(uint8_t *c,
uint8_t *k,
const uint8_t *pk,
void *random_ctx,
sntrup761_random_func *random);
void sntrup761_dec(uint8_t *k, const uint8_t *c, const uint8_t *sk);
typedef unsigned char ssh_sntrup761_pubkey[SNTRUP761_PUBLICKEY_SIZE];
typedef unsigned char ssh_sntrup761_privkey[SNTRUP761_SECRETKEY_SIZE];
typedef unsigned char ssh_sntrup761_ciphertext[SNTRUP761_CIPHERTEXT_SIZE];
int ssh_client_sntrup761x25519_init(ssh_session session);
void ssh_client_sntrup761x25519_remove_callbacks(ssh_session session);
#ifdef WITH_SERVER
void ssh_server_sntrup761x25519_init(ssh_session session);
#endif /* WITH_SERVER */
#ifdef __cplusplus
}
#endif
#endif /* SNTRUP761_H_ */

View File

@@ -33,7 +33,7 @@ void ssh_socket_cleanup(void);
ssh_socket ssh_socket_new(ssh_session session);
void ssh_socket_reset(ssh_socket s);
void ssh_socket_free(ssh_socket s);
int 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(ssh_socket s);
void ssh_socket_set_connected(ssh_socket s, struct ssh_poll_handle_struct *p);
int ssh_socket_unix(ssh_socket s, const char *path);

View File

@@ -16,8 +16,8 @@
#define SSH2_MSG_KEXDH_REPLY 31
#define SSH2_MSG_KEX_ECDH_INIT 30
#define SSH2_MSG_KEX_ECDH_REPLY 31
#define SSH2_MSG_KEX_HYBRID_INIT 30
#define SSH2_MSG_KEX_HYBRID_REPLY 31
#define SSH2_MSG_ECMQV_INIT 30
#define SSH2_MSG_ECMQV_REPLY 31
#define SSH2_MSG_KEX_DH_GEX_REQUEST_OLD 30
#define SSH2_MSG_KEX_DH_GEX_GROUP 31

View File

@@ -129,7 +129,6 @@ int evp_build_pkey(const char* name, OSSL_PARAM_BLD *param_bld, EVP_PKEY **pkey,
int evp_dup_dsa_pkey(const ssh_key key, ssh_key new_key, int demote);
int evp_dup_rsa_pkey(const ssh_key key, ssh_key new_key, int demote);
int evp_dup_ecdsa_pkey(const ssh_key key, ssh_key new_key, int demote);
int evp_dup_ed25519_pkey(const ssh_key key, ssh_key new_key, int demote);
#endif /* HAVE_LIBCRYPTO && OPENSSL_VERSION_NUMBER */
#ifdef __cplusplus

View File

@@ -8,4 +8,3 @@ Description: The SSH Library
Version: @PROJECT_VERSION@
Libs: -L${libdir} -lssh
Cflags: -I${includedir}
Requires.private: @LIBSSH_PC_REQUIRES_PRIVATE@

View File

@@ -1 +1 @@
4.10.0
4.10.2

View File

@@ -0,0 +1,445 @@
_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_aio_begin_read
sftp_aio_begin_write
sftp_aio_free
sftp_aio_wait_read
sftp_aio_wait_write
sftp_async_read
sftp_async_read_begin
sftp_attributes_free
sftp_canonicalize_path
sftp_channel_default_data_callback
sftp_channel_default_subsystem_request
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_expand_path
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_hardlink
sftp_home_directory
sftp_init
sftp_limits
sftp_limits_free
sftp_lsetstat
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_free
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_parse_config
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_state
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_forward_port
ssh_channel_open_forward_unix
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_pty_size_modes
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_dup
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_open_reply_accept_channel
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_base64_format
ssh_pki_export_privkey_file
ssh_pki_export_privkey_file_format
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_request_no_more_sessions
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_issue_banner
ssh_send_keepalive
ssh_server_init_kex
ssh_service_request
ssh_session_export_known_hosts_entry
ssh_session_get_known_hosts_entry
ssh_session_has_known_hosts_entry
ssh_session_is_known_server
ssh_session_set_disconnect_message
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_default
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_publickey_auto_get_current_identity
ssh_userauth_try_publickey
ssh_version
ssh_vlog
ssh_write_knownhost
string_burn
string_copy
string_data
string_fill
string_free
string_from_char
string_len
string_new
string_to_char

View File

@@ -0,0 +1,445 @@
_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_aio_begin_read
sftp_aio_begin_write
sftp_aio_free
sftp_aio_wait_read
sftp_aio_wait_write
sftp_async_read
sftp_async_read_begin
sftp_attributes_free
sftp_canonicalize_path
sftp_channel_default_data_callback
sftp_channel_default_subsystem_request
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_expand_path
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_hardlink
sftp_home_directory
sftp_init
sftp_limits
sftp_limits_free
sftp_lsetstat
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_free
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_parse_config
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_state
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_forward_port
ssh_channel_open_forward_unix
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_pty_size_modes
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_dup
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_open_reply_accept_channel
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_base64_format
ssh_pki_export_privkey_file
ssh_pki_export_privkey_file_format
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_request_no_more_sessions
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_issue_banner
ssh_send_keepalive
ssh_server_init_kex
ssh_service_request
ssh_session_export_known_hosts_entry
ssh_session_get_known_hosts_entry
ssh_session_has_known_hosts_entry
ssh_session_is_known_server
ssh_session_set_disconnect_message
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_default
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_publickey_auto_get_current_identity
ssh_userauth_try_publickey
ssh_version
ssh_vlog
ssh_write_knownhost
string_burn
string_copy
string_data
string_fill
string_free
string_from_char
string_len
string_new
string_to_char

View File

@@ -87,7 +87,6 @@ set(libssh_SRCS
connector.c
crypto_common.c
curve25519.c
sntrup761.c
dh.c
ecdh.c
error.c
@@ -175,13 +174,6 @@ if (WITH_GCRYPT)
chachapoly.c
)
endif (NOT HAVE_GCRYPT_CHACHA_POLY)
if (HAVE_GCRYPT_CURVE25519)
set(libssh_SRCS
${libssh_SRCS}
curve25519_gcrypt.c
)
endif(HAVE_GCRYPT_CURVE25519)
elseif (WITH_MBEDTLS)
set(libssh_SRCS
${libssh_SRCS}
@@ -198,7 +190,6 @@ elseif (WITH_MBEDTLS)
external/fe25519.c
external/ge25519.c
external/sc25519.c
external/sntrup761.c
)
if (NOT (HAVE_MBEDTLS_CHACHA20_H AND HAVE_MBEDTLS_POLY1305_H))
set(libssh_SRCS
@@ -208,24 +199,17 @@ elseif (WITH_MBEDTLS)
chachapoly.c
)
endif()
if (HAVE_MBEDTLS_CURVE25519)
set(libssh_SRCS
${libssh_SRCS}
curve25519_mbedcrypto.c
)
endif(HAVE_MBEDTLS_CURVE25519)
else (WITH_GCRYPT)
set(libssh_SRCS
${libssh_SRCS}
threads/libcrypto.c
pki_crypto.c
ecdh_crypto.c
curve25519_crypto.c
getrandom_crypto.c
md_crypto.c
libcrypto.c
dh_crypto.c
external/sntrup761.c
)
if (NOT HAVE_OPENSSL_EVP_CHACHA20)
set(libssh_SRCS
@@ -277,22 +261,14 @@ if (WITH_GSSAPI AND GSSAPI_FOUND)
endif (WITH_GSSAPI AND GSSAPI_FOUND)
if (NOT WITH_NACL)
if (NOT (HAVE_LIBCRYPTO OR HAVE_MBEDTLS_CURVE25519 OR HAVE_GCRYPT_CURVE25519))
if (NOT HAVE_LIBCRYPTO)
set(libssh_SRCS
${libssh_SRCS}
curve25519_fallback.c
external/curve25519_ref.c
)
endif()
endif (NOT WITH_NACL)
if (HAVE_MLKEM)
set(libssh_SRCS
${libssh_SRCS}
mlkem768.c
)
endif (HAVE_MLKEM)
# Set the path to the default map file
set(MAP_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.map")

View File

@@ -67,94 +67,87 @@
(((x) == SSH_AGENT_FAILURE) || ((x) == SSH_COM_AGENT2_FAILURE) || \
((x) == SSH2_AGENT_FAILURE))
static uint32_t
atomicio(struct ssh_agent_struct *agent, void *buf, uint32_t n, int do_read)
{
char *b = buf;
uint32_t pos = 0;
ssize_t res;
ssh_pollfd_t pfd;
ssh_channel channel = agent->channel;
socket_t fd;
static uint32_t atomicio(struct ssh_agent_struct *agent, void *buf, uint32_t n, int do_read) {
char *b = buf;
uint32_t pos = 0;
ssize_t res;
ssh_pollfd_t pfd;
ssh_channel channel = agent->channel;
socket_t fd;
/* Using a socket ? */
if (channel == NULL) {
fd = ssh_socket_get_fd(agent->sock);
pfd.fd = fd;
pfd.events = do_read ? POLLIN : POLLOUT;
/* Using a socket ? */
if (channel == NULL) {
fd = ssh_socket_get_fd(agent->sock);
pfd.fd = fd;
pfd.events = do_read ? POLLIN : POLLOUT;
while (n > pos) {
if (do_read) {
res = recv(fd, b + pos, n - pos, 0);
} else {
res = send(fd, b + pos, n - pos, 0);
}
switch (res) {
case -1:
if (errno == EINTR) {
continue;
}
while (n > pos) {
if (do_read) {
res = recv(fd, b + pos, n - pos, 0);
} else {
res = send(fd, b + pos, n - pos, 0);
}
switch (res) {
case -1:
if (errno == EINTR) {
continue;
}
#ifdef EWOULDBLOCK
if (errno == EAGAIN || errno == EWOULDBLOCK) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
#else
if (errno == EAGAIN) {
if (errno == EAGAIN) {
#endif
(void)ssh_poll(&pfd, 1, -1);
continue;
}
return 0;
case 0:
/* read returns 0 on end-of-file */
errno = do_read ? 0 : EPIPE;
return pos;
default:
pos += (uint32_t)res;
}
}
(void) ssh_poll(&pfd, 1, -1);
continue;
}
return 0;
case 0:
/* read returns 0 on end-of-file */
errno = do_read ? 0 : EPIPE;
return pos;
default:
pos += (uint32_t) res;
}
}
return pos;
} else {
/* using an SSH channel */
while (n > pos) {
if (do_read) {
res = ssh_channel_read(channel, b + pos, n - pos, 0);
} else {
res = ssh_channel_write(channel, b + pos, n - pos);
}
if (res == SSH_AGAIN) {
continue;
}
if (res == SSH_ERROR) {
return 0;
}
pos += (uint32_t)res;
}
return pos;
/* using an SSH channel */
while (n > pos){
if (do_read)
res = ssh_channel_read(channel,b + pos, n-pos, 0);
else
res = ssh_channel_write(channel, b+pos, n-pos);
if (res == SSH_AGAIN)
continue;
if (res == SSH_ERROR)
return 0;
pos += (uint32_t)res;
}
return pos;
}
}
ssh_agent ssh_agent_new(struct ssh_session_struct *session)
{
ssh_agent agent = NULL;
ssh_agent ssh_agent_new(struct ssh_session_struct *session) {
ssh_agent agent = NULL;
agent = calloc(1, sizeof(struct ssh_agent_struct));
if (agent == NULL) {
return NULL;
}
agent = malloc(sizeof(struct ssh_agent_struct));
if (agent == NULL) {
return NULL;
}
ZERO_STRUCTP(agent);
agent->count = 0;
agent->sock = ssh_socket_new(session);
if (agent->sock == NULL) {
SAFE_FREE(agent);
return NULL;
}
agent->channel = NULL;
return agent;
agent->count = 0;
agent->sock = ssh_socket_new(session);
if (agent->sock == NULL) {
SAFE_FREE(agent);
return NULL;
}
agent->channel = NULL;
return agent;
}
static void agent_set_channel(struct ssh_agent_struct *agent,
ssh_channel channel)
{
agent->channel = channel;
static void agent_set_channel(struct ssh_agent_struct *agent, ssh_channel channel){
agent->channel = channel;
}
/**
@@ -175,19 +168,15 @@ static void agent_set_channel(struct ssh_agent_struct *agent,
* @returns SSH_OK in case of success
* SSH_ERROR in case of an error
*/
int ssh_set_agent_channel(ssh_session session, ssh_channel channel)
{
if (!session) {
return SSH_ERROR;
}
if (!session->agent) {
ssh_set_error(session,
SSH_REQUEST_DENIED,
"Session has no active agent");
return SSH_ERROR;
}
agent_set_channel(session->agent, channel);
return SSH_OK;
int ssh_set_agent_channel(ssh_session session, ssh_channel channel){
if (!session)
return SSH_ERROR;
if (!session->agent){
ssh_set_error(session, SSH_REQUEST_DENIED, "Session has no active agent");
return SSH_ERROR;
}
agent_set_channel(session->agent, channel);
return SSH_OK;
}
/** @brief sets the SSH agent socket.
@@ -198,71 +187,64 @@ int ssh_set_agent_channel(ssh_session session, ssh_channel channel)
* @returns SSH_OK in case of success
* SSH_ERROR in case of an error
*/
int ssh_set_agent_socket(ssh_session session, socket_t fd)
{
if (!session) {
return SSH_ERROR;
}
if (!session->agent) {
ssh_set_error(session,
SSH_REQUEST_DENIED,
"Session has no active agent");
return SSH_ERROR;
}
int ssh_set_agent_socket(ssh_session session, socket_t fd){
if (!session)
return SSH_ERROR;
if (!session->agent){
ssh_set_error(session, SSH_REQUEST_DENIED, "Session has no active agent");
return SSH_ERROR;
}
return ssh_socket_set_fd(session->agent->sock, fd);
ssh_socket_set_fd(session->agent->sock, fd);
return SSH_OK;
}
/**
* @}
*/
void ssh_agent_close(struct ssh_agent_struct *agent)
{
if (agent == NULL) {
return;
}
void ssh_agent_close(struct ssh_agent_struct *agent) {
if (agent == NULL) {
return;
}
ssh_socket_close(agent->sock);
ssh_socket_close(agent->sock);
}
void ssh_agent_free(ssh_agent agent)
{
if (agent) {
if (agent->ident) {
SSH_BUFFER_FREE(agent->ident);
}
if (agent->sock) {
ssh_agent_close(agent);
ssh_socket_free(agent->sock);
}
SAFE_FREE(agent);
void ssh_agent_free(ssh_agent agent) {
if (agent) {
if (agent->ident) {
SSH_BUFFER_FREE(agent->ident);
}
if (agent->sock) {
ssh_agent_close(agent);
ssh_socket_free(agent->sock);
}
SAFE_FREE(agent);
}
}
static int agent_connect(ssh_session session)
{
const char *auth_sock = NULL;
if (session == NULL || session->agent == NULL) {
return -1;
}
if (session->agent->channel != NULL) {
return 0;
}
auth_sock = session->opts.agent_socket ? session->opts.agent_socket
: getenv("SSH_AUTH_SOCK");
if (auth_sock && *auth_sock) {
if (ssh_socket_unix(session->agent->sock, auth_sock) < 0) {
return -1;
}
return 0;
}
static int agent_connect(ssh_session session) {
const char *auth_sock = NULL;
if (session == NULL || session->agent == NULL) {
return -1;
}
if (session->agent->channel != NULL)
return 0;
auth_sock = session->opts.agent_socket ?
session->opts.agent_socket : getenv("SSH_AUTH_SOCK");
if (auth_sock && *auth_sock) {
if (ssh_socket_unix(session->agent->sock, auth_sock) < 0) {
return -1;
}
return 0;
}
return -1;
}
#if 0
@@ -286,66 +268,61 @@ static int agent_decode_reply(struct ssh_session_struct *session, int type) {
#endif
static int agent_talk(struct ssh_session_struct *session,
struct ssh_buffer_struct *request,
struct ssh_buffer_struct *reply)
{
uint32_t len = 0;
uint8_t tmpbuf[4];
uint8_t *payload = tmpbuf;
char err_msg[SSH_ERRNO_MSG_MAX] = {0};
struct ssh_buffer_struct *request, struct ssh_buffer_struct *reply) {
uint32_t len = 0;
uint8_t tmpbuf[4];
uint8_t *payload = tmpbuf;
char err_msg[SSH_ERRNO_MSG_MAX] = {0};
len = ssh_buffer_get_len(request);
SSH_LOG(SSH_LOG_TRACE, "Request length: %" PRIu32, len);
PUSH_BE_U32(payload, 0, len);
len = ssh_buffer_get_len(request);
SSH_LOG(SSH_LOG_TRACE, "Request length: %" PRIu32, len);
PUSH_BE_U32(payload, 0, len);
/* send length and then the request packet */
if (atomicio(session->agent, payload, 4, 0) == 4) {
if (atomicio(session->agent, ssh_buffer_get(request), len, 0) != len) {
SSH_LOG(SSH_LOG_TRACE,
"atomicio sending request failed: %s",
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
return -1;
}
} else {
SSH_LOG(SSH_LOG_TRACE,
"atomicio sending request length failed: %s",
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
return -1;
/* send length and then the request packet */
if (atomicio(session->agent, payload, 4, 0) == 4) {
if (atomicio(session->agent, ssh_buffer_get(request), len, 0)
!= len) {
SSH_LOG(SSH_LOG_TRACE, "atomicio sending request failed: %s",
strerror(errno));
return -1;
}
} else {
SSH_LOG(SSH_LOG_TRACE,
"atomicio sending request length failed: %s",
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
return -1;
}
/* wait for response, read the length of the response packet */
if (atomicio(session->agent, payload, 4, 1) != 4) {
SSH_LOG(SSH_LOG_TRACE,
"atomicio read response length failed: %s",
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
return -1;
}
/* wait for response, read the length of the response packet */
if (atomicio(session->agent, payload, 4, 1) != 4) {
SSH_LOG(SSH_LOG_TRACE, "atomicio read response length failed: %s",
strerror(errno));
return -1;
}
len = PULL_BE_U32(payload, 0);
if (len > 256 * 1024) {
ssh_set_error(session,
SSH_FATAL,
"Authentication response too long: %" PRIu32,
len);
return -1;
}
SSH_LOG(SSH_LOG_TRACE, "Response length: %" PRIu32, len);
len = PULL_BE_U32(payload, 0);
if (len > 256 * 1024) {
ssh_set_error(session, SSH_FATAL,
"Authentication response too long: %" PRIu32, len);
return -1;
}
SSH_LOG(SSH_LOG_TRACE, "Response length: %" PRIu32, len);
payload = ssh_buffer_allocate(reply, len);
if (payload == NULL) {
SSH_LOG(SSH_LOG_DEBUG, "Not enough space");
return -1;
}
payload = ssh_buffer_allocate(reply, len);
if (payload == NULL) {
SSH_LOG(SSH_LOG_DEBUG, "Not enough space");
return -1;
}
if (atomicio(session->agent, payload, len, 1) != len) {
SSH_LOG(SSH_LOG_DEBUG,
"Error reading response from authentication socket.");
/* Rollback the unused space */
ssh_buffer_pass_bytes_end(reply, len);
return -1;
}
if (atomicio(session->agent, payload, len, 1) != len) {
SSH_LOG(SSH_LOG_DEBUG,
"Error reading response from authentication socket.");
/* Rollback the unused space */
ssh_buffer_pass_bytes_end(reply, len);
return -1;
}
return 0;
return 0;
}
uint32_t ssh_agent_get_ident_count(struct ssh_session_struct *session)
@@ -494,23 +471,22 @@ ssh_key ssh_agent_get_next_ident(struct ssh_session_struct *session,
return key;
}
int ssh_agent_is_running(ssh_session session)
{
if (session == NULL || session->agent == NULL) {
return 0;
}
if (ssh_socket_is_open(session->agent->sock)) {
return 1;
} else {
if (agent_connect(session) < 0) {
return 0;
} else {
return 1;
}
}
int ssh_agent_is_running(ssh_session session) {
if (session == NULL || session->agent == NULL) {
return 0;
}
if (ssh_socket_is_open(session->agent->sock)) {
return 1;
} else {
if (agent_connect(session) < 0) {
return 0;
} else {
return 1;
}
}
return 0;
}
ssh_string ssh_agent_sign_data(ssh_session session,
@@ -524,7 +500,6 @@ ssh_string ssh_agent_sign_data(ssh_session session,
unsigned int type = 0;
unsigned int flags = 0;
uint32_t dlen;
size_t request_len;
int rc;
request = ssh_buffer_new();
@@ -550,14 +525,11 @@ ssh_string ssh_agent_sign_data(ssh_session session,
* - 2 x uint32_t
* - 1 x ssh_string (uint8_t + data)
*/
request_len = sizeof(uint8_t) * 2 +
sizeof(uint32_t) * 2 +
ssh_string_len(key_blob);
/* this can't overflow the uint32_t as the
* STRING_SIZE_MAX is (UINT32_MAX >> 8) + 1 */
rc = ssh_buffer_allocate_size(request, (uint32_t)request_len);
rc = ssh_buffer_allocate_size(request,
sizeof(uint8_t) * 2 +
sizeof(uint32_t) * 2 +
ssh_string_len(key_blob));
if (rc < 0) {
SSH_STRING_FREE(key_blob);
SSH_BUFFER_FREE(request);
return NULL;
}

View File

@@ -463,108 +463,6 @@ fail:
return SSH_AUTH_ERROR;
}
/**
* @internal
*
* @brief Adds the server's public key to the authentication request.
*
* This function is used internally when the hostbound public key authentication
* extension is enabled. It export the server's public key and adds it to the
* authentication buffer.
*
* @param[in] session The SSH session.
*
* @returns SSH_OK on success, SSH_ERROR if an error occurred.
*/
static int add_hostbound_pubkey(ssh_session session)
{
int rc;
ssh_string server_pubkey_s = NULL;
if (session == NULL) {
return SSH_ERROR;
}
if (session->current_crypto == NULL ||
session->current_crypto->server_pubkey == NULL) {
ssh_set_error(session,
SSH_FATAL,
"Invalid session or server public key");
return SSH_ERROR;
}
rc = ssh_pki_export_pubkey_blob(session->current_crypto->server_pubkey,
&server_pubkey_s);
if (rc < 0) {
goto error;
}
rc = ssh_buffer_add_ssh_string(session->out_buffer, server_pubkey_s);
if (rc < 0) {
goto error;
}
error:
SSH_STRING_FREE(server_pubkey_s);
return rc;
}
/**
* @internal
*
* @brief Build a public key authentication request.
*
* This helper function creates a SSH2_MSG_USERAUTH_REQUEST message for public
* key authentication and adds the server's public key if the hostbound
* extension is enabled.
*
* @param[in] session The SSH session.
* @param[in] username The username, may be NULL.
* @param[in] auth_type Authentication type (0 for key offer, 1 for actual
* auth).
* @param[in] sig_type_c The signature algorithm name.
* @param[in] pubkey_s The public key string.
*
* @return SSH_OK on success, SSH_ERROR if an error occurred.
*/
static int build_pubkey_auth_request(ssh_session session,
const char *username,
int has_signature,
const char *sig_type_c,
ssh_string pubkey_s)
{
int rc;
const char *auth_method = "publickey";
if (session->extensions & SSH_EXT_PUBLICKEY_HOSTBOUND) {
auth_method = "publickey-hostbound-v00@openssh.com";
}
/* request */
rc = ssh_buffer_pack(session->out_buffer,
"bsssbsS",
SSH2_MSG_USERAUTH_REQUEST,
username ? username : session->opts.username,
"ssh-connection",
auth_method,
has_signature, /* private key? */
sig_type_c, /* algo */
pubkey_s /* public key */
);
if (rc < 0) {
return SSH_ERROR;
}
if (session->extensions & SSH_EXT_PUBLICKEY_HOSTBOUND) {
rc = add_hostbound_pubkey(session);
if (rc < 0) {
return SSH_ERROR;
}
}
return SSH_OK;
}
/**
* @brief Try to authenticate with the given public key.
*
@@ -611,17 +509,17 @@ int ssh_userauth_try_publickey(ssh_session session,
return SSH_AUTH_ERROR;
}
switch (session->pending_call_state) {
case SSH_PENDING_CALL_NONE:
break;
case SSH_PENDING_CALL_AUTH_OFFER_PUBKEY:
goto pending;
default:
ssh_set_error(session,
SSH_FATAL,
"Wrong state (%d) during pending SSH call",
session->pending_call_state);
return SSH_AUTH_ERROR;
switch(session->pending_call_state) {
case SSH_PENDING_CALL_NONE:
break;
case SSH_PENDING_CALL_AUTH_OFFER_PUBKEY:
goto pending;
default:
ssh_set_error(session,
SSH_FATAL,
"Wrong state (%d) during pending SSH call",
session->pending_call_state);
return SSH_AUTH_ERROR;
}
/* Note, that this is intentionally before checking the signature type
@@ -638,15 +536,13 @@ int ssh_userauth_try_publickey(ssh_session session,
/* Check if the given public key algorithm is allowed */
sig_type_c = ssh_key_get_signature_algorithm(session, pubkey->type);
if (sig_type_c == NULL) {
ssh_set_error(session,
SSH_REQUEST_DENIED,
ssh_set_error(session, SSH_REQUEST_DENIED,
"Invalid key type (unknown)");
return SSH_AUTH_DENIED;
}
rc = ssh_key_algorithm_allowed(session, sig_type_c);
if (!rc) {
ssh_set_error(session,
SSH_REQUEST_DENIED,
ssh_set_error(session, SSH_REQUEST_DENIED,
"The key algorithm '%s' is not allowed to be used by"
" PUBLICKEY_ACCEPTED_TYPES configuration option",
sig_type_c);
@@ -654,12 +550,9 @@ int ssh_userauth_try_publickey(ssh_session session,
}
allowed = ssh_key_size_allowed(session, pubkey);
if (!allowed) {
ssh_set_error(session,
SSH_REQUEST_DENIED,
ssh_set_error(session, SSH_REQUEST_DENIED,
"The '%s' key type of size %d is not allowed by "
"RSA_MIN_SIZE",
sig_type_c,
ssh_key_size(pubkey));
"RSA_MIN_SIZE", sig_type_c, ssh_key_size(pubkey));
return SSH_AUTH_DENIED;
}
@@ -670,10 +563,20 @@ int ssh_userauth_try_publickey(ssh_session session,
}
SSH_LOG(SSH_LOG_TRACE, "Trying signature type %s", sig_type_c);
rc = build_pubkey_auth_request(session, username, 0, sig_type_c, pubkey_s);
/* request */
rc = ssh_buffer_pack(session->out_buffer, "bsssbsS",
SSH2_MSG_USERAUTH_REQUEST,
username ? username : session->opts.username,
"ssh-connection",
"publickey",
0, /* private key ? */
sig_type_c, /* algo */
pubkey_s /* public key */
);
if (rc < 0) {
goto fail;
}
SSH_STRING_FREE(pubkey_s);
session->auth.current_method = SSH_AUTH_METHOD_PUBLICKEY;
@@ -742,17 +645,16 @@ int ssh_userauth_publickey(ssh_session session,
return SSH_AUTH_ERROR;
}
switch (session->pending_call_state) {
case SSH_PENDING_CALL_NONE:
break;
case SSH_PENDING_CALL_AUTH_PUBKEY:
goto pending;
default:
ssh_set_error(
session,
SSH_FATAL,
"Bad call during pending SSH call in ssh_userauth_try_publickey");
return SSH_AUTH_ERROR;
switch(session->pending_call_state) {
case SSH_PENDING_CALL_NONE:
break;
case SSH_PENDING_CALL_AUTH_PUBKEY:
goto pending;
default:
ssh_set_error(session,
SSH_FATAL,
"Bad call during pending SSH call in ssh_userauth_try_publickey");
return SSH_AUTH_ERROR;
}
/* Note, that this is intentionally before checking the signature type
@@ -772,15 +674,13 @@ int ssh_userauth_publickey(ssh_session session,
/* Check if the given public key algorithm is allowed */
sig_type_c = ssh_key_get_signature_algorithm(session, key_type);
if (sig_type_c == NULL) {
ssh_set_error(session,
SSH_REQUEST_DENIED,
ssh_set_error(session, SSH_REQUEST_DENIED,
"Invalid key type (unknown)");
return SSH_AUTH_DENIED;
}
rc = ssh_key_algorithm_allowed(session, sig_type_c);
if (!rc) {
ssh_set_error(session,
SSH_REQUEST_DENIED,
ssh_set_error(session, SSH_REQUEST_DENIED,
"The key algorithm '%s' is not allowed to be used by"
" PUBLICKEY_ACCEPTED_TYPES configuration option",
sig_type_c);
@@ -788,12 +688,9 @@ int ssh_userauth_publickey(ssh_session session,
}
allowed = ssh_key_size_allowed(session, privkey);
if (!allowed) {
ssh_set_error(session,
SSH_REQUEST_DENIED,
ssh_set_error(session, SSH_REQUEST_DENIED,
"The '%s' key type of size %d is not allowed by "
"RSA_MIN_SIZE",
sig_type_c,
ssh_key_size(privkey));
"RSA_MIN_SIZE", sig_type_c, ssh_key_size(privkey));
return SSH_AUTH_DENIED;
}
@@ -804,7 +701,16 @@ int ssh_userauth_publickey(ssh_session session,
}
SSH_LOG(SSH_LOG_TRACE, "Sending signature type %s", sig_type_c);
rc = build_pubkey_auth_request(session, username, 1, sig_type_c, str);
/* request */
rc = ssh_buffer_pack(session->out_buffer, "bsssbsS",
SSH2_MSG_USERAUTH_REQUEST,
username ? username : session->opts.username,
"ssh-connection",
"publickey",
1, /* private key */
sig_type_c, /* algo */
str /* public key or cert */
);
if (rc < 0) {
goto fail;
}
@@ -892,16 +798,14 @@ static int ssh_userauth_agent_publickey(ssh_session session,
/* Check if the given public key algorithm is allowed */
sig_type_c = ssh_key_get_signature_algorithm(session, pubkey->type);
if (sig_type_c == NULL) {
ssh_set_error(session,
SSH_REQUEST_DENIED,
ssh_set_error(session, SSH_REQUEST_DENIED,
"Invalid key type (unknown)");
SSH_STRING_FREE(pubkey_s);
return SSH_AUTH_DENIED;
}
rc = ssh_key_algorithm_allowed(session, sig_type_c);
if (!rc) {
ssh_set_error(session,
SSH_REQUEST_DENIED,
ssh_set_error(session, SSH_REQUEST_DENIED,
"The key algorithm '%s' is not allowed to be used by"
" PUBLICKEY_ACCEPTED_TYPES configuration option",
sig_type_c);
@@ -910,21 +814,27 @@ static int ssh_userauth_agent_publickey(ssh_session session,
}
allowed = ssh_key_size_allowed(session, pubkey);
if (!allowed) {
ssh_set_error(session,
SSH_REQUEST_DENIED,
ssh_set_error(session, SSH_REQUEST_DENIED,
"The '%s' key type of size %d is not allowed by "
"RSA_MIN_SIZE",
sig_type_c,
ssh_key_size(pubkey));
"RSA_MIN_SIZE", sig_type_c, ssh_key_size(pubkey));
SSH_STRING_FREE(pubkey_s);
return SSH_AUTH_DENIED;
}
rc = build_pubkey_auth_request(session, username, 1, sig_type_c, pubkey_s);
/* request */
rc = ssh_buffer_pack(session->out_buffer, "bsssbsS",
SSH2_MSG_USERAUTH_REQUEST,
username ? username : session->opts.username,
"ssh-connection",
"publickey",
1, /* private key */
sig_type_c, /* algo */
pubkey_s /* public key */
);
SSH_STRING_FREE(pubkey_s);
if (rc < 0) {
goto fail;
}
SSH_STRING_FREE(pubkey_s);
/* sign the buffer with the private key */
sig_blob = ssh_pki_do_sign_agent(session, session->out_buffer, pubkey);
@@ -982,7 +892,7 @@ void ssh_agent_state_free(void *data)
if (state) {
SSH_STRING_FREE_CHAR(state->comment);
ssh_key_free(state->pubkey);
free(state);
free (state);
}
}
@@ -1008,7 +918,8 @@ void ssh_agent_state_free(void *data)
* authentication. The username should only be set with ssh_options_set() only
* before you connect to the server.
*/
int ssh_userauth_agent(ssh_session session, const char *username)
int ssh_userauth_agent(ssh_session session,
const char *username)
{
int rc = SSH_AUTH_ERROR;
struct ssh_agent_state_struct *state = NULL;
@@ -1027,11 +938,12 @@ int ssh_userauth_agent(ssh_session session, const char *username)
}
if (!session->agent_state) {
session->agent_state = calloc(1, sizeof(struct ssh_agent_state_struct));
session->agent_state = malloc(sizeof(struct ssh_agent_state_struct));
if (!session->agent_state) {
ssh_set_error_oom(session);
return SSH_AUTH_ERROR;
}
ZERO_STRUCTP(session->agent_state);
session->agent_state->state = SSH_AGENT_STATE_NONE;
}

View File

@@ -186,7 +186,7 @@ error:
static int to_block4(unsigned long *block, const char *source, int num)
{
const char *ptr = NULL;
size_t i;
unsigned int i;
*block = 0;
if (num < 1) {

View File

@@ -27,52 +27,40 @@
#include "libssh/bignum.h"
#include "libssh/string.h"
static ssh_string make_bignum_string(bignum num, size_t pad_to_len)
{
ssh_string ptr = NULL;
size_t pad = 0;
size_t len = bignum_num_bytes(num);
size_t bits = bignum_num_bits(num);
ssh_string ssh_make_bignum_string(bignum num) {
ssh_string ptr = NULL;
size_t pad = 0;
size_t len = bignum_num_bytes(num);
size_t bits = bignum_num_bits(num);
if (pad_to_len == 0) {
/* If the first bit is set we have a negative number */
if (!(bits % 8) && bignum_is_bit_set(num, bits - 1)) {
pad++;
}
} else {
if (len > pad_to_len) {
return NULL;
}
pad = pad_to_len - len;
}
if (len == 0) {
return NULL;
}
/* If the first bit is set we have a negative number */
if (!(bits % 8) && bignum_is_bit_set(num, bits - 1)) {
pad++;
}
#ifdef DEBUG_CRYPTO
SSH_LOG(SSH_LOG_TRACE, "%zu bits, %zu bytes, %zu padding", bits, len, pad);
SSH_LOG(SSH_LOG_TRACE,
"%zu bits, %zu bytes, %zu padding",
bits, len, pad);
#endif /* DEBUG_CRYPTO */
ptr = ssh_string_new(len + pad);
if (ptr == NULL) {
return NULL;
}
ptr = ssh_string_new(len + pad);
if (ptr == NULL) {
return NULL;
}
/* We have a negative number so we need a leading zero */
if (pad) {
memset(ptr->data, 0, pad);
}
/* We have a negative number so we need a leading zero */
if (pad) {
ptr->data[0] = 0;
}
bignum_bn2bin(num, len, ptr->data + pad);
bignum_bn2bin(num, len, ptr->data + pad);
return ptr;
}
ssh_string ssh_make_bignum_string(bignum num)
{
return make_bignum_string(num, 0);
}
ssh_string ssh_make_padded_bignum_string(bignum num, size_t pad_len)
{
return make_bignum_string(num, pad_len);
return ptr;
}
bignum ssh_make_string_bn(ssh_string string)
@@ -83,11 +71,10 @@ bignum ssh_make_string_bn(ssh_string string)
#ifdef DEBUG_CRYPTO
SSH_LOG(SSH_LOG_TRACE,
"Importing a %zu bits, %zu bytes object ...",
len * 8,
len);
len * 8, len);
#endif /* DEBUG_CRYPTO */
bignum_bin2bn(string->data, (int)len, &bn);
bignum_bin2bn(string->data, len, &bn);
return bn;
}
@@ -99,9 +86,7 @@ void ssh_print_bignum(const char *name, const_bignum num)
if (num != NULL) {
bignum_bn2hex(num, &hex);
}
SSH_LOG(SSH_LOG_DEBUG,
"%s value: %s",
name,
SSH_LOG(SSH_LOG_DEBUG, "%s value: %s", name,
(hex == NULL) ? "(null)" : (char *)hex);
ssh_crypto_free(hex);
}

View File

@@ -218,12 +218,28 @@ static int ssh_bind_import_keys(ssh_bind sshbind) {
return SSH_OK;
}
int ssh_bind_listen(ssh_bind sshbind)
{
int ssh_bind_listen(ssh_bind sshbind) {
const char *host = NULL;
socket_t fd;
int rc;
/* Apply global bind configurations, if it hasn't been applied before */
rc = ssh_bind_options_parse_config(sshbind, NULL);
if (rc != 0) {
ssh_set_error(sshbind, SSH_FATAL,"Could not parse global config");
return SSH_ERROR;
}
/* Set default hostkey paths if no hostkey was found before */
if (sshbind->ecdsakey == NULL &&
sshbind->rsakey == NULL &&
sshbind->ed25519key == NULL) {
sshbind->ecdsakey = strdup("/etc/ssh/ssh_host_ecdsa_key");
sshbind->rsakey = strdup("/etc/ssh/ssh_host_rsa_key");
sshbind->ed25519key = strdup("/etc/ssh/ssh_host_ed25519_key");
}
/* Apply global bind configurations, if it hasn't been applied before */
rc = ssh_bind_options_parse_config(sshbind, NULL);
if (rc != 0) {
@@ -273,10 +289,10 @@ int ssh_bind_listen(ssh_bind sshbind)
}
sshbind->bindfd = fd;
} else {
SSH_LOG(SSH_LOG_DEBUG, "Using app-provided bind socket");
}
return 0;
} else {
SSH_LOG(SSH_LOG_DEBUG, "Using app-provided bind socket");
}
return 0;
}
int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks, void *userdata)
@@ -489,10 +505,7 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd)
ssh_set_error_oom(sshbind);
return SSH_ERROR;
}
rc = ssh_socket_set_fd(session->socket, fd);
if (rc != SSH_OK) {
return rc;
}
ssh_socket_set_fd(session->socket, fd);
handle = ssh_socket_get_poll_handle(session->socket);
if (handle == NULL) {
ssh_set_error_oom(sshbind);

View File

@@ -104,11 +104,6 @@ ssh_bind_config_keyword_table[] = {
.opcode = BIND_CFG_HOSTKEY_ALGORITHMS,
.allowed_in_match = true
},
{
.name = "requiredrsasize",
.opcode = BIND_CFG_REQUIRED_RSA_SIZE,
.allowed_in_match = true
},
{
.opcode = BIND_CFG_UNKNOWN,
}
@@ -298,7 +293,6 @@ ssh_bind_config_parse_line(ssh_bind bind,
const char *p = NULL;
char *s = NULL, *x = NULL;
char *keyword = NULL;
long l;
size_t len;
int rc = 0;
@@ -600,18 +594,6 @@ ssh_bind_config_parse_line(ssh_bind bind,
}
}
break;
case BIND_CFG_REQUIRED_RSA_SIZE:
l = ssh_config_get_long(&s, -1);
if (l >= 0 && (*parser_flags & PARSING)) {
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_RSA_MIN_SIZE, &l);
if (rc != 0) {
SSH_LOG(SSH_LOG_TRACE,
"line %d: Failed to set RequiredRSASize value '%ld'",
count,
l);
}
}
break;
case BIND_CFG_NOT_ALLOWED_IN_MATCH:
SSH_LOG(SSH_LOG_DEBUG, "Option not allowed in Match block: %s, line: %d",
keyword, count);
@@ -687,8 +669,7 @@ int ssh_bind_config_parse_string(ssh_bind bind, const char *input)
{
char line[MAX_LINE_SIZE] = {0};
const char *c = input, *line_start = input;
unsigned int line_num = 0;
size_t line_len;
unsigned int line_num = 0, line_len;
uint32_t parser_flags;
int rv;
@@ -717,10 +698,8 @@ int ssh_bind_config_parse_string(ssh_bind bind, const char *input)
}
line_len = c - line_start;
if (line_len > MAX_LINE_SIZE - 1) {
SSH_LOG(SSH_LOG_WARN,
"Line %u too long: %zu characters",
line_num,
line_len);
SSH_LOG(SSH_LOG_WARN, "Line %u too long: %u characters",
line_num, line_len);
return SSH_ERROR;
}
memcpy(line, line_start, line_len);

View File

@@ -407,26 +407,20 @@ void *ssh_buffer_allocate(struct ssh_buffer_struct *buffer, uint32_t len)
*
* @return 0 on success, < 0 on error.
*/
int
ssh_buffer_add_ssh_string(struct ssh_buffer_struct *buffer,
struct ssh_string_struct *string)
{
size_t len;
int rc;
int ssh_buffer_add_ssh_string(struct ssh_buffer_struct *buffer,
struct ssh_string_struct *string) {
uint32_t len = 0;
if (string == NULL) {
return -1;
}
if (string == NULL) {
return -1;
}
len = ssh_string_len(string) + sizeof(uint32_t);
/* this can't overflow the uint32_t as the
* STRING_SIZE_MAX is (UINT32_MAX >> 8) + 1 */
rc = ssh_buffer_add_data(buffer, string, (uint32_t)len);
if (rc < 0) {
return -1;
}
len = ssh_string_len(string);
if (ssh_buffer_add_data(buffer, string, len + sizeof(uint32_t)) < 0) {
return -1;
}
return 0;
return 0;
}
/**
@@ -617,53 +611,6 @@ uint32_t ssh_buffer_get_len(struct ssh_buffer_struct *buffer){
return buffer->used - buffer->pos;
}
/**
* @internal
*
* @brief Duplicate an existing buffer.
*
* Creates a new ssh_buffer and copies all data from the source buffer.
* The new buffer preserves the secure flag setting of the source.
*
* @param[in] buffer The buffer to duplicate. Can be NULL.
*
* @return A new buffer containing a copy of the data on success,
* NULL on failure or if buffer is NULL.
*
* @see ssh_buffer_free()
*/
ssh_buffer ssh_buffer_dup(const ssh_buffer buffer)
{
ssh_buffer new_buffer = NULL;
int rc;
if (buffer == NULL) {
return NULL;
}
buffer_verify(buffer);
new_buffer = ssh_buffer_new();
if (new_buffer == NULL) {
return NULL;
}
new_buffer->secure = buffer->secure;
if (ssh_buffer_get_len(buffer) > 0) {
rc = ssh_buffer_add_data(new_buffer,
ssh_buffer_get(buffer),
ssh_buffer_get_len(buffer));
if (rc != SSH_OK) {
ssh_buffer_free(new_buffer);
return NULL;
}
}
buffer_verify(new_buffer);
return new_buffer;
}
/**
* @internal
*
@@ -876,7 +823,6 @@ static int ssh_buffer_pack_allocate_va(struct ssh_buffer_struct *buffer,
const char *p = NULL;
ssh_string string = NULL;
char *cstring = NULL;
bignum b = NULL;
size_t needed_size = 0;
size_t len;
size_t count;
@@ -921,18 +867,13 @@ static int ssh_buffer_pack_allocate_va(struct ssh_buffer_struct *buffer,
va_arg(ap, void *);
count++; /* increase argument count */
break;
case 'F':
case 'B':
b = va_arg(ap, bignum);
if (*p == 'F') {
/* For padded bignum, we know the exact length */
len = va_arg(ap, size_t);
count++; /* increase argument count */
needed_size += sizeof(uint32_t) + len;
} else {
/* The bignum bytes + 1 for possible padding */
needed_size += sizeof(uint32_t) + bignum_num_bytes(b) + 1;
}
va_arg(ap, bignum);
/*
* Use a fixed size for a bignum
* (they should normally be around 32)
*/
needed_size += 64;
break;
case 't':
cstring = va_arg(ap, char *);
@@ -1038,40 +979,24 @@ ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
case 's':
cstring = va_arg(ap, char *);
len = strlen(cstring);
if (len > UINT32_MAX) {
rc = SSH_ERROR;
break;
}
o.dword = (uint32_t)len;
rc = ssh_buffer_add_u32(buffer, htonl(o.dword));
rc = ssh_buffer_add_u32(buffer, htonl(len));
if (rc == SSH_OK){
rc = ssh_buffer_add_data(buffer, cstring, o.dword);
rc = ssh_buffer_add_data(buffer, cstring, len);
}
cstring = NULL;
break;
case 'P':
len = va_arg(ap, size_t);
if (len > UINT32_MAX) {
rc = SSH_ERROR;
break;
}
o.data = va_arg(ap, void *);
count++; /* increase argument count */
rc = ssh_buffer_add_data(buffer, o.data, (uint32_t)len);
rc = ssh_buffer_add_data(buffer, o.data, len);
o.data = NULL;
break;
case 'F':
case 'B':
b = va_arg(ap, bignum);
if (*p == 'F') {
len = va_arg(ap, size_t);
count++; /* increase argument count */
o.string = ssh_make_padded_bignum_string(b, len);
} else {
o.string = ssh_make_bignum_string(b);
}
o.string = ssh_make_bignum_string(b);
if(o.string == NULL){
rc = SSH_ERROR;
break;
@@ -1082,11 +1007,7 @@ ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
case 't':
cstring = va_arg(ap, char *);
len = strlen(cstring);
if (len > UINT32_MAX) {
rc = SSH_ERROR;
break;
}
rc = ssh_buffer_add_data(buffer, cstring, (uint32_t)len);
rc = ssh_buffer_add_data(buffer, cstring, len);
cstring = NULL;
break;
default:
@@ -1127,8 +1048,6 @@ ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
* 'P': size_t, void * (len of data, pointer to data)
* only pushes data.
* 'B': bignum (pushed as SSH string)
* 'F': bignum, size_t (bignum, padded to fixed length,
* pushed as SSH string)
* @returns SSH_OK on success
* SSH_ERROR on error
* @warning when using 'P' with a constant size (e.g. 8), do not
@@ -1268,28 +1187,28 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
if (rlen != 4){
break;
}
u32len = ntohl(u32len);
if (u32len > max_len - 1) {
len = ntohl(u32len);
if (len > max_len - 1) {
break;
}
rc = ssh_buffer_validate_length(buffer, u32len);
rc = ssh_buffer_validate_length(buffer, len);
if (rc != SSH_OK) {
break;
}
*o.cstring = malloc(u32len + 1);
*o.cstring = malloc(len + 1);
if (*o.cstring == NULL){
rc = SSH_ERROR;
break;
}
rlen = ssh_buffer_get_data(buffer, *o.cstring, u32len);
if (rlen != u32len) {
rlen = ssh_buffer_get_data(buffer, *o.cstring, len);
if (rlen != len){
SAFE_FREE(*o.cstring);
rc = SSH_ERROR;
break;
}
(*o.cstring)[u32len] = '\0';
(*o.cstring)[len] = '\0';
o.cstring = NULL;
rc = SSH_OK;
break;
@@ -1314,7 +1233,7 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
rc = SSH_ERROR;
break;
}
rlen = ssh_buffer_get_data(buffer, *o.data, (uint32_t)len);
rlen = ssh_buffer_get_data(buffer, *o.data, len);
if (rlen != len){
SAFE_FREE(*o.data);
rc = SSH_ERROR;

View File

@@ -24,11 +24,11 @@
#include "config.h"
#include "libssh/callbacks.h"
#include "libssh/misc.h"
#include "libssh/session.h"
#include "libssh/misc.h"
#define is_callback_valid(session, cb) \
(cb->size > 0 || cb->size <= 1024 * sizeof(void *))
(cb->size <= 0 || cb->size > 1024 * sizeof(void *))
/* LEGACY */
static void ssh_legacy_log_callback(int priority,
@@ -45,7 +45,8 @@ static void ssh_legacy_log_callback(int priority,
log_fn(session, priority, buffer, log_data);
}
void _ssh_remove_legacy_log_cb(void)
void
_ssh_remove_legacy_log_cb(void)
{
if (ssh_get_log_callback() == ssh_legacy_log_callback) {
_ssh_reset_log_cb();
@@ -53,27 +54,26 @@ void _ssh_remove_legacy_log_cb(void)
}
}
int ssh_set_callbacks(ssh_session session, ssh_callbacks cb)
{
if (session == NULL || cb == NULL) {
return SSH_ERROR;
}
int ssh_set_callbacks(ssh_session session, ssh_callbacks cb) {
if (session == NULL || cb == NULL) {
return SSH_ERROR;
}
if (!is_callback_valid(session, cb)) {
ssh_set_error(session,
SSH_FATAL,
"Invalid callback passed in (badly initialized)");
return SSH_ERROR;
};
session->common.callbacks = cb;
if (is_callback_valid(session, cb)) {
ssh_set_error(session,
SSH_FATAL,
"Invalid callback passed in (badly initialized)");
return SSH_ERROR;
};
session->common.callbacks = cb;
/* LEGACY */
if (ssh_get_log_callback() == NULL && cb->log_function) {
ssh_set_log_callback(ssh_legacy_log_callback);
ssh_set_log_userdata(session);
}
/* LEGACY */
if (ssh_get_log_callback() == NULL && cb->log_function) {
ssh_set_log_callback(ssh_legacy_log_callback);
ssh_set_log_userdata(session);
}
return 0;
return 0;
}
static int ssh_add_set_channel_callbacks(ssh_channel channel,
@@ -84,11 +84,11 @@ static int ssh_add_set_channel_callbacks(ssh_channel channel,
int rc;
if (channel == NULL || cb == NULL) {
return SSH_ERROR;
return SSH_ERROR;
}
session = channel->session;
if (!is_callback_valid(session, cb)) {
if (is_callback_valid(session, cb)) {
ssh_set_error(session,
SSH_FATAL,
"Invalid callback passed in (badly initialized)");
@@ -96,7 +96,7 @@ static int ssh_add_set_channel_callbacks(ssh_channel channel,
};
if (channel->callbacks == NULL) {
channel->callbacks = ssh_list_new();
if (channel->callbacks == NULL) {
if (channel->callbacks == NULL){
ssh_set_error_oom(session);
return SSH_ERROR;
}
@@ -124,12 +124,12 @@ int ssh_remove_channel_callbacks(ssh_channel channel, ssh_channel_callbacks cb)
{
struct ssh_iterator *it = NULL;
if (channel == NULL || channel->callbacks == NULL) {
if (channel == NULL || channel->callbacks == NULL){
return SSH_ERROR;
}
it = ssh_list_find(channel->callbacks, cb);
if (it == NULL) {
if (it == NULL){
return SSH_ERROR;
}
@@ -138,19 +138,19 @@ int ssh_remove_channel_callbacks(ssh_channel channel, ssh_channel_callbacks cb)
return SSH_OK;
}
int ssh_set_server_callbacks(ssh_session session, ssh_server_callbacks cb)
{
if (session == NULL || cb == NULL) {
return SSH_ERROR;
}
if (!is_callback_valid(session, cb)) {
int ssh_set_server_callbacks(ssh_session session, ssh_server_callbacks cb){
if (session == NULL || cb == NULL) {
return SSH_ERROR;
}
if (is_callback_valid(session, cb)) {
ssh_set_error(session,
SSH_FATAL,
"Invalid callback passed in (badly initialized)");
return SSH_ERROR;
};
session->server_callbacks = cb;
session->server_callbacks = cb;
return 0;
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -46,9 +46,6 @@
#include "libssh/misc.h"
#include "libssh/pki.h"
#include "libssh/kex.h"
#ifdef HAVE_MLKEM
#include "libssh/mlkem768.h"
#endif
#ifndef _WIN32
#ifdef HAVE_PTHREAD
@@ -229,7 +226,7 @@ int ssh_send_banner(ssh_session session, int server)
terminator);
}
rc = ssh_socket_write(session->socket, buffer, (uint32_t)strlen(buffer));
rc = ssh_socket_write(session->socket, buffer, strlen(buffer));
if (rc == SSH_ERROR) {
goto end;
}
@@ -238,8 +235,8 @@ int ssh_send_banner(ssh_session session, int server)
ssh_pcap_context_write(session->pcap_ctx,
SSH_PCAP_DIR_OUT,
buffer,
(uint32_t)strlen(buffer),
(uint32_t)strlen(buffer));
strlen(buffer),
strlen(buffer));
}
#endif
@@ -257,58 +254,45 @@ end:
*/
int dh_handshake(ssh_session session)
{
int rc = SSH_AGAIN;
int rc = SSH_AGAIN;
SSH_LOG(SSH_LOG_TRACE,
"dh_handshake_state = %d, kex_type = %d",
session->dh_handshake_state,
session->next_crypto->kex_type);
SSH_LOG(SSH_LOG_TRACE, "dh_handshake_state = %d, kex_type = %d",
session->dh_handshake_state, session->next_crypto->kex_type);
switch (session->dh_handshake_state) {
switch (session->dh_handshake_state) {
case DH_STATE_INIT:
switch (session->next_crypto->kex_type) {
switch(session->next_crypto->kex_type){
case SSH_KEX_DH_GROUP1_SHA1:
case SSH_KEX_DH_GROUP14_SHA1:
case SSH_KEX_DH_GROUP14_SHA256:
case SSH_KEX_DH_GROUP16_SHA512:
case SSH_KEX_DH_GROUP18_SHA512:
rc = ssh_client_dh_init(session);
break;
rc = ssh_client_dh_init(session);
break;
#ifdef WITH_GEX
case SSH_KEX_DH_GEX_SHA1:
case SSH_KEX_DH_GEX_SHA256:
rc = ssh_client_dhgex_init(session);
break;
rc = ssh_client_dhgex_init(session);
break;
#endif /* WITH_GEX */
#ifdef HAVE_ECDH
case SSH_KEX_ECDH_SHA2_NISTP256:
case SSH_KEX_ECDH_SHA2_NISTP384:
case SSH_KEX_ECDH_SHA2_NISTP521:
rc = ssh_client_ecdh_init(session);
break;
rc = ssh_client_ecdh_init(session);
break;
#endif
#ifdef HAVE_CURVE25519
case SSH_KEX_CURVE25519_SHA256:
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
rc = ssh_client_curve25519_init(session);
break;
#endif
#ifdef HAVE_SNTRUP761
case SSH_KEX_SNTRUP761X25519_SHA512:
case SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM:
rc = ssh_client_sntrup761x25519_init(session);
break;
#endif
#ifdef HAVE_MLKEM
case SSH_KEX_MLKEM768X25519_SHA256:
rc = ssh_client_mlkem768x25519_init(session);
break;
rc = ssh_client_curve25519_init(session);
break;
#endif
default:
rc = SSH_ERROR;
}
rc = SSH_ERROR;
}
break;
break;
case DH_STATE_INIT_SENT:
/* wait until ssh_packet_dh_reply is called */
break;
@@ -316,17 +300,15 @@ int dh_handshake(ssh_session session)
/* wait until ssh_packet_newkeys is called */
break;
case DH_STATE_FINISHED:
return SSH_OK;
return SSH_OK;
default:
ssh_set_error(session,
SSH_FATAL,
"Invalid state in dh_handshake(): %d",
session->dh_handshake_state);
ssh_set_error(session, SSH_FATAL, "Invalid state in dh_handshake(): %d",
session->dh_handshake_state);
return SSH_ERROR;
}
return SSH_ERROR;
}
return rc;
return rc;
}
static int ssh_service_request_termination(void *s)
@@ -611,7 +593,8 @@ int ssh_connect(ssh_session session)
if (session->opts.fd != SSH_INVALID_SOCKET) {
session->session_state = SSH_SESSION_STATE_SOCKET_CONNECTED;
ret = ssh_socket_set_fd(session->socket, session->opts.fd);
ssh_socket_set_fd(session->socket, session->opts.fd);
ret = SSH_OK;
#ifndef _WIN32
#ifdef HAVE_PTHREAD
} else if (ssh_libssh_proxy_jumps() &&
@@ -853,7 +836,6 @@ error:
session->opts.fd = SSH_INVALID_SOCKET;
session->session_state = SSH_SESSION_STATE_DISCONNECTED;
session->pending_call_state = SSH_PENDING_CALL_NONE;
session->packet_state = PACKET_STATE_INIT;
while ((it = ssh_list_get_iterator(session->channels)) != NULL) {
ssh_channel_do_free(ssh_iterator_value(ssh_channel, it));

View File

@@ -153,7 +153,6 @@ static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
{ "tunneldevice", SOC_NA},
{ "xauthlocation", SOC_NA},
{ "pubkeyacceptedkeytypes", SOC_PUBKEYACCEPTEDKEYTYPES},
{ "requiredrsasize", SOC_REQUIRED_RSA_SIZE},
{ NULL, SOC_UNKNOWN }
};
@@ -1440,12 +1439,6 @@ ssh_config_parse_line(ssh_session session,
ssh_options_set(session, SSH_OPTIONS_CERTIFICATE, p);
}
break;
case SOC_REQUIRED_RSA_SIZE:
l = ssh_config_get_long(&s, -1);
if (l >= 0 && *parsing) {
ssh_options_set(session, SSH_OPTIONS_RSA_MIN_SIZE, &l);
}
break;
default:
ssh_set_error(session, SSH_FATAL, "ERROR - unimplemented opcode: %d",
opcode);
@@ -1458,32 +1451,6 @@ ssh_config_parse_line(ssh_session session,
return 0;
}
/* @brief Parse configuration from a file pointer
*
* @params[in] session The ssh session
* @params[in] fp A valid file pointer
* @params[in] global Whether the config is global or not
*
* @returns 0 on successful parsing the configuration file, -1 on error
*/
int ssh_config_parse(ssh_session session, FILE *fp, bool global)
{
char line[MAX_LINE_SIZE] = {0};
unsigned int count = 0;
int parsing, rv;
parsing = 1;
while (fgets(line, sizeof(line), fp)) {
count++;
rv = ssh_config_parse_line(session, line, count, &parsing, 0, global);
if (rv < 0) {
return -1;
}
}
return 0;
}
/* @brief Parse configuration file and set the options to the given session
*
* @params[in] session The ssh session
@@ -1493,32 +1460,36 @@ int ssh_config_parse(ssh_session session, FILE *fp, bool global)
*/
int ssh_config_parse_file(ssh_session session, const char *filename)
{
FILE *fp = NULL;
int rv;
char line[MAX_LINE_SIZE] = {0};
unsigned int count = 0;
FILE *f = NULL;
int parsing, rv;
bool global = 0;
fp = fopen(filename, "r");
if (fp == NULL) {
f = fopen(filename, "r");
if (f == NULL) {
return 0;
}
rv = strcmp(filename, GLOBAL_CLIENT_CONFIG);
#ifdef USR_GLOBAL_CLIENT_CONFIG
if (rv != 0) {
rv = strcmp(filename, USR_GLOBAL_CLIENT_CONFIG);
}
#endif
if (rv == 0) {
global = true;
}
SSH_LOG(SSH_LOG_PACKET, "Reading configuration data from %s", filename);
rv = ssh_config_parse(session, fp, global);
parsing = 1;
while (fgets(line, sizeof(line), f)) {
count++;
rv = ssh_config_parse_line(session, line, count, &parsing, 0, global);
if (rv < 0) {
fclose(f);
return -1;
}
}
fclose(fp);
return rv;
fclose(f);
return 0;
}
/* @brief Parse configuration string and set the options to the given session
@@ -1533,8 +1504,7 @@ int ssh_config_parse_string(ssh_session session, const char *input)
{
char line[MAX_LINE_SIZE] = {0};
const char *c = input, *line_start = input;
unsigned int line_num = 0;
size_t line_len;
unsigned int line_num = 0, line_len;
int parsing, rv;
SSH_LOG(SSH_LOG_DEBUG, "Reading configuration data from string:");
@@ -1556,10 +1526,8 @@ int ssh_config_parse_string(ssh_session session, const char *input)
}
line_len = c - line_start;
if (line_len > MAX_LINE_SIZE - 1) {
SSH_LOG(SSH_LOG_TRACE,
"Line %u too long: %zu characters",
line_num,
line_len);
SSH_LOG(SSH_LOG_TRACE, "Line %u too long: %u characters",
line_num, line_len);
return SSH_ERROR;
}
memcpy(line, line_start, line_len);

View File

@@ -209,8 +209,7 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
bind_itr != NULL;
bind_itr = bind_itr->ai_next)
{
rc = bind(s, bind_itr->ai_addr, bind_itr->ai_addrlen);
if (rc < 0) {
if (bind(s, bind_itr->ai_addr, bind_itr->ai_addrlen) < 0) {
ssh_set_error(session, SSH_FATAL,
"Binding local address: %s",
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));

View File

@@ -166,7 +166,7 @@ int ssh_connector_set_out_channel(ssh_connector connector,
/* Fallback to default value for invalid flags */
if (!(flags & SSH_CONNECTOR_STDOUT) && !(flags & SSH_CONNECTOR_STDERR)) {
connector->out_flags = SSH_CONNECTOR_STDOUT;
connector->in_flags = SSH_CONNECTOR_STDOUT;
}
return ssh_add_channel_callbacks(channel, &connector->out_channel_cb);
@@ -264,17 +264,17 @@ static void ssh_connector_fd_in_cb(ssh_connector connector)
}
connector->in_available = 1; /* Don't poll on it */
return;
} else if (r > 0) {
} else if (r> 0) {
/* loop around ssh_channel_write in case our window reduced due to a race */
while (total != r){
if (connector->out_flags & SSH_CONNECTOR_STDOUT) {
w = ssh_channel_write(connector->out_channel,
buffer + total,
(uint32_t)(r - total));
r - total);
} else {
w = ssh_channel_write_stderr(connector->out_channel,
buffer + total,
(uint32_t)(r - total));
r - total);
}
if (w == SSH_ERROR) {
return;
@@ -294,7 +294,7 @@ static void ssh_connector_fd_in_cb(ssh_connector connector)
while (total < r) {
w = ssh_connector_fd_write(connector,
buffer + total,
(uint32_t)(r - total));
r - total);
if (w < 0) {
ssh_connector_except(connector, connector->out_fd);
return;
@@ -340,9 +340,8 @@ ssh_connector_fd_out_cb(ssh_connector connector)
} else if (r > 0) {
/* loop around write in case the write blocks even for CHUNKSIZE bytes */
while (total != r) {
w = ssh_connector_fd_write(connector,
buffer + total,
(uint32_t)(r - total));
w = ssh_connector_fd_write(connector, buffer + total,
r - total);
if (w < 0) {
ssh_connector_except(connector, connector->out_fd);
return;
@@ -382,13 +381,15 @@ ssh_connector_fd_out_cb(ssh_connector connector)
*
* @returns 0
*/
static int ssh_connector_fd_cb(UNUSED_PARAM(ssh_poll_handle p),
static int ssh_connector_fd_cb(ssh_poll_handle p,
socket_t fd,
int revents,
void *userdata)
{
ssh_connector connector = userdata;
(void)p;
if (revents & POLLERR) {
ssh_connector_except(connector, fd);
} else if((revents & (POLLIN|POLLHUP)) && fd == connector->in_fd) {
@@ -407,10 +408,6 @@ static int ssh_connector_fd_cb(UNUSED_PARAM(ssh_poll_handle p),
*
* @brief Callback called when data is received on channel.
*
* @param[in] session The SSH session
*
* @param[in] channel The channel data came from
*
* @param[in] data Pointer to the data
*
* @param[in] len Length of data
@@ -422,7 +419,7 @@ static int ssh_connector_fd_cb(UNUSED_PARAM(ssh_poll_handle p),
* @returns Amount of data bytes consumed
*/
static int ssh_connector_channel_data_cb(ssh_session session,
UNUSED_PARAM(ssh_channel channel),
ssh_channel channel,
void *data,
uint32_t len,
int is_stderr,
@@ -432,11 +429,11 @@ static int ssh_connector_channel_data_cb(ssh_session session,
int w;
uint32_t window;
SSH_LOG(SSH_LOG_TRACE,
"Received data (%" PRIu32 ") on channel (%" PRIu32 ":%" PRIu32 ")",
len,
channel->local_channel,
channel->remote_channel);
(void) session;
(void) channel;
(void) is_stderr;
SSH_LOG(SSH_LOG_TRACE,"connector data on channel");
if (is_stderr && !(connector->in_flags & SSH_CONNECTOR_STDERR)) {
/* ignore stderr */
@@ -450,7 +447,6 @@ static int ssh_connector_channel_data_cb(ssh_session session,
}
if (connector->out_wontblock) {
SSH_LOG(SSH_LOG_TRACE, "Writing won't block");
if (connector->out_channel != NULL) {
uint32_t window_len;
@@ -480,11 +476,9 @@ static int ssh_connector_channel_data_cb(ssh_session session,
ssh_connector_except_channel(connector, connector->out_channel);
}
} else if (connector->out_fd != SSH_INVALID_SOCKET) {
ssize_t ws = ssh_connector_fd_write(connector, data, len);
if (ws < 0) {
w = ssh_connector_fd_write(connector, data, len);
if (w < 0)
ssh_connector_except(connector, connector->out_fd);
}
w = (int)ws;
} else {
ssh_set_error(session, SSH_FATAL, "output socket or channel closed");
return SSH_ERROR;
@@ -499,7 +493,6 @@ static int ssh_connector_channel_data_cb(ssh_session session,
return w;
} else {
SSH_LOG(SSH_LOG_TRACE, "Writing would block: wait?");
connector->in_available = 1;
return 0;
@@ -517,11 +510,10 @@ static int ssh_connector_channel_data_cb(ssh_session session,
*
* @returns Amount of data bytes consumed
*/
static int
ssh_connector_channel_write_wontblock_cb(ssh_session session,
UNUSED_PARAM(ssh_channel channel),
uint32_t bytes,
void *userdata)
static int ssh_connector_channel_write_wontblock_cb(ssh_session session,
ssh_channel channel,
uint32_t bytes,
void *userdata)
{
ssh_connector connector = userdata;
uint8_t buffer[CHUNKSIZE];
@@ -529,12 +521,7 @@ ssh_connector_channel_write_wontblock_cb(ssh_session session,
(void) channel;
SSH_LOG(SSH_LOG_TRACE,
"Write won't block (%" PRIu32 ") on channel (%" PRIu32 ":%" PRIu32 ")",
bytes,
channel->local_channel,
channel->remote_channel);
SSH_LOG(SSH_LOG_TRACE, "Channel write won't block");
if (connector->in_available) {
if (connector->in_channel != NULL) {
uint32_t len = MIN(CHUNKSIZE, bytes);
@@ -545,7 +532,7 @@ ssh_connector_channel_write_wontblock_cb(ssh_session session,
0);
if (r == SSH_ERROR) {
ssh_connector_except_channel(connector, connector->in_channel);
} else if (r == 0 && ssh_channel_is_eof(connector->in_channel)) {
} else if(r == 0 && ssh_channel_is_eof(connector->in_channel)){
ssh_channel_send_eof(connector->out_channel);
} else if (r > 0) {
w = ssh_channel_write(connector->out_channel, buffer, r);
@@ -616,15 +603,15 @@ int ssh_connector_set_event(ssh_connector connector, ssh_event event)
}
}
if (connector->in_channel != NULL) {
ssh_session session = ssh_channel_get_session(connector->in_channel);
rc = ssh_event_add_session(event, session);
rc = ssh_event_add_session(event,
ssh_channel_get_session(connector->in_channel));
if (rc != SSH_OK)
goto error;
if (ssh_channel_poll_timeout(connector->in_channel, 0, 0) > 0){
connector->in_available = 1;
}
}
if (connector->out_channel != NULL) {
if(connector->out_channel != NULL) {
ssh_session session = ssh_channel_get_session(connector->out_channel);
rc = ssh_event_add_session(event, session);

View File

@@ -26,43 +26,119 @@
#include "libssh/curve25519.h"
#ifdef HAVE_CURVE25519
#include "libssh/bignum.h"
#ifdef WITH_NACL
#include "nacl/crypto_scalarmult_curve25519.h"
#endif
#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"
#include "libssh/priv.h"
#include "libssh/session.h"
#include "libssh/ssh2.h"
#include "libssh/bignum.h"
#ifdef HAVE_LIBCRYPTO
#include <openssl/err.h>
#endif
static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply);
static ssh_packet_callback dh_client_callbacks[] = {
ssh_packet_client_curve25519_reply,
ssh_packet_client_curve25519_reply
};
static struct ssh_packet_callbacks_struct ssh_curve25519_client_callbacks = {
.start = SSH2_MSG_KEX_ECDH_REPLY,
.n_callbacks = 1,
.callbacks = dh_client_callbacks,
.user = NULL,
.user = NULL
};
int ssh_curve25519_create_k(ssh_session session, ssh_curve25519_pubkey k)
static int ssh_curve25519_init(ssh_session session)
{
int rc;
#ifdef HAVE_LIBCRYPTO
EVP_PKEY_CTX *pctx = NULL;
EVP_PKEY *pkey = NULL;
size_t pubkey_len = CURVE25519_PUBKEY_SIZE;
size_t pkey_len = CURVE25519_PRIVKEY_SIZE;
#ifdef DEBUG_CRYPTO
ssh_log_hexdump("Session server cookie",
session->next_crypto->server_kex.cookie,
16);
ssh_log_hexdump("Session client cookie",
session->next_crypto->client_kex.cookie,
16);
#endif
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL);
if (pctx == NULL) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to initialize X25519 context: %s",
ERR_error_string(ERR_get_error(), NULL));
return SSH_ERROR;
}
rc = curve25519_do_create_k(session, k);
return rc;
rc = EVP_PKEY_keygen_init(pctx);
if (rc != 1) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to initialize X25519 keygen: %s",
ERR_error_string(ERR_get_error(), NULL));
EVP_PKEY_CTX_free(pctx);
return SSH_ERROR;
}
rc = EVP_PKEY_keygen(pctx, &pkey);
EVP_PKEY_CTX_free(pctx);
if (rc != 1) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to generate X25519 keys: %s",
ERR_error_string(ERR_get_error(), NULL));
return SSH_ERROR;
}
if (session->server) {
rc = EVP_PKEY_get_raw_public_key(pkey,
session->next_crypto->curve25519_server_pubkey,
&pubkey_len);
} else {
rc = EVP_PKEY_get_raw_public_key(pkey,
session->next_crypto->curve25519_client_pubkey,
&pubkey_len);
}
if (rc != 1) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to get X25519 raw public key: %s",
ERR_error_string(ERR_get_error(), NULL));
EVP_PKEY_free(pkey);
return SSH_ERROR;
}
rc = EVP_PKEY_get_raw_private_key(pkey,
session->next_crypto->curve25519_privkey,
&pkey_len);
if (rc != 1) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to get X25519 raw private key: %s",
ERR_error_string(ERR_get_error(), NULL));
EVP_PKEY_free(pkey);
return SSH_ERROR;
}
EVP_PKEY_free(pkey);
#else
rc = ssh_get_random(session->next_crypto->curve25519_privkey,
CURVE25519_PRIVKEY_SIZE, 1);
if (rc != 1) {
ssh_set_error(session, SSH_FATAL, "PRNG error");
return SSH_ERROR;
}
if (session->server) {
crypto_scalarmult_base(session->next_crypto->curve25519_server_pubkey,
session->next_crypto->curve25519_privkey);
} else {
crypto_scalarmult_base(session->next_crypto->curve25519_client_pubkey,
session->next_crypto->curve25519_privkey);
}
#endif /* HAVE_LIBCRYPTO */
return SSH_OK;
}
/** @internal
@@ -104,120 +180,193 @@ void ssh_client_curve25519_remove_callbacks(ssh_session session)
static int ssh_curve25519_build_k(ssh_session session)
{
ssh_curve25519_pubkey k;
int rc;
rc = ssh_curve25519_create_k(session, k);
if (rc != SSH_OK) {
return rc;
#ifdef HAVE_LIBCRYPTO
EVP_PKEY_CTX *pctx = NULL;
EVP_PKEY *pkey = NULL, *pubkey = NULL;
size_t shared_key_len = sizeof(k);
int rc, ret = SSH_ERROR;
pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL,
session->next_crypto->curve25519_privkey,
CURVE25519_PRIVKEY_SIZE);
if (pkey == NULL) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to create X25519 EVP_PKEY: %s",
ERR_error_string(ERR_get_error(), NULL));
return SSH_ERROR;
}
bignum_bin2bn(k,
CURVE25519_PUBKEY_SIZE,
&session->next_crypto->shared_secret);
pctx = EVP_PKEY_CTX_new(pkey, NULL);
if (pctx == NULL) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to initialize X25519 context: %s",
ERR_error_string(ERR_get_error(), NULL));
goto out;
}
rc = EVP_PKEY_derive_init(pctx);
if (rc != 1) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to initialize X25519 key derivation: %s",
ERR_error_string(ERR_get_error(), NULL));
goto out;
}
if (session->server) {
pubkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL,
session->next_crypto->curve25519_client_pubkey,
CURVE25519_PUBKEY_SIZE);
} else {
pubkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL,
session->next_crypto->curve25519_server_pubkey,
CURVE25519_PUBKEY_SIZE);
}
if (pubkey == NULL) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to create X25519 public key EVP_PKEY: %s",
ERR_error_string(ERR_get_error(), NULL));
goto out;
}
rc = EVP_PKEY_derive_set_peer(pctx, pubkey);
if (rc != 1) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to set peer X25519 public key: %s",
ERR_error_string(ERR_get_error(), NULL));
goto out;
}
rc = EVP_PKEY_derive(pctx, k, &shared_key_len);
if (rc != 1) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to derive X25519 shared secret: %s",
ERR_error_string(ERR_get_error(), NULL));
goto out;
}
ret = SSH_OK;
out:
EVP_PKEY_free(pkey);
EVP_PKEY_free(pubkey);
EVP_PKEY_CTX_free(pctx);
if (ret == SSH_ERROR) {
return ret;
}
#else
if (session->server) {
crypto_scalarmult(k, session->next_crypto->curve25519_privkey,
session->next_crypto->curve25519_client_pubkey);
} else {
crypto_scalarmult(k, session->next_crypto->curve25519_privkey,
session->next_crypto->curve25519_server_pubkey);
}
#endif /* HAVE_LIBCRYPTO */
bignum_bin2bn(k, CURVE25519_PUBKEY_SIZE, &session->next_crypto->shared_secret);
if (session->next_crypto->shared_secret == NULL) {
return SSH_ERROR;
}
#ifdef DEBUG_CRYPTO
ssh_log_hexdump("Session server cookie",
session->next_crypto->server_kex.cookie, 16);
ssh_log_hexdump("Session client cookie",
session->next_crypto->client_kex.cookie, 16);
ssh_print_bignum("Shared secret key", session->next_crypto->shared_secret);
#endif
return SSH_OK;
return 0;
}
/** @internal
* @brief parses a SSH_MSG_KEX_ECDH_REPLY packet and sends back
* a SSH_MSG_NEWKEYS
*/
static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply)
{
ssh_string q_s_string = NULL;
ssh_string pubkey_blob = NULL;
ssh_string signature = NULL;
int rc;
(void)type;
(void)user;
static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply){
ssh_string q_s_string = NULL;
ssh_string pubkey_blob = NULL;
ssh_string signature = NULL;
int rc;
(void)type;
(void)user;
ssh_client_curve25519_remove_callbacks(session);
ssh_client_curve25519_remove_callbacks(session);
pubkey_blob = ssh_buffer_get_ssh_string(packet);
if (pubkey_blob == NULL) {
ssh_set_error(session, SSH_FATAL, "No public key in packet");
goto error;
}
pubkey_blob = ssh_buffer_get_ssh_string(packet);
if (pubkey_blob == NULL) {
ssh_set_error(session,SSH_FATAL, "No public key in packet");
goto error;
}
rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob);
SSH_STRING_FREE(pubkey_blob);
if (rc != 0) {
ssh_set_error(session, SSH_FATAL, "Failed to import next public key");
goto error;
}
rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob);
SSH_STRING_FREE(pubkey_blob);
if (rc != 0) {
ssh_set_error(session,
SSH_FATAL,
"Failed to import next public key");
goto error;
}
q_s_string = ssh_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: %zu",
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);
SSH_STRING_FREE(q_s_string);
q_s_string = ssh_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",
(int)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);
SSH_STRING_FREE(q_s_string);
signature = ssh_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;
}
signature = ssh_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 */
rc = ssh_packet_send_newkeys(session);
if (rc == SSH_ERROR) {
goto error;
}
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
/* Send the MSG_NEWKEYS */
rc = ssh_packet_send_newkeys(session);
if (rc == SSH_ERROR) {
goto error;
}
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
return SSH_PACKET_USED;
return SSH_PACKET_USED;
error:
session->session_state = SSH_SESSION_STATE_ERROR;
return SSH_PACKET_USED;
session->session_state=SSH_SESSION_STATE_ERROR;
return SSH_PACKET_USED;
}
#ifdef WITH_SERVER
static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init);
static ssh_packet_callback dh_server_callbacks[] = {
ssh_packet_server_curve25519_init,
static ssh_packet_callback dh_server_callbacks[]= {
ssh_packet_server_curve25519_init
};
static struct ssh_packet_callbacks_struct ssh_curve25519_server_callbacks = {
.start = SSH2_MSG_KEX_ECDH_INIT,
.n_callbacks = 1,
.callbacks = dh_server_callbacks,
.user = NULL,
.user = NULL
};
/** @internal
* @brief sets up the curve25519-sha256@libssh.org kex callbacks
*/
void ssh_server_curve25519_init(ssh_session session)
{
void ssh_server_curve25519_init(ssh_session session){
/* register the packet callbacks */
ssh_packet_set_callbacks(session, &ssh_curve25519_server_callbacks);
}
@@ -225,8 +374,7 @@ void ssh_server_curve25519_init(ssh_session session)
/** @brief Parse a SSH_MSG_KEXDH_INIT packet (server) and send a
* SSH_MSG_KEXDH_REPLY
*/
static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init)
{
static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
/* ECDH keys */
ssh_string q_c_string = NULL;
ssh_string q_s_string = NULL;
@@ -245,10 +393,10 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init)
/* Extract the client pubkey from the init packet */
q_c_string = ssh_buffer_get_ssh_string(packet);
if (q_c_string == NULL) {
ssh_set_error(session, SSH_FATAL, "No Q_C ECC point in packet");
ssh_set_error(session,SSH_FATAL, "No Q_C ECC point in packet");
goto error;
}
if (ssh_string_len(q_c_string) != CURVE25519_PUBKEY_SIZE) {
if (ssh_string_len(q_c_string) != CURVE25519_PUBKEY_SIZE){
ssh_set_error(session,
SSH_FATAL,
"Incorrect size for server Curve25519 public key: %zu",
@@ -257,8 +405,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init)
}
memcpy(session->next_crypto->curve25519_client_pubkey,
ssh_string_data(q_c_string),
CURVE25519_PUBKEY_SIZE);
ssh_string_data(q_c_string), CURVE25519_PUBKEY_SIZE);
SSH_STRING_FREE(q_c_string);
/* Build server's key pair */
@@ -300,7 +447,8 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init)
}
/* add host's public key */
rc = ssh_buffer_add_ssh_string(session->out_buffer, server_pubkey_blob);
rc = ssh_buffer_add_ssh_string(session->out_buffer,
server_pubkey_blob);
SSH_STRING_FREE(server_pubkey_blob);
if (rc < 0) {
ssh_set_error_oom(session);
@@ -361,7 +509,7 @@ error:
SSH_STRING_FREE(q_c_string);
SSH_STRING_FREE(q_s_string);
ssh_buffer_reinit(session->out_buffer);
session->session_state = SSH_SESSION_STATE_ERROR;
session->session_state=SSH_SESSION_STATE_ERROR;
return SSH_PACKET_USED;
}

View File

@@ -1,164 +0,0 @@
/*
* curve25519_crypto.c - Curve25519 ECDH functions for key exchange (OpenSSL)
*
* This file is part of the SSH Library
*
* Copyright (c) 2013-2023 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"
#include "libssh/crypto.h"
#include "libssh/priv.h"
#include "libssh/session.h"
#include <openssl/err.h>
#include <openssl/evp.h>
int ssh_curve25519_init(ssh_session session)
{
ssh_curve25519_pubkey *pubkey_loc = NULL;
EVP_PKEY_CTX *pctx = NULL;
EVP_PKEY *pkey = NULL;
size_t pubkey_len = CURVE25519_PUBKEY_SIZE;
int rc;
if (session->server) {
pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
} else {
pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
}
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL);
if (pctx == NULL) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to initialize X25519 context: %s",
ERR_error_string(ERR_get_error(), NULL));
return SSH_ERROR;
}
rc = EVP_PKEY_keygen_init(pctx);
if (rc != 1) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to initialize X25519 keygen: %s",
ERR_error_string(ERR_get_error(), NULL));
EVP_PKEY_CTX_free(pctx);
return SSH_ERROR;
}
rc = EVP_PKEY_keygen(pctx, &pkey);
EVP_PKEY_CTX_free(pctx);
if (rc != 1) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to generate X25519 keys: %s",
ERR_error_string(ERR_get_error(), NULL));
return SSH_ERROR;
}
rc = EVP_PKEY_get_raw_public_key(pkey, *pubkey_loc, &pubkey_len);
if (rc != 1) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to get X25519 raw public key: %s",
ERR_error_string(ERR_get_error(), NULL));
EVP_PKEY_free(pkey);
return SSH_ERROR;
}
/* Free any previously allocated privkey */
if (session->next_crypto->curve25519_privkey != NULL) {
EVP_PKEY_free(session->next_crypto->curve25519_privkey);
session->next_crypto->curve25519_privkey = NULL;
}
session->next_crypto->curve25519_privkey = pkey;
pkey = NULL;
return SSH_OK;
}
int curve25519_do_create_k(ssh_session session, ssh_curve25519_pubkey k)
{
ssh_curve25519_pubkey *peer_pubkey_loc = NULL;
int rc, ret = SSH_ERROR;
EVP_PKEY_CTX *pctx = NULL;
EVP_PKEY *pkey = NULL, *pubkey = NULL;
size_t shared_key_len = CURVE25519_PUBKEY_SIZE;
if (session->server) {
peer_pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
} else {
peer_pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
}
pkey = session->next_crypto->curve25519_privkey;
if (pkey == NULL) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to create X25519 EVP_PKEY: %s",
ERR_error_string(ERR_get_error(), NULL));
return SSH_ERROR;
}
pctx = EVP_PKEY_CTX_new(pkey, NULL);
if (pctx == NULL) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to initialize X25519 context: %s",
ERR_error_string(ERR_get_error(), NULL));
goto out;
}
rc = EVP_PKEY_derive_init(pctx);
if (rc != 1) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to initialize X25519 key derivation: %s",
ERR_error_string(ERR_get_error(), NULL));
goto out;
}
pubkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519,
NULL,
*peer_pubkey_loc,
CURVE25519_PUBKEY_SIZE);
if (pubkey == NULL) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to create X25519 public key EVP_PKEY: %s",
ERR_error_string(ERR_get_error(), NULL));
goto out;
}
rc = EVP_PKEY_derive_set_peer(pctx, pubkey);
if (rc != 1) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to set peer X25519 public key: %s",
ERR_error_string(ERR_get_error(), NULL));
goto out;
}
rc = EVP_PKEY_derive(pctx, k, &shared_key_len);
if (rc != 1) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to derive X25519 shared secret: %s",
ERR_error_string(ERR_get_error(), NULL));
goto out;
}
ret = SSH_OK;
out:
EVP_PKEY_free(pubkey);
EVP_PKEY_CTX_free(pctx);
return ret;
}

View File

@@ -1,73 +0,0 @@
/*
* curve25519_fallback.c - Curve25519 ECDH functions for key exchange
*
* This file is part of the SSH Library
*
* Copyright (c) 2013-2023 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"
#include "libssh/crypto.h"
#include "libssh/priv.h"
#include "libssh/session.h"
#ifdef WITH_NACL
#include "nacl/crypto_scalarmult_curve25519.h"
#endif
int ssh_curve25519_init(ssh_session session)
{
ssh_curve25519_pubkey *pubkey_loc = NULL;
int rc;
if (session->server) {
pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
} else {
pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
}
rc = ssh_get_random(session->next_crypto->curve25519_privkey,
CURVE25519_PRIVKEY_SIZE,
1);
if (rc != 1) {
ssh_set_error(session, SSH_FATAL, "PRNG error");
return SSH_ERROR;
}
crypto_scalarmult_base(*pubkey_loc,
session->next_crypto->curve25519_privkey);
return SSH_OK;
}
int curve25519_do_create_k(ssh_session session, ssh_curve25519_pubkey k)
{
ssh_curve25519_pubkey *peer_pubkey_loc = NULL;
if (session->server) {
peer_pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
} else {
peer_pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
}
crypto_scalarmult(k,
session->next_crypto->curve25519_privkey,
*peer_pubkey_loc);
return SSH_OK;
}

View File

@@ -1,205 +0,0 @@
/*
* curve25519_gcrypt.c - Curve25519 ECDH functions for key exchange (Gcrypt)
*
* This file is part of the SSH Library
*
* Copyright (c) 2013-2023 by Aris Adamantiadis <aris@badcode.be>
* Copyright (c) 2025 Praneeth Sarode <praneethsarode@gmail.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, 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"
#include "libssh/buffer.h"
#include "libssh/crypto.h"
#include "libssh/priv.h"
#include "libssh/session.h"
#include <gcrypt.h>
int ssh_curve25519_init(ssh_session session)
{
ssh_curve25519_pubkey *pubkey_loc = NULL;
gcry_error_t gcry_err;
gcry_sexp_t param = NULL, keypair_sexp = NULL;
ssh_string pubkey = NULL;
const char *pubkey_data = NULL;
int ret = SSH_ERROR;
if (session->server) {
pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
} else {
pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
}
gcry_err =
gcry_sexp_build(&param, NULL, "(genkey (ecdh (curve Curve25519)))");
if (gcry_err != GPG_ERR_NO_ERROR) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to create keypair sexp: %s",
gcry_strerror(gcry_err));
goto out;
}
gcry_err = gcry_pk_genkey(&keypair_sexp, param);
if (gcry_err != GPG_ERR_NO_ERROR) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to generate keypair: %s",
gcry_strerror(gcry_err));
goto out;
}
/* Extract the public key */
pubkey = ssh_sexp_extract_mpi(keypair_sexp,
"q",
GCRYMPI_FMT_USG,
GCRYMPI_FMT_STD);
if (pubkey == NULL) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to extract public key: %s",
gcry_strerror(gcry_err));
goto out;
}
/* Store the public key in the session */
/* The first byte should be 0x40 indicating that the point is compressed, so
* we skip storing it */
pubkey_data = (char *)ssh_string_data(pubkey);
if (ssh_string_len(pubkey) != CURVE25519_PUBKEY_SIZE + 1 ||
pubkey_data[0] != 0x40) {
SSH_LOG(SSH_LOG_TRACE,
"Invalid public key with length: %zu",
ssh_string_len(pubkey));
goto out;
}
memcpy(*pubkey_loc, pubkey_data + 1, CURVE25519_PUBKEY_SIZE);
/* Free any previously allocated privkey */
if (session->next_crypto->curve25519_privkey != NULL) {
gcry_sexp_release(session->next_crypto->curve25519_privkey);
session->next_crypto->curve25519_privkey = NULL;
}
/* Store the private key */
session->next_crypto->curve25519_privkey = keypair_sexp;
keypair_sexp = NULL;
ret = SSH_OK;
out:
ssh_string_burn(pubkey);
SSH_STRING_FREE(pubkey);
gcry_sexp_release(param);
gcry_sexp_release(keypair_sexp);
return ret;
}
int curve25519_do_create_k(ssh_session session, ssh_curve25519_pubkey k)
{
ssh_curve25519_pubkey *peer_pubkey_loc = NULL;
gcry_error_t gcry_err;
gcry_sexp_t pubkey_sexp = NULL, privkey_data_sexp = NULL,
result_sexp = NULL;
ssh_string shared_secret = NULL, privkey = NULL;
char *shared_secret_data = NULL;
int ret = SSH_ERROR;
if (session->server) {
peer_pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
} else {
peer_pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
}
gcry_err = gcry_sexp_build(
&pubkey_sexp,
NULL,
"(key-data(public-key (ecdh (curve Curve25519) (q %b))))",
CURVE25519_PUBKEY_SIZE,
*peer_pubkey_loc);
if (gcry_err != GPG_ERR_NO_ERROR) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to create peer public key sexp: %s",
gcry_strerror(gcry_err));
goto out;
}
privkey = ssh_sexp_extract_mpi(session->next_crypto->curve25519_privkey,
"d",
GCRYMPI_FMT_USG,
GCRYMPI_FMT_STD);
if (privkey == NULL) {
SSH_LOG(SSH_LOG_TRACE, "Failed to extract private key");
goto out;
}
gcry_err = gcry_sexp_build(&privkey_data_sexp,
NULL,
"(data(flags raw)(value %b))",
ssh_string_len(privkey),
ssh_string_data(privkey));
if (gcry_err != GPG_ERR_NO_ERROR) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to create private key sexp: %s",
gcry_strerror(gcry_err));
goto out;
}
gcry_err = gcry_pk_encrypt(&result_sexp, privkey_data_sexp, pubkey_sexp);
if (gcry_err != GPG_ERR_NO_ERROR) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to compute shared secret: %s",
gcry_strerror(gcry_err));
goto out;
}
shared_secret = ssh_sexp_extract_mpi(result_sexp,
"s",
GCRYMPI_FMT_USG,
GCRYMPI_FMT_USG);
if (shared_secret == NULL) {
SSH_LOG(SSH_LOG_TRACE, "Failed to extract shared secret");
goto out;
}
/* Copy the shared secret to the output buffer */
/* The first byte should be 0x40 indicating that it is a compressed point,
* so we skip it */
shared_secret_data = (char *)ssh_string_data(shared_secret);
if (ssh_string_len(shared_secret) != CURVE25519_PUBKEY_SIZE + 1 ||
shared_secret_data[0] != 0x40) {
SSH_LOG(SSH_LOG_TRACE,
"Invalid shared secret with length: %zu",
ssh_string_len(shared_secret));
goto out;
}
memcpy(k, shared_secret_data + 1, CURVE25519_PUBKEY_SIZE);
ret = SSH_OK;
gcry_sexp_release(session->next_crypto->curve25519_privkey);
session->next_crypto->curve25519_privkey = NULL;
out:
ssh_string_burn(shared_secret);
SSH_STRING_FREE(shared_secret);
ssh_string_burn(privkey);
SSH_STRING_FREE(privkey);
gcry_sexp_release(privkey_data_sexp);
gcry_sexp_release(pubkey_sexp);
gcry_sexp_release(result_sexp);
return ret;
}

View File

@@ -1,189 +0,0 @@
/*
* curve25519_mbedcrypto.c - Curve25519 ECDH functions for key exchange
* (MbedTLS)
*
* This file is part of the SSH Library
*
* Copyright (c) 2013-2023 by Aris Adamantiadis <aris@badcode.be>
* Copyright (c) 2025 Praneeth Sarode <praneethsarode@gmail.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, 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"
#include "libssh/crypto.h"
#include "libssh/priv.h"
#include "libssh/session.h"
#include "mbedcrypto-compat.h"
#include <mbedtls/ecdh.h>
#include <mbedtls/error.h>
int ssh_curve25519_init(ssh_session session)
{
ssh_curve25519_pubkey *pubkey_loc = NULL;
mbedtls_ecdh_context ecdh_ctx;
mbedtls_ecdh_params *ecdh_params = NULL;
mbedtls_ctr_drbg_context *ctr_drbg = NULL;
int rc, ret = SSH_ERROR;
char error_buf[128];
if (session->server) {
pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
} else {
pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
}
ctr_drbg = ssh_get_mbedtls_ctr_drbg_context();
mbedtls_ecdh_init(&ecdh_ctx);
rc = mbedtls_ecdh_setup(&ecdh_ctx, MBEDTLS_ECP_DP_CURVE25519);
if (rc != 0) {
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
SSH_LOG(SSH_LOG_TRACE, "Failed to setup X25519 context: %s", error_buf);
goto out;
}
ecdh_params = &MBEDTLS_ECDH_PARAMS(ecdh_ctx);
rc = mbedtls_ecdh_gen_public(&ecdh_params->MBEDTLS_ECDH_PRIVATE(grp),
&ecdh_params->MBEDTLS_ECDH_PRIVATE(d),
&ecdh_params->MBEDTLS_ECDH_PRIVATE(Q),
mbedtls_ctr_drbg_random,
ctr_drbg);
if (rc != 0) {
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
SSH_LOG(SSH_LOG_TRACE,
"Failed to generate X25519 keypair: %s",
error_buf);
goto out;
}
rc = mbedtls_mpi_write_binary_le(&ecdh_params->MBEDTLS_ECDH_PRIVATE(d),
session->next_crypto->curve25519_privkey,
CURVE25519_PRIVKEY_SIZE);
if (rc != 0) {
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
SSH_LOG(SSH_LOG_TRACE,
"Failed to write X25519 private key: %s",
error_buf);
goto out;
}
rc = mbedtls_mpi_write_binary_le(
&ecdh_params->MBEDTLS_ECDH_PRIVATE(Q).MBEDTLS_ECDH_PRIVATE(X),
*pubkey_loc,
CURVE25519_PUBKEY_SIZE);
if (rc != 0) {
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
SSH_LOG(SSH_LOG_TRACE,
"Failed to write X25519 public key: %s",
error_buf);
goto out;
}
ret = SSH_OK;
out:
mbedtls_ecdh_free(&ecdh_ctx);
return ret;
}
int curve25519_do_create_k(ssh_session session, ssh_curve25519_pubkey k)
{
ssh_curve25519_pubkey *peer_pubkey_loc = NULL;
int rc, ret = SSH_ERROR;
mbedtls_ecdh_context ecdh_ctx;
mbedtls_ecdh_params *ecdh_params = NULL;
mbedtls_ctr_drbg_context *ctr_drbg = NULL;
char error_buf[128];
if (session->server) {
peer_pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
} else {
peer_pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
}
ctr_drbg = ssh_get_mbedtls_ctr_drbg_context();
mbedtls_ecdh_init(&ecdh_ctx);
rc = mbedtls_ecdh_setup(&ecdh_ctx, MBEDTLS_ECP_DP_CURVE25519);
if (rc != 0) {
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
SSH_LOG(SSH_LOG_TRACE, "Failed to setup X25519 context: %s", error_buf);
goto out;
}
ecdh_params = &MBEDTLS_ECDH_PARAMS(ecdh_ctx);
rc = mbedtls_mpi_read_binary_le(&ecdh_params->MBEDTLS_ECDH_PRIVATE(d),
session->next_crypto->curve25519_privkey,
CURVE25519_PRIVKEY_SIZE);
if (rc != 0) {
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
SSH_LOG(SSH_LOG_TRACE, "Failed to read private key: %s", error_buf);
goto out;
}
rc = mbedtls_mpi_read_binary_le(
&ecdh_params->MBEDTLS_ECDH_PRIVATE(Qp).MBEDTLS_ECDH_PRIVATE(X),
*peer_pubkey_loc,
CURVE25519_PUBKEY_SIZE);
if (rc != 0) {
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
SSH_LOG(SSH_LOG_TRACE, "Failed to read peer public key: %s", error_buf);
goto out;
}
rc = mbedtls_mpi_lset(
&ecdh_params->MBEDTLS_ECDH_PRIVATE(Qp).MBEDTLS_ECDH_PRIVATE(Z),
1);
if (rc != 0) {
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
SSH_LOG(SSH_LOG_TRACE, "Failed to set Z coordinate: %s", error_buf);
goto out;
}
rc = mbedtls_ecdh_compute_shared(&ecdh_params->MBEDTLS_ECDH_PRIVATE(grp),
&ecdh_params->MBEDTLS_ECDH_PRIVATE(z),
&ecdh_params->MBEDTLS_ECDH_PRIVATE(Qp),
&ecdh_params->MBEDTLS_ECDH_PRIVATE(d),
mbedtls_ctr_drbg_random,
ctr_drbg);
if (rc != 0) {
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
SSH_LOG(SSH_LOG_TRACE,
"Failed to compute shared secret: %s",
error_buf);
goto out;
}
rc = mbedtls_mpi_write_binary_le(&ecdh_params->MBEDTLS_ECDH_PRIVATE(z),
k,
CURVE25519_PUBKEY_SIZE);
if (rc != 0) {
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
SSH_LOG(SSH_LOG_TRACE, "Failed to write shared secret: %s", error_buf);
goto out;
}
ret = SSH_OK;
out:
mbedtls_ecdh_free(&ecdh_ctx);
return ret;
}

View File

@@ -416,9 +416,6 @@ static int ssh_retrieve_dhgroup_file(FILE *moduli,
do {
firstbyte = getc(moduli);
} while(firstbyte != '\n' && firstbyte != EOF);
if (firstbyte == EOF) {
break;
}
continue;
}
if (firstbyte == EOF) {
@@ -442,9 +439,6 @@ static int ssh_retrieve_dhgroup_file(FILE *moduli,
do {
firstbyte = getc(moduli);
} while(firstbyte != '\n' && firstbyte != EOF);
if (firstbyte == EOF) {
break;
}
continue;
}

View File

@@ -407,11 +407,6 @@ int ssh_dh_init_common(struct ssh_crypto_struct *crypto)
struct dh_ctx *ctx = NULL;
int rc;
/* Cleanup any previously allocated dh_ctx */
if (crypto->dh_ctx != NULL) {
ssh_dh_cleanup(crypto);
}
ctx = calloc(1, sizeof(*ctx));
if (ctx == NULL) {
return SSH_ERROR;
@@ -597,7 +592,7 @@ int ssh_dh_compute_shared_secret(struct dh_ctx *dh_ctx, int local, int remote,
}
#endif /* OPENSSL_VERSION_NUMBER */
*dest = BN_bin2bn(kstring, (int)klen, NULL);
*dest = BN_bin2bn(kstring, klen, NULL);
if (*dest == NULL) {
rc = SSH_ERROR;
goto done;

View File

@@ -237,11 +237,6 @@ int ssh_dh_init_common(struct ssh_crypto_struct *crypto)
struct dh_ctx *ctx = NULL;
int rc;
/* Cleanup any previously allocated dh_ctx */
if (crypto->dh_ctx != NULL) {
ssh_dh_cleanup(crypto);
}
ctx = calloc(1, sizeof(*ctx));
if (ctx == NULL) {
return SSH_ERROR;

View File

@@ -191,17 +191,6 @@ static ssh_string ssh_ecdh_generate(ssh_session session)
#endif /* OPENSSL_VERSION_NUMBER */
return NULL;
}
/* Free any previously allocated privkey */
if (session->next_crypto->ecdh_privkey != NULL) {
#if OPENSSL_VERSION_NUMBER < 0x30000000L
EC_KEY_free(session->next_crypto->ecdh_privkey);
#else
EVP_PKEY_free(session->next_crypto->ecdh_privkey);
#endif
session->next_crypto->ecdh_privkey = NULL;
}
session->next_crypto->ecdh_privkey = key;
return pubkey_string;
}
@@ -230,7 +219,6 @@ int ssh_client_ecdh_init(ssh_session session)
return SSH_ERROR;
}
ssh_string_free(session->next_crypto->ecdh_client_pubkey);
session->next_crypto->ecdh_client_pubkey = client_pubkey;
/* register the packet callbacks */

View File

@@ -101,15 +101,8 @@ int ssh_client_ecdh_init(ssh_session session)
goto out;
}
/* Free any previously allocated privkey */
if (session->next_crypto->ecdh_privkey != NULL) {
gcry_sexp_release(session->next_crypto->ecdh_privkey);
session->next_crypto->ecdh_privkey = NULL;
}
session->next_crypto->ecdh_privkey = key;
key = NULL;
SSH_STRING_FREE(session->next_crypto->ecdh_client_pubkey);
session->next_crypto->ecdh_client_pubkey = client_pubkey;
client_pubkey = NULL;

View File

@@ -70,12 +70,6 @@ int ssh_client_ecdh_init(ssh_session session)
return SSH_ERROR;
}
/* Free any previously allocated privkey */
if (session->next_crypto->ecdh_privkey != NULL) {
mbedtls_ecp_keypair_free(session->next_crypto->ecdh_privkey);
SAFE_FREE(session->next_crypto->ecdh_privkey);
}
session->next_crypto->ecdh_privkey = malloc(sizeof(mbedtls_ecp_keypair));
if (session->next_crypto->ecdh_privkey == NULL) {
return SSH_ERROR;
@@ -116,7 +110,6 @@ int ssh_client_ecdh_init(ssh_session session)
goto out;
}
SSH_STRING_FREE(session->next_crypto->ecdh_client_pubkey);
session->next_crypto->ecdh_client_pubkey = client_pubkey;
client_pubkey = NULL;

1060
src/external/sntrup761.c vendored

File diff suppressed because it is too large Load Diff

View File

@@ -63,7 +63,7 @@ static int ssh_gets(const char *prompt, char *buf, size_t len, int verify)
fprintf(stdout, "%s", prompt);
}
fflush(stdout);
if (fgets(tmp, (int)len, stdin) == NULL) {
if (fgets(tmp, len, stdin) == NULL) {
free(tmp);
return 0;
}
@@ -87,7 +87,7 @@ static int ssh_gets(const char *prompt, char *buf, size_t len, int verify)
fprintf(stdout, "\nVerifying, please re-enter. %s", prompt);
fflush(stdout);
if (!fgets(key_string, (int)len, stdin)) {
if (! fgets(key_string, len, stdin)) {
explicit_bzero(key_string, len);
SAFE_FREE(key_string);
clearerr(stdin);

208
src/kex.c
View File

@@ -40,10 +40,6 @@
#include "libssh/ssh2.h"
#include "libssh/string.h"
#include "libssh/curve25519.h"
#include "libssh/sntrup761.h"
#ifdef HAVE_MLKEM
#include "libssh/mlkem768.h"
#endif
#include "libssh/knownhosts.h"
#include "libssh/misc.h"
#include "libssh/pki.h"
@@ -99,18 +95,6 @@
#define CURVE25519 ""
#endif /* HAVE_CURVE25519 */
#ifdef HAVE_SNTRUP761
#define SNTRUP761X25519 "sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com,"
#else
#define SNTRUP761X25519 ""
#endif /* HAVE_SNTRUP761 */
#ifdef HAVE_MLKEM
#define MLKEM768X25519 "mlkem768x25519-sha256,"
#else
#define MLKEM768X25519 ""
#endif /* HAVE_MLKEM */
#ifdef HAVE_ECC
#define ECDH "ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,"
#define EC_HOSTKEYS "ecdsa-sha2-nistp521," \
@@ -174,8 +158,6 @@
#define CHACHA20 "chacha20-poly1305@openssh.com,"
#define DEFAULT_KEY_EXCHANGE \
MLKEM768X25519 \
SNTRUP761X25519 \
CURVE25519 \
ECDH \
"diffie-hellman-group18-sha512,diffie-hellman-group16-sha512," \
@@ -285,58 +267,38 @@ static const char *ssh_kex_descriptions[] = {
NULL
};
const char *ssh_kex_get_default_methods(enum ssh_kex_types_e type)
const char *ssh_kex_get_default_methods(uint32_t algo)
{
if (type >= SSH_KEX_METHODS) {
if (algo >= SSH_KEX_METHODS) {
return NULL;
}
return default_methods[type];
return default_methods[algo];
}
const char *ssh_kex_get_supported_method(enum ssh_kex_types_e type)
const char *ssh_kex_get_supported_method(uint32_t algo)
{
if (type >= SSH_KEX_METHODS) {
if (algo >= SSH_KEX_METHODS) {
return NULL;
}
return supported_methods[type];
return supported_methods[algo];
}
const char *ssh_kex_get_description(enum ssh_kex_types_e type)
{
if (type >= SSH_KEX_METHODS) {
return NULL;
}
const char *ssh_kex_get_description(uint32_t algo) {
if (algo >= SSH_KEX_METHODS) {
return NULL;
}
return ssh_kex_descriptions[type];
return ssh_kex_descriptions[algo];
}
const char *ssh_kex_get_fips_methods(enum ssh_kex_types_e type)
{
if (type >= SSH_KEX_METHODS) {
return NULL;
}
const char *ssh_kex_get_fips_methods(uint32_t algo) {
if (algo >= SSH_KEX_METHODS) {
return NULL;
}
return fips_methods[type];
}
/**
* @brief Get a list of supported algorithms of a given type. This respects the
* FIPS mode status.
*
* @param[in] type The type of the algorithm to query (SSH_KEX, SSH_MAC_C_S,
* ...).
*
* @return The list of supported methods as comma-separated string, or NULL for
* unknown type.
*/
const char *ssh_get_supported_methods(enum ssh_kex_types_e type)
{
if (ssh_fips_mode()) {
return ssh_kex_get_fips_methods(type);
} else {
return ssh_kex_get_supported_method(type);
}
return fips_methods[algo];
}
/**
@@ -932,14 +894,6 @@ kex_select_kex_type(const char *kex)
return SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG;
} else if (strcmp(kex, "curve25519-sha256") == 0) {
return SSH_KEX_CURVE25519_SHA256;
} else if (strcmp(kex, "sntrup761x25519-sha512@openssh.com") == 0) {
return SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM;
} else if (strcmp(kex, "sntrup761x25519-sha512") == 0) {
return SSH_KEX_SNTRUP761X25519_SHA512;
#ifdef HAVE_MLKEM
} else if (strcmp(kex, "mlkem768x25519-sha256") == 0) {
return SSH_KEX_MLKEM768X25519_SHA256;
#endif
}
/* should not happen. We should be getting only valid names at this stage */
return 0;
@@ -979,17 +933,6 @@ static void revert_kex_callbacks(ssh_session session)
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
ssh_client_curve25519_remove_callbacks(session);
break;
#endif
#ifdef HAVE_SNTRUP761
case SSH_KEX_SNTRUP761X25519_SHA512:
case SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM:
ssh_client_sntrup761x25519_remove_callbacks(session);
break;
#endif
#ifdef HAVE_MLKEM
case SSH_KEX_MLKEM768X25519_SHA256:
ssh_client_mlkem768x25519_remove_callbacks(session);
break;
#endif
}
}
@@ -1397,7 +1340,6 @@ int ssh_make_sessionid(ssh_session session)
buf = ssh_buffer_new();
if (buf == NULL) {
ssh_set_error_oom(session);
return rc;
}
@@ -1406,9 +1348,6 @@ int ssh_make_sessionid(ssh_session session)
session->clientbanner,
session->serverbanner);
if (rc == SSH_ERROR) {
ssh_set_error(session,
SSH_FATAL,
"Failed to pack client and server banner");
goto error;
}
@@ -1422,9 +1361,6 @@ int ssh_make_sessionid(ssh_session session)
rc = ssh_dh_get_next_server_publickey_blob(session, &server_pubkey_blob);
if (rc != SSH_OK) {
ssh_set_error(session,
SSH_FATAL,
"Failed to get next server pubkey blob");
goto error;
}
@@ -1439,9 +1375,6 @@ int ssh_make_sessionid(ssh_session session)
server_pubkey_blob);
SSH_STRING_FREE(server_pubkey_blob);
if (rc != SSH_OK){
ssh_set_error(session,
SSH_FATAL,
"Failed to pack hashes and pubkey blob");
goto error;
}
@@ -1466,7 +1399,6 @@ int ssh_make_sessionid(ssh_session session)
client_pubkey,
server_pubkey);
if (rc != SSH_OK) {
ssh_set_error(session, SSH_FATAL, "Failed to pack DH pubkeys");
goto error;
}
#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L
@@ -1502,7 +1434,6 @@ int ssh_make_sessionid(ssh_session session)
client_pubkey,
server_pubkey);
if (rc != SSH_OK) {
ssh_set_error(session, SSH_FATAL, "Failed to pack DH GEX params");
goto error;
}
#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L
@@ -1525,7 +1456,6 @@ int ssh_make_sessionid(ssh_session session)
session->next_crypto->ecdh_client_pubkey,
session->next_crypto->ecdh_server_pubkey);
if (rc != SSH_OK) {
ssh_set_error(session, SSH_FATAL, "Failed to pack ECDH pubkeys");
goto error;
}
break;
@@ -1543,87 +1473,13 @@ int ssh_make_sessionid(ssh_session session)
session->next_crypto->curve25519_server_pubkey);
if (rc != SSH_OK) {
ssh_set_error(session,
SSH_FATAL,
"Failed to pack Curve25519 pubkeys");
goto error;
}
break;
#endif /* HAVE_CURVE25519 */
#ifdef HAVE_SNTRUP761
case SSH_KEX_SNTRUP761X25519_SHA512:
case SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM:
rc = ssh_buffer_pack(buf,
"dPPdPP",
SNTRUP761_PUBLICKEY_SIZE + CURVE25519_PUBKEY_SIZE,
(size_t)SNTRUP761_PUBLICKEY_SIZE,
session->next_crypto->sntrup761_client_pubkey,
(size_t)CURVE25519_PUBKEY_SIZE,
session->next_crypto->curve25519_client_pubkey,
SNTRUP761_CIPHERTEXT_SIZE + CURVE25519_PUBKEY_SIZE,
(size_t)SNTRUP761_CIPHERTEXT_SIZE,
session->next_crypto->sntrup761_ciphertext,
(size_t)CURVE25519_PUBKEY_SIZE,
session->next_crypto->curve25519_server_pubkey);
if (rc != SSH_OK) {
ssh_set_error(session,
SSH_FATAL,
"Failed to pack SNTRU Prime params");
goto error;
}
break;
#endif /* HAVE_SNTRUP761 */
#ifdef HAVE_MLKEM
case SSH_KEX_MLKEM768X25519_SHA256:
rc = ssh_buffer_pack(buf,
"dPPdPP",
MLKEM768X25519_CLIENT_PUBKEY_SIZE,
(size_t)MLKEM768_PUBLICKEY_SIZE,
session->next_crypto->mlkem768_client_pubkey,
(size_t)CURVE25519_PUBKEY_SIZE,
session->next_crypto->curve25519_client_pubkey,
MLKEM768X25519_SERVER_RESPONSE_SIZE,
(size_t)MLKEM768_CIPHERTEXT_SIZE,
session->next_crypto->mlkem768_ciphertext,
(size_t)CURVE25519_PUBKEY_SIZE,
session->next_crypto->curve25519_server_pubkey);
if (rc != SSH_OK) {
ssh_set_error(session,
SSH_FATAL,
"Failed to pack ML-KEM768 individual components");
goto error;
}
break;
#endif /* HAVE_MLKEM */
default:
/* Handle unsupported kex types - this should not happen in normal operation */
rc = SSH_ERROR;
ssh_set_error(session, SSH_FATAL, "Unsupported KEX algorithm");
goto error;
}
switch (session->next_crypto->kex_type) {
case SSH_KEX_SNTRUP761X25519_SHA512:
case SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM:
rc = ssh_buffer_pack(buf,
"F",
session->next_crypto->shared_secret,
SHA512_DIGEST_LEN);
break;
#ifdef HAVE_MLKEM
case SSH_KEX_MLKEM768X25519_SHA256:
rc = ssh_buffer_pack(buf,
"F",
session->next_crypto->shared_secret,
SHA256_DIGEST_LEN);
break;
#endif /* HAVE_MLKEM */
default:
rc = ssh_buffer_pack(buf, "B", session->next_crypto->shared_secret);
break;
}
rc = ssh_buffer_pack(buf, "B", session->next_crypto->shared_secret);
if (rc != SSH_OK) {
ssh_set_error(session, SSH_FATAL, "Failed to pack shared secret");
goto error;
}
@@ -1631,8 +1487,6 @@ int ssh_make_sessionid(ssh_session session)
ssh_log_hexdump("hash buffer", ssh_buffer_get(buf), ssh_buffer_get_len(buf));
#endif
/* Set rc for the following switch statement in case we goto error. */
rc = SSH_ERROR;
switch (session->next_crypto->kex_type) {
case SSH_KEX_DH_GROUP1_SHA1:
case SSH_KEX_DH_GROUP14_SHA1:
@@ -1653,9 +1507,6 @@ int ssh_make_sessionid(ssh_session session)
case SSH_KEX_ECDH_SHA2_NISTP256:
case SSH_KEX_CURVE25519_SHA256:
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
#ifdef HAVE_MLKEM
case SSH_KEX_MLKEM768X25519_SHA256:
#endif
#ifdef WITH_GEX
case SSH_KEX_DH_GEX_SHA256:
#endif /* WITH_GEX */
@@ -1683,8 +1534,6 @@ int ssh_make_sessionid(ssh_session session)
case SSH_KEX_DH_GROUP16_SHA512:
case SSH_KEX_DH_GROUP18_SHA512:
case SSH_KEX_ECDH_SHA2_NISTP521:
case SSH_KEX_SNTRUP761X25519_SHA512:
case SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM:
session->next_crypto->digest_len = SHA512_DIGEST_LENGTH;
session->next_crypto->digest_type = SSH_KDF_SHA512;
session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
@@ -1696,13 +1545,7 @@ int ssh_make_sessionid(ssh_session session)
ssh_buffer_get_len(buf),
session->next_crypto->secret_hash);
break;
default:
/* Handle unsupported kex types - this should not happen in normal operation */
ssh_set_error(session, SSH_FATAL, "Unsupported KEX algorithm for hash computation");
rc = SSH_ERROR;
goto error;
}
/* During the first kex, secret hash and session ID are equal. However, after
* a key re-exchange, a new secret hash is calculated. This hash will not replace
* but complement existing session id.
@@ -1711,7 +1554,6 @@ int ssh_make_sessionid(ssh_session session)
session->next_crypto->session_id = malloc(session->next_crypto->digest_len);
if (session->next_crypto->session_id == NULL) {
ssh_set_error_oom(session);
rc = SSH_ERROR;
goto error;
}
memcpy(session->next_crypto->session_id, session->next_crypto->secret_hash,
@@ -1828,19 +1670,7 @@ int ssh_generate_session_keys(ssh_session session)
size_t intkey_srv_to_cli_len = 0;
int rc = -1;
switch (session->next_crypto->kex_type) {
case SSH_KEX_SNTRUP761X25519_SHA512:
case SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM:
#ifdef HAVE_MLKEM
case SSH_KEX_MLKEM768X25519_SHA256:
#endif /* HAVE_MLKEM */
k_string = ssh_make_padded_bignum_string(crypto->shared_secret,
crypto->digest_len);
break;
default:
k_string = ssh_make_bignum_string(crypto->shared_secret);
break;
}
k_string = ssh_make_bignum_string(crypto->shared_secret);
if (k_string == NULL) {
ssh_set_error_oom(session);
goto error;

View File

@@ -171,7 +171,7 @@ static int known_hosts_read_line(FILE *fp,
size_t *buf_len,
size_t *lineno)
{
while (fgets(buf, (int)buf_size, fp) != NULL) {
while (fgets(buf, buf_size, fp) != NULL) {
size_t len;
if (buf[0] == '\0') {
continue;

View File

@@ -49,9 +49,8 @@
#include <openssl/rsa.h>
#include <openssl/hmac.h>
#else
#include <openssl/core_names.h>
#include <openssl/param_build.h>
#include <openssl/provider.h>
#include <openssl/core_names.h>
#endif /* OPENSSL_VERSION_NUMBER */
#include <openssl/rand.h>
#if defined(WITH_PKCS11_URI) && !defined(WITH_PKCS11_PROVIDER)
@@ -97,37 +96,7 @@ void ssh_reseed(void){
#endif
}
#if defined(WITH_PKCS11_URI)
#if defined(WITH_PKCS11_PROVIDER)
static OSSL_PROVIDER *provider = NULL;
static bool pkcs11_provider_failed = false;
int pki_load_pkcs11_provider(void)
{
if (OSSL_PROVIDER_available(NULL, "pkcs11") == 1) {
/* the provider is already available.
* Loaded through a configuration file? */
return SSH_OK;
}
if (pkcs11_provider_failed) {
/* the loading failed previously -- do not retry */
return SSH_ERROR;
}
provider = OSSL_PROVIDER_try_load(NULL, "pkcs11", 1);
if (provider != NULL) {
return SSH_OK;
}
SSH_LOG(SSH_LOG_TRACE,
"Failed to load the pkcs11 provider: %s",
ERR_error_string(ERR_get_error(), NULL));
/* Do not attempt to load it again */
pkcs11_provider_failed = true;
return SSH_ERROR;
}
#else
#if defined(WITH_PKCS11_URI) && !defined(WITH_PKCS11_PROVIDER)
static ENGINE *engine = NULL;
ENGINE *pki_get_engine(void)
@@ -159,8 +128,7 @@ ENGINE *pki_get_engine(void)
}
return engine;
}
#endif /* defined(WITH_PKCS11_PROVIDER) */
#endif /* defined(WITH_PKCS11_URI) */
#endif /* defined(WITH_PKCS11_URI) && !defined(WITH_PKCS11_PROVIDER) */
#ifdef HAVE_OPENSSL_EVP_KDF_CTX
#if OPENSSL_VERSION_NUMBER < 0x30000000L
@@ -349,7 +317,7 @@ HMACCTX hmac_init(const void *key, size_t len, enum ssh_hmac_e type)
return NULL;
}
pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, (int)len);
pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, len);
if (pkey == NULL) {
goto error;
}
@@ -406,7 +374,7 @@ static void evp_cipher_init(struct ssh_cipher_struct *cipher)
if (cipher->ctx == NULL) {
cipher->ctx = EVP_CIPHER_CTX_new();
} else {
EVP_CIPHER_CTX_reset(cipher->ctx);
EVP_CIPHER_CTX_init(cipher->ctx);
}
switch(cipher->ciphertype){
@@ -635,7 +603,7 @@ evp_cipher_aead_encrypt(struct ssh_cipher_struct *cipher,
(unsigned char *)out + aadlen,
&tmplen,
(unsigned char *)in + aadlen,
(int)(len - aadlen));
(int)len - aadlen);
outlen = tmplen;
if (rc != 1 || outlen != (int)len - aadlen) {
SSH_LOG(SSH_LOG_TRACE, "EVP_EncryptUpdate failed");
@@ -653,7 +621,7 @@ evp_cipher_aead_encrypt(struct ssh_cipher_struct *cipher,
rc = EVP_CIPHER_CTX_ctrl(cipher->ctx,
EVP_CTRL_GCM_GET_TAG,
(int)authlen,
authlen,
(unsigned char *)tag);
if (rc != 1) {
SSH_LOG(SSH_LOG_TRACE, "EVP_CTRL_GCM_GET_TAG failed");
@@ -691,7 +659,7 @@ evp_cipher_aead_decrypt(struct ssh_cipher_struct *cipher,
/* set tag for authentication */
rc = EVP_CIPHER_CTX_ctrl(cipher->ctx,
EVP_CTRL_GCM_SET_TAG,
(int)authlen,
authlen,
(unsigned char *)complete_packet + aadlen + encrypted_size);
if (rc == 0) {
SSH_LOG(SSH_LOG_TRACE, "EVP_CTRL_GCM_SET_TAG failed");
@@ -716,7 +684,7 @@ evp_cipher_aead_decrypt(struct ssh_cipher_struct *cipher,
(unsigned char *)out,
&outlen,
(unsigned char *)complete_packet + aadlen,
(int)encrypted_size /* already subtracted aadlen */);
encrypted_size /* already subtracted aadlen */);
if (rc != 1) {
SSH_LOG(SSH_LOG_TRACE, "EVP_DecryptUpdate failed");
return SSH_ERROR;
@@ -998,7 +966,7 @@ chacha20_poly1305_aead_decrypt_length(struct ssh_cipher_struct *cipher,
return SSH_ERROR;
}
rv = EVP_CipherUpdate(ctx->header_evp, out, &outlen, in, (int)len);
rv = EVP_CipherUpdate(ctx->header_evp, out, &outlen, in, len);
if (rv != 1 || outlen != sizeof(uint32_t)) {
SSH_LOG(SSH_LOG_TRACE, "EVP_CipherUpdate failed");
return SSH_ERROR;
@@ -1085,11 +1053,9 @@ chacha20_poly1305_aead_decrypt(struct ssh_cipher_struct *cipher,
}
/* Decrypt the message */
rv = EVP_CipherUpdate(ctx->main_evp,
out,
&len,
rv = EVP_CipherUpdate(ctx->main_evp, out, &len,
(uint8_t *)complete_packet + sizeof(uint32_t),
(int)encrypted_size);
encrypted_size);
if (rv != 1) {
SSH_LOG(SSH_LOG_TRACE, "EVP_CipherUpdate failed");
goto out;
@@ -1156,7 +1122,7 @@ chacha20_poly1305_aead_encrypt(struct ssh_cipher_struct *cipher,
out_packet->payload,
&outlen,
in_packet->payload,
(int)(len - sizeof(uint32_t)));
len - sizeof(uint32_t));
if (ret != 1) {
SSH_LOG(SSH_LOG_TRACE, "EVP_CipherUpdate failed");
return;
@@ -1436,14 +1402,6 @@ void ssh_crypto_finalize(void)
engine = NULL;
}
#endif
#if defined(WITH_PKCS11_URI)
#if defined(WITH_PKCS11_PROVIDER)
if (provider != NULL) {
OSSL_PROVIDER_unload(provider);
provider = NULL;
}
#endif /* WITH_PKCS11_PROVIDER */
#endif /* WITH_PKCS11_URI */
libcrypto_initialized = 0;
}
@@ -1588,12 +1546,6 @@ int evp_dup_ecdsa_pkey(const ssh_key key, ssh_key new_key, int demote)
{
return evp_dup_pkey("EC", key, demote, new_key);
}
int evp_dup_ed25519_pkey(const ssh_key key, ssh_key new_key, int demote)
{
return evp_dup_pkey("ED25519", key, demote, new_key);
}
#endif /* OPENSSL_VERSION_NUMBER */
ssh_string

View File

@@ -966,8 +966,7 @@ int ssh_crypto_init(void)
gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
if (!gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P, 0)) {
gcry_control(GCRYCTL_USE_SECURE_RNDPOOL);
gcry_control(GCRYCTL_INIT_SECMEM, 32768, 0);
gcry_control(GCRYCTL_INIT_SECMEM, 4096);
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
}

View File

@@ -481,17 +481,3 @@ LIBSSH_4_10_0 # Released
ssh_pki_export_privkey_file_format;
ssh_request_no_more_sessions;
} LIBSSH_4_9_0;
LIBSSH_AFTER_4_10_0
{
global:
sftp_get_users_groups_by_id;
sftp_name_id_map_free;
sftp_name_id_map_new;
ssh_get_supported_methods;
sshsig_sign;
sshsig_verify;
ssh_string_cmp;
ssh_string_from_data;
} LIBSSH_4_10_0;

View File

@@ -59,22 +59,22 @@ static int current_timestring(int hires, char *buf, size_t len)
{
char tbuf[64];
struct timeval tv;
struct tm tm, *tm_ptr = NULL;
struct tm *tm;
time_t t;
gettimeofday(&tv, NULL);
t = (time_t) tv.tv_sec;
tm_ptr = localtime_r(&t, &tm);
if (tm_ptr == NULL) {
tm = localtime(&t);
if (tm == NULL) {
return -1;
}
if (hires) {
strftime(tbuf, sizeof(tbuf), "%Y/%m/%d %H:%M:%S", &tm);
strftime(tbuf, sizeof(tbuf) - 1, "%Y/%m/%d %H:%M:%S", tm);
snprintf(buf, len, "%s.%06ld", tbuf, (long)tv.tv_usec);
} else {
strftime(tbuf, sizeof(tbuf), "%Y/%m/%d %H:%M:%S", &tm);
strftime(tbuf, sizeof(tbuf) - 1, "%Y/%m/%d %H:%M:%S", tm);
snprintf(buf, len, "%s", tbuf);
}

View File

@@ -205,10 +205,8 @@ int match_pattern_list(const char *string, const char *pattern,
* Returns -1 if negation matches, 1 if there is a positive match, 0 if there
* is no match at all.
*/
int
match_hostname(const char *host, const char *pattern, size_t len)
{
return match_pattern_list(host, pattern, len, 1);
int match_hostname(const char *host, const char *pattern, unsigned int len) {
return match_pattern_list(host, pattern, len, 1);
}
#ifndef _WIN32

View File

@@ -5,17 +5,13 @@
* v3 defines the version inside build_info.h so if it isn't defined
* in version.h we should have v3
*/
#include <mbedtls/cipher.h>
#include <mbedtls/version.h>
#ifndef MBEDTLS_VERSION_MAJOR
#include <mbedtls/build_info.h>
#endif /* MBEDTLS_VERSION_MAJOR */
#include <mbedtls/cipher.h>
#ifdef MBEDTLS_VERSION_MAJOR
#if MBEDTLS_VERSION_MAJOR < 3
static inline size_t
mbedtls_cipher_info_get_key_bitlen(const mbedtls_cipher_info_t *info)
static inline size_t mbedtls_cipher_info_get_key_bitlen(
const mbedtls_cipher_info_t *info)
{
if (info == NULL) {
return 0;
@@ -23,8 +19,8 @@ mbedtls_cipher_info_get_key_bitlen(const mbedtls_cipher_info_t *info)
return info->key_bitlen;
}
static inline size_t
mbedtls_cipher_info_get_iv_size(const mbedtls_cipher_info_t *info)
static inline size_t mbedtls_cipher_info_get_iv_size(
const mbedtls_cipher_info_t *info)
{
if (info == NULL) {
return 0;
@@ -33,24 +29,11 @@ mbedtls_cipher_info_get_iv_size(const mbedtls_cipher_info_t *info)
}
#define MBEDTLS_PRIVATE(X) X
#ifdef HAVE_MBEDTLS_CURVE25519
#include <mbedtls/ecdh.h>
#define MBEDTLS_ECDH_PRIVATE(X) X
#define MBEDTLS_ECDH_PARAMS(X) X
typedef mbedtls_ecdh_context mbedtls_ecdh_params;
#endif /* HAVE_MBEDTLS_CURVE25519 */
#else /* MBEDTLS_VERSION_MAJOR < 3 */
#ifdef HAVE_MBEDTLS_CURVE25519
#include <mbedtls/ecdh.h>
#define MBEDTLS_ECDH_PRIVATE(X) MBEDTLS_PRIVATE(X)
#define MBEDTLS_ECDH_PARAMS(X) X.MBEDTLS_PRIVATE(ctx).MBEDTLS_PRIVATE(mbed_ecdh)
typedef mbedtls_ecdh_context_mbed mbedtls_ecdh_params;
#endif /* HAVE_MBEDTLS_CURVE25519 */
#endif /* MBEDTLS_VERSION_MAJOR < 3 */
#else /* MBEDTLS_VERSION_MAJOR */
#include <mbedtls/build_info.h>
#if MBEDTLS_VERSION_MAJOR < 3
#define MBEDTLS_PRIVATE(X) X
#endif /* MBEDTLS_VERSION_MAJOR < 3 */
#endif /* MBEDTLS_VERSION_MAJOR */
#endif /* MBEDCRYPTO_COMPAT_H */

View File

@@ -204,35 +204,8 @@ static int ssh_execute_server_request(ssh_session session, ssh_message msg)
ssh_message_reply_default(msg);
}
return SSH_OK;
#define CB channel_open_request_direct_tcpip_function
} else if (msg->channel_request_open.type == SSH_CHANNEL_DIRECT_TCPIP &&
ssh_callbacks_exists(session->server_callbacks, CB)) {
struct ssh_channel_request_open *rq = &msg->channel_request_open;
channel = session->server_callbacks->CB(session,
rq->destination,
rq->destination_port,
rq->originator,
rq->originator_port,
session->server_callbacks->userdata);
#undef CB
if (channel != NULL) {
rc = ssh_message_channel_request_open_reply_accept_channel(
msg,
channel);
if (rc != SSH_OK) {
SSH_LOG(SSH_LOG_TRACE,
"Failed to send reply for accepting a channel "
"open");
}
return SSH_OK;
} else {
ssh_message_reply_default(msg);
}
return SSH_OK;
}
break;
case SSH_REQUEST_CHANNEL:
channel = msg->channel_request.channel;
@@ -546,36 +519,30 @@ static void ssh_message_queue(ssh_session session, ssh_message message)
*
* @returns The head message or NULL if it doesn't exist.
*/
ssh_message ssh_message_pop_head(ssh_session session)
{
ssh_message msg = NULL;
struct ssh_iterator *i = NULL;
if (session->ssh_message_list == NULL)
return NULL;
i = ssh_list_get_iterator(session->ssh_message_list);
if (i != NULL) {
msg = ssh_iterator_value(ssh_message, i);
ssh_list_remove(session->ssh_message_list, i);
}
return msg;
ssh_message ssh_message_pop_head(ssh_session session){
ssh_message msg=NULL;
struct ssh_iterator *i = NULL;
if(session->ssh_message_list == NULL)
return NULL;
i=ssh_list_get_iterator(session->ssh_message_list);
if(i != NULL){
msg=ssh_iterator_value(ssh_message,i);
ssh_list_remove(session->ssh_message_list,i);
}
return msg;
}
/* Returns 1 if there is a message available */
static int ssh_message_termination(void *s)
{
ssh_session session = s;
struct ssh_iterator *it = NULL;
if (session->session_state == SSH_SESSION_STATE_ERROR)
return 1;
it = ssh_list_get_iterator(session->ssh_message_list);
if (!it)
return 0;
else
return 1;
static int ssh_message_termination(void *s){
ssh_session session = s;
struct ssh_iterator *it = NULL;
if(session->session_state == SSH_SESSION_STATE_ERROR)
return 1;
it = ssh_list_get_iterator(session->ssh_message_list);
if(!it)
return 0;
else
return 1;
}
/**
* @brief Retrieve a SSH message from a SSH session.
@@ -675,7 +642,6 @@ void ssh_message_free(ssh_message msg){
SAFE_FREE(msg->auth_request.password);
}
ssh_key_free(msg->auth_request.pubkey);
ssh_key_free(msg->auth_request.server_pubkey);
break;
case SSH_REQUEST_CHANNEL_OPEN:
SAFE_FREE(msg->channel_request_open.originator);
@@ -767,12 +733,11 @@ error:
static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
ssh_message msg,
const char *service,
ssh_string algo,
const char *method)
ssh_string algo)
{
struct ssh_crypto_struct *crypto = NULL;
ssh_buffer buffer = NULL;
ssh_string str = NULL;
ssh_string str=NULL;
int rc;
crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN);
@@ -798,10 +763,10 @@ static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
SSH2_MSG_USERAUTH_REQUEST, /* type */
msg->auth_request.username,
service,
method,
"publickey", /* method */
1, /* has to be signed (true) */
ssh_string_get_char(algo), /* pubkey algorithm */
str); /* public key as a blob */
str); /* public key as a blob */
SSH_STRING_FREE(str);
if (rc != SSH_OK) {
@@ -810,25 +775,6 @@ static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
return NULL;
}
/* Add server public key for hostbound extension */
if (strcmp(method, "publickey-hostbound-v00@openssh.com") == 0 &&
msg->auth_request.server_pubkey != NULL) {
rc = ssh_pki_export_pubkey_blob(msg->auth_request.server_pubkey, &str);
if (rc < 0) {
SSH_BUFFER_FREE(buffer);
return NULL;
}
rc = ssh_buffer_add_ssh_string(buffer, str);
SSH_STRING_FREE(str);
if (rc < 0) {
ssh_set_error_oom(session);
SSH_BUFFER_FREE(buffer);
return NULL;
}
}
return buffer;
}
@@ -838,334 +784,263 @@ static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
* @brief Handle a SSH_MSG_MSG_USERAUTH_REQUEST packet and queue a
* SSH Message
*/
SSH_PACKET_CALLBACK(ssh_packet_userauth_request)
{
ssh_message msg = NULL;
ssh_signature sig = NULL;
char *service = NULL;
char *method = NULL;
int cmp;
int rc;
SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
ssh_message msg = NULL;
ssh_signature sig = NULL;
char *service = NULL;
char *method = NULL;
int cmp;
int rc;
(void)user;
(void)type;
(void)user;
(void)type;
msg = ssh_message_new(session);
if (msg == NULL) {
ssh_set_error_oom(session);
goto error;
msg = ssh_message_new(session);
if (msg == NULL) {
ssh_set_error_oom(session);
goto error;
}
msg->type = SSH_REQUEST_AUTH;
rc = ssh_buffer_unpack(packet,
"sss",
&msg->auth_request.username,
&service,
&method);
if (rc != SSH_OK) {
goto error;
}
SSH_LOG(SSH_LOG_PACKET,
"Auth request for service %s, method %s for user '%s'",
service, method,
msg->auth_request.username);
cmp = strcmp(service, "ssh-connection");
if (cmp != 0) {
SSH_LOG(SSH_LOG_TRACE,
"Invalid service request: %s",
service);
goto end;
}
if (strcmp(method, "none") == 0) {
msg->auth_request.method = SSH_AUTH_METHOD_NONE;
goto end;
}
if (strcmp(method, "password") == 0) {
uint8_t tmp;
msg->auth_request.method = SSH_AUTH_METHOD_PASSWORD;
rc = ssh_buffer_unpack(packet, "bs", &tmp, &msg->auth_request.password);
if (rc != SSH_OK) {
goto error;
}
msg->type = SSH_REQUEST_AUTH;
rc = ssh_buffer_unpack(packet,
"sss",
&msg->auth_request.username,
&service,
&method);
goto end;
}
if (strcmp(method, "keyboard-interactive") == 0) {
ssh_string lang = NULL;
ssh_string submethods = NULL;
msg->auth_request.method = SSH_AUTH_METHOD_INTERACTIVE;
lang = ssh_buffer_get_ssh_string(packet);
if (lang == NULL) {
goto error;
}
/* from the RFC 4256
* 3.1. Initial Exchange
* "The language tag is deprecated and SHOULD be the empty string."
*/
SSH_STRING_FREE(lang);
submethods = ssh_buffer_get_ssh_string(packet);
if (submethods == NULL) {
goto error;
}
/* from the RFC 4256
* 3.1. Initial Exchange
* "One possible implementation strategy of the submethods field on the
* server is that, unless the user may use multiple different
* submethods, the server ignores this field."
*/
SSH_STRING_FREE(submethods);
goto end;
}
if (strcmp(method, "publickey") == 0) {
ssh_string algo = NULL;
ssh_string pubkey_blob = NULL;
uint8_t has_sign;
msg->auth_request.method = SSH_AUTH_METHOD_PUBLICKEY;
SAFE_FREE(method);
rc = ssh_buffer_unpack(packet, "bSS",
&has_sign,
&algo,
&pubkey_blob
);
if (rc != SSH_OK) {
goto error;
}
rc = ssh_pki_import_pubkey_blob(pubkey_blob, &msg->auth_request.pubkey);
SSH_STRING_FREE(pubkey_blob);
pubkey_blob = NULL;
if (rc < 0) {
SSH_STRING_FREE(algo);
algo = NULL;
goto error;
}
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_NONE;
msg->auth_request.sigtype = strdup(ssh_string_get_char(algo));
if (msg->auth_request.sigtype == NULL) {
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_ERROR;
SSH_STRING_FREE(algo);
algo = NULL;
goto error;
}
SSH_LOG(SSH_LOG_PACKET,
"Auth request for service %s, method %s for user '%s'",
service,
method,
msg->auth_request.username);
// has a valid signature ?
if(has_sign) {
ssh_string sig_blob = NULL;
ssh_buffer digest = NULL;
cmp = strcmp(service, "ssh-connection");
if (cmp != 0) {
SSH_LOG(SSH_LOG_TRACE, "Invalid service request: %s", service);
goto end;
}
if (strcmp(method, "none") == 0) {
msg->auth_request.method = SSH_AUTH_METHOD_NONE;
goto end;
}
if (strcmp(method, "password") == 0) {
uint8_t tmp;
msg->auth_request.method = SSH_AUTH_METHOD_PASSWORD;
rc = ssh_buffer_unpack(packet, "bs", &tmp, &msg->auth_request.password);
if (rc != SSH_OK) {
goto error;
}
goto end;
}
if (strcmp(method, "keyboard-interactive") == 0) {
ssh_string lang = NULL;
ssh_string submethods = NULL;
msg->auth_request.method = SSH_AUTH_METHOD_INTERACTIVE;
lang = ssh_buffer_get_ssh_string(packet);
if (lang == NULL) {
goto error;
}
/* from the RFC 4256
* 3.1. Initial Exchange
* "The language tag is deprecated and SHOULD be the empty string."
*/
SSH_STRING_FREE(lang);
submethods = ssh_buffer_get_ssh_string(packet);
if (submethods == NULL) {
goto error;
}
/* from the RFC 4256
* 3.1. Initial Exchange
* "One possible implementation strategy of the submethods field on the
* server is that, unless the user may use multiple different
* submethods, the server ignores this field."
*/
SSH_STRING_FREE(submethods);
goto end;
}
if (strcmp(method, "publickey") == 0 ||
strcmp(method, "publickey-hostbound-v00@openssh.com") == 0) {
ssh_string algo = NULL;
ssh_string pubkey_blob = NULL;
ssh_string server_pubkey_blob = NULL;
uint8_t has_sign;
msg->auth_request.method = SSH_AUTH_METHOD_PUBLICKEY;
rc = ssh_buffer_unpack(packet, "bSS", &has_sign, &algo, &pubkey_blob);
if (rc != SSH_OK) {
goto error;
}
cmp = strcmp(method, "publickey-hostbound-v00@openssh.com");
if (cmp == 0) {
server_pubkey_blob = ssh_buffer_get_ssh_string(packet);
if (server_pubkey_blob == NULL) {
SSH_STRING_FREE(pubkey_blob);
SSH_STRING_FREE(algo);
goto error;
}
rc = ssh_pki_import_pubkey_blob(server_pubkey_blob,
&msg->auth_request.server_pubkey);
SSH_STRING_FREE(server_pubkey_blob);
if (rc < 0) {
SSH_STRING_FREE(pubkey_blob);
SSH_STRING_FREE(algo);
goto error;
}
}
rc = ssh_pki_import_pubkey_blob(pubkey_blob, &msg->auth_request.pubkey);
SSH_STRING_FREE(pubkey_blob);
pubkey_blob = NULL;
if (rc < 0) {
SSH_STRING_FREE(algo);
algo = NULL;
goto error;
}
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_NONE;
msg->auth_request.sigtype = strdup(ssh_string_get_char(algo));
if (msg->auth_request.sigtype == NULL) {
sig_blob = ssh_buffer_get_ssh_string(packet);
if(sig_blob == NULL) {
SSH_LOG(SSH_LOG_PACKET, "Invalid signature packet from peer");
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_ERROR;
SSH_STRING_FREE(algo);
algo = NULL;
goto error;
}
// has a valid signature ?
if (has_sign) {
ssh_string sig_blob = NULL;
ssh_buffer digest = NULL;
digest = ssh_msg_userauth_build_digest(session, msg, service, algo);
SSH_STRING_FREE(algo);
algo = NULL;
if (digest == NULL) {
SSH_STRING_FREE(sig_blob);
SSH_LOG(SSH_LOG_PACKET, "Failed to get digest");
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_WRONG;
goto error;
}
sig_blob = ssh_buffer_get_ssh_string(packet);
if (sig_blob == NULL) {
SSH_LOG(SSH_LOG_PACKET, "Invalid signature packet from peer");
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_ERROR;
SSH_STRING_FREE(algo);
algo = NULL;
goto error;
}
digest = ssh_msg_userauth_build_digest(session,
msg,
service,
algo,
method);
SSH_STRING_FREE(algo);
algo = NULL;
if (digest == NULL) {
SSH_STRING_FREE(sig_blob);
SSH_LOG(SSH_LOG_PACKET, "Failed to get digest");
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_WRONG;
goto error;
}
rc = ssh_pki_import_signature_blob(sig_blob,
msg->auth_request.pubkey,
&sig);
if (rc == SSH_OK) {
/* Check if the signature from client matches server preferences
*/
if (session->opts.pubkey_accepted_types) {
cmp = match_group(session->opts.pubkey_accepted_types,
sig->type_c);
if (cmp != 1) {
ssh_set_error(
session,
rc = ssh_pki_import_signature_blob(sig_blob,
msg->auth_request.pubkey,
&sig);
if (rc == SSH_OK) {
/* Check if the signature from client matches server preferences */
if (session->opts.pubkey_accepted_types) {
cmp = match_group(session->opts.pubkey_accepted_types,
sig->type_c);
if (cmp != 1) {
ssh_set_error(session,
SSH_FATAL,
"Public key from client (%s) doesn't match server "
"preference (%s)",
sig->type_c,
session->opts.pubkey_accepted_types);
rc = SSH_ERROR;
}
}
if (rc == SSH_OK) {
rc = ssh_pki_signature_verify(session,
sig,
msg->auth_request.pubkey,
ssh_buffer_get(digest),
ssh_buffer_get_len(digest));
rc = SSH_ERROR;
}
}
SSH_STRING_FREE(sig_blob);
SSH_BUFFER_FREE(digest);
ssh_signature_free(sig);
if (rc < 0) {
SSH_LOG(SSH_LOG_PACKET,
"Received an invalid signature from peer");
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_WRONG;
goto error;
if (rc == SSH_OK) {
rc = ssh_pki_signature_verify(session,
sig,
msg->auth_request.pubkey,
ssh_buffer_get(digest),
ssh_buffer_get_len(digest));
}
SSH_LOG(SSH_LOG_PACKET, "Valid signature received");
cmp = strcmp(method, "publickey-hostbound-v00@openssh.com");
if (cmp == 0) {
ssh_key server_key = NULL;
if (msg->auth_request.server_pubkey == NULL) {
SSH_LOG(SSH_LOG_PACKET,
"Server public key not provided by client");
msg->auth_request.signature_state =
SSH_PUBLICKEY_STATE_WRONG;
goto error;
}
rc = ssh_get_server_publickey(session, &server_key);
if (rc != SSH_OK) {
SSH_LOG(SSH_LOG_PACKET,
"Failed to get server public key for hostbound "
"verification");
msg->auth_request.signature_state =
SSH_PUBLICKEY_STATE_ERROR;
ssh_key_free(server_key);
goto error;
}
if (ssh_key_cmp(server_key,
msg->auth_request.server_pubkey,
SSH_KEY_CMP_PUBLIC) != 0) {
SSH_LOG(SSH_LOG_PACKET,
"Server public key doesn't match the one provided "
"by client");
msg->auth_request.signature_state =
SSH_PUBLICKEY_STATE_WRONG;
ssh_key_free(server_key);
goto error;
}
ssh_key_free(server_key);
}
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_VALID;
}
SSH_STRING_FREE(sig_blob);
SSH_BUFFER_FREE(digest);
ssh_signature_free(sig);
if (rc < 0) {
SSH_LOG(
SSH_LOG_PACKET,
"Received an invalid signature from peer");
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_WRONG;
goto error;
}
SAFE_FREE(method);
SSH_STRING_FREE(algo);
goto end;
SSH_LOG(SSH_LOG_PACKET, "Valid signature received");
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_VALID;
}
SSH_STRING_FREE(algo);
goto end;
}
#ifdef WITH_GSSAPI
if (strcmp(method, "gssapi-with-mic") == 0) {
uint32_t n_oid;
ssh_string *oids = NULL;
ssh_string oid = NULL;
char *hexa = NULL;
int i;
ssh_buffer_get_u32(packet, &n_oid);
n_oid = ntohl(n_oid);
if (n_oid > 100) {
ssh_set_error(
session,
SSH_FATAL,
"USERAUTH_REQUEST: gssapi-with-mic OID count too big (%d)",
n_oid);
goto error;
}
SSH_LOG(SSH_LOG_PACKET, "gssapi: %d OIDs", n_oid);
oids = calloc(n_oid, sizeof(ssh_string));
if (oids == NULL) {
ssh_set_error_oom(session);
goto error;
}
for (i = 0; i < (int)n_oid; ++i) {
oid = ssh_buffer_get_ssh_string(packet);
if (oid == NULL) {
for (i = i - 1; i >= 0; --i) {
SAFE_FREE(oids[i]);
}
SAFE_FREE(oids);
ssh_set_error(session,
SSH_LOG_PACKET,
"USERAUTH_REQUEST: gssapi-with-mic missing OID");
goto error;
}
oids[i] = oid;
if (session->common.log_verbosity >= SSH_LOG_PACKET) {
hexa = ssh_get_hexa(ssh_string_data(oid), ssh_string_len(oid));
SSH_LOG(SSH_LOG_PACKET, "gssapi: OID %d: %s", i, hexa);
SAFE_FREE(hexa);
}
}
ssh_gssapi_handle_userauth(session,
msg->auth_request.username,
n_oid,
oids);
if (strcmp(method, "gssapi-with-mic") == 0) {
uint32_t n_oid;
ssh_string *oids = NULL;
ssh_string oid = NULL;
char *hexa = NULL;
int i;
ssh_buffer_get_u32(packet, &n_oid);
n_oid=ntohl(n_oid);
if(n_oid > 100){
ssh_set_error(session, SSH_FATAL, "USERAUTH_REQUEST: gssapi-with-mic OID count too big (%d)",n_oid);
goto error;
}
SSH_LOG(SSH_LOG_PACKET, "gssapi: %d OIDs", n_oid);
oids = calloc(n_oid, sizeof(ssh_string));
if (oids == NULL){
ssh_set_error_oom(session);
goto error;
}
for (i=0;i<(int) n_oid;++i){
oid=ssh_buffer_get_ssh_string(packet);
if(oid == NULL){
for(i=i-1;i>=0;--i){
SAFE_FREE(oids[i]);
}
SAFE_FREE(oids);
ssh_set_error(session, SSH_LOG_PACKET, "USERAUTH_REQUEST: gssapi-with-mic missing OID");
goto error;
}
oids[i] = oid;
if(session->common.log_verbosity >= SSH_LOG_PACKET){
hexa = ssh_get_hexa(ssh_string_data(oid), ssh_string_len(oid));
SSH_LOG(SSH_LOG_PACKET,"gssapi: OID %d: %s",i, hexa);
SAFE_FREE(hexa);
}
}
ssh_gssapi_handle_userauth(session, msg->auth_request.username, n_oid, oids);
for (i = 0; i < (int)n_oid; ++i) {
SAFE_FREE(oids[i]);
}
SAFE_FREE(oids);
/* bypass the message queue thing */
SAFE_FREE(service);
SAFE_FREE(method);
SSH_MESSAGE_FREE(msg);
for(i=0;i<(int)n_oid;++i){
SAFE_FREE(oids[i]);
}
SAFE_FREE(oids);
/* bypass the message queue thing */
SAFE_FREE(service);
SAFE_FREE(method);
SSH_MESSAGE_FREE(msg);
return SSH_PACKET_USED;
}
return SSH_PACKET_USED;
}
#endif
msg->auth_request.method = SSH_AUTH_METHOD_UNKNOWN;
SAFE_FREE(method);
goto end;
msg->auth_request.method = SSH_AUTH_METHOD_UNKNOWN;
SAFE_FREE(method);
goto end;
error:
SAFE_FREE(service);
SAFE_FREE(method);
SAFE_FREE(service);
SAFE_FREE(method);
SSH_MESSAGE_FREE(msg);
SSH_MESSAGE_FREE(msg);
return SSH_PACKET_USED;
return SSH_PACKET_USED;
end:
SAFE_FREE(service);
SAFE_FREE(method);
SAFE_FREE(service);
SAFE_FREE(method);
ssh_message_queue(session, msg);
ssh_message_queue(session,msg);
return SSH_PACKET_USED;
return SSH_PACKET_USED;
}
#endif /* WITH_SERVER */
@@ -1426,9 +1301,7 @@ end:
*
* @returns SSH_OK on success, SSH_ERROR if an error occurred.
*/
int ssh_message_channel_request_open_reply_accept_channel(ssh_message msg,
ssh_channel chan)
{
int ssh_message_channel_request_open_reply_accept_channel(ssh_message msg, ssh_channel chan) {
ssh_session session = NULL;
int rc;
@@ -1479,25 +1352,25 @@ int ssh_message_channel_request_open_reply_accept_channel(ssh_message msg,
*
* @returns NULL in case of error
*/
ssh_channel ssh_message_channel_request_open_reply_accept(ssh_message msg)
{
ssh_channel chan = NULL;
int rc;
ssh_channel ssh_message_channel_request_open_reply_accept(ssh_message msg) {
ssh_channel chan = NULL;
int rc;
if (msg == NULL) {
return NULL;
}
if (msg == NULL) {
return NULL;
}
chan = ssh_channel_new(msg->session);
if (chan == NULL) {
return NULL;
}
rc = ssh_message_channel_request_open_reply_accept_channel(msg, chan);
if (rc < 0) {
ssh_channel_free(chan);
chan = NULL;
}
return chan;
chan = ssh_channel_new(msg->session);
if (chan == NULL) {
return NULL;
}
rc = ssh_message_channel_request_open_reply_accept_channel(msg, chan);
if (rc < 0) {
ssh_channel_free(chan);
chan = NULL;
}
return chan;
}
/**

View File

@@ -178,35 +178,6 @@ int ssh_gettimeofday(struct timeval *__p, void *__t)
return (0);
}
/**
* @internal
*
* @brief Convert time in seconds since the Epoch to broken-down local time
*
* This is a helper used to provide localtime_r() like function interface
* on Windows.
*
* @param timer Pointer to a location storing the time_t which
* represents the time in seconds since the Epoch.
*
* @param result Pointer to a location where the broken-down time
* (expressed as local time) should be stored.
*
* @returns A pointer to the structure pointed to by the parameter
* <tt>result</tt> on success, NULL on error with the errno
* set to indicate the error.
*/
struct tm *ssh_localtime(const time_t *timer, struct tm *result)
{
errno_t rc;
rc = localtime_s(result, timer);
if (rc != 0) {
return NULL;
}
return result;
}
char *ssh_get_local_username(void)
{
DWORD size = 0;
@@ -430,22 +401,22 @@ int ssh_is_ipaddr(const char *str)
char *ssh_lowercase(const char* str)
{
char *new = NULL, *p = NULL;
char *new = NULL, *p = NULL;
if (str == NULL) {
return NULL;
}
if (str == NULL) {
return NULL;
}
new = strdup(str);
if (new == NULL) {
return NULL;
}
new = strdup(str);
if (new == NULL) {
return NULL;
}
for (p = new; *p; p++) {
*p = tolower(*p);
}
for (p = new; *p; p++) {
*p = tolower(*p);
}
return new;
return new;
}
char *ssh_hostport(const char *host, int port)
@@ -865,32 +836,32 @@ int ssh_list_prepend(struct ssh_list *list, const void *data)
void ssh_list_remove(struct ssh_list *list, struct ssh_iterator *iterator)
{
struct ssh_iterator *ptr = NULL, *prev = NULL;
struct ssh_iterator *ptr = NULL, *prev = NULL;
if (list == NULL) {
return;
}
if (list == NULL) {
return;
}
prev = NULL;
ptr = list->root;
while (ptr && ptr != iterator) {
prev = ptr;
ptr = ptr->next;
}
if (!ptr) {
/* we did not find the element */
return;
}
/* unlink it */
if (prev)
prev->next = ptr->next;
/* if iterator was the head */
if (list->root == iterator)
list->root = iterator->next;
/* if iterator was the tail */
if (list->end == iterator)
list->end = prev;
SAFE_FREE(iterator);
prev=NULL;
ptr=list->root;
while(ptr && ptr != iterator){
prev=ptr;
ptr=ptr->next;
}
if(!ptr){
/* we did not find the element */
return;
}
/* unlink it */
if(prev)
prev->next=ptr->next;
/* if iterator was the head */
if(list->root == iterator)
list->root=iterator->next;
/* if iterator was the tail */
if(list->end == iterator)
list->end = prev;
SAFE_FREE(iterator);
}
/**
@@ -1376,7 +1347,6 @@ int ssh_analyze_banner(ssh_session session, int server)
{
const char *banner = NULL;
const char *openssh = NULL;
const char *ios = NULL;
if (server) {
banner = session->clientbanner;
@@ -1466,11 +1436,6 @@ int ssh_analyze_banner(ssh_session session, int server)
major, minor, session->openssh);
}
}
/* Cisco devices have odd scp implementation which breaks */
ios = strstr(banner, "Cisco");
if (ios != NULL) {
session->flags |= SSH_SESSION_FLAG_SCP_QUOTING_BROKEN;
}
done:
return 0;
@@ -1625,27 +1590,6 @@ void explicit_bzero(void *s, size_t n)
}
#endif /* !HAVE_EXPLICIT_BZERO */
/**
* @brief Securely free memory by overwriting it before deallocation
*
* Overwrites the memory region with zeros before calling free() to prevent
* sensitive data from remaining in memory after deallocation.
*
* @param[in] ptr Pointer to the memory region to securely free.
* Can be NULL (no operation performed).
* @param[in] len Length of the memory region in bytes.
*
*/
void burn_free(void *ptr, size_t len)
{
if (ptr == NULL || len == 0) {
return;
}
explicit_bzero(ptr, len);
free(ptr);
}
#if !defined(HAVE_STRNDUP)
char *strndup(const char *s, size_t n)
{
@@ -1858,7 +1802,7 @@ int ssh_quote_file_name(const char *file_name, char *buf, size_t buf_len)
/* Put the string terminator */
*dst = '\0';
return (int)(dst - buf);
return dst - buf;
error:
return SSH_ERROR;
@@ -1904,7 +1848,7 @@ int ssh_newline_vis(const char *string, char *buf, size_t buf_len)
}
*out = '\0';
return (int)(out - buf);
return out - buf;
}
/**

View File

@@ -1,679 +0,0 @@
/*
* mlkem768x25519.c - ML-KEM768x25519 hybrid key exchange
* mlkem768x25519-sha256
*
* This file is part of the SSH Library
*
* Copyright (c) 2025 by Red Hat, Inc.
*
* Author: Sahana Prasad <sahana@redhat.com>
* Author: Claude (Anthropic)
*
* 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/bignum.h"
#include "libssh/buffer.h"
#include "libssh/crypto.h"
#include "libssh/curve25519.h"
#include "libssh/dh.h"
#include "libssh/mlkem768.h"
#include "libssh/pki.h"
#include "libssh/priv.h"
#include "libssh/session.h"
#include "libssh/ssh2.h"
#include <string.h>
#include <openssl/evp.h>
#include <openssl/err.h>
static SSH_PACKET_CALLBACK(ssh_packet_client_mlkem768x25519_reply);
static ssh_packet_callback dh_client_callbacks[] = {
ssh_packet_client_mlkem768x25519_reply,
};
static struct ssh_packet_callbacks_struct ssh_mlkem768x25519_client_callbacks =
{
.start = SSH2_MSG_KEX_HYBRID_REPLY,
.n_callbacks = 1,
.callbacks = dh_client_callbacks,
.user = NULL,
};
/* Generate ML-KEM768 keypair using OpenSSL */
static int mlkem768_keypair_gen(ssh_mlkem768_pubkey pubkey,
ssh_mlkem768_privkey privkey)
{
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *pkey = NULL;
int rc, ret = SSH_ERROR;
size_t pubkey_len = MLKEM768_PUBLICKEY_SIZE;
size_t privkey_len = MLKEM768_SECRETKEY_SIZE;
ctx = EVP_PKEY_CTX_new_from_name(NULL, "ML-KEM-768", NULL);
if (ctx == NULL) {
SSH_LOG(SSH_LOG_WARNING,
"Failed to create ML-KEM-768 context: %s",
ERR_error_string(ERR_get_error(), NULL));
goto cleanup;
}
rc = EVP_PKEY_keygen_init(ctx);
if (rc != 1) {
SSH_LOG(SSH_LOG_WARNING,
"Failed to initialize ML-KEM-768 keygen: %s",
ERR_error_string(ERR_get_error(), NULL));
goto cleanup;
}
rc = EVP_PKEY_keygen(ctx, &pkey);
if (rc != 1) {
SSH_LOG(SSH_LOG_WARNING,
"Failed to perform ML-KEM-768 keygen: %s",
ERR_error_string(ERR_get_error(), NULL));
goto cleanup;
}
rc = EVP_PKEY_get_raw_public_key(pkey, pubkey, &pubkey_len);
if (rc != 1) {
SSH_LOG(SSH_LOG_WARNING,
"Failed to extract ML-KEM-768 public key: %s",
ERR_error_string(ERR_get_error(), NULL));
goto cleanup;
}
rc = EVP_PKEY_get_raw_private_key(pkey, privkey, &privkey_len);
if (rc != 1) {
SSH_LOG(SSH_LOG_WARNING,
"Failed to extract ML-KEM-768 private key: %s",
ERR_error_string(ERR_get_error(), NULL));
goto cleanup;
}
ret = SSH_OK;
cleanup:
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
return ret;
}
/* Encapsulate shared secret using ML-KEM768 - used by server side */
static int mlkem768_encapsulate(const ssh_mlkem768_pubkey pubkey,
ssh_mlkem768_ciphertext ciphertext,
unsigned char *shared_secret)
{
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ctx = NULL;
int rc, ret = SSH_ERROR;
size_t ct_len = MLKEM768_CIPHERTEXT_SIZE;
size_t ss_len = MLKEM768_SHARED_SECRET_SIZE;
pkey = EVP_PKEY_new_raw_public_key_ex(NULL,
"ML-KEM-768",
NULL,
pubkey,
MLKEM768_PUBLICKEY_SIZE);
if (pkey == NULL) {
SSH_LOG(SSH_LOG_WARNING,
"Failed to create ML-KEM-768 public key from raw data: %s",
ERR_error_string(ERR_get_error(), NULL));
goto cleanup;
}
ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
if (ctx == NULL) {
SSH_LOG(SSH_LOG_WARNING,
"Failed to create ML-KEM-768 context: %s",
ERR_error_string(ERR_get_error(), NULL));
goto cleanup;
}
rc = EVP_PKEY_encapsulate_init(ctx, NULL);
if (rc != 1) {
SSH_LOG(SSH_LOG_WARNING,
"Failed to initialize ML-KEM-768 encapsulation: %s",
ERR_error_string(ERR_get_error(), NULL));
goto cleanup;
}
rc = EVP_PKEY_encapsulate(ctx, ciphertext, &ct_len, shared_secret, &ss_len);
if (rc != 1) {
SSH_LOG(SSH_LOG_WARNING,
"Failed to perform ML-KEM-768 encapsulation: %s",
ERR_error_string(ERR_get_error(), NULL));
goto cleanup;
}
ret = SSH_OK;
cleanup:
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
return ret;
}
/* Decapsulate shared secret using ML-KEM768 - used by client side */
static int mlkem768_decapsulate(const ssh_mlkem768_privkey privkey,
const ssh_mlkem768_ciphertext ciphertext,
unsigned char *shared_secret)
{
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ctx = NULL;
int rc, ret = SSH_ERROR;
size_t ss_len = MLKEM768_SHARED_SECRET_SIZE;
pkey = EVP_PKEY_new_raw_private_key_ex(NULL,
"ML-KEM-768",
NULL,
privkey,
MLKEM768_SECRETKEY_SIZE);
if (pkey == NULL) {
SSH_LOG(SSH_LOG_WARNING,
"Failed to create ML-KEM-768 context: %s",
ERR_error_string(ERR_get_error(), NULL));
goto cleanup;
}
ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
if (ctx == NULL) {
SSH_LOG(SSH_LOG_WARNING,
"Failed to create ML-KEM-768 context: %s",
ERR_error_string(ERR_get_error(), NULL));
goto cleanup;
}
rc = EVP_PKEY_decapsulate_init(ctx, NULL);
if (rc != 1) {
SSH_LOG(SSH_LOG_WARNING,
"Failed to initialize ML-KEM-768 decapsulation: %s",
ERR_error_string(ERR_get_error(), NULL));
goto cleanup;
}
rc = EVP_PKEY_decapsulate(ctx,
shared_secret,
&ss_len,
ciphertext,
MLKEM768_CIPHERTEXT_SIZE);
if (rc != 1) {
SSH_LOG(SSH_LOG_WARNING,
"Failed to perform ML-KEM-768 decapsulation: %s",
ERR_error_string(ERR_get_error(), NULL));
goto cleanup;
}
ret = SSH_OK;
cleanup:
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
return ret;
}
int ssh_client_mlkem768x25519_init(ssh_session session)
{
struct ssh_crypto_struct *crypto = session->next_crypto;
ssh_buffer client_pubkey = NULL;
ssh_string pubkey_blob = NULL;
int rc;
SSH_LOG(SSH_LOG_TRACE, "Initializing ML-KEM768x25519 key exchange");
/* Initialize Curve25519 component first */
rc = ssh_curve25519_init(session);
if (rc != SSH_OK) {
return rc;
}
/* Generate ML-KEM768 keypair */
rc = mlkem768_keypair_gen(crypto->mlkem768_client_pubkey,
crypto->mlkem768_client_privkey);
if (rc != SSH_OK) {
ssh_set_error(session, SSH_FATAL, "Failed to generate ML-KEM768 keypair");
return SSH_ERROR;
}
/* Create hybrid client public key: ML-KEM768 + Curve25519 */
client_pubkey = ssh_buffer_new();
if (client_pubkey == NULL) {
session->session_state = SSH_SESSION_STATE_ERROR;
rc = SSH_ERROR;
goto cleanup;
}
rc = ssh_buffer_pack(client_pubkey,
"PP",
MLKEM768_PUBLICKEY_SIZE,
crypto->mlkem768_client_pubkey,
CURVE25519_PUBKEY_SIZE,
crypto->curve25519_client_pubkey);
if (rc != SSH_OK) {
session->session_state = SSH_SESSION_STATE_ERROR;
rc = SSH_ERROR;
goto cleanup;
}
/* Convert to string for sending */
pubkey_blob = ssh_string_new(ssh_buffer_get_len(client_pubkey));
if (pubkey_blob == NULL) {
session->session_state = SSH_SESSION_STATE_ERROR;
rc = SSH_ERROR;
goto cleanup;
}
ssh_string_fill(pubkey_blob,
ssh_buffer_get(client_pubkey),
ssh_buffer_get_len(client_pubkey));
/* Send the hybrid public key to server */
rc = ssh_buffer_pack(session->out_buffer,
"bS",
SSH2_MSG_KEX_HYBRID_INIT,
pubkey_blob);
if (rc != SSH_OK) {
session->session_state = SSH_SESSION_STATE_ERROR;
rc = SSH_ERROR;
goto cleanup;
}
session->dh_handshake_state = DH_STATE_INIT_SENT;
ssh_packet_set_callbacks(session, &ssh_mlkem768x25519_client_callbacks);
rc = ssh_packet_send(session);
if (rc == SSH_ERROR) {
ssh_set_error(session, SSH_FATAL, "Failed to send SSH_MSG_KEX_ECDH_INIT");
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
cleanup:
ssh_buffer_free(client_pubkey);
ssh_string_free(pubkey_blob);
return rc;
}
static SSH_PACKET_CALLBACK(ssh_packet_client_mlkem768x25519_reply)
{
struct ssh_crypto_struct *crypto = session->next_crypto;
ssh_string s_server_blob = NULL;
ssh_string s_pubkey_blob = NULL;
ssh_string s_signature = NULL;
const unsigned char *server_data = NULL;
unsigned char mlkem_shared_secret[MLKEM768_SHARED_SECRET_SIZE];
unsigned char curve25519_shared_secret[CURVE25519_PUBKEY_SIZE];
unsigned char combined_secret[MLKEM768X25519_SHARED_SECRET_SIZE];
unsigned char hashed_secret[SHA256_DIGEST_LEN];
size_t server_blob_len;
int rc;
(void)type;
(void)user;
SSH_LOG(SSH_LOG_TRACE, "Received ML-KEM768x25519 server reply");
ssh_client_mlkem768x25519_remove_callbacks(session);
s_pubkey_blob = ssh_buffer_get_ssh_string(packet);
if (s_pubkey_blob == NULL) {
ssh_set_error(session, SSH_FATAL, "No public key in packet");
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
rc = ssh_dh_import_next_pubkey_blob(session, s_pubkey_blob);
if (rc != 0) {
ssh_set_error(session, SSH_FATAL, "Failed to import next public key");
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
/* Get server blob containing ML-KEM768 ciphertext + Curve25519 pubkey */
s_server_blob = ssh_buffer_get_ssh_string(packet);
if (s_server_blob == NULL) {
ssh_set_error(session, SSH_FATAL, "No server blob in packet");
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
server_data = ssh_string_data(s_server_blob);
server_blob_len = ssh_string_len(s_server_blob);
/* Expect ML-KEM768 ciphertext + Curve25519 pubkey */
if (server_blob_len != MLKEM768X25519_SERVER_RESPONSE_SIZE) {
ssh_set_error(session, SSH_FATAL, "Invalid server blob size");
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
/* Store ML-KEM768 ciphertext for sessionid calculation */
memcpy(crypto->mlkem768_ciphertext, server_data, MLKEM768_CIPHERTEXT_SIZE);
/* Decapsulate ML-KEM768 shared secret */
rc = mlkem768_decapsulate(crypto->mlkem768_client_privkey,
crypto->mlkem768_ciphertext,
mlkem_shared_secret);
if (rc != SSH_OK) {
ssh_set_error(session, SSH_FATAL, "ML-KEM768 decapsulation failed");
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
/* Store server Curve25519 public key for shared secret computation */
memcpy(crypto->curve25519_server_pubkey,
server_data + MLKEM768_CIPHERTEXT_SIZE,
CURVE25519_PUBKEY_SIZE);
/* Derive Curve25519 shared secret using existing libssh function */
rc = ssh_curve25519_create_k(session, curve25519_shared_secret);
if (rc != SSH_OK) {
ssh_set_error(session, SSH_FATAL, "Curve25519 ECDH failed");
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
/* Combine secrets: ML-KEM768 + Curve25519 for hybrid approach */
memcpy(combined_secret, mlkem_shared_secret, MLKEM768_SHARED_SECRET_SIZE);
memcpy(combined_secret + MLKEM768_SHARED_SECRET_SIZE,
curve25519_shared_secret,
CURVE25519_PUBKEY_SIZE);
sha256(combined_secret, MLKEM768X25519_SHARED_SECRET_SIZE, hashed_secret);
bignum_bin2bn(hashed_secret, SHA256_DIGEST_LEN, &crypto->shared_secret);
if (crypto->shared_secret == NULL) {
ssh_set_error(session, SSH_FATAL, "Failed to create shared secret bignum");
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
/* Get signature for verification */
s_signature = ssh_buffer_get_ssh_string(packet);
if (s_signature == NULL) {
ssh_set_error(session, SSH_FATAL, "No signature in packet");
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
crypto->dh_server_signature = s_signature;
s_signature = NULL;
/* Send the MSG_NEWKEYS */
rc = ssh_packet_send_newkeys(session);
if (rc == SSH_ERROR) {
ssh_set_error(session, SSH_FATAL, "Failed to send SSH_MSG_NEWKEYS");
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
cleanup:
/* Clear sensitive data */
explicit_bzero(mlkem_shared_secret, sizeof(mlkem_shared_secret));
explicit_bzero(curve25519_shared_secret, sizeof(curve25519_shared_secret));
explicit_bzero(combined_secret, sizeof(combined_secret));
explicit_bzero(hashed_secret, sizeof(hashed_secret));
ssh_string_free(s_pubkey_blob);
ssh_string_free(s_server_blob);
ssh_string_free(s_signature);
return SSH_PACKET_USED;
}
void ssh_client_mlkem768x25519_remove_callbacks(ssh_session session)
{
ssh_packet_remove_callbacks(session, &ssh_mlkem768x25519_client_callbacks);
}
#ifdef WITH_SERVER
static SSH_PACKET_CALLBACK(ssh_packet_server_mlkem768x25519_init);
static ssh_packet_callback dh_server_callbacks[] = {
ssh_packet_server_mlkem768x25519_init,
};
static struct ssh_packet_callbacks_struct ssh_mlkem768x25519_server_callbacks =
{
.start = SSH2_MSG_KEX_HYBRID_INIT,
.n_callbacks = 1,
.callbacks = dh_server_callbacks,
.user = NULL,
};
static SSH_PACKET_CALLBACK(ssh_packet_server_mlkem768x25519_init)
{
struct ssh_crypto_struct *crypto = session->next_crypto;
ssh_string client_pubkey_blob = NULL;
ssh_string server_pubkey_blob = NULL;
ssh_buffer server_response = NULL;
const unsigned char *client_data = NULL;
unsigned char mlkem_shared_secret[MLKEM768_SHARED_SECRET_SIZE];
unsigned char curve25519_shared_secret[CURVE25519_PUBKEY_SIZE];
unsigned char combined_secret[MLKEM768X25519_SHARED_SECRET_SIZE];
unsigned char mlkem_ciphertext[MLKEM768_CIPHERTEXT_SIZE];
unsigned char hashed_secret[SHA256_DIGEST_LEN];
size_t client_blob_len;
ssh_key privkey = NULL;
enum ssh_digest_e digest = SSH_DIGEST_AUTO;
ssh_string sig_blob = NULL;
ssh_string server_hostkey_blob = NULL;
int rc = SSH_ERROR;
(void)type;
(void)user;
SSH_LOG(SSH_LOG_TRACE, "Received ML-KEM768x25519 client init");
ssh_packet_remove_callbacks(session, &ssh_mlkem768x25519_server_callbacks);
/* Get client hybrid public key: ML-KEM768 + Curve25519 */
client_pubkey_blob = ssh_buffer_get_ssh_string(packet);
if (client_pubkey_blob == NULL) {
ssh_set_error(session, SSH_FATAL, "No client public key in packet");
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
client_data = ssh_string_data(client_pubkey_blob);
client_blob_len = ssh_string_len(client_pubkey_blob);
/* Expect ML-KEM768 pubkey + Curve25519 pubkey */
if (client_blob_len != MLKEM768X25519_CLIENT_PUBKEY_SIZE) {
ssh_set_error(session, SSH_FATAL, "Invalid client public key size");
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
/* Extract client ML-KEM768 public key */
memcpy(crypto->mlkem768_client_pubkey,
client_data,
MLKEM768_PUBLICKEY_SIZE);
/* Extract client Curve25519 public key */
memcpy(crypto->curve25519_client_pubkey,
client_data + MLKEM768_PUBLICKEY_SIZE,
CURVE25519_PUBKEY_SIZE);
/* Generate server Curve25519 keypair */
rc = ssh_curve25519_init(session);
if (rc != SSH_OK) {
ssh_set_error(session, SSH_FATAL, "Failed to generate server Curve25519 key");
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
/* Derive Curve25519 shared secret */
rc = ssh_curve25519_create_k(session, curve25519_shared_secret);
if (rc != SSH_OK) {
ssh_set_error(session, SSH_FATAL, "Curve25519 ECDH failed");
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
/* Encapsulate ML-KEM768 shared secret using client's public key */
rc = mlkem768_encapsulate(client_data, mlkem_ciphertext, mlkem_shared_secret);
if (rc != SSH_OK) {
ssh_set_error(session, SSH_FATAL, "ML-KEM768 encapsulation failed");
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
/* Store ML-KEM768 ciphertext for sessionid calculation */
memcpy(crypto->mlkem768_ciphertext, mlkem_ciphertext, MLKEM768_CIPHERTEXT_SIZE);
/* Combine secrets: ML-KEM768 + Curve25519 for hybrid approach */
memcpy(combined_secret, mlkem_shared_secret, MLKEM768_SHARED_SECRET_SIZE);
memcpy(combined_secret + MLKEM768_SHARED_SECRET_SIZE,
curve25519_shared_secret,
CURVE25519_PUBKEY_SIZE);
sha256(combined_secret, MLKEM768X25519_SHARED_SECRET_SIZE, hashed_secret);
/* Store the combined secret */
bignum_bin2bn(hashed_secret, SHA256_DIGEST_LEN, &crypto->shared_secret);
if (crypto->shared_secret == NULL) {
ssh_set_error(session, SSH_FATAL, "Failed to create shared secret bignum");
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
/* Create server response: ML-KEM768 ciphertext + Curve25519 pubkey */
server_response = ssh_buffer_new();
if (server_response == NULL) {
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
rc = ssh_buffer_pack(server_response,
"PP",
MLKEM768_CIPHERTEXT_SIZE,
mlkem_ciphertext,
CURVE25519_PUBKEY_SIZE,
crypto->curve25519_server_pubkey);
if (rc != SSH_OK) {
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
/* Convert to string for sending */
server_pubkey_blob = ssh_string_new(ssh_buffer_get_len(server_response));
if (server_pubkey_blob == NULL) {
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
ssh_string_fill(server_pubkey_blob,
ssh_buffer_get(server_response),
ssh_buffer_get_len(server_response));
/* Add MSG_KEX_ECDH_REPLY header */
rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_HYBRID_REPLY);
if (rc < 0) {
ssh_set_error_oom(session);
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
/* Get server host key */
rc = ssh_get_key_params(session, &privkey, &digest);
if (rc == SSH_ERROR) {
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
/* Build session ID */
rc = ssh_make_sessionid(session);
if (rc != SSH_OK) {
ssh_set_error(session, SSH_FATAL, "Could not create a session id");
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
rc = ssh_dh_get_next_server_publickey_blob(session, &server_hostkey_blob);
if (rc != 0) {
ssh_set_error(session, SSH_FATAL, "Could not export server public key");
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
/* Add server host key to output */
rc = ssh_buffer_add_ssh_string(session->out_buffer, server_hostkey_blob);
SSH_STRING_FREE(server_hostkey_blob);
if (rc < 0) {
ssh_set_error_oom(session);
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
/* Add server response (ciphertext + pubkey) */
rc = ssh_buffer_add_ssh_string(session->out_buffer, server_pubkey_blob);
if (rc < 0) {
ssh_set_error_oom(session);
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
/* Sign the exchange hash */
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey, digest);
if (sig_blob == NULL) {
ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
/* Add signature */
rc = ssh_buffer_add_ssh_string(session->out_buffer, sig_blob);
SSH_STRING_FREE(sig_blob);
if (rc < 0) {
ssh_set_error_oom(session);
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
rc = ssh_packet_send(session);
if (rc == SSH_ERROR) {
ssh_set_error(session, SSH_FATAL, "Failed to send SSH_MSG_KEX_ECDH_REPLY");
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
/* Send the MSG_NEWKEYS */
rc = ssh_packet_send_newkeys(session);
if (rc == SSH_ERROR) {
ssh_set_error(session, SSH_FATAL, "Failed to send SSH_MSG_NEWKEYS");
session->session_state = SSH_SESSION_STATE_ERROR;
goto cleanup;
}
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
cleanup:
/* Clear sensitive data */
explicit_bzero(mlkem_shared_secret, sizeof(mlkem_shared_secret));
explicit_bzero(curve25519_shared_secret, sizeof(curve25519_shared_secret));
explicit_bzero(combined_secret, sizeof(combined_secret));
explicit_bzero(hashed_secret, sizeof(hashed_secret));
ssh_string_free(client_pubkey_blob);
ssh_string_free(server_pubkey_blob);
ssh_buffer_free(server_response);
return SSH_PACKET_USED;
}
void ssh_server_mlkem768x25519_init(ssh_session session)
{
SSH_LOG(SSH_LOG_TRACE, "Setting up ML-KEM768x25519 server callbacks");
ssh_packet_set_callbacks(session, &ssh_mlkem768x25519_server_callbacks);
}
#endif /* WITH_SERVER */

View File

@@ -31,14 +31,13 @@
#else
#include <winsock2.h>
#endif
#include "libssh/config_parser.h"
#include "libssh/misc.h"
#include "libssh/options.h"
#include "libssh/pki.h"
#include <sys/types.h>
#include "libssh/pki_priv.h"
#include "libssh/priv.h"
#include "libssh/session.h"
#include <sys/types.h>
#include "libssh/misc.h"
#include "libssh/options.h"
#include "libssh/config_parser.h"
#ifdef WITH_SERVER
#include "libssh/server.h"
#include "libssh/bind.h"
@@ -593,10 +592,10 @@ int ssh_options_set_algo(ssh_session session,
* - SSH_OPTIONS_RSA_MIN_SIZE
* Set the minimum RSA key size in bits to be accepted by the
* client for both authentication and hostkey verification.
* The values under 1024 bits are not accepted even with this
* The values under 768 bits are not accepted even with this
* configuration option as they are considered completely broken.
* Setting 0 will revert the value to defaults.
* Default is 3072 bits or 2048 bits in FIPS mode.
* Default is 1024 bits or 2048 bits in FIPS mode.
* (int)
* - SSH_OPTIONS_IDENTITY_AGENT
@@ -1289,13 +1288,11 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
/* (*x == 0) is allowed as it is used to revert to default */
if (*x > 0 && *x < RSA_MIN_KEY_SIZE) {
ssh_set_error(session,
SSH_REQUEST_DENIED,
if (*x > 0 && *x < 768) {
ssh_set_error(session, SSH_REQUEST_DENIED,
"The provided value (%d) for minimal RSA key "
"size is too small. Use at least %d bits.",
*x,
RSA_MIN_KEY_SIZE);
"size is too small. Use at least 768 bits.",
*x);
return -1;
}
session->opts.rsa_min_size = *x;
@@ -1817,8 +1814,6 @@ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv)
*
* @param filename The options file to use, if NULL the default
* ~/.ssh/config and /etc/ssh/ssh_config will be used.
* If complied with support for hermetic-usr,
* /usr/etc/ssh/ssh_config will be used last.
*
* @return 0 on success, < 0 on error.
*
@@ -1826,63 +1821,48 @@ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv)
*/
int ssh_options_parse_config(ssh_session session, const char *filename)
{
char *expanded_filename = NULL;
int r;
FILE *fp = NULL;
char *expanded_filename = NULL;
int r;
if (session == NULL) {
return -1;
}
if (session->opts.host == NULL) {
ssh_set_error_invalid(session);
return -1;
}
if (session == NULL) {
return -1;
}
if (session->opts.host == NULL) {
ssh_set_error_invalid(session);
return -1;
}
if (session->opts.sshdir == NULL) {
r = ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL);
if (r < 0) {
ssh_set_error_oom(session);
return -1;
}
}
if (session->opts.sshdir == NULL) {
r = ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL);
if (r < 0) {
ssh_set_error_oom(session);
return -1;
}
}
/* set default filename */
if (filename == NULL) {
expanded_filename = ssh_path_expand_escape(session, "%d/config");
} else {
expanded_filename = ssh_path_expand_escape(session, filename);
}
if (expanded_filename == NULL) {
return -1;
}
/* set default filename */
if (filename == NULL) {
expanded_filename = ssh_path_expand_escape(session, "%d/config");
} else {
expanded_filename = ssh_path_expand_escape(session, filename);
}
if (expanded_filename == NULL) {
return -1;
}
r = ssh_config_parse_file(session, expanded_filename);
if (r < 0) {
goto out;
}
if (filename == NULL) {
if ((fp = fopen(GLOBAL_CLIENT_CONFIG, "r")) != NULL) {
filename = GLOBAL_CLIENT_CONFIG;
#ifdef USR_GLOBAL_CLIENT_CONFIG
} else if ((fp = fopen(USR_GLOBAL_CLIENT_CONFIG, "r")) != NULL) {
filename = USR_GLOBAL_CLIENT_CONFIG;
#endif
}
r = ssh_config_parse_file(session, expanded_filename);
if (r < 0) {
goto out;
}
if (filename == NULL) {
r = ssh_config_parse_file(session, GLOBAL_CLIENT_CONFIG);
}
if (fp) {
SSH_LOG(SSH_LOG_PACKET,
"Reading configuration data from %s",
filename);
r = ssh_config_parse(session, fp, true);
fclose(fp);
}
}
/* Do not process the default configuration as part of connection again */
session->opts.config_processed = true;
/* Do not process the default configuration as part of connection again */
session->opts.config_processed = true;
out:
free(expanded_filename);
return r;
free(expanded_filename);
return r;
}
int ssh_options_apply(ssh_session session)
@@ -1988,10 +1968,10 @@ int ssh_options_apply(ssh_session session)
* it with ssh expansion of ssh escape characters.
*/
tmp = ssh_path_expand_escape(session, id);
free(id);
if (tmp == NULL) {
return -1;
}
free(id);
}
/* use append to keep the order at first call and use prepend
@@ -2002,7 +1982,6 @@ int ssh_options_apply(ssh_session session)
rc = ssh_list_append(session->opts.identity, tmp);
}
if (rc != SSH_OK) {
free(tmp);
return -1;
}
}
@@ -2014,14 +1993,13 @@ int ssh_options_apply(ssh_session session)
char *id = tmp;
tmp = ssh_path_expand_escape(session, id);
free(id);
if (tmp == NULL) {
return -1;
}
free(id);
rc = ssh_list_append(session->opts.certificate, tmp);
if (rc != SSH_OK) {
free(tmp);
return -1;
}
}
@@ -2201,11 +2179,11 @@ static int ssh_bind_set_algo(ssh_bind sshbind,
* - SSH_BIND_OPTIONS_RSA_MIN_SIZE
* Set the minimum RSA key size in bits to be accepted by
* the server for both authentication and hostkey
* operations. The values under 1024 bits are not accepted
* operations. The values under 768 bits are not accepted
* even with this configuration option as they are
* considered completely broken. Setting 0 will revert
* the value to defaults.
* Default is 3072 bits or 2048 bits in FIPS mode.
* Default is 1024 bits or 2048 bits in FIPS mode.
* (int)
*
*
@@ -2290,9 +2268,6 @@ ssh_bind_options_set(ssh_bind sshbind,
SSH_FATAL,
"The host key size %d is too small.",
ssh_key_size(key));
if (type != SSH_BIND_OPTIONS_IMPORT_KEY) {
SSH_KEY_FREE(key);
}
return -1;
}
key_type = ssh_key_type(key);
@@ -2338,11 +2313,6 @@ ssh_bind_options_set(ssh_bind sshbind,
ssh_key_free(key);
return -1;
}
} else if (type == SSH_BIND_OPTIONS_IMPORT_KEY_STR) {
if (bind_key_loc == NULL) {
ssh_key_free(key);
return -1;
}
} else {
if (bind_key_loc == NULL) {
return -1;
@@ -2593,13 +2563,12 @@ ssh_bind_options_set(ssh_bind sshbind,
/* (*x == 0) is allowed as it is used to revert to default */
if (*x > 0 && *x < RSA_MIN_KEY_SIZE) {
if (*x > 0 && *x < 768) {
ssh_set_error(sshbind,
SSH_REQUEST_DENIED,
"The provided value (%d) for minimal RSA key "
"size is too small. Use at least %d bits.",
*x,
RSA_MIN_KEY_SIZE);
"size is too small. Use at least 768 bits.",
*x);
return -1;
}
sshbind->rsa_min_size = *x;
@@ -2737,13 +2706,7 @@ int ssh_bind_options_parse_config(ssh_bind sshbind, const char *filename)
/* If the global default configuration hasn't been processed yet, process it
* before the provided configuration. */
if (!(sshbind->config_processed)) {
if (ssh_file_readaccess_ok(GLOBAL_BIND_CONFIG)) {
rc = ssh_bind_config_parse_file(sshbind, GLOBAL_BIND_CONFIG);
#ifdef USR_GLOBAL_BIND_CONFIG
} else {
rc = ssh_bind_config_parse_file(sshbind, USR_GLOBAL_BIND_CONFIG);
#endif
}
rc = ssh_bind_config_parse_file(sshbind, GLOBAL_BIND_CONFIG);
if (rc != 0) {
return rc;
}

View File

@@ -294,7 +294,6 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
* or session_state == SSH_SESSION_STATE_INITIAL_KEX
* - dh_handshake_state == DH_STATE_INIT
* or dh_handshake_state == DH_STATE_INIT_SENT (re-exchange)
* or dh_handshake_state == DH_STATE_REQUEST_SENT (dh-gex)
* or dh_handshake_state == DH_STATE_FINISHED (re-exchange)
*
* Transitions:
@@ -314,7 +313,6 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
if ((session->dh_handshake_state != DH_STATE_INIT) &&
(session->dh_handshake_state != DH_STATE_INIT_SENT) &&
(session->dh_handshake_state != DH_STATE_REQUEST_SENT) &&
(session->dh_handshake_state != DH_STATE_FINISHED))
{
rc = SSH_PACKET_DENIED;
@@ -352,7 +350,7 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
break;
case SSH2_MSG_KEXDH_INIT: // 30
// SSH2_MSG_KEX_ECDH_INIT: // 30
// SSH2_MSG_KEX_HYBRID_INIT: // 30
// SSH2_MSG_ECMQV_INIT: // 30
// SSH2_MSG_KEX_DH_GEX_REQUEST_OLD: // 30
/* Server only */
@@ -388,7 +386,7 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
break;
case SSH2_MSG_KEXDH_REPLY: // 31
// SSH2_MSG_KEX_ECDH_REPLY: // 31
// SSH2_MSG_KEX_HYBRID_REPLY: // 31
// SSH2_MSG_ECMQV_REPLY: // 31
// SSH2_MSG_KEX_DH_GEX_GROUP: // 31
/* Client only */
@@ -1160,7 +1158,7 @@ ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
uint32_t lenfield_blocksize = 8;
size_t current_macsize = 0;
uint8_t *ptr = NULL;
ssize_t to_be_read;
long to_be_read;
int rc;
uint8_t *cleartext_packet = NULL;
uint8_t *packet_second_block = NULL;
@@ -1270,7 +1268,7 @@ ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
/* remote sshd sends invalid sizes? */
ssh_set_error(session,
SSH_FATAL,
"Given numbers of bytes left to be read < 0 (%zd)!",
"Given numbers of bytes left to be read < 0 (%ld)!",
to_be_read);
goto error;
}
@@ -1288,7 +1286,7 @@ ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
/* give up, not enough data in buffer */
SSH_LOG(SSH_LOG_PACKET,
"packet: partial packet (read len) "
"[len=%" PRIu32 ", receivedlen=%zu, to_be_read=%zd]",
"[len=%" PRIu32 ", receivedlen=%zu, to_be_read=%ld]",
packet_len,
receivedlen,
to_be_read);
@@ -1302,7 +1300,7 @@ ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
/* remaining encrypted bytes from the packet, MAC not included */
packet_remaining = packet_len - (packet_offset - sizeof(uint32_t));
cleartext_packet = ssh_buffer_allocate(session->in_buffer,
(uint32_t)packet_remaining);
packet_remaining);
if (cleartext_packet == NULL) {
goto error;
}
@@ -1478,7 +1476,6 @@ ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
session->packet_state = PACKET_STATE_INIT;
if (processed < receivedlen) {
size_t num;
/* Handle a potential packet left in socket buffer */
SSH_LOG(SSH_LOG_PACKET,
"Processing %zu bytes left in socket buffer",
@@ -1486,10 +1483,9 @@ ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
ptr = ((uint8_t*)data) + processed;
num = ssh_packet_socket_callback(ptr,
receivedlen - processed,
user);
processed += num;
rc = ssh_packet_socket_callback(ptr, receivedlen - processed,
user);
processed += rc;
}
ok = ssh_packet_need_rekey(session, 0);
@@ -1858,7 +1854,7 @@ static int packet_send2(ssh_session session)
if (hmac != NULL) {
rc = ssh_buffer_add_data(session->out_buffer,
hmac,
(uint32_t)hmac_digest_len(hmac_type));
hmac_digest_len(hmac_type));
if (rc < 0) {
goto error;
}

View File

@@ -291,6 +291,7 @@ SSH_PACKET_CALLBACK(ssh_packet_ext_info)
for (i = 0; i < nr_extensions; i++) {
char *name = NULL;
char *value = NULL;
int cmp;
rc = ssh_buffer_unpack(packet, "ss", &name, &value);
if (rc != SSH_OK) {
@@ -298,7 +299,8 @@ SSH_PACKET_CALLBACK(ssh_packet_ext_info)
return SSH_PACKET_USED;
}
if (strcmp(name, "server-sig-algs") == 0) {
cmp = strcmp(name, "server-sig-algs");
if (cmp == 0) {
/* TODO check for NULL bytes */
SSH_LOG(SSH_LOG_PACKET, "Extension: %s=<%s>", name, value);
@@ -311,9 +313,6 @@ SSH_PACKET_CALLBACK(ssh_packet_ext_info)
if (rc == 1) {
session->extensions |= SSH_EXT_SIG_RSA_SHA256;
}
} else if (strcmp(name, "publickey-hostbound@openssh.com") == 0) {
SSH_LOG(SSH_LOG_PACKET, "Extension: %s=<%s>", name, value);
session->extensions |= SSH_EXT_PUBLICKEY_HOSTBOUND;
} else {
SSH_LOG(SSH_LOG_PACKET, "Unknown extension: %s", name);
}

View File

@@ -126,10 +126,11 @@ ssh_pcap_file ssh_pcap_file_new(void)
{
struct ssh_pcap_file_struct *pcap = NULL;
pcap = calloc(1, sizeof(struct ssh_pcap_file_struct));
pcap = malloc(sizeof(struct ssh_pcap_file_struct));
if (pcap == NULL) {
return NULL;
}
ZERO_STRUCTP(pcap);
return pcap;
}
@@ -295,13 +296,12 @@ void ssh_pcap_file_free(ssh_pcap_file pcap)
*/
ssh_pcap_context ssh_pcap_context_new(ssh_session session)
{
ssh_pcap_context ctx = NULL;
ctx = calloc(1, sizeof(struct ssh_pcap_context_struct));
ssh_pcap_context ctx = (struct ssh_pcap_context_struct *)malloc(sizeof(struct ssh_pcap_context_struct));
if (ctx == NULL) {
ssh_set_error_oom(session);
return NULL;
}
ZERO_STRUCTP(ctx);
ctx->session = session;
return ctx;
}

1310
src/pki.c

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More