From 3a7b14e57c5c10b6fed24aa87d66ceca4109b7e1 Mon Sep 17 00:00:00 2001 From: enkore Date: Sun, 23 Jul 2023 10:06:24 +0000 Subject: [PATCH 1/8] appveyor: generate pep440 compliant version in fix_version.py I'm unsure if this script is still needed. --- ci/appveyor/fix_version.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ci/appveyor/fix_version.py b/ci/appveyor/fix_version.py index 582af74a..2d3cf826 100644 --- a/ci/appveyor/fix_version.py +++ b/ci/appveyor/fix_version.py @@ -2,6 +2,7 @@ from datetime import datetime import subprocess import json +import re import sys def get_describe_tag(): @@ -12,11 +13,12 @@ def make_version_file(basedir): subprocess.check_output(['git', 'rev-list', '--max-count=1', 'HEAD']).strip().decode('utf-8')) basedir = os.path.abspath(basedir) git_desc = get_describe_tag() + pep440ish = re.sub('^([0-9.]+)-(\\d+)-([0-9a-fg]+)', '\\1.dev\\2+\\3', git_desc) version_json = {'date': datetime.now().isoformat(), 'dirty': False, 'error': None, 'full-revisionid': rev, - 'version': git_desc} + 'version': pep440ish} data = """ import json From 70d49b1c1955b13fde46172815b5e91b5d5ed61b Mon Sep 17 00:00:00 2001 From: enkore Date: Sun, 23 Jul 2023 12:50:44 +0200 Subject: [PATCH 2/8] libssh 0.10.5 (#72) --- ci/docker/manylinux/Dockerfile | 2 +- ci/docker/manylinux/Dockerfile.2014_x86_64 | 2 +- ci/docker/manylinux/Dockerfile.aarch64 | 2 +- ci/docker/manylinux/Dockerfile.aarch64_2_24 | 2 +- ci/docker/manylinux/Dockerfile.aarch64_2_28 | 2 +- .../Dockerfile.manylinux_2_24_x86_64 | 2 +- .../Dockerfile.manylinux_2_28_x86_64 | 2 +- ci/docker/manylinux/libssh-0.10.4.tar.xz | 3 - ci/docker/manylinux/libssh-0.10.4.tar.xz.asc | 16 - ci/docker/manylinux/libssh-0.10.5.tar.xz | 3 + ci/docker/manylinux/libssh-0.10.5.tar.xz.asc | 16 + libssh/.gitlab-ci.yml | 528 ------------------ libssh/CHANGELOG | 52 +- libssh/CMakeLists.txt | 10 +- libssh/CONTRIBUTING.md | 2 +- libssh/CPackConfig.cmake | 2 +- libssh/CompilerChecks.cmake | 4 +- libssh/ConfigureChecks.cmake | 2 +- libssh/DefineOptions.cmake | 4 +- libssh/INSTALL | 2 +- .../cmake/Modules/DefineCMakeDefaults.cmake | 2 +- libssh/cmake/Modules/FindArgp.cmake | 4 + libssh/cmake/Modules/FindGSSAPI.cmake | 2 +- libssh/config.h.cmake | 6 +- libssh/doc/CMakeLists.txt | 3 +- libssh/doc/curve25519-sha256@libssh.org.txt | 12 +- libssh/doc/mainpage.dox | 2 +- libssh/examples/CMakeLists.txt | 20 +- libssh/examples/samplesftp.c | 5 +- libssh/examples/samplesshd-kbdint.c | 6 +- libssh/examples/ssh_X11_client.c | 2 +- libssh/examples/sshd_direct-tcpip.c | 7 +- libssh/examples/sshnetcat.c | 5 +- libssh/include/libssh/agent.h | 8 + libssh/include/libssh/auth.h | 8 + libssh/include/libssh/bignum.h | 7 + libssh/include/libssh/bind.h | 7 + libssh/include/libssh/bind_config.h | 8 + libssh/include/libssh/blf.h | 9 + libssh/include/libssh/buffer.h | 8 + libssh/include/libssh/callbacks.h | 35 +- libssh/include/libssh/chacha.h | 8 + libssh/include/libssh/channels.h | 10 +- libssh/include/libssh/config_parser.h | 8 + libssh/include/libssh/crypto.h | 8 + libssh/include/libssh/curve25519.h | 9 + libssh/include/libssh/dh-gex.h | 9 + libssh/include/libssh/dh.h | 12 +- libssh/include/libssh/ecdh.h | 9 + libssh/include/libssh/ed25519.h | 12 +- libssh/include/libssh/fe25519.h | 8 + libssh/include/libssh/ge25519.h | 8 + libssh/include/libssh/gssapi.h | 8 + libssh/include/libssh/kex.h | 10 +- libssh/include/libssh/keys.h | 8 + libssh/include/libssh/knownhosts.h | 8 + libssh/include/libssh/legacy.h | 8 + libssh/include/libssh/libgcrypt.h | 8 + libssh/include/libssh/libmbedcrypto.h | 8 + libssh/include/libssh/libssh.h | 6 +- libssh/include/libssh/messages.h | 8 + libssh/include/libssh/misc.h | 12 +- libssh/include/libssh/options.h | 8 + libssh/include/libssh/packet.h | 8 + libssh/include/libssh/pcap.h | 8 + libssh/include/libssh/pki.h | 12 +- libssh/include/libssh/pki_priv.h | 12 +- libssh/include/libssh/poll.h | 8 + libssh/include/libssh/poly1305.h | 8 + libssh/include/libssh/priv.h | 8 + libssh/include/libssh/sc25519.h | 8 + libssh/include/libssh/scp.h | 8 + libssh/include/libssh/server.h | 17 +- libssh/include/libssh/session.h | 40 +- libssh/include/libssh/sftp.h | 7 + libssh/include/libssh/sftp_priv.h | 8 + libssh/include/libssh/socket.h | 1 + libssh/include/libssh/string.h | 8 + libssh/include/libssh/threads.h | 8 + libssh/include/libssh/token.h | 8 + libssh/include/libssh/wrapper.h | 14 +- libssh/libssh.pc.cmake | 14 +- libssh/src/ABI/current | 2 +- libssh/src/ABI/libssh-4.9.5.symbols | 427 ++++++++++++++ libssh/src/CMakeLists.txt | 12 + libssh/src/agent.c | 14 + libssh/src/auth.c | 7 +- libssh/src/bignum.c | 5 +- libssh/src/bind.c | 11 +- libssh/src/buffer.c | 6 +- libssh/src/channels.c | 8 +- libssh/src/client.c | 179 +++--- libssh/src/config.c | 8 +- libssh/src/config_parser.c | 13 +- libssh/src/connector.c | 29 +- libssh/src/curve25519.c | 9 +- libssh/src/dh-gex.c | 9 +- libssh/src/dh.c | 9 +- libssh/src/dh_crypto.c | 43 +- libssh/src/dh_key.c | 4 +- libssh/src/ecdh.c | 7 +- libssh/src/ecdh_gcrypt.c | 2 +- libssh/src/error.c | 2 +- libssh/src/external/bcrypt_pbkdf.c | 2 +- libssh/src/getrandom_crypto.c | 10 + libssh/src/gssapi.c | 80 ++- libssh/src/gzip.c | 340 +++++------ libssh/src/init.c | 5 +- libssh/src/kex.c | 505 +++++++++++------ libssh/src/knownhosts.c | 8 +- libssh/src/libcrypto.c | 14 +- libssh/src/libgcrypt.c | 2 +- libssh/src/libmbedcrypto.c | 2 +- libssh/src/log.c | 2 +- libssh/src/messages.c | 8 + libssh/src/misc.c | 14 +- libssh/src/options.c | 185 +++--- libssh/src/packet.c | 116 ++-- libssh/src/packet_cb.c | 12 +- libssh/src/pcap.c | 9 +- libssh/src/pki.c | 29 +- libssh/src/pki_container_openssh.c | 6 +- libssh/src/pki_crypto.c | 325 +++++------ libssh/src/pki_ed25519_common.c | 20 +- libssh/src/pki_gcrypt.c | 18 +- libssh/src/pki_mbedcrypto.c | 2 + libssh/src/poll.c | 38 +- libssh/src/scp.c | 2 +- libssh/src/server.c | 319 +++++++---- libssh/src/session.c | 52 +- libssh/src/socket.c | 79 ++- libssh/src/threads.c | 2 +- libssh/src/token.c | 2 +- libssh/src/wrapper.c | 104 ++-- libssh/tests/CMakeLists.txt | 4 +- libssh/tests/benchmarks/bench1.sh | 2 +- libssh/tests/benchmarks/bench2.sh | 2 +- libssh/tests/client/torture_algorithms.c | 22 +- libssh/tests/client/torture_auth.c | 8 +- libssh/tests/client/torture_auth_pkcs11.c | 2 +- libssh/tests/client/torture_client_config.c | 2 +- libssh/tests/client/torture_connect.c | 23 +- libssh/tests/client/torture_proxycommand.c | 4 +- libssh/tests/client/torture_rekey.c | 217 ++++++- libssh/tests/ctest-default.cmake | 6 +- libssh/tests/fuzz/README.md | 4 +- libssh/tests/fuzz/ssh_server_fuzzer.c | 1 + libssh/tests/pkcs11/setup-softhsm-tokens.sh | 33 +- libssh/tests/pkd/pkd_keyutil.c | 24 +- .../tests/server/test_server/CMakeLists.txt | 2 +- libssh/tests/server/test_server/default_cb.c | 2 +- .../tests/server/torture_server_auth_kbdint.c | 6 +- libssh/tests/tests_config.h.cmake | 1 + libssh/tests/torture.c | 8 +- libssh/tests/torture.h | 2 + libssh/tests/unittests/CMakeLists.txt | 12 +- libssh/tests/unittests/hello world.sh | 1 + libssh/tests/unittests/torture_config.c | 86 ++- .../unittests/torture_knownhosts_parsing.c | 10 +- libssh/tests/unittests/torture_options.c | 252 ++++++++- libssh/tests/unittests/torture_packet.c | 15 +- .../tests/unittests/torture_packet_filter.c | 2 +- libssh/tests/unittests/torture_pki_rsa.c | 2 +- libssh/tests/unittests/torture_unit_server.c | 2 +- 164 files changed, 3284 insertions(+), 1813 deletions(-) delete mode 100644 ci/docker/manylinux/libssh-0.10.4.tar.xz delete mode 100644 ci/docker/manylinux/libssh-0.10.4.tar.xz.asc create mode 100644 ci/docker/manylinux/libssh-0.10.5.tar.xz create mode 100644 ci/docker/manylinux/libssh-0.10.5.tar.xz.asc delete mode 100644 libssh/.gitlab-ci.yml create mode 100644 libssh/src/ABI/libssh-4.9.5.symbols create mode 100755 libssh/tests/unittests/hello world.sh diff --git a/ci/docker/manylinux/Dockerfile b/ci/docker/manylinux/Dockerfile index 7d1d8235..a7adda28 100644 --- a/ci/docker/manylinux/Dockerfile +++ b/ci/docker/manylinux/Dockerfile @@ -1,7 +1,7 @@ FROM quay.io/pypa/manylinux2010_x86_64 ENV OPENSSL openssl-1.1.1q -ENV LIBSSH 0.10.4 +ENV LIBSSH 0.10.5 ENV KRB 1.18.4 ENV SYSTEM_LIBSSH 1 ENV CFLAGS "-g0 -s" diff --git a/ci/docker/manylinux/Dockerfile.2014_x86_64 b/ci/docker/manylinux/Dockerfile.2014_x86_64 index 3090212d..5836b546 100644 --- a/ci/docker/manylinux/Dockerfile.2014_x86_64 +++ b/ci/docker/manylinux/Dockerfile.2014_x86_64 @@ -1,7 +1,7 @@ FROM quay.io/pypa/manylinux2014_x86_64 ENV OPENSSL openssl-1.1.1q -ENV LIBSSH 0.10.4 +ENV LIBSSH 0.10.5 ENV KRB 1.18.4 ENV SYSTEM_LIBSSH 1 ENV CFLAGS "-g0 -s" diff --git a/ci/docker/manylinux/Dockerfile.aarch64 b/ci/docker/manylinux/Dockerfile.aarch64 index fa00ac71..1118a00e 100644 --- a/ci/docker/manylinux/Dockerfile.aarch64 +++ b/ci/docker/manylinux/Dockerfile.aarch64 @@ -1,7 +1,7 @@ FROM quay.io/pypa/manylinux2014_aarch64 ENV OPENSSL openssl-1.1.1q -ENV LIBSSH 0.10.4 +ENV LIBSSH 0.10.5 ENV KRB 1.18.4 ENV SYSTEM_LIBSSH 1 ENV CFLAGS "-g0 -s" diff --git a/ci/docker/manylinux/Dockerfile.aarch64_2_24 b/ci/docker/manylinux/Dockerfile.aarch64_2_24 index 98c48841..57395fd0 100644 --- a/ci/docker/manylinux/Dockerfile.aarch64_2_24 +++ b/ci/docker/manylinux/Dockerfile.aarch64_2_24 @@ -1,7 +1,7 @@ FROM quay.io/pypa/manylinux_2_24_aarch64 ENV OPENSSL openssl-1.1.1q -ENV LIBSSH 0.10.4 +ENV LIBSSH 0.10.5 ENV KRB 1.18.4 ENV SYSTEM_LIBSSH 1 ENV CFLAGS "-g0 -s" diff --git a/ci/docker/manylinux/Dockerfile.aarch64_2_28 b/ci/docker/manylinux/Dockerfile.aarch64_2_28 index 84977056..39ce14e4 100644 --- a/ci/docker/manylinux/Dockerfile.aarch64_2_28 +++ b/ci/docker/manylinux/Dockerfile.aarch64_2_28 @@ -1,7 +1,7 @@ FROM quay.io/pypa/manylinux_2_28_aarch64 ENV OPENSSL openssl-1.1.1q -ENV LIBSSH 0.10.4 +ENV LIBSSH 0.10.5 ENV KRB 1.18.4 ENV SYSTEM_LIBSSH 1 ENV CFLAGS "-g0 -s" diff --git a/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 b/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 index 1342fbeb..2427c9be 100644 --- a/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 +++ b/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 @@ -1,7 +1,7 @@ FROM quay.io/pypa/manylinux_2_24_x86_64 ENV OPENSSL openssl-1.1.1q -ENV LIBSSH 0.10.4 +ENV LIBSSH 0.10.5 ENV KRB 1.18.4 ENV SYSTEM_LIBSSH 1 ENV CFLAGS "-g0 -s" diff --git a/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 b/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 index 83aa2683..625283d5 100644 --- a/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 +++ b/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 @@ -1,7 +1,7 @@ FROM quay.io/pypa/manylinux_2_28_x86_64 ENV OPENSSL openssl-1.1.1q -ENV LIBSSH 0.10.4 +ENV LIBSSH 0.10.5 ENV KRB 1.18.4 ENV SYSTEM_LIBSSH 1 ENV CFLAGS "-g0 -s" diff --git a/ci/docker/manylinux/libssh-0.10.4.tar.xz b/ci/docker/manylinux/libssh-0.10.4.tar.xz deleted file mode 100644 index 2faf80b1..00000000 --- a/ci/docker/manylinux/libssh-0.10.4.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:07392c54ab61476288d1c1f0a7c557b50211797ad00c34c3af2bbc4dbc4bd97d -size 554920 diff --git a/ci/docker/manylinux/libssh-0.10.4.tar.xz.asc b/ci/docker/manylinux/libssh-0.10.4.tar.xz.asc deleted file mode 100644 index d22b4b2c..00000000 --- a/ci/docker/manylinux/libssh-0.10.4.tar.xz.asc +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQIzBAABCgAdFiEEjf9T4Y8qvI2PPJIjfuD8TcwBTj0FAmMYnSEACgkQfuD8TcwB -Tj2qGBAAn/40MU/7PcyCRK9U+MhLo28peRpTF+i1/k0V5czVLiFubeFofsa6sjy8 -C6VyQsz0NYiTf6wXLlq9jO1p31LWQ13Z3K0d7Lg2eyftsVrGM1Ue9dTLlJrZ570d -JjcBR/J3dpO9w5fz4HawWE8GIBBstZQnZYdoT75+tIeSMJ/tnovKfE1RGYc4kRJs -quC7tyej7Y+t86U8psFSy2iUCajS82b+ddZEhuxwamel+RBRJZsmi5B2OvhkEaOj -mhJOIkx3UD9XAjxeooVcTlzAaJ5JFZ7Im97o+DRbQYvJYe4ZqDo17lrzBh6wruLC -vBo+/lwh9FbCqxbDpFfqwpf8qYsWu3m0Qlu5f+BZ/9WvjFCVoRmScNHJo42tu18r -xcX2Txis8oWysgqhvIgTFRnLq010ErL8iE9WeZwrNJgcTnf+AQLolKQiVAHumMvk -Djv0No+ZTBG03Hsb0tbvA8kVtxI0ZZtzPcRkRqmUwiLCtcO9oo1hInhu+D1sPZwI -Q1xK6hI6LKsF80yPKGexZxlgV/vZYhIKtD0SIoZCpx7MSBxXqHYZARtTFUAXBSqF -tIn800/pPhGuY1/x3ho4BeWCGj1eWG5zy7dr0q/d/OiqBj3OiUfxtTl4drqrYhca -goNhzNTs0Ps+iYbVQlk4nEAjg54M8ru1jfcuNRgrhTqCI8yiESk= -=AG91 ------END PGP SIGNATURE----- diff --git a/ci/docker/manylinux/libssh-0.10.5.tar.xz b/ci/docker/manylinux/libssh-0.10.5.tar.xz new file mode 100644 index 00000000..57e2de13 --- /dev/null +++ b/ci/docker/manylinux/libssh-0.10.5.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b60e2ff7f367b9eee2b5634d3a63303ddfede0e6a18dfca88c44a8770e7e4234 +size 557776 diff --git a/ci/docker/manylinux/libssh-0.10.5.tar.xz.asc b/ci/docker/manylinux/libssh-0.10.5.tar.xz.asc new file mode 100644 index 00000000..01c56857 --- /dev/null +++ b/ci/docker/manylinux/libssh-0.10.5.tar.xz.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEjf9T4Y8qvI2PPJIjfuD8TcwBTj0FAmRTm30ACgkQfuD8TcwB +Tj0TBQ/+MS5qNXgV8I/3s0k6jpzTsEMdozOZ7RYiJg9i9UzCGsIuJ0aiMl+G1aFH +UJOkLlHgGXTSCeZk4aoSTky2jEOezcFgsi0v9j8nmxRTjlDDAY0KxOoA//wc5nQ0 +fgQKUbX0SrtIbe9qpffoGBjaEap2ICAiM7a5PJ+Js0RQ944TqmkWmhGP/2XhxsF9 +0TJ6e4ilSg/mTBV5GemLTRSc+MgFoh5jJiV1+zmkOw5bBvPx7/KgsdmhoZ63prFI +8LvfChEEx50lyTXC8eLW4uSvO5tMHyAwDNBJcKOccp5yqEr147S1pZL8iNS0C2EF +/vG7zRDa3dv81xJjuPVdO40/GE77omp1IWC3i4ZskaAocGOmHo7KSwJ/7MjtAuJT +QgqeTPHjENRYbB6FvyesHpWzesORFIxQtCMxugVpEPcc3WLIRNLvJGa7rofAGJJf +u5uLyzmBuyAWm5gpPMyLRy2ysAgBi7NVusnAuR4v28r8YYpGrwTG+epJ1fV6MKWV +tlV8aCY51H7WVmDNJlwyJOwEZWzRdi9n3e22hEm79+cj3WKY3uwYwJI4s0CgcsUw +OzEZt97Yy+pSvdOokgNHRz0tGoDXZw55PF4+mcyvXSQfZJ2QCL7q7dJ/7DmibGgY +LtsN5bSfzXgEBqpty/sD5HSSt1/fNICJjfuiTKtjKXMD45wBUkE= +=IAN/ +-----END PGP SIGNATURE----- diff --git a/libssh/.gitlab-ci.yml b/libssh/.gitlab-ci.yml deleted file mode 100644 index 6097b8e0..00000000 --- a/libssh/.gitlab-ci.yml +++ /dev/null @@ -1,528 +0,0 @@ ---- -variables: - BUILD_IMAGES_PROJECT: libssh/build-images - CENTOS7_BUILD: buildenv-centos7 - CENTOS9_BUILD: buildenv-c9s - COVERITY_BUILD: buildenv-coverity - FEDORA_BUILD: buildenv-fedora - MINGW_BUILD: buildenv-mingw - TUMBLEWEED_BUILD: buildenv-tumbleweed - UBUNTU_BUILD: buildenv-ubuntu - ALPINE_BUILD: buildenv-alpine - -stages: - - build - - test - - analysis - -.build: - stage: build - variables: - CMAKE_DEFAULT_OPTIONS: "-DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON" - CMAKE_BUILD_OPTIONS: "-DWITH_BLOWFISH_CIPHER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_DEBUG_PACKET=ON -DWITH_DEBUG_CALLTRACE=ON -DWITH_DSA=ON" - CMAKE_TEST_OPTIONS: "-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DWITH_BENCHMARKS=ON" - CMAKE_OPTIONS: $CMAKE_DEFAULT_OPTIONS $CMAKE_BUILD_OPTIONS $CMAKE_TEST_OPTIONS - before_script: &build - - uname -a - - cat /etc/os-release - - mount - - df -h - - cat /proc/swaps - - free -h - - mkdir -p obj && cd obj - script: - - cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. && - make -j$(nproc) && - make -j$(nproc) install - # Do not use after_script as it does not make the targets fail - tags: - - shared - except: - - tags - artifacts: - expire_in: 1 week - when: on_failure - paths: - - obj/ - -.tests: - extends: .build - stage: test - # This is needed to prevent passing artifacts from previous stages - dependencies: [] - script: - - cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. && - make -j$(nproc) && - ctest --output-on-failure - # Do not use after_script as it does not make the targets fail - -.fedora: - extends: .tests - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD - variables: - CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON - -.tumbleweed: - extends: .tests - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD - - -############################################################################### -# CentOS builds # -############################################################################### -# pkd tests fail on CentOS7 docker images, so we don't use -DSERVER_TESTING=ON -centos7/openssl_1.0.x/x86_64: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS7_BUILD - extends: .tests - script: - - cmake3 $CMAKE_OPTIONS .. && - make -j$(nproc) && - ctest --output-on-failure - -centos9s/openssl_3.0.x/x86_64: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS9_BUILD - extends: .tests - script: - - export OPENSSL_ENABLE_SHA1_SIGNATURES=1 - - cmake3 $CMAKE_OPTIONS .. && - make -j$(nproc) && - ctest --output-on-failure - - -############################################################################### -# Fedora builds # -############################################################################### -fedora/build: - extends: .build - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD - -fedora/docs: - extends: .build - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD - script: - - cmake .. && make docs - -fedora/ninja: - extends: .fedora - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD - script: - - cmake -G Ninja $CMAKE_OPTIONS ../ && ninja && ninja test - -fedora/openssl_3.0.x/x86_64: - extends: .fedora - -fedora/openssl_3.0.x/x86_64/fips: - extends: .fedora - before_script: - - echo "# userspace fips" > /etc/system-fips - # We do not need the kernel part, but in case we ever do: - # mkdir -p /var/tmp/userspace-fips - # echo 1 > /var/tmp/userspace-fips/fips_enabled - # mount --bind /var/tmp/userspace-fips/fips_enabled \ - # /proc/sys/crypto/fips_enabled - - update-crypto-policies --show - - update-crypto-policies --set FIPS - - update-crypto-policies --show - - mkdir -p obj && cd obj && cmake - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DPICKY_DEVELOPER=ON - -DWITH_BLOWFISH_CIPHER=ON - -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON - -DWITH_DEBUG_CRYPTO=ON -DWITH_DEBUG_PACKET=ON -DWITH_DEBUG_CALLTRACE=ON - -DWITH_DSA=ON - -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. - script: - - cmake $CMAKE_OPTIONS .. && - make -j$(nproc) && - OPENSSL_FORCE_FIPS_MODE=1 ctest --output-on-failure - -fedora/openssl_3.0.x/x86_64/minimal: - extends: .fedora - variables: - script: - - cmake $CMAKE_DEFAULT_OPTIONS - -DWITH_SFTP=OFF - -DWITH_SERVER=OFF - -DWITH_ZLIB=OFF - -DWITH_PCAP=OFF - -DWITH_DSA=OFF - -DUNIT_TESTING=ON - -DCLIENT_TESTING=ON - -DWITH_GEX=OFF .. && - make -j$(nproc) - -# Address sanitizer doesn't mix well with LD_PRELOAD used in the testsuite -# so, this is only enabled for unit tests right now. -# TODO: add -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -fedora/address-sanitizer: - extends: .fedora - stage: analysis - script: - - cmake - -DCMAKE_BUILD_TYPE=AddressSanitizer - -DCMAKE_C_COMPILER=clang - -DCMAKE_CXX_COMPILER=clang++ - -DPICKY_DEVELOPER=ON - $CMAKE_BUILD_OPTIONS - -DUNIT_TESTING=ON - -DFUZZ_TESTING=ON .. && - make -j$(nproc) && - ctest --output-on-failure - -# This is disabled as it report OpenSSL issues -# It also has the same issues with cwrap as AddressSanitizer -.fedora/memory-sanitizer: - extends: .fedora - stage: analysis - script: - - cmake - -DCMAKE_BUILD_TYPE=MemorySanitizer - -DCMAKE_C_COMPILER=clang - -DCMAKE_CXX_COMPILER=clang++ - -DPICKY_DEVELOPER=ON - $CMAKE_BUILD_OPTIONS - -DUNIT_TESTING=ON - -DFUZZ_TESTING=ON .. && - make -j$(nproc) && - ctest --output-on-failure - -fedora/undefined-sanitizer: - extends: .fedora - stage: analysis - script: - - cmake - -DCMAKE_BUILD_TYPE=UndefinedSanitizer - -DCMAKE_C_COMPILER=clang - -DCMAKE_CXX_COMPILER=clang++ - -DPICKY_DEVELOPER=ON - $CMAKE_BUILD_OPTIONS - -DUNIT_TESTING=ON - -DFUZZ_TESTING=ON .. && - make -j$(nproc) && - ctest --output-on-failure - -fedora/libgcrypt/x86_64: - extends: .fedora - variables: - CMAKE_ADDITIONAL_OPTIONS: "-DWITH_GCRYPT=ON -DWITH_DEBUG_CRYPTO=ON" - -fedora/mbedtls/x86_64: - extends: .fedora - variables: - CMAKE_ADDITIONAL_OPTIONS: "-DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_DSA=OFF" - -# Unit testing only, no client and pkd testing, because cwrap is not available -# for MinGW -fedora/mingw64: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$MINGW_BUILD - extends: .tests - script: - - export WINEPATH=/usr/x86_64-w64-mingw32/sys-root/mingw/bin - - export WINEDEBUG=-all - - mingw64-cmake $CMAKE_DEFAULT_OPTIONS - -DWITH_SFTP=ON - -DWITH_SERVER=ON - -DWITH_ZLIB=ON - -DWITH_PCAP=ON - -DUNIT_TESTING=ON .. && - make -j$(nproc) && - ctest --output-on-failure - -# Unit testing only, no client and pkd testing, because cwrap is not available -# for MinGW -fedora/mingw32: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$MINGW_BUILD - extends: .tests - script: - - export WINEPATH=/usr/i686-w64-mingw32/sys-root/mingw/bin - - export WINEDEBUG=-all - - mingw32-cmake $CMAKE_DEFAULT_OPTIONS - -DWITH_SFTP=ON - -DWITH_SERVER=ON - -DWITH_ZLIB=ON - -DWITH_PCAP=ON - -DUNIT_TESTING=ON .. && - make -j$(nproc) && - ctest --output-on-failure - - -############################################################################### -# Fedora csbuild # -############################################################################### -.csbuild: - stage: analysis - variables: - GIT_DEPTH: "100" - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD - before_script: - - | - if [[ -z "$CI_COMMIT_BEFORE_SHA" ]]; then - export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20") - fi - - # Check if the commit exists in this branch - # This is not the case for a force push - git branch --contains $CI_COMMIT_BEFORE_SHA 2>/dev/null || export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20") - - export CI_COMMIT_RANGE="$CI_COMMIT_BEFORE_SHA..$CI_COMMIT_SHA" - tags: - - shared - except: - - tags - artifacts: - expire_in: 1 week - when: on_failure - paths: - - obj-csbuild/ - -fedora/csbuild/openssl_3.0.x: - extends: .csbuild - script: - - csbuild - --build-dir=obj-csbuild - --build-cmd "rm -rf CMakeFiles CMakeCache.txt && cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON -DWITH_DSA=ON @SRCDIR@ && make clean && make -j$(nproc)" - --git-commit-range $CI_COMMIT_RANGE - --color - --print-current --print-fixed - -fedora/csbuild/libgcrypt: - extends: .csbuild - script: - - csbuild - --build-dir=obj-csbuild - --build-cmd "rm -rf CMakeFiles CMakeCache.txt && cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON -DWITH_GCRYPT=ON -DWITH_DSA=ON @SRCDIR@ && make clean && make -j$(nproc)" - --git-commit-range $CI_COMMIT_RANGE - --color - --print-current --print-fixed - -fedora/csbuild/mbedtls: - extends: .csbuild - script: - - csbuild - --build-dir=obj-csbuild - --build-cmd "rm -rf CMakeFiles CMakeCache.txt && cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON -DWITH_MBEDTLS=ON @SRCDIR@ && make clean && make -j$(nproc)" - --git-commit-range $CI_COMMIT_RANGE - --color - --print-current --print-fixed - - -############################################################################### -# Ubuntu builds # -############################################################################### -ubuntu/openssl_1.1.x/x86_64: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$UBUNTU_BUILD - extends: .tests - - -############################################################################### -# Alpine builds # -############################################################################### -alpine/musl: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$ALPINE_BUILD - extends: .tests - script: - - cmake $CMAKE_DEFAULT_OPTIONS - -DWITH_SFTP=ON - -DWITH_SERVER=ON - -DWITH_ZLIB=ON - -DWITH_PCAP=ON - -DUNIT_TESTING=ON .. && - make -j$(nproc) && - ctest --output-on-failure - - -############################################################################### -# Tumbleweed builds # -############################################################################### -tumbleweed/openssl_1.1.x/x86_64/gcc: - extends: .tumbleweed - variables: - CMAKE_ADDITIONAL_OPTIONS: "-DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config" - -tumbleweed/openssl_1.1.x/x86/gcc: - extends: .tumbleweed - script: - - cmake - -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake - $CMAKE_DEFAULT_OPTIONS - -DWITH_SFTP=ON - -DWITH_SERVER=ON - -DWITH_ZLIB=ON - -DWITH_PCAP=ON - -DWITH_DSA=ON - -DUNIT_TESTING=ON .. - -tumbleweed/openssl_1.1.x/x86_64/gcc7: - extends: .tumbleweed - variables: - CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7 -DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config" - -tumbleweed/openssl_1.1.x/x86/gcc7: - extends: .tumbleweed - script: - - cmake - -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake - -DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7 - $CMAKE_DEFAULT_OPTIONS - -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON - -DWITH_DSA=ON - -DUNIT_TESTING=ON .. && - make -j$(nproc) && - ctest --output-on-failure - -tumbleweed/openssl_1.1.x/x86_64/clang: - extends: .tumbleweed - variables: - CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config" - -tumbleweed/static-analysis: - extends: .tests - stage: analysis - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD - script: - - export CCC_CC=clang - - export CCC_CXX=clang++ - - scan-build cmake - -DCMAKE_BUILD_TYPE=Debug - -DCMAKE_C_COMPILER=clang - -DCMAKE_CXX_COMPILER=clang++ - -DPICKY_DEVELOPER=ON - $CMAKE_BUILD_OPTIONS - $CMAKE_TEST_OPTIONS .. && - scan-build --status-bugs -o scan make -j$(nproc) - artifacts: - expire_in: 1 week - when: on_failure - paths: - - obj/scan - - -############################################################################### -# FreeBSD builds # -############################################################################### -# That is a specific runner that we cannot enable universally. -# We restrict it to builds under the $BUILD_IMAGES_PROJECT project. -freebsd/x86_64: - image: - extends: .tests - before_script: - - mkdir -p obj && cd obj && cmake - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DPICKY_DEVELOPER=ON - -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON - -DUNIT_TESTING=ON .. - script: - - cmake $CMAKE_DEFAULT_OPTIONS - -DWITH_SFTP=ON - -DWITH_SERVER=ON - -DWITH_ZLIB=ON - -DWITH_PCAP=ON - -DUNIT_TESTING=ON .. && - make && - ctest --output-on-failure - tags: - - private - - freebsd - only: - - branches@libssh/libssh-mirror - - branches@cryptomilk/libssh-mirror - - branches@jjelen/libssh-mirror - - branches@marco.fortina/libssh-mirror - - -############################################################################### -# Visual Studio builds # -############################################################################### -.vs: - stage: test - cache: - key: vcpkg.${CI_JOB_NAME} - paths: - - .vcpkg - variables: - ErrorActionPreference: STOP - script: - - cmake --build . - - ctest --output-on-failure - tags: - - windows - - shared-windows - except: - - tags - artifacts: - expire_in: 1 week - when: on_failure - paths: - - obj/ - before_script: - - choco install --no-progress -y cmake - - $env:Path += ';C:\Program Files\CMake\bin' - - If (!(test-path .vcpkg\archives)) { mkdir -p .vcpkg\archives } - - $env:VCPKG_DEFAULT_BINARY_CACHE="$PWD\.vcpkg\archives" - - echo $env:VCPKG_DEFAULT_BINARY_CACHE - - $env:VCPKG_DEFAULT_TRIPLET="$TRIPLET-windows" - - vcpkg install cmocka - - vcpkg install openssl - - vcpkg install zlib - - vcpkg integrate install - - mkdir -p obj; if ($?) {cd obj}; if (! $?) {exit 1} - - cmake - -A $PLATFORM - -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake - -DPICKY_DEVELOPER=ON - -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON - -DUNIT_TESTING=ON .. - -visualstudio/x86_64: - extends: .vs - variables: - PLATFORM: "x64" - TRIPLET: "x64" - -visualstudio/x86: - extends: .vs - variables: - PLATFORM: "win32" - TRIPLET: "x86" - -############################################################################### -# Coverity # -############################################################################### -# -# git push -o ci.variable="COVERITY_SCAN_TOKEN=XXXXXX" \ -# -o ci.variable="COVERITY_SCAN_PROJECT_NAME=XXXXXX" \ -# -o ci.variable="COVERITY_SCAN_EMAIL=XXXXXX" \ -# -f gitlab - -coverity: - stage: analysis - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$COVERITY_BUILD - script: - - mkdir obj && cd obj - - wget https://scan.coverity.com/download/linux64 --post-data "token=$COVERITY_SCAN_TOKEN&project=$COVERITY_SCAN_PROJECT_NAME" -O /tmp/coverity_tool.tgz - - tar xf /tmp/coverity_tool.tgz - - cmake -DCMAKE_BUILD_TYPE=Debug $CMAKE_BUILD_OPTIONS $CMAKE_TEST_OPTIONS .. - - cov-analysis-linux64-*/bin/cov-build --dir cov-int make -j$(nproc) - - tar czf cov-int.tar.gz cov-int - - curl - --form token=$COVERITY_SCAN_TOKEN - --form email=$COVERITY_SCAN_EMAIL - --form file=@cov-int.tar.gz - --form version="`git describe --tags`" - --form description="CI build" - https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME - tags: - - shared - only: - refs: - - master - - schedules - variables: - - $COVERITY_SCAN_TOKEN != null - - $COVERITY_SCAN_PROJECT_NAME != null - - $COVERITY_SCAN_EMAIL != null - artifacts: - expire_in: 1 week - when: on_failure - paths: - - obj/cov-int/*.txt diff --git a/libssh/CHANGELOG b/libssh/CHANGELOG index 5d05bcac..ffeb5ff8 100644 --- a/libssh/CHANGELOG +++ b/libssh/CHANGELOG @@ -1,6 +1,34 @@ CHANGELOG ========= +version 0.10.5 (released 2023-05-04) + * Fix CVE-2023-1667: a NULL dereference during rekeying with algorithm guessing + * Fix CVE-2023-2283: a possible authorization bypass in + pki_verify_data_signature under low-memory conditions. + * Fix several memory leaks in GSSAPI handling code + * Escape braces in ProxyCommand created from ProxyJump options for zsh + compatibility. + * Fix pkg-config path relocation for MinGW + * Improve doxygen documentation + * Fix build with cygwin due to the glob support + * Do not enqueue outgoing packets after sending SSH2_MSG_NEWKEYS + * Add support for SSH_SUPPRESS_DEPRECATED + * Avoid functions declarations without prototype to build with clang 15 + * Fix spelling issues + * Avoid expanding KnownHosts, ProxyCommands and IdentityFiles repetitively + * Add support sk-* keys through configuration + * Improve checking for Argp library + * Log information about received extensions + * Correctly handle rekey with delayed compression + * Move the EC keys handling to OpenSSL 3.0 API + * Record peer disconnect message + * Avoid deadlock when write buffering occurs and we call poll recursively to + flush the output buffer + * Disable preauthentication compression by default + * Add CentOS 8 Stream / OpenSSL 1.1.1 to CI + * Add accidentally removed default compile flags + * Solve incorrect parsing of ProxyCommand option + version 0.10.4 (released 2022-09-07) * Fixed issues with KDF on big endian @@ -75,7 +103,7 @@ version 0.9.4 (released 2020-04-09) * Fixed CVE-2020-1730 - Possible DoS in client and server when handling AES-CTR keys with OpenSSL * Added diffie-hellman-group14-sha256 - * Fixed serveral possible memory leaks + * Fixed several possible memory leaks version 0.9.3 (released 2019-12-10) * Fixed CVE-2019-14889 - SCP: Unsanitized location leads to command execution @@ -226,7 +254,7 @@ version 0.6.1 (released 2014-02-08) * Fixed DSA signature extraction. * Fixed some memory leaks. * Fixed read of non-connected socket. - * Fixed thread dectection. + * Fixed thread detection. version 0.6.0 (released 2014-01-08) * Added new publicy key API. @@ -251,7 +279,7 @@ version 0.6.0 (released 2014-01-08) version 0.5.5 (released 2013-07-26) * BUG 103: Fix ProxyCommand parsing. * Fix setting -D_FORTIFY_SOURCE=2. - * Fix pollset error return if emtpy. + * Fix pollset error return if empty. * Fix NULL pointer checks in channel functions. * Several bugfixes. @@ -267,7 +295,7 @@ version 0.5.3 (released 2012-11-20) * BUG #84 - Fix bug in sftp_mkdir not returning on error. * BUG #85 - Fixed a possible channel infinite loop if the connection dropped. * BUG #88 - Added missing channel request_state and set it to accepted. - * BUG #89 - Reset error state to no error on successful SSHv1 authentiction. + * BUG #89 - Reset error state to no error on successful SSHv1 authentication. * Fixed a possible use after free in ssh_free(). * Fixed multiple possible NULL pointer dereferences. * Fixed multiple memory leaks in error paths. @@ -328,7 +356,7 @@ version 0.4.7 (released 2010-12-28) * Fixed a possible memory leak in ssh_get_user_home(). * Fixed a memory leak in sftp_xstat. * Fixed uninitialized fd->revents member. - * Fixed timout value in ssh_channel_accept(). + * Fixed timeout value in ssh_channel_accept(). * Fixed length checks in ssh_analyze_banner(). * Fixed a possible data overread and crash bug. * Fixed setting max_fd which breaks ssh_select(). @@ -351,7 +379,7 @@ version 0.4.5 (released 2010-07-13) * Added option to bind a client to an ip address. * Fixed the ssh socket polling function. * Fixed Windows related bugs in bsd_poll(). - * Fixed serveral build warnings. + * Fixed several build warnings. version 0.4.4 (released 2010-06-01) * Fixed a bug in the expand function for escape sequences. @@ -370,17 +398,17 @@ version 0.4.3 (released 2010-05-18) * Fixed sftp_chown. * Fixed sftp_rename on protocol version 3. * Fixed a blocking bug in channel_poll. - * Fixed config parsing wich has overwritten user specified values. + * Fixed config parsing which has overwritten user specified values. * Fixed hashed [host]:port format in knownhosts * Fixed Windows build. - * Fixed doublefree happening after a negociation error. + * Fixed doublefree happening after a negotiation error. * Fixed aes*-ctr with <= OpenSSL 0.9.7b. * Fixed some documentation. * Fixed exec example which has broken read usage. * Fixed broken algorithm choice for server. * Fixed a typo that we don't export all symbols. * Removed the unneeded dependency to doxygen. - * Build examples only on the Linux plattform. + * Build examples only on the Linux platform. version 0.4.2 (released 2010-03-15) * Added owner and group information in sftp attributes. @@ -402,7 +430,7 @@ version 0.4.1 (released 2010-02-13) * Added an example for exec. * Added private key type detection feature in privatekey_from_file(). * Fixed zlib compression fallback. - * Fixed kex bug that client preference should be prioritary + * Fixed kex bug that client preference should be priority * Fixed known_hosts file set by the user. * Fixed a memleak in channel_accept(). * Fixed underflow when leave_function() are unbalanced @@ -540,7 +568,7 @@ version 0.11-dev * Keyboard-interactive authentication working. version 0.1 (released 2004-03-05) - * Begining of sftp subsystem implementation. + * Beginning of sftp subsystem implementation. * Some cleanup into channels implementation * Now every channel functions is called by its CHANNEL handler. * Added channel_poll() and channel_read(). @@ -561,7 +589,7 @@ version 0.0.4 (released 2003-10-10) * Added a wrapper.c file. The goal is to provide a similar API to every cryptographic functions. bignums and sha/md5 are wrapped now. * More work than it first looks. - * Support for other crypto libs planed (lighter libs) + * Support for other crypto libs planned (lighter libs) * Fixed stupid select() bug. * Libssh now compiles and links with openssl 0.9.6 * RSA pubkey authentication code now works ! diff --git a/libssh/CMakeLists.txt b/libssh/CMakeLists.txt index 7bc3331c..c3565f0d 100644 --- a/libssh/CMakeLists.txt +++ b/libssh/CMakeLists.txt @@ -10,7 +10,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules") include(DefineCMakeDefaults) include(DefineCompilerFlags) -project(libssh VERSION 0.10.4 LANGUAGES C) +project(libssh VERSION 0.10.5 LANGUAGES C) # global needed variable set(APPLICATION_NAME ${PROJECT_NAME}) @@ -22,7 +22,7 @@ set(APPLICATION_NAME ${PROJECT_NAME}) # Increment AGE. Set REVISION to 0 # If the source code was changed, but there were no interface changes: # Increment REVISION. -set(LIBRARY_VERSION "4.9.4") +set(LIBRARY_VERSION "4.9.5") set(LIBRARY_SOVERSION "4") # where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked @@ -103,9 +103,7 @@ if (WITH_NACL) endif (NOT NACL_FOUND) endif (WITH_NACL) -if (BSD OR SOLARIS OR OSX OR CYGWIN) - find_package(Argp) -endif (BSD OR SOLARIS OR OSX OR CYGWIN) +find_package(Argp) # Disable symbol versioning in non UNIX platforms if (UNIX) @@ -125,7 +123,7 @@ add_subdirectory(src) # pkg-config file if (UNIX OR MINGW) -configure_file(libssh.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc) +configure_file(libssh.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc @ONLY) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc diff --git a/libssh/CONTRIBUTING.md b/libssh/CONTRIBUTING.md index 4f5bb42f..2d1a8a17 100644 --- a/libssh/CONTRIBUTING.md +++ b/libssh/CONTRIBUTING.md @@ -274,7 +274,7 @@ This is bad: * This is a multi line comment, * with some more words...*/ -### Indention & Whitespace & 80 columns +### Indentation & Whitespace & 80 columns To avoid confusion, indentations have to be 4 spaces. Do not use tabs!. When wrapping parameters for function calls, align the parameter list with the first diff --git a/libssh/CPackConfig.cmake b/libssh/CPackConfig.cmake index 5bd52c56..526bed32 100644 --- a/libssh/CPackConfig.cmake +++ b/libssh/CPackConfig.cmake @@ -10,7 +10,7 @@ set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION}) # SOURCE GENERATOR set(CPACK_SOURCE_GENERATOR "TXZ") -set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]git/;/[.]clangd/;/[.]cache/;.gitignore;/build*;/obj*;tags;cscope.*;compile_commands.json;.*\.patch") +set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]git;/[.]clangd/;/[.]cache/;.gitignore;/build*;/obj*;tags;cscope.*;compile_commands.json;.*\.patch") set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") ### NSIS INSTALLER diff --git a/libssh/CompilerChecks.cmake b/libssh/CompilerChecks.cmake index 9acae281..cbad1f56 100644 --- a/libssh/CompilerChecks.cmake +++ b/libssh/CompilerChecks.cmake @@ -70,7 +70,7 @@ if (UNIX) check_c_compiler_flag_ssp("-fstack-protector-strong" WITH_STACK_PROTECTOR_STRONG) if (WITH_STACK_PROTECTOR_STRONG) list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector-strong") - # This is needed as Solaris has a seperate libssp + # This is needed as Solaris has a separate libssp if (SOLARIS) list(APPEND SUPPORTED_LINKER_FLAGS "-fstack-protector-strong") endif() @@ -78,7 +78,7 @@ if (UNIX) check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR) if (WITH_STACK_PROTECTOR) list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector") - # This is needed as Solaris has a seperate libssp + # This is needed as Solaris has a separate libssp if (SOLARIS) list(APPEND SUPPORTED_LINKER_FLAGS "-fstack-protector") endif() diff --git a/libssh/ConfigureChecks.cmake b/libssh/ConfigureChecks.cmake index 7103f303..9de10225 100644 --- a/libssh/ConfigureChecks.cmake +++ b/libssh/ConfigureChecks.cmake @@ -320,7 +320,7 @@ int main(void) { # For detecting attributes we need to treat warnings as # errors if (UNIX OR MINGW) - # Get warnings for attributs + # Get warnings for attributes check_c_compiler_flag("-Wattributes" REQUIRED_FLAGS_WERROR) if (REQUIRED_FLAGS_WERROR) string(APPEND CMAKE_REQUIRED_FLAGS "-Wattributes ") diff --git a/libssh/DefineOptions.cmake b/libssh/DefineOptions.cmake index 068db988..6881b9a2 100644 --- a/libssh/DefineOptions.cmake +++ b/libssh/DefineOptions.cmake @@ -2,7 +2,7 @@ option(WITH_GSSAPI "Build with GSSAPI support" ON) option(WITH_ZLIB "Build with ZLIB support" ON) option(WITH_SFTP "Build with SFTP support" ON) option(WITH_SERVER "Build with SSH server support" ON) -option(WITH_DEBUG_CRYPTO "Build with cryto debug output" OFF) +option(WITH_DEBUG_CRYPTO "Build with crypto debug output" OFF) option(WITH_DEBUG_PACKET "Build with packet debug output" OFF) option(WITH_DEBUG_CALLTRACE "Build with calltrace debug output" ON) option(WITH_DSA "Build with DSA" OFF) @@ -16,7 +16,7 @@ option(WITH_PKCS11_URI "Build with PKCS#11 URI support" OFF) option(UNIT_TESTING "Build with unit tests" OFF) option(CLIENT_TESTING "Build with client tests; requires openssh" OFF) option(SERVER_TESTING "Build with server tests; requires openssh and dropbear" OFF) -option(WITH_BENCHMARKS "Build benchmarks tools" OFF) +option(WITH_BENCHMARKS "Build benchmarks tools; enables unit testing and client tests" OFF) option(WITH_EXAMPLES "Build examples" ON) option(WITH_NACL "Build with libnacl (curve25519)" ON) option(WITH_SYMBOL_VERSIONING "Build with symbol versioning" ON) diff --git a/libssh/INSTALL b/libssh/INSTALL index c2eae34b..6e9fbf13 100644 --- a/libssh/INSTALL +++ b/libssh/INSTALL @@ -39,7 +39,7 @@ GNU/Linux, MacOS X, MSYS/MinGW: cmake -DUNIT_TESTING=ON -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug .. make -On Windows you should choose a makefile gernerator with -G or use +On Windows you should choose a makefile generator with -G or use cmake-gui.exe .. diff --git a/libssh/cmake/Modules/DefineCMakeDefaults.cmake b/libssh/cmake/Modules/DefineCMakeDefaults.cmake index ef4fb337..6f369faa 100644 --- a/libssh/cmake/Modules/DefineCMakeDefaults.cmake +++ b/libssh/cmake/Modules/DefineCMakeDefaults.cmake @@ -6,7 +6,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) # Put the include dirs which are in the source or build tree # before all other include dirs, so the headers in the sources -# are prefered over the already installed ones +# are preferred over the already installed ones # since cmake 2.4.1 set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON) diff --git a/libssh/cmake/Modules/FindArgp.cmake b/libssh/cmake/Modules/FindArgp.cmake index 454965ac..45d191fe 100644 --- a/libssh/cmake/Modules/FindArgp.cmake +++ b/libssh/cmake/Modules/FindArgp.cmake @@ -1,4 +1,8 @@ # - Try to find ARGP +# +# The argp can be either shipped as part of libc (ex. glibc) or as a separate +# library that requires additional linking (ex. Windows, Mac, musl libc, ...) +# # Once done this will define # # ARGP_ROOT_DIR - Set this variable to the root installation of ARGP diff --git a/libssh/cmake/Modules/FindGSSAPI.cmake b/libssh/cmake/Modules/FindGSSAPI.cmake index 4c3f44b1..d227d8dd 100644 --- a/libssh/cmake/Modules/FindGSSAPI.cmake +++ b/libssh/cmake/Modules/FindGSSAPI.cmake @@ -5,7 +5,7 @@ # GSSAPI_ROOT_DIR - Set this variable to the root installation of GSSAPI # # Read-Only variables: -# GSSAPI_FLAVOR_MIT - set to TURE if MIT Kerberos has been found +# GSSAPI_FLAVOR_MIT - set to TRUE if MIT Kerberos has been found # GSSAPI_FLAVOR_HEIMDAL - set to TRUE if Heimdal Keberos has been found # GSSAPI_FOUND - system has GSSAPI # GSSAPI_INCLUDE_DIR - the GSSAPI include directory diff --git a/libssh/config.h.cmake b/libssh/config.h.cmake index 1357615b..cc83734d 100644 --- a/libssh/config.h.cmake +++ b/libssh/config.h.cmake @@ -82,13 +82,13 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_PTHREAD_H 1 -/* Define to 1 if you have eliptic curve cryptography in openssl */ +/* Define to 1 if you have elliptic curve cryptography in openssl */ #cmakedefine HAVE_OPENSSL_ECC 1 -/* Define to 1 if you have eliptic curve cryptography in gcrypt */ +/* Define to 1 if you have elliptic curve cryptography in gcrypt */ #cmakedefine HAVE_GCRYPT_ECC 1 -/* Define to 1 if you have eliptic curve cryptography */ +/* Define to 1 if you have elliptic curve cryptography */ #cmakedefine HAVE_ECC 1 /* Define to 1 if you have DSA */ diff --git a/libssh/doc/CMakeLists.txt b/libssh/doc/CMakeLists.txt index 259424b4..965f8e32 100644 --- a/libssh/doc/CMakeLists.txt +++ b/libssh/doc/CMakeLists.txt @@ -18,7 +18,8 @@ if (DOXYGEN_FOUND) set(DOXYGEN_PREDEFINED DOXYGEN WITH_SERVER WITH_SFTP - PRINTF_ATTRIBUTE(x,y)) + PRINTF_ATTRIBUTE\(x,y\)) + set(DOXYGEN_DOT_GRAPH_MAX_NODES 100) set(DOXYGEN_EXCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/that_style) set(DOXYGEN_HTML_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/that_style/header.html) diff --git a/libssh/doc/curve25519-sha256@libssh.org.txt b/libssh/doc/curve25519-sha256@libssh.org.txt index 75541902..04d88575 100644 --- a/libssh/doc/curve25519-sha256@libssh.org.txt +++ b/libssh/doc/curve25519-sha256@libssh.org.txt @@ -3,13 +3,13 @@ curve25519-sha256@libssh.org.txt Aris Adamantiadis 1. Introduction -This document describes the key exchange methode curve25519-sha256@libssh.org +This document describes the key exchange method curve25519-sha256@libssh.org for SSH version 2 protocol. It is provided as an alternative to the existing key exchange mechanisms based on either Diffie-Hellman or Elliptic Curve Diffie- Hellman [RFC5656]. The reason is the following : During summer of 2013, revelations from ex- consultant at NSA Edward Snowden gave proof that NSA willingly inserts backdoors -into softwares, hardware components and published standards. While it is still +into software, hardware components and published standards. While it is still believed that the mathematics behind ECC cryptography are still sound and solid, some people (including Bruce Schneier [SCHNEIER]), showed their lack of confidence in NIST-published curves such as nistp256, nistp384, nistp521, for which constant @@ -42,8 +42,8 @@ The following is an overview of the key exchange process: Client Server ------ ------ Generate ephemeral key pair. -SSH_MSG_KEX_ECDH_INIT --------> - Verify that client public key +SSH_MSG_KEX_ECDH_INIT --------> + Verify that client public key length is 32 bytes. Generate ephemeral key pair. Compute shared secret. @@ -55,7 +55,7 @@ Compute shared secret. Generate exchange hash. Verify server's signature. -* Optional but strongly recommanded as this protects against MITM attacks. +* Optional but strongly recommended as this protects against MITM attacks. This is implemented using the same messages as described in RFC5656 chapter 4 @@ -109,7 +109,7 @@ This number is calculated using the following procedure: side's public key and the local private key scalar. The whole 32 bytes of the number X are then converted into a big integer k. - This conversion follows the network byte order. This step differs from + This conversion follows the network byte order. This step differs from RFC5656. [RFC5656] https://tools.ietf.org/html/rfc5656 diff --git a/libssh/doc/mainpage.dox b/libssh/doc/mainpage.dox index a3d64087..eba140dc 100644 --- a/libssh/doc/mainpage.dox +++ b/libssh/doc/mainpage.dox @@ -149,7 +149,7 @@ The libssh Team @subsection main-rfc-secsh Secure Shell (SSH) -The following RFC documents described SSH-2 protcol as an Internet standard. +The following RFC documents described SSH-2 protocol as an Internet standard. - RFC 4250, The Secure Shell (SSH) Protocol Assigned Numbers diff --git a/libssh/examples/CMakeLists.txt b/libssh/examples/CMakeLists.txt index 466865f7..72ceed2f 100644 --- a/libssh/examples/CMakeLists.txt +++ b/libssh/examples/CMakeLists.txt @@ -39,34 +39,34 @@ if (UNIX AND NOT WIN32) target_compile_options(ssh-X11-client PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(ssh-X11-client ssh::ssh) - if (WITH_SERVER AND (ARGP_LIBRARY OR HAVE_ARGP_H)) + if (WITH_SERVER AND (ARGP_LIBRARIES OR HAVE_ARGP_H)) if (HAVE_LIBUTIL) add_executable(ssh_server_fork ssh_server.c) target_compile_options(ssh_server_fork PRIVATE ${DEFAULT_C_COMPILE_FLAGS} -DWITH_FORK) - target_link_libraries(ssh_server_fork ssh::ssh ${ARGP_LIBRARY} util) + target_link_libraries(ssh_server_fork ssh::ssh ${ARGP_LIBRARIES} util) add_executable(ssh_server_pthread ssh_server.c) target_compile_options(ssh_server_pthread PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) - target_link_libraries(ssh_server_pthread ssh::ssh ${ARGP_LIBRARY} pthread util) + target_link_libraries(ssh_server_pthread ssh::ssh ${ARGP_LIBRARIES} pthread util) endif (HAVE_LIBUTIL) if (WITH_GSSAPI AND GSSAPI_FOUND) add_executable(proxy proxy.c) target_compile_options(proxy PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) - target_link_libraries(proxy ssh::ssh ${ARGP_LIBRARY}) + target_link_libraries(proxy ssh::ssh ${ARGP_LIBRARIES}) add_executable(sshd_direct-tcpip sshd_direct-tcpip.c) target_compile_options(sshd_direct-tcpip PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) - target_link_libraries(sshd_direct-tcpip ssh::ssh ${ARGP_LIBRARY}) + target_link_libraries(sshd_direct-tcpip ssh::ssh ${ARGP_LIBRARIES}) endif (WITH_GSSAPI AND GSSAPI_FOUND) add_executable(samplesshd-kbdint samplesshd-kbdint.c) target_compile_options(samplesshd-kbdint PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) - target_link_libraries(samplesshd-kbdint ssh::ssh ${ARGP_LIBRARY}) + target_link_libraries(samplesshd-kbdint ssh::ssh ${ARGP_LIBRARIES}) add_executable(keygen2 keygen2.c ${examples_SRCS}) target_compile_options(keygen2 PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) - target_link_libraries(keygen2 ssh::ssh ${ARGP_LIBRARY}) + target_link_libraries(keygen2 ssh::ssh ${ARGP_LIBRARIES}) endif() endif (UNIX AND NOT WIN32) @@ -75,9 +75,9 @@ if (WITH_SERVER) add_executable(samplesshd-cb samplesshd-cb.c) target_compile_options(samplesshd-cb PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(samplesshd-cb ssh::ssh) - if (ARGP_LIBRARY OR HAVE_ARGP_H) - target_link_libraries(samplesshd-cb ${ARGP_LIBRARY}) - endif(ARGP_LIBRARY OR HAVE_ARGP_H) + if (ARGP_LIBRARIES OR HAVE_ARGP_H) + target_link_libraries(samplesshd-cb ${ARGP_LIBRARIES}) + endif(ARGP_LIBRARIES OR HAVE_ARGP_H) endif() add_executable(exec exec.c ${examples_SRCS}) diff --git a/libssh/examples/samplesftp.c b/libssh/examples/samplesftp.c index 9c8cd34a..bc286c4b 100644 --- a/libssh/examples/samplesftp.c +++ b/libssh/examples/samplesftp.c @@ -47,7 +47,7 @@ static void do_sftp(ssh_session session) { int len = 1; unsigned int i; char data[BUF_SIZE] = {0}; - char *lnk; + char *lnk = NULL; unsigned int count; @@ -86,6 +86,7 @@ static void do_sftp(ssh_session session) { goto end; } printf("readlink /tmp/sftp_symlink_test: %s\n", lnk); + ssh_string_free_char(lnk); sftp_unlink(sftp, "/tmp/sftp_symlink_test"); @@ -173,7 +174,7 @@ static void do_sftp(ssh_session session) { sftp_attributes_free(file); } - /* when file = NULL, an error has occured OR the directory listing is end of + /* when file = NULL, an error has occurred OR the directory listing is end of * file */ if (!sftp_dir_eof(dir)) { fprintf(stderr, "Error: %s\n", ssh_get_error(session)); diff --git a/libssh/examples/samplesshd-kbdint.c b/libssh/examples/samplesshd-kbdint.c index 9b09cf27..6608306c 100644 --- a/libssh/examples/samplesshd-kbdint.c +++ b/libssh/examples/samplesshd-kbdint.c @@ -369,9 +369,9 @@ int main(int argc, char **argv){ } } while(!chan); - if(!chan) { - printf("Error: cleint did not ask for a channel session (%s)\n", - ssh_get_error(session)); + if (!chan) { + printf("Error: client did not ask for a channel session (%s)\n", + ssh_get_error(session)); ssh_finalize(); return 1; } diff --git a/libssh/examples/ssh_X11_client.c b/libssh/examples/ssh_X11_client.c index 369b9b4a..6e785ee2 100644 --- a/libssh/examples/ssh_X11_client.c +++ b/libssh/examples/ssh_X11_client.c @@ -453,7 +453,7 @@ connect_local_xsocket(int display_number) static int -x11_connect_display() +x11_connect_display(void) { int display_number; const char *display = NULL; diff --git a/libssh/examples/sshd_direct-tcpip.c b/libssh/examples/sshd_direct-tcpip.c index 18a870b9..b0e29796 100644 --- a/libssh/examples/sshd_direct-tcpip.c +++ b/libssh/examples/sshd_direct-tcpip.c @@ -27,6 +27,9 @@ clients must be made or how a client should react. #ifdef HAVE_ARGP_H #include #endif +#ifndef _WIN32 +#include +#endif #include #include #include @@ -197,7 +200,7 @@ subsystem_request(UNUSED_PARAM(ssh_session session), UNUSED_PARAM(void *userdata)) { _ssh_log(SSH_LOG_PROTOCOL, - "=== subsystem_request", "Channel subsystem reqeuest: %s", + "=== subsystem_request", "Channel subsystem request: %s", subsystem); return 0; } @@ -293,7 +296,7 @@ my_channel_eof_function(ssh_session session, _ssh_log(SSH_LOG_PROTOCOL, "=== my_channel_eof_function", - "Got EOF on channel. Shuting down write on socket (fd = %d).", + "Got EOF on channel. Shutting down write on socket (fd = %d).", *event_fd_data->p_fd); stack_socket_close(session, event_fd_data); diff --git a/libssh/examples/sshnetcat.c b/libssh/examples/sshnetcat.c index 9bc5d52e..59b0a289 100644 --- a/libssh/examples/sshnetcat.c +++ b/libssh/examples/sshnetcat.c @@ -238,9 +238,10 @@ void set_pcap(ssh_session session){ } void cleanup_pcap(void); -void cleanup_pcap(){ +void cleanup_pcap(void) +{ ssh_pcap_file_free(pcap); - pcap=NULL; + pcap = NULL; } #endif diff --git a/libssh/include/libssh/agent.h b/libssh/include/libssh/agent.h index 72052159..caf8d3e2 100644 --- a/libssh/include/libssh/agent.h +++ b/libssh/include/libssh/agent.h @@ -70,6 +70,10 @@ #define SSH_AGENT_RSA_SHA2_256 0x02 #define SSH_AGENT_RSA_SHA2_512 0x04 +#ifdef __cplusplus +extern "C" { +#endif + struct ssh_agent_struct { struct ssh_socket_struct *sock; ssh_buffer ident; @@ -115,4 +119,8 @@ ssh_string ssh_agent_sign_data(ssh_session session, const ssh_key pubkey, struct ssh_buffer_struct *data); +#ifdef __cplusplus +} +#endif + #endif /* __AGENT_H */ diff --git a/libssh/include/libssh/auth.h b/libssh/include/libssh/auth.h index 90b377d4..b358b7a2 100644 --- a/libssh/include/libssh/auth.h +++ b/libssh/include/libssh/auth.h @@ -23,6 +23,10 @@ #include "config.h" #include "libssh/callbacks.h" +#ifdef __cplusplus +extern "C" { +#endif + SSH_PACKET_CALLBACK(ssh_packet_userauth_banner); SSH_PACKET_CALLBACK(ssh_packet_userauth_failure); SSH_PACKET_CALLBACK(ssh_packet_userauth_success); @@ -100,4 +104,8 @@ enum ssh_auth_service_state_e { SSH_AUTH_SERVICE_DENIED, }; +#ifdef __cplusplus +} +#endif + #endif /* AUTH_H_ */ diff --git a/libssh/include/libssh/bignum.h b/libssh/include/libssh/bignum.h index 726ed7b9..6b5dc1a2 100644 --- a/libssh/include/libssh/bignum.h +++ b/libssh/include/libssh/bignum.h @@ -25,9 +25,16 @@ #include "libssh/libgcrypt.h" #include "libssh/libmbedcrypto.h" +#ifdef __cplusplus +extern "C" { +#endif + bignum ssh_make_string_bn(ssh_string string); ssh_string ssh_make_bignum_string(bignum num); void ssh_print_bignum(const char *which, const_bignum num); +#ifdef __cplusplus +} +#endif #endif /* BIGNUM_H_ */ diff --git a/libssh/include/libssh/bind.h b/libssh/include/libssh/bind.h index c0439d2c..56f97f27 100644 --- a/libssh/include/libssh/bind.h +++ b/libssh/include/libssh/bind.h @@ -25,6 +25,10 @@ #include "libssh/kex.h" #include "libssh/session.h" +#ifdef __cplusplus +extern "C" { +#endif + struct ssh_bind_struct { struct ssh_common_struct common; /* stuff common to ssh_bind and ssh_session */ struct ssh_bind_callbacks_struct *bind_callbacks; @@ -57,5 +61,8 @@ struct ssh_bind_struct { struct ssh_poll_handle_struct *ssh_bind_get_poll(struct ssh_bind_struct *sshbind); +#ifdef __cplusplus +} +#endif #endif /* BIND_H_ */ diff --git a/libssh/include/libssh/bind_config.h b/libssh/include/libssh/bind_config.h index 7ee19b87..5f2dccce 100644 --- a/libssh/include/libssh/bind_config.h +++ b/libssh/include/libssh/bind_config.h @@ -28,6 +28,10 @@ #include "libssh/server.h" +#ifdef __cplusplus +extern "C" { +#endif + enum ssh_bind_config_opcode_e { /* Known but not allowed in Match block */ BIND_CFG_NOT_ALLOWED_IN_MATCH = -4, @@ -71,4 +75,8 @@ int ssh_bind_config_parse_file(ssh_bind sshbind, const char *filename); */ int ssh_bind_config_parse_string(ssh_bind bind, const char *input); +#ifdef __cplusplus +} +#endif + #endif /* BIND_CONFIG_H_ */ diff --git a/libssh/include/libssh/blf.h b/libssh/include/libssh/blf.h index ce131e6b..201821a2 100644 --- a/libssh/include/libssh/blf.h +++ b/libssh/include/libssh/blf.h @@ -49,6 +49,10 @@ #define BLF_MAXKEYLEN ((BLF_N-2)*4) /* 448 bits */ #define BLF_MAXUTILIZED ((BLF_N+2)*4) /* 576 bits */ +#ifdef __cplusplus +extern "C" { +#endif + /* Blowfish context */ typedef struct BlowfishContext { uint32_t S[4][256]; /* S-Boxes */ @@ -84,4 +88,9 @@ void ssh_blf_cbc_decrypt(ssh_blf_ctx *, uint8_t *, uint8_t *, uint32_t); uint32_t Blowfish_stream2word(const uint8_t *, uint16_t , uint16_t *); #endif /* !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H) */ + +#ifdef __cplusplus +} +#endif + #endif /* _BLF_H */ diff --git a/libssh/include/libssh/buffer.h b/libssh/include/libssh/buffer.h index a55a1b40..1fce7b76 100644 --- a/libssh/include/libssh/buffer.h +++ b/libssh/include/libssh/buffer.h @@ -27,6 +27,10 @@ #define SSH_BUFFER_PACK_END ((uint32_t) 0x4f65feb3) +#ifdef __cplusplus +extern "C" { +#endif + void ssh_buffer_set_secure(ssh_buffer buffer); int ssh_buffer_add_ssh_string(ssh_buffer buffer, ssh_string string); int ssh_buffer_add_u8(ssh_buffer buffer, uint8_t data); @@ -74,4 +78,8 @@ ssh_string ssh_buffer_get_ssh_string(ssh_buffer buffer); uint32_t ssh_buffer_pass_bytes_end(ssh_buffer buffer, uint32_t len); uint32_t ssh_buffer_pass_bytes(ssh_buffer buffer, uint32_t len); +#ifdef __cplusplus +} +#endif + #endif /* BUFFER_H_ */ diff --git a/libssh/include/libssh/callbacks.h b/libssh/include/libssh/callbacks.h index 36fe7f8c..8ccc0511 100644 --- a/libssh/include/libssh/callbacks.h +++ b/libssh/include/libssh/callbacks.h @@ -81,9 +81,9 @@ typedef void (*ssh_log_callback) (ssh_session session, int priority, * * @param priority Priority of the log, the smaller being the more important. * - * @param function The function name calling the the logging fucntions. + * @param function The function name calling the logging functions. * - * @param message The actual message + * @param buffer The actual message * * @param userdata Userdata to be passed to the callback function. */ @@ -117,6 +117,8 @@ typedef void (*ssh_global_request_callback) (ssh_session session, * sends back an X11 connection attempt. This is a client-side API * @param session current session handler * @param userdata Userdata to be passed to the callback function. + * @param originator_address IP address of the machine who sent the request + * @param originator_port port number of the machine who sent the request * @returns a valid ssh_channel handle if the request is to be allowed * @returns NULL if the request should not be allowed * @warning The channel pointer returned by this callback must be closed by the application. @@ -268,7 +270,7 @@ typedef ssh_string (*ssh_gssapi_select_oid_callback) (ssh_session session, const int n_oid, ssh_string *oids, void *userdata); /* - * @brief handle the negociation of a security context, server side. + * @brief handle the negotiation of a security context, server side. * @param session current session handler * @param[in] input_token input token provided by client * @param[out] output_token output of the gssapi accept_sec_context method, @@ -397,7 +399,7 @@ struct ssh_socket_callbacks_struct { */ ssh_callback_int_int exception; /** This function is called when the ssh_socket_connect was used on the socket - * on nonblocking state, and the connection successed. + * on nonblocking state, and the connection succeeded. */ ssh_callback_int_int connected; }; @@ -625,6 +627,7 @@ typedef void (*ssh_channel_signal_callback) (ssh_session session, * @brief SSH channel exit status callback. Called when a channel has received an exit status * @param session Current session handler * @param channel the actual channel + * @param exit_status Exit status of the ran command * @param userdata Userdata to be passed to the callback function. */ typedef void (*ssh_channel_exit_status_callback) (ssh_session session, @@ -637,7 +640,7 @@ typedef void (*ssh_channel_exit_status_callback) (ssh_session session, * @param session Current session handler * @param channel the actual channel * @param signal the signal name (without the SIG prefix) - * @param core a boolean telling wether a core has been dumped or not + * @param core a boolean telling whether a core has been dumped or not * @param errmsg the description of the exception * @param lang the language of the description (format: RFC 3066) * @param userdata Userdata to be passed to the callback function. @@ -652,12 +655,13 @@ typedef void (*ssh_channel_exit_signal_callback) (ssh_session session, /** * @brief SSH channel PTY request from a client. + * @param session the session * @param channel the channel * @param term The type of terminal emulation * @param width width of the terminal, in characters * @param height height of the terminal, in characters * @param pxwidth width of the terminal, in pixels - * @param pxheight height of the terminal, in pixels + * @param pwheight height of the terminal, in pixels * @param userdata Userdata to be passed to the callback function. * @returns 0 if the pty request is accepted * @returns -1 if the request is denied @@ -671,6 +675,7 @@ typedef int (*ssh_channel_pty_request_callback) (ssh_session session, /** * @brief SSH channel Shell request from a client. + * @param session the session * @param channel the channel * @param userdata Userdata to be passed to the callback function. * @returns 0 if the shell request is accepted @@ -683,6 +688,7 @@ typedef int (*ssh_channel_shell_request_callback) (ssh_session session, * @brief SSH auth-agent-request from the client. This request is * sent by a client when agent forwarding is available. * Server is free to ignore this callback, no answer is expected. + * @param session the session * @param channel the channel * @param userdata Userdata to be passed to the callback function. */ @@ -694,7 +700,12 @@ typedef void (*ssh_channel_auth_agent_req_callback) (ssh_session session, * @brief SSH X11 request from the client. This request is * sent by a client when X11 forwarding is requested(and available). * Server is free to ignore this callback, no answer is expected. + * @param session the session * @param channel the channel + * @param single_connection If true, only one channel should be forwarded + * @param auth_protocol The X11 authentication method to be used + * @param auth_cookie Authentication cookie encoded hexadecimal + * @param screen_number Screen number * @param userdata Userdata to be passed to the callback function. */ typedef void (*ssh_channel_x11_req_callback) (ssh_session session, @@ -706,11 +717,12 @@ typedef void (*ssh_channel_x11_req_callback) (ssh_session session, void *userdata); /** * @brief SSH channel PTY windows change (terminal size) from a client. + * @param session the session * @param channel the channel * @param width width of the terminal, in characters * @param height height of the terminal, in characters * @param pxwidth width of the terminal, in pixels - * @param pxheight height of the terminal, in pixels + * @param pwheight height of the terminal, in pixels * @param userdata Userdata to be passed to the callback function. * @returns 0 if the pty request is accepted * @returns -1 if the request is denied @@ -723,6 +735,7 @@ typedef int (*ssh_channel_pty_window_change_callback) (ssh_session session, /** * @brief SSH channel Exec request from a client. + * @param session the session * @param channel the channel * @param command the shell command to be executed * @param userdata Userdata to be passed to the callback function. @@ -736,6 +749,7 @@ typedef int (*ssh_channel_exec_request_callback) (ssh_session session, /** * @brief SSH channel environment request from a client. + * @param session the session * @param channel the channel * @param env_name name of the environment value to be set * @param env_value value of the environment value to be set @@ -752,6 +766,7 @@ typedef int (*ssh_channel_env_request_callback) (ssh_session session, void *userdata); /** * @brief SSH channel subsystem request from a client. + * @param session the session * @param channel the channel * @param subsystem the subsystem required * @param userdata Userdata to be passed to the callback function. @@ -766,6 +781,8 @@ typedef int (*ssh_channel_subsystem_request_callback) (ssh_session session, /** * @brief SSH channel write will not block (flow control). * + * @param session the session + * * @param channel the channel * * @param[in] bytes size of the remote window in bytes. Writing as much data @@ -917,7 +934,7 @@ LIBSSH_API int ssh_remove_channel_callbacks(ssh_channel channel, /** @} */ -/** @group libssh_threads +/** @addtogroup libssh_threads * @{ */ @@ -989,7 +1006,7 @@ LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_noop(void); * * @param[in] cb The callback to set. * - * @return 0 on success, < 0 on errror. + * @return 0 on success, < 0 on error. */ LIBSSH_API int ssh_set_log_callback(ssh_logging_callback cb); diff --git a/libssh/include/libssh/chacha.h b/libssh/include/libssh/chacha.h index 867f532d..ab3fe492 100644 --- a/libssh/include/libssh/chacha.h +++ b/libssh/include/libssh/chacha.h @@ -18,6 +18,10 @@ struct chacha_ctx { #define CHACHA_CTRLEN 8 #define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN) +#ifdef __cplusplus +extern "C" { +#endif + void chacha_keysetup(struct chacha_ctx *x, const uint8_t *k, uint32_t kbits) #ifdef HAVE_GCC_BOUNDED_ATTRIBUTE __attribute__((__bounded__(__minbytes__, 2, CHACHA_MINKEYLEN))) @@ -37,4 +41,8 @@ void chacha_encrypt_bytes(struct chacha_ctx *x, const uint8_t *m, #endif ; +#ifdef __cplusplus +} +#endif + #endif /* CHACHA_H */ diff --git a/libssh/include/libssh/channels.h b/libssh/include/libssh/channels.h index ce8540ae..cb2bea43 100644 --- a/libssh/include/libssh/channels.h +++ b/libssh/include/libssh/channels.h @@ -22,6 +22,10 @@ #define CHANNELS_H_ #include "libssh/priv.h" +#ifdef __cplusplus +extern "C" { +#endif + /** @internal * Describes the different possible states in a * outgoing (client) channel request @@ -35,7 +39,7 @@ enum ssh_channel_request_state_e { SSH_CHANNEL_REQ_STATE_ACCEPTED, /** A request has been replied and refused */ SSH_CHANNEL_REQ_STATE_DENIED, - /** A request has been replied and an error happend */ + /** A request has been replied and an error happened */ SSH_CHANNEL_REQ_STATE_ERROR }; @@ -109,4 +113,8 @@ int ssh_global_request(ssh_session session, ssh_buffer buffer, int reply); +#ifdef __cplusplus +} +#endif + #endif /* CHANNELS_H_ */ diff --git a/libssh/include/libssh/config_parser.h b/libssh/include/libssh/config_parser.h index e974917c..a7dd42a2 100644 --- a/libssh/include/libssh/config_parser.h +++ b/libssh/include/libssh/config_parser.h @@ -26,6 +26,10 @@ #ifndef CONFIG_PARSER_H_ #define CONFIG_PARSER_H_ +#ifdef __cplusplus +extern "C" { +#endif + char *ssh_config_get_cmd(char **str); char *ssh_config_get_token(char **str); @@ -54,4 +58,8 @@ int ssh_config_parse_uri(const char *tok, char **hostname, char **port); +#ifdef __cplusplus +} +#endif + #endif /* LIBSSH_CONFIG_H_ */ diff --git a/libssh/include/libssh/crypto.h b/libssh/include/libssh/crypto.h index 1d73613b..3dba18d0 100644 --- a/libssh/include/libssh/crypto.h +++ b/libssh/include/libssh/crypto.h @@ -216,6 +216,10 @@ struct ssh_cipher_struct { void (*cleanup)(struct ssh_cipher_struct *cipher); }; +#ifdef __cplusplus +extern "C" { +#endif + const struct ssh_cipher_struct *ssh_get_chacha20poly1305_cipher(void); int sshkdf_derive_key(struct ssh_crypto_struct *crypto, unsigned char *key, size_t key_len, @@ -227,4 +231,8 @@ int secure_memcmp(const void *s1, const void *s2, size_t n); ENGINE *pki_get_engine(void); #endif /* HAVE_LIBCRYPTO */ +#ifdef __cplusplus +} +#endif + #endif /* _CRYPTO_H_ */ diff --git a/libssh/include/libssh/curve25519.h b/libssh/include/libssh/curve25519.h index f0cc6348..a55f52c7 100644 --- a/libssh/include/libssh/curve25519.h +++ b/libssh/include/libssh/curve25519.h @@ -33,6 +33,10 @@ #define crypto_scalarmult crypto_scalarmult_curve25519 #else +#ifdef __cplusplus +extern "C" { +#endif + #define CURVE25519_PUBKEY_SIZE 32 #define CURVE25519_PRIVKEY_SIZE 32 int crypto_scalarmult_base(unsigned char *q, const unsigned char *n); @@ -48,9 +52,14 @@ typedef unsigned char ssh_curve25519_privkey[CURVE25519_PRIVKEY_SIZE]; int ssh_client_curve25519_init(ssh_session session); +void ssh_client_curve25519_remove_callbacks(ssh_session session); #ifdef WITH_SERVER void ssh_server_curve25519_init(ssh_session session); #endif /* WITH_SERVER */ +#ifdef __cplusplus +} +#endif + #endif /* CURVE25519_H_ */ diff --git a/libssh/include/libssh/dh-gex.h b/libssh/include/libssh/dh-gex.h index 4fc23d82..0f547e37 100644 --- a/libssh/include/libssh/dh-gex.h +++ b/libssh/include/libssh/dh-gex.h @@ -23,10 +23,19 @@ #ifndef SRC_DH_GEX_H_ #define SRC_DH_GEX_H_ +#ifdef __cplusplus +extern "C" { +#endif + int ssh_client_dhgex_init(ssh_session session); +void ssh_client_dhgex_remove_callbacks(ssh_session session); #ifdef WITH_SERVER void ssh_server_dhgex_init(ssh_session session); #endif /* WITH_SERVER */ +#ifdef __cplusplus +} +#endif + #endif /* SRC_DH_GEX_H_ */ diff --git a/libssh/include/libssh/dh.h b/libssh/include/libssh/dh.h index 353dc233..34c4a7ed 100644 --- a/libssh/include/libssh/dh.h +++ b/libssh/include/libssh/dh.h @@ -30,6 +30,10 @@ struct dh_ctx; #define DH_CLIENT_KEYPAIR 0 #define DH_SERVER_KEYPAIR 1 +#ifdef __cplusplus +extern "C" { +#endif + /* functions implemented by crypto backends */ int ssh_dh_init_common(struct ssh_crypto_struct *crypto); void ssh_dh_cleanup(struct ssh_crypto_struct *crypto); @@ -53,7 +57,7 @@ int ssh_dh_keypair_get_keys(struct dh_ctx *ctx, int peer, bignum *priv, bignum *pub); #endif /* OPENSSL_VERSION_NUMBER */ int ssh_dh_keypair_set_keys(struct dh_ctx *ctx, int peer, - const bignum priv, const bignum pub); + bignum priv, bignum pub); int ssh_dh_compute_shared_secret(struct dh_ctx *ctx, int local, int remote, bignum *dest); @@ -73,8 +77,10 @@ int ssh_dh_get_current_server_publickey_blob(ssh_session session, ssh_key ssh_dh_get_next_server_publickey(ssh_session session); int ssh_dh_get_next_server_publickey_blob(ssh_session session, ssh_string *pubkey_blob); +int dh_handshake(ssh_session session); int ssh_client_dh_init(ssh_session session); +void ssh_client_dh_remove_callbacks(ssh_session session); #ifdef WITH_SERVER void ssh_server_dh_init(ssh_session session); #endif /* WITH_SERVER */ @@ -82,4 +88,8 @@ int ssh_server_dh_process_init(ssh_session session, ssh_buffer packet); int ssh_fallback_group(uint32_t pmax, bignum *p, bignum *g); bool ssh_dh_is_known_group(bignum modulus, bignum generator); +#ifdef __cplusplus +} +#endif + #endif /* DH_H_ */ diff --git a/libssh/include/libssh/ecdh.h b/libssh/include/libssh/ecdh.h index 17fe02e7..4c4c54eb 100644 --- a/libssh/include/libssh/ecdh.h +++ b/libssh/include/libssh/ecdh.h @@ -42,9 +42,14 @@ #define HAVE_ECDH 1 #endif +#ifdef __cplusplus +extern "C" { +#endif + extern struct ssh_packet_callbacks_struct ssh_ecdh_client_callbacks; /* Backend-specific functions. */ int ssh_client_ecdh_init(ssh_session session); +void ssh_client_ecdh_remove_callbacks(ssh_session session); int ecdh_build_k(ssh_session session); #ifdef WITH_SERVER @@ -53,4 +58,8 @@ void ssh_server_ecdh_init(ssh_session session); SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init); #endif /* WITH_SERVER */ +#ifdef __cplusplus +} +#endif + #endif /* ECDH_H_ */ diff --git a/libssh/include/libssh/ed25519.h b/libssh/include/libssh/ed25519.h index 8a3263c8..72a86c0b 100644 --- a/libssh/include/libssh/ed25519.h +++ b/libssh/include/libssh/ed25519.h @@ -24,10 +24,10 @@ /** * @defgroup ed25519 ed25519 API - * @internal * @brief API for DJB's ed25519 * - * @{ */ + * @{ + */ #define ED25519_PK_LEN 32 #define ED25519_SK_LEN 64 @@ -37,6 +37,10 @@ typedef uint8_t ed25519_pubkey[ED25519_PK_LEN]; typedef uint8_t ed25519_privkey[ED25519_SK_LEN]; typedef uint8_t ed25519_signature[ED25519_SIG_LEN]; +#ifdef __cplusplus +extern "C" { +#endif + /** @internal * @brief generate an ed25519 key pair * @param[out] pk generated public key @@ -76,4 +80,8 @@ int crypto_sign_ed25519_open( const ed25519_pubkey pk); /** @} */ +#ifdef __cplusplus +} +#endif + #endif /* ED25519_H_ */ diff --git a/libssh/include/libssh/fe25519.h b/libssh/include/libssh/fe25519.h index 438d85db..0dfb0613 100644 --- a/libssh/include/libssh/fe25519.h +++ b/libssh/include/libssh/fe25519.h @@ -33,6 +33,10 @@ typedef struct { uint32_t v[32]; } fe25519; +#ifdef __cplusplus +extern "C" { +#endif + void fe25519_freeze(fe25519 *r); void fe25519_unpack(fe25519 *r, const unsigned char x[32]); @@ -65,4 +69,8 @@ void fe25519_invert(fe25519 *r, const fe25519 *x); void fe25519_pow2523(fe25519 *r, const fe25519 *x); +#ifdef __cplusplus +} +#endif + #endif diff --git a/libssh/include/libssh/ge25519.h b/libssh/include/libssh/ge25519.h index 329bd042..480f29dc 100644 --- a/libssh/include/libssh/ge25519.h +++ b/libssh/include/libssh/ge25519.h @@ -28,6 +28,10 @@ typedef struct fe25519 t; } ge25519; +#ifdef __cplusplus +extern "C" { +#endif + extern const ge25519 ge25519_base; int ge25519_unpackneg_vartime(ge25519 *r, const unsigned char p[32]); @@ -40,4 +44,8 @@ void ge25519_double_scalarmult_vartime(ge25519 *r, const ge25519 *p1, const sc25 void ge25519_scalarmult_base(ge25519 *r, const sc25519 *s); +#ifdef __cplusplus +} +#endif + #endif diff --git a/libssh/include/libssh/gssapi.h b/libssh/include/libssh/gssapi.h index ccd83664..b0c74c73 100644 --- a/libssh/include/libssh/gssapi.h +++ b/libssh/include/libssh/gssapi.h @@ -29,6 +29,10 @@ typedef struct ssh_gssapi_struct *ssh_gssapi; +#ifdef __cplusplus +extern "C" { +#endif + #ifdef WITH_SERVER int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n_oid, ssh_string *oids); SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server); @@ -42,4 +46,8 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_response); int ssh_gssapi_auth_mic(ssh_session session); +#ifdef __cplusplus +} +#endif + #endif /* GSSAPI_H */ diff --git a/libssh/include/libssh/kex.h b/libssh/include/libssh/kex.h index 3a1f4a6f..ede7fa8a 100644 --- a/libssh/include/libssh/kex.h +++ b/libssh/include/libssh/kex.h @@ -31,9 +31,13 @@ struct ssh_kex_struct { char *methods[SSH_KEX_METHODS]; }; +#ifdef __cplusplus +extern "C" { +#endif + SSH_PACKET_CALLBACK(ssh_packet_kexinit); -int ssh_send_kex(ssh_session session, int server_kex); +int ssh_send_kex(ssh_session session); void ssh_list_kex(struct ssh_kex_struct *kex); int ssh_set_client_kex(ssh_session session); int ssh_kex_select_methods(ssh_session session); @@ -56,4 +60,8 @@ int ssh_hashbufin_add_cookie(ssh_session session, unsigned char *cookie); int ssh_hashbufout_add_cookie(ssh_session session); int ssh_generate_session_keys(ssh_session session); +#ifdef __cplusplus +} +#endif + #endif /* KEX_H_ */ diff --git a/libssh/include/libssh/keys.h b/libssh/include/libssh/keys.h index 934189c2..615f1eae 100644 --- a/libssh/include/libssh/keys.h +++ b/libssh/include/libssh/keys.h @@ -62,9 +62,17 @@ struct ssh_private_key_struct { #endif }; +#ifdef __cplusplus +extern "C" { +#endif + const char *ssh_type_to_char(int type); int ssh_type_from_name(const char *name); ssh_public_key publickey_from_string(ssh_session session, ssh_string pubkey_s); +#ifdef __cplusplus +} +#endif + #endif /* KEYS_H_ */ diff --git a/libssh/include/libssh/knownhosts.h b/libssh/include/libssh/knownhosts.h index 44e434c0..b50018cd 100644 --- a/libssh/include/libssh/knownhosts.h +++ b/libssh/include/libssh/knownhosts.h @@ -22,6 +22,10 @@ #ifndef SSH_KNOWNHOSTS_H_ #define SSH_KNOWNHOSTS_H_ +#ifdef __cplusplus +extern "C" { +#endif + struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session); char *ssh_known_hosts_get_algorithms_names(ssh_session session); enum ssh_known_hosts_e @@ -29,4 +33,8 @@ ssh_session_get_known_hosts_entry_file(ssh_session session, const char *filename, struct ssh_knownhosts_entry **pentry); +#ifdef __cplusplus +} +#endif + #endif /* SSH_KNOWNHOSTS_H_ */ diff --git a/libssh/include/libssh/legacy.h b/libssh/include/libssh/legacy.h index c0b50e24..38bef4da 100644 --- a/libssh/include/libssh/legacy.h +++ b/libssh/include/libssh/legacy.h @@ -31,6 +31,10 @@ typedef struct ssh_private_key_struct* ssh_private_key; typedef struct ssh_public_key_struct* ssh_public_key; +#ifdef __cplusplus +extern "C" { +#endif + LIBSSH_API int ssh_auth_list(ssh_session session); LIBSSH_API int ssh_userauth_offer_pubkey(ssh_session session, const char *username, int type, ssh_string publickey); LIBSSH_API int ssh_userauth_pubkey(ssh_session session, const char *username, ssh_string publickey, ssh_private_key privatekey); @@ -117,4 +121,8 @@ SSH_DEPRECATED LIBSSH_API size_t string_len(ssh_string str); SSH_DEPRECATED LIBSSH_API ssh_string string_new(size_t size); SSH_DEPRECATED LIBSSH_API char *string_to_char(ssh_string str); +#ifdef __cplusplus +} +#endif + #endif /* LEGACY_H_ */ diff --git a/libssh/include/libssh/libgcrypt.h b/libssh/include/libssh/libgcrypt.h index 347d851b..e4087fd2 100644 --- a/libssh/include/libssh/libgcrypt.h +++ b/libssh/include/libssh/libgcrypt.h @@ -104,6 +104,10 @@ int ssh_gcry_rand_range(bignum rnd, bignum max); } while(0) /* Helper functions for data conversions. */ +#ifdef __cplusplus +extern "C" { +#endif + /* Extract an MPI from the given s-expression SEXP named NAME which is encoded using INFORMAT and store it in a newly allocated ssh_string encoded using OUTFORMAT. */ @@ -114,6 +118,10 @@ ssh_string ssh_sexp_extract_mpi(const gcry_sexp_t sexp, #define ssh_fips_mode() false +#ifdef __cplusplus +} +#endif + #endif /* HAVE_LIBGCRYPT */ #endif /* LIBGCRYPT_H_ */ diff --git a/libssh/include/libssh/libmbedcrypto.h b/libssh/include/libssh/libmbedcrypto.h index fe53019b..e6fc393c 100644 --- a/libssh/include/libssh/libmbedcrypto.h +++ b/libssh/include/libssh/libmbedcrypto.h @@ -73,6 +73,10 @@ struct mbedtls_ecdsa_sig { bignum s; }; +#ifdef __cplusplus +extern "C" { +#endif + bignum ssh_mbedcry_bn_new(void); void ssh_mbedcry_bn_free(bignum num); unsigned char *ssh_mbedcry_bn2num(const_bignum num, int radix); @@ -136,5 +140,9 @@ ssh_string make_ecpoint_string(const mbedtls_ecp_group *g, const #define ssh_fips_mode() false +#ifdef __cplusplus +} +#endif + #endif /* HAVE_LIBMBEDCRYPTO */ #endif /* LIBMBEDCRYPTO_H_ */ diff --git a/libssh/include/libssh/libssh.h b/libssh/include/libssh/libssh.h index 7857a77b..669a0a96 100644 --- a/libssh/include/libssh/libssh.h +++ b/libssh/include/libssh/libssh.h @@ -1,7 +1,7 @@ /* * This file is part of the SSH Library * - * Copyright (c) 2003-2022 by Aris Adamantiadis and the libssh team + * Copyright (c) 2003-2023 by Aris Adamantiadis and the libssh team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -82,7 +82,7 @@ #define PRINTF_ATTRIBUTE(a,b) #endif /* __GNUC__ */ -#ifdef __GNUC__ +#if !defined(SSH_SUPPRESS_DEPRECATED) && defined(__GNUC__) #define SSH_DEPRECATED __attribute__ ((deprecated)) #else #define SSH_DEPRECATED @@ -357,7 +357,7 @@ enum { #define SSH_LOG_WARN 1 /** Get some information what's going on */ #define SSH_LOG_INFO 2 -/** Get detailed debuging information **/ +/** Get detailed debugging information **/ #define SSH_LOG_DEBUG 3 /** Get trace output, packet information, ... */ #define SSH_LOG_TRACE 4 diff --git a/libssh/include/libssh/messages.h b/libssh/include/libssh/messages.h index 1341d708..160306cc 100644 --- a/libssh/include/libssh/messages.h +++ b/libssh/include/libssh/messages.h @@ -92,6 +92,10 @@ struct ssh_message_struct { struct ssh_global_request global_request; }; +#ifdef __cplusplus +extern "C" { +#endif + SSH_PACKET_CALLBACK(ssh_packet_channel_open); SSH_PACKET_CALLBACK(ssh_packet_global_request); @@ -104,4 +108,8 @@ int ssh_message_handle_channel_request(ssh_session session, ssh_channel channel, const char *request, uint8_t want_reply); ssh_message ssh_message_pop_head(ssh_session session); +#ifdef __cplusplus +} +#endif + #endif /* MESSAGES_H_ */ diff --git a/libssh/include/libssh/misc.h b/libssh/include/libssh/misc.h index 569e2b7d..924da533 100644 --- a/libssh/include/libssh/misc.h +++ b/libssh/include/libssh/misc.h @@ -21,6 +21,10 @@ #ifndef MISC_H_ #define MISC_H_ +#ifdef __cplusplus +extern "C" { +#endif + /* in misc.c */ /* gets the user home dir. */ char *ssh_get_user_home_dir(void); @@ -75,7 +79,7 @@ const void *_ssh_list_pop_head(struct ssh_list *list); /** @brief fetch the head element of a list and remove it from list * @param type type of the element to return - * @param list the ssh_list to use + * @param ssh_list the ssh_list to use * @return the first element of the list, or NULL if the list is empty */ #define ssh_list_pop_head(type, ssh_list)\ @@ -96,7 +100,11 @@ int ssh_mkdirs(const char *pathname, mode_t mode); int ssh_quote_file_name(const char *file_name, char *buf, size_t buf_len); int ssh_newline_vis(const char *string, char *buf, size_t buf_len); -int ssh_tmpname(char *template); +int ssh_tmpname(char *name); char *ssh_strreplace(const char *src, const char *pattern, const char *repl); +#ifdef __cplusplus +} +#endif + #endif /* MISC_H_ */ diff --git a/libssh/include/libssh/options.h b/libssh/include/libssh/options.h index e8dc6c69..35b3ffba 100644 --- a/libssh/include/libssh/options.h +++ b/libssh/include/libssh/options.h @@ -21,6 +21,10 @@ #ifndef _OPTIONS_H #define _OPTIONS_H +#ifdef __cplusplus +extern "C" { +#endif + int ssh_config_parse_file(ssh_session session, const char *filename); int ssh_config_parse_string(ssh_session session, const char *input); int ssh_options_set_algo(ssh_session session, @@ -28,4 +32,8 @@ int ssh_options_set_algo(ssh_session session, const char *list); int ssh_options_apply(ssh_session session); +#ifdef __cplusplus +} +#endif + #endif /* _OPTIONS_H */ diff --git a/libssh/include/libssh/packet.h b/libssh/include/libssh/packet.h index dec3a439..7f10a709 100644 --- a/libssh/include/libssh/packet.h +++ b/libssh/include/libssh/packet.h @@ -51,6 +51,10 @@ enum ssh_packet_filter_result_e { int ssh_packet_send(ssh_session session); +#ifdef __cplusplus +extern "C" { +#endif + SSH_PACKET_CALLBACK(ssh_packet_unimplemented); SSH_PACKET_CALLBACK(ssh_packet_disconnect_callback); SSH_PACKET_CALLBACK(ssh_packet_ignore_callback); @@ -88,4 +92,8 @@ int ssh_packet_set_newkeys(ssh_session session, struct ssh_crypto_struct *ssh_packet_get_current_crypto(ssh_session session, enum ssh_crypto_direction_e direction); +#ifdef __cplusplus +} +#endif + #endif /* PACKET_H_ */ diff --git a/libssh/include/libssh/pcap.h b/libssh/include/libssh/pcap.h index 2e43ae87..2a6c3c27 100644 --- a/libssh/include/libssh/pcap.h +++ b/libssh/include/libssh/pcap.h @@ -27,6 +27,10 @@ #ifdef WITH_PCAP typedef struct ssh_pcap_context_struct* ssh_pcap_context; +#ifdef __cplusplus +extern "C" { +#endif + int ssh_pcap_file_write_packet(ssh_pcap_file pcap, ssh_buffer packet, uint32_t original_len); ssh_pcap_context ssh_pcap_context_new(ssh_session session); @@ -41,5 +45,9 @@ int ssh_pcap_context_write(ssh_pcap_context,enum ssh_pcap_direction direction, v uint32_t len, uint32_t origlen); +#ifdef __cplusplus +} +#endif + #endif /* WITH_PCAP */ #endif /* PCAP_H_ */ diff --git a/libssh/include/libssh/pki.h b/libssh/include/libssh/pki.h index 1d5250ff..879a1d5c 100644 --- a/libssh/include/libssh/pki.h +++ b/libssh/include/libssh/pki.h @@ -34,7 +34,7 @@ #endif #include "libssh/crypto.h" #if defined(HAVE_LIBCRYPTO) && defined(HAVE_OPENSSL_ED25519) -/* If using OpenSSL implementation, define the signature lenght which would be +/* If using OpenSSL implementation, define the signature length which would be * defined in libssh/ed25519.h otherwise */ #define ED25519_SIG_LEN 64 #else @@ -118,6 +118,10 @@ struct ssh_signature_struct { typedef struct ssh_signature_struct *ssh_signature; +#ifdef __cplusplus +extern "C" { +#endif + /* SSH Key Functions */ void ssh_key_clean (ssh_key key); @@ -189,7 +193,13 @@ bool ssh_key_size_allowed(ssh_session session, ssh_key key); int ssh_key_size(ssh_key key); /* PKCS11 URI function to check if filename is a path or a PKCS11 URI */ +#ifdef WITH_PKCS11_URI bool ssh_pki_is_uri(const char *filename); char *ssh_pki_export_pub_uri_from_priv_uri(const char *priv_uri); +#endif /* WITH_PKCS11_URI */ + +#ifdef __cplusplus +} +#endif #endif /* PKI_H_ */ diff --git a/libssh/include/libssh/pki_priv.h b/libssh/include/libssh/pki_priv.h index c0edb851..d0e1ef44 100644 --- a/libssh/include/libssh/pki_priv.h +++ b/libssh/include/libssh/pki_priv.h @@ -23,6 +23,10 @@ #include "libssh/pki.h" +#ifdef __cplusplus +extern "C" { +#endif + /* defined in bcrypt_pbkdf.c */ int bcrypt_pbkdf(const char *pass, size_t passlen, @@ -149,7 +153,7 @@ int pki_ed25519_verify(const ssh_key pubkey, ssh_signature sig, int pki_ed25519_key_cmp(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what); -int pki_ed25519_key_dup(ssh_key new, const ssh_key key); +int pki_ed25519_key_dup(ssh_key new_key, const ssh_key key); int pki_ed25519_public_key_to_blob(ssh_buffer buffer, ssh_key key); ssh_string pki_ed25519_signature_to_blob(ssh_signature sig); int pki_signature_from_ed25519_blob(ssh_signature sig, ssh_string sig_blob); @@ -164,8 +168,14 @@ ssh_key ssh_pki_openssh_privkey_import(const char *text_key, ssh_string ssh_pki_openssh_privkey_export(const ssh_key privkey, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data); +#ifdef WITH_PKCS11_URI /* URI Function */ int pki_uri_import(const char *uri_name, ssh_key *key, enum ssh_key_e key_type); +#endif /* WITH_PKCS11_URI */ bool ssh_key_size_allowed_rsa(int min_size, ssh_key key); +#ifdef __cplusplus +} +#endif + #endif /* PKI_PRIV_H_ */ diff --git a/libssh/include/libssh/poll.h b/libssh/include/libssh/poll.h index 3aa9a49b..8e30676e 100644 --- a/libssh/include/libssh/poll.h +++ b/libssh/include/libssh/poll.h @@ -114,6 +114,10 @@ typedef unsigned long int nfds_t; #endif /* WIN32 */ #endif /* HAVE_POLL */ +#ifdef __cplusplus +extern "C" { +#endif + void ssh_poll_init(void); void ssh_poll_cleanup(void); int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout); @@ -158,4 +162,8 @@ ssh_poll_ctx ssh_poll_get_default_ctx(ssh_session session); int ssh_event_add_poll(ssh_event event, ssh_poll_handle p); void ssh_event_remove_poll(ssh_event event, ssh_poll_handle p); +#ifdef __cplusplus +} +#endif + #endif /* POLL_H_ */ diff --git a/libssh/include/libssh/poly1305.h b/libssh/include/libssh/poly1305.h index 513f1b99..a22fea87 100644 --- a/libssh/include/libssh/poly1305.h +++ b/libssh/include/libssh/poly1305.h @@ -7,6 +7,10 @@ #define POLY1305_H #include "libssh/chacha20-poly1305-common.h" +#ifdef __cplusplus +extern "C" { +#endif + void poly1305_auth(uint8_t out[POLY1305_TAGLEN], const uint8_t *m, size_t inlen, const uint8_t key[POLY1305_KEYLEN]) #ifdef HAVE_GCC_BOUNDED_ATTRIBUTE @@ -16,4 +20,8 @@ void poly1305_auth(uint8_t out[POLY1305_TAGLEN], const uint8_t *m, size_t inlen, #endif ; +#ifdef __cplusplus +} +#endif + #endif /* POLY1305_H */ diff --git a/libssh/include/libssh/priv.h b/libssh/include/libssh/priv.h index bab761b0..47af57f4 100644 --- a/libssh/include/libssh/priv.h +++ b/libssh/include/libssh/priv.h @@ -47,6 +47,10 @@ # endif #endif /* !defined(HAVE_STRTOULL) */ +#ifdef __cplusplus +extern "C" { +#endif + #if !defined(HAVE_STRNDUP) char *strndup(const char *s, size_t n); #endif /* ! HAVE_STRNDUP */ @@ -434,4 +438,8 @@ bool is_ssh_initialized(void); #define SSH_ERRNO_MSG_MAX 1024 char *ssh_strerror(int err_num, char *buf, size_t buflen); +#ifdef __cplusplus +} +#endif + #endif /* _LIBSSH_PRIV_H */ diff --git a/libssh/include/libssh/sc25519.h b/libssh/include/libssh/sc25519.h index 5a2c1b85..43b09a05 100644 --- a/libssh/include/libssh/sc25519.h +++ b/libssh/include/libssh/sc25519.h @@ -35,6 +35,10 @@ typedef struct { uint32_t v[16]; } shortsc25519; +#ifdef __cplusplus +extern "C" { +#endif + void sc25519_from32bytes(sc25519 *r, const unsigned char x[32]); void shortsc25519_from16bytes(shortsc25519 *r, const unsigned char x[16]); @@ -71,4 +75,8 @@ void sc25519_window5(signed char r[51], const sc25519 *s); void sc25519_2interleave2(unsigned char r[127], const sc25519 *s1, const sc25519 *s2); +#ifdef __cplusplus +} +#endif + #endif diff --git a/libssh/include/libssh/scp.h b/libssh/include/libssh/scp.h index d356d89b..089fcfc9 100644 --- a/libssh/include/libssh/scp.h +++ b/libssh/include/libssh/scp.h @@ -47,9 +47,17 @@ struct ssh_scp_struct { int request_mode; }; +#ifdef __cplusplus +extern "C" { +#endif + int ssh_scp_read_string(ssh_scp scp, char *buffer, size_t len); int ssh_scp_integer_mode(const char *mode); char *ssh_scp_string_mode(int mode); int ssh_scp_response(ssh_scp scp, char **response); +#ifdef __cplusplus +} +#endif + #endif diff --git a/libssh/include/libssh/server.h b/libssh/include/libssh/server.h index c1a9c15c..80f74e1a 100644 --- a/libssh/include/libssh/server.h +++ b/libssh/include/libssh/server.h @@ -117,7 +117,7 @@ LIBSSH_API int ssh_bind_listen(ssh_bind ssh_bind_o); * * @param[in] userdata A pointer to private data to pass to the callbacks. * - * @return SSH_OK on success, SSH_ERROR if an error occured. + * @return SSH_OK on success, SSH_ERROR if an error occurred. * * @code * struct ssh_callbacks_struct cb = { @@ -280,7 +280,7 @@ LIBSSH_API int ssh_message_reply_default(ssh_message msg); * * @param[in] msg The message to get the username from. * - * @return The username or NULL if an error occured. + * @return The username or NULL if an error occurred. * * @see ssh_message_get() * @see ssh_message_type() @@ -292,11 +292,11 @@ LIBSSH_API const char *ssh_message_auth_user(ssh_message msg); * * @param[in] msg The message to get the password from. * - * @return The username or NULL if an error occured. + * @return The username or NULL if an error occurred. * * @see ssh_message_get() * @see ssh_message_type() - * @warning This function should not be used anymore as there is a + * @deprecated This function should not be used anymore as there is a * callback based server implementation now auth_password_function. */ SSH_DEPRECATED LIBSSH_API const char *ssh_message_auth_password(ssh_message msg); @@ -314,14 +314,19 @@ SSH_DEPRECATED LIBSSH_API const char *ssh_message_auth_password(ssh_message msg) * @see ssh_key_cmp() * @see ssh_message_get() * @see ssh_message_type() - * @warning This function should not be used anymore as there is a + * @deprecated This function should not be used anymore as there is a * callback based server implementation auth_pubkey_function. */ SSH_DEPRECATED LIBSSH_API ssh_key ssh_message_auth_pubkey(ssh_message msg); LIBSSH_API int ssh_message_auth_kbdint_is_response(ssh_message msg); -/* Replaced by callback based server implementation auth_pubkey_function */ +/** + * @param[in] msg The message to get the public key state from. + * + * @deprecated This function should not be used anymore as there is a + * callback based server implementation auth_pubkey_function + */ SSH_DEPRECATED LIBSSH_API enum ssh_publickey_state_e ssh_message_auth_publickey_state(ssh_message msg); LIBSSH_API int ssh_message_auth_reply_success(ssh_message msg,int partial); diff --git a/libssh/include/libssh/session.h b/libssh/include/libssh/session.h index d3e5787c..eb14e97a 100644 --- a/libssh/include/libssh/session.h +++ b/libssh/include/libssh/session.h @@ -76,6 +76,11 @@ enum ssh_pending_call_e { /* Client successfully authenticated */ #define SSH_SESSION_FLAG_AUTHENTICATED 2 +/* The KEXINIT message can be sent first by either of the parties so this flag + * indicates that the message was already sent to make sure it is sent and avoid + * sending it twice during key exchange to simplify the state machine. */ +#define SSH_SESSION_FLAG_KEXINIT_SENT 4 + /* codes to use with ssh_handle_packets*() */ /* Infinite timeout */ #define SSH_TIMEOUT_INFINITE -1 @@ -93,6 +98,12 @@ enum ssh_pending_call_e { #define SSH_OPT_FLAG_KBDINT_AUTH 0x4 #define SSH_OPT_FLAG_GSSAPI_AUTH 0x8 +/* Escape expansion of different variables */ +#define SSH_OPT_EXP_FLAG_KNOWNHOSTS 0x1 +#define SSH_OPT_EXP_FLAG_GLOBAL_KNOWNHOSTS 0x2 +#define SSH_OPT_EXP_FLAG_PROXYCOMMAND 0x4 +#define SSH_OPT_EXP_FLAG_IDENTITY 0x8 + /* extensions flags */ /* negotiation enabled */ #define SSH_EXT_NEGOTIATION 0x01 @@ -132,10 +143,8 @@ struct ssh_session_struct { /* Extensions negotiated using RFC 8308 */ uint32_t extensions; - ssh_string banner; /* that's the issue banner from - the server */ - char *discon_msg; /* disconnect message from - the remote host */ + ssh_string banner; /* that's the issue banner from the server */ + char *peer_discon_msg; /* disconnect message from the remote host */ char *disconnect_message; /* disconnect message to be set */ ssh_buffer in_buffer; PACKET in_packet; @@ -160,25 +169,33 @@ struct ssh_session_struct { uint32_t current_method; } auth; + /* Sending this flag before key exchange to save one round trip during the + * key exchange. This might make sense on high-latency connections. + * So far internal only for testing. Usable only on the client side -- + * there is no key exchange method that would start with server message */ + bool send_first_kex_follows; /* * RFC 4253, 7.1: if the first_kex_packet_follows flag was set in * the received SSH_MSG_KEXINIT, but the guess was wrong, this * field will be set such that the following guessed packet will - * be ignored. Once that packet has been received and ignored, - * this field is cleared. + * be ignored on the receiving side. Once that packet has been received and + * ignored, this field is cleared. + * On the sending side, this is set after we got peer KEXINIT message and we + * need to resend the initial message of the negotiated KEX algorithm. */ - int first_kex_follows_guess_wrong; + bool first_kex_follows_guess_wrong; ssh_buffer in_hashbuf; ssh_buffer out_hashbuf; struct ssh_crypto_struct *current_crypto; - struct ssh_crypto_struct *next_crypto; /* next_crypto is going to be used after a SSH2_MSG_NEWKEYS */ + /* next_crypto is going to be used after a SSH2_MSG_NEWKEYS */ + struct ssh_crypto_struct *next_crypto; struct ssh_list *channels; /* linked list of channels */ uint32_t maxchannel; ssh_agent agent; /* ssh agent */ -/* keyb interactive data */ + /* keyboard interactive data */ struct ssh_kbdint_struct *kbdint; struct ssh_gssapi_struct *gssapi; @@ -195,7 +212,8 @@ struct ssh_session_struct { /* auths accepted by server */ struct ssh_list *ssh_message_list; /* list of delayed SSH messages */ - int (*ssh_message_callback)( struct ssh_session_struct *session, ssh_message msg, void *userdata); + int (*ssh_message_callback)(struct ssh_session_struct *session, + ssh_message msg, void *userdata); void *ssh_message_callback_data; ssh_server_callbacks server_callbacks; void (*ssh_connection_callback)( struct ssh_session_struct *session); @@ -209,6 +227,7 @@ struct ssh_session_struct { #endif struct { struct ssh_list *identity; + struct ssh_list *identity_non_exp; char *username; char *host; char *bindaddr; /* bind the client to an ip addr */ @@ -231,6 +250,7 @@ struct ssh_session_struct { char *gss_client_identity; int gss_delegate_creds; int flags; + int exp_flags; int nodelay; bool config_processed; uint8_t options_seen[SOC_MAX]; diff --git a/libssh/include/libssh/sftp.h b/libssh/include/libssh/sftp.h index c855df8a..c713466e 100644 --- a/libssh/include/libssh/sftp.h +++ b/libssh/include/libssh/sftp.h @@ -681,6 +681,11 @@ LIBSSH_API int sftp_rename(sftp_session sftp, const char *original, const char /** * @brief Set file attributes on a file, directory or symbolic link. * + * Note, that this function can only set time values using 32 bit values due to + * the restrictions in the SFTP protocol version 3 implemented by libssh. + * The support for 64 bit time values was introduced in SFTP version 5, which is + * not implemented by libssh nor any major SFTP servers. + * * @param sftp The sftp session handle. * * @param file The file which attributes should be changed. @@ -767,6 +772,8 @@ LIBSSH_API int sftp_symlink(sftp_session sftp, const char *target, const char *d * @param path Specifies the path name of the symlink to be read. * * @return The target of the link, NULL on error. + * The caller needs to free the memory + * using ssh_string_free_char(). * * @see sftp_get_error() */ diff --git a/libssh/include/libssh/sftp_priv.h b/libssh/include/libssh/sftp_priv.h index ccde008a..005bf85f 100644 --- a/libssh/include/libssh/sftp_priv.h +++ b/libssh/include/libssh/sftp_priv.h @@ -21,6 +21,10 @@ #ifndef SFTP_PRIV_H #define SFTP_PRIV_H +#ifdef __cplusplus +extern "C" { +#endif + sftp_packet sftp_packet_read(sftp_session sftp); int sftp_packet_write(sftp_session sftp, uint8_t type, ssh_buffer payload); void sftp_packet_free(sftp_packet packet); @@ -29,4 +33,8 @@ sftp_attributes sftp_parse_attr(sftp_session session, ssh_buffer buf, int expectname); +#ifdef __cplusplus +} +#endif + #endif /* SFTP_PRIV_H */ diff --git a/libssh/include/libssh/socket.h b/libssh/include/libssh/socket.h index ae56f5f6..cdd3c837 100644 --- a/libssh/include/libssh/socket.h +++ b/libssh/include/libssh/socket.h @@ -35,6 +35,7 @@ void ssh_socket_reset(ssh_socket s); void ssh_socket_free(ssh_socket s); void ssh_socket_set_fd(ssh_socket s, socket_t fd); socket_t ssh_socket_get_fd(ssh_socket s); +void ssh_socket_set_connected(ssh_socket s, struct ssh_poll_handle_struct *p); int ssh_socket_unix(ssh_socket s, const char *path); void ssh_execute_command(const char *command, socket_t in, socket_t out); #ifndef _WIN32 diff --git a/libssh/include/libssh/string.h b/libssh/include/libssh/string.h index 8c7db1df..35b2ea2e 100644 --- a/libssh/include/libssh/string.h +++ b/libssh/include/libssh/string.h @@ -22,6 +22,10 @@ #define STRING_H_ #include "libssh/priv.h" +#ifdef __cplusplus +extern "C" { +#endif + /* must be 32 bits number + immediately our data */ #ifdef _MSC_VER #pragma pack(1) @@ -38,4 +42,8 @@ __attribute__ ((packed)) #endif ; +#ifdef __cplusplus +} +#endif + #endif /* STRING_H_ */ diff --git a/libssh/include/libssh/threads.h b/libssh/include/libssh/threads.h index 522f91d5..47340d17 100644 --- a/libssh/include/libssh/threads.h +++ b/libssh/include/libssh/threads.h @@ -49,6 +49,10 @@ #endif +#ifdef __cplusplus +extern "C" { +#endif + int ssh_threads_init(void); void ssh_threads_finalize(void); const char *ssh_threads_get_type(void); @@ -60,4 +64,8 @@ struct ssh_threads_callbacks_struct *ssh_threads_get_default(void); int crypto_thread_init(struct ssh_threads_callbacks_struct *user_callbacks); void crypto_thread_finalize(void); +#ifdef __cplusplus +} +#endif + #endif /* THREADS_H_ */ diff --git a/libssh/include/libssh/token.h b/libssh/include/libssh/token.h index 9896fb06..2cd7b20f 100644 --- a/libssh/include/libssh/token.h +++ b/libssh/include/libssh/token.h @@ -31,6 +31,10 @@ struct ssh_tokens_st { char **tokens; }; +#ifdef __cplusplus +extern "C" { +#endif + struct ssh_tokens_st *ssh_tokenize(const char *chain, char separator); void ssh_tokens_free(struct ssh_tokens_st *tokens); @@ -45,4 +49,8 @@ char *ssh_remove_duplicates(const char *list); char *ssh_append_without_duplicates(const char *list, const char *appended_list); +#ifdef __cplusplus +} +#endif + #endif /* TOKEN_H_ */ diff --git a/libssh/include/libssh/wrapper.h b/libssh/include/libssh/wrapper.h index f4a33d2d..36589cff 100644 --- a/libssh/include/libssh/wrapper.h +++ b/libssh/include/libssh/wrapper.h @@ -29,6 +29,10 @@ #include "libssh/libgcrypt.h" #include "libssh/libmbedcrypto.h" +#ifdef __cplusplus +extern "C" { +#endif + enum ssh_kdf_digest { SSH_KDF_SHA1=1, SSH_KDF_SHA256, @@ -122,9 +126,13 @@ const char *ssh_hmac_type_to_string(enum ssh_hmac_e hmac_type, bool etm); #if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L int evp_build_pkey(const char* name, OSSL_PARAM_BLD *param_bld, EVP_PKEY **pkey, int selection); -int evp_dup_dsa_pkey(const ssh_key key, ssh_key new, int demote); -int evp_dup_rsa_pkey(const ssh_key key, ssh_key new, int demote); -int evp_dup_ecdsa_pkey(const ssh_key key, ssh_key new, int demote); +int evp_dup_dsa_pkey(const ssh_key key, ssh_key new_key, int demote); +int evp_dup_rsa_pkey(const ssh_key key, ssh_key new_key, int demote); +int evp_dup_ecdsa_pkey(const ssh_key key, ssh_key new_key, int demote); #endif /* HAVE_LIBCRYPTO && OPENSSL_VERSION_NUMBER */ +#ifdef __cplusplus +} +#endif + #endif /* WRAPPER_H_ */ diff --git a/libssh/libssh.pc.cmake b/libssh/libssh.pc.cmake index b37cb3fc..f288b94d 100644 --- a/libssh/libssh.pc.cmake +++ b/libssh/libssh.pc.cmake @@ -1,6 +1,10 @@ -Name: ${PROJECT_NAME} -Description: The SSH Library -Version: ${PROJECT_VERSION} -Libs: -L${CMAKE_INSTALL_FULL_LIBDIR} -lssh -Cflags: -I${CMAKE_INSTALL_FULL_INCLUDEDIR} +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=@CMAKE_INSTALL_FULL_LIBDIR@ +includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ +Name: @PROJECT_NAME@ +Description: The SSH Library +Version: @PROJECT_VERSION@ +Libs: -L${libdir} -lssh +Cflags: -I${includedir} diff --git a/libssh/src/ABI/current b/libssh/src/ABI/current index f4cfd30c..efd4ffca 100644 --- a/libssh/src/ABI/current +++ b/libssh/src/ABI/current @@ -1 +1 @@ -4.9.4 \ No newline at end of file +4.9.5 \ No newline at end of file diff --git a/libssh/src/ABI/libssh-4.9.5.symbols b/libssh/src/ABI/libssh-4.9.5.symbols new file mode 100644 index 00000000..a26e2c5e --- /dev/null +++ b/libssh/src/ABI/libssh-4.9.5.symbols @@ -0,0 +1,427 @@ +_ssh_log +buffer_free +buffer_get +buffer_get_len +buffer_new +channel_accept_x11 +channel_change_pty_size +channel_close +channel_forward_accept +channel_forward_cancel +channel_forward_listen +channel_free +channel_get_exit_status +channel_get_session +channel_is_closed +channel_is_eof +channel_is_open +channel_new +channel_open_forward +channel_open_session +channel_poll +channel_read +channel_read_buffer +channel_read_nonblocking +channel_request_env +channel_request_exec +channel_request_pty +channel_request_pty_size +channel_request_send_signal +channel_request_sftp +channel_request_shell +channel_request_subsystem +channel_request_x11 +channel_select +channel_send_eof +channel_set_blocking +channel_write +channel_write_stderr +privatekey_free +privatekey_from_file +publickey_free +publickey_from_file +publickey_from_privatekey +publickey_to_string +sftp_async_read +sftp_async_read_begin +sftp_attributes_free +sftp_canonicalize_path +sftp_chmod +sftp_chown +sftp_client_message_free +sftp_client_message_get_data +sftp_client_message_get_filename +sftp_client_message_get_flags +sftp_client_message_get_submessage +sftp_client_message_get_type +sftp_client_message_set_filename +sftp_close +sftp_closedir +sftp_dir_eof +sftp_extension_supported +sftp_extensions_get_count +sftp_extensions_get_data +sftp_extensions_get_name +sftp_file_set_blocking +sftp_file_set_nonblocking +sftp_free +sftp_fstat +sftp_fstatvfs +sftp_fsync +sftp_get_client_message +sftp_get_error +sftp_handle +sftp_handle_alloc +sftp_handle_remove +sftp_init +sftp_lstat +sftp_mkdir +sftp_new +sftp_new_channel +sftp_open +sftp_opendir +sftp_read +sftp_readdir +sftp_readlink +sftp_rename +sftp_reply_attr +sftp_reply_data +sftp_reply_handle +sftp_reply_name +sftp_reply_names +sftp_reply_names_add +sftp_reply_status +sftp_rewind +sftp_rmdir +sftp_seek +sftp_seek64 +sftp_send_client_message +sftp_server_free +sftp_server_init +sftp_server_new +sftp_server_version +sftp_setstat +sftp_stat +sftp_statvfs +sftp_statvfs_free +sftp_symlink +sftp_tell +sftp_tell64 +sftp_unlink +sftp_utimes +sftp_write +ssh_accept +ssh_add_channel_callbacks +ssh_auth_list +ssh_basename +ssh_bind_accept +ssh_bind_accept_fd +ssh_bind_fd_toaccept +ssh_bind_free +ssh_bind_get_fd +ssh_bind_listen +ssh_bind_new +ssh_bind_options_parse_config +ssh_bind_options_set +ssh_bind_set_blocking +ssh_bind_set_callbacks +ssh_bind_set_fd +ssh_blocking_flush +ssh_buffer_add_data +ssh_buffer_free +ssh_buffer_get +ssh_buffer_get_data +ssh_buffer_get_len +ssh_buffer_new +ssh_buffer_reinit +ssh_channel_accept_forward +ssh_channel_accept_x11 +ssh_channel_cancel_forward +ssh_channel_change_pty_size +ssh_channel_close +ssh_channel_free +ssh_channel_get_exit_status +ssh_channel_get_session +ssh_channel_is_closed +ssh_channel_is_eof +ssh_channel_is_open +ssh_channel_listen_forward +ssh_channel_new +ssh_channel_open_auth_agent +ssh_channel_open_forward +ssh_channel_open_forward_port +ssh_channel_open_forward_unix +ssh_channel_open_reverse_forward +ssh_channel_open_session +ssh_channel_open_x11 +ssh_channel_poll +ssh_channel_poll_timeout +ssh_channel_read +ssh_channel_read_nonblocking +ssh_channel_read_timeout +ssh_channel_request_auth_agent +ssh_channel_request_env +ssh_channel_request_exec +ssh_channel_request_pty +ssh_channel_request_pty_size +ssh_channel_request_send_break +ssh_channel_request_send_exit_signal +ssh_channel_request_send_exit_status +ssh_channel_request_send_signal +ssh_channel_request_sftp +ssh_channel_request_shell +ssh_channel_request_subsystem +ssh_channel_request_x11 +ssh_channel_select +ssh_channel_send_eof +ssh_channel_set_blocking +ssh_channel_set_counter +ssh_channel_window_size +ssh_channel_write +ssh_channel_write_stderr +ssh_clean_pubkey_hash +ssh_connect +ssh_connector_free +ssh_connector_new +ssh_connector_set_in_channel +ssh_connector_set_in_fd +ssh_connector_set_out_channel +ssh_connector_set_out_fd +ssh_copyright +ssh_dirname +ssh_disconnect +ssh_dump_knownhost +ssh_event_add_connector +ssh_event_add_fd +ssh_event_add_session +ssh_event_dopoll +ssh_event_free +ssh_event_new +ssh_event_remove_connector +ssh_event_remove_fd +ssh_event_remove_session +ssh_execute_message_callbacks +ssh_finalize +ssh_forward_accept +ssh_forward_cancel +ssh_forward_listen +ssh_free +ssh_get_cipher_in +ssh_get_cipher_out +ssh_get_clientbanner +ssh_get_disconnect_message +ssh_get_error +ssh_get_error_code +ssh_get_fd +ssh_get_fingerprint_hash +ssh_get_hexa +ssh_get_hmac_in +ssh_get_hmac_out +ssh_get_issue_banner +ssh_get_kex_algo +ssh_get_log_callback +ssh_get_log_level +ssh_get_log_userdata +ssh_get_openssh_version +ssh_get_poll_flags +ssh_get_pubkey +ssh_get_pubkey_hash +ssh_get_publickey +ssh_get_publickey_hash +ssh_get_random +ssh_get_server_publickey +ssh_get_serverbanner +ssh_get_status +ssh_get_version +ssh_getpass +ssh_gssapi_get_creds +ssh_gssapi_set_creds +ssh_handle_key_exchange +ssh_init +ssh_is_blocking +ssh_is_connected +ssh_is_server_known +ssh_key_cmp +ssh_key_dup +ssh_key_free +ssh_key_is_private +ssh_key_is_public +ssh_key_new +ssh_key_type +ssh_key_type_from_name +ssh_key_type_to_char +ssh_known_hosts_parse_line +ssh_knownhosts_entry_free +ssh_log +ssh_message_auth_interactive_request +ssh_message_auth_kbdint_is_response +ssh_message_auth_password +ssh_message_auth_pubkey +ssh_message_auth_publickey +ssh_message_auth_publickey_state +ssh_message_auth_reply_pk_ok +ssh_message_auth_reply_pk_ok_simple +ssh_message_auth_reply_success +ssh_message_auth_set_methods +ssh_message_auth_user +ssh_message_channel_request_channel +ssh_message_channel_request_command +ssh_message_channel_request_env_name +ssh_message_channel_request_env_value +ssh_message_channel_request_open_destination +ssh_message_channel_request_open_destination_port +ssh_message_channel_request_open_originator +ssh_message_channel_request_open_originator_port +ssh_message_channel_request_open_reply_accept +ssh_message_channel_request_open_reply_accept_channel +ssh_message_channel_request_pty_height +ssh_message_channel_request_pty_pxheight +ssh_message_channel_request_pty_pxwidth +ssh_message_channel_request_pty_term +ssh_message_channel_request_pty_width +ssh_message_channel_request_reply_success +ssh_message_channel_request_subsystem +ssh_message_channel_request_x11_auth_cookie +ssh_message_channel_request_x11_auth_protocol +ssh_message_channel_request_x11_screen_number +ssh_message_channel_request_x11_single_connection +ssh_message_free +ssh_message_get +ssh_message_global_request_address +ssh_message_global_request_port +ssh_message_global_request_reply_success +ssh_message_reply_default +ssh_message_retrieve +ssh_message_service_reply_success +ssh_message_service_service +ssh_message_subtype +ssh_message_type +ssh_mkdir +ssh_new +ssh_options_copy +ssh_options_get +ssh_options_get_port +ssh_options_getopt +ssh_options_parse_config +ssh_options_set +ssh_pcap_file_close +ssh_pcap_file_free +ssh_pcap_file_new +ssh_pcap_file_open +ssh_pki_copy_cert_to_privkey +ssh_pki_export_privkey_base64 +ssh_pki_export_privkey_file +ssh_pki_export_privkey_to_pubkey +ssh_pki_export_pubkey_base64 +ssh_pki_export_pubkey_file +ssh_pki_generate +ssh_pki_import_cert_base64 +ssh_pki_import_cert_file +ssh_pki_import_privkey_base64 +ssh_pki_import_privkey_file +ssh_pki_import_pubkey_base64 +ssh_pki_import_pubkey_file +ssh_pki_key_ecdsa_name +ssh_print_hash +ssh_print_hexa +ssh_privatekey_type +ssh_publickey_to_file +ssh_remove_channel_callbacks +ssh_scp_accept_request +ssh_scp_close +ssh_scp_deny_request +ssh_scp_free +ssh_scp_init +ssh_scp_leave_directory +ssh_scp_new +ssh_scp_pull_request +ssh_scp_push_directory +ssh_scp_push_file +ssh_scp_push_file64 +ssh_scp_read +ssh_scp_request_get_filename +ssh_scp_request_get_permissions +ssh_scp_request_get_size +ssh_scp_request_get_size64 +ssh_scp_request_get_warning +ssh_scp_write +ssh_select +ssh_send_debug +ssh_send_ignore +ssh_send_issue_banner +ssh_send_keepalive +ssh_server_init_kex +ssh_service_request +ssh_session_export_known_hosts_entry +ssh_session_get_known_hosts_entry +ssh_session_has_known_hosts_entry +ssh_session_is_known_server +ssh_session_set_disconnect_message +ssh_session_update_known_hosts +ssh_set_agent_channel +ssh_set_agent_socket +ssh_set_auth_methods +ssh_set_blocking +ssh_set_callbacks +ssh_set_channel_callbacks +ssh_set_counters +ssh_set_fd_except +ssh_set_fd_toread +ssh_set_fd_towrite +ssh_set_log_callback +ssh_set_log_level +ssh_set_log_userdata +ssh_set_message_callback +ssh_set_pcap_file +ssh_set_server_callbacks +ssh_silent_disconnect +ssh_string_burn +ssh_string_copy +ssh_string_data +ssh_string_fill +ssh_string_free +ssh_string_free_char +ssh_string_from_char +ssh_string_get_char +ssh_string_len +ssh_string_new +ssh_string_to_char +ssh_threads_get_default +ssh_threads_get_noop +ssh_threads_get_pthread +ssh_threads_set_callbacks +ssh_try_publickey_from_file +ssh_userauth_agent +ssh_userauth_agent_pubkey +ssh_userauth_autopubkey +ssh_userauth_gssapi +ssh_userauth_kbdint +ssh_userauth_kbdint_getanswer +ssh_userauth_kbdint_getinstruction +ssh_userauth_kbdint_getname +ssh_userauth_kbdint_getnanswers +ssh_userauth_kbdint_getnprompts +ssh_userauth_kbdint_getprompt +ssh_userauth_kbdint_setanswer +ssh_userauth_list +ssh_userauth_none +ssh_userauth_offer_pubkey +ssh_userauth_password +ssh_userauth_privatekey_file +ssh_userauth_pubkey +ssh_userauth_publickey +ssh_userauth_publickey_auto +ssh_userauth_publickey_auto_get_current_identity +ssh_userauth_try_publickey +ssh_version +ssh_vlog +ssh_write_knownhost +string_burn +string_copy +string_data +string_fill +string_free +string_from_char +string_len +string_new +string_to_char \ No newline at end of file diff --git a/libssh/src/CMakeLists.txt b/libssh/src/CMakeLists.txt index c090fef7..d6245c0d 100644 --- a/libssh/src/CMakeLists.txt +++ b/libssh/src/CMakeLists.txt @@ -348,6 +348,12 @@ endif (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT AND ABIMAP_FOUND) # This gets built as a static library, if -DBUILD_SHARED_LIBS=OFF is passed to # cmake. add_library(ssh ${libssh_SRCS}) +target_compile_options(ssh + PRIVATE + ${DEFAULT_C_COMPILE_FLAGS}) +if (CYGWIN) + target_compile_definitions(ssh PRIVATE _GNU_SOURCE) +endif () target_include_directories(ssh PUBLIC $ @@ -404,6 +410,12 @@ install(EXPORT libssh-config if (BUILD_STATIC_LIB) add_library(ssh-static STATIC ${libssh_SRCS}) + target_compile_options(ssh-static + PRIVATE + ${DEFAULT_C_COMPILE_FLAGS}) + if (CYGWIN) + target_compile_definitions(ssh-static PRIVATE _GNU_SOURCE) + endif () target_include_directories(ssh-static PUBLIC diff --git a/libssh/src/agent.c b/libssh/src/agent.c index 299b4ad1..6e3d7d79 100644 --- a/libssh/src/agent.c +++ b/libssh/src/agent.c @@ -150,11 +150,21 @@ static void agent_set_channel(struct ssh_agent_struct *agent, ssh_channel channe agent->channel = channel; } +/** + * @addtogroup libssh_auth + * + * @{ + */ + /** @brief sets the SSH agent channel. * The SSH agent channel will be used to authenticate this client using * an agent through a channel, from another session. The most likely use * is to implement SSH Agent forwarding into a SSH proxy. + * + * @param session the session + * * @param[in] channel a SSH channel from another session. + * * @returns SSH_OK in case of success * SSH_ERROR in case of an error */ @@ -189,6 +199,10 @@ int ssh_set_agent_socket(ssh_session session, socket_t fd){ return SSH_OK; } +/** + * @} + */ + void ssh_agent_close(struct ssh_agent_struct *agent) { if (agent == NULL) { return; diff --git a/libssh/src/auth.c b/libssh/src/auth.c index aa3aa965..4feb6558 100644 --- a/libssh/src/auth.c +++ b/libssh/src/auth.c @@ -47,7 +47,7 @@ #include "libssh/legacy.h" /** - * @defgroup libssh_auth The SSH authentication functions. + * @defgroup libssh_auth The SSH authentication functions * @ingroup libssh * * Functions to authenticate with a server. @@ -1140,6 +1140,7 @@ int ssh_userauth_publickey_auto(ssh_session session, state->privkey = NULL; state->pubkey = NULL; +#ifdef WITH_PKCS11_URI if (ssh_pki_is_uri(privkey_file)) { char *pub_uri_from_priv = NULL; SSH_LOG(SSH_LOG_INFO, @@ -1152,7 +1153,9 @@ int ssh_userauth_publickey_auto(ssh_session session, pub_uri_from_priv); SAFE_FREE(pub_uri_from_priv); } - } else { + } else +#endif /* WITH_PKCS11_URI */ + { snprintf(pubkey_file, sizeof(pubkey_file), "%s.pub", privkey_file); } diff --git a/libssh/src/bignum.c b/libssh/src/bignum.c index e9b95194..d812b412 100644 --- a/libssh/src/bignum.c +++ b/libssh/src/bignum.c @@ -44,7 +44,7 @@ ssh_string ssh_make_bignum_string(bignum num) { #ifdef DEBUG_CRYPTO SSH_LOG(SSH_LOG_TRACE, - "%zu bits, %zu bytes, %zu padding\n", + "%zu bits, %zu bytes, %zu padding", bits, len, pad); #endif /* DEBUG_CRYPTO */ @@ -86,7 +86,8 @@ void ssh_print_bignum(const char *name, const_bignum num) if (num != NULL) { bignum_bn2hex(num, &hex); } - SSH_LOG(SSH_LOG_DEBUG, "%s value: %s\n", name, (hex == NULL) ? "(null)" : (char *) hex); + SSH_LOG(SSH_LOG_DEBUG, "%s value: %s", name, + (hex == NULL) ? "(null)" : (char *)hex); #ifdef HAVE_LIBGCRYPT SAFE_FREE(hex); #elif defined HAVE_LIBCRYPTO diff --git a/libssh/src/bind.c b/libssh/src/bind.c index 77acbb66..a91e6747 100644 --- a/libssh/src/bind.c +++ b/libssh/src/bind.c @@ -424,7 +424,9 @@ void ssh_bind_free(ssh_bind sshbind){ SAFE_FREE(sshbind); } -int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){ +int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd) +{ + ssh_poll_handle handle = NULL; int i, rc; if (sshbind == NULL) { @@ -516,7 +518,12 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){ return SSH_ERROR; } ssh_socket_set_fd(session->socket, fd); - ssh_socket_get_poll_handle(session->socket); + handle = ssh_socket_get_poll_handle(session->socket); + if (handle == NULL) { + ssh_set_error_oom(sshbind); + return SSH_ERROR; + } + ssh_socket_set_connected(session->socket, handle); /* We must try to import any keys that could be imported in case * we are not using ssh_bind_listen (which is the other place diff --git a/libssh/src/buffer.c b/libssh/src/buffer.c index e0068015..8991e006 100644 --- a/libssh/src/buffer.c +++ b/libssh/src/buffer.c @@ -26,6 +26,7 @@ #include #include #include +#include #ifndef _WIN32 #include @@ -56,7 +57,7 @@ struct ssh_buffer_struct { #define BUFFER_SIZE_MAX 0x10000000 /** - * @defgroup libssh_buffer The SSH buffer functions. + * @defgroup libssh_buffer The SSH buffer functions * @ingroup libssh * * Functions to handle SSH buffers. @@ -747,7 +748,8 @@ uint32_t ssh_buffer_get_u64(struct ssh_buffer_struct *buffer, uint64_t *data){ */ int ssh_buffer_validate_length(struct ssh_buffer_struct *buffer, size_t len) { - if (buffer->pos + len < len || buffer->pos + len > buffer->used) { + if (buffer == NULL || buffer->pos + len < len || + buffer->pos + len > buffer->used) { return SSH_ERROR; } diff --git a/libssh/src/channels.c b/libssh/src/channels.c index 1d422801..f2fe39aa 100644 --- a/libssh/src/channels.c +++ b/libssh/src/channels.c @@ -2499,7 +2499,8 @@ ssh_channel ssh_forward_accept(ssh_session session, int timeout_ms) /** * @brief Accept an incoming TCP/IP forwarding channel and get some information - * about incomming connection + * about incoming connection + * * @param[in] session The ssh session to use. * * @param[in] timeout_ms A timeout in milliseconds. @@ -2515,7 +2516,8 @@ ssh_channel ssh_channel_accept_forward(ssh_session session, int timeout_ms, int* /** * @brief Accept an incoming TCP/IP forwarding channel and get information - * about incomming connection + * about incoming connection + * * @param[in] session The ssh session to use. * * @param[in] timeout_ms A timeout in milliseconds. @@ -3809,4 +3811,4 @@ int ssh_channel_request_send_exit_signal(ssh_channel channel, const char *sig, #endif -/* @} */ +/** @} */ diff --git a/libssh/src/client.c b/libssh/src/client.c index a35a28e1..e912090e 100644 --- a/libssh/src/client.c +++ b/libssh/src/client.c @@ -246,10 +246,13 @@ int ssh_send_banner(ssh_session session, int server) * @warning this function returning is no proof that DH handshake is * completed */ -static int dh_handshake(ssh_session session) +int dh_handshake(ssh_session session) { int rc = SSH_AGAIN; + SSH_LOG(SSH_LOG_TRACE, "dh_handshake_state = %d, kex_type = %d", + session->dh_handshake_state, session->next_crypto->kex_type); + switch (session->dh_handshake_state) { case DH_STATE_INIT: switch(session->next_crypto->kex_type){ @@ -314,8 +317,13 @@ static int ssh_service_request_termination(void *s) } /** - * @internal + * @addtogroup libssh_session * + * @{ + */ + +/** + * @internal * @brief Request a service from the SSH server. * * Service requests are for example: ssh-userauth, ssh-connection, etc. @@ -376,12 +384,6 @@ int ssh_service_request(ssh_session session, const char *service) return rc; } -/** - * @addtogroup libssh_session - * - * @{ - */ - /** * @internal * @@ -392,95 +394,101 @@ static void ssh_client_connection_callback(ssh_session session) { int rc; - switch(session->session_state) { - case SSH_SESSION_STATE_NONE: - case SSH_SESSION_STATE_CONNECTING: - break; - case SSH_SESSION_STATE_SOCKET_CONNECTED: - ssh_set_fd_towrite(session); - ssh_send_banner(session, 0); + SSH_LOG(SSH_LOG_DEBUG, "session_state=%d", session->session_state); - break; - case SSH_SESSION_STATE_BANNER_RECEIVED: - if (session->serverbanner == NULL) { - goto error; - } - set_status(session, 0.4f); - SSH_LOG(SSH_LOG_PROTOCOL, - "SSH server banner: %s", session->serverbanner); + switch (session->session_state) { + case SSH_SESSION_STATE_NONE: + case SSH_SESSION_STATE_CONNECTING: + break; + case SSH_SESSION_STATE_SOCKET_CONNECTED: + ssh_set_fd_towrite(session); + ssh_send_banner(session, 0); - /* Here we analyze the different protocols the server allows. */ - rc = ssh_analyze_banner(session, 0); - if (rc < 0) { - ssh_set_error(session, SSH_FATAL, - "No version of SSH protocol usable (banner: %s)", - session->serverbanner); - goto error; - } + break; + case SSH_SESSION_STATE_BANNER_RECEIVED: + if (session->serverbanner == NULL) { + goto error; + } + set_status(session, 0.4f); + SSH_LOG(SSH_LOG_PROTOCOL, + "SSH server banner: %s", session->serverbanner); + + /* Here we analyze the different protocols the server allows. */ + rc = ssh_analyze_banner(session, 0); + if (rc < 0) { + ssh_set_error(session, SSH_FATAL, + "No version of SSH protocol usable (banner: %s)", + session->serverbanner); + goto error; + } + + ssh_packet_register_socket_callback(session, session->socket); - ssh_packet_register_socket_callback(session, session->socket); + ssh_packet_set_default_callbacks(session); + session->session_state = SSH_SESSION_STATE_INITIAL_KEX; + rc = ssh_set_client_kex(session); + if (rc != SSH_OK) { + goto error; + } + rc = ssh_send_kex(session); + if (rc < 0) { + goto error; + } + set_status(session, 0.5f); - ssh_packet_set_default_callbacks(session); - session->session_state = SSH_SESSION_STATE_INITIAL_KEX; + break; + case SSH_SESSION_STATE_INITIAL_KEX: + /* TODO: This state should disappear in favor of get_key handle */ + break; + case SSH_SESSION_STATE_KEXINIT_RECEIVED: + set_status(session, 0.6f); + ssh_list_kex(&session->next_crypto->server_kex); + if ((session->flags & SSH_SESSION_FLAG_KEXINIT_SENT) == 0) { + /* in rekeying state if next_crypto client_kex might be empty */ rc = ssh_set_client_kex(session); if (rc != SSH_OK) { goto error; } - rc = ssh_send_kex(session, 0); + rc = ssh_send_kex(session); if (rc < 0) { goto error; } - set_status(session, 0.5f); - - break; - case SSH_SESSION_STATE_INITIAL_KEX: - /* TODO: This state should disappear in favor of get_key handle */ - break; - case SSH_SESSION_STATE_KEXINIT_RECEIVED: - set_status(session,0.6f); - ssh_list_kex(&session->next_crypto->server_kex); - if (session->next_crypto->client_kex.methods[0] == NULL) { - /* in rekeying state if next_crypto client_kex is empty */ - rc = ssh_set_client_kex(session); - if (rc != SSH_OK) { - goto error; - } - rc = ssh_send_kex(session, 0); - if (rc < 0) { - goto error; - } - } - if (ssh_kex_select_methods(session) == SSH_ERROR) - goto error; - set_status(session,0.8f); - session->session_state=SSH_SESSION_STATE_DH; - if (dh_handshake(session) == SSH_ERROR) { - goto error; - } - FALL_THROUGH; - case SSH_SESSION_STATE_DH: - if(session->dh_handshake_state==DH_STATE_FINISHED){ - set_status(session,1.0f); - session->connected = 1; - if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) - session->session_state = SSH_SESSION_STATE_AUTHENTICATED; - else - session->session_state=SSH_SESSION_STATE_AUTHENTICATING; - } - break; - case SSH_SESSION_STATE_AUTHENTICATING: - break; - case SSH_SESSION_STATE_ERROR: + } + if (ssh_kex_select_methods(session) == SSH_ERROR) goto error; - default: - ssh_set_error(session,SSH_FATAL,"Invalid state %d",session->session_state); + set_status(session, 0.8f); + session->session_state = SSH_SESSION_STATE_DH; + + /* If the init packet was already sent in previous step, this will be no + * operation */ + if (dh_handshake(session) == SSH_ERROR) { + goto error; + } + FALL_THROUGH; + case SSH_SESSION_STATE_DH: + if (session->dh_handshake_state == DH_STATE_FINISHED) { + set_status(session, 1.0f); + session->connected = 1; + if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) + session->session_state = SSH_SESSION_STATE_AUTHENTICATED; + else + session->session_state=SSH_SESSION_STATE_AUTHENTICATING; + } + break; + case SSH_SESSION_STATE_AUTHENTICATING: + break; + case SSH_SESSION_STATE_ERROR: + goto error; + default: + ssh_set_error(session, SSH_FATAL, "Invalid state %d", + session->session_state); } return; error: ssh_socket_close(session->socket); session->alive = 0; - session->session_state=SSH_SESSION_STATE_ERROR; + session->session_state = SSH_SESSION_STATE_ERROR; } @@ -731,8 +739,8 @@ ssh_session_set_disconnect_message(ssh_session session, const char *message) * * The session can then be reused to open a new session. * - * @note Note that this function wont close the socket if it was set with - * @ssh_options_set and SSH_OPTIONS_FD. You're responsible for closing the + * @note Note that this function won't close the socket if it was set with + * ssh_options_set and SSH_OPTIONS_FD. You're responsible for closing the * socket. This is new behavior in libssh 0.10. * * @param[in] session The SSH session to use. @@ -834,9 +842,16 @@ ssh_disconnect(ssh_session session) } } +/** + * @brief Copyright information + * + * Returns copyright information + * + * @returns SSH_STRING copyright + */ const char *ssh_copyright(void) { - return SSH_STRINGIFY(LIBSSH_VERSION) " (c) 2003-2022 " + return SSH_STRINGIFY(LIBSSH_VERSION) " (c) 2003-2023 " "Aris Adamantiadis, Andreas Schneider " "and libssh contributors. " "Distributed under the LGPL, please refer to COPYING " diff --git a/libssh/src/config.c b/libssh/src/config.c index 41ba1054..c5c40125 100644 --- a/libssh/src/config.c +++ b/libssh/src/config.c @@ -356,7 +356,7 @@ ssh_exec_shell(char *cmd) if (rc == -1) { SSH_LOG(SSH_LOG_WARN, "dup2: %s", ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX)); - exit(1); + exit(1); } if (devnull > STDERR_FILENO) { close(devnull); @@ -395,7 +395,7 @@ ssh_exec_shell(char *cmd) } } if (!WIFEXITED(status)) { - SSH_LOG(SSH_LOG_WARN, "Command %s exitted abnormally", cmd); + SSH_LOG(SSH_LOG_WARN, "Command %s exited abnormally", cmd); return -1; } SSH_LOG(SSH_LOG_TRACE, "Command '%s' returned %d", cmd, WEXITSTATUS(status)); @@ -491,7 +491,7 @@ ssh_config_parse_proxy_jump(ssh_session session, const char *s, bool do_parsing) if (hostname != NULL && do_parsing) { char com[512] = {0}; - rv = snprintf(com, sizeof(com), "ssh%s%s%s%s%s%s -W [%%h]:%%p %s", + rv = snprintf(com, sizeof(com), "ssh%s%s%s%s%s%s -W '[%%h]:%%p' %s", username ? " -l " : "", username ? username : "", port ? " -p " : "", @@ -1006,7 +1006,7 @@ ssh_config_parse_line(ssh_session session, if (p == NULL) { break; } else if (strcmp(p, "default") == 0) { - /* Default rekey limits enforced automaticaly */ + /* Default rekey limits enforced automatically */ ll = 0; } else { char *endp = NULL; diff --git a/libssh/src/config_parser.c b/libssh/src/config_parser.c index 2f91d39f..0d988fec 100644 --- a/libssh/src/config_parser.c +++ b/libssh/src/config_parser.c @@ -32,7 +32,7 @@ #include "libssh/priv.h" /* Returns the original string after skipping the leading whitespace - * and optional quotes. + * until finding LF. * This is useful in case we need to get the rest of the line (for example * external command). */ @@ -47,16 +47,7 @@ char *ssh_config_get_cmd(char **str) break; } } - - if (*c == '\"') { - for (r = ++c; *c; c++) { - if (*c == '\"') { - *c = '\0'; - goto out; - } - } - } - + for (r = c; *c; c++) { if (*c == '\n') { *c = '\0'; diff --git a/libssh/src/connector.c b/libssh/src/connector.c index c9f2cf03..56716749 100644 --- a/libssh/src/connector.c +++ b/libssh/src/connector.c @@ -326,35 +326,40 @@ static void ssh_connector_fd_in_cb(ssh_connector connector) /** @internal * @brief Callback called when a poll event is received on an output fd */ -static void ssh_connector_fd_out_cb(ssh_connector connector){ +static void +ssh_connector_fd_out_cb(ssh_connector connector) +{ unsigned char buffer[CHUNKSIZE]; ssize_t r; ssize_t w; ssize_t total = 0; - SSH_LOG(SSH_LOG_TRACE, "connector POLLOUT event for fd %d", connector->out_fd); + SSH_LOG(SSH_LOG_TRACE, "connector POLLOUT event for fd %d", + connector->out_fd); - if(connector->in_available){ - if (connector->in_channel != NULL){ - r = ssh_channel_read_nonblocking(connector->in_channel, buffer, CHUNKSIZE, 0); - if(r == SSH_ERROR){ + if (connector->in_available) { + if (connector->in_channel != NULL) { + r = ssh_channel_read_nonblocking(connector->in_channel, buffer, + CHUNKSIZE, 0); + if (r == SSH_ERROR) { ssh_connector_except_channel(connector, connector->in_channel); return; - } else if(r == 0 && ssh_channel_is_eof(connector->in_channel)){ + } else if (r == 0 && ssh_channel_is_eof(connector->in_channel)) { close(connector->out_fd); connector->out_fd = SSH_INVALID_SOCKET; return; - } else if(r>0) { + } else if (r > 0) { /* loop around write in case the write blocks even for CHUNKSIZE bytes */ - while (total != r){ - w = ssh_connector_fd_write(connector, buffer + total, r - total); - if (w < 0){ + while (total != r) { + w = ssh_connector_fd_write(connector, buffer + total, + r - total); + if (w < 0) { ssh_connector_except(connector, connector->out_fd); return; } total += w; } } - } else if (connector->in_fd != SSH_INVALID_SOCKET){ + } else if (connector->in_fd != SSH_INVALID_SOCKET) { /* fallback on the socket input callback */ connector->out_wontblock = 1; ssh_connector_fd_in_cb(connector); diff --git a/libssh/src/curve25519.c b/libssh/src/curve25519.c index 6a930faf..66291b5f 100644 --- a/libssh/src/curve25519.c +++ b/libssh/src/curve25519.c @@ -172,6 +172,11 @@ int ssh_client_curve25519_init(ssh_session session) return rc; } +void ssh_client_curve25519_remove_callbacks(ssh_session session) +{ + ssh_packet_remove_callbacks(session, &ssh_curve25519_client_callbacks); +} + static int ssh_curve25519_build_k(ssh_session session) { ssh_curve25519_pubkey k; @@ -285,7 +290,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply){ (void)type; (void)user; - ssh_packet_remove_callbacks(session, &ssh_curve25519_client_callbacks); + ssh_client_curve25519_remove_callbacks(session); pubkey_blob = ssh_buffer_get_ssh_string(packet); if (pubkey_blob == NULL) { @@ -408,8 +413,8 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){ memcpy(session->next_crypto->curve25519_client_pubkey, ssh_string_data(q_c_string), CURVE25519_PUBKEY_SIZE); SSH_STRING_FREE(q_c_string); - /* Build server's keypair */ + /* Build server's key pair */ rc = ssh_curve25519_init(session); if (rc != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Failed to generate curve25519 keys"); diff --git a/libssh/src/dh-gex.c b/libssh/src/dh-gex.c index d0d2890b..91617081 100644 --- a/libssh/src/dh-gex.c +++ b/libssh/src/dh-gex.c @@ -37,7 +37,7 @@ #include "libssh/buffer.h" #include "libssh/session.h" -/* Minimum, recommanded and maximum size of DH group */ +/* Minimum, recommended and maximum size of DH group */ #define DH_PMIN 2048 #define DH_PREQ 2048 #define DH_PMAX 8192 @@ -248,6 +248,11 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_group) return SSH_PACKET_USED; } +void ssh_client_dhgex_remove_callbacks(ssh_session session) +{ + ssh_packet_remove_callbacks(session, &ssh_dhgex_client_callbacks); +} + static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply) { struct ssh_crypto_struct *crypto=session->next_crypto; @@ -258,7 +263,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply) (void)user; SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEX_DH_GEX_REPLY received"); - ssh_packet_remove_callbacks(session, &ssh_dhgex_client_callbacks); + ssh_client_dhgex_remove_callbacks(session); rc = ssh_buffer_unpack(packet, "SBS", &pubkey_blob, &server_pubkey, diff --git a/libssh/src/dh.c b/libssh/src/dh.c index 1251eb64..011d97b3 100644 --- a/libssh/src/dh.c +++ b/libssh/src/dh.c @@ -25,6 +25,8 @@ #include "config.h" +#include + #include "libssh/priv.h" #include "libssh/crypto.h" #include "libssh/buffer.h" @@ -352,6 +354,11 @@ int ssh_client_dh_init(ssh_session session){ return SSH_ERROR; } +void ssh_client_dh_remove_callbacks(ssh_session session) +{ + ssh_packet_remove_callbacks(session, &ssh_dh_client_callbacks); +} + SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){ struct ssh_crypto_struct *crypto=session->next_crypto; ssh_string pubkey_blob = NULL; @@ -361,7 +368,7 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){ (void)type; (void)user; - ssh_packet_remove_callbacks(session, &ssh_dh_client_callbacks); + ssh_client_dh_remove_callbacks(session); rc = ssh_buffer_unpack(packet, "SBS", &pubkey_blob, &server_pubkey, &crypto->dh_server_signature); diff --git a/libssh/src/dh_crypto.c b/libssh/src/dh_crypto.c index a847c6a2..9ff7ad3c 100644 --- a/libssh/src/dh_crypto.c +++ b/libssh/src/dh_crypto.c @@ -154,12 +154,9 @@ int ssh_dh_keypair_get_keys(struct dh_ctx *ctx, int peer, #endif /* OPENSSL_VERSION_NUMBER */ int ssh_dh_keypair_set_keys(struct dh_ctx *ctx, int peer, - const bignum priv, const bignum pub) + bignum priv, bignum pub) { -#if OPENSSL_VERSION_NUMBER < 0x30000000L - bignum priv_key = NULL; - bignum pub_key = NULL; -#else +#if OPENSSL_VERSION_NUMBER >= 0x30000000L int rc; OSSL_PARAM *params = NULL, *out_params = NULL, *merged_params = NULL; OSSL_PARAM_BLD *param_bld = NULL; @@ -172,7 +169,11 @@ int ssh_dh_keypair_set_keys(struct dh_ctx *ctx, int peer, return SSH_ERROR; } -#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#if OPENSSL_VERSION_NUMBER < 0x30000000L + (void)DH_set0_key(ctx->keypair[peer], pub, priv); + + return SSH_OK; +#else rc = EVP_PKEY_todata(ctx->keypair[peer], EVP_PKEY_KEYPAIR, &out_params); if (rc != 1) { return SSH_ERROR; @@ -195,35 +196,22 @@ int ssh_dh_keypair_set_keys(struct dh_ctx *ctx, int peer, rc = SSH_ERROR; goto out; } -#endif /* OPENSSL_VERSION_NUMBER */ if (priv) { -#if OPENSSL_VERSION_NUMBER < 0x30000000L - priv_key = priv; -#else rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PRIV_KEY, priv); if (rc != 1) { rc = SSH_ERROR; goto out; } -#endif /* OPENSSL_VERSION_NUMBER */ } if (pub) { -#if OPENSSL_VERSION_NUMBER < 0x30000000L - pub_key = pub; -#else rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PUB_KEY, pub); if (rc != 1) { rc = SSH_ERROR; goto out; } -#endif /* OPENSSL_VERSION_NUMBER */ } -#if OPENSSL_VERSION_NUMBER < 0x30000000L - (void)DH_set0_key(ctx->keypair[peer], pub_key, priv_key); - return SSH_OK; -#else params = OSSL_PARAM_BLD_to_param(param_bld); if (params == NULL) { rc = SSH_ERROR; @@ -248,6 +236,8 @@ int ssh_dh_keypair_set_keys(struct dh_ctx *ctx, int peer, rc = SSH_OK; out: + bignum_safe_free(priv); + bignum_safe_free(pub); EVP_PKEY_CTX_free(evp_ctx); OSSL_PARAM_free(out_params); OSSL_PARAM_free(params); @@ -341,8 +331,16 @@ int ssh_dh_set_parameters(struct dh_ctx *ctx, goto done; } - OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_P, modulus); - OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_G, generator); + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_P, modulus); + if (rc != 1) { + rc = SSH_ERROR; + goto done; + } + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_G, generator); + if (rc != 1) { + rc = SSH_ERROR; + goto done; + } params = OSSL_PARAM_BLD_to_param(param_bld); if (params == NULL) { OSSL_PARAM_BLD_free(param_bld); @@ -458,7 +456,8 @@ void ssh_dh_cleanup(struct ssh_crypto_struct *crypto) /** @internal * @brief generates a secret DH parameter of at least DH_SECURITY_BITS * security as well as the corresponding public key. - * @param[out] parms a dh_ctx that will hold the new keys. + * + * @param[out] params a dh_ctx that will hold the new keys. * @param peer Select either client or server key storage. Valid values are: * DH_CLIENT_KEYPAIR or DH_SERVER_KEYPAIR * diff --git a/libssh/src/dh_key.c b/libssh/src/dh_key.c index bda54b17..20d24a31 100644 --- a/libssh/src/dh_key.c +++ b/libssh/src/dh_key.c @@ -289,8 +289,10 @@ void ssh_dh_cleanup(struct ssh_crypto_struct *crypto) /** @internal * @brief generates a secret DH parameter of at least DH_SECURITY_BITS * security as well as the corresponding public key. - * @param[out] parms a dh_kex paramters structure with preallocated bignum + * + * @param[out] params a dh_kex parameters structure with preallocated bignum * where to store the parameters + * * @return SSH_OK on success, SSH_ERROR on error */ int ssh_dh_keypair_gen_keys(struct dh_ctx *dh_ctx, int peer) diff --git a/libssh/src/ecdh.c b/libssh/src/ecdh.c index a4c07ccb..e5b11ba9 100644 --- a/libssh/src/ecdh.c +++ b/libssh/src/ecdh.c @@ -43,6 +43,11 @@ struct ssh_packet_callbacks_struct ssh_ecdh_client_callbacks = { .user = NULL }; +void ssh_client_ecdh_remove_callbacks(ssh_session session) +{ + ssh_packet_remove_callbacks(session, &ssh_ecdh_client_callbacks); +} + /** @internal * @brief parses a SSH_MSG_KEX_ECDH_REPLY packet and sends back * a SSH_MSG_NEWKEYS @@ -55,7 +60,7 @@ SSH_PACKET_CALLBACK(ssh_packet_client_ecdh_reply){ (void)type; (void)user; - ssh_packet_remove_callbacks(session, &ssh_ecdh_client_callbacks); + ssh_client_ecdh_remove_callbacks(session); pubkey_blob = ssh_buffer_get_ssh_string(packet); if (pubkey_blob == NULL) { ssh_set_error(session,SSH_FATAL, "No public key in packet"); diff --git a/libssh/src/ecdh_gcrypt.c b/libssh/src/ecdh_gcrypt.c index d9c41bf9..235f2904 100644 --- a/libssh/src/ecdh_gcrypt.c +++ b/libssh/src/ecdh_gcrypt.c @@ -295,7 +295,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ } session->next_crypto->ecdh_client_pubkey = q_c_string; - /* Build server's keypair */ + /* Build server's key pair */ err = gcry_sexp_build(¶m, NULL, "(genkey(ecdh(curve %s) (flags transient-key)))", curve); if (err) { diff --git a/libssh/src/error.c b/libssh/src/error.c index 8930d26a..6b6e1922 100644 --- a/libssh/src/error.c +++ b/libssh/src/error.c @@ -29,7 +29,7 @@ #include "libssh/session.h" /** - * @defgroup libssh_error The SSH error functions. + * @defgroup libssh_error The SSH error functions * @ingroup libssh * * Functions for error handling. diff --git a/libssh/src/external/bcrypt_pbkdf.c b/libssh/src/external/bcrypt_pbkdf.c index 75c02151..85f4be47 100644 --- a/libssh/src/external/bcrypt_pbkdf.c +++ b/libssh/src/external/bcrypt_pbkdf.c @@ -42,7 +42,7 @@ * function with the following modifications: * 1. The input password and salt are preprocessed with SHA512. * 2. The output length is expanded to 256 bits. - * 3. Subsequently the magic string to be encrypted is lengthened and modifed + * 3. Subsequently the magic string to be encrypted is lengthened and modified * to "OxychromaticBlowfishSwatDynamite" * 4. The hash function is defined to perform 64 rounds of initial state * expansion. (More rounds are performed by iterating the hash.) diff --git a/libssh/src/getrandom_crypto.c b/libssh/src/getrandom_crypto.c index 078560ec..df8bd19f 100644 --- a/libssh/src/getrandom_crypto.c +++ b/libssh/src/getrandom_crypto.c @@ -24,6 +24,12 @@ #include "libssh/crypto.h" #include +/** + * @addtogroup libssh_misc + * + * @{ + */ + /** * @brief Get random bytes * @@ -52,3 +58,7 @@ ssh_get_random(void *where, int len, int strong) /* Returns -1 when not supported, 0 on error, 1 on success */ return !!RAND_bytes(where, len); } + +/** + * @} + */ diff --git a/libssh/src/gssapi.c b/libssh/src/gssapi.c index bbfcb6e6..5325ac72 100644 --- a/libssh/src/gssapi.c +++ b/libssh/src/gssapi.c @@ -229,6 +229,7 @@ ssh_gssapi_handle_userauth(ssh_session session, const char *user, "indicate mechs", maj_stat, min_stat); + gss_release_oid_set(&min_stat, &both_supported); return SSH_ERROR; } @@ -265,8 +266,10 @@ ssh_gssapi_handle_userauth(ssh_session session, const char *user, return SSH_OK; } /* from now we have room for context */ - if (ssh_gssapi_init(session) == SSH_ERROR) + if (ssh_gssapi_init(session) == SSH_ERROR) { + gss_release_oid_set(&min_stat, &both_supported); return SSH_ERROR; + } name_buf.value = service_name; name_buf.length = strlen(name_buf.value) + 1; @@ -278,6 +281,7 @@ ssh_gssapi_handle_userauth(ssh_session session, const char *user, "importing name", maj_stat, min_stat); + gss_release_oid_set(&min_stat, &both_supported); return -1; } @@ -345,6 +349,7 @@ static char *ssh_gssapi_name_to_char(gss_name_t name) min_stat); ptr = malloc(buffer.length + 1); if (ptr == NULL) { + gss_release_buffer(&min_stat, &buffer); return NULL; } memcpy(ptr, buffer.value, buffer.length); @@ -428,6 +433,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server){ "Gssapi error", maj_stat, min_stat); + gss_release_buffer(&min_stat, &output_token); ssh_auth_reply_default(session,0); ssh_gssapi_free(session); session->gssapi=NULL; @@ -438,13 +444,23 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server){ hexa = ssh_get_hexa(output_token.value, output_token.length); SSH_LOG(SSH_LOG_PACKET, "GSSAPI: sending token %s",hexa); SAFE_FREE(hexa); - ssh_buffer_pack(session->out_buffer, - "bdP", - SSH2_MSG_USERAUTH_GSSAPI_TOKEN, - output_token.length, - (size_t)output_token.length, output_token.value); + rc = ssh_buffer_pack(session->out_buffer, + "bdP", + SSH2_MSG_USERAUTH_GSSAPI_TOKEN, + output_token.length, + (size_t)output_token.length, output_token.value); + if (rc != SSH_OK) { + ssh_set_error_oom(session); + ssh_auth_reply_default(session, 0); + ssh_gssapi_free(session); + session->gssapi = NULL; + return SSH_PACKET_USED; + } ssh_packet_send(session); } + + gss_release_buffer(&min_stat, &output_token); + if(maj_stat == GSS_S_COMPLETE){ session->gssapi->state = SSH_GSSAPI_STATE_RCV_MIC; } @@ -593,6 +609,7 @@ ssh_gssapi_creds ssh_gssapi_get_creds(ssh_session session) * Unlike ssh_gssapi_get_creds() this is called on the client side of an ssh * connection. * + * @param[in] session The session * @param[in] creds gssapi credentials handle. */ void ssh_gssapi_set_creds(ssh_session session, const ssh_gssapi_creds creds) @@ -648,7 +665,7 @@ ssh_gssapi_send_auth_mic(ssh_session session, ssh_string *oid_set, int n_oid) static int ssh_gssapi_match(ssh_session session, gss_OID_set *valid_oids) { OM_uint32 maj_stat, min_stat, lifetime; - gss_OID_set actual_mechs; + gss_OID_set actual_mechs = GSS_C_NO_OID_SET; gss_buffer_desc namebuf; gss_name_t client_id = GSS_C_NO_NAME; gss_OID oid; @@ -710,6 +727,7 @@ static int ssh_gssapi_match(ssh_session session, gss_OID_set *valid_oids) ret = SSH_OK; end: + gss_release_oid_set(&min_stat, &actual_mechs); gss_release_name(&min_stat, &client_id); return ret; } @@ -724,7 +742,7 @@ static int ssh_gssapi_match(ssh_session session, gss_OID_set *valid_oids) int ssh_gssapi_auth_mic(ssh_session session) { size_t i; - gss_OID_set selected; /* oid selected for authentication */ + gss_OID_set selected = GSS_C_NO_OID_SET; /* oid selected for authentication */ ssh_string *oids = NULL; int rc; size_t n_oids = 0; @@ -801,6 +819,8 @@ int ssh_gssapi_auth_mic(ssh_session session) SSH_STRING_FREE(oids[i]); } free(oids); + gss_release_oid_set(&min_stat, &selected); + if (rc != SSH_ERROR) { return SSH_AUTH_AGAIN; } @@ -845,6 +865,7 @@ static gss_OID ssh_gssapi_oid_from_string(ssh_string oid_s) } SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_response){ + int rc; ssh_string oid_s; gss_uint32 maj_stat, min_stat; gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; @@ -896,14 +917,20 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_response){ hexa = ssh_get_hexa(output_token.value, output_token.length); SSH_LOG(SSH_LOG_PACKET, "GSSAPI: sending token %s", hexa); SAFE_FREE(hexa); - ssh_buffer_pack(session->out_buffer, - "bdP", - SSH2_MSG_USERAUTH_GSSAPI_TOKEN, - output_token.length, - (size_t)output_token.length, output_token.value); + rc = ssh_buffer_pack(session->out_buffer, + "bdP", + SSH2_MSG_USERAUTH_GSSAPI_TOKEN, + output_token.length, + (size_t)output_token.length, output_token.value); + if (rc != SSH_OK) { + ssh_set_error_oom(session); + goto error; + } ssh_packet_send(session); session->auth.state = SSH_AUTH_STATE_GSSAPI_TOKEN; } + + gss_release_buffer(&min_stat, &output_token); return SSH_PACKET_USED; error: @@ -933,9 +960,11 @@ 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); + + SSH_BUFFER_FREE(mic_buffer); + if (GSS_ERROR(maj_stat)){ - SSH_BUFFER_FREE(mic_buffer); - ssh_gssapi_log_error(SSH_LOG_PROTOCOL, + ssh_gssapi_log_error(SSH_LOG_DEBUG, "generating MIC", maj_stat, min_stat); @@ -947,8 +976,10 @@ static int ssh_gssapi_send_mic(ssh_session session) SSH2_MSG_USERAUTH_GSSAPI_MIC, mic_token_buf.length, (size_t)mic_token_buf.length, mic_token_buf.value); + + gss_release_buffer(&min_stat, &mic_token_buf); + if (rc != SSH_OK) { - SSH_BUFFER_FREE(mic_buffer); ssh_set_error_oom(session); return SSH_ERROR; } @@ -957,6 +988,7 @@ static int ssh_gssapi_send_mic(ssh_session session) } SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_client){ + int rc; ssh_string token; char *hexa; OM_uint32 maj_stat, min_stat; @@ -1009,14 +1041,20 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_client){ hexa = ssh_get_hexa(output_token.value, output_token.length); SSH_LOG(SSH_LOG_PACKET, "GSSAPI: sending token %s",hexa); SAFE_FREE(hexa); - ssh_buffer_pack(session->out_buffer, - "bdP", - SSH2_MSG_USERAUTH_GSSAPI_TOKEN, - output_token.length, - (size_t)output_token.length, output_token.value); + rc = ssh_buffer_pack(session->out_buffer, + "bdP", + SSH2_MSG_USERAUTH_GSSAPI_TOKEN, + output_token.length, + (size_t)output_token.length, output_token.value); + if (rc != SSH_OK) { + ssh_set_error_oom(session); + goto error; + } ssh_packet_send(session); } + gss_release_buffer(&min_stat, &output_token); + if (maj_stat == GSS_S_COMPLETE) { ssh_gssapi_send_mic(session); session->auth.state = SSH_AUTH_STATE_GSSAPI_MIC_SENT; diff --git a/libssh/src/gzip.c b/libssh/src/gzip.c index 148cc21c..cff15518 100644 --- a/libssh/src/gzip.c +++ b/libssh/src/gzip.c @@ -24,211 +24,237 @@ #include "config.h" -#include #include +#include #include -#include "libssh/priv.h" #include "libssh/buffer.h" #include "libssh/crypto.h" +#include "libssh/priv.h" #include "libssh/session.h" #ifndef BLOCKSIZE #define BLOCKSIZE 4092 #endif -static z_stream *initcompress(ssh_session session, int level) { - z_stream *stream = NULL; - int status; +static z_stream * +initcompress(ssh_session session, int level) +{ + z_stream *stream = NULL; + int status; - stream = calloc(1, sizeof(z_stream)); - if (stream == NULL) { - return NULL; - } + stream = calloc(1, sizeof(z_stream)); + if (stream == NULL) { + return NULL; + } - status = deflateInit(stream, level); - if (status != Z_OK) { - SAFE_FREE(stream); - ssh_set_error(session, SSH_FATAL, - "status %d inititalising zlib deflate", status); - return NULL; - } + status = deflateInit(stream, level); + if (status != Z_OK) { + SAFE_FREE(stream); + ssh_set_error(session, + SSH_FATAL, + "status %d initialising zlib deflate", + status); + return NULL; + } - return stream; + return stream; } -static ssh_buffer gzip_compress(ssh_session session, ssh_buffer source, int level) +static ssh_buffer +gzip_compress(ssh_session session, ssh_buffer source, int level) { - struct ssh_crypto_struct *crypto = NULL; - z_stream *zout = NULL; - void *in_ptr = ssh_buffer_get(source); - uint32_t in_size = ssh_buffer_get_len(source); - ssh_buffer dest = NULL; - unsigned char out_buf[BLOCKSIZE] = {0}; - uint32_t len; - int status; - - crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_OUT); - if (crypto == NULL) { - return NULL; - } - zout = crypto->compress_out_ctx; - if (zout == NULL) { - zout = crypto->compress_out_ctx = initcompress(session, level); + struct ssh_crypto_struct *crypto = NULL; + z_stream *zout = NULL; + void *in_ptr = ssh_buffer_get(source); + uint32_t in_size = ssh_buffer_get_len(source); + ssh_buffer dest = NULL; + unsigned char out_buf[BLOCKSIZE] = {0}; + uint32_t len; + int status; + + crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_OUT); + if (crypto == NULL) { + return NULL; + } + zout = crypto->compress_out_ctx; if (zout == NULL) { - return NULL; + zout = crypto->compress_out_ctx = initcompress(session, level); + if (zout == NULL) { + return NULL; + } } - } - - dest = ssh_buffer_new(); - if (dest == NULL) { - return NULL; - } - zout->next_out = out_buf; - zout->next_in = in_ptr; - zout->avail_in = in_size; - do { - zout->avail_out = BLOCKSIZE; - status = deflate(zout, Z_PARTIAL_FLUSH); - if (status != Z_OK) { - SSH_BUFFER_FREE(dest); - ssh_set_error(session, SSH_FATAL, - "status %d deflating zlib packet", status); - return NULL; - } - len = BLOCKSIZE - zout->avail_out; - if (ssh_buffer_add_data(dest, out_buf, len) < 0) { - SSH_BUFFER_FREE(dest); - return NULL; + dest = ssh_buffer_new(); + if (dest == NULL) { + return NULL; } - zout->next_out = out_buf; - } while (zout->avail_out == 0); - return dest; + zout->next_out = out_buf; + zout->next_in = in_ptr; + zout->avail_in = in_size; + do { + zout->avail_out = BLOCKSIZE; + status = deflate(zout, Z_PARTIAL_FLUSH); + if (status != Z_OK) { + SSH_BUFFER_FREE(dest); + ssh_set_error(session, + SSH_FATAL, + "status %d deflating zlib packet", + status); + return NULL; + } + len = BLOCKSIZE - zout->avail_out; + if (ssh_buffer_add_data(dest, out_buf, len) < 0) { + SSH_BUFFER_FREE(dest); + return NULL; + } + zout->next_out = out_buf; + } while (zout->avail_out == 0); + + return dest; } -int compress_buffer(ssh_session session, ssh_buffer buf) { - ssh_buffer dest = NULL; +int +compress_buffer(ssh_session session, ssh_buffer buf) +{ + ssh_buffer dest = NULL; + int rv; - dest = gzip_compress(session, buf, session->opts.compressionlevel); - if (dest == NULL) { - return -1; - } + dest = gzip_compress(session, buf, session->opts.compressionlevel); + if (dest == NULL) { + return -1; + } - if (ssh_buffer_reinit(buf) < 0) { - SSH_BUFFER_FREE(dest); - return -1; - } + if (ssh_buffer_reinit(buf) < 0) { + SSH_BUFFER_FREE(dest); + return -1; + } - if (ssh_buffer_add_data(buf, ssh_buffer_get(dest), ssh_buffer_get_len(dest)) < 0) { - SSH_BUFFER_FREE(dest); - return -1; - } + rv = ssh_buffer_add_data(buf, + ssh_buffer_get(dest), + ssh_buffer_get_len(dest)); + if (rv < 0) { + SSH_BUFFER_FREE(dest); + return -1; + } - SSH_BUFFER_FREE(dest); - return 0; + SSH_BUFFER_FREE(dest); + return 0; } /* decompression */ -static z_stream *initdecompress(ssh_session session) { - z_stream *stream = NULL; - int status; +static z_stream * +initdecompress(ssh_session session) +{ + z_stream *stream = NULL; + int status; - stream = calloc(1, sizeof(z_stream)); - if (stream == NULL) { - return NULL; - } + stream = calloc(1, sizeof(z_stream)); + if (stream == NULL) { + return NULL; + } - status = inflateInit(stream); - if (status != Z_OK) { - SAFE_FREE(stream); - ssh_set_error(session, SSH_FATAL, - "Status = %d initiating inflate context!", status); - return NULL; - } + status = inflateInit(stream); + if (status != Z_OK) { + SAFE_FREE(stream); + ssh_set_error(session, + SSH_FATAL, + "Status = %d initiating inflate context!", + status); + return NULL; + } - return stream; + return stream; } -static ssh_buffer gzip_decompress(ssh_session session, ssh_buffer source, size_t maxlen) +static ssh_buffer +gzip_decompress(ssh_session session, ssh_buffer source, size_t maxlen) { - struct ssh_crypto_struct *crypto = NULL; - z_stream *zin = NULL; - void *in_ptr = ssh_buffer_get(source); - uint32_t in_size = ssh_buffer_get_len(source); - unsigned char out_buf[BLOCKSIZE] = {0}; - ssh_buffer dest = NULL; - uint32_t len; - int status; - - crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN); - if (crypto == NULL) { - return NULL; - } - - zin = crypto->compress_in_ctx; - if (zin == NULL) { - zin = crypto->compress_in_ctx = initdecompress(session); - if (zin == NULL) { - return NULL; + struct ssh_crypto_struct *crypto = NULL; + z_stream *zin = NULL; + void *in_ptr = ssh_buffer_get(source); + uint32_t in_size = ssh_buffer_get_len(source); + unsigned char out_buf[BLOCKSIZE] = {0}; + ssh_buffer dest = NULL; + uint32_t len; + int status; + + crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN); + if (crypto == NULL) { + return NULL; } - } - - dest = ssh_buffer_new(); - if (dest == NULL) { - return NULL; - } - - zin->next_out = out_buf; - zin->next_in = in_ptr; - zin->avail_in = in_size; - do { - zin->avail_out = BLOCKSIZE; - status = inflate(zin, Z_PARTIAL_FLUSH); - if (status != Z_OK && status != Z_BUF_ERROR) { - ssh_set_error(session, SSH_FATAL, - "status %d inflating zlib packet", status); - SSH_BUFFER_FREE(dest); - return NULL; + zin = crypto->compress_in_ctx; + if (zin == NULL) { + zin = crypto->compress_in_ctx = initdecompress(session); + if (zin == NULL) { + return NULL; + } } - len = BLOCKSIZE - zin->avail_out; - if (ssh_buffer_add_data(dest,out_buf,len) < 0) { - SSH_BUFFER_FREE(dest); - return NULL; - } - if (ssh_buffer_get_len(dest) > maxlen){ - /* Size of packet exceeded, avoid a denial of service attack */ - SSH_BUFFER_FREE(dest); - return NULL; + dest = ssh_buffer_new(); + if (dest == NULL) { + return NULL; } - zin->next_out = out_buf; - } while (zin->avail_out == 0); - return dest; + zin->next_out = out_buf; + zin->next_in = in_ptr; + zin->avail_in = in_size; + + do { + zin->avail_out = BLOCKSIZE; + status = inflate(zin, Z_PARTIAL_FLUSH); + if (status != Z_OK && status != Z_BUF_ERROR) { + ssh_set_error(session, + SSH_FATAL, + "status %d inflating zlib packet", + status); + SSH_BUFFER_FREE(dest); + return NULL; + } + + len = BLOCKSIZE - zin->avail_out; + if (ssh_buffer_add_data(dest, out_buf, len) < 0) { + SSH_BUFFER_FREE(dest); + return NULL; + } + if (ssh_buffer_get_len(dest) > maxlen) { + /* Size of packet exceeded, avoid a denial of service attack */ + SSH_BUFFER_FREE(dest); + return NULL; + } + zin->next_out = out_buf; + } while (zin->avail_out == 0); + + return dest; } -int decompress_buffer(ssh_session session,ssh_buffer buf, size_t maxlen){ - ssh_buffer dest = NULL; +int +decompress_buffer(ssh_session session, ssh_buffer buf, size_t maxlen) +{ + ssh_buffer dest = NULL; + int rv; - dest = gzip_decompress(session,buf, maxlen); - if (dest == NULL) { - return -1; - } + dest = gzip_decompress(session, buf, maxlen); + if (dest == NULL) { + return -1; + } - if (ssh_buffer_reinit(buf) < 0) { - SSH_BUFFER_FREE(dest); - return -1; - } + if (ssh_buffer_reinit(buf) < 0) { + SSH_BUFFER_FREE(dest); + return -1; + } - if (ssh_buffer_add_data(buf, ssh_buffer_get(dest), ssh_buffer_get_len(dest)) < 0) { - SSH_BUFFER_FREE(dest); - return -1; - } + rv = ssh_buffer_add_data(buf, + ssh_buffer_get(dest), + ssh_buffer_get_len(dest)); + if (rv < 0) { + SSH_BUFFER_FREE(dest); + return -1; + } - SSH_BUFFER_FREE(dest); - return 0; + SSH_BUFFER_FREE(dest); + return 0; } diff --git a/libssh/src/init.c b/libssh/src/init.c index 7f184b9c..e516c331 100644 --- a/libssh/src/init.c +++ b/libssh/src/init.c @@ -22,6 +22,9 @@ */ #include "config.h" + +#include + #include "libssh/priv.h" #include "libssh/socket.h" #include "libssh/dh.h" @@ -278,7 +281,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, * * @see ssh_init() */ -bool is_ssh_initialized() { +bool is_ssh_initialized(void) { bool is_initialized = false; diff --git a/libssh/src/kex.c b/libssh/src/kex.c index 192eb881..b9455d2d 100644 --- a/libssh/src/kex.c +++ b/libssh/src/kex.c @@ -28,6 +28,7 @@ #include #include +#include "libssh/libssh.h" #include "libssh/priv.h" #include "libssh/buffer.h" #include "libssh/dh.h" @@ -89,8 +90,10 @@ #ifdef WITH_ZLIB #define ZLIB "none,zlib@openssh.com,zlib" +#define ZLIB_DEFAULT "none,zlib@openssh.com" #else #define ZLIB "none" +#define ZLIB_DEFAULT "none" #endif /* WITH_ZLIB */ #ifdef HAVE_CURVE25519 @@ -99,17 +102,24 @@ #define CURVE25519 "" #endif /* HAVE_CURVE25519 */ -#ifdef HAVE_ECDH +#ifdef HAVE_ECC #define ECDH "ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521," -#define EC_HOSTKEYS "ecdsa-sha2-nistp521,ecdsa-sha2-nistp384,ecdsa-sha2-nistp256," -#define EC_PUBLIC_KEY_ALGORITHMS "ecdsa-sha2-nistp521-cert-v01@openssh.com," \ +#define EC_HOSTKEYS "ecdsa-sha2-nistp521," \ + "ecdsa-sha2-nistp384," \ + "ecdsa-sha2-nistp256," +#define EC_SK_HOSTKEYS "sk-ecdsa-sha2-nistp256@openssh.com," +#define EC_FIPS_PUBLIC_KEY_ALGOS "ecdsa-sha2-nistp521-cert-v01@openssh.com," \ "ecdsa-sha2-nistp384-cert-v01@openssh.com," \ "ecdsa-sha2-nistp256-cert-v01@openssh.com," +#define EC_PUBLIC_KEY_ALGORITHMS EC_FIPS_PUBLIC_KEY_ALGOS \ + "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com," #else +#define ECDH "" #define EC_HOSTKEYS "" +#define EC_SK_HOSTKEYS "" +#define EC_FIPS_PUBLIC_KEY_ALGOS "" #define EC_PUBLIC_KEY_ALGORITHMS "" -#define ECDH "" -#endif /* HAVE_ECDH */ +#endif /* HAVE_ECC */ #ifdef HAVE_DSA #define DSA_HOSTKEYS ",ssh-dss" @@ -127,16 +137,21 @@ #define HOSTKEYS "ssh-ed25519," \ EC_HOSTKEYS \ + "sk-ssh-ed25519@openssh.com," \ + EC_SK_HOSTKEYS \ "rsa-sha2-512," \ "rsa-sha2-256," \ "ssh-rsa" \ DSA_HOSTKEYS #define DEFAULT_HOSTKEYS "ssh-ed25519," \ EC_HOSTKEYS \ + "sk-ssh-ed25519@openssh.com," \ + EC_SK_HOSTKEYS \ "rsa-sha2-512," \ "rsa-sha2-256" #define PUBLIC_KEY_ALGORITHMS "ssh-ed25519-cert-v01@openssh.com," \ + "sk-ssh-ed25519-cert-v01@openssh.com," \ EC_PUBLIC_KEY_ALGORITHMS \ "rsa-sha2-512-cert-v01@openssh.com," \ "rsa-sha2-256-cert-v01@openssh.com," \ @@ -186,7 +201,7 @@ "rsa-sha2-512," \ "rsa-sha2-256" -#define FIPS_ALLOWED_PUBLIC_KEY_ALGORITHMS EC_PUBLIC_KEY_ALGORITHMS \ +#define FIPS_ALLOWED_PUBLIC_KEY_ALGORITHMS EC_FIPS_PUBLIC_KEY_ALGOS \ "rsa-sha2-512-cert-v01@openssh.com," \ "rsa-sha2-256-cert-v01@openssh.com," \ FIPS_ALLOWED_HOSTKEYS @@ -214,8 +229,8 @@ static const char *fips_methods[] = { FIPS_ALLOWED_CIPHERS, FIPS_ALLOWED_MACS, FIPS_ALLOWED_MACS, - ZLIB, - ZLIB, + ZLIB_DEFAULT, + ZLIB_DEFAULT, "", "", NULL @@ -229,8 +244,8 @@ static const char *default_methods[] = { CHACHA20 AES, "hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256,hmac-sha2-512", "hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256,hmac-sha2-512", - ZLIB, - ZLIB, + ZLIB_DEFAULT, + ZLIB_DEFAULT, "", "", NULL @@ -316,6 +331,10 @@ static int cmp_first_kex_algo(const char *client_str, int is_wrong = 1; + if (client_str == NULL || server_str == NULL) { + return is_wrong; + } + colon = strchr(client_str, ','); if (colon == NULL) { client_kex_len = strlen(client_str); @@ -342,6 +361,7 @@ static int cmp_first_kex_algo(const char *client_str, SSH_PACKET_CALLBACK(ssh_packet_kexinit) { int i, ok; + struct ssh_crypto_struct *crypto = session->next_crypto; int server_kex = session->server; ssh_string str = NULL; char *strings[SSH_KEX_METHODS] = {0}; @@ -355,35 +375,67 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit) (void)type; (void)user; + SSH_LOG(SSH_LOG_TRACE, "KEXINIT received"); + if (session->session_state == SSH_SESSION_STATE_AUTHENTICATED) { - SSH_LOG(SSH_LOG_INFO, "Initiating key re-exchange"); + if (session->dh_handshake_state == DH_STATE_FINISHED) { + SSH_LOG(SSH_LOG_DEBUG, "Peer initiated key re-exchange"); + /* Reset the sent flag if the re-kex was initiated by the peer */ + session->flags &= ~SSH_SESSION_FLAG_KEXINIT_SENT; + } else if (session->flags & SSH_SESSION_FLAG_KEXINIT_SENT && + session->dh_handshake_state == DH_STATE_INIT_SENT) { + /* This happens only when we are sending our-guessed first kex + * packet right after our KEXINIT packet. */ + SSH_LOG(SSH_LOG_DEBUG, "Received peer kexinit answer."); + } else if (session->session_state != SSH_SESSION_STATE_INITIAL_KEX) { + ssh_set_error(session, SSH_FATAL, + "SSH_KEXINIT received in wrong state"); + goto error; + } } else if (session->session_state != SSH_SESSION_STATE_INITIAL_KEX) { - ssh_set_error(session,SSH_FATAL,"SSH_KEXINIT received in wrong state"); + ssh_set_error(session, SSH_FATAL, + "SSH_KEXINIT received in wrong state"); goto error; } if (server_kex) { - len = ssh_buffer_get_data(packet,session->next_crypto->client_kex.cookie, 16); +#ifdef WITH_SERVER + len = ssh_buffer_get_data(packet, crypto->client_kex.cookie, 16); if (len != 16) { - ssh_set_error(session, SSH_FATAL, "ssh_packet_kexinit: no cookie in packet"); + ssh_set_error(session, SSH_FATAL, + "ssh_packet_kexinit: no cookie in packet"); goto error; } - ok = ssh_hashbufin_add_cookie(session, session->next_crypto->client_kex.cookie); + ok = ssh_hashbufin_add_cookie(session, crypto->client_kex.cookie); if (ok < 0) { - ssh_set_error(session, SSH_FATAL, "ssh_packet_kexinit: adding cookie failed"); + ssh_set_error(session, SSH_FATAL, + "ssh_packet_kexinit: adding cookie failed"); goto error; } + + ok = server_set_kex(session); + if (ok == SSH_ERROR) { + goto error; + } +#endif } else { - len = ssh_buffer_get_data(packet,session->next_crypto->server_kex.cookie, 16); + len = ssh_buffer_get_data(packet, crypto->server_kex.cookie, 16); if (len != 16) { - ssh_set_error(session, SSH_FATAL, "ssh_packet_kexinit: no cookie in packet"); + ssh_set_error(session, SSH_FATAL, + "ssh_packet_kexinit: no cookie in packet"); goto error; } - ok = ssh_hashbufin_add_cookie(session, session->next_crypto->server_kex.cookie); + ok = ssh_hashbufin_add_cookie(session, crypto->server_kex.cookie); if (ok < 0) { - ssh_set_error(session, SSH_FATAL, "ssh_packet_kexinit: adding cookie failed"); + ssh_set_error(session, SSH_FATAL, + "ssh_packet_kexinit: adding cookie failed"); + goto error; + } + + ok = ssh_set_client_kex(session); + if (ok == SSH_ERROR) { goto error; } } @@ -396,7 +448,8 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit) rc = ssh_buffer_add_ssh_string(session->in_hashbuf, str); if (rc < 0) { - ssh_set_error(session, SSH_FATAL, "Error adding string in hash buffer"); + ssh_set_error(session, SSH_FATAL, + "Error adding string in hash buffer"); goto error; } @@ -409,14 +462,14 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit) str = NULL; } - /* copy the server kex info into an array of strings */ + /* copy the peer kex info into an array of strings */ if (server_kex) { for (i = 0; i < SSH_KEX_METHODS; i++) { - session->next_crypto->client_kex.methods[i] = strings[i]; + crypto->client_kex.methods[i] = strings[i]; } } else { /* client */ for (i = 0; i < SSH_KEX_METHODS; i++) { - session->next_crypto->server_kex.methods[i] = strings[i]; + crypto->server_kex.methods[i] = strings[i]; } } @@ -430,30 +483,48 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit) * that its value is included when computing the session ID (see * 'make_sessionid'). */ - if (server_kex) { - rc = ssh_buffer_get_u8(packet, &first_kex_packet_follows); - if (rc != 1) { - goto error; - } + rc = ssh_buffer_get_u8(packet, &first_kex_packet_follows); + if (rc != 1) { + goto error; + } - rc = ssh_buffer_add_u8(session->in_hashbuf, first_kex_packet_follows); - if (rc < 0) { - goto error; - } + rc = ssh_buffer_add_u8(session->in_hashbuf, first_kex_packet_follows); + if (rc < 0) { + goto error; + } - rc = ssh_buffer_add_u32(session->in_hashbuf, kexinit_reserved); - if (rc < 0) { - goto error; - } + rc = ssh_buffer_add_u32(session->in_hashbuf, kexinit_reserved); + if (rc < 0) { + goto error; + } + /* + * Remember whether 'first_kex_packet_follows' was set and the client + * guess was wrong: in this case the next SSH_MSG_KEXDH_INIT message + * must be ignored on the server side. + * Client needs to start the Key exchange over with the correct method + */ + if (first_kex_packet_follows || session->send_first_kex_follows) { + char **client_methods = crypto->client_kex.methods; + char **server_methods = crypto->server_kex.methods; + session->first_kex_follows_guess_wrong = + cmp_first_kex_algo(client_methods[SSH_KEX], + server_methods[SSH_KEX]) || + cmp_first_kex_algo(client_methods[SSH_HOSTKEYS], + server_methods[SSH_HOSTKEYS]); + SSH_LOG(SSH_LOG_DEBUG, "The initial guess was %s.", + session->first_kex_follows_guess_wrong ? "wrong" : "right"); + } + + if (server_kex) { /* * If client sent a ext-info-c message in the kex list, it supports * RFC 8308 extension negotiation. */ - ok = ssh_match_group(session->next_crypto->client_kex.methods[SSH_KEX], + ok = ssh_match_group(crypto->client_kex.methods[SSH_KEX], KEX_EXTENSION_CLIENT); if (ok) { - const char *hostkeys = NULL; + const char *hostkeys = NULL, *wanted_hostkeys = NULL; /* The client supports extension negotiation */ session->extensions |= SSH_EXT_NEGOTIATION; @@ -463,14 +534,14 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit) * by the client and enable the respective extensions to provide * correct signature in the next packet if RSA is negotiated */ - hostkeys = session->next_crypto->client_kex.methods[SSH_HOSTKEYS]; + hostkeys = crypto->client_kex.methods[SSH_HOSTKEYS]; + wanted_hostkeys = session->opts.wanted_methods[SSH_HOSTKEYS]; ok = ssh_match_group(hostkeys, "rsa-sha2-512"); if (ok) { /* Check if rsa-sha2-512 is allowed by config */ - if (session->opts.wanted_methods[SSH_HOSTKEYS] != NULL) { - char *is_allowed = - ssh_find_matching(session->opts.wanted_methods[SSH_HOSTKEYS], - "rsa-sha2-512"); + if (wanted_hostkeys != NULL) { + char *is_allowed = ssh_find_matching(wanted_hostkeys, + "rsa-sha2-512"); if (is_allowed != NULL) { session->extensions |= SSH_EXT_SIG_RSA_SHA512; } @@ -480,10 +551,9 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit) ok = ssh_match_group(hostkeys, "rsa-sha2-256"); if (ok) { /* Check if rsa-sha2-256 is allowed by config */ - if (session->opts.wanted_methods[SSH_HOSTKEYS] != NULL) { - char *is_allowed = - ssh_find_matching(session->opts.wanted_methods[SSH_HOSTKEYS], - "rsa-sha2-256"); + if (wanted_hostkeys != NULL) { + char *is_allowed = ssh_find_matching(wanted_hostkeys, + "rsa-sha2-256"); if (is_allowed != NULL) { session->extensions |= SSH_EXT_SIG_RSA_SHA256; } @@ -499,7 +569,7 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit) (session->extensions & SSH_EXT_SIG_RSA_SHA512)) { session->extensions &= ~(SSH_EXT_SIG_RSA_SHA256 | SSH_EXT_SIG_RSA_SHA512); rsa_sig_ext = ssh_find_matching("rsa-sha2-512,rsa-sha2-256", - session->next_crypto->client_kex.methods[SSH_HOSTKEYS]); + hostkeys); if (rsa_sig_ext == NULL) { goto error; /* should never happen */ } else if (strcmp(rsa_sig_ext, "rsa-sha2-512") == 0) { @@ -518,24 +588,16 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit) session->extensions & SSH_EXT_SIG_RSA_SHA256 ? "SHA256" : "", session->extensions & SSH_EXT_SIG_RSA_SHA512 ? " SHA512" : ""); } - - /* - * Remember whether 'first_kex_packet_follows' was set and the client - * guess was wrong: in this case the next SSH_MSG_KEXDH_INIT message - * must be ignored. - */ - if (first_kex_packet_follows) { - session->first_kex_follows_guess_wrong = - cmp_first_kex_algo(session->next_crypto->client_kex.methods[SSH_KEX], - session->next_crypto->server_kex.methods[SSH_KEX]) || - cmp_first_kex_algo(session->next_crypto->client_kex.methods[SSH_HOSTKEYS], - session->next_crypto->server_kex.methods[SSH_HOSTKEYS]); - } } /* Note, that his overwrites authenticated state in case of rekeying */ session->session_state = SSH_SESSION_STATE_KEXINIT_RECEIVED; - session->dh_handshake_state = DH_STATE_INIT; + /* if we already sent our initial key exchange packet, do not reset the + * DH state. We will know if we were right with our guess only in + * dh_handshake_state() */ + if (session->send_first_kex_follows == false) { + session->dh_handshake_state = DH_STATE_INIT; + } session->ssh_connection_callback(session); return SSH_PACKET_USED; @@ -683,14 +745,18 @@ int ssh_set_client_kex(ssh_session session) int i; size_t kex_len, len; + /* Skip if already set, for example for the rekey or when we do the guessing + * it could have been already used to make some protocol decisions. */ + if (client->methods[0] != NULL) { + return SSH_OK; + } + ok = ssh_get_random(client->cookie, 16, 0); if (!ok) { ssh_set_error(session, SSH_FATAL, "PRNG error"); return SSH_ERROR; } - memset(client->methods, 0, SSH_KEX_METHODS * sizeof(char **)); - /* Set the list of allowed algorithms in order of preference, if it hadn't * been set yet. */ for (i = 0; i < SSH_KEX_METHODS; i++) { @@ -760,15 +826,89 @@ static const char *ssh_find_aead_hmac(const char *cipher) return NULL; } +static enum ssh_key_exchange_e +kex_select_kex_type(const char *kex) +{ + if (strcmp(kex, "diffie-hellman-group1-sha1") == 0) { + return SSH_KEX_DH_GROUP1_SHA1; + } else if (strcmp(kex, "diffie-hellman-group14-sha1") == 0) { + return SSH_KEX_DH_GROUP14_SHA1; + } else if (strcmp(kex, "diffie-hellman-group14-sha256") == 0) { + return SSH_KEX_DH_GROUP14_SHA256; + } else if (strcmp(kex, "diffie-hellman-group16-sha512") == 0) { + return SSH_KEX_DH_GROUP16_SHA512; + } else if (strcmp(kex, "diffie-hellman-group18-sha512") == 0) { + return SSH_KEX_DH_GROUP18_SHA512; +#ifdef WITH_GEX + } else if (strcmp(kex, "diffie-hellman-group-exchange-sha1") == 0) { + return SSH_KEX_DH_GEX_SHA1; + } else if (strcmp(kex, "diffie-hellman-group-exchange-sha256") == 0) { + return SSH_KEX_DH_GEX_SHA256; +#endif /* WITH_GEX */ + } else if (strcmp(kex, "ecdh-sha2-nistp256") == 0) { + return SSH_KEX_ECDH_SHA2_NISTP256; + } else if (strcmp(kex, "ecdh-sha2-nistp384") == 0) { + return SSH_KEX_ECDH_SHA2_NISTP384; + } else if (strcmp(kex, "ecdh-sha2-nistp521") == 0) { + return SSH_KEX_ECDH_SHA2_NISTP521; + } else if (strcmp(kex, "curve25519-sha256@libssh.org") == 0) { + return SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG; + } else if (strcmp(kex, "curve25519-sha256") == 0) { + return SSH_KEX_CURVE25519_SHA256; + } + /* should not happen. We should be getting only valid names at this stage */ + return 0; +} + + +/** @internal + * @brief Reverts guessed callbacks set during the dh_handshake() + * @param session session handle + * @returns void + */ +static void revert_kex_callbacks(ssh_session session) +{ + switch (session->next_crypto->kex_type) { + case SSH_KEX_DH_GROUP1_SHA1: + case SSH_KEX_DH_GROUP14_SHA1: + case SSH_KEX_DH_GROUP14_SHA256: + case SSH_KEX_DH_GROUP16_SHA512: + case SSH_KEX_DH_GROUP18_SHA512: + ssh_client_dh_remove_callbacks(session); + break; +#ifdef WITH_GEX + case SSH_KEX_DH_GEX_SHA1: + case SSH_KEX_DH_GEX_SHA256: + ssh_client_dhgex_remove_callbacks(session); + break; +#endif /* WITH_GEX */ +#ifdef HAVE_ECDH + case SSH_KEX_ECDH_SHA2_NISTP256: + case SSH_KEX_ECDH_SHA2_NISTP384: + case SSH_KEX_ECDH_SHA2_NISTP521: + ssh_client_ecdh_remove_callbacks(session); + break; +#endif +#ifdef HAVE_CURVE25519 + case SSH_KEX_CURVE25519_SHA256: + case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG: + ssh_client_curve25519_remove_callbacks(session); + break; +#endif + } +} + /** @brief Select the different methods on basis of client's and * server's kex messages, and watches out if a match is possible. */ int ssh_kex_select_methods (ssh_session session) { - struct ssh_kex_struct *server = &session->next_crypto->server_kex; - struct ssh_kex_struct *client = &session->next_crypto->client_kex; + struct ssh_crypto_struct *crypto = session->next_crypto; + struct ssh_kex_struct *server = &crypto->server_kex; + struct ssh_kex_struct *client = &crypto->client_kex; char *ext_start = NULL; const char *aead_hmac = NULL; + enum ssh_key_exchange_e kex_type; int i; /* Here we should drop the ext-info-c from the list so we avoid matching. @@ -779,51 +919,40 @@ int ssh_kex_select_methods (ssh_session session) } for (i = 0; i < SSH_KEX_METHODS; i++) { - session->next_crypto->kex_methods[i]=ssh_find_matching(server->methods[i],client->methods[i]); + crypto->kex_methods[i] = ssh_find_matching(server->methods[i], + client->methods[i]); if (i == SSH_MAC_C_S || i == SSH_MAC_S_C) { - aead_hmac = ssh_find_aead_hmac(session->next_crypto->kex_methods[i-2]); + aead_hmac = ssh_find_aead_hmac(crypto->kex_methods[i - 2]); if (aead_hmac) { - free(session->next_crypto->kex_methods[i]); - session->next_crypto->kex_methods[i] = strdup(aead_hmac); + free(crypto->kex_methods[i]); + crypto->kex_methods[i] = strdup(aead_hmac); } } - if (session->next_crypto->kex_methods[i] == NULL && i < SSH_LANG_C_S){ - ssh_set_error(session,SSH_FATAL,"kex error : no match for method %s: server [%s], client [%s]", - ssh_kex_descriptions[i],server->methods[i],client->methods[i]); + if (crypto->kex_methods[i] == NULL && i < SSH_LANG_C_S) { + ssh_set_error(session, SSH_FATAL, + "kex error : no match for method %s: server [%s], " + "client [%s]", ssh_kex_descriptions[i], + server->methods[i], client->methods[i]); return SSH_ERROR; - } else if ((i >= SSH_LANG_C_S) && (session->next_crypto->kex_methods[i] == NULL)) { + } else if ((i >= SSH_LANG_C_S) && (crypto->kex_methods[i] == NULL)) { /* we can safely do that for languages */ - session->next_crypto->kex_methods[i] = strdup(""); + crypto->kex_methods[i] = strdup(""); } } - if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group1-sha1") == 0){ - session->next_crypto->kex_type=SSH_KEX_DH_GROUP1_SHA1; - } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group14-sha1") == 0){ - session->next_crypto->kex_type=SSH_KEX_DH_GROUP14_SHA1; - } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group14-sha256") == 0){ - session->next_crypto->kex_type=SSH_KEX_DH_GROUP14_SHA256; - } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group16-sha512") == 0){ - session->next_crypto->kex_type=SSH_KEX_DH_GROUP16_SHA512; - } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group18-sha512") == 0){ - session->next_crypto->kex_type=SSH_KEX_DH_GROUP18_SHA512; -#ifdef WITH_GEX - } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group-exchange-sha1") == 0){ - session->next_crypto->kex_type=SSH_KEX_DH_GEX_SHA1; - } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group-exchange-sha256") == 0){ - session->next_crypto->kex_type=SSH_KEX_DH_GEX_SHA256; -#endif /* WITH_GEX */ - } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp256") == 0){ - session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP256; - } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp384") == 0){ - session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP384; - } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp521") == 0){ - session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP521; - } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "curve25519-sha256@libssh.org") == 0){ - session->next_crypto->kex_type=SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG; - } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "curve25519-sha256") == 0){ - session->next_crypto->kex_type=SSH_KEX_CURVE25519_SHA256; + + /* We can not set this value directly as the old value is needed to revert + * callbacks if we are client */ + kex_type = kex_select_kex_type(crypto->kex_methods[SSH_KEX]); + if (session->client && session->first_kex_follows_guess_wrong) { + SSH_LOG(SSH_LOG_DEBUG, "Our guess was wrong. Restarting the KEX"); + /* We need to remove the wrong callbacks and start kex again */ + revert_kex_callbacks(session); + session->dh_handshake_state = DH_STATE_INIT; + session->first_kex_follows_guess_wrong = false; } + crypto->kex_type = kex_type; + SSH_LOG(SSH_LOG_INFO, "Negotiated %s,%s,%s,%s,%s,%s,%s,%s,%s,%s", session->next_crypto->kex_methods[SSH_KEX], session->next_crypto->kex_methods[SSH_HOSTKEYS], @@ -841,63 +970,116 @@ int ssh_kex_select_methods (ssh_session session) /* this function only sends the predefined set of kex methods */ -int ssh_send_kex(ssh_session session, int server_kex) +int ssh_send_kex(ssh_session session) { - struct ssh_kex_struct *kex = (server_kex ? &session->next_crypto->server_kex : - &session->next_crypto->client_kex); - ssh_string str = NULL; - int i; - int rc; - - rc = ssh_buffer_pack(session->out_buffer, - "bP", - SSH2_MSG_KEXINIT, - 16, - kex->cookie); /* cookie */ - if (rc != SSH_OK) - goto error; - if (ssh_hashbufout_add_cookie(session) < 0) { - goto error; - } + struct ssh_kex_struct *kex = (session->server ? + &session->next_crypto->server_kex : + &session->next_crypto->client_kex); + ssh_string str = NULL; + int i; + int rc; + int first_kex_packet_follows = 0; + + /* Only client can initiate the handshake methods we implement. If we + * already received the peer mechanisms, there is no point in guessing */ + if (session->client && + session->session_state != SSH_SESSION_STATE_KEXINIT_RECEIVED && + session->send_first_kex_follows) { + first_kex_packet_follows = 1; + } + + SSH_LOG(SSH_LOG_TRACE, + "Sending KEXINIT packet, first_kex_packet_follows = %d", + first_kex_packet_follows); + + rc = ssh_buffer_pack(session->out_buffer, + "bP", + SSH2_MSG_KEXINIT, + 16, + kex->cookie); /* cookie */ + if (rc != SSH_OK) + goto error; + if (ssh_hashbufout_add_cookie(session) < 0) { + goto error; + } - ssh_list_kex(kex); + ssh_list_kex(kex); - for (i = 0; i < SSH_KEX_METHODS; i++) { - str = ssh_string_from_char(kex->methods[i]); - if (str == NULL) { - goto error; + for (i = 0; i < SSH_KEX_METHODS; i++) { + str = ssh_string_from_char(kex->methods[i]); + if (str == NULL) { + goto error; + } + + rc = ssh_buffer_add_ssh_string(session->out_hashbuf, str); + if (rc < 0) { + goto error; + } + rc = ssh_buffer_add_ssh_string(session->out_buffer, str); + if (rc < 0) { + goto error; + } + SSH_STRING_FREE(str); + str = NULL; } - if (ssh_buffer_add_ssh_string(session->out_hashbuf, str) < 0) { - goto error; + rc = ssh_buffer_pack(session->out_buffer, + "bd", + first_kex_packet_follows, + 0); + if (rc != SSH_OK) { + goto error; + } + + /* Prepare also the first_kex_packet_follows and reserved to 0 */ + rc = ssh_buffer_add_u8(session->out_hashbuf, first_kex_packet_follows); + if (rc < 0) { + goto error; } - if (ssh_buffer_add_ssh_string(session->out_buffer, str) < 0) { - goto error; + rc = ssh_buffer_add_u32(session->out_hashbuf, 0); + if (rc < 0) { + goto error; } - SSH_STRING_FREE(str); - str = NULL; - } - rc = ssh_buffer_pack(session->out_buffer, - "bd", - 0, - 0); - if (rc != SSH_OK) { - goto error; - } + rc = ssh_packet_send(session); + if (rc == SSH_ERROR) { + return -1; + } - if (ssh_packet_send(session) == SSH_ERROR) { - return -1; - } + session->flags |= SSH_SESSION_FLAG_KEXINIT_SENT; + SSH_LOG(SSH_LOG_PACKET, "SSH_MSG_KEXINIT sent"); + + /* If we indicated that we are sending the guessed key exchange packet, + * do it now. The packet is simple, but we need to do some preparations */ + if (first_kex_packet_follows) { + char *list = kex->methods[SSH_KEX]; + char *colon = strchr(list, ','); + size_t kex_name_len = colon ? (size_t)(colon - list) : strlen(list); + char *kex_name = calloc(kex_name_len + 1, 1); + if (kex_name == NULL) { + ssh_set_error_oom(session); + goto error; + } + snprintf(kex_name, kex_name_len + 1, "%.*s", (int)kex_name_len, list); + SSH_LOG(SSH_LOG_TRACE, "Sending the first kex packet for %s", kex_name); + + session->next_crypto->kex_type = kex_select_kex_type(kex_name); + free(kex_name); + + /* run the first step of the DH handshake */ + session->dh_handshake_state = DH_STATE_INIT; + if (dh_handshake(session) == SSH_ERROR) { + goto error; + } + } + return 0; - SSH_LOG(SSH_LOG_PACKET, "SSH_MSG_KEXINIT sent"); - return 0; error: - ssh_buffer_reinit(session->out_buffer); - ssh_buffer_reinit(session->out_hashbuf); - SSH_STRING_FREE(str); + ssh_buffer_reinit(session->out_buffer); + ssh_buffer_reinit(session->out_hashbuf); + SSH_STRING_FREE(str); - return -1; + return -1; } /* @@ -940,7 +1122,7 @@ int ssh_send_rekex(ssh_session session) } session->dh_handshake_state = DH_STATE_INIT; - rc = ssh_send_kex(session, session->server); + rc = ssh_send_kex(session); if (rc < 0) { SSH_LOG(SSH_LOG_PACKET, "Failed to send kex"); return rc; @@ -1025,33 +1207,6 @@ int ssh_make_sessionid(ssh_session session) client_hash = session->in_hashbuf; } - /* - * Handle the two final fields for the KEXINIT message (RFC 4253 7.1): - * - * boolean first_kex_packet_follows - * uint32 0 (reserved for future extension) - */ - rc = ssh_buffer_add_u8(server_hash, 0); - if (rc < 0) { - goto error; - } - rc = ssh_buffer_add_u32(server_hash, 0); - if (rc < 0) { - goto error; - } - - /* These fields are handled for the server case in ssh_packet_kexinit. */ - if (session->client) { - rc = ssh_buffer_add_u8(client_hash, 0); - if (rc < 0) { - goto error; - } - rc = ssh_buffer_add_u32(client_hash, 0); - if (rc < 0) { - goto error; - } - } - rc = ssh_dh_get_next_server_publickey_blob(session, &server_pubkey_blob); if (rc != SSH_OK) { goto error; diff --git a/libssh/src/knownhosts.c b/libssh/src/knownhosts.c index 49bdf574..9f978096 100644 --- a/libssh/src/knownhosts.c +++ b/libssh/src/knownhosts.c @@ -480,6 +480,8 @@ static const char *ssh_known_host_sigs_from_hostkey_type(enum ssh_keytypes_e typ return "rsa-sha2-512,rsa-sha2-256,ssh-rsa"; case SSH_KEYTYPE_ED25519: return "ssh-ed25519"; + case SSH_KEYTYPE_SK_ED25519: + return "sk-ssh-ed25519@openssh.com"; #ifdef HAVE_DSA case SSH_KEYTYPE_DSS: return "ssh-dss"; @@ -487,13 +489,15 @@ static const char *ssh_known_host_sigs_from_hostkey_type(enum ssh_keytypes_e typ SSH_LOG(SSH_LOG_WARN, "DSS keys are not supported by this build"); break; #endif -#ifdef HAVE_ECDH +#ifdef HAVE_ECC case SSH_KEYTYPE_ECDSA_P256: return "ecdsa-sha2-nistp256"; case SSH_KEYTYPE_ECDSA_P384: return "ecdsa-sha2-nistp384"; case SSH_KEYTYPE_ECDSA_P521: return "ecdsa-sha2-nistp521"; + case SSH_KEYTYPE_SK_ECDSA: + return "sk-ecdsa-sha2-nistp256@openssh.com"; #else case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: @@ -1227,7 +1231,7 @@ ssh_session_get_known_hosts_entry(ssh_session session, * SSH_KNOWN_HOSTS_NOT_FOUND: The known host file does not exist. The * host is thus unknown. File will be * created if host key is accepted.\n - * SSH_KNOWN_HOSTS_ERROR: There had been an eror checking the host. + * SSH_KNOWN_HOSTS_ERROR: There had been an error checking the host. * * @see ssh_knownhosts_entry_free() */ diff --git a/libssh/src/libcrypto.c b/libssh/src/libcrypto.c index 468b63f0..ebdca6e0 100644 --- a/libssh/src/libcrypto.c +++ b/libssh/src/libcrypto.c @@ -716,7 +716,7 @@ evp_cipher_aead_decrypt(struct ssh_cipher_struct *cipher, (unsigned char *)out, &outlen, (unsigned char *)complete_packet + aadlen, - encrypted_size /* already substracted aadlen*/); + encrypted_size /* already subtracted aadlen */); if (rc != 1) { SSH_LOG(SSH_LOG_WARNING, "EVP_DecryptUpdate failed"); return SSH_ERROR; @@ -1573,19 +1573,19 @@ static int evp_dup_pkey(const char* name, const ssh_key key, int demote, return SSH_OK; } -int evp_dup_dsa_pkey(const ssh_key key, ssh_key new, int demote) +int evp_dup_dsa_pkey(const ssh_key key, ssh_key new_key, int demote) { - return evp_dup_pkey("DSA", key, demote, new); + return evp_dup_pkey("DSA", key, demote, new_key); } -int evp_dup_rsa_pkey(const ssh_key key, ssh_key new, int demote) +int evp_dup_rsa_pkey(const ssh_key key, ssh_key new_key, int demote) { - return evp_dup_pkey("RSA", key, demote, new); + return evp_dup_pkey("RSA", key, demote, new_key); } -int evp_dup_ecdsa_pkey(const ssh_key key, ssh_key new, int demote) +int evp_dup_ecdsa_pkey(const ssh_key key, ssh_key new_key, int demote) { - return evp_dup_pkey("EC", key, demote, new); + return evp_dup_pkey("EC", key, demote, new_key); } #endif /* OPENSSL_VERSION_NUMBER */ diff --git a/libssh/src/libgcrypt.c b/libssh/src/libgcrypt.c index da5588ad..2e44a53c 100644 --- a/libssh/src/libgcrypt.c +++ b/libssh/src/libgcrypt.c @@ -390,7 +390,7 @@ aes_gcm_decrypt(struct ssh_cipher_struct *cipher, err = gcry_cipher_setiv(cipher->key[0], cipher->last_iv, AES_GCM_IVLEN); - /* This actualy does not increment the packet counter for the + /* This actually does not increment the packet counter for the * current encryption operation, but for the next one. The first * operation needs to be completed with the derived IV. * diff --git a/libssh/src/libmbedcrypto.c b/libssh/src/libmbedcrypto.c index 6d84bd51..594e5369 100644 --- a/libssh/src/libmbedcrypto.c +++ b/libssh/src/libmbedcrypto.c @@ -725,7 +725,7 @@ chacha20_poly1305_set_iv(struct ssh_cipher_struct *cipher, /* The nonce in mbedTLS is 96 b long. The counter is passed through separate * parameter of 32 b size. - * Encode the seqence number into the last 8 bytes. + * Encode the sequence number into the last 8 bytes. */ PUSH_BE_U64(seqbuf, 4, seq); #ifdef DEBUG_CRYPTO diff --git a/libssh/src/log.c b/libssh/src/log.c index 8ce1e71e..5bae18b8 100644 --- a/libssh/src/log.c +++ b/libssh/src/log.c @@ -47,7 +47,7 @@ static LIBSSH_THREAD ssh_logging_callback ssh_log_cb; static LIBSSH_THREAD void *ssh_log_userdata; /** - * @defgroup libssh_log The SSH logging functions. + * @defgroup libssh_log The SSH logging functions * @ingroup libssh * * Logging functions for debugging and problem resolving. diff --git a/libssh/src/messages.c b/libssh/src/messages.c index ff199f96..3f969536 100644 --- a/libssh/src/messages.c +++ b/libssh/src/messages.c @@ -1453,6 +1453,14 @@ int ssh_message_handle_channel_request(ssh_session session, ssh_channel channel, return SSH_ERROR; } +/** @internal + * + * @brief Sends a successful channel request reply + * + * @param msg A message to reply to + * + * @returns SSH_OK on success, SSH_ERROR if an error occurred. + */ int ssh_message_channel_request_reply_success(ssh_message msg) { uint32_t channel; int rc; diff --git a/libssh/src/misc.c b/libssh/src/misc.c index 3f2652d4..7c478a77 100644 --- a/libssh/src/misc.c +++ b/libssh/src/misc.c @@ -95,7 +95,7 @@ #endif /** - * @defgroup libssh_misc The SSH helper functions. + * @defgroup libssh_misc The SSH helper functions * @ingroup libssh * * Different helper functions used in the SSH Library. @@ -826,7 +826,7 @@ void ssh_list_remove(struct ssh_list *list, struct ssh_iterator *iterator) * @brief Removes the top element of the list and returns the data value * attached to it. * - * @param[in[ list The ssh_list to remove the element. + * @param[in] list The ssh_list to remove the element. * * @returns A pointer to the element being stored in head, or NULL * if the list is empty. @@ -1836,23 +1836,23 @@ int ssh_newline_vis(const char *string, char *buf, size_t buf_len) * * @brief Replaces the last 6 characters of a string from 'X' to 6 random hexdigits. * - * @param[in,out] template Any input string with last 6 characters as 'X'. + * @param[in,out] name Any input string with last 6 characters as 'X'. * @returns -1 as error when the last 6 characters of the input to be replaced are not 'X' * 0 otherwise. */ -int ssh_tmpname(char *template) +int ssh_tmpname(char *name) { char *tmp = NULL; size_t i = 0; int rc = 0; uint8_t random[6]; - if (template == NULL) { + if (name == NULL) { goto err; } - tmp = template + strlen(template) - 6; - if (tmp < template) { + tmp = name + strlen(name) - 6; + if (tmp < name) { goto err; } diff --git a/libssh/src/options.c b/libssh/src/options.c index 49aaefa2..6f2c9397 100644 --- a/libssh/src/options.c +++ b/libssh/src/options.c @@ -52,7 +52,7 @@ * @brief Duplicate the options of a session structure. * * If you make several sessions with the same options this is useful. You - * cannot use twice the same option structure in ssh_session_connect. + * cannot use twice the same option structure in ssh_connect. * * @param src The session to use to copy the options. * @@ -61,13 +61,14 @@ * * @returns 0 on success, -1 on error with errno set. * - * @see ssh_session_connect() + * @see ssh_connect() * @see ssh_free() */ int ssh_options_copy(ssh_session src, ssh_session *dest) { ssh_session new; struct ssh_iterator *it = NULL; + struct ssh_list *list = NULL; char *id = NULL; int i; @@ -105,14 +106,15 @@ int ssh_options_copy(ssh_session src, ssh_session *dest) } /* Remove the default identities */ - for (id = ssh_list_pop_head(char *, new->opts.identity); + for (id = ssh_list_pop_head(char *, new->opts.identity_non_exp); id != NULL; - id = ssh_list_pop_head(char *, new->opts.identity)) { + id = ssh_list_pop_head(char *, new->opts.identity_non_exp)) { SAFE_FREE(id); } /* Copy the new identities from the source list */ - if (src->opts.identity != NULL) { - it = ssh_list_get_iterator(src->opts.identity); + list = new->opts.identity_non_exp; + it = ssh_list_get_iterator(src->opts.identity_non_exp); + for (i = 0; i < 2; i++) { while (it) { int rc; @@ -122,7 +124,7 @@ int ssh_options_copy(ssh_session src, ssh_session *dest) return -1; } - rc = ssh_list_append(new->opts.identity, id); + rc = ssh_list_append(list, id); if (rc < 0) { free(id); ssh_free(new); @@ -130,6 +132,10 @@ int ssh_options_copy(ssh_session src, ssh_session *dest) } it = it->next; } + + /* copy the identity list if there is any already */ + list = new->opts.identity; + it = ssh_list_get_iterator(src->opts.identity); } if (src->opts.sshdir != NULL) { @@ -315,7 +321,7 @@ int ssh_options_set_algo(ssh_session session, * Add a new identity file (const char *, format string) to * the identity list.\n * \n - * By default identity, id_dsa and id_rsa are checked.\n + * By default id_rsa, id_ecdsa and id_ed25519 files are used.\n * \n * The identity used to authenticate with public key will be * prepended to the list. @@ -345,6 +351,7 @@ int ssh_options_set_algo(ssh_session session, * - SSH_LOG_PROTOCOL: High level protocol information * - SSH_LOG_PACKET: Lower level protocol information, packet level * - SSH_LOG_FUNCTIONS: Every function path + * The default is SSH_LOG_NOLOG. * * - SSH_OPTIONS_LOG_VERBOSITY_STR: * Set the session logging verbosity via a @@ -464,7 +471,7 @@ int ssh_options_set_algo(ssh_session session, * (uint64_t, 0=default) * * - SSH_OPTIONS_REKEY_TIME - * Set the time limit for a session before intializing a rekey + * Set the time limit for a session before initializing a rekey * in seconds. RFC 4253 Section 9 recommends one hour. * (uint32_t, 0=off) * @@ -565,7 +572,9 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, } i = strtol(q, &p, 10); if (q == p) { + SSH_LOG(SSH_LOG_DEBUG, "No port number was parsed"); SAFE_FREE(q); + return -1; } SAFE_FREE(q); if (i <= 0) { @@ -657,7 +666,11 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, if (q == NULL) { return -1; } - rc = ssh_list_prepend(session->opts.identity, q); + if (session->opts.exp_flags & SSH_OPT_EXP_FLAG_IDENTITY) { + rc = ssh_list_append(session->opts.identity_non_exp, q); + } else { + rc = ssh_list_prepend(session->opts.identity_non_exp, q); + } if (rc < 0) { free(q); return -1; @@ -677,6 +690,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, ssh_set_error_oom(session); return -1; } + session->opts.exp_flags &= ~SSH_OPT_EXP_FLAG_KNOWNHOSTS; } break; case SSH_OPTIONS_GLOBAL_KNOWNHOSTS: @@ -698,6 +712,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, ssh_set_error_oom(session); return -1; } + session->opts.exp_flags &= ~SSH_OPT_EXP_FLAG_GLOBAL_KNOWNHOSTS; } break; case SSH_OPTIONS_TIMEOUT: @@ -761,7 +776,9 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, } i = strtol(q, &p, 10); if (q == p) { + SSH_LOG(SSH_LOG_DEBUG, "No log verbositiy was parsed"); SAFE_FREE(q); + return -1; } SAFE_FREE(q); if (i < 0) { @@ -862,10 +879,10 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, return -1; } else { if (strcasecmp(value,"yes")==0){ - if(ssh_options_set_algo(session,SSH_COMP_C_S,"zlib@openssh.com,zlib,none") < 0) + if(ssh_options_set_algo(session,SSH_COMP_C_S,"zlib@openssh.com,none") < 0) return -1; } else if (strcasecmp(value,"no")==0){ - if(ssh_options_set_algo(session,SSH_COMP_C_S,"none,zlib@openssh.com,zlib") < 0) + if(ssh_options_set_algo(session,SSH_COMP_C_S,"none,zlib@openssh.com") < 0) return -1; } else { if (ssh_options_set_algo(session, SSH_COMP_C_S, v) < 0) @@ -880,10 +897,10 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, return -1; } else { if (strcasecmp(value,"yes")==0){ - if(ssh_options_set_algo(session,SSH_COMP_S_C,"zlib@openssh.com,zlib,none") < 0) + if(ssh_options_set_algo(session,SSH_COMP_S_C,"zlib@openssh.com,none") < 0) return -1; } else if (strcasecmp(value,"no")==0){ - if(ssh_options_set_algo(session,SSH_COMP_S_C,"none,zlib@openssh.com,zlib") < 0) + if(ssh_options_set_algo(session,SSH_COMP_S_C,"none,zlib@openssh.com") < 0) return -1; } else { if (ssh_options_set_algo(session, SSH_COMP_S_C, v) < 0) @@ -940,6 +957,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, return -1; } session->opts.ProxyCommand = q; + session->opts.exp_flags &= ~SSH_OPT_EXP_FLAG_PROXYCOMMAND; } } break; @@ -1138,7 +1156,7 @@ int ssh_options_get_port(ssh_session session, unsigned int* port_target) { * - SSH_OPTIONS_IDENTITY: * Get the first identity file name (const char *).\n * \n - * By default identity, id_dsa and id_rsa are checked. + * By default id_rsa, id_ecdsa and id_ed25519 files are used. * * - SSH_OPTIONS_PROXYCOMMAND: * Get the proxycommand necessary to log into the @@ -1182,7 +1200,11 @@ int ssh_options_get(ssh_session session, enum ssh_options_e type, char** value) break; } case SSH_OPTIONS_IDENTITY: { - struct ssh_iterator *it = ssh_list_get_iterator(session->opts.identity); + struct ssh_iterator *it; + it = ssh_list_get_iterator(session->opts.identity); + if (it == NULL) { + it = ssh_list_get_iterator(session->opts.identity_non_exp); + } if (it == NULL) { return SSH_ERROR; } @@ -1477,7 +1499,6 @@ int ssh_options_parse_config(ssh_session session, const char *filename) int ssh_options_apply(ssh_session session) { - struct ssh_iterator *it; char *tmp; int rc; @@ -1495,71 +1516,96 @@ int ssh_options_apply(ssh_session session) } } - if (session->opts.knownhosts == NULL) { - tmp = ssh_path_expand_escape(session, "%d/known_hosts"); - } else { - tmp = ssh_path_expand_escape(session, session->opts.knownhosts); - } - if (tmp == NULL) { - return -1; + if ((session->opts.exp_flags & SSH_OPT_EXP_FLAG_KNOWNHOSTS) == 0) { + if (session->opts.knownhosts == NULL) { + tmp = ssh_path_expand_escape(session, "%d/known_hosts"); + } else { + tmp = ssh_path_expand_escape(session, session->opts.knownhosts); + } + if (tmp == NULL) { + return -1; + } + free(session->opts.knownhosts); + session->opts.knownhosts = tmp; + session->opts.exp_flags |= SSH_OPT_EXP_FLAG_KNOWNHOSTS; } - free(session->opts.knownhosts); - session->opts.knownhosts = tmp; - if (session->opts.global_knownhosts == NULL) { - tmp = strdup("/etc/ssh/ssh_known_hosts"); - } else { - tmp = ssh_path_expand_escape(session, session->opts.global_knownhosts); - } - if (tmp == NULL) { - return -1; + if ((session->opts.exp_flags & SSH_OPT_EXP_FLAG_GLOBAL_KNOWNHOSTS) == 0) { + if (session->opts.global_knownhosts == NULL) { + tmp = strdup("/etc/ssh/ssh_known_hosts"); + } else { + tmp = ssh_path_expand_escape(session, + session->opts.global_knownhosts); + } + if (tmp == NULL) { + return -1; + } + free(session->opts.global_knownhosts); + session->opts.global_knownhosts = tmp; + session->opts.exp_flags |= SSH_OPT_EXP_FLAG_GLOBAL_KNOWNHOSTS; } - free(session->opts.global_knownhosts); - session->opts.global_knownhosts = tmp; - if (session->opts.ProxyCommand != NULL) { - char *p = NULL; - size_t plen = strlen(session->opts.ProxyCommand) + - 5 /* strlen("exec ") */; - p = malloc(plen + 1 /* \0 */); - if (p == NULL) { - return -1; - } + if ((session->opts.exp_flags & SSH_OPT_EXP_FLAG_PROXYCOMMAND) == 0) { + if (session->opts.ProxyCommand != NULL) { + char *p = NULL; + size_t plen = strlen(session->opts.ProxyCommand) + + 5 /* strlen("exec ") */; - rc = snprintf(p, plen + 1, "exec %s", session->opts.ProxyCommand); - if ((size_t)rc != plen) { - free(p); - return -1; - } + if (strncmp(session->opts.ProxyCommand, "exec ", 5) != 0) { + p = malloc(plen + 1 /* \0 */); + if (p == NULL) { + return -1; + } - tmp = ssh_path_expand_escape(session, p); - free(p); - if (tmp == NULL) { - return -1; + rc = snprintf(p, plen + 1, "exec %s", session->opts.ProxyCommand); + if ((size_t)rc != plen) { + free(p); + return -1; + } + tmp = ssh_path_expand_escape(session, p); + free(p); + } else { + tmp = ssh_path_expand_escape(session, + session->opts.ProxyCommand); + } + + if (tmp == NULL) { + return -1; + } + free(session->opts.ProxyCommand); + session->opts.ProxyCommand = tmp; + session->opts.exp_flags |= SSH_OPT_EXP_FLAG_PROXYCOMMAND; } - free(session->opts.ProxyCommand); - session->opts.ProxyCommand = tmp; } - for (it = ssh_list_get_iterator(session->opts.identity); - it != NULL; - it = it->next) { - char *id = (char *) it->data; - if (strncmp(id, "pkcs11:", 6) == 0) { + for (tmp = ssh_list_pop_head(char *, session->opts.identity_non_exp); + tmp != NULL; + tmp = ssh_list_pop_head(char *, session->opts.identity_non_exp)) { + char *id = tmp; + if (strncmp(id, "pkcs11:", 6) != 0) { /* PKCS#11 URIs are using percent-encoding so we can not mix * it with ssh expansion of ssh escape characters. - * Skip these identities now, before we will have PKCS#11 support */ - continue; + tmp = ssh_path_expand_escape(session, id); + if (tmp == NULL) { + return -1; + } + free(id); } - tmp = ssh_path_expand_escape(session, id); - if (tmp == NULL) { + + /* use append to keep the order at first call and use prepend + * to put anything that comes on the nth calls to the beginning */ + if (session->opts.exp_flags & SSH_OPT_EXP_FLAG_IDENTITY) { + rc = ssh_list_prepend(session->opts.identity, tmp); + } else { + rc = ssh_list_append(session->opts.identity, tmp); + } + if (rc != SSH_OK) { return -1; } - free(id); - it->data = tmp; } + session->opts.exp_flags |= SSH_OPT_EXP_FLAG_IDENTITY; return 0; } @@ -1663,6 +1709,7 @@ static int ssh_bind_set_algo(ssh_bind sshbind, * - SSH_LOG_PROTOCOL: High level protocol information * - SSH_LOG_PACKET: Lower level protocol information, packet level * - SSH_LOG_FUNCTIONS: Every function path + * The default is SSH_LOG_NOLOG. * * - SSH_BIND_OPTIONS_LOG_VERBOSITY_STR: * Set the session logging verbosity via a @@ -1943,7 +1990,9 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type, } i = strtol(q, &p, 10); if (q == p) { - SAFE_FREE(q); + SSH_LOG(SSH_LOG_DEBUG, "No bind port was parsed"); + SAFE_FREE(q); + return -1; } SAFE_FREE(q); @@ -1970,7 +2019,9 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type, } i = strtol(q, &p, 10); if (q == p) { - SAFE_FREE(q); + SSH_LOG(SSH_LOG_DEBUG, "No log verbositiy was parsed"); + SAFE_FREE(q); + return -1; } SAFE_FREE(q); diff --git a/libssh/src/packet.c b/libssh/src/packet.c index e01351aa..eb7eb42a 100644 --- a/libssh/src/packet.c +++ b/libssh/src/packet.c @@ -366,6 +366,11 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se * - session->dh_handshake_state = DH_STATE_NEWKEYS_SENT * */ + if (!session->server) { + rc = SSH_PACKET_DENIED; + break; + } + if (session->session_state != SSH_SESSION_STATE_DH) { rc = SSH_PACKET_DENIED; break; @@ -1052,9 +1057,11 @@ static bool ssh_packet_need_rekey(ssh_session session, * @param user pointer to current ssh_session * @param data pointer to the data received * @len length of data received. It might not be enough for a complete packet - * @returns number of bytes read and processed. + * @returns number of bytes read and processed. Zero means only partial packet + * received and negative value means error. */ -size_t ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user) +size_t +ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user) { ssh_session session = (ssh_session)user; uint32_t blocksize = 8; @@ -1066,7 +1073,7 @@ size_t ssh_packet_socket_callback(const void *data, size_t receivedlen, void *us uint8_t *cleartext_packet = NULL; uint8_t *packet_second_block = NULL; uint8_t *mac = NULL; - size_t packet_remaining; + size_t packet_remaining, packet_offset; uint32_t packet_len, compsize, payloadsize; uint8_t padding; size_t processed = 0; /* number of bytes processed from the callback */ @@ -1112,7 +1119,7 @@ size_t ssh_packet_socket_callback(const void *data, size_t receivedlen, void *us session->packet_state == PACKET_STATE_PROCESSING ? "PROCESSING" : "unknown"); #endif - switch(session->packet_state) { + switch (session->packet_state) { case PACKET_STATE_INIT: if (receivedlen < lenfield_blocksize + etm_packet_offset) { /* @@ -1145,11 +1152,13 @@ size_t ssh_packet_socket_callback(const void *data, size_t receivedlen, void *us } if (!etm) { - ptr = ssh_buffer_allocate(session->in_buffer, lenfield_blocksize); + ptr = ssh_buffer_allocate(session->in_buffer, + lenfield_blocksize); if (ptr == NULL) { goto error; } - packet_len = ssh_packet_decrypt_len(session, ptr, (uint8_t *)data); + packet_len = ssh_packet_decrypt_len(session, ptr, + (uint8_t *)data); to_be_read = packet_len - lenfield_blocksize + sizeof(uint32_t); } else { /* Length is unencrypted in case of Encrypt-then-MAC */ @@ -1179,11 +1188,11 @@ size_t ssh_packet_socket_callback(const void *data, size_t receivedlen, void *us FALL_THROUGH; case PACKET_STATE_SIZEREAD: packet_len = session->in_packet.len; - processed = lenfield_blocksize + etm_packet_offset; + packet_offset = processed = lenfield_blocksize + etm_packet_offset; to_be_read = packet_len + sizeof(uint32_t) + current_macsize; /* if to_be_read is zero, the whole packet was blocksize bytes. */ if (to_be_read != 0) { - if (receivedlen < (unsigned long)to_be_read) { + if (receivedlen < (unsigned long)to_be_read) { /* give up, not enough data in buffer */ SSH_LOG(SSH_LOG_PACKET, "packet: partial packet (read len) " @@ -1194,13 +1203,12 @@ size_t ssh_packet_socket_callback(const void *data, size_t receivedlen, void *us return 0; } - packet_second_block = (uint8_t*)data + lenfield_blocksize + etm_packet_offset; + packet_second_block = (uint8_t*)data + packet_offset; processed = to_be_read - current_macsize; } /* remaining encrypted bytes from the packet, MAC not included */ - packet_remaining = - packet_len - (lenfield_blocksize - sizeof(uint32_t) + etm_packet_offset); + packet_remaining = packet_len - (packet_offset - sizeof(uint32_t)); cleartext_packet = ssh_buffer_allocate(session->in_buffer, packet_remaining); if (cleartext_packet == NULL) { @@ -1223,16 +1231,16 @@ size_t ssh_packet_socket_callback(const void *data, size_t receivedlen, void *us } } /* - * Decrypt the packet. In case of EtM mode, the length is already - * known as it's unencrypted. In the other case, lenfield_blocksize bytes - * already have been decrypted. + * Decrypt the packet. In case of EtM mode, the length is + * already known as it's unencrypted. In the other case, + * lenfield_blocksize bytes already have been decrypted. */ if (packet_remaining > 0) { rc = ssh_packet_decrypt(session, cleartext_packet, (uint8_t *)data, - lenfield_blocksize + etm_packet_offset, - processed - (lenfield_blocksize + etm_packet_offset)); + packet_offset, + processed - packet_offset); if (rc < 0) { ssh_set_error(session, SSH_FATAL, @@ -1242,9 +1250,10 @@ size_t ssh_packet_socket_callback(const void *data, size_t receivedlen, void *us } if (crypto->in_hmac != SSH_HMAC_NONE && !etm) { + ssh_buffer in = session->in_buffer; rc = ssh_packet_hmac_verify(session, - ssh_buffer_get(session->in_buffer), - ssh_buffer_get_len(session->in_buffer), + ssh_buffer_get(in), + ssh_buffer_get_len(in), mac, crypto->in_hmac); if (rc < 0) { @@ -1295,9 +1304,10 @@ size_t ssh_packet_socket_callback(const void *data, size_t receivedlen, void *us compsize = ssh_buffer_get_len(session->in_buffer); #ifdef WITH_ZLIB - if (crypto && crypto->do_compress_in - && ssh_buffer_get_len(session->in_buffer) > 0) { - rc = decompress_buffer(session, session->in_buffer,MAX_PACKET_LEN); + if (crypto && crypto->do_compress_in && + ssh_buffer_get_len(session->in_buffer) > 0) { + rc = decompress_buffer(session, session->in_buffer, + MAX_PACKET_LEN); if (rc < 0) { goto error; } @@ -1324,13 +1334,15 @@ size_t ssh_packet_socket_callback(const void *data, size_t receivedlen, void *us session->packet_state = PACKET_STATE_PROCESSING; ssh_packet_parse_type(session); SSH_LOG(SSH_LOG_PACKET, - "packet: read type %hhd [len=%d,padding=%hhd,comp=%d,payload=%d]", - session->in_packet.type, packet_len, padding, compsize, payloadsize); + "packet: read type %hhd [len=%" PRIu32 ",padding=%hhd," + "comp=%" PRIu32 ",payload=%" PRIu32 "]", + session->in_packet.type, packet_len, padding, compsize, + payloadsize); /* Check if the packet is expected */ filter_result = ssh_packet_incoming_filter(session); - switch(filter_result) { + switch (filter_result) { case SSH_PACKET_ALLOWED: /* Execute callbacks */ ssh_packet_process(session, session->in_packet.type); @@ -1355,7 +1367,8 @@ size_t ssh_packet_socket_callback(const void *data, size_t receivedlen, void *us ptr = ((uint8_t*)data) + processed; - rc = ssh_packet_socket_callback(ptr, receivedlen - processed,user); + rc = ssh_packet_socket_callback(ptr, receivedlen - processed, + user); processed += rc; } @@ -1381,8 +1394,8 @@ size_t ssh_packet_socket_callback(const void *data, size_t receivedlen, void *us session->packet_state); error: - session->session_state= SSH_SESSION_STATE_ERROR; - SSH_LOG(SSH_LOG_PACKET,"Packet: processed %zu bytes", processed); + session->session_state = SSH_SESSION_STATE_ERROR; + SSH_LOG(SSH_LOG_PACKET, "Packet: processed %zu bytes", processed); return processed; } @@ -1410,18 +1423,23 @@ static void ssh_packet_socket_controlflow_callback(int code, void *userdata) } } -void ssh_packet_register_socket_callback(ssh_session session, ssh_socket s){ - session->socket_callbacks.data=ssh_packet_socket_callback; - session->socket_callbacks.connected=NULL; - session->socket_callbacks.controlflow = ssh_packet_socket_controlflow_callback; - session->socket_callbacks.userdata=session; - ssh_socket_set_callbacks(s,&session->socket_callbacks); +void ssh_packet_register_socket_callback(ssh_session session, ssh_socket s) +{ + struct ssh_socket_callbacks_struct *callbacks = &session->socket_callbacks; + + callbacks->data = ssh_packet_socket_callback; + callbacks->connected = NULL; + callbacks->controlflow = ssh_packet_socket_controlflow_callback; + callbacks->userdata = session; + ssh_socket_set_callbacks(s, callbacks); } /** @internal * @brief sets the callbacks for the packet layer */ -void ssh_packet_set_callbacks(ssh_session session, ssh_packet_callbacks callbacks){ +void +ssh_packet_set_callbacks(ssh_session session, ssh_packet_callbacks callbacks) +{ if (session->packet_callbacks == NULL) { session->packet_callbacks = ssh_list_new(); if (session->packet_callbacks == NULL) { @@ -1435,8 +1453,11 @@ void ssh_packet_set_callbacks(ssh_session session, ssh_packet_callbacks callback /** @internal * @brief remove the callbacks from the packet layer */ -void ssh_packet_remove_callbacks(ssh_session session, ssh_packet_callbacks callbacks){ +void +ssh_packet_remove_callbacks(ssh_session session, ssh_packet_callbacks callbacks) +{ struct ssh_iterator *it = NULL; + it = ssh_list_find(session->packet_callbacks, callbacks); if (it != NULL) { ssh_list_remove(session->packet_callbacks, it); @@ -1446,12 +1467,15 @@ void ssh_packet_remove_callbacks(ssh_session session, ssh_packet_callbacks callb /** @internal * @brief sets the default packet handlers */ -void ssh_packet_set_default_callbacks(ssh_session session){ - session->default_packet_callbacks.start=1; - session->default_packet_callbacks.n_callbacks=sizeof(default_packet_handlers)/sizeof(ssh_packet_callback); - session->default_packet_callbacks.user=session; - session->default_packet_callbacks.callbacks=default_packet_handlers; - ssh_packet_set_callbacks(session, &session->default_packet_callbacks); +void ssh_packet_set_default_callbacks(ssh_session session) +{ + struct ssh_packet_callbacks_struct *c = &session->default_packet_callbacks; + + c->start = 1; + c->n_callbacks = sizeof(default_packet_handlers) / sizeof(ssh_packet_callback); + c->user = session; + c->callbacks = default_packet_handlers; + ssh_packet_set_callbacks(session, c); } /** @internal @@ -1755,10 +1779,12 @@ static bool ssh_packet_in_rekey(ssh_session session) { /* We know we are rekeying if we are authenticated and the DH - * status is not finished + * status is not finished, but we only queue packets until we've + * sent our NEWKEYS. */ return (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) && - (session->dh_handshake_state != DH_STATE_FINISHED); + (session->dh_handshake_state != DH_STATE_FINISHED) && + (session->dh_handshake_state != DH_STATE_NEWKEYS_SENT); } int ssh_packet_send(ssh_session session) @@ -1799,7 +1825,7 @@ int ssh_packet_send(ssh_session session) if (need_rekey) { /* Send the KEXINIT packet instead. - * This recursivelly calls the packet_send(), but it should + * This recursively calls the packet_send(), but it should * not get into rekeying again. * After that we need to handle the key exchange responses * up to the point where we can send the rest of the queue. @@ -1930,7 +1956,7 @@ ssh_packet_set_newkeys(ssh_session session, memcpy(session->next_crypto->session_id, session->current_crypto->session_id, session_id_len); - session->next_crypto->session_id_len = session_id_len; + session->next_crypto->session_id_len = session_id_len; return SSH_OK; } diff --git a/libssh/src/packet_cb.c b/libssh/src/packet_cb.c index 39575b17..0ecf8771 100644 --- a/libssh/src/packet_cb.c +++ b/libssh/src/packet_cb.c @@ -63,6 +63,11 @@ SSH_PACKET_CALLBACK(ssh_packet_disconnect_callback){ error = ssh_string_to_char(error_s); SSH_STRING_FREE(error_s); } + + if (error != NULL) { + session->peer_discon_msg = strdup(error); + } + SSH_LOG(SSH_LOG_PACKET, "Received SSH_MSG_DISCONNECT %d:%s", code, error != NULL ? error : "no error"); ssh_set_error(session, SSH_FATAL, @@ -156,11 +161,14 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){ session->next_crypto->digest_len); SSH_SIGNATURE_FREE(sig); if (rc == SSH_ERROR) { + ssh_set_error(session, + SSH_FATAL, + "Failed to verify server hostkey signature"); goto error; } SSH_LOG(SSH_LOG_PROTOCOL,"Signature verified and valid"); - /* When receiving this packet, we switch on the incomming crypto. */ + /* When receiving this packet, we switch on the incoming crypto. */ rc = ssh_packet_set_newkeys(session, SSH_DIRECTION_IN); if (rc != SSH_OK) { goto error; @@ -244,6 +252,8 @@ SSH_PACKET_CALLBACK(ssh_packet_ext_info) if (ssh_match_group(value, "rsa-sha2-256")) { session->extensions |= SSH_EXT_SIG_RSA_SHA256; } + } else { + SSH_LOG(SSH_LOG_PACKET, "Unknown extension: %s", name); } free(name); free(value); diff --git a/libssh/src/pcap.c b/libssh/src/pcap.c index 9492df50..5b787a83 100644 --- a/libssh/src/pcap.c +++ b/libssh/src/pcap.c @@ -44,14 +44,11 @@ #include "libssh/socket.h" /** - * @internal - * * @defgroup libssh_pcap The libssh pcap functions * @ingroup libssh * * The pcap file generation * - * * @{ */ @@ -98,7 +95,6 @@ struct pcaprec_hdr_s { * in a SSH session only. Multiple pcap contexts may be used into * a single pcap file. */ - struct ssh_pcap_context_struct { ssh_session session; ssh_pcap_file file; @@ -280,7 +276,6 @@ void ssh_pcap_file_free(ssh_pcap_file pcap){ /** @internal * @brief allocates a new ssh_pcap_context object */ - ssh_pcap_context ssh_pcap_context_new(ssh_session session){ ssh_pcap_context ctx = (struct ssh_pcap_context_struct *) malloc(sizeof(struct ssh_pcap_context_struct)); if(ctx==NULL){ @@ -523,7 +518,7 @@ int ssh_set_pcap_file(ssh_session session, ssh_pcap_file pcap){ session->pcap_ctx=ctx; return SSH_OK; } - +/** @} */ #else /* WITH_PCAP */ @@ -557,5 +552,3 @@ int ssh_set_pcap_file(ssh_session session, ssh_pcap_file pcapfile){ } #endif - -/** @} */ diff --git a/libssh/src/pki.c b/libssh/src/pki.c index 8f62ce2b..a7c84c5e 100644 --- a/libssh/src/pki.c +++ b/libssh/src/pki.c @@ -137,6 +137,13 @@ ssh_key ssh_key_new (void) return ptr; } +/** + * @brief duplicates the key + * + * @param key An ssh_key to duplicate + * + * @return A duplicated ssh_key key + */ ssh_key ssh_key_dup(const ssh_key key) { if (key == NULL) { @@ -222,6 +229,8 @@ enum ssh_keytypes_e ssh_key_type(const ssh_key key) * * @param[in] type The algorithm type to convert. * + * @param[in] hash_type The hash type to convert + * * @return A string for the keytype or NULL if unknown. */ const char * @@ -1081,7 +1090,7 @@ int ssh_pki_export_privkey_file(const ssh_key privkey, return SSH_OK; } -/* temporary function to migrate seemlessly to ssh_key */ +/* temporary function to migrate seamlessly to ssh_key */ ssh_public_key ssh_pki_convert_key_to_publickey(const ssh_key key) { ssh_public_key pub; @@ -1714,6 +1723,7 @@ int ssh_pki_import_pubkey_blob(const ssh_string key_blob, return SSH_ERROR; } +#ifdef WITH_PKCS11_URI /** *@brief Detect if the pathname in cmp is a PKCS #11 URI. * @@ -1757,6 +1767,7 @@ char *ssh_pki_export_pub_uri_from_priv_uri(const char *priv_uri) return pub_uri_temp; } +#endif /* WITH_PKCS11_URI */ /** * @brief Import a public key from a file or a PKCS #11 device. @@ -1942,7 +1953,7 @@ int ssh_pki_import_cert_file(const char *filename, ssh_key *pkey) } /** - * @brief Generates a keypair. + * @brief Generates a key pair. * * @param[in] type Type of key to create * @@ -2147,6 +2158,18 @@ int ssh_pki_export_pubkey_base64(const ssh_key key, return SSH_OK; } +/** + * @brief Export public key to file + * + * Exports the public key in AuthorizedKeysFile acceptable format. + * For more information see `man sshd` + * + * @param key A key to export + * + * @param filename The name of the output file + * + * @returns SSH_OK on success, SSH_ERROR otherwise. + */ int ssh_pki_export_pubkey_file(const ssh_key key, const char *filename) { @@ -2500,7 +2523,7 @@ int ssh_pki_signature_verify(ssh_session session, allowed = ssh_key_size_allowed(session, key); if (!allowed) { ssh_set_error(session, SSH_FATAL, "The '%s' key of size %d is not " - "allowd by RSA_MIN_SIZE", key->type_c, ssh_key_size(key)); + "allowed by RSA_MIN_SIZE", key->type_c, ssh_key_size(key)); return SSH_ERROR; } diff --git a/libssh/src/pki_container_openssh.c b/libssh/src/pki_container_openssh.c index cc97da7f..4314c5b7 100644 --- a/libssh/src/pki_container_openssh.c +++ b/libssh/src/pki_container_openssh.c @@ -630,7 +630,11 @@ ssh_string ssh_pki_openssh_privkey_export(const ssh_key privkey, goto error; } - ssh_buffer_pack(kdf_buf, "Sd", salt, rounds); + rc = ssh_buffer_pack(kdf_buf, "Sd", salt, rounds); + if (rc != SSH_OK) { + SSH_BUFFER_FREE(kdf_buf); + goto error; + } kdf_options = ssh_string_new(ssh_buffer_get_len(kdf_buf)); if (kdf_options == NULL){ SSH_BUFFER_FREE(kdf_buf); diff --git a/libssh/src/pki_crypto.c b/libssh/src/pki_crypto.c index 33544d6a..5b0d7ded 100644 --- a/libssh/src/pki_crypto.c +++ b/libssh/src/pki_crypto.c @@ -954,7 +954,7 @@ int pki_key_generate_ecdsa(ssh_key key, int parameter) { #endif /* HAVE_OPENSSL_ECC */ /* With OpenSSL 3.0 and higher the parameter 'what' - * is ignored and the comparision is done by OpenSSL + * is ignored and the comparison is done by OpenSSL */ int pki_key_compare(const ssh_key k1, const ssh_key k2, @@ -1092,7 +1092,7 @@ int pki_key_compare(const ssh_key k1, #endif /* OPENSSL_VERSION_NUMBER */ case SSH_KEYTYPE_ED25519: case SSH_KEYTYPE_SK_ED25519: - /* ed25519 keys handled globaly */ + /* ed25519 keys handled globally */ case SSH_KEYTYPE_UNKNOWN: default: return 1; @@ -1492,18 +1492,18 @@ int pki_privkey_build_dss(ssh_key key, ssh_string privkey) { int rc; -#if OPENSSL_VERSION_NUMBER < 0x30000000L BIGNUM *bp, *bq, *bg, *bpub_key, *bpriv_key; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + OSSL_PARAM_BLD *param_bld = OSSL_PARAM_BLD_new(); + if (param_bld == NULL) { + return SSH_ERROR; + } #else - const BIGNUM *pb, *qb, *gb, *pubb, *privb; - OSSL_PARAM_BLD *param_bld; -#endif /* OPENSSL_VERSION_NUMBER */ - -#if OPENSSL_VERSION_NUMBER < 0x30000000L key->dsa = DSA_new(); if (key->dsa == NULL) { return SSH_ERROR; } +#endif /* OPENSSL_VERSION_NUMBER */ bp = ssh_make_string_bn(p); bq = ssh_make_string_bn(q); @@ -1512,9 +1512,11 @@ int pki_privkey_build_dss(ssh_key key, bpriv_key = ssh_make_string_bn(privkey); if (bp == NULL || bq == NULL || bg == NULL || bpub_key == NULL) { + rc = SSH_ERROR; goto fail; } +#if OPENSSL_VERSION_NUMBER < 0x30000000L /* Memory management of bp, qq and bg is transferred to DSA object */ rc = DSA_set0_pqg(key->dsa, bp, bq, bg); if (rc == 0) { @@ -1532,39 +1534,43 @@ int pki_privkey_build_dss(ssh_key key, DSA_free(key->dsa); return SSH_ERROR; #else - param_bld = OSSL_PARAM_BLD_new(); - if (param_bld == NULL) - goto err; - - pb = ssh_make_string_bn(p); - qb = ssh_make_string_bn(q); - gb = ssh_make_string_bn(g); - pubb = ssh_make_string_bn(pubkey); - privb = ssh_make_string_bn(privkey); - - rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_P, pb); - if (rc != 1) - goto err; - rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_Q, qb); - if (rc != 1) - goto err; - rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_G, gb); - if (rc != 1) - goto err; - rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PUB_KEY, pubb); - if (rc != 1) - goto err; - rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PRIV_KEY, privb); - if (rc != 1) - goto err; + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_P, bp); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; + } + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_Q, bq); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; + } + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_G, bg); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; + } + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PUB_KEY, bpub_key); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; + } + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PRIV_KEY, bpriv_key); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; + } rc = evp_build_pkey("DSA", param_bld, &(key->key), EVP_PKEY_KEYPAIR); + +fail: OSSL_PARAM_BLD_free(param_bld); + bignum_safe_free(bp); + bignum_safe_free(bq); + bignum_safe_free(bg); + bignum_safe_free(bpub_key); + bignum_safe_free(bpriv_key); return rc; -err: - OSSL_PARAM_BLD_free(param_bld); - return -1; #endif /* OPENSSL_VERSION_NUMBER */ } @@ -1574,18 +1580,18 @@ int pki_pubkey_build_dss(ssh_key key, ssh_string g, ssh_string pubkey) { int rc; -#if OPENSSL_VERSION_NUMBER < 0x30000000L BIGNUM *bp = NULL, *bq = NULL, *bg = NULL, *bpub_key = NULL; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + OSSL_PARAM_BLD *param_bld = OSSL_PARAM_BLD_new(); + if (param_bld == NULL) { + return SSH_ERROR; + } #else - const BIGNUM *pb, *qb, *gb, *pubb; - OSSL_PARAM_BLD *param_bld; -#endif /* OPENSSL_VERSION_NUMBER */ - -#if OPENSSL_VERSION_NUMBER < 0x30000000L key->dsa = DSA_new(); if (key->dsa == NULL) { return SSH_ERROR; } +#endif /* OPENSSL_VERSION_NUMBER */ bp = ssh_make_string_bn(p); bq = ssh_make_string_bn(q); @@ -1593,9 +1599,11 @@ int pki_pubkey_build_dss(ssh_key key, bpub_key = ssh_make_string_bn(pubkey); if (bp == NULL || bq == NULL || bg == NULL || bpub_key == NULL) { + rc = SSH_ERROR; goto fail; } +#if OPENSSL_VERSION_NUMBER < 0x30000000L /* Memory management of bp, bq and bg is transferred to DSA object */ rc = DSA_set0_pqg(key->dsa, bp, bq, bg); if (rc == 0) { @@ -1613,35 +1621,37 @@ int pki_pubkey_build_dss(ssh_key key, DSA_free(key->dsa); return SSH_ERROR; #else - param_bld = OSSL_PARAM_BLD_new(); - if (param_bld == NULL) - goto err; - - pb = ssh_make_string_bn(p); - qb = ssh_make_string_bn(q); - gb = ssh_make_string_bn(g); - pubb = ssh_make_string_bn(pubkey); - - rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_P, pb); - if (rc != 1) - goto err; - rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_Q, qb); - if (rc != 1) - goto err; - rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_G, gb); - if (rc != 1) - goto err; - rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PUB_KEY, pubb); - if (rc != 1) - goto err; + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_P, bp); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; + } + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_Q, bq); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; + } + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_G, bg); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; + } + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PUB_KEY, bpub_key); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; + } rc = evp_build_pkey("DSA", param_bld, &(key->key), EVP_PKEY_PUBLIC_KEY); + +fail: OSSL_PARAM_BLD_free(param_bld); + bignum_safe_free(bp); + bignum_safe_free(bq); + bignum_safe_free(bg); + bignum_safe_free(bpub_key); return rc; -err: - OSSL_PARAM_BLD_free(param_bld); - return -1; #endif /* OPENSSL_VERSION_NUMBER */ } @@ -1654,18 +1664,18 @@ int pki_privkey_build_rsa(ssh_key key, ssh_string q) { int rc; -#if OPENSSL_VERSION_NUMBER < 0x30000000L BIGNUM *be, *bn, *bd/*, *biqmp*/, *bp, *bq; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + OSSL_PARAM_BLD *param_bld = OSSL_PARAM_BLD_new(); + if (param_bld == NULL) { + return SSH_ERROR; + } #else - const BIGNUM *nb, *eb, *db, *pb, *qb; - OSSL_PARAM_BLD *param_bld; -#endif /* OPENSSL_VERSION_NUMBER */ - -#if OPENSSL_VERSION_NUMBER < 0x30000000L key->rsa = RSA_new(); if (key->rsa == NULL) { return SSH_ERROR; } +#endif /* OPENSSL_VERSION_NUMBER */ bn = ssh_make_string_bn(n); be = ssh_make_string_bn(e); @@ -1675,9 +1685,11 @@ int pki_privkey_build_rsa(ssh_key key, bq = ssh_make_string_bn(q); if (be == NULL || bn == NULL || bd == NULL || /*biqmp == NULL ||*/ bp == NULL || bq == NULL) { + rc = SSH_ERROR; goto fail; } +#if OPENSSL_VERSION_NUMBER < 0x30000000L /* Memory management of be, bn and bd is transferred to RSA object */ rc = RSA_set0_key(key->rsa, bn, be, bd); if (rc == 0) { @@ -1702,41 +1714,49 @@ int pki_privkey_build_rsa(ssh_key key, RSA_free(key->rsa); return SSH_ERROR; #else - param_bld = OSSL_PARAM_BLD_new(); - if (param_bld == NULL) - goto err; - - nb = ssh_make_string_bn(n); - eb = ssh_make_string_bn(e); - db = ssh_make_string_bn(d); - pb = ssh_make_string_bn(p); - qb = ssh_make_string_bn(q); - - rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_N, nb); - if (rc != 1) - goto err; - rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_E, eb); - if (rc != 1) - goto err; - rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_D, db); - if (rc != 1) - goto err; + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_N, bn); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; + } + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_E, be); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; + } + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_D, bd); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; + } rc = evp_build_pkey("RSA", param_bld, &(key->key), EVP_PKEY_KEYPAIR); - OSSL_PARAM_BLD_free(param_bld); + if (rc != SSH_OK) { + rc = SSH_ERROR; + goto fail; + } - rc = EVP_PKEY_set_bn_param(key->key, OSSL_PKEY_PARAM_RSA_FACTOR1, pb); - if (rc != 1) - goto err; + rc = EVP_PKEY_set_bn_param(key->key, OSSL_PKEY_PARAM_RSA_FACTOR1, bp); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; + } - rc = EVP_PKEY_set_bn_param(key->key, OSSL_PKEY_PARAM_RSA_FACTOR2, qb); - if (rc != 1) - goto err; + rc = EVP_PKEY_set_bn_param(key->key, OSSL_PKEY_PARAM_RSA_FACTOR2, bq); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; + } - return rc; -err: +fail: OSSL_PARAM_BLD_free(param_bld); - return -1; + bignum_safe_free(bn); + bignum_safe_free(be); + bignum_safe_free(bd); + bignum_safe_free(bp); + bignum_safe_free(bq); + + return rc; #endif /* OPENSSL_VERSION_NUMBER */ } @@ -1744,25 +1764,27 @@ int pki_pubkey_build_rsa(ssh_key key, ssh_string e, ssh_string n) { int rc; -#if OPENSSL_VERSION_NUMBER < 0x30000000L BIGNUM *be = NULL, *bn = NULL; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + OSSL_PARAM_BLD *param_bld = OSSL_PARAM_BLD_new(); + if (param_bld == NULL) { + return SSH_ERROR; + } #else - const BIGNUM *eb, *nb; - OSSL_PARAM_BLD *param_bld; -#endif /* OPENSSL_VERSION_NUMBER */ - -#if OPENSSL_VERSION_NUMBER < 0x30000000L key->rsa = RSA_new(); if (key->rsa == NULL) { return SSH_ERROR; } +#endif /* OPENSSL_VERSION_NUMBER */ be = ssh_make_string_bn(e); bn = ssh_make_string_bn(n); if (be == NULL || bn == NULL) { + rc = SSH_ERROR; goto fail; } +#if OPENSSL_VERSION_NUMBER < 0x30000000L /* Memory management of bn and be is transferred to RSA object */ rc = RSA_set0_key(key->rsa, bn, be, NULL); if (rc == 0) { @@ -1774,27 +1796,25 @@ int pki_pubkey_build_rsa(ssh_key key, RSA_free(key->rsa); return SSH_ERROR; #else - nb = ssh_make_string_bn(n); - eb = ssh_make_string_bn(e); - - param_bld = OSSL_PARAM_BLD_new(); - if (param_bld == NULL) - goto err; - - rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_N, nb); - if (rc != 1) - goto err; - rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_E, eb); - if (rc != 1) - goto err; + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_N, bn); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; + } + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_E, be); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; + } rc = evp_build_pkey("RSA", param_bld, &(key->key), EVP_PKEY_PUBLIC_KEY); + +fail: OSSL_PARAM_BLD_free(param_bld); + bignum_safe_free(bn); + bignum_safe_free(be); return rc; -err: - OSSL_PARAM_BLD_free(param_bld); - return -1; #endif /* OPENSSL_VERSION_NUMBER */ } @@ -2030,7 +2050,7 @@ ssh_string pki_publickey_to_blob(const ssh_key key) #if 0 const void *pubkey; size_t pubkey_len; - OSSL_PARAM *params, *locate_param; + OSSL_PARAM *params = NULL, *locate_param = NULL; #endif /* OPENSSL_VERSION_NUMBER */ type_s = ssh_string_from_char(pki_key_ecdsa_nid_to_char(key->ecdsa_nid)); @@ -2062,13 +2082,6 @@ ssh_string pki_publickey_to_blob(const ssh_key key) e = make_ecpoint_string(EC_KEY_get0_group(key->ecdsa), EC_KEY_get0_public_key(key->ecdsa)); #else - rc = ssh_buffer_add_ssh_string(buffer, type_s); - SSH_STRING_FREE(type_s); - if (rc < 0) { - SSH_BUFFER_FREE(buffer); - return NULL; - } - rc = EVP_PKEY_todata(key->key, EVP_PKEY_PUBLIC_KEY, ¶ms); if (rc < 0) { OSSL_PARAM_free(params); @@ -2089,7 +2102,6 @@ ssh_string pki_publickey_to_blob(const ssh_key key) rc = OSSL_PARAM_get_octet_string_ptr(locate_param, &pubkey, &pubkey_len); if (rc != 1) { OSSL_PARAM_free(params); - OSSL_PARAM_free(locate_param); goto fail; } @@ -2107,7 +2119,6 @@ ssh_string pki_publickey_to_blob(const ssh_key key) #if 0 if (memcpy(ssh_string_data(e), pubkey, pubkey_len) == NULL) { OSSL_PARAM_free(params); - OSSL_PARAM_free(locate_param); goto fail; } #endif /* OPENSSL_VERSION_NUMBER */ @@ -2119,7 +2130,6 @@ ssh_string pki_publickey_to_blob(const ssh_key key) */ #if 0 OSSL_PARAM_free(params); - OSSL_PARAM_free(locate_param); #endif /* OPENSSL_VERSION_NUMBER */ goto fail; } @@ -2133,13 +2143,12 @@ ssh_string pki_publickey_to_blob(const ssh_key key) */ #if 0 OSSL_PARAM_free(params); - OSSL_PARAM_free(locate_param); #endif /* OPENSSL_VERSION_NUMBER */ - if (key->type == SSH_KEYTYPE_SK_ECDSA && - ssh_buffer_add_ssh_string(buffer, key->sk_application) < 0) { - goto fail; - } + if (key->type == SSH_KEYTYPE_SK_ECDSA && + ssh_buffer_add_ssh_string(buffer, key->sk_application) < 0) { + goto fail; + } break; } @@ -3166,8 +3175,12 @@ int pki_verify_data_signature(ssh_signature signature, unsigned char *raw_sig_data = NULL; unsigned int raw_sig_len; + /* Function return code + * Do not change this variable throughout the function until the signature + * is successfully verified! + */ int rc = SSH_ERROR; - int evp_rc; + int ok; if (pubkey == NULL || ssh_key_is_private(pubkey) || input == NULL || signature == NULL || (signature->raw_sig == NULL @@ -3182,8 +3195,8 @@ int pki_verify_data_signature(ssh_signature signature, } /* Check if public key and hash type are compatible */ - rc = pki_key_check_hash_compatible(pubkey, signature->hash_type); - if (rc != SSH_OK) { + ok = pki_key_check_hash_compatible(pubkey, signature->hash_type); + if (ok != SSH_OK) { return SSH_ERROR; } @@ -3228,8 +3241,8 @@ int pki_verify_data_signature(ssh_signature signature, } /* Verify the signature */ - evp_rc = EVP_DigestVerifyInit(ctx, NULL, md, NULL, pkey); - if (evp_rc != 1){ + ok = EVP_DigestVerifyInit(ctx, NULL, md, NULL, pkey); + if (ok != 1){ SSH_LOG(SSH_LOG_TRACE, "EVP_DigestVerifyInit() failed: %s", ERR_error_string(ERR_get_error(), NULL)); @@ -3237,32 +3250,30 @@ int pki_verify_data_signature(ssh_signature signature, } #ifdef HAVE_OPENSSL_EVP_DIGESTVERIFY - evp_rc = EVP_DigestVerify(ctx, raw_sig_data, raw_sig_len, input, input_len); + ok = EVP_DigestVerify(ctx, raw_sig_data, raw_sig_len, input, input_len); #else - evp_rc = EVP_DigestVerifyUpdate(ctx, input, input_len); - if (evp_rc != 1) { + ok = EVP_DigestVerifyUpdate(ctx, input, input_len); + if (ok != 1) { SSH_LOG(SSH_LOG_TRACE, "EVP_DigestVerifyUpdate() failed: %s", ERR_error_string(ERR_get_error(), NULL)); goto out; } - evp_rc = EVP_DigestVerifyFinal(ctx, raw_sig_data, raw_sig_len); + ok = EVP_DigestVerifyFinal(ctx, raw_sig_data, raw_sig_len); #endif - if (evp_rc == 1) { - SSH_LOG(SSH_LOG_TRACE, "Signature valid"); - rc = SSH_OK; - } else { + if (ok != 1) { SSH_LOG(SSH_LOG_TRACE, "Signature invalid: %s", ERR_error_string(ERR_get_error(), NULL)); - rc = SSH_ERROR; + goto out; } + SSH_LOG(SSH_LOG_TRACE, "Signature valid"); + rc = SSH_OK; + out: - if (ctx != NULL) { - EVP_MD_CTX_free(ctx); - } + EVP_MD_CTX_free(ctx); EVP_PKEY_free(pkey); return rc; } @@ -3425,6 +3436,7 @@ ssh_signature pki_do_sign_hash(const ssh_key privkey, } #endif /* HAVE_OPENSSL_ED25519 */ +#ifdef WITH_PKCS11_URI /** * @internal * @@ -3592,5 +3604,6 @@ int pki_uri_import(const char *uri_name, return SSH_ERROR; } +#endif /* WITH_PKCS11_URI */ #endif /* _PKI_CRYPTO_H */ diff --git a/libssh/src/pki_ed25519_common.c b/libssh/src/pki_ed25519_common.c index 7aa05269..bdc6f6bb 100644 --- a/libssh/src/pki_ed25519_common.c +++ b/libssh/src/pki_ed25519_common.c @@ -137,7 +137,7 @@ int pki_ed25519_key_cmp(const ssh_key k1, * * @return SSH_ERROR on error, SSH_OK on success */ -int pki_ed25519_key_dup(ssh_key new, const ssh_key key) +int pki_ed25519_key_dup(ssh_key new_key, const ssh_key key) { if (key->ed25519_privkey == NULL && key->ed25519_pubkey == NULL) { return SSH_ERROR; @@ -147,29 +147,29 @@ int pki_ed25519_key_dup(ssh_key new, const ssh_key key) #ifdef HAVE_OPENSSL_ED25519 /* In OpenSSL implementation, the private key is the original private * seed, without the public key. */ - new->ed25519_privkey = malloc(ED25519_KEY_LEN); + new_key->ed25519_privkey = malloc(ED25519_KEY_LEN); #else /* In the internal implementation, the private key is the concatenation * of the private seed with the public key. */ - new->ed25519_privkey = malloc(2 * ED25519_KEY_LEN); + new_key->ed25519_privkey = malloc(2 * ED25519_KEY_LEN); #endif - if (new->ed25519_privkey == NULL) { + if (new_key->ed25519_privkey == NULL) { return SSH_ERROR; } #ifdef HAVE_OPENSSL_ED25519 - memcpy(new->ed25519_privkey, key->ed25519_privkey, ED25519_KEY_LEN); + memcpy(new_key->ed25519_privkey, key->ed25519_privkey, ED25519_KEY_LEN); #else - memcpy(new->ed25519_privkey, key->ed25519_privkey, 2 * ED25519_KEY_LEN); + memcpy(new_key->ed25519_privkey, key->ed25519_privkey, 2 * ED25519_KEY_LEN); #endif } if (key->ed25519_pubkey != NULL) { - new->ed25519_pubkey = malloc(ED25519_KEY_LEN); - if (new->ed25519_pubkey == NULL) { - SAFE_FREE(new->ed25519_privkey); + new_key->ed25519_pubkey = malloc(ED25519_KEY_LEN); + if (new_key->ed25519_pubkey == NULL) { + SAFE_FREE(new_key->ed25519_privkey); return SSH_ERROR; } - memcpy(new->ed25519_pubkey, key->ed25519_pubkey, ED25519_KEY_LEN); + memcpy(new_key->ed25519_pubkey, key->ed25519_pubkey, ED25519_KEY_LEN); } return SSH_OK; diff --git a/libssh/src/pki_gcrypt.c b/libssh/src/pki_gcrypt.c index b619b1a3..418a46b3 100644 --- a/libssh/src/pki_gcrypt.c +++ b/libssh/src/pki_gcrypt.c @@ -1370,9 +1370,9 @@ ssh_key pki_key_dup(const ssh_key key, int demote) } static int pki_key_generate(ssh_key key, int parameter, const char *type_s, int type){ - gcry_sexp_t parms; + gcry_sexp_t params; int rc; - rc = gcry_sexp_build(&parms, + rc = gcry_sexp_build(¶ms, NULL, "(genkey(%s(nbits %d)(transient-key)))", type_s, @@ -1381,20 +1381,20 @@ static int pki_key_generate(ssh_key key, int parameter, const char *type_s, int return SSH_ERROR; switch (type) { case SSH_KEYTYPE_RSA: - rc = gcry_pk_genkey(&key->rsa, parms); + rc = gcry_pk_genkey(&key->rsa, params); break; case SSH_KEYTYPE_DSS: - rc = gcry_pk_genkey(&key->dsa, parms); + rc = gcry_pk_genkey(&key->dsa, params); break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: - rc = gcry_pk_genkey(&key->ecdsa, parms); + rc = gcry_pk_genkey(&key->ecdsa, params); break; default: assert (! "reached"); } - gcry_sexp_release(parms); + gcry_sexp_release(params); if (rc != 0) return SSH_ERROR; return SSH_OK; @@ -1524,8 +1524,8 @@ int pki_key_compare(const ssh_key k1, break; case SSH_KEYTYPE_ED25519: case SSH_KEYTYPE_SK_ED25519: - /* ed25519 keys handled globaly */ - return 0; + /* ed25519 keys handled globally */ + return 0; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: @@ -2543,6 +2543,7 @@ int ssh_key_size(ssh_key key) } } +#ifdef WITH_PKCS11_URI int pki_uri_import(const char *uri_name, ssh_key *key, enum ssh_key_e key_type) { (void) uri_name; @@ -2552,4 +2553,5 @@ int pki_uri_import(const char *uri_name, ssh_key *key, enum ssh_key_e key_type) "gcrypt does not support PKCS #11"); return SSH_ERROR; } +#endif /* WITH_PKCS11_URI */ #endif /* HAVE_LIBGCRYPT */ diff --git a/libssh/src/pki_mbedcrypto.c b/libssh/src/pki_mbedcrypto.c index 4439b3cd..cb9d3228 100644 --- a/libssh/src/pki_mbedcrypto.c +++ b/libssh/src/pki_mbedcrypto.c @@ -1936,6 +1936,7 @@ int ssh_key_size(ssh_key key) } } +#ifdef WITH_PKCS11_URI int pki_uri_import(const char *uri_name, ssh_key *key, enum ssh_key_e key_type) { (void) uri_name; @@ -1945,4 +1946,5 @@ int pki_uri_import(const char *uri_name, ssh_key *key, enum ssh_key_e key_type) "mbedcrypto does not support PKCS #11"); return SSH_ERROR; } +#endif /* WITH_PKCS11_URI */ #endif /* HAVE_LIBMBEDCRYPTO */ diff --git a/libssh/src/poll.c b/libssh/src/poll.c index 1246f456..828f5e0a 100644 --- a/libssh/src/poll.c +++ b/libssh/src/poll.c @@ -44,7 +44,7 @@ #endif /** - * @defgroup libssh_poll The SSH poll functions. + * @defgroup libssh_poll The SSH poll functions * @ingroup libssh * * Add a generic way to handle sockets asynchronously. @@ -68,7 +68,7 @@ struct ssh_poll_handle_struct { size_t idx; } x; short events; - int lock; + uint32_t lock_cnt; ssh_poll_callback cb; void *cb_data; }; @@ -287,7 +287,7 @@ static int bsd_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) if (rc < 0) { return -1; } - /* A timeout occured */ + /* A timeout occurred */ if (rc == 0) { return 0; } @@ -412,7 +412,8 @@ short ssh_poll_get_events(ssh_poll_handle p) /** * @brief Set the events of a poll object. The events will also be propagated - * to an associated poll context. + * to an associated poll context unless the fd is locked. In that case, + * only the POLLOUT can be set. * * @param p Pointer to an already allocated poll object. * @param events Poll events. @@ -420,8 +421,14 @@ short ssh_poll_get_events(ssh_poll_handle p) void ssh_poll_set_events(ssh_poll_handle p, short events) { p->events = events; - if (p->ctx != NULL && !p->lock) { - p->ctx->pollfds[p->x.idx].events = events; + if (p->ctx != NULL) { + if (p->lock_cnt == 0) { + p->ctx->pollfds[p->x.idx].events = events; + } else if (!(p->ctx->pollfds[p->x.idx].events & POLLOUT)) { + /* if locked, allow only setting POLLOUT to prevent recursive + * callbacks */ + p->ctx->pollfds[p->x.idx].events = events & POLLOUT; + } } } @@ -621,7 +628,7 @@ int ssh_poll_ctx_add(ssh_poll_ctx ctx, ssh_poll_handle p) */ int ssh_poll_ctx_add_socket (ssh_poll_ctx ctx, ssh_socket s) { - ssh_poll_handle p; + ssh_poll_handle p = NULL; int ret; p = ssh_socket_get_poll_handle(s); @@ -691,6 +698,15 @@ int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout) return SSH_ERROR; } + /* Ignore any pollin events on locked sockets as that means we are called + * recursively and we only want process the POLLOUT events here to flush + * output buffer */ + for (i = 0; i < ctx->polls_used; i++) { + /* The lock prevents invoking POLLIN events: drop them now */ + if (ctx->pollptrs[i]->lock_cnt > 0) { + ctx->pollfds[i].events &= ~POLLIN; + } + } ssh_timestamp_init(&ts); do { int tm = ssh_timeout_update(&ts, timeout); @@ -706,7 +722,7 @@ int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout) used = ctx->polls_used; for (i = 0; i < used && rc > 0; ) { - if (!ctx->pollfds[i].revents || ctx->pollptrs[i]->lock) { + if (ctx->pollfds[i].revents == 0) { i++; } else { int ret; @@ -716,7 +732,7 @@ int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout) revents = ctx->pollfds[i].revents; /* avoid having any event caught during callback */ ctx->pollfds[i].events = 0; - p->lock = 1; + p->lock_cnt++; if (p->cb && (ret = p->cb(p, fd, revents, p->cb_data)) < 0) { if (ret == -2) { return -1; @@ -727,7 +743,7 @@ int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout) } else { ctx->pollfds[i].revents = 0; ctx->pollfds[i].events = p->events; - p->lock = 0; + p->lock_cnt--; i++; } @@ -981,7 +997,7 @@ int ssh_event_add_connector(ssh_event event, ssh_connector connector) * @returns SSH_OK on success. * SSH_ERROR Error happened during the poll. Check errno to get more * details about why it failed. - * SSH_AGAIN Timeout occured + * SSH_AGAIN Timeout occurred */ int ssh_event_dopoll(ssh_event event, int timeout) { diff --git a/libssh/src/scp.c b/libssh/src/scp.c index ef5aa139..103822ce 100644 --- a/libssh/src/scp.c +++ b/libssh/src/scp.c @@ -991,7 +991,7 @@ int ssh_scp_accept_request(ssh_scp scp) * * @param[in] size The size of the buffer. * - * @returns The nNumber of bytes read, SSH_ERROR if an error occurred + * @returns The number of bytes read, SSH_ERROR if an error occurred * while reading. */ int ssh_scp_read(ssh_scp scp, void *buffer, size_t size) diff --git a/libssh/src/server.c b/libssh/src/server.c index 04949a94..b978fc17 100644 --- a/libssh/src/server.c +++ b/libssh/src/server.c @@ -92,7 +92,11 @@ int server_set_kex(ssh_session session) size_t len; int ok; - ZERO_STRUCTP(server); + /* Skip if already set, for example for the rekey or when we do the guessing + * it could have been already used to make some protocol decisions. */ + if (server->methods[0] != NULL) { + return SSH_OK; + } ok = ssh_get_random(server->cookie, 16, 0); if (!ok) { @@ -335,116 +339,119 @@ ssh_get_key_params(ssh_session session, * @brief A function to be called each time a step has been done in the * connection. */ -static void ssh_server_connection_callback(ssh_session session){ +static void ssh_server_connection_callback(ssh_session session) +{ int rc; - switch(session->session_state){ - case SSH_SESSION_STATE_NONE: - case SSH_SESSION_STATE_CONNECTING: - case SSH_SESSION_STATE_SOCKET_CONNECTED: - break; - case SSH_SESSION_STATE_BANNER_RECEIVED: - if (session->clientbanner == NULL) { - goto error; - } - set_status(session, 0.4f); - SSH_LOG(SSH_LOG_PROTOCOL, - "SSH client banner: %s", session->clientbanner); - - /* Here we analyze the different protocols the server allows. */ - rc = ssh_analyze_banner(session, 1); - if (rc < 0) { - ssh_set_error(session, SSH_FATAL, - "No version of SSH protocol usable (banner: %s)", - session->clientbanner); - goto error; - } + switch (session->session_state) { + case SSH_SESSION_STATE_NONE: + case SSH_SESSION_STATE_CONNECTING: + case SSH_SESSION_STATE_SOCKET_CONNECTED: + break; + case SSH_SESSION_STATE_BANNER_RECEIVED: + if (session->clientbanner == NULL) { + goto error; + } + set_status(session, 0.4f); + SSH_LOG(SSH_LOG_PROTOCOL, + "SSH client banner: %s", session->clientbanner); + + /* Here we analyze the different protocols the server allows. */ + rc = ssh_analyze_banner(session, 1); + if (rc < 0) { + ssh_set_error(session, SSH_FATAL, + "No version of SSH protocol usable (banner: %s)", + session->clientbanner); + goto error; + } - /* from now, the packet layer is handling incoming packets */ - ssh_packet_register_socket_callback(session, session->socket); + /* from now, the packet layer is handling incoming packets */ + ssh_packet_register_socket_callback(session, session->socket); - ssh_packet_set_default_callbacks(session); - set_status(session, 0.5f); - session->session_state=SSH_SESSION_STATE_INITIAL_KEX; - if (ssh_send_kex(session, 1) < 0) { + ssh_packet_set_default_callbacks(session); + set_status(session, 0.5f); + session->session_state = SSH_SESSION_STATE_INITIAL_KEX; + if (ssh_send_kex(session) < 0) { + goto error; + } + break; + case SSH_SESSION_STATE_INITIAL_KEX: + /* TODO: This state should disappear in favor of get_key handle */ + break; + case SSH_SESSION_STATE_KEXINIT_RECEIVED: + set_status(session, 0.6f); + if ((session->flags & SSH_SESSION_FLAG_KEXINIT_SENT) == 0) { + if (server_set_kex(session) == SSH_ERROR) goto error; - } - break; - case SSH_SESSION_STATE_INITIAL_KEX: - /* TODO: This state should disappear in favor of get_key handle */ - break; - case SSH_SESSION_STATE_KEXINIT_RECEIVED: - set_status(session,0.6f); - if(session->next_crypto->server_kex.methods[0]==NULL){ - if(server_set_kex(session) == SSH_ERROR) - goto error; - /* We are in a rekeying, so we need to send the server kex */ - if(ssh_send_kex(session, 1) < 0) - goto error; - } - ssh_list_kex(&session->next_crypto->client_kex); // log client kex - if (ssh_kex_select_methods(session) < 0) { + /* We are in a rekeying, so we need to send the server kex */ + if (ssh_send_kex(session) < 0) goto error; - } - if (crypt_set_algorithms_server(session) == SSH_ERROR) + } + ssh_list_kex(&session->next_crypto->client_kex); // log client kex + if (ssh_kex_select_methods(session) < 0) { + goto error; + } + if (crypt_set_algorithms_server(session) == SSH_ERROR) + goto error; + set_status(session, 0.8f); + session->session_state = SSH_SESSION_STATE_DH; + break; + case SSH_SESSION_STATE_DH: + if (session->dh_handshake_state == DH_STATE_FINISHED) { + + rc = ssh_packet_set_newkeys(session, SSH_DIRECTION_IN); + if (rc != SSH_OK) { goto error; - set_status(session,0.8f); - session->session_state=SSH_SESSION_STATE_DH; - break; - case SSH_SESSION_STATE_DH: - if(session->dh_handshake_state==DH_STATE_FINISHED){ - - rc = ssh_packet_set_newkeys(session, SSH_DIRECTION_IN); - if (rc != SSH_OK) { - goto error; - } + } + /* + * If the client supports extension negotiation, we will send + * our supported extensions now. This is the first message after + * sending NEWKEYS message and after turning on crypto. + */ + if (session->extensions & SSH_EXT_NEGOTIATION && + session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { /* - * If the client supports extension negotiation, we will send - * our supported extensions now. This is the first message after - * sending NEWKEYS message and after turning on crypto. + * Only send an SSH_MSG_EXT_INFO message the first time the + * client undergoes NEWKEYS. It is unexpected for this message + * to be sent upon rekey, and may cause clients to log error + * messages. + * + * The session_state can not be used for this purpose because it + * is re-set to SSH_SESSION_STATE_KEXINIT_RECEIVED during rekey. + * So, use the connected flag which transitions from non-zero + * below. + * + * See also: + * - https://bugzilla.mindrot.org/show_bug.cgi?id=2929 */ - if (session->extensions & SSH_EXT_NEGOTIATION && - session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { - - /* - * Only send an SSH_MSG_EXT_INFO message the first time the client - * undergoes NEWKEYS. It is unexpected for this message to be sent - * upon rekey, and may cause clients to log error messages. - * - * The session_state can not be used for this purpose because it is - * re-set to SSH_SESSION_STATE_KEXINIT_RECEIVED during rekey. So, - * use the connected flag which transitions from non-zero below. - * - * See also: - * - https://bugzilla.mindrot.org/show_bug.cgi?id=2929 - */ - if (session->connected == 0) { - ssh_server_send_extensions(session); - } + if (session->connected == 0) { + ssh_server_send_extensions(session); } + } - set_status(session,1.0f); - session->connected = 1; - session->session_state=SSH_SESSION_STATE_AUTHENTICATING; - if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) - session->session_state = SSH_SESSION_STATE_AUTHENTICATED; + set_status(session, 1.0f); + session->connected = 1; + session->session_state = SSH_SESSION_STATE_AUTHENTICATING; + if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) + session->session_state = SSH_SESSION_STATE_AUTHENTICATED; - } - break; - case SSH_SESSION_STATE_AUTHENTICATING: - break; - case SSH_SESSION_STATE_ERROR: - goto error; - default: - ssh_set_error(session,SSH_FATAL,"Invalid state %d",session->session_state); + } + break; + case SSH_SESSION_STATE_AUTHENTICATING: + break; + case SSH_SESSION_STATE_ERROR: + goto error; + default: + ssh_set_error(session, SSH_FATAL, "Invalid state %d", + session->session_state); } return; error: ssh_socket_close(session->socket); session->alive = 0; - session->session_state=SSH_SESSION_STATE_ERROR; + session->session_state = SSH_SESSION_STATE_ERROR; } /** @@ -458,16 +465,17 @@ static void ssh_server_connection_callback(ssh_session session){ * @param user is a pointer to session * @returns Number of bytes processed, or zero if the banner is not complete. */ -static size_t callback_receive_banner(const void *data, size_t len, void *user) { - char *buffer = (char *) data; - ssh_session session = (ssh_session) user; +static size_t callback_receive_banner(const void *data, size_t len, void *user) +{ + char *buffer = (char *)data; + ssh_session session = (ssh_session)user; char *str = NULL; size_t i; size_t processed = 0; for (i = 0; i < len; i++) { #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, @@ -476,11 +484,11 @@ static size_t callback_receive_banner(const void *data, size_t len, void *user) } #endif if (buffer[i] == '\r') { - buffer[i]='\0'; + buffer[i] = '\0'; } if (buffer[i] == '\n') { - buffer[i]='\0'; + buffer[i] = '\0'; str = strdup(buffer); /* number of bytes read */ @@ -493,10 +501,11 @@ static size_t callback_receive_banner(const void *data, size_t len, void *user) return processed; } - if(i > 127) { + if (i > 127) { /* Too big banner */ 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; } @@ -548,10 +557,14 @@ int ssh_send_issue_banner(ssh_session session, const ssh_string banner) } /* Do the banner and key exchange */ -int ssh_handle_key_exchange(ssh_session session) { +int ssh_handle_key_exchange(ssh_session session) +{ int rc; - if (session->session_state != SSH_SESSION_STATE_NONE) - goto pending; + + if (session->session_state != SSH_SESSION_STATE_NONE) { + goto pending; + } + rc = ssh_send_banner(session, 1); if (rc < 0) { return SSH_ERROR; @@ -562,27 +575,28 @@ int ssh_handle_key_exchange(ssh_session session) { session->ssh_connection_callback = ssh_server_connection_callback; session->session_state = SSH_SESSION_STATE_SOCKET_CONNECTED; ssh_socket_set_callbacks(session->socket,&session->socket_callbacks); - session->socket_callbacks.data=callback_receive_banner; - session->socket_callbacks.exception=ssh_socket_exception_callback; - session->socket_callbacks.userdata=session; + session->socket_callbacks.data = callback_receive_banner; + session->socket_callbacks.exception = ssh_socket_exception_callback; + session->socket_callbacks.userdata = session; rc = server_set_kex(session); if (rc < 0) { return SSH_ERROR; } - pending: +pending: rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER, - ssh_server_kex_termination,session); + ssh_server_kex_termination,session); SSH_LOG(SSH_LOG_PACKET, "ssh_handle_key_exchange: current state : %d", - session->session_state); - if (rc != SSH_OK) - return rc; + session->session_state); + if (rc != SSH_OK) { + return rc; + } if (session->session_state == SSH_SESSION_STATE_ERROR || session->session_state == SSH_SESSION_STATE_DISCONNECTED) { - return SSH_ERROR; + return SSH_ERROR; } - return SSH_OK; + return SSH_OK; } /* messages */ @@ -695,6 +709,13 @@ static int ssh_message_service_request_reply_default(ssh_message msg) { return ssh_message_service_reply_success(msg); } +/** + * @brief Sends SERVICE_ACCEPT to the client + * + * @param msg The message to reply to + * + * @returns SSH_OK when success otherwise SSH_ERROR + */ int ssh_message_service_reply_success(ssh_message msg) { ssh_session session; int rc; @@ -719,6 +740,15 @@ int ssh_message_service_reply_success(ssh_message msg) { return rc; } +/** + * @brief Send a global request success message + * + * @param msg The message + * + * @param bound_port The remote bind port + * + * @returns SSH_OK on success, otherwise SSH_ERROR + */ int ssh_message_global_request_reply_success(ssh_message msg, uint16_t bound_port) { int rc; @@ -797,6 +827,13 @@ int ssh_message_reply_default(ssh_message msg) { return -1; } +/** + * @brief Gets the service name from the service request message + * + * @param msg The service request message + * + * @returns the service name from the message + */ const char *ssh_message_service_service(ssh_message msg){ if (msg == NULL) { return NULL; @@ -828,7 +865,6 @@ ssh_key ssh_message_auth_pubkey(ssh_message msg) { return msg->auth_request.pubkey; } -/* Get the publickey of an auth request */ ssh_public_key ssh_message_auth_publickey(ssh_message msg){ if (msg == NULL) { return NULL; @@ -844,6 +880,13 @@ enum ssh_publickey_state_e ssh_message_auth_publickey_state(ssh_message msg){ return msg->auth_request.signature_state; } +/** + * @brief Check if the message is a keyboard-interactive response + * + * @param msg The message to check + * + * @returns 1 if the message is a response, otherwise 0 + */ int ssh_message_auth_kbdint_is_response(ssh_message msg) { if (msg == NULL) { return -1; @@ -853,6 +896,17 @@ int ssh_message_auth_kbdint_is_response(ssh_message msg) { } /* FIXME: methods should be unsigned */ +/** + * @brief Sets the supported authentication methods to a message + * + * @param msg The message + * + * @param methods Methods to set to the message. + * The supported methods are listed in ssh_set_auth_methods + * @see ssh_set_auth_methods + * + * @returns 0 on success, otherwise -1 + */ int ssh_message_auth_set_methods(ssh_message msg, int methods) { if (msg == NULL || msg->session == NULL) { return -1; @@ -973,6 +1027,17 @@ int ssh_message_auth_interactive_request(ssh_message msg, const char *name, return rc; } +/** + * @brief Sends SSH2_MSG_USERAUTH_SUCCESS or SSH2_MSG_USERAUTH_FAILURE message + * depending on the success of the authentication method + * + * @param session The session to reply to + * + * @param partial Denotes if the authentication process was partially completed + * (unsuccessful) + * + * @returns SSH_OK on success, otherwise SSH_ERROR + */ int ssh_auth_reply_success(ssh_session session, int partial) { struct ssh_crypto_struct *crypto = NULL; @@ -1022,7 +1087,17 @@ int ssh_message_auth_reply_success(ssh_message msg, int partial) { return ssh_auth_reply_success(msg->session, partial); } -/* Answer OK to a pubkey auth request */ +/** + * @brief Answer SSH2_MSG_USERAUTH_PK_OK to a pubkey authentication request + * + * @param msg The message + * + * @param algo The algorithm of the accepted public key + * + * @param pubkey The accepted public key + * + * @returns SSH_OK on success, otherwise SSH_ERROR + */ int ssh_message_auth_reply_pk_ok(ssh_message msg, ssh_string algo, ssh_string pubkey) { int rc; if (msg == NULL) { @@ -1043,6 +1118,13 @@ int ssh_message_auth_reply_pk_ok(ssh_message msg, ssh_string algo, ssh_string pu return rc; } +/** + * @brief Answer SSH2_MSG_USERAUTH_PK_OK to a pubkey authentication request + * + * @param msg The message + * + * @returns SSH_OK on success, otherwise SSH_ERROR + */ int ssh_message_auth_reply_pk_ok_simple(ssh_message msg) { ssh_string algo; ssh_string pubkey_blob = NULL; @@ -1193,6 +1275,13 @@ int ssh_execute_message_callbacks(ssh_session session){ return SSH_OK; } +/** + * @brief Sends a keepalive message to the session + * + * @param session The session to send the message to + * + * @returns SSH_OK + */ int ssh_send_keepalive(ssh_session session) { /* Client denies the request, so the error code is not meaningful */ diff --git a/libssh/src/session.c b/libssh/src/session.c index 6025c133..0fb758ce 100644 --- a/libssh/src/session.c +++ b/libssh/src/session.c @@ -43,7 +43,7 @@ #define FIRST_CHANNEL 42 // why not ? it helps to find bugs. /** - * @defgroup libssh_session The SSH session functions. + * @defgroup libssh_session The SSH session functions * @ingroup libssh * * Functions that manage a session. @@ -114,17 +114,23 @@ ssh_session ssh_new(void) SSH_OPT_FLAG_KBDINT_AUTH | SSH_OPT_FLAG_GSSAPI_AUTH; + session->opts.exp_flags = 0; + session->opts.identity = ssh_list_new(); if (session->opts.identity == NULL) { goto err; } + session->opts.identity_non_exp = ssh_list_new(); + if (session->opts.identity_non_exp == NULL) { + goto err; + } id = strdup("%d/id_ed25519"); if (id == NULL) { goto err; } - rc = ssh_list_append(session->opts.identity, id); + rc = ssh_list_append(session->opts.identity_non_exp, id); if (rc == SSH_ERROR) { goto err; } @@ -134,7 +140,7 @@ ssh_session ssh_new(void) if (id == NULL) { goto err; } - rc = ssh_list_append(session->opts.identity, id); + rc = ssh_list_append(session->opts.identity_non_exp, id); if (rc == SSH_ERROR) { goto err; } @@ -144,7 +150,7 @@ ssh_session ssh_new(void) if (id == NULL) { goto err; } - rc = ssh_list_append(session->opts.identity, id); + rc = ssh_list_append(session->opts.identity_non_exp, id); if (rc == SSH_ERROR) { goto err; } @@ -154,7 +160,7 @@ ssh_session ssh_new(void) if (id == NULL) { goto err; } - rc = ssh_list_append(session->opts.identity, id); + rc = ssh_list_append(session->opts.identity_non_exp, id); if (rc == SSH_ERROR) { goto err; } @@ -284,6 +290,17 @@ void ssh_free(ssh_session session) ssh_list_free(session->opts.identity); } + if (session->opts.identity_non_exp) { + char *id; + + for (id = ssh_list_pop_head(char *, session->opts.identity_non_exp); + id != NULL; + id = ssh_list_pop_head(char *, session->opts.identity_non_exp)) { + SAFE_FREE(id); + } + ssh_list_free(session->opts.identity_non_exp); + } + while ((b = ssh_list_pop_head(struct ssh_buffer_struct *, session->out_queue)) != NULL) { SSH_BUFFER_FREE(b); @@ -300,6 +317,7 @@ void ssh_free(ssh_session session) SAFE_FREE(session->clientbanner); SAFE_FREE(session->banner); SAFE_FREE(session->disconnect_message); + SAFE_FREE(session->peer_discon_msg); SAFE_FREE(session->opts.agent_socket); SAFE_FREE(session->opts.bindaddr); @@ -633,9 +651,10 @@ void ssh_set_fd_except(ssh_session session) { * * @return SSH_OK on success, SSH_ERROR otherwise. */ -int ssh_handle_packets(ssh_session session, int timeout) { - ssh_poll_handle spoll; - ssh_poll_ctx ctx; +int ssh_handle_packets(ssh_session session, int timeout) +{ + ssh_poll_handle spoll = NULL; + ssh_poll_ctx ctx = NULL; int tm = timeout; int rc; @@ -653,11 +672,12 @@ int ssh_handle_packets(ssh_session session, int timeout) { } if (timeout == SSH_TIMEOUT_USER) { - if (ssh_is_blocking(session)) - tm = ssh_make_milliseconds(session->opts.timeout, - session->opts.timeout_usec); - else - tm = 0; + if (ssh_is_blocking(session)) { + tm = ssh_make_milliseconds(session->opts.timeout, + session->opts.timeout_usec); + } else { + tm = 0; + } } rc = ssh_poll_ctx_dopoll(ctx, tm); if (rc == SSH_ERROR) { @@ -819,11 +839,11 @@ const char *ssh_get_disconnect_message(ssh_session session) { if (session->session_state != SSH_SESSION_STATE_DISCONNECTED) { ssh_set_error(session, SSH_REQUEST_DENIED, "Connection not closed yet"); - } else if(!session->discon_msg) { + } else if(!session->peer_discon_msg) { ssh_set_error(session, SSH_FATAL, "Connection correctly closed but no disconnect message"); } else { - return session->discon_msg; + return session->peer_discon_msg; } return NULL; @@ -1062,7 +1082,7 @@ void ssh_clean_pubkey_hash(unsigned char **hash) * @param[out] key A pointer to store the allocated key. You need to free * the key using ssh_key_free(). * - * @return SSH_OK on success, SSH_ERROR on errror. + * @return SSH_OK on success, SSH_ERROR on error. * * @see ssh_key_free() */ diff --git a/libssh/src/socket.c b/libssh/src/socket.c index 4e637ae1..99dcf8cc 100644 --- a/libssh/src/socket.c +++ b/libssh/src/socket.c @@ -65,8 +65,6 @@ struct sockaddr_un { #include "libssh/session.h" /** - * @internal - * * @defgroup libssh_socket The SSH socket functions. * @ingroup libssh * @@ -223,6 +221,15 @@ void ssh_socket_set_callbacks(ssh_socket s, ssh_socket_callbacks callbacks) s->callbacks = callbacks; } +void ssh_socket_set_connected(ssh_socket s, struct ssh_poll_handle_struct *p) +{ + s->state = SSH_SOCKET_CONNECTED; + /* POLLOUT is the event to wait for in a nonblocking connect */ + if (p != NULL) { + ssh_poll_set_events(p, POLLIN | POLLOUT); + } +} + /** * @brief SSH poll callback. This callback will be used when an event * caught on the socket. @@ -230,7 +237,7 @@ void ssh_socket_set_callbacks(ssh_socket s, ssh_socket_callbacks callbacks) * @param p Poll object this callback belongs to. * @param fd The raw socket. * @param revents The current poll events on the socket. - * @param userdata Userdata to be passed to the callback function, + * @param v_s Userdata to be passed to the callback function, * in this case the socket object. * * @return 0 on success, < 0 when the poll object has been removed @@ -252,7 +259,8 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, if (!ssh_socket_is_open(s)) { return -1; } - SSH_LOG(SSH_LOG_TRACE, "Poll callback on socket %d (%s%s%s), out buffer %d",fd, + SSH_LOG(SSH_LOG_TRACE, + "Poll callback on socket %d (%s%s%s), out buffer %" PRIu32, fd, (revents & POLLIN) ? "POLLIN ":"", (revents & POLLOUT) ? "POLLOUT ":"", (revents & POLLERR) ? "POLLERR":"", @@ -323,12 +331,13 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, /* Call the callback */ if (s->callbacks != NULL && s->callbacks->data != NULL) { + size_t processed; do { - nread = s->callbacks->data(ssh_buffer_get(s->in_buffer), - ssh_buffer_get_len(s->in_buffer), - s->callbacks->userdata); - ssh_buffer_pass_bytes(s->in_buffer, nread); - } while ((nread > 0) && (s->state == SSH_SOCKET_CONNECTED)); + processed = s->callbacks->data(ssh_buffer_get(s->in_buffer), + ssh_buffer_get_len(s->in_buffer), + s->callbacks->userdata); + ssh_buffer_pass_bytes(s->in_buffer, processed); + } while ((processed > 0) && (s->state == SSH_SOCKET_CONNECTED)); /* p may have been freed, so don't use it * anymore in this function */ @@ -345,10 +354,7 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, /* First, POLLOUT is a sign we may be connected */ if (s->state == SSH_SOCKET_CONNECTING) { SSH_LOG(SSH_LOG_PACKET, "Received POLLOUT in connecting state"); - s->state = SSH_SOCKET_CONNECTED; - if (p != NULL) { - ssh_poll_set_events(p, POLLOUT | POLLIN); - } + ssh_socket_set_connected(s, p); rc = ssh_socket_set_blocking(ssh_socket_get_fd(s)); if (rc < 0) { @@ -376,7 +382,7 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, ssh_socket_nonblocking_flush(s); } else if (s->callbacks != NULL && s->callbacks->controlflow != NULL) { /* Otherwise advertise the upper level that write can be done */ - SSH_LOG(SSH_LOG_TRACE,"sending control flow event"); + SSH_LOG(SSH_LOG_TRACE, "sending control flow event"); s->callbacks->controlflow(SSH_SOCKET_FLOW_WRITEWONTBLOCK, s->callbacks->userdata); } @@ -401,7 +407,7 @@ ssh_poll_handle ssh_socket_get_poll_handle(ssh_socket s) if (s->poll_handle) { return s->poll_handle; } - s->poll_handle = ssh_poll_new(s->fd,0,ssh_socket_pollcallback,s); + s->poll_handle = ssh_poll_new(s->fd, 0, ssh_socket_pollcallback, s); return s->poll_handle; } @@ -513,17 +519,23 @@ void ssh_socket_close(ssh_socket s) */ void ssh_socket_set_fd(ssh_socket s, socket_t fd) { + ssh_poll_handle h = NULL; + s->fd = fd; if (s->poll_handle) { ssh_poll_set_fd(s->poll_handle,fd); } else { s->state = SSH_SOCKET_CONNECTING; + h = ssh_socket_get_poll_handle(s); + if (h == NULL) { + return; + } /* POLLOUT is the event to wait for in a nonblocking connect */ - ssh_poll_set_events(ssh_socket_get_poll_handle(s), POLLOUT); + ssh_poll_set_events(h, POLLOUT); #ifdef _WIN32 - ssh_poll_add_events(ssh_socket_get_poll_handle(s), POLLWRNORM); + ssh_poll_add_events(h, POLLWRNORM); #endif } } @@ -557,9 +569,9 @@ static ssize_t ssh_socket_unbuffered_read(ssh_socket s, return -1; } if (s->fd_is_socket) { - rc = recv(s->fd,buffer, len, 0); + rc = recv(s->fd, buffer, len, 0); } else { - rc = read(s->fd,buffer, len); + rc = read(s->fd, buffer, len); } #ifdef _WIN32 s->last_errno = WSAGetLastError(); @@ -570,6 +582,8 @@ static ssize_t ssh_socket_unbuffered_read(ssh_socket s, if (rc < 0) { s->data_except = 1; + } else { + SSH_LOG(SSH_LOG_TRACE, "read %zd", rc); } return rc; @@ -607,12 +621,13 @@ static ssize_t ssh_socket_unbuffered_write(ssh_socket s, /* Reactive the POLLOUT detector in the poll multiplexer system */ if (s->poll_handle) { SSH_LOG(SSH_LOG_PACKET, "Enabling POLLOUT for socket"); - ssh_poll_set_events(s->poll_handle,ssh_poll_get_events(s->poll_handle) | POLLOUT); + ssh_poll_add_events(s->poll_handle, POLLOUT); } if (w < 0) { s->data_except = 1; } + SSH_LOG(SSH_LOG_TRACE, "wrote %zd", w); return w; } @@ -735,6 +750,8 @@ int ssh_socket_nonblocking_flush(ssh_socket s) /* Is there some data pending? */ len = ssh_buffer_get_len(s->out_buffer); if (s->poll_handle && len > 0) { + SSH_LOG(SSH_LOG_TRACE, + "did not send all the data, queuing pollout event"); /* force the poll system to catch pollout events */ ssh_poll_add_events(s->poll_handle, POLLOUT); @@ -906,9 +923,14 @@ ssh_execute_command(const char *command, socket_t in, socket_t out) */ shell = getenv("SHELL"); if (shell == NULL || shell[0] == '\0') { - /* Fall back to bash. There are issues with dash or - * whatever people tend to link to /bin/sh */ - shell = "/bin/bash"; + /* Fall back to the /bin/sh only if the bash is not available. But there are + * issues with dash or whatever people tend to link to /bin/sh */ + rc = access("/bin/bash", 0); + if (rc != 0) { + shell = "/bin/sh"; + } else { + shell = "/bin/bash"; + } } args[0] = shell; @@ -943,6 +965,7 @@ int ssh_socket_connect_proxycommand(ssh_socket s, const char *command) { socket_t pair[2]; + ssh_poll_handle h = NULL; int pid; int rc; @@ -965,10 +988,12 @@ ssh_socket_connect_proxycommand(ssh_socket s, const char *command) close(pair[0]); SSH_LOG(SSH_LOG_PROTOCOL, "ProxyCommand connection pipe: [%d,%d]",pair[0],pair[1]); ssh_socket_set_fd(s, pair[1]); - s->state=SSH_SOCKET_CONNECTED; - s->fd_is_socket=0; - /* POLLOUT is the event to wait for in a nonblocking connect */ - ssh_poll_set_events(ssh_socket_get_poll_handle(s), POLLIN | POLLOUT); + s->fd_is_socket = 0; + h = ssh_socket_get_poll_handle(s); + if (h == NULL) { + return SSH_ERROR; + } + ssh_socket_set_connected(s, h); if (s->callbacks && s->callbacks->connected) { s->callbacks->connected(SSH_SOCKET_CONNECTED_OK, 0, s->callbacks->userdata); } diff --git a/libssh/src/threads.c b/libssh/src/threads.c index 792b976d..7660b972 100644 --- a/libssh/src/threads.c +++ b/libssh/src/threads.c @@ -20,7 +20,7 @@ */ /** - * @defgroup libssh_threads The SSH threading functions. + * @defgroup libssh_threads The SSH threading functions * @ingroup libssh * * Threading with libssh diff --git a/libssh/src/token.c b/libssh/src/token.c index 0924d3bd..58b2f3e2 100644 --- a/libssh/src/token.c +++ b/libssh/src/token.c @@ -87,7 +87,7 @@ struct ssh_tokens_st *ssh_tokenize(const char *chain, char separator) return NULL; } - tokens->buffer= strdup(chain); + tokens->buffer = strdup(chain); if (tokens->buffer == NULL) { goto error; } diff --git a/libssh/src/wrapper.c b/libssh/src/wrapper.c index bff7bab3..d317dc4c 100644 --- a/libssh/src/wrapper.c +++ b/libssh/src/wrapper.c @@ -1,5 +1,5 @@ /* - * wrapper.c - wrapper for crytpo functions + * wrapper.c - wrapper for crypto functions * * This file is part of the SSH Library * @@ -150,15 +150,16 @@ static void cipher_free(struct ssh_cipher_struct *cipher) { SAFE_FREE(cipher); } -struct ssh_crypto_struct *crypto_new(void) { - struct ssh_crypto_struct *crypto; +struct ssh_crypto_struct *crypto_new(void) +{ + struct ssh_crypto_struct *crypto; - crypto = malloc(sizeof(struct ssh_crypto_struct)); - if (crypto == NULL) { - return NULL; - } - ZERO_STRUCTP(crypto); - return crypto; + crypto = malloc(sizeof(struct ssh_crypto_struct)); + if (crypto == NULL) { + return NULL; + } + ZERO_STRUCTP(crypto); + return crypto; } void crypto_free(struct ssh_crypto_struct *crypto) @@ -242,9 +243,32 @@ void crypto_free(struct ssh_crypto_struct *crypto) SAFE_FREE(crypto); } +static void +compression_enable(ssh_session session, + enum ssh_crypto_direction_e direction, + bool delayed) +{ + /* The delayed compression is turned on AFTER authentication. This means + * that we need to turn it on immediately in case of rekeying */ + if (delayed && !(session->flags & SSH_SESSION_FLAG_AUTHENTICATED)) { + if (direction == SSH_DIRECTION_IN) { + session->next_crypto->delayed_compress_in = 1; + } else { /* SSH_DIRECTION_OUT */ + session->next_crypto->delayed_compress_out = 1; + } + } else { + if (direction == SSH_DIRECTION_IN) { + session->next_crypto->do_compress_in = 1; + } else { /* SSH_DIRECTION_OUT */ + session->next_crypto->do_compress_out = 1; + } + } +} + static int crypt_set_algorithms2(ssh_session session) { const char *wanted = NULL; + const char *method = NULL; struct ssh_cipher_struct *ssh_ciphertab=ssh_get_ciphertab(); struct ssh_hmac_struct *ssh_hmactab=ssh_get_hmactab(); uint8_t i = 0; @@ -367,22 +391,29 @@ static int crypt_set_algorithms2(ssh_session session) session->next_crypto->in_hmac = ssh_hmactab[i].hmac_type; session->next_crypto->in_hmac_etm = ssh_hmactab[i].etm; - /* compression */ - cmp = strcmp(session->next_crypto->kex_methods[SSH_COMP_C_S], "zlib"); + /* compression: client */ + method = session->next_crypto->kex_methods[SSH_COMP_C_S]; + cmp = strcmp(method, "zlib"); if (cmp == 0) { - session->next_crypto->do_compress_out = 1; + SSH_LOG(SSH_LOG_PACKET, "enabling C->S compression"); + compression_enable(session, SSH_DIRECTION_OUT, false); } - cmp = strcmp(session->next_crypto->kex_methods[SSH_COMP_S_C], "zlib"); + cmp = strcmp(method, "zlib@openssh.com"); if (cmp == 0) { - session->next_crypto->do_compress_in = 1; + SSH_LOG(SSH_LOG_PACKET, "enabling C->S delayed compression"); + compression_enable(session, SSH_DIRECTION_OUT, true); } - cmp = strcmp(session->next_crypto->kex_methods[SSH_COMP_C_S], "zlib@openssh.com"); + + method = session->next_crypto->kex_methods[SSH_COMP_S_C]; + cmp = strcmp(method, "zlib"); if (cmp == 0) { - session->next_crypto->delayed_compress_out = 1; + SSH_LOG(SSH_LOG_PACKET, "enabling S->C compression"); + compression_enable(session, SSH_DIRECTION_IN, false); } - cmp = strcmp(session->next_crypto->kex_methods[SSH_COMP_S_C], "zlib@openssh.com"); + cmp = strcmp(method, "zlib@openssh.com"); if (cmp == 0) { - session->next_crypto->delayed_compress_in = 1; + SSH_LOG(SSH_LOG_PACKET, "enabling S->C delayed compression"); + compression_enable(session, SSH_DIRECTION_IN, true); } return SSH_OK; @@ -401,7 +432,6 @@ int crypt_set_algorithms_server(ssh_session session){ struct ssh_hmac_struct *ssh_hmactab=ssh_get_hmactab(); int cmp; - if (session == NULL) { return SSH_ERROR; } @@ -520,33 +550,27 @@ int crypt_set_algorithms_server(ssh_session session){ /* compression */ method = session->next_crypto->kex_methods[SSH_COMP_C_S]; - if(strcmp(method,"zlib") == 0){ - SSH_LOG(SSH_LOG_PACKET,"enabling C->S compression"); - session->next_crypto->do_compress_in=1; + cmp = strcmp(method, "zlib"); + if (cmp == 0) { + SSH_LOG(SSH_LOG_PACKET, "enabling C->S compression"); + compression_enable(session, SSH_DIRECTION_IN, false); } - if(strcmp(method,"zlib@openssh.com") == 0){ - SSH_LOG(SSH_LOG_PACKET,"enabling C->S delayed compression"); - - if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) { - session->next_crypto->do_compress_in = 1; - } else { - session->next_crypto->delayed_compress_in = 1; - } + cmp = strcmp(method, "zlib@openssh.com"); + if (cmp == 0) { + SSH_LOG(SSH_LOG_PACKET, "enabling C->S delayed compression"); + compression_enable(session, SSH_DIRECTION_IN, true); } method = session->next_crypto->kex_methods[SSH_COMP_S_C]; - if(strcmp(method,"zlib") == 0){ + cmp = strcmp(method, "zlib"); + if (cmp == 0) { SSH_LOG(SSH_LOG_PACKET, "enabling S->C compression"); - session->next_crypto->do_compress_out=1; + compression_enable(session, SSH_DIRECTION_OUT, false); } - if(strcmp(method,"zlib@openssh.com") == 0){ - SSH_LOG(SSH_LOG_PACKET,"enabling S->C delayed compression"); - - if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) { - session->next_crypto->do_compress_out = 1; - } else { - session->next_crypto->delayed_compress_out = 1; - } + cmp = strcmp(method, "zlib@openssh.com"); + if (cmp == 0) { + SSH_LOG(SSH_LOG_PACKET, "enabling S->C delayed compression"); + compression_enable(session, SSH_DIRECTION_OUT, true); } method = session->next_crypto->kex_methods[SSH_HOSTKEYS]; diff --git a/libssh/tests/CMakeLists.txt b/libssh/tests/CMakeLists.txt index 22a36f37..09b96100 100644 --- a/libssh/tests/CMakeLists.txt +++ b/libssh/tests/CMakeLists.txt @@ -73,9 +73,9 @@ if (CLIENT_TESTING) ) endif () -if (ARGP_LIBRARY) +if (ARGP_LIBRARIES) target_link_libraries(${TORTURE_LIBRARY} - ${ARGP_LIBRARY} + ${ARGP_LIBRARIES} ) endif() diff --git a/libssh/tests/benchmarks/bench1.sh b/libssh/tests/benchmarks/bench1.sh index 4458e9a7..21b7e6ec 100755 --- a/libssh/tests/benchmarks/bench1.sh +++ b/libssh/tests/benchmarks/bench1.sh @@ -7,7 +7,7 @@ echo "Cipher : $CIPHER ; Destination : $DEST (`ssh $DEST uname -a`)" echo "Local ssh version: `ssh -V 2>&1`" echo "Ping latency to $DEST": ping -q -c 1 -n $DEST -echo "Destination $DEST SSHD vesion : `echo | nc $DEST 22 | head -n1`" +echo "Destination $DEST SSHD version : `echo | nc $DEST 22 | head -n1`" echo "ssh login latency :`(time -f user:%U ssh $DEST 'id > /dev/null') 2>&1`" ./generate.py | dd bs=4096 count=100000 | time ssh -c $CIPHER $DEST "dd bs=4096 of=/dev/null" 2>&1 diff --git a/libssh/tests/benchmarks/bench2.sh b/libssh/tests/benchmarks/bench2.sh index 01d67777..aa42689d 100755 --- a/libssh/tests/benchmarks/bench2.sh +++ b/libssh/tests/benchmarks/bench2.sh @@ -7,7 +7,7 @@ echo "Cipher : $CIPHER ; Destination : $DEST (`ssh $DEST uname -a`)" echo "Local ssh version: `samplessh -V 2>&1`" echo "Ping latency to $DEST": ping -q -c 1 -n $DEST -echo "Destination $DEST SSHD vesion : `echo | nc $DEST 22 | head -n1`" +echo "Destination $DEST SSHD version : `echo | nc $DEST 22 | head -n1`" echo "ssh login latency :`(time -f user:%U samplessh $DEST 'id > /dev/null') 2>&1`" ./generate.py | dd bs=4096 count=100000 | strace samplessh -c $CIPHER $DEST "dd bs=4096 of=/dev/null" 2>&1 diff --git a/libssh/tests/client/torture_algorithms.c b/libssh/tests/client/torture_algorithms.c index ea3b647b..60354f9b 100644 --- a/libssh/tests/client/torture_algorithms.c +++ b/libssh/tests/client/torture_algorithms.c @@ -594,24 +594,34 @@ static void torture_algorithms_zlib(void **state) { rc = ssh_options_set(session, SSH_OPTIONS_COMPRESSION_C_S, "zlib"); #ifdef WITH_ZLIB - assert_int_equal(rc, SSH_OK); + if (ssh_fips_mode()) { + assert_int_equal(rc, SSH_ERROR); + } else { + assert_int_equal(rc, SSH_OK); + } #else assert_int_equal(rc, SSH_ERROR); #endif rc = ssh_options_set(session, SSH_OPTIONS_COMPRESSION_S_C, "zlib"); #ifdef WITH_ZLIB - assert_int_equal(rc, SSH_OK); + if (ssh_fips_mode()) { + assert_int_equal(rc, SSH_ERROR); + } else { + assert_int_equal(rc, SSH_OK); + } #else assert_int_equal(rc, SSH_ERROR); #endif rc = ssh_connect(session); #ifdef WITH_ZLIB - if (ssh_get_openssh_version(session)) { - assert_false(rc == SSH_OK); - ssh_disconnect(session); - return; + if (!ssh_fips_mode()) { + if (ssh_get_openssh_version(session)) { + assert_false(rc == SSH_OK); + ssh_disconnect(session); + return; + } } #endif assert_int_equal(rc, SSH_OK); diff --git a/libssh/tests/client/torture_auth.c b/libssh/tests/client/torture_auth.c index 79dbd4a7..ff0a8df8 100644 --- a/libssh/tests/client/torture_auth.c +++ b/libssh/tests/client/torture_auth.c @@ -736,7 +736,7 @@ static void torture_auth_cert(void **state) { static void torture_auth_agent_cert(void **state) { -#if OPENSSH_VERSION_MAJOR < 8 +#if OPENSSH_VERSION_MAJOR < 8 || (OPENSSH_VERSION_MAJOR == 8 && OPENSSH_VERSION_MINOR == 0) struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; @@ -756,7 +756,7 @@ static void torture_auth_agent_cert(void **state) "ssh-rsa-cert-v01@openssh.com"); assert_int_equal(rc, SSH_OK); } -#endif /* OPENSSH_VERSION_MAJOR < 8 */ +#endif /* OPENSSH_VERSION_MAJOR < 8.1 */ /* Setup loads a different key, tests are exactly the same. */ torture_auth_agent(state); @@ -764,7 +764,7 @@ static void torture_auth_agent_cert(void **state) static void torture_auth_agent_cert_nonblocking(void **state) { -#if OPENSSH_VERSION_MAJOR < 8 +#if OPENSSH_VERSION_MAJOR < 8 || (OPENSSH_VERSION_MAJOR == 8 && OPENSSH_VERSION_MINOR == 0) struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; @@ -784,7 +784,7 @@ static void torture_auth_agent_cert_nonblocking(void **state) "ssh-rsa-cert-v01@openssh.com"); assert_int_equal(rc, SSH_OK); } -#endif /* OPENSSH_VERSION_MAJOR < 8 */ +#endif /* OPENSSH_VERSION_MAJOR < 8.1 */ torture_auth_agent_nonblocking(state); } diff --git a/libssh/tests/client/torture_auth_pkcs11.c b/libssh/tests/client/torture_auth_pkcs11.c index ee97bff4..e75fea0e 100644 --- a/libssh/tests/client/torture_auth_pkcs11.c +++ b/libssh/tests/client/torture_auth_pkcs11.c @@ -196,7 +196,7 @@ static void torture_auth_autopubkey(void **state, const char *obj_name, const ch rc = ssh_options_set(session, SSH_OPTIONS_IDENTITY, priv_uri); assert_int_equal(rc, SSH_OK); - assert_string_equal(session->opts.identity->root->data, priv_uri); + assert_string_equal(session->opts.identity_non_exp->root->data, priv_uri); rc = ssh_connect(session); assert_int_equal(rc, SSH_OK); diff --git a/libssh/tests/client/torture_client_config.c b/libssh/tests/client/torture_client_config.c index c413619a..5ac22a4c 100644 --- a/libssh/tests/client/torture_client_config.c +++ b/libssh/tests/client/torture_client_config.c @@ -130,7 +130,7 @@ static void torture_client_config_system(void **state) * configuration files retains OpenSSH semantics (the per-user overrides * the system-wide values). * The function ssh_options_parse_config() has hardcoded path to the - * system-wide configuraion file so we try to emmulate the behavior by parsing + * system-wide configuration file so we try to emulate the behavior by parsing * the files separately in the same order. */ static void torture_client_config_emulate(void **state) diff --git a/libssh/tests/client/torture_connect.c b/libssh/tests/client/torture_connect.c index f31f521f..a4e4a3bf 100644 --- a/libssh/tests/client/torture_connect.c +++ b/libssh/tests/client/torture_connect.c @@ -83,6 +83,26 @@ static int session_teardown(void **state) return 0; } +static void torture_connect_peer_discon_msg(void **state) { + struct torture_state *s = *state; + ssh_session session = s->ssh.session; + + int rc; + + rc = ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); + assert_ssh_return_code(session, rc); + + rc = ssh_connect(session); + assert_ssh_return_code(session, rc); + + rc = ssh_service_request(session, "wrong-service"); + assert_int_not_equal(rc, SSH_OK); + + ssh_disconnect(session); + assert_non_null(session->peer_discon_msg); + assert_non_null(ssh_get_disconnect_message(session)); +} + static void torture_connect_nonblocking(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; @@ -189,7 +209,7 @@ static void torture_connect_uninitialized(UNUSED_PARAM(void **state)) ssh_session session; struct passwd *pwd; - /* Make sure the library is unitialized */ + /* Make sure the library is uninitialized */ while (is_ssh_initialized()) { rc = ssh_finalize(); assert_return_code(rc, errno); @@ -218,6 +238,7 @@ static void torture_connect_uninitialized(UNUSED_PARAM(void **state)) int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(torture_connect_peer_discon_msg, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_connect_nonblocking, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_connect_double, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_connect_failure, session_setup, session_teardown), diff --git a/libssh/tests/client/torture_proxycommand.c b/libssh/tests/client/torture_proxycommand.c index 7812a959..9b8019ca 100644 --- a/libssh/tests/client/torture_proxycommand.c +++ b/libssh/tests/client/torture_proxycommand.c @@ -127,7 +127,7 @@ static void torture_options_set_proxycommand_ssh(void **state) socket_t fd; rc = snprintf(command, sizeof(command), - "ssh -oStrictHostKeyChecking=no -W [%%h]:%%p alice@%s", + "ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -W [%%h]:%%p alice@%s", address); assert_true((size_t)rc < sizeof(command)); @@ -152,7 +152,7 @@ static void torture_options_set_proxycommand_ssh_stderr(void **state) /* The -vvv switches produce the desired output on the standard error */ rc = snprintf(command, sizeof(command), - "ssh -vvv -oStrictHostKeyChecking=no -W [%%h]:%%p alice@%s", + "ssh -vvv -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -W [%%h]:%%p alice@%s", address); assert_true((size_t)rc < sizeof(command)); diff --git a/libssh/tests/client/torture_rekey.c b/libssh/tests/client/torture_rekey.c index ce31325e..ccd5ae2c 100644 --- a/libssh/tests/client/torture_rekey.c +++ b/libssh/tests/client/torture_rekey.c @@ -172,7 +172,7 @@ static void torture_rekey_send(void **state) bytes / c->in_cipher->blocksize); assert_int_equal(c->out_cipher->max_blocks, bytes / c->out_cipher->blocksize); - /* We should have less encrypted packets than transfered (first are not encrypted) */ + /* We should have less encrypted packets than transferred (first are not encrypted) */ assert_true(c->out_cipher->packets < s->ssh.session->send_seq); assert_true(c->in_cipher->packets < s->ssh.session->recv_seq); /* Copy the initial secret hash = session_id so we know we changed keys later */ @@ -192,10 +192,11 @@ static void torture_rekey_send(void **state) rc = ssh_userauth_publickey_auto(s->ssh.session, NULL, NULL); assert_int_equal(rc, SSH_AUTH_SUCCESS); - /* send ignore packets of up to 1KB to trigger rekey */ + /* send ignore packets of up to 1KB to trigger rekey. Send little bit more + * to make sure it completes with all different ciphers */ memset(data, 0, sizeof(data)); memset(data, 'A', 128); - for (i = 0; i < 16; i++) { + for (i = 0; i < KEX_RETRY; i++) { ssh_send_ignore(s->ssh.session, data); ssh_handle_packets(s->ssh.session, 50); } @@ -274,9 +275,10 @@ static void torture_rekey_recv(void **state) /* The blocks limit is set correctly */ c = s->ssh.session->current_crypto; + assert_non_null(c); assert_int_equal(c->in_cipher->max_blocks, bytes / c->in_cipher->blocksize); assert_int_equal(c->out_cipher->max_blocks, bytes / c->out_cipher->blocksize); - /* We should have less encrypted packets than transfered (first are not encrypted) */ + /* We should have less encrypted packets than transferred (first are not encrypted) */ assert_true(c->out_cipher->packets < s->ssh.session->send_seq); assert_true(c->in_cipher->packets < s->ssh.session->recv_seq); /* Copy the initial secret hash = session_id so we know we changed keys later */ @@ -471,7 +473,7 @@ static void torture_rekey_different_kex(void **state) bytes / c->in_cipher->blocksize); assert_int_equal(c->out_cipher->max_blocks, bytes / c->out_cipher->blocksize); - /* We should have less encrypted packets than transfered (first are not encrypted) */ + /* We should have less encrypted packets than transferred (first are not encrypted) */ assert_true(c->out_cipher->packets < s->ssh.session->send_seq); assert_true(c->in_cipher->packets < s->ssh.session->recv_seq); /* Copy the initial secret hash = session_id so we know we changed keys later */ @@ -497,7 +499,7 @@ static void torture_rekey_different_kex(void **state) rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_KEY_EXCHANGE, kex2); assert_ssh_return_code(s->ssh.session, rc); - /* send ignore packets of up to 1KB to trigger rekey. Send litle bit more + /* send ignore packets of up to 1KB to trigger rekey. Send little bit more * to make sure the rekey it completes with all different ciphers (paddings */ memset(data, 0, sizeof(data)); memset(data, 'A', 128); @@ -575,7 +577,7 @@ static void torture_rekey_server_different_kex(void **state) rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_KEY_EXCHANGE, kex2); assert_ssh_return_code(s->ssh.session, rc); - /* send ignore packets of up to 1KB to trigger rekey. Send litle bit more + /* send ignore packets of up to 1KB to trigger rekey. Send little bit more * to make sure the rekey it completes with all different ciphers (paddings */ memset(data, 0, sizeof(data)); memset(data, 'A', 128); @@ -670,6 +672,164 @@ static void torture_rekey_server_recv(void **state) } #endif /* WITH_SFTP */ +#ifdef WITH_ZLIB +/* This is disabled by OpenSSH since OpenSSH 7.4p1 */ +#if (OPENSSH_VERSION_MAJOR == 7 && OPENSSH_VERSION_MINOR < 4) || OPENSSH_VERSION_MAJOR < 7 +/* Compression can be funky to get right after rekey + */ +static void torture_rekey_send_compression(void **state) +{ + struct torture_state *s = *state; + const char *comp = "zlib"; + int rc; + + rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_COMPRESSION_C_S, comp); + assert_ssh_return_code(s->ssh.session, rc); + + rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_COMPRESSION_S_C, comp); + assert_ssh_return_code(s->ssh.session, rc); + + torture_rekey_send(state); +} + +#ifdef WITH_SFTP +static void torture_rekey_recv_compression(void **state) +{ + struct torture_state *s = *state; + const char *comp = "zlib"; + int rc; + + rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_COMPRESSION_C_S, comp); + assert_ssh_return_code(s->ssh.session, rc); + + rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_COMPRESSION_S_C, comp); + assert_ssh_return_code(s->ssh.session, rc); + + torture_rekey_recv(state); +} +#endif /* WITH_SFTP */ +#endif + +/* Especially the delayed compression by openssh. + */ +static void torture_rekey_send_compression_delayed(void **state) +{ + struct torture_state *s = *state; + const char *comp = "zlib@openssh.com"; + int rc; + + rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_COMPRESSION_C_S, comp); + assert_ssh_return_code(s->ssh.session, rc); + + rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_COMPRESSION_S_C, comp); + assert_ssh_return_code(s->ssh.session, rc); + + torture_rekey_send(state); +} + +#ifdef WITH_SFTP +static void torture_rekey_recv_compression_delayed(void **state) +{ + struct torture_state *s = *state; + const char *comp = "zlib@openssh.com"; + int rc; + + rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_COMPRESSION_C_S, comp); + assert_ssh_return_code(s->ssh.session, rc); + + rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_COMPRESSION_S_C, comp); + assert_ssh_return_code(s->ssh.session, rc); + + torture_rekey_recv(state); +} +#endif /* WITH_SFTP */ +#endif /* WITH_ZLIB */ + +static void setup_server_for_good_guess(void *state) +{ + const char *default_sshd_config = "KexAlgorithms curve25519-sha256"; + const char *fips_sshd_config = "KexAlgorithms ecdh-sha2-nistp256"; + const char *sshd_config = default_sshd_config; + + if (ssh_fips_mode()) { + sshd_config = fips_sshd_config; + } + /* This sets an only supported kex algorithm that we do not have as a first + * option */ + torture_update_sshd_config(state, sshd_config); +} + +static void torture_rekey_guess_send(void **state) +{ + struct torture_state *s = *state; + + setup_server_for_good_guess(state); + + /* Make the client send the first_kex_packet_follows flag during key + * exchange as well as during the rekey */ + s->ssh.session->send_first_kex_follows = true; + + torture_rekey_send(state); +} + +static void torture_rekey_guess_wrong_send(void **state) +{ + struct torture_state *s = *state; + const char *sshd_config = "KexAlgorithms diffie-hellman-group14-sha256"; + + /* This sets an only supported kex algorithm that we do not have as a first + * option */ + torture_update_sshd_config(state, sshd_config); + + /* Make the client send the first_kex_packet_follows flag during key + * exchange as well as during the rekey */ + s->ssh.session->send_first_kex_follows = true; + + torture_rekey_send(state); +} + +#ifdef WITH_SFTP +static void torture_rekey_guess_recv(void **state) +{ + struct torture_state *s = *state; + int rc; + + setup_server_for_good_guess(state); + + /* Make the client send the first_kex_packet_follows flag during key + * exchange as well as during the rekey */ + s->ssh.session->send_first_kex_follows = true; + + rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_REKEY_DATA, &bytes); + assert_ssh_return_code(s->ssh.session, rc); + + session_setup_sftp(state); + + torture_rekey_recv(state); +} + +static void torture_rekey_guess_wrong_recv(void **state) +{ + struct torture_state *s = *state; + const char *sshd_config = "KexAlgorithms diffie-hellman-group14-sha256"; + int rc; + + /* This sets an only supported kex algorithm that we do not have as a first + * option */ + torture_update_sshd_config(state, sshd_config); + + /* Make the client send the first_kex_packet_follows flag during key + * exchange as well as during the rekey */ + s->ssh.session->send_first_kex_follows = true; + + rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_REKEY_DATA, &bytes); + assert_ssh_return_code(s->ssh.session, rc); + + session_setup_sftp(state); + + torture_rekey_recv(state); +} +#endif /* WITH_SFTP */ int torture_run_tests(void) { int rc; @@ -691,19 +851,54 @@ int torture_run_tests(void) { cmocka_unit_test_setup_teardown(torture_rekey_different_kex, session_setup, session_teardown), - /* Note, that this modifies the sshd_config */ +#ifdef WITH_ZLIB +#if (OPENSSH_VERSION_MAJOR == 7 && OPENSSH_VERSION_MINOR < 4) || OPENSSH_VERSION_MAJOR < 7 + cmocka_unit_test_setup_teardown(torture_rekey_send_compression, + session_setup, + session_teardown), +#ifdef WITH_SFTP + cmocka_unit_test_setup_teardown(torture_rekey_recv_compression, + session_setup_sftp_client, + session_teardown), +#endif /* WITH_SFTP */ +#endif + cmocka_unit_test_setup_teardown(torture_rekey_send_compression_delayed, + session_setup, + session_teardown), +#ifdef WITH_SFTP + cmocka_unit_test_setup_teardown(torture_rekey_recv_compression_delayed, + session_setup_sftp_client, + session_teardown), +#endif /* WITH_SFTP */ +#endif /* WITH_ZLIB */ + /* TODO verify the two rekey are possible and the states are not broken after rekey */ + + cmocka_unit_test_setup_teardown(torture_rekey_server_different_kex, + session_setup, + session_teardown), + /* Note, that these tests modify the sshd_config so follow-up tests + * might get unexpected behavior if they do not update the server with + * torture_update_sshd_config() too */ cmocka_unit_test_setup_teardown(torture_rekey_server_send, session_setup, session_teardown), + cmocka_unit_test_setup_teardown(torture_rekey_guess_send, + session_setup, + session_teardown), + cmocka_unit_test_setup_teardown(torture_rekey_guess_wrong_send, + session_setup, + session_teardown), #ifdef WITH_SFTP cmocka_unit_test_setup_teardown(torture_rekey_server_recv, session_setup_sftp_server, session_teardown), -#endif /* WITH_SFTP */ - cmocka_unit_test_setup_teardown(torture_rekey_server_different_kex, + cmocka_unit_test_setup_teardown(torture_rekey_guess_recv, session_setup, session_teardown), - /* TODO verify the two rekey are possible and the states are not broken after rekey */ + cmocka_unit_test_setup_teardown(torture_rekey_guess_wrong_recv, + session_setup, + session_teardown), +#endif /* WITH_SFTP */ }; ssh_init(); diff --git a/libssh/tests/ctest-default.cmake b/libssh/tests/ctest-default.cmake index dbf53e30..51bbebab 100644 --- a/libssh/tests/ctest-default.cmake +++ b/libssh/tests/ctest-default.cmake @@ -17,16 +17,16 @@ set(CTEST_BUILD_OPTIONS "-DUNIT_TESTING=ON -WITH_SFTP=ON -DWITH_SERVER=ON -DWITH #set(CTEST_CUSTOM_MEMCHECK_IGNORE torture_rand) -## The Model to set: Nightly, Continous, Experimental +## The Model to set: Nightly, Continuous, Experimental set(CTEST_MODEL "Experimental") ## The branch #set(CTEST_GIT_BRANCH "--branch v0-5") -## Wether to enable memory checking. +## Whether to enable memory checking. set(WITH_MEMCHECK FALSE) -## Wether to enable code coverage. +## Whether to enable code coverage. set(WITH_COVERAGE FALSE) ####################################################################### diff --git a/libssh/tests/fuzz/README.md b/libssh/tests/fuzz/README.md index c68ef3d1..088ce27d 100644 --- a/libssh/tests/fuzz/README.md +++ b/libssh/tests/fuzz/README.md @@ -95,7 +95,7 @@ You can either pick up my branch or workaround them locally: ### Reproduce locally Clone the above repository from https://github.com/google/oss-fuzz/, apply -changes from previous secion if needed, setup local clone of libssh repository +changes from previous section if needed, setup local clone of libssh repository and build the fuzzers locally (where `~/devel/libssh` is path to local libssh checkout): @@ -111,7 +111,7 @@ This should give you the same error/leak/crash as you see on the testcase detail in oss-fuzz.com. I find it very useful to run libssh in debug mode, to see what happened and -what exit path was taken to get to the error. Fortunatelly, we can simply +what exit path was taken to get to the error. Fortunately, we can simply pass environment variables to the container: python infra/helper.py reproduce -eLIBSSH_VERBOSITY=9 libssh ssh_client_fuzzer ~/Downloads/clusterfuzz-testcase-ssh_client_fuzzer-4637376441483264 diff --git a/libssh/tests/fuzz/ssh_server_fuzzer.c b/libssh/tests/fuzz/ssh_server_fuzzer.c index 8c7913a3..cb59d0b4 100644 --- a/libssh/tests/fuzz/ssh_server_fuzzer.c +++ b/libssh/tests/fuzz/ssh_server_fuzzer.c @@ -186,6 +186,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) ssh_set_auth_methods(session, SSH_AUTH_METHOD_NONE); ssh_callbacks_init(&server_cb); + ssh_set_server_callbacks(session, &server_cb); rc = ssh_bind_accept_fd(sshbind, session, socket_fds[0]); assert(rc == SSH_OK); diff --git a/libssh/tests/pkcs11/setup-softhsm-tokens.sh b/libssh/tests/pkcs11/setup-softhsm-tokens.sh index 532c86a7..ae316c7a 100755 --- a/libssh/tests/pkcs11/setup-softhsm-tokens.sh +++ b/libssh/tests/pkcs11/setup-softhsm-tokens.sh @@ -6,7 +6,8 @@ TESTDIR=$1 PRIVKEY=$2 OBJNAME=$3 LOADPUBLIC=$4 -shift 4 +LIBSOFTHSM_PATH=$5 +shift 5 PUBKEY="$PRIVKEY.pub" @@ -17,10 +18,10 @@ echo "OBJNAME: $OBJNAME" echo "LOADPUBLIC: $LOADPUBLIC" # Create temporary directory for tokens -install -d -m 0755 $TESTDIR/db +install -d -m 0755 "$TESTDIR/db" # Create SoftHSM configuration file -cat >$TESTDIR/softhsm.conf <"$TESTDIR/softhsm.conf" <pcap = NULL; @@ -161,7 +161,7 @@ static int authenticate_kbdint(ssh_session session, initial_prompt[0] = "username: "; initial_prompt[1] = "password: "; - /* Prompt for aditional prompts */ + /* Prompt for additional prompts */ retype_prompt[0] = "retype password: "; if ((session == NULL) || (message == NULL) || (sdata == NULL)) { diff --git a/libssh/tests/tests_config.h.cmake b/libssh/tests/tests_config.h.cmake index b162db75..a8147c44 100644 --- a/libssh/tests/tests_config.h.cmake +++ b/libssh/tests/tests_config.h.cmake @@ -69,3 +69,4 @@ #cmakedefine SSH_EXECUTABLE "${SSH_EXECUTABLE}" #cmakedefine WITH_TIMEOUT ${WITH_TIMEOUT} #cmakedefine TIMEOUT_EXECUTABLE "${TIMEOUT_EXECUTABLE}" +#cmakedefine SOFTHSM2_LIBRARY "${SOFTHSM2_LIBRARY}" diff --git a/libssh/tests/torture.c b/libssh/tests/torture.c index f5a6bcc7..6b2d5b7b 100644 --- a/libssh/tests/torture.c +++ b/libssh/tests/torture.c @@ -1231,6 +1231,7 @@ void torture_teardown_sshd_server(void **state) } #endif /* SSHD_EXECUTABLE */ +#ifdef WITH_PKCS11_URI void torture_setup_tokens(const char *temp_dir, const char *filename, const char object_name[], @@ -1240,15 +1241,18 @@ void torture_setup_tokens(const char *temp_dir, int rc; snprintf(token_setup_start_cmd, sizeof(token_setup_start_cmd), - "%s/tests/pkcs11/setup-softhsm-tokens.sh %s %s %s %s", + "%s/tests/pkcs11/setup-softhsm-tokens.sh %s %s %s %s %s", BINARYDIR, temp_dir, filename, - object_name, load_public); + object_name, + load_public, + SOFTHSM2_LIBRARY); rc = system(token_setup_start_cmd); assert_return_code(rc, errno); } +#endif /* WITH_PKCS11_URI */ char *torture_make_temp_dir(const char *template) { diff --git a/libssh/tests/torture.h b/libssh/tests/torture.h index 67c249a3..498acf60 100644 --- a/libssh/tests/torture.h +++ b/libssh/tests/torture.h @@ -130,10 +130,12 @@ void torture_teardown_sshd_server(void **state); int torture_update_sshd_config(void **state, const char *config); #endif /* SSHD_EXECUTABLE */ +#ifdef WITH_PKCS11_URI void torture_setup_tokens(const char *temp_dir, const char *filename, const char object_name[], const char *load_public); +#endif /* WITH_PKCS11_URI */ void torture_reset_config(ssh_session session); diff --git a/libssh/tests/unittests/CMakeLists.txt b/libssh/tests/unittests/CMakeLists.txt index 28458d49..f85da72b 100644 --- a/libssh/tests/unittests/CMakeLists.txt +++ b/libssh/tests/unittests/CMakeLists.txt @@ -30,6 +30,12 @@ set(LIBSSH_THREAD_UNIT_TESTS torture_threads_crypto ) +set(TORTURE_UNIT_ENVIRONMENT + "LSAN_OPTIONS=suppressions=${libssh-tests_SOURCE_DIR}/suppressions/lsan.supp;") +if (OPENSSL_FOUND) + list(APPEND TORTURE_UNIT_ENVIRONMENT OPENSSL_ENABLE_SHA1_SIGNATURES=1) +endif (OPENSSL_FOUND) + if (UNIX AND NOT WIN32) set(LIBSSH_UNIT_TESTS ${LIBSSH_UNIT_TESTS} @@ -104,8 +110,7 @@ foreach(_UNIT_TEST ${LIBSSH_UNIT_TESTS}) set_property(TEST ${_UNIT_TEST} PROPERTY - ENVIRONMENT - LSAN_OPTIONS=suppressions=${libssh-tests_SOURCE_DIR}/suppressions/lsan.supp;OPENSSL_ENABLE_SHA1_SIGNATURES=1) + ENVIRONMENT ${TORTURE_UNIT_ENVIRONMENT}) endforeach() if (CMAKE_USE_PTHREADS_INIT) @@ -118,8 +123,7 @@ if (CMAKE_USE_PTHREADS_INIT) set_property(TEST ${_UNIT_TEST} PROPERTY - ENVIRONMENT - LSAN_OPTIONS=suppressions=${libssh-tests_SOURCE_DIR}/suppressions/lsan.supp;OPENSSL_ENABLE_SHA1_SIGNATURES=1) + ENVIRONMENT ${TORTURE_UNIT_ENVIRONMENT}) endforeach() endif () diff --git a/libssh/tests/unittests/hello world.sh b/libssh/tests/unittests/hello world.sh new file mode 100755 index 00000000..9a021b4e --- /dev/null +++ b/libssh/tests/unittests/hello world.sh @@ -0,0 +1 @@ +/bin/echo -n $1 2>&1 \ No newline at end of file diff --git a/libssh/tests/unittests/torture_config.c b/libssh/tests/unittests/torture_config.c index 31dadae3..406f1985 100644 --- a/libssh/tests/unittests/torture_config.c +++ b/libssh/tests/unittests/torture_config.c @@ -13,6 +13,7 @@ #include "libssh/config_parser.h" #include "match.c" #include "config.c" +#include "libssh/socket.h" extern LIBSSH_THREAD int ssh_log_level; @@ -176,7 +177,7 @@ extern LIBSSH_THREAD int ssh_log_level; "Host time4\n" \ "\tRekeyLimit default 9600\n" -/* Multiple IdentityFile settings all are aplied */ +/* Multiple IdentityFile settings all are applied */ #define LIBSSH_TESTCONFIG_STRING13 \ "IdentityFile id_rsa_one\n" \ "IdentityFile id_ecdsa_two\n" @@ -541,9 +542,9 @@ static void torture_config_new(void ** state, assert_string_equal(session->opts.bindaddr, BIND_ADDRESS); #ifdef WITH_ZLIB assert_string_equal(session->opts.wanted_methods[SSH_COMP_C_S], - "zlib@openssh.com,zlib,none"); + "zlib@openssh.com,none"); assert_string_equal(session->opts.wanted_methods[SSH_COMP_S_C], - "zlib@openssh.com,zlib,none"); + "zlib@openssh.com,none"); #else assert_string_equal(session->opts.wanted_methods[SSH_COMP_C_S], "none"); @@ -649,7 +650,7 @@ static void torture_config_unknown(void **state, /* test corner cases */ _parse_config(session, file, string, SSH_OK); assert_string_equal(session->opts.ProxyCommand, - "ssh -W [%h]:%p many-spaces.com"); + "ssh -W '[%h]:%p' many-spaces.com"); assert_string_equal(session->opts.host, "equal.sign"); ret = ssh_config_parse_file(session, "/etc/ssh/ssh_config"); @@ -945,28 +946,28 @@ static void torture_config_proxyjump(void **state, torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "simple"); _parse_config(session, file, string, SSH_OK); - assert_string_equal(session->opts.ProxyCommand, "ssh -W [%h]:%p jumpbox"); + assert_string_equal(session->opts.ProxyCommand, "ssh -W '[%h]:%p' jumpbox"); /* With username */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "user"); _parse_config(session, file, string, SSH_OK); assert_string_equal(session->opts.ProxyCommand, - "ssh -l user -W [%h]:%p jumpbox"); + "ssh -l user -W '[%h]:%p' jumpbox"); /* With port */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "port"); _parse_config(session, file, string, SSH_OK); assert_string_equal(session->opts.ProxyCommand, - "ssh -p 2222 -W [%h]:%p jumpbox"); + "ssh -p 2222 -W '[%h]:%p' jumpbox"); /* Two step jump */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "two-step"); _parse_config(session, file, string, SSH_OK); assert_string_equal(session->opts.ProxyCommand, - "ssh -l u1 -p 222 -J u2@second:33 -W [%h]:%p first"); + "ssh -l u1 -p 222 -J u2@second:33 -W '[%h]:%p' first"); /* none */ torture_reset_config(session); @@ -974,25 +975,25 @@ static void torture_config_proxyjump(void **state, _parse_config(session, file, string, SSH_OK); assert_true(session->opts.ProxyCommand == NULL); - /* If also ProxyCommand is specifed, the first is applied */ + /* If also ProxyCommand is specified, the first is applied */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "only-command"); _parse_config(session, file, string, SSH_OK); assert_string_equal(session->opts.ProxyCommand, PROXYCMD); - /* If also ProxyCommand is specifed, the first is applied */ + /* If also ProxyCommand is specified, the first is applied */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "only-jump"); _parse_config(session, file, string, SSH_OK); assert_string_equal(session->opts.ProxyCommand, - "ssh -W [%h]:%p jumpbox"); + "ssh -W '[%h]:%p' jumpbox"); /* IPv6 address */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "ipv6"); _parse_config(session, file, string, SSH_OK); assert_string_equal(session->opts.ProxyCommand, - "ssh -W [%h]:%p 2620:52:0::fed"); + "ssh -W '[%h]:%p' 2620:52:0::fed"); /* In this part, we try various other config files and strings. */ @@ -1379,17 +1380,20 @@ static void torture_config_nonewlineoneline_string(void **state) NULL, LIBSSH_TEST_NONEWLINEONELINE_STRING); } -/* ssh_config_get_cmd() does three things: +/* ssh_config_get_cmd() does these two things: * * Strips leading whitespace - * * Terminate the characted on the end of next quotes-enclosed string * * Terminate on the end of line */ static void torture_config_parser_get_cmd(void **state) { char *p = NULL, *tok = NULL; char data[256]; - - (void) state; +#ifdef __unix__ + FILE *outfile = NULL, *infile = NULL; + int pid; + char buffer[256] = {0}; +#endif + (void)state; /* Ignore leading whitespace */ strncpy(data, " \t\t string\n", sizeof(data)); @@ -1405,14 +1409,11 @@ static void torture_config_parser_get_cmd(void **state) assert_string_equal(tok, "string \t\t "); assert_int_equal(*p, '\0'); - /* should drop the quotes and split them into separate arguments */ + /* should not drop the quotes and not split them into separate arguments */ strncpy(data, "\"multi string\" something\n", sizeof(data)); p = data; tok = ssh_config_get_cmd(&p); - assert_string_equal(tok, "multi string"); - assert_int_equal(*p, ' '); - tok = ssh_config_get_cmd(&p); - assert_string_equal(tok, "something"); + assert_string_equal(tok, "\"multi string\" something"); assert_int_equal(*p, '\0'); /* But it does not split tokens by whitespace @@ -1422,6 +1423,46 @@ static void torture_config_parser_get_cmd(void **state) tok = ssh_config_get_cmd(&p); assert_string_equal(tok, "multi string something"); assert_int_equal(*p, '\0'); + + /* Commands in quotes are not treated special */ + sprintf(data, "%s%s%s%s", "\"", SOURCEDIR "/tests/unittests/hello world.sh", "\" ", "\"hello libssh\"\n"); + printf("%s\n", data); + p = data; + tok = ssh_config_get_cmd(&p); + assert_string_equal(tok, data); + assert_int_equal(*p, '\0'); + +#ifdef __unix__ + /* Check if the command would get correctly executed + * Use the script file "hello world.sh" to echo the first argument + * Run as <= "/workdir/hello world.sh" "hello libssh" => */ + + /* output to file and check wrong */ + outfile = fopen("output.log", "a+"); + assert_non_null(outfile); + printf("the tok is %s\n", tok); + + pid = fork(); + if (pid == -1) { + perror("fork"); + } else if (pid == 0) { + ssh_execute_command(tok, fileno(outfile), fileno(outfile)); + /* Does not return */ + } else { + /* parent + * wait child process */ + wait(NULL); + infile = fopen("output.log", "r"); + assert_non_null(infile); + p = fgets(buffer, sizeof(buffer), infile); + fclose(infile); + remove("output.log"); + assert_non_null(p); + } + + fclose(outfile); + assert_string_equal(buffer, "hello libssh"); +#endif } /* ssh_config_get_token() should behave as expected @@ -1697,7 +1738,8 @@ static void torture_config_identity(void **state) _parse_config(session, NULL, LIBSSH_TESTCONFIG_STRING13, SSH_OK); - it = ssh_list_get_iterator(session->opts.identity); + /* The identities are first added to this temporary list before expanding */ + it = ssh_list_get_iterator(session->opts.identity_non_exp); assert_non_null(it); id = it->data; /* The identities are prepended to the list so we start with second one */ diff --git a/libssh/tests/unittests/torture_knownhosts_parsing.c b/libssh/tests/unittests/torture_knownhosts_parsing.c index fffa8296..138f4dee 100644 --- a/libssh/tests/unittests/torture_knownhosts_parsing.c +++ b/libssh/tests/unittests/torture_knownhosts_parsing.c @@ -430,7 +430,7 @@ static void torture_knownhosts_get_algorithms_names(void **state) } #ifndef HAVE_DSA -/* Do not remove this test if we completly remove DSA support! */ +/* Do not remove this test if we completely remove DSA support! */ static void torture_knownhosts_get_algorithms_names_unsupported(void **state) { const char *knownhosts_file = *state; @@ -634,7 +634,9 @@ static void torture_knownhosts_algorithms(void **state) bool process_config = false; const char *expect = "ssh-ed25519,rsa-sha2-512,rsa-sha2-256," "ecdsa-sha2-nistp521,ecdsa-sha2-nistp384," - "ecdsa-sha2-nistp256"; + "ecdsa-sha2-nistp256," + "sk-ssh-ed25519@openssh.com," + "sk-ecdsa-sha2-nistp256@openssh.com"; const char *expect_fips = "rsa-sha2-512,rsa-sha2-256,ecdsa-sha2-nistp521," "ecdsa-sha2-nistp384,ecdsa-sha2-nistp256"; @@ -669,7 +671,9 @@ static void torture_knownhosts_algorithms_global(void **state) bool process_config = false; const char *expect = "ssh-ed25519,rsa-sha2-512,rsa-sha2-256," "ecdsa-sha2-nistp521,ecdsa-sha2-nistp384," - "ecdsa-sha2-nistp256"; + "ecdsa-sha2-nistp256," + "sk-ssh-ed25519@openssh.com," + "sk-ecdsa-sha2-nistp256@openssh.com"; const char *expect_fips = "rsa-sha2-512,rsa-sha2-256,ecdsa-sha2-nistp521," "ecdsa-sha2-nistp384,ecdsa-sha2-nistp256"; diff --git a/libssh/tests/unittests/torture_options.c b/libssh/tests/unittests/torture_options.c index e1d16f02..425d7295 100644 --- a/libssh/tests/unittests/torture_options.c +++ b/libssh/tests/unittests/torture_options.c @@ -230,7 +230,7 @@ static void torture_options_set_pubkey_accepted_types(void **state) { /* simulate the SHA2 extension was negotiated */ session->extensions = SSH_EXT_SIG_RSA_SHA256; - /* previous configuration did not list the SHA2 extension algoritms, so + /* previous configuration did not list the SHA2 extension algorithms, so * it should not be used */ type = ssh_key_type_to_hash(session, SSH_KEYTYPE_RSA); assert_int_equal(type, SSH_DIGEST_SHA1); @@ -319,6 +319,7 @@ static void torture_options_set_port(void **state) { rc = ssh_options_set(session, SSH_OPTIONS_PORT_STR, "five"); assert_true(rc == -1); + assert_int_not_equal(session->opts.port, 0); rc = ssh_options_set(session, SSH_OPTIONS_PORT, NULL); assert_true(rc == -1); @@ -406,12 +407,12 @@ static void torture_options_set_identity(void **state) { rc = ssh_options_set(session, SSH_OPTIONS_ADD_IDENTITY, "identity1"); assert_true(rc == 0); - assert_string_equal(session->opts.identity->root->data, "identity1"); + assert_string_equal(session->opts.identity_non_exp->root->data, "identity1"); rc = ssh_options_set(session, SSH_OPTIONS_IDENTITY, "identity2"); assert_true(rc == 0); - assert_string_equal(session->opts.identity->root->data, "identity2"); - assert_string_equal(session->opts.identity->root->next->data, "identity1"); + assert_string_equal(session->opts.identity_non_exp->root->data, "identity2"); + assert_string_equal(session->opts.identity_non_exp->root->next->data, "identity1"); } static void torture_options_get_identity(void **state) { @@ -429,7 +430,7 @@ static void torture_options_get_identity(void **state) { rc = ssh_options_set(session, SSH_OPTIONS_IDENTITY, "identity2"); assert_int_equal(rc, SSH_OK); - assert_string_equal(session->opts.identity->root->data, "identity2"); + assert_string_equal(session->opts.identity_non_exp->root->data, "identity2"); rc = ssh_options_get(session, SSH_OPTIONS_IDENTITY, &identity); assert_int_equal(rc, SSH_OK); assert_non_null(identity); @@ -867,9 +868,9 @@ static void torture_options_copy(void **state) assert_non_null(new); /* Check the identities match */ - it = ssh_list_get_iterator(session->opts.identity); + it = ssh_list_get_iterator(session->opts.identity_non_exp); assert_non_null(it); - it2 = ssh_list_get_iterator(new->opts.identity); + it2 = ssh_list_get_iterator(new->opts.identity_non_exp); assert_non_null(it2); while (it != NULL && it2 != NULL) { assert_string_equal(it->data, it2->data); @@ -918,6 +919,34 @@ static void torture_options_copy(void **state) sizeof(session->opts.options_seen)); ssh_free(new); + + /* test if ssh_options_apply was called before ssh_options_copy + * the opts.identity list gets copied (percent expanded list) */ + rv = ssh_options_apply(session); + assert_ssh_return_code(session, rv); + + rv = ssh_options_copy(session, &new); + assert_ssh_return_code(session, rv); + assert_non_null(new); + + it = ssh_list_get_iterator(session->opts.identity_non_exp); + assert_null(it); + it2 = ssh_list_get_iterator(new->opts.identity_non_exp); + assert_null(it2); + + it = ssh_list_get_iterator(session->opts.identity); + assert_non_null(it); + it2 = ssh_list_get_iterator(new->opts.identity); + assert_non_null(it2); + while (it != NULL && it2 != NULL) { + assert_string_equal(it->data, it2->data); + it = it->next; + it2 = it2->next; + } + assert_null(it); + assert_null(it2); + + ssh_free(new); } #define EXECUTABLE_NAME "test-exec" @@ -956,12 +985,12 @@ static void torture_options_getopt(void **state) "aes128-ctr"); assert_string_equal(session->opts.wanted_methods[SSH_CRYPT_S_C], "aes128-ctr"); - assert_string_equal(session->opts.identity->root->data, "id_rsa"); + assert_string_equal(session->opts.identity_non_exp->root->data, "id_rsa"); #ifdef WITH_ZLIB assert_string_equal(session->opts.wanted_methods[SSH_COMP_C_S], - "zlib@openssh.com,zlib,none"); + "zlib@openssh.com,none"); assert_string_equal(session->opts.wanted_methods[SSH_COMP_S_C], - "zlib@openssh.com,zlib,none"); + "zlib@openssh.com,none"); #else assert_string_equal(session->opts.wanted_methods[SSH_COMP_C_S], "none"); @@ -1040,9 +1069,9 @@ static void torture_options_getopt(void **state) assert_ssh_return_code(session, rc); #ifdef WITH_ZLIB assert_string_equal(session->opts.wanted_methods[SSH_COMP_C_S], - "none,zlib@openssh.com,zlib"); + "none,zlib@openssh.com"); assert_string_equal(session->opts.wanted_methods[SSH_COMP_S_C], - "none,zlib@openssh.com,zlib"); + "none,zlib@openssh.com"); #else assert_string_equal(session->opts.wanted_methods[SSH_COMP_C_S], "none"); @@ -1056,9 +1085,9 @@ static void torture_options_getopt(void **state) assert_string_equal(argv[0], EXECUTABLE_NAME); #ifdef WITH_ZLIB assert_string_equal(session->opts.wanted_methods[SSH_COMP_C_S], - "zlib@openssh.com,zlib,none"); + "zlib@openssh.com,none"); assert_string_equal(session->opts.wanted_methods[SSH_COMP_S_C], - "zlib@openssh.com,zlib,none"); + "zlib@openssh.com,none"); #else assert_string_equal(session->opts.wanted_methods[SSH_COMP_C_S], "none"); @@ -1087,6 +1116,190 @@ static void torture_options_getopt(void **state) #endif /* _NSC_VER */ } +static void torture_options_apply (void **state) { + ssh_session session = *state; + struct ssh_list *awaited_list = NULL; + struct ssh_iterator *it1 = NULL, *it2 = NULL; + char *id = NULL; + int rc; + + rc = ssh_options_set(session, + SSH_OPTIONS_KNOWNHOSTS, + "%%d/.ssh/known_hosts"); + assert_ssh_return_code(session, rc); + + rc = ssh_options_set(session, + SSH_OPTIONS_GLOBAL_KNOWNHOSTS, + "/etc/%%u/libssh/known_hosts"); + assert_ssh_return_code(session, rc); + + rc = ssh_options_set(session, + SSH_OPTIONS_PROXYCOMMAND, + "exec echo \"Hello libssh %%d!\""); + assert_ssh_return_code(session, rc); + + rc = ssh_options_set(session, + SSH_OPTIONS_ADD_IDENTITY, + "%%d/do_not_expand"); + assert_ssh_return_code(session, rc); + + rc = ssh_options_apply(session); + assert_ssh_return_code(session, rc); + + /* check that the values got expanded */ + assert_true(session->opts.exp_flags & SSH_OPT_EXP_FLAG_KNOWNHOSTS); + assert_true(session->opts.exp_flags & SSH_OPT_EXP_FLAG_GLOBAL_KNOWNHOSTS); + assert_true(session->opts.exp_flags & SSH_OPT_EXP_FLAG_PROXYCOMMAND); + assert_true(ssh_list_count(session->opts.identity_non_exp) == 0); + assert_true(ssh_list_count(session->opts.identity) > 0); + + /* should not change anything calling it again */ + rc = ssh_options_apply(session); + assert_ssh_return_code(session, rc); + + /* check that the expansion was done only once */ + assert_string_equal(session->opts.knownhosts, "%d/.ssh/known_hosts"); + assert_string_equal(session->opts.global_knownhosts, + "/etc/%u/libssh/known_hosts"); + /* no exec should be added if there already is one */ + assert_string_equal(session->opts.ProxyCommand, + "exec echo \"Hello libssh %d!\""); + assert_string_equal(session->opts.identity->root->data, + "%d/do_not_expand"); + + /* apply should keep the freshest setting */ + rc = ssh_options_set(session, + SSH_OPTIONS_KNOWNHOSTS, + "hello there"); + assert_ssh_return_code(session, rc); + + rc = ssh_options_set(session, + SSH_OPTIONS_GLOBAL_KNOWNHOSTS, + "lorem ipsum"); + assert_ssh_return_code(session, rc); + + rc = ssh_options_set(session, + SSH_OPTIONS_PROXYCOMMAND, + "mission_impossible"); + assert_ssh_return_code(session, rc); + + rc = ssh_options_set(session, + SSH_OPTIONS_ADD_IDENTITY, + "007"); + assert_ssh_return_code(session, rc); + + rc = ssh_options_set(session, + SSH_OPTIONS_ADD_IDENTITY, + "3"); + assert_ssh_return_code(session, rc); + + rc = ssh_options_set(session, + SSH_OPTIONS_ADD_IDENTITY, + "2"); + assert_ssh_return_code(session, rc); + + rc = ssh_options_set(session, + SSH_OPTIONS_ADD_IDENTITY, + "1"); + assert_ssh_return_code(session, rc); + + /* check that flags show need of escape expansion */ + assert_false(session->opts.exp_flags & SSH_OPT_EXP_FLAG_KNOWNHOSTS); + assert_false(session->opts.exp_flags & SSH_OPT_EXP_FLAG_GLOBAL_KNOWNHOSTS); + assert_false(session->opts.exp_flags & SSH_OPT_EXP_FLAG_PROXYCOMMAND); + assert_false(ssh_list_count(session->opts.identity_non_exp) == 0); + + rc = ssh_options_apply(session); + assert_ssh_return_code(session, rc); + + /* check that the values got expanded */ + assert_true(session->opts.exp_flags & SSH_OPT_EXP_FLAG_KNOWNHOSTS); + assert_true(session->opts.exp_flags & SSH_OPT_EXP_FLAG_GLOBAL_KNOWNHOSTS); + assert_true(session->opts.exp_flags & SSH_OPT_EXP_FLAG_PROXYCOMMAND); + assert_true(ssh_list_count(session->opts.identity_non_exp) == 0); + + assert_string_equal(session->opts.knownhosts, "hello there"); + assert_string_equal(session->opts.global_knownhosts, "lorem ipsum"); + /* check that the "exec " was added at the beginning */ + assert_string_equal(session->opts.ProxyCommand, "exec mission_impossible"); + assert_string_equal(session->opts.identity->root->data, "1"); + + /* check the order of the identity files after double expansion */ + awaited_list = ssh_list_new(); + /* append the new data in order */ + id = strdup("1"); + rc = ssh_list_append(awaited_list, id); + assert_int_equal(rc, SSH_OK); + id = strdup("2"); + rc = ssh_list_append(awaited_list, id); + assert_int_equal(rc, SSH_OK); + id = strdup("3"); + rc = ssh_list_append(awaited_list, id); + assert_int_equal(rc, SSH_OK); + id = strdup("007"); + rc = ssh_list_append(awaited_list, id); + assert_int_equal(rc, SSH_OK); + id = strdup("%d/do_not_expand"); + rc = ssh_list_append(awaited_list, id); + assert_int_equal(rc, SSH_OK); + /* append the defaults; this list is copied from ssh_new@src/session.c */ + id = ssh_path_expand_escape(session, "%d/id_ed25519"); + rc = ssh_list_append(awaited_list, id); + assert_int_equal(rc, SSH_OK); +#ifdef HAVE_ECC + id = ssh_path_expand_escape(session, "%d/id_ecdsa"); + rc = ssh_list_append(awaited_list, id); + assert_int_equal(rc, SSH_OK); +#endif + id = ssh_path_expand_escape(session, "%d/id_rsa"); + rc = ssh_list_append(awaited_list, id); + assert_int_equal(rc, SSH_OK); +#ifdef HAVE_DSA + id = ssh_path_expand_escape(session, "%d/id_dsa"); + rc = ssh_list_append(awaited_list, id); + assert_int_equal(rc, SSH_OK); +#endif + + assert_int_equal(ssh_list_count(awaited_list), + ssh_list_count(session->opts.identity)); + + it1 = ssh_list_get_iterator(awaited_list); + assert_non_null(it1); + it2 = ssh_list_get_iterator(session->opts.identity); + assert_non_null(it2); + while (it1 != NULL && it2 != NULL) { + assert_string_equal(it1->data, it2->data); + + free((void*)it1->data); + it1 = it1->next; + it2 = it2->next; + } + assert_null(it1); + assert_null(it2); + + ssh_list_free(awaited_list); +} + +static void torture_options_set_verbosity (void **state) +{ + ssh_session session = *state; + int rc, new_level; + + rc = ssh_options_set(session, + SSH_OPTIONS_LOG_VERBOSITY_STR, + "3"); + assert_int_equal(rc, SSH_OK); + new_level = ssh_get_log_level(); + assert_int_equal(new_level, SSH_LOG_PACKET); + + rc = ssh_options_set(session, + SSH_OPTIONS_LOG_VERBOSITY_STR, + "datsun"); + assert_int_equal(rc, -1); + new_level = ssh_get_log_level(); + assert_int_not_equal(new_level, 0); +} + #ifdef WITH_SERVER const char template[] = "temp_dir_XXXXXX"; @@ -1341,6 +1554,10 @@ static void torture_bind_options_bindport_str(void **state) rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_BINDPORT_STR, "23"); assert_int_equal(rc, 0); assert_int_equal(bind->bindport, 23); + + rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_BINDPORT_STR, "twentythree"); + assert_int_equal(rc, -1); + assert_int_not_equal(bind->bindport, 0); } static void torture_bind_options_log_verbosity(void **state) @@ -1390,6 +1607,11 @@ static void torture_bind_options_log_verbosity_str(void **state) new_level = ssh_get_log_level(); assert_int_equal(new_level, SSH_LOG_PACKET); + rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "verbosity"); + assert_int_equal(rc, -1); + new_level = ssh_get_log_level(); + assert_int_not_equal(new_level, 0); + rc = ssh_set_log_level(previous_level); assert_int_equal(rc, SSH_OK); } @@ -1881,6 +2103,8 @@ int torture_run_tests(void) { setup, teardown), cmocka_unit_test_setup_teardown(torture_options_getopt, setup, teardown), + cmocka_unit_test_setup_teardown(torture_options_apply, setup, teardown), + cmocka_unit_test_setup_teardown(torture_options_set_verbosity, setup, teardown), }; #ifdef WITH_SERVER diff --git a/libssh/tests/unittests/torture_packet.c b/libssh/tests/unittests/torture_packet.c index 9f07f394..faf78116 100644 --- a/libssh/tests/unittests/torture_packet.c +++ b/libssh/tests/unittests/torture_packet.c @@ -272,10 +272,15 @@ static void torture_packet_aes256_cbc_etm(UNUSED_PARAM(void **state)) } } -static void torture_packet_3des_cbc(void **state) +static void torture_packet_3des_cbc(UNUSED_PARAM(void **state)) { int i; - (void)state; /* unused */ + + /* 3des is not completely FIPS-allowed cipher since 140-3 */ + if (ssh_fips_mode()) { + skip(); + } + for (i=1;i<256;++i){ torture_packet("3des-cbc", "hmac-sha1", "none", i); } @@ -284,6 +289,12 @@ static void torture_packet_3des_cbc(void **state) static void torture_packet_3des_cbc_etm(UNUSED_PARAM(void **state)) { int i; + + /* 3des is not completely FIPS-allowed cipher since 140-3 */ + if (ssh_fips_mode()) { + skip(); + } + for (i = 1; i < 256; ++i) { torture_packet("3des-cbc", "hmac-sha1-etm@openssh.com", "none", i); } diff --git a/libssh/tests/unittests/torture_packet_filter.c b/libssh/tests/unittests/torture_packet_filter.c index ffa49602..06cd74a7 100644 --- a/libssh/tests/unittests/torture_packet_filter.c +++ b/libssh/tests/unittests/torture_packet_filter.c @@ -20,7 +20,7 @@ */ /* - * This test checks if the messages accepted by the packet filter were intented + * This test checks if the messages accepted by the packet filter were intended * to be accepted. * * The process consists in 2 steps: diff --git a/libssh/tests/unittests/torture_pki_rsa.c b/libssh/tests/unittests/torture_pki_rsa.c index 7b9d83fc..96fcb4e7 100644 --- a/libssh/tests/unittests/torture_pki_rsa.c +++ b/libssh/tests/unittests/torture_pki_rsa.c @@ -690,7 +690,7 @@ static void torture_pki_rsa_key_size(void **state) rc = ssh_pki_signature_verify(session, sign, pubkey, INPUT, sizeof(INPUT)); assert_ssh_return_code(session, rc); - /* Set the minumum RSA key size to 4k */ + /* Set the minimum RSA key size to 4k */ rc = ssh_options_set(session, SSH_OPTIONS_RSA_MIN_SIZE, &length); assert_ssh_return_code(session, rc); diff --git a/libssh/tests/unittests/torture_unit_server.c b/libssh/tests/unittests/torture_unit_server.c index ca7515ea..3e7e69f7 100644 --- a/libssh/tests/unittests/torture_unit_server.c +++ b/libssh/tests/unittests/torture_unit_server.c @@ -120,7 +120,7 @@ static void test_ssh_accept_interrupt(void **state) server = ssh_new(); assert_non_null(server); - /* Send interupt in 1 second */ + /* Send interrupt in 1 second */ rc = pthread_create(&interrupt_pthread, NULL, int_thread, NULL); assert_return_code(rc, errno); From 7ab1db25e6fe267e4a6b858d9270a9a3963ee5e6 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Sun, 23 Jul 2023 13:03:22 +0200 Subject: [PATCH 3/8] versioneer: replace deprecated (and removed in 3.12) SafeConfigParser (#71) * versioneer: replace deprecated (and removed in 3.12) SafeConfigParser See for details: https://github.com/python/cpython/pull/92503/files * versioneer: replace as well deprecated readfp with read_file --- versioneer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/versioneer.py b/versioneer.py index a2870603..eafcdacf 100644 --- a/versioneer.py +++ b/versioneer.py @@ -339,9 +339,9 @@ def get_config_from_root(root): # configparser.NoOptionError (if it lacks "VCS="). See the docstring at # the top of versioneer.py for instructions on writing your setup.cfg . setup_cfg = os.path.join(root, "setup.cfg") - parser = configparser.SafeConfigParser() + parser = configparser.ConfigParser() with open(setup_cfg, "r") as f: - parser.readfp(f) + parser.read_file(f) VCS = parser.get("versioneer", "VCS") # mandatory def get(parser, name): From abba89d3c4329a55694d1d8316d3550b5d988806 Mon Sep 17 00:00:00 2001 From: enkore Date: Sun, 23 Jul 2023 11:42:05 +0000 Subject: [PATCH 4/8] appveyor: use OpenSSL 3, copy only libcrypto into wheel --- .appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 28b9106d..30cb6f19 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -45,11 +45,11 @@ install: https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | ` Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { ` throw "There are newer queued builds for this pull request, failing early." } - - set OPENSSL_DIR="C:\OpenSSL-v11-Win%PYTHON_ARCH%" + - set OPENSSL_DIR="C:\OpenSSL-v30-Win%PYTHON_ARCH%" - set VCLIBDIR=%WINDIR%\System32 - cp %VCLIBDIR%/vcruntime140.dll ssh/ - cp %VCLIBDIR%/msvcr120.dll ssh/ - - cp %OPENSSL_DIR%/bin/*.dll ssh/ + - cp %OPENSSL_DIR%/bin/libcrypto*.dll ssh/ - for %%I in (%PYTHONVERS%) do %%I\python.exe -V - for %%I in (%PYTHONVERS%) do %%I\Scripts\pip install -U wheel setuptools twine cython From b11c02c160d1df63e78e198dbcbe56ccb917ffc6 Mon Sep 17 00:00:00 2001 From: enkore Date: Sun, 23 Jul 2023 12:18:35 +0000 Subject: [PATCH 5/8] appveyor: openssl 3 is linked againt UCRT, VCRT 12.0 not needed any more --- .appveyor.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 30cb6f19..fa2f02e8 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -48,7 +48,6 @@ install: - set OPENSSL_DIR="C:\OpenSSL-v30-Win%PYTHON_ARCH%" - set VCLIBDIR=%WINDIR%\System32 - cp %VCLIBDIR%/vcruntime140.dll ssh/ - - cp %VCLIBDIR%/msvcr120.dll ssh/ - cp %OPENSSL_DIR%/bin/libcrypto*.dll ssh/ - for %%I in (%PYTHONVERS%) do %%I\python.exe -V From f5505f8a187c9deb8192742c928f35929ad51271 Mon Sep 17 00:00:00 2001 From: enkore Date: Sun, 23 Jul 2023 13:06:05 +0200 Subject: [PATCH 6/8] manylinux: openssl 3.1.1, krb5 1.21.1, remove manylinux2010 --- ci/build-manylinux.sh | 6 +--- ci/docker/manylinux/Dockerfile | 35 ------------------- ci/docker/manylinux/Dockerfile.2014_x86_64 | 6 ++-- ci/docker/manylinux/Dockerfile.aarch64 | 6 ++-- ci/docker/manylinux/Dockerfile.aarch64_2_24 | 6 ++-- ci/docker/manylinux/Dockerfile.aarch64_2_28 | 6 ++-- .../Dockerfile.manylinux_2_24_x86_64 | 6 ++-- .../Dockerfile.manylinux_2_28_x86_64 | 6 ++-- ci/docker/manylinux/krb5-1.18.4.tar.xz | 3 -- ci/docker/manylinux/krb5-1.21.1.tar.xz | 3 ++ 10 files changed, 22 insertions(+), 61 deletions(-) delete mode 100644 ci/docker/manylinux/Dockerfile delete mode 100644 ci/docker/manylinux/krb5-1.18.4.tar.xz create mode 100644 ci/docker/manylinux/krb5-1.21.1.tar.xz diff --git a/ci/build-manylinux.sh b/ci/build-manylinux.sh index 593d4385..dd79a0a8 100755 --- a/ci/build-manylinux.sh +++ b/ci/build-manylinux.sh @@ -15,10 +15,8 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - docker_repo="parallelssh/ssh-manylinux" docker_files=( - "ci/docker/manylinux/Dockerfile" "ci/docker/manylinux/Dockerfile.2014_x86_64" # "ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64" # "ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64" @@ -36,10 +34,8 @@ if [[ $(uname -m) == "aarch64" ]]; then fi for docker_file in "${docker_files[@]}"; do - if [[ ${docker_file} == "ci/docker/manylinux/Dockerfile_2014_x86_64" ]]; then + if [[ ${docker_file} == "ci/docker/manylinux/Dockerfile.2014_x86_64" ]]; then docker_tag="${docker_repo}:2014_x86_64" - elif [[ ${docker_file} == "ci/docker/manylinux/Dockerfile" ]]; then - docker_tag="${docker_repo}:2010_x86_64" elif [[ ${docker_file} == "ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64" ]]; then docker_tag="${docker_repo}:2_24_x86_64" elif [[ ${docker_file} == "ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64" ]]; then diff --git a/ci/docker/manylinux/Dockerfile b/ci/docker/manylinux/Dockerfile deleted file mode 100644 index a7adda28..00000000 --- a/ci/docker/manylinux/Dockerfile +++ /dev/null @@ -1,35 +0,0 @@ -FROM quay.io/pypa/manylinux2010_x86_64 - -ENV OPENSSL openssl-1.1.1q -ENV LIBSSH 0.10.5 -ENV KRB 1.18.4 -ENV SYSTEM_LIBSSH 1 -ENV CFLAGS "-g0 -s" - -RUN yum install zlib-devel cmake3 -y - -ADD libssh-${LIBSSH}.tar.xz libssh.tar.xz -ADD https://www.openssl.org/source/${OPENSSL}.tar.gz ${OPENSSL}.tar.gz -ADD krb5-${KRB}.tar.xz krb5-${KRB}.tar.xz - -RUN tar -xzf ${OPENSSL}.tar.gz -# Openssl -RUN cd ${OPENSSL} && \ - ./config --prefix=/usr --openssldir=/usr/openssl threads shared && \ - make -j6 && make install_sw - -# Kerberos -RUN cd krb5-${KRB}.tar.xz/krb5-${KRB}/src && \ - ./configure && \ - make -j6 && \ - make install - -# Libssh -RUN mkdir -p build_libssh && cd build_libssh && \ - cmake3 ../libssh.tar.xz/libssh-${LIBSSH} -DCMAKE_BUILD_TYPE=Release \ - -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF && \ - make -j6 install/strip - -RUN rm -rf ${OPENSSL}* libssh build_libssh krb5-${KRB}.tar.xz - -VOLUME /var/cache diff --git a/ci/docker/manylinux/Dockerfile.2014_x86_64 b/ci/docker/manylinux/Dockerfile.2014_x86_64 index 5836b546..f41d79b4 100644 --- a/ci/docker/manylinux/Dockerfile.2014_x86_64 +++ b/ci/docker/manylinux/Dockerfile.2014_x86_64 @@ -1,12 +1,12 @@ FROM quay.io/pypa/manylinux2014_x86_64 -ENV OPENSSL openssl-1.1.1q +ENV OPENSSL openssl-3.1.1 ENV LIBSSH 0.10.5 -ENV KRB 1.18.4 +ENV KRB 1.21.1 ENV SYSTEM_LIBSSH 1 ENV CFLAGS "-g0 -s" -RUN yum install zlib-devel cmake3 -y +RUN yum install -y zlib-devel cmake3 perl-core ADD libssh-${LIBSSH}.tar.xz libssh.tar.xz ADD https://www.openssl.org/source/${OPENSSL}.tar.gz ${OPENSSL}.tar.gz diff --git a/ci/docker/manylinux/Dockerfile.aarch64 b/ci/docker/manylinux/Dockerfile.aarch64 index 1118a00e..5aaf0ce6 100644 --- a/ci/docker/manylinux/Dockerfile.aarch64 +++ b/ci/docker/manylinux/Dockerfile.aarch64 @@ -1,12 +1,12 @@ FROM quay.io/pypa/manylinux2014_aarch64 -ENV OPENSSL openssl-1.1.1q +ENV OPENSSL openssl-3.1.1 ENV LIBSSH 0.10.5 -ENV KRB 1.18.4 +ENV KRB 1.21.1 ENV SYSTEM_LIBSSH 1 ENV CFLAGS "-g0 -s" -RUN yum install epel-release -y && yum install zlib-devel cmake3 -y +RUN yum install epel-release -y && yum install zlib-devel cmake3 perl-core -y ADD libssh-${LIBSSH}.tar.xz libssh.tar.xz ADD https://www.openssl.org/source/${OPENSSL}.tar.gz ${OPENSSL}.tar.gz diff --git a/ci/docker/manylinux/Dockerfile.aarch64_2_24 b/ci/docker/manylinux/Dockerfile.aarch64_2_24 index 57395fd0..3f8c20d5 100644 --- a/ci/docker/manylinux/Dockerfile.aarch64_2_24 +++ b/ci/docker/manylinux/Dockerfile.aarch64_2_24 @@ -1,13 +1,13 @@ FROM quay.io/pypa/manylinux_2_24_aarch64 -ENV OPENSSL openssl-1.1.1q +ENV OPENSSL openssl-3.1.1 ENV LIBSSH 0.10.5 -ENV KRB 1.18.4 +ENV KRB 1.21.1 ENV SYSTEM_LIBSSH 1 ENV CFLAGS "-g0 -s" ENV OPENSSL_ROOT_DIR /usr/lib -RUN apt-get update -y && apt-get install zlib1g-dev cmake -y +RUN apt-get update -y && apt-get install zlib1g-dev cmake perl-core -y ADD libssh-${LIBSSH}.tar.xz libssh.tar.xz ADD https://www.openssl.org/source/${OPENSSL}.tar.gz ${OPENSSL}.tar.gz diff --git a/ci/docker/manylinux/Dockerfile.aarch64_2_28 b/ci/docker/manylinux/Dockerfile.aarch64_2_28 index 39ce14e4..8c3f0205 100644 --- a/ci/docker/manylinux/Dockerfile.aarch64_2_28 +++ b/ci/docker/manylinux/Dockerfile.aarch64_2_28 @@ -1,13 +1,13 @@ FROM quay.io/pypa/manylinux_2_28_aarch64 -ENV OPENSSL openssl-1.1.1q +ENV OPENSSL openssl-3.1.1 ENV LIBSSH 0.10.5 -ENV KRB 1.18.4 +ENV KRB 1.21.1 ENV SYSTEM_LIBSSH 1 ENV CFLAGS "-g0 -s" ENV OPENSSL_ROOT_DIR /usr/lib -RUN yum install zlib-devel cmake3 -y +RUN yum install zlib-devel cmake3 perl-core -y ADD libssh-${LIBSSH}.tar.xz libssh.tar.xz ADD https://www.openssl.org/source/${OPENSSL}.tar.gz ${OPENSSL}.tar.gz diff --git a/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 b/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 index 2427c9be..d07a35bf 100644 --- a/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 +++ b/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 @@ -1,13 +1,13 @@ FROM quay.io/pypa/manylinux_2_24_x86_64 -ENV OPENSSL openssl-1.1.1q +ENV OPENSSL openssl-3.1.1 ENV LIBSSH 0.10.5 -ENV KRB 1.18.4 +ENV KRB 1.21.1 ENV SYSTEM_LIBSSH 1 ENV CFLAGS "-g0 -s" ENV OPENSSL_ROOT_DIR /usr/lib -RUN apt-get update -y && apt-get install zlib1g-dev cmake -y +RUN apt-get update -y && apt-get install zlib1g-dev cmake perl-core -y ADD libssh-${LIBSSH}.tar.xz libssh.tar.xz ADD https://www.openssl.org/source/${OPENSSL}.tar.gz ${OPENSSL}.tar.gz diff --git a/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 b/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 index 625283d5..0cf606c8 100644 --- a/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 +++ b/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 @@ -1,13 +1,13 @@ FROM quay.io/pypa/manylinux_2_28_x86_64 -ENV OPENSSL openssl-1.1.1q +ENV OPENSSL openssl-3.1.1 ENV LIBSSH 0.10.5 -ENV KRB 1.18.4 +ENV KRB 1.21.1 ENV SYSTEM_LIBSSH 1 ENV CFLAGS "-g0 -s" ENV OPENSSL_ROOT_DIR /usr/lib -RUN yum install zlib-devel cmake3 -y +RUN yum install -y zlib-devel cmake3 perl-core ADD libssh-${LIBSSH}.tar.xz libssh.tar.xz ADD https://www.openssl.org/source/${OPENSSL}.tar.gz ${OPENSSL}.tar.gz diff --git a/ci/docker/manylinux/krb5-1.18.4.tar.xz b/ci/docker/manylinux/krb5-1.18.4.tar.xz deleted file mode 100644 index 7437932c..00000000 --- a/ci/docker/manylinux/krb5-1.18.4.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a98e2692c96d9eba586e491530a76bcf2e8e9022e07eadd5a490bb1ad38aaf3b -size 6095136 diff --git a/ci/docker/manylinux/krb5-1.21.1.tar.xz b/ci/docker/manylinux/krb5-1.21.1.tar.xz new file mode 100644 index 00000000..d87bc6a9 --- /dev/null +++ b/ci/docker/manylinux/krb5-1.21.1.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:39183f9e6beceaa5dacf17f90da04fd994236ff5ba9117380048d84af0e862e5 +size 6194020 From a2ad47d1126139dffb9abf8c6d61280bfd473dcc Mon Sep 17 00:00:00 2001 From: enkore Date: Sun, 23 Jul 2023 15:33:00 +0200 Subject: [PATCH 7/8] requirements_dev: pin cython to <1 for now --- requirements_dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_dev.txt b/requirements_dev.txt index 8bf2de5c..14f22256 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -1,4 +1,4 @@ -cython +cython<1 flake8 jinja2 sphinx From c3f0d7b80c47479ce30a5d5fa9b6b3fa95b7621c Mon Sep 17 00:00:00 2001 From: enkore Date: Sun, 23 Jul 2023 16:48:56 +0200 Subject: [PATCH 8/8] drop cpython 3.6 --- .appveyor.yml | 2 +- .circleci/config.yml | 3 +-- ci/build-wheels.sh | 12 +++++++----- setup.py | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index fa2f02e8..88b73606 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -32,7 +32,7 @@ environment: PYTHON_DEF: "C:\\Python38-x64" PYTHON_VERSION: "3.8" # Python versions to build wheels for - PYTHONVERS: C:\Python36-x64 C:\Python37-x64 C:\Python38-x64 C:\Python39-x64 C:\Python310-x64 C:\Python311-x64 + PYTHONVERS: C:\Python37-x64 C:\Python38-x64 C:\Python39-x64 C:\Python310-x64 C:\Python311-x64 PYTHON_ARCH: "64" install: diff --git a/.circleci/config.yml b/.circleci/config.yml index 515f5dbb..6031c862 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -141,8 +141,7 @@ workflows: matrix: parameters: python_ver: - - "3.6" - - "3.8" + - "3.7" - "3.9" - "3.11" filters: diff --git a/ci/build-wheels.sh b/ci/build-wheels.sh index 58a247d7..c06b4b55 100755 --- a/ci/build-wheels.sh +++ b/ci/build-wheels.sh @@ -17,9 +17,12 @@ # Compile wheels rm -rf /io/build -# For testing -#for PYBIN in $(ls -1d /opt/python/cp310-cp310/bin | grep -v cpython); do -for PYBIN in $(ls -1d /opt/python/*/bin | grep -v cpython); do + +PYVERS=$(ls -1d /opt/python/*/bin | grep -v cpython | grep -v cp36- | sort -V) +# For testing: +#PYVERS=/opt/python/cp311-cp311/bin + +for PYBIN in $PYVERS; do "${PYBIN}/pip" wheel /io/ -w wheelhouse/ done @@ -29,8 +32,7 @@ for whl in wheelhouse/*.whl; do done # Install packages and test -#for PYBIN in $(ls -1d /opt/python/cp310-cp310/bin | grep -v cpython); do -for PYBIN in $(ls -1d /opt/python/*/bin | grep -v cpython); do +for PYBIN in $PYVERS; do "${PYBIN}/pip" install ssh-python --no-index -f /io/wheelhouse (cd "$HOME"; "${PYBIN}/python" -c 'from ssh.session import Session; Session()') done diff --git a/setup.py b/setup.py index 99491d5e..7aceadef 100644 --- a/setup.py +++ b/setup.py @@ -125,11 +125,11 @@ 'Programming Language :: C', 'Programming Language :: Python', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', 'Topic :: System :: Shells', 'Topic :: System :: Networking', 'Topic :: Software Development :: Libraries',