From 7a1987c2c18fda1ff7093b53fa70f3de8097c110 Mon Sep 17 00:00:00 2001 From: Julius Pfrommer Date: Wed, 13 Nov 2024 00:16:05 +0100 Subject: [PATCH] feat(tools): The ua-cli tool supports encryption via certificate files --- tools/ua-cli/ua.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/tools/ua-cli/ua.c b/tools/ua-cli/ua.c index 744486a739a..ad6569f9bce 100644 --- a/tools/ua-cli/ua.c +++ b/tools/ua-cli/ua.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -19,6 +20,8 @@ static char *url = NULL; static char *service = NULL; static char *username = NULL; static char *password = NULL; +static UA_ByteString certificate; +static UA_ByteString privateKey; int return_value = 0; /* Custom logger that prints to stderr. So the "good output" can be easily separated. */ @@ -81,11 +84,36 @@ usage(void) { " Options:\n" " --username: Username for the session creation\n" " --password: Password for the session creation\n" - " --loglevel: Logging detail [1 -> TRACE, 6 -> FATAL]\n" + " --certificate : Certificate in DER format\n" + " --privatekey : Private key in DER format\n" + " --loglevel : Logging detail [1 -> TRACE, 6 -> FATAL]\n" " --help: Print this message\n"); exit(EXIT_FAILURE); } +static UA_ByteString +loadFile(const char *const path) { + /* Open the file */ + FILE *fp = fopen(path, "rb"); + if(!fp) { + fprintf(stderr, "Cannot open file %s\n", path); + exit(EXIT_FAILURE); + } + + /* Get the file length, allocate the data and read */ + UA_ByteString fileContents = UA_STRING_NULL; + fseek(fp, 0, SEEK_END); + fileContents.length = (size_t)ftell(fp); + fileContents.data = (UA_Byte *)UA_malloc(fileContents.length * sizeof(UA_Byte)); + fseek(fp, 0, SEEK_SET); + size_t read = fread(fileContents.data, sizeof(UA_Byte), fileContents.length, fp); + if(read == 0) + UA_ByteString_clear(&fileContents); + fclose(fp); + + return fileContents; +} + static void printType(void *p, const UA_DataType *type) { UA_ByteString out = UA_BYTESTRING_NULL; @@ -485,6 +513,22 @@ parseOptions(int argc, char **argv, int argpos) { continue; } + if(strcmp(argv[argpos], "--certificate") == 0) { + argpos++; + if(argpos == argc) + usage(); + certificate = loadFile(argv[argpos]); + continue; + } + + if(strcmp(argv[argpos], "--privatekey") == 0) { + argpos++; + if(argpos == argc) + usage(); + privateKey = loadFile(argv[argpos]); + continue; + } + /* Unknown option */ usage(); } @@ -510,6 +554,18 @@ main(int argc, char **argv) { cc.logging = &stderrLog; UA_ClientConfig_setDefault(&cc); + /* TODO: Trustlist end revocation list */ + if(certificate.length > 0) { + UA_StatusCode res = + UA_ClientConfig_setDefaultEncryption(&cc, certificate, privateKey, + NULL, 0, NULL, 0); + if(res != UA_STATUSCODE_GOOD) + exit(EXIT_FAILURE); + } + + cc.certificateVerification.clear(&cc.certificateVerification); + UA_CertificateGroup_AcceptAll(&cc.certificateVerification); + /* Initialize the client */ client = UA_Client_newWithConfig(&cc); if(!client) { @@ -530,6 +586,9 @@ main(int argc, char **argv) { usage(); /* Unknown service */ } + UA_ByteString_clear(&certificate); + UA_ByteString_clear(&privateKey); + UA_Client_delete(client); return return_value; }