Exemplo n.º 1
0
        /// <summary cref="IUserIdentity.GetIdentityToken" />
        public UserIdentityToken GetIdentityToken()
        {
            AnonymousIdentityToken token = new AnonymousIdentityToken();

            token.PolicyId = m_policyId;
            return(token);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Initializes the object with a UA identity token
        /// </summary>
        private void Initialize(UserIdentityToken token)
        {
            if (token == null)
            {
                throw new ArgumentNullException("token");
            }

            m_policyId = token.PolicyId;

            UserNameIdentityToken usernameToken = token as UserNameIdentityToken;

            if (usernameToken != null)
            {
                Initialize(new UserNameSecurityToken(usernameToken.UserName, usernameToken.DecryptedPassword));
                return;
            }

            X509IdentityToken x509Token = token as X509IdentityToken;

            if (x509Token != null)
            {
                X509Certificate2 certificate = CertificateFactory.Create(x509Token.CertificateData, true);
                Initialize(new X509SecurityToken(certificate));
                return;
            }

            IssuedIdentityToken wssToken = token as IssuedIdentityToken;

            if (wssToken != null)
            {
                Initialize(wssToken, WSSecurityTokenSerializer.DefaultInstance, null);
                return;
            }

            AnonymousIdentityToken anonymousToken = token as AnonymousIdentityToken;

            if (anonymousToken != null)
            {
                m_tokenType       = UserTokenType.Anonymous;
                m_issuedTokenType = null;
                m_displayName     = "Anonymous";
                m_token           = null;
                return;
            }

            throw new ArgumentException("Unrecognized UA user identity token type.", "token");
        }
Exemplo n.º 3
0
        /// <summary>
        /// Initializes the object with a UA identity token
        /// </summary>
        private void Initialize(UserIdentityToken token)
        {
            if (token == null)
            {
                throw new ArgumentNullException("token");
            }

            m_policyId = token.PolicyId;

            AnonymousIdentityToken anonymousToken = token as AnonymousIdentityToken;

            if (anonymousToken != null)
            {
                m_tokenType       = UserTokenType.Anonymous;
                m_issuedTokenType = null;
                m_displayName     = "Anonymous";
                return;
            }

            throw new ArgumentException("Unrecognized UA user identity token type.", "token");
        }
Exemplo n.º 4
0
        /// <summary>
        /// Initializes the object as an anonymous user.
        /// </summary>
        public UserIdentity()
        {
            AnonymousIdentityToken token = new AnonymousIdentityToken();

            Initialize(token);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Initializes the object with a UA identity token
        /// </summary>
        private void Initialize(UserIdentityToken token)
        {
            if (token == null)
            {
                throw new ArgumentNullException("token");
            }

            m_token = token;

            UserNameIdentityToken usernameToken = token as UserNameIdentityToken;

            if (usernameToken != null)
            {
                m_tokenType       = UserTokenType.UserName;
                m_issuedTokenType = null;
                m_displayName     = usernameToken.UserName;
                return;
            }

            X509IdentityToken x509Token = token as X509IdentityToken;

            if (x509Token != null)
            {
                m_tokenType       = UserTokenType.Certificate;
                m_issuedTokenType = null;
                if (x509Token.Certificate != null)
                {
                    m_displayName = x509Token.Certificate.Subject;
                }
                else
                {
                    X509Certificate2 cert = CertificateFactory.Create(x509Token.CertificateData, true);
                    m_displayName = cert.Subject;
                }
                return;
            }

            IssuedIdentityToken issuedToken = token as IssuedIdentityToken;

            if (issuedToken != null)
            {
                if (issuedToken.IssuedTokenType == Ua.IssuedTokenType.JWT)
                {
                    if (issuedToken.DecryptedTokenData == null || issuedToken.DecryptedTokenData.Length == 0)
                    {
                        throw new ArgumentException("JSON Web Token has no data associated with it.", "token");
                    }

                    m_tokenType       = UserTokenType.IssuedToken;
                    m_issuedTokenType = new XmlQualifiedName("", Opc.Ua.Profiles.JwtUserToken);
                    m_displayName     = "JWT";
                    return;
                }
                else
                {
                    throw new NotSupportedException("Only JWT Issued Tokens are supported!");
                }
            }

            AnonymousIdentityToken anonymousToken = token as AnonymousIdentityToken;

            if (anonymousToken != null)
            {
                m_tokenType       = UserTokenType.Anonymous;
                m_issuedTokenType = null;
                m_displayName     = "Anonymous";
                return;
            }

            throw new ArgumentException("Unrecognized UA user identity token type.", "token");
        }
Exemplo n.º 6
0
        /// <inheritdoc/>
        protected override async Task OnOpenAsync(CancellationToken token = default(CancellationToken))
        {
            this.logger?.LogInformation($"Opening session channel with endpoint '{this.RemoteEndpoint.EndpointUrl}'.");
            this.logger?.LogInformation($"SecurityPolicy: '{this.RemoteEndpoint.SecurityPolicyUri}'.");
            this.logger?.LogInformation($"SecurityMode: '{this.RemoteEndpoint.SecurityMode}'.");
            this.logger?.LogInformation($"UserIdentity: '{this.UserIdentity}'.");

            await base.OnOpenAsync(token).ConfigureAwait(false);

            token.ThrowIfCancellationRequested();

            // if SessionId is provided then we skip the CreateSessionRequest and go directly to (re)ActivateSession.
            // requires from previous Session: SessionId, AuthenticationToken, RemoteNonce
            if (this.SessionId == null)
            {
                var localNonce           = this.RemoteEndpoint.SecurityMode != MessageSecurityMode.None ? this.GetNextNonce(NonceLength) : null;
                var localCertificate     = this.RemoteEndpoint.SecurityMode != MessageSecurityMode.None ? this.LocalCertificate : null;
                var createSessionRequest = new CreateSessionRequest
                {
                    ClientDescription       = this.LocalDescription,
                    EndpointUrl             = this.RemoteEndpoint.EndpointUrl,
                    SessionName             = this.LocalDescription.ApplicationName,
                    ClientNonce             = localNonce,
                    ClientCertificate       = localCertificate,
                    RequestedSessionTimeout = this.options.SessionTimeout,
                    MaxResponseMessageSize  = this.RemoteMaxMessageSize
                };

                var createSessionResponse = await this.CreateSessionAsync(createSessionRequest).ConfigureAwait(false);

                this.SessionId           = createSessionResponse.SessionId;
                this.AuthenticationToken = createSessionResponse.AuthenticationToken;
                this.RemoteNonce         = createSessionResponse.ServerNonce;

                // verify the server's certificate is the same as the certificate from the selected endpoint.
                if (this.RemoteEndpoint.ServerCertificate != null && !this.RemoteEndpoint.ServerCertificate.SequenceEqual(createSessionResponse.ServerCertificate))
                {
                    throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Server did not return the same certificate used to create the channel.");
                }

                // verify the server's signature.
                ISigner verifier = null;
                bool    verified = false;

                switch (this.RemoteEndpoint.SecurityPolicyUri)
                {
                case SecurityPolicyUris.Basic128Rsa15:
                case SecurityPolicyUris.Basic256:
                    verifier = SignerUtilities.GetSigner("SHA-1withRSA");
                    verifier.Init(false, this.RemotePublicKey);
                    verifier.BlockUpdate(localCertificate, 0, localCertificate.Length);
                    verifier.BlockUpdate(localNonce, 0, localNonce.Length);
                    verified = verifier.VerifySignature(createSessionResponse.ServerSignature.Signature);
                    break;

                case SecurityPolicyUris.Basic256Sha256:
                case SecurityPolicyUris.Aes128_Sha256_RsaOaep:
                    verifier = SignerUtilities.GetSigner("SHA-256withRSA");
                    verifier.Init(false, this.RemotePublicKey);
                    verifier.BlockUpdate(localCertificate, 0, localCertificate.Length);
                    verifier.BlockUpdate(localNonce, 0, localNonce.Length);
                    verified = verifier.VerifySignature(createSessionResponse.ServerSignature.Signature);
                    break;

                case SecurityPolicyUris.Aes256_Sha256_RsaPss:
                    verifier = SignerUtilities.GetSigner("SHA-256withRSAandMGF1");
                    verifier.Init(false, this.RemotePublicKey);
                    verifier.BlockUpdate(localCertificate, 0, localCertificate.Length);
                    verifier.BlockUpdate(localNonce, 0, localNonce.Length);
                    verified = verifier.VerifySignature(createSessionResponse.ServerSignature.Signature);
                    break;

                default:
                    verified = true;
                    break;
                }

                verifier = null;
                if (!verified)
                {
                    throw new ServiceResultException(StatusCodes.BadApplicationSignatureInvalid, "Server did not provide a correct signature for the nonce data provided by the client.");
                }
            }

            // create client signature
            SignatureData clientSignature = null;
            ISigner       signer          = null;

            switch (this.RemoteEndpoint.SecurityPolicyUri)
            {
            case SecurityPolicyUris.Basic128Rsa15:
            case SecurityPolicyUris.Basic256:
                signer = SignerUtilities.GetSigner("SHA-1withRSA");
                signer.Init(true, this.LocalPrivateKey);
                signer.BlockUpdate(this.RemoteEndpoint.ServerCertificate, 0, this.RemoteEndpoint.ServerCertificate.Length);
                signer.BlockUpdate(this.RemoteNonce, 0, this.RemoteNonce.Length);
                clientSignature = new SignatureData
                {
                    Signature = signer.GenerateSignature(),
                    Algorithm = RsaSha1Signature,
                };

                break;

            case SecurityPolicyUris.Basic256Sha256:
            case SecurityPolicyUris.Aes128_Sha256_RsaOaep:
                signer = SignerUtilities.GetSigner("SHA-256withRSA");
                signer.Init(true, this.LocalPrivateKey);
                signer.BlockUpdate(this.RemoteEndpoint.ServerCertificate, 0, this.RemoteEndpoint.ServerCertificate.Length);
                signer.BlockUpdate(this.RemoteNonce, 0, this.RemoteNonce.Length);
                clientSignature = new SignatureData
                {
                    Signature = signer.GenerateSignature(),
                    Algorithm = RsaSha256Signature,
                };

                break;

            case SecurityPolicyUris.Aes256_Sha256_RsaPss:
                signer = SignerUtilities.GetSigner("SHA-256withRSAandMGF1");
                signer.Init(true, this.LocalPrivateKey);
                signer.BlockUpdate(this.RemoteEndpoint.ServerCertificate, 0, this.RemoteEndpoint.ServerCertificate.Length);
                signer.BlockUpdate(this.RemoteNonce, 0, this.RemoteNonce.Length);
                clientSignature = new SignatureData
                {
                    Signature = signer.GenerateSignature(),
                    Algorithm = RsaPssSha256Signature,
                };

                break;

            default:
                clientSignature = new SignatureData();
                break;
            }

            signer = null;

            // supported UserIdentityToken types are AnonymousIdentityToken, UserNameIdentityToken, IssuedIdentityToken, X509IdentityToken
            UserIdentityToken identityToken  = null;
            SignatureData     tokenSignature = null;

            // if UserIdentity type is IssuedIdentity
            if (this.UserIdentity is IssuedIdentity)
            {
                var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.IssuedToken);
                if (tokenPolicy == null)
                {
                    throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected);
                }

                var             issuedIdentity  = (IssuedIdentity)this.UserIdentity;
                int             plainTextLength = issuedIdentity.TokenData.Length + this.RemoteNonce.Length;
                IBufferedCipher encryptor;
                byte[]          cipherText;
                int             pos;

                var secPolicyUri = tokenPolicy.SecurityPolicyUri ?? this.RemoteEndpoint.SecurityPolicyUri;
                switch (secPolicyUri)
                {
                case SecurityPolicyUris.Basic128Rsa15:
                    encryptor = CipherUtilities.GetCipher("RSA//PKCS1Padding");
                    encryptor.Init(true, this.RemotePublicKey);
                    cipherText    = new byte[encryptor.GetOutputSize(4 + plainTextLength)];
                    pos           = encryptor.ProcessBytes(BitConverter.GetBytes(plainTextLength), cipherText, 0);
                    pos           = encryptor.ProcessBytes(issuedIdentity.TokenData, cipherText, pos);
                    pos           = encryptor.DoFinal(this.RemoteNonce, cipherText, pos);
                    identityToken = new IssuedIdentityToken
                    {
                        TokenData           = cipherText,
                        EncryptionAlgorithm = RsaV15KeyWrap,
                        PolicyId            = tokenPolicy.PolicyId
                    };

                    break;

                case SecurityPolicyUris.Basic256:
                case SecurityPolicyUris.Basic256Sha256:
                case SecurityPolicyUris.Aes128_Sha256_RsaOaep:
                    encryptor = CipherUtilities.GetCipher("RSA//OAEPPADDING");
                    encryptor.Init(true, this.RemotePublicKey);
                    cipherText    = new byte[encryptor.GetOutputSize(4 + plainTextLength)];
                    pos           = encryptor.ProcessBytes(BitConverter.GetBytes(plainTextLength), cipherText, 0);
                    pos           = encryptor.ProcessBytes(issuedIdentity.TokenData, cipherText, pos);
                    pos           = encryptor.DoFinal(this.RemoteNonce, cipherText, pos);
                    identityToken = new IssuedIdentityToken
                    {
                        TokenData           = cipherText,
                        EncryptionAlgorithm = RsaOaepKeyWrap,
                        PolicyId            = tokenPolicy.PolicyId
                    };

                    break;

                case SecurityPolicyUris.Aes256_Sha256_RsaPss:
                    encryptor = CipherUtilities.GetCipher("RSA//OAEPWITHSHA256ANDMGF1PADDING");
                    encryptor.Init(true, this.RemotePublicKey);
                    cipherText    = new byte[encryptor.GetOutputSize(4 + plainTextLength)];
                    pos           = encryptor.ProcessBytes(BitConverter.GetBytes(plainTextLength), cipherText, 0);
                    pos           = encryptor.ProcessBytes(issuedIdentity.TokenData, cipherText, pos);
                    pos           = encryptor.DoFinal(this.RemoteNonce, cipherText, pos);
                    identityToken = new IssuedIdentityToken
                    {
                        TokenData           = cipherText,
                        EncryptionAlgorithm = RsaOaepSha256KeyWrap,
                        PolicyId            = tokenPolicy.PolicyId
                    };

                    break;

                default:
                    identityToken = new IssuedIdentityToken
                    {
                        TokenData           = issuedIdentity.TokenData,
                        EncryptionAlgorithm = null,
                        PolicyId            = tokenPolicy.PolicyId
                    };
                    break;
                }

                tokenSignature = new SignatureData();
                encryptor      = null;
                cipherText     = null;
            }

            // if UserIdentity type is X509Identity
            else if (this.UserIdentity is X509Identity)
            {
                var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.Certificate);
                if (tokenPolicy == null)
                {
                    throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected);
                }

                var x509Identity = (X509Identity)this.UserIdentity;
                identityToken = new X509IdentityToken {
                    CertificateData = x509Identity.Certificate?.GetEncoded(), PolicyId = tokenPolicy.PolicyId
                };

                var secPolicyUri = tokenPolicy.SecurityPolicyUri ?? this.RemoteEndpoint.SecurityPolicyUri;
                switch (secPolicyUri)
                {
                case SecurityPolicyUris.Basic128Rsa15:
                case SecurityPolicyUris.Basic256:
                    signer = SignerUtilities.GetSigner("SHA-1withRSA");
                    signer.Init(true, x509Identity.PrivateKey);
                    signer.BlockUpdate(this.RemoteEndpoint.ServerCertificate, 0, this.RemoteEndpoint.ServerCertificate.Length);
                    signer.BlockUpdate(this.RemoteNonce, 0, this.RemoteNonce.Length);
                    tokenSignature = new SignatureData
                    {
                        Signature = signer.GenerateSignature(),
                        Algorithm = RsaSha1Signature,
                    };

                    break;

                case SecurityPolicyUris.Basic256Sha256:
                case SecurityPolicyUris.Aes128_Sha256_RsaOaep:
                    signer = SignerUtilities.GetSigner("SHA-256withRSA");
                    signer.Init(true, x509Identity.PrivateKey);
                    signer.BlockUpdate(this.RemoteEndpoint.ServerCertificate, 0, this.RemoteEndpoint.ServerCertificate.Length);
                    signer.BlockUpdate(this.RemoteNonce, 0, this.RemoteNonce.Length);
                    tokenSignature = new SignatureData
                    {
                        Signature = signer.GenerateSignature(),
                        Algorithm = RsaSha256Signature,
                    };
                    break;

                case SecurityPolicyUris.Aes256_Sha256_RsaPss:
                    signer = SignerUtilities.GetSigner("SHA-256withRSAandMGF1");
                    signer.Init(true, x509Identity.PrivateKey);
                    signer.BlockUpdate(this.RemoteEndpoint.ServerCertificate, 0, this.RemoteEndpoint.ServerCertificate.Length);
                    signer.BlockUpdate(this.RemoteNonce, 0, this.RemoteNonce.Length);
                    tokenSignature = new SignatureData
                    {
                        Signature = signer.GenerateSignature(),
                        Algorithm = RsaSha256Signature,
                    };
                    break;

                default:
                    tokenSignature = new SignatureData();
                    break;
                }

                signer = null;
            }

            // if UserIdentity type is UserNameIdentity
            else if (this.UserIdentity is UserNameIdentity)
            {
                var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.UserName);
                if (tokenPolicy == null)
                {
                    throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected);
                }

                var    userNameIdentity = (UserNameIdentity)this.UserIdentity;
                byte[] passwordBytes    = userNameIdentity.Password != null?System.Text.Encoding.UTF8.GetBytes(userNameIdentity.Password) : new byte[0];

                int             plainTextLength = passwordBytes.Length + this.RemoteNonce.Length;
                IBufferedCipher encryptor;
                byte[]          cipherText;
                int             pos;

                var secPolicyUri = tokenPolicy.SecurityPolicyUri ?? this.RemoteEndpoint.SecurityPolicyUri;
                switch (secPolicyUri)
                {
                case SecurityPolicyUris.Basic128Rsa15:
                    encryptor = CipherUtilities.GetCipher("RSA//PKCS1Padding");
                    encryptor.Init(true, this.RemotePublicKey);
                    cipherText    = new byte[encryptor.GetOutputSize(4 + plainTextLength)];
                    pos           = encryptor.ProcessBytes(BitConverter.GetBytes(plainTextLength), cipherText, 0);
                    pos           = encryptor.ProcessBytes(passwordBytes, cipherText, pos);
                    pos           = encryptor.DoFinal(this.RemoteNonce, cipherText, pos);
                    identityToken = new UserNameIdentityToken
                    {
                        UserName            = userNameIdentity.UserName,
                        Password            = cipherText,
                        EncryptionAlgorithm = RsaV15KeyWrap,
                        PolicyId            = tokenPolicy.PolicyId
                    };

                    break;

                case SecurityPolicyUris.Basic256:
                case SecurityPolicyUris.Basic256Sha256:
                case SecurityPolicyUris.Aes128_Sha256_RsaOaep:
                    encryptor = CipherUtilities.GetCipher("RSA//OAEPPADDING");
                    encryptor.Init(true, this.RemotePublicKey);
                    cipherText    = new byte[encryptor.GetOutputSize(4 + plainTextLength)];
                    pos           = encryptor.ProcessBytes(BitConverter.GetBytes(plainTextLength), cipherText, 0);
                    pos           = encryptor.ProcessBytes(passwordBytes, cipherText, pos);
                    pos           = encryptor.DoFinal(this.RemoteNonce, cipherText, pos);
                    identityToken = new UserNameIdentityToken
                    {
                        UserName            = userNameIdentity.UserName,
                        Password            = cipherText,
                        EncryptionAlgorithm = RsaOaepKeyWrap,
                        PolicyId            = tokenPolicy.PolicyId
                    };

                    break;

                case SecurityPolicyUris.Aes256_Sha256_RsaPss:
                    encryptor = CipherUtilities.GetCipher("RSA//OAEPWITHSHA256ANDMGF1PADDING");
                    encryptor.Init(true, this.RemotePublicKey);
                    cipherText    = new byte[encryptor.GetOutputSize(4 + plainTextLength)];
                    pos           = encryptor.ProcessBytes(BitConverter.GetBytes(plainTextLength), cipherText, 0);
                    pos           = encryptor.ProcessBytes(passwordBytes, cipherText, pos);
                    pos           = encryptor.DoFinal(this.RemoteNonce, cipherText, pos);
                    identityToken = new UserNameIdentityToken
                    {
                        UserName            = userNameIdentity.UserName,
                        Password            = cipherText,
                        EncryptionAlgorithm = RsaOaepSha256KeyWrap,
                        PolicyId            = tokenPolicy.PolicyId
                    };

                    break;

                default:
                    identityToken = new UserNameIdentityToken
                    {
                        UserName            = userNameIdentity.UserName,
                        Password            = passwordBytes,
                        EncryptionAlgorithm = null,
                        PolicyId            = tokenPolicy.PolicyId
                    };
                    break;
                }

                tokenSignature = new SignatureData();
                passwordBytes  = null;
                encryptor      = null;
                cipherText     = null;
            }

            // if UserIdentity type is AnonymousIdentity or null
            else
            {
                var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.Anonymous);
                if (tokenPolicy == null)
                {
                    throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected);
                }

                identityToken = new AnonymousIdentityToken {
                    PolicyId = tokenPolicy.PolicyId
                };
                tokenSignature = new SignatureData();
            }

            var activateSessionRequest = new ActivateSessionRequest
            {
                ClientSignature    = clientSignature,
                LocaleIds          = new[] { CultureInfo.CurrentUICulture.TwoLetterISOLanguageName },
                UserIdentityToken  = identityToken,
                UserTokenSignature = tokenSignature
            };
            var activateSessionResponse = await this.ActivateSessionAsync(activateSessionRequest).ConfigureAwait(false);

            this.RemoteNonce = activateSessionResponse.ServerNonce;

            // fetch namespace array, etc.
            var readValueIds = new ReadValueId[]
            {
                new ReadValueId
                {
                    NodeId      = NodeId.Parse(VariableIds.Server_NamespaceArray),
                    AttributeId = AttributeIds.Value
                },
                new ReadValueId
                {
                    NodeId      = NodeId.Parse(VariableIds.Server_ServerArray),
                    AttributeId = AttributeIds.Value
                }
            };
            var readRequest = new ReadRequest
            {
                NodesToRead = readValueIds
            };

            var readResponse = await this.ReadAsync(readRequest).ConfigureAwait(false);

            if (readResponse.Results.Length == 2)
            {
                if (StatusCode.IsGood(readResponse.Results[0].StatusCode))
                {
                    this.NamespaceUris.Clear();
                    this.NamespaceUris.AddRange(readResponse.Results[0].GetValueOrDefault <string[]>());
                }

                if (StatusCode.IsGood(readResponse.Results[1].StatusCode))
                {
                    this.ServerUris.Clear();
                    this.ServerUris.AddRange(readResponse.Results[1].GetValueOrDefault <string[]>());
                }
            }

            // create the keep alive subscription.
            var subscriptionRequest = new CreateSubscriptionRequest
            {
                RequestedPublishingInterval = DefaultPublishingInterval,
                RequestedMaxKeepAliveCount  = DefaultKeepaliveCount,
                RequestedLifetimeCount      = DefaultKeepaliveCount * 3,
                PublishingEnabled           = true,
            };
            var subscriptionResponse = await this.CreateSubscriptionAsync(subscriptionRequest).ConfigureAwait(false);

            // link up the dataflow blocks
            var id        = subscriptionResponse.SubscriptionId;
            var linkToken = this.LinkTo(this.actionBlock, pr => pr.SubscriptionId == id);

            // start publishing.
            this.stateMachineTask = Task.Run(() => this.StateMachineAsync(this.stateMachineCts.Token));
        }
Exemplo n.º 7
0
        /// <summary>
        /// Validates the identity token supplied by the client.
        /// </summary>
        private UserIdentityToken ValidateUserIdentityToken(
            ExtensionObject identityToken,
            SignatureData userTokenSignature,
            out UserTokenPolicy policy)
        {
            policy = null;

            // check for empty token.
            if (identityToken == null || identityToken.Body == null)
            {
                // not changing the token if already activated.
                if (m_activated)
                {
                    return(null);
                }

                // check if an anonymous login is permitted.
                if (m_endpoint.UserIdentityTokens != null && m_endpoint.UserIdentityTokens.Count > 0)
                {
                    bool found = false;

                    for (int ii = 0; ii < m_endpoint.UserIdentityTokens.Count; ii++)
                    {
                        if (m_endpoint.UserIdentityTokens[ii].TokenType == UserTokenType.Anonymous)
                        {
                            found  = true;
                            policy = m_endpoint.UserIdentityTokens[ii];
                            break;
                        }
                    }

                    if (!found)
                    {
                        throw ServiceResultException.Create(StatusCodes.BadUserAccessDenied, "Anonymous user token policy not supported.");
                    }
                }

                // create an anonymous token to use for subsequent validation.
                AnonymousIdentityToken anonymousToken = new AnonymousIdentityToken();
                anonymousToken.PolicyId = policy.PolicyId;
                return(anonymousToken);
            }

            UserIdentityToken token = null;

            // check for unrecognized token.
            if (!typeof(UserIdentityToken).IsInstanceOfType(identityToken.Body))
            {
                //handle the use case when the UserIdentityToken is binary encoded over xml message encoding
                if (identityToken.Encoding == ExtensionObjectEncoding.Binary && typeof(byte[]).IsInstanceOfType(identityToken.Body))
                {
                    UserIdentityToken newToken = BaseVariableState.DecodeExtensionObject(null, typeof(UserIdentityToken), identityToken, false) as UserIdentityToken;
                    if (newToken == null)
                    {
                        throw ServiceResultException.Create(StatusCodes.BadUserAccessDenied, "Invalid user identity token provided.");
                    }

                    policy = m_endpoint.FindUserTokenPolicy(newToken.PolicyId);
                    if (policy == null)
                    {
                        throw ServiceResultException.Create(StatusCodes.BadUserAccessDenied, "User token policy not supported.", "Opc.Ua.Server.Session.ValidateUserIdentityToken");
                    }
                    switch (policy.TokenType)
                    {
                    case UserTokenType.Anonymous:
                        token = BaseVariableState.DecodeExtensionObject(null, typeof(AnonymousIdentityToken), identityToken, true) as AnonymousIdentityToken;
                        break;

                    case UserTokenType.UserName:
                        token = BaseVariableState.DecodeExtensionObject(null, typeof(UserNameIdentityToken), identityToken, true) as UserNameIdentityToken;
                        break;

                    case UserTokenType.Certificate:
                        token = BaseVariableState.DecodeExtensionObject(null, typeof(X509IdentityToken), identityToken, true) as X509IdentityToken;
                        break;

                    case UserTokenType.IssuedToken:
                        token = BaseVariableState.DecodeExtensionObject(null, typeof(IssuedIdentityToken), identityToken, true) as IssuedIdentityToken;
                        break;

                    default:
                        throw ServiceResultException.Create(StatusCodes.BadUserAccessDenied, "Invalid user identity token provided.");
                    }
                }
                else
                {
                    throw ServiceResultException.Create(StatusCodes.BadUserAccessDenied, "Invalid user identity token provided.");
                }
            }
            else
            {
                // get the token.
                token = (UserIdentityToken)identityToken.Body;
            }

            // find the user token policy.
            policy = m_endpoint.FindUserTokenPolicy(token.PolicyId);

            if (policy == null)
            {
                throw ServiceResultException.Create(StatusCodes.BadIdentityTokenInvalid, "User token policy not supported.");
            }

            // determine the security policy uri.
            string securityPolicyUri = policy.SecurityPolicyUri;

            if (String.IsNullOrEmpty(securityPolicyUri))
            {
                securityPolicyUri = m_endpoint.SecurityPolicyUri;
            }

            if (ServerBase.RequireEncryption(m_endpoint))
            {
                // decrypt the token.
                if (m_serverCertificate == null)
                {
                    m_serverCertificate = CertificateFactory.Create(m_endpoint.ServerCertificate, true);

                    // check for valid certificate.
                    if (m_serverCertificate == null)
                    {
                        throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "ApplicationCertificate cannot be found.");
                    }
                }

                try
                {
                    token.Decrypt(m_serverCertificate, m_serverNonce, securityPolicyUri);
                }
                catch (Exception e)
                {
                    if (e is ServiceResultException)
                    {
                        throw;
                    }

                    throw ServiceResultException.Create(StatusCodes.BadIdentityTokenInvalid, e, "Could not decrypt identity token.");
                }

                // verify the signature.
                if (securityPolicyUri != SecurityPolicies.None)
                {
                    byte[] dataToSign = Utils.Append(m_serverCertificate.RawData, m_serverNonce);

                    if (!token.Verify(dataToSign, userTokenSignature, securityPolicyUri))
                    {
                        throw new ServiceResultException(StatusCodes.BadUserSignatureInvalid, "Invalid user signature!");
                    }
                }
            }

            // validate user identity token.
            return(token);
        }
 /// <summary cref="IUserIdentity.GetIdentityToken" />
 public UserIdentityToken GetIdentityToken()
 {
     AnonymousIdentityToken token = new AnonymousIdentityToken();
     token.PolicyId = m_policyId;
     return token;
 }
        /// <summary>
        /// Validates the identity token supplied by the client.
        /// </summary>
        private UserIdentityToken ValidateUserIdentityToken(
            ExtensionObject identityToken,
            SignatureData userTokenSignature,
            out UserTokenPolicy policy )
        {
            policy = null;

            // check for empty token.
            if (identityToken == null || identityToken.Body == null)
            {
                // not changing the token if already activated.
                if (m_activated)
                {
                    return null;
                }

                // check if an anonymous login is permitted.
                if (m_endpoint.UserIdentityTokens != null && m_endpoint.UserIdentityTokens.Count > 0)
                {
                    bool found = false;

                    for (int ii = 0; ii < m_endpoint.UserIdentityTokens.Count; ii++)
                    {
                        if (m_endpoint.UserIdentityTokens[ii].TokenType == UserTokenType.Anonymous)
                        {
                            found = true;
                            policy = m_endpoint.UserIdentityTokens[ii];
                            break;
                        }
                    }

                    if (!found)
                    {
                        throw ServiceResultException.Create(StatusCodes.BadUserAccessDenied, "Anonymous user token policy not supported.");
                    }
                }

                // create an anonymous token to use for subsequent validation.
                AnonymousIdentityToken anonymousToken = new AnonymousIdentityToken();
                anonymousToken.PolicyId = policy.PolicyId;
                return anonymousToken;
            }

            UserIdentityToken token = null;
            // check for unrecognized token.
            if (!typeof( UserIdentityToken ).IsInstanceOfType( identityToken.Body ))
            {
                //handle the use case when the UserIdentityToken is binary encoded over xml message encoding
                if (identityToken.Encoding == ExtensionObjectEncoding.Binary && typeof( byte[] ).IsInstanceOfType( identityToken.Body ))
                {
                    UserIdentityToken newToken = BaseVariableState.DecodeExtensionObject( null, typeof( UserIdentityToken ), identityToken, false ) as UserIdentityToken;
                    if (newToken == null)
                    {
                        throw ServiceResultException.Create( StatusCodes.BadUserAccessDenied, "Invalid user identity token provided." );
                    }

                    policy = m_endpoint.FindUserTokenPolicy( newToken.PolicyId );
                    if (policy == null)
                    {
                        throw ServiceResultException.Create( StatusCodes.BadUserAccessDenied, "User token policy not supported.", "Opc.Ua.Server.Session.ValidateUserIdentityToken" );
                    }
                    switch (policy.TokenType)
                    {
                        case UserTokenType.Anonymous:
                            token = BaseVariableState.DecodeExtensionObject( null, typeof( AnonymousIdentityToken ), identityToken, true ) as AnonymousIdentityToken;
                            break;
                        case UserTokenType.UserName:
                            token = BaseVariableState.DecodeExtensionObject( null, typeof( UserNameIdentityToken ), identityToken, true ) as UserNameIdentityToken;
                            break;
                        case UserTokenType.Certificate:
                            token = BaseVariableState.DecodeExtensionObject( null, typeof( X509IdentityToken ), identityToken, true ) as X509IdentityToken;
                            break;
                        case UserTokenType.IssuedToken:
                            token = BaseVariableState.DecodeExtensionObject( null, typeof( IssuedIdentityToken ), identityToken, true ) as IssuedIdentityToken;
                            break;
                        default:
                            throw ServiceResultException.Create( StatusCodes.BadUserAccessDenied, "Invalid user identity token provided." );
                    }
                }
                else
                {
                    throw ServiceResultException.Create( StatusCodes.BadUserAccessDenied, "Invalid user identity token provided." );
                }
            }
            else
            {
                // get the token.
                token = (UserIdentityToken) identityToken.Body;
            }

            // find the user token policy.
            policy = m_endpoint.FindUserTokenPolicy( token.PolicyId );

            if (policy == null)
            {
                throw ServiceResultException.Create(StatusCodes.BadIdentityTokenInvalid, "User token policy not supported.");
            }

            // determine the security policy uri.
            string securityPolicyUri = policy.SecurityPolicyUri;

            if (String.IsNullOrEmpty( securityPolicyUri ))
            {
                securityPolicyUri = m_endpoint.SecurityPolicyUri;
            }

            if (ServerBase.RequireEncryption(m_endpoint))
            {
                // decrypt the token.
                if (m_serverCertificate == null)
                {
                    m_serverCertificate = CertificateFactory.Create(m_endpoint.ServerCertificate, true);

                    // check for valid certificate.
                    if (m_serverCertificate == null)
                    {
                        throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "ApplicationCertificate cannot be found.");
                    }
                }

                try
                {
                    token.Decrypt(m_serverCertificate, m_serverNonce, securityPolicyUri);
                }
                catch (Exception e)
                {
                    if (e is ServiceResultException)
                    {
                        throw;
                    }

                    throw ServiceResultException.Create(StatusCodes.BadIdentityTokenInvalid, e, "Could not decrypt identity token.");
                }

                // verify the signature.
                if (securityPolicyUri != SecurityPolicies.None)
                {
                    byte[] dataToSign = Utils.Append(m_serverCertificate.RawData, m_serverNonce);

                    if (!token.Verify(dataToSign, userTokenSignature, securityPolicyUri))
                    {
                        throw new ServiceResultException(StatusCodes.BadUserSignatureInvalid, "Invalid user signature!");
                    }
                }
            }
				
            // validate user identity token.
            return token;
        }
Exemplo n.º 10
0
        /// <summary cref="IUserIdentity.GetIdentityToken" />
        public UserIdentityToken GetIdentityToken()
        {
            // check for anonymous.
            if (m_token == null)
            {
                AnonymousIdentityToken token = new AnonymousIdentityToken();
                token.PolicyId = m_policyId;
                return(token);
            }

            // return a user name token.
            UserNameSecurityToken usernameToken = m_token as UserNameSecurityToken;

            if (usernameToken != null)
            {
                UserNameIdentityToken token = new UserNameIdentityToken();
                token.PolicyId          = m_policyId;
                token.UserName          = usernameToken.UserName;
                token.DecryptedPassword = usernameToken.Password;
                return(token);
            }

            // return an X509 token.
            X509SecurityToken x509Token = m_token as X509SecurityToken;

            if (x509Token != null)
            {
                X509IdentityToken token = new X509IdentityToken();
                token.PolicyId        = m_policyId;
                token.CertificateData = x509Token.Certificate.GetRawCertData();
                token.Certificate     = x509Token.Certificate;
                return(token);
            }

            // handle SAML token.
            SamlSecurityToken samlToken = m_token as SamlSecurityToken;

            if (samlToken != null)
            {
                MemoryStream  ostrm  = new MemoryStream();
                XmlTextWriter writer = new XmlTextWriter(ostrm, new UTF8Encoding());

                try
                {
                    SamlSerializer serializer = new SamlSerializer();
                    serializer.WriteToken(samlToken, writer, WSSecurityTokenSerializer.DefaultInstance);
                }
                finally
                {
                    writer.Close();
                }

                IssuedIdentityToken wssToken = new IssuedIdentityToken();
                wssToken.PolicyId           = m_policyId;
                wssToken.DecryptedTokenData = ostrm.ToArray();

                return(wssToken);
            }

            // return a WSS token by default.
            if (m_token != null)
            {
                MemoryStream ostrm  = new MemoryStream();
                XmlWriter    writer = new XmlTextWriter(ostrm, new UTF8Encoding());

                try
                {
                    WSSecurityTokenSerializer serializer = new WSSecurityTokenSerializer();
                    serializer.WriteToken(writer, m_token);
                }
                finally
                {
                    writer.Close();
                }

                IssuedIdentityToken wssToken = new IssuedIdentityToken();
                wssToken.PolicyId           = m_policyId;
                wssToken.DecryptedTokenData = ostrm.ToArray();

                return(wssToken);
            }

            return(null);
        }
            /// <summary>
            /// Validates the identity token supplied by the client.
            /// </summary>
            /// <param name="identityToken"></param>
            /// <param name="userTokenSignature"></param>
            /// <returns></returns>
            private bool ValidateUserIdentityToken(ExtensionObject identityToken,
                                                   SignatureData userTokenSignature)
            {
                UserIdentityToken token = null;
                UserTokenPolicy   policy;

                if (identityToken == null || identityToken.Body == null)
                {
                    if (_activated)
                    {
                        // not changing the token if already activated.
                        return(false);
                    }
                    policy = Endpoint.UserIdentityTokens?
                             .FirstOrDefault(t => t.TokenType == UserTokenType.Anonymous);
                    if (policy == null)
                    {
                        throw ServiceResultException.Create(StatusCodes.BadUserAccessDenied,
                                                            "Anonymous user token policy not supported.");
                    }
                    // create an anonymous token to use for subsequent validation.
                    token = new AnonymousIdentityToken {
                        PolicyId = policy.PolicyId
                    };
                }
                else if (!typeof(UserIdentityToken).IsInstanceOfType(identityToken.Body))
                {
                    // Decode identity token from binary.
                    token = DecodeUserIdentityToken(identityToken, out policy);
                }
                else
                {
                    token = (UserIdentityToken)identityToken.Body;
                    // find the user token policy.
                    policy = Endpoint.FindUserTokenPolicy(token.PolicyId);
                    if (policy == null)
                    {
                        throw ServiceResultException.Create(StatusCodes.BadIdentityTokenInvalid,
                                                            "User token policy not supported.");
                    }
                }

                // determine the security policy uri.
                var securityPolicyUri = policy.SecurityPolicyUri;

                if (string.IsNullOrEmpty(securityPolicyUri))
                {
                    securityPolicyUri = Endpoint.SecurityPolicyUri;
                }

                if (securityPolicyUri != SecurityPolicies.None)
                {
                    // decrypt the user identity token.
                    if (_serverCertificate == null)
                    {
                        _serverCertificate = CertificateFactory.Create(
                            Endpoint.ServerCertificate, true);
                        // check for valid certificate.
                        if (_serverCertificate == null)
                        {
                            throw ServiceResultException.Create(StatusCodes.BadConfigurationError,
                                                                "ApplicationCertificate cannot be found.");
                        }
                    }
                    try {
                        token.Decrypt(_serverCertificate, _serverNonce, securityPolicyUri);
                    }
                    catch (ServiceResultException) {
                        throw;
                    }
                    catch (Exception e) {
                        throw ServiceResultException.Create(StatusCodes.BadIdentityTokenInvalid,
                                                            e, "Could not decrypt identity token.");
                    }
                    // ... and verify the signature if any.
                    VerifyUserTokenSignature(userTokenSignature, token, securityPolicyUri);
                }

                // We have a valid token - validate it through the handler chain.
                var arg = new UserIdentityHandlerArgs {
                    CurrentIdentities = Identities,
                    Token             = token
                };

                _validator?.Invoke(this, arg);
                if (arg.ValidationException != null)
                {
                    throw arg.ValidationException;
                }
                if (arg.NewIdentities != null)
                {
                    Identities = arg.NewIdentities;
                    return(true);
                }
                return(false); // No new identities
            }
Exemplo n.º 12
0
        protected override async Task OnOpenAsync(CancellationToken token)
        {
            await base.OnOpenAsync(token).ConfigureAwait(false);

            token.ThrowIfCancellationRequested();

            // if SessionId is provided then we skip the CreateSessionRequest and go directly to (re)ActivateSession.
            // requires from previous Session: SessionId, AuthenticationToken, RemoteNonce
            if (this.SessionId == null)
            {
                var localNonce           = this.RemoteEndpoint.SecurityMode != MessageSecurityMode.None ? this.GetNextNonce() : null;
                var localCertificateBlob = this.RemoteEndpoint.SecurityMode != MessageSecurityMode.None ? this.LocalCertificate.RawData : null;
                var createSessionRequest = new CreateSessionRequest
                {
                    ClientDescription       = this.LocalDescription,
                    EndpointUrl             = this.RemoteEndpoint.EndpointUrl,
                    SessionName             = this.LocalDescription.ApplicationName,
                    ClientNonce             = localNonce,
                    ClientCertificate       = localCertificateBlob,
                    RequestedSessionTimeout = this.SessionTimeout,
                    MaxResponseMessageSize  = this.RemoteMaxMessageSize
                };

                var createSessionResponse = await this.CreateSessionAsync(createSessionRequest).ConfigureAwait(false);

                this.SessionId           = createSessionResponse.SessionId;
                this.AuthenticationToken = createSessionResponse.AuthenticationToken;
                this.RemoteNonce         = createSessionResponse.ServerNonce;

                // verify the server's certificate is the same as the certificate from the selected endpoint.
                if (this.RemoteEndpoint.ServerCertificate != null && !this.RemoteEndpoint.ServerCertificate.SequenceEqual(createSessionResponse.ServerCertificate))
                {
                    throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Server did not return the same certificate used to create the channel.");
                }

                // verify the server's signature.
                switch (this.RemoteEndpoint.SecurityPolicyUri)
                {
                case SecurityPolicyUris.Basic128Rsa15:
                case SecurityPolicyUris.Basic256:
                    byte[] dataToVerify = Concat(localCertificateBlob, localNonce);
                    if (!this.RemotePublicKey.VerifyData(dataToVerify, createSessionResponse.ServerSignature.Signature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1))
                    {
                        throw new ServiceResultException(StatusCodes.BadApplicationSignatureInvalid, "Server did not provide a correct signature for the nonce data provided by the client.");
                    }

                    break;

                case SecurityPolicyUris.Basic256Sha256:
                    byte[] dataToVerify256 = Concat(localCertificateBlob, localNonce);
                    if (!this.RemotePublicKey.VerifyData(dataToVerify256, createSessionResponse.ServerSignature.Signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1))
                    {
                        throw new ServiceResultException(StatusCodes.BadApplicationSignatureInvalid, "Server did not provide a correct signature for the nonce data provided by the client.");
                    }

                    break;

                default:
                    break;
                }
            }

            // create client signature
            SignatureData clientSignature = null;

            switch (this.RemoteEndpoint.SecurityPolicyUri)
            {
            case SecurityPolicyUris.Basic128Rsa15:
            case SecurityPolicyUris.Basic256:
                byte[] dataToSign = Concat(this.RemoteEndpoint.ServerCertificate, this.RemoteNonce);
                clientSignature = new SignatureData
                {
                    Signature = this.LocalPrivateKey.SignData(dataToSign, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1),
                    Algorithm = RsaSha1Signature,
                };

                break;

            case SecurityPolicyUris.Basic256Sha256:
                byte[] dataToSign256 = Concat(this.RemoteEndpoint.ServerCertificate, this.RemoteNonce);
                clientSignature = new SignatureData
                {
                    Signature = this.LocalPrivateKey.SignData(dataToSign256, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1),
                    Algorithm = RsaSha256Signature,
                };

                break;

            default:
                clientSignature = new SignatureData();
                break;
            }

            // supported UserIdentityToken types are AnonymousIdentityToken, UserNameIdentityToken, IssuedIdentityToken, X509IdentityToken
            UserIdentityToken identityToken  = null;
            SignatureData     tokenSignature = null;

            // if UserIdentity type is IssuedIdentity
            if (this.UserIdentity is IssuedIdentity)
            {
                var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.IssuedToken);
                if (tokenPolicy == null)
                {
                    throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected);
                }

                var    issuedIdentity = (IssuedIdentity)this.UserIdentity;
                byte[] plainText      = Concat(issuedIdentity.TokenData, this.RemoteNonce);
                var    secPolicyUri   = tokenPolicy.SecurityPolicyUri ?? this.RemoteEndpoint.SecurityPolicyUri;
                RSA    asymRemoteEncryptionKey;
                switch (secPolicyUri)
                {
                case SecurityPolicyUris.Basic128Rsa15:
                    asymRemoteEncryptionKey = this.RemoteCertificate.GetRSAPublicKey();
                    identityToken           = new IssuedIdentityToken
                    {
                        TokenData           = asymRemoteEncryptionKey.EncryptTokenData(plainText, secPolicyUri),
                        EncryptionAlgorithm = RsaV15KeyWrap,
                        PolicyId            = tokenPolicy.PolicyId
                    };

                    break;

                case SecurityPolicyUris.Basic256:
                case SecurityPolicyUris.Basic256Sha256:
                    asymRemoteEncryptionKey = this.RemoteCertificate.GetRSAPublicKey();
                    identityToken           = new IssuedIdentityToken
                    {
                        TokenData           = asymRemoteEncryptionKey.EncryptTokenData(plainText, secPolicyUri),
                        EncryptionAlgorithm = RsaOaepKeyWrap,
                        PolicyId            = tokenPolicy.PolicyId
                    };

                    break;

                default:
                    identityToken = new IssuedIdentityToken
                    {
                        TokenData           = issuedIdentity.TokenData,
                        EncryptionAlgorithm = null,
                        PolicyId            = tokenPolicy.PolicyId
                    };
                    break;
                }

                tokenSignature = new SignatureData();
            }

            // if UserIdentity type is X509Identity
            else if (this.UserIdentity is X509Identity)
            {
                var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.Certificate);
                if (tokenPolicy == null)
                {
                    throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected);
                }

                var x509Identity = (X509Identity)this.UserIdentity;
                identityToken = new X509IdentityToken {
                    CertificateData = x509Identity.Certificate?.RawData, PolicyId = tokenPolicy.PolicyId
                };
                var secPolicyUri = tokenPolicy.SecurityPolicyUri ?? this.RemoteEndpoint.SecurityPolicyUri;
                switch (secPolicyUri)
                {
                case SecurityPolicyUris.Basic128Rsa15:
                case SecurityPolicyUris.Basic256:
                    var asymSigningKey = x509Identity.Certificate?.GetRSAPrivateKey();
                    if (asymSigningKey != null)
                    {
                        byte[] dataToSign = Concat(this.RemoteEndpoint.ServerCertificate, this.RemoteNonce);
                        tokenSignature = new SignatureData
                        {
                            Signature = asymSigningKey.SignData(dataToSign, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1),
                            Algorithm = RsaSha1Signature,
                        };
                        break;
                    }

                    tokenSignature = new SignatureData();
                    break;

                case SecurityPolicyUris.Basic256Sha256:
                    var asymSigningKey256 = x509Identity.Certificate?.GetRSAPrivateKey();
                    if (asymSigningKey256 != null)
                    {
                        byte[] dataToSign256 = Concat(this.RemoteEndpoint.ServerCertificate, this.RemoteNonce);
                        tokenSignature = new SignatureData
                        {
                            Signature = asymSigningKey256.SignData(dataToSign256, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1),
                            Algorithm = RsaSha256Signature,
                        };
                        break;
                    }

                    tokenSignature = new SignatureData();
                    break;

                default:
                    tokenSignature = new SignatureData();
                    break;
                }
            }

            // if UserIdentity type is UserNameIdentity
            else if (this.UserIdentity is UserNameIdentity)
            {
                var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.UserName);
                if (tokenPolicy == null)
                {
                    throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected);
                }

                var    userNameIdentity = (UserNameIdentity)this.UserIdentity;
                byte[] plainText        = Concat(System.Text.Encoding.UTF8.GetBytes(userNameIdentity.Password), this.RemoteNonce);
                var    secPolicyUri     = tokenPolicy.SecurityPolicyUri ?? this.RemoteEndpoint.SecurityPolicyUri;
                RSA    asymRemoteEncryptionKey;
                switch (secPolicyUri)
                {
                case SecurityPolicyUris.Basic128Rsa15:
                    asymRemoteEncryptionKey = this.RemoteCertificate.GetRSAPublicKey();
                    identityToken           = new UserNameIdentityToken
                    {
                        UserName            = userNameIdentity.UserName,
                        Password            = asymRemoteEncryptionKey.EncryptTokenData(plainText, secPolicyUri),
                        EncryptionAlgorithm = RsaV15KeyWrap,
                        PolicyId            = tokenPolicy.PolicyId
                    };

                    break;

                case SecurityPolicyUris.Basic256:
                case SecurityPolicyUris.Basic256Sha256:
                    asymRemoteEncryptionKey = this.RemoteCertificate.GetRSAPublicKey();
                    identityToken           = new UserNameIdentityToken
                    {
                        UserName            = userNameIdentity.UserName,
                        Password            = asymRemoteEncryptionKey.EncryptTokenData(plainText, secPolicyUri),
                        EncryptionAlgorithm = RsaOaepKeyWrap,
                        PolicyId            = tokenPolicy.PolicyId
                    };

                    break;

                default:
                    identityToken = new UserNameIdentityToken
                    {
                        UserName            = userNameIdentity.UserName,
                        Password            = System.Text.Encoding.UTF8.GetBytes(userNameIdentity.Password),
                        EncryptionAlgorithm = null,
                        PolicyId            = tokenPolicy.PolicyId
                    };
                    break;
                }

                tokenSignature = new SignatureData();
            }

            // if UserIdentity type is AnonymousIdentity or null
            else
            {
                var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.Anonymous);
                if (tokenPolicy == null)
                {
                    throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected);
                }

                identityToken = new AnonymousIdentityToken {
                    PolicyId = tokenPolicy.PolicyId
                };
                tokenSignature = new SignatureData();
            }

            var activateSessionRequest = new ActivateSessionRequest
            {
                ClientSignature    = clientSignature,
                LocaleIds          = new[] { CultureInfo.CurrentUICulture.TwoLetterISOLanguageName },
                UserIdentityToken  = identityToken,
                UserTokenSignature = tokenSignature
            };
            var activateSessionResponse = await this.ActivateSessionAsync(activateSessionRequest).ConfigureAwait(false);

            this.RemoteNonce = activateSessionResponse.ServerNonce;

            // fetch namespace array, etc.
            var readValueIds = new ReadValueId[]
            {
                new ReadValueId
                {
                    NodeId      = NodeId.Parse(VariableIds.Server_NamespaceArray),
                    AttributeId = AttributeIds.Value
                },
                new ReadValueId
                {
                    NodeId      = NodeId.Parse(VariableIds.Server_ServerArray),
                    AttributeId = AttributeIds.Value
                }
            };
            var readRequest = new ReadRequest
            {
                NodesToRead = readValueIds
            };

            var readResponse = await this.ReadAsync(readRequest).ConfigureAwait(false);

            if (readResponse.Results.Length == 2)
            {
                if (StatusCode.IsGood(readResponse.Results[0].StatusCode))
                {
                    this.NamespaceUris.Clear();
                    this.NamespaceUris.AddRange(readResponse.Results[0].GetValueOrDefault <string[]>());
                }

                if (StatusCode.IsGood(readResponse.Results[1].StatusCode))
                {
                    this.ServerUris.Clear();
                    this.ServerUris.AddRange(readResponse.Results[1].GetValueOrDefault <string[]>());
                }
            }
        }
Exemplo n.º 13
0
        /// <summary cref="IUserIdentity.GetIdentityToken" />
        public UserIdentityToken GetIdentityToken()
        {
            // check for anonymous.
            if (m_token == null)
            {
                AnonymousIdentityToken token = new AnonymousIdentityToken();
                token.PolicyId = m_policyId;
                return token;
            }

            // return a user name token.
            UserNameSecurityToken usernameToken = m_token as UserNameSecurityToken;

            if (usernameToken != null)
            {
                UserNameIdentityToken token = new UserNameIdentityToken();
                token.PolicyId = m_policyId;
                token.UserName = usernameToken.UserName;
                token.DecryptedPassword = usernameToken.Password;
                return token;
            }

            // return an X509 token.
            X509SecurityToken x509Token = m_token as X509SecurityToken;

            if (x509Token != null)
            {
                X509IdentityToken token = new X509IdentityToken();
                token.PolicyId = m_policyId;
                token.CertificateData = x509Token.Certificate.GetRawCertData();
                token.Certificate = x509Token.Certificate;
                return token;
            }
            
            // handle SAML token.
            SamlSecurityToken samlToken = m_token as SamlSecurityToken;

            if (samlToken != null)
            {
                MemoryStream ostrm = new MemoryStream();      
                XmlTextWriter writer = new XmlTextWriter(ostrm, new UTF8Encoding());   
 
                try
                {
                    SamlSerializer serializer = new SamlSerializer();
                    serializer.WriteToken(samlToken, writer, WSSecurityTokenSerializer.DefaultInstance);
                }
                finally
                {
                    writer.Close();
                }

                IssuedIdentityToken wssToken = new IssuedIdentityToken();
                wssToken.PolicyId = m_policyId;
                wssToken.DecryptedTokenData = ostrm.ToArray();

                return wssToken;
            }

            // return a WSS token by default.
            if (m_token != null)
            {
                MemoryStream ostrm = new MemoryStream();
                XmlWriter writer = new XmlTextWriter(ostrm, new UTF8Encoding());

                try
                {
                    WSSecurityTokenSerializer serializer = new WSSecurityTokenSerializer();
                    serializer.WriteToken(writer, m_token);
                }
                finally
                {
                    writer.Close();
                }

                IssuedIdentityToken wssToken = new IssuedIdentityToken();
                wssToken.PolicyId = m_policyId;
                wssToken.DecryptedTokenData = ostrm.ToArray();

                return wssToken;
            }

            return null;
        }
        protected override async Task OnOpenAsync(CancellationToken token)
        {
            await base.OnOpenAsync(token).ConfigureAwait(false);
            token.ThrowIfCancellationRequested();

            // if SessionId is provided then we skip the CreateSessionRequest and go directly to (re)ActivateSession.
            // requires from previous Session: SessionId, AuthenticationToken, RemoteNonce
            if (this.SessionId == null)
            {
                var localNonce = this.RemoteEndpoint.SecurityMode != MessageSecurityMode.None ? this.GetNextNonce() : null;
                var localCertificateBlob = this.RemoteEndpoint.SecurityMode != MessageSecurityMode.None ? this.LocalCertificate.RawData : null;
                var createSessionRequest = new CreateSessionRequest
                {
                    RequestHeader = new RequestHeader { TimeoutHint = this.TimeoutHint, ReturnDiagnostics = this.DiagnosticsHint, Timestamp = DateTime.UtcNow },
                    ClientDescription = this.LocalDescription,
                    EndpointUrl = this.RemoteEndpoint.EndpointUrl,
                    SessionName = this.LocalDescription.ApplicationName,
                    ClientNonce = localNonce,
                    ClientCertificate = localCertificateBlob,
                    RequestedSessionTimeout = this.SessionTimeout,
                    MaxResponseMessageSize = this.RemoteMaxMessageSize
                };
                var createSessionResponse = (CreateSessionResponse)await this.RequestAsync(createSessionRequest).ConfigureAwait(false);
                this.SessionId = createSessionResponse.SessionId;
                this.AuthenticationToken = createSessionResponse.AuthenticationToken;
                this.RemoteNonce = createSessionResponse.ServerNonce;

                // verify the server's certificate is the same as the certificate from the selected endpoint.
                if (this.RemoteEndpoint.ServerCertificate != null && !this.RemoteEndpoint.ServerCertificate.SequenceEqual(createSessionResponse.ServerCertificate))
                {
                    throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Server did not return the same certificate used to create the channel.");
                }

                // verify the server's signature.
                switch (this.RemoteEndpoint.SecurityPolicyUri)
                {
                    case SecurityPolicyUris.Basic128Rsa15:
                    case SecurityPolicyUris.Basic256:
                        byte[] dataToVerify = Concat(localCertificateBlob, localNonce);
                        if (!this.RemotePublicKey.VerifyData(dataToVerify, createSessionResponse.ServerSignature.Signature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1))
                        {
                            throw new ServiceResultException(StatusCodes.BadApplicationSignatureInvalid, "Server did not provide a correct signature for the nonce data provided by the client.");
                        }

                        break;

                    case SecurityPolicyUris.Basic256Sha256:
                        byte[] dataToVerify256 = Concat(localCertificateBlob, localNonce);
                        if (!this.RemotePublicKey.VerifyData(dataToVerify256, createSessionResponse.ServerSignature.Signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1))
                        {
                            throw new ServiceResultException(StatusCodes.BadApplicationSignatureInvalid, "Server did not provide a correct signature for the nonce data provided by the client.");
                        }

                        break;

                    default:
                        break;
                }
            }

            // create client signature
            SignatureData clientSignature = null;
            switch (this.RemoteEndpoint.SecurityPolicyUri)
            {
                case SecurityPolicyUris.Basic128Rsa15:
                case SecurityPolicyUris.Basic256:
                    byte[] dataToSign = Concat(this.RemoteEndpoint.ServerCertificate, this.RemoteNonce);
                    clientSignature = new SignatureData
                    {
                        Signature = this.LocalPrivateKey.SignData(dataToSign, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1),
                        Algorithm = RsaSha1Signature,
                    };

                    break;

                case SecurityPolicyUris.Basic256Sha256:
                    byte[] dataToSign256 = Concat(this.RemoteEndpoint.ServerCertificate, this.RemoteNonce);
                    clientSignature = new SignatureData
                    {
                        Signature = this.LocalPrivateKey.SignData(dataToSign256, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1),
                        Algorithm = RsaSha256Signature,
                    };

                    break;

                default:
                    clientSignature = new SignatureData();
                    break;
            }

            // supported UserIdentityToken types are AnonymousIdentityToken, UserNameIdentityToken, IssuedIdentityToken, X509IdentityToken
            UserIdentityToken identityToken = null;
            SignatureData tokenSignature = null;

            // if UserIdentity type is IssuedIdentity
            if (this.UserIdentity is IssuedIdentity)
            {
                var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.IssuedToken);
                if (tokenPolicy == null)
                {
                    throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected);
                }

                var issuedIdentity = (IssuedIdentity)this.UserIdentity;
                byte[] plainText = Concat(issuedIdentity.TokenData, this.RemoteNonce);
                var secPolicyUri = tokenPolicy.SecurityPolicyUri ?? this.RemoteEndpoint.SecurityPolicyUri;
                RSA asymRemoteEncryptionKey;
                switch (secPolicyUri)
                {
                    case SecurityPolicyUris.Basic128Rsa15:
                        asymRemoteEncryptionKey = this.RemoteCertificate.GetRSAPublicKey();
                        identityToken = new IssuedIdentityToken
                        {
                            TokenData = asymRemoteEncryptionKey.EncryptTokenData(plainText, secPolicyUri),
                            EncryptionAlgorithm = RsaV15KeyWrap,
                            PolicyId = tokenPolicy.PolicyId
                        };

                        break;

                    case SecurityPolicyUris.Basic256:
                    case SecurityPolicyUris.Basic256Sha256:
                        asymRemoteEncryptionKey = this.RemoteCertificate.GetRSAPublicKey();
                        identityToken = new IssuedIdentityToken
                        {
                            TokenData = asymRemoteEncryptionKey.EncryptTokenData(plainText, secPolicyUri),
                            EncryptionAlgorithm = RsaOaepKeyWrap,
                            PolicyId = tokenPolicy.PolicyId
                        };

                        break;

                    default:
                        identityToken = new IssuedIdentityToken
                        {
                            TokenData = issuedIdentity.TokenData,
                            EncryptionAlgorithm = null,
                            PolicyId = tokenPolicy.PolicyId
                        };
                        break;
                }

                tokenSignature = new SignatureData();
            }

            // if UserIdentity type is X509Identity
            else if (this.UserIdentity is X509Identity)
            {
                var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.Certificate);
                if (tokenPolicy == null)
                {
                    throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected);
                }

                var x509Identity = (X509Identity)this.UserIdentity;
                identityToken = new X509IdentityToken { CertificateData = x509Identity.Certificate?.RawData, PolicyId = tokenPolicy.PolicyId };
                var secPolicyUri = tokenPolicy.SecurityPolicyUri ?? this.RemoteEndpoint.SecurityPolicyUri;
                switch (secPolicyUri)
                {
                    case SecurityPolicyUris.Basic128Rsa15:
                    case SecurityPolicyUris.Basic256:
                        var asymSigningKey = x509Identity.Certificate?.GetRSAPrivateKey();
                        if (asymSigningKey != null)
                        {
                            byte[] dataToSign = Concat(this.RemoteEndpoint.ServerCertificate, this.RemoteNonce);
                            tokenSignature = new SignatureData
                            {
                                Signature = asymSigningKey.SignData(dataToSign, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1),
                                Algorithm = RsaSha1Signature,
                            };
                            break;
                        }

                        tokenSignature = new SignatureData();
                        break;

                    case SecurityPolicyUris.Basic256Sha256:
                        var asymSigningKey256 = x509Identity.Certificate?.GetRSAPrivateKey();
                        if (asymSigningKey256 != null)
                        {
                            byte[] dataToSign256 = Concat(this.RemoteEndpoint.ServerCertificate, this.RemoteNonce);
                            tokenSignature = new SignatureData
                            {
                                Signature = asymSigningKey256.SignData(dataToSign256, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1),
                                Algorithm = RsaSha256Signature,
                            };
                            break;
                        }

                        tokenSignature = new SignatureData();
                        break;

                    default:
                        tokenSignature = new SignatureData();
                        break;
                }
            }

            // if UserIdentity type is UserNameIdentity
            else if (this.UserIdentity is UserNameIdentity)
            {
                var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.UserName);
                if (tokenPolicy == null)
                {
                    throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected);
                }

                var userNameIdentity = (UserNameIdentity)this.UserIdentity;
                byte[] plainText = Concat(System.Text.Encoding.UTF8.GetBytes(userNameIdentity.Password), this.RemoteNonce);
                var secPolicyUri = tokenPolicy.SecurityPolicyUri ?? this.RemoteEndpoint.SecurityPolicyUri;
                RSA asymRemoteEncryptionKey;
                switch (secPolicyUri)
                {
                    case SecurityPolicyUris.Basic128Rsa15:
                        asymRemoteEncryptionKey = this.RemoteCertificate.GetRSAPublicKey();
                        identityToken = new UserNameIdentityToken
                        {
                            UserName = userNameIdentity.UserName,
                            Password = asymRemoteEncryptionKey.EncryptTokenData(plainText, secPolicyUri),
                            EncryptionAlgorithm = RsaV15KeyWrap,
                            PolicyId = tokenPolicy.PolicyId
                        };

                        break;

                    case SecurityPolicyUris.Basic256:
                    case SecurityPolicyUris.Basic256Sha256:
                        asymRemoteEncryptionKey = this.RemoteCertificate.GetRSAPublicKey();
                        identityToken = new UserNameIdentityToken
                        {
                            UserName = userNameIdentity.UserName,
                            Password = asymRemoteEncryptionKey.EncryptTokenData(plainText, secPolicyUri),
                            EncryptionAlgorithm = RsaOaepKeyWrap,
                            PolicyId = tokenPolicy.PolicyId
                        };

                        break;

                    default:
                        identityToken = new UserNameIdentityToken
                        {
                            UserName = userNameIdentity.UserName,
                            Password = System.Text.Encoding.UTF8.GetBytes(userNameIdentity.Password),
                            EncryptionAlgorithm = null,
                            PolicyId = tokenPolicy.PolicyId
                        };
                        break;
                }

                tokenSignature = new SignatureData();
            }

            // if UserIdentity type is AnonymousIdentity or null
            else
            {
                var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.Anonymous);
                if (tokenPolicy == null)
                {
                    throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected);
                }

                identityToken = new AnonymousIdentityToken { PolicyId = tokenPolicy.PolicyId };
                tokenSignature = new SignatureData();
            }

            var activateSessionRequest = new ActivateSessionRequest
            {
                RequestHeader = new RequestHeader { TimeoutHint = this.TimeoutHint, ReturnDiagnostics = this.DiagnosticsHint, Timestamp = DateTime.UtcNow },
                ClientSignature = clientSignature,
                LocaleIds = new[] { CultureInfo.CurrentUICulture.TwoLetterISOLanguageName },
                UserIdentityToken = identityToken,
                UserTokenSignature = tokenSignature
            };
            var activateSessionResponse = (ActivateSessionResponse)await this.RequestAsync(activateSessionRequest).ConfigureAwait(false);
            this.RemoteNonce = activateSessionResponse.ServerNonce;
            await this.FetchNamespaceTablesAsync().ConfigureAwait(false);
        }
 /// <summary>
 /// Initializes the object as an anonymous user.
 /// </summary>
 public UserIdentity()
 {
     AnonymousIdentityToken token = new AnonymousIdentityToken();
     Initialize(token);
 }