From 5423f555c4ae6d8fb900943fe67e84d586ba0817 Mon Sep 17 00:00:00 2001 From: Paul Adelsbach Date: Tue, 11 Aug 2026 09:56:31 -0700 Subject: [PATCH] Fix build with --disable-server --- apps/wolfssh/common.c | 11 ++++++++++- configure.ac | 16 +++++++++++++++- src/internal.c | 3 ++- tests/api.c | 14 ++++++++++---- tests/regress.c | 20 +++++++++++++++++--- tests/unit.c | 31 +++++++++++++++++++++++++++++++ 6 files changed, 85 insertions(+), 10 deletions(-) diff --git a/apps/wolfssh/common.c b/apps/wolfssh/common.c index f5e1883ca..e3fb744a2 100644 --- a/apps/wolfssh/common.c +++ b/apps/wolfssh/common.c @@ -287,8 +287,13 @@ static int FingerprintKey(const byte* pubKey, word32 pubKeySz, char* out) wc_Sha256Free(&sha); } - if (ret == 0) + if (ret == 0) { +#ifdef WOLFSSL_BASE64_ENCODE ret = Base64_Encode_NoNl(digest, sizeof(digest), (byte*)fp, &fpSz); +#else + ret = WS_NOT_COMPILED; +#endif + } if (ret == 0) { if (fpSz > 0 && fp[fpSz - 1] == '=') { @@ -409,7 +414,11 @@ int ClientPublicKeyCheck(const byte* pubKey, word32 pubKeySz, void* ctx) pubKeyType[sz] = 0; sz = WOLFSSH_CLIENT_ENCKEY_SIZE_ESTIMATE; +#ifdef WOLFSSL_BASE64_ENCODE ret = Base64_Encode_NoNl(pubKey, pubKeySz, (byte*)encodedKey, &sz); +#else + ret = WS_NOT_COMPILED; +#endif } if (ret == 0) diff --git a/configure.ac b/configure.ac index a98a70212..279d491c5 100644 --- a/configure.ac +++ b/configure.ac @@ -292,8 +292,22 @@ AS_IF([test "x$ENABLED_SMALLSTACK" = "xyes"], [AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_SMALL_STACK"]) AS_IF([test "x$ENABLED_NONE_CIPHER" = "xyes"], [AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_ALLOW_NONE_CIPHER"]) +dnl The client app shows host key fingerprints and writes known_hosts +dnl entries, both base64. wolfSSL only enables its encoder by default on +dnl x86_64, so check for it rather than fail later on a hidden prototype. AS_IF([test "x$ENABLED_SSHCLIENT" = "xyes"], - [AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_SSHCLIENT"]) + [AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_SSHCLIENT" + AC_MSG_CHECKING([for Base64_Encode_NoNl]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[#include +#include ]], + [[byte out[8]; + word32 outSz = sizeof(out); + (void)Base64_Encode_NoNl((const byte*)"x", 1, + out, &outSz);]])], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_MSG_ERROR([the SSH client app needs base64 encoding for host key fingerprints and known_hosts entries. Rebuild wolfSSL with --enable-base64encode, or leave out --enable-sshclient.])])]) AS_IF([test "x$ENABLED_TPM" = "xyes"], [AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_TPM" AC_CHECK_LIB([wolftpm],[wolfTPM2_Init],,[AC_MSG_ERROR([libwolftpm is required for ${PACKAGE}. It can be obtained from https://www.wolfssl.com/download.html/ .])])]) diff --git a/src/internal.c b/src/internal.c index bf52c7936..b3726876f 100644 --- a/src/internal.c +++ b/src/internal.c @@ -16794,11 +16794,12 @@ int SendServiceAccept(WOLFSSH* ssh, byte serviceId) } +#ifndef NO_WOLFSSH_SERVER + #define WS_EXTINFO_EXTENSION_COUNT 1 static const char serverSigAlgsName[] = "server-sig-algs"; -#ifndef NO_WOLFSSH_SERVER static int SendExtInfoServer(WOLFSSH* ssh) { byte* output; diff --git a/tests/api.c b/tests/api.c index 892810b99..037b1fadc 100644 --- a/tests/api.c +++ b/tests/api.c @@ -405,7 +405,9 @@ static const char serverKeyEccDer[] = "7bb87f38c66dd5a00a06082a8648ce3d030107a144034200048113ffa42bb79c" "45747a834c61f33fad26cf22cda9a3bca561b47ce662d4c2f755439a31fb8011" "20b5124b24f578d7fd22ef4635f005586b5f63c8da1bc4f569"; +#ifndef NO_WOLFSSH_SERVER static const byte serverKeyEccCurveId = ID_ECDSA_SHA2_NISTP256; +#endif #elif !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) static const char serverKeyEccDer[] = "3081a402010104303eadd2bbbf05a7be3a3f7c28151289de5bb3644d7011761d" @@ -414,7 +416,9 @@ static const char serverKeyEccDer[] = "7724316d46a23105873f2986d5c712803a6f471ab86850eb063e108961349cf8" "b4c6a4cf5e97bd7e51e975e3e9217261506eb9cf3c493d3eb88d467b5f27ebab" "2161c00066febd"; +#ifndef NO_WOLFSSH_SERVER static const byte serverKeyEccCurveId = ID_ECDSA_SHA2_NISTP384; +#endif #elif !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP521) static const char serverKeyEccDer[] = "3081dc0201010442004ca4d86428d9400e7b2df3912eb996c195895043af92e8" @@ -424,8 +428,10 @@ static const char serverKeyEccDer[] = "d18046a9717f2c6f59519c827095b29a6313306218c235769400d0f96d000a19" "3ba346652beb409a9a45c597a3ed932dd5aaae96bf2f317e5a7ac7458b3c6cdb" "aa90c355382cdfcdca7377d92eb20a5e8c74237ca5a345b19e3f1a2290b154"; +#ifndef NO_WOLFSSH_SERVER static const byte serverKeyEccCurveId = ID_ECDSA_SHA2_NISTP521; #endif +#endif #ifndef WOLFSSH_NO_RSA static const char serverKeyRsaDer[] = @@ -472,7 +478,7 @@ static const char serverKeyRsaDer[] = static void test_wolfSSH_CTX_UsePrivateKey_buffer(void) { -#ifndef WOLFSSH_NO_SERVER +#ifndef NO_WOLFSSH_SERVER WOLFSSH_CTX* ctx; #ifndef WOLFSSH_NO_ECDSA byte* eccKey; @@ -607,7 +613,7 @@ static void test_wolfSSH_CTX_UsePrivateKey_buffer(void) #ifndef WOLFSSH_NO_RSA FreeBins(rsaKey, NULL, NULL, NULL); #endif -#endif /* WOLFSSH_NO_SERVER */ +#endif /* NO_WOLFSSH_SERVER */ } @@ -1066,7 +1072,7 @@ static void test_wolfSSH_ReadCert_file(void) static void test_wolfSSH_CTX_UseCert_file(void) { #if defined(WOLFSSH_CERTS) && !defined(NO_FILESYSTEM) && \ - !defined(WOLFSSH_USER_FILESYSTEM) && !defined(WOLFSSH_NO_SERVER) + !defined(WOLFSSH_USER_FILESYSTEM) && !defined(NO_WOLFSSH_SERVER) WOLFSSH_CTX* ctx = NULL; #ifndef WOLFSSH_NO_ED25519 int ret; @@ -1115,7 +1121,7 @@ static void test_wolfSSH_CTX_UseCert_file(void) static void test_wolfSSH_CTX_AddRootCert_file(void) { #if defined(WOLFSSH_CERTS) && !defined(NO_FILESYSTEM) && \ - !defined(WOLFSSH_USER_FILESYSTEM) && !defined(WOLFSSH_NO_SERVER) + !defined(WOLFSSH_USER_FILESYSTEM) && !defined(NO_WOLFSSH_SERVER) WOLFSSH_CTX* ctx = NULL; ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL); diff --git a/tests/regress.c b/tests/regress.c index f601c61d0..8c2adc553 100644 --- a/tests/regress.c +++ b/tests/regress.c @@ -147,7 +147,8 @@ static word32 AppendUint32(byte* buf, word32 bufSz, word32 idx, word32 value) return idx; } -static word32 ReadUint32(const byte* buf) +/* Callers sit in separate conditional blocks; some builds have none. */ +static WS_MAYBE_UNUSED word32 ReadUint32(const byte* buf) { return ((word32)buf[0] << 24) | ((word32)buf[1] << 16) | ((word32)buf[2] << 8) | (word32)buf[3]; @@ -306,6 +307,11 @@ static void MemIoInit(MemIo* io, byte* in, word32 inSz, byte* out, word32 outCap io->outCap = outCap; } +/* The harness below and everything built on it drive a server-side session. + * With NO_WOLFSSH_SERVER the message filter has no server branch, so every + * message on such a session is refused and those tests cannot run. */ +#ifndef NO_WOLFSSH_SERVER + typedef struct { WOLFSSH_CTX* ctx; WOLFSSH* ssh; @@ -438,6 +444,8 @@ static void TestKbInfoResponseMismatchKeepsFraming(void) #endif /* WOLFSSH_KEYBOARD_INTERACTIVE */ +#endif /* NO_WOLFSSH_SERVER */ + /* Needs server, client, key files, and one covered host-key algorithm. */ #if !defined(NO_WOLFSSH_SERVER) && !defined(NO_WOLFSSH_CLIENT) && \ !defined(NO_FILESYSTEM) && \ @@ -1282,6 +1290,8 @@ static void TestKexDhReplyRejectsSigNameOverrun(void) #endif /* KEXDH_REPLY_REGRESS_KEX_ALGO */ +#ifndef NO_WOLFSSH_SERVER + static word32 ParseChannelOpenFailRecipient(const byte* pkt, word32 sz) { word32 chan; @@ -1504,6 +1514,8 @@ static int RejectRemoteSetupFwdCb(WS_FwdCbAction action, void* ctx, #endif +#endif /* NO_WOLFSSH_SERVER */ + /* Reject auth messages while the peer is still keying and the client * expects the KEX reply. */ static void TestAuthMessageBlockedDuringKeying(WOLFSSH* ssh) @@ -1887,7 +1899,6 @@ static void TestServerServiceRequestStateGated(WOLFSSH* ssh) * on reject. */ AssertIntEQ(ssh->error, WS_MSGID_NOT_ALLOWED_E); } -#endif /* NO_WOLFSSH_SERVER */ static void TestChannelOpenCallbackRejectSendsOpenFail(void) @@ -2535,6 +2546,9 @@ static void TestAgentChannelNullAgentSendsOpenFail(void) #endif +#endif /* NO_WOLFSSH_SERVER */ + + /* Reject a peer KEXINIT once keying is in progress. */ static void TestKexInitRejectedWhenKeying(WOLFSSH* ssh) { @@ -5848,7 +5862,6 @@ int main(int argc, char** argv) TestServerUserauthBlockedBeforeKeyed(serverSsh); TestServerOnlyUserauthMsgsBlocked(serverSsh); TestServerServiceRequestStateGated(serverSsh); -#endif TestChannelOpenCallbackRejectSendsOpenFail(); TestSecondSessionChannelRejected(); TestUsernameChangeDisconnects(); @@ -5875,6 +5888,7 @@ int main(int argc, char** argv) #ifdef WOLFSSH_AGENT TestAgentChannelNullAgentSendsOpenFail(); #endif +#endif /* NO_WOLFSSH_SERVER */ TestKexInitRejectedWhenKeying(ssh); #if !defined(WOLFSSH_NO_ECDH_SHA2_NISTP256) && !defined(WOLFSSH_NO_RSA) \ && !defined(WOLFSSH_NO_CURVE25519_SHA256) \ diff --git a/tests/unit.c b/tests/unit.c index 4cf161294..bcbd70585 100644 --- a/tests/unit.c +++ b/tests/unit.c @@ -4156,6 +4156,11 @@ static int test_DoChannelWindowAdjust_overflow(void) return result; } +/* The tests below drive a server-side session that sends a window adjust. + * With NO_WOLFSSH_SERVER the message filter has no server branch, so every + * message on such a session is refused and the tests cannot run. */ +#ifndef NO_WOLFSSH_SERVER + /* An unknown extended data type must be ignored (consumed and discarded) per * RFC 4254, not rejected: the call returns WS_SUCCESS, nothing is buffered for * the application, and the window is left intact (replenished on receipt). */ @@ -4212,6 +4217,8 @@ static int test_DoChannelExtendedData_unknown_type(void) return result; } +#endif /* NO_WOLFSSH_SERVER */ + /* Exercises the accumulating extended-data buffer and its window * back-pressure: two stderr blobs that arrive before the application reads * must both be preserved (no silent overwrite), the channel window must be @@ -4510,6 +4517,8 @@ static int CountIoSend(WOLFSSH* ssh, void* buf, word32 sz, void* ctx) return (int)sz; } +#ifndef NO_WOLFSSH_SERVER + /* RFC 4253 section 7.1: no connection-layer message (such as * SSH_MSG_CHANNEL_WINDOW_ADJUST) may go out between KEXINIT and NEWKEYS. * Neither DoChannelExtendedData() discarding an unknown data type nor @@ -4693,6 +4702,8 @@ static int test_DoChannelExtendedData_newkeys(void) return result; } +#endif /* NO_WOLFSSH_SERVER */ + /* A peer may trickle stderr in tiny packets while the app is slow to drain. The * data it can send before draining is bounded by the receive window, and the * buffer holding it must stay bounded too: an AppendBuffer() that reallocates @@ -4791,6 +4802,8 @@ static int test_ChannelExtDataBufferGrowth(void) return result; } +#ifndef NO_WOLFSSH_SERVER + /* Fires once the message highwater mark is crossed and reports an error. */ static int FailHighwater(byte side, void* ctx) { @@ -5235,6 +5248,8 @@ static int test_ChannelExtDataCreditWantWrite(void) return result; } +#endif /* NO_WOLFSSH_SERVER */ + /* ChannelCreditWindow() guards its two defensive early exits: a NULL ssh or * channel returns WS_BAD_ARGUMENT, and folding a credit that would push * pendingWindowAdjust past UINT32_MAX returns WS_OVERFLOW_E and leaves the @@ -5386,6 +5401,8 @@ static int test_ChannelReadExtBadArgs(void) return result; } +#ifndef NO_WOLFSSH_SERVER + /* A crafted transport packet staged for the receive path, and the running * offset PacketIoRecv has delivered. */ static const byte* s_recvPkt = NULL; @@ -5910,6 +5927,8 @@ static int test_ChannelReadExtClearsStaleWantWrite(void) return result; } +#endif /* NO_WOLFSSH_SERVER */ + static int test_SendChannelData_eofTxd(void) { WOLFSSH_CTX* ctx = NULL; @@ -15788,6 +15807,7 @@ int wolfSSH_UnitTest(int argc, char** argv) (unitResult == 0 ? "SUCCESS" : "FAILED")); testResult = testResult || unitResult; +#ifndef NO_WOLFSSH_SERVER unitResult = test_DoChannelExtendedData_unknown_type(); printf("DoChannelExtendedData_unknown_type: %s\n", (unitResult == 0 ? "SUCCESS" : "FAILED")); @@ -15803,11 +15823,14 @@ int wolfSSH_UnitTest(int argc, char** argv) (unitResult == 0 ? "SUCCESS" : "FAILED")); testResult = testResult || unitResult; +#endif /* NO_WOLFSSH_SERVER */ + unitResult = test_ChannelExtDataBufferGrowth(); printf("ChannelExtDataBufferGrowth: %s\n", (unitResult == 0 ? "SUCCESS" : "FAILED")); testResult = testResult || unitResult; +#ifndef NO_WOLFSSH_SERVER unitResult = test_ChannelExtDataCredit(); printf("ChannelExtDataCredit: %s\n", (unitResult == 0 ? "SUCCESS" : "FAILED")); @@ -15823,15 +15846,20 @@ int wolfSSH_UnitTest(int argc, char** argv) (unitResult == 0 ? "SUCCESS" : "FAILED")); testResult = testResult || unitResult; +#endif /* NO_WOLFSSH_SERVER */ + unitResult = test_ChannelSendExt(); printf("ChannelSendExt: %s\n", (unitResult == 0 ? "SUCCESS" : "FAILED")); testResult = testResult || unitResult; +#ifndef NO_WOLFSSH_SERVER unitResult = test_ChannelExtDataCreditWantWrite(); printf("ChannelExtDataCreditWantWrite: %s\n", (unitResult == 0 ? "SUCCESS" : "FAILED")); testResult = testResult || unitResult; +#endif /* NO_WOLFSSH_SERVER */ + unitResult = test_ChannelCreditWindowGuards(); printf("ChannelCreditWindowGuards: %s\n", (unitResult == 0 ? "SUCCESS" : "FAILED")); @@ -15842,6 +15870,7 @@ int wolfSSH_UnitTest(int argc, char** argv) (unitResult == 0 ? "SUCCESS" : "FAILED")); testResult = testResult || unitResult; +#ifndef NO_WOLFSSH_SERVER unitResult = test_StreamReadExtDataOtherChannel(); printf("StreamReadExtDataOtherChannel: %s\n", (unitResult == 0 ? "SUCCESS" : "FAILED")); @@ -15877,6 +15906,8 @@ int wolfSSH_UnitTest(int argc, char** argv) (unitResult == 0 ? "SUCCESS" : "FAILED")); testResult = testResult || unitResult; +#endif /* NO_WOLFSSH_SERVER */ + unitResult = test_SendChannelData_eofTxd(); printf("SendChannelData_eofTxd: %s\n", (unitResult == 0 ? "SUCCESS" : "FAILED")); testResult = testResult || unitResult;