Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
WebApplicationFirewall.cs
1using System;
3using System.Diagnostics.CodeAnalysis;
4using System.Threading.Tasks;
5using System.Xml;
6using System.Xml.Schema;
9using Waher.Events;
14
15namespace Waher.Security.WAF
16{
21 {
25 public const string Namespace = "http://waher.se/Schema/WAF.xsd";
26
30 private static readonly XmlSchema schema = XSL.LoadSchema(typeof(WebApplicationFirewall).Namespace + ".Schema.WAF.xsd");
31
32 private readonly Cache<string, object> internalCache;
33 private readonly ILoginAuditor loginAuditor;
34 private readonly string fileName;
35 private readonly string appDataFolder;
36 private Dictionary<string, WafAction> actionsById = new Dictionary<string, WafAction>();
37 private Dictionary<int, RedirectionInfo> redirections = new Dictionary<int, RedirectionInfo>();
38 private LinkedList<RedirectionInfo> pendingRedirections = new LinkedList<RedirectionInfo>();
39 private Root root;
40 private int redirectionCounter = 0;
41
50 string AppDataFolder)
51 : this(XML.ParseXml(Xml, true), FileName, LoginAuditor, AppDataFolder)
52 {
53 }
54
63 string AppDataFolder)
64 : this(Xml.DocumentElement, FileName, LoginAuditor, AppDataFolder)
65 {
66 }
67
76 string AppDataFolder)
77 {
78 this.fileName = FileName;
79 this.appDataFolder = AppDataFolder;
80 this.loginAuditor = LoginAuditor;
81 this.root = WafAction.Parse(Xml, null, this) as Root;
82
83 if (this.root is null)
84 throw new Exception("Invalid root element of WAF definition.");
85
86 this.internalCache = new Cache<string, object>(int.MaxValue,
87 TimeSpan.FromDays(1), TimeSpan.FromDays(1))
88 {
89 MaxTimerIntervalMs = 1000
90 };
91
92 this.root.Prepare();
93 }
94
103 string AppDataFolder)
104 {
105 XmlDocument Doc = XML.LoadFromFile(FileName, true);
106 XSL.Validate(FileName, Doc, nameof(Root), Namespace, schema);
108 }
109
113 public string FileName => this.fileName;
114
118 public string AppDataFolder => this.appDataFolder;
119
123 public ILoginAuditor LoginAuditor => this.loginAuditor;
124
129 internal void RegisterAction(WafAction Action)
130 {
131 if (!string.IsNullOrEmpty(Action.Id))
132 this.actionsById[Action.Id] = Action;
133 }
134
138 internal Cache<string, object> Cache => this.internalCache;
139
143 public void Dispose()
144 {
145 this.internalCache.Dispose();
146 }
147
154 public bool TryGetActionById(string Id, [NotNullWhen(true)] out WafAction Action)
155 {
156 return this.actionsById.TryGetValue(Id, out Action);
157 }
158
165 public async Task<WafResult> Review(HttpRequest Request, HttpResource Resource)
166 {
167 try
168 {
169 ProcessingState State = new ProcessingState(Request, Resource, this);
170
171 return await this.root.Review(State) ?? this.root.DefaultResult;
172 }
173 catch (Exception ex)
174 {
175 Log.Exception(ex);
176 return this.root.DefaultResult;
177 }
178 }
179
183 public Task Reload()
184 {
185 XmlDocument Doc = XML.LoadFromFile(this.fileName, true);
186 XSL.Validate(this.fileName, Doc, nameof(Root), Namespace, schema);
187
188 Dictionary<string, WafAction> Bak = this.actionsById; ;
189 this.actionsById = new Dictionary<string, WafAction>();
190
191 if (!(WafAction.Parse(Doc.DocumentElement, null, this) is Root Root2))
192 {
193 this.actionsById = Bak;
194 throw new Exception("Invalid root element of WAF definition.");
195 }
196
197 this.root = Root2;
198 this.root.Prepare();
199
200 this.internalCache.Clear();
201
202 return Task.CompletedTask;
203 }
204
205 internal WafResult GetRedirectionResult(RedirectionType Type, string Location)
206 {
207 DateTime Limit = DateTime.UtcNow.AddMinutes(-1);
208
209 lock (this.redirections)
210 {
211 RedirectionInfo Info;
212
213 while (!(this.pendingRedirections.First is null) &&
214 (Info = this.pendingRedirections.First.Value).Created <= Limit)
215 {
216 this.redirections.Remove(Info.Index);
217 this.pendingRedirections.RemoveFirst();
218 }
219
220 int Index = --this.redirectionCounter;
221 if (Index > 0)
222 Index = this.redirectionCounter = -1;
223
224 Info = new RedirectionInfo(Type, Location, Index);
225 this.redirections[Index] = Info;
226 Info.Node = this.pendingRedirections.AddLast(Info);
227
228 return (WafResult)Index;
229 }
230 }
231
238 public bool TryGetRedirection(WafResult Result, out HttpException Redirection)
239 {
240 lock (this.redirections)
241 {
242 if (!this.redirections.TryGetValue((int)Result, out RedirectionInfo Info))
243 {
244 Redirection = null;
245 return false;
246 }
247
248 this.redirections.Remove((int)Result);
249 this.pendingRedirections.Remove(Info.Node);
250
251 switch (Info.Type)
252 {
253 case RedirectionType.TemporaryRedirection:
254 default:
255 Redirection = new TemporaryRedirectException(Info.Location);
256 break;
257
258 case RedirectionType.PermanentRedirection:
259 Redirection = new PermanentRedirectException(Info.Location);
260 break;
261
262 case RedirectionType.SeeOther:
263 Redirection = new SeeOtherException(Info.Location);
264 break;
265 }
266
267 return true;
268 }
269 }
270 }
271}
Helps with common XML-related tasks.
Definition: XML.cs:21
static XmlDocument LoadFromFile(string FileName)
Loads an XML document from a file.
Definition: XML.cs:1808
Static class managing loading of XSL resources stored as embedded resources or in content files.
Definition: XSL.cs:16
static XmlSchema LoadSchema(string ResourceName)
Loads an XML schema from an embedded resource.
Definition: XSL.cs:24
static void Validate(string ObjectID, XmlDocument Xml, params XmlSchema[] Schemas)
Validates an XML document given a set of XML schemas.
Definition: XSL.cs:134
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:14
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
Definition: Log.cs:1657
Base class of all HTTP Exceptions.
Represents an HTTP request.
Definition: HttpRequest.cs:22
Base class for all HTTP resources.
Definition: HttpResource.cs:23
This means that the resource is now permanently located at another URI, specified by the Location: HT...
The response to the request can be found under a different URI and SHOULD be retrieved using a GET me...
The requested resource resides temporarily under a different URI. Since the redirection MAY be altere...
Implements an in-memory cache.
Definition: Cache.cs:17
Contains the current state of a review process.
Root object of Web Application Firewall rules.
Definition: Root.cs:12
WafResult DefaultResult
Default result.
Definition: Root.cs:37
override Task< WafResult?> Review(ProcessingState State)
Reviews the processing state, and returns a WAF result, if any.
Definition: Root.cs:58
Abstract base class for Web Application Firewall actions.
Definition: WafAction.cs:17
static WafAction Parse(XmlElement Xml, WafAction Parent, WebApplicationFirewall Document)
Parses an XML Element defining a WAF action.
Definition: WafAction.cs:99
override void Prepare()
Prepares the node for processing.
Definition: WafActions.cs:61
Web Application Firewall for HttpServer.
Task Reload()
Reloads the firewall configuration from its original source.
WebApplicationFirewall(string Xml, string FileName, ILoginAuditor LoginAuditor, string AppDataFolder)
Web Application Firewall for HttpServer.
string AppDataFolder
Application data folder, where content files are stored.
ILoginAuditor LoginAuditor
Login Auditor used by the Firewall.
const string Namespace
http://waher.se/Schema/WAF.xsd
static WebApplicationFirewall LoadFromFile(string FileName, ILoginAuditor LoginAuditor, string AppDataFolder)
Loads a WAF definition from file.
bool TryGetRedirection(WafResult Result, out HttpException Redirection)
Tries to get a redirection, if the result is a redirection result.
bool TryGetActionById(string Id, [NotNullWhen(true)] out WafAction Action)
Tries to get an action node by its ID.
async Task< WafResult > Review(HttpRequest Request, HttpResource Resource)
Reviews an incoming request.
WebApplicationFirewall(XmlDocument Xml, string FileName, ILoginAuditor LoginAuditor, string AppDataFolder)
Web Application Firewall for HttpServer.
WebApplicationFirewall(XmlElement Xml, string FileName, ILoginAuditor LoginAuditor, string AppDataFolder)
Web Application Firewall for HttpServer.
Interface for Web Application Firewalls (WAF).
Interface for classes that monitor login events, and help applications determine malicious intent.
WafResult
Actions that a Web Server can take after reviewing a request.