aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorThomas Vanbesien <tvanbesi@proton.me>2026-02-18 15:39:29 +0100
committerThomas Vanbesien <tvanbesi@proton.me>2026-02-18 15:39:29 +0100
commit99b5b4416193fafaa815746ea756900d2ab26917 (patch)
tree7d1ab48fcc2e8406df8d2606b691ee9e6911dcd0 /src
parent12989671c9f43707701a8cef8e77e34b1bf24a37 (diff)
downloadBobinkCOpcUa-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.c12
-rw-r--r--src/common.h8
-rw-r--r--src/server_lds.c27
-rw-r--r--src/server_register.c111
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;