Commit 4498a5ca authored by ORD's avatar ORD

Merge pull request #138 from alkor/fix-password-encryption

Support passwords with SecurityPolicy#None (plain text)
parents be502ffb bdc8c205
...@@ -381,14 +381,23 @@ class Client(object): ...@@ -381,14 +381,23 @@ class Client(object):
else: else:
params.UserIdentityToken = ua.UserNameIdentityToken() params.UserIdentityToken = ua.UserNameIdentityToken()
params.UserIdentityToken.UserName = username params.UserIdentityToken.UserName = username
if self.server_url.password: policy_uri = self.server_policy_uri(ua.UserTokenType.UserName)
if not policy_uri or policy_uri == security_policies.POLICY_NONE_URI:
# see specs part 4, 7.36.3: if the token is NOT encrypted,
# then the password only contains UTF-8 encoded password
# and EncryptionAlgorithm is null
if self.server_url.password:
self.logger.warning("Sending plain-text password")
params.UserIdentityToken.Password = password
params.UserIdentityToken.EncryptionAlgorithm = ''
elif self.server_url.password:
pubkey = uacrypto.x509_from_der(self.security_policy.server_certificate).public_key() pubkey = uacrypto.x509_from_der(self.security_policy.server_certificate).public_key()
# see specs part 4, 7.36.3: if the token is encrypted, password # see specs part 4, 7.36.3: if the token is encrypted, password
# shall be converted to UTF-8 and serialized with server nonce # shall be converted to UTF-8 and serialized with server nonce
etoken = ua.pack_bytes(bytes(password, "utf8") + self._server_nonce) etoken = ua.pack_bytes(bytes(password, "utf8") + self._server_nonce)
(data, uri) = security_policies.encrypt_asymmetric(pubkey, (data, uri) = security_policies.encrypt_asymmetric(pubkey,
etoken, etoken,
self.server_policy_uri(ua.UserTokenType.UserName)) policy_uri)
params.UserIdentityToken.Password = data params.UserIdentityToken.Password = data
params.UserIdentityToken.EncryptionAlgorithm = uri params.UserIdentityToken.EncryptionAlgorithm = uri
params.UserIdentityToken.PolicyId = self.server_policy_id(ua.UserTokenType.UserName, b"username_basic256") params.UserIdentityToken.PolicyId = self.server_policy_id(ua.UserTokenType.UserName, b"username_basic256")
......
...@@ -9,6 +9,9 @@ except ImportError: ...@@ -9,6 +9,9 @@ except ImportError:
CRYPTOGRAPHY_AVAILABLE = False CRYPTOGRAPHY_AVAILABLE = False
POLICY_NONE_URI = 'http://opcfoundation.org/UA/SecurityPolicy#None'
def require_cryptography(obj): def require_cryptography(obj):
""" """
Raise exception if cryptography module is not available. Raise exception if cryptography module is not available.
...@@ -448,4 +451,6 @@ def encrypt_asymmetric(pubkey, data, policy_uri): ...@@ -448,4 +451,6 @@ def encrypt_asymmetric(pubkey, data, policy_uri):
if policy_uri == cls.URI: if policy_uri == cls.URI:
return (cls.encrypt_asymmetric(pubkey, data), return (cls.encrypt_asymmetric(pubkey, data),
cls.AsymmetricEncryptionURI) cls.AsymmetricEncryptionURI)
if not policy_uri or policy_uri == POLICY_NONE_URI:
return (data, '')
raise UaError("Unsupported security policy `{}`".format(policy_uri)) raise UaError("Unsupported security policy `{}`".format(policy_uri))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment