PageRenderTime 41ms CodeModel.GetById 25ms app.highlight 13ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/tools/security/permview.cs

https://github.com/hollow87/mono
C# | 411 lines | 327 code | 69 blank | 15 comment | 58 complexity | c3478b6a0346eb5411c07baa000dfb07 MD5 | raw file
  1//
  2// permview.cs: Managed Permission Viewer for .NET assemblies
  3//
  4// Author:
  5//	Sebastien Pouliot  <sebastien@ximian.com>
  6//
  7// Copyright (C) 2004-2007 Novell, Inc (http://www.novell.com)
  8//
  9
 10using System;
 11using System.Collections;
 12using System.Collections.Generic;
 13using System.IO;
 14using System.Reflection;
 15using System.Security;
 16using SSP = System.Security.Permissions;
 17using System.Text;
 18
 19using Mono.Cecil;
 20
 21[assembly: AssemblyTitle ("Mono PermView")]
 22[assembly: AssemblyDescription ("Managed Permission Viewer for .NET assemblies")]
 23
 24namespace Mono.Tools {
 25
 26	static class SecurityDeclarationRocks {
 27
 28		public static PermissionSet ToPermissionSet (this SecurityDeclaration self)
 29		{
 30			if (self == null)
 31				throw new ArgumentNullException ("self");
 32
 33			PermissionSet set;
 34			if (TryProcessPermissionSetAttribute (self, out set))
 35				return set;
 36
 37			return CreatePermissionSet (self);
 38		}
 39
 40		static bool TryProcessPermissionSetAttribute (SecurityDeclaration declaration, out PermissionSet set)
 41		{
 42			set = null;
 43
 44			if (!declaration.HasSecurityAttributes && declaration.SecurityAttributes.Count != 1)
 45				return false;
 46
 47			var security_attribute = declaration.SecurityAttributes [0];
 48			var attribute_type = security_attribute.AttributeType;
 49
 50			if (attribute_type.Name != "PermissionSetAttribute" || attribute_type.Namespace != "System.Security.Permissions")
 51				return false;
 52
 53			var named_argument = security_attribute.Properties [0];
 54			if (named_argument.Name != "XML")
 55				throw new NotSupportedException ();
 56
 57			var attribute = new SSP.PermissionSetAttribute ((SSP.SecurityAction) declaration.Action);
 58			attribute.XML = (string) named_argument.Argument.Value;
 59
 60			set = attribute.CreatePermissionSet ();
 61			return true;
 62		}
 63
 64		static PermissionSet CreatePermissionSet (SecurityDeclaration declaration)
 65		{
 66			var set = new PermissionSet (SSP.PermissionState.None);
 67
 68			foreach (var attribute in declaration.SecurityAttributes) {
 69				var permission = CreatePermission (declaration, attribute);
 70				set.AddPermission (permission);
 71			}
 72
 73			return set;
 74		}
 75
 76		static IPermission CreatePermission (SecurityDeclaration declaration, SecurityAttribute attribute)
 77		{
 78			var attribute_type = Type.GetType (attribute.AttributeType.FullName);
 79			if (attribute_type == null)
 80				throw new ArgumentException ();
 81
 82			var security_attribute = CreateSecurityAttribute (attribute_type, declaration);
 83			if (security_attribute == null)
 84				throw new InvalidOperationException ();
 85
 86			CompleteSecurityAttribute (security_attribute, attribute);
 87
 88			return security_attribute.CreatePermission ();
 89		}
 90
 91		static void CompleteSecurityAttribute (SSP.SecurityAttribute security_attribute, SecurityAttribute attribute)
 92		{
 93			if (attribute.HasFields)
 94				CompleteSecurityAttributeFields (security_attribute, attribute);
 95
 96			if (attribute.HasProperties)
 97				CompleteSecurityAttributeProperties (security_attribute, attribute);
 98		}
 99
100		static void CompleteSecurityAttributeFields (SSP.SecurityAttribute security_attribute, SecurityAttribute attribute)
101		{
102			var type = security_attribute.GetType ();
103
104			foreach (var named_argument in attribute.Fields)
105				type.GetField (named_argument.Name).SetValue (security_attribute, named_argument.Argument.Value);
106		}
107
108		static void CompleteSecurityAttributeProperties (SSP.SecurityAttribute security_attribute, SecurityAttribute attribute)
109		{
110			var type = security_attribute.GetType ();
111
112			foreach (var named_argument in attribute.Properties)
113				type.GetProperty (named_argument.Name).SetValue (security_attribute, named_argument.Argument.Value, null);
114		}
115
116		static SSP.SecurityAttribute CreateSecurityAttribute (Type attribute_type, SecurityDeclaration declaration)
117		{
118			SSP.SecurityAttribute security_attribute;
119			try {
120				security_attribute = (SSP.SecurityAttribute) Activator.CreateInstance (
121					attribute_type, new object [] { (SSP.SecurityAction) declaration.Action });
122			} catch (MissingMethodException) {
123				security_attribute = (SSP.SecurityAttribute) Activator.CreateInstance (attribute_type, new object [0]);
124			}
125
126			return security_attribute;
127		}
128	}
129
130	class SecurityElementComparer : IComparer {
131
132		public int Compare (object x, object y)
133		{
134			SecurityElement sx = (x as SecurityElement);
135			SecurityElement sy = (y as SecurityElement);
136			if (sx == null)
137				return (sy == null) ? 0 : -1;
138			else if (sy == null)
139				return 1;
140
141			// compare by name (type name, method name, action name)
142			return String.Compare (sx.Attribute ("Name"), sy.Attribute ("Name"));
143		}
144	}
145
146	class PermView {
147
148		private const string NotSpecified = "\tNot specified.";
149
150		static private void Help () 
151		{
152			Console.WriteLine ("Usage: permview [options] assembly{0}", Environment.NewLine);
153			Console.WriteLine ("where options are:");
154			Console.WriteLine (" -output filename  Output information into specified file.");
155			Console.WriteLine (" -decl             Show declarative security attributes on classes and methods.");
156			Console.WriteLine (" -xml              Output in XML format");
157			Console.WriteLine (" -help             Show help informations (this text)");
158			Console.WriteLine ();
159		}
160
161		static bool declarative = false;
162		static bool xmloutput = false;
163
164		static TextWriter ProcessOptions (string[] args)
165		{
166			TextWriter tw = Console.Out;
167			for (int i=0; i < args.Length - 1; i++) {
168				switch (args [i].ToUpper ()) {
169				case "/DECL":
170				case "-DECL":
171				case "--DECL":
172					declarative = true;
173					break;
174				case "/OUTPUT":
175				case "-OUTPUT":
176				case "--OUTPUT":
177					tw = (TextWriter) new StreamWriter (args [++i]);
178					break;
179				case "/XML":
180				case "-XML":
181				case "--XML":
182					xmloutput = true;
183					break;
184				case "/HELP":
185				case "/H":
186				case "-HELP":
187				case "-H":
188				case "--HELP":
189				case "--H":
190				case "-?":
191				case "--?":
192					Help ();
193					return null;
194				}
195			}
196			return tw;
197		}
198
199		static bool ProcessAssemblyOnly (TextWriter tw, AssemblyDefinition ad) 
200		{
201			bool result = true;
202			string minimal = NotSpecified + Environment.NewLine;
203			string optional = NotSpecified + Environment.NewLine;
204			string refused = NotSpecified + Environment.NewLine;
205
206			foreach (SecurityDeclaration decl in ad.SecurityDeclarations) {
207				switch (decl.Action) {
208				case Mono.Cecil.SecurityAction.RequestMinimum:
209					minimal = decl.ToPermissionSet ().ToString ();
210					break;
211				case Mono.Cecil.SecurityAction.RequestOptional:
212					optional = decl.ToPermissionSet ().ToString ();
213					break;
214				case Mono.Cecil.SecurityAction.RequestRefuse:
215					refused = decl.ToPermissionSet ().ToString ();
216					break;
217				default:
218					tw.WriteLine ("Invalid assembly level declaration {0}{1}{2}",
219						decl.Action, Environment.NewLine, decl.ToPermissionSet ());
220					result = false;
221					break;
222				}
223			}
224
225			tw.WriteLine ("Minimal Permission Set:");
226			tw.WriteLine (minimal);
227			tw.WriteLine ("Optional Permission Set:");
228			tw.WriteLine (optional);
229			tw.WriteLine ("Refused Permission Set:");
230			tw.WriteLine (refused);
231			return result;
232		}
233
234		static void ShowSecurity (TextWriter tw, string header, IEnumerable<SecurityDeclaration> declarations)
235		{
236			foreach (SecurityDeclaration declsec in declarations) {
237				tw.WriteLine ("{0} {1} Permission Set:{2}{3}", header,
238					declsec.Action, Environment.NewLine, declsec.ToPermissionSet ());
239			}
240		}
241
242		static bool ProcessAssemblyComplete (TextWriter tw, AssemblyDefinition ad)
243		{
244			if (ad.SecurityDeclarations.Count > 0) {
245				ShowSecurity (tw, "Assembly", ad.SecurityDeclarations);
246			}
247
248			foreach (ModuleDefinition module in ad.Modules) {
249
250				foreach (TypeDefinition type in module.Types) {
251
252					if (type.SecurityDeclarations.Count > 0) {
253						ShowSecurity (tw, "Class " + type.ToString (), ad.SecurityDeclarations);
254					}
255
256					foreach (MethodDefinition method in type.Methods) {
257						if (method.SecurityDeclarations.Count > 0) {
258							ShowSecurity (tw, "Method " + method.ToString (), method.SecurityDeclarations);
259						}
260					}
261				}
262			}
263			return true;
264		}
265
266		static void AddAttribute (SecurityElement se, string attr, string value)
267		{
268			value = value.Replace ("&", "&amp;");
269			se.AddAttribute (attr, value);
270		}
271
272		static SecurityElement AddSecurityXml (IEnumerable<SecurityDeclaration> declarations)
273		{
274			ArrayList list = new ArrayList ();
275			foreach (SecurityDeclaration declsec in declarations) {
276				SecurityElement child = new SecurityElement ("Action");
277				AddAttribute (child, "Name", declsec.Action.ToString ());
278				child.AddChild (declsec.ToPermissionSet ().ToXml ());
279				list.Add (child);
280			}
281			// sort actions
282			list.Sort (Comparer);
283
284			SecurityElement se = new SecurityElement ("Actions");
285			foreach (SecurityElement child in list) {
286				se.AddChild (child);
287			}
288			return se;
289		}
290
291		static SecurityElementComparer comparer;
292		static IComparer Comparer {
293			get {
294				if (comparer == null)
295					comparer = new SecurityElementComparer ();
296				return comparer;
297			}
298		}
299
300		static bool ProcessAssemblyXml (TextWriter tw, AssemblyDefinition ad)
301		{
302			SecurityElement se = new SecurityElement ("Assembly");
303			se.AddAttribute ("Name", ad.Name.FullName);
304
305			if (ad.SecurityDeclarations.Count > 0) {
306				se.AddChild (AddSecurityXml (ad.SecurityDeclarations));
307			}
308
309			ArrayList tlist = new ArrayList ();
310			ArrayList mlist = new ArrayList ();
311
312			foreach (ModuleDefinition module in ad.Modules) {
313
314				foreach (TypeDefinition type in module.Types) {
315
316					SecurityElement klass = new SecurityElement ("Class");
317					SecurityElement methods = new SecurityElement ("Methods");
318
319					SecurityElement typelem = null;
320					if (type.SecurityDeclarations.Count > 0) {
321						typelem = AddSecurityXml (type.SecurityDeclarations);
322					}
323
324					if (mlist.Count > 0)
325						mlist.Clear ();
326
327					foreach (MethodDefinition method in type.Methods) {
328						if (method.SecurityDeclarations.Count > 0) {
329							SecurityElement meth = new SecurityElement ("Method");
330							AddAttribute (meth, "Name", method.ToString ());
331							meth.AddChild (AddSecurityXml (method.SecurityDeclarations));
332							mlist.Add (meth);
333						}
334					}
335
336					// sort methods
337					mlist.Sort (Comparer);
338					foreach (SecurityElement method in mlist) {
339						methods.AddChild (method);
340					}
341
342					if ((typelem != null) || ((methods.Children != null) && (methods.Children.Count > 0))) {
343						AddAttribute (klass, "Name", type.ToString ());
344						if (typelem != null)
345							klass.AddChild (typelem);
346						if ((methods.Children != null) && (methods.Children.Count > 0))
347							klass.AddChild (methods);
348						tlist.Add (klass);
349					}
350				}
351
352				// sort types
353				tlist.Sort (Comparer);
354				foreach (SecurityElement type in tlist) {
355					se.AddChild (type);
356				}
357			}
358
359			tw.WriteLine (se.ToString ());
360			return true;
361		}
362
363		[STAThread]
364		static int Main (string[] args) 
365		{
366			try {
367				Console.WriteLine (new AssemblyInfo ().ToString ());
368				if (args.Length == 0) {
369					Help ();
370					return 0;
371				}
372
373				TextWriter tw = ProcessOptions (args);
374				if (tw == null)
375					return 0;
376
377				string assemblyName = args [args.Length - 1];
378				AssemblyDefinition ad = AssemblyDefinition.ReadAssembly (assemblyName);
379				if (ad != null) {
380					bool complete = false;
381					
382					if (declarative) {
383						// full output (assembly+classes+methods)
384						complete = ProcessAssemblyComplete (tw, ad);
385					} else if (xmloutput) {
386						// full output in XML (for easier diffs after c14n)
387						complete = ProcessAssemblyXml (tw, ad);
388					} else {
389						// default (assembly only)
390						complete = ProcessAssemblyOnly (tw, ad);
391					}
392
393					if (!complete) {
394						Console.Error.WriteLine ("Couldn't reflect informations.");
395						return 1;
396					}
397				} else {
398					Console.Error.WriteLine ("Couldn't load assembly '{0}'.", assemblyName);
399					return 2;
400				}
401				tw.Close ();
402			}
403			catch (Exception e) {
404				Console.Error.WriteLine ("Error: " + e.ToString ());
405				Help ();
406				return 3;
407			}
408			return 0;
409		}
410	}
411}