Subj : 3rdp/dist/Botan.tar.xz src/build/botan.gmake src/ssh/posix/threads.c t To : Git commit to main/sbbs/master From : Deuc¨ Date : Thu Apr 23 2026 03:33:46 https://gitlab.synchro.net/main/sbbs/-/commit/8f25a245bb9a6abc4b191b69 Added Files: 3rdp/dist/Botan.tar.xz src/build/botan.gmake src/ssh/posix/threads.c threads.h src/ssh/win32/threads.c threads.h src/syncterm/ini_crypt.c ini_crypt.h src/syncterm/legacy_ciphers/idea.c legacy_ciphers.h rc2.c register.c src/syncterm/xp_crypt.h xp_crypt_botan3.cpp xp_crypt_none.c xp_crypt_openssl.c xp_sndfile.c xp_sndfile.h xp_tls.h xp_tls_botan3.cpp xp_tls_none.c xp_tls_openssl.c src/xpdev/extdeps.mk Modified Files: .gitlab-ci-unix.yml .gitlab-ci.yml 3rdp/build/Common.gmake GNUmakefile src/build/Common.gmake src/doors/gac/gac_bj/src/GNUmakefile src/doors/gac/gac_fc/src/GNUmakefile src/doors/gac/gac_wh/src/GNUmakefile src/ssh/CMakeLists.txt TODO.md deucessh-portable.h src/ssh/kex/sntrup761.c src/ssh/key_algo/rsa-sha2-256-botan.cpp rsa-sha2-512-botan.cpp ssh-ed25519-botan.cpp src/ssh/ssh-internal.h ssh-trans.c src/syncterm/CHANGES CMakeLists.txt GNUmakefile audio_apc.c bbslist.c bbslist.h build.bat conn.c release.bat ssh.c ssh.h syncterm.c syncterm.h targets.mk telnets.c webget.c src/xpdev/CMakeLists.txt Common.gmake GNUmakefile ini_file.c ini_file.h xpbeep.c Log Message: SyncTERM: drop Cryptlib Ä move SSH to DeuceSSH + TLS/symmetric crypto to OpenSSL or Botan 3 SyncTERM's SSH, TLS (TelnetS + HTTPS cache refresh), and encrypted- bbslist.ini paths all ran through a single monolithic Cryptlib dependency. Cryptlib is aging, actively deprecated in parts of Synchronet, and its opaque session model fit awkwardly with SyncTERM's ring-buffered I/O threads. This branch ports all of it: - SSH: Cryptlib  DeuceSSH (src/ssh/, from-scratch library already maintained in this repo). - TLS client: Cryptlib  xp_tls shim backed by OpenSSL or Botan 3. - Encrypted bbslist.ini: Cryptlib KDF + ciphers  xp_crypt shim backed by the same two backends. DeuceSSH's explicit-callback API maps cleanly onto SyncTERM's ring buffers; its test suite + branch coverage live alongside. All three workloads share a single backend choice at compile time. Architecture ------------ - xp_tls.[ch] (syncterm/): thin client-TLS API Ä open/push/pop/ flush/close Ä matching the shape of the old inline cryptPushData / cryptPopData calls in telnets.c and webget.c. OpenSSL / Botan 3 / none stubs. - xp_crypt.[ch] (syncterm/): thin symmetric-crypto + KDF API Ä xp_crypt_open(algo, keySize, salt, kdf, pwd, encrypt)  handle-based process(buf, n) semantics. Same backend trio. - ini_crypt.c (syncterm/): iniReadEncryptedFile / iniWriteEncryptedFile built on xp_crypt + ini_file.c. Moved out of xpdev so libxpdev / libsbbs / Synchronet server binaries don't transitively depend on OpenSSL / Botan 3 when they don't use TLS or encrypted INI themselves. - src/ssh/ DeuceSSH: src/syncterm/ssh.c rewritten against its native session + channel API. Algorithm preferences registered once at init; host-key callback does SHA-256 fingerprint verification; authentication tries pubkey  password  keyboard-interactive; channel setup passes terminal type + PTY size; resize via dssh_chan_send_window_change. - SFTP pubkey upload: ssh.c's add_public_key() rewritten on top of a DeuceSSH "sftp" subsystem channel. src/sftp/ itself had zero Cryptlib references and is unchanged. Encrypted bbslist.ini format ---------------------------- Reader honours both on-disk formats so existing files keep opening: v1 (Cryptlib era): PBKDF2-HMAC-SHA256, KDFiterations literal. Any of 3DES / IDEA / CAST / RC2 / RC4 / AES / ChaCha20. v2 (new writes): scrypt, N=2^15 / r=8 / p=1 by default Ä KDF parameters embedded in the header so the reader never has to guess. Write-side cipher choice restricted to AES-256 and ChaCha20; the list- encryption menu drops the legacy-cipher options. Legacy-read support: OpenSSL's legacy provider (3DES / CAST5 / RC4) is loaded lazily on first decrypt; IDEA and RC2 don't exist in either backend today, so SyncTERM ships bundled decrypt-only reference implementations (src/syncterm/legacy_ciphers/) registered with xp_crypt at startup. Automatic v1  v2 migration: iniReadBBSList does a one-shot migration immediately after a successful decrypt of the user bbslist. A PBKDF2 KDF or a 3DES/IDEA/CAST/RC2/RC4 cipher triggers re-encryption as AES-256 + scrypt and a matching update to syncterm.ini's KeyDerivationIterations setting. Both files (bbslist r+b, syncterm.ini r+) are opened and syncterm.ini is pre-read before either is mutated; any open or write failure emits a uifc.msg and exit( EXIT_FAILURE) so in-memory algo / keysize / KDF spec can't drift out of sync with disk. On the good-path the bbslist is rewritten first, then the syncterm.ini setting; the original PBKDF2 iteration hint survives until both writes commit. KeyDerivationIterations: Now a KDF-spec string in syncterm.ini, not an integer. New installs get "scrypt-N15" (N=2^15 = 32,768, ~16 MiB). Cryptlib-era digit values (e.g. "50000") are still recognised on read as the PBKDF2 iteration hint for v1 files and survive until the auto-migration above rewrites them. The config menu still takes an integer from the user Ä scrypt's cost_log2 (8..24) Ä stored as "scrypt-N"; writer parses the string and falls back to the compiled-in default for anything it can't interpret as scrypt, so a PBKDF2-shaped write is impossible by construction. iniWriteEncryptedFile's parameter type switched from int KDFiterations to const char *kdf_spec to match. SSH host-key fingerprints ------------------------- Stored SHA-1 fingerprints from pre-migration bbslist.ini files remain valid on first reconnect Ä on a match, the stored value is silently upgraded to SHA-256. The three-option mismatch dialog (Disconnect / Update / Ignore) is preserved. Build-time knobs ---------------- - DEUCESSH_BACKEND / OpenSSL | Botan. Shared probe in XP_CRYPTO_BACKEND build/Common.gmake picks one for the whole tree so every subproject of a given source tree + command-line agrees. Cached libxpdev_mt.a interoperates with its downstream linkers. - USE_VENDORED_BOTAN Fall back to building Botan 3 from 3rdp/dist/Botan.tar.xz when neither system Botan 3.6+ nor OpenSSL 3.0+ is available. Windows cross-compile always uses vendored. A shared 3rdp/build `botan:` delegation target mirrors the existing `cryptlib:` machinery. - WITHOUT_DEUCESSH Drops src/syncterm/ssh.c, CONN_TYPE_SSH / _SSHNA, the SFTP pubkey-upload bridge, and the DeuceSSH sub-build. - WITHOUT_CRYPTO Drops src/syncterm/telnets.c, CONN_TYPE_TELNETS, the encrypted bbslist.ini menu + dispatch, and the bundled legacy-cipher reference code. webget.c still compiles; its HTTPS paths no-op. xp_tls / xp_crypt fall back to "none" stub backends so nothing drags in OpenSSL or Botan 3. Auto-degradations so CI stays honest across the runner fleet: - Python 3 absent on Windows (needed for vendored Botan's configure.py)  WITHOUT_CRYPTO + WITHOUT_DEUCESSH. - Compiler cmake can't drive at C17, OR the SDK/libc doesn't ship the C11 runtime functions DeuceSSH uses (pre-10.15 macOS SDKs lack timespec_get / TIME_UTC even with an AppleClang that nominally supports -std=c17)  DeuceSSH configure fails  WITHOUT_DEUCESSH; the rest of syncterm still builds. DeuceSSH's CMakeLists probes timespec_get explicitly Ä CMake's C_STANDARD 17 + C_STANDARD_REQUIRED ON only checks compiler-version tables, not the actual SDK. DeuceSSH stays strict-C17 as its upstream- portability guarantee; the probe covers the handful of platforms that fall outside that window. The SyncTERM Build Options dialog reflects all of this Ä [*] / [ ] columns for DeuceSSH, OpenSSL, Botan 3, JPEG XL, libsndfile, display backends, audio backends Ä so users can tell at a glance what the binary they're running actually has. MinGW + MSVC + older macOS portability -------------------------------------- DeuceSSH is strict C17. Added thin shims where the libc falls short of C11's requirement: - src/ssh/posix/threads.{h,c}: pthread  C11 threads wrapper (mtx_*, cnd_*, thrd_*). Platform- gated in DeuceSSH's CMakeLists via a HAVE_THREADS_IN_LIBC probe. Covers macOS pre-14 SDK, older NetBSD, any libc without . - src/ssh/win32/threads.{h,c}: CRITICAL_SECTION / CONDITION_VARIABLE / _beginthreadex wrapper. MinGW-w64 and MSVC both lack the libc header. xpdev MSVC cmake: added /experimental:c11atomics (the hand-written xpdev.vcxproj has it; cmake path was missing it) and three C source files that had been in the gmake objects.mk but not the cmake SOURCE list (os_info.c, rwlockwrap.c, stbuf.c). SyncTERM MSVC Windows build moved onto cmake: src/syncterm/build.bat calls VsDevCmd.bat then cmake / nmake / msbuild. The hand-written SyncTERM.vcxproj + helpers are no longer the path of record. Build ordering + CI ------------------- The top-level all-target rule is Botan  xpdev-mt  ciolib-mt  uifc-mt  (sftp-mt + deucessh)  syncterm. Both gmake and cmake paths pre-probe DeuceSSH's configure once the crypto backend it needs is on disk; if cmake can't produce deucessh.pc for any reason (C17 unsupported, incomplete C11 runtime, missing crypto headers, etc.), WITHOUT_DEUCESSH is set automatically and the main build continues. New .gitlab-ci-unix.yml [botan] job mirrors [cryptlib]: it runs `gmake botan`, archives 3rdp/*.release/botan, and on systems where the build is a no-op (system Botan/OpenSSL detected) produces an empty-directory placeholder archive so `tar -T /dev/null` never has to emit an empty tarball. The .pc file is rewritten to use ${pcfiledir}-relative prefix at install time so the archive relocates cleanly across runner concurrent-ids. [syncterm] extracts the archive; other jobs that don't build SyncTERM don't (dropping the botan.tgz extract + [botan] dep from 20+ non-syncterm jobs). [syncterm-cmake] also extracts the archive rather than building a second vendored copy via its own ExternalProject. Files moved / renamed --------------------- src/xpdev/{xp_tls,xp_crypt}*.[ch,cpp]  src/syncterm/{xp_tls,xp_crypt}*.[ch,cpp] src/xpdev/ini_crypt.c  src/syncterm/ini_crypt.c src/xpdev/ini_file.h : encrypted-INI decls moved to new src/syncterm/ini_crypt.h (including enum iniCryptAlgo); ini_file.h stays crypto-free. src/syncterm/sndfile.{h,c}  src/syncterm/xp_sndfile.{h,c} (the old name shadowed libsndfile's when the syncterm source dir was on -I path). Verification ------------ SSH: - password auth, pubkey auth, keyboard-interactive auth against Synchronet test BBS. - first-connect fingerprint prompt; reconnect uses stored fingerprint; stored-SHA-1 upgrade to SHA-256 on next connect. - SFTP pubkey upload round-trip. TLS: - TelnetS handshake + interactive session against a known TelnetS BBS (Dave's, vert). - HTTPS: `lst://` bbslist refresh path; ETag / Last-Modified caching behaves unchanged. Encrypted bbslist.ini: - Read-compat: pre-migration files (AES-256, 3DES, ChaCha20, IDEA, RC2) all decrypt and populate entries. v1 PBKDF2 header is honoured; KDFiterations hint in syncterm.ini supplies the count. - Auto-migration: v1 files (PBKDF2 or legacy cipher) are re-encrypted as AES-256/scrypt in one shot at decrypt time, and syncterm.ini's KeyDerivationIterations is updated to "scrypt-N15" the same way. Any migration failure exit()s Ä next run retries from the untouched v1 state. - Round-trip: save encrypted  reload  verify entries. - Legacy-write UI gone Ä menu offers AES-256 + ChaCha20 only. - Scrypt params embedded in v2 header; reader reconstructs N / r / p from there rather than guessing. Automated: - cterm_test + termtest pass unchanged. - Disconnect from an active SSH session doesn't leak threads. Co-Authored-By: Claude Opus 4.7 (1M context) --- þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net .