open
https://gitlab.synchro.net/main/sbbs/-/work_items/1308
Enabling TLS on any JavaScript Socket without explicitly setting `tls_enhanced_certcheck = true` changes certificate compliance checking to `CRYPT_COMPLIANCELEVEL_REDUCED` for subsequent operations sharing cryptlib's default user in the process. Later sockets explicitly setting enhanced checking to true do not restore the level. Closing the socket that lowered it does not restore it either.
This is broader than an incorrectly configured individual connection: a single TLS connection using the internal default can affect other connections and services in the same Synchronet process.
## Expected behavior
A socket's enhanced-checking option should affect that socket's certificate processing without silently changing another socket's policy. Explicitly requesting enhanced checking must not inherit a reduced level left by an earlier socket.
## Cause
In `src/sbbs3/js_socket.cpp`:
- TLS sessions are created with `cryptCreateSession(..., CRYPT_UNUSED, ...)`, so they share cryptlib's default user.
- The TLS activation path calls `cryptSetAttribute(session, CRYPT_OPTION_CERT_COMPLIANCELEVEL, CRYPT_COMPLIANCELEVEL_REDUCED)` when `p->tls_enhanced_certcheck` is false. That field is internally false by default.
- There is no corresponding action when the field is true, nor any restoration when the connection closes.
The supplied cryptlib implementation routes `CRYPT_OPTION_CERT_COMPLIANCELEVEL` to `OBJECT_TYPE_USER` in `3rdp/src/cl/kernel/attr_acl.c`. Certificate import and checking subsequently read the level from their owner user. Passing a session handle to the setter therefore does not make the setting session-local.
Relevant source:
- [TLS activation and shared default user](
https://gitlab.synchro.net/main/sbbs/-/blob/master/src/sbbs3/js_socket.cpp#L2456)
- [Conditional compliance-level modification](
https://gitlab.synchro.net/main/sbbs/-/blob/master/src/sbbs3/js_socket.cpp#L2468)
## Confirmed native reproducer
Tested against the same `libsbbs.so` used by the local FreeBSD Synchronet 3.22 `jsexec` build. No network connection is needed to demonstrate the shared state:
```c
#include <stdio.h>
#include "cryptlib.h"
static void level(const char *label, int handle)
{
int value = -1;
int status = cryptGetAttribute(handle,
CRYPT_OPTION_CERT_COMPLIANCELEVEL, &value);
printf("%s: status=%d level=%d\n", label, status, value);
}
int main(void)
{
CRYPT_SESSION a, b;
if (cryptInit() != CRYPT_OK) return 1;
if (cryptCreateSession(&a, CRYPT_UNUSED, CRYPT_SESSION_TLS) != CRYPT_OK) return 2;
if (cryptCreateSession(&b, CRYPT_UNUSED, CRYPT_SESSION_TLS) != CRYPT_OK) return 3;
level("default before", CRYPT_UNUSED);
level("session B before", b);
printf("setting session A to REDUCED: %d\n",
cryptSetAttribute(a, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
CRYPT_COMPLIANCELEVEL_REDUCED));
level("session B after", b);
level("default after", CRYPT_UNUSED);
cryptDestroySession(a);
level("default after closing A", CRYPT_UNUSED);
cryptDestroySession(b);
cryptEnd();
return 0;
}
```
Observed output (`2` = STANDARD, `1` = REDUCED):
```text
default before: status=0 level=2
session B before: status=0 level=2
setting session A to REDUCED: 0
session B after: status=0 level=1
default after: status=0 level=1
default after closing A: status=0 level=1
```
The Socket binding makes the same setter call during TLS activation. Its enhanced=true path makes no call to undo it.
## Scope and correction considerations
This persists until another caller explicitly resets the shared cryptlib option; the Socket API does not provide that reset through `tls_enhanced_certcheck=true`. It affects operations sharing the default cryptlib user in that process, including other threads; separate processes have independent state.
REDUCED is the certificate compliance/structural checking level. This report does not assert that changing it automatically disables hostname verification or CA-chain signature verification; those are separate controls.
Simply saving and restoring the global level around a handshake can still race other threads performing certificate operations. Removing the shared modification or implementing genuinely isolated certificate policy would avoid that problem.
There is also a related readback defect: the `SOCK_PROP_TLS_ENHANCED_CERTCHECK` getter returns `!p->tls_disable_certverify` instead of `p->tls_enhanced_certcheck`. Consequently, reading the property can report true while the internal enhanced flag is false, concealing the default that triggers this behavior.
--- SBBSecho 3.38-Linux
* Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)