73 lines
3.2 KiB
Text
73 lines
3.2 KiB
Text
https://github.com/open62541/open62541/pull/5935
|
|
https://github.com/open62541/open62541/commit/f4b481276a9144da2a3bd9f67026751885fd803e
|
|
|
|
feat(plugin): allow custom password validation
|
|
|
|
Username password validation in access control plugin allows only
|
|
passwords stored in plaintext. Add a callback to implement custom
|
|
validation. This allows salted password hashes and timing safe
|
|
comparison in the server. Furthermore remote validation could be
|
|
implemented. The new function UA_AccessControl_defaultWithLoginCallback()
|
|
calls existing UA_AccessControl_default() and after that installs
|
|
the given UA_UsernamePasswordLoginCallback with context.
|
|
|
|
Index: plugins/ua_accesscontrol_default.c
|
|
--- plugins/ua_accesscontrol_default.c.orig
|
|
+++ plugins/ua_accesscontrol_default.c
|
|
@@ -21,6 +21,8 @@ typedef struct {
|
|
UA_Boolean allowAnonymous;
|
|
size_t usernamePasswordLoginSize;
|
|
UA_UsernamePasswordLogin *usernamePasswordLogin;
|
|
+ UA_UsernamePasswordLoginCallback loginCallback;
|
|
+ void *loginContext;
|
|
UA_CertificateVerification verifyX509;
|
|
} AccessControlContext;
|
|
|
|
@@ -95,11 +97,18 @@ activateSession_default(UA_Server *server, UA_AccessCo
|
|
|
|
/* Try to match username/pw */
|
|
UA_Boolean match = false;
|
|
- 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)) {
|
|
+ if(context->loginCallback) {
|
|
+ if(context->loginCallback(&userToken->userName, &userToken->password,
|
|
+ context->usernamePasswordLoginSize, context->usernamePasswordLogin,
|
|
+ sessionContext, context->loginContext) == UA_STATUSCODE_GOOD)
|
|
match = true;
|
|
- break;
|
|
+ } else {
|
|
+ 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;
|
|
+ }
|
|
}
|
|
}
|
|
if(!match)
|
|
@@ -399,3 +408,24 @@ UA_AccessControl_default(UA_ServerConfig *config,
|
|
return UA_STATUSCODE_GOOD;
|
|
}
|
|
|
|
+UA_StatusCode
|
|
+UA_AccessControl_defaultWithLoginCallback(UA_ServerConfig *config,
|
|
+ UA_Boolean allowAnonymous, UA_CertificateVerification *verifyX509,
|
|
+ const UA_ByteString *userTokenPolicyUri, size_t usernamePasswordLoginSize,
|
|
+ const UA_UsernamePasswordLogin *usernamePasswordLogin,
|
|
+ UA_UsernamePasswordLoginCallback loginCallback, void *loginContext)
|
|
+{
|
|
+ AccessControlContext *context;
|
|
+ UA_StatusCode sc;
|
|
+
|
|
+ sc = UA_AccessControl_default(config, allowAnonymous, verifyX509,
|
|
+ userTokenPolicyUri, usernamePasswordLoginSize, usernamePasswordLogin);
|
|
+ if (sc != UA_STATUSCODE_GOOD)
|
|
+ return sc;
|
|
+
|
|
+ context = (AccessControlContext *)config->accessControl.context;
|
|
+ context->loginCallback = loginCallback;
|
|
+ context->loginContext = loginContext;
|
|
+
|
|
+ return UA_STATUSCODE_GOOD;
|
|
+}
|