Selaa lähdekoodia

Add a context for the AccessControl plugin

Julius Pfrommer 6 vuotta sitten
vanhempi
commit
34cff1d606

+ 12 - 12
examples/access_control/server_access_control.c

@@ -7,33 +7,33 @@
 #include "open62541.h"
 
 static UA_Boolean
-allowAddNode(const UA_NodeId *sessionId, void *sessionContext,
-    const UA_AddNodesItem *item)
-{
+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(const UA_NodeId *sessionId, void *sessionContext,
-    const UA_AddReferencesItem *item)
-{
+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(const UA_NodeId *sessionId, void *sessionContext,
-    const UA_DeleteNodesItem *item)
-{
+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(const UA_NodeId *sessionId, void *sessionContext,
-    const UA_DeleteReferencesItem *item)
-{
+allowDeleteReference(UA_Server *server, UA_AccessControl *ac,
+                     const UA_NodeId *sessionId, void *sessionContext,
+                     const UA_DeleteReferencesItem *item) {
     printf("Called allowDeleteReference\n");
     return UA_TRUE;
 }

+ 31 - 16
include/ua_plugin_access_control.h

@@ -23,55 +23,70 @@ extern "C" {
  * The access control callback is used to authenticate sessions and grant access
  * rights accordingly. */
 
-typedef struct {
-    /* These booleans are used to create endpoints for the possible
-     * authentication methods */
-    UA_Boolean enableAnonymousLogin;
-    UA_Boolean enableUsernamePasswordLogin;
+struct UA_AccessControl;
+typedef struct UA_AccessControl UA_AccessControl;
 
+struct UA_AccessControl {
+    void *context;
+    void (*deleteMembers)(UA_AccessControl *ac);
+
+    /* Supported login mechanisms. The server endpoints are created from here. */
+    size_t userTokenPoliciesSize;
+    UA_UserTokenPolicy *userTokenPolicies;
+    
     /* Authenticate a session. The session context is attached to the session and
      * later passed into the node-based access control callbacks. */
-    UA_StatusCode (*activateSession)(const UA_NodeId *sessionId,
+    UA_StatusCode (*activateSession)(UA_Server *server, UA_AccessControl *ac,
+                                     const UA_NodeId *sessionId,
                                      const UA_ExtensionObject *userIdentityToken,
                                      void **sessionContext);
 
     /* Deauthenticate a session and cleanup */
-    void (*closeSession)(const UA_NodeId *sessionId, void *sessionContext);
+    void (*closeSession)(UA_Server *server, UA_AccessControl *ac,
+                         const UA_NodeId *sessionId, void *sessionContext);
 
     /* Access control for all nodes*/
-    UA_UInt32 (*getUserRightsMask)(const UA_NodeId *sessionId, void *sessionContext,
+    UA_UInt32 (*getUserRightsMask)(UA_Server *server, UA_AccessControl *ac,
+                                   const UA_NodeId *sessionId, void *sessionContext,
                                    const UA_NodeId *nodeId, void *nodeContext);
 
     /* Additional access control for variable nodes */
-    UA_Byte (*getUserAccessLevel)(const UA_NodeId *sessionId, void *sessionContext,
+    UA_Byte (*getUserAccessLevel)(UA_Server *server, UA_AccessControl *ac,
+                                  const UA_NodeId *sessionId, void *sessionContext,
                                   const UA_NodeId *nodeId, void *nodeContext);
 
     /* Additional access control for method nodes */
-    UA_Boolean (*getUserExecutable)(const UA_NodeId *sessionId, void *sessionContext,
+    UA_Boolean (*getUserExecutable)(UA_Server *server, UA_AccessControl *ac,
+                                    const UA_NodeId *sessionId, void *sessionContext,
                                     const UA_NodeId *methodId, void *methodContext);
 
     /* Additional access control for calling a method node in the context of a
      * specific object */
-    UA_Boolean (*getUserExecutableOnObject)(const UA_NodeId *sessionId, void *sessionContext,
+    UA_Boolean (*getUserExecutableOnObject)(UA_Server *server, UA_AccessControl *ac,
+                                            const UA_NodeId *sessionId, void *sessionContext,
                                             const UA_NodeId *methodId, void *methodContext,
                                             const UA_NodeId *objectId, void *objectContext);
 
     /* Allow adding a node */
-    UA_Boolean (*allowAddNode)(const UA_NodeId *sessionId, void *sessionContext,
+    UA_Boolean (*allowAddNode)(UA_Server *server, UA_AccessControl *ac,
+                               const UA_NodeId *sessionId, void *sessionContext,
                                const UA_AddNodesItem *item);
 
     /* Allow adding a reference */
-    UA_Boolean (*allowAddReference)(const UA_NodeId *sessionId, void *sessionContext,
+    UA_Boolean (*allowAddReference)(UA_Server *server, UA_AccessControl *ac,
+                                    const UA_NodeId *sessionId, void *sessionContext,
                                     const UA_AddReferencesItem *item);
 
     /* Allow deleting a node */
-    UA_Boolean (*allowDeleteNode)(const UA_NodeId *sessionId, void *sessionContext,
+    UA_Boolean (*allowDeleteNode)(UA_Server *server, UA_AccessControl *ac,
+                                  const UA_NodeId *sessionId, void *sessionContext,
                                   const UA_DeleteNodesItem *item);
 
     /* Allow deleting a reference */
-    UA_Boolean (*allowDeleteReference)(const UA_NodeId *sessionId, void *sessionContext,
+    UA_Boolean (*allowDeleteReference)(UA_Server *server, UA_AccessControl *ac,
+                                       const UA_NodeId *sessionId, void *sessionContext,
                                        const UA_DeleteReferencesItem *item);
-} UA_AccessControl;
+};
 
 #ifdef __cplusplus
 }

+ 140 - 50
plugins/ua_accesscontrol_default.c

@@ -10,44 +10,44 @@
 /* Example access control management. Anonymous and username / password login.
  * The access rights are maximally permissive. */
 
+typedef struct {
+    UA_Boolean allowAnonymous;
+    size_t usernamePasswordLoginSize;
+    UA_UsernamePasswordLogin *usernamePasswordLogin;
+} AccessControlContext;
+
 #define ANONYMOUS_POLICY "open62541-anonymous-policy"
 #define USERNAME_POLICY "open62541-username-policy"
-
-// TODO: There should be one definition of these strings in the endpoint.
-// Put the endpoint definition in the access control struct?
-#define UA_STRING_STATIC(s) {sizeof(s)-1, (UA_Byte*)s}
 const UA_String anonymous_policy = UA_STRING_STATIC(ANONYMOUS_POLICY);
 const UA_String username_policy = UA_STRING_STATIC(USERNAME_POLICY);
 
-typedef struct {
-    UA_String username;
-    UA_String password;
-} UA_UsernamePasswordLogin;
-
-const size_t usernamePasswordsSize = 2;
-UA_UsernamePasswordLogin usernamePasswords[2] = {
-    { UA_STRING_STATIC("user1"), UA_STRING_STATIC("password") },
-    { UA_STRING_STATIC("user2"), UA_STRING_STATIC("password1") } };
+/************************/
+/* Access Control Logic */
+/************************/
 
-UA_StatusCode
-activateSession_default(const UA_NodeId *sessionId,
+static UA_StatusCode
+activateSession_default(UA_Server *server, UA_AccessControl *ac,
+                        const UA_NodeId *sessionId,
                         const UA_ExtensionObject *userIdentityToken,
                         void **sessionContext) {
     /* Could the token be decoded? */
     if(userIdentityToken->encoding < UA_EXTENSIONOBJECT_DECODED)
         return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
 
+    AccessControlContext *context = (AccessControlContext*)ac->context;
+
     /* Anonymous login */
-    if(userIdentityToken->content.decoded.type ==
-       &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]) {
-        const UA_AnonymousIdentityToken *token =
-            (UA_AnonymousIdentityToken*)userIdentityToken->content.decoded.data;
+    if(userIdentityToken->content.decoded.type == &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]) {
+        if(!context->allowAnonymous)
+            return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
+
+        const UA_AnonymousIdentityToken *token = (UA_AnonymousIdentityToken*)
+            userIdentityToken->content.decoded.data;
 
         /* Compatibility notice: Siemens OPC Scout v10 provides an empty
          * policyId. This is not compliant. For compatibility, assume that empty
          * policyId == ANONYMOUS_POLICY */
-        if(token->policyId.data &&
-           !UA_String_equal(&token->policyId, &anonymous_policy))
+        if(token->policyId.data && !UA_String_equal(&token->policyId, &anonymous_policy))
             return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
 
         /* No userdata atm */
@@ -56,28 +56,26 @@ activateSession_default(const UA_NodeId *sessionId,
     }
 
     /* Username and password */
-    if(userIdentityToken->content.decoded.type ==
-       &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) {
-        const UA_UserNameIdentityToken *token =
+    if(userIdentityToken->content.decoded.type == &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) {
+        const UA_UserNameIdentityToken *userToken =
             (UA_UserNameIdentityToken*)userIdentityToken->content.decoded.data;
-        if(!UA_String_equal(&token->policyId, &username_policy))
+
+        if(!UA_String_equal(&userToken->policyId, &username_policy))
             return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
 
         /* TODO: Support encrypted username/password over unencrypted SecureChannels */
-        if(token->encryptionAlgorithm.length > 0)
+        if(userToken->encryptionAlgorithm.length > 0)
             return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
 
         /* Empty username and password */
-        if(token->userName.length == 0 && token->password.length == 0)
+        if(userToken->userName.length == 0 && userToken->password.length == 0)
             return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
 
         /* Try to match username/pw */
         UA_Boolean match = false;
-        for(size_t i = 0; i < usernamePasswordsSize; i++) {
-            const UA_String *user = &usernamePasswords[i].username;
-            const UA_String *pw = &usernamePasswords[i].password;
-            if(UA_String_equal(&token->userName, user) &&
-               UA_String_equal(&token->password, pw)) {
+        for(size_t i = 0; i < context->usernamePasswordLoginSize; i++) {
+            if(UA_String_equal(&userToken->userName, &context->usernamePasswordLogin[i].username) &&
+               UA_String_equal(&userToken->password, &context->usernamePasswordLogin[i].password)) {
                 match = true;
                 break;
             }
@@ -94,56 +92,148 @@ activateSession_default(const UA_NodeId *sessionId,
     return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
 }
 
-void
-closeSession_default(const UA_NodeId *sessionId, void *sessionContext) {
+static void
+closeSession_default(UA_Server *server, UA_AccessControl *ac,
+                     const UA_NodeId *sessionId, void *sessionContext) {
     /* no context to clean up */
 }
 
-UA_UInt32
-getUserRightsMask_default(const UA_NodeId *sessionId, void *sessionContext,
+static UA_UInt32
+getUserRightsMask_default(UA_Server *server, UA_AccessControl *ac,
+                          const UA_NodeId *sessionId, void *sessionContext,
                           const UA_NodeId *nodeId, void *nodeContext) {
     return 0xFFFFFFFF;
 }
 
-UA_Byte
-getUserAccessLevel_default(const UA_NodeId *sessionId, void *sessionContext,
+static UA_Byte
+getUserAccessLevel_default(UA_Server *server, UA_AccessControl *ac,
+                           const UA_NodeId *sessionId, void *sessionContext,
                            const UA_NodeId *nodeId, void *nodeContext) {
     return 0xFF;
 }
 
-UA_Boolean
-getUserExecutable_default(const UA_NodeId *sessionId, void *sessionContext,
+static UA_Boolean
+getUserExecutable_default(UA_Server *server, UA_AccessControl *ac,
+                          const UA_NodeId *sessionId, void *sessionContext,
                           const UA_NodeId *methodId, void *methodContext) {
     return true;
 }
 
-UA_Boolean
-getUserExecutableOnObject_default(const UA_NodeId *sessionId, void *sessionContext,
+static UA_Boolean
+getUserExecutableOnObject_default(UA_Server *server, UA_AccessControl *ac,
+                                  const UA_NodeId *sessionId, void *sessionContext,
                                   const UA_NodeId *methodId, void *methodContext,
                                   const UA_NodeId *objectId, void *objectContext) {
     return true;
 }
 
-UA_Boolean
-allowAddNode_default(const UA_NodeId *sessionId, void *sessionContext,
+static UA_Boolean
+allowAddNode_default(UA_Server *server, UA_AccessControl *ac,
+                     const UA_NodeId *sessionId, void *sessionContext,
                      const UA_AddNodesItem *item) {
     return true;
 }
 
-UA_Boolean
-allowAddReference_default(const UA_NodeId *sessionId, void *sessionContext,
+static UA_Boolean
+allowAddReference_default(UA_Server *server, UA_AccessControl *ac,
+                          const UA_NodeId *sessionId, void *sessionContext,
                           const UA_AddReferencesItem *item) {
     return true;
 }
 
-UA_Boolean
-allowDeleteNode_default(const UA_NodeId *sessionId, void *sessionContext,
+static UA_Boolean
+allowDeleteNode_default(UA_Server *server, UA_AccessControl *ac,
+                        const UA_NodeId *sessionId, void *sessionContext,
                         const UA_DeleteNodesItem *item) {
     return true;
 }
 
-UA_Boolean
-allowDeleteReference_default(const UA_NodeId *sessionId, void *sessionContext,
+static UA_Boolean
+allowDeleteReference_default(UA_Server *server, UA_AccessControl *ac,
+                             const UA_NodeId *sessionId, void *sessionContext,
                              const UA_DeleteReferencesItem *item) {
     return true;
 }
+
+/***************************************/
+/* Create Delete Access Control Plugin */
+/***************************************/
+
+static void deleteMembers_default(UA_AccessControl *ac) {
+    UA_Array_delete((void*)(uintptr_t)ac->userTokenPolicies,
+                    ac->userTokenPoliciesSize,
+                    &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
+
+    AccessControlContext *context = (AccessControlContext*)ac->context;
+    for(size_t i = 0; i < context->usernamePasswordLoginSize; i++) {
+        UA_String_deleteMembers(&context->usernamePasswordLogin[i].username);
+        UA_String_deleteMembers(&context->usernamePasswordLogin[i].password);
+    }
+    if(context->usernamePasswordLoginSize > 0)
+        UA_free(context->usernamePasswordLogin);
+    UA_free(ac->context);
+}
+
+UA_AccessControl
+UA_AccessControl_default(UA_Boolean allowAnonymous, size_t usernamePasswordLoginSize,
+                         const UA_UsernamePasswordLogin *usernamePasswordLogin) {
+    AccessControlContext *context = (AccessControlContext*)
+        UA_malloc(sizeof(AccessControlContext));
+    
+    UA_AccessControl ac;
+    memset(&ac, 0, sizeof(ac));
+    ac.context = context;
+    ac.deleteMembers = deleteMembers_default;
+    ac.activateSession = activateSession_default;
+    ac.closeSession = closeSession_default;
+    ac.getUserRightsMask = getUserRightsMask_default;
+    ac.getUserAccessLevel = getUserAccessLevel_default;
+    ac.getUserExecutable = getUserExecutable_default;
+    ac.getUserExecutableOnObject = getUserExecutableOnObject_default;
+    ac.allowAddNode = allowAddNode_default;
+    ac.allowAddReference = allowAddReference_default;
+    ac.allowDeleteNode = allowDeleteNode_default;
+    ac.allowDeleteReference = allowDeleteReference_default;
+
+    /* Allow anonymous? */
+    context->allowAnonymous = allowAnonymous;
+
+    /* Copy username/password to the access control plugin */
+    if(usernamePasswordLoginSize > 0) {
+        context->usernamePasswordLogin = (UA_UsernamePasswordLogin*)
+            UA_malloc(usernamePasswordLoginSize * sizeof(UA_UsernamePasswordLogin));
+        if(!context->usernamePasswordLogin)
+            return ac;
+        context->usernamePasswordLoginSize = usernamePasswordLoginSize;
+        for(size_t i = 0; i < usernamePasswordLoginSize; i++) {
+            UA_String_copy(&usernamePasswordLogin[i].username, &context->usernamePasswordLogin[i].username);
+            UA_String_copy(&usernamePasswordLogin[i].password, &context->usernamePasswordLogin[i].password);
+        }
+    }
+
+    /* Set the allowed policies */
+    size_t policies = 0;
+    if(allowAnonymous)
+        policies++;
+    if(usernamePasswordLoginSize > 0)
+        policies++;
+    ac.userTokenPoliciesSize = 0;
+    ac.userTokenPolicies = (UA_UserTokenPolicy *)
+        UA_Array_new(policies, &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
+    if(!ac.userTokenPolicies)
+        return ac;
+    ac.userTokenPoliciesSize = policies;
+
+    policies = 0;
+    if(allowAnonymous) {
+        ac.userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_ANONYMOUS;
+        ac.userTokenPolicies[policies].policyId = UA_STRING_ALLOC(ANONYMOUS_POLICY);
+        policies++;
+    }
+
+    if(usernamePasswordLoginSize > 0) {
+        ac.userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_USERNAME;
+        ac.userTokenPolicies[policies].policyId = UA_STRING_ALLOC(USERNAME_POLICY);
+    }
+    return ac;
+}

+ 12 - 40
plugins/ua_accesscontrol_default.h

@@ -9,51 +9,23 @@
 #define UA_ACCESSCONTROL_DEFAULT_H_
 
 #include "ua_server.h"
+#include "ua_plugin_access_control.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-UA_StatusCode UA_EXPORT
-activateSession_default(const UA_NodeId *sessionId,
-                        const UA_ExtensionObject *userIdentityToken,
-                        void **sessionContext);
-
-void UA_EXPORT
-closeSession_default(const UA_NodeId *sessionId, void *sessionContext);
-
-UA_UInt32 UA_EXPORT
-getUserRightsMask_default(const UA_NodeId *sessionId, void *sessionContext,
-                          const UA_NodeId *nodeId, void *nodeContext);
-
-UA_Byte UA_EXPORT
-getUserAccessLevel_default(const UA_NodeId *sessionId, void *sessionContext,
-                          const UA_NodeId *nodeId, void *nodeContext);
-
-UA_Boolean UA_EXPORT
-getUserExecutable_default(const UA_NodeId *sessionId, void *sessionContext,
-                          const UA_NodeId *methodId, void *methodContext);
-
-UA_Boolean UA_EXPORT
-getUserExecutableOnObject_default(const UA_NodeId *sessionId, void *sessionContext,
-                                  const UA_NodeId *methodId, void *methodContext,
-                                  const UA_NodeId *objectId, void *objectContext);
-
-UA_Boolean UA_EXPORT
-allowAddNode_default(const UA_NodeId *sessionId, void *sessionContext,
-                     const UA_AddNodesItem *item);
-
-UA_Boolean UA_EXPORT
-allowAddReference_default(const UA_NodeId *sessionId, void *sessionContext,
-                          const UA_AddReferencesItem *item);
-
-UA_Boolean UA_EXPORT
-allowDeleteNode_default(const UA_NodeId *sessionId, void *sessionContext,
-                        const UA_DeleteNodesItem *item);
-
-UA_Boolean UA_EXPORT
-allowDeleteReference_default(const UA_NodeId *sessionId, void *sessionContext,
-                             const UA_DeleteReferencesItem *item);
+typedef struct {
+    UA_String username;
+    UA_String password;
+} UA_UsernamePasswordLogin;
+
+/* Default access control. The log-in can be anonymous or username-password. A
+ * logged-in user has all access rights. */
+UA_EXPORT UA_AccessControl
+UA_AccessControl_default(UA_Boolean allowAnonymous,
+                         size_t usernamePasswordLoginSize,
+                         const UA_UsernamePasswordLogin *usernamePasswordLogin);
 
 #ifdef __cplusplus
 }

+ 30 - 54
plugins/ua_config_default.c

@@ -26,9 +26,6 @@
 #include "ua_types_generated_handling.h"
 #include "ua_client_subscriptions.h"
 
-#define ANONYMOUS_POLICY "open62541-anonymous-policy"
-#define USERNAME_POLICY "open62541-username-policy"
-
 /* Struct initialization works across ANSI C/C99/C++ if it is done when the
  * variable is first declared. Assigning values to existing structs is
  * heterogeneous across the three. */
@@ -82,26 +79,17 @@ createSecurityPolicyNoneEndpoint(UA_ServerConfig *conf, UA_Endpoint *endpoint,
     endpoint->endpointDescription.transportProfileUri =
         UA_STRING_ALLOC("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary");
 
-    /* enable anonymous and username/password */
-    size_t policies = 2;
-    endpoint->endpointDescription.userIdentityTokens = (UA_UserTokenPolicy *)
-        UA_Array_new(policies, &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
-    if(!endpoint->endpointDescription.userIdentityTokens)
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-    endpoint->endpointDescription.userIdentityTokensSize = policies;
-
-    endpoint->endpointDescription.userIdentityTokens[0].tokenType =
-        UA_USERTOKENTYPE_ANONYMOUS;
-    endpoint->endpointDescription.userIdentityTokens[0].policyId =
-        UA_STRING_ALLOC(ANONYMOUS_POLICY);
-
-    endpoint->endpointDescription.userIdentityTokens[1].tokenType =
-        UA_USERTOKENTYPE_USERNAME;
-    endpoint->endpointDescription.userIdentityTokens[1].policyId =
-        UA_STRING_ALLOC(USERNAME_POLICY);
+    /* 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,
+                                         &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);
 
@@ -127,8 +115,8 @@ createSecurityPolicyBasic128Rsa15Endpoint(UA_ServerConfig *const conf,
     UA_EndpointDescription_init(&endpoint->endpointDescription);
 
     UA_StatusCode retval =
-        UA_SecurityPolicy_Basic128Rsa15(&endpoint->securityPolicy, &conf->certificateVerification, localCertificate,
-                                        localPrivateKey, conf->logger);
+        UA_SecurityPolicy_Basic128Rsa15(&endpoint->securityPolicy, &conf->certificateVerification,
+                                        localCertificate, localPrivateKey, conf->logger);
     if(retval != UA_STATUSCODE_GOOD) {
         endpoint->securityPolicy.deleteMembers(&endpoint->securityPolicy);
         return retval;
@@ -140,26 +128,17 @@ createSecurityPolicyBasic128Rsa15Endpoint(UA_ServerConfig *const conf,
     endpoint->endpointDescription.transportProfileUri =
         UA_STRING_ALLOC("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary");
 
-    /* enable anonymous and username/password */
-    size_t policies = 1;
-    endpoint->endpointDescription.userIdentityTokens = (UA_UserTokenPolicy *)
-        UA_Array_new(policies, &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
-    if(!endpoint->endpointDescription.userIdentityTokens)
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-    endpoint->endpointDescription.userIdentityTokensSize = policies;
-
-    endpoint->endpointDescription.userIdentityTokens[0].tokenType =
-        UA_USERTOKENTYPE_ANONYMOUS;
-    endpoint->endpointDescription.userIdentityTokens[0].policyId =
-        UA_STRING_ALLOC(ANONYMOUS_POLICY);
-    /*
-    endpoint->endpointDescription.userIdentityTokens[1].tokenType =
-        UA_USERTOKENTYPE_USERNAME;
-    endpoint->endpointDescription.userIdentityTokens[1].policyId =
-        UA_STRING_ALLOC(USERNAME_POLICY);*/
+    /* 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);
 
@@ -168,6 +147,11 @@ createSecurityPolicyBasic128Rsa15Endpoint(UA_ServerConfig *const conf,
 
 #endif
 
+const size_t usernamePasswordsSize = 2;
+UA_UsernamePasswordLogin usernamePasswords[2] = {
+    { UA_STRING_STATIC("user1"), UA_STRING_STATIC("password") },
+    { UA_STRING_STATIC("user2"), UA_STRING_STATIC("password1") } };
+
 static UA_ServerConfig *
 createDefaultConfig(void) {
     UA_ServerConfig *conf = (UA_ServerConfig *) UA_malloc(sizeof(UA_ServerConfig));
@@ -227,19 +211,8 @@ createDefaultConfig(void) {
     conf->nodeLifecycle.constructor = NULL;
     conf->nodeLifecycle.destructor = NULL;
 
-    /* Access Control */
-    conf->accessControl.enableAnonymousLogin = true;
-    conf->accessControl.enableUsernamePasswordLogin = true;
-    conf->accessControl.activateSession = activateSession_default;
-    conf->accessControl.closeSession = closeSession_default;
-    conf->accessControl.getUserRightsMask = getUserRightsMask_default;
-    conf->accessControl.getUserAccessLevel = getUserAccessLevel_default;
-    conf->accessControl.getUserExecutable = getUserExecutable_default;
-    conf->accessControl.getUserExecutableOnObject = getUserExecutableOnObject_default;
-    conf->accessControl.allowAddNode = allowAddNode_default;
-    conf->accessControl.allowAddReference = allowAddReference_default;
-    conf->accessControl.allowDeleteNode = allowDeleteNode_default;
-    conf->accessControl.allowDeleteReference = allowDeleteReference_default;
+    /* Access Control. Anonymous Login only. */
+    conf->accessControl = UA_AccessControl_default(true, usernamePasswordsSize, usernamePasswords);
 
     /* Limits for SecureChannels */
     conf->maxSecureChannels = 40;
@@ -444,6 +417,9 @@ UA_ServerConfig_delete(UA_ServerConfig *config) {
     /* Certificate Validation */
     config->certificateVerification.deleteMembers(&config->certificateVerification);
 
+    /* Access Control */
+    config->accessControl.deleteMembers(&config->accessControl);
+
     UA_free(config);
 }
 

+ 6 - 3
src/server/ua_services_attribute.c

@@ -32,7 +32,8 @@ getUserWriteMask(UA_Server *server, const UA_Session *session,
     if(session == &adminSession)
         return 0xFFFFFFFF; /* the local admin user has all rights */
     return node->writeMask &
-        server->config.accessControl.getUserRightsMask(&session->sessionId, session->sessionHandle,
+        server->config.accessControl.getUserRightsMask(server, &server->config.accessControl,
+                                                       &session->sessionId, session->sessionHandle,
                                                        &node->nodeId, node->context);
 }
 
@@ -50,7 +51,8 @@ getUserAccessLevel(UA_Server *server, const UA_Session *session,
     if(session == &adminSession)
         return 0xFF; /* the local admin user has all rights */
     return node->accessLevel &
-        server->config.accessControl.getUserAccessLevel(&session->sessionId, session->sessionHandle,
+        server->config.accessControl.getUserAccessLevel(server, &server->config.accessControl,
+                                                        &session->sessionId, session->sessionHandle,
                                                         &node->nodeId, node->context);
 }
 
@@ -60,7 +62,8 @@ getUserExecutable(UA_Server *server, const UA_Session *session,
     if(session == &adminSession)
         return true; /* the local admin user has all rights */
     return node->executable &
-        server->config.accessControl.getUserExecutable(&session->sessionId, session->sessionHandle,
+        server->config.accessControl.getUserExecutable(server, &server->config.accessControl,
+                                                       &session->sessionId, session->sessionHandle,
                                                        &node->nodeId, node->context);
 }
 

+ 2 - 1
src/server/ua_services_call.c

@@ -159,7 +159,8 @@ callWithMethodAndObject(UA_Server *server, UA_Session *session,
     UA_Boolean executable = method->executable;
     if(session != &adminSession)
         executable = executable &&
-            server->config.accessControl.getUserExecutableOnObject(&session->sessionId,
+            server->config.accessControl.getUserExecutableOnObject(server, 
+                           &server->config.accessControl, &session->sessionId,
                            session->sessionHandle, &request->methodId, method->context,
                            &request->objectId, object->context);
     if(!executable) {

+ 8 - 4
src/server/ua_services_nodemanagement.c

@@ -892,7 +892,8 @@ Operation_addNode_begin(UA_Server *server, UA_Session *session, void *nodeContex
                         const UA_NodeId *referenceTypeId, UA_NodeId *outNewNodeId) {
     /* Do not check access for server */
     if(session != &adminSession && server->config.accessControl.allowAddNode &&
-       !server->config.accessControl.allowAddNode(&session->sessionId, session->sessionHandle, item)) {
+       !server->config.accessControl.allowAddNode(server, &server->config.accessControl,
+                                                  &session->sessionId, session->sessionHandle, item)) {
         return UA_STATUSCODE_BADUSERACCESSDENIED;
     }
 
@@ -1258,7 +1259,8 @@ deleteNodeOperation(UA_Server *server, UA_Session *session, void *context,
                     const UA_DeleteNodesItem *item, UA_StatusCode *result) {
     /* Do not check access for server */
     if(session != &adminSession && server->config.accessControl.allowDeleteNode &&
-       !server->config.accessControl.allowDeleteNode(&session->sessionId, session->sessionHandle, item)) {
+       !server->config.accessControl.allowDeleteNode(server, &server->config.accessControl,
+                                                     &session->sessionId, session->sessionHandle, item)) {
         *result = UA_STATUSCODE_BADUSERACCESSDENIED;
         return;
     }
@@ -1336,7 +1338,8 @@ Operation_addReference(UA_Server *server, UA_Session *session, void *context,
                        const UA_AddReferencesItem *item, UA_StatusCode *retval) {
     /* Do not check access for server */
     if(session != &adminSession && server->config.accessControl.allowAddReference &&
-       !server->config.accessControl. allowAddReference(&session->sessionId, session->sessionHandle, item)) {
+       !server->config.accessControl.allowAddReference(server, &server->config.accessControl,
+                                                       &session->sessionId, session->sessionHandle, item)) {
         *retval = UA_STATUSCODE_BADUSERACCESSDENIED;
         return;
     }
@@ -1435,7 +1438,8 @@ Operation_deleteReference(UA_Server *server, UA_Session *session, void *context,
                           const UA_DeleteReferencesItem *item, UA_StatusCode *retval) {
     /* Do not check access for server */
     if(session != &adminSession && server->config.accessControl.allowDeleteReference &&
-       !server->config.accessControl.allowDeleteReference(&session->sessionId, session->sessionHandle, item)) {
+       !server->config.accessControl.allowDeleteReference(server, &server->config.accessControl,
+                                                          &session->sessionId, session->sessionHandle, item)) {
         *retval = UA_STATUSCODE_BADUSERACCESSDENIED;
         return;
     }

+ 4 - 4
src/server/ua_services_session.c

@@ -239,8 +239,8 @@ Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel,
 
     /* Callback into userland access control */
     response->responseHeader.serviceResult =
-        server->config.accessControl.activateSession(&session->sessionId,
-                                                     &request->userIdentityToken,
+        server->config.accessControl.activateSession(server, &server->config.accessControl,
+                                                     &session->sessionId, &request->userIdentityToken,
                                                      &session->sessionHandle);
     if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
         UA_LOG_INFO_SESSION(server->config.logger, session,
@@ -283,8 +283,8 @@ Service_CloseSession(UA_Server *server, UA_Session *session,
     UA_LOG_INFO_SESSION(server->config.logger, session, "CloseSession");
 
     /* Callback into userland access control */
-    server->config.accessControl.closeSession(&session->sessionId,
-                                              session->sessionHandle);
+    server->config.accessControl.closeSession(server, &server->config.accessControl,
+                                              &session->sessionId, session->sessionHandle);
     response->responseHeader.serviceResult =
         UA_SessionManager_removeSession(&server->sessionManager,
                                         &session->header.authenticationToken);

+ 3 - 1
src/server/ua_session_manager.c

@@ -72,7 +72,9 @@ UA_SessionManager_cleanupTimedOut(UA_SessionManager *sm,
             continue;
         UA_LOG_INFO_SESSION(sm->server->config.logger, &sentry->session,
                             "Session has timed out");
-        sm->server->config.accessControl.closeSession(&sentry->session.sessionId,
+        sm->server->config.accessControl.closeSession(sm->server,
+                                                      &sm->server->config.accessControl,
+                                                      &sentry->session.sessionId,
                                                       sentry->session.sessionHandle);
         removeSession(sm, sentry);
     }