Skip to content

Commit

Permalink
Merge pull request open62541#6838 from jpfr/merge_14_master_23
Browse files Browse the repository at this point in the history
Merge 1.4 to master
  • Loading branch information
jpfr authored Nov 6, 2024
2 parents ffb7432 + c5b39c9 commit d77bcd1
Show file tree
Hide file tree
Showing 24 changed files with 221 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@ int main(int argc, char* argv[]) {
UA_ByteString certificate = loadFile(argv[2]);
UA_ByteString privateKey = loadFile(argv[3]);

/* Load the trustList. Load revocationList is not supported now */
/* Load the trustList */
size_t trustListSize = 0;
if(argc > MIN_ARGS)
trustListSize = (size_t)argc-MIN_ARGS;
UA_STACKARRAY(UA_ByteString, trustList, trustListSize+1);
for(size_t trustListCount = 0; trustListCount < trustListSize; trustListCount++)
trustList[trustListCount] = loadFile(argv[trustListCount+4]);

/* Revocation lists are supported, but not used for the example here */
UA_ByteString *revocationList = NULL;
size_t revocationListSize = 0;

Expand Down
3 changes: 1 addition & 2 deletions examples/ci_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,10 @@ int main(int argc, char* argv[]) {
size_t issuerListSize = 0;
UA_ByteString *issuerList = NULL;

/* Loading of a revocation list currently unsupported */
/* Revocation lists are supported, but not used for the example here */
UA_ByteString *revocationList = NULL;
size_t revocationListSize = 0;


retval = UA_ServerConfig_setDefaultWithSecurityPolicies(config, port,
&certificate, &privateKey,
trustList, trustListSize,
Expand Down
3 changes: 2 additions & 1 deletion examples/encryption/client_encryption.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ int main(int argc, char* argv[]) {
UA_ByteString certificate = loadFile(argv[2]);
UA_ByteString privateKey = loadFile(argv[3]);

/* Load the trustList. Load revocationList is not supported now */
/* Load the trustlist */
size_t trustListSize = 0;
if(argc > MIN_ARGS)
trustListSize = (size_t)argc-MIN_ARGS;
UA_STACKARRAY(UA_ByteString, trustList, trustListSize+1);
for(size_t trustListCount = 0; trustListCount < trustListSize; trustListCount++)
trustList[trustListCount] = loadFile(argv[trustListCount+4]);

/* Revocation lists are supported, but not used for the example here */
UA_ByteString *revocationList = NULL;
size_t revocationListSize = 0;

Expand Down
3 changes: 2 additions & 1 deletion examples/encryption/client_encryption_tpm_keystore.c
Original file line number Diff line number Diff line change
Expand Up @@ -375,14 +375,15 @@ int main(int argc, char* argv[]) {
certificate.data = certificate_out_data->data;
certificate.length = certificate_out_data->length;

/* Load the trustList. Load revocationList is not supported now */
/* Load the trust list */
size_t trustListSize = 0;
if(argc > MIN_ARGS)
trustListSize = (size_t)argc-MIN_ARGS;
UA_STACKARRAY(UA_ByteString, trustList, trustListSize+1);
for(size_t trustListCount = 0; trustListCount < trustListSize; trustListCount++)
trustList[trustListCount] = loadFile(argv[trustListCount+7]);

/* Revocation lists are supported, but not used for the example here */
UA_ByteString *revocationList = NULL;
size_t revocationListSize = 0;

Expand Down
2 changes: 1 addition & 1 deletion examples/encryption/server_encryption.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ int main(int argc, char* argv[]) {
size_t issuerListSize = 0;
UA_ByteString *issuerList = NULL;

/* Loading of a revocation list currently unsupported */
/* Revocation lists are supported, but not used for the example here */
UA_ByteString *revocationList = NULL;
size_t revocationListSize = 0;

Expand Down
2 changes: 1 addition & 1 deletion examples/encryption/server_encryption_tpm_keystore.c
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ int main(int argc, char* argv[]) {
size_t issuerListSize = 0;
UA_ByteString *issuerList = NULL;

/* Loading of a revocation list currently unsupported */
/* Revocation lists are supported, but not used for the example here */
UA_ByteString *revocationList = NULL;
size_t revocationListSize = 0;

Expand Down
2 changes: 2 additions & 0 deletions plugins/crypto/openssl/securitypolicy_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include <openssl/x509.h>
#include <openssl/evp.h>

#define UA_SHA1_LENGTH 20

_UA_BEGIN_DECLS


Expand Down
36 changes: 36 additions & 0 deletions src/pubsub/ua_pubsub_ns0.c
Original file line number Diff line number Diff line change
Expand Up @@ -1323,6 +1323,26 @@ writeContentMask(UA_Server *server, const UA_NodeId *sessionId,
return UA_STATUSCODE_GOOD;
}

static UA_StatusCode
readGroupVersion(UA_Server *server, const UA_NodeId *sessionId,
void *sessionContext, const UA_NodeId *nodeId,
void *nodeContext, UA_Boolean includeSourceTimeStamp,
const UA_NumericRange *range, UA_DataValue *value) {
UA_WriterGroup *writerGroup = (UA_WriterGroup*)nodeContext;
if((writerGroup->config.messageSettings.encoding != UA_EXTENSIONOBJECT_DECODED &&
writerGroup->config.messageSettings.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE) ||
writerGroup->config.messageSettings.content.decoded.type !=
&UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE])
return UA_STATUSCODE_BADINTERNALERROR;
UA_UadpWriterGroupMessageDataType *wgm = (UA_UadpWriterGroupMessageDataType*)
writerGroup->config.messageSettings.content.decoded.data;

UA_Variant_setScalarCopy(&value->value, &wgm->groupVersion,
&UA_TYPES[UA_DATATYPEKIND_UINT32]);
value->hasValue = true;
return UA_STATUSCODE_GOOD;
}

UA_StatusCode
addWriterGroupRepresentation(UA_Server *server, UA_WriterGroup *writerGroup) {
UA_LOCK_ASSERT(&server->serviceMutex);
Expand Down Expand Up @@ -1436,6 +1456,22 @@ addWriterGroupRepresentation(UA_Server *server, UA_WriterGroup *writerGroup) {
writeAccessLevelAttribute(server, contentMaskId,
UA_ACCESSLEVELMASK_WRITE | UA_ACCESSLEVELMASK_READ);

}
UA_NodeId groupVersionId =
findSingleChildNode(server, UA_QUALIFIEDNAME(0, "GroupVersion"),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), messageSettingsId);
if(!UA_NodeId_isNull(&groupVersionId)) {
/* Set the callback */
UA_DataSource ds;
ds.read = readGroupVersion;
ds.write = NULL;
setVariableNode_dataSource(server, groupVersionId, ds);
setNodeContext(server, groupVersionId, writerGroup);

/* Read only */
writeAccessLevelAttribute(server, groupVersionId,
UA_ACCESSLEVELMASK_READ);

}

/* Add reference to methods */
Expand Down
3 changes: 3 additions & 0 deletions src/server/ua_server_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,9 @@ UA_ServerComponent * UA_BinaryProtocolManager_new(UA_Server *server);
UA_ServerComponent * UA_PubSubManager_new(UA_Server *server);
#endif

UA_String
securityPolicyUriPostfix(const UA_String uri);

/***********/
/* RefTree */
/***********/
Expand Down
68 changes: 41 additions & 27 deletions src/server/ua_services_discovery.c
Original file line number Diff line number Diff line change
Expand Up @@ -294,18 +294,17 @@ getDefaultEncryptedSecurityPolicy(UA_Server *server) {
if(!UA_String_equal(&UA_SECURITY_POLICY_NONE_URI, &sp->policyUri))
return sp;
}
return server->config.securityPoliciesSize > 0 ?
&server->config.securityPolicies[0] : NULL;
return NULL; /* No encrypted policy found */
}

const char *securityModeStrs[4] = {"-invalid", "-none", "-sign", "-sign+encrypt"};

static UA_String
UA_String
securityPolicyUriPostfix(const UA_String uri) {
for(size_t i = 0; i < uri.length; i++) {
if(uri.data[i] != '#')
for(UA_Byte *b = uri.data + uri.length - 1; b >= uri.data; b--) {
if(*b != '#')
continue;
UA_String postfix = {uri.length - i, &uri.data[i]};
UA_String postfix = {uri.length - (size_t)(b - uri.data), b};
return postfix;
}
return uri;
Expand All @@ -321,30 +320,45 @@ updateEndpointUserIdentityToken(UA_Server *server, UA_EndpointDescription *ed) {
/* Copy the UserTokenPolicies from the AccessControl plugin, but only the matching ones to the securityPolicyUri.
* TODO: Different instances of the AccessControl plugin per Endpoint */
UA_StatusCode res = UA_STATUSCODE_GOOD;
for(size_t i = 0; i < server->config.accessControl.userTokenPoliciesSize; i++) {
UA_UserTokenPolicy *utp = &server->config.accessControl.userTokenPolicies[i];
if(UA_String_equal(&ed->securityPolicyUri, &utp->securityPolicyUri)) {
res = UA_Array_appendCopy((void**)&ed->userIdentityTokens,
&ed->userIdentityTokensSize,
utp,
&UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
if(res != UA_STATUSCODE_GOOD)
return res;
}
}

for(size_t i = 0; i < ed->userIdentityTokensSize; i++) {
/* Use the securityPolicy of the SecureChannel. But not if the
* SecureChannel is unencrypted and there is a non-anonymous token. */
UA_UserTokenPolicy *utp = &ed->userIdentityTokens[i];
UA_ServerConfig *sc = &server->config;
for(size_t i = 0; i < sc->accessControl.userTokenPoliciesSize; i++) {
UA_UserTokenPolicy *utp = &sc->accessControl.userTokenPolicies[i];
res = UA_Array_appendCopy((void**)&ed->userIdentityTokens,
&ed->userIdentityTokensSize, utp,
&UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
if(res != UA_STATUSCODE_GOOD)
return res;

/* Select the SecurityPolicy for the UserTokenType.
* If not set, the SecurityPolicy of the SecureChannel is used. */
utp = &ed->userIdentityTokens[ed->userIdentityTokensSize - 1];
UA_String_clear(&utp->securityPolicyUri);
if((!server->config.allowNonePolicyPassword || ed->userIdentityTokens[i].tokenType != UA_USERTOKENTYPE_USERNAME) &&
UA_String_equal(&ed->securityPolicyUri, &UA_SECURITY_POLICY_NONE_URI) &&
utp->tokenType != UA_USERTOKENTYPE_ANONYMOUS) {
#ifdef UA_ENABLE_ENCRYPTION
/* Anonymous tokens don't need encryption. All other tokens require
* encryption with the exception of Username/Password if also the
* allowNonePolicyPassword option has been set. The same logic is used
* in selectEndpointAndTokenPolicy (ua_services_session.c). */
if(utp->tokenType != UA_USERTOKENTYPE_ANONYMOUS &&
!(sc->allowNonePolicyPassword && utp->tokenType == UA_USERTOKENTYPE_USERNAME) &&
UA_String_equal(&ed->securityPolicyUri, &UA_SECURITY_POLICY_NONE_URI)) {
UA_SecurityPolicy *encSP = getDefaultEncryptedSecurityPolicy(server);
if(encSP)
res |= UA_String_copy(&encSP->policyUri, &utp->securityPolicyUri);
if(!encSP) {
/* No encrypted SecurityPolicy available */
UA_LOG_WARNING(sc->logging, UA_LOGCATEGORY_CLIENT,
"Removing a UserTokenPolicy that would allow the "
"password to be transmitted without encryption "
"(Can be enabled via config->allowNonePolicyPassword)");
UA_StatusCode res2 =
UA_Array_resize((void **)&ed->userIdentityTokens,
&ed->userIdentityTokensSize,
ed->userIdentityTokensSize - 1,
&UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
(void)res2;
continue;
}
res |= UA_String_copy(&encSP->policyUri, &utp->securityPolicyUri);
}
#endif

/* Append the SecurityMode and SecurityPolicy postfix to the PolicyId to
* make it unique */
Expand Down
76 changes: 45 additions & 31 deletions src/server/ua_services_session.c
Original file line number Diff line number Diff line change
Expand Up @@ -448,8 +448,9 @@ selectEndpointAndTokenPolicy(UA_Server *server, UA_SecureChannel *channel,
const UA_EndpointDescription **ed,
const UA_UserTokenPolicy **utp,
const UA_SecurityPolicy **tokenSp) {
for(size_t i = 0; i < server->config.endpointsSize; ++i) {
const UA_EndpointDescription *desc = &server->config.endpoints[i];
UA_ServerConfig *sc = &server->config;
for(size_t i = 0; i < sc->endpointsSize; ++i) {
const UA_EndpointDescription *desc = &sc->endpoints[i];

/* Match the Security Mode */
if(desc->securityMode != channel->securityMode)
Expand All @@ -464,18 +465,15 @@ selectEndpointAndTokenPolicy(UA_Server *server, UA_SecureChannel *channel,
size_t identPoliciesSize = desc->userIdentityTokensSize;
const UA_UserTokenPolicy *identPolicies = desc->userIdentityTokens;
if(identPoliciesSize == 0) {
identPoliciesSize = server->config.accessControl.userTokenPoliciesSize;
identPolicies = server->config.accessControl.userTokenPolicies;
identPoliciesSize = sc->accessControl.userTokenPoliciesSize;
identPolicies = sc->accessControl.userTokenPolicies;
}

/* Match the UserTokenType */
const UA_DataType *tokenDataType = identityToken->content.decoded.type;
for(size_t j = 0; j < identPoliciesSize ; j++) {
const UA_UserTokenPolicy *pol = &identPolicies[j];

if(!UA_String_equal(&desc->securityPolicyUri, &pol->securityPolicyUri))
continue;

/* Part 4, Section 5.6.3.2, Table 17: A NULL or empty
* UserIdentityToken should be treated as Anonymous */
if(identityToken->encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY &&
Expand Down Expand Up @@ -509,37 +507,53 @@ selectEndpointAndTokenPolicy(UA_Server *server, UA_SecureChannel *channel,
UA_AnonymousIdentityToken *token = (UA_AnonymousIdentityToken*)
identityToken->content.decoded.data;

/* In setCurrentEndPointsArray we prepend the policyId with the
* security mode to make it unique. Remove that here. */
/* Select the SecurityPolicy used to encrypt the token.
* The default is to use the SecurityPolicy of the SecureChannel. */
*tokenSp = channel->securityPolicy;
#ifdef UA_ENABLE_ENCRYPTION
if(identPolicies == sc->accessControl.userTokenPolicies) {
/* If the standard UserTokenPolicies from the AccessControl
* plugin are used, use the same logic as in
* updateEndpointUserIdentityToken (ua_services_discovery.c). */
if(pol->tokenType != UA_USERTOKENTYPE_ANONYMOUS &&
!(sc->allowNonePolicyPassword && pol->tokenType == UA_USERTOKENTYPE_USERNAME) &&
UA_String_equal(&channel->securityPolicy->policyUri, &UA_SECURITY_POLICY_NONE_URI))
*tokenSp = getDefaultEncryptedSecurityPolicy(server);
} else if(pol->securityPolicyUri.length > 0) {
/* Manually defined UserTokenPolicy. Lookup by URI */
*tokenSp = getSecurityPolicyByUri(server, &pol->securityPolicyUri);
}
if(!*tokenSp)
continue;

/* Anonymous tokens don't need encryption. All other tokens require
* encryption with the exception of Username/Password if also the
* allowNonePolicyPassword option has been set. */
if(pol->tokenType != UA_USERTOKENTYPE_ANONYMOUS &&
!(sc->allowNonePolicyPassword && pol->tokenType == UA_USERTOKENTYPE_USERNAME) &&
UA_String_equal(&UA_SECURITY_POLICY_NONE_URI, &(*tokenSp)->policyUri))
continue;
#endif

/* In setCurrentEndPointsArray we prepend the PolicyId with the
* SecurityMode of the endpoint and the postfix of the
* SecurityPolicyUri to make it unique. Check the SecurityPolicyUri
* postfix. */
if(pol->policyId.length > token->policyId.length)
continue;
UA_String tmpId = token->policyId;
tmpId.length = pol->policyId.length;
if(!UA_String_equal(&tmpId, &pol->policyId))
UA_String policyPrefix = token->policyId;
policyPrefix.length = pol->policyId.length;
if(!UA_String_equal(&policyPrefix, &pol->policyId))
continue;

UA_String secPolPostfix = securityPolicyUriPostfix((*tokenSp)->policyUri);
UA_String utPolPostfix = securityPolicyUriPostfix(token->policyId);
if(!UA_String_equal(&secPolPostfix, &utPolPostfix))
continue;

/* Match found */
*ed = desc;
*utp = pol;

/* Set the SecurityPolicy used to encrypt the token. If the
* userTokenPolicy doesn't specify a security policy the security
* policy of the secure channel is used. */
*tokenSp = channel->securityPolicy;
if(pol->securityPolicyUri.length > 0)
*tokenSp = getSecurityPolicyByUri(server, &pol->securityPolicyUri);

/* If the server does not allow unencrypted passwords, select the
* default encrypted policy for the UserTokenPolicy */
#ifdef UA_ENABLE_ENCRYPTION
if(!*tokenSp ||
(!server->config.allowNonePolicyPassword &&
((*tokenSp)->localCertificate.length == 0 ||
UA_String_equal(&UA_SECURITY_POLICY_NONE_URI, &(*tokenSp)->policyUri))))
*tokenSp = getDefaultEncryptedSecurityPolicy(server);
#endif

/* Found SecurityPolicy and UserTokenPoliy. Stop here. */
return;
}
}
Expand Down
13 changes: 11 additions & 2 deletions src/ua_types_encoding_binary.c
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ Array_encodeBinary(Ctx *ctx, const void *src, size_t length, const UA_DataType *
return UA_STATUSCODE_BADINTERNALERROR;
if(length > 0)
signed_length = (i32)length;
else if(src == UA_EMPTY_ARRAY_SENTINEL)
else if(src >= UA_EMPTY_ARRAY_SENTINEL) /* src != NULL */
signed_length = 0;

/* Encode the array length */
Expand Down Expand Up @@ -1252,9 +1252,18 @@ FUNC_DECODE_BINARY(Variant) {
}

/* Decode array dimensions */
if((encodingByte & (u8)UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS) > 0)
if((encodingByte & (u8)UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS) > 0) {
ret |= Array_decodeBinary(ctx, (void **)&dst->arrayDimensions,
&dst->arrayDimensionsSize, &UA_TYPES[UA_TYPES_INT32]);
/* Validate array length against array dimensions */
size_t totalSize = 1;
for(size_t i = 0; i < dst->arrayDimensionsSize; ++i) {
if(dst->arrayDimensions[i] == 0)
ret = UA_STATUSCODE_BADDECODINGERROR;
totalSize *= dst->arrayDimensions[i];
}
UA_CHECK(totalSize == dst->arrayLength, ret = UA_STATUSCODE_BADDECODINGERROR);
}
}

ctx->depth--;
Expand Down
Loading

0 comments on commit d77bcd1

Please sign in to comment.