/// <summary> /// Checks that the filter is valid. /// </summary> public ServiceResult Validate() { // check deadband type enumeration. if ((int)DeadbandType < (int)Opc.Ua.DeadbandType.None || (int)DeadbandType > (int)Opc.Ua.DeadbandType.Percent) { return(ServiceResult.Create( StatusCodes.BadDeadbandFilterInvalid, "Deadband type '{0}' is not recognized.", DeadbandType)); } // check data change trigger enumeration. if ((int)Trigger < (int)DataChangeTrigger.Status || (int)Trigger > (int)DataChangeTrigger.StatusValueTimestamp) { return(ServiceResult.Create( StatusCodes.BadDeadbandFilterInvalid, "Deadband trigger '{0}' is not recognized.", Trigger)); } // deadband value must always be greater than 0. if (DeadbandValue < 0) { return(ServiceResult.Create( StatusCodes.BadDeadbandFilterInvalid, "Deadband value '{0}' cannot be less than zero.", DeadbandValue)); } // deadband percentage must be less than 100. if ((int)DeadbandType == (int)Opc.Ua.DeadbandType.Percent) { if (DeadbandValue > 100) { return(ServiceResult.Create( StatusCodes.BadDeadbandFilterInvalid, "Percentage deadband value '{0}' cannot be greater than 100.", DeadbandValue)); } } // passed initial validation. return(ServiceResult.Good); }
/// <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 Exception CreateSoapFault(IServiceRequest request, Exception exception) { ServiceFault fault = CreateFault(request, exception); // get the error from the header. ServiceResult error = fault.ResponseHeader.ServiceResult; if (error == null) { error = ServiceResult.Create(StatusCodes.BadUnexpectedError, "An unknown error occurred."); } // construct the fault code and fault reason. string codeName = StatusCodes.GetBrowseName(error.Code); return(new ServiceResultException((uint)error.StatusCode, codeName, exception)); }
/// <summary> /// Validates the operand (sets the ParsedBrowsePath and ParsedIndexRange properties). /// </summary> public override ServiceResult Validate(FilterContext context, int index) { m_validated = false; // verify attribute id. if (!Attributes.IsValid(m_attributeId)) { return(ServiceResult.Create( StatusCodes.BadAttributeIdInvalid, "SimpleAttributeOperand does not specify a valid AttributeId ({0}).", m_attributeId)); } // initialize as empty. m_parsedIndexRange = NumericRange.Empty; // parse the index range. if (!String.IsNullOrEmpty(m_indexRange)) { try { m_parsedIndexRange = NumericRange.Parse(m_indexRange); } catch (Exception e) { return(ServiceResult.Create( e, StatusCodes.BadIndexRangeInvalid, "SimpleAttributeOperand does not specify a valid BrowsePath ({0}).", m_indexRange)); } if (m_attributeId != Attributes.Value) { return(ServiceResult.Create( StatusCodes.BadIndexRangeInvalid, "SimpleAttributeOperand specifies an IndexRange for an Attribute other than Value ({0}).", m_attributeId)); } } m_validated = true; return(ServiceResult.Good); }
/// <summary> /// Validates a software certificate. /// </summary> public static ServiceResult Validate( CertificateValidator validator, byte[] signedCertificate, out SoftwareCertificate softwareCertificate) { softwareCertificate = null; // validate the certificate. X509Certificate2 certificate = null; try { certificate = new X509Certificate2(signedCertificate); validator.Validate(certificate); } catch (Exception e) { return(ServiceResult.Create(e, StatusCodes.BadDecodingError, "Could not decode software certificate body.")); } // find the software certficate. byte[] encodedData = null; if (encodedData == null) { return(ServiceResult.Create(StatusCodes.BadCertificateInvalid, "Could not find extension containing the software certficate.")); } try { MemoryStream istrm = new MemoryStream(encodedData, false); DataContractSerializer serializer = new DataContractSerializer(typeof(SoftwareCertificate)); softwareCertificate = (SoftwareCertificate)serializer.ReadObject(istrm); softwareCertificate.SignedCertificate = certificate; } catch (Exception e) { return(ServiceResult.Create(e, StatusCodes.BadCertificateInvalid, "Certificate does not contain a valid SoftwareCertificate body.")); } // certificate is valid. return(ServiceResult.Good); }
/// <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 Exception CreateSoapFault(IServiceRequest request, Exception exception) { ServiceFault fault = CreateFault(request, exception); // get the error from the header. ServiceResult error = fault.ResponseHeader.ServiceResult; if (error == null) { error = ServiceResult.Create(StatusCodes.BadUnexpectedError, "An unknown error occurred."); } // construct the fault code and fault reason. string codeName = StatusCodes.GetBrowseName(error.Code); FaultCode code = null; FaultReason reason = null; if (!LocalizedText.IsNullOrEmpty(error.LocalizedText)) { reason = new FaultReason(new FaultReasonText(Utils.Format("{0}", error.LocalizedText), CultureInfo.InvariantCulture)); } else { reason = new FaultReason(new FaultReasonText(codeName, CultureInfo.InvariantCulture)); } if (!String.IsNullOrEmpty(error.SymbolicId)) { FaultCode subcode = new FaultCode(error.SymbolicId, error.NamespaceUri); code = new FaultCode(codeName, Namespaces.OpcUa, subcode); } else { code = new FaultCode(codeName, Namespaces.OpcUa); } // throw the fault. return(new FaultException <ServiceFault>(fault, reason, code)); }
/// <summary> /// Validates a read value id parameter. /// </summary> public static ServiceResult Validate(HistoryReadValueId valueId) { // check for null structure. if (valueId == null) { return(StatusCodes.BadStructureMissing); } // null node ids are always invalid. if (NodeId.IsNull(valueId.NodeId)) { return(StatusCodes.BadNodeIdInvalid); } // initialize as empty. valueId.ParsedIndexRange = NumericRange.Empty; // parse the index range if specified. if (!String.IsNullOrEmpty(valueId.IndexRange)) { try { valueId.ParsedIndexRange = NumericRange.Parse(valueId.IndexRange); } catch (Exception e) { return(ServiceResult.Create(e, StatusCodes.BadIndexRangeInvalid, String.Empty)); } } else { valueId.ParsedIndexRange = NumericRange.Empty; } // passed basic validation. return(null); }
/// <summary> /// Does any processing before a condition is enabled or disabled. /// </summary> /// <param name="context">The system context.</param> /// <param name="enabling">True is the condition is being enabled.</param> protected virtual ServiceResult ProcessBeforeEnableDisable(ISystemContext context, bool enabling) { if (enabling && this.EnabledState.Id.Value) { return(StatusCodes.BadConditionAlreadyEnabled); } if (!enabling && !this.EnabledState.Id.Value) { return(StatusCodes.BadConditionAlreadyDisabled); } if (OnEnableDisable != null) { try { return(OnEnableDisable(context, this, enabling)); } catch (Exception e) { return(ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Unexpected error enabling or disabling a Condition.")); } } return(ServiceResult.Good); }
/// <summary> /// Validates a write value parameter. /// </summary> public static ServiceResult Validate(WriteValue value) { // check for null structure. if (value == null) { return(StatusCodes.BadStructureMissing); } // null node ids are always invalid. if (value.NodeId == null) { return(StatusCodes.BadNodeIdInvalid); } // must be a legimate attribute value. if (!Attributes.IsValid(value.AttributeId)) { return(StatusCodes.BadAttributeIdInvalid); } // initialize as empty. value.ParsedIndexRange = NumericRange.Empty; // parse the index range if specified. if (!String.IsNullOrEmpty(value.IndexRange)) { try { value.ParsedIndexRange = NumericRange.Parse(value.IndexRange); } catch (Exception e) { return(ServiceResult.Create(e, StatusCodes.BadIndexRangeInvalid, String.Empty)); } // check that value provided is actually an array. Array array = value.Value.Value as Array; if (array == null) { return(StatusCodes.BadTypeMismatch); } NumericRange range = value.ParsedIndexRange; // check that the number of elements to write matches the index range. if (range.End >= 0 && (range.End - range.Begin != array.Length - 1)) { return(StatusCodes.BadIndexRangeNoData); } // check for single element. if (range.End < 0 && array.Length != 1) { return(StatusCodes.BadIndexRangeInvalid); } } else { value.ParsedIndexRange = NumericRange.Empty; } // passed basic validation. return(null); }
/// <summary> /// Applies the data encoding to the value. /// </summary> public static ServiceResult ApplyDataEncoding(ServiceMessageContext context, QualifiedName dataEncoding, ref object value) { // check if nothing to do. if (QualifiedName.IsNull(dataEncoding) || value == null) { return(ServiceResult.Good); } // check for supported encoding type. if (dataEncoding.NamespaceIndex != 0) { return(StatusCodes.BadDataEncodingUnsupported); } bool useXml = dataEncoding.Name == DefaultXml; if (!useXml && dataEncoding.Name != DefaultBinary) { return(StatusCodes.BadDataEncodingUnsupported); } try { // check for array of encodeables. IList <IEncodeable> encodeables = value as IList <IEncodeable>; if (encodeables == null) { // check for array of extension objects. IList <ExtensionObject> extensions = value as IList <ExtensionObject>; if (extensions != null) { // convert extension objects to encodeables. encodeables = new IEncodeable[extensions.Count]; for (int ii = 0; ii < encodeables.Count; ii++) { if (ExtensionObject.IsNull(extensions[ii])) { encodeables[ii] = null; continue; } IEncodeable element = extensions[ii].Body as IEncodeable; if (element == null) { return(StatusCodes.BadTypeMismatch); } encodeables[ii] = element; } } } // apply data encoding to the array. if (encodeables != null) { ExtensionObject[] extensions = new ExtensionObject[encodeables.Count]; for (int ii = 0; ii < extensions.Length; ii++) { extensions[ii] = Encode(context, encodeables[ii], useXml); } value = extensions; return(ServiceResult.Good); } // check for scalar value. IEncodeable encodeable = value as IEncodeable; if (encodeable == null) { ExtensionObject extension = value as ExtensionObject; if (extension == null) { return(StatusCodes.BadDataEncodingUnsupported); } encodeable = extension.Body as IEncodeable; } if (encodeable == null) { return(StatusCodes.BadDataEncodingUnsupported); } // do conversion. value = Encode(context, encodeable, useXml); return(ServiceResult.Good); } catch (Exception e) { return(ServiceResult.Create(e, StatusCodes.BadTypeMismatch, "Could not convert value to requested format.")); } }
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: { // 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 Windows 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)); } default: { return(ServiceResult.Create( StatusCodes.BadCertificateInvalid, "Certificate validation failed. {0}: {1}", status.Status, status.StatusInformation)); } } return(null); }
/// <summary> /// Validates a write value parameter. /// </summary> public static ServiceResult Validate(WriteValue value) { // check for null structure. if (value == null) { return(StatusCodes.BadStructureMissing); } // null node ids are always invalid. if (value.NodeId == null) { return(StatusCodes.BadNodeIdInvalid); } // must be a legimate attribute value. if (!Attributes.IsValid(value.AttributeId)) { return(StatusCodes.BadAttributeIdInvalid); } // initialize as empty. value.ParsedIndexRange = NumericRange.Empty; // parse the index range if specified. if (!String.IsNullOrEmpty(value.IndexRange)) { try { value.ParsedIndexRange = NumericRange.Parse(value.IndexRange); } catch (Exception e) { return(ServiceResult.Create(e, StatusCodes.BadIndexRangeInvalid, String.Empty)); } if (value.ParsedIndexRange.SubRanges != null) { Matrix matrix = value.Value.Value as Matrix; if (matrix == null) { // Check for String or ByteString arrays. Those DataTypes have special handling // when using sub ranges. bool isArrayWithValidDataType = value.Value.Value is Array && value.Value.WrappedValue.TypeInfo.BuiltInType == BuiltInType.String || value.Value.WrappedValue.TypeInfo.BuiltInType == BuiltInType.ByteString; if (!isArrayWithValidDataType) { return(StatusCodes.BadTypeMismatch); } } } else { // check that value provided is actually an array. Array array = value.Value.Value as Array; string str = value.Value.Value as string; if (array != null) { NumericRange range = value.ParsedIndexRange; // check that the number of elements to write matches the index range. if (range.End >= 0 && (range.End - range.Begin != array.Length - 1)) { return(StatusCodes.BadIndexRangeNoData); } // check for single element. if (range.End < 0 && array.Length != 1) { return(StatusCodes.BadIndexRangeInvalid); } } else if (str != null) { NumericRange range = value.ParsedIndexRange; // check that the number of elements to write matches the index range. if (range.End >= 0 && (range.End - range.Begin != str.Length - 1)) { return(StatusCodes.BadIndexRangeNoData); } // check for single element. if (range.End < 0 && str.Length != 1) { return(StatusCodes.BadIndexRangeInvalid); } } else { return(StatusCodes.BadTypeMismatch); } } } else { value.ParsedIndexRange = NumericRange.Empty; } // passed basic validation. return(null); }
/// <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); }
/// <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.")); }
/// <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 = 4; 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); }
/// <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); }
/// <summary> /// Initializes the exception with a message and an exception. /// </summary> public ServiceResultException(Exception e, uint defaultCode) : base(e.Message, e) { m_status = ServiceResult.Create(e, defaultCode, String.Empty); }