ua_accesscontrol_default.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
  2. * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
  3. *
  4. * Copyright 2016-2017 (c) Julius Pfrommer, Fraunhofer IOSB
  5. * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
  6. */
  7. #include "ua_accesscontrol_default.h"
  8. /* Example access control management. Anonymous and username / password login.
  9. * The access rights are maximally permissive. */
  10. typedef struct {
  11. UA_Boolean allowAnonymous;
  12. size_t usernamePasswordLoginSize;
  13. UA_UsernamePasswordLogin *usernamePasswordLogin;
  14. } AccessControlContext;
  15. #define ANONYMOUS_POLICY "open62541-anonymous-policy"
  16. #define USERNAME_POLICY "open62541-username-policy"
  17. const UA_String anonymous_policy = UA_STRING_STATIC(ANONYMOUS_POLICY);
  18. const UA_String username_policy = UA_STRING_STATIC(USERNAME_POLICY);
  19. /************************/
  20. /* Access Control Logic */
  21. /************************/
  22. static UA_StatusCode
  23. activateSession_default(UA_Server *server, UA_AccessControl *ac,
  24. const UA_NodeId *sessionId,
  25. const UA_ExtensionObject *userIdentityToken,
  26. void **sessionContext) {
  27. /* Could the token be decoded? */
  28. if(userIdentityToken->encoding < UA_EXTENSIONOBJECT_DECODED)
  29. return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
  30. AccessControlContext *context = (AccessControlContext*)ac->context;
  31. /* Anonymous login */
  32. if(userIdentityToken->content.decoded.type == &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]) {
  33. if(!context->allowAnonymous)
  34. return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
  35. const UA_AnonymousIdentityToken *token = (UA_AnonymousIdentityToken*)
  36. userIdentityToken->content.decoded.data;
  37. /* Compatibility notice: Siemens OPC Scout v10 provides an empty
  38. * policyId. This is not compliant. For compatibility, assume that empty
  39. * policyId == ANONYMOUS_POLICY */
  40. if(token->policyId.data && !UA_String_equal(&token->policyId, &anonymous_policy))
  41. return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
  42. /* No userdata atm */
  43. *sessionContext = NULL;
  44. return UA_STATUSCODE_GOOD;
  45. }
  46. /* Username and password */
  47. if(userIdentityToken->content.decoded.type == &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) {
  48. const UA_UserNameIdentityToken *userToken =
  49. (UA_UserNameIdentityToken*)userIdentityToken->content.decoded.data;
  50. if(!UA_String_equal(&userToken->policyId, &username_policy))
  51. return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
  52. /* TODO: Support encrypted username/password over unencrypted SecureChannels */
  53. if(userToken->encryptionAlgorithm.length > 0)
  54. return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
  55. /* Empty username and password */
  56. if(userToken->userName.length == 0 && userToken->password.length == 0)
  57. return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
  58. /* Try to match username/pw */
  59. UA_Boolean match = false;
  60. for(size_t i = 0; i < context->usernamePasswordLoginSize; i++) {
  61. if(UA_String_equal(&userToken->userName, &context->usernamePasswordLogin[i].username) &&
  62. UA_String_equal(&userToken->password, &context->usernamePasswordLogin[i].password)) {
  63. match = true;
  64. break;
  65. }
  66. }
  67. if(!match)
  68. return UA_STATUSCODE_BADUSERACCESSDENIED;
  69. /* No userdata atm */
  70. *sessionContext = NULL;
  71. return UA_STATUSCODE_GOOD;
  72. }
  73. /* Unsupported token type */
  74. return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
  75. }
  76. static void
  77. closeSession_default(UA_Server *server, UA_AccessControl *ac,
  78. const UA_NodeId *sessionId, void *sessionContext) {
  79. /* no context to clean up */
  80. }
  81. static UA_UInt32
  82. getUserRightsMask_default(UA_Server *server, UA_AccessControl *ac,
  83. const UA_NodeId *sessionId, void *sessionContext,
  84. const UA_NodeId *nodeId, void *nodeContext) {
  85. return 0xFFFFFFFF;
  86. }
  87. static UA_Byte
  88. getUserAccessLevel_default(UA_Server *server, UA_AccessControl *ac,
  89. const UA_NodeId *sessionId, void *sessionContext,
  90. const UA_NodeId *nodeId, void *nodeContext) {
  91. return 0xFF;
  92. }
  93. static UA_Boolean
  94. getUserExecutable_default(UA_Server *server, UA_AccessControl *ac,
  95. const UA_NodeId *sessionId, void *sessionContext,
  96. const UA_NodeId *methodId, void *methodContext) {
  97. return true;
  98. }
  99. static UA_Boolean
  100. getUserExecutableOnObject_default(UA_Server *server, UA_AccessControl *ac,
  101. const UA_NodeId *sessionId, void *sessionContext,
  102. const UA_NodeId *methodId, void *methodContext,
  103. const UA_NodeId *objectId, void *objectContext) {
  104. return true;
  105. }
  106. static UA_Boolean
  107. allowAddNode_default(UA_Server *server, UA_AccessControl *ac,
  108. const UA_NodeId *sessionId, void *sessionContext,
  109. const UA_AddNodesItem *item) {
  110. return true;
  111. }
  112. static UA_Boolean
  113. allowAddReference_default(UA_Server *server, UA_AccessControl *ac,
  114. const UA_NodeId *sessionId, void *sessionContext,
  115. const UA_AddReferencesItem *item) {
  116. return true;
  117. }
  118. static UA_Boolean
  119. allowDeleteNode_default(UA_Server *server, UA_AccessControl *ac,
  120. const UA_NodeId *sessionId, void *sessionContext,
  121. const UA_DeleteNodesItem *item) {
  122. return true;
  123. }
  124. static UA_Boolean
  125. allowDeleteReference_default(UA_Server *server, UA_AccessControl *ac,
  126. const UA_NodeId *sessionId, void *sessionContext,
  127. const UA_DeleteReferencesItem *item) {
  128. return true;
  129. }
  130. /***************************************/
  131. /* Create Delete Access Control Plugin */
  132. /***************************************/
  133. static void deleteMembers_default(UA_AccessControl *ac) {
  134. UA_Array_delete((void*)(uintptr_t)ac->userTokenPolicies,
  135. ac->userTokenPoliciesSize,
  136. &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
  137. AccessControlContext *context = (AccessControlContext*)ac->context;
  138. for(size_t i = 0; i < context->usernamePasswordLoginSize; i++) {
  139. UA_String_deleteMembers(&context->usernamePasswordLogin[i].username);
  140. UA_String_deleteMembers(&context->usernamePasswordLogin[i].password);
  141. }
  142. if(context->usernamePasswordLoginSize > 0)
  143. UA_free(context->usernamePasswordLogin);
  144. UA_free(ac->context);
  145. }
  146. UA_AccessControl
  147. UA_AccessControl_default(UA_Boolean allowAnonymous, size_t usernamePasswordLoginSize,
  148. const UA_UsernamePasswordLogin *usernamePasswordLogin) {
  149. AccessControlContext *context = (AccessControlContext*)
  150. UA_malloc(sizeof(AccessControlContext));
  151. UA_AccessControl ac;
  152. memset(&ac, 0, sizeof(ac));
  153. ac.context = context;
  154. ac.deleteMembers = deleteMembers_default;
  155. ac.activateSession = activateSession_default;
  156. ac.closeSession = closeSession_default;
  157. ac.getUserRightsMask = getUserRightsMask_default;
  158. ac.getUserAccessLevel = getUserAccessLevel_default;
  159. ac.getUserExecutable = getUserExecutable_default;
  160. ac.getUserExecutableOnObject = getUserExecutableOnObject_default;
  161. ac.allowAddNode = allowAddNode_default;
  162. ac.allowAddReference = allowAddReference_default;
  163. ac.allowDeleteNode = allowDeleteNode_default;
  164. ac.allowDeleteReference = allowDeleteReference_default;
  165. /* Allow anonymous? */
  166. context->allowAnonymous = allowAnonymous;
  167. /* Copy username/password to the access control plugin */
  168. if(usernamePasswordLoginSize > 0) {
  169. context->usernamePasswordLogin = (UA_UsernamePasswordLogin*)
  170. UA_malloc(usernamePasswordLoginSize * sizeof(UA_UsernamePasswordLogin));
  171. if(!context->usernamePasswordLogin)
  172. return ac;
  173. context->usernamePasswordLoginSize = usernamePasswordLoginSize;
  174. for(size_t i = 0; i < usernamePasswordLoginSize; i++) {
  175. UA_String_copy(&usernamePasswordLogin[i].username, &context->usernamePasswordLogin[i].username);
  176. UA_String_copy(&usernamePasswordLogin[i].password, &context->usernamePasswordLogin[i].password);
  177. }
  178. }
  179. /* Set the allowed policies */
  180. size_t policies = 0;
  181. if(allowAnonymous)
  182. policies++;
  183. if(usernamePasswordLoginSize > 0)
  184. policies++;
  185. ac.userTokenPoliciesSize = 0;
  186. ac.userTokenPolicies = (UA_UserTokenPolicy *)
  187. UA_Array_new(policies, &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
  188. if(!ac.userTokenPolicies)
  189. return ac;
  190. ac.userTokenPoliciesSize = policies;
  191. policies = 0;
  192. if(allowAnonymous) {
  193. ac.userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_ANONYMOUS;
  194. ac.userTokenPolicies[policies].policyId = UA_STRING_ALLOC(ANONYMOUS_POLICY);
  195. policies++;
  196. }
  197. if(usernamePasswordLoginSize > 0) {
  198. ac.userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_USERNAME;
  199. ac.userTokenPolicies[policies].policyId = UA_STRING_ALLOC(USERNAME_POLICY);
  200. }
  201. return ac;
  202. }