File: XmlUtils.cs

package info (click to toggle)
mono 5.18.0.240%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 1,253,216 kB
  • sloc: cs: 10,925,936; xml: 2,804,987; ansic: 643,970; cpp: 120,384; perl: 59,272; asm: 21,383; sh: 20,162; makefile: 18,157; python: 4,715; pascal: 924; sql: 859; sed: 16; php: 1
file content (253 lines) | stat: -rw-r--r-- 17,064 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
//------------------------------------------------------------------------------
// <copyright file="XmlUtils.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------

namespace System.Web.Util {

    using System.IO;
    using System.Xml;
    using System.Xml.XPath;
    using System.Xml.Xsl;
    using System.Diagnostics.CodeAnalysis;

    internal static class XmlUtils
    {
        public static readonly long MaxEntityExpansion = 1024 * 1024;

        [SuppressMessage("Microsoft.Security", "MSEC1208:DoNotUseLoadXml", Justification = "Handles developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
        [SuppressMessage("Microsoft.Security.Xml", "CA3057:DoNotUseLoadXml", Justification = "Handles developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
        public static XmlDocument CreateXmlDocumentFromContent(string content)
        {
            XmlDocument doc = new XmlDocument();

           if (AppSettings.RestrictXmlControls) {
                // We can't use the simple XmlDocument.LoadXml(string) here because there is no way to control the
                // resolver used in that process.  The only way we can do that is if we pass in our own XmlReader.
                using (StringReader sreader = new StringReader(content)) {
                    doc.Load(CreateXmlReader(sreader));
                }
            }
            else {
                doc.LoadXml(content);
            }
            return doc;
        }

        [SuppressMessage("Microsoft.Security", "MSEC1210:UseXmlReaderForXPathDocument", Justification = "Handles developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
        [SuppressMessage("Microsoft.Security.Xml", "CA3059:UseXmlReaderForXPathDocument", Justification = "Handles developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
        public static XPathDocument CreateXPathDocumentFromContent(string content)
        {
            StringReader reader = new StringReader(content);
            if (AppSettings.RestrictXmlControls) {
                return new XPathDocument(CreateXmlReader(reader));
            }
            else {
                return new XPathDocument(reader);
            }
        }

        [SuppressMessage("Microsoft.Security", "MSEC1220:ReviewDtdProcessingAssignment", Justification = "Dtd processing is needed for back-compat, but is being done as safely as possible.")]
        [SuppressMessage("Microsoft.Security.Xml", "CA3069:ReviewDtdProcessingAssignment", Justification = "Dtd processing is needed for back-compat, but is being done as safely as possible.")]
        public static XmlReaderSettings CreateXmlReaderSettings()
        {
            XmlReaderSettings settings = new XmlReaderSettings();
            if (AppSettings.RestrictXmlControls)
            {
                settings.MaxCharactersFromEntities = XmlUtils.MaxEntityExpansion;
                settings.XmlResolver = null;
                // Prohibit is the default here.  We don't need to prohibit DTD's, or even ignore them if we're using
                // RestrictXmlControls, because we use a null resolver and limit/disable entity expansion.
                settings.DtdProcessing = DtdProcessing.Parse;
            }
            return settings;
        }

        // Ideally, these XmlReader factories would use XmlReader.Create() in the non-RestrictXmlControls case,
        // but the default settings on that method are different from the default settings generated by XmlTextReader
        // constructors, which is the code we're replacing with these factories.  Since we want to keep doing
        // whatever it was that we did before in this case, we'll just new up an XmlTextReader rather than
        // try to guess at how to set matching defaults with XmlReader.Create().
        // (E.g. DtdProcessing is Parse by default using XmlTextReader directly.  It's Prohibit in default XmlReaderSettings.)
        [SuppressMessage("Microsoft.Security", "MSEC1205:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
        [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
        [SuppressMessage("Microsoft.Security", "MSEC1225:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")]
        [SuppressMessage("Microsoft.Security.Xml", "CA3074:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")]
        public static XmlReader CreateXmlReader(string filepath)
        {
            if (AppSettings.RestrictXmlControls)
            {
                NoEntitiesXmlTextReader nextr = new NoEntitiesXmlTextReader(filepath);
                return XmlReader.Create(nextr, CreateXmlReaderSettings());
            }
            else
            {
                XmlTextReader xtr = new XmlTextReader(filepath);
                return xtr;
            }
        }

        [SuppressMessage("Microsoft.Security", "MSEC1205:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
        [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
        [SuppressMessage("Microsoft.Security", "MSEC1225:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")]
        [SuppressMessage("Microsoft.Security.Xml", "CA3074:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")]
        public static XmlReader CreateXmlReader(Stream datastream)
        {
            if (AppSettings.RestrictXmlControls)
            {
                NoEntitiesXmlTextReader nextr = new NoEntitiesXmlTextReader(datastream);
                return XmlReader.Create(nextr, CreateXmlReaderSettings());
            }
            else
            {
                XmlTextReader xtr = new XmlTextReader(datastream);
                return xtr;
            }
        }

        [SuppressMessage("Microsoft.Security", "MSEC1205:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
        [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
        [SuppressMessage("Microsoft.Security", "MSEC1225:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")]
        [SuppressMessage("Microsoft.Security.Xml", "CA3074:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")]
        public static XmlReader CreateXmlReader(TextReader reader)
        {
            if (AppSettings.RestrictXmlControls)
            {
                NoEntitiesXmlTextReader nextr = new NoEntitiesXmlTextReader(reader);
                return XmlReader.Create(nextr, CreateXmlReaderSettings());
            }
            else
            {
                XmlTextReader xtr = new XmlTextReader(reader);
                return xtr;
            }
        }

        [SuppressMessage("Microsoft.Security", "MSEC1205:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
        [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
        [SuppressMessage("Microsoft.Security", "MSEC1225:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")]
        [SuppressMessage("Microsoft.Security.Xml", "CA3074:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")]
        public static XmlReader CreateXmlReader(Stream contentStream, string baseURI)
        {
            if (AppSettings.RestrictXmlControls)
            {
                NoEntitiesXmlTextReader nextr = new NoEntitiesXmlTextReader(baseURI, contentStream);
                return XmlReader.Create(nextr, CreateXmlReaderSettings());
            }
            else
            {
                XmlTextReader xtr = new XmlTextReader(baseURI, contentStream);
                return xtr;
            }
        }

        // If you use any of these overloads that take in XmlReaderSettings, the suggestion is to get your base settings from
        // CreateXmlReaderSettings().  That way you will have the correct defaults for RestrictXmlControls if applicable.
        // Then you need to be smart about which settings you change before passing in here, because we will not
        // re-enforce the correct settings, just in case you intentionally meant to change them.
        public static XmlReader CreateXmlReader(TextReader reader, string baseURI, XmlReaderSettings settings)
        {
            if (settings == null) {
                settings = CreateXmlReaderSettings();
            }

            // Note:  If there is nothing materially changed in the settings, then Create() will just return your reader back
            // to you and reader.Settings might still be null.
            return XmlReader.Create(reader, settings, baseURI);
        }

        public static XslCompiledTransform CreateXslCompiledTransform(XmlReader xmlReader)
        {
            XmlReader readerToUse = xmlReader;

            // XslCompiledTransform reconstructs its own XmlReader from scratch, so we can't rely entirely on the fancy
            // protections we have in place on our readers.  We need to bring out a bigger hammer and disable DTD's
            // alltogether.  We know how to work with XmlTextReader and which of its settings XslCompiledTransform will
            // respect.  For other reader types, just try to wrap it with new settings.
            if (AppSettings.RestrictXmlControls) {
                XmlTextReader xtr = xmlReader as XmlTextReader;
                if (xtr != null) {
                    xtr.DtdProcessing = DtdProcessing.Ignore;
                }
                else {
                    XmlReaderSettings settings = xmlReader.Settings;
                    if (settings == null) {
                        settings = CreateXmlReaderSettings();
                    }
                    settings.DtdProcessing = DtdProcessing.Ignore;
                    readerToUse = XmlReader.Create(xmlReader, settings);
                }
            }

            XslCompiledTransform compiledTransform = new XslCompiledTransform();
            // The second parameter is XsltSettings.  null results in the XsltSettings.Default being used, which disables the document function, and script
            // The third parameter is an XmlResolver to be used
            compiledTransform.Load(readerToUse, null, null);
            return compiledTransform;
        }


#pragma warning disable 0618    // To avoid deprecation warning
        [SuppressMessage("Microsoft.Security", "MSEC1201:DoNotUseXslTransform", Justification = "Handles developer-controlled input xsl.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
        [SuppressMessage("Microsoft.Security.Xml", "CA3050:DoNotUseXslTransform", Justification = "Handles developer-controlled input xsl.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
        public static XslTransform CreateXslTransform(XmlReader reader)
        {
            if (!AppSettings.RestrictXmlControls)
            {
                XslTransform xform = new XslTransform();
                xform.Load(reader);
                return xform;
            }
            return null;
        }

        [SuppressMessage("Microsoft.Security", "MSEC1201:DoNotUseXslTransform", Justification = "Handles developer-controlled input xsl.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
        [SuppressMessage("Microsoft.Security.Xml", "CA3050:DoNotUseXslTransform", Justification = "Handles developer-controlled input xsl.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
        public static XslTransform CreateXslTransform(XmlReader reader, XmlResolver resolver)
        {
            if (!AppSettings.RestrictXmlControls)
            {
                XslTransform xform = new XslTransform();
                xform.Load(reader, resolver, null);
                return xform;
            }
            return null;
        }

        public static XslTransform GetXslTransform(XslTransform xform)
        {
            return (AppSettings.RestrictXmlControls ? null : xform);
        }
#pragma warning restore 0618

        // This class exists to override the ResolveEntity() method, which can be used to force resolution of custom/external
        // entities in Xml files.  When we use this class, we should have already set EntityHandling to EntityHandling.ExpandCharEntities,
        // which will disable custom/external entity expansion by default.  But this extra protection will keep people from unintentionally
        // shooting themselves in the foot when they think they might have been safe.
        private sealed class NoEntitiesXmlTextReader : XmlTextReader
        {
            [SuppressMessage("Microsoft.Security", "MSEC1205:DoNotAllowDtdOnXmlTextReader", Justification = "Handles developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
            public NoEntitiesXmlTextReader() : base() { Restrict(); }
            [SuppressMessage("Microsoft.Security", "MSEC1205:DoNotAllowDtdOnXmlTextReader", Justification = "Handles developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
            public NoEntitiesXmlTextReader(string filepath) : base(filepath) { Restrict(); }
            [SuppressMessage("Microsoft.Security", "MSEC1205:DoNotAllowDtdOnXmlTextReader", Justification = "Handles developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
            public NoEntitiesXmlTextReader(TextReader reader) : base(reader) { Restrict(); }
            [SuppressMessage("Microsoft.Security", "MSEC1205:DoNotAllowDtdOnXmlTextReader", Justification = "Handles developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
            public NoEntitiesXmlTextReader(Stream datastream) : base(datastream) { Restrict(); }
            [SuppressMessage("Microsoft.Security", "MSEC1205:DoNotAllowDtdOnXmlTextReader", Justification = "Handles developer-controlled input xml.  Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
            public NoEntitiesXmlTextReader(string baseURI, Stream contentStream) : base(baseURI, contentStream) { Restrict(); }

            public override void ResolveEntity()
            {
                // Do not ever do general entity expansion/replacement, even when asked
                return;
            }

            private void Restrict() {
                EntityHandling = EntityHandling.ExpandCharEntities;
                XmlResolver = null;
            }
        }
    }
}