Beispiel #1
0
        /// <summary>
        /// Initializes the object when it is created by the WCF framework.
        /// </summary>
        protected EndpointBase()
        {
            SupportedServices  = new SortedList<ExpandedNodeId,ServiceDefinition>();
            
            try
            {
                m_host = GetHostForContext();
                m_server = GetServerForContext();

                MessageContext = m_server.MessageContext;
                
                // update the message context for the channel.
                ChannelBase channel = OperationContext.Current.Channel.InputSession as ChannelBase;

                if (channel != null)
                {
                    TcpChannelQuotas quotas = channel.GetProperty<TcpChannelQuotas>();

                    if (quotas != null)
                    {
                        quotas.MessageContext = m_server.MessageContext;
                    }
                }

                EndpointDescription = GetEndpointDescription();
            }
            catch (Exception e)
            {
                ServerError = new ServiceResult(e);
                EndpointDescription = null;

                m_host = null;
                m_server = null;
            }
        }
 /// <summary>
 /// Constructs a object by specifying each property.
 /// </summary>
 public ServiceResult(
     StatusCode    code,
     ServiceResult innerResult)
 :
     this(code, null, null, null, null, innerResult)
 {
 }        
Beispiel #3
0
 /// <summary>
 /// Initializes object with default values.
 /// </summary>
 public ServerBase()
 {            
     m_messageContext = new ServiceMessageContext();
     m_serverError = new ServiceResult(StatusCodes.BadServerHalted);
     m_hosts = new List<ServiceHost>();
     m_listeners = new List<ITransportListener>();
     m_endpoints = null;
     m_requestQueue = new RequestQueue(this, 10, 100, 1000);
 }
		/// <summary>
		/// Initializes the exception with a status code.
		/// </summary>
		public ServiceResultException(uint statusCode) : base(GetMessage(statusCode))
		{
			m_status = new ServiceResult(statusCode);

            if ((Utils.TraceMask & Utils.TraceMasks.StackTrace) != 0)
            {
                Utils.Trace(Utils.TraceMasks.StackTrace, "***EXCEPTION*** {0}", m_status);
            }
		}
        /// <summary>
        /// Initializes the object with a ServiceResult.
        /// </summary>
        public StatusResult(ServiceResult result)
        {
            Initialize();

            m_result = result;

            if (result != null)
            {
                m_statusCode = result.StatusCode;
            }
        }
 /// <summary>
 /// Constructs a object by specifying each property.
 /// </summary>
 public ServiceResult(
     StatusCode    code,
     string        symbolicId,
     string        namespaceUri,
     LocalizedText localizedText,
     string        additionalInfo,
     ServiceResult innerResult)
 {
     StatusCode     = code;
     SymbolicId     = symbolicId;
     NamespaceUri   = namespaceUri;
     LocalizedText  = localizedText;
     AdditionalInfo = additionalInfo;
     InnerResult    = innerResult;
 }
        /// <summary>
        /// Initializes the object when it is created by the WCF framework.
        /// </summary>
        protected EndpointBase()
        {
            SupportedServices  = new Dictionary<ExpandedNodeId,ServiceDefinition>();
            
            try
            {
                m_host = GetHostForContext();
                m_server = GetServerForContext();

                MessageContext = m_server.MessageContext;
               
                EndpointDescription = GetEndpointDescription();
            }
            catch (Exception e)
            {
                ServerError = new ServiceResult(e);
                EndpointDescription = null;

                m_host = null;
                m_server = null;
            }
        }
        /// <summary>
        /// Updates an audit event after the method is invoked.
        /// </summary>
        protected override void UpdateAuditEvent(
            ISystemContext context,
            MethodState causeMethod,
            uint causeId,
            AuditUpdateStateEventState e,
            ServiceResult result)
        {            
            base.UpdateAuditEvent(
                context,
                causeMethod,
                causeId,
                e,
                result);

            // update program specific event fields.
            if (ServiceResult.IsGood(result))
            {
                ProgramTransitionAuditEventState e2 = e as ProgramTransitionAuditEventState;

                if (e2 != null)
                {
                    e2.SetChildValue(context, BrowseNames.Transition, LastTransition, false);
                }
            }
        }
        /// <summary>
        /// Called when the Respond method is called.
        /// </summary>
        /// <param name="context">The system context.</param>
        /// <param name="method">The method being called.</param>
        /// <param name="objectId">The id of the object.</param>
        /// <param name="selectedResponse">The selected response.</param>
        /// <returns>Any error.</returns>
        protected virtual ServiceResult OnRespondCalled(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            int selectedResponse)
        {
            ServiceResult error = null;

            try
            {
                if (!this.EnabledState.Id.Value)
                {
                    return(error = StatusCodes.BadConditionDisabled);
                }

                if (!this.DialogState.Id.Value)
                {
                    return(error = StatusCodes.BadDialogNotActive);
                }

                if (selectedResponse < 0 || selectedResponse >= this.ResponseOptionSet.Value.Length)
                {
                    return(error = StatusCodes.BadDialogResponseInvalid);
                }

                if (OnRespond == null)
                {
                    return(error = StatusCodes.BadNotSupported);
                }

                error = OnRespond(context, this, selectedResponse);

                // report a state change event.
                if (ServiceResult.IsGood(error))
                {
                    ReportStateChange(context, false);
                }
            }
            finally
            {
                if (this.AreEventsMonitored)
                {
                    AuditConditionRespondEventState e = new AuditConditionRespondEventState(null);

                    TranslationInfo info = new TranslationInfo(
                        "AuditConditionDialogResponse",
                        "en-US",
                        "The Respond method was called.");

                    e.Initialize(
                        context,
                        this,
                        EventSeverity.Low,
                        new LocalizedText(info),
                        ServiceResult.IsGood(error),
                        DateTime.UtcNow);

                    e.SourceName.Value = "Attribute/Call";

                    e.MethodId       = new PropertyState <NodeId>(e);
                    e.MethodId.Value = method.NodeId;

                    e.InputArguments       = new PropertyState <object[]>(e);
                    e.InputArguments.Value = new object[] { selectedResponse };

                    ReportEvent(context, e);
                }
            }

            return(error);
        }
Beispiel #10
0
        /// <summary>
        /// Causes the specified transition to occur.
        /// </summary>
        public ServiceResult DoTransition(
            ISystemContext context,
            uint transitionId,
            uint causeId,
            IList <object> inputArguments,
            IList <object> outputArguments)
        {
            // check for valid transition.
            uint newState = GetNewStateForTransition(context, transitionId);

            if (newState == 0)
            {
                return(StatusCodes.BadNotSupported);
            }

            // check the cause permissions.
            if (causeId != 0)
            {
                if (!IsCausePermitted(context, causeId, true))
                {
                    return(StatusCodes.BadUserAccessDenied);
                }
            }

            // do any pre-transition processing.
            ServiceResult result = InvokeCallback(
                OnBeforeTransition,
                context,
                this,
                transitionId,
                causeId,
                inputArguments,
                outputArguments);

            if (ServiceResult.IsBad(result))
            {
                return(result);
            }

            // save the last state.
            if (m_lastState == null)
            {
                m_lastState = new FiniteStateVariableState(this);
            }

            m_lastState.SetChildValue(context, null, CurrentState, false);

            // update state and transition variables.
            UpdateStateVariable(context, newState, CurrentState);
            UpdateTransitionVariable(context, transitionId, LastTransition);

            // do any post-transition processing.
            InvokeCallback(
                OnAfterTransition,
                context,
                this,
                transitionId,
                causeId,
                inputArguments,
                outputArguments);

            // report the event.
            if (this.AreEventsMonitored && !m_suppressTransitionEvents)
            {
                TransitionEventState e = CreateTransitionEvent(context, transitionId, causeId);

                if (e != null)
                {
                    UpdateTransitionEvent(context, transitionId, causeId, e);
                    ReportEvent(context, e);
                }
            }

            return(ServiceResult.Good);
        }
Beispiel #11
0
        /// <summary>
        /// Returns the node ids for a set of relative paths.
        /// </summary>
        /// <param name="session">An open session with the server to use.</param>
        /// <param name="startNodeId">The starting node for the relative paths.</param>
        /// <param name="relativePaths">The relative paths.</param>
        /// <returns>A collection of local nodes.</returns>
        static List<NodeOfInterest> GetNodeIds(
            Session session,
            NodeId startNodeId,
            params string[] relativePaths)
        {
            // build the list of browse paths to follow by parsing the relative paths.
            BrowsePathCollection browsePaths = new BrowsePathCollection();

            if (relativePaths != null)
            {
                for (int ii = 0; ii < relativePaths.Length; ii++)
                {
                    BrowsePath browsePath = new BrowsePath();

                    // The relative paths used indexes in the namespacesUris table. These must be 
                    // converted to indexes used by the server. An error occurs if the relative path
                    // refers to a namespaceUri that the server does not recognize.

                    // The relative paths may refer to ReferenceType by their BrowseName. The TypeTree object
                    // allows the parser to look up the server's NodeId for the ReferenceType.

                    browsePath.RelativePath = RelativePath.Parse(
                        relativePaths[ii],
                        session.TypeTree,
                        session.NamespaceUris,
                        session.NamespaceUris);

                    browsePath.StartingNode = startNodeId;

                    browsePaths.Add(browsePath);
                }
            }

            // make the call to the server.
            BrowsePathResultCollection results;
            DiagnosticInfoCollection diagnosticInfos;

            ResponseHeader responseHeader = session.TranslateBrowsePathsToNodeIds(
                null,
                browsePaths,
                out results,
                out diagnosticInfos);

            // ensure that the server returned valid results.
            Session.ValidateResponse(results, browsePaths);
            Session.ValidateDiagnosticInfos(diagnosticInfos, browsePaths);

            Console.WriteLine("Translated {0} browse paths.", relativePaths.Length);

            // collect the list of node ids found.
            List<NodeOfInterest> nodes = new List<NodeOfInterest>();

            for (int ii = 0; ii < results.Count; ii++)
            {
                // check if the start node actually exists.
                if (StatusCode.IsBad(results[ii].StatusCode))
                {
                    ServiceResult error = new ServiceResult(
                        results[ii].StatusCode,
                        diagnosticInfos[ii],
                        responseHeader.StringTable);

                    Console.WriteLine("Path '{0}' is not valid. Error = {1}", relativePaths[ii], error);
                    continue;
                }

                // an empty list is returned if no node was found.
                if (results[ii].Targets.Count == 0)
                {
                    Console.WriteLine("Path '{0}' does not exist.", relativePaths[ii]);
                    continue;
                }

                // Multiple matches are possible, however, the node that matches the type model is the
                // one we are interested in here. The rest can be ignored.
                BrowsePathTarget target = results[ii].Targets[0];

                if (target.RemainingPathIndex != UInt32.MaxValue)
                {
                    Console.WriteLine("Path '{0}' refers to a node in another server.", relativePaths[ii]);
                    continue;
                }

                // The targetId is an ExpandedNodeId because it could be node in another server. 
                // The ToNodeId function is used to convert a local NodeId stored in a ExpandedNodeId to a NodeId.

                NodeOfInterest node = new NodeOfInterest();
                node.NodeId = ExpandedNodeId.ToNodeId(target.TargetId, session.NamespaceUris);
                nodes.Add(node);
            }

            Console.WriteLine("Translate found {0} local nodes.", nodes.Count);

            // return whatever was found.
            return nodes;
        }
        /// <summary>
        /// The delegate used to receive data change notifications via a direct function call instead of a .NET Event.
        /// </summary>
        public void OnDataChangeNotification(Opc.Ua.Client.Subscription subscription, DataChangeNotification notification, IList<string> stringTable)
        {
            for (int ii = 0; ii < notification.MonitoredItems.Count; ii++)
            {
                MonitoredItem localItem = null;
                DataValue value = null;
                ServiceResult error = null;

                lock (subscription.Session)
                {
                    Opc.Ua.Client.MonitoredItem monitoredItem = subscription.FindItemByClientHandle(notification.MonitoredItems[ii].ClientHandle);

                    if (monitoredItem != null)
                    {
                        MonitoredItemNotification value2 = notification.MonitoredItems[ii];

                        if (value2.Value.StatusCode != StatusCodes.Good)
                        {
                            error = new ServiceResult(value2.Value.StatusCode, value2.DiagnosticInfo, stringTable);
                        }

                        value = value2.Value;
                        value.WrappedValue = m_mapper.ToLocalVariant(value2.Value.WrappedValue);
                        value.ServerTimestamp = DateTime.UtcNow;

                        localItem = (MonitoredItem)monitoredItem.Handle;
                    }
                }

                localItem.QueueValue(value, error);
            }
        }
        /// <summary>
        /// Handles a write operation.
        /// </summary>
        protected override void Write(
            ServerSystemContext context,
            IList<WriteValue> nodesToWrite,
            IList<ServiceResult> errors,
            List<NodeHandle> nodesToValidate,
            IDictionary<NodeId, NodeState> cache)
        {
            WriteValueCollection requests = new WriteValueCollection();
            List<int> indexes = new List<int>();

            // validates the nodes and constructs requests for external nodes.
            for (int ii = 0; ii < nodesToValidate.Count; ii++)
            {
                WriteValue nodeToWrite = nodesToWrite[ii];
                NodeHandle handle = nodesToValidate[ii];

                lock (Lock)
                {
                    // validate node.
                    NodeState source = ValidateNode(context, handle, cache);

                    if (source == null)
                    {
                        continue;
                    }

                    // determine if a local node.
                    if (PredefinedNodes.ContainsKey(source.NodeId))
                    {
                        // write the attribute value.
                        errors[handle.Index] = source.WriteAttribute(
                            context,
                            nodeToWrite.AttributeId,
                            nodeToWrite.ParsedIndexRange,
                            nodeToWrite.Value);

                        // updates to source finished - report changes to monitored items.
                        source.ClearChangeMasks(context, false);
                    }

                    WriteValue request = (WriteValue)nodeToWrite.Clone();
                    request.NodeId = m_mapper.ToRemoteId(nodeToWrite.NodeId);
                    request.Value.WrappedValue = m_mapper.ToRemoteVariant(nodeToWrite.Value.WrappedValue);
                    requests.Add(request);
                    indexes.Add(ii);
                }
            }

            // send request to external system.
            try
            {
                Opc.Ua.Client.Session client = GetClientSession(context);

                StatusCodeCollection results = null;
                DiagnosticInfoCollection diagnosticInfos = null;

                ResponseHeader responseHeader = client.Write(
                    null,
                    requests,
                    out results,
                    out diagnosticInfos);

                // these do sanity checks on the result - make sure response matched the request.
                ClientBase.ValidateResponse(results, requests);
                ClientBase.ValidateDiagnosticInfos(diagnosticInfos, requests);

                // set results.
                for (int ii = 0; ii < requests.Count; ii++)
                {
                    errors[indexes[ii]] = ServiceResult.Good;

                    if (results[ii] != StatusCodes.Good)
                    {
                        errors[indexes[ii]] = new ServiceResult(results[ii], ii, diagnosticInfos, responseHeader.StringTable);
                    }
                }
            }
            catch (Exception e)
            {
                // handle unexpected communication error.
                ServiceResult error = ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Could not access external system.");

                for (int ii = 0; ii < requests.Count; ii++)
                {
                    errors[indexes[ii]] = error;
                }
            }
        }
Beispiel #14
0
        /// <summary>
        /// Parses a string representing a numeric range.
        /// </summary>
        /// <param name="textToParse">The text to parse, prior to checking it is within the allowed range</param>
        /// <param name="range">The parsed range.</param>
        /// <returns>The reason for any error.</returns>
        public static ServiceResult Validate(string textToParse, out NumericRange range)
        {
            range = NumericRange.Empty;

            if (String.IsNullOrEmpty(textToParse))
            {
                return(ServiceResult.Good);
            }

            // check for multidimensional ranges.
            int index = textToParse.IndexOf(',');

            if (index >= 0)
            {
                int start = 0;
                List <NumericRange> subranges = new List <NumericRange>();

                for (int ii = 0; ii < textToParse.Length; ii++)
                {
                    char ch = textToParse[ii];

                    if (ch == ',' || ii == textToParse.Length - 1)
                    {
                        NumericRange  subrange = new NumericRange();
                        string        subtext  = (ch == ',') ? textToParse.Substring(start, ii - start) : textToParse.Substring(start);
                        ServiceResult result   = Validate(subtext, out subrange);

                        if (ServiceResult.IsBad(result))
                        {
                            return(result);
                        }

                        subranges.Add(subrange);
                        start = ii + 1;
                    }
                }

                // must have at least two entries.
                if (subranges.Count < 2)
                {
                    return(StatusCodes.BadIndexRangeInvalid);
                }

                range.m_begin     = subranges[0].Begin;
                range.m_end       = subranges[0].End;
                range.m_subranges = subranges.ToArray();

                return(ServiceResult.Good);
            }

            try
            {
                index = textToParse.IndexOf(':');

                if (index != -1)
                {
                    range.Begin = Convert.ToInt32(textToParse.Substring(0, index), CultureInfo.InvariantCulture);
                    range.End   = Convert.ToInt32(textToParse.Substring(index + 1), CultureInfo.InvariantCulture);

                    if (range.End < 0)
                    {
                        return(ServiceResult.Create(
                                   StatusCodes.BadIndexRangeInvalid,
                                   "NumericRange does not have a valid end index ({0}).",
                                   range.End));
                    }

                    if (range.Begin >= range.End)
                    {
                        return(ServiceResult.Create(
                                   StatusCodes.BadIndexRangeInvalid,
                                   "NumericRange does not have a start index that is less than the end index ({0}).",
                                   range));
                    }
                }
                else
                {
                    range.Begin = Convert.ToInt32(textToParse, CultureInfo.InvariantCulture);
                    range.End   = -1;
                }

                if (range.Begin < 0)
                {
                    return(ServiceResult.Create(
                               StatusCodes.BadIndexRangeInvalid,
                               "NumericRange does not have a valid start index ({0}).",
                               range.Begin));
                }
            }
            catch (Exception e)
            {
                return(ServiceResult.Create(
                           e,
                           StatusCodes.BadIndexRangeInvalid,
                           "NumericRange cannot be parsed ({0}).",
                           textToParse));
            }

            return(ServiceResult.Good);
        }
Beispiel #15
0
        /// <summary>
        /// Validates the object.
        /// </summary>
        public Result Validate(FilterContext context)
        {
            Result result = new Result();

            // check for top level error.
            if (m_selectClauses == null || m_selectClauses.Count == 0)
            {
                result.Status = ServiceResult.Create(
                    StatusCodes.BadStructureMissing,
                    "EventFilter does not specify any Select Clauses.");

                return(result);
            }

            if (m_whereClause == null)
            {
                result.Status = ServiceResult.Create(
                    StatusCodes.BadStructureMissing,
                    "EventFilter does not specify any Where Clauses.");

                return(result);
            }

            result.Status = ServiceResult.Good;

            // validate select clause.
            bool error = false;

            foreach (SimpleAttributeOperand clause in m_selectClauses)
            {
                ServiceResult clauseResult = null;

                // check for null.
                if (clause == null)
                {
                    clauseResult = ServiceResult.Create(
                        StatusCodes.BadStructureMissing,
                        "EventFilterSelectClause cannot be null in EventFilter SelectClause.");

                    result.SelectClauseResults.Add(clauseResult);
                    error = true;
                    continue;
                }

                // validate clause.
                clauseResult = clause.Validate(context, 0);

                if (ServiceResult.IsBad(clauseResult))
                {
                    result.SelectClauseResults.Add(clauseResult);
                    error = true;
                    continue;
                }

                // clause ok.
                result.SelectClauseResults.Add(null);
            }

            if (error)
            {
                result.Status = StatusCodes.BadEventFilterInvalid;
            }
            else
            {
                result.SelectClauseResults.Clear();
            }

            // validate where clause.
            result.WhereClauseResult = m_whereClause.Validate(context);

            if (ServiceResult.IsBad(result.WhereClauseResult.Status))
            {
                result.Status = StatusCodes.BadEventFilterInvalid;
            }

            return(result);
        }
Beispiel #16
0
        /// <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)
                        {
                            ServiceResult errorResult = new ServiceResult(
                                result.StatusCode,
                                result.SymbolicId,
                                result.NamespaceUri,
                                result.LocalizedText,
                                result.AdditionalInfo,
                                StatusCodes.BadCertificateUntrusted);

                            throw new ServiceResultException(errorResult);
                        }

                        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 #17
0
        private static ServiceResult CheckChainStatus(X509ChainStatus status, CertificateIdentifier id, CertificateIdentifier issuer, bool isIssuer)
        {
            switch (status.Status)
            {
            case X509ChainStatusFlags.NotValidForUsage:
            {
                return(ServiceResult.Create(
                           (isIssuer) ? StatusCodes.BadCertificateUseNotAllowed : StatusCodes.BadCertificateIssuerUseNotAllowed,
                           "Certificate may not be used as an application instance certificate. {0}: {1}",
                           status.Status,
                           status.StatusInformation));
            }

            case X509ChainStatusFlags.NoError:
            case X509ChainStatusFlags.OfflineRevocation:
            case X509ChainStatusFlags.InvalidBasicConstraints:
            case X509ChainStatusFlags.PartialChain:
            {
                break;
            }

            case X509ChainStatusFlags.UntrustedRoot:
            {
                // self signed cert signature validation
                // .Net Core ChainStatus returns NotSignatureValid only on Windows,
                // so we have to do the extra cert signature check on all platforms
                if (issuer == null && !isIssuer &&
                    id.Certificate != null && Utils.CompareDistinguishedName(id.Certificate.Subject, id.Certificate.Issuer))
                {
                    if (!IsSignatureValid(id.Certificate))
                    {
                        goto case X509ChainStatusFlags.NotSignatureValid;
                    }
                }

                // ignore this error because the root check is done
                // by looking the certificate up in the trusted issuer stores passed to the validator.
                // the ChainStatus uses the trusted issuer stores.
                break;
            }

            case X509ChainStatusFlags.RevocationStatusUnknown:
            {
                if (issuer != null)
                {
                    if ((issuer.ValidationOptions & CertificateValidationOptions.SuppressRevocationStatusUnknown) != 0)
                    {
                        break;
                    }
                }

                // check for meaning less errors for self-signed certificates.
                if (id.Certificate != null && Utils.CompareDistinguishedName(id.Certificate.Subject, id.Certificate.Subject))
                {
                    break;
                }

                return(ServiceResult.Create(
                           (isIssuer) ? StatusCodes.BadCertificateIssuerRevocationUnknown : StatusCodes.BadCertificateRevocationUnknown,
                           "Certificate revocation status cannot be verified. {0}: {1}",
                           status.Status,
                           status.StatusInformation));
            }

            case X509ChainStatusFlags.Revoked:
            {
                return(ServiceResult.Create(
                           (isIssuer) ? StatusCodes.BadCertificateIssuerRevoked : StatusCodes.BadCertificateRevoked,
                           "Certificate has been revoked. {0}: {1}",
                           status.Status,
                           status.StatusInformation));
            }

            case X509ChainStatusFlags.NotTimeNested:
            {
                if (id != null && ((id.ValidationOptions & CertificateValidationOptions.SuppressCertificateExpired) != 0))
                {
                    break;
                }

                return(ServiceResult.Create(
                           StatusCodes.BadCertificateIssuerTimeInvalid,
                           "Certificate issuer validatity time does not overhas is expired or not yet valid. {0}: {1}",
                           status.Status,
                           status.StatusInformation));
            }

            case X509ChainStatusFlags.NotTimeValid:
            {
                if (id != null && ((id.ValidationOptions & CertificateValidationOptions.SuppressCertificateExpired) != 0))
                {
                    break;
                }

                return(ServiceResult.Create(
                           (isIssuer) ? StatusCodes.BadCertificateIssuerTimeInvalid : StatusCodes.BadCertificateTimeInvalid,
                           "Certificate has is expired or not yet valid. {0}: {1}",
                           status.Status,
                           status.StatusInformation));
            }

            case X509ChainStatusFlags.NotSignatureValid:
            {
                return(ServiceResult.Create(
                           StatusCodes.BadCertificateUntrusted,
                           status.StatusInformation));
            }

            default:
            {
                return(ServiceResult.Create(
                           StatusCodes.BadCertificateInvalid,
                           "Certificate validation failed. {0}: {1}",
                           status.Status,
                           status.StatusInformation));
            }
            }

            return(null);
        }
Beispiel #18
0
 /// <summary>
 /// Creates a new instance.
 /// </summary>
 internal CertificateValidationEventArgs(ServiceResult error, X509Certificate2 certificate)
 {
     m_error       = error;
     m_certificate = certificate;
 }
        /// <summary>
        /// Handles the Unshelve method.
        /// </summary>
        protected virtual ServiceResult OnUnshelve(
            ISystemContext context,
            MethodState method,
            IList <object> inputArguments,
            IList <object> outputArguments)
        {
            ServiceResult error = null;

            try
            {
                if (!this.EnabledState.Id.Value)
                {
                    return(error = StatusCodes.BadConditionDisabled);
                }

                if (!this.ShelvingState.IsCausePermitted(context, Methods.ShelvedStateMachineType_Unshelve, false))
                {
                    return(error = StatusCodes.BadConditionNotShelved);
                }

                if (OnShelve == null)
                {
                    return(error = StatusCodes.BadNotSupported);
                }

                error = OnShelve(context, this, false, false, 0);

                // report a state change event.
                if (ServiceResult.IsGood(error))
                {
                    ReportStateChange(context, false);
                }
            }
            finally
            {
                // raise the audit event.
                if (this.AreEventsMonitored)
                {
                    AuditConditionShelvingEventState e = new AuditConditionShelvingEventState(null);

                    TranslationInfo info = new TranslationInfo(
                        "AuditConditionUnshelve",
                        "en-US",
                        "The Unshelve method was called.");

                    e.Initialize(
                        context,
                        this,
                        EventSeverity.Low,
                        new LocalizedText(info),
                        ServiceResult.IsGood(error),
                        DateTime.UtcNow);

                    e.SourceName.Value = "Attribute/Call";

                    e.MethodId       = new PropertyState <NodeId>(e);
                    e.MethodId.Value = method.NodeId;

                    ReportEvent(context, e);
                }
            }

            return(error);
        }
        /// <summary>
        /// Handles the TimedShelve method.
        /// </summary>
        protected virtual ServiceResult OnTimedShelve(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            double shelvingTime)
        {
            ServiceResult error = null;

            try
            {
                if (!this.EnabledState.Id.Value)
                {
                    return(error = StatusCodes.BadConditionDisabled);
                }

                if (shelvingTime <= 0 || (this.MaxTimeShelved != null && shelvingTime > this.MaxTimeShelved.Value))
                {
                    return(error = StatusCodes.BadShelvingTimeOutOfRange);
                }

                if (!this.ShelvingState.IsCausePermitted(context, Methods.ShelvedStateMachineType_TimedShelve, false))
                {
                    return(error = StatusCodes.BadConditionAlreadyShelved);
                }

                if (OnShelve == null)
                {
                    return(error = StatusCodes.BadNotSupported);
                }

                error = OnShelve(context, this, true, false, shelvingTime);

                // report a state change event.
                if (ServiceResult.IsGood(error))
                {
                    ReportStateChange(context, false);
                }
            }
            finally
            {
                if (this.AreEventsMonitored)
                {
                    AuditConditionShelvingEventState e = new AuditConditionShelvingEventState(null);

                    TranslationInfo info = new TranslationInfo(
                        "AuditConditionTimedShelve",
                        "en-US",
                        "The TimedShelve method was called.");

                    e.Initialize(
                        context,
                        this,
                        EventSeverity.Low,
                        new LocalizedText(info),
                        ServiceResult.IsGood(error),
                        DateTime.UtcNow);

                    e.SourceName.Value = "Attribute/Call";

                    e.MethodId       = new PropertyState <NodeId>(e);
                    e.MethodId.Value = method.NodeId;

                    e.InputArguments       = new PropertyState <object[]>(e);
                    e.InputArguments.Value = new object[] { shelvingTime };

                    ReportEvent(context, e);
                }
            }

            return(error);
        }
Beispiel #21
0
        /// <summary>
        /// Validates the content filter element.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="index">The index.</param>
        /// <returns>The results of the validation.</returns>
        public virtual ContentFilter.ElementResult Validate(FilterContext context, int index)
        {
            ContentFilter.ElementResult result = new ContentFilter.ElementResult(null);

            // check the number of operands.
            int operandCount = -1;

            switch (m_filterOperator)
            {
            case FilterOperator.Not:
            case FilterOperator.IsNull:
            case FilterOperator.InView:
            case FilterOperator.OfType: {
                operandCount = 1;
                break;
            }

            case FilterOperator.And:
            case FilterOperator.Or:
            case FilterOperator.Equals:
            case FilterOperator.GreaterThan:
            case FilterOperator.GreaterThanOrEqual:
            case FilterOperator.LessThan:
            case FilterOperator.LessThanOrEqual:
            case FilterOperator.Like:
            case FilterOperator.Cast: {
                operandCount = 2;
                break;
            }

            case FilterOperator.Between: {
                operandCount = 3;
                break;
            }

            case FilterOperator.RelatedTo: {
                operandCount = 6;
                break;
            }

            case FilterOperator.InList: {
                operandCount = -1;
                break;
            }

            default: {
                break;
            }
            }

            if (operandCount != -1)
            {
                if (operandCount != m_filterOperands.Count)
                {
                    result.Status = ServiceResult.Create(
                        StatusCodes.BadEventFilterInvalid,
                        "ContentFilterElement does not have the correct number of operands (Operator={0} OperandCount={1}).",
                        m_filterOperator,
                        operandCount);

                    return(result);
                }
            }
            else
            {
                if (m_filterOperands.Count < 2)
                {
                    result.Status = ServiceResult.Create(
                        StatusCodes.BadEventFilterInvalid,
                        "ContentFilterElement does not have the correct number of operands (Operator={0} OperandCount={1}).",
                        m_filterOperator,
                        m_filterOperands.Count);

                    return(result);
                }
            }

            // validate the operands.
            bool error = false;

            for (int ii = 0; ii < m_filterOperands.Count; ii++)
            {
                ServiceResult operandResult = null;

                ExtensionObject operand = m_filterOperands[ii];

                // check for null.
                if (ExtensionObject.IsNull(operand))
                {
                    operandResult = ServiceResult.Create(
                        StatusCodes.BadEventFilterInvalid,
                        "The FilterOperand cannot be Null.");

                    result.OperandResults.Add(operandResult);
                    error = true;
                    continue;
                }

                // check that the extension object contains a filter operand.
                FilterOperand filterOperand = operand.Body as FilterOperand;

                if (filterOperand == null)
                {
                    operandResult = ServiceResult.Create(
                        StatusCodes.BadEventFilterInvalid,
                        "The FilterOperand is not a supported type ({0}).",
                        filterOperand.GetType());

                    result.OperandResults.Add(operandResult);
                    error = true;
                    continue;
                }

                // validate the operand.
                filterOperand.Parent = this;
                operandResult        = filterOperand.Validate(context, index);

                if (ServiceResult.IsBad(operandResult))
                {
                    result.OperandResults.Add(operandResult);
                    error = true;
                    continue;
                }

                result.OperandResults.Add(null);
            }

            // ensure the global error code.
            if (error)
            {
                result.Status = StatusCodes.BadContentFilterInvalid;
            }
            else
            {
                result.OperandResults.Clear();
            }

            return(result);
        }
Beispiel #22
0
        /// <summary>
        /// Write the value for any non-value attribute.
        /// </summary>
        protected override ServiceResult WriteNonValueAttribute(
            ISystemContext context,
            uint attributeId,
            object value)
        {
            ServiceResult result = null;

            switch (attributeId)
            {
            case Attributes.EventNotifier:
            {
                byte?eventNotifierRef = value as byte?;

                if (eventNotifierRef == null)
                {
                    return(StatusCodes.BadTypeMismatch);
                }

                if ((WriteMask & AttributeWriteMask.EventNotifier) == 0)
                {
                    return(StatusCodes.BadNotWritable);
                }

                byte eventNotifier = eventNotifierRef.Value;

                if (OnWriteEventNotifier != null)
                {
                    result = OnWriteEventNotifier(context, this, ref eventNotifier);
                }

                if (ServiceResult.IsGood(result))
                {
                    EventNotifier = eventNotifier;
                }

                return(result);
            }

            case Attributes.ContainsNoLoops:
            {
                bool?containsNoLoopsRef = value as bool?;

                if (containsNoLoopsRef == null)
                {
                    return(StatusCodes.BadTypeMismatch);
                }

                if ((WriteMask & AttributeWriteMask.ContainsNoLoops) == 0)
                {
                    return(StatusCodes.BadNotWritable);
                }

                bool containsNoLoops = containsNoLoopsRef.Value;

                if (OnWriteContainsNoLoops != null)
                {
                    result = OnWriteContainsNoLoops(context, this, ref containsNoLoops);
                }

                if (ServiceResult.IsGood(result))
                {
                    ContainsNoLoops = containsNoLoops;
                }

                return(result);
            }
            }

            return(base.WriteNonValueAttribute(context, attributeId, value));
        }
            /// <summary>
            /// Used to indicate that the asynchronous operation has completed.
            /// </summary>
            /// <param name="response">The response. May be null if an error is provided.</param>
            /// <param name="error"></param>
            public void OperationCompleted(IServiceResponse response, ServiceResult error)
            {
                // save response and/or error.
                m_error = null;
                m_response = response;

                if (ServiceResult.IsBad(error))
                {
                    m_error = new ServiceResultException(error);
                    m_response = SaveExceptionAsResponse(m_error);
                }

                // operation completed.
                OperationCompleted();
            }
Beispiel #24
0
        /// <summary>
        /// Write the value for any non-value attribute.
        /// </summary>
        protected override ServiceResult WriteNonValueAttribute(
            ISystemContext context,
            uint attributeId,
            object value)
        {
            ServiceResult result = null;

            switch (attributeId)
            {
            case Attributes.Executable:
            {
                bool?executableRef = value as bool?;

                if (executableRef == null)
                {
                    return(StatusCodes.BadTypeMismatch);
                }

                if ((WriteMask & AttributeWriteMask.Executable) == 0)
                {
                    return(StatusCodes.BadNotWritable);
                }

                bool executable = executableRef.Value;

                if (OnWriteExecutable != null)
                {
                    result = OnWriteExecutable(context, this, ref executable);
                }

                if (ServiceResult.IsGood(result))
                {
                    Executable = executable;
                }

                return(result);
            }

            case Attributes.UserExecutable:
            {
                bool?userExecutableRef = value as bool?;

                if (userExecutableRef == null)
                {
                    return(StatusCodes.BadTypeMismatch);
                }

                if ((WriteMask & AttributeWriteMask.UserExecutable) == 0)
                {
                    return(StatusCodes.BadNotWritable);
                }

                bool userExecutable = userExecutableRef.Value;

                if (OnWriteUserExecutable != null)
                {
                    result = OnWriteUserExecutable(context, this, ref userExecutable);
                }

                if (ServiceResult.IsGood(result))
                {
                    UserExecutable = userExecutable;
                }

                return(result);
            }
            }

            return(base.WriteNonValueAttribute(context, attributeId, value));
        }
        /// <summary>
        /// Serializes the service result.
        /// </summary>
        /// <param name="info">The info.</param>
        /// <param name="serviceResult">The service result.</param>
        /// <param name="prefix">The prefix.</param>
        private static void SerializeServiceResult(SerializationInfo info, ServiceResult serviceResult, string prefix)
        {
            info.AddValue(prefix + "StatusCode", serviceResult.Code);
            info.AddValue(prefix + "NamespaceUri", serviceResult.NamespaceUri);
            info.AddValue(prefix + "SymbolicId", serviceResult.SymbolicId);
            info.AddValue(prefix + "AdditionalInfo", serviceResult.AdditionalInfo);

            if (serviceResult.LocalizedText != null)
            {
                info.AddValue(prefix + "LocalizedTextText", serviceResult.LocalizedText.Text);
                info.AddValue(prefix + "LocalizedTextKey", serviceResult.LocalizedText.Key);
                info.AddValue(prefix + "LocalizedTextLocale", serviceResult.LocalizedText.Locale);
            }

            if (serviceResult.InnerResult != null)
            {
                SerializeServiceResult(info, serviceResult.InnerResult, "InnerResult");
            }
        }
Beispiel #26
0
        /// <summary>
        /// Invokes the methods and returns the output parameters.
        /// </summary>
        /// <param name="context">The context to use.</param>
        /// <param name="objectId">The object being called.</param>
        /// <param name="inputArguments">The input arguments.</param>
        /// <param name="argumentErrors">Any errors for the input arguments.</param>
        /// <param name="outputArguments">The output arguments.</param>
        /// <returns>The result of the method call.</returns>
        public virtual ServiceResult Call(
            ISystemContext context,
            NodeId objectId,
            IList <Variant> inputArguments,
            IList <ServiceResult> argumentErrors,
            IList <Variant> outputArguments)
        {
            // validate input arguments.
            List <object> inputs = new List <object>();

            // check for too few or too many arguments.
            int expectedCount = 0;

            if (InputArguments != null && InputArguments.Value != null)
            {
                expectedCount = InputArguments.Value.Length;
            }

            if (expectedCount != inputArguments.Count)
            {
                return(StatusCodes.BadArgumentsMissing);
            }

            // validate individual arguements.
            bool error = false;

            for (int ii = 0; ii < inputArguments.Count; ii++)
            {
                ServiceResult argumentError = ValidateInputArgument(context, inputArguments[ii], ii);

                if (ServiceResult.IsBad(argumentError))
                {
                    error = true;
                }

                inputs.Add(inputArguments[ii].Value);
                argumentErrors.Add(argumentError);
            }

            // return good - caller must check argument errors.
            if (error)
            {
                return(ServiceResult.Good);
            }

            // set output arguments to default values.
            List <object> outputs = new List <object>();

            if (OutputArguments != null)
            {
                IList <Argument> arguments = OutputArguments.Value;

                if (arguments != null && arguments.Count > 0)
                {
                    for (int ii = 0; ii < arguments.Count; ii++)
                    {
                        outputs.Add(GetArgumentDefaultValue(context, arguments[ii]));
                    }
                }
            }

            // invoke method.
            ServiceResult result = null;

            try
            {
                result = Call(context, objectId, inputs, outputs);
            }
            catch (Exception e)
            {
                result = new ServiceResult(e);
            }

            // copy out arguments.
            if (ServiceResult.IsGood(result))
            {
                for (int ii = 0; ii < outputs.Count; ii++)
                {
                    outputArguments.Add(new Variant(outputs[ii]));
                }
            }

            return(result);
        }
        /// <summary>
        /// Handles a read operations that fetch data from an external source.
        /// </summary>
        protected override void Read(
            ServerSystemContext context,
            IList<ReadValueId> nodesToRead,
            IList<DataValue> values,
            IList<ServiceResult> errors,
            List<NodeHandle> nodesToValidate,
            IDictionary<NodeId, NodeState> cache)
        {
            ReadValueIdCollection requests = new ReadValueIdCollection();
            List<int> indexes = new List<int>();

            for (int ii = 0; ii < nodesToValidate.Count; ii++)
            {
                NodeHandle handle = nodesToValidate[ii];
                ReadValueId nodeToRead = nodesToRead[ii];
                DataValue value = values[ii];

                lock (Lock)
                {
                    // validate node.
                    NodeState source = ValidateNode(context, handle, cache);

                    if (source == null)
                    {
                        continue;
                    }

                    // determine if a local node.
                    if (PredefinedNodes.ContainsKey(source.NodeId))
                    {
                        errors[handle.Index] = source.ReadAttribute(
                            context,
                            nodeToRead.AttributeId,
                            nodeToRead.ParsedIndexRange,
                            nodeToRead.DataEncoding,
                            value);

                        continue;
                    }

                    ReadValueId request = (ReadValueId)nodeToRead.Clone();
                    request.NodeId = m_mapper.ToRemoteId(nodeToRead.NodeId);
                    request.DataEncoding = m_mapper.ToRemoteName(nodeToRead.DataEncoding);
                    requests.Add(request);
                    indexes.Add(ii);
                }
            }

            // send request to external system.
            try
            {
                Opc.Ua.Client.Session client = GetClientSession(context);

                DataValueCollection results = null;
                DiagnosticInfoCollection diagnosticInfos = null;

                ResponseHeader responseHeader = client.Read(
                    null,
                    0,
                    TimestampsToReturn.Both,
                    requests,
                    out results,
                    out diagnosticInfos);

                // these do sanity checks on the result - make sure response matched the request.
                ClientBase.ValidateResponse(results, requests);
                ClientBase.ValidateDiagnosticInfos(diagnosticInfos, requests);

                // set results.
                for (int ii = 0; ii < requests.Count; ii++)
                {
                    values[indexes[ii]] = results[ii];
                    values[indexes[ii]].WrappedValue = m_mapper.ToLocalVariant(results[ii].WrappedValue);

                    errors[indexes[ii]] = ServiceResult.Good;

                    if (results[ii].StatusCode != StatusCodes.Good)
                    {
                        errors[indexes[ii]] = new ServiceResult(results[ii].StatusCode, ii, diagnosticInfos, responseHeader.StringTable);
                    }
                }
            }
            catch (Exception e)
            {
                // handle unexpected communication error.
                ServiceResult error = ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Could not access external system.");

                for (int ii = 0; ii < requests.Count; ii++)
                {
                    errors[indexes[ii]] = error;
                }
            }
        }
Beispiel #28
0
 /// <summary>
 /// Initializes the object with a result code.
 /// </summary>
 /// <param name="status">The status.</param>
 public Result(ServiceResult status)
 {
     m_status = status;
 }
        /// <summary>
        /// Handles a cal operation.
        /// </summary>
        public override void Call(
            OperationContext context,
            IList<CallMethodRequest> methodsToCall,
            IList<CallMethodResult> results,
            IList<ServiceResult> errors)
        {
            ServerSystemContext systemContext = SystemContext.Copy(context);
            IDictionary<NodeId, NodeState> operationCache = new NodeIdDictionary<NodeState>();

            CallMethodRequestCollection requests = new CallMethodRequestCollection();
            List<int> indexes = new List<int>();

            // validates the nodes and constructs requests for external nodes.
            for (int ii = 0; ii < methodsToCall.Count; ii++)
            {
                CallMethodRequest methodToCall = methodsToCall[ii];

                // skip items that have already been processed.
                if (methodToCall.Processed)
                {
                    continue;
                }

                MethodState method = null;

                lock (Lock)
                {
                    // check for valid handle.
                    NodeHandle handle = GetManagerHandle(systemContext, methodToCall.ObjectId, operationCache);

                    if (handle == null)
                    {
                        continue;
                    }

                    // owned by this node manager.
                    methodToCall.Processed = true;

                    // validate the source node.
                    NodeState source = ValidateNode(systemContext, handle, operationCache);

                    if (source == null)
                    {
                        errors[ii] = StatusCodes.BadNodeIdUnknown;
                        continue;
                    }

                    // determine if a local node.
                    if (PredefinedNodes.ContainsKey(handle.NodeId))
                    {
                        // find the method.
                        method = source.FindMethod(systemContext, methodToCall.MethodId);

                        if (method == null)
                        {
                            // check for loose coupling.
                            if (source.ReferenceExists(ReferenceTypeIds.HasComponent, false, methodToCall.MethodId))
                            {
                                method = (MethodState)FindPredefinedNode(methodToCall.MethodId, typeof(MethodState));
                            }

                            if (method == null)
                            {
                                errors[ii] = StatusCodes.BadMethodInvalid;
                                continue;
                            }
                        }
                    }
                }

                if (method != null)
                {
                    // call the method.
                    CallMethodResult result = results[ii] = new CallMethodResult();

                    errors[ii] = Call(
                        systemContext,
                        methodToCall,
                        method,
                        result);
                        
                    continue;
                }

                CallMethodRequest request = (CallMethodRequest)methodToCall.Clone();
                request.ObjectId = m_mapper.ToRemoteId(methodToCall.ObjectId);
                request.MethodId = m_mapper.ToRemoteId(methodToCall.MethodId);

                for (int jj = 0; jj < request.InputArguments.Count; jj++)
                {
                    request.InputArguments[jj] = m_mapper.ToRemoteVariant(methodToCall.InputArguments[jj]);
                }

                requests.Add(request);
                indexes.Add(ii);
            }

            // send request to external system.
            try
            {
                Opc.Ua.Client.Session client = GetClientSession(systemContext);

                CallMethodResultCollection results2 = null;
                DiagnosticInfoCollection diagnosticInfos = null;

                ResponseHeader responseHeader = client.Call(
                    null,
                    requests,
                    out results2,
                    out diagnosticInfos);

                // these do sanity checks on the result - make sure response matched the request.
                ClientBase.ValidateResponse(results2, requests);
                ClientBase.ValidateDiagnosticInfos(diagnosticInfos, requests);

                // set results.
                for (int ii = 0; ii < requests.Count; ii++)
                {
                    results[indexes[ii]] = results2[ii];
                    errors[indexes[ii]] = ServiceResult.Good;

                    if (results2[ii].StatusCode != StatusCodes.Good)
                    {
                        errors[indexes[ii]] = new ServiceResult(results[ii].StatusCode, ii, diagnosticInfos, responseHeader.StringTable);
                    }
                    else
                    {
                        for (int jj = 0; jj < results2[ii].OutputArguments.Count; jj++)
                        {
                            results2[ii].OutputArguments[jj] = m_mapper.ToLocalVariant(results2[ii].OutputArguments[jj]);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                // handle unexpected communication error.
                ServiceResult error = ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Could not access external system.");

                for (int ii = 0; ii < requests.Count; ii++)
                {
                    errors[indexes[ii]] = error;
                }
            }
        }
Beispiel #30
0
        /// <summary>
        /// Handles the OneShotShelve method.
        /// </summary>
        protected virtual ServiceResult OnOneShotShelve(
            ISystemContext context,
            MethodState method,
            IList <object> inputArguments,
            IList <object> outputArguments)
        {
            ServiceResult error = null;

            try
            {
                if (!this.EnabledState.Id.Value)
                {
                    return(error = StatusCodes.BadConditionDisabled);
                }

                if (!this.ShelvingState.IsCausePermitted(context, Methods.ShelvedStateMachineType_OneShotShelve, false))
                {
                    return(error = StatusCodes.BadConditionAlreadyShelved);
                }

                if (OnShelve == null)
                {
                    return(error = StatusCodes.BadNotSupported);
                }

                error = OnShelve(context, this, true, true, 0);

                // report a state change event.
                if (ServiceResult.IsGood(error))
                {
                    ReportStateChange(context, false);
                }
            }
            finally
            {
                if (this.AreEventsMonitored)
                {
                    AuditConditionShelvingEventState e = new AuditConditionShelvingEventState(null);

                    TranslationInfo info = new TranslationInfo(
                        "AuditConditionOneShotShelve",
                        "en-US",
                        "The OneShotShelve method was called.");

                    e.Initialize(
                        context,
                        this,
                        EventSeverity.Low,
                        new LocalizedText(info),
                        ServiceResult.IsGood(error),
                        DateTime.UtcNow);

                    e.SetChildValue(context, BrowseNames.SourceNode, NodeId, false);
                    e.SetChildValue(context, BrowseNames.SourceName, "Method/OneShotShelve", false);

                    e.SetChildValue(context, BrowseNames.MethodId, method.NodeId, false);
                    e.SetChildValue(context, BrowseNames.ShelvingTime, null, false);

                    ReportEvent(context, e);
                }
            }

            return(error);
        }
Beispiel #31
0
        public virtual void Stop()
        {
            // do any pre-stop processing.
            try
            {
                OnServerStopping();
            }
            catch (Exception e)
            {
                m_serverError = new ServiceResult(e);
            }

            // close any listeners.
            List<ITransportListener> listeners = m_listeners;

            if (listeners != null)
            {
                for (int ii = 0; ii < listeners.Count; ii++)
                {
                    try
                    {
                        listeners[ii].Close();
                    }
                    catch (Exception e)
                    {
                        Utils.Trace(e, "Unexpected error closing a listener. {0}", listeners[ii].GetType().FullName);
                    }
                }

                listeners.Clear();
            }

            // close the hosts.
            lock (m_hosts)
            {
                foreach (ServiceHost host in m_hosts)
                {
                    if (host.State == CommunicationState.Opened)
                    {
                        host.Abort();
                    }
                }

                m_hosts.Clear();
            }
        }
Beispiel #32
0
 /// <summary>
 /// Initializes the object with a result code.
 /// </summary>
 /// <param name="status">The status.</param>
 public Result(ServiceResult status)
 {
     m_status = status;
 }
 /// <summary>
 /// Creates a new instance.
 /// </summary>
 internal CertificateValidationEventArgs(ServiceResult error, X509Certificate2 certificate)
 {
     m_error = error;
     m_certificate = certificate;
 }
        /// <summary>
        /// Constructs a object by specifying each property.
        /// </summary>
        /// <remarks>
        /// The innerException is used to construct the inner result.
        /// </remarks>
        public ServiceResult(
            StatusCode    code,
            string        symbolicId,
            string        namespaceUri,
            LocalizedText localizedText,
            string        additionalInfo,            
            Exception     innerException)
        {
            ServiceResult innerResult = new ServiceResult(innerException);

            // check if no new information provided.
            if (code.Code == innerResult.Code && symbolicId == null && localizedText == null && additionalInfo == null)
            {
                m_code           = innerResult.Code;
                m_symbolicId     = innerResult.SymbolicId;
                m_namespaceUri   = innerResult.NamespaceUri;
                m_localizedText  = innerResult.LocalizedText;
                m_additionalInfo = innerResult.AdditionalInfo;
                m_innerResult    = innerResult.InnerResult;
            }

            // make the exception the inner result.
            else
            {
                m_code           = code.Code;
                m_symbolicId     = symbolicId;
                m_namespaceUri   = namespaceUri;
                m_localizedText  = localizedText;
                m_additionalInfo = additionalInfo;
                m_innerResult    = innerResult;
            }
        }
Beispiel #35
0
        void RunTest(AggregateType aggregate)
        {
            try
            {
                AggregateTestResultSet myResults = AggregateTestResultSet.LoadFromXMLFile(
                    String.Format(@"{0}TestResult.xml", Enum.GetName(typeof(AggregateType), aggregate)));

                for (int i = 0; i < myResults.Count; i++)
                {
                    AggregateTestResult testResult = myResults[i] as AggregateTestResult;

                    Debug.WriteLine(String.Format("Test Data: {0}", testResult.TestDataName));
                    Debug.WriteLine(String.Format("Start time: {0}\tEnd time: {1}\tInterval: {2}", 
                        testResult.Details.StartTime.TimeOfDay,
                        testResult.Details.EndTime.TimeOfDay,
                        testResult.Details.ProcessingInterval));
                    // get expected values
                    List<DataValue> expected = new List<DataValue>(testResult.DataValues.Count);
                    for (int ii = 0; ii < testResult.DataValues.Count; ii++)
                        expected.Add(testResult.DataValues[ii].GetDataValue());

                    // configure the aggregate calculator
                    NewAggregateFilter filter = new NewAggregateFilter()
                    {
                        StartTime = testResult.Details.StartTime,
                        EndTime = testResult.Details.EndTime,
                        AggregateType = AggregateLookup[aggregate],
                        AggregateConfiguration = TestData[myResults[i].TestDataName].Configuration.AggregateConfiguration,
                        ProcessingInterval = testResult.Details.ProcessingInterval
                    };
                    TestData testData = TestData[testResult.TestDataName];
                    AggregateCalculatorImpl calculator = Aggregators.CreateAggregator(filter, testData.Configuration.Stepped);
                    /*
                    calculator.Configuration = new AggregateConfiguration()
                    {
                        PercentDataBad = 0,
                        PercentDataGood = 100,
                        SteppedSlopedExtrapolation = false,
                        TreatUncertainAsBad = true
                    };
                     */
                    HistoryData rawHistoryData = new HistoryData();
                    for (int ii = 0; ii < testData.DataValues.Count; ii++)
                    {
                        DataValue dv = testData.DataValues[ii].GetDataValue();
                        rawHistoryData.DataValues.Add(dv);
                    }

                    HistoryData historyData = new HistoryData();
                    var sr = new ServiceResult(StatusCodes.Good);
                    foreach (DataValue raw in rawHistoryData.DataValues)
                    {
                        IList<DataValue> released = calculator.ProcessValue(raw, sr);
                        if (StatusCode.IsGood(sr.StatusCode) && released.Count > 0)
                        {
                            historyData.DataValues.AddRange(released);
                        }
                    }
                    var lsr = new ServiceResult(StatusCodes.Good);
                    historyData.DataValues.AddRange(calculator.ProcessTermination(lsr));

                    // obtain the actual values
                    List<DataValue> actual = new List<DataValue>(historyData.DataValues);

                    // compare the two value sets
                    bool assertion = true;
                    HelperMethods.CompareResults(expected, actual, testResult.TestDataName, assertion);
                    Console.WriteLine("Test {0} passed", i);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.StackTrace);
                throw;
            }
        }
Beispiel #36
0
 /// <summary>
 /// Validates the operand.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="index">The index.</param>
 /// <returns>the result of the validation</returns>
 public virtual ServiceResult Validate(FilterContext context, int index)
 {
     return(ServiceResult.Create(StatusCodes.BadEventFilterInvalid,
                                 "A sub-class of FilterOperand must be specified."));
 }
Beispiel #37
0
 /// <summary>
 /// Initializes the object with a result code.
 /// </summary>
 /// <param name="status">The status.</param>
 public ElementResult(ServiceResult status)
 {
     m_status = status;
 }
		/// <summary>
		/// Returns true if the status is good or uncertain.
		/// </summary>
		public static bool IsNotBad(ServiceResult status)
		{
			if (status != null)
			{
				return StatusCode.IsNotBad(status.m_code);
			}

			return true;
		}
		/// <summary>
		/// Initializes the object with a status code and a diagnostic info structure.
		/// </summary>
		public ServiceResult(StatusCode code, int index, DiagnosticInfoCollection diagnosticInfos, IList<string> stringTable)
		{
			m_code = (uint)code;

            if (index >= 0 && diagnosticInfos != null && index < diagnosticInfos.Count)
            {
                DiagnosticInfo diagnosticInfo = diagnosticInfos[index];
                
                if (diagnosticInfo != null)
                {
				    m_namespaceUri = LookupString(stringTable, diagnosticInfo.NamespaceUri);
				    m_symbolicId = LookupString(stringTable, diagnosticInfo.SymbolicId);
				    
                    string locale = LookupString(stringTable, diagnosticInfo.Locale);
				    string localizedText  = LookupString(stringTable, diagnosticInfo.LocalizedText);
                    m_localizedText  = new LocalizedText(locale, localizedText);

                    m_additionalInfo = diagnosticInfo.AdditionalInfo;

                    if (!StatusCode.IsGood(diagnosticInfo.InnerStatusCode))
                    {
                        m_innerResult = new ServiceResult(diagnosticInfo.InnerStatusCode, diagnosticInfo.InnerDiagnosticInfo, stringTable);
                    }
                }
            }
		}
Beispiel #40
0
 /// <summary>
 /// Initializes the object with a result code.
 /// </summary>
 /// <param name="status">The status.</param>
 public ElementResult(ServiceResult status)
 {
     m_status = status;
 }
		/// <summary>
		/// Returns true if the status code is uncertain.
		/// </summary>
		public static bool IsUncertain(ServiceResult status)
		{
			if (status != null)
			{
				return StatusCode.IsUncertain(status.m_code);
			}

			return false;
		}
		/// <summary>
		/// Initializes the exception with a status code, a message and an inner exception.
		/// </summary>
		public ServiceResultException(uint statusCode, string message, Exception e) : base(message, e)
		{
            m_status = new ServiceResult(statusCode, message, e);
            
            if ((Utils.TraceMask & Utils.TraceMasks.StackTrace) != 0)
            {
                Utils.Trace(Utils.TraceMasks.StackTrace, "***EXCEPTION*** {0} {1} {2}", m_status, e.GetType().Name, message);
            }
		}
		/// <summary>
		/// Initializes the exception with a Result object.
		/// </summary>
		public ServiceResultException(ServiceResult status) : base(GetMessage(status))
		{
			if (status != null)
			{
				m_status = status;
			}
			else
			{
				m_status = new ServiceResult(StatusCodes.Bad);
            }

            if ((Utils.TraceMask & Utils.TraceMasks.StackTrace) != 0)
            {
                Utils.Trace(Utils.TraceMasks.StackTrace, "***EXCEPTION*** {0}", m_status);
            }
		}
        /// <summary>
		/// Extracts an exception message from a Result object.
		/// </summary>
		private static string GetMessage(ServiceResult status)
		{
			if (status == null)
			{
				return Strings.DefaultMessage;
			}

			if (!LocalizedText.IsNullOrEmpty(status.LocalizedText))
			{
				return status.LocalizedText.Text;
			}

			return status.ToString();
		}
        /// <summary>
        /// Creates a fault message.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="exception">The exception.</param>
        /// <returns>A fault message.</returns>
        protected static ServiceFault CreateFault(IServiceRequest request, Exception exception)
        {
            DiagnosticsMasks diagnosticsMask = DiagnosticsMasks.ServiceNoInnerStatus;

            ServiceFault fault = new ServiceFault();

            if (request != null)
            {
                fault.ResponseHeader.Timestamp     = DateTime.UtcNow;
                fault.ResponseHeader.RequestHandle = request.RequestHeader.RequestHandle;

                if (request.RequestHeader != null)
                {
                    diagnosticsMask = (DiagnosticsMasks)request.RequestHeader.ReturnDiagnostics;
                }
            }

            ServiceResult result = null;

            ServiceResultException sre = exception as ServiceResultException;

            if (sre != null)
            {
                result = new ServiceResult(sre);

                Utils.Trace(
                    Utils.TraceMasks.Service, 
                    "Service Fault Occured. Reason={0}", 
                    result);
            }
            else
            {
                result = new ServiceResult(exception, StatusCodes.BadUnexpectedError);
                Utils.Trace(exception, "SERVER - Unexpected Service Fault: {0}", exception.Message);
            }                               

            fault.ResponseHeader.ServiceResult = result.Code;

            StringTable stringTable = new StringTable();

            fault.ResponseHeader.ServiceDiagnostics = new DiagnosticInfo(
                result, 
                diagnosticsMask, 
                true, 
                stringTable);

            fault.ResponseHeader.StringTable = stringTable.ToArray();
 
            return fault;
        }
		/// <summary>
		/// Initializes the object from a stream.
		/// </summary>
		protected ServiceResultException(SerializationInfo info, StreamingContext context) : base(info, context)
		{
            if (info == null)
            {
                throw new System.ArgumentNullException("info - ServiceResultException");
            }

            m_status = DeserializeServiceResult(info, string.Empty);    
		}
Beispiel #47
0
        /// <summary>
        /// Invokes the methods and returns the output parameters.
        /// </summary>
        /// <param name="context">The context to use.</param>
        /// <param name="objectId">The object being called.</param>
        /// <param name="inputArguments">The input arguments.</param>
        /// <param name="argumentErrors">Any errors for the input arguments.</param>
        /// <param name="outputArguments">The output arguments.</param>
        /// <returns>The result of the method call.</returns>
        public virtual ServiceResult Call(
            ISystemContext context,
            NodeId objectId,
            IList<Variant> inputArguments,
            IList<ServiceResult> argumentErrors,
            IList<Variant> outputArguments)
        {
            // validate input arguments.
            List<object> inputs = new List<object>();

            // check for too few or too many arguments.
            int expectedCount = 0;

            if (InputArguments != null && InputArguments.Value != null)
            {
                expectedCount = InputArguments.Value.Length;
            }

            if (expectedCount != inputArguments.Count)
            {
                return StatusCodes.BadArgumentsMissing;
            }
            
            // validate individual arguements.
            bool error = false;

            for (int ii = 0; ii < inputArguments.Count; ii++)
            {
                ServiceResult argumentError = ValidateInputArgument(context, inputArguments[ii], ii);

                if (ServiceResult.IsBad(argumentError))
                {
                    error = true;
                }

                inputs.Add(inputArguments[ii].Value);
                argumentErrors.Add(argumentError);
            }

            // return good - caller must check argument errors.
            if (error)
            {
                return ServiceResult.Good;
            }

            // set output arguments to default values.
            List<object> outputs = new List<object>();

            if (OutputArguments != null)
            {
                IList<Argument> arguments = OutputArguments.Value;

                if (arguments != null && arguments.Count > 0)
                {
                    for (int ii = 0; ii < arguments.Count; ii++)
                    {
                        outputs.Add(GetArgumentDefaultValue(context, arguments[ii]));
                    }
                }
            }

            // invoke method.
            ServiceResult result = null;

            try
            {
                result = Call(context, objectId, inputs, outputs);
            }
            catch (Exception e)
            {
                result = new ServiceResult(e);
            }

            // copy out arguments.
            if (ServiceResult.IsGood(result))
            {
                for (int ii = 0; ii < outputs.Count; ii++)
                {
                    outputArguments.Add(new Variant(outputs[ii]));
                }
            }

            return result;
        }
        /// <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 virtual void InternalValidate(IList <X509Certificate2> certificates)
        {
            lock (m_lock)
            {
                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 = GetTrustedCertificate(certificate);

                // get the issuers (checks the revocation lists if using directory stores).
                List <CertificateIdentifier> issuers = new List <CertificateIdentifier>();
                bool isIssuerTrusted = 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.
                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.Name);
                    }
                }
            }
        }