Преглед изворни кода

WIP: Separate SecurityPolicies from Endpoints in the server (#2247)

* WIP: Separate SecurityPolicies from Endpoints in the server

Currently the SecurityPolicies supported by the server are strongly
tied together with the endpoints. To be able to reuse the
SecurityPolicy instances of the server also in the Access Control
plugin to handle encrypted passwords the SecurityPolicies are moved
to the server config struct.
Jonas Green пре 5 година
родитељ
комит
1a40bb1fe1

+ 8 - 5
include/ua_plugin_securitypolicy.h

@@ -366,11 +366,6 @@ struct UA_SecurityPolicy {
     void (*deleteMembers)(UA_SecurityPolicy *policy);
 };
 
-typedef struct {
-    UA_SecurityPolicy securityPolicy;
-    UA_EndpointDescription endpointDescription;
-} UA_Endpoint;
-
 /* Gets the number of bytes that are needed by the encryption function in
  * addition to the length of the plaintext message. This is needed, since
  * most RSA encryption methods have their own padding mechanism included.
@@ -386,6 +381,14 @@ UA_SecurityPolicy_getRemoteAsymEncryptionBufferLengthOverhead(const UA_SecurityP
                                                               const void *channelContext,
                                                               size_t maxEncryptionLength);
 
+/* Gets the a pointer to the context of a security policy supported by the
+ * server matched by the security policy uri.
+ *
+ * @param server the server context.
+ * @param securityPolicyUri the security policy to get the context of. */
+UA_SecurityPolicy *
+UA_SecurityPolicy_getSecurityPolicyByUri(const UA_Server *server,
+                                         UA_ByteString *securityPolicyUri);
 
 typedef UA_StatusCode
 (*UA_SecurityPolicy_Func)(UA_SecurityPolicy *policy,

+ 5 - 1
include/ua_server_config.h

@@ -100,9 +100,13 @@ struct UA_ServerConfig {
     UA_PubSubTransportLayer *pubsubTransportLayers;
 #endif
 
+    /* Available security policies */
+    size_t securityPoliciesSize;
+    UA_SecurityPolicy* securityPolicies;
+
     /* Available endpoints */
     size_t endpointsSize;
-    UA_Endpoint *endpoints;
+    UA_EndpointDescription *endpoints;
 
     /* Node Lifecycle callbacks */
     UA_GlobalNodeLifecycle nodeLifecycle;

+ 2 - 2
plugins/securityPolicies/ua_securitypolicy_basic128rsa15.c

@@ -1,6 +1,6 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. 
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  *
  *    Copyright 2018 (c) Mark Giraud, Fraunhofer IOSB
  */
@@ -927,7 +927,7 @@ UA_SecurityPolicy_Basic128Rsa15(UA_SecurityPolicy *policy,
 
     UA_SecurityPolicyEncryptionAlgorithm *asym_encryptionAlgorithm =
         &asymmetricModule->cryptoModule.encryptionAlgorithm;
-    asym_encryptionAlgorithm->uri = UA_STRING("TODO: ALG URI");
+    asym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-1_5");
     asym_encryptionAlgorithm->encrypt =
         (UA_StatusCode(*)(const UA_SecurityPolicy *, void *, UA_ByteString *))asym_encrypt_sp_basic128rsa15;
     asym_encryptionAlgorithm->decrypt =

+ 170 - 134
plugins/ua_config_default.c

@@ -62,30 +62,29 @@ const UA_ConnectionConfig UA_ConnectionConfig_default = {
     STRINGIFY(MAJOR) "." STRINGIFY(MINOR) "." STRINGIFY(PATCH) LABEL
 
 static UA_StatusCode
-createSecurityPolicyNoneEndpoint(UA_ServerConfig *conf, UA_Endpoint *endpoint,
-                                 const UA_ByteString localCertificate) {
-    UA_EndpointDescription_init(&endpoint->endpointDescription);
-
-    UA_SecurityPolicy_None(&endpoint->securityPolicy, NULL, localCertificate, &conf->logger);
-    endpoint->endpointDescription.securityMode = UA_MESSAGESECURITYMODE_NONE;
-    endpoint->endpointDescription.securityPolicyUri =
-        UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#None");
-    endpoint->endpointDescription.transportProfileUri =
+createEndpoint(UA_ServerConfig *conf, UA_EndpointDescription *endpoint,
+               const UA_SecurityPolicy *securityPolicy,
+               UA_MessageSecurityMode securityMode) {
+    UA_EndpointDescription_init(endpoint);
+
+    endpoint->securityMode = securityMode;
+    UA_String_copy(&securityPolicy->policyUri, &endpoint->securityPolicyUri);
+    endpoint->transportProfileUri =
         UA_STRING_ALLOC("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary");
 
     /* Enable all login mechanisms from the access control plugin  */
     UA_StatusCode retval = UA_Array_copy(conf->accessControl.userTokenPolicies,
                                          conf->accessControl.userTokenPoliciesSize,
-                                         (void **)&endpoint->endpointDescription.userIdentityTokens,
+                                         (void **)&endpoint->userIdentityTokens,
                                          &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
     if(retval != UA_STATUSCODE_GOOD)
         return retval;
-    endpoint->endpointDescription.userIdentityTokensSize =
+    endpoint->userIdentityTokensSize =
         conf->accessControl.userTokenPoliciesSize;
 
-    UA_String_copy(&localCertificate, &endpoint->endpointDescription.serverCertificate);
+    UA_String_copy(&securityPolicy->localCertificate, &endpoint->serverCertificate);
     UA_ApplicationDescription_copy(&conf->applicationDescription,
-                                   &endpoint->endpointDescription.server);
+                                   &endpoint->server);
 
     return UA_STATUSCODE_GOOD;
 }
@@ -98,89 +97,6 @@ UA_ServerConfig_set_customHostname(UA_ServerConfig *config, const UA_String cust
     UA_String_copy(&customHostname, &config->customHostname);
 }
 
-#ifdef UA_ENABLE_ENCRYPTION
-
-static UA_StatusCode
-createSecurityPolicyBasic128Rsa15Endpoint(UA_ServerConfig *const conf,
-                                          UA_Endpoint *endpoint,
-                                          UA_MessageSecurityMode securityMode,
-                                          const UA_ByteString localCertificate,
-                                          const UA_ByteString localPrivateKey) {
-    UA_EndpointDescription_init(&endpoint->endpointDescription);
-
-    UA_StatusCode retval =
-        UA_SecurityPolicy_Basic128Rsa15(&endpoint->securityPolicy, &conf->certificateVerification,
-                                        localCertificate, localPrivateKey, &conf->logger);
-    if(retval != UA_STATUSCODE_GOOD) {
-        endpoint->securityPolicy.deleteMembers(&endpoint->securityPolicy);
-        return retval;
-    }
-
-    endpoint->endpointDescription.securityMode = securityMode;
-    endpoint->endpointDescription.securityPolicyUri =
-        UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15");
-    endpoint->endpointDescription.transportProfileUri =
-        UA_STRING_ALLOC("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary");
-
-    /* Enable all login mechanisms from the access control plugin  */
-    retval = UA_Array_copy(conf->accessControl.userTokenPolicies,
-                           conf->accessControl.userTokenPoliciesSize,
-                           (void **)&endpoint->endpointDescription.userIdentityTokens,
-                           &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
-    if(retval != UA_STATUSCODE_GOOD)
-        return retval;
-    endpoint->endpointDescription.userIdentityTokensSize =
-        conf->accessControl.userTokenPoliciesSize;
-
-    UA_String_copy(&localCertificate, &endpoint->endpointDescription.serverCertificate);
-    UA_ApplicationDescription_copy(&conf->applicationDescription,
-                                   &endpoint->endpointDescription.server);
-
-    return UA_STATUSCODE_GOOD;
-}
-
-static UA_StatusCode
-createSecurityPolicyBasic256Sha256Endpoint(UA_ServerConfig *const conf,
-                                           UA_Endpoint *endpoint,
-                                           UA_MessageSecurityMode securityMode,
-                                           const UA_ByteString localCertificate,
-                                           const UA_ByteString localPrivateKey) {
-    UA_EndpointDescription_init(&endpoint->endpointDescription);
-
-    UA_StatusCode retval =
-        UA_SecurityPolicy_Basic256Sha256(&endpoint->securityPolicy,
-                                         &conf->certificateVerification, localCertificate,
-                                         localPrivateKey, &conf->logger);
-    if(retval != UA_STATUSCODE_GOOD) {
-        endpoint->securityPolicy.deleteMembers(&endpoint->securityPolicy);
-        return retval;
-    }
-
-    endpoint->endpointDescription.securityMode = securityMode;
-    endpoint->endpointDescription.securityPolicyUri =
-        UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256");
-    endpoint->endpointDescription.transportProfileUri =
-        UA_STRING_ALLOC("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary");
-
-    /* Enable all login mechanisms from the access control plugin  */
-    retval = UA_Array_copy(conf->accessControl.userTokenPolicies,
-                           conf->accessControl.userTokenPoliciesSize,
-                           (void **)&endpoint->endpointDescription.userIdentityTokens,
-                           &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
-    if(retval != UA_STATUSCODE_GOOD)
-        return retval;
-    endpoint->endpointDescription.userIdentityTokensSize =
-        conf->accessControl.userTokenPoliciesSize;
-
-    UA_String_copy(&localCertificate, &endpoint->endpointDescription.serverCertificate);
-    UA_ApplicationDescription_copy(&conf->applicationDescription,
-                                   &endpoint->endpointDescription.server);
-
-    return UA_STATUSCODE_GOOD;
-}
-
-#endif
-
 const size_t usernamePasswordsSize = 2;
 UA_UsernamePasswordLogin usernamePasswords[2] = {
     {UA_STRING_STATIC("user1"), UA_STRING_STATIC("password")},
@@ -353,8 +269,27 @@ UA_ServerConfig_new_customBuffer(UA_UInt16 portNumber,
         return NULL;
     }
 
+    /* Allocate the SecurityPolicies */
+    conf->securityPoliciesSize = 1;
+    conf->securityPolicies = (UA_SecurityPolicy *)UA_malloc(sizeof(UA_SecurityPolicy));
+    if(!conf->securityPolicies) {
+       UA_ServerConfig_delete(conf);
+       return NULL;
+    }
+
+    /* Populate the SecurityPolicies */
+    UA_ByteString localCertificate = UA_BYTESTRING_NULL;
+    if(certificate)
+        localCertificate = *certificate;
+    retval =
+        UA_SecurityPolicy_None(&conf->securityPolicies[0], NULL, localCertificate, &conf->logger);
+    if(retval != UA_STATUSCODE_GOOD) {
+        UA_ServerConfig_delete(conf);
+        return NULL;
+    }
+
     /* Allocate the endpoint */
-    conf->endpoints = (UA_Endpoint *)UA_malloc(sizeof(UA_Endpoint));
+    conf->endpoints = (UA_EndpointDescription *)UA_malloc(sizeof(UA_EndpointDescription));
     if(!conf->endpoints) {
         UA_ServerConfig_delete(conf);
         return NULL;
@@ -362,11 +297,9 @@ UA_ServerConfig_new_customBuffer(UA_UInt16 portNumber,
     conf->endpointsSize = 1;
 
     /* Populate the endpoint */
-    UA_ByteString localCertificate = UA_BYTESTRING_NULL;
-    if(certificate)
-        localCertificate = *certificate;
     retval =
-        createSecurityPolicyNoneEndpoint(conf, &conf->endpoints[0], localCertificate);
+        createEndpoint(conf, &conf->endpoints[0], &conf->securityPolicies[0],
+                       UA_MESSAGESECURITYMODE_NONE);
     if(retval != UA_STATUSCODE_GOOD) {
         UA_ServerConfig_delete(conf);
         return NULL;
@@ -410,9 +343,41 @@ UA_ServerConfig_new_basic128rsa15(UA_UInt16 portNumber,
         UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
                        "No CA trust-list provided. Any remote certificate will be accepted.");
 
+    /* Allocate the SecurityPolicies */
+    conf->securityPoliciesSize = 0;
+    conf->securityPolicies = (UA_SecurityPolicy *)UA_malloc(sizeof(UA_SecurityPolicy) * 2);
+    if(!conf->securityPolicies) {
+       UA_ServerConfig_delete(conf);
+       return NULL;
+    }
+
+    /* Populate the SecurityPolicies */
+    UA_ByteString localCertificate = UA_BYTESTRING_NULL;
+    UA_ByteString localPrivateKey  = UA_BYTESTRING_NULL;
+    if(certificate)
+        localCertificate = *certificate;
+    if(privateKey)
+       localPrivateKey = *privateKey;
+
+    ++conf->securityPoliciesSize;
+    retval =
+        UA_SecurityPolicy_None(&conf->securityPolicies[0], NULL, localCertificate, &conf->logger);
+    if(retval != UA_STATUSCODE_GOOD) {
+        UA_ServerConfig_delete(conf);
+        return NULL;
+    }
+    ++conf->securityPoliciesSize;
+    retval =
+        UA_SecurityPolicy_Basic128Rsa15(&conf->securityPolicies[1], &conf->certificateVerification,
+                                        localCertificate, localPrivateKey, &conf->logger);
+    if(retval != UA_STATUSCODE_GOOD) {
+        UA_ServerConfig_delete(conf);
+        return NULL;
+    }
+
     /* Allocate the endpoints */
     conf->endpointsSize = 0;
-    conf->endpoints = (UA_Endpoint *)UA_malloc(sizeof(UA_Endpoint) * 3);
+    conf->endpoints = (UA_EndpointDescription *)UA_malloc(sizeof(UA_EndpointDescription) * 3);
     if(!conf->endpoints) {
         UA_ServerConfig_delete(conf);
         return NULL;
@@ -420,25 +385,24 @@ UA_ServerConfig_new_basic128rsa15(UA_UInt16 portNumber,
 
     /* Populate the endpoints */
     ++conf->endpointsSize;
-    retval = createSecurityPolicyNoneEndpoint(conf, &conf->endpoints[0], *certificate);
+    retval = createEndpoint(conf, &conf->endpoints[0], &conf->securityPolicies[0],
+                            UA_MESSAGESECURITYMODE_NONE);
     if(retval != UA_STATUSCODE_GOOD) {
         UA_ServerConfig_delete(conf);
         return NULL;
     }
 
     ++conf->endpointsSize;
-    retval = createSecurityPolicyBasic128Rsa15Endpoint(conf, &conf->endpoints[1],
-                                                       UA_MESSAGESECURITYMODE_SIGN, *certificate,
-                                                       *privateKey);
+    retval = createEndpoint(conf, &conf->endpoints[1], &conf->securityPolicies[1],
+                            UA_MESSAGESECURITYMODE_SIGN);
     if(retval != UA_STATUSCODE_GOOD) {
         UA_ServerConfig_delete(conf);
         return NULL;
     }
 
     ++conf->endpointsSize;
-    retval = createSecurityPolicyBasic128Rsa15Endpoint(conf, &conf->endpoints[2],
-                                                       UA_MESSAGESECURITYMODE_SIGNANDENCRYPT, *certificate,
-                                                       *privateKey);
+    retval = createEndpoint(conf, &conf->endpoints[2], &conf->securityPolicies[1],
+                            UA_MESSAGESECURITYMODE_SIGNANDENCRYPT);
     if(retval != UA_STATUSCODE_GOOD) {
         UA_ServerConfig_delete(conf);
         return NULL;
@@ -480,9 +444,40 @@ UA_ServerConfig_new_basic256sha256(UA_UInt16 portNumber,
         UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
                        "No CA trust-list provided. Any remote certificate will be accepted.");
 
+    /* Allocate the SecurityPolicies */
+    conf->securityPoliciesSize = 0;
+    conf->securityPolicies = (UA_SecurityPolicy *)UA_malloc(sizeof(UA_SecurityPolicy) * 2);
+    if(!conf->securityPolicies) {
+       UA_ServerConfig_delete(conf);
+       return NULL;
+    }
+
+    /* Populate the SecurityPolicies */
+    UA_ByteString localCertificate = UA_BYTESTRING_NULL;
+    UA_ByteString localPrivateKey  = UA_BYTESTRING_NULL;
+    if(certificate)
+        localCertificate = *certificate;
+    if(privateKey)
+       localPrivateKey = *privateKey;
+    ++conf->securityPoliciesSize;
+    retval =
+        UA_SecurityPolicy_None(&conf->securityPolicies[0], NULL, localCertificate, &conf->logger);
+    if(retval != UA_STATUSCODE_GOOD) {
+        UA_ServerConfig_delete(conf);
+        return NULL;
+    }
+    ++conf->securityPoliciesSize;
+    retval =
+        UA_SecurityPolicy_Basic256Sha256(&conf->securityPolicies[1], &conf->certificateVerification,
+                                         localCertificate, localPrivateKey, &conf->logger);
+    if(retval != UA_STATUSCODE_GOOD) {
+        UA_ServerConfig_delete(conf);
+        return NULL;
+    }
+
     /* Allocate the endpoints */
     conf->endpointsSize = 0;
-    conf->endpoints = (UA_Endpoint *)UA_malloc(sizeof(UA_Endpoint) * 3);
+    conf->endpoints = (UA_EndpointDescription *)UA_malloc(sizeof(UA_EndpointDescription) * 3);
     if(!conf->endpoints) {
         UA_ServerConfig_delete(conf);
         return NULL;
@@ -490,25 +485,24 @@ UA_ServerConfig_new_basic256sha256(UA_UInt16 portNumber,
 
     /* Populate the endpoints */
     ++conf->endpointsSize;
-    retval = createSecurityPolicyNoneEndpoint(conf, &conf->endpoints[0], *certificate);
+    retval = createEndpoint(conf, &conf->endpoints[0], &conf->securityPolicies[0],
+                            UA_MESSAGESECURITYMODE_NONE);
     if(retval != UA_STATUSCODE_GOOD) {
         UA_ServerConfig_delete(conf);
         return NULL;
     }
 
     ++conf->endpointsSize;
-    retval = createSecurityPolicyBasic256Sha256Endpoint(conf, &conf->endpoints[1],
-                                                        UA_MESSAGESECURITYMODE_SIGN, *certificate,
-                                                        *privateKey);
+    retval = createEndpoint(conf, &conf->endpoints[1], &conf->securityPolicies[1],
+                            UA_MESSAGESECURITYMODE_SIGN);
     if(retval != UA_STATUSCODE_GOOD) {
         UA_ServerConfig_delete(conf);
         return NULL;
     }
 
     ++conf->endpointsSize;
-    retval = createSecurityPolicyBasic256Sha256Endpoint(conf, &conf->endpoints[2],
-                                                        UA_MESSAGESECURITYMODE_SIGNANDENCRYPT, *certificate,
-                                                        *privateKey);
+    retval = createEndpoint(conf, &conf->endpoints[2], &conf->securityPolicies[1],
+                            UA_MESSAGESECURITYMODE_SIGNANDENCRYPT);
     if(retval != UA_STATUSCODE_GOOD) {
         UA_ServerConfig_delete(conf);
         return NULL;
@@ -550,52 +544,88 @@ UA_ServerConfig_new_allSecurityPolicies(UA_UInt16 portNumber,
         UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
                        "No CA trust-list provided. Any remote certificate will be accepted.");
 
+    /* Allocate the SecurityPolicies */
+    conf->securityPoliciesSize = 0;
+    conf->securityPolicies = (UA_SecurityPolicy *)UA_malloc(sizeof(UA_SecurityPolicy) * 3);
+    if(!conf->securityPolicies) {
+       UA_ServerConfig_delete(conf);
+       return NULL;
+    }
+
+    /* Populate the SecurityPolicies */
+    UA_ByteString localCertificate = UA_BYTESTRING_NULL;
+    UA_ByteString localPrivateKey  = UA_BYTESTRING_NULL;
+    if(certificate)
+        localCertificate = *certificate;
+    if(privateKey)
+       localPrivateKey = *privateKey;
+    ++conf->securityPoliciesSize;
+    retval =
+        UA_SecurityPolicy_None(&conf->securityPolicies[0], NULL, localCertificate, &conf->logger);
+    if(retval != UA_STATUSCODE_GOOD) {
+        UA_ServerConfig_delete(conf);
+        return NULL;
+    }
+    ++conf->securityPoliciesSize;
+    retval =
+        UA_SecurityPolicy_Basic128Rsa15(&conf->securityPolicies[1], &conf->certificateVerification,
+                                        localCertificate, localPrivateKey, &conf->logger);
+    if(retval != UA_STATUSCODE_GOOD) {
+        UA_ServerConfig_delete(conf);
+        return NULL;
+    }
+    ++conf->securityPoliciesSize;
+    retval =
+        UA_SecurityPolicy_Basic256Sha256(&conf->securityPolicies[2], &conf->certificateVerification,
+                                         localCertificate, localPrivateKey, &conf->logger);
+    if(retval != UA_STATUSCODE_GOOD) {
+        UA_ServerConfig_delete(conf);
+        return NULL;
+    }
+
     /* Allocate the endpoints */
     conf->endpointsSize = 0;
-    conf->endpoints = (UA_Endpoint *)UA_malloc(sizeof(UA_Endpoint) * 5);
+    conf->endpoints = (UA_EndpointDescription *)UA_malloc(sizeof(UA_EndpointDescription) * 5);
     if(!conf->endpoints) {
         UA_ServerConfig_delete(conf);
         return NULL;
     }
 
     /* Populate the endpoints */
-    retval = createSecurityPolicyNoneEndpoint(conf, &conf->endpoints[conf->endpointsSize], *certificate);
+    retval = createEndpoint(conf, &conf->endpoints[conf->endpointsSize], &conf->securityPolicies[0],
+                            UA_MESSAGESECURITYMODE_NONE);
     ++conf->endpointsSize;
     if(retval != UA_STATUSCODE_GOOD) {
         UA_ServerConfig_delete(conf);
         return NULL;
     }
 
-    retval = createSecurityPolicyBasic128Rsa15Endpoint(conf, &conf->endpoints[conf->endpointsSize],
-                                                       UA_MESSAGESECURITYMODE_SIGN, *certificate,
-                                                       *privateKey);
+    retval = createEndpoint(conf, &conf->endpoints[conf->endpointsSize], &conf->securityPolicies[1],
+                            UA_MESSAGESECURITYMODE_SIGN);
     ++conf->endpointsSize;
     if(retval != UA_STATUSCODE_GOOD) {
         UA_ServerConfig_delete(conf);
         return NULL;
     }
 
-    retval = createSecurityPolicyBasic128Rsa15Endpoint(conf, &conf->endpoints[conf->endpointsSize],
-                                                       UA_MESSAGESECURITYMODE_SIGNANDENCRYPT, *certificate,
-                                                       *privateKey);
+    retval = createEndpoint(conf, &conf->endpoints[conf->endpointsSize], &conf->securityPolicies[1],
+                            UA_MESSAGESECURITYMODE_SIGNANDENCRYPT);
     ++conf->endpointsSize;
     if(retval != UA_STATUSCODE_GOOD) {
         UA_ServerConfig_delete(conf);
         return NULL;
     }
 
-    retval = createSecurityPolicyBasic256Sha256Endpoint(conf, &conf->endpoints[conf->endpointsSize],
-                                                        UA_MESSAGESECURITYMODE_SIGN, *certificate,
-                                                        *privateKey);
+    retval = createEndpoint(conf, &conf->endpoints[conf->endpointsSize], &conf->securityPolicies[2],
+                            UA_MESSAGESECURITYMODE_SIGN);
     ++conf->endpointsSize;
     if(retval != UA_STATUSCODE_GOOD) {
         UA_ServerConfig_delete(conf);
         return NULL;
     }
 
-    retval = createSecurityPolicyBasic256Sha256Endpoint(conf, &conf->endpoints[conf->endpointsSize],
-                                                        UA_MESSAGESECURITYMODE_SIGNANDENCRYPT, *certificate,
-                                                        *privateKey);
+    retval = createEndpoint(conf, &conf->endpoints[conf->endpointsSize], &conf->securityPolicies[2],
+                            UA_MESSAGESECURITYMODE_SIGNANDENCRYPT);
     ++conf->endpointsSize;
     if(retval != UA_STATUSCODE_GOOD) {
         UA_ServerConfig_delete(conf);
@@ -640,11 +670,17 @@ UA_ServerConfig_delete(UA_ServerConfig *config) {
     UA_String_deleteMembers(&config->customHostname);
     config->customHostname = UA_STRING_NULL;
 
-    for(size_t i = 0; i < config->endpointsSize; ++i) {
-        UA_SecurityPolicy *policy = &config->endpoints[i].securityPolicy;
+    for(size_t i = 0; i < config->securityPoliciesSize; ++i) {
+        UA_SecurityPolicy *policy = &config->securityPolicies[i];
         policy->deleteMembers(policy);
-        UA_EndpointDescription_deleteMembers(&config->endpoints[i].endpointDescription);
     }
+    UA_free(config->securityPolicies);
+    config->securityPolicies = NULL;
+    config->securityPoliciesSize = 0;
+
+    for(size_t i = 0; i < config->endpointsSize; ++i)
+        UA_EndpointDescription_deleteMembers(&config->endpoints[i]);
+
     UA_free(config->endpoints);
     config->endpoints = NULL;
     config->endpointsSize = 0;

+ 21 - 2
src/server/ua_server.c

@@ -328,11 +328,13 @@ UA_Server_updateCertificate(UA_Server *server,
 
     size_t i = 0;
     while (i < server->config.endpointsSize) {
-        UA_EndpointDescription *ed = &server->config.endpoints[i].endpointDescription;
+        UA_EndpointDescription *ed = &server->config.endpoints[i];
         if (UA_ByteString_equal(&ed->serverCertificate, oldCertificate)) {
             UA_String_deleteMembers(&ed->serverCertificate);
             UA_String_copy(newCertificate, &ed->serverCertificate);
-            UA_SecurityPolicy *sp = &server->config.endpoints[i].securityPolicy;
+            UA_SecurityPolicy *sp = UA_SecurityPolicy_getSecurityPolicyByUri(server, &server->config.endpoints[i].securityPolicyUri);
+            if(!sp)
+                return UA_STATUSCODE_BADINTERNALERROR;
             sp->updateCertificateAndPrivateKey(sp, *newCertificate, *newPrivateKey);
         }
         i++;
@@ -341,6 +343,23 @@ UA_Server_updateCertificate(UA_Server *server,
     return UA_STATUSCODE_GOOD;
 }
 
+/***************************/
+/* Server lookup functions */
+/***************************/
+
+UA_SecurityPolicy *
+UA_SecurityPolicy_getSecurityPolicyByUri(const UA_Server *server,
+                                         UA_ByteString *securityPolicyUri)
+{
+    for(size_t i = 0; i < server->config.securityPoliciesSize; i++) {
+        UA_SecurityPolicy *securityPolicyCandidate = &server->config.securityPolicies[i];
+        if(UA_ByteString_equal(securityPolicyUri,
+                               &securityPolicyCandidate->policyUri))
+            return securityPolicyCandidate;
+    }
+    return NULL;
+}
+
 /********************/
 /* Main Server Loop */
 /********************/

+ 12 - 6
src/server/ua_server_binary.c

@@ -648,15 +648,21 @@ createSecureChannel(void *application, UA_Connection *connection,
     UA_Server *server = (UA_Server*)application;
 
     /* Iterate over available endpoints and choose the correct one */
-    UA_Endpoint *endpoint = NULL;
+    UA_EndpointDescription *endpoint = NULL;
+    UA_SecurityPolicy *securityPolicy = NULL;
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
     for(size_t i = 0; i < server->config.endpointsSize; ++i) {
-        UA_Endpoint *endpointCandidate = &server->config.endpoints[i];
+        UA_EndpointDescription *endpointCandidate = &server->config.endpoints[i];
         if(!UA_ByteString_equal(&asymHeader->securityPolicyUri,
-                                &endpointCandidate->securityPolicy.policyUri))
+                                &endpointCandidate->securityPolicyUri))
             continue;
-        retval = endpointCandidate->securityPolicy.asymmetricModule.
-            compareCertificateThumbprint(&endpointCandidate->securityPolicy,
+        securityPolicy = UA_SecurityPolicy_getSecurityPolicyByUri(server,
+                                                                  (UA_ByteString*)&endpointCandidate->securityPolicyUri);
+        if(!securityPolicy)
+            return UA_STATUSCODE_BADINTERNALERROR;
+
+        retval = securityPolicy->asymmetricModule.
+            compareCertificateThumbprint(securityPolicy,
                                          &asymHeader->receiverCertificateThumbprint);
         if(retval != UA_STATUSCODE_GOOD)
             continue;
@@ -673,7 +679,7 @@ createSecureChannel(void *application, UA_Connection *connection,
 
     /* Create a new channel */
     return UA_SecureChannelManager_create(&server->secureChannelManager, connection,
-                                          &endpoint->securityPolicy, asymHeader);
+                                          securityPolicy, asymHeader);
 }
 
 static UA_StatusCode

+ 2 - 2
src/server/ua_services_discovery.c

@@ -238,7 +238,7 @@ Service_GetEndpoints(UA_Server *server, UA_Session *session,
         for(size_t j = 0; j < server->config.endpointsSize; ++j) {
             for(size_t i = 0; i < request->profileUrisSize; ++i) {
                 if(!UA_String_equal(&request->profileUris[i],
-                                    &server->config.endpoints[j].endpointDescription.transportProfileUri))
+                                    &server->config.endpoints[j].transportProfileUri))
                     continue;
                 relevant_endpoints[j] = true;
                 ++relevant_count;
@@ -277,7 +277,7 @@ Service_GetEndpoints(UA_Server *server, UA_Session *session,
         for(size_t j = 0; j < server->config.endpointsSize; ++j) {
             if(!relevant_endpoints[j])
                 continue;
-            retval = UA_EndpointDescription_copy(&server->config.endpoints[j].endpointDescription,
+            retval = UA_EndpointDescription_copy(&server->config.endpoints[j],
                                                  &response->endpoints[k]);
             if(retval != UA_STATUSCODE_GOOD)
                 goto error;

+ 7 - 7
src/server/ua_services_session.c

@@ -135,7 +135,7 @@ Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
     /* Copy the server's endpointdescriptions into the response */
     for(size_t i = 0; i < server->config.endpointsSize; ++i)
         response->responseHeader.serviceResult |=
-            UA_EndpointDescription_copy(&server->config.endpoints[i].endpointDescription,
+            UA_EndpointDescription_copy(&server->config.endpoints[i],
                                         &response->serverEndpoints[i]);
     if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
         UA_SessionManager_removeSession(&server->sessionManager,
@@ -277,20 +277,20 @@ Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel,
     /* Find the matching endpoint */
     const UA_EndpointDescription *ed = NULL;
     for(size_t i = 0; ed == NULL && i < server->config.endpointsSize; ++i) {
-        const UA_Endpoint *e = &server->config.endpoints[i];
+        const UA_EndpointDescription *e = &server->config.endpoints[i];
 
         /* Match the Security Mode */
-        if(e->endpointDescription.securityMode != channel->securityMode)
+        if(e->securityMode != channel->securityMode)
             continue;
 
         /* Match the SecurityPolicy */
-        if(!UA_String_equal(&e->securityPolicy.policyUri,
+        if(!UA_String_equal(&e->securityPolicyUri,
                             &channel->securityPolicy->policyUri))
             continue;
 
         /* Match the UserTokenType */
-        for(size_t j = 0; j < e->endpointDescription.userIdentityTokensSize; j++) {
-            const UA_UserTokenPolicy *u = &e->endpointDescription.userIdentityTokens[j];
+        for(size_t j = 0; j < e->userIdentityTokensSize; j++) {
+            const UA_UserTokenPolicy *u = &e->userIdentityTokens[j];
             if(u->tokenType == UA_USERTOKENTYPE_ANONYMOUS) {
                 if(request->userIdentityToken.content.decoded.type != &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN])
                     continue;
@@ -309,7 +309,7 @@ Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel,
             }
 
             /* Match found */
-            ed = &e->endpointDescription;
+            ed = e;
             break;
         }