From 3a7b14e57c5c10b6fed24aa87d66ceca4109b7e1 Mon Sep 17 00:00:00 2001 From: enkore Date: Sun, 23 Jul 2023 10:06:24 +0000 Subject: [PATCH 1/9] 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/9] 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/9] 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/9] 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/9] 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/9] 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/9] 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/9] 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', From 8278f06cc82a2c480895148c7bd7f57592e24d1b Mon Sep 17 00:00:00 2001 From: enkore Date: Sun, 23 Jul 2023 15:55:49 +0200 Subject: [PATCH 9/9] remove krb, static libcrypto -rw-r--r--. 1 marx marx 1898144 Jul 23 16:21 ssh_python-1.0.0.dev10+g60f87f9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl --- ci/build-manylinux.sh | 8 ++++---- ci/build-wheels.sh | 2 +- ci/docker/manylinux/Dockerfile.2014_x86_64 | 18 +++++++++++------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/ci/build-manylinux.sh b/ci/build-manylinux.sh index dd79a0a8..34321aa8 100755 --- a/ci/build-manylinux.sh +++ b/ci/build-manylinux.sh @@ -48,9 +48,9 @@ for docker_file in "${docker_files[@]}"; do docker_tag="${docker_repo}:2_28_aarch64" fi echo "Docker tag is ${docker_tag}" - docker pull $docker_tag || echo - docker build --pull --cache-from $docker_tag ci/docker/manylinux -t $docker_tag -f "${docker_file}" - if [[ -z "${CIRCLE_PULL_REQUEST}" ]]; then docker push $docker_tag; fi - docker run --rm -v "$(pwd)":/io $docker_tag /io/ci/build-wheels.sh + #podman pull $docker_tag || echo + podman build ci/docker/manylinux -t $docker_tag -f "${docker_file}" + #if [[ -z "${CIRCLE_PULL_REQUEST}" ]]; then docker push $docker_tag; fi + podman run --rm -v "$(pwd)":/io:Z $docker_tag /io/ci/build-wheels.sh ls wheelhouse/ done diff --git a/ci/build-wheels.sh b/ci/build-wheels.sh index c06b4b55..6ce3a586 100755 --- a/ci/build-wheels.sh +++ b/ci/build-wheels.sh @@ -1,4 +1,4 @@ -#!/bin/bash -xe +#!/bin/bash -x # This file is part of ssh-python. # Copyright (C) 2017-2022 Panos Kittenis and contributors. # diff --git a/ci/docker/manylinux/Dockerfile.2014_x86_64 b/ci/docker/manylinux/Dockerfile.2014_x86_64 index f41d79b4..60ff097d 100644 --- a/ci/docker/manylinux/Dockerfile.2014_x86_64 +++ b/ci/docker/manylinux/Dockerfile.2014_x86_64 @@ -4,7 +4,7 @@ ENV OPENSSL openssl-3.1.1 ENV LIBSSH 0.10.5 ENV KRB 1.21.1 ENV SYSTEM_LIBSSH 1 -ENV CFLAGS "-g0 -s" +ENV CFLAGS "-g0 -s -flto -fpic -fno-semantic-interposition" RUN yum install -y zlib-devel cmake3 perl-core @@ -15,19 +15,23 @@ 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 && \ + ./config --prefix=/usr --openssldir=/usr/openssl threads no-shared no-stdio \ + no-autoerrinit no-autoload-config no-autoalginit no-cmp no-cms no-comp no-ct no-dgram no-dso no-filenames no-gost no-ocsp \ + no-psk no-rfc3779 no-sock no-srp no-srtp no-ts \ + no-aria no-bf no-blake2 no-camellia no-cast no-cmac no-idea no-md4 no-mdc2 no-ocb no-rc2 no-rc4 no-rmd160 no-siphash no-siv no-sm2 no-sm3 no-sm4 no-whirlpool \ + && \ make -j6 && make install_sw # Kerberos -RUN cd krb5-${KRB}.tar.xz/krb5-${KRB}/src && \ - ./configure && \ - make -j6 && \ - make install +#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 && \ + -DWITH_EXAMPLES=OFF && \ make -j6 install/strip RUN rm -rf ${OPENSSL}* libssh build_libssh krb5-${KRB}.tar.xz pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy