diff options
| author | Thomas Vanbesien <tvanbesi@proton.me> | 2026-02-18 22:01:05 +0100 |
|---|---|---|
| committer | Thomas Vanbesien <tvanbesi@proton.me> | 2026-02-18 22:01:05 +0100 |
| commit | 4a0e0ff8cca00a6e4b4557d468894682d1b91333 (patch) | |
| tree | d5611aa59dfbd2bb5d4ee38bea8f26bb9914977b /src/common.c | |
| parent | deaabd1464784a6fddbfa9e1ac6cb0e1148a8c34 (diff) | |
| download | BobinkCOpcUa-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.c | 150 |
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; } |
