diff --git a/ci/docker/manylinux/Dockerfile b/ci/docker/manylinux/Dockerfile index a58fc1f7..f3fc5cc7 100644 --- a/ci/docker/manylinux/Dockerfile +++ b/ci/docker/manylinux/Dockerfile @@ -1,23 +1,24 @@ FROM quay.io/pypa/manylinux2010_x86_64 ENV OPENSSL openssl-1.1.1g -ENV LIBSSH 0.9.5 +ENV LIBSSH 0.9.6 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-1.18.2.tar.xz krb5-1.18.2.tar.xz +ADD krb5-1.18.4.tar.xz krb5-1.18.4.tar.xz RUN tar -xzf ${OPENSSL}.tar.gz # Openssl RUN cd ${OPENSSL} && \ ./config --prefix=/usr --openssldir=/usr/openssl threads shared && \ - make -j6 && make install + make -j6 && make install_sw # Kerberos -RUN cd krb5-1.18.2.tar.xz/krb5-1.18.2/src && \ +RUN cd krb5-1.18.4.tar.xz/krb5-1.18.4/src && \ ./configure && \ make -j6 && \ make install @@ -26,8 +27,8 @@ RUN cd krb5-1.18.2.tar.xz/krb5-1.18.2/src && \ RUN mkdir -p build_libssh && cd build_libssh && \ cmake3 ../libssh.tar.xz/libssh-${LIBSSH} -DCMAKE_BUILD_TYPE=Release \ -DWITH_GSS_API=ON && \ - make -j6 install + make -j6 install/strip -RUN rm -rf ${OPENSSL}* libssh build_libssh krb5-1.18.2.tar.xz +RUN rm -rf ${OPENSSL}* libssh build_libssh krb5-1.18.4.tar.xz VOLUME /var/cache diff --git a/ci/docker/manylinux/krb5-1.18.2.tar.xz b/ci/docker/manylinux/krb5-1.18.2.tar.xz deleted file mode 100644 index 4f4795ec..00000000 --- a/ci/docker/manylinux/krb5-1.18.2.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5edbf866236e0b0ec9e8ab67593f8824ea88666c4190d2d2746519fb71691377 -size 6268820 diff --git a/ci/docker/manylinux/krb5-1.18.4.tar.xz b/ci/docker/manylinux/krb5-1.18.4.tar.xz new file mode 100644 index 00000000..7437932c --- /dev/null +++ b/ci/docker/manylinux/krb5-1.18.4.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a98e2692c96d9eba586e491530a76bcf2e8e9022e07eadd5a490bb1ad38aaf3b +size 6095136 diff --git a/ci/docker/manylinux/libssh-0.9.5.tar.xz b/ci/docker/manylinux/libssh-0.9.5.tar.xz deleted file mode 100644 index 352fe2be..00000000 --- a/ci/docker/manylinux/libssh-0.9.5.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:acffef2da98e761fc1fd9c4fddde0f3af60ab44c4f5af05cd1b2d60a3fa08718 -size 502876 diff --git a/ci/docker/manylinux/libssh-0.9.5.tar.xz.asc b/ci/docker/manylinux/libssh-0.9.5.tar.xz.asc deleted file mode 100644 index bf12d8af..00000000 --- a/ci/docker/manylinux/libssh-0.9.5.tar.xz.asc +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQIzBAABCgAdFiEEjf9T4Y8qvI2PPJIjfuD8TcwBTj0FAl9aH9kACgkQfuD8TcwB -Tj35ZA/9G7lNf/byK3cJeXKb8Lp2oZ3iiAral4uT/cylnXnEa7dOoTjwV5MYvQqm -BDYFta7wsGBEWLOLrtyDJr4+krh9TSs53UVwieRTd0Z87MlcTb+a0gtiJa3Y5Gdv -QNge9rnUGr1MdTwvpPcSvQmoa7iH9HGzC2KrOCCyihUWX9kB+DNKWeSGJAZLNIJv -C3DvB8N0di/X5f74loRsAkwA6DAfiRtd8QyuqY7NeP3ZK/cEG5R/4WpCmCHCriBI -oBamKQT2CmNkHGCxMhN5iQFcm3D92lKdTLrMP+v0HlZnIjkzVJVBJeqn7FkWT967 -JvGqDGEiNozH4eGGjQn5SyHaVCQIv5S815L2mEKG+p0F8BvW6fQs34/RA5np3J2s -SPSFhzKuORePQzoVzF8/Jsf7cTTuzgaSFKi2dkbgkqe39DnKOWhT0K6QVGfNbajz -C/a9GVRl7t6Q/kNR6dFAqc++7civlfQf2Dav1NfEobJxR+DpO5CPXBCuauTXgP8Y -gbvQjfBqk2Gl4VOfCObtEfLiHPNeLI/QpKq9+KAtQlWFawCOhIZsBH/p2ynDI+XJ -wxfLiXPkfeNuQUUuP126mkG9GxbsHGLY38p4WKEQQ3zVx1Pxilq77ZhKGMmTgnvA -/ArOwn3wNwgoP6OQdsy1hxTk16TZ+pRttJyhrdebEX7DnxAgPyw= -=eqzl ------END PGP SIGNATURE----- diff --git a/ci/docker/manylinux/libssh-0.9.6.tar.xz b/ci/docker/manylinux/libssh-0.9.6.tar.xz new file mode 100644 index 00000000..fcfcdd1c --- /dev/null +++ b/ci/docker/manylinux/libssh-0.9.6.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:86bcf885bd9b80466fe0e05453c58b877df61afa8ba947a58c356d7f0fab829b +size 1053056 diff --git a/ci/docker/manylinux/libssh-0.9.6.tar.xz.asc b/ci/docker/manylinux/libssh-0.9.6.tar.xz.asc new file mode 100644 index 00000000..cbed27f4 --- /dev/null +++ b/ci/docker/manylinux/libssh-0.9.6.tar.xz.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEjf9T4Y8qvI2PPJIjfuD8TcwBTj0FAmEniOkACgkQfuD8TcwB +Tj0TKQ/9HiMAGSMHoQ+iPVLP06iTc6Cy7rNyON2nPDQwAz0V/dfvkrKAAEflfgYd +3pt3dbE/qgh2kgQLb9kpbCUmFoGuLgKz36RPOsggwuOsN+eD1n65q8W39sMOQid3 +bjUIOKRdYWC1suZ9fMAO1Ignl69Opd8dAq1Has9YzglaeQaV/lnYQOW4UG0xKHck +ZOp2qLfjmaQiBAI61eRyxqIYC0F67WKd0bo9D2csoocDVvHLq4syPdbMOfDTB+LL +KZSAZVW1R1JUVZMkp/P/HU11jNNy3wKoLafocnq8bXkPVrqhyuo+hDJV/OPUvFLa +VE/BzIRoMNG+1R+GJpwE7ut2DIHPxnZTThRkeVN5qP1+hbhgLJhW62I+HeAnD4s+ ++W7fwJovN28I+wqSjVEP8JguprVuoDAX5jVHbeZoMT7p8ATA4Nh3KCbYELEwTtFG +zsEIlBvoNXD3ce7xGXL3MPqfgKqrZQjRG/iOWvKwDV7WrqK1cFFyL7aeBfK2+dQq +1Ew7aYlTsH6Hap7XByeSsy4Z5ts3VXIoFix/h+Br5OTYKYgITM7bijNAQ6A2ZWQN +TxCv8X0sVyaGyXhxG6QhrEWZjFe496MneZkq9e6HKZyaSbzwFwMgOvrUUC7fa8e5 +o1Rvozah81U0nsikwTmDrm15RSK3mr2X34zPW2Ahzr1I5tGZzOk= +=cO0k +-----END PGP SIGNATURE----- diff --git a/libssh/.arcconfig b/libssh/.arcconfig new file mode 100644 index 00000000..30b1a60c --- /dev/null +++ b/libssh/.arcconfig @@ -0,0 +1,4 @@ +{ + "phabricator.uri" : "https://bugs.libssh.org/", + "history.immutable": true +} diff --git a/libssh/.gitlab-ci.yml b/libssh/.gitlab-ci.yml new file mode 100644 index 00000000..e2b99e00 --- /dev/null +++ b/libssh/.gitlab-ci.yml @@ -0,0 +1,524 @@ +variables: + BUILD_IMAGES_PROJECT: libssh/build-images + FEDORA_BUILD: buildenv-fedora + CENTOS7_BUILD: buildenv-centos7 + TUMBLEWEED_BUILD: buildenv-tumbleweed + MINGW_BUILD: buildenv-mingw + +# 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 + script: + - mkdir -p obj && cd obj && cmake3 + -DCMAKE_BUILD_TYPE=RelWithDebInfo + -DPICKY_DEVELOPER=ON + -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON + -DUNIT_TESTING=ON -DCLIENT_TESTING=ON .. && + make -j$(nproc) && ctest --output-on-failure + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + +fedora/openssl_1.1.x/x86_64: + image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD + script: + - 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 + -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. && + make -j$(nproc) && ctest --output-on-failure + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + +fedora/openssl_1.1.x/x86_64/fips: + image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD + script: + - echo 1 > /etc/system-fips + - update-crypto-policies --set FIPS + - 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 + -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. && + make -j$(nproc) && OPENSSL_FORCE_FIPS_MODE=1 ctest --output-on-failure + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + +fedora/openssl_1.1.x/x86_64/minimal: + image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD + script: + - mkdir -p obj && cd obj && cmake + -DCMAKE_BUILD_TYPE=RelWithDebInfo + -DPICKY_DEVELOPER=ON + -DWITH_SFTP=OFF -DWITH_SERVER=OFF -DWITH_ZLIB=OFF -DWITH_PCAP=OFF + -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DWITH_GEX=OFF .. && + make -j$(nproc) && ctest --output-on-failure + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + +# 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: + image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD + script: + - mkdir -p obj && cd obj && cmake + -DCMAKE_BUILD_TYPE=AddressSanitizer + -DPICKY_DEVELOPER=ON + -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON + -DUNIT_TESTING=ON .. && + make -j$(nproc) && ctest --output-on-failure + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + +# This is disabled as it report OpenSSL issues +# It also has ethe same issues with cwrap as AddressSanitizer +.fedora/memory-sanitizer: + image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD + script: + - mkdir -p obj && cd obj && cmake + -DCMAKE_BUILD_TYPE=MemorySanitizer + -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ + -DPICKY_DEVELOPER=ON + -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON + -DUNIT_TESTING=ON .. + && make -j$(nproc) && ctest --output-on-failure + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + +fedora/undefined-sanitizer: + image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD + script: + - mkdir -p obj && cd obj && cmake + -DCMAKE_BUILD_TYPE=UndefinedSanitizer + -DPICKY_DEVELOPER=ON + -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON + -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. + && make -j$(nproc) && ctest --output-on-failure + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + +fedora/csbuild: + variables: + GIT_DEPTH: "100" + image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD + 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" + + - 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 @SRCDIR@ && make clean && make -j$(nproc)" + --git-commit-range $CI_COMMIT_RANGE + --color + --print-current --print-fixed + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj-csbuild/ + +# 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: + 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 .. && + make && ctest --output-on-failure + tags: + - freebsd + - private + except: + - tags + only: + - branches@libssh/libssh-mirror + - branches@cryptomilk/libssh-mirror + - branches@jjelen/libssh-mirror + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + +fedora/libgcrypt/x86_64: + image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD + 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 -DCLIENT_TESTING=ON -DSERVER_TESTING=ON + -DWITH_GCRYPT=ON -DWITH_DEBUG_CRYPTO=ON .. && + make -j$(nproc) && ctest --output-on-failure + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + +fedora/mbedtls/x86_64: + image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD + 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 -DCLIENT_TESTING=ON -DSERVER_TESTING=ON + -DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON .. && + make -j$(nproc) && ctest --output-on-failure + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + +# 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 + script: + - export WINEPATH=/usr/x86_64-w64-mingw32/sys-root/mingw/bin + - export WINEDEBUG=-all + - mkdir -p obj && cd obj && mingw64-cmake + -DCMAKE_BUILD_TYPE=RelWithDebInfo + -DPICKY_DEVELOPER=ON + -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON + -DUNIT_TESTING=ON .. && + make -j$(nproc) && + ctest --output-on-failure + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + +# 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 + script: + - export WINEPATH=/usr/i686-w64-mingw32/sys-root/mingw/bin + - export WINEDEBUG=-all + - mkdir -p obj && cd obj && mingw32-cmake + -DCMAKE_BUILD_TYPE=RelWithDebInfo + -DPICKY_DEVELOPER=ON + -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON + -DUNIT_TESTING=ON .. && + make -j$(nproc) && + ctest --output-on-failure + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + +tumbleweed/openssl_1.1.x/x86_64/gcc: + image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD + 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 + -DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config + -DUNIT_TESTING=ON -DSERVER_TESTING=ON .. && + make -j$(nproc) && ctest --output-on-failure + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + +tumbleweed/openssl_1.1.x/x86/gcc: + image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD + script: + - mkdir -p obj && cd obj && cmake + -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake + -DCMAKE_BUILD_TYPE=RelWithDebInfo + -DPICKY_DEVELOPER=ON + -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON + -DUNIT_TESTING=ON .. && + make -j$(nproc) && ctest --output-on-failure + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + +tumbleweed/openssl_1.1.x/x86_64/gcc7: + image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD + script: + - mkdir -p obj && cd obj && cmake + -DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7 + -DCMAKE_BUILD_TYPE=RelWithDebInfo + -DPICKY_DEVELOPER=ON + -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON + -DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config + -DUNIT_TESTING=ON -DSERVER_TESTING=ON .. && + make -j$(nproc) && ctest --output-on-failure + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + +tumbleweed/openssl_1.1.x/x86/gcc7: + image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD + script: + - mkdir -p obj && cd obj && cmake + -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake + -DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7 + -DCMAKE_BUILD_TYPE=RelWithDebInfo + -DPICKY_DEVELOPER=ON + -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON + -DUNIT_TESTING=ON .. && + make -j$(nproc) && ctest --output-on-failure + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + +tumbleweed/openssl_1.1.x/x86_64/clang: + image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD + script: + - mkdir -p obj && cd obj && cmake + -DCMAKE_BUILD_TYPE=RelWithDebInfo + -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ + -DPICKY_DEVELOPER=ON + -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON + -DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config + -DUNIT_TESTING=ON + -DSERVER_TESTING=ON .. && + make -j$(nproc) && ctest --output-on-failure + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + +tumbleweed/docs: + image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD + script: + - mkdir -p obj && cd obj && cmake .. && make docs + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + +tumbleweed/undefined-sanitizer: + image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD + script: + - mkdir -p obj && cd obj && cmake + -DCMAKE_BUILD_TYPE=UndefinedSanitizer + -DPICKY_DEVELOPER=ON + -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON + -DUNIT_TESTING=ON -DSERVER_TESTING=ON .. && + make -j$(nproc) && ctest --output-on-failure + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + +tumbleweed/static-analysis: + image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD + script: + - export CCC_CC=clang + - export CCC_CXX=clang++ + - mkdir -p obj && cd obj && scan-build cmake + -DCMAKE_BUILD_TYPE=Debug + -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ + -DPICKY_DEVELOPER=ON + -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON + -DUNIT_TESTING=ON -DSERVER_TESTING=ON .. && + scan-build --status-bugs -o scan make -j$(nproc) + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/scan + +############################################################################### +# Visual Studio builds # +############################################################################### +.vs: + stage: test + cache: + key: vcpkg.${CI_JOB_NAME} + paths: + - .vcpkg + variables: + ErrorActionPreference: STOP + script: + - $env:VCPKG_DEFAULT_TRIPLET="x64-windows" + - mkdir -p obj; if ($?) {cd obj}; if (! $?) {exit 1} + - cmake + -A x64 + -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_TOOLCHAIN_FILE" + -DPICKY_DEVELOPER=ON + -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON + -DUNIT_TESTING=ON .. + - 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 .. + # The Windows runners are broken for last month + # https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/-/issues/40 + allow_failure: true + +visualstudio/x86_64: + extends: .vs + variables: + PLATFORM: "x64" + TRIPLET: "x64" + +visualstudio/x86: + extends: .vs + variables: + PLATFORM: "win32" + TRIPLET: "x86" diff --git a/libssh/CMakeLists.txt b/libssh/CMakeLists.txt index 1f5b0bf5..a993012e 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.9.5 LANGUAGES C) +project(libssh VERSION 0.9.6 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.8.6") +set(LIBRARY_VERSION "4.8.7") set(LIBRARY_SOVERSION "4") # where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked @@ -59,7 +59,13 @@ elseif(WITH_MBEDTLS) endif (NOT MBEDTLS_FOUND) else (WITH_GCRYPT) find_package(OpenSSL) - if (NOT OPENSSL_FOUND) + if (OPENSSL_FOUND) + # On CMake < 3.16, OPENSSL_CRYPTO_LIBRARIES is usually a synonym for OPENSSL_CRYPTO_LIBRARY, but is not defined + # when building on Windows outside of Cygwin. We provide the synonym here, if FindOpenSSL didn't define it already. + if (NOT DEFINED OPENSSL_CRYPTO_LIBRARIES) + set(OPENSSL_CRYPTO_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) + endif (NOT DEFINED OPENSSL_CRYPTO_LIBRARIES) + else (OPENSSL_FOUND) find_package(GCrypt) if (NOT GCRYPT_FOUND) find_package(MbedTLS) @@ -67,7 +73,7 @@ else (WITH_GCRYPT) message(FATAL_ERROR "Could not find OpenSSL, GCrypt or mbedTLS") endif (NOT MBEDTLS_FOUND) endif (NOT GCRYPT_FOUND) - endif (NOT OPENSSL_FOUND) + endif (OPENSSL_FOUND) endif(WITH_GCRYPT) if (UNIT_TESTING) @@ -203,10 +209,10 @@ if (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND) endif(UPDATE_ABI) endif (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND) -add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source DEPENDS ${_SYMBOL_TARGET}) +add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source DEPENDS ${_SYMBOL_TARGET} VERBATIM) # Link compile database for clangd -execute_process(COMMAND cmake -E create_symlink +execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${CMAKE_BINARY_DIR}/compile_commands.json" "${CMAKE_SOURCE_DIR}/compile_commands.json") diff --git a/libssh/ChangeLog b/libssh/ChangeLog index 3431d837..1f3aac98 100644 --- a/libssh/ChangeLog +++ b/libssh/ChangeLog @@ -1,7 +1,23 @@ ChangeLog ========== -version 0.9.5 (released 2020-XX-XX) +version 0.9.6 (released 2021-08-26) + * CVE-2021-3634: Fix possible heap-buffer overflow when rekeying with + different key exchange mechanism + * Fix several memory leaks on error paths + * Reset pending_call_state on disconnect + * Fix handshake bug with AEAD ciphers and no HMAC overlap + * Use OPENSSL_CRYPTO_LIBRARIES in CMake + * Ignore request success and failure message if they are not expected + * Support more identity files in configuration + * Avoid setting compiler flags directly in CMake + * Support build directories with special characters + * Include stdlib.h to avoid crash in Windows + * Fix sftp_new_channel constructs an invalid object + * Fix Ninja multiple rules error + * Several tests fixes + +version 0.9.5 (released 2020-09-10) * CVE-2020-16135: Avoid null pointer dereference in sftpserver (T232) * Improve handling of library initialization (T222) * Fix parsing of subsecond times in SFTP (T219) diff --git a/libssh/ConfigureChecks.cmake b/libssh/ConfigureChecks.cmake index c8bb2aa0..5d43b36d 100644 --- a/libssh/ConfigureChecks.cmake +++ b/libssh/ConfigureChecks.cmake @@ -101,53 +101,53 @@ if (OPENSSL_FOUND) check_include_file(openssl/ecdsa.h HAVE_OPENSSL_ECDSA_H) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) - set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) + set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES}) check_function_exists(EVP_aes_128_ctr HAVE_OPENSSL_EVP_AES_CTR) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) - set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) + set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES}) check_function_exists(EVP_aes_128_cbc HAVE_OPENSSL_EVP_AES_CBC) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) - set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) + set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES}) check_function_exists(EVP_aes_128_gcm HAVE_OPENSSL_EVP_AES_GCM) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) - set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) + set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES}) check_function_exists(CRYPTO_THREADID_set_callback HAVE_OPENSSL_CRYPTO_THREADID_SET_CALLBACK) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) - set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) + set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES}) check_function_exists(CRYPTO_ctr128_encrypt HAVE_OPENSSL_CRYPTO_CTR128_ENCRYPT) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) - set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) + set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES}) check_function_exists(EVP_CIPHER_CTX_new HAVE_OPENSSL_EVP_CIPHER_CTX_NEW) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) - set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) + set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES}) check_function_exists(EVP_KDF_CTX_new_id HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) - set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) + set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES}) check_function_exists(FIPS_mode HAVE_OPENSSL_FIPS_MODE) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) - set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) + set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES}) check_function_exists(RAND_priv_bytes HAVE_OPENSSL_RAND_PRIV_BYTES) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) - set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) + set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES}) check_function_exists(EVP_DigestSign HAVE_OPENSSL_EVP_DIGESTSIGN) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) - set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) + set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES}) check_function_exists(EVP_DigestVerify HAVE_OPENSSL_EVP_DIGESTVERIFY) check_function_exists(OPENSSL_ia32cap_loc HAVE_OPENSSL_IA32CAP_LOC) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) - set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) + set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES}) check_symbol_exists(EVP_PKEY_ED25519 "openssl/evp.h" FOUND_OPENSSL_ED25519) if (HAVE_OPENSSL_EVP_DIGESTSIGN AND HAVE_OPENSSL_EVP_DIGESTVERIFY AND @@ -156,7 +156,7 @@ if (OPENSSL_FOUND) endif() set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) - set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) + set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES}) check_symbol_exists(EVP_PKEY_X25519 "openssl/evp.h" HAVE_OPENSSL_X25519) unset(CMAKE_REQUIRED_INCLUDES) diff --git a/libssh/cmake/Modules/FindABIMap.cmake b/libssh/cmake/Modules/FindABIMap.cmake index e0520abd..5117b498 100644 --- a/libssh/cmake/Modules/FindABIMap.cmake +++ b/libssh/cmake/Modules/FindABIMap.cmake @@ -302,12 +302,13 @@ function(get_file_list _TARGET_NAME) add_custom_target( ${_TARGET_NAME}_int ALL COMMAND ${CMAKE_COMMAND} - -DOUTPUT_PATH="${_get_files_list_OUTPUT_PATH}" - -DDIRECTORIES="${_get_files_list_DIRECTORIES}" - -DFILES_PATTERNS="${_get_files_list_FILES_PATTERNS}" + -DOUTPUT_PATH=${_get_files_list_OUTPUT_PATH} + -DDIRECTORIES=${_get_files_list_DIRECTORIES} + -DFILES_PATTERNS=${_get_files_list_FILES_PATTERNS} -P ${_GET_FILES_LIST_SCRIPT} COMMENT "Searching for files" + VERBATIM ) if (DEFINED _get_files_list_COPY_TO) @@ -318,6 +319,7 @@ function(get_file_list _TARGET_NAME) ${_FILES_LIST_OUTPUT_PATH} ${_get_files_list_COPY_TO} DEPENDS ${_TARGET_NAME}_int COMMENT "Copying ${_TARGET_NAME} to ${_get_files_list_COPY_TO}" + VERBATIM ) else() add_custom_target(${_TARGET_NAME} ALL @@ -369,12 +371,13 @@ function(extract_symbols _TARGET_NAME) add_custom_target( ${_TARGET_NAME}_int ALL COMMAND ${CMAKE_COMMAND} - -DOUTPUT_PATH="${_SYMBOLS_OUTPUT_PATH}" - -DHEADERS_LIST_FILE="${_HEADERS_LIST_FILE}" + -DOUTPUT_PATH=${_SYMBOLS_OUTPUT_PATH} + -DHEADERS_LIST_FILE=${_HEADERS_LIST_FILE} -DFILTER_PATTERN=${_extract_symbols_FILTER_PATTERN} -P ${_EXTRACT_SYMBOLS_SCRIPT} DEPENDS ${_extract_symbols_HEADERS_LIST} COMMENT "Extracting symbols from headers" + VERBATIM ) if (DEFINED _extract_symbols_COPY_TO) @@ -385,6 +388,7 @@ function(extract_symbols _TARGET_NAME) ${_SYMBOLS_OUTPUT_PATH} ${_extract_symbols_COPY_TO} DEPENDS ${_TARGET_NAME}_int COMMENT "Copying ${_TARGET_NAME} to ${_extract_symbols_COPY_TO}" + VERBATIM ) else() add_custom_target(${_TARGET_NAME} ALL @@ -449,35 +453,37 @@ function(generate_map_file _TARGET_NAME) ${_TARGET_NAME}_int ALL COMMAND ${CMAKE_COMMAND} -DABIMAP_EXECUTABLE=${ABIMAP_EXECUTABLE} - -DSYMBOLS="${_SYMBOLS_FILE}" + -DSYMBOLS=${_SYMBOLS_FILE} -DCURRENT_MAP=${_generate_map_file_CURRENT_MAP} - -DOUTPUT_PATH="${_MAP_OUTPUT_PATH}" + -DOUTPUT_PATH=${_MAP_OUTPUT_PATH} -DFINAL=${_generate_map_file_FINAL} -DBREAK_ABI=${_generate_map_file_BREAK_ABI} -DRELEASE_NAME_VERSION=${_generate_map_file_RELEASE_NAME_VERSION} -P ${_GENERATE_MAP_SCRIPT} DEPENDS ${_generate_map_file_SYMBOLS} COMMENT "Generating the map ${_TARGET_NAME}" + VERBATIM ) # Add a custom command setting the map as OUTPUT to allow it to be added as # a generated source add_custom_command( OUTPUT ${_MAP_OUTPUT_PATH} - DEPENDS ${_TARGET_NAME} + DEPENDS ${_TARGET_NAME}_copy ) if (DEFINED _generate_map_file_COPY_TO) # Copy the generated map back to the COPY_TO - add_custom_target(${_TARGET_NAME} ALL + add_custom_target(${_TARGET_NAME}_copy ALL COMMAND ${CMAKE_COMMAND} -E copy_if_different ${_MAP_OUTPUT_PATH} ${_generate_map_file_COPY_TO} DEPENDS ${_TARGET_NAME}_int COMMENT "Copying ${_MAP_OUTPUT_PATH} to ${_generate_map_file_COPY_TO}" + VERBATIM ) else() - add_custom_target(${_TARGET_NAME} ALL + add_custom_target(${_TARGET_NAME}_copy ALL DEPENDS ${_TARGET_NAME}_int ) endif() diff --git a/libssh/examples/libssh_scp.c b/libssh/examples/libssh_scp.c index 7a30b37f..7e086422 100644 --- a/libssh/examples/libssh_scp.c +++ b/libssh/examples/libssh_scp.c @@ -233,7 +233,7 @@ static int open_location(struct location *loc, int flag) { loc->file = fopen(loc->path, flag == READ ? "r":"w"); if (!loc->file) { if (errno == EISDIR) { - if (chdir(loc->path)) { + if (loc->path != NULL && chdir(loc->path)) { fprintf(stderr, "Error changing directory to %s: %s\n", loc->path, strerror(errno)); diff --git a/libssh/examples/sshd_direct-tcpip.c b/libssh/examples/sshd_direct-tcpip.c index 35898880..e8d5a6ce 100644 --- a/libssh/examples/sshd_direct-tcpip.c +++ b/libssh/examples/sshd_direct-tcpip.c @@ -88,7 +88,11 @@ cleanup_push(struct cleanup_node_struct** head_ref, // Allocate memory for node struct cleanup_node_struct *new_node = malloc(sizeof *new_node); - new_node->next = (*head_ref); + if (head_ref != NULL) { + new_node->next = *head_ref; + } else { + new_node->next = NULL; + } // Copy new_data new_node->data = new_data; @@ -514,6 +518,12 @@ message_callback(UNUSED_PARAM(ssh_session session), pFd = malloc(sizeof *pFd); cb_chan = malloc(sizeof *cb_chan); event_fd_data = malloc(sizeof *event_fd_data); + if (pFd == NULL || cb_chan == NULL || event_fd_data == NULL) { + SAFE_FREE(pFd); + SAFE_FREE(cb_chan); + SAFE_FREE(event_fd_data); + return 1; + } (*pFd) = socket_fd; event_fd_data->channel = channel; diff --git a/libssh/include/libssh/crypto.h b/libssh/include/libssh/crypto.h index ede71661..489b4905 100644 --- a/libssh/include/libssh/crypto.h +++ b/libssh/include/libssh/crypto.h @@ -126,8 +126,9 @@ struct ssh_crypto_struct { ssh_curve25519_pubkey curve25519_server_pubkey; #endif ssh_string dh_server_signature; /* information used by dh_handshake. */ - size_t digest_len; /* len of the two fields below */ + size_t session_id_len; unsigned char *session_id; + size_t digest_len; /* len of the secret hash */ unsigned char *secret_hash; /* Secret hash is same as session id until re-kex */ unsigned char *encryptIV; unsigned char *decryptIV; diff --git a/libssh/include/libssh/libssh.h b/libssh/include/libssh/libssh.h index d0776686..1664dfce 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-2009 by Aris Adamantiadis + * Copyright (c) 2003-2021 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 diff --git a/libssh/include/libssh/packet.h b/libssh/include/libssh/packet.h index 8fc7ce42..561bba8e 100644 --- a/libssh/include/libssh/packet.h +++ b/libssh/include/libssh/packet.h @@ -80,7 +80,7 @@ int ssh_packet_decrypt(ssh_session session, uint8_t *destination, uint8_t *sourc size_t start, size_t encrypted_size); unsigned char *ssh_packet_encrypt(ssh_session session, void *packet, - unsigned int len); + uint32_t len); int ssh_packet_hmac_verify(ssh_session session, const void *data, size_t len, unsigned char *mac, enum ssh_hmac_e type); int ssh_packet_set_newkeys(ssh_session session, diff --git a/libssh/include/libssh/pki.h b/libssh/include/libssh/pki.h index 9b104349..2fa7582c 100644 --- a/libssh/include/libssh/pki.h +++ b/libssh/include/libssh/pki.h @@ -125,6 +125,8 @@ enum ssh_digest_e ssh_key_hash_from_name(const char *name); /* SSH Signature Functions */ ssh_signature ssh_signature_new(void); void ssh_signature_free(ssh_signature sign); +#define SSH_SIGNATURE_FREE(x) \ + do { ssh_signature_free(x); x = NULL; } while(0) int ssh_pki_export_signature_blob(const ssh_signature sign, ssh_string *sign_blob); diff --git a/libssh/src/ABI/current b/libssh/src/ABI/current index c0f6eef2..4850fb30 100644 --- a/libssh/src/ABI/current +++ b/libssh/src/ABI/current @@ -1 +1 @@ -4.8.6 \ No newline at end of file +4.8.7 \ No newline at end of file diff --git a/libssh/src/CMakeLists.txt b/libssh/src/CMakeLists.txt index ccf5a337..a576cf71 100644 --- a/libssh/src/CMakeLists.txt +++ b/libssh/src/CMakeLists.txt @@ -16,7 +16,7 @@ if (WIN32) ) endif (WIN32) -if (OPENSSL_CRYPTO_LIBRARY) +if (OPENSSL_CRYPTO_LIBRARIES) set(LIBSSH_PRIVATE_INCLUDE_DIRS ${LIBSSH_PRIVATE_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} @@ -24,9 +24,9 @@ if (OPENSSL_CRYPTO_LIBRARY) set(LIBSSH_LINK_LIBRARIES ${LIBSSH_LINK_LIBRARIES} - ${OPENSSL_CRYPTO_LIBRARY} + ${OPENSSL_CRYPTO_LIBRARIES} ) -endif (OPENSSL_CRYPTO_LIBRARY) +endif (OPENSSL_CRYPTO_LIBRARIES) if (MBEDTLS_CRYPTO_LIBRARY) set(LIBSSH_PRIVATE_INCLUDE_DIRS @@ -331,7 +331,7 @@ target_link_libraries(ssh PRIVATE ${LIBSSH_LINK_LIBRARIES}) if (WIN32 AND NOT BUILD_SHARED_LIBS) - set_target_properties(ssh PROPERTIES COMPILE_FLAGS "-DLIBSSH_STATIC") + target_compile_definitions(ssh PUBLIC "LIBSSH_STATIC") endif () add_library(ssh::ssh ALIAS ssh) @@ -342,9 +342,7 @@ if (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT) set(MAP_PATH "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_dev.map") endif (ABIMAP_FOUND) - set_target_properties(ssh - PROPERTIES LINK_FLAGS - "-Wl,--version-script,\"${MAP_PATH}\"") + target_link_libraries(ssh PRIVATE "-Wl,--version-script,\"${MAP_PATH}\"") endif (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT) set_target_properties(ssh @@ -358,12 +356,12 @@ set_target_properties(ssh ) if (WITH_VISIBILITY_HIDDEN) - set_target_properties(ssh PROPERTIES COMPILE_FLAGS "-fvisibility=hidden") + set_target_properties(ssh PROPERTIES C_VISIBILITY_PRESET hidden) endif (WITH_VISIBILITY_HIDDEN) if (MINGW) - set_target_properties(ssh PROPERTIES LINK_FLAGS "-Wl,--enable-stdcall-fixup") - set_target_properties(ssh PROPERTIES COMPILE_FLAGS "-D_POSIX_SOURCE") + target_link_libraries(ssh PRIVATE "-Wl,--enable-stdcall-fixup") + target_compile_definitions(ssh PRIVATE "_POSIX_SOURCE") endif () @@ -412,12 +410,7 @@ if (BUILD_STATIC_LIB) ) if (WIN32) - set_target_properties( - ssh-static - PROPERTIES - COMPILE_FLAGS - "-DLIBSSH_STATIC" - ) + target_compile_definitions(ssh-static PUBLIC "LIBSSH_STATIC") endif (WIN32) endif (BUILD_STATIC_LIB) diff --git a/libssh/src/channels.c b/libssh/src/channels.c index 4eea885b..1041dbff 100644 --- a/libssh/src/channels.c +++ b/libssh/src/channels.c @@ -29,6 +29,9 @@ #include #include #include +#ifdef HAVE_SYS_TIME_H +#include +#endif /* HAVE_SYS_TIME_H */ #ifndef _WIN32 #include @@ -117,6 +120,13 @@ ssh_channel ssh_channel_new(ssh_session session) if (session->channels == NULL) { session->channels = ssh_list_new(); + if (session->channels == NULL) { + ssh_set_error_oom(session); + SSH_BUFFER_FREE(channel->stdout_buffer); + SSH_BUFFER_FREE(channel->stderr_buffer); + SAFE_FREE(channel); + return NULL; + } } ssh_list_prepend(session->channels, channel); diff --git a/libssh/src/client.c b/libssh/src/client.c index 4610b787..a4a7317e 100644 --- a/libssh/src/client.c +++ b/libssh/src/client.c @@ -721,6 +721,7 @@ void ssh_disconnect(ssh_session session) { } session->opts.fd = SSH_INVALID_SOCKET; session->session_state=SSH_SESSION_STATE_DISCONNECTED; + session->pending_call_state = SSH_PENDING_CALL_NONE; while ((it=ssh_list_get_iterator(session->channels)) != NULL) { ssh_channel_do_free(ssh_iterator_value(ssh_channel,it)); @@ -770,7 +771,7 @@ void ssh_disconnect(ssh_session session) { } const char *ssh_copyright(void) { - return SSH_STRINGIFY(LIBSSH_VERSION) " (c) 2003-2019 " + return SSH_STRINGIFY(LIBSSH_VERSION) " (c) 2003-2021 " "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 a08e41b8..54ada276 100644 --- a/libssh/src/config.c +++ b/libssh/src/config.c @@ -425,6 +425,7 @@ ssh_config_parse_line(ssh_session session, opcode != SOC_HOST && opcode != SOC_MATCH && opcode != SOC_INCLUDE && + opcode != SOC_IDENTITY && opcode > SOC_UNSUPPORTED) { /* Ignore all unknown types here */ /* Skip all the options that were already applied */ if (seen[opcode] != 0) { diff --git a/libssh/src/connect.c b/libssh/src/connect.c index 252e2c63..ce4d58df 100644 --- a/libssh/src/connect.c +++ b/libssh/src/connect.c @@ -29,6 +29,9 @@ #include #include #include +#ifdef HAVE_SYS_TIME_H +#include +#endif /* HAVE_SYS_TIME_H */ #include "libssh/libssh.h" #include "libssh/misc.h" diff --git a/libssh/src/curve25519.c b/libssh/src/curve25519.c index c13b3604..d2517551 100644 --- a/libssh/src/curve25519.c +++ b/libssh/src/curve25519.c @@ -377,12 +377,12 @@ void ssh_server_curve25519_init(ssh_session session){ */ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){ /* ECDH keys */ - ssh_string q_c_string; - ssh_string q_s_string; + ssh_string q_c_string = NULL; + ssh_string q_s_string = NULL; ssh_string server_pubkey_blob = NULL; /* SSH host keys (rsa,dsa,ecdsa) */ - ssh_key privkey; + ssh_key privkey = NULL; enum ssh_digest_e digest = SSH_DIGEST_AUTO; ssh_string sig_blob = NULL; int rc; @@ -402,7 +402,6 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){ SSH_FATAL, "Incorrect size for server Curve25519 public key: %zu", ssh_string_len(q_c_string)); - SSH_STRING_FREE(q_c_string); goto error; } @@ -460,12 +459,17 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){ /* add ecdh public key */ q_s_string = ssh_string_new(CURVE25519_PUBKEY_SIZE); if (q_s_string == NULL) { + ssh_set_error_oom(session); goto error; } - ssh_string_fill(q_s_string, - session->next_crypto->curve25519_server_pubkey, - CURVE25519_PUBKEY_SIZE); + rc = ssh_string_fill(q_s_string, + session->next_crypto->curve25519_server_pubkey, + CURVE25519_PUBKEY_SIZE); + if (rc < 0) { + ssh_set_error(session, SSH_FATAL, "Could not copy public key"); + goto error; + } rc = ssh_buffer_add_ssh_string(session->out_buffer, q_s_string); SSH_STRING_FREE(q_s_string); @@ -508,6 +512,8 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){ return SSH_PACKET_USED; error: + SSH_STRING_FREE(q_c_string); + SSH_STRING_FREE(q_s_string); ssh_buffer_reinit(session->out_buffer); session->session_state=SSH_SESSION_STATE_ERROR; return SSH_PACKET_USED; diff --git a/libssh/src/dh-gex.c b/libssh/src/dh-gex.c index 9bf0546a..88a97140 100644 --- a/libssh/src/dh-gex.c +++ b/libssh/src/dh-gex.c @@ -263,6 +263,8 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply) bignum_safe_free(server_pubkey); goto error; } + /* The ownership was passed to the crypto structure */ + server_pubkey = NULL; rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob); SSH_STRING_FREE(pubkey_blob); @@ -293,6 +295,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply) return SSH_PACKET_USED; error: + SSH_STRING_FREE(pubkey_blob); ssh_dh_cleanup(session->next_crypto); session->session_state = SSH_SESSION_STATE_ERROR; diff --git a/libssh/src/dh.c b/libssh/src/dh.c index 05903daf..18b71734 100644 --- a/libssh/src/dh.c +++ b/libssh/src/dh.c @@ -361,6 +361,7 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){ rc = ssh_dh_keypair_set_keys(crypto->dh_ctx, DH_SERVER_KEYPAIR, NULL, server_pubkey); if (rc != SSH_OK) { + SSH_STRING_FREE(pubkey_blob); bignum_safe_free(server_pubkey); goto error; } diff --git a/libssh/src/external/ed25519.c b/libssh/src/external/ed25519.c index 8cd58591..41b5f289 100644 --- a/libssh/src/external/ed25519.c +++ b/libssh/src/external/ed25519.c @@ -77,8 +77,8 @@ static void get_hram(unsigned char *hram, } -int crypto_sign_ed25519_keypair(unsigned char *pk, - unsigned char *sk) +int crypto_sign_ed25519_keypair(ed25519_pubkey pk, + ed25519_privkey sk) { sc25519 scsk; ge25519 gepk; @@ -114,7 +114,7 @@ int crypto_sign_ed25519(unsigned char *sm, uint64_t *smlen, const unsigned char *m, uint64_t mlen, - const unsigned char *sk) + const ed25519_privkey sk) { sc25519 sck, scs, scsk; ge25519 ger; @@ -177,7 +177,7 @@ int crypto_sign_ed25519_open(unsigned char *m, uint64_t *mlen, const unsigned char *sm, uint64_t smlen, - const unsigned char *pk) + const ed25519_pubkey pk) { unsigned int i; int ret; diff --git a/libssh/src/getpass.c b/libssh/src/getpass.c index 99627665..c00d0f54 100644 --- a/libssh/src/getpass.c +++ b/libssh/src/getpass.c @@ -255,7 +255,11 @@ int ssh_getpass(const char *prompt, /* disable nonblocking I/O */ if (fd & O_NDELAY) { - fcntl(0, F_SETFL, fd & ~O_NDELAY); + ok = fcntl(0, F_SETFL, fd & ~O_NDELAY); + if (ok < 0) { + perror("fcntl"); + return -1; + } } ok = ssh_gets(prompt, buf, len, verify); @@ -267,7 +271,11 @@ int ssh_getpass(const char *prompt, /* close fd */ if (fd & O_NDELAY) { - fcntl(0, F_SETFL, fd); + ok = fcntl(0, F_SETFL, fd); + if (ok < 0) { + perror("fcntl"); + return -1; + } } if (!ok) { diff --git a/libssh/src/gssapi.c b/libssh/src/gssapi.c index 488df582..1d0fb6ae 100644 --- a/libssh/src/gssapi.c +++ b/libssh/src/gssapi.c @@ -465,8 +465,8 @@ static ssh_buffer ssh_gssapi_build_mic(ssh_session session) rc = ssh_buffer_pack(mic_buffer, "dPbsss", - crypto->digest_len, - (size_t)crypto->digest_len, crypto->session_id, + crypto->session_id_len, + crypto->session_id_len, crypto->session_id, SSH2_MSG_USERAUTH_REQUEST, session->gssapi->user, "ssh-connection", diff --git a/libssh/src/kdf.c b/libssh/src/kdf.c index 0e90e188..09644739 100644 --- a/libssh/src/kdf.c +++ b/libssh/src/kdf.c @@ -138,7 +138,7 @@ int sshkdf_derive_key(struct ssh_crypto_struct *crypto, ssh_mac_update(ctx, key, key_len); ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len); ssh_mac_update(ctx, &letter, 1); - ssh_mac_update(ctx, crypto->session_id, crypto->digest_len); + ssh_mac_update(ctx, crypto->session_id, crypto->session_id_len); ssh_mac_final(digest, ctx); if (requested_len < output_len) { diff --git a/libssh/src/kex.c b/libssh/src/kex.c index 80b6e8ad..82071c74 100644 --- a/libssh/src/kex.c +++ b/libssh/src/kex.c @@ -735,13 +735,29 @@ int ssh_set_client_kex(ssh_session session) return SSH_OK; } +static const char *ssh_find_aead_hmac(const char *cipher) +{ + if (cipher == NULL) { + return NULL; + } else if (strcmp(cipher, "chacha20-poly1305@openssh.com") == 0) { + return "aead-poly1305"; + } else if (strcmp(cipher, "aes256-gcm@openssh.com") == 0) { + return "aead-gcm"; + } else if (strcmp(cipher, "aes128-gcm@openssh.com") == 0) { + return "aead-gcm"; + } + return NULL; +} + /** @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){ +int ssh_kex_select_methods (ssh_session session) +{ struct ssh_kex_struct *server = &session->next_crypto->server_kex; struct ssh_kex_struct *client = &session->next_crypto->client_kex; char *ext_start = NULL; + const char *aead_hmac = NULL; int i; /* Here we should drop the ext-info-c from the list so we avoid matching. @@ -753,7 +769,15 @@ 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]); - if(session->next_crypto->kex_methods[i] == NULL && i < SSH_LANG_C_S){ + + if (i == SSH_MAC_C_S || i == SSH_MAC_S_C) { + aead_hmac = ssh_find_aead_hmac(session->next_crypto->kex_methods[i-2]); + if (aead_hmac) { + free(session->next_crypto->kex_methods[i]); + session->next_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]); return SSH_ERROR; @@ -762,31 +786,31 @@ int ssh_kex_select_methods (ssh_session session){ session->next_crypto->kex_methods[i] = strdup(""); } } - if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group1-sha1") == 0){ + 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){ + } 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){ + } 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){ + } 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){ + } 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){ + } 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){ + } 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){ + } 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){ + } 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){ + } 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){ + } 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){ + } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "curve25519-sha256") == 0){ session->next_crypto->kex_type=SSH_KEX_CURVE25519_SHA256; } SSH_LOG(SSH_LOG_INFO, "Negotiated %s,%s,%s,%s,%s,%s,%s,%s,%s,%s", @@ -806,7 +830,8 @@ 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, int server_kex) +{ struct ssh_kex_struct *kex = (server_kex ? &session->next_crypto->server_kex : &session->next_crypto->client_kex); ssh_string str = NULL; @@ -1023,7 +1048,7 @@ int ssh_make_sessionid(ssh_session session) ssh_buffer_get(server_hash), server_pubkey_blob); SSH_STRING_FREE(server_pubkey_blob); - if(rc != SSH_OK){ + if (rc != SSH_OK){ goto error; } @@ -1197,11 +1222,13 @@ int ssh_make_sessionid(ssh_session session) } memcpy(session->next_crypto->session_id, session->next_crypto->secret_hash, session->next_crypto->digest_len); + /* Initial length is the same as secret hash */ + session->next_crypto->session_id_len = session->next_crypto->digest_len; } #ifdef DEBUG_CRYPTO printf("Session hash: \n"); ssh_log_hexdump("secret hash", session->next_crypto->secret_hash, session->next_crypto->digest_len); - ssh_log_hexdump("session id", session->next_crypto->session_id, session->next_crypto->digest_len); + ssh_log_hexdump("session id", session->next_crypto->session_id, session->next_crypto->session_id_len); #endif rc = SSH_OK; diff --git a/libssh/src/knownhosts.c b/libssh/src/knownhosts.c index fed75f90..f2ef088c 100644 --- a/libssh/src/knownhosts.c +++ b/libssh/src/knownhosts.c @@ -372,6 +372,7 @@ struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session) list = ssh_list_new(); if (list == NULL) { + ssh_set_error_oom(session); SAFE_FREE(host_port); return NULL; } diff --git a/libssh/src/libcrypto.c b/libssh/src/libcrypto.c index 8ff8a02b..3db75df6 100644 --- a/libssh/src/libcrypto.c +++ b/libssh/src/libcrypto.c @@ -392,7 +392,7 @@ int ssh_kdf(struct ssh_crypto_struct *crypto, goto out; } rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID, - crypto->session_id, crypto->digest_len); + crypto->session_id, crypto->session_id_len); if (rc != 1) { goto out; } diff --git a/libssh/src/libmbedcrypto.c b/libssh/src/libmbedcrypto.c index 755c5ebe..a2e74d3b 100644 --- a/libssh/src/libmbedcrypto.c +++ b/libssh/src/libmbedcrypto.c @@ -687,7 +687,7 @@ static void cipher_encrypt(struct ssh_cipher_struct *cipher, } static void cipher_encrypt_cbc(struct ssh_cipher_struct *cipher, void *in, void *out, - unsigned long len) + size_t len) { size_t outlen = 0; int rc = 0; @@ -745,7 +745,7 @@ static void cipher_decrypt(struct ssh_cipher_struct *cipher, } static void cipher_decrypt_cbc(struct ssh_cipher_struct *cipher, void *in, void *out, - unsigned long len) + size_t len) { size_t outlen = 0; int rc = 0; diff --git a/libssh/src/messages.c b/libssh/src/messages.c index 25683b23..a772d488 100644 --- a/libssh/src/messages.c +++ b/libssh/src/messages.c @@ -513,24 +513,30 @@ static int ssh_message_termination(void *s){ * @warning This function blocks until a message has been received. Betterset up * a callback if this behavior is unwanted. */ -ssh_message ssh_message_get(ssh_session session) { - ssh_message msg = NULL; - int rc; +ssh_message ssh_message_get(ssh_session session) +{ + ssh_message msg = NULL; + int rc; - msg=ssh_message_pop_head(session); - if(msg) { - return msg; - } - if(session->ssh_message_list == NULL) { - session->ssh_message_list = ssh_list_new(); - } - rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER, - ssh_message_termination, session); - if(rc || session->session_state == SSH_SESSION_STATE_ERROR) - return NULL; - msg=ssh_list_pop_head(ssh_message, session->ssh_message_list); + msg = ssh_message_pop_head(session); + if (msg != NULL) { + return msg; + } + if (session->ssh_message_list == NULL) { + session->ssh_message_list = ssh_list_new(); + if (session->ssh_message_list == NULL) { + ssh_set_error_oom(session); + return NULL; + } + } + rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER, + ssh_message_termination, session); + if (rc || session->session_state == SSH_SESSION_STATE_ERROR) { + return NULL; + } + msg = ssh_list_pop_head(ssh_message, session->ssh_message_list); - return msg; + return msg; } /** @@ -708,8 +714,8 @@ static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session, rc = ssh_buffer_pack(buffer, "dPbsssbsS", - crypto->digest_len, /* session ID string */ - (size_t)crypto->digest_len, crypto->session_id, + crypto->session_id_len, /* session ID string */ + crypto->session_id_len, crypto->session_id, SSH2_MSG_USERAUTH_REQUEST, /* type */ msg->auth_request.username, service, diff --git a/libssh/src/packet.c b/libssh/src/packet.c index e9ae5648..ec4a7203 100644 --- a/libssh/src/packet.c +++ b/libssh/src/packet.c @@ -688,10 +688,12 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATED - * - session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING * * Transitions: - * - session->global_req_state == SSH_CHANNEL_REQ_STATE_ACCEPTED + * - From channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING + * - To channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED + * + * If not in a pending state, message is ignored in the callback handler. * */ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { @@ -699,21 +701,18 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se break; } - if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING) { - rc = SSH_PACKET_DENIED; - break; - } - rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_REQUEST_FAILURE: // 82 /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATED - * - session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING * * Transitions: - * - session->global_req_state == SSH_CHANNEL_REQ_STATE_DENIED + * - From channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING + * - To channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED + * + * If not in a pending state, message is ignored in the callback handler. * */ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { @@ -721,11 +720,6 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se break; } - if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING) { - rc = SSH_PACKET_DENIED; - break; - } - rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_CHANNEL_OPEN: // 90 @@ -878,10 +872,12 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATED - * - channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING * * Transitions: - * - channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED + * - From channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING + * - To channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED + * + * If not in a pending state, message is ignored in the callback handler. * */ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { @@ -895,10 +891,12 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATED - * - channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING * * Transitions: - * - channel->request_state = SSH_CHANNEL_REQ_STATE_DENIED + * - From channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING + * - To channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED + * + * If not in a pending state, message is ignored in the callback handler. * */ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { @@ -1424,12 +1422,14 @@ void ssh_packet_register_socket_callback(ssh_session session, ssh_socket s){ * @brief sets the callbacks for the packet layer */ 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) { + if (session->packet_callbacks == NULL) { + session->packet_callbacks = ssh_list_new(); + if (session->packet_callbacks == NULL) { + ssh_set_error_oom(session); + return; + } + } ssh_list_append(session->packet_callbacks, callbacks); - } } /** @internal @@ -1899,7 +1899,7 @@ ssh_packet_set_newkeys(ssh_session session, /* Both sides switched: do the actual switch now */ if (session->next_crypto->used == SSH_DIRECTION_BOTH) { - size_t digest_len; + size_t session_id_len; if (session->current_crypto != NULL) { crypto_free(session->current_crypto); @@ -1916,8 +1916,8 @@ ssh_packet_set_newkeys(ssh_session session, return SSH_ERROR; } - digest_len = session->current_crypto->digest_len; - session->next_crypto->session_id = malloc(digest_len); + session_id_len = session->current_crypto->session_id_len; + session->next_crypto->session_id = malloc(session_id_len); if (session->next_crypto->session_id == NULL) { ssh_set_error_oom(session); return SSH_ERROR; @@ -1925,7 +1925,8 @@ ssh_packet_set_newkeys(ssh_session session, memcpy(session->next_crypto->session_id, session->current_crypto->session_id, - digest_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 4e692915..39575b17 100644 --- a/libssh/src/packet_cb.c +++ b/libssh/src/packet_cb.c @@ -129,6 +129,8 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){ } rc = ssh_pki_import_signature_blob(sig_blob, server_key, &sig); + ssh_string_burn(sig_blob); + SSH_STRING_FREE(sig_blob); if (rc != SSH_OK) { goto error; } @@ -152,9 +154,7 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){ server_key, session->next_crypto->secret_hash, session->next_crypto->digest_len); - ssh_string_burn(sig_blob); - SSH_STRING_FREE(sig_blob); - ssh_signature_free(sig); + SSH_SIGNATURE_FREE(sig); if (rc == SSH_ERROR) { goto error; } @@ -170,6 +170,9 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){ session->ssh_connection_callback(session); return SSH_PACKET_USED; error: + SSH_SIGNATURE_FREE(sig); + ssh_string_burn(sig_blob); + SSH_STRING_FREE(sig_blob); session->session_state = SSH_SESSION_STATE_ERROR; return SSH_PACKET_USED; } diff --git a/libssh/src/pki.c b/libssh/src/pki.c index 6dcb1204..932abf2c 100644 --- a/libssh/src/pki.c +++ b/libssh/src/pki.c @@ -1160,6 +1160,10 @@ int pki_import_privkey_buffer(enum ssh_keytypes_e type, nid = pki_key_ecdsa_nid_from_name(ssh_string_get_char(i)); SSH_STRING_FREE(i); if (nid == -1) { + ssh_string_burn(e); + SSH_STRING_FREE(e); + ssh_string_burn(exp); + SSH_STRING_FREE(exp); goto fail; } @@ -2086,8 +2090,12 @@ int ssh_pki_export_signature_blob(const ssh_signature sig, return SSH_ERROR; } - ssh_string_fill(str, ssh_buffer_get(buf), ssh_buffer_get_len(buf)); + rc = ssh_string_fill(str, ssh_buffer_get(buf), ssh_buffer_get_len(buf)); SSH_BUFFER_FREE(buf); + if (rc < 0) { + SSH_STRING_FREE(str); + return SSH_ERROR; + } *sig_blob = str; @@ -2328,11 +2336,14 @@ ssh_string ssh_pki_do_sign(ssh_session session, } /* Get the session ID */ - session_id = ssh_string_new(crypto->digest_len); + session_id = ssh_string_new(crypto->session_id_len); if (session_id == NULL) { return NULL; } - ssh_string_fill(session_id, crypto->session_id, crypto->digest_len); + rc = ssh_string_fill(session_id, crypto->session_id, crypto->session_id_len); + if (rc < 0) { + goto end; + } /* Fill the input */ sign_input = ssh_buffer_new(); @@ -2389,11 +2400,15 @@ ssh_string ssh_pki_do_sign_agent(ssh_session session, } /* prepend session identifier */ - session_id = ssh_string_new(crypto->digest_len); + session_id = ssh_string_new(crypto->session_id_len); if (session_id == NULL) { return NULL; } - ssh_string_fill(session_id, crypto->session_id, crypto->digest_len); + rc = ssh_string_fill(session_id, crypto->session_id, crypto->session_id_len); + if (rc < 0) { + SSH_STRING_FREE(session_id); + return NULL; + } sig_buf = ssh_buffer_new(); if (sig_buf == NULL) { diff --git a/libssh/src/pki_crypto.c b/libssh/src/pki_crypto.c index 67862a3e..ec9cfa4b 100644 --- a/libssh/src/pki_crypto.c +++ b/libssh/src/pki_crypto.c @@ -831,7 +831,12 @@ ssh_string pki_private_key_to_pem(const ssh_key key, goto err; } - ssh_string_fill(blob, buf->data, buf->length); + rc = ssh_string_fill(blob, buf->data, buf->length); + if (rc < 0) { + ssh_string_free(blob); + goto err; + } + BIO_free(mem); return blob; @@ -1383,6 +1388,7 @@ static ssh_string pki_dsa_signature_to_blob(const ssh_signature sig) const unsigned char *raw_sig_data = NULL; size_t raw_sig_len; + int rc; DSA_SIG *dsa_sig; @@ -1439,7 +1445,11 @@ static ssh_string pki_dsa_signature_to_blob(const ssh_signature sig) return NULL; } - ssh_string_fill(sig_blob, buffer, 40); + rc = ssh_string_fill(sig_blob, buffer, 40); + if (rc < 0) { + SSH_STRING_FREE(sig_blob); + return NULL; + } return sig_blob; @@ -1516,7 +1526,10 @@ static ssh_string pki_ecdsa_signature_to_blob(const ssh_signature sig) goto error; } - ssh_string_fill(sig_blob, ssh_buffer_get(buf), ssh_buffer_get_len(buf)); + rc = ssh_string_fill(sig_blob, ssh_buffer_get(buf), ssh_buffer_get_len(buf)); + if (rc < 0) { + goto error; + } SSH_STRING_FREE(r); SSH_STRING_FREE(s); @@ -1526,6 +1539,7 @@ static ssh_string pki_ecdsa_signature_to_blob(const ssh_signature sig) return sig_blob; error: + SSH_STRING_FREE(sig_blob); SSH_STRING_FREE(r); SSH_STRING_FREE(s); ECDSA_SIG_free(ecdsa_sig); @@ -1670,7 +1684,11 @@ static int pki_signature_from_dsa_blob(UNUSED_PARAM(const ssh_key pubkey), if (r == NULL) { goto error; } - ssh_string_fill(r, ssh_string_data(sig_blob), 20); + rc = ssh_string_fill(r, ssh_string_data(sig_blob), 20); + if (rc < 0) { + SSH_STRING_FREE(r); + goto error; + } pr = ssh_make_string_bn(r); ssh_string_burn(r); @@ -1683,7 +1701,11 @@ static int pki_signature_from_dsa_blob(UNUSED_PARAM(const ssh_key pubkey), if (s == NULL) { goto error; } - ssh_string_fill(s, (char *)ssh_string_data(sig_blob) + 20, 20); + rc = ssh_string_fill(s, (char *)ssh_string_data(sig_blob) + 20, 20); + if (rc < 0) { + SSH_STRING_FREE(s); + goto error; + } ps = ssh_make_string_bn(s); ssh_string_burn(s); diff --git a/libssh/src/pki_ed25519_common.c b/libssh/src/pki_ed25519_common.c index 9db14dac..7aa05269 100644 --- a/libssh/src/pki_ed25519_common.c +++ b/libssh/src/pki_ed25519_common.c @@ -214,6 +214,7 @@ int pki_ed25519_public_key_to_blob(ssh_buffer buffer, ssh_key key) ssh_string pki_ed25519_signature_to_blob(ssh_signature sig) { ssh_string sig_blob; + int rc; #ifdef HAVE_OPENSSL_ED25519 /* When using the OpenSSL implementation, the signature is stored in raw_sig @@ -235,11 +236,15 @@ ssh_string pki_ed25519_signature_to_blob(ssh_signature sig) } #ifdef HAVE_OPENSSL_ED25519 - ssh_string_fill(sig_blob, ssh_string_data(sig->raw_sig), - ssh_string_len(sig->raw_sig)); + rc = ssh_string_fill(sig_blob, ssh_string_data(sig->raw_sig), + ssh_string_len(sig->raw_sig)); #else - ssh_string_fill(sig_blob, sig->ed25519_sig, ED25519_SIG_LEN); + rc = ssh_string_fill(sig_blob, sig->ed25519_sig, ED25519_SIG_LEN); #endif + if (rc < 0) { + SSH_STRING_FREE(sig_blob); + return NULL; + } return sig_blob; } diff --git a/libssh/src/pki_gcrypt.c b/libssh/src/pki_gcrypt.c index 43d60896..bf45351d 100644 --- a/libssh/src/pki_gcrypt.c +++ b/libssh/src/pki_gcrypt.c @@ -1765,6 +1765,7 @@ ssh_string pki_signature_to_blob(const ssh_signature sig) gcry_sexp_t sexp; size_t size = 0; ssh_string sig_blob = NULL; + int rc; switch(sig->type) { case SSH_KEYTYPE_DSS: @@ -1812,7 +1813,11 @@ ssh_string pki_signature_to_blob(const ssh_signature sig) return NULL; } - ssh_string_fill(sig_blob, buffer, 40); + rc = ssh_string_fill(sig_blob, buffer, 40); + if (rc < 0) { + SSH_STRING_FREE(sig_blob); + return NULL; + } break; case SSH_KEYTYPE_RSA: sexp = gcry_sexp_find_token(sig->rsa_sig, "s", 0); @@ -1829,13 +1834,16 @@ ssh_string pki_signature_to_blob(const ssh_signature sig) if (sig_blob == NULL) { return NULL; } - ssh_string_fill(sig_blob, discard_const_p(char, s), size); - + rc = ssh_string_fill(sig_blob, discard_const_p(char, s), size); gcry_sexp_release(sexp); + if (rc < 0) { + SSH_STRING_FREE(sig_blob); + return NULL; + } break; case SSH_KEYTYPE_ED25519: - sig_blob = pki_ed25519_signature_to_blob(sig); - break; + sig_blob = pki_ed25519_signature_to_blob(sig); + break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: @@ -1844,7 +1852,6 @@ ssh_string pki_signature_to_blob(const ssh_signature sig) ssh_string R; ssh_string S; ssh_buffer b; - int rc; b = ssh_buffer_new(); if (b == NULL) { @@ -1885,9 +1892,13 @@ ssh_string pki_signature_to_blob(const ssh_signature sig) return NULL; } - ssh_string_fill(sig_blob, + rc = ssh_string_fill(sig_blob, ssh_buffer_get(b), ssh_buffer_get_len(b)); SSH_BUFFER_FREE(b); + if (rc < 0) { + SSH_STRING_FREE(sig_blob); + return NULL; + } break; } #endif diff --git a/libssh/src/pki_mbedcrypto.c b/libssh/src/pki_mbedcrypto.c index 6e3d425c..c33fb726 100644 --- a/libssh/src/pki_mbedcrypto.c +++ b/libssh/src/pki_mbedcrypto.c @@ -832,8 +832,13 @@ ssh_string pki_signature_to_blob(const ssh_signature sig) return NULL; } - ssh_string_fill(sig_blob, ssh_buffer_get(b), ssh_buffer_get_len(b)); + rc = ssh_string_fill(sig_blob, ssh_buffer_get(b), ssh_buffer_get_len(b)); SSH_BUFFER_FREE(b); + if (rc < 0) { + SSH_STRING_FREE(sig_blob); + return NULL; + } + break; } case SSH_KEYTYPE_ED25519: @@ -1074,9 +1079,13 @@ static ssh_string rsa_do_sign_hash(const unsigned char *digest, return NULL; } - ssh_string_fill(sig_blob, sig, slen); + ok = ssh_string_fill(sig_blob, sig, slen); explicit_bzero(sig, slen); SAFE_FREE(sig); + if (ok < 0) { + SSH_STRING_FREE(sig_blob); + return NULL; + } return sig_blob; } diff --git a/libssh/src/sftp.c b/libssh/src/sftp.c index 9a10b075..a8346040 100644 --- a/libssh/src/sftp.c +++ b/libssh/src/sftp.c @@ -32,6 +32,9 @@ #include #include #include +#ifdef HAVE_SYS_TIME_H +#include +#endif /* HAVE_SYS_TIME_H */ #include #include #include @@ -173,32 +176,56 @@ sftp_session sftp_new(ssh_session session) return NULL; } -sftp_session sftp_new_channel(ssh_session session, ssh_channel channel){ - sftp_session sftp; +sftp_session +sftp_new_channel(ssh_session session, ssh_channel channel) +{ + sftp_session sftp = NULL; - if (session == NULL) { - return NULL; - } + if (session == NULL) { + return NULL; + } - sftp = calloc(1, sizeof(struct sftp_session_struct)); - if (sftp == NULL) { - ssh_set_error_oom(session); + sftp = calloc(1, sizeof(struct sftp_session_struct)); + if (sftp == NULL) { + ssh_set_error_oom(session); + return NULL; + } - return NULL; - } + sftp->ext = sftp_ext_new(); + if (sftp->ext == NULL) { + ssh_set_error_oom(session); + goto error; + } - sftp->ext = sftp_ext_new(); - if (sftp->ext == NULL) { - ssh_set_error_oom(session); - SAFE_FREE(sftp); + sftp->read_packet = calloc(1, sizeof(struct sftp_packet_struct)); + if (sftp->read_packet == NULL) { + ssh_set_error_oom(session); + goto error; + } - return NULL; - } + sftp->read_packet->payload = ssh_buffer_new(); + if (sftp->read_packet->payload == NULL) { + ssh_set_error_oom(session); + goto error; + } - sftp->session = session; - sftp->channel = channel; + sftp->session = session; + sftp->channel = channel; - return sftp; + return sftp; + +error: + if (sftp->ext != NULL) { + sftp_ext_free(sftp->ext); + } + if (sftp->read_packet != NULL) { + if (sftp->read_packet->payload != NULL) { + SSH_BUFFER_FREE(sftp->read_packet->payload); + } + SAFE_FREE(sftp->read_packet); + } + SAFE_FREE(sftp); + return NULL; } #ifdef WITH_SERVER diff --git a/libssh/src/threads/winlocks.c b/libssh/src/threads/winlocks.c index a1799531..da600418 100644 --- a/libssh/src/threads/winlocks.c +++ b/libssh/src/threads/winlocks.c @@ -26,6 +26,7 @@ #include #include #include +#include static int ssh_winlock_mutex_init (void **priv) { diff --git a/libssh/src/wrapper.c b/libssh/src/wrapper.c index 7e57ab5d..05c820da 100644 --- a/libssh/src/wrapper.c +++ b/libssh/src/wrapper.c @@ -182,8 +182,9 @@ void crypto_free(struct ssh_crypto_struct *crypto) crypto->ecdh_privkey = NULL; } #endif + SAFE_FREE(crypto->dh_server_signature); if (crypto->session_id != NULL) { - explicit_bzero(crypto->session_id, crypto->digest_len); + explicit_bzero(crypto->session_id, crypto->session_id_len); SAFE_FREE(crypto->session_id); } if (crypto->secret_hash != NULL) { diff --git a/libssh/tests/client/CMakeLists.txt b/libssh/tests/client/CMakeLists.txt index 70b5de3e..14f24c26 100644 --- a/libssh/tests/client/CMakeLists.txt +++ b/libssh/tests/client/CMakeLists.txt @@ -37,6 +37,7 @@ if (WITH_SFTP) endif() set(LIBSSH_CLIENT_TESTS ${LIBSSH_CLIENT_TESTS} + torture_sftp_init torture_sftp_ext torture_sftp_canonicalize_path torture_sftp_dir diff --git a/libssh/tests/client/torture_algorithms.c b/libssh/tests/client/torture_algorithms.c index 729505ef..ea3b647b 100644 --- a/libssh/tests/client/torture_algorithms.c +++ b/libssh/tests/client/torture_algorithms.c @@ -45,6 +45,16 @@ static int sshd_teardown(void **state) { return 0; } +static int sshd_setup_hmac(void **state) +{ + torture_setup_sshd_server(state, false); + /* Set MAC to be something other than what the client will offer */ + torture_update_sshd_config(state, "MACs hmac-sha2-512"); + + return 0; +} + + static int session_setup(void **state) { struct torture_state *s = *state; int verbosity = torture_libssh_verbosity(); @@ -412,6 +422,20 @@ static void torture_algorithms_aes256_gcm(void **state) test_algorithm(s->ssh.session, NULL/*kex*/, "aes256-gcm@openssh.com", NULL); } +static void torture_algorithms_aes128_gcm_mac(void **state) +{ + struct torture_state *s = *state; + + test_algorithm(s->ssh.session, NULL/*kex*/, "aes128-gcm@openssh.com", "hmac-sha1"); +} + +static void torture_algorithms_aes256_gcm_mac(void **state) +{ + struct torture_state *s = *state; + + test_algorithm(s->ssh.session, NULL/*kex*/, "aes256-gcm@openssh.com", "hmac-sha1"); +} + static void torture_algorithms_3des_cbc_hmac_sha1(void **state) { struct torture_state *s = *state; @@ -548,6 +572,19 @@ static void torture_algorithms_chacha20_poly1305(void **state) "chacha20-poly1305@openssh.com", NULL); } +static void torture_algorithms_chacha20_poly1305_mac(void **state) +{ + struct torture_state *s = *state; + + if (ssh_fips_mode()) { + skip(); + } + + test_algorithm(s->ssh.session, + NULL, /*kex*/ + "chacha20-poly1305@openssh.com", + "hmac-sha1"); /* different from the server */ +} #endif /* OPENSSH_CHACHA20_POLY1305_OPENSSH_COM */ static void torture_algorithms_zlib(void **state) { @@ -951,10 +988,30 @@ int torture_run_tests(void) { #endif }; + struct CMUnitTest tests_hmac[] = { + cmocka_unit_test_setup_teardown(torture_algorithms_aes128_gcm_mac, + session_setup, + session_teardown), + cmocka_unit_test_setup_teardown(torture_algorithms_aes256_gcm_mac, + session_setup, + session_teardown), +#ifdef OPENSSH_CHACHA20_POLY1305_OPENSSH_COM + cmocka_unit_test_setup_teardown(torture_algorithms_chacha20_poly1305_mac, + session_setup, + session_teardown), +#endif /* OPENSSH_CHACHA20_POLY1305_OPENSSH_COM */ + }; + ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); + if (rc != 0) { + return rc; + } + + torture_filter_tests(tests); + rc = cmocka_run_group_tests(tests_hmac, sshd_setup_hmac, sshd_teardown); ssh_finalize(); diff --git a/libssh/tests/client/torture_rekey.c b/libssh/tests/client/torture_rekey.c index a70b39d6..46a015db 100644 --- a/libssh/tests/client/torture_rekey.c +++ b/libssh/tests/client/torture_rekey.c @@ -38,6 +38,8 @@ #include #include +static uint64_t bytes = 2048; /* 2KB (more than the authentication phase) */ + static int sshd_setup(void **state) { torture_setup_sshd_server(state, false); @@ -153,7 +155,6 @@ static void torture_rekey_send(void **state) int rc; char data[256]; unsigned int i; - uint64_t bytes = 2048; /* 2KB (more than the authentication phase) */ struct ssh_crypto_struct *c = NULL; unsigned char *secret_hash = NULL; @@ -234,8 +235,6 @@ static void session_setup_sftp(void **state) assert_non_null(s->ssh.tsftp); } -uint64_t bytes = 2048; /* 2KB */ - static int session_setup_sftp_client(void **state) { struct torture_state *s = *state; @@ -439,6 +438,153 @@ static void torture_rekey_server_send(void **state) ssh_disconnect(s->ssh.session); } +static void torture_rekey_different_kex(void **state) +{ + struct torture_state *s = *state; + int rc; + char data[256]; + unsigned int i; + struct ssh_crypto_struct *c = NULL; + unsigned char *secret_hash = NULL; + size_t secret_hash_len = 0; + const char *kex1 = "diffie-hellman-group14-sha256,curve25519-sha256,ecdh-sha2-nistp256"; + const char *kex2 = "diffie-hellman-group18-sha512,diffie-hellman-group16-sha512,ecdh-sha2-nistp521"; + + /* Use short digest for initial key exchange */ + rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_KEY_EXCHANGE, kex1); + assert_ssh_return_code(s->ssh.session, rc); + + rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_REKEY_DATA, &bytes); + assert_ssh_return_code(s->ssh.session, rc); + + rc = ssh_connect(s->ssh.session); + assert_ssh_return_code(s->ssh.session, rc); + + /* The blocks limit is set correctly */ + c = s->ssh.session->current_crypto; + 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) */ + 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 */ + secret_hash = malloc(c->digest_len); + assert_non_null(secret_hash); + memcpy(secret_hash, c->secret_hash, c->digest_len); + secret_hash_len = c->digest_len; + assert_int_equal(secret_hash_len, 32); /* SHA256 len */ + + /* OpenSSH can not rekey before authentication so authenticate here */ + rc = ssh_userauth_none(s->ssh.session, NULL); + /* This request should return a SSH_REQUEST_DENIED error */ + if (rc == SSH_ERROR) { + assert_int_equal(ssh_get_error_code(s->ssh.session), SSH_REQUEST_DENIED); + } + rc = ssh_userauth_list(s->ssh.session, NULL); + assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); + + rc = ssh_userauth_publickey_auto(s->ssh.session, NULL, NULL); + assert_int_equal(rc, SSH_AUTH_SUCCESS); + + /* Now try to change preference of key exchange algorithm to something with larger digest */ + 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 + * to make sure the rekey it completes with all different ciphers (paddings */ + memset(data, 0, sizeof(data)); + memset(data, 'A', 128); + for (i = 0; i < 20; i++) { + ssh_send_ignore(s->ssh.session, data); + ssh_handle_packets(s->ssh.session, 50); + } + + /* The rekey limit was restored in the new crypto to the same value */ + c = s->ssh.session->current_crypto; + 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); + /* Check that the secret hash is different than initially */ + assert_int_equal(c->digest_len, 64); /* SHA512 len */ + assert_memory_not_equal(secret_hash, c->secret_hash, secret_hash_len); + /* Session ID stays same after one rekey */ + assert_memory_equal(secret_hash, c->session_id, secret_hash_len); + free(secret_hash); + + assert_int_equal(ssh_is_connected(s->ssh.session), 1); + assert_int_equal(s->ssh.session->session_state, SSH_SESSION_STATE_AUTHENTICATED); + + ssh_disconnect(s->ssh.session); +} + +static void torture_rekey_server_different_kex(void **state) +{ + struct torture_state *s = *state; + int rc; + char data[256]; + unsigned int i; + struct ssh_crypto_struct *c = NULL; + unsigned char *secret_hash = NULL; + size_t secret_hash_len = 0; + const char *sshd_config = "RekeyLimit 2K none"; + const char *kex1 = "diffie-hellman-group14-sha256,curve25519-sha256,ecdh-sha2-nistp256"; + const char *kex2 = "diffie-hellman-group18-sha512,diffie-hellman-group16-sha512"; + + /* Use short digest for initial key exchange */ + rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_KEY_EXCHANGE, kex1); + assert_ssh_return_code(s->ssh.session, rc); + + torture_update_sshd_config(state, sshd_config); + + rc = ssh_connect(s->ssh.session); + assert_ssh_return_code(s->ssh.session, rc); + + /* Copy the initial secret hash = session_id so we know we changed keys later */ + c = s->ssh.session->current_crypto; + secret_hash = malloc(c->digest_len); + assert_non_null(secret_hash); + memcpy(secret_hash, c->secret_hash, c->digest_len); + secret_hash_len = c->digest_len; + assert_int_equal(secret_hash_len, 32); /* SHA256 len */ + + /* OpenSSH can not rekey before authentication so authenticate here */ + rc = ssh_userauth_none(s->ssh.session, NULL); + /* This request should return a SSH_REQUEST_DENIED error */ + if (rc == SSH_ERROR) { + assert_int_equal(ssh_get_error_code(s->ssh.session), SSH_REQUEST_DENIED); + } + rc = ssh_userauth_list(s->ssh.session, NULL); + assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); + + rc = ssh_userauth_publickey_auto(s->ssh.session, NULL, NULL); + assert_int_equal(rc, SSH_AUTH_SUCCESS); + + /* Now try to change preference of key exchange algorithm to something with larger digest */ + 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 + * to make sure the rekey it completes with all different ciphers (paddings */ + memset(data, 0, sizeof(data)); + memset(data, 'A', 128); + for (i = 0; i < 25; i++) { + ssh_send_ignore(s->ssh.session, data); + ssh_handle_packets(s->ssh.session, 50); + } + + /* Check that the secret hash is different than initially */ + c = s->ssh.session->current_crypto; + assert_int_equal(c->digest_len, 64); /* SHA512 len */ + assert_memory_not_equal(secret_hash, c->secret_hash, secret_hash_len); + /* Session ID stays same after one rekey */ + assert_memory_equal(secret_hash, c->session_id, secret_hash_len); + free(secret_hash); + + ssh_disconnect(s->ssh.session); +} + + #ifdef WITH_SFTP static int session_setup_sftp_server(void **state) { @@ -522,6 +668,9 @@ int torture_run_tests(void) { cmocka_unit_test_setup_teardown(torture_rekey_send, session_setup, session_teardown), + cmocka_unit_test_setup_teardown(torture_rekey_different_kex, + session_setup, + session_teardown), /* Note, that this modifies the sshd_config */ cmocka_unit_test_setup_teardown(torture_rekey_server_send, session_setup, @@ -531,6 +680,9 @@ int torture_run_tests(void) { session_setup_sftp_server, session_teardown), #endif /* WITH_SFTP */ + cmocka_unit_test_setup_teardown(torture_rekey_server_different_kex, + session_setup, + session_teardown), /* TODO verify the two rekey are possible and the states are not broken after rekey */ }; diff --git a/libssh/tests/client/torture_sftp_init.c b/libssh/tests/client/torture_sftp_init.c new file mode 100644 index 00000000..a17f01fe --- /dev/null +++ b/libssh/tests/client/torture_sftp_init.c @@ -0,0 +1,106 @@ +#include "config.h" + +#define LIBSSH_STATIC + +#include "torture.h" +#include "sftp.c" + +#include +#include +#include + +static int sshd_setup(void **state) +{ + torture_setup_sshd_server(state, false); + + return 0; +} + +static int sshd_teardown(void **state) { + torture_teardown_sshd_server(state); + + return 0; +} + +static void session_setup(void **state) +{ + struct torture_state *s = *state; + struct passwd *pwd; + int rc; + + pwd = getpwnam("bob"); + assert_non_null(pwd); + + rc = setuid(pwd->pw_uid); + assert_return_code(rc, errno); + + s->ssh.session = torture_ssh_session(s, + TORTURE_SSH_SERVER, + NULL, + TORTURE_SSH_USER_ALICE, + NULL); + assert_non_null(s->ssh.session); + + s->ssh.tsftp = torture_sftp_session(s->ssh.session); + assert_non_null(s->ssh.tsftp); +} + +static void session_setup_channel(void **state) +{ + struct torture_state *s = *state; + struct passwd *pwd = NULL; + ssh_channel c = NULL; + int rc; + + pwd = getpwnam("bob"); + assert_non_null(pwd); + + rc = setuid(pwd->pw_uid); + assert_return_code(rc, errno); + + s->ssh.session = torture_ssh_session(s, + TORTURE_SSH_SERVER, + NULL, + TORTURE_SSH_USER_ALICE, + NULL); + assert_non_null(s->ssh.session); + + c = ssh_channel_new(s->ssh.session); + assert_non_null(c); + + s->ssh.tsftp = torture_sftp_session_channel(s->ssh.session, c); + assert_non_null(s->ssh.tsftp); +} + +static int session_teardown(void **state) +{ + struct torture_state *s = *state; + + torture_rmdirs(s->ssh.tsftp->testdir); + torture_sftp_close(s->ssh.tsftp); + ssh_disconnect(s->ssh.session); + ssh_free(s->ssh.session); + + return 0; +} + +int torture_run_tests(void) { + int rc; + struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(session_setup, + NULL, + session_teardown), + cmocka_unit_test_setup_teardown(session_setup_channel, + NULL, + session_teardown) + }; + + ssh_init(); + + torture_filter_tests(tests); + rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); + + ssh_finalize(); + + return rc; +} diff --git a/libssh/tests/pkd/pkd_hello.c b/libssh/tests/pkd/pkd_hello.c index 3a5768d7..01b1b10d 100644 --- a/libssh/tests/pkd/pkd_hello.c +++ b/libssh/tests/pkd/pkd_hello.c @@ -392,45 +392,37 @@ static int torture_pkd_setup_ecdsa_521(void **state) { #endif -#define PKDTESTS_CIPHER_FIPS(f, client, ciphercmd) \ - f(client, rsa_aes128_cbc, ciphercmd("aes128-cbc"), setup_rsa, teardown) \ +#define PKDTESTS_CIPHER_COMMON(f, client, ciphercmd) \ f(client, rsa_aes128_ctr, ciphercmd("aes128-ctr"), setup_rsa, teardown) \ - f(client, rsa_aes256_cbc, ciphercmd("aes256-cbc"), setup_rsa, teardown) \ f(client, rsa_aes256_ctr, ciphercmd("aes256-ctr"), setup_rsa, teardown) \ - f(client, ecdsa_256_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_aes128_ctr, ciphercmd("aes128-ctr"), setup_ecdsa_256, teardown) \ - f(client, ecdsa_256_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_aes256_ctr, ciphercmd("aes256-ctr"), setup_ecdsa_256, teardown) \ - f(client, ecdsa_384_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_aes128_ctr, ciphercmd("aes128-ctr"), setup_ecdsa_384, teardown) \ - f(client, ecdsa_384_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_aes256_ctr, ciphercmd("aes256-ctr"), setup_ecdsa_384, teardown) \ - f(client, ecdsa_521_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_aes128_ctr, ciphercmd("aes128-ctr"), setup_ecdsa_521, teardown) \ - f(client, ecdsa_521_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_aes256_ctr, ciphercmd("aes256-ctr"), setup_ecdsa_521, teardown) +#define PKDTESTS_CIPHER_FIPS(f, client, ciphercmd) \ + PKDTESTS_CIPHER_COMMON(f, client, ciphercmd) \ + f(client, rsa_aes128_cbc, ciphercmd("aes128-cbc"), setup_rsa, teardown) \ + f(client, rsa_aes256_cbc, ciphercmd("aes256-cbc"), setup_rsa, teardown) \ + f(client, ecdsa_256_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_256, teardown) \ + f(client, ecdsa_256_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_256, teardown) \ + f(client, ecdsa_384_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_384, teardown) \ + f(client, ecdsa_384_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_384, teardown) \ + f(client, ecdsa_521_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_521, teardown) \ + f(client, ecdsa_521_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_521, teardown) + #ifdef HAVE_DSA #define PKDTESTS_CIPHER(f, client, ciphercmd) \ /* Ciphers. */ \ - PKDTESTS_CIPHER_FIPS(f, client, ciphercmd) \ - f(client, rsa_3des_cbc, ciphercmd("3des-cbc"), setup_rsa, teardown) \ - f(client, dsa_3des_cbc, ciphercmd("3des-cbc"), setup_dsa, teardown) \ - f(client, dsa_aes128_cbc, ciphercmd("aes128-cbc"), setup_dsa, teardown) \ + PKDTESTS_CIPHER_COMMON(f, client, ciphercmd) \ f(client, dsa_aes128_ctr, ciphercmd("aes128-ctr"), setup_dsa, teardown) \ - f(client, dsa_aes256_cbc, ciphercmd("aes256-cbc"), setup_dsa, teardown) \ - f(client, dsa_aes256_ctr, ciphercmd("aes256-ctr"), setup_dsa, teardown) \ - f(client, ecdsa_256_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_256, teardown) \ - f(client, ecdsa_384_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_384, teardown) \ - f(client, ecdsa_521_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_521, teardown) + f(client, dsa_aes256_ctr, ciphercmd("aes256-ctr"), setup_dsa, teardown) #else #define PKDTESTS_CIPHER(f, client, ciphercmd) \ /* Ciphers. */ \ - PKDTESTS_CIPHER_FIPS(f, client, ciphercmd) \ - f(client, rsa_3des_cbc, ciphercmd("3des-cbc"), setup_rsa, teardown) \ - f(client, ecdsa_256_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_256, teardown) \ - f(client, ecdsa_384_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_384, teardown) \ - f(client, ecdsa_521_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_521, teardown) + PKDTESTS_CIPHER_COMMON(f, client, ciphercmd) #endif #define CHACHA20 "chacha20-poly1305@openssh.com" @@ -451,10 +443,16 @@ static int torture_pkd_setup_ecdsa_521(void **state) { #define PKDTESTS_CIPHER_OPENSSHONLY(f, client, ciphercmd) \ /* Ciphers. */ \ PKDTESTS_CIPHER_OPENSSHONLY_FIPS(f, client, ciphercmd) \ + f(client, rsa_3des_cbc, ciphercmd("3des-cbc"), setup_rsa, teardown) \ + f(client, rsa_aes128_cbc, ciphercmd("aes128-cbc"), setup_rsa, teardown) \ f(client, rsa_aes192_cbc, ciphercmd("aes192-cbc"), setup_rsa, teardown) \ + f(client, rsa_aes256_cbc, ciphercmd("aes256-cbc"), setup_rsa, teardown) \ f(client, rsa_aes192_ctr, ciphercmd("aes192-ctr"), setup_rsa, teardown) \ f(client, rsa_chacha20, ciphercmd(CHACHA20), setup_rsa, teardown) \ + f(client, dsa_3des_cbc, ciphercmd("3des-cbc"), setup_dsa, teardown) \ + f(client, dsa_aes128_cbc, ciphercmd("aes128-cbc"), setup_dsa, teardown) \ f(client, dsa_aes192_cbc, ciphercmd("aes192-cbc"), setup_dsa, teardown) \ + f(client, dsa_aes256_cbc, ciphercmd("aes256-cbc"), setup_dsa, teardown) \ f(client, dsa_aes192_ctr, ciphercmd("aes192-ctr"), setup_dsa, teardown) \ f(client, dsa_chacha20, ciphercmd(CHACHA20), setup_dsa, teardown) \ f(client, dsa_aes128_gcm, ciphercmd(AES128_GCM), setup_dsa, teardown) \ @@ -469,20 +467,32 @@ static int torture_pkd_setup_ecdsa_521(void **state) { f(client, ed25519_chacha20, ciphercmd(CHACHA20), setup_ed25519, teardown) \ f(client, ed25519_aes128_gcm, ciphercmd(AES128_GCM), setup_ed25519, teardown) \ f(client, ed25519_aes256_gcm, ciphercmd(AES256_GCM), setup_ed25519, teardown) \ + f(client, ecdsa_256_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_256, teardown) \ + f(client, ecdsa_256_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_256, teardown) \ + f(client, ecdsa_256_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_chacha20, ciphercmd(CHACHA20), setup_ecdsa_256, teardown) \ + f(client, ecdsa_384_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_384, teardown) \ + f(client, ecdsa_384_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_384, teardown) \ + f(client, ecdsa_384_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_chacha20, ciphercmd(CHACHA20), setup_ecdsa_384, teardown) \ + f(client, ecdsa_521_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_521, teardown) \ + f(client, ecdsa_521_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_521, teardown) \ + f(client, ecdsa_521_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_chacha20, ciphercmd(CHACHA20), setup_ecdsa_521, teardown) #else #define PKDTESTS_CIPHER_OPENSSHONLY(f, client, ciphercmd) \ /* Ciphers. */ \ PKDTESTS_CIPHER_OPENSSHONLY_FIPS(f, client, ciphercmd) \ + f(client, rsa_3des_cbc, ciphercmd("3des-cbc"), setup_rsa, teardown) \ + f(client, rsa_aes128_cbc, ciphercmd("aes128-cbc"), setup_rsa, teardown) \ f(client, rsa_aes192_cbc, ciphercmd("aes192-cbc"), setup_rsa, teardown) \ + f(client, rsa_aes256_cbc, ciphercmd("aes256-cbc"), setup_rsa, teardown) \ f(client, rsa_aes192_ctr, ciphercmd("aes192-ctr"), setup_rsa, teardown) \ f(client, rsa_chacha20, ciphercmd(CHACHA20), setup_rsa, teardown) \ f(client, ed25519_3des_cbc, ciphercmd("3des-cbc"), setup_ed25519, teardown) \ @@ -493,13 +503,22 @@ static int torture_pkd_setup_ecdsa_521(void **state) { f(client, ed25519_aes192_cbc, ciphercmd("aes192-cbc"), setup_ed25519, teardown) \ f(client, ed25519_aes192_ctr, ciphercmd("aes192-ctr"), setup_ed25519, teardown) \ f(client, ed25519_chacha20, ciphercmd(CHACHA20), setup_ed25519, teardown) \ + f(client, ecdsa_256_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_256, teardown) \ + f(client, ecdsa_256_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_256, teardown) \ + f(client, ecdsa_256_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_chacha20, ciphercmd(CHACHA20), setup_ecdsa_256, teardown) \ + f(client, ecdsa_384_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_384, teardown) \ + f(client, ecdsa_384_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_384, teardown) \ + f(client, ecdsa_384_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_chacha20, ciphercmd(CHACHA20), setup_ecdsa_384, teardown) \ + f(client, ecdsa_521_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_521, teardown) \ + f(client, ecdsa_521_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_521, teardown) \ + f(client, ecdsa_521_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_chacha20, ciphercmd(CHACHA20), setup_ecdsa_521, teardown) #endif diff --git a/libssh/tests/torture.c b/libssh/tests/torture.c index 7289a97f..b3ea36b4 100644 --- a/libssh/tests/torture.c +++ b/libssh/tests/torture.c @@ -421,7 +421,8 @@ ssh_bind torture_ssh_bind(const char *addr, #ifdef WITH_SFTP -struct torture_sftp *torture_sftp_session(ssh_session session) { +struct torture_sftp *torture_sftp_session_channel(ssh_session session, ssh_channel channel) +{ struct torture_sftp *t; char template[] = "/tmp/ssh_torture_XXXXXX"; char *p; @@ -437,9 +438,26 @@ struct torture_sftp *torture_sftp_session(ssh_session session) { } t->ssh = session; - t->sftp = sftp_new(session); - if (t->sftp == NULL) { - goto failed; + if (channel == NULL) { + t->sftp = sftp_new(session); + if (t->sftp == NULL) { + goto failed; + } + } else { + t->sftp = sftp_new_channel(session, channel); + if (t->sftp == NULL) { + goto failed; + } + + rc = ssh_channel_open_session(channel); + if (rc != SSH_OK) { + goto failed; + } + + rc = ssh_channel_request_sftp(channel); + if (rc != SSH_OK) { + goto failed; + } } rc = sftp_init(t->sftp); @@ -470,6 +488,11 @@ struct torture_sftp *torture_sftp_session(ssh_session session) { return NULL; } +struct torture_sftp *torture_sftp_session(ssh_session session) +{ + return torture_sftp_session_channel(session, NULL); +} + void torture_sftp_close(struct torture_sftp *t) { if (t == NULL) { return; @@ -629,7 +652,8 @@ static void torture_setup_create_sshd_config(void **state, bool pam) "\n" "StrictModes no\n" "\n" - "%s" /* Here comes UsePam */ + "%s\n" /* Here comes UsePam */ + "%s" /* The space for test-specific options */ "\n" /* add all supported algorithms */ "HostKeyAlgorithms " OPENSSH_KEYS "\n" @@ -644,8 +668,7 @@ static void torture_setup_create_sshd_config(void **state, bool pam) "AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT\n" "AcceptEnv LC_IDENTIFICATION LC_ALL LC_LIBSSH\n" "\n" - "PidFile %s\n" - "%s\n"; /* The space for test-specific options */ + "PidFile %s\n"; /* FIPS config */ const char fips_config_string[]= "Port 22\n" @@ -663,7 +686,8 @@ static void torture_setup_create_sshd_config(void **state, bool pam) "\n" "StrictModes no\n" "\n" - "%s" /* UsePam */ + "%s\n" /* Here comes UsePam */ + "%s" /* The space for test-specific options */ "\n" "Ciphers " "aes256-gcm@openssh.com,aes256-ctr,aes256-cbc," @@ -692,8 +716,7 @@ static void torture_setup_create_sshd_config(void **state, bool pam) "AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT\n" "AcceptEnv LC_IDENTIFICATION LC_ALL LC_LIBSSH\n" "\n" - "PidFile %s\n" /* PID file */ - "%s\n"; /* The space for test-specific options */ + "PidFile %s\n"; /* PID file */ const char usepam_yes[] = "UsePAM yes\n" "KbdInteractiveAuthentication yes\n"; @@ -794,8 +817,8 @@ static void torture_setup_create_sshd_config(void **state, bool pam) trusted_ca_pubkey, sftp_server, usepam, - s->srv_pidfile, - additional_config); + additional_config, + s->srv_pidfile); } else { snprintf(sshd_config, sizeof(sshd_config), config_string, @@ -808,8 +831,8 @@ static void torture_setup_create_sshd_config(void **state, bool pam) trusted_ca_pubkey, sftp_server, usepam, - s->srv_pidfile, - additional_config); + additional_config, + s->srv_pidfile); } torture_write_file(s->srv_config, sshd_config); diff --git a/libssh/tests/torture.h b/libssh/tests/torture.h index a1dc6208..63ddc3cd 100644 --- a/libssh/tests/torture.h +++ b/libssh/tests/torture.h @@ -111,6 +111,7 @@ ssh_bind torture_ssh_bind(const char *addr, const char *private_key_file); struct torture_sftp *torture_sftp_session(ssh_session session); +struct torture_sftp *torture_sftp_session_channel(ssh_session session, ssh_channel channel); void torture_sftp_close(struct torture_sftp *t); void torture_write_file(const char *filename, const char *data); diff --git a/libssh/tests/unittests/torture_callbacks.c b/libssh/tests/unittests/torture_callbacks.c index f5f7e4da..85f4d1f4 100644 --- a/libssh/tests/unittests/torture_callbacks.c +++ b/libssh/tests/unittests/torture_callbacks.c @@ -138,6 +138,9 @@ static void torture_callbacks_execute_list(void **state){ }; (void)state; + + assert_non_null(list); + ssh_callbacks_init(&c1); ssh_callbacks_init(&c2); ssh_callbacks_init(&c3); @@ -213,6 +216,8 @@ static void torture_callbacks_iterate(void **state){ (void)state; /* unused */ + assert_non_null(list); + ssh_callbacks_init(&c1); ssh_callbacks_init(&c2); diff --git a/libssh/tests/unittests/torture_misc.c b/libssh/tests/unittests/torture_misc.c index ef06d65f..0a48abbe 100644 --- a/libssh/tests/unittests/torture_misc.c +++ b/libssh/tests/unittests/torture_misc.c @@ -209,7 +209,8 @@ static void torture_timeout_elapsed(void **state){ struct ssh_timestamp ts; (void) state; ssh_timestamp_init(&ts); - usleep(50000); + usleep(30000); + assert_true(ssh_timeout_elapsed(&ts,25)); assert_false(ssh_timeout_elapsed(&ts,30000)); assert_false(ssh_timeout_elapsed(&ts,75)); diff --git a/libssh/tests/unittests/torture_packet_filter.c b/libssh/tests/unittests/torture_packet_filter.c index 85fb5c1b..ffa49602 100644 --- a/libssh/tests/unittests/torture_packet_filter.c +++ b/libssh/tests/unittests/torture_packet_filter.c @@ -517,12 +517,108 @@ static void torture_packet_filter_check_channel_open(void **state) assert_int_equal(rc, 0); } +static void torture_packet_filter_check_channel_success(void **state) +{ + int rc; + + /* The only condition to accept a CHANNEL_SUCCESS is to be authenticated */ + global_state accepted[] = { + { + .flags = COMPARE_SESSION_STATE, + .session = SSH_SESSION_STATE_AUTHENTICATED, + } + }; + + int accepted_count = 1; + + /* Unused */ + (void) state; + + rc = check_message_in_all_states(accepted, accepted_count, + SSH2_MSG_CHANNEL_SUCCESS); + + assert_int_equal(rc, 0); +} + +static void torture_packet_filter_check_channel_failure(void **state) +{ + int rc; + + /* The only condition to accept a CHANNEL_FAILURE is to be authenticated */ + global_state accepted[] = { + { + .flags = COMPARE_SESSION_STATE, + .session = SSH_SESSION_STATE_AUTHENTICATED, + } + }; + + int accepted_count = 1; + + /* Unused */ + (void) state; + + rc = check_message_in_all_states(accepted, accepted_count, + SSH2_MSG_CHANNEL_FAILURE); + + assert_int_equal(rc, 0); +} + +static void torture_packet_filter_check_request_success(void **state) +{ + int rc; + + /* The only condition to accept a REQUEST_SUCCESS is to be authenticated */ + global_state accepted[] = { + { + .flags = COMPARE_SESSION_STATE, + .session = SSH_SESSION_STATE_AUTHENTICATED, + } + }; + + int accepted_count = 1; + + /* Unused */ + (void) state; + + rc = check_message_in_all_states(accepted, accepted_count, + SSH2_MSG_REQUEST_SUCCESS); + + assert_int_equal(rc, 0); +} + +static void torture_packet_filter_check_request_failure(void **state) +{ + int rc; + + /* The only condition to accept a REQUEST_FAILURE is to be authenticated */ + global_state accepted[] = { + { + .flags = COMPARE_SESSION_STATE, + .session = SSH_SESSION_STATE_AUTHENTICATED, + } + }; + + int accepted_count = 1; + + /* Unused */ + (void) state; + + rc = check_message_in_all_states(accepted, accepted_count, + SSH2_MSG_REQUEST_FAILURE); + + assert_int_equal(rc, 0); +} + int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test(torture_packet_filter_check_auth_success), cmocka_unit_test(torture_packet_filter_check_channel_open), + cmocka_unit_test(torture_packet_filter_check_channel_success), + cmocka_unit_test(torture_packet_filter_check_channel_failure), + cmocka_unit_test(torture_packet_filter_check_request_success), + cmocka_unit_test(torture_packet_filter_check_request_failure), cmocka_unit_test(torture_packet_filter_check_unfiltered), cmocka_unit_test(torture_packet_filter_check_msg_ext_info) }; diff --git a/libssh/tests/unittests/torture_pki_ed25519.c b/libssh/tests/unittests/torture_pki_ed25519.c index 07ccfd67..ff59b190 100644 --- a/libssh/tests/unittests/torture_pki_ed25519.c +++ b/libssh/tests/unittests/torture_pki_ed25519.c @@ -796,7 +796,8 @@ static void torture_pki_ed25519_verify(void **state){ assert_true(rc == SSH_OK); assert_non_null(pubkey); - ssh_string_fill(blob, ref_signature, ED25519_SIG_LEN); + rc = ssh_string_fill(blob, ref_signature, ED25519_SIG_LEN); + assert_int_equal(rc, 0); sig = pki_signature_from_blob(pubkey, blob, SSH_KEYTYPE_ED25519, SSH_DIGEST_AUTO); assert_non_null(sig); @@ -853,7 +854,8 @@ static void torture_pki_ed25519_verify_bad(void **state){ /* alter signature and expect false result */ for (i=0; i < ED25519_SIG_LEN; ++i){ - ssh_string_fill(blob, ref_signature, ED25519_SIG_LEN); + rc = ssh_string_fill(blob, ref_signature, ED25519_SIG_LEN); + assert_int_equal(rc, 0); ((uint8_t *)ssh_string_data(blob))[i] ^= 0xff; sig = pki_signature_from_blob(pubkey, blob, SSH_KEYTYPE_ED25519, SSH_DIGEST_AUTO); assert_non_null(sig); diff --git a/libssh/tests/unittests/torture_session_keys.c b/libssh/tests/unittests/torture_session_keys.c index f220e010..a5ec3d89 100644 --- a/libssh/tests/unittests/torture_session_keys.c +++ b/libssh/tests/unittests/torture_session_keys.c @@ -48,8 +48,9 @@ struct ssh_cipher_struct fake_out_cipher = { }; struct ssh_crypto_struct test_crypto = { - .digest_len = 32, + .session_id_len = 32, .session_id = secret, + .digest_len = 32, .secret_hash = secret, .in_cipher = &fake_in_cipher, .out_cipher = &fake_out_cipher, @@ -68,7 +69,9 @@ static void torture_session_keys(UNUSED_PARAM(void **state)) int rc; k_string = ssh_string_new(32); - ssh_string_fill(k_string, key, 32); + rc = ssh_string_fill(k_string, key, 32); + assert_int_equal(rc, 0); + test_crypto.shared_secret = ssh_make_string_bn(k_string); rc = ssh_generate_session_keys(&session); diff --git a/setup.py b/setup.py index 86a20185..c6059a92 100644 --- a/setup.py +++ b/setup.py @@ -47,7 +47,7 @@ ] # _comp_args = ["-ggdb"] -_comp_args = ["-O3"] if not ON_WINDOWS else None +_comp_args = ['-O3', '-g0', '-s'] if not ON_WINDOWS else None cython_directives = { 'embedsignature': True, 'boundscheck': False, @@ -124,7 +124,7 @@ 'tests', 'tests.*', '*.tests', '*.tests.*')), zip_safe=False, - include_package_data=True, + include_package_data=False, platforms='any', classifiers=[ 'Development Status :: 4 - Beta',