aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client.c7
-rw-r--r--src/common.c26
-rw-r--r--src/common.h29
-rw-r--r--src/server_lds.c2
-rw-r--r--src/server_register.c22
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