aboutsummaryrefslogtreecommitdiffstats
path: root/src/common.c
diff options
context:
space:
mode:
authorThomas Vanbesien <tvanbesi@proton.me>2026-02-18 22:01:05 +0100
committerThomas Vanbesien <tvanbesi@proton.me>2026-02-18 22:01:05 +0100
commit4a0e0ff8cca00a6e4b4557d468894682d1b91333 (patch)
treed5611aa59dfbd2bb5d4ee38bea8f26bb9914977b /src/common.c
parentdeaabd1464784a6fddbfa9e1ac6cb0e1148a8c34 (diff)
downloadBobinkCOpcUa-4a0e0ff8cca00a6e4b4557d468894682d1b91333.tar.gz
BobinkCOpcUa-4a0e0ff8cca00a6e4b4557d468894682d1b91333.zip
Refactor auth and security params into aggregate types
Introduce AuthConfig tagged union (AUTH_ANONYMOUS/AUTH_USER/AUTH_CERT) and SecurityConfig struct to replace scattered parameters. Add parseSecurityConfig helper to consolidate duplicated security parsing across all three programs. Simplify opReadTime by moving all auth handling into the client config factory functions.
Diffstat (limited to 'src/common.c')
-rw-r--r--src/common.c150
1 files changed, 105 insertions, 45 deletions
diff --git a/src/common.c b/src/common.c
index 865fc55..cf364bb 100644
--- a/src/common.c
+++ b/src/common.c
@@ -172,43 +172,33 @@ parseLogLevel (const char *name)
}
int
-parseAuthConfig (const Config *cfg, const char *program,
- UA_Boolean *allowAnonymous, const char **username,
- const char **password, UA_Boolean *certAuth)
+parseAuthConfig (const Config *cfg, const char *program, AuthConfig *auth)
{
const char *authMode = configRequire (cfg, "authMode", program);
if (!authMode)
return -1;
- *username = NULL;
- *password = NULL;
- if (certAuth)
- *certAuth = false;
+ memset (auth, 0, sizeof (*auth));
if (strcmp (authMode, "anonymous") == 0)
{
- if (allowAnonymous)
- *allowAnonymous = true;
+ auth->mode = AUTH_ANONYMOUS;
return 0;
}
if (strcmp (authMode, "user") == 0)
{
- if (allowAnonymous)
- *allowAnonymous = false;
- *username = configRequire (cfg, "username", program);
- *password = configRequire (cfg, "password", program);
- if (!*username || !*password)
+ auth->mode = AUTH_USER;
+ auth->user.username = configRequire (cfg, "username", program);
+ auth->user.password = configRequire (cfg, "password", program);
+ if (!auth->user.username || !auth->user.password)
return -1;
return 0;
}
if (strcmp (authMode, "cert") == 0)
{
- if (allowAnonymous)
- *allowAnonymous = false;
- if (certAuth)
- *certAuth = true;
+ auth->mode = AUTH_CERT;
return 0;
}
@@ -219,6 +209,63 @@ parseAuthConfig (const Config *cfg, const char *program,
return -1;
}
+int
+parseSecurityConfig (const Config *cfg, const char *program,
+ UA_Boolean needsModePolicy, SecurityConfig *sec)
+{
+ memset (sec, 0, sizeof (*sec));
+
+ const char *certPath = configGet (cfg, "certificate");
+ const char *keyPath = configGet (cfg, "privateKey");
+ const char *trustStore = configGet (cfg, "trustStore");
+ UA_Boolean secure
+ = (certPath != NULL || keyPath != NULL || trustStore != NULL);
+
+ if (!secure)
+ return 0;
+
+ if (!certPath || !keyPath || !trustStore)
+ {
+ UA_LOG_FATAL (UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
+ "%s: incomplete security config: certificate, privateKey, "
+ "and trustStore must all be set, or all omitted",
+ program);
+ return -1;
+ }
+
+ sec->certPath = certPath;
+ sec->keyPath = keyPath;
+
+ if (needsModePolicy)
+ {
+ const char *secModeStr = configRequire (cfg, "securityMode", program);
+ const char *secPolStr = configRequire (cfg, "securityPolicy", program);
+ if (!secModeStr || !secPolStr)
+ return -1;
+
+ sec->securityMode = parseSecurityMode (secModeStr);
+ if (sec->securityMode == UA_MESSAGESECURITYMODE_INVALID)
+ {
+ UA_LOG_FATAL (UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
+ "%s: unknown security mode: %s", program, secModeStr);
+ return -1;
+ }
+
+ sec->securityPolicyUri = resolveSecurityPolicyUri (secPolStr);
+ if (!sec->securityPolicyUri)
+ {
+ UA_LOG_FATAL (UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
+ "%s: unknown security policy: %s", program, secPolStr);
+ return -1;
+ }
+ }
+
+ if (loadTrustStore (trustStore, &sec->trustPaths, &sec->trustSize) != 0)
+ return -1;
+
+ return 0;
+}
+
UA_MessageSecurityMode
parseSecurityMode (const char *name)
{
@@ -351,26 +398,26 @@ printEndpoint (const UA_EndpointDescription *endpoint, size_t index)
* ======================================================================== */
UA_Server *
-createServer (UA_UInt16 port, const char *applicationUri, const char *certPath,
- const char *keyPath, char **trustPaths, size_t trustSize,
- UA_Boolean discovery, UA_StatusCode *retval)
+createServer (UA_UInt16 port, const char *applicationUri,
+ const SecurityConfig *sec, UA_Boolean discovery,
+ UA_StatusCode *retval)
{
UA_Server *server = UA_Server_new ();
UA_ServerConfig *config = UA_Server_getConfig (server);
- if (certPath)
+ if (sec && sec->certPath)
{
- UA_ByteString certificate = loadFile (certPath);
- UA_ByteString privateKey = loadFile (keyPath);
+ UA_ByteString certificate = loadFile (sec->certPath);
+ UA_ByteString privateKey = loadFile (sec->keyPath);
/* +1: UA_STACKARRAY requires a strictly positive size for VLA. */
- UA_STACKARRAY (UA_ByteString, trustList, trustSize + 1);
- for (size_t i = 0; i < trustSize; i++)
- trustList[i] = loadFile (trustPaths[i]);
+ UA_STACKARRAY (UA_ByteString, trustList, sec->trustSize + 1);
+ for (size_t i = 0; i < sec->trustSize; i++)
+ trustList[i] = loadFile (sec->trustPaths[i]);
*retval = UA_ServerConfig_setDefaultWithSecureSecurityPolicies (
- config, port, &certificate, &privateKey, trustList, trustSize, NULL,
- 0, NULL, 0);
+ config, port, &certificate, &privateKey, trustList, sec->trustSize,
+ NULL, 0, NULL, 0);
/* When discovery is true (LDS) add SecurityPolicy#None
restricted to discovery services so that unencrypted clients
@@ -390,7 +437,7 @@ createServer (UA_UInt16 port, const char *applicationUri, const char *certPath,
UA_ByteString_clear (&certificate);
UA_ByteString_clear (&privateKey);
- for (size_t i = 0; i < trustSize; i++)
+ for (size_t i = 0; i < sec->trustSize; i++)
UA_ByteString_clear (&trustList[i]);
}
else
@@ -412,8 +459,16 @@ createServer (UA_UInt16 port, const char *applicationUri, const char *certPath,
}
UA_StatusCode
-createUnsecureClientConfig (UA_ClientConfig *cc, const char *applicationUri)
+createUnsecureClientConfig (UA_ClientConfig *cc, const char *applicationUri,
+ const AuthConfig *auth)
{
+ if (auth && auth->mode == AUTH_CERT)
+ {
+ UA_LOG_ERROR (UA_Log_Stdout, UA_LOGCATEGORY_APPLICATION,
+ "Certificate authentication requires encryption");
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+
UA_StatusCode retval = UA_ClientConfig_setDefault (cc);
if (retval != UA_STATUSCODE_GOOD)
return retval;
@@ -426,38 +481,39 @@ createUnsecureClientConfig (UA_ClientConfig *cc, const char *applicationUri)
cc->securityPolicyUri = UA_String_fromChars (
"http://opcfoundation.org/UA/SecurityPolicy#None");
+ if (auth && auth->mode == AUTH_USER)
+ UA_ClientConfig_setAuthenticationUsername (cc, auth->user.username,
+ auth->user.password);
+
return UA_STATUSCODE_GOOD;
}
UA_StatusCode
createSecureClientConfig (UA_ClientConfig *cc, const char *applicationUri,
- const char *certPath, const char *keyPath,
- char **trustPaths, size_t trustSize,
- UA_MessageSecurityMode securityMode,
- const char *securityPolicyUri, UA_Boolean certAuth)
+ const SecurityConfig *sec, const AuthConfig *auth)
{
- UA_ByteString certificate = loadFile (certPath);
- UA_ByteString privateKey = loadFile (keyPath);
+ UA_ByteString certificate = loadFile (sec->certPath);
+ UA_ByteString privateKey = loadFile (sec->keyPath);
/* +1: UA_STACKARRAY requires a strictly positive size for VLA. */
- UA_STACKARRAY (UA_ByteString, trustList, trustSize + 1);
- for (size_t i = 0; i < trustSize; i++)
- trustList[i] = loadFile (trustPaths[i]);
+ UA_STACKARRAY (UA_ByteString, trustList, sec->trustSize + 1);
+ for (size_t i = 0; i < sec->trustSize; i++)
+ trustList[i] = loadFile (sec->trustPaths[i]);
UA_StatusCode retval = UA_ClientConfig_setDefaultEncryption (
- cc, certificate, privateKey, trustList, trustSize, NULL, 0);
+ cc, certificate, privateKey, trustList, sec->trustSize, NULL, 0);
/* X509 identity token: reuse the application certificate. open62541
requires that the identity cert matches the SecureChannel cert, so
a separate user cert cannot be used. Call before clearing the local
buffers since setAuthenticationCert makes its own copy. */
- if (retval == UA_STATUSCODE_GOOD && certAuth)
+ if (retval == UA_STATUSCODE_GOOD && auth && auth->mode == AUTH_CERT)
retval
= UA_ClientConfig_setAuthenticationCert (cc, certificate, privateKey);
UA_ByteString_clear (&certificate);
UA_ByteString_clear (&privateKey);
- for (size_t i = 0; i < trustSize; i++)
+ for (size_t i = 0; i < sec->trustSize; i++)
UA_ByteString_clear (&trustList[i]);
if (retval != UA_STATUSCODE_GOOD)
@@ -471,8 +527,12 @@ createSecureClientConfig (UA_ClientConfig *cc, const char *applicationUri,
UA_String_clear (&cc->clientDescription.applicationUri);
cc->clientDescription.applicationUri = UA_String_fromChars (applicationUri);
- cc->securityMode = securityMode;
- cc->securityPolicyUri = UA_String_fromChars (securityPolicyUri);
+ cc->securityMode = sec->securityMode;
+ cc->securityPolicyUri = UA_String_fromChars (sec->securityPolicyUri);
+
+ if (auth && auth->mode == AUTH_USER)
+ UA_ClientConfig_setAuthenticationUsername (cc, auth->user.username,
+ auth->user.password);
return retval;
}