Generate exact-hash SDK source overrides without modifying dependencies. Harden SSH allocation and algorithm policy, tighten web authentication cleanup, and add focused host contract tests and documentation.
93 lines
3.3 KiB
C
93 lines
3.3 KiB
C
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "ssh_protocol_policy.h"
|
|
|
|
static const char *const expected[] = {
|
|
"curve25519-sha256,ecdh-sha2-nistp256",
|
|
"ecdsa-sha2-nistp256",
|
|
"aes128-gcm@openssh.com,aes256-gcm@openssh.com",
|
|
"hmac-sha2-256",
|
|
"ssh-ed25519,ecdsa-sha2-nistp256",
|
|
};
|
|
static unsigned calls, fail_at;
|
|
static int failure;
|
|
static WOLFSSH_CTX *candidate;
|
|
|
|
static int set(WOLFSSH_CTX *ctx, const char *list, const char **field,
|
|
unsigned step)
|
|
{
|
|
assert(ctx == candidate);
|
|
assert(ctx->sentinel == 0x12345678U);
|
|
assert(++calls == step);
|
|
assert(strcmp(list, expected[step - 1]) == 0);
|
|
if (step == fail_at) return failure;
|
|
*field = list;
|
|
return WS_SUCCESS;
|
|
}
|
|
#define SETTER(name, field, step) \
|
|
int wolfSSH_CTX_SetAlgoList##name(WOLFSSH_CTX *c, const char *s) \
|
|
{ return set(c, s, &c->field, step); }
|
|
SETTER(Kex, algoListKex, 1)
|
|
SETTER(Key, algoListKey, 2)
|
|
SETTER(Cipher, algoListCipher, 3)
|
|
SETTER(Mac, algoListMac, 4)
|
|
SETTER(KeyAccepted, algoListKeyAccepted, 5)
|
|
|
|
static const char *get(const WOLFSSH_CTX *c, unsigned index)
|
|
{
|
|
switch (index) {
|
|
case 0: return c->algoListKex;
|
|
case 1: return c->algoListKey;
|
|
case 2: return c->algoListCipher;
|
|
case 3: return c->algoListMac;
|
|
default: return c->algoListKeyAccepted;
|
|
}
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
assert(ssh_protocol_policy_apply(NULL) == WS_SSH_CTX_NULL_E);
|
|
assert(calls == 0);
|
|
/* This is an unpublished stack-owned candidate. Any attempted vendor free
|
|
* has no test definition and fails linking; transport publication is outside
|
|
* this helper and is covered by the parent's integration tests. */
|
|
static const char original[] = "old-default";
|
|
for (unsigned step = 1; step <= 5; ++step) {
|
|
for (unsigned sign = 0; sign < 2; ++sign) {
|
|
WOLFSSH_CTX ctx = {
|
|
.algoListKex = original, .algoListKey = original,
|
|
.algoListCipher = original, .algoListMac = original,
|
|
.algoListKeyAccepted = original, .sentinel = 0x12345678U,
|
|
};
|
|
candidate = &ctx;
|
|
calls = 0;
|
|
fail_at = step;
|
|
failure = sign ? (int)(9000 + step) : -(int)(9000 + step);
|
|
assert(ssh_protocol_policy_apply(&ctx) == failure);
|
|
assert(calls == step);
|
|
assert(ctx.sentinel == 0x12345678U);
|
|
for (unsigned i = 0; i < 5; ++i) {
|
|
if (i + 1 < step) assert(strcmp(get(&ctx, i), expected[i]) == 0);
|
|
else assert(get(&ctx, i) == original);
|
|
}
|
|
}
|
|
}
|
|
const char *retained[5];
|
|
for (unsigned pass = 0; pass < 2; ++pass) {
|
|
WOLFSSH_CTX ctx = {.sentinel = 0x12345678U};
|
|
candidate = &ctx;
|
|
calls = fail_at = 0;
|
|
assert(ssh_protocol_policy_apply(&ctx) == WS_SUCCESS);
|
|
assert(calls == 5);
|
|
for (unsigned i = 0; i < 5; ++i) {
|
|
assert(strcmp(get(&ctx, i), expected[i]) == 0);
|
|
if (pass == 0) retained[i] = get(&ctx, i);
|
|
else assert(retained[i] == get(&ctx, i));
|
|
}
|
|
}
|
|
for (unsigned i = 0; i < 5; ++i) assert(strcmp(retained[i], expected[i]) == 0);
|
|
puts("PASS: apply NULL, five exact lists, every setter failure (+/-), stop/no fallback, retained strings");
|
|
return 0;
|
|
}
|