/// <summary>
        /// Obtain a W3C formatted SigningTime (equivalent to TimeStamp)
        /// </summary>
        /// <param name="xDoc">xml document we are building</param>
        /// <param name="dateTime">time to persist</param>
        /// <param name="signatureId">id of new signature</param>
        /// <param name="xmlDateTimeFormat">format to use - must be Xml date format legal syntax</param>
        /// <returns>given writer with SignatureProperties xml added to it</returns>
        /// <remarks>format matches that described in http://www.w3.org/TR/NOTE-datetime </remarks>
        /// <example>
        /// <Object Id="Package">
        ///     <SignatureProperties>
        ///         <SignatureProperty Target="#signatureId">
        ///             <SignatureTime>
        ///                 <Format>YYYY-MM-DDThh:mm:ssTZD</Format>
        ///                 <Value>1997-07-16T19:20:30.45+01:00</Value>
        ///             </SignatureTime>
        ///         </SignatureProperty>
        ///     </SignatureProperties>
        /// </Object>
        /// </example>
        internal static XmlElement AssembleSignatureProperties(
            XmlDocument xDoc,
            DateTime dateTime,
            String xmlDateTimeFormat,
            String signatureId)
        {
            Invariant.Assert(xDoc != null);
            Invariant.Assert(signatureId != null);

            // check for null format - use default if null
            if (xmlDateTimeFormat == null)
            {
                xmlDateTimeFormat = DefaultDateTimeFormat;
            }

            string[] dateTimeFormats = ConvertXmlFormatStringToDateTimeFormatString(xmlDateTimeFormat);

            // <SignatureProperties>
            XmlElement signatureProperties = xDoc.CreateElement(XTable.Get(XTable.ID.SignaturePropertiesTagName),
                                                                SignedXml.XmlDsigNamespaceUrl);

            // <SignatureProperty Id="idSignatureTime" Target="#signatureId">
            XmlElement signatureProperty = xDoc.CreateElement(XTable.Get(XTable.ID.SignaturePropertyTagName),
                                                              SignedXml.XmlDsigNamespaceUrl);

            signatureProperties.AppendChild(signatureProperty);
            XmlAttribute idAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.SignaturePropertyIdAttrName));

            idAttr.Value = XTable.Get(XTable.ID.SignaturePropertyIdAttrValue);
            signatureProperty.Attributes.Append(idAttr);
            XmlAttribute targetAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.TargetAttrName));

            targetAttr.Value = "#" + signatureId;
            signatureProperty.Attributes.Append(targetAttr);

            // <SignatureTime>
            XmlElement signatureTime = xDoc.CreateElement(XTable.Get(XTable.ID.SignatureTimeTagName),
                                                          XTable.Get(XTable.ID.OpcSignatureNamespace));
            XmlElement signatureTimeFormat = xDoc.CreateElement(XTable.Get(XTable.ID.SignatureTimeFormatTagName),
                                                                XTable.Get(XTable.ID.OpcSignatureNamespace));
            XmlElement signatureTimeValue = xDoc.CreateElement(XTable.Get(XTable.ID.SignatureTimeValueTagName),
                                                               XTable.Get(XTable.ID.OpcSignatureNamespace));

            signatureTimeFormat.AppendChild(xDoc.CreateTextNode(xmlDateTimeFormat));
            signatureTimeValue.AppendChild(xDoc.CreateTextNode(DateTimeToXmlFormattedTime(dateTime, dateTimeFormats[0])));

            signatureTime.AppendChild(signatureTimeFormat);
            signatureTime.AppendChild(signatureTimeValue);

            signatureProperty.AppendChild(signatureTime);

            return(signatureProperties);
        }
Esempio n. 2
0
        /// <summary>
        /// Locates and selects the target XmlElement from all available Object tags
        /// </summary>
        /// <param name="signature"></param>
        /// <param name="idValue"></param>
        /// <returns>element if found; null if not found</returns>
        /// <remarks>relies on XPath query to search the Xml in each Object tag</remarks>
        private static XmlElement SelectSubObjectNodeForXAdESInDataObjects(Signature signature, string idValue)
        {
            XmlElement node       = null;
            bool       foundMatch = false; // true if id has matched, even with the wrong namespace

            // now find an object tag that includes an element that matches
            foreach (DataObject dataObject in signature.ObjectList)
            {
                // skip the package object
                if (String.CompareOrdinal(dataObject.Id, XTable.Get(XTable.ID.OpcAttrValue)) != 0)
                {
                    XmlElement element = dataObject.GetXml();

                    // NOTE: this is executing an XPath query
                    // idValue has already been tested as an NCName (unless overridden for compatibility), so there's no
                    // escaping that needs to be done here.
                    XmlNodeList nodeList = element.SelectNodes(".//*[@Id='" + idValue + "']");

                    if (nodeList.Count > 0)
                    {
                        if (!AllowAmbiguousReferenceTargets() &&
                            (nodeList.Count > 1 || foundMatch))
                        {
                            throw new XmlException(SR.Get(SRID.DuplicateObjectId));
                        }

                        foundMatch = true;
                        XmlNode local = nodeList[0] as XmlElement;

                        if (local != null)
                        {
                            XmlNode temp = local;

                            // climb the tree towards the root until we find our namespace
                            while ((temp != null) && (temp.NamespaceURI.Length == 0))
                            {
                                temp = temp.ParentNode;
                            }

                            // only match if the target is in the XAdES namespace
                            if ((temp != null) && (String.CompareOrdinal(temp.NamespaceURI, _XAdESNameSpace) == 0))
                            {
                                node = local as XmlElement;
                                // continue searching, to find duplicates from different objects
                            }
                        }
                    }
                }
            }

            return(node);
        }
Esempio n. 3
0
        /// <summary>
        /// Verify if the SignatureProperty tag has a valid Id attribute
        /// </summary>
        /// <param name="reader">NodeReader positioned at the SignatureProperty tag</param>
        /// <returns>true, if Id attribute is present and has the correct value, else false</returns>
        private static bool VerifyIdAttribute(XmlReader reader)
        {
            string idAttrValue = reader.GetAttribute(XTable.Get(XTable.ID.SignaturePropertyIdAttrName));

            if (idAttrValue != null &&
                (String.CompareOrdinal(idAttrValue, XTable.Get(XTable.ID.SignaturePropertyIdAttrValue)) == 0))
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
        /// <summary>
        /// Generate Manifest tag
        /// </summary>
        /// <param name="manager">manager</param>
        /// <param name="xDoc">current Xml doc</param>
        /// <param name="hashAlgorithm">hash algorithm to hash with</param>
        /// <param name="parts">parts to sign - possibly null</param>
        /// <param name="relationshipSelectors">relationshipSelectors that represent the
        /// relationships that have to be signed - possibly null</param>
        /// <returns></returns>
        internal static XmlNode GenerateManifest(
            PackageDigitalSignatureManager manager,
            XmlDocument xDoc,
            HashAlgorithm hashAlgorithm,
            IEnumerable <Uri> parts,
            IEnumerable <PackageRelationshipSelector> relationshipSelectors)
        {
            Debug.Assert(manager != null);
            Debug.Assert(xDoc != null);
            Debug.Assert(hashAlgorithm != null);

            // check args
            if (!hashAlgorithm.CanReuseTransform)
            {
                throw new ArgumentException(SR.Get(SRID.HashAlgorithmMustBeReusable));
            }

            // <Manifest>
            XmlNode manifest = xDoc.CreateNode(XmlNodeType.Element,
                                               XTable.Get(XTable.ID.ManifestTagName),
                                               SignedXml.XmlDsigNamespaceUrl);

            // add part references
            if (parts != null)
            {
                // loop and write - may still be empty
                foreach (Uri partUri in parts)
                {
                    // generate a reference tag
                    manifest.AppendChild(GeneratePartSigningReference(manager, xDoc, hashAlgorithm, partUri));
                }
            }

            // any relationship references?
            int relationshipCount = 0;

            if (relationshipSelectors != null)
            {
                relationshipCount = GenerateRelationshipSigningReferences(manager, xDoc, hashAlgorithm, relationshipSelectors, manifest);
            }

            // did we sign anything? Manifest can NOT be empty
            if (parts == null && relationshipCount == 0)
            {
                throw new ArgumentException(SR.Get(SRID.NothingToSign));
            }

            return(manifest);
        }
        private static XmlNode GeneratePartSigningReference(
            PackageDigitalSignatureManager manager,
            XmlDocument xDoc,
            HashAlgorithm hashAlgorithm,
            Uri partName)
        {
            PackagePart part = manager.Package.GetPart(partName);

            // <Reference>
            XmlElement reference = xDoc.CreateElement(XTable.Get(XTable.ID.ReferenceTagName), SignedXml.XmlDsigNamespaceUrl);

            // add Uri with content type as Query
            XmlAttribute uriAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.UriAttrName));

            uriAttr.Value = PackUriHelper.GetStringForPartUri(partName) + _contentTypeQueryStringPrefix + part.ContentType;
            reference.Attributes.Append(uriAttr);

            // add transforms tag if necessary
            String transformName = String.Empty;

            if (manager.TransformMapping.ContainsKey(part.ContentType))
            {
                transformName = manager.TransformMapping[part.ContentType];

                // <Transforms>
                XmlElement transforms = xDoc.CreateElement(XTable.Get(XTable.ID.TransformsTagName), SignedXml.XmlDsigNamespaceUrl);

                // <Transform>
                XmlElement   transform     = xDoc.CreateElement(XTable.Get(XTable.ID.TransformTagName), SignedXml.XmlDsigNamespaceUrl);
                XmlAttribute algorithmAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.AlgorithmAttrName));
                algorithmAttr.Value = transformName;
                transform.Attributes.Append(algorithmAttr);

                transforms.AppendChild(transform);
                reference.AppendChild(transforms);
            }

            // <DigestMethod>
            reference.AppendChild(GenerateDigestMethod(manager, xDoc));

            // <DigestValue>
            using (Stream s = part.GetStream(FileMode.Open, FileAccess.Read))
            {
                reference.AppendChild(GenerateDigestValueNode(xDoc, hashAlgorithm, s, transformName));
            }

            return(reference);
        }
Esempio n. 6
0
        /// <summary>
        /// Locates and selects the target XmlElement from all available Object tags
        /// </summary>
        /// <param name="signature"></param>
        /// <param name="idValue"></param>
        /// <returns>element if found; null if not found</returns>
        /// <remarks>relies on XPath query to search the Xml in each Object tag</remarks>
        private static XmlElement SelectSubObjectNodeForXAdESInDataObjects(Signature signature, string idValue)
        {
            XmlElement node = null;

            // now find an object tag that includes an element that matches
            foreach (DataObject dataObject in signature.ObjectList)
            {
                // skip the package object
                if (String.CompareOrdinal(dataObject.Id, XTable.Get(XTable.ID.OpcAttrValue)) != 0)
                {
                    XmlElement element = dataObject.GetXml();

                    // NOTE: this is executing an XPath query
                    XmlElement local = element.SelectSingleNode("//*[@Id='" + idValue + "']") as XmlElement;
                    if (local == null)
                    {
                        continue;
                    }

                    // node found?
                    if (local != null)
                    {
                        XmlNode temp = local;

                        // climb the tree towards the root until we find our namespace
                        while ((temp != null) && (temp.NamespaceURI.Length == 0))
                        {
                            temp = temp.ParentNode;
                        }

                        // only match if the target is in the XAdES namespace
                        if ((temp != null) && (String.CompareOrdinal(temp.NamespaceURI, _XAdESNameSpace) == 0))
                        {
                            node = local as XmlElement;
                            break;
                        }
                    }
                }
            }

            return(node);
        }
        /// <summary>
        /// Get the part uri and it's content type from the current Reference tag
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="contentType">contentType extracted from the query portion of the Uri</param>
        /// <returns>PackagePart uri and contentType</returns>
        private static Uri ParsePartUri(XmlReader reader, out ContentType contentType)
        {
            // should be a relative Package uri with a query portion that contains the ContentType
            contentType = ContentType.Empty;
            Uri partUri = null;

            // must be one and only one attribute
            if (PackagingUtilities.GetNonXmlnsAttributeCount(reader) == 1)
            {
                string uriAttrValue = reader.GetAttribute(XTable.Get(XTable.ID.UriAttrName));
                if (uriAttrValue != null)
                {
                    partUri = ParsePartUriAttribute(uriAttrValue, out contentType);
                }
            }

            // will be null if we had no success
            if (partUri == null)
            {
                throw new XmlException(SR.Get(SRID.RequiredXmlAttributeMissing, XTable.Get(XTable.ID.UriAttrName)));
            }

            return(partUri);
        }
        /// <summary>
        /// Generates a Reference tag that contains a Relationship transform
        /// </summary>
        /// <param name="manager">manager</param>
        /// <param name="relationshipPartName">name of the relationship part</param>
        /// <param name="xDoc">current xml document</param>
        /// <param name="hashAlgorithm">hash algorithm = digest method</param>
        /// <param name="relationshipSelectors">relationshipSelectors that represent the relationships to sign </param>
        /// <remarks>ContentType is known and part name can be derived from the relationship collection</remarks>
        private static XmlNode GenerateRelationshipSigningReference(
            PackageDigitalSignatureManager manager,
            XmlDocument xDoc,
            HashAlgorithm hashAlgorithm,
            Uri relationshipPartName,
            IEnumerable <PackageRelationshipSelector> relationshipSelectors)
        {
            string relPartContentType = PackagingUtilities.RelationshipPartContentType.ToString();

            // <Reference>
            XmlElement reference = xDoc.CreateElement(XTable.Get(XTable.ID.ReferenceTagName), SignedXml.XmlDsigNamespaceUrl);

            // add Uri
            // persist the Uri of the associated Relationship part
            String relationshipPartString;

            if (PackUriHelper.ComparePartUri(relationshipPartName, PackageRelationship.ContainerRelationshipPartName) == 0)
            {
                relationshipPartString = PackageRelationship.ContainerRelationshipPartName.ToString();
            }
            else
            {
                relationshipPartString = PackUriHelper.GetStringForPartUri(relationshipPartName);
            }

            XmlAttribute uriAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.UriAttrName));

            uriAttr.Value = relationshipPartString + _contentTypeQueryStringPrefix + relPartContentType;
            reference.Attributes.Append(uriAttr);

            // add transforms tag (always necessary)

            // <Transforms>
            XmlElement transforms = xDoc.CreateElement(XTable.Get(XTable.ID.TransformsTagName), SignedXml.XmlDsigNamespaceUrl);

            // add Relationship transform
            String opcNamespace       = XTable.Get(XTable.ID.OpcSignatureNamespace);
            String opcNamespacePrefix = XTable.Get(XTable.ID.OpcSignatureNamespacePrefix);

            XmlElement   transform     = xDoc.CreateElement(XTable.Get(XTable.ID.TransformTagName), SignedXml.XmlDsigNamespaceUrl);
            XmlAttribute algorithmAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.AlgorithmAttrName));

            algorithmAttr.Value = XTable.Get(XTable.ID.RelationshipsTransformName);
            transform.Attributes.Append(algorithmAttr);

            // <RelationshipReference SourceId="abc" /> or
            // <RelationshipGroupReference SourceType="xyz" />
            foreach (PackageRelationshipSelector relationshipSelector in relationshipSelectors)
            {
                switch (relationshipSelector.SelectorType)
                {
                case PackageRelationshipSelectorType.Id:
                {
                    XmlNode      relationshipNode = xDoc.CreateElement(opcNamespacePrefix, XTable.Get(XTable.ID.RelationshipReferenceTagName), opcNamespace);
                    XmlAttribute idAttr           = xDoc.CreateAttribute(XTable.Get(XTable.ID.SourceIdAttrName));
                    idAttr.Value = relationshipSelector.SelectionCriteria;
                    relationshipNode.Attributes.Append(idAttr);
                    transform.AppendChild(relationshipNode);
                }
                break;

                case PackageRelationshipSelectorType.Type:
                {
                    XmlNode      relationshipNode = xDoc.CreateElement(opcNamespacePrefix, XTable.Get(XTable.ID.RelationshipsGroupReferenceTagName), opcNamespace);
                    XmlAttribute typeAttr         = xDoc.CreateAttribute(XTable.Get(XTable.ID.SourceTypeAttrName));
                    typeAttr.Value = relationshipSelector.SelectionCriteria;
                    relationshipNode.Attributes.Append(typeAttr);
                    transform.AppendChild(relationshipNode);
                }
                break;

                default:
                    Invariant.Assert(false, "This option should never be executed");
                    break;
                }
            }

            transforms.AppendChild(transform);

            // add non-Relationship transform (if any)
            String transformName = null;

            if (manager.TransformMapping.ContainsKey(relPartContentType))
            {
                transformName = manager.TransformMapping[relPartContentType];       // let them override

                //Currently we only support two transforms and so we validate whether its
                //one of those
                if (transformName == null ||
                    transformName.Length == 0 ||
                    !XmlDigitalSignatureProcessor.IsValidXmlCanonicalizationTransform(transformName))
                {
                    throw new InvalidOperationException(SR.Get(SRID.UnsupportedTransformAlgorithm));
                }

                // <Transform>
                transform           = xDoc.CreateElement(XTable.Get(XTable.ID.TransformTagName), SignedXml.XmlDsigNamespaceUrl);
                algorithmAttr       = xDoc.CreateAttribute(XTable.Get(XTable.ID.AlgorithmAttrName));
                algorithmAttr.Value = transformName;
                transform.Attributes.Append(algorithmAttr);

                transforms.AppendChild(transform);
            }
            reference.AppendChild(transforms);

            // <DigestMethod>
            reference.AppendChild(GenerateDigestMethod(manager, xDoc));

            // <DigestValue> - digest the virtual node list made from these Relationship tags
            using (Stream s = XmlDigitalSignatureProcessor.GenerateRelationshipNodeStream(GetRelationships(manager, relationshipSelectors)))    // serialized node list
            {
                reference.AppendChild(GenerateDigestValueNode(xDoc, hashAlgorithm, s, transformName));
            }

            return(reference);
        }
        /// <summary>
        /// Parses Transforms tag
        /// </summary>
        /// <param name="reader">node to parse</param>
        /// <param name="partUri">Part Uri for the part owning the relationships</param>
        /// <param name="relationshipSelectors">allocates and returns a list of
        /// PackageRelationshipSelectors if Relationship transform</param>
        /// <returns>ordered list of Transform names</returns>
        private static List <String> ParseTransformsTag(XmlReader reader, Uri partUri, ref List <PackageRelationshipSelector> relationshipSelectors)
        {
            // # reference that signs multiple PackageRelationships
            // <Reference URI="/shared/_rels/image.jpg.rels?ContentType=image/jpg">
            //      <Transforms>
            //          <Transform Algorithm="http://schemas.openxmlformats.org/package/2006/RelationshipTransform">
            //              <RelationshipReference SourceId="1" />
            //              <RelationshipReference SourceId="2" />
            //              <RelationshipReference SourceId="8" />
            //          </Transform>
            //          <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
            //      </Transforms>
            //      <DigestMethod Algorithm="sha1" />
            //      <DigestValue>... </DigestValue>
            // </Reference>

            // verify lack of attributes
            if (PackagingUtilities.GetNonXmlnsAttributeCount(reader) != 0)
            {
                throw new XmlException(SR.Get(SRID.XmlSignatureParseError));
            }

            List <String> transforms = null;
            bool          relationshipTransformFound = false;
            int           transformsCountWhenRelationshipTransformFound = 0;

            // Look for transforms.
            // There are currently only 3 legal transforms which can be arranged in any
            // combination.
            while (reader.Read() && (reader.MoveToContent() == XmlNodeType.Element))
            {
                String transformName = null;

                // at this level, all tags must be Transform tags
                if (reader.Depth != 4 ||
                    String.CompareOrdinal(reader.NamespaceURI, SignedXml.XmlDsigNamespaceUrl) != 0 ||
                    String.CompareOrdinal(reader.LocalName, XTable.Get(XTable.ID.TransformTagName)) != 0)
                {
                    throw new XmlException(SR.Get(SRID.XmlSignatureParseError));
                }

                // inspect the Algorithm attribute to determine the type of transform
                if (PackagingUtilities.GetNonXmlnsAttributeCount(reader) == 1)
                {
                    transformName = reader.GetAttribute(XTable.Get(XTable.ID.AlgorithmAttrName));
                }

                // legal transform name?
                if ((transformName != null) && (transformName.Length > 0))
                {
                    // what type of transform?
                    if (String.CompareOrdinal(transformName, XTable.Get(XTable.ID.RelationshipsTransformName)) == 0)
                    {
                        if (!relationshipTransformFound)
                        {
                            // relationship transform
                            ParseRelationshipsTransform(reader, partUri, ref relationshipSelectors);

                            if (transforms == null)
                            {
                                transforms = new List <String>();
                            }

                            transforms.Add(transformName);

                            relationshipTransformFound = true;
                            transformsCountWhenRelationshipTransformFound = transforms.Count;
                            continue;   // success
                        }
                        else
                        {
                            throw new XmlException(SR.Get(SRID.MultipleRelationshipTransformsFound));
                        }
                    }
                    else
                    {
                        // non-Relationship transform should have no children
                        if (reader.IsEmptyElement)
                        {
                            if (transforms == null)
                            {
                                transforms = new List <String>();
                            }

                            if (XmlDigitalSignatureProcessor.IsValidXmlCanonicalizationTransform(transformName))
                            {
                                transforms.Add(transformName); // return it
                                continue;                      // success
                            }
                            else
                            {
                                throw new InvalidOperationException(SR.Get(SRID.UnsupportedTransformAlgorithm));
                            }
                        }
                    }
                }
                throw new XmlException(SR.Get(SRID.XmlSignatureParseError));
            }

            if (transforms.Count == 0)
            {
                throw new XmlException(SR.Get(SRID.XmlSignatureParseError));
            }

            //If we found another transform after the Relationship transform, it will be validated earlier
            //in this method to make sure that its a supported xml canonicalization algorithm and so we can
            //simplify this test condition - As per the OPC spec - Relationship transform must be followed
            //by a canonicalization algorithm.
            if (relationshipTransformFound && (transforms.Count == transformsCountWhenRelationshipTransformFound))
            {
                throw new XmlException(SR.Get(SRID.RelationshipTransformNotFollowedByCanonicalizationTransform));
            }

            return(transforms);
        }
Esempio n. 10
0
        //-----------------------------------------------------------------------------
        //
        // Private Methods
        //
        //-----------------------------------------------------------------------------

        /// <summary>
        /// Parse the SignatureTime tag
        /// </summary>
        /// <param name="reader">NodeReader positioned at the SignatureProperty tag</param>
        /// <param name="timeFormat">format found</param>
        /// <exception cref="XmlException">illegal format</exception>
        /// <returns>signing time</returns>
        private static DateTime ParseSignatureTimeTag(XmlReader reader, out String timeFormat)
        {
            //There are no attributes on all the three tags that we parse in this method
            //<SignatureTime>, <Format>, <Value>
            int expectedAttributeCount = 0;

            string opcSignatureNameSpace = XTable.Get(XTable.ID.OpcSignatureNamespace);
            string signaturePropertyTag  = XTable.Get(XTable.ID.SignaturePropertyTagName);
            string signatureTimeTag      = XTable.Get(XTable.ID.SignatureTimeTagName);
            string timeValueTagName      = XTable.Get(XTable.ID.SignatureTimeValueTagName);
            string timeFormatTagName     = XTable.Get(XTable.ID.SignatureTimeFormatTagName);

            // <SignatureTime> must be one of <Format> or <Time>
            timeFormat = null;
            string timeValue = null;

            //Look for <SignatureTime> Tag
            if (reader.Read() &&
                reader.MoveToContent() == XmlNodeType.Element &&
                (String.CompareOrdinal(reader.NamespaceURI, opcSignatureNameSpace) == 0) &&
                (String.CompareOrdinal(reader.LocalName, signatureTimeTag) == 0) &&
                reader.Depth == 3 &&
                PackagingUtilities.GetNonXmlnsAttributeCount(reader) == expectedAttributeCount)
            {
                while (reader.Read())
                {
                    if (String.CompareOrdinal(reader.NamespaceURI, opcSignatureNameSpace) == 0 &&
                        reader.MoveToContent() == XmlNodeType.Element &&
                        reader.Depth == 4)
                    {
                        // which tag do we have?
                        if ((String.CompareOrdinal(reader.LocalName, timeValueTagName) == 0) &&
                            PackagingUtilities.GetNonXmlnsAttributeCount(reader) == expectedAttributeCount)
                        {
                            if (timeValue == null &&
                                reader.Read() &&
                                reader.MoveToContent() == XmlNodeType.Text &&
                                reader.Depth == 5)
                            {
                                //After reading the content, the reader progresses to the next element.
                                //So after this method is called, the reader is positioned at the
                                //EndElement corresponding to Value tag - </Value>
                                // Note: ReadContentAsString will return String.Empty but never null
                                timeValue = reader.ReadContentAsString();
                                Debug.Assert(reader.NodeType == XmlNodeType.EndElement);
                            }
                            else
                            {
                                //This would happen if we found more than one Value tags or if there
                                //are other nested elements of if they are of a different XmlNodeType type
                                throw new XmlException(SR.PackageSignatureCorruption);
                            }
                        }
                        else if ((String.CompareOrdinal(reader.LocalName, timeFormatTagName) == 0) &&
                                 PackagingUtilities.GetNonXmlnsAttributeCount(reader) == expectedAttributeCount)
                        {
                            if (timeFormat == null &&
                                reader.Read() &&
                                reader.MoveToContent() == XmlNodeType.Text &&
                                reader.Depth == 5)
                            {
                                //After reading the content, the reader progresses to the next element.
                                //So after this method is called, the reader is positioned at the
                                //EndElement corresponding to Format tag - </Format>
                                // Note: ReadContentAsString will return String.Empty but never null
                                timeFormat = reader.ReadContentAsString();
                                Debug.Assert(reader.NodeType == XmlNodeType.EndElement);
                            }
                            else
                            {
                                //This would happen if we found more than one Format tags or if there
                                //are other nested elements of if they are of a different XmlNodeType type
                                throw new XmlException(SR.PackageSignatureCorruption);
                            }
                        }
                        else
                        {
                            //If we encounter any tag other than <Format> or <Time> nested within the <SignatureTime> tag
                            throw new XmlException(SR.PackageSignatureCorruption);
                        }
                    }
                    else
                    //If we have encountered the end tag for the <SignatureTime> tag
                    //then we are done parsing the tag, and we can stop the parsing.
                    if (String.CompareOrdinal(signatureTimeTag, reader.LocalName) == 0 &&
                        (reader.NodeType == XmlNodeType.EndElement))
                    {
                        //We must find a  </SignatureProperty> tag at this point,
                        //else it could be that there are more SignatureTime or
                        //other tags nested here and that is an error.
                        if (reader.Read() &&
                            reader.MoveToContent() == XmlNodeType.EndElement &&
                            String.CompareOrdinal(signaturePropertyTag, reader.LocalName) == 0)
                        {
                            break;
                        }
                        else
                        {
                            throw new XmlException(SR.PackageSignatureCorruption);
                        }
                    }
                    else
                    {
                        // if we do not find the nested elements as expected
                        throw new XmlException(SR.PackageSignatureCorruption);
                    }
                }
            }
            else
            {
                throw new XmlException(SR.Format(SR.RequiredTagNotFound, signatureTimeTag));
            }


            // generate an equivalent DateTime object
            if (timeValue != null && timeFormat != null)
            {
                return(XmlFormattedTimeToDateTime(timeValue, timeFormat));
            }
            else
            {
                throw new XmlException(SR.PackageSignatureCorruption);
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Parse the xml and determine the signing time
        /// </summary>
        /// <param name="reader">NodeReader positioned at the SignatureProperties tag</param>
        /// <param name="signatureId">value of the Id attribute on the Signature tag</param>
        /// <param name="timeFormat">format found</param>
        /// <exception cref="XmlException">illegal format</exception>
        /// <returns>signing time</returns>
        internal static DateTime ParseSigningTime(XmlReader reader, string signatureId, out String timeFormat)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            bool   signatureTimePropertyFound = false;
            bool   signatureTimeIdFound       = false;
            string w3cSignatureNameSpace      = SignedXml.XmlDsigNamespaceUrl;

            // <SignatureProperty> tag
            string signaturePropertyTag   = XTable.Get(XTable.ID.SignaturePropertyTagName);
            string signaturePropertiesTag = XTable.Get(XTable.ID.SignaturePropertiesTagName);

            //initializing to a dummy value
            DateTime signingTime = DateTime.Now;

            timeFormat = null;

            while (reader.Read())
            {
                //Looking for <SignatureProperty> tag
                if (reader.MoveToContent() == XmlNodeType.Element &&
                    (String.CompareOrdinal(reader.NamespaceURI, w3cSignatureNameSpace) == 0) &&
                    (String.CompareOrdinal(reader.LocalName, signaturePropertyTag) == 0) &&
                    reader.Depth == 2)
                {
                    //Verify Attributes
                    //Look for well-defined Id attribute and if it is present
                    if (VerifyIdAttribute(reader))
                    {
                        //If we encounter more than one <SignatureProperty> tag with the expected
                        //id, then its an error.
                        if (signatureTimeIdFound)
                        {
                            throw new XmlException(SR.PackageSignatureCorruption);
                        }
                        else
                        {
                            signatureTimeIdFound = true;
                        }

                        //VerifyTargetAttribute will return false, if the Target attribute is missing
                        //or contains an incorrect value.
                        if (VerifyTargetAttribute(reader, signatureId))
                        {
                            signingTime = ParseSignatureTimeTag(reader, out timeFormat);
                            signatureTimePropertyFound = true;
                        }
                    }
                }
                else
                //Expected <SignatureProperty> tag not found.
                //Look for end tag corresponding to </SignatureProperty> or
                //if these are other custom defined properties, then anything with
                //depth greater than 2 should be ignored as these can be nested elements.
                if (((String.CompareOrdinal(signaturePropertyTag, reader.LocalName) == 0 &&
                      (reader.NodeType == XmlNodeType.EndElement))) ||
                    reader.Depth > 2)
                {
                    continue;
                }
                else
                //If we find the end tag for </SignatureProperties> then we can stop parsing
                if ((String.CompareOrdinal(signaturePropertiesTag, reader.LocalName) == 0 &&
                     (reader.NodeType == XmlNodeType.EndElement)))
                {
                    break;
                }
                else
                {
                    throw new XmlException(SR.Format(SR.RequiredTagNotFound, signaturePropertyTag));
                }
            }

            //We did find one or more <SignatureProperty> tags but there were none that
            //defined the id attribute and target attribute and <SignatureTime> element tag correctly.
            if (!signatureTimePropertyFound)
            {
                throw new XmlException(SR.PackageSignatureCorruption);
            }

            return(signingTime);
        }
Esempio n. 12
0
 internal TableEntry(XTable.ID index, string str) { id = index; s = str; }