mirror of
https://github.com/open62541/open62541.git
synced 2025-06-03 04:00:21 +00:00
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.
This commit is contained in:
parent
1186cfd559
commit
f4b481276a
@ -18,6 +18,11 @@ typedef struct {
|
|||||||
UA_String password;
|
UA_String password;
|
||||||
} UA_UsernamePasswordLogin;
|
} UA_UsernamePasswordLogin;
|
||||||
|
|
||||||
|
typedef UA_StatusCode (*UA_UsernamePasswordLoginCallback)
|
||||||
|
(const UA_String *userName, const UA_ByteString *password,
|
||||||
|
size_t usernamePasswordLoginSize, const UA_UsernamePasswordLogin
|
||||||
|
*usernamePasswordLogin, void **sessionContext, void *loginContext);
|
||||||
|
|
||||||
/* Default access control. The log-in can be anonymous or username-password. A
|
/* Default access control. The log-in can be anonymous or username-password. A
|
||||||
* logged-in user has all access rights.
|
* logged-in user has all access rights.
|
||||||
*
|
*
|
||||||
@ -31,6 +36,16 @@ UA_AccessControl_default(UA_ServerConfig *config,
|
|||||||
size_t usernamePasswordLoginSize,
|
size_t usernamePasswordLoginSize,
|
||||||
const UA_UsernamePasswordLogin *usernamePasswordLogin);
|
const UA_UsernamePasswordLogin *usernamePasswordLogin);
|
||||||
|
|
||||||
|
UA_EXPORT 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);
|
||||||
|
|
||||||
_UA_END_DECLS
|
_UA_END_DECLS
|
||||||
|
|
||||||
#endif /* UA_ACCESSCONTROL_DEFAULT_H_ */
|
#endif /* UA_ACCESSCONTROL_DEFAULT_H_ */
|
||||||
|
@ -21,6 +21,8 @@ typedef struct {
|
|||||||
UA_Boolean allowAnonymous;
|
UA_Boolean allowAnonymous;
|
||||||
size_t usernamePasswordLoginSize;
|
size_t usernamePasswordLoginSize;
|
||||||
UA_UsernamePasswordLogin *usernamePasswordLogin;
|
UA_UsernamePasswordLogin *usernamePasswordLogin;
|
||||||
|
UA_UsernamePasswordLoginCallback loginCallback;
|
||||||
|
void *loginContext;
|
||||||
UA_CertificateVerification verifyX509;
|
UA_CertificateVerification verifyX509;
|
||||||
} AccessControlContext;
|
} AccessControlContext;
|
||||||
|
|
||||||
@ -95,11 +97,18 @@ activateSession_default(UA_Server *server, UA_AccessControl *ac,
|
|||||||
|
|
||||||
/* Try to match username/pw */
|
/* Try to match username/pw */
|
||||||
UA_Boolean match = false;
|
UA_Boolean match = false;
|
||||||
for(size_t i = 0; i < context->usernamePasswordLoginSize; i++) {
|
if(context->loginCallback) {
|
||||||
if(UA_String_equal(&userToken->userName, &context->usernamePasswordLogin[i].username) &&
|
if(context->loginCallback(&userToken->userName, &userToken->password,
|
||||||
UA_String_equal(&userToken->password, &context->usernamePasswordLogin[i].password)) {
|
context->usernamePasswordLoginSize, context->usernamePasswordLogin,
|
||||||
|
sessionContext, context->loginContext) == UA_STATUSCODE_GOOD)
|
||||||
match = true;
|
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)
|
if(!match)
|
||||||
@ -399,3 +408,24 @@ UA_AccessControl_default(UA_ServerConfig *config,
|
|||||||
return UA_STATUSCODE_GOOD;
|
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;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user