/// <summary cref="ChannelFactoryBase{T}.OnCreateChannel" />
        protected override IRequestSessionChannel OnCreateChannel(EndpointAddress address, Uri via)
        {
            X509Certificate2 clientCertificate = null;

            if (m_credentials.ClientCertificate.Certificate != null)
            {
                clientCertificate = m_credentials.ClientCertificate.Certificate;
            }

            X509Certificate2 serverCertificate = null;

            if (m_endpointDescription != null)
            {
                serverCertificate = CertificateFactory.Create(m_endpointDescription.ServerCertificate, true);
            }

            UaTcpRequestChannel channel = new UaTcpRequestChannel(
                this,
                m_id,
                address,
                via,
                m_bufferManager,
                m_quotas,
                clientCertificate,
                serverCertificate,
                m_endpointDescription);

            return(channel);
        }
        /// <summary>
        /// Initializes the listener from a binding element.
        /// </summary>
        internal UaTcpChannelListener(UaTcpTransportBindingElement bindingElement, BindingContext context)
            :
            base(context.Binding)
        {
            // assign a unique guid to the listener.
            m_listenerId = Guid.NewGuid().ToString();

            SetUri(context.ListenUriBaseAddress, context.ListenUriRelativeAddress);

            m_descriptions  = bindingElement.Descriptions;
            m_configuration = bindingElement.Configuration;

            m_quotas = new TcpChannelQuotas();

            m_quotas.MaxBufferSize         = m_configuration.MaxBufferSize;
            m_quotas.MaxMessageSize        = m_configuration.MaxMessageSize;
            m_quotas.ChannelLifetime       = m_configuration.ChannelLifetime;
            m_quotas.SecurityTokenLifetime = m_configuration.SecurityTokenLifetime;
            m_quotas.MessageContext        = bindingElement.MessageContext;

            foreach (object parameter in context.BindingParameters)
            {
                ServiceCredentials credentials = parameter as ServiceCredentials;

                if (credentials != null)
                {
                    // TBD - paste the cert with the private key with the additional chain.
                    m_serverCertificate           = CertificateFactory.Create(credentials.ServiceCertificate.Certificate, credentials.ServiceCertificate.Certificate);
                    m_quotas.CertificateValidator = credentials.ClientCertificate.Authentication.CustomCertificateValidator;
                }
            }

            m_bufferManager = new BufferManager("Server", (int)bindingElement.MaxBufferPoolSize, m_quotas.MaxBufferSize);

            m_channels     = new Dictionary <uint, TcpServerChannel>();
            m_channelQueue = new Queue <UaTcpReplyChannel>();
            m_acceptQueue  = new Queue <TcpAsyncOperation <IReplySessionChannel> >();

            // link the channel directly to the server.
            // this is a hack designed to work around a bug in the WCF framework that results in lost requests during stress testing.
            if (bindingElement.ServiceHost != null)
            {
                if (bindingElement.ServiceHost.Server is DiscoveryServerBase)
                {
                    m_callback = new DiscoveryEndpoint(bindingElement.ServiceHost);
                }
                else
                {
                    m_callback = new SessionEndpoint(bindingElement.ServiceHost);
                }
            }
        }
        /// <summary>
        /// Displays the dialog.
        /// </summary>
        public bool ShowDialog(EndpointDescription endpoint)
        {
            if (endpoint == null)
            {
                throw new ArgumentNullException("endpoint");
            }

            EndpointTB.Text   = endpoint.EndpointUrl;
            ServerNameTB.Text = endpoint.Server.ApplicationName.Text;
            ServerUriTB.Text  = endpoint.Server.ApplicationUri;

            try
            {
                X509Certificate2 certificate = CertificateFactory.Create(endpoint.ServerCertificate, true);
                ServerCertificateTB.Text = String.Format("{0}", certificate.Subject);
            }
            catch
            {
                ServerCertificateTB.Text = "<bad certificate>";
            }


            SecurityModeTB.Text      = String.Format("{0}", endpoint.SecurityMode);;
            SecurityPolicyUriTB.Text = String.Format("{0}", endpoint.SecurityPolicyUri);

            UserIdentityTypeTB.Text = "";

            foreach (UserTokenPolicy policy in endpoint.UserIdentityTokens)
            {
                UserIdentityTypeTB.Text += String.Format("{0} ", policy.TokenType);
            }

            if (ShowDialog() != DialogResult.OK)
            {
                return(false);
            }

            return(true);
        }
Exemple #4
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);
        }
        protected void ReadAsymmetricMessageHeader(
            BinaryDecoder decoder,
            X509Certificate2 receiverCertificate,
            out uint secureChannelId,
            out X509Certificate2 senderCertificate,
            out string securityPolicyUri)
        {
            senderCertificate = null;

            uint messageType = decoder.ReadUInt32(null);
            uint messageSize = decoder.ReadUInt32(null);

            // decode security header.
            byte[] certificateData = null;
            byte[] thumbprintData  = null;

            try
            {
                secureChannelId   = decoder.ReadUInt32(null);
                securityPolicyUri = decoder.ReadString(null, TcpMessageLimits.MaxSecurityPolicyUriSize);
                certificateData   = decoder.ReadByteString(null, TcpMessageLimits.MaxCertificateSize);
                thumbprintData    = decoder.ReadByteString(null, TcpMessageLimits.CertificateThumbprintSize);
            }
            catch (Exception e)
            {
                throw ServiceResultException.Create(
                          StatusCodes.BadSecurityChecksFailed,
                          e,
                          "The asymmetric security header could not be parsed.");
            }

            // verify sender certificate.
            if (certificateData != null && certificateData.Length > 0)
            {
                senderCertificate = CertificateFactory.Create(certificateData, true);

                try
                {
                    string thumbprint = senderCertificate.Thumbprint;

                    if (thumbprint == null)
                    {
                        throw ServiceResultException.Create(StatusCodes.BadCertificateInvalid, "Invalid certificate thumbprint.");
                    }
                }
                catch (Exception e)
                {
                    throw ServiceResultException.Create(StatusCodes.BadCertificateInvalid, e, "The sender's certificate could not be parsed.");
                }
            }
            else
            {
                if (securityPolicyUri != SecurityPolicies.None)
                {
                    throw ServiceResultException.Create(StatusCodes.BadCertificateInvalid, "The sender's certificate was not specified.");
                }
            }

            // verify receiver thumbprint.
            if (thumbprintData != null && thumbprintData.Length > 0)
            {
                if (receiverCertificate.Thumbprint.ToUpperInvariant() != GetThumbprintString(thumbprintData))
                {
                    throw ServiceResultException.Create(StatusCodes.BadCertificateInvalid, "The receiver's certificate thumbprint is not valid.");
                }
            }
            else
            {
                if (securityPolicyUri != SecurityPolicies.None)
                {
                    throw ServiceResultException.Create(StatusCodes.BadCertificateInvalid, "The receiver's certificate thumbprint was not specified.");
                }
            }
        }
Exemple #6
0
        /// <summary>
        /// Runs the testcases against the endpoint.
        /// </summary>
        /// <param name="endpoint">The endpoint to test.</param>
        /// <param name="testcases">The testcases to run.</param>
        public void Run(ConfiguredEndpoint endpoint, ServerTestConfiguration testConfiguration)
        {
            // save the test configuration.
            m_testConfiguration = testConfiguration;
            m_stopped           = false;

            // create the binding factory.
            m_bindingFactory = BindingFactory.Create(m_configuration, m_messageContext);

            while (!m_stopped)
            {
                try {
                    Report("Test run started.");

                    // update from server.
                    if (endpoint.UpdateBeforeConnect)
                    {
                        endpoint.UpdateFromServer(m_bindingFactory);
                        Report("Updated endpoint from the discovery endpoint.");
                    }

                    // validate the server certificate.
                    byte[] certificateData = endpoint.Description.ServerCertificate;

                    try {
                        X509Certificate2 certificate = CertificateFactory.Create(certificateData, true);
                        m_configuration.CertificateValidator.Validate(certificate);
                    } catch (ServiceResultException e) {
                        if (e.StatusCode != StatusCodes.BadCertificateUntrusted)
                        {
                            throw new ServiceResultException(e, StatusCodes.BadCertificateInvalid);
                        }

                        // automatically trust the certificate if it is untrusted.
                        m_configuration.CertificateValidator.Update(m_configuration.SecurityConfiguration);
                    }

                    m_defaultEndpoint = endpoint;

                    // fetch all endpoints from the server.
                    m_endpoints = GetEndpoints(endpoint);
                    Report("Fetched all endpoints supported by the server.");
                } catch (Exception e) {
                    Report(e, "Could not connect to server");
                    return;
                }

                m_endpointCount       = 0;
                m_totalEndpointCount  = 0;
                m_testCount           = 0;
                m_failedTestCount     = 0;
                m_iterationCount      = 0;
                m_totalIterationCount = 0;

                uint totalCount    = 0;
                uint failedCount   = 0;
                uint endpointCount = 0;

                if (m_testConfiguration.EndpointSelection != EndpointSelection.Single)
                {
                    EndpointSelection selection = m_testConfiguration.EndpointSelection;

                    foreach (ConfiguredEndpoint current in m_endpoints.Endpoints)
                    {
                        if (IsEndpointSelected(current, selection, false))
                        {
                            m_totalEndpointCount++;
                        }

                        if (current.Description.EncodingSupport == BinaryEncodingSupport.Optional)
                        {
                            if (IsEndpointSelected(current, selection, true))
                            {
                                m_totalEndpointCount++;
                            }
                        }
                    }

                    foreach (ConfiguredEndpoint current in m_endpoints.Endpoints)
                    {
                        if (IsEndpointSelected(current, selection, false))
                        {
                            m_endpointCount++;

                            // check if test stopped.
                            if (m_stopped)
                            {
                                break;
                            }

                            DoTestForEndpoint(current, ref totalCount, ref failedCount);
                            endpointCount++;
                        }

                        if (current.Description.EncodingSupport == BinaryEncodingSupport.Optional)
                        {
                            if (IsEndpointSelected(current, selection, true))
                            {
                                m_endpointCount++;

                                // check if test stopped.
                                if (m_stopped)
                                {
                                    break;
                                }

                                current.Configuration.UseBinaryEncoding = !current.Configuration.UseBinaryEncoding;
                                DoTestForEndpoint(current, ref totalCount, ref failedCount);
                                endpointCount++;
                            }
                        }
                    }
                }
                else
                {
                    m_endpointCount++;
                    m_totalEndpointCount = 1;

                    DoTestForEndpoint(m_defaultEndpoint, ref totalCount, ref failedCount);
                    endpointCount++;
                }

                if (failedCount > 0)
                {
                    Report("WARNING: {0} tests failed. {1} tests run.", failedCount, totalCount);
                }
                else
                {
                    Report("{0} tests completed successfully for {1} endpoints.", totalCount, endpointCount);
                    DumpPerfData();
                }

                if (!m_testConfiguration.Continuous)
                {
                    break;
                }
            }
        }
            /// <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
            }