Skip to content

Commit 1b85c61

Browse files
schroeder-oroulet
authored andcommitted
reject not supported identity tokens
prevents unsupported identity tokens to create a session. For example reject anonymous connection if not set via set_security_IDs, currently this was possible and was a security issue.
1 parent 67f1555 commit 1b85c61

File tree

3 files changed

+27
-0
lines changed

3 files changed

+27
-0
lines changed

opcua/server/internal_server.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ def __init__(self, shelffile=None, user_manager=None, session_cls=None):
7373
self.current_time_node = Node(self.isession, ua.NodeId(ua.ObjectIds.Server_ServerStatus_CurrentTime))
7474
self._address_space_fixes()
7575
self.setup_nodes()
76+
self.supported_tokens = []
7677

7778
@property
7879
def thread_loop(self):
@@ -346,6 +347,10 @@ def activate_session(self, params):
346347
result.Results.append(ua.StatusCode())
347348
self.state = SessionState.Activated
348349
id_token = params.UserIdentityToken
350+
# Check if security policy is supported
351+
if not isinstance(id_token, self.iserver.supported_tokens):
352+
self.logger.error('Rejected active session UserIdentityToken not supported')
353+
raise utils.ServiceError(ua.StatusCodes.BadIdentityTokenRejected)
349354
if isinstance(id_token, ua.UserNameIdentityToken):
350355
if self.user_manager.check_user_token(self, id_token) == False:
351356
raise utils.ServiceError(ua.StatusCodes.BadUserAccessDenied)

opcua/server/server.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,23 +263,27 @@ def _setup_server_nodes(self):
263263

264264
def _set_endpoints(self, policy=ua.SecurityPolicy, mode=ua.MessageSecurityMode.None_):
265265
idtokens = []
266+
supported_token_classes = []
266267
if "Anonymous" in self._policyIDs:
267268
idtoken = ua.UserTokenPolicy()
268269
idtoken.PolicyId = 'anonymous'
269270
idtoken.TokenType = ua.UserTokenType.Anonymous
270271
idtokens.append(idtoken)
272+
supported_token_classes.append(ua.AnonymousIdentityToken)
271273

272274
if "Basic256Sha256" in self._policyIDs:
273275
idtoken = ua.UserTokenPolicy()
274276
idtoken.PolicyId = 'certificate_basic256sha256'
275277
idtoken.TokenType = ua.UserTokenType.Certificate
276278
idtokens.append(idtoken)
279+
supported_token_classes.append(ua.X509IdentityToken)
277280

278281
if "Username" in self._policyIDs:
279282
idtoken = ua.UserTokenPolicy()
280283
idtoken.PolicyId = 'username'
281284
idtoken.TokenType = ua.UserTokenType.UserName
282285
idtokens.append(idtoken)
286+
supported_token_classes.append(ua.UserNameIdentityToken)
283287

284288
appdesc = ua.ApplicationDescription()
285289
appdesc.ApplicationName = ua.LocalizedText(self.name)
@@ -299,6 +303,7 @@ def _set_endpoints(self, policy=ua.SecurityPolicy, mode=ua.MessageSecurityMode.N
299303
edp.TransportProfileUri = 'http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary'
300304
edp.SecurityLevel = 0
301305
self.iserver.add_endpoint(edp)
306+
self.iserver.supported_tokens = tuple(supported_token_classes)
302307

303308
def set_server_name(self, name):
304309
self.name = name

tests/tests_crypto_connect.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
port_num1 = 48515
1818
port_num2 = 48512
1919
port_num3 = 48510
20+
port_num4 = 48533
2021

2122
@unittest.skipIf(disable_crypto_tests, "crypto not available")
2223
class TestCryptoConnect(unittest.TestCase):
@@ -51,6 +52,14 @@ def setUpClass(cls):
5152
cls.srv_crypto2.load_private_key("examples/private-key-3072-example.pem")
5253
cls.srv_crypto2.start()
5354

55+
cls.srv_crypto_no_anoymous = Server()
56+
cls.uri_crypto_no_anoymous = 'opc.tcp://127.0.0.1:{0:d}'.format(port_num4)
57+
cls.srv_crypto_no_anoymous.set_endpoint(cls.uri_crypto_no_anoymous)
58+
cls.srv_crypto_no_anoymous.load_certificate("examples/certificate-3072-example.der")
59+
cls.srv_crypto_no_anoymous.load_private_key("examples/private-key-3072-example.pem")
60+
cls.srv_crypto_no_anoymous.set_security_IDs(["Username", "Basic256Sha256"])
61+
cls.srv_crypto_no_anoymous.start()
62+
5463
@classmethod
5564
def tearDownClass(cls):
5665
# stop the server
@@ -131,3 +140,11 @@ def test_basic256sha56_encrypt_fail(self):
131140
None,
132141
ua.MessageSecurityMode.None_
133142
)
143+
144+
def test_anonymous_rejection(self):
145+
# FIXME: how to make it fail???
146+
clt = Client(self.uri_crypto_no_anoymous)
147+
with self.assertRaises(ua.UaError) as exc_info:
148+
clt.connect()
149+
clt.disconnect()
150+
assert ua.StatusCodes.BadIdentityTokenRejected == exc_info.type.code

0 commit comments

Comments
 (0)