diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/client.c | 7 | ||||
| -rw-r--r-- | src/common.c | 26 | ||||
| -rw-r--r-- | src/common.h | 29 | ||||
| -rw-r--r-- | src/server_lds.c | 2 | ||||
| -rw-r--r-- | src/server_register.c | 22 |
5 files changed, 64 insertions, 22 deletions
diff --git a/src/client.c b/src/client.c index 3d22a4d..f2166a6 100644 --- a/src/client.c +++ b/src/client.c @@ -233,9 +233,12 @@ main (int argc, char **argv) /* ---- Auth config (read-time only) ---- */ const char *username = NULL, *password = NULL; + UA_Boolean certAuth = false; if (op == OP_READ_TIME - && parseAuthConfig (&cfg, "Client", NULL, &username, &password) != 0) + && parseAuthConfig (&cfg, "Client", NULL, &username, &password, + &certAuth) + != 0) { configFree (&cfg); return EXIT_FAILURE; @@ -287,7 +290,7 @@ main (int argc, char **argv) UA_StatusCode retval = createSecureClientConfig ( UA_Client_getConfig (client), applicationUri, certPath, keyPath, - trustPaths, trustSize, secMode, secPolUri); + trustPaths, trustSize, secMode, secPolUri, certAuth); if (retval != UA_STATUSCODE_GOOD) { UA_Client_delete (client); diff --git a/src/common.c b/src/common.c index 67ea135..865fc55 100644 --- a/src/common.c +++ b/src/common.c @@ -174,7 +174,7 @@ parseLogLevel (const char *name) int parseAuthConfig (const Config *cfg, const char *program, UA_Boolean *allowAnonymous, const char **username, - const char **password) + const char **password, UA_Boolean *certAuth) { const char *authMode = configRequire (cfg, "authMode", program); if (!authMode) @@ -182,6 +182,8 @@ parseAuthConfig (const Config *cfg, const char *program, *username = NULL; *password = NULL; + if (certAuth) + *certAuth = false; if (strcmp (authMode, "anonymous") == 0) { @@ -201,8 +203,18 @@ parseAuthConfig (const Config *cfg, const char *program, return 0; } + if (strcmp (authMode, "cert") == 0) + { + if (allowAnonymous) + *allowAnonymous = false; + if (certAuth) + *certAuth = true; + return 0; + } + UA_LOG_FATAL (UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, - "%s: unknown auth mode '%s' (expected 'anonymous' or 'user')", + "%s: unknown auth mode '%s' " + "(expected 'anonymous', 'user', or 'cert')", program, authMode); return -1; } @@ -422,7 +434,7 @@ createSecureClientConfig (UA_ClientConfig *cc, const char *applicationUri, const char *certPath, const char *keyPath, char **trustPaths, size_t trustSize, UA_MessageSecurityMode securityMode, - const char *securityPolicyUri) + const char *securityPolicyUri, UA_Boolean certAuth) { UA_ByteString certificate = loadFile (certPath); UA_ByteString privateKey = loadFile (keyPath); @@ -435,6 +447,14 @@ createSecureClientConfig (UA_ClientConfig *cc, const char *applicationUri, UA_StatusCode retval = UA_ClientConfig_setDefaultEncryption ( cc, certificate, privateKey, trustList, 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) + retval + = UA_ClientConfig_setAuthenticationCert (cc, certificate, privateKey); + 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 a531fc9..aff6ff4 100644 --- a/src/common.h +++ b/src/common.h @@ -91,22 +91,25 @@ int parseLogLevel (const char *name); /** * @brief Parses the authMode key from a configuration file. * - * When authMode is "anonymous", sets *allowAnonymous to true and - * *username / *password to NULL. When authMode is "user", sets - * *allowAnonymous to false and loads the username/password keys. + * When authMode is "anonymous", sets *allowAnonymous to true and leaves + * *username / *password as NULL. When authMode is "user", sets + * *allowAnonymous to false and loads the username/password keys. When + * authMode is "cert", sets *allowAnonymous to false and *certAuth to true. * Logs errors internally. * * @param cfg Parsed configuration. * @param program Program name (for error messages). - * @param allowAnonymous Output: true for anonymous, false for user. + * @param allowAnonymous Output: true for anonymous, false otherwise. * May be NULL (ignored — useful for client callers). * @param username Output: username string (owned by cfg), or NULL. * @param password Output: password string (owned by cfg), or NULL. + * @param certAuth Output: true when authMode is "cert", false otherwise. + * May be NULL (ignored — useful for server callers). * @return 0 on success, -1 on error. */ int parseAuthConfig (const Config *cfg, const char *program, UA_Boolean *allowAnonymous, const char **username, - const char **password); + const char **password, UA_Boolean *certAuth); /** * @brief Parses a security mode name into the corresponding enum value. @@ -149,7 +152,9 @@ UA_StatusCode createUnsecureClientConfig (UA_ClientConfig *cc, * * The config must be zero-initialized by the caller before calling this * function. Loads the certificate, private key, and trustlist, then applies - * default encryption settings. + * default encryption settings. When @p certAuth is true, also configures + * X509 certificate identity-token authentication using the same application + * certificate (mutually exclusive with username/password authentication). * * @param cc Pointer to a zero-initialized UA_ClientConfig. * @param applicationUri OPC UA application URI. @@ -161,12 +166,16 @@ UA_StatusCode createUnsecureClientConfig (UA_ClientConfig *cc, * @param securityMode Requested message security mode. * @param securityPolicyUri Security policy URI string (e.g. * "http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256"). + * @param certAuth When true, use the application certificate as X509 identity + * token. * @return UA_STATUSCODE_GOOD on success, error code otherwise. */ -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_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); /** * @brief Logs a UA_ApplicationDescription (server info from FindServers). diff --git a/src/server_lds.c b/src/server_lds.c index 99c1e8c..3307073 100644 --- a/src/server_lds.c +++ b/src/server_lds.c @@ -99,7 +99,7 @@ main (int argc, char *argv[]) UA_Boolean allowAnonymous; const char *username = NULL, *password = NULL; if (parseAuthConfig (&cfg, "ServerLDS", &allowAnonymous, &username, - &password) + &password, NULL) != 0) { configFree (&cfg); diff --git a/src/server_register.c b/src/server_register.c index 8f23d1c..705fc18 100644 --- a/src/server_register.c +++ b/src/server_register.c @@ -50,6 +50,7 @@ typedef struct int logLevel; const char *username; const char *password; + UA_Boolean certAuth; } LdsClientParams; /** @@ -65,9 +66,9 @@ makeLdsClientConfig (UA_ClientConfig *cc, const LdsClientParams *p) UA_StatusCode rv; if (p->certPath) { - rv = createSecureClientConfig (cc, p->appUri, p->certPath, p->keyPath, - p->trustPaths, p->trustSize, - p->securityMode, p->securityPolicyUri); + rv = createSecureClientConfig ( + cc, p->appUri, p->certPath, p->keyPath, p->trustPaths, p->trustSize, + p->securityMode, p->securityPolicyUri, p->certAuth); } else { @@ -157,7 +158,7 @@ main (int argc, char **argv) UA_Boolean serverAllowAnonymous; const char *serverUsername = NULL, *serverPassword = NULL; if (parseAuthConfig (&serverCfg, "ServerRegister", &serverAllowAnonymous, - &serverUsername, &serverPassword) + &serverUsername, &serverPassword, NULL) != 0) goto cleanup; @@ -230,8 +231,9 @@ main (int argc, char **argv) } const char *clientUsername = NULL, *clientPassword = NULL; + UA_Boolean clientCertAuth = false; if (parseAuthConfig (&clientCfg, "ServerRegister", NULL, &clientUsername, - &clientPassword) + &clientPassword, &clientCertAuth) != 0) goto cleanup; @@ -254,13 +256,20 @@ main (int argc, char **argv) { retval = UA_AccessControl_default (serverConfig, true, NULL, 0, NULL); } - else + else if (serverUsername) { 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); } + else + { + /* cert auth — sessionPKI.verifyCertificate is set by createServer + via setDefaultWithSecureSecurityPolicies, so UA_AccessControl_default + will automatically advertise the X509 certificate token policy. */ + retval = UA_AccessControl_default (serverConfig, false, NULL, 0, NULL); + } if (retval != UA_STATUSCODE_GOOD) goto cleanup; @@ -278,6 +287,7 @@ main (int argc, char **argv) .logLevel = logLevel, .username = clientUsername, .password = clientPassword, + .certAuth = clientCertAuth, }; /* Use run_startup + manual event loop (instead of UA_Server_run) so we |
