Compare commits

...

172 Commits

Author SHA1 Message Date
Andreas Schneider
64a2d37c30 Bump version to 0.7.7
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
2018-10-29 10:52:49 +01:00
Andreas Schneider
9d5cf209df libcrypto: Fix memory leak in evp_final()
Fixes T116

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit a280747462)
2018-10-28 14:31:33 +01:00
Meng Tan
1039732154 gssapi: Set correct state after sending GSSAPI_RESPONSE (select mechanism OID)
Signed-off-by: Meng Tan <mtan@wallix.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit bce8d56705)
2018-10-26 09:04:56 +02:00
Andreas Schneider
7ad80ba1cc server: Fix compile error
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
2018-10-24 19:57:17 +02:00
Andreas Schneider
acb0e4f401 examples: Explicitly track auth state in samplesshd-kbdint
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 0ff566b6dd)
2018-10-19 14:10:02 +02:00
Andreas Schneider
3fe7510b26 messages: Check that the requested service is 'ssh-connection'
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 9c200d3ef4)
2018-10-19 14:09:58 +02:00
Meng Tan
734e3ce674 server: Set correct state after sending INFO_REQUEST (Kbd Interactive)
Signed-off-by: Meng Tan <mtan@wallix.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 4ea46eecce)
2018-10-19 14:09:53 +02:00
Andreas Schneider
e4c6d591df packet: Add missing break in ssh_packet_incoming_filter()
CID 1396239

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit fe618a35dc)
2018-10-19 14:09:47 +02:00
Andreas Schneider
f81ca61612 misc: Add strndup implementation if not provides by the OS
Fixes T112

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 247983e982)
2018-10-17 08:23:15 +02:00
Andreas Schneider
c20b360c96 Bump version to 0.7.6
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
2018-10-16 12:45:32 +02:00
Andreas Schneider
5e061962c5 cpack: Fix ignore files
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
2018-10-16 12:45:32 +02:00
Anderson Toshiyuki Sasaki
f1d57223db CVE-2018-10933: Add tests for packet filtering
Created the test torture_packet_filter.c which tests if packets are
being correctly filtered.

Fixes T101

Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
2018-10-09 11:45:59 +02:00
Anderson Toshiyuki Sasaki
b9033ad56a CVE-2018-10933: Introduced packet filtering
The packet filter checks required states for the incoming packets and
reject them if they arrived in the wrong state.

Fixes T101

Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
2018-10-09 11:45:59 +02:00
Anderson Toshiyuki Sasaki
e5ff7aa410 CVE-2018-10933: Check channel state when OPEN_FAILURE arrives
When a SSH2_MSG_OPEN_FAILURE arrives, the channel state is checked
to be in SSH_CHANNEL_STATE_OPENING.

Fixes T101

Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
2018-10-09 11:45:59 +02:00
Anderson Toshiyuki Sasaki
3837a0547f CVE-2018-10933: Check channel state when OPEN_CONFIRMATION arrives
When a SSH2_MSG_OPEN_CONFIRMATION arrives, the channel state is checked
to be in SSH_CHANNEL_STATE_OPENING.

Fixes T101

Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
2018-10-09 11:45:58 +02:00
Anderson Toshiyuki Sasaki
7985acb768 CVE-2018-10933: Set correct state after sending MIC
After sending the client token, the auth state is set as
SSH_AUTH_STATE_GSSAPI_MIC_SENT.  Then this can be expected to be the
state when a USERAUTH_FAILURE or USERAUTH_SUCCESS arrives.

Fixes T101

Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
2018-10-09 11:45:58 +02:00
Anderson Toshiyuki Sasaki
acd6a1ca8a CVE-2018-10933: Introduce SSH_AUTH_STATE_AUTH_NONE_SENT
The introduced auth state allows to identify when a request without
authentication information was sent.

Fixes T101

Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
2018-10-09 11:45:58 +02:00
Anderson Toshiyuki Sasaki
ddea46f890 CVE-2018-10933: Introduce SSH_AUTH_STATE_PASSWORD_AUTH_SENT
The introduced auth state allows to identify when authentication using
password was tried.

Fixes T101

Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
2018-10-09 11:45:58 +02:00
Anderson Toshiyuki Sasaki
e5f0e711b0 CVE-2018-10933: Introduced new auth states
Introduced the states SSH_AUTH_STATE_PUBKEY_OFFER_SENT and
SSH_AUTH_STATE_PUBKEY_AUTH_SENT to know when SSH2_MSG_USERAUTH_PK_OK and
SSH2_MSG_USERAUTH_SUCCESS should be expected.

Fixes T101

Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
2018-10-09 11:45:58 +02:00
Andreas Schneider
e765c1400a dh: Use ssh_get_fingerprint_hash() in ssh_print_hash()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 92aa2cf496)
2018-10-09 10:16:30 +02:00
Andreas Schneider
7a7c0a54bc dh: Add ssh_get_fingerprint_hash()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit bbed139eca)
2018-10-09 10:16:27 +02:00
Jan-Niklas Burfeind
9c62d6dfcd dh: Add ssh_print_hash() function which can deal with sha256
Signed-off-by: Jan-Niklas Burfeind <libssh@aiyionpri.me>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit f32cb70675)
2018-10-09 10:16:20 +02:00
Jan-Niklas Burfeind
f3f140e65f dh: Add SSH_PUBLICKEY_HASH_SHA256 to ssh_get_publickey_hash()
Signed-off-by: Jan-Niklas Burfeind <libssh@aiyionpri.me>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 1499b38aef)
2018-10-09 10:16:14 +02:00
Jakub Jelen
c977a97093 Assorted changes to make the proxycommand test pass
Cherry-picked from the following commit:
e4653b82bd
2018-10-05 12:09:45 +02:00
Jakub Jelen
743a34ad9f Assorted changes to make the sftp_read test working
CHerry-picked from the following commit:
571f547556
2018-10-05 12:09:45 +02:00
Jakub Jelen
0f9e6598ef Assorted changes to make the sftp_dir test working
Cherry-picked from the following commit:
af3de262b6
2018-10-05 12:09:45 +02:00
Jakub Jelen
f8007d7147 Assorted changes to make the torture_forward test pass
Cherry-picked from the following commit:
be25b58380
2018-10-05 12:09:45 +02:00
Jakub Jelen
3d70d4f08d Assorted changes to make torture_request_env pass
Cherry-picked from the following commit:
4bc6af6c17
2018-10-05 12:09:45 +02:00
Andreas Schneider
bade29d3d5 torture: Fix torture_ssh_session() for cwrap testing
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit 66f51df9)
2018-10-05 12:09:45 +02:00
Andreas Schneider
399ff6bbde tests: Add public keys for bob
This also allows bob to auth as alice.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry-picked from commit ee866441)
2018-10-05 12:09:45 +02:00
Jakub Jelen
c0d9aeda18 Assorted changes to make knownhosts test work
Cherry-picked from the following commit:
b65dcb3a35
2018-10-05 12:09:45 +02:00
Andreas Schneider
82b2d31c29 tortrue: Add ed25519 hostkey to sshd
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit 250bf37a)
2018-10-05 12:09:45 +02:00
Jakub Jelen
74102dfd7a Assorted changes from master to make torture_algorithms test working
Cherry-picked from the following commits:
cbd75c3e35
3014e3c458
2018-10-05 12:09:45 +02:00
Andreas Schneider
d678f6a9ea torture: Fix building on Windows
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit b74a1841)
2018-10-05 12:09:45 +02:00
Jakub Jelen
00b8e6d1f0 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 56317caa)
2018-10-05 12:09:45 +02:00
Jakub Jelen
aeb859e130 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 ca4fb9c6)
2018-10-05 12:09:45 +02:00
Jakub Jelen
b393f7e5e9 tests: Temporarily build chroot_wrapper
(cherry-picked from commit 094aa5eb)
2018-10-05 12:09:45 +02:00
Andreas Schneider
2004617fd0 tests: Always start tests as root so we can switch to a user
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit 1729d4a1)
2018-10-05 12:09:45 +02:00
Jakub Jelen
c5fe7c5a72 tests: Do not generate pcap file by default
pcap file is generated by the processes writing to the sockets,
which is not allowed for privilege-separated process in new
OpenSSH servers (confined by seccomp filter).

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit 5d3ab421)
2018-10-05 12:09:45 +02:00
Jakub Jelen
fec4dc4eff tests: Give server more time to start
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit f8f7989c)
2018-10-05 12:09:45 +02:00
Jakub Jelen
3d0c9cc6b5 tests: Do not test blowfish ciphers with OpenSSH 7.6 and newer
(cherry-picked from commit b92c4996)
2018-10-05 12:09:45 +02:00
Andreas Schneider
4d6048ef88 torture: Add support to specify verbosity level via env variable
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit 2a9c3966)
2018-10-05 12:09:45 +02:00
Andreas Schneider
3d2d777e26 torture: Fix a warning
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit 2bd65015)
2018-10-05 12:09:45 +02:00
Aris Adamantiadis
8520adf609 osx: fix compilation
(cherry-picked from commit 886fdc8b)
2018-10-05 12:09:45 +02:00
Justus Winter
c0be59f876 tests: Make test suite work out of the box on Debian
* tests/torture.c (torture_setup_create_sshd_config): Rework how the
location of the sftp server is discovered, and add the Debian-specific
location.

Signed-off-by: Justus Winter <justus@g10code.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit e37fd832)
2018-10-05 12:09:45 +02:00
Andreas Schneider
2983b21996 torture: Fix ssh version detection
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit de309c51)
2018-10-05 12:09:45 +02:00
Andreas Schneider
88ae595583 torture: Set sshd debug level to DEBUG3
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit 06343074)
2018-10-05 12:09:45 +02:00
Andreas Schneider
a228c3f728 torture: Also write stderr to a file
This allows to capture debug information of the wrappers.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit c365ff3d)
2018-10-05 12:09:45 +02:00
Andreas Schneider
53ed121a9c torture: Add additional sftp-server path for BSD
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit 1bbfe058)
2018-10-05 12:09:45 +02:00
Andreas Schneider
5a1ebdec9d tests: Wait for sshd to start before connecting
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit a3557b81)
2018-10-05 12:09:45 +02:00
Andreas Schneider
bf2a33b21e tests: Turn on PAM support in sshd with pam_wrapper
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit 7aa84318)
2018-10-05 12:09:45 +02:00
Andreas Schneider
130194aa0e torture: Improve process termination function
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit 0e98f121)
2018-10-05 12:09:45 +02:00
Andreas Schneider
1ebfd3834a tests: Support other openssh versions ...
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit 6e7eae96)
2018-10-05 12:09:45 +02:00
Andreas Schneider
1eeeace975 cmake: Configure nss_wrapper and uid_wrapper
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit 21b0d29e)
2018-10-02 16:35:28 +02:00
Andreas Schneider
73ebcb3ab8 torture: Start sshd as root
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit a30d16c4)
2018-10-02 16:35:08 +02:00
Andreas Schneider
bd7b509278 torture: Enable old host key algos for testing
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit c1fb9483)
2018-10-02 16:34:49 +02:00
Andreas Schneider
652acbeb21 torture: Enable old cipher and kex algos in sshd
We need to test them, so enable them in the sshd.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit dd0d04ae)
2018-10-02 16:34:23 +02:00
Andreas Schneider
96e04d4691 torture: Create a torture_terminate_process() function
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit ae89b6c0)
2018-10-02 16:34:02 +02:00
Andreas Schneider
7113074ae4 torture: Add torture_teardown_sshd_server().
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit 14f1ce2e)
2018-10-02 16:33:40 +02:00
Andreas Schneider
2db325eb74 torture: Restrict files to we write to our user.
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit 62b0f58d)
2018-10-02 16:33:18 +02:00
Andreas Schneider
9937d0b552 torture: Add function to setup sshd server
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit c3f963e7)
2018-10-02 16:32:45 +02:00
Andreas Schneider
ae3e2a19c8 torture: Add torture_teardown_socket_dir().
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit fd09c4cb)
2018-10-02 16:32:04 +02:00
Andreas Schneider
3567524fb2 torture: Add torture_setup_socket_dir().
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit 13f68fc2)
2018-10-02 16:31:32 +02:00
Andreas Schneider
4814c188eb tests: Add ssh host keys for test environment.
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit c2d63627)
2018-10-02 16:31:16 +02:00
Andreas Schneider
a317188cb7 cmake: Search for cwrap and sshd.
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>

(cherry-picked from commit 6596d27e)
2018-10-02 16:29:17 +02:00
Andreas Schneider
1d4151e51f libcrypt: Add missing header for compat
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
2018-06-30 14:10:32 +02:00
Andreas Schneider
c228fa7631 pki: Fix duplicating ed25519 public keys
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 816234350d)
2018-06-29 17:18:12 +02:00
Andreas Schneider
9658d36087 kex1: Add missing NULL check in make_rsa1_string()
CID 1388445

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c705fb6e3b)
2018-06-29 17:17:27 +02:00
Nikos Mavrogiannopoulos
bbaa3dc869 kex1: Use libcrypto-compat.h for RSA_get0_key with OpenSSL
Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit a95bc8a016)
2018-06-29 17:17:03 +02:00
Andreas Schneider
4f10d6cd57 kex1: Fix building with OpenSSL 1.1+
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8d65edb41f)
2018-06-29 17:16:49 +02:00
Meng Tan
2209fcace3 Set channel as bound when accepting channel open request
Signed-off-by: Meng Tan <mtan@wallix.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit f19158cadf)
2018-06-29 17:16:06 +02:00
Andreas Schneider
a1847660a3 pki: Fix random memory corruption
Fixes T78

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 1444ae5add)
2018-06-29 17:12:46 +02:00
Jon Simons
e2b48dc662 libcrypto: fix resource leak in hmac_final
Fix a resource leak in `hmac_final`: say `HMAC_CTX_free` instead
of `HMAC_CTX_reset`.  This matches the error handling as done in
`hmac_init`.  Introduced with cf1e808e2f.

The problem is reproducible running the `pkd_hello` test with:

    valgrind --leak-check=full ./pkd_hello -i1 -t torture_pkd_openssh_dsa_rsa_default

Resolves https://red.libssh.org/issues/252.

Cherry-picked from a64ddff3fe

Signed-off-by: Jon Simons <jon@jonsimons.org>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2018-06-29 17:08:54 +02:00
Jon Simons
1a5b6ac472 libcrypto-compat: fix HMAC_CTX_free for OpenSSL < 1.1.0
On older OpenSSL versions, the EVP_MD_CTX fields within an HMAC_CTX
structure are contained inlined (change here [1]): be sure to not
try to free those fields on those builds.

Found running the `pkd_hello` test with:

    valgrind ./pkd_hello -i1 -t torture_pkd_openssh_dsa_rsa_default

^ valgrind will cite "Invalid free() ..." errors which are present
before this fix and absent after, when building with OpenSSL 1.0.1.

[1] 6e59a892db

Cherry-picked from 25384e9558

Signed-off-by: Jon Simons <jon@jonsimons.org>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2018-06-29 17:08:54 +02:00
Andreas Schneider
0dd7a963a9 cmake: Only build libcrypto and libcrypto-compat when needed
This also fixes the gcrypt build.

Cherry-picked from 2f6a866373

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
2018-06-29 17:08:54 +02:00
Andreas Schneider
1642cec280 cmake: Use configure check for CRYPTO_ctr128_encrypt
Cherry-picked from 3daf1760a1

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
2018-06-29 17:08:54 +02:00
Jakub Jelen
2f1c6668e7 pki_crypto: Use getters and setters for opaque keys and signatures
This is for OpenSSL 1.1.0 support.

Cherry-picked from 3341f49a49

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2018-06-29 17:08:54 +02:00
Jakub Jelen
fbeecf388c libcrypto: Use a pointer for EVP_MD_CTX
This is for OpenSSL 1.1.0 support.

Cherry-picked from 607c671f67

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2018-06-29 17:08:54 +02:00
Jakub Jelen
7933756b5a libcrypto: Use newer API for HMAC
This is for OpenSSL 1.1.0 support.

Cherry-picked from cf1e808e2f

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2018-06-29 17:08:54 +02:00
Jakub Jelen
837e367d2d libcrypto: Introduce a libcrypto compat file
This is for OpenSSL 1.1.0 support.

Cherry-picked from b6cfde8987

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2018-06-29 17:08:54 +02:00
Jakub Jelen
f81c3ada9c libcrypto: Remove AES_ctr128_encrypt()
This is for OpenSSL 1.1.0.

Cherry-picked from d73f665edd

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2018-06-29 17:08:54 +02:00
Artyom V. Poptsov
83663895f4 config: Bugfix: Don't skip unseen opcodes
libssh fails to read the configuration from a config file due to a
wrong check in 'ssh_config_parse_line' procedure in 'config.c'; it's
effectively skipping every opcode (and therefore every option) from
the file.  The change fixes that behaviour.

Signed-off-by: Artyom V. Poptsov <poptsov.artyom@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 5333be5988)
2018-06-29 17:08:54 +02:00
Andreas Schneider
239d0f75b5 messages: Do not leak memory of previously allocated answers
Found by ozz-fuzz

BUG: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1222

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 7c79b5c154)
2017-04-25 16:21:11 +02:00
Andreas Schneider
d88cc720fb messages: Do not leak memory if answeres had been allocated previously
Found by ozz-fuzz

BUG: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1222

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 5eb41492c4)
2017-04-24 13:28:17 +02:00
Andreas Schneider
ee13becf9c messages: Do not leak memory if answered had been allocated previously
BUG: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1184

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c78c6c6542)
2017-04-21 11:14:51 +02:00
Andreas Schneider
95b2dbbeca misc: Validate integers converted from the SSH banner
BUG: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1181

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit d5d8349224)
2017-04-21 11:14:46 +02:00
Andreas Schneider
02c0a3b99b messages: Fix memory leaks in the ssh_packet_global_request callback
BUG: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1208

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 67a2ba6f99)
2017-04-21 11:14:42 +02:00
Andreas Schneider
419731a189 auth: Use calloc in ssh_userauth_agent_pubkey()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 79437fa0c9)
2017-04-21 11:14:39 +02:00
Peter Volpe
2ac987bce9 session: Free session->kbdint in ssh_free()
Makes sure we free pending keyboard auth prompts
so prompts that have not be replied to do not leak.

Signed-off-by: Peter Volpe <pvolpe@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 76ba2b0055)
2017-04-20 17:04:54 +02:00
Andreas Schneider
0588cbf9d4 Bump version to 0.7.5
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
2017-04-13 16:33:04 +02:00
Andreas Schneider
a7cce77550 buffer: Validate the length before before memory allocation
Check if the size the other party sent is a valid size in the
transmitted buffer.

Thanks to Alex Gaynor for finding and reporting the issue.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 68b7ca6e92)
2017-04-13 16:28:18 +02:00
Andreas Schneider
5e63b40cde buffer: Create ssh_buffer_validate_length()
This functions allows if a given length can be obtained from the buffer.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c165c396de)
2017-04-13 16:27:33 +02:00
Alex Hermann
7b8b5eb4ea config: Only use first occurence of each parameter
ssh_config's manpage says:
"For each parameter, the first obtained value will be used."

Make libssh adhere to this rule.

BUG: https://red.libssh.org/issues/256

Signed-off-by: Alex Hermann <alex@hexla.nl>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 5f202d7ffa)
2017-04-13 16:10:10 +02:00
Alex Hermann
8dc3d883b8 config: Don't expand Host variable
Tokens are not allowed (according to the manpage).
Expansion was introduced by a wrong fix for #127.

This commit reverts part of 6eea08a9ef

Signed-off-by: Alex Hermann <alex@hexla.nl>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c3a8b5009f)
2017-04-13 16:10:09 +02:00
Alex Hermann
24a3f7020c config: Support expansion in the HostName variable
BUG: https://red.libssh.org/issues/127

The original "fix" for 127 was expanding the wrong variable: Host instead
of HostName.

Signed-off-by: Alex Hermann <alex@hexla.nl>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 9ef7e90821)
2017-04-13 16:10:07 +02:00
Yanis Kurganov
f74d5d5df4 session: Add SSH1 support in ssh_send_debug()
Signed-off-by: Yanis Kurganov <ykurganov@ptsecurity.com>
Reviewed-by: Andreas Schneider <asn@samba.org>
(cherry picked from commit 38cb19268a)
2017-04-11 17:40:58 +02:00
Yanis Kurganov
7a21187fb9 session: Add SSH1 support in ssh_send_ignore()
Signed-off-by: Yanis Kurganov <ykurganov@ptsecurity.com>
Reviewed-by: Andreas Schneider <asn@samba.org>
(cherry picked from commit 72fdb4867e)
2017-04-11 17:40:57 +02:00
Max Bachmann
439d3039e3 messages: Utilize the message queue for SSH_REQUEST_GLOBAL.
Signed-off-by: Max Bachmann <mabahltm@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 3ec8babfaf)
2017-04-11 09:55:46 +02:00
Andreas Schneider
61cbf160a0 cmake: Fix GCRYPT_ROOT_DIR and check correct paths
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 462c7726c3)
2017-04-11 09:55:05 +02:00
Andreas Schneider
ce029c0735 pki: Use byte mode for fopen()
BUG: https://red.libssh.org/issues/251

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit de369b46b1)
2017-02-03 13:19:24 +01:00
Andreas Schneider
8a2deeb3cc Bump version to 0.7.4 2017-02-03 09:47:18 +01:00
Andreas Schneider
40164c348e Update ChangeLog 2017-02-03 09:47:09 +01:00
Tilo Eckert
9d7f873fd3 session: Add missing ifdef that prevented Windows builds
Signed-off-by: Tilo Eckert <tilo.eckert@flam.de>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 4f392ebc7e)
2016-11-25 13:11:37 +01:00
Andreas Schneider
c5d320811b sftpserver: Fix SSH_FXP_FSTAT arguments
Thanks to Игорь Коваленко <igor.a.kovalenko@gmail.com>

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 47d21b6420)
2016-11-07 19:56:10 +01:00
Andreas Schneider
410f722ae5 misc: Use simpler macros for htonll and ntohll
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 52efbc3a23)
2016-11-07 09:43:09 +01:00
Andreas Schneider
8155b3c0a0 cmake: Always check for strtoull
This fixes building with different compilers on Windows

BUG: https://red.libssh.org/issues/225

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit fab85b495e)
2016-11-06 11:42:04 +01:00
Andreas Schneider
6836ffa103 options: Fix log level documentation
BUG: https://red.libssh.org/issues/210

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 801bc29494)
2016-11-05 17:16:14 +01:00
Andreas Schneider
b62b822100 cmake: Correctly check for *snprintf functions on Windows
BUG: https://red.libssh.org/issues/205

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 1bf6c965e4)
2016-11-05 16:41:50 +01:00
Andreas Schneider
849f5db5d1 config: Fix build warning
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
2016-11-05 16:33:29 +01:00
Pino Toscano
a6493efcae sftp: Fix memory leak in sftp_fstat
When parsing the result of a successful fstat call, make sure to free
the resulting reply message.

Signed-off-by: Pino Toscano <ptoscano@redhat.com>
Reviewed-by: Andreas Schneider <asn@samba.org>
(cherry picked from commit bc78383fac)
2016-10-22 16:04:00 +02:00
Andreas Schneider
1b0bf852be sftp: Correctly check for EOF else keep spinning if there is no data
This fixes an issue introduced with
dbf72ffba2

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit f561e6bcb3)
2016-10-07 13:37:48 +02:00
Andreas Schneider
2b3185ec29 gssapi: Use correct return code in ssh_gssapi_auth_mic()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 83421c0e8c)
2016-10-06 19:39:06 +02:00
Andreas Schneider
d63547b18a gssapi: Print minor stat in error logging function
This also releases the memory allocated for the messages.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 095733ed9c)
2016-10-06 19:39:01 +02:00
Jeremy Cross
6697f85b50 sftp: ensure sftp_packet_read recognizes channel EOF to avoid infinite loop
Signed-off-by: Jeremy Cross <jcross@bomgar.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit dbf72ffba2)
2016-09-09 11:40:07 +02:00
Travers Carter
67fe6f56ea Make "Host" pattern list handling consistent with OpenSSH
https://red.libssh.org/issues/187

Signed-off-by: Travers Carter <tcarter@noggin.com.au>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit bc2db86d1c)
2016-05-03 17:57:45 +02:00
Andreas Schneider
b5ce15eefa priv: Fix client banner specification for libssh
BUG: https://red.libssh.org/issues/231

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 4f7be0dbb2)
2016-05-03 10:58:47 +02:00
Andreas Schneider
a3688ada1a client: If SSHv1 is disabled send the banner immediately
This saves a round-trip with SSHv2 connecting to the server. See RFC
4253 section 5.2 (New Client, Old Server).

Thanks to Yang Yubo <yang@yangyubo.com> for the suggestion.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 1da5c94b44)
2016-05-03 10:58:36 +02:00
Andreas Schneider
219d0bba42 client: Fix ssh_send_banner() to confirm with RFC 4253
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 3d1edffe77)
2016-05-03 10:58:27 +02:00
Andreas Schneider
bf3d8f3ad4 client: Fix maximum banner length
According to RFC 4253 the max banner length is 255.

Thanks to Saju Panikulam <spanikulam@ipswitch.com> for the report.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit cb52ed7b12)
2016-05-03 10:58:18 +02:00
Andreas Schneider
04a5d5bd74 client: Reformat callback_receive_banner()
The function is hard to read as the indentation is not correctly
applied.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 22799b107d)
2016-05-03 10:58:06 +02:00
Ken Reister
2957aaf9f0 client: Receive the banner correctly
Comply with RFC 4253 compliance section 4.2.

Allow data other than "SSH-" to be sent across prior to the actual
version striong.

Signed-off-by: Ken Reister <reister.kenneth@CIMCOR.COM>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c3ce3d5cc3)
2016-05-03 10:57:50 +02:00
Kohei Suzuki
8360139506 Add id_ed25519 to the default identity list
Signed-off-by: Kohei Suzuki <eagletmt@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c092101e01)
2016-05-02 15:34:32 +02:00
David Kedves
0bf78b0b8b channels: Bugfix for a possible invalid pointer usage (channel->session) in various places
BUG: https://red.libssh.org/issues/230

Signed-off-by: David Kedves <kedazo@severalnines.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit d7df4429eb)
2016-05-02 15:32:16 +02:00
Stef Walter
faca78f547 auth: Cleanup memory leak when using SSH agent
In Cockpit we've seen this memory leak:

at 0x4C2A9C7: calloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x5B76B03: ssh_userauth_agent (auth.c:778)
by 0x40DD5A: cockpit_ssh_authenticate (cockpitsshtransport.c:327)

BUG: https://red.libssh.org/issues/208

Signed-off-by: Stef Walter <stefw@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit ffe8b98cc2)
2016-05-02 15:29:01 +02:00
Andreas Schneider
7da587ba6c auth1: Fix non-blocking SSHv1 auth
BUG: https://red.libssh.org/issues/232

Thanks to Fengyu Gao.

TODO: Add SSHv1 tests to our testsuite.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 33ecaaac01)
2016-05-02 12:31:53 +02:00
Andreas Schneider
c7aa51240d Update the README
(cherry picked from commit e8b28f978e)
2016-05-02 12:11:02 +02:00
Andreas Schneider
cdf7690e03 Bump version to 0.7.3
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
2016-02-23 08:23:31 +01:00
Andreas Schneider
7b19719022 Update ChangeLog 2016-02-23 08:22:09 +01:00
Aris Adamantiadis
f8d0026c65 dh: Fix CVE-2016-0739
Due to a byte/bit confusion, the DH secret was too short. This file was
completely reworked and will be commited in a future version.

Signed-off-by: Aris Adamantiadis <aris@0xbadc0de.be>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2016-02-23 08:17:43 +01:00
Hani Benhabiles
6b608e70ee options: Fix documentation typo
Signed-off-by: Hani Benhabiles <hani@linux.com>
Reviewed-by: Andreas Schneider <asn@samba.org>
(cherry picked from commit f8bde7156f)
2016-02-23 08:15:26 +01:00
Younes Serraj
a69a1af568 pki: Fixed documentation about return value.
Documentation now is congruent with the code:
- SSH_OK is returned on success,
- SSH_ERROR is returned on error.

Signed-off-by: Younes Serraj <younes.serraj@gmail.com>
Reviewed-by: Andreas Schneider <asn@samba.org>
(cherry picked from commit 66c6ae1a55)
2016-02-23 08:15:24 +01:00
pouete
32b72555ee cmake: use check_symbol for (v)snprintf
Updated how snprintf and vsnprintf are discovered by cmake. Visual studio
2015 now include it in the file stdio.h.
More information here :
https://msdn.microsoft.com/en-us/library/bb531344.aspx

Reviewed-By: Aris Adamantiadis <aris@0xbadc0de.be>
2015-12-30 19:51:26 +01:00
Sebastián Peyrott
32af6a2390 CMake: include CheckIncludeFiles for calls to check_include_files. 2015-12-24 13:01:56 +01:00
Fabiano Fidêncio
b470dd943f Fix a bunch of -Wmaybe-uninitialized
Reviewed-By: Aris Adamantiadis <aris@0xbadc0de.be>
2015-12-17 15:02:01 +01:00
Dirk Neukirchen
69ca977aed headers: fix missing mode_t (2nd)
Reviewed-By: Aris Adamantiadis <aris@0xbadc0de.be>
2015-11-10 18:39:59 +01:00
Aris Adamantiadis
728a6349b7 Revert "headers: fix missing mode_t"
I commited a patch file *headdesk*
This reverts commit 378fcccc0a.
2015-11-10 18:39:52 +01:00
Dirk Neukirchen
ec32174abc headers: fix missing mode_t
Signed-off-by: Dirk Neukirchen <dirkneukirchen@web.de>
Reviewed-by: Aris Adamantiadis <aris@0xbadc0de.be>
2015-11-10 18:28:45 +01:00
Andreas Schneider
2172cd234a Ignore all build and obj* directories
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
2015-10-28 09:28:42 +01:00
Andreas Schneider
0425ac9ad0 agent: Fix agent auth on big endian machines
BUG: https://red.libssh.org/issues/204

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
2015-10-20 17:17:17 +02:00
Aris Adamantiadis
367558bb21 crypto: fix potential memory leak in ECDH 2015-09-21 15:03:08 +02:00
Andreas Schneider
186e7b5ca4 kex: Fix zlib compression
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 747e7d05db)
2015-09-16 08:34:58 +02:00
Andreas Schneider
2197704693 Bump version to 0.7.2 2015-09-15 15:17:35 +02:00
Andreas Schneider
229eb8715d cmake: Use tar.xz source package generator
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 1f3a9105ff)
2015-09-15 15:17:35 +02:00
Andreas Schneider
1b18a06f8c kex: Prefer sha2 over sha1
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit b0f22fde62)
2015-09-15 15:09:21 +02:00
Andreas Schneider
91b513798e cmake: Handle libssh threas library correctly
This should fix the build on Windows and would not install pkg files.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 5b586fdfec)
2015-09-08 17:32:57 +02:00
Michael Wilder
25234e510a bignum: Fix OpenSSL crash in SAFE_FREE
Signed-off-by: Michael Wilder <wilder.michael@cimcor.com>
Reviewed-by: Andreas Schneider <asn@samba.org>
(cherry picked from commit 2f193b5cbb)
2015-09-08 17:32:40 +02:00
Andreas Schneider
d16eac5704 server: Fix return code check of ssh_buffer_pack()
Thanks to Andreas Gutschick <andreas.gutschick@mitel.com>

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 36d9b62f1f)
2015-08-18 09:12:47 +02:00
Andreas Schneider
46bff47975 doc: Fix typos in sftp tutorial
Thanks to Anthony Baker <AnthonyBaker@fico.com>

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit da4bebbe1e)
2015-08-18 09:05:45 +02:00
Andreas Schneider
f718b50b3f tests: Add checks for ssh_key_is_private()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit d54a1ab798)
2015-08-10 13:58:51 +02:00
Andreas Schneider
58b7d0f5d2 pki: Fix return values of ssh_key_is_(public|private)
Thanks to Kevin Haake <khaake@red-cocoa.com>

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit e1081796af)
2015-08-10 13:58:50 +02:00
Tilo Eckert
30d4581be5 sftp: Fix incorrect handling of received length fields
Signed-off-by: Tilo Eckert <tilo.eckert@flam.de>
2015-08-01 10:52:48 +03:00
Peter Volpe
83387f957f auth: Fix return status for ssh_userauth_agent()
BUG: https://red.libssh.org/issues/201

Return SSH_AUTH_DENIED instead of SSH_AUTH_ERROR when the provided agent
offers no public keys.

Signed-off-by: Peter Volpe <pvolpe@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit dc9c4d22ab)
2015-07-30 10:52:11 +02:00
Andreas Schneider
f3620bbbad cmake: Fix zlib include directory
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 728c2fbd01)
2015-07-03 12:36:53 +02:00
Andreas Schneider
b45933d30d cmake: Fix OpenSSL detection in non-standard path
This should fix the detection on Windows.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 613b71b385)
2015-07-03 11:40:04 +02:00
Andreas Schneider
1613ed556d cmake: Fail if can't find OpenSSL aes and des headers
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 70cc11618a)
2015-07-03 10:52:56 +02:00
Andreas Schneider
8f5b7b65eb include: Add stdarg.h so we can check for va_copy macro
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
2015-06-30 09:59:21 +02:00
Andreas Schneider
053f72c671 Bump version to 0.7.1
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
2015-06-30 09:34:28 +02:00
Tilo Eckert
63a8f333b8 SSH_AUTH_PARTIAL is now correctly passed to the caller of ssh_userauth_publickey_auto().
Implicitly fixed unsafe return code handling that could result in use-after-free.

Signed-off-by: Tilo Eckert <tilo.eckert@flam.de>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 0423057424)
2015-06-29 11:11:26 +02:00
Tilo Eckert
57fd8e3187 available auth_methods must be reset on partial authentication
Signed-off-by: Tilo Eckert <tilo.eckert@flam.de>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit cc25d747d4)
2015-06-29 11:11:25 +02:00
Peter Volpe
03972b16c9 channels: Fix exit-signal data unpacking
Signed-off-by: Peter Volpe <pvolpe@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 7637351065)
2015-06-29 09:50:28 +02:00
Peter Volpe
ac7ed82585 agent: Add ssh_set_agent_socket
Allow callers to specify their own socket
for an ssh agent.

Signed-off-by: Peter Volpe <pvolpe@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 7aeba71a92)
2015-06-29 09:47:35 +02:00
Seb Boving
196c2e9c1f Don't allocate a new identity list in the new session's options.
The previous list is not freed. Since the new session just got
created, an identity list is already allocated and empty.

Signed-off-by: Sebastien Boving <seb@google.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit e020dd8d59)
2015-06-24 18:36:10 +02:00
Douglas Heriot
1accbcb98b cmake: Do not use CMAKE_(SOURCE|BINARY)_DIR
(cherry picked from commit a65af1b3b8)
2015-06-24 18:36:08 +02:00
Tiamo Laitakari
342ae10f08 pki: Fix allocation of ed25519 public keys
Signed-off-by: Tiamo Laitakari <tiamo.laitakari@cs.helsinki.fi>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 5478de1a64)
2015-06-24 18:36:08 +02:00
Jordy Moos
eb98a780ed Documentation fix where unsigned is used where signed is expected
Signed-off-by: Jordy Moos <jordymoos@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit fa9fbb1d67)
2015-06-24 18:36:08 +02:00
Andreas Schneider
64233fa3bb misc: Correctly guard the sys/time.h include
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit ef751a26d0)
2015-06-24 18:36:08 +02:00
Andreas Schneider
cbf5cf4ac3 include: Add support for older MSVC versions
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 30a7229fc5)
2015-06-24 16:24:12 +02:00
Andreas Schneider
a3f3f9cb76 kex: Add comments to #if clauses
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 1d69e073af)
2015-06-24 16:24:08 +02:00
Aris Adamantiadis
5aeae08be0 channels: fix exit-status not correctly set 2015-06-03 16:41:19 +02:00
Mike DePaulo
64a658acaa Comment that ssh_forward_cancel() is deprecated.
Signed-off-by: Aris Adamantiadis <aris@badcode.be>
2015-05-29 11:30:32 +02:00
Mike DePaulo
361940a5d7 Reintroduce ssh_forward_listen() (Fixes: #194)
Signed-off-by: Aris Adamantiadis <aris@badcode.be>
2015-05-29 11:24:27 +02:00
Andreas Schneider
2721cbc8ee ChangeLog: Set release date for 0.7.0 2015-05-11 10:42:08 +02:00
86 changed files with 3763 additions and 718 deletions

4
.gitignore vendored
View File

@@ -3,7 +3,7 @@
.* .*
*.swp *.swp
*~$ *~$
obj
cscope.* cscope.*
tags tags
build /build
/obj*

View File

@@ -8,7 +8,7 @@ set(APPLICATION_NAME ${PROJECT_NAME})
set(APPLICATION_VERSION_MAJOR "0") set(APPLICATION_VERSION_MAJOR "0")
set(APPLICATION_VERSION_MINOR "7") set(APPLICATION_VERSION_MINOR "7")
set(APPLICATION_VERSION_PATCH "0") set(APPLICATION_VERSION_PATCH "7")
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}") set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
@@ -19,12 +19,12 @@ set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINO
# Increment AGE. Set REVISION to 0 # Increment AGE. Set REVISION to 0
# If the source code was changed, but there were no interface changes: # If the source code was changed, but there were no interface changes:
# Increment REVISION. # Increment REVISION.
set(LIBRARY_VERSION "4.4.0") set(LIBRARY_VERSION "4.4.4")
set(LIBRARY_SOVERSION "4") set(LIBRARY_SOVERSION "4")
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked # where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
set(CMAKE_MODULE_PATH set(CMAKE_MODULE_PATH
${CMAKE_SOURCE_DIR}/cmake/Modules ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules
) )
# add definitions # add definitions
@@ -84,7 +84,19 @@ add_subdirectory(include)
add_subdirectory(src) add_subdirectory(src)
# pkg-config file # pkg-config file
if (UNIX)
configure_file(libssh.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc) configure_file(libssh.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc)
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/libssh.pc
${CMAKE_CURRENT_BINARY_DIR}/libssh_threads.pc
DESTINATION
${LIB_INSTALL_DIR}/pkgconfig
COMPONENT
pkgconfig
)
if (LIBSSH_THREADS)
configure_file(libssh_threads.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh_threads.pc) configure_file(libssh_threads.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh_threads.pc)
install( install(
FILES FILES
@@ -95,6 +107,8 @@ install(
COMPONENT COMPONENT
pkgconfig pkgconfig
) )
endif (LIBSSH_THREADS)
endif (UNIX)
# cmake config files # cmake config files
set(LIBSSH_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}ssh${CMAKE_SHARED_LIBRARY_SUFFIX}) set(LIBSSH_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}ssh${CMAKE_SHARED_LIBRARY_SUFFIX})

View File

@@ -4,10 +4,10 @@
### general settings ### general settings
set(CPACK_PACKAGE_NAME ${APPLICATION_NAME}) set(CPACK_PACKAGE_NAME ${APPLICATION_NAME})
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The SSH library") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The SSH library")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README") set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README")
set(CPACK_PACKAGE_VENDOR "The SSH Library Development Team") set(CPACK_PACKAGE_VENDOR "The SSH Library Development Team")
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME}) set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING")
### versions ### versions
@@ -18,8 +18,8 @@ set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSIO
### source generator ### source generator
set(CPACK_SOURCE_GENERATOR "TGZ") set(CPACK_SOURCE_GENERATOR "TXZ")
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/build/;/obj/;tags;cscope.*") set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]git/;.gitignore;/build*;/obj*;tags;cscope.*")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
if (WIN32) if (WIN32)

View File

@@ -1,7 +1,53 @@
ChangeLog ChangeLog
========== ==========
version 0.7.0 (released 2015-05-xx) version 0.7.7 (released 2018-10-29)
* Fixed issues with MSVC
* Fixed keyboard-interactive auth in server mode
(regression from CVE-2018-10933)
* Fixed gssapi auth in server mode (regression from CVE-2018-10933)
* Fixed a memory leak with OpenSSL
version 0.7.6 (released 2018-10-16)
* Fixed CVE-2018-10933
* Added support for OpenSSL 1.1
* Added SHA256 support for ssh_get_publickey_hash()
* Fixed config parsing
* Fixed random memory corruption when importing pubkeys
version 0.7.5 (released 2017-04-13)
* Fixed a memory allocation issue with buffers
* Fixed PKI on Windows
* Fixed some SSHv1 functions
* Fixed config hostname expansion
version 0.7.4 (released 2017-02-03)
* Added id_ed25519 to the default identity list
* Fixed sftp EOF packet handling
* Fixed ssh_send_banner() to confirm with RFC 4253
* Fixed some memory leaks
version 0.7.3 (released 2016-01-23)
* Fixed CVE-2016-0739
* Fixed ssh-agent on big endian
* Fixed some documentation issues
version 0.7.2 (released 2015-09-15)
* Fixed OpenSSL detection on Windows
* Fixed return status for ssh_userauth_agent()
* Fixed KEX to prefer hmac-sha2-256
* Fixed sftp packet handling
* Fixed return values of ssh_key_is_(public|private)
* Fixed bug in global success reply
version 0.7.1 (released 2015-06-30)
* Fixed SSH_AUTH_PARTIAL auth with auto public key
* Fixed memory leak in session options
* Fixed allocation of ed25519 public keys
* Fixed channel exit-status and exit-signal
* Reintroduce ssh_forward_listen()
version 0.7.0 (released 2015-05-11)
* Added support for ed25519 keys * Added support for ed25519 keys
* Added SHA2 algorithms for HMAC * Added SHA2 algorithms for HMAC
* Added improved and more secure buffer handling code * Added improved and more secure buffer handling code

View File

@@ -1,4 +1,5 @@
include(CheckIncludeFile) include(CheckIncludeFile)
include(CheckIncludeFiles)
include(CheckSymbolExists) include(CheckSymbolExists)
include(CheckFunctionExists) include(CheckFunctionExists)
include(CheckLibraryExists) include(CheckLibraryExists)
@@ -56,6 +57,7 @@ check_include_file(libutil.h HAVE_LIBUTIL_H)
check_include_file(sys/time.h HAVE_SYS_TIME_H) check_include_file(sys/time.h HAVE_SYS_TIME_H)
check_include_file(sys/param.h HAVE_SYS_PARAM_H) check_include_file(sys/param.h HAVE_SYS_PARAM_H)
check_include_file(arpa/inet.h HAVE_ARPA_INET_H) check_include_file(arpa/inet.h HAVE_ARPA_INET_H)
check_include_file(byteswap.h HAVE_BYTESWAP_H)
if (WIN32) if (WIN32)
check_include_files("winsock2.h;ws2tcpip.h;wspiapi.h" HAVE_WSPIAPI_H) check_include_files("winsock2.h;ws2tcpip.h;wspiapi.h" HAVE_WSPIAPI_H)
@@ -65,24 +67,36 @@ if (WIN32)
check_include_files("winsock2.h;ws2tcpip.h" HAVE_WS2TCPIP_H) check_include_files("winsock2.h;ws2tcpip.h" HAVE_WS2TCPIP_H)
endif (WIN32) endif (WIN32)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS}) if (OPENSSL_FOUND)
check_include_file(openssl/aes.h HAVE_OPENSSL_AES_H) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
check_include_file(openssl/des.h HAVE_OPENSSL_DES_H)
if (NOT HAVE_OPENSSL_DES_H)
message(FATAL_ERROR "Could not detect openssl/des.h")
endif()
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS}) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
check_include_file(openssl/aes.h HAVE_OPENSSL_AES_H)
if (NOT HAVE_OPENSSL_AES_H)
message(FATAL_ERROR "Could not detect openssl/aes.h")
endif()
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
check_include_file(openssl/blowfish.h HAVE_OPENSSL_BLOWFISH_H) check_include_file(openssl/blowfish.h HAVE_OPENSSL_BLOWFISH_H)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS}) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
check_include_file(openssl/des.h HAVE_OPENSSL_DES_H)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
check_include_file(openssl/ecdh.h HAVE_OPENSSL_ECDH_H) check_include_file(openssl/ecdh.h HAVE_OPENSSL_ECDH_H)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS}) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
check_include_file(openssl/ec.h HAVE_OPENSSL_EC_H) check_include_file(openssl/ec.h HAVE_OPENSSL_EC_H)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS}) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
check_include_file(openssl/ecdsa.h HAVE_OPENSSL_ECDSA_H) check_include_file(openssl/ecdsa.h HAVE_OPENSSL_ECDSA_H)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
check_function_exists(CRYPTO_ctr128_encrypt HAVE_OPENSSL_CRYPTO_CTR128_ENCRYPT)
endif()
if (CMAKE_HAVE_PTHREAD_H) if (CMAKE_HAVE_PTHREAD_H)
set(HAVE_PTHREAD_H 1) set(HAVE_PTHREAD_H 1)
endif (CMAKE_HAVE_PTHREAD_H) endif (CMAKE_HAVE_PTHREAD_H)
@@ -101,16 +115,22 @@ endif (NOT WITH_GCRYPT)
check_function_exists(isblank HAVE_ISBLANK) check_function_exists(isblank HAVE_ISBLANK)
check_function_exists(strncpy HAVE_STRNCPY) check_function_exists(strncpy HAVE_STRNCPY)
check_function_exists(strndup HAVE_STRNDUP)
check_function_exists(strtoull HAVE_STRTOULL)
if (NOT WIN32)
check_function_exists(vsnprintf HAVE_VSNPRINTF) check_function_exists(vsnprintf HAVE_VSNPRINTF)
check_function_exists(snprintf HAVE_SNPRINTF) check_function_exists(snprintf HAVE_SNPRINTF)
endif (NOT WIN32)
if (WIN32) if (WIN32)
check_function_exists(_strtoui64 HAVE__STRTOUI64) check_symbol_exists(vsnprintf "stdio.h" HAVE_VSNPRINTF)
check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF)
check_function_exists(_vsnprintf_s HAVE__VSNPRINTF_S) check_symbol_exists(_vsnprintf_s "stdio.h" HAVE__VSNPRINTF_S)
check_function_exists(_vsnprintf HAVE__VSNPRINTF) check_symbol_exists(_vsnprintf "stdio.h" HAVE__VSNPRINTF)
check_function_exists(_snprintf HAVE__SNPRINTF) check_symbol_exists(_snprintf "stdio.h" HAVE__SNPRINTF)
check_function_exists(_snprintf_s HAVE__SNPRINTF_S) check_symbol_exists(_snprintf_s "stdio.h" HAVE__SNPRINTF_S)
if (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H) if (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
check_symbol_exists(ntohll winsock2.h HAVE_NTOHLL) check_symbol_exists(ntohll winsock2.h HAVE_NTOHLL)
@@ -124,6 +144,8 @@ if (WIN32)
set(CMAKE_REQUIRED_LIBRARIES) set(CMAKE_REQUIRED_LIBRARIES)
endif (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H) endif (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
check_function_exists(_strtoui64 HAVE__STRTOUI64)
set(HAVE_SELECT TRUE) set(HAVE_SELECT TRUE)
else (WIN32) else (WIN32)
check_function_exists(poll HAVE_POLL) check_function_exists(poll HAVE_POLL)
@@ -161,7 +183,6 @@ if (UNIX)
check_library_exists(util forkpty "" HAVE_LIBUTIL) check_library_exists(util forkpty "" HAVE_LIBUTIL)
check_function_exists(cfmakeraw HAVE_CFMAKERAW) check_function_exists(cfmakeraw HAVE_CFMAKERAW)
check_function_exists(strtoull HAVE_STRTOULL)
check_function_exists(__strtoull HAVE___STRTOULL) check_function_exists(__strtoull HAVE___STRTOULL)
endif (UNIX) endif (UNIX)

125
README
View File

@@ -33,130 +33,11 @@ If you ask yourself how to compile libssh, please read INSTALL before anything.
http://www.libssh.org http://www.libssh.org
4* API Changes ! 4* Contributing
-_-_-_-_-_-_-_-_-_ -_-_-_-_-_-_-_-_-_
Changes between 0.4 and 0.5 Please read the file 'SubmittingPatches' next to this README file. It explains
--------------------------- our copyright policy and how you should send patches for upstream inclusion.
We use the ssh_ prefix as namespace for every function now. There is a legacy.h
which could be used to get the old function names.
Changes between 0.3 and 0.4
---------------------------
We changed libssh to be typesafe now:
SSH_SESSION *session -> ssh_session session
SFTP_SESSION *sftp -> sftp_session sftp
CHANNEL *channel -> ssh_channel channel
STRING *string -> ssh_string string
...
The options structure has been removed and there is a new function. This
function can set all available options now. You can find the enum in the
header file and it is documented. Example:
ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
5* Copyright policy
-_-_-_-_-_-_-_-_-_-_
libssh is a project with distributed copyright ownership, which means we prefer
the copyright on parts of libssh to be held by individuals rather than
corporations if possible. There are historical legal reasons for this, but one
of the best ways to explain it is that its much easier to work with
individuals who have ownership than corporate legal departments if we ever need
to make reasonable compromises with people using and working with libssh.
We track the ownership of every part of libssh via git, our source code control
system, so we know the provenance of every piece of code that is committed to
libssh.
So if possible, if youre doing libssh changes on behalf of a company who
normally owns all the work you do please get them to assign personal copyright
ownership of your changes to you as an individual, that makes things very easy
for us to work with and avoids bringing corporate legal departments into the
picture.
If you cant do this we can still accept patches from you owned by your
employer under a standard employment contract with corporate copyright
ownership. It just requires a simple set-up process first.
We use a process very similar to the way things are done in the Linux Kernel
community, so it should be very easy to get a sign off from your corporate
legal department. The only changes weve made are to accommodate the license we
use, which is LGPLv2 (or later) whereas the Linux kernel uses GPLv2.
The process is called signing.
How to sign your work
----------------------
Once you have permission to contribute to libssh from your employer, simply
email a copy of the following text from your corporate email address to:
contributing@libssh.org
--------------------------------------------------------------------------
libssh Developer's Certificate of Origin. Version 1.0
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the appropriate
version of the GNU General Public License; or
(b) The contribution is based upon previous work that, to the best of
my knowledge, is covered under an appropriate open source license
and I have the right under that license to submit that work with
modifications, whether created in whole or in part by me, under
the GNU General Public License, in the appropriate version; or
(c) The contribution was provided directly to me by some other
person who certified (a) or (b) and I have not modified it.
(d) I understand and agree that this project and the contribution are
public and that a record of the contribution (including all
metadata and personal information I submit with it, including my
sign-off) is maintained indefinitely and may be redistributed
consistent with the libssh Team's policies and the requirements of
the GNU GPL where they are relevant.
(e) I am granting this work to this project under the terms of the
GNU Lesser General Public License as published by the
Free Software Foundation; either version 2.1 of
the License, or (at the option of the project) any later version.
http://www.gnu.org/licenses/lgpl-2.1.html
--------------------------------------------------------------------------
We will maintain a copy of that email as a record that you have the rights to
contribute code to libssh under the required licenses whilst working for the
company where the email came from.
Then when sending in a patch via the normal mechanisms described above, add a
line that states:
Signed-off-by: Random J Developer <random@developer.example.org>
using your real name and the email address you sent the original email you used
to send the libssh Developers Certificate of Origin to us (sorry, no
pseudonyms or anonymous contributions.)
Thats it! Such code can then quite happily contain changes that have copyright
messages such as:
(c) Example Corporation.
and can be merged into the libssh codebase in the same way as patches from any
other individual. You dont need to send in a copy of the libssh Developers
Certificate of Origin for each patch, or inside each patch. Just the sign-off
message is all that is required once weve received the initial email.
Have fun and happy libssh hacking! Have fun and happy libssh hacking!

View File

@@ -35,6 +35,8 @@ find_path(GCRYPT_INCLUDE_DIR
gcrypt.h gcrypt.h
HINTS HINTS
${_GCRYPT_ROOT_HINTS_AND_PATHS} ${_GCRYPT_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
include
) )
find_library(GCRYPT_LIBRARY find_library(GCRYPT_LIBRARY
@@ -44,6 +46,8 @@ find_library(GCRYPT_LIBRARY
libgcrypt-11 libgcrypt-11
HINTS HINTS
${_GCRYPT_ROOT_HINTS_AND_PATHS} ${_GCRYPT_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
lib
) )
set(GCRYPT_LIBRARIES ${GCRYPT_LIBRARY}) set(GCRYPT_LIBRARIES ${GCRYPT_LIBRARY})

View File

@@ -76,6 +76,9 @@
/*************************** FUNCTIONS ***************************/ /*************************** FUNCTIONS ***************************/
/* Define to 1 if you have the `CRYPTO_ctr128_encrypt' function. */
#cmakedefine HAVE_OPENSSL_CRYPTO_CTR128_ENCRYPT 1
/* Define to 1 if you have the `snprintf' function. */ /* Define to 1 if you have the `snprintf' function. */
#cmakedefine HAVE_SNPRINTF 1 #cmakedefine HAVE_SNPRINTF 1
@@ -100,6 +103,9 @@
/* Define to 1 if you have the `strncpy' function. */ /* Define to 1 if you have the `strncpy' function. */
#cmakedefine HAVE_STRNCPY 1 #cmakedefine HAVE_STRNCPY 1
/* Define to 1 if you have the `strndup' function. */
#cmakedefine HAVE_STRNDUP 1
/* Define to 1 if you have the `cfmakeraw' function. */ /* Define to 1 if you have the `cfmakeraw' function. */
#cmakedefine HAVE_CFMAKERAW 1 #cmakedefine HAVE_CFMAKERAW 1

View File

@@ -56,7 +56,7 @@ If an error has been encountered, it returns a negative value:
@code @code
char buffer[256]; char buffer[256];
unsigned int nbytes; int nbytes;
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
while (nbytes > 0) while (nbytes > 0)

View File

@@ -367,7 +367,7 @@ int show_remote_processes(ssh_session session)
ssh_channel channel; ssh_channel channel;
int rc; int rc;
char buffer[256]; char buffer[256];
unsigned int nbytes; int nbytes;
channel = ssh_channel_new(session); channel = ssh_channel_new(session);
if (channel == NULL) if (channel == NULL)
@@ -391,7 +391,7 @@ int show_remote_processes(ssh_session session)
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
while (nbytes > 0) while (nbytes > 0)
{ {
if (write(1, buffer, nbytes) != nbytes) if (write(1, buffer, nbytes) != (unsigned int) nbytes)
{ {
ssh_channel_close(channel); ssh_channel_close(channel);
ssh_channel_free(channel); ssh_channel_free(channel);

View File

@@ -253,7 +253,7 @@ int sftp_read_sync(ssh_session session, sftp_session sftp)
return SSH_ERROR; return SSH_ERROR;
} }
nwritten = write(fd, buf, nbytes); nwritten = write(fd, buffer, nbytes);
if (nwritten != nbytes) { if (nwritten != nbytes) {
fprintf(stderr, "Error writing: %s\n", fprintf(stderr, "Error writing: %s\n",
strerror(errno)); strerror(errno));
@@ -282,7 +282,7 @@ sftp_async_read() waits for the data to come. To open a file in nonblocking mode
call sftp_file_set_nonblocking() right after you opened it. Default is blocking mode. call sftp_file_set_nonblocking() right after you opened it. Default is blocking mode.
The example below reads a very big file in asynchronous, nonblocking, mode. Each The example below reads a very big file in asynchronous, nonblocking, mode. Each
time the data are not ready yet, a counter is incrementer. time the data is not ready yet, a counter is incremented.
@code @code
// Good chunk size // Good chunk size

View File

@@ -23,6 +23,7 @@ clients must be made or how a client should react.
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdbool.h>
#define SSHD_USER "libssh" #define SSHD_USER "libssh"
#define SSHD_PASSWORD "libssh" #define SSHD_PASSWORD "libssh"
@@ -36,6 +37,7 @@ clients must be made or how a client should react.
#endif #endif
static int port = 22; static int port = 22;
static bool authenticated = false;
#ifdef WITH_PCAP #ifdef WITH_PCAP
static const char *pcap_file = "debug.server.pcap"; static const char *pcap_file = "debug.server.pcap";
@@ -61,11 +63,20 @@ static void cleanup_pcap(void) {
#endif #endif
static int auth_password(const char *user, const char *password){ static int auth_password(const char *user, const char *password)
if(strcmp(user, SSHD_USER)) {
int cmp;
cmp = strcmp(user, SSHD_USER);
if (cmp != 0) {
return 0; return 0;
if(strcmp(password, SSHD_PASSWORD)) }
cmp = strcmp(password, SSHD_PASSWORD);
if (cmp != 0) {
return 0; return 0;
}
authenticated = true;
return 1; // authenticated return 1; // authenticated
} }
#ifdef HAVE_ARGP_H #ifdef HAVE_ARGP_H
@@ -200,6 +211,7 @@ static int kbdint_check_response(ssh_session session) {
return 0; return 0;
} }
authenticated = true;
return 1; return 1;
} }
@@ -328,7 +340,7 @@ int main(int argc, char **argv){
/* proceed to authentication */ /* proceed to authentication */
auth = authenticate(session); auth = authenticate(session);
if(!auth){ if (!auth || !authenticated) {
printf("Authentication error: %s\n", ssh_get_error(session)); printf("Authentication error: %s\n", ssh_get_error(session));
ssh_disconnect(session); ssh_disconnect(session);
return 1; return 1;

View File

@@ -1,3 +1,3 @@
project(headers C) project(libssh-headers-x C)
add_subdirectory(libssh) add_subdirectory(libssh)

View File

@@ -90,6 +90,14 @@ enum ssh_auth_state_e {
SSH_AUTH_STATE_GSSAPI_TOKEN, SSH_AUTH_STATE_GSSAPI_TOKEN,
/** We have sent the MIC and expecting to be authenticated */ /** We have sent the MIC and expecting to be authenticated */
SSH_AUTH_STATE_GSSAPI_MIC_SENT, SSH_AUTH_STATE_GSSAPI_MIC_SENT,
/** We have offered a pubkey to check if it is supported */
SSH_AUTH_STATE_PUBKEY_OFFER_SENT,
/** We have sent pubkey and signature expecting to be authenticated */
SSH_AUTH_STATE_PUBKEY_AUTH_SENT,
/** We have sent a password expecting to be authenticated */
SSH_AUTH_STATE_PASSWORD_AUTH_SENT,
/** We have sent a request without auth information (method 'none') */
SSH_AUTH_STATE_AUTH_NONE_SENT,
}; };
/** @internal /** @internal

View File

@@ -53,6 +53,8 @@ int buffer_add_u32(ssh_buffer buffer, uint32_t data);
int buffer_add_u64(ssh_buffer buffer, uint64_t data); int buffer_add_u64(ssh_buffer buffer, uint64_t data);
int ssh_buffer_add_data(ssh_buffer buffer, const void *data, uint32_t len); int ssh_buffer_add_data(ssh_buffer buffer, const void *data, uint32_t len);
int ssh_buffer_validate_length(struct ssh_buffer_struct *buffer, size_t len);
int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer, int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
const char *format, const char *format,
int argc, int argc,

View File

@@ -58,6 +58,7 @@
#else /* _MSC_VER */ #else /* _MSC_VER */
#include <unistd.h> #include <unistd.h>
#include <inttypes.h> #include <inttypes.h>
#include <sys/types.h>
#endif /* _MSC_VER */ #endif /* _MSC_VER */
#ifdef _WIN32 #ifdef _WIN32
@@ -78,7 +79,7 @@
/* libssh version */ /* libssh version */
#define LIBSSH_VERSION_MAJOR 0 #define LIBSSH_VERSION_MAJOR 0
#define LIBSSH_VERSION_MINOR 7 #define LIBSSH_VERSION_MINOR 7
#define LIBSSH_VERSION_MICRO 0 #define LIBSSH_VERSION_MICRO 7
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \ #define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
LIBSSH_VERSION_MINOR, \ LIBSSH_VERSION_MINOR, \
@@ -443,7 +444,8 @@ LIBSSH_API int ssh_get_publickey(ssh_session session, ssh_key *key);
enum ssh_publickey_hash_type { enum ssh_publickey_hash_type {
SSH_PUBLICKEY_HASH_SHA1, SSH_PUBLICKEY_HASH_SHA1,
SSH_PUBLICKEY_HASH_MD5 SSH_PUBLICKEY_HASH_MD5,
SSH_PUBLICKEY_HASH_SHA256
}; };
LIBSSH_API int ssh_get_publickey_hash(const ssh_key key, LIBSSH_API int ssh_get_publickey_hash(const ssh_key key,
enum ssh_publickey_hash_type type, enum ssh_publickey_hash_type type,
@@ -562,6 +564,10 @@ 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 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 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); LIBSSH_API int ssh_send_ignore (ssh_session session, const char *data);
LIBSSH_API int ssh_send_debug (ssh_session session, const char *message, int always_display); LIBSSH_API int ssh_send_debug (ssh_session session, const char *message, int always_display);
@@ -588,6 +594,7 @@ LIBSSH_API int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socke
fd_set *readfds, struct timeval *timeout); fd_set *readfds, struct timeval *timeout);
LIBSSH_API int ssh_service_request(ssh_session session, const char *service); LIBSSH_API int ssh_service_request(ssh_session session, const char *service);
LIBSSH_API int ssh_set_agent_channel(ssh_session session, ssh_channel channel); LIBSSH_API int ssh_set_agent_channel(ssh_session session, ssh_channel channel);
LIBSSH_API int ssh_set_agent_socket(ssh_session session, socket_t fd);
LIBSSH_API void ssh_set_blocking(ssh_session session, int blocking); LIBSSH_API void ssh_set_blocking(ssh_session session, int blocking);
LIBSSH_API void ssh_set_counters(ssh_session session, ssh_counter scounter, LIBSSH_API void ssh_set_counters(ssh_session session, ssh_counter scounter,
ssh_counter rcounter); ssh_counter rcounter);

View File

@@ -33,15 +33,6 @@ int ssh_analyze_banner(ssh_session session, int server, int *ssh1, int *ssh2);
int ssh_is_ipaddr_v4(const char *str); int ssh_is_ipaddr_v4(const char *str);
int ssh_is_ipaddr(const char *str); int ssh_is_ipaddr(const char *str);
#ifndef HAVE_NTOHLL
/* macro for byte ordering */
uint64_t ntohll(uint64_t);
#endif
#ifndef HAVE_HTONLL
#define htonll(x) ntohll((x))
#endif
/* list processing */ /* list processing */
struct ssh_list { struct ssh_list {

View File

@@ -43,6 +43,12 @@ enum ssh_packet_state_e {
PACKET_STATE_PROCESSING PACKET_STATE_PROCESSING
}; };
enum ssh_packet_filter_result_e {
SSH_PACKET_UNKNOWN,
SSH_PACKET_ALLOWED,
SSH_PACKET_DENIED
};
int packet_send(ssh_session session); int packet_send(ssh_session session);
#ifdef WITH_SSH1 #ifdef WITH_SSH1

View File

@@ -43,6 +43,20 @@
# endif # endif
#endif /* !defined(HAVE_STRTOULL) */ #endif /* !defined(HAVE_STRTOULL) */
#if !defined(HAVE_STRNDUP)
char *strndup(const char *s, size_t n);
#endif /* ! HAVE_STRNDUP */
#ifdef HAVE_BYTESWAP_H
#include <byteswap.h>
#endif
#ifndef bswap_32
#define bswap_32(x) \
((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
(((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
#endif
#ifdef _WIN32 #ifdef _WIN32
/* Imitate define of inttypes.h */ /* Imitate define of inttypes.h */
@@ -60,11 +74,16 @@
# ifdef _MSC_VER # ifdef _MSC_VER
# include <stdio.h> # include <stdio.h>
# include <stdarg.h> /* va_copy define check */
/* On Microsoft compilers define inline to __inline on all others use inline */ /* On Microsoft compilers define inline to __inline on all others use inline */
# undef inline # undef inline
# define inline __inline # define inline __inline
# ifndef va_copy
# define va_copy(dest, src) (dest = src)
# endif
# define strcasecmp _stricmp # define strcasecmp _stricmp
# define strncasecmp _strnicmp # define strncasecmp _strnicmp
# if ! defined(HAVE_ISBLANK) # if ! defined(HAVE_ISBLANK)
@@ -131,10 +150,10 @@ int gettimeofday(struct timeval *__p, void *__t);
#define ERROR_BUFFERLEN 1024 #define ERROR_BUFFERLEN 1024
#endif #endif
#ifndef CLIENTBANNER1 #ifndef CLIENTBANNER1
#define CLIENTBANNER1 "SSH-1.5-libssh-" SSH_STRINGIFY(LIBSSH_VERSION) #define CLIENTBANNER1 "SSH-1.5-libssh_" SSH_STRINGIFY(LIBSSH_VERSION)
#endif #endif
#ifndef CLIENTBANNER2 #ifndef CLIENTBANNER2
#define CLIENTBANNER2 "SSH-2.0-libssh-" SSH_STRINGIFY(LIBSSH_VERSION) #define CLIENTBANNER2 "SSH-2.0-libssh_" SSH_STRINGIFY(LIBSSH_VERSION)
#endif #endif
#ifndef KBDINT_MAX_PROMPT #ifndef KBDINT_MAX_PROMPT
#define KBDINT_MAX_PROMPT 256 /* more than openssh's :) */ #define KBDINT_MAX_PROMPT 256 /* more than openssh's :) */
@@ -346,5 +365,25 @@ int match_hostname(const char *host, const char *pattern, unsigned int len);
#define CLOSE_SOCKET(s) do { if ((s) != SSH_INVALID_SOCKET) { _XCLOSESOCKET(s); (s) = SSH_INVALID_SOCKET;} } while(0) #define CLOSE_SOCKET(s) do { if ((s) != SSH_INVALID_SOCKET) { _XCLOSESOCKET(s); (s) = SSH_INVALID_SOCKET;} } while(0)
#ifndef HAVE_HTONLL
# ifdef WORDS_BIGENDIAN
# define htonll(x) (x)
# else
# define htonll(x) \
(((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
# endif
#endif
#ifndef HAVE_NTOHLL
# ifdef WORDS_BIGENDIAN
# define ntohll(x) (x)
# else
# define ntohll(x) \
(((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
# endif
#endif
void ssh_agent_state_free(void *data);
#endif /* _LIBSSH_PRIV_H */ #endif /* _LIBSSH_PRIV_H */
/* vim: set ts=4 sw=4 et cindent: */ /* vim: set ts=4 sw=4 et cindent: */

View File

@@ -1,12 +1,12 @@
project(libssh-library C) project(libssh-library C)
set(LIBSSH_PUBLIC_INCLUDE_DIRS set(LIBSSH_PUBLIC_INCLUDE_DIRS
${CMAKE_SOURCE_DIR}/include ${libssh_SOURCE_DIR}/include
CACHE INTERNAL "libssh public include directories" CACHE INTERNAL "libssh public include directories"
) )
set(LIBSSH_PRIVATE_INCLUDE_DIRS set(LIBSSH_PRIVATE_INCLUDE_DIRS
${CMAKE_BINARY_DIR} ${libssh_BINARY_DIR}
) )
set(LIBSSH_LINK_LIBRARIES set(LIBSSH_LINK_LIBRARIES
@@ -54,7 +54,7 @@ endif (GCRYPT_LIBRARY)
if (WITH_ZLIB) if (WITH_ZLIB)
set(LIBSSH_PRIVATE_INCLUDE_DIRS set(LIBSSH_PRIVATE_INCLUDE_DIRS
${LIBSSH_PRIVATE_INCLUDE_DIRS} ${LIBSSH_PRIVATE_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIR}
) )
set(LIBSSH_LINK_LIBRARIES set(LIBSSH_LINK_LIBRARIES
@@ -124,7 +124,6 @@ set(libssh_SRCS
kex.c kex.c
known_hosts.c known_hosts.c
legacy.c legacy.c
libcrypto.c
log.c log.c
match.c match.c
messages.c messages.c
@@ -163,7 +162,11 @@ else (WITH_GCRYPT)
set(libssh_SRCS set(libssh_SRCS
${libssh_SRCS} ${libssh_SRCS}
pki_crypto.c pki_crypto.c
libcrypto.c
) )
if(OPENSSL_VERSION VERSION_LESS "1.1.0")
set(libssh_SRCS ${libssh_SRCS} libcrypto-compat.c)
endif()
endif (WITH_GCRYPT) endif (WITH_GCRYPT)
if (WITH_SFTP) if (WITH_SFTP)
@@ -300,6 +303,7 @@ if (WITH_STATIC_LIB)
) )
endif (WITH_STATIC_LIB) endif (WITH_STATIC_LIB)
message(STATUS "Threads_FOUND=${Threads_FOUND}")
if (Threads_FOUND) if (Threads_FOUND)
add_subdirectory(threads) add_subdirectory(threads)
endif (Threads_FOUND) endif (Threads_FOUND)

View File

@@ -185,16 +185,33 @@ int ssh_set_agent_channel(ssh_session session, ssh_channel channel){
return SSH_OK; return SSH_OK;
} }
/** @brief sets the SSH agent socket.
* The SSH agent will be used to authenticate this client using
* the given socket to communicate with the ssh-agent. The caller
* is responsible for connecting to the socket prior to calling
* this function.
* @returns SSH_OK in case of success
* SSH_ERROR in case of an error
*/
int ssh_set_agent_socket(ssh_session session, socket_t fd){
if (!session)
return SSH_ERROR;
if (!session->agent){
ssh_set_error(session, SSH_REQUEST_DENIED, "Session has no active agent");
return SSH_ERROR;
}
ssh_socket_set_fd(session->agent->sock, fd);
return SSH_OK;
}
void agent_close(struct ssh_agent_struct *agent) { void agent_close(struct ssh_agent_struct *agent) {
if (agent == NULL) { if (agent == NULL) {
return; return;
} }
if (getenv("SSH_AUTH_SOCK")) {
ssh_socket_close(agent->sock); ssh_socket_close(agent->sock);
} }
}
void agent_free(ssh_agent agent) { void agent_free(ssh_agent agent) {
if (agent) { if (agent) {
@@ -365,6 +382,9 @@ int ssh_agent_get_ident_count(struct ssh_session_struct *session) {
ssh_buffer_free(reply); ssh_buffer_free(reply);
return -1; return -1;
} }
#ifdef WORDS_BIGENDIAN
type = bswap_32(type);
#endif
SSH_LOG(SSH_LOG_WARN, SSH_LOG(SSH_LOG_WARN,
"Answer type: %d, expected answer: %d", "Answer type: %d, expected answer: %d",
@@ -375,7 +395,7 @@ int ssh_agent_get_ident_count(struct ssh_session_struct *session) {
return 0; return 0;
} else if (type != c2) { } else if (type != c2) {
ssh_set_error(session, SSH_FATAL, ssh_set_error(session, SSH_FATAL,
"Bad authentication reply message type: %d", type); "Bad authentication reply message type: %u", type);
ssh_buffer_free(reply); ssh_buffer_free(reply);
return -1; return -1;
} }
@@ -490,8 +510,8 @@ ssh_string ssh_agent_sign_data(ssh_session session,
ssh_buffer reply; ssh_buffer reply;
ssh_string key_blob; ssh_string key_blob;
ssh_string sig_blob; ssh_string sig_blob;
int type = SSH2_AGENT_FAILURE; unsigned int type = 0;
int flags = 0; unsigned int flags = 0;
uint32_t dlen; uint32_t dlen;
int rc; int rc;
@@ -555,13 +575,19 @@ ssh_string ssh_agent_sign_data(ssh_session session,
ssh_buffer_free(reply); ssh_buffer_free(reply);
return NULL; return NULL;
} }
#ifdef WORDS_BIGENDIAN
type = bswap_32(type);
#endif
if (agent_failed(type)) { if (agent_failed(type)) {
SSH_LOG(SSH_LOG_WARN, "Agent reports failure in signing the key"); SSH_LOG(SSH_LOG_WARN, "Agent reports failure in signing the key");
ssh_buffer_free(reply); ssh_buffer_free(reply);
return NULL; return NULL;
} else if (type != SSH2_AGENT_SIGN_RESPONSE) { } else if (type != SSH2_AGENT_SIGN_RESPONSE) {
ssh_set_error(session, SSH_FATAL, "Bad authentication response: %d", type); ssh_set_error(session,
SSH_FATAL,
"Bad authentication response: %u",
type);
ssh_buffer_free(reply); ssh_buffer_free(reply);
return NULL; return NULL;
} }

76
src/auth.c Normal file → Executable file
View File

@@ -85,6 +85,10 @@ static int ssh_auth_response_termination(void *user){
case SSH_AUTH_STATE_GSSAPI_REQUEST_SENT: case SSH_AUTH_STATE_GSSAPI_REQUEST_SENT:
case SSH_AUTH_STATE_GSSAPI_TOKEN: case SSH_AUTH_STATE_GSSAPI_TOKEN:
case SSH_AUTH_STATE_GSSAPI_MIC_SENT: case SSH_AUTH_STATE_GSSAPI_MIC_SENT:
case SSH_AUTH_STATE_PUBKEY_AUTH_SENT:
case SSH_AUTH_STATE_PUBKEY_OFFER_SENT:
case SSH_AUTH_STATE_PASSWORD_AUTH_SENT:
case SSH_AUTH_STATE_AUTH_NONE_SENT:
return 0; return 0;
default: default:
return 1; return 1;
@@ -137,6 +141,10 @@ static int ssh_userauth_get_response(ssh_session session) {
case SSH_AUTH_STATE_GSSAPI_REQUEST_SENT: case SSH_AUTH_STATE_GSSAPI_REQUEST_SENT:
case SSH_AUTH_STATE_GSSAPI_TOKEN: case SSH_AUTH_STATE_GSSAPI_TOKEN:
case SSH_AUTH_STATE_GSSAPI_MIC_SENT: case SSH_AUTH_STATE_GSSAPI_MIC_SENT:
case SSH_AUTH_STATE_PUBKEY_OFFER_SENT:
case SSH_AUTH_STATE_PUBKEY_AUTH_SENT:
case SSH_AUTH_STATE_PASSWORD_AUTH_SENT:
case SSH_AUTH_STATE_AUTH_NONE_SENT:
case SSH_AUTH_STATE_NONE: case SSH_AUTH_STATE_NONE:
/* not reached */ /* not reached */
rc = SSH_AUTH_ERROR; rc = SSH_AUTH_ERROR;
@@ -209,8 +217,8 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_failure){
"Access denied. Authentication that can continue: %s", "Access denied. Authentication that can continue: %s",
auth_methods); auth_methods);
session->auth_methods = 0;
} }
session->auth_methods = 0;
if (strstr(auth_methods, "password") != NULL) { if (strstr(auth_methods, "password") != NULL) {
session->auth_methods |= SSH_AUTH_METHOD_PASSWORD; session->auth_methods |= SSH_AUTH_METHOD_PASSWORD;
} }
@@ -275,21 +283,27 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_success){
SSH_PACKET_CALLBACK(ssh_packet_userauth_pk_ok){ SSH_PACKET_CALLBACK(ssh_packet_userauth_pk_ok){
int rc; int rc;
SSH_LOG(SSH_LOG_TRACE, "Received SSH_USERAUTH_PK_OK/INFO_REQUEST/GSSAPI_RESPONSE"); SSH_LOG(SSH_LOG_TRACE,
"Received SSH_USERAUTH_PK_OK/INFO_REQUEST/GSSAPI_RESPONSE");
if (session->auth_state == SSH_AUTH_STATE_KBDINT_SENT) { if (session->auth_state == SSH_AUTH_STATE_KBDINT_SENT) {
/* Assuming we are in keyboard-interactive context */ /* Assuming we are in keyboard-interactive context */
SSH_LOG(SSH_LOG_TRACE, SSH_LOG(SSH_LOG_TRACE,
"keyboard-interactive context, assuming SSH_USERAUTH_INFO_REQUEST"); "keyboard-interactive context, "
"assuming SSH_USERAUTH_INFO_REQUEST");
rc = ssh_packet_userauth_info_request(session, type, packet, user); rc = ssh_packet_userauth_info_request(session, type, packet, user);
#ifdef WITH_GSSAPI #ifdef WITH_GSSAPI
} else if (session->auth_state == SSH_AUTH_STATE_GSSAPI_REQUEST_SENT) { } else if (session->auth_state == SSH_AUTH_STATE_GSSAPI_REQUEST_SENT) {
rc = ssh_packet_userauth_gssapi_response(session, type, packet, user); rc = ssh_packet_userauth_gssapi_response(session, type, packet, user);
#endif #endif
} else { } else if (session->auth_state == SSH_AUTH_STATE_PUBKEY_OFFER_SENT) {
session->auth_state = SSH_AUTH_STATE_PK_OK; session->auth_state = SSH_AUTH_STATE_PK_OK;
SSH_LOG(SSH_LOG_TRACE, "Assuming SSH_USERAUTH_PK_OK"); SSH_LOG(SSH_LOG_TRACE, "Assuming SSH_USERAUTH_PK_OK");
rc = SSH_PACKET_USED; rc = SSH_PACKET_USED;
} else {
session->auth_state = SSH_AUTH_STATE_ERROR;
SSH_LOG(SSH_LOG_TRACE, "SSH_USERAUTH_PK_OK received in wrong state");
rc = SSH_PACKET_USED;
} }
return rc; return rc;
@@ -389,7 +403,7 @@ int ssh_userauth_none(ssh_session session, const char *username) {
goto fail; goto fail;
} }
session->auth_state = SSH_AUTH_STATE_NONE; session->auth_state = SSH_AUTH_STATE_AUTH_NONE_SENT;
session->pending_call_state = SSH_PENDING_CALL_AUTH_NONE; session->pending_call_state = SSH_PENDING_CALL_AUTH_NONE;
rc = packet_send(session); rc = packet_send(session);
if (rc == SSH_ERROR) { if (rc == SSH_ERROR) {
@@ -501,7 +515,7 @@ int ssh_userauth_try_publickey(ssh_session session,
ssh_string_free(pubkey_s); ssh_string_free(pubkey_s);
session->auth_state = SSH_AUTH_STATE_NONE; session->auth_state = SSH_AUTH_STATE_PUBKEY_OFFER_SENT;
session->pending_call_state = SSH_PENDING_CALL_AUTH_OFFER_PUBKEY; session->pending_call_state = SSH_PENDING_CALL_AUTH_OFFER_PUBKEY;
rc = packet_send(session); rc = packet_send(session);
if (rc == SSH_ERROR) { if (rc == SSH_ERROR) {
@@ -622,7 +636,7 @@ int ssh_userauth_publickey(ssh_session session,
goto fail; goto fail;
} }
session->auth_state = SSH_AUTH_STATE_NONE; session->auth_state = SSH_AUTH_STATE_PUBKEY_AUTH_SENT;
session->pending_call_state = SSH_PENDING_CALL_AUTH_PUBKEY; session->pending_call_state = SSH_PENDING_CALL_AUTH_PUBKEY;
rc = packet_send(session); rc = packet_send(session);
if (rc == SSH_ERROR) { if (rc == SSH_ERROR) {
@@ -706,7 +720,7 @@ static int ssh_userauth_agent_publickey(ssh_session session,
goto fail; goto fail;
} }
session->auth_state = SSH_AUTH_STATE_NONE; session->auth_state = SSH_AUTH_STATE_PUBKEY_AUTH_SENT;
session->pending_call_state = SSH_PENDING_CALL_AUTH_AGENT; session->pending_call_state = SSH_PENDING_CALL_AUTH_AGENT;
rc = packet_send(session); rc = packet_send(session);
if (rc == SSH_ERROR) { if (rc == SSH_ERROR) {
@@ -740,6 +754,15 @@ struct ssh_agent_state_struct {
char *comment; char *comment;
}; };
/* Internal function */
void ssh_agent_state_free(void *data) {
struct ssh_agent_state_struct *state = data;
if (state) {
ssh_string_free_char(state->comment);
ssh_key_free(state->pubkey);
free (state);
}
}
/** /**
* @brief Try to do public key authentication with ssh agent. * @brief Try to do public key authentication with ssh agent.
@@ -786,6 +809,11 @@ int ssh_userauth_agent(ssh_session session,
state = session->agent_state; state = session->agent_state;
if (state->pubkey == NULL) if (state->pubkey == NULL)
state->pubkey = ssh_agent_get_first_ident(session, &state->comment); state->pubkey = ssh_agent_get_first_ident(session, &state->comment);
if (state->pubkey == NULL) {
return SSH_AUTH_DENIED;
}
while (state->pubkey != NULL) { while (state->pubkey != NULL) {
if(state->state == SSH_AGENT_STATE_NONE){ if(state->state == SSH_AGENT_STATE_NONE){
SSH_LOG(SSH_LOG_DEBUG, SSH_LOG(SSH_LOG_DEBUG,
@@ -795,9 +823,8 @@ int ssh_userauth_agent(ssh_session session,
state->state == SSH_AGENT_STATE_PUBKEY){ state->state == SSH_AGENT_STATE_PUBKEY){
rc = ssh_userauth_try_publickey(session, username, state->pubkey); rc = ssh_userauth_try_publickey(session, username, state->pubkey);
if (rc == SSH_AUTH_ERROR) { if (rc == SSH_AUTH_ERROR) {
ssh_string_free_char(state->comment); ssh_agent_state_free (state);
ssh_key_free(state->pubkey); session->agent_state = NULL;
SAFE_FREE(session->agent_state);
return rc; return rc;
} else if (rc == SSH_AUTH_AGAIN) { } else if (rc == SSH_AUTH_AGAIN) {
state->state = SSH_AGENT_STATE_PUBKEY; state->state = SSH_AGENT_STATE_PUBKEY;
@@ -806,6 +833,7 @@ int ssh_userauth_agent(ssh_session session,
SSH_LOG(SSH_LOG_DEBUG, SSH_LOG(SSH_LOG_DEBUG,
"Public key of %s refused by server", state->comment); "Public key of %s refused by server", state->comment);
ssh_string_free_char(state->comment); ssh_string_free_char(state->comment);
state->comment = NULL;
ssh_key_free(state->pubkey); ssh_key_free(state->pubkey);
state->pubkey = ssh_agent_get_next_ident(session, &state->comment); state->pubkey = ssh_agent_get_next_ident(session, &state->comment);
state->state = SSH_AGENT_STATE_NONE; state->state = SSH_AGENT_STATE_NONE;
@@ -821,23 +849,27 @@ int ssh_userauth_agent(ssh_session session,
if (rc == SSH_AUTH_AGAIN) if (rc == SSH_AUTH_AGAIN)
return rc; return rc;
ssh_string_free_char(state->comment); ssh_string_free_char(state->comment);
ssh_key_free(state->pubkey); state->comment = NULL;
if (rc == SSH_AUTH_ERROR) { if (rc == SSH_AUTH_ERROR) {
SAFE_FREE(session->agent_state); ssh_agent_state_free (session->agent_state);
session->agent_state = NULL;
return rc; return rc;
} else if (rc != SSH_AUTH_SUCCESS) { } else if (rc != SSH_AUTH_SUCCESS) {
SSH_LOG(SSH_LOG_INFO, SSH_LOG(SSH_LOG_INFO,
"Server accepted public key but refused the signature"); "Server accepted public key but refused the signature");
ssh_key_free(state->pubkey);
state->pubkey = ssh_agent_get_next_ident(session, &state->comment); state->pubkey = ssh_agent_get_next_ident(session, &state->comment);
state->state = SSH_AGENT_STATE_NONE; state->state = SSH_AGENT_STATE_NONE;
continue; continue;
} }
SAFE_FREE(session->agent_state); ssh_agent_state_free (session->agent_state);
session->agent_state = NULL;
return SSH_AUTH_SUCCESS; return SSH_AUTH_SUCCESS;
} }
} }
SAFE_FREE(session->agent_state); ssh_agent_state_free (session->agent_state);
session->agent_state = NULL;
return rc; return rc;
} }
#endif #endif
@@ -1045,15 +1077,14 @@ int ssh_userauth_publickey_auto(ssh_session session,
ssh_key_free(state->privkey); ssh_key_free(state->privkey);
ssh_key_free(state->pubkey); ssh_key_free(state->pubkey);
SAFE_FREE(session->auth_auto_state); SAFE_FREE(session->auth_auto_state);
} if (rc == SSH_AUTH_SUCCESS) {
if (rc == SSH_AUTH_ERROR) {
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
SSH_LOG(SSH_LOG_INFO, SSH_LOG(SSH_LOG_INFO,
"Successfully authenticated using %s", "Successfully authenticated using %s",
privkey_file); privkey_file);
}
return rc; return rc;
} else if (rc == SSH_AUTH_AGAIN){ }
if (rc == SSH_AUTH_AGAIN){
return rc; return rc;
} }
@@ -1146,7 +1177,7 @@ int ssh_userauth_password(ssh_session session,
goto fail; goto fail;
} }
session->auth_state = SSH_AUTH_STATE_NONE; session->auth_state = SSH_AUTH_STATE_PASSWORD_AUTH_SENT;
session->pending_call_state = SSH_PENDING_CALL_AUTH_OFFER_PUBKEY; session->pending_call_state = SSH_PENDING_CALL_AUTH_OFFER_PUBKEY;
rc = packet_send(session); rc = packet_send(session);
if (rc == SSH_ERROR) { if (rc == SSH_ERROR) {
@@ -1200,11 +1231,10 @@ int ssh_userauth_agent_pubkey(ssh_session session,
ssh_kbdint ssh_kbdint_new(void) { ssh_kbdint ssh_kbdint_new(void) {
ssh_kbdint kbd; ssh_kbdint kbd;
kbd = malloc(sizeof(struct ssh_kbdint_struct)); kbd = calloc(1, sizeof(struct ssh_kbdint_struct));
if (kbd == NULL) { if (kbd == NULL) {
return NULL; return NULL;
} }
ZERO_STRUCTP(kbd);
return kbd; return kbd;
} }

View File

@@ -23,6 +23,7 @@
#include "config.h" #include "config.h"
#include <errno.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@@ -117,6 +118,7 @@ static int send_username(ssh_session session, const char *username) {
if (packet_send(session) == SSH_ERROR) { if (packet_send(session) == SSH_ERROR) {
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
} }
return SSH_AUTH_AGAIN;
pending: pending:
rc = wait_auth1_status(session); rc = wait_auth1_status(session);
switch (rc){ switch (rc){
@@ -161,12 +163,14 @@ int ssh_userauth1_password(ssh_session session, const char *username,
ssh_string pwd = NULL; ssh_string pwd = NULL;
int rc; int rc;
if (session->pending_call_state == SSH_PENDING_CALL_AUTH_PASSWORD) {
goto pending;
}
rc = send_username(session, username); rc = send_username(session, username);
if (rc != SSH_AUTH_DENIED) { if (rc != SSH_AUTH_DENIED) {
return rc; return rc;
} }
if (session->pending_call_state == SSH_PENDING_CALL_AUTH_PASSWORD)
goto pending;
/* we trick a bit here. A known flaw in SSH1 protocol is that it's /* we trick a bit here. A known flaw in SSH1 protocol is that it's
* easy to guess password sizes. * easy to guess password sizes.
* not that sure ... * not that sure ...
@@ -219,8 +223,11 @@ int ssh_userauth1_password(ssh_session session, const char *username,
} }
pending: pending:
rc = wait_auth1_status(session); rc = wait_auth1_status(session);
if (rc != SSH_AUTH_AGAIN) if (rc == SSH_AUTH_ERROR && errno == EAGAIN) {
/* Nothing to do */
} else if (rc != SSH_AUTH_AGAIN) {
session->pending_call_state = SSH_PENDING_CALL_NONE; session->pending_call_state = SSH_PENDING_CALL_NONE;
}
return rc; return rc;
} }

View File

@@ -103,5 +103,9 @@ void ssh_print_bignum(const char *which, bignum num) {
#endif #endif
fprintf(stderr, "%s value: ", which); fprintf(stderr, "%s value: ", which);
fprintf(stderr, "%s\n", (hex == NULL) ? "(null)" : (char *) hex); fprintf(stderr, "%s\n", (hex == NULL) ? "(null)" : (char *) hex);
#ifdef HAVE_LIBGCRYPT
SAFE_FREE(hex); SAFE_FREE(hex);
#elif defined HAVE_LIBCRYPTO
OPENSSL_free(hex);
#endif
} }

View File

@@ -563,11 +563,14 @@ uint32_t buffer_pass_bytes_end(struct ssh_buffer_struct *buffer, uint32_t len){
* @returns 0 if there is not enough data in buffer, len otherwise. * @returns 0 if there is not enough data in buffer, len otherwise.
*/ */
uint32_t buffer_get_data(struct ssh_buffer_struct *buffer, void *data, uint32_t len){ uint32_t buffer_get_data(struct ssh_buffer_struct *buffer, void *data, uint32_t len){
int rc;
/* /*
* Check for a integer overflow first, then check if not enough data is in * Check for a integer overflow first, then check if not enough data is in
* the buffer. * the buffer.
*/ */
if (buffer->pos + len < len || buffer->pos + len > buffer->used) { rc = ssh_buffer_validate_length(buffer, len);
if (rc != SSH_OK) {
return 0; return 0;
} }
memcpy(data,buffer->data+buffer->pos,len); memcpy(data,buffer->data+buffer->pos,len);
@@ -617,6 +620,24 @@ int buffer_get_u64(struct ssh_buffer_struct *buffer, uint64_t *data){
return buffer_get_data(buffer,data,sizeof(uint64_t)); return buffer_get_data(buffer,data,sizeof(uint64_t));
} }
/**
* @brief Valdiates that the given length can be obtained from the buffer.
*
* @param[in] buffer The buffer to read from.
*
* @param[in] len The length to be checked.
*
* @return SSH_OK if the length is valid, SSH_ERROR otherwise.
*/
int ssh_buffer_validate_length(struct ssh_buffer_struct *buffer, size_t len)
{
if (buffer->pos + len < len || buffer->pos + len > buffer->used) {
return SSH_ERROR;
}
return SSH_OK;
}
/** /**
* @internal * @internal
* *
@@ -630,13 +651,15 @@ struct ssh_string_struct *buffer_get_ssh_string(struct ssh_buffer_struct *buffer
uint32_t stringlen; uint32_t stringlen;
uint32_t hostlen; uint32_t hostlen;
struct ssh_string_struct *str = NULL; struct ssh_string_struct *str = NULL;
int rc;
if (buffer_get_u32(buffer, &stringlen) == 0) { if (buffer_get_u32(buffer, &stringlen) == 0) {
return NULL; return NULL;
} }
hostlen = ntohl(stringlen); hostlen = ntohl(stringlen);
/* verify if there is enough space in buffer to get it */ /* verify if there is enough space in buffer to get it */
if (buffer->pos + hostlen < hostlen || buffer->pos + hostlen > buffer->used) { rc = ssh_buffer_validate_length(buffer, hostlen);
if (rc != SSH_OK) {
return NULL; /* it is indeed */ return NULL; /* it is indeed */
} }
str = ssh_string_new(hostlen); str = ssh_string_new(hostlen);
@@ -867,11 +890,13 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
char **cstring; char **cstring;
void **data; void **data;
} o; } o;
size_t len, rlen; size_t len, rlen, max_len;
uint32_t u32len; uint32_t u32len;
va_list ap_copy; va_list ap_copy;
int count; int count;
max_len = ssh_buffer_get_len(buffer);
/* copy the argument list in case a rollback is needed */ /* copy the argument list in case a rollback is needed */
va_copy(ap_copy, ap); va_copy(ap_copy, ap);
@@ -921,10 +946,16 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
break; break;
} }
len = ntohl(u32len); len = ntohl(u32len);
if (len > UINT_MAX - 1){ if (len > max_len - 1) {
rc = SSH_ERROR; rc = SSH_ERROR;
break; break;
} }
rc = ssh_buffer_validate_length(buffer, len);
if (rc != SSH_OK) {
break;
}
*o.cstring = malloc(len + 1); *o.cstring = malloc(len + 1);
if (*o.cstring == NULL){ if (*o.cstring == NULL){
rc = SSH_ERROR; rc = SSH_ERROR;
@@ -942,6 +973,15 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
break; break;
case 'P': case 'P':
len = va_arg(ap, size_t); len = va_arg(ap, size_t);
if (len > max_len - 1) {
rc = SSH_ERROR;
break;
}
rc = ssh_buffer_validate_length(buffer, len);
if (rc != SSH_OK) {
break;
}
o.data = va_arg(ap, void **); o.data = va_arg(ap, void **);
count++; count++;

View File

@@ -170,6 +170,15 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_open_conf){
"Received a CHANNEL_OPEN_CONFIRMATION for channel %d:%d", "Received a CHANNEL_OPEN_CONFIRMATION for channel %d:%d",
channel->local_channel, channel->local_channel,
channel->remote_channel); channel->remote_channel);
if (channel->state != SSH_CHANNEL_STATE_OPENING) {
SSH_LOG(SSH_LOG_RARE,
"SSH2_MSG_CHANNEL_OPEN_CONFIRMATION received in incorrect "
"channel state %d",
channel->state);
goto error;
}
SSH_LOG(SSH_LOG_PROTOCOL, SSH_LOG(SSH_LOG_PROTOCOL,
"Remote window : %lu, maxpacket : %lu", "Remote window : %lu, maxpacket : %lu",
(long unsigned int) channel->remote_window, (long unsigned int) channel->remote_window,
@@ -210,6 +219,14 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_open_fail){
return SSH_PACKET_USED; return SSH_PACKET_USED;
} }
if (channel->state != SSH_CHANNEL_STATE_OPENING) {
SSH_LOG(SSH_LOG_RARE,
"SSH2_MSG_CHANNEL_OPEN_FAILURE received in incorrect channel "
"state %d",
channel->state);
goto error;
}
ssh_set_error(session, SSH_REQUEST_DENIED, ssh_set_error(session, SSH_REQUEST_DENIED,
"Channel opening failure: channel %u error (%lu) %s", "Channel opening failure: channel %u error (%lu) %s",
channel->local_channel, channel->local_channel,
@@ -217,6 +234,9 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_open_fail){
error); error);
SAFE_FREE(error); SAFE_FREE(error);
channel->state=SSH_CHANNEL_STATE_OPEN_DENIED; channel->state=SSH_CHANNEL_STATE_OPEN_DENIED;
error:
ssh_set_error(session, SSH_FATAL, "Invalid packet");
return SSH_PACKET_USED; return SSH_PACKET_USED;
} }
@@ -664,10 +684,8 @@ SSH_PACKET_CALLBACK(channel_rcv_request) {
} }
if (strcmp(request,"exit-status") == 0) { if (strcmp(request,"exit-status") == 0) {
uint32_t exit_status = 0;
SAFE_FREE(request); SAFE_FREE(request);
rc = ssh_buffer_unpack(packet, "d", &exit_status); rc = ssh_buffer_unpack(packet, "d", &channel->exit_status);
SSH_LOG(SSH_LOG_PACKET, "received exit-status %d", channel->exit_status); SSH_LOG(SSH_LOG_PACKET, "received exit-status %d", channel->exit_status);
if(ssh_callbacks_exists(channel->callbacks, channel_exit_status_function)) { if(ssh_callbacks_exists(channel->callbacks, channel_exit_status_function)) {
@@ -714,7 +732,7 @@ SSH_PACKET_CALLBACK(channel_rcv_request) {
SAFE_FREE(request); SAFE_FREE(request);
rc = ssh_buffer_unpack(packet, "sbs", rc = ssh_buffer_unpack(packet, "sbss",
&sig, /* signal name */ &sig, /* signal name */
&core_dumped, /* core dumped */ &core_dumped, /* core dumped */
&errmsg, /* error message */ &errmsg, /* error message */
@@ -1247,7 +1265,7 @@ static int channel_write_common(ssh_channel channel,
return -1; return -1;
} }
if (channel->session->session_state == SSH_SESSION_STATE_ERROR) { if (session->session_state == SSH_SESSION_STATE_ERROR) {
return SSH_ERROR; return SSH_ERROR;
} }
#ifdef WITH_SSH1 #ifdef WITH_SSH1
@@ -1278,7 +1296,7 @@ static int channel_write_common(ssh_channel channel,
ssh_channel_waitwindow_termination,channel); ssh_channel_waitwindow_termination,channel);
if (rc == SSH_ERROR || if (rc == SSH_ERROR ||
!ssh_channel_waitwindow_termination(channel) || !ssh_channel_waitwindow_termination(channel) ||
channel->session->session_state == SSH_SESSION_STATE_ERROR || session->session_state == SSH_SESSION_STATE_ERROR ||
channel->state == SSH_CHANNEL_STATE_CLOSED) channel->state == SSH_CHANNEL_STATE_CLOSED)
goto out; goto out;
continue; continue;
@@ -2205,6 +2223,11 @@ error:
return rc; return rc;
} }
/* DEPRECATED */
int ssh_forward_listen(ssh_session session, const char *address, int port, int *bound_port) {
return ssh_channel_listen_forward(session, address, port, bound_port);
}
/* DEPRECATED */ /* DEPRECATED */
ssh_channel ssh_forward_accept(ssh_session session, int timeout_ms) { ssh_channel ssh_forward_accept(ssh_session session, int timeout_ms) {
return ssh_channel_accept(session, SSH_CHANNEL_FORWARDED_TCPIP, timeout_ms, NULL); return ssh_channel_accept(session, SSH_CHANNEL_FORWARDED_TCPIP, timeout_ms, NULL);
@@ -2272,6 +2295,7 @@ error:
return rc; return rc;
} }
/* DEPRECATED */
int ssh_forward_cancel(ssh_session session, const char *address, int port) { int ssh_forward_cancel(ssh_session session, const char *address, int port) {
return ssh_channel_cancel_forward(session, address, port); return ssh_channel_cancel_forward(session, address, port);
} }
@@ -2685,7 +2709,7 @@ int ssh_channel_read_timeout(ssh_channel channel,
if (rc == SSH_ERROR){ if (rc == SSH_ERROR){
return rc; return rc;
} }
if (channel->session->session_state == SSH_SESSION_STATE_ERROR){ if (session->session_state == SSH_SESSION_STATE_ERROR){
return SSH_ERROR; return SSH_ERROR;
} }
if (channel->remote_eof && buffer_get_rest_len(stdbuf) == 0) { if (channel->remote_eof && buffer_get_rest_len(stdbuf) == 0) {
@@ -2750,7 +2774,7 @@ int ssh_channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count
to_read = ssh_channel_poll(channel, is_stderr); to_read = ssh_channel_poll(channel, is_stderr);
if (to_read <= 0) { if (to_read <= 0) {
if (channel->session->session_state == SSH_SESSION_STATE_ERROR){ if (session->session_state == SSH_SESSION_STATE_ERROR){
return SSH_ERROR; return SSH_ERROR;
} }

View File

@@ -90,7 +90,8 @@ static void socket_callback_connected(int code, int errno_code, void *user){
* @param user is a pointer to session * @param user is a pointer to session
* @returns Number of bytes processed, or zero if the banner is not complete. * @returns Number of bytes processed, or zero if the banner is not complete.
*/ */
static int callback_receive_banner(const void *data, size_t len, void *user) { static int callback_receive_banner(const void *data, size_t len, void *user)
{
char *buffer = (char *)data; char *buffer = (char *)data;
ssh_session session=(ssh_session) user; ssh_session session=(ssh_session) user;
char *str = NULL; char *str = NULL;
@@ -98,21 +99,32 @@ static int callback_receive_banner(const void *data, size_t len, void *user) {
int ret=0; int ret=0;
if (session->session_state != SSH_SESSION_STATE_SOCKET_CONNECTED) { if (session->session_state != SSH_SESSION_STATE_SOCKET_CONNECTED) {
ssh_set_error(session,SSH_FATAL,"Wrong state in callback_receive_banner : %d",session->session_state); ssh_set_error(session,SSH_FATAL,
"Wrong state in callback_receive_banner : %d",
session->session_state);
return SSH_ERROR; return SSH_ERROR;
} }
for (i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
#ifdef WITH_PCAP #ifdef WITH_PCAP
if (session->pcap_ctx && buffer[i] == '\n') { if (session->pcap_ctx && buffer[i] == '\n') {
ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_IN,buffer,i+1,i+1); ssh_pcap_context_write(session->pcap_ctx,
SSH_PCAP_DIR_IN,
buffer,i+1,
i+1);
} }
#endif #endif
if (buffer[i] == '\r') { if (buffer[i] == '\r') {
buffer[i] = '\0'; buffer[i] = '\0';
} }
if (buffer[i] == '\n') { if (buffer[i] == '\n') {
int cmp;
buffer[i] = '\0'; buffer[i] = '\0';
/* The server MAY send other lines of data... */
cmp = strncmp(buffer, "SSH-", 4);
if (cmp == 0) {
str = strdup(buffer); str = strdup(buffer);
if (str == NULL) { if (str == NULL) {
return SSH_ERROR; return SSH_ERROR;
@@ -125,11 +137,21 @@ static int callback_receive_banner(const void *data, size_t len, void *user) {
session->ssh_connection_callback(session); session->ssh_connection_callback(session);
return ret; return ret;
} else {
SSH_LOG(SSH_LOG_DEBUG,
"ssh_protocol_version_exchange: %s",
buffer);
ret = i + 1;
break;
} }
if(i>127){ }
/* According to RFC 4253 the max banner length is 255 */
if (i > 255) {
/* Too big banner */ /* Too big banner */
session->session_state=SSH_SESSION_STATE_ERROR; session->session_state=SSH_SESSION_STATE_ERROR;
ssh_set_error(session,SSH_FATAL,"Receiving banner: too large banner"); ssh_set_error(session,
SSH_FATAL,
"Receiving banner: too large banner");
return 0; return 0;
} }
@@ -147,46 +169,75 @@ static int callback_receive_banner(const void *data, size_t len, void *user) {
* *
* @return 0 on success, < 0 on error. * @return 0 on success, < 0 on error.
*/ */
int ssh_send_banner(ssh_session session, int server) { int ssh_send_banner(ssh_session session, int server)
{
const char *banner = NULL; const char *banner = NULL;
char buffer[128] = {0}; const char *terminator = NULL;
int err=SSH_ERROR; /* The maximum banner length is 255 for SSH2 */
char buffer[256] = {0};
size_t len;
int rc = SSH_ERROR;
banner = session->version == 1 ? CLIENTBANNER1 : CLIENTBANNER2; banner = session->version == 1 ? CLIENTBANNER1 : CLIENTBANNER2;
terminator = session->version == 1 ? "\n" : "\r\n";
if (server) { if (server == 1) {
if (session->opts.custombanner == NULL){ if (session->opts.custombanner == NULL){
len = strlen(banner);
session->serverbanner = strdup(banner); session->serverbanner = strdup(banner);
} else {
session->serverbanner = malloc(strlen(session->opts.custombanner) + 9);
if(!session->serverbanner)
goto end;
strcpy(session->serverbanner, "SSH-2.0-");
strcat(session->serverbanner, session->opts.custombanner);
}
if (session->serverbanner == NULL) { if (session->serverbanner == NULL) {
goto end; goto end;
} }
snprintf(buffer, 128, "%s\n", session->serverbanner); } else {
len = strlen(session->opts.custombanner);
session->serverbanner = malloc(len + 8 + 1);
if(session->serverbanner == NULL) {
goto end;
}
snprintf(session->serverbanner,
len + 8 + 1,
"SSH-2.0-%s",
session->opts.custombanner);
}
snprintf(buffer,
sizeof(buffer),
"%s%s",
session->serverbanner,
terminator);
} else { } else {
session->clientbanner = strdup(banner); session->clientbanner = strdup(banner);
if (session->clientbanner == NULL) { if (session->clientbanner == NULL) {
goto end; goto end;
} }
snprintf(buffer, 128, "%s\n", session->clientbanner);
/* SSH version 1 has a banner length of 128 only */
len = session->version == 1 ? 128 : 0;
snprintf(buffer,
sizeof(buffer) - len,
"%s%s",
session->clientbanner,
terminator);
} }
if (ssh_socket_write(session->socket, buffer, strlen(buffer)) == SSH_ERROR) { rc = ssh_socket_write(session->socket, buffer, strlen(buffer));
if (rc == SSH_ERROR) {
goto end; goto end;
} }
#ifdef WITH_PCAP #ifdef WITH_PCAP
if(session->pcap_ctx) if (session->pcap_ctx != NULL) {
ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_OUT,buffer,strlen(buffer),strlen(buffer)); ssh_pcap_context_write(session->pcap_ctx,
SSH_PCAP_DIR_OUT,
buffer,
strlen(buffer),
strlen(buffer));
}
#endif #endif
err=SSH_OK;
end:
return err; rc = SSH_OK;
end:
return rc;
} }
/** @internal /** @internal
@@ -335,7 +386,13 @@ static void ssh_client_connection_callback(ssh_session session){
switch(session->session_state){ switch(session->session_state){
case SSH_SESSION_STATE_NONE: case SSH_SESSION_STATE_NONE:
case SSH_SESSION_STATE_CONNECTING: case SSH_SESSION_STATE_CONNECTING:
break;
case SSH_SESSION_STATE_SOCKET_CONNECTED: case SSH_SESSION_STATE_SOCKET_CONNECTED:
/* If SSHv1 is disabled, we can send the banner immedietly */
if (session->opts.ssh1 == 0) {
ssh_set_fd_towrite(session);
ssh_send_banner(session, 0);
}
break; break;
case SSH_SESSION_STATE_BANNER_RECEIVED: case SSH_SESSION_STATE_BANNER_RECEIVED:
if (session->serverbanner == NULL) { if (session->serverbanner == NULL) {
@@ -381,7 +438,9 @@ static void ssh_client_connection_callback(ssh_session session){
#endif #endif
ssh_packet_set_default_callbacks(session); ssh_packet_set_default_callbacks(session);
session->session_state=SSH_SESSION_STATE_INITIAL_KEX; session->session_state=SSH_SESSION_STATE_INITIAL_KEX;
if (session->opts.ssh1 == 1) {
ssh_send_banner(session, 0); ssh_send_banner(session, 0);
}
set_status(session, 0.5f); set_status(session, 0.5f);
break; break;
case SSH_SESSION_STATE_INITIAL_KEX: case SSH_SESSION_STATE_INITIAL_KEX:

View File

@@ -50,6 +50,8 @@ enum ssh_config_opcode_e {
SOC_GSSAPISERVERIDENTITY, SOC_GSSAPISERVERIDENTITY,
SOC_GSSAPICLIENTIDENTITY, SOC_GSSAPICLIENTIDENTITY,
SOC_GSSAPIDELEGATECREDENTIALS, SOC_GSSAPIDELEGATECREDENTIALS,
SOC_END /* Keep this one last in the list */
}; };
struct ssh_config_keyword_table_s { struct ssh_config_keyword_table_s {
@@ -185,7 +187,7 @@ static int ssh_config_get_yesno(char **str, int notfound) {
} }
static int ssh_config_parse_line(ssh_session session, const char *line, static int ssh_config_parse_line(ssh_session session, const char *line,
unsigned int count, int *parsing) { unsigned int count, int *parsing, int seen[]) {
enum ssh_config_opcode_e opcode; enum ssh_config_opcode_e opcode;
const char *p; const char *p;
char *s, *x; char *s, *x;
@@ -216,32 +218,43 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
} }
opcode = ssh_config_get_opcode(keyword); opcode = ssh_config_get_opcode(keyword);
if (*parsing == 1 && opcode != SOC_HOST) {
if (seen[opcode] != 0) {
return 0;
}
seen[opcode] = 1;
}
switch (opcode) { switch (opcode) {
case SOC_HOST: case SOC_HOST: {
int ok = 0;
*parsing = 0; *parsing = 0;
lowerhost = (session->opts.host) ? ssh_lowercase(session->opts.host) : NULL; lowerhost = (session->opts.host) ? ssh_lowercase(session->opts.host) : NULL;
for (p = ssh_config_get_str_tok(&s, NULL); for (p = ssh_config_get_str_tok(&s, NULL);
p != NULL && p[0] != '\0'; p != NULL && p[0] != '\0';
p = ssh_config_get_str_tok(&s, NULL)) { p = ssh_config_get_str_tok(&s, NULL)) {
char *z = ssh_path_expand_escape(session, p); if (ok >= 0) {
int ok; ok = match_hostname(lowerhost, p, strlen(p));
if (ok < 0) {
if (z == NULL) { *parsing = 0;
z = strdup(p); } else if (ok > 0) {
}
ok = match_hostname(lowerhost, z, strlen(z));
if (ok) {
*parsing = 1; *parsing = 1;
} }
free(z); }
} }
SAFE_FREE(lowerhost); SAFE_FREE(lowerhost);
break; break;
}
case SOC_HOSTNAME: case SOC_HOSTNAME:
p = ssh_config_get_str_tok(&s, NULL); p = ssh_config_get_str_tok(&s, NULL);
if (p && *parsing) { if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_HOST, p); char *z = ssh_path_expand_escape(session, p);
if (z == NULL) {
z = strdup(p);
}
ssh_options_set(session, SSH_OPTIONS_HOST, z);
free(z);
} }
break; break;
case SOC_PORT: case SOC_PORT:
@@ -378,6 +391,7 @@ int ssh_config_parse_file(ssh_session session, const char *filename) {
unsigned int count = 0; unsigned int count = 0;
FILE *f; FILE *f;
int parsing; int parsing;
int seen[SOC_END - SOC_UNSUPPORTED] = {0};
if ((f = fopen(filename, "r")) == NULL) { if ((f = fopen(filename, "r")) == NULL) {
return 0; return 0;
@@ -388,7 +402,7 @@ int ssh_config_parse_file(ssh_session session, const char *filename) {
parsing = 1; parsing = 1;
while (fgets(line, sizeof(line), f)) { while (fgets(line, sizeof(line), f)) {
count++; count++;
if (ssh_config_parse_line(session, line, count, &parsing) < 0) { if (ssh_config_parse_line(session, line, count, &parsing, seen) < 0) {
fclose(f); fclose(f);
return -1; return -1;
} }

179
src/dh.c
View File

@@ -227,15 +227,21 @@ void ssh_crypto_finalize(void) {
} }
int dh_generate_x(ssh_session session) { int 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(); session->next_crypto->x = bignum_new();
if (session->next_crypto->x == NULL) { if (session->next_crypto->x == NULL) {
return -1; return -1;
} }
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
bignum_rand(session->next_crypto->x, 128); bignum_rand(session->next_crypto->x, keysize);
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
bignum_rand(session->next_crypto->x, 128, 0, -1); bignum_rand(session->next_crypto->x, keysize, -1, 0);
#endif #endif
/* not harder than this */ /* not harder than this */
@@ -248,15 +254,21 @@ int dh_generate_x(ssh_session session) {
/* used by server */ /* used by server */
int dh_generate_y(ssh_session session) { int 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(); session->next_crypto->y = bignum_new();
if (session->next_crypto->y == NULL) { if (session->next_crypto->y == NULL) {
return -1; return -1;
} }
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
bignum_rand(session->next_crypto->y, 128); bignum_rand(session->next_crypto->y, keysize);
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
bignum_rand(session->next_crypto->y, 128, 0, -1); bignum_rand(session->next_crypto->y, keysize, -1, 0);
#endif #endif
/* not harder than this */ /* not harder than this */
@@ -1027,6 +1039,29 @@ int ssh_get_publickey_hash(const ssh_key key,
*hlen = SHA_DIGEST_LEN; *hlen = SHA_DIGEST_LEN;
} }
break; break;
case SSH_PUBLICKEY_HASH_SHA256:
{
SHA256CTX ctx;
h = malloc(SHA256_DIGEST_LEN);
if (h == NULL) {
rc = -1;
goto out;
}
ctx = sha256_init();
if (ctx == NULL) {
free(h);
rc = -1;
goto out;
}
sha256_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
sha256_final(h, ctx);
*hlen = SHA256_DIGEST_LEN;
}
break;
case SSH_PUBLICKEY_HASH_MD5: case SSH_PUBLICKEY_HASH_MD5:
{ {
MD5CTX ctx; MD5CTX ctx;
@@ -1062,6 +1097,38 @@ out:
return rc; return rc;
} }
/**
* @internal
*
* @brief Convert a buffer into an unpadded base64 string.
* The caller has to free the memory.
*
* @param hash What should be converted to a base64 string.
*
* @param len Length of the buffer to convert.
*
* @return The base64 string or NULL on error.
*
* @see ssh_string_free_char()
*/
static char *ssh_get_b64_unpadded(const unsigned char *hash, size_t len)
{
char *b64_padded = NULL;
char *b64_unpadded = NULL;
size_t k;
b64_padded = (char *)bin_to_base64(hash, (int)len);
if (b64_padded == NULL) {
return NULL;
}
for (k = strlen(b64_padded); k != 0 && b64_padded[k-1] == '='; k--);
b64_unpadded = strndup(b64_padded, k);
SAFE_FREE(b64_padded);
return b64_unpadded;
}
/** /**
* @brief Convert a buffer into a colon separated hex string. * @brief Convert a buffer into a colon separated hex string.
* The caller has to free the memory. * The caller has to free the memory.
@@ -1099,6 +1166,110 @@ char *ssh_get_hexa(const unsigned char *what, size_t len) {
return hexa; 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.
*
* This function prints hex strings if the given hash is a md5 sum.
* But prints unpadded base64 strings for sha sums.
* 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.
*/
void ssh_print_hash(enum ssh_publickey_hash_type type,
unsigned char *hash,
size_t len)
{
char *fingerprint = NULL;
fingerprint = ssh_get_fingerprint_hash(type,
hash,
len);
if (fingerprint == NULL) {
return;
}
fprintf(stderr, "%s\n", fingerprint);
SAFE_FREE(fingerprint);
}
/** /**
* @brief Print a buffer as colon separated hex string. * @brief Print a buffer as colon separated hex string.
* *

View File

@@ -120,6 +120,7 @@ static int ssh_gssapi_send_response(ssh_session session, ssh_string oid){
ssh_set_error_oom(session); ssh_set_error_oom(session);
return SSH_ERROR; return SSH_ERROR;
} }
session->auth_state = SSH_AUTH_STATE_GSSAPI_TOKEN;
packet_send(session); packet_send(session);
SSH_LOG(SSH_LOG_PACKET, SSH_LOG(SSH_LOG_PACKET,
@@ -129,11 +130,53 @@ static int ssh_gssapi_send_response(ssh_session session, ssh_string oid){
#endif /* WITH_SERVER */ #endif /* WITH_SERVER */
static void ssh_gssapi_log_error(int verb, const char *msg, int maj_stat){ static void ssh_gssapi_log_error(int verb,
gss_buffer_desc buffer; const char *msg,
OM_uint32 dummy, message_context; int maj_stat,
gss_display_status(&dummy,maj_stat,GSS_C_GSS_CODE, GSS_C_NO_OID, &message_context, &buffer); int min_stat)
SSH_LOG(verb, "GSSAPI(%s): %s", msg, (const char *)buffer.value); {
gss_buffer_desc msg_maj = {
.length = 0,
};
gss_buffer_desc msg_min = {
.length = 0,
};
OM_uint32 dummy_maj, dummy_min;
OM_uint32 message_context = 0;
dummy_maj = gss_display_status(&dummy_min,
maj_stat,
GSS_C_GSS_CODE,
GSS_C_NO_OID,
&message_context,
&msg_maj);
if (dummy_maj != 0) {
goto out;
}
dummy_maj = gss_display_status(&dummy_min,
min_stat,
GSS_C_MECH_CODE,
GSS_C_NO_OID,
&message_context,
&msg_min);
if (dummy_maj != 0) {
goto out;
}
SSH_LOG(verb,
"GSSAPI(%s): %s - %s",
msg,
(const char *)msg_maj.value,
(const char *)msg_min.value);
out:
if (msg_maj.value) {
dummy_maj = gss_release_buffer(&dummy_min, &msg_maj);
}
if (msg_min.value) {
dummy_maj = gss_release_buffer(&dummy_min, &msg_min);
}
} }
#ifdef WITH_SERVER #ifdef WITH_SERVER
@@ -212,7 +255,10 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n
(gss_OID) GSS_C_NT_HOSTBASED_SERVICE, &server_name); (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, &server_name);
if (maj_stat != GSS_S_COMPLETE) { if (maj_stat != GSS_S_COMPLETE) {
SSH_LOG(SSH_LOG_WARNING, "importing name %d, %d", maj_stat, min_stat); SSH_LOG(SSH_LOG_WARNING, "importing name %d, %d", maj_stat, min_stat);
ssh_gssapi_log_error(SSH_LOG_WARNING, "importing name", maj_stat); ssh_gssapi_log_error(SSH_LOG_WARNING,
"importing name",
maj_stat,
min_stat);
return -1; return -1;
} }
@@ -224,7 +270,10 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n
if (maj_stat != GSS_S_COMPLETE) { if (maj_stat != GSS_S_COMPLETE) {
SSH_LOG(SSH_LOG_WARNING, "error acquiring credentials %d, %d", maj_stat, min_stat); SSH_LOG(SSH_LOG_WARNING, "error acquiring credentials %d, %d", maj_stat, min_stat);
ssh_gssapi_log_error(SSH_LOG_WARNING, "acquiring creds", maj_stat); ssh_gssapi_log_error(SSH_LOG_WARNING,
"acquiring creds",
maj_stat,
min_stat);
ssh_auth_reply_default(session,0); ssh_auth_reply_default(session,0);
return SSH_ERROR; return SSH_ERROR;
} }
@@ -266,7 +315,10 @@ static char *ssh_gssapi_name_to_char(gss_name_t name){
OM_uint32 maj_stat, min_stat; OM_uint32 maj_stat, min_stat;
char *ptr; char *ptr;
maj_stat = gss_display_name(&min_stat, name, &buffer, NULL); maj_stat = gss_display_name(&min_stat, name, &buffer, NULL);
ssh_gssapi_log_error(SSH_LOG_WARNING, "converting name", maj_stat); ssh_gssapi_log_error(SSH_LOG_WARNING,
"converting name",
maj_stat,
min_stat);
ptr=malloc(buffer.length + 1); ptr=malloc(buffer.length + 1);
memcpy(ptr, buffer.value, buffer.length); memcpy(ptr, buffer.value, buffer.length);
ptr[buffer.length] = '\0'; ptr[buffer.length] = '\0';
@@ -335,14 +387,20 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server){
maj_stat = gss_accept_sec_context(&min_stat, &session->gssapi->ctx, session->gssapi->server_creds, maj_stat = gss_accept_sec_context(&min_stat, &session->gssapi->ctx, session->gssapi->server_creds,
&input_token, input_bindings, &client_name, NULL /*mech_oid*/, &output_token, &ret_flags, &input_token, input_bindings, &client_name, NULL /*mech_oid*/, &output_token, &ret_flags,
NULL /*time*/, &session->gssapi->client_creds); NULL /*time*/, &session->gssapi->client_creds);
ssh_gssapi_log_error(SSH_LOG_PROTOCOL, "accepting token", maj_stat); ssh_gssapi_log_error(SSH_LOG_PROTOCOL,
"accepting token",
maj_stat,
min_stat);
ssh_string_free(token); ssh_string_free(token);
if (client_name != GSS_C_NO_NAME){ if (client_name != GSS_C_NO_NAME){
session->gssapi->client_name = client_name; session->gssapi->client_name = client_name;
session->gssapi->canonic_user = ssh_gssapi_name_to_char(client_name); session->gssapi->canonic_user = ssh_gssapi_name_to_char(client_name);
} }
if (GSS_ERROR(maj_stat)){ if (GSS_ERROR(maj_stat)){
ssh_gssapi_log_error(SSH_LOG_WARNING, "Gssapi error", maj_stat); ssh_gssapi_log_error(SSH_LOG_WARNING,
"Gssapi error",
maj_stat,
min_stat);
ssh_auth_reply_default(session,0); ssh_auth_reply_default(session,0);
ssh_gssapi_free(session); ssh_gssapi_free(session);
session->gssapi=NULL; session->gssapi=NULL;
@@ -439,8 +497,10 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_mic)
mic_token_buf.value = ssh_string_data(mic_token); mic_token_buf.value = ssh_string_data(mic_token);
maj_stat = gss_verify_mic(&min_stat, session->gssapi->ctx, &mic_buf, &mic_token_buf, NULL); maj_stat = gss_verify_mic(&min_stat, session->gssapi->ctx, &mic_buf, &mic_token_buf, NULL);
ssh_gssapi_log_error(SSH_LOG_PROTOCOL, "verifying MIC", maj_stat); ssh_gssapi_log_error(SSH_LOG_PROTOCOL,
ssh_gssapi_log_error(SSH_LOG_PROTOCOL, "verifying MIC (min stat)", min_stat); "verifying MIC",
maj_stat,
min_stat);
if (maj_stat == GSS_S_DEFECTIVE_TOKEN || GSS_ERROR(maj_stat)) { if (maj_stat == GSS_S_DEFECTIVE_TOKEN || GSS_ERROR(maj_stat)) {
goto error; goto error;
} }
@@ -653,8 +713,11 @@ int ssh_gssapi_auth_mic(ssh_session session){
&session->gssapi->client.server_name); &session->gssapi->client.server_name);
if (maj_stat != GSS_S_COMPLETE) { if (maj_stat != GSS_S_COMPLETE) {
SSH_LOG(SSH_LOG_WARNING, "importing name %d, %d", maj_stat, min_stat); SSH_LOG(SSH_LOG_WARNING, "importing name %d, %d", maj_stat, min_stat);
ssh_gssapi_log_error(SSH_LOG_WARNING, "importing name", maj_stat); ssh_gssapi_log_error(SSH_LOG_WARNING,
return SSH_PACKET_USED; "importing name",
maj_stat,
min_stat);
return SSH_AUTH_DENIED;
} }
/* copy username */ /* copy username */
@@ -759,7 +822,10 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_response){
0, NULL, &input_token, NULL, 0, NULL, &input_token, NULL,
&output_token, NULL, NULL); &output_token, NULL, NULL);
if(GSS_ERROR(maj_stat)){ if(GSS_ERROR(maj_stat)){
ssh_gssapi_log_error(SSH_LOG_WARNING, "Initializing gssapi context", maj_stat); ssh_gssapi_log_error(SSH_LOG_WARNING,
"Initializing gssapi context",
maj_stat,
min_stat);
return SSH_PACKET_USED; return SSH_PACKET_USED;
} }
if (output_token.length != 0){ if (output_token.length != 0){
@@ -797,7 +863,10 @@ static int ssh_gssapi_send_mic(ssh_session session){
maj_stat = gss_get_mic(&min_stat,session->gssapi->ctx, GSS_C_QOP_DEFAULT, &mic_buf, &mic_token_buf); maj_stat = gss_get_mic(&min_stat,session->gssapi->ctx, GSS_C_QOP_DEFAULT, &mic_buf, &mic_token_buf);
if (GSS_ERROR(maj_stat)){ if (GSS_ERROR(maj_stat)){
ssh_buffer_free(mic_buffer); ssh_buffer_free(mic_buffer);
ssh_gssapi_log_error(SSH_LOG_PROTOCOL, "generating MIC", maj_stat); ssh_gssapi_log_error(SSH_LOG_PROTOCOL,
"generating MIC",
maj_stat,
min_stat);
return SSH_ERROR; return SSH_ERROR;
} }
@@ -848,10 +917,16 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_client){
0, NULL, &input_token, NULL, 0, NULL, &input_token, NULL,
&output_token, NULL, NULL); &output_token, NULL, NULL);
ssh_gssapi_log_error(SSH_LOG_PROTOCOL, "accepting token", maj_stat); ssh_gssapi_log_error(SSH_LOG_PROTOCOL,
"accepting token",
maj_stat,
min_stat);
ssh_string_free(token); ssh_string_free(token);
if (GSS_ERROR(maj_stat)){ if (GSS_ERROR(maj_stat)){
ssh_gssapi_log_error(SSH_LOG_PROTOCOL, "Gssapi error", maj_stat); ssh_gssapi_log_error(SSH_LOG_PROTOCOL,
"Gssapi error",
maj_stat,
min_stat);
ssh_gssapi_free(session); ssh_gssapi_free(session);
session->gssapi=NULL; session->gssapi=NULL;
return SSH_PACKET_USED; return SSH_PACKET_USED;
@@ -869,8 +944,8 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_client){
packet_send(session); packet_send(session);
} }
if(maj_stat == GSS_S_COMPLETE){ if(maj_stat == GSS_S_COMPLETE){
session->auth_state = SSH_AUTH_STATE_NONE;
ssh_gssapi_send_mic(session); ssh_gssapi_send_mic(session);
session->auth_state = SSH_AUTH_STATE_GSSAPI_MIC_SENT;
} }
return SSH_PACKET_USED; return SSH_PACKET_USED;
} }

View File

@@ -42,24 +42,28 @@
# define AES "aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc," # define AES "aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,"
# define DES "3des-cbc" # define DES "3des-cbc"
# define DES_SUPPORTED "3des-cbc,des-cbc-ssh1" # define DES_SUPPORTED "3des-cbc,des-cbc-ssh1"
#elif defined(HAVE_LIBCRYPTO) #elif defined(HAVE_LIBCRYPTO)
# ifdef HAVE_OPENSSL_BLOWFISH_H # ifdef HAVE_OPENSSL_BLOWFISH_H
# define BLOWFISH "blowfish-cbc," # define BLOWFISH "blowfish-cbc,"
# else # else /* HAVE_OPENSSL_BLOWFISH_H */
# define BLOWFISH "" # define BLOWFISH ""
# endif # endif /* HAVE_OPENSSL_BLOWFISH_H */
# ifdef HAVE_OPENSSL_AES_H # ifdef HAVE_OPENSSL_AES_H
# ifdef BROKEN_AES_CTR # ifdef BROKEN_AES_CTR
# define AES "aes256-cbc,aes192-cbc,aes128-cbc," # define AES "aes256-cbc,aes192-cbc,aes128-cbc,"
# else # else /* BROKEN_AES_CTR */
# define AES "aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc," # define AES "aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,"
# endif /* BROKEN_AES_CTR */ # endif /* BROKEN_AES_CTR */
# else # else /* HAVE_OPENSSL_AES_H */
# define AES "" # define AES ""
# endif # endif /* HAVE_OPENSSL_AES_H */
# define DES "3des-cbc" # define DES "3des-cbc"
# define DES_SUPPORTED "3des-cbc,des-cbc-ssh1" # define DES_SUPPORTED "3des-cbc,des-cbc-ssh1"
#endif #endif /* HAVE_LIBCRYPTO */
#ifdef WITH_ZLIB #ifdef WITH_ZLIB
#define ZLIB "none,zlib,zlib@openssh.com" #define ZLIB "none,zlib,zlib@openssh.com"
@@ -90,8 +94,8 @@ static const char *default_methods[] = {
HOSTKEYS, HOSTKEYS,
AES BLOWFISH DES, AES BLOWFISH DES,
AES BLOWFISH DES, AES BLOWFISH DES,
"hmac-sha1,hmac-sha2-256,hmac-sha2-512", "hmac-sha2-256,hmac-sha2-512,hmac-sha1",
"hmac-sha1,hmac-sha2-256,hmac-sha2-512", "hmac-sha2-256,hmac-sha2-512,hmac-sha1",
"none", "none",
"none", "none",
"", "",
@@ -105,8 +109,8 @@ static const char *supported_methods[] = {
HOSTKEYS, HOSTKEYS,
AES BLOWFISH DES_SUPPORTED, AES BLOWFISH DES_SUPPORTED,
AES BLOWFISH DES_SUPPORTED, AES BLOWFISH DES_SUPPORTED,
"hmac-sha1,hmac-sha2-256,hmac-sha2-512", "hmac-sha2-256,hmac-sha2-512,hmac-sha1",
"hmac-sha1,hmac-sha2-256,hmac-sha2-512", "hmac-sha2-256,hmac-sha2-512,hmac-sha1",
ZLIB, ZLIB,
ZLIB, ZLIB,
"", "",

View File

@@ -36,6 +36,10 @@
#include "libssh/ssh1.h" #include "libssh/ssh1.h"
#include "libssh/wrapper.h" #include "libssh/wrapper.h"
#if defined(HAVE_LIBCRYPTO)
#include "libcrypto-compat.h"
#endif
/* SSHv1 functions */ /* SSHv1 functions */
/* makes a STRING contating 3 strings : ssh-rsa1,e and n */ /* makes a STRING contating 3 strings : ssh-rsa1,e and n */
@@ -46,6 +50,10 @@ static ssh_string make_rsa1_string(ssh_string e, ssh_string n){
ssh_string ret = NULL; ssh_string ret = NULL;
buffer = ssh_buffer_new(); buffer = ssh_buffer_new();
if (buffer == NULL) {
goto error;
}
rsa = ssh_string_from_char("ssh-rsa1"); rsa = ssh_string_from_char("ssh-rsa1");
if (rsa == NULL) { if (rsa == NULL) {
goto error; goto error;
@@ -119,8 +127,8 @@ static int modulus_smaller(ssh_public_key k1, ssh_public_key k2){
n2=gcry_sexp_nth_mpi(sexp,1,GCRYMPI_FMT_USG); n2=gcry_sexp_nth_mpi(sexp,1,GCRYMPI_FMT_USG);
gcry_sexp_release(sexp); gcry_sexp_release(sexp);
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
n1=k1->rsa_pub->n; RSA_get0_key(k1->rsa_pub, (const BIGNUM **)&n1, NULL, NULL);
n2=k2->rsa_pub->n; RSA_get0_key(k2->rsa_pub, (const BIGNUM **)&n2, NULL, NULL);
#endif #endif
if(bignum_cmp(n1,n2)<0) if(bignum_cmp(n1,n2)<0)
res=1; res=1;

318
src/libcrypto-compat.c Normal file
View File

@@ -0,0 +1,318 @@
/*
* Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <openssl/engine.h>
#include "libcrypto-compat.h"
static void *OPENSSL_zalloc(size_t num)
{
void *ret = OPENSSL_malloc(num);
if (ret != NULL)
memset(ret, 0, num);
return ret;
}
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
{
/* If the fields n and e in r are NULL, the corresponding input
* parameters MUST be non-NULL for n and e. d may be
* left NULL (in case only the public key is used).
*/
if ((r->n == NULL && n == NULL)
|| (r->e == NULL && e == NULL))
return 0;
if (n != NULL) {
BN_free(r->n);
r->n = n;
}
if (e != NULL) {
BN_free(r->e);
r->e = e;
}
if (d != NULL) {
BN_free(r->d);
r->d = d;
}
return 1;
}
int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
{
/* If the fields p and q in r are NULL, the corresponding input
* parameters MUST be non-NULL.
*/
if ((r->p == NULL && p == NULL)
|| (r->q == NULL && q == NULL))
return 0;
if (p != NULL) {
BN_free(r->p);
r->p = p;
}
if (q != NULL) {
BN_free(r->q);
r->q = q;
}
return 1;
}
int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
{
/* If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input
* parameters MUST be non-NULL.
*/
if ((r->dmp1 == NULL && dmp1 == NULL)
|| (r->dmq1 == NULL && dmq1 == NULL)
|| (r->iqmp == NULL && iqmp == NULL))
return 0;
if (dmp1 != NULL) {
BN_free(r->dmp1);
r->dmp1 = dmp1;
}
if (dmq1 != NULL) {
BN_free(r->dmq1);
r->dmq1 = dmq1;
}
if (iqmp != NULL) {
BN_free(r->iqmp);
r->iqmp = iqmp;
}
return 1;
}
void RSA_get0_key(const RSA *r,
const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
{
if (n != NULL)
*n = r->n;
if (e != NULL)
*e = r->e;
if (d != NULL)
*d = r->d;
}
void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q)
{
if (p != NULL)
*p = r->p;
if (q != NULL)
*q = r->q;
}
void RSA_get0_crt_params(const RSA *r,
const BIGNUM **dmp1, const BIGNUM **dmq1,
const BIGNUM **iqmp)
{
if (dmp1 != NULL)
*dmp1 = r->dmp1;
if (dmq1 != NULL)
*dmq1 = r->dmq1;
if (iqmp != NULL)
*iqmp = r->iqmp;
}
void DSA_get0_pqg(const DSA *d,
const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
{
if (p != NULL)
*p = d->p;
if (q != NULL)
*q = d->q;
if (g != NULL)
*g = d->g;
}
int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
{
/* If the fields p, q and g in d are NULL, the corresponding input
* parameters MUST be non-NULL.
*/
if ((d->p == NULL && p == NULL)
|| (d->q == NULL && q == NULL)
|| (d->g == NULL && g == NULL))
return 0;
if (p != NULL) {
BN_free(d->p);
d->p = p;
}
if (q != NULL) {
BN_free(d->q);
d->q = q;
}
if (g != NULL) {
BN_free(d->g);
d->g = g;
}
return 1;
}
void DSA_get0_key(const DSA *d,
const BIGNUM **pub_key, const BIGNUM **priv_key)
{
if (pub_key != NULL)
*pub_key = d->pub_key;
if (priv_key != NULL)
*priv_key = d->priv_key;
}
int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
{
/* If the field pub_key in d is NULL, the corresponding input
* parameters MUST be non-NULL. The priv_key field may
* be left NULL.
*/
if (d->pub_key == NULL && pub_key == NULL)
return 0;
if (pub_key != NULL) {
BN_free(d->pub_key);
d->pub_key = pub_key;
}
if (priv_key != NULL) {
BN_free(d->priv_key);
d->priv_key = priv_key;
}
return 1;
}
void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
{
if (pr != NULL)
*pr = sig->r;
if (ps != NULL)
*ps = sig->s;
}
int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s)
{
if (r == NULL || s == NULL)
return 0;
BN_clear_free(sig->r);
BN_clear_free(sig->s);
sig->r = r;
sig->s = s;
return 1;
}
void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
{
if (pr != NULL)
*pr = sig->r;
if (ps != NULL)
*ps = sig->s;
}
int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
{
if (r == NULL || s == NULL)
return 0;
BN_clear_free(sig->r);
BN_clear_free(sig->s);
sig->r = r;
sig->s = s;
return 1;
}
EVP_MD_CTX *EVP_MD_CTX_new(void)
{
return OPENSSL_zalloc(sizeof(EVP_MD_CTX));
}
static void OPENSSL_clear_free(void *str, size_t num)
{
if (str == NULL)
return;
if (num)
OPENSSL_cleanse(str, num);
OPENSSL_free(str);
}
/* This call frees resources associated with the context */
int EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
{
if (ctx == NULL)
return 1;
/*
* Don't assume ctx->md_data was cleaned in EVP_Digest_Final, because
* sometimes only copies of the context are ever finalised.
*/
if (ctx->digest && ctx->digest->cleanup
&& !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_CLEANED))
ctx->digest->cleanup(ctx);
if (ctx->digest && ctx->digest->ctx_size && ctx->md_data
&& !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE)) {
OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size);
}
EVP_PKEY_CTX_free(ctx->pctx);
#ifndef OPENSSL_NO_ENGINE
ENGINE_finish(ctx->engine);
#endif
OPENSSL_cleanse(ctx, sizeof(*ctx));
return 1;
}
void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
{
EVP_MD_CTX_reset(ctx);
OPENSSL_free(ctx);
}
HMAC_CTX *HMAC_CTX_new(void)
{
HMAC_CTX *ctx = OPENSSL_zalloc(sizeof(HMAC_CTX));
if (ctx != NULL) {
if (!HMAC_CTX_reset(ctx)) {
HMAC_CTX_free(ctx);
return NULL;
}
}
return ctx;
}
static void hmac_ctx_cleanup(HMAC_CTX *ctx)
{
EVP_MD_CTX_reset(&ctx->i_ctx);
EVP_MD_CTX_reset(&ctx->o_ctx);
EVP_MD_CTX_reset(&ctx->md_ctx);
ctx->md = NULL;
ctx->key_length = 0;
OPENSSL_cleanse(ctx->key, sizeof(ctx->key));
}
void HMAC_CTX_free(HMAC_CTX *ctx)
{
if (ctx != NULL) {
hmac_ctx_cleanup(ctx);
#if OPENSSL_VERSION_NUMBER > 0x10100000L
EVP_MD_CTX_free(&ctx->i_ctx);
EVP_MD_CTX_free(&ctx->o_ctx);
EVP_MD_CTX_free(&ctx->md_ctx);
#endif
OPENSSL_free(ctx);
}
}
int HMAC_CTX_reset(HMAC_CTX *ctx)
{
HMAC_CTX_init(ctx);
return 1;
}

42
src/libcrypto-compat.h Normal file
View File

@@ -0,0 +1,42 @@
#ifndef LIBCRYPTO_COMPAT_H
#define LIBCRYPTO_COMPAT_H
#include <openssl/opensslv.h>
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/ecdsa.h>
#include <openssl/dh.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q);
int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp);
void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d);
void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q);
void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp);
void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g);
void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key);
int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key);
void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s);
void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s);
int EVP_MD_CTX_reset(EVP_MD_CTX *ctx);
EVP_MD_CTX *EVP_MD_CTX_new(void);
void EVP_MD_CTX_free(EVP_MD_CTX *ctx);
HMAC_CTX *HMAC_CTX_new(void);
int HMAC_CTX_reset(HMAC_CTX *ctx);
void HMAC_CTX_free(HMAC_CTX *ctx);
#endif /* OPENSSL_VERSION_NUMBER */
#endif /* LIBCRYPTO_COMPAT_H */

View File

@@ -43,6 +43,8 @@
#include <openssl/hmac.h> #include <openssl/hmac.h>
#include <openssl/opensslv.h> #include <openssl/opensslv.h>
#include <openssl/rand.h> #include <openssl/rand.h>
#include <openssl/modes.h>
#include "libcrypto-compat.h"
#ifdef HAVE_OPENSSL_AES_H #ifdef HAVE_OPENSSL_AES_H
#define HAS_AES #define HAS_AES
@@ -133,18 +135,19 @@ static const EVP_MD *nid_to_evpmd(int nid)
void evp(int nid, unsigned char *digest, int len, unsigned char *hash, unsigned int *hlen) void evp(int nid, unsigned char *digest, int len, unsigned char *hash, unsigned int *hlen)
{ {
const EVP_MD *evp_md = nid_to_evpmd(nid); const EVP_MD *evp_md = nid_to_evpmd(nid);
EVP_MD_CTX md; EVP_MD_CTX *md = EVP_MD_CTX_new();
EVP_DigestInit(&md, evp_md); EVP_DigestInit(md, evp_md);
EVP_DigestUpdate(&md, digest, len); EVP_DigestUpdate(md, digest, len);
EVP_DigestFinal(&md, hash, hlen); EVP_DigestFinal(md, hash, hlen);
EVP_MD_CTX_free(md);
} }
EVPCTX evp_init(int nid) EVPCTX evp_init(int nid)
{ {
const EVP_MD *evp_md = nid_to_evpmd(nid); const EVP_MD *evp_md = nid_to_evpmd(nid);
EVPCTX ctx = malloc(sizeof(EVP_MD_CTX)); EVPCTX ctx = EVP_MD_CTX_new();
if (ctx == NULL) { if (ctx == NULL) {
return NULL; return NULL;
} }
@@ -162,6 +165,7 @@ void evp_update(EVPCTX ctx, const void *data, unsigned long len)
void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen) void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen)
{ {
EVP_DigestFinal(ctx, md, mdlen); EVP_DigestFinal(ctx, md, mdlen);
EVP_MD_CTX_free(ctx);
} }
#endif #endif
@@ -322,32 +326,33 @@ void ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx) {
HMACCTX hmac_init(const void *key, int len, enum ssh_hmac_e type) { HMACCTX hmac_init(const void *key, int len, enum ssh_hmac_e type) {
HMACCTX ctx = NULL; HMACCTX ctx = NULL;
ctx = malloc(sizeof(*ctx)); ctx = HMAC_CTX_new();
if (ctx == NULL) { if (ctx == NULL) {
return NULL; return NULL;
} }
#ifndef OLD_CRYPTO #ifndef OLD_CRYPTO
HMAC_CTX_init(ctx); // openssl 0.9.7 requires it. HMAC_CTX_reset(ctx); // openssl 0.9.7 requires it.
#endif #endif
switch(type) { switch(type) {
case SSH_HMAC_SHA1: case SSH_HMAC_SHA1:
HMAC_Init(ctx, key, len, EVP_sha1()); HMAC_Init_ex(ctx, key, len, EVP_sha1(), NULL);
break; break;
case SSH_HMAC_SHA256: case SSH_HMAC_SHA256:
HMAC_Init(ctx, key, len, EVP_sha256()); HMAC_Init_ex(ctx, key, len, EVP_sha256(), NULL);
break; break;
case SSH_HMAC_SHA384: case SSH_HMAC_SHA384:
HMAC_Init(ctx, key, len, EVP_sha384()); HMAC_Init_ex(ctx, key, len, EVP_sha384(), NULL);
break; break;
case SSH_HMAC_SHA512: case SSH_HMAC_SHA512:
HMAC_Init(ctx, key, len, EVP_sha512()); HMAC_Init_ex(ctx, key, len, EVP_sha512(), NULL);
break; break;
case SSH_HMAC_MD5: case SSH_HMAC_MD5:
HMAC_Init(ctx, key, len, EVP_md5()); HMAC_Init_ex(ctx, key, len, EVP_md5(), NULL);
break; break;
default: default:
HMAC_CTX_free(ctx);
SAFE_FREE(ctx); SAFE_FREE(ctx);
ctx = NULL; ctx = NULL;
} }
@@ -363,7 +368,8 @@ void hmac_final(HMACCTX ctx, unsigned char *hashmacbuf, unsigned int *len) {
HMAC_Final(ctx,hashmacbuf,len); HMAC_Final(ctx,hashmacbuf,len);
#ifndef OLD_CRYPTO #ifndef OLD_CRYPTO
HMAC_CTX_cleanup(ctx); HMAC_CTX_free(ctx);
ctx = NULL;
#else #else
HMAC_cleanup(ctx); HMAC_cleanup(ctx);
#endif #endif
@@ -455,7 +461,12 @@ static void aes_ctr128_encrypt(struct ssh_cipher_struct *cipher, void *in, void
* Same for num, which is being used to store the current offset in blocksize in CTR * Same for num, which is being used to store the current offset in blocksize in CTR
* function. * function.
*/ */
#ifdef HAVE_OPENSSL_CRYPTO_CTR128_ENCRYPT
CRYPTO_ctr128_encrypt(in, out, len, cipher->key, cipher->IV, tmp_buffer,
&num, (block128_f)AES_encrypt);
# else
AES_ctr128_encrypt(in, out, len, cipher->key, cipher->IV, tmp_buffer, &num); AES_ctr128_encrypt(in, out, len, cipher->key, cipher->IV, tmp_buffer, &num);
#endif /* HAVE_OPENSSL_CRYPTO_CTR128_ENCRYPT */
} }
#endif /* BROKEN_AES_CTR */ #endif /* BROKEN_AES_CTR */
#endif /* HAS_AES */ #endif /* HAS_AES */

View File

@@ -181,7 +181,7 @@ void ssh_mac_update(ssh_mac_ctx ctx, const void *data, unsigned long len) {
} }
void ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx) { void ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx) {
size_t len; size_t len = 0;
switch(ctx->mac_type){ switch(ctx->mac_type){
case SSH_MAC_SHA1: case SSH_MAC_SHA1:
len=SHA_DIGEST_LEN; len=SHA_DIGEST_LEN;

View File

@@ -649,6 +649,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
ssh_message msg = NULL; ssh_message msg = NULL;
char *service = NULL; char *service = NULL;
char *method = NULL; char *method = NULL;
int cmp;
int rc; int rc;
(void)user; (void)user;
@@ -675,6 +676,13 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
service, method, service, method,
msg->auth_request.username); msg->auth_request.username);
cmp = strcmp(service, "ssh-connection");
if (cmp != 0) {
SSH_LOG(SSH_LOG_WARNING,
"Invalid service request: %s",
service);
goto end;
}
if (strcmp(method, "none") == 0) { if (strcmp(method, "none") == 0) {
msg->auth_request.method = SSH_AUTH_METHOD_NONE; msg->auth_request.method = SSH_AUTH_METHOD_NONE;
@@ -923,6 +931,15 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_info_response){
goto error; goto error;
} }
} else if (session->kbdint->nanswers > 0) {
uint32_t n;
for (n = 0; n < session->kbdint->nanswers; n++) {
BURN_STRING(session->kbdint->answers[n]);
SAFE_FREE(session->kbdint->answers[n]);
}
SAFE_FREE(session->kbdint->answers);
session->kbdint->nanswers = 0;
} }
SSH_LOG(SSH_LOG_PACKET,"kbdint: %d answers",nanswers); SSH_LOG(SSH_LOG_PACKET,"kbdint: %d answers",nanswers);
@@ -942,7 +959,8 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_info_response){
" mismatch: p=%u a=%u", session->kbdint->nprompts, nanswers); " mismatch: p=%u a=%u", session->kbdint->nprompts, nanswers);
} }
session->kbdint->nanswers = nanswers; session->kbdint->nanswers = nanswers;
session->kbdint->answers = malloc(nanswers * sizeof(char *));
session->kbdint->answers = calloc(1, nanswers * sizeof(char *));
if (session->kbdint->answers == NULL) { if (session->kbdint->answers == NULL) {
session->kbdint->nanswers = 0; session->kbdint->nanswers = 0;
ssh_set_error_oom(session); ssh_set_error_oom(session);
@@ -951,7 +969,6 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_info_response){
goto error; goto error;
} }
memset(session->kbdint->answers, 0, nanswers * sizeof(char *));
for (i = 0; i < nanswers; i++) { for (i = 0; i < nanswers; i++) {
tmp = buffer_get_ssh_string(packet); tmp = buffer_get_ssh_string(packet);
@@ -1101,6 +1118,7 @@ int ssh_message_channel_request_open_reply_accept_channel(ssh_message msg, ssh_c
chan->remote_maxpacket = msg->channel_request_open.packet_size; chan->remote_maxpacket = msg->channel_request_open.packet_size;
chan->remote_window = msg->channel_request_open.window; chan->remote_window = msg->channel_request_open.window;
chan->state = SSH_CHANNEL_STATE_OPEN; chan->state = SSH_CHANNEL_STATE_OPEN;
chan->flags &= ~SSH_CHANNEL_FLAG_NOT_BOUND;
rc = ssh_buffer_pack(session->out_buffer, rc = ssh_buffer_pack(session->out_buffer,
"bdddd", "bdddd",
@@ -1355,7 +1373,9 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request){
msg->global_request.bind_port); msg->global_request.bind_port);
session->common.callbacks->global_request_function(session, msg, session->common.callbacks->userdata); session->common.callbacks->global_request_function(session, msg, session->common.callbacks->userdata);
} else { } else {
ssh_message_reply_default(msg); SAFE_FREE(request);
ssh_message_queue(session, msg);
return rc;
} }
} else if (strcmp(request, "cancel-tcpip-forward") == 0) { } else if (strcmp(request, "cancel-tcpip-forward") == 0) {
r = ssh_buffer_unpack(packet, "sd", r = ssh_buffer_unpack(packet, "sd",
@@ -1374,7 +1394,9 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request){
if(ssh_callbacks_exists(session->common.callbacks, global_request_function)) { if(ssh_callbacks_exists(session->common.callbacks, global_request_function)) {
session->common.callbacks->global_request_function(session, msg, session->common.callbacks->userdata); session->common.callbacks->global_request_function(session, msg, session->common.callbacks->userdata);
} else { } else {
ssh_message_reply_default(msg); SAFE_FREE(request);
ssh_message_queue(session, msg);
return rc;
} }
} else { } else {
SSH_LOG(SSH_LOG_PROTOCOL, "UNKNOWN SSH_MSG_GLOBAL_REQUEST %s %d", request, want_reply); SSH_LOG(SSH_LOG_PROTOCOL, "UNKNOWN SSH_MSG_GLOBAL_REQUEST %s %d", request, want_reply);

View File

@@ -33,9 +33,10 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#ifndef HAVE_CLOCK_GETTIME #ifdef HAVE_SYS_TIME_H
#include <sys/time.h> #include <sys/time.h>
#endif /* HAVE_CLOCK_GETTIME */ #endif /* HAVE_SYS_TIME_H */
#endif /* _WIN32 */ #endif /* _WIN32 */
#include <limits.h> #include <limits.h>
@@ -289,23 +290,6 @@ int ssh_is_ipaddr(const char *str) {
#endif /* _WIN32 */ #endif /* _WIN32 */
#ifndef HAVE_NTOHLL
uint64_t ntohll(uint64_t a) {
#ifdef WORDS_BIGENDIAN
return a;
#else /* WORDS_BIGENDIAN */
return (((uint64_t)(a) << 56) | \
(((uint64_t)(a) << 40) & 0xff000000000000ULL) | \
(((uint64_t)(a) << 24) & 0xff0000000000ULL) | \
(((uint64_t)(a) << 8) & 0xff00000000ULL) | \
(((uint64_t)(a) >> 8) & 0xff000000ULL) | \
(((uint64_t)(a) >> 24) & 0xff0000ULL) | \
(((uint64_t)(a) >> 40) & 0xff00ULL) | \
((uint64_t)(a) >> 56));
#endif /* WORDS_BIGENDIAN */
}
#endif /* HAVE_NTOHLL */
char *ssh_lowercase(const char* str) { char *ssh_lowercase(const char* str) {
char *new, *p; char *new, *p;
@@ -862,7 +846,7 @@ int ssh_analyze_banner(ssh_session session, int server, int *ssh1, int *ssh2) {
openssh = strstr(banner, "OpenSSH"); openssh = strstr(banner, "OpenSSH");
if (openssh != NULL) { if (openssh != NULL) {
int major, minor; unsigned int major, minor;
/* /*
* The banner is typical: * The banner is typical:
@@ -870,8 +854,22 @@ int ssh_analyze_banner(ssh_session session, int server, int *ssh1, int *ssh2) {
* 012345678901234567890 * 012345678901234567890
*/ */
if (strlen(openssh) > 9) { if (strlen(openssh) > 9) {
major = strtol(openssh + 8, (char **) NULL, 10); major = strtoul(openssh + 8, (char **) NULL, 10);
if (major < 1 || major > 100) {
ssh_set_error(session,
SSH_FATAL,
"Invalid major version number: %s",
banner);
return -1;
}
minor = strtol(openssh + 10, (char **) NULL, 10); minor = strtol(openssh + 10, (char **) NULL, 10);
if (minor > 100) {
ssh_set_error(session,
SSH_FATAL,
"Invalid minor version number: %s",
banner);
return -1;
}
session->openssh = SSH_VERSION_INT(major, minor, 0); session->openssh = SSH_VERSION_INT(major, minor, 0);
SSH_LOG(SSH_LOG_RARE, SSH_LOG(SSH_LOG_RARE,
"We are talking to an OpenSSH client version: %d.%d (%x)", "We are talking to an OpenSSH client version: %d.%d (%x)",
@@ -1030,6 +1028,27 @@ int ssh_match_group(const char *group, const char *object)
return 0; return 0;
} }
#if !defined(HAVE_STRNDUP)
char *strndup(const char *s, size_t n)
{
char *x = NULL;
if (n + 1 < n) {
return NULL;
}
x = malloc(n + 1);
if (x == NULL) {
return NULL;
}
memcpy(x, s, n);
x[n] = '\0';
return x;
}
#endif /* ! HAVE_STRNDUP */
/** @} */ /** @} */
/* vim: set ts=4 sw=4 et cindent: */ /* vim: set ts=4 sw=4 et cindent: */

View File

@@ -93,12 +93,6 @@ int ssh_options_copy(ssh_session src, ssh_session *dest) {
if (src->opts.identity) { if (src->opts.identity) {
struct ssh_iterator *it; struct ssh_iterator *it;
new->opts.identity = ssh_list_new();
if (new->opts.identity == NULL) {
ssh_free(new);
return -1;
}
it = ssh_list_get_iterator(src->opts.identity); it = ssh_list_get_iterator(src->opts.identity);
while (it) { while (it) {
char *id; char *id;
@@ -338,7 +332,7 @@ int ssh_options_set_algo(ssh_session session, int algo,
* - SSH_OPTIONS_HOSTKEYS: * - SSH_OPTIONS_HOSTKEYS:
* Set the preferred server host key types (const char *, * Set the preferred server host key types (const char *,
* comma-separated list). ex: * comma-separated list). ex:
* "ssh-rsa,ssh-dsa,ecdh-sha2-nistp256" * "ssh-rsa,ssh-dss,ecdh-sha2-nistp256"
* *
* - SSH_OPTIONS_COMPRESSION_C_S: * - SSH_OPTIONS_COMPRESSION_C_S:
* Set the compression to use for client to server * Set the compression to use for client to server
@@ -1356,10 +1350,10 @@ static int ssh_bind_set_key(ssh_bind sshbind, char **key_loc,
* with verbosity less than or equal to the * with verbosity less than or equal to the
* logging verbosity will be shown. * logging verbosity will be shown.
* - SSH_LOG_NOLOG: No logging * - SSH_LOG_NOLOG: No logging
* - SSH_LOG_RARE: Rare conditions or warnings * - SSH_LOG_WARNING: Only warnings
* - SSH_LOG_ENTRY: API-accessible entrypoints * - SSH_LOG_PROTOCOL: High level protocol information
* - SSH_LOG_PACKET: Packet id and size * - SSH_LOG_PACKET: Lower level protocol infomations, packet level
* - SSH_LOG_FUNCTIONS: Function entering and leaving * - SSH_LOG_FUNCTIONS: Every function path
* *
* - SSH_BIND_OPTIONS_LOG_VERBOSITY_STR: * - SSH_BIND_OPTIONS_LOG_VERBOSITY_STR:
* Set the session logging verbosity via a * Set the session logging verbosity via a

View File

@@ -127,6 +127,776 @@ static ssh_packet_callback default_packet_handlers[]= {
ssh_packet_channel_failure, // SSH2_MSG_CHANNEL_FAILURE 100 ssh_packet_channel_failure, // SSH2_MSG_CHANNEL_FAILURE 100
}; };
/** @internal
* @brief check if the received packet is allowed for the current session state
* @param session current ssh_session
* @returns SSH_PACKET_ALLOWED if the packet is allowed; SSH_PACKET_DENIED
* if the packet arrived in wrong state; SSH_PACKET_UNKNOWN if the packet type
* is unknown
*/
static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session session)
{
enum ssh_packet_filter_result_e rc;
#ifdef DEBUG_PACKET
SSH_LOG(SSH_LOG_PACKET, "Filtering packet type %d",
session->in_packet.type);
#endif
switch(session->in_packet.type) {
case SSH2_MSG_DISCONNECT: // 1
/*
* States required:
* - None
*
* Transitions:
* - session->socket->state = SSH_SOCKET_CLOSED
* - session->session_state = SSH_SESSION_STATE_ERROR
* */
/* Always allowed */
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_IGNORE: // 2
/*
* States required:
* - None
*
* Transitions:
* - None
* */
/* Always allowed */
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_UNIMPLEMENTED: // 3
/*
* States required:
* - None
*
* Transitions:
* - None
* */
/* Always allowed */
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_DEBUG: // 4
/*
* States required:
* - None
*
* Transitions:
* - None
* */
/* Always allowed */
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_SERVICE_REQUEST: // 5
/* Server only */
/*
* States required:
* - session->session_state == SSH_SESSION_STATE_AUTHENTICATING
* or session->session_state == SSH_SESSION_STATE_AUTHENTICATED
* - session->dh_handshake_state == DH_STATE_FINISHED
*
* Transitions:
* - None
* */
/* If this is a client, reject the message */
if (session->client) {
rc = SSH_PACKET_DENIED;
break;
}
if ((session->session_state != SSH_SESSION_STATE_AUTHENTICATING) &&
(session->session_state != SSH_SESSION_STATE_AUTHENTICATED))
{
rc = SSH_PACKET_DENIED;
break;
}
if (session->dh_handshake_state != DH_STATE_FINISHED) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_SERVICE_ACCEPT: // 6
/*
* States required:
* - session->session_state == SSH_SESSION_STATE_AUTHENTICATING
* or session->session_state == SSH_SESSION_STATE_AUTHENTICATED
* - session->dh_handshake_state == DH_STATE_FINISHED
* - session->auth_service_state == SSH_AUTH_SERVICE_SENT
*
* Transitions:
* - auth_service_state = SSH_AUTH_SERVICE_ACCEPTED
* */
if ((session->session_state != SSH_SESSION_STATE_AUTHENTICATING) &&
(session->session_state != SSH_SESSION_STATE_AUTHENTICATED))
{
rc = SSH_PACKET_DENIED;
break;
}
if (session->dh_handshake_state != DH_STATE_FINISHED) {
rc = SSH_PACKET_DENIED;
break;
}
/* TODO check if only auth service can be requested */
if (session->auth_service_state != SSH_AUTH_SERVICE_SENT) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_KEXINIT: // 20
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
* or session_state == SSH_SESSION_STATE_INITIAL_KEX
* - dh_handshake_state == DH_STATE_INIT
* or dh_handshake_state == DH_STATE_FINISHED (re-exchange)
*
* Transitions:
* - session->dh_handshake_state = DH_STATE_INIT
* - session->session_state = SSH_SESSION_STATE_KEXINIT_RECEIVED
*
* On server:
* - session->session_state = SSH_SESSION_STATE_DH
* */
if ((session->session_state != SSH_SESSION_STATE_AUTHENTICATED) &&
(session->session_state != SSH_SESSION_STATE_INITIAL_KEX))
{
rc = SSH_PACKET_DENIED;
break;
}
if ((session->dh_handshake_state != DH_STATE_INIT) &&
(session->dh_handshake_state != DH_STATE_FINISHED))
{
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_NEWKEYS: // 21
/*
* States required:
* - session_state == SSH_SESSION_STATE_DH
* - dh_handshake_state == DH_STATE_NEWKEYS_SENT
*
* Transitions:
* - session->dh_handshake_state = DH_STATE_FINISHED
* - session->session_state = SSH_SESSION_STATE_AUTHENTICATING
* if session->flags & SSH_SESSION_FLAG_AUTHENTICATED
* - session->session_state = SSH_SESSION_STATE_AUTHENTICATED
* */
/* If DH has not been started, reject message */
if (session->session_state != SSH_SESSION_STATE_DH) {
rc = SSH_PACKET_DENIED;
break;
}
/* Only allowed if dh_handshake_state is in NEWKEYS_SENT state */
if (session->dh_handshake_state != DH_STATE_NEWKEYS_SENT) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_KEXDH_INIT: // 30
// SSH2_MSG_KEX_ECDH_INIT: // 30
// SSH2_MSG_ECMQV_INIT: // 30
// SSH2_MSG_KEX_DH_GEX_REQUEST_OLD: // 30
/* Server only */
/*
* States required:
* - session_state == SSH_SESSION_STATE_DH
* - dh_handshake_state == DH_STATE_INIT
*
* Transitions:
* - session->dh_handshake_state = DH_STATE_INIT_SENT
* then calls dh_handshake_server which triggers:
* - session->dh_handhsake_state = DH_STATE_NEWKEYS_SENT
* */
if (session->session_state != SSH_SESSION_STATE_DH) {
rc = SSH_PACKET_DENIED;
break;
}
/* Only allowed if dh_handshake_state is in initial state */
if (session->dh_handshake_state != DH_STATE_INIT) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_KEXDH_REPLY: // 31
// SSH2_MSG_KEX_ECDH_REPLY: // 31
// SSH2_MSG_ECMQV_REPLY: // 31
// SSH2_MSG_KEX_DH_GEX_GROUP: // 31
/*
* States required:
* - session_state == SSH_SESSION_STATE_DH
* - dh_handshake_state == DH_STATE_INIT_SENT
*
* Transitions:
* - session->dh_handhsake_state = DH_STATE_NEWKEYS_SENT
* */
if (session->session_state != SSH_SESSION_STATE_DH) {
rc = SSH_PACKET_DENIED;
break;
}
if (session->dh_handshake_state != DH_STATE_INIT_SENT) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_KEX_DH_GEX_INIT: // 32
/* TODO Not filtered */
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_KEX_DH_GEX_REPLY: // 33
/* TODO Not filtered */
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_KEX_DH_GEX_REQUEST: // 34
/* TODO Not filtered */
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_USERAUTH_REQUEST: // 50
/* Server only */
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
* - dh_hanshake_state == DH_STATE_FINISHED
*
* Transitions:
* - if authentication was successful:
* - session_state = SSH_SESSION_STATE_AUTHENTICATED
* */
/* If this is a client, reject the message */
if (session->client) {
rc = SSH_PACKET_DENIED;
break;
}
if (session->dh_handshake_state != DH_STATE_FINISHED) {
rc = SSH_PACKET_DENIED;
break;
}
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_USERAUTH_FAILURE: // 51
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
* - dh_hanshake_state == DH_STATE_FINISHED
* - session->auth_state == SSH_AUTH_STATE_KBDINT_SENT
* or session->auth_state == SSH_AUTH_STATE_PUBKEY_OFFER_SENT
* or session->auth_state == SSH_AUTH_STATE_PUBKEY_AUTH_SENT
* or session->auth_state == SSH_AUTH_STATE_PASSWORD_AUTH_SENT
* or session->auth_state == SSH_AUTH_STATE_GSSAPI_MIC_SENT
*
* Transitions:
* - if unpacking failed:
* - session->auth_state = SSH_AUTH_ERROR
* - if failure was partial:
* - session->auth_state = SSH_AUTH_PARTIAL
* - else:
* - session->auth_state = SSH_AUTH_STATE_FAILED
* */
/* If this is a server, reject the message */
if (session->server) {
rc = SSH_PACKET_DENIED;
break;
}
if (session->dh_handshake_state != DH_STATE_FINISHED) {
rc = SSH_PACKET_DENIED;
break;
}
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_USERAUTH_SUCCESS: // 52
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
* - dh_hanshake_state == DH_STATE_FINISHED
* - session->auth_state == SSH_AUTH_STATE_KBDINT_SENT
* or session->auth_state == SSH_AUTH_STATE_PUBKEY_AUTH_SENT
* or session->auth_state == SSH_AUTH_STATE_PASSWORD_AUTH_SENT
* or session->auth_state == SSH_AUTH_STATE_GSSAPI_MIC_SENT
* or session->auth_state == SSH_AUTH_STATE_AUTH_NONE_SENT
*
* Transitions:
* - session->auth_state = SSH_AUTH_STATE_SUCCESS
* - session->session_state = SSH_SESSION_STATE_AUTHENTICATED
* - session->flags |= SSH_SESSION_FLAG_AUTHENTICATED
* - sessions->auth.current_method = SSH_AUTH_METHOD_UNKNOWN
* */
/* If this is a server, reject the message */
if (session->server) {
rc = SSH_PACKET_DENIED;
break;
}
if (session->dh_handshake_state != DH_STATE_FINISHED) {
rc = SSH_PACKET_DENIED;
break;
}
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
rc = SSH_PACKET_DENIED;
break;
}
if ((session->auth_state != SSH_AUTH_STATE_KBDINT_SENT) &&
(session->auth_state != SSH_AUTH_STATE_PUBKEY_AUTH_SENT) &&
(session->auth_state != SSH_AUTH_STATE_PASSWORD_AUTH_SENT) &&
(session->auth_state != SSH_AUTH_STATE_GSSAPI_MIC_SENT) &&
(session->auth_state != SSH_AUTH_STATE_AUTH_NONE_SENT))
{
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_USERAUTH_BANNER: // 53
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
*
* Transitions:
* - None
* */
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_USERAUTH_PK_OK: // 60
// SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ: // 60
// SSH2_MSG_USERAUTH_INFO_REQUEST: // 60
// SSH2_MSG_USERAUTH_GSSAPI_RESPONSE: // 60
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
* - session->auth_state == SSH_AUTH_STATE_KBDINT_SENT
* or
* session->auth_state == SSH_AUTH_STATE_GSSAPI_REQUEST_SENT
* or
* session->auth_state == SSH_AUTH_STATE_PUBKEY_OFFER_SENT
*
* Transitions:
* Depending on the current state, the message is treated
* differently:
* - session->auth_state == SSH_AUTH_STATE_KBDINT_SENT
* - session->auth_state = SSH_AUTH_STATE_INFO
* - session->auth_state == SSH_AUTH_STATE_GSSAPI_REQUEST_SENT
* - session->auth_state = SSH_AUTH_STATE_GSSAPI_TOKEN
* - session->auth_state == SSH_AUTH_STATE_PUBKEY_OFFER_SENT
* - session->auth_state = SSH_AUTH_STATE_PK_OK
* */
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
rc = SSH_PACKET_DENIED;
break;
}
if ((session->auth_state != SSH_AUTH_STATE_KBDINT_SENT) &&
(session->auth_state != SSH_AUTH_STATE_PUBKEY_OFFER_SENT) &&
(session->auth_state != SSH_AUTH_STATE_GSSAPI_REQUEST_SENT))
{
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_USERAUTH_INFO_RESPONSE: // 61
// SSH2_MSG_USERAUTH_GSSAPI_TOKEN: // 61
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
* - session_state->auth_state == SSH_SESSION_STATE_GSSAPI_TOKEN
* or
* session_state->auth_state == SSH_SESSION_STATE_INFO
*
* Transitions:
* - None
* */
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
rc = SSH_PACKET_DENIED;
break;
}
if ((session->auth_state != SSH_AUTH_STATE_INFO) &&
(session->auth_state != SSH_AUTH_STATE_GSSAPI_TOKEN))
{
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE: // 63
/* TODO Not filtered */
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_USERAUTH_GSSAPI_ERROR: // 64
/* TODO Not filtered */
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_USERAUTH_GSSAPI_ERRTOK: // 65
/* TODO Not filtered */
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_USERAUTH_GSSAPI_MIC: // 66
/* Server only */
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
* - session->gssapi->state == SSH_GSSAPI_STATE_RCV_MIC
*
* Transitions:
* Depending on the result of the verification, the states are
* changed:
* - SSH_AUTH_SUCCESS:
* - session->session_state = SSH_SESSION_STATE_AUTHENTICATED
* - session->flags != SSH_SESSION_FLAG_AUTHENTICATED
* - SSH_AUTH_PARTIAL:
* - None
* - any other case:
* - None
* */
/* If this is a client, reject the message */
if (session->client) {
rc = SSH_PACKET_DENIED;
break;
}
if (session->dh_handshake_state != DH_STATE_FINISHED) {
rc = SSH_PACKET_DENIED;
break;
}
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_GLOBAL_REQUEST: // 80
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
*
* Transitions:
* - None
* */
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_REQUEST_SUCCESS: // 81
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING
*
* Transitions:
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_ACCEPTED
* */
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
rc = SSH_PACKET_DENIED;
break;
}
if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_REQUEST_FAILURE: // 82
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING
*
* Transitions:
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_DENIED
* */
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
rc = SSH_PACKET_DENIED;
break;
}
if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_CHANNEL_OPEN: // 90
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
*
* Transitions:
* - None
* */
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: // 91
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
*
* Transitions:
* - channel->state = SSH_CHANNEL_STATE_OPEN
* - channel->flags &= ~SSH_CHANNEL_FLAG_NOT_BOUND
* */
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_CHANNEL_OPEN_FAILURE: // 92
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
*
* Transitions:
* - channel->state = SSH_CHANNEL_STATE_OPEN_DENIED
* */
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_CHANNEL_WINDOW_ADJUST: // 93
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
*
* Transitions:
* - None
* */
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_CHANNEL_DATA: // 94
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
*
* Transitions:
* - None
* */
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_CHANNEL_EXTENDED_DATA: // 95
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
*
* Transitions:
* - None
* */
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_CHANNEL_EOF: // 96
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
*
* Transitions:
* - None
* */
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_CHANNEL_CLOSE: // 97
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
*
* Transitions:
* - channel->state = SSH_CHANNEL_STATE_CLOSED
* - channel->flags |= SSH_CHANNEL_FLAG_CLOSED_REMOTE
* */
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_CHANNEL_REQUEST: // 98
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
*
* Transitions:
* - Depends on the request
* */
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_CHANNEL_SUCCESS: // 99
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
* - channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
*
* Transitions:
* - channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED
* */
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_CHANNEL_FAILURE: // 100
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
* - channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
*
* Transitions:
* - channel->request_state = SSH_CHANNEL_REQ_STATE_DENIED
* */
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
default:
/* Unknown message, do not filter */
rc = SSH_PACKET_UNKNOWN;
goto end;
}
end:
#ifdef DEBUG_PACKET
if (rc == SSH_PACKET_DENIED) {
SSH_LOG(SSH_LOG_PACKET, "REJECTED packet type %d: ",
session->in_packet.type);
}
if (rc == SSH_PACKET_UNKNOWN) {
SSH_LOG(SSH_LOG_PACKET, "UNKNOWN packet type %d",
session->in_packet.type);
}
#endif
return rc;
}
/* in nonblocking mode, socket_read will read as much as it can, and return */ /* in nonblocking mode, socket_read will read as much as it can, and return */
/* SSH_OK if it has read at least len bytes, otherwise, SSH_AGAIN. */ /* SSH_OK if it has read at least len bytes, otherwise, SSH_AGAIN. */
/* in blocking mode, it will read at least len bytes and will block until it's ok. */ /* in blocking mode, it will read at least len bytes and will block until it's ok. */
@@ -153,6 +923,7 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
uint32_t len, compsize, payloadsize; uint32_t len, compsize, payloadsize;
uint8_t padding; uint8_t padding;
size_t processed = 0; /* number of byte processed from the callback */ size_t processed = 0; /* number of byte processed from the callback */
enum ssh_packet_filter_result_e filter_result;
if(session->current_crypto != NULL) { if(session->current_crypto != NULL) {
current_macsize = hmac_digest_len(session->current_crypto->in_hmac); current_macsize = hmac_digest_len(session->current_crypto->in_hmac);
@@ -328,8 +1099,21 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
"packet: read type %hhd [len=%d,padding=%hhd,comp=%d,payload=%d]", "packet: read type %hhd [len=%d,padding=%hhd,comp=%d,payload=%d]",
session->in_packet.type, len, padding, compsize, payloadsize); session->in_packet.type, len, padding, compsize, payloadsize);
/* Check if the packet is expected */
filter_result = ssh_packet_incoming_filter(session);
switch(filter_result) {
case SSH_PACKET_ALLOWED:
/* Execute callbacks */ /* Execute callbacks */
ssh_packet_process(session, session->in_packet.type); ssh_packet_process(session, session->in_packet.type);
break;
case SSH_PACKET_DENIED:
goto error;
case SSH_PACKET_UNKNOWN:
ssh_packet_send_unimplemented(session, session->recv_seq - 1);
break;
}
session->packet_state = PACKET_STATE_INIT; session->packet_state = PACKET_STATE_INIT;
if (processed < receivedlen) { if (processed < receivedlen) {
/* Handle a potential packet left in socket buffer */ /* Handle a potential packet left in socket buffer */

View File

@@ -271,7 +271,7 @@ int ssh_key_is_public(const ssh_key k) {
return 0; return 0;
} }
return (k->flags & SSH_KEY_FLAG_PUBLIC); return (k->flags & SSH_KEY_FLAG_PUBLIC) == SSH_KEY_FLAG_PUBLIC;
} }
/** /**
@@ -286,7 +286,7 @@ int ssh_key_is_private(const ssh_key k) {
return 0; return 0;
} }
return (k->flags & SSH_KEY_FLAG_PRIVATE); return (k->flags & SSH_KEY_FLAG_PRIVATE) == SSH_KEY_FLAG_PRIVATE;
} }
/** /**
@@ -955,7 +955,7 @@ int ssh_pki_import_pubkey_file(const char *filename, ssh_key *pkey)
return SSH_ERROR; return SSH_ERROR;
} }
file = fopen(filename, "r"); file = fopen(filename, "rb");
if (file == NULL) { if (file == NULL) {
ssh_pki_log("Error opening %s: %s", ssh_pki_log("Error opening %s: %s",
filename, strerror(errno)); filename, strerror(errno));
@@ -999,7 +999,7 @@ int ssh_pki_import_pubkey_file(const char *filename, ssh_key *pkey)
key_buf[size] = '\0'; key_buf[size] = '\0';
q = p = key_buf; q = p = key_buf;
while (!isspace((int)*p)) p++; while (*p != '\0' && !isspace((int)*p)) p++;
*p = '\0'; *p = '\0';
type = ssh_key_type_from_name(q); type = ssh_key_type_from_name(q);
@@ -1008,7 +1008,7 @@ int ssh_pki_import_pubkey_file(const char *filename, ssh_key *pkey)
return SSH_ERROR; return SSH_ERROR;
} }
q = ++p; q = ++p;
while (!isspace((int)*p)) p++; while (*p != '\0' && !isspace((int)*p)) p++;
*p = '\0'; *p = '\0';
rc = ssh_pki_import_pubkey_base64(q, type, pkey); rc = ssh_pki_import_pubkey_base64(q, type, pkey);
@@ -1094,7 +1094,7 @@ error:
* @param[out] pkey A pointer to store the newly allocated public key. You * @param[out] pkey A pointer to store the newly allocated public key. You
* NEED to free the key. * NEED to free the key.
* *
* @return A public key, NULL on error. * @return SSH_OK on success, SSH_ERROR on error.
* *
* @see ssh_key_free() * @see ssh_key_free()
*/ */
@@ -1233,7 +1233,7 @@ int ssh_pki_export_pubkey_file(const ssh_key key,
return SSH_ERROR; return SSH_ERROR;
} }
fp = fopen(filename, "w+"); fp = fopen(filename, "wb+");
if (fp == NULL) { if (fp == NULL) {
return SSH_ERROR; return SSH_ERROR;
} }
@@ -1584,7 +1584,7 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
const ssh_key privkey) const ssh_key privkey)
{ {
struct ssh_crypto_struct *crypto; struct ssh_crypto_struct *crypto;
ssh_signature sig; ssh_signature sig = NULL;
ssh_string sig_blob; ssh_string sig_blob;
int rc; int rc;

View File

@@ -31,6 +31,7 @@
#include <openssl/dsa.h> #include <openssl/dsa.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/rsa.h> #include <openssl/rsa.h>
#include "libcrypto-compat.h"
#ifdef HAVE_OPENSSL_EC_H #ifdef HAVE_OPENSSL_EC_H
#include <openssl/ec.h> #include <openssl/ec.h>
@@ -230,7 +231,10 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
} }
switch (key->type) { switch (key->type) {
case SSH_KEYTYPE_DSS: case SSH_KEYTYPE_DSS: {
const BIGNUM *p = NULL, *q = NULL, *g = NULL,
*pub_key = NULL, *priv_key = NULL;
BIGNUM *np, *nq, *ng, *npub_key, *npriv_key;
new->dsa = DSA_new(); new->dsa = DSA_new();
if (new->dsa == NULL) { if (new->dsa == NULL) {
goto fail; goto fail;
@@ -243,36 +247,54 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
* pub_key = public key y = g^x * pub_key = public key y = g^x
* priv_key = private key x * priv_key = private key x
*/ */
new->dsa->p = BN_dup(key->dsa->p); DSA_get0_pqg(key->dsa, &p, &q, &g);
if (new->dsa->p == NULL) { np = BN_dup(p);
nq = BN_dup(q);
ng = BN_dup(g);
if (np == NULL || nq == NULL || ng == NULL) {
BN_free(np);
BN_free(nq);
BN_free(ng);
goto fail; goto fail;
} }
new->dsa->q = BN_dup(key->dsa->q); rc = DSA_set0_pqg(new->dsa, np, nq, ng);
if (new->dsa->q == NULL) { if (rc == 0) {
BN_free(np);
BN_free(nq);
BN_free(ng);
goto fail; goto fail;
} }
new->dsa->g = BN_dup(key->dsa->g); DSA_get0_key(key->dsa, &pub_key, &priv_key);
if (new->dsa->g == NULL) { npub_key = BN_dup(pub_key);
if (npub_key == NULL) {
goto fail; goto fail;
} }
new->dsa->pub_key = BN_dup(key->dsa->pub_key); rc = DSA_set0_key(new->dsa, npub_key, NULL);
if (new->dsa->pub_key == NULL) { if (rc == 0) {
goto fail; goto fail;
} }
if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) { if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) {
new->dsa->priv_key = BN_dup(key->dsa->priv_key); npriv_key = BN_dup(priv_key);
if (new->dsa->priv_key == NULL) { if (npriv_key == NULL) {
goto fail;
}
rc = DSA_set0_key(new->dsa, NULL, npriv_key);
if (rc == 0) {
goto fail; goto fail;
} }
} }
break; break;
}
case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA:
case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_RSA1: {
const BIGNUM *n = NULL, *e = NULL, *d = NULL;
BIGNUM *nn, *ne, *nd;
new->rsa = RSA_new(); new->rsa = RSA_new();
if (new->rsa == NULL) { if (new->rsa == NULL) {
goto fail; goto fail;
@@ -288,62 +310,82 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
* dmq1 = d mod (q-1) * dmq1 = d mod (q-1)
* iqmp = q^-1 mod p * iqmp = q^-1 mod p
*/ */
new->rsa->n = BN_dup(key->rsa->n); RSA_get0_key(key->rsa, &n, &e, &d);
if (new->rsa->n == NULL) { nn = BN_dup(n);
ne = BN_dup(e);
if (nn == NULL || ne == NULL) {
BN_free(nn);
BN_free(ne);
goto fail; goto fail;
} }
new->rsa->e = BN_dup(key->rsa->e); rc = RSA_set0_key(new->rsa, nn, ne, NULL);
if (new->rsa->e == NULL) { if (rc == 0) {
BN_free(nn);
BN_free(ne);
goto fail; goto fail;
} }
if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) { if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) {
new->rsa->d = BN_dup(key->rsa->d); const BIGNUM *p = NULL, *q = NULL, *dmp1 = NULL,
if (new->rsa->d == NULL) { *dmq1 = NULL, *iqmp = NULL;
BIGNUM *np, *nq, *ndmp1, *ndmq1, *niqmp;
nd = BN_dup(d);
if (nd == NULL) {
goto fail;
}
rc = RSA_set0_key(new->rsa, NULL, NULL, nd);
if (rc == 0) {
goto fail; goto fail;
} }
/* p, q, dmp1, dmq1 and iqmp may be NULL in private keys, but the /* p, q, dmp1, dmq1 and iqmp may be NULL in private keys, but the
* RSA operations are much faster when these values are available. * RSA operations are much faster when these values are available.
*/ */
if (key->rsa->p != NULL) { RSA_get0_factors(key->rsa, &p, &q);
new->rsa->p = BN_dup(key->rsa->p); if (p != NULL && q != NULL) { /* need to set both of them */
if (new->rsa->p == NULL) { np = BN_dup(p);
nq = BN_dup(q);
if (np == NULL || nq == NULL) {
BN_free(np);
BN_free(nq);
goto fail;
}
rc = RSA_set0_factors(new->rsa, np, nq);
if (rc == 0) {
BN_free(np);
BN_free(nq);
goto fail; goto fail;
} }
} }
if (key->rsa->q != NULL) { RSA_get0_crt_params(key->rsa, &dmp1, &dmq1, &iqmp);
new->rsa->q = BN_dup(key->rsa->q); if (dmp1 != NULL || dmq1 != NULL || iqmp != NULL) {
if (new->rsa->q == NULL) { ndmp1 = BN_dup(dmp1);
ndmq1 = BN_dup(dmq1);
niqmp = BN_dup(iqmp);
if (ndmp1 == NULL || ndmq1 == NULL || niqmp == NULL) {
BN_free(ndmp1);
BN_free(ndmq1);
BN_free(niqmp);
goto fail; goto fail;
} }
}
if (key->rsa->dmp1 != NULL) { rc = RSA_set0_crt_params(new->rsa, ndmp1, ndmq1, niqmp);
new->rsa->dmp1 = BN_dup(key->rsa->dmp1); if (rc == 0) {
if (new->rsa->dmp1 == NULL) { BN_free(ndmp1);
goto fail; BN_free(ndmq1);
} BN_free(niqmp);
}
if (key->rsa->dmq1 != NULL) {
new->rsa->dmq1 = BN_dup(key->rsa->dmq1);
if (new->rsa->dmq1 == NULL) {
goto fail;
}
}
if (key->rsa->iqmp != NULL) {
new->rsa->iqmp = BN_dup(key->rsa->iqmp);
if (new->rsa->iqmp == NULL) {
goto fail; goto fail;
} }
} }
} }
break; break;
}
case SSH_KEYTYPE_ECDSA: case SSH_KEYTYPE_ECDSA:
#ifdef HAVE_OPENSSL_ECC #ifdef HAVE_OPENSSL_ECC
new->ecdsa_nid = key->ecdsa_nid; new->ecdsa_nid = key->ecdsa_nid;
@@ -466,51 +508,64 @@ int pki_key_compare(const ssh_key k1,
enum ssh_keycmp_e what) enum ssh_keycmp_e what)
{ {
switch (k1->type) { switch (k1->type) {
case SSH_KEYTYPE_DSS: case SSH_KEYTYPE_DSS: {
const BIGNUM *p1, *p2, *q1, *q2, *g1, *g2,
*pub_key1, *pub_key2, *priv_key1, *priv_key2;
if (DSA_size(k1->dsa) != DSA_size(k2->dsa)) { if (DSA_size(k1->dsa) != DSA_size(k2->dsa)) {
return 1; return 1;
} }
if (bignum_cmp(k1->dsa->p, k2->dsa->p) != 0) { DSA_get0_pqg(k1->dsa, &p1, &q1, &g1);
DSA_get0_pqg(k2->dsa, &p2, &q2, &g2);
if (bignum_cmp(p1, p2) != 0) {
return 1; return 1;
} }
if (bignum_cmp(k1->dsa->q, k2->dsa->q) != 0) { if (bignum_cmp(q1, q2) != 0) {
return 1; return 1;
} }
if (bignum_cmp(k1->dsa->g, k2->dsa->g) != 0) { if (bignum_cmp(g1, g2) != 0) {
return 1; return 1;
} }
if (bignum_cmp(k1->dsa->pub_key, k2->dsa->pub_key) != 0) { DSA_get0_key(k1->dsa, &pub_key1, &priv_key1);
DSA_get0_key(k2->dsa, &pub_key2, &priv_key2);
if (bignum_cmp(pub_key1, pub_key2) != 0) {
return 1; return 1;
} }
if (what == SSH_KEY_CMP_PRIVATE) { if (what == SSH_KEY_CMP_PRIVATE) {
if (bignum_cmp(k1->dsa->priv_key, k2->dsa->priv_key) != 0) { if (bignum_cmp(priv_key1, priv_key2) != 0) {
return 1; return 1;
} }
} }
break; break;
}
case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA:
case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_RSA1: {
const BIGNUM *e1, *e2, *n1, *n2, *p1, *p2, *q1, *q2;
if (RSA_size(k1->rsa) != RSA_size(k2->rsa)) { if (RSA_size(k1->rsa) != RSA_size(k2->rsa)) {
return 1; return 1;
} }
if (bignum_cmp(k1->rsa->e, k2->rsa->e) != 0) { RSA_get0_key(k1->rsa, &n1, &e1, NULL);
RSA_get0_key(k2->rsa, &n2, &e2, NULL);
if (bignum_cmp(e1, e2) != 0) {
return 1; return 1;
} }
if (bignum_cmp(k1->rsa->n, k2->rsa->n) != 0) { if (bignum_cmp(n1, n2) != 0) {
return 1; return 1;
} }
if (what == SSH_KEY_CMP_PRIVATE) { if (what == SSH_KEY_CMP_PRIVATE) {
if (bignum_cmp(k1->rsa->p, k2->rsa->p) != 0) { RSA_get0_factors(k1->rsa, &p1, &q1);
RSA_get0_factors(k2->rsa, &p2, &q2);
if (bignum_cmp(p1, p2) != 0) {
return 1; return 1;
} }
if (bignum_cmp(k1->rsa->q, k2->rsa->q) != 0) { if (bignum_cmp(q1, q2) != 0) {
return 1; return 1;
} }
} }
break; break;
}
case SSH_KEYTYPE_ECDSA: case SSH_KEYTYPE_ECDSA:
#ifdef HAVE_OPENSSL_ECC #ifdef HAVE_OPENSSL_ECC
{ {
@@ -819,19 +874,32 @@ int pki_pubkey_build_dss(ssh_key key,
ssh_string q, ssh_string q,
ssh_string g, ssh_string g,
ssh_string pubkey) { ssh_string pubkey) {
int rc;
BIGNUM *bp, *bq, *bg, *bpub_key;
key->dsa = DSA_new(); key->dsa = DSA_new();
if (key->dsa == NULL) { if (key->dsa == NULL) {
return SSH_ERROR; return SSH_ERROR;
} }
key->dsa->p = make_string_bn(p); bp = make_string_bn(p);
key->dsa->q = make_string_bn(q); bq = make_string_bn(q);
key->dsa->g = make_string_bn(g); bg = make_string_bn(g);
key->dsa->pub_key = make_string_bn(pubkey); bpub_key = make_string_bn(pubkey);
if (key->dsa->p == NULL || if (bp == NULL || bq == NULL ||
key->dsa->q == NULL || bg == NULL || bpub_key == NULL) {
key->dsa->g == NULL || DSA_free(key->dsa);
key->dsa->pub_key == NULL) { return SSH_ERROR;
}
rc = DSA_set0_pqg(key->dsa, bp, bq, bg);
if (rc == 0) {
DSA_free(key->dsa);
return SSH_ERROR;
}
rc = DSA_set0_key(key->dsa, bpub_key, NULL);
if (rc == 0) {
DSA_free(key->dsa); DSA_free(key->dsa);
return SSH_ERROR; return SSH_ERROR;
} }
@@ -842,15 +910,23 @@ int pki_pubkey_build_dss(ssh_key key,
int pki_pubkey_build_rsa(ssh_key key, int pki_pubkey_build_rsa(ssh_key key,
ssh_string e, ssh_string e,
ssh_string n) { ssh_string n) {
int rc;
BIGNUM *be, *bn;
key->rsa = RSA_new(); key->rsa = RSA_new();
if (key->rsa == NULL) { if (key->rsa == NULL) {
return SSH_ERROR; return SSH_ERROR;
} }
key->rsa->e = make_string_bn(e); be = make_string_bn(e);
key->rsa->n = make_string_bn(n); bn = make_string_bn(n);
if (key->rsa->e == NULL || if (be == NULL || bn == NULL) {
key->rsa->n == NULL) { RSA_free(key->rsa);
return SSH_ERROR;
}
rc = RSA_set0_key(key->rsa, bn, be, NULL);
if (rc == 0) {
RSA_free(key->rsa); RSA_free(key->rsa);
return SSH_ERROR; return SSH_ERROR;
} }
@@ -889,23 +965,26 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
} }
switch (key->type) { switch (key->type) {
case SSH_KEYTYPE_DSS: case SSH_KEYTYPE_DSS: {
p = make_bignum_string(key->dsa->p); const BIGNUM *bp, *bq, *bg, *bpub_key;
DSA_get0_pqg(key->dsa, &bp, &bq, &bg);
p = make_bignum_string((BIGNUM *)bp);
if (p == NULL) { if (p == NULL) {
goto fail; goto fail;
} }
q = make_bignum_string(key->dsa->q); q = make_bignum_string((BIGNUM *)bq);
if (q == NULL) { if (q == NULL) {
goto fail; goto fail;
} }
g = make_bignum_string(key->dsa->g); g = make_bignum_string((BIGNUM *)bg);
if (g == NULL) { if (g == NULL) {
goto fail; goto fail;
} }
n = make_bignum_string(key->dsa->pub_key); DSA_get0_key(key->dsa, &bpub_key, NULL);
n = make_bignum_string((BIGNUM *)bpub_key);
if (n == NULL) { if (n == NULL) {
goto fail; goto fail;
} }
@@ -937,14 +1016,17 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
n = NULL; n = NULL;
break; break;
}
case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA:
case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_RSA1: {
e = make_bignum_string(key->rsa->e); const BIGNUM *be, *bn;
RSA_get0_key(key->rsa, &bn, &be, NULL);
e = make_bignum_string((BIGNUM *)be);
if (e == NULL) { if (e == NULL) {
goto fail; goto fail;
} }
n = make_bignum_string(key->rsa->n); n = make_bignum_string((BIGNUM *)bn);
if (n == NULL) { if (n == NULL) {
goto fail; goto fail;
} }
@@ -964,6 +1046,7 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
n = NULL; n = NULL;
break; break;
}
case SSH_KEYTYPE_ECDSA: case SSH_KEYTYPE_ECDSA:
#ifdef HAVE_OPENSSL_ECC #ifdef HAVE_OPENSSL_ECC
rc = ssh_buffer_reinit(buffer); rc = ssh_buffer_reinit(buffer);
@@ -1065,13 +1148,15 @@ int pki_export_pubkey_rsa1(const ssh_key key,
char *e; char *e;
char *n; char *n;
int rsa_size = RSA_size(key->rsa); int rsa_size = RSA_size(key->rsa);
const BIGNUM *be, *bn;
e = bignum_bn2dec(key->rsa->e); RSA_get0_key(key->rsa, &bn, &be, NULL);
e = bignum_bn2dec(be);
if (e == NULL) { if (e == NULL) {
return SSH_ERROR; return SSH_ERROR;
} }
n = bignum_bn2dec(key->rsa->n); n = bignum_bn2dec(bn);
if (n == NULL) { if (n == NULL) {
OPENSSL_free(e); OPENSSL_free(e);
return SSH_ERROR; return SSH_ERROR;
@@ -1136,6 +1221,7 @@ static ssh_string pki_dsa_signature_to_blob(const ssh_signature sig)
{ {
char buffer[40] = { 0 }; char buffer[40] = { 0 };
ssh_string sig_blob = NULL; ssh_string sig_blob = NULL;
const BIGNUM *pr, *ps;
ssh_string r; ssh_string r;
int r_len, r_offset_in, r_offset_out; int r_len, r_offset_in, r_offset_out;
@@ -1143,12 +1229,13 @@ static ssh_string pki_dsa_signature_to_blob(const ssh_signature sig)
ssh_string s; ssh_string s;
int s_len, s_offset_in, s_offset_out; int s_len, s_offset_in, s_offset_out;
r = make_bignum_string(sig->dsa_sig->r); DSA_SIG_get0(sig->dsa_sig, &pr, &ps);
r = make_bignum_string((BIGNUM *)pr);
if (r == NULL) { if (r == NULL) {
return NULL; return NULL;
} }
s = make_bignum_string(sig->dsa_sig->s); s = make_bignum_string((BIGNUM *)ps);
if (s == NULL) { if (s == NULL) {
ssh_string_free(r); ssh_string_free(r);
return NULL; return NULL;
@@ -1201,13 +1288,15 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
ssh_string s; ssh_string s;
ssh_buffer b; ssh_buffer b;
int rc; int rc;
const BIGNUM *pr, *ps;
b = ssh_buffer_new(); b = ssh_buffer_new();
if (b == NULL) { if (b == NULL) {
return NULL; return NULL;
} }
r = make_bignum_string(sig->ecdsa_sig->r); ECDSA_SIG_get0(sig->ecdsa_sig, &pr, &ps);
r = make_bignum_string((BIGNUM *)pr);
if (r == NULL) { if (r == NULL) {
ssh_buffer_free(b); ssh_buffer_free(b);
return NULL; return NULL;
@@ -1219,7 +1308,7 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
return NULL; return NULL;
} }
s = make_bignum_string(sig->ecdsa_sig->s); s = make_bignum_string((BIGNUM *)ps);
if (s == NULL) { if (s == NULL) {
ssh_buffer_free(b); ssh_buffer_free(b);
return NULL; return NULL;
@@ -1324,6 +1413,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
ssh_string s; ssh_string s;
size_t len; size_t len;
int rc; int rc;
BIGNUM *pr = NULL, *ps = NULL;
sig = ssh_signature_new(); sig = ssh_signature_new();
if (sig == NULL) { if (sig == NULL) {
@@ -1363,9 +1453,9 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
} }
ssh_string_fill(r, ssh_string_data(sig_blob), 20); ssh_string_fill(r, ssh_string_data(sig_blob), 20);
sig->dsa_sig->r = make_string_bn(r); pr = make_string_bn(r);
ssh_string_free(r); ssh_string_free(r);
if (sig->dsa_sig->r == NULL) { if (pr == NULL) {
ssh_signature_free(sig); ssh_signature_free(sig);
return NULL; return NULL;
} }
@@ -1377,9 +1467,15 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
} }
ssh_string_fill(s, (char *)ssh_string_data(sig_blob) + 20, 20); ssh_string_fill(s, (char *)ssh_string_data(sig_blob) + 20, 20);
sig->dsa_sig->s = make_string_bn(s); ps = make_string_bn(s);
ssh_string_free(s); ssh_string_free(s);
if (sig->dsa_sig->s == NULL) { if (ps == NULL) {
ssh_signature_free(sig);
return NULL;
}
rc = DSA_SIG_set0(sig->dsa_sig, pr, ps);
if (rc == 0) {
ssh_signature_free(sig); ssh_signature_free(sig);
return NULL; return NULL;
} }
@@ -1427,10 +1523,10 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
ssh_print_hexa("r", ssh_string_data(r), ssh_string_len(r)); ssh_print_hexa("r", ssh_string_data(r), ssh_string_len(r));
#endif #endif
make_string_bn_inplace(r, sig->ecdsa_sig->r); pr = make_string_bn(r);
ssh_string_burn(r); ssh_string_burn(r);
ssh_string_free(r); ssh_string_free(r);
if (sig->ecdsa_sig->r == NULL) { if (pr == NULL) {
ssh_buffer_free(b); ssh_buffer_free(b);
ssh_signature_free(sig); ssh_signature_free(sig);
return NULL; return NULL;
@@ -1448,10 +1544,16 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
ssh_print_hexa("s", ssh_string_data(s), ssh_string_len(s)); ssh_print_hexa("s", ssh_string_data(s), ssh_string_len(s));
#endif #endif
make_string_bn_inplace(s, sig->ecdsa_sig->s); ps = make_string_bn(s);
ssh_string_burn(s); ssh_string_burn(s);
ssh_string_free(s); ssh_string_free(s);
if (sig->ecdsa_sig->s == NULL) { if (ps == NULL) {
ssh_signature_free(sig);
return NULL;
}
rc = ECDSA_SIG_set0(sig->ecdsa_sig, pr, ps);
if (rc == 0) {
ssh_signature_free(sig); ssh_signature_free(sig);
return NULL; return NULL;
} }
@@ -1578,8 +1680,12 @@ ssh_signature pki_do_sign(const ssh_key privkey,
} }
#ifdef DEBUG_CRYPTO #ifdef DEBUG_CRYPTO
ssh_print_bignum("r", sig->dsa_sig->r); {
ssh_print_bignum("s", sig->dsa_sig->s); const BIGNUM *pr, *ps;
DSA_SIG_get0(sig->dsa_sig, &pr, &ps);
ssh_print_bignum("r", (BIGNUM *) pr);
ssh_print_bignum("s", (BIGNUM *) ps);
}
#endif #endif
break; break;
@@ -1601,8 +1707,12 @@ ssh_signature pki_do_sign(const ssh_key privkey,
} }
# ifdef DEBUG_CRYPTO # ifdef DEBUG_CRYPTO
ssh_print_bignum("r", sig->ecdsa_sig->r); {
ssh_print_bignum("s", sig->ecdsa_sig->s); const BIGNUM *pr, *ps;
ECDSA_SIG_get0(sig->ecdsa_sig, &pr, &ps);
ssh_print_bignum("r", (BIGNUM *) pr);
ssh_print_bignum("s", (BIGNUM *) ps);
}
# endif /* DEBUG_CRYPTO */ # endif /* DEBUG_CRYPTO */
break; break;

View File

@@ -35,8 +35,8 @@ int pki_key_generate_ed25519(ssh_key key)
goto error; goto error;
} }
key->ed25519_pubkey = malloc(sizeof (ed25519_privkey)); key->ed25519_pubkey = malloc(sizeof (ed25519_pubkey));
if (key->ed25519_privkey == NULL) { if (key->ed25519_pubkey == NULL) {
goto error; goto error;
} }
@@ -199,23 +199,26 @@ int pki_ed25519_key_cmp(const ssh_key k1,
*/ */
int pki_ed25519_key_dup(ssh_key new, const ssh_key key) int pki_ed25519_key_dup(ssh_key new, const ssh_key key)
{ {
if (key->ed25519_privkey == NULL || key->ed25519_pubkey == NULL) { if (key->ed25519_privkey == NULL && key->ed25519_pubkey == NULL) {
return SSH_ERROR; return SSH_ERROR;
} }
if (key->ed25519_privkey != NULL) {
new->ed25519_privkey = malloc(ED25519_SK_LEN); new->ed25519_privkey = malloc(ED25519_SK_LEN);
if (new->ed25519_privkey == NULL) { if (new->ed25519_privkey == NULL) {
return SSH_ERROR; return SSH_ERROR;
} }
memcpy(new->ed25519_privkey, key->ed25519_privkey, ED25519_SK_LEN);
}
if (key->ed25519_pubkey != NULL) {
new->ed25519_pubkey = malloc(ED25519_PK_LEN); new->ed25519_pubkey = malloc(ED25519_PK_LEN);
if (new->ed25519_privkey == NULL || new->ed25519_pubkey == NULL){ if (new->ed25519_pubkey == NULL) {
SAFE_FREE(new->ed25519_privkey); SAFE_FREE(new->ed25519_privkey);
return SSH_ERROR; return SSH_ERROR;
} }
memcpy(new->ed25519_privkey, key->ed25519_privkey, ED25519_SK_LEN);
memcpy(new->ed25519_pubkey, key->ed25519_pubkey, ED25519_PK_LEN); memcpy(new->ed25519_pubkey, key->ed25519_pubkey, ED25519_PK_LEN);
}
return SSH_OK; return SSH_OK;
} }

View File

@@ -737,7 +737,7 @@ int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e)
ssh_key pki_key_dup(const ssh_key key, int demote) ssh_key pki_key_dup(const ssh_key key, int demote)
{ {
ssh_key new; ssh_key new;
gcry_sexp_t sexp; gcry_sexp_t sexp = NULL;
gcry_error_t err; gcry_error_t err;
const char *tmp = NULL; const char *tmp = NULL;
size_t size; size_t size;

View File

@@ -116,7 +116,11 @@ static poll_fn ssh_poll_emu;
#else /* _WIN32 */ #else /* _WIN32 */
#include <sys/select.h> #include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h> # include <sys/time.h>
# endif
#endif /* _WIN32 */ #endif /* _WIN32 */
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H

View File

@@ -746,7 +746,7 @@ int ssh_message_global_request_reply_success(ssh_message msg, uint16_t bound_por
if(msg->global_request.type == SSH_GLOBAL_REQUEST_TCPIP_FORWARD if(msg->global_request.type == SSH_GLOBAL_REQUEST_TCPIP_FORWARD
&& msg->global_request.bind_port == 0) { && msg->global_request.bind_port == 0) {
rc = ssh_buffer_pack(msg->session->out_buffer, "d", bound_port); rc = ssh_buffer_pack(msg->session->out_buffer, "d", bound_port);
if (rc != SSH_ERROR) { if (rc != SSH_OK) {
ssh_set_error_oom(msg->session); ssh_set_error_oom(msg->session);
goto error; goto error;
} }
@@ -976,6 +976,7 @@ int ssh_message_auth_interactive_request(ssh_message msg, const char *name,
msg->session->kbdint->prompts = NULL; msg->session->kbdint->prompts = NULL;
msg->session->kbdint->echo = NULL; msg->session->kbdint->echo = NULL;
} }
msg->session->auth_state = SSH_AUTH_STATE_INFO;
return rc; return rc;
} }

View File

@@ -31,6 +31,9 @@
#include "libssh/crypto.h" #include "libssh/crypto.h"
#include "libssh/server.h" #include "libssh/server.h"
#include "libssh/socket.h" #include "libssh/socket.h"
#ifdef WITH_SSH1
#include "libssh/ssh1.h"
#endif /* WITH_SSH1 */
#include "libssh/ssh2.h" #include "libssh/ssh2.h"
#include "libssh/agent.h" #include "libssh/agent.h"
#include "libssh/packet.h" #include "libssh/packet.h"
@@ -115,6 +118,15 @@ ssh_session ssh_new(void) {
goto err; goto err;
} }
id = strdup("%d/id_ed25519");
if (id == NULL) {
goto err;
}
rc = ssh_list_append(session->opts.identity, id);
if (rc == SSH_ERROR) {
goto err;
}
#ifdef HAVE_ECC #ifdef HAVE_ECC
id = strdup("%d/id_ecdsa"); id = strdup("%d/id_ecdsa");
if (id == NULL) { if (id == NULL) {
@@ -245,6 +257,10 @@ void ssh_free(ssh_session session) {
ssh_list_free(session->ssh_message_list); ssh_list_free(session->ssh_message_list);
} }
if (session->kbdint != NULL) {
ssh_kbdint_free(session->kbdint);
}
if (session->packet_callbacks) { if (session->packet_callbacks) {
ssh_list_free(session->packet_callbacks); ssh_list_free(session->packet_callbacks);
} }
@@ -261,6 +277,11 @@ void ssh_free(ssh_session session) {
ssh_list_free(session->opts.identity); ssh_list_free(session->opts.identity);
} }
#ifndef _WIN32
ssh_agent_state_free (session->agent_state);
#endif
session->agent_state = NULL;
SAFE_FREE(session->auth_auto_state); SAFE_FREE(session->auth_auto_state);
SAFE_FREE(session->serverbanner); SAFE_FREE(session->serverbanner);
SAFE_FREE(session->clientbanner); SAFE_FREE(session->clientbanner);
@@ -816,13 +837,17 @@ void ssh_socket_exception_callback(int code, int errno_code, void *user){
* @return SSH_OK on success, SSH_ERROR otherwise. * @return SSH_OK on success, SSH_ERROR otherwise.
*/ */
int ssh_send_ignore (ssh_session session, const char *data) { int ssh_send_ignore (ssh_session session, const char *data) {
#ifdef WITH_SSH1
const int type = session->version == 1 ? SSH_MSG_IGNORE : SSH2_MSG_IGNORE;
#else /* WITH_SSH1 */
const int type = SSH2_MSG_IGNORE;
#endif /* WITH_SSH1 */
int rc; int rc;
if (ssh_socket_is_open(session->socket)) { if (ssh_socket_is_open(session->socket)) {
rc = ssh_buffer_pack(session->out_buffer, rc = ssh_buffer_pack(session->out_buffer,
"bs", "bs",
SSH2_MSG_IGNORE, type,
data); data);
if (rc != SSH_OK){ if (rc != SSH_OK){
ssh_set_error_oom(session); ssh_set_error_oom(session);
@@ -854,12 +879,22 @@ int ssh_send_debug (ssh_session session, const char *message, int always_display
int rc; int rc;
if (ssh_socket_is_open(session->socket)) { if (ssh_socket_is_open(session->socket)) {
#ifdef WITH_SSH1
if (session->version == 1) {
rc = ssh_buffer_pack(session->out_buffer,
"bs",
SSH_MSG_DEBUG,
message);
} else
#endif /* WITH_SSH1 */
{
rc = ssh_buffer_pack(session->out_buffer, rc = ssh_buffer_pack(session->out_buffer,
"bbsd", "bbsd",
SSH2_MSG_DEBUG, SSH2_MSG_DEBUG,
always_display != 0 ? 1 : 0, always_display != 0 ? 1 : 0,
message, message,
0); /* empty language tag */ 0); /* empty language tag */
}
if (rc != SSH_OK) { if (rc != SSH_OK) {
ssh_set_error_oom(session); ssh_set_error_oom(session);
goto error; goto error;

View File

@@ -315,7 +315,7 @@ sftp_packet sftp_packet_read(sftp_session sftp) {
sftp_packet packet = NULL; sftp_packet packet = NULL;
uint32_t tmp; uint32_t tmp;
size_t size; size_t size;
int r; int r, s;
packet = malloc(sizeof(struct sftp_packet_struct)); packet = malloc(sizeof(struct sftp_packet_struct));
if (packet == NULL) { if (packet == NULL) {
@@ -330,26 +330,33 @@ sftp_packet sftp_packet_read(sftp_session sftp) {
return NULL; return NULL;
} }
r=ssh_channel_read(sftp->channel, buffer, 4, 0); r=0;
if (r < 0) { do {
ssh_buffer_free(packet->payload); // read from channel until 4 bytes have been read or an error occurs
SAFE_FREE(packet); s=ssh_channel_read(sftp->channel, buffer+r, 4-r, 0);
return NULL; if (s < 0) {
goto error;
} else if (s == 0) {
int is_eof;
is_eof = ssh_channel_is_eof(sftp->channel);
if (is_eof) {
goto error;
} }
} else {
r += s;
}
} while (r<4);
ssh_buffer_add_data(packet->payload, buffer, r); ssh_buffer_add_data(packet->payload, buffer, r);
if (buffer_get_u32(packet->payload, &tmp) != sizeof(uint32_t)) { if (buffer_get_u32(packet->payload, &tmp) != sizeof(uint32_t)) {
ssh_set_error(sftp->session, SSH_FATAL, "Short sftp packet!"); ssh_set_error(sftp->session, SSH_FATAL, "Short sftp packet!");
ssh_buffer_free(packet->payload); goto error;
SAFE_FREE(packet);
return NULL;
} }
r=ssh_channel_read(sftp->channel, buffer, 1, 0); r=ssh_channel_read(sftp->channel, buffer, 1, 0);
if (r <= 0) { if (r <= 0) {
/* TODO: check if there are cases where an error needs to be set here */ /* TODO: check if there are cases where an error needs to be set here */
ssh_buffer_free(packet->payload); goto error;
SAFE_FREE(packet);
return NULL;
} }
ssh_buffer_add_data(packet->payload, buffer, r); ssh_buffer_add_data(packet->payload, buffer, r);
buffer_get_u8(packet->payload, &packet->type); buffer_get_u8(packet->payload, &packet->type);
@@ -366,20 +373,20 @@ sftp_packet sftp_packet_read(sftp_session sftp) {
if(r <= 0) { if(r <= 0) {
/* TODO: check if there are cases where an error needs to be set here */ /* TODO: check if there are cases where an error needs to be set here */
ssh_buffer_free(packet->payload); goto error;
SAFE_FREE(packet);
return NULL;
} }
if (ssh_buffer_add_data(packet->payload, buffer, r) == SSH_ERROR) { if (ssh_buffer_add_data(packet->payload, buffer, r) == SSH_ERROR) {
ssh_buffer_free(packet->payload);
SAFE_FREE(packet);
ssh_set_error_oom(sftp->session); ssh_set_error_oom(sftp->session);
return NULL; goto error;
} }
size -= r; size -= r;
} }
return packet; return packet;
error:
ssh_buffer_free(packet->payload);
SAFE_FREE(packet);
return NULL;
} }
static void sftp_set_error(sftp_session sftp, int errnum) { static void sftp_set_error(sftp_session sftp, int errnum) {
@@ -3070,7 +3077,10 @@ sftp_attributes sftp_fstat(sftp_file file) {
} }
if (msg->packet_type == SSH_FXP_ATTRS){ if (msg->packet_type == SSH_FXP_ATTRS){
return sftp_parse_attr(file->sftp, msg->payload, 0); sftp_attributes attr = sftp_parse_attr(file->sftp, msg->payload, 0);
sftp_message_free(msg);
return attr;
} else if (msg->packet_type == SSH_FXP_STATUS) { } else if (msg->packet_type == SSH_FXP_STATUS) {
status = parse_status_msg(msg); status = parse_status_msg(msg);
sftp_message_free(msg); sftp_message_free(msg);

View File

@@ -194,9 +194,8 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
break; break;
case SSH_FXP_FSTAT: case SSH_FXP_FSTAT:
rc = ssh_buffer_unpack(payload, rc = ssh_buffer_unpack(payload,
"Sd", "S",
&msg->handle, &msg->handle);
&msg->flags);
if (rc != SSH_OK) { if (rc != SSH_OK) {
ssh_set_error_oom(session); ssh_set_error_oom(session);
sftp_client_message_free(msg); sftp_client_message_free(msg);

View File

@@ -27,8 +27,9 @@ set(LIBSSH_THREADS_LINK_LIBRARIES
${LIBSSH_SHARED_LIBRARY} ${LIBSSH_SHARED_LIBRARY}
) )
set(libssh_threads_SRCS message(STATUS "threads library: Threads_FOUND=${Threads_FOUND}")
)
set(libssh_threads_SRCS) # empty SRC
# build and link pthread # build and link pthread
if (CMAKE_USE_PTHREADS_INIT) if (CMAKE_USE_PTHREADS_INIT)
@@ -41,6 +42,8 @@ if (CMAKE_USE_PTHREADS_INIT)
${LIBSSH_THREADS_LINK_LIBRARIES} ${LIBSSH_THREADS_LINK_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT} ${CMAKE_THREAD_LIBS_INIT}
) )
message(STATUS "libssh_threads_SRCS=${libssh_threads_SRCS}")
endif (CMAKE_USE_PTHREADS_INIT) endif (CMAKE_USE_PTHREADS_INIT)
set(LIBSSH_THREADS_LINK_LIBRARIES set(LIBSSH_THREADS_LINK_LIBRARIES
@@ -54,6 +57,8 @@ include_directories(
) )
if (libssh_threads_SRCS) if (libssh_threads_SRCS)
set(LIBSSH_THREADS ON CACHE "libssh threads lib" INTERNAL)
add_library(${LIBSSH_THREADS_SHARED_LIBRARY} SHARED ${libssh_threads_SRCS}) add_library(${LIBSSH_THREADS_SHARED_LIBRARY} SHARED ${libssh_threads_SRCS})
target_link_libraries(${LIBSSH_THREADS_SHARED_LIBRARY} ${LIBSSH_THREADS_LINK_LIBRARIES}) target_link_libraries(${LIBSSH_THREADS_SHARED_LIBRARY} ${LIBSSH_THREADS_LINK_LIBRARIES})

View File

@@ -160,6 +160,10 @@ void crypto_free(struct ssh_crypto_struct *crypto){
#ifdef HAVE_ECDH #ifdef HAVE_ECDH
SAFE_FREE(crypto->ecdh_client_pubkey); SAFE_FREE(crypto->ecdh_client_pubkey);
SAFE_FREE(crypto->ecdh_server_pubkey); SAFE_FREE(crypto->ecdh_server_pubkey);
if(crypto->ecdh_privkey != NULL){
EC_KEY_free(crypto->ecdh_privkey);
crypto->ecdh_privkey = NULL;
}
#endif #endif
if(crypto->session_id != NULL){ if(crypto->session_id != NULL){
memset(crypto->session_id, '\0', crypto->digest_len); memset(crypto->session_id, '\0', crypto->digest_len);

View File

@@ -1,4 +1,4 @@
project(tests C) project(libssh-tests C)
if (BSD OR SOLARIS OR OSX) if (BSD OR SOLARIS OR OSX)
find_package(Argp) find_package(Argp)
@@ -9,9 +9,9 @@ set(TORTURE_LIBRARY torture)
include_directories( include_directories(
${LIBSSH_PUBLIC_INCLUDE_DIRS} ${LIBSSH_PUBLIC_INCLUDE_DIRS}
${CMOCKA_INCLUDE_DIR} ${CMOCKA_INCLUDE_DIR}
${OPENSSL_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR}
${GCRYPT_INCLUDE_DIRS} ${GCRYPT_INCLUDE_DIR}
${ZLIB_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIR}
${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
@@ -22,12 +22,12 @@ set(TORTURE_LINK_LIBRARIES
${LIBSSH_STATIC_LIBRARY} ${LIBSSH_STATIC_LIBRARY}
${LIBSSH_LINK_LIBRARIES}) ${LIBSSH_LINK_LIBRARIES})
if (Threads_FOUND) if (LIBSSH_THREADS)
set(TORTURE_LINK_LIBRARIES set(TORTURE_LINK_LIBRARIES
${TORTURE_LINK_LIBRARIES} ${TORTURE_LINK_LIBRARIES}
${LIBSSH_THREADS_STATIC_LIBRARY} ${LIBSSH_THREADS_STATIC_LIBRARY}
${LIBSSH_THREADS_LINK_LIBRARIES}) ${LIBSSH_THREADS_LINK_LIBRARIES})
endif () endif (LIBSSH_THREADS)
# create test library # create test library
add_library(${TORTURE_LIBRARY} STATIC cmdline.c torture.c) add_library(${TORTURE_LIBRARY} STATIC cmdline.c torture.c)
@@ -44,6 +44,68 @@ set(TEST_TARGET_LIBRARIES
add_subdirectory(unittests) add_subdirectory(unittests)
if (WITH_CLIENT_TESTING) if (WITH_CLIENT_TESTING)
find_package(socket_wrapper 1.1.5 REQUIRED)
find_package(nss_wrapper 1.1.2 REQUIRED)
find_package(uid_wrapper 1.2.0 REQUIRED)
find_package(pam_wrapper 1.0.0 REQUIRED)
find_program(SSHD_EXECUTABLE
NAME
sshd
PATHS
/sbin
/usr/sbin
/usr/local/sbin)
if (NOT SSHD_EXECUTABLE)
message(SEND_ERROR "Could not find sshd which is required for client testing")
endif()
find_program(SSH_EXECUTABLE NAMES ssh)
if (SSH_EXECUTABLE)
execute_process(COMMAND ${SSH_EXECUTABLE} -V ERROR_VARIABLE OPENSSH_VERSION_STR)
string(REGEX REPLACE "^OpenSSH_([0-9]).[0-9].*$" "\\1" OPENSSH_VERSION_MAJOR "${OPENSSH_VERSION_STR}")
string(REGEX REPLACE "^OpenSSH_[0-9].([0-9]).*$" "\\1" OPENSSH_VERSION_MINOR "${OPENSSH_VERSION_STR}")
add_definitions(-DOPENSSH_VERSION_MAJOR=${OPENSSH_VERSION_MAJOR} -DOPENSSH_VERSION_MINOR=${OPENSSH_VERSION_MINOR})
endif()
# chroot_wrapper
add_library(chroot_wrapper SHARED chroot_wrapper.c)
set(CHROOT_WRAPPER_LIBRARY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}chroot_wrapper${CMAKE_SHARED_LIBRARY_SUFFIX})
set(TEST_TARGET_LIBRARIES
${TEST_TARGET_LIBRARIES}
chroot_wrapper
)
# homedir will be used in passwd
set(HOMEDIR ${CMAKE_CURRENT_BINARY_DIR}/home)
### Setup nss_wrapper
configure_file(etc/passwd.in ${CMAKE_CURRENT_BINARY_DIR}/etc/passwd @ONLY)
configure_file(etc/shadow.in ${CMAKE_CURRENT_BINARY_DIR}/etc/shadow @ONLY)
configure_file(etc/group.in ${CMAKE_CURRENT_BINARY_DIR}/etc/group @ONLY)
configure_file(etc/hosts.in ${CMAKE_CURRENT_BINARY_DIR}/etc/hosts @ONLY)
### Setup pam_wrapper
configure_file(etc/pam_matrix_passdb.in ${CMAKE_CURRENT_BINARY_DIR}/etc/pam_matrix_passdb @ONLY)
configure_file(etc/pam.d/sshd.in ${CMAKE_CURRENT_BINARY_DIR}/etc/pam.d/sshd @ONLY)
set(TORTURE_ENVIRONMENT "LD_PRELOAD=${SOCKET_WRAPPER_LIBRARY}:${NSS_WRAPPER_LIBRARY}:${UID_WRAPPER_LIBRARY}:${PAM_WRAPPER_LIBRARY}:${CHROOT_WRAPPER_LIBRARY}")
list(APPEND TORTURE_ENVIRONMENT UID_WRAPPER=1 UID_WRAPPER_ROOT=1)
list(APPEND TORTURE_ENVIRONMENT NSS_WRAPPER_PASSWD=${CMAKE_CURRENT_BINARY_DIR}/etc/passwd)
list(APPEND TORTURE_ENVIRONMENT NSS_WRAPPER_SHADOW=${CMAKE_CURRENT_BINARY_DIR}/etc/shadow)
list(APPEND TORTURE_ENVIRONMENT NSS_WRAPPER_GROUP=${CMAKE_CURRENT_BINARY_DIR}/etc/group)
list(APPEND TORTURE_ENVIRONMENT PAM_WRAPPER_SERVICE_DIR=${CMAKE_CURRENT_BINARY_DIR}/etc/pam.d)
# 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)
# 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)
message(STATUS "TORTURE_ENVIRONMENT=${TORTURE_ENVIRONMENT}")
add_subdirectory(client) add_subdirectory(client)
endif (WITH_CLIENT_TESTING) endif (WITH_CLIENT_TESTING)

View File

@@ -45,7 +45,7 @@ int benchmarks_sync_sftp_up (ssh_session session, struct argument_s *args,
float ms=0.0; float ms=0.0;
unsigned long total=0; unsigned long total=0;
sftp_session sftp; sftp_session sftp;
sftp_file file; sftp_file file = NULL;
bytes = args->datasize * 1024 * 1024; bytes = args->datasize * 1024 * 1024;
sftp = sftp_new(session); sftp = sftp_new(session);
@@ -101,7 +101,7 @@ int benchmarks_sync_sftp_down (ssh_session session, struct argument_s *args,
float ms=0.0; float ms=0.0;
unsigned long total=0; unsigned long total=0;
sftp_session sftp; sftp_session sftp;
sftp_file file; sftp_file file = NULL;
int r; int r;
bytes = args->datasize * 1024 * 1024; bytes = args->datasize * 1024 * 1024;
@@ -163,7 +163,7 @@ int benchmarks_async_sftp_down (ssh_session session, struct argument_s *args,
float ms=0.0; float ms=0.0;
unsigned long total=0; unsigned long total=0;
sftp_session sftp; sftp_session sftp;
sftp_file file; sftp_file file = NULL;
int r,i; int r,i;
int warned = 0; int warned = 0;
unsigned long toread; unsigned long toread;

8
tests/chroot_wrapper.c Normal file
View File

@@ -0,0 +1,8 @@
/* silent gcc */
int chroot(const char *);
int chroot(const char *path)
{
(void)path;
return 0;
}

View File

@@ -1,15 +1,41 @@
project(clienttests C) project(clienttests C)
add_cmocka_test(torture_algorithms torture_algorithms.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_auth torture_auth.c ${TORTURE_LIBRARY}) add_cmocka_test(torture_auth torture_auth.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_connect torture_connect.c ${TORTURE_LIBRARY}) add_cmocka_test(torture_connect torture_connect.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_knownhosts torture_knownhosts.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_proxycommand torture_proxycommand.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_session torture_session.c ${TORTURE_LIBRARY}) add_cmocka_test(torture_session torture_session.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_forward torture_forward.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_request_env torture_request_env.c ${TORTURE_LIBRARY})
if (WITH_SFTP) if (WITH_SFTP)
add_cmocka_test(torture_sftp_static torture_sftp_static.c ${TORTURE_LIBRARY}) add_cmocka_test(torture_sftp_static torture_sftp_static.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_sftp_dir torture_sftp_dir.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_sftp_read torture_sftp_read.c ${TORTURE_LIBRARY})
endif (WITH_SFTP) endif (WITH_SFTP)
set(LIBSSH_CLIENT_TESTS
torture_algorithms
torture_knownhosts
torture_request_env
torture_forward
torture_proxycommand)
if (WITH_SFTP)
set(LIBSSH_CLIENT_TESTS
${LIBSSH_CLIENT_TESTS}
torture_sftp_dir
torture_sftp_read)
endif (WITH_SFTP)
foreach(_CLI_TEST ${LIBSSH_CLIENT_TESTS})
add_cmocka_test(${_CLI_TEST} ${_CLI_TEST}.c ${TORTURE_LIBRARY})
if (OSX)
set_property(
TEST
${_CLI_TEST}
PROPERTY
ENVIRONMENT DYLD_FORCE_FLAT_NAMESPACE=1;DYLD_INSERT_LIBRARIES=${SOCKET_WRAPPER_LIBRARY})
else ()
set_property(
TEST
${_CLI_TEST}
PROPERTY
ENVIRONMENT ${TORTURE_ENVIRONMENT})
endif()
endforeach()

View File

@@ -25,11 +25,37 @@
#include "libssh/libssh.h" #include "libssh/libssh.h"
#include "libssh/priv.h" #include "libssh/priv.h"
#include <errno.h>
#include <sys/types.h>
#include <pwd.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 void setup(void **state) { static void setup(void **state) {
int verbosity=torture_libssh_verbosity(); int verbosity=torture_libssh_verbosity();
ssh_session session = ssh_new(); ssh_session session = ssh_new();
struct passwd *pwd;
int rc;
pwd = getpwnam("bob");
assert_non_null(pwd);
rc = setuid(pwd->pw_uid);
assert_return_code(rc, errno);
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
*state = session; *state = session;
} }
@@ -40,9 +66,6 @@ static void teardown(void **state) {
static void test_algorithm(ssh_session session, const char *algo, const char *hmac) { static void test_algorithm(ssh_session session, const char *algo, const char *hmac) {
int rc; int rc;
rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
assert_true(rc == SSH_OK);
rc = ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, algo); rc = ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, algo);
assert_true(rc == SSH_OK); assert_true(rc == SSH_OK);
@@ -151,6 +174,7 @@ static void torture_algorithms_3des_cbc_hmac_sha2_512(void **state) {
test_algorithm(*state, "3des-cbc", "hmac-sha2-512"); test_algorithm(*state, "3des-cbc", "hmac-sha2-512");
} }
#if ((OPENSSH_VERSION_MAJOR == 7 && OPENSSH_VERSION_MINOR < 6) || OPENSSH_VERSION_MAJOR <= 6)
static void torture_algorithms_blowfish_cbc_hmac_sha1(void **state) { static void torture_algorithms_blowfish_cbc_hmac_sha1(void **state) {
test_algorithm(*state, "blowfish-cbc", "hmac-sha1"); test_algorithm(*state, "blowfish-cbc", "hmac-sha1");
} }
@@ -162,14 +186,12 @@ static void torture_algorithms_blowfish_cbc_hmac_sha2_256(void **state) {
static void torture_algorithms_blowfish_cbc_hmac_sha2_512(void **state) { static void torture_algorithms_blowfish_cbc_hmac_sha2_512(void **state) {
test_algorithm(*state, "blowfish-cbc", "hmac-sha2-512"); test_algorithm(*state, "blowfish-cbc", "hmac-sha2-512");
} }
#endif
static void torture_algorithms_zlib(void **state) { static void torture_algorithms_zlib(void **state) {
ssh_session session = *state; ssh_session session = *state;
int rc; int rc;
rc = ssh_options_set(session,SSH_OPTIONS_HOST,"localhost");
assert_true(rc == SSH_OK);
rc = ssh_options_set(session, SSH_OPTIONS_COMPRESSION_C_S, "zlib"); rc = ssh_options_set(session, SSH_OPTIONS_COMPRESSION_C_S, "zlib");
#ifdef WITH_ZLIB #ifdef WITH_ZLIB
assert_true(rc == SSH_OK); assert_true(rc == SSH_OK);
@@ -207,9 +229,6 @@ static void torture_algorithms_zlib_openssh(void **state) {
ssh_session session = *state; ssh_session session = *state;
int rc; int rc;
rc = ssh_options_set(session,SSH_OPTIONS_HOST,"localhost");
assert_true(rc == SSH_OK);
rc = ssh_options_set(session, SSH_OPTIONS_COMPRESSION_C_S, "zlib@openssh.com"); rc = ssh_options_set(session, SSH_OPTIONS_COMPRESSION_C_S, "zlib@openssh.com");
#ifdef WITH_ZLIB #ifdef WITH_ZLIB
assert_true(rc == SSH_OK); assert_true(rc == SSH_OK);
@@ -249,9 +268,6 @@ static void torture_algorithms_ecdh_sha2_nistp256(void **state) {
ssh_session session = *state; ssh_session session = *state;
int rc; int rc;
rc = ssh_options_set(session,SSH_OPTIONS_HOST,"localhost");
assert_true(rc == SSH_OK);
rc = ssh_options_set(session, SSH_OPTIONS_KEY_EXCHANGE, "ecdh-sha2-nistp256"); rc = ssh_options_set(session, SSH_OPTIONS_KEY_EXCHANGE, "ecdh-sha2-nistp256");
assert_true(rc == SSH_OK); assert_true(rc == SSH_OK);
@@ -271,9 +287,6 @@ static void torture_algorithms_dh_group1(void **state) {
ssh_session session = *state; ssh_session session = *state;
int rc; int rc;
rc = ssh_options_set(session,SSH_OPTIONS_HOST,"localhost");
assert_true(rc == SSH_OK);
rc = ssh_options_set(session, SSH_OPTIONS_KEY_EXCHANGE, "diffie-hellman-group1-sha1"); rc = ssh_options_set(session, SSH_OPTIONS_KEY_EXCHANGE, "diffie-hellman-group1-sha1");
assert_true(rc == SSH_OK); assert_true(rc == SSH_OK);
@@ -289,6 +302,7 @@ static void torture_algorithms_dh_group1(void **state) {
} }
int torture_run_tests(void) { int torture_run_tests(void) {
int rc; int rc;
struct torture_state *s = NULL;
UnitTest tests[] = { UnitTest tests[] = {
unit_test_setup_teardown(torture_algorithms_aes128_cbc_hmac_sha1, setup, teardown), unit_test_setup_teardown(torture_algorithms_aes128_cbc_hmac_sha1, setup, teardown),
unit_test_setup_teardown(torture_algorithms_aes128_cbc_hmac_sha2_256, setup, teardown), unit_test_setup_teardown(torture_algorithms_aes128_cbc_hmac_sha2_256, setup, teardown),
@@ -311,9 +325,11 @@ int torture_run_tests(void) {
unit_test_setup_teardown(torture_algorithms_3des_cbc_hmac_sha1, setup, teardown), unit_test_setup_teardown(torture_algorithms_3des_cbc_hmac_sha1, setup, teardown),
unit_test_setup_teardown(torture_algorithms_3des_cbc_hmac_sha2_256, setup, teardown), unit_test_setup_teardown(torture_algorithms_3des_cbc_hmac_sha2_256, setup, teardown),
unit_test_setup_teardown(torture_algorithms_3des_cbc_hmac_sha2_512, setup, teardown), unit_test_setup_teardown(torture_algorithms_3des_cbc_hmac_sha2_512, setup, teardown),
#if ((OPENSSH_VERSION_MAJOR == 7 && OPENSSH_VERSION_MINOR < 6) || OPENSSH_VERSION_MAJOR <= 6)
unit_test_setup_teardown(torture_algorithms_blowfish_cbc_hmac_sha1, setup, teardown), unit_test_setup_teardown(torture_algorithms_blowfish_cbc_hmac_sha1, setup, teardown),
unit_test_setup_teardown(torture_algorithms_blowfish_cbc_hmac_sha2_256, setup, teardown), unit_test_setup_teardown(torture_algorithms_blowfish_cbc_hmac_sha2_256, setup, teardown),
unit_test_setup_teardown(torture_algorithms_blowfish_cbc_hmac_sha2_512, setup, teardown), unit_test_setup_teardown(torture_algorithms_blowfish_cbc_hmac_sha2_512, setup, teardown),
#endif
unit_test_setup_teardown(torture_algorithms_zlib, setup, teardown), unit_test_setup_teardown(torture_algorithms_zlib, setup, teardown),
unit_test_setup_teardown(torture_algorithms_zlib_openssh, setup, teardown), unit_test_setup_teardown(torture_algorithms_zlib_openssh, setup, teardown),
unit_test_setup_teardown(torture_algorithms_dh_group1,setup,teardown), unit_test_setup_teardown(torture_algorithms_dh_group1,setup,teardown),
@@ -324,7 +340,9 @@ int torture_run_tests(void) {
ssh_init(); ssh_init();
torture_filter_tests(tests); torture_filter_tests(tests);
sshd_setup((void **)&s);
rc = run_tests(tests); rc = run_tests(tests);
sshd_teardown((void **)&s);
ssh_finalize(); ssh_finalize();
return rc; return rc;

View File

@@ -24,24 +24,42 @@
#include "torture.h" #include "torture.h"
#include <libssh/libssh.h> #include <libssh/libssh.h>
#include <errno.h>
#include <sys/types.h>
#include <pwd.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 void setup(void **state) static void setup(void **state)
{ {
ssh_session session; ssh_session session;
const char *host; struct passwd *pwd;
const char *user; int rc;
const char *password;
host = getenv("TORTURE_HOST"); pwd = getpwnam("bob");
if (host == NULL) { assert_non_null(pwd);
host = "localhost";
}
user = getenv("TORTURE_USER"); rc = setuid(pwd->pw_uid);
password = getenv("TORTURE_PASSWORD"); assert_return_code(rc, errno);
session = torture_ssh_session(host, NULL, user, password); session = torture_ssh_session(TORTURE_SSH_SERVER,
NULL,
TORTURE_SSH_USER_ALICE,
NULL);
assert_non_null(session); assert_non_null(session);
*state = session; *state = session;
} }
@@ -60,26 +78,25 @@ static void teardown(void **state)
static void torture_ssh_forward(void **state) static void torture_ssh_forward(void **state)
{ {
ssh_session session = (ssh_session) *state; ssh_session session = (ssh_session) *state;
#if 0
ssh_channel c; ssh_channel c;
#endif int dport;
int bound_port; int bound_port;
int rc; int rc;
rc = ssh_channel_listen_forward(session, "127.0.0.1", 8080, &bound_port); rc = ssh_channel_listen_forward(session, "127.0.0.21", 8080, &bound_port);
assert_int_equal(rc, SSH_OK); assert_int_equal(rc, SSH_OK);
#if 0 c = ssh_channel_accept_forward(session, 10, &dport);
c = ssh_forward_accept(session, 60000); /* We do not get a listener and run into the timeout here */
assert_non_null(c); assert_null(c);
ssh_channel_send_eof(c); ssh_channel_send_eof(c);
ssh_channel_close(c); ssh_channel_close(c);
#endif
} }
int torture_run_tests(void) { int torture_run_tests(void) {
int rc; int rc;
struct torture_state *s = NULL;
UnitTest tests[] = { UnitTest tests[] = {
unit_test_setup_teardown(torture_ssh_forward, setup, teardown), unit_test_setup_teardown(torture_ssh_forward, setup, teardown),
@@ -88,7 +105,9 @@ int torture_run_tests(void) {
ssh_init(); ssh_init();
torture_filter_tests(tests); torture_filter_tests(tests);
sshd_setup((void **)&s);
rc = run_tests(tests); rc = run_tests(tests);
sshd_teardown((void **)&s);
ssh_finalize(); ssh_finalize();
return rc; return rc;

View File

@@ -25,6 +25,9 @@
#include "session.c" #include "session.c"
#include "known_hosts.c" #include "known_hosts.c"
#include <sys/types.h>
#include <pwd.h>
#define KNOWNHOSTFILES "libssh_torture_knownhosts" #define KNOWNHOSTFILES "libssh_torture_knownhosts"
#define BADRSA "AAAAB3NzaC1yc2EAAAADAQABAAABAQChm5" \ #define BADRSA "AAAAB3NzaC1yc2EAAAADAQABAAABAQChm5" \
"a6Av65O8cKtx5YXOnui3wJnYE6A6J/I4kZSAibbn14Jcl+34VJQwv96f25AxNmo" \ "a6Av65O8cKtx5YXOnui3wJnYE6A6J/I4kZSAibbn14Jcl+34VJQwv96f25AxNmo" \
@@ -44,11 +47,31 @@
"h0dSi8VJXI1wes5HTyLsv9VBmU1uCXUUvufoQKfF/OcSH0ufcCpnd62g1/adZcy2" \ "h0dSi8VJXI1wes5HTyLsv9VBmU1uCXUUvufoQKfF/OcSH0ufcCpnd62g1/adZcy2" \
"WJg==" "WJg=="
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 void setup(void **state) { static void setup(void **state) {
int verbosity=torture_libssh_verbosity(); int verbosity=torture_libssh_verbosity();
ssh_session session = ssh_new(); ssh_session session = ssh_new();
struct passwd *pwd;
pwd = getpwnam("bob");
assert_non_null(pwd);
setuid(pwd->pw_uid);
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
*state = session; *state = session;
} }
@@ -73,8 +96,6 @@ static void torture_knownhosts_port(void **state) {
* the known hosts file. Then check that the entry written is * the known hosts file. Then check that the entry written is
* [localhost]:1234 * [localhost]:1234
*/ */
rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
assert_true(rc == SSH_OK);
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
assert_true(rc == SSH_OK); assert_true(rc == SSH_OK);
@@ -92,7 +113,7 @@ static void torture_knownhosts_port(void **state) {
assert_false(p == NULL); assert_false(p == NULL);
fclose(file); fclose(file);
buffer[sizeof(buffer) - 1] = '\0'; buffer[sizeof(buffer) - 1] = '\0';
assert_true(strstr(buffer,"[localhost]:1234 ") != NULL); assert_true(strstr(buffer,"[127.0.0.10]:1234 ") != NULL);
ssh_disconnect(session); ssh_disconnect(session);
ssh_free(session); ssh_free(session);
@@ -100,7 +121,7 @@ static void torture_knownhosts_port(void **state) {
/* Now, connect back to the ssh server and verify the known host line */ /* Now, connect back to the ssh server and verify the known host line */
*state = session = ssh_new(); *state = session = ssh_new();
ssh_options_set(session, SSH_OPTIONS_HOST, "localhost"); ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES); ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
rc = ssh_connect(session); rc = ssh_connect(session);
@@ -116,9 +137,6 @@ static void torture_knownhosts_fail(void **state) {
FILE *file; FILE *file;
int rc; int rc;
rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
assert_true(rc == SSH_OK);
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
assert_true(rc == SSH_OK); assert_true(rc == SSH_OK);
@@ -127,7 +145,7 @@ static void torture_knownhosts_fail(void **state) {
file = fopen(KNOWNHOSTFILES, "w"); file = fopen(KNOWNHOSTFILES, "w");
assert_true(file != NULL); assert_true(file != NULL);
fprintf(file, "localhost ssh-rsa %s\n", BADRSA); fprintf(file, TORTURE_SSH_SERVER " ssh-rsa %s\n", BADRSA);
fclose(file); fclose(file);
rc = ssh_connect(session); rc = ssh_connect(session);
@@ -142,9 +160,6 @@ static void torture_knownhosts_other(void **state) {
FILE *file; FILE *file;
int rc; int rc;
rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
assert_true(rc == SSH_OK);
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
assert_true(rc == SSH_OK); assert_true(rc == SSH_OK);
@@ -153,7 +168,7 @@ static void torture_knownhosts_other(void **state) {
file = fopen(KNOWNHOSTFILES, "w"); file = fopen(KNOWNHOSTFILES, "w");
assert_true(file != NULL); assert_true(file != NULL);
fprintf(file, "localhost ssh-rsa %s\n", BADRSA); fprintf(file, TORTURE_SSH_SERVER " ssh-rsa %s\n", BADRSA);
fclose(file); fclose(file);
rc = ssh_connect(session); rc = ssh_connect(session);
@@ -167,9 +182,6 @@ static void torture_knownhosts_other_auto(void **state) {
ssh_session session = *state; ssh_session session = *state;
int rc; int rc;
rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
assert_true(rc == SSH_OK);
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
assert_true(rc == SSH_OK); assert_true(rc == SSH_OK);
@@ -191,7 +203,7 @@ static void torture_knownhosts_other_auto(void **state) {
/* connect again and check host key */ /* connect again and check host key */
*state = session = ssh_new(); *state = session = ssh_new();
rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost"); rc = ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
assert_true(rc == SSH_OK); assert_true(rc == SSH_OK);
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
@@ -210,9 +222,6 @@ static void torture_knownhosts_conflict(void **state) {
FILE *file; FILE *file;
int rc; int rc;
rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
assert_true(rc == SSH_OK);
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
assert_true(rc == SSH_OK); assert_true(rc == SSH_OK);
@@ -221,8 +230,8 @@ static void torture_knownhosts_conflict(void **state) {
file = fopen(KNOWNHOSTFILES, "w"); file = fopen(KNOWNHOSTFILES, "w");
assert_true(file != NULL); assert_true(file != NULL);
fprintf(file, "localhost ssh-rsa %s\n", BADRSA); fprintf(file, TORTURE_SSH_SERVER " ssh-rsa %s\n", BADRSA);
fprintf(file, "localhost ssh-dss %s\n", BADDSA); fprintf(file, TORTURE_SSH_SERVER " ssh-dss %s\n", BADDSA);
fclose(file); fclose(file);
rc = ssh_connect(session); rc = ssh_connect(session);
@@ -240,7 +249,7 @@ static void torture_knownhosts_conflict(void **state) {
/* connect again and check host key */ /* connect again and check host key */
*state = session = ssh_new(); *state = session = ssh_new();
ssh_options_set(session, SSH_OPTIONS_HOST, "localhost"); ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES); ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "ssh-rsa"); rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "ssh-rsa");
assert_true(rc == SSH_OK); assert_true(rc == SSH_OK);
@@ -258,16 +267,13 @@ static void torture_knownhosts_precheck(void **state) {
int rc; int rc;
char **kex; char **kex;
rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
assert_true(rc == SSH_OK);
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
assert_true(rc == SSH_OK); assert_true(rc == SSH_OK);
file = fopen(KNOWNHOSTFILES, "w"); file = fopen(KNOWNHOSTFILES, "w");
assert_true(file != NULL); assert_true(file != NULL);
fprintf(file, "localhost ssh-rsa %s\n", BADRSA); fprintf(file, TORTURE_SSH_SERVER " ssh-rsa %s\n", BADRSA);
fprintf(file, "localhost ssh-dss %s\n", BADDSA); fprintf(file, TORTURE_SSH_SERVER " ssh-dss %s\n", BADDSA);
fclose(file); fclose(file);
kex = ssh_knownhosts_algorithms(session); kex = ssh_knownhosts_algorithms(session);
@@ -282,6 +288,7 @@ static void torture_knownhosts_precheck(void **state) {
int torture_run_tests(void) { int torture_run_tests(void) {
int rc; int rc;
struct torture_state *s = NULL;
UnitTest tests[] = { UnitTest tests[] = {
unit_test_setup_teardown(torture_knownhosts_port, setup, teardown), unit_test_setup_teardown(torture_knownhosts_port, setup, teardown),
unit_test_setup_teardown(torture_knownhosts_fail, setup, teardown), unit_test_setup_teardown(torture_knownhosts_fail, setup, teardown),
@@ -294,7 +301,9 @@ int torture_run_tests(void) {
ssh_init(); ssh_init();
torture_filter_tests(tests); torture_filter_tests(tests);
sshd_setup((void **)&s);
rc = run_tests(tests); rc = run_tests(tests);
sshd_teardown((void **)&s);
ssh_finalize(); ssh_finalize();
return rc; return rc;

View File

@@ -4,8 +4,39 @@
#include <libssh/libssh.h> #include <libssh/libssh.h>
#include "libssh/priv.h" #include "libssh/priv.h"
#include <errno.h>
#include <sys/types.h>
#include <pwd.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 void setup(void **state) { static void setup(void **state) {
ssh_session session = ssh_new(); ssh_session session = ssh_new();
int verbosity = torture_libssh_verbosity();
struct passwd *pwd;
int rc;
pwd = getpwnam("bob");
assert_non_null(pwd);
rc = setuid(pwd->pw_uid);
assert_return_code(rc, errno);
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE);
*state = session; *state = session;
} }
@@ -18,10 +49,7 @@ static void torture_options_set_proxycommand(void **state) {
ssh_session session = *state; ssh_session session = *state;
int rc; int rc;
rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost"); rc = ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, "nc 127.0.0.10 22");
assert_true(rc == 0);
rc = ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, "nc localhost 22");
assert_true(rc == 0); assert_true(rc == 0);
rc = ssh_connect(session); rc = ssh_connect(session);
assert_true(rc == SSH_OK); assert_true(rc == SSH_OK);
@@ -31,9 +59,6 @@ static void torture_options_set_proxycommand_notexist(void **state) {
ssh_session session = *state; ssh_session session = *state;
int rc; int rc;
rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
assert_true(rc == 0);
rc = ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, "this_command_does_not_exist"); rc = ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, "this_command_does_not_exist");
assert_true(rc == SSH_OK); assert_true(rc == SSH_OK);
rc = ssh_connect(session); rc = ssh_connect(session);
@@ -42,6 +67,7 @@ static void torture_options_set_proxycommand_notexist(void **state) {
int torture_run_tests(void) { int torture_run_tests(void) {
int rc; int rc;
struct torture_state *s = NULL;
UnitTest tests[] = { UnitTest tests[] = {
unit_test_setup_teardown(torture_options_set_proxycommand, setup, teardown), unit_test_setup_teardown(torture_options_set_proxycommand, setup, teardown),
unit_test_setup_teardown(torture_options_set_proxycommand_notexist, setup, teardown), unit_test_setup_teardown(torture_options_set_proxycommand_notexist, setup, teardown),
@@ -51,7 +77,9 @@ int torture_run_tests(void) {
ssh_init(); ssh_init();
torture_filter_tests(tests); torture_filter_tests(tests);
sshd_setup((void **)&s);
rc = run_tests(tests); rc = run_tests(tests);
sshd_teardown((void **)&s);
ssh_finalize(); ssh_finalize();
return rc; return rc;

View File

@@ -24,22 +24,36 @@
#include "torture.h" #include "torture.h"
#include <libssh/libssh.h> #include <libssh/libssh.h>
#include <errno.h>
#include <sys/types.h>
#include <pwd.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 void setup(void **state) static void setup(void **state)
{ {
ssh_session session; ssh_session session;
const char *host; struct passwd *pwd;
const char *user;
const char *password;
host = getenv("TORTURE_HOST"); pwd = getpwnam("bob");
if (host == NULL) { assert_non_null(pwd);
host = "localhost"; setuid(pwd->pw_uid);
}
user = getenv("TORTURE_USER"); session = torture_ssh_session(TORTURE_SSH_SERVER,
password = getenv("TORTURE_PASSWORD"); NULL,
TORTURE_SSH_USER_ALICE,
session = torture_ssh_session(host, NULL, user, password); NULL);
assert_false(session == NULL); assert_false(session == NULL);
*state = session; *state = session;
@@ -99,6 +113,7 @@ static void torture_request_env(void **state)
int torture_run_tests(void) { int torture_run_tests(void) {
int rc; int rc;
struct torture_state *s = NULL;
UnitTest tests[] = { UnitTest tests[] = {
unit_test_setup_teardown(torture_request_env, setup, teardown), unit_test_setup_teardown(torture_request_env, setup, teardown),
@@ -107,7 +122,9 @@ int torture_run_tests(void) {
ssh_init(); ssh_init();
torture_filter_tests(tests); torture_filter_tests(tests);
sshd_setup((void **)&s);
rc = run_tests(tests); rc = run_tests(tests);
sshd_teardown((void **)&s);
ssh_finalize(); ssh_finalize();
return rc; return rc;

View File

@@ -92,7 +92,12 @@ static void torture_channel_read_error(void **state) {
if (rc == SSH_ERROR) if (rc == SSH_ERROR)
break; break;
} }
assert_true(rc == SSH_ERROR); #if OPENSSH_VERSION_MAJOR == 6 && OPENSSH_VERSION_MINOR >= 7
/* With openssh 6.7 this doesn't produce and error anymore */
assert_int_equal(rc, SSH_OK);
#else
assert_int_equal(rc, SSH_ERROR);
#endif
ssh_channel_free(channel); ssh_channel_free(channel);
} }

View File

@@ -3,22 +3,36 @@
#include "torture.h" #include "torture.h"
#include "sftp.c" #include "sftp.c"
#include <errno.h>
#include <sys/types.h>
#include <pwd.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 void setup(void **state) { static void setup(void **state) {
ssh_session session; ssh_session session;
struct torture_sftp *t; struct torture_sftp *t;
const char *host; struct passwd *pwd;
const char *user;
const char *password;
host = getenv("TORTURE_HOST"); pwd = getpwnam("bob");
if (host == NULL) { assert_non_null(pwd);
host = "localhost"; setuid(pwd->pw_uid);
}
user = getenv("TORTURE_USER"); session = torture_ssh_session(TORTURE_SSH_SERVER,
password = getenv("TORTURE_PASSWORD"); NULL,
TORTURE_SSH_USER_ALICE,
session = torture_ssh_session(host, NULL, user, password); NULL);
assert_false(session == NULL); assert_false(session == NULL);
t = torture_sftp_session(session); t = torture_sftp_session(session);
assert_false(t == NULL); assert_false(t == NULL);
@@ -61,6 +75,7 @@ static void torture_sftp_mkdir(void **state) {
int torture_run_tests(void) { int torture_run_tests(void) {
int rc; int rc;
struct torture_state *s = NULL;
UnitTest tests[] = { UnitTest tests[] = {
unit_test_setup_teardown(torture_sftp_mkdir, setup, teardown) unit_test_setup_teardown(torture_sftp_mkdir, setup, teardown)
}; };
@@ -68,7 +83,9 @@ int torture_run_tests(void) {
ssh_init(); ssh_init();
torture_filter_tests(tests); torture_filter_tests(tests);
sshd_setup((void **)&s);
rc = run_tests(tests); rc = run_tests(tests);
sshd_teardown((void **)&s);
ssh_finalize(); ssh_finalize();
return rc; return rc;

View File

@@ -3,24 +3,40 @@
#include "torture.h" #include "torture.h"
#include "sftp.c" #include "sftp.c"
#include <sys/types.h>
#include <pwd.h>
#define MAX_XFER_BUF_SIZE 16384 #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 void setup(void **state) { static void setup(void **state) {
ssh_session session; ssh_session session;
struct torture_sftp *t; struct torture_sftp *t;
const char *host; struct passwd *pwd;
const char *user; int rc;
const char *password;
host = getenv("TORTURE_HOST"); pwd = getpwnam("bob");
if (host == NULL) { assert_non_null(pwd);
host = "localhost";
}
user = getenv("TORTURE_USER"); rc = setuid(pwd->pw_uid);
password = getenv("TORTURE_PASSWORD"); assert_return_code(rc, errno);
session = torture_ssh_session(host, NULL, user, password); session = torture_ssh_session(TORTURE_SSH_SERVER,
NULL,
TORTURE_SSH_USER_ALICE,
NULL);
assert_false(session == NULL); assert_false(session == NULL);
t = torture_sftp_session(session); t = torture_sftp_session(session);
assert_false(t == NULL); assert_false(t == NULL);
@@ -72,6 +88,7 @@ static void torture_sftp_read_blocking(void **state) {
int torture_run_tests(void) { int torture_run_tests(void) {
int rc; int rc;
struct torture_state *s = NULL;
UnitTest tests[] = { UnitTest tests[] = {
unit_test_setup_teardown(torture_sftp_read_blocking, setup, teardown) unit_test_setup_teardown(torture_sftp_read_blocking, setup, teardown)
}; };
@@ -79,7 +96,9 @@ int torture_run_tests(void) {
ssh_init(); ssh_init();
torture_filter_tests(tests); torture_filter_tests(tests);
sshd_setup((void **)&s);
rc = run_tests(tests); rc = run_tests(tests);
sshd_teardown((void **)&s);
ssh_finalize(); ssh_finalize();
return rc; 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_BINARY_DIRECTORY "${CTEST_DIRECTORY}/${CTEST_BUILD_NAME}/build")
set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE ${CMAKE_SOURCE_DIR}/tests/valgrind.supp) set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE ${CMAKE_SOURCE_DIR}/tests/valgrind.supp)
set(CTEST_MEMORYCHECK_COMMAND_OPTIONS " --trace-children-skip=sshd")
find_program(CTEST_GIT_COMMAND NAMES git) find_program(CTEST_GIT_COMMAND NAMES git)
find_program(CTEST_COVERAGE_COMMAND NAMES gcov) find_program(CTEST_COVERAGE_COMMAND NAMES gcov)

5
tests/etc/group.in Normal file
View File

@@ -0,0 +1,5 @@
users:x:1000:
sshd:x:65531:
nobody:x:65533:
nogroup:x:65534:nobody
root:x:65532:

2
tests/etc/hosts.in Normal file
View File

@@ -0,0 +1,2 @@
127.0.0.10 server.libssh.site
127.0.0.21 client.libssh.site

4
tests/etc/pam.d/sshd.in Normal file
View File

@@ -0,0 +1,4 @@
auth required @PAM_WRAPPER_MODULE_DIR@/pam_matrix.so passdb=@CMAKE_CURRENT_BINARY_DIR@/etc/pam_matrix_passdb
account required @PAM_WRAPPER_MODULE_DIR@/pam_matrix.so passdb=@CMAKE_CURRENT_BINARY_DIR@/etc/pam_matrix_passdb
password required @PAM_WRAPPER_MODULE_DIR@/pam_matrix.so passdb=@CMAKE_CURRENT_BINARY_DIR@/etc/pam_matrix_passdb
session required @PAM_WRAPPER_MODULE_DIR@/pam_matrix.so passdb=@CMAKE_CURRENT_BINARY_DIR@/etc/pam_matrix_passdb

View File

@@ -0,0 +1,2 @@
bob:secret:sshd
alice:secret:sshd

5
tests/etc/passwd.in Normal file
View File

@@ -0,0 +1,5 @@
bob:x:1000:1000:bob gecos:@HOMEDIR@/bob:/bin/false
alice:x:1001:1000:alice gecos:@HOMEDIR@/alice:/bin/bash
sshd:x:65530:65531:sshd:@HOMEDIR@:/sbin/nologin
nobody:x:65533:65534:nobody gecos:@HOMEDIR@:/bin/false
root:x:65534:65532:root gecos:@HOMEDIR@:/bin/false

2
tests/etc/shadow.in Normal file
View File

@@ -0,0 +1,2 @@
alice:$6$0jWkA8VP$MvBUvtGy38jWCZ5KtqnZEKQWXvvImDkDhDQII1kTqtAp3/xH31b71c.AjGkBFle.2QwCJQH7OzB/NXiMprusr/::0:::::
bob:$6$0jWkA8VP$MvBUvtGy38jWCZ5KtqnZEKQWXvvImDkDhDQII1kTqtAp3/xH31b71c.AjGkBFle.2QwCJQH7OzB/NXiMprusr/::0:::::

27
tests/keys/id_rsa Normal file
View File

@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAs/fIz+Gy89XjUhXebNq2rs1K0RJEZXDbfcofb13ESDJ9fSbd
+RlCUM6i+foEVV23xWdands2Bkn72tGinJadIgOWU+koxp+gRmtJLE/ONiAKJQqR
K3eOJNBH6At96NMqJ4Gwv56G4W68uPgDwUVQwVIc6Ec6Rypiz7DE+S++gSvBQIVU
Qt7XkPcXOyN5zuj5qDhZM4l6V7Og9LWj4/2IF5acvKjfIMpeqmnp9z6BTYZQtuQU
6b1VuEYhXyvM6LkMwndsVGh46kDKMmRQhyA8A6qvLAliMMq88k5gR4AeJeTnqDR/
Q120I6PMqYNl6TLTk8/KonOOPDR/XXGb3iF67wIDAQABAoIBAAVoL2dXf5nl1jOU
Jp+cnpp33oSTiOyHTIDl/rXI2mnU4oJNFaQzRxPIcYsTIOgzrZ7HsShG+sOLm36C
h+EugUARXYXd3nTBPP6AoK0tJKPpqIReYegtal7exxpIphrFpWGUeuv25lSFkDP6
d5pp67gzMF0mLrEOq/NTe0eFULLuwa6+IKXU7deiU90pzi4jrjcIWNoGHSw1YYAZ
TC8KAxA/tYH9myya5krRCjA9B345DJ9Wd71wX+RZNgbSkIri/6dDTtvsYvqcQKo0
OZ3MUDJnKmkfPLP84qZPRoEwUI1gts1WUdoNK6LK7yOJmPL5FMyTwZx3XtDw3gAv
TVhI7ikCgYEA5Ay0TCySPQAaC14WtjgIAmTa19mAtOFpbRxToi40WjXk3R6mMqyp
biAcNecdZRC6zzgAUp8g1O3Yc1d9fG/3FpM5eUbIer7mMLTRuQQysoJY2Ayw9OEA
qPHS/K6LPOD09aZo14fRUqVO8rwMbHtq2yhH8p3FM8WZRe5ms8zpyLUCgYEAygZ3
RTMWbgcGdNoaPa5Ms9KRqAxKJLin2fE99KowZeJfvZN24sXExawQdy4BKVYT0H6e
MNEIPiEBVA4a1GDk/tyOrEt684IsidROngJaGbqb+SYm6feQAioYu0wkG/I2hS12
/Z/aK6wFz5hWzBv/YvJqC7xD1YwZm1QXDyAiL5MCgYAXz8fHqGPAoNEXXMSsVB9p
+JPtM9W/jUXP0cRdy8tFnBkAiaG66tJqIEoxyqcEFYIb/vHxrpHkCc2vBXSh2KMJ
JWg75IssXeB1N3wqgGi2wOt7659SgmfqPA3WunbpbWfGepC56IGPypj6uW3mqeBX
b9ZLW/PqWviNF757iarjfQKBgGxKBPqRxM8bcumF0xUG7dRh5XN3ivKeDFL1Tels
pF6odftPJSWvLqdqcLUBctvuaNaUWEUAdvOei3C70sPOYFEAdnWCTBhkyWzj4XQu
/I7YCS0Gt0soSQfv+qvCx4Q3U+QVF7ghTDemkMLS/IuR4lXubMt3kcDQxRUOgQG5
jrmDAoGALauF7ZyzEnQgsgMVzfm9znl5I2aIsLgdsAv3lINVrvtTKhddp7cdd+2j
dwZlaMnLET/3MY/Cvf13vEsS+bdNXjsdQidqBL8pe5PXY/pafBhtduQuvGzlHJA5
CEBnwB0SdtsXbzSpOAPZqea4Nz9MkQ8LMsINdPpxCuFhjeYa9Ow=
-----END RSA PRIVATE KEY-----

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

@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCz98jP4bLz1eNSFd5s2rauzUrREkRlcNt9yh9vXcRIMn19Jt35GUJQzqL5+gRVXbfFZ1qd2zYGSfva0aKclp0iA5ZT6SjGn6BGa0ksT842IAolCpErd44k0EfoC33o0yongbC/nobhbry4+APBRVDBUhzoRzpHKmLPsMT5L76BK8FAhVRC3teQ9xc7I3nO6PmoOFkziXpXs6D0taPj/YgXlpy8qN8gyl6qaen3PoFNhlC25BTpvVW4RiFfK8zouQzCd2xUaHjqQMoyZFCHIDwDqq8sCWIwyrzyTmBHgB4l5OeoNH9DXbQjo8ypg2XpMtOTz8qic448NH9dcZveIXrv asn@krikkit.cryptomilk.site

View File

@@ -0,0 +1,12 @@
-----BEGIN DSA PRIVATE KEY-----
MIIBuwIBAAKBgQD7vBS+d/eJP6wK2VQw+8AIfgCw9IR50utLRkkrWbfDdiM7V+fp
tJYKCyqZT9j9ANhqicB2tuqAI6WJBZMaGekxWfI30JxPkHZrrwbdFzlRbjav07lg
IKqWgcz81iVPmfn5savEoobiSFjJNMmYcizjKZgGmyNUzlJjzF7u5qD08wIVAPFp
6VKuv8VxNjENciUZCdEDRW/lAoGBAN/BFSBRSP9frsHID6e2NeKHqs8JDUWhCTE9
/WQKqUUbxO2UU98CfHuf1mNlaSsrOxaBdvTeURcZZc1svhyGr1VG+NbNTDDlzTgA
UlrzNML61TYcFXQVxgifUy+Tmh8FRGCa6Ko/EsX4ZWLTto5w1u5cPpgzSbLMco9T
AeeNLgYNAoGAJRuawWN3+NezI7+bBe42Kjg4gVUlpS+8TTlYFbwrM1Esab7gvxHB
/b2apbk9xIAkkqsnb+EPrXTLUdE2Y7XkEuGLLSTus2UlZKobBGBX/Ioysg5W9Fk/
2MhI4YssRb2alar8d+gmAHPaT+D+NDd90PBfY3HqcXFEK+eDTWo1JNICFBLdsuoO
6pObeFSOYbr38kJzZ0xG
-----END DSA PRIVATE KEY-----

View File

@@ -0,0 +1 @@
ssh-dss AAAAB3NzaC1kc3MAAACBAPu8FL5394k/rArZVDD7wAh+ALD0hHnS60tGSStZt8N2IztX5+m0lgoLKplP2P0A2GqJwHa26oAjpYkFkxoZ6TFZ8jfQnE+QdmuvBt0XOVFuNq/TuWAgqpaBzPzWJU+Z+fmxq8SihuJIWMk0yZhyLOMpmAabI1TOUmPMXu7moPTzAAAAFQDxaelSrr/FcTYxDXIlGQnRA0Vv5QAAAIEA38EVIFFI/1+uwcgPp7Y14oeqzwkNRaEJMT39ZAqpRRvE7ZRT3wJ8e5/WY2VpKys7FoF29N5RFxllzWy+HIavVUb41s1MMOXNOABSWvM0wvrVNhwVdBXGCJ9TL5OaHwVEYJroqj8SxfhlYtO2jnDW7lw+mDNJssxyj1MB540uBg0AAACAJRuawWN3+NezI7+bBe42Kjg4gVUlpS+8TTlYFbwrM1Esab7gvxHB/b2apbk9xIAkkqsnb+EPrXTLUdE2Y7XkEuGLLSTus2UlZKobBGBX/Ioysg5W9Fk/2MhI4YssRb2alar8d+gmAHPaT+D+NDd90PBfY3HqcXFEK+eDTWo1JNI= asn@magrathea

View File

@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIB9v2n1oaXvBECf0gDPxTibeUPvvkI1anNWDAIkNjs5JoAoGCCqGSM49
AwEHoUQDQgAEqkTqNu7gRegPJRy0WiseJz9NAdBimzyNSzNwI5eAkEqv9D6Y95KL
7DBEnDQ2p08iOLw+vN1PKHsCM7b/ONbYVg==
-----END EC PRIVATE KEY-----

View File

@@ -0,0 +1 @@
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKpE6jbu4EXoDyUctForHic/TQHQYps8jUszcCOXgJBKr/Q+mPeSi+wwRJw0NqdPIji8PrzdTyh7AjO2/zjW2FY= asn@magrathea

BIN
tests/keys/ssh_host_key Normal file

Binary file not shown.

View File

@@ -0,0 +1 @@
2048 65537 25221975523736997039149017470335977198642717886559395625730372192276493838727011206749822289920387480933533054627057418868711378045090730895752530916661328094497437687453813456961487210492465678475508526337829331199296553120728607984859224949182503917312492825658971738208505685553964707412720244524969161284321098487507924676797222812771309962906894332072854924265623785469343453142982185436565166155021228521252914913227554455102103918367844210755391318078654400527927267478149210805219779896806429660492177158822689909493046725157917529664436252598971135251689616517266344945600782273453037452082373553352939812279 asn@magrathea

View File

@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAqzabeU0oKbHDwdlqindABvtzgWCvXdHJ+d2Ew6te2LXjkwju
y7u6B7y63NZRy57ccrE4YSeWItVoZn+DWN+guU354Ss/tzQ9/thUmLrvtKNvJwuF
F5Ch7Q4BsrXGsb2GSv+7W5tpx3yAqH1TvKQj/MmQVX+/9KtXEnh7/vpiCqoOXQAR
zvIIQxoo1aUQBHAkRW7Yw0Ds7AjC9uV1ns4xdBXPQmDk23pWvCq7E+7rOEbKRrjj
lApS4lJYy0oEXsFdqUPd+PtT1gG0nIElHFQtsTgUvwYQmJEzrBxv41odwRvxbMjg
THPr4SLRRRSuPwICWyvxqPpa7EsfMBnbPEIUzQIDAQABAoIBAEUO15MLvgFjRDQy
P7jt9JNcZPBwUQukjLUN1nkd7Dm407wAxGDErXplc3GTuJZK01wngzgcwX/3WA7P
q+jy+l8DxqA904tPtRnPo/+elwTjTvgOu3YPzmBRX/n3O9eBPGOP1sBSZU4jN7m+
I0JZanKR0nfJ+WD0o0A9/LWRxG3MFIntBamtT6pgee8sAu44IvW0o7tHJabMq02J
Z/ndrJmox34wq6SMFANax+N1x9sZa60bL7gEoDWQJNKOaMrbtOaIoTGFIc4hFqoA
SzjNqcGsHPWs44cw0mNkUGq37jEvaCwzAp+U80ma1skBhXuJL9sQOxl1v5qW91c/
Cnm5WYECgYEA4DPvqbLt+VdyTtmCQ370yiCk4OPPMPzbM65IVKgQL/rN6HdNShTO
uLF6P8XC8vNP2OSydJeFt+kMKd7E/4o5LfvEqUGXZJDkB7fLjrOjyZU3bxtIx95x
qYGWRcWbd3sHzlBJGuFVSE7GREE+lqhkSu4ry4l/GAKxSymAXgGd/9ECgYEAw37L
ppZIavcLE2rZgXHoqMiJzeGzsidJbkHss4k7ubLe8vyBMiv0HC2anxPa2+yNWuF2
+pEr84bllh149VKeild24UEBAR2w/P41ggWqiUP7PKllh+huWzG4+KNFbfUP4dd0
4LkVgfsCz32qD8qxXNCxJCZ8H2fmjKsYw/oCID0CgYAiuSh3GdUtdtOnTpyUI4d5
/pBKnD2skpzIZkehhN3s8GUPidqYjJxvkl0in1hQFErbhp/02rrE/vz5Rx0vjpLI
gmO06wmtc5s9bsPB+CR3xfpt5MXi3pqv6/gAGli3qoBM/bY0yY1Rw5GFZK1y2+Wc
jUKPJV5fs5sNzwGojYuQ4QKBgQCNNgqOo2Fd+mLCvNyt1wTy3iBEWfL+DcjJ3s7G
hKtioKTQqbn87qjercZRf/sH/t/ANLpHlhNETj2KaHGV6v7f+PvDC7xY/QR6SnmG
GOetTTCuCcJwIGGOd+UfnHgrS+gT/xjKtoalpBXMoP31eDkTTR+XeEESQm/TTkeO
UAm3FQKBgD8Y7CLHpyZZ+eOnxRSPU4m4AWAEp7JOwHDRWWQeUornrXDYgD87d2M9
iIAEuOzNggA56Nm3AzBOPRj4HkBh57ToVKPswHwB0oWvrtSjpLkkU6q8xRG3XuJD
2AskDaZONzIDoJGfZ3+W7YbKELK7DPtFXL15sOfBmpoEkI9RA5vM
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCrNpt5TSgpscPB2WqKd0AG+3OBYK9d0cn53YTDq17YteOTCO7Lu7oHvLrc1lHLntxysThhJ5Yi1Whmf4NY36C5TfnhKz+3ND3+2FSYuu+0o28nC4UXkKHtDgGytcaxvYZK/7tbm2nHfICofVO8pCP8yZBVf7/0q1cSeHv++mIKqg5dABHO8ghDGijVpRAEcCRFbtjDQOzsCML25XWezjF0Fc9CYOTbela8KrsT7us4RspGuOOUClLiUljLSgRewV2pQ934+1PWAbScgSUcVC2xOBS/BhCYkTOsHG/jWh3BG/FsyOBMc+vhItFFFK4/AgJbK/Go+lrsSx8wGds8QhTN asn@magrathea

View File

@@ -5,9 +5,9 @@ if (WITH_SERVER AND UNIX AND NOT WIN32)
include_directories( include_directories(
${LIBSSH_PUBLIC_INCLUDE_DIRS} ${LIBSSH_PUBLIC_INCLUDE_DIRS}
${CMOCKA_INCLUDE_DIR} ${CMOCKA_INCLUDE_DIR}
${OPENSSL_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR}
${GCRYPT_INCLUDE_DIRS} ${GCRYPT_INCLUDE_DIR}
${ZLIB_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIR}
${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}

View File

@@ -28,6 +28,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <signal.h>
#ifndef _WIN32 #ifndef _WIN32
# include <dirent.h> # include <dirent.h>
@@ -219,10 +220,16 @@ static const char torture_ed25519_testkey_pp[]=
"Y3GsmYTDstmicanQ==\n" "Y3GsmYTDstmicanQ==\n"
"-----END OPENSSH PRIVATE KEY-----\n"; "-----END OPENSSH PRIVATE KEY-----\n";
#define TORTURE_SOCKET_DIR "/tmp/test_socket_wrapper_XXXXXX"
#define TORTURE_SSHD_PIDFILE "sshd/sshd.pid"
#define TORTURE_SSHD_CONFIG "sshd/sshd_config"
#define TORTURE_PCAP_FILE "socket_trace.pcap"
static int verbosity = 0; static int verbosity = 0;
static const char *pattern = NULL; static const char *pattern = NULL;
#ifndef _WIN32 #ifndef _WIN32
static int _torture_auth_kbdint(ssh_session session, static int _torture_auth_kbdint(ssh_session session,
const char *password) { const char *password) {
const char *prompt; const char *prompt;
@@ -338,6 +345,58 @@ int torture_isdir(const char *path) {
return 0; return 0;
} }
int torture_terminate_process(const char *pidfile)
{
char buf[8] = {0};
long int tmp;
ssize_t rc;
pid_t pid;
int fd;
int is_running = 1;
int count;
/* read the pidfile */
fd = open(pidfile, O_RDONLY);
if (fd < 0) {
return -1;
}
rc = read(fd, buf, sizeof(buf));
close(fd);
if (rc <= 0) {
return -1;
}
buf[sizeof(buf) - 1] = '\0';
tmp = strtol(buf, NULL, 10);
if (tmp == 0 || tmp > 0xFFFF || errno == ERANGE) {
return -1;
}
pid = (pid_t)(tmp & 0xFFFF);
for (count = 0; count < 10; count++) {
/* Make sure the daemon goes away! */
kill(pid, SIGTERM);
usleep(10 * 1000);
rc = kill(pid, 0);
if (rc != 0) {
is_running = 0;
break;
}
}
if (is_running) {
fprintf(stderr,
"WARNING: The process server is still running!\n");
}
return 0;
}
ssh_session torture_ssh_session(const char *host, ssh_session torture_ssh_session(const char *host,
const unsigned int *port, const unsigned int *port,
const char *user, const char *user,
@@ -355,11 +414,6 @@ ssh_session torture_ssh_session(const char *host,
return NULL; return NULL;
} }
rc = ssh_options_set(session, SSH_OPTIONS_SSH_DIR, "/tmp");
if (rc < 0) {
goto failed;
}
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) { if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) {
goto failed; goto failed;
} }
@@ -397,10 +451,10 @@ ssh_session torture_ssh_session(const char *host,
} }
if (password != NULL) { if (password != NULL) {
if (method & SSH_AUTH_METHOD_INTERACTIVE) { if (method & SSH_AUTH_METHOD_PASSWORD) {
rc = _torture_auth_kbdint(session, password);
} else if (method & SSH_AUTH_METHOD_PASSWORD) {
rc = ssh_userauth_password(session, NULL, password); rc = ssh_userauth_password(session, NULL, password);
} else if (method & SSH_AUTH_METHOD_INTERACTIVE) {
rc = _torture_auth_kbdint(session, password);
} }
} else { } else {
rc = ssh_userauth_publickey_auto(session, NULL, NULL); rc = ssh_userauth_publickey_auto(session, NULL, NULL);
@@ -479,7 +533,7 @@ ssh_bind torture_ssh_bind(const char *addr,
return sshbind; return sshbind;
} }
#endif #endif /* WITH_SERVER */
#ifdef WITH_SFTP #ifdef WITH_SFTP
@@ -541,37 +595,11 @@ void torture_sftp_close(struct torture_sftp *t) {
sftp_free(t->sftp); sftp_free(t->sftp);
} }
if (t->ssh != NULL) {
if (ssh_is_connected(t->ssh)) {
ssh_disconnect(t->ssh);
}
ssh_free(t->ssh);
}
free(t->testdir); free(t->testdir);
free(t); free(t);
} }
#endif /* WITH_SFTP */ #endif /* WITH_SFTP */
#endif /* _WIN32 */
void torture_write_file(const char *filename, const char *data){
int fd;
int rc;
assert_non_null(filename);
assert_true(filename[0] != '\0');
assert_non_null(data);
fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0755);
assert_true(fd >= 0);
rc = write(fd, data, strlen(data));
assert_int_equal(rc, strlen(data));
close(fd);
}
static const char *torture_get_testkey_internal(enum ssh_keytypes_e type, static const char *torture_get_testkey_internal(enum ssh_keytypes_e type,
int bits, int bits,
int with_passphrase, int with_passphrase,
@@ -647,6 +675,251 @@ const char *torture_get_testkey_passphrase(void)
return TORTURE_TESTKEY_PASSWORD; return TORTURE_TESTKEY_PASSWORD;
} }
void torture_setup_socket_dir(void **state)
{
struct torture_state *s;
const char *p;
size_t len;
char *env = getenv("TORTURE_GENERATE_PCAP");
s = malloc(sizeof(struct torture_state));
assert_non_null(s);
s->socket_dir = strdup(TORTURE_SOCKET_DIR);
assert_non_null(s->socket_dir);
p = mkdtemp(s->socket_dir);
assert_non_null(p);
/* pcap file */
len = strlen(p) + 1 + strlen(TORTURE_PCAP_FILE) + 1;
s->pcap_file = malloc(len);
assert_non_null(s->pcap_file);
snprintf(s->pcap_file, len, "%s/%s", p, TORTURE_PCAP_FILE);
/* pid file */
len = strlen(p) + 1 + strlen(TORTURE_SSHD_PIDFILE) + 1;
s->srv_pidfile = malloc(len);
assert_non_null(s->srv_pidfile);
snprintf(s->srv_pidfile, len, "%s/%s", p, TORTURE_SSHD_PIDFILE);
/* config file */
len = strlen(p) + 1 + strlen(TORTURE_SSHD_CONFIG) + 1;
s->srv_config = malloc(len);
assert_non_null(s->srv_config);
snprintf(s->srv_config, len, "%s/%s", p, TORTURE_SSHD_CONFIG);
setenv("SOCKET_WRAPPER_DIR", p, 1);
setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "170", 1);
if (env != NULL && env[0] == '1') {
setenv("SOCKET_WRAPPER_PCAP_FILE", s->pcap_file, 1);
}
*state = s;
}
static void torture_setup_create_sshd_config(void **state)
{
struct torture_state *s = *state;
char ed25519_hostkey[1024] = {0};
char dsa_hostkey[1024];
char rsa_hostkey[1024];
char ecdsa_hostkey[1024];
char sshd_config[2048];
char sshd_path[1024];
struct stat sb;
const char *sftp_server_locations[] = {
"/usr/lib/ssh/sftp-server",
"/usr/libexec/sftp-server",
"/usr/libexec/openssh/sftp-server",
"/usr/lib/openssh/sftp-server", /* Debian */
};
#ifndef OPENSSH_VERSION_MAJOR
#define OPENSSH_VERSION_MAJOR 7U
#define OPENSSH_VERSION_MINOR 0U
#endif /* OPENSSH_VERSION_MAJOR */
const char config_string[]=
"Port 22\n"
"ListenAddress 127.0.0.10\n"
"HostKey %s\n"
"HostKey %s\n"
"HostKey %s\n"
"HostKey %s\n"
"\n"
"LogLevel DEBUG3\n"
"Subsystem sftp %s -l DEBUG2\n"
"\n"
"PasswordAuthentication yes\n"
"KbdInteractiveAuthentication yes\n"
"PubkeyAuthentication yes\n"
"\n"
"StrictModes no\n"
"\n"
"UsePAM yes\n"
"\n"
#if (OPENSSH_VERSION_MAJOR == 6 && OPENSSH_VERSION_MINOR >= 7) || (OPENSSH_VERSION_MAJOR >= 7)
"HostKeyAlgorithms +ssh-dss\n"
# if (OPENSSH_VERSION_MAJOR == 7 && OPENSSH_VERSION_MINOR < 6)
"Ciphers +3des-cbc,aes128-cbc,aes192-cbc,aes256-cbc,blowfish-cbc\n"
# else /* OPENSSH_VERSION 7.0 - 7.5 */
"Ciphers +3des-cbc,aes128-cbc,aes192-cbc,aes256-cbc\n"
# endif /* OPENSSH_VERSION 7.0 - 7.6 */
"KexAlgorithms +diffie-hellman-group1-sha1"
#else /* OPENSSH_VERSION >= 6.7 */
"Ciphers 3des-cbc,aes128-cbc,aes192-cbc,aes256-cbc,aes128-ctr,"
"aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,"
"aes256-gcm@openssh.com,arcfour128,arcfour256,arcfour,"
"blowfish-cbc,cast128-cbc,chacha20-poly1305@openssh.com\n"
"KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp256,"
"ecdh-sha2-nistp384,ecdh-sha2-nistp521,"
"diffie-hellman-group-exchange-sha256,"
"diffie-hellman-group-exchange-sha1,"
"diffie-hellman-group14-sha1,"
"diffie-hellman-group1-sha1\n"
#endif /* OPENSSH_VERSION >= 6.7 */
"\n"
"AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES\n"
"AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT\n"
"AcceptEnv LC_IDENTIFICATION LC_ALL LC_LIBSSH\n"
"\n"
"PidFile %s\n";
size_t sftp_sl_size = ARRAY_SIZE(sftp_server_locations);
const char *sftp_server;
size_t i;
int rc;
snprintf(sshd_path,
sizeof(sshd_path),
"%s/sshd",
s->socket_dir);
rc = mkdir(sshd_path, 0755);
assert_return_code(rc, errno);
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(dsa_hostkey,
sizeof(dsa_hostkey),
"%s/sshd/ssh_host_dsa_key",
s->socket_dir);
torture_write_file(dsa_hostkey, torture_get_testkey(SSH_KEYTYPE_DSS, 0, 0));
snprintf(rsa_hostkey,
sizeof(rsa_hostkey),
"%s/sshd/ssh_host_rsa_key",
s->socket_dir);
torture_write_file(rsa_hostkey, torture_get_testkey(SSH_KEYTYPE_RSA, 0, 0));
snprintf(ecdsa_hostkey,
sizeof(ecdsa_hostkey),
"%s/sshd/ssh_host_ecdsa_key",
s->socket_dir);
torture_write_file(ecdsa_hostkey,
torture_get_testkey(SSH_KEYTYPE_ECDSA, 521, 0));
assert_non_null(s->socket_dir);
sftp_server = getenv("TORTURE_SFTP_SERVER");
if (sftp_server == NULL) {
for (i = 0; i < sftp_sl_size; i++) {
sftp_server = sftp_server_locations[i];
rc = lstat(sftp_server, &sb);
if (rc == 0) {
break;
}
}
}
assert_non_null(sftp_server);
snprintf(sshd_config, sizeof(sshd_config),
config_string,
ed25519_hostkey,
dsa_hostkey,
rsa_hostkey,
ecdsa_hostkey,
sftp_server,
s->srv_pidfile);
torture_write_file(s->srv_config, sshd_config);
}
void torture_setup_sshd_server(void **state)
{
struct torture_state *s;
char sshd_start_cmd[1024];
int rc;
torture_setup_socket_dir(state);
torture_setup_create_sshd_config(state);
/* Set the default interface for the server */
setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "10", 1);
setenv("PAM_WRAPPER", "1", 1);
s = *state;
snprintf(sshd_start_cmd, sizeof(sshd_start_cmd),
"/usr/sbin/sshd -r -f %s -E %s/sshd/daemon.log 2> %s/sshd/cwrap.log",
s->srv_config, s->socket_dir, s->socket_dir);
rc = system(sshd_start_cmd);
assert_return_code(rc, errno);
/* Give the process some time to start */
usleep(100 * 1000);
setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "21", 1);
unsetenv("PAM_WRAPPER");
}
void torture_teardown_socket_dir(void **state)
{
struct torture_state *s = *state;
char *env = getenv("TORTURE_SKIP_CLEANUP");
int rc;
if (env != NULL && env[0] == '1') {
fprintf(stderr, "[ TORTURE ] >>> Skipping cleanup of %s\n", s->socket_dir);
} else {
rc = torture_rmdirs(s->socket_dir);
if (rc < 0) {
fprintf(stderr,
"torture_rmdirs(%s) failed: %s",
s->socket_dir,
strerror(errno));
}
}
free(s->socket_dir);
free(s->pcap_file);
free(s->srv_pidfile);
free(s);
}
void torture_teardown_sshd_server(void **state)
{
struct torture_state *s = *state;
int rc;
rc = torture_terminate_process(s->srv_pidfile);
if (rc != 0) {
fprintf(stderr, "XXXXXX Failed to terminate sshd\n");
}
torture_teardown_socket_dir(state);
}
int torture_libssh_verbosity(void){ int torture_libssh_verbosity(void){
return verbosity; return verbosity;
} }
@@ -685,8 +958,29 @@ void _torture_filter_tests(UnitTest *tests, size_t ntests){
} }
} }
#endif /* _WIN32 */
void torture_write_file(const char *filename, const char *data){
int fd;
int rc;
assert_non_null(filename);
assert_true(filename[0] != '\0');
assert_non_null(data);
fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0600);
assert_true(fd >= 0);
rc = write(fd, data, strlen(data));
assert_int_equal(rc, strlen(data));
close(fd);
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
struct argument_s arguments; struct argument_s arguments;
char *env = getenv("LIBSSH_VERBOSITY");
arguments.verbose=0; arguments.verbose=0;
arguments.pattern=NULL; arguments.pattern=NULL;
@@ -694,6 +988,12 @@ int main(int argc, char **argv) {
verbosity=arguments.verbose; verbosity=arguments.verbose;
pattern=arguments.pattern; pattern=arguments.pattern;
if (verbosity == 0 && env != NULL && env[0] != '\0') {
if (env[0] > '0' && env[0] < '9') {
verbosity = atoi(env);
}
}
return torture_run_tests(); return torture_run_tests();
} }

View File

@@ -46,6 +46,10 @@
assert_true(code >= 0) assert_true(code >= 0)
#endif /* assert_return_code */ #endif /* assert_return_code */
#define TORTURE_SSH_SERVER "127.0.0.10"
#define TORTURE_SSH_USER_ALICE "alice"
#define TORTURE_TESTKEY_PASSWORD "libssh-rocks" #define TORTURE_TESTKEY_PASSWORD "libssh-rocks"
/* Used by main to communicate with parse_opt. */ /* Used by main to communicate with parse_opt. */
@@ -60,11 +64,24 @@ struct torture_sftp {
char *testdir; char *testdir;
}; };
struct torture_state {
char *socket_dir;
char *pcap_file;
char *srv_pidfile;
char *srv_config;
};
#ifndef ZERO_STRUCT
#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
#endif
void torture_cmdline_parse(int argc, char **argv, struct argument_s *arguments); void torture_cmdline_parse(int argc, char **argv, struct argument_s *arguments);
int torture_rmdirs(const char *path); int torture_rmdirs(const char *path);
int torture_isdir(const char *path); int torture_isdir(const char *path);
int torture_terminate_process(const char *pidfile);
/* /*
* Returns the verbosity level asked by user * Returns the verbosity level asked by user
*/ */
@@ -94,6 +111,12 @@ void torture_write_file(const char *filename, const char *data);
#define torture_filter_tests(tests) _torture_filter_tests(tests, sizeof(tests) / sizeof(tests)[0]) #define torture_filter_tests(tests) _torture_filter_tests(tests, sizeof(tests) / sizeof(tests)[0])
void _torture_filter_tests(UnitTest *tests, size_t ntests); void _torture_filter_tests(UnitTest *tests, size_t ntests);
void torture_setup_socket_dir(void **state);
void torture_setup_sshd_server(void **state);
void torture_teardown_socket_dir(void **state);
void torture_teardown_sshd_server(void **state);
/* /*
* This function must be defined in every unit test file. * This function must be defined in every unit test file.
*/ */

View File

@@ -10,15 +10,18 @@ add_cmocka_test(torture_misc torture_misc.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_options torture_options.c ${TORTURE_LIBRARY}) add_cmocka_test(torture_options torture_options.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_isipaddr torture_isipaddr.c ${TORTURE_LIBRARY}) add_cmocka_test(torture_isipaddr torture_isipaddr.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_pki_ed25519 torture_pki_ed25519.c ${TORTURE_LIBRARY}) add_cmocka_test(torture_pki_ed25519 torture_pki_ed25519.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_packet_filter torture_packet_filter.c ${TORTURE_LIBRARY})
if (UNIX AND NOT WIN32) if (UNIX AND NOT WIN32)
# requires ssh-keygen # requires ssh-keygen
add_cmocka_test(torture_keyfiles torture_keyfiles.c ${TORTURE_LIBRARY}) add_cmocka_test(torture_keyfiles torture_keyfiles.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_pki torture_pki.c ${TORTURE_LIBRARY}) add_cmocka_test(torture_pki torture_pki.c ${TORTURE_LIBRARY})
# requires pthread
add_cmocka_test(torture_rand torture_rand.c ${TORTURE_LIBRARY})
# requires /dev/null # requires /dev/null
add_cmocka_test(torture_channel torture_channel.c ${TORTURE_LIBRARY}) add_cmocka_test(torture_channel torture_channel.c ${TORTURE_LIBRARY})
if (WITH_SERVER AND Threads_FOUND) # requires pthread
if (LIBSSH_THREADS)
add_cmocka_test(torture_rand torture_rand.c ${TORTURE_LIBRARY})
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 ${TORTURE_LIBRARY})
endif (WITH_SERVER AND Threads_FOUND) endif (WITH_SERVER)
endif (LIBSSH_THREADS)
endif (UNIX AND NOT WIN32) endif (UNIX AND NOT WIN32)

View File

@@ -0,0 +1,500 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2018 by Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
*
* The SSH Library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* The SSH Library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the SSH Library; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
/*
* This test checks if the messages accepted by the packet filter were intented
* to be accepted.
*
* The process consists in 2 steps:
* - Try the filter with a message type in an arbitrary state
* - If the message is accepted by the filter, check if the message is in the
* set of accepted states.
*
* Only the values selected by the flag (COMPARE_*) are considered.
* */
#include "config.h"
#define LIBSSH_STATIC
#include "torture.h"
#include "libssh/priv.h"
#include "libssh/libssh.h"
#include "libssh/session.h"
#include "libssh/auth.h"
#include "libssh/ssh2.h"
#include "libssh/packet.h"
#include "packet.c"
#define COMPARE_SESSION_STATE 1
#define COMPARE_ROLE (1 << 1)
#define COMPARE_DH_STATE (1 << 2)
#define COMPARE_AUTH_STATE (1 << 3)
#define COMPARE_GLOBAL_REQ_STATE (1 << 4)
#define SESSION_STATE_COUNT 11
#define DH_STATE_COUNT 4
#define AUTH_STATE_COUNT 14
#define GLOBAL_REQ_STATE_COUNT 5
#define MESSAGE_COUNT 100 // from 1 to 100
#define ROLE_CLIENT 0
#define ROLE_SERVER 1
/*
* This is the list of currently unfiltered message types.
* Only unrecognized types should be in this list.
* */
static uint8_t unfiltered[] = {
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
22, 23, 24, 25, 26, 27, 28, 29,
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
54, 55, 56, 57, 58, 59,
62,
67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
83, 84, 85, 86, 87, 88, 89,
};
typedef struct global_state_st {
/* If the bit in this flag is zero, the corresponding state is not
* considered, working as a wildcard (meaning any value is accepted) */
uint32_t flags;
uint8_t role;
enum ssh_session_state_e session;
enum ssh_dh_state_e dh;
enum ssh_auth_state_e auth;
enum ssh_channel_request_state_e global_req;
} global_state;
static int cmp_state(const void *e1, const void *e2)
{
global_state *s1 = (global_state *) e1;
global_state *s2 = (global_state *) e2;
/* Compare role (client == 0 or server == 1)*/
if (s1->role < s2->role) {
return -1;
}
else if (s1->role > s2->role) {
return 1;
}
/* Compare session state */
if (s1->session < s2->session) {
return -1;
}
else if (s1->session > s2->session) {
return 1;
}
/* Compare DH state */
if (s1->dh < s2->dh) {
return -1;
}
else if (s1->dh > s2->dh) {
return 1;
}
/* Compare auth */
if (s1->auth < s2->auth) {
return -1;
}
else if (s1->auth > s2->auth) {
return 1;
}
/* Compare global_req */
if (s1->global_req < s2->global_req) {
return -1;
}
else if (s1->global_req > s2->global_req) {
return 1;
}
/* If all equal, they are equal */
return 0;
}
static int cmp_state_search(const void *key, const void *array_element)
{
global_state *s1 = (global_state *) key;
global_state *s2 = (global_state *) array_element;
int result = 0;
if (s2->flags & COMPARE_ROLE) {
/* Compare role (client == 0 or server == 1)*/
if (s1->role < s2->role) {
return -1;
}
else if (s1->role > s2->role) {
return 1;
}
}
if (s2->flags & COMPARE_SESSION_STATE) {
/* Compare session state */
if (s1->session < s2->session) {
result = -1;
goto end;
}
else if (s1->session > s2->session) {
result = 1;
goto end;
}
}
if (s2->flags & COMPARE_DH_STATE) {
/* Compare DH state */
if (s1->dh < s2->dh) {
result = -1;
goto end;
}
else if (s1->dh > s2->dh) {
result = 1;
goto end;
}
}
if (s2->flags & COMPARE_AUTH_STATE) {
/* Compare auth */
if (s1->auth < s2->auth) {
result = -1;
goto end;
}
else if (s1->auth > s2->auth) {
result = 1;
goto end;
}
}
if (s2->flags & COMPARE_GLOBAL_REQ_STATE) {
/* Compare global_req */
if (s1->global_req < s2->global_req) {
result = -1;
goto end;
}
else if (s1->global_req > s2->global_req) {
result = 1;
goto end;
}
}
end:
return result;
}
static int is_state_accepted(global_state *tested, global_state *accepted,
int accepted_len)
{
global_state *found = NULL;
found = bsearch(tested, accepted, accepted_len, sizeof(global_state),
cmp_state_search);
if (found != NULL) {
return 1;
}
return 0;
}
static int cmp_uint8(const void *i, const void *j)
{
uint8_t e1 = *((uint8_t *)i);
uint8_t e2 = *((uint8_t *)j);
if (e1 < e2) {
return -1;
}
else if (e1 > e2) {
return 1;
}
return 0;
}
static int check_unfiltered(uint8_t msg_type)
{
uint8_t *found;
found = bsearch(&msg_type, unfiltered, sizeof(unfiltered)/sizeof(uint8_t),
sizeof(uint8_t), cmp_uint8);
if (found != NULL) {
return 1;
}
return 0;
}
static void torture_packet_filter_check_unfiltered(void **state)
{
ssh_session session;
int role_c;
int auth_c;
int session_c;
int dh_c;
int global_req_c;
uint8_t msg_type;
enum ssh_packet_filter_result_e rc;
int in_unfiltered;
session = ssh_new();
for (msg_type = 1; msg_type <= MESSAGE_COUNT; msg_type++) {
session->in_packet.type = msg_type;
for (role_c = 0; role_c < 2; role_c++) {
session->server = role_c;
for (session_c = 0; session_c < SESSION_STATE_COUNT; session_c++) {
session->session_state = session_c;
for (dh_c = 0; dh_c < DH_STATE_COUNT; dh_c++) {
session->dh_handshake_state = dh_c;
for (auth_c = 0; auth_c < AUTH_STATE_COUNT; auth_c++) {
session->auth_state = auth_c;
for (global_req_c = 0;
global_req_c < GLOBAL_REQ_STATE_COUNT;
global_req_c++)
{
session->global_req_state = global_req_c;
rc = ssh_packet_incoming_filter(session);
if (rc == SSH_PACKET_UNKNOWN) {
in_unfiltered = check_unfiltered(msg_type);
if (!in_unfiltered) {
fprintf(stderr, "Message type %d UNFILTERED "
"in state: role %d, session %d, dh %d, auth %d\n",
msg_type, role_c, session_c, dh_c, auth_c);
}
assert_int_equal(in_unfiltered, 1);
}
else {
in_unfiltered = check_unfiltered(msg_type);
if (in_unfiltered) {
fprintf(stderr, "Message type %d NOT UNFILTERED "
"in state: role %d, session %d, dh %d, auth %d\n",
msg_type, role_c, session_c, dh_c, auth_c);
}
assert_int_equal(in_unfiltered, 0);
}
}
}
}
}
}
}
ssh_free(session);
}
static int check_message_in_all_states(global_state accepted[],
int accepted_count, uint8_t msg_type)
{
ssh_session session;
int role_c;
int auth_c;
int session_c;
int dh_c;
int global_req_c;
enum ssh_packet_filter_result_e rc;
int in_accepted;
global_state key;
session = ssh_new();
/* Sort the accepted array so that the elements can be searched using
* bsearch */
qsort(accepted, accepted_count, sizeof(global_state), cmp_state);
session->in_packet.type = msg_type;
for (role_c = 0; role_c < 2; role_c++) {
session->server = role_c;
key.role = role_c;
for (session_c = 0; session_c < SESSION_STATE_COUNT; session_c++) {
session->session_state = session_c;
key.session = session_c;
for (dh_c = 0; dh_c < DH_STATE_COUNT; dh_c++) {
session->dh_handshake_state = dh_c;
key.dh = dh_c;
for (auth_c = 0; auth_c < AUTH_STATE_COUNT; auth_c++) {
session->auth_state = auth_c;
key.auth = auth_c;
for (global_req_c = 0;
global_req_c < GLOBAL_REQ_STATE_COUNT;
global_req_c++)
{
session->global_req_state = global_req_c;
key.global_req = global_req_c;
rc = ssh_packet_incoming_filter(session);
if (rc == SSH_PACKET_ALLOWED) {
in_accepted = is_state_accepted(&key, accepted,
accepted_count);
if (!in_accepted) {
fprintf(stderr, "Message type %d ALLOWED "
"in state: role %d, session %d, dh %d, auth %d\n",
msg_type, role_c, session_c, dh_c, auth_c);
}
assert_int_equal(in_accepted, 1);
}
else if (rc == SSH_PACKET_DENIED) {
in_accepted = is_state_accepted(&key, accepted, accepted_count);
if (in_accepted) {
fprintf(stderr, "Message type %d DENIED "
"in state: role %d, session %d, dh %d, auth %d\n",
msg_type, role_c, session_c, dh_c, auth_c);
}
assert_int_equal(in_accepted, 0);
}
else {
fprintf(stderr, "Message type %d UNFILTERED "
"in state: role %d, session %d, dh %d, auth %d\n",
msg_type, role_c, session_c, dh_c, auth_c);
}
}
}
}
}
}
ssh_free(session);
return 0;
}
static void torture_packet_filter_check_auth_success(void **state)
{
int rc;
global_state accepted[] = {
{
.flags = (COMPARE_SESSION_STATE |
COMPARE_ROLE |
COMPARE_AUTH_STATE |
COMPARE_DH_STATE),
.role = ROLE_CLIENT,
.session = SSH_SESSION_STATE_AUTHENTICATING,
.dh = DH_STATE_FINISHED,
.auth = SSH_AUTH_STATE_PUBKEY_AUTH_SENT,
},
{
.flags = (COMPARE_SESSION_STATE |
COMPARE_ROLE |
COMPARE_AUTH_STATE |
COMPARE_DH_STATE),
.role = ROLE_CLIENT,
.session = SSH_SESSION_STATE_AUTHENTICATING,
.dh = DH_STATE_FINISHED,
.auth = SSH_AUTH_STATE_PASSWORD_AUTH_SENT,
},
{
.flags = (COMPARE_SESSION_STATE |
COMPARE_ROLE |
COMPARE_AUTH_STATE |
COMPARE_DH_STATE),
.role = ROLE_CLIENT,
.session = SSH_SESSION_STATE_AUTHENTICATING,
.dh = DH_STATE_FINISHED,
.auth = SSH_AUTH_STATE_GSSAPI_MIC_SENT,
},
{
.flags = (COMPARE_SESSION_STATE |
COMPARE_ROLE |
COMPARE_AUTH_STATE |
COMPARE_DH_STATE),
.role = ROLE_CLIENT,
.session = SSH_SESSION_STATE_AUTHENTICATING,
.dh = DH_STATE_FINISHED,
.auth = SSH_AUTH_STATE_KBDINT_SENT,
},
{
.flags = (COMPARE_SESSION_STATE |
COMPARE_ROLE |
COMPARE_AUTH_STATE |
COMPARE_DH_STATE),
.role = ROLE_CLIENT,
.session = SSH_SESSION_STATE_AUTHENTICATING,
.dh = DH_STATE_FINISHED,
.auth = SSH_AUTH_STATE_AUTH_NONE_SENT,
}
};
int accepted_count = 5;
/* Unused */
(void) state;
rc = check_message_in_all_states(accepted, accepted_count,
SSH2_MSG_USERAUTH_SUCCESS);
assert_int_equal(rc, 0);
}
static void torture_packet_filter_check_channel_open(void **state)
{
int rc;
/* The only condition to accept a CHANNEL_OPEN is to be authenticated */
global_state accepted[] = {
{
.flags = COMPARE_SESSION_STATE,
.session = SSH_SESSION_STATE_AUTHENTICATED,
}
};
int accepted_count = 1;
/* Unused */
(void) state;
rc = check_message_in_all_states(accepted, accepted_count,
SSH2_MSG_CHANNEL_OPEN);
assert_int_equal(rc, 0);
}
int torture_run_tests(void)
{
int rc;
UnitTest tests[] = {
unit_test(torture_packet_filter_check_auth_success),
unit_test(torture_packet_filter_check_channel_open),
unit_test(torture_packet_filter_check_unfiltered),
};
ssh_init();
torture_filter_tests(tests);
rc = run_tests(tests);
ssh_finalize();
return rc;
}

View File

@@ -212,6 +212,9 @@ static void torture_pki_import_privkey_base64_RSA(void **state) {
type = ssh_key_type(key); type = ssh_key_type(key);
assert_true(type == SSH_KEYTYPE_RSA); assert_true(type == SSH_KEYTYPE_RSA);
rc = ssh_key_is_private(key);
assert_true(rc == 1);
rc = ssh_key_is_public(key); rc = ssh_key_is_public(key);
assert_true(rc == 1); assert_true(rc == 1);
@@ -281,6 +284,9 @@ static void torture_pki_import_privkey_base64_ECDSA(void **state) {
rc = ssh_pki_import_privkey_base64(key_str, passphrase, NULL, NULL, &key); rc = ssh_pki_import_privkey_base64(key_str, passphrase, NULL, NULL, &key);
assert_true(rc == 0); assert_true(rc == 0);
rc = ssh_key_is_private(key);
assert_true(rc == 1);
free(key_str); free(key_str);
ssh_key_free(key); ssh_key_free(key);
} }
@@ -300,6 +306,10 @@ static void torture_pki_import_privkey_base64_passphrase(void **state) {
NULL, NULL,
&key); &key);
assert_true(rc == 0); assert_true(rc == 0);
rc = ssh_key_is_private(key);
assert_true(rc == 1);
ssh_key_free(key); ssh_key_free(key);
/* test if it returns -1 if passphrase is wrong */ /* test if it returns -1 if passphrase is wrong */
@@ -329,6 +339,10 @@ static void torture_pki_import_privkey_base64_passphrase(void **state) {
NULL, NULL,
&key); &key);
assert_true(rc == 0); assert_true(rc == 0);
rc = ssh_key_is_private(key);
assert_true(rc == 1);
ssh_key_free(key); ssh_key_free(key);
/* test if it returns -1 if passphrase is wrong */ /* test if it returns -1 if passphrase is wrong */
@@ -358,6 +372,10 @@ static void torture_pki_import_privkey_base64_passphrase(void **state) {
NULL, NULL,
&key); &key);
assert_true(rc == 0); assert_true(rc == 0);
rc = ssh_key_is_private(key);
assert_true(rc == 1);
ssh_key_free(key); ssh_key_free(key);
/* test if it returns -1 if passphrase is wrong */ /* test if it returns -1 if passphrase is wrong */
@@ -388,6 +406,9 @@ static void torture_pki_import_privkey_base64_ed25519(void **state){
type = ssh_key_type(key); type = ssh_key_type(key);
assert_true(type == SSH_KEYTYPE_ED25519); assert_true(type == SSH_KEYTYPE_ED25519);
rc = ssh_key_is_private(key);
assert_true(rc == 1);
rc = ssh_key_is_public(key); rc = ssh_key_is_public(key);
assert_true(rc == 1); assert_true(rc == 1);
@@ -411,6 +432,9 @@ static void torture_pki_pki_publickey_from_privatekey_RSA(void **state) {
&key); &key);
assert_true(rc == 0); assert_true(rc == 0);
rc = ssh_key_is_private(key);
assert_true(rc == 1);
rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey);
assert_true(rc == SSH_OK); assert_true(rc == SSH_OK);
@@ -433,6 +457,9 @@ static void torture_pki_pki_publickey_from_privatekey_DSA(void **state) {
&key); &key);
assert_true(rc == 0); assert_true(rc == 0);
rc = ssh_key_is_private(key);
assert_true(rc == 1);
rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey);
assert_true(rc == SSH_OK); assert_true(rc == SSH_OK);
@@ -455,6 +482,9 @@ static void torture_pki_pki_publickey_from_privatekey_ed25519(void **state){
&key); &key);
assert_true(rc == 0); assert_true(rc == 0);
rc = ssh_key_is_private(key);
assert_true(rc == 1);
rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey);
assert_true(rc == SSH_OK); assert_true(rc == SSH_OK);