BBS:      TELESC.NET.BR
Assunto:  3rdp/dist/Botan.tar.xz src/build/botan.gmake src/ssh/posix/threads.c t
De:       Deuc¨
Data:     Thu, 23 Apr 2026 03:33:46 -0700
-----------------------------------------------------------
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) 
n
---
  mSynchronetn  hgVertrauen n hHome of Synchronet n gh[vert/cvs/bbs].synchro.net

-----------------------------------------------------------
[Voltar]