Skip to content

BACnet/SC (Annex AB) Device UUID and VMAC identity claim to certificate - #1504

Open
skarg wants to merge 22 commits into
masterfrom
bugfix/bacnet-sc-bind-connect-request-identity-to-certificate
Open

skarg wants to merge 22 commits into
masterfrom
bugfix/bacnet-sc-bind-connect-request-identity-to-certificate

Conversation

@skarg

@skarg skarg commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

BACnet/SC (Annex AB) implementation Device UUID and VMAC identity claims are never bound to the certificate.

The BSC data plane performs zero peer-certificate inspection (bvlc-sc.c, bsc-socket.c, bsc-hub-function.c) (static check: no SSL_get_peer*/SSL_get_verify_result/peer-cert references). The UUID/VMAC in the ConnectRequest are plaintext assertions.

Implemented as an opt-in, disabled-by-default local trust mapping of the ConnectRequest identity to the certificate: the claimed Device UUID/VMAC must be authorized by the presented certificate (or an explicit operator trust mapping). This closes the real gap while staying conformant.

…aims are never bound to the certificate.

The BSC data plane performs zero peer-certificate inspection (`bvlc-sc.c`, `bsc-socket.c`, `bsc-hub-function.c`) (static check: no `SSL_get_peer*`/`SSL_get_verify_result`/peer-cert references). The UUID/VMAC in the ConnectRequest are plaintext assertions.

Implemented as an opt-in, disabled-by-default local trust mapping of the ConnectRequest identity to the certificate: the claimed Device UUID/VMAC must be authorized by the presented certificate (or an explicit operator trust mapping). This closes the real gap while staying conformant.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Certificate parsing has an authorization bypass, backend compatibility issues, and the policy is inaccessible through the standard datalink configuration path.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Adds opt-in certificate-to-UUID/VMAC authorization for BACnet/SC hub connections.

Changes:

  • Extracts BACnet identities from certificate SAN URIs.
  • Adds configurable hub identity policies and enforcement.
  • Adds integration tests for UUID authorization and rejection.
File summaries
File Description
src/bacnet/datalink/bsc/websocket.h Declares peer-certificate identity extraction.
src/bacnet/datalink/bsc/bsc-socket.h Defines identity-policy entries and context storage.
src/bacnet/datalink/bsc/bsc-socket.c Enforces policies during Connect-Request handling.
src/bacnet/datalink/bsc/bsc-hub-function.h Exposes policy configuration API.
src/bacnet/datalink/bsc/bsc-hub-function.c Implements policy assignment.
ports/linux/websocket-srv.c Extracts SAN identities using OpenSSL.
ports/bsd/websocket-srv.c Adds BSD certificate extraction.
ports/win32/websocket-srv.c Adds Windows certificate extraction.
test/bacnet/datalink/hub-sc/src/main.c Adds authorization integration tests.
Review details
  • Files reviewed: 9/9 changed files
  • Comments generated: 8
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread ports/bsd/websocket-srv.c Outdated
Comment thread ports/bsd/websocket-srv.c Outdated
Comment thread ports/linux/websocket-srv.c Outdated
Comment thread ports/linux/websocket-srv.c
Comment thread ports/win32/websocket-srv.c Outdated
Comment thread ports/win32/websocket-srv.c Outdated
Comment thread src/bacnet/datalink/bsc/bsc-hub-function.h
Comment thread test/bacnet/datalink/hub-sc/src/main.c Outdated
…cy() so operators using the documented API can actually opt in
…VMAC is accepted and a mismatched VMAC is rejected.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Policy activation has a startup authorization window, invalid configurations can be persisted after failed updates, and matching is order-dependent.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (1)

src/bacnet/datalink/bsc/bsc-socket.c:865

  • This lookup returns the first entry with the certificate identity before considering the claimed UUID/VMAC. Since the API does not require identities to be unique, a valid later entry for the same certificate identity is unreachable and authorization becomes array-order dependent. Either match identity, UUID, and optional VMAC together while scanning, or reject duplicate identities when the policy is installed.
    for (i = 0; i < c->ctx->identity_policy_num; i++) {
        if (bsc_cert_identity_matches(
                san_uri, c->ctx->identity_policy[i].identity)) {
            return &c->ctx->identity_policy[i];
  • Files reviewed: 15/15 changed files
  • Comments generated: 4
  • Review effort level: Balanced

Comment thread src/bacnet/datalink/bsc/bsc-hub-function.c
Comment thread src/bacnet/datalink/bsc/bsc-datalink.c
Comment thread src/bacnet/datalink/bsc/bsc-node.c Outdated
Comment thread src/bacnet/datalink/bsc/bsc-socket.c Outdated
…e identity matching and revalidation of connected sockets

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Out-of-bounds SAN traversal, concurrency hazards, and a missing BSD symbol affect correctness and portability.

Get a fresh assessment by requesting another Copilot review.

Review details
  • Files reviewed: 15/15 changed files
  • Comments generated: 7
  • Review effort level: Balanced

Comment thread ports/bsd/websocket-srv.c Outdated
Comment thread ports/linux/websocket-srv.c
Comment thread ports/win32/websocket-srv.c
Comment thread src/bacnet/datalink/bsc/bsc-hub-function.c Outdated
Comment thread src/bacnet/datalink/bsc/bsc-hub-function.c
Comment thread src/bacnet/datalink/bsc/bsc-socket.c Outdated
Comment thread test/bacnet/datalink/bsc-datalink/src/main.c
…r API wrapping it as in the Linux/Win32 ports.
…l, then release it before parsing the returned `X509`.
…licy operates on one consistent hub instance.
… live, and verifies that the existing connection is disconnected.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Multi-SAN authorization can reject valid claims, and policy state can retain a dangling pointer across datalink cleanup.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

test/bacnet/datalink/bsc-datalink/src/main.c:2671

  • This early-return path leaks node_ev2.e, which was allocated by init_node_ev() above. It is the path exercised by the mbedTLS build, so release the event before returning just as the normal path does.
  • Files reviewed: 15/15 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment thread src/bacnet/datalink/bsc/bsc-datalink.c Outdated
Comment thread src/bacnet/datalink/bsc/bsc-socket.c Outdated
…dd the corresponding ordering case to the multi-SAN test).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

VMAC enforcement can be bypassed through the exported helper, and the public configuration extension makes disabled-by-default behavior unsafe for existing callers.

Get a fresh assessment by requesting another Copilot review.

Review details
  • Files reviewed: 16/16 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment thread src/bacnet/datalink/bsc/bsc-node.h Outdated
Comment thread src/bacnet/datalink/bsc/bsc-socket.c Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Live policy revocation still permits unauthorized traffic during graceful disconnect, and one test path leaks an event resource.

Get a fresh assessment by requesting another Copilot review.

Review details
  • Files reviewed: 14/14 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment thread src/bacnet/datalink/bsc/bsc-hub-function.c Outdated
Comment thread test/bacnet/datalink/bsc-datalink/src/main.c

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Fixed-size SAN handling can reject authorized certificates, and cleanup can retain a stale borrowed policy pointer.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (3)

Previously missed (3) — in code that hasn't changed since the last review.

src/bacnet/datalink/bsc/bsc-hub-function.c:104

  • Live revalidation repeats the 256-byte aggregate SAN limit. A connected peer with more BACnet URI SAN data than this is forcefully disconnected after any policy update, even if one URI authorizes its UUID/VMAC. Reuse an uncapped shared certificate matcher so initial authorization and revalidation have identical, order-independent behavior.
    src/bacnet/datalink/bsc/bsc-socket.c:905
  • The authorization path is limited to 256 bytes of aggregate BACnet SAN URIs. bws_srv_get_peer_cert_identities() returns INVALID_OPERATION when multiple otherwise-valid entries exceed that buffer, so this rejects an authorized certificate even when an earlier URI matches the policy and makes acceptance depend on unrelated SAN count/order. Match while iterating the certificate names or size storage from the SAN extension instead of imposing this undocumented cap.
    test/bacnet/datalink/hub-sc/src/main.c:3179
  • This test passes URI strings directly to the policy helper, so it does not exercise the new OpenSSL SAN extraction or the fixed-size packed buffer used by real connections. A regression in extraction or SAN ordering would still pass. Use a client certificate containing multiple BACnet URI SANs through an actual hub-connector connection, including the authorized URI after another entry.
  • Files reviewed: 14/14 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread src/bacnet/datalink/bsc/bsc-datalink.c Outdated
… and revalidation have identical, order-independent behavior. Match while iterating the certificate names or size storage from the SAN extension instead of imposing this undocumented cap.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

An oversized SAN entry prematurely terminates enumeration and can reject a certificate containing a later authorized identity.

Get a fresh assessment by requesting another Copilot review.

Review details
  • Files reviewed: 15/15 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread src/bacnet/datalink/bsc/bsc-socket.c Outdated
…acefully, allowing enumeration to continue without capping.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants