Compare commits

..

188 Commits

Author SHA1 Message Date
Andreas Schneider
c91f530610 Bump version to 0.8.3 2018-09-21 09:56:06 +02:00
Andreas Schneider
69740ea841 cmake: Bump library version
(cherry picked from commit 9c37c8c5a5)
2018-09-20 17:23:42 +02:00
Chris Townsend
1bb7895cd9 sftpserver: Support some openssh extensions
Add support for "hardlink@openssh.com" and
"posix-rename@openssh.com" extensions.

Signed-off-by: Chris Townsend <christopher.townsend@canonical.com>
Signed-off-by: Alberto Aguirre <albaguirre@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 6c56c1e0d7)
2018-09-20 17:23:41 +02:00
Andreas Schneider
a028b88aed pki: Use strndup in ssh_pki_export_privkey_base64()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit e4711c469f)
2018-09-20 17:23:41 +02:00
Andreas Schneider
8a25f6bb07 tests: Add a test for ssh_pki_export_privkey_base64()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8410f43d8b)
2018-09-20 17:23:41 +02:00
DavidWed
2db453db16 pki: Add ssh_pki_export_privkey_base64()
Fixes T53

Signed-off-by: DavidWedderwille <davidwe@posteo.de>
Reviewed-by: Andreas Schneider <asn@samba.org>
(cherry picked from commit d0ce2d1ecd)
2018-09-20 17:23:41 +02:00
Andreas Schneider
03134c2932 tests: Add test for ssh_get_fingerprint_hash()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 5a198732a5)
2018-09-20 17:23:41 +02:00
Andreas Schneider
95d0c143b3 dh: Use ssh_get_fingerprint_hash() in ssh_print_hash()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 92aa2cf496)
2018-09-20 17:23:41 +02:00
Andreas Schneider
3dcdafa6d7 dh: Add ssh_get_fingerprint_hash()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit bbed139eca)
2018-09-20 17:23:41 +02:00
Anderson Toshiyuki Sasaki
75c446c529 dh: Removed duplicated code
The code for calculating SHA 512 in ssh_make_sessionid() had been
duplicated; the cases were unified.

Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
(cherry picked from commit 0eab270754)
2018-09-20 16:35:05 +02:00
Anderson Toshiyuki Sasaki
4a9c32fc81 dh: Add diffie-hellman-group18-sha512 support
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
(cherry picked from commit 71594f9d6c)
2018-09-20 16:35:05 +02:00
Andreas Schneider
1634c5a91a buffer: Don't call va_end() twice
This is handled in the cleanup.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 2ae2baf9ca)
2018-09-20 16:35:04 +02:00
Andreas Schneider
dfa7593c27 examples: Reformat authenticaton.c
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 4c47719d98)
2018-09-20 16:35:04 +02:00
Andreas Schneider
034af66338 sftp: Include stdint.h
Thanks to Apex Liu

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit a30d542207)
2018-09-19 12:42:51 +02:00
Anderson Toshiyuki Sasaki
55c7b93a0a dh: Add diffie-hellman-group16-sha512 support
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit d9d3b65df2)
2018-09-19 12:42:50 +02:00
Harald Sitter
4818cf5606 sftp: fix buffer_unpack argument to be char** rather than char*
Summary:
buffer variable 's' gets unpacked as char**, the previous code was passing
a char* causing segfaults on all readlink calls inside the unpacking code

Test Plan:
- without patchy examples/samplesftp segfaults in readlink
- with patchy it doesn't

Reviewers: asn

Differential Revision: https://bugs.libssh.org/D14

Signed-off-by: Harald Sitter <sitter@kde.org>
(cherry picked from commit 97cb302c0e)
2018-09-19 11:56:10 +02:00
Andreas Schneider
316a3a42a4 buffer: Do cleanup if ssh_buffer_unpack() fails in the first loop
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 90373d8394)
2018-09-19 11:56:10 +02:00
Andreas Schneider
546d9da185 buffer: Fix invalid memory access in ssh_buffer_unpack()
Found by oss-fuzz.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 07f7fa7806)
2018-09-19 11:56:09 +02:00
Andreas Schneider
3b7d997b54 tests: Add OK: and a new line to ssh_ping
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 5123f7955b)
2018-09-19 11:56:09 +02:00
Jakub Jelen
129744692c tests: Wait for the server to start
The previous timeout of 500 ms was not enough on slower machines or
while running the tests under valgrind. On much faster machines the
sleep() was bringing unnecessary overhead.

This method opens simple connection to the server verifying it is ready
to accept the connection from the test for 5 seconds. It the server
does not start until then, it fails the tests during initialization,
rather than leaving the cases to run against missing server.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c15ad753a7)
2018-09-18 18:09:15 +02:00
Anderson Toshiyuki Sasaki
83f6ce0928 tests: Add null checks in torture_threads_pki_rsa.c
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 63aa274f4b)
2018-09-18 13:30:29 +02:00
Anderson Toshiyuki Sasaki
b5c7f07064 tests: Add null checks in torture_pki_rsa.c
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8170e30073)
2018-09-18 13:30:29 +02:00
Anderson Toshiyuki Sasaki
223ba36d54 tests: Add null checks in torture_pki_ed25519.c
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 77f58a225f)
2018-09-18 13:30:29 +02:00
Anderson Toshiyuki Sasaki
9141e9d4fe tests: Add null checks in torture_pki_ecdsa.c
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 48459c37f6)
2018-09-18 13:30:29 +02:00
Anderson Toshiyuki Sasaki
ead42db7c8 tests: Add null checks and frees in torture_pki_dsa.c
These frees are unnecessary because the negative tests should not
allocate the keys, but the static analyser reports memory leak errors.

Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 31f24ed23e)
2018-09-18 13:30:29 +02:00
Anderson Toshiyuki Sasaki
d5a68bedfd tests: Add return and null checks in torture_options.c
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 82c3faa44d)
2018-09-18 13:30:29 +02:00
Anderson Toshiyuki Sasaki
4307489702 tests: Add null checks in torture_config.c
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 7c75e76d10)
2018-09-18 13:30:29 +02:00
Anderson Toshiyuki Sasaki
f0da1f2e03 examples: Fix code style in samplesftp.c
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit f246e31ca0)
2018-09-18 13:30:29 +02:00
Anderson Toshiyuki Sasaki
50477cb80b examples: Fixed possible memory leak in samplesftp.c
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 7390db6bbb)
2018-09-18 13:30:29 +02:00
Andreas Schneider
ded4a81ffe sftp: Fix a possible null pointer dereference
CID 1395721

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit cc83b463ce)
2018-09-18 13:30:29 +02:00
Jakub Jelen
c2bc4e62dd tests: Verify we can read public key from OpenSSH container
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 39975fdd6d)
2018-09-18 10:17:32 +02:00
Jakub Jelen
f7ab481b22 pki: Implement reading public key from OpenSSH private key container
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 1226de875b)
2018-09-18 10:17:32 +02:00
Jakub Jelen
628b529a91 Revert "pkd: Generate host keys in old format"
This is no longer needed since libssh can read the private keys
in new OpenSSH format.

This reverts commit 100c9c98ce.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 2307be32cf)
2018-09-18 10:17:32 +02:00
Jakub Jelen
7e25963130 tests: Verify the keys loaded from new OpenSSH format
This runs the same test that are ran on the legacy PEM files
also with the new OpenSSH key files.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit eaaa4131de)
2018-09-18 10:17:32 +02:00
Jakub Jelen
91d8f1a256 pki: Allow reading keys in new OpenSSH format
This implements reading the OpenSSH key format accross the
cryptographic backends. Most of the code is shared and moved
to pki.c, just the building of the keys is implemented in
pki_privkey_build_*() functions.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 39102224b2)
2018-09-18 10:17:31 +02:00
Jakub Jelen
61dcc023b0 tests: Provide testing keys also in OpenSSH format
This extends the torture API to provide a way to request
keys in different formats. This extends the keys with
private keys in the new OpenSSH format (default since
OpenSSH 7.8).

This also needs modifications to the ed25519 tests, which
do not support PEM format and expected the new format out of the
box.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit e365aed6d2)
2018-09-18 10:17:31 +02:00
Jakub Jelen
4468a78ee2 pki: Use unpack to simplify public key reading
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit d23bda8181)
2018-09-18 10:17:31 +02:00
Jakub Jelen
8f18063b6d buffer: Make sure unpack of secure buffers securely cleans up
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 86d521cbe7)
2018-09-18 10:17:31 +02:00
Andreas Schneider
a167faee3e libmbedcrypto: Fix creating evp hash
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 856dc698a9)
2018-09-18 10:17:31 +02:00
Jakub Jelen
0e8f6aaee5 buffer: Reformat ssh_buffer_get_ssh_string
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 4d09c6dc31)
2018-09-17 19:00:31 +02:00
Jakub Jelen
f0a1b94d0d tests: Use stdbool for with_passphrase argument
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 03a66b8599)
2018-09-17 19:00:31 +02:00
Jakub Jelen
5d1ddf5920 pki_crypto: Clarify that memory passed with set0 is managed by openssl objects
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c04eac40f3)
2018-09-17 19:00:31 +02:00
Jakub Jelen
152ae623c2 pki_mbedcrypto: pki_pubkey_build_rsa: properly clean up on error
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8cc0672c0c)
2018-09-17 19:00:31 +02:00
Jakub Jelen
e7bd9d02bc pki: Initialize pointers to NULL
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8f7214a584)
2018-09-17 19:00:31 +02:00
Jakub Jelen
9196639940 tests: Drop duplicate ed25519 key creation
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 9d2de880ec)
2018-09-17 19:00:31 +02:00
Jakub Jelen
786d7e39a3 buffer: Fix typo
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 039c066da5)
2018-09-17 19:00:31 +02:00
Jakub Jelen
c33710d112 tests: Verify the pubkey authentication works with ECDSA keys
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 6efbf7a30e)
2018-09-17 19:00:31 +02:00
Andreas Schneider
a14a80f35f auth: Fix ecdsa pubkey auth
Pair-Programmed-With: Jakub Jelen <jjelen@redhat.com>
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit e5170107c9)
2018-09-17 19:00:31 +02:00
Andreas Schneider
0389ff6d9d tests: Do not call sftp_canonicalize_path()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 30df04a8a5)
2018-09-17 19:00:31 +02:00
Andreas Schneider
8954fccfdb tests: Add a sftp benchmark test for write/read
The tests writes and reads a file of 128M.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit aaca395bd3)
2018-09-17 10:53:01 +02:00
Andreas Schneider
332df98fc9 sftp: Move the packet payload to the message
This reduces memory allocations and copying.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 0762057eb9)
2018-09-17 10:53:01 +02:00
Andreas Schneider
d4cc3f69c6 sftp: Use SSH_BUFFER_FREE in sftp_message_free()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 57153f6481)
2018-09-17 10:53:01 +02:00
Andreas Schneider
534c58c475 sftp: Reformat sftp_message_free()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 4c32befd93)
2018-09-17 10:53:01 +02:00
Andreas Schneider
84fd910423 sftp: Allocate a new buffer in sftp_packet_read() if needed
We will move the buffer to the message instead of duplicating the
memory.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit be8302e2f3)
2018-09-17 10:53:01 +02:00
Andreas Schneider
d51f77c2b1 sftp: Reformat sftp_read_and_dispatch()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 97d2e1f4cb)
2018-09-17 10:53:01 +02:00
Andreas Schneider
47376cbc77 sftp: Validate the packet handle before we allocate memory
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 12fc0ea1bf)
2018-09-17 10:53:01 +02:00
Andreas Schneider
85c3db3e89 sftp: Reformat sftp_get_message()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 573eab0d51)
2018-09-17 10:53:01 +02:00
Andreas Schneider
3f8a522c7f sftp: Use bool for is_eof in sftp_packet_read()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 0e317e612f)
2018-09-17 10:53:01 +02:00
Andreas Schneider
eb08802b7c sftp: Use 's' only in the scope it is needed
This revaled a bug when reading the packet type.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 01135703a3)
2018-09-17 10:53:01 +02:00
Andreas Schneider
dc587045bf sftp: Use 16K for the transfer buffer size
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c070414309)
2018-09-17 10:53:01 +02:00
Andreas Schneider
9b495b72c5 sftp: Get the packet type directly from the buffer
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit d2cc4eccc7)
2018-09-17 10:53:01 +02:00
Andreas Schneider
2ce6c56609 sftp: Limit packet size to 256 MB
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 38781f69b0)
2018-09-17 10:53:01 +02:00
Andreas Schneider
9caef95899 sftp: Directly read and validate the packet size from the bufffer
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit dc4faf9952)
2018-09-17 10:53:01 +02:00
Andreas Schneider
66c2630aaf sftp: Use read_packet from sftp handle
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit cbbc6ddcb6)
2018-09-17 10:53:01 +02:00
Andreas Schneider
b8f63ee2df sftp: Simplify the code for reading data
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit a7456bf4d5)
2018-09-17 10:53:01 +02:00
Andreas Schneider
68adb49996 sftp: Reformat sftp_packet_read()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit afc14fe003)
2018-09-17 10:53:01 +02:00
Andreas Schneider
12e94bfd18 sftp: Keep a ssh_packet for reading in the sftp handle
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 79a3fcac72)
2018-09-17 10:53:01 +02:00
Andreas Schneider
4fc3d7a27f sftp: Remove ZERO_STRUCTP from sftp_free()
The structure doesn't hold any sensitive data and this would be
optimized away anyway.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 945afaa6b4)
2018-09-17 10:53:01 +02:00
Andreas Schneider
466bb332c1 sftp: Reformat sftp_free()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit d840a05be3)
2018-09-17 10:53:01 +02:00
Andreas Schneider
ff25b45367 sftp: Reformat sftp_new()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 662c30eb72)
2018-09-17 10:53:01 +02:00
Andreas Schneider
df83f4fb57 include: Add SSH_BUFFER_FREE
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 29b5477849)
2018-09-17 10:53:01 +02:00
Andreas Schneider
5bda3ab9f6 cmake: Correctly detect if glob has gl_flags member
Thanks to Baruch Siach.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 2e8f2f03e7)
2018-09-17 10:53:01 +02:00
Andreas Schneider
9a057159a2 config: Fix size type
src/config.c:562:12: error: assuming signed overflow does not occur when
    simplifying conditional to constant [-Werror=strict-overflow]

         if (args < 1) {
            ^

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit ceecd3fd6f)
2018-09-06 09:25:05 +02:00
Andreas Schneider
9c0875dd5d cmake: Use -Wpedantic and remove -pedantic-errors
We get -Werror if -DPICKY_DEVELOPER=ON is set.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit bfd33ecf29)
2018-09-06 09:25:03 +02:00
Jakub Jelen
1fa5a2a504 tests: UsePrivilegeSeparation has no effect since OpenSSH 7.5
Additionally, we can already work around the privilege separation.

http://www.openssh.com/txt/release-7.5

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 56317caafc)
2018-09-05 21:57:40 +02:00
Jakub Jelen
a08a2f52fb tests: Do not trace sshd
OpenSSH's sshd does not work well under valgrind so lets avoid tracing it.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit ca4fb9c6f8)
2018-09-05 21:57:38 +02:00
Andreas Schneider
21d37f8605 cmake: Move CompilerFlags to own file
They need to be included before the project() call.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 91800eb243)
2018-09-05 21:57:35 +02:00
Andreas Schneider
e43586b4de cmake: Update defaults
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 2923ad59f9)
2018-09-05 21:57:24 +02:00
Jakub Jelen
dc7e1bdb39 tests: Verify the Match keyword from configuration file
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 556ad59a5a)
2018-09-05 12:39:02 +02:00
Jakub Jelen
03d559b066 tests: No need to restore log level now
Since the verbosity is now set from the setup phase, we do not
need to reset the verbosity, especially not to any arbirary value
such as WARNING.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit fcb203cb2d)
2018-09-05 12:39:02 +02:00
Jakub Jelen
3191c1f6be tests: Use global verbosity in tests
This allows adjusting the log level of config and options tests using
environment variable LIBSSH_VERBOSITY as it works in most of the other
tests.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 6dbcc21921)
2018-09-05 12:39:02 +02:00
Jakub Jelen
d46f01cb7c tests: Missing unlink
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 2eccd04ff6)
2018-09-05 12:39:02 +02:00
Jakub Jelen
04e290a19b config: Parse Match keyword
Amends f818e63f8, which introduced the constants and matching of this
configuration option, but did not implement the handling of the values
which was causing the configuration parser failing for certain
configurations.

This commit exposes match_pattern_list() from match.c

Red Hat Bugzilla:
https://bugzilla.redhat.com/show_bug.cgi?id=1624425

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit e9b44d26b1)
2018-09-05 12:39:02 +02:00
Jakub Jelen
bad407f5e2 config: Do not overwrite previously matched result in Host blocks
The match_hostname() expects comma separated list, while the Host
config keyword in openssh uses spaces separated list by default.
Therefore any subseqent match or negated match in space separated
list will overwrite the previous matches.

This also adjusts the tests to make sure both of the versions work.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 9f5f10552b)
2018-09-05 12:39:02 +02:00
Andreas Schneider
2787756efe tests: Define LIBSSH_STATIC for torture_cmocka
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 458bda8877)
2018-09-05 12:39:01 +02:00
Andreas Schneider
7b35afdf6b tests: Fix linking unit tests
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 3d35250c07)
2018-09-05 12:39:01 +02:00
Andreas Schneider
dba2903e38 channels: Allow infinite timeout for ssh_channel_read_timout()
This is also documented.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit ef06ef2c1b)
2018-09-05 12:39:01 +02:00
Andreas Schneider
965014b035 libsshpp: Initialize the string returned by getIssueBanner()
Fixes T13

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit ba1ff992ce)
2018-09-04 20:54:52 +02:00
Andreas Schneider
c4ec92f375 channels: Don't read from a closed channel
Fixes T76

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit e558827c4e)
2018-09-04 20:35:30 +02:00
Andreas Schneider
54cf9d1364 auth: Use calloc to allocate memory
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 1e195a232a)
2018-09-04 20:00:04 +02:00
Andreas Schneider
23ce6d7156 misc: Use C99 initializer to initialize string
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit d1cd914012)
2018-09-04 20:00:04 +02:00
Andreas Schneider
07473976e1 pki_container: Use string functions for cleanup
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit c3980d433a)
2018-09-04 20:00:04 +02:00
Andreas Schneider
51063fe07e packet: Use C99 initializer to reset session->in_packet
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 78498ee289)
2018-09-04 20:00:04 +02:00
Andreas Schneider
9cc1af1d53 packet: Reformat ssh_packet_parse_type()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 76f5a60a82)
2018-09-04 20:00:04 +02:00
Andreas Schneider
8a83bc0569 gzip: Use calloc in initcompress() and initdecompress()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 07986731c6)
2018-09-04 20:00:04 +02:00
Andreas Schneider
0181f5b5ed kex: Use C99 initializer instead of memset
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit f1608778be)
2018-09-04 20:00:04 +02:00
Andreas Schneider
eaae8ce086 channels: Remove memset in ssh_channel_do_free()
We have nice tools to detect that in the meantime.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 72e91d5131)
2018-09-04 20:00:04 +02:00
Andreas Schneider
0b2072dd30 channels: Reformat ssh_channel_free()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 4af4b59e21)
2018-09-04 20:00:04 +02:00
Andreas Schneider
2e77cf6b34 channels: Use calloc() in ssh_channel_new()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit ca464ca2ba)
2018-09-04 20:00:04 +02:00
Andreas Schneider
ad3c052e1c channel: Reformat ssh_channel_new()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 9ac6ac6c26)
2018-09-04 20:00:04 +02:00
Andreas Schneider
57d9d97866 pki_mbedcrypto: Use explicit_bzero()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit b6b5a61c97)
2018-09-04 20:00:04 +02:00
Andreas Schneider
22747c862a pki_crypto: Use explicit_bzero()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 1acb82e38a)
2018-09-04 20:00:04 +02:00
Andreas Schneider
fed755eee5 getpass: Use explicit_bzero()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit a6d59811bb)
2018-09-04 20:00:04 +02:00
Andreas Schneider
804410f8ad getpass: Use calloc to allocate memory
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit d4a443d56c)
2018-09-04 20:00:04 +02:00
Andreas Schneider
df57a9a81d wrapper: Use explicit_bzero() in crypto_free()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 62bff4aff1)
2018-09-04 20:00:04 +02:00
Andreas Schneider
97076780a5 wrapper: Fix size type
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit f8e68b92b8)
2018-09-04 20:00:04 +02:00
Andreas Schneider
899553f9f7 wrapper: Reformat crypto_free()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 9c5d2d4543)
2018-09-04 20:00:04 +02:00
Andreas Schneider
2edff5e69e tests: Add a test for sftp_canonicalize_path()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 7867126aa6)
2018-09-04 19:00:50 +02:00
Andreas Schneider
37f451171b sftp: Fix segfault in sftp_canonicalize_path()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 4774d2b9f7)
2018-09-04 19:00:47 +02:00
Andreas Schneider
2efc1721d8 string: Don't allow to allocate strings bigger than 256M
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit f48dcb26e3)
2018-09-04 12:29:41 +02:00
Andreas Schneider
e9613e6b52 string: Reformat ssh_string_new()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit d1f23cd6d8)
2018-09-04 12:29:40 +02:00
Andreas Schneider
73fbe68ccd sftp: Use ssh_buffer_pack() in sftp_fstat()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit e601dbd8e3)
2018-09-03 19:04:13 +02:00
Andreas Schneider
0cb282df99 sftp: Reformat sftp_lstat()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit f3ffd8aa41)
2018-09-03 19:04:13 +02:00
Andreas Schneider
fdb0c0a29b sftp: Use ssh_buffer_pack() in sftp_xstat()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 4d98b1cd7e)
2018-09-03 19:04:13 +02:00
Andreas Schneider
2e56db3b2f sftp: Reformat sftp_xstat()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit b00a0578f9)
2018-09-03 19:04:13 +02:00
Andreas Schneider
4eb759bf40 sftp: Use ssh_buffer_unpack() in sftp_canonicalize_path()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 336c097ae7)
2018-09-03 19:04:13 +02:00
Andreas Schneider
c3987a9796 sftp: Use ssh_buffer_pack() in sftp_canonicalize_path()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 1dd8466f66)
2018-09-03 19:04:13 +02:00
Andreas Schneider
a070c942e7 sftp: Reformat sftp_canonicalize_path()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8b19ef05f3)
2018-09-03 19:04:13 +02:00
Andreas Schneider
113b1872cf sftp: Use sftp_buffer_pack() in sftp_fstatvfs()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 7e11e41a9f)
2018-09-03 19:04:13 +02:00
Andreas Schneider
c7dc2937fc sftp: Reformat sftp_fstatvfs()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 5914ea7c75)
2018-09-03 19:04:13 +02:00
Andreas Schneider
075895da40 sftp: Use ssh_buffer_pack() in sftp_fsync()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit f1e84d5e67)
2018-09-03 19:04:13 +02:00
Andreas Schneider
7930086a37 sftp: Use ssh_buffer_pack() in sftp_statvfs()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8e3dd09e11)
2018-09-03 19:04:13 +02:00
Andreas Schneider
3f376f848d sftp: Reformat sftp_statvfs()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit ae0afec98d)
2018-09-03 19:04:13 +02:00
Andreas Schneider
3cee61a65b sftp: Use ssh_buffer_unpack() in sftp_readlink()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 0be43c333e)
2018-09-03 19:04:13 +02:00
Andreas Schneider
90321f732e sftp: Use ssh_buffer_pack() in sftp_readlink()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 83a5d3b258)
2018-09-03 19:04:13 +02:00
Andreas Schneider
c6140b1a4c sftp: Reformat sftp_readlink()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit bb4bdec184)
2018-09-03 19:04:13 +02:00
Andreas Schneider
9290d89570 sftp: Use ssh_buffer_pack() in sftp_setstat()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit e0449ba21f)
2018-09-03 19:04:13 +02:00
Andreas Schneider
da9ab71f88 sftp: Reformat sftp_setstat()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8a56b90c3e)
2018-09-03 19:04:13 +02:00
Andreas Schneider
53dfee98d2 sftp: Use ssh_buffer_pack() in sftp_mkdir()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 218c67a51d)
2018-09-03 19:04:13 +02:00
Andreas Schneider
bb14611f86 sftp: Reformat sftp_mkdir()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 89c525bbf1)
2018-09-03 19:04:13 +02:00
Andreas Schneider
b1aca92268 sftp: Use ssh_buffer_pack in sftp_open()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 2c0baef7d4)
2018-09-03 19:04:13 +02:00
Andreas Schneider
2b524655ae sftp: Reformat sftp_open()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit bfb6718b50)
2018-09-03 19:04:13 +02:00
Andreas Schneider
b51594c34a sftp: Use ssh_buffer_pack() in sftp_handle_close()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit d99c066a0b)
2018-09-03 19:04:13 +02:00
Andreas Schneider
b409b7d092 sftp: Reformat sftp_handle_close()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 2844942c1b)
2018-09-03 19:04:13 +02:00
Andreas Schneider
4256936fed sftp: Use ssh_buffer_pack() in sftp_readdir()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 3a729829fd)
2018-09-03 19:04:13 +02:00
Andreas Schneider
fdb6dc7069 sftp: Reformat sftp_readdir()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 576fdbe1e8)
2018-09-03 19:04:13 +02:00
Andreas Schneider
6291900234 sftp: Use ssh_buffer_pack() in sftp_opendir()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 87df9cfc5d)
2018-09-03 19:04:13 +02:00
Andreas Schneider
216bd2abd8 sftp: Reformat sftp_opendir()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit ea375d1605)
2018-09-03 19:04:13 +02:00
Andreas Schneider
574f279f00 buffer: Precalculate the size required for ssh_buffer_pack()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c15bd2831f)
2018-09-03 19:04:13 +02:00
Andreas Schneider
d886870bbf buffer: Only reduce the buffer size if it gets bigger than 64K
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit efef877356)
2018-09-03 19:04:13 +02:00
Andreas Schneider
f56c93cccd buffer: Only allow to allocate a maximum of 256MB
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 254a0f7132)
2018-09-03 19:04:13 +02:00
Andreas Schneider
bbd17bc97a buffer: Always preallocate a buffer with 64 bytes
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit d2131b286f)
2018-09-03 19:04:13 +02:00
Andreas Schneider
26fa923b55 buffer: Rewrite ssh_buffer_free()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c1c32bda14)
2018-09-03 19:04:13 +02:00
Andreas Schneider
177a082974 buffer: Use bool for secure buffer
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit a1b57d3b94)
2018-09-03 19:04:13 +02:00
Andreas Schneider
ce3ee332d4 buffer: Reformat buffer_shift()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit be703974e9)
2018-09-03 19:04:13 +02:00
Andreas Schneider
eb95f8fa85 buffer: Cleanup buffer_verify
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 29f36791c9)
2018-09-03 19:04:13 +02:00
Andreas Schneider
8d3db75724 cmake: Store Profiling and AddressSanitizer flags in the cache
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 492e3d5c77)
2018-09-03 15:43:06 +02:00
Andreas Schneider
e1fbc02209 cmake: Add -fstack-clash-protection
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 9a3f43f4ee)
2018-09-03 15:43:04 +02:00
Andreas Schneider
766041d956 cmake: Small improvements to AddCMockaTest
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit baa434ebed)
2018-09-02 13:58:42 +02:00
Andreas Schneider
f880a7728f auth: Fix freeing memory in ssh_userauth_agent_publickey()
CID 1395453

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit f99e6766d6)
2018-09-02 10:30:54 +02:00
Andreas Schneider
013203301f include: Add SSH_STRING_FREE() and SSH_STRING_FREE_CHAR()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 3efc64112a)
2018-09-02 10:30:52 +02:00
Andreas Schneider
bfb60befa7 gitlab-ci: Correctly run AddressSanitizer with cmake
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit bc19f892eb)
2018-09-01 21:34:04 +02:00
Andreas Schneider
4d34890624 messages: Fix memory leak in ssh_packet_userauth_request
Found by AddressSanitizer.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit f8fc0b9dfb)
2018-09-01 21:34:02 +02:00
Andreas Schneider
6751c0e2c3 gitlab-ci: Enable address sanitzer build
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 1b12a2415d)
2018-09-01 17:15:11 +02:00
Andreas Schneider
a641b6ea79 tests: Fix memory leaks in torture_hashes
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 1c0ac0b12e)
2018-09-01 17:15:09 +02:00
Andreas Schneider
fa3c73016d auth: Fix a memory leak in ssh_userauth_agent_publickey()
CID 1230358

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit ea2b403ab2)
2018-09-01 09:43:43 +02:00
Andreas Schneider
ffabd8c6ed pki: Fix a memory leak in ssh_pki_do_sign()
CID 1395335

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8323cd791f)
2018-09-01 09:43:40 +02:00
Andreas Schneider
219a311925 packet: Add a bound check for nr_extensions
CID 1395335

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 461ebd1e2f)
2018-09-01 09:43:36 +02:00
Andreas Schneider
8e3af4d859 doc: Update Public Key Algorithms
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit be147e897d)
2018-08-31 15:04:54 +02:00
Jakub Jelen
9fa614a36d tests: Properly initilize library in threads tests
This was already done in the torture_threads_pki.

Without the explicit initialization, we can observe random
failures tests (at least of the torture_threads_crypto) from
various threads.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 6b10bbea2f)
2018-08-31 14:30:53 +02:00
Jakub Jelen
3d207f72a0 pki: Support RSA SHA2 signatures of sessionid for server
This involves mostly creation of host keys proofs but needs
to follow the same procedure as the client authentication
signatures.

At the same time, the SHA2 extension is enabled in the pkd
so we are able to atomicaly provide correct signatures and
pass tests.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit b4c8bd9fe4)
2018-08-31 14:30:53 +02:00
Jakub Jelen
f53d2f7511 server: We should list SHA2 variants in offered hostkeys
The SHA2 variants should be preferred. Also the buffer needs to be
extended to fit all possible public key algorithms.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 5d13006650)
2018-08-31 14:30:53 +02:00
Jakub Jelen
b853d99546 server: Support for extension negotiation
This includes intercepting the  ext-info-c  string from
the client kex proposal, configuring the server to allow using
this extension and sending the SSH_MSG_EXT_INFO packet back
to the client after the new keys are in use.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 6fa5e8adb0)
2018-08-31 14:30:53 +02:00
Jakub Jelen
a09976e3d6 messages: Create correct digest for pki signatures
This does not affect old signatures, where the public key algorithm
matches the public key type.

This is a problem when using SHA2 extension for the RSA keys, where
the new signature algorithsm are introduced in addition to the
exitsing ssh-rsa which was ignored throughout the code.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 60ad7ee15d)
2018-08-31 14:30:53 +02:00
Jakub Jelen
1ba0432524 tests: Verify the public key algorithms can be limited by configuration option
SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES configuration option can limit
what keys can or can not be used for public key authentication.

This is useful for disabling obsolete algorithms while not completely
removing the support for them or allows to configure what public key
algorithms will be used with the SHA2 RSA extension.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 5fe81e89fb)
2018-08-31 14:30:53 +02:00
Jakub Jelen
7dcd749ee1 auth: Prevent authentication with non-allowed key algorithms
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 09cf301eee)
2018-08-31 14:30:53 +02:00
Jakub Jelen
30368fb06a tests: PUBLICKEY_ACCEPTED_TYPES are effective
Verify the PUBLICKEY_ACCEPTED_TYPES option is handled correctly
and affects the signature algorithm selection based on the
extensions and can be used to limit list of offered mechanisms
to the server.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 594c62d718)
2018-08-31 14:30:53 +02:00
Jakub Jelen
fd6b7db1ce pki: Allow filtering accepted public key types based on the configuration
This effectively allows to disable using the SHA2 extension, disable
other old public key mechanisms out of the box (hello DSA) or force
the new SHA2-based key algorithm types if needed.

This exposes the  default_methods  array from  kex.c.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 4169be45eb)
2018-08-31 14:30:53 +02:00
Jakub Jelen
53514b2a40 tests: Cover PubkeyAcceptedTypes configuration option
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 5d53f519bc)
2018-08-31 14:30:53 +02:00
Jakub Jelen
0e20418296 config: Accept the PubkeyAcceptedTypes configuration option
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 37864b6575)
2018-08-31 14:30:53 +02:00
Jakub Jelen
92b59ace9e options: The new option SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES
This option allows to specify acceptable public key algorithms
and reflects the PubkeyAcceptedTypes configuration option from
OpenSSH.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 4521ab73b6)
2018-08-31 14:30:53 +02:00
Jakub Jelen
af7b5b78ee kex: The public key algorithms are no longer only host keys
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 9ca6127b91)
2018-08-31 14:30:53 +02:00
Jakub Jelen
2b67e2d54c SHA2 extension in the ssh-agent interface
The new constants for flags are defined in draft-miller-ssh-agent-02
are active if the SHA2 extension is negotiated with the server.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit ebb01549d0)
2018-08-31 14:30:53 +02:00
Jakub Jelen
f44994f1e6 tests: SHA2 extension signatures
This introduces a new test case for RSA unit tests, verifying that
libraries are able to provide and verify the RSA signatures with
SHA2 hash algorithms.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 945469c9e0)
2018-08-31 14:30:53 +02:00
Jakub Jelen
97d6eb84a4 auth: Support SHA2 extension for pubkey authentication (RFC 8332)
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 82da0c3361)
2018-08-31 14:30:53 +02:00
Jakub Jelen
33f2211cae pki: RSA signatures with SHA2 hash algorithms (RFC 8332)
* This change introduces a new API to request signature using
   one key and different hash algorithms. This is used only with
   RSA keys, that used to have SHA1 hardcoded, but the new
   algorithsms allow to use the SHA2 hashes, if the extension
   is negotiated.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 1f08aabe43)
2018-08-31 14:30:53 +02:00
Jakub Jelen
03aff19b80 kex: Offer SHA2 extension signature algorithms by default
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 3ca7e1eea9)
2018-08-31 14:30:53 +02:00
Jakub Jelen
cf660fe27c pki: Support RSA verification using different hash algorithms
This changes the private API by adding one more argument to function

  pki_signature_from_blob()

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit fa60827840)
2018-08-31 14:30:53 +02:00
Jakub Jelen
f9d60e1360 client: Handle the MSG_EXT_INFO packet signalling supported extensions
RFC 8308: The extension negotiation in Secure Shell (SSH) Protocol

RFC 8332: Use of RSA Keys with SHA-256 and SHA-512
          in the Secure Shell (SSH) Protocol

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 761225712a)
2018-08-31 14:30:53 +02:00
Jakub Jelen
1098280e43 kex: Signalize support for the extension negotiation in client (RFC 8308)
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit df13d8c61f)
2018-08-31 14:30:53 +02:00
Jakub Jelen
62301834f4 pkd: Produce more useful logs
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit cbccae795d)
2018-08-31 14:30:53 +02:00
Jakub Jelen
3e0ac84001 pkd: Generate host keys in old format
This is required to work against OpenSSH 7.8, which is now
writing keys in new openssh format by default

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 100c9c98ce)
2018-08-31 14:30:53 +02:00
Andreas Schneider
4d26e08789 tests: Ignore SIGPIPE in pkd
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit d7a64b9519)
2018-08-31 14:30:53 +02:00
Andreas Schneider
3c4403c400 cmake: Use -fstack-protector-strong if possible
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit fc212d73ed)
2018-08-31 14:30:53 +02:00
Andreas Schneider
8dcde7a74f examples: Reformat ssh_client
The example should be clean code if possible.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 2b05e46b62)
2018-08-31 14:30:53 +02:00
Andreas Schneider
bb7cd8e22b doc: Update that_style
We don't need the source css files.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8d8b64cc3f)
2018-08-31 08:05:07 +02:00
Andreas Schneider
7458e95ee5 poll: Fix size types in ssh_event_free()
src/poll.c:1024:9: error: assuming signed overflow does not occur when
    simplifying conditional to constant [-Werror=strict-overflow]

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 11d87238b8)
2018-08-30 08:59:56 +02:00
Andreas Schneider
2f69c5f022 poll: Reformat ssh_event_free()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8243030c55)
2018-08-30 08:59:53 +02:00
99 changed files with 6584 additions and 4202 deletions

View File

@@ -60,14 +60,15 @@ fedora/openssl_1.1.x/x86-64/release:
- obj/
# Address sanitizer doesn't mix well with LD_PRELOAD used in the testsuite
.fedora/address-sanitizer:
# so, this is only enabled for unit tests right now.
# TODO: add -DCLIENT_TESTING=ON -DSERVER_TESTING=ON
fedora/address-sanitizer:
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
script:
- mkdir -p obj && cd obj && cmake
-DCMAKE_C_FLAGS="-O2 -g -fsanitize=address"
-DCMAKE_LINK_FLAGS="-fsanitize=address -static-libasan"
-DCMAKE_BUILD_TYPE=AddressSanitizer
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
-DUNIT_TESTING=ON .. &&
make -j$(nproc) && ctest --output-on-failure
tags:
- shared

View File

@@ -1,7 +1,16 @@
cmake_minimum_required(VERSION 3.3.0)
cmake_policy(SET CMP0048 NEW)
project(libssh VERSION 0.8.2 LANGUAGES C)
# Specify search path for CMake modules to be loaded by include()
# and find_package()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
# Add defaults for cmake
# Those need to be set before the project() call.
include(DefineCMakeDefaults)
include(DefineCompilerFlags)
project(libssh VERSION 0.8.3 LANGUAGES C)
# global needed variable
set(APPLICATION_NAME ${PROJECT_NAME})
@@ -13,16 +22,12 @@ 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.6.0")
set(LIBRARY_VERSION "4.7.0")
set(LIBRARY_SOVERSION "4")
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
set(CMAKE_MODULE_PATH
${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules
)
# add definitions
include(DefineCMakeDefaults)
include(DefinePlatformDefaults)
include(DefineInstallationPaths)
include(DefineOptions.cmake)

View File

@@ -1,6 +1,21 @@
ChangeLog
==========
version 0.8.3 (released 2018-09-21)
* Added support for rsa-sha2
* Added support to parse private keys in openssh container format
(other than ed25519)
* Added support for diffie-hellman-group18-sha512 and
diffie-hellman-group16-sha512
* Added ssh_get_fingerprint_hash()
* Added ssh_pki_export_privkey_base64()
* Added support for Match keyword in config file
* Improved performance and reduced memory footprint for sftp
* Fixed ecdsa publickey auth
* Fixed reading a closed channel
* Added support to announce posix-rename@openssh.com and
hardlink@openssh.com in the sftp server
version 0.8.2 (released 2018-08-30)
* Added sha256 fingerprints for pubkeys
* Improved compiler flag detection

View File

@@ -17,8 +17,7 @@ if (UNIX)
endif()
add_c_compiler_flag("-std=gnu99" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-pedantic" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-pedantic-errors" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wpedantic" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wall" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wshadow" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wmissing-prototypes" SUPPORTED_COMPILER_FLAGS)
@@ -63,9 +62,19 @@ if (UNIX)
endif()
endif()
check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR)
if (WITH_STACK_PROTECTOR)
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector")
check_c_compiler_flag_ssp("-fstack-protector-strong" WITH_STACK_PROTECTOR_STRONG)
if (WITH_STACK_PROTECTOR_STRONG)
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector-strong")
else (WITH_STACK_PROTECTOR_STRONG)
check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR)
if (WITH_STACK_PROTECTOR)
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector")
endif()
endif (WITH_STACK_PROTECTOR_STRONG)
check_c_compiler_flag_ssp("-fstack-clash-protection" WITH_STACK_CLASH_PROTECTION)
if (WITH_STACK_CLASH_PROTECTION)
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-clash-protection")
endif()
if (PICKY_DEVELOPER)

View File

@@ -4,7 +4,7 @@ include(CheckSymbolExists)
include(CheckFunctionExists)
include(CheckLibraryExists)
include(CheckTypeSize)
include(CheckCXXSourceCompiles)
include(CheckStructHasMember)
include(TestBigEndian)
set(PACKAGE ${PROJECT_NAME})
@@ -156,7 +156,8 @@ check_function_exists(explicit_bzero HAVE_EXPLICIT_BZERO)
check_function_exists(memset_s HAVE_MEMSET_S)
if (HAVE_GLOB_H)
check_function_exists(glob HAVE_GLOB)
check_struct_has_member(glob_t gl_flags glob.h HAVE_GLOB_GL_FLAGS_MEMBER)
check_function_exists(glob HAVE_GLOB)
endif (HAVE_GLOB_H)
if (NOT WIN32)

View File

@@ -27,9 +27,10 @@ else (WITH_ZLIB)
set(WITH_LIBZ OFF)
endif (WITH_ZLIB)
if(WITH_BENCHMARKS)
if (WITH_BENCHMARKS)
set(UNIT_TESTING ON)
endif(WITH_BENCHMARKS)
set(CLIENT_TESTING ON)
endif()
if (WITH_STATIC_LIB)
set(BUILD_STATIC_LIB ON)

View File

@@ -1,7 +1,7 @@
# - ADD_CHECK_TEST(test_name test_source linklib1 ... linklibN)
# - add_cmocka_test(test_name test_source linklib1 ... linklibN)
# Copyright (c) 2007 Daniel Gollub <dgollub@suse.de>
# Copyright (c) 2007-2010 Andreas Schneider <asn@cryptomilk.org>
# Copyright (c) 2007-2018 Andreas Schneider <asn@cryptomilk.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
@@ -9,20 +9,6 @@
enable_testing()
include(CTest)
if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
# Profiling
set(CMAKE_C_FLAGS_PROFILING "-g -O0 -Wall -W -Wshadow -Wunused-variable -Wunused-parameter -Wunused-function -Wunused -Wno-system-headers -Wwrite-strings -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Compiler Flags")
set(CMAKE_SHARED_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
set(CMAKE_MODULE_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
set(CMAKE_EXEC_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
# Address Sanitizer
set(CMAKE_C_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer" CACHE STRING "Address sanitizer compiler flags")
set(CMAKE_SHARED_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address" CACHE STRING "Address sanitizer shared linker flags")
set(CMAKE_MODULE_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address" CACHE STRING "Address sanitizer module linker flags")
set(CMAKE_EXEC_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address" CACHE STRING "Address sanitizer executable linker flags")
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
if (CMAKE_CROSSCOMPILING)
if (WIN32)
find_program(WINE_EXECUTABLE
@@ -31,8 +17,10 @@ if (CMAKE_CROSSCOMPILING)
endif()
endif()
function (ADD_CMOCKA_TEST _testName _testSource)
function(ADD_CMOCKA_TEST _testName _testSource)
add_executable(${_testName} ${_testSource})
target_link_libraries(${_testName} ${ARGN})
add_test(${_testName} ${TARGET_SYSTEM_EMULATOR} ${CMAKE_CURRENT_BINARY_DIR}/${_testName}${CMAKE_EXECUTABLE_SUFFIX})
endfunction (ADD_CMOCKA_TEST)

View File

@@ -14,17 +14,5 @@ set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON)
# since cmake 2.4.0
set(CMAKE_COLOR_MAKEFILE ON)
# Define the generic version of the libraries here
set(GENERIC_LIB_VERSION "0.1.0")
set(GENERIC_LIB_SOVERSION "0")
# Set the default build type to release with debug info
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE RelWithDebInfo
CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
)
endif (NOT CMAKE_BUILD_TYPE)
# Create the compile command database for clang by default
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

View File

@@ -0,0 +1,25 @@
if (UNIX AND NOT WIN32)
# Activate with: -DCMAKE_BUILD_TYPE=Profiling
set(CMAKE_C_FLAGS_PROFILING "-g -O0 -fprofile-arcs -ftest-coverage"
CACHE STRING "Flags used by the C compiler during PROFILING builds.")
set(CMAKE_CXX_FLAGS_PROFILING "-g -O0 -fprofile-arcs -ftest-coverage"
CACHE STRING "Flags used by the CXX compiler during PROFILING builds.")
set(CMAKE_SHARED_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage"
CACHE STRING "Flags used by the linker during the creation of shared libraries during PROFILING builds.")
set(CMAKE_MODULE_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage"
CACHE STRING "Flags used by the linker during the creation of shared libraries during PROFILING builds.")
set(CMAKE_EXEC_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage"
CACHE STRING "Flags used by the linker during PROFILING builds.")
# Activate with: -DCMAKE_BUILD_TYPE=AddressSanitizer
set(CMAKE_C_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer"
CACHE STRING "Flags used by the C compiler during ADDRESSSANITIZER builds.")
set(CMAKE_CXX_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer"
CACHE STRING "Flags used by the CXX compiler during ADDRESSSANITIZER builds.")
set(CMAKE_SHARED_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address"
CACHE STRING "Flags used by the linker during the creation of shared libraries during ADDRESSSANITIZER builds.")
set(CMAKE_MODULE_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address"
CACHE STRING "Flags used by the linker during the creation of shared libraries during ADDRESSSANITIZER builds.")
set(CMAKE_EXEC_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address"
CACHE STRING "Flags used by the linker during ADDRESSSANITIZER builds.")
endif()

View File

@@ -89,6 +89,9 @@
/* Define to 1 if you have DSA */
#cmakedefine HAVE_DSA 1
/* Define to 1 if you have gl_flags as a glob_t sturct member */
#cmakedefine HAVE_GLOB_GL_FLAGS_MEMBER 1
/*************************** FUNCTIONS ***************************/
/* Define to 1 if you have the `EVP_aes128_ctr' function. */

View File

@@ -20,7 +20,7 @@ the interesting functions as you go.
The libssh library provides:
- <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>Hostkey Types</strong>: <i>ssh-ed25519, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521</i>, ssh-dss, ssh-rsa
- <strong>Public Key Algorithms</strong>: ssh-ed25519, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, ssh-rsa, rsa-sha2-512, rsa-sha2-256,ssh-dss
- <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, none
- <strong>Compression Schemes</strong>: zlib, <i>zlib@openssh.com</i>, none
- <strong>MAC hashes</strong>: hmac-sha1, hmac-sha2-256, hmac-sha2-384, hmac-sha2-512, hmac-md5, none

View File

@@ -1,69 +0,0 @@
/*
Basic styling for fragments shared by all themes.
*/
div.fragment {
padding: 0;
margin: 4px 8px 4px 2px;
color: #bebebe;
background-color: #323232;
border: 3px solid #e8e8e8;
border-radius: 2px;
overflow-y: hidden;
overflow-x: auto;
position: relative;
}
div.line {
font-family: monospace, fixed;
font-size: 13px;
min-height: 13px;
line-height: 1.0;
text-indent: -53px;
margin: 0px;
padding: 1px 0 1px 53px;
white-space: pre;
@include transition-property(background-color);
@include transition-duration(0s);
&:hover {
background-color: #1a1a1a;
}
&::after {
// insert linefeed
content:"\000A";
white-space: pre;
}
}
span.lineno {
padding-right: 4px;
text-align: right;
color: black;
height: 100px;
white-space: pre;
border-right: 3px solid #1d7567;
background-color: #a0a0a0;
}
span.lineno a, span.lineno a:visited {
background-color: inherit;
color: #1e595a;
}
span.lineno a:hover {
background-color: #C8C8C8;
text-decoration: none;
}
.lineno {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}

View File

@@ -1,80 +0,0 @@
// colours of code view
div.fragment {
color: #bebebe;
background-color: #323232;
}
div.fragment::before {
background-color: #1a1a1a;
border-right: 1px solid #3e3e3e;
}
div.line:hover {
background-color: #1a1a1a;
}
span.lineno {
color: #969696;
background-color: #1a1a1a;
border-right: 1px solid #3e3e3e;
}
span.lineno a, span.lineno a:visited {
background-color: inherit;
color: #dcdcdc;
}
span.lineno a:hover {
background-color: #323232;
}
// syntax highlighting
a.code, a.code:visited {
color: #6cc7eb;
}
a.codeRef, a.codeRef:visited {
color: #3d95e6;
}
span.keyword {
color: #98f77a;
font-weight: bold;
}
span.keywordtype {
color: #ffa0a0;
}
span.keywordflow {
color: #98f77a;
font-weight: bold;
}
span.comment {
// color: #dadbb1;
color: #999;
font-style: oblique;
}
span.preprocessor {
color: #cd5c57;
}
span.stringliteral {
color: #64b041;
}
span.charliteral {
color: #64b041;
}
blockquote {
background-color: #F7F8FB;
border-left: 2px solid #9CAFD4;
margin: 0 24px 0 4px;
padding: 0 12px 0 16px;
}

View File

@@ -1,70 +0,0 @@
/*
* The main menu at the top
*/
#main-menu {
background-image: none;
background: $background-color-dark;
padding: 0;
}
.sm-dox {
// :not(:last-child) -> do not style search box
&> li:not(:last-child) > a {
background-image: none;
text-shadow: none;
color: white;
font-weight: normal;
letter-spacing: 1px;
font-size: 11pt;
text-transform: uppercase;
}
&> li:not(:last-child) > a:hover,
&> li:not(:last-child) > a.highlighted {
background-color: $primary-color;
}
a span.sub-arrow {
// this sets the color of the arrow
border-color: white transparent transparent;
}
ul {
// sub menus
border: none;
@include border-radius(0 !important);
padding: 0;
background: $background-color-dark;
@include box-shadow(0 0 4px rgba(0,0,0,0.35), 0 0 8px rgba(0,0,0,0.2));
a {
background: inherit;
color: white;
font-weight: normal;
letter-spacing: 1px;
font-size: 11pt;
}
a:hover {
background: $primary-color;
color: white;
font-weight: normal;
letter-spacing: 1px;
font-size: 11pt;
}
a.highlighted {
background: $primary-color;
color: white;
font-weight: normal;
letter-spacing: 1px;
font-size: 11pt;
}
a span.sub-arrow {
/* this sets the color of the arrow */
border-color: white transparent transparent;
}
}
}

View File

@@ -1,33 +0,0 @@
@mixin box-shadow($args...) {
-moz-box-shadow: $args;
-webkit-box-shadow: $args;
-o-box-shadow: $args;
box-shadow: $args;
}
@mixin border-radius($args...) {
-moz-border-radius: $args;
-webkit-border-radius: $args;
border-radius: $args;
}
@mixin transition($args...) {
-webkit-transition: $args;
-moz-transition: $args;
-o-transition: $args;
transition: $args;
}
@mixin transition-property($arg) {
-webkit-transition: $arg;
-moz-transition: $arg;
-o-transition: $arg;
transition: $arg;
}
@mixin transition-duration($arg) {
-webkit-duration: $arg;
-moz-duration: $arg;
-o-duration: $arg;
duration: $arg;
}

View File

@@ -1,72 +0,0 @@
/*
* The tree view on the left
*/
.arrow {
color:black;
cursor: pointer;
font-size: 80%;
display: inline-block;
width: 16px;
height: 22px;
margin-left: 4px;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
&:hover {
color: black;
}
}
#selected .arrow {
color: white;
&:hover {
color: #d2d2d2;
}
}
#nav-tree {
background-image: none;
background-color: white;
.item {
margin: 0;
&:hover {
background-color: #d2d2d2;
}
}
.selected {
background-image: none;
background-color: $primary-color;
color: white;
text-shadow: none;
&:hover {
background-image: none;
background-color: $primary-color;
color: white;
text-shadow: none;
}
}
a {
color: black;
}
}
.ui-resizable-e {
background: #808080 url("splitbar_handle.svg") no-repeat center;
border-right: solid 1px #c0c0c0;
border-left: solid 1px black;
&:hover {
background-color: #606060;
}
}

View File

@@ -1,121 +0,0 @@
/*
* The line at the bottom
*/
.navpath {
ul {
font-size: 11px;
background-image: none;
height: 30px;
line-height: 30px;
color: black;
border: none;
border-top: 1px solid #808080;
overflow: hidden;
margin: 0px;
padding: 0px;
}
/* intermediate navelems */
li:not(:first-child) {
list-style-type: none;
float: left;
padding-left: 18px;
padding-right: 10px;
color: black;
background-color: white;
background-image: url('nav_edge_inter.svg');
background-repeat: no-repeat;
background-position: left -1px;
background-size: auto 100%;
}
/* first navelem */
li:first-child {
list-style-type: none;
float: left;
padding-left: 15px;
padding-right: 10px;
color: black;
background-color: white;
background-image: none;
}
/* last navelem */
li:nth-last-child(2) {
list-style-type: none;
float: left;
padding-left:10px;
padding-right:15px;
color: white;
background-color: $primary-color;
background-image: url('nav_edge_right.svg');
background-repeat: no-repeat;
background-position: right -1px;
background-size: auto 100%;
}
li:nth-last-child(2):not(:first-child) {
list-style-type: none;
float: left;
padding-left:15px;
padding-right:15px;
color: white;
background-color: $primary-color;
background-image: url('nav_edge_left.svg'), url('nav_edge_right.svg');
background-repeat: no-repeat;
background-position: -1px -1px, right -1px;
background-size: auto 100%;
}
li.navelem a, .navpath li.navelem b {
height:32px;
display:block;
text-decoration: none;
outline: none;
color: inherit;
font-family: Roboto,sans-serif;
text-shadow: none;
text-decoration: none;
font-weight: normal;
}
li.navelem a:hover {
color: inherit;
text-decoration: underline;
}
// the "doxygen" logo at the right
li.footer {
list-style-type: none;
float: right;
padding-left: 0;
padding-right: 10px;
background-color: #d5d5d5;
background-image: none;
color: black;
font-size: 8pt;
// show the edge image
&:before {
content: "";
width: 13px;
height: 30px;
display: inline-block;
float: left;
background-image: url("nav_edge_right.svg");
background-repeat: no-repeat;
background-position: right 0;
background-size: auto 100%;
/* flip the element horizontally */
-moz-transform: scaleX(-1);
-o-transform: scaleX(-1);
-webkit-transform: scaleX(-1);
transform: scaleX(-1);
filter: FlipH;
-ms-filter: "FlipH";
}
}
}

View File

@@ -1,89 +0,0 @@
/*
* The search box
*/
.sm-dox > li:last-child {
margin-right: 10pt;
}
#MSearchBox {
border: 2px inset black;
display: table;
width: 350px;
height: 26px;
background: white;
margin-top: 5px;
.left {
background-image: none;
display: table-cell;
width: 100%;
height: inherit;
left: 0;
}
// don't need this element
.right {
background-image: none;
width: 0;
display: none;
visibility: hidden;
}
}
// override for when there is no main menu
nav > #MSearchBox {
border: 2px solid #666666;
margin: 5px 10pt 0 0;
height: 22px;
}
#MSearchSelect, .left #MSearchSelect {
left: 0;
background-image: url("mag_glass.svg");
width: 22px;
height: 22px;
padding: 22px 22px 0 0 ;
margin: 0 4px 0 4px;
box-sizing: border-box;
}
#MSearchField {
background-image: none;
display: table-cell;
margin: 0;
// leave room for #MSearchSelect and a bit more for the border
margin-left: 30px;
width: calc(100% - 34px);
height: 22px;
font: 11pt sans-serif;
}
#MSearchSelectWindow {
background-color: $background-color-dark;
padding: 0;
border: solid 1px black;
@include border-radius(0);
@include box-shadow(0 0 4px rgba(0,0,0,0.35), 0 0 8px rgba(0,0,0,0.2));
}
a.SelectItem {
color: white;
padding: 3px 4px;
font: 10pt sans-serif;
letter-spacing: 1px;
&:hover {
background-color: $primary-color;
color: white;
}
&:focus, &:active {
color: white;
}
}
#MSearchResultsWindow {
background-color: white;
@include box-shadow(0 0 4px rgba(0,0,0,0.35), 0 0 8px rgba(0,0,0,0.2));
}

File diff suppressed because it is too large Load Diff

View File

@@ -152,10 +152,14 @@ a.elRef, a.elRef:visited {
letter-spacing: 1px;
font-size: 11pt;
text-transform: uppercase; }
.sm-dox > li:not(:last-child) > a:hover, .sm-dox > li:not(:last-child) > a.highlighted {
.sm-dox > li:not(:last-child) > a:hover,
.sm-dox > li:not(:last-child) > a.highlighted {
background-color: #5f082b; }
.sm-dox a span.sub-arrow {
border-color: white transparent transparent; }
.sm-dox ul {
border: none;
-moz-border-radius: 0 !important;
@@ -262,7 +266,7 @@ img.footer {
Basic styling for fragments shared by all themes.
*/
div.fragment {
padding: 0;
padding: 4px;
margin: 4px 8px 4px 2px;
color: #bebebe;
background-color: #323232;
@@ -302,7 +306,7 @@ span.lineno {
height: 100px;
white-space: pre;
border-right: 3px solid #1d7567;
background-color: #a0a0a0; }
background-color: #323232; }
span.lineno a, span.lineno a:visited {
background-color: inherit;
@@ -333,7 +337,7 @@ div.line:hover {
span.lineno {
color: #969696;
background-color: #1a1a1a;
background-color: #323232;
border-right: 1px solid #3e3e3e; }
span.lineno a, span.lineno a:visited {
@@ -539,9 +543,9 @@ th.markdownTableHeadCenter, th.markdownTableHeadNone {
width: 100%; }
.memTemplParams {
color: #4665A2;
color: black;
white-space: nowrap;
font-size: 80%; }
font-size: 100%; }
/* Styles for detailed member documentation */
.memtitle {
@@ -1406,25 +1410,18 @@ div.toc {
@media print {
#top {
display: none; }
#side-nav {
display: none; }
#nav-path {
display: none; }
body {
overflow: visible; }
h1, h2, h3, h4, h5, h6 {
page-break-after: avoid; }
.summary {
display: none; }
.memitem {
page-break-inside: avoid; }
#doc-content {
margin-left: 0 !important;
height: auto !important;
@@ -1432,5 +1429,3 @@ div.toc {
overflow: inherit;
display: inline;
background-color: white; } }
/*# sourceMappingURL=that_style.css.map */

View File

@@ -24,7 +24,8 @@ clients must be made or how a client should react.
#include <libssh/libssh.h>
#include "examples_common.h"
int authenticate_kbdint(ssh_session session, const char *password) {
int authenticate_kbdint(ssh_session session, const char *password)
{
int err;
err = ssh_userauth_kbdint(session, NULL, NULL);
@@ -99,78 +100,80 @@ int authenticate_kbdint(ssh_session session, const char *password) {
return err;
}
static void error(ssh_session session){
fprintf(stderr,"Authentication failed: %s\n",ssh_get_error(session));
static void error(ssh_session session)
{
fprintf(stderr,"Authentication failed: %s\n",ssh_get_error(session));
}
int authenticate_console(ssh_session session){
int rc;
int method;
char password[128] = {0};
char *banner;
int authenticate_console(ssh_session session)
{
int rc;
int method;
char password[128] = {0};
char *banner;
// Try to authenticate
rc = ssh_userauth_none(session, NULL);
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
}
method = ssh_userauth_list(session, NULL);
while (rc != SSH_AUTH_SUCCESS) {
if (method & SSH_AUTH_METHOD_GSSAPI_MIC){
rc = ssh_userauth_gssapi(session);
if(rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
}
}
// 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) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
}
}
// Try to authenticate with keyboard interactive";
if (method & SSH_AUTH_METHOD_INTERACTIVE) {
rc = authenticate_kbdint(session, NULL);
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
}
}
if (ssh_getpass("Password: ", password, sizeof(password), 0, 0) < 0) {
return SSH_AUTH_ERROR;
}
// Try to authenticate with password
if (method & SSH_AUTH_METHOD_PASSWORD) {
rc = ssh_userauth_password(session, NULL, password);
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
}
}
memset(password, 0, sizeof(password));
}
banner = ssh_get_issue_banner(session);
if (banner) {
printf("%s\n",banner);
ssh_string_free_char(banner);
}
// Try to authenticate
rc = ssh_userauth_none(session, NULL);
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
}
method = ssh_userauth_list(session, NULL);
while (rc != SSH_AUTH_SUCCESS) {
if (method & SSH_AUTH_METHOD_GSSAPI_MIC){
rc = ssh_userauth_gssapi(session);
if(rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
}
}
// 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) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
}
}
// Try to authenticate with keyboard interactive";
if (method & SSH_AUTH_METHOD_INTERACTIVE) {
rc = authenticate_kbdint(session, NULL);
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
}
}
if (ssh_getpass("Password: ", password, sizeof(password), 0, 0) < 0) {
return SSH_AUTH_ERROR;
}
// Try to authenticate with password
if (method & SSH_AUTH_METHOD_PASSWORD) {
rc = ssh_userauth_password(session, NULL, password);
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
}
}
memset(password, 0, sizeof(password));
}
banner = ssh_get_issue_banner(session);
if (banner) {
printf("%s\n",banner);
ssh_string_free_char(banner);
}
return rc;
}

View File

@@ -33,236 +33,259 @@ static int verbosity;
static char *destination;
#define DATALEN 65536
static void do_sftp(ssh_session session){
sftp_session sftp=sftp_new(session);
static void do_sftp(ssh_session session) {
sftp_session sftp = sftp_new(session);
sftp_dir dir;
sftp_attributes file;
sftp_statvfs_t sftpstatvfs;
struct statvfs sysstatvfs;
sftp_file fichier;
sftp_file to;
int len=1;
int len = 1;
unsigned int i;
char data[DATALEN]={0};
char data[DATALEN] = {0};
char *lnk;
unsigned int count;
if(!sftp){
if (!sftp) {
fprintf(stderr, "sftp error initialising channel: %s\n",
ssh_get_error(session));
return;
ssh_get_error(session));
goto end;
}
if(sftp_init(sftp)){
if (sftp_init(sftp)) {
fprintf(stderr, "error initialising sftp: %s\n",
ssh_get_error(session));
return;
ssh_get_error(session));
goto end;
}
printf("Additional SFTP extensions provided by the server:\n");
count = sftp_extensions_get_count(sftp);
for (i = 0; i < count; i++) {
printf("\t%s, version: %s\n",
sftp_extensions_get_name(sftp, i),
sftp_extensions_get_data(sftp, i));
printf("\t%s, version: %s\n",
sftp_extensions_get_name(sftp, i),
sftp_extensions_get_data(sftp, i));
}
/* test symlink and readlink */
if (sftp_symlink(sftp, "/tmp/this_is_the_link",
"/tmp/sftp_symlink_test") < 0) {
fprintf(stderr, "Could not create link (%s)\n", ssh_get_error(session));
return;
"/tmp/sftp_symlink_test") < 0)
{
fprintf(stderr, "Could not create link (%s)\n",
ssh_get_error(session));
goto end;
}
lnk = sftp_readlink(sftp, "/tmp/sftp_symlink_test");
if (lnk == NULL) {
fprintf(stderr, "Could not read link (%s)\n", ssh_get_error(session));
return;
fprintf(stderr, "Could not read link (%s)\n", ssh_get_error(session));
goto end;
}
printf("readlink /tmp/sftp_symlink_test: %s\n", lnk);
sftp_unlink(sftp, "/tmp/sftp_symlink_test");
if (sftp_extension_supported(sftp, "statvfs@openssh.com", "2")) {
sftpstatvfs = sftp_statvfs(sftp, "/tmp");
if (sftpstatvfs == NULL) {
fprintf(stderr, "statvfs failed (%s)\n", ssh_get_error(session));
return;
}
sftpstatvfs = sftp_statvfs(sftp, "/tmp");
if (sftpstatvfs == NULL) {
fprintf(stderr, "statvfs failed (%s)\n", ssh_get_error(session));
goto end;
}
printf("sftp statvfs:\n"
"\tfile system block size: %llu\n"
"\tfundamental fs block size: %llu\n"
"\tnumber of blocks (unit f_frsize): %llu\n"
"\tfree blocks in file system: %llu\n"
"\tfree blocks for non-root: %llu\n"
"\ttotal file inodes: %llu\n"
"\tfree file inodes: %llu\n"
"\tfree file inodes for to non-root: %llu\n"
"\tfile system id: %llu\n"
"\tbit mask of f_flag values: %llu\n"
"\tmaximum filename length: %llu\n",
(unsigned long long) sftpstatvfs->f_bsize,
(unsigned long long) sftpstatvfs->f_frsize,
(unsigned long long) sftpstatvfs->f_blocks,
(unsigned long long) sftpstatvfs->f_bfree,
(unsigned long long) sftpstatvfs->f_bavail,
(unsigned long long) sftpstatvfs->f_files,
(unsigned long long) sftpstatvfs->f_ffree,
(unsigned long long) sftpstatvfs->f_favail,
(unsigned long long) sftpstatvfs->f_fsid,
(unsigned long long) sftpstatvfs->f_flag,
(unsigned long long) sftpstatvfs->f_namemax);
printf("sftp statvfs:\n"
"\tfile system block size: %llu\n"
"\tfundamental fs block size: %llu\n"
"\tnumber of blocks (unit f_frsize): %llu\n"
"\tfree blocks in file system: %llu\n"
"\tfree blocks for non-root: %llu\n"
"\ttotal file inodes: %llu\n"
"\tfree file inodes: %llu\n"
"\tfree file inodes for to non-root: %llu\n"
"\tfile system id: %llu\n"
"\tbit mask of f_flag values: %llu\n"
"\tmaximum filename length: %llu\n",
(unsigned long long) sftpstatvfs->f_bsize,
(unsigned long long) sftpstatvfs->f_frsize,
(unsigned long long) sftpstatvfs->f_blocks,
(unsigned long long) sftpstatvfs->f_bfree,
(unsigned long long) sftpstatvfs->f_bavail,
(unsigned long long) sftpstatvfs->f_files,
(unsigned long long) sftpstatvfs->f_ffree,
(unsigned long long) sftpstatvfs->f_favail,
(unsigned long long) sftpstatvfs->f_fsid,
(unsigned long long) sftpstatvfs->f_flag,
(unsigned long long) sftpstatvfs->f_namemax);
sftp_statvfs_free(sftpstatvfs);
sftp_statvfs_free(sftpstatvfs);
if (statvfs("/tmp", &sysstatvfs) < 0) {
fprintf(stderr, "statvfs failed (%s)\n", strerror(errno));
return;
}
if (statvfs("/tmp", &sysstatvfs) < 0) {
fprintf(stderr, "statvfs failed (%s)\n", strerror(errno));
goto end;
}
printf("sys statvfs:\n"
"\tfile system block size: %llu\n"
"\tfundamental fs block size: %llu\n"
"\tnumber of blocks (unit f_frsize): %llu\n"
"\tfree blocks in file system: %llu\n"
"\tfree blocks for non-root: %llu\n"
"\ttotal file inodes: %llu\n"
"\tfree file inodes: %llu\n"
"\tfree file inodes for to non-root: %llu\n"
"\tfile system id: %llu\n"
"\tbit mask of f_flag values: %llu\n"
"\tmaximum filename length: %llu\n",
(unsigned long long) sysstatvfs.f_bsize,
(unsigned long long) sysstatvfs.f_frsize,
(unsigned long long) sysstatvfs.f_blocks,
(unsigned long long) sysstatvfs.f_bfree,
(unsigned long long) sysstatvfs.f_bavail,
(unsigned long long) sysstatvfs.f_files,
(unsigned long long) sysstatvfs.f_ffree,
(unsigned long long) sysstatvfs.f_favail,
(unsigned long long) sysstatvfs.f_fsid,
(unsigned long long) sysstatvfs.f_flag,
(unsigned long long) sysstatvfs.f_namemax);
printf("sys statvfs:\n"
"\tfile system block size: %llu\n"
"\tfundamental fs block size: %llu\n"
"\tnumber of blocks (unit f_frsize): %llu\n"
"\tfree blocks in file system: %llu\n"
"\tfree blocks for non-root: %llu\n"
"\ttotal file inodes: %llu\n"
"\tfree file inodes: %llu\n"
"\tfree file inodes for to non-root: %llu\n"
"\tfile system id: %llu\n"
"\tbit mask of f_flag values: %llu\n"
"\tmaximum filename length: %llu\n",
(unsigned long long) sysstatvfs.f_bsize,
(unsigned long long) sysstatvfs.f_frsize,
(unsigned long long) sysstatvfs.f_blocks,
(unsigned long long) sysstatvfs.f_bfree,
(unsigned long long) sysstatvfs.f_bavail,
(unsigned long long) sysstatvfs.f_files,
(unsigned long long) sysstatvfs.f_ffree,
(unsigned long long) sysstatvfs.f_favail,
(unsigned long long) sysstatvfs.f_fsid,
(unsigned long long) sysstatvfs.f_flag,
(unsigned long long) sysstatvfs.f_namemax);
}
/* the connection is made */
/* opening a directory */
dir=sftp_opendir(sftp,"./");
if(!dir) {
dir = sftp_opendir(sftp, "./");
if (!dir) {
fprintf(stderr, "Directory not opened(%s)\n", ssh_get_error(session));
return ;
goto end;
}
/* reading the whole directory, file by file */
while((file=sftp_readdir(sftp,dir))){
while ((file = sftp_readdir(sftp, dir))) {
fprintf(stderr, "%30s(%.8o) : %s(%.5d) %s(%.5d) : %.10llu bytes\n",
file->name,
file->permissions,
file->owner,
file->uid,
file->group,
file->gid,
(long long unsigned int) file->size);
file->name,
file->permissions,
file->owner,
file->uid,
file->group,
file->gid,
(long long unsigned int) file->size);
sftp_attributes_free(file);
}
/* when file=NULL, an error has occured OR the directory listing is end of file */
if(!sftp_dir_eof(dir)){
/* when file = NULL, an error has occured OR the directory listing is end of
* file */
if (!sftp_dir_eof(dir)) {
fprintf(stderr, "Error: %s\n", ssh_get_error(session));
return;
goto end;
}
if(sftp_closedir(dir)){
if (sftp_closedir(dir)) {
fprintf(stderr, "Error: %s\n", ssh_get_error(session));
return;
goto end;
}
/* this will open a file and copy it into your /home directory */
/* the small buffer size was intended to stress the library. of course, you can use a buffer till 20kbytes without problem */
/* the small buffer size was intended to stress the library. of course, you
* can use a buffer till 20kbytes without problem */
fichier=sftp_open(sftp,"/usr/bin/ssh",O_RDONLY, 0);
if(!fichier){
fichier = sftp_open(sftp, "/usr/bin/ssh", O_RDONLY, 0);
if (!fichier) {
fprintf(stderr, "Error opening /usr/bin/ssh: %s\n",
ssh_get_error(session));
return;
ssh_get_error(session));
goto end;
}
/* open a file for writing... */
to=sftp_open(sftp,"ssh-copy",O_WRONLY | O_CREAT, 0700);
if(!to){
to = sftp_open(sftp, "ssh-copy", O_WRONLY | O_CREAT, 0700);
if (!to) {
fprintf(stderr, "Error opening ssh-copy for writing: %s\n",
ssh_get_error(session));
return;
ssh_get_error(session));
sftp_close(fichier);
goto end;
}
while((len=sftp_read(fichier,data,4096)) > 0){
if(sftp_write(to,data,len)!=len){
while ((len = sftp_read(fichier, data, 4096)) > 0) {
if (sftp_write(to, data, len) != len) {
fprintf(stderr, "Error writing %d bytes: %s\n",
len, ssh_get_error(session));
return;
len, ssh_get_error(session));
sftp_close(to);
sftp_close(fichier);
goto end;
}
}
printf("finished\n");
if(len<0)
if (len < 0) {
fprintf(stderr, "Error reading file: %s\n", ssh_get_error(session));
}
sftp_close(fichier);
sftp_close(to);
printf("fichiers ferm\n");
to=sftp_open(sftp,"/tmp/grosfichier",O_WRONLY|O_CREAT, 0644);
for(i=0;i<1000;++i){
len=sftp_write(to,data,DATALEN);
printf("wrote %d bytes\n",len);
if(len != DATALEN){
printf("chunk %d : %d (%s)\n",i,len,ssh_get_error(session));
to = sftp_open(sftp, "/tmp/grosfichier", O_WRONLY|O_CREAT, 0644);
for (i = 0; i < 1000; ++i) {
len = sftp_write(to, data, DATALEN);
printf("wrote %d bytes\n", len);
if (len != DATALEN) {
printf("chunk %d : %d (%s)\n", i, len, ssh_get_error(session));
}
}
sftp_close(to);
sftp_close(to);
end:
/* close the sftp session */
sftp_free(sftp);
printf("sftp session terminated\n");
}
static void usage(const char *argv0){
fprintf(stderr,"Usage : %s [-v] remotehost\n"
"sample sftp test client - libssh-%s\n"
"Options :\n"
" -v : increase log verbosity\n",
argv0,
ssh_version(0));
exit(0);
static void usage(const char *argv0) {
fprintf(stderr, "Usage : %s [-v] remotehost\n"
"sample sftp test client - libssh-%s\n"
"Options :\n"
" -v : increase log verbosity\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);
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;
}
}
destination = argv[optind];
if (destination == NULL) {
usage(argv[0]);
return -1;
}
}
destination=argv[optind];
if(destination == NULL){
usage(argv[0]);
return -1;
}
return 0;
return 0;
}
int main(int argc, char **argv){
ssh_session session;
if(opts(argc,argv)<0)
return EXIT_FAILURE;
session=connect_ssh(destination,NULL,verbosity);
if(session == NULL)
return EXIT_FAILURE;
do_sftp(session);
ssh_disconnect(session);
ssh_free(session);
return 0;
int main(int argc, char **argv) {
ssh_session session;
if (opts(argc, argv) < 0) {
return EXIT_FAILURE;
}
session = connect_ssh(destination, NULL, verbosity);
if (session == NULL) {
return EXIT_FAILURE;
}
do_sftp(session);
ssh_disconnect(session);
ssh_free(session);
return 0;
}
#endif

View File

@@ -48,12 +48,17 @@ static char *user;
static char *cmds[MAXCMD];
static struct termios terminal;
static char *pcap_file=NULL;
static char *pcap_file = NULL;
static char *proxycommand;
static int auth_callback(const char *prompt, char *buf, size_t len,
int echo, int verify, void *userdata) {
static int auth_callback(const char *prompt,
char *buf,
size_t len,
int echo,
int verify,
void *userdata)
{
(void) verify;
(void) userdata;
@@ -61,11 +66,12 @@ static int auth_callback(const char *prompt, char *buf, size_t len,
}
struct ssh_callbacks_struct cb = {
.auth_function=auth_callback,
.userdata=NULL
.auth_function = auth_callback,
.userdata = NULL,
};
static void add_cmd(char *cmd){
static void add_cmd(char *cmd)
{
int n;
for (n = 0; (n < MAXCMD) && cmds[n] != NULL; n++);
@@ -73,7 +79,8 @@ static void add_cmd(char *cmd){
if (n == MAXCMD) {
return;
}
cmds[n]=strdup(cmd);
cmds[n] = strdup(cmd);
}
static void usage(void)
@@ -98,37 +105,43 @@ static void usage(void)
exit(0);
}
static int opts(int argc, char **argv){
static int opts(int argc, char **argv)
{
int i;
// for(i=0;i<argc;i++)
// printf("%d : %s\n",i,argv[i]);
/* insert your own arguments here */
while((i=getopt(argc,argv,"T:P:"))!=-1){
while((i = getopt(argc,argv,"T:P:")) != -1) {
switch(i){
case 'P':
pcap_file=optarg;
break;
case 'P':
pcap_file = optarg;
break;
#ifndef _WIN32
case 'T':
proxycommand=optarg;
case 'T':
proxycommand = 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++];
while(optind < argc)
if (optind < argc) {
host = argv[optind++];
}
while(optind < argc) {
add_cmd(argv[optind++]);
if(host==NULL)
}
if (host == NULL) {
usage();
}
return 0;
}
#ifndef HAVE_CFMAKERAW
static void cfmakeraw(struct termios *termios_p){
static void cfmakeraw(struct termios *termios_p)
{
termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
termios_p->c_oflag &= ~OPOST;
termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
@@ -138,44 +151,53 @@ static void cfmakeraw(struct termios *termios_p){
#endif
static void do_cleanup(int i) {
static void do_cleanup(int i)
{
/* unused variable */
(void) i;
tcsetattr(0,TCSANOW,&terminal);
tcsetattr(0, TCSANOW, &terminal);
}
static void do_exit(int i) {
/* unused variable */
(void) i;
static void do_exit(int i)
{
/* unused variable */
(void) i;
do_cleanup(0);
exit(0);
do_cleanup(0);
exit(0);
}
ssh_channel chan;
int signal_delayed=0;
static ssh_channel chan;
static int signal_delayed = 0;
static void sigwindowchanged(int i){
(void) i;
signal_delayed=1;
static void sigwindowchanged(int i)
{
(void) i;
signal_delayed = 1;
}
static void setsignal(void){
static void setsignal(void)
{
signal(SIGWINCH, sigwindowchanged);
signal_delayed=0;
signal_delayed = 0;
}
static void sizechanged(void){
struct winsize win = { 0, 0, 0, 0 };
static void sizechanged(void)
{
struct winsize win = {
.ws_row = 0,
};
ioctl(1, TIOCGWINSZ, &win);
ssh_channel_change_pty_size(chan,win.ws_col, win.ws_row);
// printf("Changed pty size\n");
setsignal();
}
static void select_loop(ssh_session session,ssh_channel channel){
static void select_loop(ssh_session session,ssh_channel channel)
{
ssh_connector connector_in, connector_out, connector_err;
ssh_event event = ssh_event_new();
/* stdin */
@@ -196,9 +218,10 @@ static void select_loop(ssh_session session,ssh_channel channel){
ssh_connector_set_in_channel(connector_err, channel, SSH_CONNECTOR_STDERR);
ssh_event_add_connector(event, connector_err);
while(ssh_channel_is_open(channel)){
if(signal_delayed)
while (ssh_channel_is_open(channel)) {
if (signal_delayed) {
sizechanged();
}
ssh_event_dopoll(event, 60000);
}
ssh_event_remove_connector(event, connector_in);
@@ -213,121 +236,148 @@ static void select_loop(ssh_session session,ssh_channel channel){
ssh_channel_free(channel);
}
static void shell(ssh_session session){
static void shell(ssh_session session)
{
ssh_channel channel;
struct termios terminal_local;
int interactive=isatty(0);
channel = ssh_channel_new(session);
if(interactive){
tcgetattr(0,&terminal_local);
memcpy(&terminal,&terminal_local,sizeof(struct termios));
if (interactive) {
tcgetattr(0, &terminal_local);
memcpy(&terminal, &terminal_local, sizeof(struct termios));
}
if(ssh_channel_open_session(channel)){
printf("error opening channel : %s\n",ssh_get_error(session));
if (ssh_channel_open_session(channel)) {
printf("Error opening channel : %s\n", ssh_get_error(session));
return;
}
chan=channel;
if(interactive){
chan = channel;
if (interactive) {
ssh_channel_request_pty(channel);
sizechanged();
}
if(ssh_channel_request_shell(channel)){
printf("Requesting shell : %s\n",ssh_get_error(session));
if (ssh_channel_request_shell(channel)) {
printf("Requesting shell : %s\n", ssh_get_error(session));
return;
}
if(interactive){
if (interactive) {
cfmakeraw(&terminal_local);
tcsetattr(0,TCSANOW,&terminal_local);
tcsetattr(0, TCSANOW, &terminal_local);
setsignal();
}
signal(SIGTERM,do_cleanup);
select_loop(session,channel);
if(interactive)
do_cleanup(0);
signal(SIGTERM, do_cleanup);
select_loop(session, channel);
if (interactive) {
do_cleanup(0);
}
}
static void batch_shell(ssh_session session){
static void batch_shell(ssh_session session)
{
ssh_channel channel;
char buffer[1024];
int i,s=0;
for(i=0;i<MAXCMD && cmds[i];++i) {
s+=snprintf(buffer+s,sizeof(buffer)-s,"%s ",cmds[i]);
free(cmds[i]);
cmds[i] = NULL;
}
channel=ssh_channel_new(session);
size_t i;
int s = 0;
for (i = 0; i < MAXCMD && cmds[i]; ++i) {
s += snprintf(buffer + s, sizeof(buffer) - s, "%s ", cmds[i]);
free(cmds[i]);
cmds[i] = NULL;
}
channel = ssh_channel_new(session);
ssh_channel_open_session(channel);
if(ssh_channel_request_exec(channel,buffer)){
printf("error executing \"%s\" : %s\n",buffer,ssh_get_error(session));
if (ssh_channel_request_exec(channel, buffer)) {
printf("Error executing '%s' : %s\n", buffer, ssh_get_error(session));
return;
}
select_loop(session,channel);
select_loop(session, channel);
}
static int client(ssh_session session){
int auth=0;
char *banner;
int state;
if (user)
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0)
return -1;
if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0)
return -1;
if (proxycommand != NULL){
if(ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, proxycommand))
return -1;
}
ssh_options_parse_config(session, NULL);
static int client(ssh_session session)
{
int auth = 0;
char *banner;
int state;
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;
}
if(!cmds[0])
shell(session);
else
batch_shell(session);
return 0;
if (user) {
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
return -1;
}
}
if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0) {
return -1;
}
if (proxycommand != NULL) {
if (ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, proxycommand)) {
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;
}
if (cmds[0] == NULL) {
shell(session);
} else {
batch_shell(session);
}
return 0;
}
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(!pcap)
return;
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);
static ssh_pcap_file pcap;
static void set_pcap(ssh_session session)
{
if (pcap_file == NULL) {
return;
}
pcap = ssh_pcap_file_new();
if (pcap == NULL) {
return;
}
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(){
if(pcap)
ssh_pcap_file_free(pcap);
pcap=NULL;
static void cleanup_pcap(void)
{
if (pcap != NULL) {
ssh_pcap_file_free(pcap);
}
pcap = NULL;
}
int main(int argc, char **argv){
int main(int argc, char **argv)
{
ssh_session session;
session = ssh_new();
@@ -335,12 +385,13 @@ int main(int argc, char **argv){
ssh_callbacks_init(&cb);
ssh_set_callbacks(session,&cb);
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);
signal(SIGTERM, do_exit);
set_pcap(session);

View File

@@ -66,6 +66,9 @@
#define SSH_COM_AGENT2_FAILURE 102
#define SSH_AGENT_OLD_SIGNATURE 0x01
/* Signature flags from draft-miller-ssh-agent-02 */
#define SSH_AGENT_RSA_SHA2_256 0x02
#define SSH_AGENT_RSA_SHA2_512 0x04
struct ssh_agent_struct {
struct ssh_socket_struct *sock;

View File

@@ -24,20 +24,6 @@
#include <stdarg.h>
#include "libssh/libssh.h"
/*
* Describes a buffer state
* [XXXXXXXXXXXXDATA PAYLOAD XXXXXXXXXXXXXXXXXXXXXXXX]
* ^ ^ ^ ^]
* \_data points\_pos points here \_used points here | /
* here Allocated
*/
struct ssh_buffer_struct {
char *data;
uint32_t used;
uint32_t allocated;
uint32_t pos;
int secure;
};
#define SSH_BUFFER_PACK_END ((uint32_t) 0x4f65feb3)

View File

@@ -62,7 +62,11 @@ enum ssh_key_exchange_e {
/* curve25519-sha256@libssh.org */
SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG,
/* curve25519-sha256 */
SSH_KEX_CURVE25519_SHA256
SSH_KEX_CURVE25519_SHA256,
/* diffie-hellman-group16-sha512 */
SSH_KEX_DH_GROUP16_SHA512,
/* diffie-hellman-group18-sha512 */
SSH_KEX_DH_GROUP18_SHA512,
};
enum ssh_cipher_e {

View File

@@ -43,6 +43,7 @@ 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(uint32_t algo);
const char *ssh_kex_get_default_methods(uint32_t algo);
const char *ssh_kex_get_description(uint32_t algo);
#endif /* KEX_H_ */

View File

@@ -79,7 +79,7 @@
/* libssh version */
#define LIBSSH_VERSION_MAJOR 0
#define LIBSSH_VERSION_MINOR 8
#define LIBSSH_VERSION_MICRO 2
#define LIBSSH_VERSION_MICRO 3
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
LIBSSH_VERSION_MINOR, \
@@ -404,6 +404,7 @@ enum ssh_options_e {
SSH_OPTIONS_GSSAPI_AUTH,
SSH_OPTIONS_GLOBAL_KNOWNHOSTS,
SSH_OPTIONS_NODELAY,
SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
};
enum {
@@ -646,6 +647,11 @@ LIBSSH_API int ssh_pki_import_privkey_base64(const char *b64_key,
ssh_auth_callback auth_fn,
void *auth_data,
ssh_key *pkey);
LIBSSH_API int ssh_pki_export_privkey_base64(const ssh_key privkey,
const char *passphrase,
ssh_auth_callback auth_fn,
void *auth_data,
char **b64_key);
LIBSSH_API int ssh_pki_import_privkey_file(const char *filename,
const char *passphrase,
ssh_auth_callback auth_fn,
@@ -681,6 +687,9 @@ LIBSSH_API int ssh_pki_export_pubkey_file(const ssh_key key,
LIBSSH_API const char *ssh_pki_key_ecdsa_name(const ssh_key key);
LIBSSH_API char *ssh_get_fingerprint_hash(enum ssh_publickey_hash_type type,
unsigned char *hash,
size_t len);
LIBSSH_API void ssh_print_hash(enum ssh_publickey_hash_type type, unsigned char *hash, size_t len);
LIBSSH_API void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len);
LIBSSH_API int ssh_send_ignore (ssh_session session, const char *data);
@@ -756,12 +765,16 @@ LIBSSH_API void ssh_string_burn(ssh_string str);
LIBSSH_API ssh_string ssh_string_copy(ssh_string str);
LIBSSH_API void *ssh_string_data(ssh_string str);
LIBSSH_API int ssh_string_fill(ssh_string str, const void *data, size_t len);
#define SSH_STRING_FREE(x) \
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 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);
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_getpass(const char *prompt, char *buf, size_t len, int echo,
@@ -790,6 +803,8 @@ LIBSSH_API const char* ssh_get_hmac_out(ssh_session session);
LIBSSH_API ssh_buffer ssh_buffer_new(void);
LIBSSH_API void ssh_buffer_free(ssh_buffer buffer);
#define SSH_BUFFER_FREE(x) \
do { if ((x) != NULL) { ssh_buffer_free(x); x = NULL; } } while(0)
LIBSSH_API int ssh_buffer_reinit(ssh_buffer buffer);
LIBSSH_API int ssh_buffer_add_data(ssh_buffer buffer, const void *data, uint32_t len);
LIBSSH_API uint32_t ssh_buffer_get_data(ssh_buffer buffer, void *data, uint32_t requestedlen);

View File

@@ -335,11 +335,10 @@ public:
* @see ssh_get_issue_banner
*/
std::string getIssueBanner(){
char *banner=ssh_get_issue_banner(c_session);
std::string ret;
if (banner)
{
ret= std::string(banner);
char *banner = ssh_get_issue_banner(c_session);
std::string ret = "";
if (banner != NULL) {
ret = std::string(banner);
::free(banner);
}
return ret;

View File

@@ -51,6 +51,7 @@ SSH_PACKET_CALLBACK(ssh_packet_ignore_callback);
SSH_PACKET_CALLBACK(ssh_packet_dh_reply);
SSH_PACKET_CALLBACK(ssh_packet_newkeys);
SSH_PACKET_CALLBACK(ssh_packet_service_accept);
SSH_PACKET_CALLBACK(ssh_packet_ext_info);
#ifdef WITH_SERVER
SSH_PACKET_CALLBACK(ssh_packet_kexdh_init);

View File

@@ -69,6 +69,7 @@ struct ssh_key_struct {
struct ssh_signature_struct {
enum ssh_keytypes_e type;
enum ssh_digest_e hash_type;
const char *type_c;
#ifdef HAVE_LIBGCRYPT
gcry_sexp_t dsa_sig;
@@ -95,6 +96,11 @@ typedef struct ssh_signature_struct *ssh_signature;
ssh_key ssh_key_dup(const ssh_key key);
void ssh_key_clean (ssh_key key);
const char *
ssh_key_get_signature_algorithm(ssh_session session,
enum ssh_keytypes_e type);
enum ssh_keytypes_e ssh_key_type_from_signature_name(const char *name);
/* SSH Signature Functions */
ssh_signature ssh_signature_new(void);
void ssh_signature_free(ssh_signature sign);
@@ -133,4 +139,5 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
ssh_public_key ssh_pki_convert_key_to_publickey(const ssh_key key);
ssh_private_key ssh_pki_convert_key_to_privatekey(const ssh_key key);
int ssh_key_algorithm_allowed(ssh_session session, const char *type);
#endif /* PKI_H_ */

View File

@@ -45,6 +45,10 @@ int bcrypt_pbkdf(const char *pass,
int pki_key_ecdsa_nid_from_name(const char *name);
const char *pki_key_ecdsa_nid_to_name(int nid);
const char *ssh_key_signature_to_char(enum ssh_keytypes_e type,
enum ssh_digest_e hash_type);
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(const ssh_key key, int demote);
@@ -68,6 +72,9 @@ ssh_string pki_private_key_to_pem(const ssh_key key,
const char *passphrase,
ssh_auth_callback auth_fn,
void *auth_data);
int pki_import_privkey_buffer(enum ssh_keytypes_e type,
ssh_buffer buffer,
ssh_key *pkey);
/* SSH Public Key Functions */
int pki_pubkey_build_dss(ssh_key key,
@@ -81,11 +88,32 @@ int pki_pubkey_build_rsa(ssh_key key,
int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e);
ssh_string pki_publickey_to_blob(const ssh_key key);
/* SSH Private Key Functions */
int pki_privkey_build_dss(ssh_key key,
ssh_string p,
ssh_string q,
ssh_string g,
ssh_string pubkey,
ssh_string privkey);
int pki_privkey_build_rsa(ssh_key key,
ssh_string n,
ssh_string e,
ssh_string d,
ssh_string iqmp,
ssh_string p,
ssh_string q);
int pki_privkey_build_ecdsa(ssh_key key,
int nid,
ssh_string e,
ssh_string exp);
ssh_string pki_publickey_to_blob(const ssh_key key);
/* SSH Signature Functions */
ssh_string pki_signature_to_blob(const ssh_signature sign);
ssh_signature pki_signature_from_blob(const ssh_key pubkey,
const ssh_string sig_blob,
enum ssh_keytypes_e type);
enum ssh_keytypes_e type,
enum ssh_digest_e hash_type);
int pki_signature_verify(ssh_session session,
const ssh_signature sig,
const ssh_key key,
@@ -93,12 +121,18 @@ int pki_signature_verify(ssh_session session,
size_t hlen);
/* SSH Signing Functions */
ssh_signature pki_do_sign(const ssh_key privkey,
const unsigned char *hash,
size_t hlen);
ssh_signature pki_do_sign_sessionid(const ssh_key key,
const unsigned char *hash,
size_t hlen);
#define pki_do_sign(key, hash, hlen) \
pki_do_sign_hash(key, hash, hlen, SSH_DIGEST_AUTO)
ssh_signature pki_do_sign_hash(const ssh_key privkey,
const unsigned char *hash,
size_t hlen,
enum ssh_digest_e hash_type);
#define pki_do_sign_sessionid(key, hash, hlen) \
pki_do_sign_sessionid_hash(key, hash, hlen, SSH_DIGEST_AUTO)
ssh_signature pki_do_sign_sessionid_hash(const ssh_key key,
const unsigned char *hash,
size_t hlen,
enum ssh_digest_e hash_type);
int pki_ed25519_sign(const ssh_key privkey, ssh_signature sig,
const unsigned char *hash, size_t hlen);
int pki_ed25519_verify(const ssh_key pubkey, ssh_signature sig,
@@ -110,8 +144,12 @@ int pki_ed25519_key_dup(ssh_key new, const ssh_key key);
int pki_ed25519_public_key_to_blob(ssh_buffer buffer, ssh_key key);
ssh_string pki_ed25519_sig_to_blob(ssh_signature sig);
int pki_ed25519_sig_from_blob(ssh_signature sig, ssh_string sig_blob);
int pki_privkey_build_ed25519(ssh_key key,
ssh_string pubkey,
ssh_string privkey);
/* PKI Container OpenSSH */
ssh_key ssh_pki_openssh_pubkey_import(const char *text_key);
ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
const char *passphrase, ssh_auth_callback auth_fn, void *auth_data);
ssh_string ssh_pki_openssh_privkey_export(const ssh_key privkey,

View File

@@ -262,6 +262,8 @@ int compress_buffer(ssh_session session,ssh_buffer buf);
int decompress_buffer(ssh_session session,ssh_buffer buf, size_t maxlen);
/* match.c */
int match_pattern_list(const char *string, const char *pattern,
unsigned int len, int dolower);
int match_hostname(const char *host, const char *pattern, unsigned int len);
/* connector.c */

View File

@@ -86,6 +86,12 @@ enum ssh_pending_call_e {
#define SSH_OPT_FLAG_KBDINT_AUTH 0x4
#define SSH_OPT_FLAG_GSSAPI_AUTH 0x8
/* extensions flags */
/* server-sig-algs extension */
#define SSH_EXT_SIG_RSA_SHA256 0x01
#define SSH_EXT_SIG_RSA_SHA512 0x02
#define SSH_EXT_ALL SSH_EXT_SIG_RSA_SHA256 | SSH_EXT_SIG_RSA_SHA512
/* members that are common to ssh_session and ssh_bind */
struct ssh_common_struct {
struct error_struct error;
@@ -114,6 +120,9 @@ struct ssh_session_struct {
/* session flags (SSH_SESSION_FLAG_*) */
int flags;
/* Extensions negotiated using RFC 8308 */
uint32_t extensions;
ssh_string banner; /* that's the issue banner from
the server */
char *discon_msg; /* disconnect message from
@@ -196,6 +205,7 @@ struct ssh_session_struct {
char *knownhosts;
char *global_knownhosts;
char *wanted_methods[10];
char *pubkey_accepted_types;
char *ProxyCommand;
char *custombanner;
unsigned long timeout; /* seconds */

View File

@@ -84,6 +84,7 @@ struct sftp_session_struct {
int errnum;
void **handles;
sftp_ext ext;
sftp_packet read_packet;
};
struct sftp_packet_struct {
@@ -134,6 +135,7 @@ struct sftp_client_message_struct {
ssh_string data; /* can be newpath of rename() */
ssh_buffer complete_message; /* complete message in case of retransmission*/
char *str_data; /* cstring version of data */
char *submessage; /* for extended messages */
};
struct sftp_request_queue_struct {
@@ -862,6 +864,7 @@ LIBSSH_API const char *sftp_client_message_get_filename(sftp_client_message msg)
LIBSSH_API void sftp_client_message_set_filename(sftp_client_message msg, const char *newname);
LIBSSH_API const char *sftp_client_message_get_data(sftp_client_message msg);
LIBSSH_API uint32_t sftp_client_message_get_flags(sftp_client_message msg);
LIBSSH_API const char *sftp_client_message_get_submessage(sftp_client_message msg);
LIBSSH_API int sftp_send_client_message(sftp_session sftp, sftp_client_message msg);
LIBSSH_API int sftp_reply_name(sftp_client_message msg, const char *name,
sftp_attributes attr);
@@ -1011,6 +1014,7 @@ LIBSSH_API void sftp_handle_remove(sftp_session sftp, void *handle);
#define SFTP_RENAME SSH_FXP_RENAME
#define SFTP_READLINK SSH_FXP_READLINK
#define SFTP_SYMLINK SSH_FXP_SYMLINK
#define SFTP_EXTENDED SSH_FXP_EXTENDED
/* openssh flags */
#define SSH_FXE_STATVFS_ST_RDONLY 0x1 /* read-only */

View File

@@ -7,6 +7,7 @@
#define SSH2_MSG_DEBUG 4
#define SSH2_MSG_SERVICE_REQUEST 5
#define SSH2_MSG_SERVICE_ACCEPT 6
#define SSH2_MSG_EXT_INFO 7
#define SSH2_MSG_KEXINIT 20
#define SSH2_MSG_NEWKEYS 21

View File

@@ -27,6 +27,13 @@
#include "libssh/libgcrypt.h"
#include "libssh/libmbedcrypto.h"
enum ssh_digest_e {
SSH_DIGEST_AUTO=0,
SSH_DIGEST_SHA1=1,
SSH_DIGEST_SHA256,
SSH_DIGEST_SHA512
};
enum ssh_mac_e {
SSH_MAC_SHA1=1,
SSH_MAC_SHA256,

View File

@@ -1 +1 @@
4.6.0
4.7.0

View File

@@ -0,0 +1,415 @@
_ssh_log
buffer_free
buffer_get
buffer_get_len
buffer_new
channel_accept_x11
channel_change_pty_size
channel_close
channel_forward_accept
channel_forward_cancel
channel_forward_listen
channel_free
channel_get_exit_status
channel_get_session
channel_is_closed
channel_is_eof
channel_is_open
channel_new
channel_open_forward
channel_open_session
channel_poll
channel_read
channel_read_buffer
channel_read_nonblocking
channel_request_env
channel_request_exec
channel_request_pty
channel_request_pty_size
channel_request_send_signal
channel_request_sftp
channel_request_shell
channel_request_subsystem
channel_request_x11
channel_select
channel_send_eof
channel_set_blocking
channel_write
channel_write_stderr
privatekey_free
privatekey_from_file
publickey_free
publickey_from_file
publickey_from_privatekey
publickey_to_string
sftp_async_read
sftp_async_read_begin
sftp_attributes_free
sftp_canonicalize_path
sftp_chmod
sftp_chown
sftp_client_message_free
sftp_client_message_get_data
sftp_client_message_get_filename
sftp_client_message_get_flags
sftp_client_message_get_submessage
sftp_client_message_get_type
sftp_client_message_set_filename
sftp_close
sftp_closedir
sftp_dir_eof
sftp_extension_supported
sftp_extensions_get_count
sftp_extensions_get_data
sftp_extensions_get_name
sftp_file_set_blocking
sftp_file_set_nonblocking
sftp_free
sftp_fstat
sftp_fstatvfs
sftp_fsync
sftp_get_client_message
sftp_get_error
sftp_handle
sftp_handle_alloc
sftp_handle_remove
sftp_init
sftp_lstat
sftp_mkdir
sftp_new
sftp_new_channel
sftp_open
sftp_opendir
sftp_read
sftp_readdir
sftp_readlink
sftp_rename
sftp_reply_attr
sftp_reply_data
sftp_reply_handle
sftp_reply_name
sftp_reply_names
sftp_reply_names_add
sftp_reply_status
sftp_rewind
sftp_rmdir
sftp_seek
sftp_seek64
sftp_send_client_message
sftp_server_init
sftp_server_new
sftp_server_version
sftp_setstat
sftp_stat
sftp_statvfs
sftp_statvfs_free
sftp_symlink
sftp_tell
sftp_tell64
sftp_unlink
sftp_utimes
sftp_write
ssh_accept
ssh_add_channel_callbacks
ssh_auth_list
ssh_basename
ssh_bind_accept
ssh_bind_accept_fd
ssh_bind_fd_toaccept
ssh_bind_free
ssh_bind_get_fd
ssh_bind_listen
ssh_bind_new
ssh_bind_options_set
ssh_bind_set_blocking
ssh_bind_set_callbacks
ssh_bind_set_fd
ssh_blocking_flush
ssh_buffer_add_data
ssh_buffer_free
ssh_buffer_get
ssh_buffer_get_data
ssh_buffer_get_len
ssh_buffer_new
ssh_buffer_reinit
ssh_channel_accept_forward
ssh_channel_accept_x11
ssh_channel_cancel_forward
ssh_channel_change_pty_size
ssh_channel_close
ssh_channel_free
ssh_channel_get_exit_status
ssh_channel_get_session
ssh_channel_is_closed
ssh_channel_is_eof
ssh_channel_is_open
ssh_channel_listen_forward
ssh_channel_new
ssh_channel_open_auth_agent
ssh_channel_open_forward
ssh_channel_open_reverse_forward
ssh_channel_open_session
ssh_channel_open_x11
ssh_channel_poll
ssh_channel_poll_timeout
ssh_channel_read
ssh_channel_read_nonblocking
ssh_channel_read_timeout
ssh_channel_request_auth_agent
ssh_channel_request_env
ssh_channel_request_exec
ssh_channel_request_pty
ssh_channel_request_pty_size
ssh_channel_request_send_break
ssh_channel_request_send_exit_signal
ssh_channel_request_send_exit_status
ssh_channel_request_send_signal
ssh_channel_request_sftp
ssh_channel_request_shell
ssh_channel_request_subsystem
ssh_channel_request_x11
ssh_channel_select
ssh_channel_send_eof
ssh_channel_set_blocking
ssh_channel_set_counter
ssh_channel_window_size
ssh_channel_write
ssh_channel_write_stderr
ssh_clean_pubkey_hash
ssh_connect
ssh_connector_free
ssh_connector_new
ssh_connector_set_in_channel
ssh_connector_set_in_fd
ssh_connector_set_out_channel
ssh_connector_set_out_fd
ssh_copyright
ssh_dirname
ssh_disconnect
ssh_dump_knownhost
ssh_event_add_connector
ssh_event_add_fd
ssh_event_add_session
ssh_event_dopoll
ssh_event_free
ssh_event_new
ssh_event_remove_connector
ssh_event_remove_fd
ssh_event_remove_session
ssh_execute_message_callbacks
ssh_finalize
ssh_forward_accept
ssh_forward_cancel
ssh_forward_listen
ssh_free
ssh_get_cipher_in
ssh_get_cipher_out
ssh_get_clientbanner
ssh_get_disconnect_message
ssh_get_error
ssh_get_error_code
ssh_get_fd
ssh_get_fingerprint_hash
ssh_get_hexa
ssh_get_hmac_in
ssh_get_hmac_out
ssh_get_issue_banner
ssh_get_kex_algo
ssh_get_log_callback
ssh_get_log_level
ssh_get_log_userdata
ssh_get_openssh_version
ssh_get_poll_flags
ssh_get_pubkey
ssh_get_pubkey_hash
ssh_get_publickey
ssh_get_publickey_hash
ssh_get_random
ssh_get_server_publickey
ssh_get_serverbanner
ssh_get_status
ssh_get_version
ssh_getpass
ssh_gssapi_get_creds
ssh_gssapi_set_creds
ssh_handle_key_exchange
ssh_init
ssh_is_blocking
ssh_is_connected
ssh_is_server_known
ssh_key_cmp
ssh_key_free
ssh_key_is_private
ssh_key_is_public
ssh_key_new
ssh_key_type
ssh_key_type_from_name
ssh_key_type_to_char
ssh_known_hosts_parse_line
ssh_knownhosts_entry_free
ssh_log
ssh_message_auth_interactive_request
ssh_message_auth_kbdint_is_response
ssh_message_auth_password
ssh_message_auth_pubkey
ssh_message_auth_publickey
ssh_message_auth_publickey_state
ssh_message_auth_reply_pk_ok
ssh_message_auth_reply_pk_ok_simple
ssh_message_auth_reply_success
ssh_message_auth_set_methods
ssh_message_auth_user
ssh_message_channel_request_channel
ssh_message_channel_request_command
ssh_message_channel_request_env_name
ssh_message_channel_request_env_value
ssh_message_channel_request_open_destination
ssh_message_channel_request_open_destination_port
ssh_message_channel_request_open_originator
ssh_message_channel_request_open_originator_port
ssh_message_channel_request_open_reply_accept
ssh_message_channel_request_pty_height
ssh_message_channel_request_pty_pxheight
ssh_message_channel_request_pty_pxwidth
ssh_message_channel_request_pty_term
ssh_message_channel_request_pty_width
ssh_message_channel_request_reply_success
ssh_message_channel_request_subsystem
ssh_message_channel_request_x11_auth_cookie
ssh_message_channel_request_x11_auth_protocol
ssh_message_channel_request_x11_screen_number
ssh_message_channel_request_x11_single_connection
ssh_message_free
ssh_message_get
ssh_message_global_request_address
ssh_message_global_request_port
ssh_message_global_request_reply_success
ssh_message_reply_default
ssh_message_retrieve
ssh_message_service_reply_success
ssh_message_service_service
ssh_message_subtype
ssh_message_type
ssh_mkdir
ssh_new
ssh_options_copy
ssh_options_get
ssh_options_get_port
ssh_options_getopt
ssh_options_parse_config
ssh_options_set
ssh_pcap_file_close
ssh_pcap_file_free
ssh_pcap_file_new
ssh_pcap_file_open
ssh_pki_copy_cert_to_privkey
ssh_pki_export_privkey_base64
ssh_pki_export_privkey_file
ssh_pki_export_privkey_to_pubkey
ssh_pki_export_pubkey_base64
ssh_pki_export_pubkey_file
ssh_pki_generate
ssh_pki_import_cert_base64
ssh_pki_import_cert_file
ssh_pki_import_privkey_base64
ssh_pki_import_privkey_file
ssh_pki_import_pubkey_base64
ssh_pki_import_pubkey_file
ssh_pki_key_ecdsa_name
ssh_print_hash
ssh_print_hexa
ssh_privatekey_type
ssh_publickey_to_file
ssh_remove_channel_callbacks
ssh_scp_accept_request
ssh_scp_close
ssh_scp_deny_request
ssh_scp_free
ssh_scp_init
ssh_scp_leave_directory
ssh_scp_new
ssh_scp_pull_request
ssh_scp_push_directory
ssh_scp_push_file
ssh_scp_push_file64
ssh_scp_read
ssh_scp_request_get_filename
ssh_scp_request_get_permissions
ssh_scp_request_get_size
ssh_scp_request_get_size64
ssh_scp_request_get_warning
ssh_scp_write
ssh_select
ssh_send_debug
ssh_send_ignore
ssh_send_keepalive
ssh_server_init_kex
ssh_service_request
ssh_session_export_known_hosts_entry
ssh_session_has_known_hosts_entry
ssh_session_is_known_server
ssh_session_update_known_hosts
ssh_set_agent_channel
ssh_set_agent_socket
ssh_set_auth_methods
ssh_set_blocking
ssh_set_callbacks
ssh_set_channel_callbacks
ssh_set_counters
ssh_set_fd_except
ssh_set_fd_toread
ssh_set_fd_towrite
ssh_set_log_callback
ssh_set_log_level
ssh_set_log_userdata
ssh_set_message_callback
ssh_set_pcap_file
ssh_set_server_callbacks
ssh_silent_disconnect
ssh_string_burn
ssh_string_copy
ssh_string_data
ssh_string_fill
ssh_string_free
ssh_string_free_char
ssh_string_from_char
ssh_string_get_char
ssh_string_len
ssh_string_new
ssh_string_to_char
ssh_threads_get_noop
ssh_threads_get_pthread
ssh_threads_set_callbacks
ssh_try_publickey_from_file
ssh_userauth_agent
ssh_userauth_agent_pubkey
ssh_userauth_autopubkey
ssh_userauth_gssapi
ssh_userauth_kbdint
ssh_userauth_kbdint_getanswer
ssh_userauth_kbdint_getinstruction
ssh_userauth_kbdint_getname
ssh_userauth_kbdint_getnanswers
ssh_userauth_kbdint_getnprompts
ssh_userauth_kbdint_getprompt
ssh_userauth_kbdint_setanswer
ssh_userauth_list
ssh_userauth_none
ssh_userauth_offer_pubkey
ssh_userauth_password
ssh_userauth_privatekey_file
ssh_userauth_pubkey
ssh_userauth_publickey
ssh_userauth_publickey_auto
ssh_userauth_try_publickey
ssh_version
ssh_write_knownhost
string_burn
string_copy
string_data
string_fill
string_free
string_from_char
string_len
string_new
string_to_char

View File

@@ -548,6 +548,14 @@ ssh_string ssh_agent_sign_data(ssh_session session,
return NULL;
}
/* Add Flags: SHA2 extension (RFC 8332) if negotiated */
if (pubkey->type == SSH_KEYTYPE_RSA) {
if (session->extensions & SSH_EXT_SIG_RSA_SHA512) {
flags |= SSH_AGENT_RSA_SHA2_512;
} else if (session->extensions & SSH_EXT_SIG_RSA_SHA256) {
flags |= SSH_AGENT_RSA_SHA2_256;
}
}
if (ssh_buffer_add_u32(request, htonl(flags)) < 0) {
ssh_buffer_free(request);
return NULL;

View File

@@ -470,6 +470,7 @@ int ssh_userauth_try_publickey(ssh_session session,
const ssh_key pubkey)
{
ssh_string pubkey_s = NULL;
const char *sig_type_c = NULL;
int rc;
if (session == NULL) {
@@ -494,6 +495,34 @@ int ssh_userauth_try_publickey(ssh_session session,
return SSH_ERROR;
}
switch (pubkey->type) {
case SSH_KEYTYPE_UNKNOWN:
ssh_set_error(session,
SSH_REQUEST_DENIED,
"Invalid key type (unknown)");
return SSH_AUTH_DENIED;
case SSH_KEYTYPE_ECDSA:
sig_type_c = ssh_pki_key_ecdsa_name(pubkey);
break;
case SSH_KEYTYPE_DSS:
case SSH_KEYTYPE_RSA:
case SSH_KEYTYPE_RSA1:
case SSH_KEYTYPE_ED25519:
case SSH_KEYTYPE_DSS_CERT01:
case SSH_KEYTYPE_RSA_CERT01:
sig_type_c = ssh_key_get_signature_algorithm(session, pubkey->type);
break;
}
/* Check if the given public key algorithm is allowed */
if (!ssh_key_algorithm_allowed(session, sig_type_c)) {
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);
return SSH_AUTH_DENIED;
}
rc = ssh_userauth_request_service(session);
if (rc == SSH_AGAIN) {
return SSH_AUTH_AGAIN;
@@ -514,7 +543,7 @@ int ssh_userauth_try_publickey(ssh_session session,
"ssh-connection",
"publickey",
0, /* private key ? */
pubkey->type_c, /* algo */
sig_type_c, /* algo */
pubkey_s /* public key */
);
if (rc < 0) {
@@ -575,7 +604,7 @@ int ssh_userauth_publickey(ssh_session session,
{
ssh_string str = NULL;
int rc;
const char *type_c;
const char *sig_type_c = NULL;
enum ssh_keytypes_e key_type;
if (session == NULL) {
@@ -599,6 +628,37 @@ int ssh_userauth_publickey(ssh_session session,
return SSH_AUTH_ERROR;
}
/* Cert auth requires presenting the cert type name (*-cert@openssh.com) */
key_type = privkey->cert != NULL ? privkey->cert_type : privkey->type;
switch (key_type) {
case SSH_KEYTYPE_UNKNOWN:
ssh_set_error(session,
SSH_REQUEST_DENIED,
"Invalid key type (unknown)");
return SSH_AUTH_DENIED;
case SSH_KEYTYPE_ECDSA:
sig_type_c = ssh_pki_key_ecdsa_name(privkey);
break;
case SSH_KEYTYPE_DSS:
case SSH_KEYTYPE_RSA:
case SSH_KEYTYPE_RSA1:
case SSH_KEYTYPE_ED25519:
case SSH_KEYTYPE_DSS_CERT01:
case SSH_KEYTYPE_RSA_CERT01:
sig_type_c = ssh_key_get_signature_algorithm(session, key_type);
break;
}
/* Check if the given public key algorithm is allowed */
if (!ssh_key_algorithm_allowed(session, sig_type_c)) {
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);
return SSH_AUTH_DENIED;
}
rc = ssh_userauth_request_service(session);
if (rc == SSH_AGAIN) {
return SSH_AUTH_AGAIN;
@@ -606,10 +666,6 @@ int ssh_userauth_publickey(ssh_session session,
return SSH_AUTH_ERROR;
}
/* Cert auth requires presenting the cert type name (*-cert@openssh.com) */
key_type = privkey->cert != NULL ? privkey->cert_type : privkey->type;
type_c = ssh_key_type_to_char(key_type);
/* get public key or cert */
rc = ssh_pki_export_pubkey_blob(privkey, &str);
if (rc < 0) {
@@ -623,7 +679,7 @@ int ssh_userauth_publickey(ssh_session session,
"ssh-connection",
"publickey",
1, /* private key */
type_c, /* algo */
sig_type_c, /* algo */
str /* public key or cert */
);
if (rc < 0) {
@@ -672,7 +728,9 @@ static int ssh_userauth_agent_publickey(ssh_session session,
const char *username,
ssh_key pubkey)
{
ssh_string str = NULL;
ssh_string pubkey_s = NULL;
ssh_string sig_blob = NULL;
const char *sig_type_c = NULL;
int rc;
switch(session->pending_call_state) {
@@ -694,12 +752,22 @@ static int ssh_userauth_agent_publickey(ssh_session session,
return SSH_AUTH_ERROR;
}
/* public key */
rc = ssh_pki_export_pubkey_blob(pubkey, &str);
rc = ssh_pki_export_pubkey_blob(pubkey, &pubkey_s);
if (rc < 0) {
goto fail;
}
sig_type_c = ssh_key_get_signature_algorithm(session, pubkey->type);
/* Check if the given public key algorithm is allowed */
if (!ssh_key_algorithm_allowed(session, sig_type_c)) {
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);
SSH_STRING_FREE(pubkey_s);
return SSH_AUTH_DENIED;
}
/* request */
rc = ssh_buffer_pack(session->out_buffer, "bsssbsS",
@@ -708,24 +776,22 @@ static int ssh_userauth_agent_publickey(ssh_session session,
"ssh-connection",
"publickey",
1, /* private key */
pubkey->type_c, /* algo */
str /* public key */
sig_type_c, /* algo */
pubkey_s /* public key */
);
SSH_STRING_FREE(pubkey_s);
if (rc < 0) {
goto fail;
}
ssh_string_free(str);
/* sign the buffer with the private key */
str = ssh_pki_do_sign_agent(session, session->out_buffer, pubkey);
if (str == NULL) {
sig_blob = ssh_pki_do_sign_agent(session, session->out_buffer, pubkey);
if (sig_blob == NULL) {
goto fail;
}
rc = ssh_buffer_add_ssh_string(session->out_buffer, str);
ssh_string_free(str);
str = NULL;
rc = ssh_buffer_add_ssh_string(session->out_buffer, sig_blob);
SSH_STRING_FREE(sig_blob);
if (rc < 0) {
goto fail;
}
@@ -748,7 +814,7 @@ pending:
fail:
ssh_set_error_oom(session);
ssh_buffer_reinit(session->out_buffer);
ssh_string_free(str);
SSH_STRING_FREE(pubkey_s);
return SSH_AUTH_ERROR;
}
@@ -1514,7 +1580,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_info_request) {
return SSH_PACKET_USED;
}
session->kbdint->echo = malloc(nprompts);
session->kbdint->echo = calloc(nprompts, sizeof(unsigned char));
if (session->kbdint->echo == NULL) {
session->kbdint->nprompts = 0;
ssh_set_error_oom(session);
@@ -1523,7 +1589,6 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_info_request) {
return SSH_PACKET_USED;
}
memset(session->kbdint->echo, 0, nprompts);
for (i = 0; i < nprompts; i++) {
rc = ssh_buffer_unpack(packet, "sb",

View File

@@ -25,6 +25,7 @@
#include <limits.h>
#include <stdarg.h>
#include <stdbool.h>
#ifndef _WIN32
#include <netinet/in.h>
@@ -36,6 +37,24 @@
#include "libssh/misc.h"
#include "libssh/bignum.h"
/*
* Describes a buffer state
* [XXXXXXXXXXXXDATA PAYLOAD XXXXXXXXXXXXXXXXXXXXXXXX]
* ^ ^ ^ ^]
* \_data points\_pos points here \_used points here | /
* here Allocated
*/
struct ssh_buffer_struct {
bool secure;
size_t used;
size_t allocated;
size_t pos;
uint8_t *data;
};
/* Buffer size maximum is 256M */
#define BUFFER_SIZE_MAX 0x10000000
/**
* @defgroup libssh_buffer The SSH buffer functions.
* @ingroup libssh
@@ -54,24 +73,38 @@
*
* @param[in] buf The buffer to check.
*/
static void buffer_verify(ssh_buffer buf){
int doabort=0;
if(buf->data == NULL)
return;
if(buf->used > buf->allocated){
fprintf(stderr,"Buffer error : allocated %u, used %u\n",buf->allocated, buf->used);
doabort=1;
}
if(buf->pos > buf->used){
fprintf(stderr,"Buffer error : position %u, used %u\n",buf->pos, buf->used);
doabort=1;
}
if(buf->pos > buf->allocated){
fprintf(stderr,"Buffer error : position %u, allocated %u\n",buf->pos, buf->allocated);
doabort=1;
}
if(doabort)
abort();
static void buffer_verify(ssh_buffer buf)
{
bool do_abort = false;
if (buf->data == NULL) {
return;
}
if (buf->used > buf->allocated) {
fprintf(stderr,
"BUFFER ERROR: allocated %zu, used %zu\n",
buf->allocated,
buf->used);
do_abort = true;
}
if (buf->pos > buf->used) {
fprintf(stderr,
"BUFFER ERROR: position %zu, used %zu\n",
buf->pos,
buf->used);
do_abort = true;
}
if (buf->pos > buf->allocated) {
fprintf(stderr,
"BUFFER ERROR: position %zu, allocated %zu\n",
buf->pos,
buf->allocated);
do_abort = true;
}
if (do_abort) {
abort();
}
}
#else
@@ -83,15 +116,29 @@ static void buffer_verify(ssh_buffer buf){
*
* @return A newly initialized SSH buffer, NULL on error.
*/
struct ssh_buffer_struct *ssh_buffer_new(void) {
struct ssh_buffer_struct *buf =
calloc(1, sizeof(struct ssh_buffer_struct));
if (buf == NULL) {
return NULL;
}
struct ssh_buffer_struct *ssh_buffer_new(void)
{
struct ssh_buffer_struct *buf = NULL;
int rc;
buffer_verify(buf);
return buf;
buf = calloc(1, sizeof(struct ssh_buffer_struct));
if (buf == NULL) {
return NULL;
}
/*
* Always preallocate 64 bytes.
*
* -1 for ralloc_buffer magic.
*/
rc = ssh_buffer_allocate_size(buf, 64 - 1);
if (rc != 0) {
SAFE_FREE(buf);
return NULL;
}
buffer_verify(buf);
return buf;
}
/**
@@ -99,19 +146,23 @@ struct ssh_buffer_struct *ssh_buffer_new(void) {
*
* \param[in] buffer The buffer to free.
*/
void ssh_buffer_free(struct ssh_buffer_struct *buffer) {
if (buffer == NULL) {
return;
}
buffer_verify(buffer);
void ssh_buffer_free(struct ssh_buffer_struct *buffer)
{
if (buffer == NULL) {
return;
}
buffer_verify(buffer);
if (buffer->data) {
/* burn the data */
explicit_bzero(buffer->data, buffer->allocated);
SAFE_FREE(buffer->data);
}
explicit_bzero(buffer, sizeof(struct ssh_buffer_struct));
SAFE_FREE(buffer);
if (buffer->secure && buffer->allocated > 0) {
/* burn the data */
explicit_bzero(buffer->data, buffer->allocated);
SAFE_FREE(buffer->data);
explicit_bzero(buffer, sizeof(struct ssh_buffer_struct));
} else {
SAFE_FREE(buffer->data);
}
SAFE_FREE(buffer);
}
/**
@@ -122,13 +173,15 @@ void ssh_buffer_free(struct ssh_buffer_struct *buffer) {
*
* @param[in] buffer buffer to set secure.
*/
void ssh_buffer_set_secure(ssh_buffer buffer){
buffer->secure = 1;
void ssh_buffer_set_secure(ssh_buffer buffer)
{
buffer->secure = true;
}
static int realloc_buffer(struct ssh_buffer_struct *buffer, size_t needed) {
static int realloc_buffer(struct ssh_buffer_struct *buffer, size_t needed)
{
size_t smallest = 1;
char *new;
uint8_t *new = NULL;
buffer_verify(buffer);
@@ -140,25 +193,28 @@ static int realloc_buffer(struct ssh_buffer_struct *buffer, size_t needed) {
smallest <<= 1;
}
needed = smallest;
if (buffer->secure){
if (needed > BUFFER_SIZE_MAX) {
return -1;
}
if (buffer->secure) {
new = malloc(needed);
if (new == NULL) {
return -1;
}
if (buffer->used > 0) {
memcpy(new, buffer->data,buffer->used);
explicit_bzero(buffer->data, buffer->used);
SAFE_FREE(buffer->data);
}
memcpy(new, buffer->data, buffer->used);
explicit_bzero(buffer->data, buffer->used);
SAFE_FREE(buffer->data);
} else {
new = realloc(buffer->data, needed);
if (new == NULL) {
buffer->data = NULL;
return -1;
}
}
buffer->data = new;
buffer->allocated = needed;
buffer_verify(buffer);
return 0;
}
@@ -167,45 +223,64 @@ static int realloc_buffer(struct ssh_buffer_struct *buffer, size_t needed) {
* @brief shifts a buffer to remove unused data in the beginning
* @param buffer SSH buffer
*/
static void buffer_shift(ssh_buffer buffer){
uint32_t burn_pos = buffer->pos;
static void buffer_shift(ssh_buffer buffer)
{
size_t burn_pos = buffer->pos;
buffer_verify(buffer);
if(buffer->pos==0)
return;
memmove(buffer->data, buffer->data + buffer->pos, buffer->used - buffer->pos);
buffer->used -= buffer->pos;
buffer->pos=0;
buffer_verify(buffer);
if (buffer->secure){
void *ptr = buffer->data + buffer->used;
explicit_bzero(ptr, burn_pos);
}
if (buffer->pos == 0) {
return;
}
memmove(buffer->data,
buffer->data + buffer->pos,
buffer->used - buffer->pos);
buffer->used -= buffer->pos;
buffer->pos = 0;
buffer_verify(buffer);
if (buffer->secure) {
void *ptr = buffer->data + buffer->used;
explicit_bzero(ptr, burn_pos);
}
buffer_verify(buffer);
}
/**
* @brief Reinitialize a SSH buffer.
*
* In case the buffer has exceeded 64K in size, the buffer will be reallocated
* to 64K.
*
* @param[in] buffer The buffer to reinitialize.
*
* @return 0 on success, < 0 on error.
*/
int ssh_buffer_reinit(struct ssh_buffer_struct *buffer)
{
if (buffer == NULL) {
return -1;
}
buffer_verify(buffer);
if (buffer->used > 0) {
explicit_bzero(buffer->data, buffer->used);
if (buffer->secure && buffer->allocated > 0) {
explicit_bzero(buffer->data, buffer->allocated);
}
buffer->used = 0;
buffer->pos = 0;
if (buffer->allocated > 127) {
if (realloc_buffer(buffer, 127) < 0) {
/* If the buffer is bigger then 64K, reset it to 64K */
if (buffer->allocated > 65536) {
int rc;
/* -1 for realloc_buffer magic */
rc = realloc_buffer(buffer, 65536 - 1);
if (rc != 0) {
return -1;
}
}
buffer_verify(buffer);
return 0;
@@ -683,32 +758,153 @@ int ssh_buffer_validate_length(struct ssh_buffer_struct *buffer, size_t len)
*
* @returns The SSH String, NULL on error.
*/
struct ssh_string_struct *ssh_buffer_get_ssh_string(struct ssh_buffer_struct *buffer) {
uint32_t stringlen;
uint32_t hostlen;
struct ssh_string_struct *str = NULL;
int rc;
struct ssh_string_struct *
ssh_buffer_get_ssh_string(struct ssh_buffer_struct *buffer)
{
uint32_t stringlen;
uint32_t hostlen;
struct ssh_string_struct *str = NULL;
int rc;
if (ssh_buffer_get_u32(buffer, &stringlen) == 0) {
return NULL;
}
hostlen = ntohl(stringlen);
/* verify if there is enough space in buffer to get it */
rc = ssh_buffer_validate_length(buffer, hostlen);
if (rc != SSH_OK) {
return NULL; /* it is indeed */
}
str = ssh_string_new(hostlen);
if (str == NULL) {
return NULL;
}
if (ssh_buffer_get_data(buffer, ssh_string_data(str), hostlen) != hostlen) {
/* should never happen */
SAFE_FREE(str);
return NULL;
}
rc = ssh_buffer_get_u32(buffer, &stringlen);
if (rc == 0) {
return NULL;
}
hostlen = ntohl(stringlen);
/* verify if there is enough space in buffer to get it */
rc = ssh_buffer_validate_length(buffer, hostlen);
if (rc != SSH_OK) {
return NULL; /* it is indeed */
}
str = ssh_string_new(hostlen);
if (str == NULL) {
return NULL;
}
return str;
stringlen = ssh_buffer_get_data(buffer, ssh_string_data(str), hostlen);
if (stringlen != hostlen) {
/* should never happen */
SAFE_FREE(str);
return NULL;
}
return str;
}
/**
* @brief Pre-calculate the size we need for packing the buffer.
*
* This makes sure that enough memory is allocated for packing the buffer and
* we only have to do one memory allocation.
*
* @param[in] buffer The buffer to allocate
*
* @param[in] format A format string of arguments.
*
* @param[in] argc The number of arguments.
*
* @param[in] ap The va_list of arguments.
*
* @return SSH_OK on success, SSH_ERROR on error.
*/
static int ssh_buffer_pack_allocate_va(struct ssh_buffer_struct *buffer,
const char *format,
int argc,
va_list ap)
{
const char *p = NULL;
ssh_string string = NULL;
char *cstring = NULL;
size_t needed_size = 0;
size_t count;
size_t len;
int rc = SSH_OK;
for (p = format, count = 0; *p != '\0'; p++, count++) {
/* Invalid number of arguments passed */
if (argc != -1 && count > argc) {
return SSH_ERROR;
}
switch(*p) {
case 'b':
va_arg(ap, unsigned int);
needed_size += sizeof(uint8_t);
break;
case 'w':
va_arg(ap, unsigned int);
needed_size += sizeof(uint16_t);
break;
case 'd':
va_arg(ap, uint32_t);
needed_size += sizeof(uint32_t);
break;
case 'q':
va_arg(ap, uint64_t);
needed_size += sizeof(uint64_t);
break;
case 'S':
string = va_arg(ap, ssh_string);
needed_size += 4 + ssh_string_len(string);
string = NULL;
break;
case 's':
cstring = va_arg(ap, char *);
needed_size += sizeof(uint32_t) + strlen(cstring);
cstring = NULL;
break;
case 'P':
len = va_arg(ap, size_t);
needed_size += len;
va_arg(ap, void *);
count++; /* increase argument count */
break;
case 'B':
va_arg(ap, bignum);
/*
* Use a fixed size for a bignum
* (they should normaly be around 32)
*/
needed_size += 64;
break;
case 't':
cstring = va_arg(ap, char *);
needed_size += strlen(cstring);
cstring = NULL;
break;
default:
SSH_LOG(SSH_LOG_WARN, "Invalid buffer format %c", *p);
rc = SSH_ERROR;
}
if (rc != SSH_OK){
break;
}
}
if (argc != -1 && argc != count) {
return SSH_ERROR;
}
if (rc != SSH_ERROR){
/*
* Check if our canary is intact, if not, something really bad happened.
*/
uint32_t canary = va_arg(ap, uint32_t);
if (canary != SSH_BUFFER_PACK_END) {
if (argc == -1){
return SSH_ERROR;
} else {
abort();
}
}
}
rc = ssh_buffer_allocate_size(buffer, needed_size);
if (rc != 0) {
return SSH_ERROR;
}
return SSH_OK;
}
/** @internal
@@ -860,9 +1056,18 @@ int _ssh_buffer_pack(struct ssh_buffer_struct *buffer,
va_list ap;
int rc;
va_start(ap, argc);
rc = ssh_buffer_pack_allocate_va(buffer, format, argc, ap);
va_end(ap);
if (rc != SSH_OK) {
return rc;
}
va_start(ap, argc);
rc = ssh_buffer_pack_va(buffer, format, argc, ap);
va_end(ap);
return rc;
}
@@ -903,8 +1108,8 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
for (p = format, count = 0; *p != '\0'; p++, count++) {
/* Invalid number of arguments passed */
if (argc != -1 && count > argc) {
va_end(ap_copy);
return SSH_ERROR;
rc = SSH_ERROR;
goto cleanup;
}
switch (*p) {
@@ -1016,8 +1221,9 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
rc = SSH_ERROR;
}
cleanup:
if (rc != SSH_ERROR){
/* Check if our canary is intact, if not somthing really bad happened */
/* Check if our canary is intact, if not something really bad happened */
uint32_t canary = va_arg(ap, uint32_t);
if (canary != SSH_BUFFER_PACK_END){
if (argc == -1){
@@ -1034,22 +1240,53 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
for(p=format;p<last;++p){
switch(*p){
case 'b':
o.byte = va_arg(ap_copy, uint8_t *);
if (buffer->secure) {
explicit_bzero(o.byte, sizeof(uint8_t));
break;
}
break;
case 'w':
o.word = va_arg(ap_copy, uint16_t *);
if (buffer->secure) {
explicit_bzero(o.word, sizeof(uint16_t));
break;
}
break;
case 'd':
o.dword = va_arg(ap_copy, uint32_t *);
if (buffer->secure) {
explicit_bzero(o.dword, sizeof(uint32_t));
break;
}
break;
case 'q':
(void)va_arg(ap_copy, void *);
o.qword = va_arg(ap_copy, uint64_t *);
if (buffer->secure) {
explicit_bzero(o.qword, sizeof(uint64_t));
break;
}
break;
case 'S':
o.string=va_arg(ap_copy, ssh_string *);
o.string = va_arg(ap_copy, ssh_string *);
if (buffer->secure) {
ssh_string_burn(*o.string);
}
SAFE_FREE(*o.string);
break;
case 's':
o.cstring=va_arg(ap_copy, char **);
o.cstring = va_arg(ap_copy, char **);
if (buffer->secure) {
explicit_bzero(*o.cstring, strlen(*o.cstring));
}
SAFE_FREE(*o.cstring);
break;
case 'P':
(void)va_arg(ap_copy, size_t);
len = va_arg(ap_copy, size_t);
o.data = va_arg(ap_copy, void **);
if (buffer->secure) {
explicit_bzero(*o.data, len);
}
SAFE_FREE(*o.data);
break;
default:

View File

@@ -76,44 +76,46 @@ static ssh_channel channel_from_msg(ssh_session session, ssh_buffer packet);
*
* @return A pointer to a newly allocated channel, NULL on error.
*/
ssh_channel ssh_channel_new(ssh_session session) {
ssh_channel channel = NULL;
ssh_channel ssh_channel_new(ssh_session session)
{
ssh_channel channel = NULL;
if(session == NULL) {
return NULL;
}
if (session == NULL) {
return NULL;
}
channel = malloc(sizeof(struct ssh_channel_struct));
if (channel == NULL) {
ssh_set_error_oom(session);
return NULL;
}
memset(channel,0,sizeof(struct ssh_channel_struct));
channel = calloc(1, sizeof(struct ssh_channel_struct));
if (channel == NULL) {
ssh_set_error_oom(session);
return NULL;
}
channel->stdout_buffer = ssh_buffer_new();
if (channel->stdout_buffer == NULL) {
ssh_set_error_oom(session);
SAFE_FREE(channel);
return NULL;
}
channel->stdout_buffer = ssh_buffer_new();
if (channel->stdout_buffer == NULL) {
ssh_set_error_oom(session);
SAFE_FREE(channel);
return NULL;
}
channel->stderr_buffer = ssh_buffer_new();
if (channel->stderr_buffer == NULL) {
ssh_set_error_oom(session);
ssh_buffer_free(channel->stdout_buffer);
SAFE_FREE(channel);
return NULL;
}
channel->stderr_buffer = ssh_buffer_new();
if (channel->stderr_buffer == NULL) {
ssh_set_error_oom(session);
ssh_buffer_free(channel->stdout_buffer);
SAFE_FREE(channel);
return NULL;
}
channel->session = session;
channel->exit_status = -1;
channel->flags = SSH_CHANNEL_FLAG_NOT_BOUND;
channel->session = session;
channel->exit_status = -1;
channel->flags = SSH_CHANNEL_FLAG_NOT_BOUND;
if(session->channels == NULL) {
session->channels = ssh_list_new();
}
ssh_list_prepend(session->channels, channel);
return channel;
if (session->channels == NULL) {
session->channels = ssh_list_new();
}
ssh_list_prepend(session->channels, channel);
return channel;
}
/**
@@ -1005,22 +1007,24 @@ void ssh_channel_free(ssh_channel channel) {
* @brief Effectively free a channel, without caring about flags
*/
void ssh_channel_do_free(ssh_channel channel){
struct ssh_iterator *it;
ssh_session session = channel->session;
it = ssh_list_find(session->channels, channel);
if(it != NULL){
ssh_list_remove(session->channels, it);
}
ssh_buffer_free(channel->stdout_buffer);
ssh_buffer_free(channel->stderr_buffer);
if (channel->callbacks != NULL){
ssh_list_free(channel->callbacks);
}
void ssh_channel_do_free(ssh_channel channel)
{
struct ssh_iterator *it = NULL;
ssh_session session = channel->session;
/* debug trick to catch use after frees */
memset(channel, 'X', sizeof(struct ssh_channel_struct));
SAFE_FREE(channel);
it = ssh_list_find(session->channels, channel);
if (it != NULL) {
ssh_list_remove(session->channels, it);
}
ssh_buffer_free(channel->stdout_buffer);
ssh_buffer_free(channel->stderr_buffer);
if (channel->callbacks != NULL) {
ssh_list_free(channel->callbacks);
}
SAFE_FREE(channel);
}
/**
@@ -2631,7 +2635,11 @@ static int ssh_channel_read_termination(void *s){
*/
int ssh_channel_read(ssh_channel channel, void *dest, uint32_t count, int is_stderr)
{
return ssh_channel_read_timeout(channel, dest, count, is_stderr, -1);
return ssh_channel_read_timeout(channel,
dest,
count,
is_stderr,
SSH_TIMEOUT_DEFAULT);
}
/**
@@ -2712,7 +2720,7 @@ int ssh_channel_read_timeout(ssh_channel channel,
ctx.count = 1;
if (timeout_ms < 0) {
timeout_ms = SSH_TIMEOUT_DEFAULT;
timeout_ms = SSH_TIMEOUT_INFINITE;
}
rc = ssh_handle_packets_termination(session,
@@ -2722,7 +2730,12 @@ int ssh_channel_read_timeout(ssh_channel channel,
if (rc == SSH_ERROR){
return rc;
}
if (session->session_state == SSH_SESSION_STATE_ERROR){
/*
* If the channel is closed or in an error state, reading from it is an error
*/
if (session->session_state == SSH_SESSION_STATE_ERROR ||
channel->state == SSH_CHANNEL_STATE_CLOSED) {
return SSH_ERROR;
}
if (channel->remote_eof && ssh_buffer_get_len(stdbuf) == 0) {

View File

@@ -250,6 +250,8 @@ static int dh_handshake(ssh_session session) {
switch(session->next_crypto->kex_type){
case SSH_KEX_DH_GROUP1_SHA1:
case SSH_KEX_DH_GROUP14_SHA1:
case SSH_KEX_DH_GROUP16_SHA512:
case SSH_KEX_DH_GROUP18_SHA512:
rc = ssh_client_dh_init(session);
break;
#ifdef HAVE_ECDH

View File

@@ -30,6 +30,7 @@
#ifdef HAVE_GLOB_H
# include <glob.h>
#endif
#include <stdbool.h>
#include "libssh/priv.h"
#include "libssh/session.h"
@@ -72,6 +73,7 @@ enum ssh_config_opcode_e {
SOC_KBDINTERACTIVEAUTHENTICATION,
SOC_PASSWORDAUTHENTICATION,
SOC_PUBKEYAUTHENTICATION,
SOC_PUBKEYACCEPTEDTYPES,
SOC_END /* Keep this one last in the list */
};
@@ -144,7 +146,7 @@ static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
{ "preferredauthentications", SOC_UNSUPPORTED},
{ "proxyjump", SOC_UNSUPPORTED},
{ "proxyusefdpass", SOC_UNSUPPORTED},
{ "pubkeyacceptedtypes", SOC_UNSUPPORTED},
{ "pubkeyacceptedtypes", SOC_PUBKEYACCEPTEDTYPES},
{ "rekeylimit", SOC_UNSUPPORTED},
{ "remotecommand", SOC_UNSUPPORTED},
{ "revokedhostkeys", SOC_UNSUPPORTED},
@@ -184,6 +186,32 @@ static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
{ NULL, SOC_UNKNOWN }
};
enum ssh_config_match_e {
MATCH_UNKNOWN = -1,
MATCH_ALL,
MATCH_CANONICAL,
MATCH_EXEC,
MATCH_HOST,
MATCH_ORIGINALHOST,
MATCH_USER,
MATCH_LOCALUSER
};
struct ssh_config_match_keyword_table_s {
const char *name;
enum ssh_config_match_e opcode;
};
static struct ssh_config_match_keyword_table_s ssh_config_match_keyword_table[] = {
{ "all", MATCH_ALL },
{ "canonical", MATCH_CANONICAL },
{ "exec", MATCH_EXEC },
{ "host", MATCH_HOST },
{ "originalhost", MATCH_ORIGINALHOST },
{ "user", MATCH_USER },
{ "localuser", MATCH_LOCALUSER },
};
static int ssh_config_parse_line(ssh_session session, const char *line,
unsigned int count, int *parsing, int seen[]);
@@ -319,7 +347,7 @@ static void local_parse_file(ssh_session session, const char *filename, int *par
return;
}
#ifdef HAVE_GLOB
#if defined(HAVE_GLOB) && defined(HAVE_GLOB_GL_FLAGS_MEMBER)
static void local_parse_glob(ssh_session session,
const char *fileglob,
int *parsing,
@@ -348,7 +376,41 @@ static void local_parse_glob(ssh_session session,
globfree(&globbuf);
}
#endif /* HAVE_GLOB */
#endif /* HAVE_GLOB HAVE_GLOB_GL_FLAGS_MEMBER */
static enum ssh_config_match_e
ssh_config_get_match_opcode(const char *keyword)
{
size_t i;
for (i = 0; ssh_config_match_keyword_table[i].name != NULL; i++) {
if (strcasecmp(keyword, ssh_config_match_keyword_table[i].name) == 0) {
return ssh_config_match_keyword_table[i].opcode;
}
}
return MATCH_UNKNOWN;
}
static int
ssh_config_match(char *value, const char *pattern, bool negate)
{
int ok, result = 0;
char *lowervalue;
lowervalue = (value) ? ssh_lowercase(value) : NULL;
ok = match_pattern_list(lowervalue, pattern, strlen(pattern), 0);
if (ok <= 0 && negate == true) {
result = 1;
} else if (ok > 0 && negate == false) {
result = 1;
}
SSH_LOG(SSH_LOG_TRACE, "%s '%s' against pattern '%s'%s (ok=%d)",
result == 1 ? "Matched" : "Not matched", value, pattern,
negate == true ? " (negated)" : "", ok);
SAFE_FREE(lowervalue);
return result;
}
static int ssh_config_parse_line(ssh_session session, const char *line,
unsigned int count, int *parsing, int seen[]) {
@@ -383,7 +445,10 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
}
opcode = ssh_config_get_opcode(keyword);
if (*parsing == 1 && opcode != SOC_HOST && opcode != SOC_INCLUDE &&
if (*parsing == 1 &&
opcode != SOC_HOST &&
opcode != SOC_MATCH &&
opcode != SOC_INCLUDE &&
opcode > SOC_UNSUPPORTED) { /* Ignore all unknown types here */
if (seen[opcode] != 0) {
SAFE_FREE(x);
@@ -404,8 +469,108 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
#endif /* HAVE_GLOB */
}
break;
case SOC_MATCH: {
bool negate;
int result = 1;
size_t args = 0;
enum ssh_config_match_e opt;
*parsing = 0;
do {
p = ssh_config_get_str_tok(&s, NULL);
if (p == NULL || p[0] == '\0') {
break;
}
args++;
SSH_LOG(SSH_LOG_TRACE, "line %d: Processing Match keyword '%s'",
count, p);
/* If the option is prefixed with ! the result should be negated */
negate = false;
if (p[0] == '!') {
negate = true;
p++;
}
opt = ssh_config_get_match_opcode(p);
switch (opt) {
case MATCH_ALL:
p = ssh_config_get_str_tok(&s, NULL);
if (args == 1 && (p == NULL || p[0] == '\0')) {
/* The first argument and end of line */
if (negate == true) {
result = 0;
}
break;
}
ssh_set_error(session, SSH_FATAL,
"line %d: ERROR - Match all can not be combined with "
"other Match attributes", count);
SAFE_FREE(x);
return -1;
case MATCH_EXEC:
case MATCH_ORIGINALHOST:
case MATCH_LOCALUSER:
/* Skip one argument */
p = ssh_config_get_str_tok(&s, NULL);
args++;
FALL_THROUGH;
case MATCH_CANONICAL:
SSH_LOG(SSH_LOG_WARN, "line: %d: Unsupported Match keyword "
"'%s', Ignoring\n", count, p);
result = 0;
break;
case MATCH_HOST:
/* Here we match only one argument */
p = ssh_config_get_str_tok(&s, NULL);
if (p == NULL || p[0] == '\0') {
ssh_set_error(session, SSH_FATAL,
"line %d: ERROR - Match host keyword "
"requires argument", count);
SAFE_FREE(x);
return -1;
}
result &= ssh_config_match(session->opts.host, p, negate);
args++;
break;
case MATCH_USER:
/* Here we match only one argument */
p = ssh_config_get_str_tok(&s, NULL);
if (p == NULL || p[0] == '\0') {
ssh_set_error(session, SSH_FATAL,
"line %d: ERROR - Match user keyword "
"requires argument", count);
SAFE_FREE(x);
return -1;
}
result &= ssh_config_match(session->opts.username, p, negate);
args++;
break;
case MATCH_UNKNOWN:
default:
ssh_set_error(session, SSH_FATAL,
"ERROR - Unknown argument '%s' for Match keyword", p);
SAFE_FREE(x);
return -1;
}
} while (p != NULL && p[0] != '\0');
if (args == 0) {
ssh_set_error(session, SSH_FATAL,
"ERROR - Match keyword requires an argument");
SAFE_FREE(x);
return -1;
}
*parsing = result;
break;
}
case SOC_HOST: {
int ok = 0;
int ok = 0, result = -1;
*parsing = 0;
lowerhost = (session->opts.host) ? ssh_lowercase(session->opts.host) : NULL;
@@ -414,14 +579,17 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
p = ssh_config_get_str_tok(&s, NULL)) {
if (ok >= 0) {
ok = match_hostname(lowerhost, p, strlen(p));
if (ok < 0) {
*parsing = 0;
} else if (ok > 0) {
*parsing = 1;
if (result == -1 && ok < 0) {
result = 0;
} else if (result == -1 && ok > 0) {
result = 1;
}
}
}
SAFE_FREE(lowerhost);
if (result != -1) {
*parsing = result;
}
break;
}
case SOC_HOSTNAME:
@@ -592,6 +760,12 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, p);
}
break;
case SOC_PUBKEYACCEPTEDTYPES:
p = ssh_config_get_str_tok(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, p);
}
break;
case SOC_KEXALGORITHMS:
p = ssh_config_get_str_tok(&s, NULL);
if (p && *parsing) {

416
src/dh.c
View File

@@ -112,14 +112,164 @@ static unsigned char p_group14_value[] = {
#define P_GROUP14_LEN 256 /* Size in bytes of the p number for group 14 */
static unsigned char p_group16_value[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
#define P_GROUP16_LEN 512 /* Size in bytes of the p number for group 16 */
static unsigned char p_group18_value[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92,
0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, 0xC1, 0xD4, 0xDC, 0xB2,
0x60, 0x26, 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD,
0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, 0x2F,
0x41, 0x30, 0x01, 0xAE, 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31,
0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, 0xDA, 0x3E, 0xDB, 0xEB,
0xCF, 0x9B, 0x14, 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B,
0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51,
0x2B, 0xD7, 0xAF, 0x42, 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF,
0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, 0xF0, 0x32, 0xEA, 0x15,
0xD1, 0x72, 0x1D, 0x03, 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6,
0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31,
0x90, 0x0B, 0x1C, 0x9E, 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3,
0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, 0x0F, 0x1D, 0x45, 0xB7,
0xFF, 0x58, 0x5A, 0xC5, 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA,
0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, 0x14, 0xCC, 0x5E, 0xD2,
0x0F, 0x80, 0x37, 0xE0, 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28,
0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, 0xF5, 0x50, 0xAA, 0x3D,
0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C,
0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, 0x38, 0x7F, 0xE8, 0xD7,
0x6E, 0x3C, 0x04, 0x68, 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE,
0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, 0xE6, 0x94, 0xF9, 0x1E,
0x6D, 0xBE, 0x11, 0x59, 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4,
0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, 0xD8, 0xBE, 0xC4, 0xD0,
0x73, 0xB9, 0x31, 0xBA, 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00,
0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED, 0x25, 0x76, 0xF6, 0x93,
0x6B, 0xA4, 0x24, 0x66, 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68,
0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, 0x23, 0x8F, 0x16, 0xCB,
0xE3, 0x9D, 0x65, 0x2D, 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9,
0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07, 0x13, 0xEB, 0x57, 0xA8,
0x1A, 0x23, 0xF0, 0xC7, 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B,
0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, 0xFA, 0x9D, 0x4B, 0x7F,
0xA2, 0xC0, 0x87, 0xE8, 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A,
0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6, 0x6D, 0x2A, 0x13, 0xF8,
0x3F, 0x44, 0xF8, 0x2D, 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36,
0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, 0x64, 0xF3, 0x1C, 0xC5,
0x08, 0x46, 0x85, 0x1D, 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1,
0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73, 0xFA, 0xF3, 0x6B, 0xC3,
0x1E, 0xCF, 0xA2, 0x68, 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92,
0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, 0x88, 0x9A, 0x00, 0x2E,
0xD5, 0xEE, 0x38, 0x2B, 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47,
0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA, 0x9E, 0x30, 0x50, 0xE2,
0x76, 0x56, 0x94, 0xDF, 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71,
0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF};
#define P_GROUP18_LEN 1024 /* Size in bytes of the p number for group 18 */
static unsigned long g_int = 2 ; /* G is defined as 2 by the ssh2 standards */
static bignum g;
static bignum p_group1;
static bignum p_group14;
static bignum p_group16;
static bignum p_group18;
static int dh_crypto_initialized;
static bignum select_p(enum ssh_key_exchange_e type) {
return type == SSH_KEX_DH_GROUP14_SHA1 ? p_group14 : p_group1;
switch(type) {
case SSH_KEX_DH_GROUP1_SHA1:
return p_group1;
case SSH_KEX_DH_GROUP14_SHA1:
return p_group14;
case SSH_KEX_DH_GROUP16_SHA512:
return p_group16;
case SSH_KEX_DH_GROUP18_SHA512:
return p_group18;
default:
return NULL;
}
}
/**
@@ -151,6 +301,23 @@ int ssh_dh_init(void)
bignum_safe_free(g);
bignum_safe_free(p_group1);
return SSH_ERROR;
}
bignum_bin2bn(p_group16_value, P_GROUP16_LEN, &p_group16);
if (p_group16 == NULL) {
bignum_safe_free(g);
bignum_safe_free(p_group1);
bignum_safe_free(p_group14);
return SSH_ERROR;
}
bignum_bin2bn(p_group18_value, P_GROUP18_LEN, &p_group18);
if (p_group18 == NULL) {
bignum_safe_free(g);
bignum_safe_free(p_group1);
bignum_safe_free(p_group14);
bignum_safe_free(p_group16);
return SSH_ERROR;
}
#elif defined(HAVE_LIBCRYPTO)
@@ -170,12 +337,39 @@ int ssh_dh_init(void)
return SSH_ERROR;
}
bignum_bin2bn(p_group14_value, P_GROUP14_LEN, p_group14);
p_group16 = bignum_new();
if (p_group16 == NULL) {
bignum_safe_free(g);
bignum_safe_free(p_group1);
bignum_safe_free(p_group14);
return SSH_ERROR;
}
bignum_bin2bn(p_group16_value, P_GROUP16_LEN, p_group16);
p_group18 = bignum_new();
if (p_group18 == NULL) {
bignum_safe_free(g);
bignum_safe_free(p_group1);
bignum_safe_free(p_group14);
bignum_safe_free(p_group16);
return SSH_ERROR;
}
bignum_bin2bn(p_group18_value, P_GROUP18_LEN, p_group18);
#elif defined(HAVE_LIBMBEDCRYPTO)
p_group1 = bignum_new();
bignum_bin2bn(p_group1_value, P_GROUP1_LEN, p_group1);
p_group14 = bignum_new();
bignum_bin2bn(p_group14_value, P_GROUP14_LEN, p_group14);
p_group16 = bignum_new();
bignum_bin2bn(p_group16_value, P_GROUP16_LEN, p_group16);
p_group18 = bignum_new();
bignum_bin2bn(p_group18_value, P_GROUP18_LEN, p_group18);
#endif
dh_crypto_initialized = 1;
@@ -195,53 +389,83 @@ void ssh_dh_finalize(void)
bignum_safe_free(g);
bignum_safe_free(p_group1);
bignum_safe_free(p_group14);
bignum_safe_free(p_group16);
bignum_safe_free(p_group18);
dh_crypto_initialized = 0;
}
int ssh_dh_generate_x(ssh_session session) {
int keysize;
if (session->next_crypto->kex_type == SSH_KEX_DH_GROUP1_SHA1) {
keysize = 1023;
} else {
keysize = 2047;
}
session->next_crypto->x = bignum_new();
if (session->next_crypto->x == NULL) {
return -1;
}
int ssh_dh_generate_x(ssh_session session)
{
size_t keysize;
bignum_rand(session->next_crypto->x, keysize);
switch(session->next_crypto->kex_type) {
case SSH_KEX_DH_GROUP1_SHA1:
keysize = 1023;
break;
case SSH_KEX_DH_GROUP14_SHA1:
keysize = 2047;
break;
case SSH_KEX_DH_GROUP16_SHA512:
keysize = 4095;
break;
case SSH_KEX_DH_GROUP18_SHA512:
keysize = 8191;
break;
default:
return -1;
}
/* not harder than this */
session->next_crypto->x = bignum_new();
if (session->next_crypto->x == NULL) {
return -1;
}
bignum_rand(session->next_crypto->x, keysize);
/* not harder than this */
#ifdef DEBUG_CRYPTO
ssh_print_bignum("x", session->next_crypto->x);
ssh_print_bignum("x", session->next_crypto->x);
#endif
return 0;
return 0;
}
/* used by server */
int ssh_dh_generate_y(ssh_session session) {
int keysize;
if (session->next_crypto->kex_type == SSH_KEX_DH_GROUP1_SHA1) {
keysize = 1023;
} else {
keysize = 2047;
}
session->next_crypto->y = bignum_new();
if (session->next_crypto->y == NULL) {
return -1;
}
int ssh_dh_generate_y(ssh_session session)
{
size_t keysize;
bignum_rand(session->next_crypto->y, keysize);
switch(session->next_crypto->kex_type) {
case SSH_KEX_DH_GROUP1_SHA1:
keysize = 1023;
break;
case SSH_KEX_DH_GROUP14_SHA1:
keysize = 2047;
break;
case SSH_KEX_DH_GROUP16_SHA512:
keysize = 4095;
break;
case SSH_KEX_DH_GROUP18_SHA512:
keysize = 8191;
break;
default:
return -1;
}
/* not harder than this */
session->next_crypto->y = bignum_new();
if (session->next_crypto->y == NULL) {
return -1;
}
bignum_rand(session->next_crypto->y, keysize);
/* not harder than this */
#ifdef DEBUG_CRYPTO
ssh_print_bignum("y", session->next_crypto->y);
ssh_print_bignum("y", session->next_crypto->y);
#endif
return 0;
return 0;
}
/* used by server */
@@ -597,8 +821,11 @@ int ssh_make_sessionid(ssh_session session) {
goto error;
}
if (session->next_crypto->kex_type == SSH_KEX_DH_GROUP1_SHA1 ||
session->next_crypto->kex_type == SSH_KEX_DH_GROUP14_SHA1) {
switch(session->next_crypto->kex_type) {
case SSH_KEX_DH_GROUP1_SHA1:
case SSH_KEX_DH_GROUP14_SHA1:
case SSH_KEX_DH_GROUP16_SHA512:
case SSH_KEX_DH_GROUP18_SHA512:
rc = ssh_buffer_pack(buf,
"BB",
session->next_crypto->e,
@@ -606,11 +833,11 @@ int ssh_make_sessionid(ssh_session session) {
if (rc != SSH_OK) {
goto error;
}
break;
#ifdef HAVE_ECDH
} else if ((session->next_crypto->kex_type == SSH_KEX_ECDH_SHA2_NISTP256) ||
(session->next_crypto->kex_type == SSH_KEX_ECDH_SHA2_NISTP384) ||
(session->next_crypto->kex_type == SSH_KEX_ECDH_SHA2_NISTP521)) {
case SSH_KEX_ECDH_SHA2_NISTP256:
case SSH_KEX_ECDH_SHA2_NISTP384:
case SSH_KEX_ECDH_SHA2_NISTP521:
if (session->next_crypto->ecdh_client_pubkey == NULL ||
session->next_crypto->ecdh_server_pubkey == NULL) {
SSH_LOG(SSH_LOG_WARNING, "ECDH parameted missing");
@@ -623,10 +850,11 @@ int ssh_make_sessionid(ssh_session session) {
if (rc != SSH_OK) {
goto error;
}
break;
#endif
#ifdef HAVE_CURVE25519
} else if ((session->next_crypto->kex_type == SSH_KEX_CURVE25519_SHA256) ||
(session->next_crypto->kex_type == SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG)) {
case SSH_KEX_CURVE25519_SHA256:
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
rc = ssh_buffer_pack(buf,
"dPdP",
CURVE25519_PUBKEY_SIZE,
@@ -637,6 +865,7 @@ int ssh_make_sessionid(ssh_session session) {
if (rc != SSH_OK) {
goto error;
}
break;
#endif
}
rc = ssh_buffer_pack(buf, "B", session->next_crypto->k);
@@ -685,6 +914,8 @@ int ssh_make_sessionid(ssh_session session) {
sha384(ssh_buffer_get(buf), ssh_buffer_get_len(buf),
session->next_crypto->secret_hash);
break;
case SSH_KEX_DH_GROUP16_SHA512:
case SSH_KEX_DH_GROUP18_SHA512:
case SSH_KEX_ECDH_SHA2_NISTP521:
session->next_crypto->digest_len = SHA512_DIGEST_LENGTH;
session->next_crypto->mac_type = SSH_MAC_SHA512;
@@ -693,8 +924,9 @@ int ssh_make_sessionid(ssh_session session) {
ssh_set_error_oom(session);
goto error;
}
sha512(ssh_buffer_get(buf), ssh_buffer_get_len(buf),
session->next_crypto->secret_hash);
sha512(ssh_buffer_get(buf),
ssh_buffer_get_len(buf),
session->next_crypto->secret_hash);
break;
}
/* During the first kex, secret hash and session ID are equal. However, after
@@ -1269,6 +1501,79 @@ char *ssh_get_hexa(const unsigned char *what, size_t len) {
return hexa;
}
/**
* @brief Get a hash as a human-readable hex- or base64-string.
*
* This gets an allocated fingerprint hash. It is a hex strings if the given
* hash is a md5 sum. If it is a SHA sum, it will return an unpadded base64
* strings. Either way, the output is prepended by the hash-type.
*
* @param type Which sort of hash is given.
*
* @param hash What should be converted to a base64 string.
*
* @param len Length of the buffer to convert.
*
* @return Returns the allocated fingerprint hash or NULL on error.
*
* @see ssh_string_free_char()
*/
char *ssh_get_fingerprint_hash(enum ssh_publickey_hash_type type,
unsigned char *hash,
size_t len)
{
const char *prefix = "UNKNOWN";
char *fingerprint = NULL;
char *str = NULL;
size_t str_len;
int rc;
switch (type) {
case SSH_PUBLICKEY_HASH_SHA1:
case SSH_PUBLICKEY_HASH_SHA256:
fingerprint = ssh_get_b64_unpadded(hash, len);
break;
case SSH_PUBLICKEY_HASH_MD5:
fingerprint = ssh_get_hexa(hash, len);
break;
}
if (fingerprint == NULL) {
return NULL;
}
switch (type) {
case SSH_PUBLICKEY_HASH_MD5:
prefix = "MD5";
break;
case SSH_PUBLICKEY_HASH_SHA1:
prefix = "SHA1";
break;
case SSH_PUBLICKEY_HASH_SHA256:
prefix = "SHA256";
break;
}
str_len = strlen(prefix);
if (str_len + 1 + strlen(fingerprint) + 1 < str_len) {
SAFE_FREE(fingerprint);
return NULL;
}
str_len += 1 + strlen(fingerprint) + 1;
str = malloc(str_len);
if (str == NULL) {
SAFE_FREE(fingerprint);
return NULL;
}
rc = snprintf(str, str_len, "%s:%s", prefix, fingerprint);
SAFE_FREE(fingerprint);
if (rc < 0 || rc < (int)(str_len - 1)) {
SAFE_FREE(str);
}
return str;
}
/**
* @brief Print a hash as a human-readable hex- or base64-string.
*
@@ -1284,35 +1589,18 @@ char *ssh_get_hexa(const unsigned char *what, size_t len) {
*/
void ssh_print_hash(enum ssh_publickey_hash_type type,
unsigned char *hash,
size_t len) {
const char *prefix = "UNKNOWN";
size_t len)
{
char *fingerprint = NULL;
switch (type) {
case SSH_PUBLICKEY_HASH_SHA1:
case SSH_PUBLICKEY_HASH_SHA256:
fingerprint = ssh_get_b64_unpadded(hash, len);
break;
case SSH_PUBLICKEY_HASH_MD5:
fingerprint = ssh_get_hexa(hash, len);
break;
}
fingerprint = ssh_get_fingerprint_hash(type,
hash,
len);
if (fingerprint == NULL) {
return;
}
switch (type) {
case SSH_PUBLICKEY_HASH_MD5:
prefix = "MD5";
break;
case SSH_PUBLICKEY_HASH_SHA1:
prefix = "SHA1";
break;
case SSH_PUBLICKEY_HASH_SHA256:
prefix = "SHA256";
break;
}
fprintf(stderr, "%s:%s\n", prefix, fingerprint);
fprintf(stderr, "%s\n", fingerprint);
SAFE_FREE(fingerprint);
}

View File

@@ -49,11 +49,10 @@ static int ssh_gets(const char *prompt, char *buf, size_t len, int verify) {
char *ptr = NULL;
int ok = 0;
tmp = malloc(len);
tmp = calloc(1, len);
if (tmp == NULL) {
return 0;
}
memset(tmp,'\0',len);
/* read the password */
while (!ok) {
@@ -80,16 +79,15 @@ static int ssh_gets(const char *prompt, char *buf, size_t len, int verify) {
if (verify) {
char *key_string;
key_string = malloc(len);
key_string = calloc(1, len);
if (key_string == NULL) {
break;
}
memset(key_string, '\0', len);
fprintf(stdout, "\nVerifying, please re-enter. %s", prompt);
fflush(stdout);
if (! fgets(key_string, len, stdin)) {
memset(key_string, '\0', len);
explicit_bzero(key_string, len);
SAFE_FREE(key_string);
clearerr(stdin);
continue;
@@ -100,17 +98,17 @@ static int ssh_gets(const char *prompt, char *buf, size_t len, int verify) {
fprintf(stdout, "\n");
if (strcmp(buf, key_string)) {
printf("\n\07\07Mismatch - try again\n");
memset(key_string, '\0', len);
explicit_bzero(key_string, len);
SAFE_FREE(key_string);
fflush(stdout);
continue;
}
memset(key_string, '\0', len);
explicit_bzero(key_string, len);
SAFE_FREE(key_string);
}
ok = 1;
}
memset(tmp, '\0', len);
explicit_bzero(tmp, len);
free(tmp);
return ok;
@@ -152,7 +150,7 @@ int ssh_getpass(const char *prompt,
SetConsoleMode(h, mode);
if (!ok) {
memset (buf, '\0', len);
explicit_bzero(buf, len);
return -1;
}
@@ -273,7 +271,7 @@ int ssh_getpass(const char *prompt,
}
if (!ok) {
memset (buf, '\0', len);
explicit_bzero(buf, len);
return -1;
}

View File

@@ -39,11 +39,10 @@ static z_stream *initcompress(ssh_session session, int level) {
z_stream *stream = NULL;
int status;
stream = malloc(sizeof(z_stream));
stream = calloc(1, sizeof(z_stream));
if (stream == NULL) {
return NULL;
}
memset(stream, 0, sizeof(z_stream));
status = deflateInit(stream, level);
if (status != Z_OK) {
@@ -128,11 +127,10 @@ static z_stream *initdecompress(ssh_session session) {
z_stream *stream = NULL;
int status;
stream = malloc(sizeof(z_stream));
stream = calloc(1, sizeof(z_stream));
if (stream == NULL) {
return NULL;
}
memset(stream,0,sizeof(z_stream));
status = inflateInit(stream);
if (status != Z_OK) {

View File

@@ -86,25 +86,28 @@
#ifdef HAVE_ECDH
#define ECDH "ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,"
#define HOSTKEYS "ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-rsa,ssh-dss"
#define PUBLIC_KEY_ALGORITHMS "ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-rsa,rsa-sha2-512,rsa-sha2-256,ssh-dss"
#else
#ifdef HAVE_DSA
#define HOSTKEYS "ssh-ed25519,ssh-rsa,ssh-dss"
#define PUBLIC_KEY_ALGORITHMS "ssh-ed25519,ssh-rsa,rsa-sha2-512,rsa-sha2-256,ssh-dss"
#else
#define HOSTKEYS "ssh-ed25519,ssh-rsa"
#define PUBLIC_KEY_ALGORITHMS "ssh-ed25519,ssh-rsa,rsa-sha2-512,rsa-sha2-256"
#endif
#define ECDH ""
#endif
#define CHACHA20 "chacha20-poly1305@openssh.com,"
#define KEY_EXCHANGE CURVE25519 ECDH "diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"
#define KEY_EXCHANGE CURVE25519 ECDH "diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"
#define KEX_METHODS_SIZE 10
/* RFC 8308 */
#define KEX_EXTENSION_CLIENT "ext-info-c"
/* NOTE: This is a fixed API and the index is defined by ssh_kex_types_e */
static const char *default_methods[] = {
KEY_EXCHANGE,
HOSTKEYS,
PUBLIC_KEY_ALGORITHMS,
AES BLOWFISH DES,
AES BLOWFISH DES,
"hmac-sha2-256,hmac-sha2-512,hmac-sha1",
@@ -119,7 +122,7 @@ static const char *default_methods[] = {
/* NOTE: This is a fixed API and the index is defined by ssh_kex_types_e */
static const char *supported_methods[] = {
KEY_EXCHANGE,
HOSTKEYS,
PUBLIC_KEY_ALGORITHMS,
CHACHA20 AES BLOWFISH DES_SUPPORTED,
CHACHA20 AES BLOWFISH DES_SUPPORTED,
"hmac-sha2-256,hmac-sha2-512,hmac-sha1",
@@ -232,6 +235,15 @@ char **ssh_space_tokenize(const char *chain){
return tokens;
}
const char *ssh_kex_get_default_methods(uint32_t algo)
{
if (algo >= KEX_METHODS_SIZE) {
return NULL;
}
return default_methods[algo];
}
const char *ssh_kex_get_supported_method(uint32_t algo) {
if (algo >= KEX_METHODS_SIZE) {
return NULL;
@@ -403,10 +415,10 @@ out:
}
SSH_PACKET_CALLBACK(ssh_packet_kexinit){
int i;
int i, ok;
int server_kex=session->server;
ssh_string str = NULL;
char *strings[KEX_METHODS_SIZE];
char *strings[KEX_METHODS_SIZE] = {0};
int rc = SSH_ERROR;
uint8_t first_kex_packet_follows = 0;
@@ -415,7 +427,6 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit){
(void)type;
(void)user;
memset(strings, 0, sizeof(strings));
if (session->session_state == SSH_SESSION_STATE_AUTHENTICATED){
SSH_LOG(SSH_LOG_WARNING, "Other side initiating key re-exchange");
} else if(session->session_state != SSH_SESSION_STATE_INITIAL_KEX){
@@ -507,6 +518,22 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit){
goto error;
}
/*
* If client sent a ext-info-c message in the kex list, it supports
* RFC 8308 extension negotiation.
*/
ok = ssh_match_group(session->next_crypto->client_kex.methods[SSH_KEX],
KEX_EXTENSION_CLIENT);
if (ok) {
/*
* Enable all the supported extensions and when the time comes
* (after NEWKEYS) send them to the client.
*/
SSH_LOG(SSH_LOG_DEBUG, "The client supports extension "
"negotiation: enabling all extensions");
session->extensions = SSH_EXT_ALL;
}
/*
* Remember whether 'first_kex_packet_follows' was set and the client
* guess was wrong: in this case the next SSH_MSG_KEXDH_INIT message
@@ -642,11 +669,15 @@ static char *ssh_client_select_hostkeys(ssh_session session)
* @brief sets the key exchange parameters to be sent to the server,
* in function of the options and available methods.
*/
int ssh_set_client_kex(ssh_session session){
int ssh_set_client_kex(ssh_session session)
{
struct ssh_kex_struct *client= &session->next_crypto->client_kex;
const char *wanted;
char *kex = NULL;
char *kex_tmp = NULL;
int ok;
int i;
size_t kex_len, len;
ok = ssh_get_random(client->cookie, 16, 0);
if (!ok) {
@@ -673,6 +704,23 @@ int ssh_set_client_kex(ssh_session session){
}
}
/* Here we append ext-info-c to the list of kex algorithms */
kex = client->methods[SSH_KEX];
len = strlen(kex);
if (len + strlen(KEX_EXTENSION_CLIENT) + 2 < len) {
/* Overflow */
return SSH_ERROR;
}
kex_len = len + strlen(KEX_EXTENSION_CLIENT) + 2; /* comma, NULL */
kex_tmp = realloc(kex, kex_len);
if (kex_tmp == NULL) {
free(kex);
ssh_set_error_oom(session);
return SSH_ERROR;
}
snprintf(kex_tmp + len, kex_len - len, ",%s", KEX_EXTENSION_CLIENT);
client->methods[SSH_KEX] = kex_tmp;
return SSH_OK;
}
@@ -682,8 +730,16 @@ int ssh_set_client_kex(ssh_session session){
int ssh_kex_select_methods (ssh_session session){
struct ssh_kex_struct *server = &session->next_crypto->server_kex;
struct ssh_kex_struct *client = &session->next_crypto->client_kex;
char *ext_start = NULL;
int i;
/* Here we should drop the ext-info-c from the list so we avoid matching.
* it. We added it to the end, so we can just truncate the string here */
ext_start = strstr(client->methods[SSH_KEX], ","KEX_EXTENSION_CLIENT);
if (ext_start != NULL) {
ext_start[0] = '\0';
}
for (i = 0; i < KEX_METHODS_SIZE; i++) {
session->next_crypto->kex_methods[i]=ssh_find_matching(server->methods[i],client->methods[i]);
if(session->next_crypto->kex_methods[i] == NULL && i < SSH_LANG_C_S){
@@ -699,6 +755,10 @@ int ssh_kex_select_methods (ssh_session session){
session->next_crypto->kex_type=SSH_KEX_DH_GROUP1_SHA1;
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group14-sha1") == 0){
session->next_crypto->kex_type=SSH_KEX_DH_GROUP14_SHA1;
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group16-sha512") == 0){
session->next_crypto->kex_type=SSH_KEX_DH_GROUP16_SHA512;
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group18-sha512") == 0){
session->next_crypto->kex_type=SSH_KEX_DH_GROUP18_SHA512;
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp256") == 0){
session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP256;
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp384") == 0){

View File

@@ -172,7 +172,7 @@ void evp_update(EVPCTX ctx, const void *data, unsigned long len)
void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen)
{
*mdlen = mbedtls_md_get_size(ctx->md_info);
mbedtls_md_hmac_finish(ctx, md);
mbedtls_md_finish(ctx, md);
mbedtls_md_free(ctx);
SAFE_FREE(ctx);
}

View File

@@ -424,3 +424,10 @@ LIBSSH_4_6_0 # Released
ssh_print_hash;
} LIBSSH_4_5_0;
LIBSSH_4_7_0 # Released
{
global:
sftp_client_message_get_submessage;
ssh_get_fingerprint_hash;
ssh_pki_export_privkey_base64;
} LIBSSH_4_6_0;

View File

@@ -119,7 +119,7 @@ static int match_pattern(const char *s, const char *pattern) {
* Returns -1 if negation matches, 1 if there is a positive match, 0 if there is
* no match at all.
*/
static int match_pattern_list(const char *string, const char *pattern,
int match_pattern_list(const char *string, const char *pattern,
unsigned int len, int dolower) {
char sub[1024];
int negated;

View File

@@ -645,7 +645,8 @@ error:
*/
static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
ssh_message msg,
const char *service)
const char *service,
ssh_string algo)
{
struct ssh_crypto_struct *crypto =
session->current_crypto ? session->current_crypto :
@@ -673,7 +674,7 @@ static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
service,
"publickey", /* method */
1, /* has to be signed (true) */
msg->auth_request.pubkey->type_c, /* pubkey algorithm */
ssh_string_get_char(algo), /* pubkey algorithm */
str); /* public key as a blob */
ssh_string_free(str);
@@ -785,13 +786,13 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
if (rc != SSH_OK) {
goto error;
}
ssh_string_free(algo);
algo = NULL;
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;
@@ -804,10 +805,14 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
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);
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");
@@ -834,6 +839,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_VALID;
}
ssh_string_free(algo);
goto end;
}
#ifdef WITH_GSSAPI

View File

@@ -217,7 +217,7 @@ char *ssh_get_user_home_dir(void) {
char *szPath = NULL;
struct passwd pwd;
struct passwd *pwdbuf;
char buf[NSS_BUFLEN_PASSWD];
char buf[NSS_BUFLEN_PASSWD] = {0};
int rc;
rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
@@ -226,7 +226,6 @@ char *ssh_get_user_home_dir(void) {
if (szPath == NULL) {
return NULL;
}
memset(buf, 0, sizeof(buf));
snprintf(buf, sizeof(buf), "%s", szPath);
return strdup(buf);

View File

@@ -147,6 +147,14 @@ int ssh_options_copy(ssh_session src, ssh_session *dest) {
return -1;
}
}
if (src->opts.pubkey_accepted_types != NULL) {
new->opts.pubkey_accepted_types = strdup(src->opts.pubkey_accepted_types);
if (new->opts.pubkey_accepted_types == NULL) {
ssh_free(new);
return -1;
}
}
new->opts.fd = src->opts.fd;
new->opts.port = src->opts.port;
new->opts.timeout = src->opts.timeout;
@@ -343,6 +351,11 @@ int ssh_options_set_algo(ssh_session session,
* comma-separated list). ex:
* "ssh-rsa,ssh-dss,ecdh-sha2-nistp256"
*
* - SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES:
* Set the preferred public key algorithms to be used for
* authentication (const char *, comma-separated list). ex:
* "ssh-rsa,rsa-sha2-256,ssh-dss,ecdh-sha2-nistp256"
*
* - SSH_OPTIONS_COMPRESSION_C_S:
* Set the compression to use for client to server
* communication (const char *, "yes", "no" or a specific
@@ -743,6 +756,24 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
return -1;
}
break;
case SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES:
v = value;
if (v == NULL || v[0] == '\0') {
ssh_set_error_invalid(session);
return -1;
} else {
p = ssh_keep_known_algos(SSH_HOSTKEYS, v);
if (p == NULL) {
ssh_set_error(session, SSH_REQUEST_DENIED,
"Setting method: no known public key algorithm (%s)",
v);
return -1;
}
SAFE_FREE(session->opts.pubkey_accepted_types);
session->opts.pubkey_accepted_types = p;
}
break;
case SSH_OPTIONS_HMAC_C_S:
v = value;
if (v == NULL || v[0] == '\0') {

View File

@@ -59,8 +59,9 @@ static ssh_packet_callback default_packet_handlers[]= {
NULL,
#endif
ssh_packet_service_accept, // SSH2_MSG_SERVICE_ACCEPT 6
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, // 7-19
ssh_packet_ext_info, // SSH2_MSG_EXT_INFO 7
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, // 8-19
ssh_packet_kexinit, // SSH2_MSG_KEXINIT 20
ssh_packet_newkeys, // SSH2_MSG_NEWKEYS 21
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -198,7 +199,9 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
return 0;
}
memset(&session->in_packet, 0, sizeof(PACKET));
session->in_packet = (struct packet_struct) {
.type = 0,
};
if (session->in_buffer) {
rc = ssh_buffer_reinit(session->in_buffer);
@@ -514,20 +517,24 @@ SSH_PACKET_CALLBACK(ssh_packet_unimplemented){
/** @internal
* @parse the "Type" header field of a packet and updates the session
*/
int ssh_packet_parse_type(ssh_session session) {
memset(&session->in_packet, 0, sizeof(PACKET));
if(session->in_buffer == NULL) {
return SSH_ERROR;
}
int ssh_packet_parse_type(struct ssh_session_struct *session)
{
session->in_packet = (struct packet_struct) {
.type = 0,
};
if(ssh_buffer_get_u8(session->in_buffer, &session->in_packet.type) == 0) {
ssh_set_error(session, SSH_FATAL, "Packet too short to read type");
return SSH_ERROR;
}
if (session->in_buffer == NULL) {
return SSH_ERROR;
}
session->in_packet.valid = 1;
if (ssh_buffer_get_u8(session->in_buffer, &session->in_packet.type) == 0) {
ssh_set_error(session, SSH_FATAL, "Packet too short to read type");
return SSH_ERROR;
}
return SSH_OK;
session->in_packet.valid = 1;
return SSH_OK;
}
/*

View File

@@ -106,6 +106,8 @@ SSH_PACKET_CALLBACK(ssh_packet_dh_reply){
switch(session->next_crypto->kex_type){
case SSH_KEX_DH_GROUP1_SHA1:
case SSH_KEX_DH_GROUP14_SHA1:
case SSH_KEX_DH_GROUP16_SHA512:
case SSH_KEX_DH_GROUP18_SHA512:
rc=ssh_client_dh_reply(session, packet);
break;
#ifdef HAVE_ECDH
@@ -270,3 +272,61 @@ SSH_PACKET_CALLBACK(ssh_packet_service_accept){
return SSH_PACKET_USED;
}
/**
* @internal
* @brief handles a SSH2_MSG_EXT_INFO packet defined in RFC 8308
*
*/
SSH_PACKET_CALLBACK(ssh_packet_ext_info)
{
int rc;
uint32_t nr_extensions = 0;
uint32_t i;
(void)type;
(void)user;
SSH_LOG(SSH_LOG_PACKET, "Received SSH_MSG_EXT_INFO");
rc = ssh_buffer_get_u32(packet, &nr_extensions);
if (rc == 0) {
SSH_LOG(SSH_LOG_PACKET, "Failed to read number of extensions");
return SSH_PACKET_USED;
}
nr_extensions = ntohl(nr_extensions);
if (nr_extensions > 128) {
SSH_LOG(SSH_LOG_PACKET, "Invalid number of extensions");
return SSH_PACKET_USED;
}
SSH_LOG(SSH_LOG_PACKET, "Follows %u extensions", nr_extensions);
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) {
SSH_LOG(SSH_LOG_PACKET, "Error reading extension name-value pair");
return SSH_PACKET_USED;
}
cmp = strcmp(name, "server-sig-algs");
if (cmp == 0) {
/* TODO check for NULL bytes */
SSH_LOG(SSH_LOG_PACKET, "Extension: %s=<%s>", name, value);
if (ssh_match_group(value, "rsa-sha2-512")) {
session->extensions |= SSH_EXT_SIG_RSA_SHA512;
}
if (ssh_match_group(value, "rsa-sha2-256")) {
session->extensions |= SSH_EXT_SIG_RSA_SHA256;
}
}
free(name);
free(value);
}
return SSH_PACKET_USED;
}

597
src/pki.c
View File

@@ -193,6 +193,36 @@ enum ssh_keytypes_e ssh_key_type(const ssh_key key){
return key->type;
}
/**
* @brief Convert a signature type to a string.
*
* @param[in] type The algorithm type to convert.
*
* @return A string for the keytype or NULL if unknown.
*/
const char *
ssh_key_signature_to_char(enum ssh_keytypes_e type,
enum ssh_digest_e hash_type)
{
if (type != SSH_KEYTYPE_RSA) {
return ssh_key_type_to_char(type);
}
switch (hash_type) {
case SSH_DIGEST_SHA256:
return "rsa-sha2-256";
case SSH_DIGEST_SHA512:
return "rsa-sha2-512";
case SSH_DIGEST_SHA1:
return "ssh-rsa";
default:
return NULL;
}
/* We should never reach this */
return NULL;
}
/**
* @brief Convert a key type to a string.
*
@@ -223,6 +253,124 @@ const char *ssh_key_type_to_char(enum ssh_keytypes_e type) {
return NULL;
}
static enum ssh_digest_e ssh_key_hash_from_name(const char *name)
{
if (name == NULL) {
/* TODO we should rather fail */
return SSH_DIGEST_AUTO;
}
if (strcmp(name, "ssh-rsa") == 0) {
return SSH_DIGEST_SHA1;
} else if (strcmp(name, "rsa-sha2-256") == 0) {
return SSH_DIGEST_SHA256;
} else if (strcmp(name, "rsa-sha2-512") == 0) {
return SSH_DIGEST_SHA512;
}
/* we do not care for others now */
return SSH_DIGEST_AUTO;
}
/**
* @brief Checks the given key against the configured allowed
* public key algorithm types
*
* @param[in] session The SSH session
* @parma[in] type The key algorithm to check
* @returns 1 if the key algorithm is allowed 0 otherwise
*/
int ssh_key_algorithm_allowed(ssh_session session, const char *type)
{
const char *allowed_list;
allowed_list = session->opts.pubkey_accepted_types;
if (allowed_list == NULL) {
allowed_list = ssh_kex_get_default_methods(SSH_HOSTKEYS);
}
SSH_LOG(SSH_LOG_DEBUG, "Checking %s with list <%s>", type, allowed_list);
return ssh_match_group(allowed_list, type);
}
/**
* @brief Convert a key type to a hash type. This is usually unambiguous
* for all the key types, unless the SHA2 extension (RFC 8332) is
* negotiated during key exchange.
*
* @param[in] session SSH Session.
*
* @param[in] type The type to convert.
*
* @return A hash type to be used.
*/
enum ssh_digest_e ssh_key_type_to_hash(ssh_session session,
enum ssh_keytypes_e type)
{
switch (type) {
case SSH_KEYTYPE_RSA:
if (ssh_key_algorithm_allowed(session, "rsa-sha2-512") &&
(session->extensions & SSH_EXT_SIG_RSA_SHA512)) {
return SSH_DIGEST_SHA512;
}
if (ssh_key_algorithm_allowed(session, "rsa-sha2-256") &&
(session->extensions & SSH_EXT_SIG_RSA_SHA256)) {
return SSH_DIGEST_SHA256;
}
/* Default algorithm for RSA is SHA1 */
return SSH_DIGEST_SHA1;
default:
/* Other key types use the default value (not used) */
return SSH_DIGEST_AUTO;
}
/* We should never reach this */
return SSH_DIGEST_AUTO;
}
/**
* @brief Gets signature algorithm name to be used with the given
* key type.
*
* @param[in] session SSH session.
* @param[in] type The algorithm type to convert.
*
* @return A string for the keytype or NULL if unknown.
*/
const char *
ssh_key_get_signature_algorithm(ssh_session session,
enum ssh_keytypes_e type)
{
enum ssh_digest_e hash_type;
hash_type = ssh_key_type_to_hash(session, type);
return ssh_key_signature_to_char(type, hash_type);
}
/**
* @brief Convert a ssh key algorithm name to a ssh key algorithm type.
*
* @param[in] name The name to convert.
*
* @return The enum ssh key algorithm type.
*/
enum ssh_keytypes_e ssh_key_type_from_signature_name(const char *name) {
if (name == NULL) {
return SSH_KEYTYPE_UNKNOWN;
}
if ((strcmp(name, "rsa-sha2-256") == 0) ||
(strcmp(name, "rsa-sha2-512") == 0)) {
return SSH_KEYTYPE_RSA;
}
/* Otherwise the key type matches the signature type */
return ssh_key_type_from_name(name);
}
/**
* @brief Convert a ssh key name to a ssh key type.
*
@@ -448,6 +596,62 @@ int ssh_pki_import_privkey_base64(const char *b64_key,
return SSH_OK;
}
/**
* @brief Convert a private key to a pem base64 encoded key, or OpenSSH format for
* keytype ssh-ed25519
*
* @param[in] privkey The private key to export.
*
* @param[in] passphrase The passphrase to use to encrypt the key with or
* NULL. An empty string means no passphrase.
*
* @param[in] auth_fn An auth function you may want to use or NULL.
*
* @param[in] auth_data Private data passed to the auth function.
*
* @param[out] b64_key A pointer to store the allocated base64 encoded key. You
* need to free the buffer.
*
* @return SSH_OK on success, SSH_ERROR on error.
*/
int ssh_pki_export_privkey_base64(const ssh_key privkey,
const char *passphrase,
ssh_auth_callback auth_fn,
void *auth_data,
char **b64_key)
{
ssh_string blob = NULL;
char *b64 = NULL;
if (privkey == NULL || !ssh_key_is_private(privkey)) {
return SSH_ERROR;
}
if (privkey->type == SSH_KEYTYPE_ED25519){
blob = ssh_pki_openssh_privkey_export(privkey,
passphrase,
auth_fn,
auth_data);
} else {
blob = pki_private_key_to_pem(privkey,
passphrase,
auth_fn,
auth_data);
}
if (blob == NULL) {
return SSH_ERROR;
}
b64 = strndup(ssh_string_data(blob), ssh_string_len(blob));
ssh_string_free(blob);
if (b64 == NULL) {
return SSH_ERROR;
}
*b64_key = b64;
return SSH_OK;
}
/**
* @brief Import a key from a file.
@@ -662,10 +866,183 @@ ssh_private_key ssh_pki_convert_key_to_privatekey(const ssh_key key) {
return privkey;
}
int pki_import_privkey_buffer(enum ssh_keytypes_e type,
ssh_buffer buffer,
ssh_key *pkey)
{
ssh_key key = NULL;
int rc;
key = ssh_key_new();
if (key == NULL) {
return SSH_ERROR;
}
key->type = type;
key->type_c = ssh_key_type_to_char(type);
key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC;
switch (type) {
case SSH_KEYTYPE_DSS:
{
ssh_string p = NULL;
ssh_string q = NULL;
ssh_string g = NULL;
ssh_string pubkey = NULL;
ssh_string privkey = NULL;
rc = ssh_buffer_unpack(buffer, "SSSSS", &p, &q, &g,
&pubkey, &privkey);
if (rc != SSH_OK) {
SSH_LOG(SSH_LOG_WARN, "Unpack error");
goto fail;
}
rc = pki_privkey_build_dss(key, p, q, g, pubkey, privkey);
#ifdef DEBUG_CRYPTO
ssh_print_hexa("p", ssh_string_data(p), ssh_string_len(p));
ssh_print_hexa("q", ssh_string_data(q), ssh_string_len(q));
ssh_print_hexa("g", ssh_string_data(g), ssh_string_len(g));
ssh_print_hexa("pubkey", ssh_string_data(pubkey),
ssh_string_len(pubkey));
ssh_print_hexa("privkey", ssh_string_data(privkey),
ssh_string_len(privkey));
#endif
ssh_string_burn(p);
ssh_string_free(p);
ssh_string_burn(q);
ssh_string_free(q);
ssh_string_burn(g);
ssh_string_free(g);
ssh_string_burn(pubkey);
ssh_string_free(pubkey);
ssh_string_burn(privkey);
ssh_string_free(privkey);
if (rc == SSH_ERROR) {
goto fail;
}
}
break;
case SSH_KEYTYPE_RSA:
{
ssh_string n = NULL;
ssh_string e = NULL;
ssh_string d = NULL;
ssh_string iqmp = NULL;
ssh_string p = NULL;
ssh_string q = NULL;
rc = ssh_buffer_unpack(buffer, "SSSSSS", &n, &e, &d,
&iqmp, &p, &q);
if (rc != SSH_OK) {
SSH_LOG(SSH_LOG_WARN, "Unpack error");
goto fail;
}
rc = pki_privkey_build_rsa(key, n, e, d, iqmp, p, q);
#ifdef DEBUG_CRYPTO
ssh_print_hexa("n", ssh_string_data(n), ssh_string_len(n));
ssh_print_hexa("e", ssh_string_data(e), ssh_string_len(e));
ssh_print_hexa("d", ssh_string_data(d), ssh_string_len(d));
ssh_print_hexa("iqmp", ssh_string_data(iqmp),
ssh_string_len(iqmp));
ssh_print_hexa("p", ssh_string_data(p), ssh_string_len(p));
ssh_print_hexa("q", ssh_string_data(q), ssh_string_len(q));
#endif
ssh_string_burn(n);
ssh_string_free(n);
ssh_string_burn(e);
ssh_string_free(e);
ssh_string_burn(d);
ssh_string_free(d);
ssh_string_burn(iqmp);
ssh_string_free(iqmp);
ssh_string_burn(p);
ssh_string_free(p);
ssh_string_burn(q);
ssh_string_free(q);
if (rc == SSH_ERROR) {
SSH_LOG(SSH_LOG_WARN, "Failed to build RSA private key");
goto fail;
}
}
break;
#ifdef HAVE_ECC
case SSH_KEYTYPE_ECDSA:
{
ssh_string e = NULL;
ssh_string exp = NULL;
ssh_string i = NULL;
int nid;
rc = ssh_buffer_unpack(buffer, "SSS", &i, &e, &exp);
if (rc != SSH_OK) {
SSH_LOG(SSH_LOG_WARN, "Unpack error");
goto fail;
}
nid = pki_key_ecdsa_nid_from_name(ssh_string_get_char(i));
ssh_string_free(i);
if (nid == -1) {
goto fail;
}
rc = pki_privkey_build_ecdsa(key, nid, e, exp);
ssh_string_burn(e);
ssh_string_free(e);
ssh_string_burn(exp);
ssh_string_free(exp);
if (rc < 0) {
SSH_LOG(SSH_LOG_WARN, "Failed to build ECDSA private key");
goto fail;
}
/* Update key type */
key->type_c = ssh_pki_key_ecdsa_name(key);
}
break;
#endif
case SSH_KEYTYPE_ED25519:
{
ssh_string pubkey = NULL, privkey = NULL;
rc = ssh_buffer_unpack(buffer, "SS", &pubkey, &privkey);
if (rc != SSH_OK){
SSH_LOG(SSH_LOG_WARN, "Unpack error");
goto fail;
}
rc = pki_privkey_build_ed25519(key, pubkey, privkey);
ssh_string_burn(privkey);
ssh_string_free(privkey);
ssh_string_free(pubkey);
if (rc != SSH_OK) {
SSH_LOG(SSH_LOG_WARN, "Failed to build ed25519 key");
goto fail;
}
}
break;
case SSH_KEYTYPE_DSS_CERT01:
case SSH_KEYTYPE_RSA_CERT01:
case SSH_KEYTYPE_RSA1:
case SSH_KEYTYPE_UNKNOWN:
default:
SSH_LOG(SSH_LOG_WARN, "Unknown private key type (%d)", type);
goto fail;
}
*pkey = key;
return SSH_OK;
fail:
ssh_key_free(key);
return SSH_ERROR;
}
static int pki_import_pubkey_buffer(ssh_buffer buffer,
enum ssh_keytypes_e type,
ssh_key *pkey) {
ssh_key key;
ssh_key key = NULL;
int rc;
key = ssh_key_new();
@@ -680,40 +1057,14 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
switch (type) {
case SSH_KEYTYPE_DSS:
{
ssh_string p;
ssh_string q;
ssh_string g;
ssh_string pubkey;
p = ssh_buffer_get_ssh_string(buffer);
if (p == NULL) {
goto fail;
}
q = ssh_buffer_get_ssh_string(buffer);
if (q == NULL) {
ssh_string_burn(p);
ssh_string_free(p);
goto fail;
}
g = ssh_buffer_get_ssh_string(buffer);
if (g == NULL) {
ssh_string_burn(p);
ssh_string_free(p);
ssh_string_burn(q);
ssh_string_free(q);
goto fail;
}
pubkey = ssh_buffer_get_ssh_string(buffer);
if (pubkey == NULL) {
ssh_string_burn(p);
ssh_string_free(p);
ssh_string_burn(q);
ssh_string_free(q);
ssh_string_burn(g);
ssh_string_free(g);
ssh_string p = NULL;
ssh_string q = NULL;
ssh_string g = NULL;
ssh_string pubkey = NULL;
rc = ssh_buffer_unpack(buffer, "SSSS", &p, &q, &g, &pubkey);
if (rc != SSH_OK) {
SSH_LOG(SSH_LOG_WARN, "Unpack error");
goto fail;
}
@@ -732,24 +1083,19 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
ssh_string_burn(pubkey);
ssh_string_free(pubkey);
if (rc == SSH_ERROR) {
SSH_LOG(SSH_LOG_WARN, "Failed to build DSA public key");
goto fail;
}
}
break;
case SSH_KEYTYPE_RSA:
{
ssh_string e;
ssh_string n;
e = ssh_buffer_get_ssh_string(buffer);
if (e == NULL) {
goto fail;
}
n = ssh_buffer_get_ssh_string(buffer);
if (n == NULL) {
ssh_string_burn(e);
ssh_string_free(e);
ssh_string e = NULL;
ssh_string n = NULL;
rc = ssh_buffer_unpack(buffer, "SS", &e, &n);
if (rc != SSH_OK) {
SSH_LOG(SSH_LOG_WARN, "Unpack error");
goto fail;
}
@@ -763,6 +1109,7 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
ssh_string_burn(n);
ssh_string_free(n);
if (rc == SSH_ERROR) {
SSH_LOG(SSH_LOG_WARN, "Failed to build RSA public key");
goto fail;
}
}
@@ -770,30 +1117,27 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
#ifdef HAVE_ECC
case SSH_KEYTYPE_ECDSA:
{
ssh_string e;
ssh_string i;
ssh_string e = NULL;
ssh_string i = NULL;
int nid;
i = ssh_buffer_get_ssh_string(buffer);
if (i == NULL) {
rc = ssh_buffer_unpack(buffer, "SS", &i, &e);
if (rc != SSH_OK) {
SSH_LOG(SSH_LOG_WARN, "Unpack error");
goto fail;
}
nid = pki_key_ecdsa_nid_from_name(ssh_string_get_char(i));
ssh_string_free(i);
if (nid == -1) {
goto fail;
}
e = ssh_buffer_get_ssh_string(buffer);
if (e == NULL) {
goto fail;
}
rc = pki_pubkey_build_ecdsa(key, nid, e);
ssh_string_burn(e);
ssh_string_free(e);
if (rc < 0) {
SSH_LOG(SSH_LOG_WARN, "Failed to build ECDSA public key");
goto fail;
}
@@ -910,8 +1254,8 @@ fail:
int ssh_pki_import_pubkey_base64(const char *b64_key,
enum ssh_keytypes_e type,
ssh_key *pkey) {
ssh_buffer buffer;
ssh_string type_s;
ssh_buffer buffer = NULL;
ssh_string type_s = NULL;
int rc;
if (b64_key == NULL || pkey == NULL) {
@@ -958,7 +1302,7 @@ int ssh_pki_import_pubkey_base64(const char *b64_key,
*/
int ssh_pki_import_pubkey_blob(const ssh_string key_blob,
ssh_key *pkey) {
ssh_buffer buffer;
ssh_buffer buffer = NULL;
ssh_string type_s = NULL;
enum ssh_keytypes_e type;
int rc;
@@ -1032,7 +1376,7 @@ int ssh_pki_import_pubkey_file(const char *filename, ssh_key *pkey)
const char *q;
FILE *file;
off_t size;
int rc;
int rc, cmp;
if (pkey == NULL || filename == NULL || *filename == '\0') {
return SSH_ERROR;
@@ -1082,6 +1426,20 @@ int ssh_pki_import_pubkey_file(const char *filename, ssh_key *pkey)
key_buf[size] = '\0';
buflen = strlen(key_buf);
/* Test for new OpenSSH key format first */
cmp = strncmp(key_buf, OPENSSH_HEADER_BEGIN, strlen(OPENSSH_HEADER_BEGIN));
if (cmp == 0) {
*pkey = ssh_pki_openssh_pubkey_import(key_buf);
SAFE_FREE(key_buf);
if (*pkey == NULL) {
SSH_LOG(SSH_LOG_WARN, "Failed to import public key from OpenSSH"
" private key file");
return SSH_ERROR;
}
return SSH_OK;
}
/* This the old one-line public key format */
q = p = key_buf;
for (i = 0; i < buflen; i++) {
if (isspace((int)p[i])) {
@@ -1507,8 +1865,10 @@ int ssh_pki_import_signature_blob(const ssh_string sig_blob,
{
ssh_signature sig;
enum ssh_keytypes_e type;
enum ssh_digest_e hash_type;
ssh_string str;
ssh_buffer buf;
const char *alg = NULL;
int rc;
if (sig_blob == NULL || psig == NULL) {
@@ -1534,7 +1894,9 @@ int ssh_pki_import_signature_blob(const ssh_string sig_blob,
return SSH_ERROR;
}
type = ssh_key_type_from_name(ssh_string_get_char(str));
alg = ssh_string_get_char(str);
type = ssh_key_type_from_signature_name(alg);
hash_type = ssh_key_hash_from_name(alg);
ssh_string_free(str);
str = ssh_buffer_get_ssh_string(buf);
@@ -1543,7 +1905,7 @@ int ssh_pki_import_signature_blob(const ssh_string sig_blob,
return SSH_ERROR;
}
sig = pki_signature_from_blob(pubkey, str, type);
sig = pki_signature_from_blob(pubkey, str, type, hash_type);
ssh_string_free(str);
if (sig == NULL) {
return SSH_ERROR;
@@ -1593,22 +1955,45 @@ int ssh_pki_signature_verify_blob(ssh_session session,
} else if (key->type == SSH_KEYTYPE_ED25519) {
rc = pki_signature_verify(session, sig, key, digest, dlen);
} else {
unsigned char hash[SHA_DIGEST_LEN] = {0};
unsigned char hash[SHA512_DIGEST_LEN] = {0};
uint32_t hlen = 0;
sha1(digest, dlen, hash);
if (sig->type != SSH_KEYTYPE_RSA && sig->hash_type != SSH_DIGEST_AUTO) {
SSH_LOG(SSH_LOG_TRACE, "Only RSA keys support non-SHA1 hashes.");
return SSH_ERROR;
}
switch (sig->hash_type) {
case SSH_DIGEST_SHA256:
sha256(digest, dlen, hash);
hlen = SHA256_DIGEST_LEN;
break;
case SSH_DIGEST_SHA512:
sha512(digest, dlen, hash);
hlen = SHA512_DIGEST_LEN;
break;
case SSH_DIGEST_SHA1:
case SSH_DIGEST_AUTO:
sha1(digest, dlen, hash);
hlen = SHA_DIGEST_LEN;
break;
default:
SSH_LOG(SSH_LOG_TRACE, "Unknown sig->hash_type: %d", sig->hash_type);
return SSH_ERROR;
}
#ifdef DEBUG_CRYPTO
ssh_print_hexa(key->type == SSH_KEYTYPE_DSS
? "Hash to be verified with DSA"
: "Hash to be verified with RSA",
hash,
SHA_DIGEST_LEN);
hlen);
#endif
rc = pki_signature_verify(session,
sig,
key,
hash,
SHA_DIGEST_LEN);
hlen);
}
ssh_signature_free(sig);
@@ -1687,24 +2072,57 @@ ssh_string ssh_pki_do_sign(ssh_session session,
ssh_buffer_get_len(buf));
ssh_buffer_free(buf);
} else {
unsigned char hash[SHA_DIGEST_LEN] = {0};
SHACTX ctx;
unsigned char hash[SHA512_DIGEST_LEN] = {0};
uint32_t hlen = 0;
enum ssh_digest_e hash_type;
ssh_buffer buf;
ctx = sha1_init();
if (ctx == NULL) {
buf = ssh_buffer_new();
if (buf == NULL) {
ssh_string_free(session_id);
return NULL;
}
sha1_update(ctx, session_id, ssh_string_len(session_id) + 4);
sha1_update(ctx, ssh_buffer_get(sigbuf), ssh_buffer_get_len(sigbuf));
sha1_final(hash, ctx);
ssh_buffer_set_secure(buf);
rc = ssh_buffer_pack(buf,
"SP",
session_id,
ssh_buffer_get_len(sigbuf), ssh_buffer_get(sigbuf));
if (rc != SSH_OK) {
ssh_string_free(session_id);
ssh_buffer_free(buf);
return NULL;
}
hash_type = ssh_key_type_to_hash(session, privkey->type);
switch (hash_type) {
case SSH_DIGEST_SHA256:
sha256(ssh_buffer_get(buf), ssh_buffer_get_len(buf), hash);
hlen = SHA256_DIGEST_LEN;
break;
case SSH_DIGEST_SHA512:
sha512(ssh_buffer_get(buf), ssh_buffer_get_len(buf), hash);
hlen = SHA512_DIGEST_LEN;
break;
case SSH_DIGEST_SHA1:
case SSH_DIGEST_AUTO:
sha1(ssh_buffer_get(buf), ssh_buffer_get_len(buf), hash);
hlen = SHA_DIGEST_LEN;
break;
default:
SSH_LOG(SSH_LOG_TRACE, "Unknown hash algorithm for type: %d",
sig->type);
ssh_string_free(session_id);
ssh_buffer_free(buf);
return NULL;
}
ssh_buffer_free(buf);
#ifdef DEBUG_CRYPTO
ssh_print_hexa("Hash being signed", hash, SHA_DIGEST_LEN);
ssh_print_hexa("Hash being signed", hash, hlen);
#endif
sig = pki_do_sign(privkey, hash, SHA_DIGEST_LEN);
sig = pki_do_sign_hash(privkey, hash, hlen, hash_type);
}
ssh_string_free(session_id);
if (sig == NULL) {
@@ -1827,21 +2245,36 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
sig = NULL;
}
} else {
unsigned char hash[SHA_DIGEST_LEN] = {0};
SHACTX ctx;
unsigned char hash[SHA512_DIGEST_LEN] = {0};
uint32_t hlen = 0;
enum ssh_digest_e hash_type;
ctx = sha1_init();
if (ctx == NULL) {
hash_type = ssh_key_type_to_hash(session, privkey->type);
switch (hash_type) {
case SSH_DIGEST_SHA256:
sha256(crypto->secret_hash, crypto->digest_len, hash);
hlen = SHA256_DIGEST_LEN;
break;
case SSH_DIGEST_SHA512:
sha512(crypto->secret_hash, crypto->digest_len, hash);
hlen = SHA512_DIGEST_LEN;
break;
case SSH_DIGEST_SHA1:
case SSH_DIGEST_AUTO:
sha1(crypto->secret_hash, crypto->digest_len, hash);
hlen = SHA_DIGEST_LEN;
break;
default:
SSH_LOG(SSH_LOG_TRACE, "Unknown sig->type: %d", sig->type);
return NULL;
}
sha1_update(ctx, crypto->secret_hash, crypto->digest_len);
sha1_final(hash, ctx);
#ifdef DEBUG_CRYPTO
ssh_print_hexa("Hash being signed", hash, SHA_DIGEST_LEN);
ssh_print_hexa("Hash being signed", hash, hlen);
#endif
sig = pki_do_sign_sessionid(privkey, hash, SHA_DIGEST_LEN);
sig = pki_do_sign_sessionid_hash(privkey, hash, hlen, hash_type);
if (sig == NULL) {
return NULL;
}

View File

@@ -30,6 +30,7 @@
#include <ctype.h>
#include <string.h>
#include <stdbool.h>
#include "libssh/libssh.h"
#include "libssh/priv.h"
@@ -60,7 +61,6 @@ static int pki_openssh_import_privkey_blob(ssh_buffer key_blob_buffer,
enum ssh_keytypes_e type;
char *type_s = NULL;
ssh_key key = NULL;
ssh_string pubkey = NULL, privkey = NULL;
int rc;
if (pkey == NULL) {
@@ -75,57 +75,14 @@ static int pki_openssh_import_privkey_blob(ssh_buffer key_blob_buffer,
type = ssh_key_type_from_name(type_s);
if (type == SSH_KEYTYPE_UNKNOWN) {
SSH_LOG(SSH_LOG_WARN, "Unknown key type found!");
SSH_LOG(SSH_LOG_WARN, "Unknown key type '%s' found!", type_s);
return SSH_ERROR;
}
SAFE_FREE(type_s);
key = ssh_key_new();
if (key == NULL) {
SSH_LOG(SSH_LOG_WARN, "Out of memory");
return SSH_ERROR;
}
key->type = type;
key->type_c = ssh_key_type_to_char(type);
key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC;
switch (type) {
case SSH_KEYTYPE_ED25519:
rc = ssh_buffer_unpack(key_blob_buffer, "SS", &pubkey, &privkey);
if (rc != SSH_OK){
SSH_LOG(SSH_LOG_WARN, "Unpack error");
goto fail;
}
if(ssh_string_len(pubkey) != ED25519_PK_LEN ||
ssh_string_len(privkey) != ED25519_SK_LEN){
SSH_LOG(SSH_LOG_WARN, "Invalid ed25519 key len");
goto fail;
}
key->ed25519_privkey = malloc(ED25519_SK_LEN);
key->ed25519_pubkey = malloc(ED25519_PK_LEN);
if(key->ed25519_privkey == NULL || key->ed25519_pubkey == NULL){
goto fail;
}
memcpy(key->ed25519_privkey, ssh_string_data(privkey), ED25519_SK_LEN);
memcpy(key->ed25519_pubkey, ssh_string_data(pubkey), ED25519_PK_LEN);
explicit_bzero(ssh_string_data(privkey), ED25519_SK_LEN);
SAFE_FREE(privkey);
SAFE_FREE(pubkey);
break;
case SSH_KEYTYPE_DSS_CERT01:
case SSH_KEYTYPE_DSS:
/* p,q,g,pub_key,priv_key */
case SSH_KEYTYPE_RSA_CERT01:
case SSH_KEYTYPE_RSA:
/* n,e,d,iqmp,p,q */
case SSH_KEYTYPE_ECDSA:
/* curve_name, group, privkey */
SSH_LOG(SSH_LOG_WARN, "Unsupported private key method %s", key->type_c);
goto fail;
case SSH_KEYTYPE_RSA1:
case SSH_KEYTYPE_UNKNOWN:
SSH_LOG(SSH_LOG_WARN, "Unknown private key protocol %s", key->type_c);
rc = pki_import_privkey_buffer(type, key_blob_buffer, &key);
if (rc != SSH_OK) {
SSH_LOG(SSH_LOG_WARN, "Failed to read key in OpenSSH format");
goto fail;
}
@@ -133,11 +90,6 @@ static int pki_openssh_import_privkey_blob(ssh_buffer key_blob_buffer,
return SSH_OK;
fail:
ssh_key_free(key);
if(privkey != NULL){
memset(ssh_string_data(privkey), 0, ssh_string_len(privkey));
}
SAFE_FREE(pubkey);
SAFE_FREE(privkey);
return SSH_ERROR;
}
@@ -274,10 +226,12 @@ static int pki_private_key_decrypt(ssh_string blob,
* @brief Import a private key in OpenSSH (new) format. This format is
* typically used with ed25519 keys but can be used for others.
*/
ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
const char *passphrase,
ssh_auth_callback auth_fn,
void *auth_data)
static ssh_key
ssh_pki_openssh_import(const char *text_key,
const char *passphrase,
ssh_auth_callback auth_fn,
void *auth_data,
bool private)
{
const char *ptr=text_key;
const char *end;
@@ -298,7 +252,7 @@ ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
cmp = strncmp(ptr, OPENSSH_HEADER_BEGIN, strlen(OPENSSH_HEADER_BEGIN));
if (cmp != 0){
SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (no header)");
goto error;
goto out;
}
ptr += strlen(OPENSSH_HEADER_BEGIN);
while(ptr[0] != '\0' && !isspace((int)ptr[0])) {
@@ -307,11 +261,11 @@ ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
end = strstr(ptr, OPENSSH_HEADER_END);
if (end == NULL){
SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (no footer)");
goto error;
goto out;
}
base64 = malloc(end - ptr + 1);
if (base64 == NULL){
goto error;
goto out;
}
for (i = 0; ptr < end; ptr++){
if (!isspace((int)ptr[0])) {
@@ -324,7 +278,7 @@ ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
SAFE_FREE(base64);
if (buffer == NULL){
SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (base64 error)");
goto error;
goto out;
}
rc = ssh_buffer_unpack(buffer, "PssSdSS",
strlen(OPENSSH_AUTH_MAGIC) + 1,
@@ -337,12 +291,12 @@ ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
&privkeys);
if (rc == SSH_ERROR){
SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (unpack error)");
goto error;
goto out;
}
cmp = strncmp(magic, OPENSSH_AUTH_MAGIC, strlen(OPENSSH_AUTH_MAGIC));
if (cmp != 0){
SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (bad magic)");
goto error;
goto out;
}
SSH_LOG(SSH_LOG_INFO,
"Opening OpenSSH private key: ciphername: %s, kdf: %s, nkeys: %d\n",
@@ -351,8 +305,18 @@ ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
nkeys);
if (nkeys != 1){
SSH_LOG(SSH_LOG_WARN, "Opening OpenSSH private key: only 1 key supported (%d available)", nkeys);
goto error;
goto out;
}
/* If we are interested only in public key do not progress
* to the key decryption later
*/
if (!private) {
rc = ssh_pki_import_pubkey_blob(pubkey0, &key);
/* in either case we clean up here */
goto out;
}
rc = pki_private_key_decrypt(privkeys,
passphrase,
ciphername,
@@ -361,13 +325,13 @@ ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
auth_fn,
auth_data);
if (rc == SSH_ERROR){
goto error;
goto out;
}
privkey_buffer = ssh_buffer_new();
if (privkey_buffer == NULL) {
rc = SSH_ERROR;
goto error;
goto out;
}
ssh_buffer_set_secure(privkey_buffer);
@@ -378,11 +342,11 @@ ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
rc = ssh_buffer_unpack(privkey_buffer, "dd", &checkint1, &checkint2);
if (rc == SSH_ERROR || checkint1 != checkint2){
SSH_LOG(SSH_LOG_WARN, "OpenSSH private key unpack error (correct password?)");
goto error;
goto out;
}
rc = pki_openssh_import_privkey_blob(privkey_buffer, &key);
if (rc == SSH_ERROR){
goto error;
goto out;
}
comment = ssh_buffer_get_ssh_string(privkey_buffer);
SAFE_FREE(comment);
@@ -393,15 +357,15 @@ ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
ssh_key_free(key);
key = NULL;
SSH_LOG(SSH_LOG_WARN, "Invalid padding");
goto error;
goto out;
}
}
error:
if(buffer != NULL){
out:
if (buffer != NULL) {
ssh_buffer_free(buffer);
buffer = NULL;
}
if(privkey_buffer != NULL){
if (privkey_buffer != NULL) {
ssh_buffer_free(privkey_buffer);
privkey_buffer = NULL;
}
@@ -414,6 +378,19 @@ error:
return key;
}
ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
const char *passphrase,
ssh_auth_callback auth_fn,
void *auth_data)
{
return ssh_pki_openssh_import(text_key, passphrase, auth_fn, auth_data, true);
}
ssh_key ssh_pki_openssh_pubkey_import(const char *text_key)
{
return ssh_pki_openssh_import(text_key, NULL, NULL, NULL, false);
}
/** @internal
* @brief exports a private key to a string blob.

View File

@@ -172,10 +172,65 @@ static ssh_string make_ecpoint_string(const EC_GROUP *g,
return s;
}
int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp)
{
EC_POINT *p = NULL;
const EC_GROUP *g = NULL;
int ok;
BIGNUM *bexp = NULL;
key->ecdsa_nid = nid;
key->type_c = pki_key_ecdsa_nid_to_name(nid);
key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid);
if (key->ecdsa == NULL) {
return -1;
}
g = EC_KEY_get0_group(key->ecdsa);
p = EC_POINT_new(g);
if (p == NULL) {
return -1;
}
ok = EC_POINT_oct2point(g,
p,
ssh_string_data(e),
ssh_string_len(e),
NULL);
if (!ok) {
EC_POINT_free(p);
return -1;
}
/* EC_KEY_set_public_key duplicates p */
ok = EC_KEY_set_public_key(key->ecdsa, p);
EC_POINT_free(p);
if (!ok) {
return -1;
}
bexp = ssh_make_string_bn(exp);
if (bexp == NULL) {
EC_KEY_free(key->ecdsa);
return -1;
}
/* EC_KEY_set_private_key duplicates exp */
ok = EC_KEY_set_private_key(key->ecdsa, bexp);
BN_free(bexp);
if (!ok) {
EC_KEY_free(key->ecdsa);
return -1;
}
return 0;
}
int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e)
{
EC_POINT *p;
const EC_GROUP *g;
EC_POINT *p = NULL;
const EC_GROUP *g = NULL;
int ok;
key->ecdsa_nid = nid;
@@ -260,6 +315,7 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
goto fail;
}
/* Memory management of np, nq and ng is transfered to DSA object */
rc = DSA_set0_pqg(new->dsa, np, nq, ng);
if (rc == 0) {
BN_free(np);
@@ -274,6 +330,7 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
goto fail;
}
/* Memory management of npubkey is transfered to DSA object */
rc = DSA_set0_key(new->dsa, npub_key, NULL);
if (rc == 0) {
goto fail;
@@ -285,6 +342,7 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
goto fail;
}
/* Memory management of npriv_key is transfered to DSA object */
rc = DSA_set0_key(new->dsa, NULL, npriv_key);
if (rc == 0) {
goto fail;
@@ -321,6 +379,7 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
goto fail;
}
/* Memory management of nn and ne is transfered to RSA object */
rc = RSA_set0_key(new->rsa, nn, ne, NULL);
if (rc == 0) {
BN_free(nn);
@@ -338,6 +397,7 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
goto fail;
}
/* Memory management of nd is transfered to RSA object */
rc = RSA_set0_key(new->rsa, NULL, NULL, nd);
if (rc == 0) {
goto fail;
@@ -356,6 +416,7 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
goto fail;
}
/* Memory management of np and nq is transfered to RSA object */
rc = RSA_set0_factors(new->rsa, np, nq);
if (rc == 0) {
BN_free(np);
@@ -376,6 +437,8 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
goto fail;
}
/* Memory management of ndmp1, ndmq1 and niqmp is transfered
* to RSA object */
rc = RSA_set0_crt_params(new->rsa, ndmp1, ndmq1, niqmp);
if (rc == 0) {
BN_free(ndmp1);
@@ -888,13 +951,56 @@ fail:
return NULL;
}
int pki_privkey_build_dss(ssh_key key,
ssh_string p,
ssh_string q,
ssh_string g,
ssh_string pubkey,
ssh_string privkey)
{
int rc;
BIGNUM *bp, *bq, *bg, *bpub_key, *bpriv_key;
key->dsa = DSA_new();
if (key->dsa == NULL) {
return SSH_ERROR;
}
bp = ssh_make_string_bn(p);
bq = ssh_make_string_bn(q);
bg = ssh_make_string_bn(g);
bpub_key = ssh_make_string_bn(pubkey);
bpriv_key = ssh_make_string_bn(privkey);
if (bp == NULL || bq == NULL ||
bg == NULL || bpub_key == NULL) {
goto fail;
}
/* Memory management of bp, qq and bg is transfered to DSA object */
rc = DSA_set0_pqg(key->dsa, bp, bq, bg);
if (rc == 0) {
goto fail;
}
/* Memory management of bpub_key and bpriv_key is transfered to DSA object */
rc = DSA_set0_key(key->dsa, bpub_key, bpriv_key);
if (rc == 0) {
goto fail;
}
return SSH_OK;
fail:
DSA_free(key->dsa);
return SSH_ERROR;
}
int pki_pubkey_build_dss(ssh_key key,
ssh_string p,
ssh_string q,
ssh_string g,
ssh_string pubkey) {
int rc;
BIGNUM *bp, *bq, *bg, *bpub_key;
BIGNUM *bp = NULL, *bq = NULL, *bg = NULL, *bpub_key = NULL;
key->dsa = DSA_new();
if (key->dsa == NULL) {
@@ -910,11 +1016,13 @@ int pki_pubkey_build_dss(ssh_key key,
goto fail;
}
/* Memory management of bp, bq and bg is transfered to DSA object */
rc = DSA_set0_pqg(key->dsa, bp, bq, bg);
if (rc == 0) {
goto fail;
}
/* Memory management of npub_key is transfered to DSA object */
rc = DSA_set0_key(key->dsa, bpub_key, NULL);
if (rc == 0) {
goto fail;
@@ -926,11 +1034,63 @@ fail:
return SSH_ERROR;
}
int pki_privkey_build_rsa(ssh_key key,
ssh_string n,
ssh_string e,
ssh_string d,
ssh_string iqmp,
ssh_string p,
ssh_string q)
{
int rc;
BIGNUM *be, *bn, *bd/*, *biqmp*/, *bp, *bq;
key->rsa = RSA_new();
if (key->rsa == NULL) {
return SSH_ERROR;
}
bn = ssh_make_string_bn(n);
be = ssh_make_string_bn(e);
bd = ssh_make_string_bn(d);
/*biqmp = ssh_make_string_bn(iqmp);*/
bp = ssh_make_string_bn(p);
bq = ssh_make_string_bn(q);
if (be == NULL || bn == NULL || bd == NULL ||
/*biqmp == NULL ||*/ bp == NULL || bq == NULL) {
goto fail;
}
/* Memory management of be, bn and bd is transfered to RSA object */
rc = RSA_set0_key(key->rsa, bn, be, bd);
if (rc == 0) {
goto fail;
}
/* Memory management of bp and bq is transfered to RSA object */
rc = RSA_set0_factors(key->rsa, bp, bq);
if (rc == 0) {
goto fail;
}
/* p, q, dmp1, dmq1 and iqmp may be NULL in private keys, but the RSA
* operations are much faster when these values are available.
* https://www.openssl.org/docs/man1.0.2/crypto/rsa.html
*/
/* RSA_set0_crt_params(key->rsa, biqmp, NULL, NULL);
TODO calculate missing crt_params */
return SSH_OK;
fail:
RSA_free(key->rsa);
return SSH_ERROR;
}
int pki_pubkey_build_rsa(ssh_key key,
ssh_string e,
ssh_string n) {
int rc;
BIGNUM *be, *bn;
BIGNUM *be = NULL, *bn = NULL;
key->rsa = RSA_new();
if (key->rsa == NULL) {
@@ -943,6 +1103,7 @@ int pki_pubkey_build_rsa(ssh_key key,
goto fail;
}
/* Memory management of bn and be is transfered to RSA object */
rc = RSA_set0_key(key->rsa, bn, be, NULL);
if (rc == 0) {
goto fail;
@@ -1181,23 +1342,43 @@ fail:
*
* @param[in] privkey The private rsa key to use for signing.
*
* @param[in] hash_type The hash algorithm to use.
*
* @return A newly allocated rsa sig blob or NULL on error.
*/
static ssh_string _RSA_do_sign(const unsigned char *digest,
int dlen,
RSA *privkey)
static ssh_string _RSA_do_sign_hash(const unsigned char *digest,
int dlen,
RSA *privkey,
enum ssh_digest_e hash_type)
{
ssh_string sig_blob;
unsigned char *sig;
unsigned int slen;
int ok;
int nid = 0;
switch (hash_type) {
case SSH_DIGEST_SHA1:
case SSH_DIGEST_AUTO:
nid = NID_sha1;
break;
case SSH_DIGEST_SHA256:
nid = NID_sha256;
break;
case SSH_DIGEST_SHA512:
nid = NID_sha512;
break;
default:
SSH_LOG(SSH_LOG_WARN, "Incomplatible hash type");
return NULL;
}
sig = malloc(RSA_size(privkey));
if (sig == NULL) {
return NULL;
}
ok = RSA_sign(NID_sha1, digest, dlen, sig, &slen, privkey);
ok = RSA_sign(nid, digest, dlen, sig, &slen, privkey);
if (!ok) {
SAFE_FREE(sig);
return NULL;
@@ -1210,7 +1391,7 @@ static ssh_string _RSA_do_sign(const unsigned char *digest,
}
ssh_string_fill(sig_blob, sig, slen);
memset(sig, 'd', slen);
explicit_bzero(sig, slen);
SAFE_FREE(sig);
return sig_blob;
@@ -1409,7 +1590,8 @@ errout:
ssh_signature pki_signature_from_blob(const ssh_key pubkey,
const ssh_string sig_blob,
enum ssh_keytypes_e type)
enum ssh_keytypes_e type,
enum ssh_digest_e hash_type)
{
ssh_signature sig;
ssh_string r;
@@ -1424,7 +1606,8 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
}
sig->type = type;
sig->type_c = ssh_key_type_to_char(type);
sig->hash_type = hash_type;
sig->type_c = ssh_key_signature_to_char(type, hash_type);
len = ssh_string_len(sig_blob);
@@ -1478,6 +1661,8 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
return NULL;
}
/* Memory management of pr and ps is transfered to DSA signature
* object */
rc = DSA_SIG_set0(sig->dsa_sig, pr, ps);
if (rc == 0) {
ssh_signature_free(sig);
@@ -1556,6 +1741,8 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
return NULL;
}
/* Memory management of pr and ps is transfered to
* ECDSA signature object */
rc = ECDSA_SIG_set0(sig->ecdsa_sig, pr, ps);
if (rc == 0) {
ssh_signature_free(sig);
@@ -1598,6 +1785,7 @@ int pki_signature_verify(ssh_session session,
size_t hlen)
{
int rc;
int nid;
switch(key->type) {
case SSH_KEYTYPE_DSS:
@@ -1615,13 +1803,33 @@ int pki_signature_verify(ssh_session session,
break;
case SSH_KEYTYPE_RSA:
case SSH_KEYTYPE_RSA1:
rc = RSA_verify(NID_sha1,
switch (sig->hash_type) {
case SSH_DIGEST_AUTO:
case SSH_DIGEST_SHA1:
nid = NID_sha1;
break;
case SSH_DIGEST_SHA256:
nid = NID_sha256;
break;
case SSH_DIGEST_SHA512:
nid = NID_sha512;
break;
default:
SSH_LOG(SSH_LOG_TRACE, "Unknown hash type %d", sig->hash_type);
ssh_set_error(session,
SSH_FATAL,
"Unexpected hash type %d during RSA verify",
sig->hash_type);
return SSH_ERROR;
}
rc = RSA_verify(nid,
hash,
hlen,
ssh_string_data(sig->rsa_sig),
ssh_string_len(sig->rsa_sig),
key->rsa);
if (rc <= 0) {
SSH_LOG(SSH_LOG_TRACE, "RSA verify failed");
ssh_set_error(session,
SSH_FATAL,
"RSA error: %s",
@@ -1655,6 +1863,7 @@ int pki_signature_verify(ssh_session session,
#endif
case SSH_KEYTYPE_UNKNOWN:
default:
SSH_LOG(SSH_LOG_TRACE, "Unknown key type");
ssh_set_error(session, SSH_FATAL, "Unknown public key type");
return SSH_ERROR;
}
@@ -1662,18 +1871,27 @@ int pki_signature_verify(ssh_session session,
return SSH_OK;
}
ssh_signature pki_do_sign(const ssh_key privkey,
const unsigned char *hash,
size_t hlen) {
ssh_signature pki_do_sign_hash(const ssh_key privkey,
const unsigned char *hash,
size_t hlen,
enum ssh_digest_e hash_type)
{
ssh_signature sig;
int rc;
/* Only RSA supports different signature algorithm types now */
if (privkey->type != SSH_KEYTYPE_RSA && hash_type != SSH_DIGEST_AUTO) {
SSH_LOG(SSH_LOG_WARN, "Incompatible signature algorithm passed");
return NULL;
}
sig = ssh_signature_new();
if (sig == NULL) {
return NULL;
}
sig->type = privkey->type;
sig->hash_type = hash_type;
sig->type_c = privkey->type_c;
switch(privkey->type) {
@@ -1696,7 +1914,8 @@ ssh_signature pki_do_sign(const ssh_key privkey,
break;
case SSH_KEYTYPE_RSA:
case SSH_KEYTYPE_RSA1:
sig->rsa_sig = _RSA_do_sign(hash, hlen, privkey->rsa);
sig->type_c = ssh_key_signature_to_char(privkey->type, hash_type);
sig->rsa_sig = _RSA_do_sign_hash(hash, hlen, privkey->rsa, hash_type);
if (sig->rsa_sig == NULL) {
ssh_signature_free(sig);
return NULL;
@@ -1739,16 +1958,24 @@ ssh_signature pki_do_sign(const ssh_key privkey,
}
#ifdef WITH_SERVER
ssh_signature pki_do_sign_sessionid(const ssh_key key,
const unsigned char *hash,
size_t hlen)
ssh_signature pki_do_sign_sessionid_hash(const ssh_key key,
const unsigned char *hash,
size_t hlen,
enum ssh_digest_e hash_type)
{
ssh_signature sig;
/* Only RSA supports different signature algorithm types now */
if (key->type != SSH_KEYTYPE_RSA && hash_type != SSH_DIGEST_AUTO) {
SSH_LOG(SSH_LOG_WARN, "Incompatible signature algorithm passed");
return NULL;
}
sig = ssh_signature_new();
if (sig == NULL) {
return NULL;
}
sig->type = key->type;
sig->type_c = key->type_c;
@@ -1762,7 +1989,8 @@ ssh_signature pki_do_sign_sessionid(const ssh_key key,
break;
case SSH_KEYTYPE_RSA:
case SSH_KEYTYPE_RSA1:
sig->rsa_sig = _RSA_do_sign(hash, hlen, key->rsa);
sig->type_c = ssh_key_signature_to_char(key->type, hash_type);
sig->rsa_sig = _RSA_do_sign_hash(hash, hlen, key->rsa, hash_type);
if (sig->rsa_sig == NULL) {
ssh_signature_free(sig);
return NULL;

View File

@@ -56,6 +56,28 @@ error:
return SSH_ERROR;
}
int pki_privkey_build_ed25519(ssh_key key,
ssh_string pubkey,
ssh_string privkey)
{
if (ssh_string_len(pubkey) != ED25519_PK_LEN ||
ssh_string_len(privkey) != ED25519_SK_LEN) {
SSH_LOG(SSH_LOG_WARN, "Invalid ed25519 key len");
return SSH_ERROR;
}
key->ed25519_privkey = malloc(ED25519_SK_LEN);
key->ed25519_pubkey = malloc(ED25519_PK_LEN);
if (key->ed25519_privkey == NULL || key->ed25519_pubkey == NULL) {
return SSH_ERROR;
}
memcpy(key->ed25519_privkey, ssh_string_data(privkey),
ED25519_SK_LEN);
memcpy(key->ed25519_pubkey, ssh_string_data(pubkey),
ED25519_PK_LEN);
return SSH_OK;
}
int pki_ed25519_sign(const ssh_key privkey,
ssh_signature sig,
const unsigned char *hash,

View File

@@ -1030,6 +1030,27 @@ fail:
return NULL;
}
int pki_privkey_build_dss(ssh_key key,
ssh_string p,
ssh_string q,
ssh_string g,
ssh_string pubkey,
ssh_string privkey)
{
gcry_sexp_build(&key->dsa, NULL,
"(private-key(dsa(p %b)(q %b)(g %b)(y %b)(x %b)))",
ssh_string_len(p), ssh_string_data(p),
ssh_string_len(q), ssh_string_data(q),
ssh_string_len(g), ssh_string_data(g),
ssh_string_len(pubkey), ssh_string_data(pubkey),
ssh_string_len(privkey), ssh_string_data(privkey));
if (key->dsa == NULL) {
return SSH_ERROR;
}
return SSH_OK;
}
int pki_pubkey_build_dss(ssh_key key,
ssh_string p,
ssh_string q,
@@ -1048,6 +1069,32 @@ int pki_pubkey_build_dss(ssh_key key,
return SSH_OK;
}
int pki_privkey_build_rsa(ssh_key key,
ssh_string n,
ssh_string e,
ssh_string d,
ssh_string iqmp,
ssh_string p,
ssh_string q)
{
/* in gcrypt, there is no iqmp (inverse of q mod p) argument,
* but it is ipmq (inverse of p mod q) so we need to swap
* the p and q arguments */
gcry_sexp_build(&key->rsa, NULL,
"(private-key(rsa(n %b)(e %b)(d %b)(p %b)(q %b)(u %b)))",
ssh_string_len(n), ssh_string_data(n),
ssh_string_len(e), ssh_string_data(e),
ssh_string_len(d), ssh_string_data(d),
ssh_string_len(q), ssh_string_data(q),
ssh_string_len(p), ssh_string_data(p),
ssh_string_len(iqmp), ssh_string_data(iqmp));
if (key->rsa == NULL) {
return SSH_ERROR;
}
return SSH_OK;
}
int pki_pubkey_build_rsa(ssh_key key,
ssh_string e,
ssh_string n) {
@@ -1063,6 +1110,25 @@ int pki_pubkey_build_rsa(ssh_key key,
}
#ifdef HAVE_GCRYPT_ECC
int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp)
{
gpg_error_t err;
key->ecdsa_nid = nid;
key->type_c = pki_key_ecdsa_nid_to_name(nid);
err = gcry_sexp_build(&key->ecdsa, NULL,
"(private-key(ecdsa(curve %s)(d %b)(q %b)))",
pki_key_ecdsa_nid_to_gcrypt_name(nid),
ssh_string_len(exp), ssh_string_data(exp),
ssh_string_len(e), ssh_string_data(e));
if (err) {
return SSH_ERROR;
}
return SSH_OK;
}
int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e)
{
gpg_error_t err;
@@ -1773,7 +1839,8 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
ssh_signature pki_signature_from_blob(const ssh_key pubkey,
const ssh_string sig_blob,
enum ssh_keytypes_e type)
enum ssh_keytypes_e type,
enum ssh_digest_e hash_type)
{
ssh_signature sig;
gcry_error_t err;
@@ -1787,6 +1854,8 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
}
sig->type = type;
sig->hash_type = hash_type;
sig->type_c = ssh_key_signature_to_char(type, hash_type);
len = ssh_string_len(sig_blob);
@@ -1952,6 +2021,7 @@ int pki_signature_verify(ssh_session session,
size_t hlen)
{
unsigned char ghash[hlen + 1];
const char *hash_type = NULL;
gcry_sexp_t sexp;
gcry_error_t err;
@@ -1986,10 +2056,29 @@ int pki_signature_verify(ssh_session session,
}
break;
case SSH_KEYTYPE_RSA:
switch (sig->hash_type) {
case SSH_DIGEST_SHA256:
hash_type = "sha256";
break;
case SSH_DIGEST_SHA512:
hash_type = "sha512";
break;
case SSH_DIGEST_SHA1:
case SSH_DIGEST_AUTO:
hash_type = "sha1";
break;
default:
SSH_LOG(SSH_LOG_TRACE, "Unknown sig type %d", sig->hash_type);
ssh_set_error(session,
SSH_FATAL,
"Unexpected signature type %d during RSA verify",
sig->hash_type);
return SSH_ERROR;
}
err = gcry_sexp_build(&sexp,
NULL,
"(data(flags pkcs1)(hash sha1 %b))",
hlen, hash);
"(data(flags pkcs1)(hash %s %b))",
hash_type, hlen, hash);
if (err) {
ssh_set_error(session,
SSH_FATAL,
@@ -2056,19 +2145,29 @@ int pki_signature_verify(ssh_session session,
return SSH_OK;
}
ssh_signature pki_do_sign(const ssh_key privkey,
const unsigned char *hash,
size_t hlen) {
ssh_signature pki_do_sign_hash(const ssh_key privkey,
const unsigned char *hash,
size_t hlen,
enum ssh_digest_e hash_type)
{
unsigned char ghash[hlen + 1];
const char *hash_c = NULL;
ssh_signature sig;
gcry_sexp_t sexp;
gcry_error_t err;
/* Only RSA supports different signature algorithm types now */
if (privkey->type != SSH_KEYTYPE_RSA && hash_type != SSH_DIGEST_AUTO) {
SSH_LOG(SSH_LOG_WARN, "Incompatible signature algorithm passed");
return NULL;
}
sig = ssh_signature_new();
if (sig == NULL) {
return NULL;
}
sig->type = privkey->type;
sig->hash_type = hash_type;
sig->type_c = privkey->type_c;
switch (privkey->type) {
case SSH_KEYTYPE_DSS:
@@ -2094,9 +2193,26 @@ ssh_signature pki_do_sign(const ssh_key privkey,
}
break;
case SSH_KEYTYPE_RSA:
sig->type_c = ssh_key_signature_to_char(privkey->type, hash_type);
switch (hash_type) {
case SSH_DIGEST_SHA1:
case SSH_DIGEST_AUTO:
hash_c = "sha1";
break;
case SSH_DIGEST_SHA256:
hash_c = "sha256";
break;
case SSH_DIGEST_SHA512:
hash_c = "sha512";
break;
default:
SSH_LOG(SSH_LOG_WARN, "Incomplatible key algorithm");
return NULL;
}
err = gcry_sexp_build(&sexp,
NULL,
"(data(flags pkcs1)(hash sha1 %b))",
"(data(flags pkcs1)(hash %s %b))",
hash_c,
hlen,
hash);
if (err) {
@@ -2149,19 +2265,28 @@ ssh_signature pki_do_sign(const ssh_key privkey,
}
#ifdef WITH_SERVER
ssh_signature pki_do_sign_sessionid(const ssh_key key,
const unsigned char *hash,
size_t hlen)
ssh_signature pki_do_sign_sessionid_hash(const ssh_key key,
const unsigned char *hash,
size_t hlen,
enum ssh_digest_e hash_type)
{
unsigned char ghash[hlen + 1];
const char *hash_c = NULL;
ssh_signature sig;
gcry_sexp_t sexp;
gcry_error_t err;
/* Only RSA supports different signature algorithm types now */
if (key->type != SSH_KEYTYPE_RSA && hash_type != SSH_DIGEST_AUTO) {
SSH_LOG(SSH_LOG_WARN, "Incompatible signature algorithm passed");
return NULL;
}
sig = ssh_signature_new();
if (sig == NULL) {
return NULL;
}
sig->type = key->type;
sig->type_c = key->type_c;
@@ -2188,9 +2313,25 @@ ssh_signature pki_do_sign_sessionid(const ssh_key key,
}
break;
case SSH_KEYTYPE_RSA:
sig->type_c = ssh_key_signature_to_char(key->type, hash_type);
switch (hash_type) {
case SSH_DIGEST_SHA1:
hash_c = "sha1";
break;
case SSH_DIGEST_SHA256:
hash_c = "sha256";
break;
case SSH_DIGEST_SHA512:
hash_c = "sha512";
break;
default:
SSH_LOG(SSH_LOG_WARN, "Incomplatible key algorithm");
return NULL;
}
err = gcry_sexp_build(&sexp,
NULL,
"(data(flags pkcs1)(hash sha1 %b))",
"(data(flags pkcs1)(hash %s %b))",
hash_c,
hlen,
hash);
if (err) {

View File

@@ -214,6 +214,64 @@ fail:
return NULL;
}
int pki_privkey_build_rsa(ssh_key key,
ssh_string n,
ssh_string e,
ssh_string d,
ssh_string iqmp,
ssh_string p,
ssh_string q)
{
mbedtls_rsa_context *rsa = NULL;
const mbedtls_pk_info_t *pk_info = NULL;
int rc;
key->rsa = malloc(sizeof(mbedtls_pk_context));
if (key->rsa == NULL) {
return SSH_ERROR;
}
mbedtls_pk_init(key->rsa);
pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
mbedtls_pk_setup(key->rsa, pk_info);
rc = mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA);
if (rc == 0) {
goto fail;
}
rsa = mbedtls_pk_rsa(*key->rsa);
rc = mbedtls_rsa_import_raw(rsa,
ssh_string_data(n), ssh_string_len(n),
ssh_string_data(p), ssh_string_len(p),
ssh_string_data(q), ssh_string_len(q),
ssh_string_data(d), ssh_string_len(d),
ssh_string_data(e), ssh_string_len(e));
if (rc != 0) {
SSH_LOG(SSH_LOG_WARN, "Failed to import private RSA key");
goto fail;
}
rc = mbedtls_rsa_complete(rsa);
if (rc != 0) {
SSH_LOG(SSH_LOG_WARN, "Failed to complete private RSA key");
goto fail;
}
rc = mbedtls_rsa_check_privkey(rsa);
if (rc != 0) {
SSH_LOG(SSH_LOG_WARN, "Inconsistent private RSA key");
goto fail;
}
return SSH_OK;
fail:
mbedtls_pk_free(key->rsa);
SAFE_FREE(key->rsa);
return SSH_ERROR;
}
int pki_pubkey_build_rsa(ssh_key key, ssh_string e, ssh_string n)
{
mbedtls_rsa_context *rsa = NULL;
@@ -229,25 +287,31 @@ int pki_pubkey_build_rsa(ssh_key key, ssh_string e, ssh_string n)
pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
mbedtls_pk_setup(key->rsa, pk_info);
if (mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA)) {
rsa = mbedtls_pk_rsa(*key->rsa);
rc = mbedtls_mpi_read_binary(&rsa->N, ssh_string_data(n),
ssh_string_len(n));
if (rc != 0) {
return SSH_ERROR;
}
rc = mbedtls_mpi_read_binary(&rsa->E, ssh_string_data(e),
ssh_string_len(e));
if (rc != 0) {
return SSH_ERROR;
}
rsa->len = (mbedtls_mpi_bitlen(&rsa->N) + 7) >> 3;
} else {
return SSH_ERROR;
rc = mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA);
if (rc == 0) {
goto fail;
}
rsa = mbedtls_pk_rsa(*key->rsa);
rc = mbedtls_mpi_read_binary(&rsa->N, ssh_string_data(n),
ssh_string_len(n));
if (rc != 0) {
goto fail;
}
rc = mbedtls_mpi_read_binary(&rsa->E, ssh_string_data(e),
ssh_string_len(e));
if (rc != 0) {
goto fail;
}
rsa->len = (mbedtls_mpi_bitlen(&rsa->N) + 7) >> 3;
return SSH_OK;
fail:
mbedtls_pk_free(key->rsa);
SAFE_FREE(key->rsa);
return SSH_ERROR;
}
ssh_key pki_key_dup(const ssh_key key, int demote)
@@ -825,8 +889,10 @@ errout:
ssh_signature_free(sig);
return NULL;
}
ssh_signature pki_signature_from_blob(const ssh_key pubkey, const ssh_string
sig_blob, enum ssh_keytypes_e type)
ssh_signature pki_signature_from_blob(const ssh_key pubkey,
const ssh_string sig_blob,
enum ssh_keytypes_e type,
enum ssh_digest_e hash_type)
{
ssh_signature sig = NULL;
int rc;
@@ -837,7 +903,8 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey, const ssh_string
}
sig->type = type;
sig->type_c = ssh_key_type_to_char(type);
sig->hash_type = hash_type;
sig->type_c = ssh_key_signature_to_char(type, hash_type);
switch(type) {
case SSH_KEYTYPE_RSA:
@@ -930,10 +997,30 @@ int pki_signature_verify(ssh_session session, const ssh_signature sig, const
ssh_key key, const unsigned char *hash, size_t hlen)
{
int rc;
mbedtls_md_type_t md = 0;
switch (key->type) {
case SSH_KEYTYPE_RSA:
rc = mbedtls_pk_verify(key->rsa, MBEDTLS_MD_SHA1, hash, hlen,
switch (sig->hash_type) {
case SSH_DIGEST_SHA1:
case SSH_DIGEST_AUTO:
md = MBEDTLS_MD_SHA1;
break;
case SSH_DIGEST_SHA256:
md = MBEDTLS_MD_SHA256;
break;
case SSH_DIGEST_SHA512:
md = MBEDTLS_MD_SHA512;
break;
default:
SSH_LOG(SSH_LOG_TRACE, "Unknown sig type %d", sig->hash_type);
ssh_set_error(session,
SSH_FATAL,
"Unexpected signature hash type %d during RSA verify",
sig->hash_type);
return SSH_ERROR;
}
rc = mbedtls_pk_verify(key->rsa, md, hash, hlen,
ssh_string_data(sig->rsa_sig),
ssh_string_len(sig->rsa_sig));
if (rc != 0) {
@@ -970,21 +1057,40 @@ int pki_signature_verify(ssh_session session, const ssh_signature sig, const
return SSH_OK;
}
static ssh_string rsa_do_sign(const unsigned char *digest, int dlen,
mbedtls_pk_context *privkey)
static ssh_string rsa_do_sign_hash(const unsigned char *digest,
int dlen,
mbedtls_pk_context *privkey,
enum ssh_digest_e hash_type)
{
ssh_string sig_blob = NULL;
mbedtls_md_type_t md = 0;
unsigned char *sig = NULL;
size_t slen;
int ok;
switch (hash_type) {
case SSH_DIGEST_SHA1:
case SSH_DIGEST_AUTO:
md = MBEDTLS_MD_SHA1;
break;
case SSH_DIGEST_SHA256:
md = MBEDTLS_MD_SHA256;
break;
case SSH_DIGEST_SHA512:
md = MBEDTLS_MD_SHA512;
break;
default:
SSH_LOG(SSH_LOG_WARN, "Incomplatible key algorithm");
return NULL;
}
sig = malloc(mbedtls_pk_get_bitlen(privkey) / 8);
if (sig == NULL) {
return NULL;
}
ok = mbedtls_pk_sign(privkey,
MBEDTLS_MD_SHA1,
md,
digest,
dlen,
sig,
@@ -1004,30 +1110,40 @@ static ssh_string rsa_do_sign(const unsigned char *digest, int dlen,
}
ssh_string_fill(sig_blob, sig, slen);
memset(sig, 'd', slen);
explicit_bzero(sig, slen);
SAFE_FREE(sig);
return sig_blob;
}
ssh_signature pki_do_sign(const ssh_key privkey, const unsigned char *hash,
size_t hlen)
ssh_signature pki_do_sign_hash(const ssh_key privkey,
const unsigned char *hash,
size_t hlen,
enum ssh_digest_e hash_type)
{
ssh_signature sig = NULL;
int rc;
/* Only RSA supports different signature algorithm types now */
if (privkey->type != SSH_KEYTYPE_RSA && hash_type != SSH_DIGEST_AUTO) {
SSH_LOG(SSH_LOG_WARN, "Incompatible signature algorithm passed");
return NULL;
}
sig = ssh_signature_new();
if (sig == NULL) {
return NULL;
}
sig->type = privkey->type;
sig->hash_type = hash_type;
sig->type_c = privkey->type_c;
switch(privkey->type) {
case SSH_KEYTYPE_RSA:
sig->rsa_sig = rsa_do_sign(hash, hlen, privkey->rsa);
sig->type_c = ssh_key_signature_to_char(privkey->type, hash_type);
sig->rsa_sig = rsa_do_sign_hash(hash, hlen, privkey->rsa, hash_type);
if (sig->rsa_sig == NULL) {
ssh_signature_free(sig);
return NULL;
@@ -1075,22 +1191,32 @@ ssh_signature pki_do_sign(const ssh_key privkey, const unsigned char *hash,
}
#ifdef WITH_SERVER
ssh_signature pki_do_sign_sessionid(const ssh_key key, const unsigned char
*hash, size_t hlen)
ssh_signature pki_do_sign_sessionid_hash(const ssh_key key,
const unsigned char *hash,
size_t hlen,
enum ssh_digest_e hash_type)
{
ssh_signature sig = NULL;
int rc;
/* Only RSA supports different signature algorithm types now */
if (key->type != SSH_KEYTYPE_RSA && hash_type != SSH_DIGEST_AUTO) {
SSH_LOG(SSH_LOG_WARN, "Incompatible signature algorithm passed");
return NULL;
}
sig = ssh_signature_new();
if (sig == NULL) {
return NULL;
}
sig->type = key->type;
sig->type_c = key->type_c;
switch (key->type) {
case SSH_KEYTYPE_RSA:
sig->rsa_sig = rsa_do_sign(hash, hlen, key->rsa);
sig->type_c = ssh_key_signature_to_char(key->type, hash_type);
sig->rsa_sig = rsa_do_sign_hash(hash, hlen, key->rsa, hash_type);
if (sig->rsa_sig == NULL) {
ssh_signature_free(sig);
return NULL;
@@ -1175,6 +1301,73 @@ static mbedtls_ecp_group_id pki_key_ecdsa_nid_to_mbed_gid(int nid)
return MBEDTLS_ECP_DP_NONE;
}
int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp)
{
int rc;
mbedtls_ecp_keypair keypair;
mbedtls_ecp_group group;
mbedtls_ecp_point Q;
key->ecdsa_nid = nid;
key->type_c = pki_key_ecdsa_nid_to_name(nid);
key->ecdsa = malloc(sizeof(mbedtls_ecdsa_context));
if (key->ecdsa == NULL) {
return SSH_ERROR;
}
mbedtls_ecdsa_init(key->ecdsa);
mbedtls_ecp_keypair_init(&keypair);
mbedtls_ecp_group_init(&group);
mbedtls_ecp_point_init(&Q);
rc = mbedtls_ecp_group_load(&group,
pki_key_ecdsa_nid_to_mbed_gid(nid));
if (rc != 0) {
goto fail;
}
rc = mbedtls_ecp_point_read_binary(&group, &Q, ssh_string_data(e),
ssh_string_len(e));
if (rc != 0) {
goto fail;
}
rc = mbedtls_ecp_copy(&keypair.Q, &Q);
if (rc != 0) {
goto fail;
}
rc = mbedtls_ecp_group_copy(&keypair.grp, &group);
if (rc != 0) {
goto fail;
}
rc = mbedtls_mpi_read_binary(&keypair.d, ssh_string_data(exp),
ssh_string_len(exp));
if (rc != 0) {
goto fail;
}
rc = mbedtls_ecdsa_from_keypair(key->ecdsa, &keypair);
if (rc != 0) {
goto fail;
}
mbedtls_ecp_point_free(&Q);
mbedtls_ecp_group_free(&group);
mbedtls_ecp_keypair_free(&keypair);
return SSH_OK;
fail:
mbedtls_ecdsa_free(key->ecdsa);
mbedtls_ecp_point_free(&Q);
mbedtls_ecp_group_free(&group);
mbedtls_ecp_keypair_free(&keypair);
SAFE_FREE(key->ecdsa);
return SSH_ERROR;
}
int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e)
{
int rc;
@@ -1279,6 +1472,18 @@ int pki_key_generate_ecdsa(ssh_key key, int parameter)
return SSH_OK;
}
int pki_privkey_build_dss(ssh_key key, ssh_string p, ssh_string q, ssh_string g,
ssh_string pubkey, ssh_string privkey)
{
(void) key;
(void) p;
(void) q;
(void) g;
(void) pubkey;
(void) privkey;
return SSH_ERROR;
}
int pki_pubkey_build_dss(ssh_key key, ssh_string p, ssh_string q, ssh_string g,
ssh_string pubkey)
{

View File

@@ -1013,17 +1013,20 @@ int ssh_event_remove_connector(ssh_event event, ssh_connector connector){
* fds before freeing the event object.
*
*/
void ssh_event_free(ssh_event event) {
int used, i;
ssh_poll_handle p;
if(event == NULL) {
void ssh_event_free(ssh_event event)
{
size_t used, i;
ssh_poll_handle p;
if(event == NULL) {
return;
}
if(event->ctx != NULL) {
if (event->ctx != NULL) {
used = event->ctx->polls_used;
for(i = 0; i < used; i++) {
p = event->ctx->pollptrs[i];
if(p->session != NULL){
p = event->ctx->pollptrs[i];
if (p->session != NULL) {
ssh_poll_ctx_remove(event->ctx, p);
ssh_poll_ctx_add(p->session->default_poll_ctx, p);
p->session = NULL;

View File

@@ -67,7 +67,6 @@
static int dh_handshake_server(ssh_session session);
/**
* @addtogroup libssh_server
*
@@ -87,7 +86,7 @@ static int server_set_kex(ssh_session session) {
struct ssh_kex_struct *server = &session->next_crypto->server_kex;
int i, j, rc;
const char *wanted;
char hostkeys[64] = {0};
char hostkeys[128] = {0};
enum ssh_keytypes_e keytype;
size_t len;
int ok;
@@ -123,6 +122,11 @@ static int server_set_kex(ssh_session session) {
}
#endif
if (session->srv.rsa_key != NULL) {
/* We support also the SHA2 variants */
len = strlen(hostkeys);
snprintf(hostkeys + len, sizeof(hostkeys) - len,
",rsa-sha2-512,rsa-sha2-256");
len = strlen(hostkeys);
keytype = ssh_key_type(session->srv.rsa_key);
@@ -194,6 +198,37 @@ static int ssh_server_kexdh_init(ssh_session session, ssh_buffer packet){
return SSH_OK;
}
static int ssh_server_send_extensions(ssh_session session) {
int rc;
const char *hostkey_algorithms;
SSH_LOG(SSH_LOG_PACKET, "Sending SSH_MSG_EXT_INFO");
/*
* We can list here all the default hostkey methods, since
* they already contain the SHA2 extension algorithms
*/
hostkey_algorithms = ssh_kex_get_default_methods(SSH_HOSTKEYS);
rc = ssh_buffer_pack(session->out_buffer,
"bdss",
SSH2_MSG_EXT_INFO,
1, /* nr. of extensions */
"server-sig-algs",
hostkey_algorithms);
if (rc != SSH_OK) {
goto error;
}
if (ssh_packet_send(session) == SSH_ERROR) {
goto error;
}
return 0;
error:
ssh_buffer_reinit(session->out_buffer);
return -1;
}
SSH_PACKET_CALLBACK(ssh_packet_kexdh_init){
int rc = SSH_ERROR;
(void)type;
@@ -217,6 +252,8 @@ SSH_PACKET_CALLBACK(ssh_packet_kexdh_init){
switch(session->next_crypto->kex_type){
case SSH_KEX_DH_GROUP1_SHA1:
case SSH_KEX_DH_GROUP14_SHA1:
case SSH_KEX_DH_GROUP16_SHA512:
case SSH_KEX_DH_GROUP18_SHA512:
rc=ssh_server_kexdh_init(session, packet);
break;
#ifdef HAVE_ECDH
@@ -486,6 +523,15 @@ static void ssh_server_connection_callback(ssh_session session){
session->session_state=SSH_SESSION_STATE_AUTHENTICATING;
if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED)
session->session_state = SSH_SESSION_STATE_AUTHENTICATED;
/*
* If the client supports extension negotiation, we will send
* our supported extensions now. This is the first message after
* sending NEWKEYS message and after turning on crypto.
*/
if (session->extensions) {
ssh_server_send_extensions(session);
}
}
break;
case SSH_SESSION_STATE_AUTHENTICATING:

View File

@@ -282,6 +282,7 @@ void ssh_free(ssh_session session) {
SAFE_FREE(session->opts.ProxyCommand);
SAFE_FREE(session->opts.gss_server_identity);
SAFE_FREE(session->opts.gss_client_identity);
SAFE_FREE(session->opts.pubkey_accepted_types);
for (i = 0; i < 10; i++) {
if (session->opts.wanted_methods[i]) {
@@ -341,6 +342,10 @@ const char* ssh_get_kex_algo(ssh_session session) {
return "diffie-hellman-group1-sha1";
case SSH_KEX_DH_GROUP14_SHA1:
return "diffie-hellman-group14-sha1";
case SSH_KEX_DH_GROUP16_SHA512:
return "diffie-hellman-group16-sha512";
case SSH_KEX_DH_GROUP18_SHA512:
return "diffie-hellman-group18-sha512";
case SSH_KEX_ECDH_SHA2_NISTP256:
return "ecdh-sha2-nistp256";
case SSH_KEX_ECDH_SHA2_NISTP384:

2497
src/sftp.c

File diff suppressed because it is too large Load Diff

View File

@@ -202,6 +202,29 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
return NULL;
}
break;
case SSH_FXP_EXTENDED:
rc = ssh_buffer_unpack(payload,
"s",
&msg->submessage);
if (rc != SSH_OK) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
if (strcmp(msg->submessage, "hardlink@openssh.com") == 0 ||
strcmp(msg->submessage, "posix-rename@openssh.com") == 0) {
rc = ssh_buffer_unpack(payload,
"sS",
&msg->filename,
&msg->data);
if (rc != SSH_OK) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
}
break;
default:
ssh_set_error(sftp->session, SSH_FATAL,
"Received unhandled sftp message %d", msg->type);
@@ -242,12 +265,17 @@ uint32_t sftp_client_message_get_flags(sftp_client_message msg){
return msg->flags;
}
const char *sftp_client_message_get_submessage(sftp_client_message msg){
return msg->submessage;
}
void sftp_client_message_free(sftp_client_message msg) {
if (msg == NULL) {
return;
}
SAFE_FREE(msg->filename);
SAFE_FREE(msg->submessage);
ssh_string_free(msg->data);
ssh_string_free(msg->handle);
sftp_attributes_free(msg->attr);

View File

@@ -34,6 +34,9 @@
#include "libssh/priv.h"
#include "libssh/string.h"
/* String maximum size is 256M */
#define STRING_SIZE_MAX 0x10000000
/**
* @defgroup libssh_string The SSH string functions
* @ingroup libssh
@@ -50,22 +53,24 @@
*
* @return The newly allocated string, NULL on error.
*/
struct ssh_string_struct *ssh_string_new(size_t size) {
struct ssh_string_struct *str = NULL;
struct ssh_string_struct *ssh_string_new(size_t size)
{
struct ssh_string_struct *str = NULL;
if (size > UINT_MAX - sizeof(struct ssh_string_struct)) {
return NULL;
}
if (size > STRING_SIZE_MAX) {
errno = EINVAL;
return NULL;
}
str = malloc(sizeof(struct ssh_string_struct) + size);
if (str == NULL) {
return NULL;
}
str = malloc(sizeof(struct ssh_string_struct) + size);
if (str == NULL) {
return NULL;
}
str->size = htonl(size);
str->data[0] = 0;
str->size = htonl(size);
str->data[0] = 0;
return str;
return str;
}
/**
@@ -136,7 +141,7 @@ size_t ssh_string_len(struct ssh_string_struct *s) {
}
size = ntohl(s->size);
if (size > 0 && size < UINT_MAX) {
if (size > 0 && size <= STRING_SIZE_MAX) {
return size;
}

View File

@@ -146,81 +146,79 @@ struct ssh_crypto_struct *crypto_new(void) {
return crypto;
}
void crypto_free(struct ssh_crypto_struct *crypto){
int i;
if (crypto == NULL) {
return;
}
void crypto_free(struct ssh_crypto_struct *crypto)
{
size_t i;
ssh_key_free(crypto->server_pubkey);
if (crypto == NULL) {
return;
}
cipher_free(crypto->in_cipher);
cipher_free(crypto->out_cipher);
ssh_key_free(crypto->server_pubkey);
bignum_safe_free(crypto->e);
bignum_safe_free(crypto->f);
bignum_safe_free(crypto->x);
bignum_safe_free(crypto->y);
bignum_safe_free(crypto->k);
cipher_free(crypto->in_cipher);
cipher_free(crypto->out_cipher);
bignum_safe_free(crypto->e);
bignum_safe_free(crypto->f);
bignum_safe_free(crypto->x);
bignum_safe_free(crypto->y);
bignum_safe_free(crypto->k);
#ifdef HAVE_ECDH
SAFE_FREE(crypto->ecdh_client_pubkey);
SAFE_FREE(crypto->ecdh_server_pubkey);
if(crypto->ecdh_privkey != NULL){
SAFE_FREE(crypto->ecdh_client_pubkey);
SAFE_FREE(crypto->ecdh_server_pubkey);
if(crypto->ecdh_privkey != NULL){
#ifdef HAVE_OPENSSL_ECC
EC_KEY_free(crypto->ecdh_privkey);
EC_KEY_free(crypto->ecdh_privkey);
#elif defined HAVE_GCRYPT_ECC
gcry_sexp_release(crypto->ecdh_privkey);
gcry_sexp_release(crypto->ecdh_privkey);
#endif
crypto->ecdh_privkey = NULL;
}
crypto->ecdh_privkey = NULL;
}
#endif
if(crypto->session_id != NULL){
memset(crypto->session_id, '\0', crypto->digest_len);
SAFE_FREE(crypto->session_id);
}
if(crypto->secret_hash != NULL){
memset(crypto->secret_hash, '\0', crypto->digest_len);
SAFE_FREE(crypto->secret_hash);
}
if (crypto->session_id != NULL) {
explicit_bzero(crypto->session_id, crypto->digest_len);
SAFE_FREE(crypto->session_id);
}
if (crypto->secret_hash != NULL) {
explicit_bzero(crypto->secret_hash, crypto->digest_len);
SAFE_FREE(crypto->secret_hash);
}
#ifdef WITH_ZLIB
if (crypto->compress_out_ctx &&
(deflateEnd(crypto->compress_out_ctx) != 0)) {
inflateEnd(crypto->compress_out_ctx);
}
SAFE_FREE(crypto->compress_out_ctx);
if (crypto->compress_out_ctx &&
(deflateEnd(crypto->compress_out_ctx) != 0)) {
inflateEnd(crypto->compress_out_ctx);
}
SAFE_FREE(crypto->compress_out_ctx);
if (crypto->compress_in_ctx &&
(deflateEnd(crypto->compress_in_ctx) != 0)) {
inflateEnd(crypto->compress_in_ctx);
}
SAFE_FREE(crypto->compress_in_ctx);
if (crypto->compress_in_ctx &&
(deflateEnd(crypto->compress_in_ctx) != 0)) {
inflateEnd(crypto->compress_in_ctx);
}
SAFE_FREE(crypto->compress_in_ctx);
#endif /* WITH_ZLIB */
if(crypto->encryptIV)
SAFE_FREE(crypto->encryptIV);
if(crypto->decryptIV)
SAFE_FREE(crypto->decryptIV);
if(crypto->encryptMAC)
SAFE_FREE(crypto->encryptMAC);
if(crypto->decryptMAC)
SAFE_FREE(crypto->decryptMAC);
if(crypto->encryptkey){
memset(crypto->encryptkey, 0, crypto->digest_len);
SAFE_FREE(crypto->encryptkey);
}
if(crypto->decryptkey){
memset(crypto->decryptkey, 0, crypto->digest_len);
SAFE_FREE(crypto->decryptkey);
}
if (crypto->encryptkey != NULL) {
explicit_bzero(crypto->encryptkey, crypto->digest_len);
SAFE_FREE(crypto->encryptkey);
}
if (crypto->decryptkey != NULL) {
explicit_bzero(crypto->decryptkey, crypto->digest_len);
SAFE_FREE(crypto->decryptkey);
}
for (i = 0; i < SSH_KEX_METHODS; i++) {
SAFE_FREE(crypto->client_kex.methods[i]);
SAFE_FREE(crypto->server_kex.methods[i]);
SAFE_FREE(crypto->kex_methods[i]);
}
for (i = 0; i < SSH_KEX_METHODS; i++) {
SAFE_FREE(crypto->client_kex.methods[i]);
SAFE_FREE(crypto->server_kex.methods[i]);
SAFE_FREE(crypto->kex_methods[i]);
}
explicit_bzero(crypto, sizeof(struct ssh_crypto_struct));
explicit_bzero(crypto, sizeof(struct ssh_crypto_struct));
SAFE_FREE(crypto);
SAFE_FREE(crypto);
}
static int crypt_set_algorithms2(ssh_session session){
@@ -509,7 +507,7 @@ int crypt_set_algorithms_server(ssh_session session){
}
method = session->next_crypto->kex_methods[SSH_HOSTKEYS];
session->srv.hostkey = ssh_key_type_from_name(method);
session->srv.hostkey = ssh_key_type_from_signature_name(method);
return SSH_OK;
}

View File

@@ -31,6 +31,9 @@ add_library(${TORTURE_LIBRARY}
torture_pki.c
torture_cmocka.c)
target_link_libraries(${TORTURE_LIBRARY} ${TORTURE_LINK_LIBRARIES})
target_compile_options(${TORTURE_LIBRARY} PRIVATE
-DSSH_PING_EXECUTABLE="${CMAKE_CURRENT_BINARY_DIR}/ssh_ping"
)
if (ARGP_LIBRARY)
target_link_libraries(${TORTURE_LIBRARY}
@@ -87,6 +90,11 @@ if (CLIENT_TESTING)
chroot_wrapper
)
# ssh_ping
add_executable(ssh_ping ssh_ping.c)
target_compile_options(ssh_ping PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(ssh_ping ${LIBSSH_SHARED_LIBRARY})
# homedir will be used in passwd
set(HOMEDIR ${CMAKE_CURRENT_BINARY_DIR}/home)
@@ -111,9 +119,14 @@ if (CLIENT_TESTING)
# Give bob some keys
file(COPY keys/id_rsa DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
file(COPY keys/id_rsa.pub DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
file(COPY keys/id_ecdsa DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
file(COPY keys/id_ecdsa.pub DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
# Allow to auth with bob his public keys on alice account
configure_file(keys/id_rsa.pub ${CMAKE_CURRENT_BINARY_DIR}/home/alice/.ssh/authorized_keys @ONLY)
# append ECDSA public key
file(READ keys/id_ecdsa.pub CONTENTS)
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/home/alice/.ssh/authorized_keys "${CONTENTS}")
# Copy the signed key to an alternative directory in bob's homedir.
file(COPY keys/certauth/id_rsa DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh_cert/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)

View File

@@ -15,12 +15,18 @@ set(LIBSSH_CLIENT_TESTS
torture_request_env)
if (WITH_SFTP)
if (WITH_BENCHMARKS)
set(SFTP_BENCHMARK_TESTS
torture_sftp_benchmark)
endif()
set(LIBSSH_CLIENT_TESTS
${LIBSSH_CLIENT_TESTS}
torture_sftp_ext
torture_sftp_canonicalize_path
torture_sftp_dir
torture_sftp_read
torture_sftp_fsync)
torture_sftp_fsync
${SFTP_BENCHMARK_TESTS})
endif (WITH_SFTP)
foreach(_CLI_TEST ${LIBSSH_CLIENT_TESTS})

View File

@@ -547,6 +547,175 @@ static void torture_auth_agent_cert_nonblocking(void **state) {
torture_auth_agent_nonblocking(state);
}
static void torture_auth_pubkey_types(void **state)
{
struct torture_state *s = *state;
ssh_session session = s->ssh.session;
int rc;
rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE);
assert_ssh_return_code(session, rc);
rc = ssh_connect(session);
assert_ssh_return_code(session, rc);
rc = ssh_userauth_none(session,NULL);
/* This request should return a SSH_REQUEST_DENIED error */
if (rc == SSH_ERROR) {
assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
}
rc = ssh_userauth_list(session, NULL);
assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);
/* Disable RSA key types for authentication */
rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
"ssh-dss");
assert_ssh_return_code(session, rc);
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
assert_int_equal(rc, SSH_AUTH_DENIED);
/* Now enable it and retry */
rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
"rsa-sha2-512,ssh-rsa");
assert_ssh_return_code(session, rc);
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
assert_int_equal(rc, SSH_AUTH_SUCCESS);
}
static void torture_auth_pubkey_types_ecdsa(void **state)
{
struct torture_state *s = *state;
ssh_session session = s->ssh.session;
int rc;
rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE);
assert_ssh_return_code(session, rc);
rc = ssh_connect(session);
assert_ssh_return_code(session, rc);
rc = ssh_userauth_none(session,NULL);
/* This request should return a SSH_REQUEST_DENIED error */
if (rc == SSH_ERROR) {
assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
}
rc = ssh_userauth_list(session, NULL);
assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);
/* We have only the 256b key -- whitelisting only larger should fail */
rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
"ecdsa-sha2-nistp384");
assert_ssh_return_code(session, rc);
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
assert_int_equal(rc, SSH_AUTH_DENIED);
/* Verify we can use also ECDSA keys with their various names */
rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
"ecdsa-sha2-nistp256");
assert_ssh_return_code(session, rc);
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
assert_int_equal(rc, SSH_AUTH_SUCCESS);
}
static void torture_auth_pubkey_types_nonblocking(void **state)
{
struct torture_state *s = *state;
ssh_session session = s->ssh.session;
int rc;
rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE);
assert_ssh_return_code(session, rc);
rc = ssh_connect(session);
assert_ssh_return_code(session, rc);
ssh_set_blocking(session,0);
do {
rc = ssh_userauth_none(session, NULL);
} while (rc == SSH_AUTH_AGAIN);
/* This request should return a SSH_REQUEST_DENIED error */
if (rc == SSH_ERROR) {
assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);
}
rc = ssh_userauth_list(session, NULL);
assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);
/* Disable RSA key types for authentication */
rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
"ssh-dss");
assert_ssh_return_code(session, rc);
do {
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
} while (rc == SSH_AUTH_AGAIN);
assert_int_equal(rc, SSH_AUTH_DENIED);
/* Now enable it and retry */
rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
"rsa-sha2-512,ssh-rsa");
assert_ssh_return_code(session, rc);
do {
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
} while (rc == SSH_AUTH_AGAIN);
assert_int_equal(rc, SSH_AUTH_SUCCESS);
}
static void torture_auth_pubkey_types_ecdsa_nonblocking(void **state)
{
struct torture_state *s = *state;
ssh_session session = s->ssh.session;
int rc;
rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE);
assert_ssh_return_code(session, rc);
rc = ssh_connect(session);
assert_ssh_return_code(session, rc);
ssh_set_blocking(session,0);
do {
rc = ssh_userauth_none(session, NULL);
} while (rc == SSH_AUTH_AGAIN);
/* This request should return a SSH_REQUEST_DENIED error */
if (rc == SSH_ERROR) {
assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);
}
rc = ssh_userauth_list(session, NULL);
assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);
/* We have only the 256b key -- whitelisting only larger should fail */
rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
"ecdsa-sha2-nistp384");
assert_ssh_return_code(session, rc);
do {
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
} while (rc == SSH_AUTH_AGAIN);
assert_int_equal(rc, SSH_AUTH_DENIED);
/* Verify we can use also ECDSA keys with their various names */
rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
"ecdsa-sha2-nistp256");
assert_ssh_return_code(session, rc);
do {
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
} while (rc == SSH_AUTH_AGAIN);
assert_int_equal(rc, SSH_AUTH_SUCCESS);
}
int torture_run_tests(void) {
int rc;
@@ -590,6 +759,18 @@ int torture_run_tests(void) {
cmocka_unit_test_setup_teardown(torture_auth_agent_cert_nonblocking,
agent_cert_setup,
agent_teardown),
cmocka_unit_test_setup_teardown(torture_auth_pubkey_types,
pubkey_setup,
session_teardown),
cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_nonblocking,
pubkey_setup,
session_teardown),
cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ecdsa,
pubkey_setup,
session_teardown),
cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ecdsa_nonblocking,
pubkey_setup,
session_teardown),
};
ssh_init();

View File

@@ -0,0 +1,132 @@
#define LIBSSH_STATIC
#include "config.h"
#include "torture.h"
#include "sftp.c"
#include <sys/types.h>
#include <pwd.h>
#include <errno.h>
#define MAX_XFER_BUF_SIZE 16384
static int sshd_setup(void **state)
{
torture_setup_sshd_server(state);
return 0;
}
static int sshd_teardown(void **state) {
torture_teardown_sshd_server(state);
return 0;
}
static int session_setup(void **state)
{
struct torture_state *s = *state;
struct passwd *pwd;
int rc;
pwd = getpwnam("bob");
assert_non_null(pwd);
rc = setuid(pwd->pw_uid);
assert_return_code(rc, errno);
s->ssh.session = torture_ssh_session(TORTURE_SSH_SERVER,
NULL,
TORTURE_SSH_USER_ALICE,
NULL);
assert_non_null(s->ssh.session);
s->ssh.tsftp = torture_sftp_session(s->ssh.session);
assert_non_null(s->ssh.tsftp);
return 0;
}
static int session_teardown(void **state)
{
struct torture_state *s = *state;
torture_rmdirs(s->ssh.tsftp->testdir);
torture_sftp_close(s->ssh.tsftp);
ssh_disconnect(s->ssh.session);
ssh_free(s->ssh.session);
return 0;
}
static void torture_sftp_benchmark_write_read(void **state)
{
struct torture_state *s = *state;
struct torture_sftp *t = s->ssh.tsftp;
sftp_session sftp = t->sftp;
ssh_session session = s->ssh.session;
sftp_file file = NULL;
struct stat sb = {
.st_size = 0,
};
uint8_t buf_16k[MAX_XFER_BUF_SIZE];
char local_path[1024] = {0};
ssize_t bwritten, nread;
size_t i;
int rc;
memset(buf_16k, 'X', sizeof(buf_16k));
snprintf(local_path, sizeof(local_path), "%s/128M.dat", t->testdir);
file = sftp_open(sftp, local_path, O_CREAT|O_WRONLY|O_TRUNC, 0644);
assert_non_null(file);
/* Write 128M */
for (i = 0; i < 0x2000; i++) {
bwritten = sftp_write(file, buf_16k, sizeof(buf_16k));
assert_int_equal(bwritten, sizeof(buf_16k));
}
rc = sftp_close(file);
assert_ssh_return_code(session, rc);
/* Check that 128M has been written */
rc = stat(local_path, &sb);
assert_int_equal(sb.st_size, 0x8000000);
file = sftp_open(sftp, local_path, O_RDONLY, 0);
assert_non_null(file);
for (;;) {
nread = sftp_read(file, buf_16k, sizeof(buf_16k));
if (nread == 0) {
break; /* EOF */
}
assert_int_equal(nread, sizeof(buf_16k));
}
rc = sftp_close(file);
assert_ssh_return_code(session, rc);
unlink(local_path);
}
int torture_run_tests(void)
{
int rc;
struct CMUnitTest tests[] = {
cmocka_unit_test_setup_teardown(torture_sftp_benchmark_write_read,
session_setup,
session_teardown)
};
ssh_init();
torture_filter_tests(tests);
rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown);
ssh_finalize();
return rc;
}

View File

@@ -0,0 +1,96 @@
#include "config.h"
#define LIBSSH_STATIC
#include "torture.h"
#include "sftp.c"
#include <sys/types.h>
#include <pwd.h>
#include <errno.h>
static int sshd_setup(void **state)
{
torture_setup_sshd_server(state);
return 0;
}
static int sshd_teardown(void **state) {
torture_teardown_sshd_server(state);
return 0;
}
static int session_setup(void **state)
{
struct torture_state *s = *state;
struct passwd *pwd;
int rc;
pwd = getpwnam("bob");
assert_non_null(pwd);
rc = setuid(pwd->pw_uid);
assert_return_code(rc, errno);
s->ssh.session = torture_ssh_session(TORTURE_SSH_SERVER,
NULL,
TORTURE_SSH_USER_ALICE,
NULL);
assert_non_null(s->ssh.session);
s->ssh.tsftp = torture_sftp_session(s->ssh.session);
assert_non_null(s->ssh.tsftp);
return 0;
}
static int session_teardown(void **state)
{
struct torture_state *s = *state;
torture_rmdirs(s->ssh.tsftp->testdir);
torture_sftp_close(s->ssh.tsftp);
ssh_disconnect(s->ssh.session);
ssh_free(s->ssh.session);
return 0;
}
static void torture_sftp_canonicalize_path(void **state)
{
struct torture_state *s = *state;
struct torture_sftp *t = s->ssh.tsftp;
struct passwd *pwd = NULL;
char *canonicalized_path = NULL;
pwd = getpwnam(TORTURE_SSH_USER_ALICE);
assert_non_null(pwd);
canonicalized_path = sftp_canonicalize_path(t->sftp, ".");
assert_non_null(canonicalized_path);
assert_string_equal(canonicalized_path, pwd->pw_dir);
SSH_STRING_FREE_CHAR(canonicalized_path);
}
int torture_run_tests(void) {
int rc;
struct CMUnitTest tests[] = {
cmocka_unit_test_setup_teardown(torture_sftp_canonicalize_path,
session_setup,
session_teardown)
};
ssh_init();
torture_filter_tests(tests);
rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown);
ssh_finalize();
return rc;
}

View File

@@ -39,6 +39,7 @@ set(CTEST_SOURCE_DIRECTORY "${CTEST_DIRECTORY}/${CTEST_BUILD_NAME}/source")
set(CTEST_BINARY_DIRECTORY "${CTEST_DIRECTORY}/${CTEST_BUILD_NAME}/build")
set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE ${CMAKE_SOURCE_DIR}/tests/valgrind.supp)
set(CTEST_MEMORYCHECK_COMMAND_OPTIONS " --trace-children-skip=sshd")
find_program(CTEST_GIT_COMMAND NAMES git)
find_program(CTEST_COVERAGE_COMMAND NAMES gcov)

5
tests/keys/id_ecdsa Normal file
View File

@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIHbL0nzpzLS3ImIlhEffbDzPlIw/tn5QcfB64PbSiBl6oAoGCCqGSM49
AwEHoUQDQgAERzA8X8OP7C3W/e1UNLh+21xIZVBiQ7i4Qb4xoOebRWuwzitEZon/
8Dz+VpE29krJgCagqSt5RLllOx8eS2i8fw==
-----END EC PRIVATE KEY-----

1
tests/keys/id_ecdsa.pub Normal file
View File

@@ -0,0 +1 @@
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEcwPF/Dj+wt1v3tVDS4fttcSGVQYkO4uEG+MaDnm0VrsM4rRGaJ//A8/laRNvZKyYAmoKkreUS5ZTsfHktovH8= comment

View File

@@ -38,7 +38,7 @@ target_link_libraries(pkd_hello ${pkd_libs})
# specified with `-i` and may be helpful for chasing down bugs that
# are not 100% reproducible.
#
add_test(pkd_hello_i1 ${CMAKE_CURRENT_BINARY_DIR}/pkd_hello -i1 -w /tmp/pkd_socket_wrapper_XXXXXX)
add_test(pkd_hello_i1 ${CMAKE_CURRENT_BINARY_DIR}/pkd_hello -e -o -i1 -w /tmp/pkd_socket_wrapper_XXXXXX)
#
# Configure environment for cwrap socket wrapper.

View File

@@ -15,8 +15,8 @@
#define OPENSSH_BINARY "ssh"
#define OPENSSH_KEYGEN "ssh-keygen"
#define OPENSSH_HOSTKEY_ALGOS_DEFAULT "ssh-ed25519,ssh-rsa"
#define OPENSSH_PKACCEPTED_DEFAULT "ssh-ed25519,ssh-rsa"
#define OPENSSH_HOSTKEY_ALGOS_DEFAULT "ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa"
#define OPENSSH_PKACCEPTED_DEFAULT "ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa"
#if HAVE_ECC
#define OPENSSH_HOSTKEY_ALGOS_ECDSA ",ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521"

View File

@@ -438,6 +438,9 @@ static void *pkd_main(void *args) {
goto out;
}
/* Ignore SIGPIPE */
signal(SIGPIPE, SIG_IGN);
rc = pkd_init_libssh();
if (rc != 0) {
pkderr("pkd_init_libssh: %d\n", rc);

View File

@@ -222,6 +222,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
f(client, rsa_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_rsa, teardown) \
f(client, rsa_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_rsa, teardown) \
f(client, rsa_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_rsa, teardown) \
f(client, rsa_diffie_hellman_group16_sha512, kexcmd("diffie-hellman-group16-sha512"), setup_rsa, teardown) \
f(client, rsa_diffie_hellman_group18_sha512, kexcmd("diffie-hellman-group18-sha512"), setup_rsa, teardown) \
f(client, rsa_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_rsa, teardown) \
f(client, rsa_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_rsa, teardown) \
f(client, dsa_curve25519_sha256, kexcmd("curve25519-sha256"), setup_dsa, teardown) \
@@ -229,6 +231,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
f(client, dsa_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256 "), setup_dsa, teardown) \
f(client, dsa_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384 "), setup_dsa, teardown) \
f(client, dsa_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521 "), setup_dsa, teardown) \
f(client, dsa_diffie_hellman_group16_sha512, kexcmd("diffie-hellman-group16-sha512"), setup_dsa, teardown) \
f(client, dsa_diffie_hellman_group18_sha512, kexcmd("diffie-hellman-group18-sha512"), setup_dsa, teardown) \
f(client, dsa_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_dsa, teardown) \
f(client, dsa_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_dsa, teardown) \
f(client, ecdsa_256_curve25519_sha256, kexcmd("curve25519-sha256"), setup_ecdsa_256, teardown) \
@@ -236,6 +240,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
f(client, ecdsa_256_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ecdsa_256, teardown) \
f(client, ecdsa_256_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ecdsa_256, teardown) \
f(client, ecdsa_256_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ecdsa_256, teardown) \
f(client, ecdsa_256_diffie_hellman_group16_sha512,kexcmd("diffie-hellman-group16-sha512"), setup_ecdsa_256, teardown) \
f(client, ecdsa_256_diffie_hellman_group18_sha512,kexcmd("diffie-hellman-group18-sha512"), setup_ecdsa_256, teardown) \
f(client, ecdsa_256_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ecdsa_256, teardown) \
f(client, ecdsa_256_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ecdsa_256, teardown) \
f(client, ecdsa_384_curve25519_sha256, kexcmd("curve25519-sha256"), setup_ecdsa_384, teardown) \
@@ -243,6 +249,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
f(client, ecdsa_384_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ecdsa_384, teardown) \
f(client, ecdsa_384_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ecdsa_384, teardown) \
f(client, ecdsa_384_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ecdsa_384, teardown) \
f(client, ecdsa_384_diffie_hellman_group16_sha512,kexcmd("diffie-hellman-group16-sha512"), setup_ecdsa_384, teardown) \
f(client, ecdsa_384_diffie_hellman_group18_sha512,kexcmd("diffie-hellman-group18-sha512"), setup_ecdsa_384, teardown) \
f(client, ecdsa_384_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ecdsa_384, teardown) \
f(client, ecdsa_384_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ecdsa_384, teardown) \
f(client, ecdsa_521_curve25519_sha256, kexcmd("curve25519-sha256"), setup_ecdsa_521, teardown) \
@@ -250,6 +258,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
f(client, ecdsa_521_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ecdsa_521, teardown) \
f(client, ecdsa_521_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ecdsa_521, teardown) \
f(client, ecdsa_521_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ecdsa_521, teardown) \
f(client, ecdsa_521_diffie_hellman_group16_sha512,kexcmd("diffie-hellman-group16-sha512"), setup_ecdsa_521, teardown) \
f(client, ecdsa_521_diffie_hellman_group18_sha512,kexcmd("diffie-hellman-group18-sha512"), setup_ecdsa_521, teardown) \
f(client, ecdsa_521_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ecdsa_521, teardown) \
f(client, ecdsa_521_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ecdsa_521, teardown)
#else
@@ -260,6 +270,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
f(client, rsa_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_rsa, teardown) \
f(client, rsa_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_rsa, teardown) \
f(client, rsa_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_rsa, teardown) \
f(client, rsa_diffie_hellman_group16_sha512, kexcmd("diffie-hellman-group16-sha512"), setup_rsa, teardown) \
f(client, rsa_diffie_hellman_group18_sha512, kexcmd("diffie-hellman-group18-sha512"), setup_rsa, teardown) \
f(client, rsa_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_rsa, teardown) \
f(client, rsa_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_rsa, teardown) \
f(client, ecdsa_256_curve25519_sha256, kexcmd("curve25519-sha256"), setup_ecdsa_256, teardown) \
@@ -267,6 +279,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
f(client, ecdsa_256_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ecdsa_256, teardown) \
f(client, ecdsa_256_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ecdsa_256, teardown) \
f(client, ecdsa_256_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ecdsa_256, teardown) \
f(client, ecdsa_256_diffie_hellman_group16_sha512,kexcmd("diffie-hellman-group16-sha512"), setup_ecdsa_256, teardown) \
f(client, ecdsa_256_diffie_hellman_group18_sha512,kexcmd("diffie-hellman-group18-sha512"), setup_ecdsa_256, teardown) \
f(client, ecdsa_256_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ecdsa_256, teardown) \
f(client, ecdsa_256_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ecdsa_256, teardown) \
f(client, ecdsa_384_curve25519_sha256, kexcmd("curve25519-sha256"), setup_ecdsa_384, teardown) \
@@ -274,6 +288,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
f(client, ecdsa_384_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ecdsa_384, teardown) \
f(client, ecdsa_384_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ecdsa_384, teardown) \
f(client, ecdsa_384_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ecdsa_384, teardown) \
f(client, ecdsa_384_diffie_hellman_group16_sha512,kexcmd("diffie-hellman-group16-sha512"), setup_ecdsa_384, teardown) \
f(client, ecdsa_384_diffie_hellman_group18_sha512,kexcmd("diffie-hellman-group18-sha512"), setup_ecdsa_384, teardown) \
f(client, ecdsa_384_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ecdsa_384, teardown) \
f(client, ecdsa_384_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ecdsa_384, teardown) \
f(client, ecdsa_521_curve25519_sha256, kexcmd("curve25519-sha256"), setup_ecdsa_521, teardown) \
@@ -281,6 +297,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
f(client, ecdsa_521_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ecdsa_521, teardown) \
f(client, ecdsa_521_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ecdsa_521, teardown) \
f(client, ecdsa_521_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ecdsa_521, teardown) \
f(client, ecdsa_521_diffie_hellman_group16_sha512,kexcmd("diffie-hellman-group16-sha512"), setup_ecdsa_521, teardown) \
f(client, ecdsa_521_diffie_hellman_group18_sha512,kexcmd("diffie-hellman-group18-sha512"), setup_ecdsa_521, teardown) \
f(client, ecdsa_521_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ecdsa_521, teardown) \
f(client, ecdsa_521_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ecdsa_521, teardown)
#endif
@@ -294,6 +312,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
f(client, ed25519_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ed25519, teardown) \
f(client, ed25519_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ed25519, teardown) \
f(client, ed25519_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ed25519, teardown) \
f(client, ed25519_diffie_hellman_group16_sha512, kexcmd("diffie-hellman-group16-sha512"), setup_ed25519, teardown) \
f(client, ed25519_diffie_hellman_group18_sha512, kexcmd("diffie-hellman-group18-sha512"), setup_ed25519, teardown) \
f(client, ed25519_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ed25519, teardown) \
f(client, ed25519_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ed25519, teardown)
#else
@@ -304,7 +324,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
f(client, ed25519_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ed25519, teardown) \
f(client, ed25519_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ed25519, teardown) \
f(client, ed25519_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ed25519, teardown) \
f(client, ed25519_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ed25519, teardown) \
f(client, ed25519_diffie_hellman_group16_sha512, kexcmd("diffie-hellman-group16-sha512"), setup_ed25519, teardown) \
f(client, ed25519_diffie_hellman_group18_sha512, kexcmd("diffie-hellman-group18-sha512"), setup_ed25519, teardown) \
f(client, ed25519_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ed25519, teardown)
#endif

67
tests/ssh_ping.c Normal file
View File

@@ -0,0 +1,67 @@
/* ssh_ping.c */
/*
Copyright 2018 Red Hat, Inc
Author: Jakub Jelen <jjelen@redhat.com>
This file is part of the SSH Library
You are free to copy this file, modify it in any way, consider it being public
domain. This does not apply to the rest of the library though, but it is
allowed to cut-and-paste working code from this file to any license of
program.
The goal is to show the API in action. It's not a reference on how terminal
clients must be made or how a client should react.
*/
#include <stdio.h>
#include <stdlib.h>
#include <libssh/libssh.h>
int main(int argc, char **argv)
{
const char *banner = NULL;
ssh_session session = NULL;
int rc = 1;
if (argc < 1 || argv[1] == NULL) {
fprintf(stderr, "Error: Need an argument (hostname)\n");
goto out;
}
session = ssh_new();
if (session == NULL) {
goto out;
}
rc = ssh_options_set(session, SSH_OPTIONS_HOST, argv[1]);
if (rc < 0) {
goto out;
}
/* The automatic username is not available under uid wrapper */
rc = ssh_options_set(session, SSH_OPTIONS_USER, "ping");
if (rc < 0) {
goto out;
}
rc = ssh_connect(session);
if (rc != SSH_OK) {
fprintf(stderr, "Connection failed : %s\n", ssh_get_error(session));
goto out;
}
banner = ssh_get_serverbanner(session);
if (banner == NULL) {
fprintf(stderr, "Did not receive SSH banner\n");
goto out;
}
printf("OK: %s\n", banner);
rc = 0;
out:
ssh_free(session);
return rc;
}

View File

@@ -42,6 +42,7 @@
#include "torture.h"
#include "torture_key.h"
#include "libssh/misc.h"
/* for pattern matching */
#include "match.c"
@@ -577,7 +578,6 @@ static void torture_setup_create_sshd_config(void **state)
"KbdInteractiveAuthentication yes\n"
"PubkeyAuthentication yes\n"
"\n"
"UsePrivilegeSeparation no\n"
"StrictModes no\n"
"\n"
"UsePAM yes\n"
@@ -603,6 +603,8 @@ static void torture_setup_create_sshd_config(void **state)
"ecdh-sha2-nistp384,ecdh-sha2-nistp521,"
"diffie-hellman-group-exchange-sha256,"
"diffie-hellman-group-exchange-sha1,"
"diffie-hellman-group16-sha512,"
"diffie-hellman-group18-sha512,"
"diffie-hellman-group14-sha1,"
"diffie-hellman-group1-sha1\n"
#endif /* OPENSSH_VERSION >= 6.7 */
@@ -630,7 +632,7 @@ static void torture_setup_create_sshd_config(void **state)
"%s/sshd/ssh_host_ed25519_key",
s->socket_dir);
torture_write_file(ed25519_hostkey,
torture_get_testkey(SSH_KEYTYPE_ED25519, 0, 0));
torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0, 0));
#ifdef HAVE_DSA
snprintf(dsa_hostkey,
@@ -653,13 +655,6 @@ static void torture_setup_create_sshd_config(void **state)
torture_write_file(ecdsa_hostkey,
torture_get_testkey(SSH_KEYTYPE_ECDSA, 521, 0));
snprintf(ed25519_hostkey,
sizeof(ed25519_hostkey),
"%s/sshd/ssh_host_ed25519_key",
s->socket_dir);
torture_write_file(ed25519_hostkey,
torture_get_testkey(SSH_KEYTYPE_ED25519, 0, 0));
snprintf(trusted_ca_pubkey,
sizeof(trusted_ca_pubkey),
"%s/sshd/user_ca.pub",
@@ -704,6 +699,24 @@ static void torture_setup_create_sshd_config(void **state)
torture_write_file(s->srv_config, sshd_config);
}
static int torture_wait_for_daemon(unsigned int seconds)
{
struct ssh_timestamp start;
int rc;
ssh_timestamp_init(&start);
while (!ssh_timeout_elapsed(&start, seconds * 1000)) {
rc = system(SSH_PING_EXECUTABLE " " TORTURE_SSH_SERVER);
if (rc == 0) {
return 0;
}
/* Wait 200 ms before retrying */
usleep(200 * 1000);
}
return 1;
}
void torture_setup_sshd_server(void **state)
{
struct torture_state *s;
@@ -726,11 +739,12 @@ void torture_setup_sshd_server(void **state)
rc = system(sshd_start_cmd);
assert_return_code(rc, errno);
/* Give the process 500ms time to initialize and start */
usleep(500 * 1000);
setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "21", 1);
unsetenv("PAM_WRAPPER");
/* Wait until the sshd is ready to accept connections */
rc = torture_wait_for_daemon(5);
assert_int_equal(rc, 0);
}
void torture_teardown_socket_dir(void **state)

View File

@@ -23,6 +23,8 @@
#include "config.h"
#define LIBSSH_STATIC
#include "torture.h"
void _assert_ssh_return_code(ssh_session session,

View File

@@ -91,6 +91,70 @@ static const char torture_rsa_private_testkey_passphrase[] =
"JSvUyxoaZUjQkT7iF94HsF+FVVJdI55UjgnMiZ0d5vKffWyTHYcYHkFYaSloAMWN\n"
"-----END RSA PRIVATE KEY-----\n";
static const char torture_rsa_private_openssh_testkey_passphrase[] =
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
"b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDX\n"
"ClCBeHgYyOEqmWpAanz9AAAAEAAAAAEAAAEXAAAAB3NzaC1yc2EAAAADAQABAAAB\n"
"AQDXvXuawzaArEwkLIXTz/EWywLOCtqQL3P9yKkrhz6AplXP2PhOh5pyxa1VfGKe\n"
"453jNeYBJ0ROto3BshXgZXbo86oLXTkbe0gO5xi3r5WjXxjOFvRRTLot5fPLNDOv\n"
"9+TnsPmkNn0iIeyPnfrcPIyjWt5zSWUfkNC8oNHxsiSshjpbJvTXSDipukpUy41d\n"
"7jg4uWGuonMTF7yu7HfuHqq7lhb0WlwSpfbqAbfYARBddcdcARyhix4RMWZZqVY2\n"
"0H3Vsjq8bjKC+NJXFce1PRg+qcOWQdlXEei4dkzAvHvfQRx1TjzkrBZ6B6thmZty\n"
"eb9IsiB0tg2g0JN2VTAGkxqpAAADwG8gm8jZpx+GIKdhV+igcvYvIhzA+fz6UdXf\n"
"d/8wnYzMXtg+Ys7XsKUsxtMD8HGPiuwYsTrd/YGiol7SpkJV0STqtW+UZrcKamJ5\n"
"reFaDoIU8hhWTXCe/ogplTxH/zNNK7Xx5OAGnNWE3zsR1vbZaCv+Vwwa27eUCbpv\n"
"V1+92nBwkah3FCKCbwYDvTVRn1TZHQwnuNxDCRrlwaMjf8eX2ssqLLX7jqrb3j1u\n"
"c28GR3fNJ8ENaWshZ77tqexUQCnCx14/qtT434CMvENXnCP5BP/cRmbOlCFQ6Id7\n"
"nLMW0uDIy/q3xBsAcdMyV0LJW7sJNXIjTnS4lyXd0XescXrqTAKxTkqd1E0VIBpc\n"
"37+7vqv9A9Xxq74jy//L9L4Yrbijc9Vt+oNWFgOuakZGBLIQvm36Oqb0z0oWJcUt\n"
"VdZcvkCNMeixBqCnrQ8egO3x0pnZwo6cwH586Me8FgFacOnzWjzuQT6vYJ4EK5ch\n"
"YNRQpjtz5+T3rZK7eIF1ZUobM4S6di7A6lW9tycQVhjo5XlhalMfCfajhazgcIrY\n"
"Qdaq8+AguP8H+3bvXPZmitL8/mv5uVjqxy1lYh2xLzViTmFnvfdbZ92BWI9C6JBI\n"
"+mRWzXeEY71MjfeEaPStwBm5OYBMFwYrXPL7E3JjAXRxbB+LKUksj/lRk3K7aQp4\n"
"IDKCzAACgkOixfP39BgKQkrLjAoi6mEDqu5Ajc3GoljXsJEkcbu0j+0tVth+41nV\n"
"8yCkP5SVUQTCSKzoduE+0pk6oYO6vrwKLM62cQRPXLl/XNoUqETIe8dklIKojYo6\n"
"3ho1RaHgYr9/NAS0029CFt/rGmONWF9ihKON6wMavJRcofZ25FeylKiP2rrqdDIb\n"
"EiWULZi3MUJfKBwSeZMwaYYmSpaOZF1U/MgvEfeRkE1UmDp3FmBLSNHBYhAxNazH\n"
"R393BTr1zk7h+8s7QK986ZtcKkyUNXEK1NkLLuKlqMwFnjiOdeAIGwz9NEn+Tj60\n"
"jE5IcCE06B6ze/MOZcsPp1SoZv4kKmgWY5Gdqv/9O9SyFQ0Yh4MvBSD8l4x0epId\n"
"8Xm54ISVWP1SZ1x3Oe8yvtwOGqDkZeOVjnP7EQ7R0+1PZzW5P/x47skACqadGChN\n"
"ahbngIl+EhPOqhx+wIfDbtzTmGABgNhcI/d02b8py5MXFnA+uzeSucDREYRdm2TO\n"
"TQQ2CtxB6lcatIYG4AhyouQbujLd/AwpZJ05S1i/Qt6NenTgK3YyTWdXLQnjZSMx\n"
"FBRkf+Jj9eVXieT4PJKtWuvxNNrJVA==\n"
"-----END OPENSSH PRIVATE KEY-----\n";
static const char torture_rsa_private_openssh_testkey[] =
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdz\n"
"c2gtcnNhAAAAAwEAAQAAAQEA1717msM2gKxMJCyF08/xFssCzgrakC9z/cipK4c+\n"
"gKZVz9j4ToeacsWtVXxinuOd4zXmASdETraNwbIV4GV26POqC105G3tIDucYt6+V\n"
"o18Yzhb0UUy6LeXzyzQzr/fk57D5pDZ9IiHsj5363DyMo1rec0llH5DQvKDR8bIk\n"
"rIY6Wyb010g4qbpKVMuNXe44OLlhrqJzExe8rux37h6qu5YW9FpcEqX26gG32AEQ\n"
"XXXHXAEcoYseETFmWalWNtB91bI6vG4ygvjSVxXHtT0YPqnDlkHZVxHouHZMwLx7\n"
"30EcdU485KwWegerYZmbcnm/SLIgdLYNoNCTdlUwBpMaqQAAA7iQHqVWkB6lVgAA\n"
"AAdzc2gtcnNhAAABAQDXvXuawzaArEwkLIXTz/EWywLOCtqQL3P9yKkrhz6AplXP\n"
"2PhOh5pyxa1VfGKe453jNeYBJ0ROto3BshXgZXbo86oLXTkbe0gO5xi3r5WjXxjO\n"
"FvRRTLot5fPLNDOv9+TnsPmkNn0iIeyPnfrcPIyjWt5zSWUfkNC8oNHxsiSshjpb\n"
"JvTXSDipukpUy41d7jg4uWGuonMTF7yu7HfuHqq7lhb0WlwSpfbqAbfYARBddcdc\n"
"ARyhix4RMWZZqVY20H3Vsjq8bjKC+NJXFce1PRg+qcOWQdlXEei4dkzAvHvfQRx1\n"
"TjzkrBZ6B6thmZtyeb9IsiB0tg2g0JN2VTAGkxqpAAAAAwEAAQAAAQAdjR3uQAkq\n"
"LO+tENAwCE680YgL0x7HG0jnHWJWzQq5so8UjmLM1vRH/l3U1Nnpa8JHyi08QTWx\n"
"Fn5qZstqVluoYyAKuHVHF2bya6NOHeYAX9lU+X3z2O+zs8jmL7tYwjr/pZU8ch5H\n"
"25+8uGYRXtXg1mScJBSO81Y0UE8RrVYqr2Os583yB657kYiVYYYSZlRGd9wmfXnJ\n"
"w0t8LaYcTn+i/lOvrJGa0Q0iV6+4rYmjwYd/D/vyNzF31hUEFrn3vDSgTnJdShgH\n"
"VqW0OwNuEDe/4p8KkKR1EVVj6xv4zicwouY7aQI+zT3MwAzvNdvYwytsIj6bhT9x\n"
"oyeAAIW0vaKVAAAAgQD6pPfu6tb7DiTlaH3/IPdGh3PTIf0zXHZ/ygxORXBZdoLY\n"
"Fq2h/YnBd2Hs8vARAjGJYs78gTPP0FVXPV8ut38xct4DQ2hbPMrjWv5gdhDazq8Q\n"
"qaFEa0+DeYONej8ItKwpsV2Rskkv5Pfm7M6EffVty1uzOpIcT8RYDAYUlc5D/wAA\n"
"AIEA+44ykLho3BDWnUzshVEm6iNoqlZqcDVcNSpCuYDnCy5UrTDk0zj+OUG9M0Zx\n"
"4c7kAmu/poXSimgAgMh9GNCzy3+a70WvH+fBqvG5tXLaSOQCswSdQjltANAnlt5L\n"
"YDHzGGJBsS4pYxoz22MKhFbpYUCQJvotXnZJpTQU6hdFRX8AAACBANuNSlFq/vG8\n"
"Vf9c2YsPiITmOrYxpUDMiMLvUGQOdyIIc45EAggOFHNF3AdPZEhinpD92EK+LiJc\n"
"WYJ26muVcicZoddgmpcHRt2gByC+ckWOM4sLpih6EyQLFZfqTx2X+KOI0ZTt7zEi\n"
"zfm1MJUNDFOr3DM0VBIf34Bn1hU/isPXAAAAAAEC\n"
"-----END OPENSSH PRIVATE KEY-----\n";
static const char torture_rsa_public_testkey[] =
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsA5ERRaUFckApnmEAFjLGdFrIN"
"k/Vsl4ts9Ur6enF6auEfJmCN1tjcAOi34lHJaO+WXbDYYj7duW3SP7H9lbCMwq79B"
@@ -161,6 +225,55 @@ static const char torture_dsa_private_testkey_passphrase[] =
"wHBOL6HrOnD+gGs6DUFwzA==\n"
"-----END DSA PRIVATE KEY-----\n";
static const char torture_dsa_private_openssh_testkey_passphrase[] =
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
"b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABBC\n"
"UZK61oXs3uKMs4l7G0cpAAAAEAAAAAEAAAGxAAAAB3NzaC1kc3MAAACBAJTK9U8S\n"
"SfdSdkOPMLNLNIelOW3OvQRz7WbP8kAKMcwEn0L9b8/C8ffKOR+gWGFES+hjsg+f\n"
"AC7ltzHDxOQhKrthE5DjT0+rDA+/LQ3cZSn/6QpLbrwEgn5Uo3nXddF/t4vV7hod\n"
"Qn5qX3HUnFOZzpPQYGrWXK74JNRTKHblo0MXAAAAFQCvOI9tBplPs3sI0MLCF7lW\n"
"+gvzxwAAAIBeG4hWwnFRAnmdZBEt/ujdcQZD4RxWYc7MwHXEKweNiekSGFyj6v8c\n"
"NlIPfWTMN4BlTJzPfVaoYvzJev45lEuoSwYLt3AQDM+JcO6XTMdyXTKIo+tGsuA0\n"
"kd4pxPol+UGeAruNBEhVSDcXfXTh9tVravBqeIuXgZIFk9cylR2eDwAAAIB4roDQ\n"
"Bfgf8AoSAJAb7y8OVvxt5cT7iqaRMQX2XgtW09Nu9RbUIVS7n2mw3iqZG0xnG3iv\n"
"1oL9gwNXMLlf+gLmsqU3788jaEZ9IhZ8VdgHAoHm6UWM7b2uADmhirI6dRZUVO+/\n"
"iMGUvDxa66OI4hDV055pbwQhtxupUatThyDzIgAAAeAtGFEW6JZTeSumizZJI4T2\n"
"Kha05Ze3juTeW+BMjqTcf77yAL2jvsljogCtu4+5CWWO4g+cr80vyVytji6IYTNM\n"
"MPn1qe6dHXnfmgtiegHXxrjr5v5/i1cvD32Bxffy+yjR9kbV9GJYF+K5pfYVpQBa\n"
"XVmq6AJUPd/yxKw6jRGZJi8GTcrKbCZAL+VYSPwc0veCrmGPjeeMCgYcEXPvhSui\n"
"P0JnG1Ap12FeK+61rIbZBAr7qbTGJi5Z5HlDlgon2tmMZOkIuL1Oytgut4MpmYjP\n"
"ph+qrzgwfSwOsjVIuHlb1L0phWRlgbT8lmysEE7McGKWiCOabxgl3NF9lClhDBb9\n"
"nzupkK1cg/4p17USYMOdeNhTmJ0DkQT+8UenfBOmzV7kamLlEYXJdDZBN//dZ8UR\n"
"KEzAzpaAVIyJQ+wvCUIh/VO8sJP+3q4XQUkv0QcIRlc0+r9qbW2Tqv3vajFcFtK6\n"
"nrTmIJVL0pG+z/93Ncpy5susD+JvhJ4yfl7Jet3jy4fWwm3qkLl0WsobJ7Om+GyH\n"
"DzHH9RgDk3XuUHS/fz+kTwmtyIH/Rq1jIt+s+T8iA9CzKSX6sBu2yfMo1w2/LbCx\n"
"Xy1rHS42TePw28m1cQuUfjqdOC3IBgQ1m3x2f1on7hk=\n"
"-----END OPENSSH PRIVATE KEY-----\n";
static const char torture_dsa_private_openssh_testkey[] =
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsQAAAAdz\n"
"c2gtZHNzAAAAgQCUyvVPEkn3UnZDjzCzSzSHpTltzr0Ec+1mz/JACjHMBJ9C/W/P\n"
"wvH3yjkfoFhhREvoY7IPnwAu5bcxw8TkISq7YROQ409PqwwPvy0N3GUp/+kKS268\n"
"BIJ+VKN513XRf7eL1e4aHUJ+al9x1JxTmc6T0GBq1lyu+CTUUyh25aNDFwAAABUA\n"
"rziPbQaZT7N7CNDCwhe5VvoL88cAAACAXhuIVsJxUQJ5nWQRLf7o3XEGQ+EcVmHO\n"
"zMB1xCsHjYnpEhhco+r/HDZSD31kzDeAZUycz31WqGL8yXr+OZRLqEsGC7dwEAzP\n"
"iXDul0zHcl0yiKPrRrLgNJHeKcT6JflBngK7jQRIVUg3F3104fbVa2rwaniLl4GS\n"
"BZPXMpUdng8AAACAeK6A0AX4H/AKEgCQG+8vDlb8beXE+4qmkTEF9l4LVtPTbvUW\n"
"1CFUu59psN4qmRtMZxt4r9aC/YMDVzC5X/oC5rKlN+/PI2hGfSIWfFXYBwKB5ulF\n"
"jO29rgA5oYqyOnUWVFTvv4jBlLw8WuujiOIQ1dOeaW8EIbcbqVGrU4cg8yIAAAHY\n"
"tbI937WyPd8AAAAHc3NoLWRzcwAAAIEAlMr1TxJJ91J2Q48ws0s0h6U5bc69BHPt\n"
"Zs/yQAoxzASfQv1vz8Lx98o5H6BYYURL6GOyD58ALuW3McPE5CEqu2ETkONPT6sM\n"
"D78tDdxlKf/pCktuvASCflSjedd10X+3i9XuGh1CfmpfcdScU5nOk9BgatZcrvgk\n"
"1FModuWjQxcAAAAVAK84j20GmU+zewjQwsIXuVb6C/PHAAAAgF4biFbCcVECeZ1k\n"
"ES3+6N1xBkPhHFZhzszAdcQrB42J6RIYXKPq/xw2Ug99ZMw3gGVMnM99Vqhi/Ml6\n"
"/jmUS6hLBgu3cBAMz4lw7pdMx3JdMoij60ay4DSR3inE+iX5QZ4Cu40ESFVINxd9\n"
"dOH21Wtq8Gp4i5eBkgWT1zKVHZ4PAAAAgHiugNAF+B/wChIAkBvvLw5W/G3lxPuK\n"
"ppExBfZeC1bT0271FtQhVLufabDeKpkbTGcbeK/Wgv2DA1cwuV/6AuaypTfvzyNo\n"
"Rn0iFnxV2AcCgebpRYztva4AOaGKsjp1FlRU77+IwZS8PFrro4jiENXTnmlvBCG3\n"
"G6lRq1OHIPMiAAAAFQCNR3fP4j87IO2086Db40C/jaMosgAAAAABAg==\n"
"-----END OPENSSH PRIVATE KEY-----\n";
static const char torture_dsa_public_testkey[] =
"ssh-dss AAAAB3NzaC1kc3MAAACBAJTK9U8SSfdSdkOPMLNLNIelOW3OvQRz7WbP8k"
"AKMcwEn0L9b8/C8ffKOR+gWGFES+hjsg+fAC7ltzHDxOQhKrthE5DjT0+rDA+/LQ3c"
@@ -222,6 +335,29 @@ static const char torture_ecdsa256_private_testkey_passphrase[] =
"8VZn2VJDaitLy8ARqA/lMGQfqHSa3EOqti9FzWG/P6s=\n"
"-----END EC PRIVATE KEY-----\n";
static const char torture_ecdsa256_private_openssh_testkey[] =
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNl\n"
"Y2RzYS1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTH7253zxDkZa0t37Iy\n"
"1hpqkLzmD7ZkuntW0UcDQRs0eoFRDGiH4iTz0yWvsBTFwU936QKj40TrKr+Y1Bwv\n"
"sTqJAAAAmOuDchHrg3IRAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAy\n"
"NTYAAABBBMfvbnfPEORlrS3fsjLWGmqQvOYPtmS6e1bRRwNBGzR6gVEMaIfiJPPT\n"
"Ja+wFMXBT3fpAqPjROsqv5jUHC+xOokAAAAgEIN55hgC1fcSew/Stq3BWk1NoD/g\n"
"rU3pW8cyJRmVV2EAAAAA\n"
"-----END OPENSSH PRIVATE KEY-----\n";
static const char torture_ecdsa256_private_openssh_testkey_pasphrase[] =
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
"b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABA+\n"
"O0w3yPZF2q0FjVBhQjn2AAAAEAAAAAEAAABoAAAAE2VjZHNhLXNoYTItbmlzdHAy\n"
"NTYAAAAIbmlzdHAyNTYAAABBBMfvbnfPEORlrS3fsjLWGmqQvOYPtmS6e1bRRwNB\n"
"GzR6gVEMaIfiJPPTJa+wFMXBT3fpAqPjROsqv5jUHC+xOokAAACghvb4EX8M06UB\n"
"zigxOn9bg5cZkZ2yWY8jzxtOWH4YJXsuhON/jePDJuI2ro5u4iKFD1u2JLfcshdh\n"
"vKZyjixU9KdewykQQt/wFkrCfNUyCH8jFiQsAqhBfopRFyDJV9pmcUBL/3fJqwut\n"
"ZeBSfA7tXORp3xrwFI1tXiiUCM+/nhxiCsFaCJXeiM3tN+kFtwQ8kamINqwaC8Vj\n"
"lFLKHDfwJQ==\n"
"-----END OPENSSH PRIVATE KEY-----\n";
static const char torture_ecdsa256_public_testkey[] =
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNT"
"YAAABBBMfvbnfPEORlrS3fsjLWGmqQvOYPtmS6e1bRRwNBGzR6gVEMaIfiJPPTJa+w"
@@ -245,6 +381,31 @@ static const char torture_ecdsa384_private_testkey_passphrase[] =
"8VZn2VJDaitLy8ARqA/lMGQfqHSa3EOqti9FzWG/P6s=\n"
"-----END EC PRIVATE KEY-----\n";
static const char torture_ecdsa384_private_openssh_testkey[] =
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAiAAAABNl\n"
"Y2RzYS1zaGEyLW5pc3RwMzg0AAAACG5pc3RwMzg0AAAAYQRXc4BN6BrVo1QMi3+i\n"
"/B85Lu7SMuzBi+1PbJti8xz+Szgq64gaBGOK9o+WOdLAd/w7p7DJLdztJ0bYoyT4\n"
"V3B3ZqR9RyGq6mYCjkXlc5YbYHjueBbp0oeNXqsXHNAWQZoAAADIITfDfiE3w34A\n"
"AAATZWNkc2Etc2hhMi1uaXN0cDM4NAAAAAhuaXN0cDM4NAAAAGEEV3OATega1aNU\n"
"DIt/ovwfOS7u0jLswYvtT2ybYvMc/ks4KuuIGgRjivaPljnSwHf8O6ewyS3c7SdG\n"
"2KMk+Fdwd2akfUchqupmAo5F5XOWG2B47ngW6dKHjV6rFxzQFkGaAAAAMFjyMRrk\n"
"O1HLgBV5NaE8n9Mrbntt6GILe5p8SLpgDagc5GJupfnkQM3DPb0xPjSZBAAAAAA=\n"
"-----END OPENSSH PRIVATE KEY-----\n";
static const char torture_ecdsa384_private_openssh_testkey_passphrase[] =
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
"b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABB4N\n"
"dKGEoxFeg6dqiR2vTl6AAAAEAAAAAEAAACIAAAAE2VjZHNhLXNoYTItbmlzdHAzOD\n"
"QAAAAIbmlzdHAzODQAAABhBFdzgE3oGtWjVAyLf6L8Hzku7tIy7MGL7U9sm2LzHP5\n"
"LOCrriBoEY4r2j5Y50sB3/DunsMkt3O0nRtijJPhXcHdmpH1HIarqZgKOReVzlhtg\n"
"eO54FunSh41eqxcc0BZBmgAAANDOL7sWcylFf8SsjGVFvr36mpyUBpAJ/e7o4RbQg\n"
"H8FDu1IxscOfbLDoB3CV7UEIgG58nVsDamfL6rXV/tzWnPxYxi6jUHcKT1BugO/Jt\n"
"/ncelMeoAS6MAZhElaGKzU1cJMlMTV9ofmuKuAwllQULG7L8lwHs9whBK4JmWPaGL\n"
"pU3i9ZoT33/g6pcvA83vicCNqj7ggl6Vb9MeO/zGW1+oV2HC3WiLTqBsYxEJu4YCM\n"
"ewfx9pWeWaCllNy/F1rCBu3cxqzcge9hqIlNtpT7Dq3k\n"
"-----END OPENSSH PRIVATE KEY-----\n";
static const char torture_ecdsa384_public_testkey[] =
"ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzOD"
"QAAABhBFdzgE3oGtWjVAyLf6L8Hzku7tIy7MGL7U9sm2LzHP5LOCrriBoEY4r2j5Y5"
@@ -272,6 +433,36 @@ static const char torture_ecdsa521_private_testkey_passphrase[] =
"uRzL95L05ctOBGYNYqpPNIX3UdQU07kzwNC+yaHOb2s=\n"
"-----END EC PRIVATE KEY-----\n";
static const char torture_ecdsa521_private_openssh_testkey[] =
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAArAAAABNl\n"
"Y2RzYS1zaGEyLW5pc3RwNTIxAAAACG5pc3RwNTIxAAAAhQQBzoPvbx1tpCQedI+3\n"
"O1pHAnDrcIGXXlzKQHhJde7BZ0060/MGKNRQsxNO8FdutryAvgBN311Ce7CfwpBS\n"
"HZP/P4EBGNY8qFwdwbHntelcISRrDMxhodRSdF14USY1GxtfKmx/SYkoBNTeHyDN\n"
"MyRuvHwMlMUcQiNcFKGzjgexJhWXdfIAAAEAt6sYz7erGM8AAAATZWNkc2Etc2hh\n"
"Mi1uaXN0cDUyMQAAAAhuaXN0cDUyMQAAAIUEAc6D728dbaQkHnSPtztaRwJw63CB\n"
"l15cykB4SXXuwWdNOtPzBijUULMTTvBXbra8gL4ATd9dQnuwn8KQUh2T/z+BARjW\n"
"PKhcHcGx57XpXCEkawzMYaHUUnRdeFEmNRsbXypsf0mJKATU3h8gzTMkbrx8DJTF\n"
"HEIjXBShs44HsSYVl3XyAAAAQgC83nSJ2SLoiBvEku1JteQKWx/Xt6THksgC7rrI\n"
"aTUmNzk+60f0sCCmGll0dgrZLmeIw+TtnG1E20VZflCKq+IdkQAAAAABAg==\n"
"-----END OPENSSH PRIVATE KEY-----\n";
static const char torture_ecdsa521_private_openssh_testkey_passphrase[] =
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
"b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABAj\n"
"9WBFa/piJcPFEE4CGZTKAAAAEAAAAAEAAACsAAAAE2VjZHNhLXNoYTItbmlzdHA1\n"
"MjEAAAAIbmlzdHA1MjEAAACFBAHOg+9vHW2kJB50j7c7WkcCcOtwgZdeXMpAeEl1\n"
"7sFnTTrT8wYo1FCzE07wV262vIC+AE3fXUJ7sJ/CkFIdk/8/gQEY1jyoXB3Bsee1\n"
"6VwhJGsMzGGh1FJ0XXhRJjUbG18qbH9JiSgE1N4fIM0zJG68fAyUxRxCI1wUobOO\n"
"B7EmFZd18gAAAQDLjaKp+DLEHFb98f5WnVFg6LgDN847sfeuPZVfVjeSAiIv016O\n"
"ld7DXb137B2xYVsuce6sHbypr10dJOvgMTLdzTl+crYNJL+8UufJP0rOIFaDenzQ\n"
"RW8wydwiQxwt1ZqtD8ASqFmadxngufJKZzPLGfjCbCz3uATKa2sXN66nRXRZJbVA\n"
"IlNYDY8ivAStNhfItUMqyM6PkYlKJECtJw7w7TYKpvts7t72JmtgqVjS45JI/YZ+\n"
"kitIG0YmG8rzL9d1vBB5m+MH/fnFz2uJqbQYCH9Ctc8HZodAVoTNDzXHU2mYF9PE\n"
"Z6+gi3jd+kOyUk3NifHcre9K6ie7LL33JayM\n"
"-----END OPENSSH PRIVATE KEY-----\n";
static const char torture_ecdsa521_public_testkey[] =
"ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1Mj"
"EAAACFBAHOg+9vHW2kJB50j7c7WkcCcOtwgZdeXMpAeEl17sFnTTrT8wYo1FCzE07w"
@@ -307,54 +498,93 @@ static const char torture_ed25519_public_testkey[] =
static const char *torture_get_testkey_internal(enum ssh_keytypes_e type,
int bits,
int with_passphrase,
int pubkey)
bool with_passphrase,
int pubkey,
int format)
{
switch (type) {
case SSH_KEYTYPE_DSS:
if (pubkey) {
return torture_dsa_public_testkey;
} else if (with_passphrase) {
if (format == 1) {
return torture_dsa_private_openssh_testkey_passphrase;
}
return torture_dsa_private_testkey_passphrase;
}
if (format == 1) {
return torture_dsa_private_openssh_testkey;
}
return torture_dsa_private_testkey;
case SSH_KEYTYPE_RSA:
if (pubkey) {
return torture_rsa_public_testkey;
} else if (with_passphrase) {
if (format == 1) {
return torture_rsa_private_openssh_testkey_passphrase;
}
return torture_rsa_private_testkey_passphrase;
}
if (format == 1) {
return torture_rsa_private_openssh_testkey;
}
return torture_rsa_private_testkey;
case SSH_KEYTYPE_ECDSA:
if (bits == 521) {
if (pubkey) {
return torture_ecdsa521_public_testkey;
} else if (with_passphrase) {
if (format == 1) {
return torture_ecdsa521_private_openssh_testkey_passphrase;
}
return torture_ecdsa521_private_testkey_passphrase;
}
if (format == 1) {
return torture_ecdsa521_private_openssh_testkey;
}
return torture_ecdsa521_private_testkey;
} else if (bits == 384) {
if (pubkey) {
return torture_ecdsa384_public_testkey;
} else if (with_passphrase){
if (format == 1) {
return torture_ecdsa384_private_openssh_testkey_passphrase;
}
return torture_ecdsa384_private_testkey_passphrase;
}
if (format == 1) {
return torture_ecdsa384_private_openssh_testkey;
}
return torture_ecdsa384_private_testkey;
}
if (pubkey) {
return torture_ecdsa256_public_testkey;
} else if (with_passphrase){
if (format == 1) {
return torture_ecdsa256_private_openssh_testkey_pasphrase;
}
return torture_ecdsa256_private_testkey_passphrase;
}
if (format == 1) {
return torture_ecdsa256_private_openssh_testkey;
}
return torture_ecdsa256_private_testkey;
case SSH_KEYTYPE_ED25519:
if (pubkey) {
return torture_ed25519_public_testkey;
} else if (with_passphrase) {
return torture_ed25519_private_testkey_passphrase;
if (format == 1) {
return torture_ed25519_private_testkey_passphrase;
}
/* ed25519 keys are not available in legacy PEM format */
return NULL;
}
return torture_ed25519_private_testkey;
if (format == 1) {
return torture_ed25519_private_testkey;
}
/* ed25519 keys are not available in legacy PEM format */
return NULL;
case SSH_KEYTYPE_DSS_CERT01:
return torture_dsa_testkey_cert;
case SSH_KEYTYPE_RSA_CERT01:
@@ -367,16 +597,25 @@ static const char *torture_get_testkey_internal(enum ssh_keytypes_e type,
return NULL;
}
/* Return the encrypted private key in a new OpenSSH format */
const char *torture_get_openssh_testkey(enum ssh_keytypes_e type,
int ecda_bits,
bool with_passphrase)
{
return torture_get_testkey_internal(type, ecda_bits, with_passphrase, 0, 1);
}
/* Return the private key in the legacy PEM format */
const char *torture_get_testkey(enum ssh_keytypes_e type,
int ecda_bits,
int with_passphrase)
bool with_passphrase)
{
return torture_get_testkey_internal(type, ecda_bits, with_passphrase, 0);
return torture_get_testkey_internal(type, ecda_bits, with_passphrase, 0, 0);
}
const char *torture_get_testkey_pub(enum ssh_keytypes_e type, int ecda_bits)
{
return torture_get_testkey_internal(type, ecda_bits, 0, 1);
return torture_get_testkey_internal(type, ecda_bits, 0, 1, 0);
}
const char *torture_get_testkey_passphrase(void)

View File

@@ -24,11 +24,19 @@
#ifndef _TORTURE_KEY_H
#define _TORTURE_KEY_H
#include <stdbool.h>
#define TORTURE_TESTKEY_PASSWORD "libssh-rocks"
/* Return the encrypted private key in a new OpenSSH format */
const char *torture_get_openssh_testkey(enum ssh_keytypes_e type,
int ecdsa_bits,
bool with_passphrase);
/* Return the private key in the legacy PEM format */
const char *torture_get_testkey(enum ssh_keytypes_e type,
int ecdsa_bits,
int with_passphrase);
bool with_passphrase);
const char *torture_get_testkey_passphrase(void);
const char *torture_get_testkey_pub(enum ssh_keytypes_e type, int ecdsa_bits);

View File

@@ -2,95 +2,95 @@ project(unittests C)
include_directories(${OPENSSL_INCLUDE_DIR})
add_cmocka_test(torture_buffer torture_buffer.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_buffer torture_buffer.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_buffer PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
add_cmocka_test(torture_callbacks torture_callbacks.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_callbacks torture_callbacks.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_callbacks PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
add_cmocka_test(torture_crypto torture_crypto.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_crypto torture_crypto.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_crypto PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
add_cmocka_test(torture_init torture_init.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_init torture_init.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_init PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
add_cmocka_test(torture_list torture_list.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_list torture_list.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_list PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
add_cmocka_test(torture_misc torture_misc.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_misc torture_misc.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_misc PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
add_cmocka_test(torture_config torture_config.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_config torture_config.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_config PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
add_cmocka_test(torture_options torture_options.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_options torture_options.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_options PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
add_cmocka_test(torture_isipaddr torture_isipaddr.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_isipaddr torture_isipaddr.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_isipaddr PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
add_cmocka_test(torture_knownhosts_parsing torture_knownhosts_parsing.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_knownhosts_parsing torture_knownhosts_parsing.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_knownhosts_parsing PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
add_cmocka_test(torture_hashes torture_hashes.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_hashes torture_hashes.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_hashes PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
if (CMAKE_USE_PTHREADS_INIT)
add_cmocka_test(torture_rand torture_rand.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_rand torture_rand.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_rand PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(torture_rand Threads::Threads)
add_cmocka_test(torture_threads_init torture_threads_init.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_threads_init torture_threads_init.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_threads_init PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(torture_threads_init Threads::Threads)
add_cmocka_test(torture_threads_buffer torture_threads_buffer.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_threads_buffer torture_threads_buffer.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_threads_buffer PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(torture_threads_buffer Threads::Threads)
add_cmocka_test(torture_threads_crypto torture_threads_crypto.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_threads_crypto torture_threads_crypto.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_threads_crypto PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(torture_threads_crypto Threads::Threads)
endif ()
if (UNIX AND NOT WIN32)
# this uses a socketpair
add_cmocka_test(torture_packet torture_packet.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_packet torture_packet.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_packet PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
# requires ssh-keygen
add_cmocka_test(torture_keyfiles torture_keyfiles.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_keyfiles torture_keyfiles.c ${TEST_TARGET_LIBRARIES})
add_cmocka_test(torture_pki torture_pki.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_pki torture_pki.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_pki PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
add_cmocka_test(torture_pki_rsa torture_pki_rsa.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_pki_rsa torture_pki_rsa.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_pki_rsa PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
add_cmocka_test(torture_pki_ed25519 torture_pki_ed25519.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_pki_ed25519 torture_pki_ed25519.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_pki_ed25519 PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
if (HAVE_DSA)
add_cmocka_test(torture_pki_dsa torture_pki_dsa.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_pki_dsa torture_pki_dsa.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_pki_dsa PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
endif()
if (HAVE_ECC)
add_cmocka_test(torture_pki_ecdsa torture_pki_ecdsa.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_pki_ecdsa torture_pki_ecdsa.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_pki_ecdsa PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
endif()
# requires /dev/null
add_cmocka_test(torture_channel torture_channel.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_channel torture_channel.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_channel PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
# requires pthread
if (CMAKE_USE_PTHREADS_INIT)
add_cmocka_test(torture_threads_pki_rsa torture_threads_pki_rsa.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_threads_pki_rsa torture_threads_pki_rsa.c ${TEST_TARGET_LIBRARIES})
target_compile_options(torture_threads_pki_rsa PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(torture_threads_pki_rsa Threads::Threads)
# Not working correctly
#if (WITH_SERVER)
# add_cmocka_test(torture_server_x11 torture_server_x11.c ${TORTURE_LIBRARY})
# add_cmocka_test(torture_server_x11 torture_server_x11.c ${TEST_TARGET_LIBRARIES})
#endif (WITH_SERVER)
endif ()
endif (UNIX AND NOT WIN32)

View File

@@ -17,13 +17,15 @@ extern LIBSSH_THREAD int ssh_log_level;
#define LIBSSH_TESTCONFIG7 "libssh_testconfig7.tmp"
#define LIBSSH_TESTCONFIG8 "libssh_testconfig8.tmp"
#define LIBSSH_TESTCONFIG9 "libssh_testconfig9.tmp"
#define LIBSSH_TESTCONFIG10 "libssh_testconfig10.tmp"
#define LIBSSH_TESTCONFIGGLOB "libssh_testc*[36].tmp"
#define USERNAME "testuser"
#define PROXYCMD "ssh -q -W %h:%p gateway.example.com"
#define ID_FILE "/etc/xxx"
#define KEXALGORITHMS "ecdh-sha2-nistp521,diffie-hellman-group14-sha1"
#define KEXALGORITHMS "ecdh-sha2-nistp521,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha1"
#define HOSTKEYALGORITHMS "ssh-ed25519,ecdsa-sha2-nistp521,ssh-rsa"
#define PUBKEYACCEPTEDTYPES "rsa-sha2-512,ssh-rsa,ecdsa-sha2-nistp521"
#define MACS "hmac-sha1,hmac-sha2-256"
#define USER_KNOWN_HOSTS "%d/my_known_hosts"
#define GLOBAL_KNOWN_HOSTS "/etc/ssh/my_ssh_known_hosts"
@@ -32,6 +34,7 @@ extern LIBSSH_THREAD int ssh_log_level;
static int setup_config_files(void **state)
{
ssh_session session;
int verbosity;
unlink(LIBSSH_TESTCONFIG1);
unlink(LIBSSH_TESTCONFIG2);
@@ -41,6 +44,7 @@ static int setup_config_files(void **state)
unlink(LIBSSH_TESTCONFIG6);
unlink(LIBSSH_TESTCONFIG7);
unlink(LIBSSH_TESTCONFIG8);
unlink(LIBSSH_TESTCONFIG9);
torture_write_file(LIBSSH_TESTCONFIG1,
"User "USERNAME"\nInclude "LIBSSH_TESTCONFIG2"\n\n");
@@ -51,6 +55,7 @@ static int setup_config_files(void **state)
"\n\nIdentityFile "ID_FILE"\n"
"\n\nKexAlgorithms "KEXALGORITHMS"\n"
"\n\nHostKeyAlgorithms "HOSTKEYALGORITHMS"\n"
"\n\nPubkeyAcceptedTypes "PUBKEYACCEPTEDTYPES"\n"
"\n\nMACs "MACS"\n");
/* Multiple Port settings -> parsing returns early. */
@@ -102,7 +107,27 @@ static int setup_config_files(void **state)
"VisualHostkey yes\n" /* SOC_UNSUPPORTED */
"");
/* Match keyword */
torture_write_file(LIBSSH_TESTCONFIG10,
"Match host example\n"
"\tHostName example.com\n"
"Match host example1,example2\n"
"\tHostName exampleN\n"
"Match user guest\n"
"\tHostName guest.com\n"
"Match user tester host testhost\n"
"\tHostName testhost.com\n"
"Match !user tester host testhost\n"
"\tHostName nonuser-testhost.com\n"
"Match all\n"
"\tHostName all-matched.com\n"
"");
session = ssh_new();
verbosity = torture_libssh_verbosity();
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
*state = session;
return 0;
@@ -119,6 +144,7 @@ static int teardown(void **state)
unlink(LIBSSH_TESTCONFIG7);
unlink(LIBSSH_TESTCONFIG8);
unlink(LIBSSH_TESTCONFIG9);
unlink(LIBSSH_TESTCONFIG10);
ssh_free(*state);
@@ -141,18 +167,21 @@ static void torture_config_from_file(void **state) {
ret = ssh_options_get(session, SSH_OPTIONS_PROXYCOMMAND, &v);
assert_true(ret == 0);
assert_non_null(v);
assert_string_equal(v, PROXYCMD);
ssh_string_free_char(v);
ret = ssh_options_get(session, SSH_OPTIONS_IDENTITY, &v);
assert_true(ret == 0);
assert_non_null(v);
assert_string_equal(v, ID_FILE);
ssh_string_free_char(v);
ret = ssh_options_get(session, SSH_OPTIONS_USER, &v);
assert_true(ret == 0);
assert_non_null(v);
assert_string_equal(v, USERNAME);
ssh_string_free_char(v);
@@ -161,6 +190,8 @@ static void torture_config_from_file(void **state) {
assert_string_equal(session->opts.wanted_methods[SSH_HOSTKEYS], HOSTKEYALGORITHMS);
assert_string_equal(session->opts.pubkey_accepted_types, PUBKEYACCEPTEDTYPES);
assert_string_equal(session->opts.wanted_methods[SSH_MAC_C_S], MACS);
assert_string_equal(session->opts.wanted_methods[SSH_MAC_S_C], MACS);
}
@@ -210,7 +241,6 @@ static void torture_config_new(void **state)
{
ssh_session session = *state;
int ret = 0;
int verbosity = SSH_LOG_WARNING;
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG7);
assert_true(ret == 0);
@@ -222,9 +252,6 @@ static void torture_config_new(void **state)
assert_int_equal(ssh_get_log_level(), SSH_LOG_TRACE);
assert_int_equal(session->common.log_verbosity, SSH_LOG_TRACE);
/* reset to something sane */
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
}
/**
@@ -297,6 +324,61 @@ static void torture_config_unknown(void **state) {
assert_true(ret == 0);
}
/**
* @brief Verify the configuration parser accepts Match keyword with
* full OpenSSH syntax.
*/
static void torture_config_match(void **state)
{
ssh_session session = *state;
int ret = 0;
/* Without any settings we should get all-matched.com hostname */
ssh_options_set(session, SSH_OPTIONS_HOST, "unmatched");
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10);
assert_true(ret == 0);
assert_string_equal(session->opts.host, "all-matched.com");
/* Hostname example does simple hostname matching */
ssh_options_set(session, SSH_OPTIONS_HOST, "example");
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10);
assert_true(ret == 0);
assert_string_equal(session->opts.host, "example.com");
/* We can match also both hosts from a comma separated list */
ssh_options_set(session, SSH_OPTIONS_HOST, "example1");
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10);
assert_true(ret == 0);
assert_string_equal(session->opts.host, "exampleN");
ssh_options_set(session, SSH_OPTIONS_HOST, "example2");
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10);
assert_true(ret == 0);
assert_string_equal(session->opts.host, "exampleN");
/* We can match by user */
ssh_options_set(session, SSH_OPTIONS_USER, "guest");
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10);
assert_true(ret == 0);
assert_string_equal(session->opts.host, "guest.com");
/* We can combine two options on a single line to match both of them */
ssh_options_set(session, SSH_OPTIONS_USER, "tester");
ssh_options_set(session, SSH_OPTIONS_HOST, "testhost");
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10);
assert_true(ret == 0);
assert_string_equal(session->opts.host, "testhost.com");
/* We can also negate conditions */
ssh_options_set(session, SSH_OPTIONS_USER, "not-tester");
ssh_options_set(session, SSH_OPTIONS_HOST, "testhost");
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10);
assert_true(ret == 0);
assert_string_equal(session->opts.host, "nonuser-testhost.com");
}
int torture_run_tests(void) {
int rc;
struct CMUnitTest tests[] = {
@@ -318,6 +400,9 @@ int torture_run_tests(void) {
cmocka_unit_test_setup_teardown(torture_config_unknown,
setup_config_files,
teardown),
cmocka_unit_test_setup_teardown(torture_config_match,
setup_config_files,
teardown),
};

View File

@@ -57,6 +57,7 @@ static void torture_md5_hash(void **state)
assert_true(rc == 0);
hexa = ssh_get_hexa(hash, hlen);
ssh_string_free_char((char *)hash);
assert_string_equal(hexa,
"50:15:a0:9b:92:bf:33:1c:01:c5:8c:fe:18:fa:ce:78");
@@ -75,6 +76,7 @@ static void torture_sha1_hash(void **state)
assert_true(rc == 0);
sha1 = ssh_get_b64_unpadded(hash, hlen);
ssh_string_free_char((char *)hash);
assert_string_equal(sha1, "6wP+houujQmxLBiFugTcoeoODCM");
ssh_string_free_char(sha1);
@@ -92,12 +94,37 @@ static void torture_sha256_hash(void **state)
assert_true(rc == 0);
sha256 = ssh_get_b64_unpadded(hash, hlen);
ssh_string_free_char((char *)hash);
assert_string_equal(sha256, "jXstVLLe84fSDo1kEYGn6iumnPCSorhaiWxnJz8VTII");
ssh_string_free_char(sha256);
}
static void torture_sha256_fingerprint(void **state)
{
ssh_key pubkey = *state;
unsigned char *hash = NULL;
char *sha256 = NULL;
int rc = 0;
size_t hlen;
rc = ssh_get_publickey_hash(pubkey,
SSH_PUBLICKEY_HASH_SHA256,
&hash,
&hlen);
assert_true(rc == 0);
sha256 = ssh_get_fingerprint_hash(SSH_PUBLICKEY_HASH_SHA256,
hash,
hlen);
ssh_string_free_char(discard_const(hash));
assert_string_equal(sha256,
"SHA256:jXstVLLe84fSDo1kEYGn6iumnPCSorhaiWxnJz8VTII");
ssh_string_free_char(sha256);
}
int torture_run_tests(void) {
int rc;
struct CMUnitTest tests[] = {
@@ -110,6 +137,9 @@ int torture_run_tests(void) {
cmocka_unit_test_setup_teardown(torture_sha256_hash,
setup_rsa_key,
teardown),
cmocka_unit_test_setup_teardown(torture_sha256_fingerprint,
setup_rsa_key,
teardown),
};
torture_filter_tests(tests);

View File

@@ -11,10 +11,18 @@
#include "torture_key.h"
#include <libssh/session.h>
#include <libssh/misc.h>
#include <libssh/pki_priv.h>
static int setup(void **state)
{
ssh_session session = ssh_new();
ssh_session session;
int verbosity;
session = ssh_new();
verbosity = torture_libssh_verbosity();
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
*state = session;
return 0;
@@ -68,18 +76,18 @@ static void torture_options_set_key_exchange(void **state)
/* Test known kexes */
rc = ssh_options_set(session,
SSH_OPTIONS_KEY_EXCHANGE,
"curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,diffie-hellman-group14-sha1");
"curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha1");
assert_true(rc == 0);
assert_string_equal(session->opts.wanted_methods[SSH_KEX],
"curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,diffie-hellman-group14-sha1");
"curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha1");
/* Test one unknown kex */
rc = ssh_options_set(session,
SSH_OPTIONS_KEY_EXCHANGE,
"curve25519-sha256,curve25519-sha256@libssh.org,unknown-crap@example.com,diffie-hellman-group14-sha1");
"curve25519-sha256,curve25519-sha256@libssh.org,unknown-crap@example.com,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha1");
assert_true(rc == 0);
assert_string_equal(session->opts.wanted_methods[SSH_KEX],
"curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group14-sha1");
"curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha1");
/* Test all unknown kexes */
rc = ssh_options_set(session,
@@ -115,6 +123,54 @@ static void torture_options_set_hostkey(void **state) {
assert_false(rc == 0);
}
static void torture_options_set_pubkey_accepted_types(void **state) {
ssh_session session = *state;
int rc;
enum ssh_digest_e type;
/* Test known public key algorithms */
rc = ssh_options_set(session,
SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
"ssh-ed25519,ecdsa-sha2-nistp384,ssh-rsa");
assert_true(rc == 0);
assert_string_equal(session->opts.pubkey_accepted_types,
"ssh-ed25519,ecdsa-sha2-nistp384,ssh-rsa");
/* Test one unknown public key algorithms */
rc = ssh_options_set(session,
SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
"ssh-ed25519,unknown-crap@example.com,ssh-rsa");
assert_true(rc == 0);
assert_string_equal(session->opts.pubkey_accepted_types,
"ssh-ed25519,ssh-rsa");
/* Test all unknown public key algorithms */
rc = ssh_options_set(session,
SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
"unknown-crap@example.com,more-crap@example.com");
assert_false(rc == 0);
/* Test that the option affects the algorithm selection for RSA keys */
/* simulate the SHA2 extension was negotiated */
session->extensions = SSH_EXT_SIG_RSA_SHA256;
/* previous configuration did not list the SHA2 extension algoritms, so
* it should not be used */
type = ssh_key_type_to_hash(session, SSH_KEYTYPE_RSA);
assert_int_equal(type, SSH_DIGEST_SHA1);
/* now, lets allow the signature from SHA2 extension and expect
* it to be used */
rc = ssh_options_set(session,
SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
"rsa-sha2-256,ssh-rsa");
assert_true(rc == 0);
assert_string_equal(session->opts.pubkey_accepted_types,
"rsa-sha2-256,ssh-rsa");
type = ssh_key_type_to_hash(session, SSH_KEYTYPE_RSA);
assert_int_equal(type, SSH_DIGEST_SHA256);
}
static void torture_options_set_macs(void **state) {
ssh_session session = *state;
int rc;
@@ -194,8 +250,10 @@ static void torture_options_get_user(void **state) {
char* user = NULL;
int rc;
rc = ssh_options_set(session, SSH_OPTIONS_USER, "magicaltrevor");
assert_true(rc == SSH_OK);
assert_int_equal(rc, SSH_OK);
rc = ssh_options_get(session, SSH_OPTIONS_USER, &user);
assert_int_equal(rc, SSH_OK);
assert_non_null(user);
assert_string_equal(user, "magicaltrevor");
free(user);
}
@@ -273,15 +331,17 @@ static void torture_options_get_identity(void **state) {
rc = ssh_options_set(session, SSH_OPTIONS_ADD_IDENTITY, "identity1");
assert_true(rc == 0);
rc = ssh_options_get(session, SSH_OPTIONS_IDENTITY, &identity);
assert_true(rc == SSH_OK);
assert_int_equal(rc, SSH_OK);
assert_non_null(identity);
assert_string_equal(identity, "identity1");
SAFE_FREE(identity);
rc = ssh_options_set(session, SSH_OPTIONS_IDENTITY, "identity2");
assert_true(rc == 0);
assert_int_equal(rc, SSH_OK);
assert_string_equal(session->opts.identity->root->data, "identity2");
rc = ssh_options_get(session, SSH_OPTIONS_IDENTITY, &identity);
assert_true(rc == SSH_OK);
assert_int_equal(rc, SSH_OK);
assert_non_null(identity);
assert_string_equal(identity, "identity2");
free(identity);
}
@@ -310,7 +370,10 @@ static void torture_options_config_host(void **state) {
/* create a new config file */
config = fopen("test_config", "w");
assert_non_null(config);
fputs("Host testhost1\nPort 42\nHost testhost2,testhost3\nPort 43\n", config);
fputs("Host testhost1\nPort 42\n"
"Host testhost2,testhost3\nPort 43\n"
"Host testhost4 testhost5\nPort 44\n",
config);
fclose(config);
ssh_options_set(session, SSH_OPTIONS_HOST, "testhost1");
@@ -328,9 +391,146 @@ static void torture_options_config_host(void **state) {
ssh_options_parse_config(session, "test_config");
assert_int_equal(session->opts.port, 43);
ssh_options_set(session, SSH_OPTIONS_HOST, "testhost4");
ssh_options_parse_config(session, "test_config");
assert_int_equal(session->opts.port, 44);
session->opts.port = 0;
ssh_options_set(session, SSH_OPTIONS_HOST, "testhost5");
ssh_options_parse_config(session, "test_config");
assert_int_equal(session->opts.port, 44);
unlink("test_config");
}
static void torture_options_config_match(void **state)
{
ssh_session session = *state;
FILE *config = NULL;
int rv;
/* Required for options_parse_config() */
ssh_options_set(session, SSH_OPTIONS_HOST, "testhost1");
/* The Match keyword requires argument */
config = fopen("test_config", "w");
assert_non_null(config);
fputs("Match\n",
config);
fclose(config);
rv = ssh_options_parse_config(session, "test_config");
assert_ssh_return_code_equal(session, rv, SSH_ERROR);
/* The Match all keyword needs to be the only one (start) */
config = fopen("test_config", "w");
assert_non_null(config);
fputs("Match all host local\n",
config);
fclose(config);
rv = ssh_options_parse_config(session, "test_config");
assert_ssh_return_code_equal(session, rv, SSH_ERROR);
/* The Match all keyword needs to be the only one (end) */
config = fopen("test_config", "w");
assert_non_null(config);
fputs("Match host local all\n",
config);
fclose(config);
rv = ssh_options_parse_config(session, "test_config");
assert_ssh_return_code_equal(session, rv, SSH_ERROR);
/* The Match host keyword requires an argument */
config = fopen("test_config", "w");
assert_non_null(config);
fputs("Match host\n",
config);
fclose(config);
rv = ssh_options_parse_config(session, "test_config");
assert_ssh_return_code_equal(session, rv, SSH_ERROR);
/* The Match user keyword requires an argument */
config = fopen("test_config", "w");
assert_non_null(config);
fputs("Match user\n",
config);
fclose(config);
rv = ssh_options_parse_config(session, "test_config");
assert_ssh_return_code_equal(session, rv, SSH_ERROR);
/* The Match canonical keyword is ignored */
config = fopen("test_config", "w");
assert_non_null(config);
fputs("Match canonical\n"
"\tPort 33\n"
"Match all\n"
"\tPort 34\n",
config);
fclose(config);
rv = ssh_options_parse_config(session, "test_config");
assert_ssh_return_code_equal(session, rv, SSH_OK);
assert_int_equal(session->opts.port, 34);
session->opts.port = 0;
/* The Match originalhost keyword is ignored */
config = fopen("test_config", "w");
assert_non_null(config);
fputs("Match originalhost origin\n"
"\tPort 33\n"
"Match all\n"
"\tPort 34\n",
config);
fclose(config);
rv = ssh_options_parse_config(session, "test_config");
assert_ssh_return_code(session, rv);
assert_int_equal(session->opts.port, 34);
session->opts.port = 0;
/* The Match localuser keyword is ignored */
config = fopen("test_config", "w");
assert_non_null(config);
fputs("Match originalhost origin\n"
"\tPort 33\n"
"Match all\n"
"\tPort 34\n",
config);
fclose(config);
rv = ssh_options_parse_config(session, "test_config");
assert_ssh_return_code(session, rv);
assert_int_equal(session->opts.port, 34);
session->opts.port = 0;
/* The Match exec keyword is ignored */
config = fopen("test_config", "w");
assert_non_null(config);
fputs("Match exec /bin/true\n"
"\tPort 33\n"
"Match all\n"
"\tPort 34\n",
config);
fclose(config);
rv = ssh_options_parse_config(session, "test_config");
assert_ssh_return_code(session, rv);
assert_int_equal(session->opts.port, 34);
session->opts.port = 0;
unlink("test_config");
}
#ifdef WITH_SERVER
/* sshbind options */
@@ -366,19 +566,26 @@ static void torture_bind_options_import_key(void **state)
base64_key = torture_get_testkey(SSH_KEYTYPE_RSA, 0, 0);
rc = ssh_pki_import_privkey_base64(base64_key, NULL, NULL, NULL, &key);
assert_int_equal(rc, SSH_OK);
assert_non_null(key);
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_IMPORT_KEY, key);
assert_int_equal(rc, 0);
#ifdef HAVE_DSA
/* set dsa key */
base64_key = torture_get_testkey(SSH_KEYTYPE_DSS, 0, 0);
ssh_pki_import_privkey_base64(base64_key, NULL, NULL, NULL, &key);
rc = ssh_pki_import_privkey_base64(base64_key, NULL, NULL, NULL, &key);
assert_int_equal(rc, SSH_OK);
assert_non_null(key);
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_IMPORT_KEY, key);
assert_int_equal(rc, 0);
#endif
/* set ecdsa key */
base64_key = torture_get_testkey(SSH_KEYTYPE_ECDSA, 512, 0);
ssh_pki_import_privkey_base64(base64_key, NULL, NULL, NULL, &key);
rc = ssh_pki_import_privkey_base64(base64_key, NULL, NULL, NULL, &key);
assert_int_equal(rc, SSH_OK);
assert_non_null(key);
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_IMPORT_KEY, key);
assert_int_equal(rc, 0);
}
@@ -401,8 +608,11 @@ int torture_run_tests(void) {
cmocka_unit_test_setup_teardown(torture_options_set_ciphers, setup, teardown),
cmocka_unit_test_setup_teardown(torture_options_set_key_exchange, setup, teardown),
cmocka_unit_test_setup_teardown(torture_options_set_hostkey, setup, teardown),
cmocka_unit_test_setup_teardown(torture_options_set_pubkey_accepted_types, setup, teardown),
cmocka_unit_test_setup_teardown(torture_options_set_macs, setup, teardown),
cmocka_unit_test_setup_teardown(torture_options_config_host, setup, teardown)
cmocka_unit_test_setup_teardown(torture_options_config_host, setup, teardown),
cmocka_unit_test_setup_teardown(torture_options_config_match,
setup, teardown)
};
#ifdef WITH_SERVER

View File

@@ -28,7 +28,28 @@ static int setup_dsa_key(void **state)
torture_write_file(LIBSSH_DSA_TESTKEY,
torture_get_testkey(SSH_KEYTYPE_DSS, 0, 0));
torture_write_file(LIBSSH_DSA_TESTKEY_PASSPHRASE,
torture_get_testkey(SSH_KEYTYPE_DSS, 0, 0));
torture_get_testkey(SSH_KEYTYPE_DSS, 0, 1));
torture_write_file(LIBSSH_DSA_TESTKEY ".pub",
torture_get_testkey_pub(SSH_KEYTYPE_DSS, 0));
torture_write_file(LIBSSH_DSA_TESTKEY "-cert.pub",
torture_get_testkey_pub(SSH_KEYTYPE_DSS_CERT01, 0));
return 0;
}
static int setup_openssh_dsa_key(void **state)
{
(void) state; /* unused */
unlink(LIBSSH_DSA_TESTKEY);
unlink(LIBSSH_DSA_TESTKEY_PASSPHRASE);
unlink(LIBSSH_DSA_TESTKEY ".pub");
unlink(LIBSSH_DSA_TESTKEY "-cert.pub");
torture_write_file(LIBSSH_DSA_TESTKEY,
torture_get_openssh_testkey(SSH_KEYTYPE_DSS, 0, 0));
torture_write_file(LIBSSH_DSA_TESTKEY_PASSPHRASE,
torture_get_openssh_testkey(SSH_KEYTYPE_DSS, 0, 1));
torture_write_file(LIBSSH_DSA_TESTKEY ".pub",
torture_get_testkey_pub(SSH_KEYTYPE_DSS, 0));
torture_write_file(LIBSSH_DSA_TESTKEY "-cert.pub",
@@ -49,6 +70,36 @@ static int teardown_dsa_key(void **state)
return 0;
}
static void torture_pki_dsa_import_pubkey_file(void **state)
{
ssh_key pubkey = NULL;
int rc;
(void)state;
/* The key doesn't have the hostname as comment after the key */
rc = ssh_pki_import_pubkey_file(LIBSSH_DSA_TESTKEY ".pub", &pubkey);
assert_return_code(rc, errno);
assert_non_null(pubkey);
ssh_key_free(pubkey);
}
static void torture_pki_dsa_import_pubkey_from_openssh_privkey(void **state)
{
ssh_key pubkey = NULL;
int rc;
(void)state;
/* The key doesn't have the hostname as comment after the key */
rc = ssh_pki_import_pubkey_file(LIBSSH_DSA_TESTKEY_PASSPHRASE, &pubkey);
assert_return_code(rc, errno);
assert_non_null(pubkey);
ssh_key_free(pubkey);
}
static void torture_pki_dsa_import_privkey_base64(void **state)
{
int rc;
@@ -98,6 +149,7 @@ static void torture_pki_dsa_write_privkey(void **state)
NULL,
&privkey);
assert_true(rc == 0);
assert_non_null(privkey);
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
assert_true(rc == 0);
@@ -112,6 +164,7 @@ static void torture_pki_dsa_write_privkey(void **state)
NULL,
&origkey);
assert_true(rc == 0);
assert_non_null(origkey);
unlink(LIBSSH_DSA_TESTKEY_PASSPHRASE);
rc = ssh_pki_export_privkey_file(origkey,
@@ -205,6 +258,9 @@ static void torture_pki_dsa_import_privkey_base64_passphrase(void **state)
&key);
assert_true(rc == -1);
/* This free in unnecessary, but the static analyser does not know */
ssh_key_free(key);
#ifndef HAVE_LIBCRYPTO
/* test if it returns -1 if passphrase is NULL */
/* libcrypto asks for a passphrase, so skip this test */
@@ -214,9 +270,85 @@ static void torture_pki_dsa_import_privkey_base64_passphrase(void **state)
NULL,
&key);
assert_true(rc == -1);
/* This free in unnecessary, but the static analyser does not know */
ssh_key_free(key);
#endif /* HAVE_LIBCRYPTO */
}
static void
torture_pki_dsa_import_openssh_privkey_base64_passphrase(void **state)
{
int rc;
ssh_key key = NULL;
const char *passphrase = torture_get_testkey_passphrase();
const char *keystring = NULL;
(void) state; /* unused */
keystring = torture_get_openssh_testkey(SSH_KEYTYPE_DSS, 0, 1);
assert_true(keystring != NULL);
rc = ssh_pki_import_privkey_base64(keystring,
passphrase,
NULL,
NULL,
&key);
assert_return_code(rc, errno);
rc = ssh_key_is_private(key);
assert_true(rc == 1);
ssh_key_free(key);
key = NULL;
/* test if it returns -1 if passphrase is wrong */
rc = ssh_pki_import_privkey_base64(keystring,
"wrong passphrase !!",
NULL,
NULL,
&key);
assert_true(rc == -1);
/* test if it returns -1 if passphrase is NULL */
rc = ssh_pki_import_privkey_base64(keystring,
NULL,
NULL,
NULL,
&key);
assert_true(rc == -1);
rc = ssh_pki_import_privkey_base64(keystring,
passphrase,
NULL,
NULL,
&key);
assert_return_code(rc, errno);
rc = ssh_key_is_private(key);
assert_true(rc == 1);
ssh_key_free(key);
key = NULL;
/* test if it returns -1 if passphrase is wrong */
rc = ssh_pki_import_privkey_base64(keystring,
"wrong passphrase !!",
NULL,
NULL,
&key);
assert_true(rc == -1);
/* test if it returns -1 if passphrase is NULL */
rc = ssh_pki_import_privkey_base64(keystring,
NULL,
NULL,
NULL,
&key);
assert_true(rc == -1);
}
static void torture_pki_dsa_publickey_from_privatekey(void **state)
{
int rc;
@@ -367,6 +499,7 @@ static void torture_pki_dsa_duplicate_key(void **state)
rc = ssh_pki_import_pubkey_file(LIBSSH_DSA_TESTKEY ".pub", &pubkey);
assert_true(rc == 0);
assert_non_null(pubkey);
rc = ssh_pki_export_pubkey_base64(pubkey, &b64_key);
assert_true(rc == 0);
@@ -378,15 +511,19 @@ static void torture_pki_dsa_duplicate_key(void **state)
NULL,
&privkey);
assert_true(rc == 0);
assert_non_null(privkey);
privkey_dup = ssh_key_dup(privkey);
assert_true(privkey_dup != NULL);
assert_non_null(privkey_dup);
rc = ssh_pki_export_privkey_to_pubkey(privkey, &pubkey);
assert_true(rc == SSH_OK);
assert_non_null(pubkey);
rc = ssh_pki_export_pubkey_base64(pubkey, &b64_key_gen);
assert_true(rc == 0);
assert_non_null(b64_key_gen);
assert_string_equal(b64_key, b64_key_gen);
@@ -448,9 +585,18 @@ int torture_run_tests(void)
{
int rc;
struct CMUnitTest tests[] = {
cmocka_unit_test_setup_teardown(torture_pki_dsa_import_pubkey_file,
setup_dsa_key,
teardown_dsa_key),
cmocka_unit_test_setup_teardown(torture_pki_dsa_import_pubkey_from_openssh_privkey,
setup_openssh_dsa_key,
teardown_dsa_key),
cmocka_unit_test_setup_teardown(torture_pki_dsa_import_privkey_base64,
setup_dsa_key,
teardown_dsa_key),
cmocka_unit_test_setup_teardown(torture_pki_dsa_import_privkey_base64,
setup_openssh_dsa_key,
teardown_dsa_key),
cmocka_unit_test_setup_teardown(torture_pki_dsa_publickey_from_privatekey,
setup_dsa_key,
teardown_dsa_key),
@@ -463,6 +609,7 @@ int torture_run_tests(void)
teardown_dsa_key),
#endif
cmocka_unit_test(torture_pki_dsa_import_privkey_base64_passphrase),
cmocka_unit_test(torture_pki_dsa_import_openssh_privkey_base64_passphrase),
/* public key */
cmocka_unit_test_setup_teardown(torture_pki_dsa_publickey_base64,

View File

@@ -26,7 +26,30 @@ static int setup_ecdsa_key(void **state, int ecdsa_bits)
torture_write_file(LIBSSH_ECDSA_TESTKEY,
torture_get_testkey(SSH_KEYTYPE_ECDSA, ecdsa_bits, 0));
torture_write_file(LIBSSH_ECDSA_TESTKEY_PASSPHRASE,
torture_get_testkey(SSH_KEYTYPE_ECDSA, ecdsa_bits, 0));
torture_get_testkey(SSH_KEYTYPE_ECDSA, ecdsa_bits, 1));
torture_write_file(LIBSSH_ECDSA_TESTKEY ".pub",
torture_get_testkey_pub(SSH_KEYTYPE_ECDSA, ecdsa_bits));
return 0;
}
static int setup_openssh_ecdsa_key(void **state, int ecdsa_bits)
{
const char *keystring = NULL;
(void) state; /* unused */
unlink(LIBSSH_ECDSA_TESTKEY);
unlink(LIBSSH_ECDSA_TESTKEY_PASSPHRASE);
unlink(LIBSSH_ECDSA_TESTKEY ".pub");
keystring = torture_get_openssh_testkey(SSH_KEYTYPE_ECDSA, ecdsa_bits, 0);
torture_write_file(LIBSSH_ECDSA_TESTKEY,
keystring);
keystring = torture_get_openssh_testkey(SSH_KEYTYPE_ECDSA, ecdsa_bits, 1);
torture_write_file(LIBSSH_ECDSA_TESTKEY_PASSPHRASE,
keystring);
torture_write_file(LIBSSH_ECDSA_TESTKEY ".pub",
torture_get_testkey_pub(SSH_KEYTYPE_ECDSA, ecdsa_bits));
@@ -54,6 +77,27 @@ static int setup_ecdsa_key_256(void **state)
return 0;
}
static int setup_openssh_ecdsa_key_521(void **state)
{
setup_openssh_ecdsa_key(state, 521);
return 0;
}
static int setup_openssh_ecdsa_key_384(void **state)
{
setup_openssh_ecdsa_key(state, 384);
return 0;
}
static int setup_openssh_ecdsa_key_256(void **state)
{
setup_openssh_ecdsa_key(state, 256);
return 0;
}
static int teardown(void **state)
{
(void) state; /* unused */
@@ -65,6 +109,36 @@ static int teardown(void **state)
return 0;
}
static void torture_pki_ecdsa_import_pubkey_file(void **state)
{
ssh_key pubkey = NULL;
int rc;
(void)state;
/* The key doesn't have the hostname as comment after the key */
rc = ssh_pki_import_pubkey_file(LIBSSH_ECDSA_TESTKEY ".pub", &pubkey);
assert_return_code(rc, errno);
assert_non_null(pubkey);
ssh_key_free(pubkey);
}
static void torture_pki_ecdsa_import_pubkey_from_openssh_privkey(void **state)
{
ssh_key pubkey = NULL;
int rc;
(void)state;
/* The key doesn't have the hostname as comment after the key */
rc = ssh_pki_import_pubkey_file(LIBSSH_ECDSA_TESTKEY_PASSPHRASE, &pubkey);
assert_return_code(rc, errno);
assert_non_null(pubkey);
ssh_key_free(pubkey);
}
static void torture_pki_ecdsa_import_privkey_base64(void **state)
{
int rc;
@@ -215,6 +289,7 @@ static void torture_pki_ecdsa_duplicate_key(void **state)
NULL,
&privkey);
assert_true(rc == 0);
assert_non_null(privkey);
privkey_dup = ssh_key_dup(privkey);
assert_non_null(privkey_dup);
@@ -371,6 +446,7 @@ static void torture_pki_ecdsa_write_privkey(void **state)
NULL,
&privkey);
assert_true(rc == 0);
assert_non_null(privkey);
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
assert_true(rc == 0);
@@ -385,6 +461,7 @@ static void torture_pki_ecdsa_write_privkey(void **state)
NULL,
&origkey);
assert_true(rc == 0);
assert_non_null(origkey);
unlink(LIBSSH_ECDSA_TESTKEY_PASSPHRASE);
rc = ssh_pki_export_privkey_file(origkey,
@@ -452,6 +529,24 @@ static void torture_pki_ecdsa_name521(void **state)
int torture_run_tests(void) {
int rc;
struct CMUnitTest tests[] = {
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_pubkey_file,
setup_ecdsa_key_256,
teardown),
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_pubkey_file,
setup_ecdsa_key_384,
teardown),
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_pubkey_file,
setup_ecdsa_key_521,
teardown),
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_pubkey_from_openssh_privkey,
setup_openssh_ecdsa_key_256,
teardown),
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_pubkey_from_openssh_privkey,
setup_openssh_ecdsa_key_384,
teardown),
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_pubkey_file,
setup_openssh_ecdsa_key_521,
teardown),
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64,
setup_ecdsa_key_256,
teardown),
@@ -461,6 +556,15 @@ int torture_run_tests(void) {
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64,
setup_ecdsa_key_521,
teardown),
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64,
setup_openssh_ecdsa_key_256,
teardown),
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64,
setup_openssh_ecdsa_key_384,
teardown),
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64,
setup_openssh_ecdsa_key_521,
teardown),
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_publickey_from_privatekey,
setup_ecdsa_key_256,
teardown),

View File

@@ -21,16 +21,18 @@ const uint8_t ref_signature[ED25519_SIG_LEN]=
static int setup_ed25519_key(void **state)
{
const char *keystring = NULL;
(void) state; /* unused */
unlink(LIBSSH_ED25519_TESTKEY);
unlink(LIBSSH_ED25519_TESTKEY_PASSPHRASE);
unlink(LIBSSH_ED25519_TESTKEY ".pub");
torture_write_file(LIBSSH_ED25519_TESTKEY,
torture_get_testkey(SSH_KEYTYPE_ED25519, 0,0));
torture_write_file(LIBSSH_ED25519_TESTKEY_PASSPHRASE,
torture_get_testkey(SSH_KEYTYPE_ED25519, 0,0));
keystring = torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0, 0);
torture_write_file(LIBSSH_ED25519_TESTKEY, keystring);
keystring = torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0, 1);
torture_write_file(LIBSSH_ED25519_TESTKEY_PASSPHRASE, keystring);
torture_write_file(LIBSSH_ED25519_TESTKEY ".pub",
torture_get_testkey_pub(SSH_KEYTYPE_ED25519,0));
@@ -48,6 +50,36 @@ static int teardown(void **state) {
return 0;
}
static void torture_pki_ed25519_import_pubkey_file(void **state)
{
ssh_key pubkey = NULL;
int rc;
(void)state;
/* The key doesn't have the hostname as comment after the key */
rc = ssh_pki_import_pubkey_file(LIBSSH_ED25519_TESTKEY ".pub", &pubkey);
assert_return_code(rc, errno);
assert_non_null(pubkey);
ssh_key_free(pubkey);
}
static void torture_pki_ed25519_import_pubkey_from_openssh_privkey(void **state)
{
ssh_key pubkey = NULL;
int rc;
(void)state;
/* The key doesn't have the hostname as comment after the key */
rc = ssh_pki_import_pubkey_file(LIBSSH_ED25519_TESTKEY_PASSPHRASE, &pubkey);
assert_return_code(rc, errno);
assert_non_null(pubkey);
ssh_key_free(pubkey);
}
static void torture_pki_ed25519_import_privkey_base64(void **state)
{
int rc;
@@ -78,16 +110,68 @@ static void torture_pki_ed25519_import_privkey_base64(void **state)
}
static void torture_pki_ed25519_import_export_privkey_base64(void **state)
{
char *b64_key = NULL;
ssh_key key = NULL;
const char *passphrase = torture_get_testkey_passphrase();
enum ssh_keytypes_e type;
int rc;
(void) state; /* unused */
rc = ssh_pki_import_privkey_base64(torture_get_openssh_testkey(SSH_KEYTYPE_ED25519,
0,
false),
passphrase,
NULL,
NULL,
&key);
assert_return_code(rc, errno);
type = ssh_key_type(key);
assert_true(type == SSH_KEYTYPE_ED25519);
rc = ssh_key_is_private(key);
assert_true(rc == 1);
rc = ssh_pki_export_privkey_base64(key,
passphrase,
NULL,
NULL,
&b64_key);
assert_return_code(rc, errno);
ssh_key_free(key);
rc = ssh_pki_import_privkey_base64(b64_key,
passphrase,
NULL,
NULL,
&key);
assert_return_code(rc, errno);
type = ssh_key_type(key);
assert_true(type == SSH_KEYTYPE_ED25519);
rc = ssh_key_is_private(key);
assert_true(rc == 1);
SSH_STRING_FREE_CHAR(b64_key);
ssh_key_free(key);
}
static void torture_pki_ed25519_publickey_from_privatekey(void **state)
{
int rc;
ssh_key key = NULL;
ssh_key pubkey = NULL;
const char *passphrase = NULL;
const char *keystring = NULL;
(void) state; /* unused */
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_ED25519, 0, 0),
keystring = torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0, 0);
rc = ssh_pki_import_privkey_base64(keystring,
passphrase,
NULL,
NULL,
@@ -229,6 +313,7 @@ static void torture_pki_ed25519_write_privkey(void **state)
NULL,
&origkey);
assert_true(rc == 0);
assert_non_null(origkey);
unlink(LIBSSH_ED25519_TESTKEY);
@@ -245,6 +330,7 @@ static void torture_pki_ed25519_write_privkey(void **state)
NULL,
&privkey);
assert_true(rc == 0);
assert_non_null(privkey);
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
assert_true(rc == 0);
@@ -273,6 +359,7 @@ static void torture_pki_ed25519_write_privkey(void **state)
NULL,
&privkey);
assert_true(rc == 0);
assert_non_null(privkey);
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
assert_true(rc == 0);
@@ -288,6 +375,7 @@ static void torture_pki_ed25519_write_privkey(void **state)
NULL,
&origkey);
assert_true(rc == 0);
assert_non_null(origkey);
unlink(LIBSSH_ED25519_TESTKEY_PASSPHRASE);
rc = ssh_pki_export_privkey_file(origkey,
@@ -311,6 +399,7 @@ static void torture_pki_ed25519_write_privkey(void **state)
NULL,
&privkey);
assert_true(rc == 0);
assert_non_null(privkey);
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
assert_true(rc == 0);
@@ -319,10 +408,12 @@ static void torture_pki_ed25519_write_privkey(void **state)
ssh_key_free(privkey);
}
static void torture_pki_ed25519_sign(void **state){
static void torture_pki_ed25519_sign(void **state)
{
ssh_key privkey = NULL;
ssh_signature sig = NULL;
ssh_string blob = NULL;
const char *keystring = NULL;
int rc;
(void)state;
@@ -330,9 +421,8 @@ static void torture_pki_ed25519_sign(void **state){
sig = ssh_signature_new();
assert_non_null(sig);
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_ED25519,
0,
0),
keystring = torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0, 0);
rc = ssh_pki_import_privkey_base64(keystring,
NULL,
NULL,
NULL,
@@ -374,7 +464,7 @@ static void torture_pki_ed25519_verify(void **state){
assert_true(rc == SSH_OK);
ssh_string_fill(blob, ref_signature, ED25519_SIG_LEN);
sig = pki_signature_from_blob(pubkey, blob, SSH_KEYTYPE_ED25519);
sig = pki_signature_from_blob(pubkey, blob, SSH_KEYTYPE_ED25519, SSH_DIGEST_AUTO);
assert_true(sig != NULL);
rc = pki_ed25519_verify(pubkey, sig, HASH, sizeof(HASH));
@@ -411,7 +501,7 @@ static void torture_pki_ed25519_verify_bad(void **state){
for (i=0; i < ED25519_SIG_LEN; ++i){
ssh_string_fill(blob, ref_signature, ED25519_SIG_LEN);
((uint8_t *)ssh_string_data(blob))[i] ^= 0xff;
sig = pki_signature_from_blob(pubkey, blob, SSH_KEYTYPE_ED25519);
sig = pki_signature_from_blob(pubkey, blob, SSH_KEYTYPE_ED25519, SSH_DIGEST_AUTO);
assert_true(sig != NULL);
rc = pki_ed25519_verify(pubkey, sig, HASH, sizeof(HASH));
@@ -429,11 +519,13 @@ static void torture_pki_ed25519_import_privkey_base64_passphrase(void **state)
int rc;
ssh_key key = NULL;
const char *passphrase = torture_get_testkey_passphrase();
const char *testkey = NULL;
(void) state; /* unused */
/* same for ED25519 */
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_ED25519, 0, 1),
testkey = torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0, 1);
rc = ssh_pki_import_privkey_base64(testkey,
passphrase,
NULL,
NULL,
@@ -447,7 +539,7 @@ static void torture_pki_ed25519_import_privkey_base64_passphrase(void **state)
key = NULL;
/* test if it returns -1 if passphrase is wrong */
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_ED25519, 0, 1),
rc = ssh_pki_import_privkey_base64(testkey,
"wrong passphrase !!",
NULL,
NULL,
@@ -461,11 +553,13 @@ static void torture_pki_ed25519_privkey_dup(void **state)
const char *passphrase = torture_get_testkey_passphrase();
ssh_key key = NULL;
ssh_key dup = NULL;
const char *testkey = NULL;
int rc;
(void) state; /* unused */
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_ED25519, 0, 1),
testkey = torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0, 1);
rc = ssh_pki_import_privkey_base64(testkey,
passphrase,
NULL,
NULL,
@@ -521,10 +615,19 @@ static void torture_pki_ed25519_pubkey_dup(void **state)
int torture_run_tests(void) {
int rc;
const struct CMUnitTest tests[] = {
struct CMUnitTest tests[] = {
cmocka_unit_test_setup_teardown(torture_pki_ed25519_import_pubkey_file,
setup_ed25519_key,
teardown),
cmocka_unit_test_setup_teardown(torture_pki_ed25519_import_pubkey_from_openssh_privkey,
setup_ed25519_key,
teardown),
cmocka_unit_test_setup_teardown(torture_pki_ed25519_import_privkey_base64,
setup_ed25519_key,
teardown),
cmocka_unit_test_setup_teardown(torture_pki_ed25519_import_export_privkey_base64,
setup_ed25519_key,
teardown),
cmocka_unit_test_setup_teardown(torture_pki_ed25519_publickey_from_privatekey,
setup_ed25519_key,
teardown),
@@ -547,6 +650,7 @@ int torture_run_tests(void) {
};
ssh_init();
torture_filter_tests(tests);
rc = cmocka_run_group_tests(tests, NULL, NULL);
ssh_finalize();
return rc;

View File

@@ -15,6 +15,9 @@
#define LIBSSH_RSA_TESTKEY_PASSPHRASE "libssh_testkey_passphrase.id_rsa"
const unsigned char RSA_HASH[] = "12345678901234567890";
const unsigned char SHA256_HASH[] = "12345678901234567890123456789012";
const unsigned char SHA512_HASH[] = "1234567890123456789012345678901234567890"
"123456789012345678901234";
static int setup_rsa_key(void **state)
{
@@ -31,6 +34,25 @@ static int setup_rsa_key(void **state)
torture_get_testkey(SSH_KEYTYPE_RSA, 0, 1));
torture_write_file(LIBSSH_RSA_TESTKEY ".pub",
torture_get_testkey_pub(SSH_KEYTYPE_RSA, 0));
torture_write_file(LIBSSH_RSA_TESTKEY "-cert.pub",
torture_get_testkey_pub(SSH_KEYTYPE_RSA_CERT01, 0));
return 0;
}
static int setup_rsa_openssh_key(void **state)
{
(void) state; /* unused */
unlink(LIBSSH_RSA_TESTKEY);
unlink(LIBSSH_RSA_TESTKEY_PASSPHRASE);
unlink(LIBSSH_RSA_TESTKEY ".pub");
unlink(LIBSSH_RSA_TESTKEY "-cert.pub");
torture_write_file(LIBSSH_RSA_TESTKEY,
torture_get_openssh_testkey(SSH_KEYTYPE_RSA, 0, 0));
torture_write_file(LIBSSH_RSA_TESTKEY_PASSPHRASE,
torture_get_openssh_testkey(SSH_KEYTYPE_RSA, 0, 1));
torture_write_file(LIBSSH_RSA_TESTKEY ".pub",
torture_get_testkey_pub(SSH_KEYTYPE_RSA, 0));
torture_write_file(LIBSSH_RSA_TESTKEY "-cert.pub",
@@ -65,6 +87,21 @@ static void torture_pki_rsa_import_pubkey_file(void **state)
ssh_key_free(pubkey);
}
static void torture_pki_rsa_import_pubkey_from_openssh_privkey(void **state)
{
ssh_key pubkey = NULL;
int rc;
(void)state;
/* The key doesn't have the hostname as comment after the key */
rc = ssh_pki_import_pubkey_file(LIBSSH_RSA_TESTKEY_PASSPHRASE, &pubkey);
assert_return_code(rc, errno);
assert_non_null(pubkey);
ssh_key_free(pubkey);
}
static void torture_pki_rsa_import_privkey_base64_NULL_key(void **state)
{
int rc;
@@ -315,6 +352,7 @@ static void torture_pki_rsa_duplicate_key(void **state)
rc = ssh_pki_import_pubkey_file(LIBSSH_RSA_TESTKEY ".pub", &pubkey);
assert_true(rc == 0);
assert_non_null(pubkey);
rc = ssh_pki_export_pubkey_base64(pubkey, &b64_key);
assert_true(rc == 0);
@@ -329,13 +367,15 @@ static void torture_pki_rsa_duplicate_key(void **state)
assert_non_null(privkey);
privkey_dup = ssh_key_dup(privkey);
assert_true(privkey_dup != NULL);
assert_non_null(privkey_dup);
rc = ssh_pki_export_privkey_to_pubkey(privkey, &pubkey);
assert_true(rc == SSH_OK);
assert_non_null(pubkey);
rc = ssh_pki_export_pubkey_base64(pubkey, &b64_key_gen);
assert_true(rc == 0);
assert_non_null(b64_key_gen);
assert_string_equal(b64_key, b64_key_gen);
@@ -393,6 +433,54 @@ static void torture_pki_rsa_generate_key(void **state)
ssh_free(session);
}
static void torture_pki_rsa_sha2(void **state)
{
int rc;
ssh_key key = NULL;
ssh_signature sign;
ssh_session session=ssh_new();
(void) state;
assert_non_null(session);
/* Setup */
rc = ssh_pki_generate(SSH_KEYTYPE_RSA, 2048, &key);
assert_true(rc == SSH_OK);
assert_true(key != NULL);
/* Sign using automatic digest */
sign = pki_do_sign_hash(key, RSA_HASH, 20, SSH_DIGEST_AUTO);
assert_true(sign != NULL);
rc = pki_signature_verify(session, sign, key, RSA_HASH, 20);
assert_ssh_return_code(session, rc);
ssh_signature_free(sign);
/* Sign using old SHA1 digest */
sign = pki_do_sign_hash(key, RSA_HASH, 20, SSH_DIGEST_SHA1);
assert_true(sign != NULL);
rc = pki_signature_verify(session, sign, key, RSA_HASH, 20);
assert_ssh_return_code(session, rc);
ssh_signature_free(sign);
/* Sign using new SHA256 digest */
sign = pki_do_sign_hash(key, SHA256_HASH, 32, SSH_DIGEST_SHA256);
assert_true(sign != NULL);
rc = pki_signature_verify(session, sign, key, SHA256_HASH, 32);
assert_ssh_return_code(session, rc);
ssh_signature_free(sign);
/* Sign using rsa-sha2-512 algorithm */
sign = pki_do_sign_hash(key, SHA512_HASH, 64, SSH_DIGEST_SHA512);
assert_true(sign != NULL);
rc = pki_signature_verify(session, sign, key, SHA512_HASH, 64);
assert_ssh_return_code(session, rc);
ssh_signature_free(sign);
/* Cleanup */
ssh_key_free(key);
ssh_free(session);
}
#ifdef HAVE_LIBCRYPTO
static void torture_pki_rsa_write_privkey(void **state)
{
@@ -408,6 +496,7 @@ static void torture_pki_rsa_write_privkey(void **state)
NULL,
&origkey);
assert_true(rc == 0);
assert_non_null(origkey);
unlink(LIBSSH_RSA_TESTKEY);
@@ -424,6 +513,7 @@ static void torture_pki_rsa_write_privkey(void **state)
NULL,
&privkey);
assert_true(rc == 0);
assert_non_null(privkey);
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
assert_true(rc == 0);
@@ -438,6 +528,7 @@ static void torture_pki_rsa_write_privkey(void **state)
NULL,
&origkey);
assert_true(rc == 0);
assert_non_null(origkey);
unlink(LIBSSH_RSA_TESTKEY_PASSPHRASE);
rc = ssh_pki_export_privkey_file(origkey,
@@ -517,12 +608,63 @@ static void torture_pki_rsa_import_privkey_base64_passphrase(void **state)
#endif
}
static void
torture_pki_rsa_import_openssh_privkey_base64_passphrase(void **state)
{
int rc;
ssh_key key = NULL;
const char *passphrase = torture_get_testkey_passphrase();
const char *keystring = NULL;
(void) state; /* unused */
keystring = torture_get_openssh_testkey(SSH_KEYTYPE_RSA, 0, 1);
assert_true(keystring != NULL);
rc = ssh_pki_import_privkey_base64(keystring,
passphrase,
NULL,
NULL,
&key);
assert_return_code(rc, errno);
rc = ssh_key_is_private(key);
assert_true(rc == 1);
ssh_key_free(key);
key = NULL;
/* test if it returns -1 if passphrase is wrong */
rc = ssh_pki_import_privkey_base64(keystring,
"wrong passphrase !!",
NULL,
NULL,
&key);
assert_true(rc == -1);
ssh_key_free(key);
key = NULL;
/* test if it returns -1 if passphrase is NULL */
/* libcrypto asks for a passphrase, so skip this test */
rc = ssh_pki_import_privkey_base64(keystring,
NULL,
NULL,
NULL,
&key);
assert_true(rc == -1);
ssh_key_free(key);
key = NULL;
}
int torture_run_tests(void) {
int rc;
struct CMUnitTest tests[] = {
cmocka_unit_test_setup_teardown(torture_pki_rsa_import_pubkey_file,
setup_rsa_key,
teardown),
cmocka_unit_test_setup_teardown(torture_pki_rsa_import_pubkey_from_openssh_privkey,
setup_rsa_openssh_key,
teardown),
cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64_NULL_key,
setup_rsa_key,
teardown),
@@ -532,10 +674,14 @@ int torture_run_tests(void) {
cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64,
setup_rsa_key,
teardown),
cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64,
setup_rsa_openssh_key,
teardown),
cmocka_unit_test_setup_teardown(torture_pki_rsa_publickey_from_privatekey,
setup_rsa_key,
teardown),
cmocka_unit_test(torture_pki_rsa_import_privkey_base64_passphrase),
cmocka_unit_test(torture_pki_rsa_import_openssh_privkey_base64_passphrase),
cmocka_unit_test_setup_teardown(torture_pki_rsa_copy_cert_to_privkey,
setup_rsa_key,
teardown),
@@ -557,6 +703,7 @@ int torture_run_tests(void) {
setup_rsa_key,
teardown),
#endif /* HAVE_LIBCRYPTO */
cmocka_unit_test(torture_pki_rsa_sha2),
};
ssh_init();

View File

@@ -589,8 +589,14 @@ int torture_run_tests(void)
cmocka_unit_test(torture_mixed),
};
/*
* If the library is statically linked, ssh_init() is not called
* automatically
*/
ssh_init();
torture_filter_tests(tests);
rc = cmocka_run_group_tests(tests, NULL, NULL);
ssh_finalize();
return rc;
}

View File

@@ -175,7 +175,13 @@ int torture_run_tests(void)
cmocka_unit_test(torture_crypto_aes256_cbc),
};
/*
* If the library is statically linked, ssh_init() is not called
* automatically
*/
ssh_init();
rc = cmocka_run_group_tests(tests, NULL, NULL);
ssh_finalize();
return rc;
}

View File

@@ -88,8 +88,14 @@ int torture_run_tests(void)
cmocka_unit_test(torture_ssh_init),
};
/*
* If the library is statically linked, ssh_init() is not called
* automatically
*/
ssh_init();
torture_filter_tests(tests);
rc = cmocka_run_group_tests(tests, NULL, NULL);
ssh_finalize();
return rc;
}

View File

@@ -274,12 +274,14 @@ static void *thread_pki_rsa_publickey_from_privatekey(void *threadid)
NULL,
&key);
assert_true(rc == 0);
assert_non_null(key);
ok = ssh_key_is_private(key);
assert_true(ok);
rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey);
assert_true(rc == SSH_OK);
assert_non_null(pubkey);
ssh_key_free(key);
ssh_key_free(pubkey);