Reputation: 5389
I am trying to create a minimal server using ACS and AES256 certificates.
I've build the certificates using OpenSSL.
Step | Command | Result |
---|---|---|
Server Private Key | openssl genpkey -algorithm RSA -out opcua_server.key -aes256 | Encrypted key |
Server Signing Request | openssl req -new -key opcua_server.key -out request.csr | CSR Request |
Server Certificate with URI | openssl req -new -key decrypted_opcua_server.key -x509 -days 365 -out certificate.pem -subj "/C=IT/ST=Campania/L=Roma/O=Senatus Romanum/CN=Opcua Legionis" -addext "subjectAltName=URI:urn:OPCUASecureServerTest" | PEM Certificate |
Decapsulate to DER | openssl x509 -in certificate.pem -outform der -out certificate.der | DER Certificate |
Certificate Data Display | openssl x509 -in certificate.der -inform der -text -noout | None |
I then attempt to setup the server.
UA_StatusCode myInsecurePasswordCallback(UA_ServerConfig *sc,
UA_ByteString *bytestringPassword) {
char* sec = (char*)"insecure_password";
*bytestringPassword = UA_STRING_ALLOC(sec);
return UA_STATUSCODE_GOOD;
}
void printApplicationUriFromLoadedCertificate(UA_ServerConfig *config) {
UA_Boolean none = false;
printf("Verifying certificates on endpoints...\n");
// Loop through the existing security policies and print certificate info
for(size_t i = 0; i < config->securityPoliciesSize; i++) {
UA_EndpointDescription *endpoint = &config->endpoints[0];
UA_ByteString *certificate = &endpoint->serverCertificate;
printf("*");
if(certificate->length > 0) {
printf("\nLoaded Certificate Application URI: %.*s\n", (int)certificate->length, certificate->data);
none = true;
}
}
if (!none) printf("\nNo certificate loaded.\n");
}
// Custom permissions and roles functions
UA_UInt32 custom_getUserPermissions(const UA_AccessControl *ac, void *sessionContext, const UA_NodeId *nodeId, UA_UInt32 permissions) {
return permissions;
}
static UA_Boolean
allowAddNode(UA_Server *server, UA_AccessControl *ac,
const UA_NodeId *sessionId, void *sessionContext,
const UA_AddNodesItem *item) {
printf("Called allowAddNode\n");
return UA_TRUE;
}
static UA_Boolean
allowAddReference(UA_Server *server, UA_AccessControl *ac,
const UA_NodeId *sessionId, void *sessionContext,
const UA_AddReferencesItem *item) {
printf("Called allowAddReference\n");
return UA_TRUE;
}
static UA_Boolean
allowDeleteNode(UA_Server *server, UA_AccessControl *ac,
const UA_NodeId *sessionId, void *sessionContext,
const UA_DeleteNodesItem *item) {
printf("Called allowDeleteNode\n");
return UA_FALSE; // Do not allow deletion from client
}
static UA_Boolean
allowDeleteReference(UA_Server *server, UA_AccessControl *ac,
const UA_NodeId *sessionId, void *sessionContext,
const UA_DeleteReferencesItem *item) {
printf("Called allowDeleteReference\n");
return UA_TRUE;
}
static UA_UsernamePasswordLogin userNamePW[2] = {
{UA_STRING_STATIC("station-client"), UA_STRING_STATIC("operator1")},
{UA_STRING_STATIC("admin-client"), UA_STRING_STATIC("superSecurePassword1!")}
};
int main() {
signal(SIGINT, stopHandler);
signal(SIGTERM, stopHandler);
UA_String applicationUri = UA_String_fromChars("urn:open62541.OPCUASecureServerTest");
// Hardcoded paths to the certificate and private key files
const char* certificatePath = "./modules/opcua/src/.server_security/certificate.der";
const char* privateKeyPath = "./modules/opcua/src/.server_security/privatekey.der";
// Load server certificates
const UA_ByteString certificate = loadFile(certificatePath);
const UA_ByteString privateKey = loadFile(privateKeyPath);
// Create the server
UA_Server *server = UA_Server_new();
UA_ServerConfig *config = UA_Server_getConfig(server);
// Output the Application URI for debugging
std::cout << "############\n## " << "Application URI: " << std::string((char*)config->applicationDescription.applicationUri.data, applicationUri.length) << "\n############\n" << std::endl;
UA_StatusCode retval;
UA_UInt16 portNumber = 4840;
UA_ByteString trustList[] = { certificate };
size_t trustListSize = sizeof(trustList) / sizeof(UA_ByteString);
const UA_ByteString *issuerList = {};
size_t issuerListSize = 0;
const UA_ByteString *revocationList = {};
size_t revocationListSize = 0;
/// option to start the server without None auth enabled.
retval = UA_ServerConfig_setDefaultWithSecureSecurityPolicies(
config, portNumber,
&certificate, &privateKey,
trustList, trustListSize,
issuerList, issuerListSize,
revocationList, revocationListSize);
config->privateKeyPasswordCallback = myInsecurePasswordCallback;
config->applicationDescription.applicationUri = applicationUri;
config->applicationDescription.applicationName = UA_LOCALIZEDTEXT_ALLOC("en-US", "Secure Monkey Server");
/* Override accessControl functions for nodeManagement */
config->accessControl.allowAddNode = allowAddNode;
config->accessControl.allowAddReference = allowAddReference;
config->accessControl.allowDeleteNode = allowDeleteNode;
config->accessControl.allowDeleteReference = allowDeleteReference;
UA_ServerConfig_addSecurityPolicyBasic256Sha256(config, &certificate, &privateKey);
// Output the Application URI for debugging
std::cout << "Application URI: " << std::string((char*)config->applicationDescription.applicationUri.data, applicationUri.length) << std::endl;
// Print the Application URI from the certificate after it has been loaded
printApplicationUriFromLoadedCertificate(config);
// [AUDITING](https://reference.opcfoundation.org/Core/Part4/v104/docs/6.5)
if(retval != UA_STATUSCODE_GOOD)
goto cleanup;
if(!running)
goto cleanup; // received ctrl-c already
retval = UA_Server_run(server, &running);
cleanup:
UA_ByteString_clear((UA_ByteString*)&certificate);
UA_ByteString_clear((UA_ByteString*)&privateKey);
UA_Server_delete(server);
return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
}
I have edited this slightly for readability.
[2024-09-27 10:05:45.864 (UTC+0200)] warn/server AccessControl: Unconfigured AccessControl. Users have all permissions.
[2024-09-27 10:05:45.865 (UTC+0200)] info/server
AccessControl: Anonymous login is enabled
[2024-09-27 10:05:45.866 (UTC+0200)] warn/server x509 Certificate Authentication configured, but no encrypting SecurityPolicy. This can leak credentials on the network.
############
## Application URI: urn:open62541.server.application²²²
############
[2024-09-27 10:05:46.043 (UTC+0200)] warn/userland ServerUrls already set. Overriding.
[2024-09-27 10:05:46.047 (UTC+0200)] warn/server AccessControl: Unconfigured AccessControl. Users have all permissions.
[2024-09-27 10:05:46.047 (UTC+0200)] warn/server x509 Certificate Authentication configured, but no encrypting SecurityPolicy. This can leak credentials on the network.
Application URI: urn:open62541.OPCUASecureServerTest Verifying certificates on endpoints...
***** No certificate loaded.
[2024-09-27 10:05:46.048 (UTC+0200)] warn/server The certificate's application URI could not be verified. StatusCode BadCertificateUriInvalid
[2024-09-27 10:05:46.048 (UTC+0200)] warn/server The certificate's application URI could not be verified. StatusCode BadCertificateUriInvalid
[2024-09-27 10:05:46.048 (UTC+0200)] warn/server The certificate's application URI could not be verified. StatusCode BadCertificateUtificateUriInvalid
[2024-09-27 10:05:46.048 (UTC+0200)] warn/server The certificate's application URI could not be verified. StatusCode BadCertificateUriInvalid
1- Is my assumption that I should start with a new server, using UA_Server_new
then set it up with default secure policies using the UA_ServerConfig_setDefaultWithSecureSecurityPolicies
method, then rely on UA_ServerConfig_addSecurityPolicyBasic256Sha256
to set the certificate, awfully incorrect? The many warnings seem to suggest I'm doing something wrong.
2- Why is my certificate not working? Did I fail in the creation step, in the import state, or both?
3- Is my ACS correct or not? I used the project example as a source.
Upvotes: 0
Views: 299
Reputation: 1608
I am not sure about other parts of your question, but you certainly also need the hostname(s) or IP address(es) of the server in the subjectAltName. See https://reference.opcfoundation.org/Core/Part6/v104/docs/6.2.2 .
Upvotes: 1