ua_accesscontrol_default.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  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) Fraunhofer IOSB (Author: Julius Pfrommer)
  5. * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
  6. */
  7. #include <open62541/plugin/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_EndpointDescription *endpointDescription,
  25. const UA_ByteString *secureChannelRemoteCertificate,
  26. const UA_NodeId *sessionId,
  27. const UA_ExtensionObject *userIdentityToken,
  28. void **sessionContext) {
  29. AccessControlContext *context = (AccessControlContext*)ac->context;
  30. /* The empty token is interpreted as anonymous */
  31. if(userIdentityToken->encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) {
  32. if(!context->allowAnonymous)
  33. return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
  34. /* No userdata atm */
  35. *sessionContext = NULL;
  36. return UA_STATUSCODE_GOOD;
  37. }
  38. /* Could the token be decoded? */
  39. if(userIdentityToken->encoding < UA_EXTENSIONOBJECT_DECODED)
  40. return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
  41. /* Anonymous login */
  42. if(userIdentityToken->content.decoded.type == &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]) {
  43. if(!context->allowAnonymous)
  44. return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
  45. const UA_AnonymousIdentityToken *token = (UA_AnonymousIdentityToken*)
  46. userIdentityToken->content.decoded.data;
  47. /* Compatibility notice: Siemens OPC Scout v10 provides an empty
  48. * policyId. This is not compliant. For compatibility, assume that empty
  49. * policyId == ANONYMOUS_POLICY */
  50. if(token->policyId.data && !UA_String_equal(&token->policyId, &anonymous_policy))
  51. return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
  52. /* No userdata atm */
  53. *sessionContext = NULL;
  54. return UA_STATUSCODE_GOOD;
  55. }
  56. /* Username and password */
  57. if(userIdentityToken->content.decoded.type == &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) {
  58. const UA_UserNameIdentityToken *userToken =
  59. (UA_UserNameIdentityToken*)userIdentityToken->content.decoded.data;
  60. if(!UA_String_equal(&userToken->policyId, &username_policy))
  61. return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
  62. /* TODO: Support encrypted username/password over unencrypted SecureChannels */
  63. if(userToken->encryptionAlgorithm.length > 0)
  64. return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
  65. /* Empty username and password */
  66. if(userToken->userName.length == 0 && userToken->password.length == 0)
  67. return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
  68. /* Try to match username/pw */
  69. UA_Boolean match = false;
  70. for(size_t i = 0; i < context->usernamePasswordLoginSize; i++) {
  71. if(UA_String_equal(&userToken->userName, &context->usernamePasswordLogin[i].username) &&
  72. UA_String_equal(&userToken->password, &context->usernamePasswordLogin[i].password)) {
  73. match = true;
  74. break;
  75. }
  76. }
  77. if(!match)
  78. return UA_STATUSCODE_BADUSERACCESSDENIED;
  79. /* No userdata atm */
  80. *sessionContext = NULL;
  81. return UA_STATUSCODE_GOOD;
  82. }
  83. /* Unsupported token type */
  84. return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
  85. }
  86. static void
  87. closeSession_default(UA_Server *server, UA_AccessControl *ac,
  88. const UA_NodeId *sessionId, void *sessionContext) {
  89. /* no context to clean up */
  90. }
  91. static UA_UInt32
  92. getUserRightsMask_default(UA_Server *server, UA_AccessControl *ac,
  93. const UA_NodeId *sessionId, void *sessionContext,
  94. const UA_NodeId *nodeId, void *nodeContext) {
  95. return 0xFFFFFFFF;
  96. }
  97. static UA_Byte
  98. getUserAccessLevel_default(UA_Server *server, UA_AccessControl *ac,
  99. const UA_NodeId *sessionId, void *sessionContext,
  100. const UA_NodeId *nodeId, void *nodeContext) {
  101. return 0xFF;
  102. }
  103. static UA_Boolean
  104. getUserExecutable_default(UA_Server *server, UA_AccessControl *ac,
  105. const UA_NodeId *sessionId, void *sessionContext,
  106. const UA_NodeId *methodId, void *methodContext) {
  107. return true;
  108. }
  109. static UA_Boolean
  110. getUserExecutableOnObject_default(UA_Server *server, UA_AccessControl *ac,
  111. const UA_NodeId *sessionId, void *sessionContext,
  112. const UA_NodeId *methodId, void *methodContext,
  113. const UA_NodeId *objectId, void *objectContext) {
  114. return true;
  115. }
  116. static UA_Boolean
  117. allowAddNode_default(UA_Server *server, UA_AccessControl *ac,
  118. const UA_NodeId *sessionId, void *sessionContext,
  119. const UA_AddNodesItem *item) {
  120. return true;
  121. }
  122. static UA_Boolean
  123. allowAddReference_default(UA_Server *server, UA_AccessControl *ac,
  124. const UA_NodeId *sessionId, void *sessionContext,
  125. const UA_AddReferencesItem *item) {
  126. return true;
  127. }
  128. static UA_Boolean
  129. allowDeleteNode_default(UA_Server *server, UA_AccessControl *ac,
  130. const UA_NodeId *sessionId, void *sessionContext,
  131. const UA_DeleteNodesItem *item) {
  132. return true;
  133. }
  134. static UA_Boolean
  135. allowDeleteReference_default(UA_Server *server, UA_AccessControl *ac,
  136. const UA_NodeId *sessionId, void *sessionContext,
  137. const UA_DeleteReferencesItem *item) {
  138. return true;
  139. }
  140. #ifdef UA_ENABLE_HISTORIZING
  141. static UA_Boolean
  142. allowHistoryUpdateUpdateData_default(UA_Server *server, UA_AccessControl *ac,
  143. const UA_NodeId *sessionId, void *sessionContext,
  144. const UA_NodeId *nodeId,
  145. UA_PerformUpdateType performInsertReplace,
  146. const UA_DataValue *value) {
  147. return true;
  148. }
  149. static UA_Boolean
  150. allowHistoryUpdateDeleteRawModified_default(UA_Server *server, UA_AccessControl *ac,
  151. const UA_NodeId *sessionId, void *sessionContext,
  152. const UA_NodeId *nodeId,
  153. UA_DateTime startTimestamp,
  154. UA_DateTime endTimestamp,
  155. bool isDeleteModified) {
  156. return true;
  157. }
  158. #endif
  159. /***************************************/
  160. /* Create Delete Access Control Plugin */
  161. /***************************************/
  162. static void deleteMembers_default(UA_AccessControl *ac) {
  163. UA_Array_delete((void*)(uintptr_t)ac->userTokenPolicies,
  164. ac->userTokenPoliciesSize,
  165. &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
  166. ac->userTokenPolicies = NULL;
  167. ac->userTokenPoliciesSize = 0;
  168. AccessControlContext *context = (AccessControlContext*)ac->context;
  169. if (context) {
  170. for(size_t i = 0; i < context->usernamePasswordLoginSize; i++) {
  171. UA_String_deleteMembers(&context->usernamePasswordLogin[i].username);
  172. UA_String_deleteMembers(&context->usernamePasswordLogin[i].password);
  173. }
  174. if(context->usernamePasswordLoginSize > 0)
  175. UA_free(context->usernamePasswordLogin);
  176. UA_free(ac->context);
  177. }
  178. }
  179. UA_StatusCode
  180. UA_AccessControl_default(UA_AccessControl *ac,
  181. UA_Boolean allowAnonymous, size_t usernamePasswordLoginSize,
  182. const UA_UsernamePasswordLogin *usernamePasswordLogin) {
  183. ac->deleteMembers = deleteMembers_default;
  184. ac->activateSession = activateSession_default;
  185. ac->closeSession = closeSession_default;
  186. ac->getUserRightsMask = getUserRightsMask_default;
  187. ac->getUserAccessLevel = getUserAccessLevel_default;
  188. ac->getUserExecutable = getUserExecutable_default;
  189. ac->getUserExecutableOnObject = getUserExecutableOnObject_default;
  190. ac->allowAddNode = allowAddNode_default;
  191. ac->allowAddReference = allowAddReference_default;
  192. #ifdef UA_ENABLE_HISTORIZING
  193. ac->allowHistoryUpdateUpdateData = allowHistoryUpdateUpdateData_default;
  194. ac->allowHistoryUpdateDeleteRawModified = allowHistoryUpdateDeleteRawModified_default;
  195. #endif
  196. ac->allowDeleteNode = allowDeleteNode_default;
  197. ac->allowDeleteReference = allowDeleteReference_default;
  198. AccessControlContext *context = (AccessControlContext*)
  199. UA_malloc(sizeof(AccessControlContext));
  200. if (!context)
  201. return UA_STATUSCODE_BADOUTOFMEMORY;
  202. memset(context, 0, sizeof(AccessControlContext));
  203. ac->context = context;
  204. /* Allow anonymous? */
  205. context->allowAnonymous = allowAnonymous;
  206. /* Copy username/password to the access control plugin */
  207. if(usernamePasswordLoginSize > 0) {
  208. context->usernamePasswordLogin = (UA_UsernamePasswordLogin*)
  209. UA_malloc(usernamePasswordLoginSize * sizeof(UA_UsernamePasswordLogin));
  210. if(!context->usernamePasswordLogin)
  211. return UA_STATUSCODE_BADOUTOFMEMORY;
  212. context->usernamePasswordLoginSize = usernamePasswordLoginSize;
  213. for(size_t i = 0; i < usernamePasswordLoginSize; i++) {
  214. UA_String_copy(&usernamePasswordLogin[i].username, &context->usernamePasswordLogin[i].username);
  215. UA_String_copy(&usernamePasswordLogin[i].password, &context->usernamePasswordLogin[i].password);
  216. }
  217. }
  218. /* Set the allowed policies */
  219. size_t policies = 0;
  220. if(allowAnonymous)
  221. policies++;
  222. if(usernamePasswordLoginSize > 0)
  223. policies++;
  224. ac->userTokenPoliciesSize = 0;
  225. ac->userTokenPolicies = (UA_UserTokenPolicy *)
  226. UA_Array_new(policies, &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
  227. if(!ac->userTokenPolicies)
  228. return UA_STATUSCODE_BADOUTOFMEMORY;
  229. ac->userTokenPoliciesSize = policies;
  230. policies = 0;
  231. if(allowAnonymous) {
  232. ac->userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_ANONYMOUS;
  233. ac->userTokenPolicies[policies].policyId = UA_STRING_ALLOC(ANONYMOUS_POLICY);
  234. if (!ac->userTokenPolicies[policies].policyId.data)
  235. return UA_STATUSCODE_BADOUTOFMEMORY;
  236. policies++;
  237. }
  238. if(usernamePasswordLoginSize > 0) {
  239. ac->userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_USERNAME;
  240. ac->userTokenPolicies[policies].policyId = UA_STRING_ALLOC(USERNAME_POLICY);
  241. if (!ac->userTokenPolicies[policies].policyId.data)
  242. return UA_STATUSCODE_BADOUTOFMEMORY;
  243. /* No encryption of username/password supported at the moment */
  244. ac->userTokenPolicies[policies].securityPolicyUri =
  245. UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#None");
  246. if (!ac->userTokenPolicies[policies].securityPolicyUri.data)
  247. return UA_STATUSCODE_BADOUTOFMEMORY;
  248. }
  249. return UA_STATUSCODE_GOOD;
  250. }