Create() public static method

Creates a new instance of a ServiceResultException
public static Create ( Opc.Ua.StatusCode code, int index, DiagnosticInfoCollection diagnosticInfos, IList stringTable ) : ServiceResultException
code Opc.Ua.StatusCode
index int
diagnosticInfos DiagnosticInfoCollection
stringTable IList
return ServiceResultException
        /// <summary>
        /// Parses a relative path formatted as a string.
        /// </summary>
        public static RelativePath Parse(string browsePath, ITypeTable typeTree)
        {
            if (typeTree == null)
            {
                throw new ArgumentNullException("typeTree");
            }

            // parse the string.
            RelativePathFormatter formatter = RelativePathFormatter.Parse(browsePath);

            // convert the browse names to node ids.
            RelativePath relativePath = new RelativePath();

            foreach (RelativePathFormatter.Element element in formatter.Elements)
            {
                RelativePathElement parsedElement = new RelativePathElement();

                parsedElement.ReferenceTypeId = null;
                parsedElement.IsInverse       = false;
                parsedElement.IncludeSubtypes = element.IncludeSubtypes;
                parsedElement.TargetName      = element.TargetName;

                switch (element.ElementType)
                {
                case RelativePathFormatter.ElementType.AnyHierarchical:
                {
                    parsedElement.ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences;
                    break;
                }

                case RelativePathFormatter.ElementType.AnyComponent:
                {
                    parsedElement.ReferenceTypeId = ReferenceTypeIds.Aggregates;
                    break;
                }

                case RelativePathFormatter.ElementType.ForwardReference:
                {
                    parsedElement.ReferenceTypeId = typeTree.FindReferenceType(element.ReferenceTypeName);
                    break;
                }

                case RelativePathFormatter.ElementType.InverseReference:
                {
                    parsedElement.ReferenceTypeId = typeTree.FindReferenceType(element.ReferenceTypeName);
                    parsedElement.IsInverse       = true;
                    break;
                }
                }

                if (NodeId.IsNull(parsedElement.ReferenceTypeId))
                {
                    throw ServiceResultException.Create(
                              StatusCodes.BadSyntaxError,
                              "Could not convert BrowseName to a ReferenceTypeId: {0}",
                              element.ReferenceTypeName);
                }

                relativePath.Elements.Add(parsedElement);
            }

            return(relativePath);
        }
Beispiel #2
0
        /// <summary>
        /// Ensures that the application configuration is valid.
        /// </summary>
        /// <param name="applicationType">Type of the application.</param>
        public virtual async Task Validate(ApplicationType applicationType)
        {
            if (String.IsNullOrEmpty(ApplicationName))
            {
                throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "ApplicationName must be specified.");
            }

            if (SecurityConfiguration == null)
            {
                throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "SecurityConfiguration must be specified.");
            }

            SecurityConfiguration.Validate();

            //  generate a default uri if null
            if (String.IsNullOrEmpty(ApplicationUri))
            {
                StringBuilder buffer = new StringBuilder();

                buffer.Append("urn:");
                buffer.Append(Utils.GetHostName());
                buffer.Append(":");
                buffer.Append(ApplicationName);

                m_applicationUri = buffer.ToString();
            }

            // load app cert
            await SecurityConfiguration.ApplicationCertificate.LoadApplicationCertificate(m_applicationUri, null);

            if (applicationType == ApplicationType.Client || applicationType == ApplicationType.ClientAndServer)
            {
                if (ClientConfiguration == null)
                {
                    throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "ClientConfiguration must be specified.");
                }

                ClientConfiguration.Validate();
            }

            if (applicationType == ApplicationType.Server || applicationType == ApplicationType.ClientAndServer)
            {
                if (ServerConfiguration == null)
                {
                    throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "ServerConfiguration must be specified.");
                }

                ServerConfiguration.Validate();
            }

            if (applicationType == ApplicationType.DiscoveryServer)
            {
                if (DiscoveryServerConfiguration == null)
                {
                    throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "DiscoveryServerConfiguration must be specified.");
                }

                DiscoveryServerConfiguration.Validate();
            }

            // toggle the state of the hi-res clock.
            HiResClock.Disabled = m_disableHiResClock;

            if (m_disableHiResClock)
            {
                if (m_serverConfiguration != null)
                {
                    if (m_serverConfiguration.PublishingResolution < 50)
                    {
                        m_serverConfiguration.PublishingResolution = 50;
                    }
                }
            }

            // create the certificate validator.
            m_certificateValidator = new CertificateValidator();
            await m_certificateValidator.Update(this.SecurityConfiguration);
        }
        /// <summary>
        /// Encrypts the text using the SecurityPolicyUri and returns the result.
        /// </summary>
        public static EncryptedData Encrypt(X509Certificate2 certificate, string securityPolicyUri, byte[] plainText)
        {
            EncryptedData encryptedData = new EncryptedData();

            encryptedData.Algorithm = null;
            encryptedData.Data      = plainText;

            // check if nothing to do.
            if (plainText == null)
            {
                return(encryptedData);
            }

            // nothing more to do if no encryption.
            if (String.IsNullOrEmpty(securityPolicyUri))
            {
                return(encryptedData);
            }

            // encrypt data.
            switch (securityPolicyUri)
            {
            case SecurityPolicies.Basic256:
            case SecurityPolicies.Basic256Sha256:
            case SecurityPolicies.Aes128_Sha256_RsaOaep:
            {
                encryptedData.Algorithm = SecurityAlgorithms.RsaOaep;
                encryptedData.Data      = RsaUtils.Encrypt(plainText, certificate, RsaUtils.Padding.OaepSHA1);
                break;
            }

            case SecurityPolicies.Basic128Rsa15:
            {
                encryptedData.Algorithm = SecurityAlgorithms.Rsa15;
                encryptedData.Data      = RsaUtils.Encrypt(plainText, certificate, RsaUtils.Padding.Pkcs1);
                break;
            }

            case SecurityPolicies.Aes256_Sha256_RsaPss:
            {
                encryptedData.Algorithm = SecurityAlgorithms.RsaOaepSha256;
                encryptedData.Data      = RsaUtils.Encrypt(plainText, certificate, RsaUtils.Padding.OaepSHA256);
                break;
            }

            case SecurityPolicies.None:
            {
                break;
            }

            default:
            {
                throw ServiceResultException.Create(
                          StatusCodes.BadSecurityPolicyRejected,
                          "Unsupported security policy: {0}",
                          securityPolicyUri);
            }
            }

            return(encryptedData);
        }
        /// <summary>
        /// Verifies the signature using the SecurityPolicyUri and return true if valid.
        /// </summary>
        public static bool Verify(X509Certificate2 certificate, string securityPolicyUri, byte[] dataToVerify, SignatureData signature)
        {
            // check if nothing to do.
            if (signature == null)
            {
                return(true);
            }

            // nothing more to do if no encryption.
            if (String.IsNullOrEmpty(securityPolicyUri))
            {
                return(true);
            }

            // decrypt data.
            switch (securityPolicyUri)
            {
            case SecurityPolicies.Basic256:
            case SecurityPolicies.Basic128Rsa15:
            {
                if (signature.Algorithm == SecurityAlgorithms.RsaSha1)
                {
                    return(RsaUtils.Rsa_Verify(new ArraySegment <byte>(dataToVerify), signature.Signature, certificate, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1));
                }
                throw ServiceResultException.Create(
                          StatusCodes.BadSecurityChecksFailed,
                          "Unexpected signature algorithm for Basic256/Basic128Rsa15: {0}\n" +
                          "Expected signature algorithm: {1}",
                          signature.Algorithm,
                          SecurityAlgorithms.RsaSha1);
            }

            case SecurityPolicies.Aes128_Sha256_RsaOaep:
            case SecurityPolicies.Basic256Sha256:
            {
                if (signature.Algorithm == SecurityAlgorithms.RsaSha256)
                {
                    return(RsaUtils.Rsa_Verify(new ArraySegment <byte>(dataToVerify), signature.Signature, certificate, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
                }
                throw ServiceResultException.Create(
                          StatusCodes.BadSecurityChecksFailed,
                          "Unexpected signature algorithm for Basic256Sha256/Aes128_Sha256_RsaOaep: {0}\n" +
                          "Expected signature algorithm: {1}",
                          signature.Algorithm,
                          SecurityAlgorithms.RsaSha256);
            }

            case SecurityPolicies.Aes256_Sha256_RsaPss:
            {
                if (signature.Algorithm == SecurityAlgorithms.RsaPssSha256)
                {
                    return(RsaUtils.Rsa_Verify(new ArraySegment <byte>(dataToVerify), signature.Signature, certificate, HashAlgorithmName.SHA256, RSASignaturePadding.Pss));
                }
                throw ServiceResultException.Create(
                          StatusCodes.BadSecurityChecksFailed,
                          "Unexpected signature algorithm for Aes256_Sha256_RsaPss: {0}\n" +
                          "Expected signature algorithm : {1}",
                          signature.Algorithm,
                          SecurityAlgorithms.RsaPssSha256);
            }

            // always accept signatures if security is not used.
            case SecurityPolicies.None:
            {
                return(true);
            }

            default:
            {
                throw ServiceResultException.Create(
                          StatusCodes.BadSecurityPolicyRejected,
                          "Unsupported security policy: {0}",
                          securityPolicyUri);
            }
            }

            throw ServiceResultException.Create(
                      StatusCodes.BadSecurityChecksFailed,
                      "Unexpected security policy Uri: {0}",
                      securityPolicyUri);
        }
Beispiel #5
0
        /// <summary>
        /// Ensures that the application configuration is valid.
        /// </summary>
        /// <param name="applicationType">Type of the application.</param>
        public virtual async Task Validate(ApplicationType applicationType)
        {
            if (String.IsNullOrEmpty(ApplicationName))
            {
                throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "ApplicationName must be specified.");
            }

            if (SecurityConfiguration == null)
            {
                throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "SecurityConfiguration must be specified.");
            }

            SecurityConfiguration.Validate();

            // load private key
            await SecurityConfiguration.ApplicationCertificate.LoadPrivateKey(null);

            Func <string> generateDefaultUri = () => {
                var sb = new StringBuilder();
                sb.Append("urn:");
                sb.Append(Utils.GetHostName());
                sb.Append(":");
                sb.Append(ApplicationName);
                return(sb.ToString());
            };

            if (String.IsNullOrEmpty(ApplicationUri))
            {
                m_applicationUri = generateDefaultUri();
            }

            if (applicationType == ApplicationType.Client || applicationType == ApplicationType.ClientAndServer)
            {
                if (ClientConfiguration == null)
                {
                    throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "ClientConfiguration must be specified.");
                }

                ClientConfiguration.Validate();
            }

            if (applicationType == ApplicationType.Server || applicationType == ApplicationType.ClientAndServer)
            {
                if (ServerConfiguration == null)
                {
                    throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "ServerConfiguration must be specified.");
                }

                ServerConfiguration.Validate();
            }

            if (applicationType == ApplicationType.DiscoveryServer)
            {
                if (DiscoveryServerConfiguration == null)
                {
                    throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "DiscoveryServerConfiguration must be specified.");
                }

                DiscoveryServerConfiguration.Validate();
            }

            // toggle the state of the hi-res clock.
            HiResClock.Disabled = m_disableHiResClock;

            if (m_disableHiResClock)
            {
                if (m_serverConfiguration != null)
                {
                    if (m_serverConfiguration.PublishingResolution < 50)
                    {
                        m_serverConfiguration.PublishingResolution = 50;
                    }
                }
            }

            await m_certificateValidator.Update(this.SecurityConfiguration);
        }
        /// <summary>
        /// Creates a new UA-binary transport channel if requested. Null otherwise.
        /// </summary>
        /// <param name="configuration">The application configuration.</param>
        /// <param name="description">The description for the endpoint.</param>
        /// <param name="endpointConfiguration">The configuration to use with the endpoint.</param>
        /// <param name="clientCertificate">The client certificate.</param>
        /// <param name="clientCertificateChain">The client certificate chain.</param>
        /// <param name="messageContext">The message context to use when serializing the messages.</param>
        /// <returns></returns>
        public static ITransportChannel CreateUaBinaryChannel(
            ApplicationConfiguration configuration,
            EndpointDescription description,
            EndpointConfiguration endpointConfiguration,
            X509Certificate2 clientCertificate,
            X509Certificate2Collection clientCertificateChain,
            IServiceMessageContext messageContext)
        {
            string uriScheme = new Uri(description.EndpointUrl).Scheme;

            switch (description.TransportProfileUri)
            {
            case Profiles.UaTcpTransport:
            {
                uriScheme = Utils.UriSchemeOpcTcp;
                break;
            }

            case Profiles.HttpsBinaryTransport:
            {
                uriScheme = Utils.UriSchemeHttps;
                break;
            }

            case Profiles.UaWssTransport:
            {
                uriScheme = Utils.UriSchemeOpcWss;
                break;
            }
            }

            // initialize the channel which will be created with the server.
            ITransportChannel channel = TransportBindings.Channels.GetChannel(uriScheme);

            if (channel == null)
            {
                throw ServiceResultException.Create(
                          StatusCodes.BadProtocolVersionUnsupported,
                          "Unsupported transport profile for scheme {0}.", uriScheme);
            }

            // create a UA-TCP channel.
            TransportChannelSettings settings = new TransportChannelSettings {
                Description            = description,
                Configuration          = endpointConfiguration,
                ClientCertificate      = clientCertificate,
                ClientCertificateChain = clientCertificateChain
            };

            if (description.ServerCertificate != null && description.ServerCertificate.Length > 0)
            {
                settings.ServerCertificate = Utils.ParseCertificateBlob(description.ServerCertificate);
            }

            if (configuration != null)
            {
                settings.CertificateValidator = configuration.CertificateValidator.GetChannelValidator();
            }

            settings.NamespaceUris = messageContext.NamespaceUris;
            settings.Factory       = messageContext.Factory;

            channel.Initialize(new Uri(description.EndpointUrl), settings);
            channel.Open();

            return(channel);
        }
        /// <summary>
        /// Ensures that the application configuration is valid.
        /// </summary>
        /// <param name="applicationType">Type of the application.</param>
        public virtual void Validate(ApplicationType applicationType)
        {
            if (String.IsNullOrEmpty(ApplicationName))
            {
                throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "ApplicationName must be specified.");
            }

#if !SILVERLIGHT
            if (SecurityConfiguration == null)
            {
                throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "SecurityConfiguration must be specified.");
            }

            SecurityConfiguration.Validate();

            // ensure application uri matches the certificate.
            X509Certificate2 certificate = SecurityConfiguration.ApplicationCertificate.LoadPrivateKey(null);

            if (certificate != null)
            {
                ApplicationUri = Utils.GetApplicationUriFromCertficate(certificate);
            }
#endif

            //  generate a default uri.
            if (String.IsNullOrEmpty(ApplicationUri))
            {
                StringBuilder buffer = new StringBuilder();

                buffer.Append("urn:");
                buffer.Append(System.Net.Dns.GetHostName());
                buffer.Append(":");
                buffer.Append(ApplicationName);

                m_applicationUri = buffer.ToString();
            }

            if (applicationType == ApplicationType.Client || applicationType == ApplicationType.ClientAndServer)
            {
                if (ClientConfiguration == null)
                {
                    throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "ClientConfiguration must be specified.");
                }

                ClientConfiguration.Validate();
            }

            if (applicationType == ApplicationType.Server || applicationType == ApplicationType.ClientAndServer)
            {
                if (ServerConfiguration == null)
                {
                    throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "ServerConfiguration must be specified.");
                }

                ServerConfiguration.Validate();
            }

            if (applicationType == ApplicationType.DiscoveryServer)
            {
                if (DiscoveryServerConfiguration == null)
                {
                    throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "DiscoveryServerConfiguration must be specified.");
                }

                DiscoveryServerConfiguration.Validate();
            }

            // toggle the state of the hi-res clock.
            HiResClock.Disabled = m_disableHiResClock;

            if (m_disableHiResClock)
            {
                if (m_serverConfiguration != null)
                {
                    if (m_serverConfiguration.PublishingResolution < 50)
                    {
                        m_serverConfiguration.PublishingResolution = 50;
                    }
                }
            }

            #if !SILVERLIGHT
            // create the certificate validator.
            m_certificateValidator = new CertificateValidator();
            m_certificateValidator.Update(this.SecurityConfiguration);
            #endif
        }
        /// <summary>
        /// Throws an exception if validation fails.
        /// </summary>
        /// <param name="certificates">The certificates to be checked.</param>
        /// <exception cref="ServiceResultException">If certificate[0] cannot be accepted</exception>
        protected virtual async Task InternalValidate(X509Certificate2Collection certificates)
        {
            X509Certificate2 certificate = certificates[0];

            // check for previously validated certificate.
            X509Certificate2 certificate2 = null;

            if (m_validatedCertificates.TryGetValue(certificate.Thumbprint, out certificate2))
            {
                if (Utils.IsEqual(certificate2.RawData, certificate.RawData))
                {
                    return;
                }
            }

            CertificateIdentifier trustedCertificate = await GetTrustedCertificate(certificate);

            // get the issuers (checks the revocation lists if using directory stores).
            List <CertificateIdentifier> issuers = new List <CertificateIdentifier>();
            bool isIssuerTrusted = await GetIssuers(certificates, issuers);

            // setup policy chain
            X509ChainPolicy policy = new X509ChainPolicy();

            policy.RevocationFlag    = X509RevocationFlag.EntireChain;
            policy.RevocationMode    = X509RevocationMode.NoCheck;
            policy.VerificationFlags = X509VerificationFlags.NoFlag;

            foreach (CertificateIdentifier issuer in issuers)
            {
                if ((issuer.ValidationOptions & CertificateValidationOptions.SuppressRevocationStatusUnknown) != 0)
                {
                    policy.VerificationFlags |= X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknown;
                    policy.VerificationFlags |= X509VerificationFlags.IgnoreCtlSignerRevocationUnknown;
                    policy.VerificationFlags |= X509VerificationFlags.IgnoreEndRevocationUnknown;
                    policy.VerificationFlags |= X509VerificationFlags.IgnoreRootRevocationUnknown;
                }

                // we did the revocation check in the GetIssuers call. No need here.
                policy.RevocationMode = X509RevocationMode.NoCheck;
                policy.ExtraStore.Add(issuer.Certificate);
            }

            // build chain.
            bool      chainStatusChecked = false;
            X509Chain chain = new X509Chain();

            chain.ChainPolicy = policy;
            chain.Build(certificate);

            // check the chain results.
            CertificateIdentifier target = trustedCertificate;

            if (target == null)
            {
                target = new CertificateIdentifier(certificate);
            }

            for (int ii = 0; ii < chain.ChainElements.Count; ii++)
            {
                X509ChainElement element = chain.ChainElements[ii];

                CertificateIdentifier issuer = null;

                if (ii < issuers.Count)
                {
                    issuer = issuers[ii];
                }

                // check for chain status errors.
                foreach (X509ChainStatus status in element.ChainElementStatus)
                {
                    ServiceResult result = CheckChainStatus(status, target, issuer, (ii != 0));

                    if (ServiceResult.IsBad(result))
                    {
                        // check untrusted certificates.
                        if (trustedCertificate == null)
                        {
                            throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed);
                        }

                        throw new ServiceResultException(result);
                    }
                    chainStatusChecked = true;
                }

                if (issuer != null)
                {
                    target = issuer;
                }
            }

            // check whether the chain is complete (if there is a chain)
            bool issuedByCA      = !Utils.CompareDistinguishedName(certificate.Subject, certificate.Issuer);
            bool chainIncomplete = false;

            if (issuers.Count > 0)
            {
                var rootCertificate = issuers[issuers.Count - 1].Certificate;
                if (!Utils.CompareDistinguishedName(rootCertificate.Subject, rootCertificate.Issuer))
                {
                    chainIncomplete = true;
                }
            }
            else
            {
                if (issuedByCA)
                {
                    // no issuer found at all
                    chainIncomplete = true;
                }
            }

            if (issuedByCA && (!chainStatusChecked || chainIncomplete))
            {
                throw ServiceResultException.Create(
                          StatusCodes.BadCertificateChainIncomplete,
                          "Certificate chain validation incomplete.\r\nSubjectName: {0}\r\nIssuerName: {1}",
                          certificate.SubjectName.Name,
                          certificate.IssuerName.Name);
            }

            // check if certificate issuer is trusted.
            if (issuedByCA && !isIssuerTrusted && trustedCertificate == null)
            {
                if (m_applicationCertificate == null || !Utils.IsEqual(m_applicationCertificate.RawData, certificate.RawData))
                {
                    throw ServiceResultException.Create(
                              StatusCodes.BadCertificateUntrusted,
                              "Certificate issuer is not trusted.\r\nSubjectName: {0}\r\nIssuerName: {1}",
                              certificate.SubjectName.Name,
                              certificate.IssuerName.Name);
                }
            }

            // check if certificate is trusted.
            if (trustedCertificate == null && !isIssuerTrusted)
            {
                if (m_applicationCertificate == null || !Utils.IsEqual(m_applicationCertificate.RawData, certificate.RawData))
                {
                    throw ServiceResultException.Create(
                              StatusCodes.BadCertificateUntrusted,
                              "Certificate is not trusted.\r\nSubjectName: {0}\r\nIssuerName: {1}",
                              certificate.SubjectName.Name,
                              certificate.IssuerName.Name);
                }
            }

            // check if certificate is valid for use as app/sw or user cert
            X509KeyUsageFlags certificateKeyUsage = CertificateFactory.GetKeyUsage(certificate);

            if ((certificateKeyUsage & X509KeyUsageFlags.DataEncipherment) == 0)
            {
                throw new ServiceResultException(StatusCodes.BadCertificateUseNotAllowed, "Usage of certificate is not allowed.");
            }

            // check if minimum requirements are met
            if (m_rejectSHA1SignedCertificates && IsSHA1SignatureAlgorithm(certificate.SignatureAlgorithm))
            {
                throw new ServiceResultException(StatusCodes.BadCertificatePolicyCheckFailed, "SHA1 signed certificates are not trusted");
            }

            if (certificate.GetRSAPublicKey().KeySize < m_minimumCertificateKeySize)
            {
                throw new ServiceResultException(StatusCodes.BadCertificatePolicyCheckFailed, "Certificate doesn't meet minimum key length requirement");
            }
        }
Beispiel #9
0
        /// <summary>
        /// Updates an endpoint with information from the server's discovery endpoint.
        /// </summary>
        public void UpdateFromServer(
            Uri endpointUrl,
            MessageSecurityMode securityMode,
            string securityPolicyUri)
        {
            // get the a discovery url.
            Uri discoveryUrl = GetDiscoveryUrl(endpointUrl);

            // create the discovery client.
            DiscoveryClient client = DiscoveryClient.Create(discoveryUrl, m_configuration);

            try
            {
                // get the endpoints.
                EndpointDescriptionCollection collection = client.GetEndpoints(null);

                if (collection == null || collection.Count == 0)
                {
                    throw ServiceResultException.Create(
                              StatusCodes.BadUnknownResponse,
                              "Server does not have any endpoints defined.");
                }

                // find list of matching endpoints.
                EndpointDescriptionCollection matches = new EndpointDescriptionCollection();

                // first pass - match on the requested security parameters.
                foreach (EndpointDescription description in collection)
                {
                    // check for match on security policy.
                    if (!String.IsNullOrEmpty(securityPolicyUri))
                    {
                        if (securityPolicyUri != description.SecurityPolicyUri)
                        {
                            continue;
                        }
                    }

                    // check for match on security mode.
                    if (securityMode != MessageSecurityMode.Invalid)
                    {
                        if (securityMode != description.SecurityMode)
                        {
                            continue;
                        }
                    }

                    // add to list of matches.
                    matches.Add(description);
                }

                // no matches (security parameters may have changed).
                if (matches.Count == 0)
                {
                    matches = collection;
                }

                // check if list has to be narrowed down further.
                if (matches.Count > 1)
                {
                    collection = matches;
                    matches    = new EndpointDescriptionCollection();

                    // second pass - match on the url scheme.
                    foreach (EndpointDescription description in collection)
                    {
                        // parse the endpoint url.
                        Uri sessionUrl = Utils.ParseUri(description.EndpointUrl);

                        if (sessionUrl == null)
                        {
                            continue;
                        }

                        // check for matching protocol.
                        if (sessionUrl.Scheme != endpointUrl.Scheme)
                        {
                            continue;
                        }

                        matches.Add(description);
                    }
                }

                // no matches (protocol may not be supported).
                if (matches.Count == 0)
                {
                    matches = collection;
                }

                // choose first in list by default.
                EndpointDescription match = matches[0];

                // check if list has to be narrowed down further.
                if (matches.Count > 1)
                {
                    // third pass - match based on security level.
                    foreach (EndpointDescription description in matches)
                    {
                        if (description.SecurityMode > match.SecurityMode)
                        {
                            match = description;
                        }
                    }
                }

                // check if the endpoint url matches the endpoint used in the request.
                Uri matchUrl = Utils.ParseUri(match.EndpointUrl);

                if (matchUrl == null || String.Compare(discoveryUrl.DnsSafeHost, matchUrl.DnsSafeHost, StringComparison.OrdinalIgnoreCase) != 0)
                {
                    UriBuilder uri = new UriBuilder(matchUrl);
                    uri.Host          = discoveryUrl.DnsSafeHost;
                    uri.Port          = discoveryUrl.Port;
                    match.EndpointUrl = uri.ToString();

                    // need to update the discovery urls.
                    match.Server.DiscoveryUrls.Clear();
                    match.Server.DiscoveryUrls.Add(discoveryUrl.ToString());
                }

                // update the endpoint.
                Update(match);
            }
            finally
            {
                client.Close();
            }
        }
Beispiel #10
0
        /// <summary>
        /// Returns the issuers for the certificates.
        /// </summary>
        public bool GetIssuersWithChainSupportEnabled(X509Certificate2Collection certificates,
                                                      List <CertificateIdentifier> issuers)
        {
            bool isTrusted                    = false;
            bool isChainComplete              = false;
            CertificateIdentifier issuer      = null;
            X509Certificate2      certificate = certificates[0];

            // application certificate is trusted
            CertificateIdentifier trustedCertificate = GetTrustedCertificate(certificate);

            if (trustedCertificate != null)
            {
                isTrusted = true;
            }

            if (Utils.CompareDistinguishedName(certificate.Subject, certificate.Issuer))
            {
                if (!isTrusted)
                {
                    throw ServiceResultException.Create(
                              StatusCodes.BadCertificateUntrusted,
                              "Self Signed Certificate is not trusted.\r\nIssuerName: {0}",
                              certificate.IssuerName.Name);
                }

                return(isTrusted);
            }

            CertificateIdentifierCollection collection = new CertificateIdentifierCollection();

            for (int ii = 1; ii < certificates.Count; ii++)
            {
                collection.Add(new CertificateIdentifier(certificates[ii]));
            }

            do
            {
                issuer = GetIssuer(certificate, m_trustedCertificateList, m_trustedCertificateStore, true);
                if (issuer != null)
                {
                    isTrusted = true;
                }

                if (issuer == null)
                {
                    issuer = GetIssuer(certificate, m_issuerCertificateList, m_issuerCertificateStore, true);

                    if (issuer == null)
                    {
                        issuer = GetIssuer(certificate, collection, null, true);
                    }
                }

                if (issuer != null)
                {
                    //isTrusted = true;

                    issuers.Add(issuer);
                    certificate = issuer.Find(false);

                    // check for root.
                    if (Utils.CompareDistinguishedName(certificate.Subject, certificate.Issuer))
                    {
                        isChainComplete = true;
                        break;
                    }
                }
                else
                {
                    isTrusted = false;
                }
            } while (issuer != null);

            if (!isChainComplete)
            {
                throw ServiceResultException.Create(
                          StatusCodes.BadSecurityChecksFailed,
                          "Certificate chain not complete.\r\nSubjectName: {0}\r\nIssuerName: {1}",
                          certificates[0].SubjectName.Name,
                          certificates[0].IssuerName.Name);
            }

            if (!isTrusted)
            {
                throw ServiceResultException.Create(
                          StatusCodes.BadCertificateUntrusted,
                          "Certificate issuer is not trusted.\r\nSubjectName: {0}\r\nIssuerName: {1}",
                          certificates[0].SubjectName.Name,
                          certificates[0].IssuerName.Name);
            }

            return(isTrusted);
        }
        /// <summary>
        /// Creates a new UA-binary transport channel if requested. Null otherwise.
        /// </summary>
        /// <param name="configuration">The application configuration.</param>
        /// <param name="description">The description for the endpoint.</param>
        /// <param name="endpointConfiguration">The configuration to use with the endpoint.</param>
        /// <param name="clientCertificate">The client certificate.</param>
        /// <param name="messageContext">The message context to use when serializing the messages.</param>
        /// <returns></returns>
        public static ITransportChannel CreateUaBinaryChannel(
            ApplicationConfiguration configuration,
            EndpointDescription description,
            EndpointConfiguration endpointConfiguration,
            X509Certificate2 clientCertificate,
            ServiceMessageContext messageContext)
        {
            // check if the server if configured to use the ANSI C stack.
            bool useUaTcp = description.EndpointUrl.StartsWith(Utils.UriSchemeOpcTcp);
            bool useHttps = description.EndpointUrl.StartsWith(Utils.UriSchemeHttps);

            bool useAnsiCStack = false;

            switch (description.TransportProfileUri)
            {
            case Profiles.UaTcpTransport:
            {
                useUaTcp = true;

                if (configuration != null)
                {
                    useAnsiCStack = configuration.UseNativeStack;
                }

                break;
            }

            case Profiles.HttpsXmlTransport:
            case Profiles.HttpsBinaryTransport:
            case Profiles.HttpsXmlOrBinaryTransport:
            {
                useHttps = true;
                break;
            }
            }

            // note: WCF channels are not supported
            if (!useUaTcp && !useHttps)
            {
                throw ServiceResultException.Create(
                          StatusCodes.BadServiceUnsupported,
                          "Unsupported transport profile\r\n");
            }

            // initialize the channel which will be created with the server.
            ITransportChannel channel = null;

            // create a UA-TCP channel.
            TransportChannelSettings settings = new TransportChannelSettings();

            settings.Description       = description;
            settings.Configuration     = endpointConfiguration;
            settings.ClientCertificate = clientCertificate;

            if (description.ServerCertificate != null && description.ServerCertificate.Length > 0)
            {
                settings.ServerCertificate = Utils.ParseCertificateBlob(description.ServerCertificate);
            }

            if (configuration != null)
            {
                settings.CertificateValidator = configuration.CertificateValidator.GetChannelValidator();
            }

            settings.NamespaceUris = messageContext.NamespaceUris;
            settings.Factory       = messageContext.Factory;

            if (useUaTcp)
            {
                Type type = null;

                if (useAnsiCStack)
                {
                    type = Type.GetType("Opc.Ua.NativeStack.NativeStackChannel,Opc.Ua.NativeStackWrapper");
                }

                if (useAnsiCStack && type != null)
                {
                    channel = (ITransportChannel)Activator.CreateInstance(type);
                }
                else
                {
                    channel = new Opc.Ua.Bindings.TcpTransportChannel();
                }
            }
            else if (useHttps)
            {
                channel = new Opc.Ua.Bindings.HttpsTransportChannel();
            }

            channel.Initialize(new Uri(description.EndpointUrl), settings);
            channel.Open();

            return(channel);
        }
Beispiel #12
0
        /// <summary>
        /// Recursively builds the full inhierited type hierarchy starting with the top-level type.
        /// </summary>
        private void GetInstanceHierarchyForType(ExpandedNodeId typeId, InstanceDeclarationHierarchy hierarchy)
        {
            // the type must be local to the address space.
            ILocalNode type = m_nodes.Find(typeId) as ILocalNode;

            if (type == null)
            {
                throw ServiceResultException.Create(
                          StatusCodes.BadNodeIdUnknown,
                          "The type is not in the local address space.\r\nNodeId = {0}",
                          typeId);
            }

            // must be an object or variable type.
            if ((type.NodeClass & (NodeClass.ObjectType | NodeClass.VariableType)) == 0)
            {
                throw ServiceResultException.Create(
                          StatusCodes.BadNodeClassInvalid,
                          "The type node is not an ObjectType or VariableType.\r\nNodeId = {0}\r\nNodeClass = {1}",
                          typeId,
                          type.NodeClass);
            }

            // find hierarchy in supertypes first.
            foreach (IReference reference in type.References.Find(ReferenceTypeIds.HasSubtype, true, false, null))
            {
                GetInstanceHierarchyForType(reference.TargetId, hierarchy);
            }

            string browsePath = "/";

            // check if the browse path already exists in the hierarchy.
            HierarchyBrowsePath parent = null;

            if (!hierarchy.BrowsePaths.TryGetValue(browsePath, out parent))
            {
                parent = new HierarchyBrowsePath();

                parent.BrowsePath    = browsePath;
                parent.DeclarationId = type.NodeId;
                parent.InstanceId    = null;
                parent.IsModelParent = true;
                parent.IsOptional    = false;

                // add new browse path to hierarchy.
                hierarchy.BrowsePaths.Add(browsePath, parent);
            }

            // override any declaration specified in a supertype.
            parent.DeclarationId = type.NodeId;
            hierarchy.Declarations[type.NodeId] = parent;

            // follow hierarchial references to nodes with a naming rule of unique or unique optional.
            foreach (IReference reference in type.References.Find(ReferenceTypeIds.HierarchicalReferences, false, true, m_nodes.TypeTree))
            {
                GetInstanceHierarchyForType(parent, reference.TargetId, hierarchy);
            }

            // update references defined in the type.
            foreach (HierarchyBrowsePath declaration in hierarchy.Declarations.Values)
            {
                // the declaration must be local to the address space.
                ILocalNode declarationNode = m_nodes.Find(declaration.DeclarationId) as ILocalNode;

                if (declarationNode == null)
                {
                    continue;
                }

                // process all references.
                foreach (IReference reference in declarationNode.References)
                {
                    UpdateReferenceDeclaration(declaration, reference, hierarchy);
                }
            }
        }
Beispiel #13
0
        /// <summary>
        /// Writes the given value in raw format without meta information.
        /// </summary>
        /// <param name="encoder">The encoder to use.</param>
        /// <param name="fieldName">The name of the field.</param>
        /// <param name="value">The value to write.</param>
        /// <param name="typeInfo">The type of the value.</param>
        /// <exception cref="NotImplementedException"></exception>
        /// <exception cref="ServiceResultException"></exception>
        public static void WriteRaw(this IEncoder encoder, string fieldName, object value, TypeInfo typeInfo)
        {
            if (value != null)
            {
                if (typeInfo.ValueRank < 0)
                {
                    switch (typeInfo.BuiltInType)
                    {
                    case BuiltInType.Boolean:
                        encoder.WriteBoolean(fieldName, (bool)value);
                        return;

                    case BuiltInType.SByte:
                        encoder.WriteSByte(fieldName, (sbyte)value);
                        return;

                    case BuiltInType.Byte:
                        encoder.WriteByte(fieldName, (byte)value);
                        return;

                    case BuiltInType.Int16:
                        encoder.WriteInt16(fieldName, (short)value);
                        return;

                    case BuiltInType.UInt16:
                        encoder.WriteUInt16(fieldName, (ushort)value);
                        return;

                    case BuiltInType.Int32:
                        encoder.WriteInt32(fieldName, (int)value);
                        return;

                    case BuiltInType.UInt32:
                        encoder.WriteUInt32(fieldName, (uint)value);
                        return;

                    case BuiltInType.Int64:
                        encoder.WriteInt64(fieldName, (long)value);
                        return;

                    case BuiltInType.UInt64:
                        encoder.WriteUInt64(fieldName, (ulong)value);
                        return;

                    case BuiltInType.Float:
                        encoder.WriteFloat(fieldName, (float)value);
                        return;

                    case BuiltInType.Double:
                        encoder.WriteDouble(fieldName, (double)value);
                        return;

                    case BuiltInType.String:
                        encoder.WriteString(fieldName, (string)value);
                        return;

                    case BuiltInType.DateTime:
                        encoder.WriteDateTime(fieldName, (DateTime)value);
                        return;

                    case BuiltInType.Guid:
                        encoder.WriteGuid(fieldName, (Uuid)value);
                        return;

                    case BuiltInType.ByteString:
                        encoder.WriteByteString(fieldName, (byte[])value);
                        return;

                    case BuiltInType.XmlElement:
                        encoder.WriteXmlElement(fieldName, (XmlElement)value);
                        return;

                    case BuiltInType.NodeId:
                        encoder.WriteNodeId(fieldName, (NodeId)value);
                        return;

                    case BuiltInType.ExpandedNodeId:
                        encoder.WriteExpandedNodeId(fieldName, (ExpandedNodeId)value);
                        return;

                    case BuiltInType.StatusCode:
                        encoder.WriteStatusCode(fieldName, (StatusCode)value);
                        return;

                    case BuiltInType.QualifiedName:
                        encoder.WriteQualifiedName(fieldName, (QualifiedName)value);
                        return;

                    case BuiltInType.LocalizedText:
                        encoder.WriteLocalizedText(fieldName, (LocalizedText)value);
                        return;

                    case BuiltInType.ExtensionObject:
                        encoder.WriteExtensionObject(fieldName, (ExtensionObject)value);
                        return;

                    case BuiltInType.DataValue:
                        encoder.WriteDataValue(fieldName, (DataValue)value);
                        return;

                    case BuiltInType.Enumeration:
                        encoder.WriteInt32(fieldName, (int)value);
                        return;
                    }
                }
                else if (typeInfo.ValueRank <= 1)
                {
                    switch (typeInfo.BuiltInType)
                    {
                    case BuiltInType.Boolean:
                        encoder.WriteBooleanArray(fieldName, (bool[])value);
                        return;

                    case BuiltInType.SByte:
                        encoder.WriteSByteArray(fieldName, (sbyte[])value);
                        return;

                    case BuiltInType.Byte:
                        encoder.WriteByteArray(fieldName, (byte[])value);
                        return;

                    case BuiltInType.Int16:
                        encoder.WriteInt16Array(fieldName, (short[])value);
                        return;

                    case BuiltInType.UInt16:
                        encoder.WriteUInt16Array(fieldName, (ushort[])value);
                        return;

                    case BuiltInType.Int32:
                        encoder.WriteInt32Array(fieldName, (int[])value);
                        return;

                    case BuiltInType.UInt32:
                        encoder.WriteUInt32Array(fieldName, (uint[])value);
                        return;

                    case BuiltInType.Int64:
                        encoder.WriteInt64Array(fieldName, (long[])value);
                        return;

                    case BuiltInType.UInt64:
                        encoder.WriteUInt64Array(fieldName, (ulong[])value);
                        return;

                    case BuiltInType.Float:
                        encoder.WriteFloatArray(fieldName, (float[])value);
                        return;

                    case BuiltInType.Double:
                        encoder.WriteDoubleArray(fieldName, (double[])value);
                        return;

                    case BuiltInType.String:
                        encoder.WriteStringArray(fieldName, (string[])value);
                        return;

                    case BuiltInType.DateTime:
                        encoder.WriteDateTimeArray(fieldName, (DateTime[])value);
                        return;

                    case BuiltInType.Guid:
                        encoder.WriteGuidArray(fieldName, (Uuid[])value);
                        return;

                    case BuiltInType.ByteString:
                        encoder.WriteByteStringArray(fieldName, (byte[][])value);
                        return;

                    case BuiltInType.XmlElement:
                        encoder.WriteXmlElementArray(fieldName, (XmlElement[])value);
                        return;

                    case BuiltInType.NodeId:
                        encoder.WriteNodeIdArray(fieldName, (NodeId[])value);
                        return;

                    case BuiltInType.ExpandedNodeId:
                        encoder.WriteExpandedNodeIdArray(fieldName, (ExpandedNodeId[])value);
                        return;

                    case BuiltInType.StatusCode:
                        encoder.WriteStatusCodeArray(fieldName, (StatusCode[])value);
                        return;

                    case BuiltInType.QualifiedName:
                        encoder.WriteQualifiedNameArray(fieldName, (QualifiedName[])value);
                        return;

                    case BuiltInType.LocalizedText:
                        encoder.WriteLocalizedTextArray(fieldName, (LocalizedText[])value);
                        return;

                    case BuiltInType.ExtensionObject:
                        encoder.WriteExtensionObjectArray(fieldName, (ExtensionObject[])value);
                        return;

                    case BuiltInType.DataValue:
                        encoder.WriteDataValueArray(fieldName, (DataValue[])value);
                        return;

                    case BuiltInType.Variant:
                        if (value is Variant[] variantArray)
                        {
                            encoder.WriteVariantArray(fieldName, variantArray);
                            return;
                        }
                        if (value is object[] objArray)
                        {
                            throw new NotImplementedException();
                        }
                        throw ServiceResultException.Create(2147876864U, "Unexpected type encountered while encoding an array of Variants: {0}", (object)value.GetType());

                    case BuiltInType.Enumeration:
                        var enumArray = value as Enum[];
                        var strArray  = new string[enumArray.Length];

                        for (var index = 0; index < enumArray.Length; ++index)
                        {
                            var str = enumArray[index].ToString() + "_" + enumArray[index].As <int>().ToString(CultureInfo.InvariantCulture);
                            strArray[index] = str;
                        }
                        encoder.WriteStringArray(null, strArray);
                        return;
                    }
                }
                else if (typeInfo.ValueRank > 1)
                {
                    encoder.WriteMatrix(fieldName, (Matrix)value);
                    return;
                }
                throw new ServiceResultException(2147876864U, Utils.Format("Type '{0}' is not allowed in an Variant.", (object)value.GetType().FullName));
            }
        }
        /// <summary>
        /// Pushes a new element onto the stack.
        /// </summary>
        /// <param name="op">The filter operator.</param>
        /// <param name="operands">The operands.</param>
        /// <returns></returns>
        public ContentFilterElement Push(FilterOperator op, params object[] operands)
        {
            // check if nothing more to do.
            if (operands == null || operands.Length == 0)
            {
                throw ServiceResultException.Create(StatusCodes.BadInvalidArgument, "ContentFilterElement does not have an operands.");
            }

            // create the element and set the operator.
            ContentFilterElement element = new ContentFilterElement();

            element.FilterOperator = op;

            for (int ii = 0; ii < operands.Length; ii++)
            {
                // check if a FilterOperand was provided.
                FilterOperand filterOperand = operands[ii] as FilterOperand;

                if (filterOperand != null)
                {
                    element.FilterOperands.Add(new ExtensionObject(filterOperand));
                    continue;
                }

                // check for reference to another ContentFilterElement.
                ContentFilterElement existingElement = operands[ii] as ContentFilterElement;

                if (existingElement != null)
                {
                    int index = FindElementIndex(existingElement);

                    if (index == -1)
                    {
                        throw ServiceResultException.Create(StatusCodes.BadInvalidArgument, "ContentFilterElement is not part of the ContentFilter.");
                    }

                    ElementOperand operand = new ElementOperand();
                    operand.Index = (uint)index;

                    element.FilterOperands.Add(new ExtensionObject(operand));
                    continue;
                }

                // assume a literal operand.
                LiteralOperand literalOperand = new LiteralOperand();
                literalOperand.Value = new Variant(operands[ii]);
                element.FilterOperands.Add(new ExtensionObject(literalOperand));
            }

            // insert the new element at the begining of the list.
            m_elements.Insert(0, element);

            // re-number ElementOperands since all element were shifted up.
            for (int ii = 0; ii < m_elements.Count; ii++)
            {
                foreach (ExtensionObject extension in m_elements[ii].FilterOperands)
                {
                    if (extension != null)
                    {
                        ElementOperand operand = extension.Body as ElementOperand;

                        if (operand != null)
                        {
                            operand.Index++;
                        }
                    }
                }
            }

            // return new element.
            return(element);
        }
Beispiel #15
0
        /// <summary>
        /// Adds a node to the type table if it is a type and does not already exist. If it exists references are updated.
        /// </summary>
        /// <param name="node">The node.</param>
        public void Add(ILocalNode node)
        {
            // ignore null.
            if (node == null || NodeId.IsNull(node.NodeId))
            {
                return;
            }

            // ignore non-types.
            if ((node.NodeClass & (NodeClass.ObjectType | NodeClass.VariableType | NodeClass.ReferenceType | NodeClass.DataType)) == 0)
            {
                return;
            }

            NodeId localsuperTypeId = null;

            // find the supertype.
            ExpandedNodeId superTypeId = node.References.FindTarget(ReferenceTypeIds.HasSubtype, true, false, null, 0);

            if (superTypeId != null)
            {
                localsuperTypeId = ExpandedNodeId.ToNodeId(superTypeId, m_namespaceUris);

                if (localsuperTypeId == null)
                {
                    throw ServiceResultException.Create(StatusCodes.BadNodeIdInvalid, "A valid supertype identifier is required.");
                }
            }

            lock (m_lock)
            {
                // lookup the supertype.
                TypeInfo superTypeInfo = null;

                if (localsuperTypeId != null)
                {
                    if (!m_nodes.TryGetValue(localsuperTypeId, out superTypeInfo))
                    {
                        throw ServiceResultException.Create(StatusCodes.BadNodeIdInvalid, "A valid supertype identifier is required.");
                    }
                }

                // create the type info.
                TypeInfo typeInfo = null;

                if (!m_nodes.TryGetValue(node.NodeId, out typeInfo))
                {
                    typeInfo = new TypeInfo();
                    m_nodes.Add(node.NodeId, typeInfo);
                }

                // update the info.
                typeInfo.NodeId    = node.NodeId;
                typeInfo.SuperType = superTypeInfo;
                typeInfo.Deleted   = false;

                // add to supertype.
                if (superTypeInfo != null)
                {
                    superTypeInfo.AddSubType(typeInfo);
                }

                // remove the encodings.
                if (typeInfo.Encodings != null)
                {
                    foreach (NodeId encoding in typeInfo.Encodings)
                    {
                        m_encodings.Remove(encoding);
                    }
                }

                // any new encodings.
                IList <IReference> encodings = node.References.Find(ReferenceTypeIds.HasEncoding, false, false, null);

                if (encodings.Count > 0)
                {
                    typeInfo.Encodings = new NodeId[encodings.Count];

                    for (int ii = 0; ii < encodings.Count; ii++)
                    {
                        typeInfo.Encodings[ii] = ExpandedNodeId.ToNodeId(encodings[ii].TargetId, m_namespaceUris);
                        m_encodings[typeInfo.Encodings[ii]] = typeInfo;
                    }
                }

                // add reference type.
                if ((node.NodeClass & NodeClass.ReferenceType) != 0)
                {
                    if (!QualifiedName.IsNull(typeInfo.BrowseName))
                    {
                        m_referenceTypes.Remove(typeInfo.BrowseName);
                    }

                    typeInfo.BrowseName = node.BrowseName;

                    m_referenceTypes[node.BrowseName] = typeInfo;
                }
            }
        }
Beispiel #16
0
        /// <summary>
        /// Decrypts the CipherText using the SecurityPolicyUri and returns the PlainTetx.
        /// </summary>
        public static byte[] Decrypt(X509Certificate2 certificate, string securityPolicyUri, EncryptedData dataToDecrypt)
        {
            // check if nothing to do.
            if (dataToDecrypt == null)
            {
                return(null);
            }

            // nothing more to do if no encryption.
            if (String.IsNullOrEmpty(securityPolicyUri))
            {
                return(dataToDecrypt.Data);
            }

            // decrypt data.
            switch (securityPolicyUri)
            {
            case SecurityPolicies.Basic256:
            case SecurityPolicies.Basic256Sha256:
            {
                if (dataToDecrypt.Algorithm == SecurityAlgorithms.RsaOaep)
                {
                    return(RsaUtils.Decrypt(new ArraySegment <byte>(dataToDecrypt.Data), certificate, true));
                }

                break;
            }

            case SecurityPolicies.Basic128Rsa15:
            {
                if (dataToDecrypt.Algorithm == SecurityAlgorithms.Rsa15)
                {
                    return(RsaUtils.Decrypt(new ArraySegment <byte>(dataToDecrypt.Data), certificate, false));
                }

                break;
            }

            case SecurityPolicies.None:
            {
                if (String.IsNullOrEmpty(dataToDecrypt.Algorithm))
                {
                    return(dataToDecrypt.Data);
                }

                break;
            }

            default:
            {
                throw ServiceResultException.Create(
                          StatusCodes.BadSecurityPolicyRejected,
                          "Unsupported security policy: {0}",
                          securityPolicyUri);
            }
            }

            throw ServiceResultException.Create(
                      StatusCodes.BadIdentityTokenInvalid,
                      "Unexpected encryption algorithm : {0}",
                      dataToDecrypt.Algorithm);
        }
Beispiel #17
0
        /// <summary>
        /// Creates a new UA-binary transport channel if requested. Null otherwise.
        /// </summary>
        /// <param name="configuration">The application configuration.</param>
        /// <param name="description">The description for the endpoint.</param>
        /// <param name="endpointConfiguration">The configuration to use with the endpoint.</param>
        /// <param name="clientCertificate">The client certificate.</param>
        /// <param name="clientCertificateChain">The client certificate chain.</param>
        /// <param name="messageContext">The message context to use when serializing the messages.</param>
        /// <returns></returns>
        public static ITransportChannel CreateUaBinaryChannel(
            ApplicationConfiguration configuration,
            EndpointDescription description,
            EndpointConfiguration endpointConfiguration,
            X509Certificate2 clientCertificate,
            X509Certificate2Collection clientCertificateChain,
            ServiceMessageContext messageContext)
        {
            bool useUaTcp = description.EndpointUrl.StartsWith(Utils.UriSchemeOpcTcp);
            bool useHttps = description.EndpointUrl.StartsWith(Utils.UriSchemeHttps);


            switch (description.TransportProfileUri)
            {
            case Profiles.UaTcpTransport:
            {
                useUaTcp = true;
                break;
            }

            case Profiles.HttpsBinaryTransport:
            {
                useHttps = true;
                break;
            }
            }

            // note: WCF channels are not supported
            if (!useUaTcp
#if !NO_HTTPS
                && !useHttps
#endif
                )
            {
                throw ServiceResultException.Create(
                          StatusCodes.BadProtocolVersionUnsupported,
                          "Unsupported transport profile\r\n");
            }

            // initialize the channel which will be created with the server.
            ITransportChannel channel = null;

            // create a UA-TCP channel.
            TransportChannelSettings settings = new TransportChannelSettings();

            settings.Description            = description;
            settings.Configuration          = endpointConfiguration;
            settings.ClientCertificate      = clientCertificate;
            settings.ClientCertificateChain = clientCertificateChain;

            if (description.ServerCertificate != null && description.ServerCertificate.Length > 0)
            {
                settings.ServerCertificate = Utils.ParseCertificateBlob(description.ServerCertificate);
            }

            if (configuration != null)
            {
                settings.CertificateValidator = configuration.CertificateValidator.GetChannelValidator();
            }

            settings.NamespaceUris = messageContext.NamespaceUris;
            settings.Factory       = messageContext.Factory;

            if (useUaTcp)
            {
                if (g_CustomTransportChannel != null)
                {
                    channel = g_CustomTransportChannel.Create();
                }
                else
                {
                    channel = new TcpTransportChannel();
                }
            }
            else if (useHttps)
            {
#if !NO_HTTPS
                channel = new HttpsTransportChannel();
#endif
            }

            channel.Initialize(new Uri(description.EndpointUrl), settings);
            channel.Open();

            return(channel);
        }
Beispiel #18
0
        /// <summary>
        /// Throws an exception if validation fails.
        /// </summary>
        /// <param name="certificate">The certificate to be checked.</param>
        /// <exception cref="ServiceResultException">If certificate cannot be accepted</exception>
        protected async virtual Task InternalValidate(X509Certificate2 certificate)
        {
            // check for previously validated certificate.
            X509Certificate2 certificate2 = null;

            if (m_validatedCertificates.TryGetValue(certificate.Thumbprint, out certificate2))
            {
                if (Utils.IsEqual(certificate2.RawData, certificate.RawData))
                {
                    return;
                }
            }

            CertificateIdentifier trustedCertificate = await GetTrustedCertificate(certificate);

            // get the issuers (checks the revocation lists if using directory stores).
            List <CertificateIdentifier> issuers = new List <CertificateIdentifier>();
            bool isIssuerTrusted = await GetIssuers(certificate, issuers);

            // setup policy chain
            X509ChainPolicy policy = new X509ChainPolicy();

            policy.RevocationFlag    = X509RevocationFlag.EntireChain;
            policy.RevocationMode    = X509RevocationMode.NoCheck;
            policy.VerificationFlags = X509VerificationFlags.NoFlag;

            foreach (CertificateIdentifier issuer in issuers)
            {
                if ((issuer.ValidationOptions & CertificateValidationOptions.SuppressRevocationStatusUnknown) != 0)
                {
                    policy.VerificationFlags |= X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknown;
                    policy.VerificationFlags |= X509VerificationFlags.IgnoreCtlSignerRevocationUnknown;
                    policy.VerificationFlags |= X509VerificationFlags.IgnoreEndRevocationUnknown;
                    policy.VerificationFlags |= X509VerificationFlags.IgnoreRootRevocationUnknown;
                }

                // we did the revocation check in the GetIssuers call. No need here.
                policy.RevocationMode = X509RevocationMode.NoCheck;
                policy.ExtraStore.Add(issuer.Certificate);
            }

            // build chain.
            X509Chain chain = new X509Chain();

            chain.ChainPolicy = policy;
            chain.Build(certificate);

            // check the chain results.
            CertificateIdentifier target = trustedCertificate;

            if (target == null)
            {
                target = new CertificateIdentifier(certificate);
            }

            for (int ii = 0; ii < chain.ChainElements.Count; ii++)
            {
                X509ChainElement element = chain.ChainElements[ii];

                CertificateIdentifier issuer = null;

                if (ii < issuers.Count)
                {
                    issuer = issuers[ii];
                }

                // check for chain status errors.
                foreach (X509ChainStatus status in element.ChainElementStatus)
                {
                    ServiceResult result = CheckChainStatus(status, target, issuer, (ii != 0));

                    if (ServiceResult.IsBad(result))
                    {
                        throw new ServiceResultException(result);
                    }
                }

                if (issuer != null)
                {
                    target = issuer;
                }
            }

            // check if certificate is trusted.
            if (trustedCertificate == null && !isIssuerTrusted)
            {
                if (m_applicationCertificate == null || !Utils.IsEqual(m_applicationCertificate.RawData, certificate.RawData))
                {
                    throw ServiceResultException.Create(
                              StatusCodes.BadCertificateUntrusted,
                              "Certificate is not trusted.\r\nSubjectName: {0}\r\nIssuerName: {1}",
                              certificate.SubjectName.Name,
                              certificate.IssuerName);
                }
            }
        }
Beispiel #19
0
        /// <inheritdoc cref="IEncodeable.Encode(IEncoder)" />
        public void Encode(IEncoder encoder)
        {
            encoder.WriteUInt32("UriVersion", UriVersion);
            if (NamespaceUris != null && NamespaceUris.Count > 1)
            {
                string[] uris = new string[NamespaceUris.Count - 1];

                for (int ii = 1; ii < NamespaceUris.Count; ii++)
                {
                    uris[ii - 1] = NamespaceUris.GetString((uint)ii);
                }

                encoder.WriteStringArray("NamespaceUris", uris);
            }
            else
            {
                encoder.WriteStringArray("NamespaceUris", Array.Empty <string>());
            }

            if (ServerUris != null && ServerUris.Count > 1)
            {
                string[] uris = new string[ServerUris.Count - 1];

                for (int ii = 1; ii < ServerUris.Count; ii++)
                {
                    uris[ii - 1] = ServerUris.GetString((uint)ii);
                }

                encoder.WriteStringArray("ServerUris", uris);
            }
            else
            {
                encoder.WriteStringArray("ServerUris", Array.Empty <string>());
            }

            if (LocaleIds != null && LocaleIds.Count > 1)
            {
                encoder.WriteStringArray("LocaleIds", LocaleIds.ToArray());
            }
            else
            {
                encoder.WriteStringArray("LocaleIds", Array.Empty <string>());
            }

            if (Message != null)
            {
                encoder.SetMappingTables(NamespaceUris, ServerUris);

                if (Message.TypeId == null || Message.TypeId.IdType != IdType.Numeric)
                {
                    throw ServiceResultException.Create(StatusCodes.BadEncodingError, "SessionLessServiceMessage message body must have a numeric TypeId defined. ({0})", Message.TypeId);
                }

                encoder.WriteUInt32("ServiceId", (uint)Message.TypeId.Identifier);
                encoder.WriteEncodeable("Body", Message, null);
            }
            else
            {
                encoder.WriteUInt32("TypeId", (uint)0);
            }
        }