1 //
2 // Unit tests for XmlDecryptionTransform
3 //
4 // Author:
5 //	Sebastien Pouliot  <sebastien@ximian.com>
6 //
7 // Copyright (C) 2008 Novell, Inc (http://www.novell.com)
8 //
9 // Licensed to the .NET Foundation under one or more agreements.
10 // See the LICENSE file in the project root for more information.
11 
12 using System.IO;
13 using System.Xml;
14 using Xunit;
15 
16 namespace System.Security.Cryptography.Xml.Tests
17 {
18 
19     public class UnprotectedXmlDecryptionTransform : XmlDecryptionTransform
20     {
UnprotectedIsTargetElement(XmlElement inputElement, string idValue)21         public bool UnprotectedIsTargetElement(XmlElement inputElement, string idValue)
22         {
23             return base.IsTargetElement(inputElement, idValue);
24         }
25 
UnprotectedGetInnerXml()26         public XmlNodeList UnprotectedGetInnerXml()
27         {
28             return base.GetInnerXml();
29         }
30     }
31 
32     public class XmlDecryptionTransformTest
33     {
34         private UnprotectedXmlDecryptionTransform transform;
35 
XmlDecryptionTransformTest()36         public XmlDecryptionTransformTest()
37         {
38             transform = new UnprotectedXmlDecryptionTransform();
39         }
40 
41         [Fact]
IsTargetElement_XmlElementNull()42         public void IsTargetElement_XmlElementNull()
43         {
44             Assert.False(transform.UnprotectedIsTargetElement(null, "value"));
45         }
46 
47         [Fact]
IsTargetElement_StringNull()48         public void IsTargetElement_StringNull()
49         {
50             XmlDocument doc = new XmlDocument();
51             Assert.False(transform.UnprotectedIsTargetElement(doc.DocumentElement, null));
52         }
53 
54         [Theory]
55         [InlineData("<a id=\"1\" />", "1", true)]
56         [InlineData("<a ID=\"1\" />", "1", true)]
57         [InlineData("<a Id=\"1\" />", "1", true)]
58         [InlineData("<a iD=\"1\" />", "1", false)]
59         [InlineData("<a id=\"1\" />", "2", false)]
IsTargetElement_ValidXml(string xml, string id, bool expectedResult)60         public void IsTargetElement_ValidXml(string xml, string id, bool expectedResult)
61         {
62             XmlDocument doc = new XmlDocument();
63             doc.LoadXml(xml);
64 
65             Assert.Equal(expectedResult, transform.UnprotectedIsTargetElement(doc.DocumentElement, id));
66         }
67 
68         [Fact]
AddExceptUri_Null()69         public void AddExceptUri_Null()
70         {
71             Assert.Throws<ArgumentNullException>(() => transform.AddExceptUri(null));
72         }
73 
74         [Fact]
EncryptedXml_NotNull()75         public void EncryptedXml_NotNull()
76         {
77             Assert.NotNull(transform.EncryptedXml);
78         }
79 
80         [Fact]
InputTypes()81         public void InputTypes()
82         {
83             Type[] inputTypes = transform.InputTypes;
84 
85             Assert.Equal(2, inputTypes.Length);
86             Assert.Contains(typeof(Stream), inputTypes);
87             Assert.Contains(typeof(XmlDocument), inputTypes);
88         }
89 
90         [Fact]
OutputTypes()91         public void OutputTypes()
92         {
93             Type[] outputTypes = transform.OutputTypes;
94 
95             Assert.Equal(1, outputTypes.Length);
96             Assert.Contains(typeof(XmlDocument), outputTypes);
97         }
98 
99         [Fact]
LoadInnerXml_XmlNull()100         public void LoadInnerXml_XmlNull()
101         {
102             Assert.Throws<CryptographicException>(() => transform.LoadInnerXml(null));
103         }
104 
105         [Fact]
LoadInnerXml_XmlNoExcept()106         public void LoadInnerXml_XmlNoExcept()
107         {
108             XmlDocument doc = new XmlDocument();
109             doc.LoadXml("<a />");
110 
111             transform.LoadInnerXml(doc.ChildNodes);
112 
113             Assert.Null(transform.UnprotectedGetInnerXml());
114         }
115 
116         [Fact]
LoadInnerXml_XmlNoUriForExcept()117         public void LoadInnerXml_XmlNoUriForExcept()
118         {
119             XmlDocument doc = new XmlDocument();
120             doc.LoadXml(@"<dcrpt:Except xmlns:dcrpt=""http://www.w3.org/2002/07/decrypt#""/>");
121 
122             Assert.Throws<CryptographicException>(() => transform.LoadInnerXml(doc.ChildNodes));
123         }
124 
125         [Fact]
LoadInnerXml_XmlValidUriForExcept()126         public void LoadInnerXml_XmlValidUriForExcept()
127         {
128             XmlDocument doc = new XmlDocument();
129             doc.LoadXml(@"<dcrpt:Except URI=""#item1"" xmlns:dcrpt=""http://www.w3.org/2002/07/decrypt#""/>");
130 
131             transform.LoadInnerXml(doc.ChildNodes);
132 
133             Assert.NotNull(transform.UnprotectedGetInnerXml());
134         }
135 
136         [Fact]
137         [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "https://github.com/dotnet/corefx/issues/16798")]
LoadStreamInput_CorrectXml()138         public void LoadStreamInput_CorrectXml()
139         {
140             XmlDocument doc = new XmlDocument();
141             string xml = "<root><a /><b /></root>";
142             doc.LoadXml(xml);
143 
144             using (MemoryStream memoryStream = new MemoryStream())
145             using (StreamWriter streamWriter = new StreamWriter(memoryStream, Text.Encoding.Unicode))
146             {
147                 streamWriter.Write(xml);
148                 streamWriter.Flush();
149                 memoryStream.Position = 0;
150 
151                 transform.LoadInput(memoryStream);
152                 XmlDocument output = (XmlDocument)transform.GetOutput();
153 
154                 Assert.Equal(xml, output.OuterXml);
155             }
156         }
157 
158         [Fact]
GetOutput_WrongType()159         public void GetOutput_WrongType()
160         {
161             XmlDocument doc = new XmlDocument();
162             string xml = "<test />";
163             doc.LoadXml(xml);
164 
165             transform.LoadInput(doc);
166             AssertExtensions.Throws<ArgumentException>("type", () => transform.GetOutput(typeof(string)));
167         }
168 
169         [Fact]
170         [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "https://github.com/dotnet/corefx/issues/16798")]
GetOutput_XmlNoEncryptedData()171         public void GetOutput_XmlNoEncryptedData()
172         {
173             XmlDocument doc = new XmlDocument();
174             string xml = "<test />";
175             doc.LoadXml(xml);
176 
177             transform.LoadInput(doc);
178             XmlDocument transformedDocument = (XmlDocument)transform.GetOutput(typeof(XmlDocument));
179 
180             Assert.Equal(xml, transformedDocument.OuterXml);
181         }
182 
183         [Fact]
184         [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "https://github.com/dotnet/corefx/issues/16798")]
GetOutput_XmlWithEncryptedData()185         public void GetOutput_XmlWithEncryptedData()
186         {
187             XmlDocument doc = new XmlDocument();
188             string xml = "<root><a /><b /><c>To Be Encrypted</c><d /></root>";
189             doc.LoadXml(xml);
190 
191             XmlDocument transformedDocument = GetTransformedOutput(doc, "c");
192 
193             Assert.NotNull(transformedDocument);
194             Assert.Equal(xml, transformedDocument.OuterXml);
195         }
196 
197         [Fact]
198         [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "https://github.com/dotnet/corefx/issues/16798")]
GetOutput_XmlWithEncryptedDataInRoot()199         public void GetOutput_XmlWithEncryptedDataInRoot()
200         {
201             XmlDocument doc = new XmlDocument();
202             string xml = "<root>To Be Encrypted</root>";
203             doc.LoadXml(xml);
204 
205             XmlDocument transformedDocument = GetTransformedOutput(doc, "//root");
206 
207             Assert.NotNull(transformedDocument);
208             Assert.Equal(xml, transformedDocument.OuterXml);
209         }
210 
211         [Fact]
212         [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "https://github.com/dotnet/corefx/issues/16798")]
GetOutput_XmlWithEncryptedDataAndExcept()213         public void GetOutput_XmlWithEncryptedDataAndExcept()
214         {
215             XmlDocument doc = new XmlDocument();
216             string xml = "<root><a /><b /><c>To Be Encrypted</c><d /></root>";
217             doc.LoadXml(xml);
218 
219             transform.AddExceptUri("#_notfound");
220             transform.AddExceptUri("#_0");
221             XmlDocument transformedDocument = GetTransformedOutput(doc, "c");
222 
223             XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(doc.NameTable);
224             xmlNamespaceManager.AddNamespace("enc", EncryptedXml.XmlEncNamespaceUrl);
225             Assert.NotNull(transformedDocument.DocumentElement.SelectSingleNode("//enc:EncryptedData", xmlNamespaceManager));
226             Assert.NotEqual(xml, transformedDocument.OuterXml);
227         }
228 
GetTransformedOutput(XmlDocument doc, string nodeToEncrypt)229         private XmlDocument GetTransformedOutput(XmlDocument doc, string nodeToEncrypt)
230         {
231             using (var aesAlgo = Aes.Create())
232             {
233                 var encryptedXml = new EncryptedXml();
234                 encryptedXml.AddKeyNameMapping("aes", aesAlgo);
235                 XmlElement elementToEncrypt = (XmlElement)doc.DocumentElement.SelectSingleNode(nodeToEncrypt);
236                 EncryptedData encryptedData = encryptedXml.Encrypt(elementToEncrypt, "aes");
237                 EncryptedXml.ReplaceElement(elementToEncrypt, encryptedData, false);
238 
239                 XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(doc.NameTable);
240                 xmlNamespaceManager.AddNamespace("enc", EncryptedXml.XmlEncNamespaceUrl);
241                 XmlElement encryptedNode = (XmlElement)doc.DocumentElement.SelectSingleNode("//enc:EncryptedData", xmlNamespaceManager);
242                 encryptedNode.SetAttribute("ID", "#_0");
243 
244                 transform.LoadInput(doc);
245                 transform.EncryptedXml = encryptedXml;
246                 XmlDocument transformedDocument = (XmlDocument)transform.GetOutput();
247 
248                 transform.EncryptedXml = null;
249 
250                 return transformedDocument;
251             }
252         }
253     }
254 }
255 
256