diff options
| author | Thomas Vanbesien <tvanbesi@proton.me> | 2026-02-18 15:39:29 +0100 |
|---|---|---|
| committer | Thomas Vanbesien <tvanbesi@proton.me> | 2026-02-18 15:39:29 +0100 |
| commit | 99b5b4416193fafaa815746ea756900d2ab26917 (patch) | |
| tree | 7d1ab48fcc2e8406df8d2606b691ee9e6911dcd0 /src | |
| parent | 12989671c9f43707701a8cef8e77e34b1bf24a37 (diff) | |
| download | BobinkCOpcUa-99b5b4416193fafaa815746ea756900d2ab26917.tar.gz BobinkCOpcUa-99b5b4416193fafaa815746ea756900d2ab26917.zip | |
Make client/server encryption optional, rename tests to full names
Make encryption optional for both ServerRegister's LDS client
connection and the server side of ServerLDS/ServerRegister: when
certificate, privateKey, and trustStore are omitted the programs
run with SecurityPolicy#None only. Secure servers also add a
discovery-only None endpoint so unencrypted clients can still call
FindServers and GetEndpoints.
Consolidate tests from 5 policy-specific cases (nosec_anon,
none_user, basic256sha256_anon, aes256_anon, aes128_user) down to
3 that cover the important axes: unsecure_anonymous,
secure_anonymous, secure_user. Rename directories to use full
names. Auto-generate certificates and trust stores in run_test.sh.
Update readme and CLAUDE.md to reflect the current program
interface (unified Client binary, split ServerRegister configs)
and the new test names.
Diffstat (limited to 'src')
| -rw-r--r-- | src/common.c | 12 | ||||
| -rw-r--r-- | src/common.h | 8 | ||||
| -rw-r--r-- | src/server_lds.c | 27 | ||||
| -rw-r--r-- | src/server_register.c | 111 |
4 files changed, 104 insertions, 54 deletions
diff --git a/src/common.c b/src/common.c index 39a2a68..f8b08a1 100644 --- a/src/common.c +++ b/src/common.c @@ -356,10 +356,20 @@ createServer (UA_UInt16 port, const char *applicationUri, const char *certPath, for (size_t i = 0; i < trustSize; i++) trustList[i] = loadFile (trustPaths[i]); - *retval = UA_ServerConfig_setDefaultWithSecurityPolicies ( + *retval = UA_ServerConfig_setDefaultWithSecureSecurityPolicies ( config, port, &certificate, &privateKey, trustList, trustSize, NULL, 0, NULL, 0); + /* Also offer SecurityPolicy#None, but restricted to discovery + services (FindServers, GetEndpoints) so that unencrypted clients + can still discover the server without being able to open a + full session. */ + if (*retval == UA_STATUSCODE_GOOD) + { + UA_ServerConfig_addSecurityPolicyNone (config, &certificate); + config->securityPolicyNoneDiscoveryOnly = true; + } + UA_ByteString_clear (&certificate); UA_ByteString_clear (&privateKey); for (size_t i = 0; i < trustSize; i++) diff --git a/src/common.h b/src/common.h index b4bd323..6d5294a 100644 --- a/src/common.h +++ b/src/common.h @@ -52,9 +52,11 @@ void freeTrustStore (char **paths, size_t size); * @brief Creates a UA_Server, optionally configured with security policies. * * When @p certPath is non-NULL the server is initialized with encryption - * (certificate, private key, trustlist). When @p certPath is NULL the server - * runs with SecurityPolicy#None only (keyPath and trustPaths are ignored). - * The applicationUri is set in both cases. + * (certificate, private key, trustlist) and also adds SecurityPolicy#None + * restricted to discovery services (FindServers, GetEndpoints) so that + * unencrypted clients can still discover the server. When @p certPath is + * NULL the server runs with SecurityPolicy#None only (keyPath and trustPaths + * are ignored). The applicationUri is set in both cases. * * @param port Server port number. * @param applicationUri OPC UA application URI. diff --git a/src/server_lds.c b/src/server_lds.c index f1efa99..14c26b7 100644 --- a/src/server_lds.c +++ b/src/server_lds.c @@ -132,23 +132,26 @@ main (int argc, char *argv[]) Downgrade to a warning so third-party servers can still register. */ serverConfig->verifyRequestTimestamp = UA_RULEHANDLING_WARN; - /* Configure access control after server creation because both - UA_ServerConfig_setDefaultWithSecurityPolicies and - UA_ServerConfig_setMinimal reset the access control plugin. The - credential list is deep-copied by UA_AccessControl_default. */ - if (!allowAnonymous) + /* Configure access control. UA_ServerConfig_setDefaultWithSecure- + SecurityPolicies sets certificate-only auth by default, so we must + always call UA_AccessControl_default to get the desired policy. */ + if (allowAnonymous) + { + retval = UA_AccessControl_default (serverConfig, true, NULL, 0, NULL); + } + else { UA_UsernamePasswordLogin logins[1]; logins[0].username = UA_STRING ((char *)username); logins[0].password = UA_STRING ((char *)password); retval = UA_AccessControl_default (serverConfig, false, NULL, 1, logins); - if (retval != UA_STATUSCODE_GOOD) - { - UA_Server_delete (server); - freeTrustStore (trustPaths, trustSize); - configFree (&cfg); - return EXIT_FAILURE; - } + } + if (retval != UA_STATUSCODE_GOOD) + { + UA_Server_delete (server); + freeTrustStore (trustPaths, trustSize); + configFree (&cfg); + return EXIT_FAILURE; } /* Mark this server as a Discovery Server so clients can identify it. */ diff --git a/src/server_register.c b/src/server_register.c index ec5045f..817169f 100644 --- a/src/server_register.c +++ b/src/server_register.c @@ -62,9 +62,23 @@ static UA_StatusCode makeLdsClientConfig (UA_ClientConfig *cc, const LdsClientParams *p) { memset (cc, 0, sizeof (UA_ClientConfig)); - UA_StatusCode rv = createSecureClientConfig ( - cc, p->appUri, p->certPath, p->keyPath, p->trustPaths, p->trustSize, - p->securityMode, p->securityPolicyUri); + UA_StatusCode rv; + if (p->certPath) + { + rv = createSecureClientConfig (cc, p->appUri, p->certPath, p->keyPath, + p->trustPaths, p->trustSize, + p->securityMode, p->securityPolicyUri); + } + else + { + rv = UA_ClientConfig_setDefault (cc); + if (rv == UA_STATUSCODE_GOOD) + { + UA_String_clear (&cc->clientDescription.applicationUri); + cc->clientDescription.applicationUri + = UA_String_fromChars (p->appUri); + } + } if (rv != UA_STATUSCODE_GOOD) return rv; cc->logging->context = (void *)(uintptr_t)p->logLevel; @@ -165,33 +179,60 @@ main (int argc, char **argv) const char *clientAppUri = configRequire (&clientCfg, "applicationUri", "ServerRegister"); - const char *clientCertPath - = configRequire (&clientCfg, "certificate", "ServerRegister"); - const char *clientKeyPath - = configRequire (&clientCfg, "privateKey", "ServerRegister"); - const char *securityModeStr - = configRequire (&clientCfg, "securityMode", "ServerRegister"); - const char *securityPolicyStr - = configRequire (&clientCfg, "securityPolicy", "ServerRegister"); - - if (!clientAppUri || !clientCertPath || !clientKeyPath || !securityModeStr - || !securityPolicyStr) + if (!clientAppUri) goto cleanup; - UA_MessageSecurityMode securityMode = parseSecurityMode (securityModeStr); - if (securityMode == UA_MESSAGESECURITYMODE_INVALID) + /* Security configuration (optional). When certificate, privateKey, and + trustStore are all omitted the client connects without encryption. + When any of the three is present, all three are required. */ + const char *clientCertPath = configGet (&clientCfg, "certificate"); + const char *clientKeyPath = configGet (&clientCfg, "privateKey"); + const char *clientTrustStore = configGet (&clientCfg, "trustStore"); + UA_Boolean clientSecure = (clientCertPath != NULL || clientKeyPath != NULL + || clientTrustStore != NULL); + + if (clientSecure && (!clientCertPath || !clientKeyPath || !clientTrustStore)) { UA_LOG_FATAL (UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, - "Unknown security mode: %s", securityModeStr); + "Incomplete client security config: certificate, " + "privateKey, and trustStore must all be set, or all " + "omitted"); goto cleanup; } - const char *securityPolicyUri = resolveSecurityPolicyUri (securityPolicyStr); - if (!securityPolicyUri) + UA_MessageSecurityMode securityMode = UA_MESSAGESECURITYMODE_NONE; + const char *securityPolicyUri + = "http://opcfoundation.org/UA/SecurityPolicy#None"; + + if (clientSecure) { - UA_LOG_FATAL (UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, - "Unknown security policy: %s", securityPolicyStr); - goto cleanup; + const char *securityModeStr + = configRequire (&clientCfg, "securityMode", "ServerRegister"); + const char *securityPolicyStr + = configRequire (&clientCfg, "securityPolicy", "ServerRegister"); + if (!securityModeStr || !securityPolicyStr) + goto cleanup; + + securityMode = parseSecurityMode (securityModeStr); + if (securityMode == UA_MESSAGESECURITYMODE_INVALID) + { + UA_LOG_FATAL (UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, + "Unknown security mode: %s", securityModeStr); + goto cleanup; + } + + securityPolicyUri = resolveSecurityPolicyUri (securityPolicyStr); + if (!securityPolicyUri) + { + UA_LOG_FATAL (UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, + "Unknown security policy: %s", securityPolicyStr); + goto cleanup; + } + + if (loadTrustStore (clientTrustStore, &clientTrustPaths, + &clientTrustSize) + != 0) + goto cleanup; } const char *clientUsername = NULL, *clientPassword = NULL; @@ -200,15 +241,6 @@ main (int argc, char **argv) != 0) goto cleanup; - const char *clientTrustStore - = configRequire (&clientCfg, "trustStore", "ServerRegister"); - if (!clientTrustStore) - goto cleanup; - - if (loadTrustStore (clientTrustStore, &clientTrustPaths, &clientTrustSize) - != 0) - goto cleanup; - /* ── Create and configure server ────────────────────────────── */ UA_StatusCode retval; @@ -221,19 +253,22 @@ main (int argc, char **argv) UA_ServerConfig *serverConfig = UA_Server_getConfig (server); serverConfig->logging->context = (void *)(uintptr_t)logLevel; - /* Configure access control after server creation because both - UA_ServerConfig_setDefaultWithSecurityPolicies and - UA_ServerConfig_setMinimal reset the access control plugin. The - credential list is deep-copied by UA_AccessControl_default. */ - if (!serverAllowAnonymous) + /* Configure access control. UA_ServerConfig_setDefaultWithSecure- + SecurityPolicies sets certificate-only auth by default, so we must + always call UA_AccessControl_default to get the desired policy. */ + if (serverAllowAnonymous) + { + retval = UA_AccessControl_default (serverConfig, true, NULL, 0, NULL); + } + else { UA_UsernamePasswordLogin logins[1]; logins[0].username = UA_STRING ((char *)serverUsername); logins[0].password = UA_STRING ((char *)serverPassword); retval = UA_AccessControl_default (serverConfig, false, NULL, 1, logins); - if (retval != UA_STATUSCODE_GOOD) - goto cleanup; } + if (retval != UA_STATUSCODE_GOOD) + goto cleanup; serverConfig->applicationDescription.applicationType = UA_APPLICATIONTYPE_SERVER; |
