From 4a0e0ff8cca00a6e4b4557d468894682d1b91333 Mon Sep 17 00:00:00 2001 From: Thomas Vanbesien Date: Wed, 18 Feb 2026 22:01:05 +0100 Subject: 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. --- src/common.c | 150 +++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 105 insertions(+), 45 deletions(-) (limited to 'src/common.c') 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; } -- cgit v1.2.3