first commit

This commit is contained in:
Mateusz Gruszczyński committed 2026-10-28 09:16:54 +01:00
commit 32a7ba8e8f
168 files changed
+123856

No files matched your search

+15
View File
@@ -0,0 +1,15 @@
#!/bin/sh
# Run against the exact bundled libssh2 archive produced by the Cargo build.
set -eu
if [ "$#" -ne 1 ] || [ ! -f "$1" ]; then
echo "Usage: $0 /absolute/path/to/target/.../out/build/libssh2.a" >&2
exit 2
fi
test_root=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
test_temp=$(mktemp -d)
trap 'rm -rf "$test_temp"' EXIT HUP INT TERM
"${CC:-cc}" -std=c99 -O2 -DNDEBUG -Wall -Wextra -Werror \
-I"$test_root/../libssh2/include" \
"$test_root/security-regression.c" "$1" -lssl -lcrypto -lz \
-o "$test_temp/security-regression"
"$test_temp/security-regression"
+73
View File
@@ -0,0 +1,73 @@
/* Targeted runtime checks for the vendored libssh2 security backports.
* SPDX-License-Identifier: MIT
* This program deliberately supplies boundary lengths, without any network.
*/
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include "libssh2.h"
/* Internal function from the statically linked, patched OpenSSL backend. */
extern int _libssh2_cipher_crypt(EVP_CIPHER_CTX **ctx,
const EVP_CIPHER *(*algo)(void),
int encrypt, unsigned char *block,
size_t blocksize, int firstlast);
static int check_crypto_bounds(void)
{
unsigned char buffer[EVP_MAX_BLOCK_LENGTH + 32];
unsigned char original[sizeof(buffer)];
size_t length;
memset(buffer, 0xa5, sizeof(buffer));
memcpy(original, buffer, sizeof(buffer));
/* A complete AES-GCM block requires 4 bytes of AAD plus a 16-byte tag.
* A null context makes an accidental call into OpenSSL fail immediately;
* a correct bounds check rejects these inputs before touching it. */
for(length = 0; length < 20; length++) {
if(_libssh2_cipher_crypt(NULL, EVP_aes_128_gcm, 0, buffer,
length, 3) != 1)
return 1;
}
if(_libssh2_cipher_crypt(NULL, EVP_aes_128_gcm, 0, buffer,
sizeof(buffer), 3) != 1)
return 1;
if(_libssh2_cipher_crypt(NULL, EVP_aes_128_gcm, 0, buffer,
SIZE_MAX, 3) != 1)
return 1;
return memcmp(buffer, original, sizeof(buffer)) != 0;
}
static int check_username_bounds(void)
{
LIBSSH2_SESSION *session = libssh2_session_init();
int failure = 0;
if(!session)
return 1;
if(libssh2_userauth_list(session, "x", UINT_MAX) != NULL ||
libssh2_session_last_errno(session) != LIBSSH2_ERROR_PROTO)
failure = 1;
if(libssh2_userauth_password_ex(session, "x", UINT_MAX, "p", 1,
NULL) != LIBSSH2_ERROR_PROTO)
failure = 1;
libssh2_session_free(session);
return failure;
}
int main(void)
{
int failure;
if(libssh2_init(0) != 0)
return 1;
failure = check_crypto_bounds() | check_username_bounds();
libssh2_exit();
if(failure) {
fputs("libssh2 security boundary regression failed\n", stderr);
return 1;
}
puts("libssh2 security boundaries: AES-GCM short/oversized blocks and overflowing username lengths PASS");
return 0;
}