Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
Assert.cs
1using System;
3using System.Diagnostics;
4using System.IO;
5using System.Reflection;
6using System.Text.RegularExpressions;
7using Waher.Events;
8
10{
14 public static class Assert
15 {
20 [Obsolete("Use CallFromSource(ICallStackCheck[]) instead.")]
21 public static void CallFromAssembly(params Assembly[] Assemblies)
22 {
23 int i, c = Assemblies.Length;
24 ICallStackCheck[] Sources = new ICallStackCheck[c];
25
26 for (i = 0; i < c; i++)
27 Sources[i] = new ApproveAssembly(Assemblies[i]);
28
29 CallFromSource(Sources);
30 }
31
36 [Obsolete("Use CallFromSource(ICallStackCheck[]) instead.")]
37 public static void CallFromClass(params Type[] Classes)
38 {
39 int i, c = Classes.Length;
40 ICallStackCheck[] Sources = new ICallStackCheck[c];
41
42 for (i = 0; i < c; i++)
43 Sources[i] = new ApproveType(Classes[i]);
44
45 CallFromSource(Sources);
46 }
47
53 [Obsolete("Use CallFromSource(ICallStackCheck[]) instead.")]
54 public static void CallFromSource(params string[] Sources)
55 {
56 int i, c = Sources.Length;
57 ICallStackCheck[] Sources2 = new ICallStackCheck[c];
58
59 for (i = 0; i < c; i++)
60 Sources2[i] = new ApproveString(Sources[i]);
61
62 CallFromSource(Sources2);
63 }
64
70 [Obsolete("Use CallFromSource(ICallStackCheck[]) instead.")]
71 public static void CallFromSource(params Regex[] Sources)
72 {
73 int i, c = Sources.Length;
74 ICallStackCheck[] Sources2 = new ICallStackCheck[c];
75
76 for (i = 0; i < c; i++)
77 Sources2[i] = new ApproveRegex(Sources[i]);
78
79 CallFromSource(Sources2);
80 }
81
87 [Obsolete("Use CallFromSource(ICallStackCheck[]) instead.")]
88 public static void CallFromSource(params object[] Sources)
89 {
90 CallFromSource(Convert(Sources));
91 }
92
99 public static ICallStackCheck[] Convert(params object[] Sources)
100 {
101 int i, c = Sources.Length;
102 ICallStackCheck[] Sources2 = new ICallStackCheck[c];
103
104 for (i = 0; i < c; i++)
105 {
106 object Source = Sources[i];
107
108 if (Source is ICallStackCheck Check)
109 Sources2[i] = Check;
110 else if (Source is Assembly A)
111 Sources2[i] = new ApproveAssembly(A);
112 else if (Source is Type T)
113 Sources2[i] = new ApproveType(T);
114 else if (Source is Regex Regex)
115 Sources2[i] = new ApproveRegex(Regex);
116 else if (Source is string s)
117 Sources2[i] = new ApproveString(s);
118 else
119 throw new ArgumentException("Invalid source type: " + Source.GetType().FullName, nameof(Sources));
120 }
121
122 return Sources2;
123 }
124
131 public static void CallFromSource(params ICallStackCheck[] Sources)
132 {
133 CallFromSource(new ICallStackCheck[][] { Sources });
134 }
135
144 public static void CallFromSource(params ICallStackCheck[][] SourcesByPriority)
145 {
146 FrameInformation FrameInfo;
147 int Skip = 1;
148 bool WaherPersistence = false;
149 bool WaherRuntime = false;
150 bool AsynchTask = false;
151 bool Other = false;
152
153 while (true)
154 {
155 FrameInfo = new FrameInformation(new StackFrame(Skip));
156 if (FrameInfo.Last)
157 break;
158
159 if (FrameInfo.Valid && FrameInfo.Type != typeof(Assert))
160 break;
161
162 Skip++;
163 }
164
165 int Caller = Skip;
166 bool Prohibited = false;
167 bool? Status;
168
169 foreach (ICallStackCheck[] Sources in SourcesByPriority)
170 {
171 Skip = Caller + 1;
172
173 while (!Prohibited)
174 {
175 FrameInfo = new FrameInformation(new StackFrame(Skip++));
176 if (FrameInfo.Last)
177 break;
178
179 if (!FrameInfo.Valid)
180 continue;
181
182 foreach (ICallStackCheck Source in Sources)
183 {
184 Status = Source.Check(FrameInfo);
185 if (Status.HasValue)
186 {
187 if (Status.Value)
188 return;
189 else
190 {
191 Prohibited = true;
192 break;
193 }
194 }
195 }
196
197 if (Prohibited)
198 break;
199
200 if (!Other || !AsynchTask || !WaherPersistence)
201 {
202 if (string.IsNullOrEmpty(FrameInfo.Assembly.Location))
203 {
204 if (FrameInfo.AssemblyName.StartsWith("WPSA."))
205 WaherPersistence = true;
206 else
207 Other = true;
208 }
209 else
210 {
211 string AssemblyName = FrameInfo.AssemblyName;
212
213 switch (AssemblyName)
214 {
215 case "Waher.Persistence.Serialization.Compiled":
216 AssemblyName = "Waher.Persistence.Serialization";
217 break;
218
219 case "Waher.Persistence.FilesLW":
220 AssemblyName = "Waher.Persistence.Files";
221 break;
222
223 default:
224 if (AssemblyName.EndsWith(".UWP"))
225 AssemblyName = AssemblyName.Substring(0, AssemblyName.Length - 4);
226 break;
227 }
228
229 if (FrameInfo.Type == typeof(System.Threading.Tasks.Task))
230 AsynchTask = true;
231 else if (FrameInfo.TypeName.StartsWith(AssemblyName) &&
232 FrameInfo.AssemblyName + "." == Path.ChangeExtension(Path.GetFileName(FrameInfo.Assembly.Location), string.Empty))
233 {
234 if (FrameInfo.AssemblyName.StartsWith("Waher.Persistence.") ||
235 FrameInfo.AssemblyName.StartsWith("WPSA."))
236 {
237 WaherPersistence = true;
238 }
239 else if (FrameInfo.AssemblyName.StartsWith("Waher.Runtime."))
240 WaherRuntime = true;
241 else if (FrameInfo.AssemblyName.StartsWith("WPSA."))
242 WaherPersistence = true;
243 else if (!FrameInfo.AssemblyName.StartsWith("Waher.") && !FrameInfo.AssemblyName.StartsWith("System."))
244 Other = true;
245 }
246 else if (!Path.GetFileName(FrameInfo.Assembly.Location).StartsWith("System."))
247 Other = true;
248 }
249 }
250 }
251
252 if (Prohibited)
253 break;
254 }
255
256 // In asynch call - stack trace not showing asynchronous call stack after JIT.
257 // If loading from database, i.e. populating object asynchronously, (possibly,
258 // check is vulnerable), give check a pass. Access will be restricted at a later
259 // stage, when accessing properties synchronously.
260
261 if (!Prohibited && AsynchTask && (WaherPersistence || WaherRuntime) && !Other)
262 return;
263
264 FrameInfo = new FrameInformation(new StackFrame(Skip = Caller));
265
266 string ObjectId = FrameInfo.Type.FullName + "." + FrameInfo.Method.Name;
267 StackTrace Trace = new StackTrace(Skip, false);
269 List<KeyValuePair<string, object>> Tags = new List<KeyValuePair<string, object>>()
270 {
271 new KeyValuePair<string, object>("Method", FrameInfo.Method.Name),
272 new KeyValuePair<string, object>("Type", FrameInfo.Type.FullName),
273 new KeyValuePair<string, object>("Assembly", FrameInfo.Assembly.FullName)
274 };
275
276 Skip = 0;
277 while (true)
278 {
279 FrameInfo = new FrameInformation(new StackFrame(Skip));
280 if (FrameInfo.Last)
281 break;
282
283 if (FrameInfo.Valid)
284 {
285 Tags.Add(new KeyValuePair<string, object>("Pos" + Skip.ToString(),
286 FrameInfo.Assembly.GetName().Name + ", " + FrameInfo.TypeName + ", " +
287 FrameInfo.Method.Name));
288 }
289 else
290 Tags.Add(new KeyValuePair<string, object>("Pos" + Skip.ToString(), FrameInfo.ToString()));
291
292 Skip++;
293 }
294
295 Log.Warning("Unauthorized access detected and prevented.", ObjectId, string.Empty, "UnauthorizedAccess", EventLevel.Major,
296 string.Empty, e.Assembly.FullName, Trace.ToString(), Tags.ToArray());
297
298 UnauthorizedAccess?.Raise(null, e);
299
300 throw new UnauthorizedCallstackException("Unauthorized access.");
301 }
302
306 public static event EventHandler<UnauthorizedAccessEventArgs> UnauthorizedAccess = null;
307
308 }
309}
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:14
static void Warning(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs a warning event.
Definition: Log.cs:576
Checks for an approved assembly in the call stack.
Checks for approved sources in the call stack using a regular expression.
Definition: ApproveRegex.cs:11
Checks for approved sources in the call stack using a string.
Checks for an approved type in the call stack.
Definition: ApproveType.cs:10
Static class containing methods that can be used to make sure calls are made from appropriate locatio...
Definition: Assert.cs:15
static ICallStackCheck[] Convert(params object[] Sources)
Converts an array of objects into an array of ICallStackCheck objects, assuming each listed source is...
Definition: Assert.cs:99
static void CallFromSource(params Regex[] Sources)
Makes sure the call is made from one of the listed sources.
Definition: Assert.cs:71
static EventHandler< UnauthorizedAccessEventArgs > UnauthorizedAccess
Event raised when an unauthorized access has been detected.
Definition: Assert.cs:306
static void CallFromSource(params string[] Sources)
Makes sure the call is made from one of the listed sources.
Definition: Assert.cs:54
static void CallFromClass(params Type[] Classes)
Makes sure the call is made from one of the listed classes.
Definition: Assert.cs:37
static void CallFromSource(params object[] Sources)
Makes sure the call is made from one of the listed sources.
Definition: Assert.cs:88
static void CallFromSource(params ICallStackCheck[] Sources)
Makes sure the call is made from one of the approved sources and not from one of the prohibited sourc...
Definition: Assert.cs:131
static void CallFromAssembly(params Assembly[] Assemblies)
Makes sure the call is made from one of the listed assemblies.
Definition: Assert.cs:21
static void CallFromSource(params ICallStackCheck[][] SourcesByPriority)
Makes sure the call is made from one of the approved sources and not from one of the prohibited sourc...
Definition: Assert.cs:144
Contains information about a specific frame in a call stack.
bool Last
If this is the last frame in the stack (no method information available).
Type Type
Call made from this type.
Event arguments for the Assert.UnauthorizedAccess event.
Assembly Assembly
Assembly in which the type is defined.
Exception raised when code tries to access protected code while having a callstack out of the permitt...
Interface for call stack checks.
bool? Check(FrameInformation Frame)
Performs a check of a stack frame.
EventLevel
Event level.
Definition: EventLevel.cs:7